blob: f8c0c7acfd9cd4fa8036e15a008ebbc2cd95bf84 [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]);
27 if (winnr > 0)
28 {
29 if (argvars[1].v_type == VAR_UNKNOWN)
30 wp = firstwin;
31 else
32 {
33 tabpage_T *tp;
34 int tabnr = tv_get_number(&argvars[1]);
35
36 FOR_ALL_TABPAGES(tp)
37 if (--tabnr == 0)
38 break;
39 if (tp == NULL)
40 return -1;
41 if (tp == curtab)
42 wp = firstwin;
43 else
44 wp = tp->tp_firstwin;
45 }
46 for ( ; wp != NULL; wp = wp->w_next)
47 if (--winnr == 0)
48 return wp->w_id;
49 }
50 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
383 if (nr > 0)
384 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
385 wp != twin; wp = wp->w_next)
386 {
387 if (wp == NULL)
388 {
389 // didn't find it in this tabpage
390 nr = 0;
391 break;
392 }
393 ++nr;
394 }
395 return nr;
396}
397
398/*
399 * Returns information about a window as a dictionary.
400 */
401 static dict_T *
402get_win_info(win_T *wp, short tpnr, short winnr)
403{
404 dict_T *dict;
405
406 dict = dict_alloc();
407 if (dict == NULL)
408 return NULL;
409
LemonBoy8530b412022-04-20 19:00:36 +0100410 // make sure w_botline is valid
411 validate_botline_win(wp);
412
Bram Moolenaar261f3462019-09-07 15:45:32 +0200413 dict_add_number(dict, "tabnr", tpnr);
414 dict_add_number(dict, "winnr", winnr);
415 dict_add_number(dict, "winid", wp->w_id);
416 dict_add_number(dict, "height", wp->w_height);
417 dict_add_number(dict, "winrow", wp->w_winrow + 1);
418 dict_add_number(dict, "topline", wp->w_topline);
419 dict_add_number(dict, "botline", wp->w_botline - 1);
420#ifdef FEAT_MENU
421 dict_add_number(dict, "winbar", wp->w_winbar_height);
422#endif
423 dict_add_number(dict, "width", wp->w_width);
424 dict_add_number(dict, "wincol", wp->w_wincol + 1);
Bram Moolenaarcdf5fdb2021-11-20 11:14:24 +0000425 dict_add_number(dict, "textoff", win_col_off(wp));
Bram Moolenaar261f3462019-09-07 15:45:32 +0200426 dict_add_number(dict, "bufnr", wp->w_buffer->b_fnum);
427
428#ifdef FEAT_TERMINAL
429 dict_add_number(dict, "terminal", bt_terminal(wp->w_buffer));
430#endif
431#ifdef FEAT_QUICKFIX
432 dict_add_number(dict, "quickfix", bt_quickfix(wp->w_buffer));
433 dict_add_number(dict, "loclist",
434 (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL));
435#endif
436
437 // Add a reference to window variables
438 dict_add_dict(dict, "variables", wp->w_vars);
439
440 return dict;
441}
442
443/*
444 * Returns information (variables, options, etc.) about a tab page
445 * as a dictionary.
446 */
447 static dict_T *
448get_tabpage_info(tabpage_T *tp, int tp_idx)
449{
450 win_T *wp;
451 dict_T *dict;
452 list_T *l;
453
454 dict = dict_alloc();
455 if (dict == NULL)
456 return NULL;
457
458 dict_add_number(dict, "tabnr", tp_idx);
459
460 l = list_alloc();
461 if (l != NULL)
462 {
Bram Moolenaar00d253e2020-04-06 22:13:01 +0200463 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200464 list_append_number(l, (varnumber_T)wp->w_id);
465 dict_add_list(dict, "windows", l);
466 }
467
468 // Make a reference to tabpage variables
469 dict_add_dict(dict, "variables", tp->tp_vars);
470
471 return dict;
472}
473
474/*
475 * "gettabinfo()" function
476 */
477 void
478f_gettabinfo(typval_T *argvars, typval_T *rettv)
479{
480 tabpage_T *tp, *tparg = NULL;
481 dict_T *d;
482 int tpnr = 0;
483
Bram Moolenaar93a10962022-06-16 11:42:09 +0100484 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200485 return;
486
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200487 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
488 return;
489
Bram Moolenaar261f3462019-09-07 15:45:32 +0200490 if (argvars[0].v_type != VAR_UNKNOWN)
491 {
492 // Information about one tab page
493 tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
494 if (tparg == NULL)
495 return;
496 }
497
498 // Get information about a specific tab page or all tab pages
499 FOR_ALL_TABPAGES(tp)
500 {
501 tpnr++;
502 if (tparg != NULL && tp != tparg)
503 continue;
504 d = get_tabpage_info(tp, tpnr);
505 if (d != NULL)
506 list_append_dict(rettv->vval.v_list, d);
507 if (tparg != NULL)
508 return;
509 }
510}
511
512/*
513 * "getwininfo()" function
514 */
515 void
516f_getwininfo(typval_T *argvars, typval_T *rettv)
517{
518 tabpage_T *tp;
519 win_T *wp = NULL, *wparg = NULL;
520 dict_T *d;
521 short tabnr = 0, winnr;
522
Bram Moolenaar93a10962022-06-16 11:42:09 +0100523 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200524 return;
525
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200526 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
527 return;
528
Bram Moolenaar261f3462019-09-07 15:45:32 +0200529 if (argvars[0].v_type != VAR_UNKNOWN)
530 {
531 wparg = win_id2wp(tv_get_number(&argvars[0]));
532 if (wparg == NULL)
533 return;
534 }
535
536 // Collect information about either all the windows across all the tab
537 // pages or one particular window.
538 FOR_ALL_TABPAGES(tp)
539 {
540 tabnr++;
541 winnr = 0;
542 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
543 {
544 winnr++;
545 if (wparg != NULL && wp != wparg)
546 continue;
547 d = get_win_info(wp, tabnr, winnr);
548 if (d != NULL)
549 list_append_dict(rettv->vval.v_list, d);
550 if (wparg != NULL)
551 // found information about a specific window
552 return;
553 }
554 }
Bram Moolenaar99ca9c42020-09-22 21:55:41 +0200555#ifdef FEAT_PROP_POPUP
556 if (wparg != NULL)
557 {
558 tabnr = 0;
559 FOR_ALL_TABPAGES(tp)
560 {
561 tabnr++;
562 FOR_ALL_POPUPWINS_IN_TAB(tp, wp)
563 if (wp == wparg)
564 break;
565 }
566 d = get_win_info(wparg, tp == NULL ? 0 : tabnr, 0);
567 if (d != NULL)
568 list_append_dict(rettv->vval.v_list, d);
569 }
570#endif
Bram Moolenaar261f3462019-09-07 15:45:32 +0200571}
572
573/*
574 * "getwinpos({timeout})" function
575 */
576 void
577f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv)
578{
579 int x = -1;
580 int y = -1;
581
582 if (rettv_list_alloc(rettv) == FAIL)
583 return;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200584
585 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
586 return;
587
Bram Moolenaar261f3462019-09-07 15:45:32 +0200588#if defined(FEAT_GUI) \
589 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
590 || defined(MSWIN)
591 {
592 varnumber_T timeout = 100;
593
594 if (argvars[0].v_type != VAR_UNKNOWN)
595 timeout = tv_get_number(&argvars[0]);
596
597 (void)ui_get_winpos(&x, &y, timeout);
598 }
599#endif
600 list_append_number(rettv->vval.v_list, (varnumber_T)x);
601 list_append_number(rettv->vval.v_list, (varnumber_T)y);
602}
603
604
605/*
606 * "getwinposx()" function
607 */
608 void
609f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
610{
611 rettv->vval.v_number = -1;
612#if defined(FEAT_GUI) \
613 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
614 || defined(MSWIN)
615
616 {
617 int x, y;
618
619 if (ui_get_winpos(&x, &y, 100) == OK)
620 rettv->vval.v_number = x;
621 }
622#endif
623}
624
625/*
626 * "getwinposy()" function
627 */
628 void
629f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
630{
631 rettv->vval.v_number = -1;
632#if defined(FEAT_GUI) \
633 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
634 || defined(MSWIN)
635 {
636 int x, y;
637
638 if (ui_get_winpos(&x, &y, 100) == OK)
639 rettv->vval.v_number = y;
640 }
641#endif
642}
643
644/*
645 * "tabpagenr()" function
646 */
647 void
648f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
649{
650 int nr = 1;
651 char_u *arg;
652
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200653 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
654 return;
655
Bram Moolenaar261f3462019-09-07 15:45:32 +0200656 if (argvars[0].v_type != VAR_UNKNOWN)
657 {
658 arg = tv_get_string_chk(&argvars[0]);
659 nr = 0;
660 if (arg != NULL)
661 {
662 if (STRCMP(arg, "$") == 0)
663 nr = tabpage_index(NULL) - 1;
Bram Moolenaar62a23252020-08-09 14:04:42 +0200664 else if (STRCMP(arg, "#") == 0)
665 nr = valid_tabpage(lastused_tabpage) ?
666 tabpage_index(lastused_tabpage) : 0;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200667 else
Bram Moolenaar108010a2021-06-27 22:03:33 +0200668 semsg(_(e_invalid_expression_str), arg);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200669 }
670 }
671 else
672 nr = tabpage_index(curtab);
673 rettv->vval.v_number = nr;
674}
675
676/*
677 * "tabpagewinnr()" function
678 */
679 void
680f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv)
681{
682 int nr = 1;
683 tabpage_T *tp;
684
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200685 if (in_vim9script()
686 && (check_for_number_arg(argvars, 0) == FAIL
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200687 || check_for_opt_string_arg(argvars, 1) == FAIL))
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200688 return;
689
Bram Moolenaar261f3462019-09-07 15:45:32 +0200690 tp = find_tabpage((int)tv_get_number(&argvars[0]));
691 if (tp == NULL)
692 nr = 0;
693 else
694 nr = get_winnr(tp, &argvars[1]);
695 rettv->vval.v_number = nr;
696}
697
698/*
699 * "win_execute()" function
700 */
701 void
702f_win_execute(typval_T *argvars, typval_T *rettv)
703{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200704 int id;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200705 tabpage_T *tp;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200706 win_T *wp;
Bram Moolenaar18f47402022-01-06 13:24:51 +0000707 switchwin_T switchwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200708
Bram Moolenaar37487e12021-01-12 22:08:53 +0100709 // Return an empty string if something fails.
710 rettv->v_type = VAR_STRING;
711 rettv->vval.v_string = NULL;
712
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200713 if (in_vim9script()
714 && (check_for_number_arg(argvars, 0) == FAIL
715 || check_for_string_or_list_arg(argvars, 1) == FAIL
716 || check_for_opt_string_arg(argvars, 2) == FAIL))
717 return;
718
719 id = (int)tv_get_number(argvars);
720 wp = win_id2wp_tp(id, &tp);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200721 if (wp != NULL && tp != NULL)
722 {
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200723 pos_T curpos = wp->w_cursor;
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000724 char_u cwd[MAXPATHL];
Bram Moolenaard6f27c62022-01-11 12:37:20 +0000725 int cwd_status = FAIL;
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000726#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000727 char_u autocwd[MAXPATHL];
728 int apply_acd = FALSE;
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000729#endif
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000730
Bram Moolenaard6f27c62022-01-11 12:37:20 +0000731 // Getting and setting directory can be slow on some systems, only do
732 // this when the current or target window/tab have a local directory or
733 // 'acd' is set.
734 if (curwin != wp
735 && (curwin->w_localdir != NULL
736 || wp->w_localdir != NULL
737 || (curtab != tp
738 && (curtab->tp_localdir != NULL
739 || tp->tp_localdir != NULL))
740#ifdef FEAT_AUTOCHDIR
741 || p_acd
742#endif
743 ))
744 cwd_status = mch_dirname(cwd, MAXPATHL);
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000745
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000746#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000747 // If 'acd' is set, check we are using that directory. If yes, then
748 // apply 'acd' afterwards, otherwise restore the current directory.
749 if (cwd_status == OK && p_acd)
750 {
751 do_autochdir();
752 apply_acd = mch_dirname(autocwd, MAXPATHL) == OK
753 && STRCMP(cwd, autocwd) == 0;
754 }
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000755#endif
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200756
Bram Moolenaar18f47402022-01-06 13:24:51 +0000757 if (switch_win_noblock(&switchwin, wp, tp, TRUE) == OK)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200758 {
759 check_cursor();
760 execute_common(argvars, rettv, 1);
761 }
Bram Moolenaar18f47402022-01-06 13:24:51 +0000762 restore_win_noblock(&switchwin, TRUE);
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000763#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000764 if (apply_acd)
765 do_autochdir();
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000766 else
767#endif
768 if (cwd_status == OK)
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000769 mch_chdir((char *)cwd);
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200770
771 // Update the status line if the cursor moved.
772 if (win_valid(wp) && !EQUAL_POS(curpos, wp->w_cursor))
773 wp->w_redr_status = TRUE;
Bram Moolenaare664a322022-01-07 14:08:03 +0000774
775 // In case the command moved the cursor or changed the Visual area,
776 // check it is valid.
777 check_cursor();
778 if (VIsual_active)
779 check_pos(curbuf, &VIsual);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200780 }
781}
782
783/*
784 * "win_findbuf()" function
785 */
786 void
787f_win_findbuf(typval_T *argvars, typval_T *rettv)
788{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200789 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
790 return;
791
Bram Moolenaar93a10962022-06-16 11:42:09 +0100792 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200793 win_findbuf(argvars, rettv->vval.v_list);
794}
795
796/*
797 * "win_getid()" function
798 */
799 void
800f_win_getid(typval_T *argvars, typval_T *rettv)
801{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200802 if (in_vim9script()
803 && (check_for_opt_number_arg(argvars, 0) == FAIL
804 || (argvars[0].v_type != VAR_UNKNOWN
805 && check_for_opt_number_arg(argvars, 1) == FAIL)))
806 return;
807
Bram Moolenaar261f3462019-09-07 15:45:32 +0200808 rettv->vval.v_number = win_getid(argvars);
809}
810
811/*
812 * "win_gotoid()" function
813 */
814 void
815f_win_gotoid(typval_T *argvars, typval_T *rettv)
816{
Bram Moolenaara046b372019-09-15 17:26:07 +0200817 win_T *wp;
818 tabpage_T *tp;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200819 int id;
Bram Moolenaara046b372019-09-15 17:26:07 +0200820
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200821 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
822 return;
823
824 id = tv_get_number(&argvars[0]);
Bram Moolenaara046b372019-09-15 17:26:07 +0200825 if (cmdwin_type != 0)
826 {
Bram Moolenaar108010a2021-06-27 22:03:33 +0200827 emsg(_(e_invalid_in_cmdline_window));
Bram Moolenaara046b372019-09-15 17:26:07 +0200828 return;
829 }
LemonBoy4a392d22022-04-23 14:07:56 +0100830#if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL)
831 if (popup_is_popup(curwin) && curbuf->b_term != NULL)
832 {
833 emsg(_(e_not_allowed_for_terminal_in_popup_window));
834 return;
835 }
836#endif
Bram Moolenaara046b372019-09-15 17:26:07 +0200837 FOR_ALL_TAB_WINDOWS(tp, wp)
838 if (wp->w_id == id)
839 {
Bram Moolenaar3aca0912022-04-18 18:32:19 +0100840 // When jumping to another buffer stop Visual mode.
841 if (VIsual_active && wp->w_buffer != curbuf)
842 end_visual_mode();
Bram Moolenaara046b372019-09-15 17:26:07 +0200843 goto_tabpage_win(tp, wp);
844 rettv->vval.v_number = 1;
845 return;
846 }
Bram Moolenaar261f3462019-09-07 15:45:32 +0200847}
848
849/*
850 * "win_id2tabwin()" function
851 */
852 void
853f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
854{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200855 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
856 return;
857
Bram Moolenaar93a10962022-06-16 11:42:09 +0100858 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200859 win_id2tabwin(argvars, rettv->vval.v_list);
860}
861
862/*
863 * "win_id2win()" function
864 */
865 void
866f_win_id2win(typval_T *argvars, typval_T *rettv)
867{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200868 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
869 return;
870
Bram Moolenaar261f3462019-09-07 15:45:32 +0200871 rettv->vval.v_number = win_id2win(argvars);
872}
873
874/*
Daniel Steinbergee630312022-01-10 13:36:34 +0000875 * "win_move_separator()" function
876 */
877 void
878f_win_move_separator(typval_T *argvars, typval_T *rettv)
879{
880 win_T *wp;
881 int offset;
882
883 rettv->vval.v_number = FALSE;
884
885 if (in_vim9script()
886 && (check_for_number_arg(argvars, 0) == FAIL
887 || check_for_number_arg(argvars, 1) == FAIL))
888 return;
889
890 wp = find_win_by_nr_or_id(&argvars[0]);
891 if (wp == NULL || win_valid_popup(wp))
892 return;
zeertzjq873f41a2022-11-01 11:44:43 +0000893 if (!win_valid(wp))
894 {
895 emsg(_(e_cannot_resize_window_in_another_tab_page));
896 return;
897 }
Daniel Steinbergee630312022-01-10 13:36:34 +0000898
899 offset = (int)tv_get_number(&argvars[1]);
900 win_drag_vsep_line(wp, offset);
901 rettv->vval.v_number = TRUE;
902}
903
904/*
905 * "win_move_statusline()" function
906 */
907 void
908f_win_move_statusline(typval_T *argvars, typval_T *rettv)
909{
910 win_T *wp;
911 int offset;
912
913 rettv->vval.v_number = FALSE;
914
915 if (in_vim9script()
916 && (check_for_number_arg(argvars, 0) == FAIL
917 || check_for_number_arg(argvars, 1) == FAIL))
918 return;
919
920 wp = find_win_by_nr_or_id(&argvars[0]);
921 if (wp == NULL || win_valid_popup(wp))
922 return;
Bram Moolenaar86e67172022-10-31 12:24:12 +0000923 if (!win_valid(wp))
924 {
925 emsg(_(e_cannot_resize_window_in_another_tab_page));
926 return;
927 }
Daniel Steinbergee630312022-01-10 13:36:34 +0000928
929 offset = (int)tv_get_number(&argvars[1]);
930 win_drag_status_line(wp, offset);
931 rettv->vval.v_number = TRUE;
932}
933
934/*
Bram Moolenaar261f3462019-09-07 15:45:32 +0200935 * "win_screenpos()" function
936 */
937 void
938f_win_screenpos(typval_T *argvars, typval_T *rettv)
939{
940 win_T *wp;
941
942 if (rettv_list_alloc(rettv) == FAIL)
943 return;
944
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200945 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
946 return;
947
Bram Moolenaar261f3462019-09-07 15:45:32 +0200948 wp = find_win_by_nr_or_id(&argvars[0]);
949 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1);
950 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1);
951}
952
953/*
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200954 * Move the window wp into a new split of targetwin in a given direction
955 */
956 static void
957win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
958{
959 int dir;
960 int height = wp->w_height;
961 win_T *oldwin = curwin;
962
963 if (wp == targetwin)
964 return;
965
966 // Jump to the target window
967 if (curwin != targetwin)
968 win_goto(targetwin);
969
970 // Remove the old window and frame from the tree of frames
971 (void)winframe_remove(wp, &dir, NULL);
972 win_remove(wp, NULL);
973 last_status(FALSE); // may need to remove last status line
974 (void)win_comp_pos(); // recompute window positions
975
976 // Split a window on the desired side and put the old window there
977 (void)win_split_ins(size, flags, wp, dir);
978
979 // If splitting horizontally, try to preserve height
980 if (size == 0 && !(flags & WSP_VERT))
981 {
982 win_setheight_win(height, wp);
983 if (p_ea)
984 win_equal(wp, TRUE, 'v');
985 }
986
987#if defined(FEAT_GUI)
988 // When 'guioptions' includes 'L' or 'R' may have to remove or add
989 // scrollbars. Have to update them anyway.
990 gui_may_update_scrollbars();
991#endif
992
993 if (oldwin != curwin)
994 win_goto(oldwin);
995}
996
997/*
998 * "win_splitmove()" function
999 */
1000 void
1001f_win_splitmove(typval_T *argvars, typval_T *rettv)
1002{
1003 win_T *wp;
1004 win_T *targetwin;
1005 int flags = 0, size = 0;
1006
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001007 if (in_vim9script()
1008 && (check_for_number_arg(argvars, 0) == FAIL
1009 || check_for_number_arg(argvars, 1) == FAIL
1010 || check_for_opt_dict_arg(argvars, 2) == FAIL))
1011 return;
1012
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001013 wp = find_win_by_nr_or_id(&argvars[0]);
1014 targetwin = find_win_by_nr_or_id(&argvars[1]);
1015
Bram Moolenaar7b94e772020-01-06 21:03:24 +01001016 if (wp == NULL || targetwin == NULL || wp == targetwin
Bram Moolenaar0f1563f2020-03-20 21:15:51 +01001017 || !win_valid(wp) || !win_valid(targetwin)
1018 || win_valid_popup(wp) || win_valid_popup(targetwin))
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001019 {
Bram Moolenaar6ed545e2022-05-09 20:09:23 +01001020 emsg(_(e_invalid_window_number));
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001021 rettv->vval.v_number = -1;
1022 return;
1023 }
1024
1025 if (argvars[2].v_type != VAR_UNKNOWN)
1026 {
Bram Moolenaar6ed545e2022-05-09 20:09:23 +01001027 dict_T *d;
1028 dictitem_T *di;
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001029
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001030 if (check_for_nonnull_dict_arg(argvars, 2) == FAIL)
Bram Moolenaar6ed545e2022-05-09 20:09:23 +01001031 return;
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001032
Bram Moolenaar6ed545e2022-05-09 20:09:23 +01001033 d = argvars[2].vval.v_dict;
Bram Moolenaard61efa52022-07-23 09:52:04 +01001034 if (dict_get_bool(d, "vertical", FALSE))
Bram Moolenaar6ed545e2022-05-09 20:09:23 +01001035 flags |= WSP_VERT;
1036 if ((di = dict_find(d, (char_u *)"rightbelow", -1)) != NULL)
1037 flags |= tv_get_bool(&di->di_tv) ? WSP_BELOW : WSP_ABOVE;
Bram Moolenaard61efa52022-07-23 09:52:04 +01001038 size = (int)dict_get_number(d, "size");
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001039 }
1040
1041 win_move_into_split(wp, targetwin, size, flags);
1042}
1043
1044/*
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001045 * "win_gettype(nr)" function
1046 */
1047 void
1048f_win_gettype(typval_T *argvars, typval_T *rettv)
1049{
1050 win_T *wp = curwin;
1051
1052 rettv->v_type = VAR_STRING;
1053 rettv->vval.v_string = NULL;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001054
1055 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
1056 return;
1057
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001058 if (argvars[0].v_type != VAR_UNKNOWN)
1059 {
1060 wp = find_win_by_nr_or_id(&argvars[0]);
1061 if (wp == NULL)
1062 {
1063 rettv->vval.v_string = vim_strsave((char_u *)"unknown");
1064 return;
1065 }
1066 }
Bram Moolenaare76062c2022-11-28 18:51:43 +00001067 if (is_aucmd_win(wp))
Bram Moolenaar40a019f2020-06-17 21:41:35 +02001068 rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001069#if defined(FEAT_QUICKFIX)
1070 else if (wp->w_p_pvw)
1071 rettv->vval.v_string = vim_strsave((char_u *)"preview");
1072#endif
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001073#ifdef FEAT_PROP_POPUP
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001074 else if (WIN_IS_POPUP(wp))
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001075 rettv->vval.v_string = vim_strsave((char_u *)"popup");
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001076#endif
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001077 else if (wp == curwin && cmdwin_type != 0)
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001078 rettv->vval.v_string = vim_strsave((char_u *)"command");
Yegappan Lakshmanan28d84212021-07-31 12:43:23 +02001079#ifdef FEAT_QUICKFIX
1080 else if (bt_quickfix(wp->w_buffer))
1081 rettv->vval.v_string = vim_strsave((char_u *)
1082 (wp->w_llist_ref != NULL ? "loclist" : "quickfix"));
1083#endif
1084
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001085}
1086
1087/*
1088 * "getcmdwintype()" function
1089 */
1090 void
1091f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv)
1092{
1093 rettv->v_type = VAR_STRING;
1094 rettv->vval.v_string = NULL;
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001095 rettv->vval.v_string = alloc(2);
1096 if (rettv->vval.v_string != NULL)
1097 {
1098 rettv->vval.v_string[0] = cmdwin_type;
1099 rettv->vval.v_string[1] = NUL;
1100 }
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001101}
1102
1103/*
Bram Moolenaar261f3462019-09-07 15:45:32 +02001104 * "winbufnr(nr)" function
1105 */
1106 void
1107f_winbufnr(typval_T *argvars, typval_T *rettv)
1108{
1109 win_T *wp;
1110
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001111 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1112 return;
1113
Bram Moolenaar261f3462019-09-07 15:45:32 +02001114 wp = find_win_by_nr_or_id(&argvars[0]);
1115 if (wp == NULL)
1116 rettv->vval.v_number = -1;
1117 else
1118 rettv->vval.v_number = wp->w_buffer->b_fnum;
1119}
1120
1121/*
1122 * "wincol()" function
1123 */
1124 void
1125f_wincol(typval_T *argvars UNUSED, typval_T *rettv)
1126{
1127 validate_cursor();
1128 rettv->vval.v_number = curwin->w_wcol + 1;
1129}
1130
1131/*
1132 * "winheight(nr)" function
1133 */
1134 void
1135f_winheight(typval_T *argvars, typval_T *rettv)
1136{
1137 win_T *wp;
1138
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001139 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1140 return;
1141
Bram Moolenaar261f3462019-09-07 15:45:32 +02001142 wp = find_win_by_nr_or_id(&argvars[0]);
1143 if (wp == NULL)
1144 rettv->vval.v_number = -1;
1145 else
1146 rettv->vval.v_number = wp->w_height;
1147}
1148
1149/*
1150 * "winlayout()" function
1151 */
1152 void
1153f_winlayout(typval_T *argvars, typval_T *rettv)
1154{
1155 tabpage_T *tp;
1156
Bram Moolenaar93a10962022-06-16 11:42:09 +01001157 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001158 return;
1159
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001160 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
1161 return;
1162
Bram Moolenaar261f3462019-09-07 15:45:32 +02001163 if (argvars[0].v_type == VAR_UNKNOWN)
1164 tp = curtab;
1165 else
1166 {
1167 tp = find_tabpage((int)tv_get_number(&argvars[0]));
1168 if (tp == NULL)
1169 return;
1170 }
1171
1172 get_framelayout(tp->tp_topframe, rettv->vval.v_list, TRUE);
1173}
1174
1175/*
1176 * "winline()" function
1177 */
1178 void
1179f_winline(typval_T *argvars UNUSED, typval_T *rettv)
1180{
1181 validate_cursor();
1182 rettv->vval.v_number = curwin->w_wrow + 1;
1183}
1184
1185/*
1186 * "winnr()" function
1187 */
1188 void
1189f_winnr(typval_T *argvars UNUSED, typval_T *rettv)
1190{
1191 int nr = 1;
1192
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001193 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
1194 return;
1195
Bram Moolenaar261f3462019-09-07 15:45:32 +02001196 nr = get_winnr(curtab, &argvars[0]);
1197 rettv->vval.v_number = nr;
1198}
1199
1200/*
1201 * "winrestcmd()" function
1202 */
1203 void
1204f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv)
1205{
1206 win_T *wp;
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001207 int i;
1208 int winnr;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001209 garray_T ga;
1210 char_u buf[50];
1211
Bram Moolenaar04935fb2022-01-08 16:19:22 +00001212 ga_init2(&ga, sizeof(char), 70);
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001213
1214 // Do this twice to handle some window layouts properly.
1215 for (i = 0; i < 2; ++i)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001216 {
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001217 winnr = 1;
1218 FOR_ALL_WINDOWS(wp)
1219 {
1220 sprintf((char *)buf, ":%dresize %d|", winnr, wp->w_height);
1221 ga_concat(&ga, buf);
1222 sprintf((char *)buf, "vert :%dresize %d|", winnr, wp->w_width);
1223 ga_concat(&ga, buf);
1224 ++winnr;
1225 }
Bram Moolenaar261f3462019-09-07 15:45:32 +02001226 }
1227 ga_append(&ga, NUL);
1228
1229 rettv->vval.v_string = ga.ga_data;
1230 rettv->v_type = VAR_STRING;
1231}
1232
1233/*
1234 * "winrestview()" function
1235 */
1236 void
1237f_winrestview(typval_T *argvars, typval_T *rettv UNUSED)
1238{
1239 dict_T *dict;
1240
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001241 if (check_for_nonnull_dict_arg(argvars, 0) == FAIL)
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001242 return;
1243
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001244 dict = argvars[0].vval.v_dict;
1245 if (dict_has_key(dict, "lnum"))
1246 curwin->w_cursor.lnum = (linenr_T)dict_get_number(dict, "lnum");
1247 if (dict_has_key(dict, "col"))
1248 curwin->w_cursor.col = (colnr_T)dict_get_number(dict, "col");
1249 if (dict_has_key(dict, "coladd"))
1250 curwin->w_cursor.coladd = (colnr_T)dict_get_number(dict, "coladd");
1251 if (dict_has_key(dict, "curswant"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001252 {
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001253 curwin->w_curswant = (colnr_T)dict_get_number(dict, "curswant");
1254 curwin->w_set_curswant = FALSE;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001255 }
Yegappan Lakshmanan04c4c572022-08-30 19:48:24 +01001256
1257 if (dict_has_key(dict, "topline"))
1258 set_topline(curwin, (linenr_T)dict_get_number(dict, "topline"));
1259#ifdef FEAT_DIFF
1260 if (dict_has_key(dict, "topfill"))
1261 curwin->w_topfill = (int)dict_get_number(dict, "topfill");
1262#endif
1263 if (dict_has_key(dict, "leftcol"))
1264 curwin->w_leftcol = (colnr_T)dict_get_number(dict, "leftcol");
1265 if (dict_has_key(dict, "skipcol"))
1266 curwin->w_skipcol = (colnr_T)dict_get_number(dict, "skipcol");
1267
1268 check_cursor();
1269 win_new_height(curwin, curwin->w_height);
1270 win_new_width(curwin, curwin->w_width);
1271 changed_window_setting();
1272
1273 if (curwin->w_topline <= 0)
1274 curwin->w_topline = 1;
1275 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
1276 curwin->w_topline = curbuf->b_ml.ml_line_count;
1277#ifdef FEAT_DIFF
1278 check_topfill(curwin, TRUE);
1279#endif
Bram Moolenaar261f3462019-09-07 15:45:32 +02001280}
1281
1282/*
1283 * "winsaveview()" function
1284 */
1285 void
1286f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv)
1287{
1288 dict_T *dict;
1289
1290 if (rettv_dict_alloc(rettv) == FAIL)
1291 return;
1292 dict = rettv->vval.v_dict;
1293
1294 dict_add_number(dict, "lnum", (long)curwin->w_cursor.lnum);
1295 dict_add_number(dict, "col", (long)curwin->w_cursor.col);
1296 dict_add_number(dict, "coladd", (long)curwin->w_cursor.coladd);
1297 update_curswant();
1298 dict_add_number(dict, "curswant", (long)curwin->w_curswant);
1299
1300 dict_add_number(dict, "topline", (long)curwin->w_topline);
1301#ifdef FEAT_DIFF
1302 dict_add_number(dict, "topfill", (long)curwin->w_topfill);
1303#endif
1304 dict_add_number(dict, "leftcol", (long)curwin->w_leftcol);
1305 dict_add_number(dict, "skipcol", (long)curwin->w_skipcol);
1306}
1307
1308/*
1309 * "winwidth(nr)" function
1310 */
1311 void
1312f_winwidth(typval_T *argvars, typval_T *rettv)
1313{
1314 win_T *wp;
1315
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001316 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1317 return;
1318
Bram Moolenaar261f3462019-09-07 15:45:32 +02001319 wp = find_win_by_nr_or_id(&argvars[0]);
1320 if (wp == NULL)
1321 rettv->vval.v_number = -1;
1322 else
1323 rettv->vval.v_number = wp->w_width;
1324}
1325#endif // FEAT_EVAL
1326
1327#if defined(FEAT_EVAL) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
1328 || defined(PROTO)
1329/*
1330 * Set "win" to be the curwin and "tp" to be the current tab page.
1331 * restore_win() MUST be called to undo, also when FAIL is returned.
1332 * No autocommands will be executed until restore_win() is called.
1333 * When "no_display" is TRUE the display won't be affected, no redraw is
1334 * triggered, another tabpage access is limited.
1335 * Returns FAIL if switching to "win" failed.
1336 */
1337 int
1338switch_win(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001339 switchwin_T *switchwin,
1340 win_T *win,
1341 tabpage_T *tp,
1342 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001343{
1344 block_autocmds();
Bram Moolenaar18f47402022-01-06 13:24:51 +00001345 return switch_win_noblock(switchwin, win, tp, no_display);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001346}
1347
1348/*
1349 * As switch_win() but without blocking autocommands.
1350 */
1351 int
1352switch_win_noblock(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001353 switchwin_T *switchwin,
1354 win_T *win,
1355 tabpage_T *tp,
1356 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001357{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001358 CLEAR_POINTER(switchwin);
1359 switchwin->sw_curwin = curwin;
1360 if (win == curwin)
1361 switchwin->sw_same_win = TRUE;
1362 else
1363 {
1364 // Disable Visual selection, because redrawing may fail.
1365 switchwin->sw_visual_active = VIsual_active;
1366 VIsual_active = FALSE;
1367 }
1368
Bram Moolenaar261f3462019-09-07 15:45:32 +02001369 if (tp != NULL)
1370 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00001371 switchwin->sw_curtab = curtab;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001372 if (no_display)
1373 {
1374 curtab->tp_firstwin = firstwin;
1375 curtab->tp_lastwin = lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001376 curtab->tp_topframe = topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001377 curtab = tp;
1378 firstwin = curtab->tp_firstwin;
1379 lastwin = curtab->tp_lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001380 topframe = curtab->tp_topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001381 }
1382 else
1383 goto_tabpage_tp(tp, FALSE, FALSE);
1384 }
1385 if (!win_valid(win))
1386 return FAIL;
1387 curwin = win;
1388 curbuf = curwin->w_buffer;
1389 return OK;
1390}
1391
1392/*
1393 * Restore current tabpage and window saved by switch_win(), if still valid.
1394 * When "no_display" is TRUE the display won't be affected, no redraw is
1395 * triggered.
1396 */
1397 void
1398restore_win(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001399 switchwin_T *switchwin,
1400 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001401{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001402 restore_win_noblock(switchwin, no_display);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001403 unblock_autocmds();
1404}
1405
1406/*
1407 * As restore_win() but without unblocking autocommands.
1408 */
1409 void
1410restore_win_noblock(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001411 switchwin_T *switchwin,
1412 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001413{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001414 if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001415 {
1416 if (no_display)
1417 {
1418 curtab->tp_firstwin = firstwin;
1419 curtab->tp_lastwin = lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001420 curtab->tp_topframe = topframe;
Bram Moolenaar18f47402022-01-06 13:24:51 +00001421 curtab = switchwin->sw_curtab;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001422 firstwin = curtab->tp_firstwin;
1423 lastwin = curtab->tp_lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001424 topframe = curtab->tp_topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001425 }
1426 else
Bram Moolenaar18f47402022-01-06 13:24:51 +00001427 goto_tabpage_tp(switchwin->sw_curtab, FALSE, FALSE);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001428 }
Bram Moolenaar18f47402022-01-06 13:24:51 +00001429
1430 if (!switchwin->sw_same_win)
1431 VIsual_active = switchwin->sw_visual_active;
1432
1433 if (win_valid(switchwin->sw_curwin))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001434 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00001435 curwin = switchwin->sw_curwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001436 curbuf = curwin->w_buffer;
1437 }
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01001438# ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +02001439 else if (WIN_IS_POPUP(curwin))
1440 // original window was closed and now we're in a popup window: Go
1441 // to the first valid window.
1442 win_goto(firstwin);
1443# endif
Bram Moolenaar261f3462019-09-07 15:45:32 +02001444}
1445#endif