diff options
author | frosch <frosch@openttd.org> | 2012-06-09 19:54:16 +0000 |
---|---|---|
committer | frosch <frosch@openttd.org> | 2012-06-09 19:54:16 +0000 |
commit | 03046f614f4fb8c88d1a8ee05e0caee2bde887bc (patch) | |
tree | 8ee6fcb2c3c316b89bb884e10a52e42136674b94 /src/stringfilter.cpp | |
parent | db709aff32244d45e613d53dbf9f0ffbc3aa5cb1 (diff) | |
download | openttd-03046f614f4fb8c88d1a8ee05e0caee2bde887bc.tar.xz |
(svn r24337) -Feature: Allow filtering for multiple words (separated by whitespace resp. quoted) in the sign list, content- and NewGRF-guis.
Diffstat (limited to 'src/stringfilter.cpp')
-rw-r--r-- | src/stringfilter.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/stringfilter.cpp b/src/stringfilter.cpp new file mode 100644 index 000000000..616fd9854 --- /dev/null +++ b/src/stringfilter.cpp @@ -0,0 +1,120 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD 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 Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file stringfilter.cpp Searching and filtering using a stringterm. */ + +#include "stdafx.h" +#include "string_func.h" +#include "stringfilter_type.h" + +static const WChar STATE_WHITESPACE = ' '; +static const WChar STATE_WORD = 'w'; +static const WChar STATE_QUOTE1 = '\''; +static const WChar STATE_QUOTE2 = '"'; + +/** + * Set the term to filter on. + * @param str Filter term + */ +void StringFilter::SetFilterTerm(const char *str) +{ + this->word_index.Reset(); + this->word_matches = 0; + free(this->filter_buffer); + + assert(str != NULL); + + char *dest = (char *)malloc(strlen(str) + 1); + this->filter_buffer = dest; + + WChar state = STATE_WHITESPACE; + const char *pos = str; + WordState *word = NULL; + size_t len; + for (;; pos += len) { + WChar c; + len = Utf8Decode(&c, pos); + + if (c == 0 || (state == STATE_WORD && IsWhitespace(c))) { + /* Finish word */ + if (word != NULL) { + *(dest++) = '\0'; + word = NULL; + } + state = STATE_WHITESPACE; + if (c != 0) continue; else break; + } + + if (state == STATE_WHITESPACE) { + /* Skip whitespace */ + if (IsWhitespace(c)) continue; + state = STATE_WORD; + } + + if (c == STATE_QUOTE1 || c == STATE_QUOTE2) { + if (state == c) { + /* Stop quoting */ + state = STATE_WORD; + continue; + } else if (state == STATE_WORD) { + /* Start quoting */ + state = c; + continue; + } + } + + /* Add to word */ + if (word == NULL) { + word = this->word_index.Append(); + word->start = dest; + word->match = false; + } + + memcpy(dest, pos, len); + dest += len; + } +} + +/** + * Reset the matching state to process a new item. + */ +void StringFilter::ResetState() +{ + this->word_matches = 0; + const WordState *end = this->word_index.End(); + for (WordState *it = this->word_index.Begin(); it != end; ++it) { + it->match = false; + } +} + +/** + * Pass another text line from the current item to the filter. + * + * You can call this multiple times for a single item, if the filter shall apply to multiple things. + * Before processing the next item you have to call ResetState(). + * + * @param str Another line from the item. + */ +void StringFilter::AddLine(const char *str) +{ + if (str == NULL) return; + + bool match_case = this->case_sensitive != NULL && *this->case_sensitive; + const WordState *end = this->word_index.End(); + for (WordState *it = this->word_index.Begin(); it != end; ++it) { + if (!it->match) { + if ((match_case ? strstr(str, it->start) : strcasestr(str, it->start)) != NULL) { + it->match = true; + this->word_matches++; + } + } + } +} + + |