home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1555 / io.c next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  14.2 KB  |  596 lines

  1. /*********************************************************************
  2. *
  3. *    io.c
  4. *        cross system inkey and screen calls for
  5. *        XENIX
  6. *        SYSV
  7. *        DOS
  8. *
  9. *        TERMINAL SETUP AND RESET
  10. *        tsetup()  :
  11. *        treset()  :
  12. *
  13. *        KEYBOARD SETUP AND RESET
  14. *        kbsetup() :
  15. *        kbreset() :
  16. *
  17. *        CHARACTER AND KEYSTROKE
  18. *        getch()   :
  19. *        inkey()   :
  20. *
  21. *        SCREEN CONTROL
  22. *        cls()     :
  23. *        eol()     :
  24. *        rev()     :
  25. *        norm()    :
  26. *
  27. *********************************************************************/
  28. /*LINTLIBRARY*/
  29. /*
  30. $Id: io.c,v 1.5 90/05/19 03:50:00 mark Exp Locker: mark $
  31. $Log:    io.c,v $
  32.  * Revision 1.5  90/05/19  03:50:00  mark
  33.  * *** empty log message ***
  34.  * 
  35.  * Revision 1.4  90/04/05  16:17:37  mark
  36.  * corrected for lint
  37.  * 
  38.  * Revision 1.3  90/02/10  12:42:24  mark
  39.  * *** empty log message ***
  40.  * 
  41.  * Revision 1.2  90/01/24  23:15:47  mark
  42.  * ioctl flag INLCR added to kbsetup()
  43.  * input key buffer tested each key read - fix Wyse50 arrow keys
  44.  * 
  45.  * Revision 1.1  90/01/23  16:32:33  mark
  46.  * Initial revision
  47.  * 
  48. */
  49.  
  50. /*********************************************************************
  51. *
  52. *    only one can be defined: XENIX_IO SYSV_IO DOS_IO
  53. *
  54. *********************************************************************/
  55. #ifdef XENIX_IO
  56. #undef SYSV_IO
  57. #undef DOS_IO
  58. #endif
  59.  
  60. #ifdef SYSV_IO
  61. #undef XENIX_IO
  62. #undef DOS_IO
  63. #endif
  64.  
  65. #ifdef DOS_IO
  66. #undef XENIX_IO
  67. #undef SYSV_IO
  68. #endif
  69.  
  70. #include "io.h"
  71.  
  72. #ifndef DOS_IO
  73. /*********************************************************************
  74. *
  75. *    include files -- io.h is local
  76. *
  77. *********************************************************************/
  78. #include <stdio.h>
  79. #include <string.h>
  80. #include <memory.h>
  81. /*#include <termio.h>*/
  82.  
  83. /*********************************************************************
  84. *
  85. *    extra include files and variable definition
  86. *    SYSV_IO uses alarm(), setjmp(), and lngjmp() system calls.
  87. *
  88. *********************************************************************/
  89. #ifdef SYSV_IO
  90. #include <setjmp.h>
  91. #include <signal.h>
  92. jmp_buf e_buff;
  93. char c_buff[5];
  94. #endif
  95.  
  96. /*********************************************************************
  97. *
  98. *    original terminal settings
  99. *
  100. *********************************************************************/
  101. static struct termio tsaved;
  102.  
  103. /*********************************************************************
  104. *
  105. *    character indexing buffers for function key mapping 
  106. *
  107. *********************************************************************/
  108. char key1[256];
  109. char key2[256];
  110.  
  111. /*********************************************************************
  112. *
  113. *    structures containing terminal and keyboard definitions 
  114. *
  115. *********************************************************************/
  116. struct crt_stru crt;
  117. struct fkey_stru spec;
  118.  
  119. /*********************************************************************
  120. *
  121. *    function prototypes 
  122. *
  123. *********************************************************************/
  124. int ioctl();
  125. int read();
  126. char *getenv();
  127.  
  128.  
  129. /*********************************************************************
  130. *
  131. *    tsetup
  132. *        prepares the terminal for absolute cursor positioning 
  133. *        retrieves and saves the current terminals keyboard definition
  134. *        sets the keyboard in character break mode
  135. *
  136. *********************************************************************/
  137. tsetup()
  138. {
  139.     tinit();
  140.     fillkeys();
  141.     kbsetup();
  142.     cps(crt.init); 
  143.     (void)fflush(stdout);
  144. }
  145.  
  146. /*********************************************************************
  147. *
  148. *    treset
  149. *        resets the terminal to the state in which it was found
  150. *
  151. *********************************************************************/
  152. treset()
  153. {
  154.     cps(crt.close); 
  155.     kbreset();
  156.     tflush();
  157. }
  158.  
  159. /*********************************************************************
  160. *
  161. *    kbsetup
  162. *        sets the keyboard in character break mode
  163. *
  164. *********************************************************************/
  165. int kbsetup()
  166. {
  167.     struct termio tnew;
  168.     int echo = 0; /* 0 == no echo | 1 == echo */
  169.  
  170.     (void)ioctl(0, TCGETA, &tsaved);
  171.     tnew = tsaved;
  172.  
  173.     tnew.c_iflag &= INLCR;
  174.  
  175.     tnew.c_lflag &= ~ICANON;
  176.     tnew.c_lflag &= ~ISIG;
  177.     if(echo == 0)
  178.         tnew.c_lflag &= ~ECHO;
  179.     else
  180.         tnew.c_lflag &= ECHO;
  181.     tnew.c_cc[VMIN] = 1;
  182.     tnew.c_cc[VTIME] = 0;
  183.     (void)ioctl(0, TCSETA, &tnew);
  184. }
  185.  
  186. /*********************************************************************
  187. *
  188. *    kbreset
  189. *        resets the keyboard to the state in which it was found
  190. *
  191. *********************************************************************/
  192. int kbreset()
  193. {
  194.     (void)ioctl(0, TCSETA, &tsaved);
  195. }
  196.  
  197. /*********************************************************************
  198. *
  199. *    getch
  200. *        character by character input function - cbreak mode
  201. *
  202. *********************************************************************/
  203. int getch()
  204. {
  205.     char buf;
  206.  
  207.     (void)read(0, &buf, 1);
  208.     if(buf == tsaved.c_cc[VEOF])
  209.         return(EOF);
  210.     return(buf);
  211. }
  212.  
  213. /*********************************************************************
  214. *
  215. *    flush the standard output file
  216. *
  217. *********************************************************************/
  218. refresh()    { (void)fflush(stdout);    }
  219. tflush()        { (void)fflush(stdout);    }
  220.  
  221. /*********************************************************************
  222. *
  223. *    position the cursor
  224. *
  225. *********************************************************************/
  226. cup(row,col)
  227. int row, col;
  228. {
  229.     cps((char *)(tgoto(crt.dca,col,row)));
  230. }
  231.  
  232. /*********************************************************************
  233. *
  234. *    clear the screen
  235. *
  236. *********************************************************************/
  237. cls()        { cps(crt.cls); cup(0,0); }
  238.  
  239. /*********************************************************************
  240. *
  241. *    clear to end of line
  242. *
  243. *********************************************************************/
  244. eol()        { cps(crt.eol);    }
  245. clreol()    { cps(crt.eol);    }
  246.  
  247. /*********************************************************************
  248. *
  249. *    set reverse video
  250. *
  251. *********************************************************************/
  252. rev()        { cps(crt.rev);    }
  253. revvid()    { cps(crt.rev);    }
  254.  
  255. /*********************************************************************
  256. *
  257. *    set normal video
  258. *
  259. *********************************************************************/
  260. norm()    { cps(crt.norm);    }
  261. normvid(){ cps(crt.norm);    }
  262.  
  263. /*********************************************************************
  264. *
  265. *    output a string to the crt
  266. *
  267. *********************************************************************/
  268. cps(str)
  269. char *str;
  270. {
  271.    char *tptr;  tptr = str;
  272.    while(*tptr) (void)putc(*(tptr++),stdout);
  273.     tflush();
  274. }
  275.  
  276. /*********************************************************************
  277. *
  278. *    general purpose XENIX SYSV terminal setup routines
  279. *    based on termcap database
  280. *
  281. *********************************************************************/
  282. /*********************************************************************
  283. *
  284. *    compare checks the contents on the buffer kbuff
  285. *              against the structure spec for special key 
  286. *              definitions. when a match is made a negative value
  287. *              is returned, otherwise zero is returned.
  288. *
  289. *********************************************************************/
  290. int compare(kbuff)
  291. char *kbuff;
  292. {
  293.     if(!strcmp(kbuff,spec.up))                    { return(-101);
  294.     } else if(!strcmp(kbuff,spec.down))        { return(-102);
  295.     } else if(!strcmp(kbuff,spec.left))        { return(-103);
  296.     } else if(!strcmp(kbuff,spec.right))    { return(-104);
  297.     } else if(!strcmp(kbuff,spec.pu))        { return(-105);
  298.     } else if(!strcmp(kbuff,spec.pd))        { return(-106);
  299.     } else if(!strcmp(kbuff,spec.f1))        { return(-1);
  300.     } else if(!strcmp(kbuff,spec.f2))        { return(-2);
  301.     } else if(!strcmp(kbuff,spec.f3))        { return(-3);
  302.     } else if(!strcmp(kbuff,spec.f4))        { return(-4);
  303.     } else if(!strcmp(kbuff,spec.f5))        { return(-5);
  304.     } else if(!strcmp(kbuff,spec.f6))         { return(-6);
  305.     } else if(!strcmp(kbuff,spec.f7))        { return(-7);
  306.     } else if(!strcmp(kbuff,spec.f8))        { return(-8);
  307.     } else if(!strcmp(kbuff,spec.f9))        { return(-9);
  308.     } else if(!strcmp(kbuff,spec.f10))        { return(-10);
  309.     } return(0);
  310. }
  311.  
  312. /*********************************************************************
  313. *
  314. *    tinit
  315. *        reads and parses the termcap entry pointed to by the
  316. *        TERM environment variable
  317. *
  318. *********************************************************************/
  319. tinit()
  320. {
  321.     char *cptr;
  322.     char *tptr;
  323.     char buff[1024];
  324.  
  325.     if((tptr = getenv("TERM")) == NULL) {
  326.         (void)printf("Error initilizing terminal. Exiting ...\n");
  327.         (void)exit(1);
  328.     }
  329.     tgetent(buff,tptr);
  330.  
  331.     /* terminal attribute initialization */
  332.     cptr = crt.dca;    tgetstr("cm",&cptr); 
  333.     cptr = crt.cls;    tgetstr("cl",&cptr);
  334.     cptr = crt.rev;    tgetstr("so",&cptr); 
  335.     cptr = crt.norm;    tgetstr("se",&cptr);
  336.     cptr = crt.eol;    tgetstr("ce",&cptr);
  337.     cptr = crt.init;    tgetstr("ti",&cptr);
  338.     cptr = crt.close;    tgetstr("te",&cptr);
  339.     cptr = crt.uss;    tgetstr("us",&cptr);
  340.     cptr = crt.use;    tgetstr("ue",&cptr);
  341.  
  342.     /* terminal special key initialization */
  343.     cptr = spec.up;        tgetstr("ku",&cptr);
  344.     cptr = spec.down;        tgetstr("kd",&cptr);
  345.     cptr = spec.left;        tgetstr("kl",&cptr);
  346.     cptr = spec.right;    tgetstr("kr",&cptr);
  347.     cptr = spec.pu;        tgetstr("pu",&cptr);
  348.     cptr = spec.pd;        tgetstr("pd",&cptr);
  349.  
  350.     /* function key initialization */
  351.     cptr = spec.f1;        tgetstr("k1",&cptr);
  352.     cptr = spec.f2;        tgetstr("k2",&cptr);
  353.     cptr = spec.f3;        tgetstr("k3",&cptr);
  354.     cptr = spec.f4;        tgetstr("k4",&cptr);
  355.     cptr = spec.f5;         tgetstr("k5",&cptr);
  356.     cptr = spec.f6;        tgetstr("k6",&cptr);
  357.     cptr = spec.f7;        tgetstr("k7",&cptr);
  358.     cptr = spec.f8;        tgetstr("k8",&cptr);
  359.     cptr = spec.f9;        tgetstr("k9",&cptr);
  360.     cptr = spec.f10;        tgetstr("k0",&cptr);
  361.  
  362.     /* miscellaneous integral values */
  363.     crt.co = tgetnum("co");
  364.     crt.li = tgetnum("li");
  365.     crt.sg = tgetnum("sg");
  366.     crt.ug = tgetnum("ug");
  367.     crt.gg = tgetnum("gg");
  368. }
  369.  
  370. /*********************************************************************
  371. *
  372. *    fillkeys reads the zero'th postion of the members in structure spec 
  373. *        to be used in the masking of special characters
  374. *
  375. *********************************************************************/
  376. fillkeys()
  377. {    
  378.     memset(key1,0,sizeof(key1));
  379.     memset(key2,0,sizeof(key2));
  380.  
  381.     key1[spec.up[0]] = 1;        key2[spec.up[1]] = 1;
  382.     key1[spec.down[0]] = 1;        key2[spec.down[1]] = 1;
  383.     key1[spec.left[0]] = 1;        key2[spec.left[1]] = 1;
  384.     key1[spec.right[0]] = 1;    key2[spec.right[1]] = 1;
  385.     key1[spec.pu[0]] = 1;        key2[spec.pu[1]] = 1;
  386.     key1[spec.pd[0]] = 1;        key2[spec.pd[1]] = 1;
  387.  
  388.     key1[spec.f1[0]] = 1;        key2[spec.f1[1]] = 1;
  389.     key1[spec.f2[0]] = 1;        key2[spec.f2[1]] = 1;
  390.     key1[spec.f3[0]] = 1;        key2[spec.f3[1]] = 1;
  391.     key1[spec.f4[0]] = 1;        key2[spec.f4[1]] = 1;
  392.     key1[spec.f5[0]] = 1;        key2[spec.f5[1]] = 1;
  393.     key1[spec.f6[0]] = 1;        key2[spec.f6[1]] = 1;
  394.     key1[spec.f7[0]] = 1;        key2[spec.f7[1]] = 1;
  395.     key1[spec.f8[0]] = 1;        key2[spec.f8[1]] = 1;
  396.     key1[spec.f9[0]] = 1;        key2[spec.f9[1]] = 1;
  397.     key1[spec.f10[0]] = 1;        key2[spec.f10[1]] = 1;
  398. }
  399.  
  400.  
  401. /*********************************************************************
  402. *
  403. *    Inkey routines -- these tend to be non standard from system 
  404. *    to system. Each method has advantages and disadvantages.
  405. *
  406. *    XENIX_IO uses rdchk() and nap()
  407. *    SYSV_IO  uses alarm(), setjmp(), and lngjmp()
  408. *
  409. *********************************************************************/
  410.  
  411. #ifdef XENIX_IO
  412. /*********************************************************************
  413. *
  414. *    XENIX_IO inkey
  415. *        if > 0 return ascii code of character
  416. *        if < 0 return number cooresponding to function key map
  417. *
  418. *********************************************************************/
  419. inkey()
  420. {
  421.     char tbuf[10];
  422.     int cnt = 0, ret;
  423.  
  424.     /* first char ! */ 
  425.     tbuf[cnt] = (char)getch(); tbuf[++cnt] = '\0';
  426.     if((ret = compare(tbuf)) < 0) { return(ret); }
  427.  
  428.     /* possible second char ?  (i.e. [Escape] */ 
  429.     if(!key1[tbuf[cnt-1]]) { return(tbuf[cnt-1]); }
  430.     nap((long)PERIOD);
  431.     if(!rdchk(0)) { return(tbuf[cnt-1]); }
  432.  
  433.     /* second char  !!! */
  434.     tbuf[cnt] = (char)getch(); tbuf[++cnt] = '\0';
  435.     if((ret = compare(tbuf)) < 0) { return(ret); }
  436.     if(!key2[tbuf[cnt-1]]) { return(0); }
  437.  
  438.     /* third char ! */
  439.     if(rdchk(0)) { tbuf[cnt] = (char)getch(); tbuf[++cnt] = '\0'; }
  440.     return(compare(tbuf));
  441. }
  442.  
  443. #endif
  444.  
  445. #ifdef SYSV_IO
  446. /*********************************************************************
  447. *
  448. *    timeout
  449. *        Called by  signal  when an alarm is set. Used to exit
  450. *        the last call to  getchar  when no characters arrive within
  451. *        one second.
  452. *
  453. *********************************************************************/
  454. int timeout()
  455. {
  456.     longjmp(e_buff,1);
  457. }
  458.  
  459. /*********************************************************************
  460. *
  461. *    SYSV_IO inkey
  462. *        if > 0 return ascii code of character
  463. *        if < 0 return number cooresponding to function key map
  464. *
  465. *********************************************************************/
  466. int inkey()
  467. {
  468.     int go = 1, keycnt = 0, maxkey = 3;
  469.  
  470.     memset(c_buff,(int)'\0',5);
  471.     setjmp(e_buff);
  472.  
  473.     if(go) {
  474.         go = 0;
  475.         signal(SIGALRM,timeout);
  476.         c_buff[keycnt] = getchar();
  477.         if(!key1[c_buff[keycnt++]]) {
  478.             keycnt = maxkey;
  479.         }
  480.  
  481.         while(keycnt < maxkey) {
  482.             if(compare(c_buff) < 0) {
  483.                 longjmp(e_buff,1);
  484.             }
  485.             alarm((unsigned) PERIOD);
  486.             c_buff[keycnt++] = getchar(); 
  487.             c_buff[keycnt] = '\0';
  488.             alarm((unsigned) 0);
  489.         }
  490.     }
  491.  
  492.     if(strlen(c_buff) == 1) { return(c_buff[0]); }
  493.     return(compare(c_buff));
  494. }
  495. #endif
  496. #endif
  497.  
  498. #ifdef DOS_IO
  499. #include <dos.h>
  500.  
  501. tsetup()  { ; }
  502. treset()  { ; }
  503. kbsetup() { ; }
  504. kbreset() { ; }
  505. tflush()  { ; }
  506.  
  507. inkey() {
  508.     int ch;
  509.     ch = getch();
  510.     if(ch != 0) {
  511.         return(ch);
  512.     } else {
  513.         ch = getch();
  514.         switch(ch) {
  515.             case 59 : ch = -1; break; /* F1 */
  516.             case 60 : ch = -2; break; /* F2 */
  517.             case 61 : ch = -3; break; /* F3 */
  518.             case 62 : ch = -4; break; /* F4 */
  519.             case 63 : ch = -5; break; /* F5 */
  520.             case 64 : ch = -6; break; /* F6 */
  521.             case 65 : ch = -7; break; /* F7 */
  522.             case 66 : ch = -8; break; /* F8 */
  523.             case 67 : ch = -9; break; /* F9 */
  524.             case 68 : ch = -10; break; /* F10 */
  525.             case 72 : ch = -101; break; /* UP */
  526.             case 80 : ch = -102; break; /* DOWN */
  527.             case 75 : ch = -103; break; /* LEFT */
  528.             case 77 : ch = -104; break; /* RIGHT */
  529.             case 73 : ch = -105; break; /* PGUP */
  530.             case 81 : ch = -106; break; /* PGDOWN */
  531.             default : ch = 0;
  532.         }
  533.         return(ch);
  534.     }
  535. }
  536.  
  537. /* sets reverse video */
  538. void rev()
  539. {
  540.    (void)printf("\x1b[7m");
  541. }
  542.  
  543. void revvid()
  544. {
  545.    (void)printf("\x1b[7m");
  546. }
  547.  
  548.  
  549. /* sets low video */
  550. void norm()
  551. {
  552.    (void)printf("\x1b[0m");
  553. }
  554.  
  555. void normvid()
  556. {
  557.    (void)printf("\x1b[0m");
  558. }
  559.  
  560. /* clear to the end of current line */
  561. void eol()
  562. {
  563.    (void)printf("\x1b[0K");
  564. }
  565.  
  566. void clreol()
  567. {
  568.    (void)printf("\x1b[0K");
  569. }
  570.  
  571.  
  572. /* clear terminal screen */
  573. void cls()
  574. {
  575.    (void)printf("\x1b[2J");
  576. }
  577.  
  578.  
  579. /* position cursor on terminal */
  580. void cup(row,col)
  581. int row, col;
  582. {
  583.    (void)printf("\x1b[%d;%dH",row,col);
  584. }
  585.  
  586. void un_on()
  587. {
  588.    (void)printf("\x1b[4m");
  589. }
  590.  
  591. void un_off()
  592. {
  593.    (void)printf("\x1b[0m");
  594. }
  595. #endif
  596.