|
|
1.1 ! root 1: /* redraw.c */ ! 2: ! 3: /* Author: ! 4: * Steve Kirkendall ! 5: * 16820 SW Tallac Way ! 6: * Beaverton, OR 97006 ! 7: * [email protected], or ...uunet!tektronix!psueea!jove!kirkenda ! 8: */ ! 9: ! 10: ! 11: /* This file contains functions that draw text on the screen. The major entry ! 12: * points are: ! 13: * redrawrange() - called from modify.c to give hints about what parts ! 14: * of the screen need to be redrawn. ! 15: * redraw() - redraws the screen (or part of it) and positions ! 16: * the cursor where it belongs. ! 17: * idx2col() - converts a markidx() value to a logical column number. ! 18: */ ! 19: ! 20: #include "config.h" ! 21: #include "vi.h" ! 22: ! 23: /* This variable contains the line number that smartdrawtext() knows best */ ! 24: static long smartlno; ! 25: ! 26: /* This function remebers where changes were made, so that the screen can be ! 27: * redraw in a more efficient manner. ! 28: */ ! 29: static long redrawafter; /* line# of first line that must be redrawn */ ! 30: static long preredraw; /* line# of last line changed, before change */ ! 31: static long postredraw; /* line# of last line changed, after change */ ! 32: void redrawrange(after, pre, post) ! 33: long after; /* lower bound of redrawafter */ ! 34: long pre; /* upper bound of preredraw */ ! 35: long post; /* upper bound of postredraw */ ! 36: { ! 37: if (after == redrawafter) ! 38: { ! 39: /* multiple insertions/deletions at the same place -- combine ! 40: * them ! 41: */ ! 42: preredraw -= (post - pre); ! 43: if (postredraw < post) ! 44: { ! 45: preredraw += (post - postredraw); ! 46: postredraw = post; ! 47: } ! 48: if (redrawafter > preredraw) ! 49: { ! 50: redrawafter = preredraw; ! 51: } ! 52: if (redrawafter < 1L) ! 53: { ! 54: redrawafter = 0L; ! 55: preredraw = postredraw = INFINITY; ! 56: } ! 57: } ! 58: else if (postredraw > 0L) ! 59: { ! 60: /* multiple changes in different places -- redraw everything ! 61: * after "after". ! 62: */ ! 63: postredraw = preredraw = INFINITY; ! 64: if (after < redrawafter) ! 65: redrawafter = after; ! 66: } ! 67: else ! 68: { ! 69: /* first change */ ! 70: redrawafter = after; ! 71: preredraw = pre; ! 72: postredraw = post; ! 73: } ! 74: } ! 75: ! 76: ! 77: #ifndef NO_CHARATTR ! 78: /* see if a given line uses character attribute strings */ ! 79: static int hasattr(lno, text) ! 80: long lno; /* the line# of the cursor */ ! 81: REG char *text; /* the text of the line, from fetchline */ ! 82: { ! 83: static long plno; /* previous line number */ ! 84: static long chgs; /* previous value of changes counter */ ! 85: static int panswer;/* previous answer */ ! 86: char *scan; ! 87: ! 88: /* if charattr is off, then the answer is "no, it doesn't" */ ! 89: if (!*o_charattr) ! 90: { ! 91: chgs = 0; /* <- forces us to check if charattr is later set */ ! 92: return FALSE; ! 93: } ! 94: ! 95: /* if we already know the answer, return it... */ ! 96: if (lno == plno && chgs == changes) ! 97: { ! 98: return panswer; ! 99: } ! 100: ! 101: /* get the line & look for "\fX" */ ! 102: if (!text[0] || !text[1] || !text[2]) ! 103: { ! 104: panswer = FALSE; ! 105: } ! 106: else ! 107: { ! 108: for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++) ! 109: { ! 110: } ! 111: panswer = (scan[2] != '\0'); ! 112: } ! 113: ! 114: /* save the results */ ! 115: plno = lno; ! 116: chgs = changes; ! 117: ! 118: /* return the results */ ! 119: return panswer; ! 120: } ! 121: #endif ! 122: ! 123: ! 124: ! 125: /* This function converts a MARK to a column number. It doesn't automatically ! 126: * adjust for leftcol; that must be done by the calling function ! 127: */ ! 128: int idx2col(curs, text, inputting) ! 129: MARK curs; /* the line# & index# of the cursor */ ! 130: REG char *text; /* the text of the line, from fetchline */ ! 131: int inputting; /* boolean: called from input() ? */ ! 132: { ! 133: static MARK pcursor;/* previous cursor, for possible shortcut */ ! 134: static MARK pcol; /* column number for pcol */ ! 135: static long chgs; /* previous value of changes counter */ ! 136: REG int col; /* used to count column numbers */ ! 137: REG int idx; /* used to count down the index */ ! 138: REG int i; ! 139: ! 140: /* for now, assume we have to start counting at the left edge */ ! 141: col = 0; ! 142: idx = markidx(curs); ! 143: ! 144: /* if the file hasn't changed & line number is the same & it has no ! 145: * embedded character attribute strings, can we do shortcuts? ! 146: */ ! 147: if (chgs == changes ! 148: && !((curs ^ pcursor) & ~(BLKSIZE - 1)) ! 149: #ifndef NO_CHARATTR ! 150: && !hasattr(markline(curs), text) ! 151: #endif ! 152: ) ! 153: { ! 154: /* no movement? */ ! 155: if (curs == pcursor) ! 156: { ! 157: /* return the column of the char; for tabs, return its last column */ ! 158: if (text[idx] == '\t' && !inputting && !*o_list) ! 159: { ! 160: return pcol + *o_tabstop - (pcol % *o_tabstop) - 1; ! 161: } ! 162: else ! 163: { ! 164: return pcol; ! 165: } ! 166: } ! 167: ! 168: /* movement to right? */ ! 169: if (curs > pcursor) ! 170: { ! 171: /* start counting from previous place */ ! 172: col = pcol; ! 173: idx = markidx(curs) - markidx(pcursor); ! 174: text += markidx(pcursor); ! 175: } ! 176: } ! 177: ! 178: /* count over to the char after the idx position */ ! 179: while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */ ! 180: { ! 181: if (i == '\t' && !*o_list) ! 182: { ! 183: col += *o_tabstop; ! 184: col -= col % *o_tabstop; ! 185: } ! 186: else if (i >= '\0' && i < ' ' || i == '\177') ! 187: { ! 188: col += 2; ! 189: } ! 190: #ifndef NO_CHARATTR ! 191: else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr) ! 192: { ! 193: text += 2; /* plus one more at bottom of loop */ ! 194: idx -= 2; ! 195: } ! 196: #endif ! 197: else ! 198: { ! 199: col++; ! 200: } ! 201: text++; ! 202: idx--; ! 203: } ! 204: ! 205: /* save stuff to speed next call */ ! 206: pcursor = curs; ! 207: pcol = col; ! 208: chgs = changes; ! 209: ! 210: /* return the column of the char; for tabs, return its last column */ ! 211: if (*text == '\t' && !inputting && !*o_list) ! 212: { ! 213: return col + *o_tabstop - (col % *o_tabstop) - 1; ! 214: } ! 215: else ! 216: { ! 217: return col; ! 218: } ! 219: } ! 220: ! 221: ! 222: /* This function is similar to idx2col except that it takes care of sideways ! 223: * scrolling - for the given line, at least. ! 224: */ ! 225: int mark2phys(m, text, inputting) ! 226: MARK m; /* a mark to convert */ ! 227: char *text; /* the line that m refers to */ ! 228: int inputting; /* boolean: caled from input() ? */ ! 229: { ! 230: int i; ! 231: ! 232: i = idx2col(m, text, inputting); ! 233: while (i < leftcol) ! 234: { ! 235: leftcol -= *o_sidescroll; ! 236: mustredraw = TRUE; ! 237: redrawrange(1L, INFINITY, INFINITY); ! 238: qaddch('\r'); ! 239: /* drawtext(text); */ ! 240: } ! 241: while (i > rightcol) ! 242: { ! 243: leftcol += *o_sidescroll; ! 244: mustredraw = TRUE; ! 245: redrawrange(1L, INFINITY, INFINITY); ! 246: qaddch('\r'); ! 247: /* drawtext(text); */ ! 248: } ! 249: physcol = i - leftcol; ! 250: physrow = markline(m) - topline; ! 251: ! 252: return physcol; ! 253: } ! 254: ! 255: /* This function draws a single line of text on the screen. The screen's ! 256: * cursor is assumed to be located at the leftmost column of the appropriate ! 257: * row. ! 258: */ ! 259: static void drawtext(text, clr) ! 260: REG char *text; /* the text to draw */ ! 261: int clr; /* boolean: do a clrtoeol? */ ! 262: { ! 263: REG int col; /* column number */ ! 264: REG int i; ! 265: REG int tabstop; /* *o_tabstop */ ! 266: REG int limitcol; /* leftcol or leftcol + COLS */ ! 267: int abnormal; /* boolean: charattr != A_NORMAL? */ ! 268: ! 269: #ifndef NO_SENTENCE ! 270: /* if we're hiding format lines, and this is one of them, then hide it */ ! 271: if (*o_hideformat && *text == '.') ! 272: { ! 273: clrtoeol(); ! 274: #if OSK ! 275: qaddch('\l'); ! 276: #else ! 277: qaddch('\n'); ! 278: #endif ! 279: return; ! 280: } ! 281: #endif ! 282: ! 283: /* move some things into registers... */ ! 284: limitcol = leftcol; ! 285: tabstop = *o_tabstop; ! 286: abnormal = FALSE; ! 287: ! 288: #ifndef CRUNCH ! 289: if (clr) ! 290: clrtoeol(); ! 291: #endif ! 292: /* skip stuff that was scrolled off left edge */ ! 293: for (col = 0; ! 294: (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */ ! 295: text++) ! 296: { ! 297: if (i == '\t' && !*o_list) ! 298: { ! 299: col = col + tabstop - (col % tabstop); ! 300: } ! 301: else if (i >= 0 && i < ' ' || i == '\177') ! 302: { ! 303: col += 2; ! 304: } ! 305: #ifndef NO_CHARATTR ! 306: else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr) ! 307: { ! 308: text += 2; /* plus one more as part of "for" loop */ ! 309: ! 310: /* since this attribute might carry over, we need it */ ! 311: switch (*text) ! 312: { ! 313: case 'R': ! 314: case 'P': ! 315: attrset(A_NORMAL); ! 316: abnormal = FALSE; ! 317: break; ! 318: ! 319: case 'B': ! 320: attrset(A_BOLD); ! 321: abnormal = TRUE; ! 322: break; ! 323: ! 324: case 'U': ! 325: attrset(A_UNDERLINE); ! 326: abnormal = TRUE; ! 327: break; ! 328: ! 329: case 'I': ! 330: attrset(A_ALTCHARSET); ! 331: abnormal = TRUE; ! 332: break; ! 333: } ! 334: } ! 335: #endif ! 336: else ! 337: { ! 338: col++; ! 339: } ! 340: } ! 341: ! 342: /* adjust for control char that was partially visible */ ! 343: while (col > limitcol) ! 344: { ! 345: qaddch(' '); ! 346: limitcol++; ! 347: } ! 348: ! 349: /* now for the visible characters */ ! 350: for (limitcol = leftcol + COLS; ! 351: (i = *text) && col < limitcol; ! 352: text++) ! 353: { ! 354: if (i == '\t' && !*o_list) ! 355: { ! 356: i = col + tabstop - (col % tabstop); ! 357: if (i < limitcol) ! 358: { ! 359: #ifdef CRUNCH ! 360: if (!clr && has_PT && !((i - leftcol) & 7)) ! 361: #else ! 362: if (has_PT && !((i - leftcol) & 7)) ! 363: #endif ! 364: { ! 365: do ! 366: { ! 367: qaddch('\t'); ! 368: col += 8; /* not exact! */ ! 369: } while (col < i); ! 370: col = i; /* NOW it is exact */ ! 371: } ! 372: else ! 373: { ! 374: do ! 375: { ! 376: qaddch(' '); ! 377: col++; ! 378: } while (col < i); ! 379: } ! 380: } ! 381: else /* tab ending after screen? next line! */ ! 382: { ! 383: col = limitcol; ! 384: if (has_AM) ! 385: { ! 386: addch('\n'); /* GB */ ! 387: } ! 388: } ! 389: } ! 390: else if (i >= 0 && i < ' ' || i == '\177') ! 391: { ! 392: col += 2; ! 393: qaddch('^'); ! 394: if (col <= limitcol) ! 395: { ! 396: qaddch(i ^ '@'); ! 397: } ! 398: } ! 399: #ifndef NO_CHARATTR ! 400: else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr) ! 401: { ! 402: text += 2; /* plus one more as part of "for" loop */ ! 403: switch (*text) ! 404: { ! 405: case 'R': ! 406: case 'P': ! 407: attrset(A_NORMAL); ! 408: abnormal = FALSE; ! 409: break; ! 410: ! 411: case 'B': ! 412: attrset(A_BOLD); ! 413: abnormal = TRUE; ! 414: break; ! 415: ! 416: case 'U': ! 417: attrset(A_UNDERLINE); ! 418: abnormal = TRUE; ! 419: break; ! 420: ! 421: case 'I': ! 422: attrset(A_ALTCHARSET); ! 423: abnormal = TRUE; ! 424: break; ! 425: } ! 426: } ! 427: #endif ! 428: else ! 429: { ! 430: col++; ! 431: qaddch(i); ! 432: } ! 433: } ! 434: ! 435: /* get ready for the next line */ ! 436: #ifndef NO_CHARATTR ! 437: if (abnormal) ! 438: { ! 439: attrset(A_NORMAL); ! 440: } ! 441: #endif ! 442: if (*o_list && col < limitcol) ! 443: { ! 444: qaddch('$'); ! 445: col++; ! 446: } ! 447: #ifdef CRUNCH ! 448: if (clr && col < limitcol) ! 449: { ! 450: clrtoeol(); ! 451: } ! 452: #endif ! 453: if (!has_AM || col < limitcol) ! 454: { ! 455: addch('\n'); ! 456: } ! 457: } ! 458: ! 459: ! 460: #ifndef CRUNCH ! 461: static void nudgecursor(same, scan, new, lno) ! 462: int same; /* number of chars to be skipped over */ ! 463: char *scan; /* where the same chars end */ ! 464: char *new; /* where the visible part of the line starts */ ! 465: long lno; /* line number of this line */ ! 466: { ! 467: if (same > 0) ! 468: { ! 469: if (same < 5) ! 470: { ! 471: /* move the cursor by overwriting */ ! 472: while (same > 0) ! 473: { ! 474: qaddch(scan[-same]); ! 475: same--; ! 476: } ! 477: } ! 478: else ! 479: { ! 480: /* move the cursor by calling move() */ ! 481: move((int)(lno - topline), (int)(scan - new)); ! 482: } ! 483: } ! 484: } ! 485: #endif /* not CRUNCH */ ! 486: ! 487: /* This function draws a single line of text on the screen, possibly with ! 488: * some cursor optimization. The cursor is repositioned before drawing ! 489: * begins, so its position before doesn't really matter. ! 490: */ ! 491: static void smartdrawtext(text, lno) ! 492: REG char *text; /* the text to draw */ ! 493: long lno; /* line number of the text */ ! 494: { ! 495: #ifdef CRUNCH ! 496: move((int)(lno - topline), 0); ! 497: drawtext(text, TRUE); ! 498: #else /* not CRUNCH */ ! 499: static char old[256]; /* how the line looked last time */ ! 500: char new[256]; /* how it looks now */ ! 501: char *build; /* used to put chars into new[] */ ! 502: char *scan; /* used for moving thru new[] or old[] */ ! 503: char *end; /* last non-blank changed char */ ! 504: char *shift; /* used to insert/delete chars */ ! 505: int same; /* length of a run of unchanged chars */ ! 506: int limitcol; ! 507: int col; ! 508: int i; ! 509: ! 510: # ifndef NO_CHARATTR ! 511: /* if this line has attributes, do it the dumb way instead */ ! 512: if (hasattr(lno, text)) ! 513: { ! 514: move((int)(lno - topline), 0); ! 515: drawtext(text, TRUE); ! 516: return; ! 517: } ! 518: # endif ! 519: # ifndef NO_SENTENCE ! 520: /* if this line is a format line, & we're hiding format lines, then ! 521: * let the dumb drawtext() function handle it ! 522: */ ! 523: if (*o_hideformat && *text == '.') ! 524: { ! 525: move((int)(lno - topline), 0); ! 526: drawtext(text, TRUE); ! 527: return; ! 528: } ! 529: # endif ! 530: ! 531: /* skip stuff that was scrolled off left edge */ ! 532: limitcol = leftcol; ! 533: for (col = 0; ! 534: (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */ ! 535: text++) ! 536: { ! 537: if (i == '\t' && !*o_list) ! 538: { ! 539: col = col + *o_tabstop - (col % *o_tabstop); ! 540: } ! 541: else if (i >= 0 && i < ' ' || i == '\177') ! 542: { ! 543: col += 2; ! 544: } ! 545: else ! 546: { ! 547: col++; ! 548: } ! 549: } ! 550: ! 551: /* adjust for control char that was partially visible */ ! 552: build = new; ! 553: while (col > limitcol) ! 554: { ! 555: *build++ = ' '; ! 556: limitcol++; ! 557: } ! 558: ! 559: /* now for the visible characters */ ! 560: for (limitcol = leftcol + COLS; ! 561: (i = *text) && col < limitcol; ! 562: text++) ! 563: { ! 564: if (i == '\t' && !*o_list) ! 565: { ! 566: i = col + *o_tabstop - (col % *o_tabstop); ! 567: while (col < i && col < limitcol) ! 568: { ! 569: *build++ = ' '; ! 570: col++; ! 571: } ! 572: } ! 573: else if (i >= 0 && i < ' ' || i == '\177') ! 574: { ! 575: col += 2; ! 576: *build++ = '^'; ! 577: if (col <= limitcol) ! 578: { ! 579: *build++ = (i ^ '@'); ! 580: } ! 581: } ! 582: else ! 583: { ! 584: col++; ! 585: *build++ = i; ! 586: } ! 587: } ! 588: if (col < limitcol && *o_list) ! 589: { ! 590: *build++ = '$'; ! 591: col++; ! 592: } ! 593: end = build; ! 594: while (col < limitcol) ! 595: { ! 596: *build++ = ' '; ! 597: col++; ! 598: } ! 599: ! 600: /* locate the last non-blank character */ ! 601: while (end > new && end[-1] == ' ') ! 602: { ! 603: end--; ! 604: } ! 605: ! 606: /* can we optimize the displaying of this line? */ ! 607: if (lno != smartlno) ! 608: { ! 609: /* nope, can't optimize - different line */ ! 610: move((int)(lno - topline), 0); ! 611: for (scan = new, build = old; scan < end; ) ! 612: { ! 613: qaddch(*scan); ! 614: *build++ = *scan++; ! 615: } ! 616: if (end < new + COLS) ! 617: { ! 618: clrtoeol(); ! 619: while (build < old + COLS) ! 620: { ! 621: *build++ = ' '; ! 622: } ! 623: } ! 624: smartlno = lno; ! 625: return; ! 626: } ! 627: ! 628: /* skip any initial unchanged characters */ ! 629: for (scan = new, build = old; scan < end && *scan == *build; scan++, build++) ! 630: { ! 631: } ! 632: move((int)(lno - topline), (int)(scan - new)); ! 633: ! 634: /* The in-between characters must be changed */ ! 635: same = 0; ! 636: while (scan < end) ! 637: { ! 638: /* is this character a match? */ ! 639: if (scan[0] == build[0]) ! 640: { ! 641: same++; ! 642: } ! 643: else /* do we want to insert? */ ! 644: if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM)) ! 645: { ! 646: nudgecursor(same, scan, new, lno); ! 647: same = 0; ! 648: ! 649: insch(*scan); ! 650: for (shift = old + COLS; --shift > build; ) ! 651: { ! 652: shift[0] = shift[-1]; ! 653: } ! 654: *build = *scan; ! 655: } ! 656: else /* do we want to delete? */ ! 657: if (build < old + COLS - 1 && scan[0] == build[1] && has_DC) ! 658: { ! 659: nudgecursor(same, scan, new, lno); ! 660: same = 0; ! 661: ! 662: delch(); ! 663: same++; ! 664: for (shift = build; shift < old + COLS - 1; shift++) ! 665: { ! 666: shift[0] = shift[1]; ! 667: } ! 668: *shift = ' '; ! 669: } ! 670: else /* we must overwrite */ ! 671: { ! 672: nudgecursor(same, scan, new, lno); ! 673: same = 0; ! 674: ! 675: addch(*scan); ! 676: *build = *scan; ! 677: } ! 678: ! 679: build++; ! 680: scan++; ! 681: } ! 682: ! 683: /* maybe clear to EOL */ ! 684: while (build < old + COLS && *build == ' ') ! 685: { ! 686: build++; ! 687: } ! 688: if (build < old + COLS) ! 689: { ! 690: nudgecursor(same, scan, new, lno); ! 691: same = 0; ! 692: ! 693: clrtoeol(); ! 694: while (build < old + COLS) ! 695: { ! 696: *build++ = ' '; ! 697: } ! 698: } ! 699: #endif /* not CRUNCH */ ! 700: } ! 701: ! 702: ! 703: /* This function is used in visual mode for drawing the screen (or just parts ! 704: * of the screen, if that's all thats needed). It also takes care of ! 705: * scrolling. ! 706: */ ! 707: void redraw(curs, inputting) ! 708: MARK curs; /* where to leave the screen's cursor */ ! 709: int inputting; /* boolean: being called from input() ? */ ! 710: { ! 711: char *text; /* a line of text to display */ ! 712: static long chgs; /* previous changes level */ ! 713: long l; ! 714: int i; ! 715: ! 716: /* if curs == MARK_UNSET, then we should reset internal vars */ ! 717: if (curs == MARK_UNSET) ! 718: { ! 719: if (topline < 1 || topline > nlines) ! 720: { ! 721: topline = 1L; ! 722: } ! 723: else ! 724: { ! 725: move(LINES - 1, 0); ! 726: clrtoeol(); ! 727: } ! 728: leftcol = 0; ! 729: mustredraw = TRUE; ! 730: redrawafter = INFINITY; ! 731: preredraw = 0L; ! 732: postredraw = 0L; ! 733: chgs = 0; ! 734: smartlno = 0L; ! 735: return; ! 736: } ! 737: ! 738: /* figure out which column the cursor will be in */ ! 739: l = markline(curs); ! 740: text = fetchline(l); ! 741: mark2phys(curs, text, inputting); ! 742: ! 743: /* adjust topline, if necessary, to get the cursor on the screen */ ! 744: if (l >= topline && l <= botline) ! 745: { ! 746: /* it is on the screen already */ ! 747: ! 748: /* if the file was changed but !mustredraw, then redraw line */ ! 749: if (chgs != changes && !mustredraw) ! 750: { ! 751: smartdrawtext(text, l); ! 752: } ! 753: } ! 754: else if (l < topline && l > topline - LINES && (has_SR || has_AL)) ! 755: { ! 756: /* near top - scroll down */ ! 757: if (!mustredraw) ! 758: { ! 759: move(0,0); ! 760: while (l < topline) ! 761: { ! 762: topline--; ! 763: if (has_SR) ! 764: { ! 765: do_SR(); ! 766: } ! 767: else ! 768: { ! 769: insertln(); ! 770: } ! 771: text = fetchline(topline); ! 772: drawtext(text, FALSE); ! 773: do_UP(); ! 774: } ! 775: ! 776: /* blank out the last line */ ! 777: move(LINES - 1, 0); ! 778: clrtoeol(); ! 779: } ! 780: else ! 781: { ! 782: topline = l; ! 783: redrawafter = INFINITY; ! 784: preredraw = 0L; ! 785: postredraw = 0L; ! 786: } ! 787: } ! 788: else if (l > topline && l < botline + LINES) ! 789: { ! 790: /* near bottom -- scroll up */ ! 791: if (!mustredraw ! 792: #if 1 ! 793: || redrawafter == preredraw && preredraw == botline && postredraw == l ! 794: #endif ! 795: ) ! 796: { ! 797: move(LINES - 1,0); ! 798: clrtoeol(); ! 799: while (l > botline) ! 800: { ! 801: topline++; /* <-- also adjusts botline */ ! 802: text = fetchline(botline); ! 803: drawtext(text, FALSE); ! 804: } ! 805: mustredraw = FALSE; ! 806: } ! 807: else ! 808: { ! 809: topline = l - (LINES - 2); ! 810: redrawafter = INFINITY; ! 811: preredraw = 0L; ! 812: postredraw = 0L; ! 813: } ! 814: } ! 815: else ! 816: { ! 817: /* distant line - center it & force a redraw */ ! 818: topline = l - (LINES / 2) - 1; ! 819: if (topline < 1) ! 820: { ! 821: topline = 1; ! 822: } ! 823: mustredraw = TRUE; ! 824: redrawafter = INFINITY; ! 825: preredraw = 0L; ! 826: postredraw = 0L; ! 827: } ! 828: ! 829: /* Now... do we really have to redraw? */ ! 830: if (mustredraw) ! 831: { ! 832: /* If redrawfter (and friends) aren't set, assume we should ! 833: * redraw everything. ! 834: */ ! 835: if (redrawafter == INFINITY) ! 836: { ! 837: redrawafter = 0L; ! 838: preredraw = postredraw = INFINITY; ! 839: } ! 840: ! 841: /* adjust smartlno to correspond with inserted/deleted lines */ ! 842: if (smartlno >= redrawafter) ! 843: { ! 844: if (smartlno < preredraw) ! 845: { ! 846: smartlno = 0L; ! 847: } ! 848: else ! 849: { ! 850: smartlno += (postredraw - preredraw); ! 851: } ! 852: } ! 853: ! 854: /* should we insert some lines into the screen? */ ! 855: if (preredraw < postredraw && preredraw <= botline) ! 856: { ! 857: /* lines were inserted into the file */ ! 858: ! 859: /* decide where insertion should start */ ! 860: if (preredraw < topline) ! 861: { ! 862: l = topline; ! 863: } ! 864: else ! 865: { ! 866: l = preredraw; ! 867: } ! 868: ! 869: /* insert the lines... maybe */ ! 870: if (l + postredraw - preredraw > botline || !has_AL) ! 871: { ! 872: /* Whoa! a whole screen full - just redraw */ ! 873: preredraw = postredraw = INFINITY; ! 874: } ! 875: else ! 876: { ! 877: /* really insert 'em */ ! 878: move((int)(l - topline), 0); ! 879: for (i = postredraw - preredraw; i > 0; i--) ! 880: { ! 881: insertln(); ! 882: } ! 883: ! 884: /* NOTE: the contents of those lines will be ! 885: * drawn as part of the regular redraw loop. ! 886: */ ! 887: ! 888: /* clear the last line */ ! 889: move(LINES - 1, 0); ! 890: clrtoeol(); ! 891: } ! 892: } ! 893: ! 894: /* do we want to delete some lines from the screen? */ ! 895: if (preredraw > postredraw && postredraw <= botline) ! 896: { ! 897: if (preredraw > botline || !has_DL) ! 898: { ! 899: postredraw = preredraw = INFINITY; ! 900: } ! 901: else /* we'd best delete some lines from the screen */ ! 902: { ! 903: /* clear the last line, so it doesn't look ! 904: * ugly as it gets pulled up into the screen ! 905: */ ! 906: move(LINES - 1, 0); ! 907: clrtoeol(); ! 908: ! 909: /* delete the lines */ ! 910: move((int)(postredraw - topline), 0); ! 911: for (l = postredraw; ! 912: l < preredraw && l <= botline; ! 913: l++) ! 914: { ! 915: deleteln(); ! 916: } ! 917: ! 918: /* draw the lines that are now newly visible ! 919: * at the bottom of the screen ! 920: */ ! 921: i = LINES - 1 + (postredraw - preredraw); ! 922: move(i, 0); ! 923: for (l = topline + i; l <= botline; l++) ! 924: { ! 925: /* clear this line */ ! 926: clrtoeol(); ! 927: ! 928: /* draw the line, or ~ for non-lines */ ! 929: if (l <= nlines) ! 930: { ! 931: text = fetchline(l); ! 932: drawtext(text, FALSE); ! 933: } ! 934: else ! 935: { ! 936: addstr("~\n"); ! 937: } ! 938: } ! 939: } ! 940: } ! 941: ! 942: /* redraw the current line */ ! 943: l = markline(curs); ! 944: pfetch(l); ! 945: smartdrawtext(ptext, l); ! 946: ! 947: /* decide where we should start redrawing from */ ! 948: if (redrawafter < topline) ! 949: { ! 950: l = topline; ! 951: } ! 952: else ! 953: { ! 954: l = redrawafter; ! 955: } ! 956: move((int)(l - topline), 0); ! 957: ! 958: /* draw the other lines */ ! 959: for (; l <= botline && l < postredraw; l++) ! 960: { ! 961: /* we already drew the current line, so skip it now */ ! 962: if (l == smartlno) ! 963: { ! 964: #if OSK ! 965: qaddch('\l'); ! 966: #else ! 967: qaddch('\n'); ! 968: #endif ! 969: continue; ! 970: } ! 971: ! 972: /* draw the line, or ~ for non-lines */ ! 973: if (l <= nlines) ! 974: { ! 975: text = fetchline(l); ! 976: drawtext(text, TRUE); ! 977: } ! 978: else ! 979: { ! 980: qaddch('~'); ! 981: clrtoeol(); ! 982: addch('\n'); ! 983: } ! 984: } ! 985: ! 986: mustredraw = FALSE; ! 987: } ! 988: ! 989: /* force total (non-partial) redraw next time if not set */ ! 990: redrawafter = INFINITY; ! 991: preredraw = 0L; ! 992: postredraw = 0L; ! 993: ! 994: /* move the cursor to where it belongs */ ! 995: move((int)(markline(curs) - topline), physcol); ! 996: wqrefresh(stdscr); ! 997: ! 998: chgs = changes; ! 999: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.