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