Mercurial > vim
comparison src/ex_getln.c @ 14503:4825955cb706 v8.1.0265
patch 8.1.0265: the getcmdline() function is way too big
commit https://github.com/vim/vim/commit/0ee81cb63876e6ec1b2a6e0125295b43f1c63c7d
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Aug 10 22:07:32 2018 +0200
patch 8.1.0265: the getcmdline() function is way too big
Problem: The getcmdline() function is way too big.
Solution: Factor out the incremental search highlighting.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Fri, 10 Aug 2018 22:15:05 +0200 |
parents | e4c553e9132b |
children | 3648e74dd523 |
comparison
equal
deleted
inserted
replaced
14502:f6cb0b08aedb | 14503:4825955cb706 |
---|---|
139 #ifdef __BORLANDC__ | 139 #ifdef __BORLANDC__ |
140 _RTLENTRYF | 140 _RTLENTRYF |
141 #endif | 141 #endif |
142 sort_func_compare(const void *s1, const void *s2); | 142 sort_func_compare(const void *s1, const void *s2); |
143 #endif | 143 #endif |
144 #ifdef FEAT_SEARCH_EXTRA | |
145 static void set_search_match(pos_T *t); | |
146 #endif | |
147 | 144 |
148 | 145 |
149 static void | 146 static void |
150 trigger_cmd_autocmd(int typechar, int evt) | 147 trigger_cmd_autocmd(int typechar, int evt) |
151 { | 148 { |
183 while (n >= 2 && p[n - 2] == '\\' | 180 while (n >= 2 && p[n - 2] == '\\' |
184 && vim_strchr((char_u *)"mMvVcCZ", p[n - 1]) != NULL) | 181 && vim_strchr((char_u *)"mMvVcCZ", p[n - 1]) != NULL) |
185 n -= 2; | 182 n -= 2; |
186 return n == 0 || (n >= 2 && p[n - 2] == '\\' && p[n - 1] == '|'); | 183 return n == 0 || (n >= 2 && p[n - 2] == '\\' && p[n - 1] == '|'); |
187 } | 184 } |
188 #endif | 185 |
189 | 186 // Struct to store the viewstate during 'incsearch' highlighting. |
190 #ifdef FEAT_SEARCH_EXTRA | |
191 typedef struct { | 187 typedef struct { |
192 colnr_T vs_curswant; | 188 colnr_T vs_curswant; |
193 colnr_T vs_leftcol; | 189 colnr_T vs_leftcol; |
194 linenr_T vs_topline; | 190 linenr_T vs_topline; |
195 # ifdef FEAT_DIFF | 191 # ifdef FEAT_DIFF |
221 # ifdef FEAT_DIFF | 217 # ifdef FEAT_DIFF |
222 curwin->w_topfill = vs->vs_topfill; | 218 curwin->w_topfill = vs->vs_topfill; |
223 # endif | 219 # endif |
224 curwin->w_botline = vs->vs_botline; | 220 curwin->w_botline = vs->vs_botline; |
225 curwin->w_empty_rows = vs->vs_empty_rows; | 221 curwin->w_empty_rows = vs->vs_empty_rows; |
222 } | |
223 | |
224 // Struct to store the state of 'incsearch' highlighting. | |
225 typedef struct { | |
226 pos_T search_start; // where 'incsearch' starts searching | |
227 pos_T save_cursor; | |
228 viewstate_T init_viewstate; | |
229 viewstate_T old_viewstate; | |
230 pos_T match_start; | |
231 pos_T match_end; | |
232 int did_incsearch; | |
233 int incsearch_postponed; | |
234 } incsearch_state_T; | |
235 | |
236 static void | |
237 init_incsearch_state(incsearch_state_T *is_state) | |
238 { | |
239 is_state->match_start = curwin->w_cursor; | |
240 is_state->did_incsearch = FALSE; | |
241 is_state->incsearch_postponed = FALSE; | |
242 CLEAR_POS(&is_state->match_end); | |
243 is_state->save_cursor = curwin->w_cursor; // may be restored later | |
244 is_state->search_start = curwin->w_cursor; | |
245 save_viewstate(&is_state->init_viewstate); | |
246 save_viewstate(&is_state->old_viewstate); | |
247 } | |
248 | |
249 /* | |
250 * First move cursor to end of match, then to the start. This | |
251 * moves the whole match onto the screen when 'nowrap' is set. | |
252 */ | |
253 static void | |
254 set_search_match(pos_T *t) | |
255 { | |
256 t->lnum += search_match_lines; | |
257 t->col = search_match_endcol; | |
258 if (t->lnum > curbuf->b_ml.ml_line_count) | |
259 { | |
260 t->lnum = curbuf->b_ml.ml_line_count; | |
261 coladvance((colnr_T)MAXCOL); | |
262 } | |
263 } | |
264 | |
265 /* | |
266 * Return TRUE when 'incsearch' highlighting is to be done. | |
267 */ | |
268 static int | |
269 do_incsearch_highlighting(int firstc) | |
270 { | |
271 return p_is && !cmd_silent && (firstc == '/' || firstc == '?'); | |
272 } | |
273 | |
274 /* | |
275 * Do 'incsearch' highlighting if desired. | |
276 */ | |
277 static void | |
278 may_do_incsearch_highlighting( | |
279 int firstc, | |
280 long count, | |
281 incsearch_state_T *is_state) | |
282 { | |
283 int i; | |
284 pos_T end_pos; | |
285 struct cmdline_info save_ccline; | |
286 #ifdef FEAT_RELTIME | |
287 proftime_T tm; | |
288 #endif | |
289 | |
290 if (!do_incsearch_highlighting(firstc)) | |
291 return; | |
292 | |
293 // If there is a character waiting, search and redraw later. | |
294 if (char_avail()) | |
295 { | |
296 is_state->incsearch_postponed = TRUE; | |
297 return; | |
298 } | |
299 is_state->incsearch_postponed = FALSE; | |
300 | |
301 // start at old position | |
302 curwin->w_cursor = is_state->search_start; | |
303 save_last_search_pattern(); | |
304 | |
305 // If there is no command line, don't do anything. | |
306 if (ccline.cmdlen == 0) | |
307 { | |
308 i = 0; | |
309 set_no_hlsearch(TRUE); // turn off previous highlight | |
310 redraw_all_later(SOME_VALID); | |
311 } | |
312 else | |
313 { | |
314 int search_flags = SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK; | |
315 | |
316 cursor_off(); // so the user knows we're busy | |
317 out_flush(); | |
318 ++emsg_off; // so it doesn't beep if bad expr | |
319 #ifdef FEAT_RELTIME | |
320 // Set the time limit to half a second. | |
321 profile_setlimit(500L, &tm); | |
322 #endif | |
323 if (!p_hls) | |
324 search_flags += SEARCH_KEEP; | |
325 i = do_search(NULL, firstc, ccline.cmdbuff, count, search_flags, | |
326 #ifdef FEAT_RELTIME | |
327 &tm, NULL | |
328 #else | |
329 NULL, NULL | |
330 #endif | |
331 ); | |
332 --emsg_off; | |
333 | |
334 // if interrupted while searching, behave like it failed | |
335 if (got_int) | |
336 { | |
337 (void)vpeekc(); // remove <C-C> from input stream | |
338 got_int = FALSE; // don't abandon the command line | |
339 i = 0; | |
340 } | |
341 else if (char_avail()) | |
342 // cancelled searching because a char was typed | |
343 is_state->incsearch_postponed = TRUE; | |
344 } | |
345 if (i != 0) | |
346 highlight_match = TRUE; // highlight position | |
347 else | |
348 highlight_match = FALSE; // remove highlight | |
349 | |
350 // First restore the old curwin values, so the screen is positioned in the | |
351 // same way as the actual search command. | |
352 restore_viewstate(&is_state->old_viewstate); | |
353 changed_cline_bef_curs(); | |
354 update_topline(); | |
355 | |
356 if (i != 0) | |
357 { | |
358 pos_T save_pos = curwin->w_cursor; | |
359 | |
360 is_state->match_start = curwin->w_cursor; | |
361 set_search_match(&curwin->w_cursor); | |
362 validate_cursor(); | |
363 end_pos = curwin->w_cursor; | |
364 is_state->match_end = end_pos; | |
365 curwin->w_cursor = save_pos; | |
366 } | |
367 else | |
368 end_pos = curwin->w_cursor; // shutup gcc 4 | |
369 | |
370 // Disable 'hlsearch' highlighting if the pattern matches everything. | |
371 // Avoids a flash when typing "foo\|". | |
372 if (empty_pattern(ccline.cmdbuff)) | |
373 set_no_hlsearch(TRUE); | |
374 | |
375 validate_cursor(); | |
376 // May redraw the status line to show the cursor position. | |
377 if (p_ru && curwin->w_status_height > 0) | |
378 curwin->w_redr_status = TRUE; | |
379 | |
380 save_cmdline(&save_ccline); | |
381 update_screen(SOME_VALID); | |
382 restore_cmdline(&save_ccline); | |
383 restore_last_search_pattern(); | |
384 | |
385 // Leave it at the end to make CTRL-R CTRL-W work. | |
386 if (i != 0) | |
387 curwin->w_cursor = end_pos; | |
388 | |
389 msg_starthere(); | |
390 redrawcmdline(); | |
391 is_state->did_incsearch = TRUE; | |
392 } | |
393 | |
394 /* | |
395 * May adjust 'incsearch' highlighting for typing CTRL-G and CTRL-T, go to next | |
396 * or previous match. | |
397 * Returns FAIL when jumping to cmdline_not_changed; | |
398 */ | |
399 static int | |
400 may_adjust_incsearch_highlighting( | |
401 int firstc, | |
402 long count, | |
403 incsearch_state_T *is_state, | |
404 int c) | |
405 { | |
406 pos_T t; | |
407 char_u *pat; | |
408 int search_flags = SEARCH_NOOF; | |
409 int i; | |
410 | |
411 if (!do_incsearch_highlighting(firstc)) | |
412 return OK; | |
413 if (ccline.cmdlen == 0) | |
414 return FAIL; | |
415 | |
416 if (firstc == ccline.cmdbuff[0]) | |
417 pat = last_search_pattern(); | |
418 else | |
419 pat = ccline.cmdbuff; | |
420 | |
421 save_last_search_pattern(); | |
422 cursor_off(); | |
423 out_flush(); | |
424 if (c == Ctrl_G) | |
425 { | |
426 t = is_state->match_end; | |
427 if (LT_POS(is_state->match_start, is_state->match_end)) | |
428 // Start searching at the end of the match not at the beginning of | |
429 // the next column. | |
430 (void)decl(&t); | |
431 search_flags += SEARCH_COL; | |
432 } | |
433 else | |
434 t = is_state->match_start; | |
435 if (!p_hls) | |
436 search_flags += SEARCH_KEEP; | |
437 ++emsg_off; | |
438 i = searchit(curwin, curbuf, &t, | |
439 c == Ctrl_G ? FORWARD : BACKWARD, | |
440 pat, count, search_flags, | |
441 RE_SEARCH, 0, NULL, NULL); | |
442 --emsg_off; | |
443 if (i) | |
444 { | |
445 is_state->search_start = is_state->match_start; | |
446 is_state->match_end = t; | |
447 is_state->match_start = t; | |
448 if (c == Ctrl_T && firstc == '/') | |
449 { | |
450 // Move just before the current match, so that when nv_search | |
451 // finishes the cursor will be put back on the match. | |
452 is_state->search_start = t; | |
453 (void)decl(&is_state->search_start); | |
454 } | |
455 else if (c == Ctrl_G && firstc == '?') | |
456 { | |
457 // Move just after the current match, so that when nv_search | |
458 // finishes the cursor will be put back on the match. | |
459 is_state->search_start = t; | |
460 (void)incl(&is_state->search_start); | |
461 } | |
462 if (LT_POS(t, is_state->search_start) && c == Ctrl_G) | |
463 { | |
464 // wrap around | |
465 is_state->search_start = t; | |
466 if (firstc == '?') | |
467 (void)incl(&is_state->search_start); | |
468 else | |
469 (void)decl(&is_state->search_start); | |
470 } | |
471 | |
472 set_search_match(&is_state->match_end); | |
473 curwin->w_cursor = is_state->match_start; | |
474 changed_cline_bef_curs(); | |
475 update_topline(); | |
476 validate_cursor(); | |
477 highlight_match = TRUE; | |
478 save_viewstate(&is_state->old_viewstate); | |
479 update_screen(NOT_VALID); | |
480 redrawcmdline(); | |
481 } | |
482 else | |
483 vim_beep(BO_ERROR); | |
484 restore_last_search_pattern(); | |
485 return FAIL; | |
486 } | |
487 | |
488 /* | |
489 * When CTRL-L typed: add character from the match to the pattern. | |
490 * May set "*c" to the added character. | |
491 * Return OK when jumping to cmdline_not_changed. | |
492 */ | |
493 static int | |
494 may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state) | |
495 { | |
496 if (!do_incsearch_highlighting(firstc)) | |
497 return FAIL; | |
498 | |
499 // Add a character from under the cursor for 'incsearch'. | |
500 if (is_state->did_incsearch) | |
501 { | |
502 curwin->w_cursor = is_state->match_end; | |
503 if (!EQUAL_POS(curwin->w_cursor, is_state->search_start)) | |
504 { | |
505 *c = gchar_cursor(); | |
506 | |
507 // If 'ignorecase' and 'smartcase' are set and the | |
508 // command line has no uppercase characters, convert | |
509 // the character to lowercase. | |
510 if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff)) | |
511 *c = MB_TOLOWER(*c); | |
512 if (*c != NUL) | |
513 { | |
514 if (*c == firstc || vim_strchr((char_u *)( | |
515 p_magic ? "\\~^$.*[" : "\\^$"), *c) != NULL) | |
516 { | |
517 // put a backslash before special characters | |
518 stuffcharReadbuff(*c); | |
519 *c = '\\'; | |
520 } | |
521 return FAIL; | |
522 } | |
523 } | |
524 } | |
525 return OK; | |
526 } | |
527 | |
528 static void | |
529 finish_incsearch_highlighting(int gotesc, incsearch_state_T *is_state) | |
530 { | |
531 if (is_state->did_incsearch) | |
532 { | |
533 if (gotesc) | |
534 curwin->w_cursor = is_state->save_cursor; | |
535 else | |
536 { | |
537 if (!EQUAL_POS(is_state->save_cursor, is_state->search_start)) | |
538 { | |
539 // put the '" mark at the original position | |
540 curwin->w_cursor = is_state->save_cursor; | |
541 setpcmark(); | |
542 } | |
543 curwin->w_cursor = is_state->search_start; | |
544 } | |
545 restore_viewstate(&is_state->old_viewstate); | |
546 highlight_match = FALSE; | |
547 validate_cursor(); /* needed for TAB */ | |
548 redraw_all_later(SOME_VALID); | |
549 } | |
226 } | 550 } |
227 #endif | 551 #endif |
228 | 552 |
229 /* | 553 /* |
230 * getcmdline() - accept a command line starting with firstc. | 554 * getcmdline() - accept a command line starting with firstc. |
260 char_u *lookfor = NULL; /* string to match */ | 584 char_u *lookfor = NULL; /* string to match */ |
261 int hiscnt; /* current history line in use */ | 585 int hiscnt; /* current history line in use */ |
262 int histype; /* history type to be used */ | 586 int histype; /* history type to be used */ |
263 #endif | 587 #endif |
264 #ifdef FEAT_SEARCH_EXTRA | 588 #ifdef FEAT_SEARCH_EXTRA |
265 pos_T search_start; /* where 'incsearch' starts searching */ | 589 incsearch_state_T is_state; |
266 pos_T save_cursor; | |
267 viewstate_T init_viewstate; | |
268 viewstate_T old_viewstate; | |
269 pos_T match_start = curwin->w_cursor; | |
270 pos_T match_end; | |
271 int did_incsearch = FALSE; | |
272 int incsearch_postponed = FALSE; | |
273 #endif | 590 #endif |
274 int did_wild_list = FALSE; /* did wild_list() recently */ | 591 int did_wild_list = FALSE; /* did wild_list() recently */ |
275 int wim_index = 0; /* index in wim_flags[] */ | 592 int wim_index = 0; /* index in wim_flags[] */ |
276 int res; | 593 int res; |
277 int save_msg_scroll = msg_scroll; | 594 int save_msg_scroll = msg_scroll; |
285 #ifdef FEAT_EVAL | 602 #ifdef FEAT_EVAL |
286 int break_ctrl_c = FALSE; | 603 int break_ctrl_c = FALSE; |
287 #endif | 604 #endif |
288 expand_T xpc; | 605 expand_T xpc; |
289 long *b_im_ptr = NULL; | 606 long *b_im_ptr = NULL; |
290 #if defined(FEAT_WILDMENU) || defined(FEAT_EVAL) || defined(FEAT_SEARCH_EXTRA) | 607 #if defined(FEAT_WILDMENU) || defined(FEAT_EVAL) |
291 /* Everything that may work recursively should save and restore the | 608 /* Everything that may work recursively should save and restore the |
292 * current command line in save_ccline. That includes update_screen(), a | 609 * current command line in save_ccline. That includes update_screen(), a |
293 * custom status line may invoke ":normal". */ | 610 * custom status line may invoke ":normal". */ |
294 struct cmdline_info save_ccline; | 611 struct cmdline_info save_ccline; |
295 #endif | 612 #endif |
307 if (firstc == ':' || firstc == '=' || firstc == '>') | 624 if (firstc == ':' || firstc == '=' || firstc == '>') |
308 cmd_hkmap = 0; | 625 cmd_hkmap = 0; |
309 #endif | 626 #endif |
310 | 627 |
311 ccline.overstrike = FALSE; /* always start in insert mode */ | 628 ccline.overstrike = FALSE; /* always start in insert mode */ |
629 | |
312 #ifdef FEAT_SEARCH_EXTRA | 630 #ifdef FEAT_SEARCH_EXTRA |
313 CLEAR_POS(&match_end); | 631 init_incsearch_state(&is_state); |
314 save_cursor = curwin->w_cursor; /* may be restored later */ | |
315 search_start = curwin->w_cursor; | |
316 save_viewstate(&init_viewstate); | |
317 save_viewstate(&old_viewstate); | |
318 #endif | 632 #endif |
319 | 633 |
320 /* | 634 /* |
321 * set some variables for redrawcmd() | 635 * set some variables for redrawcmd() |
322 */ | 636 */ |
1087 /* Truncate at the end, required for multi-byte chars. */ | 1401 /* Truncate at the end, required for multi-byte chars. */ |
1088 ccline.cmdbuff[ccline.cmdlen] = NUL; | 1402 ccline.cmdbuff[ccline.cmdlen] = NUL; |
1089 #ifdef FEAT_SEARCH_EXTRA | 1403 #ifdef FEAT_SEARCH_EXTRA |
1090 if (ccline.cmdlen == 0) | 1404 if (ccline.cmdlen == 0) |
1091 { | 1405 { |
1092 search_start = save_cursor; | 1406 is_state.search_start = is_state.save_cursor; |
1093 /* save view settings, so that the screen | 1407 /* save view settings, so that the screen |
1094 * won't be restored at the wrong position */ | 1408 * won't be restored at the wrong position */ |
1095 old_viewstate = init_viewstate; | 1409 is_state.old_viewstate = is_state.init_viewstate; |
1096 } | 1410 } |
1097 #endif | 1411 #endif |
1098 redrawcmd(); | 1412 redrawcmd(); |
1099 } | 1413 } |
1100 else if (ccline.cmdlen == 0 && c != Ctrl_W | 1414 else if (ccline.cmdlen == 0 && c != Ctrl_W |
1119 msg_col = 0; | 1433 msg_col = 0; |
1120 msg_putchar(' '); /* delete ':' */ | 1434 msg_putchar(' '); /* delete ':' */ |
1121 } | 1435 } |
1122 #ifdef FEAT_SEARCH_EXTRA | 1436 #ifdef FEAT_SEARCH_EXTRA |
1123 if (ccline.cmdlen == 0) | 1437 if (ccline.cmdlen == 0) |
1124 search_start = save_cursor; | 1438 is_state.search_start = is_state.save_cursor; |
1125 #endif | 1439 #endif |
1126 redraw_cmdline = TRUE; | 1440 redraw_cmdline = TRUE; |
1127 goto returncmd; /* back to cmd mode */ | 1441 goto returncmd; /* back to cmd mode */ |
1128 } | 1442 } |
1129 goto cmdline_changed; | 1443 goto cmdline_changed; |
1206 ccline.cmdbuff[i++] = ccline.cmdbuff[j++]; | 1520 ccline.cmdbuff[i++] = ccline.cmdbuff[j++]; |
1207 /* Truncate at the end, required for multi-byte chars. */ | 1521 /* Truncate at the end, required for multi-byte chars. */ |
1208 ccline.cmdbuff[ccline.cmdlen] = NUL; | 1522 ccline.cmdbuff[ccline.cmdlen] = NUL; |
1209 #ifdef FEAT_SEARCH_EXTRA | 1523 #ifdef FEAT_SEARCH_EXTRA |
1210 if (ccline.cmdlen == 0) | 1524 if (ccline.cmdlen == 0) |
1211 search_start = save_cursor; | 1525 is_state.search_start = is_state.save_cursor; |
1212 #endif | 1526 #endif |
1213 redrawcmd(); | 1527 redrawcmd(); |
1214 goto cmdline_changed; | 1528 goto cmdline_changed; |
1215 | 1529 |
1216 #ifdef FEAT_CLIPBOARD | 1530 #ifdef FEAT_CLIPBOARD |
1543 break; | 1857 break; |
1544 goto cmdline_changed; | 1858 goto cmdline_changed; |
1545 | 1859 |
1546 case Ctrl_L: | 1860 case Ctrl_L: |
1547 #ifdef FEAT_SEARCH_EXTRA | 1861 #ifdef FEAT_SEARCH_EXTRA |
1548 if (p_is && !cmd_silent && (firstc == '/' || firstc == '?')) | 1862 if (may_add_char_to_search(firstc, &c, &is_state) == OK) |
1549 { | |
1550 /* Add a character from under the cursor for 'incsearch' */ | |
1551 if (did_incsearch) | |
1552 { | |
1553 curwin->w_cursor = match_end; | |
1554 if (!EQUAL_POS(curwin->w_cursor, search_start)) | |
1555 { | |
1556 c = gchar_cursor(); | |
1557 /* If 'ignorecase' and 'smartcase' are set and the | |
1558 * command line has no uppercase characters, convert | |
1559 * the character to lowercase */ | |
1560 if (p_ic && p_scs | |
1561 && !pat_has_uppercase(ccline.cmdbuff)) | |
1562 c = MB_TOLOWER(c); | |
1563 if (c != NUL) | |
1564 { | |
1565 if (c == firstc || vim_strchr((char_u *)( | |
1566 p_magic ? "\\~^$.*[" : "\\^$"), c) | |
1567 != NULL) | |
1568 { | |
1569 /* put a backslash before special | |
1570 * characters */ | |
1571 stuffcharReadbuff(c); | |
1572 c = '\\'; | |
1573 } | |
1574 break; | |
1575 } | |
1576 } | |
1577 } | |
1578 goto cmdline_not_changed; | 1863 goto cmdline_not_changed; |
1579 } | |
1580 #endif | 1864 #endif |
1581 | 1865 |
1582 /* completion: longest common part */ | 1866 /* completion: longest common part */ |
1583 if (nextwild(&xpc, WILD_LONGEST, 0, firstc != '@') == FAIL) | 1867 if (nextwild(&xpc, WILD_LONGEST, 0, firstc != '@') == FAIL) |
1584 break; | 1868 break; |
1740 goto cmdline_not_changed; | 2024 goto cmdline_not_changed; |
1741 | 2025 |
1742 #ifdef FEAT_SEARCH_EXTRA | 2026 #ifdef FEAT_SEARCH_EXTRA |
1743 case Ctrl_G: /* next match */ | 2027 case Ctrl_G: /* next match */ |
1744 case Ctrl_T: /* previous match */ | 2028 case Ctrl_T: /* previous match */ |
1745 if (p_is && !cmd_silent && (firstc == '/' || firstc == '?')) | 2029 if (may_adjust_incsearch_highlighting( |
1746 { | 2030 firstc, count, &is_state, c) == FAIL) |
1747 pos_T t; | |
1748 char_u *pat; | |
1749 int search_flags = SEARCH_NOOF; | |
1750 | |
1751 if (ccline.cmdlen == 0) | |
1752 goto cmdline_not_changed; | |
1753 | |
1754 if (firstc == ccline.cmdbuff[0]) | |
1755 pat = last_search_pattern(); | |
1756 else | |
1757 pat = ccline.cmdbuff; | |
1758 | |
1759 save_last_search_pattern(); | |
1760 cursor_off(); | |
1761 out_flush(); | |
1762 if (c == Ctrl_G) | |
1763 { | |
1764 t = match_end; | |
1765 if (LT_POS(match_start, match_end)) | |
1766 /* start searching at the end of the match | |
1767 * not at the beginning of the next column */ | |
1768 (void)decl(&t); | |
1769 search_flags += SEARCH_COL; | |
1770 } | |
1771 else | |
1772 t = match_start; | |
1773 if (!p_hls) | |
1774 search_flags += SEARCH_KEEP; | |
1775 ++emsg_off; | |
1776 i = searchit(curwin, curbuf, &t, | |
1777 c == Ctrl_G ? FORWARD : BACKWARD, | |
1778 pat, count, search_flags, | |
1779 RE_SEARCH, 0, NULL, NULL); | |
1780 --emsg_off; | |
1781 if (i) | |
1782 { | |
1783 search_start = match_start; | |
1784 match_end = t; | |
1785 match_start = t; | |
1786 if (c == Ctrl_T && firstc == '/') | |
1787 { | |
1788 /* move just before the current match, so that | |
1789 * when nv_search finishes the cursor will be | |
1790 * put back on the match */ | |
1791 search_start = t; | |
1792 (void)decl(&search_start); | |
1793 } | |
1794 else if (c == Ctrl_G && firstc == '?') | |
1795 { | |
1796 /* move just after the current match, so that | |
1797 * when nv_search finishes the cursor will be | |
1798 * put back on the match */ | |
1799 search_start = t; | |
1800 (void)incl(&search_start); | |
1801 } | |
1802 if (LT_POS(t, search_start) && c == Ctrl_G) | |
1803 { | |
1804 /* wrap around */ | |
1805 search_start = t; | |
1806 if (firstc == '?') | |
1807 (void)incl(&search_start); | |
1808 else | |
1809 (void)decl(&search_start); | |
1810 } | |
1811 | |
1812 set_search_match(&match_end); | |
1813 curwin->w_cursor = match_start; | |
1814 changed_cline_bef_curs(); | |
1815 update_topline(); | |
1816 validate_cursor(); | |
1817 highlight_match = TRUE; | |
1818 save_viewstate(&old_viewstate); | |
1819 update_screen(NOT_VALID); | |
1820 redrawcmdline(); | |
1821 } | |
1822 else | |
1823 vim_beep(BO_ERROR); | |
1824 restore_last_search_pattern(); | |
1825 goto cmdline_not_changed; | 2031 goto cmdline_not_changed; |
1826 } | |
1827 break; | 2032 break; |
1828 #endif | 2033 #endif |
1829 | 2034 |
1830 case Ctrl_V: | 2035 case Ctrl_V: |
1831 case Ctrl_Q: | 2036 case Ctrl_Q: |
1949 * Jump to cmdline_changed when the command line did change. | 2154 * Jump to cmdline_changed when the command line did change. |
1950 * (Sorry for the goto's, I know it is ugly). | 2155 * (Sorry for the goto's, I know it is ugly). |
1951 */ | 2156 */ |
1952 cmdline_not_changed: | 2157 cmdline_not_changed: |
1953 #ifdef FEAT_SEARCH_EXTRA | 2158 #ifdef FEAT_SEARCH_EXTRA |
1954 if (!incsearch_postponed) | 2159 if (!is_state.incsearch_postponed) |
1955 continue; | 2160 continue; |
1956 #endif | 2161 #endif |
1957 | 2162 |
1958 cmdline_changed: | 2163 cmdline_changed: |
1959 /* Trigger CmdlineChanged autocommands. */ | 2164 /* Trigger CmdlineChanged autocommands. */ |
1960 trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED); | 2165 trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED); |
1961 | 2166 |
1962 #ifdef FEAT_SEARCH_EXTRA | 2167 #ifdef FEAT_SEARCH_EXTRA |
1963 /* | 2168 may_do_incsearch_highlighting(firstc, count, &is_state); |
1964 * 'incsearch' highlighting. | |
1965 */ | |
1966 if (p_is && !cmd_silent && (firstc == '/' || firstc == '?')) | |
1967 { | |
1968 pos_T end_pos; | |
1969 #ifdef FEAT_RELTIME | |
1970 proftime_T tm; | |
1971 #endif | |
1972 | |
1973 /* if there is a character waiting, search and redraw later */ | |
1974 if (char_avail()) | |
1975 { | |
1976 incsearch_postponed = TRUE; | |
1977 continue; | |
1978 } | |
1979 incsearch_postponed = FALSE; | |
1980 curwin->w_cursor = search_start; /* start at old position */ | |
1981 save_last_search_pattern(); | |
1982 | |
1983 /* If there is no command line, don't do anything */ | |
1984 if (ccline.cmdlen == 0) | |
1985 { | |
1986 i = 0; | |
1987 set_no_hlsearch(TRUE); /* turn off previous highlight */ | |
1988 redraw_all_later(SOME_VALID); | |
1989 } | |
1990 else | |
1991 { | |
1992 int search_flags = SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK; | |
1993 cursor_off(); /* so the user knows we're busy */ | |
1994 out_flush(); | |
1995 ++emsg_off; /* So it doesn't beep if bad expr */ | |
1996 #ifdef FEAT_RELTIME | |
1997 /* Set the time limit to half a second. */ | |
1998 profile_setlimit(500L, &tm); | |
1999 #endif | |
2000 if (!p_hls) | |
2001 search_flags += SEARCH_KEEP; | |
2002 i = do_search(NULL, firstc, ccline.cmdbuff, count, | |
2003 search_flags, | |
2004 #ifdef FEAT_RELTIME | |
2005 &tm, NULL | |
2006 #else | |
2007 NULL, NULL | |
2008 #endif | |
2009 ); | |
2010 --emsg_off; | |
2011 /* if interrupted while searching, behave like it failed */ | |
2012 if (got_int) | |
2013 { | |
2014 (void)vpeekc(); /* remove <C-C> from input stream */ | |
2015 got_int = FALSE; /* don't abandon the command line */ | |
2016 i = 0; | |
2017 } | |
2018 else if (char_avail()) | |
2019 /* cancelled searching because a char was typed */ | |
2020 incsearch_postponed = TRUE; | |
2021 } | |
2022 if (i != 0) | |
2023 highlight_match = TRUE; /* highlight position */ | |
2024 else | |
2025 highlight_match = FALSE; /* remove highlight */ | |
2026 | |
2027 /* first restore the old curwin values, so the screen is | |
2028 * positioned in the same way as the actual search command */ | |
2029 restore_viewstate(&old_viewstate); | |
2030 changed_cline_bef_curs(); | |
2031 update_topline(); | |
2032 | |
2033 if (i != 0) | |
2034 { | |
2035 pos_T save_pos = curwin->w_cursor; | |
2036 | |
2037 match_start = curwin->w_cursor; | |
2038 set_search_match(&curwin->w_cursor); | |
2039 validate_cursor(); | |
2040 end_pos = curwin->w_cursor; | |
2041 match_end = end_pos; | |
2042 curwin->w_cursor = save_pos; | |
2043 } | |
2044 else | |
2045 end_pos = curwin->w_cursor; /* shutup gcc 4 */ | |
2046 | |
2047 /* Disable 'hlsearch' highlighting if the pattern matches | |
2048 * everything. Avoids a flash when typing "foo\|". */ | |
2049 if (empty_pattern(ccline.cmdbuff)) | |
2050 set_no_hlsearch(TRUE); | |
2051 | |
2052 validate_cursor(); | |
2053 /* May redraw the status line to show the cursor position. */ | |
2054 if (p_ru && curwin->w_status_height > 0) | |
2055 curwin->w_redr_status = TRUE; | |
2056 | |
2057 save_cmdline(&save_ccline); | |
2058 update_screen(SOME_VALID); | |
2059 restore_cmdline(&save_ccline); | |
2060 restore_last_search_pattern(); | |
2061 | |
2062 /* Leave it at the end to make CTRL-R CTRL-W work. */ | |
2063 if (i != 0) | |
2064 curwin->w_cursor = end_pos; | |
2065 | |
2066 msg_starthere(); | |
2067 redrawcmdline(); | |
2068 did_incsearch = TRUE; | |
2069 } | |
2070 #else /* FEAT_SEARCH_EXTRA */ | |
2071 ; | |
2072 #endif | 2169 #endif |
2073 | 2170 |
2074 #ifdef FEAT_RIGHTLEFT | 2171 #ifdef FEAT_RIGHTLEFT |
2075 if (cmdmsg_rl | 2172 if (cmdmsg_rl |
2076 # ifdef FEAT_ARABIC | 2173 # ifdef FEAT_ARABIC |
2098 | 2195 |
2099 ExpandCleanup(&xpc); | 2196 ExpandCleanup(&xpc); |
2100 ccline.xpc = NULL; | 2197 ccline.xpc = NULL; |
2101 | 2198 |
2102 #ifdef FEAT_SEARCH_EXTRA | 2199 #ifdef FEAT_SEARCH_EXTRA |
2103 if (did_incsearch) | 2200 finish_incsearch_highlighting(gotesc, &is_state); |
2104 { | |
2105 if (gotesc) | |
2106 curwin->w_cursor = save_cursor; | |
2107 else | |
2108 { | |
2109 if (!EQUAL_POS(save_cursor, search_start)) | |
2110 { | |
2111 /* put the '" mark at the original position */ | |
2112 curwin->w_cursor = save_cursor; | |
2113 setpcmark(); | |
2114 } | |
2115 curwin->w_cursor = search_start; | |
2116 } | |
2117 restore_viewstate(&old_viewstate); | |
2118 highlight_match = FALSE; | |
2119 validate_cursor(); /* needed for TAB */ | |
2120 redraw_all_later(SOME_VALID); | |
2121 } | |
2122 #endif | 2201 #endif |
2123 | 2202 |
2124 if (ccline.cmdbuff != NULL) | 2203 if (ccline.cmdbuff != NULL) |
2125 { | 2204 { |
2126 /* | 2205 /* |
7237 } | 7316 } |
7238 ga_append(&ga, NUL); | 7317 ga_append(&ga, NUL); |
7239 | 7318 |
7240 return (char_u *)ga.ga_data; | 7319 return (char_u *)ga.ga_data; |
7241 } | 7320 } |
7242 | |
7243 #ifdef FEAT_SEARCH_EXTRA | |
7244 static void | |
7245 set_search_match(pos_T *t) | |
7246 { | |
7247 /* | |
7248 * First move cursor to end of match, then to the start. This | |
7249 * moves the whole match onto the screen when 'nowrap' is set. | |
7250 */ | |
7251 t->lnum += search_match_lines; | |
7252 t->col = search_match_endcol; | |
7253 if (t->lnum > curbuf->b_ml.ml_line_count) | |
7254 { | |
7255 t->lnum = curbuf->b_ml.ml_line_count; | |
7256 coladvance((colnr_T)MAXCOL); | |
7257 } | |
7258 } | |
7259 #endif |