home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / a / hdsetup / dialog-0.4-1 / dialog-0 / dialog-0.4-slackware / src / menubox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-09  |  10.5 KB  |  309 lines

  1. /*
  2.  *  menubox.c -- implements the menu box
  3.  *
  4.  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
  5.  *
  6.  *  This program is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU General Public License
  8.  *  as published by the Free Software Foundation; either version 2
  9.  *  of the License, or (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21.  
  22. #include "dialog.h"
  23.  
  24.  
  25. static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int choice, int selected);
  26.  
  27.  
  28. static int menu_width, tag_x, item_x;
  29.  
  30.  
  31. /*
  32.  * Display a menu for choosing among a number of options
  33.  */
  34. int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, int item_no, unsigned char **items)
  35. {
  36.   int i, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0,
  37.       scroll = 0, max_choice;
  38.   WINDOW *dialog, *menu;
  39.  
  40.   max_choice = MIN(menu_height, item_no);
  41.  
  42.   /* center dialog box on screen */
  43.   x = (COLS - width)/2;
  44.   y = (LINES - height)/2;
  45.   
  46. #ifdef HAVE_NCURSES
  47.   if (use_shadow)
  48.     draw_shadow(stdscr, y, x, height, width);
  49. #endif
  50.   dialog = newwin(height, width, y, x);
  51.   keypad(dialog, TRUE);
  52.  
  53.   draw_box(dialog, 0, 0, height, width, border_attr, border_attr);
  54.   wattrset(dialog, border_attr);
  55.   wmove(dialog, height-3, 0);
  56.   waddch(dialog, ACS_LTEE);
  57.   for (i = 0; i < width-2; i++)
  58.     waddch(dialog, ACS_HLINE);
  59.   waddch(dialog, ACS_RTEE);
  60.   wmove(dialog, height-2, 1);
  61.   for (i = 0; i < width-2; i++)
  62.     waddch(dialog, ' ');
  63.  
  64.   if (title != NULL) {
  65.     wattrset(dialog, title_attr);
  66.     wmove(dialog, 0, (width - strlen(title))/2 - 1);
  67.     waddch(dialog, ' ');
  68.     waddstr(dialog, title);
  69.     waddch(dialog, ' ');
  70.   }
  71.   wattrset(dialog, dialog_attr);
  72.   print_autowrap(dialog, prompt, width, 1, 3);
  73.  
  74.   menu_width = width-6;
  75.   getyx(dialog, cur_y, cur_x);
  76.   box_y = cur_y + 1;
  77.   box_x = (width - menu_width)/2 - 1;
  78.  
  79.   /* create new window for the menu */
  80.   menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1);
  81.   keypad(menu, TRUE);
  82.  
  83.   /* draw a box around the menu items */
  84.   draw_box(dialog, box_y, box_x, menu_height+2, menu_width+2, menubox_border_attr, menubox_border_attr);
  85.  
  86.   tag_x = 0;
  87.   item_x = 0;
  88.   /* Find length of longest item in order to center menu */
  89.   for (i = 0; i < item_no; i++) {
  90.     tag_x = MAX(tag_x, strlen(items[i*2]) + strlen(items[i*2 + 1]) + 2);
  91.     item_x = MAX(item_x, strlen(items[i*2]));
  92.   }
  93.   tag_x = (menu_width - tag_x) / 2;
  94.   item_x = tag_x + item_x + 2;
  95.  
  96.   /* Print the menu */
  97.   for (i = 0; i < max_choice; i++)
  98.     print_item(menu, items[i*2], items[i*2 + 1], i, i == choice);
  99.   wnoutrefresh(menu);
  100.  
  101.   if (menu_height < item_no) {
  102.     wattrset(dialog, darrow_attr);
  103.     wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 1);
  104.     waddch(dialog, ACS_DARROW);
  105.     wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 2);
  106.     waddstr(dialog,"(+)");
  107.   }
  108.  
  109.   x = width/2-11;
  110.   y = height-2;
  111.   print_button(dialog, "Cancel", y, x+14, FALSE);
  112.   print_button(dialog, "  OK  ", y, x, TRUE);
  113.   wrefresh(dialog);
  114.  
  115.   while (key != ESC) {
  116.     key = wgetch(dialog);
  117.     /* Check if key pressed matches first character of any item tag in menu */
  118.     for (i = 0; i < max_choice; i++)
  119.       if (key < 0x100 && toupper(key) == toupper(items[(scroll+i)*2][0]))
  120.         break;
  121.  
  122.     if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || 
  123.         key == KEY_UP || key == KEY_DOWN || key == '-' || key == '+') {
  124.       if (key >= '1' && key <= MIN('9', '0'+max_choice))
  125.         i = key - '1';
  126.       else if (key == KEY_UP || key == '-') {
  127.         if (!choice) {
  128.           if (scroll) {
  129. #ifdef BROKEN_WSCRL
  130.     /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation
  131.        violation when scrolling windows of height = 4, so scrolling is not
  132.        used for now */
  133.             scroll--;
  134.             getyx(dialog, cur_y, cur_x);    /* Save cursor position */
  135.             /* Reprint menu to scroll down */
  136.             for (i = 0; i < max_choice; i++)
  137.               print_item(menu, items[(scroll+i)*2], items[(scroll+i)*2 + 1], i, i == choice);
  138.  
  139. #else
  140.  
  141.             /* Scroll menu down */
  142.             getyx(dialog, cur_y, cur_x);    /* Save cursor position */
  143.             if (menu_height > 1) {
  144.               /* De-highlight current first item before scrolling down */
  145.               print_item(menu, items[scroll*2], items[scroll*2 + 1], 0, FALSE);
  146.               scrollok(menu, TRUE);
  147.               wscrl(menu, -1);
  148.               scrollok(menu, FALSE);
  149.             }
  150.             scroll--;
  151.             print_item(menu, items[scroll*2], items[scroll*2 + 1], 0, TRUE);
  152. #endif
  153.             wnoutrefresh(menu);
  154.  
  155.             /* print the up/down arrows */
  156.             wmove(dialog, box_y, box_x + tag_x + 1);
  157.             wattrset(dialog, scroll ? uarrow_attr : menubox_border_attr);
  158.             waddch(dialog, scroll ? ACS_UARROW : ACS_HLINE);
  159.             wmove(dialog, box_y, box_x + tag_x + 2);
  160.             waddch(dialog, scroll ? '(' : ACS_HLINE);
  161.             wmove(dialog, box_y, box_x + tag_x + 3);
  162.             waddch(dialog, scroll ? '-' : ACS_HLINE);
  163.             wmove(dialog, box_y, box_x + tag_x + 4);
  164.             waddch(dialog, scroll ? ')' : ACS_HLINE);
  165.             wattrset(dialog, darrow_attr);
  166.             wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 1);
  167.             waddch(dialog, ACS_DARROW);
  168.             wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 2);
  169.             waddstr(dialog,"(+)");
  170.             wmove(dialog, cur_y, cur_x);  /* Restore cursor position */
  171.             wrefresh(dialog);
  172.           }
  173.           continue;    /* wait for another key press */
  174.         }
  175.         else
  176.           i = choice - 1;
  177.       }
  178.       else if (key == KEY_DOWN || key == '+')
  179.         if (choice == max_choice - 1) {
  180.           if (scroll+choice < item_no-1) {
  181. #ifdef BROKEN_WSCRL
  182.     /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation
  183.        violation when scrolling windows of height = 4, so scrolling is not
  184.        used for now */
  185.             scroll++;
  186.             getyx(dialog, cur_y, cur_x);    /* Save cursor position */
  187.             /* Reprint menu to scroll up */
  188.             for (i = 0; i < max_choice; i++)
  189.               print_item(menu, items[(scroll+i)*2], items[(scroll+i)*2 + 1], i, i == choice);
  190.  
  191. #else
  192.  
  193.             /* Scroll menu up */
  194.             getyx(dialog, cur_y, cur_x);    /* Save cursor position */
  195.             if (menu_height > 1) {
  196.               /* De-highlight current last item before scrolling up */
  197.               print_item(menu, items[(scroll+max_choice-1)*2], items[(scroll+max_choice-1)*2 + 1], max_choice-1, FALSE);
  198.               scrollok(menu, TRUE);
  199.               scroll(menu);
  200.               scrollok(menu, FALSE);
  201.             }
  202.             scroll++;
  203.               print_item(menu, items[(scroll+max_choice-1)*2], items[(scroll+max_choice-1)*2 + 1], max_choice-1, TRUE);
  204. #endif
  205.             wnoutrefresh(menu);
  206.  
  207.             /* print the up/down arrows */
  208.             wattrset(dialog, uarrow_attr);
  209.             wmove(dialog, box_y, box_x + tag_x + 1);
  210.             waddch(dialog, ACS_UARROW);
  211.             wmove(dialog, box_y, box_x + tag_x + 2);
  212.             waddstr(dialog,"(-)");
  213.             wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 1);
  214.             wattrset(dialog, scroll+choice < item_no-1 ? darrow_attr : menubox_border_attr);
  215.             waddch(dialog, scroll+choice < item_no-1 ? ACS_DARROW : ACS_HLINE);
  216.             wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 2);
  217.             waddch(dialog, scroll+choice < item_no-1 ? '(' : ACS_HLINE);
  218.             wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 3);
  219.             waddch(dialog, scroll+choice < item_no-1 ? '+' : ACS_HLINE);
  220.             wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 4);
  221.             waddch(dialog, scroll+choice < item_no-1 ? ')' : ACS_HLINE);
  222.             wmove(dialog, cur_y, cur_x);  /* Restore cursor position */
  223.             wrefresh(dialog);
  224.           }
  225.           continue;    /* wait for another key press */
  226.         }
  227.         else
  228.           i = choice + 1;
  229.  
  230.       if (i != choice) {
  231.         /* De-highlight current item */
  232.         getyx(dialog, cur_y, cur_x);    /* Save cursor position */
  233.         print_item(menu, items[(scroll+choice)*2], items[(scroll+choice)*2 + 1], choice, FALSE);
  234.  
  235.         /* Highlight new item */
  236.         choice = i;
  237.         print_item(menu, items[(scroll+choice)*2], items[(scroll+choice)*2 + 1], choice, TRUE);
  238.         wnoutrefresh(menu);
  239.         wmove(dialog, cur_y, cur_x);  /* Restore cursor to previous position */
  240.         wrefresh(dialog);
  241.       }
  242.       continue;    /* wait for another key press */
  243.     }
  244.  
  245.     switch (key) {
  246.       case 'O':
  247.       case 'o':
  248.         delwin(dialog);
  249.         fprintf(stderr, items[(scroll+choice)*2]);
  250.         return 0;
  251.       case 'C':
  252.       case 'c':
  253.         delwin(dialog);
  254.         return 1;
  255.       case TAB:
  256.       case KEY_LEFT:
  257.       case KEY_RIGHT:
  258.         if (!button) {
  259.           button = 1;    /* Indicates "Cancel" button is selected */
  260.           print_button(dialog, "  OK  ", y, x, FALSE);
  261.           print_button(dialog, "Cancel", y, x+14, TRUE);
  262.         }
  263.         else {
  264.           button = 0;    /* Indicates "OK" button is selected */
  265.           print_button(dialog, "Cancel", y, x+14, FALSE);
  266.           print_button(dialog, "  OK  ", y, x, TRUE);
  267.         }
  268.         wrefresh(dialog);
  269.         break;
  270.       case ' ':
  271.       case '\n':
  272.         delwin(dialog);
  273.         if (!button)
  274.           fprintf(stderr, items[(scroll+choice)*2]);
  275.         return button;
  276.       case ESC:
  277.         break;
  278.     }
  279.   }
  280.  
  281.   delwin(dialog);
  282.   return -1;    /* ESC pressed */
  283. }
  284. /* End of dialog_menu() */
  285.  
  286.  
  287. /*
  288.  * Print menu item
  289.  */
  290. static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int choice, int selected)
  291. {
  292.   int i;
  293.  
  294.   /* Clear 'residue' of last item */
  295.   wattrset(win, menubox_attr);
  296.   wmove(win, choice, 0);
  297.   for (i = 0; i < menu_width; i++)
  298.     waddch(win, ' ');
  299.   wmove(win, choice, tag_x);
  300.   wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
  301.   waddch(win, tag[0]);
  302.   wattrset(win, selected ? tag_selected_attr : tag_attr);
  303.   waddstr(win, tag + 1);
  304.   wmove(win, choice, item_x);
  305.   wattrset(win, selected ? item_selected_attr : item_attr);
  306.   waddstr(win, item);
  307. }
  308. /* End of print_item() */
  309.