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 31static 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 */ 38int 39dialog_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 59draw: 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 */ 631static void 632print_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() */ 662