00001 /* $Id: stringfilter.cpp 24632 2012-10-27 15:26:17Z frosch $ */ 00002 00003 /* 00004 * This file is part of OpenTTD. 00005 * 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. 00006 * 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. 00007 * 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/>. 00008 */ 00009 00012 #include "stdafx.h" 00013 #include "string_func.h" 00014 #include "strings_func.h" 00015 #include "stringfilter_type.h" 00016 #include "gfx_func.h" 00017 00018 static const WChar STATE_WHITESPACE = ' '; 00019 static const WChar STATE_WORD = 'w'; 00020 static const WChar STATE_QUOTE1 = '\''; 00021 static const WChar STATE_QUOTE2 = '"'; 00022 00027 void StringFilter::SetFilterTerm(const char *str) 00028 { 00029 this->word_index.Reset(); 00030 this->word_matches = 0; 00031 free(this->filter_buffer); 00032 00033 assert(str != NULL); 00034 00035 char *dest = (char *)malloc(strlen(str) + 1); 00036 this->filter_buffer = dest; 00037 00038 WChar state = STATE_WHITESPACE; 00039 const char *pos = str; 00040 WordState *word = NULL; 00041 size_t len; 00042 for (;; pos += len) { 00043 WChar c; 00044 len = Utf8Decode(&c, pos); 00045 00046 if (c == 0 || (state == STATE_WORD && IsWhitespace(c))) { 00047 /* Finish word */ 00048 if (word != NULL) { 00049 *(dest++) = '\0'; 00050 word = NULL; 00051 } 00052 state = STATE_WHITESPACE; 00053 if (c != 0) continue; else break; 00054 } 00055 00056 if (state == STATE_WHITESPACE) { 00057 /* Skip whitespace */ 00058 if (IsWhitespace(c)) continue; 00059 state = STATE_WORD; 00060 } 00061 00062 if (c == STATE_QUOTE1 || c == STATE_QUOTE2) { 00063 if (state == c) { 00064 /* Stop quoting */ 00065 state = STATE_WORD; 00066 continue; 00067 } else if (state == STATE_WORD) { 00068 /* Start quoting */ 00069 state = c; 00070 continue; 00071 } 00072 } 00073 00074 /* Add to word */ 00075 if (word == NULL) { 00076 word = this->word_index.Append(); 00077 word->start = dest; 00078 word->match = false; 00079 } 00080 00081 memcpy(dest, pos, len); 00082 dest += len; 00083 } 00084 } 00085 00089 void StringFilter::ResetState() 00090 { 00091 this->word_matches = 0; 00092 const WordState *end = this->word_index.End(); 00093 for (WordState *it = this->word_index.Begin(); it != end; ++it) { 00094 it->match = false; 00095 } 00096 } 00097 00106 void StringFilter::AddLine(const char *str) 00107 { 00108 if (str == NULL) return; 00109 00110 bool match_case = this->case_sensitive != NULL && *this->case_sensitive; 00111 const WordState *end = this->word_index.End(); 00112 for (WordState *it = this->word_index.Begin(); it != end; ++it) { 00113 if (!it->match) { 00114 if ((match_case ? strstr(str, it->start) : strcasestr(str, it->start)) != NULL) { 00115 it->match = true; 00116 this->word_matches++; 00117 } 00118 } 00119 } 00120 } 00121 00130 void StringFilter::AddLine(StringID str) 00131 { 00132 char buffer[DRAW_STRING_BUFFER]; 00133 GetString(buffer, str, lastof(buffer)); 00134 AddLine(buffer); 00135 }