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: }