Commit c5c5230b authored by David Lawrence Ramsey's avatar David Lawrence Ramsey
Browse files

overhaul the bracket searching code so that it no longer requires regex

support to work, and add some miscellaneous search code cleanups


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@3183 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
No related merge requests found
Showing with 160 additions and 99 deletions
+160 -99
......@@ -101,6 +101,10 @@ CVS code -
nano is built with --disable-nls. Changes to Makefile.am and
doc/man/Makefile.am. (Mike Frysinger)
- Rename the NANO_SMALL #define to NANO_TINY. (DLR)
- Overhaul the bracket searching code so that it no longer
requires regex support to work. New functions revstrpbrk()
and find_bracket_match(); changes to sc_init_one() and
do_find_bracket(). (DLR)
- chars.c:
mbwidth()
- If wcwidth() returns -1 for the character passed in, treat the
......@@ -132,6 +136,15 @@ CVS code -
- rcfile.c:
do_rcfile()
- Remove unneeded assert. (DLR)
- search.c:
findnextstr()
- Remove parameter can_display_wrap, as it's always set to TRUE
now, and rename parameter wholeword to whole_word for
consistency. (DLR)
do_replace_loop()
- Change order of parameters to more closely match those of
findnextstr(), and rename parameter wholewords to whole_word
for consistency. (DLR)
- text.c:
begpar()
- Return FALSE if foo is NULL, as inpar() does. (DLR)
......
......@@ -814,6 +814,26 @@ size_t mbstrnlen(const char *s, size_t maxlen)
return strnlen(s, maxlen);
}
#ifndef NANO_TINY
/* This function is equivalent to strpbrk(), except in that it scans the
* string in reverse, starting at rev_start. */
char *revstrpbrk(const char *s, const char *accept, const char
*rev_start)
{
assert(s != NULL && accept != NULL && rev_start != NULL);
for (; rev_start >= s; rev_start--) {
const char *q = (*rev_start == '\0') ? NULL : strchr(accept,
*rev_start);
if (q != NULL)
return (char *)rev_start;
}
return NULL;
}
#endif /* !NANO_TINY */
#ifndef DISABLE_JUSTIFY
/* This function is equivalent to strchr() for multibyte strings. */
char *mbstrchr(const char *s, char *c)
......
......@@ -313,7 +313,7 @@ void shortcut_init(bool unjustify)
#ifndef DISABLE_JUSTIFY
const char *nano_fulljustify_msg = N_("Justify the entire file");
#endif
#if !defined(NANO_TINY) && defined(HAVE_REGEX_H)
#ifndef NANO_TINY
const char *nano_bracket_msg = N_("Find other bracket");
#endif
const char *nano_cancel_msg = N_("Cancel the current function");
......@@ -594,7 +594,7 @@ void shortcut_init(bool unjustify)
NANO_NO_KEY, NANO_NO_KEY, NOVIEW, do_full_justify);
#endif
#if !defined(NANO_TINY) && defined(HAVE_REGEX_H)
#ifndef NANO_TINY
sc_init_one(&main_list, NANO_NO_KEY, N_("Find Other Bracket"),
IFHELP(nano_bracket_msg, NANO_BRACKET_KEY), NANO_NO_KEY,
NANO_NO_KEY, VIEW, do_find_bracket);
......
......@@ -196,6 +196,10 @@ size_t mbstrlen(const char *s);
size_t nstrnlen(const char *s, size_t maxlen);
#endif
size_t mbstrnlen(const char *s, size_t maxlen);
#ifndef NANO_TINY
char *revstrpbrk(const char *s, const char *accept, const char
*rev_start);
#endif
#ifndef DISABLE_JUSTIFY
char *mbstrchr(const char *s, char *c);
#ifdef ENABLE_NANORC
......@@ -489,9 +493,8 @@ void not_found_msg(const char *str);
void search_abort(void);
void search_init_globals(void);
int search_init(bool replacing, bool use_answer);
bool findnextstr(bool can_display_wrap, bool wholeword, bool
no_sameline, const filestruct *begin, size_t begin_x, const char
*needle, size_t *needle_len);
bool findnextstr(bool whole_word, bool no_sameline, const filestruct
*begin, size_t begin_x, const char *needle, size_t *needle_len);
void findnextstr_wrap_reset(void);
void do_search(void);
#ifndef NANO_TINY
......@@ -502,9 +505,9 @@ void replace_abort(void);
int replace_regexp(char *string, bool create);
#endif
char *replace_line(const char *needle);
ssize_t do_replace_loop(const char *needle, const filestruct
*real_current, size_t *real_current_x, bool wholewords, bool
*canceled);
ssize_t do_replace_loop(bool whole_word, bool *canceled, const
filestruct *real_current, size_t *real_current_x, const char
*needle);
void do_replace(void);
void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
bool interactive, bool save_pos, bool allow_update);
......@@ -514,9 +517,8 @@ void do_gotopos(ssize_t line, size_t pos_x, ssize_t pos_y, size_t
pos_pww);
#endif
#ifndef NANO_TINY
#ifdef HAVE_REGEX_H
bool find_bracket_match(bool reverse, const char *bracket_set);
void do_find_bracket(void);
#endif
#ifdef ENABLE_NANORC
bool history_has_changed(void);
#endif
......
......@@ -256,21 +256,18 @@ int search_init(bool replacing, bool use_answer)
/* Look for needle, starting at (current, current_x). If no_sameline is
* TRUE, skip over begin when looking for needle. begin is the line
* where we first started searching, at column begin_x. If
* can_display_wrap is TRUE, we put messages on the statusbar and wrap
* around the file boundaries. The return value specifies whether we
* found anything. If we did, set needle_len to the length of the
* string we found if it isn't NULL. */
bool findnextstr(bool can_display_wrap, bool wholeword, bool
no_sameline, const filestruct *begin, size_t begin_x, const char
*needle, size_t *needle_len)
* where we first started searching, at column begin_x. The return
* value specifies whether we found anything. If we did, set needle_len
* to the length of the string we found if it isn't NULL. */
bool findnextstr(bool whole_word, bool no_sameline, const filestruct
*begin, size_t begin_x, const char *needle, size_t *needle_len)
{
filestruct *fileptr = openfile->current;
const char *rev_start = NULL, *found = NULL;
size_t found_len;
/* The length of the match we found. */
size_t current_x_find = 0;
/* The location of the match we found. */
/* The location in the current line of the match we found. */
ssize_t current_y_find = openfile->current_y;
/* rev_start might end up 1 character before the start or after the
......@@ -304,7 +301,7 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
/* If we're searching for whole words, see if this potential
* match is a whole word. */
if (wholeword) {
if (whole_word) {
char *word = mallocstrncpy(NULL, found, found_len + 1);
word[found_len] = '\0';
......@@ -317,15 +314,14 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
* match isn't a whole word, or if we're not allowed to find
* a match on the same line we started on and this potential
* match is on that line, continue searching. */
if ((!wholeword || found_whole) && (!no_sameline ||
if ((!whole_word || found_whole) && (!no_sameline ||
fileptr != openfile->current))
break;
}
/* We've finished processing the file, so get out. */
if (search_last_line) {
if (can_display_wrap)
not_found_msg(needle);
not_found_msg(needle);
return FALSE;
}
......@@ -343,9 +339,6 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
/* Start or end of buffer reached, so wrap around. */
if (fileptr == NULL) {
if (!can_display_wrap)
return FALSE;
#ifndef NANO_TINY
if (ISSET(BACKWARDS_SEARCH)) {
fileptr = openfile->filebot;
......@@ -358,8 +351,7 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
}
#endif
if (can_display_wrap)
statusbar(_("Search Wrapped"));
statusbar(_("Search Wrapped"));
}
/* Original start line reached. */
......@@ -385,8 +377,7 @@ bool findnextstr(bool can_display_wrap, bool wholeword, bool
current_x_find > begin_x
#endif
) {
if (can_display_wrap)
not_found_msg(needle);
not_found_msg(needle);
return FALSE;
}
......@@ -450,7 +441,7 @@ void do_search(void)
#endif
findnextstr_wrap_reset();
didfind = findnextstr(TRUE, FALSE, FALSE, openfile->current,
didfind = findnextstr(FALSE, FALSE, openfile->current,
openfile->current_x, answer, NULL);
/* Check to see if there's only one occurrence of the string and
......@@ -465,7 +456,7 @@ void do_search(void)
* which case it's the only occurrence. */
if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp,
last_search)) {
didfind = findnextstr(TRUE, FALSE, TRUE, openfile->current,
didfind = findnextstr(FALSE, TRUE, openfile->current,
openfile->current_x, answer, NULL);
if (fileptr == openfile->current && fileptr_x ==
openfile->current_x && !didfind)
......@@ -506,7 +497,7 @@ void do_research(void)
#endif
findnextstr_wrap_reset();
didfind = findnextstr(TRUE, FALSE, FALSE, openfile->current,
didfind = findnextstr(FALSE, FALSE, openfile->current,
openfile->current_x, last_search, NULL);
/* Check to see if there's only one occurrence of the string and
......@@ -521,9 +512,8 @@ void do_research(void)
* found again, in which case it's the only occurrence. */
if (ISSET(USE_REGEXP) && regexp_bol_or_eol(&search_regexp,
last_search)) {
didfind = findnextstr(TRUE, FALSE, TRUE,
openfile->current, openfile->current_x, answer,
NULL);
didfind = findnextstr(FALSE, TRUE, openfile->current,
openfile->current_x, answer, NULL);
if (fileptr == openfile->current && fileptr_x ==
openfile->current_x && !didfind)
statusbar(_("This is the only occurrence"));
......@@ -649,9 +639,9 @@ char *replace_line(const char *needle)
* needle is the string to seek. We replace it with answer. Return -1
* if needle isn't found, else the number of replacements performed. If
* canceled isn't NULL, set it to TRUE if we canceled. */
ssize_t do_replace_loop(const char *needle, const filestruct
*real_current, size_t *real_current_x, bool wholewords, bool
*canceled)
ssize_t do_replace_loop(bool whole_word, bool *canceled, const
filestruct *real_current, size_t *real_current_x, const char
*needle)
{
ssize_t numreplaced = -1;
size_t match_len;
......@@ -685,7 +675,7 @@ ssize_t do_replace_loop(const char *needle, const filestruct
*canceled = FALSE;
findnextstr_wrap_reset();
while (findnextstr(TRUE, wholewords,
while (findnextstr(whole_word,
#ifdef HAVE_REGEX_H
/* We should find a bol and/or eol regex only once per line. If
* the bol_or_eol flag is set, it means that the last search
......@@ -922,8 +912,8 @@ void do_replace(void)
begin_x = openfile->current_x;
pww_save = openfile->placewewant;
numreplaced = do_replace_loop(last_search, begin, &begin_x, FALSE,
NULL);
numreplaced = do_replace_loop(FALSE, NULL, begin, &begin_x,
last_search);
/* Restore where we were. */
openfile->edittop = edittop_save;
......@@ -1034,22 +1024,95 @@ void do_gotopos(ssize_t line, size_t pos_x, ssize_t pos_y, size_t
#endif
#ifndef NANO_TINY
#ifdef HAVE_REGEX_H
/* Search for a match to one of the two characters in bracket_set. If
* reverse is TRUE, search backwards. Otherwise, search forwards. */
bool find_bracket_match(bool reverse, const char *bracket_set)
{
filestruct *fileptr = openfile->current;
const char *rev_start = NULL, *found = NULL;
size_t current_x_find = 0;
/* The location in the current line of the match we found. */
ssize_t current_y_find = openfile->current_y;
assert(strlen(bracket_set) == 2);
/* rev_start might end up 1 character before the start or after the
* end of the line. This won't be a problem because we'll skip over
* it below in that case, and rev_start will be properly set when
* the search continues on the previous or next line. */
rev_start = reverse ? fileptr->data + (openfile->current_x - 1) :
fileptr->data + (openfile->current_x + 1);
/* Look for either of the two characters in bracket_set. rev_start
* can be 1 character before the start or after the end of the line.
* In either case, just act as though no match is found. */
while (TRUE) {
found = ((rev_start > fileptr->data && *(rev_start - 1) ==
'\0') || rev_start < fileptr->data) ? NULL : (reverse ?
revstrpbrk(fileptr->data, bracket_set, rev_start) :
strpbrk(rev_start, bracket_set));
/* We've found a potential match. */
if (found != NULL)
break;
if (reverse) {
fileptr = fileptr->prev;
current_y_find--;
} else {
fileptr = fileptr->next;
current_y_find++;
}
/* Start or end of buffer reached, so get out. */
if (fileptr == NULL)
return FALSE;
rev_start = fileptr->data;
if (reverse)
rev_start += strlen(fileptr->data);
}
/* We found an instance. */
current_x_find = found - fileptr->data;
/* We've definitely found something. */
openfile->current = fileptr;
openfile->current_x = current_x_find;
openfile->placewewant = xplustabs();
openfile->current_y = current_y_find;
return TRUE;
}
/* Search for a match to the bracket at the current cursor position, if
* there is one. */
void do_find_bracket(void)
{
const char *bracket_pat = "()<>[]{}", *pos;
char regex_pat[] = "[ ]", ch, wanted_ch;
filestruct *current_save;
size_t current_x_save, pww_save;
bool regexp_set = ISSET(USE_REGEXP);
bool backwards_search_set = ISSET(BACKWARDS_SEARCH);
int count = 1;
assert(strlen(bracket_pat) % 2 == 0);
const char *bracket_list = "()<>[]{}";
/* The list of brackets we can find matches to. */
const char *pos;
/* The location in bracket_list of the bracket at the current
* cursor position. */
char ch;
/* The bracket at the current cursor position. */
char wanted_ch;
/* The bracket complementing the bracket at the current cursor
* position. */
char bracket_set[3];
/* The pair of characters in ch and wanted_ch. */
size_t count = 1;
/* The initial bracket count. */
bool reverse;
/* The direction we search. */
assert(strlen(bracket_list) % 2 == 0);
ch = openfile->current->data[openfile->current_x];
if (ch == '\0' || (pos = strchr(bracket_pat, ch)) == NULL) {
if (ch == '\0' || (pos = strchr(bracket_list, ch)) == NULL) {
statusbar(_("Not a bracket"));
return;
}
......@@ -1059,40 +1122,17 @@ void do_find_bracket(void)
current_x_save = openfile->current_x;
pww_save = openfile->placewewant;
/* Turn regular expression searches on. */
SET(USE_REGEXP);
/* If we're on an opening bracket, we want to search forwards for a
* closing bracket, and if we're on a closing bracket, we want to
* search backwards for an opening bracket.
*
* We replace the spaces in regex_pat with the opening and closing
* brackets, and then do a regular expression search using it. We
* have to put the closing bracket first when we do the latter,
* since "[[]]" won't work properly, but "[][]" will. */
if ((pos - bracket_pat) % 2 == 0) {
wanted_ch = *(pos + 1);
regex_pat[1] = wanted_ch;
regex_pat[2] = ch;
UNSET(BACKWARDS_SEARCH);
} else {
wanted_ch = *(pos - 1);
regex_pat[1] = ch;
regex_pat[2] = wanted_ch;
SET(BACKWARDS_SEARCH);
}
/* Compile the regular expression in regex_pat. */
regexp_init(regex_pat);
/* The regular expression in regex_pat should always be valid. */
assert(regexp_compiled);
findnextstr_wrap_reset();
* search backwards for an opening bracket. */
reverse = ((pos - bracket_list) % 2 != 0);
wanted_ch = reverse ? *(pos - 1) : *(pos + 1);
bracket_set[0] = ch;
bracket_set[1] = wanted_ch;
bracket_set[2] = '\0';
while (TRUE) {
if (findnextstr(FALSE, FALSE, FALSE, openfile->current,
openfile->current_x, regex_pat, NULL)) {
if (find_bracket_match(reverse, bracket_set)) {
/* If we found an identical bracket, increment count. If we
* found a complementary bracket, decrement it. */
count += (openfile->current->data[openfile->current_x] ==
......@@ -1114,21 +1154,7 @@ void do_find_bracket(void)
break;
}
}
/* Decompile the regular expression in regex_pat. */
regexp_cleanup();
/* Restore search/replace direction. */
if (backwards_search_set)
SET(BACKWARDS_SEARCH);
else
UNSET(BACKWARDS_SEARCH);
/* Restore regular expression usage setting. */
if (!regexp_set)
UNSET(USE_REGEXP);
}
#endif /* HAVE_REGEX_H */
#ifdef ENABLE_NANORC
/* Indicate whether any of the history lists have changed. */
......
......@@ -1589,9 +1589,9 @@ bool do_int_spell_fix(const char *word)
openfile->current_x = (size_t)-1;
openfile->placewewant = 0;
/* Find the first whole-word occurrence of word. */
/* Find the first whole occurrence of word. */
findnextstr_wrap_reset();
while (findnextstr(TRUE, TRUE, FALSE, openfile->fileage, 0, word,
while (findnextstr(TRUE, FALSE, openfile->fileage, 0, word,
&match_len)) {
if (is_whole_word(openfile->current_x, openfile->current->data,
word)) {
......@@ -1617,8 +1617,8 @@ bool do_int_spell_fix(const char *word)
if (!canceled && strcmp(word, answer) != 0) {
openfile->current_x--;
do_replace_loop(word, openfile->current,
&openfile->current_x, TRUE, &canceled);
do_replace_loop(TRUE, &canceled, openfile->current,
&openfile->current_x, word);
}
break;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment