"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/search.c" between
most-5.0.0a.tar.gz and most-5.1.0.tar.gz

About: most is a textfile paging program (supports multiple windows and can scroll left and right).

search.c  (most-5.0.0a):search.c  (most-5.1.0)
/* -*- mode: C; mode: fold -*- */ /* -*- mode: C; mode: fold -*- */
/* /*
This file is part of MOST. This file is part of MOST.
Copyright (c) 1991, 1999, 2002, 2005, 2006, 2007 John E. Davis Copyright (c) 1991, 1999, 2002, 2005-2018, 2019 John E. Davis
This program is free software; you can redistribute it and/or modify it This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) Software Foundation; either version 2 of the License, or (at your option)
any later version. any later version.
This program is distributed in the hope that it will be useful, but WITHOUT This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 675 with this program; if not, write to the Free Software Foundation, Inc., 675
Mass Ave, Cambridge, MA 02139, USA. Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include <slang.h> #include <slang.h>
#include "most.h" #include "most.h"
#include "window.h" #include "window.h"
#include "line.h" #include "line.h"
#include "file.h" #include "file.h"
#include "display.h" #include "display.h"
#include "search.h" #include "search.h"
/* Note!!! The regular expression searches may not work. I have not /* Note!!! The regular expression searches may not work. I have not
* tested them. * tested them.
* FIXME!!! This whole thing needs to be rewritten. It is a mess. * FIXME!!! This whole thing needs to be rewritten. It is a mess.
*/ */
int Most_Case_Sensitive = 0; int Most_Case_Sensitive = 0;
char Most_Search_Str[256]; char Most_Search_Str[256];
int Most_Search_Dir = 1; int Most_Search_Dir = 1;
#include "jdmacros.h" #include "jdmacros.h"
#undef SLANG_REGEXP typedef struct Search_Type_ Search_Type;
#undef HAVE_V8_REGCOMP struct Search_Type_
{
#define UPCASE(ch) ((!Most_Case_Sensitive && (ch <= 'z') && (ch >= 'a')) ? (ch - void *cd;
32) : ch) unsigned char *(*fsearch_method) (Search_Type *, unsigned char *, unsigned ch
#if defined(HAVE_V8_REGCOMP) || defined(SLANG_REGEXP) ar *, unsigned char *);
unsigned char *(*bsearch_method) (Search_Type *, unsigned char *, unsigned ch
/* ar *, unsigned char *);
* Regular expression stuff void (*close_method)(Search_Type *);
* ************************ };
*/
# ifdef HAVE_V8_REGCOMP
# include "regexp.h"
/* pointer to area malloced by regcomp() */
static struct regexp *regpattern = NULL;
# else
/* slang regular expression structure */
#if SLANG_VERSION < 20000
static SLRegexp_Type regdata;
/* buffer for compiled regular expression */
static unsigned char regbuf[sizeof(Most_Search_Str) * 3];
#else
static SLRegexp_Type *Regexp;
#endif
# endif /* HAVE_V8_REGCOMP */
/* set if regexp compiled OK, 0 if regular expression error */ static unsigned char Ascii_Upper[256];
static int regcompOK = 1;
/* uncompiled search pattern */ static void bs_search_init (void)
static char savepattern[sizeof(Most_Search_Str)];
/*
* This function is called by the V8 regcomp to report
* errors in regular expressions.
*/
static void regerror(char *s)
{ {
char string[256]; static int inited = 0;
unsigned int i;
regcompOK = 0; /* clear flag, ie regexp error */ if (inited) return;
sprintf(string, "Regular expression error: %s", s); for (i = 0; i < 256; i++) Ascii_Upper[i] = i;
most_message(string, 1); for (i = 'a'; i <= 'z'; i++) Ascii_Upper[i] = (i - 32);
inited = 1;
} }
/*
* Compiles the search pattern "key" into a regular expression for use by
* do_regexec()
*
* Returns: 1 success
* 0 error
*
*/
static int do_regcomp(unsigned char *key)
{
static int old_Most_Case_Sensitive;
unsigned char UpCaseKey[sizeof(savepattern)];
# ifndef HAVE_V8_REGCOMP
int posn; /* reg exp error at this offset */
# endif
/* #define UPCASE(ch) (Ascii_Upper[(ch)])
* Only recompile search string if it has changed
*/
if ((0 == strcmp ((char *)key, (char *) savepattern))
&& (Most_Case_Sensitive == old_Most_Case_Sensitive))
return 1;
# ifdef HAVE_V8_REGCOMP #define CHAR_EQS(a,b) \
if (regpattern != NULL) (((a) == (b)) || (!Most_Case_Sensitive && (UPCASE(a) == UPCASE(b))))
free(regpattern);
# endif
if ( strlen((char *)key) >= sizeof(savepattern) ) static int is_ansi_escape (unsigned char **begp, unsigned char *end)
{ {
regerror("Search string too long"); unsigned char *p, ch;
savepattern[0] = '\0';
return 0;
}
old_Most_Case_Sensitive = Most_Case_Sensitive; p = *begp;
if ((p == end) || (*p++ != '[')) return 0;
if ( Most_Case_Sensitive == 0 ) /* Look for "ESC X m", where X is one of:
* X = ""
* X = digit
* X = digit ; digit ...
*/
ch = *p++;
while (isdigit (ch))
{ {
register unsigned char *p; /* ptr to UpCaseKey */ while ((p < end) && isdigit (*p))
register unsigned char *keyp; /* ptr to key */ p++;
register unsigned char c; /* source character */
/*
* Make a upper case copy of every character from "key"
* into "UpCaseKey"
*/
p = UpCaseKey;
keyp = key;
while ( (c = *keyp++) != '\0' )
*p++ = UPCASE(c);
*p = '\0';
}
strcpy((char *)savepattern, (char *)key); if (p == end)
return 0;
# ifdef HAVE_V8_REGCOMP ch = *p++;
regpattern = regcomp((char *)(Most_Case_Sensitive ? key : UpCaseKey)); if (ch == 'm')
if (regpattern == NULL) break;
{
regcompOK = 1;
return 1;
}
# else
# if SLANG_VERSION < 20000 if ((ch != ';') || (p == end))
regdata.case_sensitive = 1; return 0;
regdata.buf = regbuf;
regdata.pat = Most_Case_Sensitive ? key : UpCaseKey;
regdata.buf_len = sizeof (regbuf);
posn = SLang_regexp_compile(&regdata);
# else
if (Regexp != NULL)
SLregexp_free (Regexp);
if (NULL == (Regexp = SLregexp_compile ((char *)key, Most_Case_Sensitive ? 0
: SLREGEXP_CASELESS)))
posn = -1;
else
posn = 0;
# endif
if (posn == 0) ch = *p++;
{
regcompOK = 1;
return 1;
} }
regerror ("Unable to compile pattern"); if (ch != 'm')
# endif /* HAVE_V8_REGCOMP */ return 0;
/*
* regcomp has already printed error message via regerror().
*/
savepattern[0] = '\0';
return 0; /* failure */
}
/* *begp = p;
* Call the appropriate regular expression execute function return 1;
*/
static unsigned char *do_regexec(unsigned char *string, unsigned int len)
{
# ifdef HAVE_V8_REGCOMP
if ( regexec(regpattern, (char *)string) )
return( (unsigned char *)regpattern->startp[0] );
else
return( NULL );
# else
# if SLANG_VERSION < 20000
return ( SLang_regexp_match(string, len, &regdata) );
# else
return (unsigned char *)SLregexp_match (Regexp, (char *)string, len));
# endif
# endif /* HAVE_V8_REGCOMP */
} }
/*
* Make a upper case copy of a string. Also changes any "c\b" character
* strings into just "" so that highlighted and underlined characters
* can be searched.
*
* Reuses malloced memory, so a copy cannot be retained between calls.
*/
static unsigned char *StrUpCaseCopy(unsigned char *input) static int is_rev_ansi_escape (unsigned char *beg, unsigned char **endp)
{ {
static unsigned char *uppercase; /* ptr to malloced area */ unsigned char *p, ch;
static size_t bufsize; /* size of malloced area */
unsigned char *src; /* ptr to source */
register unsigned char *dest; /* ptr to destination */
register int idx; /* index into uppercase[] */
register unsigned char c; /* source character */
size_t length; /* size of string to copy */
src = input; p = *endp;
length = strlen((char *)src) + 1; /* len of line plus terminator */ if (p == beg)
return 0;
if ( length > bufsize ) ch = *p--;
while (isdigit (ch))
{ {
if ( uppercase != (unsigned char *)NULL ) while ((p > beg) && isdigit (*p))
free(uppercase); p--;
bufsize = (length > 256 ) ? length : 256; /* 256 byte default */ if (p == beg)
return 0;
uppercase = (unsigned char *)malloc(bufsize); ch = *p--;
if ( uppercase == (unsigned char *)NULL )
return(NULL);
}
/* if (ch == '[')
* Make the copy converting to upper case as we go break;
*/
dest = uppercase; if ((ch != ';') || (p == beg))
return 0;
for ( idx = 0 ; (c = *src) != '\0' ; src++ ) ch = *p--;
{
if ( c == '\b' ) /* backspace */
{
if ( idx-- > 0 )
dest--; /* back up dest pointer */
}
else
{
if ( idx++ >= 0 )
*dest++ = UPCASE(c);
}
} }
*dest = '\0'; /* add termination */ if ((ch != '[') || (p < beg) || (*p != 033))
return 0;
return(uppercase); *endp = p-1;
return 1;
} }
/*
* Given an offset into a copy made by StrUpCaseCopy() and a pointer to the
* original string, returns a pointer into the original string corresponding
* to this offset.
*/
static unsigned char *GetOrigPtr(unsigned char *original, int offset)
{
register unsigned char *p = original;
register int j = offset;
/* /* These routines have special processing for ANSI escape sequence and backspace
* Step through, adjusting offset according to backspaces found handling.
*/ * For example, "hello world" may occur as:
while ( *p != '\0' ) * plain: hello world
{ * underlined: h_e_l_l_o_ world
if ( *p == '\b' ) * underlined: _h_e_l_l_o world
j++; * bold: hheelllloo world
else * ansi: hello world
j--; * ansi: hello world
*/
if ( j < 0 )
break;
else
p++;
}
return(p);
}
#endif /* HAVE_V8_REGCOMP || SLANG_REGEXP */
/* This routine returns the 1 + position of first match of key in str. /* This routine returns the 1 + position of first match of key in str.
key is modified to match the case of str. */ * searches from beg up to but not including end. Handles backspace, etc
/* We should try to optimize this routine */ */
/* searches from beg up to but not including end */
#if defined(SLANG_REGEXP)
static unsigned char * static unsigned char *
forw_search_region_regexp (unsigned char *beg, unsigned char *end, bs_fsearch (Search_Type *st,
unsigned char *key) unsigned char *beg, unsigned char *end,
unsigned char *key)
{ {
if (Regexp != NULL) unsigned char ch, ch1, ch1up;
SLregexp_free (Regexp);
if (NULL == (Regexp = SLregexp_compile ((char *)key, Most_Case_Sensitive ? 0
: SLREGEXP_CASELESS)))
return NULL;
if ( do_regcomp(key) == 0 )
return(Most_Eob);
/*
* For regular expression searches we need to do a line by line
* search, so it is necessary to temporarily replace '\n' with '\0'
* characters.
*
* ***** THIS IS NOT ALLOWED FOR MMAPPED FILES!!!!!!!!! *****
*/
p = beg;
linebeg = beg;
while (linebeg < end)
{
while ((p < end) && (*p != '\n')) p++;
if (p == end) break;
/* *p = 0; -- not allow for mmapped files */
if ( Most_Case_Sensitive == 0 ) /* i.e. case insensitive */
{
copy = StrUpCaseCopy(linebeg);
if ( copy == (unsigned char *)NULL )
return(Most_Eob);
}
/*
* Quick sanity check for beginning of line archored tests.
* If 1st char of key is "^", then the character before linebeg (which
* must be beyond the start of the window), must be a "\n",
* otherwise do_regexec() isn't called.
*/
if (
# if 0
((*key != '^')
|| (linebeg > Most_Win->beg_pos && linebeg[-1] == '\n'))
&&
#endif
(match = do_regexec(Most_Case_Sensitive ? linebeg : copy)))
{
/* *p = '\n'; --- NOT ALLOWED */
if ( Most_Case_Sensitive == 0 )
{
/*
* Use offset into "copy" as idx to find point in
* real line.
*/
return( GetOrigPtr(linebeg, match - copy) );
}
else
{
return( match );
}
}
/* *p++ = '\n'; */
linebeg = p;
}
return(Most_Eob);
}
#endif
static unsigned char *forw_search_region(unsigned char *beg,
unsigned char *end,
unsigned char *key)
{
#if defined(HAVE_V8_REGCOMP) || defined(SLANG_REGEXP)
return forw_search_region_regexp (beg, end, key);
#else
char ch, char1, work[256];
unsigned char *pos; unsigned char *pos;
int key_len,j, str_len; int cis, key_len, j, str_len;
if (Most_Case_Sensitive)
{
strcpy(work, (char *) key);
key_len = strlen((char *) key);
}
else
{
/* upcase key */
key_len = 0;
while (0 != (ch = key[key_len]))
{
ch = UPCASE(ch);
work[key_len++] = ch; /* null char is ok */
}
}
(void) st;
key_len = strlen ((char *)key);
if (key_len == 0) if (key_len == 0)
return Most_Eob; return Most_Eob;
str_len = (int) (end - beg); str_len = (int) (end - beg);
if (str_len < key_len) return (Most_Eob); if (str_len < key_len) return (Most_Eob);
# if 0 cis = (Most_Case_Sensitive == 0);
str_len -= key_len; /* effective length */ ch1 = key[0];
end -= (key_len - 1); ch1up = UPCASE(ch1);
# endif
char1 = work[0];
while (1) while (1)
{ {
/* Find first character that matches */ /* Find first character that matches */
while (1) while (1)
{ {
if (beg == end) return Most_Eob; if (beg == end) return Most_Eob;
ch = *beg++; ch = *beg++;
ch = UPCASE(ch); if ((ch == ch1)
if (ch == char1) || (cis && (ch1up == UPCASE(ch))))
break; break;
} }
/* so we have a position of possible match */ /* so we have a position of possible match */
j = 1; j = 1;
pos = beg; /* save this position so we start from here again */ pos = beg; /* save this position so we start from here again */
while (1) while (1)
{ {
skipping to change at line 445 skipping to change at line 213
break; break;
ch = *beg++; ch = *beg++;
/* FIXME: This only works for x^Hx but not x^Hx^Hx... /* FIXME: This only works for x^Hx but not x^Hx^Hx...
* It is probably better to skip all the ^H characters * It is probably better to skip all the ^H characters
* until the end. That is, regard "a^Hb^Hc" as 'c'. * until the end. That is, regard "a^Hb^Hc" as 'c'.
*/ */
if ((ch == 8) if ((ch == 8)
&& (beg + 1 < end) && (beg + 1 < end)
&& (Most_V_Opt == 0) && (CHAR_EQS(key[j - 1], *beg)
&& ((work[j - 1] == UPCASE(*beg))
|| (*beg == '_'))) || (*beg == '_')))
{ {
ch = *(beg + 1); ch = *(beg + 1);
beg += 2; beg += 2;
} }
else if ((ch == '_') && (beg + 1 < end)) else if ((ch == '_') && (beg + 1 < end))
{ {
ch = *beg++; ch = *beg++;
if (ch == 8) ch = *beg++; if (ch == 8) ch = *beg++;
else else
{ {
ch = '_'; ch = '_';
beg--; beg--;
} }
} }
else if ((ch == 033) && is_ansi_escape (&beg, end))
continue;
if (UPCASE(ch) != work[j]) if (!CHAR_EQS(ch, key[j]))
break; break;
j++; j++;
} }
beg = pos; beg = pos;
} }
#endif /* HAVE_V8_REGCOMP || SLANG_REGEXP */
} }
/* /*
* Search backwards in the buffer "beg" up to, but not including "end" for * Search backwards in the buffer "beg" up to, but not including "end" for
* pattern "key". * pattern "key". It handles backspaces, etc
*/ */
static unsigned char *
static unsigned char *back_search_region(unsigned char *beg, bs_bsearch (Search_Type *st,
unsigned char *end, unsigned char *beg, unsigned char *end,
unsigned char *key) unsigned char *key)
{ {
#if defined(HAVE_V8_REGCOMP) || defined(SLANG_REGEXP) unsigned char ch, ch1, ch1up;
register unsigned char *p;
unsigned char *endp, /* end of line */
*lastmatch, /* last match in line */
*endprevline, /* end of line before this one */
*match; /* ptr to matching string */
unsigned char savec; /* last char on line */
/*
* Compile "key" into an executable regular expression
*/
if ( do_regcomp(key) == 0 )
return(Most_Eob);
/*
* Starting from the end of the buffer, break the buffer into lines
* then for each line do forward search to find a match. If one is
* found, move pointer forward one character and try again until
* unsuccessful. In this way we find the last match on the line
* and isn't that what we want to do in a reverse search.
*/
endp = end;
lastmatch = Most_Eob;
while ( 1 ) /* forever loop */
{
if ( (endp < beg) )
return(Most_Eob); /* Reach start of buffer, no match */
/* Find the real end of current line */
if ( (p = (unsigned char *)strchr((char *)endp, '\n')) != NULL )
endp = p;
savec = *endp;
*endp = '\0'; /* terminate line with NULL */
/* Find the beginning of line */
for ( p = endp - 1 ; (p >= beg) && (*p != '\n') ; p-- )
{
}
endprevline = p;
p++; /* point to 1st char after newline */
/*
* Keep searching forward in this line till no more matches
*/
if ( Most_Case_Sensitive == 0 ) /* i.e. case insensitive */
{
unsigned char *copy; /* ptr to upper case copy */
unsigned char *savecopy; /* copy of "copy" */
copy = StrUpCaseCopy(p);
if ( copy == (unsigned char *)NULL )
return(Most_Eob);
savecopy = copy;
/*
* Quick sanity check for beginning of line archored tests.
* Must be at start of line.
*/
while ( ((*key != '^') || (copy == savecopy))
&& (match = do_regexec(copy)) )
{
if ( GetOrigPtr(p, match - savecopy) > end )
break;
lastmatch = match;
if ( *lastmatch == '\0' ) /* key must be "$" or "^" */
break;
copy = lastmatch + 1; /* character after match */
}
if ( lastmatch != Most_Eob ) /* found a match */
lastmatch = GetOrigPtr(p, lastmatch - savecopy);
}
else
{
/*
* Quick sanity check for beginning of line archored tests.
* Must be at start of buffer or start of line
*/
while ( ( (*key != '^') || (p == endprevline + 1) )
&& (match = do_regexec(p)) )
{
if ( match > end )
break;
lastmatch = match;
if ( *lastmatch == '\0' ) /* key must be "$" or "^" */
break;
p = lastmatch + 1; /* character after match */
}
}
*endp = savec;
if ( lastmatch != Most_Eob ) /* found a match */
return(lastmatch);
endp = endprevline;
}
#else
char ch, char1, work[256];
unsigned char *pos; unsigned char *pos;
int key_len,j, str_len; int key_len,j, str_len;
int cis;
if (Most_Case_Sensitive) (void) st;
{ key_len = strlen ((char *)key);
strcpy(work, (char *) key);
key_len = strlen((char *) key);
}
else
{
/* upcase key */
key_len = 0;
while (0 != (ch = key[key_len]))
{
ch = UPCASE(ch);
work[key_len++] = ch; /* null char is ok */
}
}
if (key_len == 0) return Most_Eob; if (key_len == 0) return Most_Eob;
str_len = (int) (end - beg); str_len = (int) (end - beg);
if (str_len < key_len) return Most_Eob; if (str_len < key_len) return Most_Eob;
# if 0 ch1 = key[key_len-1];
str_len = str_len - key_len; /* effective length */ ch1up = UPCASE(ch1);
beg += key_len; cis = (Most_Case_Sensitive == 0);
# endif
char1 = work [key_len - 1];
while (1) while (1)
{ {
while (1) while (1)
{ {
if (end < beg) if (end < beg)
return Most_Eob; return Most_Eob;
ch = *end--; ch = *end--;
ch = UPCASE (ch); if ((ch == ch1)
if (ch == char1) || (cis && (ch1up == UPCASE(ch))))
break; break;
} }
pos = end; /* save this position so we start from here again */ pos = end; /* save this position so we start from here again */
j = key_len - 2; j = key_len - 2;
while (1) while (1)
{ {
if (j < 0) if (j < 0)
return end + 1; return end + 1;
if (end < beg) if (end < beg)
break; break;
ch = *end--; ch = *end--;
if ((ch == 8) if ((ch == 8)
&& (end >= beg + 1) && (end >= beg + 1)
&& (Most_V_Opt == 0) && (CHAR_EQS(key[j + 1], *end)
&& ((work[j + 1] == UPCASE(*end))
|| (*end == '_'))) || (*end == '_')))
{ {
ch = *(end - 1); ch = *(end - 1);
end -= 2; end -= 2;
} }
else if ((ch == '_') else if ((ch == '_')
&& (end >= beg + 1) && (end >= beg + 1))
&& (Most_V_Opt == 0))
{ {
ch = *end--; ch = *end--;
if (ch == 8) ch = *end--; if (ch == 8) ch = *end--;
else else
{ {
ch = '_'; ch = '_';
end++; end++;
} }
} }
else if ((ch == 'm') && is_rev_ansi_escape (beg, &end))
continue;
if (UPCASE (ch) != work[j]) if (!CHAR_EQS(ch, key[j]))
break; break;
j--; j--;
} }
end = pos; end = pos;
} }
#endif /* HAVE_V8_REGCOMP || SLANG_REGEXP */
} }
int most_search(unsigned char *from, int repeat, MOST_INT *col) static int bs_open_search (Search_Type *st, char *key)
{ {
/* return the line match was found as well as line number, (void) key;
* search from i on; assume that line_array match the i so we need
* no initial lookup */ bs_search_init ();
st->fsearch_method = bs_fsearch;
st->bsearch_method = bs_bsearch;
st->close_method = NULL;
st->cd = NULL;
return 0;
}
static unsigned char *sl_fsearch (Search_Type *st,
unsigned char *beg, unsigned char *end,
unsigned char *key)
{
unsigned char *p;
(void) key;
if (NULL == (p = SLsearch_forward ((SLsearch_Type *)st->cd, beg, end)))
p = Most_Eob;
return p;
}
static unsigned char *sl_bsearch (Search_Type *st,
unsigned char *beg, unsigned char *end,
unsigned char *key)
{
unsigned char *p;
(void) key;
if (NULL == (p = SLsearch_backward ((SLsearch_Type *)st->cd, beg, end, end)))
p = Most_Eob;
return p;
}
static void sl_search_close (Search_Type *st)
{
if (st->cd != NULL)
SLsearch_delete ((SLsearch_Type *) st->cd);
}
static int sl_open_search (Search_Type *st, char *key)
{
unsigned int flags = 0;
if (Most_Case_Sensitive == 0) flags |= SLSEARCH_CASELESS;
if (Most_UTF8_Mode) flags |= SLSEARCH_UTF8;
if (NULL == (st->cd = SLsearch_new ((SLuchar_Type *) key, flags)))
return -1;
st->fsearch_method = sl_fsearch;
st->bsearch_method = sl_bsearch;
st->close_method = sl_search_close;
return 0;
}
static int
do_search_internal (Search_Type *st,
unsigned char *from, int repeat, MOST_INT *col)
{
/* return the line match was found as well as line number,
* search from i on; assume that line_array match the i so we need
* no initial lookup */
int test; int test;
MOST_INT save_line, the_col, row, s_len; MOST_INT save_line, the_col, row, s_len;
char string[300]; char string[300];
unsigned char *pos; unsigned char *pos, *eob;
unsigned int save_ofs; unsigned int save_ofs;
unsigned int found_ofs; unsigned int found_ofs;
if ((from < Most_Beg) || (from > Most_Eob)) return(-1); if (*Most_Search_Str == 0)
{
most_message("Search string not specified.",1);
return -1;
}
if ((from < Most_Beg) || (from > Most_Eob)) return -1;
save_ofs = Most_C_Offset; save_ofs = Most_C_Offset;
save_line = Most_C_Line; save_line = Most_C_Line;
found_ofs = Most_Eob - Most_Beg; found_ofs = Most_Eob - Most_Beg;
*col = 0; *col = 0;
s_len = strlen (Most_Search_Str); s_len = strlen (Most_Search_Str);
pos = from; pos = from;
if (*Most_Search_Str) eob = Most_Eob;
test = repeat && (pos < Most_Eob) && (pos >= Most_Beg);
while(test)
{ {
test = repeat && (pos < Most_Eob) && (pos >= Most_Beg); if (Most_Search_Dir == 1)
while(test)
{ {
if (Most_Search_Dir == 1) while (1)
{ {
while (1) unsigned int pos_ofs;
{
unsigned int pos_ofs;
pos = forw_search_region(pos, Most_Eob, (unsigned char*) M pos = (*st->fsearch_method)(st, pos, Most_Eob, (unsigned char*)
ost_Search_Str); Most_Search_Str);
pos_ofs = (unsigned int) (Most_Eob - Most_Beg); pos_ofs = (unsigned int) (Most_Eob - Most_Beg);
if (pos < Most_Eob) if (pos < Most_Eob)
break; break;
if (0 == most_read_file_dsc (10)) if (0 == most_read_file_dsc (10, 0))
{ {
/* Pointer may be invalid after this call */ /* Pointer may be invalid after this call */
pos = Most_Beg + pos_ofs; pos = Most_Beg + pos_ofs;
break; break;
}
/* This might need an adjustment */
pos = Most_Beg + (pos_ofs - s_len);
if (pos < Most_Beg) pos = Most_Beg;
} }
}
else
pos = back_search_region(Most_Beg, pos,
(unsigned char *) Most_Search_Str);
if (pos < Most_Eob) /* This might need an adjustment */
{ pos = Most_Beg + (pos_ofs - s_len);
repeat--; if (pos < Most_Beg) pos = Most_Beg;
found_ofs = pos - Most_Beg;
if (Most_Search_Dir == 1)
pos += s_len;
else pos--;
} }
test = repeat && (pos < Most_Eob) && (pos >= Most_Beg); }
else
pos = (*st->bsearch_method)(st, Most_Beg, pos, (unsigned char *) Most_S
earch_Str);
if (pos < Most_Eob)
{
repeat--;
found_ofs = pos - Most_Beg;
if (Most_Search_Dir == 1)
pos += s_len;
else pos--;
}
test = repeat && (pos < Most_Eob) && (pos >= Most_Beg);
if (SLKeyBoard_Quit)
{
most_message ("Search Interrupted.", 1);
break;
} }
} }
if (eob != Most_Eob)
Most_Num_Lines = most_count_lines (Most_Beg, Most_Eob);
if (repeat) /* not found */ if (repeat) /* not found */
{ {
*col = 0; *col = 0;
#if defined(HAVE_V8_REGCOMP) || defined(SLANG_REGEXP)
if ( regcompOK ) /* don't print error msg if regerr msg */
{
#endif
if (Most_Search_Str[0] == '\0')
most_message("Search string not specified.",1);
else
{
(void) sprintf(string,"Search failed: %s",Most_Search_Str);
most_message(string,1);
}
#if defined(HAVE_V8_REGCOMP) || defined(SLANG_REGEXP)
}
#endif
(void) sprintf(string,"Search failed: %s",Most_Search_Str);
most_message(string,1);
row = -1; row = -1;
} }
else /* if ( !Most_T_Opt && !Most_B_Opt) */ /* expand tabs to get col corre ct */ else /* if ( !Most_T_Opt && !Most_B_Opt) */ /* expand tabs to get col corre ct */
{ {
most_find_row_column(Most_Beg + found_ofs, &row, &the_col); most_find_row_column(Most_Beg + found_ofs, &row, &the_col);
if (Most_B_Opt) *col = the_col + 52; if (Most_B_Opt) *col = the_col + 52;
else else
*col = 1 + most_apparant_distance(Most_Beg + found_ofs); *col = 1 + most_apparant_distance(Most_Beg + found_ofs);
} }
Most_C_Offset = save_ofs; Most_C_Offset = save_ofs;
Most_C_Line = save_line; Most_C_Line = save_line;
if (row > 0) Most_Curs_Offset = found_ofs; if (row > 0) Most_Curs_Offset = found_ofs;
return row; return row;
} }
static int search_internal (Search_Type *st, unsigned char *from, int repeat, MO
ST_INT *colp)
{
int status;
status = do_search_internal (st, from, repeat, colp);
if (st->close_method != NULL)
(st->close_method)(st);
return status;
}
static int simple_search (unsigned char *from, int repeat, MOST_INT *colp)
{
Search_Type st;
if (Most_V_Opt || Most_B_Opt)
{
/* Nothing special about the ^H and _ chars. User faster SLsearch */
if (-1 == sl_open_search (&st, Most_Search_Str))
return -1;
}
else if (-1 == bs_open_search (&st, Most_Search_Str))
return -1;
return search_internal (&st, from, repeat, colp);
}
static void re_search_close (Search_Type *st)
{
if (st->cd != NULL)
SLregexp_free ((SLRegexp_Type *) st->cd);
}
static unsigned char *
re_fsearch (Search_Type *st,
unsigned char *beg, unsigned char *end,
unsigned char *key)
{
SLRegexp_Type *re;
unsigned char *p;
unsigned int flags;
(void) key;
re = (SLRegexp_Type *)st->cd;
(void) SLregexp_get_hints (re, &flags);
while (beg < end)
{
unsigned char *line_end = beg;
while (line_end < end)
{
unsigned char ch = *line_end++;
if (ch == '\n') break;
}
p = (unsigned char *)SLregexp_match (re, (char *)beg, (line_end - beg));
if (p != NULL)
{
if ((0 == (flags & SLREGEXP_HINT_BOL))
|| (p != beg)
|| (beg == Most_Beg)
|| (*(beg - 1) == '\n'))
return p;
}
beg = line_end;
}
return Most_Eob;
}
static unsigned char *
re_bsearch (Search_Type *st,
unsigned char *beg, unsigned char *end,
unsigned char *key)
{
SLRegexp_Type *re;
unsigned char *line_end, *eob;
unsigned int flags;
(void) key;
re = (SLRegexp_Type *)st->cd;
(void) SLregexp_get_hints (re, &flags);
line_end = end;
eob = Most_Eob;
while (line_end < eob)
{
if (*line_end == '\n')
break;
line_end++;
}
while (end > beg)
{
unsigned char *p, *match;
unsigned char *line = end;
while (line > beg)
{
line--;
if (*line == '\n')
{
line++;
break;
}
}
/* line is now at the start of a line */
if (NULL != (match = (unsigned char *)SLregexp_match (re, (char *)line, l
ine_end-line)))
{
if (match >= end)
{
/* Match occurs to right of boundary. Try previous line */
end = line_end = line-1;
continue;
}
if (flags & SLREGEXP_HINT_BOL)
return match;
/* t tt z t t t z */
/* Find match closest to end */
while ((line < end)
&& (NULL != (p = (unsigned char *)SLregexp_match (re, (char *
)line, (line_end - line))))
&& (p < end))
{
match = p;
line++;
}
return match;
}
end = line-1;
line_end = end;
}
return Most_Eob;
}
static int regexp_search (unsigned char *from, int repeat, MOST_INT *colp)
{
Search_Type st;
SLRegexp_Type *re;
char *pattern;
unsigned int flags;
pattern = Most_Search_Str;
flags = 0;
if (Most_Case_Sensitive == 0) flags |= SLREGEXP_CASELESS;
re = SLregexp_compile (pattern, flags);
if (re == NULL)
return -1;
(void) SLregexp_get_hints (re, &flags);
if (flags & SLREGEXP_HINT_OSEARCH)
{
SLregexp_free (re);
return simple_search (from, repeat, colp);
}
st.cd = (void *)re;
st.fsearch_method = re_fsearch;
st.bsearch_method = re_bsearch;
st.close_method = re_search_close;
return search_internal (&st, from, repeat, colp);
}
int most_search (unsigned char *from, int repeat, MOST_INT *colp)
{
if (Most_Do_Regexp_Search)
return regexp_search (from, repeat, colp);
return simple_search (from, repeat, colp);
}
 End of changes. 79 change blocks. 
523 lines changed or deleted 237 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)