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