home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 001-099 / ff093.lzh / MicroEmacs / source / src.arc / termio.c < prev    next >
C/C++ Source or Header  |  1987-08-16  |  17KB  |  624 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    MEGAMAX & ST520
  11. overlay    "termio"
  12. #endif
  13.  
  14. #if     AMIGA
  15. #undef TRUE
  16. #undef FALSE
  17. #include <exec/types.h>
  18. #include <exec/nodes.h>
  19. #include <exec/lists.h>
  20. #include <exec/tasks.h>
  21. #include <exec/ports.h>
  22. #include <exec/io.h>
  23. #include <devices/console.h>
  24. #include <devices/conunit.h>
  25. #include <libraries/dos.h>
  26. #include <libraries/dosextens.h>
  27. #include <graphics/clip.h>
  28. #include <graphics/view.h>
  29. #include <graphics/rastport.h>
  30. #include <graphics/layers.h>
  31. #include <graphics/text.h>
  32. #include <intuition/intuition.h>
  33.  
  34. #define    CSI                0x9b
  35. #define AMG_MAXBUF            4608L       /* worst case size  */
  36.  
  37. extern    struct    IntuitionBase   *IntuitionBase;     /* library bases    */
  38. extern    struct  GfxBase            *GfxBase;   
  39. extern    struct    Window        *EmacsWindow;        /* Our window       */
  40. extern    struct    MsgPort        *consoleport;        /* I/O port        */
  41. extern    struct    IOStdReq    *consoleWriteMsg;   /* I/O messages    */
  42. extern    struct    IOStdReq    *consoleReadMsg;
  43. extern  struct  Window          *savewindow;
  44.  
  45. extern  char    *itoa();                            /* we decide the    */
  46. extern     LONG    newsize();                          /* the screen size  */
  47. extern    LONG    newwidth();                         /* a startup        */
  48. extern  VOID    CursorOn(),                         /* these guys help  */
  49.                 CursorOff();                        /* speed up screen  */
  50.                                                     /* writes           */
  51.  
  52. extern    VOID            *OpenLibrary();
  53. extern    LONG            OpenConsole();
  54. extern  struct  Task            *FindTask();
  55. extern    struct    Window        *InitWindow();
  56. extern    struct    MsgPort        *CreatePort();
  57. extern    struct    IOStdReq    *CreateStdIO();
  58. extern  UWORD                   getrows();          /* determine number  */
  59. extern  UWORD                   getcols();          /* of rows and cols  */
  60.                                                     /* available         */
  61.  
  62. extern    LONG            Enable_Abort;    /* Do NOT allow abort!    */
  63. extern  VOID            cleanup();
  64.  
  65. /*
  66.    storage for pernament real estate...
  67. */
  68.    
  69. static    char            scrtitle[81];  
  70. static  char            scrn_tmp[AMG_MAXBUF+1];
  71. static  LONG            scrn_tmp_p = 0L;
  72.  
  73. #endif
  74.  
  75. #if ST520
  76. #include <osbind.h>
  77.     int STscancode = 0;    
  78. #endif
  79.  
  80. #if     VMS
  81. #include        <stsdef.h>
  82. #include        <ssdef.h>
  83. #include        <descrip.h>
  84. #include        <iodef.h>
  85. #include        <ttdef.h>
  86. #include    <tt2def.h>
  87.  
  88. #define NIBUF   128                     /* Input buffer size            */
  89. #define NOBUF   1024                    /* MM says bug buffers win!     */
  90. #define EFN     0                       /* Event flag                   */
  91.  
  92. char    obuf[NOBUF];                    /* Output buffer                */
  93. int     nobuf;                  /* # of bytes in above    */
  94. char    ibuf[NIBUF];                    /* Input buffer          */
  95. int     nibuf;                  /* # of bytes in above  */
  96. int     ibufi;                  /* Read index                   */
  97. int     oldmode[3];                     /* Old TTY mode bits            */
  98. int     newmode[3];                     /* New TTY mode bits            */
  99. short   iochan;                  /* TTY I/O channel             */
  100. #endif
  101.  
  102. #if     CPM
  103. #include        <bdos.h>
  104. #endif
  105.  
  106. #if     MSDOS & (LATTICE | MSC | AZTEC | MWC86)
  107. union REGS rg;        /* cpu register for use of DOS calls */
  108. int nxtchar = -1;    /* character held from type ahead    */
  109. #endif
  110.  
  111. #if RAINBOW
  112. #include "rainbow.h"
  113. #endif
  114.  
  115. #if    USG            /* System V */
  116. #include    <signal.h>
  117. #include    <termio.h>
  118. struct    termio    otermio;    /* original terminal characteristics */
  119. struct    termio    ntermio;    /* charactoristics to use inside */
  120. #endif
  121.  
  122. #if V7 | BSD
  123. #undef    CTRL
  124. #include        <sgtty.h>        /* for stty/gtty functions */
  125. #include    <signal.h>
  126. struct  sgttyb  ostate;          /* saved tty state */
  127. struct  sgttyb  nstate;          /* values for editor mode */
  128. struct tchars    otchars;    /* Saved terminal special character set */
  129. struct tchars    ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  130.                 /* A lot of nothing */
  131. #if BSD
  132. #include <sys/ioctl.h>        /* to get at the typeahead */
  133. extern    int rtfrmshell();    /* return from suspended shell */
  134. #define    TBUFSIZ    128
  135. char tobuf[TBUFSIZ];        /* terminal output buffer */
  136. #endif
  137. #endif
  138.  
  139. /*
  140.  * This function is called once to set up the terminal device streams.
  141.  * On VMS, it translates TT until it finds the terminal, then assigns
  142.  * a channel to it and sets it raw. On CPM it is a no-op.
  143.  */
  144. ttopen()
  145. {
  146. #if     AMIGA
  147.  
  148.     register struct ConUnit *conunit;
  149.     register UWORD          count;
  150.     struct   Process        *myproc;
  151.     UWORD                   rows,cols;
  152.  
  153.     Enable_Abort = 0L;        /* Disable ^C         */
  154.  
  155.     GfxBase = (struct GfxBase *)
  156.         OpenLibrary("graphics.library", (LONG) 0);
  157.     if (!GfxBase)                /* Graphics lib    */
  158.         cleanup();
  159.  
  160.     IntuitionBase = (struct IntuitionBase *)    /* Intuition    */
  161.         OpenLibrary("intuition.library", (LONG) 0);
  162.  
  163.     if (!IntuitionBase)
  164.         cleanup();
  165.  
  166.     strcpy(scrtitle,"MicroEMACS ");
  167.     strcat(scrtitle,VERSION); 
  168.  
  169.     EmacsWindow = InitWindow(-1,0,0,0,scrtitle);
  170.     if (!EmacsWindow)
  171.         cleanup();
  172.  
  173.     /* Port for reading and writing */
  174.     consoleport = CreatePort("emacs.con.port",0L);
  175.     if (!consoleport)
  176.         cleanup();
  177.  
  178.     consoleWriteMsg = CreateStdIO(consoleport);
  179.     if (!consoleWriteMsg)
  180.         cleanup();
  181.  
  182.     consoleReadMsg = CreateStdIO(consoleport);
  183.     if (!consoleReadMsg)
  184.         cleanup();
  185.  
  186.     /* attach the console device to our window */
  187.     if ((OpenConsole(consoleWriteMsg,consoleReadMsg,EmacsWindow)))
  188.         cleanup();
  189.  
  190.         /* Make AmigaDOS requesters appear in our screen */
  191.         /*  "cleanup()" will restore previous value      */
  192.  
  193.         myproc  = (struct Process *) FindTask(0L);
  194.         Forbid();
  195.         savewindow              = (struct Window *) myproc->pr_WindowPtr;
  196.         myproc->pr_WindowPtr    = (APTR) EmacsWindow;
  197.         Permit();    
  198.  
  199.     /* Set-up window size for EMACS and console.device... */
  200.     
  201.     conunit = (struct ConUnit *) consoleReadMsg->io_Unit;
  202.  
  203.         rows = getrows(conunit->cu_Window,conunit->cu_Font);
  204.         cols = getcols(conunit->cu_Window,conunit->cu_Font);
  205.         
  206.         term.t_mrow = term.t_nrow = rows-1;
  207.         term.t_mcol = term.t_ncol = cols;
  208.              
  209.     newsize(TRUE,     rows );
  210.         newwidth(TRUE,  cols );
  211.  
  212.     /* set top offset */
  213.         ttputc(CSI);  
  214.         ttputc('0');
  215.         ttputc('y'); 
  216.   
  217.        /* set page length */
  218.         ttputc(CSI);  
  219.         ttputstr(itoa( rows ));
  220.         ttputc('t'); 
  221.  
  222.        /* set  left offset */
  223.         ttputc(CSI);  
  224.         ttputc('0');
  225.         ttputc('x');
  226.  
  227.        /* set line length */
  228.         ttputc(CSI);
  229.         ttputstr(itoa( cols ));
  230.         ttputc('u'); 
  231.         
  232.        /* clear screen */
  233.     ttputc(0x0c);
  234.         
  235.         /* flush output buffer */
  236.     ttflush();
  237.  
  238. #endif
  239. #if     VMS
  240.         struct  dsc$descriptor  idsc;
  241.         struct  dsc$descriptor  odsc;
  242.         char    oname[40];
  243.         int     iosb[2];
  244.         int     status;
  245.  
  246.         odsc.dsc$a_pointer = "TT";
  247.         odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
  248.         odsc.dsc$b_dtype        = DSC$K_DTYPE_T;
  249.         odsc.dsc$b_class        = DSC$K_CLASS_S;
  250.         idsc.dsc$b_dtype        = DSC$K_DTYPE_T;
  251.         idsc.dsc$b_class        = DSC$K_CLASS_S;
  252.         do {
  253.                 idsc.dsc$a_pointer = odsc.dsc$a_pointer;
  254.                 idsc.dsc$w_length  = odsc.dsc$w_length;
  255.                 odsc.dsc$a_pointer = &oname[0];
  256.                 odsc.dsc$w_length  = sizeof(oname);
  257.                 status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
  258.                 if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
  259.                         exit(status);
  260.                 if (oname[0] == 0x1B) {
  261.                         odsc.dsc$a_pointer += 4;
  262.                         odsc.dsc$w_length  -= 4;
  263.                 }
  264.         } while (status == SS$_NORMAL);
  265.         status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
  266.         if (status != SS$_NORMAL)
  267.                 exit(status);
  268.         status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
  269.                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
  270.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  271.                 exit(status);
  272.         newmode[0] = oldmode[0];
  273.         newmode[1] = oldmode[1] | TT$M_NOECHO;
  274.         newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
  275.         newmode[2] = oldmode[2] | TT2$M_PASTHRU;
  276.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  277.                           newmode, sizeof(newmode), 0, 0, 0, 0);
  278.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  279.                 exit(status);
  280.         term.t_nrow = (newmode[1]>>24) - 1;
  281.         term.t_ncol = newmode[0]>>16;
  282.  
  283. #endif
  284. #if     CPM
  285. #endif
  286.  
  287. #if     MSDOS & (HP150 == 0) & LATTICE
  288.     /* kill the ctrl-break interupt */
  289.     rg.h.ah = 0x33;        /* control-break check dos call */
  290.     rg.h.al = 1;        /* set the current state */
  291.     rg.h.dl = 0;        /* set it OFF */
  292.     intdos(&rg, &rg);    /* go for it! */
  293. #endif
  294.  
  295. #if    USG
  296.     ioctl(0, TCGETA, &otermio);    /* save old settings */
  297.     ntermio.c_iflag = 0;        /* setup new settings */
  298.     ntermio.c_oflag = 0;
  299.     ntermio.c_cflag = otermio.c_cflag;
  300.     ntermio.c_lflag = 0;
  301.     ntermio.c_line = otermio.c_line;
  302.     ntermio.c_cc[VMIN] = 1;
  303.     ntermio.c_cc[VTIME] = 0;
  304.     ioctl(0, TCSETA, &ntermio);    /* and activate them */
  305. #endif
  306.  
  307. #if     V7 | BSD
  308.         gtty(0, &ostate);                       /* save old state */
  309.         gtty(0, &nstate);                       /* get base of new state */
  310.         nstate.sg_flags |= RAW;
  311.         nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
  312.         stty(0, &nstate);                       /* set mode */
  313.     ioctl(0, TIOCGETC, &otchars);        /* Save old characters */
  314.     ioctl(0, TIOCSETC, &ntchars);        /* Place new character into K */
  315. #if    BSD
  316.     /* provide a smaller terminal output buffer so that
  317.        the type ahead detection works better (more often) */
  318.     setbuffer(stdout, &tobuf[0], TBUFSIZ);
  319.     signal(SIGTSTP,SIG_DFL);    /* set signals so that we can */
  320.     signal(SIGCONT,rtfrmshell);    /* suspend & restart emacs */
  321. #endif
  322. #endif
  323.     /* on all screens we are not sure of the initial position
  324.        of the cursor                    */
  325.     ttrow = 999;
  326.     ttcol = 999;
  327. }
  328.  
  329. /*
  330.  * This function gets called just before we go back home to the command
  331.  * interpreter. On VMS it puts the terminal back in a reasonable state.
  332.  * Another no-operation on CPM.
  333.  */
  334. ttclose()
  335. {
  336. #if     AMIGA
  337.         amg_flush();
  338.         cleanup();
  339. #endif
  340. #if     VMS
  341.         int     status;
  342.         int     iosb[1];
  343.  
  344.         ttflush();
  345.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  346.                  oldmode, sizeof(oldmode), 0, 0, 0, 0);
  347.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  348.                 exit(status);
  349.         status = SYS$DASSGN(iochan);
  350.         if (status != SS$_NORMAL)
  351.                 exit(status);
  352. #endif
  353. #if     CPM
  354. #endif
  355. #if     MSDOS & (HP150 == 0) & LATTICE
  356.     /* restore the ctrl-break interupt */
  357.     rg.h.ah = 0x33;        /* control-break check dos call */
  358.     rg.h.al = 1;        /* set the current state */
  359.     rg.h.dl = 1;        /* set it ON */
  360.     intdos(&rg, &rg);    /* go for it! */
  361. #endif
  362.  
  363. #if    USG
  364.     ioctl(0, TCSETA, &otermio);    /* restore terminal settings */
  365. #endif
  366.  
  367. #if     V7 | BSD
  368.         stty(0, &ostate);
  369.     ioctl(0, TIOCSETC, &otchars);    /* Place old character into K */
  370. #endif
  371. }
  372.  
  373. /*
  374.  * Write a character to the display. On VMS, terminal output is buffered, and
  375.  * we just put the characters in the big array, after checking for overflow.
  376.  * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
  377.  * MS-DOS (use the very very raw console output routine).
  378.  */
  379. ttputc(c)
  380. #if     AMIGA | ST520
  381.         char c;
  382. #endif
  383. {
  384. #if     AMIGA
  385.         scrn_tmp[scrn_tmp_p++] = c;
  386.         if(scrn_tmp_p >= AMG_MAXBUF)
  387.                 amg_flush();
  388. #endif
  389. #if    ST520
  390.     Bconout(2,c);
  391. #endif
  392. #if     VMS
  393.         if (nobuf >= NOBUF)
  394.                 ttflush();
  395.         obuf[nobuf++] = c;
  396. #endif
  397.  
  398. #if     CPM
  399.         bios(BCONOUT, c, 0);
  400. #endif
  401.  
  402. #if     MSDOS & MWC86
  403.         putcnb(c);
  404. #endif
  405.  
  406. #if    MSDOS & (LATTICE | AZTEC) & ~IBMPC
  407.     bdos(6, c, 0);
  408. #endif
  409.  
  410. #if RAINBOW
  411.         Put_Char(c);                    /* fast video */
  412. #endif
  413.  
  414.  
  415. #if     V7 | USG | BSD
  416.         fputc(c, stdout);
  417. #endif
  418. }
  419.  
  420. #if    AMIGA
  421. amg_flush()
  422. {
  423.         /* speed up screen writes by turning off the cursor */
  424.  
  425.         if(scrn_tmp_p)
  426.           {
  427.                 CursorOff(consoleWriteMsg);
  428.         ConWrite(consoleWriteMsg,scrn_tmp,scrn_tmp_p);
  429.         CursorOn(consoleWriteMsg);
  430.       }    
  431.         scrn_tmp_p = 0L;
  432. }
  433.  
  434.  
  435. ttputstr(a_str)
  436. char *a_str;
  437. {
  438.     while(*a_str) ttputc(*a_str++);
  439. }
  440.  
  441. #endif
  442.  
  443. /*
  444.  * Flush terminal buffer. Does real work where the terminal output is buffered
  445.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  446.  */
  447. ttflush()
  448. {
  449. #if     AMIGA
  450.         amg_flush();
  451. #endif
  452. #if     VMS
  453.         int     status;
  454.         int     iosb[2];
  455.  
  456.         status = SS$_NORMAL;
  457.         if (nobuf != 0) {
  458.                 status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
  459.                          iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
  460.                 if (status == SS$_NORMAL)
  461.                         status = iosb[0] & 0xFFFF;
  462.                 nobuf = 0;
  463.         }
  464.         return (status);
  465. #endif
  466.  
  467. #if     CPM
  468. #endif
  469.  
  470. #if     MSDOS
  471. #endif
  472.  
  473. #if     V7 | USG | BSD
  474.         fflush(stdout);
  475. #endif
  476. }
  477.  
  478. /*
  479.  * Read a character from the terminal, performing no editing and doing no echo
  480.  * at all. More complex in VMS that almost anyplace else, which figures. Very
  481.  * simple on CPM, because the system can do exactly what you want.
  482.  */
  483. ttgetc()
  484. {
  485. #if     AMIGA
  486.         char ch;
  487.         amg_flush();
  488.         GetChar(consoleReadMsg,&ch);
  489.         return( 255 & (int) ch);
  490. #endif
  491. #if    ST520
  492.     long ch;
  493. /*
  494.  * blink the cursor only if nothing is happening, this keeps the
  495.  * cursor on steadily during movement making it easier to track
  496.  */
  497.     STcurblink(TRUE);  /* the cursor blinks while we wait */
  498.     ch = Bconin(2);
  499.     STcurblink(FALSE); /* the cursor is steady while we work */
  500.     STscancode = (ch >> 16) & 0xff;
  501.            return(255 & (int)ch);
  502. #endif
  503. #if     VMS
  504.         int     status;
  505.         int     iosb[2];
  506.         int     term[2];
  507.  
  508.         while (ibufi >= nibuf) {
  509.                 ibufi = 0;
  510.                 term[0] = 0;
  511.                 term[1] = 0;
  512.                 status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
  513.                          iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
  514.                 if (status != SS$_NORMAL)
  515.                         exit(status);
  516.                 status = iosb[0] & 0xFFFF;
  517.                 if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
  518.                         exit(status);
  519.                 nibuf = (iosb[0]>>16) + (iosb[1]>>16);
  520.                 if (nibuf == 0) {
  521.                         status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
  522.                                  iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
  523.                         if (status != SS$_NORMAL
  524.                         || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
  525.                                 exit(status);
  526.                         nibuf = (iosb[0]>>16) + (iosb[1]>>16);
  527.                 }
  528.         }
  529.         return (ibuf[ibufi++] & 0xFF);    /* Allow multinational  */
  530. #endif
  531.  
  532. #if     CPM
  533.         return (biosb(BCONIN, 0, 0));
  534. #endif
  535.  
  536. #if RAINBOW
  537.         int Ch;
  538.  
  539.         while ((Ch = Read_Keyboard()) < 0);
  540.  
  541.         if ((Ch & Function_Key) == 0)
  542.                 if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
  543.                         Ch &= 0xFF;
  544.  
  545.         return Ch;
  546. #endif
  547.  
  548. #if     MSDOS & MWC86
  549.         return (getcnb());
  550. #endif
  551.  
  552. #if    MSDOS & (LATTICE | MSC | AZTEC)
  553.     int c;        /* character read */
  554.  
  555.     /* if a char already is ready, return it */
  556.     if (nxtchar >= 0) {
  557.         c = nxtchar;
  558.         nxtchar = -1;
  559.         return(c);
  560.     }
  561.  
  562.     /* call the dos to get a char */
  563.     rg.h.ah = 7;        /* dos Direct Console Input call */
  564.     intdos(&rg, &rg);
  565.     c = rg.h.al;        /* grab the char */
  566.     return(c & 255);
  567. #endif
  568.  
  569. #if     V7 | USG | BSD
  570.         return(127 & fgetc(stdin));
  571. #endif
  572. }
  573.  
  574. #if    TYPEAH
  575. /* typahead:    Check to see if any characters are already in the
  576.         keyboard buffer
  577. */
  578.  
  579. typahead()
  580.  
  581. {
  582. #if    MSDOS & (LATTICE | AZTEC | MWC86)
  583.     int c;        /* character read */
  584.     int flags;    /* cpu flags from dos call */
  585.  
  586. #if    MSC
  587.     if (kbhit() != 0)
  588.         return(TRUE);
  589.     else
  590.         return(FALSE);
  591. #endif
  592.  
  593.     if (nxtchar >= 0)
  594.         return(TRUE);
  595.  
  596.     rg.h.ah = 6;    /* Direct Console I/O call */
  597.     rg.h.dl = 255;    /*         does console input */
  598. #if    LATTICE | AZTEC
  599.     flags = intdos(&rg, &rg);
  600. #else
  601.     intcall(&rg, &rg, 0x21);
  602.     flags = rg.x.flags;
  603. #endif
  604.     c = rg.h.al;    /* grab the character */
  605.  
  606.     /* no character pending */
  607.     if ((flags & 64) != 0)
  608.         return(FALSE);
  609.  
  610.     /* save the character and return true */
  611.     nxtchar = c;
  612.     return(TRUE);
  613. #endif
  614.  
  615. #if    BSD
  616.     int x;    /* holds # of pending chars */
  617.  
  618.     return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
  619. #endif
  620.     return(FALSE);
  621. }
  622. #endif
  623.  
  624.