|
|
1.1 root 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: #if defined(IPROCS)
20: # include "iproc.h"
21: #endif
22:
23: #ifdef MAC
24: # include "mac.h"
25: #else
26: # ifdef STDARGS
27: # include <stdarg.h>
28: # else
29: # include <varargs.h>
30: # endif
31: # include <sys/stat.h>
32: #endif
33:
34: #include <signal.h>
35: #include <errno.h>
36:
37: #ifdef UNIX
38: # ifndef SYSV
39: # include <sgtty.h>
40: # else
41: # include <termio.h>
42: # endif /* SYSV */
43: #endif /* UNIX */
44:
45: #ifdef USE_OLD_TTY
46: # define gtty(fd, buf) ioctl(fd, TIOCGETP, buf)
47: # define stty(fd, buf) ioctl(fd, TIOCSETP, buf)
48: #endif
49:
50: #ifdef MSDOS
51: # include <process.h>
52: #endif /* MSDOS */
53:
54: #ifndef MAC
55: # include <fcntl.h>
56: #endif
57:
58: #ifdef MSDOS
59: extern time_t time proto((time_t *));
60: private void break_off proto((void)),
61: break_rst proto((void));
62: #endif
63:
64: private void
65: DoKeys proto((int firsttime)),
66: UNIX_cmdline proto((int argc,char * *argv));
67:
68: #ifdef MSDOS
69: extern void UnsetTerm proto((char *));
70: #else
71: private void UnsetTerm proto((char *));
72: #endif
73:
74: /* Various tty state structures.
75: * Each is an array, subscripted by one of "OFF" or "ON".
76: */
77:
78: #ifndef MAC
79: #include "ttystate.h"
80: #endif
81:
82: #ifdef UNIX
83: # ifdef TIOCSLTC
84: struct ltchars ls[2];
85: # endif /* TIOCSLTC */
86:
87: # if defined(TIOCGETC) && !defined(SYSV)
88: struct tchars tc[2];
89: # endif
90:
91: # ifdef PASS8 /* use pass8 instead of raw for meta-key */
92: private int lmword[2]; /* local mode word */
93: # endif
94:
95: # ifdef BRLUNIX
96: struct sg_brl sg[2];
97: # else
98: # ifdef SYSV
99: struct termio sg[2];
100: # else /* SYSV */
101: struct sgttyb sg[2];
102: # endif /* SYSV */
103: # endif /* BRLUNIX */
104:
105: # ifdef BIFF
106: private struct stat tt_stat; /* for biff */
107: # ifndef BSD4_2
108: private char *tt_name = 0; /* name of the control tty */
109: extern char *ttyname(); /* for systems w/o fchmod ... */
110: # endif
111: private int dw_biff = NO; /* whether or not to fotz at all */
112: # endif /* BIFF */
113: #endif /* UNIX */
114:
115: int errormsg;
116: char NullStr[] = "";
117: jmp_buf mainjmp;
118:
119:
120: #ifdef MSDOS
121: # define SIGHUP 99
122: #endif /* MSDOS */
123:
124: /* finish() does not return, so it is funny that it returns a non-void
125: * result. This is because most systems claim that signal(2) deals
126: * with functions of type int (). ANSI changes this: the function
127: * type must be void (int). This bridge must soon be crossed.
128: */
129: SIGRESULT
130: finish(code)
131: int code;
132: {
133: int CoreDump = (code != 0 && code != SIGHUP),
134: DelTmps = 1; /* Usually we delete them. */
135:
136: if (code == SIGINT) {
137: char c;
138: #if defined(IPROCS) && defined(PIPEPROCS)
139: int started;
140: #endif
141: #ifndef MENLO_JCL
142: (void) signal(code, finish);
143: #endif
144: f_mess("Abort (Type 'n' if you're not sure)? ");
145: #ifndef MSDOS
146: # if defined(IPROCS) && defined(PIPEPROCS)
147: started = kbd_stop();
148: # endif
149: #ifdef SYSV
150: if (read(0, &c, (size_t) 1) != 1)
151: #endif
152: (void) read(0, &c, (size_t) 1);
153: # if defined(IPROCS) && defined(PIPEPROCS)
154: if (started)
155: (void) kbd_strt();
156: # endif
157: #else /* MSDOS */
158: c = getrawinchar();
159: #endif /* MSDOS */
160: message(NullStr);
161: if ((c & 0377) != 'y') {
162: redisplay();
163: SIGRETURN;
164: }
165: }
166: DisabledRedisplay = YES;
167: #ifndef MAC
168: UnsetTerm(NullStr);
169: #endif
170: #if defined(IPROCS) && defined(PIPEPROCS)
171: kbd_kill(); /* kill the keyboard process */
172: #endif
173: #ifndef MSDOS
174: if (code != 0) {
175: if (!Crashing) {
176: Crashing = YES;
177: lsave();
178: SyncRec();
179: writef("JOVE CRASH!! (code %d)\n", code);
180: if (ModBufs(1)) {
181: writef("Your buffers have been saved.\n");
182: writef("Use \"jove -r\" to have a look at them.\n");
183: DelTmps = 0; /* Don't delete anymore. */
184: } else
185: writef("You didn't lose any work.\n");
186: } else
187: writef("\r\nYou may have lost your work!\n");
188: }
189: #endif /* MSDOS */
190: flusho();
191: if (DelTmps) {
192: #if defined(IPROCS) && !defined(PIPEPROCS)
193: (void) signal(SIGCHLD, SIG_IGN);
194: #endif
195: tmpclose();
196: #ifndef MSDOS
197: recclose();
198: #endif /* MSDOS */
199: }
200: #ifdef UNIX
201: if (CoreDump)
202: abort();
203: #ifdef PROFILING
204: monitor(0);
205: #endif
206: _exit(0);
207: #else /* MSDOS or MAC*/
208: #ifdef MSDOS
209: break_rst(); /* restore previous ctrl-c handling */
210: #endif
211: exit(0);
212: #endif /* UNIX */
213: /*NOTREACHED*/
214: }
215:
216: private char smbuf[20],
217: *bp = smbuf;
218: private int nchars = 0;
219:
220: private char peekbuf[10],
221: *peekp = peekbuf;
222:
223: #if defined(SYSV) || defined(M_XENIX)
224: void
225: setblock(fd, on) /* turn blocking on or off */
226: register int fd, on;
227: {
228: static int blockf, nonblockf;
229: static int first = 1;
230: int flags;
231:
232: if (first) {
233: first = 0;
234: if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
235: finish(SIGHUP);
236: blockf = flags & ~O_NDELAY; /* make sure O_NDELAY is off */
237: nonblockf = flags | O_NDELAY; /* make sure O_NDELAY is on */
238: }
239: if (fcntl(fd, F_SETFL, on ? blockf : nonblockf) == -1)
240: finish(SIGHUP);
241: }
242: #endif /* SYSV */
243:
244: private int
245: Peekc()
246: {
247: int c;
248:
249: if (peekp == peekbuf)
250: c = EOF;
251: else
252: c = *--peekp & 0377;
253: return c;
254: }
255:
256: void
257: Ungetc(c)
258: int c;
259: {
260: if (peekp == &peekbuf[(sizeof peekbuf) - 1])
261: return; /* Sorry, can't oblige you ... */
262: *peekp++ = c;
263: }
264:
265: int InputPending = 0;
266:
267: char *Inputp = 0;
268:
269: #if (defined(IPROCS) && !defined(PIPEPROCS)) /* that is, if ptys */
270: int
271: jgetchar()
272: {
273: long reads;
274: register int tmp,
275: nfds;
276: int c;
277:
278: if (nchars <= 0) {
279: /* Get a character from the keyboard, first checking for
280: any input from a process. Handle that first, and then
281: deal with the terminal input. */
282: do {
283: do {
284: reads = global_fd;
285: nfds = select(32, &reads, (long *) 0, (long *) 0, (struct timeval *) 0);
286: } while (nfds < 0 && errno == EINTR);
287:
288: if (nfds == -1)
289: complain("\rerror %d in select %ld", errno, global_fd);
290: else {
291: if (reads & 01) {
292: nchars = read(0, smbuf, sizeof(smbuf));
293: reads &= ~01;
294: nfds -= 1;
295: }
296: while (nfds--) {
297: tmp = ffs(reads) - 1;
298: read_proc(tmp);
299: reads &= ~(1L << tmp);
300: }
301: }
302: } while (nchars <= 0);
303:
304: if (nchars <= 0)
305: finish(SIGHUP);
306:
307: bp = smbuf;
308: InputPending = (nchars > 1);
309: }
310:
311: if (((c = *bp) & 0200) && MetaKey != 0) {
312: *bp = (c & CHARMASK);
313: return '\033';
314: }
315: nchars -= 1;
316: return *bp++ & 0377;
317: }
318:
319: #else
320:
321: jgetchar()
322: {
323: register int c;
324: struct header {
325: int pid;
326: int nbytes;
327: } header;
328: int n;
329:
330: normal:
331: if (nchars <= 0) {
332: bp = smbuf;
333: #ifdef MSDOS
334: *bp = getrawinchar();
335: nchars = 1;
336: #else
337: # ifdef IPROCS
338: if (NumProcs == 0) {
339: # endif
340: do
341: nchars = read(0, smbuf, sizeof smbuf);
342: # ifdef SYSV
343: while (nchars == 0 || (nchars < 0 && errno == EINTR));
344: if (nchars < 0)
345: # else
346: while (nchars < 0 && errno == EINTR);
347: if (nchars <= 0)
348: # endif /* SYSV */
349: finish(SIGHUP);
350: # ifdef IPROCS
351: } else for (;;) {
352: n = f_readn(ProcInput, &header, sizeof (header));
353: if (n == EOF) {
354: printf("\rError reading kbd process.\n");
355: finish(1);
356: }
357: /* data is from the keyboard process */
358: if (header.pid == kbd_pid) {
359: nchars = f_readn(ProcInput, smbuf, header.nbytes);
360: if (nchars != header.nbytes) {
361: printf("\rError reading kbd process.");
362: finish(1);
363: } else
364: break;
365: } else
366: read_proc(header.pid, header.nbytes);
367: if (NumProcs == 0) {
368: (void) kbd_stop();
369: goto normal;
370: }
371: }
372: # endif /* IPROCS */
373: #endif /* MSDOS */
374: InputPending = nchars > 0;
375: }
376: if (((c = *bp) & 0200) && MetaKey != 0) {
377: *bp = (c & CHARMASK);
378: return '\033';
379: }
380: nchars -= 1;
381: return (*bp++ & CHARMASK);
382: }
383:
384: #endif /* IPROCS */
385:
386: /* Returns non-zero if a character waiting */
387:
388: int
389: charp()
390: {
391: int some = 0;
392:
393: if (InJoverc != 0 || nchars > 0 || Inputp != 0)
394: return 1;
395: #ifdef BRLUNIX
396: {
397: static struct sg_brl gttyBuf;
398:
399: gtty(0, (char *) >tyBuf);
400: if (gttyBuf.sg_xflags & INWAIT)
401: some += 1;
402: }
403: #endif
404: #ifdef FIONREAD
405: {
406: long c;
407:
408: if (ioctl(0, FIONREAD, (UnivPtr) &c) == -1)
409: c = 0;
410: some = (c > 0);
411: }
412: #endif /* FIONREAD */
413: #if defined(SYSV) || defined(M_XENIX)
414: setblock(0, 0); /* turn blocking off */
415: nchars = read(0, smbuf, sizeof smbuf); /* Is anything there? */
416: setblock(0, 1); /* turn blocking on */
417: if (nchars > 0) /* something was there */
418: bp = smbuf; /* make sure bp points to it */
419: some = (nchars > 0); /* just say we found something */
420: #endif /* SYSV */
421: #ifdef c70
422: some = !empty(0);
423: #endif
424: #ifdef MSDOS
425: some = rawkey_ready();
426: #endif
427: #ifdef MAC
428: some = rawchkc();
429: #endif
430: return some;
431: }
432:
433: void do_sgtty proto((void));
434: #ifdef BIFF
435: private void biff_init proto((void));
436: #endif
437:
438: #ifdef TERMCAP
439:
440: private void
441: ResetTerm()
442: {
443: do_sgtty(); /* this is so if you change baudrate or stuff
444: like that, JOVE will notice. */
445: ttyset(ON);
446: putpad(TI, 1);
447: putpad(VS, 1);
448: putpad(KS, 1);
449: #ifdef UNIX
450: (void) chkmail(YES); /* force it to check to we can be accurate */
451: #endif
452: #ifdef BIFF
453: if (BiffChk != dw_biff)
454: biff_init();
455: /* just in case we changed our minds about whether to deal with
456: biff */
457: #endif
458: }
459:
460: private void
461: UnsetTerm(mesg)
462: char *mesg;
463: {
464: ttyset(OFF);
465: #ifdef ID_CHAR
466: INSmode(0);
467: #endif
468: putpad(KE, 1);
469: putpad(VE, 1);
470: /*
471: * For terminals without an alternate page, go the bottom of the
472: * screen. Alternate page - just return to the original place on
473: * the screen
474: */
475: if (!TE) {
476: Placur(ILI, 0);
477: putpad(CE, 1);
478: } else {
479: putpad(TE, 1);
480: }
481: if (mesg[0] != '\0')
482: writef("%s\n", mesg);
483: flusho();
484: }
485: #endif /* TERMCAP */
486:
487: #ifdef JOB_CONTROL
488: void
489: PauseJove()
490: {
491: UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr);
492: (void) kill(0, SIGTSTP);
493: ResetTerm();
494: ClAndRedraw();
495: }
496: #endif
497:
498:
499: #ifndef MAC
500: void
501: Push()
502: {
503: #ifndef MSDOS
504: int pid;
505: SIGRESULT (*old_quit) proto((int)) = signal(SIGQUIT, SIG_IGN);
506: #endif /* MSDOS */
507: SIGRESULT (*old_int) proto((int)) = signal(SIGINT, SIG_IGN);
508:
509: #ifndef MSDOS
510: #ifdef IPROCS
511: SigHold(SIGCHLD);
512: #endif
513: #if defined(TIOCGWINSZ) && defined(SIGWINCH) && defined(SigRelse)
514: SigHold(SIGWINCH);
515: #endif
516: alarm(0);
517: switch (pid = fork()) {
518: case -1:
519: complain("[Fork failed]");
520: /*NOTREACHED*/
521:
522: case 0:
523: UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr);
524: #if defined(TIOCGWINSZ) && defined(SIGWINCH) && defined(SigRelse)
525: SigRelse(SIGWINCH);
526: #endif
527: #ifdef IPROCS
528: SigRelse(SIGCHLD);
529: #endif
530: (void) signal(SIGTERM, SIG_DFL);
531: #else /* MSDOS */
532: UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr);
533: #endif /* MSDOS */
534: (void) signal(SIGINT, SIG_DFL);
535: #ifdef UNIX
536: (void) signal(SIGQUIT, SIG_DFL);
537: execl(Shell, basename(Shell), "-i", (char *)0);
538: message("[Execl failed]");
539: _exit(1);
540: }
541: #ifdef IPROCS
542: SigRelse(SIGCHLD);
543: #endif
544: dowait(pid, (int *) 0);
545: #endif /* UNIX */
546: #ifdef MSDOS
547: break_rst();
548: if (spawnl(0, Shell, basename(Shell), (char *)0) == -1)
549: message("[Spawn failed]");
550: #endif /* MSDOS */
551: #ifndef MAC
552: ResetTerm();
553: #endif
554: #if defined(TIOCGWINSZ) && defined(SIGWINCH) && defined(SigRelse)
555: SigRelse(SIGWINCH);
556: #endif
557: ClAndRedraw();
558: #ifndef MSDOS
559: (void) signal(SIGQUIT, old_quit);
560: #else /* MSDOS */
561: break_off();
562: getCWD();
563: #endif /* MSDOS */
564: (void) signal(SIGINT, old_int);
565: (void) alarm((unsigned) (UpdFreq - (time((time_t *) 0) % UpdFreq)));
566: }
567: #endif /* MAC */
568:
569: int OKXonXoff = 0, /* ^S and ^Q initially DON'T work */
570: IntChar = CTL(']');
571:
572: private void
573: ttsize()
574: {
575: #ifdef UNIX
576: # ifdef TIOCGWINSZ
577: struct winsize win;
578:
579: if (ioctl (0, TIOCGWINSZ, (UnivPtr) &win) == 0) {
580: if (win.ws_col)
581: CO = win.ws_col;
582: if (win.ws_row)
583: LI = win.ws_row;
584: }
585: # else /* TIOCGWINSZ */
586: # ifdef BTL_BLIT
587: #include <sys/jioctl.h>
588: struct jwinsize jwin;
589:
590: if (ioctl(0, JWINSIZE, &jwin) == 0) {
591: if (jwin.bytesx)
592: CO = jwin.bytesx;
593: if (jwin.bytesy)
594: LI = jwin.bytesy;
595: }
596: # endif /* BTL_BLIT */
597: # endif /* TIOCGWINSZ */
598: #endif /* UNIX */
599: #ifdef MAC
600: CO = getCO(); /* see mac.c */
601: LI = getLI();
602: Windchange = 1;
603: clr_page();
604: #endif
605: ILI = LI - 1;
606: }
607:
608: #ifdef BIFF
609: private void
610: biff_init()
611: {
612: dw_biff = ((BiffChk) &&
613: # ifndef BSD4_2
614: ((tt_name != 0) || (tt_name = ttyname(0))) &&
615: (stat(tt_name, &tt_stat) != -1) &&
616: # else
617: (fstat(0, &tt_stat) != -1) &&
618: # endif
619: (tt_stat.st_mode & S_IEXEC)); /* he's using biff */
620:
621: }
622:
623: private void
624: biff(on)
625: int on;
626: {
627: if (dw_biff == NO)
628: return;
629: # ifndef BSD4_2
630: (void) chmod(tt_name, on ? tt_stat.st_mode :
631: (tt_stat.st_mode & ~S_IEXEC));
632: # else
633: (void) fchmod(0, on ? tt_stat.st_mode :
634: (tt_stat.st_mode & ~S_IEXEC));
635: # endif
636: }
637:
638: #endif /* BIFF */
639:
640: private void
641: ttinit()
642: {
643: #ifdef BIFF
644: biff_init();
645: #endif
646: #ifdef TIOCSLTC
647: (void) ioctl(0, TIOCGLTC, (UnivPtr) &ls[OFF]);
648: ls[ON] = ls[OFF];
649: ls[ON].t_suspc = (char) -1;
650: ls[ON].t_dsuspc = (char) -1;
651: ls[ON].t_flushc = (char) -1;
652: ls[ON].t_lnextc = (char) -1;
653: #endif
654:
655: #if defined(TIOCGETC) && !defined(SYSV)
656: /* Change interupt and quit. */
657: (void) ioctl(0, TIOCGETC, (UnivPtr) &tc[OFF]);
658: tc[ON] = tc[OFF];
659: tc[ON].t_intrc = IntChar;
660: tc[ON].t_quitc = (char) -1;
661: if (OKXonXoff) {
662: tc[ON].t_stopc = (char) -1;
663: tc[ON].t_startc = (char) -1;
664: }
665: #endif /* TIOCGETC */
666: do_sgtty();
667: }
668:
669: private int done_ttinit = 0;
670:
671: void
672: do_sgtty()
673: {
674: #ifdef UNIX
675: # ifdef SYSV
676: (void) ioctl(0, TCGETA, (char *) &sg[OFF]);
677: # else
678: (void) gtty(0, &sg[OFF]);
679: # endif /* SYSV */
680: sg[ON] = sg[OFF];
681:
682: # ifdef LPASS8
683: (void) ioctl(0, TIOCLGET, (UnivPtr) &lmword[OFF]);
684: lmword[ON] = lmword[OFF];
685: if (MetaKey == YES)
686: lmword[ON] |= LPASS8;
687: if (HZ)
688: lmword[ON] &= ~LTILDE;
689: # endif
690:
691: # ifdef SYSV
692: TABS = !((sg[OFF].c_oflag & TAB3) == TAB3);
693: ospeed = sg[OFF].c_cflag & CBAUD;
694:
695: if (OKXonXoff)
696: sg[ON].c_iflag &= ~(IXON | IXOFF);
697: sg[ON].c_iflag &= ~(INLCR|ICRNL|IGNCR);
698: sg[ON].c_lflag &= ~(ICANON|ECHO);
699: sg[ON].c_oflag &= ~(OCRNL|ONLCR);
700: sg[ON].c_cc[VINTR] = IntChar;
701: sg[ON].c_cc[VQUIT] = (char) -1;
702: sg[ON].c_cc[VSWTCH] = (char) -1;
703: sg[ON].c_cc[VMIN] = sizeof smbuf;
704: sg[ON].c_cc[VTIME] = 1;
705: # else
706: TABS = !(sg[OFF].sg_flags & XTABS);
707: sg[ON].sg_flags &= ~XTABS;
708: ospeed = sg[OFF].sg_ospeed;
709: # ifdef BRLUNIX
710: sg[ON].sg_flags &= ~(ECHO | CRMOD);
711: sg[ON].sg_flags |= CBREAK;
712:
713: /* VT100 Kludge: leave STALL on for flow control if DC3DC1 (Yuck.) */
714: sg[ON].sg_xflags &= ~((sg[ON].sg_xflags&DC3DC1 ? 0 : STALL) | PAGE);
715: # else
716: sg[ON].sg_flags &= ~(ECHO | CRMOD);
717: # endif /* BRLUNIX */
718:
719: # ifdef LPASS8
720: sg[ON].sg_flags |= CBREAK;
721: # else
722: sg[ON].sg_flags |= (MetaKey ? RAW : CBREAK);
723: # endif
724: # endif /* SYSV */
725: #endif /* UNIX */
726:
727: #ifdef MSDOS
728: # ifndef IBMPC
729: setmode(1, 0x8000);
730: # endif /* IBMPC */
731: TABS = 0;
732: #endif /* MSDOS */
733: }
734:
735: void
736: tty_reset()
737: {
738: if (!done_ttinit)
739: return;
740: ttyset(OFF); /* go back to original modes */
741: ttinit();
742: ttyset(ON);
743: }
744:
745: /* If n is OFF reset to original modes */
746:
747: void
748: ttyset(n)
749: int n;
750: {
751: if (!done_ttinit && n == 0) /* Try to reset before we've set! */
752: return;
753: #ifdef UNIX
754: # ifdef SYSV
755: (void) ioctl(0, TCSETAW, (UnivPtr) &sg[n]);
756: # else
757: # ifdef BRLUNIX
758: (void) stty(0, &sg[n]);
759: # else
760: (void) ioctl(0, TIOCSETN, (UnivPtr) &sg[n]);
761: # endif /* BRLUNIX */
762: # endif /* SYSV */
763:
764: # if defined(TIOCSETC) && !defined(SYSV)
765: (void) ioctl(0, TIOCSETC, (UnivPtr) &tc[n]);
766: # endif /* TIOCSETC */
767: # ifdef TIOCSLTC
768: (void) ioctl(0, TIOCSLTC, (UnivPtr) &ls[n]);
769: # endif /* TIOCSLTC */
770: # ifdef LPASS8
771: (void) ioctl(0, TIOCLSET, (UnivPtr) &lmword[n]);
772: # endif
773: #endif /* UNIX */
774:
775: #ifdef MSDOS
776: # ifndef IBMPC
777: setmode(1, n == 0 ? 0x4000 : 0x8000);
778: # endif
779: #endif /* MSDOS */
780: done_ttinit = 1;
781: #ifdef BIFF
782: biff(!n);
783: #endif
784: }
785:
786: int this_cmd,
787: last_cmd,
788: LastKeyStruck,
789: MetaKey = 0;
790:
791: int
792: getch()
793: {
794: register int c,
795: peekc;
796:
797: if (Inputp) {
798: if ((c = *Inputp++) != '\0')
799: return LastKeyStruck = c;
800: Inputp = NULL;
801: }
802:
803: if (InJoverc)
804: return EOF; /* somethings wrong if Inputp runs out while
805: we're reading a .joverc file. */
806:
807: #ifndef MSDOS
808: if (ModCount >= SyncFreq) {
809: ModCount = 0;
810: SyncRec();
811: }
812: #endif /* MSDOS */
813:
814: /* If we're not interactive and we're not executing a macro,
815: AND there are no ungetc'd characters, we read from the
816: terminal (i.e., getch()). And characters only get put
817: in macros from inside this if. */
818: if (((peekc = c = Peekc()) == EOF) &&
819: (Interactive || ((c = mac_getc()) == EOF))) {
820: /* So messages that aren't error messages don't
821: hang around forever. */
822: if (!UpdMesg && !Asking && mesgbuf[0] != '\0' && !errormsg)
823: message(NullStr);
824: redisplay();
825: #ifdef UNIX
826: inIOread = 1;
827: #endif
828: if ((c = jgetchar()) == EOF)
829: finish(SIGHUP);
830: #ifdef UNIX
831: inIOread = 0;
832: #endif
833:
834: if (!Interactive && InMacDefine)
835: mac_putc(c);
836: }
837: if (peekc == EOF) /* don't add_stroke peekc's */
838: add_stroke(c);
839: return LastKeyStruck = c;
840: }
841:
842: #ifdef UNIX
843: private void
844: dorecover()
845: {
846: /* Since recover is a normal cooked mode program, reset the terminal */
847: UnsetTerm(NullStr);
848: #if defined(IPROCS) && defined(PIPEPROCS)
849: kbd_kill(); /* kill the keyboard process */
850: #endif
851: execl(Recover, "recover", "-d", TmpFilePath, (char *) NULL);
852: writef("%s: execl failed!\n", Recover);
853: flusho();
854: _exit(-1);
855: /* NOTREACHED */
856: }
857: #endif /* UNIX */
858:
859: void
860: ShowVersion()
861: {
862: s_mess("Jonathan's Own Version of Emacs (%s)", version);
863: }
864:
865: private void
866: UNIX_cmdline(argc, argv)
867: int argc;
868: char *argv[];
869: {
870: int lineno = 0,
871: nwinds = 1;
872: Buffer *b;
873:
874: ShowVersion();
875: while (argc > 1) {
876: if (argv[1][0] != '-' && argv[1][0] != '+') {
877: int force = (nwinds > 0 || lineno != 0);
878:
879: #ifdef MSDOS
880: strlwr(argv[1]);
881: #endif
882: minib_add(argv[1], force);
883: b = do_find(nwinds > 0 ? curwind : (Window *) NULL,
884: argv[1], force);
885: if (force) {
886: SetABuf(curbuf);
887: SetBuf(b);
888: if (lineno >= 0)
889: SetLine(next_line(curbuf->b_first, lineno));
890: else
891: SetLine(curbuf->b_last);
892: if (nwinds > 1)
893: NextWindow();
894: if (nwinds)
895: nwinds -= 1;
896: }
897: lineno = 0;
898: } else switch (argv[1][1]) {
899: case 'd':
900: argv += 1;
901: argc -= 1;
902: break;
903:
904: case 'j': /* Ignore .joverc in HOME */
905: break;
906: #ifndef MAC
907: case 'p':
908: argv += 1;
909: argc -= 1;
910: if (argv[1] != NULL) {
911: SetBuf(do_find(curwind, argv[1], NO));
912: ErrParse();
913: nwinds = 0;
914: }
915: break;
916: #endif
917: case 't':
918: /* check if syntax is -tTag or -t Tag */
919: if (argv[1][2] != '\0') {
920: find_tag(&(argv[1][2]), YES);
921: } else {
922: argv += 1;
923: argc -= 1;
924: if (argv[1] != NULL)
925: find_tag(argv[1], YES);
926: }
927: break;
928:
929: case 'w':
930: if (argv[1][2] == '\0')
931: nwinds += 1;
932: else {
933: int n;
934:
935: (void) chr_to_int(&argv[1][2], 10, NO, &n);
936: nwinds += -1 + n;
937: }
938: (void) div_wind(curwind, nwinds - 1);
939: break;
940:
941: case '0':
942: case '1':
943: case '2':
944: case '3':
945: case '4':
946: case '5':
947: case '6':
948: case '7':
949: case '8':
950: case '9':
951: (void) chr_to_int(&argv[1][1], 10, NO, &lineno);
952: lineno -= 1;
953: break;
954: case 0:
955: lineno = -1; /* goto end of file ... */
956: break; /* just like some people's */
957: } /* favourite editor */
958: argv += 1;
959: argc -= 1;
960: }
961: }
962:
963: #ifdef STDARGS
964: void
965: error(char *fmt, ...)
966: #else
967: /*VARARGS1*/ void
968: error(fmt, va_alist)
969: char *fmt;
970: va_dcl
971: #endif
972: {
973: va_list ap;
974:
975: if (fmt) {
976: va_init(ap, fmt);
977: format(mesgbuf, sizeof mesgbuf, fmt, ap);
978: va_end(ap);
979: UpdMesg = YES;
980: }
981: rbell();
982: longjmp(mainjmp, ERROR);
983: }
984:
985: #ifdef STDARGS
986: void
987: complain(char *fmt, ...)
988: #else
989: /*VARARGS1*/ void
990: complain(fmt, va_alist)
991: char *fmt;
992: va_dcl
993: #endif
994: {
995: va_list ap;
996:
997: if (fmt) {
998: va_init(ap, fmt);
999: format(mesgbuf, sizeof mesgbuf, fmt, ap);
1000: va_end(ap);
1001: UpdMesg = YES;
1002: }
1003: rbell();
1004: longjmp(mainjmp, COMPLAIN);
1005: }
1006:
1007: #ifdef STDARGS
1008: void
1009: confirm(char *fmt, ...)
1010: #else
1011: /*VARARGS1*/ void
1012: confirm(fmt, va_alist)
1013: char *fmt;
1014: va_dcl
1015: #endif
1016: {
1017: char *yorn;
1018: va_list ap;
1019:
1020: va_init(ap, fmt);
1021: format(mesgbuf, sizeof mesgbuf, fmt, ap);
1022: va_end(ap);
1023: yorn = ask((char *) 0, mesgbuf);
1024: if (*yorn != 'Y' && *yorn != 'y')
1025: longjmp(mainjmp, COMPLAIN);
1026: }
1027:
1028: int RecDepth = 0;
1029:
1030: void
1031: Recur()
1032: {
1033: char bname[128];
1034: Mark *m;
1035:
1036: swritef(bname, "%s", curbuf->b_name);
1037: m = MakeMark(curline, curchar, M_FLOATER);
1038:
1039: RecDepth += 1;
1040: UpdModLine = YES;
1041: DoKeys(NO); /* NO means not first time */
1042: UpdModLine = YES;
1043: RecDepth -= 1;
1044: SetBuf(do_select(curwind, bname));
1045: if (!is_an_arg())
1046: ToMark(m);
1047: DelMark(m);
1048: }
1049:
1050: #ifdef MAC
1051: jmp_buf auxjmp;
1052: #endif
1053:
1054: private int iniargc; /* main sets these for DoKeys() */
1055: private char **iniargv;
1056:
1057: private void
1058: DoKeys(firsttime)
1059: int firsttime;
1060: {
1061: int c;
1062: jmp_buf savejmp;
1063:
1064: push_env(savejmp);
1065:
1066: switch (setjmp(mainjmp)) {
1067: case 0:
1068: if (firsttime)
1069: UNIX_cmdline(iniargc, iniargv);
1070: break;
1071:
1072: case QUIT:
1073: if (RecDepth == 0) {
1074: if (ModMacs()) {
1075: rbell();
1076: if (CharUpcase(*ask("No",
1077: "Some MACROS haven't been saved; leave anyway? ")) != 'Y')
1078: break;
1079: }
1080: if (ModBufs(0)) {
1081: rbell();
1082: if (CharUpcase(*ask("No",
1083: "Some buffers haven't been saved; leave anyway? ")) != 'Y')
1084: break;
1085: }
1086: #ifdef IPROCS
1087: KillProcs();
1088: #endif
1089: }
1090: pop_env(savejmp);
1091: return;
1092:
1093: case ERROR:
1094: getDOT(); /* God knows what state linebuf was in */
1095: /*FALLTHROUGH*/
1096: case COMPLAIN:
1097: {
1098: gc_openfiles(); /* close any files we left open */
1099: errormsg = YES;
1100: unwind_macro_stack();
1101: Asking = 0;
1102: curwind->w_bufp = curbuf;
1103: DisabledRedisplay = NO;
1104: redisplay();
1105: break;
1106: }
1107: }
1108:
1109: this_cmd = last_cmd = 0;
1110:
1111: for (;;) {
1112: #ifdef MAC
1113: setjmp(auxjmp);
1114: #endif
1115: if (this_cmd != ARG_CMD) {
1116: clr_arg_value();
1117: last_cmd = this_cmd;
1118: init_strokes();
1119: }
1120: #ifdef MAC
1121: HiliteMenu(0);
1122: EventCmd = 0;
1123: menus_on();
1124: #endif
1125: c = getch();
1126: if (c == EOF)
1127: continue;
1128: dispatch(c);
1129: }
1130: }
1131:
1132: int Crashing = 0;
1133:
1134: private char **
1135: scanvec(args, str)
1136: register char **args,
1137: *str;
1138: {
1139: while (*args) {
1140: if (strcmp(*args, str) == 0)
1141: return args;
1142: args += 1;
1143: }
1144: return 0;
1145: }
1146:
1147: #ifdef UNIX
1148: int UpdFreq = 30,
1149: inIOread = 0;
1150:
1151: private SIGRESULT
1152: updmode(junk)
1153: int junk; /* passed in on signal; of no interest */
1154: {
1155: UpdModLine = YES;
1156: if (inIOread)
1157: redisplay();
1158: #ifndef JOB_CONTROL
1159: (void) signal(SIGALRM, updmode);
1160: #endif
1161: (void) alarm((unsigned) (UpdFreq - (time((time_t *) 0) % UpdFreq)));
1162: SIGRETURN;
1163: }
1164: #endif /* UNIX */
1165:
1166: #ifdef MSDOS
1167: # ifndef IBMPC
1168: char ttbuf[JBUFSIZ];
1169: # endif /* IBMPC */
1170: #endif /* MSDOS */
1171:
1172: #if defined(MAC) || (defined(TIOCGWINSZ) && defined(SIGWINCH))
1173: #ifndef MAC
1174: private
1175: #endif
1176: SIGRESULT
1177: win_reshape(junk)
1178: int junk; /* passed in when invoked by a signal; of no interest */
1179: {
1180: register int oldLI;
1181: register int newsize, total;
1182: register Window *wp;
1183:
1184: #ifdef UNIX
1185: (void) SigHold(SIGWINCH);
1186: #endif
1187: /*
1188: * Save old number of lines.
1189: */
1190: oldLI = LI;
1191:
1192: /*
1193: * Get new line/col info.
1194: */
1195: ttsize();
1196:
1197: /*
1198: * LI has changed, and now holds the
1199: * new value.
1200: */
1201: /*
1202: * Go through the window list, changing each window size in
1203: * proportion to the resize. If a window becomes too small,
1204: * delete it. We keep track of all the excess lines (caused by
1205: * roundoff!), and give them to the current window, as a sop -
1206: * can't be more than one or two lines anyway. This seems fairer
1207: * than just resizing the current window.
1208: */
1209: wp = fwind;
1210: total = 0;
1211: do {
1212: newsize = LI * wp->w_height / oldLI;
1213:
1214: if (newsize < 2) {
1215: total += wp->w_height;
1216: wp = wp->w_next;
1217: del_wind(wp->w_prev);
1218: } else {
1219: wp->w_height = newsize;
1220: total += newsize;
1221: wp = wp->w_next;
1222: }
1223: } while (wp != fwind);
1224:
1225: curwind->w_height += LI - total - 1;
1226:
1227: /* Make a new screen structure */
1228: make_scr();
1229: /* Do a 'hard' update on the screen - clear and redraw */
1230: cl_scr(YES);
1231: flusho();
1232: redisplay();
1233:
1234: #ifdef UNIX
1235: (void) signal(SIGWINCH, win_reshape);
1236: #endif
1237: SIGRETURN;
1238: }
1239: #endif
1240:
1241: void
1242:
1243: #ifdef MAC /* will get args from user, if option key held during launch */
1244: main()
1245: {
1246: int argc;
1247: char **argv;
1248: #else
1249: main(argc, argv)
1250: int argc;
1251: char *argv[];
1252: {
1253: #endif /* MAC */
1254: char *cp;
1255: char ttbuf[MAXTTYBUF];
1256: #ifndef MSDOS
1257: # ifndef VMUNIX
1258: char s_iobuff[LBSIZE],
1259: s_genbuf[LBSIZE],
1260: s_linebuf[LBSIZE];
1261: /* The way I look at it, there ain't no way I is gonna run
1262: out of stack space UNLESS I have some kind of infinite
1263: recursive bug. So why use up some valuable memory, when
1264: there is plenty of space on the stack? (This only matters
1265: on wimpy pdp11's, of course.) */
1266:
1267: iobuff = s_iobuff;
1268: genbuf = s_genbuf;
1269: linebuf = s_linebuf;
1270: # endif
1271:
1272: #else /* MSDOS */
1273: char *getenv();
1274: #endif /* MSDOS */
1275:
1276: #ifdef MAC
1277: MacInit(); /* initializes all */
1278: if(make_cache() == 0) exit(-1);
1279: argc = getArgs(&argv);
1280: #endif /* MAC */
1281:
1282: iniargc = argc;
1283: iniargv = argv;
1284:
1285: if (setjmp(mainjmp)) {
1286: writef("\rAck! I can't deal with error \"%s\" now.\n\r", mesgbuf);
1287: finish(6);
1288: }
1289:
1290: #ifdef MSDOS
1291: /* import the temporary file path from the environment and
1292: fix the string, so that we can append a slash safely */
1293:
1294: if (((cp = getenv("TMP")) || (cp = getenv("TMPDIR"))) &&
1295: (*cp != '\0')) {
1296: strcpy(TmpFilePath, cp);
1297: cp = &TmpFilePath[strlen(TmpFilePath)-1];
1298: if ((*cp == '/') || (*cp == '\\'))
1299: *cp = 0;
1300: }
1301: ShFlags[0] = switchar();
1302: #endif /* MSDOS */
1303:
1304: getTERM(); /* Get terminal. */
1305: if (getenv("METAKEY"))
1306: MetaKey = 1;
1307: ttsize();
1308: #ifdef MAC
1309: InitEvents();
1310: #else
1311: InitCM();
1312: #endif
1313:
1314: d_cache_init(); /* initialize the disk buffer cache */
1315: #ifdef MSDOS
1316: if ((cp = getenv("COMSPEC")) && (*cp != '\0')) {
1317: strcpy(Shell, cp);
1318: }
1319: if ((cp = getenv("DESCRIBE")) && (*cp != '\0'))
1320: strcpy(CmdDb, cp);
1321: #else /* !MSDOS */
1322: #ifndef MAC
1323: if ((cp = getenv("SHELL"))!=NULL && (*cp != '\0')) {
1324: strcpy(Shell, cp);
1325: }
1326: #endif
1327: #endif /* !MSDOS */
1328:
1329: make_scr();
1330: mac_init(); /* Initialize Macros */
1331: winit(); /* Initialize Window */
1332: #ifdef IPROCS
1333: pinit(); /* Pipes/process initialization */
1334: #endif
1335: buf_init();
1336:
1337: {
1338: char **argp;
1339:
1340: if ((argp = scanvec(argv, "-d"))!=NULL
1341: #ifdef UNIX
1342: && chkCWD(argp[1])
1343: #endif
1344: )
1345: setCWD(argp[1]);
1346: else
1347: getCWD(); /* After we setup curbuf in case we have to getwd() */
1348: }
1349:
1350: HomeDir = getenv("HOME");
1351: if (HomeDir == NULL)
1352: HomeDir = "/";
1353: HomeLen = strlen(HomeDir);
1354:
1355: #ifdef UNIX
1356: # ifdef SYSV
1357: swritef(Mailbox, "/usr/mail/%s", getenv("LOGNAME"));
1358: # else
1359: swritef(Mailbox, "/usr/spool/mail/%s", getenv("USER"));
1360: # endif
1361: #endif
1362:
1363: InitKeymaps();
1364:
1365: ttinit(); /* initialize terminal (before ~/.joverc) */
1366: settout(ttbuf); /* not until we know baudrate */
1367: #ifndef MAC
1368: ResetTerm();
1369: #endif
1370:
1371: (void) joverc(Joverc); /* system wide .joverc */
1372: cp = 0;
1373: #if defined(MSDOS) || defined(UNIX)
1374: /* If a JOVERC environment variable is set, then use that instead */
1375: if ((cp = getenv("JOVERC")) && (*cp != '\0'))
1376: (void) joverc(cp);
1377: #endif /* MSDOS || UNIX */
1378: if (!scanvec(argv, "-j") && (!cp || *cp == '\0')) {
1379: char tmpbuf[100];
1380:
1381: swritef(tmpbuf, "%s/.joverc", HomeDir);
1382: (void) joverc(tmpbuf); /* .joverc in home directory */
1383: }
1384:
1385: #ifndef MSDOS
1386: if (scanvec(argv, "-r"))
1387: dorecover();
1388: if (scanvec(argv, "-rc"))
1389: FullRecover();
1390: #endif /* MSDOS */
1391:
1392: #ifdef MSDOS
1393: (void) signal(SIGINT, SIG_IGN);
1394: break_off(); /* disable ctrl-c checking */
1395: #endif /* MSDOS */
1396: #ifdef UNIX
1397: (void) signal(SIGHUP, finish);
1398: (void) signal(SIGINT, finish);
1399: (void) signal(SIGBUS, finish);
1400: (void) signal(SIGSEGV, finish);
1401: (void) signal(SIGPIPE, finish);
1402: (void) signal(SIGTERM, SIG_IGN);
1403: # if defined(TIOCGWINSZ) && defined(SIGWINCH)
1404: (void) signal(SIGWINCH, win_reshape);
1405: # endif
1406: /* set things up to update the modeline every UpdFreq seconds */
1407: (void) signal(SIGALRM, updmode);
1408: (void) alarm((unsigned) (UpdFreq - (time((time_t *) 0) % UpdFreq)));
1409: #endif /* UNIX */
1410: cl_scr(1);
1411: flusho();
1412: RedrawDisplay(); /* start the redisplay process. */
1413: DoKeys(YES);
1414: finish(0);
1415: }
1416:
1417: #ifdef MSDOS
1418:
1419: #include <dos.h>
1420:
1421: static char break_state;
1422:
1423: /* set the break state to off */
1424: private void
1425: break_off()
1426: {
1427: union REGS regs;
1428:
1429: regs.h.ah = 0x33; /* break status */
1430: regs.h.al = 0x00; /* request current state */
1431: intdos(®s, ®s);
1432: break_state = regs.h.dl;
1433: bdos(0x33, 0, 1); /* turn off break */
1434: }
1435:
1436: /* reset the break state */
1437: private void
1438: break_rst()
1439: {
1440: bdos(0x33, break_state, 1);
1441: }
1442: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.