~mhall119/ubuntu/precise/geany/add_keywords

« back to all changes in this revision

Viewing changes to scintilla/lexlib/WordList.cxx

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2011-12-10 07:43:26 UTC
  • mfrom: (3.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20111210074326-s8yqbew5i20h33tf
Tags: 0.21-1ubuntu1
* Merge from Debian Unstable, remaining changes:
  - debian/patches/20_use_evince_viewer.patch:
     + use evince as viewer for pdf and dvi files
  - debian/patches/20_use_x_terminal_emulator.patch:
     + use x-terminal-emulator as terminal
  - debian/control
     + Add breaks on geany-plugins-common << 0.20
* Also fixes bugs:
  - Filter for MATLAB/Octave files filters everythign (LP: 885505)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Scintilla source code edit control
 
2
/** @file KeyWords.cxx
 
3
 ** Colourise for particular languages.
 
4
 **/
 
5
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
 
6
// The License.txt file describes the conditions under which this software may be distributed.
 
7
 
 
8
#include <stdlib.h>
 
9
#include <string.h>
 
10
#include <ctype.h>
 
11
#include <stdio.h>
 
12
#include <stdarg.h>
 
13
 
 
14
#include "WordList.h"
 
15
 
 
16
#ifdef SCI_NAMESPACE
 
17
using namespace Scintilla;
 
18
#endif
 
19
 
 
20
/**
 
21
 * Creates an array that points into each word in the string and puts \0 terminators
 
22
 * after each word.
 
23
 */
 
24
static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = false) {
 
25
        int prev = '\n';
 
26
        int words = 0;
 
27
        // For rapid determination of whether a character is a separator, build
 
28
        // a look up table.
 
29
        bool wordSeparator[256];
 
30
        for (int i=0; i<256; i++) {
 
31
                wordSeparator[i] = false;
 
32
        }
 
33
        wordSeparator['\r'] = true;
 
34
        wordSeparator['\n'] = true;
 
35
        if (!onlyLineEnds) {
 
36
                wordSeparator[' '] = true;
 
37
                wordSeparator['\t'] = true;
 
38
        }
 
39
        for (int j = 0; wordlist[j]; j++) {
 
40
                int curr = static_cast<unsigned char>(wordlist[j]);
 
41
                if (!wordSeparator[curr] && wordSeparator[prev])
 
42
                        words++;
 
43
                prev = curr;
 
44
        }
 
45
        char **keywords = new char *[words + 1];
 
46
        if (keywords) {
 
47
                words = 0;
 
48
                prev = '\0';
 
49
                size_t slen = strlen(wordlist);
 
50
                for (size_t k = 0; k < slen; k++) {
 
51
                        if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
 
52
                                if (!prev) {
 
53
                                        keywords[words] = &wordlist[k];
 
54
                                        words++;
 
55
                                }
 
56
                        } else {
 
57
                                wordlist[k] = '\0';
 
58
                        }
 
59
                        prev = wordlist[k];
 
60
                }
 
61
                keywords[words] = &wordlist[slen];
 
62
                *len = words;
 
63
        } else {
 
64
                *len = 0;
 
65
        }
 
66
        return keywords;
 
67
}
 
68
 
 
69
bool WordList::operator!=(const WordList &other) const {
 
70
        if (len != other.len)
 
71
                return true;
 
72
        for (int i=0; i<len; i++) {
 
73
                if (strcmp(words[i], other.words[i]) != 0)
 
74
                        return true;
 
75
        }
 
76
        return false;
 
77
}
 
78
 
 
79
void WordList::Clear() {
 
80
        if (words) {
 
81
                delete []list;
 
82
                delete []words;
 
83
        }
 
84
        words = 0;
 
85
        list = 0;
 
86
        len = 0;
 
87
}
 
88
 
 
89
extern "C" int cmpString(const void *a1, const void *a2) {
 
90
        // Can't work out the correct incantation to use modern casts here
 
91
        return strcmp(*(char **)(a1), *(char **)(a2));
 
92
}
 
93
 
 
94
static void SortWordList(char **words, unsigned int len) {
 
95
        qsort(reinterpret_cast<void *>(words), len, sizeof(*words),
 
96
              cmpString);
 
97
}
 
98
 
 
99
void WordList::Set(const char *s) {
 
100
        Clear();
 
101
        list = new char[strlen(s) + 1];
 
102
        strcpy(list, s);
 
103
        words = ArrayFromWordList(list, &len, onlyLineEnds);
 
104
        SortWordList(words, len);
 
105
        for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
 
106
                starts[k] = -1;
 
107
        for (int l = len - 1; l >= 0; l--) {
 
108
                unsigned char indexChar = words[l][0];
 
109
                starts[indexChar] = l;
 
110
        }
 
111
}
 
112
 
 
113
/** Check whether a string is in the list.
 
114
 * List elements are either exact matches or prefixes.
 
115
 * Prefix elements start with '^' and match all strings that start with the rest of the element
 
116
 * so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'.
 
117
 */
 
118
bool WordList::InList(const char *s) const {
 
119
        if (0 == words)
 
120
                return false;
 
121
        unsigned char firstChar = s[0];
 
122
        int j = starts[firstChar];
 
123
        if (j >= 0) {
 
124
                while ((unsigned char)words[j][0] == firstChar) {
 
125
                        if (s[1] == words[j][1]) {
 
126
                                const char *a = words[j] + 1;
 
127
                                const char *b = s + 1;
 
128
                                while (*a && *a == *b) {
 
129
                                        a++;
 
130
                                        b++;
 
131
                                }
 
132
                                if (!*a && !*b)
 
133
                                        return true;
 
134
                        }
 
135
                        j++;
 
136
                }
 
137
        }
 
138
        j = starts['^'];
 
139
        if (j >= 0) {
 
140
                while (words[j][0] == '^') {
 
141
                        const char *a = words[j] + 1;
 
142
                        const char *b = s;
 
143
                        while (*a && *a == *b) {
 
144
                                a++;
 
145
                                b++;
 
146
                        }
 
147
                        if (!*a)
 
148
                                return true;
 
149
                        j++;
 
150
                }
 
151
        }
 
152
        return false;
 
153
}
 
154
 
 
155
/** similar to InList, but word s can be a substring of keyword.
 
156
 * eg. the keyword define is defined as def~ine. This means the word must start
 
157
 * with def to be a keyword, but also defi, defin and define are valid.
 
158
 * The marker is ~ in this case.
 
159
 */
 
160
bool WordList::InListAbbreviated(const char *s, const char marker) const {
 
161
        if (0 == words)
 
162
                return false;
 
163
        unsigned char firstChar = s[0];
 
164
        int j = starts[firstChar];
 
165
        if (j >= 0) {
 
166
                while (words[j][0] == firstChar) {
 
167
                        bool isSubword = false;
 
168
                        int start = 1;
 
169
                        if (words[j][1] == marker) {
 
170
                                isSubword = true;
 
171
                                start++;
 
172
                        }
 
173
                        if (s[1] == words[j][start]) {
 
174
                                const char *a = words[j] + start;
 
175
                                const char *b = s + 1;
 
176
                                while (*a && *a == *b) {
 
177
                                        a++;
 
178
                                        if (*a == marker) {
 
179
                                                isSubword = true;
 
180
                                                a++;
 
181
                                        }
 
182
                                        b++;
 
183
                                }
 
184
                                if ((!*a || isSubword) && !*b)
 
185
                                        return true;
 
186
                        }
 
187
                        j++;
 
188
                }
 
189
        }
 
190
        j = starts['^'];
 
191
        if (j >= 0) {
 
192
                while (words[j][0] == '^') {
 
193
                        const char *a = words[j] + 1;
 
194
                        const char *b = s;
 
195
                        while (*a && *a == *b) {
 
196
                                a++;
 
197
                                b++;
 
198
                        }
 
199
                        if (!*a)
 
200
                                return true;
 
201
                        j++;
 
202
                }
 
203
        }
 
204
        return false;
 
205
}