version 1.7, 2011/09/21 19:01:49 |
version 1.8, 2014/04/25 13:38:21 |
|
|
/* |
/* |
* Copyright (C) 1984-2011 Mark Nudelman |
* Copyright (C) 1984-2012 Mark Nudelman |
* |
* |
* You may distribute under the terms of either the GNU General Public |
* You may distribute under the terms of either the GNU General Public |
* License or the Less License, as specified in the README file. |
* License or the Less License, as specified in the README file. |
* |
* |
* For more information about less, or for information on how to |
* For more information, see the README file. |
* contact the author, see the README file. |
|
*/ |
*/ |
|
|
|
|
|
|
char* text; |
char* text; |
int search_type; |
int search_type; |
}; |
}; |
|
|
|
#if NO_REGEX |
|
#define info_compiled(info) ((void*)0) |
|
#else |
|
#define info_compiled(info) ((info)->compiled) |
|
#endif |
|
|
static struct pattern_info search_info; |
static struct pattern_info search_info; |
static struct pattern_info filter_info; |
static struct pattern_info filter_info; |
|
|
char *pattern; |
char *pattern; |
int search_type; |
int search_type; |
{ |
{ |
|
#if !NO_REGEX |
if (pattern == NULL) |
if (pattern == NULL) |
CLEAR_PATTERN(search_info.compiled); |
CLEAR_PATTERN(info->compiled); |
else if (compile_pattern(pattern, search_type, &info->compiled) < 0) |
else if (compile_pattern(pattern, search_type, &info->compiled) < 0) |
return -1; |
return -1; |
|
#endif |
/* Pattern compiled successfully; save the text too. */ |
/* Pattern compiled successfully; save the text too. */ |
if (info->text != NULL) |
if (info->text != NULL) |
free(info->text); |
free(info->text); |
|
|
if (info->text != NULL) |
if (info->text != NULL) |
free(info->text); |
free(info->text); |
info->text = NULL; |
info->text = NULL; |
|
#if !NO_REGEX |
uncompile_pattern(&info->compiled); |
uncompile_pattern(&info->compiled); |
|
#endif |
} |
} |
|
|
/* |
/* |
|
|
prev_pattern(info) |
prev_pattern(info) |
struct pattern_info *info; |
struct pattern_info *info; |
{ |
{ |
if (info->search_type & SRCH_NO_REGEX) |
#if !NO_REGEX |
return (info->text != NULL); |
if ((info->search_type & SRCH_NO_REGEX) == 0) |
return (!is_null_pattern(info->compiled)); |
return (!is_null_pattern(info->compiled)); |
|
#endif |
|
return (info->text != NULL); |
} |
} |
|
|
#if HILITE_SEARCH |
#if HILITE_SEARCH |
|
|
} |
} |
|
|
/* |
/* |
|
* Hilight every character in a range of displayed characters. |
|
*/ |
|
static void |
|
create_hilites(linepos, start_index, end_index, chpos) |
|
POSITION linepos; |
|
int start_index; |
|
int end_index; |
|
int *chpos; |
|
{ |
|
struct hilite *hl; |
|
int i; |
|
|
|
/* Start the first hilite. */ |
|
hl = (struct hilite *) ecalloc(1, sizeof(struct hilite)); |
|
hl->hl_startpos = linepos + chpos[start_index]; |
|
|
|
/* |
|
* Step through the displayed chars. |
|
* If the source position (before cvt) of the char is one more |
|
* than the source pos of the previous char (the usual case), |
|
* just increase the size of the current hilite by one. |
|
* Otherwise (there are backspaces or something involved), |
|
* finish the current hilite and start a new one. |
|
*/ |
|
for (i = start_index+1; i <= end_index; i++) |
|
{ |
|
if (chpos[i] != chpos[i-1] + 1 || i == end_index) |
|
{ |
|
hl->hl_endpos = linepos + chpos[i-1] + 1; |
|
add_hilite(&hilite_anchor, hl); |
|
/* Start new hilite unless this is the last char. */ |
|
if (i < end_index) |
|
{ |
|
hl = (struct hilite *) ecalloc(1, sizeof(struct hilite)); |
|
hl->hl_startpos = linepos + chpos[i]; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
* Make a hilite for each string in a physical line which matches |
* Make a hilite for each string in a physical line which matches |
* the current pattern. |
* the current pattern. |
* sp,ep delimit the first match already found. |
* sp,ep delimit the first match already found. |
|
|
{ |
{ |
char *searchp; |
char *searchp; |
char *line_end = line + line_len; |
char *line_end = line + line_len; |
struct hilite *hl; |
|
|
|
if (sp == NULL || ep == NULL) |
if (sp == NULL || ep == NULL) |
return; |
return; |
|
|
*/ |
*/ |
searchp = line; |
searchp = line; |
do { |
do { |
if (ep > sp) |
create_hilites(linepos, sp-line, ep-line, chpos); |
{ |
|
hl = (struct hilite *) ecalloc(1, sizeof(struct hilite)); |
|
hl->hl_startpos = linepos + chpos[sp-line]; |
|
hl->hl_endpos = linepos + chpos[ep-line]; |
|
add_hilite(&hilite_anchor, hl); |
|
} |
|
/* |
/* |
* If we matched more than zero characters, |
* If we matched more than zero characters, |
* move to the first char after the string we matched. |
* move to the first char after the string we matched. |
|
|
searchp++; |
searchp++; |
else /* end of line */ |
else /* end of line */ |
break; |
break; |
} while (match_pattern(search_info.compiled, search_info.text, |
} while (match_pattern(info_compiled(&search_info), search_info.text, |
searchp, line_end - searchp, &sp, &ep, 1, search_info.search_type)); |
searchp, line_end - searchp, &sp, &ep, 1, search_info.search_type)); |
} |
} |
#endif |
#endif |
|
|
* If so, add an entry to the filter list. |
* If so, add an entry to the filter list. |
*/ |
*/ |
if ((search_type & SRCH_FIND_ALL) && prev_pattern(&filter_info)) { |
if ((search_type & SRCH_FIND_ALL) && prev_pattern(&filter_info)) { |
int line_filter = match_pattern(filter_info.compiled, filter_info.text, |
int line_filter = match_pattern(info_compiled(&filter_info), filter_info.text, |
cline, line_len, &sp, &ep, 0, filter_info.search_type); |
cline, line_len, &sp, &ep, 0, filter_info.search_type); |
if (line_filter) |
if (line_filter) |
{ |
{ |
|
|
*/ |
*/ |
if (prev_pattern(&search_info)) |
if (prev_pattern(&search_info)) |
{ |
{ |
line_match = match_pattern(search_info.compiled, search_info.text, |
line_match = match_pattern(info_compiled(&search_info), search_info.text, |
cline, line_len, &sp, &ep, 0, search_type); |
cline, line_len, &sp, &ep, 0, search_type); |
if (line_match) |
if (line_match) |
{ |
{ |