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/>.
10 /** @file stringfilter.cpp Searching and filtering using a stringterm. */
13 #include "string_func.h"
14 #include "strings_func.h"
15 #include "stringfilter_type.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
= '"';
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
);
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
;
46 len
= Utf8Decode(&c
, pos
);
48 if (c
== 0 || (state
== STATE_WORD
&& IsWhitespace(c
))) {
54 state
= STATE_WHITESPACE
;
55 if (c
!= 0) continue; else break;
58 if (state
== STATE_WHITESPACE
) {
60 if (IsWhitespace(c
)) continue;
64 if (c
== STATE_QUOTE1
|| c
== STATE_QUOTE2
) {
69 } else if (state
== STATE_WORD
) {
78 word
= this->word_index
.Append();
83 memcpy(dest
, pos
, len
);
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
) {
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
) {
116 if ((match_case
? strstr(str
, it
->start
) : strcasestr(str
, it
->start
)) != NULL
) {
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
));