|
|
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: #include "jove.h"
9: #include "ctype.h"
10: #include "termcap.h"
11: #include <signal.h>
12:
13: #ifdef MAC
14: # include "mac.h"
15: #else
16: # include <varargs.h>
17: #endif
18:
19: #ifdef MSDOS
20: #include <time.h>
21: #endif
22:
23: struct cmd *
24: FindCmd(proc)
25: register void (*proc)();
26: {
27: register struct cmd *cp;
28:
29: for (cp = commands; cp->Name; cp++)
30: if (cp->c_proc == proc)
31: return cp;
32: return 0;
33: }
34:
35: int Interactive; /* True when we invoke with the command handler? */
36: data_obj *LastCmd;
37: char *ProcFmt = ": %f ";
38:
39: void
40: ExecCmd(cp)
41: data_obj *cp;
42: {
43: LastCmd = cp;
44: if (cp->Type & MAJOR_MODE)
45: SetMajor((cp->Type >> 8));
46: else if (cp->Type & MINOR_MODE)
47: TogMinor((cp->Type >> 8));
48: else switch (cp->Type&TYPEMASK) {
49: case MACRO:
50: do_macro((struct macro *) cp);
51: break;
52:
53: case FUNCTION:
54: {
55: struct cmd *cmd = (struct cmd *) cp;
56:
57: if (cmd->c_proc)
58: (*cmd->c_proc)();
59: }
60: }
61: }
62:
63: Line *
64: lastline(lp)
65: register Line *lp;
66: {
67: register Line *next;
68:
69: while (next = lp->l_next)
70: lp = next;
71: return lp;
72: }
73:
74: private int *slowp = 0;
75:
76: char key_strokes[100];
77: private char *key_p = key_strokes;
78:
79: void
80: init_strokes()
81: {
82: key_strokes[0] = 0;
83: key_p = key_strokes;
84: }
85:
86: void
87: add_stroke(c)
88: {
89: if (key_p + 5 > &key_strokes[(sizeof key_strokes) - 1])
90: key_p = key_strokes;
91: sprintf(key_p, "%p ", c);
92: key_p += strlen(key_p);
93: }
94:
95: void
96: slowpoke()
97: {
98: if (slowp)
99: *slowp = YES;
100: f_mess(key_strokes);
101: }
102:
103: #ifdef UNIX
104: # ifdef BSD4_2
105: # define N_SEC 1 /* will be precisely 1 second on 4.2 */
106: # else
107: # define N_SEC 2 /* but from 1 to 2 seconds otherwise */
108: # endif
109: #else /* MSDOS or MAC */
110: # define N_SEC 1
111: int in_macro();
112: #endif /* UNIX */
113:
114: int
115: waitchar(slow)
116: int *slow;
117: {
118: #ifdef UNIX
119: unsigned int old_time;
120: int c;
121: int (*oldproc)();
122: #else /* MSDOS or MAC */
123: long sw, time();
124: #endif /* UNIX */
125:
126: slowp = slow;
127: if (slow)
128: *slow = NO;
129: #ifdef UNIX
130: oldproc = signal(SIGALRM, slowpoke);
131:
132: if ((old_time = alarm((unsigned) N_SEC)) == 0)
133: old_time = UpdFreq;
134: c = getch();
135: (void) alarm(old_time);
136: (void) signal(SIGALRM, oldproc);
137:
138: return c;
139: #else /* MSDOS or MAC */
140: #ifdef MAC
141: Keyonly = 1;
142: if(charp() || in_macro()) return getch(); /* to avoid flicker */
143: #endif
144: time(&sw);
145: sw += N_SEC;
146: while(time(NULL) <= sw)
147: if (charp() || in_macro())
148: return getch();
149: #ifdef MAC
150: menus_off();
151: #endif
152: slowpoke();
153: return getch();
154: #endif /* UNIX */
155: }
156:
157: /* dir > 0 means forward; else means backward. */
158:
159: char *
160: StrIndex(dir, buf, charpos, what)
161: char *buf,
162: what;
163: {
164: char *cp = &buf[charpos],
165: c;
166:
167: if (dir > 0) {
168: while (c = *cp++)
169: if (c == what)
170: return (cp - 1);
171: } else {
172: while (cp >= buf && (c = *cp--))
173: if (c == what)
174: return (cp + 1);
175: }
176: return 0;
177: }
178:
179: int
180: blnkp(buf)
181: register char *buf;
182: {
183: register char c;
184:
185: while ((c = *buf++) && (c == ' ' || c == '\t'))
186: ;
187: return c == 0; /* It's zero if we got to the end of the Line */
188: }
189:
190: Line *
191: next_line(line, num)
192: register Line *line;
193: register int num;
194: {
195: if (num < 0)
196: return prev_line(line, -num);
197: if (line)
198: while (--num >= 0 && line->l_next != 0)
199: line = line->l_next;
200: return line;
201: }
202:
203: Line *
204: prev_line(line, num)
205: register Line *line;
206: register int num;
207: {
208: if (num < 0)
209: return next_line(line, -num);
210: if (line)
211: while (--num >= 0 && line->l_prev != 0)
212: line = line->l_prev;
213: return line;
214: }
215:
216: void
217: DotTo(line, col)
218: Line *line;
219: {
220: Bufpos bp;
221:
222: bp.p_line = line;
223: bp.p_char = col;
224: SetDot(&bp);
225: }
226:
227: /* If bp->p_line is != current line, then save current line. Then set dot
228: to bp->p_line, and if they weren't equal get that line into linebuf. */
229:
230: void
231: SetDot(bp)
232: register Bufpos *bp;
233: {
234: register int notequal;
235:
236: if (bp == 0)
237: return;
238:
239: notequal = bp->p_line != curline;
240: if (notequal)
241: lsave();
242: if (bp->p_line)
243: curline = bp->p_line;
244: if (notequal)
245: getDOT();
246: curchar = bp->p_char;
247: if (curchar > length(curline))
248: curchar = length(curline);
249: }
250:
251: void
252: ToLast()
253: {
254: SetLine(curbuf->b_last);
255: Eol();
256: }
257:
258: int MarkThresh = 22; /* average screen size ... */
259: static int line_diff;
260:
261: int
262: LineDist(nextp, endp)
263: register Line *nextp,
264: *endp;
265: {
266: (void) inorder(nextp, 0, endp, 0);
267: return line_diff;
268: }
269:
270: int
271: inorder(nextp, char1, endp, char2)
272: register Line *nextp,
273: *endp;
274: {
275: int count = 0;
276: register Line *prevp = nextp;
277:
278: line_diff = 0;
279: if (nextp == endp)
280: return char1 < char2;
281:
282: while (nextp || prevp) {
283: if (nextp == endp || prevp == endp)
284: break;
285: if (nextp)
286: nextp = nextp->l_next;
287: if (prevp)
288: prevp = prevp->l_prev;
289: count += 1;
290: }
291: if (nextp == 0 && prevp == 0)
292: return -1;
293: line_diff = count;
294:
295: return nextp == endp;
296: }
297:
298: void
299: PushPntp(line)
300: register Line *line;
301: {
302: if (LineDist(curline, line) >= MarkThresh)
303: set_mark();
304: }
305:
306: void
307: ToFirst()
308: {
309: SetLine(curbuf->b_first);
310: }
311:
312: int
313: length(line)
314: Line *line;
315: {
316: return strlen(lcontents(line));
317: };
318:
319: void
320: to_word(dir)
321: register int dir;
322: {
323: register char c;
324:
325: if (dir == FORWARD) {
326: while ((c = linebuf[curchar]) != 0 && !isword(c))
327: curchar += 1;
328: if (eolp()) {
329: if (curline->l_next == 0)
330: return;
331: SetLine(curline->l_next);
332: to_word(dir);
333: return;
334: }
335: } else {
336: while (!bolp() && (c = linebuf[curchar - 1], !isword(c)))
337: curchar -= 1;
338: if (bolp()) {
339: if (curline->l_prev == 0)
340: return;
341: SetLine(curline->l_prev);
342: Eol();
343: to_word(dir);
344: }
345: }
346: }
347:
348: /* Are there any modified buffers? Allp means include B_PROCESS
349: buffers in the check. */
350:
351: int
352: ModBufs(allp)
353: {
354: register Buffer *b;
355:
356: for (b = world; b != 0; b = b->b_next) {
357: if (b->b_type == B_SCRATCH)
358: continue;
359: if ((b->b_type == B_FILE || allp) && IsModified(b))
360: return 1;
361: }
362: return 0;
363: }
364:
365: char *
366: filename(b)
367: register Buffer *b;
368: {
369: return b->b_fname ? pr_name(b->b_fname, YES) : "[No file]";
370: }
371:
372: char *
373: itoa(num)
374: register int num;
375: {
376: static char line[15];
377:
378: sprintf(line, "%d", num);
379: return line;
380: }
381:
382: int
383: min(a, b)
384: register int a,
385: b;
386: {
387: return (a < b) ? a : b;
388: }
389:
390: int
391: max(a, b)
392: register int a,
393: b;
394: {
395: return (a > b) ? a : b;
396: }
397:
398: void
399: tiewind(w, bp)
400: register Window *w;
401: register Buffer *bp;
402: {
403: int not_tied = (w->w_bufp != bp);
404:
405: UpdModLine = YES; /* kludge ... but speeds things up considerably */
406: w->w_line = bp->b_dot;
407: w->w_char = bp->b_char;
408: w->w_bufp = bp;
409: if (not_tied)
410: CalcWind(w); /* ah, this has been missing since the
411: beginning of time! */
412: }
413:
414: extern int Jr_Len;
415:
416: char *
417: lcontents(line)
418: register Line *line;
419: {
420: if (line == curline)
421: return linebuf;
422: else
423: return lbptr(line);
424: }
425:
426: char *
427: ltobuf(line, buf)
428: Line *line;
429: char *buf;
430: {
431: if (line == curline) {
432: if (buf != linebuf)
433: strcpy(buf, linebuf);
434: Jr_Len = strlen(linebuf);
435: } else
436: getline(line->l_dline, buf);
437: return buf;
438: }
439:
440: void
441: DOTsave(buf)
442: Bufpos *buf;
443: {
444: buf->p_line = curline;
445: buf->p_char = curchar;
446: }
447:
448: /* Return none-zero if we had to rearrange the order. */
449:
450: int
451: fixorder(line1, char1, line2, char2)
452: register Line **line1,
453: **line2;
454: register int *char1,
455: *char2;
456: {
457: Line *tline;
458: int tchar;
459:
460: if (inorder(*line1, *char1, *line2, *char2))
461: return 0;
462:
463: tline = *line1;
464: tchar = *char1;
465: *line1 = *line2;
466: *char1 = *char2;
467: *line2 = tline;
468: *char2 = tchar;
469:
470: return 1;
471: }
472:
473: int
474: inlist(first, what)
475: register Line *first,
476: *what;
477: {
478: while (first) {
479: if (first == what)
480: return 1;
481: first = first->l_next;
482: }
483: return 0;
484: }
485:
486: /* Make `buf' (un)modified and tell the redisplay code to update the modeline
487: if it will need to be changed. */
488:
489: int ModCount = 0;
490:
491: void
492: modify()
493: {
494: extern int DOLsave;
495:
496: if (!curbuf->b_modified) {
497: UpdModLine = YES;
498: curbuf->b_modified = YES;
499: }
500: DOLsave = YES;
501: if (!Asking)
502: ModCount += 1;
503: }
504:
505: void
506: unmodify()
507: {
508: if (curbuf->b_modified) {
509: UpdModLine = YES;
510: curbuf->b_modified = NO;
511: }
512: }
513:
514: int
515: numcomp(s1, s2)
516: register char *s1,
517: *s2;
518: {
519: register int count = 0;
520:
521: while (*s1 != 0 && *s1++ == *s2++)
522: count += 1;
523: return count;
524: }
525:
526: char *
527: copystr(str)
528: char *str;
529: {
530: char *val;
531:
532: if (str == 0)
533: return 0;
534: val = emalloc(strlen(str) + 1);
535:
536: strcpy(val, str);
537: return val;
538: }
539:
540: #ifndef byte_copy
541: void
542: byte_copy(from, to, count)
543: register char *from,
544: *to;
545: register int count;
546: {
547: while (--count >= 0)
548: *to++ = *from++;
549: }
550: #endif
551:
552: void
553: len_error(flag)
554: {
555: char *mesg = "[line too long]";
556:
557: if (flag == COMPLAIN)
558: complain(mesg);
559: else
560: error(mesg);
561: }
562:
563: /* Insert num number of c's at offset atchar in a linebuf of LBSIZE */
564:
565: void
566: ins_c(c, buf, atchar, num, max)
567: char c, *buf;
568: {
569: register char *pp, *pp1;
570: register int len;
571: int numchars; /* number of characters to copy forward */
572:
573: if (num <= 0)
574: return;
575: len = atchar + strlen(&buf[atchar]);
576: if (len + num >= max)
577: len_error(COMPLAIN);
578: pp = &buf[len + 1]; /* + 1 so we can --pp (not pp--) */
579: pp1 = &buf[len + num + 1];
580: numchars = len - atchar;
581: while (numchars-- >= 0)
582: *--pp1 = *--pp;
583: pp = &buf[atchar];
584: while (--num >= 0)
585: *pp++ = c;
586: }
587:
588: int
589: TwoBlank()
590: {
591: register Line *next = curline->l_next;
592:
593: return ((next != 0) &&
594: (*(lcontents(next)) == '\0') &&
595: (next->l_next != 0) &&
596: (*(lcontents(next->l_next)) == '\0'));
597: }
598:
599: void
600: linecopy(onto, atchar, from)
601: register char *onto,
602: *from;
603: {
604: register char *endp = &onto[LBSIZE - 2];
605:
606: onto += atchar;
607:
608: while (*onto = *from++)
609: if (onto++ >= endp)
610: len_error(ERROR);
611: }
612:
613: char *
614: IOerr(err, file)
615: char *err, *file;
616: {
617: return sprint("Couldn't %s \"%s\".", err, file);
618: }
619:
620: #ifdef UNIX
621: void
622: pclose(p)
623: int *p;
624: {
625: (void) close(p[0]);
626: (void) close(p[1]);
627: }
628:
629: void
630: dopipe(p)
631: int p[];
632: {
633: if (pipe(p) == -1)
634: complain("[Pipe failed]");
635: }
636:
637: #endif /* UNIX */
638: /* NOSTRICT */
639:
640: char *
641: emalloc(size)
642: {
643: register char *ptr;
644:
645: if (ptr = malloc((unsigned) size))
646: return ptr;
647: /* Try garbage collecting lines */
648: GCchunks();
649: if (ptr = malloc((unsigned) size))
650: return ptr;
651: /* Uh ... Oh screw it! */
652: error("[Out of memory] ");
653: /* NOTREACHED */
654: }
655:
656: /* Return the basename of file F. */
657:
658: char *
659: basename(f)
660: register char *f;
661: {
662: register char *cp;
663:
664: if (cp = rindex(f, '/'))
665: return cp + 1;
666: else
667: #ifdef MSDOS
668: if (cp = rindex(f, '\\'))
669: return cp + 1;
670: else
671: if (cp = rindex(f, ':'))
672: return cp + 1;
673: #endif /* MSDOS */
674: return f;
675: }
676:
677: void
678: push_env(savejmp)
679: jmp_buf savejmp;
680: {
681: byte_copy((char *) mainjmp, (char *) savejmp, sizeof (jmp_buf));
682: }
683:
684: void
685: pop_env(savejmp)
686: jmp_buf savejmp;
687: {
688: byte_copy((char *) savejmp, (char *) mainjmp, sizeof (jmp_buf));
689: }
690:
691: #ifdef LOAD_AV
692: # if defined(BSD4_2) && !defined(BSD2_10)
693: # if defined(PURDUE_EE) && (defined(vax) || defined(gould))
694:
695: void
696: get_la(dp)
697: double *dp;
698: {
699: *dp = (double) loadav(0) / 100.0;
700: }
701:
702: # else /* !PURDUE_EE || (!vax && !gould) */
703:
704: #ifdef sun
705: # include <sys/param.h>
706: #endif
707: #include <nlist.h>
708:
709: static struct nlist nl[] = {
710: { "_avenrun" },
711: #define X_AVENRUN 0
712: { "" }
713: };
714:
715: void
716: get_la(dp)
717: double *dp;
718: {
719: #ifdef sun
720: long avenrun[3];
721: #else
722: double avenrun[3];
723: #endif
724: static int kmem = 0;
725:
726: if (kmem == -1) {
727: *dp = 4.0; /* So shell commands will say "Chugging" */
728: return;
729: } else if (kmem == 0) {
730: if ((kmem = open("/dev/kmem", 0)) == -1) {
731: f_mess("Can't open kmem for load average.");
732: *dp = 4.0;
733: return;
734: }
735: nlist("/vmunix", nl);
736: }
737: lseek(kmem, (long) nl[X_AVENRUN].n_value, 0);
738: read(kmem, (char *) avenrun, sizeof(avenrun));
739: #ifdef sun
740: *dp = (double) avenrun[0] / FSCALE;
741: #else
742: *dp = avenrun[0];
743: #endif
744: }
745:
746: # endif
747: # else /* !BSD4_2 || BSD2_10 */
748:
749: void
750: get_la(dp)
751: double *dp;
752: {
753: short avg[3];
754:
755: gldav(avg);
756: *dp = (double) avg[0] / 256;
757: }
758:
759: # endif
760: #endif /* LOAD_AV */
761:
762: /* get the time buf, designated by *timep, from FROM to TO. */
763: char *
764: get_time(timep, buf, from, to)
765: char *buf;
766: time_t *timep;
767: {
768: time_t now;
769: char *cp;
770: extern char *ctime();
771:
772: if (timep != 0)
773: now = *timep;
774: else
775: (void) time(&now);
776: cp = ctime(&now) + from;
777: #ifndef MSDOS
778: if (to == -1)
779: #else /* MSDOS */
780: if ((to == -1) && (cp[strlen(cp)-1] == '\n'))
781: #endif /* MSDOS */
782: cp[strlen(cp) - 1] = '\0'; /* Get rid of \n */
783: else
784: cp[to - from] = '\0';
785: if (buf) {
786: strcpy(buf, cp);
787: return buf;
788: } else
789: return cp;
790: }
791:
792: char *
793: index(s, c)
794: register char *s;
795: register int c;
796: {
797: register int c1;
798:
799: if (c != 0)
800: while (c1 = *s++)
801: if (c == c1)
802: return s - 1;
803: return 0;
804: }
805:
806: #if !(defined(MSDOS) || defined(MAC))
807:
808: int
809: strcmp(s1, s2)
810: register char *s1,
811: *s2;
812: {
813: if (!s1 || !s2)
814: return 1; /* which is not zero ... */
815: while (*s1 == *s2++)
816: if (*s1++ == '\0')
817: return 0;
818: return (*s1 - *--s2);
819: }
820:
821: #endif
822:
823: int
824: casecmp(s1, s2)
825: register char *s1,
826: *s2;
827: {
828: if (!s1 || !s2)
829: return 1; /* which is not zero ... */
830: while (CharUpcase(*s1) == CharUpcase(*s2++))
831: if (*s1++ == '\0')
832: return 0;
833: return (*s1 - *--s2);
834: }
835:
836: int
837: casencmp(s1, s2, n)
838: register char *s1,
839: *s2;
840: register int n;
841: {
842: if (!s1 || !s2)
843: return 1; /* which is not zero ... */
844: while (--n >= 0 && (CharUpcase(*s1) == CharUpcase(*s2++)))
845: if (*s1++ == '\0')
846: return 0;
847: return ((n < 0) ? 0 : *s1 - *--s2);
848: }
849:
850: void
851: null_ncpy(to, from, n)
852: char *to,
853: *from;
854: {
855: (void) strncpy(to, from, n);
856: to[n] = '\0';
857: }
858:
859: /* Tries to pause for delay/10 seconds OR until a character is typed
860: at the keyboard. This works well on BSD4_2 and not so well on the
861: rest. Returns 1 if it returned because of keyboard input, or 0
862: otherwise. */
863:
864: #ifdef MAC
865: void
866: SitFor(delay)
867: unsigned int delay;
868: {
869: long start,
870: end;
871:
872: #define Ticks (long *) 0x16A /* 1/60 sec */
873: Keyonly = 1;
874: redisplay();
875: start = *Ticks;
876:
877: end = start + delay * 6;
878: do
879: if (InputPending = charp())
880: break;
881: while (*Ticks < end);
882: }
883: #else /* not MAC */
884:
885: void
886: SitFor(delay)
887: unsigned int delay;
888: {
889: #ifndef MSDOS
890: #if defined(BSD4_2) && !defined(BSD2_10)
891: #include <sys/time.h>
892:
893: struct timeval timer;
894: long readfds = 1;
895:
896: timer.tv_sec = (delay / 10);
897: timer.tv_usec = (delay % 10) * 100000;
898:
899: if (charp())
900: return;
901: /* gross that I had to snarf this from getch() */
902: if (!UpdMesg && !Asking) { /* Don't erase if we are asking */
903: if (mesgbuf[0] && !errormsg)
904: message(NullStr);
905: }
906: redisplay();
907: select(1, &readfds, (long *)0, (long *)0, &timer);
908: #else
909: static int cps[] = {
910: 0,
911: 5,
912: 7,
913: 11,
914: 13,
915: 15,
916: 20,
917: 30,
918: 60,
919: 120,
920: 180,
921: 240,
922: 480,
923: 960,
924: 1920,
925: 1920,
926: };
927: register int nchars,
928: check_cnt;
929:
930: if (charp())
931: return;
932: nchars = (delay * cps[ospeed]) / 10;
933: check_cnt = BufSize;
934: redisplay();
935: while ((--nchars > 0) && !InputPending) {
936: putchar(0);
937: if (--check_cnt == 0) {
938: check_cnt = BufSize;
939: InputPending = charp();
940: }
941: }
942: #endif
943: #else /* MSDOS */
944: #include <bios.h>
945: #include <dos.h>
946:
947: long start,
948: end;
949: #ifndef IBMPC
950: struct dostime_t tc;
951: #endif
952:
953: redisplay();
954: #ifdef IBMPC
955: _bios_timeofday(_TIME_GETCLOCK, &start);
956: #else
957: _dos_gettime(&tc);
958: start = (long)(tc.hour*60L*60L*10L)+(long)(tc.minute*60L*10L)+
959: (long)(tc.second*10)+(long)(tc.hsecond/10);
960: #endif
961: end = (start + delay);
962: do {
963: if (InputPending = charp())
964: break;
965: #ifdef IBMPC
966: if (_bios_timeofday(_TIME_GETCLOCK, &start))
967: break; /* after midnight */
968: #else
969: start = (long)(tc.hour*60L*60L*10L)+(long)(tc.minute*60L*10L)+
970: (long)(tc.second*10)+(long)(tc.hsecond/10);
971: #endif
972: }
973: while (start < end);
974: #endif /* MSDOS */
975: }
976: #endif /* MAC */
977:
978: int
979: sindex(pattern, string)
980: register char *pattern,
981: *string;
982: {
983: register int len = strlen(pattern);
984:
985: while (*string != '\0') {
986: if (*pattern == *string && strncmp(pattern, string, len) == 0)
987: return TRUE;
988: string += 1;
989: }
990: return FALSE;
991: }
992:
993: void
994: make_argv(argv, ap)
995: register char *argv[];
996: va_list ap;
997: {
998: register char *cp;
999: register int i = 0;
1000:
1001: argv[i++] = va_arg(ap, char *);
1002: argv[i++] = basename(argv[0]);
1003: while (cp = va_arg(ap, char *))
1004: argv[i++] = cp;
1005: argv[i] = 0;
1006: }
1007:
1008: int
1009: pnt_line()
1010: {
1011: register Line *lp = curbuf->b_first;
1012: register int i;
1013:
1014: for (i = 0; lp != 0; i++, lp = lp->l_next)
1015: if (lp == curline)
1016: break;
1017: return i + 1;
1018: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.