Mercurial > vim
comparison 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 |
comparison
equal
deleted
inserted
replaced
12864:e98532b79dba | 12865:ebb4f6c93598 |
---|---|
21 | 21 |
22 static int pum_height; /* nr of displayed pum items */ | 22 static int pum_height; /* nr of displayed pum items */ |
23 static int pum_width; /* width of displayed pum items */ | 23 static int pum_width; /* width of displayed pum items */ |
24 static int pum_base_width; /* width of pum items base */ | 24 static int pum_base_width; /* width of pum items base */ |
25 static int pum_kind_width; /* width of pum items kind column */ | 25 static int pum_kind_width; /* width of pum items kind column */ |
26 static int pum_extra_width; /* width of extra stuff */ | |
26 static int pum_scrollbar; /* TRUE when scrollbar present */ | 27 static int pum_scrollbar; /* TRUE when scrollbar present */ |
27 | 28 |
28 static int pum_row; /* top row of pum */ | 29 static int pum_row; /* top row of pum */ |
29 static int pum_col; /* left column of pum */ | 30 static int pum_col; /* left column of pum */ |
30 | 31 |
32 | 33 |
33 static int pum_set_selected(int n, int repeat); | 34 static int pum_set_selected(int n, int repeat); |
34 | 35 |
35 #define PUM_DEF_HEIGHT 10 | 36 #define PUM_DEF_HEIGHT 10 |
36 #define PUM_DEF_WIDTH 15 | 37 #define PUM_DEF_WIDTH 15 |
38 | |
39 static void | |
40 pum_compute_size(void) | |
41 { | |
42 int i; | |
43 int w; | |
44 | |
45 /* Compute the width of the widest match and the widest extra. */ | |
46 pum_base_width = 0; | |
47 pum_kind_width = 0; | |
48 pum_extra_width = 0; | |
49 for (i = 0; i < pum_size; ++i) | |
50 { | |
51 w = vim_strsize(pum_array[i].pum_text); | |
52 if (pum_base_width < w) | |
53 pum_base_width = w; | |
54 if (pum_array[i].pum_kind != NULL) | |
55 { | |
56 w = vim_strsize(pum_array[i].pum_kind) + 1; | |
57 if (pum_kind_width < w) | |
58 pum_kind_width = w; | |
59 } | |
60 if (pum_array[i].pum_extra != NULL) | |
61 { | |
62 w = vim_strsize(pum_array[i].pum_extra) + 1; | |
63 if (pum_extra_width < w) | |
64 pum_extra_width = w; | |
65 } | |
66 } | |
67 } | |
37 | 68 |
38 /* | 69 /* |
39 * Show the popup menu with items "array[size]". | 70 * Show the popup menu with items "array[size]". |
40 * "array" must remain valid until pum_undisplay() is called! | 71 * "array" must remain valid until pum_undisplay() is called! |
41 * When possible the leftmost character is aligned with screen column "col". | 72 * When possible the leftmost character is aligned with screen column "col". |
46 pumitem_T *array, | 77 pumitem_T *array, |
47 int size, | 78 int size, |
48 int selected) /* index of initially selected item, none if | 79 int selected) /* index of initially selected item, none if |
49 out of range */ | 80 out of range */ |
50 { | 81 { |
51 int w; | |
52 int def_width; | 82 int def_width; |
53 int max_width; | 83 int max_width; |
54 int kind_width; | |
55 int extra_width; | |
56 int i; | |
57 int row; | 84 int row; |
58 int context_lines; | 85 int context_lines; |
59 int col; | 86 int col; |
60 int above_row; | 87 int above_row; |
61 int below_row; | 88 int below_row; |
65 #endif | 92 #endif |
66 | 93 |
67 do | 94 do |
68 { | 95 { |
69 def_width = PUM_DEF_WIDTH; | 96 def_width = PUM_DEF_WIDTH; |
70 max_width = 0; | |
71 kind_width = 0; | |
72 extra_width = 0; | |
73 above_row = 0; | 97 above_row = 0; |
74 below_row = cmdline_row; | 98 below_row = cmdline_row; |
75 | 99 |
76 /* Pretend the pum is already there to avoid that must_redraw is set | 100 /* Pretend the pum is already there to avoid that must_redraw is set |
77 * when 'cuc' is on. */ | 101 * when 'cuc' is on. */ |
105 pum_height = p_ph; | 129 pum_height = p_ph; |
106 | 130 |
107 /* Put the pum below "row" if possible. If there are few lines decide | 131 /* Put the pum below "row" if possible. If there are few lines decide |
108 * on where there is more room. */ | 132 * on where there is more room. */ |
109 if (row + 2 >= below_row - pum_height | 133 if (row + 2 >= below_row - pum_height |
110 && row - above_row > (below_row - above_row) / 2) | 134 && row - above_row > (below_row - above_row) / 2) |
111 { | 135 { |
112 /* pum above "row" */ | 136 /* pum above "row" */ |
113 | 137 |
114 /* Leave two lines of context if possible */ | 138 /* Leave two lines of context if possible */ |
115 if (curwin->w_wrow - curwin->w_cline_row >= 2) | 139 if (curwin->w_wrow - curwin->w_cline_row >= 2) |
165 pum_row += above_row; | 189 pum_row += above_row; |
166 pum_height -= above_row; | 190 pum_height -= above_row; |
167 } | 191 } |
168 #endif | 192 #endif |
169 | 193 |
170 /* Compute the width of the widest match and the widest extra. */ | 194 pum_array = array; |
171 for (i = 0; i < size; ++i) | 195 pum_size = size; |
172 { | 196 pum_compute_size(); |
173 w = vim_strsize(array[i].pum_text); | 197 max_width = pum_base_width; |
174 if (max_width < w) | |
175 max_width = w; | |
176 if (array[i].pum_kind != NULL) | |
177 { | |
178 w = vim_strsize(array[i].pum_kind) + 1; | |
179 if (kind_width < w) | |
180 kind_width = w; | |
181 } | |
182 if (array[i].pum_extra != NULL) | |
183 { | |
184 w = vim_strsize(array[i].pum_extra) + 1; | |
185 if (extra_width < w) | |
186 extra_width = w; | |
187 } | |
188 } | |
189 pum_base_width = max_width; | |
190 pum_kind_width = kind_width; | |
191 | 198 |
192 /* Calculate column */ | 199 /* Calculate column */ |
193 #ifdef FEAT_RIGHTLEFT | 200 #ifdef FEAT_RIGHTLEFT |
194 if (curwin->w_p_rl) | 201 if (curwin->w_p_rl) |
195 col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1; | 202 col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1; |
224 pum_width = pum_col - pum_scrollbar + 1; | 231 pum_width = pum_col - pum_scrollbar + 1; |
225 else | 232 else |
226 #endif | 233 #endif |
227 pum_width = Columns - pum_col - pum_scrollbar; | 234 pum_width = Columns - pum_col - pum_scrollbar; |
228 | 235 |
229 if (pum_width > max_width + kind_width + extra_width + 1 | 236 if (pum_width > max_width + pum_kind_width + pum_extra_width + 1 |
230 && pum_width > PUM_DEF_WIDTH) | 237 && pum_width > PUM_DEF_WIDTH) |
231 { | 238 { |
232 pum_width = max_width + kind_width + extra_width + 1; | 239 pum_width = max_width + pum_kind_width + pum_extra_width + 1; |
233 if (pum_width < PUM_DEF_WIDTH) | 240 if (pum_width < PUM_DEF_WIDTH) |
234 pum_width = PUM_DEF_WIDTH; | 241 pum_width = PUM_DEF_WIDTH; |
235 } | 242 } |
236 } | 243 } |
237 else if (Columns < def_width) | 244 else if (Columns < def_width) |
255 else | 262 else |
256 #endif | 263 #endif |
257 pum_col = Columns - max_width; | 264 pum_col = Columns - max_width; |
258 pum_width = max_width - pum_scrollbar; | 265 pum_width = max_width - pum_scrollbar; |
259 } | 266 } |
260 | |
261 pum_array = array; | |
262 pum_size = size; | |
263 | 267 |
264 /* Set selected item and redraw. If the window size changed need to | 268 /* Set selected item and redraw. If the window size changed need to |
265 * redo the positioning. Limit this to two times, when there is not | 269 * redo the positioning. Limit this to two times, when there is not |
266 * much room the window size will keep changing. */ | 270 * much room the window size will keep changing. */ |
267 } while (pum_set_selected(selected, redo_count) && ++redo_count <= 2); | 271 } while (pum_set_selected(selected, redo_count) && ++redo_count <= 2); |
754 pum_get_height(void) | 758 pum_get_height(void) |
755 { | 759 { |
756 return pum_height; | 760 return pum_height; |
757 } | 761 } |
758 | 762 |
759 #endif | 763 # if defined(FEAT_BEVALTERM) || defined(PROTO) |
764 static pumitem_T *balloon_array = NULL; | |
765 static int balloon_arraysize; | |
766 static int balloon_mouse_row = 0; | |
767 static int balloon_mouse_col = 0; | |
768 | |
769 #define BALLOON_MIN_WIDTH 40 | |
770 #define BALLOON_MIN_HEIGHT 10 | |
771 | |
772 void | |
773 ui_remove_balloon(void) | |
774 { | |
775 if (balloon_array != NULL) | |
776 { | |
777 pum_undisplay(); | |
778 while (balloon_arraysize > 0) | |
779 vim_free(balloon_array[--balloon_arraysize].pum_text); | |
780 vim_free(balloon_array); | |
781 balloon_array = NULL; | |
782 } | |
783 } | |
784 | |
785 /* | |
786 * Terminal version of a balloon, uses the popup menu code. | |
787 */ | |
788 void | |
789 ui_post_balloon(char_u *mesg) | |
790 { | |
791 ui_remove_balloon(); | |
792 | |
793 /* TODO: split the text in multiple lines. */ | |
794 balloon_arraysize = 3; | |
795 balloon_array = (pumitem_T *)alloc_clear( | |
796 (unsigned)sizeof(pumitem_T) * balloon_arraysize); | |
797 if (balloon_array != NULL) | |
798 { | |
799 /* Add an empty line above and below, looks better. */ | |
800 balloon_array[0].pum_text = vim_strsave((char_u *)""); | |
801 balloon_array[1].pum_text = vim_strsave(mesg); | |
802 balloon_array[2].pum_text = vim_strsave((char_u *)""); | |
803 | |
804 pum_array = balloon_array; | |
805 pum_size = balloon_arraysize; | |
806 pum_compute_size(); | |
807 pum_scrollbar = 0; | |
808 pum_height = balloon_arraysize; | |
809 | |
810 if (Rows - mouse_row > BALLOON_MIN_HEIGHT) | |
811 { | |
812 /* Enough space below the mouse row. */ | |
813 pum_row = mouse_row + 1; | |
814 if (pum_height > Rows - pum_row) | |
815 pum_height = Rows - pum_row; | |
816 } | |
817 else | |
818 { | |
819 /* Show above the mouse row, reduce height if it does not fit. */ | |
820 pum_row = mouse_row - 1 - pum_size; | |
821 if (pum_row < 0) | |
822 { | |
823 pum_height += pum_row; | |
824 pum_row = 0; | |
825 } | |
826 } | |
827 if (Columns - mouse_col >= pum_base_width | |
828 || Columns - mouse_col > BALLOON_MIN_WIDTH) | |
829 /* Enough space to show at mouse column. */ | |
830 pum_col = mouse_col; | |
831 else | |
832 /* Not enough space, right align with window. */ | |
833 pum_col = Columns - (pum_base_width > BALLOON_MIN_WIDTH | |
834 ? BALLOON_MIN_WIDTH : pum_base_width); | |
835 | |
836 pum_width = Columns - pum_col; | |
837 if (pum_width > pum_base_width + 1) | |
838 pum_width = pum_base_width + 1; | |
839 | |
840 pum_selected = -1; | |
841 pum_first = 0; | |
842 pum_redraw(); | |
843 } | |
844 } | |
845 | |
846 /* | |
847 * Called when the mouse moved, may remove any displayed balloon. | |
848 */ | |
849 void | |
850 ui_may_remove_balloon(void) | |
851 { | |
852 if (mouse_row != balloon_mouse_row || mouse_col != balloon_mouse_col) | |
853 ui_remove_balloon(); | |
854 } | |
855 # endif | |
856 #endif |