diff options
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r-- | src/nvim/window.c | 228 |
1 files changed, 143 insertions, 85 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c index 274bf72f3b..8be79f0cff 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -367,7 +367,7 @@ newwindow: g_do_tagpreview = Prenum; else g_do_tagpreview = p_pvh; - /*FALLTHROUGH*/ + FALLTHROUGH; case ']': case Ctrl_RSB: CHECK_CMDWIN @@ -420,8 +420,8 @@ wingotofile: case 'i': /* Go to any match */ case Ctrl_I: type = FIND_ANY; - /* FALLTHROUGH */ - case 'd': /* Go to definition, using 'define' */ + FALLTHROUGH; + case 'd': // Go to definition, using 'define' case Ctrl_D: CHECK_CMDWIN if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0) @@ -465,7 +465,7 @@ wingotofile: g_do_tagpreview = Prenum; else g_do_tagpreview = p_pvh; - /*FALLTHROUGH*/ + FALLTHROUGH; case ']': case Ctrl_RSB: // Keep visual mode, can select words to use as a tag. @@ -565,6 +565,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) int before; int minheight; int wmh1; + bool did_set_fraction = false; if (flags & WSP_TOP) oldwin = firstwin; @@ -729,6 +730,11 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) * 'winfixheight' window. Take them from a window above or below * instead, if possible. */ if (oldwin->w_p_wfh) { + // Set w_fraction now so that the cursor keeps the same relative + // vertical position using the old height. + set_fraction(oldwin); + did_set_fraction = true; + win_setheight_win(oldwin->w_height + new_size + STATUS_HEIGHT, oldwin); oldwin_height = oldwin->w_height; @@ -843,8 +849,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) /* Set w_fraction now so that the cursor keeps the same relative * vertical position. */ - if (oldwin->w_height > 0) + if (!did_set_fraction) { set_fraction(oldwin); + } wp->w_fraction = oldwin->w_fraction; if (flags & WSP_VERT) { @@ -1258,7 +1265,8 @@ static void win_exchange(long Prenum) (void)win_comp_pos(); /* recompute window positions */ win_enter(wp, true); - redraw_later(CLEAR); + redraw_later(NOT_VALID); + redraw_win_later(wp, NOT_VALID); } /* @@ -1333,7 +1341,7 @@ static void win_rotate(int upwards, int count) (void)win_comp_pos(); } - redraw_later(CLEAR); + redraw_all_later(NOT_VALID); } /* @@ -1470,10 +1478,10 @@ static void win_equal_rec( || topfr->fr_width != width || topfr->fr_win->w_wincol != col ) { topfr->fr_win->w_winrow = row; - frame_new_height(topfr, height, FALSE, FALSE); + frame_new_height(topfr, height, false, false); topfr->fr_win->w_wincol = col; - frame_new_width(topfr, width, FALSE, FALSE); - redraw_all_later(CLEAR); + frame_new_width(topfr, width, false, false); + redraw_all_later(NOT_VALID); } } else if (topfr->fr_layout == FR_ROW) { topfr->fr_width = width; @@ -1852,20 +1860,18 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, return true; } -/* - * Close window "win". Only works for the current tab page. - * If "free_buf" is TRUE related buffer may be unloaded. - * - * Called by :quit, :close, :xit, :wq and findtag(). - * Returns FAIL when the window was not closed. - */ -int win_close(win_T *win, int free_buf) +// Close window "win". Only works for the current tab page. +// If "free_buf" is true related buffer may be unloaded. +// +// Called by :quit, :close, :xit, :wq and findtag(). +// Returns FAIL when the window was not closed. +int win_close(win_T *win, bool free_buf) { win_T *wp; int other_buffer = FALSE; int close_curwin = FALSE; int dir; - int help_window = FALSE; + bool help_window = false; tabpage_T *prev_curtab = curtab; frame_T *win_frame = win->w_frame->fr_parent; @@ -1895,10 +1901,11 @@ int win_close(win_T *win, int free_buf) /* When closing the help window, try restoring a snapshot after closing * the window. Otherwise clear the snapshot, it's now invalid. */ - if (win->w_buffer != NULL && win->w_buffer->b_help) - help_window = TRUE; - else + if (bt_help(win->w_buffer)) { + help_window = true; + } else { clear_snapshot(curtab, SNAP_HELP_IDX); + } if (win == curwin) { /* @@ -1960,10 +1967,11 @@ int win_close(win_T *win, int free_buf) if (only_one_window() && win_valid(win) && win->w_buffer == NULL && (last_window() || curtab != prev_curtab || close_last_window_tabpage(win, free_buf, prev_curtab))) { - /* Autocommands have close all windows, quit now. Restore - * curwin->w_buffer, otherwise writing ShaDa file may fail. */ - if (curwin->w_buffer == NULL) + // Autocommands have closed all windows, quit now. Restore + // curwin->w_buffer, otherwise writing ShaDa file may fail. + if (curwin->w_buffer == NULL) { curwin->w_buffer = curbuf; + } getout(0); } // Autocommands may have moved to another tab page. @@ -2296,6 +2304,9 @@ winframe_remove ( if (frp2->fr_win != NULL) frp2->fr_win->w_frame = frp2->fr_parent; frp = frp2->fr_parent; + if (topframe->fr_child == frp2) { + topframe->fr_child = frp; + } xfree(frp2); frp2 = frp->fr_parent; @@ -2317,6 +2328,9 @@ winframe_remove ( break; } } + if (topframe->fr_child == frp) { + topframe->fr_child = frp2; + } xfree(frp); } } @@ -2324,14 +2338,14 @@ winframe_remove ( return wp; } -/* - * Find out which frame is going to get the freed up space when "win" is - * closed. - * if 'splitbelow'/'splitleft' the space goes to the window above/left. - * if 'nosplitbelow'/'nosplitleft' the space goes to the window below/right. - * This makes opening a window and closing it immediately keep the same window - * layout. - */ +// Return a pointer to the frame that will receive the empty screen space that +// is left over after "win" is closed. +// +// If 'splitbelow' or 'splitright' is set, the space goes above or to the left +// by default. Otherwise, the free space goes below or to the right. The +// result is that opening a window and then immediately closing it will +// preserve the initial window layout. The 'wfh' and 'wfw' settings are +// respected when possible. static frame_T * win_altframe ( win_T *win, @@ -2339,20 +2353,40 @@ win_altframe ( ) { frame_T *frp; - int b; - if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) - /* Last window in this tab page, will go to next tab page. */ + if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) { return alt_tabpage()->tp_curwin->w_frame; + } frp = win->w_frame; - if (frp->fr_parent != NULL && frp->fr_parent->fr_layout == FR_ROW) - b = p_spr; - else - b = p_sb; - if ((!b && frp->fr_next != NULL) || frp->fr_prev == NULL) + + if (frp->fr_prev == NULL) { return frp->fr_next; - return frp->fr_prev; + } + if (frp->fr_next == NULL) { + return frp->fr_prev; + } + + frame_T *target_fr = frp->fr_next; + frame_T *other_fr = frp->fr_prev; + if (p_spr || p_sb) { + target_fr = frp->fr_prev; + other_fr = frp->fr_next; + } + + // If 'wfh' or 'wfw' is set for the target and not for the alternate + // window, reverse the selection. + if (frp->fr_parent != NULL && frp->fr_parent->fr_layout == FR_ROW) { + if (frame_fixed_width(target_fr) && !frame_fixed_width(other_fr)) { + target_fr = other_fr; + } + } else { + if (frame_fixed_height(target_fr) && !frame_fixed_height(other_fr)) { + target_fr = other_fr; + } + } + + return target_fr; } /* @@ -2849,8 +2883,8 @@ close_others ( } if (!r) { if (message && (p_confirm || cmdmod.confirm) && p_write) { - dialog_changed(wp->w_buffer, FALSE); - if (!win_valid(wp)) { /* autocommands messed wp up */ + dialog_changed(wp->w_buffer, false); + if (!win_valid(wp)) { // autocommands messed wp up nextwp = firstwin; continue; } @@ -2959,7 +2993,6 @@ static int win_alloc_firstwin(win_T *oldwin) topframe = curwin->w_frame; topframe->fr_width = Columns; topframe->fr_height = Rows - p_ch; - topframe->fr_win = curwin; return OK; } @@ -3073,7 +3106,7 @@ int win_new_tabpage(int after, char_u *filename) newtp->tp_topframe = topframe; last_status(FALSE); - redraw_all_later(CLEAR); + redraw_all_later(NOT_VALID); apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf); apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf); @@ -3278,10 +3311,9 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au trigger_enter_autocmds, trigger_leave_autocmds); prevwin = next_prevwin; - last_status(FALSE); /* status line may appear or disappear */ - (void)win_comp_pos(); /* recompute w_winrow for all windows */ - must_redraw = CLEAR; /* need to redraw everything */ - diff_need_scrollbind = TRUE; + last_status(false); // status line may appear or disappear + (void)win_comp_pos(); // recompute w_winrow for all windows + diff_need_scrollbind = true; /* The tabpage line may have appeared or disappeared, may need to resize * the frames for that. When the Vim window was resized need to update @@ -3303,7 +3335,8 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); } - redraw_all_later(CLEAR); + redraw_all_later(NOT_VALID); + must_redraw = NOT_VALID; } /* @@ -3970,18 +4003,20 @@ win_remove ( tabpage_T *tp /* tab page "win" is in, NULL for current */ ) { - if (wp->w_prev != NULL) + if (wp->w_prev != NULL) { wp->w_prev->w_next = wp->w_next; - else if (tp == NULL) - firstwin = wp->w_next; - else + } else if (tp == NULL) { + firstwin = curtab->tp_firstwin = wp->w_next; + } else { tp->tp_firstwin = wp->w_next; - if (wp->w_next != NULL) + } + if (wp->w_next != NULL) { wp->w_next->w_prev = wp->w_prev; - else if (tp == NULL) - lastwin = wp->w_prev; - else + } else if (tp == NULL) { + lastwin = curtab->tp_lastwin = wp->w_prev; + } else { tp->tp_lastwin = wp->w_prev; + } } /* @@ -4015,12 +4050,18 @@ static void frame_insert(frame_T *before, frame_T *frp) */ static void frame_remove(frame_T *frp) { - if (frp->fr_prev != NULL) + if (frp->fr_prev != NULL) { frp->fr_prev->fr_next = frp->fr_next; - else + } else { frp->fr_parent->fr_child = frp->fr_next; - if (frp->fr_next != NULL) + // special case: topframe->fr_child == frp + if (topframe->fr_child == frp) { + topframe->fr_child = frp->fr_next; + } + } + if (frp->fr_next != NULL) { frp->fr_next->fr_prev = frp->fr_prev; + } } @@ -4778,10 +4819,13 @@ void win_drag_vsep_line(win_T *dragwin, int offset) #define FRACTION_MULT 16384L // Set wp->w_fraction for the current w_wrow and w_height. +// Has no effect when the window is less than two lines. void set_fraction(win_T *wp) { - wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT + wp->w_height / 2) + if (wp->w_height > 1) { + wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT + wp->w_height / 2) / (long)wp->w_height; + } } /* @@ -4848,8 +4892,8 @@ void scroll_to_fraction(win_T *wp, int prev_height) sline = wp->w_wrow - line_size; if (sline >= 0) { - /* Make sure the whole cursor line is visible, if possible. */ - int rows = plines_win(wp, lnum, FALSE); + // Make sure the whole cursor line is visible, if possible. + const int rows = plines_win(wp, lnum, false); if (sline > wp->w_height - rows) { sline = wp->w_height - rows; @@ -4884,12 +4928,13 @@ void scroll_to_fraction(win_T *wp, int prev_height) --sline; break; } - --lnum; - if (lnum == wp->w_topline) - line_size = plines_win_nofill(wp, lnum, TRUE) + lnum--; + if (lnum == wp->w_topline) { + line_size = plines_win_nofill(wp, lnum, true) + wp->w_topfill; - else - line_size = plines_win(wp, lnum, TRUE); + } else { + line_size = plines_win(wp, lnum, true); + } sline -= line_size; } @@ -5096,6 +5141,8 @@ file_name_in_line ( { char_u *ptr; size_t len; + bool in_type = true; + bool is_url = false; /* * search forward for what could be the start of a file name @@ -5116,13 +5163,14 @@ file_name_in_line ( * Go one char back to ":" before "//" even when ':' is not in 'isfname'. */ while (ptr > line) { - if (has_mbyte && (len = (size_t)((*mb_head_off)(line, ptr - 1))) > 0) + if ((len = (size_t)(utf_head_off(line, ptr - 1))) > 0) { ptr -= len + 1; - else if (vim_isfilec(ptr[-1]) - || ((options & FNAME_HYP) && path_is_url((char *)ptr - 1))) - --ptr; - else + } else if (vim_isfilec(ptr[-1]) + || ((options & FNAME_HYP) && path_is_url((char *)ptr - 1))) { + ptr--; + } else { break; + } } /* @@ -5131,7 +5179,19 @@ file_name_in_line ( */ len = 0; while (vim_isfilec(ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ') - || ((options & FNAME_HYP) && path_is_url((char *)ptr + len))) { + || ((options & FNAME_HYP) && path_is_url((char *)ptr + len)) + || (is_url && vim_strchr((char_u *)"?&=", ptr[len]) != NULL)) { + // After type:// we also include ?, & and = as valid characters, so that + // http://google.com?q=this&that=ok works. + if ((ptr[len] >= 'A' && ptr[len] <= 'Z') + || (ptr[len] >= 'a' && ptr[len] <= 'z')) { + if (in_type && path_is_url((char *)ptr + len + 1)) { + is_url = true; + } + } else { + in_type = false; + } + if (ptr[len] == '\\' && ptr[len + 1] == ' ') { // Skip over the "\" in "\ ". ++len; @@ -5282,7 +5342,7 @@ bool only_one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT int count = 0; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->w_buffer != NULL - && (!((wp->w_buffer->b_help && !curbuf->b_help) + && (!((bt_help(wp->w_buffer) && !bt_help(curbuf)) || wp->w_p_pvw) || wp == curwin) && wp != aucmd_win) { count++; } @@ -5384,7 +5444,7 @@ restore_snapshot ( win_comp_pos(); if (wp != NULL && close_curwin) win_goto(wp); - redraw_all_later(CLEAR); + redraw_all_later(NOT_VALID); } clear_snapshot(curtab, idx); } @@ -5488,12 +5548,10 @@ int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage return OK; } -/* - * Restore current tabpage and window saved by switch_win(), if still valid. - * When "no_display" is TRUE the display won't be affected, no redraw is - * triggered. - */ -void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display) +// Restore current tabpage and window saved by switch_win(), if still valid. +// When "no_display" is true the display won't be affected, no redraw is +// triggered. +void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display) { if (save_curtab != NULL && valid_tabpage(save_curtab)) { if (no_display) { @@ -5608,7 +5666,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, m->match.rmm_maxcol = 0; m->conceal_char = 0; if (conceal_char != NULL) { - m->conceal_char = (*mb_ptr2char)((const char_u *)conceal_char); + m->conceal_char = utf_ptr2char((const char_u *)conceal_char); } // Set up position matches |