diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-06-15 21:46:30 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-06-15 21:46:30 +0200 |
commit | a42d945efc60e6130c15f72b5a5aa9fd2b63241a (patch) | |
tree | 241a17519918476c5d216d203fecad13d7ff4159 /src | |
parent | 26910de8b0da6abab87bd5a397330f9cbe483309 (diff) | |
download | vim-git-a42d945efc60e6130c15f72b5a5aa9fd2b63241a.tar.gz |
patch 8.1.1548: popup_dialog() is not implementedv8.1.1548
Problem: Popup_dialog() is not implemented.
Solution: Implement popup_dialog() and popup_filter_yesno().
Diffstat (limited to 'src')
-rw-r--r-- | src/evalfunc.c | 2 | ||||
-rw-r--r-- | src/globals.h | 3 | ||||
-rw-r--r-- | src/popupwin.c | 149 | ||||
-rw-r--r-- | src/proto/popupwin.pro | 2 | ||||
-rw-r--r-- | src/structs.h | 3 | ||||
-rw-r--r-- | src/testdir/test_popupwin.vim | 30 | ||||
-rw-r--r-- | src/version.c | 2 |
7 files changed, 158 insertions, 33 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 544426fa6..d371c28b6 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -815,6 +815,8 @@ static struct fst {"popup_clear", 0, 0, f_popup_clear}, {"popup_close", 1, 2, f_popup_close}, {"popup_create", 2, 2, f_popup_create}, + {"popup_dialog", 2, 2, f_popup_dialog}, + {"popup_filter_yesno", 2, 2, f_popup_filter_yesno}, {"popup_getoptions", 1, 1, f_popup_getoptions}, {"popup_getpos", 1, 1, f_popup_getpos}, {"popup_hide", 1, 1, f_popup_hide}, diff --git a/src/globals.h b/src/globals.h index 992ce2a54..ec4298494 100644 --- a/src/globals.h +++ b/src/globals.h @@ -599,7 +599,8 @@ EXTERN win_T *aucmd_win; /* window used in aucmd_prepbuf() */ EXTERN int aucmd_win_used INIT(= FALSE); /* aucmd_win is being used */ #ifdef FEAT_TEXT_PROP -EXTERN win_T *first_popupwin; // first global popup window +EXTERN win_T *first_popupwin; // first global popup window +EXTERN win_T *popup_dragwin INIT(= NULL); // popup window being dragged #endif /* diff --git a/src/popupwin.c b/src/popupwin.c index aeed2e79b..adbc72914 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -201,6 +201,10 @@ popup_start_drag(win_T *wp) drag_start_wantcol = wp->w_wincol + 1; else drag_start_wantcol = wp->w_wantcol; + + // Stop centering the popup + if (wp->w_popup_pos == POPPOS_CENTER) + wp->w_popup_pos = POPPOS_TOPLEFT; } /* @@ -301,7 +305,9 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict) wp->w_p_wrap = nr != 0; } - wp->w_popup_drag = dict_get_number(dict, (char_u *)"drag"); + di = dict_find(dict, (char_u *)"drag", -1); + if (di != NULL) + wp->w_popup_drag = dict_get_number(dict, (char_u *)"drag"); di = dict_find(dict, (char_u *)"callback", -1); if (di != NULL) @@ -692,13 +698,13 @@ typedef enum { TYPE_NORMAL, TYPE_ATCURSOR, - TYPE_NOTIFICATION + TYPE_NOTIFICATION, + TYPE_DIALOG } create_type_T; /* * popup_create({text}, {options}) * popup_atcursor({text}, {options}) - * When called from f_popup_atcursor() "type" is TYPE_ATCURSOR. */ static void popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) @@ -871,6 +877,20 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) OPT_FREE|OPT_LOCAL, 0); } + if (type == TYPE_DIALOG) + { + int i; + + wp->w_popup_pos = POPPOS_CENTER; + wp->w_zindex = POPUPWIN_DIALOG_ZINDEX; + wp->w_popup_drag = 1; + for (i = 0; i < 4; ++i) + { + wp->w_popup_border[i] = 1; + wp->w_popup_padding[i] = 1; + } + } + // Deal with options. apply_options(wp, buf, argvars[1].vval.v_dict); @@ -913,33 +933,6 @@ f_popup_atcursor(typval_T *argvars, typval_T *rettv) } /* - * popup_notification({text}, {options}) - */ - void -f_popup_notification(typval_T *argvars, typval_T *rettv) -{ - popup_create(argvars, rettv, TYPE_NOTIFICATION); -} - -/* - * Find the popup window with window-ID "id". - * If the popup window does not exist NULL is returned. - * If the window is not a popup window, and error message is given. - */ - static win_T * -find_popup_win(int id) -{ - win_T *wp = win_id2wp(id); - - if (wp != NULL && !bt_popup(wp->w_buffer)) - { - semsg(_("E993: window %d is not a popup window"), id); - return NULL; - } - return wp; -} - -/* * Invoke the close callback for window "wp" with value "result". * Careful: The callback may make "wp" invalid! */ @@ -986,6 +979,90 @@ popup_close_and_callback(win_T *wp, typval_T *arg) } /* + * popup_filter_yesno({text}, {options}) + */ + void +f_popup_filter_yesno(typval_T *argvars, typval_T *rettv) +{ + int id = tv_get_number(&argvars[0]); + win_T *wp = win_id2wp(id); + char_u *key = tv_get_string(&argvars[1]); + typval_T res; + + // If the popup has been closed don't consume the key. + if (wp == NULL) + return; + + // consume all keys until done + rettv->vval.v_number = 1; + + if (STRCMP(key, "y") == 0 || STRCMP(key, "Y") == 0) + res.vval.v_number = 1; + else if (STRCMP(key, "n") == 0 || STRCMP(key, "N") == 0 + || STRCMP(key, "x") == 0 || STRCMP(key, "X") == 0 + || STRCMP(key, "\x1b") == 0) + res.vval.v_number = 0; + else + { + int c = *key; + int row = mouse_row; + int col = mouse_col; + + if (c == K_SPECIAL && key[1] != NUL) + c = TO_SPECIAL(key[1], key[2]); + if (wp->w_popup_drag + && is_mouse_key(c) + && (wp == popup_dragwin + || wp == mouse_find_win(&row, &col, FIND_POPUP))) + // allow for dragging the popup + rettv->vval.v_number = 0; + + // ignore this key + return; + } + + // Invoke callback + res.v_type = VAR_NUMBER; + popup_close_and_callback(wp, &res); +} + +/* + * popup_dialog({text}, {options}) + */ + void +f_popup_dialog(typval_T *argvars, typval_T *rettv) +{ + popup_create(argvars, rettv, TYPE_DIALOG); +} + +/* + * popup_notification({text}, {options}) + */ + void +f_popup_notification(typval_T *argvars, typval_T *rettv) +{ + popup_create(argvars, rettv, TYPE_NOTIFICATION); +} + +/* + * Find the popup window with window-ID "id". + * If the popup window does not exist NULL is returned. + * If the window is not a popup window, and error message is given. + */ + static win_T * +find_popup_win(int id) +{ + win_T *wp = win_id2wp(id); + + if (wp != NULL && !bt_popup(wp->w_buffer)) + { + semsg(_("E993: window %d is not a popup window"), id); + return NULL; + } + return wp; +} + +/* * popup_close({id}) */ void @@ -1299,6 +1376,15 @@ invoke_popup_filter(win_T *wp, int c) typval_T argv[3]; char_u buf[NUMBUFLEN]; + // Emergency exit: CTRL-C closes the popup. + if (c == Ctrl_C) + { + rettv.v_type = VAR_NUMBER; + rettv.vval.v_number = -1; + popup_close_and_callback(wp, &rettv); + return 1; + } + argv[0].v_type = VAR_NUMBER; argv[0].vval.v_number = (varnumber_T)wp->w_id; @@ -1310,6 +1396,7 @@ invoke_popup_filter(win_T *wp, int c) argv[2].v_type = VAR_UNKNOWN; + // NOTE: The callback might close the popup, thus make "wp" invalid. call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL); res = tv_get_number(&rettv); @@ -1326,7 +1413,7 @@ invoke_popup_filter(win_T *wp, int c) popup_do_filter(int c) { int res = FALSE; - win_T *wp; + win_T *wp; popup_reset_handled(); diff --git a/src/proto/popupwin.pro b/src/proto/popupwin.pro index cde0cae6e..6e93791e6 100644 --- a/src/proto/popupwin.pro +++ b/src/proto/popupwin.pro @@ -8,6 +8,8 @@ void popup_adjust_position(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); +void f_popup_filter_yesno(typval_T *argvars, typval_T *rettv); +void f_popup_dialog(typval_T *argvars, typval_T *rettv); void f_popup_notification(typval_T *argvars, typval_T *rettv); void f_popup_close(typval_T *argvars, typval_T *rettv); void f_popup_hide(typval_T *argvars, typval_T *rettv); diff --git a/src/structs.h b/src/structs.h index 59259274a..09158a0cc 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1998,7 +1998,8 @@ typedef enum { # define POPUPWIN_DEFAULT_ZINDEX 50 # define POPUPMENU_ZINDEX 100 -# define POPUPWIN_NOTIFICATION_ZINDEX 200 +# define POPUPWIN_DIALOG_ZINDEX 200 +# define POPUPWIN_NOTIFICATION_ZINDEX 300 #endif /* diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index a3f2046f4..f7a319c23 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -870,6 +870,36 @@ func Test_popup_filter() call popup_clear() endfunc +func ShowDialog(key, result) + let s:cb_res = 999 + let winid = popup_dialog('do you want to quit (Yes/no)?', { + \ 'filter': 'popup_filter_yesno', + \ 'callback': 'QuitCallback', + \ }) + redraw + call feedkeys(a:key, "xt") + call assert_equal(winid, s:cb_winid) + call assert_equal(a:result, s:cb_res) +endfunc + +func Test_popup_dialog() + func QuitCallback(id, res) + let s:cb_winid = a:id + let s:cb_res = a:res + endfunc + + let winid = ShowDialog("y", 1) + let winid = ShowDialog("Y", 1) + let winid = ShowDialog("n", 0) + let winid = ShowDialog("N", 0) + let winid = ShowDialog("x", 0) + let winid = ShowDialog("X", 0) + let winid = ShowDialog("\<Esc>", 0) + let winid = ShowDialog("\<C-C>", -1) + + delfunc QuitCallback +endfunc + func Test_popup_close_callback() func PopupDone(id, result) let g:result = a:result diff --git a/src/version.c b/src/version.c index 113fb97ce..9d457038e 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 */ /**/ + 1548, +/**/ 1547, /**/ 1546, |