diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 21:52:58 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 21:52:58 +0000 |
commit | 931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch) | |
tree | d8c1843a95da5ea0bb4acc09f7e37843d9995c86 /src/nvim/api/window.c | |
parent | 142d9041391780ac15b89886a54015fdc5c73995 (diff) | |
parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
download | rneovim-931bffbda3668ddc609fc1da8f9eb576b170aa52.tar.gz rneovim-931bffbda3668ddc609fc1da8f9eb576b170aa52.tar.bz2 rneovim-931bffbda3668ddc609fc1da8f9eb576b170aa52.zip |
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'src/nvim/api/window.c')
-rw-r--r-- | src/nvim/api/window.c | 177 |
1 files changed, 138 insertions, 39 deletions
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index e2c234ab29..de5b40940f 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -1,27 +1,30 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <limits.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> +#include "nvim/api/keysets_defs.h" #include "nvim/api/private/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/api/window.h" -#include "nvim/ascii.h" +#include "nvim/autocmd.h" #include "nvim/buffer_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/eval/window.h" #include "nvim/ex_docmd.h" +#include "nvim/func_attr.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/lua/executor.h" -#include "nvim/memline_defs.h" +#include "nvim/memory.h" +#include "nvim/message.h" #include "nvim/move.h" -#include "nvim/pos.h" -#include "nvim/types.h" +#include "nvim/plines.h" +#include "nvim/pos_defs.h" +#include "nvim/types_defs.h" #include "nvim/window.h" /// Gets the current buffer in a window @@ -48,15 +51,26 @@ Buffer nvim_win_get_buf(Window window, Error *err) /// @param[out] err Error details, if any void nvim_win_set_buf(Window window, Buffer buffer, Error *err) FUNC_API_SINCE(5) - FUNC_API_CHECK_TEXTLOCK + FUNC_API_TEXTLOCK_ALLOW_CMDWIN { - win_set_buf(window, buffer, false, err); + win_T *win = find_window_by_handle(window, err); + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!win || !buf) { + return; + } + if (cmdwin_type != 0 && (win == curwin || win == cmdwin_old_curwin || buf == curbuf)) { + api_set_error(err, kErrorTypeException, "%s", e_cmdwin); + return; + } + win_set_buf(win, buf, false, err); } /// Gets the (1,0)-indexed, buffer-relative cursor position for a given window /// (different windows showing the same buffer have independent cursor /// positions). |api-indexing| /// +/// @see |getcurpos()| +/// /// @param window Window handle, or 0 for current window /// @param[out] err Error details, if any /// @return (row, col) tuple @@ -167,13 +181,8 @@ void nvim_win_set_height(Window window, Integer height, Error *err) return; } - win_T *savewin = curwin; - curwin = win; - curbuf = curwin->w_buffer; try_start(); - win_setheight((int)height); - curwin = savewin; - curbuf = curwin->w_buffer; + win_setheight_win((int)height, win); try_end(err); } @@ -214,13 +223,8 @@ void nvim_win_set_width(Window window, Integer width, Error *err) return; } - win_T *savewin = curwin; - curwin = win; - curbuf = curwin->w_buffer; try_start(); - win_setwidth((int)width); - curwin = savewin; - curbuf = curwin->w_buffer; + win_setwidth_win((int)width, win); try_end(err); } @@ -359,10 +363,10 @@ Boolean nvim_win_is_valid(Window window) /// @param[out] err Error details, if any void nvim_win_hide(Window window, Error *err) FUNC_API_SINCE(7) - FUNC_API_CHECK_TEXTLOCK + FUNC_API_TEXTLOCK_ALLOW_CMDWIN { win_T *win = find_window_by_handle(window, err); - if (!win) { + if (!win || !can_close_in_cmdwin(win, err)) { return; } @@ -391,19 +395,10 @@ void nvim_win_hide(Window window, Error *err) /// @param[out] err Error details, if any void nvim_win_close(Window window, Boolean force, Error *err) FUNC_API_SINCE(6) - FUNC_API_CHECK_TEXTLOCK + FUNC_API_TEXTLOCK_ALLOW_CMDWIN { win_T *win = find_window_by_handle(window, err); - if (!win) { - return; - } - - if (cmdwin_type != 0) { - if (win == curwin) { - cmdwin_result = Ctrl_C; - } else { - api_set_error(err, kErrorTypeException, "%s", _(e_cmdwin)); - } + if (!win || !can_close_in_cmdwin(win, err)) { return; } @@ -420,11 +415,11 @@ void nvim_win_close(Window window, Boolean force, Error *err) /// @see |nvim_buf_call()| /// /// @param window Window handle, or 0 for current window -/// @param fun Function to call inside the window (currently lua callable +/// @param fun Function to call inside the window (currently Lua callable /// only) /// @param[out] err Error details, if any -/// @return Return value of function. NB: will deepcopy lua values -/// currently, use upvalues to send lua references in and out. +/// @return Return value of function. NB: will deepcopy Lua values +/// currently, use upvalues to send Lua references in and out. Object nvim_win_call(Window window, LuaRef fun, Error *err) FUNC_API_SINCE(7) FUNC_API_LUA_ONLY @@ -445,8 +440,9 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err) return res; } -/// Set highlight namespace for a window. This will use highlights defined in -/// this namespace, but fall back to global highlights (ns=0) when missing. +/// Set highlight namespace for a window. This will use highlights defined with +/// |nvim_set_hl()| for this namespace, but fall back to global highlights (ns=0) when +/// missing. /// /// This takes precedence over the 'winhighlight' option. /// @@ -469,3 +465,106 @@ void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err) win->w_hl_needs_update = true; redraw_later(win, UPD_NOT_VALID); } + +/// Computes the number of screen lines occupied by a range of text in a given window. +/// Works for off-screen text and takes folds into account. +/// +/// Diff filler or virtual lines above a line are counted as a part of that line, +/// unless the line is on "start_row" and "start_vcol" is specified. +/// +/// Diff filler or virtual lines below the last buffer line are counted in the result +/// when "end_row" is omitted. +/// +/// Line indexing is similar to |nvim_buf_get_text()|. +/// +/// @param window Window handle, or 0 for current window. +/// @param opts Optional parameters: +/// - start_row: Starting line index, 0-based inclusive. +/// When omitted start at the very top. +/// - end_row: Ending line index, 0-based inclusive. +/// When omitted end at the very bottom. +/// - start_vcol: Starting virtual column index on "start_row", +/// 0-based inclusive, rounded down to full screen lines. +/// When omitted include the whole line. +/// - end_vcol: Ending virtual column index on "end_row", +/// 0-based exclusive, rounded up to full screen lines. +/// When omitted include the whole line. +/// @return Dictionary containing text height information, with these keys: +/// - all: The total number of screen lines occupied by the range. +/// - fill: The number of diff filler or virtual lines among them. +/// +/// @see |virtcol()| for text width. +Dictionary nvim_win_text_height(Window window, Dict(win_text_height) *opts, Arena *arena, + Error *err) + FUNC_API_SINCE(12) +{ + Dictionary rv = arena_dict(arena, 2); + + win_T *const win = find_window_by_handle(window, err); + if (!win) { + return rv; + } + buf_T *const buf = win->w_buffer; + const linenr_T line_count = buf->b_ml.ml_line_count; + + linenr_T start_lnum = 1; + linenr_T end_lnum = line_count; + int64_t start_vcol = -1; + int64_t end_vcol = -1; + + bool oob = false; + + if (HAS_KEY(opts, win_text_height, start_row)) { + start_lnum = (linenr_T)normalize_index(buf, opts->start_row, false, &oob); + } + + if (HAS_KEY(opts, win_text_height, end_row)) { + end_lnum = (linenr_T)normalize_index(buf, opts->end_row, false, &oob); + } + + VALIDATE(!oob, "%s", "Line index out of bounds", { + return rv; + }); + VALIDATE((start_lnum <= end_lnum), "%s", "'start_row' is higher than 'end_row'", { + return rv; + }); + + if (HAS_KEY(opts, win_text_height, start_vcol)) { + VALIDATE(HAS_KEY(opts, win_text_height, start_row), + "%s", "'start_vcol' specified without 'start_row'", { + return rv; + }); + start_vcol = opts->start_vcol; + VALIDATE_RANGE((start_vcol >= 0 && start_vcol <= MAXCOL), "start_vcol", { + return rv; + }); + } + + if (HAS_KEY(opts, win_text_height, end_vcol)) { + VALIDATE(HAS_KEY(opts, win_text_height, end_row), + "%s", "'end_vcol' specified without 'end_row'", { + return rv; + }); + end_vcol = opts->end_vcol; + VALIDATE_RANGE((end_vcol >= 0 && end_vcol <= MAXCOL), "end_vcol", { + return rv; + }); + } + + if (start_lnum == end_lnum && start_vcol >= 0 && end_vcol >= 0) { + VALIDATE((start_vcol <= end_vcol), "%s", "'start_vcol' is higher than 'end_vcol'", { + return rv; + }); + } + + int64_t fill = 0; + int64_t all = win_text_height(win, start_lnum, start_vcol, end_lnum, end_vcol, &fill); + if (!HAS_KEY(opts, win_text_height, end_row)) { + const int64_t end_fill = win_get_fill(win, line_count + 1); + fill += end_fill; + all += end_fill; + } + PUT_C(rv, "all", INTEGER_OBJ(all)); + PUT_C(rv, "fill", INTEGER_OBJ(fill)); + return rv; +} |