home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / courses / charget.c < prev    next >
Text File  |  1992-07-09  |  9KB  |  261 lines

  1. /****************************************************************/
  2. /* Getch() routines of the PCcurses package            */
  3. /*                                */
  4. /****************************************************************/
  5. /* This version of curses is based on ncurses, a curses version    */
  6. /* originally written by Pavel Curtis at Cornell University.    */
  7. /* I have made substantial changes to make it run on IBM PC's,    */
  8. /* and therefore consider myself free to make it public domain.    */
  9. /*        Bjorn Larsson (...mcvax!enea!infovax!bl)    */
  10. /****************************************************************/
  11. /* 1.0:    Release:                    870515    */
  12. /* 1.1:    Bug fixes: call to _curseskeytest() changed        */
  13. /*    _curseskeytst(). Test of that routine also        */
  14. /*    lacked () in one place:                870907    */
  15. /* 1.2:    #undef:ine of getch now covers all the file, to        */
  16. /*    make sure this module's getch() calls go to DOS,    */
  17. /*    not to the PCCurses 'getch()' function. Fixed        */
  18. /*    thanks to N.D. Pentcheff:            881002    */
  19. /* 1.3:    MSC -W3, Turbo'C' -w -w-pro checkes:        881005    */
  20. /****************************************************************/
  21.  
  22. #include <curses.h>
  23. #include <curspriv.h>
  24.  
  25. #undef getch                /* We use MSC getch() below */
  26.  
  27. #include <conio.h>
  28.  
  29. static    int    rawgetch();        /* get raw char via BIOS */
  30. static    int    sysgetch();        /* get char via system */
  31. static    int    validchar();        /* keypad xlate and char check */
  32.  
  33. char _curses_charget_rcsid[] = "@(#)charget.c v1.3 - 881005";
  34.  
  35. static    int    buffer[_INBUFSIZ];    /* character buffer */
  36. static    int    pindex = 0;        /* putter index */
  37. static    int    gindex = 1;        /* getter index */
  38. static    WINDOW *w;            /* to reduce stack usage */
  39. static    int    ungind = 0;        /* wungetch() push index */
  40. static    int    ungch[NUNGETCH];    /* array of ungotten chars */
  41.  
  42. /* Table for key code translation of function keys in keypad mode */
  43. /* These values are for strict IBM keyboard compatibles only */
  44.  
  45. static    int    kptab[] =
  46.   {
  47.   0x3b,KEY_F(1),  0x3c,KEY_F(2),  0x3d,KEY_F(3),  0x3e,KEY_F(4),
  48.   0x3f,KEY_F(5),  0x40,KEY_F(6),  0x41,KEY_F(7),  0x42,KEY_F(8),
  49.   0x43,KEY_F(9),  0x44,KEY_F(10), 0x47,KEY_HOME,  0x48,KEY_UP,
  50.   0x49,KEY_PPAGE, 0x4b,KEY_LEFT,  0x4d,KEY_RIGHT, 0x4f,KEY_LL,
  51.   0x50,KEY_DOWN,  0x51,KEY_NPAGE, 0x52,KEY_IC,    0x53,KEY_DC,
  52.   0x54,KEY_F(11), 0x55,KEY_F(12), 0x56,KEY_F(13), 0x57,KEY_F(14),
  53.   0x58,KEY_F(15), 0x59,KEY_F(16), 0x5a,KEY_F(17), 0x5b,KEY_F(18),
  54.   0x5c,KEY_F(19), 0x5d,KEY_F(20), 0x5e,KEY_F(21), 0x5f,KEY_F(22),
  55.   0x60,KEY_F(23), 0x61,KEY_F(24), 0x62,KEY_F(25), 0x63,KEY_F(26),
  56.   0x64,KEY_F(27), 0x65,KEY_F(28), 0x66,KEY_F(29), 0x67,KEY_F(30),
  57.   0x73,KEY_LEFT,  0x74,KEY_RIGHT,  0x75,KEY_LL,   0x76,KEY_NPAGE,
  58.   0x77,KEY_HOME,  0x84,KEY_PPAGE,  0x100,        -1
  59.   };
  60.  
  61.  
  62. /****************************************************************/
  63. /* Wgetch(win) gets a character from the terminal, in normal,    */
  64. /* cbreak or raw mode, optionally echoing to window  'win'.    */
  65. /****************************************************************/
  66.  
  67. int wgetch(win)
  68.   WINDOW    *win;
  69.   {
  70.   int key;
  71.   int cbr;
  72.  
  73.   if (ungind)                    /* if ungotten char exists */
  74.     return(ungch[--ungind]);            /* remove and return it */
  75.  
  76.   if ((!_cursvar.raw) && (!_cursvar.cbreak))    /* if normal */
  77.     if (gindex < pindex)            /* and data in buffer */
  78.       return(buffer[gindex++]);
  79.  
  80.   w = win;                    /* static for speed & stack */
  81.   pindex = 0;                    /* prepare to buffer data */
  82.   gindex = 0;
  83.   while(1)                    /* loop for any buffering */
  84.     {
  85.     if (_cursvar.raw)                /* get a raw character */
  86.       key = rawgetch();
  87.     else                    /* get a system character */
  88.       {
  89.       cbr = _cursesgcb();            /* get ^BREAK status */
  90.       _cursesscb(_cursvar.orgcbr);        /* if break return proper */
  91.       key = sysgetch();
  92.       _cursesscb(cbr);                /* restore as it was */
  93.       }
  94.     if (w->_nodelay && (key == -1))        /* if nodelay and no char */
  95.       return(-1);
  96.     if ((key == '\r') && _cursvar.autocr && !_cursvar.raw) /* translate cr */
  97.       key = '\n';
  98.     if (_cursvar.echo && (key < 0x100))        /* check if echo */
  99.       {
  100.       waddch(w,key);
  101.       wrefresh(w);
  102.       }
  103.     if (_cursvar.raw || _cursvar.cbreak)    /* if no buffering */
  104.       return(key);
  105.     if (pindex < _INBUFSIZ-2)            /* if no overflow, */
  106.       buffer[pindex++] = key;            /* put data in buffer */
  107.     if ((key == '\n') || (key == '\r'))        /* if we got a line */
  108.       return(buffer[gindex++]);
  109.     } /* while */
  110.   } /* wgetch */
  111.  
  112. /****************************************************************/
  113. /* Flushinp() kills any pending input characters.        */
  114. /****************************************************************/
  115.  
  116. void flushinp()
  117.   {
  118.   while(_curseskeytst())        /* empty keyboard buffer */
  119.     _curseskey();
  120.   while(kbhit())            /* empty system's buffers */
  121.     (void) getch();
  122.   gindex = 1;                /* set indices to kill buffer */
  123.   pindex = 0;
  124.   ungind = 0;                /* clear ungch array */
  125.   } /* flushinp */
  126.  
  127. /****************************************************************/
  128. /* Wungetch() pushes back its argument on the input stream. If    */
  129. /* OK, returns 1, otherwise returns 0.                */
  130. /****************************************************************/
  131.  
  132. int    wungetch(ch)
  133.   int     ch;
  134.   {
  135.   if (ungind >= NUNGETCH)        /* pushback stack full */
  136.     return(0);
  137.   ungch[ungind++] = ch;
  138.   return(1);
  139.   } /* wungetch() */
  140.  
  141. /****************************************************************/
  142. /* Mvgetch() first moves the stdscr cursor to a new location,    */
  143. /* then does a wgetch() on stdscr.                */
  144. /****************************************************************/
  145.  
  146. int    mvgetch(y,x)
  147.   int y;
  148.   int x;
  149.   {
  150.   wmove(stdscr,y,x);
  151.   return(wgetch(stdscr));
  152.   } /* mvgetch */
  153.  
  154. /****************************************************************/
  155. /* Mvwgetch() first moves the cursor of window 'win' to a new    */
  156. /* location, then does a wgetch() in 'win'.            */
  157. /****************************************************************/
  158.  
  159. int mvwgetch(win,y,x)
  160.   WINDOW *win;
  161.   int y;
  162.   int x;
  163.   {
  164.   wmove(win,y,x);
  165.   return(wgetch(win));
  166.   } /* mvwgetch */
  167.  
  168. /****************************************************************/
  169. /* rawgetch() gets a character without any interpretation at    */
  170. /* all and returns it. If keypad mode is active for the desig-    */
  171. /* nated window, function key translation will be performed.    */
  172. /* Otherwise, function keys are ignored.If nodelay mode is    */
  173. /* active in the window, then rawgetch() returns -1 if no cha-    */
  174. /* racter is available.                        */
  175. /****************************************************************/
  176.  
  177. static int rawgetch()
  178.   {
  179.   int c;
  180.  
  181.   if (w->_nodelay && !_curseskeytst())
  182.     return(-1);
  183.   while(1)                      /* loop to get valid char */
  184.     {
  185.     if ((c = validchar(_curseskey())) >= 0)
  186.       return(c);
  187.     } /* while */
  188.   } /* rawgetch */
  189.  
  190. /****************************************************************/
  191. /* Sysgetch() gets a character with normal ^S, ^Q, ^P and ^C    */
  192. /* interpretation and returns it. If keypad mode is active for    */
  193. /* the designated window, function key translation will be per-    */
  194. /* formed. Otherwise, function keys are ignored. If nodelay    */
  195. /* mode is active in the window, then sysgetch() returns -1 if    */
  196. /* no character is available.                    */
  197. /****************************************************************/
  198.  
  199. static int sysgetch()
  200.   {
  201.   int c;
  202.  
  203.   if (w->_nodelay && !kbhit())
  204.     return(-1);
  205.   while(1)
  206.     {
  207.     c = getch();
  208.     if (c)                    /* if not a function key */
  209.       return(c & 0xff);                /* avoids sign-extending */
  210.     c = getch();
  211.     if ((c = validchar(c << 8)) >= 0)        /* get & check next char */
  212.       return(c);
  213.     } /* while */
  214.   } /* sysgetch */
  215.  
  216. /****************************************************************/
  217. /* Validchar(c) chacks that 'c' is a valid character, and    */
  218. /* if so returns it, with function key translation applied if    */
  219. /* 'w' has keypad mode set. If char is invalid, returns -1.    */
  220. /****************************************************************/
  221.  
  222. static int validchar(c)
  223.   int    c;
  224.   {
  225.   int *scanp;
  226.  
  227.   if (c == 0x0300)            /* special case, ^@ = NULL */
  228.     return(0);
  229.   if (!(c & 0xff00))            /* normal character */
  230.     return(c);
  231.   if (!(w->_keypad))            /* skip f keys if not keypad mode */
  232.     return(-1);
  233.   c = (c >> 8) & 0xff;
  234.   scanp = kptab;
  235.   while(*scanp <= c)            /* search for value */
  236.     {                    /* (stops on table entry 0x100) */
  237.     if (*scanp++ == c)
  238.       return(*scanp);            /* found, return it */
  239.     scanp++;
  240.     }
  241.   return(-1);                /* not found, invalid */
  242.   } /* validchar */
  243.  
  244. /****************************************************************/
  245. /* _cursespendch() returns 1 if there is any character avai-    */
  246. /* lable, and 0 if there is none. This is not for programmer    */
  247. /* usage, but for the updatew routines.                */
  248. /****************************************************************/
  249.  
  250. bool    _cursespendch()
  251.   {
  252.   if (ungind)                /* ungotten char */
  253.     return(TRUE);
  254.   if (pindex > gindex)            /* buffered char */
  255.     return(TRUE);
  256.   if (_cursvar.raw)            /* raw mode test */
  257.     return(_curseskeytst());
  258.   return((bool)kbhit());        /* normal mode test */
  259.   } /* _cursespendch */
  260. 
  261.