aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r--src/nvim/window.c428
1 files changed, 263 insertions, 165 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 83ddf534cf..6bc082ffb2 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -502,10 +502,11 @@ wingotofile:
break;
}
FloatConfig config = FLOAT_CONFIG_INIT;
+ config.width = curwin->w_width;
+ config.height = curwin->w_height;
config.external = true;
Error err = ERROR_INIT;
- if (!win_new_float(curwin, curwin->w_width, curwin->w_height, config,
- &err)) {
+ if (!win_new_float(curwin, config, &err)) {
EMSG(err.msg);
api_clear_error(&err);
beep_flush();
@@ -538,12 +539,9 @@ static void cmd_with_count(char *cmd, char_u *bufp, size_t bufsize,
/// float. It must then already belong to the current tabpage!
///
/// config must already have been validated!
-win_T *win_new_float(win_T *wp, int width, int height, FloatConfig config,
- Error *err)
+win_T *win_new_float(win_T *wp, FloatConfig fconfig, Error *err)
{
- bool new = false;
if (wp == NULL) {
- new = true;
wp = win_alloc(lastwin_nofloating(), false);
win_init(wp, curwin, 0);
} else {
@@ -569,29 +567,30 @@ win_T *win_new_float(win_T *wp, int width, int height, FloatConfig config,
wp->w_floating = 1;
wp->w_status_height = 0;
wp->w_vsep_width = 0;
- win_config_float(wp, width, height, config);
+
+ // TODO(bfredl): use set_option_to() after merging #9110 ?
+ wp->w_p_nu = false;
+ wp->w_allbuf_opt.wo_nu = false;
+ win_config_float(wp, fconfig);
wp->w_pos_changed = true;
redraw_win_later(wp, VALID);
- if (new) {
- win_enter(wp, false);
- }
return wp;
}
-void win_config_float(win_T *wp, int width, int height,
- FloatConfig config)
+void win_config_float(win_T *wp, FloatConfig fconfig)
{
- wp->w_height = MAX(height, 1);
- wp->w_width = MAX(width, 2);
+ wp->w_width = MAX(fconfig.width, 1);
+ wp->w_height = MAX(fconfig.height, 1);
- if (config.relative == kFloatRelativeCursor) {
- config.relative = kFloatRelativeWindow;
- config.row += curwin->w_wrow;
- config.col += curwin->w_wcol;
- config.window = curwin->handle;
+ if (fconfig.relative == kFloatRelativeCursor) {
+ fconfig.relative = kFloatRelativeWindow;
+ fconfig.row += curwin->w_wrow;
+ fconfig.col += curwin->w_wcol;
+ fconfig.window = curwin->handle;
}
- wp->w_float_config = config;
+ bool change_external = fconfig.external != wp->w_float_config.external;
+ wp->w_float_config = fconfig;
if (!ui_has(kUIMultigrid)) {
wp->w_height = MIN(wp->w_height, Rows-1);
@@ -601,6 +600,10 @@ void win_config_float(win_T *wp, int width, int height,
win_set_inner_size(wp);
must_redraw = MAX(must_redraw, VALID);
wp->w_pos_changed = true;
+ if (change_external) {
+ wp->w_hl_needs_update = true;
+ redraw_win_later(wp, NOT_VALID);
+ }
}
static void ui_ext_win_position(win_T *wp)
@@ -610,28 +613,25 @@ static void ui_ext_win_position(win_T *wp)
wp->w_wincol, wp->w_width, wp->w_height);
return;
}
- const char *const anchor_str[] = {
- "NW",
- "NE",
- "SW",
- "SE"
- };
FloatConfig c = wp->w_float_config;
if (!c.external) {
ScreenGrid *grid = &default_grid;
- int row = c.row, col = c.col;
+ float row = c.row, col = c.col;
if (c.relative == kFloatRelativeWindow) {
Error dummy = ERROR_INIT;
win_T *win = find_window_by_handle(c.window, &dummy);
if (win) {
grid = &win->w_grid;
- screen_adjust_grid(&grid, &row, &col);
+ int row_off = 0, col_off = 0;
+ screen_adjust_grid(&grid, &row_off, &col_off);
+ row += row_off;
+ col += col_off;
}
api_clear_error(&dummy);
}
if (ui_has(kUIMultigrid)) {
- String anchor = cstr_to_string(anchor_str[c.anchor]);
+ String anchor = cstr_to_string(float_anchor_str[c.anchor]);
ui_call_win_float_pos(wp->w_grid.handle, wp->handle, anchor, grid->handle,
row, col, c.focusable);
} else {
@@ -640,16 +640,16 @@ static void ui_ext_win_position(win_T *wp)
bool east = c.anchor & kFloatAnchorEast;
bool south = c.anchor & kFloatAnchorSouth;
- row -= (south ? wp->w_height : 0);
- col -= (east ? wp->w_width : 0);
- row = MAX(MIN(row, Rows-wp->w_height-1), 0);
- col = MAX(MIN(col, Columns-wp->w_width), 0);
- wp->w_winrow = row;
- wp->w_wincol = col;
+ int comp_row = (int)row - (south ? wp->w_height : 0);
+ int comp_col = (int)col - (east ? wp->w_width : 0);
+ comp_row = MAX(MIN(comp_row, Rows-wp->w_height-1), 0);
+ comp_col = MAX(MIN(comp_col, Columns-wp->w_width), 0);
+ wp->w_winrow = comp_row;
+ wp->w_wincol = comp_col;
bool valid = (wp->w_redr_type == 0);
bool on_top = (curwin == wp) || !curwin->w_floating;
- ui_comp_put_grid(&wp->w_grid, row, col, wp->w_height, wp->w_width,
- valid, on_top);
+ ui_comp_put_grid(&wp->w_grid, comp_row, comp_col, wp->w_height,
+ wp->w_width, valid, on_top);
if (!valid) {
wp->w_grid.valid = false;
redraw_win_later(wp, NOT_VALID);
@@ -668,14 +668,14 @@ static bool parse_float_anchor(String anchor, FloatAnchor *out)
*out = (FloatAnchor)0;
}
char *str = anchor.data;
- if (!STRICMP(str, "NW")) {
- *out = kFloatAnchorNW;
- } else if (!STRICMP(str, "NE")) {
- *out = kFloatAnchorNE;
- } else if (!STRICMP(str, "SW")) {
- *out = kFloatAnchorSW;
- } else if (!STRICMP(str, "SE")) {
- *out = kFloatAnchorSE;
+ if (striequal(str, "NW")) {
+ *out = 0; // NW is the default
+ } else if (striequal(str, "NE")) {
+ *out = kFloatAnchorEast;
+ } else if (striequal(str, "SW")) {
+ *out = kFloatAnchorSouth;
+ } else if (striequal(str, "SE")) {
+ *out = kFloatAnchorSouth | kFloatAnchorEast;
} else {
return false;
}
@@ -684,15 +684,12 @@ static bool parse_float_anchor(String anchor, FloatAnchor *out)
static bool parse_float_relative(String relative, FloatRelative *out)
{
- if (relative.size == 0) {
- *out = (FloatRelative)0;
- }
char *str = relative.data;
- if (!STRICMP(str, "editor")) {
+ if (striequal(str, "editor")) {
*out = kFloatRelativeEditor;
- } else if (!STRICMP(str, "win")) {
+ } else if (striequal(str, "win")) {
*out = kFloatRelativeWindow;
- } else if (!STRICMP(str, "cursor")) {
+ } else if (striequal(str, "cursor")) {
*out = kFloatRelativeCursor;
} else {
return false;
@@ -700,11 +697,14 @@ static bool parse_float_relative(String relative, FloatRelative *out)
return true;
}
-bool parse_float_config(Dictionary config, FloatConfig *out, bool reconf,
+bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
Error *err)
{
+ // TODO(bfredl): use a get/has_key interface instead and get rid of extra
+ // flags
bool has_row = false, has_col = false, has_relative = false;
bool has_external = false, has_window = false;
+ bool has_width = false, has_height = false;
for (size_t i = 0; i < config.size; i++) {
char *key = config.items[i].key.data;
@@ -712,109 +712,137 @@ bool parse_float_config(Dictionary config, FloatConfig *out, bool reconf,
if (!strcmp(key, "row")) {
has_row = true;
if (val.type == kObjectTypeInteger) {
- out->row = val.data.integer;
+ fconfig->row = val.data.integer;
} else if (val.type == kObjectTypeFloat) {
- out->row = val.data.floating;
+ fconfig->row = val.data.floating;
} else {
api_set_error(err, kErrorTypeValidation,
- "'row' option has to be Integer or Float");
+ "'row' key must be Integer or Float");
return false;
}
} else if (!strcmp(key, "col")) {
has_col = true;
if (val.type == kObjectTypeInteger) {
- out->col = val.data.integer;
+ fconfig->col = val.data.integer;
} else if (val.type == kObjectTypeFloat) {
- out->col = val.data.floating;
+ fconfig->col = val.data.floating;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'col' key must be Integer or Float");
+ return false;
+ }
+ } else if (strequal(key, "width")) {
+ has_width = true;
+ if (val.type == kObjectTypeInteger && val.data.integer > 0) {
+ fconfig->width = val.data.integer;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'width' key must be a positive Integer");
+ return false;
+ }
+ } else if (strequal(key, "height")) {
+ has_height = true;
+ if (val.type == kObjectTypeInteger && val.data.integer > 0) {
+ fconfig->height= val.data.integer;
} else {
api_set_error(err, kErrorTypeValidation,
- "'col' option has to be Integer or Float");
+ "'height' key must be a positive Integer");
return false;
}
} else if (!strcmp(key, "anchor")) {
if (val.type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation,
- "'anchor' option has to be String");
+ "'anchor' key must be String");
return false;
}
- if (!parse_float_anchor(val.data.string, &out->anchor)) {
+ if (!parse_float_anchor(val.data.string, &fconfig->anchor)) {
api_set_error(err, kErrorTypeValidation,
- "Invalid value of 'anchor' option");
+ "Invalid value of 'anchor' key");
return false;
}
} else if (!strcmp(key, "relative")) {
- has_relative = true;
if (val.type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation,
- "'relative' option has to be String");
+ "'relative' key must be String");
return false;
}
- if (!parse_float_relative(val.data.string, &out->relative)) {
- api_set_error(err, kErrorTypeValidation,
- "Invalid value of 'relative' option");
- return false;
+ // ignore empty string, to match nvim_win_get_config
+ if (val.data.string.size > 0) {
+ has_relative = true;
+ if (!parse_float_relative(val.data.string, &fconfig->relative)) {
+ api_set_error(err, kErrorTypeValidation,
+ "Invalid value of 'relative' key");
+ return false;
+ }
}
} else if (!strcmp(key, "win")) {
has_window = true;
if (val.type != kObjectTypeInteger
&& val.type != kObjectTypeWindow) {
api_set_error(err, kErrorTypeValidation,
- "'win' option has to be Integer or Window");
+ "'win' key must be Integer or Window");
return false;
}
- out->window = val.data.integer;
+ fconfig->window = val.data.integer;
} else if (!strcmp(key, "external")) {
if (val.type == kObjectTypeInteger) {
- out->external = val.data.integer;
+ fconfig->external = val.data.integer;
} else if (val.type == kObjectTypeBoolean) {
- out->external = val.data.boolean;
+ fconfig->external = val.data.boolean;
} else {
api_set_error(err, kErrorTypeValidation,
- "'external' option has to be Boolean");
+ "'external' key must be Boolean");
return false;
}
- has_external = out->external;
+ has_external = fconfig->external;
} else if (!strcmp(key, "focusable")) {
if (val.type == kObjectTypeInteger) {
- out->focusable = val.data.integer;
+ fconfig->focusable = val.data.integer;
} else if (val.type == kObjectTypeBoolean) {
- out->focusable = val.data.boolean;
+ fconfig->focusable = val.data.boolean;
} else {
api_set_error(err, kErrorTypeValidation,
- "'focusable' option has to be Boolean");
+ "'focusable' key must be Boolean");
return false;
}
} else {
api_set_error(err, kErrorTypeValidation,
- "Invalid options key '%s'", key);
+ "Invalid key '%s'", key);
return false;
}
}
- if (has_window && !(has_relative && out->relative == kFloatRelativeWindow)) {
+ if (has_window && !(has_relative
+ && fconfig->relative == kFloatRelativeWindow)) {
api_set_error(err, kErrorTypeValidation,
- "'win' option is only valid with relative='win'");
+ "'win' key is only valid with relative='win'");
return false;
}
- if ((has_relative && out->relative == kFloatRelativeWindow)
- && (!has_window || out->window == 0)) {
- out->window = curwin->handle;
+ if ((has_relative && fconfig->relative == kFloatRelativeWindow)
+ && (!has_window || fconfig->window == 0)) {
+ fconfig->window = curwin->handle;
}
if (has_relative && has_external) {
api_set_error(err, kErrorTypeValidation,
- "Only one of 'relative' and 'external' should be used");
+ "Only one of 'relative' and 'external' must be used");
return false;
} else if (!reconf && !has_relative && !has_external) {
api_set_error(err, kErrorTypeValidation,
"One of 'relative' and 'external' must be used");
return false;
} else if (has_relative) {
- out->external = false;
+ fconfig->external = false;
}
- if (out->external && !ui_has(kUIMultigrid)) {
+ if (!reconf && !(has_height && has_width)) {
+ api_set_error(err, kErrorTypeValidation,
+ "Must specify 'width' and 'height'");
+ return false;
+ }
+
+ if (fconfig->external && !ui_has(kUIMultigrid)) {
api_set_error(err, kErrorTypeValidation,
"UI doesn't support external windows");
return false;
@@ -1121,6 +1149,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
} else if (wp->w_floating) {
new_frame(wp);
wp->w_floating = false;
+ // non-floating window doesn't store float config.
+ wp->w_float_config = FLOAT_CONFIG_INIT;
}
/*
@@ -2265,8 +2295,7 @@ int win_close(win_T *win, bool free_buf)
EMSG(_("E813: Cannot close autocmd window"));
return FAIL;
}
- if ((firstwin == aucmd_win || lastwin_nofloating() == aucmd_win)
- && one_window()) {
+ if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window()) {
EMSG(_("E814: Cannot close window, only autocmd window would remain"));
return FAIL;
}
@@ -2299,10 +2328,10 @@ int win_close(win_T *win, bool free_buf)
if (!win->w_floating) {
wp = frame2win(win_altframe(win, NULL));
} else {
- if (win_valid(prevwin)) {
+ if (win_valid(prevwin) && prevwin != win) {
wp = prevwin;
} else {
- wp = curtab->tp_firstwin;
+ wp = firstwin;
}
}
@@ -2448,7 +2477,7 @@ int win_close(win_T *win, bool free_buf)
}
if (!was_floating) {
- if (p_ea && (*p_ead == 'b' || *p_ead == dir)) {
+ if (!curwin->w_floating && p_ea && (*p_ead == 'b' || *p_ead == dir)) {
// If the frame of the closed window contains the new current window,
// only resize that frame. Otherwise resize all windows.
win_equal(curwin, curwin->w_frame->fr_parent == win_frame, dir);
@@ -2561,15 +2590,12 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
free_tabpage(tp);
}
-/*
- * Free the memory used for a window.
- * Returns a pointer to the window that got the freed up space.
- */
-static win_T *
-win_free_mem (
+// Free the memory used for a window.
+// Returns a pointer to the window that got the freed up space.
+static win_T *win_free_mem(
win_T *win,
- int *dirp, /* set to 'v' or 'h' for direction if 'ea' */
- tabpage_T *tp /* tab page "win" is in, NULL for current */
+ int *dirp, // set to 'v' or 'h' for direction if 'ea'
+ tabpage_T *tp // tab page "win" is in, NULL for current
)
{
frame_T *frp;
@@ -2581,18 +2607,20 @@ win_free_mem (
wp = winframe_remove(win, dirp, tp);
xfree(frp);
} else {
- if (win_valid(prevwin)) {
+ *dirp = 'h'; // Dummy value.
+ if (win_valid(prevwin) && prevwin != win) {
wp = prevwin;
} else {
- wp = curtab->tp_firstwin;
+ wp = firstwin;
}
}
win_free(win, tp);
- /* When deleting the current window of another tab page select a new
- * current window. */
- if (tp != NULL && win == tp->tp_curwin)
+ // When deleting the current window of another tab page select a new
+ // current window.
+ if (tp != NULL && win == tp->tp_curwin) {
tp->tp_curwin = wp;
+ }
return wp;
}
@@ -2665,9 +2693,9 @@ winframe_remove (
frp3 = frp_close->fr_next;
while (frp != NULL || frp3 != NULL) {
if (frp != NULL) {
- if (frp->fr_win != NULL && !frp->fr_win->w_p_wfh) {
+ if (!frame_fixed_height(frp)) {
frp2 = frp;
- wp = frp->fr_win;
+ wp = frame2win(frp2);
break;
}
frp = frp->fr_prev;
@@ -2694,9 +2722,9 @@ winframe_remove (
frp3 = frp_close->fr_next;
while (frp != NULL || frp3 != NULL) {
if (frp != NULL) {
- if (frp->fr_win != NULL && !frp->fr_win->w_p_wfw) {
+ if (!frame_fixed_width(frp)) {
frp2 = frp;
- wp = frp->fr_win;
+ wp = frame2win(frp2);
break;
}
frp = frp->fr_prev;
@@ -3384,16 +3412,18 @@ int win_alloc_first(void)
return OK;
}
-/*
- * Init "aucmd_win". This can only be done after the first
- * window is fully initialized, thus it can't be in win_alloc_first().
- */
+// Init `aucmd_win`. This can only be done after the first window
+// is fully initialized, thus it can't be in win_alloc_first().
void win_alloc_aucmd_win(void)
{
- aucmd_win = win_alloc(NULL, TRUE);
- win_init_some(aucmd_win, curwin);
+ Error err = ERROR_INIT;
+ FloatConfig fconfig = FLOAT_CONFIG_INIT;
+ fconfig.width = Columns;
+ fconfig.height = 5;
+ fconfig.focusable = false;
+ aucmd_win = win_new_float(NULL, fconfig, &err);
+ aucmd_win->w_buffer->b_nwindows--;
RESET_BINDING(aucmd_win);
- new_frame(aucmd_win);
}
/*
@@ -3764,6 +3794,9 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au
* the frames for that. When the Vim window was resized need to update
* frame sizes too. Use the stored value of p_ch, so that it can be
* different for each tab page. */
+ if (p_ch != curtab->tp_ch_used) {
+ clear_cmdline = true;
+ }
p_ch = curtab->tp_ch_used;
if (curtab->tp_old_Rows != Rows || (old_off != firstwin->w_winrow
))
@@ -3806,7 +3839,7 @@ static void tabpage_check_windows(tabpage_T *old_curtab)
for (win_T *wp = firstwin; wp; wp = wp->w_next) {
if (wp->w_floating && !wp->w_float_config.external) {
- win_config_float(wp, wp->w_width, wp->w_height, wp->w_float_config);
+ win_config_float(wp, wp->w_float_config);
}
wp->w_pos_changed = true;
}
@@ -3818,7 +3851,7 @@ static void tabpage_check_windows(tabpage_T *old_curtab)
*/
void goto_tabpage(int n)
{
- tabpage_T *tp;
+ tabpage_T *tp = NULL; // shut up compiler
tabpage_T *ttp;
int i;
@@ -4006,24 +4039,25 @@ tabpage_T *win_find_tabpage(win_T *win)
return NULL;
}
-/*
- * Move to window above or below "count" times.
- */
-static void
-win_goto_ver (
- int up, /* TRUE to go to win above */
- long count
-)
+/// Get the above or below neighbor window of the specified window.
+///
+/// Returns the specified window if the neighbor is not found.
+/// Returns the previous window if the specifiecied window is a floating window.
+///
+/// @param up true for the above neighbor
+/// @param count nth neighbor window
+///
+/// @return found window
+win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, bool up, long count)
{
frame_T *fr;
frame_T *nfr;
frame_T *foundfr;
- foundfr = curwin->w_frame;
+ foundfr = wp->w_frame;
- if (curwin->w_floating) {
- win_goto(prevwin);
- return;
+ if (wp->w_floating) {
+ return win_valid(prevwin) && !prevwin->w_floating ? prevwin : firstwin;
}
while (count--) {
@@ -4033,14 +4067,17 @@ win_goto_ver (
*/
fr = foundfr;
for (;; ) {
- if (fr == topframe)
+ if (fr == tp->tp_topframe) {
goto end;
- if (up)
+ }
+ if (up) {
nfr = fr->fr_prev;
- else
+ } else {
nfr = fr->fr_next;
- if (fr->fr_parent->fr_layout == FR_COL && nfr != NULL)
+ }
+ if (fr->fr_parent->fr_layout == FR_COL && nfr != NULL) {
break;
+ }
fr = fr->fr_parent;
}
@@ -4054,11 +4091,12 @@ win_goto_ver (
}
fr = nfr->fr_child;
if (nfr->fr_layout == FR_ROW) {
- /* Find the frame at the cursor row. */
+ // Find the frame at the cursor row.
while (fr->fr_next != NULL
&& frame2win(fr)->w_wincol + fr->fr_width
- <= curwin->w_wincol + curwin->w_wcol)
+ <= wp->w_wincol + wp->w_wcol) {
fr = fr->fr_next;
+ }
}
if (nfr->fr_layout == FR_COL && up)
while (fr->fr_next != NULL)
@@ -4067,28 +4105,40 @@ win_goto_ver (
}
}
end:
- if (foundfr != NULL)
- win_goto(foundfr->fr_win);
+ return foundfr != NULL ? foundfr->fr_win : NULL;
}
-/*
- * Move to left or right window.
- */
-static void
-win_goto_hor (
- int left, /* TRUE to go to left win */
- long count
-)
+/// Move to window above or below "count" times.
+///
+/// @param up true to go to win above
+/// @param count go count times into direction
+static void win_goto_ver(bool up, long count)
+{
+ win_T *win = win_vert_neighbor(curtab, curwin, up, count);
+ if (win != NULL) {
+ win_goto(win);
+ }
+}
+
+/// Get the left or right neighbor window of the specified window.
+///
+/// Returns the specified window if the neighbor is not found.
+/// Returns the previous window if the specifiecied window is a floating window.
+///
+/// @param left true for the left neighbor
+/// @param count nth neighbor window
+///
+/// @return found window
+win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, bool left, long count)
{
frame_T *fr;
frame_T *nfr;
frame_T *foundfr;
- foundfr = curwin->w_frame;
+ foundfr = wp->w_frame;
- if (curwin->w_floating) {
- win_goto(prevwin);
- return;
+ if (wp->w_floating) {
+ return win_valid(prevwin) && !prevwin->w_floating ? prevwin : firstwin;
}
while (count--) {
@@ -4098,14 +4148,17 @@ win_goto_hor (
*/
fr = foundfr;
for (;; ) {
- if (fr == topframe)
+ if (fr == tp->tp_topframe) {
goto end;
- if (left)
+ }
+ if (left) {
nfr = fr->fr_prev;
- else
+ } else {
nfr = fr->fr_next;
- if (fr->fr_parent->fr_layout == FR_ROW && nfr != NULL)
+ }
+ if (fr->fr_parent->fr_layout == FR_ROW && nfr != NULL) {
break;
+ }
fr = fr->fr_parent;
}
@@ -4122,7 +4175,7 @@ win_goto_hor (
/* Find the frame at the cursor row. */
while (fr->fr_next != NULL
&& frame2win(fr)->w_winrow + fr->fr_height
- <= curwin->w_winrow + curwin->w_wrow)
+ <= wp->w_winrow + wp->w_wrow)
fr = fr->fr_next;
}
if (nfr->fr_layout == FR_ROW && left)
@@ -4132,8 +4185,19 @@ win_goto_hor (
}
}
end:
- if (foundfr != NULL)
- win_goto(foundfr->fr_win);
+ return foundfr != NULL ? foundfr->fr_win : NULL;
+}
+
+/// Move to left or right window.
+///
+/// @param left true to go to left window
+/// @param count go count times into direction
+static void win_goto_hor(bool left, long count)
+{
+ win_T *win = win_horz_neighbor(curtab, curwin, left, count);
+ if (win != NULL) {
+ win_goto(win);
+ }
}
/*
@@ -4242,9 +4306,12 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
}
if (trigger_enter_autocmds) {
- apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
- if (other_buffer)
- apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
+ apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
+ if (other_buffer) {
+ apply_autocmds(EVENT_BUFENTER, NULL, NULL, false, curbuf);
+ }
+ apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, false, curbuf);
+ curwin->w_last_cursormoved = curwin->w_cursor;
}
maketitle();
@@ -4374,6 +4441,7 @@ static win_T *win_alloc(win_T *after, int hidden)
new_wp->w_cursor.lnum = 1;
new_wp->w_scbind_pos = 1;
new_wp->w_floating = 0;
+ new_wp->w_float_config = FLOAT_CONFIG_INIT;
/* We won't calculate w_fraction until resizing the window */
new_wp->w_fraction = 0;
@@ -4642,8 +4710,12 @@ void win_size_restore(garray_T *gap)
{
int i = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- frame_setwidth(wp->w_frame, ((int *)gap->ga_data)[i++]);
- win_setheight_win(((int *)gap->ga_data)[i++], wp);
+ int width = ((int *)gap->ga_data)[i++];
+ int height = ((int *)gap->ga_data)[i++];
+ if (!wp->w_floating) {
+ frame_setwidth(wp->w_frame, width);
+ win_setheight_win(height, wp);
+ }
}
}
/* recompute the window positions */
@@ -4666,7 +4738,7 @@ int win_comp_pos(void)
// Too often, but when we support anchoring floats to split windows,
// this will be needed
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
- win_config_float(wp, wp->w_width, wp->w_height, wp->w_float_config);
+ win_config_float(wp, wp->w_float_config);
}
return row;
@@ -4739,7 +4811,8 @@ void win_setheight_win(int height, win_T *win)
if (win->w_floating) {
if (win->w_float_config.external) {
- win_config_float(win, win->w_width, height, win->w_float_config);
+ win->w_float_config.height = height;
+ win_config_float(win, win->w_float_config);
} else {
beep_flush();
return;
@@ -4944,7 +5017,8 @@ void win_setwidth_win(int width, win_T *wp)
}
if (wp->w_floating) {
if (wp->w_float_config.external) {
- win_config_float(wp, width, wp->w_height, wp->w_float_config);
+ wp->w_float_config.width = width;
+ win_config_float(wp, wp->w_float_config);
} else {
beep_flush();
return;
@@ -5770,7 +5844,7 @@ last_status (
{
/* Don't make a difference between horizontal or vertical split. */
last_status_rec(topframe, (p_ls == 2
- || (p_ls == 1 && (morewin || !ONE_WINDOW))));
+ || (p_ls == 1 && (morewin || !one_window()))));
}
static void last_status_rec(frame_T *fr, int statusline)
@@ -5889,16 +5963,40 @@ void check_lnums(int do_curwin)
{
FOR_ALL_TAB_WINDOWS(tp, wp) {
if ((do_curwin || wp != curwin) && wp->w_buffer == curbuf) {
+ // save the original cursor position and topline
+ wp->w_save_cursor.w_cursor_save = wp->w_cursor;
+ wp->w_save_cursor.w_topline_save = wp->w_topline;
+
if (wp->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
wp->w_cursor.lnum = curbuf->b_ml.ml_line_count;
}
if (wp->w_topline > curbuf->b_ml.ml_line_count) {
wp->w_topline = curbuf->b_ml.ml_line_count;
}
+
+ // save the corrected cursor position and topline
+ wp->w_save_cursor.w_cursor_corr = wp->w_cursor;
+ wp->w_save_cursor.w_topline_corr = wp->w_topline;
}
}
}
+/// Reset cursor and topline to its stored values from check_lnums().
+/// check_lnums() must have been called first!
+void reset_lnums(void)
+{
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ if (wp->w_buffer == curbuf) {
+ // Restore the value if the autocommand didn't change it.
+ if (equalpos(wp->w_save_cursor.w_cursor_corr, wp->w_cursor)) {
+ wp->w_cursor = wp->w_save_cursor.w_cursor_save;
+ }
+ if (wp->w_save_cursor.w_topline_corr == wp->w_topline) {
+ wp->w_topline = wp->w_save_cursor.w_topline_save;
+ }
+ }
+ }
+}
/*
* A snapshot of the window sizes, to restore them after closing the help
@@ -6044,7 +6142,7 @@ static win_T *get_snapshot_focus(int idx)
}
}
- return sn->fr_win;
+ return win_valid(sn->fr_win) ? sn->fr_win : NULL;
}
/*