demo_menus.c 19 KB

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