1 // Scintilla source code edit control
3 ** Colourise for particular languages.
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.
16 #include "StringCopy.h"
20 using namespace Scintilla
;
24 * Creates an array that points into each word in the string and puts \0 terminators
27 static char **ArrayFromWordList(char *wordlist
, int *len
, bool onlyLineEnds
= false) {
30 // For rapid determination of whether a character is a separator, build
32 bool wordSeparator
[256];
33 for (int i
=0; i
<256; i
++) {
34 wordSeparator
[i
] = false;
36 wordSeparator
[static_cast<unsigned int>('\r')] = true;
37 wordSeparator
[static_cast<unsigned int>('\n')] = true;
39 wordSeparator
[static_cast<unsigned int>(' ')] = true;
40 wordSeparator
[static_cast<unsigned int>('\t')] = true;
42 for (int j
= 0; wordlist
[j
]; j
++) {
43 int curr
= static_cast<unsigned char>(wordlist
[j
]);
44 if (!wordSeparator
[curr
] && wordSeparator
[prev
])
48 char **keywords
= new char *[words
+ 1];
50 const size_t slen
= strlen(wordlist
);
53 for (size_t k
= 0; k
< slen
; k
++) {
54 if (!wordSeparator
[static_cast<unsigned char>(wordlist
[k
])]) {
56 keywords
[wordsStore
] = &wordlist
[k
];
65 keywords
[wordsStore
] = &wordlist
[slen
];
70 WordList::WordList(bool onlyLineEnds_
) :
71 words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_
) {
72 // Prevent warnings by static analyzers about uninitialized starts.
76 WordList::~WordList() {
80 WordList::operator bool() const {
81 return len
? true : false;
84 bool WordList::operator!=(const WordList
&other
) const {
87 for (int i
=0; i
<len
; i
++) {
88 if (strcmp(words
[i
], other
.words
[i
]) != 0)
94 int WordList::Length() const {
98 void WordList::Clear() {
110 static bool cmpWords(const char *a
, const char *b
) {
111 return strcmp(a
, b
) < 0;
116 static int cmpWords(const void *a
, const void *b
) {
117 return strcmp(*static_cast<const char * const *>(a
), *static_cast<const char * const *>(b
));
120 static void SortWordList(char **words
, unsigned int len
) {
121 qsort(reinterpret_cast<void *>(words
), len
, sizeof(*words
), cmpWords
);
126 void WordList::Set(const char *s
) {
128 const size_t lenS
= strlen(s
) + 1;
129 list
= new char[lenS
];
130 memcpy(list
, s
, lenS
);
131 words
= ArrayFromWordList(list
, &len
, onlyLineEnds
);
133 std::sort(words
, words
+ len
, cmpWords
);
135 SortWordList(words
, len
);
137 for (unsigned int k
= 0; k
< ELEMENTS(starts
); k
++)
139 for (int l
= len
- 1; l
>= 0; l
--) {
140 unsigned char indexChar
= words
[l
][0];
141 starts
[indexChar
] = l
;
145 /** Check whether a string is in the list.
146 * List elements are either exact matches or prefixes.
147 * Prefix elements start with '^' and match all strings that start with the rest of the element
148 * so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'.
150 bool WordList::InList(const char *s
) const {
153 unsigned char firstChar
= s
[0];
154 int j
= starts
[firstChar
];
156 while (static_cast<unsigned char>(words
[j
][0]) == firstChar
) {
157 if (s
[1] == words
[j
][1]) {
158 const char *a
= words
[j
] + 1;
159 const char *b
= s
+ 1;
160 while (*a
&& *a
== *b
) {
170 j
= starts
[static_cast<unsigned int>('^')];
172 while (words
[j
][0] == '^') {
173 const char *a
= words
[j
] + 1;
175 while (*a
&& *a
== *b
) {
187 /** similar to InList, but word s can be a substring of keyword.
188 * eg. the keyword define is defined as def~ine. This means the word must start
189 * with def to be a keyword, but also defi, defin and define are valid.
190 * The marker is ~ in this case.
192 bool WordList::InListAbbreviated(const char *s
, const char marker
) const {
195 unsigned char firstChar
= s
[0];
196 int j
= starts
[firstChar
];
198 while (static_cast<unsigned char>(words
[j
][0]) == firstChar
) {
199 bool isSubword
= false;
201 if (words
[j
][1] == marker
) {
205 if (s
[1] == words
[j
][start
]) {
206 const char *a
= words
[j
] + start
;
207 const char *b
= s
+ 1;
208 while (*a
&& *a
== *b
) {
216 if ((!*a
|| isSubword
) && !*b
)
222 j
= starts
[static_cast<unsigned int>('^')];
224 while (words
[j
][0] == '^') {
225 const char *a
= words
[j
] + 1;
227 while (*a
&& *a
== *b
) {
239 const char *WordList::WordAt(int n
) const {