diff options
| author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-12-04 17:29:01 +0100 |
|---|---|---|
| committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-12-04 22:07:08 +0100 |
| commit | d8a316514c03d85b771a9dce4a8a51b875d955b3 (patch) | |
| tree | 8966c29db767a155848f6d90f76771ce5b9de32e /search.cpp | |
| parent | b120616b6da52e951097f69ad267de06081d218a (diff) | |
autoconf preparation: move everything into src/ subdir
Diffstat (limited to 'search.cpp')
| -rw-r--r-- | search.cpp | 571 |
1 files changed, 0 insertions, 571 deletions
diff --git a/search.cpp b/search.cpp deleted file mode 100644 index 701f36c..0000000 --- a/search.cpp +++ /dev/null @@ -1,571 +0,0 @@ -#include <string.h> - -#include <glib.h> -#include <glib/gprintf.h> - -#include "sciteco.h" -#include "expressions.h" -#include "undo.h" -#include "qregisters.h" -#include "ring.h" -#include "parser.h" -#include "search.h" - -namespace States { - StateSearch search; - StateSearchAll searchall; - StateSearchKill searchkill; - StateSearchDelete searchdelete; - StateReplace replace; - StateReplace_insert replace_insert; - StateReplaceDefault replacedefault; - StateReplaceDefault_insert replacedefault_insert; -} - -/* - * Command states - */ - -void -StateSearch::initial(void) throw (Error) -{ - gint64 v1, v2; - - undo.push_var(parameters); - - parameters.dot = interface.ssm(SCI_GETCURRENTPOS); - - v2 = expressions.pop_num_calc(); - if (expressions.args()) { - /* TODO: optional count argument? */ - v1 = expressions.pop_num_calc(); - if (v1 <= v2) { - parameters.count = 1; - parameters.from = (gint)v1; - parameters.to = (gint)v2; - } else { - parameters.count = -1; - parameters.from = (gint)v2; - parameters.to = (gint)v1; - } - - if (!Validate::pos(parameters.from) || - !Validate::pos(parameters.to)) - throw RangeError("S"); - } else { - parameters.count = (gint)v2; - if (v2 >= 0) { - parameters.from = parameters.dot; - parameters.to = interface.ssm(SCI_GETLENGTH); - } else { - parameters.from = 0; - parameters.to = parameters.dot; - } - } - - parameters.from_buffer = ring.current; - parameters.to_buffer = NULL; -} - -static inline const gchar * -regexp_escape_chr(gchar chr) -{ - static gchar escaped[] = {'\\', '\0', '\0'}; - - escaped[1] = chr; - return g_ascii_isalnum(chr) ? escaped + 1 : escaped; -} - -gchar * -StateSearch::class2regexp(MatchState &state, const gchar *&pattern, - bool escape_default) -{ - while (*pattern) { - QRegister *reg; - gchar *temp, *temp2; - - switch (state) { - case STATE_START: - switch (*pattern) { - case CTL_KEY('S'): - return g_strdup("[:^alnum:]"); - case CTL_KEY('E'): - state = STATE_CTL_E; - break; - default: - temp = escape_default - ? g_strdup(regexp_escape_chr(*pattern)) - : NULL; - return temp; - } - break; - - case STATE_CTL_E: - switch (g_ascii_toupper(*pattern)) { - case 'A': - state = STATE_START; - return g_strdup("[:alpha:]"); - /* same as <CTRL/S> */ - case 'B': - state = STATE_START; - return g_strdup("[:^alnum:]"); - case 'C': - state = STATE_START; - return g_strdup("[:alnum:].$"); - case 'D': - state = STATE_START; - return g_strdup("[:digit:]"); - case 'G': - state = STATE_ANYQ; - break; - case 'L': - state = STATE_START; - return g_strdup("\r\n\v\f"); - case 'R': - state = STATE_START; - return g_strdup("[:alnum:]"); - case 'V': - state = STATE_START; - return g_strdup("[:lower:]"); - case 'W': - state = STATE_START; - return g_strdup("[:upper:]"); - default: - return NULL; - } - break; - - case STATE_ANYQ: - /* FIXME: Q-Register spec might get more complicated */ - reg = QRegisters::globals[g_ascii_toupper(*pattern)]; - if (!reg) - return NULL; - - temp = reg->get_string(); - temp2 = g_regex_escape_string(temp, -1); - g_free(temp); - state = STATE_START; - return temp2; - - default: - return NULL; - } - - pattern++; - } - - return NULL; -} - -gchar * -StateSearch::pattern2regexp(const gchar *&pattern, - bool single_expr) -{ - MatchState state = STATE_START; - gchar *re = NULL; - - while (*pattern) { - gchar *new_re, *temp; - - temp = class2regexp(state, pattern); - if (temp) { - new_re = g_strconcat(re ? : "", "[", temp, "]", NULL); - g_free(temp); - g_free(re); - re = new_re; - - goto next; - } - if (!*pattern) - break; - - switch (state) { - case STATE_START: - switch (*pattern) { - case CTL_KEY('X'): String::append(re, "."); break; - case CTL_KEY('N'): state = STATE_NOT; break; - default: - String::append(re, regexp_escape_chr(*pattern)); - } - break; - - case STATE_NOT: - state = STATE_START; - temp = class2regexp(state, pattern, true); - if (!temp) - goto error; - new_re = g_strconcat(re ? : "", "[^", temp, "]", NULL); - g_free(temp); - g_free(re); - re = new_re; - g_assert(state == STATE_START); - break; - - case STATE_CTL_E: - state = STATE_START; - switch (g_ascii_toupper(*pattern)) { - case 'M': state = STATE_MANY; break; - case 'S': String::append(re, "\\s+"); break; - /* same as <CTRL/X> */ - case 'X': String::append(re, "."); break; - /* TODO: ASCII octal code!? */ - case '[': - String::append(re, "("); - state = STATE_ALT; - break; - default: - goto error; - } - break; - - case STATE_MANY: - temp = pattern2regexp(pattern, true); - if (!temp) - goto error; - new_re = g_strconcat(re ? : "", "(", temp, ")+", NULL); - g_free(temp); - g_free(re); - re = new_re; - state = STATE_START; - break; - - case STATE_ALT: - switch (*pattern) { - case ',': - String::append(re, "|"); - break; - case ']': - String::append(re, ")"); - state = STATE_START; - break; - default: - temp = pattern2regexp(pattern, true); - if (!temp) - goto error; - String::append(re, temp); - g_free(temp); - } - break; - - default: - /* shouldn't happen */ - g_assert(true); - } - -next: - if (single_expr && state == STATE_START) - return re; - - pattern++; - } - - if (state == STATE_ALT) - String::append(re, ")"); - - return re; - -error: - g_free(re); - return NULL; -} - -void -StateSearch::do_search(GRegex *re, gint from, gint to, gint &count) -{ - GMatchInfo *info; - const gchar *buffer; - - gint matched_from = -1, matched_to = -1; - - buffer = (const gchar *)interface.ssm(SCI_GETCHARACTERPOINTER); - g_regex_match_full(re, buffer, (gssize)to, from, - (GRegexMatchFlags)0, &info, NULL); - - if (count >= 0) { - while (g_match_info_matches(info) && --count) - g_match_info_next(info, NULL); - - if (!count) - /* successful */ - g_match_info_fetch_pos(info, 0, - &matched_from, &matched_to); - } else { - /* only keep the last `count' matches, in a circular stack */ - struct Range { - gint from, to; - }; - Range *matched = new Range[-count]; - gint matched_total = 0, i = 0; - - while (g_match_info_matches(info)) { - g_match_info_fetch_pos(info, 0, - &matched[i].from, - &matched[i].to); - - g_match_info_next(info, NULL); - i = ++matched_total % -count; - } - - count = MIN(count + matched_total, 0); - if (!count) { - /* successful, i points to stack bottom */ - matched_from = matched[i].from; - matched_to = matched[i].to; - } - - delete matched; - } - - g_match_info_free(info); - - if (matched_from >= 0 && matched_to >= 0) - /* match success */ - interface.ssm(SCI_SETSEL, matched_from, matched_to); -} - -void -StateSearch::process(const gchar *str, - gint new_chars __attribute__((unused))) throw (Error) -{ - static const gint flags = G_REGEX_CASELESS | G_REGEX_MULTILINE | - G_REGEX_DOTALL | G_REGEX_RAW; - - QRegister *search_reg = QRegisters::globals["_"]; - - gchar *re_pattern; - GRegex *re; - - gint count = parameters.count; - - undo.push_msg(SCI_SETSEL, - interface.ssm(SCI_GETANCHOR), - interface.ssm(SCI_GETCURRENTPOS)); - - search_reg->undo_set_integer(); - search_reg->set_integer(FAILURE); - - /* NOTE: pattern2regexp() modifies str pointer */ - re_pattern = pattern2regexp(str); -#ifdef DEBUG - g_printf("REGEXP: %s\n", re_pattern); -#endif - if (!re_pattern) - goto failure; - re = g_regex_new(re_pattern, (GRegexCompileFlags)flags, - (GRegexMatchFlags)0, NULL); - g_free(re_pattern); - if (!re) - goto failure; - - if (ring.current != parameters.from_buffer) { - ring.undo_edit(); - parameters.from_buffer->edit(); - } - - do_search(re, parameters.from, parameters.to, count); - - if (parameters.to_buffer && count) { - Buffer *buffer = parameters.from_buffer; - - if (ring.current == buffer) - ring.undo_edit(); - - if (count > 0) { - do { - buffer = buffer->next() ? : ring.first(); - buffer->edit(); - - if (buffer == parameters.to_buffer) { - do_search(re, 0, parameters.dot, count); - break; - } - - do_search(re, 0, interface.ssm(SCI_GETLENGTH), - count); - } while (count); - } else /* count < 0 */ { - do { - buffer = buffer->prev() ? : ring.last(); - buffer->edit(); - - if (buffer == parameters.to_buffer) { - do_search(re, parameters.dot, - interface.ssm(SCI_GETLENGTH), - count); - break; - } - - do_search(re, 0, interface.ssm(SCI_GETLENGTH), - count); - } while (count); - } - - ring.current = buffer; - } - - search_reg->set_integer(TECO_BOOL(!count)); - - g_regex_unref(re); - - if (!count) - return; - -failure: - interface.ssm(SCI_GOTOPOS, parameters.dot); -} - -State * -StateSearch::done(const gchar *str) throw (Error) -{ - BEGIN_EXEC(&States::start); - - QRegister *search_reg = QRegisters::globals["_"]; - - if (*str) { - /* workaround: preserve selection (also on rubout) */ - gint anchor = interface.ssm(SCI_GETANCHOR); - undo.push_msg(SCI_SETANCHOR, anchor); - - search_reg->undo_set_string(); - search_reg->set_string(str); - - interface.ssm(SCI_SETANCHOR, anchor); - } else { - gchar *search_str = search_reg->get_string(); - process(search_str, 0 /* unused */); - g_free(search_str); - } - - if (eval_colon()) - expressions.push(search_reg->get_integer()); - else if (IS_FAILURE(search_reg->get_integer()) && - !expressions.find_op(Expressions::OP_LOOP) /* not in loop */) - interface.msg(Interface::MSG_ERROR, "Search string not found!"); - - return &States::start; -} - -void -StateSearchAll::initial(void) throw (Error) -{ - gint64 v1, v2; - - undo.push_var(parameters); - - parameters.dot = interface.ssm(SCI_GETCURRENTPOS); - - v2 = expressions.pop_num_calc(); - if (expressions.args()) { - /* TODO: optional count argument? */ - v1 = expressions.pop_num_calc(); - if (v1 <= v2) { - parameters.count = 1; - parameters.from_buffer = ring.find(v1); - parameters.to_buffer = ring.find(v2); - } else { - parameters.count = -1; - parameters.from_buffer = ring.find(v2); - parameters.to_buffer = ring.find(v1); - } - - if (!parameters.from_buffer || !parameters.to_buffer) - throw RangeError("N"); - } else { - parameters.count = (gint)v2; - /* NOTE: on Q-Registers, behave like "S" */ - parameters.from_buffer = parameters.to_buffer = ring.current; - } - - if (parameters.count >= 0) { - parameters.from = parameters.dot; - parameters.to = interface.ssm(SCI_GETLENGTH); - } else { - parameters.from = 0; - parameters.to = parameters.dot; - } -} - -State * -StateSearchAll::done(const gchar *str) throw (Error) -{ - BEGIN_EXEC(&States::start); - - StateSearch::done(str); - QRegisters::hook(QRegisters::HOOK_EDIT); - - return &States::start; -} - -State * -StateSearchKill::done(const gchar *str) throw (Error) -{ - gint anchor; - - BEGIN_EXEC(&States::start); - - StateSearch::done(str); - - undo.push_msg(SCI_GOTOPOS, interface.ssm(SCI_GETCURRENTPOS)); - anchor = interface.ssm(SCI_GETANCHOR); - interface.ssm(SCI_GOTOPOS, anchor); - - interface.ssm(SCI_BEGINUNDOACTION); - interface.ssm(SCI_DELETERANGE, - parameters.dot, anchor - parameters.dot); - interface.ssm(SCI_ENDUNDOACTION); - ring.dirtify(); - - undo.push_msg(SCI_UNDO); - - return &States::start; -} - -State * -StateSearchDelete::done(const gchar *str) throw (Error) -{ - BEGIN_EXEC(&States::start); - - StateSearch::done(str); - - interface.ssm(SCI_BEGINUNDOACTION); - interface.ssm(SCI_REPLACESEL, 0, (sptr_t)""); - interface.ssm(SCI_ENDUNDOACTION); - ring.dirtify(); - - undo.push_msg(SCI_UNDO); - - return &States::start; -} - -State * -StateReplace::done(const gchar *str) throw (Error) -{ - StateSearchDelete::done(str); - return &States::replace_insert; -} - -State * -StateReplaceDefault::done(const gchar *str) throw (Error) -{ - StateSearchDelete::done(str); - return &States::replacedefault_insert; -} - -State * -StateReplaceDefault_insert::done(const gchar *str) throw (Error) -{ - BEGIN_EXEC(&States::start); - - QRegister *replace_reg = QRegisters::globals["-"]; - - if (*str) { - replace_reg->undo_set_string(); - replace_reg->set_string(str); - } else { - gchar *replace_str = replace_reg->get_string(); - StateInsert::process(replace_str, strlen(replace_str)); - g_free(replace_str); - } - - return &States::start; -} |
