summaryrefslogtreecommitdiff
path: root/noncore/apps/tinykate/libkate/document/katehighlight.cpp
Unidiff
Diffstat (limited to 'noncore/apps/tinykate/libkate/document/katehighlight.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/tinykate/libkate/document/katehighlight.cpp1459
1 files changed, 1459 insertions, 0 deletions
diff --git a/noncore/apps/tinykate/libkate/document/katehighlight.cpp b/noncore/apps/tinykate/libkate/document/katehighlight.cpp
new file mode 100644
index 0000000..797968b
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katehighlight.cpp
@@ -0,0 +1,1459 @@
1/*
2 Copyright (C) 1998, 1999 Jochen Wilhelmy
3 digisnap@cs.tu-berlin.de
4 (C) 2002, 2001 The Kate Team <kwrite-devel@kde.org>
5 (C) 2002 Joseph Wenninger <jowenn@kde.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20*/
21
22#include <string.h>
23
24#include <qtextstream.h>
25#include <qpe/config.h>
26#include <kglobal.h>
27//#include <kinstance.h>
28//#include <kmimemagic.h>
29#include <klocale.h>
30//#include <kregexp.h>
31#include <kglobalsettings.h>
32#include <kdebug.h>
33#include <kstddirs.h>
34
35#include "katehighlight.h"
36
37
38#include "katetextline.h"
39#include "katedocument.h"
40#include "katesyntaxdocument.h"
41
42
43HlManager *HlManager::s_pSelf = 0;
44
45enum Item_styles { dsNormal,dsKeyword,dsDataType,dsDecVal,dsBaseN,dsFloat,dsChar,dsString,dsComment,dsOthers};
46
47static bool trueBool = true;
48static QString stdDeliminator = QString ("!%&()*+,-./:;<=>?[]^{|}~ \t\\");
49
50int getDefStyleNum(QString name)
51{
52 if (name=="dsNormal") return dsNormal;
53 if (name=="dsKeyword") return dsKeyword;
54 if (name=="dsDataType") return dsDataType;
55 if (name=="dsDecVal") return dsDecVal;
56 if (name=="dsBaseN") return dsBaseN;
57 if (name=="dsFloat") return dsFloat;
58 if (name=="dsChar") return dsChar;
59 if (name=="dsString") return dsString;
60 if (name=="dsComment") return dsComment;
61 if (name=="dsOthers") return dsOthers;
62
63 return dsNormal;
64}
65
66bool ustrchr(const QChar *s, uint len, QChar c)
67{
68 for (int z=0; z < len; z++)
69 {
70 if (*s == c) return true;
71 s++;
72 }
73
74 return false;
75}
76
77HlItem::HlItem(int attribute, int context)
78 : attr(attribute), ctx(context) {subItems=0;
79}
80
81HlItem::~HlItem()
82{
83 //kdDebug(13010)<<"In hlItem::~HlItem()"<<endl;
84 if (subItems!=0) {subItems->setAutoDelete(true); subItems->clear(); delete subItems;}
85}
86
87bool HlItem::startEnable(QChar c)
88{
89 return true;
90}
91
92HlCharDetect::HlCharDetect(int attribute, int context, QChar c)
93 : HlItem(attribute,context), sChar(c) {
94}
95
96const QChar *HlCharDetect::checkHgl(const QChar *str, int len, bool) {
97 if (*str == sChar) return str + 1;
98 return 0L;
99}
100
101Hl2CharDetect::Hl2CharDetect(int attribute, int context, QChar ch1, QChar ch2)
102 : HlItem(attribute,context) {
103 sChar1 = ch1;
104 sChar2 = ch2;
105}
106
107const QChar *Hl2CharDetect::checkHgl(const QChar *str, int len, bool) {
108 if (str[0] == sChar1 && str[1] == sChar2) return str + 2;
109 return 0L;
110}
111
112HlStringDetect::HlStringDetect(int attribute, int context, const QString &s, bool inSensitive)
113 : HlItem(attribute, context), str(inSensitive ? s.upper():s), _inSensitive(inSensitive) {
114}
115
116HlStringDetect::~HlStringDetect() {
117}
118
119const QChar *HlStringDetect::checkHgl(const QChar *s, int len, bool) {
120 if (!_inSensitive) {if (memcmp(s, str.unicode(), str.length()*sizeof(QChar)) == 0) return s + str.length();}
121 else
122 {
123 QString tmp=QString(s,str.length()).upper();
124 if (tmp==str) return s+str.length();
125 }
126 return 0L;
127}
128
129
130HlRangeDetect::HlRangeDetect(int attribute, int context, QChar ch1, QChar ch2)
131 : HlItem(attribute,context) {
132 sChar1 = ch1;
133 sChar2 = ch2;
134}
135
136const QChar *HlRangeDetect::checkHgl(const QChar *s, int len, bool) {
137 if (*s == sChar1)
138 {
139 do
140 {
141 s++;
142 len--;
143 if (len == 0) return 0L;
144 }
145 while (*s != sChar2);
146
147 return s + 1;
148 }
149 return 0L;
150}
151
152HlKeyword::HlKeyword (int attribute, int context,bool casesensitive, const QChar *deliminator, uint deliLen)
153 : HlItem(attribute,context), dict (113, casesensitive)
154{
155 deliminatorChars = deliminator;
156 deliminatorLen = deliLen;
157 _caseSensitive=casesensitive;
158}
159
160HlKeyword::~HlKeyword() {
161}
162
163bool HlKeyword::startEnable(QChar c)
164{
165 return ustrchr(deliminatorChars, deliminatorLen, c);
166}
167
168// If we use a dictionary for lookup we don't really need
169// an item as such we are using the key to lookup
170void HlKeyword::addWord(const QString &word)
171{
172 words.append(word);
173 dict.insert(word,&trueBool);
174}
175
176void HlKeyword::addList(const QStringList& list)
177{
178
179 words+=list;
180 for(uint i=0;i<list.count();i++) dict.insert(list[i], &trueBool);
181}
182
183const QChar *HlKeyword::checkHgl(const QChar *s, int len, bool b)
184{
185 if (len == 0) return 0L;
186
187 const QChar *s2 = s;
188
189 while ( (len > 0) && (!ustrchr(deliminatorChars, deliminatorLen, *s2)) )
190 {
191 s2++;
192 len--;
193 }
194
195 if (s2 == s) return 0L;
196
197 QString lookup = QString(s,s2-s);
198
199 if ( dict.find(lookup) ) return s2;
200 return 0L;
201}
202
203HlInt::HlInt(int attribute, int context)
204 : HlItem(attribute,context) {
205}
206
207const QChar *HlInt::checkHgl(const QChar *str, int len, bool) {
208 const QChar *s,*s1;
209
210 s = str;
211 while (s->isDigit()) s++;
212 if (s > str)
213 {
214 if (subItems)
215 {
216 for (HlItem *it=subItems->first();it;it=subItems->next())
217 {
218 s1=it->checkHgl(s, len, false);
219 if (s1) return s1;
220 }
221 }
222 return s;
223 }
224 return 0L;
225}
226
227HlFloat::HlFloat(int attribute, int context)
228 : HlItem(attribute,context) {
229}
230
231const QChar *HlFloat::checkHgl(const QChar *s, int len, bool) {
232 bool b, p;
233 const QChar *s1;
234
235 b = false;
236 while (s->isDigit()){
237 s++;
238 b = true;
239 }
240 if (p = (*s == '.')) {
241 s++;
242 while (s->isDigit()) {
243 s++;
244 b = true;
245 }
246 }
247 if (!b) return 0L;
248 if ((*s&0xdf) == 'E') s++;
249 else
250 if (!p) return 0L;
251 else
252 {
253 if (subItems)
254 {
255 for (HlItem *it=subItems->first();it;it=subItems->next())
256 {
257 s1=it->checkHgl(s, len, false);
258 if (s1) return s1;
259 }
260 }
261 return s;
262 }
263 if ((*s == '-')||(*s =='+')) s++;
264 b = false;
265 while (s->isDigit()) {
266 s++;
267 b = true;
268 }
269 if (b)
270 {
271 if (subItems)
272 {
273 for (HlItem *it=subItems->first();it;it=subItems->next())
274 {
275 s1=it->checkHgl(s, len, false);
276 if (s1) return s1;
277 }
278 }
279 return s;
280 }
281 else return 0L;
282}
283
284
285HlCInt::HlCInt(int attribute, int context)
286 : HlInt(attribute,context) {
287}
288
289const QChar *HlCInt::checkHgl(const QChar *s, int len, bool lineStart) {
290
291// if (*s == '0') s++; else s = HlInt::checkHgl(s);
292 s = HlInt::checkHgl(s, len, lineStart);
293 if (s != 0L) {
294 int l = 0;
295 int u = 0;
296 const QChar *str;
297
298 do {
299 str = s;
300 if ((*s&0xdf) == 'L' ) {
301 l++;
302 if (l > 2) return 0L;
303 s++;
304 }
305 if ((*s&0xdf) == 'U' ){
306 u++;
307 if (u > 1) return 0L;
308 s++;
309 }
310 } while (s != str);
311 }
312 return s;
313}
314
315HlCOct::HlCOct(int attribute, int context)
316 : HlItem(attribute,context) {
317}
318
319const QChar *HlCOct::checkHgl(const QChar *str, int len, bool) {
320 const QChar *s;
321
322 if (*str == '0') {
323 str++;
324 s = str;
325 while (*s >= '0' && *s <= '7') s++;
326 if (s > str) {
327 if ((*s&0xdf) == 'L' || (*s&0xdf) == 'U' ) s++;
328 return s;
329 }
330 }
331 return 0L;
332}
333
334HlCHex::HlCHex(int attribute, int context)
335 : HlItem(attribute,context) {
336}
337
338const QChar *HlCHex::checkHgl(const QChar *str, int len, bool) {
339 const QChar *s=str;
340#if 0
341 int i;
342 for (i=0;(*s)!='\0';s++,i++);
343 QString line(str,i);
344 QRegExp3 rx("0[xX][a-fA-F\\d]+[UuLl]?"); // this matches but is also matching parenthesis
345 int pos=rx.search(line,0);
346 if(pos > -1) return str+rx.matchedLength();
347 else
348 return 0L;
349
350#else
351 if (str[0] == '0' && ((str[1]&0xdf) == 'X' )) {
352 str += 2;
353 s = str;
354 while (s->isDigit() || ((*s&0xdf) >= 'A' && (*s&0xdf) <= 'F') /*|| (*s >= 'a' && *s <= 'f')*/) s++;
355 if (s > str) {
356 if ((*s&0xdf) == 'L' || (*s&0xdf) == 'U' ) s++;
357 return s;
358 }
359 }
360 return 0L;
361#endif
362}
363
364HlCFloat::HlCFloat(int attribute, int context)
365 : HlFloat(attribute,context) {
366}
367
368const QChar *HlCFloat::checkHgl(const QChar *s, int len, bool lineStart) {
369
370 s = HlFloat::checkHgl(s, len, lineStart);
371 if (s && ((*s&0xdf) == 'F' )) s++;
372 return s;
373}
374
375HlAnyChar::HlAnyChar(int attribute, int context, const QChar* charList, uint len)
376 : HlItem(attribute, context) {
377 _charList=charList;
378 _charListLen=len;
379}
380
381const QChar *HlAnyChar::checkHgl(const QChar *s, int len, bool)
382{
383 if (ustrchr(_charList, _charListLen, *s)) return s +1;
384 return 0L;
385}
386
387HlRegExpr::HlRegExpr(int attribute, int context,QString regexp)
388 : HlItem(attribute, context) {
389
390 handlesLinestart=regexp.startsWith("^");
391 if(!handlesLinestart) regexp.prepend("^");
392 Expr=new QRegExp3(regexp);
393}
394
395const QChar *HlRegExpr::checkHgl(const QChar *s, int len, bool lineStart)
396{
397 if ((!lineStart) && handlesLinestart) return 0;
398
399 QString line(s,len);
400 int pos = Expr->search( line, 0 );
401 if (pos==-1) return 0L;
402 else
403 return (s+Expr->matchedLength());
404};
405
406
407HlLineContinue::HlLineContinue(int attribute, int context)
408 : HlItem(attribute,context) {
409}
410
411const QChar *HlLineContinue::checkHgl(const QChar *s, int len, bool) {
412
413 if ((s[0].latin1() == '\\') && (len == 1))
414 {
415 return s + 1;
416 }
417 return 0L;
418}
419
420
421HlCStringChar::HlCStringChar(int attribute, int context)
422 : HlItem(attribute,context) {
423}
424
425//checks for hex and oct (for example \x1b or \033)
426const QChar *checkCharHexOct(const QChar *str) {
427 const QChar *s;
428 s=str;
429 int n;
430 if (*s == 'x') {
431 n = 0;
432 do {
433 s++;
434 n *= 16;
435 if (s->isDigit()) n += *s - '0';
436 else if ((*s&0xdf) >= 'A' && (*s&0xdf) <= 'F') n += (*s&0xdf) - 'A' + 10;
437// else if (*s >= 'a' && *s <= 'f') n += *s - 'a' + 10;
438 else break;
439 if (n >= 256) return 0L;
440 } while (true);
441 if (s - str == 1) return 0L;
442 } else {
443 if (!(*s >= '0' && *s <= '7')) return 0L;
444 n = *s - '0';
445 do {
446 s++;
447 n *= 8;
448 if (*s >= '0' && *s <= '7') n += *s - '0'; else break;
449 if (n >= 256) return s;
450 } while (s - str < 3);
451 }
452 return s;
453}
454// checks for C escaped chars \n and escaped hex/octal chars
455const QChar *checkEscapedChar(const QChar *s, int len) {
456 int i;
457 if (s[0] == '\\' && (len > 1) ) {
458 s++;
459 switch(*s){
460 case 'a': // checks for control chars
461 case 'b': // we want to fall through
462 case 'e':
463 case 'f':
464
465 case 'n':
466 case 'r':
467 case 't':
468 case 'v':
469 case '\'':
470 case '\"':
471 case '?' : // added ? ANSI C classifies this as an escaped char
472 case '\\': s++;
473 break;
474 case 'x': // if it's like \xff
475 s++; // eat the x
476 // these for loops can probably be
477 // replaced with something else but
478 // for right now they work
479 // check for hexdigits
480 for(i=0;i<2 &&(*s >= '0' && *s <= '9' || (*s&0xdf) >= 'A' && (*s&0xdf) <= 'F');i++,s++);
481 if(i==0) return 0L; // takes care of case '\x'
482 break;
483
484 case '0': case '1': case '2': case '3' :
485 case '4': case '5': case '6': case '7' :
486 for(i=0;i < 3 &&(*s >='0'&& *s<='7');i++,s++);
487 break;
488 default: return 0L;
489 }
490 return s;
491 }
492 return 0L;
493}
494
495const QChar *HlCStringChar::checkHgl(const QChar *str, int len, bool) {
496 return checkEscapedChar(str, len);
497}
498
499
500HlCChar::HlCChar(int attribute, int context)
501 : HlItem(attribute,context) {
502}
503
504const QChar *HlCChar::checkHgl(const QChar *str, int len, bool) {
505 const QChar *s;
506
507 if ((len > 1) && (str[0] == '\'') && (str[1] != '\''))
508 {
509 s = checkEscapedChar(&str[1], len); //try to match escaped char
510 if (!s) s = &str[2]; //match single non-escaped char
511 if (*s == '\'') return s + 1;
512 }
513 return 0L;
514}
515
516
517//--------
518ItemStyle::ItemStyle() : selCol(Qt::white), bold(false), italic(false) {
519}
520
521ItemStyle::ItemStyle(const QColor &col, const QColor &selCol,
522 bool bold, bool italic)
523 : col(col), selCol(selCol), bold(bold), italic(italic) {
524}
525
526ItemData::ItemData(const QString name, int defStyleNum)
527 : name(name), defStyleNum(defStyleNum), defStyle(true) {
528}
529
530ItemData::ItemData(const QString name, int defStyleNum,
531 const QColor &col, const QColor &selCol, bool bold, bool italic)
532 : ItemStyle(col,selCol,bold,italic), name(name), defStyleNum(defStyleNum),
533 defStyle(false) {
534}
535
536HlData::HlData(const QString &wildcards, const QString &mimetypes, const QString &identifier)
537 : wildcards(wildcards), mimetypes(mimetypes), identifier(identifier) {
538
539//JW itemDataList.setAutoDelete(true);
540}
541
542HlContext::HlContext(int attribute, int lineEndContext, int _lineBeginContext)
543 : attr(attribute), ctx(lineEndContext),lineBeginContext(_lineBeginContext) {
544 items.setAutoDelete(true);
545}
546
547Hl2CharDetect::Hl2CharDetect(int attribute, int context, const QChar *s)
548 : HlItem(attribute,context) {
549 sChar1 = s[0];
550 sChar2 = s[1];
551}
552
553Highlight::Highlight(syntaxModeListItem *def) : refCount(0)
554{
555 noHl = false;
556
557 if (def == 0)
558 {
559 noHl = true;
560 iName = I18N_NOOP("Normal");
561 iSection = "";
562 }
563 else
564 {
565 iName = def->name;
566 iSection = def->section;
567 iWildcards = def->extension;
568 iMimetypes = def->mimetype;
569 identifier = def->identifier;
570 }
571 deliminator = stdDeliminator;
572 deliminatorChars = deliminator.unicode();
573 deliminatorLen = deliminator.length();
574}
575
576Highlight::~Highlight()
577{
578}
579
580int Highlight::doHighlight(int ctxNum, TextLine *textLine)
581{
582 if (noHl)
583 {
584 textLine->setAttribs(0,0,textLine->length());
585 textLine->setAttr(0);
586 return 0;
587 }
588
589 HlContext *context;
590 const QChar *s2;
591 HlItem *item;
592
593 context = contextList[ctxNum];
594 if (context->lineBeginContext!=-1)
595 {
596 ctxNum=context->lineBeginContext;
597 context=contextList[ctxNum];
598 }
599
600 QChar lastChar = ' ';
601
602 // first char
603 const QChar *str = textLine->getText();
604
605 // non space char - index of that char
606 const QChar *s1 = textLine->firstNonSpace();
607 uint z = textLine->firstChar();
608
609 // length of textline
610 uint len = textLine->length();
611
612 bool found = false;
613 while (z < len)
614 {
615 found = false;
616
617 for (item = context->items.first(); item != 0L; item = context->items.next())
618 {
619 if (item->startEnable(lastChar))
620 {
621 s2 = item->checkHgl(s1, len-z, z==0);
622 if (s2 > s1)
623 {
624 qDebug("An item has been detected");
625 textLine->setAttribs(item->attr,s1 - str,s2 - str);
626 ctxNum = item->ctx;
627 context = contextList[ctxNum];
628 z = z + s2 - s1 - 1;
629 s1 = s2 - 1;
630 found = true;
631 break;
632 }
633 }
634 }
635
636 // nothing found: set attribute of one char
637 if (!found)
638 textLine->setAttribs(context->attr,s1 - str,s1 - str + 1);
639
640 lastChar = *s1;
641 s1++;
642 z++;
643 }
644
645 //set "end of line"-properties
646 textLine->setAttr(context->attr);
647
648 //return new context
649 return context->ctx;
650}
651
652KConfig *Highlight::getKConfig() {
653 KConfig *config;
654 config=KGlobal::config();
655 config->setGroup(iName + QString(" Highlight"));
656 return config;
657}
658
659QString Highlight::getWildcards() {
660 KConfig *config;
661
662 config = getKConfig();
663
664 //if wildcards not yet in config, then use iWildCards as default
665 return config->readEntry("Wildcards", iWildcards);
666}
667
668
669QString Highlight::getMimetypes() {
670 KConfig *config;
671
672 config = getKConfig();
673
674 return config->readEntry("Mimetypes", iMimetypes);
675}
676
677
678HlData *Highlight::getData() {
679 KConfig *config;
680 HlData *hlData;
681
682 config = getKConfig();
683
684// iWildcards = config->readEntry("Wildcards");
685// iMimetypes = config->readEntry("Mimetypes");
686// hlData = new HlData(iWildcards,iMimetypes);
687 hlData = new HlData(
688 config->readEntry("Wildcards", iWildcards),
689 config->readEntry("Mimetypes", iMimetypes),
690 config->readEntry("Identifier", identifier));
691 getItemDataList(hlData->itemDataList, config);
692 return hlData;
693}
694
695void Highlight::setData(HlData *hlData) {
696 KConfig *config;
697
698 config = getKConfig();
699
700// iWildcards = hlData->wildcards;
701// iMimetypes = hlData->mimetypes;
702
703 config->writeEntry("Wildcards",hlData->wildcards);
704 config->writeEntry("Mimetypes",hlData->mimetypes);
705
706 setItemDataList(hlData->itemDataList,config);
707}
708
709void Highlight::getItemDataList(ItemDataList &list) {
710 KConfig *config;
711
712 config = getKConfig();
713 getItemDataList(list, config);
714}
715
716void Highlight::getItemDataList(ItemDataList &list, KConfig *config) {
717 ItemData *p;
718 QString s;
719 QRgb col, selCol;
720
721 list.clear();
722//JW list.setAutoDelete(true);
723 createItemData(list);
724
725 for (p = list.first(); p != 0L; p = list.next()) {
726 s = config->readEntry(p->name);
727 if (!s.isEmpty()) {
728 sscanf(s.latin1(),"%d,%X,%X,%d,%d", &p->defStyle,&col,&selCol,&p->bold,&p->italic);
729 p->col.setRgb(col);
730 p->selCol.setRgb(selCol);
731 }
732 }
733}
734
735/*******************************************************************************************
736 Highlight - setItemDataList
737 saves the ItemData / attribute / style definitions to the apps configfile.
738 Especially needed for user overridden values.
739
740 * input: ItemDataList &list :reference to the list, whose
741 * items should be saved
742 * KConfig *config :Pointer KDE configuration
743 * class, which should be used
744 * as storage
745 *************
746 * output: none
747 *************
748 * return value: none
749*******************************************************************************************/
750
751void Highlight::setItemDataList(ItemDataList &list, KConfig *config) {
752 ItemData *p;
753 QString s;
754
755 for (p = list.first(); p != 0L; p = list.next()) {
756 s.sprintf("%d,%X,%X,%d,%d",
757 p->defStyle,p->col.rgb(),p->selCol.rgb(),p->bold,p->italic);
758 config->writeEntry(p->name,s);
759 }
760}
761
762
763/*******************************************************************************************
764 Highlight - use
765 Increase the usage count and trigger initialization if needed
766
767 * input: none
768 *************
769 * output: none
770 *************
771 * return value: none
772*******************************************************************************************/
773
774void Highlight::use()
775{
776 if (refCount == 0) init();
777 refCount++;
778}
779
780
781/*******************************************************************************************
782 Highlight - release
783 Decrease the usage count and trigger a cleanup if needed
784
785 * input: none
786 *************
787 * output: none
788 *************
789 * return value: none
790*******************************************************************************************/
791
792void Highlight::release()
793{
794 refCount--;
795 if (refCount == 0) done();
796}
797
798/*******************************************************************************************
799 Highlight - init
800 If it's the first time a particular highlighting is used create the needed contextlist
801
802 * input: none
803 *************
804 * output: none
805 *************
806 * return value: none
807*******************************************************************************************/
808
809void Highlight::init()
810{
811 if (noHl)
812 return;
813
814 for (int z = 0; z < nContexts; z++) contextList[z] = 0L;
815 makeContextList();
816}
817
818
819/*******************************************************************************************
820 Highlight - done
821 If the there is no document using the highlighting style free the complete context
822 structure.
823
824 * input: none
825 *************
826 * output: none
827 *************
828 * return value: none
829*******************************************************************************************/
830
831void Highlight::done()
832{
833 if (noHl)
834 return;
835
836 for (int z = 0; z < nContexts; z++) delete contextList[z];
837}
838
839
840/*******************************************************************************************
841 Highlight - createItemData
842 This function reads the itemData entries from the config file, which specifies the
843 default attribute styles for matched items/contexts.
844
845 * input: none
846 *************
847 * output: ItemDataList &list :A reference to the internal
848 list containing the parsed
849 default config
850 *************
851 * return value: none
852*******************************************************************************************/
853
854void Highlight::createItemData(ItemDataList &list)
855{
856 qDebug("Highlight::createItemData");
857
858 // If no highlighting is selected we need only one default.
859 if (noHl)
860 {
861 list.append(new ItemData(I18N_NOOP("Normal Text"), dsNormal));
862 return;
863 }
864
865 QString color;
866 QString selColor;
867 QString bold;
868 QString italic;
869
870 // If the internal list isn't already available read the config file
871 if (internalIDList.count()==0)
872 {
873 //if all references to the list are destried the contents will also be deleted
874 internalIDList.setAutoDelete(true);
875 syntaxContextData *data;
876
877 qDebug("Trying to read itemData section");
878
879 //Tell the syntax document class which file we want to parse and which data group
880 HlManager::self()->syntax->setIdentifier(identifier);
881 data=HlManager::self()->syntax->getGroupInfo("highlighting","itemData");
882 //begin with the real parsing
883 while (HlManager::self()->syntax->nextGroup(data))
884 {
885 qDebug("Setting up one itemData element");
886 // read all attributes
887 color=HlManager::self()->syntax->groupData(data,QString("color"));
888 selColor=HlManager::self()->syntax->groupData(data,QString("selColor"));
889 bold=HlManager::self()->syntax->groupData(data,QString("bold"));
890 italic=HlManager::self()->syntax->groupData(data,QString("italic"));
891 //check if the user overrides something
892 if ( (!color.isEmpty()) && (!selColor.isEmpty()) && (!bold.isEmpty()) && (!italic.isEmpty()))
893 {
894 //create a user defined style
895 internalIDList.append(new ItemData(
896 HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(),
897 getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum"))),
898 QColor(color),QColor(selColor),(bold=="true") || (bold=="1"), (italic=="true") || (italic=="1")
899 ));
900 }
901 else
902 {
903 //assign a default style
904 internalIDList.append(new ItemData(
905 HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(),
906 getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum")))));
907
908 }
909 }
910 //clean up
911 if (data) HlManager::self()->syntax->freeGroupInfo(data);
912 }
913
914 //set the ouput reference
915 list=internalIDList;
916}
917
918
919/*******************************************************************************************
920 Highlight - lookupAttrName
921 This function is a helper for makeContextList and createHlItem. It looks the given
922 attribute name in the itemData list up and returns it's index
923
924 * input: QString &name :the attribute name to lookup
925 * ItemDataList &iDl :the list containing all
926 * available attributes
927 *************
928 * output: none
929 *************
930 * return value: int :The index of the attribute
931 * or 0
932*******************************************************************************************/
933
934int Highlight::lookupAttrName(const QString& name, ItemDataList &iDl)
935{
936 for (int i=0;i<iDl.count();i++)
937 {
938 if (iDl.at(i)->name==name) return i;
939 }
940 kdDebug(13010)<<"Couldn't resolve itemDataName"<<endl;
941 return 0;
942}
943
944
945/*******************************************************************************************
946 Highlight - createHlItem
947 This function is a helper for makeContextList. It parses the xml file for
948 information, how single or multi line comments are marked
949
950 * input: syntaxContextData *data : Data about the item read from
951 * the xml file
952 * ItemDataList &iDl : List of all available itemData
953 * entries. Needed for attribute
954 * name->index translation
955 *************
956 * output: none
957 *************
958 * return value: HlItem * : Pointer to the newly created item
959 * object
960*******************************************************************************************/
961
962HlItem *Highlight::createHlItem(syntaxContextData *data, ItemDataList &iDl)
963{
964 // No highlighting -> exit
965 if (noHl)
966 return 0;
967
968 // get the (tagname) itemd type
969 QString dataname=HlManager::self()->syntax->groupItemData(data,QString(""));
970
971 // BEGIN - Translation of the attribute parameter
972 QString tmpAttr=HlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace();
973 int attr;
974 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
975 attr=tmpAttr.toInt();
976 else
977 attr=lookupAttrName(tmpAttr,iDl);
978 // END - Translation of the attribute parameter
979
980 // Info about context switch
981 int context=((HlManager::self()->syntax->groupItemData(data,QString("context"))).toInt());
982
983 // Get the char parameter (eg DetectChar)
984 char chr;
985 if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty())
986 chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0];
987 else
988 chr=0;
989
990 // Get the String parameter (eg. StringDetect)
991 QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String"));
992
993 // Get a second char parameter (char1) (eg Detect2Chars)
994 char chr1;
995 if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty())
996 chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0];
997 else
998 chr1=0;
999
1000 // Will be removed eventuall. Atm used for StringDetect
1001 bool insensitive=(HlManager::self()->syntax->groupItemData(data,QString("insensitive"))==QString("TRUE"));
1002
1003
1004 //Create the item corresponding to it's type and set it's parameters
1005 if (dataname=="keyword")
1006 {
1007 HlKeyword *keyword=new HlKeyword(attr,context,casesensitive,
1008 deliminatorChars, deliminatorLen);
1009
1010 //Get the entries for the keyword lookup list
1011 keyword->addList(HlManager::self()->syntax->finddata("highlighting",stringdata));
1012 return keyword;
1013 } else
1014 if (dataname=="Float") return (new HlFloat(attr,context)); else
1015 if (dataname=="Int") return(new HlInt(attr,context)); else
1016 if (dataname=="DetectChar") return(new HlCharDetect(attr,context,chr)); else
1017 if (dataname=="Detect2Chars") return(new Hl2CharDetect(attr,context,chr,chr1)); else
1018 if (dataname=="RangeDetect") return(new HlRangeDetect(attr,context, chr, chr1)); else
1019 if (dataname=="LineContinue") return(new HlLineContinue(attr,context)); else
1020 if (dataname=="StringDetect") return(new HlStringDetect(attr,context,stringdata,insensitive)); else
1021 if (dataname=="AnyChar") return(new HlAnyChar(attr,context,stringdata.unicode(), stringdata.length())); else
1022 if (dataname=="RegExpr") return(new HlRegExpr(attr,context,stringdata)); else
1023 if(dataname=="HlCChar") return ( new HlCChar(attr,context));else
1024 if(dataname=="HlCHex") return (new HlCHex(attr,context));else
1025 if(dataname=="HlCOct") return (new HlCOct(attr,context)); else
1026 if(dataname=="HlCStringChar") return (new HlCStringChar(attr,context)); else
1027
1028 {
1029 // oops, unknown type. Perhaps a spelling error in the xml file
1030 return 0;
1031 }
1032
1033
1034}
1035
1036
1037/*******************************************************************************************
1038 Highlight - isInWord
1039
1040 * input: Qchar c Character to investigate
1041 *************
1042 * output: none
1043 *************
1044 * return value: returns true, if c is no deliminator
1045*******************************************************************************************/
1046
1047bool Highlight::isInWord(QChar c)
1048{
1049 return !ustrchr(deliminatorChars, deliminatorLen, c);
1050}
1051
1052
1053
1054/*******************************************************************************************
1055 Highlight - readCommentConfig
1056 This function is a helper for makeContextList. It parses the xml file for
1057 information, how single or multi line comments are marked
1058
1059 * input: none
1060 *************
1061 * output: none
1062 *************
1063 * return value: none
1064*******************************************************************************************/
1065
1066void Highlight::readCommentConfig()
1067{
1068
1069 cslStart = "";
1070 HlManager::self()->syntax->setIdentifier(identifier);
1071
1072 syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("general","comment");
1073 if (data)
1074 {
1075// kdDebug(13010)<<"COMMENT DATA FOUND"<<endl;
1076 while (HlManager::self()->syntax->nextGroup(data))
1077 {
1078
1079 if (HlManager::self()->syntax->groupData(data,"name")=="singleLine")
1080 cslStart=HlManager::self()->syntax->groupData(data,"start");
1081 if (HlManager::self()->syntax->groupData(data,"name")=="multiLine")
1082 {
1083 cmlStart=HlManager::self()->syntax->groupData(data,"start");
1084 cmlEnd=HlManager::self()->syntax->groupData(data,"end");
1085 }
1086 }
1087 HlManager::self()->syntax->freeGroupInfo(data);
1088 }
1089
1090}
1091
1092/*******************************************************************************************
1093 Highlight - readGlobalKeyWordConfig
1094 This function is a helper for makeContextList. It parses the xml file for
1095 information, if keywords should be treated case(in)sensitive and creates the keyword
1096 delimiter list. Which is the default list, without any given weak deliminiators
1097
1098 * input: none
1099 *************
1100 * output: none
1101 *************
1102 * return value: none
1103*******************************************************************************************/
1104
1105
1106void Highlight::readGlobalKeywordConfig()
1107{
1108 // Tell the syntax document class which file we want to parse
1109 HlManager::self()->syntax->setIdentifier(identifier);
1110
1111 // Get the keywords config entry
1112 syntaxContextData * data=HlManager::self()->syntax->getConfig("general","keywords");
1113 if (data)
1114 {
1115 kdDebug(13010)<<"Found global keyword config"<<endl;
1116
1117 if (HlManager::self()->syntax->groupItemData(data,QString("casesensitive"))!="0")
1118 casesensitive=true; else {casesensitive=false; kdDebug(13010)<<"Turning on case insensitiveness"<<endl;}
1119 //get the weak deliminators
1120 weakDeliminator=(!HlManager::self()->syntax->groupItemData(data,QString("weakDeliminator")));
1121
1122 // remove any weakDelimitars (if any) from the default list and store this list.
1123 int f;
1124 for (int s=0; s < weakDeliminator.length(); s++)
1125 {
1126 f = 0;
1127 f = deliminator.find (weakDeliminator[s]);
1128
1129 if (f > -1)
1130 deliminator.remove (f, 1);
1131 }
1132
1133 deliminatorChars = deliminator.unicode();
1134 deliminatorLen = deliminator.length();
1135
1136 HlManager::self()->syntax->freeGroupInfo(data);
1137 }
1138 else
1139 {
1140 //Default values
1141 casesensitive=true;
1142 weakDeliminator=QString("");
1143 }
1144
1145}
1146
1147/*******************************************************************************************
1148 Highlight - makeContextList
1149 That's the most important initialization function for each highlighting. It's called
1150 each time a document gets a highlighting style assigned. parses the xml file and
1151 creates a corresponding internal structure
1152
1153 * input: none
1154 *************
1155 * output: none
1156 *************
1157 * return value: none
1158*******************************************************************************************/
1159
1160
1161void Highlight::makeContextList()
1162{
1163 if (noHl)
1164 return;
1165
1166 HlKeyword *keyword=0, *dataType=0;
1167 syntaxContextData *data, *datasub;
1168 HlItem *c;
1169
1170 readCommentConfig();
1171 readGlobalKeywordConfig();
1172
1173 // Let the syntax document class know, which file we'd like to parse
1174 HlManager::self()->syntax->setIdentifier(identifier);
1175
1176 // This list is needed for the translation of the attribute parameter, if the itemData name is given instead of the index
1177 ItemDataList iDl;
1178 createItemData(iDl);
1179
1180 //start the real work
1181 data=HlManager::self()->syntax->getGroupInfo("highlighting","context");
1182 int i=0;
1183 if (data)
1184 {
1185 while (HlManager::self()->syntax->nextGroup(data))
1186 {
1187
1188 // BEGIN - Translation of the attribute parameter
1189 QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace();
1190 int attr;
1191 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
1192 attr=tmpAttr.toInt();
1193 else
1194 attr=lookupAttrName(tmpAttr,iDl);
1195 // END - Translation of the attribute parameter
1196
1197 contextList[i]=new HlContext(
1198 attr,
1199 (HlManager::self()->syntax->groupData(data,QString("lineEndContext"))).toInt(),
1200 (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1:
1201 (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt());
1202
1203
1204 //Let's create all items for the context
1205 while (HlManager::self()->syntax->nextItem(data))
1206 {
1207 // kdDebug(13010)<< "In make Contextlist: Item:"<<endl;
1208 c=createHlItem(data,iDl);
1209 if (c)
1210 {
1211 contextList[i]->items.append(c);
1212
1213 // Not supported completely atm and only one level. Subitems.(all have to be matched to at once)
1214 datasub=HlManager::self()->syntax->getSubItems(data);
1215 bool tmpbool;
1216 if (tmpbool=HlManager::self()->syntax->nextItem(datasub))
1217 {
1218 c->subItems=new QList<HlItem>;
1219 for (;tmpbool;tmpbool=HlManager::self()->syntax->nextItem(datasub))
1220 c->subItems->append(createHlItem(datasub,iDl));
1221 }
1222 HlManager::self()->syntax->freeGroupInfo(datasub);
1223 // end of sublevel
1224 }
1225 // kdDebug(13010)<<"Last line in loop"<<endl;
1226 }
1227 i++;
1228 }
1229 }
1230
1231 HlManager::self()->syntax->freeGroupInfo(data);
1232
1233
1234}
1235
1236HlManager::HlManager() : QObject(0L)
1237{
1238 syntax = new SyntaxDocument();
1239 SyntaxModeList modeList = syntax->modeList();
1240
1241 hlList.setAutoDelete(true);
1242 hlList.append(new Highlight(0));
1243
1244 uint i=0;
1245 while (i < modeList.count())
1246 {
1247 hlList.append(new Highlight(modeList.at(i)));
1248 i++;
1249 }
1250}
1251
1252HlManager::~HlManager() {
1253 if(syntax) delete syntax;
1254}
1255
1256HlManager *HlManager::self()
1257{
1258 if ( !s_pSelf )
1259 s_pSelf = new HlManager;
1260 return s_pSelf;
1261}
1262
1263Highlight *HlManager::getHl(int n) {
1264 if (n < 0 || n >= (int) hlList.count()) n = 0;
1265 return hlList.at(n);
1266}
1267
1268int HlManager::defaultHl() {
1269 KConfig *config;
1270 config = KGlobal::config();
1271 config->setGroup("General Options");
1272
1273#warning fixme return nameFind(config->readEntry("Highlight"));
1274
1275}
1276
1277
1278int HlManager::nameFind(const QString &name) {
1279 int z;
1280
1281 for (z = hlList.count() - 1; z > 0; z--) {
1282 if (hlList.at(z)->iName == name) break;
1283 }
1284 return z;
1285}
1286
1287int HlManager::wildcardFind(const QString &fileName) {
1288 Highlight *highlight;
1289 int p1, p2;
1290 QString w;
1291 for (highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) {
1292 p1 = 0;
1293 w = highlight->getWildcards();
1294 while (p1 < (int) w.length()) {
1295 p2 = w.find(';',p1);
1296 if (p2 == -1) p2 = w.length();
1297 if (p1 < p2) {
1298 QRegExp regExp(w.mid(p1,p2 - p1),true,true);
1299 if (regExp.match(fileName) == 0) return hlList.at();
1300 }
1301 p1 = p2 + 1;
1302 }
1303 }
1304 return -1;
1305}
1306
1307
1308int HlManager::makeAttribs(Highlight *highlight, Attribute *a, int maxAttribs) {
1309 ItemStyleList defaultStyleList;
1310 ItemStyle *defaultStyle;
1311 ItemDataList itemDataList;
1312 ItemData *itemData;
1313 int nAttribs, z;
1314
1315 qDebug("HlManager::makeAttribs");
1316
1317 defaultStyleList.setAutoDelete(true);
1318 getDefaults(defaultStyleList);
1319
1320// itemDataList.setAutoDelete(true);
1321 highlight->getItemDataList(itemDataList);
1322 nAttribs = itemDataList.count();
1323 for (z = 0; z < nAttribs; z++) {
1324 qDebug("HlManager::makeAttribs: createing one attribute definition");
1325 itemData = itemDataList.at(z);
1326 if (itemData->defStyle) {
1327 // default style
1328 defaultStyle = defaultStyleList.at(itemData->defStyleNum);
1329 a[z].col = defaultStyle->col;
1330 a[z].selCol = defaultStyle->selCol;
1331 a[z].bold = defaultStyle->bold;
1332 a[z].italic = defaultStyle->italic;
1333 } else {
1334 // custom style
1335 a[z].col = itemData->col;
1336 a[z].selCol = itemData->selCol;
1337 a[z].bold = itemData->bold;
1338 a[z].italic = itemData->italic;
1339 }
1340 }
1341
1342 for (; z < maxAttribs; z++) {
1343 a[z].col = black;
1344 a[z].selCol = black;
1345 a[z].bold = defaultStyle->bold;
1346 a[z].italic = defaultStyle->italic;
1347 }
1348 return nAttribs;
1349}
1350
1351int HlManager::defaultStyles() {
1352 return 10;
1353}
1354
1355QString HlManager::defaultStyleName(int n)
1356{
1357 static QStringList names;
1358
1359 if (names.isEmpty())
1360 {
1361 names << i18n("Normal");
1362 names << i18n("Keyword");
1363 names << i18n("Data Type");
1364 names << i18n("Decimal/Value");
1365 names << i18n("Base-N Integer");
1366 names << i18n("Floating Point");
1367 names << i18n("Character");
1368 names << i18n("String");
1369 names << i18n("Comment");
1370 names << i18n("Others");
1371 }
1372
1373 return names[n];
1374}
1375
1376void HlManager::getDefaults(ItemStyleList &list) {
1377 KConfig *config;
1378 int z;
1379 ItemStyle *i;
1380 QString s;
1381 QRgb col, selCol;
1382
1383 list.setAutoDelete(true);
1384 //ItemStyle(color, selected color, bold, italic)
1385 list.append(new ItemStyle(black,white,false,false)); //normal
1386 list.append(new ItemStyle(black,white,true,false)); //keyword
1387 list.append(new ItemStyle(darkRed,white,false,false)); //datatype
1388 list.append(new ItemStyle(blue,cyan,false,false)); //decimal/value
1389 list.append(new ItemStyle(darkCyan,cyan,false,false)); //base n
1390 list.append(new ItemStyle(darkMagenta,cyan,false,false));//float
1391 list.append(new ItemStyle(magenta,magenta,false,false)); //char
1392 list.append(new ItemStyle(red,red,false,false)); //string
1393 list.append(new ItemStyle(darkGray,gray,false,true)); //comment
1394 list.append(new ItemStyle(darkGreen,green,false,false)); //others
1395
1396#warning fixme
1397/*
1398 config = KateFactory::instance()->config();
1399 config->setGroup("Default Item Styles");
1400 for (z = 0; z < defaultStyles(); z++) {
1401 i = list.at(z);
1402 s = config->readEntry(defaultStyleName(z));
1403 if (!s.isEmpty()) {
1404 sscanf(s.latin1(),"%X,%X,%d,%d",&col,&selCol,&i->bold,&i->italic);
1405 i->col.setRgb(col);
1406 i->selCol.setRgb(selCol);
1407 }
1408 }
1409*/
1410}
1411
1412void HlManager::setDefaults(ItemStyleList &list) {
1413 KConfig *config;
1414 int z;
1415 ItemStyle *i;
1416 char s[64];
1417#warning fixme
1418/*
1419 config = KateFactory::instance()->config();
1420 config->setGroup("Default Item Styles");
1421 for (z = 0; z < defaultStyles(); z++) {
1422 i = list.at(z);
1423 sprintf(s,"%X,%X,%d,%d",i->col.rgb(),i->selCol.rgb(),i->bold, i->italic);
1424 config->writeEntry(defaultStyleName(z),s);
1425 }
1426*/
1427 emit changed();
1428}
1429
1430
1431int HlManager::highlights() {
1432 return (int) hlList.count();
1433}
1434
1435QString HlManager::hlName(int n) {
1436 return hlList.at(n)->iName;
1437}
1438
1439QString HlManager::hlSection(int n) {
1440 return hlList.at(n)->iSection;
1441}
1442
1443void HlManager::getHlDataList(HlDataList &list) {
1444 int z;
1445
1446 for (z = 0; z < (int) hlList.count(); z++) {
1447 list.append(hlList.at(z)->getData());
1448 }
1449}
1450
1451void HlManager::setHlDataList(HlDataList &list) {
1452 int z;
1453
1454 for (z = 0; z < (int) hlList.count(); z++) {
1455 hlList.at(z)->setData(list.at(z));
1456 }
1457 //notify documents about changes in highlight configuration
1458 emit changed();
1459}