home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 328_02 / wgetc.c < prev    next >
C/C++ Source or Header  |  1991-03-17  |  8KB  |  403 lines

  1. /*! wgetc.c        window-oriented  get keyboard/mouse, process as needed.
  2.  *
  3.  *    get a key from the keyboard or from the mouse.
  4.  *    if (timeout), black out the screen (blackout)
  5.  *
  6.  *    If a user-defined keytrap routine is in place, call it.
  7.  *        repeat getting keys until the user_defined routine is done.
  8.  *
  9.  *
  10.  *
  11.  *                    @ David Blum, 1986, 1989
  12.  */
  13. #include "wsys.h"
  14.  
  15.  
  16.  
  17.  
  18. /* timer function for 3-minute wait.
  19.  */
  20. static clock_t         W_NEAR get_limit(void);
  21.  
  22. /* screen blackout after 3 minute wait.
  23.  */
  24. static void         W_NEAR blackout ( void);
  25.  
  26. /* check_button() tests mouse use to see if it matches an active button.
  27.  *         PARAMETERS: whether to match BUTTONS or SCROLLBARS.
  28.  */
  29. static int W_NEAR check_button ( unsigned char button_test );
  30.  
  31. /* wait_flush() -
  32.  * small routine to wait for a keypress and then flush that key. 
  33.  */
  34. static void W_NEAR wait_flush (void);
  35.  
  36.  
  37.  
  38.  
  39.  
  40. /*! wgetc - get a single character
  41.  *
  42.  * caution: turning mouse on and off in graphics mode
  43.  *         prevents garbage on screen,
  44.  *         but you have to make sure that the calls stay balanced
  45.  *            ( or the mouse driver will go bonkers)
  46.  *         so I adopted these conventions for wgetc() routines:
  47.  *            1) turn mouse ON  at entry to wgetc()
  48.  *            2) turn mouse OFF afetr key is read.
  49.  *            3) no 'hooks' to external routines in between
  50.  *
  51.  */
  52. int wgetc(void)
  53.     {
  54.  
  55.     int key;
  56.  
  57.     clock_t time_limit, now_time;
  58.  
  59.  
  60.  
  61.     do
  62.         {
  63.  
  64.         time_limit = get_limit();
  65.  
  66.  
  67.         wmouse_turn (ON);
  68.  
  69.  
  70.  
  71.         /* is a key ready to get? */
  72.         while ( ! wready() )
  73.             {
  74.             now_time = clock();
  75.             if  ( now_time > time_limit )
  76.                 {
  77.                 blackout ( );
  78.                 time_limit = get_limit();
  79.                 }
  80.             }  /*end while !kbhit */
  81.  
  82.  
  83.         key = wreadc ();
  84.  
  85.  
  86.         wmouse_turn (OFF);
  87.  
  88.  
  89.  
  90.         if ( wkeytrap != NULL )
  91.             {
  92.             key = (*wkeytrap)(key);
  93.             }
  94.  
  95.  
  96.         } /* end of do... */
  97.  
  98.     while ( key == 0 );
  99.  
  100.     return (key);    /* wgetc()  */
  101.     }
  102.  
  103.  
  104.  
  105. /*! wready ()
  106.  *    tests to see if a key has been hit or if mouse has been used.
  107.  *
  108.  *
  109.  *
  110.  *
  111.  */
  112.  
  113.  
  114.  
  115.  
  116.  
  117. int wready(void)
  118.     {
  119.  
  120.  
  121.     int retcode;
  122.  
  123.     PSEUDOREGS;
  124.  
  125.  
  126.  
  127.     if ( wunget_buffer )
  128.         {
  129.         retcode = 1;
  130.         }
  131.  
  132.     else
  133.     if ( wpipein )
  134.         {
  135.         retcode = 1;
  136.         }
  137.     else
  138.         {
  139.         wmouse_location ();
  140.         if ( wmouse.wms_internal )
  141.             {
  142.             /* mouse was used */
  143.             retcode = 1;
  144.             }
  145.  
  146.         else
  147.             {
  148.             /* mouse not pressed --- check keyboard
  149.              */
  150.  
  151.             retcode = wready_kbd();
  152.  
  153.             }
  154.         }
  155.  
  156.  
  157.     return ( retcode );     /* wready */
  158.  
  159.     }
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172. /*! wreadc()
  173.  *
  174.  *    read unget buffer and/or redirection sources and/or mouse or kbd.
  175.  *
  176.  *      this function is like wgetc() but it does not do:
  177.  *        1) screen blackout if waiting for keypress.
  178.  *        2) mouse on/off (prevent garbage appearing on grpahics screen
  179.  *              3) call keyboard trap routine
  180.  *        4) repeat operation until an acceptable keypress is made.
  181.  *
  182.  *    NOTE 'pipes' are processed here:
  183.  *        unget buffer takes precedence over pipes.
  184.  *        keys which were ungot don't get passed on to any output pipes
  185.  *
  186.  *
  187.  */
  188. int wreadc(void)
  189.     {
  190.     int key=0;
  191.     register int temp;
  192.  
  193.     if ( wunget_buffer )
  194.         {
  195.         /* if a key is waiting in the unget buffer */
  196.         key = wunget_buffer;
  197.         wunget_buffer = 0;
  198.         }
  199.     else
  200.         {
  201.         if ( wpipein )
  202.             {
  203.             key = wpipein();
  204.             }
  205.         else
  206.             {
  207.             wmouse_location();
  208.             if ( wmouse.wms_used )
  209.                 {
  210.                 /* tell the user that the mouse was used,
  211.                  * and reset the interanl use marker
  212.                  * so that next call won't return MOUSE
  213.                  * unless mouse has actually been used.
  214.                  */
  215.                 wmouse.wms_internal = 0;
  216.  
  217.                 /* Map mouse clicks on buttons to appropriate key values
  218.                  * Map right button to ESCAPE
  219.                  * all other mouse use is WMOUSE.
  220.                  */
  221.                 key = MOUSE;
  222.                 if ( wmouse.wms_used & WMS_RIGHT_PRS )
  223.                     {
  224.                     key = ESCAPE;
  225.                     }
  226.                 else
  227.                 if ( wmouse.wms_used & WMS_LEFT_RLS )
  228.                     {
  229.                     if ( 0!=( temp= check_button(WBTN_BUTTON+WBTN_ACTIVE) ) )
  230.                         {
  231.                         key = temp;
  232.                         }
  233.                     }    /* end if (LEFT_RLS) */
  234.                 else
  235.                 if ( wmouse.wms_used & WMS_LEFT_PRS )
  236.                     {
  237.                     if ( 0!=( temp= check_button(WBTN_SCROLL+WBTN_ACTIVE) ) )
  238.                         {
  239.                         /* look for scrollbars if new button press.
  240.                          */
  241.                         key = temp;
  242.                         }
  243.                     }    /* end if (LEFT_PRS) */
  244.                 }    /* end if (mouse used) */
  245.             else
  246.                 {
  247.                 key = wread_kbd();
  248.                 }
  249.             }            /* end of getting MOUSE/kbd combo */
  250.  
  251.         if ( wpipeout )
  252.             {
  253.             wpipeout (key);
  254.             }
  255.  
  256.         }
  257.  
  258.     return (key);          /* wreadc() */
  259.     }
  260.     
  261.  
  262. static int W_NEAR check_button ( unsigned char button_test )
  263.     {
  264.     int key = 0;
  265.     WBUTTON *Bptr;
  266.  
  267.     /* look over list of buttons
  268.      * if mouse is 'inside' any of them, 
  269.      * set key value to button value.
  270.      */
  271.     for (Bptr = w0->winbutton;     Bptr; Bptr = Bptr->Bchain )
  272.         {
  273.         /*  both the type of button and the ACTIVE flag have to be on.
  274.          *  requires an exact match to all specified bits.
  275.          *
  276.          *  Also note the testing to see if mouse is inside button area. 
  277.          */
  278.         if (  (  ( (Bptr->Bstyle) & button_test )  == button_test ) 
  279.                  && (wmouse.wms_x >= Bptr->Bx   )
  280.                  &&    (wmouse.wms_x <  Bptr->Bxend)
  281.                  && (wmouse.wms_y >= Bptr->By   )
  282.                  && (wmouse.wms_y <= Bptr->Byend)
  283.                 )
  284.                 {
  285.                 key = Bptr->Bval;    /* set key = button */
  286.                 break;                /* quit for() loop  */
  287.                 }    /* end mouse inside button border */
  288.         }    /* end looking for Buttons */
  289.         
  290.         return (key);    /* check_button */
  291.         }
  292.  
  293.  
  294.  
  295. static clock_t     W_NEAR get_limit (void)
  296.     {
  297.     clock_t t;
  298.  
  299.     /* NOTE: in Microsoft C the CLK_TCK is 1000, 
  300.      * so if the timeout limit is > 32, you'll get integer arithmetic errors
  301.      */
  302.     #if WITMEOUT_LIMIT > 32
  303.         #ifndef __TURBOC__
  304.             #error WGETC-- must recode using long arithmetic 
  305.         #endif
  306.     #endif        /* TIMEOUT_LIMIT >32 */
  307.     
  308.     
  309.     t = clock() + WTIMEOUT_LIMIT * CLK_TCK;
  310.  
  311.     return (t);
  312.  
  313.     }
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322. /*! blackout  - screen saver routine.
  323.  *  black out the screen, wait for a keypress, restore the screen.
  324.  *
  325.  *  METHOD:
  326.  *    Hercules: hercules control port at 0x3B8 contains:
  327.  *        bit 7 (=hi, 0x80) = page assignment 0=0, 1=1
  328.  *        bit 5 ( 0x20 )    = blink enable (always on).
  329.  *                  3 ( 0x08 )    = video enable/disable
  330.  *            1 ( 0x02 )    = mode  ( 1= graphics )
  331.  *            0 ( 0x01 )    = hi-res control (always on)
  332.  *            unfortunately the port is write-only, so
  333.  *         need to construct appropriate bit values before setting.
  334.  *    EGA/VGA:
  335.  *        set color palette 
  336.  */
  337. #define  HCONTROL 0x21    /* default value for hercules control por 0x3B8 */
  338.  
  339.  
  340.  
  341. static void W_NEAR blackout (void)
  342.     {
  343.     char herc_byte;
  344.     unsigned char save_palette[17];
  345.     unsigned char black_palette[17];
  346.  
  347.  
  348.     PSEUDOREGS
  349.  
  350.     /* black the screen
  351.      */
  352.     switch (wmonitor)
  353.         {
  354.     case ('H'):
  355.     case ('M'):
  356.         /* build control byte to turn off video
  357.          * without affecting graphics mode, blink, or page
  358.          */
  359.         herc_byte = HCONTROL;
  360.         if ( wmode == 'G' )      herc_byte |= 0x02;
  361.         if ( w0-> winpage == 1 )  herc_byte |= 0x80;
  362.         outp ( 0x3B8, herc_byte );
  363.         wait_flush ();
  364.         /* video enable
  365.          */
  366.         herc_byte |= 0x08;    
  367.         outp ( 0x3B8, herc_byte );
  368.         break;
  369.  
  370.     case ('E'):
  371.     case ('V'):
  372.             wgetpalette ( save_palette );
  373.             memset ( black_palette, 0, sizeof (black_palette) );
  374.             wsetpalette ( black_palette );        
  375.             wait_flush ();
  376.             wsetpalette ( save_palette );
  377.  
  378.         break;
  379.  
  380.     default:
  381.         /* do nothing if another type of monitor */
  382.         return;
  383.  
  384.         }/*end switch*/
  385.  
  386.     return; /* wblackout */
  387.     }
  388.  
  389. static void W_NEAR wait_flush (void)
  390.     {
  391.     /* wait for a keypress, then flush that key */
  392.     while ( !wready() )
  393.         {/*empty*/}
  394.  
  395.     wreadc ();
  396.     return;        /* wait_flush */
  397.     
  398.     }
  399.  
  400.  
  401. /*----------------------end of WGETC.C ----------------------------------*/
  402.  
  403.