home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / proglc / uem_mods.lzh / TERMIO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-12-19  |  13.3 KB  |  498 lines

  1. /*
  2.  * The functions in this file negotiate with the operating system for
  3.  * characters, and write characters in a barely buffered fashion on the display.
  4.  * All operating systems.
  5.  */
  6. #include        <stdio.h>
  7. #include    "estruct.h"
  8. #include        "edef.h"
  9.  
  10. #if   MSDOS & TURBO
  11. #include <conio.h>
  12. #endif
  13.  
  14. #if     AMIGA
  15. #define NEW 1006L
  16. #define AMG_MAXBUF      1024L
  17. static long terminal;
  18. static char     scrn_tmp[AMG_MAXBUF+1];
  19. static long     scrn_tmp_p = 0;
  20. #endif
  21.  
  22. #if     VMS
  23. #include        <stsdef.h>
  24. #include        <ssdef.h>
  25. #include        <descrip.h>
  26. #include        <iodef.h>
  27. #include        <ttdef.h>
  28. #include    <tt2def.h>
  29.  
  30. #define NIBUF   128                     /* Input buffer size            */
  31. #define NOBUF   1024                    /* MM says bug buffers win!     */
  32. #define EFN     0                       /* Event flag                   */
  33.  
  34. char    obuf[NOBUF];                    /* Output buffer                */
  35. int     nobuf;                  /* # of bytes in above    */
  36. char    ibuf[NIBUF];                    /* Input buffer          */
  37. int     nibuf;                  /* # of bytes in above  */
  38. int     ibufi;                  /* Read index                   */
  39. int     oldmode[3];                     /* Old TTY mode bits            */
  40. int     newmode[3];                     /* New TTY mode bits            */
  41. short   iochan;                  /* TTY I/O channel             */
  42. #endif
  43.  
  44. #if     CPM
  45. #include        <bdos.h>
  46. #endif
  47.  
  48. #if     MSDOS & (LATTICE | MSC | TURBO | AZTEC | MWC86)
  49. union REGS rg;        /* cpu register for use of DOS calls */
  50. int nxtchar = -1;    /* character held from type ahead    */
  51. #endif
  52.  
  53. #if RAINBOW
  54. #include "rainbow.h"
  55. #endif
  56.  
  57. #if    USG            /* System V */
  58. #include    <signal.h>
  59. #include    <termio.h>
  60. #include    <fcntl.h>
  61. int kbdflgs;            /* saved keyboard fd flags    */
  62. int kbdpoll;            /* in O_NDELAY mode            */
  63. int kbdqp;            /* there is a char in kbdq    */
  64. char kbdq;            /* char we've already read    */
  65. struct    termio    otermio;    /* original terminal characteristics */
  66. struct    termio    ntermio;    /* charactoristics to use inside */
  67. #endif
  68.  
  69. #if V7 | BSD
  70. #undef    CTRL
  71. #include        <sgtty.h>        /* for stty/gtty functions */
  72. #include    <signal.h>
  73. struct  sgttyb  ostate;          /* saved tty state */
  74. struct  sgttyb  nstate;          /* values for editor mode */
  75. struct tchars    otchars;    /* Saved terminal special character set */
  76. struct tchars    ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  77.                 /* A lot of nothing */
  78. #if BSD
  79. #include <sys/ioctl.h>        /* to get at the typeahead */
  80. extern    int rtfrmshell();    /* return from suspended shell */
  81. #define    TBUFSIZ    128
  82. char tobuf[TBUFSIZ];        /* terminal output buffer */
  83. #endif
  84. #endif
  85.  
  86. /*
  87.  * This function is called once to set up the terminal device streams.
  88.  * On VMS, it translates TT until it finds the terminal, then assigns
  89.  * a channel to it and sets it raw. On CPM it is a no-op.
  90.  */
  91. ttopen()
  92. {
  93. #if     AMIGA
  94.     char oline[NSTRING];
  95. #if    AZTEC
  96.     extern    Enable_Abort;    /* Turn off ctrl-C interrupt */
  97.  
  98.     Enable_Abort = 0;    /* for the Manx compiler */
  99. #endif
  100.     strcpy(oline, "RAW:0/0/640/200/");
  101.     strcat(oline, PROGNAME);
  102.     strcat(oline, " ");
  103.     strcat(oline, VERSION);
  104.     strcat(oline, "/Amiga");
  105.         terminal = Open(oline, NEW);
  106. #endif
  107. #if     VMS
  108.         struct  dsc$descriptor  idsc;
  109.         struct  dsc$descriptor  odsc;
  110.         char    oname[40];
  111.         int     iosb[2];
  112.         int     status;
  113.  
  114.         odsc.dsc$a_pointer = "TT";
  115.         odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
  116.         odsc.dsc$b_dtype        = DSC$K_DTYPE_T;
  117.         odsc.dsc$b_class        = DSC$K_CLASS_S;
  118.         idsc.dsc$b_dtype        = DSC$K_DTYPE_T;
  119.         idsc.dsc$b_class        = DSC$K_CLASS_S;
  120.         do {
  121.                 idsc.dsc$a_pointer = odsc.dsc$a_pointer;
  122.                 idsc.dsc$w_length  = odsc.dsc$w_length;
  123.                 odsc.dsc$a_pointer = &oname[0];
  124.                 odsc.dsc$w_length  = sizeof(oname);
  125.                 status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
  126.                 if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
  127.                         exit(status);
  128.                 if (oname[0] == 0x1B) {
  129.                         odsc.dsc$a_pointer += 4;
  130.                         odsc.dsc$w_length  -= 4;
  131.                 }
  132.         } while (status == SS$_NORMAL);
  133.         status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
  134.         if (status != SS$_NORMAL)
  135.                 exit(status);
  136.         status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
  137.                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
  138.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  139.                 exit(status);
  140.         newmode[0] = oldmode[0];
  141.         newmode[1] = oldmode[1] | TT$M_NOECHO;
  142.         newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
  143.         newmode[2] = oldmode[2] | TT2$M_PASTHRU;
  144.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  145.                           newmode, sizeof(newmode), 0, 0, 0, 0);
  146.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  147.                 exit(status);
  148.         term.t_nrow = (newmode[1]>>24) - 1;
  149.         term.t_ncol = newmode[0]>>16;
  150.  
  151. #endif
  152. #if     CPM
  153. #endif
  154.  
  155. #if     MSDOS & (HP150 == 0) & LATTICE
  156.     /* kill the ctrl-break interupt */
  157.     rg.h.ah = 0x33;        /* control-break check dos call */
  158.     rg.h.al = 1;        /* set the current state */
  159.     rg.h.dl = 0;        /* set it OFF */
  160.     intdos(&rg, &rg);    /* go for it! */
  161. #endif
  162.  
  163. #if    USG
  164.     ioctl(0, TCGETA, &otermio);    /* save old settings */
  165.     ntermio.c_iflag = 0;        /* setup new settings */
  166.     ntermio.c_oflag = 0;
  167.     ntermio.c_cflag = otermio.c_cflag;
  168.     ntermio.c_lflag = 0;
  169.     ntermio.c_line = otermio.c_line;
  170.     ntermio.c_cc[VMIN] = 1;
  171.     ntermio.c_cc[VTIME] = 0;
  172.     ioctl(0, TCSETA, &ntermio);    /* and activate them */
  173.     kbdflgs = fcntl( 0, F_GETFL, 0 );
  174.     kbdpoll = FALSE;
  175. #endif
  176.  
  177. #if     V7 | BSD
  178.         gtty(0, &ostate);                       /* save old state */
  179.         gtty(0, &nstate);                       /* get base of new state */
  180.         nstate.sg_flags |= RAW;
  181.         nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
  182.         stty(0, &nstate);                       /* set mode */
  183.     ioctl(0, TIOCGETC, &otchars);        /* Save old characters */
  184.     ioctl(0, TIOCSETC, &ntchars);        /* Place new character into K */
  185. #if    BSD
  186.     /* provide a smaller terminal output buffer so that
  187.        the type ahead detection works better (more often) */
  188.     setbuffer(stdout, &tobuf[0], TBUFSIZ);
  189.     signal(SIGTSTP,SIG_DFL);    /* set signals so that we can */
  190.     signal(SIGCONT,rtfrmshell);    /* suspend & restart emacs */
  191. #endif
  192. #endif
  193.     /* on all screens we are not sure of the initial position
  194.        of the cursor                    */
  195.     ttrow = 999;
  196.     ttcol = 999;
  197. }
  198.  
  199. /*
  200.  * This function gets called just before we go back home to the command
  201.  * interpreter. On VMS it puts the terminal back in a reasonable state.
  202.  * Another no-operation on CPM.
  203.  */
  204. ttclose()
  205. {
  206. #if     AMIGA
  207. #if    LATTICE
  208.         amg_flush();
  209.         Close(terminal);
  210. #endif
  211. #if    AZTEC
  212.         amg_flush();
  213.     Enable_Abort = 1;    /* Fix for Manx */
  214.         Close(terminal);
  215. #endif
  216. #endif
  217.  
  218. #if     VMS
  219.         int     status;
  220.         int     iosb[1];
  221.  
  222.         ttflush();
  223.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  224.                  oldmode, sizeof(oldmode), 0, 0, 0, 0);
  225.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  226.                 exit(status);
  227.         status = SYS$DASSGN(iochan);
  228.         if (status != SS$_NORMAL)
  229.                 exit(status);
  230. #endif
  231. #if     CPM
  232. #endif
  233. #if     MSDOS & (HP150 == 0) & LATTICE
  234.     /* restore the ctrl-break interupt */
  235.     rg.h.ah = 0x33;        /* control-break check dos call */
  236.     rg.h.al = 1;        /* set the current state */
  237.     rg.h.dl = 1;        /* set it ON */
  238.     intdos(&rg, &rg);    /* go for it! */
  239. #endif
  240.  
  241. #if    USG
  242.     ioctl(0, TCSETA, &otermio);    /* restore terminal settings */
  243.     fcntl(0, F_SETFL, kbdflgs);
  244. #endif
  245.  
  246. #if     V7 | BSD
  247.         stty(0, &ostate);
  248.     ioctl(0, TIOCSETC, &otchars);    /* Place old character into K */
  249. #endif
  250. }
  251.  
  252. /*
  253.  * Write a character to the display. On VMS, terminal output is buffered, and
  254.  * we just put the characters in the big array, after checking for overflow.
  255.  * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
  256.  * MS-DOS (use the very very raw console output routine).
  257.  */
  258. ttputc(c)
  259. #if     AMIGA
  260.         char c;
  261. #endif
  262. {
  263. #if     AMIGA
  264.         scrn_tmp[scrn_tmp_p++] = c;
  265.         if(scrn_tmp_p>=AMG_MAXBUF)
  266.                 amg_flush();
  267. #endif
  268. #if     VMS
  269.         if (nobuf >= NOBUF)
  270.                 ttflush();
  271.         obuf[nobuf++] = c;
  272. #endif
  273.  
  274. #if     CPM
  275.         bios(BCONOUT, c, 0);
  276. #endif
  277.  
  278. #if     MSDOS & MWC86
  279.         putcnb(c);
  280. #endif
  281.  
  282. #if    MSDOS & (LATTICE | AZTEC) & ~IBMPC
  283.     bdos(6, c, 0);
  284. #endif
  285.  
  286. #if RAINBOW
  287.         Put_Char(c);                    /* fast video */
  288. #endif
  289.  
  290.  
  291. #if     V7 | USG | BSD
  292.         fputc(c, stdout);
  293. #endif
  294. }
  295.  
  296. #if    AMIGA
  297. amg_flush()
  298. {
  299.         if(scrn_tmp_p)
  300.                 Write(terminal,scrn_tmp,scrn_tmp_p);
  301.         scrn_tmp_p = 0;
  302. }
  303. #endif
  304.  
  305. /*
  306.  * Flush terminal buffer. Does real work where the terminal output is buffered
  307.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  308.  */
  309. ttflush()
  310. {
  311. #if     AMIGA
  312.         amg_flush();
  313. #endif
  314. #if     VMS
  315.         int     status;
  316.         int     iosb[2];
  317.  
  318.         status = SS$_NORMAL;
  319.         if (nobuf != 0) {
  320.                 status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
  321.                          iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
  322.                 if (status == SS$_NORMAL)
  323.                         status = iosb[0] & 0xFFFF;
  324.                 nobuf = 0;
  325.         }
  326.         return (status);
  327. #endif
  328.  
  329. #if     CPM
  330. #endif
  331.  
  332. #if     MSDOS
  333. #endif
  334.  
  335. #if     V7 | USG | BSD
  336.         fflush(stdout);
  337. #endif
  338. }
  339.  
  340. /*
  341.  * Read a character from the terminal, performing no editing and doing no echo
  342.  * at all. More complex in VMS that almost anyplace else, which figures. Very
  343.  * simple on CPM, because the system can do exactly what you want.
  344.  */
  345. ttgetc()
  346. {
  347. #if     AMIGA
  348.         char ch;
  349.         amg_flush();
  350.         Read(terminal, &ch, 1L);
  351.         return(255 & (int)ch);
  352. #endif
  353. #if     VMS
  354.         int     status;
  355.         int     iosb[2];
  356.         int     term[2];
  357.  
  358.         while (ibufi >= nibuf) {
  359.                 ibufi = 0;
  360.                 term[0] = 0;
  361.                 term[1] = 0;
  362.                 status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
  363.                          iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
  364.                 if (status != SS$_NORMAL)
  365.                         exit(status);
  366.                 status = iosb[0] & 0xFFFF;
  367.                 if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
  368.                         exit(status);
  369.                 nibuf = (iosb[0]>>16) + (iosb[1]>>16);
  370.                 if (nibuf == 0) {
  371.                         status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
  372.                                  iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
  373.                         if (status != SS$_NORMAL
  374.                         || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
  375.                                 exit(status);
  376.                         nibuf = (iosb[0]>>16) + (iosb[1]>>16);
  377.                 }
  378.         }
  379.         return (ibuf[ibufi++] & 0xFF);    /* Allow multinational  */
  380. #endif
  381.  
  382. #if     CPM
  383.         return (biosb(BCONIN, 0, 0));
  384. #endif
  385.  
  386. #if RAINBOW
  387.         int Ch;
  388.  
  389.         while ((Ch = Read_Keyboard()) < 0);
  390.  
  391.         if ((Ch & Function_Key) == 0)
  392.                 if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
  393.                         Ch &= 0xFF;
  394.  
  395.         return Ch;
  396. #endif
  397.  
  398. #if     MSDOS & MWC86
  399.         return (getcnb());
  400. #endif
  401.  
  402. #if    MSDOS & (LATTICE | MSC | TURBO | AZTEC)
  403.     int c;        /* character read */
  404.  
  405.     /* if a char already is ready, return it */
  406.     if (nxtchar >= 0) {
  407.         c = nxtchar;
  408.         nxtchar = -1;
  409.         return(c);
  410.     }
  411.  
  412.     /* call the dos to get a char */
  413.     rg.h.ah = 7;        /* dos Direct Console Input call */
  414.     intdos(&rg, &rg);
  415.     c = rg.h.al;        /* grab the char */
  416.     return(c & 255);
  417. #endif
  418.  
  419. #if     V7 | BSD
  420.         return(127 & fgetc(stdin));
  421. #endif
  422.  
  423. #if    USG
  424.     if( kbdqp )
  425.         kbdqp = FALSE;
  426.     else
  427.     {
  428.         if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
  429.             return FALSE;
  430.         kbdpoll = FALSE;
  431.         while (read(0, &kbdq, 1) != 1)
  432.             ;
  433.     }
  434.     return ( kbdq & 127 );
  435. #endif
  436. }
  437.  
  438. #if    TYPEAH & (~ST520)
  439. /* typahead:    Check to see if any characters are already in the
  440.         keyboard buffer
  441. */
  442.  
  443. typahead()
  444.  
  445. {
  446. #if    MSDOS & (MSC | TURBO)
  447.     if (kbhit() != 0)
  448.         return(TRUE);
  449.     else
  450.         return(FALSE);
  451. #endif
  452.  
  453. #if    MSDOS & (LATTICE | AZTEC | MWC86)
  454.     int c;        /* character read */
  455.     int flags;    /* cpu flags from dos call */
  456.  
  457.     if (nxtchar >= 0)
  458.         return(TRUE);
  459.  
  460.     rg.h.ah = 6;    /* Direct Console I/O call */
  461.     rg.h.dl = 255;    /*         does console input */
  462. #if    LATTICE | AZTEC
  463.     flags = intdos(&rg, &rg);
  464. #else
  465.     intcall(&rg, &rg, 0x21);
  466.     flags = rg.x.flags;
  467. #endif
  468.     c = rg.h.al;    /* grab the character */
  469.  
  470.     /* no character pending */
  471.     if ((flags & 64) != 0)
  472.         return(FALSE);
  473.  
  474.     /* save the character and return true */
  475.     nxtchar = c;
  476.     return(TRUE);
  477. #endif
  478.  
  479. #if    BSD
  480.     int x;    /* holds # of pending chars */
  481.  
  482.     return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
  483. #endif
  484.  
  485. #if    USG
  486.     if( !kbdqp )
  487.     {
  488.         if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
  489.             return(FALSE);
  490.         kbdqp = (1 == read( 0, &kbdq, 1 ));
  491.     }
  492.     return ( kbdqp );
  493. #endif
  494.     return(FALSE);
  495. }
  496. #endif
  497.  
  498.