]> git.saurik.com Git - wxWidgets.git/blob - utils/HelpGen/src/sourcepainter.cpp
Better doc
[wxWidgets.git] / utils / HelpGen / src / sourcepainter.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: No names yet.
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: 22/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleskandars Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22
23 #if defined( wxUSE_TEMPLATE_STL )
24 # include <map>
25 #else
26 # include "wxstlac.h"
27 #endif
28
29 #include "sourcepainter.h"
30
31 const int MAX_KEYWORD_LEN = 16;
32
33 struct KeywordT
34 {
35 char keyWord[MAX_KEYWORD_LEN];
36 int rank;
37 };
38
39 // source fragment ranks :
40
41 // 0 - nomral text
42 // 1 - basic types
43 // 2 - reserved words
44
45 // multil-language keywords map
46
47 static KeywordT __gKeyWords[] =
48 {
49 { "for", 1 },
50 { "FOR", 1 },
51 { "For", 1 },
52
53 { "next", 1 },
54 { "Next", 1 },
55 { "NEXT", 1 },
56
57 { "if", 1 },
58 { "If", 1 },
59 { "IF", 1 },
60
61 { "then", 1 },
62 { "Then", 1 },
63 { "THEN", 1 },
64
65 { "else", 1 },
66 { "Else", 1 },
67 { "ELSE", 1 },
68
69 { "do", 1 },
70 { "Do", 1 },
71 { "DO", 1 },
72
73
74 { "break", 1 },
75 { "Break", 1 },
76 { "BREAK", 1 },
77
78 { "continue", 1 },
79
80 { "goto", 1 },
81 { "Goto", 1 },
82 { "GOTO", 1 },
83
84 { "switch", 1 },
85 { "default", 1 },
86 { "case", 1 },
87
88 { "repeat", 1 },
89 { "Repeat", 1 },
90 { "REPEAT", 1 },
91
92 { "until", 1 },
93 { "Until", 1 },
94 { "UNTIL", 1 },
95
96 { "return", 1 },
97 { "Return", 1 },
98 { "RETURN", 1 },
99
100 { "unit", 1 },
101 { "Unit", 1 },
102 { "UNIT", 1 },
103
104 { "procedure", 1 },
105 { "Procedure", 1 },
106 { "PROCEDURE", 1 },
107
108 { "function", 1 },
109 { "Function", 1 },
110 { "FUNCTION", 1 },
111
112 { "begin", 1 },
113 { "Begin", 1 },
114 { "BEGIN", 1 },
115
116 { "End", 1 },
117 { "END", 1 },
118
119 ////////////////////////////////////////////////////
120
121 { "enum", 1 },
122 { "static", 1 },
123 { "const", 1 },
124 { "mutable", 1 },
125 { "volatile", 1 },
126 { "__asm", 1 },
127 { "asm", 1 },
128
129 { "typeid", 1 },
130 { "sizeof", 1 },
131 { "typeof", 1 },
132
133
134 { "native", 1 },
135
136 { "#include", 1 },
137 { "#define", 1 },
138 { "#def", 1 },
139 { "#undef", 1 },
140 { "#ifdef", 1 },
141 { "#ifndef", 1 },
142 { "#if", 1 },
143 { "#endif", 1 },
144 { "#elif", 1 },
145 { "#else", 1 },
146 { "#pragma", 1 },
147 { "#line", 1 },
148
149 { "package", 1 },
150 { "import", 1 },
151 { "export", 1 },
152
153 ////////////////////////////////////////////////////
154
155 { "dynamic_cast", 1 },
156 { "const_cast", 1 },
157
158 //////// some hacks for VB /////////
159
160 { "sub", 1 },
161 { "Sub", 1 },
162 { "SUB", 1 },
163 { "as", 1 },
164 { "As", 1 },
165 { "AS", 1 },
166
167 /////// data types ///////
168
169 { "int" , 1 },
170 { "integer", 1 },
171 { "Integer", 1 },
172 { "INTEGER", 1 },
173
174 { "real", 1 },
175 { "Real", 1 },
176 { "REAL", 1 },
177
178 { "float", 1 },
179 { "Float", 1 },
180 { "FLOAT", 1 },
181
182 { "char", 1 },
183 { "Char", 1 },
184 { "CHAR", 1 },
185
186 { "register", 1 },
187
188 { "string", 1 },
189 { "String", 1 },
190 { "STRING", 1 },
191
192 { "array", 1 },
193 { "Array", 1 },
194 { "ARRAY", 1 },
195
196 { "packed", 1 },
197 { "Packed", 1 },
198 { "PACKED", 1 },
199
200 { "property", 1 },
201 { "Property", 1 },
202 { "PROPERTY", 1 },
203
204 { "unsigned", 1 },
205
206 { "long", 1 },
207 { "double", 1 },
208 { "short", 1 },
209 { "bool", 1 },
210
211 { "longint", 1 },
212 { "Longint", 1 },
213 { "LONGINT", 1 },
214
215 { "extended", 1 },
216 { "Extended", 1 },
217 { "EXTENTED", 1 },
218
219 { "pointer", 1 },
220 { "Pointer", 1 },
221 { "POINTER", 1 },
222
223 { "and", 1 },
224 { "And", 1 },
225 { "AND", 1 },
226 { "or", 1 },
227 { "Or", 1 },
228 { "OR", 1 },
229 { "xor", 1 },
230 { "Xor", 1 },
231 { "XOR", 1 },
232
233 { "void", 1 },
234 { "__stdcall", 1 },
235 { "__declspec", 1 },
236 { "extern", 1 },
237 { "stdcall", 1 },
238 { "dllimport", 1 },
239 { "dllexport", 1 },
240 { "__cdecl", 1 },
241 { "cdecl", 1 },
242 { "template", 1 },
243 { "typedef", 1 },
244 { "naked", 1 },
245
246 { "try", 1 },
247 { "catch", 1 },
248 { "throw", 2 }, // C++
249 { "throws", 1 }, // Java
250
251
252 { "finalize", 1 },
253
254 // "STL-suport"
255
256 { "size_t", 1 },
257 { "NPOS", 1 },
258 { "vector", 1 },
259 { "list", 1 },
260 { "map", 1 },
261 { "multimap", 1 },
262
263 { "external", 1 },
264 { "External", 1 },
265 { "EXTERNAL", 1 },
266
267 //////////// meta-information //////////////
268
269 { "virtual", 2 },
270 { "Virtual", 2 },
271
272 { "override", 2 },
273 { "Override", 2 },
274
275 { "class", 2 },
276 { "Class", 2 },
277 { "CLASS", 2 },
278
279 { "struct", 2 },
280 { "union", 2 },
281
282 { "record", 2 },
283 { "Record", 2 },
284 { "RECORD", 2 },
285
286 { "form", 1 },
287 { "Form", 1 },
288 { "FORM", 1 },
289
290 { "namespace", 2 },
291
292 { "interface" , 2 },
293 { "abstract", 2 },
294
295 { "Interface" , 2 },
296 { "INTERFACE" , 2 },
297
298 { "implementation", 2 },
299 { "Implementation", 2 },
300 { "IMPLEMENTATION", 2 },
301
302 { "label", 2 },
303 { "Label", 2 },
304 { "LABEL", 2 },
305
306 { "implements", 2 },
307
308 { "public", 2 },
309 { "private", 2 },
310 { "protected", 2 },
311
312 { "this", 2 },
313 { "This", 2 },
314 { "THIS", 2 },
315
316 { "new", 2 },
317 { "New", 2 },
318 { "NEW", 2 },
319
320 { "delete", 2 },
321 { "inline", 2 },
322
323 { "operator", 2 },
324
325 { "Inherited", 2 },
326 { "Inherited", 2 },
327
328 { "final", 2 },
329 { "implements", 2 },
330 { "super", 2 },
331
332 // even more...
333 { "java", 2 },
334 { "Java", 2 },
335 { "JAVA", 2 },
336 { "delphi", 2 },
337 { "Delphi", 2 },
338 { "SmallTalk", 2 },
339 { "Smalltalk", 2 },
340 { "smalltalk", 2 },
341 { "assembler", 2 },
342 { "Assembler", 2 },
343 { "Basic", 2 },
344 { "BASIC", 2 },
345 { "basic", 2 },
346 { "CORBA", 2 },
347 { "COBOL", 2 },
348 { "ADA", 2 },
349 { "LISP", 2 },
350
351 // just for fun...
352 { "life", 2 },
353 { "sucks", 2 },
354 { "rules", 2 },
355 { "Quake", 2 },
356 { "QuakeWorld", 2 },
357 { "[ag_slammer]",2 },
358 { "Aleksandras", 2 },
359 { "Gluchovas" , 2 },
360 { "Alex", 2 },
361 { "alex", 2 },
362 { "aleks", 2 },
363 { "aleksas", 3 },
364 { "AlexSoft", 2 },
365 { "Alexsoft", 2 },
366 { "SpringSky", 2 },
367 { "SK_Team", 2 },
368 { "soften", 2 },
369 { "UB40", 2 },
370 { "U96", 2 }
371 };
372
373 struct less_c_str
374 {
375 inline bool operator()( char* x, char* y) const
376 { return ( strcmp( x,y ) < 0 );
377 }
378 };
379
380 #if defined( wxUSE_TEMPLATE_STL )
381
382 typedef map< char*, char*, less_c_str > KeywordMapT;
383
384 #else
385
386 typedef char* CharPtrT;
387 typedef WXSTL_MAP( CharPtrT, CharPtrT ,less_c_str) KeywordMapT;
388
389 #endif
390
391 static KeywordMapT __gMultiLangMap;
392 static int __gMapReady = 0;
393
394 void check_keyword_map( int keywordMapNr )
395 {
396 if ( !__gMapReady )
397 {
398 __gMapReady = 1;
399
400 // "make sure" the address of the first member of non-polimorphic class
401 // coinsides with the address of the instance
402
403 /*
404 KeywordT dummy;
405
406 if ( (char*)& dummy != &dummy.keyWord[0] )
407 throw;
408 */
409
410 int size = sizeof(__gKeyWords) / sizeof( KeywordT );
411
412 for( int i = 0; i != size; ++i )
413
414 __gMultiLangMap.insert(
415 KeywordMapT::value_type( (char*)&__gKeyWords[i],
416 (char*)&__gKeyWords[i]
417 )
418 );
419 }
420 }
421
422 int get_rank( char* start, char* end )
423 {
424 // FIXME:: what if end is no longer leagal adress?
425
426 char tmp = *end;
427 *end = '\0'; // put temporary terminator
428
429 KeywordMapT::iterator i;
430
431 if ( (i = __gMultiLangMap.find( start ) ) != __gMultiLangMap.end() )
432 {
433 KeywordT* pKey = (KeywordT*)(*i).second;
434
435 *end = tmp;
436
437 return pKey->rank;
438 }
439 else
440 {
441 *end = tmp;
442 return 0;
443 }
444 }
445
446 static inline void store_range( SPBlockListT& results, int rank, int range_len )
447 {
448 if ( !range_len ) return;
449
450 results.push_back ( ( rank << 16 ) | ( range_len ) );
451 }
452
453
454 #define STORE_RANGE store_range( results, cur_rank, cur_range_len );\
455 cur_rank = cur_range_len = 0;
456
457 #define NEXT_CHAR cur_range_len++; \
458 ++cur; \
459 continue;
460
461 static inline int is_alpha( char ch )
462 {
463 return ( (( ch >= '_' ) && ( ch <= 'z' )) ||
464 (( ch >= 'A' ) && ( ch <= 'Z' ))
465 );
466 }
467
468 // _ . .
469 // Ziema atEjo netikEtai
470
471 static void heighlight_syntax( char* str, int strLen,
472 SPBlockListT& results, bool& isComment )
473 {
474 bool isMultiline = 0;
475 char* cur = str;
476 char* end = str + strLen;
477
478 int cur_rank = ( isComment == 1 ) ? RANK_GREEN : RANK_BLACK;
479 int cur_range_len = 0;
480
481 while ( cur != end )
482 {
483 int has_next = ( cur+1 != end );
484
485 if ( isComment )
486 {
487 if ( *cur == '*' )
488 if ( has_next && *(cur+1) == '/' )
489 {
490 // turn off multiline comment mode
491 cur += 2;
492 cur_range_len += 2;
493 isComment = 0;
494 isMultiline = 0;
495 STORE_RANGE;
496
497 continue;
498 }
499
500 ++cur_range_len;
501 ++cur;
502 continue;
503 }
504
505 /*
506 if ( *cur == 10 )
507 if ( isComment )
508 if ( isMultiline )
509 {
510 cur_rank = RANK_GREEN;
511 cur_range_len = end - cur;
512 STORE_RANGE;
513 isComment = 0;
514 isMultiline = 0;
515 continue;
516 }*/
517
518 if ( *cur == '/' )
519 {
520 if ( has_next )
521 {
522 if ( *(cur+1) == '/' )
523 {
524 STORE_RANGE;
525
526 char* eol = cur;
527 while ( eol < end && *eol != 10 )
528 ++eol;
529
530 cur_rank = RANK_GREEN;
531 cur_range_len = eol - cur;
532 cur = eol;
533 STORE_RANGE;
534
535 continue;
536 }
537
538 if ( *(cur+1) == '*' )
539 {
540 STORE_RANGE;
541 cur_rank = RANK_GREEN;
542 cur_range_len = 2;
543 isComment = 1;
544 cur += 2;
545 isMultiline = 1;
546 continue;
547 }
548 }
549
550 NEXT_CHAR;
551 }
552
553 if ( ( is_alpha( *cur ) || *(cur) == '#' )
554 && has_next
555 )
556 {
557 if ( is_alpha( *(cur+1) ) )
558 {
559 char* start = cur;
560 cur += 2;
561
562 while ( cur != end && is_alpha(*cur) ) ++cur;
563
564 int wordRank;
565
566 if ( (wordRank = get_rank( start, cur )) > 0 )
567 {
568 STORE_RANGE;
569
570 store_range( results, wordRank, int(cur-start) );
571 cur_rank = cur_range_len = 0;
572 continue;
573 }
574
575 cur_range_len += ( cur-start );
576 continue;
577 }
578 else
579 NEXT_CHAR;
580 }
581
582 NEXT_CHAR;
583 }
584
585 if ( cur_range_len > 0 ) STORE_RANGE;
586 }
587
588 /***** Implementation for class SourcePainter ******/
589
590 SourcePainter::SourcePainter( bool assembleResultString )
591 : mCollectResultsOn( assembleResultString ),
592 mIsInComment( FALSE ),
593 mCommentIsMultiline( FALSE )
594 {
595 check_keyword_map(0);
596 }
597
598 void SourcePainter::ProcessSource( char* src, int srcLen )
599 {
600 // TBD:: multilne state...
601
602 heighlight_syntax( src, srcLen, mBlocks, mIsInComment );
603
604 if ( mCollectResultsOn )
605
606 mResultStr += string( src, srcLen );
607 }
608
609 void SourcePainter::SetState( bool isInComment,
610 bool commentIsMultiline )
611 {
612 mIsInComment = isInComment;
613 mCommentIsMultiline = commentIsMultiline;
614 }
615
616 void SourcePainter::Init(bool assembleResultString)
617 {
618 mIsInComment = 0;
619 mCommentIsMultiline = 0;
620 mCollectResultsOn = assembleResultString;
621
622 mResultStr = "";
623
624 mBlocks.erase( mBlocks.begin(), mBlocks.end() );
625 }
626
627 static int rank_tags_map[] =
628 {
629 TAG_BLACK_FONT,
630 TAG_BLUE_FONT,
631 TAG_RED_FONT,
632 TAG_GREEN_FONT
633 };
634
635 void SourcePainter::GetResultString(string& result, MarkupTagsT tags)
636 {
637 // this method works, only if results of processing
638 // are collected
639 // ASSERT( mCollectResultsOn );
640 result = "";
641
642 int pos = 0;
643
644 for( size_t i = 0; i != mBlocks.size(); ++i )
645 {
646 int desc = mBlocks[i];
647
648 int len = desc & 0xFFFF;
649 int rank = (desc >> 16) & 0xFFFF;
650
651 result += tags[ rank_tags_map[rank] ].start;
652
653 for( int n = 0; n != len; ++n )
654
655 result += mResultStr[pos+n];
656
657 pos += len;
658
659 result += tags[ rank_tags_map[rank] ].end;
660 }
661 }
662
663 SPBlockListT& SourcePainter::GetBlocks()
664 {
665 return mBlocks;
666 }
667
668 bool SourcePainter::IsKeyword( char* word, int wordLen )
669 {
670 check_keyword_map(0);
671
672 int rank = get_rank( word, word + wordLen );
673
674 return ( rank == RANK_BLUE || rank == RANK_RED );
675 }