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