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_PROP_POPUP 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_PROP_POPUP 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 * Returns NULL when not found. 203 */ 204 win_T * 205 find_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 * 219 find_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 264 get_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 314 get_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 * 389 get_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 * 431 get_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 462 f_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 497 f_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 539 f_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 567 f_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 587 f_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 606 f_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 632 f_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 649 f_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 { 659 pos_T curpos = wp->w_cursor; 660 661 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); 667 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; 671 } 672 } 673 674 /* 675 * "win_findbuf()" function 676 */ 677 void 678 f_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 688 f_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 697 f_win_gotoid(typval_T *argvars, typval_T *rettv) 698 { 699 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 } 717 } 718 719 /* 720 * "win_id2tabwin()" function 721 */ 722 void 723 f_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 733 f_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 742 f_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 /* 755 * Move the window wp into a new split of targetwin in a given direction 756 */ 757 static void 758 win_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 802 f_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 /* 841 * "winbufnr(nr)" function 842 */ 843 void 844 f_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 859 f_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 869 f_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 884 f_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 907 f_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 917 f_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 929 f_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 955 f_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 1006 f_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 1032 f_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 1055 switch_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 1070 switch_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 1105 restore_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 1118 restore_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 } 1141 # ifdef FEAT_PROP_POPUP 1142 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 1149