diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-11-18 18:52:04 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-11-18 18:52:04 +0100 |
commit | 51b0f3701ecb440aa72ab6017c1df6940c0e0f6f (patch) | |
tree | 9cfd3546d8e52be2b1425dcc65095f8e650eadde /src | |
parent | 234d16286a2733adedef56784c17415ae169b9ad (diff) |
patch 8.0.1309: cannot use 'balloonexpr' in a terminalv8.0.1309
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/edit.c | 1 | ||||
-rw-r--r-- | src/evalfunc.c | 5 | ||||
-rw-r--r-- | src/ex_cmds2.c | 39 | ||||
-rw-r--r-- | src/ex_getln.c | 1 | ||||
-rw-r--r-- | src/feature.h | 7 | ||||
-rw-r--r-- | src/getchar.c | 8 | ||||
-rw-r--r-- | src/globals.h | 6 | ||||
-rw-r--r-- | src/gui.c | 5 | ||||
-rw-r--r-- | src/gui_beval.c | 42 | ||||
-rw-r--r-- | src/keymap.h | 2 | ||||
-rw-r--r-- | src/message.c | 1 | ||||
-rw-r--r-- | src/misc1.c | 1 | ||||
-rw-r--r-- | src/misc2.c | 3 | ||||
-rw-r--r-- | src/normal.c | 18 | ||||
-rw-r--r-- | src/option.c | 26 | ||||
-rw-r--r-- | src/option.h | 3 | ||||
-rw-r--r-- | src/os_unix.c | 65 | ||||
-rw-r--r-- | src/popupmnu.c | 167 | ||||
-rw-r--r-- | src/proto/gui_beval.pro | 1 | ||||
-rw-r--r-- | src/proto/os_unix.pro | 1 | ||||
-rw-r--r-- | src/proto/popupmnu.pro | 3 | ||||
-rw-r--r-- | src/term.c | 1 | ||||
-rw-r--r-- | src/terminal.c | 6 | ||||
-rw-r--r-- | src/version.c | 7 |
24 files changed, 343 insertions, 76 deletions
diff --git a/src/edit.c b/src/edit.c index 435e1ed812..65c53f52f6 100644 --- a/src/edit.c +++ b/src/edit.c @@ -1177,6 +1177,7 @@ doESCkey: case K_LEFTDRAG: case K_LEFTRELEASE: case K_LEFTRELEASE_NM: + case K_MOUSEMOVE: case K_MIDDLEMOUSE: case K_MIDDLEDRAG: case K_MIDDLERELEASE: diff --git a/src/evalfunc.c b/src/evalfunc.c index 25b28bb3a2..bd5cf8dec5 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1410,7 +1410,7 @@ f_atan2(typval_T *argvars, typval_T *rettv) f_balloon_show(typval_T *argvars, typval_T *rettv UNUSED) { if (balloonEval != NULL) - gui_mch_post_balloon(balloonEval, get_tv_string_chk(&argvars[0])); + post_balloon(balloonEval, get_tv_string_chk(&argvars[0])); } #endif @@ -5589,6 +5589,9 @@ f_has(typval_T *argvars, typval_T *rettv) "balloon_multiline", # endif #endif +#ifdef FEAT_BEVALTERM + "balloon_eval_term", +#endif #if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS) "builtin_terms", # ifdef ALL_BUILTIN_TCAPS diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 2eef050eea..c6a6dbe14d 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1093,21 +1093,21 @@ static timer_T *first_timer = NULL; static long last_timer_id = 0; static long -timer_time_left(timer_T *timer, proftime_T *now) +proftime_time_left(proftime_T *due, proftime_T *now) { # ifdef WIN3264 LARGE_INTEGER fr; - if (now->QuadPart > timer->tr_due.QuadPart) + if (now->QuadPart > due->QuadPart) return 0; QueryPerformanceFrequency(&fr); - return (long)(((double)(timer->tr_due.QuadPart - now->QuadPart) + return (long)(((double)(due->QuadPart - now->QuadPart) / (double)fr.QuadPart) * 1000); # else - if (now->tv_sec > timer->tr_due.tv_sec) + if (now->tv_sec > due->tv_sec) return 0; - return (timer->tr_due.tv_sec - now->tv_sec) * 1000 - + (timer->tr_due.tv_usec - now->tv_usec) / 1000; + return (due->tv_sec - now->tv_sec) * 1000 + + (due->tv_usec - now->tv_usec) / 1000; # endif } @@ -1219,7 +1219,7 @@ check_due_timer(void) if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused) continue; - this_due = timer_time_left(timer, &now); + this_due = proftime_time_left(&timer->tr_due, &now); if (this_due <= 1) { int save_timer_busy = timer_busy; @@ -1271,7 +1271,7 @@ check_due_timer(void) && timer->tr_emsg_count < 3) { profile_setlimit(timer->tr_interval, &timer->tr_due); - this_due = timer_time_left(timer, &now); + this_due = proftime_time_left(&timer->tr_due, &now); if (this_due < 1) this_due = 1; if (timer->tr_repeat > 0) @@ -1291,6 +1291,27 @@ check_due_timer(void) if (did_one) redraw_after_callback(need_update_screen); +#ifdef FEAT_BEVALTERM + if (bevalexpr_due_set) + { + this_due = proftime_time_left(&bevalexpr_due, &now); + if (this_due <= 1) + { + bevalexpr_due_set = FALSE; + + if (balloonEval == NULL) + { + balloonEval = (BalloonEval *)alloc(sizeof(BalloonEval)); + balloonEvalForTerm = TRUE; + } + if (balloonEval != NULL) + general_beval_cb(balloonEval, 0); + } + else if (this_due > 0 && (next_due == -1 || next_due > this_due)) + next_due = this_due; + } +#endif + return current_id != last_timer_id ? 1 : next_due; } @@ -1358,7 +1379,7 @@ add_timer_info(typval_T *rettv, timer_T *timer) dict_add_nr_str(dict, "time", (long)timer->tr_interval, NULL); profile_start(&now); - remaining = timer_time_left(timer, &now); + remaining = proftime_time_left(&timer->tr_due, &now); dict_add_nr_str(dict, "remaining", (long)remaining, NULL); dict_add_nr_str(dict, "repeat", diff --git a/src/ex_getln.c b/src/ex_getln.c index 7c0db89a87..f8a193d1d0 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1452,6 +1452,7 @@ getcmdline( case K_X2MOUSE: case K_X2DRAG: case K_X2RELEASE: + case K_MOUSEMOVE: goto cmdline_not_changed; #endif /* FEAT_MOUSE */ diff --git a/src/feature.h b/src/feature.h index a6a1599977..f17a5c1674 100644 --- a/src/feature.h +++ b/src/feature.h @@ -1328,6 +1328,13 @@ # define FEAT_BEVAL_TIP /* balloon eval used for toolbar tooltip */ #endif +/* + * +balloon_eval_term Allow balloon expression evaluation in the terminal. + */ +#if defined(FEAT_BEVAL) && defined(UNIX) && defined(FEAT_TIMERS) +# define FEAT_BEVALTERM +#endif + /* both Motif and Athena are X11 and share some code */ #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) # define FEAT_GUI_X11 diff --git a/src/getchar.c b/src/getchar.c index 455c013884..2e91c24c1a 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -1792,6 +1792,14 @@ vgetc(void) */ may_garbage_collect = FALSE; #endif +#ifdef FEAT_BEVALTERM + if (c != K_MOUSEMOVE && c != K_IGNORE) + { + /* Don't trigger 'balloonexpr' unless only the mouse was moved. */ + bevalexpr_due_set = FALSE; + ui_remove_balloon(); + } +#endif return c; } diff --git a/src/globals.h b/src/globals.h index ae62710d57..c19866497c 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1231,6 +1231,7 @@ EXTERN int no_hlsearch INIT(= FALSE); #if defined(FEAT_BEVAL) && !defined(NO_X11_INCLUDES) EXTERN BalloonEval *balloonEval INIT(= NULL); +EXTERN int balloonEvalForTerm INIT(= FALSE); # if defined(FEAT_NETBEANS_INTG) || defined(FEAT_SUN_WORKSHOP) EXTERN int bevalServers INIT(= 0); # define BEVAL_NETBEANS 0x01 @@ -1648,6 +1649,11 @@ EXTERN int did_add_timer INIT(= FALSE); EXTERN int timer_busy INIT(= 0); /* when timer is inside vgetc() then > 0 */ #endif +#ifdef FEAT_BEVALTERM +EXTERN int bevalexpr_due_set INIT(= FALSE); +EXTERN proftime_T bevalexpr_due; +#endif + #ifdef FEAT_EVAL EXTERN time_T time_for_testing INIT(= 0); @@ -740,7 +740,10 @@ gui_init(void) #ifdef FEAT_BEVAL /* Always create the Balloon Evaluation area, but disable it when - * 'ballooneval' is off */ + * 'ballooneval' is off. */ + if (balloonEval != NULL) + vim_free(balloonEval); + balloonEvalForTerm = FALSE; # ifdef FEAT_GUI_GTK balloonEval = gui_mch_create_beval_area(gui.drawarea, NULL, &general_beval_cb, NULL); diff --git a/src/gui_beval.c b/src/gui_beval.c index 1c01ecc84a..ada048c62c 100644 --- a/src/gui_beval.c +++ b/src/gui_beval.c @@ -35,7 +35,11 @@ general_beval_cb(BalloonEval *beval, int state UNUSED) /* Don't do anything when 'ballooneval' is off, messages scrolled the * windows up or we have no beval area. */ - if (!p_beval || balloonEval == NULL || msg_scrolled > 0) + if (!((gui.in_use && p_beval) +# ifdef FEAT_BEVALTERM + || (!gui.in_use && p_bevalterm) +# endif + ) || beval == NULL || msg_scrolled > 0) return; /* Don't do this recursively. Happens when the expression evaluation @@ -45,7 +49,7 @@ general_beval_cb(BalloonEval *beval, int state UNUSED) recursive = TRUE; #ifdef FEAT_EVAL - if (get_beval_info(balloonEval, TRUE, &wp, &lnum, &text, &col) == OK) + if (get_beval_info(beval, TRUE, &wp, &lnum, &text, &col) == OK) { bexpr = (*wp->w_buffer->b_p_bexpr == NUL) ? p_bexpr : wp->w_buffer->b_p_bexpr; @@ -96,7 +100,7 @@ general_beval_cb(BalloonEval *beval, int state UNUSED) set_vim_var_string(VV_BEVAL_TEXT, NULL, -1); if (result != NULL && result[0] != NUL) { - gui_mch_post_balloon(beval, result); + post_balloon(beval, result); recursive = FALSE; return; } @@ -335,8 +339,18 @@ get_beval_info( linenr_T lnum; *textp = NULL; - row = Y_2_ROW(beval->y); - col = X_2_COL(beval->x); +# ifdef FEAT_BEVALTERM + if (!gui.in_use) + { + row = mouse_row; + col = mouse_col; + } + else +# endif + { + row = Y_2_ROW(beval->y); + col = X_2_COL(beval->x); + } wp = mouse_find_win(&row, &col); if (wp != NULL && row < wp->w_height && col < wp->w_width) { @@ -421,6 +435,20 @@ get_beval_info( return FAIL; } +/* + * Show a balloon with "mesg". + */ + void +post_balloon(BalloonEval *beval, char_u *mesg) +{ +# ifdef FEAT_BEVALTERM + if (!gui.in_use) + ui_post_balloon(mesg); + else +# endif + gui_mch_post_balloon(beval, mesg); +} + # if !defined(FEAT_GUI_W32) || defined(PROTO) /* @@ -451,10 +479,6 @@ gui_mch_unpost_balloon(BalloonEval *beval) #endif #ifdef FEAT_GUI_GTK -/* - * We can unconditionally use ANSI-style prototypes here since - * GTK+ requires an ANSI C compiler anyway. - */ static void addEventHandler(GtkWidget *target, BalloonEval *beval) { diff --git a/src/keymap.h b/src/keymap.h index 7cb5c69bcc..8a34f0e296 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -269,6 +269,7 @@ enum key_extra , KE_NOP = 97 /* doesn't do something */ , KE_FOCUSGAINED = 98 /* focus gained */ , KE_FOCUSLOST = 99 /* focus lost */ + , KE_MOUSEMOVE = 100 /* mouse moved with no button down */ }; /* @@ -437,6 +438,7 @@ enum key_extra #define K_LEFTDRAG TERMCAP2KEY(KS_EXTRA, KE_LEFTDRAG) #define K_LEFTRELEASE TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE) #define K_LEFTRELEASE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE_NM) +#define K_MOUSEMOVE TERMCAP2KEY(KS_EXTRA, KE_MOUSEMOVE) #define K_MIDDLEMOUSE TERMCAP2KEY(KS_EXTRA, KE_MIDDLEMOUSE) #define K_MIDDLEDRAG TERMCAP2KEY(KS_EXTRA, KE_MIDDLEDRAG) #define K_MIDDLERELEASE TERMCAP2KEY(KS_EXTRA, KE_MIDDLERELEASE) diff --git a/src/message.c b/src/message.c index 221e3d8012..c40b6cf15b 100644 --- a/src/message.c +++ b/src/message.c @@ -1179,6 +1179,7 @@ wait_return(int redraw) || c == K_RIGHTDRAG || c == K_RIGHTRELEASE || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_MOUSEDOWN || c == K_MOUSEUP + || c == K_MOUSEMOVE || (!mouse_has(MOUSE_RETURN) && mouse_row < msg_row && (c == K_LEFTMOUSE diff --git a/src/misc1.c b/src/misc1.c index f33fd3b9e6..4c691bb258 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -3345,6 +3345,7 @@ is_mouse_key(int c) || c == K_LEFTDRAG || c == K_LEFTRELEASE || c == K_LEFTRELEASE_NM + || c == K_MOUSEMOVE || c == K_MIDDLEMOUSE || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE diff --git a/src/misc2.c b/src/misc2.c index 63d9e81d69..87b79fae1e 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -2453,6 +2453,7 @@ static struct key_name_entry {K_LEFTDRAG, (char_u *)"LeftDrag"}, {K_LEFTRELEASE, (char_u *)"LeftRelease"}, {K_LEFTRELEASE_NM, (char_u *)"LeftReleaseNM"}, + {K_MOUSEMOVE, (char_u *)"MouseMove"}, {K_MIDDLEMOUSE, (char_u *)"MiddleMouse"}, {K_MIDDLEDRAG, (char_u *)"MiddleDrag"}, {K_MIDDLERELEASE, (char_u *)"MiddleRelease"}, @@ -2515,7 +2516,7 @@ static struct mousetable {(int)KE_X2DRAG, MOUSE_X2, FALSE, TRUE}, {(int)KE_X2RELEASE, MOUSE_X2, FALSE, FALSE}, /* DRAG without CLICK */ - {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, TRUE}, + {(int)KE_MOUSEMOVE, MOUSE_RELEASE, FALSE, TRUE}, /* RELEASE without CLICK */ {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, FALSE}, {0, 0, 0, 0}, diff --git a/src/normal.c b/src/normal.c index e781cd70e2..81bedfdba1 100644 --- a/src/normal.c +++ b/src/normal.c @@ -358,6 +358,7 @@ static const struct nv_cmd {K_LEFTDRAG, nv_mouse, 0, 0}, {K_LEFTRELEASE, nv_mouse, 0, 0}, {K_LEFTRELEASE_NM, nv_mouse, 0, 0}, + {K_MOUSEMOVE, nv_mouse, 0, 0}, {K_MIDDLEMOUSE, nv_mouse, 0, 0}, {K_MIDDLEDRAG, nv_mouse, 0, 0}, {K_MIDDLERELEASE, nv_mouse, 0, 0}, @@ -2396,6 +2397,20 @@ do_mouse( break; } + if (c == K_MOUSEMOVE) + { + /* Mouse moved without a button pressed. */ +#ifdef FEAT_BEVALTERM + ui_may_remove_balloon(); + if (p_bevalterm && !VIsual_active) + { + profile_setlimit(p_bdlay, &bevalexpr_due); + bevalexpr_due_set = TRUE; + } +#endif + return FALSE; + } + #ifdef FEAT_MOUSESHAPE /* May have stopped dragging the status or separator line. The pointer is * most likely still on the status or separator line. */ @@ -3843,7 +3858,7 @@ add_to_showcmd(int c) K_LEFTMOUSE_NM, K_LEFTRELEASE_NM, # endif K_IGNORE, K_PS, - K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE, + K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE, K_MOUSEMOVE, K_MIDDLEMOUSE, K_MIDDLEDRAG, K_MIDDLERELEASE, K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE, K_MOUSEDOWN, K_MOUSEUP, K_MOUSELEFT, K_MOUSERIGHT, @@ -8358,6 +8373,7 @@ nv_g_cmd(cmdarg_T *cap) case K_LEFTMOUSE: case K_LEFTDRAG: case K_LEFTRELEASE: + case K_MOUSEMOVE: case K_RIGHTMOUSE: case K_RIGHTDRAG: case K_RIGHTRELEASE: diff --git a/src/option.c b/src/option.c index 4f25c1ff44..495a89dddb 100644 --- a/src/option.c +++ b/src/option.c @@ -642,6 +642,15 @@ static struct vimoption options[] = {(char_u *)0L, (char_u *)0L} #endif SCRIPTID_INIT}, + {"balloonevalterm", "bevalterm",P_BOOL|P_VI_DEF|P_NO_MKRC, +#ifdef FEAT_BEVALTERM + (char_u *)&p_bevalterm, PV_NONE, + {(char_u *)FALSE, (char_u *)0L} +#else + (char_u *)NULL, PV_NONE, + {(char_u *)0L, (char_u *)0L} +#endif + SCRIPTID_INIT}, {"balloonexpr", "bexpr", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM, #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) (char_u *)&p_bexpr, PV_BEXPR, @@ -8423,12 +8432,21 @@ set_bool_option( #ifdef FEAT_BEVAL else if ((int *)varp == &p_beval) { - if (p_beval && !old_value) - gui_mch_enable_beval_area(balloonEval); - else if (!p_beval && old_value) - gui_mch_disable_beval_area(balloonEval); + if (!balloonEvalForTerm) + { + if (p_beval && !old_value) + gui_mch_enable_beval_area(balloonEval); + else if (!p_beval && old_value) + gui_mch_disable_beval_area(balloonEval); + } } #endif +# ifdef FEAT_BEVALTERM + else if ((int *)varp == &p_bevalterm) + { + mch_bevalterm_changed(); + } +# endif #ifdef FEAT_AUTOCHDIR else if ((int *)varp == &p_acd) diff --git a/src/option.h b/src/option.h index f9972f21ac..2084517d55 100644 --- a/src/option.h +++ b/src/option.h @@ -382,6 +382,9 @@ EXTERN int p_beval; /* 'ballooneval' */ EXTERN char_u *p_bexpr; # endif #endif +# ifdef FEAT_BEVALTERM +EXTERN int p_bevalterm; /* 'balloonevalterm' */ +# endif #ifdef FEAT_BROWSE EXTERN char_u *p_bsdir; /* 'browsedir' */ #endif diff --git a/src/os_unix.c b/src/os_unix.c index d2f080529e..1c2a902761 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3564,16 +3564,25 @@ get_tty_info(int fd, ttyinfo_T *info) #endif /* VMS */ #if defined(FEAT_MOUSE_TTY) || defined(PROTO) +static int mouse_ison = FALSE; + /* * Set mouse clicks on or off. */ void mch_setmouse(int on) { - static int ison = FALSE; +# ifdef FEAT_BEVALTERM + static int bevalterm_ison = FALSE; +# endif int xterm_mouse_vers; - if (on == ison) /* return quickly if nothing to do */ + if (on == mouse_ison +# ifdef FEAT_BEVALTERM + && p_bevalterm == bevalterm_ison +# endif + ) + /* return quickly if nothing to do */ return; xterm_mouse_vers = use_xterm_mouse(); @@ -3585,18 +3594,30 @@ mch_setmouse(int on) (on ? IF_EB("\033[?1015h", ESC_STR "[?1015h") : IF_EB("\033[?1015l", ESC_STR "[?1015l"))); - ison = on; + mouse_ison = on; } # endif # ifdef FEAT_MOUSE_SGR if (ttym_flags == TTYM_SGR) { + /* SGR mode supports columns above 223 */ out_str_nf((char_u *) (on ? IF_EB("\033[?1006h", ESC_STR "[?1006h") : IF_EB("\033[?1006l", ESC_STR "[?1006l"))); - ison = on; + mouse_ison = on; + } +# endif + +# ifdef FEAT_BEVALTERM + if (bevalterm_ison != (p_bevalterm && on)) + { + bevalterm_ison = (p_bevalterm && on); + if (xterm_mouse_vers > 1 && !bevalterm_ison) + /* disable mouse movement events, enabling is below */ + out_str_nf((char_u *) + (IF_EB("\033[?1003l", ESC_STR "[?1003l"))); } # endif @@ -3605,14 +3626,19 @@ mch_setmouse(int on) if (on) /* enable mouse events, use mouse tracking if available */ out_str_nf((char_u *) (xterm_mouse_vers > 1 - ? IF_EB("\033[?1002h", ESC_STR "[?1002h") + ? ( +# ifdef FEAT_BEVALTERM + bevalterm_ison + ? IF_EB("\033[?1003h", ESC_STR "[?1003h") : +# endif + IF_EB("\033[?1002h", ESC_STR "[?1002h")) : IF_EB("\033[?1000h", ESC_STR "[?1000h"))); else /* disable mouse events, could probably always send the same */ out_str_nf((char_u *) (xterm_mouse_vers > 1 ? IF_EB("\033[?1002l", ESC_STR "[?1002l") : IF_EB("\033[?1000l", ESC_STR "[?1000l"))); - ison = on; + mouse_ison = on; } # ifdef FEAT_MOUSE_DEC @@ -3622,7 +3648,7 @@ mch_setmouse(int on) out_str_nf((char_u *)"\033[1;2'z\033[1;3'{"); else /* disable mouse events */ out_str_nf((char_u *)"\033['z"); - ison = on; + mouse_ison = on; } # endif @@ -3632,12 +3658,12 @@ mch_setmouse(int on) if (on) { if (gpm_open()) - ison = TRUE; + mouse_ison = TRUE; } else { gpm_close(); - ison = FALSE; + mouse_ison = FALSE; } } # endif @@ -3648,12 +3674,12 @@ mch_setmouse(int on) if (on) { if (sysmouse_open() == OK) - ison = TRUE; + mouse_ison = TRUE; } else { sysmouse_close(); - ison = FALSE; + mouse_ison = FALSE; } } # endif @@ -3686,13 +3712,13 @@ mch_setmouse(int on) out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\", ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\")); # endif - ison = TRUE; + mouse_ison = TRUE; } else { out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\", ESC_STR "[0~ZwQ" ESC_STR "\\")); - ison = FALSE; + mouse_ison = FALSE; } } # endif @@ -3704,11 +3730,22 @@ mch_setmouse(int on) out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l"); else out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h"); - ison = on; + mouse_ison = on; } # endif } +#if defined(FEAT_BEVALTERM) || defined(PROTO) +/* + * Called when 'balloonevalterm' changed. + */ + void +mch_bevalterm_changed(void) +{ + mch_setmouse(mouse_ison); +} +#endif + /* * Set the mouse termcode, depending on the 'term' and 'ttymouse' options. */ diff --git a/src/popupmnu.c b/src/popupmnu.c index ec75281e77..dc66e75944 100644 --- a/src/popupmnu.c +++ b/src/popupmnu.c @@ -23,6 +23,7 @@ static int pum_height; /* nr of displayed pum items */ 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 repeat); #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 diff --git a/src/proto/gui_beval.pro b/src/proto/gui_beval.pro index b0067a00a4..aa0553fa00 100644 --- a/src/proto/gui_beval.pro +++ b/src/proto/gui_beval.pro @@ -6,6 +6,7 @@ void gui_mch_enable_beval_area(BalloonEval *beval); void gui_mch_disable_beval_area(BalloonEval *beval); BalloonEval *gui_mch_currently_showing_beval(void); int get_beval_info(BalloonEval *beval, int getword, win_T **winp, linenr_T *lnump, char_u **textp, int *colp); +void post_balloon(BalloonEval *beval, char_u *mesg); void gui_mch_post_balloon(BalloonEval *beval, char_u *mesg); void gui_mch_unpost_balloon(BalloonEval *beval); /* vim: set ft=c : */ diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro index d3a00b5a24..fbdad15709 100644 --- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -53,6 +53,7 @@ void mch_settmode(int tmode); void get_stty(void); int get_tty_info(int fd, ttyinfo_T *info); void mch_setmouse(int on); +void mch_bevalterm_changed(void); void check_mouse_termcode(void); int mch_screenmode(char_u *arg); int mch_get_shellsize(void); diff --git a/src/proto/popupmnu.pro b/src/proto/popupmnu.pro index 423076c3ef..57795338b0 100644 --- a/src/proto/popupmnu.pro +++ b/src/proto/popupmnu.pro @@ -5,4 +5,7 @@ void pum_undisplay(void); void pum_clear(void); int pum_visible(void); int pum_get_height(void); +void ui_remove_balloon(void); +void ui_post_balloon(char_u *mesg); +void ui_may_remove_balloon(void); /* vim: set ft=c : */ |