📄 findrep.c
字号:
++md2;
} else
for (i--; i >= 0 && last_c != p[i]; i--)
++md2;
assert( md2 >= 1 && md2 <= len );
return( md2 );
}
/*
* Name: calculate_backward_md2
* Purpose: Calculate mini delta2 for backward searches
* Date: October 31, 1992
* Passed: p: pointer to pattern
* len: length of pattern
* Notes: the backward mini delta2 is, from the start of the string, the
* first rightmost occurrence of the leftmost character. in the
* worst case, mini delta2 is -1. typically, mini delta2 is the
* negative length of the search pattern.
*/
int calculate_backward_md2( char *p, int len )
{
int first_c;
register int i;
register int md2;
md2 = -1;
i = 1;
first_c = *p;
if (mode.search_case == IGNORE) {
first_c = tolower( first_c );
for (; i < len && first_c != tolower( p[i] ); i++)
--md2;
} else
for (; i < len && first_c != p[i]; i++)
--md2;
assert( md2 <= -1 && md2 >= -len );
return( md2 );
}
/*
* Name: forward_boyer_moore_search
* Purpose: search forward for pattern using boyer array
* Passed: window: pointer to current window
* rline: pointer to real line counter
* rcol: pointer to real column variable
* Returns: position in file if found or NULL if not found
* Date: June 5, 1991
* Notes: Start searching from cursor position to end of file. If we hit
* end of file without a match, start searching from the beginning
* of file to cursor position. (do wrapped searches)
*/
line_list_ptr forward_boyer_moore_search( WINDOW *window, long *rline,
int *rcol )
{
register int len;
int i;
int end;
register WINDOW *win; /* put window pointer in a register */
line_list_ptr ll;
/*
* if cursor is beyond end of line then start at end of line
*/
win = window;
i = win->rcol + 1;
len = win->ll->len;
if (i > len)
i = len;
if (i < 0)
i = 0;
*rcol = i;
assert( *rcol >= 0 );
*rline = win->rline;
ll = search_forward( win->ll, rline, (size_t *)rcol );
if (ll == NULL) {
end = 0;
if (win->ll->next != NULL) {
end = win->ll->next->len;
win->ll->next->len = EOF;
}
/*
* haven't found pattern yet - now search from beginning of file
*/
g_status.wrapped = TRUE;
*rcol = 0;
*rline = 1L;
ll = search_forward( win->file_info->line_list, rline, (size_t *)rcol );
if (ll == win->ll && *rcol >= win->rcol)
ll = NULL;
if (win->ll->next != NULL)
win->ll->next->len = end;
}
if (ll != NULL)
bin_offset_adjust( win, *rline );
return( ll );
}
/*
* Name: search_forward
* Purpose: search forward for pattern using boyer array
* Passed: ll: pointer to current node in linked list
* rline: pointer to real line counter
* offset: offset into ll->line to begin search
* Returns: position in file if found or NULL if not found
* Date: January 8, 1992
* Notes: mini delta2 is the first leftmost occurrence of the rightmost
* character.
*/
line_list_ptr search_forward( line_list_ptr ll, long *rline, size_t *offset )
{
register int i;
text_ptr p;
text_ptr q;
int mini_delta2;
unsigned int mini_guard;
int guard;
int pat_len;
int len_s;
text_ptr s;
char *skip;
boyer_moore_type *bmp;
if (ll->len == EOF)
return( NULL );
else {
if (g_status.command == DefineGrep || g_status.command == RepeatGrep)
bmp = &sas_bm;
else
bmp = &bm;
pat_len = bmp->pattern_length;
mini_delta2 = bmp->forward_md2;
skip = bmp->skip_forward;
p = bmp->pattern;
i = pat_len - 1;
guard = -i;
mini_guard = *p;
if (mode.search_case != MATCH)
mini_guard = tolower( mini_guard );
s = ll->line;
s += *offset;
len_s = ll->len - *offset;
for (;;) {
/*
* Boyer-Moore fast skip loop. check character count as we move
* down the line.
*/
for (s+=i, len_s-=i; len_s > 0 && (i = skip[(unsigned char)*s]);
s+=i, len_s-=i);
if (len_s > 0) {
/*
* i == 0, possible match. Boyer-Moore slow match loop.
*/
if (mode.search_case == MATCH) {
if (s[guard] != mini_guard)
goto shift_func;
q = s + 1 - pat_len;
for (i=0; i < pat_len; i++)
if (q[i] != p[i])
goto shift_func;
} else {
if ((unsigned int)tolower( s[guard] ) != mini_guard)
goto shift_func;
q = s + 1 - pat_len;
for (i=0; i < pat_len; i++)
if (tolower( q[i] ) != tolower( p[i] ))
goto shift_func;
}
*offset = (size_t)(q - ll->line);
assert( *offset <= (unsigned)(ll->len - pat_len) );
return( ll );
}
shift_func:
if (len_s <= 0) {
++*rline;
ll = ll->next;
s = ll->line;
if (ll->len == EOF)
return( NULL );
len_s = ll->len;
i = pat_len - 1;
} else
i = mini_delta2;
}
}
}
/*
* Name: backward_boyer_moore_search
* Purpose: search backward for pattern using boyer array
* Passed: window: pointer to current window
* rline: pointer current real line counter
* rcol: pointer to real column
* Returns: position in file if found or NULL if not found
* Date: June 5, 1991
* Notes: Start searching from cursor position to beginning of file. If we
* hit beginning end of file without a match, start searching from the
* end of file to cursor position. (do wrapped searches)
*/
line_list_ptr backward_boyer_moore_search( WINDOW *window, long *rline, int *rcol )
{
int i;
int len;
int end;
register WINDOW *win; /* put window pointer in a register */
line_list_ptr ll;
win = window;
*rline = win->rline;
/*
* see if cursor is on EOF line. if so, move search start to previous node.
*/
if (win->ll->len != EOF) {
ll = win->ll;
i = win->rcol - 1;
i += bm.pattern_length - 1;
len = ll->len;
if (i >= len)
i = len - 1;
} else {
ll = win->ll->prev;
--*rline;
i = 0;
if (ll != NULL)
i = ll->len - 1;
}
*rcol = i;
ll = search_backward( ll, rline, (size_t *)rcol );
if (ll == NULL && win->rline <= win->file_info->length) {
end = 0;
if (win->ll->prev != NULL) {
end = win->ll->prev->len;
win->ll->prev->len = EOF;
}
/*
* haven't found pattern yet - now search from end of file
*/
g_status.wrapped = TRUE;
ll = win->file_info->line_list_end;
if (ll->prev != NULL)
*rcol = ll->prev->len;
else
*rcol = 0;
*rline = win->file_info->length;
ll = search_backward( ll->prev, rline, (size_t *)rcol );
if (ll == win->ll && *rcol <= win->rcol)
ll = NULL;
if (win->ll->prev != NULL)
win->ll->prev->len = end;
}
if (ll != NULL)
bin_offset_adjust( win, *rline );
return( ll );
}
/*
* Name: search_backward
* Purpose: search backward for pattern using boyer array
* Passed: ll: pointer to node in linked list to start search
* rline: pointer to real line counter
* offset: offset into ll->line to start search
* Returns: position in file if found else return NULL
* Date: January 8, 1992
* Notes: Start searching from cursor position to beginning of file.
* mini delta2 is the first rightmost occurrence of the leftmost character.
*/
line_list_ptr search_backward( line_list_ptr ll, long *rline, size_t *offset )
{
register int i;
text_ptr p;
int mini_delta2;
int pat_len;
int len_s;
text_ptr s;
if (ll == NULL)
return( NULL );
if (ll->len == EOF)
return( NULL );
else {
mini_delta2 = bm.backward_md2;
pat_len = bm.pattern_length;
p = bm.pattern;
i = -bm.pattern_length + 1;
s = ll->line;
s += *offset;
len_s = *offset + 1;
for (;;) {
/*
* Boyer-Moore fast skip loop. check character count as we move
* up the line.
*/
for (s+=i, len_s+=i; len_s > 0 &&
(i = bm.skip_backward[(unsigned char)*s]); s+=i, len_s+=i);
if (len_s > 0) {
/*
* i == 0, possible match. Boyer-Moore slow match loop.
*/
if (mode.search_case == MATCH) {
for (i=0; i < pat_len; i++)
if (s[i] != p[i])
goto shift_func;
} else {
for (i=0; i < pat_len; i++)
if (tolower( s[i] ) != tolower( p[i] ))
goto shift_func;
}
*offset =(size_t)(s - ll->line);
assert( *offset <= (unsigned)(ll->len - pat_len) );
return( ll );
}
shift_func:
if (len_s <= 0) {
--*rline;
ll = ll->prev;
if (ll == NULL)
return( NULL );
if (ll->len == EOF)
return( NULL );
len_s = ll->len;
s = ll->line + len_s - 1;
i = 1 - pat_len;
} else
i = mini_delta2;
}
}
}
/*
* Name: show_search_message
* Purpose: display search status
* Date: January 8, 1992
* Passed: i: index into message array
* color: color to display message
*/
void show_search_message( int i, int color )
{
/*
* 0 = blank
* 1 = wrapped...
* 2 = searching
* 3 = replacing
* 4 = nfa choked
*/
assert( i >= 0 && i <= 4);
s_output( find7[i], g_display.mode_line, 67, color );
}
/*
* Name: bin_offset_adjust
* Purpose: place cursor on screen given a position in file - default cline
* Date: June 5, 1991
* Passed: window: pointer to current window
* rline: real line position some where in the file
* Notes: in binary mode, we keep an accurate count of the offset of the
* cursor from the beginning of the file.
*/
void bin_offset_adjust( WINDOW *window, long rline )
{
line_list_ptr node;
long found_distance;
assert( rline >= 1L && rline <= window->file_info->length );
found_distance = window->rline - rline;
node = window->ll;
if (found_distance < 0) {
while (found_distance++ < 0) {
window->bin_offset += node->len;
node = node->next;
}
} else if (found_distance > 0) {
while (found_distance-- > 0) {
node = node->prev;
window->bin_offset -= node->len;
}
}
assert( window->bin_offset >= 0 );
}
/*
* Name: find_adjust
* Purpose: place cursor on screen given a position in file - default cline
* Date: June 5, 1991
* Passed: window: pointer to current window
* ll: position anywhere in file
* rline: real line number of ll in the file
* rcol: real column of ll in the file
* Notes: ll could be anywhere in file. Find the start of line that
* ll is on. Determine if start of line is behind or ahead of
* current line. Once that is done, it is easy to determine if ll
* is on screen. Lastly, current cursor position becomes start of
* ll line - reposition and display.
*/
void find_adjust( WINDOW *window, line_list_ptr ll, long rline, int rcol )
{
int cmd;
long test_line;
file_infos *file;
register WINDOW *win; /* put window pointer in a register */
win = window;
file = win->file_info;
/*
* given a real column, adjust for inflated tabs.
*/
if (mode.inflate_tabs)
rcol = detab_adjust_rcol( ll->line, rcol );
/*
* if p, start of found line, is greater than current line, see if
* p is between current line and bottom line on screen.
*/
if (win->rline < rline) {
/*
* test_line is the number of lines between rline and found line.
*/
test_line = rline - win->rline;
if ((long)win->cline + test_line <= (long)win->bottom_line)
win->cline += (int)test_line;
else
file->dirty = LOCAL;
/*
* if p, start of found line, is less than current line, see if
* p is between current line and top line on screen.
*/
} else if (win->rline > rline) {
test_line = win->rline - rline;
if ((long)win->cline - test_line > (long)(win->top_line+win->ruler-1))
win->cline -= (int)test_line;
else
file->dirty = LOCAL;
if (rline < (long)(win->cline - (win->top_line+win->ruler-1)))
win->cline = (int)rline + win->top_line+win->ruler - 1;
}
/*
* cursor line becomes found line. check if column is on screen.
*/
win->rline = rline;
win->ll = ll;
if (file->dirty == LOCAL && (win->cline == win->bottom_line ||
win->cline == win->top_line + win->ruler)) {
cmd = g_status.command;
if (cmd == RepeatFindForward1 || cmd == RepeatFindBackward1 ||
cmd == DefineDiff || cmd == RepeatDiff ||
cmd == FindRegX || cmd == RepeatFindRegX ||
cmd == DefineGrep || cmd == RepeatGrep) {
center_window( win );
} else if (cmd == ReplaceString) {
if (win->visible)
center_window( win );
}
}
check_virtual_col( win, rcol, rcol );
}
/*
* Name: replace_string
* Purpose: To set up and perform a replace operation.
* Date: June 5, 1991
* Passed: window: pointer to current window
*/
int replace_string( WINDOW *window )
{
int direction;
char pattern[MAX_COLS]; /* the old and replacement text */
int net_change;
int sub_len;
int file_changed;
int finished;
int use_prev_find;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -