1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2006 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44 void set_menu_vars(int c
, int rows
, int items
, int *item
, int *top
)
51 selected
= toppos
= 0;
55 toppos
= items
- rows
+ 1;
58 if (selected
- 1 < 0) {
61 toppos
= selected
- rows
+ 1;
66 if (toppos
&& selected
<= toppos
)
71 if (selected
+ 1 > items
)
72 selected
= toppos
= 0;
76 if (selected
- toppos
>= rows
)
86 toppos
= selected
- rows
+ 1;
97 toppos
= selected
- rows
+ 1;
103 if (selected
== MAX_MENU_HEIGHT
- 4)
105 else if (selected
<= rows
)
108 toppos
= selected
- rows
+ 1;
115 if (selected
> items
) {
117 toppos
= selected
- rows
+ 1;
127 static void fix_menu_vals(WIN
*win
)
129 struct menu_input_s
*m
= win
->data
;
137 for (i
= 0; m
->items
[i
]; i
++) {
138 n
= strlen(m
->items
[i
]->name
);
143 if (m
->items
[i
]->value
)
144 n
= strlen(m
->items
[i
]->value
) + nlen
;
146 n
= (!m
->name_only
) ? strlen(UNKNOWN
) + nlen
: nlen
;
156 for (i
= 0; m
->items
[i
]; i
++);
159 if (!m
->rstatic
&& m
->title
)
163 win
->cols
+= (!m
->name_only
) ? 5 : 2; // 2 box, 3 separator
166 win
->rows
+= 3; // 2 box, 1 prompt
168 if (!m
->rstatic
&& win
->rows
> MAX_MENU_HEIGHT
)
169 win
->rows
= MAX_MENU_HEIGHT
;
171 snprintf(buf
, sizeof(buf
), "Item %i %s %i %s", m
->selected
+ 1,
172 N_OF_N_STR
, m
->total
, HELP_PROMPT
);
174 if (win
->cols
< strlen(buf
))
175 win
->cols
= strlen(buf
) + 2; // 2 box
177 if (win
->cols
> MAX_MENU_WIDTH
)
178 win
->cols
= MAX_MENU_WIDTH
;
180 wresize(win
->w
, win
->rows
, win
->cols
);
181 replace_panel(win
->p
, win
->w
);
182 move_panel(win
->p
, (m
->ystatic
== -1) ? CALCPOSY(win
->rows
) : m
->ystatic
,
183 (m
->xstatic
== -1) ? CALCPOSX(win
->cols
) : m
->xstatic
);
184 keypad(win
->w
, TRUE
);
187 window_draw_title(win
->w
, m
->title
, win
->cols
, CP_INPUT_TITLE
,
189 window_draw_prompt(win
->w
, win
->rows
- 2, win
->cols
, buf
, CP_INPUT_PROMPT
);
192 static void draw_menu(WIN
*win
)
196 struct menu_input_s
*m
= win
->data
;
204 for (i
= 0; m
->items
[i
]; i
++) {
205 y
= strlen(m
->items
[i
]->name
);
211 for (i
= m
->top
, y
= 2; i
< m
->total
&& y
< win
->rows
- 2; i
++, y
++) {
212 if (m
->items
[i
]->value
)
213 n
= strlen(m
->items
[i
]->value
) + nlen
;
218 p
= m
->items
[i
]->value
;
220 if (i
== m
->selected
)
221 wattron(win
->w
, CP_MENU_SELECTED
);
222 else if (m
->items
[i
]->selected
)
223 wattron(win
->w
, CP_MENU_HIGHLIGHT
);
226 mvwprintw(win
->w
, y
, 1, "%*s - %-*s", nlen
, m
->items
[i
]->name
,
227 win
->cols
- 5 - nlen
, (m
->items
[i
]->value
) ? p
: UNKNOWN
);
229 mvwprintw(win
->w
, y
, 1, "%-*s", nlen
, m
->items
[i
]->name
);
231 if (i
== m
->selected
)
232 wattroff(win
->w
, CP_MENU_SELECTED
);
233 else if (m
->items
[i
]->selected
)
234 wattroff(win
->w
, CP_MENU_HIGHLIGHT
);
238 int display_menu(WIN
*win
)
240 struct menu_input_s
*m
= win
->data
;
248 keypad(win
->w
, TRUE
);
252 for (i
= 0; m
->keys
[i
]; i
++) {
253 if (win
->c
== m
->keys
[i
]->c
) {
254 (*m
->keys
[i
]->func
)(m
);
255 m
->items
= (*m
->func
)(win
);
265 m
->items
= (*m
->func
)(win
);
280 if (strlen(m
->search
) + 1 > sizeof(m
->search
) - 1)
293 for (i
= 0; m
->items
[i
]; i
++) {
294 if (strncasecmp(m
->search
, m
->items
[i
]->name
,
295 strlen(m
->search
)) == 0) {
302 if (n
== m
->selected
)
307 set_menu_vars(win
->c
, win
->rows
- 4, m
->total
- 1, &m
->selected
, &m
->top
);
316 for (i
= 0; m
->items
[i
]; i
++) {
318 free(m
->items
[i
]->name
);
320 if (!m
->nofree
&& m
->items
[i
]->value
)
321 free(m
->items
[i
]->value
);
330 for (i
= 0; m
->keys
[i
]; i
++)
343 WIN
*construct_menu(int rows
, int cols
, int y
, int x
, const char *title
,
344 int name_only
, menu_items
*func
, struct menu_key_s
**keys
, void *data
,
345 window_exit_func
*efunc
)
349 struct menu_input_s
*m
;
351 m
= Calloc(1, sizeof(struct menu_input_s
));
352 win
= window_create(rows
, cols
, (y
>= 0) ? y
: CALCPOSY(h
),
353 (x
>= 0) ? x
: CALCPOSX(w
), display_menu
, m
, efunc
);
367 m
->name_only
= name_only
;
370 m
->title
= strdup(title
);
372 wbkgd(win
->w
, CP_MENU
);
375 keypad(win
->w
, TRUE
);
377 m
->items
= (*m
->func
)(win
);
383 void add_menu_key(struct menu_key_s
***dst
, int c
, menu_key func
)
386 struct menu_key_s
**keys
= *dst
;
389 for (; keys
[n
]; n
++);
391 keys
= Realloc(keys
, (n
+ 2) * sizeof(struct menu_key_s
*));
392 keys
[n
] = Malloc(sizeof(struct menu_key_s
));
394 keys
[n
++]->func
= func
;