]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - gnu/lib/libdialog/checklist.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / gnu / lib / libdialog / checklist.c
1 /*
2  *  checklist.c -- implements the checklist box
3  *
4  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5  *
6  *      Substantial rennovation:  12/18/95, Jordan K. Hubbard
7  *
8  *  This program is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU General Public License
10  *  as published by the Free Software Foundation; either version 2
11  *  of the License, or (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23
24 #include <sys/cdefs.h>
25 __FBSDID("$FreeBSD$");
26
27 #include <dialog.h>
28 #include "dialog.priv.h"
29
30
31 static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected, dialogMenuItem *me, int list_width, int item_x, int check_x);
32
33 #define DREF(di, item)          ((di) ? &((di)[(item)]) : NULL)
34
35 /*
36  * Display a dialog box with a list of options that can be turned on or off
37  */
38 int
39 dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width,
40                  int list_height, int cnt, void *it, unsigned char *result)
41 {
42     int i, j, x, y, cur_x, cur_y, old_x, old_y, box_x, box_y, key = 0, button,
43         choice, l, k, scroll, max_choice, item_no = 0, *status;
44     int redraw_menu = FALSE, cursor_reset = FALSE;
45     int rval = 0, onlist = 1, ok_space, cancel_space;
46     char okButton, cancelButton;
47     WINDOW *dialog, *list;
48     unsigned char **items = NULL;
49     dialogMenuItem *ditems;
50     int list_width, check_x, item_x;
51
52     /* Allocate space for storing item on/off status */
53     if ((status = alloca(sizeof(int) * abs(cnt))) == NULL) {
54         endwin();
55         fprintf(stderr, "\nCan't allocate memory in dialog_checklist().\n");
56         exit(-1);
57     }
58     
59 draw:
60     choice = scroll = button = 0;
61     /* Previous calling syntax, e.g. just a list of strings? */
62     if (cnt >= 0) {
63         items = it;
64         ditems = NULL;
65         item_no = cnt;
66         /* Initializes status */
67         for (i = 0; i < item_no; i++)
68             status[i] = !strcasecmp(items[i*3 + 2], "on");
69     }
70     /* It's the new specification format - fake the rest of the code out */
71     else {
72         item_no = abs(cnt);
73         ditems = it;
74         if (!items)
75             items = (unsigned char **)alloca((item_no * 3) * sizeof(unsigned char *));
76         
77         /* Initializes status */
78         for (i = 0; i < item_no; i++) {
79             status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
80             items[i*3] = ditems[i].prompt;
81             items[i*3 + 1] = ditems[i].title;
82             items[i*3 + 2] = status[i] ? "on" : "off";
83         }
84     }
85     max_choice = MIN(list_height, item_no);
86     
87     check_x = 0;
88     item_x = 0;
89     /* Find length of longest item in order to center checklist */
90     for (i = 0; i < item_no; i++) {
91         l = strlen(items[i*3]);
92         for (j = 0; j < item_no; j++) {
93             k = strlen(items[j*3 + 1]);
94             check_x = MAX(check_x, l + k + 6);
95         }
96         item_x = MAX(item_x, l);
97     }
98     if (height < 0)
99         height = strheight(prompt)+list_height+4+2;
100     if (width < 0) {
101         i = strwidth(prompt);
102         j = ((title != NULL) ? strwidth(title) : 0);
103         width = MAX(i,j);
104         width = MAX(width,check_x+4)+4;
105     }
106     width = MAX(width,24);
107     
108     if (width > COLS)
109         width = COLS;
110     if (height > LINES)
111         height = LINES;
112     /* center dialog box on screen */
113     x = (COLS - width)/2;
114     y = (LINES - height)/2;
115
116 #ifdef HAVE_NCURSES
117     if (use_shadow)
118         draw_shadow(stdscr, y, x, height, width);
119 #endif
120     dialog = newwin(height, width, y, x);
121     if (dialog == NULL) {
122         endwin();
123         fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width, y, x);
124         return -1;
125     }
126     keypad(dialog, TRUE);
127     
128     draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
129     wattrset(dialog, border_attr);
130     wmove(dialog, height-3, 0);
131     waddch(dialog, ACS_LTEE);
132     for (i = 0; i < width-2; i++)
133         waddch(dialog, ACS_HLINE);
134     wattrset(dialog, dialog_attr);
135     waddch(dialog, ACS_RTEE);
136     wmove(dialog, height-2, 1);
137     for (i = 0; i < width-2; i++)
138         waddch(dialog, ' ');
139     
140     if (title != NULL) {
141         wattrset(dialog, title_attr);
142         wmove(dialog, 0, (width - strlen(title))/2 - 1);
143         waddch(dialog, ' ');
144         waddstr(dialog, title);
145         waddch(dialog, ' ');
146     }
147     wattrset(dialog, dialog_attr);
148     wmove(dialog, 1, 2);
149     print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE);
150     
151     list_width = width - 6;
152     getyx(dialog, cur_y, cur_x);
153     box_y = cur_y + 1;
154     box_x = (width - list_width) / 2 - 1;
155     
156     /* create new window for the list */
157     list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1);
158     if (list == NULL) {
159         delwin(dialog);
160         endwin();
161         fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height, list_width,
162                 y + box_y + 1, x + box_x + 1);
163         return -1;
164     }
165     keypad(list, TRUE);
166     
167     /* draw a box around the list items */
168     draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr);
169     
170     check_x = (list_width - check_x) / 2;
171     item_x = check_x + item_x + 6;
172     
173     /* Print the list */
174     for (i = 0; i < max_choice; i++)
175         print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i), list_width, item_x, check_x);
176     wnoutrefresh(list);
177     print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
178     
179     display_helpline(dialog, height - 1, width);
180     
181     x = width / 2 - 11;
182     y = height - 2;
183     /* Is this a fancy new style argument string where we get to override
184      * the buttons, or an old style one where they're fixed?
185      */
186     if (ditems && result) {
187         cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]);
188         print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : FALSE);
189         okButton = toupper(ditems[OK_BUTTON].prompt[0]);
190         print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : TRUE);
191     }
192     else {
193         cancelButton = 'C';
194         print_button(dialog, "Cancel", y, x + 14, FALSE);
195         okButton = 'O';
196         print_button(dialog, "  OK  ", y, x, TRUE);
197     }
198     wnoutrefresh(dialog);
199     wmove(list, choice, check_x+1);
200     wrefresh(list);
201     
202     while (key != ESC) {
203         key = wgetch(dialog);
204         
205         /* Shortcut to OK? */
206         if (toupper(key) == okButton) {
207             if (ditems) {
208                 if (result && ditems[OK_BUTTON].fire) {
209                     int st;
210                     WINDOW *save;
211
212                     save = dupwin(newscr);
213                     st = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]);
214                     if (st & DITEM_RESTORE) {
215                         touchwin(save);
216                         wrefresh(save);
217                     }
218                     delwin(save);
219                 }
220             }
221             else if (result) {
222                 *result = '\0';
223                 for (i = 0; i < item_no; i++) {
224                     if (status[i]) {
225                         strcat(result, items[i*3]);
226                         strcat(result, "\n");
227                     }
228                 }
229             }
230             rval = 0;
231             key = ESC;  /* Lemme out! */
232             break;
233         }
234
235         /* Shortcut to cancel? */
236         if (toupper(key) == cancelButton) {
237             if (ditems && result && ditems[CANCEL_BUTTON].fire) {
238                 int st;
239                 WINDOW *save;
240
241                 save = dupwin(newscr);
242                 st = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]);
243                 if (st & DITEM_RESTORE) {
244                     touchwin(save);
245                     wrefresh(save);
246                     wmove(dialog, cur_y, cur_x);
247                 }
248                 delwin(save);
249             }
250             rval = 1;
251             key = ESC;  /* I gotta go! */
252             break;
253         }
254         
255         /* Check if key pressed matches first character of any item tag in list */
256         for (i = 0; i < max_choice; i++)
257             if (key != ' ' && key < 0x100 && toupper(key) == toupper(items[(scroll+i)*3][0]))
258                 break;
259
260         if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) ||
261             KEY_IS_UP(key) || KEY_IS_DOWN(key) || ((key == ' ' || key == '\n' ||
262             key == '\r') && onlist)) {
263
264             /* if moving from buttons to the list, reset and redraw buttons */
265             if (!onlist) {
266                 onlist = 1;
267                 button = 0;
268
269                 if (ditems && result) {
270                     print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
271                     print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
272                 }
273                 else {
274                     print_button(dialog, "Cancel", y, x + 14, button);
275                     print_button(dialog, "  OK  ", y, x, !button);
276                 }
277                 wmove(list, choice, check_x+1);
278                 wnoutrefresh(dialog);
279                 wrefresh(list);
280             }
281
282             if (key >= '1' && key <= MIN('9', '0'+max_choice))
283                 i = key - '1';
284             
285             else if (KEY_IS_UP(key)) {
286                 if (!choice) {
287                     if (scroll) {
288                         /* Scroll list down */
289                         getyx(dialog, cur_y, cur_x);    /* Save cursor position */
290                         if (list_height > 1) {
291                             /* De-highlight current first item before scrolling down */
292                             print_item(list, items[scroll * 3], items[scroll * 3 + 1], status[scroll], 0,
293                                        FALSE, DREF(ditems, scroll), list_width, item_x, check_x);
294                             scrollok(list, TRUE);
295                             wscrl(list, -1);
296                             scrollok(list, FALSE);
297                         }
298                         scroll--;
299                         print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
300                                    TRUE, DREF(ditems, scroll), list_width, item_x, check_x);
301                         print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
302                         wmove(list, choice, check_x+1);
303                         wnoutrefresh(dialog);
304                         wrefresh(list);
305                     }
306                     continue;    /* wait for another key press */
307                 }
308                 else
309                     i = choice - 1;
310             }
311             else if (KEY_IS_DOWN(key)) {
312                 if (choice == max_choice - 1) {
313                     if (scroll + choice < item_no - 1) {
314                         /* Scroll list up */
315                         getyx(dialog, cur_y, cur_x);    /* Save cursor position */
316                         if (list_height > 1) {
317                             /* De-highlight current last item before scrolling up */
318                             print_item(list, items[(scroll + max_choice - 1) * 3],
319                                        items[(scroll + max_choice - 1) * 3 + 1],
320                                        status[scroll + max_choice - 1], max_choice - 1,
321                                        FALSE, DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x);
322                             scrollok(list, TRUE);
323                             scroll(list);
324                             scrollok(list, FALSE);
325                         }
326                         scroll++;
327                         print_item(list, items[(scroll + max_choice - 1) * 3],
328                                    items[(scroll + max_choice - 1) * 3 + 1],
329                                    status[scroll + max_choice - 1], max_choice - 1, TRUE,
330                                    DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x);
331                         print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
332                         wmove(list, choice, check_x+1);
333                         wnoutrefresh(dialog);
334                         wrefresh(list);
335                     }
336                     continue;    /* wait for another key press */
337                 }
338                 else
339                     i = choice + 1;
340             }
341             else if ((key == ' ' || key == '\n' || key == '\r') && onlist) {    /* Toggle item status */
342                 char lbra = 0, rbra = 0, mark = 0;
343
344                 getyx(list, old_y, old_x);    /* Save cursor position */
345                 
346                 if (ditems) {
347                     if (ditems[scroll + choice].fire) {
348                         int st;
349                         WINDOW *save;
350
351                         save = dupwin(newscr);
352                         st = ditems[scroll + choice].fire(&ditems[scroll + choice]);    /* Call "fire" action */
353                         if (st & DITEM_RESTORE) {
354                             touchwin(save);
355                             wrefresh(save);
356                         }
357                         delwin(save);
358                         if (st & DITEM_REDRAW) {
359                             wclear(list);
360                             for (i = 0; i < item_no; i++)
361                                 status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
362                             for (i = 0; i < max_choice; i++) {
363                                 print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1],
364                                            status[scroll + i], i, i == choice, DREF(ditems, scroll + i), list_width, item_x, check_x);
365                             }
366                             wnoutrefresh(list);
367                             print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4,
368                                          cur_x, cur_y);
369                             wrefresh(dialog);
370                         }
371                         if (st & DITEM_LEAVE_MENU) {
372                             /* Allow a fire action to take us out of the menu */
373                             key = ESC;
374                             rval = 0;
375                             break;
376                         }
377                         else if (st & DITEM_RECREATE) {
378                             delwin(list);
379                             delwin(dialog);
380                             dialog_clear();
381                             goto draw;
382                         }
383                     }
384                     status[scroll + choice] = ditems[scroll + choice].checked ?
385                         ditems[scroll + choice].checked(&ditems[scroll + choice]) : FALSE;
386                     lbra = ditems[scroll + choice].lbra;
387                     rbra = ditems[scroll + choice].rbra;
388                     mark = ditems[scroll + choice].mark;
389                 }
390                 else
391                     status[scroll + choice] = !status[scroll + choice];
392                 wmove(list, choice, check_x);
393                 wattrset(list, check_selected_attr);
394                 if (!lbra)
395                     lbra = '[';
396                 if (!rbra)
397                     rbra = ']';
398                 if (!mark)
399                     mark = 'X';
400                 wprintw(list, "%c%c%c", lbra, status[scroll + choice] ? mark : ' ', rbra);
401                 wmove(list, old_y, old_x);  /* Restore cursor to previous position */
402                 wrefresh(list);
403                 continue;    /* wait for another key press */
404             }
405             
406             if (i != choice) {
407                 /* De-highlight current item */
408                 getyx(dialog, cur_y, cur_x);    /* Save cursor position */
409                 print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1],
410                            status[scroll + choice], choice, FALSE, DREF(ditems, scroll + choice), list_width, item_x, check_x);
411                 
412                 /* Highlight new item */
413                 choice = i;
414                 print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1], status[scroll + choice], choice, TRUE, DREF(ditems, scroll + choice), list_width, item_x, check_x);
415                 wmove(list, choice, check_x+1);   /* Restore cursor to previous position */
416                 wrefresh(list);
417             }
418             continue;    /* wait for another key press */
419         }
420         
421         switch (key) {
422         case KEY_PPAGE: /* can we go up? */
423             if (scroll > height - 4)
424                 scroll -= (height-4);
425             else
426                 scroll = 0;
427             redraw_menu = TRUE;
428             if (!onlist) {
429                 onlist = 1;
430                 button = 0;
431             }
432             break;
433             
434         case KEY_NPAGE:      /* can we go down a full page? */
435             if (scroll + list_height >= item_no-1 - list_height) {
436                 scroll = item_no - list_height;
437                 if (scroll < 0)
438                     scroll = 0;
439             }
440             else
441                 scroll += list_height;
442             redraw_menu = TRUE;
443             if (!onlist) {
444                 onlist = 1;
445                 button = 0;
446             }
447             break;
448             
449         case KEY_HOME:      /* go to the top */
450             scroll = 0;
451             choice = 0;
452             redraw_menu = TRUE;
453             cursor_reset = TRUE;
454             onlist = 1;
455             break;
456             
457         case KEY_END:      /* Go to the bottom */
458             scroll = item_no - list_height;
459             if (scroll < 0)
460                 scroll = 0;
461             choice = max_choice - 1;
462             redraw_menu = TRUE;
463             cursor_reset = TRUE;
464             onlist = 1;
465             break;
466             
467         case TAB:
468         case KEY_BTAB:
469             /* move to next component */
470             if (onlist) {       /* on list, next is ok button */
471                 onlist = 0;
472                 if (ditems && result) {
473                     print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
474                     print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
475                     ok_space = 1;
476                     cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
477                 }
478                 else {
479                     print_button(dialog, "Cancel", y, x + 14, button);
480                     print_button(dialog, "  OK  ", y, x, !button);
481                     ok_space = 3;
482                     cancel_space = 15;
483                 }
484                 if (button)
485                     wmove(dialog, y, x + cancel_space);
486                 else
487                     wmove(dialog, y, x + ok_space);
488                 wrefresh(dialog);
489                 break;
490             }
491             else if (button) {     /* on cancel button, next is list */
492                 button = 0;
493                 onlist = 1;
494                 redraw_menu = TRUE;
495                 break; 
496             }
497             /* on ok button, next is cancel button, same as left/right case */
498
499         case KEY_LEFT:
500         case KEY_RIGHT:
501             onlist = 0;
502             button = !button;
503             if (ditems && result) {
504                 print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
505                 print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ?  ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
506                 ok_space = 1;
507                 cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
508             }
509             else {
510                 print_button(dialog, "Cancel", y, x + 14, button);
511                 print_button(dialog, "  OK  ", y, x, !button);
512                 ok_space = 3;
513                 cancel_space = 15;
514             }
515             if (button)
516                 wmove(dialog, y, x + cancel_space);
517             else
518                 wmove(dialog, y, x + ok_space);
519             wrefresh(dialog);
520             break;
521
522         case ' ':
523         case '\n':
524         case '\r':
525             if (!onlist) {
526                 if (ditems) {
527                     if (result && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) {
528                         int st;
529                         WINDOW *save = dupwin(newscr);
530
531                         st = ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]);
532                         if (st & DITEM_RESTORE) {
533                             touchwin(save);
534                             wrefresh(save);
535                         }
536                         delwin(save);
537                         if (st == DITEM_FAILURE)
538                         continue;
539                     }
540                 }
541                 else if (result) {
542                     *result = '\0';
543                     for (i = 0; i < item_no; i++) {
544                         if (status[i]) {
545                             strcat(result, items[i*3]);
546                             strcat(result, "\n");
547                         }
548                     }
549                 }
550                 rval = button;
551                 key = ESC;      /* Bail out! */
552                 break;
553             }
554             
555             /* Let me outta here! */
556         case ESC:
557             rval = -1;
558             break;
559             
560             /* Help! */
561         case KEY_F(1):
562         case '?':
563             display_helpfile();
564             break;
565         }
566         
567         if (redraw_menu) {
568             getyx(list, old_y, old_x);
569             wclear(list);
570
571             /*
572              * Re-draw a box around the list items.  It is required
573              * if amount of list items is smaller than height of listbox.
574              * Otherwise un-redrawn field will be filled with default
575              * screen attributes instead of dialog attributes.
576              */
577             draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr);
578
579             for (i = 0; i < max_choice; i++)
580                 print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i], i, i == choice, DREF(ditems, scroll + i), list_width, item_x, check_x);
581             print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
582
583             /* redraw buttons to fix highlighting */
584             if (ditems && result) {
585                 print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
586                 print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
587             }
588             else {
589                 print_button(dialog, "Cancel", y, x + 14, button);
590                 print_button(dialog, "  OK  ", y, x, !button);
591             }
592             wnoutrefresh(dialog);
593             if (cursor_reset) {
594                 wmove(list, choice, check_x+1);
595                 cursor_reset = FALSE;
596             }
597             else {
598                 wmove(list, old_y, old_x);
599             }
600             wrefresh(list);
601             redraw_menu = FALSE;
602         }
603     }
604     delwin(list);
605     delwin(dialog);
606     return rval;
607 }
608
609
610 /*
611  * Print list item
612  */
613 static void
614 print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected, dialogMenuItem *me, int list_width, int item_x, int check_x)
615 {
616     int i;
617     
618     /* Clear 'residue' of last item */
619     wattrset(win, menubox_attr);
620     wmove(win, choice, 0);
621     for (i = 0; i < list_width; i++)
622         waddch(win, ' ');
623     wmove(win, choice, check_x);
624     wattrset(win, selected ? check_selected_attr : check_attr);
625     wprintw(win, "%c%c%c",  me && me->lbra ? me->lbra : '[',
626             status ? me && me->mark ? me->mark : 'X' : ' ',
627             me && me->rbra ? me->rbra : ']');
628     wattrset(win, menubox_attr);
629     waddch(win, ' ');
630     wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
631     waddch(win, tag[0]);
632     wattrset(win, selected ? tag_selected_attr : tag_attr);
633     waddstr(win, tag + 1);
634     wmove(win, choice, item_x);
635     wattrset(win, selected ? item_selected_attr : item_attr);
636     waddstr(win, item);
637     /* If have a selection handler for this, call it */
638     if (me && me->selected) {
639         wrefresh(win);
640         me->selected(me, selected);
641     }
642 }
643 /* End of print_item() */