From c3719bd87beca9f72d2e9f11e36d561c2c3b57b0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 18 Nov 2017 22:13:31 +0100 Subject: patch 8.0.1312: balloon_show() only works in terminal when compiled with GUI Problem: balloon_show() only works in terminal when compiled with the GUI. Solution: Add FEAT_BEVAL_GUI and refactor to move common code out of the GUI specific file. --- src/beval.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 src/beval.c (limited to 'src/beval.c') diff --git a/src/beval.c b/src/beval.c new file mode 100644 index 0000000000..d4705b8b99 --- /dev/null +++ b/src/beval.c @@ -0,0 +1,280 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * Visual Workshop integration by Gordon Prieur + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +#include "vim.h" + +#if defined(FEAT_BEVAL) || defined(PROTO) + +/* + * Get the text and position to be evaluated for "beval". + * If "getword" is true the returned text is not the whole line but the + * relevant word in allocated memory. + * Returns OK or FAIL. + */ + int +get_beval_info( + BalloonEval *beval, + int getword, + win_T **winp, + linenr_T *lnump, + char_u **textp, + int *colp) +{ + win_T *wp; + int row, col; + char_u *lbuf; + linenr_T lnum; + + *textp = NULL; +# ifdef FEAT_BEVAL_TERM +# ifdef FEAT_GUI + if (!gui.in_use) +# endif + { + row = mouse_row; + col = mouse_col; + } +# endif +# ifdef FEAT_GUI + if (gui.in_use) + { + row = Y_2_ROW(beval->y); + col = X_2_COL(beval->x); + } +#endif + wp = mouse_find_win(&row, &col); + if (wp != NULL && row < wp->w_height && col < wp->w_width) + { + /* Found a window and the cursor is in the text. Now find the line + * number. */ + if (!mouse_comp_pos(wp, &row, &col, &lnum)) + { + /* Not past end of the file. */ + lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE); + if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL)) + { + /* Not past end of line. */ + if (getword) + { + /* For Netbeans we get the relevant part of the line + * instead of the whole line. */ + int len; + pos_T *spos = NULL, *epos = NULL; + + if (VIsual_active) + { + if (LT_POS(VIsual, curwin->w_cursor)) + { + spos = &VIsual; + epos = &curwin->w_cursor; + } + else + { + spos = &curwin->w_cursor; + epos = &VIsual; + } + } + + col = vcol2col(wp, lnum, col); + + if (VIsual_active + && wp->w_buffer == curwin->w_buffer + && (lnum == spos->lnum + ? col >= (int)spos->col + : lnum > spos->lnum) + && (lnum == epos->lnum + ? col <= (int)epos->col + : lnum < epos->lnum)) + { + /* Visual mode and pointing to the line with the + * Visual selection: return selected text, with a + * maximum of one line. */ + if (spos->lnum != epos->lnum || spos->col == epos->col) + return FAIL; + + lbuf = ml_get_buf(curwin->w_buffer, VIsual.lnum, FALSE); + len = epos->col - spos->col; + if (*p_sel != 'e') + len += MB_PTR2LEN(lbuf + epos->col); + lbuf = vim_strnsave(lbuf + spos->col, len); + lnum = spos->lnum; + col = spos->col; + } + else + { + /* Find the word under the cursor. */ + ++emsg_off; + len = find_ident_at_pos(wp, lnum, (colnr_T)col, &lbuf, + FIND_IDENT + FIND_STRING + FIND_EVAL); + --emsg_off; + if (len == 0) + return FAIL; + lbuf = vim_strnsave(lbuf, len); + } + } + + *winp = wp; + *lnump = lnum; + *textp = lbuf; + *colp = col; + beval->ts = wp->w_buffer->b_p_ts; + return OK; + } + } + } + + return FAIL; +} + +/* + * Show a balloon with "mesg". + */ + void +post_balloon(BalloonEval *beval UNUSED, char_u *mesg) +{ +# ifdef FEAT_BEVAL_TERM +# ifdef FEAT_GUI + if (!gui.in_use) +# endif + ui_post_balloon(mesg); +# endif +# ifdef FEAT_BEVAL_GUI + if (gui.in_use) + gui_mch_post_balloon(beval, mesg); +# endif +} + +/* + * Returns TRUE if the balloon eval has been enabled: + * 'ballooneval' for the GUI and 'balloonevalterm' for the terminal. + * Also checks if the screen isn't scrolled up. + */ + int +can_use_beval(void) +{ + return (0 +#ifdef FEAT_BEVAL_GUI + || (gui.in_use && p_beval) +#endif +#ifdef FEAT_BEVAL_TERM + || ( +# ifdef FEAT_GUI + !gui.in_use && +# endif + p_bevalterm) +#endif + ) && msg_scrolled == 0; +} + +/* + * Common code, invoked when the mouse is resting for a moment. + */ + void +general_beval_cb(BalloonEval *beval, int state UNUSED) +{ +#ifdef FEAT_EVAL + win_T *wp; + int col; + int use_sandbox; + linenr_T lnum; + char_u *text; + static char_u *result = NULL; + long winnr = 0; + char_u *bexpr; + buf_T *save_curbuf; + size_t len; + win_T *cw; +#endif + static int recursive = FALSE; + + /* Don't do anything when 'ballooneval' is off, messages scrolled the + * windows up or we have no beval area. */ + if (!can_use_beval() || beval == NULL) + return; + + /* Don't do this recursively. Happens when the expression evaluation + * takes a long time and invokes something that checks for CTRL-C typed. */ + if (recursive) + return; + recursive = TRUE; + +#ifdef FEAT_EVAL + 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; + if (*bexpr != NUL) + { + /* Convert window pointer to number. */ + for (cw = firstwin; cw != wp; cw = cw->w_next) + ++winnr; + + set_vim_var_nr(VV_BEVAL_BUFNR, (long)wp->w_buffer->b_fnum); + set_vim_var_nr(VV_BEVAL_WINNR, winnr); + set_vim_var_nr(VV_BEVAL_WINID, wp->w_id); + set_vim_var_nr(VV_BEVAL_LNUM, (long)lnum); + set_vim_var_nr(VV_BEVAL_COL, (long)(col + 1)); + set_vim_var_string(VV_BEVAL_TEXT, text, -1); + vim_free(text); + + /* + * Temporarily change the curbuf, so that we can determine whether + * the buffer-local balloonexpr option was set insecurely. + */ + save_curbuf = curbuf; + curbuf = wp->w_buffer; + use_sandbox = was_set_insecurely((char_u *)"balloonexpr", + *curbuf->b_p_bexpr == NUL ? 0 : OPT_LOCAL); + curbuf = save_curbuf; + if (use_sandbox) + ++sandbox; + ++textlock; + + vim_free(result); + result = eval_to_string(bexpr, NULL, TRUE); + + /* Remove one trailing newline, it is added when the result was a + * list and it's hardly ever useful. If the user really wants a + * trailing newline he can add two and one remains. */ + if (result != NULL) + { + len = STRLEN(result); + if (len > 0 && result[len - 1] == NL) + result[len - 1] = NUL; + } + + if (use_sandbox) + --sandbox; + --textlock; + + set_vim_var_string(VV_BEVAL_TEXT, NULL, -1); + if (result != NULL && result[0] != NUL) + { + post_balloon(beval, result); + recursive = FALSE; + return; + } + } + } +#endif +#ifdef FEAT_NETBEANS_INTG + if (bevalServers & BEVAL_NETBEANS) + netbeans_beval_cb(beval, state); +#endif +#ifdef FEAT_SUN_WORKSHOP + if (bevalServers & BEVAL_WORKSHOP) + workshop_beval_cb(beval, state); +#endif + + recursive = FALSE; +} + +#endif + -- cgit v1.2.3