00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "katehighlight.h"
00024 #include "katehighlight.moc"
00025
00026 #include "katetextline.h"
00027 #include "katedocument.h"
00028 #include "katesyntaxdocument.h"
00029 #include "katerenderer.h"
00030 #include "katefactory.h"
00031 #include "kateschema.h"
00032 #include "kateconfig.h"
00033
00034 #include <kconfig.h>
00035 #include <kglobal.h>
00036 #include <kinstance.h>
00037 #include <kmimetype.h>
00038 #include <klocale.h>
00039 #include <kregexp.h>
00040 #include <kpopupmenu.h>
00041 #include <kglobalsettings.h>
00042 #include <kdebug.h>
00043 #include <kstandarddirs.h>
00044 #include <kmessagebox.h>
00045 #include <kstaticdeleter.h>
00046 #include <kapplication.h>
00047
00048 #include <qstringlist.h>
00049 #include <qtextstream.h>
00050
00051
00052
00053 #define KATE_HL_HOWMANY 1024
00054
00055
00056
00057 class HlItem
00058 {
00059 public:
00060 HlItem(int attribute, int context,signed char regionId, signed char regionId2);
00061 virtual ~HlItem();
00062
00063 public:
00064 virtual bool alwaysStartEnable() const { return true; };
00065 virtual bool hasCustomStartEnable() const { return false; };
00066 virtual bool startEnable(const QChar&);
00067
00068
00069
00070
00071
00072 virtual int checkHgl(const QString& text, int offset, int len) = 0;
00073
00074 virtual bool lineContinue(){return false;}
00075
00076 QPtrList<HlItem> *subItems;
00077 int attr;
00078 int ctx;
00079 signed char region;
00080 signed char region2;
00081 };
00082
00083 class HlContext
00084 {
00085 public:
00086 HlContext (int attribute, int lineEndContext,int _lineBeginContext,
00087 bool _fallthrough, int _fallthroughContext);
00088
00089 QPtrList<HlItem> items;
00090 int attr;
00091 int ctx;
00092 int lineBeginContext;
00098 bool fallthrough;
00099 int ftctx;
00100 };
00101
00102 class EmbeddedHlInfo
00103 {
00104 public:
00105 EmbeddedHlInfo() {loaded=false;context0=-1;}
00106 EmbeddedHlInfo(bool l, int ctx0) {loaded=l;context0=ctx0;}
00107
00108 public:
00109 bool loaded;
00110 int context0;
00111 };
00112
00113 class IncludeRule
00114 {
00115 public:
00116 IncludeRule(int ctx_, uint pos_, const QString &incCtxN_) {ctx=ctx_;pos=pos_;incCtxN=incCtxN_;incCtx=-1;}
00117 IncludeRule(int ctx_, uint pos_) {ctx=ctx_;pos=pos_;incCtx=-1;incCtxN="";}
00118
00119 public:
00120 uint pos;
00121 int ctx;
00122 int incCtx;
00123 QString incCtxN;
00124 };
00125
00126 class HlCharDetect : public HlItem
00127 {
00128 public:
00129 HlCharDetect(int attribute, int context,signed char regionId,signed char regionId2, QChar);
00130 virtual int checkHgl(const QString& text, int offset, int len);
00131
00132 private:
00133 QChar sChar;
00134 };
00135
00136 class Hl2CharDetect : public HlItem
00137 {
00138 public:
00139 Hl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2);
00140 Hl2CharDetect(int attribute, int context,signed char regionId,signed char regionId2, const QChar *ch);
00141
00142 virtual int checkHgl(const QString& text, int offset, int len);
00143
00144 private:
00145 QChar sChar1;
00146 QChar sChar2;
00147 };
00148
00149 class HlStringDetect : public HlItem
00150 {
00151 public:
00152 HlStringDetect(int attribute, int context, signed char regionId,signed char regionId2, const QString &, bool inSensitive=false);
00153
00154 virtual ~HlStringDetect();
00155 virtual int checkHgl(const QString& text, int offset, int len);
00156
00157 private:
00158 const QString str;
00159 bool _inSensitive;
00160 };
00161
00162 class HlRangeDetect : public HlItem
00163 {
00164 public:
00165 HlRangeDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2);
00166
00167 virtual int checkHgl(const QString& text, int offset, int len);
00168
00169 private:
00170 QChar sChar1;
00171 QChar sChar2;
00172 };
00173
00174 class HlKeyword : public HlItem
00175 {
00176 public:
00177 HlKeyword(int attribute, int context,signed char regionId,signed char regionId2, bool casesensitive, const QString& delims);
00178 virtual ~HlKeyword();
00179
00180 virtual void addWord(const QString &);
00181 virtual void addList(const QStringList &);
00182 virtual int checkHgl(const QString& text, int offset, int len);
00183 virtual bool startEnable(const QChar& c);
00184 virtual bool alwaysStartEnable() const;
00185 virtual bool hasCustomStartEnable() const;
00186
00187 private:
00188 QDict<bool> dict;
00189 bool _caseSensitive;
00190 const QString& deliminators;
00191 };
00192
00193 class HlInt : public HlItem
00194 {
00195 public:
00196 HlInt(int attribute, int context, signed char regionId,signed char regionId2);
00197
00198 virtual int checkHgl(const QString& text, int offset, int len);
00199 virtual bool alwaysStartEnable() const;
00200 };
00201
00202 class HlFloat : public HlItem
00203 {
00204 public:
00205 HlFloat(int attribute, int context, signed char regionId,signed char regionId2);
00206
00207 virtual int checkHgl(const QString& text, int offset, int len);
00208 virtual bool alwaysStartEnable() const;
00209 };
00210
00211 class HlCOct : public HlItem
00212 {
00213 public:
00214 HlCOct(int attribute, int context, signed char regionId,signed char regionId2);
00215
00216 virtual int checkHgl(const QString& text, int offset, int len);
00217 virtual bool alwaysStartEnable() const;
00218 };
00219
00220 class HlCHex : public HlItem
00221 {
00222 public:
00223 HlCHex(int attribute, int context, signed char regionId,signed char regionId2);
00224
00225 virtual int checkHgl(const QString& text, int offset, int len);
00226 virtual bool alwaysStartEnable() const;
00227 };
00228
00229 class HlCFloat : public HlFloat
00230 {
00231 public:
00232 HlCFloat(int attribute, int context, signed char regionId,signed char regionId2);
00233
00234 virtual int checkHgl(const QString& text, int offset, int len);
00235 int checkIntHgl(const QString& text, int offset, int len);
00236 virtual bool alwaysStartEnable() const;
00237 };
00238
00239 class HlLineContinue : public HlItem
00240 {
00241 public:
00242 HlLineContinue(int attribute, int context, signed char regionId,signed char regionId2);
00243
00244 virtual bool endEnable(QChar c) {return c == '\0';}
00245 virtual int checkHgl(const QString& text, int offset, int len);
00246 virtual bool lineContinue(){return true;}
00247 };
00248
00249 class HlCStringChar : public HlItem
00250 {
00251 public:
00252 HlCStringChar(int attribute, int context, signed char regionId,signed char regionId2);
00253
00254 virtual int checkHgl(const QString& text, int offset, int len);
00255 };
00256
00257 class HlCChar : public HlItem
00258 {
00259 public:
00260 HlCChar(int attribute, int context,signed char regionId,signed char regionId2);
00261
00262 virtual int checkHgl(const QString& text, int offset, int len);
00263 };
00264
00265 class HlAnyChar : public HlItem
00266 {
00267 public:
00268 HlAnyChar(int attribute, int context, signed char regionId,signed char regionId2, const QString& charList);
00269
00270 virtual int checkHgl(const QString& text, int offset, int len);
00271
00272 private:
00273 const QString _charList;
00274 };
00275
00276 class HlRegExpr : public HlItem
00277 {
00278 public:
00279 HlRegExpr(int attribute, int context,signed char regionId,signed char regionId2 ,QString expr, bool insensitive, bool minimal);
00280 ~HlRegExpr(){delete Expr;};
00281
00282 virtual int checkHgl(const QString& text, int offset, int len);
00283
00284 private:
00285 QRegExp *Expr;
00286 bool handlesLinestart;
00287 };
00288
00289
00290
00291
00292 HlManager *HlManager::s_self = 0;
00293
00294 enum Item_styles { dsNormal,dsKeyword,dsDataType,dsDecVal,dsBaseN,dsFloat,dsChar,dsString,dsComment,dsOthers};
00295
00296 static const bool trueBool = true;
00297 static const QString stdDeliminator = QString (" \t.():!+,-<=>%&*/;?[]^{|}~\\");
00298
00299
00300
00301 static int getDefStyleNum(QString name)
00302 {
00303 if (name=="dsNormal") return dsNormal;
00304 else if (name=="dsKeyword") return dsKeyword;
00305 else if (name=="dsDataType") return dsDataType;
00306 else if (name=="dsDecVal") return dsDecVal;
00307 else if (name=="dsBaseN") return dsBaseN;
00308 else if (name=="dsFloat") return dsFloat;
00309 else if (name=="dsChar") return dsChar;
00310 else if (name=="dsString") return dsString;
00311 else if (name=="dsComment") return dsComment;
00312 else if (name=="dsOthers") return dsOthers;
00313
00314 return dsNormal;
00315 }
00316
00317
00318
00319 HlItem::HlItem(int attribute, int context,signed char regionId,signed char regionId2)
00320 : attr(attribute), ctx(context),region(regionId),region2(regionId2) {subItems=0;
00321 }
00322
00323 HlItem::~HlItem()
00324 {
00325
00326 if (subItems!=0)
00327 {
00328 subItems->setAutoDelete(true);
00329 subItems->clear();
00330 delete subItems;
00331 }
00332 }
00333
00334 bool HlItem::startEnable(const QChar& c)
00335 {
00336
00337
00338 Q_ASSERT(false);
00339 return stdDeliminator.find(c) != -1;
00340 }
00341
00342
00343
00344 HlCharDetect::HlCharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar c)
00345 : HlItem(attribute,context,regionId,regionId2), sChar(c)
00346 {
00347 }
00348
00349 int HlCharDetect::checkHgl(const QString& text, int offset, int len)
00350 {
00351 if (len && text[offset] == sChar)
00352 return offset + 1;
00353
00354 return 0;
00355 }
00356
00357
00358
00359 Hl2CharDetect::Hl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2)
00360 : HlItem(attribute,context,regionId,regionId2)
00361 {
00362 sChar1 = ch1;
00363 sChar2 = ch2;
00364 }
00365
00366 int Hl2CharDetect::checkHgl(const QString& text, int offset, int len)
00367 {
00368 if (len < 2)
00369 return offset;
00370
00371 if (text[offset++] == sChar1 && text[offset++] == sChar2)
00372 return offset;
00373
00374 return 0;
00375 }
00376
00377
00378
00379 HlStringDetect::HlStringDetect(int attribute, int context, signed char regionId,signed char regionId2,const QString &s, bool inSensitive)
00380 : HlItem(attribute, context,regionId,regionId2), str(inSensitive ? s.upper():s), _inSensitive(inSensitive) {
00381 }
00382
00383 HlStringDetect::~HlStringDetect() {
00384 }
00385
00386 int HlStringDetect::checkHgl(const QString& text, int offset, int len)
00387 {
00388 if (len < (int)str.length())
00389 return 0;
00390
00391 if (QConstString(text.unicode() + offset, str.length()).string().find(str, 0, !_inSensitive) == 0)
00392 return offset + str.length();
00393
00394 return 0;
00395 }
00396
00397
00398
00399
00400 HlRangeDetect::HlRangeDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2)
00401 : HlItem(attribute,context,regionId,regionId2) {
00402 sChar1 = ch1;
00403 sChar2 = ch2;
00404 }
00405
00406 int HlRangeDetect::checkHgl(const QString& text, int offset, int len)
00407 {
00408 if ((len > 0) && (text[offset] == sChar1))
00409 {
00410 do
00411 {
00412 offset++;
00413 len--;
00414 if (len < 1) return 0;
00415 }
00416 while (text[offset] != sChar2);
00417
00418 return offset + 1;
00419 }
00420 return 0;
00421 }
00422
00423
00424
00425 HlKeyword::HlKeyword (int attribute, int context, signed char regionId,signed char regionId2, bool casesensitive, const QString& delims)
00426 : HlItem(attribute,context,regionId,regionId2)
00427 , dict (113, casesensitive)
00428 , _caseSensitive(casesensitive)
00429 , deliminators(delims)
00430 {
00431 }
00432
00433 HlKeyword::~HlKeyword() {
00434 }
00435
00436 bool HlKeyword::alwaysStartEnable() const
00437 {
00438 return false;
00439 }
00440
00441 bool HlKeyword::hasCustomStartEnable() const
00442 {
00443 return true;
00444 }
00445
00446 bool HlKeyword::startEnable(const QChar& c)
00447 {
00448 return deliminators.find(c) != -1;
00449 }
00450
00451
00452
00453 void HlKeyword::addWord(const QString &word)
00454 {
00455 dict.insert(word,&trueBool);
00456 }
00457
00458 void HlKeyword::addList(const QStringList& list)
00459 {
00460 for(uint i=0;i<list.count();i++) dict.insert(list[i], &trueBool);
00461 }
00462
00463 int HlKeyword::checkHgl(const QString& text, int offset, int len)
00464 {
00465 if (len == 0 || dict.isEmpty()) return 0;
00466
00467 int offset2 = offset;
00468
00469 while (len > 0 && deliminators.find(text[offset2]) == -1 )
00470 {
00471 offset2++;
00472 len--;
00473 }
00474
00475 if (offset2 == offset) return 0;
00476
00477 if ( dict.find(text.mid(offset, offset2 - offset)) ) return offset2;
00478
00479 return 0;
00480 }
00481
00482
00483
00484 HlInt::HlInt(int attribute, int context, signed char regionId,signed char regionId2)
00485 : HlItem(attribute,context,regionId,regionId2)
00486 {
00487 }
00488
00489 bool HlInt::alwaysStartEnable() const
00490 {
00491 return false;
00492 }
00493
00494 int HlInt::checkHgl(const QString& text, int offset, int len)
00495 {
00496 int offset2 = offset;
00497
00498 while ((len > 0) && text[offset2].isDigit())
00499 {
00500 offset2++;
00501 len--;
00502 }
00503
00504 if (offset2 > offset)
00505 {
00506 if (subItems)
00507 {
00508 for (HlItem *it = subItems->first(); it; it = subItems->next())
00509 {
00510 if ( (offset = it->checkHgl(text, offset2, len)) )
00511 return offset;
00512 }
00513 }
00514
00515 return offset2;
00516 }
00517
00518 return 0;
00519 }
00520
00521
00522
00523 HlFloat::HlFloat(int attribute, int context, signed char regionId,signed char regionId2)
00524 : HlItem(attribute,context, regionId,regionId2) {
00525 }
00526
00527 bool HlFloat::alwaysStartEnable() const
00528 {
00529 return false;
00530 }
00531
00532 int HlFloat::checkHgl(const QString& text, int offset, int len)
00533 {
00534 bool b = false;
00535 bool p = false;
00536
00537 while ((len > 0) && text[offset].isDigit())
00538 {
00539 offset++;
00540 len--;
00541 b = true;
00542 }
00543
00544 if ((len > 0) && (p = (text[offset] == '.')))
00545 {
00546 offset++;
00547 len--;
00548
00549 while ((len > 0) && text[offset].isDigit())
00550 {
00551 offset++;
00552 len--;
00553 b = true;
00554 }
00555 }
00556
00557 if (!b)
00558 return 0;
00559
00560 if ((len > 0) && ((text[offset] & 0xdf) == 'E'))
00561 {
00562 offset++;
00563 len--;
00564 }
00565 else
00566 {
00567 if (!p)
00568 return 0;
00569 else
00570 {
00571 if (subItems)
00572 {
00573 for (HlItem *it = subItems->first(); it; it = subItems->next())
00574 {
00575 int offset2 = it->checkHgl(text, offset, len);
00576
00577 if (offset2)
00578 return offset2;
00579 }
00580 }
00581
00582 return offset;
00583 }
00584 }
00585
00586 if ((len > 0) && (text[offset] == '-' || text[offset] =='+'))
00587 {
00588 offset++;
00589 len--;
00590 }
00591
00592 b = false;
00593
00594 while ((len > 0) && text[offset].isDigit())
00595 {
00596 offset++;
00597 len--;
00598 b = true;
00599 }
00600
00601 if (b)
00602 {
00603 if (subItems)
00604 {
00605 for (HlItem *it = subItems->first(); it; it = subItems->next())
00606 {
00607 int offset2 = it->checkHgl(text, offset, len);
00608
00609 if (offset2)
00610 return offset2;
00611 }
00612 }
00613
00614 return offset;
00615 }
00616
00617 return 0;
00618 }
00619
00620
00621
00622 HlCOct::HlCOct(int attribute, int context, signed char regionId,signed char regionId2)
00623 : HlItem(attribute,context,regionId,regionId2) {
00624 }
00625
00626 bool HlCOct::alwaysStartEnable() const
00627 {
00628 return false;
00629 }
00630
00631 int HlCOct::checkHgl(const QString& text, int offset, int len)
00632 {
00633 if ((len > 0) && text[offset] == '0')
00634 {
00635 offset++;
00636 len--;
00637
00638 int offset2 = offset;
00639
00640 while ((len > 0) && (text[offset2] >= '0' && text[offset2] <= '7'))
00641 {
00642 offset2++;
00643 len--;
00644 }
00645
00646 if (offset2 > offset)
00647 {
00648 if ((len > 0) && ((text[offset2] & 0xdf) == 'L' || (text[offset] & 0xdf) == 'U' ))
00649 offset2++;
00650
00651 return offset2;
00652 }
00653 }
00654
00655 return 0;
00656 }
00657
00658
00659
00660 HlCHex::HlCHex(int attribute, int context,signed char regionId,signed char regionId2)
00661 : HlItem(attribute,context,regionId,regionId2) {
00662 }
00663
00664 bool HlCHex::alwaysStartEnable() const
00665 {
00666 return false;
00667 }
00668
00669 int HlCHex::checkHgl(const QString& text, int offset, int len)
00670 {
00671 if ((len > 1) && (text[offset++] == '0') && ((text[offset++] & 0xdf) == 'X' ))
00672 {
00673 len -= 2;
00674
00675 int offset2 = offset;
00676
00677 while ((len > 0) && (text[offset2].isDigit() || ((text[offset2] & 0xdf) >= 'A' && (text[offset2] & 0xdf) <= 'F')))
00678 {
00679 offset2++;
00680 len--;
00681 }
00682
00683 if (offset2 > offset)
00684 {
00685 if ((len > 0) && ((text[offset2] & 0xdf) == 'L' || (text[offset2] & 0xdf) == 'U' ))
00686 offset2++;
00687
00688 return offset2;
00689 }
00690 }
00691
00692 return 0;
00693 }
00694
00695
00696
00697 HlCFloat::HlCFloat(int attribute, int context, signed char regionId,signed char regionId2)
00698 : HlFloat(attribute,context,regionId,regionId2) {
00699 }
00700
00701 bool HlCFloat::alwaysStartEnable() const
00702 {
00703 return false;
00704 }
00705
00706 int HlCFloat::checkIntHgl(const QString& text, int offset, int len)
00707 {
00708 int offset2 = offset;
00709
00710 while ((len > 0) && text[offset].isDigit()) {
00711 offset2++;
00712 len--;
00713 }
00714
00715 if (offset2 > offset)
00716 return offset2;
00717
00718 return 0;
00719 }
00720
00721 int HlCFloat::checkHgl(const QString& text, int offset, int len)
00722 {
00723 int offset2 = HlFloat::checkHgl(text, offset, len);
00724
00725 if (offset2)
00726 {
00727 if ((text[offset2] & 0xdf) == 'F' )
00728 offset2++;
00729
00730 return offset2;
00731 }
00732 else
00733 {
00734 offset2 = checkIntHgl(text, offset, len);
00735
00736 if (offset2 && ((text[offset2] & 0xdf) == 'F' ))
00737 return ++offset2;
00738 else
00739 return 0;
00740 }
00741 }
00742
00743
00744
00745 HlAnyChar::HlAnyChar(int attribute, int context, signed char regionId,signed char regionId2, const QString& charList)
00746 : HlItem(attribute, context,regionId,regionId2)
00747 , _charList(charList)
00748 {
00749 }
00750
00751 int HlAnyChar::checkHgl(const QString& text, int offset, int len)
00752 {
00753 if ((len > 0) && _charList.find(text[offset]) != -1)
00754 return ++offset;
00755
00756 return 0;
00757 }
00758
00759
00760
00761 HlRegExpr::HlRegExpr( int attribute, int context, signed char regionId,signed char regionId2, QString regexp, bool insensitive, bool minimal )
00762 : HlItem(attribute, context, regionId,regionId2)
00763 {
00764 handlesLinestart=regexp.startsWith("^");
00765 if(!handlesLinestart) regexp.prepend("^");
00766 Expr=new QRegExp(regexp, !insensitive);
00767 Expr->setMinimal(minimal);
00768 }
00769
00770 int HlRegExpr::checkHgl(const QString& text, int offset, int )
00771 {
00772 if (offset && handlesLinestart)
00773 return 0;
00774
00775 int offset2 = Expr->search( text, offset, QRegExp::CaretAtOffset );
00776
00777 if (offset2 == -1) return 0;
00778
00779 return (offset + Expr->matchedLength());
00780 }
00781
00782
00783
00784 HlLineContinue::HlLineContinue(int attribute, int context, signed char regionId,signed char regionId2)
00785 : HlItem(attribute,context,regionId,regionId2) {
00786 }
00787
00788 int HlLineContinue::checkHgl(const QString& text, int offset, int len)
00789 {
00790 if ((len == 1) && (text[offset] == '\\'))
00791 return ++offset;
00792
00793 return 0;
00794 }
00795
00796
00797
00798 HlCStringChar::HlCStringChar(int attribute, int context,signed char regionId,signed char regionId2)
00799 : HlItem(attribute,context,regionId,regionId2) {
00800 }
00801
00802
00803 static int checkEscapedChar(const QString& text, int offset, int& len)
00804 {
00805 int i;
00806 if (text[offset] == '\\' && len > 1)
00807 {
00808 offset++;
00809 len--;
00810
00811 switch(text[offset])
00812 {
00813 case 'a':
00814 case 'b':
00815 case 'e':
00816 case 'f':
00817
00818 case 'n':
00819 case 'r':
00820 case 't':
00821 case 'v':
00822 case '\'':
00823 case '\"':
00824 case '?' :
00825 case '\\':
00826 offset++;
00827 len--;
00828 break;
00829
00830 case 'x':
00831 offset++;
00832 len--;
00833
00834
00835
00836
00837 for (i = 0; (len > 0) && (i < 2) && (text[offset] >= '0' && text[offset] <= '9' || (text[offset] & 0xdf) >= 'A' && (text[offset] & 0xdf) <= 'F'); i++)
00838 {
00839 offset++;
00840 len--;
00841 }
00842
00843 if (i == 0)
00844 return 0;
00845
00846 break;
00847
00848 case '0': case '1': case '2': case '3' :
00849 case '4': case '5': case '6': case '7' :
00850 for (i = 0; (len > 0) && (i < 3) && (text[offset] >='0'&& text[offset] <='7'); i++)
00851 {
00852 offset++;
00853 len--;
00854 }
00855 break;
00856
00857 default:
00858 return 0;
00859 }
00860
00861 return offset;
00862 }
00863
00864 return 0;
00865 }
00866
00867 int HlCStringChar::checkHgl(const QString& text, int offset, int len)
00868 {
00869 return checkEscapedChar(text, offset, len);
00870 }
00871
00872
00873
00874 HlCChar::HlCChar(int attribute, int context,signed char regionId,signed char regionId2)
00875 : HlItem(attribute,context,regionId,regionId2) {
00876 }
00877
00878 int HlCChar::checkHgl(const QString& text, int offset, int len)
00879 {
00880 if ((len > 1) && (text[offset] == '\'') && (text[offset+1] != '\''))
00881 {
00882 int oldl;
00883 oldl = len;
00884
00885 len--;
00886
00887 int offset2 = checkEscapedChar(text, offset + 1, len);
00888
00889 if (!offset2)
00890 {
00891 if (oldl > 2)
00892 {
00893 offset2 = offset + 2;
00894 len = oldl - 2;
00895 }
00896 else
00897 {
00898 return 0;
00899 }
00900 }
00901
00902 if ((len > 0) && (text[offset2] == '\''))
00903 return ++offset2;
00904 }
00905
00906 return 0;
00907 }
00908
00909
00910 ItemData::ItemData(const QString name, int defStyleNum)
00911 : name(name), defStyleNum(defStyleNum) {
00912 }
00913
00914 HlData::HlData(const QString &wildcards, const QString &mimetypes, const QString &identifier, int priority)
00915 : wildcards(wildcards), mimetypes(mimetypes), identifier(identifier), priority(priority)
00916 {
00917 }
00918
00919 HlContext::HlContext (int attribute, int lineEndContext, int _lineBeginContext, bool _fallthrough, int _fallthroughContext)
00920 {
00921 attr = attribute;
00922 ctx = lineEndContext;
00923 lineBeginContext = _lineBeginContext;
00924 fallthrough = _fallthrough;
00925 ftctx = _fallthroughContext;
00926 }
00927
00928 Hl2CharDetect::Hl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, const QChar *s)
00929 : HlItem(attribute,context,regionId,regionId2) {
00930 sChar1 = s[0];
00931 sChar2 = s[1];
00932 }
00933
00934
00935 Highlight::Highlight(const syntaxModeListItem *def) : refCount(0)
00936 {
00937 m_attributeArrays.setAutoDelete (true);
00938
00939 errorsAndWarnings = "";
00940 building=false;
00941 noHl = false;
00942 m_foldingIndentationSensitive = false;
00943 folding=false;
00944 internalIDList.setAutoDelete(true);
00945
00946 if (def == 0)
00947 {
00948 noHl = true;
00949 iName = I18N_NOOP("None");
00950 iSection = "";
00951 m_priority = 0;
00952 }
00953 else
00954 {
00955 iName = def->name;
00956 iSection = def->section;
00957 iWildcards = def->extension;
00958 iMimetypes = def->mimetype;
00959 identifier = def->identifier;
00960 iVersion=def->version;
00961 m_priority=def->priority.toInt();
00962 }
00963
00964 deliminator = stdDeliminator;
00965 }
00966
00967 Highlight::~Highlight()
00968 {
00969 contextList.setAutoDelete( true );
00970 }
00971
00972 void Highlight::generateContextStack(int *ctxNum, int ctx, QMemArray<short>* ctxs, int *prevLine, bool lineContinue)
00973 {
00974
00975
00976 if (lineContinue)
00977 {
00978 if ( !ctxs->isEmpty() )
00979 {
00980 (*ctxNum)=(*ctxs)[ctxs->size()-1];
00981 (*prevLine)--;
00982 }
00983 else
00984 {
00985
00986 (*ctxNum)=0;
00987 }
00988
00989 return;
00990 }
00991
00992 if (ctx >= 0)
00993 {
00994 (*ctxNum) = ctx;
00995
00996 ctxs->resize (ctxs->size()+1);
00997 (*ctxs)[ctxs->size()-1]=(*ctxNum);
00998 }
00999 else
01000 {
01001 if (ctx < -1)
01002 {
01003 while (ctx < -1)
01004 {
01005 if ( ctxs->isEmpty() )
01006 (*ctxNum)=0;
01007 else
01008 {
01009 ctxs->truncate (ctxs->size()-1);
01010
01011 (*ctxNum) = ( (ctxs->isEmpty() ) ? 0 : (*ctxs)[ctxs->size()-1]);
01012 }
01013
01014 ctx++;
01015 }
01016
01017 ctx = 0;
01018
01019 if ((*prevLine) >= (int)(ctxs->size()-1))
01020 {
01021 *prevLine=ctxs->size()-1;
01022
01023 if ( ctxs->isEmpty() )
01024 return;
01025
01026 if (contextNum((*ctxs)[ctxs->size()-1]) && (contextNum((*ctxs)[ctxs->size()-1])->ctx != -1))
01027 {
01028
01029 generateContextStack(ctxNum, contextNum((*ctxs)[ctxs->size()-1])->ctx,ctxs, prevLine);
01030 return;
01031 }
01032 }
01033 }
01034 else
01035 {
01036 if (ctx == -1)
01037 (*ctxNum)=( (ctxs->isEmpty() ) ? 0 : (*ctxs)[ctxs->size()-1]);
01038 }
01039 }
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 void Highlight::doHighlight(QMemArray<short> oCtx, TextLine *textLine,bool lineContinue,
01056 QMemArray<signed char>* foldingList)
01057 {
01058 if (!textLine)
01059 return;
01060
01061 if (noHl)
01062 {
01063 textLine->setAttribs(0,0,textLine->length());
01064 return;
01065 }
01066
01067
01068
01069 HlContext *context;
01070
01071
01072
01073 int ctxNum;
01074 int prevLine;
01075
01076 QMemArray<short> ctx;
01077 ctx.duplicate (oCtx);
01078
01079 if ( oCtx.isEmpty() )
01080 {
01081
01082 ctxNum=0;
01083 context=contextNum(ctxNum);
01084 prevLine=-1;
01085 }
01086 else
01087 {
01088
01089 ctxNum=ctx[oCtx.size()-1];
01090
01091
01092
01093
01094
01095 if (!(context = contextNum(ctxNum)))
01096 context = contextNum(0);
01097
01098
01099
01100 prevLine=oCtx.size()-1;
01101
01102
01103 generateContextStack(&ctxNum, context->ctx, &ctx, &prevLine, lineContinue);
01104
01105
01106
01107 if (!(context = contextNum(ctxNum)))
01108 context = contextNum(0);
01109
01110
01111 }
01112
01113
01114 QChar lastChar = ' ';
01115 const QString& text = textLine->string();
01116 uint len = textLine->length();
01117
01118 int offset1 = 0;
01119 uint z = 0;
01120 HlItem *item = 0;
01121 bool found = false;
01122
01123 while (z < len)
01124 {
01125 found = false;
01126
01127 bool standardStartEnableDetermined = false;
01128 bool standardStartEnable = false;
01129
01130 for (item = context->items.first(); item != 0L; item = context->items.next())
01131 {
01132 bool thisStartEnabled = false;
01133
01134 if (item->alwaysStartEnable())
01135 {
01136 thisStartEnabled = true;
01137 }
01138 else if (!item->hasCustomStartEnable())
01139 {
01140 if (!standardStartEnableDetermined)
01141 {
01142 standardStartEnable = stdDeliminator.find(lastChar) != -1;
01143 standardStartEnableDetermined = true;
01144 }
01145
01146 thisStartEnabled = standardStartEnable;
01147 }
01148 else if (item->startEnable(lastChar))
01149 {
01150 thisStartEnabled = true;
01151 }
01152
01153 if (thisStartEnabled)
01154 {
01155 int offset2 = item->checkHgl(text, offset1, len-z);
01156
01157 if (offset2 > offset1)
01158 {
01159 textLine->setAttribs(item->attr,offset1,offset2);
01160
01161
01162 if (item->region)
01163 {
01164
01165
01166 if ( !foldingList->isEmpty() && ((item->region < 0) && (*foldingList)[foldingList->size()-1] == -item->region ) )
01167 {
01168 foldingList->resize (foldingList->size()-1);
01169 }
01170 else
01171 {
01172 foldingList->resize (foldingList->size()+1);
01173 (*foldingList)[foldingList->size()-1] = item->region;
01174 }
01175
01176 }
01177
01178 if (item->region2)
01179 {
01180
01181
01182 if ( !foldingList->isEmpty() && ((item->region2 < 0) && (*foldingList)[foldingList->size()-1] == -item->region2 ) )
01183 {
01184 foldingList->resize (foldingList->size()-1);
01185 }
01186 else
01187 {
01188 foldingList->resize (foldingList->size()+1);
01189 (*foldingList)[foldingList->size()-1] = item->region2;
01190 }
01191
01192 }
01193
01194 generateContextStack(&ctxNum, item->ctx, &ctx, &prevLine);
01195
01196
01197
01198
01199 context=contextNum(ctxNum);
01200
01201 z = z + offset2 - offset1 - 1;
01202 offset1 = offset2 - 1;
01203 found = true;
01204 break;
01205 }
01206 }
01207 }
01208
01209 lastChar = text[offset1];
01210
01211
01212
01213 if (!found)
01214 {
01215 if ( context->fallthrough )
01216 {
01217
01218 generateContextStack(&ctxNum, context->ftctx, &ctx, &prevLine);
01219 context=contextNum(ctxNum);
01220
01221
01222
01223
01224 if (z)
01225 lastChar = text[offset1 - 1];
01226 else
01227 lastChar = '\\';
01228 continue;
01229 }
01230 else
01231 textLine->setAttribs(context->attr,offset1,offset1 + 1);
01232 }
01233
01234 offset1++;
01235 z++;
01236 }
01237
01238 if (item==0)
01239 textLine->setHlLineContinue(false);
01240 else
01241 textLine->setHlLineContinue(item->lineContinue());
01242
01243 textLine->setContext(ctx.data(), ctx.size());
01244 }
01245
01246 void Highlight::loadWildcards()
01247 {
01248 KConfig *config = HlManager::self()->getKConfig();
01249 config->setGroup("Highlighting " + iName);
01250
01251 QString extensionString = config->readEntry("Wildcards", iWildcards);
01252
01253 if (extensionSource != extensionString) {
01254 regexpExtensions.clear();
01255 plainExtensions.clear();
01256
01257 extensionSource = extensionString;
01258
01259 static QRegExp sep("\\s*;\\s*");
01260
01261 QStringList l = QStringList::split( sep, extensionSource );
01262
01263 static QRegExp boringExpression("\\*\\.[\\d\\w]+");
01264
01265 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it )
01266 if (boringExpression.exactMatch(*it))
01267 plainExtensions.append((*it).mid(1));
01268 else
01269 regexpExtensions.append(QRegExp((*it), true, true));
01270 }
01271 }
01272
01273 QValueList<QRegExp>& Highlight::getRegexpExtensions()
01274 {
01275 return regexpExtensions;
01276 }
01277
01278 QStringList& Highlight::getPlainExtensions()
01279 {
01280 return plainExtensions;
01281 }
01282
01283 QString Highlight::getMimetypes()
01284 {
01285 KConfig *config = HlManager::self()->getKConfig();
01286 config->setGroup("Highlighting " + iName);
01287
01288 return config->readEntry("Mimetypes", iMimetypes);
01289 }
01290
01291 int Highlight::priority()
01292 {
01293 KConfig *config = HlManager::self()->getKConfig();
01294 config->setGroup("Highlighting " + iName);
01295
01296 return config->readNumEntry("Priority", m_priority);
01297 }
01298
01299 HlData *Highlight::getData()
01300 {
01301 KConfig *config = HlManager::self()->getKConfig();
01302 config->setGroup("Highlighting " + iName);
01303
01304 HlData *hlData = new HlData(
01305 config->readEntry("Wildcards", iWildcards),
01306 config->readEntry("Mimetypes", iMimetypes),
01307 config->readEntry("Identifier", identifier),
01308 config->readNumEntry("Priority", m_priority));
01309
01310 return hlData;
01311 }
01312
01313 void Highlight::setData(HlData *hlData)
01314 {
01315 KConfig *config = HlManager::self()->getKConfig();
01316 config->setGroup("Highlighting " + iName);
01317
01318 config->writeEntry("Wildcards",hlData->wildcards);
01319 config->writeEntry("Mimetypes",hlData->mimetypes);
01320 config->writeEntry("Priority",hlData->priority);
01321 }
01322
01323 void Highlight::getItemDataList (uint schema, ItemDataList &list)
01324 {
01325 KConfig *config = HlManager::self()->getKConfig();
01326 config->setGroup("Highlighting " + iName + " - Schema " + KateFactory::self()->schemaManager()->name(schema));
01327
01328 list.clear();
01329 createItemData(list);
01330
01331 for (ItemData *p = list.first(); p != 0L; p = list.next())
01332 {
01333 QStringList s = config->readListEntry(p->name);
01334
01335
01336 if (s.count()>0)
01337 {
01338
01339 while(s.count()<9) s<<"";
01340 p->clear();
01341
01342 QString tmp=s[0]; if (!tmp.isEmpty()) p->defStyleNum=tmp.toInt();
01343
01344 QRgb col;
01345
01346 tmp=s[1]; if (!tmp.isEmpty()) {
01347 col=tmp.toUInt(0,16); p->setTextColor(col); }
01348
01349 tmp=s[2]; if (!tmp.isEmpty()) {
01350 col=tmp.toUInt(0,16); p->setSelectedTextColor(col); }
01351
01352 tmp=s[3]; if (!tmp.isEmpty()) p->setBold(tmp!="0");
01353
01354 tmp=s[4]; if (!tmp.isEmpty()) p->setItalic(tmp!="0");
01355
01356 tmp=s[5]; if (!tmp.isEmpty()) p->setStrikeOut(tmp!="0");
01357
01358 tmp=s[6]; if (!tmp.isEmpty()) p->setUnderline(tmp!="0");
01359
01360 tmp=s[7]; if (!tmp.isEmpty()) {
01361 col=tmp.toUInt(0,16); p->setBGColor(col); }
01362
01363 tmp=s[8]; if (!tmp.isEmpty()) {
01364 col=tmp.toUInt(0,16); p->setSelectedBGColor(col); }
01365
01366 }
01367 }
01368 }
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386 void Highlight::setItemDataList(uint schema, ItemDataList &list)
01387 {
01388 KConfig *config = HlManager::self()->getKConfig();
01389 config->setGroup("Highlighting " + iName + " - Schema " + KateFactory::self()->schemaManager()->name(schema));
01390
01391 QStringList settings;
01392
01393 for (ItemData *p = list.first(); p != 0L; p = list.next())
01394 {
01395 settings.clear();
01396 settings<<QString::number(p->defStyleNum,10);
01397 settings<<(p->itemSet(KateAttribute::TextColor)?QString::number(p->textColor().rgb(),16):"");
01398 settings<<(p->itemSet(KateAttribute::SelectedTextColor)?QString::number(p->selectedTextColor().rgb(),16):"");
01399 settings<<(p->itemSet(KateAttribute::Weight)?(p->bold()?"1":"0"):"");
01400 settings<<(p->itemSet(KateAttribute::Italic)?(p->italic()?"1":"0"):"");
01401 settings<<(p->itemSet(KateAttribute::StrikeOut)?(p->strikeOut()?"1":"0"):"");
01402 settings<<(p->itemSet(KateAttribute::Underline)?(p->underline()?"1":"0"):"");
01403 settings<<(p->itemSet(KateAttribute::BGColor)?QString::number(p->bgColor().rgb(),16):"");
01404 settings<<(p->itemSet(KateAttribute::SelectedBGColor)?QString::number(p->selectedBGColor().rgb(),16):"");
01405 settings<<"---";
01406 config->writeEntry(p->name,settings);
01407 }
01408 }
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421 void Highlight::use()
01422 {
01423 if (refCount == 0)
01424 init();
01425
01426 refCount++;
01427 }
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 void Highlight::release()
01441 {
01442 refCount--;
01443
01444 if (refCount == 0)
01445 done();
01446 }
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459 void Highlight::init()
01460 {
01461 if (noHl)
01462 return;
01463
01464 contextList.clear ();
01465 makeContextList();
01466 }
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481 void Highlight::done()
01482 {
01483 if (noHl)
01484 return;
01485
01486 contextList.clear ();
01487 }
01488
01489 HlContext *Highlight::contextNum (uint n)
01490 {
01491 return contextList[n];
01492 }
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508 void Highlight::createItemData(ItemDataList &list)
01509 {
01510
01511 if (noHl)
01512 {
01513 list.append(new ItemData(I18N_NOOP("Normal Text"), dsNormal));
01514 return;
01515 }
01516
01517
01518 if (internalIDList.isEmpty())
01519 makeContextList();
01520
01521 list=internalIDList;
01522 }
01523
01524 void Highlight::addToItemDataList()
01525 {
01526
01527 HlManager::self()->syntax->setIdentifier(buildIdentifier);
01528 syntaxContextData *data = HlManager::self()->syntax->getGroupInfo("highlighting","itemData");
01529
01530
01531 while (HlManager::self()->syntax->nextGroup(data))
01532 {
01533
01534 QString color = HlManager::self()->syntax->groupData(data,QString("color"));
01535 QString selColor = HlManager::self()->syntax->groupData(data,QString("selColor"));
01536 QString bold = HlManager::self()->syntax->groupData(data,QString("bold"));
01537 QString italic = HlManager::self()->syntax->groupData(data,QString("italic"));
01538 QString underline = HlManager::self()->syntax->groupData(data,QString("underline"));
01539 QString strikeOut = HlManager::self()->syntax->groupData(data,QString("strikeOut"));
01540 QString bgColor = HlManager::self()->syntax->groupData(data,QString("backgroundColor"));
01541 QString selBgColor = HlManager::self()->syntax->groupData(data,QString("selBackgroundColor"));
01542
01543 ItemData* newData = new ItemData(
01544 buildPrefix+HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(),
01545 getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum"))));
01546
01547
01548
01549 if (!color.isEmpty()) newData->setTextColor(QColor(color));
01550 if (!selColor.isEmpty()) newData->setSelectedTextColor(QColor(selColor));
01551 if (!bold.isEmpty()) newData->setBold(bold=="true" || bold=="1");
01552 if (!italic.isEmpty()) newData->setItalic(italic=="true" || italic=="1");
01553
01554 if (!underline.isEmpty()) newData->setUnderline(underline=="true" || underline=="1");
01555 if (!strikeOut.isEmpty()) newData->setStrikeOut(strikeOut=="true" || strikeOut=="1");
01556 if (!bgColor.isEmpty()) newData->setBGColor(QColor(bgColor));
01557 if (!selBgColor.isEmpty()) newData->setSelectedBGColor(QColor(selBgColor));
01558
01559 internalIDList.append(newData);
01560 }
01561
01562
01563 if (data)
01564 HlManager::self()->syntax->freeGroupInfo(data);
01565 }
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582 int Highlight::lookupAttrName(const QString& name, ItemDataList &iDl)
01583 {
01584 for (uint i = 0; i < iDl.count(); i++)
01585 if (iDl.at(i)->name == buildPrefix+name)
01586 return i;
01587
01588 kdDebug(13010)<<"Couldn't resolve itemDataName"<<endl;
01589 return 0;
01590 }
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611 HlItem *Highlight::createHlItem(struct syntaxContextData *data, ItemDataList &iDl,QStringList *RegionList, QStringList *ContextNameList)
01612 {
01613
01614 if (noHl)
01615 return 0;
01616
01617
01618 QString dataname=HlManager::self()->syntax->groupItemData(data,QString(""));
01619
01620
01621 QString tmpAttr=HlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace();
01622 int attr;
01623 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
01624 {
01625 errorsAndWarnings+=i18n("<B>%1</B>: Deprecated syntax. Attribute (%2) not addressed by symbolic name<BR>").
01626 arg(buildIdentifier).arg(tmpAttr);
01627 attr=tmpAttr.toInt();
01628 }
01629 else
01630 attr=lookupAttrName(tmpAttr,iDl);
01631
01632
01633
01634 int context;
01635 QString tmpcontext=HlManager::self()->syntax->groupItemData(data,QString("context"));
01636
01637
01638 QString unresolvedContext;
01639 context=getIdFromString(ContextNameList, tmpcontext,unresolvedContext);
01640
01641
01642 char chr;
01643 if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty())
01644 chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0];
01645 else
01646 chr=0;
01647
01648
01649 QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String"));
01650
01651
01652 char chr1;
01653 if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty())
01654 chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0];
01655 else
01656 chr1=0;
01657
01658
01659 bool insensitive=( HlManager::self()->syntax->groupItemData(data,QString("insensitive")).lower() == QString("true") );
01660
01661
01662
01663 bool minimal = ( HlManager::self()->syntax->groupItemData(data,QString("minimal")).lower() == QString("true") );
01664
01665
01666
01667 QString beginRegionStr=HlManager::self()->syntax->groupItemData(data,QString("beginRegion"));
01668 QString endRegionStr=HlManager::self()->syntax->groupItemData(data,QString("endRegion"));
01669
01670 signed char regionId=0;
01671 signed char regionId2=0;
01672
01673 if (!beginRegionStr.isEmpty())
01674 {
01675 regionId = RegionList->findIndex(beginRegionStr);
01676
01677 if (regionId==-1)
01678 {
01679 (*RegionList)<<beginRegionStr;
01680 regionId = RegionList->findIndex(beginRegionStr);
01681 }
01682
01683 regionId++;
01684
01685 kdDebug () << "########### BEG REG: " << beginRegionStr << " NUM: " << regionId << endl;
01686 }
01687
01688 if (!endRegionStr.isEmpty())
01689 {
01690 regionId2 = RegionList->findIndex(endRegionStr);
01691
01692 if (regionId2==-1)
01693 {
01694 (*RegionList)<<endRegionStr;
01695 regionId2 = RegionList->findIndex(endRegionStr);
01696 }
01697
01698 regionId2 = -regionId2 - 1;
01699
01700 kdDebug () << "########### END REG: " << endRegionStr << " NUM: " << regionId2 << endl;
01701 }
01702
01703
01704 HlItem *tmpItem;
01705
01706 if (dataname=="keyword")
01707 {
01708 HlKeyword *keyword=new HlKeyword(attr,context,regionId,regionId2,casesensitive,
01709 deliminator);
01710
01711
01712 keyword->addList(HlManager::self()->syntax->finddata("highlighting",stringdata));
01713 tmpItem=keyword;
01714 } else
01715 if (dataname=="Float") tmpItem= (new HlFloat(attr,context,regionId,regionId2)); else
01716 if (dataname=="Int") tmpItem=(new HlInt(attr,context,regionId,regionId2)); else
01717 if (dataname=="DetectChar") tmpItem=(new HlCharDetect(attr,context,regionId,regionId2,chr)); else
01718 if (dataname=="Detect2Chars") tmpItem=(new Hl2CharDetect(attr,context,regionId,regionId2,chr,chr1)); else
01719 if (dataname=="RangeDetect") tmpItem=(new HlRangeDetect(attr,context,regionId,regionId2, chr, chr1)); else
01720 if (dataname=="LineContinue") tmpItem=(new HlLineContinue(attr,context,regionId,regionId2)); else
01721 if (dataname=="StringDetect") tmpItem=(new HlStringDetect(attr,context,regionId,regionId2,stringdata,insensitive)); else
01722 if (dataname=="AnyChar") tmpItem=(new HlAnyChar(attr,context,regionId,regionId2,stringdata)); else
01723 if (dataname=="RegExpr") tmpItem=(new HlRegExpr(attr,context,regionId,regionId2,stringdata, insensitive, minimal)); else
01724 if (dataname=="HlCChar") tmpItem= ( new HlCChar(attr,context,regionId,regionId2));else
01725 if (dataname=="HlCHex") tmpItem= (new HlCHex(attr,context,regionId,regionId2));else
01726 if (dataname=="HlCOct") tmpItem= (new HlCOct(attr,context,regionId,regionId2)); else
01727 if (dataname=="HlCFloat") tmpItem= (new HlCFloat(attr,context,regionId,regionId2)); else
01728 if (dataname=="HlCStringChar") tmpItem= (new HlCStringChar(attr,context,regionId,regionId2)); else
01729
01730 {
01731
01732 return 0;
01733 }
01734
01735 if (!unresolvedContext.isEmpty())
01736 {
01737 unresolvedContextReferences.insert(&(tmpItem->ctx),unresolvedContext);
01738 }
01739 return tmpItem;
01740 }
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753 bool Highlight::isInWord(QChar c)
01754 {
01755 static const QString sq("\"'");
01756 return deliminator.find(c) == -1 && sq.find(c) == -1;
01757 }
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771 void Highlight::readCommentConfig()
01772 {
01773 HlManager::self()->syntax->setIdentifier(buildIdentifier);
01774 syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("general","comment");
01775
01776 if (data)
01777 {
01778 while (HlManager::self()->syntax->nextGroup(data))
01779 {
01780 if (HlManager::self()->syntax->groupData(data,"name")=="singleLine")
01781 cslStart=HlManager::self()->syntax->groupData(data,"start");
01782
01783 if (HlManager::self()->syntax->groupData(data,"name")=="multiLine")
01784 {
01785 cmlStart=HlManager::self()->syntax->groupData(data,"start");
01786 cmlEnd=HlManager::self()->syntax->groupData(data,"end");
01787 }
01788 }
01789
01790 HlManager::self()->syntax->freeGroupInfo(data);
01791 }
01792 else
01793 {
01794 cslStart = "";
01795 cmlStart = "";
01796 cmlEnd = "";
01797 }
01798 }
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814 void Highlight::readGlobalKeywordConfig()
01815 {
01816
01817 kdDebug(13010)<<"readGlobalKeywordConfig:BEGIN"<<endl;
01818
01819 HlManager::self()->syntax->setIdentifier(buildIdentifier);
01820 syntaxContextData *data = HlManager::self()->syntax->getConfig("general","keywords");
01821
01822 if (data)
01823 {
01824 kdDebug(13010)<<"Found global keyword config"<<endl;
01825
01826 if (HlManager::self()->syntax->groupItemData(data,QString("casesensitive"))!="0")
01827 casesensitive=true;
01828 else
01829 casesensitive=false;
01830
01831
01832 weakDeliminator=(HlManager::self()->syntax->groupItemData(data,QString("weakDeliminator")));
01833
01834 kdDebug(13010)<<"weak delimiters are: "<<weakDeliminator<<endl;
01835
01836
01837 for (uint s=0; s < weakDeliminator.length(); s++)
01838 {
01839 int f = deliminator.find (weakDeliminator[s]);
01840
01841 if (f > -1)
01842 deliminator.remove (f, 1);
01843 }
01844
01845 QString addDelim = (HlManager::self()->syntax->groupItemData(data,QString("additionalDeliminator")));
01846
01847 if (!addDelim.isEmpty())
01848 deliminator=deliminator+addDelim;
01849
01850 HlManager::self()->syntax->freeGroupInfo(data);
01851 }
01852 else
01853 {
01854
01855 casesensitive=true;
01856 weakDeliminator=QString("");
01857 }
01858
01859 kdDebug(13010)<<"readGlobalKeywordConfig:END"<<endl;
01860
01861 kdDebug(13010)<<"delimiterCharacters are: "<<deliminator<<endl;
01862 }
01863
01864
01865 void Highlight::readFoldingConfig()
01866 {
01867
01868 kdDebug(13010)<<"readfoldignConfig:BEGIN"<<endl;
01869
01870 HlManager::self()->syntax->setIdentifier(buildIdentifier);
01871 syntaxContextData *data = HlManager::self()->syntax->getConfig("general","folding");
01872
01873 if (data)
01874 {
01875 kdDebug(13010)<<"Found global keyword config"<<endl;
01876
01877 if (HlManager::self()->syntax->groupItemData(data,QString("indentationsensitive"))!="1")
01878 m_foldingIndentationSensitive=false;
01879 else
01880 m_foldingIndentationSensitive=true;
01881
01882 HlManager::self()->syntax->freeGroupInfo(data);
01883 }
01884 else
01885 {
01886
01887 m_foldingIndentationSensitive = false;
01888 }
01889
01890 kdDebug(13010)<<"readfoldingConfig:END"<<endl;
01891
01892 kdDebug(13010)<<"############################ use indent for fold are: "<<m_foldingIndentationSensitive<<endl;
01893 }
01894
01895 void Highlight::createContextNameList(QStringList *ContextNameList,int ctx0)
01896 {
01897 kdDebug(13010)<<"creatingContextNameList:BEGIN"<<endl;
01898
01899 if (ctx0 == 0)
01900 ContextNameList->clear();
01901
01902 HlManager::self()->syntax->setIdentifier(buildIdentifier);
01903
01904 syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("highlighting","context");
01905
01906 int id=ctx0;
01907
01908 if (data)
01909 {
01910 while (HlManager::self()->syntax->nextGroup(data))
01911 {
01912 QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace();
01913 if (tmpAttr.isEmpty())
01914 {
01915 tmpAttr=QString("!KATE_INTERNAL_DUMMY! %1").arg(id);
01916 errorsAndWarnings +=i18n("<B>%1</B>: Deprecated syntax. Context %2 has no symbolic name<BR>").arg(buildIdentifier).arg(id-ctx0);
01917 }
01918 else tmpAttr=buildPrefix+tmpAttr;
01919 (*ContextNameList)<<tmpAttr;
01920 id++;
01921 }
01922 HlManager::self()->syntax->freeGroupInfo(data);
01923 }
01924 kdDebug(13010)<<"creatingContextNameList:END"<<endl;
01925
01926 }
01927
01928 int Highlight::getIdFromString(QStringList *ContextNameList, QString tmpLineEndContext, QString &unres)
01929 {
01930 unres="";
01931 int context;
01932 if ((tmpLineEndContext=="#stay") || (tmpLineEndContext.simplifyWhiteSpace().isEmpty())) context=-1;
01933 else if (tmpLineEndContext.startsWith("#pop"))
01934 {
01935 context=-1;
01936 for(;tmpLineEndContext.startsWith("#pop");context--)
01937 {
01938 tmpLineEndContext.remove(0,4);
01939 kdDebug(13010)<<"#pop found"<<endl;
01940 }
01941 }
01942 else
01943 if ( tmpLineEndContext.startsWith("##"))
01944 {
01945 QString tmp=tmpLineEndContext.right(tmpLineEndContext.length()-2);
01946 if (!embeddedHls.contains(tmp)) embeddedHls.insert(tmp,EmbeddedHlInfo());
01947 unres=tmp;
01948 context=0;
01949 }
01950 else
01951 {
01952 context=ContextNameList->findIndex(buildPrefix+tmpLineEndContext);
01953 if (context==-1)
01954 {
01955 context=tmpLineEndContext.toInt();
01956 errorsAndWarnings+=i18n("<B>%1</B>:Deprecated syntax. Context %2 not addressed by a symbolic name").arg(buildIdentifier).arg(tmpLineEndContext);
01957 }
01958
01959
01960 }
01961 return context;
01962 }
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977 void Highlight::makeContextList()
01978 {
01979 if (noHl)
01980 return;
01981
01982 embeddedHls.clear();
01983 unresolvedContextReferences.clear();
01984 RegionList.clear();
01985 ContextNameList.clear();
01986
01987
01988 embeddedHls.insert(iName,EmbeddedHlInfo());
01989
01990 bool something_changed;
01991 int startctx=0;
01992 building=true;
01993 do
01994 {
01995 kdDebug(13010)<<"**************** Outter loop in make ContextList"<<endl;
01996 kdDebug(13010)<<"**************** Hl List count:"<<embeddedHls.count()<<endl;
01997 something_changed=false;
01998 for (EmbeddedHlInfos::const_iterator it=embeddedHls.begin(); it!=embeddedHls.end();++it)
01999 {
02000 if (!it.data().loaded)
02001 {
02002 kdDebug(13010)<<"**************** Inner loop in make ContextList"<<endl;
02003 QString identifierToUse;
02004 kdDebug(13010)<<"Trying to open highlighting definition file: "<< it.key()<<endl;
02005 if (iName==it.key()) identifierToUse=identifier;
02006 else
02007 identifierToUse=HlManager::self()->identifierForName(it.key());
02008
02009 kdDebug(13010)<<"Location is:"<< identifierToUse<<endl;
02010
02011 buildPrefix=it.key()+':';
02012
02013 if (identifierToUse.isEmpty() ) kdDebug()<<"OHOH, unknown highlighting description referenced"<<endl;
02014
02015 kdDebug()<<"setting ("<<it.key()<<") to loaded"<<endl;
02016 it=embeddedHls.insert(it.key(),EmbeddedHlInfo(true,startctx));
02017 buildContext0Offset=startctx;
02018 startctx=addToContextList(identifierToUse,startctx);
02019 if (noHl) return;
02020 something_changed=true;
02021
02022 }
02023 }
02024 } while (something_changed);
02025
02026
02027
02028
02029
02030 kdDebug(13010)<<"Unresolved contexts, which need attention: "<<unresolvedContextReferences.count()<<endl;
02031
02032 for (UnresolvedContextReferences::iterator unresIt=unresolvedContextReferences.begin();
02033 unresIt!=unresolvedContextReferences.end();++unresIt)
02034 {
02035
02036 EmbeddedHlInfos::const_iterator hlIt=embeddedHls.find(unresIt.data());
02037 if (hlIt!=embeddedHls.end())
02038 *(unresIt.key())=hlIt.data().context0;
02039 }
02040
02041
02042
02043
02044 handleIncludeRules();
02045
02046 embeddedHls.clear();
02047 unresolvedContextReferences.clear();
02048 RegionList.clear();
02049 ContextNameList.clear();
02050
02051
02052
02053 if (!errorsAndWarnings.isEmpty())
02054 KMessageBox::detailedSorry(0L,i18n("There were warning(s) and/or error(s) while parsing the syntax highlighting configuration."), errorsAndWarnings, i18n("Kate Syntax Highlight Parser"));
02055
02056
02057 building=false;
02058 }
02059
02060 void Highlight::handleIncludeRules()
02061 {
02062
02063
02064 kdDebug(13010)<<"IncludeRules, which need attention: " <<includeRules.count()<<endl;
02065 if (includeRules.isEmpty()) return;
02066
02067 buildPrefix="";
02068 QString dummy;
02069
02070
02071
02072
02073
02074
02075
02076 for (IncludeRules::iterator it=includeRules.begin();it!=includeRules.end();)
02077 {
02078
02079 if ((*it)->incCtx==-1)
02080 {
02081
02082 if ((*it)->incCtxN.isEmpty())
02083 {
02084
02085 IncludeRules::iterator it1=it;
02086 ++it1;
02087 delete (*it);
02088 includeRules.remove(it);
02089 it=it1;
02090 }
02091 else
02092 {
02093
02094 (*it)->incCtx=getIdFromString(&ContextNameList,(*it)->incCtxN,dummy);
02095 kdDebug()<<"Resolved "<<(*it)->incCtxN<< " to "<<(*it)->incCtx<<" for include rule"<<endl;
02096
02097 }
02098 } else ++it;
02099 }
02100
02101
02102
02103
02104
02105 while (!includeRules.isEmpty())
02106 handleIncludeRulesRecursive(includeRules.begin(),&includeRules);
02107
02108
02109 }
02110
02111 void Highlight::handleIncludeRulesRecursive(IncludeRules::iterator it, IncludeRules *list)
02112 {
02113 if (it==list->end()) return;
02114 IncludeRules::iterator it1=it;
02115 int ctx=(*it1)->ctx;
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125 while ((it!=list->end()) && ((*it)->ctx==ctx))
02126 {
02127 it1=it;
02128 ++it;
02129
02130 }
02131
02132 while ((it1!=list->end()) && ((*it1)->ctx==ctx))
02133 {
02134
02135
02136
02137 int ctx1=(*it1)->incCtx;
02138
02139
02140 for (IncludeRules::iterator it2=list->begin();it2!=list->end();++it2)
02141 {
02142
02143
02144 if ((*it2)->ctx==ctx1)
02145 {
02146
02147
02148 handleIncludeRulesRecursive(it2,list);
02149 break;
02150 }
02151 }
02152
02153
02154 HlContext *dest=contextList[ctx];
02155 HlContext *src=contextList[ctx1];
02156 uint p=(*it1)->pos;
02157 for ( HlItem *c = src->items.first(); c; c=src->items.next(), p++ )
02158 dest->items.insert(p,c);
02159
02160 it=it1;
02161 --it1;
02162 delete (*it);
02163 list->remove(it);
02164 }
02165 }
02166
02167 int Highlight::addToContextList(const QString &ident, int ctx0)
02168 {
02169 buildIdentifier=ident;
02170 syntaxContextData *data, *datasub;
02171 HlItem *c;
02172
02173 QString dummy;
02174
02175
02176 if (!HlManager::self()->syntax->setIdentifier(ident))
02177 {
02178 noHl=true;
02179 KMessageBox::information(0L,i18n("Since there has been an error parsing the highlighting description, this highlighting will be disabled"));
02180 return 0;
02181 }
02182
02183 RegionList<<"!KateInternal_TopLevel!";
02184 readCommentConfig();
02185 readGlobalKeywordConfig();
02186 readFoldingConfig ();
02187
02188 QString ctxName;
02189
02190
02191 addToItemDataList();
02192 ItemDataList iDl = internalIDList;
02193
02194 createContextNameList(&ContextNameList,ctx0);
02195
02196 kdDebug(13010)<<"Parsing Context structure"<<endl;
02197
02198 data=HlManager::self()->syntax->getGroupInfo("highlighting","context");
02199 uint i=buildContext0Offset;
02200 if (data)
02201 {
02202 while (HlManager::self()->syntax->nextGroup(data))
02203 {
02204 kdDebug(13010)<<"Found a context in file, building structure now"<<endl;
02205
02206 QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace();
02207 int attr;
02208 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
02209 attr=tmpAttr.toInt();
02210 else
02211 attr=lookupAttrName(tmpAttr,iDl);
02212
02213
02214 ctxName=buildPrefix+HlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace();
02215
02216 QString tmpLineEndContext=HlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace();
02217 int context;
02218
02219 context=getIdFromString(&ContextNameList, tmpLineEndContext,dummy);
02220
02221
02222 bool ft = false;
02223 int ftc = 0;
02224 if ( i > 0 ) {
02225 QString tmpFt = HlManager::self()->syntax->groupData(data, QString("fallthrough") );
02226 if ( tmpFt.lower() == "true" || tmpFt.toInt() == 1 )
02227 ft = true;
02228 if ( ft ) {
02229 QString tmpFtc = HlManager::self()->syntax->groupData( data, QString("fallthroughContext") );
02230
02231 ftc=getIdFromString(&ContextNameList, tmpFtc,dummy);
02232 if (ftc == -1) ftc =0;
02233
02234 kdDebug(13010)<<"Setting fall through context (context "<<i<<"): "<<ftc<<endl;
02235 }
02236 }
02237
02238
02239 contextList.insert (i, new HlContext (
02240 attr,
02241 context,
02242 (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1:
02243 (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt(),
02244 ft, ftc
02245 ));
02246
02247
02248
02249 while (HlManager::self()->syntax->nextItem(data))
02250 {
02251
02252
02253
02254
02255 QString tag = HlManager::self()->syntax->groupItemData(data,QString(""));
02256 if ( tag == "IncludeRules" ) {
02257 QString incCtx=HlManager::self()->syntax->groupItemData( data, QString("context"));
02258
02259 if (incCtx.startsWith("##") || (!incCtx.startsWith("#"))) {
02260 if (!incCtx.startsWith("#")) {
02261 incCtx=buildPrefix+incCtx.simplifyWhiteSpace();
02262 includeRules.append(new IncludeRule(i,contextList[i]->items.count(),incCtx));
02263 }
02264 else {
02265 kdDebug()<<"Cross highlight reference <IncludeRules>"<<endl;
02266 IncludeRule *ir=new IncludeRule(i,contextList[i]->items.count());
02267
02268 if (!embeddedHls.contains(incCtx.right(incCtx.length()-2)))
02269 embeddedHls.insert(incCtx.right(incCtx.length()-2),EmbeddedHlInfo());
02270 unresolvedContextReferences.insert(&(ir->incCtx),
02271 incCtx.right(incCtx.length()-2));
02272 includeRules.append(ir);
02273 }
02274 }
02275 continue;
02276 }
02277 #if 0
02278 QString tag = HlManager::self()->syntax->groupItemData(data,QString(""));
02279 if ( tag == "IncludeRules" ) {
02280
02281 int ctxId = getIdFromString(&ContextNameList,
02282 HlManager::self()->syntax->groupItemData( data, QString("context")),dummy);
02283 if ( ctxId > -1) {
02284 kdDebug(13010)<<"makeContextList["<<i<<"]: including all items of context "<<ctxId<<endl;
02285 if ( ctxId < (int) i ) {
02286 for ( c = contextList[ctxId]->items.first(); c; c = contextList[ctxId]->items.next() )
02287 contextList[i]->items.append(c);
02288 }
02289 else
02290 kdDebug(13010)<<"Context "<<ctxId<<"not defined. You can not include the rules of an undefined context"<<endl;
02291 }
02292 continue;
02293 }
02294 #endif
02295 c=createHlItem(data,iDl,&RegionList,&ContextNameList);
02296 if (c)
02297 {
02298 contextList[i]->items.append(c);
02299
02300
02301 datasub=HlManager::self()->syntax->getSubItems(data);
02302 bool tmpbool;
02303 if (tmpbool=HlManager::self()->syntax->nextItem(datasub))
02304 {
02305 c->subItems=new QPtrList<HlItem>;
02306 for (;tmpbool;tmpbool=HlManager::self()->syntax->nextItem(datasub))
02307 c->subItems->append(createHlItem(datasub,iDl,&RegionList,&ContextNameList));
02308 }
02309 HlManager::self()->syntax->freeGroupInfo(datasub);
02310
02311 }
02312
02313 }
02314 i++;
02315 }
02316 }
02317
02318 HlManager::self()->syntax->freeGroupInfo(data);
02319 if (RegionList.count()!=1) folding=true;
02320 folding = folding || m_foldingIndentationSensitive;
02321 return i;
02322 }
02323
02324 void Highlight::clearAttributeArrays ()
02325 {
02326 for ( QIntDictIterator< QMemArray<KateAttribute> > it( m_attributeArrays ); it.current(); ++it )
02327 {
02328
02329 KateAttributeList defaultStyleList;
02330 defaultStyleList.setAutoDelete(true);
02331 HlManager::self()->getDefaults(it.currentKey(), defaultStyleList);
02332
02333 ItemDataList itemDataList;
02334 getItemDataList(it.currentKey(), itemDataList);
02335
02336 uint nAttribs = itemDataList.count();
02337 QMemArray<KateAttribute> *array = it.current();
02338 array->resize (nAttribs);
02339
02340 for (uint z = 0; z < nAttribs; z++)
02341 {
02342 ItemData *itemData = itemDataList.at(z);
02343 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum);
02344
02345 if (itemData && itemData->isSomethingSet())
02346 n += *itemData;
02347
02348 array->at(z) = n;
02349 }
02350 }
02351 }
02352
02353 QMemArray<KateAttribute> *Highlight::attributes (uint schema)
02354 {
02355 QMemArray<KateAttribute> *array;
02356
02357
02358 if ((array = m_attributeArrays[schema]))
02359 return array;
02360
02361
02362 if (!KateFactory::self()->schemaManager()->validSchema(schema))
02363 {
02364
02365 return attributes (0);
02366 }
02367
02368
02369 KateAttributeList defaultStyleList;
02370 defaultStyleList.setAutoDelete(true);
02371 HlManager::self()->getDefaults(schema, defaultStyleList);
02372
02373 ItemDataList itemDataList;
02374 getItemDataList(schema, itemDataList);
02375
02376 uint nAttribs = itemDataList.count();
02377 array = new QMemArray<KateAttribute> (nAttribs);
02378
02379 for (uint z = 0; z < nAttribs; z++)
02380 {
02381 ItemData *itemData = itemDataList.at(z);
02382 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum);
02383
02384 if (itemData && itemData->isSomethingSet())
02385 n += *itemData;
02386
02387 array->at(z) = n;
02388 }
02389
02390 m_attributeArrays.insert(schema, array);
02391
02392 return array;
02393 }
02394
02395 void Highlight::getItemDataListCopy (uint schema, ItemDataList &outlist)
02396 {
02397 ItemDataList itemDataList;
02398 getItemDataList(schema, itemDataList);
02399
02400 outlist.clear ();
02401 outlist.setAutoDelete (true);
02402 for (uint z=0; z < itemDataList.count(); z++)
02403 outlist.append (new ItemData (*itemDataList.at(z)));
02404 }
02405
02406
02407
02408
02409 HlManager::HlManager()
02410 : QObject()
02411 , m_config ("katesyntaxhighlightingrc", false, false)
02412 , commonSuffixes (QStringList::split(";", ".orig;.new;~;.bak;.BAK"))
02413 , syntax (new SyntaxDocument())
02414 {
02415 hlList.setAutoDelete(true);
02416 hlDict.setAutoDelete(false);
02417
02418 SyntaxModeList modeList = syntax->modeList();
02419 for (uint i=0; i < modeList.count(); i++)
02420 {
02421 Highlight *hl = new Highlight(modeList.at(i));
02422
02423 uint insert = 0;
02424 for (; insert <= hlList.count(); insert++)
02425 {
02426 if (insert == hlList.count())
02427 break;
02428
02429 if ( QString(hlList.at(insert)->section() + hlList.at(insert)->name()).lower()
02430 > QString(hl->section() + hl->name()).lower() )
02431 break;
02432 }
02433
02434 hlList.insert (insert, hl);
02435 hlDict.insert (hl->name(), hl);
02436 }
02437
02438 // Normal HL
02439 Highlight *hl = new Highlight(0);
02440 hlList.prepend (hl);
02441 hlDict.insert (hl->name(), hl);
02442 }
02443
02444 HlManager::~HlManager()
02445 {
02446 delete syntax;
02447 }
02448
02449 static KStaticDeleter<HlManager> sdHlMan;
02450
02451 HlManager *HlManager::self()
02452 {
02453 if ( !s_self )
02454 sdHlMan.setObject(s_self, new HlManager ());
02455
02456 return s_self;
02457 }
02458
02459 Highlight *HlManager::getHl(int n)
02460 {
02461 if (n < 0 || n >= (int) hlList.count())
02462 n = 0;
02463
02464 return hlList.at(n);
02465 }
02466
02467 int HlManager::nameFind(const QString &name)
02468 {
02469 int z (hlList.count() - 1);
02470 for (; z > 0; z--)
02471 if (hlList.at(z)->name() == name)
02472 return z;
02473
02474 return z;
02475 }
02476
02477 int HlManager::detectHighlighting (KateDocument *doc)
02478 {
02479 int hl = wildcardFind( doc->url().filename() );
02480
02481 if (hl == -1)
02482 {
02483 QByteArray buf (KATE_HL_HOWMANY);
02484 uint bufpos = 0;
02485 for (uint i=0; i < doc->numLines(); i++)
02486 {
02487 QString line = doc->textLine( i );
02488 uint len = line.length() + 1;
02489
02490 if (bufpos + len > KATE_HL_HOWMANY)
02491 len = KATE_HL_HOWMANY - bufpos;
02492
02493 memcpy(&buf[bufpos], (line + "\n").latin1(), len);
02494
02495 bufpos += len;
02496
02497 if (bufpos >= KATE_HL_HOWMANY)
02498 break;
02499 }
02500 buf.resize( bufpos );
02501
02502 hl = mimeFind (buf);
02503 }
02504
02505 return hl;
02506 }
02507
02508 int HlManager::wildcardFind(const QString &fileName)
02509 {
02510 int result = -1;
02511 if ((result = realWildcardFind(fileName)) != -1)
02512 return result;
02513
02514 int length = fileName.length();
02515 QString backupSuffix = KateDocumentConfig::global()->backupSuffix();
02516 if (fileName.endsWith(backupSuffix)) {
02517 if ((result = realWildcardFind(fileName.left(length - backupSuffix.length()))) != -1)
02518 return result;
02519 }
02520
02521 for (QStringList::Iterator it = commonSuffixes.begin(); it != commonSuffixes.end(); ++it) {
02522 if (*it != backupSuffix && fileName.endsWith(*it)) {
02523 if ((result = realWildcardFind(fileName.left(length - (*it).length()))) != -1)
02524 return result;
02525 }
02526 }
02527
02528 return -1;
02529 }
02530
02531 int HlManager::realWildcardFind(const QString &fileName)
02532 {
02533 static QRegExp sep("\\s*;\\s*");
02534
02535 QPtrList<Highlight> highlights;
02536
02537 for (Highlight *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) {
02538 highlight->loadWildcards();
02539
02540 for (QStringList::Iterator it = highlight->getPlainExtensions().begin(); it != highlight->getPlainExtensions().end(); ++it)
02541 if (fileName.endsWith((*it)))
02542 highlights.append(highlight);
02543
02544 for (int i = 0; i < (int)highlight->getRegexpExtensions().count(); i++) {
02545 QRegExp re = highlight->getRegexpExtensions()[i];
02546 if (re.exactMatch(fileName))
02547 highlights.append(highlight);
02548 }
02549 }
02550
02551 if ( !highlights.isEmpty() )
02552 {
02553 int pri = -1;
02554 int hl = -1;
02555
02556 for (Highlight *highlight = highlights.first(); highlight != 0L; highlight = highlights.next())
02557 {
02558 if (highlight->priority() > pri)
02559 {
02560 pri = highlight->priority();
02561 hl = hlList.findRef (highlight);
02562 }
02563 }
02564
02565 return hl;
02566 }
02567
02568 return -1;
02569 }
02570
02571 int HlManager::mimeFind(const QByteArray &contents)
02572 {
02573 static QRegExp sep("\\s*;\\s*");
02574
02575 int accuracy = 0;
02576 KMimeType::Ptr mt = KMimeType::findByContent( contents, &accuracy );
02577
02578 QPtrList<Highlight> highlights;
02579
02580 for (Highlight *highlight = hlList.first(); highlight != 0L; highlight = hlList.next())
02581 {
02582 QStringList l = QStringList::split( sep, highlight->getMimetypes() );
02583
02584 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it )
02585 {
02586 if ( *it == mt->name() ) // faster than a regexp i guess?
02587 highlights.append (highlight);
02588 }
02589 }
02590
02591 if ( !highlights.isEmpty() )
02592 {
02593 int pri = -1;
02594 int hl = -1;
02595
02596 for (Highlight *highlight = highlights.first(); highlight != 0L; highlight = highlights.next())
02597 {
02598 if (highlight->priority() > pri)
02599 {
02600 pri = highlight->priority();
02601 hl = hlList.findRef (highlight);
02602 }
02603 }
02604
02605 return hl;
02606 }
02607
02608 return -1;
02609 }
02610
02611 uint HlManager::defaultStyles()
02612 {
02613 return 10;
02614 }
02615
02616 QString HlManager::defaultStyleName(int n)
02617 {
02618 static QStringList names;
02619
02620 if (names.isEmpty())
02621 {
02622 names << i18n("Normal");
02623 names << i18n("Keyword");
02624 names << i18n("Data Type");
02625 names << i18n("Decimal/Value");
02626 names << i18n("Base-N Integer");
02627 names << i18n("Floating Point");
02628 names << i18n("Character");
02629 names << i18n("String");
02630 names << i18n("Comment");
02631 names << i18n("Others");
02632 }
02633
02634 return names[n];
02635 }
02636
02637 void HlManager::getDefaults(uint schema, KateAttributeList &list)
02638 {
02639 list.setAutoDelete(true);
02640
02641 KateAttribute* normal = new KateAttribute();
02642 normal->setTextColor(Qt::black);
02643 normal->setSelectedTextColor(Qt::white);
02644 list.append(normal);
02645
02646 KateAttribute* keyword = new KateAttribute();
02647 keyword->setTextColor(Qt::black);
02648 keyword->setSelectedTextColor(Qt::white);
02649 keyword->setBold(true);
02650 list.append(keyword);
02651
02652 KateAttribute* dataType = new KateAttribute();
02653 dataType->setTextColor(Qt::darkRed);
02654 dataType->setSelectedTextColor(Qt::white);
02655 list.append(dataType);
02656
02657 KateAttribute* decimal = new KateAttribute();
02658 decimal->setTextColor(Qt::blue);
02659 decimal->setSelectedTextColor(Qt::cyan);
02660 list.append(decimal);
02661
02662 KateAttribute* basen = new KateAttribute();
02663 basen->setTextColor(Qt::darkCyan);
02664 basen->setSelectedTextColor(Qt::cyan);
02665 list.append(basen);
02666
02667 KateAttribute* floatAttribute = new KateAttribute();
02668 floatAttribute->setTextColor(Qt::darkMagenta);
02669 floatAttribute->setSelectedTextColor(Qt::cyan);
02670 list.append(floatAttribute);
02671
02672 KateAttribute* charAttribute = new KateAttribute();
02673 charAttribute->setTextColor(Qt::magenta);
02674 charAttribute->setSelectedTextColor(Qt::magenta);
02675 list.append(charAttribute);
02676
02677 KateAttribute* string = new KateAttribute();
02678 string->setTextColor(Qt::red);
02679 string->setSelectedTextColor(Qt::red);
02680 list.append(string);
02681
02682 KateAttribute* comment = new KateAttribute();
02683 comment->setTextColor(Qt::darkGray);
02684 comment->setSelectedTextColor(Qt::gray);
02685 comment->setItalic(true);
02686 list.append(comment);
02687
02688 KateAttribute* others = new KateAttribute();
02689 others->setTextColor(Qt::darkGreen);
02690 others->setSelectedTextColor(Qt::green);
02691 list.append(others);
02692
02693 KConfig *config = HlManager::self()->self()->getKConfig();
02694 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema));
02695
02696 for (uint z = 0; z < defaultStyles(); z++)
02697 {
02698 KateAttribute *i = list.at(z);
02699 QStringList s = config->readListEntry(defaultStyleName(z));
02700
02701 if (!s.isEmpty())
02702 {
02703 while( s.count()<8)
02704 s << "";
02705
02706 QString tmp;
02707 QRgb col;
02708
02709 tmp=s[0]; if (!tmp.isEmpty()) {
02710 col=tmp.toUInt(0,16); i->setTextColor(col); }
02711
02712 tmp=s[1]; if (!tmp.isEmpty()) {
02713 col=tmp.toUInt(0,16); i->setSelectedTextColor(col); }
02714
02715 tmp=s[2]; if (!tmp.isEmpty()) i->setBold(tmp!="0");
02716
02717 tmp=s[3]; if (!tmp.isEmpty()) i->setItalic(tmp!="0");
02718
02719 tmp=s[4]; if (!tmp.isEmpty()) i->setStrikeOut(tmp!="0");
02720
02721 tmp=s[5]; if (!tmp.isEmpty()) i->setUnderline(tmp!="0");
02722
02723 tmp=s[6]; if (!tmp.isEmpty()) {
02724 col=tmp.toUInt(0,16); i->setBGColor(col); }
02725
02726 tmp=s[7]; if (!tmp.isEmpty()) {
02727 col=tmp.toUInt(0,16); i->setSelectedBGColor(col); }
02728
02729 }
02730
02731 }
02732 }
02733
02734 void HlManager::setDefaults(uint schema, KateAttributeList &list)
02735 {
02736 KConfig *config = HlManager::self()->self()->getKConfig();
02737 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema));
02738
02739 for (uint z = 0; z < defaultStyles(); z++)
02740 {
02741 QStringList settings;
02742 KateAttribute *i = list.at(z);
02743
02744 settings<<(i->itemSet(KateAttribute::TextColor)?QString::number(i->textColor().rgb(),16):"");
02745 settings<<(i->itemSet(KateAttribute::SelectedTextColor)?QString::number(i->selectedTextColor().rgb(),16):"");
02746 settings<<(i->itemSet(KateAttribute::Weight)?(i->bold()?"1":"0"):"");
02747 settings<<(i->itemSet(KateAttribute::Italic)?(i->italic()?"1":"0"):"");
02748 settings<<(i->itemSet(KateAttribute::StrikeOut)?(i->strikeOut()?"1":"0"):"");
02749 settings<<(i->itemSet(KateAttribute::Underline)?(i->underline()?"1":"0"):"");
02750 settings<<(i->itemSet(KateAttribute::BGColor)?QString::number(i->bgColor().rgb(),16):"");
02751 settings<<(i->itemSet(KateAttribute::SelectedBGColor)?QString::number(i->selectedBGColor().rgb(),16):"");
02752 settings<<"---";
02753
02754 config->writeEntry(defaultStyleName(z),settings);
02755 }
02756
02757 emit changed();
02758 }
02759
02760 int HlManager::highlights()
02761 {
02762 return (int) hlList.count();
02763 }
02764
02765 QString HlManager::hlName(int n)
02766 {
02767 return hlList.at(n)->name();
02768 }
02769
02770 QString HlManager::hlSection(int n)
02771 {
02772 return hlList.at(n)->section();
02773 }
02774
02775 QString HlManager::identifierForName(const QString& name)
02776 {
02777 Highlight *hl = 0;
02778
02779 if ((hl = hlDict[name]))
02780 return hl->getIdentifier ();
02781
02782 return QString();
02783 }
02784 //END
02785
02786 void KateViewHighlightAction::init()
02787 {
02788 m_doc = 0;
02789 subMenus.setAutoDelete( true );
02790
02791 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow()));
02792 }
02793
02794 void KateViewHighlightAction::updateMenu (Kate::Document *doc)
02795 {
02796 m_doc = doc;
02797 }
02798
02799 void KateViewHighlightAction::slotAboutToShow()
02800 {
02801 Kate::Document *doc=m_doc;
02802 int count = HlManager::self()->highlights();
02803
02804 for (int z=0; z<count; z++)
02805 {
02806 QString hlName = HlManager::self()->hlName (z);
02807 QString hlSection = HlManager::self()->hlSection (z);
02808
02809 if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) )
02810 {
02811 if (subMenusName.contains(hlSection) < 1)
02812 {
02813 subMenusName << hlSection;
02814 QPopupMenu *menu = new QPopupMenu ();
02815 subMenus.append(menu);
02816 popupMenu()->insertItem (hlSection, menu);
02817 }
02818
02819 int m = subMenusName.findIndex (hlSection);
02820 names << hlName;
02821 subMenus.at(m)->insertItem ( hlName, this, SLOT(setHl(int)), 0, z);
02822 }
02823 else if (names.contains(hlName) < 1)
02824 {
02825 names << hlName;
02826 popupMenu()->insertItem ( hlName, this, SLOT(setHl(int)), 0, z);
02827 }
02828 }
02829
02830 if (!doc) return;
02831
02832 for (uint i=0;i<subMenus.count();i++)
02833 {
02834 for (uint i2=0;i2<subMenus.at(i)->count();i2++)
02835 subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false);
02836 }
02837 popupMenu()->setItemChecked (0, false);
02838
02839 int i = subMenusName.findIndex (HlManager::self()->hlSection(doc->hlMode()));
02840 if (i >= 0 && subMenus.at(i))
02841 subMenus.at(i)->setItemChecked (doc->hlMode(), true);
02842 else
02843 popupMenu()->setItemChecked (0, true);
02844 }
02845
02846 void KateViewHighlightAction::setHl (int mode)
02847 {
02848 Kate::Document *doc=m_doc;
02849
02850 if (doc)
02851 doc->setHlMode((uint)mode);
02852 }
02853
02854 // kate: space-indent on; indent-width 2; replace-tabs on;