summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-07-18 21:43:07 +0200
committerBram Moolenaar <Bram@vim.org>2019-07-18 21:43:07 +0200
commit7964873afe59d0896a921b7c585167674bb784d5 (patch)
treec72d46d9af739d51471bf940a1bc077e526daaf5 /src
parentdf9c6cad8cc318e26e99c3b055f0788e7d6582de (diff)
patch 8.1.1714: cannot preview a file in a popup windowv8.1.1714
Problem: Cannot preview a file in a popup window. Solution: Add the 'previewpopup' option.
Diffstat (limited to 'src')
-rw-r--r--src/ex_cmds.c32
-rw-r--r--src/ex_docmd.c7
-rw-r--r--src/option.c18
-rw-r--r--src/option.h3
-rw-r--r--src/popupwin.c269
-rw-r--r--src/proto/popupwin.pro6
-rw-r--r--src/testdir/dumps/Test_popupwin_previewpopup_1.dump14
-rw-r--r--src/testdir/dumps/Test_popupwin_previewpopup_2.dump14
-rw-r--r--src/testdir/gen_opt_test.vim1
-rw-r--r--src/version.c2
10 files changed, 301 insertions, 65 deletions
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 4126fe09f9..e262da1d59 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -6270,9 +6270,20 @@ prepare_tagpreview(
*/
if (!curwin->w_p_pvw)
{
- FOR_ALL_WINDOWS(wp)
- if (wp->w_p_pvw)
- break;
+# ifdef FEAT_TEXT_PROP
+ if (*p_pvp != NUL)
+ {
+ wp = popup_find_preview_window();
+ if (wp != NULL)
+ popup_set_wantpos(wp);
+ }
+ else
+# endif
+ {
+ FOR_ALL_WINDOWS(wp)
+ if (wp->w_p_pvw)
+ break;
+ }
if (wp != NULL)
win_enter(wp, undo_sync);
else
@@ -6280,18 +6291,21 @@ prepare_tagpreview(
/*
* There is no preview window open yet. Create one.
*/
- if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
- == FAIL)
+# ifdef FEAT_TEXT_PROP
+ if (*p_pvp != NUL)
+ return popup_create_preview_window();
+# endif
+ if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0) == FAIL)
return FALSE;
curwin->w_p_pvw = TRUE;
curwin->w_p_wfh = TRUE;
- RESET_BINDING(curwin); /* don't take over 'scrollbind'
- and 'cursorbind' */
+ RESET_BINDING(curwin); // don't take over 'scrollbind'
+ // and 'cursorbind'
# ifdef FEAT_DIFF
- curwin->w_p_diff = FALSE; /* no 'diff' */
+ curwin->w_p_diff = FALSE; // no 'diff'
# endif
# ifdef FEAT_FOLDING
- curwin->w_p_fdc = 0; /* no 'foldcolumn' */
+ curwin->w_p_fdc = 0; // no 'foldcolumn'
# endif
return TRUE;
}
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index a76261b40d..462851d6a1 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -5893,12 +5893,17 @@ ex_pclose(exarg_T *eap)
{
win_T *win;
+ // First close any normal window.
FOR_ALL_WINDOWS(win)
if (win->w_p_pvw)
{
ex_win_close(eap->forceit, win, NULL);
- break;
+ return;
}
+# ifdef FEAT_TEXT_PROP
+ // Also when 'previewpopup' is empty, it might have been cleared.
+ popup_close_preview();
+# endif
}
#endif
diff --git a/src/option.c b/src/option.c
index 4856a598d6..c17e9128a2 100644
--- a/src/option.c
+++ b/src/option.c
@@ -2079,6 +2079,15 @@ static struct vimoption options[] =
(char_u *)NULL, PV_NONE,
#endif
{(char_u *)12L, (char_u *)0L} SCTX_INIT},
+ {"previewpopup", "pvp", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_TEXT_PROP
+ (char_u *)&p_pvp, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ SCTX_INIT},
{"previewwindow", "pvw", P_BOOL|P_VI_DEF|P_RSTAT|P_NOGLOB,
#if defined(FEAT_QUICKFIX)
(char_u *)VAR_WIN, PV_PVW,
@@ -7831,6 +7840,15 @@ did_set_string_option(
}
#endif
+#ifdef FEAT_TEXT_PROP
+ // 'previewpopup'
+ else if (varp == &p_pvp)
+ {
+ if (parse_previewpopup(NULL) == FAIL)
+ errmsg = e_invarg;
+ }
+#endif
+
/* Options that are a list of flags. */
else
{
diff --git a/src/option.h b/src/option.h
index 7e657ddc3b..605d588eac 100644
--- a/src/option.h
+++ b/src/option.h
@@ -499,6 +499,9 @@ EXTERN char_u *p_fp; /* 'formatprg' */
EXTERN int p_fs; /* 'fsync' */
#endif
EXTERN int p_gd; /* 'gdefault' */
+#ifdef FEAT_TEXT_PROP
+EXTERN char_u *p_pvp; // 'previewpopup'
+#endif
#ifdef FEAT_PRINTER
EXTERN char_u *p_pdev; /* 'printdevice' */
# ifdef FEAT_POSTSCRIPT
diff --git a/src/popupwin.c b/src/popupwin.c
index 4fe64fd237..47a5c789dc 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -13,7 +13,7 @@
#include "vim.h"
-#ifdef FEAT_TEXT_PROP
+#if defined(FEAT_TEXT_PROP) || defined(PROTO)
typedef struct {
char *pp_name;
@@ -442,6 +442,18 @@ check_highlight(dict_T *dict, char *name, char_u **pval)
}
/*
+ * Scroll to show the line with the cursor. This assumes lines don't wrap.
+ */
+ static void
+popup_show_curline(win_T *wp)
+{
+ if (wp->w_cursor.lnum < wp->w_topline)
+ wp->w_topline = wp->w_cursor.lnum;
+ else if (wp->w_cursor.lnum >= wp->w_botline)
+ wp->w_topline = wp->w_cursor.lnum - wp->w_height + 1;
+}
+
+/*
* Highlight the line with the cursor.
* Also scrolls the text to put the cursor line in view.
*/
@@ -455,12 +467,7 @@ popup_highlight_curline(win_T *wp)
if ((wp->w_popup_flags & POPF_CURSORLINE) != 0)
{
- // Scroll to show the line with the cursor. This assumes lines don't
- // wrap.
- while (wp->w_topline + wp->w_height - 1 < wp->w_cursor.lnum)
- wp->w_topline++;
- while (wp->w_cursor.lnum < wp->w_topline)
- wp->w_topline--;
+ popup_show_curline(wp);
id = syn_name2id((char_u *)"PopupSelected");
vim_snprintf(buf, sizeof(buf), "\\%%%dl.*", (int)wp->w_cursor.lnum);
@@ -923,7 +930,8 @@ popup_adjust_position(win_T *wp)
}
// start at the desired first line
- wp->w_topline = wp->w_firstline;
+ if (wp->w_firstline != 0)
+ wp->w_topline = wp->w_firstline;
if (wp->w_topline > wp->w_buffer->b_ml.ml_line_count)
wp->w_topline = wp->w_buffer->b_ml.ml_line_count;
@@ -1078,7 +1086,8 @@ typedef enum
TYPE_BEVAL,
TYPE_NOTIFICATION,
TYPE_DIALOG,
- TYPE_MENU
+ TYPE_MENU,
+ TYPE_PREVIEW
} create_type_T;
/*
@@ -1124,59 +1133,134 @@ popup_set_buffer_text(buf_T *buf, typval_T text)
}
/*
+ * Parse the 'previewpopup' option and apply the values to window "wp" if it
+ * not NULL.
+ * Return FAIL if the parsing fails.
+ */
+ int
+parse_previewpopup(win_T *wp)
+{
+ char_u *p;
+
+ for (p = p_pvp; *p != NUL; p += (*p == ',' ? 1 : 0))
+ {
+ char_u *e, *dig;
+ char_u *s = p;
+ int x;
+
+ e = vim_strchr(p, ':');
+ if (e == NULL || e[1] == NUL)
+ return FAIL;
+
+ p = vim_strchr(e, ',');
+ if (p == NULL)
+ p = e + STRLEN(e);
+ dig = e + 1;
+ x = getdigits(&dig);
+ if (dig != p)
+ return FAIL;
+
+ if (STRNCMP(s, "height:", 7) == 0)
+ {
+ if (wp != NULL)
+ {
+ wp->w_minheight = x;
+ wp->w_maxheight = x;
+ }
+ }
+ else if (STRNCMP(s, "width:", 6) == 0)
+ {
+ if (wp != NULL)
+ {
+ wp->w_minwidth = x;
+ wp->w_maxwidth = x;
+ }
+ }
+ else
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * Set w_wantline and w_wantcol for the cursor position in the current window.
+ */
+ void
+popup_set_wantpos(win_T *wp)
+{
+ setcursor_mayforce(TRUE);
+ wp->w_wantline = curwin->w_winrow + curwin->w_wrow;
+ if (wp->w_wantline == 0) // cursor in first line
+ {
+ wp->w_wantline = 2;
+ wp->w_popup_pos = POPPOS_TOPLEFT;
+ }
+ wp->w_wantcol = curwin->w_wincol + curwin->w_wcol + 1;
+ popup_adjust_position(wp);
+}
+
+/*
* popup_create({text}, {options})
* popup_atcursor({text}, {options})
+ * etc.
+ * When creating a preview window popup "argvars" and "rettv" are NULL.
*/
static win_T *
popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
{
win_T *wp;
tabpage_T *tp = NULL;
- int tabnr;
+ int tabnr = 0;
int new_buffer;
buf_T *buf = NULL;
- dict_T *d;
+ dict_T *d = NULL;
int nr;
int i;
- // Check arguments look OK.
- if (argvars[0].v_type == VAR_NUMBER)
+ if (argvars != NULL)
{
- buf = buflist_findnr( argvars[0].vval.v_number);
- if (buf == NULL)
+ // Check arguments look OK.
+ if (argvars[0].v_type == VAR_NUMBER)
{
- semsg(_(e_nobufnr), argvars[0].vval.v_number);
+ buf = buflist_findnr( argvars[0].vval.v_number);
+ if (buf == NULL)
+ {
+ semsg(_(e_nobufnr), argvars[0].vval.v_number);
+ return NULL;
+ }
+ }
+ else if (!(argvars[0].v_type == VAR_STRING
+ && argvars[0].vval.v_string != NULL)
+ && !(argvars[0].v_type == VAR_LIST
+ && argvars[0].vval.v_list != NULL))
+ {
+ emsg(_(e_listreq));
return NULL;
}
+ if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)
+ {
+ emsg(_(e_dictreq));
+ return NULL;
+ }
+ d = argvars[1].vval.v_dict;
}
- else if (!(argvars[0].v_type == VAR_STRING
- && argvars[0].vval.v_string != NULL)
- && !(argvars[0].v_type == VAR_LIST
- && argvars[0].vval.v_list != NULL))
- {
- emsg(_(e_listreq));
- return NULL;
- }
- if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)
- {
- emsg(_(e_dictreq));
- return NULL;
- }
- d = argvars[1].vval.v_dict;
- if (dict_find(d, (char_u *)"tabpage", -1) != NULL)
- tabnr = (int)dict_get_number(d, (char_u *)"tabpage");
- else if (type == TYPE_NOTIFICATION)
- tabnr = -1; // notifications are global by default
- else
- tabnr = 0;
- if (tabnr > 0)
+ if (d != NULL)
{
- tp = find_tabpage(tabnr);
- if (tp == NULL)
+ if (dict_find(d, (char_u *)"tabpage", -1) != NULL)
+ tabnr = (int)dict_get_number(d, (char_u *)"tabpage");
+ else if (type == TYPE_NOTIFICATION)
+ tabnr = -1; // notifications are global by default
+ else
+ tabnr = 0;
+ if (tabnr > 0)
{
- semsg(_("E997: Tabpage not found: %d"), tabnr);
- return NULL;
+ tp = find_tabpage(tabnr);
+ if (tp == NULL)
+ {
+ semsg(_("E997: Tabpage not found: %d"), tabnr);
+ return NULL;
+ }
}
}
@@ -1184,7 +1268,8 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
wp = win_alloc_popup_win();
if (wp == NULL)
return NULL;
- rettv->vval.v_number = wp->w_id;
+ if (rettv != NULL)
+ rettv->vval.v_number = wp->w_id;
wp->w_popup_pos = POPPOS_TOPLEFT;
wp->w_popup_flags = POPF_IS_POPUP;
@@ -1211,7 +1296,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
set_string_option_direct_in_buf(buf, (char_u *)"buftype", -1,
(char_u *)"popup", OPT_FREE|OPT_LOCAL, 0);
set_string_option_direct_in_buf(buf, (char_u *)"bufhidden", -1,
- (char_u *)"hide", OPT_FREE|OPT_LOCAL, 0);
+ (char_u *)"wipe", OPT_FREE|OPT_LOCAL, 0);
buf->b_p_ul = -1; // no undo
buf->b_p_swf = FALSE; // no swap file
buf->b_p_bl = FALSE; // unlisted buffer
@@ -1250,20 +1335,16 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
}
}
- if (new_buffer)
+ if (new_buffer && argvars != NULL)
popup_set_buffer_text(buf, argvars[0]);
- if (type == TYPE_ATCURSOR)
+ if (type == TYPE_ATCURSOR || type == TYPE_PREVIEW)
{
wp->w_popup_pos = POPPOS_BOTLEFT;
- setcursor_mayforce(TRUE);
- wp->w_wantline = curwin->w_winrow + curwin->w_wrow;
- if (wp->w_wantline == 0) // cursor in first line
- {
- wp->w_wantline = 2;
- wp->w_popup_pos = POPPOS_TOPLEFT;
- }
- wp->w_wantcol = curwin->w_wincol + curwin->w_wcol + 1;
+ popup_set_wantpos(wp);
+ }
+ if (type == TYPE_ATCURSOR)
+ {
set_moved_values(wp);
set_moved_columns(wp, FIND_STRING);
}
@@ -1360,6 +1441,15 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
wp->w_popup_flags |= POPF_CURSORLINE;
}
+ if (type == TYPE_PREVIEW)
+ {
+ wp->w_popup_drag = 1;
+ wp->w_popup_close = POPCLOSE_BUTTON;
+ for (i = 0; i < 4; ++i)
+ wp->w_popup_border[i] = 1;
+ parse_previewpopup(wp);
+ }
+
for (i = 0; i < 4; ++i)
VIM_CLEAR(wp->w_border_highlight[i]);
for (i = 0; i < 8; ++i)
@@ -1367,8 +1457,9 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
wp->w_want_scrollbar = 1;
wp->w_popup_fixed = 0;
- // Deal with options.
- apply_options(wp, argvars[1].vval.v_dict);
+ if (d != NULL)
+ // Deal with options.
+ apply_options(wp, d);
#ifdef FEAT_TIMERS
if (type == TYPE_NOTIFICATION && wp->w_popup_timer == NULL)
@@ -2839,4 +2930,72 @@ set_ref_in_popups(int copyID)
}
return abort;
}
+
+/*
+ * Find an existing popup used as the preview window, in the current tab page.
+ * Return NULL if not found.
+ */
+ win_T *
+popup_find_preview_window(void)
+{
+ win_T *wp;
+
+ // Preview window popup is always local to tab page.
+ for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_p_pvw)
+ return wp;
+ return wp;
+}
+
+ int
+popup_is_popup(win_T *wp)
+{
+ return wp->w_popup_flags != 0;
+}
+
+/*
+ * Create a popup to be used as the preview window.
+ * NOTE: this makes the popup the current window, so that the file can be
+ * edited. However, it must not remain to be the current window, the caller
+ * must make sure of that.
+ */
+ int
+popup_create_preview_window(void)
+{
+ win_T *wp = popup_create(NULL, NULL, TYPE_PREVIEW);
+
+ if (wp == NULL)
+ return FAIL;
+ wp->w_p_pvw = TRUE;
+
+ // Set the width to a reasonable value, so that w_topline can be computed.
+ if (wp->w_minwidth > 0)
+ wp->w_width = wp->w_minwidth;
+ else if (wp->w_maxwidth > 0)
+ wp->w_width = wp->w_maxwidth;
+ else
+ wp->w_width = curwin->w_width;
+
+ // Will switch to another buffer soon, dummy one can be wiped.
+ wp->w_buffer->b_locked = FALSE;
+
+ win_enter(wp, FALSE);
+ return OK;
+}
+
+ void
+popup_close_preview()
+{
+ win_T *wp = popup_find_preview_window();
+
+ if (wp != NULL)
+ {
+ typval_T res;
+
+ res.v_type = VAR_NUMBER;
+ res.vval.v_number = -1;
+ popup_close_and_callback(wp, &res);
+ }
+}
+
#endif // FEAT_TEXT_PROP
diff --git a/src/proto/popupwin.pro b/src/proto/popupwin.pro
index d1267e0224..605575b77b 100644
--- a/src/proto/popupwin.pro
+++ b/src/proto/popupwin.pro
@@ -8,6 +8,8 @@ void popup_handle_scrollbar_click(win_T *wp, int row, int col);
int popup_height(win_T *wp);
int popup_width(win_T *wp);
void popup_adjust_position(win_T *wp);
+int parse_previewpopup(win_T *wp);
+void popup_set_wantpos(win_T *wp);
void f_popup_clear(typval_T *argvars, typval_T *rettv);
void f_popup_create(typval_T *argvars, typval_T *rettv);
void f_popup_atcursor(typval_T *argvars, typval_T *rettv);
@@ -39,4 +41,8 @@ void popup_check_cursor_pos(void);
void may_update_popup_mask(int type);
void update_popups(void (*win_update)(win_T *wp));
int set_ref_in_popups(int copyID);
+win_T *popup_find_preview_window(void);
+int popup_is_popup(win_T *wp);
+int popup_create_preview_window(void);
+void popup_close_preview(void);
/* vim: set ft=c : */
diff --git a/src/testdir/dumps/Test_popupwin_previewpopup_1.dump b/src/testdir/dumps/Test_popupwin_previewpopup_1.dump
new file mode 100644
index 0000000000..d23dd677f8
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_previewpopup_1.dump
@@ -0,0 +1,14 @@
+|o+0&#ffffff0|n|e| @71
+|t|w|o| @1|╔+0#0000001#ffd7ff255|═@40|X| +0#0000000#ffffff0@26
+|t|h|r|e@1|║+0#0000001#ffd7ff255|2|0| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
+|f|o|u|r| |║+0#0000001#ffd7ff255|t|h|e|w|o|r|d| |i|s| |h|e|r|e| @24| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
+|f|i|v|e| |║+0#0000001#ffd7ff255|2@1| @37| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
+|s|i|x| @1|║+0#0000001#ffd7ff255|2|3| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
+|s|e|v|e|n|╚+0#0000001#ffd7ff255|═@40|╝| +0#0000000#ffffff0@26
+|f|i|n|d| >t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @52
+|n|i|n|e| @70
+|t|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @54
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|:+0#0000000&| @55|8|,|6| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_popupwin_previewpopup_2.dump b/src/testdir/dumps/Test_popupwin_previewpopup_2.dump
new file mode 100644
index 0000000000..4d0e49ca0d
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_previewpopup_2.dump
@@ -0,0 +1,14 @@
+|o+0&#ffffff0|n|e| @71
+|t|w|o| @71
+|t|h|r|e@1| @69
+|f|o|u|r| @3|╔+0#0000001#ffd7ff255|═@40|X| +0#0000000#ffffff0@23
+|f|i|v|e| @3|║+0#0000001#ffd7ff255|2|7| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@23
+|s|i|x| @4|║+0#0000001#ffd7ff255|t|h|i|s| |i|s| |a|n|o|t|h|e|r| |p|l|a|c|e| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@23
+|s|e|v|e|n| @2|║+0#0000001#ffd7ff255|2|9| @37| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@23
+|f|i|n|d| |t|h|e|║+0#0000001#ffd7ff255|3|0| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@23
+|n|i|n|e| @3|╚+0#0000001#ffd7ff255|═@40|╝| +0#0000000#ffffff0@23
+|t|h|i|s| |i|s| >a|n|o|t|h|e|r| |w|o|r|d| @54
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|/+0#0000000&|a|n|o|t|h|e|r| @48|1|0|,|9| @9|A|l@1|
diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim
index 22d7c8cdba..e410feb42d 100644
--- a/src/testdir/gen_opt_test.vim
+++ b/src/testdir/gen_opt_test.vim
@@ -116,6 +116,7 @@ let test_values = {
\ 'mousemodel': [['', 'popup'], ['xxx']],
\ 'mouseshape': [['', 'n:arrow'], ['xxx']],
\ 'nrformats': [['', 'alpha', 'alpha,hex,bin'], ['xxx']],
+ \ 'previewpopup': [['', 'height:13', 'width:10,height:234'], ['height:yes', 'xxx', 'xxx:99']],
\ 'printmbfont': [['', 'r:some', 'b:Bold,c:yes'], ['xxx']],
\ 'printoptions': [['', 'header:0', 'left:10pc,top:5pc'], ['xxx']],
\ 'scrollopt': [['', 'ver', 'ver,hor'], ['xxx']],
diff --git a/src/version.c b/src/version.c
index 492e1ae29f..64a6daa80a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -778,6 +778,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1714,
+/**/
1713,
/**/
1712,