|
|
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: ! 12: ! 13: #ifdef MAC ! 14: # include "mac.h" ! 15: #else ! 16: # include <varargs.h> ! 17: # include <sys/stat.h> ! 18: #endif ! 19: ! 20: #include <signal.h> ! 21: ! 22: #ifdef MAC ! 23: # undef private ! 24: # define private ! 25: #endif ! 26: ! 27: #ifdef LINT_ARGS ! 28: private void ! 29: #ifdef ID_CHAR ! 30: DeTab(int, char *, char *, int, int), ! 31: DelChar(int, int, int), ! 32: InsChar(int, int, int, char *), ! 33: #endif ! 34: DoIDline(int), ! 35: do_cl_eol(int), ! 36: ModeLine(Window *), ! 37: mode_app(char *), ! 38: GotoDot(void), ! 39: UpdLine(int), ! 40: UpdWindow(Window *, int); ! 41: ! 42: private int ! 43: AddLines(int, int), ! 44: DelLines(int, int), ! 45: UntilEqual(int); ! 46: #else ! 47: private void ! 48: #ifdef ID_CHAR ! 49: DeTab(), ! 50: DelChar(), ! 51: InsChar(), ! 52: #endif ! 53: DoIDline(), ! 54: do_cl_eol(), ! 55: GotoDot(), ! 56: ModeLine(), ! 57: mode_app(), ! 58: UpdLine(), ! 59: UpdWindow(); ! 60: private int ! 61: AddLines(), ! 62: DelLines(), ! 63: UntilEqual(); ! 64: #endif /* LINT_ARGS */ ! 65: ! 66: #ifdef MAC ! 67: # undef private ! 68: # define private static ! 69: #endif ! 70: ! 71: int DisabledRedisplay = NO; ! 72: ! 73: /* Kludge windows gets called by the routines that delete lines from the ! 74: buffer. If the w->w_line or w->w_top are deleted and this procedure ! 75: is not called, the redisplay routine will barf. */ ! 76: ! 77: void ! 78: ChkWindows(line1, line2) ! 79: Line *line1; ! 80: register Line *line2; ! 81: { ! 82: register Window *w = fwind; ! 83: register Line *lp; ! 84: ! 85: do { ! 86: for (lp = line1->l_next; lp != line2->l_next; lp = lp->l_next) { ! 87: if (lp == w->w_top) ! 88: w->w_flags |= W_TOPGONE; ! 89: if (lp == w->w_line) ! 90: w->w_flags |= W_CURGONE; ! 91: } ! 92: w = w->w_next; ! 93: } while (w != fwind); ! 94: } ! 95: ! 96: extern int RingBell; ! 97: ! 98: void ! 99: redisplay() ! 100: { ! 101: extern int AbortCnt; ! 102: register Window *w = fwind; ! 103: int lineno, ! 104: done_ID = NO, ! 105: i; ! 106: register struct scrimage *des_p, ! 107: *phys_p; ! 108: ! 109: if (DisabledRedisplay == YES) ! 110: return; ! 111: curwind->w_line = curwind->w_bufp->b_dot; ! 112: curwind->w_char = curwind->w_bufp->b_char; ! 113: #ifdef MAC ! 114: InputPending = 0; ! 115: #else ! 116: if (InputPending = charp()) /* calls CheckEvent, which could */ ! 117: return; /* result in a call to rediplay(). We don't want that. */ ! 118: #endif ! 119: #ifdef JOB_CONTROL ! 120: if (UpdFreq) ! 121: sighold(SIGALRM); ! 122: #endif ! 123: if (RingBell) { ! 124: dobell(1); ! 125: RingBell = 0; ! 126: } ! 127: AbortCnt = BufSize; /* initialize this now */ ! 128: if (UpdMesg) ! 129: DrawMesg(YES); ! 130: ! 131: for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) { ! 132: UpdWindow(w, lineno); ! 133: lineno += w->w_height; ! 134: } ! 135: ! 136: UpdModLine = 0; /* Now that we've called update window, we can ! 137: assume that the modeline will be updated. But ! 138: if while redrawing the modeline the user types ! 139: a character, ModeLine() is free to set this on ! 140: again so that the modeline will be fully drawn ! 141: at the next redisplay. */ ! 142: ! 143: des_p = DesiredScreen; ! 144: phys_p = PhysScreen; ! 145: for (i = 0; i < ILI; i++, des_p++, phys_p++) { ! 146: if (!done_ID && (des_p->s_id != phys_p->s_id)) { ! 147: DoIDline(i); ! 148: done_ID = YES; ! 149: } ! 150: if ((des_p->s_flags & (DIRTY | L_MOD)) || ! 151: (des_p->s_id != phys_p->s_id) || ! 152: (des_p->s_vln != phys_p->s_vln) || ! 153: (des_p->s_offset != phys_p->s_offset)) ! 154: UpdLine(i); ! 155: if (InputPending) ! 156: goto ret; ! 157: } ! 158: ! 159: ! 160: if (Asking) { ! 161: Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, Asking))); ! 162: /* Nice kludge */ ! 163: flusho(); ! 164: } else ! 165: GotoDot(); ! 166: ret: ! 167: #ifdef JOB_CONTROL ! 168: if (UpdFreq) ! 169: sigrelse(SIGALRM); ! 170: #else ! 171: ; /* yuck */ ! 172: #endif ! 173: #ifdef MAC ! 174: if(Windchange) docontrols(); ! 175: #endif /* MAC */ ! 176: } ! 177: ! 178: #ifndef IBMPC ! 179: private void ! 180: dobell(n) ! 181: { ! 182: while (--n >= 0) { ! 183: #ifndef MAC ! 184: if (VisBell && VB) ! 185: putstr(VB); ! 186: else ! 187: putpad(BL, 1); ! 188: #else ! 189: SysBeep(5); ! 190: #endif ! 191: } ! 192: flusho(); ! 193: } ! 194: #endif /* IBMPC */ ! 195: ! 196: /* find_pos() returns the position on the line, that C_CHAR represents ! 197: in LINE */ ! 198: ! 199: int ! 200: find_pos(line, c_char) ! 201: Line *line; ! 202: { ! 203: return calc_pos(lcontents(line), c_char); ! 204: } ! 205: ! 206: int ! 207: calc_pos(lp, c_char) ! 208: register char *lp; ! 209: register int c_char; ! 210: { ! 211: register int pos = 0; ! 212: register int c; ! 213: ! 214: ! 215: while ((--c_char >= 0) && ((c = *lp++) & CHARMASK) != 0) { ! 216: if (c == '\t') ! 217: pos += (tabstop - (pos % tabstop)); ! 218: else if (isctrl(c)) ! 219: pos += 2; ! 220: else ! 221: pos += 1; ! 222: } ! 223: return pos; ! 224: } ! 225: ! 226: int UpdModLine = 0, ! 227: UpdMesg = 0, ! 228: CanScroll = 0; ! 229: ! 230: private void ! 231: DoIDline(start) ! 232: { ! 233: register struct scrimage *des_p = &DesiredScreen[start]; ! 234: struct scrimage *phys_p = &PhysScreen[start]; ! 235: register int i, ! 236: j; ! 237: ! 238: /* Some changes have been made. Try for insert or delete lines. ! 239: If either case has happened, Addlines and/or DelLines will do ! 240: necessary scrolling, also CONVERTING PhysScreen to account for the ! 241: physical changes. The comparison continues from where the ! 242: insertion/deletion takes place; this doesn't happen very often, ! 243: usually it happens with more than one window with the same ! 244: buffer. */ ! 245: ! 246: if (!CanScroll) ! 247: return; /* We should never have been called! */ ! 248: ! 249: for (i = start; i < ILI; i++, des_p++, phys_p++) ! 250: if (des_p->s_id != phys_p->s_id) ! 251: break; ! 252: ! 253: for (; i < ILI; i++) { ! 254: for (j = i + 1; j < ILI; j++) { ! 255: des_p = &DesiredScreen[j]; ! 256: phys_p = &PhysScreen[j]; ! 257: if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id) ! 258: break; ! 259: if (des_p->s_id == PhysScreen[i].s_id) { ! 260: if (des_p->s_id == 0) ! 261: continue; ! 262: if (AddLines(i, j - i)) { ! 263: DoIDline(j); ! 264: return; ! 265: } ! 266: break; ! 267: } ! 268: if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) { ! 269: if (des_p->s_id == 0) ! 270: continue; ! 271: if (DelLines(i, j - i)) { ! 272: DoIDline(i); ! 273: return; ! 274: } ! 275: break; ! 276: } ! 277: } ! 278: } ! 279: } ! 280: ! 281: /* Make DesiredScreen reflect what the screen should look like when we are done ! 282: with the redisplay. This deals with horizontal scrolling. Also makes ! 283: sure the current line of the Window is in the window. */ ! 284: ! 285: int ScrollAll = NO; ! 286: ! 287: private void ! 288: UpdWindow(w, start) ! 289: register Window *w; ! 290: { ! 291: Line *lp; ! 292: int i, ! 293: upper, /* top of window */ ! 294: lower, /* bottom of window */ ! 295: strt_col, /* starting print column of current line */ ! 296: ntries = 0; /* # of tries at updating window */ ! 297: register struct scrimage *des_p, ! 298: *phys_p; ! 299: Buffer *bp = w->w_bufp; ! 300: ! 301: retry: ! 302: if (w->w_flags & W_CURGONE) { ! 303: w->w_line = bp->b_dot; ! 304: w->w_char = bp->b_char; ! 305: } ! 306: if (w->w_flags & W_TOPGONE) ! 307: CentWind(w); /* reset topline of screen */ ! 308: w->w_flags &= ~(W_CURGONE | W_TOPGONE); ! 309: ! 310: /* make sure that the current line is in the window */ ! 311: upper = start; ! 312: lower = upper + w->w_height - 1; /* don't include modeline */ ! 313: for (i = upper, lp = w->w_top; i < lower && lp != 0; lp = lp->l_next, i++) ! 314: if (lp == w->w_line) ! 315: break; ! 316: if (i == lower || lp == 0) { ! 317: ntries += 1; ! 318: if (ntries == 1) { ! 319: CalcWind(w); ! 320: goto retry; ! 321: } else if (ntries == 2) { ! 322: w->w_top = w->w_line = w->w_bufp->b_first; ! 323: printf("\rERROR in redisplay: I got hopelessly lost!"); ! 324: dobell(2); ! 325: goto retry; ! 326: } else if (ntries == 3) { ! 327: printf("\n\rOops, still lost, quitting ...\r\n"); ! 328: finish(1); ! 329: } ! 330: } ! 331: ! 332: /* first do some calculations for the current line */ ! 333: { ! 334: int diff = (w->w_flags & W_NUMLINES) ? 8 : 0, ! 335: end_col; ! 336: ! 337: strt_col = (ScrollAll == YES) ? w->w_LRscroll : ! 338: PhysScreen[i].s_offset; ! 339: end_col = strt_col + (CO - 2) - diff; ! 340: /* Right now we are displaying from strt_col to ! 341: end_col of the buffer line. These are PRINT ! 342: columns, not actual characters. */ ! 343: w->w_dotcol = find_pos(w->w_line, w->w_char); ! 344: /* if the new dotcol is out of range, reselect ! 345: a horizontal window */ ! 346: if ((PhysScreen[i].s_offset == -1) || ! 347: (w->w_dotcol < strt_col) || ! 348: (w->w_dotcol >= end_col)) { ! 349: if (w->w_dotcol < ((CO - 2) - diff)) ! 350: strt_col = 0; ! 351: else ! 352: strt_col = w->w_dotcol - (CO / 2); ! 353: if (ScrollAll == YES) { ! 354: if (w->w_LRscroll != strt_col) ! 355: UpdModLine = YES; ! 356: w->w_LRscroll = strt_col; ! 357: } ! 358: } ! 359: w->w_dotline = i; ! 360: w->w_dotcol += diff; ! 361: } ! 362: ! 363: des_p = &DesiredScreen[upper]; ! 364: phys_p = &PhysScreen[upper]; ! 365: for (i = upper, lp = w->w_top; lp != 0 && i < lower; i++, des_p++, phys_p++, lp = lp->l_next) { ! 366: des_p->s_window = w; ! 367: des_p->s_lp = lp; ! 368: des_p->s_id = lp->l_dline & ~DIRTY; ! 369: des_p->s_flags = isdirty(lp) ? L_MOD : 0; ! 370: if (w->w_flags & W_NUMLINES) ! 371: des_p->s_vln = w->w_topnum + (i - upper); ! 372: else ! 373: des_p->s_vln = 0; ! 374: ! 375: if (lp == w->w_line) ! 376: des_p->s_offset = strt_col; ! 377: else ! 378: des_p->s_offset = w->w_LRscroll; ! 379: } ! 380: ! 381: /* Is structure assignment faster than copy each field separately? */ ! 382: if (i < lower) { ! 383: static struct scrimage dirty_plate = { 0, DIRTY, 0, 0, 0, 0 }, ! 384: clean_plate = { 0, 0, 0, 0, 0, 0 }; ! 385: ! 386: for (; i < lower; i++, des_p++, phys_p++) ! 387: if (phys_p->s_id != 0) ! 388: *des_p = dirty_plate; ! 389: else ! 390: *des_p = clean_plate; ! 391: } ! 392: ! 393: des_p->s_window = w; ! 394: des_p->s_flags = 0; ! 395: if (((des_p->s_id = (int) w->w_bufp) != phys_p->s_id) || UpdModLine) ! 396: des_p->s_flags = MODELINE | DIRTY; ! 397: #ifdef MAC ! 398: if(UpdModLine) Modechange = 1; ! 399: if(w == curwind && w->w_control) SetScrollBar(w->w_control); ! 400: #endif ! 401: } ! 402: ! 403: /* Write whatever is in mesgbuf (maybe we are Asking, or just printed ! 404: a message). Turns off the UpdateMesg line flag. */ ! 405: ! 406: void ! 407: DrawMesg(abortable) ! 408: { ! 409: #ifndef MAC /* same reason as in redisplay() */ ! 410: if (charp()) ! 411: return; ! 412: #endif ! 413: i_set(ILI, 0); ! 414: if (swrite(mesgbuf, NO, abortable)) { ! 415: cl_eol(); ! 416: UpdMesg = 0; ! 417: } ! 418: flusho(); ! 419: } ! 420: ! 421: /* Goto the current position in the current window. Presumably redisplay() ! 422: has already been called, and curwind->{w_dotline,w_dotcol} have been set ! 423: correctly. */ ! 424: ! 425: private void ! 426: GotoDot() ! 427: { ! 428: if (InputPending) ! 429: return; ! 430: Placur(curwind->w_dotline, curwind->w_dotcol - ! 431: PhysScreen[curwind->w_dotline].s_offset); ! 432: flusho(); ! 433: } ! 434: ! 435: private int ! 436: UntilEqual(start) ! 437: register int start; ! 438: { ! 439: register struct scrimage *des_p = &DesiredScreen[start], ! 440: *phys_p = &PhysScreen[start]; ! 441: ! 442: while ((start < ILI) && (des_p->s_id != phys_p->s_id)) { ! 443: des_p += 1; ! 444: phys_p += 1; ! 445: start += 1; ! 446: } ! 447: ! 448: return start; ! 449: } ! 450: ! 451: /* Calls the routine to do the physical changes, and changes PhysScreen to ! 452: reflect those changes. */ ! 453: ! 454: private int ! 455: AddLines(at, num) ! 456: register int at, ! 457: num; ! 458: { ! 459: register int i; ! 460: int bottom = UntilEqual(at + num); ! 461: ! 462: if (num == 0 || num >= ((bottom - 1) - at)) ! 463: return NO; /* we did nothing */ ! 464: v_ins_line(num, at, bottom - 1); ! 465: ! 466: /* Now change PhysScreen to account for the physical change. */ ! 467: ! 468: for (i = bottom - 1; i - num >= at; i--) ! 469: PhysScreen[i] = PhysScreen[i - num]; ! 470: for (i = 0; i < num; i++) ! 471: PhysScreen[at + i].s_id = 0; ! 472: return YES; /* we did something */ ! 473: } ! 474: ! 475: private int ! 476: DelLines(at, num) ! 477: register int at, ! 478: num; ! 479: { ! 480: register int i; ! 481: int bottom = UntilEqual(at + num); ! 482: ! 483: if (num == 0 || num >= ((bottom - 1) - at)) ! 484: return NO; ! 485: v_del_line(num, at, bottom - 1); ! 486: ! 487: for (i = at; num + i < bottom; i++) ! 488: PhysScreen[i] = PhysScreen[num + i]; ! 489: for (i = bottom - num; i < bottom; i++) ! 490: PhysScreen[i].s_id = 0; ! 491: return YES; ! 492: } ! 493: ! 494: /* Update line linenum in window w. Only set PhysScreen to DesiredScreen ! 495: if the swrite or cl_eol works, that is nothing is interupted by ! 496: characters typed. */ ! 497: ! 498: private void ! 499: UpdLine(linenum) ! 500: register int linenum; ! 501: { ! 502: register struct scrimage *des_p = &DesiredScreen[linenum]; ! 503: register Window *w = des_p->s_window; ! 504: ! 505: i_set(linenum, 0); ! 506: if (des_p->s_flags & MODELINE) ! 507: ModeLine(w); ! 508: else if (des_p->s_id) { ! 509: des_p->s_lp->l_dline &= ~DIRTY; ! 510: des_p->s_flags &= ~(DIRTY | L_MOD); ! 511: #ifdef ID_CHAR ! 512: if (!UseIC && (w->w_flags & W_NUMLINES)) ! 513: #else ! 514: if (w->w_flags & W_NUMLINES) ! 515: #endif ! 516: (void) swrite(sprint("%6d ", des_p->s_vln), NO, YES); ! 517: ! 518: #ifdef ID_CHAR ! 519: if (UseIC) { ! 520: char outbuf[MAXCOLS], ! 521: *lptr; ! 522: int fromcol = (w->w_flags & W_NUMLINES) ? 8 : 0; ! 523: ! 524: if (w->w_flags & W_NUMLINES) ! 525: sprintf(outbuf, "%6d ", des_p->s_vln); ! 526: lptr = lcontents(des_p->s_lp); ! 527: DeTab(des_p->s_offset, lptr, outbuf + fromcol, ! 528: (sizeof outbuf) - 1 - fromcol, ! 529: des_p->s_window->w_flags & W_VISSPACE); ! 530: if (IDchar(outbuf, linenum, 0)) ! 531: PhysScreen[linenum] = *des_p; ! 532: else if (i_set(linenum, 0), swrite(outbuf, NO, YES)) ! 533: do_cl_eol(linenum); ! 534: else ! 535: PhysScreen[linenum].s_id = -1; ! 536: } else ! 537: #endif /* ID_CHAR */ ! 538: if (BufSwrite(linenum)) ! 539: do_cl_eol(linenum); ! 540: else ! 541: PhysScreen[linenum].s_id = -1; ! 542: } else if (PhysScreen[linenum].s_id) /* not the same ... make sure */ ! 543: do_cl_eol(linenum); ! 544: } ! 545: ! 546: private void ! 547: do_cl_eol(linenum) ! 548: register int linenum; ! 549: { ! 550: cl_eol(); ! 551: PhysScreen[linenum] = DesiredScreen[linenum]; ! 552: } ! 553: ! 554: #ifdef ID_CHAR ! 555: ! 556: /* From here to the end of the file is code that tries to utilize the ! 557: insert/delete character feature on some terminals. It is very confusing ! 558: and not so well written code, AND there is a lot of it. You may want ! 559: to use the space for something else. */ ! 560: ! 561: extern struct screenline *Screen; ! 562: int IN_INSmode = 0; ! 563: ! 564: int UseIC; ! 565: ! 566: int DClen, ! 567: MDClen, ! 568: IClen, ! 569: MIClen, ! 570: IMlen, ! 571: CElen; ! 572: ! 573: void ! 574: disp_opt_init() ! 575: { ! 576: DClen = DC ? strlen(DC) : 0; ! 577: MDClen = M_DC ? strlen(M_DC) : 9999; ! 578: IClen = IC ? strlen(IC) : 0; ! 579: MIClen = M_IC ? strlen(M_IC) : 9999; ! 580: IMlen = IM ? strlen(IM) : 0; ! 581: CElen = CE ? strlen(CE) : 0; ! 582: ! 583: UseIC = (IC || IM || M_IC); ! 584: } ! 585: ! 586: void ! 587: INSmode(on) ! 588: { ! 589: if (on && !IN_INSmode) { ! 590: putpad(IM, 1); ! 591: IN_INSmode = YES; ! 592: } else if (!on && IN_INSmode) { ! 593: putpad(EI, 1); ! 594: IN_INSmode = NO; ! 595: } ! 596: } ! 597: ! 598: private void ! 599: DeTab(s_offset, buf, outbuf, limit, visspace) ! 600: register char *buf; ! 601: char *outbuf; ! 602: { ! 603: register char *phys_p = outbuf, ! 604: c; ! 605: register int pos = 0; ! 606: char *limitp = &outbuf[limit]; ! 607: ! 608: #define OkayOut(ch) if ((pos++ >= s_offset) && (phys_p < limitp))\ ! 609: *phys_p++ = ch;\ ! 610: else ! 611: ! 612: while (c = *buf++) { ! 613: if (c == '\t') { ! 614: int nchars = (tabstop - (pos % tabstop)); ! 615: ! 616: if (visspace) { ! 617: OkayOut('>'); ! 618: nchars -= 1; ! 619: } ! 620: while (--nchars >= 0) ! 621: OkayOut(' '); ! 622: ! 623: } else if (isctrl(c)) { ! 624: OkayOut('^'); ! 625: OkayOut(c == 0177 ? '?' : c + '@'); ! 626: } else { ! 627: if (visspace && c == ' ') ! 628: c = '_'; ! 629: OkayOut(c); ! 630: } ! 631: if (pos - s_offset >= CO) { ! 632: phys_p = &outbuf[CO - 1]; ! 633: *phys_p++ = '!'; ! 634: break; ! 635: } ! 636: } ! 637: *phys_p = 0; ! 638: } ! 639: ! 640: /* ID character routines full of special cases and other fun stuff like that. ! 641: It actually works though ... ! 642: ! 643: Returns Non-Zero if you are finished (no differences left). */ ! 644: ! 645: private int ! 646: IDchar(new, lineno, col) ! 647: register char *new; ! 648: { ! 649: register int i; ! 650: int j, ! 651: oldlen, ! 652: NumSaved; ! 653: register struct screenline *sline = &Screen[lineno]; ! 654: ! 655: oldlen = sline->s_length - sline->s_line; ! 656: ! 657: for (i = col; i < oldlen && new[i] != 0; i++) ! 658: if (sline->s_line[i] != new[i]) ! 659: break; ! 660: if (new[i] == 0 || i == oldlen) ! 661: return (new[i] == 0 && i == oldlen); ! 662: ! 663: for (j = i + 1; j < oldlen && new[j]; j++) { ! 664: if (new[j] == sline->s_line[i]) { ! 665: NumSaved = IDcomp(new + j, sline->s_line + i, ! 666: strlen(new)) + NumSimilar(new + i, ! 667: sline->s_line + i, j - i); ! 668: if (OkayInsert(NumSaved, j - i)) { ! 669: InsChar(lineno, i, j - i, new); ! 670: return(IDchar(new, lineno, j)); ! 671: } ! 672: } ! 673: } ! 674: ! 675: for (j = i + 1; j < oldlen && new[i]; j++) { ! 676: if (new[i] == sline->s_line[j]) { ! 677: NumSaved = IDcomp(new + i, sline->s_line + j, ! 678: oldlen - j); ! 679: if (OkayDelete(NumSaved, j - i, new[oldlen] == 0)) { ! 680: DelChar(lineno, i, j - i); ! 681: return(IDchar(new, lineno, j)); ! 682: } ! 683: } ! 684: } ! 685: return 0; ! 686: } ! 687: ! 688: private int ! 689: NumSimilar(s, t, n) ! 690: register char *s, ! 691: *t; ! 692: { ! 693: register int num = 0; ! 694: ! 695: while (n--) ! 696: if (*s++ == *t++) ! 697: num += 1; ! 698: return num; ! 699: } ! 700: ! 701: private int ! 702: IDcomp(s, t, len) ! 703: register char *s, ! 704: *t; ! 705: { ! 706: register int i; ! 707: int num = 0, ! 708: nonspace = 0; ! 709: char c; ! 710: ! 711: for (i = 0; i < len; i++) { ! 712: if ((c = *s++) != *t++) ! 713: break; ! 714: if (c != ' ') ! 715: nonspace++; ! 716: if (nonspace) ! 717: num += 1; ! 718: } ! 719: ! 720: return num; ! 721: } ! 722: ! 723: private int ! 724: OkayDelete(Saved, num, samelength) ! 725: { ! 726: /* If the old and the new are the same length, then we don't ! 727: * have to clear to end of line. We take that into consideration. ! 728: */ ! 729: return ((Saved + (!samelength ? CElen : 0)) ! 730: > min(MDClen, DClen * num)); ! 731: } ! 732: ! 733: private int ! 734: OkayInsert(Saved, num) ! 735: { ! 736: register int n = 0; ! 737: ! 738: if (IC) /* Per character prefixes */ ! 739: n = min(num * IClen, MIClen); ! 740: ! 741: if (IM && !IN_INSmode) { ! 742: /* Good terminal. Fewer characters in this case */ ! 743: n += IMlen; ! 744: } ! 745: ! 746: n += num; /* The characters themselves */ ! 747: ! 748: return Saved > n; ! 749: } ! 750: ! 751: extern int CapCol; ! 752: extern char *cursend; ! 753: extern struct screenline *Curline; ! 754: ! 755: private void ! 756: DelChar(lineno, col, num) ! 757: { ! 758: register char *from, ! 759: *to; ! 760: register int i; ! 761: struct screenline *sp = (&Screen[lineno]); ! 762: ! 763: Placur(lineno, col); ! 764: if (M_DC && num > 1) { ! 765: char minibuf[16]; ! 766: ! 767: sprintf(minibuf, M_DC, num); ! 768: putpad(minibuf, num); ! 769: } else { ! 770: for (i = num; --i >= 0; ) ! 771: putpad(DC, 1); ! 772: } ! 773: ! 774: to = sp->s_line + col; ! 775: from = to + num; ! 776: ! 777: byte_copy(from, to, sp->s_length - from + 1); ! 778: clrline(sp->s_length - num, sp->s_length); ! 779: sp->s_length -= num; ! 780: } ! 781: ! 782: private void ! 783: InsChar(lineno, col, num, new) ! 784: char *new; ! 785: { ! 786: register char *sp1, ! 787: *sp2, /* To push over the array. */ ! 788: *sp3; /* Last character to push over. */ ! 789: int i; ! 790: ! 791: i_set(lineno, 0); ! 792: sp2 = Curline->s_length + num; ! 793: ! 794: if (sp2 >= cursend) { ! 795: i_set(lineno, CO - num - 1); ! 796: cl_eol(); ! 797: sp2 = cursend - 1; ! 798: } ! 799: Curline->s_length = sp2; ! 800: sp1 = sp2 - num; ! 801: sp3 = Curline->s_line + col; ! 802: ! 803: while (sp1 >= sp3) ! 804: *sp2-- = *sp1--; ! 805: ! 806: new += col; ! 807: byte_copy(new, sp3, num); ! 808: /* The internal screen is correct, and now we have to do ! 809: the physical stuff. */ ! 810: ! 811: Placur(lineno, col); ! 812: if (IM) { ! 813: if (!IN_INSmode) ! 814: INSmode(1); ! 815: } else if (M_IC && num > 1) { ! 816: char minibuf[16]; ! 817: ! 818: sprintf(minibuf, M_IC, num); ! 819: putpad(minibuf, num); ! 820: } else if (IC) { ! 821: for (i = 0; i < num; i++) ! 822: putpad(IC, 1); ! 823: } ! 824: for (i = 0; i < num; i++) { ! 825: putchar(new[i]); ! 826: if (IN_INSmode) ! 827: putpad(IP, 1); ! 828: } ! 829: CapCol += num; ! 830: } ! 831: ! 832: #endif /* ID_CHAR */ ! 833: ! 834: #ifdef UNIX /* obviously ... no mail today if not Unix*/ ! 835: ! 836: /* chkmail() returns nonzero if there is new mail since the ! 837: last time we checked. */ ! 838: ! 839: char Mailbox[FILESIZE]; /* initialized in main */ ! 840: int MailInt = 60; /* check no more often than 60 seconds */ ! 841: #ifdef BIFF ! 842: int BiffChk = NO; /* whether or not to turn off biff while in JOVE */ ! 843: #endif ! 844: ! 845: int ! 846: chkmail(force) ! 847: { ! 848: time_t now; ! 849: static time_t last_chk = 0; ! 850: static int value = FALSE; ! 851: static off_t last_size = 0; ! 852: struct stat stbuf; ! 853: int last_val; ! 854: static time_t last_time = 0; ! 855: ! 856: time(&now); ! 857: if (!force && (now < last_chk + MailInt)) ! 858: return value; ! 859: last_chk = now; ! 860: if (force) ! 861: last_time = now; ! 862: if (stat(Mailbox, &stbuf) < 0) { ! 863: value = FALSE; ! 864: return FALSE; ! 865: } ! 866: last_val = value; ! 867: value = ((stbuf.st_mtime > last_time) && ! 868: (stbuf.st_size > 0) && ! 869: (stbuf.st_size >= last_size) && ! 870: (stbuf.st_mtime + 5 > stbuf.st_atime)); ! 871: if (value == TRUE && ! 872: ((value != last_val) || (stbuf.st_size != last_size))) ! 873: dobell(3); ! 874: if (stbuf.st_size < last_size) ! 875: last_time = now; ! 876: last_size = stbuf.st_size; ! 877: return value; ! 878: } ! 879: ! 880: #endif /* UNIX */ ! 881: ! 882: /* Print the mode line. */ ! 883: ! 884: private char *mode_p, ! 885: *mend_p; ! 886: int BriteMode = 1; /* modeline should standout */ ! 887: ! 888: private void ! 889: mode_app(str) ! 890: register char *str; ! 891: { ! 892: if (mode_p >= mend_p) ! 893: return; ! 894: while ((mode_p < mend_p) && (*mode_p++ = *str++)) ! 895: ; ! 896: mode_p -= 1; /* back over the null */ ! 897: } ! 898: ! 899: char ModeFmt[120] = "%3c %w %[%sJOVE (%M) Buffer: %b \"%f\" %]%s%m*- %((%t)%s%)%e"; ! 900: ! 901: private void ! 902: ModeLine(w) ! 903: register Window *w; ! 904: { ! 905: extern int i_line; ! 906: extern char *pwd(); ! 907: int n, ! 908: ign_some = NO; ! 909: char line[MAXCOLS], ! 910: *fmt = ModeFmt, ! 911: fillc, ! 912: c; ! 913: register Buffer *thisbuf = w->w_bufp; ! 914: register Buffer *bp; ! 915: ! 916: mode_p = line; ! 917: mend_p = &line[(sizeof line) - 1]; ! 918: ! 919: #if defined(UNIX) || (defined (MSDOS) && !defined(IBMPC)) ! 920: if (BriteMode != 0 && SO == 0) ! 921: BriteMode = 0; ! 922: fillc = BriteMode ? ' ' : '-'; ! 923: #endif /* UNIX */ ! 924: #ifdef IBMPC /* very subtle - don't mess up attributes too much */ ! 925: fillc = '-'; /*BriteMode ? ' ' : '-';*/ ! 926: #endif /* IBMPC */ ! 927: #ifdef MAC ! 928: fillc = '_'; /* looks better on a Mac */ ! 929: #endif /* MAC */ ! 930: ! 931: while (c = *fmt++) { ! 932: if (c != '%') { ! 933: if (c == '\\') ! 934: if ((c = *fmt++) == '\0') ! 935: break; ! 936: if (!ign_some) ! 937: *mode_p++ = c; ! 938: continue; ! 939: } ! 940: if ((c = *fmt++) == '\0') /* char after the '%' */ ! 941: break; ! 942: if (ign_some && c != ')') ! 943: continue; ! 944: n = 1; ! 945: if (c >= '0' && c <= '9') { ! 946: n = 0; ! 947: while (c >= '0' && c <= '9') { ! 948: n = n * 10 + (c - '0'); ! 949: c = *fmt++; ! 950: } ! 951: } ! 952: switch (c) { ! 953: case '(': ! 954: if (w->w_next != fwind) /* Not bottom window. */ ! 955: ign_some = YES; ! 956: break; ! 957: ! 958: case ')': ! 959: ign_some = NO; ! 960: break; ! 961: ! 962: case '[': ! 963: case ']': ! 964: { ! 965: char *strs = (c == '[') ? "[[[[[[[[[[" : "]]]]]]]]]]"; ! 966: ! 967: mode_app(strs + 10 - RecDepth); ! 968: break; ! 969: } ! 970: ! 971: #ifdef UNIX ! 972: case 'C': /* check mail here */ ! 973: if (chkmail(NO)) ! 974: mode_app("[New mail]"); ! 975: break; ! 976: ! 977: #endif /* UNIX */ ! 978: ! 979: case 'M': ! 980: { ! 981: static char *mmodes[] = { ! 982: "Fundamental ", ! 983: "Text ", ! 984: "C ", ! 985: #ifdef LISP ! 986: "Lisp ", ! 987: #endif ! 988: 0 ! 989: }; ! 990: ! 991: mode_app(mmodes[thisbuf->b_major]); ! 992: ! 993: if (BufMinorMode(thisbuf, Fill)) ! 994: mode_app("Fill "); ! 995: if (BufMinorMode(thisbuf, Abbrev)) ! 996: mode_app("Abbrev "); ! 997: if (BufMinorMode(thisbuf, OverWrite)) ! 998: mode_app("OvrWt "); ! 999: if (BufMinorMode(thisbuf, Indent)) ! 1000: mode_app("AI "); ! 1001: if (InMacDefine) ! 1002: mode_app("Def "); ! 1003: mode_p -= 1; /* Back over the extra space. */ ! 1004: break; ! 1005: } ! 1006: ! 1007: case 'c': ! 1008: while (--n >= 0) ! 1009: *mode_p++ = fillc; ! 1010: break; ! 1011: ! 1012: #ifdef CHDIR ! 1013: case 'd': /* print working directory */ ! 1014: mode_app(pr_name(pwd(), YES)); ! 1015: break; ! 1016: #endif ! 1017: ! 1018: case 'e': ! 1019: { ! 1020: /* 2 space pad pluss padding for magic cookies */ ! 1021: char *last_p = &line[CO - 2 - (2 * SG)]; ! 1022: ! 1023: while (mode_p < last_p) ! 1024: *mode_p++ = fillc; ! 1025: ! 1026: goto outahere; /* %e means we're done! */ ! 1027: } ! 1028: ! 1029: case 'b': ! 1030: mode_app(thisbuf->b_name); ! 1031: break; ! 1032: ! 1033: case 'f': ! 1034: case 'F': ! 1035: if (thisbuf->b_fname == 0) ! 1036: mode_app("[No file]"); ! 1037: else { ! 1038: if (c == 'f') ! 1039: mode_app(pr_name(thisbuf->b_fname, YES)); ! 1040: else ! 1041: mode_app(basename(thisbuf->b_fname)); ! 1042: } ! 1043: break; ! 1044: ! 1045: #ifdef LOAD_AV ! 1046: case 'l': ! 1047: { ! 1048: double theavg; ! 1049: char minibuf[10]; ! 1050: ! 1051: get_la(&theavg); ! 1052: theavg += .005; /* round to nearest .01 */ ! 1053: sprintf(minibuf, "%d.%02d", ! 1054: (int) theavg, ! 1055: (int)((theavg - (int) theavg) * 100)); ! 1056: mode_app(minibuf); ! 1057: break; ! 1058: } ! 1059: #endif ! 1060: ! 1061: case 'm': ! 1062: if (IsModified(w->w_bufp)) ! 1063: *mode_p++ = fmt[0]; ! 1064: else ! 1065: *mode_p++ = fmt[1]; ! 1066: fmt += 2; /* skip two characters */ ! 1067: break; ! 1068: ! 1069: case 'n': ! 1070: { ! 1071: char tmp[16]; ! 1072: for (bp = world, n = 1; bp != 0; bp = bp->b_next, n++) ! 1073: if (bp == thisbuf) ! 1074: break; ! 1075: ! 1076: sprintf(tmp, "%d", n); ! 1077: mode_app(tmp); ! 1078: break; ! 1079: } ! 1080: ! 1081: #ifdef IPROCS ! 1082: case 'p': ! 1083: if (thisbuf->b_type == B_PROCESS) { ! 1084: char tmp[40]; ! 1085: ! 1086: sprintf(tmp, "(%s)", (thisbuf->b_process == 0) ? ! 1087: "No process" : ! 1088: pstate(thisbuf->b_process)); ! 1089: mode_app(tmp); ! 1090: break; ! 1091: } ! 1092: #endif ! 1093: ! 1094: case 's': ! 1095: if (mode_p[-1] == ' ') ! 1096: continue; ! 1097: *mode_p++ = ' '; ! 1098: break; ! 1099: ! 1100: case 't': ! 1101: { ! 1102: char timestr[12]; ! 1103: ! 1104: mode_app(get_time((time_t *) 0, timestr, 11, 16)); ! 1105: break; ! 1106: } ! 1107: ! 1108: case 'w': ! 1109: if (w->w_LRscroll > 0) ! 1110: mode_app(">"); ! 1111: } ! 1112: } ! 1113: ! 1114: outahere: ! 1115: *mode_p = 0; ! 1116: ! 1117: /* Highlight mode line. */ ! 1118: if (BriteMode) { ! 1119: #ifdef ID_CHAR ! 1120: if (IN_INSmode) ! 1121: INSmode(0); ! 1122: #endif ! 1123: #ifdef TERMCAP ! 1124: putpad(SO, 1); ! 1125: #else ! 1126: SO_on(); ! 1127: #endif /* TERMCAP */ ! 1128: } ! 1129: if (swrite(line, BriteMode, YES)) ! 1130: do_cl_eol(i_line); ! 1131: else ! 1132: UpdModLine = 1; ! 1133: if (BriteMode) ! 1134: #ifdef TERMCAP ! 1135: putpad(SE, 1); ! 1136: #else ! 1137: SO_off(); ! 1138: #endif /* TERMCAP */ ! 1139: } ! 1140: ! 1141: /* This tries to place the current line of the current window in the ! 1142: center of the window, OR to place it at the arg'th line of the window. ! 1143: This also causes the horizontal position of the line to be centered, ! 1144: if the line needs scrolling, or moved all the way back to the left, ! 1145: if that's possible. */ ! 1146: void ! 1147: RedrawDisplay() ! 1148: { ! 1149: int line; ! 1150: Line *newtop = prev_line((curwind->w_line = curline), is_an_arg() ? ! 1151: arg_value() : HALF(curwind)); ! 1152: ! 1153: if ((line = in_window(curwind, curwind->w_line)) != -1) ! 1154: PhysScreen[line].s_offset = -1; ! 1155: if (newtop == curwind->w_top) ! 1156: v_clear(FLine(curwind), FLine(curwind) + SIZE(curwind)); ! 1157: else ! 1158: SetTop(curwind, newtop); ! 1159: } ! 1160: ! 1161: void ! 1162: v_clear(line1, line2) ! 1163: register int line1; ! 1164: { ! 1165: register struct scrimage *phys_p, *des_p; ! 1166: ! 1167: phys_p = &PhysScreen[line1]; ! 1168: des_p = &DesiredScreen[line1]; ! 1169: ! 1170: while (line1 <= line2) { ! 1171: i_set(line1, 0); ! 1172: cl_eol(); ! 1173: phys_p->s_id = des_p->s_id = 0; ! 1174: phys_p += 1; ! 1175: des_p += 1; ! 1176: line1 += 1; ! 1177: } ! 1178: } ! 1179: ! 1180: void ! 1181: ClAndRedraw() ! 1182: { ! 1183: cl_scr(YES); ! 1184: } ! 1185: ! 1186: void ! 1187: NextPage() ! 1188: { ! 1189: Line *newline; ! 1190: ! 1191: if (Asking) ! 1192: return; ! 1193: if (arg_value() < 0) { ! 1194: negate_arg_value(); ! 1195: PrevPage(); ! 1196: return; ! 1197: } ! 1198: if (arg_type() == YES) ! 1199: UpScroll(); ! 1200: else { ! 1201: if (in_window(curwind, curwind->w_bufp->b_last) != -1) { ! 1202: rbell(); ! 1203: return; ! 1204: } ! 1205: newline = next_line(curwind->w_top, max(1, SIZE(curwind) - 1)); ! 1206: SetTop(curwind, curwind->w_line = newline); ! 1207: if (curwind->w_bufp == curbuf) ! 1208: SetLine(newline); ! 1209: } ! 1210: } ! 1211: ! 1212: #ifdef MSDOS /* kg */ ! 1213: ! 1214: void ! 1215: PageScrollUp() ! 1216: { ! 1217: int i, n; ! 1218: ! 1219: n = max(1, SIZE(curwind) - 1); ! 1220: for (i=0; i<n; i++) { ! 1221: UpScroll(); ! 1222: redisplay(); ! 1223: } ! 1224: } ! 1225: ! 1226: void ! 1227: PageScrollDown() ! 1228: { ! 1229: int i, n; ! 1230: ! 1231: n = max(1, SIZE(curwind) - 1); ! 1232: for (i=0; i<n; i++) { ! 1233: DownScroll(); ! 1234: redisplay(); ! 1235: } ! 1236: } ! 1237: #endif /* MSDOS */ ! 1238: ! 1239: void ! 1240: PrevPage() ! 1241: { ! 1242: Line *newline; ! 1243: ! 1244: if (Asking) ! 1245: return; ! 1246: if (arg_value() < 0) { ! 1247: negate_arg_value(); ! 1248: NextPage(); ! 1249: return; ! 1250: } ! 1251: if (arg_type() == YES) ! 1252: DownScroll(); ! 1253: else { ! 1254: newline = prev_line(curwind->w_top, max(1, SIZE(curwind) - 1)); ! 1255: SetTop(curwind, curwind->w_line = newline); ! 1256: if (curwind->w_bufp == curbuf) ! 1257: SetLine(newline); ! 1258: } ! 1259: } ! 1260: ! 1261: void ! 1262: UpScroll() ! 1263: { ! 1264: SetTop(curwind, next_line(curwind->w_top, arg_value())); ! 1265: if ((curwind->w_bufp == curbuf) && ! 1266: (in_window(curwind, curline) == -1)) ! 1267: SetLine(curwind->w_top); ! 1268: } ! 1269: ! 1270: void ! 1271: DownScroll() ! 1272: { ! 1273: SetTop(curwind, prev_line(curwind->w_top, arg_value())); ! 1274: if ((curwind->w_bufp == curbuf) && ! 1275: (in_window(curwind, curline) == -1)) ! 1276: SetLine(curwind->w_top); ! 1277: } ! 1278: ! 1279: int VisBell = NO, ! 1280: RingBell = NO; /* So if we have a lot of errors ... ! 1281: ring the bell only ONCE */ ! 1282: void ! 1283: rbell() ! 1284: { ! 1285: RingBell = YES; ! 1286: } ! 1287: ! 1288: /* Message prints the null terminated string onto the bottom line of the ! 1289: terminal. */ ! 1290: ! 1291: void ! 1292: message(str) ! 1293: char *str; ! 1294: { ! 1295: if (InJoverc) ! 1296: return; ! 1297: UpdMesg = YES; ! 1298: errormsg = NO; ! 1299: if (str != mesgbuf) ! 1300: null_ncpy(mesgbuf, str, (sizeof mesgbuf) - 1); ! 1301: } ! 1302: ! 1303: /* End of Window */ ! 1304: ! 1305: void ! 1306: Eow() ! 1307: { ! 1308: if (Asking) ! 1309: return; ! 1310: SetLine(next_line(curwind->w_top, SIZE(curwind) - 1 - ! 1311: min(SIZE(curwind) - 1, arg_value() - 1))); ! 1312: if (!is_an_arg()) ! 1313: Eol(); ! 1314: } ! 1315: ! 1316: /* Beginning of Window */ ! 1317: ! 1318: void ! 1319: Bow() ! 1320: { ! 1321: if (Asking) ! 1322: return; ! 1323: SetLine(next_line(curwind->w_top, min(SIZE(curwind) - 1, arg_value() - 1))); ! 1324: } ! 1325: ! 1326: private int LineNo, ! 1327: last_col, ! 1328: DoAutoNL; ! 1329: private Window *old_wind; /* save the window we were in BEFORE ! 1330: before we were called, if UseBuffers ! 1331: is nonzero */ ! 1332: ! 1333: int UseBuffers = FALSE; ! 1334: int TOabort = 0; ! 1335: ! 1336: /* This initializes the typeout. If send-typeout-to-buffers is set ! 1337: the buffer NAME is created (emptied if it already exists) and output ! 1338: goes to the buffer. Otherwise output is drawn on the screen and ! 1339: erased by TOstop() */ ! 1340: ! 1341: void ! 1342: TOstart(name, auto_newline) ! 1343: char *name; ! 1344: { ! 1345: if (UseBuffers) { ! 1346: old_wind = curwind; ! 1347: pop_wind(name, YES, B_SCRATCH); ! 1348: } else ! 1349: DisabledRedisplay = YES; ! 1350: TOabort = LineNo = last_col = 0; ! 1351: DoAutoNL = auto_newline; ! 1352: } ! 1353: ! 1354: /* VARARGS1 */ ! 1355: ! 1356: void ! 1357: Typeout(fmt, va_alist) ! 1358: char *fmt; ! 1359: va_dcl ! 1360: { ! 1361: if (TOabort) ! 1362: return; ! 1363: ! 1364: if (!UseBuffers && (LineNo == ILI - 1)) { ! 1365: register int c; ! 1366: ! 1367: LineNo = 0; ! 1368: last_col = 0; ! 1369: f_mess("--more--"); ! 1370: if ((c = getchar()) != ' ') { ! 1371: TOabort = YES; ! 1372: if (c != AbortChar && c != RUBOUT) ! 1373: Ungetc(c); ! 1374: f_mess(NullStr); ! 1375: return; ! 1376: } ! 1377: f_mess(NullStr); ! 1378: } ! 1379: ! 1380: if (fmt) { ! 1381: extern int i_col; ! 1382: char string[132]; ! 1383: va_list ap; ! 1384: ! 1385: va_start(ap); ! 1386: format(string, sizeof string, fmt, ap); ! 1387: va_end(ap); ! 1388: if (UseBuffers) ! 1389: ins_str(string, NO); ! 1390: else { ! 1391: i_set(LineNo, last_col); ! 1392: (void) swrite(string, NO, YES); ! 1393: last_col = i_col; ! 1394: } ! 1395: } ! 1396: if (!UseBuffers) { ! 1397: PhysScreen[LineNo].s_id = -1; ! 1398: if (fmt == 0 || DoAutoNL == YES) { ! 1399: cl_eol(); ! 1400: flusho(); ! 1401: LineNo += 1; ! 1402: last_col = 0; ! 1403: } ! 1404: } else if (fmt == 0 || DoAutoNL != 0) ! 1405: ins_str("\n", NO); ! 1406: } ! 1407: ! 1408: void ! 1409: TOstop() ! 1410: { ! 1411: int c; ! 1412: ! 1413: if (UseBuffers) { ! 1414: ToFirst(); ! 1415: SetWind(old_wind); ! 1416: } else { ! 1417: if (TOabort) { ! 1418: DisabledRedisplay = NO; ! 1419: return; ! 1420: } ! 1421: if (last_col != 0) ! 1422: Typeout((char *) 0); ! 1423: Typeout("----------"); ! 1424: cl_eol(); ! 1425: flusho(); ! 1426: c = getchar(); ! 1427: if (c != ' ') ! 1428: Ungetc(c); ! 1429: DisabledRedisplay = NO; ! 1430: } ! 1431: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.