home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / jove.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  30KB  |  1,572 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* Contains the main loop initializations, and some system dependent
  9.    type things, e.g. putting terminal in CBREAK mode, etc. */
  10.  
  11. #include "jove.h"
  12. #include "fp.h"
  13. #include "termcap.h"
  14. #include "ctype.h"
  15. #include "chars.h"
  16. #include "disp.h"
  17. #include "re.h"    /* for find_tag() */
  18. #include "rec.h"
  19. #ifdef    IPROCS
  20. # include "iproc.h"
  21. #endif
  22.  
  23. #ifdef UNIX
  24. #include "ttystate.h"
  25. #endif
  26.  
  27. #ifdef SCO
  28. #undef TIOCGWINSZ
  29.  
  30. #include <sys/stream.h>
  31. #include <sys/ptem.h>
  32. #endif
  33.  
  34. #ifdef    MAC
  35. # include "mac.h"
  36. #else
  37. # ifdef    STDARGS
  38. #  include <stdarg.h>
  39. # else
  40. #  include <varargs.h>
  41. # endif
  42. # include <sys/stat.h>
  43. #endif
  44.  
  45. #include <signal.h>
  46. #include <errno.h>
  47.  
  48. #ifdef    MSDOS
  49. # include <process.h>
  50. #endif    /* MSDOS */
  51.  
  52. #ifndef    MAC
  53. # include <fcntl.h>
  54. #endif
  55.  
  56. #ifdef    MSDOS
  57. private    void    break_off proto((void)),
  58.         break_rst proto((void));
  59. #endif
  60.  
  61. #ifdef    MAC
  62. # define    WINRESIZE    1
  63. #else
  64. # ifdef    TIOCGWINSZ
  65. #   ifdef    SIGWINCH
  66. #     define    WINRESIZE    1
  67. #   endif
  68. # endif
  69. #endif
  70.  
  71. private void
  72.     DoKeys proto((bool firsttime));
  73.  
  74. #ifdef    MSDOS
  75. extern
  76. #else
  77. private
  78. #endif
  79.     void
  80.     UnsetTerm proto((char *)),
  81.     do_sgtty proto((void));
  82.  
  83. /* Various tty state structures.
  84.  * Each is an array, subscripted by one of "OFF" or "ON".
  85.  */
  86.  
  87. #ifdef    UNIX
  88.  
  89. # ifdef    TIOCSLTC
  90. struct ltchars    ls[2];
  91. # endif    /* TIOCSLTC */
  92.  
  93. # ifdef    TIOCGETC
  94. struct tchars    tc[2];
  95. # endif
  96.  
  97. # ifdef    PASS8            /* use pass8 instead of raw for meta-key */
  98. private int    lmword[2];        /* local mode word */
  99. # endif
  100.  
  101. # ifdef    BRLUNIX
  102. struct sg_brl    sg[2];
  103. #endif
  104. #ifdef TERMIO
  105. struct termio    sg[2];
  106. #endif
  107. #ifdef TERMIOS
  108. struct termios    sg[2];
  109. #endif
  110. #ifdef SGTTY
  111. struct sgttyb    sg[2];
  112. #endif
  113.  
  114. # ifdef    BIFF
  115. private struct stat    tt_stat;    /* for biff */
  116. #  ifndef    BSD4_2
  117. private char    *tt_name = NULL;        /* name of the control tty */
  118. extern char    *ttyname();        /* for systems w/o fchmod ... */
  119. #  endif
  120. private bool    dw_biff = NO;        /* whether or not to fotz at all */
  121. # endif    /* BIFF */
  122. #endif    /* UNIX */
  123.  
  124. bool    errormsg;
  125. char    NullStr[] = "";
  126. jmp_buf    mainjmp;
  127.  
  128.  
  129. #ifdef    MSDOS
  130. # define SIGHUP    99
  131. # define SIGIOT 99
  132. #endif    /* MSDOS */
  133.  
  134. /* finish() does not return, so it is funny that it returns a non-void
  135.  * result.  This is because most systems claim that signal(2) deals
  136.  * with functions of type int ().  ANSI changes this: the function
  137.  * type must be void (int).  This bridge must soon be crossed.
  138.  */
  139. SIGRESULT
  140. finish(code)
  141. int    code;
  142. {
  143.     int save_errno = errno;    /* Subtle, but necessary! */
  144.     static int    Crashing = 0;    /* we are in the middle of crashing */
  145.     bool    CoreDump = (code != 0 && code != SIGHUP),
  146.         DelTmps = YES;        /* Usually we delete them. */
  147.  
  148.     if (code == SIGINT) {
  149.         char    c;
  150. #ifdef    PIPEPROCS
  151.         int    started;
  152. #endif
  153. #ifndef    MENLO_JCL
  154.         (void) signal(code, finish);
  155. #endif
  156.         f_mess("Abort (Type 'n' if you're not sure)? ");
  157. #ifndef    MSDOS
  158. # ifdef    PIPEPROCS
  159.         started = kbd_stop();
  160. # endif
  161. #ifdef    SYSV
  162.         if (read(0, (UnivPtr) &c, (size_t) 1) != 1)
  163. #endif
  164.             (void) read(0, (UnivPtr) &c, (size_t) 1);
  165. # ifdef    PIPEPROCS
  166.         if (started)
  167.             (void) kbd_strt();
  168. # endif
  169. #else    /* MSDOS */
  170.         c = getrawinchar();
  171. #endif    /* MSDOS */
  172.         message(NullStr);
  173.         if ((c & 0377) != 'y') {
  174.             redisplay();
  175.             errno = save_errno;
  176.             SIGRETURN;
  177.         }
  178.     }
  179.     DisabledRedisplay = YES;
  180. #ifndef    MAC
  181.     UnsetTerm(NullStr);
  182. #endif
  183. #ifdef    PIPEPROCS
  184.     kbd_kill();        /* kill the keyboard process */
  185. #endif
  186. #ifndef    MSDOS
  187.     if (code != 0) {
  188.         if (!Crashing) {
  189.             Crashing = YES;
  190.             lsave();
  191.             SyncRec();
  192.             writef("JOVE CRASH!! (code %d): %s\n", code,
  193.                    strerror(errno));
  194.             if (ModBufs(YES)) {
  195.                 writef("Your buffers have been saved.\n");
  196.                 writef("Use \"jove -r\" to have a look at them.\n");
  197.                 DelTmps = NO;    /* Don't delete anymore. */
  198.             } else
  199.                 writef("You didn't lose any work.\n");
  200.         } else
  201.             writef("\r\nYou may have lost your work!\n");
  202.     }
  203. #endif    /* MSDOS */
  204.     flushscreen();
  205.     if (DelTmps) {
  206. #ifdef    PTYPROCS
  207.         (void) signal(SIGCHLD, SIG_IGN);
  208. #endif
  209.         tmpremove();
  210. #ifndef    MSDOS
  211.         recremove();
  212. #endif    /* MSDOS */
  213.     }
  214. #ifdef    UNIX
  215.     if (CoreDump)
  216.         abort();
  217. #ifdef    PROFILING
  218.     exit(0);
  219. #else
  220.     _exit(0);
  221. #endif
  222. #else    /* !UNIX */
  223. #ifdef    MSDOS
  224.     break_rst();    /* restore previous ctrl-c handling */
  225. #endif
  226.     exit(0);
  227. #endif    /* !UNIX */
  228.     /*NOTREACHED*/
  229. }
  230.  
  231. private char    smbuf[20],
  232.         *bp = smbuf;
  233. private int    nchars = 0;
  234.  
  235. private char    peekbuf[10],
  236.         *peekp = peekbuf;
  237.  
  238. #if    defined(SYSV) || defined(M_XENIX)
  239.  
  240. #define    NONBLOCKINGREAD    1
  241.  
  242. private void
  243. setblock(fd, on)    /* turn blocking on or off */
  244. register int    fd;
  245. bool    on;
  246. {
  247.     static int blockf, nonblockf;
  248.     static bool    first = TRUE;
  249.  
  250.     if (first) {
  251.     int flags;
  252.  
  253.     first = FALSE;
  254.     if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
  255.         finish(SIGHUP);
  256.     blockf = flags & ~O_NDELAY;    /* make sure O_NDELAY is off */
  257.     nonblockf = flags | O_NDELAY;    /* make sure O_NDELAY is on */
  258.     }
  259.     if (fcntl(fd, F_SETFL, on ? blockf : nonblockf) == -1)
  260.     finish(SIGHUP);
  261. }
  262.  
  263. #endif    /* defined(SYSV) || defined(M_XENIX) */
  264.  
  265. private int
  266. Peekc()
  267. {
  268.     return peekp == peekbuf? EOF : *--peekp & 0377;
  269. }
  270.  
  271. void
  272. Ungetc(c)
  273. int    c;
  274. {
  275.     if (peekp != &peekbuf[(sizeof peekbuf) - 1])
  276.         *peekp++ = c;
  277. }
  278.  
  279. bool    InputPending = NO;
  280.  
  281. char    *Inputp = NULL;
  282.  
  283. #ifdef    PTYPROCS
  284. int
  285. jgetchar()
  286. {
  287.  
  288.     fd_set        reads;
  289.     register int    max = getdtablesize();
  290.     register int    tmp,
  291.             nfds;
  292.     int        c;
  293.  
  294.     if (nchars <= 0) {
  295.         /* Get a character from the keyboard, first checking for
  296.            any input from a process.  Handle that first, and then
  297.            deal with the terminal input. */
  298.         do {
  299.             do {
  300.                 reads = global_fd;
  301.                 nfds = select(max, &reads, (fd_set *)0, (fd_set *)0, (struct timeval *)NULL);
  302.             } while (nfds < 0 && errno == EINTR);
  303.  
  304.             if (nfds == -1)
  305.                 complain("\rerror in select %ld: %s", global_fd, strerror(errno));
  306.             else {
  307.                 if (FD_ISSET(0, &reads)) {
  308.                     nchars = read(0, (UnivPtr) smbuf, sizeof(smbuf));
  309.                     FD_CLR(0, &reads);
  310.                     nfds--;
  311.                 }
  312.                 for (tmp = 1; tmp < max; tmp++) {
  313.                     if (FD_ISSET(tmp, &reads)) {
  314.                         read_proc(tmp);
  315.                         FD_CLR(tmp, &reads);
  316.                         if (--nfds == 0)
  317.                             break;
  318.                     }
  319.                 }
  320.             }
  321.         } while (nchars <= 0);
  322.  
  323.         if (nchars <= 0)
  324.             finish(SIGHUP);
  325.  
  326.         bp = smbuf;
  327.         InputPending = (nchars > 1);
  328.     }
  329.  
  330.     if (((c = *bp) & 0200) && MetaKey) {
  331.         *bp = (c & CHARMASK);
  332.         return '\033';
  333.     }
  334.     nchars -= 1;
  335.     return *bp++ & 0377;
  336. }
  337.  
  338. #else    /* !PTYPROCS */
  339.  
  340. int
  341. jgetchar()
  342. {
  343.     register int    c;
  344.     struct header {
  345.         int    pid;
  346.         int    nbytes;
  347.     } header;
  348.  
  349. normal:
  350.     if (nchars <= 0) {
  351.         bp = smbuf;
  352. #ifdef    MSDOS
  353.         *bp = getrawinchar();
  354.         nchars = 1;
  355. #else    /* !MSDOS */
  356. # ifdef    IPROCS
  357.         if (NumProcs > 0) {
  358.             for (;;) {
  359.                 size_t    n = f_readn(ProcInput, (char *) &header,
  360.                         sizeof(header));
  361.  
  362.                 if (n != sizeof(header)) {
  363.                     raw_complain("\r\nError reading kbd process, expected %d, got %d bytes\r\n", sizeof header, n);
  364.                     finish(SIGHUP);
  365.                 }
  366.                 /* data is from the keyboard process */
  367.                 if (header.pid == kbd_pid) {
  368.                     nchars = f_readn(ProcInput, smbuf, header.nbytes);
  369.                     if (nchars != header.nbytes) {
  370.                         raw_complain("\r\nError reading kbd process, expected %d, got %d bytes.\r\n", header.nbytes, nchars);
  371.                         finish(SIGHUP);
  372.                     }
  373.                     break;
  374.                 }
  375.                 read_proc(header.pid, header.nbytes);
  376.                 if (NumProcs == 0) {
  377.                     (void) kbd_stop();
  378.                     goto normal;
  379.                 }
  380.             }
  381.         } else /*...*/
  382. # endif
  383.         /*...*/ {
  384.             for (;;) {
  385.                 nchars = read(0, (UnivPtr) smbuf, sizeof smbuf);
  386.                 if (nchars > 0)
  387.                     break;
  388. # ifdef    SYSV
  389.                 /* System V seems to allow zero-length results */
  390.                 if (nchars == 0)
  391.                     continue;
  392. # endif    /* SYSV */
  393.                 /* retry on interrupt */
  394.                 if (!(nchars < 0 && errno == EINTR))
  395.                     finish(SIGHUP);
  396.             }
  397.         }
  398. #endif    /* !MSDOS */
  399.         InputPending = nchars > 0;
  400.     }
  401.     if (((c = *bp) & 0200) && MetaKey) {
  402.         *bp = (c & CHARMASK);
  403.         return '\033';
  404.     }
  405.     nchars -= 1;
  406.     return (*bp++ & CHARMASK);
  407. }
  408.  
  409. #endif    /* !PTYPROCS */
  410.  
  411. /* Returns non-zero if a character waiting */
  412.  
  413. bool
  414. ch