Mercurial > vim
comparison src/window.c @ 34383:a84fe48ae523 v9.1.0118
patch 9.1.0118: Use different restoration strategy in win_splitmove
Commit: https://github.com/vim/vim/commit/704966c2545897dfcf426dd9ef946aeb6fa80c38
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date: Tue Feb 20 22:00:33 2024 +0100
patch 9.1.0118: Use different restoration strategy in win_splitmove
Problem: saving and restoring all frames to split-move is overkill now
that WinNewPre is not fired when split-moving.
Solution: defer the flattening of frames until win_split_ins begins
reorganising them, and attempt to restore the layout by
undoing our changes. (Sean Dewar)
This also means we no longer must allocate.
related: #14042
Signed-off-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Tue, 20 Feb 2024 22:30:07 +0100 |
parents | 4e0da2b33607 |
children | 8b0e390b61fe |
comparison
equal
deleted
inserted
replaced
34382:17d926feeb82 | 34383:a84fe48ae523 |
---|---|
28 static void win_fix_scroll(int resize); | 28 static void win_fix_scroll(int resize); |
29 static void win_fix_cursor(int normal); | 29 static void win_fix_cursor(int normal); |
30 static void frame_new_height(frame_T *topfrp, int height, int topfirst, int wfh); | 30 static void frame_new_height(frame_T *topfrp, int height, int topfirst, int wfh); |
31 static int frame_fixed_height(frame_T *frp); | 31 static int frame_fixed_height(frame_T *frp); |
32 static int frame_fixed_width(frame_T *frp); | 32 static int frame_fixed_width(frame_T *frp); |
33 static void frame_add_statusline(frame_T *frp, int adjust_winheight); | 33 static void frame_add_statusline(frame_T *frp); |
34 static void frame_new_width(frame_T *topfrp, int width, int leftfirst, int wfw); | 34 static void frame_new_width(frame_T *topfrp, int width, int leftfirst, int wfw); |
35 static void frame_add_vsep(frame_T *frp); | 35 static void frame_add_vsep(frame_T *frp); |
36 static int frame_minwidth(frame_T *topfrp, win_T *next_curwin); | 36 static int frame_minwidth(frame_T *topfrp, win_T *next_curwin); |
37 static void frame_fix_width(win_T *wp); | 37 static void frame_fix_width(win_T *wp); |
38 static int win_alloc_firstwin(win_T *oldwin); | 38 static int win_alloc_firstwin(win_T *oldwin); |
51 static void frame_remove(frame_T *frp); | 51 static void frame_remove(frame_T *frp); |
52 static void win_goto_ver(int up, long count); | 52 static void win_goto_ver(int up, long count); |
53 static void win_goto_hor(int left, long count); | 53 static void win_goto_hor(int left, long count); |
54 static void frame_add_height(frame_T *frp, int n); | 54 static void frame_add_height(frame_T *frp, int n); |
55 static void last_status_rec(frame_T *fr, int statusline); | 55 static void last_status_rec(frame_T *fr, int statusline); |
56 | 56 static void frame_flatten(frame_T *frp); |
57 static int make_snapshot_rec(frame_T *fr, frame_T **frp, int snap_wins); | 57 static void winframe_restore(win_T *wp, int dir, frame_T *to_flatten); |
58 | |
59 static int make_snapshot_rec(frame_T *fr, frame_T **frp); | |
58 static void clear_snapshot(tabpage_T *tp, int idx); | 60 static void clear_snapshot(tabpage_T *tp, int idx); |
59 static void clear_snapshot_rec(frame_T *fr); | 61 static void clear_snapshot_rec(frame_T *fr); |
60 static int check_snapshot_rec(frame_T *sn, frame_T *fr); | 62 static int check_snapshot_rec(frame_T *sn, frame_T *fr); |
61 static win_T *restore_snapshot_rec(frame_T *sn, frame_T *fr); | 63 static win_T *restore_snapshot_rec(frame_T *sn, frame_T *fr); |
62 static win_T *get_snapshot_curwin(int idx); | 64 static win_T *get_snapshot_curwin(int idx); |
63 static frame_T *make_full_snapshot(void); | |
64 static void restore_full_snapshot(frame_T *sn); | |
65 static void restore_full_snapshot_rec(frame_T *sn); | |
66 | 65 |
67 static int frame_check_height(frame_T *topfrp, int height); | 66 static int frame_check_height(frame_T *topfrp, int height); |
68 static int frame_check_width(frame_T *topfrp, int width); | 67 static int frame_check_width(frame_T *topfrp, int width); |
69 | 68 |
70 static win_T *win_alloc(win_T *after, int hidden); | 69 static win_T *win_alloc(win_T *after, int hidden); |
926 if (flags & WSP_HELP) | 925 if (flags & WSP_HELP) |
927 make_snapshot(SNAP_HELP_IDX); | 926 make_snapshot(SNAP_HELP_IDX); |
928 else | 927 else |
929 clear_snapshot(curtab, SNAP_HELP_IDX); | 928 clear_snapshot(curtab, SNAP_HELP_IDX); |
930 | 929 |
931 return win_split_ins(size, flags, NULL, 0); | 930 return win_split_ins(size, flags, NULL, 0, NULL); |
932 } | 931 } |
933 | 932 |
934 /* | 933 /* |
935 * When "new_wp" is NULL: split the current window in two. | 934 * When "new_wp" is NULL: split the current window in two. |
936 * When "new_wp" is not NULL: insert this window at the far | 935 * When "new_wp" is not NULL: insert this window at the far |
937 * top/left/right/bottom. | 936 * top/left/right/bottom. |
937 * When "to_flatten" is not NULL: flatten this frame before reorganising frames; | |
938 * remains unflattened on failure. | |
939 * | |
938 * On failure, if "new_wp" was not NULL, no changes will have been made to the | 940 * On failure, if "new_wp" was not NULL, no changes will have been made to the |
939 * window layout or sizes. | 941 * window layout or sizes. |
940 * Return FAIL for failure, OK otherwise. | 942 * Return FAIL for failure, OK otherwise. |
941 */ | 943 */ |
942 int | 944 int |
943 win_split_ins( | 945 win_split_ins( |
944 int size, | 946 int size, |
945 int flags, | 947 int flags, |
946 win_T *new_wp, | 948 win_T *new_wp, |
947 int dir) | 949 int dir, |
950 frame_T *to_flatten) | |
948 { | 951 { |
949 win_T *wp = new_wp; | 952 win_T *wp = new_wp; |
950 win_T *oldwin; | 953 win_T *oldwin; |
951 int new_size = size; | 954 int new_size = size; |
952 int i; | 955 int i; |
1217 | 1220 |
1218 // make the contents of the new window the same as the current one | 1221 // make the contents of the new window the same as the current one |
1219 win_init(wp, curwin, flags); | 1222 win_init(wp, curwin, flags); |
1220 } | 1223 } |
1221 | 1224 |
1225 // Going to reorganize frames now, make sure they're flat. | |
1226 if (to_flatten != NULL) | |
1227 frame_flatten(to_flatten); | |
1228 | |
1222 /* | 1229 /* |
1223 * Reorganise the tree of frames to insert the new window. | 1230 * Reorganise the tree of frames to insert the new window. |
1224 */ | 1231 */ |
1225 if (flags & (WSP_TOP | WSP_BOT)) | 1232 if (flags & (WSP_TOP | WSP_BOT)) |
1226 { | 1233 { |
1369 + WINBAR_HEIGHT(wp) ; | 1376 + WINBAR_HEIGHT(wp) ; |
1370 | 1377 |
1371 if (!((flags & WSP_BOT) && p_ls == 0)) | 1378 if (!((flags & WSP_BOT) && p_ls == 0)) |
1372 new_fr_height -= STATUS_HEIGHT; | 1379 new_fr_height -= STATUS_HEIGHT; |
1373 if (flags & WSP_BOT) | 1380 if (flags & WSP_BOT) |
1374 frame_add_statusline(curfrp, FALSE); | 1381 frame_add_statusline(curfrp); |
1375 frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, FALSE); | 1382 frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, FALSE); |
1376 } | 1383 } |
1377 else | 1384 else |
1378 win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT)); | 1385 win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT)); |
1379 if (before) // new window above current one | 1386 if (before) // new window above current one |
1919 int | 1926 int |
1920 win_splitmove(win_T *wp, int size, int flags) | 1927 win_splitmove(win_T *wp, int size, int flags) |
1921 { | 1928 { |
1922 int dir; | 1929 int dir; |
1923 int height = wp->w_height; | 1930 int height = wp->w_height; |
1924 frame_T *frp; | 1931 frame_T *unflat_altfr; |
1925 | 1932 |
1926 if (ONE_WINDOW) | 1933 if (ONE_WINDOW) |
1927 return OK; // nothing to do | 1934 return OK; // nothing to do |
1928 if (check_split_disallowed(wp) == FAIL) | 1935 if (check_split_disallowed(wp) == FAIL) |
1929 return FAIL; | 1936 return FAIL; |
1930 | 1937 |
1931 // Undoing changes to frames if splitting fails is complicated. | 1938 // Remove the window and frame from the tree of frames. Don't flatten any |
1932 // Save a full snapshot to restore instead. | 1939 // frames yet so we can restore things if win_split_ins fails. |
1933 frp = make_full_snapshot(); | 1940 winframe_remove(wp, &dir, NULL, &unflat_altfr); |
1934 if (frp == NULL) | |
1935 { | |
1936 emsg(_(e_out_of_memory)); | |
1937 return FAIL; | |
1938 } | |
1939 | |
1940 // Remove the window and frame from the tree of frames. | |
1941 (void)winframe_remove(wp, &dir, NULL); | |
1942 win_remove(wp, NULL); | 1941 win_remove(wp, NULL); |
1943 last_status(FALSE); // may need to remove last status line | 1942 last_status(FALSE); // may need to remove last status line |
1944 (void)win_comp_pos(); // recompute window positions | 1943 (void)win_comp_pos(); // recompute window positions |
1945 | 1944 |
1946 // Split a window on the desired side and put "wp" there. | 1945 // Split a window on the desired side and put "wp" there. |
1947 if (win_split_ins(size, flags, wp, dir) == FAIL) | 1946 if (win_split_ins(size, flags, wp, dir, unflat_altfr) == FAIL) |
1948 { | 1947 { |
1949 // Restore the previous layout from the snapshot. | 1948 // win_split_ins doesn't change sizes or layout if it fails to insert an |
1950 vim_free(wp->w_frame); | 1949 // existing window, so just undo winframe_remove. |
1951 restore_full_snapshot(frp); | 1950 winframe_restore(wp, dir, unflat_altfr); |
1952 | |
1953 // Vertical separators to the left may have been lost. Restore them. | |
1954 frp = wp->w_frame; | |
1955 if (frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL) | |
1956 frame_add_vsep(frp->fr_prev); | |
1957 | |
1958 // Statuslines above may have been lost. Restore them. | |
1959 if (frp->fr_parent->fr_layout == FR_COL && frp->fr_prev != NULL) | |
1960 frame_add_statusline(frp->fr_prev, TRUE); | |
1961 | |
1962 win_append(wp->w_prev, wp); | 1951 win_append(wp->w_prev, wp); |
1952 (void)win_comp_pos(); // recompute window positions | |
1963 return FAIL; | 1953 return FAIL; |
1964 } | 1954 } |
1965 clear_snapshot_rec(frp); | |
1966 | 1955 |
1967 // If splitting horizontally, try to preserve height. | 1956 // If splitting horizontally, try to preserve height. |
1968 if (size == 0 && !(flags & WSP_VERT)) | 1957 if (size == 0 && !(flags & WSP_VERT)) |
1969 { | 1958 { |
1970 win_setheight_win(height, wp); | 1959 win_setheight_win(height, wp); |
3410 win_T *wp; | 3399 win_T *wp; |
3411 tabpage_T *win_tp = tp == NULL ? curtab : tp; | 3400 tabpage_T *win_tp = tp == NULL ? curtab : tp; |
3412 | 3401 |
3413 // Remove the window and its frame from the tree of frames. | 3402 // Remove the window and its frame from the tree of frames. |
3414 frp = win->w_frame; | 3403 frp = win->w_frame; |
3415 wp = winframe_remove(win, dirp, tp); | 3404 wp = winframe_remove(win, dirp, tp, NULL); |
3416 vim_free(frp); | 3405 vim_free(frp); |
3417 win_free(win, tp); | 3406 win_free(win, tp); |
3418 | 3407 |
3419 // When deleting the current window in the tab, select a new current | 3408 // When deleting the current window in the tab, select a new current |
3420 // window. | 3409 // window. |
3460 */ | 3449 */ |
3461 win_T * | 3450 win_T * |
3462 winframe_remove( | 3451 winframe_remove( |
3463 win_T *win, | 3452 win_T *win, |
3464 int *dirp UNUSED, // set to 'v' or 'h' for direction if 'ea' | 3453 int *dirp UNUSED, // set to 'v' or 'h' for direction if 'ea' |
3465 tabpage_T *tp) // tab page "win" is in, NULL for current | 3454 tabpage_T *tp, // tab page "win" is in, NULL for current |
3455 frame_T **unflat_altfr) // if not NULL, set to pointer of frame that got | |
3456 // the space, and it is not flattened | |
3466 { | 3457 { |
3467 frame_T *frp, *frp2, *frp3; | 3458 frame_T *frp, *frp2, *frp3; |
3468 frame_T *frp_close = win->w_frame; | 3459 frame_T *frp_close = win->w_frame; |
3469 win_T *wp; | 3460 win_T *wp; |
3470 | 3461 |
3515 frp3 = frp3->fr_next; | 3506 frp3 = frp3->fr_next; |
3516 } | 3507 } |
3517 } | 3508 } |
3518 } | 3509 } |
3519 frame_new_height(frp2, frp2->fr_height + frp_close->fr_height, | 3510 frame_new_height(frp2, frp2->fr_height + frp_close->fr_height, |
3520 frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE); | 3511 frp2 == frp_close->fr_next, FALSE); |
3521 *dirp = 'v'; | 3512 *dirp = 'v'; |
3522 } | 3513 } |
3523 else | 3514 else |
3524 { | 3515 { |
3525 // When 'winfixwidth' is set, try to find another frame in the column | 3516 // When 'winfixwidth' is set, try to find another frame in the column |
3552 frp3 = frp3->fr_next; | 3543 frp3 = frp3->fr_next; |
3553 } | 3544 } |
3554 } | 3545 } |
3555 } | 3546 } |
3556 frame_new_width(frp2, frp2->fr_width + frp_close->fr_width, | 3547 frame_new_width(frp2, frp2->fr_width + frp_close->fr_width, |
3557 frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE); | 3548 frp2 == frp_close->fr_next, FALSE); |
3558 *dirp = 'h'; | 3549 *dirp = 'h'; |
3559 } | 3550 } |
3560 | 3551 |
3561 // If rows/columns go to a window below/right its positions need to be | 3552 // If rows/columns go to a window below/right its positions need to be |
3562 // updated. Can only be done after the sizes have been updated. | 3553 // updated. Can only be done after the sizes have been updated. |
3566 int col = win->w_wincol; | 3557 int col = win->w_wincol; |
3567 | 3558 |
3568 frame_comp_pos(frp2, &row, &col); | 3559 frame_comp_pos(frp2, &row, &col); |
3569 } | 3560 } |
3570 | 3561 |
3571 if (frp2->fr_next == NULL && frp2->fr_prev == NULL) | 3562 if (unflat_altfr == NULL) |
3572 { | 3563 frame_flatten(frp2); |
3573 // There is no other frame in this list, move its info to the parent | 3564 else |
3574 // and remove it. | 3565 *unflat_altfr = frp2; |
3575 frp2->fr_parent->fr_layout = frp2->fr_layout; | 3566 |
3576 frp2->fr_parent->fr_child = frp2->fr_child; | 3567 return wp; |
3577 FOR_ALL_FRAMES(frp, frp2->fr_child) | 3568 } |
3578 frp->fr_parent = frp2->fr_parent; | 3569 |
3579 frp2->fr_parent->fr_win = frp2->fr_win; | 3570 /* |
3580 if (frp2->fr_win != NULL) | 3571 * Flatten "frp" into its parent frame if it's the only child, also merging its |
3581 frp2->fr_win->w_frame = frp2->fr_parent; | 3572 * list with the grandparent if they share the same layout. |
3582 frp = frp2->fr_parent; | 3573 * Frees "frp" if flattened; also "frp->fr_parent" if it has the same layout. |
3574 * "frp" must be valid in the current tabpage. | |
3575 */ | |
3576 static void | |
3577 frame_flatten(frame_T *frp) | |
3578 { | |
3579 frame_T *frp2, *frp3; | |
3580 | |
3581 if (frp->fr_next != NULL || frp->fr_prev != NULL) | |
3582 return; | |
3583 | |
3584 // There is no other frame in this list, move its info to the parent | |
3585 // and remove it. | |
3586 frp->fr_parent->fr_layout = frp->fr_layout; | |
3587 frp->fr_parent->fr_child = frp->fr_child; | |
3588 FOR_ALL_FRAMES(frp2, frp->fr_child) | |
3589 frp2->fr_parent = frp->fr_parent; | |
3590 frp->fr_parent->fr_win = frp->fr_win; | |
3591 if (frp->fr_win != NULL) | |
3592 frp->fr_win->w_frame = frp->fr_parent; | |
3593 frp2 = frp->fr_parent; | |
3594 if (topframe->fr_child == frp) | |
3595 topframe->fr_child = frp2; | |
3596 vim_free(frp); | |
3597 | |
3598 frp = frp2->fr_parent; | |
3599 if (frp != NULL && frp->fr_layout == frp2->fr_layout) | |
3600 { | |
3601 // The frame above the parent has the same layout, have to merge | |
3602 // the frames into this list. | |
3603 if (frp->fr_child == frp2) | |
3604 frp->fr_child = frp2->fr_child; | |
3605 frp2->fr_child->fr_prev = frp2->fr_prev; | |
3606 if (frp2->fr_prev != NULL) | |
3607 frp2->fr_prev->fr_next = frp2->fr_child; | |
3608 for (frp3 = frp2->fr_child; ; frp3 = frp3->fr_next) | |
3609 { | |
3610 frp3->fr_parent = frp; | |
3611 if (frp3->fr_next == NULL) | |
3612 { | |
3613 frp3->fr_next = frp2->fr_next; | |
3614 if (frp2->fr_next != NULL) | |
3615 frp2->fr_next->fr_prev = frp3; | |
3616 break; | |
3617 } | |
3618 } | |
3583 if (topframe->fr_child == frp2) | 3619 if (topframe->fr_child == frp2) |
3584 topframe->fr_child = frp; | 3620 topframe->fr_child = frp; |
3585 vim_free(frp2); | 3621 vim_free(frp2); |
3586 | 3622 } |
3587 frp2 = frp->fr_parent; | 3623 } |
3588 if (frp2 != NULL && frp2->fr_layout == frp->fr_layout) | 3624 |
3589 { | 3625 /* |
3590 // The frame above the parent has the same layout, have to merge | 3626 * Undo changes from a prior call to winframe_remove, also restoring lost |
3591 // the frames into this list. | 3627 * vertical separators and statuslines. |
3592 if (frp2->fr_child == frp) | 3628 * Caller must ensure no other changes were made to the layout or window sizes! |
3593 frp2->fr_child = frp->fr_child; | 3629 */ |
3594 frp->fr_child->fr_prev = frp->fr_prev; | 3630 static void |
3595 if (frp->fr_prev != NULL) | 3631 winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr) |
3596 frp->fr_prev->fr_next = frp->fr_child; | 3632 { |
3597 for (frp3 = frp->fr_child; ; frp3 = frp3->fr_next) | 3633 frame_T *frp = wp->w_frame; |
3598 { | 3634 |
3599 frp3->fr_parent = frp2; | 3635 // Put "wp"'s frame back where it was. |
3600 if (frp3->fr_next == NULL) | 3636 if (frp->fr_prev != NULL) |
3601 { | 3637 frame_append(frp->fr_prev, frp); |
3602 frp3->fr_next = frp->fr_next; | 3638 else |
3603 if (frp->fr_next != NULL) | 3639 frame_insert(frp->fr_next, frp); |
3604 frp->fr_next->fr_prev = frp3; | 3640 |
3605 break; | 3641 // Vertical separators to the left may have been lost. Restore them. |
3606 } | 3642 if (wp->w_vsep_width == 0 |
3607 } | 3643 && frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL) |
3608 if (topframe->fr_child == frp) | 3644 frame_add_vsep(frp->fr_prev); |
3609 topframe->fr_child = frp2; | 3645 |
3610 vim_free(frp); | 3646 // Statuslines above may have been lost. Restore them. |
3611 } | 3647 if (wp->w_status_height == 0 |
3612 } | 3648 && frp->fr_parent->fr_layout == FR_COL && frp->fr_prev != NULL) |
3613 | 3649 frame_add_statusline(frp->fr_prev); |
3614 return wp; | 3650 |
3651 // Restore the lost room that was redistributed to the altframe. | |
3652 if (dir == 'v') | |
3653 { | |
3654 frame_new_height(unflat_altfr, unflat_altfr->fr_height - frp->fr_height, | |
3655 unflat_altfr == frp->fr_next, FALSE); | |
3656 } | |
3657 else if (dir == 'h') | |
3658 { | |
3659 frame_new_width(unflat_altfr, unflat_altfr->fr_width - frp->fr_width, | |
3660 unflat_altfr == frp->fr_next, FALSE); | |
3661 } | |
3615 } | 3662 } |
3616 | 3663 |
3617 /* | 3664 /* |
3618 * Return a pointer to the frame that will receive the empty screen space that | 3665 * Return a pointer to the frame that will receive the empty screen space that |
3619 * is left over after "win" is closed. | 3666 * is left over after "win" is closed. |
3893 return TRUE; | 3940 return TRUE; |
3894 } | 3941 } |
3895 | 3942 |
3896 /* | 3943 /* |
3897 * Add a status line to windows at the bottom of "frp". | 3944 * Add a status line to windows at the bottom of "frp". |
3898 * If "adjust_winheight" is set, reduce the height of windows without a | 3945 * Note: Does not check if there is room! |
3899 * statusline to accommodate one; otherwise, there is no check for room! | |
3900 */ | 3946 */ |
3901 static void | 3947 static void |
3902 frame_add_statusline(frame_T *frp, int adjust_winheight) | 3948 frame_add_statusline(frame_T *frp) |
3903 { | 3949 { |
3904 win_T *wp; | 3950 win_T *wp; |
3905 | 3951 |
3906 if (frp->fr_layout == FR_LEAF) | 3952 if (frp->fr_layout == FR_LEAF) |
3907 { | 3953 { |
3908 wp = frp->fr_win; | 3954 wp = frp->fr_win; |
3909 if (adjust_winheight && wp->w_status_height == 0 | |
3910 && wp->w_height >= STATUS_HEIGHT) // don't make it negative | |
3911 wp->w_height -= STATUS_HEIGHT - wp->w_status_height; | |
3912 wp->w_status_height = STATUS_HEIGHT; | 3955 wp->w_status_height = STATUS_HEIGHT; |
3913 } | 3956 } |
3914 else if (frp->fr_layout == FR_ROW) | 3957 else if (frp->fr_layout == FR_ROW) |
3915 { | 3958 { |
3916 // Handle all the frames in the row. | 3959 // Handle all the frames in the row. |
3917 FOR_ALL_FRAMES(frp, frp->fr_child) | 3960 FOR_ALL_FRAMES(frp, frp->fr_child) |
3918 frame_add_statusline(frp, adjust_winheight); | 3961 frame_add_statusline(frp); |
3919 } | 3962 } |
3920 else // frp->fr_layout == FR_COL | 3963 else // frp->fr_layout == FR_COL |
3921 { | 3964 { |
3922 // Only need to handle the last frame in the column. | 3965 // Only need to handle the last frame in the column. |
3923 for (frp = frp->fr_child; frp->fr_next != NULL; frp = frp->fr_next) | 3966 for (frp = frp->fr_child; frp->fr_next != NULL; frp = frp->fr_next) |
3924 ; | 3967 ; |
3925 frame_add_statusline(frp, adjust_winheight); | 3968 frame_add_statusline(frp); |
3926 } | 3969 } |
3927 } | 3970 } |
3928 | 3971 |
3929 /* | 3972 /* |
3930 * Set width of a frame. Handles recursively going through contained frames. | 3973 * Set width of a frame. Handles recursively going through contained frames. |
7552 */ | 7595 */ |
7553 int | 7596 int |
7554 make_snapshot(int idx) | 7597 make_snapshot(int idx) |
7555 { | 7598 { |
7556 clear_snapshot(curtab, idx); | 7599 clear_snapshot(curtab, idx); |
7557 if (make_snapshot_rec(topframe, &curtab->tp_snapshot[idx], FALSE) == FAIL) | 7600 if (make_snapshot_rec(topframe, &curtab->tp_snapshot[idx]) == FAIL) |
7558 { | 7601 { |
7559 clear_snapshot(curtab, idx); | 7602 clear_snapshot(curtab, idx); |
7560 return FAIL; | 7603 return FAIL; |
7561 } | 7604 } |
7562 return OK; | 7605 return OK; |
7563 } | 7606 } |
7564 | 7607 |
7565 static int | 7608 static int |
7566 make_snapshot_rec(frame_T *fr, frame_T **frp, int snap_wins) | 7609 make_snapshot_rec(frame_T *fr, frame_T **frp) |
7567 { | 7610 { |
7568 *frp = ALLOC_CLEAR_ONE(frame_T); | 7611 *frp = ALLOC_CLEAR_ONE(frame_T); |
7569 if (*frp == NULL) | 7612 if (*frp == NULL) |
7570 return FAIL; | 7613 return FAIL; |
7571 (*frp)->fr_layout = fr->fr_layout; | 7614 (*frp)->fr_layout = fr->fr_layout; |
7572 (*frp)->fr_width = fr->fr_width; | 7615 (*frp)->fr_width = fr->fr_width; |
7573 (*frp)->fr_height = fr->fr_height; | 7616 (*frp)->fr_height = fr->fr_height; |
7574 if (fr->fr_next != NULL) | 7617 if (fr->fr_next != NULL) |
7575 { | 7618 { |
7576 if (make_snapshot_rec(fr->fr_next, &((*frp)->fr_next), snap_wins) | 7619 if (make_snapshot_rec(fr->fr_next, &((*frp)->fr_next)) == FAIL) |
7577 == FAIL) | |
7578 return FAIL; | 7620 return FAIL; |
7579 } | 7621 } |
7580 if (fr->fr_child != NULL) | 7622 if (fr->fr_child != NULL) |
7581 { | 7623 { |
7582 if (make_snapshot_rec(fr->fr_child, &((*frp)->fr_child), snap_wins) | 7624 if (make_snapshot_rec(fr->fr_child, &((*frp)->fr_child)) == FAIL) |
7583 == FAIL) | |
7584 return FAIL; | 7625 return FAIL; |
7585 } | 7626 } |
7586 if (fr->fr_layout == FR_LEAF && (snap_wins || fr->fr_win == curwin)) | 7627 if (fr->fr_layout == FR_LEAF && fr->fr_win == curwin) |
7587 (*frp)->fr_win = fr->fr_win; | 7628 (*frp)->fr_win = curwin; |
7588 return OK; | 7629 return OK; |
7589 } | 7630 } |
7590 | 7631 |
7591 /* | 7632 /* |
7592 * Remove any existing snapshot. | 7633 * Remove any existing snapshot. |
7718 wp2 = restore_snapshot_rec(sn->fr_child, fr->fr_child); | 7759 wp2 = restore_snapshot_rec(sn->fr_child, fr->fr_child); |
7719 if (wp2 != NULL) | 7760 if (wp2 != NULL) |
7720 wp = wp2; | 7761 wp = wp2; |
7721 } | 7762 } |
7722 return wp; | 7763 return wp; |
7723 } | |
7724 | |
7725 /* | |
7726 * Return a snapshot of all frames in the current tabpage and which windows are | |
7727 * in them, or NULL if out of memory. | |
7728 * Use clear_snapshot_rec to free the snapshot. | |
7729 */ | |
7730 static frame_T * | |
7731 make_full_snapshot(void) | |
7732 { | |
7733 frame_T *frp; | |
7734 | |
7735 if (make_snapshot_rec(topframe, &frp, TRUE) == FAIL) | |
7736 { | |
7737 clear_snapshot_rec(frp); | |
7738 return NULL; | |
7739 } | |
7740 return frp; | |
7741 } | |
7742 | |
7743 /* | |
7744 * Restore all frames in the full snapshot "sn" for the current tabpage. | |
7745 * Caller must ensure that the screen size didn't change, no windows with frames | |
7746 * in the snapshot were freed, and windows with frames not in the snapshot are | |
7747 * removed from their frames! | |
7748 * Doesn't restore changed window vertical separators or statuslines. | |
7749 * Frees the old frames. Don't call clear_snapshot_rec on "sn" afterwards! | |
7750 */ | |
7751 static void | |
7752 restore_full_snapshot(frame_T *sn) | |
7753 { | |
7754 if (sn == NULL) | |
7755 return; | |
7756 | |
7757 clear_snapshot_rec(topframe); | |
7758 restore_full_snapshot_rec(sn); | |
7759 curtab->tp_topframe = topframe = sn; | |
7760 last_status(FALSE); | |
7761 | |
7762 // If the amount of space available changed, first try setting the sizes of | |
7763 // windows with 'winfix{width,height}'. If that doesn't result in the right | |
7764 // size, forget about that option. | |
7765 if (topframe->fr_width != Columns) | |
7766 { | |
7767 frame_new_width(topframe, Columns, FALSE, TRUE); | |
7768 if (!frame_check_width(topframe, Columns)) | |
7769 frame_new_width(topframe, Columns, FALSE, FALSE); | |
7770 } | |
7771 if (topframe->fr_height != ROWS_AVAIL) | |
7772 { | |
7773 frame_new_height(topframe, ROWS_AVAIL, FALSE, TRUE); | |
7774 if (!frame_check_height(topframe, ROWS_AVAIL)) | |
7775 frame_new_height(topframe, ROWS_AVAIL, FALSE, FALSE); | |
7776 } | |
7777 | |
7778 win_comp_pos(); | |
7779 } | |
7780 | |
7781 static void | |
7782 restore_full_snapshot_rec(frame_T *sn) | |
7783 { | |
7784 if (sn == NULL) | |
7785 return; | |
7786 | |
7787 if (sn->fr_child != NULL) | |
7788 sn->fr_child->fr_parent = sn; | |
7789 if (sn->fr_next != NULL) | |
7790 { | |
7791 sn->fr_next->fr_parent = sn->fr_parent; | |
7792 sn->fr_next->fr_prev = sn; | |
7793 } | |
7794 if (sn->fr_win != NULL) | |
7795 { | |
7796 sn->fr_win->w_frame = sn; | |
7797 // Resize window to fit the frame. | |
7798 frame_new_height(sn, sn->fr_height, FALSE, FALSE); | |
7799 frame_new_width(sn, sn->fr_width, FALSE, FALSE); | |
7800 } | |
7801 restore_full_snapshot_rec(sn->fr_child); | |
7802 restore_full_snapshot_rec(sn->fr_next); | |
7803 } | 7764 } |
7804 | 7765 |
7805 #if defined(FEAT_GUI) || defined(PROTO) | 7766 #if defined(FEAT_GUI) || defined(PROTO) |
7806 /* | 7767 /* |
7807 * Return TRUE if there is any vertically split window. | 7768 * Return TRUE if there is any vertically split window. |