blob: fb54033e5e925cb9385059f80b1e89dcb4c563ce [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)
109 for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
110 if (wp->w_id == id)
111 {
112 if (tpp != NULL)
113 *tpp = tp;
114 return wp;
115 }
116 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
117 if (wp->w_id == id)
118 {
119 if (tpp != NULL)
120 *tpp = tp;
121 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
191 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
192 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;
335 if (twin == NULL)
336 nr = 0;
337 }
338 else
339 {
340 long count;
341 char_u *endp;
342
343 // Extract the window count (if specified). e.g. winnr('3j')
344 count = strtol((char *)arg, (char **)&endp, 10);
345 if (count <= 0)
346 count = 1; // if count is not specified, default to 1
347 if (endp != NULL && *endp != '\0')
348 {
349 if (STRCMP(endp, "j") == 0)
350 twin = win_vert_neighbor(tp, twin, FALSE, count);
351 else if (STRCMP(endp, "k") == 0)
352 twin = win_vert_neighbor(tp, twin, TRUE, count);
353 else if (STRCMP(endp, "h") == 0)
354 twin = win_horz_neighbor(tp, twin, TRUE, count);
355 else if (STRCMP(endp, "l") == 0)
356 twin = win_horz_neighbor(tp, twin, FALSE, count);
357 else
358 invalid_arg = TRUE;
359 }
360 else
361 invalid_arg = TRUE;
362 }
363
364 if (invalid_arg)
365 {
366 semsg(_(e_invexpr2), arg);
367 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);
410 dict_add_number(dict, "bufnr", wp->w_buffer->b_fnum);
411
412#ifdef FEAT_TERMINAL
413 dict_add_number(dict, "terminal", bt_terminal(wp->w_buffer));
414#endif
415#ifdef FEAT_QUICKFIX
416 dict_add_number(dict, "quickfix", bt_quickfix(wp->w_buffer));
417 dict_add_number(dict, "loclist",
418 (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL));
419#endif
420
421 // Add a reference to window variables
422 dict_add_dict(dict, "variables", wp->w_vars);
423
424 return dict;
425}
426
427/*
428 * Returns information (variables, options, etc.) about a tab page
429 * as a dictionary.
430 */
431 static dict_T *
432get_tabpage_info(tabpage_T *tp, int tp_idx)
433{
434 win_T *wp;
435 dict_T *dict;
436 list_T *l;
437
438 dict = dict_alloc();
439 if (dict == NULL)
440 return NULL;
441
442 dict_add_number(dict, "tabnr", tp_idx);
443
444 l = list_alloc();
445 if (l != NULL)
446 {
447 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
448 wp != NULL; wp = wp->w_next)
449 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
472 if (argvars[0].v_type != VAR_UNKNOWN)
473 {
474 // Information about one tab page
475 tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
476 if (tparg == NULL)
477 return;
478 }
479
480 // Get information about a specific tab page or all tab pages
481 FOR_ALL_TABPAGES(tp)
482 {
483 tpnr++;
484 if (tparg != NULL && tp != tparg)
485 continue;
486 d = get_tabpage_info(tp, tpnr);
487 if (d != NULL)
488 list_append_dict(rettv->vval.v_list, d);
489 if (tparg != NULL)
490 return;
491 }
492}
493
494/*
495 * "getwininfo()" function
496 */
497 void
498f_getwininfo(typval_T *argvars, typval_T *rettv)
499{
500 tabpage_T *tp;
501 win_T *wp = NULL, *wparg = NULL;
502 dict_T *d;
503 short tabnr = 0, winnr;
504
505 if (rettv_list_alloc(rettv) != OK)
506 return;
507
508 if (argvars[0].v_type != VAR_UNKNOWN)
509 {
510 wparg = win_id2wp(tv_get_number(&argvars[0]));
511 if (wparg == NULL)
512 return;
513 }
514
515 // Collect information about either all the windows across all the tab
516 // pages or one particular window.
517 FOR_ALL_TABPAGES(tp)
518 {
519 tabnr++;
520 winnr = 0;
521 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
522 {
523 winnr++;
524 if (wparg != NULL && wp != wparg)
525 continue;
526 d = get_win_info(wp, tabnr, winnr);
527 if (d != NULL)
528 list_append_dict(rettv->vval.v_list, d);
529 if (wparg != NULL)
530 // found information about a specific window
531 return;
532 }
533 }
534}
535
536/*
537 * "getwinpos({timeout})" function
538 */
539 void
540f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv)
541{
542 int x = -1;
543 int y = -1;
544
545 if (rettv_list_alloc(rettv) == FAIL)
546 return;
547#if defined(FEAT_GUI) \
548 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
549 || defined(MSWIN)
550 {
551 varnumber_T timeout = 100;
552
553 if (argvars[0].v_type != VAR_UNKNOWN)
554 timeout = tv_get_number(&argvars[0]);
555
556 (void)ui_get_winpos(&x, &y, timeout);
557 }
558#endif
559 list_append_number(rettv->vval.v_list, (varnumber_T)x);
560 list_append_number(rettv->vval.v_list, (varnumber_T)y);
561}
562
563
564/*
565 * "getwinposx()" function
566 */
567 void
568f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
569{
570 rettv->vval.v_number = -1;
571#if defined(FEAT_GUI) \
572 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
573 || defined(MSWIN)
574
575 {
576 int x, y;
577
578 if (ui_get_winpos(&x, &y, 100) == OK)
579 rettv->vval.v_number = x;
580 }
581#endif
582}
583
584/*
585 * "getwinposy()" function
586 */
587 void
588f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
589{
590 rettv->vval.v_number = -1;
591#if defined(FEAT_GUI) \
592 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
593 || defined(MSWIN)
594 {
595 int x, y;
596
597 if (ui_get_winpos(&x, &y, 100) == OK)
598 rettv->vval.v_number = y;
599 }
600#endif
601}
602
603/*
604 * "tabpagenr()" function
605 */
606 void
607f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
608{
609 int nr = 1;
610 char_u *arg;
611
612 if (argvars[0].v_type != VAR_UNKNOWN)
613 {
614 arg = tv_get_string_chk(&argvars[0]);
615 nr = 0;
616 if (arg != NULL)
617 {
618 if (STRCMP(arg, "$") == 0)
619 nr = tabpage_index(NULL) - 1;
620 else
621 semsg(_(e_invexpr2), arg);
622 }
623 }
624 else
625 nr = tabpage_index(curtab);
626 rettv->vval.v_number = nr;
627}
628
629/*
630 * "tabpagewinnr()" function
631 */
632 void
633f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv)
634{
635 int nr = 1;
636 tabpage_T *tp;
637
638 tp = find_tabpage((int)tv_get_number(&argvars[0]));
639 if (tp == NULL)
640 nr = 0;
641 else
642 nr = get_winnr(tp, &argvars[1]);
643 rettv->vval.v_number = nr;
644}
645
646/*
647 * "win_execute()" function
648 */
649 void
650f_win_execute(typval_T *argvars, typval_T *rettv)
651{
652 int id = (int)tv_get_number(argvars);
653 tabpage_T *tp;
654 win_T *wp = win_id2wp_tp(id, &tp);
655 win_T *save_curwin;
656 tabpage_T *save_curtab;
657
658 if (wp != NULL && tp != NULL)
659 {
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200660 pos_T curpos = wp->w_cursor;
661
Bram Moolenaar261f3462019-09-07 15:45:32 +0200662 if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, TRUE) == OK)
663 {
664 check_cursor();
665 execute_common(argvars, rettv, 1);
666 }
667 restore_win_noblock(save_curwin, save_curtab, TRUE);
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200668
669 // Update the status line if the cursor moved.
670 if (win_valid(wp) && !EQUAL_POS(curpos, wp->w_cursor))
671 wp->w_redr_status = TRUE;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200672 }
673}
674
675/*
676 * "win_findbuf()" function
677 */
678 void
679f_win_findbuf(typval_T *argvars, typval_T *rettv)
680{
681 if (rettv_list_alloc(rettv) != FAIL)
682 win_findbuf(argvars, rettv->vval.v_list);
683}
684
685/*
686 * "win_getid()" function
687 */
688 void
689f_win_getid(typval_T *argvars, typval_T *rettv)
690{
691 rettv->vval.v_number = win_getid(argvars);
692}
693
694/*
695 * "win_gotoid()" function
696 */
697 void
698f_win_gotoid(typval_T *argvars, typval_T *rettv)
699{
Bram Moolenaara046b372019-09-15 17:26:07 +0200700 win_T *wp;
701 tabpage_T *tp;
702 int id = tv_get_number(&argvars[0]);
703
704#ifdef FEAT_CMDWIN
705 if (cmdwin_type != 0)
706 {
707 emsg(_(e_cmdwin));
708 return;
709 }
710#endif
711 FOR_ALL_TAB_WINDOWS(tp, wp)
712 if (wp->w_id == id)
713 {
714 goto_tabpage_win(tp, wp);
715 rettv->vval.v_number = 1;
716 return;
717 }
Bram Moolenaar261f3462019-09-07 15:45:32 +0200718}
719
720/*
721 * "win_id2tabwin()" function
722 */
723 void
724f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
725{
726 if (rettv_list_alloc(rettv) != FAIL)
727 win_id2tabwin(argvars, rettv->vval.v_list);
728}
729
730/*
731 * "win_id2win()" function
732 */
733 void
734f_win_id2win(typval_T *argvars, typval_T *rettv)
735{
736 rettv->vval.v_number = win_id2win(argvars);
737}
738
739/*
740 * "win_screenpos()" function
741 */
742 void
743f_win_screenpos(typval_T *argvars, typval_T *rettv)
744{
745 win_T *wp;
746
747 if (rettv_list_alloc(rettv) == FAIL)
748 return;
749
750 wp = find_win_by_nr_or_id(&argvars[0]);
751 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1);
752 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1);
753}
754
755/*
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200756 * Move the window wp into a new split of targetwin in a given direction
757 */
758 static void
759win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
760{
761 int dir;
762 int height = wp->w_height;
763 win_T *oldwin = curwin;
764
765 if (wp == targetwin)
766 return;
767
768 // Jump to the target window
769 if (curwin != targetwin)
770 win_goto(targetwin);
771
772 // Remove the old window and frame from the tree of frames
773 (void)winframe_remove(wp, &dir, NULL);
774 win_remove(wp, NULL);
775 last_status(FALSE); // may need to remove last status line
776 (void)win_comp_pos(); // recompute window positions
777
778 // Split a window on the desired side and put the old window there
779 (void)win_split_ins(size, flags, wp, dir);
780
781 // If splitting horizontally, try to preserve height
782 if (size == 0 && !(flags & WSP_VERT))
783 {
784 win_setheight_win(height, wp);
785 if (p_ea)
786 win_equal(wp, TRUE, 'v');
787 }
788
789#if defined(FEAT_GUI)
790 // When 'guioptions' includes 'L' or 'R' may have to remove or add
791 // scrollbars. Have to update them anyway.
792 gui_may_update_scrollbars();
793#endif
794
795 if (oldwin != curwin)
796 win_goto(oldwin);
797}
798
799/*
800 * "win_splitmove()" function
801 */
802 void
803f_win_splitmove(typval_T *argvars, typval_T *rettv)
804{
805 win_T *wp;
806 win_T *targetwin;
807 int flags = 0, size = 0;
808
809 wp = find_win_by_nr_or_id(&argvars[0]);
810 targetwin = find_win_by_nr_or_id(&argvars[1]);
811
Bram Moolenaar7b94e772020-01-06 21:03:24 +0100812 if (wp == NULL || targetwin == NULL || wp == targetwin
813 || !win_valid(wp) || !win_valid(targetwin))
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200814 {
815 emsg(_(e_invalwindow));
816 rettv->vval.v_number = -1;
817 return;
818 }
819
820 if (argvars[2].v_type != VAR_UNKNOWN)
821 {
822 dict_T *d;
823 dictitem_T *di;
824
825 if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL)
826 {
827 emsg(_(e_invarg));
828 return;
829 }
830
831 d = argvars[2].vval.v_dict;
832 if (dict_get_number(d, (char_u *)"vertical"))
833 flags |= WSP_VERT;
834 if ((di = dict_find(d, (char_u *)"rightbelow", -1)) != NULL)
835 flags |= tv_get_number(&di->di_tv) ? WSP_BELOW : WSP_ABOVE;
836 size = (int)dict_get_number(d, (char_u *)"size");
837 }
838
839 win_move_into_split(wp, targetwin, size, flags);
840}
841
842/*
Bram Moolenaar261f3462019-09-07 15:45:32 +0200843 * "winbufnr(nr)" function
844 */
845 void
846f_winbufnr(typval_T *argvars, typval_T *rettv)
847{
848 win_T *wp;
849
850 wp = find_win_by_nr_or_id(&argvars[0]);
851 if (wp == NULL)
852 rettv->vval.v_number = -1;
853 else
854 rettv->vval.v_number = wp->w_buffer->b_fnum;
855}
856
857/*
858 * "wincol()" function
859 */
860 void
861f_wincol(typval_T *argvars UNUSED, typval_T *rettv)
862{
863 validate_cursor();
864 rettv->vval.v_number = curwin->w_wcol + 1;
865}
866
867/*
868 * "winheight(nr)" function
869 */
870 void
871f_winheight(typval_T *argvars, typval_T *rettv)
872{
873 win_T *wp;
874
875 wp = find_win_by_nr_or_id(&argvars[0]);
876 if (wp == NULL)
877 rettv->vval.v_number = -1;
878 else
879 rettv->vval.v_number = wp->w_height;
880}
881
882/*
883 * "winlayout()" function
884 */
885 void
886f_winlayout(typval_T *argvars, typval_T *rettv)
887{
888 tabpage_T *tp;
889
890 if (rettv_list_alloc(rettv) != OK)
891 return;
892
893 if (argvars[0].v_type == VAR_UNKNOWN)
894 tp = curtab;
895 else
896 {
897 tp = find_tabpage((int)tv_get_number(&argvars[0]));
898 if (tp == NULL)
899 return;
900 }
901
902 get_framelayout(tp->tp_topframe, rettv->vval.v_list, TRUE);
903}
904
905/*
906 * "winline()" function
907 */
908 void
909f_winline(typval_T *argvars UNUSED, typval_T *rettv)
910{
911 validate_cursor();
912 rettv->vval.v_number = curwin->w_wrow + 1;
913}
914
915/*
916 * "winnr()" function
917 */
918 void
919f_winnr(typval_T *argvars UNUSED, typval_T *rettv)
920{
921 int nr = 1;
922
923 nr = get_winnr(curtab, &argvars[0]);
924 rettv->vval.v_number = nr;
925}
926
927/*
928 * "winrestcmd()" function
929 */
930 void
931f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv)
932{
933 win_T *wp;
934 int winnr = 1;
935 garray_T ga;
936 char_u buf[50];
937
938 ga_init2(&ga, (int)sizeof(char), 70);
939 FOR_ALL_WINDOWS(wp)
940 {
941 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
942 ga_concat(&ga, buf);
943 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
944 ga_concat(&ga, buf);
945 ++winnr;
946 }
947 ga_append(&ga, NUL);
948
949 rettv->vval.v_string = ga.ga_data;
950 rettv->v_type = VAR_STRING;
951}
952
953/*
954 * "winrestview()" function
955 */
956 void
957f_winrestview(typval_T *argvars, typval_T *rettv UNUSED)
958{
959 dict_T *dict;
960
961 if (argvars[0].v_type != VAR_DICT
962 || (dict = argvars[0].vval.v_dict) == NULL)
963 emsg(_(e_invarg));
964 else
965 {
966 if (dict_find(dict, (char_u *)"lnum", -1) != NULL)
967 curwin->w_cursor.lnum = (linenr_T)dict_get_number(dict, (char_u *)"lnum");
968 if (dict_find(dict, (char_u *)"col", -1) != NULL)
969 curwin->w_cursor.col = (colnr_T)dict_get_number(dict, (char_u *)"col");
970 if (dict_find(dict, (char_u *)"coladd", -1) != NULL)
971 curwin->w_cursor.coladd = (colnr_T)dict_get_number(dict, (char_u *)"coladd");
972 if (dict_find(dict, (char_u *)"curswant", -1) != NULL)
973 {
974 curwin->w_curswant = (colnr_T)dict_get_number(dict, (char_u *)"curswant");
975 curwin->w_set_curswant = FALSE;
976 }
977
978 if (dict_find(dict, (char_u *)"topline", -1) != NULL)
979 set_topline(curwin, (linenr_T)dict_get_number(dict, (char_u *)"topline"));
980#ifdef FEAT_DIFF
981 if (dict_find(dict, (char_u *)"topfill", -1) != NULL)
982 curwin->w_topfill = (int)dict_get_number(dict, (char_u *)"topfill");
983#endif
984 if (dict_find(dict, (char_u *)"leftcol", -1) != NULL)
985 curwin->w_leftcol = (colnr_T)dict_get_number(dict, (char_u *)"leftcol");
986 if (dict_find(dict, (char_u *)"skipcol", -1) != NULL)
987 curwin->w_skipcol = (colnr_T)dict_get_number(dict, (char_u *)"skipcol");
988
989 check_cursor();
990 win_new_height(curwin, curwin->w_height);
991 win_new_width(curwin, curwin->w_width);
992 changed_window_setting();
993
994 if (curwin->w_topline <= 0)
995 curwin->w_topline = 1;
996 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
997 curwin->w_topline = curbuf->b_ml.ml_line_count;
998#ifdef FEAT_DIFF
999 check_topfill(curwin, TRUE);
1000#endif
1001 }
1002}
1003
1004/*
1005 * "winsaveview()" function
1006 */
1007 void
1008f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv)
1009{
1010 dict_T *dict;
1011
1012 if (rettv_dict_alloc(rettv) == FAIL)
1013 return;
1014 dict = rettv->vval.v_dict;
1015
1016 dict_add_number(dict, "lnum", (long)curwin->w_cursor.lnum);
1017 dict_add_number(dict, "col", (long)curwin->w_cursor.col);
1018 dict_add_number(dict, "coladd", (long)curwin->w_cursor.coladd);
1019 update_curswant();
1020 dict_add_number(dict, "curswant", (long)curwin->w_curswant);
1021
1022 dict_add_number(dict, "topline", (long)curwin->w_topline);
1023#ifdef FEAT_DIFF
1024 dict_add_number(dict, "topfill", (long)curwin->w_topfill);
1025#endif
1026 dict_add_number(dict, "leftcol", (long)curwin->w_leftcol);
1027 dict_add_number(dict, "skipcol", (long)curwin->w_skipcol);
1028}
1029
1030/*
1031 * "winwidth(nr)" function
1032 */
1033 void
1034f_winwidth(typval_T *argvars, typval_T *rettv)
1035{
1036 win_T *wp;
1037
1038 wp = find_win_by_nr_or_id(&argvars[0]);
1039 if (wp == NULL)
1040 rettv->vval.v_number = -1;
1041 else
1042 rettv->vval.v_number = wp->w_width;
1043}
1044#endif // FEAT_EVAL
1045
1046#if defined(FEAT_EVAL) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
1047 || defined(PROTO)
1048/*
1049 * Set "win" to be the curwin and "tp" to be the current tab page.
1050 * restore_win() MUST be called to undo, also when FAIL is returned.
1051 * No autocommands will be executed until restore_win() is called.
1052 * When "no_display" is TRUE the display won't be affected, no redraw is
1053 * triggered, another tabpage access is limited.
1054 * Returns FAIL if switching to "win" failed.
1055 */
1056 int
1057switch_win(
1058 win_T **save_curwin,
1059 tabpage_T **save_curtab,
1060 win_T *win,
1061 tabpage_T *tp,
1062 int no_display)
1063{
1064 block_autocmds();
1065 return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display);
1066}
1067
1068/*
1069 * As switch_win() but without blocking autocommands.
1070 */
1071 int
1072switch_win_noblock(
1073 win_T **save_curwin,
1074 tabpage_T **save_curtab,
1075 win_T *win,
1076 tabpage_T *tp,
1077 int no_display)
1078{
1079 *save_curwin = curwin;
1080 if (tp != NULL)
1081 {
1082 *save_curtab = curtab;
1083 if (no_display)
1084 {
1085 curtab->tp_firstwin = firstwin;
1086 curtab->tp_lastwin = lastwin;
1087 curtab = tp;
1088 firstwin = curtab->tp_firstwin;
1089 lastwin = curtab->tp_lastwin;
1090 }
1091 else
1092 goto_tabpage_tp(tp, FALSE, FALSE);
1093 }
1094 if (!win_valid(win))
1095 return FAIL;
1096 curwin = win;
1097 curbuf = curwin->w_buffer;
1098 return OK;
1099}
1100
1101/*
1102 * Restore current tabpage and window saved by switch_win(), if still valid.
1103 * When "no_display" is TRUE the display won't be affected, no redraw is
1104 * triggered.
1105 */
1106 void
1107restore_win(
1108 win_T *save_curwin,
1109 tabpage_T *save_curtab,
1110 int no_display)
1111{
1112 restore_win_noblock(save_curwin, save_curtab, no_display);
1113 unblock_autocmds();
1114}
1115
1116/*
1117 * As restore_win() but without unblocking autocommands.
1118 */
1119 void
1120restore_win_noblock(
1121 win_T *save_curwin,
1122 tabpage_T *save_curtab,
1123 int no_display)
1124{
1125 if (save_curtab != NULL && valid_tabpage(save_curtab))
1126 {
1127 if (no_display)
1128 {
1129 curtab->tp_firstwin = firstwin;
1130 curtab->tp_lastwin = lastwin;
1131 curtab = save_curtab;
1132 firstwin = curtab->tp_firstwin;
1133 lastwin = curtab->tp_lastwin;
1134 }
1135 else
1136 goto_tabpage_tp(save_curtab, FALSE, FALSE);
1137 }
1138 if (win_valid(save_curwin))
1139 {
1140 curwin = save_curwin;
1141 curbuf = curwin->w_buffer;
1142 }
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01001143# ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +02001144 else if (WIN_IS_POPUP(curwin))
1145 // original window was closed and now we're in a popup window: Go
1146 // to the first valid window.
1147 win_goto(firstwin);
1148# endif
1149}
1150#endif