blob: fd62579cd1e1fc5ee64f014c8467d99094c0c132 [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
LemonBoy8530b412022-04-20 19:00:36 +0100398 // make sure w_botline is valid
399 validate_botline_win(wp);
400
Bram Moolenaar261f3462019-09-07 15:45:32 +0200401 dict_add_number(dict, "tabnr", tpnr);
402 dict_add_number(dict, "winnr", winnr);
403 dict_add_number(dict, "winid", wp->w_id);
404 dict_add_number(dict, "height", wp->w_height);
405 dict_add_number(dict, "winrow", wp->w_winrow + 1);
406 dict_add_number(dict, "topline", wp->w_topline);
407 dict_add_number(dict, "botline", wp->w_botline - 1);
408#ifdef FEAT_MENU
409 dict_add_number(dict, "winbar", wp->w_winbar_height);
410#endif
411 dict_add_number(dict, "width", wp->w_width);
412 dict_add_number(dict, "wincol", wp->w_wincol + 1);
Bram Moolenaarcdf5fdb2021-11-20 11:14:24 +0000413 dict_add_number(dict, "textoff", win_col_off(wp));
Bram Moolenaar261f3462019-09-07 15:45:32 +0200414 dict_add_number(dict, "bufnr", wp->w_buffer->b_fnum);
415
416#ifdef FEAT_TERMINAL
417 dict_add_number(dict, "terminal", bt_terminal(wp->w_buffer));
418#endif
419#ifdef FEAT_QUICKFIX
420 dict_add_number(dict, "quickfix", bt_quickfix(wp->w_buffer));
421 dict_add_number(dict, "loclist",
422 (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL));
423#endif
424
425 // Add a reference to window variables
426 dict_add_dict(dict, "variables", wp->w_vars);
427
428 return dict;
429}
430
431/*
432 * Returns information (variables, options, etc.) about a tab page
433 * as a dictionary.
434 */
435 static dict_T *
436get_tabpage_info(tabpage_T *tp, int tp_idx)
437{
438 win_T *wp;
439 dict_T *dict;
440 list_T *l;
441
442 dict = dict_alloc();
443 if (dict == NULL)
444 return NULL;
445
446 dict_add_number(dict, "tabnr", tp_idx);
447
448 l = list_alloc();
449 if (l != NULL)
450 {
Bram Moolenaar00d253e2020-04-06 22:13:01 +0200451 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200452 list_append_number(l, (varnumber_T)wp->w_id);
453 dict_add_list(dict, "windows", l);
454 }
455
456 // Make a reference to tabpage variables
457 dict_add_dict(dict, "variables", tp->tp_vars);
458
459 return dict;
460}
461
462/*
463 * "gettabinfo()" function
464 */
465 void
466f_gettabinfo(typval_T *argvars, typval_T *rettv)
467{
468 tabpage_T *tp, *tparg = NULL;
469 dict_T *d;
470 int tpnr = 0;
471
472 if (rettv_list_alloc(rettv) != OK)
473 return;
474
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200475 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
476 return;
477
Bram Moolenaar261f3462019-09-07 15:45:32 +0200478 if (argvars[0].v_type != VAR_UNKNOWN)
479 {
480 // Information about one tab page
481 tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
482 if (tparg == NULL)
483 return;
484 }
485
486 // Get information about a specific tab page or all tab pages
487 FOR_ALL_TABPAGES(tp)
488 {
489 tpnr++;
490 if (tparg != NULL && tp != tparg)
491 continue;
492 d = get_tabpage_info(tp, tpnr);
493 if (d != NULL)
494 list_append_dict(rettv->vval.v_list, d);
495 if (tparg != NULL)
496 return;
497 }
498}
499
500/*
501 * "getwininfo()" function
502 */
503 void
504f_getwininfo(typval_T *argvars, typval_T *rettv)
505{
506 tabpage_T *tp;
507 win_T *wp = NULL, *wparg = NULL;
508 dict_T *d;
509 short tabnr = 0, winnr;
510
511 if (rettv_list_alloc(rettv) != OK)
512 return;
513
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200514 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
515 return;
516
Bram Moolenaar261f3462019-09-07 15:45:32 +0200517 if (argvars[0].v_type != VAR_UNKNOWN)
518 {
519 wparg = win_id2wp(tv_get_number(&argvars[0]));
520 if (wparg == NULL)
521 return;
522 }
523
524 // Collect information about either all the windows across all the tab
525 // pages or one particular window.
526 FOR_ALL_TABPAGES(tp)
527 {
528 tabnr++;
529 winnr = 0;
530 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
531 {
532 winnr++;
533 if (wparg != NULL && wp != wparg)
534 continue;
535 d = get_win_info(wp, tabnr, winnr);
536 if (d != NULL)
537 list_append_dict(rettv->vval.v_list, d);
538 if (wparg != NULL)
539 // found information about a specific window
540 return;
541 }
542 }
Bram Moolenaar99ca9c42020-09-22 21:55:41 +0200543#ifdef FEAT_PROP_POPUP
544 if (wparg != NULL)
545 {
546 tabnr = 0;
547 FOR_ALL_TABPAGES(tp)
548 {
549 tabnr++;
550 FOR_ALL_POPUPWINS_IN_TAB(tp, wp)
551 if (wp == wparg)
552 break;
553 }
554 d = get_win_info(wparg, tp == NULL ? 0 : tabnr, 0);
555 if (d != NULL)
556 list_append_dict(rettv->vval.v_list, d);
557 }
558#endif
Bram Moolenaar261f3462019-09-07 15:45:32 +0200559}
560
561/*
562 * "getwinpos({timeout})" function
563 */
564 void
565f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv)
566{
567 int x = -1;
568 int y = -1;
569
570 if (rettv_list_alloc(rettv) == FAIL)
571 return;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200572
573 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
574 return;
575
Bram Moolenaar261f3462019-09-07 15:45:32 +0200576#if defined(FEAT_GUI) \
577 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
578 || defined(MSWIN)
579 {
580 varnumber_T timeout = 100;
581
582 if (argvars[0].v_type != VAR_UNKNOWN)
583 timeout = tv_get_number(&argvars[0]);
584
585 (void)ui_get_winpos(&x, &y, timeout);
586 }
587#endif
588 list_append_number(rettv->vval.v_list, (varnumber_T)x);
589 list_append_number(rettv->vval.v_list, (varnumber_T)y);
590}
591
592
593/*
594 * "getwinposx()" function
595 */
596 void
597f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
598{
599 rettv->vval.v_number = -1;
600#if defined(FEAT_GUI) \
601 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
602 || defined(MSWIN)
603
604 {
605 int x, y;
606
607 if (ui_get_winpos(&x, &y, 100) == OK)
608 rettv->vval.v_number = x;
609 }
610#endif
611}
612
613/*
614 * "getwinposy()" function
615 */
616 void
617f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
618{
619 rettv->vval.v_number = -1;
620#if defined(FEAT_GUI) \
621 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
622 || defined(MSWIN)
623 {
624 int x, y;
625
626 if (ui_get_winpos(&x, &y, 100) == OK)
627 rettv->vval.v_number = y;
628 }
629#endif
630}
631
632/*
633 * "tabpagenr()" function
634 */
635 void
636f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
637{
638 int nr = 1;
639 char_u *arg;
640
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200641 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
642 return;
643
Bram Moolenaar261f3462019-09-07 15:45:32 +0200644 if (argvars[0].v_type != VAR_UNKNOWN)
645 {
646 arg = tv_get_string_chk(&argvars[0]);
647 nr = 0;
648 if (arg != NULL)
649 {
650 if (STRCMP(arg, "$") == 0)
651 nr = tabpage_index(NULL) - 1;
Bram Moolenaar62a23252020-08-09 14:04:42 +0200652 else if (STRCMP(arg, "#") == 0)
653 nr = valid_tabpage(lastused_tabpage) ?
654 tabpage_index(lastused_tabpage) : 0;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200655 else
Bram Moolenaar108010a2021-06-27 22:03:33 +0200656 semsg(_(e_invalid_expression_str), arg);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200657 }
658 }
659 else
660 nr = tabpage_index(curtab);
661 rettv->vval.v_number = nr;
662}
663
664/*
665 * "tabpagewinnr()" function
666 */
667 void
668f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv)
669{
670 int nr = 1;
671 tabpage_T *tp;
672
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200673 if (in_vim9script()
674 && (check_for_number_arg(argvars, 0) == FAIL
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200675 || check_for_opt_string_arg(argvars, 1) == FAIL))
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200676 return;
677
Bram Moolenaar261f3462019-09-07 15:45:32 +0200678 tp = find_tabpage((int)tv_get_number(&argvars[0]));
679 if (tp == NULL)
680 nr = 0;
681 else
682 nr = get_winnr(tp, &argvars[1]);
683 rettv->vval.v_number = nr;
684}
685
686/*
687 * "win_execute()" function
688 */
689 void
690f_win_execute(typval_T *argvars, typval_T *rettv)
691{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200692 int id;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200693 tabpage_T *tp;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200694 win_T *wp;
Bram Moolenaar18f47402022-01-06 13:24:51 +0000695 switchwin_T switchwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200696
Bram Moolenaar37487e12021-01-12 22:08:53 +0100697 // Return an empty string if something fails.
698 rettv->v_type = VAR_STRING;
699 rettv->vval.v_string = NULL;
700
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200701 if (in_vim9script()
702 && (check_for_number_arg(argvars, 0) == FAIL
703 || check_for_string_or_list_arg(argvars, 1) == FAIL
704 || check_for_opt_string_arg(argvars, 2) == FAIL))
705 return;
706
707 id = (int)tv_get_number(argvars);
708 wp = win_id2wp_tp(id, &tp);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200709 if (wp != NULL && tp != NULL)
710 {
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200711 pos_T curpos = wp->w_cursor;
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000712 char_u cwd[MAXPATHL];
Bram Moolenaard6f27c62022-01-11 12:37:20 +0000713 int cwd_status = FAIL;
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000714#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000715 char_u autocwd[MAXPATHL];
716 int apply_acd = FALSE;
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000717#endif
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000718
Bram Moolenaard6f27c62022-01-11 12:37:20 +0000719 // Getting and setting directory can be slow on some systems, only do
720 // this when the current or target window/tab have a local directory or
721 // 'acd' is set.
722 if (curwin != wp
723 && (curwin->w_localdir != NULL
724 || wp->w_localdir != NULL
725 || (curtab != tp
726 && (curtab->tp_localdir != NULL
727 || tp->tp_localdir != NULL))
728#ifdef FEAT_AUTOCHDIR
729 || p_acd
730#endif
731 ))
732 cwd_status = mch_dirname(cwd, MAXPATHL);
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000733
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000734#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000735 // If 'acd' is set, check we are using that directory. If yes, then
736 // apply 'acd' afterwards, otherwise restore the current directory.
737 if (cwd_status == OK && p_acd)
738 {
739 do_autochdir();
740 apply_acd = mch_dirname(autocwd, MAXPATHL) == OK
741 && STRCMP(cwd, autocwd) == 0;
742 }
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000743#endif
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200744
Bram Moolenaar18f47402022-01-06 13:24:51 +0000745 if (switch_win_noblock(&switchwin, wp, tp, TRUE) == OK)
Bram Moolenaar261f3462019-09-07 15:45:32 +0200746 {
747 check_cursor();
748 execute_common(argvars, rettv, 1);
749 }
Bram Moolenaar18f47402022-01-06 13:24:51 +0000750 restore_win_noblock(&switchwin, TRUE);
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000751#ifdef FEAT_AUTOCHDIR
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000752 if (apply_acd)
753 do_autochdir();
Bram Moolenaar92f246e2021-12-28 20:03:43 +0000754 else
755#endif
756 if (cwd_status == OK)
Bram Moolenaar90c317f2021-12-28 13:15:05 +0000757 mch_chdir((char *)cwd);
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200758
759 // Update the status line if the cursor moved.
760 if (win_valid(wp) && !EQUAL_POS(curpos, wp->w_cursor))
761 wp->w_redr_status = TRUE;
Bram Moolenaare664a322022-01-07 14:08:03 +0000762
763 // In case the command moved the cursor or changed the Visual area,
764 // check it is valid.
765 check_cursor();
766 if (VIsual_active)
767 check_pos(curbuf, &VIsual);
Bram Moolenaar261f3462019-09-07 15:45:32 +0200768 }
769}
770
771/*
772 * "win_findbuf()" function
773 */
774 void
775f_win_findbuf(typval_T *argvars, typval_T *rettv)
776{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200777 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
778 return;
779
Bram Moolenaar261f3462019-09-07 15:45:32 +0200780 if (rettv_list_alloc(rettv) != FAIL)
781 win_findbuf(argvars, rettv->vval.v_list);
782}
783
784/*
785 * "win_getid()" function
786 */
787 void
788f_win_getid(typval_T *argvars, typval_T *rettv)
789{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200790 if (in_vim9script()
791 && (check_for_opt_number_arg(argvars, 0) == FAIL
792 || (argvars[0].v_type != VAR_UNKNOWN
793 && check_for_opt_number_arg(argvars, 1) == FAIL)))
794 return;
795
Bram Moolenaar261f3462019-09-07 15:45:32 +0200796 rettv->vval.v_number = win_getid(argvars);
797}
798
799/*
800 * "win_gotoid()" function
801 */
802 void
803f_win_gotoid(typval_T *argvars, typval_T *rettv)
804{
Bram Moolenaara046b372019-09-15 17:26:07 +0200805 win_T *wp;
806 tabpage_T *tp;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200807 int id;
Bram Moolenaara046b372019-09-15 17:26:07 +0200808
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200809 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
810 return;
811
812 id = tv_get_number(&argvars[0]);
Bram Moolenaara046b372019-09-15 17:26:07 +0200813#ifdef FEAT_CMDWIN
814 if (cmdwin_type != 0)
815 {
Bram Moolenaar108010a2021-06-27 22:03:33 +0200816 emsg(_(e_invalid_in_cmdline_window));
Bram Moolenaara046b372019-09-15 17:26:07 +0200817 return;
818 }
819#endif
LemonBoy4a392d22022-04-23 14:07:56 +0100820#if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL)
821 if (popup_is_popup(curwin) && curbuf->b_term != NULL)
822 {
823 emsg(_(e_not_allowed_for_terminal_in_popup_window));
824 return;
825 }
826#endif
Bram Moolenaara046b372019-09-15 17:26:07 +0200827 FOR_ALL_TAB_WINDOWS(tp, wp)
828 if (wp->w_id == id)
829 {
Bram Moolenaar3aca0912022-04-18 18:32:19 +0100830 // When jumping to another buffer stop Visual mode.
831 if (VIsual_active && wp->w_buffer != curbuf)
832 end_visual_mode();
Bram Moolenaara046b372019-09-15 17:26:07 +0200833 goto_tabpage_win(tp, wp);
834 rettv->vval.v_number = 1;
835 return;
836 }
Bram Moolenaar261f3462019-09-07 15:45:32 +0200837}
838
839/*
840 * "win_id2tabwin()" function
841 */
842 void
843f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
844{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200845 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
846 return;
847
Bram Moolenaar261f3462019-09-07 15:45:32 +0200848 if (rettv_list_alloc(rettv) != FAIL)
849 win_id2tabwin(argvars, rettv->vval.v_list);
850}
851
852/*
853 * "win_id2win()" function
854 */
855 void
856f_win_id2win(typval_T *argvars, typval_T *rettv)
857{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200858 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
859 return;
860
Bram Moolenaar261f3462019-09-07 15:45:32 +0200861 rettv->vval.v_number = win_id2win(argvars);
862}
863
864/*
Daniel Steinbergee630312022-01-10 13:36:34 +0000865 * "win_move_separator()" function
866 */
867 void
868f_win_move_separator(typval_T *argvars, typval_T *rettv)
869{
870 win_T *wp;
871 int offset;
872
873 rettv->vval.v_number = FALSE;
874
875 if (in_vim9script()
876 && (check_for_number_arg(argvars, 0) == FAIL
877 || check_for_number_arg(argvars, 1) == FAIL))
878 return;
879
880 wp = find_win_by_nr_or_id(&argvars[0]);
881 if (wp == NULL || win_valid_popup(wp))
882 return;
883
884 offset = (int)tv_get_number(&argvars[1]);
885 win_drag_vsep_line(wp, offset);
886 rettv->vval.v_number = TRUE;
887}
888
889/*
890 * "win_move_statusline()" function
891 */
892 void
893f_win_move_statusline(typval_T *argvars, typval_T *rettv)
894{
895 win_T *wp;
896 int offset;
897
898 rettv->vval.v_number = FALSE;
899
900 if (in_vim9script()
901 && (check_for_number_arg(argvars, 0) == FAIL
902 || check_for_number_arg(argvars, 1) == FAIL))
903 return;
904
905 wp = find_win_by_nr_or_id(&argvars[0]);
906 if (wp == NULL || win_valid_popup(wp))
907 return;
908
909 offset = (int)tv_get_number(&argvars[1]);
910 win_drag_status_line(wp, offset);
911 rettv->vval.v_number = TRUE;
912}
913
914/*
Bram Moolenaar261f3462019-09-07 15:45:32 +0200915 * "win_screenpos()" function
916 */
917 void
918f_win_screenpos(typval_T *argvars, typval_T *rettv)
919{
920 win_T *wp;
921
922 if (rettv_list_alloc(rettv) == FAIL)
923 return;
924
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +0200925 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
926 return;
927
Bram Moolenaar261f3462019-09-07 15:45:32 +0200928 wp = find_win_by_nr_or_id(&argvars[0]);
929 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1);
930 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1);
931}
932
933/*
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200934 * Move the window wp into a new split of targetwin in a given direction
935 */
936 static void
937win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
938{
939 int dir;
940 int height = wp->w_height;
941 win_T *oldwin = curwin;
942
943 if (wp == targetwin)
944 return;
945
946 // Jump to the target window
947 if (curwin != targetwin)
948 win_goto(targetwin);
949
950 // Remove the old window and frame from the tree of frames
951 (void)winframe_remove(wp, &dir, NULL);
952 win_remove(wp, NULL);
953 last_status(FALSE); // may need to remove last status line
954 (void)win_comp_pos(); // recompute window positions
955
956 // Split a window on the desired side and put the old window there
957 (void)win_split_ins(size, flags, wp, dir);
958
959 // If splitting horizontally, try to preserve height
960 if (size == 0 && !(flags & WSP_VERT))
961 {
962 win_setheight_win(height, wp);
963 if (p_ea)
964 win_equal(wp, TRUE, 'v');
965 }
966
967#if defined(FEAT_GUI)
968 // When 'guioptions' includes 'L' or 'R' may have to remove or add
969 // scrollbars. Have to update them anyway.
970 gui_may_update_scrollbars();
971#endif
972
973 if (oldwin != curwin)
974 win_goto(oldwin);
975}
976
977/*
978 * "win_splitmove()" function
979 */
980 void
981f_win_splitmove(typval_T *argvars, typval_T *rettv)
982{
983 win_T *wp;
984 win_T *targetwin;
985 int flags = 0, size = 0;
986
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +0200987 if (in_vim9script()
988 && (check_for_number_arg(argvars, 0) == FAIL
989 || check_for_number_arg(argvars, 1) == FAIL
990 || check_for_opt_dict_arg(argvars, 2) == FAIL))
991 return;
992
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200993 wp = find_win_by_nr_or_id(&argvars[0]);
994 targetwin = find_win_by_nr_or_id(&argvars[1]);
995
Bram Moolenaar7b94e772020-01-06 21:03:24 +0100996 if (wp == NULL || targetwin == NULL || wp == targetwin
Bram Moolenaar0f1563f2020-03-20 21:15:51 +0100997 || !win_valid(wp) || !win_valid(targetwin)
998 || win_valid_popup(wp) || win_valid_popup(targetwin))
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200999 {
Bram Moolenaar3a846e62022-01-01 16:21:00 +00001000 emsg(_(e_invalid_window_number));
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001001 rettv->vval.v_number = -1;
1002 return;
1003 }
1004
1005 if (argvars[2].v_type != VAR_UNKNOWN)
1006 {
1007 dict_T *d;
1008 dictitem_T *di;
1009
1010 if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL)
1011 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001012 emsg(_(e_invalid_argument));
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001013 return;
1014 }
1015
1016 d = argvars[2].vval.v_dict;
Bram Moolenaar4b9bd692020-09-05 21:57:53 +02001017 if (dict_get_bool(d, (char_u *)"vertical", FALSE))
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001018 flags |= WSP_VERT;
1019 if ((di = dict_find(d, (char_u *)"rightbelow", -1)) != NULL)
Bram Moolenaar4b9bd692020-09-05 21:57:53 +02001020 flags |= tv_get_bool(&di->di_tv) ? WSP_BELOW : WSP_ABOVE;
Bram Moolenaard20dcb32019-09-10 21:22:58 +02001021 size = (int)dict_get_number(d, (char_u *)"size");
1022 }
1023
1024 win_move_into_split(wp, targetwin, size, flags);
1025}
1026
1027/*
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001028 * "win_gettype(nr)" function
1029 */
1030 void
1031f_win_gettype(typval_T *argvars, typval_T *rettv)
1032{
1033 win_T *wp = curwin;
1034
1035 rettv->v_type = VAR_STRING;
1036 rettv->vval.v_string = NULL;
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001037
1038 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
1039 return;
1040
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001041 if (argvars[0].v_type != VAR_UNKNOWN)
1042 {
1043 wp = find_win_by_nr_or_id(&argvars[0]);
1044 if (wp == NULL)
1045 {
1046 rettv->vval.v_string = vim_strsave((char_u *)"unknown");
1047 return;
1048 }
1049 }
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001050 if (wp == aucmd_win)
Bram Moolenaar40a019f2020-06-17 21:41:35 +02001051 rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001052#if defined(FEAT_QUICKFIX)
1053 else if (wp->w_p_pvw)
1054 rettv->vval.v_string = vim_strsave((char_u *)"preview");
1055#endif
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001056#ifdef FEAT_PROP_POPUP
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001057 else if (WIN_IS_POPUP(wp))
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001058 rettv->vval.v_string = vim_strsave((char_u *)"popup");
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001059#endif
1060#ifdef FEAT_CMDWIN
Bram Moolenaar0fe937f2020-06-16 22:42:04 +02001061 else if (wp == curwin && cmdwin_type != 0)
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001062 rettv->vval.v_string = vim_strsave((char_u *)"command");
1063#endif
Yegappan Lakshmanan28d84212021-07-31 12:43:23 +02001064#ifdef FEAT_QUICKFIX
1065 else if (bt_quickfix(wp->w_buffer))
1066 rettv->vval.v_string = vim_strsave((char_u *)
1067 (wp->w_llist_ref != NULL ? "loclist" : "quickfix"));
1068#endif
1069
Bram Moolenaar00f3b4e2020-02-14 14:32:22 +01001070}
1071
1072/*
1073 * "getcmdwintype()" function
1074 */
1075 void
1076f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv)
1077{
1078 rettv->v_type = VAR_STRING;
1079 rettv->vval.v_string = NULL;
1080#ifdef FEAT_CMDWIN
1081 rettv->vval.v_string = alloc(2);
1082 if (rettv->vval.v_string != NULL)
1083 {
1084 rettv->vval.v_string[0] = cmdwin_type;
1085 rettv->vval.v_string[1] = NUL;
1086 }
1087#endif
1088}
1089
1090/*
Bram Moolenaar261f3462019-09-07 15:45:32 +02001091 * "winbufnr(nr)" function
1092 */
1093 void
1094f_winbufnr(typval_T *argvars, typval_T *rettv)
1095{
1096 win_T *wp;
1097
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001098 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1099 return;
1100
Bram Moolenaar261f3462019-09-07 15:45:32 +02001101 wp = find_win_by_nr_or_id(&argvars[0]);
1102 if (wp == NULL)
1103 rettv->vval.v_number = -1;
1104 else
1105 rettv->vval.v_number = wp->w_buffer->b_fnum;
1106}
1107
1108/*
1109 * "wincol()" function
1110 */
1111 void
1112f_wincol(typval_T *argvars UNUSED, typval_T *rettv)
1113{
1114 validate_cursor();
1115 rettv->vval.v_number = curwin->w_wcol + 1;
1116}
1117
1118/*
1119 * "winheight(nr)" function
1120 */
1121 void
1122f_winheight(typval_T *argvars, typval_T *rettv)
1123{
1124 win_T *wp;
1125
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001126 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1127 return;
1128
Bram Moolenaar261f3462019-09-07 15:45:32 +02001129 wp = find_win_by_nr_or_id(&argvars[0]);
1130 if (wp == NULL)
1131 rettv->vval.v_number = -1;
1132 else
1133 rettv->vval.v_number = wp->w_height;
1134}
1135
1136/*
1137 * "winlayout()" function
1138 */
1139 void
1140f_winlayout(typval_T *argvars, typval_T *rettv)
1141{
1142 tabpage_T *tp;
1143
1144 if (rettv_list_alloc(rettv) != OK)
1145 return;
1146
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001147 if (in_vim9script() && check_for_opt_number_arg(argvars, 0) == FAIL)
1148 return;
1149
Bram Moolenaar261f3462019-09-07 15:45:32 +02001150 if (argvars[0].v_type == VAR_UNKNOWN)
1151 tp = curtab;
1152 else
1153 {
1154 tp = find_tabpage((int)tv_get_number(&argvars[0]));
1155 if (tp == NULL)
1156 return;
1157 }
1158
1159 get_framelayout(tp->tp_topframe, rettv->vval.v_list, TRUE);
1160}
1161
1162/*
1163 * "winline()" function
1164 */
1165 void
1166f_winline(typval_T *argvars UNUSED, typval_T *rettv)
1167{
1168 validate_cursor();
1169 rettv->vval.v_number = curwin->w_wrow + 1;
1170}
1171
1172/*
1173 * "winnr()" function
1174 */
1175 void
1176f_winnr(typval_T *argvars UNUSED, typval_T *rettv)
1177{
1178 int nr = 1;
1179
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001180 if (in_vim9script() && check_for_opt_string_arg(argvars, 0) == FAIL)
1181 return;
1182
Bram Moolenaar261f3462019-09-07 15:45:32 +02001183 nr = get_winnr(curtab, &argvars[0]);
1184 rettv->vval.v_number = nr;
1185}
1186
1187/*
1188 * "winrestcmd()" function
1189 */
1190 void
1191f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv)
1192{
1193 win_T *wp;
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001194 int i;
1195 int winnr;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001196 garray_T ga;
1197 char_u buf[50];
1198
Bram Moolenaar04935fb2022-01-08 16:19:22 +00001199 ga_init2(&ga, sizeof(char), 70);
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001200
1201 // Do this twice to handle some window layouts properly.
1202 for (i = 0; i < 2; ++i)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001203 {
Bram Moolenaara0c8aea2021-03-20 19:55:35 +01001204 winnr = 1;
1205 FOR_ALL_WINDOWS(wp)
1206 {
1207 sprintf((char *)buf, ":%dresize %d|", winnr, wp->w_height);
1208 ga_concat(&ga, buf);
1209 sprintf((char *)buf, "vert :%dresize %d|", winnr, wp->w_width);
1210 ga_concat(&ga, buf);
1211 ++winnr;
1212 }
Bram Moolenaar261f3462019-09-07 15:45:32 +02001213 }
1214 ga_append(&ga, NUL);
1215
1216 rettv->vval.v_string = ga.ga_data;
1217 rettv->v_type = VAR_STRING;
1218}
1219
1220/*
1221 * "winrestview()" function
1222 */
1223 void
1224f_winrestview(typval_T *argvars, typval_T *rettv UNUSED)
1225{
1226 dict_T *dict;
1227
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001228 if (in_vim9script() && check_for_dict_arg(argvars, 0) == FAIL)
1229 return;
1230
Bram Moolenaar261f3462019-09-07 15:45:32 +02001231 if (argvars[0].v_type != VAR_DICT
1232 || (dict = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001233 emsg(_(e_invalid_argument));
Bram Moolenaar261f3462019-09-07 15:45:32 +02001234 else
1235 {
Yegappan Lakshmanan4829c1c2022-04-04 15:16:54 +01001236 if (dict_has_key(dict, "lnum"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001237 curwin->w_cursor.lnum = (linenr_T)dict_get_number(dict, (char_u *)"lnum");
Yegappan Lakshmanan4829c1c2022-04-04 15:16:54 +01001238 if (dict_has_key(dict, "col"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001239 curwin->w_cursor.col = (colnr_T)dict_get_number(dict, (char_u *)"col");
Yegappan Lakshmanan4829c1c2022-04-04 15:16:54 +01001240 if (dict_has_key(dict, "coladd"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001241 curwin->w_cursor.coladd = (colnr_T)dict_get_number(dict, (char_u *)"coladd");
Yegappan Lakshmanan4829c1c2022-04-04 15:16:54 +01001242 if (dict_has_key(dict, "curswant"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001243 {
1244 curwin->w_curswant = (colnr_T)dict_get_number(dict, (char_u *)"curswant");
1245 curwin->w_set_curswant = FALSE;
1246 }
1247
Yegappan Lakshmanan4829c1c2022-04-04 15:16:54 +01001248 if (dict_has_key(dict, "topline"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001249 set_topline(curwin, (linenr_T)dict_get_number(dict, (char_u *)"topline"));
1250#ifdef FEAT_DIFF
Yegappan Lakshmanan4829c1c2022-04-04 15:16:54 +01001251 if (dict_has_key(dict, "topfill"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001252 curwin->w_topfill = (int)dict_get_number(dict, (char_u *)"topfill");
1253#endif
Yegappan Lakshmanan4829c1c2022-04-04 15:16:54 +01001254 if (dict_has_key(dict, "leftcol"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001255 curwin->w_leftcol = (colnr_T)dict_get_number(dict, (char_u *)"leftcol");
Yegappan Lakshmanan4829c1c2022-04-04 15:16:54 +01001256 if (dict_has_key(dict, "skipcol"))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001257 curwin->w_skipcol = (colnr_T)dict_get_number(dict, (char_u *)"skipcol");
1258
1259 check_cursor();
1260 win_new_height(curwin, curwin->w_height);
1261 win_new_width(curwin, curwin->w_width);
1262 changed_window_setting();
1263
1264 if (curwin->w_topline <= 0)
1265 curwin->w_topline = 1;
1266 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
1267 curwin->w_topline = curbuf->b_ml.ml_line_count;
1268#ifdef FEAT_DIFF
1269 check_topfill(curwin, TRUE);
1270#endif
1271 }
1272}
1273
1274/*
1275 * "winsaveview()" function
1276 */
1277 void
1278f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv)
1279{
1280 dict_T *dict;
1281
1282 if (rettv_dict_alloc(rettv) == FAIL)
1283 return;
1284 dict = rettv->vval.v_dict;
1285
1286 dict_add_number(dict, "lnum", (long)curwin->w_cursor.lnum);
1287 dict_add_number(dict, "col", (long)curwin->w_cursor.col);
1288 dict_add_number(dict, "coladd", (long)curwin->w_cursor.coladd);
1289 update_curswant();
1290 dict_add_number(dict, "curswant", (long)curwin->w_curswant);
1291
1292 dict_add_number(dict, "topline", (long)curwin->w_topline);
1293#ifdef FEAT_DIFF
1294 dict_add_number(dict, "topfill", (long)curwin->w_topfill);
1295#endif
1296 dict_add_number(dict, "leftcol", (long)curwin->w_leftcol);
1297 dict_add_number(dict, "skipcol", (long)curwin->w_skipcol);
1298}
1299
1300/*
1301 * "winwidth(nr)" function
1302 */
1303 void
1304f_winwidth(typval_T *argvars, typval_T *rettv)
1305{
1306 win_T *wp;
1307
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02001308 if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL)
1309 return;
1310
Bram Moolenaar261f3462019-09-07 15:45:32 +02001311 wp = find_win_by_nr_or_id(&argvars[0]);
1312 if (wp == NULL)
1313 rettv->vval.v_number = -1;
1314 else
1315 rettv->vval.v_number = wp->w_width;
1316}
1317#endif // FEAT_EVAL
1318
1319#if defined(FEAT_EVAL) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
1320 || defined(PROTO)
1321/*
1322 * Set "win" to be the curwin and "tp" to be the current tab page.
1323 * restore_win() MUST be called to undo, also when FAIL is returned.
1324 * No autocommands will be executed until restore_win() is called.
1325 * When "no_display" is TRUE the display won't be affected, no redraw is
1326 * triggered, another tabpage access is limited.
1327 * Returns FAIL if switching to "win" failed.
1328 */
1329 int
1330switch_win(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001331 switchwin_T *switchwin,
1332 win_T *win,
1333 tabpage_T *tp,
1334 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001335{
1336 block_autocmds();
Bram Moolenaar18f47402022-01-06 13:24:51 +00001337 return switch_win_noblock(switchwin, win, tp, no_display);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001338}
1339
1340/*
1341 * As switch_win() but without blocking autocommands.
1342 */
1343 int
1344switch_win_noblock(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001345 switchwin_T *switchwin,
1346 win_T *win,
1347 tabpage_T *tp,
1348 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001349{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001350 CLEAR_POINTER(switchwin);
1351 switchwin->sw_curwin = curwin;
1352 if (win == curwin)
1353 switchwin->sw_same_win = TRUE;
1354 else
1355 {
1356 // Disable Visual selection, because redrawing may fail.
1357 switchwin->sw_visual_active = VIsual_active;
1358 VIsual_active = FALSE;
1359 }
1360
Bram Moolenaar261f3462019-09-07 15:45:32 +02001361 if (tp != NULL)
1362 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00001363 switchwin->sw_curtab = curtab;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001364 if (no_display)
1365 {
1366 curtab->tp_firstwin = firstwin;
1367 curtab->tp_lastwin = lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001368 curtab->tp_topframe = topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001369 curtab = tp;
1370 firstwin = curtab->tp_firstwin;
1371 lastwin = curtab->tp_lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001372 topframe = curtab->tp_topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001373 }
1374 else
1375 goto_tabpage_tp(tp, FALSE, FALSE);
1376 }
1377 if (!win_valid(win))
1378 return FAIL;
1379 curwin = win;
1380 curbuf = curwin->w_buffer;
1381 return OK;
1382}
1383
1384/*
1385 * Restore current tabpage and window saved by switch_win(), if still valid.
1386 * When "no_display" is TRUE the display won't be affected, no redraw is
1387 * triggered.
1388 */
1389 void
1390restore_win(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001391 switchwin_T *switchwin,
1392 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001393{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001394 restore_win_noblock(switchwin, no_display);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001395 unblock_autocmds();
1396}
1397
1398/*
1399 * As restore_win() but without unblocking autocommands.
1400 */
1401 void
1402restore_win_noblock(
Bram Moolenaar18f47402022-01-06 13:24:51 +00001403 switchwin_T *switchwin,
1404 int no_display)
Bram Moolenaar261f3462019-09-07 15:45:32 +02001405{
Bram Moolenaar18f47402022-01-06 13:24:51 +00001406 if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001407 {
1408 if (no_display)
1409 {
1410 curtab->tp_firstwin = firstwin;
1411 curtab->tp_lastwin = lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001412 curtab->tp_topframe = topframe;
Bram Moolenaar18f47402022-01-06 13:24:51 +00001413 curtab = switchwin->sw_curtab;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001414 firstwin = curtab->tp_firstwin;
1415 lastwin = curtab->tp_lastwin;
Bram Moolenaardab17a02021-12-20 21:35:59 +00001416 topframe = curtab->tp_topframe;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001417 }
1418 else
Bram Moolenaar18f47402022-01-06 13:24:51 +00001419 goto_tabpage_tp(switchwin->sw_curtab, FALSE, FALSE);
Bram Moolenaar261f3462019-09-07 15:45:32 +02001420 }
Bram Moolenaar18f47402022-01-06 13:24:51 +00001421
1422 if (!switchwin->sw_same_win)
1423 VIsual_active = switchwin->sw_visual_active;
1424
1425 if (win_valid(switchwin->sw_curwin))
Bram Moolenaar261f3462019-09-07 15:45:32 +02001426 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00001427 curwin = switchwin->sw_curwin;
Bram Moolenaar261f3462019-09-07 15:45:32 +02001428 curbuf = curwin->w_buffer;
1429 }
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01001430# ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +02001431 else if (WIN_IS_POPUP(curwin))
1432 // original window was closed and now we're in a popup window: Go
1433 // to the first valid window.
1434 win_goto(firstwin);
1435# endif
Bram Moolenaar261f3462019-09-07 15:45:32 +02001436}
1437#endif