Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <svtools/syntaxhighlight.hxx>
22 :
23 : #include <unotools/charclass.hxx>
24 : #include <comphelper/string.hxx>
25 :
26 : // ##########################################################################
27 : // ATTENTION: all these words needs to be in small caps
28 : // ##########################################################################
29 : static const char* strListBasicKeyWords[] = {
30 : "access",
31 : "alias",
32 : "and",
33 : "any",
34 : "append",
35 : "as",
36 : "attribute",
37 : "base",
38 : "binary",
39 : "boolean",
40 : "byref",
41 : "byte",
42 : "byval",
43 : "call",
44 : "case",
45 : "cdecl",
46 : "classmodule",
47 : "close",
48 : "compare",
49 : "compatible",
50 : "const",
51 : "currency",
52 : "date",
53 : "declare",
54 : "defbool",
55 : "defcur",
56 : "defdate",
57 : "defdbl",
58 : "deferr",
59 : "defint",
60 : "deflng",
61 : "defobj",
62 : "defsng",
63 : "defstr",
64 : "defvar",
65 : "dim",
66 : "do",
67 : "double",
68 : "each",
69 : "else",
70 : "elseif",
71 : "end",
72 : "end enum",
73 : "end function",
74 : "end if",
75 : "end property",
76 : "end select",
77 : "end sub",
78 : "end type",
79 : "endif",
80 : "enum",
81 : "eqv",
82 : "erase",
83 : "error",
84 : "exit",
85 : "explicit",
86 : "for",
87 : "function",
88 : "get",
89 : "global",
90 : "gosub",
91 : "goto",
92 : "if",
93 : "imp",
94 : "implements",
95 : "in",
96 : "input",
97 : "integer",
98 : "is",
99 : "let",
100 : "lib",
101 : "like",
102 : "line",
103 : "line input",
104 : "local",
105 : "lock",
106 : "long",
107 : "loop",
108 : "lprint",
109 : "lset",
110 : "mod",
111 : "name",
112 : "new",
113 : "next",
114 : "not",
115 : "object",
116 : "on",
117 : "open",
118 : "option",
119 : "optional",
120 : "or",
121 : "output",
122 : "paramarray",
123 : "preserve",
124 : "print",
125 : "private",
126 : "property",
127 : "public",
128 : "random",
129 : "read",
130 : "redim",
131 : "rem",
132 : "resume",
133 : "return",
134 : "rset",
135 : "select",
136 : "set",
137 : "shared",
138 : "single",
139 : "static",
140 : "step",
141 : "stop",
142 : "string",
143 : "sub",
144 : "system",
145 : "text",
146 : "then",
147 : "to",
148 : "type",
149 : "typeof",
150 : "until",
151 : "variant",
152 : "vbasupport",
153 : "wend",
154 : "while",
155 : "with",
156 : "withevent",
157 : "write",
158 : "xor"
159 : };
160 :
161 :
162 : static const char* strListSqlKeyWords[] = {
163 : "all",
164 : "and",
165 : "any",
166 : "as",
167 : "asc",
168 : "avg",
169 : "between",
170 : "by",
171 : "cast",
172 : "corresponding",
173 : "count",
174 : "create",
175 : "cross",
176 : "delete",
177 : "desc",
178 : "distinct",
179 : "drop",
180 : "escape",
181 : "except",
182 : "exists",
183 : "false",
184 : "from",
185 : "full",
186 : "global",
187 : "group",
188 : "having",
189 : "in",
190 : "inner",
191 : "insert",
192 : "intersect",
193 : "into",
194 : "is",
195 : "join",
196 : "left",
197 : "like",
198 : "local",
199 : "match",
200 : "max",
201 : "min",
202 : "natural",
203 : "not",
204 : "null",
205 : "on",
206 : "or",
207 : "order",
208 : "outer",
209 : "right",
210 : "select",
211 : "set",
212 : "some",
213 : "sum",
214 : "table",
215 : "temporary",
216 : "true",
217 : "union",
218 : "unique",
219 : "unknown",
220 : "update",
221 : "using",
222 : "values",
223 : "where"
224 : };
225 :
226 :
227 0 : extern "C" int CDECL compare_strings( const void *arg1, const void *arg2 )
228 : {
229 0 : return strcmp( (char *)arg1, *(char **)arg2 );
230 : }
231 :
232 :
233 : namespace
234 : {
235 :
236 : class LetterTable
237 : {
238 : bool IsLetterTab[256];
239 :
240 : public:
241 : LetterTable( void );
242 :
243 0 : inline bool isLetter( sal_Unicode c )
244 : {
245 0 : bool bRet = (c < 256) ? IsLetterTab[c] : isLetterUnicode( c );
246 0 : return bRet;
247 : }
248 : bool isLetterUnicode( sal_Unicode c );
249 : };
250 :
251 0 : static bool isAlpha(sal_Unicode c)
252 : {
253 0 : if (comphelper::string::isalphaAscii(c))
254 0 : return true;
255 0 : static LetterTable aLetterTable;
256 0 : return aLetterTable.isLetter(c);
257 : }
258 : }
259 :
260 0 : LetterTable::LetterTable( void )
261 : {
262 0 : for( int i = 0 ; i < 256 ; ++i )
263 0 : IsLetterTab[i] = false;
264 :
265 0 : IsLetterTab[0xC0] = true; // ?, CAPITAL LETTER A WITH GRAVE ACCENT
266 0 : IsLetterTab[0xC1] = true; // ?, CAPITAL LETTER A WITH ACUTE ACCENT
267 0 : IsLetterTab[0xC2] = true; // ?, CAPITAL LETTER A WITH CIRCUMFLEX ACCENT
268 0 : IsLetterTab[0xC3] = true; // ?, CAPITAL LETTER A WITH TILDE
269 0 : IsLetterTab[0xC4] = true; // ?, CAPITAL LETTER A WITH DIAERESIS
270 0 : IsLetterTab[0xC5] = true; // ?, CAPITAL LETTER A WITH RING ABOVE
271 0 : IsLetterTab[0xC6] = true; // ?, CAPITAL LIGATURE AE
272 0 : IsLetterTab[0xC7] = true; // ?, CAPITAL LETTER C WITH CEDILLA
273 0 : IsLetterTab[0xC8] = true; // ?, CAPITAL LETTER E WITH GRAVE ACCENT
274 0 : IsLetterTab[0xC9] = true; // ?, CAPITAL LETTER E WITH ACUTE ACCENT
275 0 : IsLetterTab[0xCA] = true; // ?, CAPITAL LETTER E WITH CIRCUMFLEX ACCENT
276 0 : IsLetterTab[0xCB] = true; // ?, CAPITAL LETTER E WITH DIAERESIS
277 0 : IsLetterTab[0xCC] = true; // ?, CAPITAL LETTER I WITH GRAVE ACCENT
278 0 : IsLetterTab[0xCD] = true; // ?, CAPITAL LETTER I WITH ACUTE ACCENT
279 0 : IsLetterTab[0xCE] = true; // ?, CAPITAL LETTER I WITH CIRCUMFLEX ACCENT
280 0 : IsLetterTab[0xCF] = true; // ?, CAPITAL LETTER I WITH DIAERESIS
281 0 : IsLetterTab[0xD0] = true; // ?, CAPITAL LETTER ETH
282 0 : IsLetterTab[0xD1] = true; // ?, CAPITAL LETTER N WITH TILDE
283 0 : IsLetterTab[0xD2] = true; // ?, CAPITAL LETTER O WITH GRAVE ACCENT
284 0 : IsLetterTab[0xD3] = true; // ?, CAPITAL LETTER O WITH ACUTE ACCENT
285 0 : IsLetterTab[0xD4] = true; // ?, CAPITAL LETTER O WITH CIRCUMFLEX ACCENT
286 0 : IsLetterTab[0xD5] = true; // ?, CAPITAL LETTER O WITH TILDE
287 0 : IsLetterTab[0xD6] = true; // ?, CAPITAL LETTER O WITH DIAERESIS
288 0 : IsLetterTab[0xD8] = true; // ?, CAPITAL LETTER O WITH STROKE
289 0 : IsLetterTab[0xD9] = true; // ?, CAPITAL LETTER U WITH GRAVE ACCENT
290 0 : IsLetterTab[0xDA] = true; // ?, CAPITAL LETTER U WITH ACUTE ACCENT
291 0 : IsLetterTab[0xDB] = true; // ?, CAPITAL LETTER U WITH CIRCUMFLEX ACCENT
292 0 : IsLetterTab[0xDC] = true; // ?, CAPITAL LETTER U WITH DIAERESIS
293 0 : IsLetterTab[0xDD] = true; // ?, CAPITAL LETTER Y WITH ACUTE ACCENT
294 0 : IsLetterTab[0xDE] = true; // ?, CAPITAL LETTER THORN
295 0 : IsLetterTab[0xDF] = true; // ?, SMALL LETTER SHARP S
296 0 : IsLetterTab[0xE0] = true; // ?, SMALL LETTER A WITH GRAVE ACCENT
297 0 : IsLetterTab[0xE1] = true; // ?, SMALL LETTER A WITH ACUTE ACCENT
298 0 : IsLetterTab[0xE2] = true; // ?, SMALL LETTER A WITH CIRCUMFLEX ACCENT
299 0 : IsLetterTab[0xE3] = true; // ?, SMALL LETTER A WITH TILDE
300 0 : IsLetterTab[0xE4] = true; // ?, SMALL LETTER A WITH DIAERESIS
301 0 : IsLetterTab[0xE5] = true; // ?, SMALL LETTER A WITH RING ABOVE
302 0 : IsLetterTab[0xE6] = true; // ?, SMALL LIGATURE AE
303 0 : IsLetterTab[0xE7] = true; // ?, SMALL LETTER C WITH CEDILLA
304 0 : IsLetterTab[0xE8] = true; // ?, SMALL LETTER E WITH GRAVE ACCENT
305 0 : IsLetterTab[0xE9] = true; // ?, SMALL LETTER E WITH ACUTE ACCENT
306 0 : IsLetterTab[0xEA] = true; // ?, SMALL LETTER E WITH CIRCUMFLEX ACCENT
307 0 : IsLetterTab[0xEB] = true; // ?, SMALL LETTER E WITH DIAERESIS
308 0 : IsLetterTab[0xEC] = true; // ?, SMALL LETTER I WITH GRAVE ACCENT
309 0 : IsLetterTab[0xED] = true; // ?, SMALL LETTER I WITH ACUTE ACCENT
310 0 : IsLetterTab[0xEE] = true; // ?, SMALL LETTER I WITH CIRCUMFLEX ACCENT
311 0 : IsLetterTab[0xEF] = true; // ?, SMALL LETTER I WITH DIAERESIS
312 0 : IsLetterTab[0xF0] = true; // ?, SMALL LETTER ETH
313 0 : IsLetterTab[0xF1] = true; // ?, SMALL LETTER N WITH TILDE
314 0 : IsLetterTab[0xF2] = true; // ?, SMALL LETTER O WITH GRAVE ACCENT
315 0 : IsLetterTab[0xF3] = true; // ?, SMALL LETTER O WITH ACUTE ACCENT
316 0 : IsLetterTab[0xF4] = true; // ?, SMALL LETTER O WITH CIRCUMFLEX ACCENT
317 0 : IsLetterTab[0xF5] = true; // ?, SMALL LETTER O WITH TILDE
318 0 : IsLetterTab[0xF6] = true; // ?, SMALL LETTER O WITH DIAERESIS
319 0 : IsLetterTab[0xF8] = true; // ?, SMALL LETTER O WITH OBLIQUE BAR
320 0 : IsLetterTab[0xF9] = true; // ?, SMALL LETTER U WITH GRAVE ACCENT
321 0 : IsLetterTab[0xFA] = true; // ?, SMALL LETTER U WITH ACUTE ACCENT
322 0 : IsLetterTab[0xFB] = true; // ?, SMALL LETTER U WITH CIRCUMFLEX ACCENT
323 0 : IsLetterTab[0xFC] = true; // ?, SMALL LETTER U WITH DIAERESIS
324 0 : IsLetterTab[0xFD] = true; // ?, SMALL LETTER Y WITH ACUTE ACCENT
325 0 : IsLetterTab[0xFE] = true; // ?, SMALL LETTER THORN
326 0 : IsLetterTab[0xFF] = true; // � , SMALL LETTER Y WITH DIAERESIS
327 0 : }
328 :
329 0 : bool LetterTable::isLetterUnicode( sal_Unicode c )
330 : {
331 : static CharClass* pCharClass = NULL;
332 0 : if( pCharClass == NULL )
333 0 : pCharClass = new CharClass( Application::GetSettings().GetLanguageTag() );
334 0 : rtl::OUString aStr( c );
335 0 : bool bRet = pCharClass->isLetter( aStr, 0 );
336 0 : return bRet;
337 : }
338 :
339 : // Hilfsfunktion: Zeichen-Flag Testen
340 0 : sal_Bool SimpleTokenizer_Impl::testCharFlags( sal_Unicode c, sal_uInt16 nTestFlags )
341 : {
342 0 : bool bRet = false;
343 0 : if( c != 0 && c <= 255 )
344 : {
345 0 : bRet = ( (aCharTypeTab[c] & nTestFlags) != 0 );
346 : }
347 0 : else if( c > 255 )
348 : {
349 : bRet = (( CHAR_START_IDENTIFIER | CHAR_IN_IDENTIFIER ) & nTestFlags) != 0
350 0 : ? isAlpha(c) : false;
351 : }
352 0 : return bRet;
353 : }
354 :
355 0 : void SimpleTokenizer_Impl::setKeyWords( const char** ppKeyWords, sal_uInt16 nCount )
356 : {
357 0 : ppListKeyWords = ppKeyWords;
358 0 : nKeyWordCount = nCount;
359 0 : }
360 :
361 : // Neues Token holen
362 0 : sal_Bool SimpleTokenizer_Impl::getNextToken( /*out*/TokenTypes& reType,
363 : /*out*/const sal_Unicode*& rpStartPos, /*out*/const sal_Unicode*& rpEndPos )
364 : {
365 0 : reType = TT_UNKNOWN;
366 :
367 : // Position merken
368 0 : rpStartPos = mpActualPos;
369 :
370 : // Zeichen untersuchen
371 0 : sal_Unicode c = peekChar();
372 0 : if( c == CHAR_EOF )
373 0 : return sal_False;
374 :
375 : // Zeichen lesen
376 0 : getChar();
377 :
378 : //*** Alle Moeglichkeiten durchgehen ***
379 : // Space?
380 0 : if ( (testCharFlags( c, CHAR_SPACE ) == sal_True) )
381 : {
382 0 : while( testCharFlags( peekChar(), CHAR_SPACE ) == sal_True )
383 0 : getChar();
384 :
385 0 : reType = TT_WHITESPACE;
386 : }
387 :
388 : // Identifier?
389 0 : else if ( (testCharFlags( c, CHAR_START_IDENTIFIER ) == sal_True) )
390 : {
391 : sal_Bool bIdentifierChar;
392 0 : do
393 : {
394 : // Naechstes Zeichen holen
395 0 : c = peekChar();
396 0 : bIdentifierChar = testCharFlags( c, CHAR_IN_IDENTIFIER );
397 0 : if( bIdentifierChar )
398 0 : getChar();
399 : }
400 : while( bIdentifierChar );
401 :
402 0 : reType = TT_IDENTIFIER;
403 :
404 : // Schluesselwort-Tabelle
405 0 : if (ppListKeyWords != NULL)
406 : {
407 0 : int nCount = mpActualPos - rpStartPos;
408 :
409 : // No keyword if string contains char > 255
410 0 : bool bCanBeKeyword = true;
411 0 : for( int i = 0 ; i < nCount ; i++ )
412 : {
413 0 : if( rpStartPos[i] > 255 )
414 : {
415 0 : bCanBeKeyword = false;
416 0 : break;
417 : }
418 : }
419 :
420 0 : if( bCanBeKeyword )
421 : {
422 0 : rtl::OUString aKWString(rpStartPos, nCount);
423 : rtl::OString aByteStr = rtl::OUStringToOString(aKWString,
424 0 : RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase();
425 0 : if ( bsearch( aByteStr.getStr(), ppListKeyWords, nKeyWordCount, sizeof( char* ),
426 0 : compare_strings ) )
427 : {
428 0 : reType = TT_KEYWORDS;
429 :
430 0 : if (aByteStr.equalsL(RTL_CONSTASCII_STRINGPARAM("rem")))
431 : {
432 : // Alle Zeichen bis Zeilen-Ende oder EOF entfernen
433 0 : sal_Unicode cPeek = peekChar();
434 0 : while( cPeek != CHAR_EOF && testCharFlags( cPeek, CHAR_EOL ) == sal_False )
435 : {
436 0 : c = getChar();
437 0 : cPeek = peekChar();
438 : }
439 :
440 0 : reType = TT_COMMENT;
441 : }
442 0 : }
443 : }
444 : }
445 : }
446 :
447 : // Operator?
448 : // only for BASIC '\'' should be a comment, otherwise it is a normal string and handled there
449 0 : else if ( ( testCharFlags( c, CHAR_OPERATOR ) == sal_True ) || ( (c == '\'') && (aLanguage==HIGHLIGHT_BASIC)) )
450 : {
451 : // parameters for SQL view
452 0 : if ( (c==':') || (c=='?'))
453 : {
454 0 : if (c!='?')
455 : {
456 : sal_Bool bIdentifierChar;
457 0 : do
458 : {
459 : // Naechstes Zeichen holen
460 0 : c = peekChar();
461 0 : bIdentifierChar = isAlpha(c);
462 0 : if( bIdentifierChar )
463 0 : getChar();
464 : }
465 : while( bIdentifierChar );
466 : }
467 0 : reType = TT_PARAMETER;
468 : }
469 0 : else if (c=='-')
470 : {
471 0 : sal_Unicode cPeekNext = peekChar();
472 0 : if (cPeekNext=='-')
473 : {
474 : // Alle Zeichen bis Zeilen-Ende oder EOF entfernen
475 0 : while( cPeekNext != CHAR_EOF && testCharFlags( cPeekNext, CHAR_EOL ) == sal_False )
476 : {
477 0 : getChar();
478 0 : cPeekNext = peekChar();
479 : }
480 0 : reType = TT_COMMENT;
481 : }
482 : }
483 0 : else if (c=='/')
484 : {
485 0 : sal_Unicode cPeekNext = peekChar();
486 0 : if (cPeekNext=='/')
487 : {
488 : // Alle Zeichen bis Zeilen-Ende oder EOF entfernen
489 0 : while( cPeekNext != CHAR_EOF && testCharFlags( cPeekNext, CHAR_EOL ) == sal_False )
490 : {
491 0 : getChar();
492 0 : cPeekNext = peekChar();
493 : }
494 0 : reType = TT_COMMENT;
495 : }
496 : }
497 : else
498 : {
499 : // Kommentar ?
500 0 : if ( c == '\'' )
501 : {
502 0 : c = getChar(); // '/' entfernen
503 :
504 : // Alle Zeichen bis Zeilen-Ende oder EOF entfernen
505 0 : sal_Unicode cPeek = c;
506 0 : while( cPeek != CHAR_EOF && testCharFlags( cPeek, CHAR_EOL ) == sal_False )
507 : {
508 0 : getChar();
509 0 : cPeek = peekChar();
510 : }
511 :
512 0 : reType = TT_COMMENT;
513 : }
514 :
515 : // Echter Operator, kann hier einfach behandelt werden,
516 : // da nicht der wirkliche Operator, wie z.B. += interessiert,
517 : // sondern nur die Tatsache, dass es sich um einen handelt.
518 0 : if( reType != TT_COMMENT )
519 : {
520 0 : reType = TT_OPERATOR;
521 : }
522 :
523 : }
524 : }
525 :
526 : // Objekt-Trenner? Muss vor Number abgehandelt werden
527 0 : else if( c == '.' && ( peekChar() < '0' || peekChar() > '9' ) )
528 : {
529 0 : reType = TT_OPERATOR;
530 : }
531 :
532 : // Zahl?
533 0 : else if( testCharFlags( c, CHAR_START_NUMBER ) == sal_True )
534 : {
535 0 : reType = TT_NUMBER;
536 :
537 : // Zahlensystem, 10 = normal, wird bei Oct/Hex geaendert
538 0 : int nRadix = 10;
539 :
540 : // Ist es eine Hex- oder Oct-Zahl?
541 0 : if( c == '&' )
542 : {
543 : // Octal?
544 0 : if( peekChar() == 'o' || peekChar() == 'O' )
545 : {
546 : // o entfernen
547 0 : getChar();
548 0 : nRadix = 8; // Octal-Basis
549 :
550 : // Alle Ziffern einlesen
551 0 : while( testCharFlags( peekChar(), CHAR_IN_OCT_NUMBER ) )
552 0 : c = getChar();
553 : }
554 : // Hex?
555 0 : else if( peekChar() == 'h' || peekChar() == 'H' )
556 : {
557 : // x entfernen
558 0 : getChar();
559 0 : nRadix = 16; // Hex-Basis
560 :
561 : // Alle Ziffern einlesen und puffern
562 0 : while( testCharFlags( peekChar(), CHAR_IN_HEX_NUMBER ) )
563 0 : c = getChar();
564 : }
565 : else
566 : {
567 0 : reType = TT_OPERATOR;
568 : }
569 : }
570 :
571 : // Wenn nicht Oct oder Hex als double ansehen
572 0 : if( reType == TT_NUMBER && nRadix == 10 )
573 : {
574 : // Flag, ob das letzte Zeichen ein Exponent war
575 0 : sal_Bool bAfterExpChar = sal_False;
576 :
577 : // Alle Ziffern einlesen
578 0 : while( testCharFlags( peekChar(), CHAR_IN_NUMBER ) ||
579 0 : (bAfterExpChar && peekChar() == '+' ) ||
580 0 : (bAfterExpChar && peekChar() == '-' ) )
581 : // Nach Exponent auch +/- OK
582 : {
583 0 : c = getChar(); // Zeichen lesen
584 0 : bAfterExpChar = ( c == 'e' || c == 'E' );
585 : }
586 : }
587 :
588 : // reType = TT_NUMBER;
589 : }
590 :
591 : // String?
592 0 : else if( testCharFlags( c, CHAR_START_STRING ) == sal_True )
593 : {
594 : // Merken, welches Zeichen den String eroeffnet hat
595 0 : sal_Unicode cEndString = c;
596 0 : if( c == '[' )
597 0 : cEndString = ']';
598 :
599 : // Alle Ziffern einlesen und puffern
600 0 : while( peekChar() != cEndString )
601 : {
602 : // #58846 EOF vor getChar() abfangen, damit EOF micht verloren geht
603 0 : if( peekChar() == CHAR_EOF )
604 : {
605 : // ERROR: unterminated string literal
606 0 : reType = TT_ERROR;
607 0 : break;
608 : }
609 0 : c = getChar();
610 0 : if( testCharFlags( c, CHAR_EOL ) == sal_True )
611 : {
612 : // ERROR: unterminated string literal
613 0 : reType = TT_ERROR;
614 0 : break;
615 : }
616 : }
617 :
618 : // Zeichen lesen
619 0 : if( reType != TT_ERROR )
620 : {
621 0 : getChar();
622 0 : if( cEndString == ']' )
623 0 : reType = TT_IDENTIFIER;
624 : else
625 0 : reType = TT_STRING;
626 : }
627 : }
628 :
629 : // Zeilenende?
630 0 : else if( testCharFlags( c, CHAR_EOL ) == sal_True )
631 : {
632 : // Falls ein weiteres anderes EOL-Char folgt, weg damit
633 0 : sal_Unicode cNext = peekChar();
634 0 : if( cNext != c && testCharFlags( cNext, CHAR_EOL ) == sal_True )
635 0 : getChar();
636 :
637 : // Positions-Daten auf Zeilen-Beginn setzen
638 0 : nCol = 0;
639 0 : nLine++;
640 :
641 0 : reType = TT_EOL;
642 : }
643 :
644 : // Alles andere bleibt TT_UNKNOWN
645 :
646 :
647 : // End-Position eintragen
648 0 : rpEndPos = mpActualPos;
649 0 : return sal_True;
650 : }
651 :
652 0 : SimpleTokenizer_Impl::SimpleTokenizer_Impl( HighlighterLanguage aLang ): aLanguage(aLang)
653 : {
654 0 : memset( aCharTypeTab, 0, sizeof( aCharTypeTab ) );
655 :
656 : // Zeichen-Tabelle fuellen
657 : sal_uInt16 i;
658 :
659 : // Zulaessige Zeichen fuer Identifier
660 0 : sal_uInt16 nHelpMask = (sal_uInt16)( CHAR_START_IDENTIFIER | CHAR_IN_IDENTIFIER );
661 0 : for( i = 'a' ; i <= 'z' ; i++ )
662 0 : aCharTypeTab[i] |= nHelpMask;
663 0 : for( i = 'A' ; i <= 'Z' ; i++ )
664 0 : aCharTypeTab[i] |= nHelpMask;
665 : // '_' extra eintragen
666 0 : aCharTypeTab[(int)'_'] |= nHelpMask;
667 : // AB 23.6.97: '$' ist auch erlaubt
668 0 : aCharTypeTab[(int)'$'] |= nHelpMask;
669 :
670 : // Ziffern (Identifier und Number ist moeglich)
671 : nHelpMask = (sal_uInt16)( CHAR_IN_IDENTIFIER | CHAR_START_NUMBER |
672 0 : CHAR_IN_NUMBER | CHAR_IN_HEX_NUMBER );
673 0 : for( i = '0' ; i <= '9' ; i++ )
674 0 : aCharTypeTab[i] |= nHelpMask;
675 :
676 : // e und E sowie . von Hand ergaenzen
677 0 : aCharTypeTab[(int)'e'] |= CHAR_IN_NUMBER;
678 0 : aCharTypeTab[(int)'E'] |= CHAR_IN_NUMBER;
679 0 : aCharTypeTab[(int)'.'] |= (sal_uInt16)( CHAR_IN_NUMBER | CHAR_START_NUMBER );
680 0 : aCharTypeTab[(int)'&'] |= CHAR_START_NUMBER;
681 :
682 : // Hex-Ziffern
683 0 : for( i = 'a' ; i <= 'f' ; i++ )
684 0 : aCharTypeTab[i] |= CHAR_IN_HEX_NUMBER;
685 0 : for( i = 'A' ; i <= 'F' ; i++ )
686 0 : aCharTypeTab[i] |= CHAR_IN_HEX_NUMBER;
687 :
688 : // Oct-Ziffern
689 0 : for( i = '0' ; i <= '7' ; i++ )
690 0 : aCharTypeTab[i] |= CHAR_IN_OCT_NUMBER;
691 :
692 : // String-Beginn/End-Zeichen
693 0 : aCharTypeTab[(int)'\''] |= CHAR_START_STRING;
694 0 : aCharTypeTab[(int)'\"'] |= CHAR_START_STRING;
695 0 : aCharTypeTab[(int)'['] |= CHAR_START_STRING;
696 0 : aCharTypeTab[(int)'`'] |= CHAR_START_STRING;
697 :
698 : // Operator-Zeichen
699 0 : aCharTypeTab[(int)'!'] |= CHAR_OPERATOR;
700 0 : aCharTypeTab[(int)'%'] |= CHAR_OPERATOR;
701 : // aCharTypeTab[(int)'&'] |= CHAR_OPERATOR; Removed because of #i14140
702 0 : aCharTypeTab[(int)'('] |= CHAR_OPERATOR;
703 0 : aCharTypeTab[(int)')'] |= CHAR_OPERATOR;
704 0 : aCharTypeTab[(int)'*'] |= CHAR_OPERATOR;
705 0 : aCharTypeTab[(int)'+'] |= CHAR_OPERATOR;
706 0 : aCharTypeTab[(int)','] |= CHAR_OPERATOR;
707 0 : aCharTypeTab[(int)'-'] |= CHAR_OPERATOR;
708 0 : aCharTypeTab[(int)'/'] |= CHAR_OPERATOR;
709 0 : aCharTypeTab[(int)':'] |= CHAR_OPERATOR;
710 0 : aCharTypeTab[(int)'<'] |= CHAR_OPERATOR;
711 0 : aCharTypeTab[(int)'='] |= CHAR_OPERATOR;
712 0 : aCharTypeTab[(int)'>'] |= CHAR_OPERATOR;
713 0 : aCharTypeTab[(int)'?'] |= CHAR_OPERATOR;
714 0 : aCharTypeTab[(int)'^'] |= CHAR_OPERATOR;
715 0 : aCharTypeTab[(int)'|'] |= CHAR_OPERATOR;
716 0 : aCharTypeTab[(int)'~'] |= CHAR_OPERATOR;
717 0 : aCharTypeTab[(int)'{'] |= CHAR_OPERATOR;
718 0 : aCharTypeTab[(int)'}'] |= CHAR_OPERATOR;
719 : // aCharTypeTab[(int)'['] |= CHAR_OPERATOR; Removed because of #i17826
720 0 : aCharTypeTab[(int)']'] |= CHAR_OPERATOR;
721 0 : aCharTypeTab[(int)';'] |= CHAR_OPERATOR;
722 :
723 : // Space
724 0 : aCharTypeTab[(int)' ' ] |= CHAR_SPACE;
725 0 : aCharTypeTab[(int)'\t'] |= CHAR_SPACE;
726 :
727 : // Zeilen-Ende-Zeichen
728 0 : aCharTypeTab[(int)'\r'] |= CHAR_EOL;
729 0 : aCharTypeTab[(int)'\n'] |= CHAR_EOL;
730 :
731 0 : ppListKeyWords = NULL;
732 0 : }
733 :
734 0 : SimpleTokenizer_Impl::~SimpleTokenizer_Impl( void )
735 : {
736 0 : }
737 :
738 0 : SimpleTokenizer_Impl* getSimpleTokenizer( void )
739 : {
740 : static SimpleTokenizer_Impl* pSimpleTokenizer = NULL;
741 0 : if( !pSimpleTokenizer )
742 0 : pSimpleTokenizer = new SimpleTokenizer_Impl();
743 0 : return pSimpleTokenizer;
744 : }
745 :
746 : // Heraussuchen der jeweils naechsten Funktion aus einem JavaScript-Modul
747 0 : sal_uInt16 SimpleTokenizer_Impl::parseLine( sal_uInt32 nParseLine, const String* aSource )
748 : {
749 : // Position auf den Anfang des Source-Strings setzen
750 0 : mpStringBegin = mpActualPos = aSource->GetBuffer();
751 :
752 : // Zeile und Spalte initialisieren
753 0 : nLine = nParseLine;
754 0 : nCol = 0L;
755 :
756 : // Variablen fuer die Out-Parameter
757 : TokenTypes eType;
758 : const sal_Unicode* pStartPos;
759 : const sal_Unicode* pEndPos;
760 :
761 : // Schleife ueber alle Tokens
762 0 : sal_uInt16 nTokenCount = 0;
763 0 : while( getNextToken( eType, pStartPos, pEndPos ) )
764 0 : nTokenCount++;
765 :
766 0 : return nTokenCount;
767 : }
768 :
769 0 : void SimpleTokenizer_Impl::getHighlightPortions( sal_uInt32 nParseLine, const String& rLine,
770 : /*out*/HighlightPortions& portions )
771 : {
772 : // Position auf den Anfang des Source-Strings setzen
773 0 : mpStringBegin = mpActualPos = rLine.GetBuffer();
774 :
775 : // Zeile und Spalte initialisieren
776 0 : nLine = nParseLine;
777 0 : nCol = 0L;
778 :
779 : // Variablen fuer die Out-Parameter
780 : TokenTypes eType;
781 : const sal_Unicode* pStartPos;
782 : const sal_Unicode* pEndPos;
783 :
784 : // Schleife ueber alle Tokens
785 0 : while( getNextToken( eType, pStartPos, pEndPos ) )
786 : {
787 : HighlightPortion portion;
788 :
789 0 : portion.nBegin = (sal_uInt16)(pStartPos - mpStringBegin);
790 0 : portion.nEnd = (sal_uInt16)(pEndPos - mpStringBegin);
791 0 : portion.tokenType = eType;
792 :
793 0 : portions.push_back(portion);
794 : }
795 0 : }
796 :
797 :
798 : //////////////////////////////////////////////////////////////////////////
799 : // Implementierung des SyntaxHighlighter
800 :
801 0 : SyntaxHighlighter::SyntaxHighlighter()
802 : {
803 0 : m_pSimpleTokenizer = 0;
804 0 : m_pKeyWords = NULL;
805 0 : m_nKeyWordCount = 0;
806 0 : }
807 :
808 0 : SyntaxHighlighter::~SyntaxHighlighter()
809 : {
810 0 : delete m_pSimpleTokenizer;
811 0 : delete m_pKeyWords;
812 0 : }
813 :
814 0 : void SyntaxHighlighter::initialize( HighlighterLanguage eLanguage_ )
815 : {
816 0 : eLanguage = eLanguage_;
817 0 : delete m_pSimpleTokenizer;
818 0 : m_pSimpleTokenizer = new SimpleTokenizer_Impl(eLanguage);
819 :
820 0 : switch (eLanguage)
821 : {
822 : case HIGHLIGHT_BASIC:
823 : m_pSimpleTokenizer->setKeyWords( strListBasicKeyWords,
824 0 : sizeof( strListBasicKeyWords ) / sizeof( char* ));
825 0 : break;
826 : case HIGHLIGHT_SQL:
827 : m_pSimpleTokenizer->setKeyWords( strListSqlKeyWords,
828 0 : sizeof( strListSqlKeyWords ) / sizeof( char* ));
829 0 : break;
830 : default:
831 0 : m_pSimpleTokenizer->setKeyWords( NULL, 0 );
832 : }
833 0 : }
834 :
835 0 : const Range SyntaxHighlighter::notifyChange( sal_uInt32 nLine, sal_Int32 nLineCountDifference,
836 : const String* pChangedLines, sal_uInt32 nArrayLength)
837 : {
838 : (void)nLineCountDifference;
839 :
840 0 : for( sal_uInt32 i=0 ; i < nArrayLength ; i++ )
841 0 : m_pSimpleTokenizer->parseLine(nLine+i, &pChangedLines[i]);
842 :
843 0 : return Range( nLine, nLine + nArrayLength-1 );
844 : }
845 :
846 0 : void SyntaxHighlighter::getHighlightPortions( sal_uInt32 nLine, const String& rLine,
847 : /*out*/HighlightPortions& portions )
848 : {
849 0 : m_pSimpleTokenizer->getHighlightPortions( nLine, rLine, portions );
850 0 : }
851 :
852 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|