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