blob: d29f3e4baa3fafdf0bb50ef8358c5f958e4d3ab7 [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".
92 */
93 win_T *
94win_id2wp_tp(int id, tabpage_T **tpp)
95{
96 win_T *wp;
97 tabpage_T *tp;
98
99 FOR_ALL_TAB_WINDOWS(tp, wp)
100 if (wp->w_id == id)
101 {
102 if (tpp != NULL)
103 *tpp = tp;
104 return wp;
105 }
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100106#ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +0200107 // popup windows are in separate lists
108 FOR_ALL_TABPAGES(tp)
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200109 FOR_ALL_POPUPWINS_IN_TAB(tp, wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200110 if (wp->w_id == id)
111 {
112 if (tpp != NULL)
113 *tpp = tp;
114 return wp;
115 }
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200116 FOR_ALL_POPUPWINS(wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200117 if (wp->w_id == id)
118 {
119 if (tpp != NULL)
Bram Moolenaar1f42f5a2020-09-03 18:52:24 +0200120 *tpp = curtab; // any tabpage would do
Bram Moolenaar261f3462019-09-07 15:45:32 +0200121 return wp;
122 }
123#endif
124
125 return NULL;
126}
127
128 static int
129win_id2win(typval_T *argvars)
130{
131 win_T *wp;
132 int nr = 1;
133 int id = tv_get_number(&argvars[0]);
134
135 FOR_ALL_WINDOWS(wp)
136 {
137 if (wp->w_id == id)
138 return nr;
139 ++nr;
140 }
141 return 0;
142}
143
144 void
145win_findbuf(typval_T *argvars, list_T *list)
146{
147 win_T *wp;
148 tabpage_T *tp;
149 int bufnr = tv_get_number(&argvars[0]);
150
151 FOR_ALL_TAB_WINDOWS(tp, wp)
152 if (wp->w_buffer->b_fnum == bufnr)
153 list_append_number(list, wp->w_id);
154}
155
156/*
157 * Find window specified by "vp" in tabpage "tp".
158 */
159 win_T *
160find_win_by_nr(
161 typval_T *vp,
162 tabpage_T *tp) // NULL for current tab page
163{
164 win_T *wp;
165 int nr = (int)tv_get_number_chk(vp, NULL);
166
167 if (nr < 0)
168 return NULL;
169 if (nr == 0)
170 return curwin;
171
172 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
173 {
174 if (nr >= LOWEST_WIN_ID)
175 {
176 if (wp->w_id == nr)
177 return wp;
178 }
179 else if (--nr <= 0)
180 break;
181 }
182 if (nr >= LOWEST_WIN_ID)
183 {
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100184#ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +0200185 // check tab-local popup windows
Bram Moolenaaree93b732020-01-14 19:05:39 +0100186 for (wp = (tp == NULL ? curtab : tp)->tp_first_popupwin;
187 wp != NULL; wp = wp->w_next)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200188 if (wp->w_id == nr)
189 return wp;
190 // check global popup windows
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200191 FOR_ALL_POPUPWINS(wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200192 if (wp->w_id == nr)
193 return wp;
194#endif
195 return NULL;
196 }
197 return wp;
198}
199
200/*
201 * Find a window: When using a Window ID in any tab page, when using a number
202 * in the current tab page.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100203 * Returns NULL when not found.
Bram Moolenaar261f3462019-09-07 15:45:32 +0200204 */
205 win_T *
206find_win_by_nr_or_id(typval_T *vp)
207{
208 int nr = (int)tv_get_number_chk(vp, NULL);
209
210 if (nr >= LOWEST_WIN_ID)
211 return win_id2wp(tv_get_number(vp));
212 return find_win_by_nr(vp, NULL);
213}
214
215/*
216 * Find window specified by "wvp" in tabpage "tvp".
217 * Returns the tab page in 'ptp'
218 */
219 win_T *
220find_tabwin(
221 typval_T *wvp, // VAR_UNKNOWN for current window
222 typval_T *tvp, // VAR_UNKNOWN for current tab page
223 tabpage_T **ptp)
224{
225 win_T *wp = NULL;
226 tabpage_T *tp = NULL;
227 long n;
228
229 if (wvp->v_type != VAR_UNKNOWN)
230 {
231 if (tvp->v_type != VAR_UNKNOWN)
232 {
233 n = (long)tv_get_number(tvp);
234 if (n >= 0)
235 tp = find_tabpage(n);
236 }
237 else
238 tp = curtab;
239
240 if (tp != NULL)
241 {
242 wp = find_win_by_nr(wvp, tp);
243 if (wp == NULL && wvp->v_type == VAR_NUMBER
244 && wvp->vval.v_number != -1)
245 // A window with the specified number is not found
246 tp = NULL;
247 }
248 }
249 else
250 {
251 wp = curwin;
252 tp = curtab;
253 }
254
255 if (ptp != NULL)
256 *ptp = tp;
257
258 return wp;
259}
260
261/*
262 * Get the layout of the given tab page for winlayout().
263 */
264 static void
265get_framelayout(frame_T *fr, list_T *l, int outer)
266{
267 frame_T *child;
268 list_T *fr_list;
269 list_T *win_list;
270
271 if (fr == NULL)
272 return;
273
274 if (outer)
275 // outermost call from f_winlayout()
276 fr_list = l;
277 else
278 {
279 fr_list = list_alloc();
280 if (fr_list == NULL)
281 return;
282 list_append_list(l, fr_list);
283 }
284
285 if (fr->fr_layout == FR_LEAF)
286 {
287 if (fr->fr_win != NULL)
288 {
289 list_append_string(fr_list, (char_u *)"leaf", -1);
290 list_append_number(fr_list, fr->fr_win->w_id);
291 }
292 }
293 else
294 {
295 list_append_string(fr_list,
296 fr->fr_layout == FR_ROW ? (char_u *)"row" : (char_u *)"col", -1);
297
298 win_list = list_alloc();
299 if (win_list == NULL)
300 return;
301 list_append_list(fr_list, win_list);
302 child = fr->fr_child;
303 while (child != NULL)
304 {
305 get_framelayout(child, win_list, FALSE);
306 child = child->fr_next;
307 }
308 }
309}
310
311/*
312 * Common code for tabpagewinnr() and winnr().
313 */
314 static int
315get_winnr(tabpage_T *tp, typval_T *argvar)
316{
317 win_T *twin;
318 int nr = 1;
319 win_T *wp;
320 char_u *arg;
321
322 twin = (tp == curtab) ? curwin : tp->tp_curwin;
323 if (argvar->v_type != VAR_UNKNOWN)
324 {
325 int invalid_arg = FALSE;
326
327 arg = tv_get_string_chk(argvar);
328 if (arg == NULL)
329 nr = 0; // type error; errmsg already given
330 else if (STRCMP(arg, "$") == 0)
331 twin = (tp == curtab) ? lastwin : tp->tp_lastwin;
332 else if (STRCMP(arg, "#") == 0)
333 {
334 twin = (tp == curtab) ? prevwin : tp->tp_prevwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200335 }
336 else
337 {
338 long count;
339 char_u *endp;
340
341 // Extract the window count (if specified). e.g. winnr('3j')
342 count = strtol((char *)arg, (char **)&endp, 10);
343 if (count <= 0)
344 count = 1; // if count is not specified, default to 1
345 if (endp != NULL && *endp != '\0')
346 {
347 if (STRCMP(endp, "j") == 0)
348 twin = win_vert_neighbor(tp, twin, FALSE, count);
349 else if (STRCMP(endp, "k") == 0)
350 twin = win_vert_neighbor(tp, twin, TRUE, count);
351 else if (STRCMP(endp, "h") == 0)
352 twin = win_horz_neighbor(tp, twin, TRUE, count);
353 else if (STRCMP(endp, "l") == 0)
354 twin = win_horz_neighbor(tp, twin, FALSE, count);
355 else
356 invalid_arg = TRUE;
357 }
358 else
359 invalid_arg = TRUE;
360 }
Bram Moolenaar631ebc42020-02-03 22:15:26 +0100361 if (twin == NULL)
362 nr = 0;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200363
364 if (invalid_arg)
365 {
Bram Moolenaar108010a2021-06-27 22:03:33 +0200366 semsg(_(e_invalid_expression_str), arg);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200367 nr = 0;
368 }
369 }
370
371 if (nr > 0)
372 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
373 wp != twin; wp = wp->w_next)
374 {
375 if (wp == NULL)
376 {
377 // didn't find it in this tabpage
378 nr = 0;
379 break;
380 }
381 ++nr;
382 }
383 return nr;
384}
385
386/*
387 * Returns information about a window as a dictionary.
388 */
389 static dict_T *
390get_win_info(win_T *wp, short tpnr, short winnr)
391{
392 dict_T *dict;
393
394 dict = dict_alloc();
395 if (dict == NULL)
396 return NULL;
397
398 dict_add_number(dict, "tabnr", tpnr);
399 dict_add_number(dict, "winnr", winnr);
400 dict_add_number(dict, "winid", wp->w_id);
401 dict_add_number(dict, "height", wp->w_height);
402 dict_add_number(dict, "winrow", wp->w_winrow + 1);
403 dict_add_number(dict, "topline", wp->w_topline);
404 dict_add_number(dict, "botline", wp->w_botline - 1);
405#ifdef FEAT_MENU
406 dict_add_number(dict, "winbar", wp->w_winbar_height);
407#endif
408 dict_add_number(dict, "width", wp->w_width);
409 dict_add_number(dict, "wincol", wp->w_wincol + 1);
Bram Moolenaarcdf5fdb2021-11-20 11:14:24 +0000410 dict_add_number(dict, "textoff", win_col_off(wp));
Bram Moolenaar261f3462019-09-07 15:45:32 +0200411 dict_add_number(dict, "bufnr", wp->w_buffer->b_fnum);
412
413#ifdef FEAT_TERMINAL
414 dict_add_number(dict, "terminal", bt_terminal(wp->w_buffer));
415#endif
416#ifdef FEAT_QUICKFIX
417 dict_add_number(dict, "quickfix", bt_quickfix(wp->w_buffer));
418 dict_add_number(dict, "loclist",
419 (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL));
420#endif
421
422 // Add a reference to window variables
423 dict_add_dict(dict, "variables", wp->w_vars);
424
425 return dict;
426}
427
428/*
429 * Returns information (variables, options, etc.) about a tab page
430 * as a dictionary.
431 */
432 static dict_T *
433get_tabpage_info(tabpage_T *tp, int tp_idx)
434{
435 win_T *wp;
436 dict_T *dict;
437 list_T *l;
438
439 dict = dict_alloc();
440 if (dict == NULL)
441 return NULL;
442
443 dict_add_number(dict, "tabnr", tp_idx);
444
445 l = list_alloc();
446 if (l != NULL)
447 {
Bram Moolenaar00d253e2020-04-06 22:13:01 +0200448 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200449 list_append_number(l, (varnumber_T)wp->w_id);
450 dict_add_list(dict, "windows", l);
451 }
452
453 // Make a reference to tabpage variables
454 dict_add_dict(dict, "variables", tp->tp_vars);
455
456 return dict;
457}
458
459/*
460 * "gettabinfo()" function
461 */
462 void
463f_gettabinfo(typval_T *argvars, typval_T *rettv)
464{
465 tabpage_T *tp, *tparg = NULL;
466 dict_T *d;
467 int tpnr = 0;
468
469 if (rettv_list_alloc(rettv) != OK)
470 return;
471
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200472 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
473 return;
474
Bram Moolenaar261f3462019-09-07 15:45:32 +0200475 if (argvars[0].v_type != VAR_UNKNOWN)
476 {
477 // Information about one tab page
478 tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
479 if (tparg == NULL)
480 return;
481 }
482
483 // Get information about a specific tab page or all tab pages
484 FOR_ALL_TABPAGES(tp)
485 {
486 tpnr++;
487 if (tparg != NULL && tp != tparg)
488 continue;
489 d = get_tabpage_info(tp, tpnr);
490 if (d != NULL)
491 list_append_dict(rettv->vval.v_list, d);
492 if (tparg != NULL)
493 return;
494 }
495}
496
497/*
498 * "getwininfo()" function
499 */
500 void
501f_getwininfo(typval_T *argvars, typval_T *rettv)
502{
503 tabpage_T *tp;
504 win_T *wp = NULL, *wparg = NULL;
505 dict_T *d;
506 short tabnr = 0, winnr;
507
508 if (rettv_list_alloc(rettv) != OK)
509 return;
510
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200511 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
512 return;
513
Bram Moolenaar261f3462019-09-07 15:45:32 +0200514 if (argvars[0].v_type != VAR_UNKNOWN)
515 {
516 wparg = win_id2wp(tv_get_number(&argvars[0]));
517 if (wparg == NULL)
518 return;
519 }
520
521 // Collect information about either all the windows across all the tab
522 // pages or one particular window.
523 FOR_ALL_TABPAGES(tp)
524 {
525 tabnr++;
526 winnr = 0;
527 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
528 {
529 winnr++;
530 if (wparg != NULL && wp != wparg)
531 continue;
532 d = get_win_info(wp, tabnr, winnr);
533 if (d != NULL)
534 list_append_dict(rettv->vval.v_list, d);
535 if (wparg != NULL)
536 // found information about a specific window
537 return;
538 }
539 }
Bram Moolenaar99ca9c42020-09-22 21:55:41 +0200540#ifdef FEAT_PROP_POPUP
541 if (wparg != NULL)
542 {
543 tabnr = 0;
544 FOR_ALL_TABPAGES(tp)
545 {
546 tabnr++;
547 FOR_ALL_POPUPWINS_IN_TAB(tp, wp)
548 if (wp == wparg)
549 break;
550 }
551 d = get_win_info(wparg, tp == NULL ? 0 : tabnr, 0);
552 if (d != NULL)
553 list_append_dict(rettv->vval.v_list, d);
554 }
555#endif
Bram Moolenaar261f3462019-09-07 15:45:32 +0200556}
557
558/*
559 * "getwinpos({timeout})" function
560 */
561 void
562f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv)
563{
564 int x = -1;
565 int y = -1;
566
567 if (rettv_list_alloc(rettv) == FAIL)
568 return;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200569
570 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
571 return;
572
Bram Moolenaar261f3462019-09-07 15:45:32 +0200573#if defined(FEAT_GUI) \
574 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
575 || defined(MSWIN)
576 {
577 varnumber_T timeout = 100;
578
579 if (argvars[0].v_type != VAR_UNKNOWN)
580 timeout = tv_get_number(&argvars[0]);
581
582 (void)ui_get_winpos(&x, &y, timeout);
583 }
584#endif
585 list_append_number(rettv->vval.v_list, (varnumber_T)x);
586 list_append_number(rettv->vval.v_list, (varnumber_T)y);
587}
588
589
590/*
591 * "getwinposx()" function
592 */
593 void
594f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
595{
596 rettv->vval.v_number = -1;
597#if defined(FEAT_GUI) \
598 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
599 || defined(MSWIN)
600
601 {
602 int x, y;
603
604 if (ui_get_winpos(&x, &y, 100) == OK)
605 rettv->vval.v_number = x;
606 }
607#endif
608}
609
610/*
611 * "getwinposy()" function
612 */
613 void
614f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
615{
616 rettv->vval.v_number = -1;
617#if defined(FEAT_GUI) \
618 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
619 || defined(MSWIN)
620 {
621 int x, y;
622
623 if (ui_get_winpos(&x, &y, 100) == OK)
624 rettv->vval.v_number = y;
625 }
626#endif
627}
628
629/*
630 * "tabpagenr()" function
631 */
632 void
633f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
634{
635 int nr = 1;
636 char_u *arg;
637
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200638 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
639 return;
640
Bram Moolenaar261f3462019-09-07 15:45:32 +0200641 if (argvars[0].v_type != VAR_UNKNOWN)
642 {
643 arg = tv_get_string_chk(&argvars[0]);
644 nr = 0;
645 if (arg != NULL)
646 {
647 if (STRCMP(arg, "$") == 0)
648 nr = tabpage_index(NULL) - 1;
Bram Moolenaar62a23252020-08-09 14:04:42 +0200649 else if (STRCMP(arg, "#") == 0)
650 nr = valid_tabpage(lastused_tabpage) ?
651 tabpage_index(lastused_tabpage) : 0;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200652 else
Bram Moolenaar108010a2021-06-27 22:03:33 +0200653 semsg(_(e_invalid_expression_str), arg);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200654 }
655 }
656 else
657 nr = tabpage_index(curtab);
658 rettv->vval.v_number = nr;
659}
660
661/*
662 * "tabpagewinnr()" function
663 */
664 void
665f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv)
666{
667 int nr = 1;
668 tabpage_T *tp;
669
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200670 if (in_vim9script()
671 && (check_for_number_arg(argvars, 0) == FAIL
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200672 || check_for_opt_string_arg(argvars, 1) == FAIL))
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200673 return;
674
Bram Moolenaar261f3462019-09-07 15:45:32 +0200675 tp = find_tabpage((int)tv_get_number(&argvars[0]));
676 if (tp == NULL)
677 nr = 0;
678 else
679 nr = get_winnr(tp, &argvars[1]);
680 rettv->vval.v_number = nr;
681}
682
683/*
684 * "win_execute()" function
685 */
686 void
687f_win_execute(typval_T *argvars, typval_T *rettv)
688{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200689 int id;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200690 tabpage_T *tp;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200691 win_T *wp;
Bram Moolenaar18f47402022-01-06 13:24:51 +0000692 switchwin_T switchwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200693
Bram Moolenaar37487e12021-01-12 22:08:53 +0100694 // Return an empty string if something fails.
695 rettv->v_type = VAR_STRING;
696 rettv->vval.v_string = NULL;
697
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200698 if (in_vim9script()
699 && (check_for_number_arg(argvars, 0) == FAIL
700 || check_for_string_or_list_arg(argvars, 1) == FAIL
701 || check_for_opt_string_arg(argvars, 2) == FAIL))
702 return;
703
704 id = (int)tv_get_number(argvars);
705 wp = win_id2wp_tp(id, &tp);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200706 if (wp != NULL && tp != NULL)
707 {
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200708 pos_T curpos = wp->w_cursor;
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000709 char_u cwd[MAXPATHL];
710 int cwd_status;
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000711#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000712 char_u autocwd[MAXPATHL];
713 int apply_acd = FALSE;
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000714#endif
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000715
716 cwd_status = mch_dirname(cwd, MAXPATHL);
717
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000718#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000719 // If 'acd' is set, check we are using that directory. If yes, then
720 // apply 'acd' afterwards, otherwise restore the current directory.
721 if (cwd_status == OK && p_acd)
722 {
723 do_autochdir();
724 apply_acd = mch_dirname(autocwd, MAXPATHL) == OK
725 && STRCMP(cwd, autocwd) == 0;
726 }
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000727#endif
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200728
Bram Moolenaar18f47402022-01-06 13:24:51 +0000729 if (switch_win_noblock(&switchwin, wp, tp, TRUE) == OK)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200730 {
731 check_cursor();
732 execute_common(argvars, rettv, 1);
733 }
Bram Moolenaar18f47402022-01-06 13:24:51 +0000734 restore_win_noblock(&switchwin, TRUE);
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000735#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000736 if (apply_acd)
737 do_autochdir();
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000738 else
739#endif
740 if (cwd_status == OK)
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000741 mch_chdir((char *)cwd);
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200742
743 // Update the status line if the cursor moved.
744 if (win_valid(wp) && !EQUAL_POS(curpos, wp->w_cursor))
745 wp->w_redr_status = TRUE;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200746 }
747}
748
749/*
750 * "win_findbuf()" function
751 */
752 void
753f_win_findbuf(typval_T *argvars, typval_T *rettv)
754{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200755 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
756 return;
757
Bram Moolenaar261f3462019-09-07 15:45:32 +0200758 if (rettv_list_alloc(rettv) != FAIL)
759 win_findbuf(argvars, rettv->vval.v_list);
760}
761
762/*
763 * "win_getid()" function
764 */
765 void
766f_win_getid(typval_T *argvars, typval_T *rettv)
767{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200768 if (in_vim9script()
769 && (check_for_opt_number_arg(argvars, 0) == FAIL
770 || (argvars[0].v_type != VAR_UNKNOWN
771 && check_for_opt_number_arg(argvars, 1) == FAIL)))
772 return;
773
Bram Moolenaar261f3462019-09-07 15:45:32 +0200774 rettv->vval.v_number = win_getid(argvars);
775}
776
777/*
778 * "win_gotoid()" function
779 */
780 void
781f_win_gotoid(typval_T *argvars, typval_T *rettv)
782{
Bram Moolenaara046b372019-09-15 17:26:07 +0200783 win_T *wp;
784 tabpage_T *tp;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200785 int id;
Bram Moolenaara046b372019-09-15 17:26:07 +0200786
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200787 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
788 return;
789
790 id = tv_get_number(&argvars[0]);
Bram Moolenaara046b372019-09-15 17:26:07 +0200791#ifdef FEAT_CMDWIN
792 if (cmdwin_type != 0)
793 {
Bram Moolenaar108010a2021-06-27 22:03:33 +0200794 emsg(_(e_invalid_in_cmdline_window));
Bram Moolenaara046b372019-09-15 17:26:07 +0200795 return;
796 }
797#endif
798 FOR_ALL_TAB_WINDOWS(tp, wp)
799 if (wp->w_id == id)
800 {
801 goto_tabpage_win(tp, wp);
802 rettv->vval.v_number = 1;
803 return;
804 }
Bram Moolenaar261f3462019-09-07 15:45:32 +0200805}
806
807/*
808 * "win_id2tabwin()" function
809 */
810 void
811f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
812{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200813 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
814 return;
815
Bram Moolenaar261f3462019-09-07 15:45:32 +0200816 if (rettv_list_alloc(rettv) != FAIL)
817 win_id2tabwin(argvars, rettv->vval.v_list);
818}
819
820/*
821 * "win_id2win()" function
822 */
823 void
824f_win_id2win(typval_T *argvars, typval_T *rettv)
825{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200826 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
827 return;
828
Bram Moolenaar261f3462019-09-07 15:45:32 +0200829 rettv->vval.v_number = win_id2win(argvars);
830}
831
832/*
833 * "win_screenpos()" function
834 */
835 void
836f_win_screenpos(typval_T *argvars, typval_T *rettv)
837{
838 win_T *wp;
839
840 if (rettv_list_alloc(rettv) == FAIL)
841 return;
842
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200843 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
844 return;
845
Bram Moolenaar261f3462019-09-07 15:45:32 +0200846 wp = find_win_by_nr_or_id(&argvars[0]);
847 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1);
848 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1);
849}
850
851/*
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200852 * Move the window wp into a new split of targetwin in a given direction
853 */
854 static void
855win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
856{
857 int dir;
858 int height = wp->w_height;
859 win_T *oldwin = curwin;
860
861 if (wp == targetwin)
862 return;
863
864 // Jump to the target window
865 if (curwin != targetwin)
866 win_goto(targetwin);
867
868 // Remove the old window and frame from the tree of frames
869 (void)winframe_remove(wp, &dir, NULL);
870 win_remove(wp, NULL);
871 last_status(FALSE); // may need to remove last status line
872 (void)win_comp_pos(); // recompute window positions
873
874 // Split a window on the desired side and put the old window there
875 (void)win_split_ins(size, flags, wp, dir);
876
877 // If splitting horizontally, try to preserve height
878 if (size == 0 && !(flags & WSP_VERT))
879 {
880 win_setheight_win(height, wp);
881 if (p_ea)
882 win_equal(wp, TRUE, 'v');
883 }
884
885#if defined(FEAT_GUI)
886 // When 'guioptions' includes 'L' or 'R' may have to remove or add
887 // scrollbars. Have to update them anyway.
888 gui_may_update_scrollbars();
889#endif
890
891 if (oldwin != curwin)
892 win_goto(oldwin);
893}
894
895/*
896 * "win_splitmove()" function
897 */
898 void
899f_win_splitmove(typval_T *argvars, typval_T *rettv)
900{
901 win_T *wp;
902 win_T *targetwin;
903 int flags = 0, size = 0;
904
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200905 if (in_vim9script()
906 && (check_for_number_arg(argvars, 0) == FAIL
907 || check_for_number_arg(argvars, 1) == FAIL
908 || check_for_opt_dict_arg(argvars, 2) == FAIL))
909 return;
910
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200911 wp = find_win_by_nr_or_id(&argvars[0]);
912 targetwin = find_win_by_nr_or_id(&argvars[1]);
913
Bram Moolenaar7b94e772020-01-06 21:03:24 +0100914 if (wp == NULL || targetwin == NULL || wp == targetwin
Bram Moolenaar0f1563f2020-03-20 21:15:51 +0100915 || !win_valid(wp) || !win_valid(targetwin)
916 || win_valid_popup(wp) || win_valid_popup(targetwin))
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200917 {
Bram Moolenaar3a846e62022-01-01 16:21:00 +0000918 emsg(_(e_invalid_window_number));
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200919 rettv->vval.v_number = -1;
920 return;
921 }
922
923 if (argvars[2].v_type != VAR_UNKNOWN)
924 {
925 dict_T *d;
926 dictitem_T *di;
927
928 if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL)
929 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +0000930 emsg(_(e_invalid_argument));
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200931 return;
932 }
933
934 d = argvars[2].vval.v_dict;
Bram Moolenaar4b9bd692020-09-05 21:57:53 +0200935 if (dict_get_bool(d, (char_u *)"vertical", FALSE))
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200936 flags |= WSP_VERT;
937 if ((di = dict_find(d, (char_u *)"rightbelow", -1)) != NULL)
Bram Moolenaar4b9bd692020-09-05 21:57:53 +0200938 flags |= tv_get_bool(&di->di_tv) ? WSP_BELOW : WSP_ABOVE;
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200939 size = (int)dict_get_number(d, (char_u *)"size");
940 }
941
942 win_move_into_split(wp, targetwin, size, flags);
943}
944
945/*
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +0100946 * "win_gettype(nr)" function
947 */
948 void
949f_win_gettype(typval_T *argvars, typval_T *rettv)
950{
951 win_T *wp = curwin;
952
953 rettv->v_type = VAR_STRING;
954 rettv->vval.v_string = NULL;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200955
956 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
957 return;
958
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +0100959 if (argvars[0].v_type != VAR_UNKNOWN)
960 {
961 wp = find_win_by_nr_or_id(&argvars[0]);
962 if (wp == NULL)
963 {
964 rettv->vval.v_string = vim_strsave((char_u *)"unknown");
965 return;
966 }
967 }
Bram Moolenaar0fe937f2020-06-16 22:42:04 +0200968 if (wp == aucmd_win)
Bram Moolenaar40a019f2020-06-17 21:41:35 +0200969 rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
Bram Moolenaar0fe937f2020-06-16 22:42:04 +0200970#if defined(FEAT_QUICKFIX)
971 else if (wp->w_p_pvw)
972 rettv->vval.v_string = vim_strsave((char_u *)"preview");
973#endif
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +0100974#ifdef FEAT_PROP_POPUP
Bram Moolenaar0fe937f2020-06-16 22:42:04 +0200975 else if (WIN_IS_POPUP(wp))
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +0100976 rettv->vval.v_string = vim_strsave((char_u *)"popup");
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +0100977#endif
978#ifdef FEAT_CMDWIN
Bram Moolenaar0fe937f2020-06-16 22:42:04 +0200979 else if (wp == curwin && cmdwin_type != 0)
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +0100980 rettv->vval.v_string = vim_strsave((char_u *)"command");
981#endif
Yegappan Lakshmanan28d84212021-07-31 12:43:23 +0200982#ifdef FEAT_QUICKFIX
983 else if (bt_quickfix(wp->w_buffer))
984 rettv->vval.v_string = vim_strsave((char_u *)
985 (wp->w_llist_ref != NULL ? "loclist" : "quickfix"));
986#endif
987
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +0100988}
989
990/*
991 * "getcmdwintype()" function
992 */
993 void
994f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv)
995{
996 rettv->v_type = VAR_STRING;
997 rettv->vval.v_string = NULL;
998#ifdef FEAT_CMDWIN
999 rettv->vval.v_string = alloc(2);
1000 if (rettv->vval.v_string != NULL)
1001 {
1002 rettv->vval.v_string[0] = cmdwin_type;
1003 rettv->vval.v_string[1] = NUL;
1004 }
1005#endif
1006}
1007
1008/*
Bram Moolenaar261f3462019-09-07 15:45:32 +02001009 * "winbufnr(nr)" function
1010 */
1011 void
1012f_winbufnr(typval_T *argvars, typval_T *rettv)
1013{
1014 win_T *wp;
1015
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001016 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1017 return;
1018
Bram Moolenaar261f3462019-09-07 15:45:32 +02001019 wp = find_win_by_nr_or_id(&argvars[0]);
1020 if (wp == NULL)
1021 rettv->vval.v_number = -1;
1022 else
1023 rettv->vval.v_number = wp->w_buffer->b_fnum;
1024}
1025
1026/*
1027 * "wincol()" function
1028 */
1029 void
1030f_wincol(typval_T *argvars UNUSED, typval_T *rettv)
1031{
1032 validate_cursor();
1033 rettv->vval.v_number = curwin->w_wcol + 1;
1034}
1035
1036/*
1037 * "winheight(nr)" function
1038 */
1039 void
1040f_winheight(typval_T *argvars, typval_T *rettv)
1041{
1042 win_T *wp;
1043
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001044 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1045 return;
1046
Bram Moolenaar261f3462019-09-07 15:45:32 +02001047 wp = find_win_by_nr_or_id(&argvars[0]);
1048 if (wp == NULL)
1049 rettv->vval.v_number = -1;
1050 else
1051 rettv->vval.v_number = wp->w_height;
1052}
1053
1054/*
1055 * "winlayout()" function
1056 */
1057 void
1058f_winlayout(typval_T *argvars, typval_T *rettv)
1059{
1060 tabpage_T *tp;
1061
1062 if (rettv_list_alloc(rettv) != OK)
1063 return;
1064
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001065 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
1066 return;
1067
Bram Moolenaar261f3462019-09-07 15:45:32 +02001068 if (argvars[0].v_type == VAR_UNKNOWN)
1069 tp = curtab;
1070 else
1071 {
1072 tp = find_tabpage((int)tv_get_number(&argvars[0]));
1073 if (tp == NULL)
1074 return;
1075 }
1076
1077 get_framelayout(tp->tp_topframe, rettv->vval.v_list, TRUE);
1078}
1079
1080/*
1081 * "winline()" function
1082 */
1083 void
1084f_winline(typval_T *argvars UNUSED, typval_T *rettv)
1085{
1086 validate_cursor();
1087 rettv->vval.v_number = curwin->w_wrow + 1;
1088}
1089
1090/*
1091 * "winnr()" function
1092 */
1093 void
1094f_winnr(typval_T *argvars UNUSED, typval_T *rettv)
1095{
1096 int nr = 1;
1097
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001098 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
1099 return;
1100
Bram Moolenaar261f3462019-09-07 15:45:32 +02001101 nr = get_winnr(curtab, &argvars[0]);
1102 rettv->vval.v_number = nr;
1103}
1104
1105/*
1106 * "winrestcmd()" function
1107 */
1108 void
1109f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv)
1110{
1111 win_T *wp;
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001112 int i;
1113 int winnr;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001114 garray_T ga;
1115 char_u buf[50];
1116
1117 ga_init2(&ga, (int)sizeof(char), 70);
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001118
1119 // Do this twice to handle some window layouts properly.
1120 for (i = 0; i < 2; ++i)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001121 {
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001122 winnr = 1;
1123 FOR_ALL_WINDOWS(wp)
1124 {
1125 sprintf((char *)buf, ":%dresize %d|", winnr, wp->w_height);
1126 ga_concat(&ga, buf);
1127 sprintf((char *)buf, "vert :%dresize %d|", winnr, wp->w_width);
1128 ga_concat(&ga, buf);
1129 ++winnr;
1130 }
Bram Moolenaar261f3462019-09-07 15:45:32 +02001131 }
1132 ga_append(&ga, NUL);
1133
1134 rettv->vval.v_string = ga.ga_data;
1135 rettv->v_type = VAR_STRING;
1136}
1137
1138/*
1139 * "winrestview()" function
1140 */
1141 void
1142f_winrestview(typval_T *argvars, typval_T *rettv UNUSED)
1143{
1144 dict_T *dict;
1145
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001146 if (in_vim9script() && check_for_dict_arg(argvars, 0) == FAIL)
1147 return;
1148
Bram Moolenaar261f3462019-09-07 15:45:32 +02001149 if (argvars[0].v_type != VAR_DICT
1150 || (dict = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001151 emsg(_(e_invalid_argument));
Bram Moolenaar261f3462019-09-07 15:45:32 +02001152 else
1153 {
1154 if (dict_find(dict, (char_u *)"lnum", -1) != NULL)
1155 curwin->w_cursor.lnum = (linenr_T)dict_get_number(dict, (char_u *)"lnum");
1156 if (dict_find(dict, (char_u *)"col", -1) != NULL)
1157 curwin->w_cursor.col = (colnr_T)dict_get_number(dict, (char_u *)"col");
1158 if (dict_find(dict, (char_u *)"coladd", -1) != NULL)
1159 curwin->w_cursor.coladd = (colnr_T)dict_get_number(dict, (char_u *)"coladd");
1160 if (dict_find(dict, (char_u *)"curswant", -1) != NULL)
1161 {
1162 curwin->w_curswant = (colnr_T)dict_get_number(dict, (char_u *)"curswant");
1163 curwin->w_set_curswant = FALSE;
1164 }
1165
1166 if (dict_find(dict, (char_u *)"topline", -1) != NULL)
1167 set_topline(curwin, (linenr_T)dict_get_number(dict, (char_u *)"topline"));
1168#ifdef FEAT_DIFF
1169 if (dict_find(dict, (char_u *)"topfill", -1) != NULL)
1170 curwin->w_topfill = (int)dict_get_number(dict, (char_u *)"topfill");
1171#endif
1172 if (dict_find(dict, (char_u *)"leftcol", -1) != NULL)
1173 curwin->w_leftcol = (colnr_T)dict_get_number(dict, (char_u *)"leftcol");
1174 if (dict_find(dict, (char_u *)"skipcol", -1) != NULL)
1175 curwin->w_skipcol = (colnr_T)dict_get_number(dict, (char_u *)"skipcol");
1176
1177 check_cursor();
1178 win_new_height(curwin, curwin->w_height);
1179 win_new_width(curwin, curwin->w_width);
1180 changed_window_setting();
1181
1182 if (curwin->w_topline <= 0)
1183 curwin->w_topline = 1;
1184 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
1185 curwin->w_topline = curbuf->b_ml.ml_line_count;
1186#ifdef FEAT_DIFF
1187 check_topfill(curwin, TRUE);
1188#endif
1189 }
1190}
1191
1192/*
1193 * "winsaveview()" function
1194 */
1195 void
1196f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv)
1197{
1198 dict_T *dict;
1199
1200 if (rettv_dict_alloc(rettv) == FAIL)
1201 return;
1202 dict = rettv->vval.v_dict;
1203
1204 dict_add_number(dict, "lnum", (long)curwin->w_cursor.lnum);
1205 dict_add_number(dict, "col", (long)curwin->w_cursor.col);
1206 dict_add_number(dict, "coladd", (long)curwin->w_cursor.coladd);
1207 update_curswant();
1208 dict_add_number(dict, "curswant", (long)curwin->w_curswant);
1209
1210 dict_add_number(dict, "topline", (long)curwin->w_topline);
1211#ifdef FEAT_DIFF
1212 dict_add_number(dict, "topfill", (long)curwin->w_topfill);
1213#endif
1214 dict_add_number(dict, "leftcol", (long)curwin->w_leftcol);
1215 dict_add_number(dict, "skipcol", (long)curwin->w_skipcol);
1216}
1217
1218/*
1219 * "winwidth(nr)" function
1220 */
1221 void
1222f_winwidth(typval_T *argvars, typval_T *rettv)
1223{
1224 win_T *wp;
1225
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001226 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1227 return;
1228
Bram Moolenaar261f3462019-09-07 15:45:32 +02001229 wp = find_win_by_nr_or_id(&argvars[0]);
1230 if (wp == NULL)
1231 rettv->vval.v_number = -1;
1232 else
1233 rettv->vval.v_number = wp->w_width;
1234}
1235#endif // FEAT_EVAL
1236
1237#if defined(FEAT_EVAL) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
1238 || defined(PROTO)
1239/*
1240 * Set "win" to be the curwin and "tp" to be the current tab page.
1241 * restore_win() MUST be called to undo, also when FAIL is returned.
1242 * No autocommands will be executed until restore_win() is called.
1243 * When "no_display" is TRUE the display won't be affected, no redraw is
1244 * triggered, another tabpage access is limited.
1245 * Returns FAIL if switching to "win" failed.
1246 */
1247 int
1248switch_win(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001249 switchwin_T *switchwin,
1250 win_T *win,
1251 tabpage_T *tp,
1252 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001253{
1254 block_autocmds();
Bram Moolenaar18f47402022-01-06 13:24:51 +00001255 return switch_win_noblock(switchwin, win, tp, no_display);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001256}
1257
1258/*
1259 * As switch_win() but without blocking autocommands.
1260 */
1261 int
1262switch_win_noblock(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001263 switchwin_T *switchwin,
1264 win_T *win,
1265 tabpage_T *tp,
1266 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001267{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001268 CLEAR_POINTER(switchwin);
1269 switchwin->sw_curwin = curwin;
1270 if (win == curwin)
1271 switchwin->sw_same_win = TRUE;
1272 else
1273 {
1274 // Disable Visual selection, because redrawing may fail.
1275 switchwin->sw_visual_active = VIsual_active;
1276 VIsual_active = FALSE;
1277 }
1278
Bram Moolenaar261f3462019-09-07 15:45:32 +02001279 if (tp != NULL)
1280 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00001281 switchwin->sw_curtab = curtab;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001282 if (no_display)
1283 {
1284 curtab->tp_firstwin = firstwin;
1285 curtab->tp_lastwin = lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001286 curtab->tp_topframe = topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001287 curtab = tp;
1288 firstwin = curtab->tp_firstwin;
1289 lastwin = curtab->tp_lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001290 topframe = curtab->tp_topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001291 }
1292 else
1293 goto_tabpage_tp(tp, FALSE, FALSE);
1294 }
1295 if (!win_valid(win))
1296 return FAIL;
1297 curwin = win;
1298 curbuf = curwin->w_buffer;
1299 return OK;
1300}
1301
1302/*
1303 * Restore current tabpage and window saved by switch_win(), if still valid.
1304 * When "no_display" is TRUE the display won't be affected, no redraw is
1305 * triggered.
1306 */
1307 void
1308restore_win(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001309 switchwin_T *switchwin,
1310 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001311{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001312 restore_win_noblock(switchwin, no_display);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001313 unblock_autocmds();
1314}
1315
1316/*
1317 * As restore_win() but without unblocking autocommands.
1318 */
1319 void
1320restore_win_noblock(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001321 switchwin_T *switchwin,
1322 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001323{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001324 if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001325 {
1326 if (no_display)
1327 {
1328 curtab->tp_firstwin = firstwin;
1329 curtab->tp_lastwin = lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001330 curtab->tp_topframe = topframe;
Bram Moolenaar18f47402022-01-06 13:24:51 +00001331 curtab = switchwin->sw_curtab;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001332 firstwin = curtab->tp_firstwin;
1333 lastwin = curtab->tp_lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001334 topframe = curtab->tp_topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001335 }
1336 else
Bram Moolenaar18f47402022-01-06 13:24:51 +00001337 goto_tabpage_tp(switchwin->sw_curtab, FALSE, FALSE);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001338 }
Bram Moolenaar18f47402022-01-06 13:24:51 +00001339
1340 if (!switchwin->sw_same_win)
1341 VIsual_active = switchwin->sw_visual_active;
1342
1343 if (win_valid(switchwin->sw_curwin))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001344 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00001345 curwin = switchwin->sw_curwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001346 curbuf = curwin->w_buffer;
1347 }
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01001348# ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +02001349 else if (WIN_IS_POPUP(curwin))
1350 // original window was closed and now we're in a popup window: Go
1351 // to the first valid window.
1352 win_goto(firstwin);
1353# endif
Bram Moolenaar261f3462019-09-07 15:45:32 +02001354}
1355#endif