(svn r27950) -Merge: Documentation updates from 1.7 branch
[openttd.git] / src / stringfilter.cpp
blob6045c19ef493a2c3ba66a410d1e1bfe8dba1d1ba
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file stringfilter.cpp Searching and filtering using a stringterm. */
12 #include "stdafx.h"
13 #include "string_func.h"
14 #include "strings_func.h"
15 #include "stringfilter_type.h"
16 #include "gfx_func.h"
18 #include "safeguards.h"
20 static const WChar STATE_WHITESPACE = ' ';
21 static const WChar STATE_WORD = 'w';
22 static const WChar STATE_QUOTE1 = '\'';
23 static const WChar STATE_QUOTE2 = '"';
25 /**
26 * Set the term to filter on.
27 * @param str Filter term
29 void StringFilter::SetFilterTerm(const char *str)
31 this->word_index.Reset();
32 this->word_matches = 0;
33 free(this->filter_buffer);
35 assert(str != NULL);
37 char *dest = MallocT<char>(strlen(str) + 1);
38 this->filter_buffer = dest;
40 WChar state = STATE_WHITESPACE;
41 const char *pos = str;
42 WordState *word = NULL;
43 size_t len;
44 for (;; pos += len) {
45 WChar c;
46 len = Utf8Decode(&c, pos);
48 if (c == 0 || (state == STATE_WORD && IsWhitespace(c))) {
49 /* Finish word */
50 if (word != NULL) {
51 *(dest++) = '\0';
52 word = NULL;
54 state = STATE_WHITESPACE;
55 if (c != 0) continue; else break;
58 if (state == STATE_WHITESPACE) {
59 /* Skip whitespace */
60 if (IsWhitespace(c)) continue;
61 state = STATE_WORD;
64 if (c == STATE_QUOTE1 || c == STATE_QUOTE2) {
65 if (state == c) {
66 /* Stop quoting */
67 state = STATE_WORD;
68 continue;
69 } else if (state == STATE_WORD) {
70 /* Start quoting */
71 state = c;
72 continue;
76 /* Add to word */
77 if (word == NULL) {
78 word = this->word_index.Append();
79 word->start = dest;
80 word->match = false;
83 memcpy(dest, pos, len);
84 dest += len;
88 /**
89 * Reset the matching state to process a new item.
91 void StringFilter::ResetState()
93 this->word_matches = 0;
94 const WordState *end = this->word_index.End();
95 for (WordState *it = this->word_index.Begin(); it != end; ++it) {
96 it->match = false;
101 * Pass another text line from the current item to the filter.
103 * You can call this multiple times for a single item, if the filter shall apply to multiple things.
104 * Before processing the next item you have to call ResetState().
106 * @param str Another line from the item.
108 void StringFilter::AddLine(const char *str)
110 if (str == NULL) return;
112 bool match_case = this->case_sensitive != NULL && *this->case_sensitive;
113 const WordState *end = this->word_index.End();
114 for (WordState *it = this->word_index.Begin(); it != end; ++it) {
115 if (!it->match) {
116 if ((match_case ? strstr(str, it->start) : strcasestr(str, it->start)) != NULL) {
117 it->match = true;
118 this->word_matches++;
125 * Pass another text line from the current item to the filter.
127 * You can call this multiple times for a single item, if the filter shall apply to multiple things.
128 * Before processing the next item you have to call ResetState().
130 * @param str Another line from the item.
132 void StringFilter::AddLine(StringID str)
134 char buffer[DRAW_STRING_BUFFER];
135 GetString(buffer, str, lastof(buffer));
136 AddLine(buffer);