From afce081b90c1e2c50c3507758c7558a0dfa1f33e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 15:18:03 +0200 Subject: Adding upstream version 2:8.2.2434. Signed-off-by: Daniel Baumann --- src/evalwindow.c | 1226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1226 insertions(+) create mode 100644 src/evalwindow.c (limited to 'src/evalwindow.c') diff --git a/src/evalwindow.c b/src/evalwindow.c new file mode 100644 index 0000000..e00747a --- /dev/null +++ b/src/evalwindow.c @@ -0,0 +1,1226 @@ +/* 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) + { + 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". + */ + 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". + */ + 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(). + */ + 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; + list_append_list(l, fr_list); + } + + 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; + list_append_list(fr_list, win_list); + 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_invexpr2), arg); + nr = 0; + } + } + + if (nr > 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; + + 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, "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) != OK) + 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) != OK) + 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 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 (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_invexpr2), 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; + + 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 = (int)tv_get_number(argvars); + tabpage_T *tp; + win_T *wp = win_id2wp_tp(id, &tp); + win_T *save_curwin; + tabpage_T *save_curtab; + + // Return an empty string if something fails. + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + + if (wp != NULL && tp != NULL) + { + pos_T curpos = wp->w_cursor; + + if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, TRUE) == OK) + { + check_cursor(); + execute_common(argvars, rettv, 1); + } + restore_win_noblock(save_curwin, save_curtab, TRUE); + + // Update the status line if the cursor moved. + if (win_valid(wp) && !EQUAL_POS(curpos, wp->w_cursor)) + wp->w_redr_status = TRUE; + } +} + +/* + * "win_findbuf()" function + */ + void +f_win_findbuf(typval_T *argvars, typval_T *rettv) +{ + if (rettv_list_alloc(rettv) != FAIL) + win_findbuf(argvars, rettv->vval.v_list); +} + +/* + * "win_getid()" function + */ + void +f_win_getid(typval_T *argvars, typval_T *rettv) +{ + 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 = tv_get_number(&argvars[0]); + +#ifdef FEAT_CMDWIN + if (cmdwin_type != 0) + { + emsg(_(e_cmdwin)); + return; + } +#endif + FOR_ALL_TAB_WINDOWS(tp, wp) + if (wp->w_id == id) + { + 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 (rettv_list_alloc(rettv) != FAIL) + win_id2tabwin(argvars, rettv->vval.v_list); +} + +/* + * "win_id2win()" function + */ + void +f_win_id2win(typval_T *argvars, typval_T *rettv) +{ + rettv->vval.v_number = win_id2win(argvars); +} + +/* + * "win_screenpos()" function + */ + void +f_win_screenpos(typval_T *argvars, typval_T *rettv) +{ + win_T *wp; + + if (rettv_list_alloc(rettv) == 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; + + 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_invalwindow)); + rettv->vval.v_number = -1; + return; + } + + if (argvars[2].v_type != VAR_UNKNOWN) + { + dict_T *d; + dictitem_T *di; + + if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL) + { + emsg(_(e_invarg)); + return; + } + + d = argvars[2].vval.v_dict; + if (dict_get_bool(d, (char_u *)"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, (char_u *)"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 (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 (wp == aucmd_win) + 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 +#ifdef FEAT_CMDWIN + else if (wp == curwin && cmdwin_type != 0) + rettv->vval.v_string = vim_strsave((char_u *)"command"); +#endif +} + +/* + * "getcmdwintype()" function + */ + void +f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv) +{ + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; +#ifdef FEAT_CMDWIN + rettv->vval.v_string = alloc(2); + if (rettv->vval.v_string != NULL) + { + rettv->vval.v_string[0] = cmdwin_type; + rettv->vval.v_string[1] = NUL; + } +#endif +} + +/* + * "winbufnr(nr)" function + */ + void +f_winbufnr(typval_T *argvars, typval_T *rettv) +{ + win_T *wp; + + 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; + + 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) != OK) + 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; + + 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 winnr = 1; + garray_T ga; + char_u buf[50]; + + ga_init2(&ga, (int)sizeof(char), 70); + 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 (argvars[0].v_type != VAR_DICT + || (dict = argvars[0].vval.v_dict) == NULL) + emsg(_(e_invarg)); + else + { + if (dict_find(dict, (char_u *)"lnum", -1) != NULL) + curwin->w_cursor.lnum = (linenr_T)dict_get_number(dict, (char_u *)"lnum"); + if (dict_find(dict, (char_u *)"col", -1) != NULL) + curwin->w_cursor.col = (colnr_T)dict_get_number(dict, (char_u *)"col"); + if (dict_find(dict, (char_u *)"coladd", -1) != NULL) + curwin->w_cursor.coladd = (colnr_T)dict_get_number(dict, (char_u *)"coladd"); + if (dict_find(dict, (char_u *)"curswant", -1) != NULL) + { + curwin->w_curswant = (colnr_T)dict_get_number(dict, (char_u *)"curswant"); + curwin->w_set_curswant = FALSE; + } + + if (dict_find(dict, (char_u *)"topline", -1) != NULL) + set_topline(curwin, (linenr_T)dict_get_number(dict, (char_u *)"topline")); +#ifdef FEAT_DIFF + if (dict_find(dict, (char_u *)"topfill", -1) != NULL) + curwin->w_topfill = (int)dict_get_number(dict, (char_u *)"topfill"); +#endif + if (dict_find(dict, (char_u *)"leftcol", -1) != NULL) + curwin->w_leftcol = (colnr_T)dict_get_number(dict, (char_u *)"leftcol"); + if (dict_find(dict, (char_u *)"skipcol", -1) != NULL) + curwin->w_skipcol = (colnr_T)dict_get_number(dict, (char_u *)"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; + + 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( + win_T **save_curwin, + tabpage_T **save_curtab, + win_T *win, + tabpage_T *tp, + int no_display) +{ + block_autocmds(); + return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display); +} + +/* + * As switch_win() but without blocking autocommands. + */ + int +switch_win_noblock( + win_T **save_curwin, + tabpage_T **save_curtab, + win_T *win, + tabpage_T *tp, + int no_display) +{ + *save_curwin = curwin; + if (tp != NULL) + { + *save_curtab = curtab; + if (no_display) + { + curtab->tp_firstwin = firstwin; + curtab->tp_lastwin = lastwin; + curtab = tp; + firstwin = curtab->tp_firstwin; + lastwin = curtab->tp_lastwin; + } + 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( + win_T *save_curwin, + tabpage_T *save_curtab, + int no_display) +{ + restore_win_noblock(save_curwin, save_curtab, no_display); + unblock_autocmds(); +} + +/* + * As restore_win() but without unblocking autocommands. + */ + void +restore_win_noblock( + win_T *save_curwin, + tabpage_T *save_curtab, + int no_display) +{ + if (save_curtab != NULL && valid_tabpage(save_curtab)) + { + if (no_display) + { + curtab->tp_firstwin = firstwin; + curtab->tp_lastwin = lastwin; + curtab = save_curtab; + firstwin = curtab->tp_firstwin; + lastwin = curtab->tp_lastwin; + } + else + goto_tabpage_tp(save_curtab, FALSE, FALSE); + } + if (win_valid(save_curwin)) + { + curwin = save_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 -- cgit v1.2.3