]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - gnu/lib/libodialog/checklist.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / gnu / lib / libodialog / 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     /*
203      *  XXX Black magic voodoo that allows printing to the checklist
204      *  window. For some reason, if this "refresh" code is not in
205      *  place, printing to the window from the selected callback
206      *  prints "behind" the checklist window. There is probably a
207      *  better way to do this.
208      */
209     draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr);
210
211     for (i = 0; i < max_choice; i++)
212         print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i), list_width, item_x, check_x);
213     print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
214
215     wmove(list, choice, check_x+1);
216     wnoutrefresh(dialog);
217     wrefresh(list);
218     /* XXX Black magic XXX */
219     
220     while (key != ESC) {
221         key = wgetch(dialog);
222         
223         /* Shortcut to OK? */
224         if (toupper(key) == okButton) {
225             if (ditems) {
226                 if (result && ditems[OK_BUTTON].fire) {
227                     int st;
228                     WINDOW *save;
229
230                     save = dupwin(newscr);
231                     st = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]);
232                     if (st & DITEM_RESTORE) {
233                         touchwin(save);
234                         wrefresh(save);
235                     }
236                     delwin(save);
237                 }
238             }
239             else if (result) {
240                 *result = '\0';
241                 for (i = 0; i < item_no; i++) {
242                     if (status[i]) {
243                         strcat(result, items[i*3]);
244                         strcat(result, "\n");
245                     }
246                 }
247             }
248             rval = 0;
249             key = ESC;  /* Lemme out! */
250             break;
251         }
252
253         /* Shortcut to cancel? */
254         if (toupper(key) == cancelButton) {
255             if (ditems && result && ditems[CANCEL_BUTTON].fire) {
256                 int st;
257                 WINDOW *save;
258
259                 save = dupwin(newscr);
260                 st = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]);
261                 if (st & DITEM_RESTORE) {
262                     touchwin(save);
263                     wrefresh(save);
264                     wmove(dialog, cur_y, cur_x);
265                 }
266                 delwin(save);
267             }
268             rval = 1;
269             key = ESC;  /* I gotta go! */
270             break;
271         }
272         
273         /* Check if key pressed matches first character of any item tag in list */
274         for (i = 0; i < max_choice; i++)
275             if (key != ' ' && key < 0x100 && toupper(key) == toupper(items[(scroll+i)*3][0]))
276                 break;
277
278         if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) ||
279             KEY_IS_UP(key) || KEY_IS_DOWN(key) || ((key == ' ' || key == '\n' ||
280             key == '\r') && onlist)) {
281
282             /* if moving from buttons to the list, reset and redraw buttons */
283             if (!onlist) {
284                 onlist = 1;
285                 button = 0;
286
287                 if (ditems && result) {
288                     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);
289                     print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
290                 }
291                 else {
292                     print_button(dialog, "Cancel", y, x + 14, button);
293                     print_button(dialog, "  OK  ", y, x, !button);
294                 }
295                 wmove(list, choice, check_x+1);
296                 wnoutrefresh(dialog);
297                 wrefresh(list);
298             }
299
300             if (key >= '1' && key <= MIN('9', '0'+max_choice))
301                 i = key - '1';
302             
303             else if (KEY_IS_UP(key)) {
304                 if (!choice) {
305                     if (scroll) {
306                         /* Scroll list down */
307                         getyx(dialog, cur_y, cur_x);    /* Save cursor position */
308                         if (list_height > 1) {
309                             /* De-highlight current first item before scrolling down */
310                             print_item(list, items[scroll * 3], items[scroll * 3 + 1], status[scroll], 0,
311                                        FALSE, DREF(ditems, scroll), list_width, item_x, check_x);
312                             scrollok(list, TRUE);
313                             wscrl(list, -1);
314                             scrollok(list, FALSE);
315                         }
316                         scroll--;
317                         print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
318                                    TRUE, DREF(ditems, scroll), list_width, item_x, check_x);
319                         print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
320                         wmove(list, choice, check_x+1);
321                         wnoutrefresh(dialog);
322                         wrefresh(list);
323                     }
324                     continue;    /* wait for another key press */
325                 }
326                 else
327                     i = choice - 1;
328             }
329             else if (KEY_IS_DOWN(key)) {
330                 if (choice == max_choice - 1) {
331                     if (scroll + choice < item_no - 1) {
332                         /* Scroll list up */
333                         getyx(dialog, cur_y, cur_x);    /* Save cursor position */
334                         if (list_height > 1) {
335                             /* De-highlight current last item before scrolling up */
336                             print_item(list, items[(scroll + max_choice - 1) * 3],
337                                        items[(scroll + max_choice - 1) * 3 + 1],
338                                        status[scroll + max_choice - 1], max_choice - 1,
339                                        FALSE, DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x);
340                             scrollok(list, TRUE);
341                             scroll(list);
342                             scrollok(list, FALSE);
343                         }
344                         scroll++;
345                         print_item(list, items[(scroll + max_choice - 1) * 3],
346                                    items[(scroll + max_choice - 1) * 3 + 1],
347                                    status[scroll + max_choice - 1], max_choice - 1, TRUE,
348                                    DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x);
349                         print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
350                         wmove(list, choice, check_x+1);
351                         wnoutrefresh(dialog);
352                         wrefresh(list);
353                     }
354                     continue;    /* wait for another key press */
355                 }
356                 else
357                     i = choice + 1;
358             }
359             else if ((key == ' ' || key == '\n' || key == '\r') && onlist) {    /* Toggle item status */
360                 char lbra = 0, rbra = 0, mark = 0;
361
362                 getyx(list, old_y, old_x);    /* Save cursor position */
363                 
364                 if (ditems) {
365                     if (ditems[scroll + choice].fire) {
366                         int st;
367                         WINDOW *save;
368
369                         save = dupwin(newscr);
370                         st = ditems[scroll + choice].fire(&ditems[scroll + choice]);    /* Call "fire" action */
371                         if (st & DITEM_RESTORE) {
372                             touchwin(save);
373                             wrefresh(save);
374                         }
375                         delwin(save);
376                         if (st & DITEM_REDRAW) {
377                             wclear(list);
378                             for (i = 0; i < item_no; i++)
379                                 status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
380                             for (i = 0; i < max_choice; i++) {
381                                 print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1],
382                                            status[scroll + i], i, i == choice, DREF(ditems, scroll + i), list_width, item_x, check_x);
383                             }
384                             wnoutrefresh(list);
385                             print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4,
386                                          cur_x, cur_y);
387                             wrefresh(dialog);
388                         }
389                         if (st & DITEM_LEAVE_MENU) {
390                             /* Allow a fire action to take us out of the menu */
391                             key = ESC;
392                             rval = 0;
393                             break;
394                         }
395                         else if (st & DITEM_RECREATE) {
396                             delwin(list);
397                             delwin(dialog);
398                             dialog_clear();
399                             goto draw;
400                         }
401                     }
402                     status[scroll + choice] = ditems[scroll + choice].checked ?
403                         ditems[scroll + choice].checked(&ditems[scroll + choice]) : FALSE;
404                     lbra = ditems[scroll + choice].lbra;
405                     rbra = ditems[scroll + choice].rbra;
406                     mark = ditems[scroll + choice].mark;
407                 }
408                 else
409                     status[scroll + choice] = !status[scroll + choice];
410                 wmove(list, choice, check_x);
411                 wattrset(list, check_selected_attr);
412                 if (!lbra)
413                     lbra = '[';
414                 if (!rbra)
415                     rbra = ']';
416                 if (!mark)
417                     mark = 'X';
418                 wprintw(list, "%c%c%c", lbra, status[scroll + choice] ? mark : ' ', rbra);
419                 wmove(list, old_y, old_x);  /* Restore cursor to previous position */
420                 wrefresh(list);
421                 continue;    /* wait for another key press */
422             }
423             
424             if (i != choice) {
425                 /* De-highlight current item */
426                 getyx(dialog, cur_y, cur_x);    /* Save cursor position */
427                 print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1],
428                            status[scroll + choice], choice, FALSE, DREF(ditems, scroll + choice), list_width, item_x, check_x);
429                 
430                 /* Highlight new item */
431                 choice = i;
432                 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);
433                 wmove(list, choice, check_x+1);   /* Restore cursor to previous position */
434                 wrefresh(list);
435             }
436             continue;    /* wait for another key press */
437         }
438         
439         switch (key) {
440         case KEY_PPAGE: /* can we go up? */
441             if (scroll > height - 4)
442                 scroll -= (height-4);
443             else
444                 scroll = 0;
445             redraw_menu = TRUE;
446             if (!onlist) {
447                 onlist = 1;
448                 button = 0;
449             }
450             break;
451             
452         case KEY_NPAGE:      /* can we go down a full page? */
453             if (scroll + list_height >= item_no-1 - list_height) {
454                 scroll = item_no - list_height;
455                 if (scroll < 0)
456                     scroll = 0;
457             }
458             else
459                 scroll += list_height;
460             redraw_menu = TRUE;
461             if (!onlist) {
462                 onlist = 1;
463                 button = 0;
464             }
465             break;
466             
467         case KEY_HOME:      /* go to the top */
468             scroll = 0;
469             choice = 0;
470             redraw_menu = TRUE;
471             cursor_reset = TRUE;
472             onlist = 1;
473             break;
474             
475         case KEY_END:      /* Go to the bottom */
476             scroll = item_no - list_height;
477             if (scroll < 0)
478                 scroll = 0;
479             choice = max_choice - 1;
480             redraw_menu = TRUE;
481             cursor_reset = TRUE;
482             onlist = 1;
483             break;
484             
485         case TAB:
486         case KEY_BTAB:
487             /* move to next component */
488             if (onlist) {       /* on list, next is ok button */
489                 onlist = 0;
490                 if (ditems && result) {
491                     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);
492                     print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
493                     ok_space = 1;
494                     cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
495                 }
496                 else {
497                     print_button(dialog, "Cancel", y, x + 14, button);
498                     print_button(dialog, "  OK  ", y, x, !button);
499                     ok_space = 3;
500                     cancel_space = 15;
501                 }
502                 if (button)
503                     wmove(dialog, y, x + cancel_space);
504                 else
505                     wmove(dialog, y, x + ok_space);
506                 wrefresh(dialog);
507                 break;
508             }
509             else if (button) {     /* on cancel button, next is list */
510                 button = 0;
511                 onlist = 1;
512                 redraw_menu = TRUE;
513                 break; 
514             }
515             /* on ok button, next is cancel button, same as left/right case */
516
517         case KEY_LEFT:
518         case KEY_RIGHT:
519             onlist = 0;
520             button = !button;
521             if (ditems && result) {
522                 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);
523                 print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ?  ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
524                 ok_space = 1;
525                 cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
526             }
527             else {
528                 print_button(dialog, "Cancel", y, x + 14, button);
529                 print_button(dialog, "  OK  ", y, x, !button);
530                 ok_space = 3;
531                 cancel_space = 15;
532             }
533             if (button)
534                 wmove(dialog, y, x + cancel_space);
535             else
536                 wmove(dialog, y, x + ok_space);
537             wrefresh(dialog);
538             break;
539
540         case ' ':
541         case '\n':
542         case '\r':
543             if (!onlist) {
544                 if (ditems) {
545                     if (result && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) {
546                         int st;
547                         WINDOW *save = dupwin(newscr);
548
549                         st = ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]);
550                         if (st & DITEM_RESTORE) {
551                             touchwin(save);
552                             wrefresh(save);
553                         }
554                         delwin(save);
555                         if (st == DITEM_FAILURE)
556                         continue;
557                     }
558                 }
559                 else if (result) {
560                     *result = '\0';
561                     for (i = 0; i < item_no; i++) {
562                         if (status[i]) {
563                             strcat(result, items[i*3]);
564                             strcat(result, "\n");
565                         }
566                     }
567                 }
568                 rval = button;
569                 key = ESC;      /* Bail out! */
570                 break;
571             }
572             
573             /* Let me outta here! */
574         case ESC:
575             rval = -1;
576             break;
577             
578             /* Help! */
579         case KEY_F(1):
580         case '?':
581             display_helpfile();
582             break;
583         }
584         
585         if (redraw_menu) {
586             getyx(list, old_y, old_x);
587             wclear(list);
588
589             /*
590              * Re-draw a box around the list items.  It is required
591              * if amount of list items is smaller than height of listbox.
592              * Otherwise un-redrawn field will be filled with default
593              * screen attributes instead of dialog attributes.
594              */
595             draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr);
596
597             for (i = 0; i < max_choice; i++)
598                 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);
599             print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
600
601             /* redraw buttons to fix highlighting */
602             if (ditems && result) {
603                 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);
604                 print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
605             }
606             else {
607                 print_button(dialog, "Cancel", y, x + 14, button);
608                 print_button(dialog, "  OK  ", y, x, !button);
609             }
610             wnoutrefresh(dialog);
611             if (cursor_reset) {
612                 wmove(list, choice, check_x+1);
613                 cursor_reset = FALSE;
614             }
615             else {
616                 wmove(list, old_y, old_x);
617             }
618             wrefresh(list);
619             redraw_menu = FALSE;
620         }
621     }
622     delwin(list);
623     delwin(dialog);
624     return rval;
625 }
626
627
628 /*
629  * Print list item
630  */
631 static void
632 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)
633 {
634     int i;
635     
636     /* Clear 'residue' of last item */
637     wattrset(win, menubox_attr);
638     wmove(win, choice, 0);
639     for (i = 0; i < list_width; i++)
640         waddch(win, ' ');
641     wmove(win, choice, check_x);
642     wattrset(win, selected ? check_selected_attr : check_attr);
643     wprintw(win, "%c%c%c",  me && me->lbra ? me->lbra : '[',
644             status ? me && me->mark ? me->mark : 'X' : ' ',
645             me && me->rbra ? me->rbra : ']');
646     wattrset(win, menubox_attr);
647     waddch(win, ' ');
648     wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
649     waddch(win, tag[0]);
650     wattrset(win, selected ? tag_selected_attr : tag_attr);
651     waddstr(win, tag + 1);
652     wmove(win, choice, item_x);
653     wattrset(win, selected ? item_selected_attr : item_attr);
654     waddstr(win, item);
655     /* If have a selection handler for this, call it */
656     if (me && me->selected) {
657         wrefresh(win);
658         me->selected(me, selected);
659     }
660 }
661 /* End of print_item() */