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