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