|
|
1.1 root 1: /*************************************************************************
2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
3: * provided to you without charge for use only on a licensed Unix *
4: * system. You may copy JOVE provided that this notice is included with *
5: * the copy. You may not sell copies of this program or versions *
6: * modified for use on microcomputer systems, unless the copies are *
7: * included with a Unix system distribution and the source is provided. *
8: *************************************************************************/
9:
10: #include "jove.h"
11: #include "ctype.h"
12: #include <signal.h>
13:
14: struct cmd *
15: FindCmd(proc)
16: register int (*proc)();
17: {
18: register struct cmd *cp;
19:
20: for (cp = commands; cp->Name; cp++)
21: if (cp->c_proc == proc)
22: return cp;
23: return 0;
24: }
25:
26: int Interactive; /* True when we invoke with the command handler? */
27: char *ProcFmt = ": %f ";
28:
29: ExecCmd(cp)
30: data_obj *cp;
31: {
32: LastCmd = cp;
33: if (cp->Type & MAJOR_MODE)
34: SetMajor((cp->Type >> 8));
35: else if (cp->Type & MINOR_MODE)
36: TogMinor((cp->Type >> 8));
37: else switch (cp->Type&TYPEMASK) {
38: case MACRO:
39: do_macro((struct macro *) cp);
40: break;
41:
42: case FUNCTION:
43: {
44: struct cmd *cmd = (struct cmd *) cp;
45:
46: if (cmd->c_proc)
47: (*cmd->c_proc)();
48: }
49: }
50: }
51:
52: Line *
53: lastline(lp)
54: register Line *lp;
55: {
56: while (lp->l_next)
57: lp = lp->l_next;
58: return lp;
59: }
60:
61: Upper(c)
62: register int c;
63: {
64: return (islower(c) ? toupper(c) : c);
65: }
66:
67: int alarmed = 0;
68:
69: char key_strokes[100];
70: static char *key_p = key_strokes;
71:
72: init_strokes()
73: {
74: key_strokes[0] = 0;
75: key_p = key_strokes;
76: }
77:
78: add_stroke(c)
79: {
80: if (key_p + 5 > &key_strokes[(sizeof key_strokes) - 1])
81: key_p = key_strokes;
82: sprintf(key_p, "%p ", c);
83: key_p += strlen(key_p);
84: }
85:
86: slowpoke()
87: {
88: alarmed++;
89: f_mess(key_strokes);
90: }
91:
92: #ifdef BSD4_2
93: # define N_SEC 1 /* will be precisely 1 second on 4.2 */
94: #else
95: # define N_SEC 2 /* but from 0 to 2 seconds otherwise */
96: #endif
97:
98: waitchar()
99: {
100: #ifdef EUNICE
101: return getch();
102: #endif
103: unsigned int old_time;
104: int c;
105: int (*oldproc)();
106:
107: alarmed = 0;
108: oldproc = signal(SIGALRM, slowpoke);
109:
110: if ((old_time = alarm((unsigned) N_SEC)) == 0)
111: old_time = UpdFreq;
112: c = getch();
113: (void) alarm(old_time);
114: (void) signal(SIGALRM, oldproc);
115:
116: return c;
117: }
118:
119: /* dir > 0 means forward; else means backward. */
120:
121: char *
122: StrIndex(dir, buf, charpos, what)
123: char *buf,
124: what;
125: {
126: char *cp = &buf[charpos],
127: c;
128:
129: if (dir > 0) {
130: while (c = *cp++)
131: if (c == what)
132: return (cp - 1);
133: } else {
134: while (cp >= buf && (c = *cp--))
135: if (c == what)
136: return (cp + 1);
137: }
138: return 0;
139: }
140:
141: blnkp(buf)
142: register char *buf;
143: {
144: register char c;
145:
146: while ((c = *buf++) && (c == ' ' || c == '\t'))
147: ;
148: return c == 0; /* It's zero if we got to the end of the Line */
149: }
150:
151: Line *
152: next_line(line, num)
153: register Line *line;
154: register int num;
155: {
156: if (num < 0)
157: return prev_line(line, -num);
158: if (line)
159: while (--num >= 0 && line->l_next != 0)
160: line = line->l_next;
161: return line;
162: }
163:
164: Line *
165: prev_line(line, num)
166: register Line *line;
167: register int num;
168: {
169: if (num < 0)
170: return next_line(line, -num);
171: if (line)
172: while (--num >= 0 && line->l_prev != 0)
173: line = line->l_prev;
174: return line;
175: }
176:
177: DotTo(line, col)
178: Line *line;
179: {
180: Bufpos bp;
181:
182: bp.p_line = line;
183: bp.p_char = col;
184: SetDot(&bp);
185: }
186:
187: /* If bp->p_line is != current line, then save current line. Then set dot
188: to bp->p_line, and if they weren't equal get that line into linebuf. */
189:
190: SetDot(bp)
191: register Bufpos *bp;
192: {
193: register int notequal;
194:
195: if (bp == 0)
196: return;
197:
198: notequal = bp->p_line != curline;
199: if (notequal)
200: lsave();
201: if (bp->p_line)
202: curline = bp->p_line;
203: curchar = bp->p_char;
204: if (notequal)
205: getDOT();
206: }
207:
208: ToLast()
209: {
210: SetLine(curbuf->b_last);
211: Eol();
212: }
213:
214: int MarkThresh = 22; /* Average screen size ... */
215: static int line_diff;
216:
217: LineDist(nextp, endp)
218: register Line *nextp,
219: *endp;
220: {
221: (void) inorder(nextp, 0, endp, 0);
222: return line_diff;
223: }
224:
225: inorder(nextp, char1, endp, char2)
226: register Line *nextp,
227: *endp;
228: {
229: int count = 0;
230: register Line *prevp = nextp;
231:
232: line_diff = 0;
233: if (nextp == endp)
234: return char1 < char2;
235:
236: while (nextp || prevp) {
237: if (nextp == endp || prevp == endp)
238: break;
239: if (nextp)
240: nextp = nextp->l_next;
241: if (prevp)
242: prevp = prevp->l_prev;
243: count++;
244: }
245: if (nextp == 0 && prevp == 0)
246: return -1;
247: line_diff = count;
248:
249: return nextp == endp;
250: }
251:
252: PushPntp(line)
253: register Line *line;
254: {
255: exp_p = 0;
256: if (LineDist(curline, line) >= MarkThresh)
257: SetMark();
258: }
259:
260: ToFirst()
261: {
262: SetLine(curbuf->b_first);
263: }
264:
265: length(line)
266: Line *line;
267: {
268: return strlen(lcontents(line));
269: };
270:
271: to_word(dir)
272: register int dir;
273: {
274: register char c;
275:
276: if (dir > 0) {
277: while ((c = linebuf[curchar]) != 0 && !isword(c))
278: curchar++;
279: if (eolp()) {
280: if (curline->l_next == 0)
281: return;
282: SetLine(curline->l_next);
283: to_word(dir);
284: return;
285: }
286: } else {
287: while (!bolp() && (c = linebuf[curchar - 1], !isword(c)))
288: --curchar;
289: if (bolp()) {
290: if (curline->l_prev == 0)
291: return;
292: SetLine(curline->l_prev);
293: Eol();
294: to_word(dir);
295: }
296: }
297: }
298:
299: /* Are there any modified buffers? Allp means include B_PROCESS and
300: B_IPROCESS buffers in the check, but never scratch buffers. */
301:
302: ModBufs(allp)
303: {
304: register Buffer *b;
305:
306: for (b = world; b != 0; b = b->b_next) {
307: if (b->b_type == B_SCRATCH)
308: continue;
309: if ((b->b_type == B_FILE || allp) && IsModified(b))
310: return 1;
311: }
312: return 0;
313: }
314:
315: char *
316: filename(b)
317: register Buffer *b;
318: {
319: return b->b_fname ? pr_name(b->b_fname) : "[No file]";
320: }
321:
322: char *
323: itoa(num)
324: register int num;
325: {
326: static char line[15];
327:
328: sprintf(line, "%d", num);
329: return line;
330: }
331:
332: min(a, b)
333: register int a,
334: b;
335: {
336: return (a < b) ? a : b;
337: }
338:
339: max(a, b)
340: register int a,
341: b;
342: {
343: return (a > b) ? a : b;
344: }
345:
346: tiewind(wp, bp)
347: register Window *wp;
348: register Buffer *bp;
349: {
350: UpdModLine++; /* Kludge ... but speeds things up considerably */
351: wp->w_line = bp->b_dot;
352: wp->w_char = bp->b_char;
353: wp->w_bufp = bp;
354: }
355:
356: extern int Jr_Len;
357:
358: char *
359: lcontents(line)
360: register Line *line;
361: {
362: if (line == curline)
363: return linebuf;
364: else
365: return lbptr(line);
366: }
367:
368: char *
369: ltobuf(line, buf)
370: Line *line;
371: char *buf;
372: {
373: if (line == curline) {
374: if (buf != linebuf)
375: strcpy(buf, linebuf);
376: Jr_Len = strlen(linebuf);
377: } else
378: (void) getline(line->l_dline, buf);
379: return buf;
380: }
381:
382: /* Return none-zero if we had to rearrange the order. */
383:
384: fixorder(line1, char1, line2, char2)
385: register Line **line1,
386: **line2;
387: register int *char1,
388: *char2;
389: {
390: Line *tline;
391: int tchar;
392:
393: if (inorder(*line1, *char1, *line2, *char2))
394: return 0;
395:
396: tline = *line1;
397: tchar = *char1;
398: *line1 = *line2;
399: *char1 = *char2;
400: *line2 = tline;
401: *char2 = tchar;
402:
403: return 1;
404: }
405:
406: inlist(first, what)
407: register Line *first,
408: *what;
409: {
410: while (first) {
411: if (first == what)
412: return 1;
413: first = first->l_next;
414: }
415: return 0;
416: }
417:
418: /* Make `buf' modified and tell the redisplay code to update the modeline
419: if it will need to be changed. */
420:
421: int ModCount = 0;
422:
423: modify()
424: {
425: extern int DOLsave;
426:
427: if (!curbuf->b_modified)
428: UpdModLine++;
429: curbuf->b_modified++;
430: DOLsave++;
431: if (!Asking)
432: ModCount++;
433: }
434:
435: unmodify()
436: {
437: if (curbuf->b_modified)
438: UpdModLine++;
439: curbuf->b_modified = 0;
440: }
441:
442: numcomp(s1, s2)
443: register char *s1,
444: *s2;
445: {
446: register int count = 0;
447:
448: while (*s1 != 0 && *s1++ == *s2++)
449: count++;
450: return count;
451: }
452:
453: char *
454: copystr(str)
455: char *str;
456: {
457: char *val = emalloc(strlen(str) + 1);
458:
459: strcpy(val, str);
460: return val;
461: }
462:
463: #ifndef byte_copy
464: byte_copy(from, to, count)
465: register char *from,
466: *to;
467: register int count;
468: {
469: while (--count >= 0)
470: *to++ = *from++;
471: }
472: #endif
473:
474: len_error(flag)
475: {
476: char *mesg = "[line too long]";
477:
478: (flag == COMPLAIN) ? complain(mesg) : error(mesg);
479: }
480:
481: /* Insert num number of c's at offset atchar in a linebuf of LBSIZE */
482:
483: ins_c(c, buf, atchar, num, max)
484: char c, *buf;
485: {
486: register char *pp, *pp1;
487: register int len;
488: int numchars; /* Number of characters to copy forward */
489:
490: if (num <= 0)
491: return;
492: len = atchar + strlen(&buf[atchar]);
493: if (len + num >= max)
494: len_error(COMPLAIN);
495: pp = &buf[len + 1]; /* + 1 so we can --pp (not pp--) */
496: pp1 = &buf[len + num + 1];
497: numchars = len - atchar;
498: while (numchars-- >= 0)
499: *--pp1 = *--pp;
500: pp = &buf[atchar];
501: while (--num >= 0)
502: *pp++ = c;
503: }
504:
505: TwoBlank()
506: {
507: register Line *next = curline->l_next;
508:
509: return ((next != 0) &&
510: (*(lcontents(next)) == '\0') &&
511: (next->l_next != 0) &&
512: (*(lcontents(next->l_next)) == '\0'));
513: }
514:
515: linecopy(onto, atchar, from)
516: register char *onto,
517: *from;
518: {
519: register char *endp = &onto[LBSIZE - 2];
520:
521: onto += atchar;
522:
523: while (*onto = *from++)
524: if (onto++ >= endp)
525: len_error(ERROR);
526: }
527:
528: char *
529: IOerr(err, file)
530: char *err, *file;
531: {
532: return sprint("Couldn't %s \"%s\".", err, file);
533: }
534:
535: pclose(p)
536: int *p;
537: {
538: (void) close(p[0]);
539: (void) close(p[1]);
540: }
541:
542: dopipe(p)
543: int p[];
544: {
545: if (pipe(p) == -1)
546: complain("[Pipe failed]");
547: }
548:
549: /* NOSTRICT */
550:
551: char *
552: emalloc(size)
553: {
554: char *ptr;
555:
556: if (ptr = malloc((unsigned) size))
557: return ptr;
558: /* Try garbage collecting lines */
559: GCchunks();
560: if (ptr = malloc((unsigned) size))
561: return ptr;
562: /* Uh ... Oh screw it! */
563: error("[Out of memory] ");
564: /* NOTREACHED */
565: }
566:
567: /* Return the basename of file F. */
568:
569: char *
570: basename(f)
571: register char *f;
572: {
573: register char *cp;
574:
575: if (cp = rindex(f, '/'))
576: return cp + 1;
577: else
578: return f;
579: }
580:
581: push_env(savejmp)
582: jmp_buf savejmp;
583: {
584: byte_copy((char *) mainjmp, (char *) savejmp, sizeof (jmp_buf));
585: }
586:
587: pop_env(savejmp)
588: jmp_buf savejmp;
589: {
590: byte_copy((char *) savejmp, (char *) mainjmp, sizeof (jmp_buf));
591: }
592:
593: #ifdef LOAD_AV
594: # ifdef BSD4_2
595: # ifdef PURDUE_EE
596:
597: get_la(dp)
598: double *dp;
599: {
600: *dp = (double) loadav(0) / 100.0;
601: }
602:
603: # else PURDUE_EE
604:
605: #include <nlist.h>
606:
607: static struct nlist nl[] = {
608: { "_avenrun" },
609: #define X_AVENRUN 0
610: { "" }
611: };
612:
613: get_la(dp)
614: double *dp;
615: {
616: double avenrun[3];
617: static int kmem = 0;
618:
619: if (kmem == -1) {
620: *dp = 4.0; /* So shell commands will say "Chugging" */
621: return;
622: } else if (kmem == 0) {
623: if ((kmem = open("/dev/kmem", 0)) == -1) {
624: f_mess("Can't open kmem for load average.");
625: *dp = 4.0;
626: return;
627: }
628: nlist("/vmunix", nl);
629: }
630: lseek(kmem, (long) nl[X_AVENRUN].n_value, 0);
631: read(kmem, (char *) avenrun, sizeof(avenrun));
632: *dp = avenrun[0];
633: }
634:
635: # endif PURDUE_EE
636: # else BSD4_2
637:
638: get_la(dp)
639: double *dp;
640: {
641: short avg[3];
642:
643: gldav(avg);
644: *dp = (double) avg[0] / 256;
645: }
646:
647: # endif BSD4_2
648: #endif LOAD_AV
649:
650: /* get the time buf, designated by *timep, from FROM to TO. */
651: char *
652: get_time(timep, buf, from, to)
653: char *buf;
654: time_t *timep;
655: {
656: time_t now;
657: char *cp;
658: extern char *ctime();
659:
660: if (timep != 0)
661: now = *timep;
662: else
663: (void) time(&now);
664: cp = ctime(&now) + from;
665: if (to == -1)
666: cp[strlen(cp) - 1] = '\0'; /* Get rid of \n */
667: else
668: cp[to - from] = '\0';
669: if (buf) {
670: strcpy(buf, cp);
671: return buf;
672: } else
673: return cp;
674: }
675:
676: /* Return length of null terminated string. */
677:
678: strlen(s)
679: register char *s;
680: {
681: register char *base = s + 1; /* Can you say kludge? */
682:
683: while (*s++)
684: ;
685: return (s - base);
686: }
687:
688: char *
689: index(s, c)
690: register char *s;
691: register int c;
692: {
693: register int c1;
694:
695: if (c != 0)
696: while (c1 = *s++)
697: if (c == c1)
698: return s - 1;
699: return 0;
700: }
701:
702: strcmp(s1, s2)
703: register char *s1,
704: *s2;
705: {
706: if (!s1 || !s2)
707: return 1; /* Which is not zero ... */
708: while (*s1 == *s2++)
709: if (*s1++ == '\0')
710: return 0;
711: return (*s1 - *--s2);
712: }
713:
714: casecmp(s1, s2)
715: register char *s1,
716: *s2;
717: {
718: if (!s1 || !s2)
719: return 1; /* Which is not zero ... */
720: while (*s1 == *s2++ || Upper(*s1) == Upper(s2[-1]))
721: if (*s1++ == '\0')
722: return 0;
723: return (*s1 - *--s2);
724: }
725:
726: casencmp(s1, s2, n)
727: register char *s1,
728: *s2;
729: register int n;
730: {
731: if (!s1 || !s2)
732: return 1; /* Which is not zero ... */
733: while (--n >= 0 && (*s1 == *s2++ || Upper(*s1) == Upper(s2[-1])))
734: if (*s1++ == '\0')
735: return 0;
736: return ((n < 0) ? 0 : *s1 - *--s2);
737: }
738:
739: null_ncpy(to, from, n)
740: char *to,
741: *from;
742: {
743: (void) strncpy(to, from, n);
744: to[n] = '\0';
745: }
746:
747: strcpy(t, f)
748: register char *t,
749: *f;
750: {
751: while (*t++ = *f++)
752: ;
753: }
754:
755: /* Tries to pause for delay/10 seconds OR until a character is typed
756: at the keyboard. This works well on BSD4_2 and not so well on the
757: rest. Returns 1 if it returned because of keyboard input, or 0
758: otherwise. */
759:
760: SitFor(delay)
761: int delay;
762: {
763: #ifdef BSD4_2
764: #include <sys/time.h>
765:
766: struct timeval timer;
767: int readfds = 1,
768: writefds = 0,
769: exceptfds = 0;
770:
771: timer.tv_sec = (delay / 10);
772: timer.tv_usec = (delay % 10) * 100000;
773:
774: if (charp())
775: return 1;
776: /* gross that I had to snarf this from getch() */
777: if (!UpdMesg && !Asking) { /* Don't erase if we are asking */
778: if (mesgbuf[0] && !errormsg)
779: message(NullStr);
780: }
781: redisplay();
782: return select(1, &readfds, &writefds, &exceptfds, &timer);
783: #else
784: static float cps[] = {
785: 0.0,
786: 5.0,
787: 7.5,
788: 11.0,
789: 13.4,
790: 15.0,
791: 20.0,
792: 30.0,
793: 60.0,
794: 120.0,
795: 180.0,
796: 240.0,
797: 480.0,
798: 960.0,
799: 1920.0,
800: 1920.0,
801: };
802: float nsecs;
803: register int nchars;
804:
805: if (charp())
806: return 1;
807: nsecs = (float) delay / 10;
808: nchars = (int) (nsecs * cps[ospeed]);
809: redisplay();
810: while ((--nchars > 0) && !InputPending) {
811: putchar(0);
812: if (OkayAbort) {
813: OkayAbort = 0;
814: InputPending = charp();
815: }
816: }
817: return InputPending;
818: #endif
819: }
820:
821: sindex(pattern, string)
822: register char *pattern,
823: *string;
824: {
825: register int len = strlen(pattern);
826:
827: while (*string != '\0') {
828: if (*pattern == *string && strncmp(pattern, string, len) == 0)
829: return TRUE;
830: string++;
831: }
832: return FALSE;
833: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.