Annotation of src/usr.bin/vim/screen.c, Revision 1.1
1.1 ! downsj 1: /* $OpenBSD$ */
! 2: /* vi:set ts=4 sw=4:
! 3: *
! 4: * VIM - Vi IMproved by Bram Moolenaar
! 5: *
! 6: * Do ":help uganda" in Vim to read copying and usage conditions.
! 7: * Do ":help credits" in Vim to see a list of people who contributed.
! 8: */
! 9:
! 10: /*
! 11: * screen.c: code for displaying on the screen
! 12: */
! 13:
! 14: #include "vim.h"
! 15: #include "globals.h"
! 16: #include "proto.h"
! 17: #include "option.h"
! 18: #include "ops.h" /* For op_inclusive */
! 19:
! 20: char *tgoto __PARMS((char *cm, int col, int line));
! 21:
! 22: static int canopt; /* TRUE when cursor goto can be optimized */
! 23: static int attributes = 0; /* current attributes for screen character*/
! 24: static int highlight_attr = 0; /* attributes when highlighting on */
! 25: #ifdef RIGHTLEFT
! 26: static int rightleft = 0; /* set to 1 for right to left in screen_fill */
! 27: #endif
! 28:
! 29: static int win_line __ARGS((WIN *, linenr_t, int, int));
! 30: static void comp_Botline_sub __ARGS((WIN *wp, linenr_t lnum, int done));
! 31: static void screen_char __ARGS((char_u *, int, int));
! 32: static void screenclear2 __ARGS((void));
! 33: static void lineclear __ARGS((char_u *p));
! 34: static int screen_ins_lines __ARGS((int, int, int, int));
! 35:
! 36: /*
! 37: * updateline() - like updateScreen() but only for cursor line
! 38: *
! 39: * Check if the size of the cursor line has changed. If it did change, lines
! 40: * below the cursor will move up or down and we need to call the routine
! 41: * updateScreen() to examine the entire screen.
! 42: */
! 43: void
! 44: updateline()
! 45: {
! 46: int row;
! 47: int n;
! 48:
! 49: if (!screen_valid(TRUE))
! 50: return;
! 51:
! 52: if (must_redraw) /* must redraw whole screen */
! 53: {
! 54: updateScreen(must_redraw);
! 55: return;
! 56: }
! 57:
! 58: if (RedrawingDisabled)
! 59: {
! 60: must_redraw = NOT_VALID; /* remember to update later */
! 61: return;
! 62: }
! 63:
! 64: cursor_off();
! 65:
! 66: (void)set_highlight('v');
! 67: row = win_line(curwin, curwin->w_cursor.lnum,
! 68: curwin->w_cline_row, curwin->w_height);
! 69:
! 70: if (row == curwin->w_height + 1) /* line too long for window */
! 71: {
! 72: /* window needs to be scrolled up to show the cursor line */
! 73: if (curwin->w_topline < curwin->w_cursor.lnum)
! 74: ++curwin->w_topline;
! 75: updateScreen(VALID_TO_CURSCHAR);
! 76: cursupdate();
! 77: }
! 78: else if (!dollar_vcol)
! 79: {
! 80: n = row - curwin->w_cline_row;
! 81: if (n != curwin->w_cline_height) /* line changed size */
! 82: {
! 83: if (n < curwin->w_cline_height) /* got smaller: delete lines */
! 84: win_del_lines(curwin, row,
! 85: curwin->w_cline_height - n, FALSE, TRUE);
! 86: else /* got bigger: insert lines */
! 87: win_ins_lines(curwin,
! 88: curwin->w_cline_row + curwin->w_cline_height,
! 89: n - curwin->w_cline_height, FALSE, TRUE);
! 90: updateScreen(VALID_TO_CURSCHAR);
! 91: }
! 92: else if (clear_cmdline || redraw_cmdline)
! 93: showmode(); /* clear cmdline, show mode and ruler */
! 94: }
! 95: }
! 96:
! 97: /*
! 98: * update all windows that are editing the current buffer
! 99: */
! 100: void
! 101: update_curbuf(type)
! 102: int type;
! 103: {
! 104: WIN *wp;
! 105:
! 106: for (wp = firstwin; wp; wp = wp->w_next)
! 107: if (wp->w_buffer == curbuf && wp->w_redr_type < type)
! 108: wp->w_redr_type = type;
! 109: updateScreen(type);
! 110: }
! 111:
! 112: /*
! 113: * updateScreen()
! 114: *
! 115: * Based on the current value of curwin->w_topline, transfer a screenfull
! 116: * of stuff from Filemem to NextScreen, and update curwin->w_botline.
! 117: */
! 118:
! 119: void
! 120: updateScreen(type)
! 121: int type;
! 122: {
! 123: WIN *wp;
! 124:
! 125: if (!screen_valid(TRUE))
! 126: return;
! 127:
! 128: dollar_vcol = 0;
! 129:
! 130: if (must_redraw)
! 131: {
! 132: if (type < must_redraw) /* use maximal type */
! 133: type = must_redraw;
! 134: must_redraw = 0;
! 135: }
! 136:
! 137: if (type == CURSUPD) /* update cursor and then redraw NOT_VALID */
! 138: {
! 139: curwin->w_lsize_valid = 0;
! 140: cursupdate(); /* will call updateScreen() */
! 141: return;
! 142: }
! 143: if (curwin->w_lsize_valid == 0 && type < NOT_VALID)
! 144: type = NOT_VALID;
! 145:
! 146: if (RedrawingDisabled)
! 147: {
! 148: must_redraw = type; /* remember type for next time */
! 149: curwin->w_redr_type = type;
! 150: curwin->w_lsize_valid = 0; /* don't use w_lsize[] now */
! 151: return;
! 152: }
! 153:
! 154: /*
! 155: * if the screen was scrolled up when displaying a message, scroll it down
! 156: */
! 157: if (msg_scrolled)
! 158: {
! 159: clear_cmdline = TRUE;
! 160: if (msg_scrolled > Rows - 5) /* clearing is faster */
! 161: type = CLEAR;
! 162: else if (type != CLEAR)
! 163: {
! 164: if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows) == FAIL)
! 165: type = CLEAR;
! 166: win_rest_invalid(firstwin); /* should do only first/last few */
! 167: }
! 168: msg_scrolled = 0;
! 169: need_wait_return = FALSE;
! 170: }
! 171:
! 172: /*
! 173: * reset cmdline_row now (may have been changed temporarily)
! 174: */
! 175: compute_cmdrow();
! 176:
! 177: if (type == CLEAR) /* first clear screen */
! 178: {
! 179: screenclear(); /* will reset clear_cmdline */
! 180: type = NOT_VALID;
! 181: }
! 182:
! 183: if (clear_cmdline) /* first clear cmdline */
! 184: {
! 185: if (emsg_on_display)
! 186: {
! 187: mch_delay(1000L, TRUE);
! 188: emsg_on_display = FALSE;
! 189: }
! 190: msg_row = cmdline_row;
! 191: msg_col = 0;
! 192: msg_clr_eos(); /* will reset clear_cmdline */
! 193: }
! 194:
! 195: /* return if there is nothing to do */
! 196: if (!((type == VALID && curwin->w_topline == curwin->w_lsize_lnum[0]) ||
! 197: (type == INVERTED &&
! 198: curwin->w_old_cursor_lnum == curwin->w_cursor.lnum &&
! 199: curwin->w_old_cursor_vcol == curwin->w_virtcol &&
! 200: curwin->w_old_curswant == curwin->w_curswant)))
! 201: {
! 202: /*
! 203: * go from top to bottom through the windows, redrawing the ones that
! 204: * need it
! 205: */
! 206: curwin->w_redr_type = type;
! 207: cursor_off();
! 208: for (wp = firstwin; wp; wp = wp->w_next)
! 209: {
! 210: if (wp->w_redr_type)
! 211: win_update(wp);
! 212: if (wp->w_redr_status)
! 213: win_redr_status(wp);
! 214: }
! 215: }
! 216: if (redraw_cmdline)
! 217: showmode();
! 218: }
! 219:
! 220: #ifdef USE_GUI
! 221: /*
! 222: * Update a single window, its status line and maybe the command line msg.
! 223: * Used for the GUI scrollbar.
! 224: */
! 225: void
! 226: updateWindow(wp)
! 227: WIN *wp;
! 228: {
! 229: win_update(wp);
! 230: if (wp->w_redr_status)
! 231: win_redr_status(wp);
! 232: if (redraw_cmdline)
! 233: showmode();
! 234: }
! 235: #endif
! 236:
! 237: /*
! 238: * update a single window
! 239: *
! 240: * This may cause the windows below it also to be redrawn
! 241: */
! 242: void
! 243: win_update(wp)
! 244: WIN *wp;
! 245: {
! 246: int type = wp->w_redr_type;
! 247: register int row;
! 248: register int endrow;
! 249: linenr_t lnum;
! 250: linenr_t lastline = 0; /* only valid if endrow != Rows -1 */
! 251: int done; /* if TRUE, we hit the end of the file */
! 252: int didline; /* if TRUE, we finished the last line */
! 253: int srow = 0; /* starting row of the current line */
! 254: int idx;
! 255: int i;
! 256: long j;
! 257:
! 258: if (type == NOT_VALID)
! 259: {
! 260: wp->w_redr_status = TRUE;
! 261: wp->w_lsize_valid = 0;
! 262: }
! 263:
! 264: idx = 0;
! 265: row = 0;
! 266: lnum = wp->w_topline;
! 267:
! 268: /* The number of rows shown is w_height. */
! 269: /* The default last row is the status/command line. */
! 270: endrow = wp->w_height;
! 271:
! 272: if (type == VALID || type == VALID_TO_CURSCHAR)
! 273: {
! 274: /*
! 275: * We handle two special cases:
! 276: * 1: we are off the top of the screen by a few lines: scroll down
! 277: * 2: wp->w_topline is below wp->w_lsize_lnum[0]: may scroll up
! 278: */
! 279: if (wp->w_topline < wp->w_lsize_lnum[0]) /* may scroll down */
! 280: {
! 281: j = wp->w_lsize_lnum[0] - wp->w_topline;
! 282: if (j < wp->w_height - 2) /* not too far off */
! 283: {
! 284: lastline = wp->w_lsize_lnum[0] - 1;
! 285: i = plines_m_win(wp, wp->w_topline, lastline);
! 286: if (i < wp->w_height - 2) /* less than a screen off */
! 287: {
! 288: /*
! 289: * Try to insert the correct number of lines.
! 290: * If not the last window, delete the lines at the bottom.
! 291: * win_ins_lines may fail.
! 292: */
! 293: if (win_ins_lines(wp, 0, i, FALSE, wp == firstwin) == OK &&
! 294: wp->w_lsize_valid)
! 295: {
! 296: endrow = i;
! 297:
! 298: if ((wp->w_lsize_valid += j) > wp->w_height)
! 299: wp->w_lsize_valid = wp->w_height;
! 300: for (idx = wp->w_lsize_valid; idx - j >= 0; idx--)
! 301: {
! 302: wp->w_lsize_lnum[idx] = wp->w_lsize_lnum[idx - j];
! 303: wp->w_lsize[idx] = wp->w_lsize[idx - j];
! 304: }
! 305: idx = 0;
! 306: }
! 307: }
! 308: else if (lastwin == firstwin)
! 309: screenclear(); /* far off: clearing the screen is faster */
! 310: }
! 311: else if (lastwin == firstwin)
! 312: screenclear(); /* far off: clearing the screen is faster */
! 313: }
! 314: else /* may scroll up */
! 315: {
! 316: j = -1;
! 317: /* try to find wp->w_topline in wp->w_lsize_lnum[] */
! 318: for (i = 0; i < wp->w_lsize_valid; i++)
! 319: {
! 320: if (wp->w_lsize_lnum[i] == wp->w_topline)
! 321: {
! 322: j = i;
! 323: break;
! 324: }
! 325: row += wp->w_lsize[i];
! 326: }
! 327: if (j == -1) /* wp->w_topline is not in wp->w_lsize_lnum */
! 328: {
! 329: row = 0;
! 330: if (lastwin == firstwin)
! 331: screenclear(); /* far off: clearing the screen is faster */
! 332: }
! 333: else
! 334: {
! 335: /*
! 336: * Try to delete the correct number of lines.
! 337: * wp->w_topline is at wp->w_lsize_lnum[i].
! 338: */
! 339: if ((row == 0 || win_del_lines(wp, 0, row,
! 340: FALSE, wp == firstwin) == OK) && wp->w_lsize_valid)
! 341: {
! 342: srow = row;
! 343: row = 0;
! 344: for (;;)
! 345: {
! 346: if (type == VALID_TO_CURSCHAR &&
! 347: lnum == wp->w_cursor.lnum)
! 348: break;
! 349: if (row + srow + (int)wp->w_lsize[j] >= wp->w_height)
! 350: break;
! 351: wp->w_lsize[idx] = wp->w_lsize[j];
! 352: wp->w_lsize_lnum[idx] = lnum++;
! 353:
! 354: row += wp->w_lsize[idx++];
! 355: if ((int)++j >= wp->w_lsize_valid)
! 356: break;
! 357: }
! 358: wp->w_lsize_valid = idx;
! 359: }
! 360: else
! 361: row = 0; /* update all lines */
! 362: }
! 363: }
! 364: if (endrow == wp->w_height && idx == 0) /* no scrolling */
! 365: wp->w_lsize_valid = 0;
! 366: }
! 367:
! 368: done = didline = FALSE;
! 369:
! 370: if (VIsual_active) /* check if we are updating the inverted part */
! 371: {
! 372: linenr_t from, to;
! 373:
! 374: /* find the line numbers that need to be updated */
! 375: if (curwin->w_cursor.lnum < wp->w_old_cursor_lnum)
! 376: {
! 377: from = curwin->w_cursor.lnum;
! 378: to = wp->w_old_cursor_lnum;
! 379: }
! 380: else
! 381: {
! 382: from = wp->w_old_cursor_lnum;
! 383: to = curwin->w_cursor.lnum;
! 384: }
! 385: /* if VIsual changed, update the maximal area */
! 386: if (VIsual.lnum != wp->w_old_visual_lnum)
! 387: {
! 388: if (wp->w_old_visual_lnum < from)
! 389: from = wp->w_old_visual_lnum;
! 390: if (wp->w_old_visual_lnum > to)
! 391: to = wp->w_old_visual_lnum;
! 392: if (VIsual.lnum < from)
! 393: from = VIsual.lnum;
! 394: if (VIsual.lnum > to)
! 395: to = VIsual.lnum;
! 396: }
! 397: /* if in block mode and changed column or wp->w_curswant: update all
! 398: * lines */
! 399: if (VIsual_mode == Ctrl('V') &&
! 400: (curwin->w_virtcol != wp->w_old_cursor_vcol ||
! 401: wp->w_curswant != wp->w_old_curswant))
! 402: {
! 403: if (from > VIsual.lnum)
! 404: from = VIsual.lnum;
! 405: if (to < VIsual.lnum)
! 406: to = VIsual.lnum;
! 407: }
! 408:
! 409: if (from < wp->w_topline)
! 410: from = wp->w_topline;
! 411: if (from >= wp->w_botline)
! 412: from = wp->w_botline - 1;
! 413: if (to >= wp->w_botline)
! 414: to = wp->w_botline - 1;
! 415:
! 416: /* find the minimal part to be updated */
! 417: if (type == INVERTED)
! 418: {
! 419: while (lnum < from) /* find start */
! 420: {
! 421: row += wp->w_lsize[idx++];
! 422: ++lnum;
! 423: }
! 424: srow = row;
! 425: for (j = idx; j < wp->w_lsize_valid; ++j) /* find end */
! 426: {
! 427: if (wp->w_lsize_lnum[j] == to + 1)
! 428: {
! 429: endrow = srow;
! 430: break;
! 431: }
! 432: srow += wp->w_lsize[j];
! 433: }
! 434: }
! 435:
! 436: /* if we update the lines between from and to set old_cursor */
! 437: if (type == INVERTED || (lnum <= from &&
! 438: (endrow == wp->w_height || lastline >= to)))
! 439: {
! 440: wp->w_old_cursor_lnum = curwin->w_cursor.lnum;
! 441: wp->w_old_cursor_vcol = curwin->w_virtcol;
! 442: wp->w_old_visual_lnum = VIsual.lnum;
! 443: wp->w_old_curswant = wp->w_curswant;
! 444: }
! 445: }
! 446: else
! 447: {
! 448: wp->w_old_cursor_lnum = 0;
! 449: wp->w_old_visual_lnum = 0;
! 450: }
! 451:
! 452: (void)set_highlight('v');
! 453:
! 454: /*
! 455: * Update the screen rows from "row" to "endrow".
! 456: * Start at line "lnum" which is at wp->w_lsize_lnum[idx].
! 457: */
! 458: for (;;)
! 459: {
! 460: if (lnum > wp->w_buffer->b_ml.ml_line_count)
! 461: {
! 462: done = TRUE; /* hit the end of the file */
! 463: break;
! 464: }
! 465: srow = row;
! 466: row = win_line(wp, lnum, srow, endrow);
! 467: if (row > endrow) /* past end of screen */
! 468: { /* we may need the size of that */
! 469: wp->w_lsize[idx] = plines_win(wp, lnum);
! 470: wp->w_lsize_lnum[idx++] = lnum; /* too long line later on */
! 471: break;
! 472: }
! 473:
! 474: wp->w_lsize[idx] = row - srow;
! 475: wp->w_lsize_lnum[idx++] = lnum;
! 476: if (++lnum > wp->w_buffer->b_ml.ml_line_count)
! 477: {
! 478: done = TRUE;
! 479: break;
! 480: }
! 481:
! 482: if (row == endrow)
! 483: {
! 484: didline = TRUE;
! 485: break;
! 486: }
! 487: }
! 488: if (idx > wp->w_lsize_valid)
! 489: wp->w_lsize_valid = idx;
! 490:
! 491: /* Do we have to do off the top of the screen processing ? */
! 492: if (endrow != wp->w_height)
! 493: {
! 494: row = 0;
! 495: for (idx = 0; idx < wp->w_lsize_valid && row < wp->w_height; idx++)
! 496: row += wp->w_lsize[idx];
! 497:
! 498: if (row < wp->w_height)
! 499: {
! 500: done = TRUE;
! 501: }
! 502: else if (row > wp->w_height) /* Need to blank out the last line */
! 503: {
! 504: lnum = wp->w_lsize_lnum[idx - 1];
! 505: srow = row - wp->w_lsize[idx - 1];
! 506: didline = FALSE;
! 507: }
! 508: else
! 509: {
! 510: lnum = wp->w_lsize_lnum[idx - 1] + 1;
! 511: didline = TRUE;
! 512: }
! 513: }
! 514:
! 515: wp->w_empty_rows = 0;
! 516: /*
! 517: * If we didn't hit the end of the file, and we didn't finish the last
! 518: * line we were working on, then the line didn't fit.
! 519: */
! 520: if (!done && !didline)
! 521: {
! 522: if (lnum == wp->w_topline)
! 523: {
! 524: /*
! 525: * Single line that does not fit!
! 526: * Fill last line with '@' characters.
! 527: */
! 528: screen_fill(wp->w_winpos + wp->w_height - 1,
! 529: wp->w_winpos + wp->w_height, 0, (int)Columns, '@', '@');
! 530: wp->w_botline = lnum + 1;
! 531: }
! 532: else
! 533: {
! 534: /*
! 535: * Clear the rest of the screen and mark the unused lines.
! 536: */
! 537: #ifdef RIGHTLEFT
! 538: if (wp->w_p_rl)
! 539: rightleft = 1;
! 540: #endif
! 541: screen_fill(wp->w_winpos + srow,
! 542: wp->w_winpos + wp->w_height, 0, (int)Columns, '@', ' ');
! 543: #ifdef RIGHTLEFT
! 544: rightleft = 0;
! 545: #endif
! 546: wp->w_botline = lnum;
! 547: wp->w_empty_rows = wp->w_height - srow;
! 548: }
! 549: }
! 550: else
! 551: {
! 552: /* make sure the rest of the screen is blank */
! 553: /* put '~'s on rows that aren't part of the file. */
! 554: #ifdef RIGHTLEFT
! 555: if (wp->w_p_rl)
! 556: rightleft = 1;
! 557: #endif
! 558: screen_fill(wp->w_winpos + row,
! 559: wp->w_winpos + wp->w_height, 0, (int)Columns, '~', ' ');
! 560: #ifdef RIGHTLEFT
! 561: rightleft = 0;
! 562: #endif
! 563: wp->w_empty_rows = wp->w_height - row;
! 564:
! 565: if (done) /* we hit the end of the file */
! 566: wp->w_botline = wp->w_buffer->b_ml.ml_line_count + 1;
! 567: else
! 568: wp->w_botline = lnum;
! 569: }
! 570:
! 571: wp->w_redr_type = 0;
! 572: }
! 573:
! 574: /*
! 575: * mark all status lines for redraw; used after first :cd
! 576: */
! 577: void
! 578: status_redraw_all()
! 579: {
! 580: WIN *wp;
! 581:
! 582: for (wp = firstwin; wp; wp = wp->w_next)
! 583: wp->w_redr_status = TRUE;
! 584: updateScreen(NOT_VALID);
! 585: }
! 586:
! 587: /*
! 588: * Redraw the status line of window wp.
! 589: *
! 590: * If inversion is possible we use it. Else '=' characters are used.
! 591: */
! 592: void
! 593: win_redr_status(wp)
! 594: WIN *wp;
! 595: {
! 596: int row;
! 597: char_u *p;
! 598: int len;
! 599: int fillchar;
! 600:
! 601: if (wp->w_status_height) /* if there is a status line */
! 602: {
! 603: if (set_highlight('s') == OK) /* can highlight */
! 604: {
! 605: fillchar = ' ';
! 606: start_highlight();
! 607: }
! 608: else /* can't highlight, use '=' */
! 609: fillchar = '=';
! 610:
! 611: p = wp->w_buffer->b_xfilename;
! 612: if (p == NULL)
! 613: STRCPY(NameBuff, "[No File]");
! 614: else
! 615: {
! 616: home_replace(wp->w_buffer, p, NameBuff, MAXPATHL);
! 617: trans_characters(NameBuff, MAXPATHL);
! 618: }
! 619: p = NameBuff;
! 620: len = STRLEN(p);
! 621:
! 622: if (wp->w_buffer->b_help || wp->w_buffer->b_changed ||
! 623: wp->w_buffer->b_p_ro)
! 624: *(p + len++) = ' ';
! 625: if (wp->w_buffer->b_help)
! 626: {
! 627: STRCPY(p + len, "[help]");
! 628: len += 6;
! 629: }
! 630: if (wp->w_buffer->b_changed)
! 631: {
! 632: STRCPY(p + len, "[+]");
! 633: len += 3;
! 634: }
! 635: if (wp->w_buffer->b_p_ro)
! 636: {
! 637: STRCPY(p + len, "[RO]");
! 638: len += 4;
! 639: }
! 640:
! 641: if (len > ru_col - 1)
! 642: {
! 643: p += len - (ru_col - 1);
! 644: *p = '<';
! 645: len = ru_col - 1;
! 646: }
! 647:
! 648: row = wp->w_winpos + wp->w_height;
! 649: screen_msg(p, row, 0);
! 650: screen_fill(row, row + 1, len, ru_col, fillchar, fillchar);
! 651:
! 652: stop_highlight();
! 653: win_redr_ruler(wp, TRUE);
! 654: }
! 655: else /* no status line, can only be last window */
! 656: redraw_cmdline = TRUE;
! 657: wp->w_redr_status = FALSE;
! 658: }
! 659:
! 660: /*
! 661: * display line "lnum" of window 'wp' on the screen
! 662: * Start at row "startrow", stop when "endrow" is reached.
! 663: * Return the number of last row the line occupies.
! 664: */
! 665:
! 666: static int
! 667: win_line(wp, lnum, startrow, endrow)
! 668: WIN *wp;
! 669: linenr_t lnum;
! 670: int startrow;
! 671: int endrow;
! 672: {
! 673: char_u *screenp;
! 674: int c;
! 675: int col; /* visual column on screen */
! 676: long vcol; /* visual column for tabs */
! 677: int row; /* row in the window, excl w_winpos */
! 678: int screen_row; /* row on the screen, incl w_winpos */
! 679: char_u *ptr;
! 680: char_u extra[16]; /* "%ld" must fit in here */
! 681: char_u *p_extra;
! 682: char_u *showbreak = NULL;
! 683: int n_extra;
! 684: int n_spaces = 0;
! 685:
! 686: int fromcol, tocol; /* start/end of inverting */
! 687: int noinvcur = FALSE; /* don't invert the cursor */
! 688: FPOS *top, *bot;
! 689:
! 690: if (startrow > endrow) /* past the end already! */
! 691: return startrow;
! 692:
! 693: row = startrow;
! 694: screen_row = row + wp->w_winpos;
! 695: col = 0;
! 696: vcol = 0;
! 697: fromcol = -10;
! 698: tocol = MAXCOL;
! 699: canopt = TRUE;
! 700:
! 701: /*
! 702: * handle visual active in this window
! 703: */
! 704: if (VIsual_active && wp->w_buffer == curwin->w_buffer)
! 705: {
! 706: /* Visual is after curwin->w_cursor */
! 707: if (ltoreq(curwin->w_cursor, VIsual))
! 708: {
! 709: top = &curwin->w_cursor;
! 710: bot = &VIsual;
! 711: }
! 712: else /* Visual is before curwin->w_cursor */
! 713: {
! 714: top = &VIsual;
! 715: bot = &curwin->w_cursor;
! 716: }
! 717: if (VIsual_mode == Ctrl('V')) /* block mode */
! 718: {
! 719: if (lnum >= top->lnum && lnum <= bot->lnum)
! 720: {
! 721: colnr_t from, to;
! 722:
! 723: getvcol(wp, top, (colnr_t *)&fromcol, NULL, (colnr_t *)&tocol);
! 724: getvcol(wp, bot, &from, NULL, &to);
! 725: if ((int)from < fromcol)
! 726: fromcol = from;
! 727: if ((int)to > tocol)
! 728: tocol = to;
! 729: ++tocol;
! 730:
! 731: if (wp->w_curswant == MAXCOL)
! 732: tocol = MAXCOL;
! 733: }
! 734: }
! 735: else /* non-block mode */
! 736: {
! 737: if (lnum > top->lnum && lnum <= bot->lnum)
! 738: fromcol = 0;
! 739: else if (lnum == top->lnum)
! 740: getvcol(wp, top, (colnr_t *)&fromcol, NULL, NULL);
! 741: if (lnum == bot->lnum)
! 742: {
! 743: getvcol(wp, bot, NULL, NULL, (colnr_t *)&tocol);
! 744: ++tocol;
! 745: }
! 746:
! 747: if (VIsual_mode == 'V') /* linewise */
! 748: {
! 749: if (fromcol > 0)
! 750: fromcol = 0;
! 751: tocol = MAXCOL;
! 752: }
! 753: }
! 754: /* if the cursor can't be switched off, don't invert the
! 755: * character where the cursor is */
! 756: #ifndef MSDOS
! 757: if (!highlight_match && *T_VI == NUL &&
! 758: lnum == curwin->w_cursor.lnum && wp == curwin)
! 759: noinvcur = TRUE;
! 760: #endif
! 761:
! 762: if (tocol <= (int)wp->w_leftcol) /* inverting is left of screen */
! 763: fromcol = 0;
! 764: /* start of invert is left of screen */
! 765: else if (fromcol >= 0 && fromcol < (int)wp->w_leftcol)
! 766: fromcol = wp->w_leftcol;
! 767:
! 768: /* if inverting in this line, can't optimize cursor positioning */
! 769: if (fromcol >= 0)
! 770: canopt = FALSE;
! 771: }
! 772: /*
! 773: * handle incremental search position highlighting
! 774: */
! 775: else if (highlight_match && wp == curwin && search_match_len)
! 776: {
! 777: if (lnum == curwin->w_cursor.lnum)
! 778: {
! 779: getvcol(curwin, &(curwin->w_cursor),
! 780: (colnr_t *)&fromcol, NULL, NULL);
! 781: curwin->w_cursor.col += search_match_len;
! 782: getvcol(curwin, &(curwin->w_cursor),
! 783: (colnr_t *)&tocol, NULL, NULL);
! 784: curwin->w_cursor.col -= search_match_len;
! 785: canopt = FALSE;
! 786: if (fromcol == tocol) /* do at least one character */
! 787: tocol = fromcol + 1; /* happens when past end of line */
! 788: }
! 789: }
! 790:
! 791: ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
! 792: if (!wp->w_p_wrap) /* advance to first character to be displayed */
! 793: {
! 794: while ((colnr_t)vcol < wp->w_leftcol && *ptr)
! 795: vcol += win_chartabsize(wp, *ptr++, (colnr_t)vcol);
! 796: if ((colnr_t)vcol > wp->w_leftcol)
! 797: {
! 798: n_spaces = vcol - wp->w_leftcol; /* begin with some spaces */
! 799: vcol = wp->w_leftcol;
! 800: }
! 801: }
! 802: screenp = LinePointers[screen_row];
! 803: #ifdef RIGHTLEFT
! 804: if (wp->w_p_rl)
! 805: {
! 806: col = Columns - 1; /* col follows screenp here */
! 807: screenp += Columns - 1;
! 808: }
! 809: #endif
! 810: if (wp->w_p_nu)
! 811: {
! 812: #ifdef RIGHTLEFT
! 813: if (wp->w_p_rl) /* reverse line numbers */
! 814: {
! 815: char_u *c1, *c2, t;
! 816:
! 817: sprintf((char *)extra, " %-7ld", (long)lnum);
! 818: for (c1 = extra, c2 = extra + STRLEN(extra) - 1; c1 < c2;
! 819: c1++, c2--)
! 820: {
! 821: t = *c1;
! 822: *c1 = *c2;
! 823: *c2 = t;
! 824: }
! 825: }
! 826: else
! 827: #endif
! 828: sprintf((char *)extra, "%7ld ", (long)lnum);
! 829: p_extra = extra;
! 830: n_extra = 8;
! 831: vcol -= 8; /* so vcol is 0 when line number has been printed */
! 832: }
! 833: else
! 834: {
! 835: p_extra = NULL;
! 836: n_extra = 0;
! 837: }
! 838: for (;;)
! 839: {
! 840: if (!canopt) /* Visual or match highlighting in this line */
! 841: {
! 842: if (((vcol == fromcol && !(noinvcur &&
! 843: (colnr_t)vcol == wp->w_virtcol)) ||
! 844: (noinvcur && (colnr_t)vcol == wp->w_virtcol + 1 &&
! 845: vcol >= fromcol)) && vcol < tocol)
! 846: start_highlight(); /* start highlighting */
! 847: else if (attributes && (vcol == tocol ||
! 848: (noinvcur && (colnr_t)vcol == wp->w_virtcol)))
! 849: stop_highlight(); /* stop highlighting */
! 850: }
! 851:
! 852: /* Get the next character to put on the screen. */
! 853:
! 854: /*
! 855: * if 'showbreak' is set it contains the characters to put at the
! 856: * start of each broken line
! 857: */
! 858: if (
! 859: #ifdef RIGHTLEFT
! 860: (wp->w_p_rl ? col == -1 : col == Columns)
! 861: #else
! 862: col == Columns
! 863: #endif
! 864: && (*ptr != NUL || (wp->w_p_list && n_extra == 0) ||
! 865: (n_extra && *p_extra) || n_spaces) &&
! 866: vcol != 0 && STRLEN(p_sbr) != 0)
! 867: showbreak = p_sbr;
! 868: if (showbreak != NULL)
! 869: {
! 870: c = *showbreak++;
! 871: if (*showbreak == NUL)
! 872: showbreak = NULL;
! 873: }
! 874: /*
! 875: * The 'extra' array contains the extra stuff that is inserted to
! 876: * represent special characters (non-printable stuff).
! 877: */
! 878: else if (n_extra)
! 879: {
! 880: c = *p_extra++;
! 881: n_extra--;
! 882: }
! 883: else if (n_spaces)
! 884: {
! 885: c = ' ';
! 886: n_spaces--;
! 887: }
! 888: else
! 889: {
! 890: c = *ptr++;
! 891: /*
! 892: * Found last space before word: check for line break
! 893: */
! 894: if (wp->w_p_lbr && isbreak(c) && !isbreak(*ptr) && !wp->w_p_list)
! 895: {
! 896: n_spaces = win_lbr_chartabsize(wp, ptr - 1,
! 897: (colnr_t)vcol, NULL) - 1;
! 898: if (vim_iswhite(c))
! 899: c = ' ';
! 900: }
! 901: else if (!isprintchar(c))
! 902: {
! 903: /*
! 904: * when getting a character from the file, we may have to turn
! 905: * it into something else on the way to putting it into
! 906: * 'NextScreen'.
! 907: */
! 908: if (c == TAB && !wp->w_p_list)
! 909: {
! 910: /* tab amount depends on current column */
! 911: n_spaces = (int)wp->w_buffer->b_p_ts -
! 912: vcol % (int)wp->w_buffer->b_p_ts - 1;
! 913: c = ' ';
! 914: }
! 915: else if (c == NUL && wp->w_p_list)
! 916: {
! 917: p_extra = (char_u *)"";
! 918: n_extra = 1;
! 919: c = '$';
! 920: --ptr; /* put it back at the NUL */
! 921: }
! 922: else if (c != NUL)
! 923: {
! 924: p_extra = transchar(c);
! 925: n_extra = charsize(c) - 1;
! 926: c = *p_extra++;
! 927: }
! 928: }
! 929: }
! 930:
! 931: if (c == NUL)
! 932: {
! 933: if (attributes)
! 934: {
! 935: /* invert at least one char, used for Visual and empty line or
! 936: * highlight match at end of line. If it's beyond the last
! 937: * char on the screen, just overwrite that one (tricky!) */
! 938: if (vcol == fromcol)
! 939: {
! 940: #ifdef RIGHTLEFT
! 941: if (wp->w_p_rl)
! 942: {
! 943: if (col < 0)
! 944: {
! 945: ++screenp;
! 946: ++col;
! 947: }
! 948: }
! 949: else
! 950: #endif
! 951: {
! 952: if (col >= Columns)
! 953: {
! 954: --screenp;
! 955: --col;
! 956: }
! 957: }
! 958: if (*screenp != ' ' || *(screenp + Columns) != attributes)
! 959: {
! 960: *screenp = ' ';
! 961: *(screenp + Columns) = attributes;
! 962: screen_char(screenp, screen_row, col);
! 963: }
! 964: #ifdef RIGHTLEFT
! 965: if (wp->w_p_rl)
! 966: {
! 967: --screenp;
! 968: --col;
! 969: }
! 970: else
! 971: #endif
! 972: {
! 973: ++screenp;
! 974: ++col;
! 975: }
! 976: }
! 977: stop_highlight();
! 978: }
! 979: /*
! 980: * blank out the rest of this row, if necessary
! 981: */
! 982: #ifdef RIGHTLEFT
! 983: if (wp->w_p_rl)
! 984: {
! 985: while (col >= 0 && *screenp == ' ' &&
! 986: *(screenp + Columns) == 0)
! 987: {
! 988: --screenp;
! 989: --col;
! 990: }
! 991: if (col >= 0)
! 992: screen_fill(screen_row, screen_row + 1,
! 993: 0, col + 1, ' ', ' ');
! 994: }
! 995: else
! 996: #endif
! 997: {
! 998: while (col < Columns && *screenp == ' ' &&
! 999: *(screenp + Columns) == 0)
! 1000: {
! 1001: ++screenp;
! 1002: ++col;
! 1003: }
! 1004: if (col < Columns)
! 1005: screen_fill(screen_row, screen_row + 1,
! 1006: col, (int)Columns, ' ', ' ');
! 1007: }
! 1008: row++;
! 1009: break;
! 1010: }
! 1011: if (
! 1012: #ifdef RIGHTLEFT
! 1013: wp->w_p_rl ? (col < 0) :
! 1014: #endif
! 1015: (col >= Columns)
! 1016: )
! 1017: {
! 1018: col = 0;
! 1019: ++row;
! 1020: ++screen_row;
! 1021: if (!wp->w_p_wrap)
! 1022: break;
! 1023: if (row == endrow) /* line got too long for screen */
! 1024: {
! 1025: ++row;
! 1026: break;
! 1027: }
! 1028: screenp = LinePointers[screen_row];
! 1029: #ifdef RIGHTLEFT
! 1030: if (wp->w_p_rl)
! 1031: {
! 1032: col = Columns - 1; /* col is not used if breaking! */
! 1033: screenp += Columns - 1;
! 1034: }
! 1035: #endif
! 1036: }
! 1037:
! 1038: /*
! 1039: * Store the character in NextScreen.
! 1040: */
! 1041: if (*screenp != c || *(screenp + Columns) != attributes)
! 1042: {
! 1043: /*
! 1044: * Special trick to make copy/paste of wrapped lines work with
! 1045: * xterm/screen:
! 1046: * If the first column is to be written, write the preceding
! 1047: * char twice. This will work with all terminal types
! 1048: * (regardless of the xn,am settings).
! 1049: * Only do this on a fast tty.
! 1050: */
! 1051: if (p_tf && row > startrow && col == 0 &&
! 1052: LinePointers[screen_row - 1][Columns - 1 + Columns] ==
! 1053: attributes)
! 1054: {
! 1055: if (screen_cur_row != screen_row - 1 ||
! 1056: screen_cur_col != Columns)
! 1057: screen_char(LinePointers[screen_row - 1] + Columns - 1,
! 1058: screen_row - 1, (int)(Columns - 1));
! 1059: screen_char(LinePointers[screen_row - 1] + Columns - 1,
! 1060: screen_row - 1, (int)Columns);
! 1061: screen_start();
! 1062: }
! 1063:
! 1064: *screenp = c;
! 1065: *(screenp + Columns) = attributes;
! 1066: screen_char(screenp, screen_row, col);
! 1067: }
! 1068: #ifdef RIGHTLEFT
! 1069: if (wp->w_p_rl)
! 1070: {
! 1071: --screenp;
! 1072: --col;
! 1073: }
! 1074: else
! 1075: #endif
! 1076: {
! 1077: ++screenp;
! 1078: ++col;
! 1079: }
! 1080: ++vcol;
! 1081: /* stop before '$' of change command */
! 1082: if (wp == curwin && dollar_vcol && vcol >= (long)wp->w_virtcol)
! 1083: break;
! 1084: }
! 1085:
! 1086: stop_highlight();
! 1087: return (row);
! 1088: }
! 1089:
! 1090: /*
! 1091: * Called when p_dollar is set: display a '$' at the end of the changed text
! 1092: * Only works when cursor is in the line that changes.
! 1093: */
! 1094: void
! 1095: display_dollar(col)
! 1096: colnr_t col;
! 1097: {
! 1098: colnr_t save_col;
! 1099:
! 1100: if (RedrawingDisabled)
! 1101: return;
! 1102:
! 1103: cursor_off();
! 1104: save_col = curwin->w_cursor.col;
! 1105: curwin->w_cursor.col = col;
! 1106: curs_columns(FALSE);
! 1107: if (!curwin->w_p_wrap)
! 1108: curwin->w_col -= curwin->w_leftcol;
! 1109: if (curwin->w_col < Columns)
! 1110: {
! 1111: screen_msg((char_u *)"$", curwin->w_winpos + curwin->w_row,
! 1112: #ifdef RIGHTLEFT
! 1113: curwin->w_p_rl ? (int)Columns - 1 - curwin->w_col :
! 1114: #endif
! 1115: curwin->w_col);
! 1116: dollar_vcol = curwin->w_virtcol;
! 1117: }
! 1118: curwin->w_cursor.col = save_col;
! 1119: }
! 1120:
! 1121: /*
! 1122: * Call this function before moving the cursor from the normal insert position
! 1123: * in insert mode.
! 1124: */
! 1125: void
! 1126: undisplay_dollar()
! 1127: {
! 1128: if (dollar_vcol)
! 1129: {
! 1130: dollar_vcol = 0;
! 1131: updateline();
! 1132: }
! 1133: }
! 1134:
! 1135: /*
! 1136: * output a single character directly to the screen
! 1137: * update NextScreen
! 1138: */
! 1139: void
! 1140: screen_outchar(c, row, col)
! 1141: int c;
! 1142: int row, col;
! 1143: {
! 1144: char_u buf[2];
! 1145:
! 1146: buf[0] = c;
! 1147: buf[1] = NUL;
! 1148: screen_msg(buf, row, col);
! 1149: }
! 1150:
! 1151: /*
! 1152: * put string '*text' on the screen at position 'row' and 'col'
! 1153: * update NextScreen
! 1154: * Note: only outputs within one row, message is truncated at screen boundary!
! 1155: * Note: if NextScreen, row and/or col is invalid, nothing is done.
! 1156: */
! 1157: void
! 1158: screen_msg(text, row, col)
! 1159: char_u *text;
! 1160: int row;
! 1161: int col;
! 1162: {
! 1163: char_u *screenp;
! 1164:
! 1165: if (NextScreen != NULL && row < Rows) /* safety check */
! 1166: {
! 1167: screenp = LinePointers[row] + col;
! 1168: while (*text && col < Columns)
! 1169: {
! 1170: if (*screenp != *text || *(screenp + Columns) != attributes)
! 1171: {
! 1172: *screenp = *text;
! 1173: *(screenp + Columns) = attributes;
! 1174: screen_char(screenp, row, col);
! 1175: }
! 1176: ++screenp;
! 1177: ++col;
! 1178: ++text;
! 1179: }
! 1180: }
! 1181: }
! 1182:
! 1183: /*
! 1184: * Reset cursor position. Use whenever cursor was moved because of outputting
! 1185: * something directly to the screen (shell commands) or a terminal control
! 1186: * code.
! 1187: */
! 1188: void
! 1189: screen_start()
! 1190: {
! 1191: screen_cur_row = screen_cur_col = 9999;
! 1192: }
! 1193:
! 1194: /*
! 1195: * set_highlight - set highlight depending on 'highlight' option and context.
! 1196: *
! 1197: * return FAIL if highlighting is not possible, OK otherwise
! 1198: */
! 1199: int
! 1200: set_highlight(context)
! 1201: int context;
! 1202: {
! 1203: int i;
! 1204: int mode;
! 1205: char_u *p;
! 1206:
! 1207: /*
! 1208: * Try to find the mode in the 'highlight' option.
! 1209: * If not found, try the default for the 'highlight' option.
! 1210: * If still not found, use 'r' (should not happen).
! 1211: */
! 1212: mode = 'r';
! 1213: for (i = 0; i < 2; ++i)
! 1214: {
! 1215: if (i)
! 1216: p = get_highlight_default();
! 1217: else
! 1218: p = p_hl;
! 1219: if (p == NULL)
! 1220: continue;
! 1221:
! 1222: while (*p)
! 1223: {
! 1224: if (*p == context) /* found what we are looking for */
! 1225: break;
! 1226: while (*p && *p != ',') /* skip to comma */
! 1227: ++p;
! 1228: p = skip_to_option_part(p); /* skip comma and spaces */
! 1229: }
! 1230: if (p[0] && p[1])
! 1231: {
! 1232: mode = p[1];
! 1233: break;
! 1234: }
! 1235: }
! 1236:
! 1237: switch (mode)
! 1238: {
! 1239: case 'b': highlight = T_MD; /* bold */
! 1240: unhighlight = T_ME;
! 1241: highlight_attr = CHAR_BOLD;
! 1242: break;
! 1243: case 's': highlight = T_SO; /* standout */
! 1244: unhighlight = T_SE;
! 1245: highlight_attr = CHAR_STDOUT;
! 1246: break;
! 1247: case 'n': highlight = NULL; /* no highlighting */
! 1248: unhighlight = NULL;
! 1249: highlight_attr = 0;
! 1250: break;
! 1251: case 'u': highlight = T_US; /* underline */
! 1252: unhighlight = T_UE;
! 1253: highlight_attr = CHAR_UNDERL;
! 1254: break;
! 1255: case 'i': highlight = T_CZH; /* italic */
! 1256: unhighlight = T_CZR;
! 1257: highlight_attr = CHAR_ITALIC;
! 1258: break;
! 1259: default: highlight = T_MR; /* reverse (invert) */
! 1260: unhighlight = T_ME;
! 1261: highlight_attr = CHAR_INVERT;
! 1262: break;
! 1263: }
! 1264: if (highlight == NULL || *highlight == NUL ||
! 1265: unhighlight == NULL || *unhighlight == NUL)
! 1266: {
! 1267: highlight = NULL;
! 1268: return FAIL;
! 1269: }
! 1270: return OK;
! 1271: }
! 1272:
! 1273: void
! 1274: start_highlight()
! 1275: {
! 1276: if (full_screen &&
! 1277: #ifdef WIN32
! 1278: termcap_active &&
! 1279: #endif
! 1280: highlight != NULL)
! 1281: {
! 1282: outstr(highlight);
! 1283: attributes = highlight_attr;
! 1284: }
! 1285: }
! 1286:
! 1287: void
! 1288: stop_highlight()
! 1289: {
! 1290: if (attributes)
! 1291: {
! 1292: outstr(unhighlight);
! 1293: attributes = 0;
! 1294: }
! 1295: }
! 1296:
! 1297: /*
! 1298: * variables used for one level depth of highlighting
! 1299: * Used for "-- More --" message.
! 1300: */
! 1301:
! 1302: static char_u *old_highlight = NULL;
! 1303: static char_u *old_unhighlight = NULL;
! 1304: static int old_highlight_attr = 0;
! 1305:
! 1306: void
! 1307: remember_highlight()
! 1308: {
! 1309: old_highlight = highlight;
! 1310: old_unhighlight = unhighlight;
! 1311: old_highlight_attr = highlight_attr;
! 1312: }
! 1313:
! 1314: void
! 1315: recover_old_highlight()
! 1316: {
! 1317: highlight = old_highlight;
! 1318: unhighlight = old_unhighlight;
! 1319: highlight_attr = old_highlight_attr;
! 1320: }
! 1321:
! 1322: /*
! 1323: * put character '*p' on the screen at position 'row' and 'col'
! 1324: */
! 1325: static void
! 1326: screen_char(p, row, col)
! 1327: char_u *p;
! 1328: int row;
! 1329: int col;
! 1330: {
! 1331: int c;
! 1332: int noinvcurs;
! 1333:
! 1334: /*
! 1335: * Outputting the last character on the screen may scrollup the screen.
! 1336: * Don't to it!
! 1337: */
! 1338: if (col == Columns - 1 && row == Rows - 1)
! 1339: return;
! 1340: if (screen_cur_col != col || screen_cur_row != row)
! 1341: {
! 1342: /* check if no cursor movement is allowed in standout mode */
! 1343: if (attributes && !p_wiv && *T_MS == NUL)
! 1344: noinvcurs = 7;
! 1345: else
! 1346: noinvcurs = 0;
! 1347:
! 1348: /*
! 1349: * If we're on the same row (which happens a lot!), try to
! 1350: * avoid a windgoto().
! 1351: * If we are only a few characters off, output the
! 1352: * characters. That is faster than cursor positioning.
! 1353: * This can't be used when switching between inverting and not
! 1354: * inverting.
! 1355: */
! 1356: if (screen_cur_row == row && screen_cur_col < col)
! 1357: {
! 1358: register int i;
! 1359:
! 1360: i = col - screen_cur_col;
! 1361: if (i <= 4 + noinvcurs)
! 1362: {
! 1363: /* stop at the first character that has different attributes
! 1364: * from the ones that are active */
! 1365: while (i && *(p - i + Columns) == attributes)
! 1366: {
! 1367: c = *(p - i--);
! 1368: outchar(c);
! 1369: }
! 1370: }
! 1371: if (i)
! 1372: {
! 1373: if (noinvcurs)
! 1374: stop_highlight();
! 1375:
! 1376: if (*T_CRI != NUL) /* use tgoto interface! jw */
! 1377: OUTSTR(tgoto((char *)T_CRI, 0, i));
! 1378: else
! 1379: windgoto(row, col);
! 1380:
! 1381: if (noinvcurs)
! 1382: start_highlight();
! 1383: }
! 1384: }
! 1385: /*
! 1386: * If the cursor is at the line above where we want to be, use CR LF,
! 1387: * this is quicker than windgoto().
! 1388: * Don't do this if the cursor went beyond the last column, the cursor
! 1389: * position is unknown then (some terminals wrap, some don't )
! 1390: */
! 1391: else if (screen_cur_row + 1 == row && col == 0 &&
! 1392: screen_cur_col < Columns)
! 1393: {
! 1394: if (noinvcurs)
! 1395: stop_highlight();
! 1396: outchar('\n');
! 1397: if (noinvcurs)
! 1398: start_highlight();
! 1399: }
! 1400: else
! 1401: {
! 1402: if (noinvcurs)
! 1403: stop_highlight();
! 1404: windgoto(row, col);
! 1405: if (noinvcurs)
! 1406: start_highlight();
! 1407: }
! 1408: screen_cur_row = row;
! 1409: screen_cur_col = col;
! 1410: }
! 1411:
! 1412: /*
! 1413: * For weird invert mechanism: output (un)highlight before every char
! 1414: * Lots of extra output, but works.
! 1415: */
! 1416: if (p_wiv)
! 1417: {
! 1418: if (attributes)
! 1419: outstr(highlight);
! 1420: else if (full_screen)
! 1421: outstr(unhighlight);
! 1422: }
! 1423: outchar(*p);
! 1424: screen_cur_col++;
! 1425: }
! 1426:
! 1427: /*
! 1428: * Fill the screen from 'start_row' to 'end_row', from 'start_col' to 'end_col'
! 1429: * with character 'c1' in first column followed by 'c2' in the other columns.
! 1430: */
! 1431: void
! 1432: screen_fill(start_row, end_row, start_col, end_col, c1, c2)
! 1433: int start_row, end_row;
! 1434: int start_col, end_col;
! 1435: int c1, c2;
! 1436: {
! 1437: int row;
! 1438: int col;
! 1439: char_u *screenp;
! 1440: char_u *attrp;
! 1441: int did_delete;
! 1442: int c;
! 1443:
! 1444: if (end_row > Rows) /* safety check */
! 1445: end_row = Rows;
! 1446: if (end_col > Columns) /* safety check */
! 1447: end_col = Columns;
! 1448: if (NextScreen == NULL ||
! 1449: start_row >= end_row || start_col >= end_col) /* nothing to do */
! 1450: return;
! 1451:
! 1452: for (row = start_row; row < end_row; ++row)
! 1453: {
! 1454: /* try to use delete-line termcap code */
! 1455: did_delete = FALSE;
! 1456: if (attributes == 0 && c2 == ' ' && end_col == Columns && *T_CE != NUL
! 1457: #ifdef RIGHTLEFT
! 1458: && !rightleft
! 1459: #endif
! 1460: )
! 1461: {
! 1462: /*
! 1463: * check if we really need to clear something
! 1464: */
! 1465: col = start_col;
! 1466: screenp = LinePointers[row] + start_col;
! 1467: if (c1 != ' ') /* don't clear first char */
! 1468: {
! 1469: ++col;
! 1470: ++screenp;
! 1471: }
! 1472:
! 1473: /* skip blanks (used often, keep it fast!) */
! 1474: attrp = screenp + Columns;
! 1475: while (col < end_col && *screenp == ' ' && *attrp == 0)
! 1476: {
! 1477: ++col;
! 1478: ++screenp;
! 1479: ++attrp;
! 1480: }
! 1481: if (col < end_col) /* something to be cleared */
! 1482: {
! 1483: windgoto(row, col); /* clear rest of this screen line */
! 1484: outstr(T_CE);
! 1485: screen_start(); /* don't know where cursor is now */
! 1486: col = end_col - col;
! 1487: while (col--) /* clear chars in NextScreen */
! 1488: {
! 1489: *attrp++ = 0;
! 1490: *screenp++ = ' ';
! 1491: }
! 1492: }
! 1493: did_delete = TRUE; /* the chars are cleared now */
! 1494: }
! 1495:
! 1496: screenp = LinePointers[row] +
! 1497: #ifdef RIGHTLEFT
! 1498: (rightleft ? (int)Columns - 1 - start_col : start_col);
! 1499: #else
! 1500: start_col;
! 1501: #endif
! 1502: c = c1;
! 1503: for (col = start_col; col < end_col; ++col)
! 1504: {
! 1505: if (*screenp != c || *(screenp + Columns) != attributes)
! 1506: {
! 1507: *screenp = c;
! 1508: *(screenp + Columns) = attributes;
! 1509: if (!did_delete || c != ' ')
! 1510: screen_char(screenp, row,
! 1511: #ifdef RIGHTLEFT
! 1512: rightleft ? Columns - 1 - col :
! 1513: #endif
! 1514: col);
! 1515: }
! 1516: #ifdef RIGHTLEFT
! 1517: if (rightleft)
! 1518: --screenp;
! 1519: else
! 1520: #endif
! 1521: ++screenp;
! 1522: if (col == start_col)
! 1523: {
! 1524: if (did_delete)
! 1525: break;
! 1526: c = c2;
! 1527: }
! 1528: }
! 1529: if (row == Rows - 1) /* overwritten the command line */
! 1530: {
! 1531: redraw_cmdline = TRUE;
! 1532: if (c1 == ' ' && c2 == ' ')
! 1533: clear_cmdline = FALSE; /* command line has been cleared */
! 1534: }
! 1535: }
! 1536: }
! 1537:
! 1538: /*
! 1539: * recompute all w_botline's. Called after Rows changed.
! 1540: */
! 1541: void
! 1542: comp_Botline_all()
! 1543: {
! 1544: WIN *wp;
! 1545:
! 1546: for (wp = firstwin; wp; wp = wp->w_next)
! 1547: comp_Botline(wp);
! 1548: }
! 1549:
! 1550: /*
! 1551: * compute wp->w_botline. Can be called after wp->w_topline changed.
! 1552: */
! 1553: void
! 1554: comp_Botline(wp)
! 1555: WIN *wp;
! 1556: {
! 1557: comp_Botline_sub(wp, wp->w_topline, 0);
! 1558: }
! 1559:
! 1560: /*
! 1561: * Compute wp->w_botline, may have a start at the cursor position.
! 1562: * Code shared between comp_Botline() and cursupdate().
! 1563: */
! 1564: static void
! 1565: comp_Botline_sub(wp, lnum, done)
! 1566: WIN *wp;
! 1567: linenr_t lnum;
! 1568: int done;
! 1569: {
! 1570: int n;
! 1571:
! 1572: for ( ; lnum <= wp->w_buffer->b_ml.ml_line_count; ++lnum)
! 1573: {
! 1574: n = plines_win(wp, lnum);
! 1575: if (done + n > wp->w_height)
! 1576: break;
! 1577: done += n;
! 1578: }
! 1579:
! 1580: /* wp->w_botline is the line that is just below the window */
! 1581: wp->w_botline = lnum;
! 1582:
! 1583: /* Also set wp->w_empty_rows, otherwise scroll_cursor_bot() won't work */
! 1584: if (done == 0)
! 1585: wp->w_empty_rows = 0; /* single line that doesn't fit */
! 1586: else
! 1587: wp->w_empty_rows = wp->w_height - done;
! 1588: }
! 1589:
! 1590: void
! 1591: screenalloc(clear)
! 1592: int clear;
! 1593: {
! 1594: register int new_row, old_row;
! 1595: WIN *wp;
! 1596: int outofmem = FALSE;
! 1597: int len;
! 1598: char_u *new_NextScreen;
! 1599: char_u **new_LinePointers;
! 1600:
! 1601: /*
! 1602: * Allocation of the screen buffers is done only when the size changes
! 1603: * and when Rows and Columns have been set and we are doing full screen
! 1604: * stuff.
! 1605: */
! 1606: if ((NextScreen != NULL && Rows == screen_Rows && Columns == screen_Columns)
! 1607: || Rows == 0 || Columns == 0 || !full_screen)
! 1608: return;
! 1609:
! 1610: comp_col(); /* recompute columns for shown command and ruler */
! 1611:
! 1612: /*
! 1613: * We're changing the size of the screen.
! 1614: * - Allocate new arrays for NextScreen.
! 1615: * - Move lines from the old arrays into the new arrays, clear extra
! 1616: * lines (unless the screen is going to be cleared).
! 1617: * - Free the old arrays.
! 1618: */
! 1619: for (wp = firstwin; wp; wp = wp->w_next)
! 1620: win_free_lsize(wp);
! 1621:
! 1622: new_NextScreen = (char_u *)malloc((size_t) (Rows * Columns * 2));
! 1623: new_LinePointers = (char_u **)malloc(sizeof(char_u *) * Rows);
! 1624:
! 1625: for (wp = firstwin; wp; wp = wp->w_next)
! 1626: {
! 1627: if (win_alloc_lsize(wp) == FAIL)
! 1628: {
! 1629: outofmem = TRUE;
! 1630: break;
! 1631: }
! 1632: }
! 1633:
! 1634: if (new_NextScreen == NULL || new_LinePointers == NULL || outofmem)
! 1635: {
! 1636: do_outofmem_msg();
! 1637: vim_free(new_NextScreen);
! 1638: new_NextScreen = NULL;
! 1639: }
! 1640: else
! 1641: {
! 1642: for (new_row = 0; new_row < Rows; ++new_row)
! 1643: {
! 1644: new_LinePointers[new_row] = new_NextScreen + new_row * Columns * 2;
! 1645:
! 1646: /*
! 1647: * If the screen is not going to be cleared, copy as much as
! 1648: * possible from the old screen to the new one and clear the rest
! 1649: * (used when resizing the window at the "--more--" prompt or when
! 1650: * executing an external command, for the GUI).
! 1651: */
! 1652: if (!clear)
! 1653: {
! 1654: lineclear(new_LinePointers[new_row]);
! 1655: old_row = new_row + (screen_Rows - Rows);
! 1656: if (old_row >= 0)
! 1657: {
! 1658: if (screen_Columns < Columns)
! 1659: len = screen_Columns;
! 1660: else
! 1661: len = Columns;
! 1662: vim_memmove(new_LinePointers[new_row],
! 1663: LinePointers[old_row], (size_t)len);
! 1664: vim_memmove(new_LinePointers[new_row] + Columns,
! 1665: LinePointers[old_row] + screen_Columns, (size_t)len);
! 1666: }
! 1667: }
! 1668: }
! 1669: }
! 1670:
! 1671: vim_free(NextScreen);
! 1672: vim_free(LinePointers);
! 1673: NextScreen = new_NextScreen;
! 1674: LinePointers = new_LinePointers;
! 1675:
! 1676: must_redraw = CLEAR; /* need to clear the screen later */
! 1677: if (clear)
! 1678: screenclear2();
! 1679:
! 1680: #ifdef USE_GUI
! 1681: else if (gui.in_use && NextScreen != NULL && Rows != screen_Rows)
! 1682: {
! 1683: gui_redraw_block(0, 0, Rows - 1, Columns - 1);
! 1684: /*
! 1685: * Adjust the position of the cursor, for when executing an external
! 1686: * command.
! 1687: */
! 1688: if (msg_row >= Rows) /* Rows got smaller */
! 1689: msg_row = Rows - 1; /* put cursor at last row */
! 1690: else if (Rows > screen_Rows) /* Rows got bigger */
! 1691: msg_row += Rows - screen_Rows; /* put cursor in same place */
! 1692: if (msg_col >= Columns) /* Columns got smaller */
! 1693: msg_col = Columns - 1; /* put cursor at last column */
! 1694: }
! 1695: #endif
! 1696:
! 1697: screen_Rows = Rows;
! 1698: screen_Columns = Columns;
! 1699: }
! 1700:
! 1701: void
! 1702: screenclear()
! 1703: {
! 1704: if (emsg_on_display)
! 1705: {
! 1706: mch_delay(1000L, TRUE);
! 1707: emsg_on_display = FALSE;
! 1708: }
! 1709: screenalloc(FALSE); /* allocate screen buffers if size changed */
! 1710: screenclear2(); /* clear the screen */
! 1711: }
! 1712:
! 1713: static void
! 1714: screenclear2()
! 1715: {
! 1716: int i;
! 1717:
! 1718: if (starting || NextScreen == NULL)
! 1719: return;
! 1720:
! 1721: outstr(T_CL); /* clear the display */
! 1722:
! 1723: /* blank out NextScreen */
! 1724: for (i = 0; i < Rows; ++i)
! 1725: lineclear(LinePointers[i]);
! 1726:
! 1727: screen_cleared = TRUE; /* can use contents of NextScreen now */
! 1728:
! 1729: win_rest_invalid(firstwin);
! 1730: clear_cmdline = FALSE;
! 1731: redraw_cmdline = TRUE;
! 1732: if (must_redraw == CLEAR) /* no need to clear again */
! 1733: must_redraw = NOT_VALID;
! 1734: compute_cmdrow();
! 1735: msg_pos((int)Rows - 1, 0); /* put cursor on last line for messages */
! 1736: screen_start(); /* don't know where cursor is now */
! 1737: msg_scrolled = 0; /* can't scroll back */
! 1738: msg_didany = FALSE;
! 1739: msg_didout = FALSE;
! 1740: }
! 1741:
! 1742: /*
! 1743: * Clear one line in NextScreen.
! 1744: */
! 1745: static void
! 1746: lineclear(p)
! 1747: char_u *p;
! 1748: {
! 1749: (void)vim_memset(p, ' ', (size_t)Columns);
! 1750: (void)vim_memset(p + Columns, 0, (size_t)Columns);
! 1751: }
! 1752:
! 1753: /*
! 1754: * check cursor for a valid lnum
! 1755: */
! 1756: void
! 1757: check_cursor()
! 1758: {
! 1759: if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
! 1760: curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
! 1761: if (curwin->w_cursor.lnum <= 0)
! 1762: curwin->w_cursor.lnum = 1;
! 1763: }
! 1764:
! 1765: void
! 1766: cursupdate()
! 1767: {
! 1768: linenr_t lnum;
! 1769: long line_count;
! 1770: int sline;
! 1771: int done;
! 1772: int temp;
! 1773:
! 1774: if (!screen_valid(TRUE))
! 1775: return;
! 1776:
! 1777: /*
! 1778: * Make sure the cursor is on a valid line number
! 1779: */
! 1780: check_cursor();
! 1781:
! 1782: /*
! 1783: * If the buffer is empty, always set topline to 1.
! 1784: */
! 1785: if (bufempty()) /* special case - file is empty */
! 1786: {
! 1787: curwin->w_topline = 1;
! 1788: curwin->w_cursor.lnum = 1;
! 1789: curwin->w_cursor.col = 0;
! 1790: curwin->w_lsize[0] = 0;
! 1791: if (curwin->w_lsize_valid == 0) /* don't know about screen contents */
! 1792: updateScreen(NOT_VALID);
! 1793: curwin->w_lsize_valid = 1;
! 1794: }
! 1795:
! 1796: /*
! 1797: * If the cursor is above the top of the window, scroll the window to put
! 1798: * it at the top of the window.
! 1799: * If we weren't very close to begin with, we scroll to put the cursor in
! 1800: * the middle of the window.
! 1801: */
! 1802: else if (curwin->w_cursor.lnum < curwin->w_topline + p_so &&
! 1803: curwin->w_topline > 1)
! 1804: {
! 1805: temp = curwin->w_height / 2 - 1;
! 1806: if (temp < 2)
! 1807: temp = 2;
! 1808: /* not very close, put cursor halfway screen */
! 1809: if (curwin->w_topline + p_so - curwin->w_cursor.lnum >= temp)
! 1810: scroll_cursor_halfway(FALSE);
! 1811: else
! 1812: scroll_cursor_top((int)p_sj, FALSE);
! 1813: updateScreen(VALID);
! 1814: }
! 1815:
! 1816: /*
! 1817: * If the cursor is below the bottom of the window, scroll the window
! 1818: * to put the cursor on the window. If the cursor is less than a
! 1819: * windowheight down compute the number of lines at the top which have
! 1820: * the same or more rows than the rows of the lines below the bottom.
! 1821: * Note: After curwin->w_botline was computed lines may have been
! 1822: * added or deleted, it may be greater than ml_line_count.
! 1823: */
! 1824: else if ((long)curwin->w_cursor.lnum >= (long)curwin->w_botline - p_so &&
! 1825: curwin->w_botline <= curbuf->b_ml.ml_line_count)
! 1826: {
! 1827: line_count = curwin->w_cursor.lnum - curwin->w_botline + 1 + p_so;
! 1828: if (line_count <= curwin->w_height + 1)
! 1829: scroll_cursor_bot((int)p_sj, FALSE);
! 1830: else
! 1831: scroll_cursor_halfway(FALSE);
! 1832: updateScreen(VALID);
! 1833: }
! 1834:
! 1835: /*
! 1836: * If the window contents is unknown, need to update the screen.
! 1837: */
! 1838: else if (curwin->w_lsize_valid == 0)
! 1839: updateScreen(NOT_VALID);
! 1840:
! 1841: /*
! 1842: * Figure out the row number of the cursor line.
! 1843: * This is used often, keep it fast!
! 1844: */
! 1845: curwin->w_row = sline = 0;
! 1846: /* curwin->w_lsize[] invalid */
! 1847: if (RedrawingDisabled || curwin->w_lsize_valid == 0)
! 1848: {
! 1849: done = 0;
! 1850: for (lnum = curwin->w_topline; lnum != curwin->w_cursor.lnum; ++lnum)
! 1851: done += plines(lnum);
! 1852: curwin->w_row = done;
! 1853:
! 1854: /*
! 1855: * Also need to compute w_botline and w_empty_rows, because
! 1856: * updateScreen() will not have done that.
! 1857: */
! 1858: comp_Botline_sub(curwin, lnum, done);
! 1859: }
! 1860: else
! 1861: {
! 1862: for (done = curwin->w_cursor.lnum - curwin->w_topline; done > 0; --done)
! 1863: curwin->w_row += curwin->w_lsize[sline++];
! 1864: }
! 1865:
! 1866: curwin->w_cline_row = curwin->w_row;
! 1867: curwin->w_col = curwin->w_virtcol = 0;
! 1868: if (!RedrawingDisabled && sline > curwin->w_lsize_valid)
! 1869: /* Should only happen with a line that is too */
! 1870: /* long to fit on the last screen line. */
! 1871: curwin->w_cline_height = 0;
! 1872: else
! 1873: {
! 1874: /* curwin->w_lsize[] invalid */
! 1875: if (RedrawingDisabled || curwin->w_lsize_valid == 0)
! 1876: curwin->w_cline_height = plines(curwin->w_cursor.lnum);
! 1877: else
! 1878: curwin->w_cline_height = curwin->w_lsize[sline];
! 1879: /* compute curwin->w_virtcol and curwin->w_col */
! 1880: curs_columns(!RedrawingDisabled);
! 1881: if (must_redraw)
! 1882: updateScreen(must_redraw);
! 1883: }
! 1884:
! 1885: if (curwin->w_set_curswant)
! 1886: {
! 1887: curwin->w_curswant = curwin->w_virtcol;
! 1888: curwin->w_set_curswant = FALSE;
! 1889: }
! 1890: }
! 1891:
! 1892: /*
! 1893: * Recompute topline to put the cursor at the top of the window.
! 1894: * Scroll at least "min_scroll" lines.
! 1895: * If "always" is TRUE, always set topline (for "zt").
! 1896: */
! 1897: void
! 1898: scroll_cursor_top(min_scroll, always)
! 1899: int min_scroll;
! 1900: int always;
! 1901: {
! 1902: int scrolled = 0;
! 1903: int extra = 0;
! 1904: int used;
! 1905: int i;
! 1906: int sline; /* screen line for cursor */
! 1907:
! 1908: /*
! 1909: * Decrease topline until:
! 1910: * - it has become 1
! 1911: * - (part of) the cursor line is moved off the screen or
! 1912: * - moved at least 'scrolljump' lines and
! 1913: * - at least 'scrolloff' lines above and below the cursor
! 1914: */
! 1915: used = plines(curwin->w_cursor.lnum);
! 1916: for (sline = 1; sline < curwin->w_cursor.lnum; ++sline)
! 1917: {
! 1918: i = plines(curwin->w_cursor.lnum - sline);
! 1919: used += i;
! 1920: extra += i;
! 1921: if (extra <= p_so &&
! 1922: curwin->w_cursor.lnum + sline < curbuf->b_ml.ml_line_count)
! 1923: used += plines(curwin->w_cursor.lnum + sline);
! 1924: if (used > curwin->w_height)
! 1925: break;
! 1926: if (curwin->w_cursor.lnum - sline < curwin->w_topline)
! 1927: scrolled += i;
! 1928:
! 1929: /*
! 1930: * If scrolling is needed, scroll at least 'sj' lines.
! 1931: */
! 1932: if ((curwin->w_cursor.lnum - (sline - 1) >= curwin->w_topline ||
! 1933: scrolled >= min_scroll) && extra > p_so)
! 1934: break;
! 1935: }
! 1936:
! 1937: /*
! 1938: * If we don't have enough space, put cursor in the middle.
! 1939: * This makes sure we get the same position when using "k" and "j"
! 1940: * in a small window.
! 1941: */
! 1942: if (used > curwin->w_height)
! 1943: scroll_cursor_halfway(FALSE);
! 1944: else
! 1945: {
! 1946: /*
! 1947: * If "always" is FALSE, only adjust topline to a lower value, higher
! 1948: * value may happen with wrapping lines
! 1949: */
! 1950: if (curwin->w_cursor.lnum - (sline - 1) < curwin->w_topline || always)
! 1951: curwin->w_topline = curwin->w_cursor.lnum - (sline - 1);
! 1952: if (curwin->w_topline > curwin->w_cursor.lnum)
! 1953: curwin->w_topline = curwin->w_cursor.lnum;
! 1954: }
! 1955: }
! 1956:
! 1957: /*
! 1958: * Recompute topline to put the cursor at the bottom of the window.
! 1959: * Scroll at least "min_scroll" lines.
! 1960: * If "set_topline" is TRUE, set topline and botline first (for "zb").
! 1961: * This is messy stuff!!!
! 1962: */
! 1963: void
! 1964: scroll_cursor_bot(min_scroll, set_topline)
! 1965: int min_scroll;
! 1966: int set_topline;
! 1967: {
! 1968: int used;
! 1969: int scrolled = 0;
! 1970: int extra = 0;
! 1971: int sline; /* screen line for cursor from bottom */
! 1972: int i;
! 1973: linenr_t lnum;
! 1974: linenr_t line_count;
! 1975: linenr_t old_topline = curwin->w_topline;
! 1976: linenr_t old_botline = curwin->w_botline;
! 1977: int old_empty_rows = curwin->w_empty_rows;
! 1978: linenr_t cln; /* Cursor Line Number */
! 1979:
! 1980: cln = curwin->w_cursor.lnum;
! 1981: if (set_topline)
! 1982: {
! 1983: used = 0;
! 1984: curwin->w_botline = cln + 1;
! 1985: for (curwin->w_topline = curwin->w_botline;
! 1986: curwin->w_topline != 1;
! 1987: --curwin->w_topline)
! 1988: {
! 1989: i = plines(curwin->w_topline - 1);
! 1990: if (used + i > curwin->w_height)
! 1991: break;
! 1992: used += i;
! 1993: }
! 1994: curwin->w_empty_rows = curwin->w_height - used;
! 1995: }
! 1996:
! 1997: used = plines(cln);
! 1998: if (cln >= curwin->w_botline)
! 1999: {
! 2000: scrolled = used;
! 2001: if (cln == curwin->w_botline)
! 2002: scrolled -= curwin->w_empty_rows;
! 2003: }
! 2004:
! 2005: /*
! 2006: * Stop counting lines to scroll when
! 2007: * - hitting start of the file
! 2008: * - scrolled nothing or at least 'sj' lines
! 2009: * - at least 'so' lines below the cursor
! 2010: * - lines between botline and cursor have been counted
! 2011: */
! 2012: for (sline = 1; sline < cln; ++sline)
! 2013: {
! 2014: if ((((scrolled <= 0 || scrolled >= min_scroll) && extra >= p_so) ||
! 2015: cln + sline > curbuf->b_ml.ml_line_count) &&
! 2016: cln - sline < curwin->w_botline)
! 2017: break;
! 2018: i = plines(cln - sline);
! 2019: used += i;
! 2020: if (used > curwin->w_height)
! 2021: break;
! 2022: if (cln - sline >= curwin->w_botline)
! 2023: {
! 2024: scrolled += i;
! 2025: if (cln - sline == curwin->w_botline)
! 2026: scrolled -= curwin->w_empty_rows;
! 2027: }
! 2028: if (cln + sline <= curbuf->b_ml.ml_line_count)
! 2029: {
! 2030: i = plines(cln + sline);
! 2031: used += i;
! 2032: if (used > curwin->w_height)
! 2033: break;
! 2034: if (extra < p_so || scrolled < min_scroll)
! 2035: {
! 2036: extra += i;
! 2037: if (cln + sline >= curwin->w_botline)
! 2038: {
! 2039: scrolled += i;
! 2040: if (cln + sline == curwin->w_botline)
! 2041: scrolled -= curwin->w_empty_rows;
! 2042: }
! 2043: }
! 2044: }
! 2045: }
! 2046: /* curwin->w_empty_rows is larger, no need to scroll */
! 2047: if (scrolled <= 0)
! 2048: line_count = 0;
! 2049: /* more than a screenfull, don't scroll but redraw */
! 2050: else if (used > curwin->w_height)
! 2051: line_count = used;
! 2052: /* scroll minimal number of lines */
! 2053: else
! 2054: {
! 2055: for (i = 0, lnum = curwin->w_topline;
! 2056: i < scrolled && lnum < curwin->w_botline; ++lnum)
! 2057: i += plines(lnum);
! 2058: if (i >= scrolled) /* it's possible to scroll */
! 2059: line_count = lnum - curwin->w_topline;
! 2060: else /* below curwin->w_botline, don't scroll */
! 2061: line_count = 9999;
! 2062: }
! 2063:
! 2064: /*
! 2065: * Scroll up if the cursor is off the bottom of the screen a bit.
! 2066: * Otherwise put it at 1/2 of the screen.
! 2067: */
! 2068: if (line_count >= curwin->w_height && line_count > min_scroll)
! 2069: scroll_cursor_halfway(FALSE);
! 2070: else
! 2071: scrollup(line_count);
! 2072:
! 2073: /*
! 2074: * If topline didn't change we need to restore w_botline and w_empty_rows
! 2075: * (we changed them).
! 2076: * If topline did change, updateScreen() will set botline.
! 2077: */
! 2078: if (curwin->w_topline == old_topline && set_topline)
! 2079: {
! 2080: curwin->w_botline = old_botline;
! 2081: curwin->w_empty_rows = old_empty_rows;
! 2082: }
! 2083: }
! 2084:
! 2085: /*
! 2086: * Recompute topline to put the cursor halfway the window
! 2087: * If "atend" is TRUE, also put it halfway at the end of the file.
! 2088: */
! 2089: void
! 2090: scroll_cursor_halfway(atend)
! 2091: int atend;
! 2092: {
! 2093: int above = 0;
! 2094: linenr_t topline;
! 2095: int below = 0;
! 2096: linenr_t botline;
! 2097: int used;
! 2098: int i;
! 2099: linenr_t cln; /* Cursor Line Number */
! 2100:
! 2101: topline = botline = cln = curwin->w_cursor.lnum;
! 2102: used = plines(cln);
! 2103: while (topline > 1)
! 2104: {
! 2105: if (below <= above) /* add a line below the cursor */
! 2106: {
! 2107: if (botline + 1 <= curbuf->b_ml.ml_line_count)
! 2108: {
! 2109: i = plines(botline + 1);
! 2110: used += i;
! 2111: if (used > curwin->w_height)
! 2112: break;
! 2113: below += i;
! 2114: ++botline;
! 2115: }
! 2116: else
! 2117: {
! 2118: ++below; /* count a "~" line */
! 2119: if (atend)
! 2120: ++used;
! 2121: }
! 2122: }
! 2123:
! 2124: if (below > above) /* add a line above the cursor */
! 2125: {
! 2126: i = plines(topline - 1);
! 2127: used += i;
! 2128: if (used > curwin->w_height)
! 2129: break;
! 2130: above += i;
! 2131: --topline;
! 2132: }
! 2133: }
! 2134: curwin->w_topline = topline;
! 2135: }
! 2136:
! 2137: /*
! 2138: * Correct the cursor position so that it is in a part of the screen at least
! 2139: * 'so' lines from the top and bottom, if possible.
! 2140: * If not possible, put it at the same position as scroll_cursor_halfway().
! 2141: * When called topline and botline must be valid!
! 2142: */
! 2143: void
! 2144: cursor_correct()
! 2145: {
! 2146: int above = 0; /* screen lines above topline */
! 2147: linenr_t topline;
! 2148: int below = 0; /* screen lines below botline */
! 2149: linenr_t botline;
! 2150: int above_wanted, below_wanted;
! 2151: linenr_t cln; /* Cursor Line Number */
! 2152: int max_off;
! 2153:
! 2154: /*
! 2155: * How many lines we would like to have above/below the cursor depends on
! 2156: * whether the first/last line of the file is on screen.
! 2157: */
! 2158: above_wanted = p_so;
! 2159: below_wanted = p_so;
! 2160: if (curwin->w_topline == 1)
! 2161: {
! 2162: above_wanted = 0;
! 2163: max_off = curwin->w_height / 2;
! 2164: if (below_wanted > max_off)
! 2165: below_wanted = max_off;
! 2166: }
! 2167: if (curwin->w_botline == curbuf->b_ml.ml_line_count + 1)
! 2168: {
! 2169: below_wanted = 0;
! 2170: max_off = (curwin->w_height - 1) / 2;
! 2171: if (above_wanted > max_off)
! 2172: above_wanted = max_off;
! 2173: }
! 2174:
! 2175: /*
! 2176: * If there are sufficient file-lines above and below the cursor, we can
! 2177: * return now.
! 2178: */
! 2179: cln = curwin->w_cursor.lnum;
! 2180: if (cln >= curwin->w_topline + above_wanted &&
! 2181: cln < curwin->w_botline - below_wanted)
! 2182: return;
! 2183:
! 2184: /*
! 2185: * Narrow down the area where the cursor can be put by taking lines from
! 2186: * the top and the bottom until:
! 2187: * - the desired context lines are found
! 2188: * - the lines from the top is past the lines from the bottom
! 2189: */
! 2190: topline = curwin->w_topline;
! 2191: botline = curwin->w_botline - 1;
! 2192: while ((above < above_wanted || below < below_wanted) && topline < botline)
! 2193: {
! 2194: if (below < below_wanted && (below <= above || above >= above_wanted))
! 2195: {
! 2196: below += plines(botline);
! 2197: --botline;
! 2198: }
! 2199: if (above < above_wanted && (above < below || below >= below_wanted))
! 2200: {
! 2201: above += plines(topline);
! 2202: ++topline;
! 2203: }
! 2204: }
! 2205: if (topline == botline || botline == 0)
! 2206: curwin->w_cursor.lnum = topline;
! 2207: else if (topline > botline)
! 2208: curwin->w_cursor.lnum = botline;
! 2209: else
! 2210: {
! 2211: if (cln < topline && curwin->w_topline > 1)
! 2212: curwin->w_cursor.lnum = topline;
! 2213: if (cln > botline && curwin->w_botline <= curbuf->b_ml.ml_line_count)
! 2214: curwin->w_cursor.lnum = botline;
! 2215: }
! 2216: }
! 2217:
! 2218: /*
! 2219: * Compute curwin->w_row.
! 2220: * Can be called when topline and botline have not been updated.
! 2221: * return OK when cursor is in the window, FAIL when it isn't.
! 2222: */
! 2223: int
! 2224: curs_rows()
! 2225: {
! 2226: linenr_t lnum;
! 2227: int i;
! 2228:
! 2229: if (curwin->w_cursor.lnum < curwin->w_topline ||
! 2230: curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count ||
! 2231: curwin->w_cursor.lnum >= curwin->w_botline)
! 2232: return FAIL;
! 2233:
! 2234: curwin->w_row = i = 0;
! 2235: for (lnum = curwin->w_topline; lnum != curwin->w_cursor.lnum; ++lnum)
! 2236: if (RedrawingDisabled) /* curwin->w_lsize[] invalid */
! 2237: curwin->w_row += plines(lnum);
! 2238: else
! 2239: curwin->w_row += curwin->w_lsize[i++];
! 2240: return OK;
! 2241: }
! 2242:
! 2243: /*
! 2244: * compute curwin->w_col and curwin->w_virtcol
! 2245: */
! 2246: void
! 2247: curs_columns(scroll)
! 2248: int scroll; /* when TRUE, may scroll horizontally */
! 2249: {
! 2250: int diff;
! 2251: int extra;
! 2252: int new_leftcol;
! 2253: colnr_t startcol;
! 2254: colnr_t endcol;
! 2255:
! 2256: getvcol(curwin, &curwin->w_cursor,
! 2257: &startcol, &(curwin->w_virtcol), &endcol);
! 2258:
! 2259: /* remove '$' from change command when cursor moves onto it */
! 2260: if (startcol > dollar_vcol)
! 2261: dollar_vcol = 0;
! 2262:
! 2263: curwin->w_col = curwin->w_virtcol;
! 2264: if (curwin->w_p_nu)
! 2265: {
! 2266: curwin->w_col += 8;
! 2267: endcol += 8;
! 2268: }
! 2269:
! 2270: curwin->w_row = curwin->w_cline_row;
! 2271: if (curwin->w_p_wrap) /* long line wrapping, adjust curwin->w_row */
! 2272: {
! 2273: while (curwin->w_col >= Columns)
! 2274: {
! 2275: curwin->w_col -= Columns;
! 2276: curwin->w_row++;
! 2277: }
! 2278: }
! 2279: else if (scroll) /* no line wrapping, compute curwin->w_leftcol if
! 2280: * scrolling is on. If scrolling is off,
! 2281: * curwin->w_leftcol is assumed to be 0 */
! 2282: {
! 2283: /* If Cursor is left of the screen, scroll rightwards */
! 2284: /* If Cursor is right of the screen, scroll leftwards */
! 2285: if ((extra = (int)startcol - (int)curwin->w_leftcol) < 0 ||
! 2286: (extra = (int)endcol - (int)(curwin->w_leftcol + Columns) + 1) > 0)
! 2287: {
! 2288: if (extra < 0)
! 2289: diff = -extra;
! 2290: else
! 2291: diff = extra;
! 2292:
! 2293: /* far off, put cursor in middle of window */
! 2294: if (p_ss == 0 || diff >= Columns / 2)
! 2295: new_leftcol = curwin->w_col - Columns / 2;
! 2296: else
! 2297: {
! 2298: if (diff < p_ss)
! 2299: diff = p_ss;
! 2300: if (extra < 0)
! 2301: new_leftcol = curwin->w_leftcol - diff;
! 2302: else
! 2303: new_leftcol = curwin->w_leftcol + diff;
! 2304: }
! 2305: if (new_leftcol < 0)
! 2306: curwin->w_leftcol = 0;
! 2307: else
! 2308: curwin->w_leftcol = new_leftcol;
! 2309: /* screen has to be redrawn with new curwin->w_leftcol */
! 2310: redraw_later(NOT_VALID);
! 2311: }
! 2312: curwin->w_col -= curwin->w_leftcol;
! 2313: }
! 2314: /* Cursor past end of screen */
! 2315: /* happens with line that does not fit on screen */
! 2316: if (curwin->w_row > curwin->w_height - 1)
! 2317: curwin->w_row = curwin->w_height - 1;
! 2318: }
! 2319:
! 2320: void
! 2321: scrolldown(line_count)
! 2322: long line_count;
! 2323: {
! 2324: register long done = 0; /* total # of physical lines done */
! 2325:
! 2326: /* Scroll up 'line_count' lines. */
! 2327: while (line_count--)
! 2328: {
! 2329: if (curwin->w_topline == 1)
! 2330: break;
! 2331: done += plines(--curwin->w_topline);
! 2332: }
! 2333: /*
! 2334: * Compute the row number of the last row of the cursor line
! 2335: * and move it onto the screen.
! 2336: */
! 2337: curwin->w_row += done;
! 2338: if (curwin->w_p_wrap)
! 2339: curwin->w_row += plines(curwin->w_cursor.lnum) -
! 2340: 1 - curwin->w_virtcol / Columns;
! 2341: while (curwin->w_row >= curwin->w_height && curwin->w_cursor.lnum > 1)
! 2342: curwin->w_row -= plines(curwin->w_cursor.lnum--);
! 2343: comp_Botline(curwin);
! 2344: }
! 2345:
! 2346: void
! 2347: scrollup(line_count)
! 2348: long line_count;
! 2349: {
! 2350: curwin->w_topline += line_count;
! 2351: if (curwin->w_topline > curbuf->b_ml.ml_line_count)
! 2352: curwin->w_topline = curbuf->b_ml.ml_line_count;
! 2353: if (curwin->w_cursor.lnum < curwin->w_topline)
! 2354: curwin->w_cursor.lnum = curwin->w_topline;
! 2355: comp_Botline(curwin);
! 2356: }
! 2357:
! 2358: /*
! 2359: * Scroll the screen one line down, but don't do it if it would move the
! 2360: * cursor off the screen.
! 2361: */
! 2362: void
! 2363: scrolldown_clamp()
! 2364: {
! 2365: int end_row;
! 2366:
! 2367: if (curwin->w_topline == 1)
! 2368: return;
! 2369:
! 2370: /*
! 2371: * Compute the row number of the last row of the cursor line
! 2372: * and make sure it doesn't go off the screen. Make sure the cursor
! 2373: * doesn't go past 'scrolloff' lines from the screen end.
! 2374: */
! 2375: end_row = curwin->w_row + plines(curwin->w_topline - 1);
! 2376: if (curwin->w_p_wrap)
! 2377: end_row += plines(curwin->w_cursor.lnum) - 1 -
! 2378: curwin->w_virtcol / Columns;
! 2379: if (end_row < curwin->w_height - p_so)
! 2380: --curwin->w_topline;
! 2381: }
! 2382:
! 2383: /*
! 2384: * Scroll the screen one line up, but don't do it if it would move the cursor
! 2385: * off the screen.
! 2386: */
! 2387: void
! 2388: scrollup_clamp()
! 2389: {
! 2390: int start_row;
! 2391:
! 2392: if (curwin->w_topline == curbuf->b_ml.ml_line_count)
! 2393: return;
! 2394:
! 2395: /*
! 2396: * Compute the row number of the first row of the cursor line
! 2397: * and make sure it doesn't go off the screen. Make sure the cursor
! 2398: * doesn't go before 'scrolloff' lines from the screen start.
! 2399: */
! 2400: start_row = curwin->w_row - plines(curwin->w_topline);
! 2401: if (curwin->w_p_wrap)
! 2402: start_row -= curwin->w_virtcol / Columns;
! 2403: if (start_row >= p_so)
! 2404: ++curwin->w_topline;
! 2405: }
! 2406:
! 2407: /*
! 2408: * insert 'line_count' lines at 'row' in window 'wp'
! 2409: * if 'invalid' is TRUE the wp->w_lsize_lnum[] is invalidated.
! 2410: * if 'mayclear' is TRUE the screen will be cleared if it is faster than
! 2411: * scrolling.
! 2412: * Returns FAIL if the lines are not inserted, OK for success.
! 2413: */
! 2414: int
! 2415: win_ins_lines(wp, row, line_count, invalid, mayclear)
! 2416: WIN *wp;
! 2417: int row;
! 2418: int line_count;
! 2419: int invalid;
! 2420: int mayclear;
! 2421: {
! 2422: int did_delete;
! 2423: int nextrow;
! 2424: int lastrow;
! 2425: int retval;
! 2426:
! 2427: if (invalid)
! 2428: wp->w_lsize_valid = 0;
! 2429:
! 2430: if (RedrawingDisabled || line_count <= 0 || wp->w_height < 5)
! 2431: return FAIL;
! 2432:
! 2433: if (line_count > wp->w_height - row)
! 2434: line_count = wp->w_height - row;
! 2435:
! 2436: if (mayclear && Rows - line_count < 5) /* only a few lines left: redraw is faster */
! 2437: {
! 2438: screenclear(); /* will set wp->w_lsize_valid to 0 */
! 2439: return FAIL;
! 2440: }
! 2441:
! 2442: /*
! 2443: * Delete all remaining lines
! 2444: */
! 2445: if (row + line_count >= wp->w_height)
! 2446: {
! 2447: screen_fill(wp->w_winpos + row, wp->w_winpos + wp->w_height,
! 2448: 0, (int)Columns, ' ', ' ');
! 2449: return OK;
! 2450: }
! 2451:
! 2452: /*
! 2453: * when scrolling, the message on the command line should be cleared,
! 2454: * otherwise it will stay there forever.
! 2455: */
! 2456: clear_cmdline = TRUE;
! 2457:
! 2458: /*
! 2459: * if the terminal can set a scroll region, use that
! 2460: */
! 2461: if (scroll_region)
! 2462: {
! 2463: scroll_region_set(wp, row);
! 2464: retval = screen_ins_lines(wp->w_winpos + row, 0, line_count,
! 2465: wp->w_height - row);
! 2466: scroll_region_reset();
! 2467: return retval;
! 2468: }
! 2469:
! 2470: if (wp->w_next && p_tf) /* don't delete/insert on fast terminal */
! 2471: return FAIL;
! 2472:
! 2473: /*
! 2474: * If there is a next window or a status line, we first try to delete the
! 2475: * lines at the bottom to avoid messing what is after the window.
! 2476: * If this fails and there are following windows, don't do anything to avoid
! 2477: * messing up those windows, better just redraw.
! 2478: */
! 2479: did_delete = FALSE;
! 2480: if (wp->w_next || wp->w_status_height)
! 2481: {
! 2482: if (screen_del_lines(0, wp->w_winpos + wp->w_height - line_count,
! 2483: line_count, (int)Rows, FALSE) == OK)
! 2484: did_delete = TRUE;
! 2485: else if (wp->w_next)
! 2486: return FAIL;
! 2487: }
! 2488: /*
! 2489: * if no lines deleted, blank the lines that will end up below the window
! 2490: */
! 2491: if (!did_delete)
! 2492: {
! 2493: wp->w_redr_status = TRUE;
! 2494: redraw_cmdline = TRUE;
! 2495: nextrow = wp->w_winpos + wp->w_height + wp->w_status_height;
! 2496: lastrow = nextrow + line_count;
! 2497: if (lastrow > Rows)
! 2498: lastrow = Rows;
! 2499: screen_fill(nextrow - line_count, lastrow - line_count,
! 2500: 0, (int)Columns, ' ', ' ');
! 2501: }
! 2502:
! 2503: if (screen_ins_lines(0, wp->w_winpos + row, line_count, (int)Rows) == FAIL)
! 2504: {
! 2505: /* deletion will have messed up other windows */
! 2506: if (did_delete)
! 2507: {
! 2508: wp->w_redr_status = TRUE;
! 2509: win_rest_invalid(wp->w_next);
! 2510: }
! 2511: return FAIL;
! 2512: }
! 2513:
! 2514: return OK;
! 2515: }
! 2516:
! 2517: /*
! 2518: * delete 'line_count' lines at 'row' in window 'wp'
! 2519: * If 'invalid' is TRUE curwin->w_lsize_lnum[] is invalidated.
! 2520: * If 'mayclear' is TRUE the screen will be cleared if it is faster than
! 2521: * scrolling
! 2522: * Return OK for success, FAIL if the lines are not deleted.
! 2523: */
! 2524: int
! 2525: win_del_lines(wp, row, line_count, invalid, mayclear)
! 2526: WIN *wp;
! 2527: int row;
! 2528: int line_count;
! 2529: int invalid;
! 2530: int mayclear;
! 2531: {
! 2532: int retval;
! 2533:
! 2534: if (invalid)
! 2535: wp->w_lsize_valid = 0;
! 2536:
! 2537: if (RedrawingDisabled || line_count <= 0)
! 2538: return FAIL;
! 2539:
! 2540: if (line_count > wp->w_height - row)
! 2541: line_count = wp->w_height - row;
! 2542:
! 2543: /* only a few lines left: redraw is faster */
! 2544: if (mayclear && Rows - line_count < 5)
! 2545: {
! 2546: screenclear(); /* will set wp->w_lsize_valid to 0 */
! 2547: return FAIL;
! 2548: }
! 2549:
! 2550: /*
! 2551: * Delete all remaining lines
! 2552: */
! 2553: if (row + line_count >= wp->w_height)
! 2554: {
! 2555: screen_fill(wp->w_winpos + row, wp->w_winpos + wp->w_height,
! 2556: 0, (int)Columns, ' ', ' ');
! 2557: return OK;
! 2558: }
! 2559:
! 2560: /*
! 2561: * when scrolling, the message on the command line should be cleared,
! 2562: * otherwise it will stay there forever.
! 2563: */
! 2564: clear_cmdline = TRUE;
! 2565:
! 2566: /*
! 2567: * if the terminal can set a scroll region, use that
! 2568: */
! 2569: if (scroll_region)
! 2570: {
! 2571: scroll_region_set(wp, row);
! 2572: retval = screen_del_lines(wp->w_winpos + row, 0, line_count,
! 2573: wp->w_height - row, FALSE);
! 2574: scroll_region_reset();
! 2575: return retval;
! 2576: }
! 2577:
! 2578: if (wp->w_next && p_tf) /* don't delete/insert on fast terminal */
! 2579: return FAIL;
! 2580:
! 2581: if (screen_del_lines(0, wp->w_winpos + row, line_count,
! 2582: (int)Rows, FALSE) == FAIL)
! 2583: return FAIL;
! 2584:
! 2585: /*
! 2586: * If there are windows or status lines below, try to put them at the
! 2587: * correct place. If we can't do that, they have to be redrawn.
! 2588: */
! 2589: if (wp->w_next || wp->w_status_height || cmdline_row < Rows - 1)
! 2590: {
! 2591: if (screen_ins_lines(0, wp->w_winpos + wp->w_height - line_count,
! 2592: line_count, (int)Rows) == FAIL)
! 2593: {
! 2594: wp->w_redr_status = TRUE;
! 2595: win_rest_invalid(wp->w_next);
! 2596: }
! 2597: }
! 2598: /*
! 2599: * If this is the last window and there is no status line, redraw the
! 2600: * command line later.
! 2601: */
! 2602: else
! 2603: redraw_cmdline = TRUE;
! 2604: return OK;
! 2605: }
! 2606:
! 2607: /*
! 2608: * window 'wp' and everything after it is messed up, mark it for redraw
! 2609: */
! 2610: void
! 2611: win_rest_invalid(wp)
! 2612: WIN *wp;
! 2613: {
! 2614: while (wp)
! 2615: {
! 2616: wp->w_lsize_valid = 0;
! 2617: wp->w_redr_type = NOT_VALID;
! 2618: wp->w_redr_status = TRUE;
! 2619: wp = wp->w_next;
! 2620: }
! 2621: redraw_cmdline = TRUE;
! 2622: }
! 2623:
! 2624: /*
! 2625: * The rest of the routines in this file perform screen manipulations. The
! 2626: * given operation is performed physically on the screen. The corresponding
! 2627: * change is also made to the internal screen image. In this way, the editor
! 2628: * anticipates the effect of editing changes on the appearance of the screen.
! 2629: * That way, when we call screenupdate a complete redraw isn't usually
! 2630: * necessary. Another advantage is that we can keep adding code to anticipate
! 2631: * screen changes, and in the meantime, everything still works.
! 2632: */
! 2633:
! 2634: /*
! 2635: * types for inserting or deleting lines
! 2636: */
! 2637: #define USE_T_CAL 1
! 2638: #define USE_T_CDL 2
! 2639: #define USE_T_AL 3
! 2640: #define USE_T_CE 4
! 2641: #define USE_T_DL 5
! 2642: #define USE_T_SR 6
! 2643: #define USE_NL 7
! 2644: #define USE_T_CD 8
! 2645:
! 2646: /*
! 2647: * insert lines on the screen and update NextScreen
! 2648: * 'end' is the line after the scrolled part. Normally it is Rows.
! 2649: * When scrolling region used 'off' is the offset from the top for the region.
! 2650: * 'row' and 'end' are relative to the start of the region.
! 2651: *
! 2652: * return FAIL for failure, OK for success.
! 2653: */
! 2654: static int
! 2655: screen_ins_lines(off, row, line_count, end)
! 2656: int off;
! 2657: int row;
! 2658: int line_count;
! 2659: int end;
! 2660: {
! 2661: int i;
! 2662: int j;
! 2663: char_u *temp;
! 2664: int cursor_row;
! 2665: int type;
! 2666: int result_empty;
! 2667:
! 2668: /*
! 2669: * FAIL if
! 2670: * - there is no valid screen
! 2671: * - the screen has to be redrawn completely
! 2672: * - the line count is less than one
! 2673: * - the line count is more than 'ttyscroll'
! 2674: */
! 2675: if (!screen_valid(TRUE) || line_count <= 0 || line_count > p_ttyscroll)
! 2676: return FAIL;
! 2677:
! 2678: /*
! 2679: * There are seven ways to insert lines:
! 2680: * 1. Use T_CD (clear to end of display) if it exists and the result of
! 2681: * the insert is just empty lines
! 2682: * 2. Use T_CAL (insert multiple lines) if it exists and T_AL is not
! 2683: * present or line_count > 1. It looks better if we do all the inserts
! 2684: * at once.
! 2685: * 3. Use T_CDL (delete multiple lines) if it exists and the result of the
! 2686: * insert is just empty lines and T_CE is not present or line_count >
! 2687: * 1.
! 2688: * 4. Use T_AL (insert line) if it exists.
! 2689: * 5. Use T_CE (erase line) if it exists and the result of the insert is
! 2690: * just empty lines.
! 2691: * 6. Use T_DL (delete line) if it exists and the result of the insert is
! 2692: * just empty lines.
! 2693: * 7. Use T_SR (scroll reverse) if it exists and inserting at row 0 and
! 2694: * the 'da' flag is not set or we have clear line capability.
! 2695: *
! 2696: * Careful: In a hpterm scroll reverse doesn't work as expected, it moves
! 2697: * the scrollbar for the window. It does have insert line, use that if it
! 2698: * exists.
! 2699: */
! 2700: result_empty = (row + line_count >= end);
! 2701: if (*T_CD != NUL && result_empty)
! 2702: type = USE_T_CD;
! 2703: else if (*T_CAL != NUL && (line_count > 1 || *T_AL == NUL))
! 2704: type = USE_T_CAL;
! 2705: else if (*T_CDL != NUL && result_empty && (line_count > 1 || *T_CE == NUL))
! 2706: type = USE_T_CDL;
! 2707: else if (*T_AL != NUL)
! 2708: type = USE_T_AL;
! 2709: else if (*T_CE != NUL && result_empty)
! 2710: type = USE_T_CE;
! 2711: else if (*T_DL != NUL && result_empty)
! 2712: type = USE_T_DL;
! 2713: else if (*T_SR != NUL && row == 0 && (*T_DA == NUL || *T_CE))
! 2714: type = USE_T_SR;
! 2715: else
! 2716: return FAIL;
! 2717:
! 2718: /*
! 2719: * For clearing the lines screen_del_lines is used. This will also take
! 2720: * care of t_db if necessary.
! 2721: */
! 2722: if (type == USE_T_CD || type == USE_T_CDL ||
! 2723: type == USE_T_CE || type == USE_T_DL)
! 2724: return screen_del_lines(off, row, line_count, end, FALSE);
! 2725:
! 2726: /*
! 2727: * If text is retained below the screen, first clear or delete as many
! 2728: * lines at the bottom of the window as are about to be inserted so that
! 2729: * the deleted lines won't later surface during a screen_del_lines.
! 2730: */
! 2731: if (*T_DB)
! 2732: screen_del_lines(off, end - line_count, line_count, end, FALSE);
! 2733:
! 2734: if (*T_CSC != NUL) /* cursor relative to region */
! 2735: cursor_row = row;
! 2736: else
! 2737: cursor_row = row + off;
! 2738:
! 2739: /*
! 2740: * Shift LinePointers line_count down to reflect the inserted lines.
! 2741: * Clear the inserted lines in NextScreen.
! 2742: */
! 2743: row += off;
! 2744: end += off;
! 2745: for (i = 0; i < line_count; ++i)
! 2746: {
! 2747: j = end - 1 - i;
! 2748: temp = LinePointers[j];
! 2749: while ((j -= line_count) >= row)
! 2750: LinePointers[j + line_count] = LinePointers[j];
! 2751: LinePointers[j + line_count] = temp;
! 2752: lineclear(temp);
! 2753: }
! 2754:
! 2755: windgoto(cursor_row, 0);
! 2756: if (type == USE_T_CAL)
! 2757: {
! 2758: OUTSTR(tgoto((char *)T_CAL, 0, line_count));
! 2759: screen_start(); /* don't know where cursor is now */
! 2760: }
! 2761: else
! 2762: {
! 2763: for (i = 0; i < line_count; i++)
! 2764: {
! 2765: if (type == USE_T_AL)
! 2766: {
! 2767: if (i && cursor_row != 0)
! 2768: windgoto(cursor_row, 0);
! 2769: outstr(T_AL);
! 2770: }
! 2771: else /* type == USE_T_SR */
! 2772: outstr(T_SR);
! 2773: screen_start(); /* don't know where cursor is now */
! 2774: }
! 2775: }
! 2776:
! 2777: /*
! 2778: * With scroll-reverse and 'da' flag set we need to clear the lines that
! 2779: * have been scrolled down into the region.
! 2780: */
! 2781: if (type == USE_T_SR && *T_DA)
! 2782: {
! 2783: for (i = 0; i < line_count; ++i)
! 2784: {
! 2785: windgoto(off + i, 0);
! 2786: outstr(T_CE);
! 2787: screen_start(); /* don't know where cursor is now */
! 2788: }
! 2789: }
! 2790:
! 2791: return OK;
! 2792: }
! 2793:
! 2794: /*
! 2795: * delete lines on the screen and update NextScreen
! 2796: * 'end' is the line after the scrolled part. Normally it is Rows.
! 2797: * When scrolling region used 'off' is the offset from the top for the region.
! 2798: * 'row' and 'end' are relative to the start of the region.
! 2799: *
! 2800: * Return OK for success, FAIL if the lines are not deleted.
! 2801: */
! 2802: int
! 2803: screen_del_lines(off, row, line_count, end, force)
! 2804: int off;
! 2805: int row;
! 2806: int line_count;
! 2807: int end;
! 2808: int force; /* even when line_count > p_ttyscroll */
! 2809: {
! 2810: int j;
! 2811: int i;
! 2812: char_u *temp;
! 2813: int cursor_row;
! 2814: int cursor_end;
! 2815: int result_empty; /* result is empty until end of region */
! 2816: int can_delete; /* deleting line codes can be used */
! 2817: int type;
! 2818:
! 2819: /*
! 2820: * FAIL if
! 2821: * - there is no valid screen
! 2822: * - the screen has to be redrawn completely
! 2823: * - the line count is less than one
! 2824: * - the line count is more than 'ttyscroll'
! 2825: */
! 2826: if (!screen_valid(TRUE) || line_count <= 0 ||
! 2827: (!force && line_count > p_ttyscroll))
! 2828: return FAIL;
! 2829:
! 2830: /*
! 2831: * Check if the rest of the current region will become empty.
! 2832: */
! 2833: result_empty = row + line_count >= end;
! 2834:
! 2835: /*
! 2836: * We can delete lines only when 'db' flag not set or when 'ce' option
! 2837: * available.
! 2838: */
! 2839: can_delete = (*T_DB == NUL || *T_CE);
! 2840:
! 2841: /*
! 2842: * There are four ways to delete lines:
! 2843: * 1. Use T_CD if it exists and the result is empty.
! 2844: * 2. Use newlines if row == 0 and count == 1 or T_CDL does not exist.
! 2845: * 3. Use T_CDL (delete multiple lines) if it exists and line_count > 1 or
! 2846: * none of the other ways work.
! 2847: * 4. Use T_CE (erase line) if the result is empty.
! 2848: * 5. Use T_DL (delete line) if it exists.
! 2849: */
! 2850: if (*T_CD != NUL && result_empty)
! 2851: type = USE_T_CD;
! 2852: else if (row == 0 && (line_count == 1 || *T_CDL == NUL))
! 2853: type = USE_NL;
! 2854: else if (*T_CDL != NUL && line_count > 1 && can_delete)
! 2855: type = USE_T_CDL;
! 2856: else if (*T_CE != NUL && result_empty)
! 2857: type = USE_T_CE;
! 2858: else if (*T_DL != NUL && can_delete)
! 2859: type = USE_T_DL;
! 2860: else if (*T_CDL != NUL && can_delete)
! 2861: type = USE_T_CDL;
! 2862: else
! 2863: return FAIL;
! 2864:
! 2865: if (*T_CSC != NUL) /* cursor relative to region */
! 2866: {
! 2867: cursor_row = row;
! 2868: cursor_end = end;
! 2869: }
! 2870: else
! 2871: {
! 2872: cursor_row = row + off;
! 2873: cursor_end = end + off;
! 2874: }
! 2875:
! 2876: /*
! 2877: * Now shift LinePointers line_count up to reflect the deleted lines.
! 2878: * Clear the inserted lines in NextScreen.
! 2879: */
! 2880: row += off;
! 2881: end += off;
! 2882: for (i = 0; i < line_count; ++i)
! 2883: {
! 2884: j = row + i;
! 2885: temp = LinePointers[j];
! 2886: while ((j += line_count) <= end - 1)
! 2887: LinePointers[j - line_count] = LinePointers[j];
! 2888: LinePointers[j - line_count] = temp;
! 2889: lineclear(temp);
! 2890: }
! 2891:
! 2892: /* delete the lines */
! 2893: if (type == USE_T_CD)
! 2894: {
! 2895: windgoto(cursor_row, 0);
! 2896: outstr(T_CD);
! 2897: screen_start(); /* don't know where cursor is now */
! 2898: }
! 2899: else if (type == USE_T_CDL)
! 2900: {
! 2901: windgoto(cursor_row, 0);
! 2902: OUTSTR(tgoto((char *)T_CDL, 0, line_count));
! 2903: screen_start(); /* don't know where cursor is now */
! 2904: }
! 2905: /*
! 2906: * Deleting lines at top of the screen or scroll region: Just scroll
! 2907: * the whole screen (scroll region) up by outputting newlines on the
! 2908: * last line.
! 2909: */
! 2910: else if (type == USE_NL)
! 2911: {
! 2912: windgoto(cursor_end - 1, 0);
! 2913: for (i = line_count; --i >= 0; )
! 2914: outchar('\n'); /* cursor will remain on same line */
! 2915: }
! 2916: else
! 2917: {
! 2918: for (i = line_count; --i >= 0; )
! 2919: {
! 2920: if (type == USE_T_DL)
! 2921: {
! 2922: windgoto(cursor_row, 0);
! 2923: outstr(T_DL); /* delete a line */
! 2924: }
! 2925: else /* type == USE_T_CE */
! 2926: {
! 2927: windgoto(cursor_row + i, 0);
! 2928: outstr(T_CE); /* erase a line */
! 2929: }
! 2930: screen_start(); /* don't know where cursor is now */
! 2931: }
! 2932: }
! 2933:
! 2934: /*
! 2935: * If the 'db' flag is set, we need to clear the lines that have been
! 2936: * scrolled up at the bottom of the region.
! 2937: */
! 2938: if (*T_DB && (type == USE_T_DL || type == USE_T_CDL))
! 2939: {
! 2940: for (i = line_count; i > 0; --i)
! 2941: {
! 2942: windgoto(cursor_end - i, 0);
! 2943: outstr(T_CE); /* erase a line */
! 2944: screen_start(); /* don't know where cursor is now */
! 2945: }
! 2946: }
! 2947: return OK;
! 2948: }
! 2949:
! 2950: /*
! 2951: * show the current mode and ruler
! 2952: *
! 2953: * If clear_cmdline is TRUE, clear the rest of the cmdline.
! 2954: * If clear_cmdline is FALSE there may be a message there that needs to be
! 2955: * cleared only if a mode is shown.
! 2956: */
! 2957: void
! 2958: showmode()
! 2959: {
! 2960: int need_clear = FALSE;
! 2961: int do_mode = (p_smd &&
! 2962: ((State & INSERT) || restart_edit || VIsual_active));
! 2963:
! 2964: if (do_mode || Recording)
! 2965: {
! 2966: if (emsg_on_display)
! 2967: {
! 2968: mch_delay(1000L, TRUE);
! 2969: emsg_on_display = FALSE;
! 2970: }
! 2971: msg_didout = FALSE; /* never scroll up */
! 2972: msg_col = 0;
! 2973: gotocmdline(FALSE);
! 2974: set_highlight('M'); /* Highlight mode */
! 2975: if (do_mode)
! 2976: {
! 2977: start_highlight();
! 2978: MSG_OUTSTR("--");
! 2979: #ifdef INSERT_EXPAND
! 2980: if (edit_submode != NULL) /* CTRL-X in Insert mode */
! 2981: {
! 2982: msg_outstr(edit_submode);
! 2983: if (edit_submode_extra != NULL)
! 2984: {
! 2985: msg_outchar(' '); /* add a space in between */
! 2986: if (edit_submode_highl)
! 2987: {
! 2988: stop_highlight();
! 2989: set_highlight('r'); /* Highlight mode */
! 2990: start_highlight();
! 2991: }
! 2992: msg_outstr(edit_submode_extra);
! 2993: if (edit_submode_highl)
! 2994: {
! 2995: stop_highlight();
! 2996: set_highlight('M'); /* Highlight mode */
! 2997: start_highlight();
! 2998: }
! 2999: }
! 3000: }
! 3001: else
! 3002: #endif
! 3003: {
! 3004: if (State == INSERT)
! 3005: {
! 3006: #ifdef RIGHTLEFT
! 3007: if (p_ri)
! 3008: MSG_OUTSTR(" REVERSE");
! 3009: #endif
! 3010: MSG_OUTSTR(" INSERT");
! 3011: }
! 3012: else if (State == REPLACE)
! 3013: MSG_OUTSTR(" REPLACE");
! 3014: else if (restart_edit == 'I')
! 3015: MSG_OUTSTR(" (insert)");
! 3016: else if (restart_edit == 'R')
! 3017: MSG_OUTSTR(" (replace)");
! 3018: #ifdef RIGHTLEFT
! 3019: if (p_hkmap)
! 3020: MSG_OUTSTR(" Hebrew");
! 3021: #endif
! 3022: if ((State & INSERT) && p_paste)
! 3023: MSG_OUTSTR(" (paste)");
! 3024: if (VIsual_active)
! 3025: {
! 3026: MSG_OUTSTR(" VISUAL");
! 3027: if (VIsual_mode == Ctrl('V'))
! 3028: MSG_OUTSTR(" BLOCK");
! 3029: else if (VIsual_mode == 'V')
! 3030: MSG_OUTSTR(" LINE");
! 3031: }
! 3032: }
! 3033: MSG_OUTSTR(" --");
! 3034: need_clear = TRUE;
! 3035: }
! 3036: if (Recording)
! 3037: {
! 3038: if (!need_clear)
! 3039: start_highlight();
! 3040: MSG_OUTSTR("recording");
! 3041: need_clear = TRUE;
! 3042: }
! 3043: if (need_clear)
! 3044: stop_highlight();
! 3045: if (need_clear || clear_cmdline)
! 3046: msg_clr_eos();
! 3047: msg_didout = FALSE; /* overwrite this message */
! 3048: msg_col = 0;
! 3049: }
! 3050: else if (clear_cmdline) /* just clear anything */
! 3051: {
! 3052: msg_row = cmdline_row;
! 3053: msg_col = 0;
! 3054: msg_clr_eos(); /* will reset clear_cmdline */
! 3055: }
! 3056: win_redr_ruler(lastwin, TRUE);
! 3057: redraw_cmdline = FALSE;
! 3058: }
! 3059:
! 3060: /*
! 3061: * delete mode message
! 3062: */
! 3063: void
! 3064: delmode()
! 3065: {
! 3066: if (Recording)
! 3067: MSG("recording");
! 3068: else
! 3069: MSG("");
! 3070: }
! 3071:
! 3072: /*
! 3073: * if ruler option is set: show current cursor position
! 3074: * if always is FALSE, only print if position has changed
! 3075: */
! 3076: void
! 3077: showruler(always)
! 3078: int always;
! 3079: {
! 3080: win_redr_ruler(curwin, always);
! 3081: }
! 3082:
! 3083: void
! 3084: win_redr_ruler(wp, always)
! 3085: WIN *wp;
! 3086: int always;
! 3087: {
! 3088: static linenr_t old_lnum = 0;
! 3089: static colnr_t old_col = 0;
! 3090: char_u buffer[30];
! 3091: int row;
! 3092: int fillchar;
! 3093:
! 3094: if (p_ru && (redraw_cmdline || always ||
! 3095: wp->w_cursor.lnum != old_lnum || wp->w_virtcol != old_col))
! 3096: {
! 3097: cursor_off();
! 3098: if (wp->w_status_height)
! 3099: {
! 3100: row = wp->w_winpos + wp->w_height;
! 3101: if (set_highlight('s') == OK) /* can use highlighting */
! 3102: {
! 3103: fillchar = ' ';
! 3104: start_highlight();
! 3105: }
! 3106: else
! 3107: fillchar = '=';
! 3108: }
! 3109: else
! 3110: {
! 3111: row = Rows - 1;
! 3112: fillchar = ' ';
! 3113: }
! 3114: /*
! 3115: * Some sprintfs return the length, some return a pointer.
! 3116: * To avoid portability problems we use strlen() here.
! 3117: */
! 3118:
! 3119: sprintf((char *)buffer, "%ld,",
! 3120: (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ?
! 3121: 0L :
! 3122: (long)(wp->w_cursor.lnum));
! 3123: /*
! 3124: * Check if cursor.lnum is valid, since win_redr_ruler() may be called
! 3125: * after deleting lines, before cursor.lnum is corrected.
! 3126: */
! 3127: if (wp->w_cursor.lnum <= wp->w_buffer->b_ml.ml_line_count)
! 3128: col_print(buffer + STRLEN(buffer),
! 3129: !(State & INSERT) &&
! 3130: *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, FALSE) == NUL ?
! 3131: 0 :
! 3132: (int)wp->w_cursor.col + 1,
! 3133: (int)wp->w_virtcol + 1);
! 3134:
! 3135: screen_msg(buffer, row, ru_col);
! 3136: screen_fill(row, row + 1, ru_col + (int)STRLEN(buffer),
! 3137: (int)Columns, fillchar, fillchar);
! 3138: old_lnum = wp->w_cursor.lnum;
! 3139: old_col = wp->w_virtcol;
! 3140: stop_highlight();
! 3141: }
! 3142: }
! 3143:
! 3144: /*
! 3145: * screen_valid - allocate screen buffers if size changed
! 3146: * If "clear" is TRUE: clear screen if it has been resized.
! 3147: * Returns TRUE if there is a valid screen to write to.
! 3148: * Returns FALSE when starting up and screen not initialized yet.
! 3149: */
! 3150: int
! 3151: screen_valid(clear)
! 3152: int clear;
! 3153: {
! 3154: screenalloc(clear); /* allocate screen buffers if size changed */
! 3155: return (NextScreen != NULL);
! 3156: }
! 3157:
! 3158: #ifdef USE_MOUSE
! 3159: /*
! 3160: * Move the cursor to the specified row and column on the screen.
! 3161: * Change current window if neccesary. Returns an integer with the
! 3162: * CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
! 3163: *
! 3164: * If flags has MOUSE_FOCUS, then the current window will not be changed, and
! 3165: * if the mouse is outside the window then the text will scroll, or if the
! 3166: * mouse was previously on a status line, then the status line may be dragged.
! 3167: *
! 3168: * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
! 3169: * cursor is moved unless the cursor was on a status line. Ignoring the
! 3170: * CURSOR_MOVED bit, this function returns one of IN_UNKNOWN, IN_BUFFER, or
! 3171: * IN_STATUS_LINE depending on where the cursor was clicked.
! 3172: *
! 3173: * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
! 3174: * the last call.
! 3175: *
! 3176: * If flags has MOUSE_SETPOS, nothing is done, only the current position is
! 3177: * remembered.
! 3178: */
! 3179: int
! 3180: jump_to_mouse(flags)
! 3181: int flags;
! 3182: {
! 3183: static int on_status_line = 0; /* #lines below bottom of window */
! 3184: static int prev_row = -1;
! 3185: static int prev_col = -1;
! 3186:
! 3187: WIN *wp, *old_curwin;
! 3188: FPOS old_cursor;
! 3189: int count;
! 3190: int first;
! 3191: int row = mouse_row;
! 3192: int col = mouse_col;
! 3193:
! 3194: mouse_past_bottom = FALSE;
! 3195: mouse_past_eol = FALSE;
! 3196:
! 3197: if ((flags & MOUSE_DID_MOVE) && prev_row == mouse_row &&
! 3198: prev_col == mouse_col)
! 3199: return IN_BUFFER; /* mouse pointer didn't move */
! 3200:
! 3201: prev_row = mouse_row;
! 3202: prev_col = mouse_col;
! 3203:
! 3204: if ((flags & MOUSE_SETPOS))
! 3205: return IN_BUFFER; /* mouse pointer didn't move */
! 3206:
! 3207: old_curwin = curwin;
! 3208: old_cursor = curwin->w_cursor;
! 3209:
! 3210: if (!(flags & MOUSE_FOCUS))
! 3211: {
! 3212: if (row < 0 || col < 0) /* check if it makes sense */
! 3213: return IN_UNKNOWN;
! 3214:
! 3215: /* find the window where the row is in */
! 3216: for (wp = firstwin; wp->w_next; wp = wp->w_next)
! 3217: if (row < wp->w_next->w_winpos)
! 3218: break;
! 3219: /*
! 3220: * winpos and height may change in win_enter()!
! 3221: */
! 3222: row -= wp->w_winpos;
! 3223: if (row >= wp->w_height) /* In (or below) status line */
! 3224: on_status_line = row - wp->w_height + 1;
! 3225: else
! 3226: on_status_line = 0;
! 3227: win_enter(wp, TRUE);
! 3228: if (on_status_line) /* In (or below) status line */
! 3229: {
! 3230: /* Don't use start_arrow() if we're in the same window */
! 3231: if (curwin == old_curwin)
! 3232: return IN_STATUS_LINE;
! 3233: else
! 3234: return IN_STATUS_LINE | CURSOR_MOVED;
! 3235: }
! 3236:
! 3237: curwin->w_cursor.lnum = curwin->w_topline;
! 3238: }
! 3239: else if (on_status_line)
! 3240: {
! 3241: /* Drag the status line */
! 3242: count = row - curwin->w_winpos - curwin->w_height + 1 - on_status_line;
! 3243: win_drag_status_line(count);
! 3244: return IN_STATUS_LINE; /* Cursor didn't move */
! 3245: }
! 3246: else /* keep_window_focus must be TRUE */
! 3247: {
! 3248: row -= curwin->w_winpos;
! 3249:
! 3250: /*
! 3251: * When clicking beyond the end of the window, scroll the screen.
! 3252: * Scroll by however many rows outside the window we are.
! 3253: */
! 3254: if (row < 0)
! 3255: {
! 3256: count = 0;
! 3257: for (first = TRUE; curwin->w_topline > 1; --curwin->w_topline)
! 3258: {
! 3259: count += plines(curwin->w_topline - 1);
! 3260: if (!first && count > -row)
! 3261: break;
! 3262: first = FALSE;
! 3263: }
! 3264: redraw_later(VALID);
! 3265: row = 0;
! 3266: }
! 3267: else if (row >= curwin->w_height)
! 3268: {
! 3269: count = 0;
! 3270: for (first = TRUE; curwin->w_topline < curbuf->b_ml.ml_line_count;
! 3271: ++curwin->w_topline)
! 3272: {
! 3273: count += plines(curwin->w_topline);
! 3274: if (!first && count > row - curwin->w_height + 1)
! 3275: break;
! 3276: first = FALSE;
! 3277: }
! 3278: redraw_later(VALID);
! 3279: row = curwin->w_height - 1;
! 3280: }
! 3281: curwin->w_cursor.lnum = curwin->w_topline;
! 3282: }
! 3283:
! 3284: #ifdef RIGHTLEFT
! 3285: if (curwin->w_p_rl)
! 3286: col = Columns - 1 - col;
! 3287: #endif
! 3288:
! 3289: if (curwin->w_p_nu) /* skip number in front of the line */
! 3290: if ((col -= 8) < 0)
! 3291: col = 0;
! 3292:
! 3293: if (curwin->w_p_wrap) /* lines wrap */
! 3294: {
! 3295: while (row)
! 3296: {
! 3297: count = plines(curwin->w_cursor.lnum);
! 3298: if (count > row)
! 3299: {
! 3300: col += row * Columns;
! 3301: break;
! 3302: }
! 3303: if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
! 3304: {
! 3305: mouse_past_bottom = TRUE;
! 3306: break;
! 3307: }
! 3308: row -= count;
! 3309: ++curwin->w_cursor.lnum;
! 3310: }
! 3311: }
! 3312: else /* lines don't wrap */
! 3313: {
! 3314: curwin->w_cursor.lnum += row;
! 3315: if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
! 3316: {
! 3317: curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
! 3318: mouse_past_bottom = TRUE;
! 3319: }
! 3320: col += curwin->w_leftcol;
! 3321: }
! 3322: curwin->w_curswant = col;
! 3323: curwin->w_set_curswant = FALSE; /* May still have been TRUE */
! 3324: if (coladvance(col) == FAIL)
! 3325: {
! 3326: /* Mouse click beyond end of line */
! 3327: op_inclusive = TRUE;
! 3328: mouse_past_eol = TRUE;
! 3329: }
! 3330: else
! 3331: op_inclusive = FALSE;
! 3332:
! 3333: if ((flags & MOUSE_MAY_VIS) && !VIsual_active)
! 3334: {
! 3335: start_visual_highlight();
! 3336: VIsual = old_cursor;
! 3337: VIsual_active = TRUE;
! 3338: #ifdef USE_MOUSE
! 3339: setmouse();
! 3340: #endif
! 3341: if (p_smd)
! 3342: redraw_cmdline = TRUE; /* show visual mode later */
! 3343: }
! 3344:
! 3345: if (curwin == old_curwin && curwin->w_cursor.lnum == old_cursor.lnum &&
! 3346: curwin->w_cursor.col == old_cursor.col)
! 3347: return IN_BUFFER; /* Cursor has not moved */
! 3348: return IN_BUFFER | CURSOR_MOVED; /* Cursor has moved */
! 3349: }
! 3350: #endif /* USE_MOUSE */
! 3351:
! 3352: /*
! 3353: * Redraw the screen later, with UpdateScreen(type).
! 3354: * Set must_redraw only of not already set to a higher value.
! 3355: * e.g. if must_redraw is CLEAR, type == NOT_VALID will do nothing.
! 3356: */
! 3357: void
! 3358: redraw_later(type)
! 3359: int type;
! 3360: {
! 3361: if (must_redraw < type)
! 3362: must_redraw = type;
! 3363: }