1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * Visual Workshop integration by Gordon Prieur 5 * 6 * Do ":help uganda" in Vim to read copying and usage conditions. 7 * Do ":help credits" in Vim to see a list of people who contributed. 8 * See README.txt for an overview of the Vim source code. 9 */ 10 11 #include "vim.h" 12 13 #if defined(FEAT_BEVAL) || defined(PROTO) 14 15 /* 16 * Get the text and position to be evaluated for "beval". 17 * If "getword" is true the returned text is not the whole line but the 18 * relevant word in allocated memory. 19 * Returns OK or FAIL. 20 */ 21 int 22 get_beval_info( 23 BalloonEval *beval, 24 int getword, 25 win_T **winp, 26 linenr_T *lnump, 27 char_u **textp, 28 int *colp) 29 { 30 win_T *wp; 31 int row, col; 32 char_u *lbuf; 33 linenr_T lnum; 34 35 *textp = NULL; 36 # ifdef FEAT_BEVAL_TERM 37 # ifdef FEAT_GUI 38 if (!gui.in_use) 39 # endif 40 { 41 row = mouse_row; 42 col = mouse_col; 43 } 44 # endif 45 # ifdef FEAT_GUI 46 if (gui.in_use) 47 { 48 row = Y_2_ROW(beval->y); 49 col = X_2_COL(beval->x); 50 } 51 #endif 52 wp = mouse_find_win(&row, &col); 53 if (wp != NULL && row >= 0 && row < wp->w_height && col < wp->w_width) 54 { 55 /* Found a window and the cursor is in the text. Now find the line 56 * number. */ 57 if (!mouse_comp_pos(wp, &row, &col, &lnum)) 58 { 59 /* Not past end of the file. */ 60 lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE); 61 if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL)) 62 { 63 /* Not past end of line. */ 64 if (getword) 65 { 66 /* For Netbeans we get the relevant part of the line 67 * instead of the whole line. */ 68 int len; 69 pos_T *spos = NULL, *epos = NULL; 70 71 if (VIsual_active) 72 { 73 if (LT_POS(VIsual, curwin->w_cursor)) 74 { 75 spos = &VIsual; 76 epos = &curwin->w_cursor; 77 } 78 else 79 { 80 spos = &curwin->w_cursor; 81 epos = &VIsual; 82 } 83 } 84 85 col = vcol2col(wp, lnum, col); 86 87 if (VIsual_active 88 && wp->w_buffer == curwin->w_buffer 89 && (lnum == spos->lnum 90 ? col >= (int)spos->col 91 : lnum > spos->lnum) 92 && (lnum == epos->lnum 93 ? col <= (int)epos->col 94 : lnum < epos->lnum)) 95 { 96 /* Visual mode and pointing to the line with the 97 * Visual selection: return selected text, with a 98 * maximum of one line. */ 99 if (spos->lnum != epos->lnum || spos->col == epos->col) 100 return FAIL; 101 102 lbuf = ml_get_buf(curwin->w_buffer, VIsual.lnum, FALSE); 103 len = epos->col - spos->col; 104 if (*p_sel != 'e') 105 len += MB_PTR2LEN(lbuf + epos->col); 106 lbuf = vim_strnsave(lbuf + spos->col, len); 107 lnum = spos->lnum; 108 col = spos->col; 109 } 110 else 111 { 112 /* Find the word under the cursor. */ 113 ++emsg_off; 114 len = find_ident_at_pos(wp, lnum, (colnr_T)col, &lbuf, 115 FIND_IDENT + FIND_STRING + FIND_EVAL); 116 --emsg_off; 117 if (len == 0) 118 return FAIL; 119 lbuf = vim_strnsave(lbuf, len); 120 } 121 } 122 123 *winp = wp; 124 *lnump = lnum; 125 *textp = lbuf; 126 *colp = col; 127 #ifdef FEAT_VARTABS 128 vim_free(beval->vts); 129 beval->vts = tabstop_copy(wp->w_buffer->b_p_vts_array); 130 if (wp->w_buffer->b_p_vts_array != NULL && beval->vts == NULL) 131 return FAIL; 132 #endif 133 beval->ts = wp->w_buffer->b_p_ts; 134 return OK; 135 } 136 } 137 } 138 139 return FAIL; 140 } 141 142 /* 143 * Show a balloon with "mesg" or "list". 144 */ 145 void 146 post_balloon(BalloonEval *beval UNUSED, char_u *mesg, list_T *list UNUSED) 147 { 148 # ifdef FEAT_BEVAL_TERM 149 # ifdef FEAT_GUI 150 if (!gui.in_use) 151 # endif 152 ui_post_balloon(mesg, list); 153 # endif 154 # ifdef FEAT_BEVAL_GUI 155 if (gui.in_use) 156 /* GUI can't handle a list */ 157 gui_mch_post_balloon(beval, mesg); 158 # endif 159 } 160 161 /* 162 * Returns TRUE if the balloon eval has been enabled: 163 * 'ballooneval' for the GUI and 'balloonevalterm' for the terminal. 164 * Also checks if the screen isn't scrolled up. 165 */ 166 int 167 can_use_beval(void) 168 { 169 return (0 170 #ifdef FEAT_BEVAL_GUI 171 || (gui.in_use && p_beval) 172 #endif 173 #ifdef FEAT_BEVAL_TERM 174 || ( 175 # ifdef FEAT_GUI 176 !gui.in_use && 177 # endif 178 p_bevalterm) 179 #endif 180 ) && msg_scrolled == 0; 181 } 182 183 /* 184 * Common code, invoked when the mouse is resting for a moment. 185 */ 186 void 187 general_beval_cb(BalloonEval *beval, int state UNUSED) 188 { 189 #ifdef FEAT_EVAL 190 win_T *wp; 191 int col; 192 int use_sandbox; 193 linenr_T lnum; 194 char_u *text; 195 static char_u *result = NULL; 196 long winnr = 0; 197 char_u *bexpr; 198 buf_T *save_curbuf; 199 size_t len; 200 win_T *cw; 201 #endif 202 static int recursive = FALSE; 203 204 /* Don't do anything when 'ballooneval' is off, messages scrolled the 205 * windows up or we have no beval area. */ 206 if (!can_use_beval() || beval == NULL) 207 return; 208 209 /* Don't do this recursively. Happens when the expression evaluation 210 * takes a long time and invokes something that checks for CTRL-C typed. */ 211 if (recursive) 212 return; 213 recursive = TRUE; 214 215 #ifdef FEAT_EVAL 216 if (get_beval_info(beval, TRUE, &wp, &lnum, &text, &col) == OK) 217 { 218 bexpr = (*wp->w_buffer->b_p_bexpr == NUL) ? p_bexpr 219 : wp->w_buffer->b_p_bexpr; 220 if (*bexpr != NUL) 221 { 222 /* Convert window pointer to number. */ 223 for (cw = firstwin; cw != wp; cw = cw->w_next) 224 ++winnr; 225 226 set_vim_var_nr(VV_BEVAL_BUFNR, (long)wp->w_buffer->b_fnum); 227 set_vim_var_nr(VV_BEVAL_WINNR, winnr); 228 set_vim_var_nr(VV_BEVAL_WINID, wp->w_id); 229 set_vim_var_nr(VV_BEVAL_LNUM, (long)lnum); 230 set_vim_var_nr(VV_BEVAL_COL, (long)(col + 1)); 231 set_vim_var_string(VV_BEVAL_TEXT, text, -1); 232 vim_free(text); 233 234 /* 235 * Temporarily change the curbuf, so that we can determine whether 236 * the buffer-local balloonexpr option was set insecurely. 237 */ 238 save_curbuf = curbuf; 239 curbuf = wp->w_buffer; 240 use_sandbox = was_set_insecurely((char_u *)"balloonexpr", 241 *curbuf->b_p_bexpr == NUL ? 0 : OPT_LOCAL); 242 curbuf = save_curbuf; 243 if (use_sandbox) 244 ++sandbox; 245 ++textlock; 246 247 vim_free(result); 248 result = eval_to_string(bexpr, NULL, TRUE); 249 250 /* Remove one trailing newline, it is added when the result was a 251 * list and it's hardly ever useful. If the user really wants a 252 * trailing newline he can add two and one remains. */ 253 if (result != NULL) 254 { 255 len = STRLEN(result); 256 if (len > 0 && result[len - 1] == NL) 257 result[len - 1] = NUL; 258 } 259 260 if (use_sandbox) 261 --sandbox; 262 --textlock; 263 264 set_vim_var_string(VV_BEVAL_TEXT, NULL, -1); 265 if (result != NULL && result[0] != NUL) 266 { 267 post_balloon(beval, result, NULL); 268 recursive = FALSE; 269 return; 270 } 271 } 272 } 273 #endif 274 #ifdef FEAT_NETBEANS_INTG 275 if (bevalServers & BEVAL_NETBEANS) 276 netbeans_beval_cb(beval, state); 277 #endif 278 279 recursive = FALSE; 280 } 281 282 #endif 283 284