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