# 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 }