blob: 00081d43d592a64513ca10ad5b32aafbc9c40959 [file] [log] [blame]
Bram Moolenaar261f3462019-09-07 15:45:32 +02001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * evalwindow.c: Window related builtin functions
12 */
13
14#include "vim.h"
15
16#if defined(FEAT_EVAL) || defined(PROTO)
17
18 static int
19win_getid(typval_T *argvars)
20{
21 int winnr;
22 win_T *wp;
23
24 if (argvars[0].v_type == VAR_UNKNOWN)
25 return curwin->w_id;
26 winnr = tv_get_number(&argvars[0]);
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +000027 if (winnr <= 0)
28 return 0;
29
30 if (argvars[1].v_type == VAR_UNKNOWN)
31 wp = firstwin;
32 else
Bram Moolenaar261f3462019-09-07 15:45:32 +020033 {
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +000034 tabpage_T *tp;
35 int tabnr = tv_get_number(&argvars[1]);
36
37 FOR_ALL_TABPAGES(tp)
38 if (--tabnr == 0)
39 break;
40 if (tp == NULL)
41 return -1;
42 if (tp == curtab)
Bram Moolenaar261f3462019-09-07 15:45:32 +020043 wp = firstwin;
44 else
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +000045 wp = tp->tp_firstwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +020046 }
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +000047 for ( ; wp != NULL; wp = wp->w_next)
48 if (--winnr == 0)
49 return wp->w_id;
Bram Moolenaar261f3462019-09-07 15:45:32 +020050 return 0;
51}
52
Bram Moolenaar261f3462019-09-07 15:45:32 +020053 static void
54win_id2tabwin(typval_T *argvars, list_T *list)
55{
56 win_T *wp;
57 tabpage_T *tp;
58 int winnr = 1;
59 int tabnr = 1;
60 int id = tv_get_number(&argvars[0]);
61
62 FOR_ALL_TABPAGES(tp)
63 {
64 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
65 {
66 if (wp->w_id == id)
67 {
68 list_append_number(list, tabnr);
69 list_append_number(list, winnr);
70 return;
71 }
72 ++winnr;
73 }
74 ++tabnr;
75 winnr = 1;
76 }
77 list_append_number(list, 0);
78 list_append_number(list, 0);
79}
80
81/*
82 * Return the window pointer of window "id".
83 */
84 win_T *
85win_id2wp(int id)
86{
87 return win_id2wp_tp(id, NULL);
88}
89
90/*
91 * Return the window and tab pointer of window "id".
Bram Moolenaar88456cd2022-11-18 22:14:09 +000092 * Returns NULL when not found.
Bram Moolenaar261f3462019-09-07 15:45:32 +020093 */
94 win_T *
95win_id2wp_tp(int id, tabpage_T **tpp)
96{
97 win_T *wp;
98 tabpage_T *tp;
99
100 FOR_ALL_TAB_WINDOWS(tp, wp)
101 if (wp->w_id == id)
102 {
103 if (tpp != NULL)
104 *tpp = tp;
105 return wp;
106 }
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100107#ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +0200108 // popup windows are in separate lists
109 FOR_ALL_TABPAGES(tp)
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200110 FOR_ALL_POPUPWINS_IN_TAB(tp, wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200111 if (wp->w_id == id)
112 {
113 if (tpp != NULL)
114 *tpp = tp;
115 return wp;
116 }
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200117 FOR_ALL_POPUPWINS(wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200118 if (wp->w_id == id)
119 {
120 if (tpp != NULL)
Bram Moolenaar1f42f5a2020-09-03 18:52:24 +0200121 *tpp = curtab; // any tabpage would do
Bram Moolenaar261f3462019-09-07 15:45:32 +0200122 return wp;
123 }
124#endif
125
126 return NULL;
127}
128
129 static int
130win_id2win(typval_T *argvars)
131{
132 win_T *wp;
133 int nr = 1;
134 int id = tv_get_number(&argvars[0]);
135
136 FOR_ALL_WINDOWS(wp)
137 {
138 if (wp->w_id == id)
139 return nr;
140 ++nr;
141 }
142 return 0;
143}
144
145 void
146win_findbuf(typval_T *argvars, list_T *list)
147{
148 win_T *wp;
149 tabpage_T *tp;
150 int bufnr = tv_get_number(&argvars[0]);
151
152 FOR_ALL_TAB_WINDOWS(tp, wp)
153 if (wp->w_buffer->b_fnum == bufnr)
154 list_append_number(list, wp->w_id);
155}
156
157/*
158 * Find window specified by "vp" in tabpage "tp".
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100159 * Returns current window if "vp" is number zero.
160 * Returns NULL if not found.
Bram Moolenaar261f3462019-09-07 15:45:32 +0200161 */
162 win_T *
163find_win_by_nr(
164 typval_T *vp,
165 tabpage_T *tp) // NULL for current tab page
166{
167 win_T *wp;
168 int nr = (int)tv_get_number_chk(vp, NULL);
169
170 if (nr < 0)
171 return NULL;
172 if (nr == 0)
173 return curwin;
174
175 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
176 {
177 if (nr >= LOWEST_WIN_ID)
178 {
179 if (wp->w_id == nr)
180 return wp;
181 }
182 else if (--nr <= 0)
183 break;
184 }
185 if (nr >= LOWEST_WIN_ID)
186 {
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100187#ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +0200188 // check tab-local popup windows
Bram Moolenaaree93b732020-01-14 19:05:39 +0100189 for (wp = (tp == NULL ? curtab : tp)->tp_first_popupwin;
190 wp != NULL; wp = wp->w_next)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200191 if (wp->w_id == nr)
192 return wp;
193 // check global popup windows
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200194 FOR_ALL_POPUPWINS(wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200195 if (wp->w_id == nr)
196 return wp;
197#endif
198 return NULL;
199 }
200 return wp;
201}
202
203/*
204 * Find a window: When using a Window ID in any tab page, when using a number
205 * in the current tab page.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100206 * Returns NULL when not found.
Bram Moolenaar261f3462019-09-07 15:45:32 +0200207 */
208 win_T *
209find_win_by_nr_or_id(typval_T *vp)
210{
211 int nr = (int)tv_get_number_chk(vp, NULL);
212
213 if (nr >= LOWEST_WIN_ID)
214 return win_id2wp(tv_get_number(vp));
215 return find_win_by_nr(vp, NULL);
216}
217
218/*
219 * Find window specified by "wvp" in tabpage "tvp".
220 * Returns the tab page in 'ptp'
221 */
222 win_T *
223find_tabwin(
224 typval_T *wvp, // VAR_UNKNOWN for current window
225 typval_T *tvp, // VAR_UNKNOWN for current tab page
226 tabpage_T **ptp)
227{
228 win_T *wp = NULL;
229 tabpage_T *tp = NULL;
230 long n;
231
232 if (wvp->v_type != VAR_UNKNOWN)
233 {
234 if (tvp->v_type != VAR_UNKNOWN)
235 {
236 n = (long)tv_get_number(tvp);
237 if (n >= 0)
238 tp = find_tabpage(n);
239 }
240 else
241 tp = curtab;
242
243 if (tp != NULL)
244 {
245 wp = find_win_by_nr(wvp, tp);
246 if (wp == NULL && wvp->v_type == VAR_NUMBER
247 && wvp->vval.v_number != -1)
248 // A window with the specified number is not found
249 tp = NULL;
250 }
251 }
252 else
253 {
254 wp = curwin;
255 tp = curtab;
256 }
257
258 if (ptp != NULL)
259 *ptp = tp;
260
261 return wp;
262}
263
264/*
Bram Moolenaar9ba61942022-08-31 11:25:06 +0100265 * Get the layout of the given tab page for winlayout() and add it to "l".
Bram Moolenaar261f3462019-09-07 15:45:32 +0200266 */
267 static void
268get_framelayout(frame_T *fr, list_T *l, int outer)
269{
270 frame_T *child;
271 list_T *fr_list;
272 list_T *win_list;
273
274 if (fr == NULL)
275 return;
276
277 if (outer)
278 // outermost call from f_winlayout()
279 fr_list = l;
280 else
281 {
282 fr_list = list_alloc();
283 if (fr_list == NULL)
284 return;
Bram Moolenaar9ba61942022-08-31 11:25:06 +0100285 if (list_append_list(l, fr_list) == FAIL)
286 {
287 vim_free(fr_list);
288 return;
289 }
Bram Moolenaar261f3462019-09-07 15:45:32 +0200290 }
291
292 if (fr->fr_layout == FR_LEAF)
293 {
294 if (fr->fr_win != NULL)
295 {
296 list_append_string(fr_list, (char_u *)"leaf", -1);
297 list_append_number(fr_list, fr->fr_win->w_id);
298 }
299 }
300 else
301 {
302 list_append_string(fr_list,
303 fr->fr_layout == FR_ROW ? (char_u *)"row" : (char_u *)"col", -1);
304
305 win_list = list_alloc();
306 if (win_list == NULL)
307 return;
Bram Moolenaar9ba61942022-08-31 11:25:06 +0100308 if (list_append_list(fr_list, win_list) == FAIL)
309 {
310 vim_free(win_list);
311 return;
312 }
313
Bram Moolenaar261f3462019-09-07 15:45:32 +0200314 child = fr->fr_child;
315 while (child != NULL)
316 {
317 get_framelayout(child, win_list, FALSE);
318 child = child->fr_next;
319 }
320 }
321}
322
323/*
324 * Common code for tabpagewinnr() and winnr().
325 */
326 static int
327get_winnr(tabpage_T *tp, typval_T *argvar)
328{
329 win_T *twin;
330 int nr = 1;
331 win_T *wp;
332 char_u *arg;
333
334 twin = (tp == curtab) ? curwin : tp->tp_curwin;
335 if (argvar->v_type != VAR_UNKNOWN)
336 {
337 int invalid_arg = FALSE;
338
339 arg = tv_get_string_chk(argvar);
340 if (arg == NULL)
341 nr = 0; // type error; errmsg already given
342 else if (STRCMP(arg, "$") == 0)
343 twin = (tp == curtab) ? lastwin : tp->tp_lastwin;
344 else if (STRCMP(arg, "#") == 0)
345 {
346 twin = (tp == curtab) ? prevwin : tp->tp_prevwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200347 }
348 else
349 {
350 long count;
351 char_u *endp;
352
353 // Extract the window count (if specified). e.g. winnr('3j')
354 count = strtol((char *)arg, (char **)&endp, 10);
355 if (count <= 0)
356 count = 1; // if count is not specified, default to 1
357 if (endp != NULL && *endp != '\0')
358 {
359 if (STRCMP(endp, "j") == 0)
360 twin = win_vert_neighbor(tp, twin, FALSE, count);
361 else if (STRCMP(endp, "k") == 0)
362 twin = win_vert_neighbor(tp, twin, TRUE, count);
363 else if (STRCMP(endp, "h") == 0)
364 twin = win_horz_neighbor(tp, twin, TRUE, count);
365 else if (STRCMP(endp, "l") == 0)
366 twin = win_horz_neighbor(tp, twin, FALSE, count);
367 else
368 invalid_arg = TRUE;
369 }
370 else
371 invalid_arg = TRUE;
372 }
Bram Moolenaar631ebc42020-02-03 22:15:26 +0100373 if (twin == NULL)
374 nr = 0;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200375
376 if (invalid_arg)
377 {
Bram Moolenaar108010a2021-06-27 22:03:33 +0200378 semsg(_(e_invalid_expression_str), arg);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200379 nr = 0;
380 }
381 }
382
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +0000383 if (nr <= 0)
384 return 0;
385
386 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
387 wp != twin; wp = wp->w_next)
388 {
389 if (wp == NULL)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200390 {
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +0000391 // didn't find it in this tabpage
392 nr = 0;
393 break;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200394 }
Yegappan Lakshmanan1cfb14a2023-01-09 19:04:23 +0000395 ++nr;
396 }
Bram Moolenaar261f3462019-09-07 15:45:32 +0200397 return nr;
398}
399
400/*
401 * Returns information about a window as a dictionary.
402 */
403 static dict_T *
404get_win_info(win_T *wp, short tpnr, short winnr)
405{
406 dict_T *dict;
407
408 dict = dict_alloc();
409 if (dict == NULL)
410 return NULL;
411
LemonBoy8530b412022-04-20 19:00:36 +0100412 // make sure w_botline is valid
413 validate_botline_win(wp);
414
Bram Moolenaar261f3462019-09-07 15:45:32 +0200415 dict_add_number(dict, "tabnr", tpnr);
416 dict_add_number(dict, "winnr", winnr);
417 dict_add_number(dict, "winid", wp->w_id);
418 dict_add_number(dict, "height", wp->w_height);
419 dict_add_number(dict, "winrow", wp->w_winrow + 1);
420 dict_add_number(dict, "topline", wp->w_topline);
421 dict_add_number(dict, "botline", wp->w_botline - 1);
422#ifdef FEAT_MENU
423 dict_add_number(dict, "winbar", wp->w_winbar_height);
424#endif
425 dict_add_number(dict, "width", wp->w_width);
426 dict_add_number(dict, "wincol", wp->w_wincol + 1);
Bram Moolenaarcdf5fdb2021-11-20 11:14:24 +0000427 dict_add_number(dict, "textoff", win_col_off(wp));
Bram Moolenaar261f3462019-09-07 15:45:32 +0200428 dict_add_number(dict, "bufnr", wp->w_buffer->b_fnum);
429
430#ifdef FEAT_TERMINAL
431 dict_add_number(dict, "terminal", bt_terminal(wp->w_buffer));
432#endif
433#ifdef FEAT_QUICKFIX
434 dict_add_number(dict, "quickfix", bt_quickfix(wp->w_buffer));
435 dict_add_number(dict, "loclist",
436 (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL));
437#endif
438
439 // Add a reference to window variables
440 dict_add_dict(dict, "variables", wp->w_vars);
441
442 return dict;
443}
444
445/*
446 * Returns information (variables, options, etc.) about a tab page
447 * as a dictionary.
448 */
449 static dict_T *
450get_tabpage_info(tabpage_T *tp, int tp_idx)
451{
452 win_T *wp;
453 dict_T *dict;
454 list_T *l;
455
456 dict = dict_alloc();
457 if (dict == NULL)
458 return NULL;
459
460 dict_add_number(dict, "tabnr", tp_idx);
461
462 l = list_alloc();
463 if (l != NULL)
464 {
Bram Moolenaar00d253e2020-04-06 22:13:01 +0200465 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200466 list_append_number(l, (varnumber_T)wp->w_id);
467 dict_add_list(dict, "windows", l);
468 }
469
470 // Make a reference to tabpage variables
471 dict_add_dict(dict, "variables", tp->tp_vars);
472
473 return dict;
474}
475
476/*
477 * "gettabinfo()" function
478 */
479 void
480f_gettabinfo(typval_T *argvars, typval_T *rettv)
481{
482 tabpage_T *tp, *tparg = NULL;
483 dict_T *d;
484 int tpnr = 0;
485
Bram Moolenaar93a10962022-06-16 11:42:09 +0100486 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200487 return;
488
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200489 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
490 return;
491
Bram Moolenaar261f3462019-09-07 15:45:32 +0200492 if (argvars[0].v_type != VAR_UNKNOWN)
493 {
494 // Information about one tab page
495 tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
496 if (tparg == NULL)
497 return;
498 }
499
500 // Get information about a specific tab page or all tab pages
501 FOR_ALL_TABPAGES(tp)
502 {
503 tpnr++;
504 if (tparg != NULL && tp != tparg)
505 continue;
506 d = get_tabpage_info(tp, tpnr);
507 if (d != NULL)
508 list_append_dict(rettv->vval.v_list, d);
509 if (tparg != NULL)
510 return;
511 }
512}
513
514/*
515 * "getwininfo()" function
516 */
517 void
518f_getwininfo(typval_T *argvars, typval_T *rettv)
519{
520 tabpage_T *tp;
521 win_T *wp = NULL, *wparg = NULL;
522 dict_T *d;
523 short tabnr = 0, winnr;
524
Bram Moolenaar93a10962022-06-16 11:42:09 +0100525 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200526 return;
527
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200528 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
529 return;
530
Bram Moolenaar261f3462019-09-07 15:45:32 +0200531 if (argvars[0].v_type != VAR_UNKNOWN)
532 {
533 wparg = win_id2wp(tv_get_number(&argvars[0]));
534 if (wparg == NULL)
535 return;
536 }
537
538 // Collect information about either all the windows across all the tab
539 // pages or one particular window.
540 FOR_ALL_TABPAGES(tp)
541 {
542 tabnr++;
543 winnr = 0;
544 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
545 {
546 winnr++;
547 if (wparg != NULL && wp != wparg)
548 continue;
549 d = get_win_info(wp, tabnr, winnr);
550 if (d != NULL)
551 list_append_dict(rettv->vval.v_list, d);
552 if (wparg != NULL)
553 // found information about a specific window
554 return;
555 }
556 }
Bram Moolenaar99ca9c42020-09-22 21:55:41 +0200557#ifdef FEAT_PROP_POPUP
558 if (wparg != NULL)
559 {
560 tabnr = 0;
561 FOR_ALL_TABPAGES(tp)
562 {
563 tabnr++;
564 FOR_ALL_POPUPWINS_IN_TAB(tp, wp)
565 if (wp == wparg)
566 break;
567 }
568 d = get_win_info(wparg, tp == NULL ? 0 : tabnr, 0);
569 if (d != NULL)
570 list_append_dict(rettv->vval.v_list, d);
571 }
572#endif
Bram Moolenaar261f3462019-09-07 15:45:32 +0200573}
574
575/*
576 * "getwinpos({timeout})" function
577 */
578 void
579f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv)
580{
581 int x = -1;
582 int y = -1;
583
584 if (rettv_list_alloc(rettv) == FAIL)
585 return;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200586
587 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
588 return;
589
Bram Moolenaar261f3462019-09-07 15:45:32 +0200590#if defined(FEAT_GUI) \
591 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
592 || defined(MSWIN)
593 {
594 varnumber_T timeout = 100;
595
596 if (argvars[0].v_type != VAR_UNKNOWN)
597 timeout = tv_get_number(&argvars[0]);
598
599 (void)ui_get_winpos(&x, &y, timeout);
600 }
601#endif
602 list_append_number(rettv->vval.v_list, (varnumber_T)x);
603 list_append_number(rettv->vval.v_list, (varnumber_T)y);
604}
605
606
607/*
608 * "getwinposx()" function
609 */
610 void
611f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
612{
613 rettv->vval.v_number = -1;
614#if defined(FEAT_GUI) \
615 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
616 || defined(MSWIN)
617
618 {
619 int x, y;
620
621 if (ui_get_winpos(&x, &y, 100) == OK)
622 rettv->vval.v_number = x;
623 }
624#endif
625}
626
627/*
628 * "getwinposy()" function
629 */
630 void
631f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
632{
633 rettv->vval.v_number = -1;
634#if defined(FEAT_GUI) \
635 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
636 || defined(MSWIN)
637 {
638 int x, y;
639
640 if (ui_get_winpos(&x, &y, 100) == OK)
641 rettv->vval.v_number = y;
642 }
643#endif
644}
645
646/*
647 * "tabpagenr()" function
648 */
649 void
650f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
651{
652 int nr = 1;
653 char_u *arg;
654
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200655 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
656 return;
657
Bram Moolenaar261f3462019-09-07 15:45:32 +0200658 if (argvars[0].v_type != VAR_UNKNOWN)
659 {
660 arg = tv_get_string_chk(&argvars[0]);
661 nr = 0;
662 if (arg != NULL)
663 {
664 if (STRCMP(arg, "$") == 0)
665 nr = tabpage_index(NULL) - 1;
Bram Moolenaar62a23252020-08-09 14:04:42 +0200666 else if (STRCMP(arg, "#") == 0)
667 nr = valid_tabpage(lastused_tabpage) ?
668 tabpage_index(lastused_tabpage) : 0;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200669 else
Bram Moolenaar108010a2021-06-27 22:03:33 +0200670 semsg(_(e_invalid_expression_str), arg);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200671 }
672 }
673 else
674 nr = tabpage_index(curtab);
675 rettv->vval.v_number = nr;
676}
677
678/*
679 * "tabpagewinnr()" function
680 */
681 void
682f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv)
683{
684 int nr = 1;
685 tabpage_T *tp;
686
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200687 if (in_vim9script()
688 && (check_for_number_arg(argvars, 0) == FAIL
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200689 || check_for_opt_string_arg(argvars, 1) == FAIL))
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200690 return;
691
Bram Moolenaar261f3462019-09-07 15:45:32 +0200692 tp = find_tabpage((int)tv_get_number(&argvars[0]));
693 if (tp == NULL)
694 nr = 0;
695 else
696 nr = get_winnr(tp, &argvars[1]);
697 rettv->vval.v_number = nr;
698}
699
700/*
701 * "win_execute()" function
702 */
703 void
704f_win_execute(typval_T *argvars, typval_T *rettv)
705{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200706 int id;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200707 tabpage_T *tp;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200708 win_T *wp;
Bram Moolenaar18f47402022-01-06 13:24:51 +0000709 switchwin_T switchwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200710
Bram Moolenaar37487e12021-01-12 22:08:53 +0100711 // Return an empty string if something fails.
712 rettv->v_type = VAR_STRING;
713 rettv->vval.v_string = NULL;
714
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200715 if (in_vim9script()
716 && (check_for_number_arg(argvars, 0) == FAIL
717 || check_for_string_or_list_arg(argvars, 1) == FAIL
718 || check_for_opt_string_arg(argvars, 2) == FAIL))
719 return;
720
721 id = (int)tv_get_number(argvars);
722 wp = win_id2wp_tp(id, &tp);
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +0000723 if (wp == NULL || tp == NULL)
724 return;
725
726 pos_T curpos = wp->w_cursor;
727 char_u cwd[MAXPATHL];
728 int cwd_status = FAIL;
729#ifdef FEAT_AUTOCHDIR
730 char_u autocwd[MAXPATHL];
731 int apply_acd = FALSE;
732#endif
733
734 // Getting and setting directory can be slow on some systems, only do
735 // this when the current or target window/tab have a local directory or
736 // 'acd' is set.
737 if (curwin != wp
738 && (curwin->w_localdir != NULL
739 || wp->w_localdir != NULL
740 || (curtab != tp
741 && (curtab->tp_localdir != NULL
742 || tp->tp_localdir != NULL))
743#ifdef FEAT_AUTOCHDIR
744 || p_acd
745#endif
746 ))
747 cwd_status = mch_dirname(cwd, MAXPATHL);
748
749#ifdef FEAT_AUTOCHDIR
750 // If 'acd' is set, check we are using that directory. If yes, then
751 // apply 'acd' afterwards, otherwise restore the current directory.
752 if (cwd_status == OK && p_acd)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200753 {
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +0000754 do_autochdir();
755 apply_acd = mch_dirname(autocwd, MAXPATHL) == OK
756 && STRCMP(cwd, autocwd) == 0;
757 }
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000758#endif
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000759
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +0000760 if (switch_win_noblock(&switchwin, wp, tp, TRUE) == OK)
761 {
762 check_cursor();
763 execute_common(argvars, rettv, 1);
764 }
765 restore_win_noblock(&switchwin, TRUE);
Bram Moolenaard6f27c62022-01-11 12:37:20 +0000766#ifdef FEAT_AUTOCHDIR
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +0000767 if (apply_acd)
768 do_autochdir();
769 else
Bram Moolenaard6f27c62022-01-11 12:37:20 +0000770#endif
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +0000771 if (cwd_status == OK)
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000772 mch_chdir((char *)cwd);
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200773
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +0000774 // Update the status line if the cursor moved.
775 if (win_valid(wp) && !EQUAL_POS(curpos, wp->w_cursor))
776 wp->w_redr_status = TRUE;
Bram Moolenaare664a322022-01-07 14:08:03 +0000777
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +0000778 // In case the command moved the cursor or changed the Visual area,
779 // check it is valid.
780 check_cursor();
781 if (VIsual_active)
782 check_pos(curbuf, &VIsual);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200783}
784
785/*
786 * "win_findbuf()" function
787 */
788 void
789f_win_findbuf(typval_T *argvars, typval_T *rettv)
790{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200791 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
792 return;
793
Bram Moolenaar93a10962022-06-16 11:42:09 +0100794 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200795 win_findbuf(argvars, rettv->vval.v_list);
796}
797
798/*
799 * "win_getid()" function
800 */
801 void
802f_win_getid(typval_T *argvars, typval_T *rettv)
803{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200804 if (in_vim9script()
805 && (check_for_opt_number_arg(argvars, 0) == FAIL
806 || (argvars[0].v_type != VAR_UNKNOWN
807 && check_for_opt_number_arg(argvars, 1) == FAIL)))
808 return;
809
Bram Moolenaar261f3462019-09-07 15:45:32 +0200810 rettv->vval.v_number = win_getid(argvars);
811}
812
813/*
814 * "win_gotoid()" function
815 */
816 void
817f_win_gotoid(typval_T *argvars, typval_T *rettv)
818{
Bram Moolenaara046b372019-09-15 17:26:07 +0200819 win_T *wp;
820 tabpage_T *tp;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200821 int id;
Bram Moolenaara046b372019-09-15 17:26:07 +0200822
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200823 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
824 return;
825
826 id = tv_get_number(&argvars[0]);
Sean Dewarf8658952024-02-20 22:05:10 +0100827 if (text_or_buf_locked())
Bram Moolenaara046b372019-09-15 17:26:07 +0200828 return;
LemonBoy4a392d22022-04-23 14:07:56 +0100829#if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL)
830 if (popup_is_popup(curwin) && curbuf->b_term != NULL)
831 {
832 emsg(_(e_not_allowed_for_terminal_in_popup_window));
833 return;
834 }
835#endif
Bram Moolenaara046b372019-09-15 17:26:07 +0200836 FOR_ALL_TAB_WINDOWS(tp, wp)
837 if (wp->w_id == id)
838 {
Bram Moolenaar3aca0912022-04-18 18:32:19 +0100839 // When jumping to another buffer stop Visual mode.
840 if (VIsual_active && wp->w_buffer != curbuf)
841 end_visual_mode();
Bram Moolenaara046b372019-09-15 17:26:07 +0200842 goto_tabpage_win(tp, wp);
843 rettv->vval.v_number = 1;
844 return;
845 }
Bram Moolenaar261f3462019-09-07 15:45:32 +0200846}
847
848/*
849 * "win_id2tabwin()" function
850 */
851 void
852f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
853{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200854 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
855 return;
856
Bram Moolenaar93a10962022-06-16 11:42:09 +0100857 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200858 win_id2tabwin(argvars, rettv->vval.v_list);
859}
860
861/*
862 * "win_id2win()" function
863 */
864 void
865f_win_id2win(typval_T *argvars, typval_T *rettv)
866{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200867 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
868 return;
869
Bram Moolenaar261f3462019-09-07 15:45:32 +0200870 rettv->vval.v_number = win_id2win(argvars);
871}
872
873/*
Daniel Steinbergee630312022-01-10 13:36:34 +0000874 * "win_move_separator()" function
875 */
876 void
877f_win_move_separator(typval_T *argvars, typval_T *rettv)
878{
879 win_T *wp;
880 int offset;
881
882 rettv->vval.v_number = FALSE;
883
884 if (in_vim9script()
885 && (check_for_number_arg(argvars, 0) == FAIL
886 || check_for_number_arg(argvars, 1) == FAIL))
887 return;
888
889 wp = find_win_by_nr_or_id(&argvars[0]);
890 if (wp == NULL || win_valid_popup(wp))
891 return;
zeertzjq873f41a2022-11-01 11:44:43 +0000892 if (!win_valid(wp))
893 {
894 emsg(_(e_cannot_resize_window_in_another_tab_page));
895 return;
896 }
Daniel Steinbergee630312022-01-10 13:36:34 +0000897
898 offset = (int)tv_get_number(&argvars[1]);
899 win_drag_vsep_line(wp, offset);
900 rettv->vval.v_number = TRUE;
901}
902
903/*
904 * "win_move_statusline()" function
905 */
906 void
907f_win_move_statusline(typval_T *argvars, typval_T *rettv)
908{
909 win_T *wp;
910 int offset;
911
912 rettv->vval.v_number = FALSE;
913
914 if (in_vim9script()
915 && (check_for_number_arg(argvars, 0) == FAIL
916 || check_for_number_arg(argvars, 1) == FAIL))
917 return;
918
919 wp = find_win_by_nr_or_id(&argvars[0]);
920 if (wp == NULL || win_valid_popup(wp))
921 return;
Bram Moolenaar86e67172022-10-31 12:24:12 +0000922 if (!win_valid(wp))
923 {
924 emsg(_(e_cannot_resize_window_in_another_tab_page));
925 return;
926 }
Daniel Steinbergee630312022-01-10 13:36:34 +0000927
928 offset = (int)tv_get_number(&argvars[1]);
929 win_drag_status_line(wp, offset);
930 rettv->vval.v_number = TRUE;
931}
932
933/*
Bram Moolenaar261f3462019-09-07 15:45:32 +0200934 * "win_screenpos()" function
935 */
936 void
937f_win_screenpos(typval_T *argvars, typval_T *rettv)
938{
939 win_T *wp;
940
941 if (rettv_list_alloc(rettv) == FAIL)
942 return;
943
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200944 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
945 return;
946
Bram Moolenaar261f3462019-09-07 15:45:32 +0200947 wp = find_win_by_nr_or_id(&argvars[0]);
948 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1);
949 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1);
950}
951
952/*
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200953 * "win_splitmove()" function
954 */
955 void
956f_win_splitmove(typval_T *argvars, typval_T *rettv)
957{
Sean Dewar0fd44a52024-02-20 20:28:15 +0100958 win_T *wp, *targetwin;
959 win_T *oldwin = curwin;
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200960 int flags = 0, size = 0;
961
Sean Dewar0fd44a52024-02-20 20:28:15 +0100962 rettv->vval.v_number = -1;
963
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200964 if (in_vim9script()
965 && (check_for_number_arg(argvars, 0) == FAIL
966 || check_for_number_arg(argvars, 1) == FAIL
967 || check_for_opt_dict_arg(argvars, 2) == FAIL))
968 return;
969
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200970 wp = find_win_by_nr_or_id(&argvars[0]);
971 targetwin = find_win_by_nr_or_id(&argvars[1]);
972
Bram Moolenaar7b94e772020-01-06 21:03:24 +0100973 if (wp == NULL || targetwin == NULL || wp == targetwin
Bram Moolenaar0f1563f2020-03-20 21:15:51 +0100974 || !win_valid(wp) || !win_valid(targetwin)
975 || win_valid_popup(wp) || win_valid_popup(targetwin))
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200976 {
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100977 emsg(_(e_invalid_window_number));
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200978 return;
979 }
980
981 if (argvars[2].v_type != VAR_UNKNOWN)
982 {
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100983 dict_T *d;
984 dictitem_T *di;
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200985
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +0100986 if (check_for_nonnull_dict_arg(argvars, 2) == FAIL)
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100987 return;
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200988
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100989 d = argvars[2].vval.v_dict;
Bram Moolenaard61efa52022-07-23 09:52:04 +0100990 if (dict_get_bool(d, "vertical", FALSE))
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100991 flags |= WSP_VERT;
992 if ((di = dict_find(d, (char_u *)"rightbelow", -1)) != NULL)
993 flags |= tv_get_bool(&di->di_tv) ? WSP_BELOW : WSP_ABOVE;
Bram Moolenaard61efa52022-07-23 09:52:04 +0100994 size = (int)dict_get_number(d, "size");
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200995 }
996
Sean Dewar0fd44a52024-02-20 20:28:15 +0100997 // Check if we can split the target before we bother switching windows.
Sean Dewarf8658952024-02-20 22:05:10 +0100998 if (text_or_buf_locked() || check_split_disallowed(targetwin) == FAIL)
Sean Dewar0fd44a52024-02-20 20:28:15 +0100999 return;
1000
1001 if (curwin != targetwin)
1002 win_goto(targetwin);
1003
1004 // Autocommands may have sent us elsewhere or closed "wp" or "oldwin".
1005 if (curwin == targetwin && win_valid(wp))
1006 {
1007 if (win_splitmove(wp, size, flags) == OK)
1008 rettv->vval.v_number = 0;
1009 }
1010 else
1011 emsg(_(e_autocommands_caused_command_to_abort));
1012
1013 if (oldwin != curwin && win_valid(oldwin))
1014 win_goto(oldwin);
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001015}
1016
1017/*
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001018 * "win_gettype(nr)" function
1019 */
1020 void
1021f_win_gettype(typval_T *argvars, typval_T *rettv)
1022{
1023 win_T *wp = curwin;
1024
1025 rettv->v_type = VAR_STRING;
1026 rettv->vval.v_string = NULL;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001027
1028 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
1029 return;
1030
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001031 if (argvars[0].v_type != VAR_UNKNOWN)
1032 {
1033 wp = find_win_by_nr_or_id(&argvars[0]);
1034 if (wp == NULL)
1035 {
1036 rettv->vval.v_string = vim_strsave((char_u *)"unknown");
1037 return;
1038 }
1039 }
Bram Moolenaare76062c2022-11-28 18:51:43 +00001040 if (is_aucmd_win(wp))
Bram Moolenaar40a019f2020-06-17 21:41:35 +02001041 rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001042#if defined(FEAT_QUICKFIX)
1043 else if (wp->w_p_pvw)
1044 rettv->vval.v_string = vim_strsave((char_u *)"preview");
1045#endif
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001046#ifdef FEAT_PROP_POPUP
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001047 else if (WIN_IS_POPUP(wp))
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001048 rettv->vval.v_string = vim_strsave((char_u *)"popup");
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001049#endif
Sean Dewar988f7432023-08-16 14:17:36 +01001050 else if (wp == cmdwin_win)
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001051 rettv->vval.v_string = vim_strsave((char_u *)"command");
Yegappan Lakshmanan28d84212021-07-31 12:43:23 +02001052#ifdef FEAT_QUICKFIX
1053 else if (bt_quickfix(wp->w_buffer))
1054 rettv->vval.v_string = vim_strsave((char_u *)
1055 (wp->w_llist_ref != NULL ? "loclist" : "quickfix"));
1056#endif
1057
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001058}
1059
1060/*
1061 * "getcmdwintype()" function
1062 */
1063 void
1064f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv)
1065{
1066 rettv->v_type = VAR_STRING;
1067 rettv->vval.v_string = NULL;
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001068 rettv->vval.v_string = alloc(2);
Yegappan Lakshmanandc4daa32023-01-02 16:54:53 +00001069 if (rettv->vval.v_string == NULL)
1070 return;
1071
1072 rettv->vval.v_string[0] = cmdwin_type;
1073 rettv->vval.v_string[1] = NUL;
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001074}
1075
1076/*
Bram Moolenaar261f3462019-09-07 15:45:32 +02001077 * "winbufnr(nr)" function
1078 */
1079 void
1080f_winbufnr(typval_T *argvars, typval_T *rettv)
1081{
1082 win_T *wp;
1083
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001084 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1085 return;
1086
Bram Moolenaar261f3462019-09-07 15:45:32 +02001087 wp = find_win_by_nr_or_id(&argvars[0]);
1088 if (wp == NULL)
1089 rettv->vval.v_number = -1;
1090 else
1091 rettv->vval.v_number = wp->w_buffer->b_fnum;
1092}
1093
1094/*
1095 * "wincol()" function
1096 */
1097 void
1098f_wincol(typval_T *argvars UNUSED, typval_T *rettv)
1099{
1100 validate_cursor();
1101 rettv->vval.v_number = curwin->w_wcol + 1;
1102}
1103
1104/*
1105 * "winheight(nr)" function
1106 */
1107 void
1108f_winheight(typval_T *argvars, typval_T *rettv)
1109{
1110 win_T *wp;
1111
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001112 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1113 return;
1114
Bram Moolenaar261f3462019-09-07 15:45:32 +02001115 wp = find_win_by_nr_or_id(&argvars[0]);
1116 if (wp == NULL)
1117 rettv->vval.v_number = -1;
1118 else
1119 rettv->vval.v_number = wp->w_height;
1120}
1121
1122/*
1123 * "winlayout()" function
1124 */
1125 void
1126f_winlayout(typval_T *argvars, typval_T *rettv)
1127{
1128 tabpage_T *tp;
1129
Bram Moolenaar93a10962022-06-16 11:42:09 +01001130 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001131 return;
1132
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001133 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
1134 return;
1135
Bram Moolenaar261f3462019-09-07 15:45:32 +02001136 if (argvars[0].v_type == VAR_UNKNOWN)
1137 tp = curtab;
1138 else
1139 {
1140 tp = find_tabpage((int)tv_get_number(&argvars[0]));
1141 if (tp == NULL)
1142 return;
1143 }
1144
1145 get_framelayout(tp->tp_topframe, rettv->vval.v_list, TRUE);
1146}
1147
1148/*
1149 * "winline()" function
1150 */
1151 void
1152f_winline(typval_T *argvars UNUSED, typval_T *rettv)
1153{
1154 validate_cursor();
1155 rettv->vval.v_number = curwin->w_wrow + 1;
1156}
1157
1158/*
1159 * "winnr()" function
1160 */
1161 void
1162f_winnr(typval_T *argvars UNUSED, typval_T *rettv)
1163{
1164 int nr = 1;
1165
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001166 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
1167 return;
1168
Bram Moolenaar261f3462019-09-07 15:45:32 +02001169 nr = get_winnr(curtab, &argvars[0]);
1170 rettv->vval.v_number = nr;
1171}
1172
1173/*
1174 * "winrestcmd()" function
1175 */
1176 void
1177f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv)
1178{
1179 win_T *wp;
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001180 int i;
1181 int winnr;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001182 garray_T ga;
1183 char_u buf[50];
1184
Bram Moolenaar04935fb2022-01-08 16:19:22 +00001185 ga_init2(&ga, sizeof(char), 70);
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001186
1187 // Do this twice to handle some window layouts properly.
1188 for (i = 0; i < 2; ++i)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001189 {
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001190 winnr = 1;
1191 FOR_ALL_WINDOWS(wp)
1192 {
1193 sprintf((char *)buf, ":%dresize %d|", winnr, wp->w_height);
1194 ga_concat(&ga, buf);
1195 sprintf((char *)buf, "vert :%dresize %d|", winnr, wp->w_width);
1196 ga_concat(&ga, buf);
1197 ++winnr;
1198 }
Bram Moolenaar261f3462019-09-07 15:45:32 +02001199 }
1200 ga_append(&ga, NUL);
1201
1202 rettv->vval.v_string = ga.ga_data;
1203 rettv->v_type = VAR_STRING;
1204}
1205
1206/*
1207 * "winrestview()" function
1208 */
1209 void
1210f_winrestview(typval_T *argvars, typval_T *rettv UNUSED)
1211{
1212 dict_T *dict;
1213
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001214 if (check_for_nonnull_dict_arg(argvars, 0) == FAIL)
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001215 return;
1216
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001217 dict = argvars[0].vval.v_dict;
1218 if (dict_has_key(dict, "lnum"))
1219 curwin->w_cursor.lnum = (linenr_T)dict_get_number(dict, "lnum");
1220 if (dict_has_key(dict, "col"))
1221 curwin->w_cursor.col = (colnr_T)dict_get_number(dict, "col");
1222 if (dict_has_key(dict, "coladd"))
1223 curwin->w_cursor.coladd = (colnr_T)dict_get_number(dict, "coladd");
1224 if (dict_has_key(dict, "curswant"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001225 {
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001226 curwin->w_curswant = (colnr_T)dict_get_number(dict, "curswant");
1227 curwin->w_set_curswant = FALSE;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001228 }
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001229
1230 if (dict_has_key(dict, "topline"))
1231 set_topline(curwin, (linenr_T)dict_get_number(dict, "topline"));
1232#ifdef FEAT_DIFF
1233 if (dict_has_key(dict, "topfill"))
1234 curwin->w_topfill = (int)dict_get_number(dict, "topfill");
1235#endif
1236 if (dict_has_key(dict, "leftcol"))
1237 curwin->w_leftcol = (colnr_T)dict_get_number(dict, "leftcol");
1238 if (dict_has_key(dict, "skipcol"))
1239 curwin->w_skipcol = (colnr_T)dict_get_number(dict, "skipcol");
1240
1241 check_cursor();
1242 win_new_height(curwin, curwin->w_height);
1243 win_new_width(curwin, curwin->w_width);
1244 changed_window_setting();
1245
1246 if (curwin->w_topline <= 0)
1247 curwin->w_topline = 1;
1248 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
1249 curwin->w_topline = curbuf->b_ml.ml_line_count;
1250#ifdef FEAT_DIFF
1251 check_topfill(curwin, TRUE);
1252#endif
Bram Moolenaar261f3462019-09-07 15:45:32 +02001253}
1254
1255/*
1256 * "winsaveview()" function
1257 */
1258 void
1259f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv)
1260{
1261 dict_T *dict;
1262
1263 if (rettv_dict_alloc(rettv) == FAIL)
1264 return;
1265 dict = rettv->vval.v_dict;
1266
1267 dict_add_number(dict, "lnum", (long)curwin->w_cursor.lnum);
1268 dict_add_number(dict, "col", (long)curwin->w_cursor.col);
1269 dict_add_number(dict, "coladd", (long)curwin->w_cursor.coladd);
1270 update_curswant();
1271 dict_add_number(dict, "curswant", (long)curwin->w_curswant);
1272
1273 dict_add_number(dict, "topline", (long)curwin->w_topline);
1274#ifdef FEAT_DIFF
1275 dict_add_number(dict, "topfill", (long)curwin->w_topfill);
1276#endif
1277 dict_add_number(dict, "leftcol", (long)curwin->w_leftcol);
1278 dict_add_number(dict, "skipcol", (long)curwin->w_skipcol);
1279}
1280
1281/*
1282 * "winwidth(nr)" function
1283 */
1284 void
1285f_winwidth(typval_T *argvars, typval_T *rettv)
1286{
1287 win_T *wp;
1288
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001289 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1290 return;
1291
Bram Moolenaar261f3462019-09-07 15:45:32 +02001292 wp = find_win_by_nr_or_id(&argvars[0]);
1293 if (wp == NULL)
1294 rettv->vval.v_number = -1;
1295 else
1296 rettv->vval.v_number = wp->w_width;
1297}
1298#endif // FEAT_EVAL
1299
1300#if defined(FEAT_EVAL) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
1301 || defined(PROTO)
1302/*
1303 * Set "win" to be the curwin and "tp" to be the current tab page.
1304 * restore_win() MUST be called to undo, also when FAIL is returned.
1305 * No autocommands will be executed until restore_win() is called.
1306 * When "no_display" is TRUE the display won't be affected, no redraw is
1307 * triggered, another tabpage access is limited.
1308 * Returns FAIL if switching to "win" failed.
1309 */
1310 int
1311switch_win(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001312 switchwin_T *switchwin,
1313 win_T *win,
1314 tabpage_T *tp,
1315 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001316{
1317 block_autocmds();
Bram Moolenaar18f47402022-01-06 13:24:51 +00001318 return switch_win_noblock(switchwin, win, tp, no_display);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001319}
1320
1321/*
1322 * As switch_win() but without blocking autocommands.
1323 */
1324 int
1325switch_win_noblock(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001326 switchwin_T *switchwin,
1327 win_T *win,
1328 tabpage_T *tp,
1329 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001330{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001331 CLEAR_POINTER(switchwin);
1332 switchwin->sw_curwin = curwin;
1333 if (win == curwin)
1334 switchwin->sw_same_win = TRUE;
1335 else
1336 {
1337 // Disable Visual selection, because redrawing may fail.
1338 switchwin->sw_visual_active = VIsual_active;
1339 VIsual_active = FALSE;
1340 }
1341
Bram Moolenaar261f3462019-09-07 15:45:32 +02001342 if (tp != NULL)
1343 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00001344 switchwin->sw_curtab = curtab;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001345 if (no_display)
1346 {
1347 curtab->tp_firstwin = firstwin;
1348 curtab->tp_lastwin = lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001349 curtab->tp_topframe = topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001350 curtab = tp;
1351 firstwin = curtab->tp_firstwin;
1352 lastwin = curtab->tp_lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001353 topframe = curtab->tp_topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001354 }
1355 else
1356 goto_tabpage_tp(tp, FALSE, FALSE);
1357 }
1358 if (!win_valid(win))
1359 return FAIL;
1360 curwin = win;
1361 curbuf = curwin->w_buffer;
1362 return OK;
1363}
1364
1365/*
1366 * Restore current tabpage and window saved by switch_win(), if still valid.
1367 * When "no_display" is TRUE the display won't be affected, no redraw is
1368 * triggered.
1369 */
1370 void
1371restore_win(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001372 switchwin_T *switchwin,
1373 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001374{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001375 restore_win_noblock(switchwin, no_display);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001376 unblock_autocmds();
1377}
1378
1379/*
1380 * As restore_win() but without unblocking autocommands.
1381 */
1382 void
1383restore_win_noblock(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001384 switchwin_T *switchwin,
1385 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001386{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001387 if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001388 {
1389 if (no_display)
1390 {
1391 curtab->tp_firstwin = firstwin;
1392 curtab->tp_lastwin = lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001393 curtab->tp_topframe = topframe;
Bram Moolenaar18f47402022-01-06 13:24:51 +00001394 curtab = switchwin->sw_curtab;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001395 firstwin = curtab->tp_firstwin;
1396 lastwin = curtab->tp_lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001397 topframe = curtab->tp_topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001398 }
1399 else
Bram Moolenaar18f47402022-01-06 13:24:51 +00001400 goto_tabpage_tp(switchwin->sw_curtab, FALSE, FALSE);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001401 }
Bram Moolenaar18f47402022-01-06 13:24:51 +00001402
1403 if (!switchwin->sw_same_win)
1404 VIsual_active = switchwin->sw_visual_active;
1405
1406 if (win_valid(switchwin->sw_curwin))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001407 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00001408 curwin = switchwin->sw_curwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001409 curbuf = curwin->w_buffer;
1410 }
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01001411# ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +02001412 else if (WIN_IS_POPUP(curwin))
1413 // original window was closed and now we're in a popup window: Go
1414 // to the first valid window.
1415 win_goto(firstwin);
1416# endif
Bram Moolenaar261f3462019-09-07 15:45:32 +02001417}
1418#endif