Mercurial > vim
view src/evalwindow.c @ 32721:94f4a488412e v9.0.1683
Updated runtime files
Commit: https://github.com/vim/vim/commit/6efb1980336ff324e9c57a4e282530b952fca816
Author: Christian Brabandt <cb@256bit.org>
Date: Thu Aug 10 05:44:25 2023 +0200
Updated runtime files
This is a collection of various PRs from github that all require a minor
patch number:
1) https://github.com/vim/vim/pull/12612
Do not conflate dictionary key with end of block
2) https://github.com/vim/vim/pull/12729:
When saving and restoring 'undolevels', the constructs `&undolevels` and
`:set undolevels` are problematic.
The construct `&undolevels` reads an unpredictable value; it will be the
local option value (if one has been set), or the global option value
(otherwise), making it unsuitable for saving a value for later
restoration.
Similarly, if a local option value has been set for 'undolevels',
temporarily modifying the option via `:set undolevels` changes the local
value as well as the global value, requiring extra work to restore both
values.
Saving and restoring the option value in one step via the construct
`:let &undolevels = &undolevels` appears to make no changes to the
'undolevels' option, but if a local option has been set to a different
value than the global option, it has the unintended effect of changing
the global 'undolevels' value to the local value.
Update the documentation to explain these issues and recommend explicit
use of global and local option values when saving and restoring. Update
some unit tests to use `g:undolevels`.
3) https://github.com/vim/vim/pull/12702:
Problem: Pip requirements files are not recognized.
Solution: Add a pattern to match pip requirements files.
4) https://github.com/vim/vim/pull/12688:
Add indent file and tests for ABB Rapid
5) https://github.com/vim/vim/pull/12668:
Use Lua 5.1 numeric escapes in tests and add to CI
Only Lua 5.2+ and LuaJIT understand hexadecimal escapes in strings. Lua
5.1 only supports decimal escapes:
> A character in a string can also be specified by its numerical value
> using the escape sequence \ddd, where ddd is a sequence of up to three
> decimal digits. (Note that if a numerical escape is to be followed by a
> digit, it must be expressed using exactly three digits.) Strings in Lua
> can contain any 8-bit value, including embedded zeros, which can be
> specified as '\0'.
To make sure this works with Lua 5.4 and Lua 5.1 change the Vim CI to
run with Lua 5.1 as well as Lua 5.4
6) https://github.com/vim/vim/pull/12631:
Add hurl filetype detection
7) https://github.com/vim/vim/pull/12573:
Problem: Files for haskell persistent library are not recognized
Solution: Add pattern persistentmodels for haskell persistent library
closes: #12612
closes: #12729
closes: #12702
closes: #12688
closes: #12668
closes: #12631
closes: #12573
Co-authored-by: lacygoill <lacygoill@lacygoill.me>
Co-authored-by: Michael Henry <drmikehenry@drmikehenry.com>
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
Co-authored-by: KnoP-01 <knosowski@graeffrobotics.de>
Co-authored-by: James McCoy <jamessan@jamessan.com>
Co-authored-by: Jacob Pfeifer <jacob@pfeifer.dev>
Co-authored-by: Borys Lykah <lykahb@fastmail.com>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 10 Aug 2023 06:30:06 +0200 |
parents | b89cfd86e18e |
children | a522c6c0127b |
line wrap: on
line source
/* vi:set ts=8 sts=4 sw=4 noet: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * evalwindow.c: Window related builtin functions */ #include "vim.h" #if defined(FEAT_EVAL) || defined(PROTO) static int win_getid(typval_T *argvars) { int winnr; win_T *wp; if (argvars[0].v_type == VAR_UNKNOWN) return curwin->w_id; winnr = tv_get_number(&argvars[0]); if (winnr <= 0) return 0; if (argvars[1].v_type == VAR_UNKNOWN) wp = firstwin; else { tabpage_T *tp; int tabnr = tv_get_number(&argvars[1]); FOR_ALL_TABPAGES(tp) if (--tabnr == 0) break; if (tp == NULL) return -1; if (tp == curtab) wp = firstwin; else wp = tp->tp_firstwin; } for ( ; wp != NULL; wp = wp->w_next) if (--winnr == 0) return wp->w_id; return 0; } static void win_id2tabwin(typval_T *argvars, list_T *list) { win_T *wp; tabpage_T *tp; int winnr = 1; int tabnr = 1; int id = tv_get_number(&argvars[0]); FOR_ALL_TABPAGES(tp) { FOR_ALL_WINDOWS_IN_TAB(tp, wp) { if (wp->w_id == id) { list_append_number(list, tabnr); list_append_number(list, winnr); return; } ++winnr; } ++tabnr; winnr = 1; } list_append_number(list, 0); list_append_number(list, 0); } /* * Return the window pointer of window "id". */ win_T * win_id2wp(int id) { return win_id2wp_tp(id, NULL); } /* * Return the window and tab pointer of window "id". * Returns NULL when not found. */ win_T * win_id2wp_tp(int id, tabpage_T **tpp) { win_T *wp; tabpage_T *tp; FOR_ALL_TAB_WINDOWS(tp, wp) if (wp->w_id == id) { if (tpp != NULL) *tpp = tp; return wp; } #ifdef FEAT_PROP_POPUP // popup windows are in separate lists FOR_ALL_TABPAGES(tp) FOR_ALL_POPUPWINS_IN_TAB(tp, wp) if (wp->w_id == id) { if (tpp != NULL) *tpp = tp; return wp; } FOR_ALL_POPUPWINS(wp) if (wp->w_id == id) { if (tpp != NULL) *tpp = curtab; // any tabpage would do return wp; } #endif return NULL; } static int win_id2win(typval_T *argvars) { win_T *wp; int nr = 1; int id = tv_get_number(&argvars[0]); FOR_ALL_WINDOWS(wp) { if (wp->w_id == id) return nr; ++nr; } return 0; } void win_findbuf(typval_T *argvars, list_T *list) { win_T *wp; tabpage_T *tp; int bufnr = tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) if (wp->w_buffer->b_fnum == bufnr) list_append_number(list, wp->w_id); } /* * Find window specified by "vp" in tabpage "tp". * Returns current window if "vp" is number zero. * Returns NULL if not found. */ win_T * find_win_by_nr( typval_T *vp, tabpage_T *tp) // NULL for current tab page { win_T *wp; int nr = (int)tv_get_number_chk(vp, NULL); if (nr < 0) return NULL; if (nr == 0) return curwin; FOR_ALL_WINDOWS_IN_TAB(tp, wp) { if (nr >= LOWEST_WIN_ID) { if (wp->w_id == nr) return wp; } else if (--nr <= 0) break; } if (nr >= LOWEST_WIN_ID) { #ifdef FEAT_PROP_POPUP // check tab-local popup windows for (wp = (tp == NULL ? curtab : tp)->tp_first_popupwin; wp != NULL; wp = wp->w_next) if (wp->w_id == nr) return wp; // check global popup windows FOR_ALL_POPUPWINS(wp) if (wp->w_id == nr) return wp; #endif return NULL; } return wp; } /* * Find a window: When using a Window ID in any tab page, when using a number * in the current tab page. * Returns NULL when not found. */ win_T * find_win_by_nr_or_id(typval_T *vp) { int nr = (int)tv_get_number_chk(vp, NULL); if (nr >= LOWEST_WIN_ID) return win_id2wp(tv_get_number(vp)); return find_win_by_nr(vp, NULL); } /* * Find window specified by "wvp" in tabpage "tvp". * Returns the tab page in 'ptp' */ win_T * find_tabwin( typval_T *wvp, // VAR_UNKNOWN for current window typval_T *tvp, // VAR_UNKNOWN for current tab page tabpage_T **ptp) { win_T *wp = NULL; tabpage_T *tp = NULL; long n; if (wvp->v_type != VAR_UNKNOWN) { if (tvp->v_type != VAR_UNKNOWN) { n = (long)tv_get_number(tvp); if (n >= 0) tp = find_tabpage(n); } else tp = curtab; if (tp != NULL) { wp = find_win_by_nr(wvp, tp); if (wp == NULL && wvp->v_type == VAR_NUMBER && wvp->vval.v_number != -1) // A window with the specified number is not found tp = NULL; } } else { wp = curwin; tp = curtab; } if (ptp != NULL) *ptp = tp; return wp; } /* * Get the layout of the given tab page for winlayout() and add it to "l". */ static void get_framelayout(frame_T *fr, list_T *l, int outer) { frame_T *child; list_T *fr_list; list_T *win_list; if (fr == NULL) return; if (outer) // outermost call from f_winlayout() fr_list = l; else { fr_list = list_alloc(); if (fr_list == NULL) return; if (list_append_list(l, fr_list) == FAIL) { vim_free(fr_list); return; } } if (fr->fr_layout == FR_LEAF) { if (fr->fr_win != NULL) { list_append_string(fr_list, (char_u *)"leaf", -1); list_append_number(fr_list, fr->fr_win->w_id); } } else { list_append_string(fr_list, fr->fr_layout == FR_ROW ? (char_u *)"row" : (char_u *)"col", -1); win_list = list_alloc(); if (win_list == NULL) return; if (list_append_list(fr_list, win_list) == FAIL) { vim_free(win_list); return; } child = fr->fr_child; while (child != NULL) { get_framelayout(child, win_list, FALSE); child = child->fr_next; } } } /* * Common code for tabpagewinnr() and winnr(). */ static int get_winnr(tabpage_T *tp, typval_T *argvar) { win_T *twin; int nr = 1; win_T *wp; char_u *arg; twin = (tp == curtab) ? curwin : tp->tp_curwin; if (argvar->v_type != VAR_UNKNOWN) { int invalid_arg = FALSE; arg = tv_get_string_chk(argvar); if (arg == NULL) nr = 0; // type error; errmsg already given else if (STRCMP(arg, "$") == 0) twin = (tp == curtab) ? lastwin : tp->tp_lastwin; else if (STRCMP(arg, "#") == 0) { twin = (tp == curtab) ? prevwin : tp->tp_prevwin; } else { long count; char_u *endp; // Extract the window count (if specified). e.g. winnr('3j') count = strtol((char *)arg, (char **)&endp, 10); if (count <= 0) count = 1; // if count is not specified, default to 1 if (endp != NULL && *endp != '\0') { if (STRCMP(endp, "j") == 0) twin = win_vert_neighbor(tp, twin, FALSE, count); else if (STRCMP(endp, "k") == 0) twin = win_vert_neighbor(tp, twin, TRUE, count); else if (STRCMP(endp, "h") == 0) twin = win_horz_neighbor(tp, twin, TRUE, count); else if (STRCMP(endp, "l") == 0) twin = win_horz_neighbor(tp, twin, FALSE, count); else invalid_arg = TRUE; } else invalid_arg = TRUE; } if (twin == NULL) nr = 0; if (invalid_arg) { semsg(_(e_invalid_expression_str), arg); nr = 0; } } if (nr <= 0) return 0; for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin; wp != twin; wp = wp->w_next) { if (wp == NULL) { // didn't find it in this tabpage nr = 0; break; } ++nr; } return nr; } /* * Returns information about a window as a dictionary. */ static dict_T * get_win_info(win_T *wp, short tpnr, short winnr) { dict_T *dict; dict = dict_alloc(); if (dict == NULL) return NULL; // make sure w_botline is valid validate_botline_win(wp); dict_add_number(dict, "tabnr", tpnr); dict_add_number(dict, "winnr", winnr); dict_add_number(dict, "winid", wp->w_id); dict_add_number(dict, "height", wp->w_height); dict_add_number(dict, "winrow", wp->w_winrow + 1); dict_add_number(dict, "topline", wp->w_topline); dict_add_number(dict, "botline", wp->w_botline - 1); #ifdef FEAT_MENU dict_add_number(dict, "winbar", wp->w_winbar_height); #endif dict_add_number(dict, "width", wp->w_width); dict_add_number(dict, "wincol", wp->w_wincol + 1); dict_add_number(dict, "textoff", win_col_off(wp)); dict_add_number(dict, "bufnr", wp->w_buffer->b_fnum); #ifdef FEAT_TERMINAL dict_add_number(dict, "terminal", bt_terminal(wp->w_buffer)); #endif #ifdef FEAT_QUICKFIX dict_add_number(dict, "quickfix", bt_quickfix(wp->w_buffer)); dict_add_number(dict, "loclist", (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)); #endif // Add a reference to window variables dict_add_dict(dict, "variables", wp->w_vars); return dict; } /* * Returns information (variables, options, etc.) about a tab page * as a dictionary. */ static dict_T * get_tabpage_info(tabpage_T *tp, int tp_idx) { win_T *wp; dict_T *dict; list_T *l; dict = dict_alloc(); if (dict == NULL) return NULL; dict_add_number(dict, "tabnr", tp_idx); l = list_alloc(); if (l != NULL) { FOR_ALL_WINDOWS_IN_TAB(tp, wp) list_append_number(l, (varnumber_T)wp->w_id); dict_add_list(dict, "windows", l); } // Make a reference to tabpage variables dict_add_dict(dict, "variables", tp->tp_vars); return dict; } /* * "gettabinfo()" function */ void f_gettabinfo(typval_T *argvars, typval_T *rettv) { tabpage_T *tp, *tparg = NULL; dict_T *d; int tpnr = 0; if (rettv_list_alloc(rettv) == FAIL) return; if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type != VAR_UNKNOWN) { // Information about one tab page tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); if (tparg == NULL) return; } // Get information about a specific tab page or all tab pages FOR_ALL_TABPAGES(tp) { tpnr++; if (tparg != NULL && tp != tparg) continue; d = get_tabpage_info(tp, tpnr); if (d != NULL) list_append_dict(rettv->vval.v_list, d); if (tparg != NULL) return; } } /* * "getwininfo()" function */ void f_getwininfo(typval_T *argvars, typval_T *rettv) { tabpage_T *tp; win_T *wp = NULL, *wparg = NULL; dict_T *d; short tabnr = 0, winnr; if (rettv_list_alloc(rettv) == FAIL) return; if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type != VAR_UNKNOWN) { wparg = win_id2wp(tv_get_number(&argvars[0])); if (wparg == NULL) return; } // Collect information about either all the windows across all the tab // pages or one particular window. FOR_ALL_TABPAGES(tp) { tabnr++; winnr = 0; FOR_ALL_WINDOWS_IN_TAB(tp, wp) { winnr++; if (wparg != NULL && wp != wparg) continue; d = get_win_info(wp, tabnr, winnr); if (d != NULL) list_append_dict(rettv->vval.v_list, d); if (wparg != NULL) // found information about a specific window return; } } #ifdef FEAT_PROP_POPUP if (wparg != NULL) { tabnr = 0; FOR_ALL_TABPAGES(tp) { tabnr++; FOR_ALL_POPUPWINS_IN_TAB(tp, wp) if (wp == wparg) break; } d = get_win_info(wparg, tp == NULL ? 0 : tabnr, 0); if (d != NULL) list_append_dict(rettv->vval.v_list, d); } #endif } /* * "getwinpos({timeout})" function */ void f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv) { int x = -1; int y = -1; if (rettv_list_alloc(rettv) == FAIL) return; if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL) return; #if defined(FEAT_GUI) \ || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \ || defined(MSWIN) { varnumber_T timeout = 100; if (argvars[0].v_type != VAR_UNKNOWN) timeout = tv_get_number(&argvars[0]); (void)ui_get_winpos(&x, &y, timeout); } #endif list_append_number(rettv->vval.v_list, (varnumber_T)x); list_append_number(rettv->vval.v_list, (varnumber_T)y); } /* * "getwinposx()" function */ void f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv) { rettv->vval.v_number = -1; #if defined(FEAT_GUI) \ || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \ || defined(MSWIN) { int x, y; if (ui_get_winpos(&x, &y, 100) == OK) rettv->vval.v_number = x; } #endif } /* * "getwinposy()" function */ void f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv) { rettv->vval.v_number = -1; #if defined(FEAT_GUI) \ || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \ || defined(MSWIN) { int x, y; if (ui_get_winpos(&x, &y, 100) == OK) rettv->vval.v_number = y; } #endif } /* * "tabpagenr()" function */ void f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv) { int nr = 1; char_u *arg; if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type != VAR_UNKNOWN) { arg = tv_get_string_chk(&argvars[0]); nr = 0; if (arg != NULL) { if (STRCMP(arg, "$") == 0) nr = tabpage_index(NULL) - 1; else if (STRCMP(arg, "#") == 0) nr = valid_tabpage(lastused_tabpage) ? tabpage_index(lastused_tabpage) : 0; else semsg(_(e_invalid_expression_str), arg); } } else nr = tabpage_index(curtab); rettv->vval.v_number = nr; } /* * "tabpagewinnr()" function */ void f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv) { int nr = 1; tabpage_T *tp; if (in_vim9script() && (check_for_number_arg(argvars, 0) == FAIL || check_for_opt_string_arg(argvars, 1) == FAIL)) return; tp = find_tabpage((int)tv_get_number(&argvars[0])); if (tp == NULL) nr = 0; else nr = get_winnr(tp, &argvars[1]); rettv->vval.v_number = nr; } /* * "win_execute()" function */ void f_win_execute(typval_T *argvars, typval_T *rettv) { int id; tabpage_T *tp; win_T *wp; switchwin_T switchwin; // Return an empty string if something fails. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; if (in_vim9script() && (check_for_number_arg(argvars, 0) == FAIL || check_for_string_or_list_arg(argvars, 1) == FAIL || check_for_opt_string_arg(argvars, 2) == FAIL)) return; id = (int)tv_get_number(argvars); wp = win_id2wp_tp(id, &tp); if (wp == NULL || tp == NULL) return; pos_T curpos = wp->w_cursor; char_u cwd[MAXPATHL]; int cwd_status = FAIL; #ifdef FEAT_AUTOCHDIR char_u autocwd[MAXPATHL]; int apply_acd = FALSE; #endif // Getting and setting directory can be slow on some systems, only do // this when the current or target window/tab have a local directory or // 'acd' is set. if (curwin != wp && (curwin->w_localdir != NULL || wp->w_localdir != NULL || (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) #ifdef FEAT_AUTOCHDIR || p_acd #endif )) cwd_status = mch_dirname(cwd, MAXPATHL); #ifdef FEAT_AUTOCHDIR // If 'acd' is set, check we are using that directory. If yes, then // apply 'acd' afterwards, otherwise restore the current directory. if (cwd_status == OK && p_acd) { do_autochdir(); apply_acd = mch_dirname(autocwd, MAXPATHL) == OK && STRCMP(cwd, autocwd) == 0; } #endif if (switch_win_noblock(&switchwin, wp, tp, TRUE) == OK) { check_cursor(); execute_common(argvars, rettv, 1); } restore_win_noblock(&switchwin, TRUE); #ifdef FEAT_AUTOCHDIR if (apply_acd) do_autochdir(); else #endif if (cwd_status == OK) mch_chdir((char *)cwd); // Update the status line if the cursor moved. if (win_valid(wp) && !EQUAL_POS(curpos, wp->w_cursor)) wp->w_redr_status = TRUE; // In case the command moved the cursor or changed the Visual area, // check it is valid. check_cursor(); if (VIsual_active) check_pos(curbuf, &VIsual); } /* * "win_findbuf()" function */ void f_win_findbuf(typval_T *argvars, typval_T *rettv) { if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) return; if (rettv_list_alloc(rettv) == OK) win_findbuf(argvars, rettv->vval.v_list); } /* * "win_getid()" function */ void f_win_getid(typval_T *argvars, typval_T *rettv) { if (in_vim9script() && (check_for_opt_number_arg(argvars, 0) == FAIL || (argvars[0].v_type != VAR_UNKNOWN && check_for_opt_number_arg(argvars, 1) == FAIL))) return; rettv->vval.v_number = win_getid(argvars); } /* * "win_gotoid()" function */ void f_win_gotoid(typval_T *argvars, typval_T *rettv) { win_T *wp; tabpage_T *tp; int id; if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) return; id = tv_get_number(&argvars[0]); if (cmdwin_type != 0) { emsg(_(e_invalid_in_cmdline_window)); return; } #if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL) if (popup_is_popup(curwin) && curbuf->b_term != NULL) { emsg(_(e_not_allowed_for_terminal_in_popup_window)); return; } #endif FOR_ALL_TAB_WINDOWS(tp, wp) if (wp->w_id == id) { // When jumping to another buffer stop Visual mode. if (VIsual_active && wp->w_buffer != curbuf) end_visual_mode(); goto_tabpage_win(tp, wp); rettv->vval.v_number = 1; return; } } /* * "win_id2tabwin()" function */ void f_win_id2tabwin(typval_T *argvars, typval_T *rettv) { if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) return; if (rettv_list_alloc(rettv) == OK) win_id2tabwin(argvars, rettv->vval.v_list); } /* * "win_id2win()" function */ void f_win_id2win(typval_T *argvars, typval_T *rettv) { if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) return; rettv->vval.v_number = win_id2win(argvars); } /* * "win_move_separator()" function */ void f_win_move_separator(typval_T *argvars, typval_T *rettv) { win_T *wp; int offset; rettv->vval.v_number = FALSE; if (in_vim9script() && (check_for_number_arg(argvars, 0) == FAIL || check_for_number_arg(argvars, 1) == FAIL)) return; wp = find_win_by_nr_or_id(&argvars[0]); if (wp == NULL || win_valid_popup(wp)) return; if (!win_valid(wp)) { emsg(_(e_cannot_resize_window_in_another_tab_page)); return; } offset = (int)tv_get_number(&argvars[1]); win_drag_vsep_line(wp, offset); rettv->vval.v_number = TRUE; } /* * "win_move_statusline()" function */ void f_win_move_statusline(typval_T *argvars, typval_T *rettv) { win_T *wp; int offset; rettv->vval.v_number = FALSE; if (in_vim9script() && (check_for_number_arg(argvars, 0) == FAIL || check_for_number_arg(argvars, 1) == FAIL)) return; wp = find_win_by_nr_or_id(&argvars[0]); if (wp == NULL || win_valid_popup(wp)) return; if (!win_valid(wp)) { emsg(_(e_cannot_resize_window_in_another_tab_page)); return; } offset = (int)tv_get_number(&argvars[1]); win_drag_status_line(wp, offset); rettv->vval.v_number = TRUE; } /* * "win_screenpos()" function */ void f_win_screenpos(typval_T *argvars, typval_T *rettv) { win_T *wp; if (rettv_list_alloc(rettv) == FAIL) return; if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) return; wp = find_win_by_nr_or_id(&argvars[0]); list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1); list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1); } /* * Move the window wp into a new split of targetwin in a given direction */ static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags) { int dir; int height = wp->w_height; win_T *oldwin = curwin; if (wp == targetwin) return; // Jump to the target window if (curwin != targetwin) win_goto(targetwin); // Remove the old window and frame from the tree of frames (void)winframe_remove(wp, &dir, NULL); win_remove(wp, NULL); last_status(FALSE); // may need to remove last status line (void)win_comp_pos(); // recompute window positions // Split a window on the desired side and put the old window there (void)win_split_ins(size, flags, wp, dir); // If splitting horizontally, try to preserve height if (size == 0 && !(flags & WSP_VERT)) { win_setheight_win(height, wp); if (p_ea) win_equal(wp, TRUE, 'v'); } #if defined(FEAT_GUI) // When 'guioptions' includes 'L' or 'R' may have to remove or add // scrollbars. Have to update them anyway. gui_may_update_scrollbars(); #endif if (oldwin != curwin) win_goto(oldwin); } /* * "win_splitmove()" function */ void f_win_splitmove(typval_T *argvars, typval_T *rettv) { win_T *wp; win_T *targetwin; int flags = 0, size = 0; if (in_vim9script() && (check_for_number_arg(argvars, 0) == FAIL || check_for_number_arg(argvars, 1) == FAIL || check_for_opt_dict_arg(argvars, 2) == FAIL)) return; wp = find_win_by_nr_or_id(&argvars[0]); targetwin = find_win_by_nr_or_id(&argvars[1]); if (wp == NULL || targetwin == NULL || wp == targetwin || !win_valid(wp) || !win_valid(targetwin) || win_valid_popup(wp) || win_valid_popup(targetwin)) { emsg(_(e_invalid_window_number)); rettv->vval.v_number = -1; return; } if (argvars[2].v_type != VAR_UNKNOWN) { dict_T *d; dictitem_T *di; if (check_for_nonnull_dict_arg(argvars, 2) == FAIL) return; d = argvars[2].vval.v_dict; if (dict_get_bool(d, "vertical", FALSE)) flags |= WSP_VERT; if ((di = dict_find(d, (char_u *)"rightbelow", -1)) != NULL) flags |= tv_get_bool(&di->di_tv) ? WSP_BELOW : WSP_ABOVE; size = (int)dict_get_number(d, "size"); } win_move_into_split(wp, targetwin, size, flags); } /* * "win_gettype(nr)" function */ void f_win_gettype(typval_T *argvars, typval_T *rettv) { win_T *wp = curwin; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type != VAR_UNKNOWN) { wp = find_win_by_nr_or_id(&argvars[0]); if (wp == NULL) { rettv->vval.v_string = vim_strsave((char_u *)"unknown"); return; } } if (is_aucmd_win(wp)) rettv->vval.v_string = vim_strsave((char_u *)"autocmd"); #if defined(FEAT_QUICKFIX) else if (wp->w_p_pvw) rettv->vval.v_string = vim_strsave((char_u *)"preview"); #endif #ifdef FEAT_PROP_POPUP else if (WIN_IS_POPUP(wp)) rettv->vval.v_string = vim_strsave((char_u *)"popup"); #endif else if (wp == curwin && cmdwin_type != 0) rettv->vval.v_string = vim_strsave((char_u *)"command"); #ifdef FEAT_QUICKFIX else if (bt_quickfix(wp->w_buffer)) rettv->vval.v_string = vim_strsave((char_u *) (wp->w_llist_ref != NULL ? "loclist" : "quickfix")); #endif } /* * "getcmdwintype()" function */ void f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; rettv->vval.v_string = alloc(2); if (rettv->vval.v_string == NULL) return; rettv->vval.v_string[0] = cmdwin_type; rettv->vval.v_string[1] = NUL; } /* * "winbufnr(nr)" function */ void f_winbufnr(typval_T *argvars, typval_T *rettv) { win_T *wp; if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) return; wp = find_win_by_nr_or_id(&argvars[0]); if (wp == NULL) rettv->vval.v_number = -1; else rettv->vval.v_number = wp->w_buffer->b_fnum; } /* * "wincol()" function */ void f_wincol(typval_T *argvars UNUSED, typval_T *rettv) { validate_cursor(); rettv->vval.v_number = curwin->w_wcol + 1; } /* * "winheight(nr)" function */ void f_winheight(typval_T *argvars, typval_T *rettv) { win_T *wp; if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) return; wp = find_win_by_nr_or_id(&argvars[0]); if (wp == NULL) rettv->vval.v_number = -1; else rettv->vval.v_number = wp->w_height; } /* * "winlayout()" function */ void f_winlayout(typval_T *argvars, typval_T *rettv) { tabpage_T *tp; if (rettv_list_alloc(rettv) == FAIL) return; if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type == VAR_UNKNOWN) tp = curtab; else { tp = find_tabpage((int)tv_get_number(&argvars[0])); if (tp == NULL) return; } get_framelayout(tp->tp_topframe, rettv->vval.v_list, TRUE); } /* * "winline()" function */ void f_winline(typval_T *argvars UNUSED, typval_T *rettv) { validate_cursor(); rettv->vval.v_number = curwin->w_wrow + 1; } /* * "winnr()" function */ void f_winnr(typval_T *argvars UNUSED, typval_T *rettv) { int nr = 1; if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL) return; nr = get_winnr(curtab, &argvars[0]); rettv->vval.v_number = nr; } /* * "winrestcmd()" function */ void f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv) { win_T *wp; int i; int winnr; garray_T ga; char_u buf[50]; ga_init2(&ga, sizeof(char), 70); // Do this twice to handle some window layouts properly. for (i = 0; i < 2; ++i) { winnr = 1; FOR_ALL_WINDOWS(wp) { sprintf((char *)buf, ":%dresize %d|", winnr, wp->w_height); ga_concat(&ga, buf); sprintf((char *)buf, "vert :%dresize %d|", winnr, wp->w_width); ga_concat(&ga, buf); ++winnr; } } ga_append(&ga, NUL); rettv->vval.v_string = ga.ga_data; rettv->v_type = VAR_STRING; } /* * "winrestview()" function */ void f_winrestview(typval_T *argvars, typval_T *rettv UNUSED) { dict_T *dict; if (check_for_nonnull_dict_arg(argvars, 0) == FAIL) return; dict = argvars[0].vval.v_dict; if (dict_has_key(dict, "lnum")) curwin->w_cursor.lnum = (linenr_T)dict_get_number(dict, "lnum"); if (dict_has_key(dict, "col")) curwin->w_cursor.col = (colnr_T)dict_get_number(dict, "col"); if (dict_has_key(dict, "coladd")) curwin->w_cursor.coladd = (colnr_T)dict_get_number(dict, "coladd"); if (dict_has_key(dict, "curswant")) { curwin->w_curswant = (colnr_T)dict_get_number(dict, "curswant"); curwin->w_set_curswant = FALSE; } if (dict_has_key(dict, "topline")) set_topline(curwin, (linenr_T)dict_get_number(dict, "topline")); #ifdef FEAT_DIFF if (dict_has_key(dict, "topfill")) curwin->w_topfill = (int)dict_get_number(dict, "topfill"); #endif if (dict_has_key(dict, "leftcol")) curwin->w_leftcol = (colnr_T)dict_get_number(dict, "leftcol"); if (dict_has_key(dict, "skipcol")) curwin->w_skipcol = (colnr_T)dict_get_number(dict, "skipcol"); check_cursor(); win_new_height(curwin, curwin->w_height); win_new_width(curwin, curwin->w_width); changed_window_setting(); if (curwin->w_topline <= 0) curwin->w_topline = 1; if (curwin->w_topline > curbuf->b_ml.ml_line_count) curwin->w_topline = curbuf->b_ml.ml_line_count; #ifdef FEAT_DIFF check_topfill(curwin, TRUE); #endif } /* * "winsaveview()" function */ void f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv) { dict_T *dict; if (rettv_dict_alloc(rettv) == FAIL) return; dict = rettv->vval.v_dict; dict_add_number(dict, "lnum", (long)curwin->w_cursor.lnum); dict_add_number(dict, "col", (long)curwin->w_cursor.col); dict_add_number(dict, "coladd", (long)curwin->w_cursor.coladd); update_curswant(); dict_add_number(dict, "curswant", (long)curwin->w_curswant); dict_add_number(dict, "topline", (long)curwin->w_topline); #ifdef FEAT_DIFF dict_add_number(dict, "topfill", (long)curwin->w_topfill); #endif dict_add_number(dict, "leftcol", (long)curwin->w_leftcol); dict_add_number(dict, "skipcol", (long)curwin->w_skipcol); } /* * "winwidth(nr)" function */ void f_winwidth(typval_T *argvars, typval_T *rettv) { win_T *wp; if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) return; wp = find_win_by_nr_or_id(&argvars[0]); if (wp == NULL) rettv->vval.v_number = -1; else rettv->vval.v_number = wp->w_width; } #endif // FEAT_EVAL #if defined(FEAT_EVAL) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \ || defined(PROTO) /* * Set "win" to be the curwin and "tp" to be the current tab page. * restore_win() MUST be called to undo, also when FAIL is returned. * No autocommands will be executed until restore_win() is called. * When "no_display" is TRUE the display won't be affected, no redraw is * triggered, another tabpage access is limited. * Returns FAIL if switching to "win" failed. */ int switch_win( switchwin_T *switchwin, win_T *win, tabpage_T *tp, int no_display) { block_autocmds(); return switch_win_noblock(switchwin, win, tp, no_display); } /* * As switch_win() but without blocking autocommands. */ int switch_win_noblock( switchwin_T *switchwin, win_T *win, tabpage_T *tp, int no_display) { CLEAR_POINTER(switchwin); switchwin->sw_curwin = curwin; if (win == curwin) switchwin->sw_same_win = TRUE; else { // Disable Visual selection, because redrawing may fail. switchwin->sw_visual_active = VIsual_active; VIsual_active = FALSE; } if (tp != NULL) { switchwin->sw_curtab = curtab; if (no_display) { curtab->tp_firstwin = firstwin; curtab->tp_lastwin = lastwin; curtab->tp_topframe = topframe; curtab = tp; firstwin = curtab->tp_firstwin; lastwin = curtab->tp_lastwin; topframe = curtab->tp_topframe; } else goto_tabpage_tp(tp, FALSE, FALSE); } if (!win_valid(win)) return FAIL; curwin = win; curbuf = curwin->w_buffer; return OK; } /* * Restore current tabpage and window saved by switch_win(), if still valid. * When "no_display" is TRUE the display won't be affected, no redraw is * triggered. */ void restore_win( switchwin_T *switchwin, int no_display) { restore_win_noblock(switchwin, no_display); unblock_autocmds(); } /* * As restore_win() but without unblocking autocommands. */ void restore_win_noblock( switchwin_T *switchwin, int no_display) { if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab)) { if (no_display) { curtab->tp_firstwin = firstwin; curtab->tp_lastwin = lastwin; curtab->tp_topframe = topframe; curtab = switchwin->sw_curtab; firstwin = curtab->tp_firstwin; lastwin = curtab->tp_lastwin; topframe = curtab->tp_topframe; } else goto_tabpage_tp(switchwin->sw_curtab, FALSE, FALSE); } if (!switchwin->sw_same_win) VIsual_active = switchwin->sw_visual_active; if (win_valid(switchwin->sw_curwin)) { curwin = switchwin->sw_curwin; curbuf = curwin->w_buffer; } # ifdef FEAT_PROP_POPUP else if (WIN_IS_POPUP(curwin)) // original window was closed and now we're in a popup window: Go // to the first valid window. win_goto(firstwin); # endif } #endif