1/**************************************************************************** 2 * Copyright (c) 2005-2007,2008 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28/* 29 * $Id: demo_menus.c,v 1.28 2008/08/23 20:31:54 tom Exp $ 30 * 31 * Demonstrate a variety of functions from the menu library. 32 * Thomas Dickey - 2005/4/9 33 */ 34/* 35item_description - 36item_init - 37item_opts - 38item_opts_off - 39item_opts_on - 40item_term - 41item_userptr - 42item_visible - 43menu_back - 44menu_fore - 45menu_format - 46menu_grey - 47menu_init - 48menu_opts - 49menu_pad - 50menu_request_by_name - 51menu_request_name - 52menu_sub - 53menu_term - 54menu_userptr - 55set_current_item - 56set_item_init - 57set_item_opts - 58set_item_term - 59set_item_userptr - 60set_menu_grey - 61set_menu_init - 62set_menu_items - 63set_menu_opts - 64set_menu_pad - 65set_menu_pattern - 66set_menu_spacing - 67set_menu_term - 68set_menu_userptr - 69set_top_row - 70top_row - 71*/ 72 73#include <test.priv.h> 74 75#if USE_LIBMENU 76 77#include <menu.h> 78 79#include <sys/types.h> 80#include <sys/stat.h> 81 82#ifdef NCURSES_VERSION 83#ifdef TRACE 84static unsigned save_trace = TRACE_ORDINARY | TRACE_CALLS; 85extern unsigned _nc_tracing; 86static MENU *mpTrace; 87#endif 88#else 89#undef TRACE 90#endif 91 92typedef enum { 93 eBanner = -1 94 ,eFile 95 ,eSelect 96#ifdef TRACE 97 ,eTrace 98#endif 99 ,eMAX 100} MenuNo; 101 102#define okMenuNo(n) (((n) > eBanner) && ((n) < eMAX)) 103 104#define MENU_Y 1 105 106static MENU *mpBanner; 107static MENU *mpFile; 108static MENU *mpSelect; 109 110static bool loaded_file = FALSE; 111 112#if !HAVE_STRDUP 113#define strdup my_strdup 114static char * 115strdup(char *s) 116{ 117 char *p = typeMalloc(char, strlen(s) + 1); 118 if (p) 119 strcpy(p, s); 120 return (p); 121} 122#endif /* not HAVE_STRDUP */ 123 124/* Common function to allow ^T to toggle trace-mode in the middle of a test 125 * so that trace-files can be made smaller. 126 */ 127static int 128wGetchar(WINDOW *win) 129{ 130 int c; 131#ifdef TRACE 132 while ((c = wgetch(win)) == CTRL('T')) { 133 if (_nc_tracing) { 134 save_trace = _nc_tracing; 135 Trace(("TOGGLE-TRACING OFF")); 136 _nc_tracing = 0; 137 } else { 138 _nc_tracing = save_trace; 139 } 140 trace(_nc_tracing); 141 if (_nc_tracing) 142 Trace(("TOGGLE-TRACING ON")); 143 } 144#else 145 c = wgetch(win); 146#endif 147 return c; 148} 149#define Getchar() wGetchar(stdscr) 150 151static int 152menu_virtualize(int c) 153{ 154 int result; 155 156 if (c == '\n' || c == KEY_EXIT) 157 result = (MAX_COMMAND + 1); 158 else if (c == 'u') 159 result = (REQ_SCR_ULINE); 160 else if (c == 'd') 161 result = (REQ_SCR_DLINE); 162 else if (c == 'b' || c == KEY_NPAGE) 163 result = (REQ_SCR_UPAGE); 164 else if (c == 'f' || c == KEY_PPAGE) 165 result = (REQ_SCR_DPAGE); 166 else if (c == 'l' || c == KEY_LEFT || c == KEY_BTAB) 167 result = (REQ_LEFT_ITEM); 168 else if (c == 'n' || c == KEY_DOWN) 169 result = (REQ_NEXT_ITEM); 170 else if (c == 'p' || c == KEY_UP) 171 result = (REQ_PREV_ITEM); 172 else if (c == 'r' || c == KEY_RIGHT || c == '\t') 173 result = (REQ_RIGHT_ITEM); 174 else if (c == ' ') 175 result = (REQ_TOGGLE_ITEM); 176 else { 177 if (c != KEY_MOUSE) 178 beep(); 179 result = (c); 180 } 181 return result; 182} 183 184static int 185menu_getc(MENU * m) 186{ 187 return wGetchar(menu_win(m)); 188} 189 190static int 191menu_offset(MenuNo number) 192{ 193 int result = 0; 194 195 if (okMenuNo(number)) { 196 int spc_desc, spc_rows, spc_cols; 197 198#ifdef NCURSES_VERSION 199 menu_spacing(mpBanner, &spc_desc, &spc_rows, &spc_cols); 200#else 201 spc_rows = 0; 202#endif 203 204 /* FIXME: MENU.itemlen seems the only way to get actual width of items */ 205 result = (number - (eBanner + 1)) * (mpBanner->itemlen + spc_rows); 206 } 207 return result; 208} 209 210static MENU * 211menu_create(ITEM ** items, int count, int ncols, MenuNo number) 212{ 213 MENU *result; 214 WINDOW *menuwin; 215 int mrows, mcols; 216 int y = okMenuNo(number) ? MENU_Y : 0; 217 int x = menu_offset(number); 218 int margin = (y == MENU_Y) ? 1 : 0; 219 int maxcol = (ncols + x) < COLS ? ncols : (COLS - x - 1); 220 int maxrow = (count + 1) / ncols; 221 222 if ((maxrow + y) >= (LINES - 4)) 223 maxrow = LINES - 4 - y; 224 225 result = new_menu(items); 226 227 if (has_colors()) { 228 set_menu_fore(result, COLOR_PAIR(1)); 229 set_menu_back(result, COLOR_PAIR(2)); 230 } 231 232 set_menu_format(result, maxrow, maxcol); 233 scale_menu(result, &mrows, &mcols); 234 235 if (mcols + (2 * margin + x) >= COLS) 236 mcols = COLS - (2 * margin + x); 237 238#ifdef TRACE 239 if (number == eTrace) 240 menu_opts_off(result, O_ONEVALUE); 241 else 242 menu_opts_on(result, O_ONEVALUE); 243#endif 244 245 menuwin = newwin(mrows + (2 * margin), mcols + (2 * margin), y, x); 246 set_menu_win(result, menuwin); 247 keypad(menuwin, TRUE); 248 if (margin) 249 box(menuwin, 0, 0); 250 251 set_menu_sub(result, derwin(menuwin, mrows, mcols, margin, margin)); 252 253 post_menu(result); 254 255 return result; 256} 257 258static void 259menu_destroy(MENU * m) 260{ 261 int count; 262 263 Trace(("menu_destroy %p", m)); 264 if (m != 0) { 265 ITEM **items = menu_items(m); 266 const char *blob = 0; 267 268 count = item_count(m); 269 Trace(("menu_destroy %p count %d", m, count)); 270 if ((count > 0) && (m == mpSelect)) { 271 blob = item_name(*items); 272 } 273 274 unpost_menu(m); 275 free_menu(m); 276 277 /* free the extra data allocated in build_select_menu() */ 278 if ((count > 0) && (m == mpSelect)) { 279 if (blob && loaded_file) { 280 Trace(("freeing blob %p", blob)); 281 free((char *) blob); 282 } 283 free(items); 284 } 285#ifdef TRACE 286 if ((count > 0) && (m == mpTrace)) { 287 ITEM **ip = items; 288 while (*ip) 289 free(*ip++); 290 } 291#endif 292 } 293} 294 295/* force the given menu to appear */ 296static void 297menu_display(MENU * m) 298{ 299 touchwin(menu_win(m)); 300 wrefresh(menu_win(m)); 301} 302 303/*****************************************************************************/ 304 305static void 306build_file_menu(MenuNo number) 307{ 308 static CONST_MENUS char *labels[] = 309 { 310 "Exit", 311 (char *) 0 312 }; 313 static ITEM *items[SIZEOF(labels)]; 314 315 ITEM **ip = items; 316 CONST_MENUS char **ap; 317 318 for (ap = labels; *ap; ap++) 319 *ip++ = new_item(*ap, ""); 320 *ip = (ITEM *) 0; 321 322 mpFile = menu_create(items, SIZEOF(labels) - 1, 1, number); 323} 324 325static int 326perform_file_menu(int cmd) 327{ 328 return menu_driver(mpFile, cmd); 329} 330 331/*****************************************************************************/ 332 333static void 334build_select_menu(MenuNo number, char *filename) 335{ 336 static CONST_MENUS char *labels[] = 337 { 338 "Lions", 339 "Tigers", 340 "Bears", 341 "(Oh my!)", 342 "Newts", 343 "Platypi", 344 "Lemurs", 345 "(Oh really?!)", 346 "Leopards", 347 "Panthers", 348 "Pumas", 349 "Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs", 350 "Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs, Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs", 351 (char *) 0 352 }; 353 static ITEM **items; 354 355 ITEM **ip; 356 CONST_MENUS char **ap = 0; 357 CONST_MENUS char **myList = 0; 358 unsigned count = 0; 359 360 if (filename != 0) { 361 struct stat sb; 362 if (stat(filename, &sb) == 0 363 && (sb.st_mode & S_IFMT) == S_IFREG 364 && sb.st_size != 0) { 365 size_t size = (size_t) sb.st_size; 366 unsigned j, k; 367 char *blob = typeMalloc(char, size + 1); 368 CONST_MENUS char **list = typeCalloc(CONST_MENUS char *, size + 1); 369 370 items = typeCalloc(ITEM *, size + 1); 371 Trace(("build_select_menu blob=%p, items=%p", blob, items)); 372 if (blob != 0 && list != 0) { 373 FILE *fp = fopen(filename, "r"); 374 if (fp != 0) { 375 if (fread(blob, sizeof(char), size, fp) == size) { 376 bool mark = TRUE; 377 for (j = k = 0; j < size; ++j) { 378 if (mark) { 379 list[k++] = blob + j; 380 mark = FALSE; 381 } 382 if (blob[j] == '\n') { 383 blob[j] = '\0'; 384 if (k > 0 && *list[k - 1] == '\0') 385 --k; 386 mark = TRUE; 387 } else if (blob[j] == '\t') { 388 blob[j] = ' '; /* menu items are printable */ 389 } 390 } 391 list[k] = 0; 392 count = k; 393 ap = myList = list; 394 } 395 fclose(fp); 396 } 397 loaded_file = TRUE; 398 } 399 } 400 } 401 if (ap == 0) { 402 count = SIZEOF(labels) - 1; 403 items = typeCalloc(ITEM *, count + 1); 404 ap = labels; 405 } 406 407 ip = items; 408 while (*ap != 0) 409 *ip++ = new_item(*ap++, ""); 410 *ip = 0; 411 412 mpSelect = menu_create(items, (int) count, 1, number); 413 if (myList != 0) 414 free(myList); 415} 416 417static int 418perform_select_menu(int cmd) 419{ 420 return menu_driver(mpSelect, cmd); 421} 422 423/*****************************************************************************/ 424 425#ifdef TRACE 426#define T_TBL(name) { #name, name } 427static struct { 428 const char *name; 429 unsigned mask; 430} t_tbl[] = { 431 432 T_TBL(TRACE_DISABLE), 433 T_TBL(TRACE_TIMES), 434 T_TBL(TRACE_TPUTS), 435 T_TBL(TRACE_UPDATE), 436 T_TBL(TRACE_MOVE), 437 T_TBL(TRACE_CHARPUT), 438 T_TBL(TRACE_ORDINARY), 439 T_TBL(TRACE_CALLS), 440 T_TBL(TRACE_VIRTPUT), 441 T_TBL(TRACE_IEVENT), 442 T_TBL(TRACE_BITS), 443 T_TBL(TRACE_ICALLS), 444 T_TBL(TRACE_CCALLS), 445 T_TBL(TRACE_DATABASE), 446 T_TBL(TRACE_ATTRS), 447 T_TBL(TRACE_MAXIMUM), 448 { 449 (char *) 0, 0 450 } 451}; 452 453static void 454build_trace_menu(MenuNo number) 455{ 456 static ITEM *items[SIZEOF(t_tbl)]; 457 458 ITEM **ip = items; 459 int n; 460 461 for (n = 0; t_tbl[n].name != 0; n++) 462 *ip++ = new_item(t_tbl[n].name, ""); 463 *ip = (ITEM *) 0; 464 465 mpTrace = menu_create(items, SIZEOF(t_tbl) - 1, 2, number); 466} 467 468static char * 469tracetrace(unsigned tlevel) 470{ 471 static char *buf; 472 int n; 473 474 if (buf == 0) { 475 size_t need = 12; 476 for (n = 0; t_tbl[n].name != 0; n++) 477 need += strlen(t_tbl[n].name) + 2; 478 buf = typeMalloc(char, need); 479 } 480 sprintf(buf, "0x%02x = {", tlevel); 481 if (tlevel == 0) { 482 sprintf(buf + strlen(buf), "%s, ", t_tbl[0].name); 483 } else { 484 for (n = 1; t_tbl[n].name != 0; n++) 485 if ((tlevel & t_tbl[n].mask) == t_tbl[n].mask) { 486 strcat(buf, t_tbl[n].name); 487 strcat(buf, ", "); 488 } 489 } 490 if (buf[strlen(buf) - 2] == ',') 491 buf[strlen(buf) - 2] = '\0'; 492 return (strcat(buf, "}")); 493} 494 495/* fake a dynamically reconfigurable menu using the 0th entry to deselect 496 * the others 497 */ 498static bool 499update_trace_menu(MENU * m) 500{ 501 ITEM **items; 502 ITEM *i, **p; 503 bool changed = FALSE; 504 505 items = menu_items(m); 506 i = current_item(m); 507 if (i == items[0]) { 508 if (item_value(i)) { 509 for (p = items + 1; *p != 0; p++) 510 if (item_value(*p)) { 511 set_item_value(*p, FALSE); 512 changed = TRUE; 513 } 514 } 515 } 516 return changed; 517} 518 519static int 520perform_trace_menu(int cmd) 521/* interactively set the trace level */ 522{ 523 ITEM **ip; 524 unsigned newtrace; 525 int result; 526 527 for (ip = menu_items(mpTrace); *ip; ip++) { 528 unsigned mask = t_tbl[item_index(*ip)].mask; 529 if (mask == 0) 530 set_item_value(*ip, _nc_tracing == 0); 531 else if ((mask & _nc_tracing) == mask) 532 set_item_value(*ip, TRUE); 533 } 534 535 result = menu_driver(mpTrace, cmd); 536 537 if (result == E_OK) { 538 if (update_trace_menu(mpTrace) || cmd == REQ_TOGGLE_ITEM) { 539 newtrace = 0; 540 for (ip = menu_items(mpTrace); *ip; ip++) { 541 if (item_value(*ip)) 542 newtrace |= t_tbl[item_index(*ip)].mask; 543 } 544 trace(newtrace); 545 Trace(("trace level interactively set to %s", tracetrace(_nc_tracing))); 546 547 (void) mvprintw(LINES - 2, 0, 548 "Trace level is %s\n", tracetrace(_nc_tracing)); 549 refresh(); 550 } 551 } 552 return result; 553} 554#endif /* TRACE */ 555 556/*****************************************************************************/ 557 558static int 559menu_number(void) 560{ 561 return item_index(current_item(mpBanner)) - (eBanner + 1); 562} 563 564static MENU * 565current_menu(void) 566{ 567 MENU *result; 568 569 switch (menu_number()) { 570 case eFile: 571 result = mpFile; 572 break; 573 case eSelect: 574 result = mpSelect; 575 break; 576#ifdef TRACE 577 case eTrace: 578 result = mpTrace; 579 break; 580#endif 581 default: 582 result = 0; 583 break; 584 } 585 return result; 586} 587 588static void 589build_menus(char *filename) 590{ 591 static CONST_MENUS char *labels[] = 592 { 593 "File", 594 "Select", 595#ifdef TRACE 596 "Trace", 597#endif 598 (char *) 0 599 }; 600 static ITEM *items[SIZEOF(labels)]; 601 602 ITEM **ip = items; 603 CONST_MENUS char **ap; 604 605 for (ap = labels; *ap; ap++) 606 *ip++ = new_item(*ap, ""); 607 *ip = (ITEM *) 0; 608 609 mpBanner = menu_create(items, SIZEOF(labels) - 1, SIZEOF(labels) - 1, eBanner); 610 set_menu_mark(mpBanner, ">"); 611 612 build_file_menu(eFile); 613 build_select_menu(eSelect, filename); 614#ifdef TRACE 615 build_trace_menu(eTrace); 616#endif 617} 618 619static int 620move_menu(MENU * menu, MENU * current, int by_y, int by_x) 621{ 622 WINDOW *top_win = menu_win(menu); 623 WINDOW *sub_win = menu_sub(menu); 624 int y0, x0; 625 int y1, x1; 626 int result; 627 628 getbegyx(top_win, y0, x0); 629 y0 += by_y; 630 x0 += by_x; 631 632 getbegyx(sub_win, y1, x1); 633 y1 += by_y; 634 x1 += by_x; 635 636 if ((result = mvwin(top_win, y0, x0)) != ERR) { 637#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH < 20060218) 638 sub_win->_begy = y1; 639 sub_win->_begx = x1; 640#else 641 mvwin(sub_win, y1, x1); 642#endif 643 if (menu == current) { 644 touchwin(top_win); 645 wnoutrefresh(top_win); 646 } 647 } 648 return result; 649} 650 651/* 652 * Move the menus around on the screen, to test mvwin(). 653 */ 654static void 655move_menus(MENU * current, int by_y, int by_x) 656{ 657 if (move_menu(mpBanner, current, by_y, by_x) != ERR) { 658 erase(); 659 wnoutrefresh(stdscr); 660 move_menu(mpFile, current, by_y, by_x); 661 move_menu(mpSelect, current, by_y, by_x); 662#ifdef TRACE 663 move_menu(mpTrace, current, by_y, by_x); 664#endif 665 doupdate(); 666 } 667} 668 669static void 670show_status(int ch, MENU * menu) 671{ 672 move(LINES - 1, 0); 673 printw("key %s, menu %d, mark %s, match %s", 674 keyname(ch), 675 menu_number(), 676 menu_mark(menu), 677 menu_pattern(menu)); 678 clrtoeol(); 679 refresh(); 680} 681 682static void 683perform_menus(void) 684{ 685 MENU *this_menu; 686 MENU *last_menu = mpFile; 687 int code = E_UNKNOWN_COMMAND; 688 int cmd; 689 int ch = ERR; 690 691#ifdef NCURSES_MOUSE_VERSION 692 mousemask(ALL_MOUSE_EVENTS, (mmask_t *) 0); 693#endif 694 695 menu_display(last_menu); 696 697 for (;;) { 698 699 if (ch != ERR) 700 show_status(ch, last_menu); 701 702 ch = menu_getc(mpBanner); 703 704 /* 705 * Provide for moving the menu around in the screen using shifted 706 * cursor keys. 707 */ 708 switch (ch) { 709 case KEY_SF: 710 move_menus(last_menu, 1, 0); 711 continue; 712 case KEY_SR: 713 move_menus(last_menu, -1, 0); 714 continue; 715 case KEY_SLEFT: 716 move_menus(last_menu, 0, -1); 717 continue; 718 case KEY_SRIGHT: 719 move_menus(last_menu, 0, 1); 720 continue; 721 } 722 cmd = menu_virtualize(ch); 723 724 switch (cmd) { 725 /* 726 * The banner menu acts solely to select one of the other menus. 727 * Move between its items, wrapping at the left/right limits. 728 */ 729 case REQ_LEFT_ITEM: 730 case REQ_RIGHT_ITEM: 731 code = menu_driver(mpBanner, cmd); 732 if (code == E_REQUEST_DENIED) { 733 if (menu_number() > 0) 734 code = menu_driver(mpBanner, REQ_FIRST_ITEM); 735 else 736 code = menu_driver(mpBanner, REQ_LAST_ITEM); 737 } 738 break; 739 default: 740 switch (menu_number()) { 741 case eFile: 742 code = perform_file_menu(cmd); 743 break; 744 case eSelect: 745 code = perform_select_menu(cmd); 746 break; 747#ifdef TRACE 748 case eTrace: 749 code = perform_trace_menu(cmd); 750 break; 751#endif 752 } 753 754 if ((code == E_REQUEST_DENIED) && (cmd == KEY_MOUSE)) { 755 code = menu_driver(mpBanner, cmd); 756 } 757 758 break; 759 } 760 761 if (code == E_OK) { 762 this_menu = current_menu(); 763 if (this_menu != last_menu) { 764 move(1, 0); 765 clrtobot(); 766 box(menu_win(this_menu), 0, 0); 767 refresh(); 768 769 /* force the current menu to appear */ 770 menu_display(this_menu); 771 772 last_menu = this_menu; 773 } 774 } 775 wrefresh(menu_win(last_menu)); 776 if (code == E_UNKNOWN_COMMAND 777 || code == E_NOT_POSTED) { 778 if (menu_number() == eFile) 779 break; 780 beep(); 781 } 782 if (code == E_REQUEST_DENIED) 783 beep(); 784 continue; 785 } 786 787#ifdef NCURSES_MOUSE_VERSION 788 mousemask(0, (mmask_t *) 0); 789#endif 790} 791 792static void 793destroy_menus(void) 794{ 795 menu_destroy(mpFile); 796 menu_destroy(mpSelect); 797#ifdef TRACE 798 menu_destroy(mpTrace); 799#endif 800 menu_destroy(mpBanner); 801} 802 803#if HAVE_RIPOFFLINE 804static int 805rip_footer(WINDOW *win, int cols) 806{ 807 wbkgd(win, A_REVERSE); 808 werase(win); 809 wmove(win, 0, 0); 810 wprintw(win, "footer: %d columns", cols); 811 wnoutrefresh(win); 812 return OK; 813} 814 815static int 816rip_header(WINDOW *win, int cols) 817{ 818 wbkgd(win, A_REVERSE); 819 werase(win); 820 wmove(win, 0, 0); 821 wprintw(win, "header: %d columns", cols); 822 wnoutrefresh(win); 823 return OK; 824} 825#endif /* HAVE_RIPOFFLINE */ 826 827static void 828usage(void) 829{ 830 static const char *const tbl[] = 831 { 832 "Usage: demo_menus [options]" 833 ,"" 834 ,"Options:" 835#if HAVE_RIPOFFLINE 836 ," -f rip-off footer line (can repeat)" 837 ," -h rip-off header line (can repeat)" 838#endif 839#ifdef TRACE 840 ," -t mask specify default trace-level (may toggle with ^T)" 841#endif 842 }; 843 size_t n; 844 for (n = 0; n < SIZEOF(tbl); n++) 845 fprintf(stderr, "%s\n", tbl[n]); 846 ExitProgram(EXIT_FAILURE); 847} 848 849int 850main(int argc, char *argv[]) 851{ 852 int c; 853 854 setlocale(LC_ALL, ""); 855 856 while ((c = getopt(argc, argv, "a:de:fhmp:s:t:")) != -1) { 857 switch (c) { 858#if HAVE_RIPOFFLINE 859 case 'f': 860 ripoffline(-1, rip_footer); 861 break; 862 case 'h': 863 ripoffline(1, rip_header); 864 break; 865#endif /* HAVE_RIPOFFLINE */ 866#ifdef TRACE 867 case 't': 868 trace(strtoul(optarg, 0, 0)); 869 break; 870#endif 871 default: 872 usage(); 873 } 874 } 875 876 initscr(); 877 noraw(); 878 cbreak(); 879 noecho(); 880 881 if (has_colors()) { 882 start_color(); 883 init_pair(1, COLOR_RED, COLOR_BLACK); 884 init_pair(2, COLOR_BLUE, COLOR_WHITE); 885 } 886 build_menus(argc > 1 ? argv[1] : 0); 887 perform_menus(); 888 destroy_menus(); 889 890 endwin(); 891 ExitProgram(EXIT_SUCCESS); 892} 893#else 894int 895main(void) 896{ 897 printf("This program requires the curses menu library\n"); 898 ExitProgram(EXIT_FAILURE); 899} 900#endif 901