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 beval->ts = wp->w_buffer->b_p_ts; 128 return OK; 129 } 130 } 131 } 132 133 return FAIL; 134 } 135 136 /* 137 * Show a balloon with "mesg" or "list". 138 */ 139 void 140 post_balloon(BalloonEval *beval UNUSED, char_u *mesg, list_T *list) 141 { 142 # ifdef FEAT_BEVAL_TERM 143 # ifdef FEAT_GUI 144 if (!gui.in_use) 145 # endif 146 ui_post_balloon(mesg, list); 147 # endif 148 # ifdef FEAT_BEVAL_GUI 149 if (gui.in_use) 150 /* GUI can't handle a list */ 151 gui_mch_post_balloon(beval, mesg); 152 # endif 153 } 154 155 /* 156 * Returns TRUE if the balloon eval has been enabled: 157 * 'ballooneval' for the GUI and 'balloonevalterm' for the terminal. 158 * Also checks if the screen isn't scrolled up. 159 */ 160 int 161 can_use_beval(void) 162 { 163 return (0 164 #ifdef FEAT_BEVAL_GUI 165 || (gui.in_use && p_beval) 166 #endif 167 #ifdef FEAT_BEVAL_TERM 168 || ( 169 # ifdef FEAT_GUI 170 !gui.in_use && 171 # endif 172 p_bevalterm) 173 #endif 174 ) && msg_scrolled == 0; 175 } 176 177 /* 178 * Common code, invoked when the mouse is resting for a moment. 179 */ 180 void 181 general_beval_cb(BalloonEval *beval, int state UNUSED) 182 { 183 #ifdef FEAT_EVAL 184 win_T *wp; 185 int col; 186 int use_sandbox; 187 linenr_T lnum; 188 char_u *text; 189 static char_u *result = NULL; 190 long winnr = 0; 191 char_u *bexpr; 192 buf_T *save_curbuf; 193 size_t len; 194 win_T *cw; 195 #endif 196 static int recursive = FALSE; 197 198 /* Don't do anything when 'ballooneval' is off, messages scrolled the 199 * windows up or we have no beval area. */ 200 if (!can_use_beval() || beval == NULL) 201 return; 202 203 /* Don't do this recursively. Happens when the expression evaluation 204 * takes a long time and invokes something that checks for CTRL-C typed. */ 205 if (recursive) 206 return; 207 recursive = TRUE; 208 209 #ifdef FEAT_EVAL 210 if (get_beval_info(beval, TRUE, &wp, &lnum, &text, &col) == OK) 211 { 212 bexpr = (*wp->w_buffer->b_p_bexpr == NUL) ? p_bexpr 213 : wp->w_buffer->b_p_bexpr; 214 if (*bexpr != NUL) 215 { 216 /* Convert window pointer to number. */ 217 for (cw = firstwin; cw != wp; cw = cw->w_next) 218 ++winnr; 219 220 set_vim_var_nr(VV_BEVAL_BUFNR, (long)wp->w_buffer->b_fnum); 221 set_vim_var_nr(VV_BEVAL_WINNR, winnr); 222 set_vim_var_nr(VV_BEVAL_WINID, wp->w_id); 223 set_vim_var_nr(VV_BEVAL_LNUM, (long)lnum); 224 set_vim_var_nr(VV_BEVAL_COL, (long)(col + 1)); 225 set_vim_var_string(VV_BEVAL_TEXT, text, -1); 226 vim_free(text); 227 228 /* 229 * Temporarily change the curbuf, so that we can determine whether 230 * the buffer-local balloonexpr option was set insecurely. 231 */ 232 save_curbuf = curbuf; 233 curbuf = wp->w_buffer; 234 use_sandbox = was_set_insecurely((char_u *)"balloonexpr", 235 *curbuf->b_p_bexpr == NUL ? 0 : OPT_LOCAL); 236 curbuf = save_curbuf; 237 if (use_sandbox) 238 ++sandbox; 239 ++textlock; 240 241 vim_free(result); 242 result = eval_to_string(bexpr, NULL, TRUE); 243 244 /* Remove one trailing newline, it is added when the result was a 245 * list and it's hardly ever useful. If the user really wants a 246 * trailing newline he can add two and one remains. */ 247 if (result != NULL) 248 { 249 len = STRLEN(result); 250 if (len > 0 && result[len - 1] == NL) 251 result[len - 1] = NUL; 252 } 253 254 if (use_sandbox) 255 --sandbox; 256 --textlock; 257 258 set_vim_var_string(VV_BEVAL_TEXT, NULL, -1); 259 if (result != NULL && result[0] != NUL) 260 { 261 post_balloon(beval, result, NULL); 262 recursive = FALSE; 263 return; 264 } 265 } 266 } 267 #endif 268 #ifdef FEAT_NETBEANS_INTG 269 if (bevalServers & BEVAL_NETBEANS) 270 netbeans_beval_cb(beval, state); 271 #endif 272 #ifdef FEAT_SUN_WORKSHOP 273 if (bevalServers & BEVAL_WORKSHOP) 274 workshop_beval_cb(beval, state); 275 #endif 276 277 recursive = FALSE; 278 } 279 280 #endif 281 282