screen.c
资源名称:vim53src.zip [点击查看]
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:133k
源码类别:
编辑器/阅读器
开发平台:
DOS
- /* vi:set ts=8 sts=4 sw=4:
- *
- * VIM - Vi IMproved by Bram Moolenaar
- *
- * Do ":help uganda" in Vim to read copying and usage conditions.
- * Do ":help credits" in Vim to see a list of people who contributed.
- */
- /*
- * screen.c: code for displaying on the screen
- */
- #include "vim.h"
- /*
- * The attributes that are actually active for writing to the screen.
- */
- static int screen_attr = 0;
- /*
- * Positioning the cursor is reduced by remembering the last position.
- * Mostly used by windgoto() and screen_char().
- */
- static int screen_cur_row, screen_cur_col; /* last known cursor position */
- #ifdef EXTRA_SEARCH
- /*
- * When highlighting matches for the last use search pattern:
- * - search_hl_prog points to the regexp program for it
- * - search_hl_attr contains the attributes to be used
- * - search_hl_ic is the value for "reg_ic" for this search
- */
- vim_regexp *search_hl_prog = NULL;
- int search_hl_attr;
- int search_hl_ic;
- #endif
- /*
- * Flags for w_valid.
- * These are suppose to be used only in screen.c. From other files, use the
- * functions that set or reset them.
- *
- * VALID_BOTLINE VALID_BOTLINE_AP
- * on on w_botline valid
- * off on w_botline approximated
- * off off w_botline not valid
- * on off not possible
- */
- #define VALID_WROW 0x01 /* w_wrow (window row) is valid */
- #define VALID_WCOL 0x02 /* w_wcol (window col) is valid */
- #define VALID_VIRTCOL 0x04 /* w_virtcol (file col) is valid */
- #define VALID_CHEIGHT 0x08 /* w_cline_height is valid */
- #define VALID_CROW 0x10 /* w_cline_row is valid */
- #define VALID_BOTLINE 0x20 /* w_botine and w_empty_rows are valid */
- #define VALID_BOTLINE_AP 0x40 /* w_botine is approximated */
- /*
- * Buffer for one screen line.
- */
- static char_u *current_LinePointer;
- static void win_update __ARGS((WIN *wp));
- static int win_line __ARGS((WIN *, linenr_t, int, int));
- #ifdef RIGHTLEFT
- static void screen_line __ARGS((int row, int endcol, int clear_rest, int rlflag));
- #define SCREEN_LINE(r, e, c, rl) screen_line((r), (e), (c), (rl))
- #else
- static void screen_line __ARGS((int row, int endcol, int clear_rest));
- #define SCREEN_LINE(r, e, c, rl) screen_line((r), (e), (c))
- #endif
- #ifdef EXTRA_SEARCH
- static void start_search_hl __ARGS((void));
- static void end_search_hl __ARGS((void));
- #endif
- static void screen_start_highlight __ARGS((int attr));
- static void comp_botline __ARGS((void));
- static void screen_char __ARGS((char_u *, int, int));
- static void screenclear2 __ARGS((void));
- static void lineclear __ARGS((char_u *p));
- static void check_cursor_moved __ARGS((WIN *wp));
- static void curs_rows __ARGS((int do_botline));
- static void validate_virtcol_win __ARGS((WIN *wp));
- static int screen_ins_lines __ARGS((int, int, int, int));
- static int highlight_status __ARGS((int *attr, int is_curwin));
- static void win_redr_ruler __ARGS((WIN *wp, int always));
- static void intro_message __ARGS((void));
- /*
- * update_screenline() - like update_screen() but only for cursor line
- *
- * Must only be called when something in the cursor line has changed (e.g.
- * character inserted or deleted).
- *
- * Check if the size of the cursor line has changed since the last screen
- * update. If it did change, lines below the cursor will move up or down and
- * we need to call the routine update_screen() to examine the entire screen.
- */
- void
- update_screenline()
- {
- int row;
- int old_cline_height;
- if (!screen_valid(TRUE))
- return;
- if (must_redraw) /* must redraw whole screen */
- {
- update_screen(must_redraw);
- return;
- }
- if (!redrawing())
- {
- redraw_later(NOT_VALID); /* remember to update later */
- return;
- }
- /*
- * If the screen has scrolled, or some lines after the cursor line have
- * been invalidated, call update_screen().
- */
- if (curwin->w_lsize_valid <= curwin->w_cursor.lnum - curwin->w_topline ||
- curwin->w_lsize_lnum[0] != curwin->w_topline)
- {
- update_screen(VALID_TO_CURSCHAR);
- return;
- }
- /*
- * Get the current height of the cursor line, as it is on the screen.
- * w_lsize[] must be used here, since w_cline_height might already have
- * been updated to the new height of the line in the buffer.
- */
- old_cline_height = curwin->w_lsize[curwin->w_cursor.lnum
- - curwin->w_topline];
- /*
- * Check if the cursor line is still at the same position. Be aware of
- * the cursor having moved around, w_cline_row may be invalid, use the
- * values from w_lsize[] by calling curs_rows().
- */
- check_cursor_moved(curwin);
- if (!(curwin->w_valid & VALID_CROW))
- curs_rows(FALSE);
- #ifdef EXTRA_SEARCH
- start_search_hl();
- #endif
- /*
- * w_virtcol needs to be valid.
- */
- validate_virtcol();
- cursor_off();
- row = win_line(curwin, curwin->w_cursor.lnum,
- curwin->w_cline_row, curwin->w_height);
- display_hint = HINT_NONE;
- #ifdef EXTRA_SEARCH
- end_search_hl();
- #endif
- if (row == curwin->w_height + 1) /* line too long for window */
- {
- if (curwin->w_topline < curwin->w_cursor.lnum)
- {
- /*
- * Window needs to be scrolled up to show the cursor line.
- * We know w_botline was valid before the change, so it should now
- * be one less. This removes the need to recompute w_botline in
- * update_topline().
- */
- --curwin->w_botline;
- curwin->w_valid |= VALID_BOTLINE_AP;
- }
- update_topline();
- update_screen(VALID_TO_CURSCHAR);
- }
- else if (!dollar_vcol)
- {
- /*
- * If the cursor line changed size, delete or insert screen lines and
- * redraw the rest of the window.
- */
- if (old_cline_height != curwin->w_cline_height)
- {
- if (curwin->w_cline_height < old_cline_height)
- win_del_lines(curwin, row,
- old_cline_height - curwin->w_cline_height, FALSE, TRUE);
- else
- win_ins_lines(curwin,
- curwin->w_cline_row + curwin->w_cline_height,
- curwin->w_cline_height - old_cline_height, FALSE, TRUE);
- update_screen(VALID_TO_CURSCHAR);
- }
- #ifdef SYNTAX_HL
- /*
- * If syntax lost its sync, have to redraw the following lines.
- */
- else if (syntax_present(curbuf) && row < cmdline_row
- && syntax_check_changed(curwin->w_cursor.lnum + 1))
- update_screen(VALID_TO_CURSCHAR);
- #endif
- else if (clear_cmdline || redraw_cmdline)
- showmode(); /* clear cmdline, show mode and ruler */
- }
- }
- /*
- * Redraw the current window later, with UpdateScreen(type).
- * Set must_redraw only of not already set to a higher value.
- * e.g. if must_redraw is CLEAR, type == NOT_VALID will do nothing.
- */
- void
- redraw_later(type)
- int type;
- {
- if (curwin->w_redr_type < type)
- curwin->w_redr_type = type;
- if (must_redraw < type) /* must_redraw is the maximum of all windows */
- must_redraw = type;
- }
- /*
- * Mark all windows to be redrawn later.
- */
- void
- redraw_all_later(type)
- int type;
- {
- WIN *wp;
- for (wp = firstwin; wp; wp = wp->w_next)
- if (wp->w_redr_type < type)
- wp->w_redr_type = type;
- redraw_later(type);
- }
- /*
- * Mark all windows that are editing the current buffer to be udpated later.
- */
- void
- redraw_curbuf_later(type)
- int type;
- {
- WIN *wp;
- for (wp = firstwin; wp; wp = wp->w_next)
- if (wp->w_redr_type < type && wp->w_buffer == curbuf)
- wp->w_redr_type = type;
- redraw_later(type);
- }
- /*
- * update all windows that are editing the current buffer
- */
- void
- update_curbuf(type)
- int type;
- {
- redraw_curbuf_later(type);
- update_screen(type);
- }
- /*
- * update_screen()
- *
- * Based on the current value of curwin->w_topline, transfer a screenfull
- * of stuff from Filemem to NextScreen, and update curwin->w_botline.
- */
- void
- update_screen(type)
- int type;
- {
- WIN *wp;
- static int did_intro = FALSE;
- if (!screen_valid(TRUE))
- return;
- dollar_vcol = 0;
- if (must_redraw)
- {
- if (type < must_redraw) /* use maximal type */
- type = must_redraw;
- must_redraw = 0;
- }
- if (curwin->w_lsize_valid == 0 && type < NOT_VALID)
- type = NOT_VALID;
- if (!redrawing())
- {
- redraw_later(type); /* remember type for next time */
- curwin->w_redr_type = type;
- curwin->w_lsize_valid = 0; /* don't use w_lsize[] now */
- return;
- }
- /*
- * if the screen was scrolled up when displaying a message, scroll it down
- */
- if (msg_scrolled)
- {
- clear_cmdline = TRUE;
- if (msg_scrolled > Rows - 5) /* clearing is faster */
- type = CLEAR;
- else if (type != CLEAR)
- {
- check_for_delay(FALSE);
- if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows) == FAIL)
- type = CLEAR;
- win_rest_invalid(firstwin); /* should do only first/last few */
- }
- msg_scrolled = 0;
- need_wait_return = FALSE;
- }
- /* reset cmdline_row now (may have been changed temporarily) */
- compute_cmdrow();
- /* Check for changed highlighting */
- if (need_highlight_changed)
- highlight_changed();
- if (type == CLEAR) /* first clear screen */
- {
- screenclear(); /* will reset clear_cmdline */
- type = NOT_VALID;
- }
- if (clear_cmdline) /* first clear cmdline */
- {
- check_for_delay(FALSE);
- msg_clr_cmdline(); /* will reset clear_cmdline */
- }
- /*
- * Only start redrawing if there is really something to do.
- */
- if (type == INVERTED)
- update_curswant();
- if (!((type == VALID && curwin->w_topline == curwin->w_lsize_lnum[0])
- || (type == INVERTED
- && curwin->w_old_cursor_lnum == curwin->w_cursor.lnum
- && (curwin->w_valid & VALID_VIRTCOL)
- && curwin->w_old_curswant == curwin->w_curswant)))
- {
- /*
- * go from top to bottom through the windows, redrawing the ones that
- * need it
- */
- curwin->w_redr_type = type;
- cursor_off();
- #ifdef EXTRA_SEARCH
- start_search_hl();
- #endif
- for (wp = firstwin; wp; wp = wp->w_next)
- {
- if (wp->w_redr_type)
- win_update(wp);
- if (wp->w_redr_status)
- win_redr_status(wp);
- }
- #ifdef EXTRA_SEARCH
- end_search_hl();
- #endif
- }
- if (redraw_cmdline)
- showmode();
- display_hint = HINT_NONE;
- /* May put up an introductory message when not editing a file */
- if (!did_intro && bufempty()
- && curbuf->b_fname == NULL
- && firstwin->w_next == NULL
- && vim_strchr(p_shm, SHM_INTRO) == NULL)
- intro_message();
- did_intro = TRUE;
- }
- #ifdef USE_GUI
- /*
- * Update a single window, its status line and maybe the command line msg.
- * Used for the GUI scrollbar.
- */
- void
- updateWindow(wp)
- WIN *wp;
- {
- cursor_off();
- #ifdef EXTRA_SEARCH
- start_search_hl();
- #endif
- win_update(wp);
- if (wp->w_redr_status || p_ru)
- win_redr_status(wp);
- if (redraw_cmdline)
- showmode();
- #ifdef EXTRA_SEARCH
- end_search_hl();
- #endif
- }
- #endif
- /*
- * Update all windows for the current buffer, except curwin.
- * Used after modifying text, to update the other windows on the same buffer.
- */
- void
- update_other_win()
- {
- WIN *wp;
- int first = TRUE;
- for (wp = firstwin; wp; wp = wp->w_next)
- if (wp != curwin && wp->w_buffer == curbuf)
- {
- if (first)
- {
- cursor_off();
- #ifdef EXTRA_SEARCH
- start_search_hl();
- #endif
- first = FALSE;
- }
- wp->w_redr_type = NOT_VALID;
- /*
- * don't do the actual redraw if wait_return() has just been
- * called and the user typed a ":"
- */
- if (!skip_redraw)
- win_update(wp);
- }
- #ifdef EXTRA_SEARCH
- end_search_hl();
- #endif
- }
- /*
- * Update a single window.
- *
- * This may cause the windows below it also to be redrawn.
- */
- static void
- win_update(wp)
- WIN *wp;
- {
- int type;
- int row;
- int endrow;
- linenr_t lnum;
- linenr_t lastline; /* only valid if endrow != Rows -1 */
- int done; /* if TRUE, we hit the end of the file */
- int didline; /* if TRUE, we finished the last line */
- int srow = 0; /* starting row of the current line */
- int idx;
- int i;
- long j;
- static int recursive = FALSE; /* being called recursively */
- int old_botline = wp->w_botline;
- int must_start_top = FALSE; /* update must start at top row */
- int must_end_bot = FALSE; /* update must end at bottom row */
- type = wp->w_redr_type;
- if (type == NOT_VALID)
- {
- wp->w_redr_status = TRUE;
- wp->w_lsize_valid = 0;
- }
- wp->w_redr_type = 0; /* reset it now, may be set again later */
- idx = 0;
- row = 0;
- lnum = wp->w_topline;
- validate_virtcol_win(wp);
- /* The number of rows shown is w_height. */
- /* The default last row is the status/command line. */
- endrow = wp->w_height;
- /*
- * If there are no changes on the screen, handle two special cases:
- * 1: we are off the top of the screen by a few lines: scroll down
- * 2: wp->w_topline is below wp->w_lsize_lnum[0]: may scroll up
- */
- if (type == VALID || type == VALID_TO_CURSCHAR ||
- type == VALID_BEF_CURSCHAR || type == INVERTED)
- {
- if (wp->w_topline < wp->w_lsize_lnum[0]) /* may scroll down */
- {
- j = wp->w_lsize_lnum[0] - wp->w_topline;
- if (j < wp->w_height - 2 /* not too far off */
- && (type != VALID_TO_CURSCHAR
- || wp->w_lsize_lnum[0] < curwin->w_cursor.lnum)
- && (type != VALID_BEF_CURSCHAR
- || wp->w_lsize_lnum[0] < curwin->w_cursor.lnum - 1))
- {
- lastline = wp->w_lsize_lnum[0] - 1;
- i = plines_m_win(wp, wp->w_topline, lastline);
- if (i < wp->w_height - 2) /* less than a screen off */
- {
- /*
- * Try to insert the correct number of lines.
- * If not the last window, delete the lines at the bottom.
- * win_ins_lines may fail.
- */
- if (i > 0)
- check_for_delay(FALSE);
- if (win_ins_lines(wp, 0, i, FALSE, wp == firstwin) == OK
- && wp->w_lsize_valid)
- {
- must_start_top = TRUE;
- endrow = i;
- /* If there are changes, must redraw the rest too */
- if (type == VALID_TO_CURSCHAR
- || type == VALID_BEF_CURSCHAR)
- wp->w_redr_type = type;
- if ((wp->w_lsize_valid += j) > wp->w_height)
- wp->w_lsize_valid = wp->w_height;
- for (idx = wp->w_lsize_valid; idx - j >= 0; idx--)
- {
- wp->w_lsize_lnum[idx] = wp->w_lsize_lnum[idx - j];
- wp->w_lsize[idx] = wp->w_lsize[idx - j];
- }
- idx = 0;
- }
- }
- else if (lastwin == firstwin)
- {
- screenclear(); /* far off: clearing the screen is faster */
- must_start_top = TRUE;
- must_end_bot = TRUE;
- }
- }
- else if (lastwin == firstwin)
- {
- screenclear(); /* far off: clearing the screen is faster */
- must_start_top = TRUE;
- must_end_bot = TRUE;
- }
- }
- else /* may scroll up */
- {
- j = -1;
- /* try to find wp->w_topline in wp->w_lsize_lnum[] */
- for (i = 0; i < wp->w_lsize_valid; i++)
- {
- if (wp->w_lsize_lnum[i] == wp->w_topline)
- {
- j = i;
- break;
- }
- row += wp->w_lsize[i];
- }
- if (j == -1) /* wp->w_topline is not in wp->w_lsize_lnum */
- {
- row = 0; /* start at the first row */
- if (lastwin == firstwin)
- {
- screenclear(); /* far off: clearing the screen is faster */
- must_start_top = TRUE;
- must_end_bot = TRUE;
- }
- }
- else
- {
- /*
- * Try to delete the correct number of lines.
- * wp->w_topline is at wp->w_lsize_lnum[i].
- */
- if (row)
- {
- check_for_delay(FALSE);
- if (win_del_lines(wp, 0, row, FALSE, wp == firstwin) == OK)
- must_end_bot = TRUE;
- }
- if ((row == 0 || must_end_bot) && wp->w_lsize_valid)
- {
- /*
- * Skip the lines (below the deleted lines) that are still
- * valid and don't need redrawing. Copy their info
- * upwards, to compensate for the deleted lines. Leave
- * row and lnum on the first line that needs redrawing.
- */
- srow = row;
- row = 0;
- for (;;)
- {
- if ((type == VALID_TO_CURSCHAR &&
- lnum == wp->w_cursor.lnum) ||
- (type == VALID_BEF_CURSCHAR &&
- lnum == wp->w_cursor.lnum - 1))
- {
- wp->w_lsize_valid = idx;
- break;
- }
- wp->w_lsize[idx] = wp->w_lsize[j];
- wp->w_lsize_lnum[idx] = lnum;
- if (row + srow + (int)wp->w_lsize[j] > wp->w_height)
- {
- wp->w_lsize_valid = idx + 1;
- break;
- }
- ++lnum;
- row += wp->w_lsize[idx++];
- if ((int)++j >= wp->w_lsize_valid)
- {
- wp->w_lsize_valid = idx;
- break;
- }
- }
- }
- else
- row = 0; /* update all lines */
- }
- }
- if (endrow == wp->w_height && idx == 0) /* no scrolling */
- wp->w_lsize_valid = 0;
- }
- done = didline = FALSE;
- if (VIsual_active) /* check if we are updating the inverted part */
- {
- linenr_t from, to;
- /*
- * Find the line numbers that need to be updated: The lines between
- * the old cursor position and the current cursor position. Also
- * check if the Visual position changed.
- */
- if (curwin->w_cursor.lnum < wp->w_old_cursor_lnum)
- {
- from = curwin->w_cursor.lnum;
- to = wp->w_old_cursor_lnum;
- }
- else
- {
- from = wp->w_old_cursor_lnum;
- to = curwin->w_cursor.lnum;
- }
- if (VIsual.lnum != wp->w_old_visual_lnum)
- {
- if (wp->w_old_visual_lnum < from)
- from = wp->w_old_visual_lnum;
- if (wp->w_old_visual_lnum > to)
- to = wp->w_old_visual_lnum;
- if (VIsual.lnum < from)
- from = VIsual.lnum;
- if (VIsual.lnum > to)
- to = VIsual.lnum;
- }
- /*
- * If in block mode and changed column or curwin->w_curswant: update
- * all lines.
- * First compute the actual start and end column.
- */
- if (VIsual_mode == Ctrl('V'))
- {
- colnr_t from1, from2, to1, to2;
- if (lt(VIsual, curwin->w_cursor))
- {
- getvcol(wp, &VIsual, &from1, NULL, &to1);
- getvcol(wp, &curwin->w_cursor, &from2, NULL, &to2);
- }
- else
- {
- getvcol(wp, &curwin->w_cursor, &from1, NULL, &to1);
- getvcol(wp, &VIsual, &from2, NULL, &to2);
- }
- if (from2 < from1)
- from1 = from2;
- if (to2 > to1)
- {
- if (*p_sel == 'e' && from2 - 1 >= to1)
- to1 = from2 - 1;
- else
- to1 = to2;
- }
- ++to1;
- if (curwin->w_curswant == MAXCOL)
- to1 = MAXCOL;
- if (from1 != wp->w_old_cursor_fcol || to1 != wp->w_old_cursor_lcol)
- {
- if (from > VIsual.lnum)
- from = VIsual.lnum;
- if (to < VIsual.lnum)
- to = VIsual.lnum;
- }
- wp->w_old_cursor_fcol = from1;
- wp->w_old_cursor_lcol = to1;
- }
- /*
- * There is no need to update lines above the top of the window.
- * If "must_start_top" is set, always start at w_topline.
- */
- if (from < wp->w_topline || must_start_top)
- from = wp->w_topline;
- /*
- * If we know the value of w_botline, use it to restrict the update to
- * the lines that are visible in the window.
- */
- if (wp->w_valid & VALID_BOTLINE)
- {
- if (from >= wp->w_botline)
- from = wp->w_botline - 1;
- if (to >= wp->w_botline)
- to = wp->w_botline - 1;
- }
- /*
- * Find the minimal part to be updated.
- *
- * If "lnum" is past "from" already, start at w_topline (can
- * happen when scrolling).
- */
- if (lnum > from)
- {
- lnum = wp->w_topline;
- idx = 0;
- row = 0;
- }
- while (lnum < from && idx < wp->w_lsize_valid) /* find start */
- {
- row += wp->w_lsize[idx++];
- ++lnum;
- }
- if (!must_end_bot && !must_start_top)
- {
- srow = row;
- for (j = idx; j < wp->w_lsize_valid; ++j) /* find end */
- {
- if (wp->w_lsize_lnum[j] == to + 1)
- {
- endrow = srow;
- break;
- }
- srow += wp->w_lsize[j];
- }
- }
- else
- {
- /* Redraw until the end, otherwise we could miss something when
- * doing CTRL-U. */
- endrow = wp->w_height;
- }
- wp->w_old_cursor_lnum = curwin->w_cursor.lnum;
- wp->w_old_visual_lnum = VIsual.lnum;
- wp->w_old_curswant = curwin->w_curswant;
- }
- else
- {
- wp->w_old_cursor_lnum = 0;
- wp->w_old_visual_lnum = 0;
- }
- /*
- * Update the screen rows from "row" to "endrow".
- * Start at line "lnum" which is at wp->w_lsize_lnum[idx].
- */
- for (;;)
- {
- if (row == endrow)
- {
- didline = TRUE;
- break;
- }
- if (lnum > wp->w_buffer->b_ml.ml_line_count)
- {
- done = TRUE; /* hit the end of the file */
- break;
- }
- srow = row;
- row = win_line(wp, lnum, srow, endrow);
- if (row > endrow) /* past end of screen */
- {
- /* we may need the size of that too long line later on */
- wp->w_lsize[idx] = plines_win(wp, lnum);
- wp->w_lsize_lnum[idx++] = lnum;
- break;
- }
- wp->w_lsize[idx] = row - srow;
- wp->w_lsize_lnum[idx++] = lnum;
- if (++lnum > wp->w_buffer->b_ml.ml_line_count)
- {
- done = TRUE;
- break;
- }
- }
- if (idx > wp->w_lsize_valid)
- wp->w_lsize_valid = idx;
- /* Do we have to do off the top of the screen processing ? */
- if (endrow != wp->w_height)
- {
- row = 0;
- for (idx = 0; idx < wp->w_lsize_valid && row < wp->w_height; idx++)
- row += wp->w_lsize[idx];
- if (row < wp->w_height)
- {
- done = TRUE;
- }
- else if (row > wp->w_height) /* Need to blank out the last line */
- {
- lnum = wp->w_lsize_lnum[idx - 1];
- srow = row - wp->w_lsize[idx - 1];
- didline = FALSE;
- }
- else
- {
- lnum = wp->w_lsize_lnum[idx - 1] + 1;
- didline = TRUE;
- }
- }
- wp->w_empty_rows = 0;
- /*
- * If we didn't hit the end of the file, and we didn't finish the last
- * line we were working on, then the line didn't fit.
- */
- if (!done && !didline)
- {
- if (lnum == wp->w_topline)
- {
- #if 0
- /*
- * Single line that does not fit!
- * Fill last line with '@' characters.
- */
- screen_fill(wp->w_winpos + wp->w_height - 1,
- wp->w_winpos + wp->w_height, 0, (int)Columns, '@', '@',
- hl_attr(HLF_AT));
- #endif
- wp->w_botline = lnum + 1;
- }
- else
- {
- /*
- * Clear the rest of the screen and mark the unused lines.
- */
- #ifdef RIGHTLEFT
- if (wp->w_p_rl)
- {
- screen_fill(wp->w_winpos + srow,
- wp->w_winpos + wp->w_height, 0, (int)Columns - 1,
- ' ', ' ', hl_attr(HLF_AT));
- screen_fill(wp->w_winpos + srow,
- wp->w_winpos + wp->w_height, (int)Columns - 1,
- (int)Columns, '@', ' ', hl_attr(HLF_AT));
- }
- else
- #endif
- screen_fill(wp->w_winpos + srow,
- wp->w_winpos + wp->w_height, 0, (int)Columns, '@', ' ',
- hl_attr(HLF_AT));
- wp->w_botline = lnum;
- wp->w_empty_rows = wp->w_height - srow;
- }
- }
- else
- {
- /* make sure the rest of the screen is blank */
- /* put '~'s on rows that aren't part of the file. */
- #ifdef RIGHTLEFT
- if (wp->w_p_rl)
- {
- screen_fill(wp->w_winpos + row,
- wp->w_winpos + wp->w_height, 0, (int)Columns - 1,
- ' ', ' ', hl_attr(HLF_AT));
- screen_fill(wp->w_winpos + row,
- wp->w_winpos + wp->w_height, (int)Columns - 1,
- (int)Columns, '~', ' ', hl_attr(HLF_AT));
- }
- else
- #endif
- screen_fill(wp->w_winpos + row,
- wp->w_winpos + wp->w_height, 0, (int)Columns, '~', ' ',
- hl_attr(HLF_AT));
- wp->w_empty_rows = wp->w_height - row;
- if (done) /* we hit the end of the file */
- wp->w_botline = wp->w_buffer->b_ml.ml_line_count + 1;
- else
- wp->w_botline = lnum;
- }
- /*
- * There is a trick with w_botline. If we invalidate it on each change
- * that might modify it, this will cause a lot of expensive calls to
- * plines() in update_topline() each time. Therefore the value of
- * w_botline is often approximated, and this value is used to compute the
- * value of w_topline. If the value of w_botline was wrong, check that
- * the value of w_topline is correct (cursor is on the visible part of the
- * text). If it's not, we need to redraw again. Mostly this just means
- * scrolling up a few lines, so it doesn't look too bad. Only do this for
- * the current window (where changes are relevant).
- */
- wp->w_valid |= VALID_BOTLINE;
- if (wp == curwin && wp->w_botline != old_botline && !recursive)
- {
- recursive = TRUE;
- update_topline(); /* may invalidate w_botline again */
- if (must_redraw)
- {
- win_update(wp);
- must_redraw = 0;
- }
- recursive = FALSE;
- }
- /* When insering lines at top, these have been redrawn now. Still need to
- * redraw other lines with changes */
- if (wp->w_redr_type && !recursive)
- {
- recursive = TRUE;
- win_update(wp);
- recursive = FALSE;
- }
- }
- /*
- * Display line "lnum" of window 'wp' on the screen.
- * Start at row "startrow", stop when "endrow" is reached.
- * wp->w_virtcol needs to be valid.
- *
- * Return the number of last row the line occupies.
- */
- static int
- win_line(wp, lnum, startrow, endrow)
- WIN *wp;
- linenr_t lnum;
- int startrow;
- int endrow;
- {
- char_u *screenp;
- int c = 0; /* init for GCC */
- int col; /* visual column on screen */
- long vcol; /* visual column for tabs */
- long v;
- #ifdef SYNTAX_HL
- int rcol; /* real column in the line */
- #endif
- int row; /* row in the window, excl w_winpos */
- int screen_row; /* row on the screen, incl w_winpos */
- char_u *ptr;
- #ifdef SYNTAX_HL
- char_u *line;
- #endif
- char_u extra[16]; /* "%ld" must fit in here */
- int n_extra = 0; /* number of extra chars */
- char_u *p_extra = NULL; /* string of extra chars */
- int c_extra = NUL; /* extra chars, all the same */
- char_u *showbreak = NULL;
- int n_attr = 0; /* chars with current attr */
- int n_skip = 0; /* nr of chars to skip for 'nowrap' */
- int n_number = 0; /* chars for 'number' */
- int fromcol, tocol; /* start/end of inverting */
- int noinvcur = FALSE; /* don't invert the cursor */
- FPOS *top, *bot;
- int area_highlighting; /* Visual or incsearch highlighting in
- this line */
- int attr; /* attributes for area highlighting */
- int area_attr = 0; /* attributes desired by highlighting */
- int search_attr = 0; /* attributes sesired by 'searchhl' */
- #ifdef SYNTAX_HL
- int syntax_attr = 0; /* attributes desired by syntax */
- int has_syntax = FALSE; /* this buffer has syntax highl. */
- #endif
- int extra_check; /* has syntax or linebreak */
- int char_attr; /* attributes for next character */
- int saved_attr1 = 0; /* char_attr saved for showbreak */
- int saved_attr2 = 0; /* char_attr saved for listtabstring */
- int extra_attr = 0;
- #ifdef EXTRA_SEARCH
- char_u *matchp;
- char_u *search_hl_start = NULL;
- char_u *search_hl_end = NULL;
- #endif
- #ifdef MULTI_BYTE
- int bCharacter = 0;
- char_u *line_head;
- #endif
- char_u *trail = NULL; /* start of trailing spaces */
- if (startrow > endrow) /* past the end already! */
- return startrow;
- row = startrow;
- screen_row = row + wp->w_winpos;
- attr = hl_attr(HLF_V);
- /*
- * To speed up the loop below, set extra_check when there is linebreak,
- * trailing white spcae and/or syntax processing to be done.
- */
- extra_check = wp->w_p_lbr;
- #ifdef SYNTAX_HL
- if (syntax_present(wp->w_buffer))
- {
- syntax_start(wp, lnum);
- has_syntax = TRUE;
- extra_check = TRUE;
- }
- #endif
- col = 0;
- vcol = 0;
- fromcol = -10;
- tocol = MAXCOL;
- area_highlighting = FALSE;
- char_attr = 0;
- /*
- * handle visual active in this window
- */
- if (VIsual_active && wp->w_buffer == curwin->w_buffer)
- {
- /* Visual is after curwin->w_cursor */
- if (ltoreq(curwin->w_cursor, VIsual))
- {
- top = &curwin->w_cursor;
- bot = &VIsual;
- }
- else /* Visual is before curwin->w_cursor */
- {
- top = &VIsual;
- bot = &curwin->w_cursor;
- }
- if (VIsual_mode == Ctrl('V')) /* block mode */
- {
- if (lnum >= top->lnum && lnum <= bot->lnum)
- {
- fromcol = wp->w_old_cursor_fcol;
- tocol = wp->w_old_cursor_lcol;
- }
- }
- else /* non-block mode */
- {
- if (lnum > top->lnum && lnum <= bot->lnum)
- fromcol = 0;
- else if (lnum == top->lnum)
- {
- if (VIsual_mode == 'V') /* linewise */
- fromcol = 0;
- else
- getvcol(wp, top, (colnr_t *)&fromcol, NULL, NULL);
- }
- if (VIsual_mode != 'V' && lnum == bot->lnum)
- {
- if (*p_sel == 'e' && bot->col == 0)
- {
- fromcol = -10;
- tocol = MAXCOL;
- }
- else
- {
- FPOS pos;
- pos = *bot;
- if (*p_sel == 'e')
- --pos.col;
- getvcol(wp, &pos, NULL, NULL, (colnr_t *)&tocol);
- ++tocol;
- }
- }
- }
- #ifndef MSDOS
- /* Check if the character under the cursor should not be inverted */
- if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin
- # ifdef USE_GUI
- && !gui.in_use
- # endif
- )
- noinvcur = TRUE;
- #endif
- /*
- * 'nowrap': adjust for when the inverted text is left of the screen,
- * and when the start of the inverted text is left of the screen.
- */
- if (!wp->w_p_wrap)
- {
- if (tocol <= (int)wp->w_leftcol)
- fromcol = 0;
- else if (fromcol >= 0 && fromcol < (int)wp->w_leftcol)
- fromcol = wp->w_leftcol;
- }
- /* if inverting in this line, can't optimize cursor positioning */
- if (fromcol >= 0)
- area_highlighting = TRUE;
- }
- /*
- * handle incremental search position highlighting
- */
- else if (highlight_match && wp == curwin && search_match_len)
- {
- if (lnum == curwin->w_cursor.lnum)
- {
- getvcol(curwin, &(curwin->w_cursor),
- (colnr_t *)&fromcol, NULL, NULL);
- curwin->w_cursor.col += search_match_len;
- getvcol(curwin, &(curwin->w_cursor),
- (colnr_t *)&tocol, NULL, NULL);
- curwin->w_cursor.col -= search_match_len;
- area_highlighting = TRUE;
- attr = hl_attr(HLF_I);
- if (fromcol == tocol) /* do at least one character */
- tocol = fromcol + 1; /* happens when past end of line */
- }
- }
- ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
- #ifdef EXTRA_SEARCH
- matchp = ptr;
- #endif
- #ifdef SYNTAX_HL
- line = ptr;
- rcol = 0;
- #endif
- #ifdef MULTI_BYTE
- line_head = ptr;
- #endif
- /* find start of trailing whitespace */
- if (wp->w_p_list && lcs_trail)
- {
- trail = ptr + STRLEN(ptr);
- while (trail > ptr && vim_iswhite(trail[-1]))
- --trail;
- extra_check = TRUE;
- }
- /*
- * 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the
- * first character to be displayed.
- */
- if (!wp->w_p_wrap || wp->w_skipcol)
- {
- if (wp->w_p_wrap)
- v = wp->w_skipcol;
- else
- v = wp->w_leftcol;
- while (vcol < v && *ptr)
- {
- c = win_chartabsize(wp, *ptr++, (colnr_t)vcol);
- vcol += c;
- #ifdef SYNTAX_HL
- ++rcol;
- #endif
- }
- /* handle a character that's not completely on the screen */
- if (vcol > v)
- {
- vcol -= c;
- --ptr;
- #ifdef SYNTAX_HL
- --rcol;
- #endif
- n_skip = v - vcol;
- }
- }
- #ifdef EXTRA_SEARCH
- /*
- * Handle highlighting the last used search pattern.
- */
- if (search_hl_prog != NULL)
- {
- reg_ic = search_hl_ic;
- for (;;)
- {
- if (vim_regexec(search_hl_prog, matchp, TRUE))
- {
- search_hl_start = search_hl_prog->startp[0];
- search_hl_end = search_hl_prog->endp[0];
- if (search_hl_end <= ptr) /* match before leftcol */
- {
- if (matchp == search_hl_end) /* empty match */
- ++matchp;
- else
- matchp = search_hl_end;
- continue;
- }
- if (search_hl_start < ptr) /* match at leftcol */
- search_attr = search_hl_attr;
- }
- else
- {
- search_hl_start = NULL;
- search_hl_end = NULL;
- }
- break;
- }
- if (search_hl_start != NULL)
- area_highlighting = TRUE;
- }
- #endif
- screenp = current_LinePointer;
- #ifdef RIGHTLEFT
- if (wp->w_p_rl)
- {
- col = Columns - 1; /* col follows screenp here */
- screenp += Columns - 1;
- }
- #endif
- /* add a line number if 'number' is set */
- if (wp->w_p_nu)
- {
- sprintf((char *)extra, "%7ld ", (long)lnum);
- #ifdef RIGHTLEFT
- if (wp->w_p_rl) /* reverse line numbers */
- {
- char_u *c1, *c2, t;
- for (c1 = extra, c2 = extra + STRLEN(extra) - 1; c1 < c2;
- c1++, c2--)
- {
- t = *c1;
- *c1 = *c2;
- *c2 = t;
- }
- }
- #endif
- n_number = 8;
- n_extra = 8;
- p_extra = extra;
- c_extra = NUL;
- vcol -= 8; /* so vcol is right when line number has been printed */
- n_attr = 8;
- extra_attr = hl_attr(HLF_N);
- saved_attr2 = 0;
- }
- /*
- * Repeat for the whole displayed line.
- */
- for (;;)
- {
- /* handle Visual or match highlighting in this line (but not when
- * still in the line number) */
- if (area_highlighting && n_number <= 0)
- {
- if (((vcol == fromcol
- && !(noinvcur
- && (colnr_t)vcol == wp->w_virtcol))
- || (noinvcur
- && (colnr_t)vcol == wp->w_virtcol + 1
- && vcol >= fromcol))
- && vcol < tocol)
- area_attr = attr; /* start highlighting */
- else if (area_attr
- && (vcol == tocol
- || (noinvcur
- && (colnr_t)vcol == wp->w_virtcol)))
- area_attr = 0; /* stop highlighting */
- #ifdef EXTRA_SEARCH
- /*
- * Check for start/end of search pattern match.
- * After end, check for start/end of next match.
- * When another match, have to check for start again.
- * Watch out for matching an empty string!
- */
- if (!n_extra)
- {
- for (;;)
- {
- if (ptr == search_hl_start)
- search_attr = search_hl_attr;
- if (ptr == search_hl_end)
- {
- search_attr = 0;
- reg_ic = search_hl_ic;
- if (vim_regexec(search_hl_prog, ptr, FALSE))
- {
- search_hl_start = search_hl_prog->startp[0];
- search_hl_end = search_hl_prog->endp[0];
- if (search_hl_start != search_hl_end)
- continue;
- ++search_hl_end; /* try again after empty match */
- }
- }
- break;
- }
- }
- #endif
- if (area_attr)
- char_attr = area_attr;
- #ifdef SYNTAX_HL
- else if (!search_attr && has_syntax)
- char_attr = syntax_attr;
- #endif
- else
- char_attr = search_attr;
- }
- /*
- * Get the next character to put on the screen.
- */
- /*
- * If 'showbreak' is set it contains the characters to put at the
- * start of each broken line.
- */
- if (*p_sbr != 0)
- {
- if (
- #ifdef RIGHTLEFT
- (wp->w_p_rl ? col == -1 : col == Columns)
- #else
- col == Columns
- #endif
- && (*ptr != NUL
- || (wp->w_p_list && lcs_eol != NUL)
- || (n_extra && (c_extra != NUL || *p_extra != NUL)))
- && vcol != 0)
- {
- showbreak = p_sbr;
- saved_attr1 = char_attr; /* save current attributes */
- }
- if (showbreak != NULL)
- {
- if (*showbreak == NUL)
- {
- showbreak = NULL;
- char_attr = saved_attr1; /* restore attributes */
- }
- else
- {
- c = *showbreak++;
- char_attr = hl_attr(HLF_AT);
- }
- }
- }
- if (showbreak == NULL)
- {
- /*
- * The 'extra' array contains the extra stuff that is inserted to
- * represent special characters (non-printable stuff). When all
- * characters are the same, c_extra is used.
- * For the '$' of the 'list' option, n_extra == 1, p_extra == "".
- */
- if (n_extra)
- {
- if (c_extra)
- c = c_extra;
- else
- c = *p_extra++;
- --n_extra;
- }
- else
- {
- c = *ptr++;
- #ifdef MULTI_BYTE
- bCharacter = 1;
- #endif
- if (extra_check)
- {
- #ifdef SYNTAX_HL
- if (has_syntax)
- {
- syntax_attr = get_syntax_attr(rcol++, line);
- if (!area_attr && !search_attr)
- char_attr = syntax_attr;
- }
- #endif
- /*
- * Found last space before word: check for line break
- */
- if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr)
- && !wp->w_p_list)
- {
- n_extra = win_lbr_chartabsize(wp, ptr - 1,
- (colnr_t)vcol, NULL) - 1;
- c_extra = ' ';
- if (vim_iswhite(c))
- c = ' ';
- }
- if (trail != NULL && ptr > trail && c == ' ')
- {
- c = lcs_trail;
- if (!area_attr && !search_attr)
- {
- n_attr = 1;
- extra_attr = hl_attr(HLF_AT);
- saved_attr2 = char_attr; /* save current attr */
- }
- }
- }
- /*
- * Handling of non-printable characters.
- */
- if (!safe_vim_isprintc(c))
- {
- /*
- * when getting a character from the file, we may have to
- * turn it into something else on the way to putting it
- * into 'NextScreen'.
- */
- if (c == TAB && (!wp->w_p_list || lcs_tab1))
- {
- /* tab amount depends on current column */
- n_extra = (int)wp->w_buffer->b_p_ts -
- vcol % (int)wp->w_buffer->b_p_ts - 1;
- if (wp->w_p_list)
- {
- c = lcs_tab1;
- c_extra = lcs_tab2;
- if (!area_attr && !search_attr)
- {
- n_attr = n_extra + 1;
- extra_attr = hl_attr(HLF_AT);
- saved_attr2 = char_attr; /* save current attr */
- }
- }
- else
- {
- c_extra = ' ';
- c = ' ';
- }
- }
- else if (c == NUL && wp->w_p_list && lcs_eol != NUL)
- {
- p_extra = (char_u *)"";
- n_extra = 1;
- c_extra = NUL;
- c = lcs_eol;
- --ptr; /* put it back at the NUL */
- char_attr = hl_attr(HLF_AT);
- }
- else if (c != NUL)
- {
- p_extra = transchar(c);
- n_extra = charsize(c) - 1;
- c_extra = NUL;
- c = *p_extra++;
- }
- }
- }
- if (n_attr)
- char_attr = extra_attr;
- }
- /*
- * At end of the text line.
- */
- if (c == NUL)
- {
- if (area_attr)
- {
- /* invert at least one char, used for Visual and empty line or
- * highlight match at end of line. If it's beyond the last
- * char on the screen, just overwrite that one (tricky!) */
- if (vcol == fromcol)
- {
- #ifdef RIGHTLEFT
- if (wp->w_p_rl)
- {
- if (col < 0)
- {
- ++screenp;
- ++col;
- }
- }
- else
- #endif
- {
- if (col >= Columns)
- {
- --screenp;
- --col;
- }
- }
- *screenp = ' ';
- *(screenp + Columns) = char_attr;
- #ifdef RIGHTLEFT
- if (wp->w_p_rl)
- --col;
- else
- #endif
- ++col;
- }
- }
- SCREEN_LINE(screen_row, col, TRUE, wp->w_p_rl);
- row++;
- /*
- * Update w_cline_height if we can (saves a call to plines()
- * later).
- */
- if (wp == curwin && lnum == curwin->w_cursor.lnum)
- {
- curwin->w_cline_row = startrow;
- curwin->w_cline_height = row - startrow;
- curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
- }
- break;
- }
- /*
- * At end of screen line.
- */
- if (
- #ifdef RIGHTLEFT
- wp->w_p_rl ? (col < 0) :
- #endif
- (col >= Columns))
- {
- SCREEN_LINE(screen_row, col, TRUE, wp->w_p_rl);
- col = 0;
- ++row;
- ++screen_row;
- if (!wp->w_p_wrap)
- break;
- if (row == endrow) /* line got too long for screen */
- {
- ++row;
- break;
- }
- /*
- * Special trick to make copy/paste of wrapped lines work with
- * xterm/screen: write an extra character beyond the end of the
- * line. This will work with all terminal types (regardless of the
- * xn,am settings).
- * Only do this on a fast tty.
- * Only do this if the cursor is on the current line (something
- * has been written in it).
- * Don't do this for the GUI.
- */
- if (p_tf && screen_cur_row == screen_row - 1
- #ifdef USE_GUI
- && !gui.in_use
- #endif
- )
- {
- if (screen_cur_col != Columns)
- screen_char(LinePointers[screen_row - 1] + Columns - 1,
- screen_row - 1, (int)(Columns - 1));
- screen_char(LinePointers[screen_row],
- screen_row - 1, (int)Columns);
- screen_start(); /* don't know where cursor is now */
- }
- screenp = current_LinePointer;
- #ifdef RIGHTLEFT
- if (wp->w_p_rl)
- {
- col = Columns - 1; /* col is not used if breaking! */
- screenp += Columns - 1;
- }
- #endif
- }
- /* line continues beyond line end */
- if (lcs_ext
- && !wp->w_p_wrap
- && (
- #ifdef RIGHTLEFT
- wp->w_p_rl ? col == 0 :
- #endif
- col == Columns - 1)
- && (*ptr != NUL
- || (wp->w_p_list && lcs_eol != NUL)
- || (n_extra && (c_extra != NUL || *p_extra != NUL))))
- {
- c = lcs_ext;
- char_attr = hl_attr(HLF_AT);
- }
- #ifdef MULTI_BYTE
- if (is_dbcs)
- {
- /* if an mult-byte character splits by line edge,
- lead or trail byte is substituted by '~' */
- if (col == 0 && bCharacter)
- {
- if (IsTrailByte(line_head, ptr-1))
- c = '~';
- }
- if (
- # ifdef RIGHTLEFT
- wp->w_p_rl ? (col <= 0) :
- # endif
- (col >= Columns-1))
- {
- if (bCharacter && IsLeadByte(*(ptr-1))
- && IsTrailByte(line_head, ptr))
- c = '~';
- }
- bCharacter = 0;
- }
- #endif
- /* Skip characters that are left of the screen for 'nowrap' */
- if (n_number > 0 || n_skip <= 0)
- {
- /*
- * Store the character.
- */
- *screenp = c;
- *(screenp + Columns) = char_attr;
- #ifdef RIGHTLEFT
- if (wp->w_p_rl)
- {
- --screenp;
- --col;
- }
- else
- #endif
- {
- ++screenp;
- ++col;
- }
- --n_number;
- }
- else
- --n_skip;
- ++vcol;
- /* restore attributes after last 'listchars' or 'number' char */
- if (n_attr && --n_attr == 0)
- char_attr = saved_attr2;
- /* When still displaying '$' of change command, stop at cursor */
- if (dollar_vcol && wp == curwin && vcol >= (long)wp->w_virtcol)
- {
- SCREEN_LINE(screen_row, col, FALSE, wp->w_p_rl);
- break;
- }
- }
- return (row);
- }
- /*
- * Move one "cooked" screen line to the screen, but only the characters that
- * have actually changed. Handle insert/delete character.
- * 'endcol' gives the columns where valid characters are.
- * 'clear_rest' is TRUE if the rest of the line needs to be cleared.
- * 'rlflag' is TRUE in a rightleft window:
- * When TRUE and clear_rest, line is cleared in 0 -- endcol.
- * When FALSE and clear_rest, line is cleared in endcol -- Columns-1.
- */
- static void
- screen_line(row, endcol, clear_rest
- #ifdef RIGHTLEFT
- , rlflag
- #endif
- )
- int row;
- int endcol;
- int clear_rest;
- #ifdef RIGHTLEFT
- int rlflag;
- #endif
- {
- char_u *screenp_from;
- char_u *screenp_to;
- int col = 0;
- int force = FALSE; /* force update rest of the line */
- screenp_from = current_LinePointer;
- screenp_to = LinePointers[row];
- #ifdef RIGHTLEFT
- if (rlflag)
- {
- if (clear_rest)
- {
- while (col <= endcol && *screenp_to == ' '
- && *(screenp_to + Columns) == 0)
- {
- ++screenp_to;
- ++col;
- }
- if (col <= endcol)
- screen_fill(row, row + 1, col, endcol + 1, ' ', ' ', 0);
- }
- col = endcol + 1;
- screenp_to = LinePointers[row] + col;
- screenp_from += col;
- }
- while (rlflag ? (col < Columns) : (col < endcol))
- #else
- while (col < endcol)
- #endif
- {
- if (
- #if defined(MULTI_BYTE)
- /* a multi byte ch. is misprinted when right/left scrolling. */
- is_dbcs ||
- #endif
- force
- || *screenp_from != *screenp_to
- || *(screenp_from + Columns) != *(screenp_to + Columns)
- )
- {
- /*
- * Special handling when 'xs' termcap flag set (hpterm):
- * Attributes for characters are stored at the position where the
- * cursor is when writing the highlighting code. The
- * start-highlighting code must be written with the cursor on the
- * first highlighted character. The stop-highlighting code must
- * be written with the cursor just after the last highlighted
- * character.
- * Overwriting a character doesn't remove it's highlighting. Need
- * to clear the rest of the line, and force redrawing it
- * completely.
- */
- if ( p_wiv
- && !force
- #ifdef USE_GUI
- && !gui.in_use
- #endif
- && *(screenp_to + Columns)
- && *(screenp_from + Columns) != *(screenp_to + Columns))
- {
- /*
- * Need to remove highlighting attributes here.
- */
- windgoto(row, col);
- out_str(T_CE); /* clear rest of this screen line */
- screen_start(); /* don't know where cursor is now */
- force = TRUE; /* force redraw of rest of the line */
- /*
- * If the previous character was highlighted, need to stop
- * highlighting at this character.
- */
- if (col > 0 && *(screenp_to + Columns - 1))
- {
- screen_attr = *(screenp_to + Columns - 1);
- term_windgoto(row, col);
- screen_stop_highlight();
- }
- else
- screen_attr = 0; /* highlighting has stopped */
- }
- *screenp_to = *screenp_from;
- #if defined(USE_GUI) || defined(UNIX)
- /* The bold trick makes a single row of pixels appear in the next
- * character. When a bold character is removed, the next
- * character should be redrawn too. This happens for our own GUI
- * and for some xterms. */
- if (
- # ifdef USE_GUI
- gui.in_use
- # endif
- # if defined(USE_GUI) && defined(UNIX)
- ||
- # endif
- # ifdef UNIX
- vim_is_xterm(T_NAME)
- # endif
- )
- {
- int n;
- n = *(screenp_to + Columns);
- if (col + 1 < Columns && (n > HL_ALL || (n & HL_BOLD)))
- *(screenp_to + 1) = 0;
- }
- #endif
- *(screenp_to + Columns) = *(screenp_from + Columns);
- screen_char(screenp_to, row, col);
- }
- else if ( p_wiv
- #ifdef USE_GUI
- && !gui.in_use
- #endif
- && col > 0)
- {
- if (*(screenp_to + Columns) == *(screenp_to + Columns - 1))
- {
- /*
- * Don't output stop-highlight when moving the cursor, it will
- * stop the highlighting when it should continue.
- */
- screen_attr = 0;
- }
- else if (screen_attr)
- {
- screen_stop_highlight();
- }
- }
- ++screenp_to;
- ++screenp_from;
- ++col;
- }
- if (clear_rest
- #ifdef RIGHTLEFT
- && !rlflag
- #endif
- )
- {
- /* blank out the rest of the line */
- while (col < Columns && *screenp_to == ' ' &&
- *(screenp_to + Columns) == 0)
- {
- ++screenp_to;
- ++col;
- }
- if (col < Columns)
- screen_fill(row, row + 1, col, (int)Columns, ' ', ' ', 0);
- }
- }
- /*
- * mark all status lines for redraw; used after first :cd
- */
- void
- status_redraw_all()
- {
- WIN *wp;
- for (wp = firstwin; wp; wp = wp->w_next)
- if (wp->w_status_height)
- {
- wp->w_redr_status = TRUE;
- redraw_later(NOT_VALID);
- }
- }
- /*
- * Redraw all status lines that need to be redrawn.
- */
- void
- redraw_statuslines()
- {
- WIN *wp;
- for (wp = firstwin; wp; wp = wp->w_next)
- if (wp->w_redr_status)
- win_redr_status(wp);
- }
- /*
- * Redraw the status line of window wp.
- *
- * If inversion is possible we use it. Else '=' characters are used.
- */
- void
- win_redr_status(wp)
- WIN *wp;
- {
- int row;
- char_u *p;
- int len;
- int fillchar;
- int attr;
- if (wp->w_status_height) /* if there is a status line */
- {
- fillchar = highlight_status(&attr, wp == curwin);
- p = wp->w_buffer->b_fname;
- if (p == NULL)
- STRCPY(NameBuff, "[No File]");
- else
- {
- home_replace(wp->w_buffer, p, NameBuff, MAXPATHL, TRUE);
- trans_characters(NameBuff, MAXPATHL);
- }
- p = NameBuff;
- len = STRLEN(p);
- if (wp->w_buffer->b_help || buf_changed(wp->w_buffer) ||
- wp->w_buffer->b_p_ro)
- *(p + len++) = ' ';
- if (wp->w_buffer->b_help)
- {
- STRCPY(p + len, "[help]");
- len += 6;
- }
- if (buf_changed(wp->w_buffer))
- {
- STRCPY(p + len, "[+]");
- len += 3;
- }
- if (wp->w_buffer->b_p_ro)
- {
- STRCPY(p + len, "[RO]");
- len += 4;
- }
- if (len > ru_col - 1)
- {
- p += len - (ru_col - 1);
- *p = '<';
- len = ru_col - 1;
- }
- row = wp->w_winpos + wp->w_height;
- screen_puts(p, row, 0, attr);
- screen_fill(row, row + 1, len, ru_col, fillchar, fillchar, attr);
- win_redr_ruler(wp, TRUE);
- }
- else /* no status line, can only be last window */
- redraw_cmdline = TRUE;
- wp->w_redr_status = FALSE;
- }
- /*
- * Output a single character directly to the screen and update NextScreen.
- */
- void
- screen_putchar(c, row, col, attr)
- int c;
- int row, col;
- int attr;
- {
- char_u buf[2];
- buf[0] = c;
- buf[1] = NUL;
- screen_puts(buf, row, col, attr);
- }
- /*
- * Put string '*text' on the screen at position 'row' and 'col', with
- * attributes 'attr', and update NextScreen.
- * Note: only outputs within one row, message is truncated at screen boundary!
- * Note: if NextScreen, row and/or col is invalid, nothing is done.
- */
- void
- screen_puts(text, row, col, attr)
- char_u *text;
- int row;
- int col;
- int attr;
- {
- char_u *screenp;
- if (NextScreen != NULL && row < Rows) /* safety check */
- {
- screenp = LinePointers[row] + col;
- while (*text && col < Columns)
- {
- if (*screenp != *text || *(screenp + Columns) != attr ||
- exmode_active)
- {
- *screenp = *text;
- *(screenp + Columns) = attr;
- screen_char(screenp, row, col);
- }
- ++screenp;
- ++col;
- ++text;
- }
- }
- }
- #ifdef EXTRA_SEARCH
- /*
- * Prepare for 'searchhl' highlighting.
- */
- static void
- start_search_hl()
- {
- if (p_hls && !no_hlsearch)
- {
- search_hl_prog = last_pat_prog();
- search_hl_attr = hl_attr(HLF_L);
- search_hl_ic = reg_ic;
- }
- }
- /*
- * Clean up for 'searchhl' highlighting.
- */
- static void
- end_search_hl()
- {
- if (search_hl_prog != NULL)
- {
- vim_free(search_hl_prog);
- search_hl_prog = NULL;
- }
- }
- #endif
- /*
- * Reset cursor position. Use whenever cursor was moved because of outputting
- * something directly to the screen (shell commands) or a terminal control
- * code.
- */
- void
- screen_start()
- {
- screen_cur_row = screen_cur_col = 9999;
- }
- /*
- * Note that the cursor has gone down to the next line, column 0.
- * Used for Ex mode.
- */
- void
- screen_down()
- {
- screen_cur_col = 0;
- if (screen_cur_row < Rows - 1)
- ++screen_cur_row;
- }
- static void
- screen_start_highlight(attr)
- int attr;
- {
- struct attr_entry *aep = NULL;
- screen_attr = attr;
- if (full_screen
- #ifdef WIN32
- && termcap_active
- #endif
- )
- {
- #ifdef USE_GUI
- if (gui.in_use)
- {
- char buf[20];
- sprintf(buf, "