|
|
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 "fp.h" ! 10: #include "ctype.h" ! 11: #include "termcap.h" ! 12: #include "disp.h" ! 13: ! 14: int AbortCnt, ! 15: CanScroll = 0, ! 16: tabstop = 8; ! 17: ! 18: #if !(defined(IBMPC) || defined(MAC)) ! 19: private void ! 20: (*TTins_line) proto((int, int, int)), ! 21: (*TTdel_line) proto((int, int, int)); ! 22: #endif /* (defined(IBMPC) || defined(MAC)) */ ! 23: ! 24: struct scrimage ! 25: *DesiredScreen = 0, ! 26: *PhysScreen = 0; ! 27: ! 28: struct screenline *Screen = 0, /* the screen (a bunch of screenline) */ ! 29: *Curline = 0; /* current line */ ! 30: ! 31: private struct screenline *Savelines = 0; /* another bunch (LI of them) */ ! 32: ! 33: ! 34: private char *cursor; /* offset into current Line */ ! 35: ! 36: char *cursend; ! 37: ! 38: int CapCol, ! 39: CapLine, ! 40: ! 41: i_line, ! 42: i_col; ! 43: ! 44: #ifdef IBMPC ! 45: extern unsigned char CHPL; ! 46: extern void near normfun(), ! 47: near scr_win(), ! 48: near clr_page(), ! 49: near clr_eoln(); ! 50: ! 51: #endif ! 52: ! 53: void ! 54: make_scr() ! 55: { ! 56: register int i; ! 57: register struct screenline *ns; ! 58: register char *nsp; ! 59: ! 60: #ifdef RESHAPING ! 61: /* In case we are RESHAPING the window! */ ! 62: if (DesiredScreen) ! 63: free((char *) DesiredScreen); ! 64: if (PhysScreen) ! 65: free((char *) PhysScreen); ! 66: if (Savelines) ! 67: free((char *) Savelines); ! 68: if (Screen) { ! 69: free(Screen->s_line); /* free all the screen data */ ! 70: free((char *) Screen); ! 71: } ! 72: #endif /* RESHAPING */ ! 73: ! 74: DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage)); ! 75: PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage)); ! 76: ! 77: Savelines = (struct screenline *) ! 78: malloc((unsigned) LI * sizeof(struct screenline)); ! 79: ns = Screen = (struct screenline *) ! 80: malloc((unsigned) LI * sizeof(struct screenline)); ! 81: ! 82: nsp = (char *) malloc((unsigned)CO * LI); ! 83: if (nsp == 0) { ! 84: writef("\n\rCannot malloc screen!\n"); ! 85: finish(1); ! 86: } ! 87: ! 88: for (i = 0; i < LI; i++) { ! 89: ns->s_line = nsp; ! 90: nsp += CO; ! 91: ns->s_length = nsp - 1; /* End of Line */ ! 92: ns += 1; ! 93: } ! 94: cl_scr(0); ! 95: } ! 96: ! 97: void ! 98: clrline(cp1, cp2) ! 99: register char *cp1, ! 100: *cp2; ! 101: { ! 102: while (cp1 <= cp2) ! 103: *cp1++ = ' '; ! 104: } ! 105: ! 106: #if !(defined(IBMPC) || defined(MAC)) ! 107: # define sputc(c) ((*cursor != (char) (c)) ? dosputc((c)) : (cursor++, i_col++)) ! 108: #endif /* (defined(IBMPC) || defined(MAC)) */ ! 109: ! 110: #ifdef IBMPC ! 111: int force = 0; ! 112: # define sputc(c) dosputc((c)) ! 113: #endif /* IBMPC */ ! 114: ! 115: #ifdef MAC ! 116: # define sputc(c) bufputc((c)) /* line buffered for mac display */ ! 117: #endif /* MAC */ ! 118: ! 119: #define soutputc(c) { if (--n <= 0) break; else sputc((c)); } ! 120: ! 121: void ! 122: cl_eol() ! 123: { ! 124: if (cursor > cursend) ! 125: return; ! 126: ! 127: if (cursor < Curline->s_length) { ! 128: #if !(defined(IBMPC) || defined(MAC)) ! 129: if (CE) { ! 130: #endif /* (defined(IBMPC) || defined(MAC)) */ ! 131: Placur(i_line, i_col); ! 132: #ifdef TERMCAP ! 133: putpad(CE, 1); ! 134: #else ! 135: clr_eoln(); ! 136: #endif /* TERMCAP */ ! 137: clrline(cursor, Curline->s_length); ! 138: #if !(defined(IBMPC) || defined(MAC)) ! 139: } else { ! 140: /* Ugh. The slow way for dumb terminals. */ ! 141: register char *savecp = cursor; ! 142: ! 143: while (cursor <= Curline->s_length) ! 144: sputc(' '); ! 145: cursor = savecp; ! 146: } ! 147: #endif /* (defined(IBMPC) || defined(MAC)) */ ! 148: Curline->s_length = cursor; ! 149: } ! 150: } ! 151: ! 152: void ! 153: cl_scr(doit) ! 154: int doit; ! 155: { ! 156: register int i; ! 157: register struct screenline *sp = Screen; ! 158: ! 159: for (i = 0; i < LI; i++, sp++) { ! 160: clrline(sp->s_line, sp->s_length); ! 161: sp->s_length = sp->s_line; ! 162: PhysScreen[i].s_id = 0; ! 163: } ! 164: if (doit) { ! 165: #ifdef TERMCAP ! 166: putpad(CL, LI); ! 167: #else ! 168: clr_page(); ! 169: #endif /* TERMCAP */ ! 170: CapCol = CapLine = 0; ! 171: UpdMesg = YES; ! 172: } ! 173: } ! 174: ! 175: /* Output one character (if necessary) at the current position */ ! 176: ! 177: #ifndef MAC ! 178: int /* only for lints sake */ ! 179: dosputc(c) ! 180: register int c; ! 181: { ! 182: #ifndef IBMPC ! 183: if (*cursor != c) { ! 184: # ifdef ID_CHAR ! 185: if (IN_INSmode) ! 186: INSmode(0); ! 187: # endif ! 188: #else /* IBMPC */ ! 189: if ((force) || (*cursor != c)) { ! 190: #endif /* IBMPC */ ! 191: if (i_line != CapLine || i_col != CapCol) ! 192: Placur(i_line, i_col); ! 193: #ifndef IBMPC ! 194: if (UL && (c & CHARMASK) == '_' && (*cursor & CHARMASK) != ' ') ! 195: putstr(" \b"); /* Erase so '_' looks right. */ ! 196: #endif /* IBMPC */ ! 197: *cursor++ = c; ! 198: #ifndef IBMPC ! 199: jputchar(c & CHARMASK); ! 200: #else /* IBMPC */ ! 201: normfun((char) c); ! 202: #endif /* IBMPC */ ! 203: AbortCnt -= 1; ! 204: CapCol += 1; ! 205: i_col += 1; ! 206: } else { ! 207: cursor += 1; ! 208: i_col += 1; ! 209: } ! 210: return 0; /* useless result */ ! 211: } ! 212: #else /* MAC */ ! 213: ! 214: /* Character output to bit-mapped screen is very expensive. It makes ! 215: much more sense to write the entire line at once. So, we print all ! 216: the characters, whether already there or not, once the line is ! 217: complete. */ ! 218: ! 219: #define BUFFLUSH (char) 0 ! 220: #define BUFSTART (char) 1 ! 221: ! 222: bufputc(c) ! 223: register char c; ! 224: { ! 225: static char buf[256]; ! 226: static int len = 0; ! 227: ! 228: if(c == BUFSTART) { ! 229: /* if (i_line != CapLine || i_col != CapCol)*/ ! 230: NPlacur(i_line, i_col); ! 231: len = 0; ! 232: return; ! 233: } ! 234: if(c == BUFFLUSH) { ! 235: buf[0] = (unsigned char) len; ! 236: writechr(buf); ! 237: len = 0; ! 238: } ! 239: else { ! 240: if(len > 255) return; ! 241: *cursor++ = c; ! 242: if(c == '0') buf[++len] = 0xAF; /* slashed zero */ ! 243: else buf[++len] = c; ! 244: CapCol++; ! 245: i_col++; ! 246: } ! 247: return; ! 248: } ! 249: #endif /* MAC */ ! 250: ! 251: /* Write `line' at the current position of `cursor'. Stop when we ! 252: reach the end of the screen. Aborts if there is a character ! 253: waiting. */ ! 254: ! 255: #ifdef MAC /* This was getting too complicated with ifdefs ... */ ! 256: int ! 257: swrite(line, inversep, abortable) ! 258: register char *line; ! 259: register int abortable; ! 260: { ! 261: register int c; ! 262: int col = i_col, ! 263: aborted = 0; ! 264: register int n = cursend - cursor; ! 265: ! 266: if (n <= 0) ! 267: return 1; ! 268: sputc(BUFSTART); /* Okay, because no interruption possible */ ! 269: ! 270: while (c = *line++) { ! 271: if (abortable && AbortCnt < 0) { ! 272: AbortCnt = BufSize; ! 273: if (InputPending = charp()) { ! 274: aborted = 1; ! 275: break; ! 276: } ! 277: } ! 278: if (c == '\t') { ! 279: int nchars; ! 280: ! 281: nchars = (tabstop - (col % tabstop)); ! 282: col += nchars; ! 283: ! 284: while (nchars--) ! 285: soutputc(' '); ! 286: if (n <= 0) ! 287: break; ! 288: } else if (isctrl(c)) { ! 289: soutputc('^'); ! 290: c = ((c == '\177') ? '?' : c + '@'); ! 291: soutputc(c); ! 292: col += 2; ! 293: } else { ! 294: soutputc(c); ! 295: col += 1; ! 296: } ! 297: } ! 298: if (n <= 0) { ! 299: if ((*line == '\0') && (c != '\t') && !isctrl(c)) ! 300: sputc(c); ! 301: sputc('!'); ! 302: } ! 303: if (cursor > Curline->s_length) ! 304: Curline->s_length = cursor; ! 305: sputc(BUFFLUSH); ! 306: return !aborted; ! 307: } ! 308: ! 309: #else /* MAC */ ! 310: ! 311: int ! 312: swrite(line, inversep, abortable) ! 313: register char *line; ! 314: int inversep; ! 315: register int abortable; ! 316: { ! 317: register int c; ! 318: int col = i_col, ! 319: aborted = 0; ! 320: register int n = cursend - cursor; ! 321: #ifndef IBMPC ! 322: int or_byte = inversep ? 0200 : 0, ! 323: thebyte; ! 324: #else ! 325: int thebyte; ! 326: #endif /* IBMPC */ ! 327: ! 328: #ifdef IBMPC ! 329: force = inversep? 1: 0; /* to force a redraw of the modeline */ ! 330: #endif /* IBMPC */ ! 331: ! 332: if (n <= 0) ! 333: return 1; ! 334: while ((c = *line++) != '\0') { ! 335: if (abortable && AbortCnt < 0) { ! 336: AbortCnt = BufSize; ! 337: if ((InputPending = charp()) != '\0') { ! 338: aborted = 1; ! 339: break; ! 340: } ! 341: } ! 342: if (c == '\t') { ! 343: int nchars; ! 344: ! 345: nchars = (tabstop - (col % tabstop)); ! 346: col += nchars; ! 347: ! 348: #ifndef IBMPC ! 349: thebyte = (' ' | or_byte); ! 350: #endif /* IBMPC */ ! 351: while (nchars--) ! 352: #ifndef IBMPC ! 353: soutputc(thebyte); ! 354: #else /* IBMPC */ ! 355: soutputc(' '); ! 356: #endif /* IBMPC */ ! 357: if (n <= 0) ! 358: break; ! 359: } else if (isctrl(c)) { ! 360: #ifndef IBMPC ! 361: thebyte = ('^' | or_byte); ! 362: soutputc(thebyte); ! 363: thebyte = (((c == '\177') ? '?' : c + '@') | or_byte); ! 364: soutputc(thebyte); ! 365: #else /* IBMPC */ ! 366: soutputc('^'); ! 367: c = ((c == '\177') ? '?' : c + '@'); ! 368: soutputc(c); ! 369: #endif /* IBMPC */ ! 370: col += 2; ! 371: #ifdef TERMCAP ! 372: } else if (HZ && c == '~') { ! 373: thebyte = ('`' | or_byte); ! 374: soutputc(thebyte); ! 375: col += 1; ! 376: #endif ! 377: } else { ! 378: #ifndef IBMPC ! 379: thebyte = (c | or_byte); ! 380: soutputc(thebyte); ! 381: #else /* IBMPC */ ! 382: if (c == 255) c = 1; ! 383: if (c == ' ' && inversep) c = 255; ! 384: soutputc(c); ! 385: #endif /* IBMPC */ ! 386: col += 1; ! 387: } ! 388: } ! 389: if (n <= 0) { ! 390: if ((*line == '\0') && (c != '\t') && !isctrl(c)) ! 391: #ifndef IBMPC ! 392: sputc(c|or_byte); ! 393: #else /* IBMPC */ ! 394: sputc(c); ! 395: #endif /* IBMPC */ ! 396: else ! 397: #ifndef IBMPC ! 398: sputc('!'|or_byte); ! 399: #else /* IBMPC */ ! 400: sputc('!'); ! 401: #endif /* IBMPC */ ! 402: } ! 403: if (cursor > Curline->s_length) ! 404: Curline->s_length = cursor; ! 405: #ifdef IBMPC ! 406: force = 0; ! 407: #endif ! 408: return !aborted; ! 409: } ! 410: #endif /* MAC */ ! 411: ! 412: /* This is for writing a buffer line to the screen. This is to ! 413: minimize the amount of copying from one buffer to another buffer. ! 414: This gets the info directly from the disk buffers. */ ! 415: ! 416: int ! 417: BufSwrite(linenum) ! 418: int linenum; ! 419: { ! 420: register int n = cursend - cursor, ! 421: col = 0, ! 422: c = -1; ! 423: register char *bp; ! 424: int StartCol = DesiredScreen[linenum].s_offset, ! 425: visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE, ! 426: aborted = 0; ! 427: ! 428: bp = lcontents(DesiredScreen[linenum].s_lp); ! 429: if (*bp) for (;;) { ! 430: if (col >= StartCol) { ! 431: DesiredScreen[linenum].s_offset = col; ! 432: break; ! 433: } ! 434: ! 435: c = *bp++ & CHARMASK; ! 436: if (c == '\0') ! 437: break; ! 438: if (c == '\t') ! 439: col += (tabstop - (col % tabstop)); ! 440: else if (isctrl(c)) ! 441: col += 2; ! 442: else ! 443: col += 1; ! 444: } ! 445: #ifdef MAC ! 446: sputc(BUFSTART); /* Okay because we can't be interrupted */ ! 447: #endif ! 448: ! 449: if (c != '\0') while ((c = *bp++) != '\0') { ! 450: if (AbortCnt < 0) { ! 451: AbortCnt = BufSize; ! 452: if ((InputPending = charp()) != '\0') { ! 453: aborted = 1; ! 454: break; ! 455: } ! 456: } ! 457: if (c == '\t') { ! 458: int nchars = (tabstop - (col % tabstop)); ! 459: ! 460: col += nchars; ! 461: if (visspace) { ! 462: soutputc('>'); ! 463: nchars -= 1; ! 464: } ! 465: while (--nchars >= 0) ! 466: soutputc(' '); ! 467: if (n <= 0) ! 468: break; ! 469: } else if (isctrl(c)) { ! 470: soutputc('^'); ! 471: soutputc((c == '\177') ? '?' : c + '@'); ! 472: col += 2; ! 473: #ifdef TERMCAP ! 474: } else if (HZ && c == '~') { ! 475: soutputc('`'); ! 476: col += 1; ! 477: #endif ! 478: } else { ! 479: if (c == ' ' && visspace) ! 480: c = '_'; ! 481: #ifdef IBMPC ! 482: if (c == 255) ! 483: c = 1; ! 484: #endif /* IBMPC */ ! 485: soutputc(c); ! 486: col += 1; ! 487: } ! 488: } ! 489: if (n <= 0) { ! 490: if ((*bp == '\0') && (c != '\t') && !isctrl(c)) ! 491: sputc(c); ! 492: else ! 493: sputc('!'); ! 494: } ! 495: if (cursor > Curline->s_length) ! 496: Curline->s_length = cursor; ! 497: #ifdef MAC ! 498: sputc(BUFFLUSH); ! 499: #endif ! 500: return !aborted; /* Didn't abort */ ! 501: } ! 502: ! 503: void ! 504: i_set(nline, ncol) ! 505: register int nline, ! 506: ncol; ! 507: { ! 508: Curline = &Screen[nline]; ! 509: cursor = Curline->s_line + ncol; ! 510: cursend = &Curline->s_line[CO - 1]; ! 511: i_line = nline; ! 512: i_col = ncol; ! 513: } ! 514: ! 515: #if !(defined(MAC) || defined(IBMPC)) ! 516: void ! 517: SO_on() ! 518: { ! 519: /* If there are magic cookies, then WHERE the SO string is ! 520: printed decides where the SO actually starts on the screen. ! 521: So it's important to make sure the cursor is positioned there ! 522: anyway. I think this is right. */ ! 523: if (SG != 0) { ! 524: Placur(i_line, i_col); ! 525: i_col += SG; ! 526: CapCol += SG; ! 527: } ! 528: putpad(SO, 1); ! 529: } ! 530: ! 531: void ! 532: SO_off() ! 533: { ! 534: /* see comment in SO_on() */ ! 535: if (SG != 0) { ! 536: Placur(i_line, i_col); ! 537: i_col += SG; ! 538: CapCol += SG; ! 539: } ! 540: putpad(SE, 1); ! 541: } ! 542: #endif ! 543: ! 544: /* Insert `num' lines a top, but leave all the lines BELOW `bottom' ! 545: alone (at least they won't look any different when we are done). ! 546: This changes the screen array AND does the physical changes. */ ! 547: ! 548: void ! 549: v_ins_line(num, top, bottom) ! 550: int num, ! 551: top, ! 552: bottom; ! 553: { ! 554: register int i; ! 555: ! 556: /* Save the screen pointers. */ ! 557: ! 558: for(i = 0; i < num && top + i <= bottom; i++) ! 559: Savelines[i] = Screen[bottom - i]; ! 560: ! 561: /* Num number of bottom lines will be lost. ! 562: Copy everything down num number of times. */ ! 563: ! 564: for (i = bottom; i > top && i-num >= 0; i--) ! 565: Screen[i] = Screen[i - num]; ! 566: ! 567: /* Restore the saved ones, making them blank. */ ! 568: ! 569: for (i = 0; i < num; i++) { ! 570: Screen[top + i] = Savelines[i]; ! 571: clrline(Screen[top + i].s_line, Screen[top + i].s_length); ! 572: Screen[top + i].s_length = Screen[top + i].s_line; ! 573: } ! 574: ! 575: #if !(defined(IBMPC) || defined(MAC)) ! 576: (*TTins_line)(top, bottom, num); ! 577: #endif ! 578: ! 579: #ifdef MAC ! 580: i_lines(top, bottom, num); ! 581: #endif ! 582: ! 583: #ifdef IBMPC ! 584: scr_win((int) -num, (unsigned char) top, 0, (unsigned char) bottom, CHPL-1); ! 585: #endif ! 586: } ! 587: ! 588: /* Delete `num' lines starting at `top' leaving the lines below `bottom' ! 589: alone. This updates the internal image as well as the physical image. */ ! 590: ! 591: void ! 592: v_del_line(num, top, bottom) ! 593: int num, ! 594: top, ! 595: bottom; ! 596: { ! 597: register int i, ! 598: bot; ! 599: ! 600: bot = bottom; ! 601: ! 602: /* Save the lost lines. */ ! 603: ! 604: for (i = 0; i < num && top + i <= bottom; i++) ! 605: Savelines[i] = Screen[top + i]; ! 606: ! 607: /* Copy everything up num number of lines. */ ! 608: ! 609: for (i = top; num + i <= bottom; i++) ! 610: Screen[i] = Screen[i + num]; ! 611: ! 612: /* Restore the lost ones, clearing them. */ ! 613: ! 614: for (i = 0; i < num; i++) { ! 615: Screen[bottom - i] = Savelines[i]; ! 616: clrline(Screen[bot].s_line, Screen[bot].s_length); ! 617: Screen[bot].s_length = Screen[bot].s_line; ! 618: bot -= 1; ! 619: } ! 620: ! 621: #if !(defined(IBMPC) || defined(MAC)) ! 622: (*TTdel_line)(top, bottom, num); ! 623: #endif ! 624: ! 625: #ifdef MAC ! 626: d_lines(top, bottom, num); ! 627: #endif ! 628: ! 629: #ifdef IBMPC ! 630: scr_win(num, (unsigned char) top, 0, (unsigned char) bottom, CHPL-1); ! 631: #endif ! 632: ! 633: } ! 634: ! 635: #if !(defined(MAC) || defined(IBMPC)) /* remainder of this file */ ! 636: ! 637: /* The cursor optimization happens here. You may decide that this ! 638: is going too far with cursor optimization, or perhaps it should ! 639: limit the amount of checking to when the output speed is slow. ! 640: What ever turns you on ... */ ! 641: ! 642: struct cursaddr { ! 643: int cm_numchars; ! 644: void (*cm_proc) (); ! 645: }; ! 646: ! 647: private char *Cmstr; ! 648: private struct cursaddr *HorMin, ! 649: *VertMin, ! 650: *DirectMin; ! 651: ! 652: private void ! 653: GENi_lines proto((int, int, int)), ! 654: GENd_lines proto((int, int, int)), ! 655: ForMotion proto((int)), ! 656: ForTab proto((int)), ! 657: BackMotion proto((int)), ! 658: RetTab proto((int)), ! 659: DownMotion proto((int)), ! 660: UpMotion proto((int)), ! 661: GoDirect proto((int, int)), ! 662: HomeGo proto((int, int)), ! 663: BottomUp proto((int, int)); ! 664: ! 665: ! 666: private struct cursaddr WarpHor[] = { ! 667: 0, ForMotion, ! 668: 0, ForTab, ! 669: 0, BackMotion, ! 670: 0, RetTab ! 671: }; ! 672: ! 673: private struct cursaddr WarpVert[] = { ! 674: 0, DownMotion, ! 675: 0, UpMotion ! 676: }; ! 677: ! 678: private struct cursaddr WarpDirect[] = { ! 679: 0, GoDirect, ! 680: 0, HomeGo, ! 681: 0, BottomUp ! 682: }; ! 683: ! 684: #undef FORWARD ! 685: #define FORWARD 0 /* Move forward */ ! 686: #define FORTAB 1 /* Forward using tabs */ ! 687: #undef BACKWARD ! 688: #define BACKWARD 2 /* Move backward */ ! 689: #define RETFORWARD 3 /* Beginning of line and then tabs */ ! 690: #define NUMHOR 4 ! 691: ! 692: #define DOWN 0 /* Move down */ ! 693: #define UPMOVE 1 /* Move up */ ! 694: #define NUMVERT 2 ! 695: ! 696: #define DIRECT 0 /* Using CM */ ! 697: #define HOME 1 /* HOME */ ! 698: #define LOWER 2 /* Lower Line */ ! 699: #define NUMDIRECT 3 ! 700: ! 701: #define home() Placur(0, 0) ! 702: #define LowLine() { putpad(LL, 1); CapLine = ILI; CapCol = 0; } ! 703: #define PrintHo() { putpad(HO, 1); CapLine = CapCol = 0; } ! 704: ! 705: int phystab = 8; ! 706: ! 707: private void ! 708: GoDirect(line, col) ! 709: register int line, ! 710: col; ! 711: { ! 712: putpad(Cmstr, 1); ! 713: CapLine = line; ! 714: CapCol = col; ! 715: } ! 716: ! 717: private void ! 718: RetTab(col) ! 719: register int col; ! 720: { ! 721: jputchar('\r'); ! 722: CapCol = 0; ! 723: ForTab(col); ! 724: } ! 725: ! 726: private void ! 727: HomeGo(line, col) ! 728: int line, ! 729: col; ! 730: { ! 731: PrintHo(); ! 732: DownMotion(line); ! 733: ForTab(col); ! 734: } ! 735: ! 736: private void ! 737: BottomUp(line, col) ! 738: register int line, ! 739: col; ! 740: { ! 741: LowLine(); ! 742: UpMotion(line); ! 743: ForTab(col); ! 744: } ! 745: ! 746: /* Tries to move forward using tabs (if possible). It tabs to the ! 747: closest tabstop which means it may go past 'destcol' and backspace ! 748: to it. */ ! 749: ! 750: private void ! 751: ForTab(destcol) ! 752: int destcol; ! 753: { ! 754: register int tabgoal, ! 755: ntabs, ! 756: tabstp = phystab; ! 757: ! 758: if (TABS && (tabstp > 0)) { ! 759: tabgoal = destcol + (tabstp / 2); ! 760: tabgoal -= (tabgoal % tabstp); ! 761: ! 762: /* Don't tab to last place or else it is likely to screw up. */ ! 763: if (tabgoal >= CO) ! 764: tabgoal -= tabstp; ! 765: ! 766: ntabs = (tabgoal / tabstp) - (CapCol / tabstp); ! 767: while (--ntabs >= 0) ! 768: jputchar('\t'); ! 769: CapCol = tabgoal; ! 770: } ! 771: if (CapCol > destcol) ! 772: BackMotion(destcol); ! 773: else if (CapCol < destcol) ! 774: ForMotion(destcol); ! 775: } ! 776: ! 777: private void ! 778: ForMotion(destcol) ! 779: register int destcol; ! 780: { ! 781: register int nchars = destcol - CapCol; ! 782: register char *cp = &Screen[CapLine].s_line[CapCol]; ! 783: ! 784: while (--nchars >= 0) ! 785: jputchar(*cp++ & CHARMASK); ! 786: CapCol = destcol; ! 787: } ! 788: ! 789: private void ! 790: BackMotion(destcol) ! 791: register int destcol; ! 792: { ! 793: register int nchars = CapCol - destcol; ! 794: ! 795: if (BC) ! 796: while (--nchars >= 0) ! 797: putpad(BC, 1); ! 798: else ! 799: while (--nchars >= 0) ! 800: jputchar('\b'); ! 801: CapCol = destcol; ! 802: } ! 803: ! 804: private void ! 805: DownMotion(destline) ! 806: register int destline; ! 807: { ! 808: register int nlines = destline - CapLine; ! 809: ! 810: while (--nlines >= 0) ! 811: putpad(DO, 1); ! 812: CapLine = destline; ! 813: } ! 814: ! 815: private void ! 816: UpMotion(destline) ! 817: register int destline; ! 818: { ! 819: register int nchars = CapLine - destline; ! 820: ! 821: while (--nchars >= 0) ! 822: putpad(UP, 1); ! 823: CapLine = destline; ! 824: } ! 825: ! 826: #ifdef ID_CHAR ! 827: static int EIlen; ! 828: #endif ! 829: ! 830: #ifndef IBMPC ! 831: ! 832: void ! 833: InitCM() ! 834: { ! 835: HOlen = HO ? strlen(HO) : 1000; ! 836: LLlen = LL ? strlen(LL) : 1000; ! 837: UPlen = UP ? strlen(UP) : 1000; ! 838: #ifdef ID_CHAR ! 839: if (EI) ! 840: EIlen = strlen(EI); ! 841: #endif ! 842: } ! 843: ! 844: private int ForNum proto((int from, int to)); ! 845: ! 846: void ! 847: Placur(line, col) ! 848: int line, ! 849: col; ! 850: { ! 851: int dline, /* Number of lines to move */ ! 852: dcol; /* Number of columns to move */ ! 853: register int best, ! 854: i; ! 855: register struct cursaddr *cp; ! 856: int xtracost = 0; /* Misc addition to cost. */ ! 857: ! 858: #define CursMin(which,addrs,max) { \ ! 859: for (best = 0, cp = &(addrs)[1], i = 1; i < (max); i++, cp++) \ ! 860: if (cp->cm_numchars < (addrs)[best].cm_numchars) \ ! 861: best = i; \ ! 862: (which) = &(addrs)[best]; \ ! 863: } ! 864: ! 865: if (line == CapLine && col == CapCol) ! 866: return; /* We are already there. */ ! 867: ! 868: dline = line - CapLine; ! 869: dcol = col - CapCol; ! 870: #ifdef ID_CHAR ! 871: if (IN_INSmode && MI) ! 872: xtracost = EIlen + IMlen; ! 873: /* If we're already in insert mode, it is likely that we will ! 874: want to be in insert mode again, after the insert. */ ! 875: #endif ! 876: ! 877: /* Number of characters to move horizontally for each case. ! 878: 1: Just move forward by typing the right character on the screen. ! 879: 2: Print the correct number of back spaces. ! 880: 3: Try tabbing to the correct place. ! 881: 4: Try going to the beginning of the line, and then tab. */ ! 882: ! 883: if (dcol == 1 || dcol == 0) { /* Most common case. */ ! 884: HorMin = &WarpHor[FORWARD]; ! 885: HorMin->cm_numchars = dcol + xtracost; ! 886: } else { ! 887: WarpHor[FORWARD].cm_numchars = dcol >= 0 ? dcol + xtracost : 1000; ! 888: WarpHor[BACKWARD].cm_numchars = dcol < 0 ? -(dcol + xtracost) : 1000; ! 889: WarpHor[FORTAB].cm_numchars = dcol >= 0 && TABS ? ! 890: ForNum(CapCol, col) + xtracost : 1000; ! 891: WarpHor[RETFORWARD].cm_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col)); ! 892: ! 893: /* Which is the shortest of the bunch */ ! 894: ! 895: CursMin(HorMin, WarpHor, NUMHOR); ! 896: } ! 897: ! 898: /* Moving vertically is more simple. */ ! 899: ! 900: WarpVert[DOWN].cm_numchars = dline >= 0 ? dline : 1000; ! 901: WarpVert[UPMOVE].cm_numchars = dline < 0 ? ((-dline) * UPlen) : 1000; ! 902: ! 903: /* Which of these is simpler */ ! 904: CursMin(VertMin, WarpVert, NUMVERT); ! 905: ! 906: /* Homing first and lowering first are considered ! 907: direct motions. ! 908: Homing first's total is the sum of the cost of homing ! 909: and the sum of tabbing (if possible) to the right. */ ! 910: ! 911: if (VertMin->cm_numchars + HorMin->cm_numchars <= 3) { ! 912: DirectMin = &WarpDirect[DIRECT]; /* A dummy ... */ ! 913: DirectMin->cm_numchars = 100; ! 914: } else { ! 915: WarpDirect[DIRECT].cm_numchars = CM ? ! 916: strlen(Cmstr = tgoto(CM, col, line)) : 1000; ! 917: WarpDirect[HOME].cm_numchars = HOlen + line + ! 918: WarpHor[RETFORWARD].cm_numchars; ! 919: WarpDirect[LOWER].cm_numchars = LLlen + ((ILI - line) * UPlen) + ! 920: WarpHor[RETFORWARD].cm_numchars; ! 921: CursMin(DirectMin, WarpDirect, NUMDIRECT); ! 922: } ! 923: ! 924: if (HorMin->cm_numchars + VertMin->cm_numchars < DirectMin->cm_numchars) { ! 925: if (line != CapLine) ! 926: (*VertMin->cm_proc)(line); ! 927: if (col != CapCol) { ! 928: #ifdef ID_CHAR ! 929: if (IN_INSmode) /* We may use real characters ... */ ! 930: INSmode(0); ! 931: #endif ! 932: (*HorMin->cm_proc)(col); ! 933: } ! 934: } else { ! 935: #ifdef ID_CHAR ! 936: if (IN_INSmode && !MI) ! 937: INSmode(0); ! 938: #endif ! 939: (*DirectMin->cm_proc)(line, col); ! 940: } ! 941: } ! 942: ! 943: #endif /* IBMPC */ ! 944: ! 945: #define abs(x) ((x) >= 0 ? (x) : -(x)) ! 946: ! 947: private int ! 948: ForNum(from, to) ! 949: register int from; ! 950: int to; ! 951: { ! 952: register int tabgoal, ! 953: tabstp = phystab; ! 954: int numchars = 0; ! 955: ! 956: if (from >= to) ! 957: return from - to; ! 958: if (TABS && (tabstp > 0)) { ! 959: tabgoal = to + (tabstp / 2); ! 960: tabgoal -= (tabgoal % tabstp); ! 961: if (tabgoal >= CO) ! 962: tabgoal -= tabstp; ! 963: numchars = (tabgoal / tabstop) - (from / tabstp); ! 964: from = tabgoal; ! 965: } ! 966: return numchars + abs(from - to); ! 967: } ! 968: ! 969: #ifdef WIRED_TERMS ! 970: ! 971: private void ! 972: BGi_lines(top, bottom, num) ! 973: int top, ! 974: bottom, ! 975: num; ! 976: { ! 977: writef("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num); ! 978: CapCol = CapLine = 0; ! 979: } ! 980: ! 981: private void ! 982: SUNi_lines(top, bottom, num) ! 983: int top, ! 984: bottom, ! 985: num; ! 986: { ! 987: Placur(bottom - num + 1, 0); ! 988: writef("\033[%dM", num); ! 989: Placur(top, 0); ! 990: writef("\033[%dL", num); ! 991: } ! 992: ! 993: private void ! 994: C100i_lines(top, bottom, num) ! 995: int top, ! 996: bottom, ! 997: num; ! 998: { ! 999: if (num <= 1) { ! 1000: GENi_lines(top, bottom, num); ! 1001: return; ! 1002: } ! 1003: writef("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO); ! 1004: CapLine = CapCol = 0; ! 1005: Placur(top, 0); ! 1006: while (num--) ! 1007: putpad(AL, ILI - CapLine); ! 1008: writef("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO); ! 1009: CapLine = CapCol = 0; ! 1010: } ! 1011: ! 1012: #endif /* WIRED_TERMS */ ! 1013: ! 1014: private void ! 1015: GENi_lines(top, bottom, num) ! 1016: int top, ! 1017: bottom, ! 1018: num; ! 1019: { ! 1020: register int i; ! 1021: ! 1022: if (CS) { ! 1023: putpad(tgoto(CS, bottom, top), 1); ! 1024: CapCol = CapLine = 0; ! 1025: Placur(top, 0); ! 1026: for (i = 0; i < num; i++) ! 1027: putpad(SR, bottom - top); ! 1028: putpad(tgoto(CS, ILI, 0), 1); ! 1029: CapCol = CapLine = 0; ! 1030: } else { ! 1031: Placur(bottom - num + 1, 0); ! 1032: if (M_DL && (num > 1)) { ! 1033: putargpad(M_DL, num, ILI - CapLine); ! 1034: } else { ! 1035: for (i = 0; i < num; i++) ! 1036: putpad(DL, ILI - CapLine); ! 1037: } ! 1038: Placur(top, 0); ! 1039: if (M_AL && (num > 1)) { ! 1040: putargpad(M_AL, num, ILI - CapLine); ! 1041: } else { ! 1042: for (i = 0; i < num; i++) ! 1043: putpad(AL, ILI - CapLine); ! 1044: } ! 1045: } ! 1046: } ! 1047: ! 1048: #ifdef WIRED_TERMS ! 1049: ! 1050: private void ! 1051: BGd_lines(top, bottom, num) ! 1052: int top, ! 1053: bottom, ! 1054: num; ! 1055: { ! 1056: writef("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num); ! 1057: CapCol = CapLine = 0; ! 1058: } ! 1059: ! 1060: private void ! 1061: SUNd_lines(top, bottom, num) ! 1062: int top, ! 1063: bottom, ! 1064: num; ! 1065: { ! 1066: Placur(top, 0); ! 1067: writef("\033[%dM", num); ! 1068: Placur(bottom + 1 - num, 0); ! 1069: writef("\033[%dL", num); ! 1070: } ! 1071: ! 1072: private void ! 1073: C100d_lines(top, bottom, num) ! 1074: int top, ! 1075: bottom, ! 1076: num; ! 1077: { ! 1078: if (num <= 1) { ! 1079: GENd_lines(top, bottom, num); ! 1080: return; ! 1081: } ! 1082: writef("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO); ! 1083: CapLine = CapCol = 0; ! 1084: Placur(top, 0); ! 1085: while (num--) ! 1086: putpad(DL, ILI - CapLine); ! 1087: writef("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO); ! 1088: CapLine = CapCol = 0; ! 1089: } ! 1090: ! 1091: #endif /* WIRED_TERMS */ ! 1092: ! 1093: private void ! 1094: GENd_lines(top, bottom, num) ! 1095: int top, ! 1096: bottom, ! 1097: num; ! 1098: { ! 1099: register int i; ! 1100: ! 1101: if (CS) { ! 1102: putpad(tgoto(CS, bottom, top), 1); ! 1103: CapCol = CapLine = 0; ! 1104: Placur(bottom, 0); ! 1105: for (i = 0; i < num; i++) ! 1106: putpad(SF, bottom - top); ! 1107: putpad(tgoto(CS, ILI, 0), 1); ! 1108: CapCol = CapLine = 0; ! 1109: } else { ! 1110: Placur(top, 0); ! 1111: if (M_DL && (num > 1)) { ! 1112: putargpad(M_DL, num, ILI - top); ! 1113: } else { ! 1114: for (i = 0; i < num; i++) ! 1115: putpad(DL, ILI - top); ! 1116: } ! 1117: Placur(bottom + 1 - num, 0); ! 1118: if (M_AL && (num > 1)) { ! 1119: putargpad(M_AL, num, ILI - CapLine); ! 1120: } else { ! 1121: for (i = 0; i < num; i++) ! 1122: putpad(AL, ILI - CapLine); ! 1123: } ! 1124: } ! 1125: } ! 1126: ! 1127: private const struct ID_lookup { ! 1128: char *ID_name; ! 1129: void (*I_proc) proto((int, int, int)); /* proc to insert lines */ ! 1130: void (*D_proc) proto((int, int, int)); /* proc to delete lines */ ! 1131: } ID_trms[] = { ! 1132: "generic", GENi_lines, GENd_lines, /* This should stay here */ ! 1133: #ifdef WIRED_TERMS ! 1134: "sun", SUNi_lines, SUNd_lines, ! 1135: "bg", BGi_lines, BGd_lines, ! 1136: "c1", C100i_lines, C100d_lines, ! 1137: #endif /* WIRED_TERMS */ ! 1138: 0, 0, 0 ! 1139: }; ! 1140: ! 1141: void ! 1142: IDline_setup(tname) ! 1143: char *tname; ! 1144: { ! 1145: register const struct ID_lookup *idp; ! 1146: ! 1147: for (idp = &ID_trms[1]; idp->ID_name; idp++) ! 1148: if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0) ! 1149: break; ! 1150: if (idp->ID_name == 0) ! 1151: idp = &ID_trms[0]; ! 1152: #ifndef IBMPC ! 1153: TTins_line = idp->I_proc; ! 1154: TTdel_line = idp->D_proc; ! 1155: #endif ! 1156: } ! 1157: ! 1158: #endif /* MAC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.