Highlight.cpp

Full CSS3 Highlight supprot (Without unnecessary comments) - Zbigniew Rebacz, 04/10/2014 09:54 PM

Download (30.1 KB)

 
1
#include "CodeEditor.h"
2

    
3
NAMESPACE_UPP
4

    
5
#define LTIMING(x)  // RTIMING(x)
6

    
7
bool cmps(const wchar *q, const char *s, int& n) {
8
        const wchar *t = q;
9
        while(*q)
10
                if(*q++ != *s++)
11
                        return false;
12
        n += int(q - t);
13
        return *q == *s;
14
}
15

    
16
bool IsUpperString(const char *q)
17
{
18
        while(*q)
19
        {
20
                if(*q != '_' && (*q < '0' || *q > '9') && !IsUpper(*q))
21
                        return false;
22
                q++;
23
    }
24
        return true;
25
}
26

    
27
#define UVSALERT      Color(255, 240, 240)
28
#define UVSREPINSERT  Color(240, 240, 255)
29
#define UVSYOUINSERT  Color(240, 255, 240)
30
#define UVSDELETE     Color(240, 240, 240)
31

    
32
Color GetUvsHighlight(const wchar *text, int& n) {
33
        n = 0;
34
        if(text[0] != '$' || text[1] != 'u' || text[2] != 'v' || text[3] != 's' || text[4] != ':' || text[5] != ' ')
35
                return Null;
36
        n = 6;
37
        const wchar *q = text + 6;
38
        if(cmps(q, "PENDING CONFLICT", n))
39
                return Null;
40
        if(cmps(q, "YOUR DELETE (REPOSITORY DELETE)", n))
41
                return UVSALERT;
42
        if(cmps(q, "END YOUR DELETE (REPOSITORY DELETE)", n))
43
                return UVSDELETE;
44
        if(cmps(q, "YOUR INSERT (REPOSITORY DELETE)", n))
45
                return UVSALERT;
46
        if(cmps(q, "END YOUR INSERT (REPOSITORY DELETE)", n))
47
                return UVSDELETE;
48
        if(cmps(q, "REPOSITORY DELETE (YOUR DELETE)", n))
49
                return UVSALERT;
50
        if(cmps(q, "END REPOSITORY DELETE (YOUR DELETE)", n))
51
                return UVSDELETE;
52
        if(cmps(q, "REPOSITORY INSERT (YOUR DELETE)", n))
53
                return UVSALERT;
54
        if(cmps(q, "END REPOSITORY INSERT (YOUR DELETE)", n))
55
                return UVSDELETE;
56
        if(cmps(q, "YOUR INSERT", n))
57
                return UVSYOUINSERT;
58
        if(cmps(q, "END YOUR INSERT", n))
59
                return Null;
60
        if(cmps(q, "YOUR DELETE", n))
61
                return UVSDELETE;
62
        if(cmps(q, "END YOUR DELETE", n))
63
                return Null;
64
        if(cmps(q, "REPOSITORY DELETE", n))
65
                return UVSDELETE;
66
        if(cmps(q, "END REPOSITORY DELETE", n))
67
                return Null;
68
        if(cmps(q, "REPOSITORY INSERT", n))
69
                return UVSREPINSERT;
70
        if(cmps(q, "END REPOSITORY INSERT", n))
71
                return Null;
72
        n = 0;
73
        return Null;
74
}
75

    
76
struct CodeEditor::HlSt {
77
        Vector<LineEdit::Highlight>& v;
78
        LineEdit::Highlight          def;
79
        int                          pos;
80

    
81
        void Set(int pos, int count, const HlStyle& ink);
82
        void SetFont(int pos, int count, const HlStyle& f);
83
        void SetPaper(int pos, int count, Color paper);
84
        void SetInk(int pos, int count, Color ink);
85
        void Put(int count, const HlStyle& ink)           { Set(pos, count, ink); pos += count; }
86
        void Put(const HlStyle& ink)                      { Put(1, ink); }
87
        void Put(const HlStyle& ink, word flags)          { Put(1, ink); v[pos - 1].flags = flags; }
88

    
89
        HlSt(Vector<LineEdit::Highlight>& v) : v(v) {
90
                pos = 0;
91
                def = v[0];
92
                def.chr = ' ';
93
                v.Top().chr = ' ';
94
        }
95

    
96
        ~HlSt() {
97
                for(int i = 0; i < v.GetCount(); i++)
98
                        if(v[i].chr == '_') {
99
                                v[i].font.NoBold();
100
                                v[i].font.NoItalic();
101
                        }
102
        }
103
};
104

    
105
void CodeEditor::HlSt::Set(int pos, int count, const HlStyle& ink)
106
{
107
        if(pos + count > v.GetCount())
108
                v.At(pos + count - 1, def);
109
        while(count-- > 0) {
110
                LineEdit::Highlight& x = v[pos++];
111
                x.ink = ink.color;
112
                if(ink.bold)
113
                        x.font.Bold();
114
                if(ink.italic)
115
                        x.font.Italic();
116
                if(ink.underline)
117
                        x.font.Underline();
118
        }
119
}
120

    
121
void CodeEditor::HlSt::SetFont(int pos, int count, const HlStyle& f)
122
{
123
        if(pos + count > v.GetCount())
124
                v.At(pos + count - 1, def);
125
        while(count-- > 0) {
126
                LineEdit::Highlight& x = v[pos++];
127
                if(f.bold)
128
                        x.font.Bold();
129
                if(f.italic)
130
                        x.font.Italic();
131
                if(f.underline)
132
                        x.font.Underline();
133
        }
134
}
135

    
136
void CodeEditor::HlSt::SetPaper(int pos, int count, Color paper)
137
{
138
        if(pos + count > v.GetCount())
139
                v.At(pos + count - 1, def);
140
        while(count-- > 0)
141
                v[pos++].paper = paper;
142
}
143

    
144
void CodeEditor::HlSt::SetInk(int pos, int count, Color ink)
145
{
146
        if(pos + count > v.GetCount())
147
                v.At(pos + count - 1, def);
148
        while(count-- > 0)
149
                v[pos++].ink = ink;
150
}
151

    
152
const wchar *CodeEditor::HlString(HlSt& hls, const wchar *p)
153
{
154
        hls.Put(hl_style[INK_CONST_STRING]);
155
        const wchar delim = *p;
156
        p++;
157
        while(*p && *p != delim)
158
                if(*p == '\\') {
159
                        const wchar *t = p++;
160
                        if(*p == 'x' || *p == 'X') {
161
                                p++;
162
                                if(IsXDigit(*p))
163
                                        p++;
164
                                if(IsXDigit(*p))
165
                                        p++;
166
                                hls.Put(int(p - t), hl_style[INK_CONST_STRINGOP]);
167
                        }
168
                        else
169
                        if(*p >= '0' && *p <= '7') {
170
                                p++;
171
                                if(*p >= '0' && *p <= '7') p++;
172
                                if(*p >= '0' && *p <= '7') p++;
173
                                hls.Put(int(p - t), hl_style[INK_CONST_STRINGOP]);
174
                        }
175
                        else {
176
                                hls.Put(hl_style[INK_CONST_STRINGOP]);
177
                                if(*p) {
178
                                        hls.Put(hl_style[INK_CONST_STRINGOP]);
179
                                        p++;
180
                                }
181
                        }
182
                }
183
                else
184
                if(*p == '%')
185
                        if(p[1] == '%') {
186
                                hls.Put(2, hl_style[INK_CONST_STRING]);
187
                                p += 2;
188
                        }
189
                        else {
190
                                const wchar *t = p++;
191
                                while(!IsAlpha(*p) && *p && *p != '`' && *p != '\"' && *p != '\'' && *p != '\\')
192
                                        p++;
193
                                while(IsAlpha(*p) && *p)
194
                                        p++;
195
                                hls.Put(int(p - t), hl_style[INK_CONST_STRINGOP]);
196
                        }
197
                else {
198
                        hls.Put(hl_style[INK_CONST_STRING]);
199
                        p++;
200
                }
201
        if(*p == delim)        {
202
                hls.Put(hl_style[INK_CONST_STRING]);
203
                p++;
204
        }
205
        return p;
206
}
207

    
208
Color CodeEditor::BlockColor(int level)
209
{
210
        if(hilite_scope == 1)
211
                return  GetHlStyle(level & 1 ? PAPER_BLOCK1 : PAPER_NORMAL).color;
212
        if(hilite_scope == 2) {
213
                int q = level % 5;
214
                return  GetHlStyle(q ? PAPER_BLOCK1 + q - 1 : PAPER_NORMAL).color;
215
        }
216
        return GetHlStyle(PAPER_NORMAL).color;
217
}
218

    
219
void CodeEditor::Bracket(int pos, HlSt& hls)
220
{
221
        if(pos == highlight_bracket_pos0 && hilite_bracket
222
           || pos == highlight_bracket_pos && (hilite_bracket == 1 || hilite_bracket == 2 && bracket_flash)) {
223
                        HlStyle& h = hl_style[pos == highlight_bracket_pos0 ? PAPER_BRACKET0 : PAPER_BRACKET];
224
                        hls.SetPaper(hls.pos, 1, h.color);
225
                        hls.SetFont(hls.pos, 1, h);
226
        }
227
}
228

    
229
Vector <Index<String> > CodeEditor::keyword;
230
Vector <Index<String> > CodeEditor::name;
231
Index<String> CodeEditor::kw_upp;
232
int CodeEditor::kw_macros;
233
int CodeEditor::kw_logs;
234
int CodeEditor::kw_sql_base;
235
int CodeEditor::kw_sql_func;
236

    
237
const Index<String>& CodeEditor::CppKeywords()
238
{
239
        return keyword[0];
240
}
241

    
242
int CodeEditor::InitUpp(const char **q)
243
{
244
        while(*q)
245
                kw_upp.Add(*q++);
246
        return kw_upp.GetCount();
247
}
248

    
249
void CodeEditor::InitKeywords()
250
{
251
        static const char *cpp[] = {
252
                "namespace", "asm", "__asm", "else", "struct",
253
                "enum", "switch", "auto", "__except", "template",
254
                "explicit", "this",
255
                "bool", "extern", "mutable", "thread",
256
                "break", "false", "throw",
257
                "case", "__fastcall", "true",
258
                "catch", "__finally", "new", "try",
259
                "__cdecl", "float", "__try",
260
                "char", "wchar_t", "for", "operator", "typedef",
261
                "class", "friend", "private", "typeid",
262
                "const", "goto", "protected", "typename",
263
                "const_cast", "if", "public", "union",
264
                "continue", "inline", "register", "unsigned",
265
                "__declspec", "__inline", "reinterpret_cast", "using",
266
                "using", "default", "int", "return",
267
                "delete", "__int8", "short", "__uuidof",
268
                "dllexport", "__int16", "signed", "virtual",
269
                "dllimport", "__int32", "sizeof", "void",
270
                "do", "__int64", "static", "volatile",
271
                "double", "__leave", "static_cast",
272
                "dynamic_cast", "long", "__stdcall", "while",
273
                "force_inline",
274
                "and", "bitor", "or", "xor", 
275
                "compl", "bitand", "and_eq", "or_eq",
276
                "xor_eq", "not", "not_eq",
277
                "char16_t", "char32_t", "constexpr", "decltype",
278
                "noexcept", "nullptr", "static_assert",
279
                "override", "final",
280
                NULL
281
        };
282
        static const char *cs[] = {
283
                "abstract", "event", "new", "struct",
284
                "as", "explicit", "null", "switch",
285
                "base", "extern", "object", "this",
286
                "bool", "false", "operator", "throw",
287
                "break", "finally", "out", "true",
288
                "byte", "fixed", "override", "try",
289
                "case", "float", "params", "typeof",
290
                "catch", "for", "private", "uint",
291
                "char", "foreach", "protected", "ulong",
292
                "checked", "goto", "public", "unchecked",
293
                "class", "if", "readonly", "unsafe",
294
                "const", "implicit", "ref", "ushort",
295
                "continue", "in", "return", "using",
296
                "decimal", "int", "sbyte", "virtual",
297
                "default", "interface", "sealed", "volatile",
298
                "delegate", "internal", "short", "void",
299
                "do", "is", "sizeof", "while",
300
                "double", "lock", "stackalloc",
301
                "else", "long", "static",
302
                "enum", "namespace", "string",
303
                "await", "async", "throws", "awaits",
304
                NULL
305
        };
306
        static const char *upp[] = {
307
                "byte", "word", "dword", "__countof", "pick_", "wchar", "NULL", "Null",
308
                "int8", "uint8", "int16", "uint16", "int32", "uint32", "int64", "uint64", "qword",
309
                "INTERLOCKED_", "INTERLOCKED", "ONCELOCK", "ONCELOCK_", "INITBLOCK", "EXITBLOCK",
310
                "rval_", "rval_default",
311
                NULL
312
        };
313
        static const char *usc[] = {
314
                "void", "self", "if", "else", "while", "do", "case",
315
                "default", "break", "return", "switch", "operator", "for",
316
                "fn", "group", "ctrl", "subctrl", "template", "enum_property",
317
                "raw", "int", "double", "String", "bool",
318
                "Text", "Qtf", "Doc", "Font", "Color", "macro",
319
                NULL
320
        };
321
        static const char *usclib[] = {
322
                "Color", "Point", "Size", "Rect", "RectC",
323
                "StdFont", "Arial", "Roman", "Courier", "GetImageSize",
324
                "GetTextSize", "print", "Black", "Gray", "LtGray",
325
                "WhiteGray", "White", "Red", "Green", "Brown", "Blue",
326
                "Magenta", "Cyan", "Yellow", "LtRed", "LtGreen", "LtYellow",
327
                "LtBlue", "LtMagenta", "LtCyan", "SBlack", "SGray", "SLtGray",
328
                "SWhiteGray", "SWhite", "SRed", "SGreen", "SBrown", "SBlue",
329
                "SMagenta", "SCyan", "SYellow", "SLtRed", "SLtGreen", "SLtYellow",
330
                "SLtBlue", "SLtMagenta", "SLtCyan", "IntNull", "DblNullLim",
331
                "DrawRect", "DrawText", "DrawSmartText", "DrawImage", "is_number",
332
                "GetSmartTextSize", "GetQtfHeight", "DrawQtf",
333
                "is_array", "is_map", "is_void", "int", "to_string", "count",
334
                "len", "remove", "insert", "mid", "keys", "values", "exists",
335
                "erase", "rand", "OpenFileOut", "OpenFileAppend", "OpenFileIn",
336
                "GetMinSize", "GetStdSize",
337
                NULL
338
        };
339
        static const char *java[] = {
340
                "abstract", "assert", "boolean", "break", "byte", "case",
341
                "catch", "char", "class", "const", "continue",
342
                "default", "do", "double", "else", "enum", "extends",
343
                "false", "final", "finally", "float", "for",
344
                "goto", "if", "implements", "import", "instanceof",
345
                "int", "interface", "long", "native", "new",
346
                "null", "package", "private", "protected", "public",
347
                "return", "short", "static", "strictfp", "super", "switch",
348
                "synchronized", "this", "throw", "throws", "transient",
349
                "true", "try", "void", "volatile", "while",
350
                NULL
351
        };
352
        static const char *javascript[] = {
353
                "break", "continue", "do", "for", "import", "new", "this", "void",
354
                "case", "default", "else", "function", "in", "return", "typeof", "while",
355
                "comment", "delete", "export", "if", "label", "switch", "var", "with",
356
                "catch", "enum", "throw", "class", "extends", "try", "const", "finally",
357
                "debugger", "super", "true", "false", "undefined",
358
                NULL
359
        };
360
        static const char *css[] = {
361
                "azimuth", "background-attachment", "background-color", "background-image", "background-position",
362
                "background-repeat", "background", "border-collapse", "border-color", "border-spacing", "border-style",
363
                "border-top", "border-right", "border-bottom", "border-left", "border-top-color", "border-right-color",
364
                "border-bottom-color", "border-left-color", "border-top-style", "border-right-style", "border-bottom-style",
365
                "border-left-style", "border-top-width", "border-right-width", "border-bottom-width", "border-left-width",
366
                "border-width", "border", "bottom", "caption-side", "clear", "clip", "color", "content", "counter-increment",
367
                "counter-reset", "cue-after", "cue-before", "cue", "cursor", "direction", "display", "elevation", "empty-cells",
368
                "float", "font-family", "font-size", "font-style", "font-variant", "font-weight", "font", "height", "left",
369
                "letter-spacing", "line-height", "list-style-image", "list-style-position", "list-style-type", "list-style",
370
                "margin-right", "margin-left", "margin-top", "margin-bottom", "margin", "max-height", "max-width", "min-height",
371
                "min-width", "orphans", "outline-color", "outline-style", "outline-width", "outline", "overflow", "padding-top",
372
                "padding-right", "padding-bottom", "padding-left", "padding", "page-break-after", "page-break-before",
373
                "page-break-inside", "pause-after", "pause-before", "pause", "pitch-range", "pitch", "play-during", "position",
374
                "quotes", "richness", "right", "speak-header", "speak-numeral", "speak-punctuation", "speak", "speech-rate",
375
                "stress", "table-layout", "text-align", "text-decoration", "text-indent", "text-transform", "top",
376
                "unicode-bidi", "vertical-align", "visibility", "voice-family", "volume", "white-space", "widows", "width",
377
                "word-spacing", "z-index",
378
                // CSS3
379
                "opacity",
380
                "background-clip", "background-origin", "background-size", "border-bottom-left-radius", "border-bottom-right-radius",
381
                "border-image", "border-image-outset", "border-image-repeat", "border-image-slice", "border-image-source",
382
                "border-image-width", "border-radius", "border-top-left-radius", "border-top-right-radius", "box-decoration-break", 
383
                "box-shadow",
384
                "overflow-x", "overflow-y",
385
                "align-content", "align-items", "align-self", "flex", "flex-basis", "flex-direction", "flex-flow", "flex-grow",
386
                "flex-shrink", "flex-wrap", "justify-content", "order",
387
                "hanging-punctuation", "hyphens", "line-break", "overflow-wrap", "tab-size", "text-align-last", "text-justify",
388
                "word-break", "word-wrap",
389
                "text-decoration-color", "text-decoration-line", "text-decoration-style", "text-shadow", "text-underline-position",
390
                "animation", "animation-delay", "animation-direction", "animation-duration", "animation-fill-mode",
391
                "animation-iteration-count", "animation-name", "animation-timing-function", "animation-play-state",
392
                "backface-visibility", "perspective", "perspective-origin", "transform", "transform-origin", "transform-style",
393
                "transition", "transition-property", "transition-duration", "transition-timing-function", "transition-delay",
394
                "box-sizing", "nav-down", "nav-index", "nav-left", "nav-right", "nav-up", "outline-offset", "resize", "text-overflow",
395
                "break-after", "break-before", "break-inside", "column-count", "column-fill", "column-gap", "column-rule",
396
                "column-rule-color", "column-rule-style", "column-rule-width", "column-span", "column-width", "columns",
397
                "marks",
398
                "filter",
399
                "image-orientation", "image-rendering", "image-resolution", "object-fit", "object-position",
400
                "mask", "mask-type",
401
                "mark", "mark-after", "mark-before", "phonemes", "rest", "rest-after", "rest-before", "voice-balance",
402
                "voice-duration", "voice-pitch", "voice-pitch-range", "voice-rate", "voice-stress", "voice-volume",
403
                "marquee-direction", "marquee-play-count", "marquee-speed", "marquee-style",
404
                NULL
405
        };
406
        static const char *cssn[] = {
407
                "em", "px", "pt",
408
                "left-side", "far-left", "left", "center-left", "center", "center-right", "right", "far-right", "right-side",
409
                "behind", "leftwards", "rightwards", "inherit", "scroll", "fixed", "transparent", "none", "top", "bottom",
410
                "repeat", "repeat-x", "repeat-y", "no-repeat", "background-color", "background-image", "background-repeat",
411
                "background-attachment", "background-position", "collapse", "separate", "border-top-color", "auto", "both",
412
                "normal", "attr", "open-quote", "close-quote", "no-open-quote", "no-close-quote", "cue-before", "cue-after",
413
                "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize",
414
                "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress", "ltr", "rtl", "inline", "block",
415
                "list-item", "inline-block", "table", "inline-table", "table-row-group", "table-header-group",
416
                "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption",
417
                "below", "level", "above", "higher", "lower", "show", "hide", "italic", "oblique", "small-caps", "bold",
418
                "bolder", "lighter", "font-style",
419
                "font-variant", "font-weight", "font-size", "line-height", "font-family", "caption", "icon", "menu",
420
                "message-box", "small-caption", "status-bar", "inside", "outside", "disc", "circle", "square", "decimal",
421
                "decimal-leading-zero", "lower-roman", "upper-roman", "lower-greek", "lower-latin", "upper-latin", "armenian",
422
                "georgian", "lower-alpha", "upper-alpha", "list-style-type", "list-style-position", "list-style-image",
423
                "invert", "outline-color", "outline-style", "outline-width", "visible", "hidden", "always", "avoid",
424
                "x-low", "low", "medium", "high", "x-high", "mix", "static", "relative", "absolute", "once", "digits",
425
                "continuous", "code", "spell-out", "x-slow", "slow", "fast", "x-fast", "faster", "slower", "justify",
426
                "underline", "overline", "line-through", "blink", "capitalize", "uppercase", "lowercase", "embed",
427
                "bidi-override", "baseline", "sub", "super", "text-top", "middle", "text-bottom", "silent", "x-soft", "soft",
428
                "loud", "x-loud", "pre", "nowrap", "pre-wrap", "pre-line", "solid",
429
                NULL
430
        };
431
        static const char *upp_macros[] = {
432
                "CLASSNAME", "THISBACK", "THISBACK1", "THISBACK2", "THISBACK3", "THISBACK4",
433
                "PTEBACK", "PTEBACK1", "PTEBACK2",  "PTEBACK3",  "PTEBACK4", 
434
                "QUOTE", "XASSERT", "NEVER", "XNEVER", "CHECK", "XCHECK", "ASSERT", "ASSERT_",
435
                "NAMESPACE_UPP", "END_UPP_NAMESPACE", "NEVER_", "SKYLARK", "RPC_METHOD", "RPC_GMETHOD",
436
                NULL
437
        };
438
        static const char *upp_logs[] = {
439
                "LOG", "LOGF", "DUMP", "DUMPC", "DUMPCC", "DUMPCCC", "DUMPM",
440
                "LLOG", "LLOGF", "LDUMP", "LDUMPC", "LDUMPCC", "LDUMPCCC", "LDUMPM",
441
                "DLOG", "DLOGF", "DDUMP", "DDUMPC", "DDUMPCC", "DDUMPCCC", "DDUMPM",
442
                "RLOG", "RLOGF", "RDUMP", "RDUMPC", "RDUMPCC", "RDUMPCCC", "RDUMPM",
443
                "LOGBEGIN", "LOGEND", "LOGBLOCK", "LOGHEXDUMP", "LOGSRCPOS", 
444
                "RLOGBEGIN", "RLOGEND", "RLOGBLOCK", "RLOGHEXDUMP", "RLOGSRCPOS", "RQUOTE",
445
                "RTIMING", "TIMING", "LTIMING", "DTIMING",
446
                "LOGHEX", "DUMPHEX", "DLOGHEX", "DDUMPHEX", "RLOGHEX", "RDUMPHEX", "LLOGHEX", "LDUMPHEX",
447
                "DEBUGCODE",                        
448
                NULL
449
        };
450
        static const char *sql_base[] = {
451
                "Select", "Update", "Insert", "Delete", "From",
452
                "Join", "InnerJoin", "LeftJoin", "RightJoin", "FullJoin", "OuterJoin",
453
                "Where", "On", "OrderBy", "GroupBy",
454
                "Of", "As", "StartWith", "ConnectBy", "Having", "ForUpdate", "NoWait", "Limit",
455
                "Offset", "Hint", "SQL",
456
                NULL
457
        };
458
        static const char *sql_func[] = {
459
                "Decode", "Distinct", "All", "SqlAll", "Count", "Descending",
460
                "SqlMax", "SqlMin", "SqlSum", "Avg", "Stddev", "Variance",
461
                "Greatest", "Least", "ConvertCharset", "ConvertAscii",
462
                "Upper", "Lower", "Substr", "Instr", "Wild", "SqlDate", "AddMonths", "LastDay",
463
                "MonthsBetween", "NextDay", "SqlNvl", "Prior", "NextVal", "CurrVal", "SqlArg",
464
                NULL
465
        };
466
        static const char *sql_bool[] = {
467
                "SqlIsNull", "NotNull", "Like", "LikeUpperAscii", "NotLike", "Between",
468
                "NotBetween", "In", "NotIn", "Exists", "NotExists",
469
                NULL
470
        };
471
        static const char *tfile[] = {
472
                "T_",
473
                NULL,
474
        };
475
        static const char *tlng[] = {
476
                "enUS", "enGB", "enAU", "enCA", "enNZ", "enIE", "enZA", "enJM", "enCB", "enBZ",
477
                "enTT", "bgBG", "csCZ", "daDK", "deDE", "deCH", "deAT", "deLU", "deLI", "elGR",
478
                "esES", "esMX", "esES", "esGT", "esCR", "esPA", "esDO", "esVE", "esCO", "esPE",
479
                "esAR", "esEC", "esCL", "esUY", "esPY", "esBO", "esSV", "esHN", "esNI", "esPR",
480
                "fiFI", "frFR", "frBE", "frCA", "frCH", "frLU", "huHU", "isIS", "itIT", "itCH",
481
                "nlNL", "nlBE", "noNO", "noNO", "plPL", "ptBR", "ptPT", "roRO", "ruRU", "hrHR",
482
                "srSP", "srSP", "skSK", "svSE", "svFI", "trTR", "slSI", "afZA", "sqAL", "euES",
483
                "beBY", "caES", "etEE", "foFO", "idID", "lvLV", "ltLT", "ukUA", "zhCN", "zhTW",
484
                "koKR", "jaJP",
485
                NULL
486
        };
487
        static const char *lay[] = {
488
                "LAYOUT", "ITEM", "UNTYPED", "END_LAYOUT",
489
                NULL
490
        };
491
        static const char *sch[] = {
492
                "BIT", "BIT_ARRAY", "BIT_", "BIT_ARRAY_",
493
                "BOOL", "BOOL_ARRAY", "BOOL_", "BOOL_ARRAY_",
494
                "INT", "INT_ARRAY", "INT_", "INT_ARRAY_",
495
                "DOUBLE", "DOUBLE_ARRAY", "DOUBLE_", "DOUBLE_ARRAY_",
496
                "DATE", "DATE_ARRAY", "DATE_", "DATE_ARRAY_",
497
                "DATETIME", "DATETIME_ARRAY", "DATETIME_", "DATETIME_ARRAY_",
498
                "TIME", "TIME_ARRAY", "TIME_", "TIME_ARRAY_",
499
                "STRING", "STRING_ARRAY", "STRING_", "STRING_ARRAY_",
500
                "LONG", "LONG_", "LONGRAW", "LONGRAW_", "BLOB", "BLOB_", "CLOB", "CLOB_",
501
                "AUTO_INCREMENT", "KEY", "NOT_NULL", "TIMESTAMP", "COMMENT", "SEQUENCE", "SEQUENCE_",
502
                "PRIMARY_KEY", "INDEX", "PARTIAL_INDEX", "UNIQUE", "SQLDEFAULT", "REFERENCES", "REFERENCES_",
503
                "REFERENCES_CASCADE", "REFERENCES_CASCADE_", "DUAL_PRIMARY_KEY", "DUAL_UNIQUE",
504
                "UNIQUE_LIST", "SQLCHECK",
505
                "TABLE", "TABLE_", "END_TABLE", "TABLE_I", "TABLE_I_", "TABLE_II",
506
                "TABLE_II_", "TABLE_III", "TABLE_III_", "VAR", "VAR_",
507
                "COLUMN", "COLUMN_ARRAY", "ATTRIBUTE", "INLINE_ATTRIBUTE",
508
                "TYPE", "TYPE_I", "TYPE_II", "TYPE_III", "END_TYPE",
509
                "TYPE_", "TYPE_I_", "TYPE_II_", "TYPE_III_", "SERIAL", "ISERIAL",
510
                "INDEX_LIST",
511
                NULL
512
        };
513
        static const char *sql[] = {
514
                "ABORT", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", "ATTACH",
515
                "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", "CASCADE", "CASE", "CHECK",
516
                "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS",
517
                "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT",
518
                "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", "END", "EXCEPT",
519
                "EXCLUSIVE", "EXISTS", "FOREIGN", "FROM", "FULL", "GROUP", "HAVING",
520
                "IN", "INDEX", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO",
521
                "IS", "ISNULL", "JOIN", "KEY", "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NOT",
522
                "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PRIMARY", "RAISE",
523
                "REFERENCES", "REPLACE", "RESTRICT", "UPDATE", "SET", "WHERE", "NEW", "OLD", "TRIGGER",
524
                "SELECT", "TABLE",
525
                NULL
526
        };
527
        static const char *empty[] = {
528
                NULL
529
        };
530
        static const char *javascriptn[] = {
531
                "alert", "eval", "toString", "valueOf", "length",
532
                NULL
533
        };
534

    
535
        LoadSyntax(cpp, upp); // Order here is important, must be the same as enum
536
        LoadSyntax(usc, usclib);
537
        LoadSyntax(java, empty);
538
        LoadSyntax(tfile, tlng);
539
        LoadSyntax(usc, usclib);
540
        LoadSyntax(lay, empty);
541
        LoadSyntax(sch, empty);
542
        LoadSyntax(sql, empty);
543
        LoadSyntax(cs, empty);
544
        LoadSyntax(javascript, javascriptn);
545
        LoadSyntax(css, cssn);
546
        LoadSyntax(empty, empty);
547

    
548
        kw_macros = InitUpp(upp_macros);
549
        kw_logs = InitUpp(upp_logs);
550
        kw_sql_base = InitUpp(sql_base);
551
        kw_sql_func = InitUpp(sql_func);
552
        InitUpp(sql_bool);
553
}
554

    
555
int CodeEditor::LoadSyntax(const char *keywords[], const char *names[])        // Changed
556
{
557
        Index <String> &key = keyword.Add()        ;
558
        while(*keywords)
559
                key.Add(*keywords++);
560
        Index <String> &nam = name.Add();
561
        while(*names)
562
                nam.Add(*names++);        
563
        return keyword.GetCount() - 1;
564
}
565

    
566
void CodeEditor::HighlightLine(int line, Vector<LineEdit::Highlight>& hl, int pos)
567
{
568
        LTIMING("HighlightLine");
569
        if(highlight < 0 || highlight >= keyword.GetCount())
570
                return;
571
        WString text = GetWLine(line);
572
        SyntaxState ss = ScanSyntax(line);
573
        ss.Grounding(text.Begin(), text.End());
574
        SyntaxState sm = ScanSyntax(line + 1);
575
        HlSt hls(hl);
576
        const wchar *p = text;
577
        const wchar *e = text.End();
578
        int uvsn;
579
        GetUvsHighlight(text, uvsn);
580
        if(uvsn) {
581
                hls.SetInk(0, text.GetLength() + 1, Yellow);
582
                hls.SetPaper(0, text.GetLength() + 1, Gray);
583
                hls.pos += uvsn;
584
                p += uvsn;
585
                return;
586
        }
587
        else
588
        if(highlight == HIGHLIGHT_CALC) {
589
                if(line == GetLineCount() - 1 || *p == '$')
590
                        hls.SetPaper(0, text.GetLength() + 1, hl_style[PAPER_BLOCK1].color);
591
        }
592
        else
593
                hls.SetPaper(0, text.GetLength() + 1,
594
                             Nvl(ss.uvscolor, sm.macro ? hl_style[PAPER_MACRO].color : hl_style[PAPER_NORMAL].color));
595
        int block_level = ss.bid.GetCount() - 1;
596
        String cppid;
597
        if(IsNull(ss.uvscolor) && !uvsn && !ss.comment && highlight != HIGHLIGHT_CALC) {
598
                if(!sm.macro) {
599
                        int i = 0, bid = 0, pos = 0, tabsz = GetTabSize();
600
                        while(bid < ss.bid.GetCount() - 1
601
                        && (i >= text.GetLength() || text[i] == ' ' || text[i] == '\t')) {
602
                                hls.SetPaper(i, 1, BlockColor(bid));
603
                                if(i < text.GetLength() && text[i] == '\t' || ++pos >= tabsz) {
604
                                        pos = 0;
605
                                        bid++;
606
                                }
607
                                i++;
608
                        }
609
                        hls.SetPaper(i, 1 + max(0, text.GetLength() - i), BlockColor(ss.bid.GetCount() - 1));
610
                }
611
                while(*p == ' ' || *p == '\t') {
612
                        p++;
613
                        hls.Put(hl_style[INK_NORMAL]);
614
                }
615
                if(*p == '#' && findarg(highlight, HIGHLIGHT_JAVASCRIPT, HIGHLIGHT_CSS, HIGHLIGHT_JSON) < 0) {
616
                        static const char *pd[] = {
617
                                "define", "error", "if", "elif", "else", "endif",
618
                                "ifdef", "ifndef", "include", "line", "undef", "pragma",
619
                                // CLR
620
                                "using"
621
                        };
622
                        static Index<String> macro;
623
                        if(macro.GetCount() == 0)
624
                                for(int i = 0; i < __countof(pd); i++)
625
                                        macro.Add(pd[i]);
626
                        const wchar *q = p + 1;
627
                        while(*q == ' ' || *q == '\t')
628
                                q++;
629
                        StringBuffer id;
630
                        while(IsAlpha(*q))
631
                                id.Cat(*q++);
632
                        cppid = id;
633
                        hls.Put(macro.Find(cppid) < 0 ? 1 : int(q - p), hl_style[INK_MACRO]);
634
                        p = q;
635
                }
636
        }
637
        int lindent = int(p - ~text);
638
        int lbrace = -1;
639
        int lbclose = -1;
640
        Color lbcolor = Null;
641
        bool is_comment = false;
642
        while(p < e) {
643
                int pair = MAKELONG(p[0], p[1]);
644
                if(ss.linecomment && ss.linecont || pair == MAKELONG('/', '/') && highlight != HIGHLIGHT_CSS && highlight != HIGHLIGHT_JSON) {
645
                        hls.Put(text.GetLength() + 1 - hls.pos, hl_style[INK_COMMENT]);
646
                        is_comment = true;
647
                        break;
648
                }
649
                else
650
                if(ss.comment && highlight != HIGHLIGHT_JSON)
651
                        if(pair == MAKELONG('*', '/')) {
652
                                hls.Put(2, hl_style[INK_COMMENT]);
653
                                p += 2;
654
                                ss.comment = false;
655
                        }
656
                        else {
657
                                hls.Put(hl_style[INK_COMMENT]);
658
                                p++;
659
                        }
660
                else
661
                if((*p == '\"' || *p == '\'') || ss.linecont && ss.string)
662
                        p = HlString(hls, p);
663
                else
664
                if(pair == MAKELONG('/', '*') && highlight != HIGHLIGHT_JSON) {
665
                        hls.Put(2, hl_style[INK_COMMENT]);
666
                        p += 2;
667
                        ss.comment = true;
668
                        is_comment = true;
669
                }
670
                else
671
                if(*p == '(') {
672
                        ss.brk.Add(')');
673
                        Bracket(int(p - text) + pos, hls);
674
                        hls.Put(hl_style[INK_PAR0 + max(ss.pl++, 0) % 4]);
675
                        p++;
676
                }
677
                else
678
                if(*p == '{') {
679
                        ss.brk.Add(ss.was_namespace ? 0 : '}');
680
                        Bracket(int(p - text) + pos, hls);
681
                        hls.Put(hl_style[INK_PAR0 + max(ss.cl, 0) % 4]);
682
                        if(ss.was_namespace)
683
                                ss.was_namespace = false;
684
                        else {
685
                                ++block_level;
686
                                ++ss.cl;
687
                        }
688
                        if(hls.pos < text.GetCount())
689
                                hls.SetPaper(hls.pos, text.GetCount() - hls.pos + 1, BlockColor(block_level));
690
                        p++;
691
                }
692
                else
693
                if(*p == '[') {
694
                        ss.brk.Add(']');
695
                        Bracket(int(p - text) + pos, hls);
696
                        hls.Put(hl_style[INK_PAR0 + max(ss.bl++, 0) % 4]);
697
                        p++;
698
                }
699
                else
700
                if(*p == ')' || *p == '}' || *p == ']') {
701
                        int bl = ss.brk.GetCount();
702
                        int bc = bl ? ss.brk.Pop() : 0;
703
                        if(*p == '}' && hilite_scope && block_level > 0 && bc)
704
                                hls.SetPaper(hls.pos, text.GetLength() + 1 - hls.pos, BlockColor(--block_level));
705
                        Bracket(int(p - text) + pos, hls);
706
                        int& l = *p == ')' ? ss.pl : *p == '}' ? ss.cl : ss.bl;
707
                        if(bc && (bc != *p || l <= 0) || bc == 0 && *p != '}') {
708
                                hls.Put(p == ~text ? hl_style[INK_PAR0] : hl_style[INK_ERROR]);
709
                                ss.brk.Clear();
710
                                ss.cl = ss.bl = ss.pl = 0;
711
                        }
712
                        else {
713
                                if(bc) --l;
714
                                hls.Put(1, hl_style[INK_PAR0 + l % 4]);
715
                        }
716
                        p++;
717
                }
718
                else
719
                if(highlight == HIGHLIGHT_CSS ? *p == '#' : pair == MAKELONG('0', 'x') || pair == MAKELONG('0', 'X')) {
720
                        hls.Put(2, hl_style[INK_CONST_HEX]);
721
                        p += 2;
722
                        const wchar *t = p;
723
                        while(IsXDigit(*p))
724
                                p++;
725
                        hls.Put(int(p - t), hl_style[INK_CONST_HEX]);
726
                }
727
                else
728
                if(IsDigit(*p)) {
729
                        const wchar *t = p;
730
                        int c = INK_CONST_INT;
731
                        bool isDot, isFloat = false;
732
                        if(*p == '0') c = INK_CONST_OCT;
733
                        while(IsDigit(*p)) p++;
734
                        int fixdigits = p - t;
735
                        if(*p == '.' || (*p == 'e' || *p == 'E') && highlight != HIGHLIGHT_CSS) {
736
                                if(*p == '.')
737
                                        isDot = true;
738
                                c = INK_CONST_FLOAT;
739
                                p++;
740
                                if(*p == '-')
741
                                        p++;
742
                        }
743
                        while((IsDigit(*p) || (isDot && *p == 'f')) && (isFloat == false)) {
744
                                if(*p == 'f')
745
                                        isFloat = true;
746
                                p++;
747
                        }
748
                        if(c == INK_CONST_OCT && p - t == 1)
749
                                c = INK_CONST_INT;
750
                        int n = int(p - t);
751
                        for(int i = 0; i < n; i++)
752
                                hls.Put(hl_style[c],
753
                                        c == INK_CONST_OCT || (fixdigits < 4 && n - fixdigits < 5) || i == fixdigits || !thousands_separator ? 0 :
754
                                        i < fixdigits ? decode((fixdigits - i) % 3, 1, LineEdit::SHIFT_L, 0, LineEdit::SHIFT_R, 0) :
755
                                                        decode((i - fixdigits) % 3, 1, LineEdit::SHIFT_R, 0, LineEdit::SHIFT_L, 0));
756

    
757
//                                hls.Put(q > 0 && ((q / 3) & 1) == 1 && c != INK_CONST_OCT ?
758
//                                        hl_style[c == INK_CONST_INT ? INK_CONST_INT_3 : INK_CONST_FLOAT_3]
759
//                                        : hl_style[c]);
760
                }
761
                else
762
                if(pair == MAKELONG('t', '_') && p[2] == '(' && p[3] == '\"') {
763
                        int pos0 = hls.pos;
764
                        hls.Put(3, hl_style[INK_UPP]);
765
                        p = HlString(hls, p + 3);
766
                        if(*p == ')') {
767
                                hls.Put(hl_style[INK_UPP]);
768
                                p++;
769
                        }
770
                        hls.SetPaper(pos0, hls.pos - pos0, hl_style[PAPER_LNG].color);
771
                }
772
                else
773
                if(pair == MAKELONG('t', 't') && p[3] == '(' && p[4] == '\"') {
774
                        int pos0 = hls.pos;
775
                        hls.Put(4, hl_style[INK_UPP]);
776
                        p = HlString(hls, p + 4);
777
                        if(*p == ')') {
778
                                hls.Put(hl_style[INK_UPP]);
779
                                p++;
780
                        }
781
                        hls.SetPaper(pos0, hls.pos - pos0, hl_style[PAPER_LNG].color);
782
                }
783
                else
784
                if(iscib(*p)) {
785
                        const wchar *q = p;
786
                        StringBuffer id;
787
                        while((iscidl(*q) || highlight == HIGHLIGHT_CSS && *q == '-') && q < e)
788
                                id.Cat(*q++);
789
                        String iid = id;
790
                        if(highlight == HIGHLIGHT_SQL)
791
                                iid = ToUpper(iid);
792
                        int uq = kw_upp.Find(iid);
793
                        int nq;
794
                        hls.Put(int(q - p), (nq = keyword[highlight].Find(iid)) >= 0 ? hl_style[INK_KEYWORD] :
795
                                            name[highlight].Find(iid) >= 0 ? hl_style[INK_UPP] :
796
                                            uq >= 0 ? uq < kw_macros ? hl_style[INK_UPPMACROS] :
797
                                                      uq < kw_logs ? hl_style[INK_UPPLOGS] :
798
                                                      uq < kw_sql_base ? hl_style[INK_SQLBASE] : 
799
                                                      uq < kw_sql_func ? hl_style[INK_SQLFUNC] :
800
                                                      hl_style[INK_SQLBOOL] :
801
                                            IsUpperString(iid) && !sm.macro ? hl_style[INK_UPPER] :
802
                                            hl_style[INK_NORMAL]);
803
                        p = q;
804
                        if(nq == 0)
805
                                ss.was_namespace = true;
806
                }
807
                else {
808
                        if(*p == ';')
809
                                ss.was_namespace = false;
810
                        hls.Put(strchr("!+-*^/%~&|=[]:?<>.", *p) ? hl_style[INK_OPERATOR] : hl_style[INK_NORMAL]);
811
                        p++;
812
                }
813
        }
814
        if(hilite_ifdef && !IsNull(cppid) && !is_comment) {
815
                if((cppid == "else" || cppid == "elif" || cppid == "endif") && !ss.ifstack.IsEmpty()) {
816
                        WStringBuffer ifln;
817
                        ifln.Cat(" // ");
818
                        ifln.Cat(ss.ifstack.Top().iftext);
819
                        if(ss.ifstack.Top().ifline && hilite_ifdef == 2) {
820
                                ifln.Cat(", line ");
821
                                ifln.Cat(FormatInt(ss.ifstack.Top().ifline));
822
                        }
823
                        ifln.Cat('\t');
824
                        int start = text.GetLength();
825
                        WString ifs(ifln);
826
                        hls.Set(start, ifs.GetLength(), hl_style[INK_IFDEF]);
827
                        for(int i = 0; i < ifs.GetCount(); i++)
828
                                hl[start + i].chr = ifs[i];
829
                }
830
        }
831
        if(hilite_scope) {
832
                if(lbrace >= 0 && lbclose < 0 && lbrace > lindent)
833
                        hls.SetPaper(lindent, lbrace - lindent, lbcolor);
834
                if(lbrace < 0 && lbclose >= 0)
835
                        hls.SetPaper(lbclose, text.GetLength() + 1 - lbclose, lbcolor);
836
        }
837
        if(!IsNull(cppid) && (cppid == "else" || cppid == "elif" || cppid == "endif" || cppid == "if"
838
                              || cppid == "ifdef" || cppid == "ifndef"))
839
           hls.SetPaper(0, hls.v.GetCount(), hl_style[PAPER_IFDEF].color);
840
}
841

    
842
INITBLOCK {
843
        CodeEditor::InitKeywords();
844
}
845

    
846
END_UPP_NAMESPACE