xref: /vim-8.2.3635/src/drawscreen.c (revision 9b0b844d)
17528d1f6SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
27528d1f6SBram Moolenaar  *
37528d1f6SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
47528d1f6SBram Moolenaar  *
57528d1f6SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
67528d1f6SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
77528d1f6SBram Moolenaar  * See README.txt for an overview of the Vim source code.
87528d1f6SBram Moolenaar  */
97528d1f6SBram Moolenaar 
107528d1f6SBram Moolenaar /*
117528d1f6SBram Moolenaar  * drawscreen.c: Code for updating all the windows on the screen.
127528d1f6SBram Moolenaar  * This is the top level, drawline.c is the middle and screen.c the lower
137528d1f6SBram Moolenaar  * level.
147528d1f6SBram Moolenaar  *
157528d1f6SBram Moolenaar  * update_screen() is the function that updates all windows and status lines.
167528d1f6SBram Moolenaar  * It is called form the main loop when must_redraw is non-zero.  It may be
177528d1f6SBram Moolenaar  * called from other places when an immediate screen update is needed.
187528d1f6SBram Moolenaar  *
197528d1f6SBram Moolenaar  * The part of the buffer that is displayed in a window is set with:
207528d1f6SBram Moolenaar  * - w_topline (first buffer line in window)
217528d1f6SBram Moolenaar  * - w_topfill (filler lines above the first line)
227528d1f6SBram Moolenaar  * - w_leftcol (leftmost window cell in window),
237528d1f6SBram Moolenaar  * - w_skipcol (skipped window cells of first line)
247528d1f6SBram Moolenaar  *
257528d1f6SBram Moolenaar  * Commands that only move the cursor around in a window, do not need to take
267528d1f6SBram Moolenaar  * action to update the display.  The main loop will check if w_topline is
277528d1f6SBram Moolenaar  * valid and update it (scroll the window) when needed.
287528d1f6SBram Moolenaar  *
297528d1f6SBram Moolenaar  * Commands that scroll a window change w_topline and must call
307528d1f6SBram Moolenaar  * check_cursor() to move the cursor into the visible part of the window, and
317528d1f6SBram Moolenaar  * call redraw_later(VALID) to have the window displayed by update_screen()
327528d1f6SBram Moolenaar  * later.
337528d1f6SBram Moolenaar  *
347528d1f6SBram Moolenaar  * Commands that change text in the buffer must call changed_bytes() or
357528d1f6SBram Moolenaar  * changed_lines() to mark the area that changed and will require updating
367528d1f6SBram Moolenaar  * later.  The main loop will call update_screen(), which will update each
377528d1f6SBram Moolenaar  * window that shows the changed buffer.  This assumes text above the change
387528d1f6SBram Moolenaar  * can remain displayed as it is.  Text after the change may need updating for
397528d1f6SBram Moolenaar  * scrolling, folding and syntax highlighting.
407528d1f6SBram Moolenaar  *
417528d1f6SBram Moolenaar  * Commands that change how a window is displayed (e.g., setting 'list') or
427528d1f6SBram Moolenaar  * invalidate the contents of a window in another way (e.g., change fold
437528d1f6SBram Moolenaar  * settings), must call redraw_later(NOT_VALID) to have the whole window
447528d1f6SBram Moolenaar  * redisplayed by update_screen() later.
457528d1f6SBram Moolenaar  *
467528d1f6SBram Moolenaar  * Commands that change how a buffer is displayed (e.g., setting 'tabstop')
477528d1f6SBram Moolenaar  * must call redraw_curbuf_later(NOT_VALID) to have all the windows for the
487528d1f6SBram Moolenaar  * buffer redisplayed by update_screen() later.
497528d1f6SBram Moolenaar  *
507528d1f6SBram Moolenaar  * Commands that change highlighting and possibly cause a scroll too must call
517528d1f6SBram Moolenaar  * redraw_later(SOME_VALID) to update the whole window but still use scrolling
527528d1f6SBram Moolenaar  * to avoid redrawing everything.  But the length of displayed lines must not
537528d1f6SBram Moolenaar  * change, use NOT_VALID then.
547528d1f6SBram Moolenaar  *
557528d1f6SBram Moolenaar  * Commands that move the window position must call redraw_later(NOT_VALID).
567528d1f6SBram Moolenaar  * TODO: should minimize redrawing by scrolling when possible.
577528d1f6SBram Moolenaar  *
587528d1f6SBram Moolenaar  * Commands that change everything (e.g., resizing the screen) must call
597528d1f6SBram Moolenaar  * redraw_all_later(NOT_VALID) or redraw_all_later(CLEAR).
607528d1f6SBram Moolenaar  *
617528d1f6SBram Moolenaar  * Things that are handled indirectly:
627528d1f6SBram Moolenaar  * - When messages scroll the screen up, msg_scrolled will be set and
637528d1f6SBram Moolenaar  *   update_screen() called to redraw.
647528d1f6SBram Moolenaar  */
657528d1f6SBram Moolenaar 
667528d1f6SBram Moolenaar #include "vim.h"
677528d1f6SBram Moolenaar 
687528d1f6SBram Moolenaar static void win_update(win_T *wp);
697528d1f6SBram Moolenaar #ifdef FEAT_STL_OPT
707528d1f6SBram Moolenaar static void redraw_custom_statusline(win_T *wp);
717528d1f6SBram Moolenaar #endif
72e52e0c89SBram Moolenaar #if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
73e52e0c89SBram Moolenaar static int  did_update_one_window;
74e52e0c89SBram Moolenaar #endif
757528d1f6SBram Moolenaar 
76bdff012fSBram Moolenaar static void win_redr_status(win_T *wp, int ignore_pum);
77bdff012fSBram Moolenaar 
787528d1f6SBram Moolenaar /*
797528d1f6SBram Moolenaar  * Based on the current value of curwin->w_topline, transfer a screenfull
807528d1f6SBram Moolenaar  * of stuff from Filemem to ScreenLines[], and update curwin->w_botline.
817528d1f6SBram Moolenaar  * Return OK when the screen was updated, FAIL if it was not done.
827528d1f6SBram Moolenaar  */
837528d1f6SBram Moolenaar     int
update_screen(int type_arg)847528d1f6SBram Moolenaar update_screen(int type_arg)
857528d1f6SBram Moolenaar {
867528d1f6SBram Moolenaar     int		type = type_arg;
877528d1f6SBram Moolenaar     win_T	*wp;
887528d1f6SBram Moolenaar     static int	did_intro = FALSE;
897528d1f6SBram Moolenaar #ifdef FEAT_GUI
90e52e0c89SBram Moolenaar     int		did_one = FALSE;
917528d1f6SBram Moolenaar     int		did_undraw = FALSE;
927528d1f6SBram Moolenaar     int		gui_cursor_col = 0;
937528d1f6SBram Moolenaar     int		gui_cursor_row = 0;
947528d1f6SBram Moolenaar #endif
957528d1f6SBram Moolenaar     int		no_update = FALSE;
96e0c03c8eSBram Moolenaar     int		save_pum_will_redraw = pum_will_redraw;
977528d1f6SBram Moolenaar 
987528d1f6SBram Moolenaar     // Don't do anything if the screen structures are (not yet) valid.
997528d1f6SBram Moolenaar     if (!screen_valid(TRUE))
1007528d1f6SBram Moolenaar 	return FAIL;
1017528d1f6SBram Moolenaar 
1027528d1f6SBram Moolenaar     if (type == VALID_NO_UPDATE)
1037528d1f6SBram Moolenaar     {
1047528d1f6SBram Moolenaar 	no_update = TRUE;
1057528d1f6SBram Moolenaar 	type = 0;
1067528d1f6SBram Moolenaar     }
1077528d1f6SBram Moolenaar 
1087528d1f6SBram Moolenaar #ifdef FEAT_EVAL
1097528d1f6SBram Moolenaar     {
1107528d1f6SBram Moolenaar 	buf_T *buf;
1117528d1f6SBram Moolenaar 
1127528d1f6SBram Moolenaar 	// Before updating the screen, notify any listeners of changed text.
1137528d1f6SBram Moolenaar 	FOR_ALL_BUFFERS(buf)
1147528d1f6SBram Moolenaar 	    invoke_listeners(buf);
1157528d1f6SBram Moolenaar     }
1167528d1f6SBram Moolenaar #endif
1177528d1f6SBram Moolenaar 
1187528d1f6SBram Moolenaar #ifdef FEAT_DIFF
1197528d1f6SBram Moolenaar     // May have postponed updating diffs.
1207528d1f6SBram Moolenaar     if (need_diff_redraw)
1217528d1f6SBram Moolenaar 	diff_redraw(TRUE);
1227528d1f6SBram Moolenaar #endif
1237528d1f6SBram Moolenaar 
1247528d1f6SBram Moolenaar     if (must_redraw)
1257528d1f6SBram Moolenaar     {
1267528d1f6SBram Moolenaar 	if (type < must_redraw)	    // use maximal type
1277528d1f6SBram Moolenaar 	    type = must_redraw;
1287528d1f6SBram Moolenaar 
1297528d1f6SBram Moolenaar 	// must_redraw is reset here, so that when we run into some weird
1307528d1f6SBram Moolenaar 	// reason to redraw while busy redrawing (e.g., asynchronous
1317528d1f6SBram Moolenaar 	// scrolling), or update_topline() in win_update() will cause a
1327528d1f6SBram Moolenaar 	// scroll, the screen will be redrawn later or in win_update().
1337528d1f6SBram Moolenaar 	must_redraw = 0;
1347528d1f6SBram Moolenaar     }
1357528d1f6SBram Moolenaar 
1367528d1f6SBram Moolenaar     // May need to update w_lines[].
1377528d1f6SBram Moolenaar     if (curwin->w_lines_valid == 0 && type < NOT_VALID
1387528d1f6SBram Moolenaar #ifdef FEAT_TERMINAL
1397528d1f6SBram Moolenaar 	    && !term_do_update_window(curwin)
1407528d1f6SBram Moolenaar #endif
1417528d1f6SBram Moolenaar 		)
1427528d1f6SBram Moolenaar 	type = NOT_VALID;
1437528d1f6SBram Moolenaar 
1447528d1f6SBram Moolenaar     // Postpone the redrawing when it's not needed and when being called
1457528d1f6SBram Moolenaar     // recursively.
1467528d1f6SBram Moolenaar     if (!redrawing() || updating_screen)
1477528d1f6SBram Moolenaar     {
1487528d1f6SBram Moolenaar 	redraw_later(type);		// remember type for next time
1497528d1f6SBram Moolenaar 	must_redraw = type;
1507528d1f6SBram Moolenaar 	if (type > INVERTED_ALL)
1517528d1f6SBram Moolenaar 	    curwin->w_lines_valid = 0;	// don't use w_lines[].wl_size now
1527528d1f6SBram Moolenaar 	return FAIL;
1537528d1f6SBram Moolenaar     }
1547528d1f6SBram Moolenaar     updating_screen = TRUE;
1557528d1f6SBram Moolenaar 
15605ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
1577528d1f6SBram Moolenaar     // Update popup_mask if needed.  This may set w_redraw_top and w_redraw_bot
1587528d1f6SBram Moolenaar     // in some windows.
1597528d1f6SBram Moolenaar     may_update_popup_mask(type);
1607528d1f6SBram Moolenaar #endif
1617528d1f6SBram Moolenaar 
1627528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
1637528d1f6SBram Moolenaar     ++display_tick;	    // let syntax code know we're in a next round of
1647528d1f6SBram Moolenaar 			    // display updating
1657528d1f6SBram Moolenaar #endif
1667528d1f6SBram Moolenaar     if (no_update)
1677528d1f6SBram Moolenaar 	++no_win_do_lines_ins;
1687528d1f6SBram Moolenaar 
1697528d1f6SBram Moolenaar     // if the screen was scrolled up when displaying a message, scroll it down
1707528d1f6SBram Moolenaar     if (msg_scrolled)
1717528d1f6SBram Moolenaar     {
1727528d1f6SBram Moolenaar 	clear_cmdline = TRUE;
1737528d1f6SBram Moolenaar 	if (msg_scrolled > Rows - 5)	    // clearing is faster
1747528d1f6SBram Moolenaar 	    type = CLEAR;
1757528d1f6SBram Moolenaar 	else if (type != CLEAR)
1767528d1f6SBram Moolenaar 	{
1777528d1f6SBram Moolenaar 	    check_for_delay(FALSE);
1787528d1f6SBram Moolenaar 	    if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows, 0, NULL)
1797528d1f6SBram Moolenaar 								       == FAIL)
1807528d1f6SBram Moolenaar 		type = CLEAR;
1817528d1f6SBram Moolenaar 	    FOR_ALL_WINDOWS(wp)
1827528d1f6SBram Moolenaar 	    {
1837528d1f6SBram Moolenaar 		if (wp->w_winrow < msg_scrolled)
1847528d1f6SBram Moolenaar 		{
1857528d1f6SBram Moolenaar 		    if (W_WINROW(wp) + wp->w_height > msg_scrolled
1867528d1f6SBram Moolenaar 			    && wp->w_redr_type < REDRAW_TOP
1877528d1f6SBram Moolenaar 			    && wp->w_lines_valid > 0
1887528d1f6SBram Moolenaar 			    && wp->w_topline == wp->w_lines[0].wl_lnum)
1897528d1f6SBram Moolenaar 		    {
1907528d1f6SBram Moolenaar 			wp->w_upd_rows = msg_scrolled - W_WINROW(wp);
1917528d1f6SBram Moolenaar 			wp->w_redr_type = REDRAW_TOP;
1927528d1f6SBram Moolenaar 		    }
1937528d1f6SBram Moolenaar 		    else
1947528d1f6SBram Moolenaar 		    {
1957528d1f6SBram Moolenaar 			wp->w_redr_type = NOT_VALID;
1967528d1f6SBram Moolenaar 			if (W_WINROW(wp) + wp->w_height + wp->w_status_height
1977528d1f6SBram Moolenaar 							       <= msg_scrolled)
1987528d1f6SBram Moolenaar 			    wp->w_redr_status = TRUE;
1997528d1f6SBram Moolenaar 		    }
2007528d1f6SBram Moolenaar 		}
2017528d1f6SBram Moolenaar 	    }
2027528d1f6SBram Moolenaar 	    if (!no_update)
2037528d1f6SBram Moolenaar 		redraw_cmdline = TRUE;
2047528d1f6SBram Moolenaar 	    redraw_tabline = TRUE;
2057528d1f6SBram Moolenaar 	}
2067528d1f6SBram Moolenaar 	msg_scrolled = 0;
2077528d1f6SBram Moolenaar 	need_wait_return = FALSE;
2087528d1f6SBram Moolenaar     }
2097528d1f6SBram Moolenaar 
2107528d1f6SBram Moolenaar     // reset cmdline_row now (may have been changed temporarily)
2117528d1f6SBram Moolenaar     compute_cmdrow();
2127528d1f6SBram Moolenaar 
2137528d1f6SBram Moolenaar     // Check for changed highlighting
2147528d1f6SBram Moolenaar     if (need_highlight_changed)
2157528d1f6SBram Moolenaar 	highlight_changed();
2167528d1f6SBram Moolenaar 
2177528d1f6SBram Moolenaar     if (type == CLEAR)		// first clear screen
2187528d1f6SBram Moolenaar     {
2197528d1f6SBram Moolenaar 	screenclear();		// will reset clear_cmdline
2207528d1f6SBram Moolenaar 	type = NOT_VALID;
2217528d1f6SBram Moolenaar 	// must_redraw may be set indirectly, avoid another redraw later
2227528d1f6SBram Moolenaar 	must_redraw = 0;
2237528d1f6SBram Moolenaar     }
2247528d1f6SBram Moolenaar 
2257528d1f6SBram Moolenaar     if (clear_cmdline)		// going to clear cmdline (done below)
2267528d1f6SBram Moolenaar 	check_for_delay(FALSE);
2277528d1f6SBram Moolenaar 
2287528d1f6SBram Moolenaar #ifdef FEAT_LINEBREAK
2297528d1f6SBram Moolenaar     // Force redraw when width of 'number' or 'relativenumber' column
2307528d1f6SBram Moolenaar     // changes.
2317528d1f6SBram Moolenaar     if (curwin->w_redr_type < NOT_VALID
2327528d1f6SBram Moolenaar 	   && curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu)
2337528d1f6SBram Moolenaar 				    ? number_width(curwin) : 0))
2347528d1f6SBram Moolenaar 	curwin->w_redr_type = NOT_VALID;
2357528d1f6SBram Moolenaar #endif
2367528d1f6SBram Moolenaar 
2377528d1f6SBram Moolenaar     // Only start redrawing if there is really something to do.
2387528d1f6SBram Moolenaar     if (type == INVERTED)
2397528d1f6SBram Moolenaar 	update_curswant();
2407528d1f6SBram Moolenaar     if (curwin->w_redr_type < type
2417528d1f6SBram Moolenaar 	    && !((type == VALID
2427528d1f6SBram Moolenaar 		    && curwin->w_lines[0].wl_valid
2437528d1f6SBram Moolenaar #ifdef FEAT_DIFF
2447528d1f6SBram Moolenaar 		    && curwin->w_topfill == curwin->w_old_topfill
2457528d1f6SBram Moolenaar 		    && curwin->w_botfill == curwin->w_old_botfill
2467528d1f6SBram Moolenaar #endif
2477528d1f6SBram Moolenaar 		    && curwin->w_topline == curwin->w_lines[0].wl_lnum)
2487528d1f6SBram Moolenaar 		|| (type == INVERTED
2497528d1f6SBram Moolenaar 		    && VIsual_active
2507528d1f6SBram Moolenaar 		    && curwin->w_old_cursor_lnum == curwin->w_cursor.lnum
2517528d1f6SBram Moolenaar 		    && curwin->w_old_visual_mode == VIsual_mode
2527528d1f6SBram Moolenaar 		    && (curwin->w_valid & VALID_VIRTCOL)
2537528d1f6SBram Moolenaar 		    && curwin->w_old_curswant == curwin->w_curswant)
2547528d1f6SBram Moolenaar 		))
2557528d1f6SBram Moolenaar 	curwin->w_redr_type = type;
2567528d1f6SBram Moolenaar 
2577528d1f6SBram Moolenaar     // Redraw the tab pages line if needed.
2587528d1f6SBram Moolenaar     if (redraw_tabline || type >= NOT_VALID)
2597528d1f6SBram Moolenaar 	draw_tabline();
2607528d1f6SBram Moolenaar 
2617528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
2627528d1f6SBram Moolenaar     // Correct stored syntax highlighting info for changes in each displayed
2637528d1f6SBram Moolenaar     // buffer.  Each buffer must only be done once.
2647528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
2657528d1f6SBram Moolenaar     {
2667528d1f6SBram Moolenaar 	if (wp->w_buffer->b_mod_set)
2677528d1f6SBram Moolenaar 	{
2687528d1f6SBram Moolenaar 	    win_T	*wwp;
2697528d1f6SBram Moolenaar 
2707528d1f6SBram Moolenaar 	    // Check if we already did this buffer.
2717528d1f6SBram Moolenaar 	    for (wwp = firstwin; wwp != wp; wwp = wwp->w_next)
2727528d1f6SBram Moolenaar 		if (wwp->w_buffer == wp->w_buffer)
2737528d1f6SBram Moolenaar 		    break;
2747528d1f6SBram Moolenaar 	    if (wwp == wp && syntax_present(wp))
2757528d1f6SBram Moolenaar 		syn_stack_apply_changes(wp->w_buffer);
2767528d1f6SBram Moolenaar 	}
2777528d1f6SBram Moolenaar     }
2787528d1f6SBram Moolenaar #endif
2797528d1f6SBram Moolenaar 
280e0c03c8eSBram Moolenaar     if (pum_redraw_in_same_position())
281e0c03c8eSBram Moolenaar 	// Avoid flicker if the popup menu is going to be redrawn in the same
282e0c03c8eSBram Moolenaar 	// position.
283e0c03c8eSBram Moolenaar 	pum_will_redraw = TRUE;
284e0c03c8eSBram Moolenaar 
2857528d1f6SBram Moolenaar     // Go from top to bottom through the windows, redrawing the ones that need
2867528d1f6SBram Moolenaar     // it.
2877528d1f6SBram Moolenaar #if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
288e52e0c89SBram Moolenaar     did_update_one_window = FALSE;
2897528d1f6SBram Moolenaar #endif
2907528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
2917528d1f6SBram Moolenaar     screen_search_hl.rm.regprog = NULL;
2927528d1f6SBram Moolenaar #endif
2937528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
2947528d1f6SBram Moolenaar     {
2957528d1f6SBram Moolenaar 	if (wp->w_redr_type != 0)
2967528d1f6SBram Moolenaar 	{
2977528d1f6SBram Moolenaar 	    cursor_off();
298e52e0c89SBram Moolenaar #ifdef FEAT_GUI
2997528d1f6SBram Moolenaar 	    if (!did_one)
3007528d1f6SBram Moolenaar 	    {
3017528d1f6SBram Moolenaar 		did_one = TRUE;
302e52e0c89SBram Moolenaar 
3037528d1f6SBram Moolenaar 		// Remove the cursor before starting to do anything, because
3047528d1f6SBram Moolenaar 		// scrolling may make it difficult to redraw the text under
3057528d1f6SBram Moolenaar 		// it.
30609f067fcSBram Moolenaar 		// Also remove the cursor if it needs to be hidden due to an
30709f067fcSBram Moolenaar 		// ongoing cursor-less sleep.
30809f067fcSBram Moolenaar 		if (gui.in_use && (wp == curwin || cursor_is_sleeping()))
3097528d1f6SBram Moolenaar 		{
3107528d1f6SBram Moolenaar 		    gui_cursor_col = gui.cursor_col;
3117528d1f6SBram Moolenaar 		    gui_cursor_row = gui.cursor_row;
3127528d1f6SBram Moolenaar 		    gui_undraw_cursor();
3137528d1f6SBram Moolenaar 		    did_undraw = TRUE;
3147528d1f6SBram Moolenaar 		}
3157528d1f6SBram Moolenaar 	    }
3167528d1f6SBram Moolenaar #endif
3177528d1f6SBram Moolenaar 	    win_update(wp);
3187528d1f6SBram Moolenaar 	}
3197528d1f6SBram Moolenaar 
3207528d1f6SBram Moolenaar 	// redraw status line after the window to minimize cursor movement
3217528d1f6SBram Moolenaar 	if (wp->w_redr_status)
3227528d1f6SBram Moolenaar 	{
3237528d1f6SBram Moolenaar 	    cursor_off();
3247528d1f6SBram Moolenaar 	    win_redr_status(wp, TRUE); // any popup menu will be redrawn below
3257528d1f6SBram Moolenaar 	}
3267528d1f6SBram Moolenaar     }
3277528d1f6SBram Moolenaar #if defined(FEAT_SEARCH_EXTRA)
3287528d1f6SBram Moolenaar     end_search_hl();
3297528d1f6SBram Moolenaar #endif
330e0c03c8eSBram Moolenaar 
3317528d1f6SBram Moolenaar     // May need to redraw the popup menu.
332e0c03c8eSBram Moolenaar     pum_will_redraw = save_pum_will_redraw;
3337528d1f6SBram Moolenaar     pum_may_redraw();
3347528d1f6SBram Moolenaar 
3357528d1f6SBram Moolenaar     // Reset b_mod_set flags.  Going through all windows is probably faster
3367528d1f6SBram Moolenaar     // than going through all buffers (there could be many buffers).
3377528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
3387528d1f6SBram Moolenaar 	wp->w_buffer->b_mod_set = FALSE;
3397528d1f6SBram Moolenaar 
34005ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
3417528d1f6SBram Moolenaar     // Display popup windows on top of the windows and command line.
3427528d1f6SBram Moolenaar     update_popups(win_update);
3437528d1f6SBram Moolenaar #endif
3447528d1f6SBram Moolenaar 
3457528d1f6SBram Moolenaar     after_updating_screen(TRUE);
3467528d1f6SBram Moolenaar 
3477528d1f6SBram Moolenaar     // Clear or redraw the command line.  Done last, because scrolling may
3487528d1f6SBram Moolenaar     // mess up the command line.
3497528d1f6SBram Moolenaar     if (clear_cmdline || redraw_cmdline || redraw_mode)
3507528d1f6SBram Moolenaar 	showmode();
3517528d1f6SBram Moolenaar 
3527528d1f6SBram Moolenaar     if (no_update)
3537528d1f6SBram Moolenaar 	--no_win_do_lines_ins;
3547528d1f6SBram Moolenaar 
3557528d1f6SBram Moolenaar     // May put up an introductory message when not editing a file
3567528d1f6SBram Moolenaar     if (!did_intro)
3577528d1f6SBram Moolenaar 	maybe_intro_message();
3587528d1f6SBram Moolenaar     did_intro = TRUE;
3597528d1f6SBram Moolenaar 
3607528d1f6SBram Moolenaar #ifdef FEAT_GUI
3617528d1f6SBram Moolenaar     // Redraw the cursor and update the scrollbars when all screen updating is
3627528d1f6SBram Moolenaar     // done.
3637528d1f6SBram Moolenaar     if (gui.in_use)
3647528d1f6SBram Moolenaar     {
3657528d1f6SBram Moolenaar 	if (did_undraw && !gui_mch_is_blink_off())
3667528d1f6SBram Moolenaar 	{
3677528d1f6SBram Moolenaar 	    mch_disable_flush();
3687528d1f6SBram Moolenaar 	    out_flush();	// required before updating the cursor
3697528d1f6SBram Moolenaar 	    mch_enable_flush();
3707528d1f6SBram Moolenaar 
3717528d1f6SBram Moolenaar 	    // Put the GUI position where the cursor was, gui_update_cursor()
3727528d1f6SBram Moolenaar 	    // uses that.
3737528d1f6SBram Moolenaar 	    gui.col = gui_cursor_col;
3747528d1f6SBram Moolenaar 	    gui.row = gui_cursor_row;
3757528d1f6SBram Moolenaar 	    gui.col = mb_fix_col(gui.col, gui.row);
3767528d1f6SBram Moolenaar 	    gui_update_cursor(FALSE, FALSE);
3777528d1f6SBram Moolenaar 	    gui_may_flush();
3787528d1f6SBram Moolenaar 	    screen_cur_col = gui.col;
3797528d1f6SBram Moolenaar 	    screen_cur_row = gui.row;
3807528d1f6SBram Moolenaar 	}
3817528d1f6SBram Moolenaar 	else
3827528d1f6SBram Moolenaar 	    out_flush();
3837528d1f6SBram Moolenaar 	gui_update_scrollbars(FALSE);
3847528d1f6SBram Moolenaar     }
3857528d1f6SBram Moolenaar #endif
3867528d1f6SBram Moolenaar     return OK;
3877528d1f6SBram Moolenaar }
3887528d1f6SBram Moolenaar 
3897528d1f6SBram Moolenaar /*
390ae0f151dSBram Moolenaar  * Return the row for drawing the statusline and the ruler of window "wp".
391ae0f151dSBram Moolenaar  */
39249c51b82SBram Moolenaar     int
statusline_row(win_T * wp)393ae0f151dSBram Moolenaar statusline_row(win_T *wp)
394ae0f151dSBram Moolenaar {
395ae0f151dSBram Moolenaar #if defined(FEAT_PROP_POPUP)
396ae0f151dSBram Moolenaar     // If the window is really zero height the winbar isn't displayed.
397ae0f151dSBram Moolenaar     if (wp->w_frame->fr_height == wp->w_status_height && !popup_is_popup(wp))
398ae0f151dSBram Moolenaar 	return wp->w_winrow;
399ae0f151dSBram Moolenaar #endif
400ae0f151dSBram Moolenaar     return W_WINROW(wp) + wp->w_height;
401ae0f151dSBram Moolenaar }
402ae0f151dSBram Moolenaar 
403ae0f151dSBram Moolenaar /*
4047528d1f6SBram Moolenaar  * Redraw the status line of window wp.
4057528d1f6SBram Moolenaar  *
4067528d1f6SBram Moolenaar  * If inversion is possible we use it. Else '=' characters are used.
4077528d1f6SBram Moolenaar  * If "ignore_pum" is TRUE, also redraw statusline when the popup menu is
4087528d1f6SBram Moolenaar  * displayed.
4097528d1f6SBram Moolenaar  */
410bdff012fSBram Moolenaar     static void
win_redr_status(win_T * wp,int ignore_pum UNUSED)4117528d1f6SBram Moolenaar win_redr_status(win_T *wp, int ignore_pum UNUSED)
4127528d1f6SBram Moolenaar {
4137528d1f6SBram Moolenaar     int		row;
4147528d1f6SBram Moolenaar     char_u	*p;
4157528d1f6SBram Moolenaar     int		len;
4167528d1f6SBram Moolenaar     int		fillchar;
4177528d1f6SBram Moolenaar     int		attr;
4187528d1f6SBram Moolenaar     int		this_ru_col;
4197528d1f6SBram Moolenaar     static int  busy = FALSE;
4207528d1f6SBram Moolenaar 
4217528d1f6SBram Moolenaar     // It's possible to get here recursively when 'statusline' (indirectly)
4227528d1f6SBram Moolenaar     // invokes ":redrawstatus".  Simply ignore the call then.
4237528d1f6SBram Moolenaar     if (busy)
4247528d1f6SBram Moolenaar 	return;
4257528d1f6SBram Moolenaar     busy = TRUE;
4267528d1f6SBram Moolenaar 
427ae0f151dSBram Moolenaar     row = statusline_row(wp);
428ae0f151dSBram Moolenaar 
4297528d1f6SBram Moolenaar     wp->w_redr_status = FALSE;
4307528d1f6SBram Moolenaar     if (wp->w_status_height == 0)
4317528d1f6SBram Moolenaar     {
4327528d1f6SBram Moolenaar 	// no status line, can only be last window
4337528d1f6SBram Moolenaar 	redraw_cmdline = TRUE;
4347528d1f6SBram Moolenaar     }
4357528d1f6SBram Moolenaar     else if (!redrawing()
4367528d1f6SBram Moolenaar 	    // don't update status line when popup menu is visible and may be
4377528d1f6SBram Moolenaar 	    // drawn over it, unless it will be redrawn later
4387528d1f6SBram Moolenaar 	    || (!ignore_pum && pum_visible()))
4397528d1f6SBram Moolenaar     {
4407528d1f6SBram Moolenaar 	// Don't redraw right now, do it later.
4417528d1f6SBram Moolenaar 	wp->w_redr_status = TRUE;
4427528d1f6SBram Moolenaar     }
4437528d1f6SBram Moolenaar #ifdef FEAT_STL_OPT
4447528d1f6SBram Moolenaar     else if (*p_stl != NUL || *wp->w_p_stl != NUL)
4457528d1f6SBram Moolenaar     {
4467528d1f6SBram Moolenaar 	// redraw custom status line
4477528d1f6SBram Moolenaar 	redraw_custom_statusline(wp);
4487528d1f6SBram Moolenaar     }
4497528d1f6SBram Moolenaar #endif
4507528d1f6SBram Moolenaar     else
4517528d1f6SBram Moolenaar     {
4527528d1f6SBram Moolenaar 	fillchar = fillchar_status(&attr, wp);
4537528d1f6SBram Moolenaar 
4547528d1f6SBram Moolenaar 	get_trans_bufname(wp->w_buffer);
4557528d1f6SBram Moolenaar 	p = NameBuff;
4567528d1f6SBram Moolenaar 	len = (int)STRLEN(p);
4577528d1f6SBram Moolenaar 
4587528d1f6SBram Moolenaar 	if (bt_help(wp->w_buffer)
4597528d1f6SBram Moolenaar #ifdef FEAT_QUICKFIX
4607528d1f6SBram Moolenaar 		|| wp->w_p_pvw
4617528d1f6SBram Moolenaar #endif
4627528d1f6SBram Moolenaar 		|| bufIsChanged(wp->w_buffer)
4637528d1f6SBram Moolenaar 		|| wp->w_buffer->b_p_ro)
4647528d1f6SBram Moolenaar 	    *(p + len++) = ' ';
4657528d1f6SBram Moolenaar 	if (bt_help(wp->w_buffer))
4667528d1f6SBram Moolenaar 	{
467826bfe4bSBram Moolenaar 	    vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[Help]"));
4687528d1f6SBram Moolenaar 	    len += (int)STRLEN(p + len);
4697528d1f6SBram Moolenaar 	}
4707528d1f6SBram Moolenaar #ifdef FEAT_QUICKFIX
4717528d1f6SBram Moolenaar 	if (wp->w_p_pvw)
4727528d1f6SBram Moolenaar 	{
473826bfe4bSBram Moolenaar 	    vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[Preview]"));
4747528d1f6SBram Moolenaar 	    len += (int)STRLEN(p + len);
4757528d1f6SBram Moolenaar 	}
4767528d1f6SBram Moolenaar #endif
4777528d1f6SBram Moolenaar 	if (bufIsChanged(wp->w_buffer)
4787528d1f6SBram Moolenaar #ifdef FEAT_TERMINAL
4797528d1f6SBram Moolenaar 		&& !bt_terminal(wp->w_buffer)
4807528d1f6SBram Moolenaar #endif
4817528d1f6SBram Moolenaar 		)
4827528d1f6SBram Moolenaar 	{
483826bfe4bSBram Moolenaar 	    vim_snprintf((char *)p + len, MAXPATHL - len, "%s", "[+]");
484826bfe4bSBram Moolenaar 	    len += (int)STRLEN(p + len);
4857528d1f6SBram Moolenaar 	}
4867528d1f6SBram Moolenaar 	if (wp->w_buffer->b_p_ro)
4877528d1f6SBram Moolenaar 	{
488826bfe4bSBram Moolenaar 	    vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[RO]"));
4897528d1f6SBram Moolenaar 	    len += (int)STRLEN(p + len);
4907528d1f6SBram Moolenaar 	}
4917528d1f6SBram Moolenaar 
4927528d1f6SBram Moolenaar 	this_ru_col = ru_col - (Columns - wp->w_width);
4937528d1f6SBram Moolenaar 	if (this_ru_col < (wp->w_width + 1) / 2)
4947528d1f6SBram Moolenaar 	    this_ru_col = (wp->w_width + 1) / 2;
4957528d1f6SBram Moolenaar 	if (this_ru_col <= 1)
4967528d1f6SBram Moolenaar 	{
4977528d1f6SBram Moolenaar 	    p = (char_u *)"<";		// No room for file name!
4987528d1f6SBram Moolenaar 	    len = 1;
4997528d1f6SBram Moolenaar 	}
5007528d1f6SBram Moolenaar 	else if (has_mbyte)
5017528d1f6SBram Moolenaar 	{
5027528d1f6SBram Moolenaar 	    int	clen = 0, i;
5037528d1f6SBram Moolenaar 
5047528d1f6SBram Moolenaar 	    // Count total number of display cells.
5057528d1f6SBram Moolenaar 	    clen = mb_string2cells(p, -1);
5067528d1f6SBram Moolenaar 
5077528d1f6SBram Moolenaar 	    // Find first character that will fit.
5087528d1f6SBram Moolenaar 	    // Going from start to end is much faster for DBCS.
5097528d1f6SBram Moolenaar 	    for (i = 0; p[i] != NUL && clen >= this_ru_col - 1;
5107528d1f6SBram Moolenaar 		    i += (*mb_ptr2len)(p + i))
5117528d1f6SBram Moolenaar 		clen -= (*mb_ptr2cells)(p + i);
5127528d1f6SBram Moolenaar 	    len = clen;
5137528d1f6SBram Moolenaar 	    if (i > 0)
5147528d1f6SBram Moolenaar 	    {
5157528d1f6SBram Moolenaar 		p = p + i - 1;
5167528d1f6SBram Moolenaar 		*p = '<';
5177528d1f6SBram Moolenaar 		++len;
5187528d1f6SBram Moolenaar 	    }
5197528d1f6SBram Moolenaar 
5207528d1f6SBram Moolenaar 	}
5217528d1f6SBram Moolenaar 	else if (len > this_ru_col - 1)
5227528d1f6SBram Moolenaar 	{
5237528d1f6SBram Moolenaar 	    p += len - (this_ru_col - 1);
5247528d1f6SBram Moolenaar 	    *p = '<';
5257528d1f6SBram Moolenaar 	    len = this_ru_col - 1;
5267528d1f6SBram Moolenaar 	}
5277528d1f6SBram Moolenaar 
5287528d1f6SBram Moolenaar 	screen_puts(p, row, wp->w_wincol, attr);
5297528d1f6SBram Moolenaar 	screen_fill(row, row + 1, len + wp->w_wincol,
5307528d1f6SBram Moolenaar 			this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
5317528d1f6SBram Moolenaar 
5327528d1f6SBram Moolenaar 	if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL)
5337528d1f6SBram Moolenaar 		&& (int)(this_ru_col - len) > (int)(STRLEN(NameBuff) + 1))
5347528d1f6SBram Moolenaar 	    screen_puts(NameBuff, row, (int)(this_ru_col - STRLEN(NameBuff)
5357528d1f6SBram Moolenaar 						   - 1 + wp->w_wincol), attr);
5367528d1f6SBram Moolenaar 
5377528d1f6SBram Moolenaar #ifdef FEAT_CMDL_INFO
5387528d1f6SBram Moolenaar 	win_redr_ruler(wp, TRUE, ignore_pum);
5397528d1f6SBram Moolenaar #endif
5407528d1f6SBram Moolenaar     }
5417528d1f6SBram Moolenaar 
5427528d1f6SBram Moolenaar     /*
5437528d1f6SBram Moolenaar      * May need to draw the character below the vertical separator.
5447528d1f6SBram Moolenaar      */
5457528d1f6SBram Moolenaar     if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing())
5467528d1f6SBram Moolenaar     {
5477528d1f6SBram Moolenaar 	if (stl_connected(wp))
5487528d1f6SBram Moolenaar 	    fillchar = fillchar_status(&attr, wp);
5497528d1f6SBram Moolenaar 	else
5507528d1f6SBram Moolenaar 	    fillchar = fillchar_vsep(&attr);
551ae0f151dSBram Moolenaar 	screen_putchar(fillchar, row, W_ENDCOL(wp), attr);
5527528d1f6SBram Moolenaar     }
5537528d1f6SBram Moolenaar     busy = FALSE;
5547528d1f6SBram Moolenaar }
5557528d1f6SBram Moolenaar 
5567528d1f6SBram Moolenaar #ifdef FEAT_STL_OPT
5577528d1f6SBram Moolenaar /*
5587528d1f6SBram Moolenaar  * Redraw the status line according to 'statusline' and take care of any
5597528d1f6SBram Moolenaar  * errors encountered.
5607528d1f6SBram Moolenaar  */
5617528d1f6SBram Moolenaar     static void
redraw_custom_statusline(win_T * wp)5627528d1f6SBram Moolenaar redraw_custom_statusline(win_T *wp)
5637528d1f6SBram Moolenaar {
5647528d1f6SBram Moolenaar     static int	    entered = FALSE;
5657528d1f6SBram Moolenaar     int		    saved_did_emsg = did_emsg;
5667528d1f6SBram Moolenaar 
5677528d1f6SBram Moolenaar     // When called recursively return.  This can happen when the statusline
5687528d1f6SBram Moolenaar     // contains an expression that triggers a redraw.
5697528d1f6SBram Moolenaar     if (entered)
5707528d1f6SBram Moolenaar 	return;
5717528d1f6SBram Moolenaar     entered = TRUE;
5727528d1f6SBram Moolenaar 
5737528d1f6SBram Moolenaar     did_emsg = FALSE;
5747528d1f6SBram Moolenaar     win_redr_custom(wp, FALSE);
5757528d1f6SBram Moolenaar     if (did_emsg)
5767528d1f6SBram Moolenaar     {
5777528d1f6SBram Moolenaar 	// When there is an error disable the statusline, otherwise the
5787528d1f6SBram Moolenaar 	// display is messed up with errors and a redraw triggers the problem
5797528d1f6SBram Moolenaar 	// again and again.
5807528d1f6SBram Moolenaar 	set_string_option_direct((char_u *)"statusline", -1,
5817528d1f6SBram Moolenaar 		(char_u *)"", OPT_FREE | (*wp->w_p_stl != NUL
5827528d1f6SBram Moolenaar 					? OPT_LOCAL : OPT_GLOBAL), SID_ERROR);
5837528d1f6SBram Moolenaar     }
5847528d1f6SBram Moolenaar     did_emsg |= saved_did_emsg;
5857528d1f6SBram Moolenaar     entered = FALSE;
5867528d1f6SBram Moolenaar }
5877528d1f6SBram Moolenaar #endif
5887528d1f6SBram Moolenaar 
5897528d1f6SBram Moolenaar /*
5907528d1f6SBram Moolenaar  * Show current status info in ruler and various other places
5917528d1f6SBram Moolenaar  * If always is FALSE, only show ruler if position has changed.
5927528d1f6SBram Moolenaar  */
5937528d1f6SBram Moolenaar     void
showruler(int always)5947528d1f6SBram Moolenaar showruler(int always)
5957528d1f6SBram Moolenaar {
5967528d1f6SBram Moolenaar     if (!always && !redrawing())
5977528d1f6SBram Moolenaar 	return;
5987528d1f6SBram Moolenaar     if (pum_visible())
5997528d1f6SBram Moolenaar     {
6007528d1f6SBram Moolenaar 	// Don't redraw right now, do it later.
6017528d1f6SBram Moolenaar 	curwin->w_redr_status = TRUE;
6027528d1f6SBram Moolenaar 	return;
6037528d1f6SBram Moolenaar     }
6047528d1f6SBram Moolenaar #if defined(FEAT_STL_OPT)
6057528d1f6SBram Moolenaar     if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height)
6067528d1f6SBram Moolenaar 	redraw_custom_statusline(curwin);
6077528d1f6SBram Moolenaar     else
6087528d1f6SBram Moolenaar #endif
6097528d1f6SBram Moolenaar #ifdef FEAT_CMDL_INFO
6107528d1f6SBram Moolenaar 	win_redr_ruler(curwin, always, FALSE);
6117528d1f6SBram Moolenaar #endif
6127528d1f6SBram Moolenaar 
6137528d1f6SBram Moolenaar #ifdef FEAT_TITLE
6147528d1f6SBram Moolenaar     if (need_maketitle
6157528d1f6SBram Moolenaar # ifdef FEAT_STL_OPT
6167528d1f6SBram Moolenaar 	    || (p_icon && (stl_syntax & STL_IN_ICON))
6177528d1f6SBram Moolenaar 	    || (p_title && (stl_syntax & STL_IN_TITLE))
6187528d1f6SBram Moolenaar # endif
6197528d1f6SBram Moolenaar        )
6207528d1f6SBram Moolenaar 	maketitle();
6217528d1f6SBram Moolenaar #endif
6227528d1f6SBram Moolenaar     // Redraw the tab pages line if needed.
6237528d1f6SBram Moolenaar     if (redraw_tabline)
6247528d1f6SBram Moolenaar 	draw_tabline();
6257528d1f6SBram Moolenaar }
6267528d1f6SBram Moolenaar 
6277528d1f6SBram Moolenaar #if defined(FEAT_CMDL_INFO) || defined(PROTO)
6287528d1f6SBram Moolenaar     void
win_redr_ruler(win_T * wp,int always,int ignore_pum)6297528d1f6SBram Moolenaar win_redr_ruler(win_T *wp, int always, int ignore_pum)
6307528d1f6SBram Moolenaar {
6317528d1f6SBram Moolenaar #define RULER_BUF_LEN 70
6327528d1f6SBram Moolenaar     char_u	buffer[RULER_BUF_LEN];
6337528d1f6SBram Moolenaar     int		row;
6347528d1f6SBram Moolenaar     int		fillchar;
6357528d1f6SBram Moolenaar     int		attr;
6367528d1f6SBram Moolenaar     int		empty_line = FALSE;
6377528d1f6SBram Moolenaar     colnr_T	virtcol;
6387528d1f6SBram Moolenaar     int		i;
6397528d1f6SBram Moolenaar     size_t	len;
6407528d1f6SBram Moolenaar     int		o;
6417528d1f6SBram Moolenaar     int		this_ru_col;
6427528d1f6SBram Moolenaar     int		off = 0;
6437528d1f6SBram Moolenaar     int		width;
6447528d1f6SBram Moolenaar 
6457528d1f6SBram Moolenaar     // If 'ruler' off or redrawing disabled, don't do anything
6467528d1f6SBram Moolenaar     if (!p_ru)
6477528d1f6SBram Moolenaar 	return;
6487528d1f6SBram Moolenaar 
6497528d1f6SBram Moolenaar     /*
6507528d1f6SBram Moolenaar      * Check if cursor.lnum is valid, since win_redr_ruler() may be called
6517528d1f6SBram Moolenaar      * after deleting lines, before cursor.lnum is corrected.
6527528d1f6SBram Moolenaar      */
6537528d1f6SBram Moolenaar     if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count)
6547528d1f6SBram Moolenaar 	return;
6557528d1f6SBram Moolenaar 
6567528d1f6SBram Moolenaar     // Don't draw the ruler while doing insert-completion, it might overwrite
6577528d1f6SBram Moolenaar     // the (long) mode message.
6587528d1f6SBram Moolenaar     if (wp == lastwin && lastwin->w_status_height == 0)
6597528d1f6SBram Moolenaar 	if (edit_submode != NULL)
6607528d1f6SBram Moolenaar 	    return;
6617528d1f6SBram Moolenaar     // Don't draw the ruler when the popup menu is visible, it may overlap.
6627528d1f6SBram Moolenaar     // Except when the popup menu will be redrawn anyway.
6637528d1f6SBram Moolenaar     if (!ignore_pum && pum_visible())
6647528d1f6SBram Moolenaar 	return;
6657528d1f6SBram Moolenaar 
6667528d1f6SBram Moolenaar #ifdef FEAT_STL_OPT
6677528d1f6SBram Moolenaar     if (*p_ruf)
6687528d1f6SBram Moolenaar     {
66953989554SBram Moolenaar 	int	called_emsg_before = called_emsg;
6707528d1f6SBram Moolenaar 
6717528d1f6SBram Moolenaar 	win_redr_custom(wp, TRUE);
67253989554SBram Moolenaar 	if (called_emsg > called_emsg_before)
6737528d1f6SBram Moolenaar 	    set_string_option_direct((char_u *)"rulerformat", -1,
6747528d1f6SBram Moolenaar 					   (char_u *)"", OPT_FREE, SID_ERROR);
6757528d1f6SBram Moolenaar 	return;
6767528d1f6SBram Moolenaar     }
6777528d1f6SBram Moolenaar #endif
6787528d1f6SBram Moolenaar 
6797528d1f6SBram Moolenaar     /*
6807528d1f6SBram Moolenaar      * Check if not in Insert mode and the line is empty (will show "0-1").
6817528d1f6SBram Moolenaar      */
6827528d1f6SBram Moolenaar     if (!(State & INSERT)
6837528d1f6SBram Moolenaar 		&& *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, FALSE) == NUL)
6847528d1f6SBram Moolenaar 	empty_line = TRUE;
6857528d1f6SBram Moolenaar 
6867528d1f6SBram Moolenaar     /*
6877528d1f6SBram Moolenaar      * Only draw the ruler when something changed.
6887528d1f6SBram Moolenaar      */
6897528d1f6SBram Moolenaar     validate_virtcol_win(wp);
6907528d1f6SBram Moolenaar     if (       redraw_cmdline
6917528d1f6SBram Moolenaar 	    || always
6927528d1f6SBram Moolenaar 	    || wp->w_cursor.lnum != wp->w_ru_cursor.lnum
6937528d1f6SBram Moolenaar 	    || wp->w_cursor.col != wp->w_ru_cursor.col
6947528d1f6SBram Moolenaar 	    || wp->w_virtcol != wp->w_ru_virtcol
6957528d1f6SBram Moolenaar 	    || wp->w_cursor.coladd != wp->w_ru_cursor.coladd
6967528d1f6SBram Moolenaar 	    || wp->w_topline != wp->w_ru_topline
6977528d1f6SBram Moolenaar 	    || wp->w_buffer->b_ml.ml_line_count != wp->w_ru_line_count
6987528d1f6SBram Moolenaar #ifdef FEAT_DIFF
6997528d1f6SBram Moolenaar 	    || wp->w_topfill != wp->w_ru_topfill
7007528d1f6SBram Moolenaar #endif
7017528d1f6SBram Moolenaar 	    || empty_line != wp->w_ru_empty)
7027528d1f6SBram Moolenaar     {
7037528d1f6SBram Moolenaar 	cursor_off();
7047528d1f6SBram Moolenaar 	if (wp->w_status_height)
7057528d1f6SBram Moolenaar 	{
706ae0f151dSBram Moolenaar 	    row = statusline_row(wp);
7077528d1f6SBram Moolenaar 	    fillchar = fillchar_status(&attr, wp);
7087528d1f6SBram Moolenaar 	    off = wp->w_wincol;
7097528d1f6SBram Moolenaar 	    width = wp->w_width;
7107528d1f6SBram Moolenaar 	}
7117528d1f6SBram Moolenaar 	else
7127528d1f6SBram Moolenaar 	{
7137528d1f6SBram Moolenaar 	    row = Rows - 1;
7147528d1f6SBram Moolenaar 	    fillchar = ' ';
7157528d1f6SBram Moolenaar 	    attr = 0;
7167528d1f6SBram Moolenaar 	    width = Columns;
7177528d1f6SBram Moolenaar 	    off = 0;
7187528d1f6SBram Moolenaar 	}
7197528d1f6SBram Moolenaar 
7207528d1f6SBram Moolenaar 	// In list mode virtcol needs to be recomputed
7217528d1f6SBram Moolenaar 	virtcol = wp->w_virtcol;
722eed9d462SBram Moolenaar 	if (wp->w_p_list && wp->w_lcs_chars.tab1 == NUL)
7237528d1f6SBram Moolenaar 	{
7247528d1f6SBram Moolenaar 	    wp->w_p_list = FALSE;
7257528d1f6SBram Moolenaar 	    getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL);
7267528d1f6SBram Moolenaar 	    wp->w_p_list = TRUE;
7277528d1f6SBram Moolenaar 	}
7287528d1f6SBram Moolenaar 
7297528d1f6SBram Moolenaar 	/*
7307528d1f6SBram Moolenaar 	 * Some sprintfs return the length, some return a pointer.
7317528d1f6SBram Moolenaar 	 * To avoid portability problems we use strlen() here.
7327528d1f6SBram Moolenaar 	 */
7337528d1f6SBram Moolenaar 	vim_snprintf((char *)buffer, RULER_BUF_LEN, "%ld,",
7347528d1f6SBram Moolenaar 		(wp->w_buffer->b_ml.ml_flags & ML_EMPTY)
7357528d1f6SBram Moolenaar 		    ? 0L
7367528d1f6SBram Moolenaar 		    : (long)(wp->w_cursor.lnum));
7377528d1f6SBram Moolenaar 	len = STRLEN(buffer);
7387528d1f6SBram Moolenaar 	col_print(buffer + len, RULER_BUF_LEN - len,
7397528d1f6SBram Moolenaar 			empty_line ? 0 : (int)wp->w_cursor.col + 1,
7407528d1f6SBram Moolenaar 			(int)virtcol + 1);
7417528d1f6SBram Moolenaar 
7427528d1f6SBram Moolenaar 	/*
7437528d1f6SBram Moolenaar 	 * Add a "50%" if there is room for it.
7447528d1f6SBram Moolenaar 	 * On the last line, don't print in the last column (scrolls the
7457528d1f6SBram Moolenaar 	 * screen up on some terminals).
7467528d1f6SBram Moolenaar 	 */
7477528d1f6SBram Moolenaar 	i = (int)STRLEN(buffer);
7487528d1f6SBram Moolenaar 	get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1);
7497528d1f6SBram Moolenaar 	o = i + vim_strsize(buffer + i + 1);
7507528d1f6SBram Moolenaar 	if (wp->w_status_height == 0)	// can't use last char of screen
7517528d1f6SBram Moolenaar 	    ++o;
7527528d1f6SBram Moolenaar 	this_ru_col = ru_col - (Columns - width);
7537528d1f6SBram Moolenaar 	if (this_ru_col < 0)
7547528d1f6SBram Moolenaar 	    this_ru_col = 0;
7557528d1f6SBram Moolenaar 	// Never use more than half the window/screen width, leave the other
7567528d1f6SBram Moolenaar 	// half for the filename.
7577528d1f6SBram Moolenaar 	if (this_ru_col < (width + 1) / 2)
7587528d1f6SBram Moolenaar 	    this_ru_col = (width + 1) / 2;
7597528d1f6SBram Moolenaar 	if (this_ru_col + o < width)
7607528d1f6SBram Moolenaar 	{
7617528d1f6SBram Moolenaar 	    // need at least 3 chars left for get_rel_pos() + NUL
7627528d1f6SBram Moolenaar 	    while (this_ru_col + o < width && RULER_BUF_LEN > i + 4)
7637528d1f6SBram Moolenaar 	    {
7647528d1f6SBram Moolenaar 		if (has_mbyte)
7657528d1f6SBram Moolenaar 		    i += (*mb_char2bytes)(fillchar, buffer + i);
7667528d1f6SBram Moolenaar 		else
7677528d1f6SBram Moolenaar 		    buffer[i++] = fillchar;
7687528d1f6SBram Moolenaar 		++o;
7697528d1f6SBram Moolenaar 	    }
7707528d1f6SBram Moolenaar 	    get_rel_pos(wp, buffer + i, RULER_BUF_LEN - i);
7717528d1f6SBram Moolenaar 	}
7727528d1f6SBram Moolenaar 	// Truncate at window boundary.
7737528d1f6SBram Moolenaar 	if (has_mbyte)
7747528d1f6SBram Moolenaar 	{
7757528d1f6SBram Moolenaar 	    o = 0;
7767528d1f6SBram Moolenaar 	    for (i = 0; buffer[i] != NUL; i += (*mb_ptr2len)(buffer + i))
7777528d1f6SBram Moolenaar 	    {
7787528d1f6SBram Moolenaar 		o += (*mb_ptr2cells)(buffer + i);
7797528d1f6SBram Moolenaar 		if (this_ru_col + o > width)
7807528d1f6SBram Moolenaar 		{
7817528d1f6SBram Moolenaar 		    buffer[i] = NUL;
7827528d1f6SBram Moolenaar 		    break;
7837528d1f6SBram Moolenaar 		}
7847528d1f6SBram Moolenaar 	    }
7857528d1f6SBram Moolenaar 	}
7867528d1f6SBram Moolenaar 	else if (this_ru_col + (int)STRLEN(buffer) > width)
7877528d1f6SBram Moolenaar 	    buffer[width - this_ru_col] = NUL;
7887528d1f6SBram Moolenaar 
7897528d1f6SBram Moolenaar 	screen_puts(buffer, row, this_ru_col + off, attr);
7907528d1f6SBram Moolenaar 	i = redraw_cmdline;
7917528d1f6SBram Moolenaar 	screen_fill(row, row + 1,
7927528d1f6SBram Moolenaar 		this_ru_col + off + (int)STRLEN(buffer),
7937528d1f6SBram Moolenaar 		(int)(off + width),
7947528d1f6SBram Moolenaar 		fillchar, fillchar, attr);
7957528d1f6SBram Moolenaar 	// don't redraw the cmdline because of showing the ruler
7967528d1f6SBram Moolenaar 	redraw_cmdline = i;
7977528d1f6SBram Moolenaar 	wp->w_ru_cursor = wp->w_cursor;
7987528d1f6SBram Moolenaar 	wp->w_ru_virtcol = wp->w_virtcol;
7997528d1f6SBram Moolenaar 	wp->w_ru_empty = empty_line;
8007528d1f6SBram Moolenaar 	wp->w_ru_topline = wp->w_topline;
8017528d1f6SBram Moolenaar 	wp->w_ru_line_count = wp->w_buffer->b_ml.ml_line_count;
8027528d1f6SBram Moolenaar #ifdef FEAT_DIFF
8037528d1f6SBram Moolenaar 	wp->w_ru_topfill = wp->w_topfill;
8047528d1f6SBram Moolenaar #endif
8057528d1f6SBram Moolenaar     }
8067528d1f6SBram Moolenaar }
8077528d1f6SBram Moolenaar #endif
8087528d1f6SBram Moolenaar 
8097528d1f6SBram Moolenaar /*
8107528d1f6SBram Moolenaar  * To be called when "updating_screen" was set before and now the postponed
8117528d1f6SBram Moolenaar  * side effects may take place.
8127528d1f6SBram Moolenaar  */
8137528d1f6SBram Moolenaar     void
after_updating_screen(int may_resize_shell UNUSED)8147528d1f6SBram Moolenaar after_updating_screen(int may_resize_shell UNUSED)
8157528d1f6SBram Moolenaar {
8167528d1f6SBram Moolenaar     updating_screen = FALSE;
8177528d1f6SBram Moolenaar #ifdef FEAT_GUI
8187528d1f6SBram Moolenaar     if (may_resize_shell)
8197528d1f6SBram Moolenaar 	gui_may_resize_shell();
8207528d1f6SBram Moolenaar #endif
8217528d1f6SBram Moolenaar #ifdef FEAT_TERMINAL
8227528d1f6SBram Moolenaar     term_check_channel_closed_recently();
8237528d1f6SBram Moolenaar #endif
8247528d1f6SBram Moolenaar 
8257528d1f6SBram Moolenaar #ifdef HAVE_DROP_FILE
8267528d1f6SBram Moolenaar     // If handle_drop() was called while updating_screen was TRUE need to
8277528d1f6SBram Moolenaar     // handle the drop now.
8287528d1f6SBram Moolenaar     handle_any_postponed_drop();
8297528d1f6SBram Moolenaar #endif
8307528d1f6SBram Moolenaar }
8317528d1f6SBram Moolenaar 
8327528d1f6SBram Moolenaar /*
8337528d1f6SBram Moolenaar  * Update all windows that are editing the current buffer.
8347528d1f6SBram Moolenaar  */
8357528d1f6SBram Moolenaar     void
update_curbuf(int type)8367528d1f6SBram Moolenaar update_curbuf(int type)
8377528d1f6SBram Moolenaar {
8387528d1f6SBram Moolenaar     redraw_curbuf_later(type);
8397528d1f6SBram Moolenaar     update_screen(type);
8407528d1f6SBram Moolenaar }
8417528d1f6SBram Moolenaar 
8427528d1f6SBram Moolenaar #if defined(FEAT_MENU) || defined(FEAT_FOLDING)
8437528d1f6SBram Moolenaar /*
8447528d1f6SBram Moolenaar  * Copy "text" to ScreenLines using "attr".
8457528d1f6SBram Moolenaar  * Returns the next screen column.
8467528d1f6SBram Moolenaar  */
8477528d1f6SBram Moolenaar     static int
text_to_screenline(win_T * wp,char_u * text,int col)8487528d1f6SBram Moolenaar text_to_screenline(win_T *wp, char_u *text, int col)
8497528d1f6SBram Moolenaar {
8507528d1f6SBram Moolenaar     int		off = (int)(current_ScreenLine - ScreenLines);
8517528d1f6SBram Moolenaar 
8527528d1f6SBram Moolenaar     if (has_mbyte)
8537528d1f6SBram Moolenaar     {
8547528d1f6SBram Moolenaar 	int	cells;
8557528d1f6SBram Moolenaar 	int	u8c, u8cc[MAX_MCO];
8567528d1f6SBram Moolenaar 	int	i;
8577528d1f6SBram Moolenaar 	int	idx;
8587528d1f6SBram Moolenaar 	int	c_len;
8597528d1f6SBram Moolenaar 	char_u	*p;
8607528d1f6SBram Moolenaar # ifdef FEAT_ARABIC
8617528d1f6SBram Moolenaar 	int	prev_c = 0;		// previous Arabic character
8627528d1f6SBram Moolenaar 	int	prev_c1 = 0;		// first composing char for prev_c
8637528d1f6SBram Moolenaar # endif
8647528d1f6SBram Moolenaar 
8657528d1f6SBram Moolenaar # ifdef FEAT_RIGHTLEFT
8667528d1f6SBram Moolenaar 	if (wp->w_p_rl)
8677528d1f6SBram Moolenaar 	    idx = off;
8687528d1f6SBram Moolenaar 	else
8697528d1f6SBram Moolenaar # endif
8707528d1f6SBram Moolenaar 	    idx = off + col;
8717528d1f6SBram Moolenaar 
8727528d1f6SBram Moolenaar 	// Store multibyte characters in ScreenLines[] et al. correctly.
8737528d1f6SBram Moolenaar 	for (p = text; *p != NUL; )
8747528d1f6SBram Moolenaar 	{
8757528d1f6SBram Moolenaar 	    cells = (*mb_ptr2cells)(p);
8767528d1f6SBram Moolenaar 	    c_len = (*mb_ptr2len)(p);
8777528d1f6SBram Moolenaar 	    if (col + cells > wp->w_width
8787528d1f6SBram Moolenaar # ifdef FEAT_RIGHTLEFT
8797528d1f6SBram Moolenaar 		    - (wp->w_p_rl ? col : 0)
8807528d1f6SBram Moolenaar # endif
8817528d1f6SBram Moolenaar 		    )
8827528d1f6SBram Moolenaar 		break;
8837528d1f6SBram Moolenaar 	    ScreenLines[idx] = *p;
8847528d1f6SBram Moolenaar 	    if (enc_utf8)
8857528d1f6SBram Moolenaar 	    {
8867528d1f6SBram Moolenaar 		u8c = utfc_ptr2char(p, u8cc);
8877528d1f6SBram Moolenaar 		if (*p < 0x80 && u8cc[0] == 0)
8887528d1f6SBram Moolenaar 		{
8897528d1f6SBram Moolenaar 		    ScreenLinesUC[idx] = 0;
8907528d1f6SBram Moolenaar #ifdef FEAT_ARABIC
8917528d1f6SBram Moolenaar 		    prev_c = u8c;
8927528d1f6SBram Moolenaar #endif
8937528d1f6SBram Moolenaar 		}
8947528d1f6SBram Moolenaar 		else
8957528d1f6SBram Moolenaar 		{
8967528d1f6SBram Moolenaar #ifdef FEAT_ARABIC
8977528d1f6SBram Moolenaar 		    if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c))
8987528d1f6SBram Moolenaar 		    {
8997528d1f6SBram Moolenaar 			// Do Arabic shaping.
9007528d1f6SBram Moolenaar 			int	pc, pc1, nc;
9017528d1f6SBram Moolenaar 			int	pcc[MAX_MCO];
9027528d1f6SBram Moolenaar 			int	firstbyte = *p;
9037528d1f6SBram Moolenaar 
9047528d1f6SBram Moolenaar 			// The idea of what is the previous and next
9057528d1f6SBram Moolenaar 			// character depends on 'rightleft'.
9067528d1f6SBram Moolenaar 			if (wp->w_p_rl)
9077528d1f6SBram Moolenaar 			{
9087528d1f6SBram Moolenaar 			    pc = prev_c;
9097528d1f6SBram Moolenaar 			    pc1 = prev_c1;
9107528d1f6SBram Moolenaar 			    nc = utf_ptr2char(p + c_len);
9117528d1f6SBram Moolenaar 			    prev_c1 = u8cc[0];
9127528d1f6SBram Moolenaar 			}
9137528d1f6SBram Moolenaar 			else
9147528d1f6SBram Moolenaar 			{
9157528d1f6SBram Moolenaar 			    pc = utfc_ptr2char(p + c_len, pcc);
9167528d1f6SBram Moolenaar 			    nc = prev_c;
9177528d1f6SBram Moolenaar 			    pc1 = pcc[0];
9187528d1f6SBram Moolenaar 			}
9197528d1f6SBram Moolenaar 			prev_c = u8c;
9207528d1f6SBram Moolenaar 
9217528d1f6SBram Moolenaar 			u8c = arabic_shape(u8c, &firstbyte, &u8cc[0],
9227528d1f6SBram Moolenaar 								 pc, pc1, nc);
9237528d1f6SBram Moolenaar 			ScreenLines[idx] = firstbyte;
9247528d1f6SBram Moolenaar 		    }
9257528d1f6SBram Moolenaar 		    else
9267528d1f6SBram Moolenaar 			prev_c = u8c;
9277528d1f6SBram Moolenaar #endif
9287528d1f6SBram Moolenaar 		    // Non-BMP character: display as ? or fullwidth ?.
9297528d1f6SBram Moolenaar 		    ScreenLinesUC[idx] = u8c;
9307528d1f6SBram Moolenaar 		    for (i = 0; i < Screen_mco; ++i)
9317528d1f6SBram Moolenaar 		    {
9327528d1f6SBram Moolenaar 			ScreenLinesC[i][idx] = u8cc[i];
9337528d1f6SBram Moolenaar 			if (u8cc[i] == 0)
9347528d1f6SBram Moolenaar 			    break;
9357528d1f6SBram Moolenaar 		    }
9367528d1f6SBram Moolenaar 		}
9377528d1f6SBram Moolenaar 		if (cells > 1)
9387528d1f6SBram Moolenaar 		    ScreenLines[idx + 1] = 0;
9397528d1f6SBram Moolenaar 	    }
9407528d1f6SBram Moolenaar 	    else if (enc_dbcs == DBCS_JPNU && *p == 0x8e)
9417528d1f6SBram Moolenaar 		// double-byte single width character
9427528d1f6SBram Moolenaar 		ScreenLines2[idx] = p[1];
9437528d1f6SBram Moolenaar 	    else if (cells > 1)
9447528d1f6SBram Moolenaar 		// double-width character
9457528d1f6SBram Moolenaar 		ScreenLines[idx + 1] = p[1];
9467528d1f6SBram Moolenaar 	    col += cells;
9477528d1f6SBram Moolenaar 	    idx += cells;
9487528d1f6SBram Moolenaar 	    p += c_len;
9497528d1f6SBram Moolenaar 	}
9507528d1f6SBram Moolenaar     }
9517528d1f6SBram Moolenaar     else
9527528d1f6SBram Moolenaar     {
9537528d1f6SBram Moolenaar 	int len = (int)STRLEN(text);
9547528d1f6SBram Moolenaar 
9557528d1f6SBram Moolenaar 	if (len > wp->w_width - col)
9567528d1f6SBram Moolenaar 	    len = wp->w_width - col;
9577528d1f6SBram Moolenaar 	if (len > 0)
9587528d1f6SBram Moolenaar 	{
9597528d1f6SBram Moolenaar #ifdef FEAT_RIGHTLEFT
9607528d1f6SBram Moolenaar 	    if (wp->w_p_rl)
9617528d1f6SBram Moolenaar 		mch_memmove(current_ScreenLine, text, len);
9627528d1f6SBram Moolenaar 	    else
9637528d1f6SBram Moolenaar #endif
9647528d1f6SBram Moolenaar 		mch_memmove(current_ScreenLine + col, text, len);
9657528d1f6SBram Moolenaar 	    col += len;
9667528d1f6SBram Moolenaar 	}
9677528d1f6SBram Moolenaar     }
9687528d1f6SBram Moolenaar     return col;
9697528d1f6SBram Moolenaar }
9707528d1f6SBram Moolenaar #endif
9717528d1f6SBram Moolenaar 
9727528d1f6SBram Moolenaar #ifdef FEAT_MENU
9737528d1f6SBram Moolenaar /*
9747528d1f6SBram Moolenaar  * Draw the window toolbar.
9757528d1f6SBram Moolenaar  */
9767528d1f6SBram Moolenaar     static void
redraw_win_toolbar(win_T * wp)9777528d1f6SBram Moolenaar redraw_win_toolbar(win_T *wp)
9787528d1f6SBram Moolenaar {
9797528d1f6SBram Moolenaar     vimmenu_T	*menu;
9807528d1f6SBram Moolenaar     int		item_idx = 0;
9817528d1f6SBram Moolenaar     int		item_count = 0;
9827528d1f6SBram Moolenaar     int		col = 0;
9837528d1f6SBram Moolenaar     int		next_col;
9847528d1f6SBram Moolenaar     int		off = (int)(current_ScreenLine - ScreenLines);
9857528d1f6SBram Moolenaar     int		fill_attr = syn_name2attr((char_u *)"ToolbarLine");
9867528d1f6SBram Moolenaar     int		button_attr = syn_name2attr((char_u *)"ToolbarButton");
9877528d1f6SBram Moolenaar 
9887528d1f6SBram Moolenaar     vim_free(wp->w_winbar_items);
98900d253e2SBram Moolenaar     FOR_ALL_CHILD_MENUS(wp->w_winbar, menu)
9907528d1f6SBram Moolenaar 	++item_count;
9917528d1f6SBram Moolenaar     wp->w_winbar_items = ALLOC_CLEAR_MULT(winbar_item_T, item_count + 1);
9927528d1f6SBram Moolenaar 
9937528d1f6SBram Moolenaar     // TODO: use fewer spaces if there is not enough room
9947528d1f6SBram Moolenaar     for (menu = wp->w_winbar->children;
9957528d1f6SBram Moolenaar 			  menu != NULL && col < wp->w_width; menu = menu->next)
9967528d1f6SBram Moolenaar     {
9977528d1f6SBram Moolenaar 	space_to_screenline(off + col, fill_attr);
9987528d1f6SBram Moolenaar 	if (++col >= wp->w_width)
9997528d1f6SBram Moolenaar 	    break;
10007528d1f6SBram Moolenaar 	if (col > 1)
10017528d1f6SBram Moolenaar 	{
10027528d1f6SBram Moolenaar 	    space_to_screenline(off + col, fill_attr);
10037528d1f6SBram Moolenaar 	    if (++col >= wp->w_width)
10047528d1f6SBram Moolenaar 		break;
10057528d1f6SBram Moolenaar 	}
10067528d1f6SBram Moolenaar 
10077528d1f6SBram Moolenaar 	wp->w_winbar_items[item_idx].wb_startcol = col;
10087528d1f6SBram Moolenaar 	space_to_screenline(off + col, button_attr);
10097528d1f6SBram Moolenaar 	if (++col >= wp->w_width)
10107528d1f6SBram Moolenaar 	    break;
10117528d1f6SBram Moolenaar 
10127528d1f6SBram Moolenaar 	next_col = text_to_screenline(wp, menu->name, col);
10137528d1f6SBram Moolenaar 	while (col < next_col)
10147528d1f6SBram Moolenaar 	{
10157528d1f6SBram Moolenaar 	    ScreenAttrs[off + col] = button_attr;
10167528d1f6SBram Moolenaar 	    ++col;
10177528d1f6SBram Moolenaar 	}
10187528d1f6SBram Moolenaar 	wp->w_winbar_items[item_idx].wb_endcol = col;
10197528d1f6SBram Moolenaar 	wp->w_winbar_items[item_idx].wb_menu = menu;
10207528d1f6SBram Moolenaar 	++item_idx;
10217528d1f6SBram Moolenaar 
10227528d1f6SBram Moolenaar 	if (col >= wp->w_width)
10237528d1f6SBram Moolenaar 	    break;
10247528d1f6SBram Moolenaar 	space_to_screenline(off + col, button_attr);
10257528d1f6SBram Moolenaar 	++col;
10267528d1f6SBram Moolenaar     }
10277528d1f6SBram Moolenaar     while (col < wp->w_width)
10287528d1f6SBram Moolenaar     {
10297528d1f6SBram Moolenaar 	space_to_screenline(off + col, fill_attr);
10307528d1f6SBram Moolenaar 	++col;
10317528d1f6SBram Moolenaar     }
10327528d1f6SBram Moolenaar     wp->w_winbar_items[item_idx].wb_menu = NULL; // end marker
10337528d1f6SBram Moolenaar 
10347528d1f6SBram Moolenaar     screen_line(wp->w_winrow, wp->w_wincol, (int)wp->w_width,
10357528d1f6SBram Moolenaar 							  (int)wp->w_width, 0);
10367528d1f6SBram Moolenaar }
10377528d1f6SBram Moolenaar #endif
10387528d1f6SBram Moolenaar 
10397528d1f6SBram Moolenaar #if defined(FEAT_FOLDING) || defined(PROTO)
10407528d1f6SBram Moolenaar /*
10417528d1f6SBram Moolenaar  * Copy "buf[len]" to ScreenLines["off"] and set attributes to "attr".
10427528d1f6SBram Moolenaar  */
10437528d1f6SBram Moolenaar     static void
copy_text_attr(int off,char_u * buf,int len,int attr)10447528d1f6SBram Moolenaar copy_text_attr(
10457528d1f6SBram Moolenaar     int		off,
10467528d1f6SBram Moolenaar     char_u	*buf,
10477528d1f6SBram Moolenaar     int		len,
10487528d1f6SBram Moolenaar     int		attr)
10497528d1f6SBram Moolenaar {
10507528d1f6SBram Moolenaar     int		i;
10517528d1f6SBram Moolenaar 
10527528d1f6SBram Moolenaar     mch_memmove(ScreenLines + off, buf, (size_t)len);
10537528d1f6SBram Moolenaar     if (enc_utf8)
10547528d1f6SBram Moolenaar 	vim_memset(ScreenLinesUC + off, 0, sizeof(u8char_T) * (size_t)len);
10557528d1f6SBram Moolenaar     for (i = 0; i < len; ++i)
10567528d1f6SBram Moolenaar 	ScreenAttrs[off + i] = attr;
10577528d1f6SBram Moolenaar }
10587528d1f6SBram Moolenaar 
10597528d1f6SBram Moolenaar /*
10607528d1f6SBram Moolenaar  * Display one folded line.
10617528d1f6SBram Moolenaar  */
10627528d1f6SBram Moolenaar     static void
fold_line(win_T * wp,long fold_count,foldinfo_T * foldinfo,linenr_T lnum,int row)10637528d1f6SBram Moolenaar fold_line(
10647528d1f6SBram Moolenaar     win_T	*wp,
10657528d1f6SBram Moolenaar     long	fold_count,
10667528d1f6SBram Moolenaar     foldinfo_T	*foldinfo,
10677528d1f6SBram Moolenaar     linenr_T	lnum,
10687528d1f6SBram Moolenaar     int		row)
10697528d1f6SBram Moolenaar {
10704fa11757SBram Moolenaar     // Max value of 'foldcolumn' is 12 and maximum number of bytes in a
10714fa11757SBram Moolenaar     // multi-byte character is MAX_MCO.
10724fa11757SBram Moolenaar     char_u	buf[MAX_MCO * 12 + 1];
10737528d1f6SBram Moolenaar     pos_T	*top, *bot;
10747528d1f6SBram Moolenaar     linenr_T	lnume = lnum + fold_count - 1;
10757528d1f6SBram Moolenaar     int		len;
10767528d1f6SBram Moolenaar     char_u	*text;
10777528d1f6SBram Moolenaar     int		fdc;
10787528d1f6SBram Moolenaar     int		col;
10797528d1f6SBram Moolenaar     int		txtcol;
10807528d1f6SBram Moolenaar     int		off = (int)(current_ScreenLine - ScreenLines);
10817528d1f6SBram Moolenaar     int		ri;
10827528d1f6SBram Moolenaar 
10837528d1f6SBram Moolenaar     // Build the fold line:
10847528d1f6SBram Moolenaar     // 1. Add the cmdwin_type for the command-line window
10857528d1f6SBram Moolenaar     // 2. Add the 'foldcolumn'
10867528d1f6SBram Moolenaar     // 3. Add the 'number' or 'relativenumber' column
10877528d1f6SBram Moolenaar     // 4. Compose the text
10887528d1f6SBram Moolenaar     // 5. Add the text
10897528d1f6SBram Moolenaar     // 6. set highlighting for the Visual area an other text
10907528d1f6SBram Moolenaar     col = 0;
10917528d1f6SBram Moolenaar 
10927528d1f6SBram Moolenaar     // 1. Add the cmdwin_type for the command-line window
10937528d1f6SBram Moolenaar     // Ignores 'rightleft', this window is never right-left.
10947528d1f6SBram Moolenaar #ifdef FEAT_CMDWIN
10957528d1f6SBram Moolenaar     if (cmdwin_type != 0 && wp == curwin)
10967528d1f6SBram Moolenaar     {
10977528d1f6SBram Moolenaar 	ScreenLines[off] = cmdwin_type;
10987528d1f6SBram Moolenaar 	ScreenAttrs[off] = HL_ATTR(HLF_AT);
10997528d1f6SBram Moolenaar 	if (enc_utf8)
11007528d1f6SBram Moolenaar 	    ScreenLinesUC[off] = 0;
11017528d1f6SBram Moolenaar 	++col;
11027528d1f6SBram Moolenaar     }
11037528d1f6SBram Moolenaar #endif
11047528d1f6SBram Moolenaar 
11057528d1f6SBram Moolenaar #ifdef FEAT_RIGHTLEFT
11067528d1f6SBram Moolenaar # define RL_MEMSET(p, v, l) \
11077528d1f6SBram Moolenaar     do { \
11087528d1f6SBram Moolenaar 	if (wp->w_p_rl) \
11097528d1f6SBram Moolenaar 	    for (ri = 0; ri < l; ++ri) \
11107528d1f6SBram Moolenaar 	       ScreenAttrs[off + (wp->w_width - (p) - (l)) + ri] = v; \
11117528d1f6SBram Moolenaar 	 else \
11127528d1f6SBram Moolenaar 	    for (ri = 0; ri < l; ++ri) \
11137528d1f6SBram Moolenaar 	       ScreenAttrs[off + (p) + ri] = v; \
11147528d1f6SBram Moolenaar     } while (0)
11157528d1f6SBram Moolenaar #else
11167528d1f6SBram Moolenaar # define RL_MEMSET(p, v, l) \
11177528d1f6SBram Moolenaar     do { \
11187528d1f6SBram Moolenaar 	for (ri = 0; ri < l; ++ri) \
11197528d1f6SBram Moolenaar 	    ScreenAttrs[off + (p) + ri] = v; \
11207528d1f6SBram Moolenaar     } while (0)
11217528d1f6SBram Moolenaar #endif
11227528d1f6SBram Moolenaar 
11234fa11757SBram Moolenaar     // 2. Add the 'foldcolumn'
11244fa11757SBram Moolenaar     //    Reduce the width when there is not enough space.
11254fa11757SBram Moolenaar     fdc = compute_foldcolumn(wp, col);
11264fa11757SBram Moolenaar     if (fdc > 0)
11274fa11757SBram Moolenaar     {
11284fa11757SBram Moolenaar 	char_u	*p;
11294fa11757SBram Moolenaar 	int	i;
11304fa11757SBram Moolenaar 	int	idx;
11314fa11757SBram Moolenaar 
11324fa11757SBram Moolenaar 	fill_foldcolumn(buf, wp, TRUE, lnum);
11334fa11757SBram Moolenaar 	p = buf;
11344fa11757SBram Moolenaar 	for (i = 0; i < fdc; i++)
11354fa11757SBram Moolenaar 	{
11364fa11757SBram Moolenaar 	    int		ch;
11374fa11757SBram Moolenaar 
11384fa11757SBram Moolenaar 	    if (has_mbyte)
11394fa11757SBram Moolenaar 		ch = mb_ptr2char_adv(&p);
11404fa11757SBram Moolenaar 	    else
11414fa11757SBram Moolenaar 		ch = *p++;
11424fa11757SBram Moolenaar #ifdef FEAT_RIGHTLEFT
11434fa11757SBram Moolenaar 	    if (wp->w_p_rl)
11444fa11757SBram Moolenaar 		idx = off + wp->w_width - i - 1 - col;
11454fa11757SBram Moolenaar 	    else
11464fa11757SBram Moolenaar #endif
11474fa11757SBram Moolenaar 		idx = off + col + i;
11484fa11757SBram Moolenaar 	    if (enc_utf8)
11494fa11757SBram Moolenaar 	    {
11504fa11757SBram Moolenaar 		if (ch >= 0x80)
11514fa11757SBram Moolenaar 		{
11524fa11757SBram Moolenaar 		    ScreenLinesUC[idx] = ch;
11534fa11757SBram Moolenaar 		    ScreenLinesC[0][idx] = 0;
11544fa11757SBram Moolenaar 		    ScreenLines[idx] = 0x80;
11554fa11757SBram Moolenaar 		}
11564fa11757SBram Moolenaar 		else
11574fa11757SBram Moolenaar 		{
11584fa11757SBram Moolenaar 		    ScreenLines[idx] = ch;
11594fa11757SBram Moolenaar 		    ScreenLinesUC[idx] = 0;
11604fa11757SBram Moolenaar 		}
11614fa11757SBram Moolenaar 	    }
11624fa11757SBram Moolenaar 	    else
11634fa11757SBram Moolenaar 		ScreenLines[idx] = ch;
11644fa11757SBram Moolenaar 	}
11654fa11757SBram Moolenaar 
11664fa11757SBram Moolenaar 	RL_MEMSET(col, HL_ATTR(HLF_FC), fdc);
11674fa11757SBram Moolenaar 	col += fdc;
11684fa11757SBram Moolenaar     }
11694fa11757SBram Moolenaar 
11707528d1f6SBram Moolenaar     // Set all attributes of the 'number' or 'relativenumber' column and the
11717528d1f6SBram Moolenaar     // text
11727528d1f6SBram Moolenaar     RL_MEMSET(col, HL_ATTR(HLF_FL), wp->w_width - col);
11737528d1f6SBram Moolenaar 
11747528d1f6SBram Moolenaar #ifdef FEAT_SIGNS
11757528d1f6SBram Moolenaar     // If signs are being displayed, add two spaces.
11767528d1f6SBram Moolenaar     if (signcolumn_on(wp))
11777528d1f6SBram Moolenaar     {
11787528d1f6SBram Moolenaar 	len = wp->w_width - col;
11797528d1f6SBram Moolenaar 	if (len > 0)
11807528d1f6SBram Moolenaar 	{
11817528d1f6SBram Moolenaar 	    if (len > 2)
11827528d1f6SBram Moolenaar 		len = 2;
11837528d1f6SBram Moolenaar # ifdef FEAT_RIGHTLEFT
11847528d1f6SBram Moolenaar 	    if (wp->w_p_rl)
11857528d1f6SBram Moolenaar 		// the line number isn't reversed
11867528d1f6SBram Moolenaar 		copy_text_attr(off + wp->w_width - len - col,
11877528d1f6SBram Moolenaar 					(char_u *)"  ", len, HL_ATTR(HLF_FL));
11887528d1f6SBram Moolenaar 	    else
11897528d1f6SBram Moolenaar # endif
11907528d1f6SBram Moolenaar 		copy_text_attr(off + col, (char_u *)"  ", len, HL_ATTR(HLF_FL));
11917528d1f6SBram Moolenaar 	    col += len;
11927528d1f6SBram Moolenaar 	}
11937528d1f6SBram Moolenaar     }
11947528d1f6SBram Moolenaar #endif
11957528d1f6SBram Moolenaar 
11967528d1f6SBram Moolenaar     // 3. Add the 'number' or 'relativenumber' column
11977528d1f6SBram Moolenaar     if (wp->w_p_nu || wp->w_p_rnu)
11987528d1f6SBram Moolenaar     {
11997528d1f6SBram Moolenaar 	len = wp->w_width - col;
12007528d1f6SBram Moolenaar 	if (len > 0)
12017528d1f6SBram Moolenaar 	{
12027528d1f6SBram Moolenaar 	    int	    w = number_width(wp);
12037528d1f6SBram Moolenaar 	    long    num;
12047528d1f6SBram Moolenaar 	    char    *fmt = "%*ld ";
12057528d1f6SBram Moolenaar 
12067528d1f6SBram Moolenaar 	    if (len > w + 1)
12077528d1f6SBram Moolenaar 		len = w + 1;
12087528d1f6SBram Moolenaar 
12097528d1f6SBram Moolenaar 	    if (wp->w_p_nu && !wp->w_p_rnu)
12107528d1f6SBram Moolenaar 		// 'number' + 'norelativenumber'
12117528d1f6SBram Moolenaar 		num = (long)lnum;
12127528d1f6SBram Moolenaar 	    else
12137528d1f6SBram Moolenaar 	    {
12147528d1f6SBram Moolenaar 		// 'relativenumber', don't use negative numbers
12157528d1f6SBram Moolenaar 		num = labs((long)get_cursor_rel_lnum(wp, lnum));
12167528d1f6SBram Moolenaar 		if (num == 0 && wp->w_p_nu && wp->w_p_rnu)
12177528d1f6SBram Moolenaar 		{
12187528d1f6SBram Moolenaar 		    // 'number' + 'relativenumber': cursor line shows absolute
12197528d1f6SBram Moolenaar 		    // line number
12207528d1f6SBram Moolenaar 		    num = lnum;
12217528d1f6SBram Moolenaar 		    fmt = "%-*ld ";
12227528d1f6SBram Moolenaar 		}
12237528d1f6SBram Moolenaar 	    }
12247528d1f6SBram Moolenaar 
12257528d1f6SBram Moolenaar 	    sprintf((char *)buf, fmt, w, num);
12267528d1f6SBram Moolenaar #ifdef FEAT_RIGHTLEFT
12277528d1f6SBram Moolenaar 	    if (wp->w_p_rl)
12287528d1f6SBram Moolenaar 		// the line number isn't reversed
12297528d1f6SBram Moolenaar 		copy_text_attr(off + wp->w_width - len - col, buf, len,
12307528d1f6SBram Moolenaar 							     HL_ATTR(HLF_FL));
12317528d1f6SBram Moolenaar 	    else
12327528d1f6SBram Moolenaar #endif
12337528d1f6SBram Moolenaar 		copy_text_attr(off + col, buf, len, HL_ATTR(HLF_FL));
12347528d1f6SBram Moolenaar 	    col += len;
12357528d1f6SBram Moolenaar 	}
12367528d1f6SBram Moolenaar     }
12377528d1f6SBram Moolenaar 
12387528d1f6SBram Moolenaar     // 4. Compose the folded-line string with 'foldtext', if set.
12397528d1f6SBram Moolenaar     text = get_foldtext(wp, lnum, lnume, foldinfo, buf);
12407528d1f6SBram Moolenaar 
12417528d1f6SBram Moolenaar     txtcol = col;	// remember where text starts
12427528d1f6SBram Moolenaar 
12437528d1f6SBram Moolenaar     // 5. move the text to current_ScreenLine.  Fill up with "fill_fold".
12447528d1f6SBram Moolenaar     //    Right-left text is put in columns 0 - number-col, normal text is put
12457528d1f6SBram Moolenaar     //    in columns number-col - window-width.
12467528d1f6SBram Moolenaar     col = text_to_screenline(wp, text, col);
12477528d1f6SBram Moolenaar 
12487528d1f6SBram Moolenaar     // Fill the rest of the line with the fold filler
12497528d1f6SBram Moolenaar #ifdef FEAT_RIGHTLEFT
12507528d1f6SBram Moolenaar     if (wp->w_p_rl)
12517528d1f6SBram Moolenaar 	col -= txtcol;
12527528d1f6SBram Moolenaar #endif
12537528d1f6SBram Moolenaar     while (col < wp->w_width
12547528d1f6SBram Moolenaar #ifdef FEAT_RIGHTLEFT
12557528d1f6SBram Moolenaar 		    - (wp->w_p_rl ? txtcol : 0)
12567528d1f6SBram Moolenaar #endif
12577528d1f6SBram Moolenaar 	    )
12587528d1f6SBram Moolenaar     {
12597528d1f6SBram Moolenaar 	if (enc_utf8)
12607528d1f6SBram Moolenaar 	{
12617528d1f6SBram Moolenaar 	    if (fill_fold >= 0x80)
12627528d1f6SBram Moolenaar 	    {
12637528d1f6SBram Moolenaar 		ScreenLinesUC[off + col] = fill_fold;
12647528d1f6SBram Moolenaar 		ScreenLinesC[0][off + col] = 0;
12657528d1f6SBram Moolenaar 		ScreenLines[off + col] = 0x80; // avoid storing zero
12667528d1f6SBram Moolenaar 	    }
12677528d1f6SBram Moolenaar 	    else
12687528d1f6SBram Moolenaar 	    {
12697528d1f6SBram Moolenaar 		ScreenLinesUC[off + col] = 0;
12707528d1f6SBram Moolenaar 		ScreenLines[off + col] = fill_fold;
12717528d1f6SBram Moolenaar 	    }
12727528d1f6SBram Moolenaar 	    col++;
12737528d1f6SBram Moolenaar 	}
12747528d1f6SBram Moolenaar 	else
12757528d1f6SBram Moolenaar 	    ScreenLines[off + col++] = fill_fold;
12767528d1f6SBram Moolenaar     }
12777528d1f6SBram Moolenaar 
12787528d1f6SBram Moolenaar     if (text != buf)
12797528d1f6SBram Moolenaar 	vim_free(text);
12807528d1f6SBram Moolenaar 
12817528d1f6SBram Moolenaar     // 6. set highlighting for the Visual area an other text.
12827528d1f6SBram Moolenaar     // If all folded lines are in the Visual area, highlight the line.
12837528d1f6SBram Moolenaar     if (VIsual_active && wp->w_buffer == curwin->w_buffer)
12847528d1f6SBram Moolenaar     {
12857528d1f6SBram Moolenaar 	if (LTOREQ_POS(curwin->w_cursor, VIsual))
12867528d1f6SBram Moolenaar 	{
12877528d1f6SBram Moolenaar 	    // Visual is after curwin->w_cursor
12887528d1f6SBram Moolenaar 	    top = &curwin->w_cursor;
12897528d1f6SBram Moolenaar 	    bot = &VIsual;
12907528d1f6SBram Moolenaar 	}
12917528d1f6SBram Moolenaar 	else
12927528d1f6SBram Moolenaar 	{
12937528d1f6SBram Moolenaar 	    // Visual is before curwin->w_cursor
12947528d1f6SBram Moolenaar 	    top = &VIsual;
12957528d1f6SBram Moolenaar 	    bot = &curwin->w_cursor;
12967528d1f6SBram Moolenaar 	}
12977528d1f6SBram Moolenaar 	if (lnum >= top->lnum
12987528d1f6SBram Moolenaar 		&& lnume <= bot->lnum
12997528d1f6SBram Moolenaar 		&& (VIsual_mode != 'v'
13007528d1f6SBram Moolenaar 		    || ((lnum > top->lnum
13017528d1f6SBram Moolenaar 			    || (lnum == top->lnum
13027528d1f6SBram Moolenaar 				&& top->col == 0))
13037528d1f6SBram Moolenaar 			&& (lnume < bot->lnum
13047528d1f6SBram Moolenaar 			    || (lnume == bot->lnum
13057528d1f6SBram Moolenaar 				&& (bot->col - (*p_sel == 'e'))
13067528d1f6SBram Moolenaar 		>= (colnr_T)STRLEN(ml_get_buf(wp->w_buffer, lnume, FALSE)))))))
13077528d1f6SBram Moolenaar 	{
13087528d1f6SBram Moolenaar 	    if (VIsual_mode == Ctrl_V)
13097528d1f6SBram Moolenaar 	    {
13107528d1f6SBram Moolenaar 		// Visual block mode: highlight the chars part of the block
13117528d1f6SBram Moolenaar 		if (wp->w_old_cursor_fcol + txtcol < (colnr_T)wp->w_width)
13127528d1f6SBram Moolenaar 		{
13137528d1f6SBram Moolenaar 		    if (wp->w_old_cursor_lcol != MAXCOL
13147528d1f6SBram Moolenaar 			     && wp->w_old_cursor_lcol + txtcol
13157528d1f6SBram Moolenaar 						       < (colnr_T)wp->w_width)
13167528d1f6SBram Moolenaar 			len = wp->w_old_cursor_lcol;
13177528d1f6SBram Moolenaar 		    else
13187528d1f6SBram Moolenaar 			len = wp->w_width - txtcol;
13197528d1f6SBram Moolenaar 		    RL_MEMSET(wp->w_old_cursor_fcol + txtcol, HL_ATTR(HLF_V),
13207528d1f6SBram Moolenaar 					    len - (int)wp->w_old_cursor_fcol);
13217528d1f6SBram Moolenaar 		}
13227528d1f6SBram Moolenaar 	    }
13237528d1f6SBram Moolenaar 	    else
13247528d1f6SBram Moolenaar 	    {
13257528d1f6SBram Moolenaar 		// Set all attributes of the text
13267528d1f6SBram Moolenaar 		RL_MEMSET(txtcol, HL_ATTR(HLF_V), wp->w_width - txtcol);
13277528d1f6SBram Moolenaar 	    }
13287528d1f6SBram Moolenaar 	}
13297528d1f6SBram Moolenaar     }
13307528d1f6SBram Moolenaar 
13317528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
13327528d1f6SBram Moolenaar     // Show colorcolumn in the fold line, but let cursorcolumn override it.
13337528d1f6SBram Moolenaar     if (wp->w_p_cc_cols)
13347528d1f6SBram Moolenaar     {
13357528d1f6SBram Moolenaar 	int i = 0;
13367528d1f6SBram Moolenaar 	int j = wp->w_p_cc_cols[i];
13377528d1f6SBram Moolenaar 	int old_txtcol = txtcol;
13387528d1f6SBram Moolenaar 
13397528d1f6SBram Moolenaar 	while (j > -1)
13407528d1f6SBram Moolenaar 	{
13417528d1f6SBram Moolenaar 	    txtcol += j;
13427528d1f6SBram Moolenaar 	    if (wp->w_p_wrap)
13437528d1f6SBram Moolenaar 		txtcol -= wp->w_skipcol;
13447528d1f6SBram Moolenaar 	    else
13457528d1f6SBram Moolenaar 		txtcol -= wp->w_leftcol;
13467528d1f6SBram Moolenaar 	    if (txtcol >= 0 && txtcol < wp->w_width)
13477528d1f6SBram Moolenaar 		ScreenAttrs[off + txtcol] = hl_combine_attr(
13487528d1f6SBram Moolenaar 				    ScreenAttrs[off + txtcol], HL_ATTR(HLF_MC));
13497528d1f6SBram Moolenaar 	    txtcol = old_txtcol;
13507528d1f6SBram Moolenaar 	    j = wp->w_p_cc_cols[++i];
13517528d1f6SBram Moolenaar 	}
13527528d1f6SBram Moolenaar     }
13537528d1f6SBram Moolenaar 
13547528d1f6SBram Moolenaar     // Show 'cursorcolumn' in the fold line.
13557528d1f6SBram Moolenaar     if (wp->w_p_cuc)
13567528d1f6SBram Moolenaar     {
13577528d1f6SBram Moolenaar 	txtcol += wp->w_virtcol;
13587528d1f6SBram Moolenaar 	if (wp->w_p_wrap)
13597528d1f6SBram Moolenaar 	    txtcol -= wp->w_skipcol;
13607528d1f6SBram Moolenaar 	else
13617528d1f6SBram Moolenaar 	    txtcol -= wp->w_leftcol;
13627528d1f6SBram Moolenaar 	if (txtcol >= 0 && txtcol < wp->w_width)
13637528d1f6SBram Moolenaar 	    ScreenAttrs[off + txtcol] = hl_combine_attr(
13647528d1f6SBram Moolenaar 				 ScreenAttrs[off + txtcol], HL_ATTR(HLF_CUC));
13657528d1f6SBram Moolenaar     }
13667528d1f6SBram Moolenaar #endif
13677528d1f6SBram Moolenaar 
13687528d1f6SBram Moolenaar     screen_line(row + W_WINROW(wp), wp->w_wincol, (int)wp->w_width,
13697528d1f6SBram Moolenaar 						     (int)wp->w_width, 0);
13707528d1f6SBram Moolenaar 
13717528d1f6SBram Moolenaar     // Update w_cline_height and w_cline_folded if the cursor line was
13727528d1f6SBram Moolenaar     // updated (saves a call to plines() later).
13737528d1f6SBram Moolenaar     if (wp == curwin
13747528d1f6SBram Moolenaar 	    && lnum <= curwin->w_cursor.lnum
13757528d1f6SBram Moolenaar 	    && lnume >= curwin->w_cursor.lnum)
13767528d1f6SBram Moolenaar     {
13777528d1f6SBram Moolenaar 	curwin->w_cline_row = row;
13787528d1f6SBram Moolenaar 	curwin->w_cline_height = 1;
13797528d1f6SBram Moolenaar 	curwin->w_cline_folded = TRUE;
13807528d1f6SBram Moolenaar 	curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
13817528d1f6SBram Moolenaar     }
138200aaa512SBram Moolenaar 
138300aaa512SBram Moolenaar # ifdef FEAT_CONCEAL
138400aaa512SBram Moolenaar     // When the line was not folded w_wrow may have been set, recompute it.
13855cb09620SBram Moolenaar     if (wp == curwin
13865cb09620SBram Moolenaar 	    && wp->w_cursor.lnum >= lnum
13875cb09620SBram Moolenaar 	    && wp->w_cursor.lnum <= lnume
13885cb09620SBram Moolenaar 	    && conceal_cursor_line(wp))
138900aaa512SBram Moolenaar 	curs_columns(TRUE);
139000aaa512SBram Moolenaar # endif
13917528d1f6SBram Moolenaar }
13927528d1f6SBram Moolenaar #endif
13937528d1f6SBram Moolenaar 
13947528d1f6SBram Moolenaar /*
13957528d1f6SBram Moolenaar  * Update a single window.
13967528d1f6SBram Moolenaar  *
13977528d1f6SBram Moolenaar  * This may cause the windows below it also to be redrawn (when clearing the
13987528d1f6SBram Moolenaar  * screen or scrolling lines).
13997528d1f6SBram Moolenaar  *
14007528d1f6SBram Moolenaar  * How the window is redrawn depends on wp->w_redr_type.  Each type also
14017528d1f6SBram Moolenaar  * implies the one below it.
14027528d1f6SBram Moolenaar  * NOT_VALID	redraw the whole window
14037528d1f6SBram Moolenaar  * SOME_VALID	redraw the whole window but do scroll when possible
14047528d1f6SBram Moolenaar  * REDRAW_TOP	redraw the top w_upd_rows window lines, otherwise like VALID
14057528d1f6SBram Moolenaar  * INVERTED	redraw the changed part of the Visual area
14067528d1f6SBram Moolenaar  * INVERTED_ALL	redraw the whole Visual area
14077528d1f6SBram Moolenaar  * VALID	1. scroll up/down to adjust for a changed w_topline
14087528d1f6SBram Moolenaar  *		2. update lines at the top when scrolled down
14097528d1f6SBram Moolenaar  *		3. redraw changed text:
14107528d1f6SBram Moolenaar  *		   - if wp->w_buffer->b_mod_set set, update lines between
14117528d1f6SBram Moolenaar  *		     b_mod_top and b_mod_bot.
14127528d1f6SBram Moolenaar  *		   - if wp->w_redraw_top non-zero, redraw lines between
14137528d1f6SBram Moolenaar  *		     wp->w_redraw_top and wp->w_redr_bot.
14147528d1f6SBram Moolenaar  *		   - continue redrawing when syntax status is invalid.
14157528d1f6SBram Moolenaar  *		4. if scrolled up, update lines at the bottom.
14167528d1f6SBram Moolenaar  * This results in three areas that may need updating:
14177528d1f6SBram Moolenaar  * top:	from first row to top_end (when scrolled down)
14187528d1f6SBram Moolenaar  * mid: from mid_start to mid_end (update inversion or changed text)
14197528d1f6SBram Moolenaar  * bot: from bot_start to last row (when scrolled up)
14207528d1f6SBram Moolenaar  */
14217528d1f6SBram Moolenaar     static void
win_update(win_T * wp)14227528d1f6SBram Moolenaar win_update(win_T *wp)
14237528d1f6SBram Moolenaar {
14247528d1f6SBram Moolenaar     buf_T	*buf = wp->w_buffer;
14257528d1f6SBram Moolenaar     int		type;
14267528d1f6SBram Moolenaar     int		top_end = 0;	// Below last row of the top area that needs
14277528d1f6SBram Moolenaar 				// updating.  0 when no top area updating.
14287528d1f6SBram Moolenaar     int		mid_start = 999;// first row of the mid area that needs
14297528d1f6SBram Moolenaar 				// updating.  999 when no mid area updating.
14307528d1f6SBram Moolenaar     int		mid_end = 0;	// Below last row of the mid area that needs
14317528d1f6SBram Moolenaar 				// updating.  0 when no mid area updating.
14327528d1f6SBram Moolenaar     int		bot_start = 999;// first row of the bot area that needs
14337528d1f6SBram Moolenaar 				// updating.  999 when no bot area updating
14347528d1f6SBram Moolenaar     int		scrolled_down = FALSE;	// TRUE when scrolled down when
14357528d1f6SBram Moolenaar 					// w_topline got smaller a bit
14367528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
14377528d1f6SBram Moolenaar     int		top_to_mod = FALSE;    // redraw above mod_top
14387528d1f6SBram Moolenaar #endif
14397528d1f6SBram Moolenaar 
14407528d1f6SBram Moolenaar     int		row;		// current window row to display
14417528d1f6SBram Moolenaar     linenr_T	lnum;		// current buffer lnum to display
14427528d1f6SBram Moolenaar     int		idx;		// current index in w_lines[]
14437528d1f6SBram Moolenaar     int		srow;		// starting row of the current line
14447528d1f6SBram Moolenaar 
14457528d1f6SBram Moolenaar     int		eof = FALSE;	// if TRUE, we hit the end of the file
14467528d1f6SBram Moolenaar     int		didline = FALSE; // if TRUE, we finished the last line
14477528d1f6SBram Moolenaar     int		i;
14487528d1f6SBram Moolenaar     long	j;
14497528d1f6SBram Moolenaar     static int	recursive = FALSE;	// being called recursively
1450cbee635eSBram Moolenaar     linenr_T	old_botline = wp->w_botline;
1451cbee635eSBram Moolenaar #ifdef FEAT_CONCEAL
1452cbee635eSBram Moolenaar     int		old_wrow = wp->w_wrow;
1453cbee635eSBram Moolenaar     int		old_wcol = wp->w_wcol;
1454cbee635eSBram Moolenaar #endif
14557528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
14567528d1f6SBram Moolenaar     long	fold_count;
14577528d1f6SBram Moolenaar #endif
14587528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
14597528d1f6SBram Moolenaar     // remember what happened to the previous line, to know if
14607528d1f6SBram Moolenaar     // check_visual_highlight() can be used
14617528d1f6SBram Moolenaar #define DID_NONE 1	// didn't update a line
14627528d1f6SBram Moolenaar #define DID_LINE 2	// updated a normal line
14637528d1f6SBram Moolenaar #define DID_FOLD 3	// updated a folded line
14647528d1f6SBram Moolenaar     int		did_update = DID_NONE;
14657528d1f6SBram Moolenaar     linenr_T	syntax_last_parsed = 0;		// last parsed text line
14667528d1f6SBram Moolenaar #endif
14677528d1f6SBram Moolenaar     linenr_T	mod_top = 0;
14687528d1f6SBram Moolenaar     linenr_T	mod_bot = 0;
14697528d1f6SBram Moolenaar #if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA)
14707528d1f6SBram Moolenaar     int		save_got_int;
14717528d1f6SBram Moolenaar #endif
14727528d1f6SBram Moolenaar #ifdef SYN_TIME_LIMIT
14737528d1f6SBram Moolenaar     proftime_T	syntax_tm;
14747528d1f6SBram Moolenaar #endif
14757528d1f6SBram Moolenaar 
1476e52e0c89SBram Moolenaar #if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
1477e52e0c89SBram Moolenaar     // This needs to be done only for the first window when update_screen() is
1478e52e0c89SBram Moolenaar     // called.
1479e52e0c89SBram Moolenaar     if (!did_update_one_window)
1480e52e0c89SBram Moolenaar     {
1481e52e0c89SBram Moolenaar 	did_update_one_window = TRUE;
1482e52e0c89SBram Moolenaar # ifdef FEAT_SEARCH_EXTRA
1483e52e0c89SBram Moolenaar 	start_search_hl();
1484e52e0c89SBram Moolenaar # endif
1485e52e0c89SBram Moolenaar # ifdef FEAT_CLIPBOARD
1486e52e0c89SBram Moolenaar 	// When Visual area changed, may have to update selection.
1487e52e0c89SBram Moolenaar 	if (clip_star.available && clip_isautosel_star())
1488e52e0c89SBram Moolenaar 	    clip_update_selection(&clip_star);
1489e52e0c89SBram Moolenaar 	if (clip_plus.available && clip_isautosel_plus())
1490e52e0c89SBram Moolenaar 	    clip_update_selection(&clip_plus);
1491e52e0c89SBram Moolenaar # endif
1492e52e0c89SBram Moolenaar     }
1493e52e0c89SBram Moolenaar #endif
1494e52e0c89SBram Moolenaar 
14957528d1f6SBram Moolenaar     type = wp->w_redr_type;
14967528d1f6SBram Moolenaar 
14977528d1f6SBram Moolenaar     if (type == NOT_VALID)
14987528d1f6SBram Moolenaar     {
14997528d1f6SBram Moolenaar 	wp->w_redr_status = TRUE;
15007528d1f6SBram Moolenaar 	wp->w_lines_valid = 0;
15017528d1f6SBram Moolenaar     }
15027528d1f6SBram Moolenaar 
1503ae0f151dSBram Moolenaar     // Window frame is zero-height: nothing to draw.
1504ae0f151dSBram Moolenaar     if (wp->w_height + WINBAR_HEIGHT(wp) == 0
1505ae0f151dSBram Moolenaar 	    || (wp->w_frame->fr_height == wp->w_status_height
1506ae0f151dSBram Moolenaar #if defined(FEAT_PROP_POPUP)
1507ae0f151dSBram Moolenaar 		&& !popup_is_popup(wp)
1508ae0f151dSBram Moolenaar #endif
1509ae0f151dSBram Moolenaar 	       ))
15107528d1f6SBram Moolenaar     {
15117528d1f6SBram Moolenaar 	wp->w_redr_type = 0;
15127528d1f6SBram Moolenaar 	return;
15137528d1f6SBram Moolenaar     }
15147528d1f6SBram Moolenaar 
15157528d1f6SBram Moolenaar     // Window is zero-width: Only need to draw the separator.
15167528d1f6SBram Moolenaar     if (wp->w_width == 0)
15177528d1f6SBram Moolenaar     {
15187528d1f6SBram Moolenaar 	// draw the vertical separator right of this window
15197528d1f6SBram Moolenaar 	draw_vsep_win(wp, 0);
15207528d1f6SBram Moolenaar 	wp->w_redr_type = 0;
15217528d1f6SBram Moolenaar 	return;
15227528d1f6SBram Moolenaar     }
15237528d1f6SBram Moolenaar 
15247528d1f6SBram Moolenaar #ifdef FEAT_TERMINAL
15257528d1f6SBram Moolenaar     // If this window contains a terminal, redraw works completely differently.
15267528d1f6SBram Moolenaar     if (term_do_update_window(wp))
15277528d1f6SBram Moolenaar     {
15287528d1f6SBram Moolenaar 	term_update_window(wp);
15297528d1f6SBram Moolenaar # ifdef FEAT_MENU
15307528d1f6SBram Moolenaar 	// Draw the window toolbar, if there is one.
15317528d1f6SBram Moolenaar 	if (winbar_height(wp) > 0)
15327528d1f6SBram Moolenaar 	    redraw_win_toolbar(wp);
15337528d1f6SBram Moolenaar # endif
15347528d1f6SBram Moolenaar 	wp->w_redr_type = 0;
15357528d1f6SBram Moolenaar 	return;
15367528d1f6SBram Moolenaar     }
15377528d1f6SBram Moolenaar #endif
15387528d1f6SBram Moolenaar 
15397528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
15407528d1f6SBram Moolenaar     init_search_hl(wp, &screen_search_hl);
15417528d1f6SBram Moolenaar #endif
15427528d1f6SBram Moolenaar 
15437528d1f6SBram Moolenaar #ifdef FEAT_LINEBREAK
15447528d1f6SBram Moolenaar     // Force redraw when width of 'number' or 'relativenumber' column
15457528d1f6SBram Moolenaar     // changes.
15467528d1f6SBram Moolenaar     i = (wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) : 0;
15477528d1f6SBram Moolenaar     if (wp->w_nrwidth != i)
15487528d1f6SBram Moolenaar     {
15497528d1f6SBram Moolenaar 	type = NOT_VALID;
15507528d1f6SBram Moolenaar 	wp->w_nrwidth = i;
15517528d1f6SBram Moolenaar     }
15527528d1f6SBram Moolenaar     else
15537528d1f6SBram Moolenaar #endif
15547528d1f6SBram Moolenaar 
15557528d1f6SBram Moolenaar     if (buf->b_mod_set && buf->b_mod_xlines != 0 && wp->w_redraw_top != 0)
15567528d1f6SBram Moolenaar     {
15577528d1f6SBram Moolenaar 	// When there are both inserted/deleted lines and specific lines to be
15587528d1f6SBram Moolenaar 	// redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw
15597528d1f6SBram Moolenaar 	// everything (only happens when redrawing is off for while).
15607528d1f6SBram Moolenaar 	type = NOT_VALID;
15617528d1f6SBram Moolenaar     }
15627528d1f6SBram Moolenaar     else
15637528d1f6SBram Moolenaar     {
15647528d1f6SBram Moolenaar 	// Set mod_top to the first line that needs displaying because of
15657528d1f6SBram Moolenaar 	// changes.  Set mod_bot to the first line after the changes.
15667528d1f6SBram Moolenaar 	mod_top = wp->w_redraw_top;
15677528d1f6SBram Moolenaar 	if (wp->w_redraw_bot != 0)
15687528d1f6SBram Moolenaar 	    mod_bot = wp->w_redraw_bot + 1;
15697528d1f6SBram Moolenaar 	else
15707528d1f6SBram Moolenaar 	    mod_bot = 0;
15717528d1f6SBram Moolenaar 	if (buf->b_mod_set)
15727528d1f6SBram Moolenaar 	{
15737528d1f6SBram Moolenaar 	    if (mod_top == 0 || mod_top > buf->b_mod_top)
15747528d1f6SBram Moolenaar 	    {
15757528d1f6SBram Moolenaar 		mod_top = buf->b_mod_top;
15767528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
15777528d1f6SBram Moolenaar 		// Need to redraw lines above the change that may be included
15787528d1f6SBram Moolenaar 		// in a pattern match.
15797528d1f6SBram Moolenaar 		if (syntax_present(wp))
15807528d1f6SBram Moolenaar 		{
15817528d1f6SBram Moolenaar 		    mod_top -= buf->b_s.b_syn_sync_linebreaks;
15827528d1f6SBram Moolenaar 		    if (mod_top < 1)
15837528d1f6SBram Moolenaar 			mod_top = 1;
15847528d1f6SBram Moolenaar 		}
15857528d1f6SBram Moolenaar #endif
15867528d1f6SBram Moolenaar 	    }
15877528d1f6SBram Moolenaar 	    if (mod_bot == 0 || mod_bot < buf->b_mod_bot)
15887528d1f6SBram Moolenaar 		mod_bot = buf->b_mod_bot;
15897528d1f6SBram Moolenaar 
15907528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
15917528d1f6SBram Moolenaar 	    // When 'hlsearch' is on and using a multi-line search pattern, a
15927528d1f6SBram Moolenaar 	    // change in one line may make the Search highlighting in a
15937528d1f6SBram Moolenaar 	    // previous line invalid.  Simple solution: redraw all visible
15947528d1f6SBram Moolenaar 	    // lines above the change.
15957528d1f6SBram Moolenaar 	    // Same for a match pattern.
15967528d1f6SBram Moolenaar 	    if (screen_search_hl.rm.regprog != NULL
15977528d1f6SBram Moolenaar 		    && re_multiline(screen_search_hl.rm.regprog))
15987528d1f6SBram Moolenaar 		top_to_mod = TRUE;
15997528d1f6SBram Moolenaar 	    else
16007528d1f6SBram Moolenaar 	    {
16017528d1f6SBram Moolenaar 		matchitem_T *cur = wp->w_match_head;
16027528d1f6SBram Moolenaar 
16037528d1f6SBram Moolenaar 		while (cur != NULL)
16047528d1f6SBram Moolenaar 		{
16057528d1f6SBram Moolenaar 		    if (cur->match.regprog != NULL
16067528d1f6SBram Moolenaar 					   && re_multiline(cur->match.regprog))
16077528d1f6SBram Moolenaar 		    {
16087528d1f6SBram Moolenaar 			top_to_mod = TRUE;
16097528d1f6SBram Moolenaar 			break;
16107528d1f6SBram Moolenaar 		    }
16117528d1f6SBram Moolenaar 		    cur = cur->next;
16127528d1f6SBram Moolenaar 		}
16137528d1f6SBram Moolenaar 	    }
16147528d1f6SBram Moolenaar #endif
16157528d1f6SBram Moolenaar 	}
16167528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
16177528d1f6SBram Moolenaar 	if (mod_top != 0 && hasAnyFolding(wp))
16187528d1f6SBram Moolenaar 	{
16197528d1f6SBram Moolenaar 	    linenr_T	lnumt, lnumb;
16207528d1f6SBram Moolenaar 
16217528d1f6SBram Moolenaar 	    // A change in a line can cause lines above it to become folded or
16227528d1f6SBram Moolenaar 	    // unfolded.  Find the top most buffer line that may be affected.
16237528d1f6SBram Moolenaar 	    // If the line was previously folded and displayed, get the first
16247528d1f6SBram Moolenaar 	    // line of that fold.  If the line is folded now, get the first
16257528d1f6SBram Moolenaar 	    // folded line.  Use the minimum of these two.
16267528d1f6SBram Moolenaar 
16277528d1f6SBram Moolenaar 	    // Find last valid w_lines[] entry above mod_top.  Set lnumt to
16287528d1f6SBram Moolenaar 	    // the line below it.  If there is no valid entry, use w_topline.
16297528d1f6SBram Moolenaar 	    // Find the first valid w_lines[] entry below mod_bot.  Set lnumb
16307528d1f6SBram Moolenaar 	    // to this line.  If there is no valid entry, use MAXLNUM.
16317528d1f6SBram Moolenaar 	    lnumt = wp->w_topline;
16327528d1f6SBram Moolenaar 	    lnumb = MAXLNUM;
16337528d1f6SBram Moolenaar 	    for (i = 0; i < wp->w_lines_valid; ++i)
16347528d1f6SBram Moolenaar 		if (wp->w_lines[i].wl_valid)
16357528d1f6SBram Moolenaar 		{
16367528d1f6SBram Moolenaar 		    if (wp->w_lines[i].wl_lastlnum < mod_top)
16377528d1f6SBram Moolenaar 			lnumt = wp->w_lines[i].wl_lastlnum + 1;
16387528d1f6SBram Moolenaar 		    if (lnumb == MAXLNUM && wp->w_lines[i].wl_lnum >= mod_bot)
16397528d1f6SBram Moolenaar 		    {
16407528d1f6SBram Moolenaar 			lnumb = wp->w_lines[i].wl_lnum;
16417528d1f6SBram Moolenaar 			// When there is a fold column it might need updating
16427528d1f6SBram Moolenaar 			// in the next line ("J" just above an open fold).
16437528d1f6SBram Moolenaar 			if (compute_foldcolumn(wp, 0) > 0)
16447528d1f6SBram Moolenaar 			    ++lnumb;
16457528d1f6SBram Moolenaar 		    }
16467528d1f6SBram Moolenaar 		}
16477528d1f6SBram Moolenaar 
16487528d1f6SBram Moolenaar 	    (void)hasFoldingWin(wp, mod_top, &mod_top, NULL, TRUE, NULL);
16497528d1f6SBram Moolenaar 	    if (mod_top > lnumt)
16507528d1f6SBram Moolenaar 		mod_top = lnumt;
16517528d1f6SBram Moolenaar 
16527528d1f6SBram Moolenaar 	    // Now do the same for the bottom line (one above mod_bot).
16537528d1f6SBram Moolenaar 	    --mod_bot;
16547528d1f6SBram Moolenaar 	    (void)hasFoldingWin(wp, mod_bot, NULL, &mod_bot, TRUE, NULL);
16557528d1f6SBram Moolenaar 	    ++mod_bot;
16567528d1f6SBram Moolenaar 	    if (mod_bot < lnumb)
16577528d1f6SBram Moolenaar 		mod_bot = lnumb;
16587528d1f6SBram Moolenaar 	}
16597528d1f6SBram Moolenaar #endif
16607528d1f6SBram Moolenaar 
16617528d1f6SBram Moolenaar 	// When a change starts above w_topline and the end is below
16627528d1f6SBram Moolenaar 	// w_topline, start redrawing at w_topline.
16637528d1f6SBram Moolenaar 	// If the end of the change is above w_topline: do like no change was
16647528d1f6SBram Moolenaar 	// made, but redraw the first line to find changes in syntax.
16657528d1f6SBram Moolenaar 	if (mod_top != 0 && mod_top < wp->w_topline)
16667528d1f6SBram Moolenaar 	{
16677528d1f6SBram Moolenaar 	    if (mod_bot > wp->w_topline)
16687528d1f6SBram Moolenaar 		mod_top = wp->w_topline;
16697528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
16707528d1f6SBram Moolenaar 	    else if (syntax_present(wp))
16717528d1f6SBram Moolenaar 		top_end = 1;
16727528d1f6SBram Moolenaar #endif
16737528d1f6SBram Moolenaar 	}
16747528d1f6SBram Moolenaar 
16757528d1f6SBram Moolenaar 	// When line numbers are displayed need to redraw all lines below
16767528d1f6SBram Moolenaar 	// inserted/deleted lines.
16777528d1f6SBram Moolenaar 	if (mod_top != 0 && buf->b_mod_xlines != 0 && wp->w_p_nu)
16787528d1f6SBram Moolenaar 	    mod_bot = MAXLNUM;
16797528d1f6SBram Moolenaar     }
16807528d1f6SBram Moolenaar     wp->w_redraw_top = 0;	// reset for next time
16817528d1f6SBram Moolenaar     wp->w_redraw_bot = 0;
16827528d1f6SBram Moolenaar 
16837528d1f6SBram Moolenaar     // When only displaying the lines at the top, set top_end.  Used when
16847528d1f6SBram Moolenaar     // window has scrolled down for msg_scrolled.
16857528d1f6SBram Moolenaar     if (type == REDRAW_TOP)
16867528d1f6SBram Moolenaar     {
16877528d1f6SBram Moolenaar 	j = 0;
16887528d1f6SBram Moolenaar 	for (i = 0; i < wp->w_lines_valid; ++i)
16897528d1f6SBram Moolenaar 	{
16907528d1f6SBram Moolenaar 	    j += wp->w_lines[i].wl_size;
16917528d1f6SBram Moolenaar 	    if (j >= wp->w_upd_rows)
16927528d1f6SBram Moolenaar 	    {
16937528d1f6SBram Moolenaar 		top_end = j;
16947528d1f6SBram Moolenaar 		break;
16957528d1f6SBram Moolenaar 	    }
16967528d1f6SBram Moolenaar 	}
16977528d1f6SBram Moolenaar 	if (top_end == 0)
16987528d1f6SBram Moolenaar 	    // not found (cannot happen?): redraw everything
16997528d1f6SBram Moolenaar 	    type = NOT_VALID;
17007528d1f6SBram Moolenaar 	else
17017528d1f6SBram Moolenaar 	    // top area defined, the rest is VALID
17027528d1f6SBram Moolenaar 	    type = VALID;
17037528d1f6SBram Moolenaar     }
17047528d1f6SBram Moolenaar 
17057528d1f6SBram Moolenaar     // Trick: we want to avoid clearing the screen twice.  screenclear() will
17067528d1f6SBram Moolenaar     // set "screen_cleared" to TRUE.  The special value MAYBE (which is still
17077528d1f6SBram Moolenaar     // non-zero and thus not FALSE) will indicate that screenclear() was not
17087528d1f6SBram Moolenaar     // called.
17097528d1f6SBram Moolenaar     if (screen_cleared)
17107528d1f6SBram Moolenaar 	screen_cleared = MAYBE;
17117528d1f6SBram Moolenaar 
17127528d1f6SBram Moolenaar     // If there are no changes on the screen that require a complete redraw,
17137528d1f6SBram Moolenaar     // handle three cases:
17147528d1f6SBram Moolenaar     // 1: we are off the top of the screen by a few lines: scroll down
17157528d1f6SBram Moolenaar     // 2: wp->w_topline is below wp->w_lines[0].wl_lnum: may scroll up
17167528d1f6SBram Moolenaar     // 3: wp->w_topline is wp->w_lines[0].wl_lnum: find first entry in
17177528d1f6SBram Moolenaar     //    w_lines[] that needs updating.
17187528d1f6SBram Moolenaar     if ((type == VALID || type == SOME_VALID
17197528d1f6SBram Moolenaar 				  || type == INVERTED || type == INVERTED_ALL)
17207528d1f6SBram Moolenaar #ifdef FEAT_DIFF
17217528d1f6SBram Moolenaar 	    && !wp->w_botfill && !wp->w_old_botfill
17227528d1f6SBram Moolenaar #endif
17237528d1f6SBram Moolenaar 	    )
17247528d1f6SBram Moolenaar     {
1725f8992d47SBram Moolenaar 	if (mod_top != 0
1726f8992d47SBram Moolenaar 		&& wp->w_topline == mod_top
1727f8992d47SBram Moolenaar 		&& (!wp->w_lines[0].wl_valid
17289dc1917fSBram Moolenaar 		    || wp->w_topline <= wp->w_lines[0].wl_lnum))
17297528d1f6SBram Moolenaar 	{
1730f8992d47SBram Moolenaar 	    // w_topline is the first changed line and window is not scrolled,
1731f8992d47SBram Moolenaar 	    // the scrolling from changed lines will be done further down.
17327528d1f6SBram Moolenaar 	}
17337528d1f6SBram Moolenaar 	else if (wp->w_lines[0].wl_valid
17347528d1f6SBram Moolenaar 		&& (wp->w_topline < wp->w_lines[0].wl_lnum
17357528d1f6SBram Moolenaar #ifdef FEAT_DIFF
17367528d1f6SBram Moolenaar 		    || (wp->w_topline == wp->w_lines[0].wl_lnum
17377528d1f6SBram Moolenaar 			&& wp->w_topfill > wp->w_old_topfill)
17387528d1f6SBram Moolenaar #endif
17397528d1f6SBram Moolenaar 		   ))
17407528d1f6SBram Moolenaar 	{
17417528d1f6SBram Moolenaar 	    // New topline is above old topline: May scroll down.
17427528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
17437528d1f6SBram Moolenaar 	    if (hasAnyFolding(wp))
17447528d1f6SBram Moolenaar 	    {
17457528d1f6SBram Moolenaar 		linenr_T ln;
17467528d1f6SBram Moolenaar 
17477528d1f6SBram Moolenaar 		// count the number of lines we are off, counting a sequence
17487528d1f6SBram Moolenaar 		// of folded lines as one
17497528d1f6SBram Moolenaar 		j = 0;
17507528d1f6SBram Moolenaar 		for (ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ++ln)
17517528d1f6SBram Moolenaar 		{
17527528d1f6SBram Moolenaar 		    ++j;
17537528d1f6SBram Moolenaar 		    if (j >= wp->w_height - 2)
17547528d1f6SBram Moolenaar 			break;
17557528d1f6SBram Moolenaar 		    (void)hasFoldingWin(wp, ln, NULL, &ln, TRUE, NULL);
17567528d1f6SBram Moolenaar 		}
17577528d1f6SBram Moolenaar 	    }
17587528d1f6SBram Moolenaar 	    else
17597528d1f6SBram Moolenaar #endif
17607528d1f6SBram Moolenaar 		j = wp->w_lines[0].wl_lnum - wp->w_topline;
17617528d1f6SBram Moolenaar 	    if (j < wp->w_height - 2)		// not too far off
17627528d1f6SBram Moolenaar 	    {
17637528d1f6SBram Moolenaar 		i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1);
17647528d1f6SBram Moolenaar #ifdef FEAT_DIFF
17657528d1f6SBram Moolenaar 		// insert extra lines for previously invisible filler lines
17667528d1f6SBram Moolenaar 		if (wp->w_lines[0].wl_lnum != wp->w_topline)
17677528d1f6SBram Moolenaar 		    i += diff_check_fill(wp, wp->w_lines[0].wl_lnum)
17687528d1f6SBram Moolenaar 							  - wp->w_old_topfill;
17697528d1f6SBram Moolenaar #endif
17707528d1f6SBram Moolenaar 		if (i < wp->w_height - 2)	// less than a screen off
17717528d1f6SBram Moolenaar 		{
17727528d1f6SBram Moolenaar 		    // Try to insert the correct number of lines.
17737528d1f6SBram Moolenaar 		    // If not the last window, delete the lines at the bottom.
17747528d1f6SBram Moolenaar 		    // win_ins_lines may fail when the terminal can't do it.
17757528d1f6SBram Moolenaar 		    if (i > 0)
17767528d1f6SBram Moolenaar 			check_for_delay(FALSE);
17777528d1f6SBram Moolenaar 		    if (win_ins_lines(wp, 0, i, FALSE, wp == firstwin) == OK)
17787528d1f6SBram Moolenaar 		    {
17797528d1f6SBram Moolenaar 			if (wp->w_lines_valid != 0)
17807528d1f6SBram Moolenaar 			{
17817528d1f6SBram Moolenaar 			    // Need to update rows that are new, stop at the
17827528d1f6SBram Moolenaar 			    // first one that scrolled down.
17837528d1f6SBram Moolenaar 			    top_end = i;
17847528d1f6SBram Moolenaar 			    scrolled_down = TRUE;
17857528d1f6SBram Moolenaar 
17867528d1f6SBram Moolenaar 			    // Move the entries that were scrolled, disable
17877528d1f6SBram Moolenaar 			    // the entries for the lines to be redrawn.
17887528d1f6SBram Moolenaar 			    if ((wp->w_lines_valid += j) > wp->w_height)
17897528d1f6SBram Moolenaar 				wp->w_lines_valid = wp->w_height;
17907528d1f6SBram Moolenaar 			    for (idx = wp->w_lines_valid; idx - j >= 0; idx--)
17917528d1f6SBram Moolenaar 				wp->w_lines[idx] = wp->w_lines[idx - j];
17927528d1f6SBram Moolenaar 			    while (idx >= 0)
17937528d1f6SBram Moolenaar 				wp->w_lines[idx--].wl_valid = FALSE;
17947528d1f6SBram Moolenaar 			}
17957528d1f6SBram Moolenaar 		    }
17967528d1f6SBram Moolenaar 		    else
17977528d1f6SBram Moolenaar 			mid_start = 0;		// redraw all lines
17987528d1f6SBram Moolenaar 		}
17997528d1f6SBram Moolenaar 		else
18007528d1f6SBram Moolenaar 		    mid_start = 0;		// redraw all lines
18017528d1f6SBram Moolenaar 	    }
18027528d1f6SBram Moolenaar 	    else
18037528d1f6SBram Moolenaar 		mid_start = 0;		// redraw all lines
18047528d1f6SBram Moolenaar 	}
18057528d1f6SBram Moolenaar 	else
18067528d1f6SBram Moolenaar 	{
18077528d1f6SBram Moolenaar 	    // New topline is at or below old topline: May scroll up.
18087528d1f6SBram Moolenaar 	    // When topline didn't change, find first entry in w_lines[] that
18097528d1f6SBram Moolenaar 	    // needs updating.
18107528d1f6SBram Moolenaar 
18117528d1f6SBram Moolenaar 	    // try to find wp->w_topline in wp->w_lines[].wl_lnum
18127528d1f6SBram Moolenaar 	    j = -1;
18137528d1f6SBram Moolenaar 	    row = 0;
18147528d1f6SBram Moolenaar 	    for (i = 0; i < wp->w_lines_valid; i++)
18157528d1f6SBram Moolenaar 	    {
18167528d1f6SBram Moolenaar 		if (wp->w_lines[i].wl_valid
18177528d1f6SBram Moolenaar 			&& wp->w_lines[i].wl_lnum == wp->w_topline)
18187528d1f6SBram Moolenaar 		{
18197528d1f6SBram Moolenaar 		    j = i;
18207528d1f6SBram Moolenaar 		    break;
18217528d1f6SBram Moolenaar 		}
18227528d1f6SBram Moolenaar 		row += wp->w_lines[i].wl_size;
18237528d1f6SBram Moolenaar 	    }
18247528d1f6SBram Moolenaar 	    if (j == -1)
18257528d1f6SBram Moolenaar 	    {
18267528d1f6SBram Moolenaar 		// if wp->w_topline is not in wp->w_lines[].wl_lnum redraw all
18277528d1f6SBram Moolenaar 		// lines
18287528d1f6SBram Moolenaar 		mid_start = 0;
18297528d1f6SBram Moolenaar 	    }
18307528d1f6SBram Moolenaar 	    else
18317528d1f6SBram Moolenaar 	    {
18327528d1f6SBram Moolenaar 		// Try to delete the correct number of lines.
18337528d1f6SBram Moolenaar 		// wp->w_topline is at wp->w_lines[i].wl_lnum.
18347528d1f6SBram Moolenaar #ifdef FEAT_DIFF
18357528d1f6SBram Moolenaar 		// If the topline didn't change, delete old filler lines,
18367528d1f6SBram Moolenaar 		// otherwise delete filler lines of the new topline...
18377528d1f6SBram Moolenaar 		if (wp->w_lines[0].wl_lnum == wp->w_topline)
18387528d1f6SBram Moolenaar 		    row += wp->w_old_topfill;
18397528d1f6SBram Moolenaar 		else
18407528d1f6SBram Moolenaar 		    row += diff_check_fill(wp, wp->w_topline);
18417528d1f6SBram Moolenaar 		// ... but don't delete new filler lines.
18427528d1f6SBram Moolenaar 		row -= wp->w_topfill;
18437528d1f6SBram Moolenaar #endif
18447528d1f6SBram Moolenaar 		if (row > 0)
18457528d1f6SBram Moolenaar 		{
18467528d1f6SBram Moolenaar 		    check_for_delay(FALSE);
18477528d1f6SBram Moolenaar 		    if (win_del_lines(wp, 0, row, FALSE, wp == firstwin, 0)
18487528d1f6SBram Moolenaar 									 == OK)
18497528d1f6SBram Moolenaar 			bot_start = wp->w_height - row;
18507528d1f6SBram Moolenaar 		    else
18517528d1f6SBram Moolenaar 			mid_start = 0;		// redraw all lines
18527528d1f6SBram Moolenaar 		}
18537528d1f6SBram Moolenaar 		if ((row == 0 || bot_start < 999) && wp->w_lines_valid != 0)
18547528d1f6SBram Moolenaar 		{
18557528d1f6SBram Moolenaar 		    // Skip the lines (below the deleted lines) that are still
18567528d1f6SBram Moolenaar 		    // valid and don't need redrawing.	Copy their info
18577528d1f6SBram Moolenaar 		    // upwards, to compensate for the deleted lines.  Set
18587528d1f6SBram Moolenaar 		    // bot_start to the first row that needs redrawing.
18597528d1f6SBram Moolenaar 		    bot_start = 0;
18607528d1f6SBram Moolenaar 		    idx = 0;
18617528d1f6SBram Moolenaar 		    for (;;)
18627528d1f6SBram Moolenaar 		    {
18637528d1f6SBram Moolenaar 			wp->w_lines[idx] = wp->w_lines[j];
18647528d1f6SBram Moolenaar 			// stop at line that didn't fit, unless it is still
18657528d1f6SBram Moolenaar 			// valid (no lines deleted)
18667528d1f6SBram Moolenaar 			if (row > 0 && bot_start + row
18677528d1f6SBram Moolenaar 				 + (int)wp->w_lines[j].wl_size > wp->w_height)
18687528d1f6SBram Moolenaar 			{
18697528d1f6SBram Moolenaar 			    wp->w_lines_valid = idx + 1;
18707528d1f6SBram Moolenaar 			    break;
18717528d1f6SBram Moolenaar 			}
18727528d1f6SBram Moolenaar 			bot_start += wp->w_lines[idx++].wl_size;
18737528d1f6SBram Moolenaar 
18747528d1f6SBram Moolenaar 			// stop at the last valid entry in w_lines[].wl_size
18757528d1f6SBram Moolenaar 			if (++j >= wp->w_lines_valid)
18767528d1f6SBram Moolenaar 			{
18777528d1f6SBram Moolenaar 			    wp->w_lines_valid = idx;
18787528d1f6SBram Moolenaar 			    break;
18797528d1f6SBram Moolenaar 			}
18807528d1f6SBram Moolenaar 		    }
18817528d1f6SBram Moolenaar #ifdef FEAT_DIFF
18827528d1f6SBram Moolenaar 		    // Correct the first entry for filler lines at the top
18837528d1f6SBram Moolenaar 		    // when it won't get updated below.
18847528d1f6SBram Moolenaar 		    if (wp->w_p_diff && bot_start > 0)
18857528d1f6SBram Moolenaar 			wp->w_lines[0].wl_size =
18867528d1f6SBram Moolenaar 			    plines_win_nofill(wp, wp->w_topline, TRUE)
18877528d1f6SBram Moolenaar 							      + wp->w_topfill;
18887528d1f6SBram Moolenaar #endif
18897528d1f6SBram Moolenaar 		}
18907528d1f6SBram Moolenaar 	    }
18917528d1f6SBram Moolenaar 	}
18927528d1f6SBram Moolenaar 
18937528d1f6SBram Moolenaar 	// When starting redraw in the first line, redraw all lines.  When
18947528d1f6SBram Moolenaar 	// there is only one window it's probably faster to clear the screen
18957528d1f6SBram Moolenaar 	// first.
18967528d1f6SBram Moolenaar 	if (mid_start == 0)
18977528d1f6SBram Moolenaar 	{
18987528d1f6SBram Moolenaar 	    mid_end = wp->w_height;
18997528d1f6SBram Moolenaar 	    if (ONE_WINDOW && !WIN_IS_POPUP(wp))
19007528d1f6SBram Moolenaar 	    {
19017528d1f6SBram Moolenaar 		// Clear the screen when it was not done by win_del_lines() or
19027528d1f6SBram Moolenaar 		// win_ins_lines() above, "screen_cleared" is FALSE or MAYBE
19037528d1f6SBram Moolenaar 		// then.
19047528d1f6SBram Moolenaar 		if (screen_cleared != TRUE)
19057528d1f6SBram Moolenaar 		    screenclear();
19067528d1f6SBram Moolenaar 		// The screen was cleared, redraw the tab pages line.
19077528d1f6SBram Moolenaar 		if (redraw_tabline)
19087528d1f6SBram Moolenaar 		    draw_tabline();
19097528d1f6SBram Moolenaar 	    }
19107528d1f6SBram Moolenaar 	}
19117528d1f6SBram Moolenaar 
19127528d1f6SBram Moolenaar 	// When win_del_lines() or win_ins_lines() caused the screen to be
19137528d1f6SBram Moolenaar 	// cleared (only happens for the first window) or when screenclear()
19147528d1f6SBram Moolenaar 	// was called directly above, "must_redraw" will have been set to
19157528d1f6SBram Moolenaar 	// NOT_VALID, need to reset it here to avoid redrawing twice.
19167528d1f6SBram Moolenaar 	if (screen_cleared == TRUE)
19177528d1f6SBram Moolenaar 	    must_redraw = 0;
19187528d1f6SBram Moolenaar     }
19197528d1f6SBram Moolenaar     else
19207528d1f6SBram Moolenaar     {
19217528d1f6SBram Moolenaar 	// Not VALID or INVERTED: redraw all lines.
19227528d1f6SBram Moolenaar 	mid_start = 0;
19237528d1f6SBram Moolenaar 	mid_end = wp->w_height;
19247528d1f6SBram Moolenaar     }
19257528d1f6SBram Moolenaar 
19267528d1f6SBram Moolenaar     if (type == SOME_VALID)
19277528d1f6SBram Moolenaar     {
19287528d1f6SBram Moolenaar 	// SOME_VALID: redraw all lines.
19297528d1f6SBram Moolenaar 	mid_start = 0;
19307528d1f6SBram Moolenaar 	mid_end = wp->w_height;
19317528d1f6SBram Moolenaar 	type = NOT_VALID;
19327528d1f6SBram Moolenaar     }
19337528d1f6SBram Moolenaar 
19347528d1f6SBram Moolenaar     // check if we are updating or removing the inverted part
19357528d1f6SBram Moolenaar     if ((VIsual_active && buf == curwin->w_buffer)
19367528d1f6SBram Moolenaar 	    || (wp->w_old_cursor_lnum != 0 && type != NOT_VALID))
19377528d1f6SBram Moolenaar     {
19387528d1f6SBram Moolenaar 	linenr_T    from, to;
19397528d1f6SBram Moolenaar 
19407528d1f6SBram Moolenaar 	if (VIsual_active)
19417528d1f6SBram Moolenaar 	{
19427528d1f6SBram Moolenaar 	    if (VIsual_active
19437528d1f6SBram Moolenaar 		    && (VIsual_mode != wp->w_old_visual_mode
19447528d1f6SBram Moolenaar 			|| type == INVERTED_ALL))
19457528d1f6SBram Moolenaar 	    {
19467528d1f6SBram Moolenaar 		// If the type of Visual selection changed, redraw the whole
19477528d1f6SBram Moolenaar 		// selection.  Also when the ownership of the X selection is
19487528d1f6SBram Moolenaar 		// gained or lost.
19497528d1f6SBram Moolenaar 		if (curwin->w_cursor.lnum < VIsual.lnum)
19507528d1f6SBram Moolenaar 		{
19517528d1f6SBram Moolenaar 		    from = curwin->w_cursor.lnum;
19527528d1f6SBram Moolenaar 		    to = VIsual.lnum;
19537528d1f6SBram Moolenaar 		}
19547528d1f6SBram Moolenaar 		else
19557528d1f6SBram Moolenaar 		{
19567528d1f6SBram Moolenaar 		    from = VIsual.lnum;
19577528d1f6SBram Moolenaar 		    to = curwin->w_cursor.lnum;
19587528d1f6SBram Moolenaar 		}
19597528d1f6SBram Moolenaar 		// redraw more when the cursor moved as well
19607528d1f6SBram Moolenaar 		if (wp->w_old_cursor_lnum < from)
19617528d1f6SBram Moolenaar 		    from = wp->w_old_cursor_lnum;
19627528d1f6SBram Moolenaar 		if (wp->w_old_cursor_lnum > to)
19637528d1f6SBram Moolenaar 		    to = wp->w_old_cursor_lnum;
19647528d1f6SBram Moolenaar 		if (wp->w_old_visual_lnum < from)
19657528d1f6SBram Moolenaar 		    from = wp->w_old_visual_lnum;
19667528d1f6SBram Moolenaar 		if (wp->w_old_visual_lnum > to)
19677528d1f6SBram Moolenaar 		    to = wp->w_old_visual_lnum;
19687528d1f6SBram Moolenaar 	    }
19697528d1f6SBram Moolenaar 	    else
19707528d1f6SBram Moolenaar 	    {
19717528d1f6SBram Moolenaar 		// Find the line numbers that need to be updated: The lines
19727528d1f6SBram Moolenaar 		// between the old cursor position and the current cursor
19737528d1f6SBram Moolenaar 		// position.  Also check if the Visual position changed.
19747528d1f6SBram Moolenaar 		if (curwin->w_cursor.lnum < wp->w_old_cursor_lnum)
19757528d1f6SBram Moolenaar 		{
19767528d1f6SBram Moolenaar 		    from = curwin->w_cursor.lnum;
19777528d1f6SBram Moolenaar 		    to = wp->w_old_cursor_lnum;
19787528d1f6SBram Moolenaar 		}
19797528d1f6SBram Moolenaar 		else
19807528d1f6SBram Moolenaar 		{
19817528d1f6SBram Moolenaar 		    from = wp->w_old_cursor_lnum;
19827528d1f6SBram Moolenaar 		    to = curwin->w_cursor.lnum;
19837528d1f6SBram Moolenaar 		    if (from == 0)	// Visual mode just started
19847528d1f6SBram Moolenaar 			from = to;
19857528d1f6SBram Moolenaar 		}
19867528d1f6SBram Moolenaar 
19877528d1f6SBram Moolenaar 		if (VIsual.lnum != wp->w_old_visual_lnum
19887528d1f6SBram Moolenaar 					|| VIsual.col != wp->w_old_visual_col)
19897528d1f6SBram Moolenaar 		{
19907528d1f6SBram Moolenaar 		    if (wp->w_old_visual_lnum < from
19917528d1f6SBram Moolenaar 						&& wp->w_old_visual_lnum != 0)
19927528d1f6SBram Moolenaar 			from = wp->w_old_visual_lnum;
19937528d1f6SBram Moolenaar 		    if (wp->w_old_visual_lnum > to)
19947528d1f6SBram Moolenaar 			to = wp->w_old_visual_lnum;
19957528d1f6SBram Moolenaar 		    if (VIsual.lnum < from)
19967528d1f6SBram Moolenaar 			from = VIsual.lnum;
19977528d1f6SBram Moolenaar 		    if (VIsual.lnum > to)
19987528d1f6SBram Moolenaar 			to = VIsual.lnum;
19997528d1f6SBram Moolenaar 		}
20007528d1f6SBram Moolenaar 	    }
20017528d1f6SBram Moolenaar 
20027528d1f6SBram Moolenaar 	    // If in block mode and changed column or curwin->w_curswant:
20037528d1f6SBram Moolenaar 	    // update all lines.
20047528d1f6SBram Moolenaar 	    // First compute the actual start and end column.
20057528d1f6SBram Moolenaar 	    if (VIsual_mode == Ctrl_V)
20067528d1f6SBram Moolenaar 	    {
20077528d1f6SBram Moolenaar 		colnr_T	    fromc, toc;
20087528d1f6SBram Moolenaar #if defined(FEAT_LINEBREAK)
200951ad850fSGary Johnson 		int	    save_ve_flags = curwin->w_ve_flags;
20107528d1f6SBram Moolenaar 
20117528d1f6SBram Moolenaar 		if (curwin->w_p_lbr)
201251ad850fSGary Johnson 		    curwin->w_ve_flags = VE_ALL;
20137528d1f6SBram Moolenaar #endif
20147528d1f6SBram Moolenaar 		getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc);
2015b17ab86eSBram Moolenaar 		++toc;
20167528d1f6SBram Moolenaar #if defined(FEAT_LINEBREAK)
201751ad850fSGary Johnson 		curwin->w_ve_flags = save_ve_flags;
20187528d1f6SBram Moolenaar #endif
20199cee4a1cSBram Moolenaar 		// Highlight to the end of the line, unless 'virtualedit' has
20209cee4a1cSBram Moolenaar 		// "block".
2021b17ab86eSBram Moolenaar 		if (curwin->w_curswant == MAXCOL)
2022b17ab86eSBram Moolenaar 		{
202353ba05b0SGary Johnson 		    if (get_ve_flags() & VE_BLOCK)
2024b17ab86eSBram Moolenaar 		    {
2025b17ab86eSBram Moolenaar 			pos_T	    pos;
2026b17ab86eSBram Moolenaar 			int	    cursor_above =
2027b17ab86eSBram Moolenaar 					   curwin->w_cursor.lnum < VIsual.lnum;
2028b17ab86eSBram Moolenaar 
2029b17ab86eSBram Moolenaar 			// Need to find the longest line.
2030b17ab86eSBram Moolenaar 			toc = 0;
2031b17ab86eSBram Moolenaar 			pos.coladd = 0;
2032b17ab86eSBram Moolenaar 			for (pos.lnum = curwin->w_cursor.lnum; cursor_above
2033b17ab86eSBram Moolenaar 					? pos.lnum <= VIsual.lnum
2034b17ab86eSBram Moolenaar 					: pos.lnum >= VIsual.lnum;
2035b17ab86eSBram Moolenaar 					     pos.lnum += cursor_above ? 1 : -1)
2036b17ab86eSBram Moolenaar 			{
2037b17ab86eSBram Moolenaar 			    colnr_T t;
2038b17ab86eSBram Moolenaar 
20396bcb1825SBram Moolenaar 			    pos.col = (int)STRLEN(ml_get_buf(wp->w_buffer,
2040b17ab86eSBram Moolenaar 							     pos.lnum, FALSE));
2041b17ab86eSBram Moolenaar 			    getvvcol(wp, &pos, NULL, NULL, &t);
2042b17ab86eSBram Moolenaar 			    if (toc < t)
2043b17ab86eSBram Moolenaar 				toc = t;
2044b17ab86eSBram Moolenaar 			}
2045b17ab86eSBram Moolenaar 			++toc;
2046b17ab86eSBram Moolenaar 		    }
2047b17ab86eSBram Moolenaar 		    else
20487528d1f6SBram Moolenaar 			toc = MAXCOL;
2049b17ab86eSBram Moolenaar 		}
20507528d1f6SBram Moolenaar 
20517528d1f6SBram Moolenaar 		if (fromc != wp->w_old_cursor_fcol
20527528d1f6SBram Moolenaar 			|| toc != wp->w_old_cursor_lcol)
20537528d1f6SBram Moolenaar 		{
20547528d1f6SBram Moolenaar 		    if (from > VIsual.lnum)
20557528d1f6SBram Moolenaar 			from = VIsual.lnum;
20567528d1f6SBram Moolenaar 		    if (to < VIsual.lnum)
20577528d1f6SBram Moolenaar 			to = VIsual.lnum;
20587528d1f6SBram Moolenaar 		}
20597528d1f6SBram Moolenaar 		wp->w_old_cursor_fcol = fromc;
20607528d1f6SBram Moolenaar 		wp->w_old_cursor_lcol = toc;
20617528d1f6SBram Moolenaar 	    }
20627528d1f6SBram Moolenaar 	}
20637528d1f6SBram Moolenaar 	else
20647528d1f6SBram Moolenaar 	{
20657528d1f6SBram Moolenaar 	    // Use the line numbers of the old Visual area.
20667528d1f6SBram Moolenaar 	    if (wp->w_old_cursor_lnum < wp->w_old_visual_lnum)
20677528d1f6SBram Moolenaar 	    {
20687528d1f6SBram Moolenaar 		from = wp->w_old_cursor_lnum;
20697528d1f6SBram Moolenaar 		to = wp->w_old_visual_lnum;
20707528d1f6SBram Moolenaar 	    }
20717528d1f6SBram Moolenaar 	    else
20727528d1f6SBram Moolenaar 	    {
20737528d1f6SBram Moolenaar 		from = wp->w_old_visual_lnum;
20747528d1f6SBram Moolenaar 		to = wp->w_old_cursor_lnum;
20757528d1f6SBram Moolenaar 	    }
20767528d1f6SBram Moolenaar 	}
20777528d1f6SBram Moolenaar 
20787528d1f6SBram Moolenaar 	// There is no need to update lines above the top of the window.
20797528d1f6SBram Moolenaar 	if (from < wp->w_topline)
20807528d1f6SBram Moolenaar 	    from = wp->w_topline;
20817528d1f6SBram Moolenaar 
20827528d1f6SBram Moolenaar 	// If we know the value of w_botline, use it to restrict the update to
20837528d1f6SBram Moolenaar 	// the lines that are visible in the window.
20847528d1f6SBram Moolenaar 	if (wp->w_valid & VALID_BOTLINE)
20857528d1f6SBram Moolenaar 	{
20867528d1f6SBram Moolenaar 	    if (from >= wp->w_botline)
20877528d1f6SBram Moolenaar 		from = wp->w_botline - 1;
20887528d1f6SBram Moolenaar 	    if (to >= wp->w_botline)
20897528d1f6SBram Moolenaar 		to = wp->w_botline - 1;
20907528d1f6SBram Moolenaar 	}
20917528d1f6SBram Moolenaar 
20927528d1f6SBram Moolenaar 	// Find the minimal part to be updated.
20937528d1f6SBram Moolenaar 	// Watch out for scrolling that made entries in w_lines[] invalid.
20947528d1f6SBram Moolenaar 	// E.g., CTRL-U makes the first half of w_lines[] invalid and sets
20957528d1f6SBram Moolenaar 	// top_end; need to redraw from top_end to the "to" line.
20967528d1f6SBram Moolenaar 	// A middle mouse click with a Visual selection may change the text
20977528d1f6SBram Moolenaar 	// above the Visual area and reset wl_valid, do count these for
20987528d1f6SBram Moolenaar 	// mid_end (in srow).
20997528d1f6SBram Moolenaar 	if (mid_start > 0)
21007528d1f6SBram Moolenaar 	{
21017528d1f6SBram Moolenaar 	    lnum = wp->w_topline;
21027528d1f6SBram Moolenaar 	    idx = 0;
21037528d1f6SBram Moolenaar 	    srow = 0;
21047528d1f6SBram Moolenaar 	    if (scrolled_down)
21057528d1f6SBram Moolenaar 		mid_start = top_end;
21067528d1f6SBram Moolenaar 	    else
21077528d1f6SBram Moolenaar 		mid_start = 0;
21087528d1f6SBram Moolenaar 	    while (lnum < from && idx < wp->w_lines_valid)	// find start
21097528d1f6SBram Moolenaar 	    {
21107528d1f6SBram Moolenaar 		if (wp->w_lines[idx].wl_valid)
21117528d1f6SBram Moolenaar 		    mid_start += wp->w_lines[idx].wl_size;
21127528d1f6SBram Moolenaar 		else if (!scrolled_down)
21137528d1f6SBram Moolenaar 		    srow += wp->w_lines[idx].wl_size;
21147528d1f6SBram Moolenaar 		++idx;
21157528d1f6SBram Moolenaar # ifdef FEAT_FOLDING
21167528d1f6SBram Moolenaar 		if (idx < wp->w_lines_valid && wp->w_lines[idx].wl_valid)
21177528d1f6SBram Moolenaar 		    lnum = wp->w_lines[idx].wl_lnum;
21187528d1f6SBram Moolenaar 		else
21197528d1f6SBram Moolenaar # endif
21207528d1f6SBram Moolenaar 		    ++lnum;
21217528d1f6SBram Moolenaar 	    }
21227528d1f6SBram Moolenaar 	    srow += mid_start;
21237528d1f6SBram Moolenaar 	    mid_end = wp->w_height;
21247528d1f6SBram Moolenaar 	    for ( ; idx < wp->w_lines_valid; ++idx)		// find end
21257528d1f6SBram Moolenaar 	    {
21267528d1f6SBram Moolenaar 		if (wp->w_lines[idx].wl_valid
21277528d1f6SBram Moolenaar 			&& wp->w_lines[idx].wl_lnum >= to + 1)
21287528d1f6SBram Moolenaar 		{
21297528d1f6SBram Moolenaar 		    // Only update until first row of this line
21307528d1f6SBram Moolenaar 		    mid_end = srow;
21317528d1f6SBram Moolenaar 		    break;
21327528d1f6SBram Moolenaar 		}
21337528d1f6SBram Moolenaar 		srow += wp->w_lines[idx].wl_size;
21347528d1f6SBram Moolenaar 	    }
21357528d1f6SBram Moolenaar 	}
21367528d1f6SBram Moolenaar     }
21377528d1f6SBram Moolenaar 
21387528d1f6SBram Moolenaar     if (VIsual_active && buf == curwin->w_buffer)
21397528d1f6SBram Moolenaar     {
21407528d1f6SBram Moolenaar 	wp->w_old_visual_mode = VIsual_mode;
21417528d1f6SBram Moolenaar 	wp->w_old_cursor_lnum = curwin->w_cursor.lnum;
21427528d1f6SBram Moolenaar 	wp->w_old_visual_lnum = VIsual.lnum;
21437528d1f6SBram Moolenaar 	wp->w_old_visual_col = VIsual.col;
21447528d1f6SBram Moolenaar 	wp->w_old_curswant = curwin->w_curswant;
21457528d1f6SBram Moolenaar     }
21467528d1f6SBram Moolenaar     else
21477528d1f6SBram Moolenaar     {
21487528d1f6SBram Moolenaar 	wp->w_old_visual_mode = 0;
21497528d1f6SBram Moolenaar 	wp->w_old_cursor_lnum = 0;
21507528d1f6SBram Moolenaar 	wp->w_old_visual_lnum = 0;
21517528d1f6SBram Moolenaar 	wp->w_old_visual_col = 0;
21527528d1f6SBram Moolenaar     }
21537528d1f6SBram Moolenaar 
21547528d1f6SBram Moolenaar #if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA)
21557528d1f6SBram Moolenaar     // reset got_int, otherwise regexp won't work
21567528d1f6SBram Moolenaar     save_got_int = got_int;
21577528d1f6SBram Moolenaar     got_int = 0;
21587528d1f6SBram Moolenaar #endif
21597528d1f6SBram Moolenaar #ifdef SYN_TIME_LIMIT
21607528d1f6SBram Moolenaar     // Set the time limit to 'redrawtime'.
21617528d1f6SBram Moolenaar     profile_setlimit(p_rdt, &syntax_tm);
21627528d1f6SBram Moolenaar     syn_set_timeout(&syntax_tm);
21637528d1f6SBram Moolenaar #endif
21647528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
21657528d1f6SBram Moolenaar     win_foldinfo.fi_level = 0;
21667528d1f6SBram Moolenaar #endif
21677528d1f6SBram Moolenaar 
21687528d1f6SBram Moolenaar #ifdef FEAT_MENU
21697528d1f6SBram Moolenaar     // Draw the window toolbar, if there is one.
21707528d1f6SBram Moolenaar     // TODO: only when needed.
21717528d1f6SBram Moolenaar     if (winbar_height(wp) > 0)
21727528d1f6SBram Moolenaar 	redraw_win_toolbar(wp);
21737528d1f6SBram Moolenaar #endif
21747528d1f6SBram Moolenaar 
21757528d1f6SBram Moolenaar     // Update all the window rows.
21767528d1f6SBram Moolenaar     idx = 0;		// first entry in w_lines[].wl_size
21777528d1f6SBram Moolenaar     row = 0;
21787528d1f6SBram Moolenaar     srow = 0;
21797528d1f6SBram Moolenaar     lnum = wp->w_topline;	// first line shown in window
21807528d1f6SBram Moolenaar     for (;;)
21817528d1f6SBram Moolenaar     {
21827528d1f6SBram Moolenaar 	// stop updating when reached the end of the window (check for _past_
21837528d1f6SBram Moolenaar 	// the end of the window is at the end of the loop)
21847528d1f6SBram Moolenaar 	if (row == wp->w_height)
21857528d1f6SBram Moolenaar 	{
21867528d1f6SBram Moolenaar 	    didline = TRUE;
21877528d1f6SBram Moolenaar 	    break;
21887528d1f6SBram Moolenaar 	}
21897528d1f6SBram Moolenaar 
21907528d1f6SBram Moolenaar 	// stop updating when hit the end of the file
21917528d1f6SBram Moolenaar 	if (lnum > buf->b_ml.ml_line_count)
21927528d1f6SBram Moolenaar 	{
21937528d1f6SBram Moolenaar 	    eof = TRUE;
21947528d1f6SBram Moolenaar 	    break;
21957528d1f6SBram Moolenaar 	}
21967528d1f6SBram Moolenaar 
21977528d1f6SBram Moolenaar 	// Remember the starting row of the line that is going to be dealt
21987528d1f6SBram Moolenaar 	// with.  It is used further down when the line doesn't fit.
21997528d1f6SBram Moolenaar 	srow = row;
22007528d1f6SBram Moolenaar 
22017528d1f6SBram Moolenaar 	// Update a line when it is in an area that needs updating, when it
22027528d1f6SBram Moolenaar 	// has changes or w_lines[idx] is invalid.
22037528d1f6SBram Moolenaar 	// "bot_start" may be halfway a wrapped line after using
22047528d1f6SBram Moolenaar 	// win_del_lines(), check if the current line includes it.
22057528d1f6SBram Moolenaar 	// When syntax folding is being used, the saved syntax states will
22067528d1f6SBram Moolenaar 	// already have been updated, we can't see where the syntax state is
22077528d1f6SBram Moolenaar 	// the same again, just update until the end of the window.
22087528d1f6SBram Moolenaar 	if (row < top_end
22097528d1f6SBram Moolenaar 		|| (row >= mid_start && row < mid_end)
22107528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
22117528d1f6SBram Moolenaar 		|| top_to_mod
22127528d1f6SBram Moolenaar #endif
22137528d1f6SBram Moolenaar 		|| idx >= wp->w_lines_valid
22147528d1f6SBram Moolenaar 		|| (row + wp->w_lines[idx].wl_size > bot_start)
22157528d1f6SBram Moolenaar 		|| (mod_top != 0
22167528d1f6SBram Moolenaar 		    && (lnum == mod_top
22177528d1f6SBram Moolenaar 			|| (lnum >= mod_top
22187528d1f6SBram Moolenaar 			    && (lnum < mod_bot
22197528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
22207528d1f6SBram Moolenaar 				|| did_update == DID_FOLD
22217528d1f6SBram Moolenaar 				|| (did_update == DID_LINE
22227528d1f6SBram Moolenaar 				    && syntax_present(wp)
22237528d1f6SBram Moolenaar 				    && (
22247528d1f6SBram Moolenaar # ifdef FEAT_FOLDING
22257528d1f6SBram Moolenaar 					(foldmethodIsSyntax(wp)
22267528d1f6SBram Moolenaar 						      && hasAnyFolding(wp)) ||
22277528d1f6SBram Moolenaar # endif
22287528d1f6SBram Moolenaar 					syntax_check_changed(lnum)))
22297528d1f6SBram Moolenaar #endif
22307528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
22317528d1f6SBram Moolenaar 				// match in fixed position might need redraw
22327528d1f6SBram Moolenaar 				// if lines were inserted or deleted
22337528d1f6SBram Moolenaar 				|| (wp->w_match_head != NULL
22347528d1f6SBram Moolenaar 						    && buf->b_mod_xlines != 0)
22357528d1f6SBram Moolenaar #endif
223611a58af6SBram Moolenaar 				))))
223711a58af6SBram Moolenaar #ifdef FEAT_SYN_HL
223811a58af6SBram Moolenaar 		|| (wp->w_p_cul && (lnum == wp->w_cursor.lnum
223911a58af6SBram Moolenaar 					     || lnum == wp->w_last_cursorline))
224011a58af6SBram Moolenaar #endif
224111a58af6SBram Moolenaar 				)
22427528d1f6SBram Moolenaar 	{
22437528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
22447528d1f6SBram Moolenaar 	    if (lnum == mod_top)
22457528d1f6SBram Moolenaar 		top_to_mod = FALSE;
22467528d1f6SBram Moolenaar #endif
22477528d1f6SBram Moolenaar 
22487528d1f6SBram Moolenaar 	    // When at start of changed lines: May scroll following lines
22497528d1f6SBram Moolenaar 	    // up or down to minimize redrawing.
22507528d1f6SBram Moolenaar 	    // Don't do this when the change continues until the end.
22517528d1f6SBram Moolenaar 	    // Don't scroll when dollar_vcol >= 0, keep the "$".
2252c9e7e344SBram Moolenaar 	    // Don't scroll when redrawing the top, scrolled already above.
22537528d1f6SBram Moolenaar 	    if (lnum == mod_top
22547528d1f6SBram Moolenaar 		    && mod_bot != MAXLNUM
2255c9e7e344SBram Moolenaar 		    && !(dollar_vcol >= 0 && mod_bot == mod_top + 1)
2256c9e7e344SBram Moolenaar 		    && row >= top_end)
22577528d1f6SBram Moolenaar 	    {
22587528d1f6SBram Moolenaar 		int		old_rows = 0;
22597528d1f6SBram Moolenaar 		int		new_rows = 0;
22607528d1f6SBram Moolenaar 		int		xtra_rows;
22617528d1f6SBram Moolenaar 		linenr_T	l;
22627528d1f6SBram Moolenaar 
22637528d1f6SBram Moolenaar 		// Count the old number of window rows, using w_lines[], which
22647528d1f6SBram Moolenaar 		// should still contain the sizes for the lines as they are
22657528d1f6SBram Moolenaar 		// currently displayed.
22667528d1f6SBram Moolenaar 		for (i = idx; i < wp->w_lines_valid; ++i)
22677528d1f6SBram Moolenaar 		{
22687528d1f6SBram Moolenaar 		    // Only valid lines have a meaningful wl_lnum.  Invalid
22697528d1f6SBram Moolenaar 		    // lines are part of the changed area.
22707528d1f6SBram Moolenaar 		    if (wp->w_lines[i].wl_valid
22717528d1f6SBram Moolenaar 			    && wp->w_lines[i].wl_lnum == mod_bot)
22727528d1f6SBram Moolenaar 			break;
22737528d1f6SBram Moolenaar 		    old_rows += wp->w_lines[i].wl_size;
22747528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
22757528d1f6SBram Moolenaar 		    if (wp->w_lines[i].wl_valid
22767528d1f6SBram Moolenaar 			    && wp->w_lines[i].wl_lastlnum + 1 == mod_bot)
22777528d1f6SBram Moolenaar 		    {
22787528d1f6SBram Moolenaar 			// Must have found the last valid entry above mod_bot.
22797528d1f6SBram Moolenaar 			// Add following invalid entries.
22807528d1f6SBram Moolenaar 			++i;
22817528d1f6SBram Moolenaar 			while (i < wp->w_lines_valid
22827528d1f6SBram Moolenaar 						  && !wp->w_lines[i].wl_valid)
22837528d1f6SBram Moolenaar 			    old_rows += wp->w_lines[i++].wl_size;
22847528d1f6SBram Moolenaar 			break;
22857528d1f6SBram Moolenaar 		    }
22867528d1f6SBram Moolenaar #endif
22877528d1f6SBram Moolenaar 		}
22887528d1f6SBram Moolenaar 
22897528d1f6SBram Moolenaar 		if (i >= wp->w_lines_valid)
22907528d1f6SBram Moolenaar 		{
22917528d1f6SBram Moolenaar 		    // We can't find a valid line below the changed lines,
22927528d1f6SBram Moolenaar 		    // need to redraw until the end of the window.
22937528d1f6SBram Moolenaar 		    // Inserting/deleting lines has no use.
22947528d1f6SBram Moolenaar 		    bot_start = 0;
22957528d1f6SBram Moolenaar 		}
22967528d1f6SBram Moolenaar 		else
22977528d1f6SBram Moolenaar 		{
22987528d1f6SBram Moolenaar 		    // Able to count old number of rows: Count new window
22997528d1f6SBram Moolenaar 		    // rows, and may insert/delete lines
23007528d1f6SBram Moolenaar 		    j = idx;
23017528d1f6SBram Moolenaar 		    for (l = lnum; l < mod_bot; ++l)
23027528d1f6SBram Moolenaar 		    {
23037528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
23047528d1f6SBram Moolenaar 			if (hasFoldingWin(wp, l, NULL, &l, TRUE, NULL))
23057528d1f6SBram Moolenaar 			    ++new_rows;
23067528d1f6SBram Moolenaar 			else
23077528d1f6SBram Moolenaar #endif
2308*9b0b844dSDominique Pelle 			{
23097528d1f6SBram Moolenaar #ifdef FEAT_DIFF
23107528d1f6SBram Moolenaar 			    if (l == wp->w_topline)
23117528d1f6SBram Moolenaar 				new_rows += plines_win_nofill(wp, l, TRUE)
23127528d1f6SBram Moolenaar 							      + wp->w_topfill;
23137528d1f6SBram Moolenaar 			    else
23147528d1f6SBram Moolenaar #endif
23157528d1f6SBram Moolenaar 				new_rows += plines_win(wp, l, TRUE);
2316*9b0b844dSDominique Pelle 			}
23177528d1f6SBram Moolenaar 			++j;
23187528d1f6SBram Moolenaar 			if (new_rows > wp->w_height - row - 2)
23197528d1f6SBram Moolenaar 			{
23207528d1f6SBram Moolenaar 			    // it's getting too much, must redraw the rest
23217528d1f6SBram Moolenaar 			    new_rows = 9999;
23227528d1f6SBram Moolenaar 			    break;
23237528d1f6SBram Moolenaar 			}
23247528d1f6SBram Moolenaar 		    }
23257528d1f6SBram Moolenaar 		    xtra_rows = new_rows - old_rows;
23267528d1f6SBram Moolenaar 		    if (xtra_rows < 0)
23277528d1f6SBram Moolenaar 		    {
23287528d1f6SBram Moolenaar 			// May scroll text up.  If there is not enough
23297528d1f6SBram Moolenaar 			// remaining text or scrolling fails, must redraw the
23307528d1f6SBram Moolenaar 			// rest.  If scrolling works, must redraw the text
23317528d1f6SBram Moolenaar 			// below the scrolled text.
23327528d1f6SBram Moolenaar 			if (row - xtra_rows >= wp->w_height - 2)
23337528d1f6SBram Moolenaar 			    mod_bot = MAXLNUM;
23347528d1f6SBram Moolenaar 			else
23357528d1f6SBram Moolenaar 			{
23367528d1f6SBram Moolenaar 			    check_for_delay(FALSE);
23377528d1f6SBram Moolenaar 			    if (win_del_lines(wp, row,
23387528d1f6SBram Moolenaar 					  -xtra_rows, FALSE, FALSE, 0) == FAIL)
23397528d1f6SBram Moolenaar 				mod_bot = MAXLNUM;
23407528d1f6SBram Moolenaar 			    else
23417528d1f6SBram Moolenaar 				bot_start = wp->w_height + xtra_rows;
23427528d1f6SBram Moolenaar 			}
23437528d1f6SBram Moolenaar 		    }
23447528d1f6SBram Moolenaar 		    else if (xtra_rows > 0)
23457528d1f6SBram Moolenaar 		    {
23467528d1f6SBram Moolenaar 			// May scroll text down.  If there is not enough
23477528d1f6SBram Moolenaar 			// remaining text of scrolling fails, must redraw the
23487528d1f6SBram Moolenaar 			// rest.
23497528d1f6SBram Moolenaar 			if (row + xtra_rows >= wp->w_height - 2)
23507528d1f6SBram Moolenaar 			    mod_bot = MAXLNUM;
23517528d1f6SBram Moolenaar 			else
23527528d1f6SBram Moolenaar 			{
23537528d1f6SBram Moolenaar 			    check_for_delay(FALSE);
23547528d1f6SBram Moolenaar 			    if (win_ins_lines(wp, row + old_rows,
23557528d1f6SBram Moolenaar 					     xtra_rows, FALSE, FALSE) == FAIL)
23567528d1f6SBram Moolenaar 				mod_bot = MAXLNUM;
23577528d1f6SBram Moolenaar 			    else if (top_end > row + old_rows)
23587528d1f6SBram Moolenaar 				// Scrolled the part at the top that requires
23597528d1f6SBram Moolenaar 				// updating down.
23607528d1f6SBram Moolenaar 				top_end += xtra_rows;
23617528d1f6SBram Moolenaar 			}
23627528d1f6SBram Moolenaar 		    }
23637528d1f6SBram Moolenaar 
23647528d1f6SBram Moolenaar 		    // When not updating the rest, may need to move w_lines[]
23657528d1f6SBram Moolenaar 		    // entries.
23667528d1f6SBram Moolenaar 		    if (mod_bot != MAXLNUM && i != j)
23677528d1f6SBram Moolenaar 		    {
23687528d1f6SBram Moolenaar 			if (j < i)
23697528d1f6SBram Moolenaar 			{
23707528d1f6SBram Moolenaar 			    int x = row + new_rows;
23717528d1f6SBram Moolenaar 
23727528d1f6SBram Moolenaar 			    // move entries in w_lines[] upwards
23737528d1f6SBram Moolenaar 			    for (;;)
23747528d1f6SBram Moolenaar 			    {
23757528d1f6SBram Moolenaar 				// stop at last valid entry in w_lines[]
23767528d1f6SBram Moolenaar 				if (i >= wp->w_lines_valid)
23777528d1f6SBram Moolenaar 				{
23787528d1f6SBram Moolenaar 				    wp->w_lines_valid = j;
23797528d1f6SBram Moolenaar 				    break;
23807528d1f6SBram Moolenaar 				}
23817528d1f6SBram Moolenaar 				wp->w_lines[j] = wp->w_lines[i];
23827528d1f6SBram Moolenaar 				// stop at a line that won't fit
23837528d1f6SBram Moolenaar 				if (x + (int)wp->w_lines[j].wl_size
23847528d1f6SBram Moolenaar 							   > wp->w_height)
23857528d1f6SBram Moolenaar 				{
23867528d1f6SBram Moolenaar 				    wp->w_lines_valid = j + 1;
23877528d1f6SBram Moolenaar 				    break;
23887528d1f6SBram Moolenaar 				}
23897528d1f6SBram Moolenaar 				x += wp->w_lines[j++].wl_size;
23907528d1f6SBram Moolenaar 				++i;
23917528d1f6SBram Moolenaar 			    }
23927528d1f6SBram Moolenaar 			    if (bot_start > x)
23937528d1f6SBram Moolenaar 				bot_start = x;
23947528d1f6SBram Moolenaar 			}
23957528d1f6SBram Moolenaar 			else // j > i
23967528d1f6SBram Moolenaar 			{
23977528d1f6SBram Moolenaar 			    // move entries in w_lines[] downwards
23987528d1f6SBram Moolenaar 			    j -= i;
23997528d1f6SBram Moolenaar 			    wp->w_lines_valid += j;
24007528d1f6SBram Moolenaar 			    if (wp->w_lines_valid > wp->w_height)
24017528d1f6SBram Moolenaar 				wp->w_lines_valid = wp->w_height;
24027528d1f6SBram Moolenaar 			    for (i = wp->w_lines_valid; i - j >= idx; --i)
24037528d1f6SBram Moolenaar 				wp->w_lines[i] = wp->w_lines[i - j];
24047528d1f6SBram Moolenaar 
24057528d1f6SBram Moolenaar 			    // The w_lines[] entries for inserted lines are
24067528d1f6SBram Moolenaar 			    // now invalid, but wl_size may be used above.
24077528d1f6SBram Moolenaar 			    // Reset to zero.
24087528d1f6SBram Moolenaar 			    while (i >= idx)
24097528d1f6SBram Moolenaar 			    {
24107528d1f6SBram Moolenaar 				wp->w_lines[i].wl_size = 0;
24117528d1f6SBram Moolenaar 				wp->w_lines[i--].wl_valid = FALSE;
24127528d1f6SBram Moolenaar 			    }
24137528d1f6SBram Moolenaar 			}
24147528d1f6SBram Moolenaar 		    }
24157528d1f6SBram Moolenaar 		}
24167528d1f6SBram Moolenaar 	    }
24177528d1f6SBram Moolenaar 
24187528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
24197528d1f6SBram Moolenaar 	    // When lines are folded, display one line for all of them.
24207528d1f6SBram Moolenaar 	    // Otherwise, display normally (can be several display lines when
24217528d1f6SBram Moolenaar 	    // 'wrap' is on).
24227528d1f6SBram Moolenaar 	    fold_count = foldedCount(wp, lnum, &win_foldinfo);
24237528d1f6SBram Moolenaar 	    if (fold_count != 0)
24247528d1f6SBram Moolenaar 	    {
24257528d1f6SBram Moolenaar 		fold_line(wp, fold_count, &win_foldinfo, lnum, row);
24267528d1f6SBram Moolenaar 		++row;
24277528d1f6SBram Moolenaar 		--fold_count;
24287528d1f6SBram Moolenaar 		wp->w_lines[idx].wl_folded = TRUE;
24297528d1f6SBram Moolenaar 		wp->w_lines[idx].wl_lastlnum = lnum + fold_count;
24307528d1f6SBram Moolenaar # ifdef FEAT_SYN_HL
24317528d1f6SBram Moolenaar 		did_update = DID_FOLD;
24327528d1f6SBram Moolenaar # endif
24337528d1f6SBram Moolenaar 	    }
24347528d1f6SBram Moolenaar 	    else
24357528d1f6SBram Moolenaar #endif
24367528d1f6SBram Moolenaar 	    if (idx < wp->w_lines_valid
24377528d1f6SBram Moolenaar 		    && wp->w_lines[idx].wl_valid
24387528d1f6SBram Moolenaar 		    && wp->w_lines[idx].wl_lnum == lnum
24397528d1f6SBram Moolenaar 		    && lnum > wp->w_topline
24407528d1f6SBram Moolenaar 		    && !(dy_flags & (DY_LASTLINE | DY_TRUNCATE))
24417528d1f6SBram Moolenaar 		    && !WIN_IS_POPUP(wp)
24427528d1f6SBram Moolenaar 		    && srow + wp->w_lines[idx].wl_size > wp->w_height
24437528d1f6SBram Moolenaar #ifdef FEAT_DIFF
24447528d1f6SBram Moolenaar 		    && diff_check_fill(wp, lnum) == 0
24457528d1f6SBram Moolenaar #endif
24467528d1f6SBram Moolenaar 		    )
24477528d1f6SBram Moolenaar 	    {
24487528d1f6SBram Moolenaar 		// This line is not going to fit.  Don't draw anything here,
24497528d1f6SBram Moolenaar 		// will draw "@  " lines below.
24507528d1f6SBram Moolenaar 		row = wp->w_height + 1;
24517528d1f6SBram Moolenaar 	    }
24527528d1f6SBram Moolenaar 	    else
24537528d1f6SBram Moolenaar 	    {
24547528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
24557528d1f6SBram Moolenaar 		prepare_search_hl(wp, &screen_search_hl, lnum);
24567528d1f6SBram Moolenaar #endif
24577528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
24587528d1f6SBram Moolenaar 		// Let the syntax stuff know we skipped a few lines.
24597528d1f6SBram Moolenaar 		if (syntax_last_parsed != 0 && syntax_last_parsed + 1 < lnum
24607528d1f6SBram Moolenaar 						       && syntax_present(wp))
24617528d1f6SBram Moolenaar 		    syntax_end_parsing(syntax_last_parsed + 1);
24627528d1f6SBram Moolenaar #endif
24637528d1f6SBram Moolenaar 
24647528d1f6SBram Moolenaar 		// Display one line.
24657528d1f6SBram Moolenaar 		row = win_line(wp, lnum, srow, wp->w_height,
24667528d1f6SBram Moolenaar 							  mod_top == 0, FALSE);
24677528d1f6SBram Moolenaar 
24687528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
24697528d1f6SBram Moolenaar 		wp->w_lines[idx].wl_folded = FALSE;
24707528d1f6SBram Moolenaar 		wp->w_lines[idx].wl_lastlnum = lnum;
24717528d1f6SBram Moolenaar #endif
24727528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
24737528d1f6SBram Moolenaar 		did_update = DID_LINE;
24747528d1f6SBram Moolenaar 		syntax_last_parsed = lnum;
24757528d1f6SBram Moolenaar #endif
24767528d1f6SBram Moolenaar 	    }
24777528d1f6SBram Moolenaar 
24787528d1f6SBram Moolenaar 	    wp->w_lines[idx].wl_lnum = lnum;
24797528d1f6SBram Moolenaar 	    wp->w_lines[idx].wl_valid = TRUE;
24807528d1f6SBram Moolenaar 
24817528d1f6SBram Moolenaar 	    // Past end of the window or end of the screen. Note that after
24827528d1f6SBram Moolenaar 	    // resizing wp->w_height may be end up too big. That's a problem
24837528d1f6SBram Moolenaar 	    // elsewhere, but prevent a crash here.
24847528d1f6SBram Moolenaar 	    if (row > wp->w_height || row + wp->w_winrow >= Rows)
24857528d1f6SBram Moolenaar 	    {
24867528d1f6SBram Moolenaar 		// we may need the size of that too long line later on
24877528d1f6SBram Moolenaar 		if (dollar_vcol == -1)
24887528d1f6SBram Moolenaar 		    wp->w_lines[idx].wl_size = plines_win(wp, lnum, TRUE);
24897528d1f6SBram Moolenaar 		++idx;
24907528d1f6SBram Moolenaar 		break;
24917528d1f6SBram Moolenaar 	    }
24927528d1f6SBram Moolenaar 	    if (dollar_vcol == -1)
24937528d1f6SBram Moolenaar 		wp->w_lines[idx].wl_size = row - srow;
24947528d1f6SBram Moolenaar 	    ++idx;
24957528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
24967528d1f6SBram Moolenaar 	    lnum += fold_count + 1;
24977528d1f6SBram Moolenaar #else
24987528d1f6SBram Moolenaar 	    ++lnum;
24997528d1f6SBram Moolenaar #endif
25007528d1f6SBram Moolenaar 	}
25017528d1f6SBram Moolenaar 	else
25027528d1f6SBram Moolenaar 	{
25037528d1f6SBram Moolenaar 	    if (wp->w_p_rnu)
25047528d1f6SBram Moolenaar 	    {
25057528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
25067528d1f6SBram Moolenaar 		// 'relativenumber' set: The text doesn't need to be drawn, but
25077528d1f6SBram Moolenaar 		// the number column nearly always does.
25087528d1f6SBram Moolenaar 		fold_count = foldedCount(wp, lnum, &win_foldinfo);
25097528d1f6SBram Moolenaar 		if (fold_count != 0)
25107528d1f6SBram Moolenaar 		    fold_line(wp, fold_count, &win_foldinfo, lnum, row);
25117528d1f6SBram Moolenaar 		else
25127528d1f6SBram Moolenaar #endif
25137528d1f6SBram Moolenaar 		    (void)win_line(wp, lnum, srow, wp->w_height, TRUE, TRUE);
25147528d1f6SBram Moolenaar 	    }
25157528d1f6SBram Moolenaar 
25167528d1f6SBram Moolenaar 	    // This line does not need to be drawn, advance to the next one.
25177528d1f6SBram Moolenaar 	    row += wp->w_lines[idx++].wl_size;
25187528d1f6SBram Moolenaar 	    if (row > wp->w_height)	// past end of screen
25197528d1f6SBram Moolenaar 		break;
25207528d1f6SBram Moolenaar #ifdef FEAT_FOLDING
25217528d1f6SBram Moolenaar 	    lnum = wp->w_lines[idx - 1].wl_lastlnum + 1;
25227528d1f6SBram Moolenaar #else
25237528d1f6SBram Moolenaar 	    ++lnum;
25247528d1f6SBram Moolenaar #endif
25257528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
25267528d1f6SBram Moolenaar 	    did_update = DID_NONE;
25277528d1f6SBram Moolenaar #endif
25287528d1f6SBram Moolenaar 	}
25297528d1f6SBram Moolenaar 
25307528d1f6SBram Moolenaar 	if (lnum > buf->b_ml.ml_line_count)
25317528d1f6SBram Moolenaar 	{
25327528d1f6SBram Moolenaar 	    eof = TRUE;
25337528d1f6SBram Moolenaar 	    break;
25347528d1f6SBram Moolenaar 	}
25357528d1f6SBram Moolenaar     }
25367528d1f6SBram Moolenaar 
25377528d1f6SBram Moolenaar     // End of loop over all window lines.
25387528d1f6SBram Moolenaar 
25397528d1f6SBram Moolenaar #ifdef FEAT_VTP
25407528d1f6SBram Moolenaar     // Rewrite the character at the end of the screen line.
25417ed8f59aSBram Moolenaar     // See the version that was fixed.
25427ed8f59aSBram Moolenaar     if (use_vtp() && get_conpty_fix_type() < 1)
25437528d1f6SBram Moolenaar     {
25447528d1f6SBram Moolenaar 	int i;
25457528d1f6SBram Moolenaar 
25467528d1f6SBram Moolenaar 	for (i = 0; i < Rows; ++i)
25477528d1f6SBram Moolenaar 	    if (enc_utf8)
25487528d1f6SBram Moolenaar 		if ((*mb_off2cells)(LineOffset[i] + Columns - 2,
25497528d1f6SBram Moolenaar 					   LineOffset[i] + screen_Columns) > 1)
25507528d1f6SBram Moolenaar 		    screen_draw_rectangle(i, Columns - 2, 1, 2, FALSE);
25517528d1f6SBram Moolenaar 		else
25527528d1f6SBram Moolenaar 		    screen_draw_rectangle(i, Columns - 1, 1, 1, FALSE);
25537528d1f6SBram Moolenaar 	    else
25547528d1f6SBram Moolenaar 		screen_char(LineOffset[i] + Columns - 1, i, Columns - 1);
25557528d1f6SBram Moolenaar     }
25567528d1f6SBram Moolenaar #endif
25577528d1f6SBram Moolenaar 
25587528d1f6SBram Moolenaar     if (idx > wp->w_lines_valid)
25597528d1f6SBram Moolenaar 	wp->w_lines_valid = idx;
25607528d1f6SBram Moolenaar 
25617528d1f6SBram Moolenaar #ifdef FEAT_SYN_HL
25627528d1f6SBram Moolenaar     // Let the syntax stuff know we stop parsing here.
25637528d1f6SBram Moolenaar     if (syntax_last_parsed != 0 && syntax_present(wp))
25647528d1f6SBram Moolenaar 	syntax_end_parsing(syntax_last_parsed + 1);
25657528d1f6SBram Moolenaar #endif
25667528d1f6SBram Moolenaar 
25677528d1f6SBram Moolenaar     // If we didn't hit the end of the file, and we didn't finish the last
25687528d1f6SBram Moolenaar     // line we were working on, then the line didn't fit.
25697528d1f6SBram Moolenaar     wp->w_empty_rows = 0;
25707528d1f6SBram Moolenaar #ifdef FEAT_DIFF
25717528d1f6SBram Moolenaar     wp->w_filler_rows = 0;
25727528d1f6SBram Moolenaar #endif
25737528d1f6SBram Moolenaar     if (!eof && !didline)
25747528d1f6SBram Moolenaar     {
25757528d1f6SBram Moolenaar 	if (lnum == wp->w_topline)
25767528d1f6SBram Moolenaar 	{
25777528d1f6SBram Moolenaar 	    // Single line that does not fit!
25787528d1f6SBram Moolenaar 	    // Don't overwrite it, it can be edited.
25797528d1f6SBram Moolenaar 	    wp->w_botline = lnum + 1;
25807528d1f6SBram Moolenaar 	}
25817528d1f6SBram Moolenaar #ifdef FEAT_DIFF
25827528d1f6SBram Moolenaar 	else if (diff_check_fill(wp, lnum) >= wp->w_height - srow)
25837528d1f6SBram Moolenaar 	{
25847528d1f6SBram Moolenaar 	    // Window ends in filler lines.
25857528d1f6SBram Moolenaar 	    wp->w_botline = lnum;
25867528d1f6SBram Moolenaar 	    wp->w_filler_rows = wp->w_height - srow;
25877528d1f6SBram Moolenaar 	}
25887528d1f6SBram Moolenaar #endif
258905ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
25907528d1f6SBram Moolenaar 	else if (WIN_IS_POPUP(wp))
25917528d1f6SBram Moolenaar 	{
25927528d1f6SBram Moolenaar 	    // popup line that doesn't fit is left as-is
25937528d1f6SBram Moolenaar 	    wp->w_botline = lnum;
25947528d1f6SBram Moolenaar 	}
25957528d1f6SBram Moolenaar #endif
25967528d1f6SBram Moolenaar 	else if (dy_flags & DY_TRUNCATE)	// 'display' has "truncate"
25977528d1f6SBram Moolenaar 	{
25987528d1f6SBram Moolenaar 	    int scr_row = W_WINROW(wp) + wp->w_height - 1;
25997528d1f6SBram Moolenaar 
26007528d1f6SBram Moolenaar 	    // Last line isn't finished: Display "@@@" in the last screen line.
26017528d1f6SBram Moolenaar 	    screen_puts_len((char_u *)"@@", 2, scr_row, wp->w_wincol,
26027528d1f6SBram Moolenaar 							      HL_ATTR(HLF_AT));
26037528d1f6SBram Moolenaar 	    screen_fill(scr_row, scr_row + 1,
26047528d1f6SBram Moolenaar 		    (int)wp->w_wincol + 2, (int)W_ENDCOL(wp),
26057528d1f6SBram Moolenaar 		    '@', ' ', HL_ATTR(HLF_AT));
26067528d1f6SBram Moolenaar 	    set_empty_rows(wp, srow);
26077528d1f6SBram Moolenaar 	    wp->w_botline = lnum;
26087528d1f6SBram Moolenaar 	}
26097528d1f6SBram Moolenaar 	else if (dy_flags & DY_LASTLINE)	// 'display' has "lastline"
26107528d1f6SBram Moolenaar 	{
26117528d1f6SBram Moolenaar 	    // Last line isn't finished: Display "@@@" at the end.
26127528d1f6SBram Moolenaar 	    screen_fill(W_WINROW(wp) + wp->w_height - 1,
26137528d1f6SBram Moolenaar 		    W_WINROW(wp) + wp->w_height,
26147528d1f6SBram Moolenaar 		    (int)W_ENDCOL(wp) - 3, (int)W_ENDCOL(wp),
26157528d1f6SBram Moolenaar 		    '@', '@', HL_ATTR(HLF_AT));
26167528d1f6SBram Moolenaar 	    set_empty_rows(wp, srow);
26177528d1f6SBram Moolenaar 	    wp->w_botline = lnum;
26187528d1f6SBram Moolenaar 	}
26197528d1f6SBram Moolenaar 	else
26207528d1f6SBram Moolenaar 	{
26217528d1f6SBram Moolenaar 	    win_draw_end(wp, '@', ' ', TRUE, srow, wp->w_height, HLF_AT);
26227528d1f6SBram Moolenaar 	    wp->w_botline = lnum;
26237528d1f6SBram Moolenaar 	}
26247528d1f6SBram Moolenaar     }
26257528d1f6SBram Moolenaar     else
26267528d1f6SBram Moolenaar     {
26277528d1f6SBram Moolenaar 	draw_vsep_win(wp, row);
26287528d1f6SBram Moolenaar 	if (eof)		// we hit the end of the file
26297528d1f6SBram Moolenaar 	{
26307528d1f6SBram Moolenaar 	    wp->w_botline = buf->b_ml.ml_line_count + 1;
26317528d1f6SBram Moolenaar #ifdef FEAT_DIFF
26327528d1f6SBram Moolenaar 	    j = diff_check_fill(wp, wp->w_botline);
26337528d1f6SBram Moolenaar 	    if (j > 0 && !wp->w_botfill)
26347528d1f6SBram Moolenaar 	    {
26357528d1f6SBram Moolenaar 		// Display filler lines at the end of the file.
26367528d1f6SBram Moolenaar 		if (char2cells(fill_diff) > 1)
26377528d1f6SBram Moolenaar 		    i = '-';
26387528d1f6SBram Moolenaar 		else
26397528d1f6SBram Moolenaar 		    i = fill_diff;
26407528d1f6SBram Moolenaar 		if (row + j > wp->w_height)
26417528d1f6SBram Moolenaar 		    j = wp->w_height - row;
26427528d1f6SBram Moolenaar 		win_draw_end(wp, i, i, TRUE, row, row + (int)j, HLF_DED);
26437528d1f6SBram Moolenaar 		row += j;
26447528d1f6SBram Moolenaar 	    }
26457528d1f6SBram Moolenaar #endif
26467528d1f6SBram Moolenaar 	}
26477528d1f6SBram Moolenaar 	else if (dollar_vcol == -1)
26487528d1f6SBram Moolenaar 	    wp->w_botline = lnum;
26497528d1f6SBram Moolenaar 
26507528d1f6SBram Moolenaar 	// Make sure the rest of the screen is blank
2651a98f8a23SBram Moolenaar 	// write the 'fill_eob' character to rows that aren't part of the file
26521666ac9cSBram Moolenaar 	if (WIN_IS_POPUP(wp))
26531666ac9cSBram Moolenaar 	    win_draw_end(wp, ' ', ' ', FALSE, row, wp->w_height, HLF_AT);
26541666ac9cSBram Moolenaar 	else
2655a98f8a23SBram Moolenaar 	    win_draw_end(wp, fill_eob, ' ', FALSE, row, wp->w_height, HLF_EOB);
26567528d1f6SBram Moolenaar     }
26577528d1f6SBram Moolenaar 
26587528d1f6SBram Moolenaar #ifdef SYN_TIME_LIMIT
26597528d1f6SBram Moolenaar     syn_set_timeout(NULL);
26607528d1f6SBram Moolenaar #endif
26617528d1f6SBram Moolenaar 
26627528d1f6SBram Moolenaar     // Reset the type of redrawing required, the window has been updated.
26637528d1f6SBram Moolenaar     wp->w_redr_type = 0;
26647528d1f6SBram Moolenaar #ifdef FEAT_DIFF
26657528d1f6SBram Moolenaar     wp->w_old_topfill = wp->w_topfill;
26667528d1f6SBram Moolenaar     wp->w_old_botfill = wp->w_botfill;
26677528d1f6SBram Moolenaar #endif
26687528d1f6SBram Moolenaar 
26697528d1f6SBram Moolenaar     if (dollar_vcol == -1)
26707528d1f6SBram Moolenaar     {
26717528d1f6SBram Moolenaar 	// There is a trick with w_botline.  If we invalidate it on each
26727528d1f6SBram Moolenaar 	// change that might modify it, this will cause a lot of expensive
26737528d1f6SBram Moolenaar 	// calls to plines() in update_topline() each time.  Therefore the
26747528d1f6SBram Moolenaar 	// value of w_botline is often approximated, and this value is used to
26757528d1f6SBram Moolenaar 	// compute the value of w_topline.  If the value of w_botline was
26767528d1f6SBram Moolenaar 	// wrong, check that the value of w_topline is correct (cursor is on
26777528d1f6SBram Moolenaar 	// the visible part of the text).  If it's not, we need to redraw
26787528d1f6SBram Moolenaar 	// again.  Mostly this just means scrolling up a few lines, so it
26797528d1f6SBram Moolenaar 	// doesn't look too bad.  Only do this for the current window (where
26807528d1f6SBram Moolenaar 	// changes are relevant).
26817528d1f6SBram Moolenaar 	wp->w_valid |= VALID_BOTLINE;
26827528d1f6SBram Moolenaar 	if (wp == curwin && wp->w_botline != old_botline && !recursive)
26837528d1f6SBram Moolenaar 	{
2684cbee635eSBram Moolenaar 	    win_T	*wwp;
2685cbee635eSBram Moolenaar #if defined(FEAT_CONCEAL)
2686cbee635eSBram Moolenaar 	    linenr_T	old_topline = wp->w_topline;
2687cbee635eSBram Moolenaar 	    int		new_wcol = wp->w_wcol;
2688cbee635eSBram Moolenaar #endif
26897528d1f6SBram Moolenaar 	    recursive = TRUE;
26907528d1f6SBram Moolenaar 	    curwin->w_valid &= ~VALID_TOPLINE;
26917528d1f6SBram Moolenaar 	    update_topline();	// may invalidate w_botline again
2692cbee635eSBram Moolenaar 
2693cbee635eSBram Moolenaar #if defined(FEAT_CONCEAL)
2694cbee635eSBram Moolenaar 	    if (old_wcol != new_wcol && (wp->w_valid & (VALID_WCOL|VALID_WROW))
2695cbee635eSBram Moolenaar 						    != (VALID_WCOL|VALID_WROW))
2696cbee635eSBram Moolenaar 	    {
2697cbee635eSBram Moolenaar 		// A win_line() call applied a fix to screen cursor column to
269805ad5ff0SBram Moolenaar 		// accommodate concealment of cursor line, but in this call to
2699cbee635eSBram Moolenaar 		// update_topline() the cursor's row or column got invalidated.
2700cbee635eSBram Moolenaar 		// If they are left invalid, setcursor() will recompute them
2701cbee635eSBram Moolenaar 		// but there won't be any further win_line() call to re-fix the
2702cbee635eSBram Moolenaar 		// column and the cursor will end up misplaced.  So we call
2703cbee635eSBram Moolenaar 		// cursor validation now and reapply the fix again (or call
2704cbee635eSBram Moolenaar 		// win_line() to do it for us).
2705cbee635eSBram Moolenaar 		validate_cursor();
2706cbee635eSBram Moolenaar 		if (wp->w_wcol == old_wcol && wp->w_wrow == old_wrow
2707cbee635eSBram Moolenaar 					       && old_topline == wp->w_topline)
2708cbee635eSBram Moolenaar 		    wp->w_wcol = new_wcol;
2709cbee635eSBram Moolenaar 		else
2710cbee635eSBram Moolenaar 		    redrawWinline(wp, wp->w_cursor.lnum);
2711cbee635eSBram Moolenaar 	    }
2712cbee635eSBram Moolenaar #endif
2713cbee635eSBram Moolenaar 	    // New redraw either due to updated topline or due to wcol fix.
2714cbee635eSBram Moolenaar 	    if (wp->w_redr_type != 0)
27157528d1f6SBram Moolenaar 	    {
27167528d1f6SBram Moolenaar 		// Don't update for changes in buffer again.
27177528d1f6SBram Moolenaar 		i = curbuf->b_mod_set;
27187528d1f6SBram Moolenaar 		curbuf->b_mod_set = FALSE;
2719cbee635eSBram Moolenaar 		j = curbuf->b_mod_xlines;
2720cbee635eSBram Moolenaar 		curbuf->b_mod_xlines = 0;
27217528d1f6SBram Moolenaar 		win_update(curwin);
27227528d1f6SBram Moolenaar 		curbuf->b_mod_set = i;
2723cbee635eSBram Moolenaar 		curbuf->b_mod_xlines = j;
27247528d1f6SBram Moolenaar 	    }
2725cbee635eSBram Moolenaar 	    // Other windows might have w_redr_type raised in update_topline().
2726cbee635eSBram Moolenaar 	    must_redraw = 0;
2727cbee635eSBram Moolenaar 	    FOR_ALL_WINDOWS(wwp)
2728cbee635eSBram Moolenaar 		if (wwp->w_redr_type > must_redraw)
2729cbee635eSBram Moolenaar 		    must_redraw = wwp->w_redr_type;
27307528d1f6SBram Moolenaar 	    recursive = FALSE;
27317528d1f6SBram Moolenaar 	}
27327528d1f6SBram Moolenaar     }
27337528d1f6SBram Moolenaar 
27347528d1f6SBram Moolenaar #if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA)
27357528d1f6SBram Moolenaar     // restore got_int, unless CTRL-C was hit while redrawing
27367528d1f6SBram Moolenaar     if (!got_int)
27377528d1f6SBram Moolenaar 	got_int = save_got_int;
27387528d1f6SBram Moolenaar #endif
27397528d1f6SBram Moolenaar }
27407528d1f6SBram Moolenaar 
27417528d1f6SBram Moolenaar #if defined(FEAT_NETBEANS_INTG) || defined(FEAT_GUI)
27427528d1f6SBram Moolenaar /*
27437528d1f6SBram Moolenaar  * Prepare for updating one or more windows.
27447528d1f6SBram Moolenaar  * Caller must check for "updating_screen" already set to avoid recursiveness.
27457528d1f6SBram Moolenaar  */
27467528d1f6SBram Moolenaar     static void
update_prepare(void)27477528d1f6SBram Moolenaar update_prepare(void)
27487528d1f6SBram Moolenaar {
27497528d1f6SBram Moolenaar     cursor_off();
27507528d1f6SBram Moolenaar     updating_screen = TRUE;
27517528d1f6SBram Moolenaar #ifdef FEAT_GUI
27527528d1f6SBram Moolenaar     // Remove the cursor before starting to do anything, because scrolling may
27537528d1f6SBram Moolenaar     // make it difficult to redraw the text under it.
27547528d1f6SBram Moolenaar     if (gui.in_use)
27557528d1f6SBram Moolenaar 	gui_undraw_cursor();
27567528d1f6SBram Moolenaar #endif
27577528d1f6SBram Moolenaar #ifdef FEAT_SEARCH_EXTRA
27587528d1f6SBram Moolenaar     start_search_hl();
27597528d1f6SBram Moolenaar #endif
276005ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
27617528d1f6SBram Moolenaar     // Update popup_mask if needed.
27627528d1f6SBram Moolenaar     may_update_popup_mask(must_redraw);
27637528d1f6SBram Moolenaar #endif
27647528d1f6SBram Moolenaar }
27657528d1f6SBram Moolenaar 
27667528d1f6SBram Moolenaar /*
27677528d1f6SBram Moolenaar  * Finish updating one or more windows.
27687528d1f6SBram Moolenaar  */
27697528d1f6SBram Moolenaar     static void
update_finish(void)27707528d1f6SBram Moolenaar update_finish(void)
27717528d1f6SBram Moolenaar {
27727528d1f6SBram Moolenaar     if (redraw_cmdline || redraw_mode)
27737528d1f6SBram Moolenaar 	showmode();
27747528d1f6SBram Moolenaar 
27757528d1f6SBram Moolenaar # ifdef FEAT_SEARCH_EXTRA
27767528d1f6SBram Moolenaar     end_search_hl();
27777528d1f6SBram Moolenaar # endif
27787528d1f6SBram Moolenaar 
27797528d1f6SBram Moolenaar     after_updating_screen(TRUE);
27807528d1f6SBram Moolenaar 
27817528d1f6SBram Moolenaar # ifdef FEAT_GUI
27827528d1f6SBram Moolenaar     // Redraw the cursor and update the scrollbars when all screen updating is
27837528d1f6SBram Moolenaar     // done.
27847528d1f6SBram Moolenaar     if (gui.in_use)
27857528d1f6SBram Moolenaar     {
27867528d1f6SBram Moolenaar 	out_flush_cursor(FALSE, FALSE);
27877528d1f6SBram Moolenaar 	gui_update_scrollbars(FALSE);
27887528d1f6SBram Moolenaar     }
27897528d1f6SBram Moolenaar # endif
27907528d1f6SBram Moolenaar }
27917528d1f6SBram Moolenaar #endif
27927528d1f6SBram Moolenaar 
27937528d1f6SBram Moolenaar #if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
27947528d1f6SBram Moolenaar     void
update_debug_sign(buf_T * buf,linenr_T lnum)27957528d1f6SBram Moolenaar update_debug_sign(buf_T *buf, linenr_T lnum)
27967528d1f6SBram Moolenaar {
27977528d1f6SBram Moolenaar     win_T	*wp;
27987528d1f6SBram Moolenaar     int		doit = FALSE;
27997528d1f6SBram Moolenaar 
28007528d1f6SBram Moolenaar # ifdef FEAT_FOLDING
28017528d1f6SBram Moolenaar     win_foldinfo.fi_level = 0;
28027528d1f6SBram Moolenaar # endif
28037528d1f6SBram Moolenaar 
28047528d1f6SBram Moolenaar     // update/delete a specific sign
28057528d1f6SBram Moolenaar     redraw_buf_line_later(buf, lnum);
28067528d1f6SBram Moolenaar 
28077528d1f6SBram Moolenaar     // check if it resulted in the need to redraw a window
28087528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
28097528d1f6SBram Moolenaar 	if (wp->w_redr_type != 0)
28107528d1f6SBram Moolenaar 	    doit = TRUE;
28117528d1f6SBram Moolenaar 
28127528d1f6SBram Moolenaar     // Return when there is nothing to do, screen updating is already
28137528d1f6SBram Moolenaar     // happening (recursive call), messages on the screen or still starting up.
28147528d1f6SBram Moolenaar     if (!doit || updating_screen
28157528d1f6SBram Moolenaar 	    || State == ASKMORE || State == HITRETURN
28167528d1f6SBram Moolenaar 	    || msg_scrolled
28177528d1f6SBram Moolenaar #ifdef FEAT_GUI
28187528d1f6SBram Moolenaar 	    || gui.starting
28197528d1f6SBram Moolenaar #endif
28207528d1f6SBram Moolenaar 	    || starting)
28217528d1f6SBram Moolenaar 	return;
28227528d1f6SBram Moolenaar 
28237528d1f6SBram Moolenaar     // update all windows that need updating
28247528d1f6SBram Moolenaar     update_prepare();
28257528d1f6SBram Moolenaar 
28267528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
28277528d1f6SBram Moolenaar     {
28287528d1f6SBram Moolenaar 	if (wp->w_redr_type != 0)
28297528d1f6SBram Moolenaar 	    win_update(wp);
28307528d1f6SBram Moolenaar 	if (wp->w_redr_status)
28317528d1f6SBram Moolenaar 	    win_redr_status(wp, FALSE);
28327528d1f6SBram Moolenaar     }
28337528d1f6SBram Moolenaar 
28347528d1f6SBram Moolenaar     update_finish();
28357528d1f6SBram Moolenaar }
28367528d1f6SBram Moolenaar #endif
28377528d1f6SBram Moolenaar 
28387528d1f6SBram Moolenaar #if defined(FEAT_GUI) || defined(PROTO)
28397528d1f6SBram Moolenaar /*
28407528d1f6SBram Moolenaar  * Update a single window, its status line and maybe the command line msg.
28417528d1f6SBram Moolenaar  * Used for the GUI scrollbar.
28427528d1f6SBram Moolenaar  */
28437528d1f6SBram Moolenaar     void
updateWindow(win_T * wp)28447528d1f6SBram Moolenaar updateWindow(win_T *wp)
28457528d1f6SBram Moolenaar {
28467528d1f6SBram Moolenaar     // return if already busy updating
28477528d1f6SBram Moolenaar     if (updating_screen)
28487528d1f6SBram Moolenaar 	return;
28497528d1f6SBram Moolenaar 
28507528d1f6SBram Moolenaar     update_prepare();
28517528d1f6SBram Moolenaar 
28527528d1f6SBram Moolenaar #ifdef FEAT_CLIPBOARD
28537528d1f6SBram Moolenaar     // When Visual area changed, may have to update selection.
28547528d1f6SBram Moolenaar     if (clip_star.available && clip_isautosel_star())
28557528d1f6SBram Moolenaar 	clip_update_selection(&clip_star);
28567528d1f6SBram Moolenaar     if (clip_plus.available && clip_isautosel_plus())
28577528d1f6SBram Moolenaar 	clip_update_selection(&clip_plus);
28587528d1f6SBram Moolenaar #endif
28597528d1f6SBram Moolenaar 
28607528d1f6SBram Moolenaar     win_update(wp);
28617528d1f6SBram Moolenaar 
28627528d1f6SBram Moolenaar     // When the screen was cleared redraw the tab pages line.
28637528d1f6SBram Moolenaar     if (redraw_tabline)
28647528d1f6SBram Moolenaar 	draw_tabline();
28657528d1f6SBram Moolenaar 
28667528d1f6SBram Moolenaar     if (wp->w_redr_status
28677528d1f6SBram Moolenaar # ifdef FEAT_CMDL_INFO
28687528d1f6SBram Moolenaar 	    || p_ru
28697528d1f6SBram Moolenaar # endif
28707528d1f6SBram Moolenaar # ifdef FEAT_STL_OPT
28717528d1f6SBram Moolenaar 	    || *p_stl != NUL || *wp->w_p_stl != NUL
28727528d1f6SBram Moolenaar # endif
28737528d1f6SBram Moolenaar 	    )
28747528d1f6SBram Moolenaar 	win_redr_status(wp, FALSE);
28757528d1f6SBram Moolenaar 
287605ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
28777528d1f6SBram Moolenaar     // Display popup windows on top of everything.
28787528d1f6SBram Moolenaar     update_popups(win_update);
28797528d1f6SBram Moolenaar #endif
28807528d1f6SBram Moolenaar 
28817528d1f6SBram Moolenaar     update_finish();
28827528d1f6SBram Moolenaar }
28837528d1f6SBram Moolenaar #endif
28847528d1f6SBram Moolenaar 
28857528d1f6SBram Moolenaar #if defined(FEAT_TERMRESPONSE) || defined(PROTO)
28867528d1f6SBram Moolenaar /*
28877528d1f6SBram Moolenaar  * Redraw as soon as possible.  When the command line is not scrolled redraw
28887528d1f6SBram Moolenaar  * right away and restore what was on the command line.
28897528d1f6SBram Moolenaar  * Return a code indicating what happened.
28907528d1f6SBram Moolenaar  */
28917528d1f6SBram Moolenaar     int
redraw_asap(int type)28927528d1f6SBram Moolenaar redraw_asap(int type)
28937528d1f6SBram Moolenaar {
28947528d1f6SBram Moolenaar     int		rows;
28957528d1f6SBram Moolenaar     int		cols = screen_Columns;
28967528d1f6SBram Moolenaar     int		r;
28977528d1f6SBram Moolenaar     int		ret = 0;
28987528d1f6SBram Moolenaar     schar_T	*screenline;	// copy from ScreenLines[]
28997528d1f6SBram Moolenaar     sattr_T	*screenattr;	// copy from ScreenAttrs[]
29007528d1f6SBram Moolenaar     int		i;
29017528d1f6SBram Moolenaar     u8char_T	*screenlineUC = NULL;	// copy from ScreenLinesUC[]
29027528d1f6SBram Moolenaar     u8char_T	*screenlineC[MAX_MCO];	// copy from ScreenLinesC[][]
29037528d1f6SBram Moolenaar     schar_T	*screenline2 = NULL;	// copy from ScreenLines2[]
29047528d1f6SBram Moolenaar 
29057528d1f6SBram Moolenaar     redraw_later(type);
29067528d1f6SBram Moolenaar     if (msg_scrolled || (State != NORMAL && State != NORMAL_BUSY) || exiting)
29077528d1f6SBram Moolenaar 	return ret;
29087528d1f6SBram Moolenaar 
29097528d1f6SBram Moolenaar     // Allocate space to save the text displayed in the command line area.
29107528d1f6SBram Moolenaar     rows = screen_Rows - cmdline_row;
29117528d1f6SBram Moolenaar     screenline = LALLOC_MULT(schar_T, rows * cols);
29127528d1f6SBram Moolenaar     screenattr = LALLOC_MULT(sattr_T, rows * cols);
29137528d1f6SBram Moolenaar     if (screenline == NULL || screenattr == NULL)
29147528d1f6SBram Moolenaar 	ret = 2;
29157528d1f6SBram Moolenaar     if (enc_utf8)
29167528d1f6SBram Moolenaar     {
29177528d1f6SBram Moolenaar 	screenlineUC = LALLOC_MULT(u8char_T, rows * cols);
29187528d1f6SBram Moolenaar 	if (screenlineUC == NULL)
29197528d1f6SBram Moolenaar 	    ret = 2;
29207528d1f6SBram Moolenaar 	for (i = 0; i < p_mco; ++i)
29217528d1f6SBram Moolenaar 	{
29227528d1f6SBram Moolenaar 	    screenlineC[i] = LALLOC_MULT(u8char_T, rows * cols);
29237528d1f6SBram Moolenaar 	    if (screenlineC[i] == NULL)
29247528d1f6SBram Moolenaar 		ret = 2;
29257528d1f6SBram Moolenaar 	}
29267528d1f6SBram Moolenaar     }
29277528d1f6SBram Moolenaar     if (enc_dbcs == DBCS_JPNU)
29287528d1f6SBram Moolenaar     {
29297528d1f6SBram Moolenaar 	screenline2 = LALLOC_MULT(schar_T, rows * cols);
29307528d1f6SBram Moolenaar 	if (screenline2 == NULL)
29317528d1f6SBram Moolenaar 	    ret = 2;
29327528d1f6SBram Moolenaar     }
29337528d1f6SBram Moolenaar 
29347528d1f6SBram Moolenaar     if (ret != 2)
29357528d1f6SBram Moolenaar     {
29367528d1f6SBram Moolenaar 	// Save the text displayed in the command line area.
29377528d1f6SBram Moolenaar 	for (r = 0; r < rows; ++r)
29387528d1f6SBram Moolenaar 	{
29397528d1f6SBram Moolenaar 	    mch_memmove(screenline + r * cols,
29407528d1f6SBram Moolenaar 			ScreenLines + LineOffset[cmdline_row + r],
29417528d1f6SBram Moolenaar 			(size_t)cols * sizeof(schar_T));
29427528d1f6SBram Moolenaar 	    mch_memmove(screenattr + r * cols,
29437528d1f6SBram Moolenaar 			ScreenAttrs + LineOffset[cmdline_row + r],
29447528d1f6SBram Moolenaar 			(size_t)cols * sizeof(sattr_T));
29457528d1f6SBram Moolenaar 	    if (enc_utf8)
29467528d1f6SBram Moolenaar 	    {
29477528d1f6SBram Moolenaar 		mch_memmove(screenlineUC + r * cols,
29487528d1f6SBram Moolenaar 			    ScreenLinesUC + LineOffset[cmdline_row + r],
29497528d1f6SBram Moolenaar 			    (size_t)cols * sizeof(u8char_T));
29507528d1f6SBram Moolenaar 		for (i = 0; i < p_mco; ++i)
29517528d1f6SBram Moolenaar 		    mch_memmove(screenlineC[i] + r * cols,
29527528d1f6SBram Moolenaar 				ScreenLinesC[i] + LineOffset[cmdline_row + r],
29537528d1f6SBram Moolenaar 				(size_t)cols * sizeof(u8char_T));
29547528d1f6SBram Moolenaar 	    }
29557528d1f6SBram Moolenaar 	    if (enc_dbcs == DBCS_JPNU)
29567528d1f6SBram Moolenaar 		mch_memmove(screenline2 + r * cols,
29577528d1f6SBram Moolenaar 			    ScreenLines2 + LineOffset[cmdline_row + r],
29587528d1f6SBram Moolenaar 			    (size_t)cols * sizeof(schar_T));
29597528d1f6SBram Moolenaar 	}
29607528d1f6SBram Moolenaar 
29617528d1f6SBram Moolenaar 	update_screen(0);
29627528d1f6SBram Moolenaar 	ret = 3;
29637528d1f6SBram Moolenaar 
29647528d1f6SBram Moolenaar 	if (must_redraw == 0)
29657528d1f6SBram Moolenaar 	{
29667528d1f6SBram Moolenaar 	    int	off = (int)(current_ScreenLine - ScreenLines);
29677528d1f6SBram Moolenaar 
29687528d1f6SBram Moolenaar 	    // Restore the text displayed in the command line area.
29697528d1f6SBram Moolenaar 	    for (r = 0; r < rows; ++r)
29707528d1f6SBram Moolenaar 	    {
29717528d1f6SBram Moolenaar 		mch_memmove(current_ScreenLine,
29727528d1f6SBram Moolenaar 			    screenline + r * cols,
29737528d1f6SBram Moolenaar 			    (size_t)cols * sizeof(schar_T));
29747528d1f6SBram Moolenaar 		mch_memmove(ScreenAttrs + off,
29757528d1f6SBram Moolenaar 			    screenattr + r * cols,
29767528d1f6SBram Moolenaar 			    (size_t)cols * sizeof(sattr_T));
29777528d1f6SBram Moolenaar 		if (enc_utf8)
29787528d1f6SBram Moolenaar 		{
29797528d1f6SBram Moolenaar 		    mch_memmove(ScreenLinesUC + off,
29807528d1f6SBram Moolenaar 				screenlineUC + r * cols,
29817528d1f6SBram Moolenaar 				(size_t)cols * sizeof(u8char_T));
29827528d1f6SBram Moolenaar 		    for (i = 0; i < p_mco; ++i)
29837528d1f6SBram Moolenaar 			mch_memmove(ScreenLinesC[i] + off,
29847528d1f6SBram Moolenaar 				    screenlineC[i] + r * cols,
29857528d1f6SBram Moolenaar 				    (size_t)cols * sizeof(u8char_T));
29867528d1f6SBram Moolenaar 		}
29877528d1f6SBram Moolenaar 		if (enc_dbcs == DBCS_JPNU)
29887528d1f6SBram Moolenaar 		    mch_memmove(ScreenLines2 + off,
29897528d1f6SBram Moolenaar 				screenline2 + r * cols,
29907528d1f6SBram Moolenaar 				(size_t)cols * sizeof(schar_T));
29917528d1f6SBram Moolenaar 		screen_line(cmdline_row + r, 0, cols, cols, 0);
29927528d1f6SBram Moolenaar 	    }
29937528d1f6SBram Moolenaar 	    ret = 4;
29947528d1f6SBram Moolenaar 	}
29957528d1f6SBram Moolenaar     }
29967528d1f6SBram Moolenaar 
29977528d1f6SBram Moolenaar     vim_free(screenline);
29987528d1f6SBram Moolenaar     vim_free(screenattr);
29997528d1f6SBram Moolenaar     if (enc_utf8)
30007528d1f6SBram Moolenaar     {
30017528d1f6SBram Moolenaar 	vim_free(screenlineUC);
30027528d1f6SBram Moolenaar 	for (i = 0; i < p_mco; ++i)
30037528d1f6SBram Moolenaar 	    vim_free(screenlineC[i]);
30047528d1f6SBram Moolenaar     }
30057528d1f6SBram Moolenaar     if (enc_dbcs == DBCS_JPNU)
30067528d1f6SBram Moolenaar 	vim_free(screenline2);
30077528d1f6SBram Moolenaar 
30087528d1f6SBram Moolenaar     // Show the intro message when appropriate.
30097528d1f6SBram Moolenaar     maybe_intro_message();
30107528d1f6SBram Moolenaar 
30117528d1f6SBram Moolenaar     setcursor();
30127528d1f6SBram Moolenaar 
30137528d1f6SBram Moolenaar     return ret;
30147528d1f6SBram Moolenaar }
30157528d1f6SBram Moolenaar #endif
30167528d1f6SBram Moolenaar 
30177528d1f6SBram Moolenaar /*
30187528d1f6SBram Moolenaar  * Invoked after an asynchronous callback is called.
30197528d1f6SBram Moolenaar  * If an echo command was used the cursor needs to be put back where
30207528d1f6SBram Moolenaar  * it belongs. If highlighting was changed a redraw is needed.
30217528d1f6SBram Moolenaar  * If "call_update_screen" is FALSE don't call update_screen() when at the
30227528d1f6SBram Moolenaar  * command line.
30237528d1f6SBram Moolenaar  */
30247528d1f6SBram Moolenaar     void
redraw_after_callback(int call_update_screen)30257528d1f6SBram Moolenaar redraw_after_callback(int call_update_screen)
30267528d1f6SBram Moolenaar {
30277528d1f6SBram Moolenaar     ++redrawing_for_callback;
30287528d1f6SBram Moolenaar 
30297528d1f6SBram Moolenaar     if (State == HITRETURN || State == ASKMORE)
30307528d1f6SBram Moolenaar 	; // do nothing
30317528d1f6SBram Moolenaar     else if (State & CMDLINE)
30327528d1f6SBram Moolenaar     {
30337528d1f6SBram Moolenaar 	// Don't redraw when in prompt_for_number().
30347528d1f6SBram Moolenaar 	if (cmdline_row > 0)
30357528d1f6SBram Moolenaar 	{
30367528d1f6SBram Moolenaar 	    // Redrawing only works when the screen didn't scroll. Don't clear
30377528d1f6SBram Moolenaar 	    // wildmenu entries.
30387528d1f6SBram Moolenaar 	    if (msg_scrolled == 0
30397528d1f6SBram Moolenaar #ifdef FEAT_WILDMENU
30407528d1f6SBram Moolenaar 		    && wild_menu_showing == 0
30417528d1f6SBram Moolenaar #endif
30427528d1f6SBram Moolenaar 		    && call_update_screen)
30437528d1f6SBram Moolenaar 		update_screen(0);
30447528d1f6SBram Moolenaar 
30457528d1f6SBram Moolenaar 	    // Redraw in the same position, so that the user can continue
30467528d1f6SBram Moolenaar 	    // editing the command.
30477528d1f6SBram Moolenaar 	    redrawcmdline_ex(FALSE);
30487528d1f6SBram Moolenaar 	}
30497528d1f6SBram Moolenaar     }
30507528d1f6SBram Moolenaar     else if (State & (NORMAL | INSERT | TERMINAL))
30517528d1f6SBram Moolenaar     {
30527528d1f6SBram Moolenaar 	// keep the command line if possible
30537528d1f6SBram Moolenaar 	update_screen(VALID_NO_UPDATE);
30547528d1f6SBram Moolenaar 	setcursor();
30559f28416eSBram Moolenaar 
30569f28416eSBram Moolenaar 	if (msg_scrolled == 0)
30579f28416eSBram Moolenaar 	{
30589f28416eSBram Moolenaar 	    // don't want a hit-enter prompt when something else is displayed
30599f28416eSBram Moolenaar 	    msg_didany = FALSE;
30609f28416eSBram Moolenaar 	    need_wait_return = FALSE;
30619f28416eSBram Moolenaar 	}
30627528d1f6SBram Moolenaar     }
30637528d1f6SBram Moolenaar     cursor_on();
30647528d1f6SBram Moolenaar #ifdef FEAT_GUI
30657528d1f6SBram Moolenaar     if (gui.in_use && !gui_mch_is_blink_off())
30667528d1f6SBram Moolenaar 	// Don't update the cursor when it is blinking and off to avoid
30677528d1f6SBram Moolenaar 	// flicker.
30687528d1f6SBram Moolenaar 	out_flush_cursor(FALSE, FALSE);
30697528d1f6SBram Moolenaar     else
30707528d1f6SBram Moolenaar #endif
30717528d1f6SBram Moolenaar 	out_flush();
30727528d1f6SBram Moolenaar 
30737528d1f6SBram Moolenaar     --redrawing_for_callback;
30747528d1f6SBram Moolenaar }
30757528d1f6SBram Moolenaar 
30767528d1f6SBram Moolenaar /*
30777528d1f6SBram Moolenaar  * Redraw the current window later, with update_screen(type).
30787528d1f6SBram Moolenaar  * Set must_redraw only if not already set to a higher value.
30797528d1f6SBram Moolenaar  * E.g. if must_redraw is CLEAR, type NOT_VALID will do nothing.
30807528d1f6SBram Moolenaar  */
30817528d1f6SBram Moolenaar     void
redraw_later(int type)30827528d1f6SBram Moolenaar redraw_later(int type)
30837528d1f6SBram Moolenaar {
30847528d1f6SBram Moolenaar     redraw_win_later(curwin, type);
30857528d1f6SBram Moolenaar }
30867528d1f6SBram Moolenaar 
30877528d1f6SBram Moolenaar     void
redraw_win_later(win_T * wp,int type)30887528d1f6SBram Moolenaar redraw_win_later(
30897528d1f6SBram Moolenaar     win_T	*wp,
30907528d1f6SBram Moolenaar     int		type)
30917528d1f6SBram Moolenaar {
30927528d1f6SBram Moolenaar     if (!exiting && wp->w_redr_type < type)
30937528d1f6SBram Moolenaar     {
30947528d1f6SBram Moolenaar 	wp->w_redr_type = type;
30957528d1f6SBram Moolenaar 	if (type >= NOT_VALID)
30967528d1f6SBram Moolenaar 	    wp->w_lines_valid = 0;
30977528d1f6SBram Moolenaar 	if (must_redraw < type)	// must_redraw is the maximum of all windows
30987528d1f6SBram Moolenaar 	    must_redraw = type;
30997528d1f6SBram Moolenaar     }
31007528d1f6SBram Moolenaar }
31017528d1f6SBram Moolenaar 
31027528d1f6SBram Moolenaar /*
31037528d1f6SBram Moolenaar  * Force a complete redraw later.  Also resets the highlighting.  To be used
31047528d1f6SBram Moolenaar  * after executing a shell command that messes up the screen.
31057528d1f6SBram Moolenaar  */
31067528d1f6SBram Moolenaar     void
redraw_later_clear(void)31077528d1f6SBram Moolenaar redraw_later_clear(void)
31087528d1f6SBram Moolenaar {
31097528d1f6SBram Moolenaar     redraw_all_later(CLEAR);
31107528d1f6SBram Moolenaar     reset_screen_attr();
31117528d1f6SBram Moolenaar }
31127528d1f6SBram Moolenaar 
31137528d1f6SBram Moolenaar /*
31147528d1f6SBram Moolenaar  * Mark all windows to be redrawn later.
31157528d1f6SBram Moolenaar  */
31167528d1f6SBram Moolenaar     void
redraw_all_later(int type)31177528d1f6SBram Moolenaar redraw_all_later(int type)
31187528d1f6SBram Moolenaar {
31197528d1f6SBram Moolenaar     win_T	*wp;
31207528d1f6SBram Moolenaar 
31217528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
31227528d1f6SBram Moolenaar 	redraw_win_later(wp, type);
31237528d1f6SBram Moolenaar     // This may be needed when switching tabs.
31247528d1f6SBram Moolenaar     if (must_redraw < type)
31257528d1f6SBram Moolenaar 	must_redraw = type;
31267528d1f6SBram Moolenaar }
31277528d1f6SBram Moolenaar 
31287528d1f6SBram Moolenaar /*
31297528d1f6SBram Moolenaar  * Mark all windows that are editing the current buffer to be updated later.
31307528d1f6SBram Moolenaar  */
31317528d1f6SBram Moolenaar     void
redraw_curbuf_later(int type)31327528d1f6SBram Moolenaar redraw_curbuf_later(int type)
31337528d1f6SBram Moolenaar {
31347528d1f6SBram Moolenaar     redraw_buf_later(curbuf, type);
31357528d1f6SBram Moolenaar }
31367528d1f6SBram Moolenaar 
31377528d1f6SBram Moolenaar     void
redraw_buf_later(buf_T * buf,int type)31387528d1f6SBram Moolenaar redraw_buf_later(buf_T *buf, int type)
31397528d1f6SBram Moolenaar {
31407528d1f6SBram Moolenaar     win_T	*wp;
31417528d1f6SBram Moolenaar 
31427528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
31437528d1f6SBram Moolenaar     {
31447528d1f6SBram Moolenaar 	if (wp->w_buffer == buf)
31457528d1f6SBram Moolenaar 	    redraw_win_later(wp, type);
31467528d1f6SBram Moolenaar     }
3147e52e0c89SBram Moolenaar #if defined(FEAT_TERMINAL) && defined(FEAT_PROP_POPUP)
3148e52e0c89SBram Moolenaar     // terminal in popup window is not in list of windows
3149e52e0c89SBram Moolenaar     if (curwin->w_buffer == buf)
3150e52e0c89SBram Moolenaar 	redraw_win_later(curwin, type);
3151e52e0c89SBram Moolenaar #endif
31527528d1f6SBram Moolenaar }
31537528d1f6SBram Moolenaar 
31547528d1f6SBram Moolenaar #if defined(FEAT_SIGNS) || defined(PROTO)
31557528d1f6SBram Moolenaar     void
redraw_buf_line_later(buf_T * buf,linenr_T lnum)31567528d1f6SBram Moolenaar redraw_buf_line_later(buf_T *buf, linenr_T lnum)
31577528d1f6SBram Moolenaar {
31587528d1f6SBram Moolenaar     win_T	*wp;
31597528d1f6SBram Moolenaar 
31607528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
31617528d1f6SBram Moolenaar 	if (wp->w_buffer == buf && lnum >= wp->w_topline
31627528d1f6SBram Moolenaar 						  && lnum < wp->w_botline)
31637528d1f6SBram Moolenaar 	    redrawWinline(wp, lnum);
31647528d1f6SBram Moolenaar }
31657528d1f6SBram Moolenaar #endif
31667528d1f6SBram Moolenaar 
31677528d1f6SBram Moolenaar #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
31687528d1f6SBram Moolenaar     void
redraw_buf_and_status_later(buf_T * buf,int type)31697528d1f6SBram Moolenaar redraw_buf_and_status_later(buf_T *buf, int type)
31707528d1f6SBram Moolenaar {
31717528d1f6SBram Moolenaar     win_T	*wp;
31727528d1f6SBram Moolenaar 
31737528d1f6SBram Moolenaar #ifdef FEAT_WILDMENU
31747528d1f6SBram Moolenaar     if (wild_menu_showing != 0)
31757528d1f6SBram Moolenaar 	// Don't redraw while the command line completion is displayed, it
31767528d1f6SBram Moolenaar 	// would disappear.
31777528d1f6SBram Moolenaar 	return;
31787528d1f6SBram Moolenaar #endif
31797528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
31807528d1f6SBram Moolenaar     {
31817528d1f6SBram Moolenaar 	if (wp->w_buffer == buf)
31827528d1f6SBram Moolenaar 	{
31837528d1f6SBram Moolenaar 	    redraw_win_later(wp, type);
31847528d1f6SBram Moolenaar 	    wp->w_redr_status = TRUE;
31857528d1f6SBram Moolenaar 	}
31867528d1f6SBram Moolenaar     }
31877528d1f6SBram Moolenaar }
31887528d1f6SBram Moolenaar #endif
31897528d1f6SBram Moolenaar 
31907528d1f6SBram Moolenaar /*
31917528d1f6SBram Moolenaar  * mark all status lines for redraw; used after first :cd
31927528d1f6SBram Moolenaar  */
31937528d1f6SBram Moolenaar     void
status_redraw_all(void)31947528d1f6SBram Moolenaar status_redraw_all(void)
31957528d1f6SBram Moolenaar {
31967528d1f6SBram Moolenaar     win_T	*wp;
31977528d1f6SBram Moolenaar 
31987528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
31997528d1f6SBram Moolenaar 	if (wp->w_status_height)
32007528d1f6SBram Moolenaar 	{
32017528d1f6SBram Moolenaar 	    wp->w_redr_status = TRUE;
32027528d1f6SBram Moolenaar 	    redraw_later(VALID);
32037528d1f6SBram Moolenaar 	}
32047528d1f6SBram Moolenaar }
32057528d1f6SBram Moolenaar 
32067528d1f6SBram Moolenaar /*
32077528d1f6SBram Moolenaar  * mark all status lines of the current buffer for redraw
32087528d1f6SBram Moolenaar  */
32097528d1f6SBram Moolenaar     void
status_redraw_curbuf(void)32107528d1f6SBram Moolenaar status_redraw_curbuf(void)
32117528d1f6SBram Moolenaar {
32127528d1f6SBram Moolenaar     win_T	*wp;
32137528d1f6SBram Moolenaar 
32147528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
32157528d1f6SBram Moolenaar 	if (wp->w_status_height != 0 && wp->w_buffer == curbuf)
32167528d1f6SBram Moolenaar 	{
32177528d1f6SBram Moolenaar 	    wp->w_redr_status = TRUE;
32187528d1f6SBram Moolenaar 	    redraw_later(VALID);
32197528d1f6SBram Moolenaar 	}
32207528d1f6SBram Moolenaar }
32217528d1f6SBram Moolenaar 
32227528d1f6SBram Moolenaar /*
32237528d1f6SBram Moolenaar  * Redraw all status lines that need to be redrawn.
32247528d1f6SBram Moolenaar  */
32257528d1f6SBram Moolenaar     void
redraw_statuslines(void)32267528d1f6SBram Moolenaar redraw_statuslines(void)
32277528d1f6SBram Moolenaar {
32287528d1f6SBram Moolenaar     win_T	*wp;
32297528d1f6SBram Moolenaar 
32307528d1f6SBram Moolenaar     FOR_ALL_WINDOWS(wp)
32317528d1f6SBram Moolenaar 	if (wp->w_redr_status)
32327528d1f6SBram Moolenaar 	    win_redr_status(wp, FALSE);
32337528d1f6SBram Moolenaar     if (redraw_tabline)
32347528d1f6SBram Moolenaar 	draw_tabline();
32357528d1f6SBram Moolenaar }
32367528d1f6SBram Moolenaar 
32377528d1f6SBram Moolenaar #if defined(FEAT_WILDMENU) || defined(PROTO)
32387528d1f6SBram Moolenaar /*
32397528d1f6SBram Moolenaar  * Redraw all status lines at the bottom of frame "frp".
32407528d1f6SBram Moolenaar  */
32417528d1f6SBram Moolenaar     void
win_redraw_last_status(frame_T * frp)32427528d1f6SBram Moolenaar win_redraw_last_status(frame_T *frp)
32437528d1f6SBram Moolenaar {
32447528d1f6SBram Moolenaar     if (frp->fr_layout == FR_LEAF)
32457528d1f6SBram Moolenaar 	frp->fr_win->w_redr_status = TRUE;
32467528d1f6SBram Moolenaar     else if (frp->fr_layout == FR_ROW)
32477528d1f6SBram Moolenaar     {
32487528d1f6SBram Moolenaar 	FOR_ALL_FRAMES(frp, frp->fr_child)
32497528d1f6SBram Moolenaar 	    win_redraw_last_status(frp);
32507528d1f6SBram Moolenaar     }
32517528d1f6SBram Moolenaar     else // frp->fr_layout == FR_COL
32527528d1f6SBram Moolenaar     {
32537528d1f6SBram Moolenaar 	frp = frp->fr_child;
32547528d1f6SBram Moolenaar 	while (frp->fr_next != NULL)
32557528d1f6SBram Moolenaar 	    frp = frp->fr_next;
32567528d1f6SBram Moolenaar 	win_redraw_last_status(frp);
32577528d1f6SBram Moolenaar     }
32587528d1f6SBram Moolenaar }
32597528d1f6SBram Moolenaar #endif
32607528d1f6SBram Moolenaar 
32617528d1f6SBram Moolenaar /*
32627528d1f6SBram Moolenaar  * Changed something in the current window, at buffer line "lnum", that
32637528d1f6SBram Moolenaar  * requires that line and possibly other lines to be redrawn.
32647528d1f6SBram Moolenaar  * Used when entering/leaving Insert mode with the cursor on a folded line.
32657528d1f6SBram Moolenaar  * Used to remove the "$" from a change command.
32667528d1f6SBram Moolenaar  * Note that when also inserting/deleting lines w_redraw_top and w_redraw_bot
32677528d1f6SBram Moolenaar  * may become invalid and the whole window will have to be redrawn.
32687528d1f6SBram Moolenaar  */
32697528d1f6SBram Moolenaar     void
redrawWinline(win_T * wp,linenr_T lnum)32707528d1f6SBram Moolenaar redrawWinline(
32717528d1f6SBram Moolenaar     win_T	*wp,
32727528d1f6SBram Moolenaar     linenr_T	lnum)
32737528d1f6SBram Moolenaar {
32747528d1f6SBram Moolenaar     if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum)
32757528d1f6SBram Moolenaar 	wp->w_redraw_top = lnum;
32767528d1f6SBram Moolenaar     if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum)
32777528d1f6SBram Moolenaar 	wp->w_redraw_bot = lnum;
32787528d1f6SBram Moolenaar     redraw_win_later(wp, VALID);
32797528d1f6SBram Moolenaar }
3280