summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-05-25 19:51:39 +0200
committerBram Moolenaar <Bram@vim.org>2019-05-25 19:51:39 +0200
commit4d784b21d14fc66e98a2b07f70343cdd4acd62aa (patch)
treec2e869a4f07eebdf7e0272c74b0fe7392807836c /src/window.c
parent8f46e4c4bde13fd5ad68a6670b79cc462b65fbec (diff)
downloadvim-git-4d784b21d14fc66e98a2b07f70343cdd4acd62aa.tar.gz
patch 8.1.1391: no popup window supportv8.1.1391
Problem: No popup window support. Solution: Add initial code for popup windows. Add the 'wincolor' option.
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c176
1 files changed, 131 insertions, 45 deletions
diff --git a/src/window.c b/src/window.c
index 6e02caad6..bed3d3fb7 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1362,6 +1362,21 @@ win_init_some(win_T *newp, win_T *oldp)
win_copy_options(oldp, newp);
}
+ static int
+win_valid_popup(win_T *win)
+{
+#ifdef FEAT_TEXT_PROP
+ win_T *wp;
+
+ for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
+ if (wp == win)
+ return TRUE;
+ for (wp = first_tab_popupwin; wp != NULL; wp = wp->w_next)
+ if (wp == win)
+ return TRUE;
+#endif
+ return FALSE;
+}
/*
* Check if "win" is a pointer to an existing window in the current tab page.
@@ -1376,7 +1391,7 @@ win_valid(win_T *win)
FOR_ALL_WINDOWS(wp)
if (wp == win)
return TRUE;
- return FALSE;
+ return win_valid_popup(win);
}
/*
@@ -1398,7 +1413,7 @@ win_valid_any_tab(win_T *win)
return TRUE;
}
}
- return FALSE;
+ return win_valid_popup(win);
}
/*
@@ -2293,6 +2308,44 @@ close_last_window_tabpage(
}
/*
+ * Close the buffer of "win" and unload it if "free_buf" is TRUE.
+ * "abort_if_last" is passed to close_buffer(): abort closing if all other
+ * windows are closed.
+ */
+ static void
+win_close_buffer(win_T *win, int free_buf, int abort_if_last)
+{
+#ifdef FEAT_SYN_HL
+ // Free independent synblock before the buffer is freed.
+ if (win->w_buffer != NULL)
+ reset_synblock(win);
+#endif
+
+#ifdef FEAT_QUICKFIX
+ // When the quickfix/location list window is closed, unlist the buffer.
+ if (win->w_buffer != NULL && bt_quickfix(win->w_buffer))
+ win->w_buffer->b_p_bl = FALSE;
+#endif
+
+ // Close the link to the buffer.
+ if (win->w_buffer != NULL)
+ {
+ bufref_T bufref;
+
+ set_bufref(&bufref, curbuf);
+ win->w_closing = TRUE;
+ close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0,
+ abort_if_last);
+ if (win_valid_any_tab(win))
+ win->w_closing = FALSE;
+ // Make sure curbuf is valid. It can become invalid if 'bufhidden' is
+ // "wipe".
+ if (!bufref_valid(&bufref))
+ curbuf = firstbuf;
+ }
+}
+
+/*
* Close window "win". Only works for the current tab page.
* If "free_buf" is TRUE related buffer may be unloaded.
*
@@ -2319,9 +2372,9 @@ win_close(win_T *win, int free_buf)
if (win->w_closing || (win->w_buffer != NULL
&& win->w_buffer->b_locked > 0))
return FAIL; /* window is already being closed */
- if (win == aucmd_win)
+ if (win_unlisted(win))
{
- emsg(_("E813: Cannot close autocmd window"));
+ emsg(_("E813: Cannot close autocmd or popup window"));
return FAIL;
}
if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window())
@@ -2390,35 +2443,7 @@ win_close(win_T *win, int free_buf)
out_flush();
#endif
-#ifdef FEAT_SYN_HL
- // Free independent synblock before the buffer is freed.
- if (win->w_buffer != NULL)
- reset_synblock(win);
-#endif
-
-#ifdef FEAT_QUICKFIX
- // When the quickfix/location list window is closed, unlist the buffer.
- if (win->w_buffer != NULL && bt_quickfix(win->w_buffer))
- win->w_buffer->b_p_bl = FALSE;
-#endif
-
- /*
- * Close the link to the buffer.
- */
- if (win->w_buffer != NULL)
- {
- bufref_T bufref;
-
- set_bufref(&bufref, curbuf);
- win->w_closing = TRUE;
- close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, TRUE);
- if (win_valid_any_tab(win))
- win->w_closing = FALSE;
- /* Make sure curbuf is valid. It can become invalid if 'bufhidden' is
- * "wipe". */
- if (!bufref_valid(&bufref))
- curbuf = firstbuf;
- }
+ win_close_buffer(win, free_buf, TRUE);
if (only_one_window() && win_valid(win) && win->w_buffer == NULL
&& (last_window() || curtab != prev_curtab
@@ -2627,6 +2652,9 @@ win_free_all(void)
(void)win_free_mem(aucmd_win, &dummy, NULL);
aucmd_win = NULL;
}
+# ifdef FEAT_TEXT_PROP
+ close_all_popups();
+# endif
while (firstwin != NULL)
(void)win_free_mem(firstwin, &dummy, NULL);
@@ -3458,7 +3486,7 @@ win_init_empty(win_T *wp)
wp->w_topfill = 0;
#endif
wp->w_botline = 2;
-#ifdef FEAT_SYN_HL
+#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
wp->w_s = &wp->w_buffer->b_s;
#endif
}
@@ -3484,19 +3512,41 @@ win_alloc_first(void)
}
/*
- * Init "aucmd_win". This can only be done after the first
- * window is fully initialized, thus it can't be in win_alloc_first().
+ * Allocate and init a window that is not a regular window.
+ * 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)
+ win_T *
+win_alloc_popup_win(void)
{
- aucmd_win = win_alloc(NULL, TRUE);
- if (aucmd_win != NULL)
+ win_T *wp;
+
+ wp = win_alloc(NULL, TRUE);
+ if (wp != NULL)
{
- win_init_some(aucmd_win, curwin);
- RESET_BINDING(aucmd_win);
- new_frame(aucmd_win);
+ // We need to initialize options with something, using the current
+ // window makes most sense.
+ win_init_some(wp, curwin);
+
+ RESET_BINDING(wp);
+ new_frame(wp);
}
+ return wp;
+}
+
+/*
+ * Initialize window "wp" to display buffer "buf".
+ */
+ void
+win_init_popup_win(win_T *wp, buf_T *buf)
+{
+ wp->w_buffer = buf;
+ ++buf->b_nwindows;
+ win_init_empty(wp); // set cursor and topline to safe values
+
+ // Make sure w_localdir and globaldir are NULL to avoid a chdir() in
+ // win_enter_ext().
+ VIM_CLEAR(wp->w_localdir);
}
/*
@@ -3619,6 +3669,10 @@ free_tabpage(tabpage_T *tp)
# ifdef FEAT_DIFF
diff_clear(tp);
# endif
+# ifdef FEAT_TEXT_PROP
+ while (tp->tp_first_popupwin != NULL)
+ popup_close(tp->tp_first_popupwin->w_id);
+#endif
for (idx = 0; idx < SNAP_COUNT; ++idx)
clear_snapshot(tp, idx);
#ifdef FEAT_EVAL
@@ -4782,7 +4836,7 @@ win_free(
vim_free(wp->w_p_cc_cols);
#endif
- if (wp != aucmd_win)
+ if (win_valid_any_tab(wp))
win_remove(wp, tp);
if (autocmd_busy)
{
@@ -4796,6 +4850,28 @@ win_free(
}
/*
+ * Return TRUE if "wp" is not in the list of windows: the autocmd window or a
+ * popup window.
+ */
+ int
+win_unlisted(win_T *wp)
+{
+ return wp == aucmd_win || bt_popup(wp->w_buffer);
+}
+
+/*
+ * Free a popup window. This does not take the window out of the window list
+ * and assumes there is only one toplevel frame, no split.
+ */
+ void
+win_free_popup(win_T *win)
+{
+ win_close_buffer(win, TRUE, FALSE);
+ vim_free(win->w_frame);
+ win_free(win, NULL);
+}
+
+/*
* Append window "wp" in the window list after window "after".
*/
void
@@ -6182,7 +6258,7 @@ min_rows(void)
/*
* Return TRUE if there is only one window (in the current tab page), not
* counting a help or preview window, unless it is the current window.
- * Does not count "aucmd_win".
+ * Does not count unlisted windows.
*/
int
only_one_window(void)
@@ -6974,6 +7050,16 @@ win_id2wp(int id)
FOR_ALL_TAB_WINDOWS(tp, wp)
if (wp->w_id == id)
return wp;
+#ifdef FEAT_TEXT_PROP
+ // popup windows are in a separate list
+ FOR_ALL_TABPAGES(tp)
+ for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_id == id)
+ return wp;
+ for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_id == id)
+ return wp;
+#endif
return NULL;
}