stringfilter.cpp

Go to the documentation of this file.
00001 /* $Id$ */
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 }