blob: 34d202e0ad7712a53d4ef3566c8dc0d79cb910d1 [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
186 for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
187 if (wp->w_id == nr)
188 return wp;
189 // check global popup windows
190 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
191 if (wp->w_id == nr)
192 return wp;
193#endif
194 return NULL;
195 }
196 return wp;
197}
198
199/*
200 * Find a window: When using a Window ID in any tab page, when using a number
201 * in the current tab page.
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +0100202 * Returns NULL when not found.
Bram Moolenaar261f3462019-09-07 15:45:32 +0200203 */
204 win_T *
205find_win_by_nr_or_id(typval_T *vp)
206{
207 int nr = (int)tv_get_number_chk(vp, NULL);
208
209 if (nr >= LOWEST_WIN_ID)
210 return win_id2wp(tv_get_number(vp));
211 return find_win_by_nr(vp, NULL);
212}
213
214/*
215 * Find window specified by "wvp" in tabpage "tvp".
216 * Returns the tab page in 'ptp'
217 */
218 win_T *
219find_tabwin(
220 typval_T *wvp, // VAR_UNKNOWN for current window
221 typval_T *tvp, // VAR_UNKNOWN for current tab page
222 tabpage_T **ptp)
223{
224 win_T *wp = NULL;
225 tabpage_T *tp = NULL;
226 long n;
227
228 if (wvp->v_type != VAR_UNKNOWN)
229 {
230 if (tvp->v_type != VAR_UNKNOWN)
231 {
232 n = (long)tv_get_number(tvp);
233 if (n >= 0)
234 tp = find_tabpage(n);
235 }
236 else
237 tp = curtab;
238
239 if (tp != NULL)
240 {
241 wp = find_win_by_nr(wvp, tp);
242 if (wp == NULL && wvp->v_type == VAR_NUMBER
243 && wvp->vval.v_number != -1)
244 // A window with the specified number is not found
245 tp = NULL;
246 }
247 }
248 else
249 {
250 wp = curwin;
251 tp = curtab;
252 }
253
254 if (ptp != NULL)
255 *ptp = tp;
256
257 return wp;
258}
259
260/*
261 * Get the layout of the given tab page for winlayout().
262 */
263 static void
264get_framelayout(frame_T *fr, list_T *l, int outer)
265{
266 frame_T *child;
267 list_T *fr_list;
268 list_T *win_list;
269
270 if (fr == NULL)
271 return;
272
273 if (outer)
274 // outermost call from f_winlayout()
275 fr_list = l;
276 else
277 {
278 fr_list = list_alloc();
279 if (fr_list == NULL)
280 return;
281 list_append_list(l, fr_list);
282 }
283
284 if (fr->fr_layout == FR_LEAF)
285 {
286 if (fr->fr_win != NULL)
287 {
288 list_append_string(fr_list, (char_u *)"leaf", -1);
289 list_append_number(fr_list, fr->fr_win->w_id);
290 }
291 }
292 else
293 {
294 list_append_string(fr_list,
295 fr->fr_layout == FR_ROW ? (char_u *)"row" : (char_u *)"col", -1);
296
297 win_list = list_alloc();
298 if (win_list == NULL)
299 return;
300 list_append_list(fr_list, win_list);
301 child = fr->fr_child;
302 while (child != NULL)
303 {
304 get_framelayout(child, win_list, FALSE);
305 child = child->fr_next;
306 }
307 }
308}
309
310/*
311 * Common code for tabpagewinnr() and winnr().
312 */
313 static int
314get_winnr(tabpage_T *tp, typval_T *argvar)
315{
316 win_T *twin;
317 int nr = 1;
318 win_T *wp;
319 char_u *arg;
320
321 twin = (tp == curtab) ? curwin : tp->tp_curwin;
322 if (argvar->v_type != VAR_UNKNOWN)
323 {
324 int invalid_arg = FALSE;
325
326 arg = tv_get_string_chk(argvar);
327 if (arg == NULL)
328 nr = 0; // type error; errmsg already given
329 else if (STRCMP(arg, "$") == 0)
330 twin = (tp == curtab) ? lastwin : tp->tp_lastwin;
331 else if (STRCMP(arg, "#") == 0)
332 {
333 twin = (tp == curtab) ? prevwin : tp->tp_prevwin;
334 if (twin == NULL)
335 nr = 0;
336 }
337 else
338 {
339 long count;
340 char_u *endp;
341
342 // Extract the window count (if specified). e.g. winnr('3j')
343 count = strtol((char *)arg, (char **)&endp, 10);
344 if (count <= 0)
345 count = 1; // if count is not specified, default to 1
346 if (endp != NULL && *endp != '\0')
347 {
348 if (STRCMP(endp, "j") == 0)
349 twin = win_vert_neighbor(tp, twin, FALSE, count);
350 else if (STRCMP(endp, "k") == 0)
351 twin = win_vert_neighbor(tp, twin, TRUE, count);
352 else if (STRCMP(endp, "h") == 0)
353 twin = win_horz_neighbor(tp, twin, TRUE, count);
354 else if (STRCMP(endp, "l") == 0)
355 twin = win_horz_neighbor(tp, twin, FALSE, count);
356 else
357 invalid_arg = TRUE;
358 }
359 else
360 invalid_arg = TRUE;
361 }
362
363 if (invalid_arg)
364 {
365 semsg(_(e_invexpr2), arg);
366 nr = 0;
367 }
368 }
369
370 if (nr > 0)
371 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
372 wp != twin; wp = wp->w_next)
373 {
374 if (wp == NULL)
375 {
376 // didn't find it in this tabpage
377 nr = 0;
378 break;
379 }
380 ++nr;
381 }
382 return nr;
383}
384
385/*
386 * Returns information about a window as a dictionary.
387 */
388 static dict_T *
389get_win_info(win_T *wp, short tpnr, short winnr)
390{
391 dict_T *dict;
392
393 dict = dict_alloc();
394 if (dict == NULL)
395 return NULL;
396
397 dict_add_number(dict, "tabnr", tpnr);
398 dict_add_number(dict, "winnr", winnr);
399 dict_add_number(dict, "winid", wp->w_id);
400 dict_add_number(dict, "height", wp->w_height);
401 dict_add_number(dict, "winrow", wp->w_winrow + 1);
402 dict_add_number(dict, "topline", wp->w_topline);
403 dict_add_number(dict, "botline", wp->w_botline - 1);
404#ifdef FEAT_MENU
405 dict_add_number(dict, "winbar", wp->w_winbar_height);
406#endif
407 dict_add_number(dict, "width", wp->w_width);
408 dict_add_number(dict, "wincol", wp->w_wincol + 1);
409 dict_add_number(dict, "bufnr", wp->w_buffer->b_fnum);
410
411#ifdef FEAT_TERMINAL
412 dict_add_number(dict, "terminal", bt_terminal(wp->w_buffer));
413#endif
414#ifdef FEAT_QUICKFIX
415 dict_add_number(dict, "quickfix", bt_quickfix(wp->w_buffer));
416 dict_add_number(dict, "loclist",
417 (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL));
418#endif
419
420 // Add a reference to window variables
421 dict_add_dict(dict, "variables", wp->w_vars);
422
423 return dict;
424}
425
426/*
427 * Returns information (variables, options, etc.) about a tab page
428 * as a dictionary.
429 */
430 static dict_T *
431get_tabpage_info(tabpage_T *tp, int tp_idx)
432{
433 win_T *wp;
434 dict_T *dict;
435 list_T *l;
436
437 dict = dict_alloc();
438 if (dict == NULL)
439 return NULL;
440
441 dict_add_number(dict, "tabnr", tp_idx);
442
443 l = list_alloc();
444 if (l != NULL)
445 {
446 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
447 wp != NULL; wp = wp->w_next)
448 list_append_number(l, (varnumber_T)wp->w_id);
449 dict_add_list(dict, "windows", l);
450 }
451
452 // Make a reference to tabpage variables
453 dict_add_dict(dict, "variables", tp->tp_vars);
454
455 return dict;
456}
457
458/*
459 * "gettabinfo()" function
460 */
461 void
462f_gettabinfo(typval_T *argvars, typval_T *rettv)
463{
464 tabpage_T *tp, *tparg = NULL;
465 dict_T *d;
466 int tpnr = 0;
467
468 if (rettv_list_alloc(rettv) != OK)
469 return;
470
471 if (argvars[0].v_type != VAR_UNKNOWN)
472 {
473 // Information about one tab page
474 tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
475 if (tparg == NULL)
476 return;
477 }
478
479 // Get information about a specific tab page or all tab pages
480 FOR_ALL_TABPAGES(tp)
481 {
482 tpnr++;
483 if (tparg != NULL && tp != tparg)
484 continue;
485 d = get_tabpage_info(tp, tpnr);
486 if (d != NULL)
487 list_append_dict(rettv->vval.v_list, d);
488 if (tparg != NULL)
489 return;
490 }
491}
492
493/*
494 * "getwininfo()" function
495 */
496 void
497f_getwininfo(typval_T *argvars, typval_T *rettv)
498{
499 tabpage_T *tp;
500 win_T *wp = NULL, *wparg = NULL;
501 dict_T *d;
502 short tabnr = 0, winnr;
503
504 if (rettv_list_alloc(rettv) != OK)
505 return;
506
507 if (argvars[0].v_type != VAR_UNKNOWN)
508 {
509 wparg = win_id2wp(tv_get_number(&argvars[0]));
510 if (wparg == NULL)
511 return;
512 }
513
514 // Collect information about either all the windows across all the tab
515 // pages or one particular window.
516 FOR_ALL_TABPAGES(tp)
517 {
518 tabnr++;
519 winnr = 0;
520 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
521 {
522 winnr++;
523 if (wparg != NULL && wp != wparg)
524 continue;
525 d = get_win_info(wp, tabnr, winnr);
526 if (d != NULL)
527 list_append_dict(rettv->vval.v_list, d);
528 if (wparg != NULL)
529 // found information about a specific window
530 return;
531 }
532 }
533}
534
535/*
536 * "getwinpos({timeout})" function
537 */
538 void
539f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv)
540{
541 int x = -1;
542 int y = -1;
543
544 if (rettv_list_alloc(rettv) == FAIL)
545 return;
546#if defined(FEAT_GUI) \
547 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
548 || defined(MSWIN)
549 {
550 varnumber_T timeout = 100;
551
552 if (argvars[0].v_type != VAR_UNKNOWN)
553 timeout = tv_get_number(&argvars[0]);
554
555 (void)ui_get_winpos(&x, &y, timeout);
556 }
557#endif
558 list_append_number(rettv->vval.v_list, (varnumber_T)x);
559 list_append_number(rettv->vval.v_list, (varnumber_T)y);
560}
561
562
563/*
564 * "getwinposx()" function
565 */
566 void
567f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
568{
569 rettv->vval.v_number = -1;
570#if defined(FEAT_GUI) \
571 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
572 || defined(MSWIN)
573
574 {
575 int x, y;
576
577 if (ui_get_winpos(&x, &y, 100) == OK)
578 rettv->vval.v_number = x;
579 }
580#endif
581}
582
583/*
584 * "getwinposy()" function
585 */
586 void
587f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
588{
589 rettv->vval.v_number = -1;
590#if defined(FEAT_GUI) \
591 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) \
592 || defined(MSWIN)
593 {
594 int x, y;
595
596 if (ui_get_winpos(&x, &y, 100) == OK)
597 rettv->vval.v_number = y;
598 }
599#endif
600}
601
602/*
603 * "tabpagenr()" function
604 */
605 void
606f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
607{
608 int nr = 1;
609 char_u *arg;
610
611 if (argvars[0].v_type != VAR_UNKNOWN)
612 {
613 arg = tv_get_string_chk(&argvars[0]);
614 nr = 0;
615 if (arg != NULL)
616 {
617 if (STRCMP(arg, "$") == 0)
618 nr = tabpage_index(NULL) - 1;
619 else
620 semsg(_(e_invexpr2), arg);
621 }
622 }
623 else
624 nr = tabpage_index(curtab);
625 rettv->vval.v_number = nr;
626}
627
628/*
629 * "tabpagewinnr()" function
630 */
631 void
632f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv)
633{
634 int nr = 1;
635 tabpage_T *tp;
636
637 tp = find_tabpage((int)tv_get_number(&argvars[0]));
638 if (tp == NULL)
639 nr = 0;
640 else
641 nr = get_winnr(tp, &argvars[1]);
642 rettv->vval.v_number = nr;
643}
644
645/*
646 * "win_execute()" function
647 */
648 void
649f_win_execute(typval_T *argvars, typval_T *rettv)
650{
651 int id = (int)tv_get_number(argvars);
652 tabpage_T *tp;
653 win_T *wp = win_id2wp_tp(id, &tp);
654 win_T *save_curwin;
655 tabpage_T *save_curtab;
656
657 if (wp != NULL && tp != NULL)
658 {
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200659 pos_T curpos = wp->w_cursor;
660
Bram Moolenaar261f3462019-09-07 15:45:32 +0200661 if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, TRUE) == OK)
662 {
663 check_cursor();
664 execute_common(argvars, rettv, 1);
665 }
666 restore_win_noblock(save_curwin, save_curtab, TRUE);
Bram Moolenaar345f28d2019-10-08 22:20:35 +0200667
668 // Update the status line if the cursor moved.
669 if (win_valid(wp) && !EQUAL_POS(curpos, wp->w_cursor))
670 wp->w_redr_status = TRUE;
Bram Moolenaar261f3462019-09-07 15:45:32 +0200671 }
672}
673
674/*
675 * "win_findbuf()" function
676 */
677 void
678f_win_findbuf(typval_T *argvars, typval_T *rettv)
679{
680 if (rettv_list_alloc(rettv) != FAIL)
681 win_findbuf(argvars, rettv->vval.v_list);
682}
683
684/*
685 * "win_getid()" function
686 */
687 void
688f_win_getid(typval_T *argvars, typval_T *rettv)
689{
690 rettv->vval.v_number = win_getid(argvars);
691}
692
693/*
694 * "win_gotoid()" function
695 */
696 void
697f_win_gotoid(typval_T *argvars, typval_T *rettv)
698{
Bram Moolenaara046b372019-09-15 17:26:07 +0200699 win_T *wp;
700 tabpage_T *tp;
701 int id = tv_get_number(&argvars[0]);
702
703#ifdef FEAT_CMDWIN
704 if (cmdwin_type != 0)
705 {
706 emsg(_(e_cmdwin));
707 return;
708 }
709#endif
710 FOR_ALL_TAB_WINDOWS(tp, wp)
711 if (wp->w_id == id)
712 {
713 goto_tabpage_win(tp, wp);
714 rettv->vval.v_number = 1;
715 return;
716 }
Bram Moolenaar261f3462019-09-07 15:45:32 +0200717}
718
719/*
720 * "win_id2tabwin()" function
721 */
722 void
723f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
724{
725 if (rettv_list_alloc(rettv) != FAIL)
726 win_id2tabwin(argvars, rettv->vval.v_list);
727}
728
729/*
730 * "win_id2win()" function
731 */
732 void
733f_win_id2win(typval_T *argvars, typval_T *rettv)
734{
735 rettv->vval.v_number = win_id2win(argvars);
736}
737
738/*
739 * "win_screenpos()" function
740 */
741 void
742f_win_screenpos(typval_T *argvars, typval_T *rettv)
743{
744 win_T *wp;
745
746 if (rettv_list_alloc(rettv) == FAIL)
747 return;
748
749 wp = find_win_by_nr_or_id(&argvars[0]);
750 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1);
751 list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1);
752}
753
754/*
Bram Moolenaard20dcb32019-09-10 21:22:58 +0200755 * Move the window wp into a new split of targetwin in a given direction
756 */
757 static void
758win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
759{
760 int dir;
761 int height = wp->w_height;
762 win_T *oldwin = curwin;
763
764 if (wp == targetwin)
765 return;
766
767 // Jump to the target window
768 if (curwin != targetwin)
769 win_goto(targetwin);
770
771 // Remove the old window and frame from the tree of frames
772 (void)winframe_remove(wp, &dir, NULL);
773 win_remove(wp, NULL);
774 last_status(FALSE); // may need to remove last status line
775 (void)win_comp_pos(); // recompute window positions
776
777 // Split a window on the desired side and put the old window there
778 (void)win_split_ins(size, flags, wp, dir);
779
780 // If splitting horizontally, try to preserve height
781 if (size == 0 && !(flags & WSP_VERT))
782 {
783 win_setheight_win(height, wp);
784 if (p_ea)
785 win_equal(wp, TRUE, 'v');
786 }
787
788#if defined(FEAT_GUI)
789 // When 'guioptions' includes 'L' or 'R' may have to remove or add
790 // scrollbars. Have to update them anyway.
791 gui_may_update_scrollbars();
792#endif
793
794 if (oldwin != curwin)
795 win_goto(oldwin);
796}
797
798/*
799 * "win_splitmove()" function
800 */
801 void
802f_win_splitmove(typval_T *argvars, typval_T *rettv)
803{
804 win_T *wp;
805 win_T *targetwin;
806 int flags = 0, size = 0;
807
808 wp = find_win_by_nr_or_id(&argvars[0]);
809 targetwin = find_win_by_nr_or_id(&argvars[1]);
810
811 if (wp == NULL || targetwin == NULL || wp == targetwin)
812 {
813 emsg(_(e_invalwindow));
814 rettv->vval.v_number = -1;
815 return;
816 }
817
818 if (argvars[2].v_type != VAR_UNKNOWN)
819 {
820 dict_T *d;
821 dictitem_T *di;
822
823 if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL)
824 {
825 emsg(_(e_invarg));
826 return;
827 }
828
829 d = argvars[2].vval.v_dict;
830 if (dict_get_number(d, (char_u *)"vertical"))
831 flags |= WSP_VERT;
832 if ((di = dict_find(d, (char_u *)"rightbelow", -1)) != NULL)
833 flags |= tv_get_number(&di->di_tv) ? WSP_BELOW : WSP_ABOVE;
834 size = (int)dict_get_number(d, (char_u *)"size");
835 }
836
837 win_move_into_split(wp, targetwin, size, flags);
838}
839
840/*
Bram Moolenaar261f3462019-09-07 15:45:32 +0200841 * "winbufnr(nr)" function
842 */
843 void
844f_winbufnr(typval_T *argvars, typval_T *rettv)
845{
846 win_T *wp;
847
848 wp = find_win_by_nr_or_id(&argvars[0]);
849 if (wp == NULL)
850 rettv->vval.v_number = -1;
851 else
852 rettv->vval.v_number = wp->w_buffer->b_fnum;
853}
854
855/*
856 * "wincol()" function
857 */
858 void
859f_wincol(typval_T *argvars UNUSED, typval_T *rettv)
860{
861 validate_cursor();
862 rettv->vval.v_number = curwin->w_wcol + 1;
863}
864
865/*
866 * "winheight(nr)" function
867 */
868 void
869f_winheight(typval_T *argvars, typval_T *rettv)
870{
871 win_T *wp;
872
873 wp = find_win_by_nr_or_id(&argvars[0]);
874 if (wp == NULL)
875 rettv->vval.v_number = -1;
876 else
877 rettv->vval.v_number = wp->w_height;
878}
879
880/*
881 * "winlayout()" function
882 */
883 void
884f_winlayout(typval_T *argvars, typval_T *rettv)
885{
886 tabpage_T *tp;
887
888 if (rettv_list_alloc(rettv) != OK)
889 return;
890
891 if (argvars[0].v_type == VAR_UNKNOWN)
892 tp = curtab;
893 else
894 {
895 tp = find_tabpage((int)tv_get_number(&argvars[0]));
896 if (tp == NULL)
897 return;
898 }
899
900 get_framelayout(tp->tp_topframe, rettv->vval.v_list, TRUE);
901}
902
903/*
904 * "winline()" function
905 */
906 void
907f_winline(typval_T *argvars UNUSED, typval_T *rettv)
908{
909 validate_cursor();
910 rettv->vval.v_number = curwin->w_wrow + 1;
911}
912
913/*
914 * "winnr()" function
915 */
916 void
917f_winnr(typval_T *argvars UNUSED, typval_T *rettv)
918{
919 int nr = 1;
920
921 nr = get_winnr(curtab, &argvars[0]);
922 rettv->vval.v_number = nr;
923}
924
925/*
926 * "winrestcmd()" function
927 */
928 void
929f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv)
930{
931 win_T *wp;
932 int winnr = 1;
933 garray_T ga;
934 char_u buf[50];
935
936 ga_init2(&ga, (int)sizeof(char), 70);
937 FOR_ALL_WINDOWS(wp)
938 {
939 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
940 ga_concat(&ga, buf);
941 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
942 ga_concat(&ga, buf);
943 ++winnr;
944 }
945 ga_append(&ga, NUL);
946
947 rettv->vval.v_string = ga.ga_data;
948 rettv->v_type = VAR_STRING;
949}
950
951/*
952 * "winrestview()" function
953 */
954 void
955f_winrestview(typval_T *argvars, typval_T *rettv UNUSED)
956{
957 dict_T *dict;
958
959 if (argvars[0].v_type != VAR_DICT
960 || (dict = argvars[0].vval.v_dict) == NULL)
961 emsg(_(e_invarg));
962 else
963 {
964 if (dict_find(dict, (char_u *)"lnum", -1) != NULL)
965 curwin->w_cursor.lnum = (linenr_T)dict_get_number(dict, (char_u *)"lnum");
966 if (dict_find(dict, (char_u *)"col", -1) != NULL)
967 curwin->w_cursor.col = (colnr_T)dict_get_number(dict, (char_u *)"col");
968 if (dict_find(dict, (char_u *)"coladd", -1) != NULL)
969 curwin->w_cursor.coladd = (colnr_T)dict_get_number(dict, (char_u *)"coladd");
970 if (dict_find(dict, (char_u *)"curswant", -1) != NULL)
971 {
972 curwin->w_curswant = (colnr_T)dict_get_number(dict, (char_u *)"curswant");
973 curwin->w_set_curswant = FALSE;
974 }
975
976 if (dict_find(dict, (char_u *)"topline", -1) != NULL)
977 set_topline(curwin, (linenr_T)dict_get_number(dict, (char_u *)"topline"));
978#ifdef FEAT_DIFF
979 if (dict_find(dict, (char_u *)"topfill", -1) != NULL)
980 curwin->w_topfill = (int)dict_get_number(dict, (char_u *)"topfill");
981#endif
982 if (dict_find(dict, (char_u *)"leftcol", -1) != NULL)
983 curwin->w_leftcol = (colnr_T)dict_get_number(dict, (char_u *)"leftcol");
984 if (dict_find(dict, (char_u *)"skipcol", -1) != NULL)
985 curwin->w_skipcol = (colnr_T)dict_get_number(dict, (char_u *)"skipcol");
986
987 check_cursor();
988 win_new_height(curwin, curwin->w_height);
989 win_new_width(curwin, curwin->w_width);
990 changed_window_setting();
991
992 if (curwin->w_topline <= 0)
993 curwin->w_topline = 1;
994 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
995 curwin->w_topline = curbuf->b_ml.ml_line_count;
996#ifdef FEAT_DIFF
997 check_topfill(curwin, TRUE);
998#endif
999 }
1000}
1001
1002/*
1003 * "winsaveview()" function
1004 */
1005 void
1006f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv)
1007{
1008 dict_T *dict;
1009
1010 if (rettv_dict_alloc(rettv) == FAIL)
1011 return;
1012 dict = rettv->vval.v_dict;
1013
1014 dict_add_number(dict, "lnum", (long)curwin->w_cursor.lnum);
1015 dict_add_number(dict, "col", (long)curwin->w_cursor.col);
1016 dict_add_number(dict, "coladd", (long)curwin->w_cursor.coladd);
1017 update_curswant();
1018 dict_add_number(dict, "curswant", (long)curwin->w_curswant);
1019
1020 dict_add_number(dict, "topline", (long)curwin->w_topline);
1021#ifdef FEAT_DIFF
1022 dict_add_number(dict, "topfill", (long)curwin->w_topfill);
1023#endif
1024 dict_add_number(dict, "leftcol", (long)curwin->w_leftcol);
1025 dict_add_number(dict, "skipcol", (long)curwin->w_skipcol);
1026}
1027
1028/*
1029 * "winwidth(nr)" function
1030 */
1031 void
1032f_winwidth(typval_T *argvars, typval_T *rettv)
1033{
1034 win_T *wp;
1035
1036 wp = find_win_by_nr_or_id(&argvars[0]);
1037 if (wp == NULL)
1038 rettv->vval.v_number = -1;
1039 else
1040 rettv->vval.v_number = wp->w_width;
1041}
1042#endif // FEAT_EVAL
1043
1044#if defined(FEAT_EVAL) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
1045 || defined(PROTO)
1046/*
1047 * Set "win" to be the curwin and "tp" to be the current tab page.
1048 * restore_win() MUST be called to undo, also when FAIL is returned.
1049 * No autocommands will be executed until restore_win() is called.
1050 * When "no_display" is TRUE the display won't be affected, no redraw is
1051 * triggered, another tabpage access is limited.
1052 * Returns FAIL if switching to "win" failed.
1053 */
1054 int
1055switch_win(
1056 win_T **save_curwin,
1057 tabpage_T **save_curtab,
1058 win_T *win,
1059 tabpage_T *tp,
1060 int no_display)
1061{
1062 block_autocmds();
1063 return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display);
1064}
1065
1066/*
1067 * As switch_win() but without blocking autocommands.
1068 */
1069 int
1070switch_win_noblock(
1071 win_T **save_curwin,
1072 tabpage_T **save_curtab,
1073 win_T *win,
1074 tabpage_T *tp,
1075 int no_display)
1076{
1077 *save_curwin = curwin;
1078 if (tp != NULL)
1079 {
1080 *save_curtab = curtab;
1081 if (no_display)
1082 {
1083 curtab->tp_firstwin = firstwin;
1084 curtab->tp_lastwin = lastwin;
1085 curtab = tp;
1086 firstwin = curtab->tp_firstwin;
1087 lastwin = curtab->tp_lastwin;
1088 }
1089 else
1090 goto_tabpage_tp(tp, FALSE, FALSE);
1091 }
1092 if (!win_valid(win))
1093 return FAIL;
1094 curwin = win;
1095 curbuf = curwin->w_buffer;
1096 return OK;
1097}
1098
1099/*
1100 * Restore current tabpage and window saved by switch_win(), if still valid.
1101 * When "no_display" is TRUE the display won't be affected, no redraw is
1102 * triggered.
1103 */
1104 void
1105restore_win(
1106 win_T *save_curwin,
1107 tabpage_T *save_curtab,
1108 int no_display)
1109{
1110 restore_win_noblock(save_curwin, save_curtab, no_display);
1111 unblock_autocmds();
1112}
1113
1114/*
1115 * As restore_win() but without unblocking autocommands.
1116 */
1117 void
1118restore_win_noblock(
1119 win_T *save_curwin,
1120 tabpage_T *save_curtab,
1121 int no_display)
1122{
1123 if (save_curtab != NULL && valid_tabpage(save_curtab))
1124 {
1125 if (no_display)
1126 {
1127 curtab->tp_firstwin = firstwin;
1128 curtab->tp_lastwin = lastwin;
1129 curtab = save_curtab;
1130 firstwin = curtab->tp_firstwin;
1131 lastwin = curtab->tp_lastwin;
1132 }
1133 else
1134 goto_tabpage_tp(save_curtab, FALSE, FALSE);
1135 }
1136 if (win_valid(save_curwin))
1137 {
1138 curwin = save_curwin;
1139 curbuf = curwin->w_buffer;
1140 }
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01001141# ifdef FEAT_PROP_POPUP
Bram Moolenaar261f3462019-09-07 15:45:32 +02001142 else if (WIN_IS_POPUP(curwin))
1143 // original window was closed and now we're in a popup window: Go
1144 // to the first valid window.
1145 win_goto(firstwin);
1146# endif
1147}
1148#endif