@@ -264,11 +264,78 @@ set_search_match(pos_T *t)
264264
265265/*
266266 * Return TRUE when 'incsearch' highlighting is to be done.
267+ * Sets search_first_line and search_last_line to the address range.
267268 */
268269 static int
269- do_incsearch_highlighting (int firstc )
270+ do_incsearch_highlighting (int firstc , incsearch_state_T * is_state ,
271+ int * skiplen , int * patlen )
270272{
271- return p_is && !cmd_silent && (firstc == '/' || firstc == '?' );
273+ * skiplen = 0 ;
274+ * patlen = ccline .cmdlen ;
275+
276+ if (p_is && !cmd_silent )
277+ {
278+ // by default search all lines
279+ search_first_line = 0 ;
280+ search_last_line = MAXLNUM ;
281+
282+ if (firstc == '/' || firstc == '?' )
283+ return TRUE;
284+ if (firstc == ':' )
285+ {
286+ char_u * cmd = skip_range (ccline .cmdbuff , NULL );
287+ char_u * p ;
288+ int delim ;
289+ char_u * end ;
290+
291+ if (* cmd == 's' || * cmd == 'g' || * cmd == 'v' )
292+ {
293+ // Skip over "substitute" to find the pattern separator.
294+ for (p = cmd ; ASCII_ISALPHA (* p ); ++ p )
295+ ;
296+ if (* p != NUL )
297+ {
298+ delim = * p ++ ;
299+ end = skip_regexp (p , delim , p_magic , NULL );
300+ if (end > p )
301+ {
302+ char_u * dummy ;
303+ exarg_T ea ;
304+ pos_T save_cursor = curwin -> w_cursor ;
305+
306+ // found a non-empty pattern
307+ * skiplen = (int )(p - ccline .cmdbuff );
308+ * patlen = (int )(end - p );
309+
310+ // parse the address range
311+ vim_memset (& ea , 0 , sizeof (ea ));
312+ ea .line1 = 1 ;
313+ ea .line2 = 1 ;
314+ ea .cmd = ccline .cmdbuff ;
315+ ea .addr_type = ADDR_LINES ;
316+ parse_cmd_address (& ea , & dummy );
317+ curwin -> w_cursor = is_state -> search_start ;
318+ if (ea .addr_count > 0 )
319+ {
320+ search_first_line = ea .line1 ;
321+ search_last_line = ea .line2 ;
322+ }
323+ else if (* cmd == 's' )
324+ {
325+ // :s defaults to the current line
326+ search_first_line = curwin -> w_cursor .lnum ;
327+ search_last_line = curwin -> w_cursor .lnum ;
328+ }
329+
330+ curwin -> w_cursor = save_cursor ;
331+ return TRUE;
332+ }
333+ }
334+ }
335+ }
336+ }
337+
338+ return FALSE;
272339}
273340
274341/*
@@ -280,14 +347,16 @@ may_do_incsearch_highlighting(
280347 long count ,
281348 incsearch_state_T * is_state )
282349{
350+ int skiplen , patlen ;
283351 int i ;
284352 pos_T end_pos ;
285353 struct cmdline_info save_ccline ;
286354#ifdef FEAT_RELTIME
287355 proftime_T tm ;
288356#endif
357+ int c ;
289358
290- if (!do_incsearch_highlighting (firstc ))
359+ if (!do_incsearch_highlighting (firstc , is_state , & skiplen , & patlen ))
291360 return ;
292361
293362 // If there is a character waiting, search and redraw later.
@@ -298,12 +367,19 @@ may_do_incsearch_highlighting(
298367 }
299368 is_state -> incsearch_postponed = FALSE;
300369
301- // start at old position
302- curwin -> w_cursor = is_state -> search_start ;
370+ if (search_first_line == 0 )
371+ // start at the original cursor position
372+ curwin -> w_cursor = is_state -> search_start ;
373+ else
374+ {
375+ // start at the first line in the range
376+ curwin -> w_cursor .lnum = search_first_line ;
377+ curwin -> w_cursor .col = 0 ;
378+ }
303379 save_last_search_pattern ();
304380
305381 // If there is no command line, don't do anything.
306- if (ccline . cmdlen == 0 )
382+ if (patlen == 0 )
307383 {
308384 i = 0 ;
309385 set_no_hlsearch (TRUE); // turn off previous highlight
@@ -322,15 +398,24 @@ may_do_incsearch_highlighting(
322398#endif
323399 if (!p_hls )
324400 search_flags += SEARCH_KEEP ;
325- i = do_search (NULL , firstc , ccline .cmdbuff , count , search_flags ,
401+ c = ccline .cmdbuff [skiplen + patlen ];
402+ ccline .cmdbuff [skiplen + patlen ] = NUL ;
403+ i = do_search (NULL , firstc == ':' ? '/' : firstc ,
404+ ccline .cmdbuff + skiplen , count , search_flags ,
326405#ifdef FEAT_RELTIME
327406 & tm , NULL
328407#else
329408 NULL , NULL
330409#endif
331410 );
411+ ccline .cmdbuff [skiplen + patlen ] = c ;
332412 -- emsg_off ;
333413
414+ if (curwin -> w_cursor .lnum < search_first_line
415+ || curwin -> w_cursor .lnum > search_last_line )
416+ // match outside of address range
417+ i = 0 ;
418+
334419 // if interrupted while searching, behave like it failed
335420 if (got_int )
336421 {
@@ -369,8 +454,11 @@ may_do_incsearch_highlighting(
369454
370455 // Disable 'hlsearch' highlighting if the pattern matches everything.
371456 // Avoids a flash when typing "foo\|".
457+ c = ccline .cmdbuff [skiplen + patlen ];
458+ ccline .cmdbuff [skiplen + patlen ] = NUL ;
372459 if (empty_pattern (ccline .cmdbuff ))
373460 set_no_hlsearch (TRUE);
461+ ccline .cmdbuff [skiplen + patlen ] = c ;
374462
375463 validate_cursor ();
376464 // May redraw the status line to show the cursor position.
@@ -398,25 +486,27 @@ may_do_incsearch_highlighting(
398486 */
399487 static int
400488may_adjust_incsearch_highlighting (
401- int firstc ,
402- long count ,
489+ int firstc ,
490+ long count ,
403491 incsearch_state_T * is_state ,
404- int c )
492+ int c )
405493{
494+ int skiplen , patlen ;
406495 pos_T t ;
407496 char_u * pat ;
408497 int search_flags = SEARCH_NOOF ;
409498 int i ;
499+ int save ;
410500
411- if (!do_incsearch_highlighting (firstc ))
501+ if (!do_incsearch_highlighting (firstc , is_state , & skiplen , & patlen ))
412502 return OK ;
413- if (ccline .cmdlen == 0 )
503+ if (patlen == 0 && ccline .cmdbuff [ skiplen ] == NUL )
414504 return FAIL ;
415505
416- if (firstc == ccline .cmdbuff [0 ])
506+ if (firstc == ccline .cmdbuff [skiplen ])
417507 pat = last_search_pattern ();
418508 else
419- pat = ccline .cmdbuff ;
509+ pat = ccline .cmdbuff + skiplen ;
420510
421511 save_last_search_pattern ();
422512 cursor_off ();
@@ -435,17 +525,20 @@ may_adjust_incsearch_highlighting(
435525 if (!p_hls )
436526 search_flags += SEARCH_KEEP ;
437527 ++ emsg_off ;
528+ save = pat [patlen ];
529+ pat [patlen ] = NUL ;
438530 i = searchit (curwin , curbuf , & t ,
439531 c == Ctrl_G ? FORWARD : BACKWARD ,
440532 pat , count , search_flags ,
441533 RE_SEARCH , 0 , NULL , NULL );
442534 -- emsg_off ;
535+ pat [patlen ] = save ;
443536 if (i )
444537 {
445538 is_state -> search_start = is_state -> match_start ;
446539 is_state -> match_end = t ;
447540 is_state -> match_start = t ;
448- if (c == Ctrl_T && firstc == '/ ' )
541+ if (c == Ctrl_T && firstc != '? ' )
449542 {
450543 // Move just before the current match, so that when nv_search
451544 // finishes the cursor will be put back on the match.
@@ -493,7 +586,9 @@ may_adjust_incsearch_highlighting(
493586 static int
494587may_add_char_to_search (int firstc , int * c , incsearch_state_T * is_state )
495588{
496- if (!do_incsearch_highlighting (firstc ))
589+ int skiplen , patlen ;
590+
591+ if (!do_incsearch_highlighting (firstc , is_state , & skiplen , & patlen ))
497592 return FAIL ;
498593
499594 // Add a character from under the cursor for 'incsearch'.
@@ -507,7 +602,7 @@ may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state)
507602 // If 'ignorecase' and 'smartcase' are set and the
508603 // command line has no uppercase characters, convert
509604 // the character to lowercase.
510- if (p_ic && p_scs && !pat_has_uppercase (ccline .cmdbuff ))
605+ if (p_ic && p_scs && !pat_has_uppercase (ccline .cmdbuff + skiplen ))
511606 * c = MB_TOLOWER (* c );
512607 if (* c != NUL )
513608 {
0 commit comments