Remove SIGTYPE_LAST_NOPBS
[openttd/fttd.git] / src / stringfilter.cpp
blobe021c57b57097953672888a024946bab4c0f9cb3
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 static const WChar STATE_WHITESPACE = ' ';
19 static const WChar STATE_WORD = 'w';
20 static const WChar STATE_QUOTE1 = '\'';
21 static const WChar STATE_QUOTE2 = '"';
23 /**
24 * Set the term to filter on.
25 * @param str Filter term
27 void StringFilter::SetFilterTerm(const char *str)
29 this->word_index.Reset();
30 this->word_matches = 0;
31 free(this->filter_buffer);
33 assert(str != NULL);
35 char *dest = (char *)malloc(strlen(str) + 1);
36 this->filter_buffer = dest;
38 WChar state = STATE_WHITESPACE;
39 const char *pos = str;
40 WordState *word = NULL;
41 size_t len;
42 for (;; pos += len) {
43 WChar c;
44 len = Utf8Decode(&c, pos);
46 if (c == 0 || (state == STATE_WORD && IsWhitespace(c))) {
47 /* Finish word */
48 if (word != NULL) {
49 *(dest++) = '\0';
50 word = NULL;
52 state = STATE_WHITESPACE;
53 if (c != 0) continue; else break;
56 if (state == STATE_WHITESPACE) {
57 /* Skip whitespace */
58 if (IsWhitespace(c)) continue;
59 state = STATE_WORD;
62 if (c == STATE_QUOTE1 || c == STATE_QUOTE2) {
63 if (state == c) {
64 /* Stop quoting */
65 state = STATE_WORD;
66 continue;
67 } else if (state == STATE_WORD) {
68 /* Start quoting */
69 state = c;
70 continue;
74 /* Add to word */
75 if (word == NULL) {
76 word = this->word_index.Append();
77 word->start = dest;
78 word->match = false;
81 memcpy(dest, pos, len);
82 dest += len;
86 /**
87 * Reset the matching state to process a new item.
89 void StringFilter::ResetState()
91 this->word_matches = 0;
92 const WordState *end = this->word_index.End();
93 for (WordState *it = this->word_index.Begin(); it != end; ++it) {
94 it->match = false;
98 /**
99 * Pass another text line from the current item to the filter.
101 * You can call this multiple times for a single item, if the filter shall apply to multiple things.
102 * Before processing the next item you have to call ResetState().
104 * @param str Another line from the item.
106 void StringFilter::AddLine(const char *str)
108 if (str == NULL) return;
110 bool match_case = this->case_sensitive != NULL && *this->case_sensitive;
111 const WordState *end = this->word_index.End();
112 for (WordState *it = this->word_index.Begin(); it != end; ++it) {
113 if (!it->match) {
114 if ((match_case ? strstr(str, it->start) : strcasestr(str, it->start)) != NULL) {
115 it->match = true;
116 this->word_matches++;
123 * Pass another text line from the current item to the filter.
125 * You can call this multiple times for a single item, if the filter shall apply to multiple things.
126 * Before processing the next item you have to call ResetState().
128 * @param str Another line from the item.
130 void StringFilter::AddLine(StringID str)
132 char buffer[DRAW_STRING_BUFFER];
133 GetString(buffer, str, lastof(buffer));
134 AddLine(buffer);