|
|
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.