aboutsummaryrefslogtreecommitdiff
path: root/src/screen.c
diff options
context:
space:
mode:
authorEliseo Martínez <eliseomarmol@gmail.com>2014-05-12 02:25:17 +0200
committerEliseo Martínez <eliseomarmol@gmail.com>2014-05-15 20:46:01 +0200
commitda51dc9cf202772f60bd2da975dbef257bd9237c (patch)
tree5c16b93238a153f55634e9323077f30c8133970c /src/screen.c
parentffe61e5ba1721340ca51d56bae3ddaca415fb5bc (diff)
downloadrneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.gz
rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.bz2
rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.zip
Introduce nvim namespace: Move files.
Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library.
Diffstat (limited to 'src/screen.c')
-rw-r--r--src/screen.c8008
1 files changed, 0 insertions, 8008 deletions
diff --git a/src/screen.c b/src/screen.c
deleted file mode 100644
index aa021c032e..0000000000
--- a/src/screen.c
+++ /dev/null
@@ -1,8008 +0,0 @@
-/*
- * 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.
- * See README.txt for an overview of the Vim source code.
- */
-
-/*
- * screen.c: code for displaying on the screen
- *
- * Output to the screen (console, terminal emulator or GUI window) is minimized
- * by remembering what is already on the screen, and only updating the parts
- * that changed.
- *
- * ScreenLines[off] Contains a copy of the whole screen, as it is currently
- * displayed (excluding text written by external commands).
- * ScreenAttrs[off] Contains the associated attributes.
- * LineOffset[row] Contains the offset into ScreenLines*[] and ScreenAttrs[]
- * for each line.
- * LineWraps[row] Flag for each line whether it wraps to the next line.
- *
- * For double-byte characters, two consecutive bytes in ScreenLines[] can form
- * one character which occupies two display cells.
- * For UTF-8 a multi-byte character is converted to Unicode and stored in
- * ScreenLinesUC[]. ScreenLines[] contains the first byte only. For an ASCII
- * character without composing chars ScreenLinesUC[] will be 0 and
- * ScreenLinesC[][] is not used. When the character occupies two display
- * cells the next byte in ScreenLines[] is 0.
- * ScreenLinesC[][] contain up to 'maxcombine' composing characters
- * (drawn on top of the first character). There is 0 after the last one used.
- * ScreenLines2[] is only used for euc-jp to store the second byte if the
- * first byte is 0x8e (single-width character).
- *
- * The screen_*() functions write to the screen and handle updating
- * ScreenLines[].
- *
- * update_screen() is the function that updates all windows and status lines.
- * It is called form the main loop when must_redraw is non-zero. It may be
- * called from other places when an immediate screen update is needed.
- *
- * The part of the buffer that is displayed in a window is set with:
- * - w_topline (first buffer line in window)
- * - w_topfill (filler line above the first line)
- * - w_leftcol (leftmost window cell in window),
- * - w_skipcol (skipped window cells of first line)
- *
- * Commands that only move the cursor around in a window, do not need to take
- * action to update the display. The main loop will check if w_topline is
- * valid and update it (scroll the window) when needed.
- *
- * Commands that scroll a window change w_topline and must call
- * check_cursor() to move the cursor into the visible part of the window, and
- * call redraw_later(VALID) to have the window displayed by update_screen()
- * later.
- *
- * Commands that change text in the buffer must call changed_bytes() or
- * changed_lines() to mark the area that changed and will require updating
- * later. The main loop will call update_screen(), which will update each
- * window that shows the changed buffer. This assumes text above the change
- * can remain displayed as it is. Text after the change may need updating for
- * scrolling, folding and syntax highlighting.
- *
- * Commands that change how a window is displayed (e.g., setting 'list') or
- * invalidate the contents of a window in another way (e.g., change fold
- * settings), must call redraw_later(NOT_VALID) to have the whole window
- * redisplayed by update_screen() later.
- *
- * Commands that change how a buffer is displayed (e.g., setting 'tabstop')
- * must call redraw_curbuf_later(NOT_VALID) to have all the windows for the
- * buffer redisplayed by update_screen() later.
- *
- * Commands that change highlighting and possibly cause a scroll too must call
- * redraw_later(SOME_VALID) to update the whole window but still use scrolling
- * to avoid redrawing everything. But the length of displayed lines must not
- * change, use NOT_VALID then.
- *
- * Commands that move the window position must call redraw_later(NOT_VALID).
- * TODO: should minimize redrawing by scrolling when possible.
- *
- * Commands that change everything (e.g., resizing the screen) must call
- * redraw_all_later(NOT_VALID) or redraw_all_later(CLEAR).
- *
- * Things that are handled indirectly:
- * - When messages scroll the screen up, msg_scrolled will be set and
- * update_screen() called to redraw.
- */
-
-#include <string.h>
-
-#include "vim.h"
-#include "arabic.h"
-#include "screen.h"
-#include "buffer.h"
-#include "charset.h"
-#include "diff.h"
-#include "eval.h"
-#include "ex_cmds.h"
-#include "ex_cmds2.h"
-#include "ex_getln.h"
-#include "farsi.h"
-#include "fileio.h"
-#include "fold.h"
-#include "getchar.h"
-#include "main.h"
-#include "mbyte.h"
-#include "memline.h"
-#include "memory.h"
-#include "menu.h"
-#include "message.h"
-#include "misc1.h"
-#include "misc2.h"
-#include "garray.h"
-#include "move.h"
-#include "normal.h"
-#include "option.h"
-#include "path.h"
-#include "popupmnu.h"
-#include "quickfix.h"
-#include "regexp.h"
-#include "search.h"
-#include "spell.h"
-#include "syntax.h"
-#include "term.h"
-#include "ui.h"
-#include "undo.h"
-#include "version.h"
-#include "window.h"
-
-#define MB_FILLER_CHAR '<' /* character used when a double-width character
- * doesn't fit. */
-
-/*
- * 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 */
-
-static match_T search_hl; /* used for 'hlsearch' highlight matching */
-
-static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
-
-/*
- * Buffer for one screen line (characters and attributes).
- */
-static schar_T *current_ScreenLine;
-
-static void win_update(win_T *wp);
-static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow,
- hlf_T hl);
-static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo,
- linenr_T lnum,
- int row);
-static void fill_foldcolumn(char_u *p, win_T *wp, int closed,
- linenr_T lnum);
-static void copy_text_attr(int off, char_u *buf, int len, int attr);
-static int win_line(win_T *, linenr_T, int, int, int nochange);
-static int char_needs_redraw(int off_from, int off_to, int cols);
-static void screen_line(int row, int coloff, int endcol,
- int clear_width,
- int rlflag);
-# define SCREEN_LINE(r, o, e, c, rl) screen_line((r), (o), (e), (c), (rl))
-static void draw_vsep_win(win_T *wp, int row);
-static void redraw_custom_statusline(win_T *wp);
-#define SEARCH_HL_PRIORITY 0
-static void start_search_hl(void);
-static void end_search_hl(void);
-static void init_search_hl(win_T *wp);
-static void prepare_search_hl(win_T *wp, linenr_T lnum);
-static void next_search_hl(win_T *win, match_T *shl, linenr_T lnum,
- colnr_T mincol);
-static void screen_start_highlight(int attr);
-static void screen_char(unsigned off, int row, int col);
-static void screen_char_2(unsigned off, int row, int col);
-static void screenclear2(void);
-static void lineclear(unsigned off, int width);
-static void lineinvalid(unsigned off, int width);
-static void linecopy(int to, int from, win_T *wp);
-static void redraw_block(int row, int end, win_T *wp);
-static int win_do_lines(win_T *wp, int row, int line_count,
- int mayclear,
- int del);
-static void win_rest_invalid(win_T *wp);
-static void msg_pos_mode(void);
-static void draw_tabline(void);
-static int fillchar_status(int *attr, int is_curwin);
-static int fillchar_vsep(int *attr);
-static void win_redr_custom(win_T *wp, int draw_ruler);
-static void win_redr_ruler(win_T *wp, int always);
-
-//signs column
-static void update_prepare(void);
-static void update_finish(void);
-static int draw_signcolumn (win_T *wp);
-
-/* Ugly global: overrule attribute used by screen_char() */
-static int screen_char_attr = 0;
-
-/*
- * Redraw the current window later, with update_screen(type).
- * Set must_redraw only if not already set to a higher value.
- * e.g. if must_redraw is CLEAR, type NOT_VALID will do nothing.
- */
-void redraw_later(int type)
-{
- redraw_win_later(curwin, type);
-}
-
-void redraw_win_later(win_T *wp, int type)
-{
- if (wp->w_redr_type < type) {
- wp->w_redr_type = type;
- if (type >= NOT_VALID)
- wp->w_lines_valid = 0;
- if (must_redraw < type) /* must_redraw is the maximum of all windows */
- must_redraw = type;
- }
-}
-
-/*
- * Force a complete redraw later. Also resets the highlighting. To be used
- * after executing a shell command that messes up the screen.
- */
-void redraw_later_clear(void)
-{
- redraw_all_later(CLEAR);
- /* Use attributes that is very unlikely to appear in text. */
- screen_attr = HL_BOLD | HL_UNDERLINE | HL_INVERSE;
-}
-
-/*
- * Mark all windows to be redrawn later.
- */
-void redraw_all_later(int type)
-{
- win_T *wp;
-
- FOR_ALL_WINDOWS(wp)
- {
- redraw_win_later(wp, type);
- }
-}
-
-/*
- * Mark all windows that are editing the current buffer to be updated later.
- */
-void redraw_curbuf_later(int type)
-{
- redraw_buf_later(curbuf, type);
-}
-
-void redraw_buf_later(buf_T *buf, int type)
-{
- win_T *wp;
-
- FOR_ALL_WINDOWS(wp)
- {
- if (wp->w_buffer == buf)
- redraw_win_later(wp, type);
- }
-}
-
-/*
- * Redraw as soon as possible. When the command line is not scrolled redraw
- * right away and restore what was on the command line.
- * Return a code indicating what happened.
- */
-int redraw_asap(int type)
-{
- int rows;
- int r;
- int ret = 0;
- schar_T *screenline; /* copy from ScreenLines[] */
- sattr_T *screenattr; /* copy from ScreenAttrs[] */
- int i;
- u8char_T *screenlineUC = NULL; /* copy from ScreenLinesUC[] */
- u8char_T *screenlineC[MAX_MCO]; /* copy from ScreenLinesC[][] */
- schar_T *screenline2 = NULL; /* copy from ScreenLines2[] */
-
- redraw_later(type);
- if (msg_scrolled || (State != NORMAL && State != NORMAL_BUSY))
- return ret;
-
- /* Allocate space to save the text displayed in the command line area. */
- rows = Rows - cmdline_row;
- screenline = xmalloc((size_t)(rows * Columns * sizeof(schar_T)));
- screenattr = xmalloc((size_t)(rows * Columns * sizeof(sattr_T)));
-
- if (enc_utf8) {
- screenlineUC = xmalloc((size_t)(rows * Columns * sizeof(u8char_T)));
-
- for (i = 0; i < p_mco; ++i) {
- screenlineC[i] = xmalloc((size_t)(rows * Columns * sizeof(u8char_T)));
- }
- }
- if (enc_dbcs == DBCS_JPNU) {
- screenline2 = xmalloc((size_t)(rows * Columns * sizeof(schar_T)));
- }
-
- /* Save the text displayed in the command line area. */
- for (r = 0; r < rows; ++r) {
- memmove(screenline + r * Columns,
- ScreenLines + LineOffset[cmdline_row + r],
- (size_t)Columns * sizeof(schar_T));
- memmove(screenattr + r * Columns,
- ScreenAttrs + LineOffset[cmdline_row + r],
- (size_t)Columns * sizeof(sattr_T));
- if (enc_utf8) {
- memmove(screenlineUC + r * Columns,
- ScreenLinesUC + LineOffset[cmdline_row + r],
- (size_t)Columns * sizeof(u8char_T));
- for (i = 0; i < p_mco; ++i)
- memmove(screenlineC[i] + r * Columns,
- ScreenLinesC[r] + LineOffset[cmdline_row + r],
- (size_t)Columns * sizeof(u8char_T));
- }
- if (enc_dbcs == DBCS_JPNU)
- memmove(screenline2 + r * Columns,
- ScreenLines2 + LineOffset[cmdline_row + r],
- (size_t)Columns * sizeof(schar_T));
- }
-
- update_screen(0);
- ret = 3;
-
- if (must_redraw == 0) {
- int off = (int)(current_ScreenLine - ScreenLines);
-
- /* Restore the text displayed in the command line area. */
- for (r = 0; r < rows; ++r) {
- memmove(current_ScreenLine,
- screenline + r * Columns,
- (size_t)Columns * sizeof(schar_T));
- memmove(ScreenAttrs + off,
- screenattr + r * Columns,
- (size_t)Columns * sizeof(sattr_T));
- if (enc_utf8) {
- memmove(ScreenLinesUC + off,
- screenlineUC + r * Columns,
- (size_t)Columns * sizeof(u8char_T));
- for (i = 0; i < p_mco; ++i)
- memmove(ScreenLinesC[i] + off,
- screenlineC[i] + r * Columns,
- (size_t)Columns * sizeof(u8char_T));
- }
- if (enc_dbcs == DBCS_JPNU)
- memmove(ScreenLines2 + off,
- screenline2 + r * Columns,
- (size_t)Columns * sizeof(schar_T));
- SCREEN_LINE(cmdline_row + r, 0, Columns, Columns, FALSE);
- }
- ret = 4;
- }
-
- free(screenline);
- free(screenattr);
- if (enc_utf8) {
- free(screenlineUC);
- for (i = 0; i < p_mco; ++i)
- free(screenlineC[i]);
- }
- if (enc_dbcs == DBCS_JPNU)
- free(screenline2);
-
- /* Show the intro message when appropriate. */
- maybe_intro_message();
-
- setcursor();
-
- return ret;
-}
-
-/*
- * Changed something in the current window, at buffer line "lnum", that
- * requires that line and possibly other lines to be redrawn.
- * Used when entering/leaving Insert mode with the cursor on a folded line.
- * Used to remove the "$" from a change command.
- * Note that when also inserting/deleting lines w_redraw_top and w_redraw_bot
- * may become invalid and the whole window will have to be redrawn.
- */
-void
-redrawWinline (
- linenr_T lnum,
- int invalid /* window line height is invalid now */
-)
-{
- int i;
-
- if (curwin->w_redraw_top == 0 || curwin->w_redraw_top > lnum)
- curwin->w_redraw_top = lnum;
- if (curwin->w_redraw_bot == 0 || curwin->w_redraw_bot < lnum)
- curwin->w_redraw_bot = lnum;
- redraw_later(VALID);
-
- if (invalid) {
- /* A w_lines[] entry for this lnum has become invalid. */
- i = find_wl_entry(curwin, lnum);
- if (i >= 0)
- curwin->w_lines[i].wl_valid = FALSE;
- }
-}
-
-/*
- * update all windows that are editing the current buffer
- */
-void update_curbuf(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 ScreenLines[], and update curwin->w_botline.
- */
-void update_screen(int type)
-{
- win_T *wp;
- static int did_intro = FALSE;
- int did_one;
-
- /* Don't do anything if the screen structures are (not yet) valid. */
- if (!screen_valid(TRUE))
- return;
-
- if (must_redraw) {
- if (type < must_redraw) /* use maximal type */
- type = must_redraw;
-
- /* must_redraw is reset here, so that when we run into some weird
- * reason to redraw while busy redrawing (e.g., asynchronous
- * scrolling), or update_topline() in win_update() will cause a
- * scroll, the screen will be redrawn later or in win_update(). */
- must_redraw = 0;
- }
-
- /* Need to update w_lines[]. */
- if (curwin->w_lines_valid == 0 && type < NOT_VALID)
- type = NOT_VALID;
-
- /* Postpone the redrawing when it's not needed and when being called
- * recursively. */
- if (!redrawing() || updating_screen) {
- redraw_later(type); /* remember type for next time */
- must_redraw = type;
- if (type > INVERTED_ALL)
- curwin->w_lines_valid = 0; /* don't use w_lines[].wl_size now */
- return;
- }
-
- updating_screen = TRUE;
- ++display_tick; /* let syntax code know we're in a next round of
- * display updating */
-
- /*
- * 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, NULL) == FAIL)
- type = CLEAR;
- FOR_ALL_WINDOWS(wp)
- {
- if (W_WINROW(wp) < msg_scrolled) {
- if (W_WINROW(wp) + wp->w_height > msg_scrolled
- && wp->w_redr_type < REDRAW_TOP
- && wp->w_lines_valid > 0
- && wp->w_topline == wp->w_lines[0].wl_lnum) {
- wp->w_upd_rows = msg_scrolled - W_WINROW(wp);
- wp->w_redr_type = REDRAW_TOP;
- } else {
- wp->w_redr_type = NOT_VALID;
- if (W_WINROW(wp) + wp->w_height + W_STATUS_HEIGHT(wp)
- <= msg_scrolled)
- wp->w_redr_status = TRUE;
- }
- }
- }
- redraw_cmdline = TRUE;
- redraw_tabline = TRUE;
- }
- 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) /* going to clear cmdline (done below) */
- check_for_delay(FALSE);
-
- /* Force redraw when width of 'number' or 'relativenumber' column
- * changes. */
- if (curwin->w_redr_type < NOT_VALID
- && curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu)
- ? number_width(curwin) : 0))
- curwin->w_redr_type = NOT_VALID;
-
- /*
- * Only start redrawing if there is really something to do.
- */
- if (type == INVERTED)
- update_curswant();
- if (curwin->w_redr_type < type
- && !((type == VALID
- && curwin->w_lines[0].wl_valid
- && curwin->w_topfill == curwin->w_old_topfill
- && curwin->w_botfill == curwin->w_old_botfill
- && curwin->w_topline == curwin->w_lines[0].wl_lnum)
- || (type == INVERTED
- && VIsual_active
- && curwin->w_old_cursor_lnum == curwin->w_cursor.lnum
- && curwin->w_old_visual_mode == VIsual_mode
- && (curwin->w_valid & VALID_VIRTCOL)
- && curwin->w_old_curswant == curwin->w_curswant)
- ))
- curwin->w_redr_type = type;
-
- /* Redraw the tab pages line if needed. */
- if (redraw_tabline || type >= NOT_VALID)
- draw_tabline();
-
- /*
- * Correct stored syntax highlighting info for changes in each displayed
- * buffer. Each buffer must only be done once.
- */
- FOR_ALL_WINDOWS(wp)
- {
- if (wp->w_buffer->b_mod_set) {
- win_T *wwp;
-
- /* Check if we already did this buffer. */
- for (wwp = firstwin; wwp != wp; wwp = wwp->w_next)
- if (wwp->w_buffer == wp->w_buffer)
- break;
- if (
- wwp == wp &&
- syntax_present(wp))
- syn_stack_apply_changes(wp->w_buffer);
- }
- }
-
- /*
- * Go from top to bottom through the windows, redrawing the ones that need
- * it.
- */
- did_one = FALSE;
- search_hl.rm.regprog = NULL;
- FOR_ALL_WINDOWS(wp)
- {
- if (wp->w_redr_type != 0) {
- cursor_off();
- if (!did_one) {
- did_one = TRUE;
- start_search_hl();
- }
- win_update(wp);
- }
-
- /* redraw status line after the window to minimize cursor movement */
- if (wp->w_redr_status) {
- cursor_off();
- win_redr_status(wp);
- }
- }
- end_search_hl();
- /* May need to redraw the popup menu. */
- if (pum_visible())
- pum_redraw();
-
- /* Reset b_mod_set flags. Going through all windows is probably faster
- * than going through all buffers (there could be many buffers). */
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
- wp->w_buffer->b_mod_set = FALSE;
-
- updating_screen = FALSE;
-
- /* Clear or redraw the command line. Done last, because scrolling may
- * mess up the command line. */
- if (clear_cmdline || redraw_cmdline)
- showmode();
-
- /* May put up an introductory message when not editing a file */
- if (!did_intro)
- maybe_intro_message();
- did_intro = TRUE;
-
-}
-
-/*
- * Return TRUE if the cursor line in window "wp" may be concealed, according
- * to the 'concealcursor' option.
- */
-int conceal_cursor_line(win_T *wp)
-{
- int c;
-
- if (*wp->w_p_cocu == NUL)
- return FALSE;
- if (get_real_state() & VISUAL)
- c = 'v';
- else if (State & INSERT)
- c = 'i';
- else if (State & NORMAL)
- c = 'n';
- else if (State & CMDLINE)
- c = 'c';
- else
- return FALSE;
- return vim_strchr(wp->w_p_cocu, c) != NULL;
-}
-
-/*
- * Check if the cursor line needs to be redrawn because of 'concealcursor'.
- */
-void conceal_check_cursur_line(void)
-{
- if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin)) {
- need_cursor_line_redraw = TRUE;
- /* Need to recompute cursor column, e.g., when starting Visual mode
- * without concealing. */
- curs_columns(TRUE);
- }
-}
-
-void update_single_line(win_T *wp, linenr_T lnum)
-{
- int row;
- int j;
-
- if (lnum >= wp->w_topline && lnum < wp->w_botline
- && foldedCount(wp, lnum, &win_foldinfo) == 0) {
- row = 0;
- for (j = 0; j < wp->w_lines_valid; ++j) {
- if (lnum == wp->w_lines[j].wl_lnum) {
- screen_start(); /* not sure of screen cursor */
- init_search_hl(wp);
- start_search_hl();
- prepare_search_hl(wp, lnum);
- win_line(wp, lnum, row, row + wp->w_lines[j].wl_size, FALSE);
- end_search_hl();
- break;
- }
- row += wp->w_lines[j].wl_size;
- }
- }
- need_cursor_line_redraw = FALSE;
-}
-
-
-/*
- * Prepare for updating one or more windows.
- * Caller must check for "updating_screen" already set to avoid recursiveness.
- */
-static void update_prepare()
-{
- cursor_off();
- updating_screen = TRUE;
- start_search_hl();
-}
-
-/*
- * Finish updating one or more windows.
- */
-static void update_finish()
-{
- if (redraw_cmdline) {
- showmode();
- }
-
- end_search_hl();
- updating_screen = FALSE;
-}
-
-void update_debug_sign(buf_T *buf, linenr_T lnum)
-{
- win_T *wp;
- int doit = FALSE;
- win_foldinfo.fi_level = 0;
-
- /* update/delete a specific mark */
- FOR_ALL_WINDOWS(wp)
- {
- if (buf != NULL && lnum > 0) {
- if (wp->w_buffer == buf && lnum >= wp->w_topline
- && lnum < wp->w_botline)
- {
- if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum) {
- wp->w_redraw_top = lnum;
- }
- if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum) {
- wp->w_redraw_bot = lnum;
- }
- redraw_win_later(wp, VALID);
- }
- } else {
- redraw_win_later(wp, VALID);
- }
- if (wp->w_redr_type != 0) {
- doit = TRUE;
- }
- }
-
- /* Return when there is nothing to do, screen updating is already
- * happening (recursive call) or still starting up. */
- if (!doit || updating_screen || starting) {
- return;
- }
-
- /* update all windows that need updating */
- update_prepare();
-
- for (wp = firstwin; wp; wp = wp->w_next) {
- if (wp->w_redr_type != 0) {
- win_update(wp);
- }
- if (wp->w_redr_status) {
- win_redr_status(wp);
- }
- }
-
- update_finish();
-}
-
-/*
- * Return TRUE when window "wp" has a column to draw signs in.
- */
-static int draw_signcolumn(win_T *wp)
-{
- return (wp->w_buffer->b_signlist != NULL);
-}
-
-
-/*
- * Update a single window.
- *
- * This may cause the windows below it also to be redrawn (when clearing the
- * screen or scrolling lines).
- *
- * How the window is redrawn depends on wp->w_redr_type. Each type also
- * implies the one below it.
- * NOT_VALID redraw the whole window
- * SOME_VALID redraw the whole window but do scroll when possible
- * REDRAW_TOP redraw the top w_upd_rows window lines, otherwise like VALID
- * INVERTED redraw the changed part of the Visual area
- * INVERTED_ALL redraw the whole Visual area
- * VALID 1. scroll up/down to adjust for a changed w_topline
- * 2. update lines at the top when scrolled down
- * 3. redraw changed text:
- * - if wp->w_buffer->b_mod_set set, update lines between
- * b_mod_top and b_mod_bot.
- * - if wp->w_redraw_top non-zero, redraw lines between
- * wp->w_redraw_top and wp->w_redr_bot.
- * - continue redrawing when syntax status is invalid.
- * 4. if scrolled up, update lines at the bottom.
- * This results in three areas that may need updating:
- * top: from first row to top_end (when scrolled down)
- * mid: from mid_start to mid_end (update inversion or changed text)
- * bot: from bot_start to last row (when scrolled up)
- */
-static void win_update(win_T *wp)
-{
- buf_T *buf = wp->w_buffer;
- int type;
- int top_end = 0; /* Below last row of the top area that needs
- updating. 0 when no top area updating. */
- int mid_start = 999; /* first row of the mid area that needs
- updating. 999 when no mid area updating. */
- int mid_end = 0; /* Below last row of the mid area that needs
- updating. 0 when no mid area updating. */
- int bot_start = 999; /* first row of the bot area that needs
- updating. 999 when no bot area updating */
- int scrolled_down = FALSE; /* TRUE when scrolled down when
- w_topline got smaller a bit */
- matchitem_T *cur; /* points to the match list */
- int top_to_mod = FALSE; /* redraw above mod_top */
-
- int row; /* current window row to display */
- linenr_T lnum; /* current buffer lnum to display */
- int idx; /* current index in w_lines[] */
- int srow; /* starting row of the current line */
-
- int eof = FALSE; /* if TRUE, we hit the end of the file */
- int didline = FALSE; /* if TRUE, we finished the last line */
- int i;
- long j;
- static int recursive = FALSE; /* being called recursively */
- int old_botline = wp->w_botline;
- long fold_count;
- /* remember what happened to the previous line, to know if
- * check_visual_highlight() can be used */
-#define DID_NONE 1 /* didn't update a line */
-#define DID_LINE 2 /* updated a normal line */
-#define DID_FOLD 3 /* updated a folded line */
- int did_update = DID_NONE;
- linenr_T syntax_last_parsed = 0; /* last parsed text line */
- linenr_T mod_top = 0;
- linenr_T mod_bot = 0;
- int save_got_int;
-
- type = wp->w_redr_type;
-
- if (type == NOT_VALID) {
- wp->w_redr_status = TRUE;
- wp->w_lines_valid = 0;
- }
-
- /* Window is zero-height: nothing to draw. */
- if (wp->w_height == 0) {
- wp->w_redr_type = 0;
- return;
- }
-
- /* Window is zero-width: Only need to draw the separator. */
- if (wp->w_width == 0) {
- /* draw the vertical separator right of this window */
- draw_vsep_win(wp, 0);
- wp->w_redr_type = 0;
- return;
- }
-
- init_search_hl(wp);
-
- /* Force redraw when width of 'number' or 'relativenumber' column
- * changes. */
- i = (wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) : 0;
- if (wp->w_nrwidth != i) {
- type = NOT_VALID;
- wp->w_nrwidth = i;
- } else if (buf->b_mod_set && buf->b_mod_xlines != 0 && wp->w_redraw_top != 0) {
- /*
- * When there are both inserted/deleted lines and specific lines to be
- * redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw
- * everything (only happens when redrawing is off for while).
- */
- type = NOT_VALID;
- } else {
- /*
- * Set mod_top to the first line that needs displaying because of
- * changes. Set mod_bot to the first line after the changes.
- */
- mod_top = wp->w_redraw_top;
- if (wp->w_redraw_bot != 0)
- mod_bot = wp->w_redraw_bot + 1;
- else
- mod_bot = 0;
- wp->w_redraw_top = 0; /* reset for next time */
- wp->w_redraw_bot = 0;
- if (buf->b_mod_set) {
- if (mod_top == 0 || mod_top > buf->b_mod_top) {
- mod_top = buf->b_mod_top;
- /* Need to redraw lines above the change that may be included
- * in a pattern match. */
- if (syntax_present(wp)) {
- mod_top -= buf->b_s.b_syn_sync_linebreaks;
- if (mod_top < 1)
- mod_top = 1;
- }
- }
- if (mod_bot == 0 || mod_bot < buf->b_mod_bot)
- mod_bot = buf->b_mod_bot;
-
- /* When 'hlsearch' is on and using a multi-line search pattern, a
- * change in one line may make the Search highlighting in a
- * previous line invalid. Simple solution: redraw all visible
- * lines above the change.
- * Same for a match pattern.
- */
- if (search_hl.rm.regprog != NULL
- && re_multiline(search_hl.rm.regprog))
- top_to_mod = TRUE;
- else {
- cur = wp->w_match_head;
- while (cur != NULL) {
- if (cur->match.regprog != NULL
- && re_multiline(cur->match.regprog)) {
- top_to_mod = TRUE;
- break;
- }
- cur = cur->next;
- }
- }
- }
- if (mod_top != 0 && hasAnyFolding(wp)) {
- linenr_T lnumt, lnumb;
-
- /*
- * A change in a line can cause lines above it to become folded or
- * unfolded. Find the top most buffer line that may be affected.
- * If the line was previously folded and displayed, get the first
- * line of that fold. If the line is folded now, get the first
- * folded line. Use the minimum of these two.
- */
-
- /* Find last valid w_lines[] entry above mod_top. Set lnumt to
- * the line below it. If there is no valid entry, use w_topline.
- * Find the first valid w_lines[] entry below mod_bot. Set lnumb
- * to this line. If there is no valid entry, use MAXLNUM. */
- lnumt = wp->w_topline;
- lnumb = MAXLNUM;
- for (i = 0; i < wp->w_lines_valid; ++i)
- if (wp->w_lines[i].wl_valid) {
- if (wp->w_lines[i].wl_lastlnum < mod_top)
- lnumt = wp->w_lines[i].wl_lastlnum + 1;
- if (lnumb == MAXLNUM && wp->w_lines[i].wl_lnum >= mod_bot) {
- lnumb = wp->w_lines[i].wl_lnum;
- /* When there is a fold column it might need updating
- * in the next line ("J" just above an open fold). */
- if (wp->w_p_fdc > 0)
- ++lnumb;
- }
- }
-
- (void)hasFoldingWin(wp, mod_top, &mod_top, NULL, TRUE, NULL);
- if (mod_top > lnumt)
- mod_top = lnumt;
-
- /* Now do the same for the bottom line (one above mod_bot). */
- --mod_bot;
- (void)hasFoldingWin(wp, mod_bot, NULL, &mod_bot, TRUE, NULL);
- ++mod_bot;
- if (mod_bot < lnumb)
- mod_bot = lnumb;
- }
-
- /* When a change starts above w_topline and the end is below
- * w_topline, start redrawing at w_topline.
- * If the end of the change is above w_topline: do like no change was
- * made, but redraw the first line to find changes in syntax. */
- if (mod_top != 0 && mod_top < wp->w_topline) {
- if (mod_bot > wp->w_topline)
- mod_top = wp->w_topline;
- else if (syntax_present(wp))
- top_end = 1;
- }
-
- /* When line numbers are displayed need to redraw all lines below
- * inserted/deleted lines. */
- if (mod_top != 0 && buf->b_mod_xlines != 0 && wp->w_p_nu)
- mod_bot = MAXLNUM;
- }
-
- /*
- * When only displaying the lines at the top, set top_end. Used when
- * window has scrolled down for msg_scrolled.
- */
- if (type == REDRAW_TOP) {
- j = 0;
- for (i = 0; i < wp->w_lines_valid; ++i) {
- j += wp->w_lines[i].wl_size;
- if (j >= wp->w_upd_rows) {
- top_end = j;
- break;
- }
- }
- if (top_end == 0)
- /* not found (cannot happen?): redraw everything */
- type = NOT_VALID;
- else
- /* top area defined, the rest is VALID */
- type = VALID;
- }
-
- /* Trick: we want to avoid clearing the screen twice. screenclear() will
- * set "screen_cleared" to TRUE. The special value MAYBE (which is still
- * non-zero and thus not FALSE) will indicate that screenclear() was not
- * called. */
- if (screen_cleared)
- screen_cleared = MAYBE;
-
- /*
- * If there are no changes on the screen that require a complete redraw,
- * handle three cases:
- * 1: we are off the top of the screen by a few lines: scroll down
- * 2: wp->w_topline is below wp->w_lines[0].wl_lnum: may scroll up
- * 3: wp->w_topline is wp->w_lines[0].wl_lnum: find first entry in
- * w_lines[] that needs updating.
- */
- if ((type == VALID || type == SOME_VALID
- || type == INVERTED || type == INVERTED_ALL)
- && !wp->w_botfill && !wp->w_old_botfill
- ) {
- if (mod_top != 0 && wp->w_topline == mod_top) {
- /*
- * w_topline is the first changed line, the scrolling will be done
- * further down.
- */
- } else if (wp->w_lines[0].wl_valid
- && (wp->w_topline < wp->w_lines[0].wl_lnum
- || (wp->w_topline == wp->w_lines[0].wl_lnum
- && wp->w_topfill > wp->w_old_topfill)
- )) {
- /*
- * New topline is above old topline: May scroll down.
- */
- if (hasAnyFolding(wp)) {
- linenr_T ln;
-
- /* count the number of lines we are off, counting a sequence
- * of folded lines as one */
- j = 0;
- for (ln = wp->w_topline; ln < wp->w