diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/buffer.c | 2 | ||||
-rw-r--r-- | src/nvim/api/ui.c | 5 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 99 | ||||
-rw-r--r-- | src/nvim/buffer.c | 4 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 7 | ||||
-rw-r--r-- | src/nvim/charset.c | 24 | ||||
-rw-r--r-- | src/nvim/cursor.c | 8 | ||||
-rw-r--r-- | src/nvim/edit.c | 8 | ||||
-rw-r--r-- | src/nvim/eval.c | 4 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 10 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 6 | ||||
-rw-r--r-- | src/nvim/getchar.c | 6 | ||||
-rw-r--r-- | src/nvim/grid_defs.h | 8 | ||||
-rw-r--r-- | src/nvim/indent.c | 2 | ||||
-rw-r--r-- | src/nvim/memline_defs.h | 71 | ||||
-rw-r--r-- | src/nvim/menu.c | 55 | ||||
-rw-r--r-- | src/nvim/misc1.c | 12 | ||||
-rw-r--r-- | src/nvim/mouse.c | 18 | ||||
-rw-r--r-- | src/nvim/move.c | 127 | ||||
-rw-r--r-- | src/nvim/normal.c | 30 | ||||
-rw-r--r-- | src/nvim/option.c | 2 | ||||
-rw-r--r-- | src/nvim/screen.c | 105 | ||||
-rw-r--r-- | src/nvim/screen.h | 3 | ||||
-rw-r--r-- | src/nvim/search.c | 2 | ||||
-rw-r--r-- | src/nvim/terminal.c | 37 | ||||
-rw-r--r-- | src/nvim/testdir/test_menu.vim | 23 | ||||
-rw-r--r-- | src/nvim/ui.c | 8 | ||||
-rw-r--r-- | src/nvim/window.c | 164 |
28 files changed, 427 insertions, 423 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 5df0f0bb47..9cd178eaeb 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -104,7 +104,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) /// the whole buffer. If so, the first notification will be a /// `nvim_buf_lines_event`. Otherwise, the first notification will be /// a `nvim_buf_changedtick_event` -/// @param opts Optional parameters. Currently not used. +/// @param opts Optional parameters. Reserved for future use. /// @param[out] err Details of an error that may have occurred /// @return False when updates couldn't be enabled because the buffer isn't /// loaded or `opts` contained an invalid key; otherwise True. diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 7ba5251c60..bc8a1a941f 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -245,9 +245,8 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, name.data); } -/// Tell nvim to resize a grid. Nvim sends grid_resize event with the -/// requested grid size is within size limits and with maximum allowed size -/// otherwise. +/// Tell Nvim to resize a grid. Triggers a grid_resize event with the requested +/// grid size or the maximum size if it exceeds size limits. /// /// On invalid grid handle, fails with error. /// diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 7f62333d88..5b59ff39f4 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -198,9 +198,8 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) /// @note |keycodes| like <CR> are translated, so "<" is special. /// To input a literal "<", send <LT>. /// -/// For mouse events use |nvim_input_mouse()|. For back-compat reasons -/// this method supports mouse input as "<LeftMouse><col,row>". This -/// usage is deprecated since API level 6, use the dedicated method instead. +/// @note For mouse events use |nvim_input_mouse()|. The pseudokey form +/// "<LeftMouse><col,row>" is deprecated since |api-level| 6. /// /// @param keys to be typed /// @return Number of bytes actually written (can be fewer than @@ -211,7 +210,7 @@ Integer nvim_input(String keys) return (Integer)input_enqueue(keys); } -/// Send mouse event from GUI +/// Send mouse event from GUI. /// /// The call is non-blocking. It doesn't wait on any resulting action, but /// queues the event to be processed soon by the event loop. @@ -220,20 +219,18 @@ Integer nvim_input(String keys) /// by calling it multiple times in a loop: the intermediate mouse /// positions will be ignored. It should be used to implement real-time /// mouse input in a GUI. The deprecated pseudokey form -/// ("<LeftMouse><col,row>") in |nvim_input()| has the same limitiation. +/// ("<LeftMouse><col,row>") of |nvim_input()| has the same limitiation. /// -/// @param button Which mouse button, one of "left", "right", "middle" or -/// "wheel". -/// @param action For ordinary buttons, one of "press", "drag" and "release" -/// For the wheel, use "up", "down", "left" and "right". +/// @param button Mouse button: one of "left", "right", "middle", "wheel". +/// @param action For ordinary buttons, one of "press", "drag", "release". +/// For the wheel, one of "up", "down", "left", "right". /// @param modifier String of modifiers each represented by a single char. /// The same specifiers are used as for a key press, except /// that the "-" separator is optional, so "C-A-", "c-a" -/// and "CA" can all be used to specify Ctrl+Alt+click -/// @param grid For a client using |ui-multigrid| pass in the grid number. -/// Other clients should pass in 0 (not 1). -/// @param row row position of mouse (zero-based, like in redraw events) -/// @param col column position of mouse (zero-based, like in redraw events) +/// and "CA" can all be used to specify Ctrl+Alt+click. +/// @param grid Grid number if the client uses |ui-multigrid|, else 0. +/// @param row Mouse row-position (zero-based, like redraw events) +/// @param col Mouse column-position (zero-based, like redraw events) void nvim_input_mouse(String button, String action, String modifier, Integer grid, Integer row, Integer col, Error *err) FUNC_API_SINCE(6) FUNC_API_ASYNC @@ -694,7 +691,7 @@ void nvim_set_current_dir(String dir, Error *err) try_end(err); } -/// Gets the current line +/// Gets the current line. /// /// @param[out] err Error details, if any /// @return Current line string @@ -704,7 +701,7 @@ String nvim_get_current_line(Error *err) return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } -/// Sets the current line +/// Sets the current line. /// /// @param line Line contents /// @param[out] err Error details, if any @@ -714,7 +711,7 @@ void nvim_set_current_line(String line, Error *err) buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err); } -/// Deletes the current line +/// Deletes the current line. /// /// @param[out] err Error details, if any void nvim_del_current_line(Error *err) @@ -723,7 +720,7 @@ void nvim_del_current_line(Error *err) buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } -/// Gets a global (g:) variable +/// Gets a global (g:) variable. /// /// @param name Variable name /// @param[out] err Error details, if any @@ -734,7 +731,7 @@ Object nvim_get_var(String name, Error *err) return dict_get_value(&globvardict, name, err); } -/// Sets a global (g:) variable +/// Sets a global (g:) variable. /// /// @param name Variable name /// @param value Variable value @@ -745,7 +742,7 @@ void nvim_set_var(String name, Object value, Error *err) dict_set_var(&globvardict, name, value, false, false, err); } -/// Removes a global (g:) variable +/// Removes a global (g:) variable. /// /// @param name Variable name /// @param[out] err Error details, if any @@ -772,7 +769,7 @@ Object vim_del_var(String name, Error *err) return dict_set_var(&globvardict, name, NIL, true, true, err); } -/// Gets a v: variable +/// Gets a v: variable. /// /// @param name Variable name /// @param[out] err Error details, if any @@ -783,7 +780,7 @@ Object nvim_get_vvar(String name, Error *err) return dict_get_value(&vimvardict, name, err); } -/// Sets a v: variable, if it is not readonly +/// Sets a v: variable, if it is not readonly. /// /// @param name Variable name /// @param value Variable value @@ -794,7 +791,7 @@ void nvim_set_vvar(String name, Object value, Error *err) dict_set_var(&vimvardict, name, value, false, false, err); } -/// Gets an option value string +/// Gets an option value string. /// /// @param name Option name /// @param[out] err Error details, if any @@ -805,7 +802,7 @@ Object nvim_get_option(String name, Error *err) return get_option_from(NULL, SREQ_GLOBAL, name, err); } -/// Sets an option value +/// Sets an option value. /// /// @param name Option name /// @param value New option value @@ -873,7 +870,7 @@ ArrayOf(Buffer) nvim_list_bufs(void) return rv; } -/// Gets the current buffer +/// Gets the current buffer. /// /// @return Buffer handle Buffer nvim_get_current_buf(void) @@ -882,7 +879,7 @@ Buffer nvim_get_current_buf(void) return curbuf->handle; } -/// Sets the current buffer +/// Sets the current buffer. /// /// @param buffer Buffer handle /// @param[out] err Error details, if any @@ -905,7 +902,7 @@ void nvim_set_current_buf(Buffer buffer, Error *err) } } -/// Gets the current list of window handles +/// Gets the current list of window handles. /// /// @return List of window handles ArrayOf(Window) nvim_list_wins(void) @@ -927,7 +924,7 @@ ArrayOf(Window) nvim_list_wins(void) return rv; } -/// Gets the current window +/// Gets the current window. /// /// @return Window handle Window nvim_get_current_win(void) @@ -936,7 +933,7 @@ Window nvim_get_current_win(void) return curwin->handle; } -/// Sets the current window +/// Sets the current window. /// /// @param window Window handle void nvim_set_current_win(Window window, Error *err) @@ -958,7 +955,7 @@ void nvim_set_current_win(Window window, Error *err) } } -/// Gets the current list of tabpage handles +/// Gets the current list of tabpage handles. /// /// @return List of tabpage handles ArrayOf(Tabpage) nvim_list_tabpages(void) @@ -980,7 +977,7 @@ ArrayOf(Tabpage) nvim_list_tabpages(void) return rv; } -/// Gets the current tabpage +/// Gets the current tabpage. /// /// @return Tabpage handle Tabpage nvim_get_current_tabpage(void) @@ -989,7 +986,7 @@ Tabpage nvim_get_current_tabpage(void) return curtab->handle; } -/// Sets the current tabpage +/// Sets the current tabpage. /// /// @param tabpage Tabpage handle /// @param[out] err Error details, if any @@ -1012,7 +1009,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) } } -/// Creates a new namespace, or gets an existing one +/// Creates a new namespace, or gets an existing one. /// /// Namespaces are used for buffer highlights and virtual text, see /// |nvim_buf_add_highlight()| and |nvim_buf_set_virtual_text()|. @@ -1038,7 +1035,7 @@ Integer nvim_create_namespace(String name) return (Integer)id; } -/// Gets existing, non-anonymous namespaces +/// Gets existing, non-anonymous namespaces. /// /// @return dict that maps from names to namespace ids. Dictionary nvim_get_namespaces(void) @@ -1055,7 +1052,7 @@ Dictionary nvim_get_namespaces(void) return retval; } -/// Subscribes to event broadcasts +/// Subscribes to event broadcasts. /// /// @param channel_id Channel id (passed automatically by the dispatcher) /// @param event Event type string @@ -1069,7 +1066,7 @@ void nvim_subscribe(uint64_t channel_id, String event) rpc_subscribe(channel_id, e); } -/// Unsubscribes to event broadcasts +/// Unsubscribes to event broadcasts. /// /// @param channel_id Channel id (passed automatically by the dispatcher) /// @param event Event type string @@ -1379,7 +1376,7 @@ typedef struct { typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// @endcond -/// Parse a VimL expression +/// Parse a VimL expression. /// /// @param[in] expr Expression to parse. Is always treated as a single line. /// @param[in] flags Flags: @@ -1860,7 +1857,7 @@ static void write_msg(String message, bool to_err) // Functions used for testing purposes -/// Returns object given as argument +/// Returns object given as argument. /// /// This API function is used for testing. One should not rely on its presence /// in plugins. @@ -1873,7 +1870,7 @@ Object nvim__id(Object obj) return copy_object(obj); } -/// Returns array given as argument +/// Returns array given as argument. /// /// This API function is used for testing. One should not rely on its presence /// in plugins. @@ -1886,7 +1883,7 @@ Array nvim__id_array(Array arr) return copy_object(ARRAY_OBJ(arr)).data.array; } -/// Returns dictionary given as argument +/// Returns dictionary given as argument. /// /// This API function is used for testing. One should not rely on its presence /// in plugins. @@ -1899,7 +1896,7 @@ Dictionary nvim__id_dictionary(Dictionary dct) return copy_object(DICTIONARY_OBJ(dct)).data.dictionary; } -/// Returns floating-point value given as argument +/// Returns floating-point value given as argument. /// /// This API function is used for testing. One should not rely on its presence /// in plugins. @@ -2023,19 +2020,19 @@ Object nvim_get_proc(Integer pid, Error *err) return rvobj; } -/// Selects an item in the completion popupmenu +/// Selects an item in the completion popupmenu. /// -/// When insert completion is not active, this API call is silently ignored. -/// It is mostly useful for an external UI using |ui-popupmenu| for instance -/// to control the popupmenu with the mouse. But it can also be used in an -/// insert mode mapping, use <cmd> mapping |:map-cmd| to ensure the mapping -/// doesn't end completion mode. +/// If |ins-completion| is not active this API call is silently ignored. +/// Useful for an external UI using |ui-popupmenu| to control the popupmenu +/// with the mouse. Can also be used in a mapping; use <cmd> |:map-cmd| to +/// ensure the mapping doesn't end completion mode. /// -/// @param item Index of the item to select, starting with zero. Pass in "-1" -/// to select no item (restore original text). +/// @param item Index (zero-based) of the item to select. Value of -1 selects +/// nothing and restores the original text. /// @param insert Whether the selection should be inserted in the buffer. -/// @param finish If true, completion will be finished with this item, and the -/// popupmenu dissmissed. Implies `insert`. +/// @param finish Finish the completion and dismiss the popupmenu. Implies +/// `insert`. +/// @param opts Optional parameters. Reserved for future use. void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Dictionary opts, Error *err) FUNC_API_SINCE(6) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 048fde07e7..7b90cbe4f4 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1472,6 +1472,10 @@ void set_curbuf(buf_T *buf, int action) if (old_tw != curbuf->b_p_tw) check_colorcolumn(curwin); } + + if (bufref_valid(&prevbufref) && prevbuf->terminal != NULL) { + terminal_check_size(prevbuf->terminal); + } } /* diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 09d22c4233..b3977e0176 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1063,6 +1063,13 @@ struct window_S { int w_width; /* Width of window, excluding separation. */ int w_vsep_width; /* Number of separator columns (0 or 1). */ + // inner size of window, which can be overriden by external UI + int w_height_inner; + int w_width_inner; + // external UI request. If non-zero, the inner size will use this. + int w_height_request; + int w_width_request; + /* * === start of cached values ==== */ diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 16e24cc55a..08ecff149c 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1022,12 +1022,12 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he && vim_isbreak(c) && !vim_isbreak((int)s[1]) && wp->w_p_wrap - && (wp->w_grid.Columns != 0)) { + && (wp->w_width_inner != 0)) { // Count all characters from first non-blank after a blank up to next // non-blank after a blank. numberextra = win_col_off(wp); col2 = col; - colmax = (colnr_T)(wp->w_grid.Columns - numberextra - col_adj); + colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj); if (col >= colmax) { colmax += col_adj; @@ -1076,9 +1076,9 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he numberextra = numberwidth; col += numberextra + mb_added; - if (col >= (colnr_T)wp->w_grid.Columns) { - col -= wp->w_grid.Columns; - numberextra = wp->w_grid.Columns - (numberextra - win_col_off2(wp)); + if (col >= (colnr_T)wp->w_width_inner) { + col -= wp->w_width_inner; + numberextra = wp->w_width_inner - (numberextra - win_col_off2(wp)); if (col >= numberextra && numberextra > 0) { col %= numberextra; } @@ -1097,17 +1097,17 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he numberwidth -= win_col_off2(wp); } - if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_grid.Columns)) { + if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_width_inner)) { added = 0; if (*p_sbr != NUL) { - if (size + sbrlen + numberwidth > (colnr_T)wp->w_grid.Columns) { + if (size + sbrlen + numberwidth > (colnr_T)wp->w_width_inner) { // Calculate effective window width. - int width = (colnr_T)wp->w_grid.Columns - sbrlen - numberwidth; - int prev_width = col ? ((colnr_T)wp->w_grid.Columns - (sbrlen + col)) + int width = (colnr_T)wp->w_width_inner - sbrlen - numberwidth; + int prev_width = col ? ((colnr_T)wp->w_width_inner - (sbrlen + col)) : 0; if (width == 0) { - width = (colnr_T)wp->w_grid.Columns; + width = (colnr_T)wp->w_width_inner; } added += ((size - prev_width) / width) * vim_strsize(p_sbr); if ((size - prev_width) % width) { @@ -1176,11 +1176,11 @@ bool in_win_border(win_T *wp, colnr_T vcol) int width1; // width of first line (after line number) int width2; // width of further lines - if (wp->w_grid.Columns == 0) { + if (wp->w_width_inner == 0) { // there is no border return false; } - width1 = wp->w_grid.Columns - win_col_off(wp); + width1 = wp->w_width_inner - win_col_off(wp); if ((int)vcol < width1 - 1) { return false; diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 6c1bd01ff5..bc14761877 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -121,11 +121,11 @@ static int coladvance2( --curwin->w_curswant; } } else { - int width = curwin->w_grid.Columns - win_col_off(curwin); + int width = curwin->w_width_inner - win_col_off(curwin); if (finetune && curwin->w_p_wrap - && curwin->w_grid.Columns != 0 + && curwin->w_width_inner != 0 && wcol >= (colnr_T)width) { csize = linetabsize(line); if (csize > 0) @@ -230,7 +230,7 @@ static int coladvance2( int b = (int)wcol - (int)col; // The difference between wcol and col is used to set coladd. - if (b > 0 && b < (MAXCOL - 2 * curwin->w_grid.Columns)) { + if (b > 0 && b < (MAXCOL - 2 * curwin->w_width_inner)) { pos->coladd = b; } @@ -444,7 +444,7 @@ bool leftcol_changed(void) bool retval = false; changed_cline_bef_curs(); - lastcol = curwin->w_leftcol + curwin->w_grid.Columns - curwin_col_off() - 1; + lastcol = curwin->w_leftcol + curwin->w_width_inner - curwin_col_off() - 1; validate_virtcol(); /* diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 90507cd0a5..bb16e2ae4d 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -566,7 +566,7 @@ static int insert_check(VimState *state) if (curwin->w_wcol < s->mincol - curbuf->b_p_ts && curwin->w_wrow == curwin->w_winrow - + curwin->w_grid.Rows - 1 - p_so + + curwin->w_height_inner - 1 - p_so && (curwin->w_cursor.lnum != curwin->w_topline || curwin->w_topfill > 0)) { if (curwin->w_topfill > 0) { @@ -5868,7 +5868,7 @@ static void check_auto_format( /* * Find out textwidth to be used for formatting: * if 'textwidth' option is set, use it - * else if 'wrapmargin' option is set, use curwin->w_grid.Columns-'wrapmargin' + * else if 'wrapmargin' option is set, use curwin->w_width_inner-'wrapmargin' * if invalid value, use 0. * Set default to window width (maximum 79) for "gq" operator. */ @@ -5883,7 +5883,7 @@ comp_textwidth ( if (textwidth == 0 && curbuf->b_p_wm) { /* The width is the window width minus 'wrapmargin' minus all the * things that add to the margin. */ - textwidth = curwin->w_grid.Columns - curbuf->b_p_wm; + textwidth = curwin->w_width_inner - curbuf->b_p_wm; if (cmdwin_type != 0) { textwidth -= 1; } @@ -5899,7 +5899,7 @@ comp_textwidth ( if (textwidth < 0) textwidth = 0; if (ff && textwidth == 0) { - textwidth = curwin->w_grid.Columns - 1; + textwidth = curwin->w_width_inner - 1; if (textwidth > 79) { textwidth = 79; } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 993edec5ef..3980516d32 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -16798,10 +16798,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - uint16_t term_width = MAX(0, curwin->w_grid.Columns - win_col_off(curwin)); + uint16_t term_width = MAX(0, curwin->w_width_inner - win_col_off(curwin)); Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, true, false, false, cwd, - term_width, curwin->w_grid.Rows, + term_width, curwin->w_height_inner, xstrdup("xterm-256color"), &rettv->vval.v_number); if (rettv->vval.v_number <= 0) { diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index c574ac10e9..abdf411fc3 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -257,7 +257,7 @@ void ex_align(exarg_T *eap) if (width <= 0) width = curbuf->b_p_tw; if (width == 0 && curbuf->b_p_wm > 0) { - width = curwin->w_grid.Columns - curbuf->b_p_wm; + width = curwin->w_width_inner - curbuf->b_p_wm; } if (width <= 0) { width = 80; @@ -2678,6 +2678,10 @@ int do_ecmd( theend: + if (bufref_valid(&old_curbuf) && old_curbuf.br_buf->terminal != NULL) { + terminal_check_size(old_curbuf.br_buf->terminal); + } + if (did_inc_redrawing_disabled) { RedrawingDisabled--; } @@ -2872,11 +2876,11 @@ void ex_z(exarg_T *eap) // Vi compatible: ":z!" uses display height, without a count uses // 'scroll' if (eap->forceit) { - bigness = curwin->w_grid.Rows; + bigness = curwin->w_height_inner; } else if (ONE_WINDOW) { bigness = curwin->w_p_scr * 2; } else { - bigness = curwin->w_grid.Rows - 3; + bigness = curwin->w_height_inner - 3; } if (bigness < 1) { bigness = 1; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index ae618bfc61..02d96603b7 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -9201,7 +9201,7 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin) && (fprintf(fd, "exe '%dresize ' . ((&lines * %" PRId64 " + %" PRId64 ") / %" PRId64 ")", - n, (int64_t)wp->w_grid.Rows, + n, (int64_t)wp->w_height, (int64_t)Rows / 2, (int64_t)Rows) < 0 || put_eol(fd) == FAIL)) { return FAIL; @@ -9469,8 +9469,8 @@ put_view( " * winheight(0) + %" PRId64 ") / %" PRId64 ")", (int64_t)wp->w_cursor.lnum, (int64_t)(wp->w_cursor.lnum - wp->w_topline), - (int64_t)(wp->w_grid.Rows / 2), - (int64_t)wp->w_grid.Rows) < 0 + (int64_t)(wp->w_height_inner / 2), + (int64_t)wp->w_height_inner) < 0 || put_eol(fd) == FAIL || put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL || put_line(fd, "exe s:l") == FAIL diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index be3e7bb676..b24acb5ebb 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2123,8 +2123,8 @@ static int vgetorpeek(int advance) ++col; } curwin->w_wrow = curwin->w_cline_row - + curwin->w_wcol / curwin->w_grid.Columns; - curwin->w_wcol %= curwin->w_grid.Columns; + + curwin->w_wcol / curwin->w_width_inner; + curwin->w_wcol %= curwin->w_width_inner; curwin->w_wcol += curwin_col_off(); col = 0; /* no correction needed */ } else { @@ -2133,7 +2133,7 @@ static int vgetorpeek(int advance) } } else if (curwin->w_p_wrap && curwin->w_wrow) { curwin->w_wrow--; - curwin->w_wcol = curwin->w_grid.Columns - 1; + curwin->w_wcol = curwin->w_width_inner - 1; col = curwin->w_cursor.col - 1; } if (col > 0 && curwin->w_wcol > 0) { diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h index 37d85ead0c..cf9e550f48 100644 --- a/src/nvim/grid_defs.h +++ b/src/nvim/grid_defs.h @@ -48,12 +48,8 @@ typedef struct { // offsets for the grid relative to the global screen int row_offset; int col_offset; - - // grid size requested by the UI. Used for window grids only. - int requested_rows; - int requested_cols; - - int was_resized; } ScreenGrid; +#define SCREEN_GRID_INIT { 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0 } + #endif // NVIM_GRID_DEFS_H diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 30962faa23..8e20aa5be4 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -474,7 +474,7 @@ int get_breakindent_win(win_T *wp, char_u *line) static varnumber_T prev_tick = 0; // Changedtick of cached value. int bri = 0; // window width minus window margin space, i.e. what rests for text - const int eff_wwidth = wp->w_grid.Columns + const int eff_wwidth = wp->w_width_inner - ((wp->w_p_nu || wp->w_p_rnu) && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) ? number_width(wp) + 1 : 0); diff --git a/src/nvim/memline_defs.h b/src/nvim/memline_defs.h index 34a002af5d..edd933b2cd 100644 --- a/src/nvim/memline_defs.h +++ b/src/nvim/memline_defs.h @@ -3,54 +3,65 @@ #include "nvim/memfile_defs.h" -/* - * When searching for a specific line, we remember what blocks in the tree - * are the branches leading to that block. This is stored in ml_stack. Each - * entry is a pointer to info in a block (may be data block or pointer block) - */ +/// +/// When searching for a specific line, we remember what blocks in the tree +/// are the branches leading to that block. This is stored in ml_stack. Each +/// entry is a pointer to info in a block (may be data block or pointer block) +/// typedef struct info_pointer { - blocknr_T ip_bnum; /* block number */ - linenr_T ip_low; /* lowest lnum in this block */ - linenr_T ip_high; /* highest lnum in this block */ - int ip_index; /* index for block with current lnum */ -} infoptr_T; /* block/index pair */ + blocknr_T ip_bnum; // block number + linenr_T ip_low; // lowest lnum in this block + linenr_T ip_high; // highest lnum in this block + int ip_index; // index for block with current lnum +} infoptr_T; // block/index pair typedef struct ml_chunksize { int mlcs_numlines; long mlcs_totalsize; } chunksize_T; -/* Flags when calling ml_updatechunk() */ - +// Flags when calling ml_updatechunk() #define ML_CHNK_ADDLINE 1 #define ML_CHNK_DELLINE 2 #define ML_CHNK_UPDLINE 3 -/* - * the memline structure holds all the information about a memline - */ +/// memline structure: the contents of a buffer. +/// Essentially a tree with a branch factor of 128. +/// Lines are stored at leaf nodes. +/// Nodes are stored on ml_mfp (memfile_T): +/// pointer_block: internal nodes +/// data_block: leaf nodes +/// +/// Memline also has "chunks" of 800 lines that are separate from the 128-tree +/// structure, primarily used to speed up line2byte() and byte2line(). +/// +/// Motivation: If you have a file that is 10000 lines long, and you insert +/// a line at linenr 1000, you don't want to move 9000 lines in +/// memory. With this structure it is roughly (N * 128) pointer +/// moves, where N is the height (typically 1-3). +/// typedef struct memline { - linenr_T ml_line_count; /* number of lines in the buffer */ + linenr_T ml_line_count; // number of lines in the buffer - memfile_T *ml_mfp; /* pointer to associated memfile */ + memfile_T *ml_mfp; // pointer to associated memfile -#define ML_EMPTY 1 /* empty buffer */ -#define ML_LINE_DIRTY 2 /* cached line was changed and allocated */ -#define ML_LOCKED_DIRTY 4 /* ml_locked was changed */ -#define ML_LOCKED_POS 8 /* ml_locked needs positive block number */ +#define ML_EMPTY 1 // empty buffer +#define ML_LINE_DIRTY 2 // cached line was changed and allocated +#define ML_LOCKED_DIRTY 4 // ml_locked was changed +#define ML_LOCKED_POS 8 // ml_locked needs positive block number int ml_flags; - infoptr_T *ml_stack; /* stack of pointer blocks (array of IPTRs) */ - int ml_stack_top; /* current top of ml_stack */ - int ml_stack_size; /* total number of entries in ml_stack */ + infoptr_T *ml_stack; // stack of pointer blocks (array of IPTRs) + int ml_stack_top; // current top of ml_stack + int ml_stack_size; // total number of entries in ml_stack - linenr_T ml_line_lnum; /* line number of cached line, 0 if not valid */ - char_u *ml_line_ptr; /* pointer to cached line */ + linenr_T ml_line_lnum; // line number of cached line, 0 if not valid + char_u *ml_line_ptr; // pointer to cached line - bhdr_T *ml_locked; /* block used by last ml_get */ - linenr_T ml_locked_low; /* first line in ml_locked */ - linenr_T ml_locked_high; /* last line in ml_locked */ - int ml_locked_lineadd; /* number of lines inserted in ml_locked */ + bhdr_T *ml_locked; // block used by last ml_get + linenr_T ml_locked_low; // first line in ml_locked + linenr_T ml_locked_high; // last line in ml_locked + int ml_locked_lineadd; // number of lines inserted in ml_locked chunksize_T *ml_chunksize; int ml_numchunks; int ml_usedchunks; diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 1c54db10eb..aea297fce2 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -660,7 +660,8 @@ static void free_menu_string(vimmenu_T *menu, int idx) /// /// @param[in] menu if null, starts from root_menu /// @param modes, a choice of \ref MENU_MODES -/// @return a dict with name/commands +/// @return dict with name/commands +/// @see show_menus_recursive /// @see menu_get static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes) { @@ -715,10 +716,10 @@ static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes) // visit recursively all children list_T *const children_list = tv_list_alloc(kListLenMayKnow); for (menu = menu->children; menu != NULL; menu = menu->next) { - dict_T *dic = menu_get_recursive(menu, modes); - if (tv_dict_len(dict) > 0) { - tv_list_append_dict(children_list, dic); - } + dict_T *d = menu_get_recursive(menu, modes); + if (tv_dict_len(d) > 0) { + tv_list_append_dict(children_list, d); + } } tv_dict_add_list(dict, S_LEN("submenus"), children_list); } @@ -734,42 +735,51 @@ static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes) /// @return false if could not find path_name bool menu_get(char_u *const path_name, int modes, list_T *list) { - vimmenu_T *menu; - menu = find_menu(root_menu, path_name, modes); + vimmenu_T *menu = find_menu(root_menu, path_name, modes); if (!menu) { return false; } for (; menu != NULL; menu = menu->next) { - dict_T *dict = menu_get_recursive(menu, modes); - if (dict && tv_dict_len(dict) > 0) { - tv_list_append_dict(list, dict); + dict_T *d = menu_get_recursive(menu, modes); + if (d && tv_dict_len(d) > 0) { + tv_list_append_dict(list, d); + } + if (*path_name != NUL) { + // If a (non-empty) path query was given, only the first node in the + // find_menu() result is relevant. Else we want all nodes. + break; } } return true; } -/// Find menu matching required name and modes +/// Find menu matching `name` and `modes`. /// /// @param menu top menu to start looking from /// @param name path towards the menu /// @return menu if \p name is null, found menu or NULL -vimmenu_T * -find_menu(vimmenu_T *menu, char_u * name, int modes) +static vimmenu_T *find_menu(vimmenu_T *menu, char_u *name, int modes) { char_u *p; while (*name) { + // find the end of one dot-separated name and put a NUL at the dot p = menu_name_skip(name); while (menu != NULL) { if (menu_name_equal(name, menu)) { - /* Found menu */ + // Found menu if (*p != NUL && menu->children == NULL) { - EMSG(_(e_notsubmenu)); - return NULL; - } else if ((menu->modes & modes) == 0x0) { - EMSG(_(e_othermode)); - return NULL; + if (*p != NUL) { + EMSG(_(e_notsubmenu)); + return NULL; + } else if ((menu->modes & modes) == 0x0) { + EMSG(_(e_othermode)); + return NULL; + } + } + if (*p == NUL) { // found a full match + return menu; } break; } @@ -780,6 +790,7 @@ find_menu(vimmenu_T *menu, char_u * name, int modes) EMSG2(_(e_nomenu), name); return NULL; } + // Found a match, search the sub-menu. name = p; menu = menu->children; } @@ -1235,7 +1246,7 @@ static char_u *popup_mode_name(char_u *name, int idx) /// /// @return a pointer to allocated memory. static char_u *menu_text(const char_u *str, int *mnemonic, char_u **actext) - FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1) { char_u *p; @@ -1520,7 +1531,7 @@ static char_u *menutrans_lookup(char_u *name, int len) char_u *dname; for (int i = 0; i < menutrans_ga.ga_len; i++) { - if (STRNCMP(name, tp[i].from, len) == 0 && tp[i].from[len] == NUL) { + if (STRNICMP(name, tp[i].from, len) == 0 && tp[i].from[len] == NUL) { return tp[i].to; } } @@ -1531,7 +1542,7 @@ static char_u *menutrans_lookup(char_u *name, int len) dname = menu_text(name, NULL, NULL); name[len] = c; for (int i = 0; i < menutrans_ga.ga_len; i++) { - if (STRCMP(dname, tp[i].from_noamp) == 0) { + if (STRICMP(dname, tp[i].from_noamp) == 0) { xfree(dname); return tp[i].to; } diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index ef4562f4e9..e752910a4b 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -1251,7 +1251,7 @@ int plines_win_nofill( return 1; } - if (wp->w_grid.Columns == 0) { + if (wp->w_width_inner == 0) { return 1; } @@ -1261,8 +1261,8 @@ int plines_win_nofill( } const int lines = plines_win_nofold(wp, lnum); - if (winheight && lines > wp->w_grid.Rows) { - return wp->w_grid.Rows; + if (winheight && lines > wp->w_height_inner) { + return wp->w_height_inner; } return lines; } @@ -1291,7 +1291,7 @@ int plines_win_nofold(win_T *wp, linenr_T lnum) /* * Add column offset for 'number', 'relativenumber' and 'foldcolumn'. */ - width = wp->w_grid.Columns - win_col_off(wp); + width = wp->w_width_inner - win_col_off(wp); if (width <= 0 || col > 32000) { return 32000; // bigger than the number of screen columns } @@ -1317,7 +1317,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) if (!wp->w_p_wrap) return lines + 1; - if (wp->w_grid.Columns == 0) { + if (wp->w_width_inner == 0) { return lines + 1; } @@ -1341,7 +1341,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) } // Add column offset for 'number', 'relativenumber', 'foldcolumn', etc. - int width = wp->w_grid.Columns - win_col_off(wp); + int width = wp->w_width_inner - win_col_off(wp); if (width <= 0) { return 9999; } diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 48fd765e1b..50dba92eca 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -164,7 +164,7 @@ retnomove: || (!on_status_line && !on_sep_line && (wp->w_p_rl - ? col < wp->w_grid.Columns - wp->w_p_fdc + ? col < wp->w_width_inner - wp->w_p_fdc : col >= wp->w_p_fdc + (cmdwin_type == 0 && wp == curwin ? 0 : 1)) && (flags & MOUSE_MAY_STOP_VIS)))) { @@ -258,7 +258,7 @@ retnomove: ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); redraw_later(VALID); row = 0; - } else if (row >= curwin->w_grid.Rows) { + } else if (row >= curwin->w_height_inner) { count = 0; for (first = true; curwin->w_topline < curbuf->b_ml.ml_line_count; ) { if (curwin->w_topfill > 0) { @@ -267,7 +267,7 @@ retnomove: count += plines(curwin->w_topline); } - if (!first && count > row - curwin->w_grid.Rows + 1) { + if (!first && count > row - curwin->w_height_inner + 1) { break; } first = false; @@ -289,7 +289,7 @@ retnomove: redraw_later(VALID); curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); - row = curwin->w_grid.Rows - 1; + row = curwin->w_height_inner - 1; } else if (row == 0) { // When dragging the mouse, while the text has been scrolled up as // far as it goes, moving the mouse in the top line should scroll @@ -304,7 +304,7 @@ retnomove: } // Check for position outside of the fold column. - if (curwin->w_p_rl ? col < curwin->w_grid.Columns - curwin->w_p_fdc : + if (curwin->w_p_rl ? col < curwin->w_width_inner - curwin->w_p_fdc : col >= curwin->w_p_fdc + (cmdwin_type == 0 ? 0 : 1)) { mouse_char = ' '; } @@ -371,7 +371,7 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump) int count; if (win->w_p_rl) { - col = win->w_grid.Columns - 1 - col; + col = win->w_width_inner - 1 - col; } lnum = win->w_topline; @@ -409,7 +409,7 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump) off = win_col_off(win) - win_col_off2(win); if (col < off) col = off; - col += row * (win->w_grid.Columns - off); + col += row * (win->w_width_inner - off); // add skip column (for long wrapping line) col += win->w_skipcol; } @@ -622,7 +622,7 @@ bool mouse_scroll_horiz(int dir) int step = 6; if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { - step = curwin->w_grid.Columns; + step = curwin->w_width_inner; } int leftcol = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : +step); @@ -674,7 +674,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col) // Find the offset where scanning should begin. int offset = wp->w_leftcol; if (row > 0) { - offset += row * (wp->w_grid.Columns - win_col_off(wp) - win_col_off2(wp) - + offset += row * (wp->w_width_inner - win_col_off(wp) - win_col_off2(wp) - wp->w_leftcol + wp->w_skipcol); } diff --git a/src/nvim/move.c b/src/nvim/move.c index 07b355e603..610fd04ebc 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -83,7 +83,7 @@ static void comp_botline(win_T *wp) redraw_for_cursorline(wp); wp->w_valid |= (VALID_CROW|VALID_CHEIGHT); } - if (done + n > wp->w_grid.Rows) { + if (done + n > wp->w_height_inner) { break; } done += n; @@ -150,12 +150,9 @@ void update_topline(void) bool check_botline = false; long save_so = p_so; - // need to have w_grid.Rows/Columns updated - win_grid_alloc(curwin); - // If there is no valid screen and when the window height is zero just use // the cursor line. - if (!screen_valid(true) || curwin->w_grid.Rows == 0) { + if (!screen_valid(true) || curwin->w_height_inner == 0) { curwin->w_topline = curwin->w_cursor.lnum; curwin->w_botline = curwin->w_topline; curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP; @@ -204,7 +201,7 @@ void update_topline(void) check_topline = true; if (check_topline) { - int halfheight = curwin->w_grid.Rows / 2 - 1; + int halfheight = curwin->w_height_inner / 2 - 1; if (halfheight < 2) { halfheight = 2; } @@ -297,7 +294,7 @@ void update_topline(void) lnum >= curwin->w_botline - p_so; lnum--) { line_count++; // stop at end of file or when we know we are far off - if (lnum <= 0 || line_count > curwin->w_grid.Rows + 1) { + if (lnum <= 0 || line_count > curwin->w_height_inner + 1) { break; } (void)hasFolding(lnum, &lnum, NULL); @@ -305,7 +302,7 @@ void update_topline(void) } else line_count = curwin->w_cursor.lnum - curwin->w_botline + 1 + p_so; - if (line_count <= curwin->w_grid.Rows + 1) { + if (line_count <= curwin->w_height_inner + 1) { scroll_cursor_bot(scrolljump_value(), false); } else { scroll_cursor_halfway(false); @@ -353,7 +350,7 @@ void update_topline_win(win_T* win) */ static int scrolljump_value(void) { - long result = p_sj >= 0 ? p_sj : (curwin->w_grid.Rows * -p_sj) / 100; + long result = p_sj >= 0 ? p_sj : (curwin->w_height_inner * -p_sj) / 100; assert(result <= INT_MAX); return (int)result; } @@ -529,7 +526,6 @@ int cursor_valid(void) */ void validate_cursor(void) { - win_grid_alloc(curwin); // we need to have w_grid.Rows/Columns updated check_cursor_moved(curwin); if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW)) curs_columns(true); @@ -668,13 +664,13 @@ void validate_cursor_col(void) colnr_T col = curwin->w_virtcol; colnr_T off = curwin_col_off(); col += off; - int width = curwin->w_grid.Columns - off + curwin_col_off2(); + int width = curwin->w_width_inner - off + curwin_col_off2(); // long line wrapping, adjust curwin->w_wrow - if (curwin->w_p_wrap && col >= (colnr_T)curwin->w_grid.Columns + if (curwin->w_p_wrap && col >= (colnr_T)curwin->w_width_inner && width > 0) { // use same formula as what is used in curs_columns() - col -= ((col - curwin->w_grid.Columns) / width + 1) * width; + col -= ((col - curwin->w_width_inner) / width + 1) * width; } if (col > (int)curwin->w_leftcol) { col -= curwin->w_leftcol; @@ -769,20 +765,20 @@ void curs_columns( */ curwin->w_wrow = curwin->w_cline_row; - int textwidth = curwin->w_grid.Columns - extra; + int textwidth = curwin->w_width_inner - extra; if (textwidth <= 0) { // No room for text, put cursor in last char of window. - curwin->w_wcol = curwin->w_grid.Columns - 1; - curwin->w_wrow = curwin->w_grid.Rows - 1; + curwin->w_wcol = curwin->w_width_inner - 1; + curwin->w_wrow = curwin->w_height_inner - 1; } else if (curwin->w_p_wrap - && curwin->w_grid.Columns != 0 + && curwin->w_width_inner != 0 ) { width = textwidth + curwin_col_off2(); // long line wrapping, adjust curwin->w_wrow - if (curwin->w_wcol >= curwin->w_grid.Columns) { + if (curwin->w_wcol >= curwin->w_width_inner) { // this same formula is used in validate_cursor_col() - n = (curwin->w_wcol - curwin->w_grid.Columns) / width + 1; + n = (curwin->w_wcol - curwin->w_width_inner) / width + 1; curwin->w_wcol -= n * width; curwin->w_wrow += n; @@ -809,7 +805,7 @@ void curs_columns( assert(p_siso <= INT_MAX); int off_left = startcol - curwin->w_leftcol - (int)p_siso; int off_right = - endcol - curwin->w_leftcol - curwin->w_grid.Columns + (int)p_siso + 1; + endcol - curwin->w_leftcol - curwin->w_width_inner + (int)p_siso + 1; if (off_left < 0 || off_right > 0) { int diff = (off_left < 0) ? -off_left: off_right; @@ -852,16 +848,16 @@ void curs_columns( prev_skipcol = curwin->w_skipcol; int p_lines = 0; - if ((curwin->w_wrow >= curwin->w_grid.Rows + if ((curwin->w_wrow >= curwin->w_height_inner || ((prev_skipcol > 0 - || curwin->w_wrow + p_so >= curwin->w_grid.Rows) + || curwin->w_wrow + p_so >= curwin->w_height_inner) && (p_lines = plines_win_nofill(curwin, curwin->w_cursor.lnum, false)) - 1 - >= curwin->w_grid.Rows)) - && curwin->w_grid.Rows != 0 + >= curwin->w_height_inner)) + && curwin->w_height_inner != 0 && curwin->w_cursor.lnum == curwin->w_topline && width > 0 - && curwin->w_grid.Columns != 0 + && curwin->w_width_inner != 0 ) { /* Cursor past end of screen. Happens with a single line that does * not fit on screen. Find a skipcol to show the text around the @@ -883,21 +879,21 @@ void curs_columns( } else n = p_lines; - if ((colnr_T)n >= curwin->w_grid.Rows + curwin->w_skipcol / width) { + if ((colnr_T)n >= curwin->w_height_inner + curwin->w_skipcol / width) { extra += 2; } if (extra == 3 || p_lines < p_so * 2) { // not enough room for 'scrolloff', put cursor in the middle n = curwin->w_virtcol / width; - if (n > curwin->w_grid.Rows / 2) { - n -= curwin->w_grid.Rows / 2; + if (n > curwin->w_height_inner / 2) { + n -= curwin->w_height_inner / 2; } else { n = 0; } // don't skip more than necessary - if (n > p_lines - curwin->w_grid.Rows + 1) { - n = p_lines - curwin->w_grid.Rows + 1; + if (n > p_lines - curwin->w_height_inner + 1) { + n = p_lines - curwin->w_height_inner + 1; } curwin->w_skipcol = n * width; } else if (extra == 1) { @@ -912,7 +908,7 @@ void curs_columns( } } else if (extra == 2) { // less then 'scrolloff' lines below, increase skipcol - endcol = (n - curwin->w_grid.Rows + 1) * width; + endcol = (n - curwin->w_height_inner + 1) * width; while (endcol > curwin->w_virtcol) { endcol -= width; } @@ -922,9 +918,9 @@ void curs_columns( } curwin->w_wrow -= curwin->w_skipcol / width; - if (curwin->w_wrow >= curwin->w_grid.Rows) { + if (curwin->w_wrow >= curwin->w_height_inner) { // small window, make sure cursor is in it - extra = curwin->w_wrow - curwin->w_grid.Rows + 1; + extra = curwin->w_wrow - curwin->w_height_inner + 1; curwin->w_skipcol += extra * width; curwin->w_wrow -= extra; } @@ -966,7 +962,7 @@ scrolldown ( validate_cursor(); /* w_wrow needs to be valid */ while (line_count-- > 0) { if (curwin->w_topfill < diff_check(curwin, curwin->w_topline) - && curwin->w_topfill < curwin->w_grid.Rows - 1) { + && curwin->w_topfill < curwin->w_height_inner - 1) { curwin->w_topfill++; done++; } else { @@ -1001,15 +997,15 @@ scrolldown ( */ int wrow = curwin->w_wrow; if (curwin->w_p_wrap - && curwin->w_grid.Columns != 0 + && curwin->w_width_inner != 0 ) { validate_virtcol(); validate_cheight(); wrow += curwin->w_cline_height - 1 - - curwin->w_virtcol / curwin->w_grid.Columns; + curwin->w_virtcol / curwin->w_width_inner; } bool moved = false; - while (wrow >= curwin->w_grid.Rows && curwin->w_cursor.lnum > 1) { + while (wrow >= curwin->w_height_inner && curwin->w_cursor.lnum > 1) { linenr_T first; if (hasFolding(curwin->w_cursor.lnum, &first, NULL)) { --wrow; @@ -1094,12 +1090,12 @@ check_topfill ( { if (wp->w_topfill > 0) { int n = plines_win_nofill(wp, wp->w_topline, true); - if (wp->w_topfill + n > wp->w_grid.Rows) { + if (wp->w_topfill + n > wp->w_height_inner) { if (down && wp->w_topline > 1) { --wp->w_topline; wp->w_topfill = 0; } else { - wp->w_topfill = wp->w_grid.Rows - n; + wp->w_topfill = wp->w_height_inner - n; if (wp->w_topfill < 0) { wp->w_topfill = 0; } @@ -1115,12 +1111,12 @@ check_topfill ( static void max_topfill(void) { int n = plines_nofill(curwin->w_topline); - if (n >= curwin->w_grid.Rows) { + if (n >= curwin->w_height_inner) { curwin->w_topfill = 0; } else { curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline); - if (curwin->w_topfill + n > curwin->w_grid.Rows) { - curwin->w_topfill = curwin->w_grid.Rows - n; + if (curwin->w_topfill + n > curwin->w_height_inner) { + curwin->w_topfill = curwin->w_height_inner - n; } } } @@ -1152,14 +1148,14 @@ void scrolldown_clamp(void) else end_row += plines_nofill(curwin->w_topline - 1); if (curwin->w_p_wrap - && curwin->w_grid.Columns != 0 + && curwin->w_width_inner != 0 ) { validate_cheight(); validate_virtcol(); end_row += curwin->w_cline_height - 1 - - curwin->w_virtcol / curwin->w_grid.Columns; + curwin->w_virtcol / curwin->w_width_inner; } - if (end_row < curwin->w_grid.Rows - p_so) { + if (end_row < curwin->w_height_inner - p_so) { if (can_fill) { ++curwin->w_topfill; check_topfill(curwin, true); @@ -1194,10 +1190,10 @@ void scrollup_clamp(void) int start_row = curwin->w_wrow - plines_nofill(curwin->w_topline) - curwin->w_topfill; if (curwin->w_p_wrap - && curwin->w_grid.Columns != 0 + && curwin->w_width_inner != 0 ) { validate_virtcol(); - start_row -= curwin->w_virtcol / curwin->w_grid.Columns; + start_row -= curwin->w_virtcol / curwin->w_width_inner; } if (start_row >= p_so) { if (curwin->w_topfill > 0) @@ -1351,7 +1347,7 @@ void scroll_cursor_top(int min_scroll, int always) else used += plines(bot); } - if (used > curwin->w_grid.Rows) { + if (used > curwin->w_height_inner) { break; } if (top < curwin->w_topline) { @@ -1376,7 +1372,7 @@ void scroll_cursor_top(int min_scroll, int always) * This makes sure we get the same position when using "k" and "j" * in a small window. */ - if (used > curwin->w_grid.Rows) { + if (used > curwin->w_height_inner) { scroll_cursor_halfway(false); } else { /* @@ -1413,7 +1409,7 @@ void set_empty_rows(win_T *wp, int used) if (used == 0) { wp->w_empty_rows = 0; // single line that doesn't fit } else { - wp->w_empty_rows = wp->w_grid.Rows - used; + wp->w_empty_rows = wp->w_height_inner - used; if (wp->w_botline <= wp->w_buffer->b_ml.ml_line_count) { wp->w_filler_rows = diff_check_fill(wp, wp->w_botline); if (wp->w_empty_rows > wp->w_filler_rows) @@ -1456,7 +1452,8 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) curwin->w_topline = loff.lnum) { loff.lnum = curwin->w_topline; topline_back(&loff); - if (loff.height == MAXCOL || used + loff.height > curwin->w_grid.Rows) { + if (loff.height == MAXCOL + || used + loff.height > curwin->w_height_inner) { break; } used += loff.height; @@ -1520,7 +1517,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) } else { used += loff.height; } - if (used > curwin->w_grid.Rows) { + if (used > curwin->w_height_inner) { break; } if (loff.lnum >= curwin->w_botline @@ -1539,7 +1536,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) /* Add one line below */ botline_forw(&boff); used += boff.height; - if (used > curwin->w_grid.Rows) { + if (used > curwin->w_height_inner) { break; } if (extra < ( @@ -1566,7 +1563,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) if (scrolled <= 0) { line_count = 0; // more than a screenfull, don't scroll but redraw - } else if (used > curwin->w_grid.Rows) { + } else if (used > curwin->w_height_inner) { line_count = used; // scroll minimal number of lines } else { @@ -1587,7 +1584,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) * Scroll up if the cursor is off the bottom of the screen a bit. * Otherwise put it at 1/2 of the screen. */ - if (line_count >= curwin->w_grid.Rows && line_count > min_scroll) { + if (line_count >= curwin->w_height_inner && line_count > min_scroll) { scroll_cursor_halfway(false); } else { scrollup(line_count, true); @@ -1630,7 +1627,7 @@ void scroll_cursor_halfway(int atend) if (boff.lnum < curbuf->b_ml.ml_line_count) { botline_forw(&boff); used += boff.height; - if (used > curwin->w_grid.Rows) { + if (used > curwin->w_height_inner) { break; } below += boff.height; @@ -1647,7 +1644,7 @@ void scroll_cursor_halfway(int atend) used = MAXCOL; else used += loff.height; - if (used > curwin->w_grid.Rows) { + if (used > curwin->w_height_inner) { break; } above += loff.height; @@ -1658,7 +1655,7 @@ void scroll_cursor_halfway(int atend) if (!hasFolding(topline, &curwin->w_topline, NULL)) curwin->w_topline = topline; curwin->w_topfill = topfill; - if (old_topline > curwin->w_topline + curwin->w_grid.Rows) { + if (old_topline > curwin->w_topline + curwin->w_height_inner) { curwin->w_botfill = false; } check_topfill(curwin, false); @@ -1687,7 +1684,7 @@ void cursor_correct(void) } if (curwin->w_topline == 1) { above_wanted = 0; - int max_off = curwin->w_grid.Rows / 2; + int max_off = curwin->w_height_inner / 2; if (below_wanted > max_off) { below_wanted = max_off; } @@ -1697,7 +1694,7 @@ void cursor_correct(void) && mouse_dragging == 0 ) { below_wanted = 0; - int max_off = (curwin->w_grid.Rows - 1) / 2; + int max_off = (curwin->w_height_inner - 1) / 2; if (above_wanted > max_off) { above_wanted = max_off; } @@ -1871,7 +1868,7 @@ int onepage(Direction dir, long count) /* Find the line just above the new topline to get the right line * at the bottom of the window. */ n = 0; - while (n <= curwin->w_grid.Rows && loff.lnum >= 1) { + while (n <= curwin->w_height_inner && loff.lnum >= 1) { topline_back(&loff); if (loff.height == MAXCOL) n = MAXCOL; @@ -1962,7 +1959,7 @@ int onepage(Direction dir, long count) */ static void get_scroll_overlap(lineoff_T *lp, int dir) { - int min_height = curwin->w_grid.Rows - 2; + int min_height = curwin->w_height_inner - 2; if (lp->fill > 0) lp->height = 1; @@ -2017,12 +2014,12 @@ void halfpage(bool flag, linenr_T Prenum) int i; if (Prenum) { - curwin->w_p_scr = (Prenum > curwin->w_grid.Rows) ? curwin->w_grid.Rows + curwin->w_p_scr = (Prenum > curwin->w_height_inner) ? curwin->w_height_inner : Prenum; } assert(curwin->w_p_scr <= INT_MAX); - int n = curwin->w_p_scr <= curwin->w_grid.Rows ? (int)curwin->w_p_scr - : curwin->w_grid.Rows; + int n = curwin->w_p_scr <= curwin->w_height_inner ? (int)curwin->w_p_scr + : curwin->w_height_inner; update_topline(); validate_botline(); diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 844e748681..44e6ab46f1 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -3875,14 +3875,14 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist) col_off1 = curwin_col_off(); col_off2 = col_off1 - curwin_col_off2(); - width1 = curwin->w_grid.Columns - col_off1; - width2 = curwin->w_grid.Columns - col_off2; + width1 = curwin->w_width_inner - col_off1; + width2 = curwin->w_width_inner - col_off2; if (width2 == 0) { width2 = 1; // Avoid divide by zero. } - if (curwin->w_grid.Columns != 0) { + if (curwin->w_width_inner != 0) { // Instead of sticking at the last character of the buffer line we // try to stick in the last column of the screen. if (curwin->w_curswant == MAXCOL) { @@ -4226,7 +4226,7 @@ dozet: /* "zH" - scroll screen right half-page */ case 'H': - cap->count1 *= curwin->w_grid.Columns / 2; + cap->count1 *= curwin->w_width_inner / 2; FALLTHROUGH; /* "zh" - scroll screen to the right */ @@ -4242,7 +4242,7 @@ dozet: break; // "zL" - scroll screen left half-page - case 'L': cap->count1 *= curwin->w_grid.Columns / 2; + case 'L': cap->count1 *= curwin->w_width_inner / 2; FALLTHROUGH; /* "zl" - scroll screen to the left */ @@ -4278,7 +4278,7 @@ dozet: col = 0; /* like the cursor is in col 0 */ else getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col); - n = curwin->w_grid.Columns - curwin_col_off(); + n = curwin->w_width_inner - curwin_col_off(); if (col + l_p_siso < n) { col = 0; } else { @@ -4989,7 +4989,7 @@ static void nv_scroll(cmdarg_T *cap) used -= diff_check_fill(curwin, curwin->w_topline) - curwin->w_topfill; validate_botline(); // make sure w_empty_rows is valid - half = (curwin->w_grid.Rows - curwin->w_empty_rows + 1) / 2; + half = (curwin->w_height_inner - curwin->w_empty_rows + 1) / 2; for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; n++) { // Count half he number of filler lines to be "below this // line" and half to be "above the next line". @@ -5004,7 +5004,7 @@ static void nv_scroll(cmdarg_T *cap) if (hasFolding(curwin->w_topline + n, NULL, &lnum)) n = lnum - curwin->w_topline; } - if (n > 0 && used > curwin->w_grid.Rows) { + if (n > 0 && used > curwin->w_height_inner) { n--; } } else { // (cap->cmdchar == 'H') @@ -6716,9 +6716,9 @@ static void nv_g_cmd(cmdarg_T *cap) oap->motion_type = kMTCharWise; oap->inclusive = false; if (curwin->w_p_wrap - && curwin->w_grid.Columns != 0 + && curwin->w_width_inner != 0 ) { - int width1 = curwin->w_grid.Columns - curwin_col_off(); + int width1 = curwin->w_width_inner - curwin_col_off(); int width2 = width1 + curwin_col_off2(); validate_virtcol(); @@ -6731,7 +6731,7 @@ static void nv_g_cmd(cmdarg_T *cap) * 'relativenumber' is on and lines are wrapping the middle can be more * to the left. */ if (cap->nchar == 'm') { - i += (curwin->w_grid.Columns - curwin_col_off() + i += (curwin->w_width_inner - curwin_col_off() + ((curwin->w_p_wrap && i > 0) ? curwin_col_off2() : 0)) / 2; } @@ -6778,11 +6778,11 @@ static void nv_g_cmd(cmdarg_T *cap) oap->motion_type = kMTCharWise; oap->inclusive = true; if (curwin->w_p_wrap - && curwin->w_grid.Columns != 0 + && curwin->w_width_inner != 0 ) { curwin->w_curswant = MAXCOL; /* so we stay at the end */ if (cap->count1 == 1) { - int width1 = curwin->w_grid.Columns - col_off; + int width1 = curwin->w_width_inner - col_off; int width2 = width1 + curwin_col_off2(); validate_virtcol(); @@ -6808,7 +6808,7 @@ static void nv_g_cmd(cmdarg_T *cap) } else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == false) clearopbeep(oap); } else { - i = curwin->w_leftcol + curwin->w_grid.Columns - col_off - 1; + i = curwin->w_leftcol + curwin->w_width_inner - col_off - 1; coladvance((colnr_T)i); /* Make sure we stick in this column. */ @@ -7918,7 +7918,7 @@ static void get_op_vcol( colnr_T end; if (VIsual_mode != Ctrl_V - || (!initial && oap->end.col < curwin->w_grid.Columns)) { + || (!initial && oap->end.col < curwin->w_width_inner)) { return; } diff --git a/src/nvim/option.c b/src/nvim/option.c index d8e5b78e80..c57e6649bb 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4356,7 +4356,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, } else if (pp == &curbuf->b_p_scbk || pp == &p_scbk) { if (curbuf->terminal) { // Force the scrollback to take effect. - terminal_resize(curbuf->terminal, UINT16_MAX, UINT16_MAX); + terminal_check_size(curbuf->terminal); } } else if (pp == &curwin->w_p_nuw) { curwin->w_nrwidth_line_count = 0; diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 29a71fc0e1..2038fb4d2c 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -324,7 +324,7 @@ void update_screen(int type) wp->w_redr_status = true; } } - } else if (msg_scrolled > default_grid.Rows - 5) { // clearing is faster + } else if (msg_scrolled > Rows - 5) { // clearing is faster type = CLEAR; } else if (type != CLEAR) { check_for_delay(false); @@ -629,9 +629,7 @@ static void win_update(win_T *wp) wp->w_nrwidth = i; if (buf->terminal) { - terminal_resize(buf->terminal, - (uint16_t)(MAX(0, wp->w_grid.Columns - win_col_off(wp))), - (uint16_t)wp->w_grid.Rows); + terminal_check_size(buf->terminal); } } else if (buf->b_mod_set && buf->b_mod_xlines != 0 @@ -4661,8 +4659,7 @@ win_redr_status_matches ( if (matches == NULL) /* interrupted completion? */ return; - buf = xmalloc(has_mbyte ? default_grid.Columns * MB_MAXBYTES + 1 - : default_grid.Columns + 1); + buf = xmalloc(Columns * MB_MAXBYTES + 1); if (match == -1) { /* don't show match but original text */ match = 0; @@ -4683,13 +4680,13 @@ win_redr_status_matches ( if (first_match > 0) clen += 2; // jumping right, put match at the left - if ((long)clen > default_grid.Columns) { + if ((long)clen > Columns) { first_match = match; /* if showing the last match, we can add some on the left */ clen = 2; for (i = match; i < num_matches; ++i) { clen += status_match_len(xp, L_MATCH(i)) + 2; - if ((long)clen >= default_grid.Columns) { + if ((long)clen >= Columns) { break; } } @@ -4700,7 +4697,7 @@ win_redr_status_matches ( if (add_left) while (first_match > 0) { clen += status_match_len(xp, L_MATCH(first_match - 1)) + 2; - if ((long)clen >= default_grid.Columns) { + if ((long)clen >= Columns) { break; } first_match--; @@ -4718,8 +4715,7 @@ win_redr_status_matches ( clen = len; i = first_match; - while ((long)(clen + status_match_len(xp, L_MATCH(i)) + 2) - < default_grid.Columns) { + while ((long)(clen + status_match_len(xp, L_MATCH(i)) + 2) < Columns) { if (i == match) { selstart = buf + len; selstart_col = clen; @@ -4770,7 +4766,7 @@ win_redr_status_matches ( if (msg_scrolled > 0) { /* Put the wildmenu just above the command line. If there is * no room, scroll the screen one line up. */ - if (cmdline_row == default_grid.Rows - 1) { + if (cmdline_row == Rows - 1) { grid_del_lines(&default_grid, 0, 1, (int)Rows, 0, (int)Columns); msg_scrolled++; } else { @@ -4799,7 +4795,7 @@ win_redr_status_matches ( grid_puts(&default_grid, selstart, row, selstart_col, HL_ATTR(HLF_WM)); } - grid_fill(&default_grid, row, row + 1, clen, (int)default_grid.Columns, + grid_fill(&default_grid, row, row + 1, clen, (int)Columns, fillchar, fillchar, attr); } @@ -5065,7 +5061,7 @@ win_redr_custom ( row = 0; fillchar = ' '; attr = HL_ATTR(HLF_TPF); - maxwidth = default_grid.Columns; + maxwidth = Columns; use_sandbox = was_set_insecurely((char_u *)"tabline", 0); } else { row = W_ENDROW(wp); @@ -5084,13 +5080,13 @@ win_redr_custom ( if (*stl++ != '(') stl = p_ruf; } - col = ru_col - (default_grid.Columns - wp->w_width); + col = ru_col - (Columns - wp->w_width); if (col < (wp->w_width + 1) / 2) { col = (wp->w_width + 1) / 2; } maxwidth = wp->w_width - col; if (!wp->w_status_height) { - row = default_grid.Rows - 1; + row = Rows - 1; maxwidth--; // writing in last column may cause scrolling fillchar = ' '; attr = 0; @@ -5184,7 +5180,7 @@ win_redr_custom ( p = (char_u *) tabtab[n].start; cur_click_def = tabtab[n].def; } - while (col < default_grid.Columns) { + while (col < Columns) { tab_page_click_defs[col++] = cur_click_def; } } @@ -5883,7 +5879,7 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, } // TODO(bfredl): The relevant caller should do this - if (row == default_grid.Rows - 1) { // overwritten the command line + if (row == Rows - 1) { // overwritten the command line redraw_cmdline = true; if (start_col == 0 && end_col == Columns && c1 == ' ' && c2 == ' ' && attr == 0) { @@ -5934,15 +5930,8 @@ void win_grid_alloc(win_T *wp) { ScreenGrid *grid = &wp->w_grid; - int rows = grid->requested_rows; - if (rows == 0) { - rows = wp->w_height; - } - - int columns = grid->requested_cols; - if (columns == 0) { - columns = wp->w_width; - } + int rows = wp->w_height_inner; + int cols = wp->w_width_inner; // TODO(bfredl): floating windows should force this to true bool want_allocation = ui_is_external(kUIMultigrid); @@ -5952,20 +5941,24 @@ void win_grid_alloc(win_T *wp) grid_invalidate(grid); } + if (grid->Rows != rows) { + wp->w_lines_valid = 0; + xfree(wp->w_lines); + wp->w_lines = xcalloc(rows+1, sizeof(wline_T)); + } + int was_resized = false; if ((has_allocation != want_allocation) || grid->Rows != rows - || grid->Columns != columns) { + || grid->Columns != cols) { if (want_allocation) { - grid_alloc(grid, rows, columns, true); - win_free_lsize(wp); - win_alloc_lines(wp); + grid_alloc(grid, rows, cols, true); } else { // Single grid mode, all rendering will be redirected to default_grid. // Only keep track of the size and offset of the window. grid_free(grid); grid->Rows = rows; - grid->Columns = columns; + grid->Columns = cols; } was_resized = true; } @@ -6050,28 +6043,16 @@ retry: // If anything fails, make grid arrays NULL, so we don't do anything! // Continuing with the old arrays may result in a crash, because the // size is wrong. - FOR_ALL_TAB_WINDOWS(tp, wp) { - win_free_lsize(wp); - } - if (aucmd_win != NULL) - win_free_lsize(aucmd_win); grid_alloc(&default_grid, Rows, Columns, !doclear); StlClickDefinition *new_tab_page_click_defs = xcalloc( (size_t)Columns, sizeof(*new_tab_page_click_defs)); - FOR_ALL_TAB_WINDOWS(tp, wp) { - win_alloc_lines(wp); - } - if (aucmd_win != NULL && aucmd_win->w_lines == NULL) { - win_alloc_lines(aucmd_win); - } - clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size); xfree(tab_page_click_defs); tab_page_click_defs = new_tab_page_click_defs; - tab_page_click_defs_size = default_grid.Columns; + tab_page_click_defs_size = Columns; default_grid.row_offset = 0; default_grid.col_offset = 0; @@ -6269,7 +6250,7 @@ void setcursor(void) if (curwin->w_p_rl) { // With 'rightleft' set and the cursor on a double-wide character, // position it on the leftmost column. - col = curwin->w_grid.Columns - curwin->w_wcol + col = curwin->w_width_inner - curwin->w_wcol - ((utf_ptr2cells(get_cursor_pos_ptr()) == 2 && vim_isprintc(gchar_cursor())) ? 2 : 1); } @@ -6477,7 +6458,7 @@ int showmode(void) /* if the cmdline is more than one line high, erase top lines */ need_clear = clear_cmdline; - if (clear_cmdline && cmdline_row < default_grid.Rows - 1) { + if (clear_cmdline && cmdline_row < Rows - 1) { msg_clr_cmdline(); // will reset clear_cmdline } @@ -6497,7 +6478,7 @@ int showmode(void) if (edit_submode != NULL && !shortmess(SHM_COMPLETIONMENU)) { /* These messages can get long, avoid a wrap in a narrow * window. Prefer showing edit_submode_extra. */ - length = (default_grid.Rows - msg_row) * default_grid.Columns - 3; + length = (Rows - msg_row) * Columns - 3; if (edit_submode_extra != NULL) { length -= vim_strsize(edit_submode_extra); } @@ -6621,7 +6602,7 @@ int showmode(void) static void msg_pos_mode(void) { msg_col = 0; - msg_row = default_grid.Rows - 1; + msg_row = Rows - 1; } /// Delete mode message. Used when ESC is typed which is expected to end @@ -6695,7 +6676,7 @@ static void draw_tabline(void) // Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect. - assert(default_grid.Columns == tab_page_click_defs_size); + assert(Columns == tab_page_click_defs_size); clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size); /* Use the 'tabline' option if it's set. */ @@ -6717,7 +6698,7 @@ static void draw_tabline(void) } if (tabcount > 0) { - tabwidth = (default_grid.Columns - 1 + tabcount / 2) / tabcount; + tabwidth = (Columns - 1 + tabcount / 2) / tabcount; } if (tabwidth < 6) { @@ -6728,7 +6709,7 @@ static void draw_tabline(void) tabcount = 0; FOR_ALL_TABS(tp) { - if (col >= default_grid.Columns - 4) { + if (col >= Columns - 4) { break; } @@ -6769,7 +6750,7 @@ static void draw_tabline(void) if (wincount > 1) { vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount); len = (int)STRLEN(NameBuff); - if (col + len >= default_grid.Columns - 3) { + if (col + len >= Columns - 3) { break; } grid_puts_len(&default_grid, NameBuff, len, 0, col, @@ -6798,8 +6779,8 @@ static void draw_tabline(void) p += len - room; len = room; } - if (len > default_grid.Columns - col - 1) { - len = default_grid.Columns - col - 1; + if (len > Columns - col - 1) { + len = Columns - col - 1; } grid_puts_len(&default_grid, p, (int)STRLEN(p), 0, col, attr); @@ -6823,14 +6804,14 @@ static void draw_tabline(void) c = '_'; else c = ' '; - grid_fill(&default_grid, 0, 1, col, (int)default_grid.Columns, c, c, + grid_fill(&default_grid, 0, 1, col, (int)Columns, c, c, attr_fill); /* Put an "X" for closing the current tab if there are several. */ if (first_tabpage->tp_next != NULL) { - grid_putchar(&default_grid, 'X', 0, (int)default_grid.Columns - 1, + grid_putchar(&default_grid, 'X', 0, (int)Columns - 1, attr_nosel); - tab_page_click_defs[default_grid.Columns - 1] = (StlClickDefinition) { + tab_page_click_defs[Columns - 1] = (StlClickDefinition) { .type = kStlClickTabClose, .tabnr = 999, .func = NULL, @@ -7026,10 +7007,10 @@ static void win_redr_ruler(win_T *wp, int always) off = wp->w_wincol; width = wp->w_width; } else { - row = default_grid.Rows - 1; + row = Rows - 1; fillchar = ' '; attr = 0; - width = default_grid.Columns; + width = Columns; off = 0; } @@ -7067,7 +7048,7 @@ static void win_redr_ruler(win_T *wp, int always) if (wp->w_status_height == 0) { // can't use last char of screen o++; } - int this_ru_col = ru_col - (default_grid.Columns - width); + int this_ru_col = ru_col - (Columns - width); if (this_ru_col < 0) { this_ru_col = 0; } @@ -7122,7 +7103,7 @@ int number_width(win_T *wp) if (wp->w_p_rnu && !wp->w_p_nu) { // cursor line shows "0" - lnum = wp->w_grid.Rows; + lnum = wp->w_height_inner; } else { // cursor line shows absolute line number lnum = wp->w_buffer->b_ml.ml_line_count; diff --git a/src/nvim/screen.h b/src/nvim/screen.h index 109541ef07..61ed98247d 100644 --- a/src/nvim/screen.h +++ b/src/nvim/screen.h @@ -28,8 +28,7 @@ /// /// Note: before the screen is initialized and when out of memory these can be /// NULL. -EXTERN ScreenGrid default_grid INIT(= { 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0, - 0, 0, 0 }); +EXTERN ScreenGrid default_grid INIT(= SCREEN_GRID_INIT); #define DEFAULT_GRID_HANDLE 1 // handle for the default_grid diff --git a/src/nvim/search.c b/src/nvim/search.c index cf0f1ea287..5f0ff96f95 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -2168,7 +2168,7 @@ showmatch( } if (curwin->w_p_wrap || (vcol >= curwin->w_leftcol - && vcol < curwin->w_leftcol + curwin->w_grid.Columns)) { + && vcol < curwin->w_leftcol + curwin->w_width_inner)) { mpos = *lpos; // save the pos, update_screen() may change it save_cursor = curwin->w_cursor; save_so = p_so; diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index eae0f7ca13..6516f46b2f 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -334,41 +334,32 @@ void terminal_close(Terminal *term, char *msg) } } -void terminal_resize(Terminal *term, uint16_t width, uint16_t height) +void terminal_check_size(Terminal *term) { if (term->closed) { - // If two windows display the same terminal and one is closed by keypress. return; } - bool force = width == UINT16_MAX || height == UINT16_MAX; + int curwidth, curheight; vterm_get_size(term->vt, &curheight, &curwidth); + uint16_t width = 0, height = 0; - if (force || !width) { - width = (uint16_t)curwidth; - } - - if (force || !height) { - height = (uint16_t)curheight; - } - - if (!force && curheight == height && curwidth == width) { - return; - } - - if (height == 0 || width == 0) { - return; - } FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer && wp->w_buffer->terminal == term) { const uint16_t win_width = - (uint16_t)(MAX(0, wp->w_width - win_col_off(wp))); + (uint16_t)(MAX(0, wp->w_width_inner - win_col_off(wp))); width = MAX(width, win_width); - height = (uint16_t)MAX(height, wp->w_height); + height = (uint16_t)MAX(height, wp->w_height_inner); } } + // if no window displays the terminal, or such all windows are zero-height, + // don't resize the terminal. + if ((curheight == height && curwidth == width) || height == 0 || width == 0) { + return; + } + vterm_set_size(term->vt, height, width); vterm_screen_flush_damage(term->vts); term->pending_resize = true; @@ -383,8 +374,10 @@ void terminal_enter(void) memset(s, 0, sizeof(TerminalState)); s->term = buf->terminal; - // Ensure the terminal is properly sized. - terminal_resize(s->term, 0, 0); + // Ensure the terminal is properly sized. Ideally window size management + // code should always have resized the terminal already, but check here to + // be sure. + terminal_check_size(s->term); int save_state = State; s->save_rd = RedrawingDisabled; diff --git a/src/nvim/testdir/test_menu.vim b/src/nvim/testdir/test_menu.vim index af18760065..055d944b15 100644 --- a/src/nvim/testdir/test_menu.vim +++ b/src/nvim/testdir/test_menu.vim @@ -1,9 +1,32 @@ " Test that the system menu can be loaded. +if !has('menu') + finish +endif + func Test_load_menu() try source $VIMRUNTIME/menu.vim catch call assert_report('error while loading menus: ' . v:exception) endtry + call assert_match('browse confirm w', execute(':menu File.Save')) + source $VIMRUNTIME/delmenu.vim +endfunc + +func Test_translate_menu() + if !has('multi_lang') + return + endif + if !filereadable($VIMRUNTIME . '/lang/menu_de_de.latin1.vim') + throw 'Skipped: translated menu not found' + endif + + " First delete any English menus. + source $VIMRUNTIME/delmenu.vim + set langmenu=de_de + source $VIMRUNTIME/menu.vim + call assert_match('browse confirm w', execute(':menu Datei.Speichern')) + + source $VIMRUNTIME/delmenu.vim endfunc diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 73d45d8192..b65f3be746 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -452,8 +452,8 @@ void ui_grid_resize(handle_T grid_handle, int width, int height, Error *error) return; } - wp->w_grid.requested_rows = (int)height; - wp->w_grid.requested_cols = (int)width; - win_inner_width_changed(wp); - redraw_win_later(wp, SOME_VALID); + // non-positive indicates no request + wp->w_height_request = (int)MAX(height, 0); + wp->w_width_request = (int)MAX(width, 0); + win_set_inner_size(wp); } diff --git a/src/nvim/window.c b/src/nvim/window.c index a2e3825274..91a983e4c7 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3025,8 +3025,10 @@ static void new_frame(win_T *wp) void win_init_size(void) { firstwin->w_height = ROWS_AVAIL; + firstwin->w_height_inner = firstwin->w_height; topframe->fr_height = ROWS_AVAIL; firstwin->w_width = Columns; + firstwin->w_width_inner = firstwin->w_width; topframe->fr_width = Columns; } @@ -3889,7 +3891,6 @@ static win_T *win_alloc(win_T *after, int hidden) // allocate window structure and linesizes arrays win_T *new_wp = xcalloc(1, sizeof(win_T)); - win_alloc_lines(new_wp); new_wp->handle = ++last_win_id; handle_register_window(new_wp); @@ -3970,7 +3971,7 @@ win_free ( } } - win_free_lsize(wp); + xfree(wp->w_lines); for (i = 0; i < wp->w_tagstacklen; ++i) xfree(wp->w_tagstack[i].tagname); @@ -4118,28 +4119,6 @@ static void frame_remove(frame_T *frp) /* - * Allocate w_lines[] for window "wp". - */ -void win_alloc_lines(win_T *wp) -{ - wp->w_lines_valid = 0; - assert(wp->w_grid.Rows >= 0); - wp->w_lines = xcalloc(MAX(wp->w_grid.Rows + 1, Rows), sizeof(wline_T)); -} - -/* - * free lsize arrays for a window - */ -void win_free_lsize(win_T *wp) -{ - // TODO: why would wp be NULL here? - if (wp != NULL) { - xfree(wp->w_lines); - wp->w_lines = NULL; - } -} - -/* * Called from win_new_shellsize() after Rows changed. * This only does the current tab page, others must be done when made active. */ @@ -4876,9 +4855,9 @@ void win_drag_vsep_line(win_T *dragwin, int offset) // Has no effect when the window is less than two lines. void set_fraction(win_T *wp) { - if (wp->w_height > 1) { - wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT + wp->w_height / 2) - / (long)wp->w_height; + if (wp->w_height_inner > 1) { + wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT + wp->w_height_inner / 2) + / (long)wp->w_height_inner; } } @@ -4889,46 +4868,25 @@ void set_fraction(win_T *wp) */ void win_new_height(win_T *wp, int height) { - int prev_height = wp->w_height; - - /* Don't want a negative height. Happens when splitting a tiny window. - * Will equalize heights soon to fix it. */ - if (height < 0) + // Don't want a negative height. Happens when splitting a tiny window. + // Will equalize heights soon to fix it. + if (height < 0) { height = 0; - if (wp->w_height == height) - return; /* nothing to do */ - - if (wp->w_height > 0) { - if (wp == curwin) { - // w_wrow needs to be valid. When setting 'laststatus' this may - // call win_new_height() recursively. - validate_cursor(); - } - if (wp->w_height != prev_height) { // -V547 - return; // Recursive call already changed the size, bail out. - } - if (wp->w_wrow != wp->w_prev_fraction_row) { - set_fraction(wp); - } } - - wp->w_height = height; - wp->w_skipcol = 0; - - // There is no point in adjusting the scroll position when exiting. Some - // values might be invalid. - if (!exiting) { - scroll_to_fraction(wp, prev_height); + if (wp->w_height == height) { + return; // nothing to do } + wp->w_height = height; wp->w_pos_changed = true; + win_set_inner_size(wp); } void scroll_to_fraction(win_T *wp, int prev_height) { linenr_T lnum; int sline, line_size; - int height = wp->w_height; + int height = wp->w_height_inner; /* Don't change w_topline when height is zero. Don't set w_topline when * 'scrollbind' is set and this isn't the current window. */ @@ -4951,8 +4909,8 @@ void scroll_to_fraction(win_T *wp, int prev_height) // Make sure the whole cursor line is visible, if possible. const int rows = plines_win(wp, lnum, false); - if (sline > wp->w_height - rows) { - sline = wp->w_height - rows; + if (sline > wp->w_height_inner - rows) { + sline = wp->w_height_inner - rows; wp->w_wrow -= rows - line_size; } } @@ -4964,14 +4922,14 @@ void scroll_to_fraction(win_T *wp, int prev_height) * room use w_skipcol; */ wp->w_wrow = line_size; - if (wp->w_wrow >= wp->w_height - && (wp->w_width - win_col_off(wp)) > 0) { - wp->w_skipcol += wp->w_width - win_col_off(wp); - --wp->w_wrow; - while (wp->w_wrow >= wp->w_height) { - wp->w_skipcol += wp->w_width - win_col_off(wp) + if (wp->w_wrow >= wp->w_height_inner + && (wp->w_width_inner - win_col_off(wp)) > 0) { + wp->w_skipcol += wp->w_width_inner - win_col_off(wp); + wp->w_wrow--; + while (wp->w_wrow >= wp->w_height_inner) { + wp->w_skipcol += wp->w_width_inner - win_col_off(wp) + win_col_off2(wp); - --wp->w_wrow; + wp->w_wrow--; } } set_topline(wp, lnum); @@ -5024,21 +4982,58 @@ void scroll_to_fraction(win_T *wp, int prev_height) redraw_win_later(wp, SOME_VALID); wp->w_redr_status = TRUE; invalidate_botline_win(wp); - - if (wp->w_buffer->terminal) { - terminal_resize(wp->w_buffer->terminal, 0, wp->w_height); - redraw_win_later(wp, NOT_VALID); - } } -void win_inner_width_changed(win_T *wp) +void win_set_inner_size(win_T *wp) { - wp->w_lines_valid = 0; - changed_line_abv_curs_win(wp); - invalidate_botline_win(wp); - if (wp == curwin) { - update_topline(); - curs_columns(TRUE); /* validate w_wrow */ + int width = wp->w_width_request; + if (width == 0) { + width = wp->w_width; + } + + int prev_height = wp->w_height_inner; + int height = wp->w_height_request; + if (height == 0) { + height = wp->w_height; + } + + if (height != prev_height) { + if (height > 0) { + if (wp == curwin) { + // w_wrow needs to be valid. When setting 'laststatus' this may + // call win_new_height() recursively. + validate_cursor(); + } + if (wp->w_height_inner != prev_height) { // -V547 + return; // Recursive call already changed the size, bail out. + } + if (wp->w_wrow != wp->w_prev_fraction_row) { + set_fraction(wp); + } + } + wp->w_height_inner = height; + wp->w_skipcol = 0; + + // There is no point in adjusting the scroll position when exiting. Some + // values might be invalid. + if (!exiting) { + scroll_to_fraction(wp, prev_height); + } + } + + if (width != wp->w_width_inner) { + wp->w_width_inner = width; + wp->w_lines_valid = 0; + changed_line_abv_curs_win(wp); + invalidate_botline_win(wp); + if (wp == curwin) { + update_topline(); + curs_columns(true); // validate w_wrow + } + } + + if (wp->w_buffer->terminal) { + terminal_check_size(wp->w_buffer->terminal); } } @@ -5046,24 +5041,11 @@ void win_inner_width_changed(win_T *wp) void win_new_width(win_T *wp, int width) { wp->w_width = width; - // TODO(bfredl): refactor this. There should be some variable - // wp->w_inner_width which always contains the final actual width. - // Alternatively use wp->w_width for this and introduce wp->w_outer_width - // Then use this to fix terminal_resize. - if (!ui_is_external(kUIMultigrid) || wp->w_grid.requested_cols == 0) { - win_inner_width_changed(wp); - } + win_set_inner_size(wp); redraw_win_later(wp, NOT_VALID); wp->w_redr_status = TRUE; - if (wp->w_buffer->terminal) { - if (wp->w_height != 0) { - terminal_resize(wp->w_buffer->terminal, - (uint16_t)(MAX(0, wp->w_width - win_col_off(wp))), - 0); - } - } wp->w_pos_changed = true; } |