diff options
Diffstat (limited to 'contrib/less/search.c')
-rw-r--r-- | contrib/less/search.c | 126 |
1 files changed, 84 insertions, 42 deletions
diff --git a/contrib/less/search.c b/contrib/less/search.c index 31133fb..7d0af8b 100644 --- a/contrib/less/search.c +++ b/contrib/less/search.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2000 Mark Nudelman + * Copyright (C) 1984-2002 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -52,6 +52,7 @@ extern int linenums; extern int sc_height; extern int jump_sline; extern int bs_mode; +extern int ctldisp; extern int status_col; extern POSITION start_attnpos; extern POSITION end_attnpos; @@ -106,6 +107,7 @@ static char *last_pattern = NULL; #define CVT_TO_LC 01 /* Convert upper-case to lower-case */ #define CVT_BS 02 /* Do backspace processing */ #define CVT_CRLF 04 /* Remove CR after LF */ +#define CVT_ANSI 010 /* Remove ANSI escape sequences */ static void cvt_text(odst, osrc, ops) @@ -116,17 +118,23 @@ cvt_text(odst, osrc, ops) register char *dst; register char *src; - for (src = osrc, dst = odst; *src != '\0'; src++, dst++) + for (src = osrc, dst = odst; *src != '\0'; src++) { if ((ops & CVT_TO_LC) && isupper((unsigned char) *src)) /* Convert uppercase to lowercase. */ - *dst = tolower((unsigned char) *src); + *dst++ = tolower((unsigned char) *src); else if ((ops & CVT_BS) && *src == '\b' && dst > odst) /* Delete BS and preceding char. */ - dst -= 2; - else + dst--; + else if ((ops & CVT_ANSI) && *src == ESC) + { + /* Skip to end of ANSI escape sequence. */ + while (src[1] != '\0') + if (is_ansi_end(*++src)) + break; + } else /* Just copy. */ - *dst = *src; + *dst++ = *src; } if ((ops & CVT_CRLF) && dst > odst && dst[-1] == '\r') dst--; @@ -134,6 +142,30 @@ cvt_text(odst, osrc, ops) } /* + * Determine which conversions to perform. + */ + static int +get_cvt_ops() +{ + int ops = 0; + if (is_caseless || bs_mode == BS_SPECIAL) + { + if (is_caseless) + ops |= CVT_TO_LC; + if (bs_mode == BS_SPECIAL) + ops |= CVT_BS; + if (bs_mode != BS_CONTROL) + ops |= CVT_CRLF; + } else if (bs_mode != BS_CONTROL) + { + ops |= CVT_CRLF; + } + if (ctldisp == OPT_ONPLUS) + ops |= CVT_ANSI; + return (ops); +} + +/* * Are there any uppercase letters in this string? */ static int @@ -587,9 +619,10 @@ add_hilite(anchor, hl) * Adjust hl_startpos & hl_endpos to account for backspace processing. */ static void -adj_hilite(anchor, linepos) +adj_hilite(anchor, linepos, cvt_ops) struct hilite *anchor; POSITION linepos; + int cvt_ops; { char *line; struct hilite *hl; @@ -631,18 +664,39 @@ adj_hilite(anchor, linepos) } if (*line == '\0') break; + if (cvt_ops & CVT_ANSI) + { + while (line[0] == ESC) + { + /* + * Found an ESC. The file position moves + * forward past the entire ANSI escape sequence. + */ + line++; + npos++; + while (*line != '\0') + { + npos++; + if (is_ansi_end(*line++)) + break; + } + } + } opos++; npos++; line++; - while (line[0] == '\b' && line[1] != '\0') + if (cvt_ops & CVT_BS) { - /* - * Found a backspace. The file position moves - * forward by 2 relative to the processed line - * which was searched in hilite_line. - */ - npos += 2; - line += 2; + while (line[0] == '\b' && line[1] != '\0') + { + /* + * Found a backspace. The file position moves + * forward by 2 relative to the processed line + * which was searched in hilite_line. + */ + npos += 2; + line += 2; + } } } } @@ -653,11 +707,12 @@ adj_hilite(anchor, linepos) * sp,ep delimit the first match already found. */ static void -hilite_line(linepos, line, sp, ep) +hilite_line(linepos, line, sp, ep, cvt_ops) POSITION linepos; char *line; char *sp; char *ep; + int cvt_ops; { char *searchp; struct hilite *hl; @@ -706,15 +761,13 @@ hilite_line(linepos, line, sp, ep) break; } while (match_pattern(searchp, &sp, &ep, 1)); - if (bs_mode == BS_SPECIAL) - { - /* - * If there were backspaces in the original line, they - * were removed, and hl_startpos/hl_endpos are not correct. - * {{ This is very ugly. }} - */ - adj_hilite(&hilites, linepos); - } + /* + * If there were backspaces in the original line, they + * were removed, and hl_startpos/hl_endpos are not correct. + * {{ This is very ugly. }} + */ + adj_hilite(&hilites, linepos, cvt_ops); + /* * Now put the hilites into the real list. */ @@ -871,9 +924,10 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) POSITION *pendpos; { char *line; - int linenum; + LINENUM linenum; char *sp, *ep; int line_match; + int cvt_ops; POSITION linepos, oldpos; linenum = find_linenum(pos); @@ -953,20 +1007,8 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) * If it's a caseless search, convert the line to lowercase. * If we're doing backspace processing, delete backspaces. */ - if (is_caseless || bs_mode == BS_SPECIAL) - { - int ops = 0; - if (is_caseless) - ops |= CVT_TO_LC; - if (bs_mode == BS_SPECIAL) - ops |= CVT_BS; - if (bs_mode != BS_CONTROL) - ops |= CVT_CRLF; - cvt_text(line, line, ops); - } else if (bs_mode != BS_CONTROL) - { - cvt_text(line, line, CVT_CRLF); - } + cvt_ops = get_cvt_ops(); + cvt_text(line, line, cvt_ops); /* * Test the next line to see if we have a match. @@ -990,7 +1032,7 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) * hilite list and keep searching. */ if (line_match) - hilite_line(linepos, line, sp, ep); + hilite_line(linepos, line, sp, ep, cvt_ops); #endif } else if (--matches <= 0) { @@ -1007,7 +1049,7 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) */ clr_hilite(); if (line_match) - hilite_line(linepos, line, sp, ep); + hilite_line(linepos, line, sp, ep, cvt_ops); } #endif if (plinepos != NULL) |