home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 315_01 / menu.c < prev    next >
C/C++ Source or Header  |  1990-05-16  |  22KB  |  715 lines

  1.  
  2. /* mgetch() and mgets() were added 9/89 by T Clune. */
  3. /* clear_input_devices() made externally-visible 9/89 by T Clune */
  4.  
  5. /* print_headline() added 8/89, because I always use this construct anyway. */
  6. /* added by T Clune. */
  7.  
  8. /* menu_mouse_config() added 8/89 by T. Clune to support user-configuration */
  9. /* of mouse parameters, as per Frans VdV request. */
  10.  
  11. /* get_file() was added to menu.c [it was formerly in grabmain.c] and */
  12. /* dir_menu() was eliminated 12/88, and get_dir() in dos_func.c was */
  13. /* rewritten to use string pointers instead of character arrays.  Now */
  14. /* get_dir() is compatible with menu(), so dir_menu() is superfluous. */
  15. /* Modified by T Clune. */
  16.  
  17. /* Modified by T Clune 12/88 to support mouse selection of menu items. */
  18. /* menu.obj must be linked with mouselib.obj and sound.obj and the */
  19. /* Microsoft library mouse.lib now.  Sound.obj is used to generate the */
  20. /* pause between mouse queries to give a pause between menu */
  21. /* selections, analogous to the pause in keyboard repeats.  Mouselib.obj */
  22. /* is my mouse library front end. */
  23.  
  24. /* pathprint() added to menu.c 11/20/88 by T. Clune.  Moved from */
  25. /* tmbr_gp.c for conceptual unity. */
  26.  
  27. /* c_dir fname_unused() and get_dir() functions moved to dos_func.c */
  28. /* 11/88 by T. Clune. */
  29.  
  30. /* c_dir.c functions added to menu.c 6/88 by T. Clune. */
  31. /* the dir_menu() function supports a menu() -style selection of */
  32. /* directory files. */
  33. /* written by T. Clune for R. Webb, 5/18/88. */
  34. /* Copyright (c) 1988, Eye Research Institute, 20 Staniford St., Boston, MA */
  35. /* All rights reserved. */
  36.  
  37. /* menu.c is a menu-creation utility for use with large memory model */
  38. /* Microsoft C routines.  It expects to run on an IBM PC or At with */
  39. /* either monchrome (including Hercules in text mode) or CGA adaptor */
  40. /* menu() and reset_menu() are externally visible, highlight() is an */
  41. /* internal routine called by menu() only.  Written by Thomas Clune */
  42. /* for the Eye Research Institute, 20 Staniford St., Boston, MA 02114 */
  43. /* Copyright 1987, E.R.I.  All rights reserved. */
  44.  
  45.  
  46. #include "msc_hdrs.h"   /* the usual gang of MS C headers */
  47. #include "menu.h"
  48. #include "ansi.h"
  49. #include "mouselib.h"
  50. #include "keys.h"
  51. #include "sound.h"
  52. #include "dos_func.h"
  53.  
  54. #define HERC_BASE       0XB0000000      /* base address of mono card */
  55. #define CGA_BASE        0XB8000000      /* base address of color card */
  56.  
  57.  
  58. static unsigned char off = 7;      /* unlit character attribute code */
  59. static unsigned char on = 112;     /* lit character attribute code */
  60.  
  61. static int mouse_flag=KEYBOARD_ONLY;    /* flag for whether mouse-based selection is  */
  62.     /* active.  Set to NO for compatibility with old version of menu.c */
  63.     /* See mouse_flag_toggle() for mouse_flag values */
  64. static double off_time=OFF_TIME;
  65. static double duty_time=DUTY_TIME;
  66. static int mouse_sensitivity=MOUSE_SENSITIVITY;
  67.  
  68. static char *screen_ptr;  /* base of screen memory to be named later */
  69. static char *mode_ptr = (char *)0X00000410; /* mode memory address */
  70.  
  71. static void highlight();    /* local function for turning reverse */
  72.                 /* video on and off */
  73. static int get_response();  /* the operator-selection function, added 12/88 */
  74.     /* to support mouse input option as well as keyboard input */
  75. static int mouse_read();    /* mouse support function for get_response() */
  76.  
  77.  
  78.  
  79.  
  80.  
  81. /* +++++++++++++++++ clear_input_devices() +++++++++++++++++++++++++ */
  82. /* clear_input_devices() makes sure that no keypresses are pending  */
  83. /* or mouse buttons depressed before the menu selection is active */
  84.  
  85. void clear_input_devices()
  86. {
  87.     int delay=0;
  88.  
  89.     /* clear the keyboard bufffer */
  90.     if((mouse_flag != MOUSE_ONLY) && kbhit())
  91.     while(kbhit())
  92.        getch();
  93.  /* if the mouse is active, make sure the buttons are not depressed on entry */
  94.     if((mouse_flag !=KEYBOARD_ONLY) && (button_read().status != 0))
  95.     {
  96.     do
  97.     {
  98.         pause(0.1);
  99.         delay++;
  100.     }while((button_read().status != 0) && (delay<20));
  101.  
  102.     /* after 2 secs, tell 'em to get their finger off the damn button */
  103.     if(delay>=20)
  104.     {
  105.         while(button_read().status !=0)
  106.         mouse_warning_sound();
  107.     }
  108.     }
  109. }
  110.  
  111.  
  112.  
  113.  
  114.  
  115. /* +++++++++++++++++++++ get_file() +++++++++++++++++++++++++++++++++ */
  116. /* get a filename by selecting from highlighting menu. Val returned is 0 */
  117. /* unless there are too many files for this routine to process, in which case  */
  118. /* the f.error_flag is -1, or unless QUIT is the menu item selected, in which */
  119. /* case f.error_flag is set to 1. The memory freed in get_file() was allocated */
  120. /* in get_dir() (ind dos_func.c) except for the QUIT string area, which was */
  121. /* allocated here. */
  122.  
  123.  
  124. string_struc get_file()
  125. {
  126.  
  127.     int i,j,k;
  128.     int length;
  129.     static char *fnames[MAX_FILES+1];
  130.     static string_struc f;
  131.     static char dir_name[40]="";
  132.     int default_flag=0;
  133.     static char spec[14]="*.*";
  134.     char search_name[54];
  135.     static int last_choice=0;
  136.     char c;
  137.  
  138.     f.error_flag=0;
  139.     CLS;
  140.     if(!strlen(dir_name))
  141.     {
  142.     strcpy(search_name, "Default directory");
  143.     default_flag=1;
  144.     }
  145.     else
  146.     strcpy(search_name, dir_name);
  147.     printf("Current search path is %s\n",search_name);
  148.     printf("Enter new path, or <CR> to keep current path\n");
  149.     if(mouse_flag != KEYBOARD_ONLY)
  150.     mouse_gets(dir_name);
  151.     else
  152.     gets(dir_name);
  153.     if((!strlen(dir_name)) && (default_flag == 0))
  154.     strcpy(dir_name, search_name);
  155.     printf("Enter file format for search, or <CR> to keep default %s\n", spec);
  156.     if(mouse_flag != KEYBOARD_ONLY)
  157.     mouse_gets(f.string);
  158.     else
  159.     gets(f.string);
  160.     if(strlen(f.string))
  161.     strcpy(spec, f.string);
  162.  
  163.     strcpy(search_name, dir_name);
  164.     length=strlen(search_name);
  165.     if(length && (!(search_name[length-1]=='\\')))
  166.     strcat(search_name, "\\");
  167.     strcat(search_name, spec);
  168.  
  169.     i=get_dir(search_name,fnames,MAX_FILES);
  170.     if(i>MAX_FILES)
  171.     {
  172.     printf("Too many files for array size\n");
  173.     printf("Maximum number of file entries supported=%d\n", MAX_FILES);
  174.     printf("Try using a more restrictive file format for the search\n");
  175.     printf("Press any key to return to menu\n");
  176.     if(mouse_flag != KEYBOARD_ONLY)
  177.         inpause();
  178.     else
  179.         getch();
  180.     f.error_flag=-1;
  181.     i=MAX_FILES-1;  /* the number of buffers to free() */
  182.     }
  183.     else
  184.     {
  185.     k=MAX_FILES/20;  /* 20 lines for display */
  186.     fnames[i]=malloc(5);
  187.     if(fnames[i]==NULL)
  188.     {
  189.         printf("Error allocating menu buffer memory.  Program aborting.\n");
  190.         exit(-1);
  191.     }
  192.     strcpy(fnames[i], "Quit");  /* add an ABORT option to menu */
  193.     CLS;
  194.     printf("Number of matching files: %d\n",i);
  195.         /* 80/k=number of spaces per field width */
  196.  
  197.     reset_menu(last_choice);
  198.     j=menu(2,0,80/k,k,1,i+1,0,fnames);
  199.     last_choice=j;
  200.     CLS;
  201.     if(j != i)  /* if not QUIT */
  202.     {
  203.         strcpy(f.string, dir_name);
  204.         if((strlen(f.string))&&(!(f.string[strlen(f.string)-1]=='\\')))
  205.         strcat(f.string, "\\");
  206.         strcat(f.string, fnames[j]);
  207.     }
  208.     else
  209.         f.error_flag=1;
  210.     }
  211.     for(j=0;j<=i;j++)
  212.     free(fnames[j]);
  213.  
  214.     return(f);
  215.  
  216. }
  217.  
  218.  
  219.  
  220. /* ++++++++++++++++ get_mouse_flag() +++++++++++++++++++++++++++ */
  221. /* get_mouse_flag() returns the current status of the mouse flag. */
  222. /* it is useful in making other i/o operations conform to the menu */
  223. /* style, i.e., if the mouse is active for the menu, you may want */
  224. /* other input options to support mouse input, etc. Any non-zero */
  225. /* value means that the mouse is active.  Any value >=0 means that */
  226. /* the keyboard is active. */
  227.  
  228. int get_mouse_flag()
  229. {
  230.     return mouse_flag;
  231.  
  232. }
  233.  
  234.  
  235.  
  236.  
  237.  
  238. /* +++++++++++++++++++ menu() +++++++++++++++++++++++++++++++++++++++++ */
  239. /*                                                                      */
  240. /*              top_mar = top margin spacing (0<=t_m<=24)               */
  241. /*              left_mar = left margin spacing (0<=l_m<=79)             */
  242. /*              tab = total spaces per column                           */
  243. /*              columns = number of columns in menu                     */
  244. /*              line_feed = number of spaces between lines in menu      */
  245. /*              entries = number of items in menu array                 */
  246. /*              label = no auto numbering of menu items if 0,           */
  247. /*                      auto number but no number-key select if = 1     */
  248. /*                      auto number and number-key select if > 1        */
  249. /*                      MAX. ENTRIES FOR AUTO NUMBERING = 10            */
  250. /*                      auto capital lettering but no select if = -1    */
  251. /*                      auto lettering with keyboard select if < -1     */
  252. /*                      MAX. ENTRIES FOR AUTO LETTERING = 26            */
  253. /*              str_ptr = pointer to menu entries array                 */
  254. /*                                                                      */
  255. /*              menu() returns the subscript of the menu item selected  */
  256. /*              i.e., first item = 0, last item = ENTRIES - 1.          */
  257. /*                                                                      */
  258. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  259.  
  260.  
  261. int menu(top_mar,left_mar,tab,columns,line_feed,entries,label,str_ptr)
  262.  
  263.  
  264. int top_mar, left_mar, tab, columns, line_feed, entries, label;
  265. char *str_ptr[];
  266.  
  267.  
  268. {
  269.  
  270.     static int index = 0;      /* menu array element currently active */
  271.     int x, y, i, j, disp_num;  /* x,y screen coords, i,j menu array elements */
  272.                    /* disp_num menu auto number */
  273.     unsigned char inchar;       /* input key selection variable */
  274.  
  275.  
  276.     if(columns==0)      /* reset index flag from reset_menu() */
  277.     {
  278.     index=line_feed;
  279.     return;
  280.     }
  281.  
  282.     if(index>=entries)  /* make sure index is not larger than the array */
  283.     index=0;
  284.  
  285.  
  286.     outp(0X3B4, 10);        /* turn off cursor */
  287.     outp(0X3B5, 32);
  288.  
  289.     i = *mode_ptr;          /* is the system monitor monochrome? */
  290.     if((i & 48) == 48)      /* if so, set mono screen base address */
  291.         screen_ptr = (char *)HERC_BASE;
  292.     else                    /* if not, set color screen base address */
  293.         screen_ptr = (char *)CGA_BASE;
  294.  
  295.  
  296.     for(i=0;i<entries;i++)                          /* print menu */
  297.     {
  298.         j = 0;                     /* first element in menu[i] entry */
  299.         x = left_mar + (i % columns) * tab;   /* x-location for print */
  300.         y = top_mar + (i/columns)*line_feed;  /* screen y for print */
  301.         if(label > 0)             /* use numbers if appropriate */
  302.         {
  303.         disp_num = i + '1';      /* "ASCII-ize" the number */
  304.         if(disp_num > '9')       /* >=10 prints as 0 */
  305.                disp_num = '0';
  306.         }
  307.         if(label < 0)      /* use capital letters if appropriate */
  308.         {
  309.         disp_num = 'A' + i;
  310.         if(disp_num > 'Z')
  311.             disp_num = 'Z';
  312.         }
  313.         if(label != 0)     /* for auto numbers or letters */
  314.         {
  315.         *(screen_ptr + 160*y + 2*x) = disp_num;
  316.         if(index == i)             /* highlight first number */
  317.             *(screen_ptr + 160*y + 2*x + 1) = on;
  318.         else                    /* but not the others */
  319.             *(screen_ptr + 160*y + 2*x + 1) = off;
  320.         x += 1;         /* go to next screen memory location */
  321.         *(screen_ptr + 160*y + 2*x) = 32;  /* print space after # */
  322.         if(index == i)               /* highlight first space */
  323.             *(screen_ptr + 160*y + 2*x + 1) = on;
  324.         else                    /* but not the others */
  325.             *(screen_ptr + 160*y + 2*x + 1) = off;
  326.         x += 1;         /* go to next screen memory location */
  327.         }
  328.         while(str_ptr[i][j]!='\0')  /* print the string to the end */
  329.         {
  330.         *(screen_ptr + 160*y + 2*x) = str_ptr[i][j];
  331.         if(index == i)      /* highlight as appropriate */
  332.             *(screen_ptr + 160*y + 2*x + 1) = on;
  333.         else
  334.             *(screen_ptr + 160*y + 2*x + 1) = off;
  335.         x += 1;     /* next screen memory location */
  336.         j += 1;     /* next menu[i] character */
  337.         }
  338.         *(screen_ptr + 160*y + 2*x) = str_ptr[i][j]; /* use '\0' */
  339.                 /* to mark end of menu entry on screen */
  340.     }
  341.  
  342.     clear_input_devices();
  343.  
  344.     while((inchar=get_response())!=CARRIAGE_RETURN)  /* move highlight around selections */
  345.     {
  346.     inchar = toupper(inchar);   /* caps only for alpha entries */
  347.  
  348.     highlight(index,top_mar,left_mar,tab,columns,line_feed,off);
  349.  
  350.     if(inchar==UP_MOVE)     /* going up? */
  351.         if((index-columns)>=0)
  352.         index -= columns;     /* increment selection */
  353.  
  354.     if(inchar==RIGHT_MOVE)  /* right? */
  355.         if(((index%columns)<(columns-1)) && ((index+1)<entries))
  356.         index++;
  357.  
  358.     if(inchar==DOWN_MOVE)   /* going down? */
  359.         if((index+columns)<entries)
  360.         index  += columns;
  361.  
  362.     if(inchar==LEFT_MOVE)  /* going left? */
  363.          if((index%columns)>0)
  364.          index--;
  365.  
  366.     highlight(index,top_mar,left_mar,tab,columns,line_feed,on);
  367.  
  368.     if(label>1)   /* are number keys active for selection? */
  369.     {
  370.         if(entries != 10)
  371.         j='1';
  372.         else
  373.         j='0';
  374.         if(inchar>=j && inchar <=(j+entries-1))
  375.         /* if num-key selection */
  376.         {
  377.         highlight(index,top_mar,left_mar,tab,columns,line_feed,off);
  378.         index=inchar-'1';   /* "Numberize" ASCII and */
  379.             /* subtract 1 for array starting at 0 */
  380.         if(index<0)   /* menu 0 = array 9 */
  381.            index = 9;
  382.         highlight(index,top_mar,left_mar,tab,columns,line_feed,on);
  383.         break;
  384.         }
  385.     }
  386.  
  387.     if(label<-1)  /* are letter keys active? */
  388.     {
  389.        if(inchar>='A' && inchar<=('A'+entries-1))
  390.         /* if letter key selected */
  391.         {
  392.            highlight(index,top_mar,left_mar,tab,columns,line_feed,off);
  393.            index = inchar-'A';
  394.            highlight(index,top_mar,left_mar,tab,columns,line_feed,on);
  395.            break;
  396.         }
  397.     }
  398.  
  399.  
  400.     }
  401.  
  402.  
  403.     outp(0X3B4, 10);            /* turn cursor back on */
  404.     outp(0X3B5, 11);
  405.  
  406.     return index;         /* return selected number */
  407. }
  408.  
  409.  
  410.  
  411. /* +++++++++++++++++++ menu_mouse_config() ++++++++++++++++++++++++++++++ */
  412. /* menu_mouse_config() sets the number of mickeys needed for a mouse movement */
  413. /* to register as significant, and the duty cycle for evaluating the mouse */
  414. /* motion.  duty_on is the time in second when the mouse is accumulating */
  415. /* data, and duty_off is the time when the data is ignored.  The need for */
  416. /* an "off" time is to give a positive feel to making a selection. */
  417.  
  418. void menu_mouse_config(sensitivity,duty_on,duty_off)
  419. int sensitivity;
  420. double duty_on, duty_off;
  421. {
  422.     mouse_sensitivity=sensitivity;
  423.     duty_time=duty_on;
  424.     off_time=duty_off;
  425. }
  426.  
  427.  
  428.  
  429.  
  430.  
  431. /* +++++++++++++++++++++++++ mgetch() +++++++++++++++++++++++++++++++++ */
  432. /* mgetch() is the generic mouse-and-keyboard or just-keyboard getch() */
  433. /* function.  It decides whether to use the mouse on the basis of the status */
  434. /* of mouse_flag.   inpause() is in mouselib.c */
  435.  
  436. int mgetch()
  437. {
  438.     int ret_val;
  439.  
  440.     if(mouse_flag)
  441.     ret_val=inpause();
  442.     else
  443.     ret_val=getch();
  444.  
  445.     return ret_val;
  446.  
  447. }
  448.  
  449.  
  450.  
  451. /* +++++++++++++++++++++ mgets() ++++++++++++++++++++++++++++++++++++ */
  452. /* mgets() is the generic mouse-plus keuyboard or just-keyboard gets() */
  453. /* function.  The decision on whether to use the mouse is based on the */
  454. /* status of mouse_flag. mouse_gets() is in mouselib.c */
  455.  
  456. char * mgets(strptr)
  457. char *strptr;
  458. {
  459.     clear_input_devices();
  460.     if(mouse_flag)
  461.     strptr=mouse_gets(strptr);
  462.     else
  463.     strptr=gets(strptr);
  464.  
  465.     return strptr;
  466.  
  467. }
  468.  
  469.  
  470.  
  471.  
  472.  
  473. /* +++++++++++++++++++++++++ mouse_flag_toggle() +++++++++++++++++++++++++++++++ */
  474. /* mouse_flag_toggle() sets the variable mouse_flag on or off to enable and disable */
  475. /* mouse-based selection of menu items in menu() and dir_menu().  Added 12/88 */
  476. /* by T Clune. if VAL=0, mouse is disabled.  If VAL>0, mouse and keyboard */
  477. /* are enabled.  IF mouse<0, mouse only is enabled. */
  478.  
  479. void mouse_flag_toggle(val)
  480. int val;
  481. {
  482.     if(val>0)
  483.     mouse_flag=MOUSE_PLUS_KEYBOARD;
  484.     if(val==0)
  485.     mouse_flag=KEYBOARD_ONLY;
  486.     if(val<0)
  487.     mouse_flag=MOUSE_ONLY;
  488. }
  489.  
  490.  
  491.  
  492.  
  493. /* ++++++++++++++++++++++++++++ pathprint() ++++++++++++++++++++++++++++ */
  494. /* pathprint() prints your current position in the menu structure on the */
  495. /* bottom of the screen.  Pathprint() must be called at each menu in the */
  496. /* heirarchy in order to have the correct information.  MENU_NAME is the */
  497. /* current menu's pathprint name.  All pathprint() does is determine whether */
  498. /* that name is new to the list or not.  If yes, it is added to the path, */
  499. /* if no, the path list is truncated at that name. */
  500.  
  501. void pathprint(menu_name)
  502. char menu_name[];
  503. {
  504.     static char path_name[80]="";
  505.     static char divider[]="->";
  506.     char *strptr;
  507.  
  508.     strptr=strstr(path_name, menu_name);
  509.  
  510.     /* if the name is not currently on the printed path */
  511.     if(strptr==NULL)
  512.     {
  513.     if(strlen(path_name))  /* if not the first name, add name separator */
  514.         strcat(path_name, divider);
  515.     strcat(path_name, menu_name);  /* add the name */
  516.     }
  517.     /* if the name is already on the path */
  518.     else
  519.     {
  520.     *strptr='\0'; /* delete everything from the name on in the path */
  521.     strcat(path_name, menu_name); /* and re-append the name at the end */
  522.     }
  523.     POSITION(1,24);
  524.     LINE_CLEAR;
  525.     POSITION(1,24);
  526.     printf("You are here: %s\n", path_name);
  527.  
  528. }
  529.  
  530.  
  531.  
  532. /* +++++++++++++++++++++++ print_headline() +++++++++++++++++++++++++++++ */
  533. /* print_headline() writes an underlined string starting at x, y (1<=x<=80, */
  534. /* 1<=y<=25).  It is intended for use printing the title of a menu, which is */
  535. /* passed as STRING.  Added by T. Clune, 8/89. */
  536.  
  537. void print_headline(string, x, y)
  538. char string[];
  539. int x, y;
  540. {
  541.  
  542.         /* POSITION and CHAR_ATTRIBUTE are ANSI.H macros */
  543.  
  544.     POSITION(x,y); /* center heading */
  545.     CHAR_ATTRIBUTE(UNDERSCORE);
  546.     printf("%s\n",string);
  547.  
  548.     CHAR_ATTRIBUTE(NORMAL);
  549. }
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556. /* ++++++++++++++++ reset_menu() ++++++++++++++++++++++++++++++ */
  557. /* reset_menu() resets the static variable that "remembers" which */
  558. /* selection was last made on the current menu.  It should be called */
  559. /* whenever leaving a menu level for a new menu level that may call */
  560. /* menu(), or an error condition can result if the next menu has */
  561. /* fewer entries than the previous menu. SETTING may be set to the */
  562. /* value that the menu being returned to last had or to 0 as a reset */
  563. /* without "memory." */
  564.  
  565.  
  566. void reset_menu(setting)
  567. int setting;
  568. {
  569.     char *dummy;
  570.  
  571.     menu(0,0,0,0,setting,0,0,dummy);      /* reset menu static variable to setting */
  572. }
  573.  
  574.  
  575.  
  576.  
  577.  
  578. /* ++++++++++++++++++++++++++++++ get_extended_key() ++++++++++++++++++++++ */
  579. /* get_extended_key() gets the ALT:KEY arrow codes and maps them onto single */
  580. /* character values (The arrow keys are mapped onto four low-usage ASCII */
  581. /* vals: CTL-A, CTL-B, CTL-D, and CTL-E.) */
  582.  
  583. static int get_extended_key()
  584. {
  585.     int inchar;
  586.  
  587.     inchar=getch();     /* get the second key */
  588.     switch(inchar)
  589.     {
  590.     case UPARROW:        /* UP=CNTL-A */
  591.         inchar=UP_MOVE;
  592.         break;
  593.     case LEFTARROW:        /* LEFT=CNTL-B */
  594.         inchar=LEFT_MOVE;
  595.         break;
  596.     case RIGHTARROW:        /* RIGHT=CNTL-D */
  597.         inchar=RIGHT_MOVE;
  598.         break;
  599.     case DOWNARROW:        /* DOWN=CNTL-E */
  600.         inchar=DOWN_MOVE;
  601.         break;
  602.     default:        /* if it was anything else, "erase" it */
  603.         inchar=0;
  604.     }
  605.     return inchar;
  606. }
  607.  
  608.  
  609.  
  610.  
  611. /* ++++++++++++++++++++++++ get_response() +++++++++++++++++++++++++++ */
  612. /* get_response() is the menu() and dir_menu() operator selection function */
  613. /* that returns the character selected by keyboard or the mouse selection */
  614. /* if mouse_flag is not zero */
  615.  
  616. static int get_response()
  617. {
  618.     int ret_val= -1;
  619.  
  620.     while(ret_val == -1)
  621.     {
  622.     if((mouse_flag != MOUSE_ONLY) && kbhit())
  623.     {
  624.         ret_val=getch();
  625.         if(ret_val==ALT)
  626.         ret_val=get_extended_key();
  627.         /* clear the keyboard buffer */
  628.         while(kbhit())
  629.         getch();
  630.     }
  631.     else
  632.         if(mouse_flag != KEYBOARD_ONLY)
  633.         ret_val=mouse_read();
  634.  
  635.     }
  636.     return ret_val;
  637.  
  638. }
  639.  
  640.  
  641.  
  642. /* +++++++++++++++++++ highlight() +++++++++++++++++++++++++++ */
  643.  
  644.  
  645. static void highlight(index,top_mar,left_mar,tab,columns,line_feed,value)
  646.  
  647.  
  648. int index,top_mar,left_mar,tab,columns,line_feed;
  649. unsigned char value;
  650.  
  651. {
  652.     /* Highlight selected entry and un-highlight deselected entry */
  653.     /* only menu attributes are modified */
  654.  
  655.  
  656.     int x, y;
  657.  
  658.     x = left_mar + (index % columns) * tab;
  659.     y = top_mar + (index/columns)*line_feed;
  660.  
  661.  
  662.     while(*(screen_ptr + 160*y + 2*x) != '\0')
  663.     {
  664.         *(screen_ptr + 160*y + 2*x + 1) = value;
  665.         x += 1;
  666.     }
  667.  
  668.  
  669. }
  670.  
  671.  
  672. /* ++++++++++++++++++++++++++ mouse_read() +++++++++++++++++++++++++++++ */
  673. /* mouse_read() reads the current condition of the mouse, and returns -1 */
  674. /* if there is "nothing to report", the value is the keyboard equivalent */
  675. /* to the mouse reading significance otherwise. */
  676.  
  677. static int mouse_read()
  678. {
  679.     int ret_val= -1;
  680.     mstruc m;
  681.     if(button_read().status == RIGHT_BUTTON)
  682.     ret_val=CARRIAGE_RETURN;
  683.     else
  684.     {
  685.     /* clear mouse position counter, pause to let user feel positive lock */
  686.     /* on selected position, like keyboard repeat delay */
  687.     pause(off_time);
  688.     mdpos_read();
  689.     pause(duty_time);
  690.     m=mdpos_read();
  691.     m.dx /=mouse_sensitivity;
  692.     m.dy /=mouse_sensitivity;
  693.     /* the mouse will only respond left/right or up/down on a given read */
  694.     if(m.dx || m.dy)
  695.     {
  696.         if(abs(m.dx) >= abs(m.dy))
  697.         {
  698.          if(m.dx>0)
  699.              ret_val=RIGHT_MOVE;
  700.           else
  701.              ret_val=LEFT_MOVE;
  702.         }
  703.         else
  704.         {
  705.         if(m.dy>0)
  706.             ret_val=DOWN_MOVE;
  707.         else
  708.             ret_val=UP_MOVE;
  709.         }
  710.     }
  711.     }
  712.  
  713.     return ret_val;
  714. }
  715.