Mercurial > vim
diff src/popupwin.c @ 16880:998603a243d7 v8.1.1441
patch 8.1.1441: popup window filter not yet implemented
commit https://github.com/vim/vim/commit/bf0eff0b724ebf4951f7ca82e6c648451f9f0c01
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jun 1 17:13:36 2019 +0200
patch 8.1.1441: popup window filter not yet implemented
Problem: Popup window filter not yet implemented.
Solution: Implement the popup filter.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 01 Jun 2019 17:15:06 +0200 |
parents | da5f5836e90c |
children | 59e4148c0c73 |
line wrap: on
line diff
--- a/src/popupwin.c +++ b/src/popupwin.c @@ -149,25 +149,33 @@ apply_options(win_T *wp, buf_T *buf UNUS if (get_lambda_tv(&ptr, &tv, TRUE) == OK) { wp->w_popup_timer = create_timer(nr, 0); - wp->w_popup_timer->tr_callback.cb_name = - vim_strsave(partial_name(tv.vval.v_partial)); - func_ref(wp->w_popup_timer->tr_callback.cb_name); - wp->w_popup_timer->tr_callback.cb_partial = tv.vval.v_partial; + wp->w_popup_timer->tr_callback = get_callback(&tv); + clear_tv(&tv); } } #endif // Option values resulting in setting an option. - str = dict_get_string(dict, (char_u *)"highlight", TRUE); + str = dict_get_string(dict, (char_u *)"highlight", FALSE); if (str != NULL) set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, str, OPT_FREE|OPT_LOCAL, 0); + di = dict_find(dict, (char_u *)"wrap", -1); if (di != NULL) { nr = dict_get_number(dict, (char_u *)"wrap"); wp->w_p_wrap = nr != 0; } + + di = dict_find(dict, (char_u *)"filter", -1); + if (di != NULL) + { + callback_T callback = get_callback(&di->di_tv); + + if (callback.cb_name != NULL) + set_callback(&wp->w_filter_cb, &callback); + } } /* @@ -759,4 +767,109 @@ not_in_popup_window() return FALSE; } +/* + * Reset all the POPF_HANDLED flags in global popup windows and popup windows + * in the current tab. + */ + void +popup_reset_handled() +{ + win_T *wp; + + for (wp = first_popupwin; wp != NULL; wp = wp->w_next) + wp->w_popup_flags &= ~POPF_HANDLED; + for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next) + wp->w_popup_flags &= ~POPF_HANDLED; +} + +/* + * Find the next visible popup where POPF_HANDLED is not set. + * Must have called popup_reset_handled() first. + * When "lowest" is TRUE find the popup with the lowest zindex, otherwise the + * popup with the highest zindex. + */ + win_T * +find_next_popup(int lowest) +{ + win_T *wp; + win_T *found_wp; + int found_zindex; + + found_zindex = lowest ? INT_MAX : 0; + found_wp = NULL; + for (wp = first_popupwin; wp != NULL; wp = wp->w_next) + if ((wp->w_popup_flags & (POPF_HANDLED|POPF_HIDDEN)) == 0 + && (lowest ? wp->w_zindex < found_zindex + : wp->w_zindex > found_zindex)) + { + found_zindex = wp->w_zindex; + found_wp = wp; + } + for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next) + if ((wp->w_popup_flags & (POPF_HANDLED|POPF_HIDDEN)) == 0 + && (lowest ? wp->w_zindex < found_zindex + : wp->w_zindex > found_zindex)) + { + found_zindex = wp->w_zindex; + found_wp = wp; + } + + if (found_wp != NULL) + found_wp->w_popup_flags |= POPF_HANDLED; + return found_wp; +} + +/* + * Invoke the filter callback for window "wp" with typed character "c". + * Uses the global "mod_mask" for modifiers. + * Returns the return value of the filter. + * Careful: The filter may make "wp" invalid! + */ + static int +invoke_popup_filter(win_T *wp, int c) +{ + int res; + typval_T rettv; + int dummy; + typval_T argv[3]; + char_u buf[NUMBUFLEN]; + + argv[0].v_type = VAR_NUMBER; + argv[0].vval.v_number = (varnumber_T)wp->w_id; + + // Convert the number to a string, so that the function can use: + // if a:c == "\<F2>" + buf[special_to_buf(c, mod_mask, TRUE, buf)] = NUL; + argv[1].v_type = VAR_STRING; + argv[1].vval.v_string = vim_strsave(buf); + + argv[2].v_type = VAR_UNKNOWN; + + call_callback(&wp->w_filter_cb, -1, + &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL); + res = tv_get_number(&rettv); + vim_free(argv[1].vval.v_string); + clear_tv(&rettv); + return res; +} + +/* + * Called when "c" was typed: invoke popup filter callbacks. + * Returns TRUE when the character was consumed, + */ + int +popup_do_filter(int c) +{ + int res = FALSE; + win_T *wp; + + popup_reset_handled(); + + while (!res && (wp = find_next_popup(FALSE)) != NULL) + if (wp->w_filter_cb.cb_name != NULL) + res = invoke_popup_filter(wp, c); + + return res; +} + #endif // FEAT_TEXT_PROP