Mercurial > vim
diff src/popupmnu.c @ 12865:ebb4f6c93598 v8.0.1309
patch 8.0.1309: cannot use 'balloonexpr' in a terminal
commit https://github.com/vim/vim/commit/51b0f3701ecb440aa72ab6017c1df6940c0e0f6f
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Nov 18 18:52:04 2017 +0100
patch 8.0.1309: cannot use 'balloonexpr' in a terminal
Problem: Cannot use 'balloonexpr' in a terminal.
Solution: Add 'balloonevalterm' and add code to handle mouse movements in a
terminal. Initial implementation for Unix with GUI.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 18 Nov 2017 19:00:06 +0100 |
parents | fad36581f788 |
children | 1a450ce6980c |
line wrap: on
line diff
--- a/src/popupmnu.c +++ b/src/popupmnu.c @@ -23,6 +23,7 @@ static int pum_height; /* nr of displa static int pum_width; /* width of displayed pum items */ static int pum_base_width; /* width of pum items base */ static int pum_kind_width; /* width of pum items kind column */ +static int pum_extra_width; /* width of extra stuff */ static int pum_scrollbar; /* TRUE when scrollbar present */ static int pum_row; /* top row of pum */ @@ -35,6 +36,36 @@ static int pum_set_selected(int n, int r #define PUM_DEF_HEIGHT 10 #define PUM_DEF_WIDTH 15 + static void +pum_compute_size(void) +{ + int i; + int w; + + /* Compute the width of the widest match and the widest extra. */ + pum_base_width = 0; + pum_kind_width = 0; + pum_extra_width = 0; + for (i = 0; i < pum_size; ++i) + { + w = vim_strsize(pum_array[i].pum_text); + if (pum_base_width < w) + pum_base_width = w; + if (pum_array[i].pum_kind != NULL) + { + w = vim_strsize(pum_array[i].pum_kind) + 1; + if (pum_kind_width < w) + pum_kind_width = w; + } + if (pum_array[i].pum_extra != NULL) + { + w = vim_strsize(pum_array[i].pum_extra) + 1; + if (pum_extra_width < w) + pum_extra_width = w; + } + } +} + /* * Show the popup menu with items "array[size]". * "array" must remain valid until pum_undisplay() is called! @@ -48,12 +79,8 @@ pum_display( int selected) /* index of initially selected item, none if out of range */ { - int w; int def_width; int max_width; - int kind_width; - int extra_width; - int i; int row; int context_lines; int col; @@ -67,9 +94,6 @@ pum_display( do { def_width = PUM_DEF_WIDTH; - max_width = 0; - kind_width = 0; - extra_width = 0; above_row = 0; below_row = cmdline_row; @@ -107,7 +131,7 @@ pum_display( /* Put the pum below "row" if possible. If there are few lines decide * on where there is more room. */ if (row + 2 >= below_row - pum_height - && row - above_row > (below_row - above_row) / 2) + && row - above_row > (below_row - above_row) / 2) { /* pum above "row" */ @@ -167,27 +191,10 @@ pum_display( } #endif - /* Compute the width of the widest match and the widest extra. */ - for (i = 0; i < size; ++i) - { - w = vim_strsize(array[i].pum_text); - if (max_width < w) - max_width = w; - if (array[i].pum_kind != NULL) - { - w = vim_strsize(array[i].pum_kind) + 1; - if (kind_width < w) - kind_width = w; - } - if (array[i].pum_extra != NULL) - { - w = vim_strsize(array[i].pum_extra) + 1; - if (extra_width < w) - extra_width = w; - } - } - pum_base_width = max_width; - pum_kind_width = kind_width; + pum_array = array; + pum_size = size; + pum_compute_size(); + max_width = pum_base_width; /* Calculate column */ #ifdef FEAT_RIGHTLEFT @@ -226,10 +233,10 @@ pum_display( #endif pum_width = Columns - pum_col - pum_scrollbar; - if (pum_width > max_width + kind_width + extra_width + 1 - && pum_width > PUM_DEF_WIDTH) + if (pum_width > max_width + pum_kind_width + pum_extra_width + 1 + && pum_width > PUM_DEF_WIDTH) { - pum_width = max_width + kind_width + extra_width + 1; + pum_width = max_width + pum_kind_width + pum_extra_width + 1; if (pum_width < PUM_DEF_WIDTH) pum_width = PUM_DEF_WIDTH; } @@ -258,9 +265,6 @@ pum_display( pum_width = max_width - pum_scrollbar; } - pum_array = array; - pum_size = size; - /* Set selected item and redraw. If the window size changed need to * redo the positioning. Limit this to two times, when there is not * much room the window size will keep changing. */ @@ -756,4 +760,97 @@ pum_get_height(void) return pum_height; } +# if defined(FEAT_BEVALTERM) || defined(PROTO) +static pumitem_T *balloon_array = NULL; +static int balloon_arraysize; +static int balloon_mouse_row = 0; +static int balloon_mouse_col = 0; + +#define BALLOON_MIN_WIDTH 40 +#define BALLOON_MIN_HEIGHT 10 + + void +ui_remove_balloon(void) +{ + if (balloon_array != NULL) + { + pum_undisplay(); + while (balloon_arraysize > 0) + vim_free(balloon_array[--balloon_arraysize].pum_text); + vim_free(balloon_array); + balloon_array = NULL; + } +} + +/* + * Terminal version of a balloon, uses the popup menu code. + */ + void +ui_post_balloon(char_u *mesg) +{ + ui_remove_balloon(); + + /* TODO: split the text in multiple lines. */ + balloon_arraysize = 3; + balloon_array = (pumitem_T *)alloc_clear( + (unsigned)sizeof(pumitem_T) * balloon_arraysize); + if (balloon_array != NULL) + { + /* Add an empty line above and below, looks better. */ + balloon_array[0].pum_text = vim_strsave((char_u *)""); + balloon_array[1].pum_text = vim_strsave(mesg); + balloon_array[2].pum_text = vim_strsave((char_u *)""); + + pum_array = balloon_array; + pum_size = balloon_arraysize; + pum_compute_size(); + pum_scrollbar = 0; + pum_height = balloon_arraysize; + + if (Rows - mouse_row > BALLOON_MIN_HEIGHT) + { + /* Enough space below the mouse row. */ + pum_row = mouse_row + 1; + if (pum_height > Rows - pum_row) + pum_height = Rows - pum_row; + } + else + { + /* Show above the mouse row, reduce height if it does not fit. */ + pum_row = mouse_row - 1 - pum_size; + if (pum_row < 0) + { + pum_height += pum_row; + pum_row = 0; + } + } + if (Columns - mouse_col >= pum_base_width + || Columns - mouse_col > BALLOON_MIN_WIDTH) + /* Enough space to show at mouse column. */ + pum_col = mouse_col; + else + /* Not enough space, right align with window. */ + pum_col = Columns - (pum_base_width > BALLOON_MIN_WIDTH + ? BALLOON_MIN_WIDTH : pum_base_width); + + pum_width = Columns - pum_col; + if (pum_width > pum_base_width + 1) + pum_width = pum_base_width + 1; + + pum_selected = -1; + pum_first = 0; + pum_redraw(); + } +} + +/* + * Called when the mouse moved, may remove any displayed balloon. + */ + void +ui_may_remove_balloon(void) +{ + if (mouse_row != balloon_mouse_row || mouse_col != balloon_mouse_col) + ui_remove_balloon(); +} +# endif #endif