00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "katehighlight.h"
00025 #include "katehighlight.moc"
00026
00027 #include "katetextline.h"
00028 #include "katedocument.h"
00029 #include "katesyntaxdocument.h"
00030 #include "katerenderer.h"
00031 #include "katefactory.h"
00032 #include "kateschema.h"
00033 #include "kateconfig.h"
00034
00035 #include <kconfig.h>
00036 #include <kglobal.h>
00037 #include <kinstance.h>
00038 #include <kmimetype.h>
00039 #include <klocale.h>
00040 #include <kregexp.h>
00041 #include <kpopupmenu.h>
00042 #include <kglobalsettings.h>
00043 #include <kdebug.h>
00044 #include <kstandarddirs.h>
00045 #include <kmessagebox.h>
00046 #include <kstaticdeleter.h>
00047 #include <kapplication.h>
00048
00049 #include <qstringlist.h>
00050 #include <qtextstream.h>
00051
00052
00053
00054
00055 #define KATE_HL_HOWMANY 1024
00056
00057
00058 static const int KATE_DYNAMIC_CONTEXTS_RESET_DELAY = 30 * 1000;
00059
00060
00061 #define IS_TRUE(x) x.lower() == QString("true") || x.toInt() == 1
00062
00063
00064
00065
00066 inline bool kateInsideString (const QString &str, QChar ch)
00067 {
00068 for (uint i=0; i < str.length(); i++)
00069 if (*(str.unicode()+i) == ch)
00070 return true;
00071
00072 return false;
00073 }
00074
00075 class KateHlItem
00076 {
00077 public:
00078 KateHlItem(int attribute, int context,signed char regionId, signed char regionId2);
00079 virtual ~KateHlItem();
00080
00081 public:
00082
00083
00084
00085 virtual int checkHgl(const QString& text, int offset, int len) = 0;
00086
00087 virtual bool lineContinue(){return false;}
00088
00089 virtual QStringList *capturedTexts() {return 0;}
00090 virtual KateHlItem *clone(const QStringList *) {return this;}
00091
00092 static void dynamicSubstitute(QString& str, const QStringList *args);
00093
00094 QMemArray<KateHlItem*> subItems;
00095 int attr;
00096 int ctx;
00097 signed char region;
00098 signed char region2;
00099
00100 bool lookAhead;
00101
00102 bool dynamic;
00103 bool dynamicChild;
00104 bool firstNonSpace;
00105 bool onlyConsume;
00106 int column;
00107
00108
00109
00110 bool alwaysStartEnable;
00111 bool customStartEnable;
00112 };
00113
00114 class KateHlContext
00115 {
00116 public:
00117 KateHlContext(const QString &_hlId, int attribute, int lineEndContext,int _lineBeginContext,
00118 bool _fallthrough, int _fallthroughContext, bool _dynamic);
00119 virtual ~KateHlContext();
00120 KateHlContext *clone(const QStringList *args);
00121
00122 QValueVector<KateHlItem*> items;
00123 QString hlId;
00124 int attr;
00125 int ctx;
00126 int lineBeginContext;
00132 bool fallthrough;
00133 int ftctx;
00134
00135 bool dynamic;
00136 bool dynamicChild;
00137 };
00138
00139 class KateEmbeddedHlInfo
00140 {
00141 public:
00142 KateEmbeddedHlInfo() {loaded=false;context0=-1;}
00143 KateEmbeddedHlInfo(bool l, int ctx0) {loaded=l;context0=ctx0;}
00144
00145 public:
00146 bool loaded;
00147 int context0;
00148 };
00149
00150 class KateHlIncludeRule
00151 {
00152 public:
00153 KateHlIncludeRule(int ctx_=0, uint pos_=0, const QString &incCtxN_="", bool incAttrib=false)
00154 : ctx(ctx_)
00155 , pos( pos_)
00156 , incCtxN( incCtxN_ )
00157 , includeAttrib( incAttrib )
00158 {
00159 incCtx=-1;
00160 }
00161
00162
00163 public:
00164 int ctx;
00165 uint pos;
00166 int incCtx;
00167 QString incCtxN;
00168 bool includeAttrib;
00169 };
00170
00171 class KateHlCharDetect : public KateHlItem
00172 {
00173 public:
00174 KateHlCharDetect(int attribute, int context,signed char regionId,signed char regionId2, QChar);
00175
00176 virtual int checkHgl(const QString& text, int offset, int len);
00177 virtual KateHlItem *clone(const QStringList *args);
00178
00179 private:
00180 QChar sChar;
00181 };
00182
00183 class KateHl2CharDetect : public KateHlItem
00184 {
00185 public:
00186 KateHl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2);
00187 KateHl2CharDetect(int attribute, int context,signed char regionId,signed char regionId2, const QChar *ch);
00188
00189 virtual int checkHgl(const QString& text, int offset, int len);
00190 virtual KateHlItem *clone(const QStringList *args);
00191
00192 private:
00193 QChar sChar1;
00194 QChar sChar2;
00195 };
00196
00197 class KateHlStringDetect : public KateHlItem
00198 {
00199 public:
00200 KateHlStringDetect(int attribute, int context, signed char regionId,signed char regionId2, const QString &, bool inSensitive=false);
00201
00202 virtual int checkHgl(const QString& text, int offset, int len);
00203 virtual KateHlItem *clone(const QStringList *args);
00204
00205 private:
00206 const QString str;
00207 const int strLen;
00208 const bool _inSensitive;
00209 };
00210
00211 class KateHlRangeDetect : public KateHlItem
00212 {
00213 public:
00214 KateHlRangeDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2);
00215
00216 virtual int checkHgl(const QString& text, int offset, int len);
00217
00218 private:
00219 QChar sChar1;
00220 QChar sChar2;
00221 };
00222
00223 class KateHlKeyword : public KateHlItem
00224 {
00225 public:
00226 KateHlKeyword(int attribute, int context,signed char regionId,signed char regionId2, bool casesensitive, const QString& delims);
00227 virtual ~KateHlKeyword ();
00228
00229 void addList(const QStringList &);
00230 virtual int checkHgl(const QString& text, int offset, int len);
00231
00232 private:
00233 QMemArray< QDict<bool>* > dict;
00234 bool _caseSensitive;
00235 const QString& deliminators;
00236 int minLen;
00237 int maxLen;
00238 };
00239
00240 class KateHlInt : public KateHlItem
00241 {
00242 public:
00243 KateHlInt(int attribute, int context, signed char regionId,signed char regionId2);
00244
00245 virtual int checkHgl(const QString& text, int offset, int len);
00246 };
00247
00248 class KateHlFloat : public KateHlItem
00249 {
00250 public:
00251 KateHlFloat(int attribute, int context, signed char regionId,signed char regionId2);
00252 virtual ~KateHlFloat () {}
00253
00254 virtual int checkHgl(const QString& text, int offset, int len);
00255 };
00256
00257 class KateHlCFloat : public KateHlFloat
00258 {
00259 public:
00260 KateHlCFloat(int attribute, int context, signed char regionId,signed char regionId2);
00261
00262 virtual int checkHgl(const QString& text, int offset, int len);
00263 int checkIntHgl(const QString& text, int offset, int len);
00264 };
00265
00266 class KateHlCOct : public KateHlItem
00267 {
00268 public:
00269 KateHlCOct(int attribute, int context, signed char regionId,signed char regionId2);
00270
00271 virtual int checkHgl(const QString& text, int offset, int len);
00272 };
00273
00274 class KateHlCHex : public KateHlItem
00275 {
00276 public:
00277 KateHlCHex(int attribute, int context, signed char regionId,signed char regionId2);
00278
00279 virtual int checkHgl(const QString& text, int offset, int len);
00280 };
00281
00282 class KateHlLineContinue : public KateHlItem
00283 {
00284 public:
00285 KateHlLineContinue(int attribute, int context, signed char regionId,signed char regionId2);
00286
00287 virtual bool endEnable(QChar c) {return c == '\0';}
00288 virtual int checkHgl(const QString& text, int offset, int len);
00289 virtual bool lineContinue(){return true;}
00290 };
00291
00292 class KateHlCStringChar : public KateHlItem
00293 {
00294 public:
00295 KateHlCStringChar(int attribute, int context, signed char regionId,signed char regionId2);
00296
00297 virtual int checkHgl(const QString& text, int offset, int len);
00298 };
00299
00300 class KateHlCChar : public KateHlItem
00301 {
00302 public:
00303 KateHlCChar(int attribute, int context,signed char regionId,signed char regionId2);
00304
00305 virtual int checkHgl(const QString& text, int offset, int len);
00306 };
00307
00308 class KateHlAnyChar : public KateHlItem
00309 {
00310 public:
00311 KateHlAnyChar(int attribute, int context, signed char regionId,signed char regionId2, const QString& charList);
00312
00313 virtual int checkHgl(const QString& text, int offset, int len);
00314
00315 private:
00316 const QString _charList;
00317 };
00318
00319 class KateHlRegExpr : public KateHlItem
00320 {
00321 public:
00322 KateHlRegExpr(int attribute, int context,signed char regionId,signed char regionId2 ,QString expr, bool insensitive, bool minimal);
00323 ~KateHlRegExpr() { delete Expr; };
00324
00325 virtual int checkHgl(const QString& text, int offset, int len);
00326 virtual QStringList *capturedTexts();
00327 virtual KateHlItem *clone(const QStringList *args);
00328
00329 private:
00330 QRegExp *Expr;
00331 bool handlesLinestart;
00332 QString _regexp;
00333 bool _insensitive;
00334 bool _minimal;
00335 };
00336
00337 class KateHlDetectSpaces : public KateHlItem
00338 {
00339 public:
00340 KateHlDetectSpaces (int attribute, int context,signed char regionId,signed char regionId2)
00341 : KateHlItem(attribute,context,regionId,regionId2) {}
00342
00343 virtual int checkHgl(const QString& text, int offset, int len)
00344 {
00345 int len2 = offset + len;
00346 while ((offset < len2) && text[offset].isSpace()) offset++;
00347 return offset;
00348 }
00349 };
00350
00351 class KateHlDetectIdentifier : public KateHlItem
00352 {
00353 public:
00354 KateHlDetectIdentifier (int attribute, int context,signed char regionId,signed char regionId2)
00355 : KateHlItem(attribute,context,regionId,regionId2) { alwaysStartEnable = false; }
00356
00357 virtual int checkHgl(const QString& text, int offset, int len)
00358 {
00359
00360 if ( text[offset].isLetter() || text[offset] == QChar ('_') )
00361 {
00362
00363 int len2 = offset+len;
00364
00365
00366 offset++;
00367
00368
00369 while (
00370 (offset < len2)
00371 && (text[offset].isLetterOrNumber() || (text[offset] == QChar ('_')))
00372 )
00373 offset++;
00374
00375 return offset;
00376 }
00377
00378 return 0;
00379 }
00380 };
00381
00382
00383
00384
00385 KateHlManager *KateHlManager::s_self = 0;
00386
00387 static const bool trueBool = true;
00388 static const QString stdDeliminator = QString (" \t.():!+,-<=>%&*/;?[]^{|}~\\");
00389 //END
00390
00391 //BEGIN NON MEMBER FUNCTIONS
00392 static KateHlItemData::ItemStyles getDefStyleNum(QString name)
00393 {
00394 if (name=="dsNormal") return KateHlItemData::dsNormal;
00395 else if (name=="dsKeyword") return KateHlItemData::dsKeyword;
00396 else if (name=="dsDataType") return KateHlItemData::dsDataType;
00397 else if (name=="dsDecVal") return KateHlItemData::dsDecVal;
00398 else if (name=="dsBaseN") return KateHlItemData::dsBaseN;
00399 else if (name=="dsFloat") return KateHlItemData::dsFloat;
00400 else if (name=="dsChar") return KateHlItemData::dsChar;
00401 else if (name=="dsString") return KateHlItemData::dsString;
00402 else if (name=="dsComment") return KateHlItemData::dsComment;
00403 else if (name=="dsOthers") return KateHlItemData::dsOthers;
00404 else if (name=="dsAlert") return KateHlItemData::dsAlert;
00405 else if (name=="dsFunction") return KateHlItemData::dsFunction;
00406 else if (name=="dsRegionMarker") return KateHlItemData::dsRegionMarker;
00407 else if (name=="dsError") return KateHlItemData::dsError;
00408
00409 return KateHlItemData::dsNormal;
00410 }
00411 //END
00412
00413 //BEGIN KateHlItem
00414 KateHlItem::KateHlItem(int attribute, int context,signed char regionId,signed char regionId2)
00415 : attr(attribute),
00416 ctx(context),
00417 region(regionId),
00418 region2(regionId2),
00419 lookAhead(false),
00420 dynamic(false),
00421 dynamicChild(false),
00422 firstNonSpace(false),
00423 onlyConsume(false),
00424 column (-1),
00425 alwaysStartEnable (true),
00426 customStartEnable (false)
00427 {
00428 }
00429
00430 KateHlItem::~KateHlItem()
00431 {
00432 //kdDebug(13010)<<"In hlItem::~KateHlItem()"<<endl;
00433 for (uint i=0; i < subItems.size(); i++)
00434 delete subItems[i];
00435 }
00436
00437 void KateHlItem::dynamicSubstitute(QString &str, const QStringList *args)
00438 {
00439 for (uint i = 0; i < str.length() - 1; ++i)
00440 {
00441 if (str[i] == '%')
00442 {
00443 char c = str[i + 1].latin1();
00444 if (c == '%')
00445 str.replace(i, 1, "");
00446 else if (c >= '0' && c <= '9')
00447 {
00448 if ((uint)(c - '0') < args->size())
00449 {
00450 str.replace(i, 2, (*args)[c - '0']);
00451 i += ((*args)[c - '0']).length() - 1;
00452 }
00453 else
00454 {
00455 str.replace(i, 2, "");
00456 --i;
00457 }
00458 }
00459 }
00460 }
00461 }
00462 //END
00463
00464 //BEGIN KateHlCharDetect
00465 KateHlCharDetect::KateHlCharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar c)
00466 : KateHlItem(attribute,context,regionId,regionId2)
00467 , sChar(c)
00468 {
00469 }
00470
00471 int KateHlCharDetect::checkHgl(const QString& text, int offset, int /*len*/)
00472 {
00473 if (text[offset] == sChar)
00474 return offset + 1;
00475
00476 return 0;
00477 }
00478
00479 KateHlItem *KateHlCharDetect::clone(const QStringList *args)
00480 {
00481 char c = sChar.latin1();
00482
00483 if (c < '0' || c > '9' || (unsigned)(c - '0') >= args->size())
00484 return this;
00485
00486 KateHlCharDetect *ret = new KateHlCharDetect(attr, ctx, region, region2, (*args)[c - '0'][0]);
00487 ret->dynamicChild = true;
00488 return ret;
00489 }
00490 //END
00491
00492 //BEGIN KateHl2CharDetect
00493 KateHl2CharDetect::KateHl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2)
00494 : KateHlItem(attribute,context,regionId,regionId2)
00495 , sChar1 (ch1)
00496 , sChar2 (ch2)
00497 {
00498 }
00499
00500 int KateHl2CharDetect::checkHgl(const QString& text, int offset, int len)
00501 {
00502 if ((len >= 2) && text[offset++] == sChar1 && text[offset++] == sChar2)
00503 return offset;
00504
00505 return 0;
00506 }
00507
00508 KateHlItem *KateHl2CharDetect::clone(const QStringList *args)
00509 {
00510 char c1 = sChar1.latin1();
00511 char c2 = sChar2.latin1();
00512
00513 if (c1 < '0' || c1 > '9' || (unsigned)(c1 - '0') >= args->size())
00514 return this;
00515
00516 if (c2 < '0' || c2 > '9' || (unsigned)(c2 - '0') >= args->size())
00517 return this;
00518
00519 KateHl2CharDetect *ret = new KateHl2CharDetect(attr, ctx, region, region2, (*args)[c1 - '0'][0], (*args)[c2 - '0'][0]);
00520 ret->dynamicChild = true;
00521 return ret;
00522 }
00523 //END
00524
00525 //BEGIN KateHlStringDetect
00526 KateHlStringDetect::KateHlStringDetect(int attribute, int context, signed char regionId,signed char regionId2,const QString &s, bool inSensitive)
00527 : KateHlItem(attribute, context,regionId,regionId2)
00528 , str(inSensitive ? s.upper() : s)
00529 , strLen (str.length())
00530 , _inSensitive(inSensitive)
00531 {
00532 }
00533
00534 int KateHlStringDetect::checkHgl(const QString& text, int offset, int len)
00535 {
00536 if (len < strLen)
00537 return 0;
00538
00539 if (_inSensitive)
00540 {
00541 for (int i=0; i < strLen; i++)
00542 if (text[offset++].upper() != str[i])
00543 return 0;
00544
00545 return offset;
00546 }
00547 else
00548 {
00549 for (int i=0; i < strLen; i++)
00550 if (text[offset++] != str[i])
00551 return 0;
00552
00553 return offset;
00554 }
00555
00556 return 0;
00557 }
00558
00559 KateHlItem *KateHlStringDetect::clone(const QStringList *args)
00560 {
00561 QString newstr = str;
00562
00563 dynamicSubstitute(newstr, args);
00564
00565 if (newstr == str)
00566 return this;
00567
00568 KateHlStringDetect *ret = new KateHlStringDetect(attr, ctx, region, region2, newstr, _inSensitive);
00569 ret->dynamicChild = true;
00570 return ret;
00571 }
00572 //END
00573
00574 //BEGIN KateHlRangeDetect
00575 KateHlRangeDetect::KateHlRangeDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2)
00576 : KateHlItem(attribute,context,regionId,regionId2)
00577 , sChar1 (ch1)
00578 , sChar2 (ch2)
00579 {
00580 }
00581
00582 int KateHlRangeDetect::checkHgl(const QString& text, int offset, int len)
00583 {
00584 if (text[offset] == sChar1)
00585 {
00586 do
00587 {
00588 offset++;
00589 len--;
00590 if (len < 1) return 0;
00591 }
00592 while (text[offset] != sChar2);
00593
00594 return offset + 1;
00595 }
00596 return 0;
00597 }
00598 //END
00599
00600 //BEGIN KateHlKeyword
00601 KateHlKeyword::KateHlKeyword (int attribute, int context, signed char regionId,signed char regionId2, bool casesensitive, const QString& delims)
00602 : KateHlItem(attribute,context,regionId,regionId2)
00603 , _caseSensitive(casesensitive)
00604 , deliminators(delims)
00605 , minLen (0xFFFFFF)
00606 , maxLen (0)
00607 {
00608 alwaysStartEnable = false;
00609 customStartEnable = true;
00610 }
00611
00612 KateHlKeyword::~KateHlKeyword ()
00613 {
00614 for (uint i=0; i < dict.size(); ++i)
00615 delete dict[i];
00616 }
00617
00618 void KateHlKeyword::addList(const QStringList& list)
00619 {
00620 for(uint i=0; i < list.count(); ++i)
00621 {
00622 int len = list[i].length();
00623
00624 if (minLen > len)
00625 minLen = len;
00626
00627 if (maxLen < len)
00628 maxLen = len;
00629
00630 if ((uint)len >= dict.size())
00631 {
00632 uint oldSize = dict.size();
00633 dict.resize (len+1);
00634
00635 for (uint m=oldSize; m < dict.size(); ++m)
00636 dict[m] = 0;
00637 }
00638
00639 if (!dict[len])
00640 dict[len] = new QDict<bool> (17, _caseSensitive);
00641
00642 dict[len]->insert(list[i], &trueBool);
00643 }
00644 }
00645
00646 int KateHlKeyword::checkHgl(const QString& text, int offset, int len)
00647 {
00648 int offset2 = offset;
00649 int wordLen = 0;
00650
00651 while ((len > wordLen) && !kateInsideString (deliminators, text[offset2]))
00652 {
00653 offset2++;
00654 wordLen++;
00655
00656 if (wordLen > maxLen) return 0;
00657 }
00658
00659 if (wordLen < minLen) return 0;
00660
00661 if ( dict[wordLen] && dict[wordLen]->find(QConstString(text.unicode() + offset, wordLen).string()) )
00662 return offset2;
00663
00664 return 0;
00665 }
00666 //END
00667
00668 //BEGIN KateHlInt
00669 KateHlInt::KateHlInt(int attribute, int context, signed char regionId,signed char regionId2)
00670 : KateHlItem(attribute,context,regionId,regionId2)
00671 {
00672 alwaysStartEnable = false;
00673 }
00674
00675 int KateHlInt::checkHgl(const QString& text, int offset, int len)
00676 {
00677 int offset2 = offset;
00678
00679 while ((len > 0) && text[offset2].isDigit())
00680 {
00681 offset2++;
00682 len--;
00683 }
00684
00685 if (offset2 > offset)
00686 {
00687 if (len > 0)
00688 {
00689 for (uint i=0; i < subItems.size(); i++)
00690 {
00691 if ( (offset = subItems[i]->checkHgl(text, offset2, len)) )
00692 return offset;
00693 }
00694 }
00695
00696 return offset2;
00697 }
00698
00699 return 0;
00700 }
00701 //END
00702
00703 //BEGIN KateHlFloat
00704 KateHlFloat::KateHlFloat(int attribute, int context, signed char regionId,signed char regionId2)
00705 : KateHlItem(attribute,context, regionId,regionId2)
00706 {
00707 alwaysStartEnable = false;
00708 }
00709
00710 int KateHlFloat::checkHgl(const QString& text, int offset, int len)
00711 {
00712 bool b = false;
00713 bool p = false;
00714
00715 while ((len > 0) && text[offset].isDigit())
00716 {
00717 offset++;
00718 len--;
00719 b = true;
00720 }
00721
00722 if ((len > 0) && (p = (text[offset] == '.')))
00723 {
00724 offset++;
00725 len--;
00726
00727 while ((len > 0) && text[offset].isDigit())
00728 {
00729 offset++;
00730 len--;
00731 b = true;
00732 }
00733 }
00734
00735 if (!b)
00736 return 0;
00737
00738 if ((len > 0) && ((text[offset] & 0xdf) == 'E'))
00739 {
00740 offset++;
00741 len--;
00742 }
00743 else
00744 {
00745 if (!p)
00746 return 0;
00747 else
00748 {
00749 if (len > 0)
00750 {
00751 for (uint i=0; i < subItems.size(); i++)
00752 {
00753 int offset2 = subItems[i]->checkHgl(text, offset, len);
00754
00755 if (offset2)
00756 return offset2;
00757 }
00758 }
00759
00760 return offset;
00761 }
00762 }
00763
00764 if ((len > 0) && (text[offset] == '-' || text[offset] =='+'))
00765 {
00766 offset++;
00767 len--;
00768 }
00769
00770 b = false;
00771
00772 while ((len > 0) && text[offset].isDigit())
00773 {
00774 offset++;
00775 len--;
00776 b = true;
00777 }
00778
00779 if (b)
00780 {
00781 if (len > 0)
00782 {
00783 for (uint i=0; i < subItems.size(); i++)
00784 {
00785 int offset2 = subItems[i]->checkHgl(text, offset, len);
00786
00787 if (offset2)
00788 return offset2;
00789 }
00790 }
00791
00792 return offset;
00793 }
00794
00795 return 0;
00796 }
00797 //END
00798
00799 //BEGIN KateHlCOct
00800 KateHlCOct::KateHlCOct(int attribute, int context, signed char regionId,signed char regionId2)
00801 : KateHlItem(attribute,context,regionId,regionId2)
00802 {
00803 alwaysStartEnable = false;
00804 }
00805
00806 int KateHlCOct::checkHgl(const QString& text, int offset, int len)
00807 {
00808 if (text[offset] == '0')
00809 {
00810 offset++;
00811 len--;
00812
00813 int offset2 = offset;
00814
00815 while ((len > 0) && (text[offset2] >= '0' && text[offset2] <= '7'))
00816 {
00817 offset2++;
00818 len--;
00819 }
00820
00821 if (offset2 > offset)
00822 {
00823 if ((len > 0) && ((text[offset2] & 0xdf) == 'L' || (text[offset] & 0xdf) == 'U' ))
00824 offset2++;
00825
00826 return offset2;
00827 }
00828 }
00829
00830 return 0;
00831 }
00832 //END
00833
00834 //BEGIN KateHlCHex
00835 KateHlCHex::KateHlCHex(int attribute, int context,signed char regionId,signed char regionId2)
00836 : KateHlItem(attribute,context,regionId,regionId2)
00837 {
00838 alwaysStartEnable = false;
00839 }
00840
00841 int KateHlCHex::checkHgl(const QString& text, int offset, int len)
00842 {
00843 if ((len > 1) && (text[offset++] == '0') && ((text[offset++] & 0xdf) == 'X' ))
00844 {
00845 len -= 2;
00846
00847 int offset2 = offset;
00848
00849 while ((len > 0) && (text[offset2].isDigit() || ((text[offset2] & 0xdf) >= 'A' && (text[offset2] & 0xdf) <= 'F')))
00850 {
00851 offset2++;
00852 len--;
00853 }
00854
00855 if (offset2 > offset)
00856 {
00857 if ((len > 0) && ((text[offset2] & 0xdf) == 'L' || (text[offset2] & 0xdf) == 'U' ))
00858 offset2++;
00859
00860 return offset2;
00861 }
00862 }
00863
00864 return 0;
00865 }
00866 //END
00867
00868 //BEGIN KateHlCFloat
00869 KateHlCFloat::KateHlCFloat(int attribute, int context, signed char regionId,signed char regionId2)
00870 : KateHlFloat(attribute,context,regionId,regionId2)
00871 {
00872 alwaysStartEnable = false;
00873 }
00874
00875 int KateHlCFloat::checkIntHgl(const QString& text, int offset, int len)
00876 {
00877 int offset2 = offset;
00878
00879 while ((len > 0) && text[offset].isDigit()) {
00880 offset2++;
00881 len--;
00882 }
00883
00884 if (offset2 > offset)
00885 return offset2;
00886
00887 return 0;
00888 }
00889
00890 int KateHlCFloat::checkHgl(const QString& text, int offset, int len)
00891 {
00892 int offset2 = KateHlFloat::checkHgl(text, offset, len);
00893
00894 if (offset2)
00895 {
00896 if ((text[offset2] & 0xdf) == 'F' )
00897 offset2++;
00898
00899 return offset2;
00900 }
00901 else
00902 {
00903 offset2 = checkIntHgl(text, offset, len);
00904
00905 if (offset2 && ((text[offset2] & 0xdf) == 'F' ))
00906 return ++offset2;
00907 else
00908 return 0;
00909 }
00910 }
00911 //END
00912
00913 //BEGIN KateHlAnyChar
00914 KateHlAnyChar::KateHlAnyChar(int attribute, int context, signed char regionId,signed char regionId2, const QString& charList)
00915 : KateHlItem(attribute, context,regionId,regionId2)
00916 , _charList(charList)
00917 {
00918 }
00919
00920 int KateHlAnyChar::checkHgl(const QString& text, int offset, int)
00921 {
00922 if (kateInsideString (_charList, text[offset]))
00923 return ++offset;
00924
00925 return 0;
00926 }
00927 //END
00928
00929 //BEGIN KateHlRegExpr
00930 KateHlRegExpr::KateHlRegExpr( int attribute, int context, signed char regionId,signed char regionId2, QString regexp, bool insensitive, bool minimal)
00931 : KateHlItem(attribute, context, regionId,regionId2)
00932 , handlesLinestart (regexp.startsWith("^"))
00933 , _regexp(regexp)
00934 , _insensitive(insensitive)
00935 , _minimal(minimal)
00936 {
00937 if (!handlesLinestart)
00938 regexp.prepend("^");
00939
00940 Expr = new QRegExp(regexp, !_insensitive);
00941 Expr->setMinimal(_minimal);
00942 }
00943
00944 int KateHlRegExpr::checkHgl(const QString& text, int offset, int /*len*/)
00945 {
00946 if (offset && handlesLinestart)
00947 return 0;
00948
00949 int offset2 = Expr->search( text, offset, QRegExp::CaretAtOffset );
00950
00951 if (offset2 == -1) return 0;
00952
00953 return (offset + Expr->matchedLength());
00954 }
00955
00956 QStringList *KateHlRegExpr::capturedTexts()
00957 {
00958 return new QStringList(Expr->capturedTexts());
00959 }
00960
00961 KateHlItem *KateHlRegExpr::clone(const QStringList *args)
00962 {
00963 QString regexp = _regexp;
00964 QStringList escArgs = *args;
00965
00966 for (QStringList::Iterator it = escArgs.begin(); it != escArgs.end(); ++it)
00967 {
00968 (*it).replace(QRegExp("(\\W)"), "\\\\1");
00969 }
00970
00971 dynamicSubstitute(regexp, &escArgs);
00972
00973 if (regexp == _regexp)
00974 return this;
00975
00976 // kdDebug (13010) << "clone regexp: " << regexp << endl;
00977
00978 KateHlRegExpr *ret = new KateHlRegExpr(attr, ctx, region, region2, regexp, _insensitive, _minimal);
00979 ret->dynamicChild = true;
00980 return ret;
00981 }
00982 //END
00983
00984 //BEGIN KateHlLineContinue
00985 KateHlLineContinue::KateHlLineContinue(int attribute, int context, signed char regionId,signed char regionId2)
00986 : KateHlItem(attribute,context,regionId,regionId2) {
00987 }
00988
00989 int KateHlLineContinue::checkHgl(const QString& text, int offset, int len)
00990 {
00991 if ((len == 1) && (text[offset] == '\\'))
00992 return ++offset;
00993
00994 return 0;
00995 }
00996 //END
00997
00998 //BEGIN KateHlCStringChar
00999 KateHlCStringChar::KateHlCStringChar(int attribute, int context,signed char regionId,signed char regionId2)
01000 : KateHlItem(attribute,context,regionId,regionId2) {
01001 }
01002
01003 // checks for C escaped chars \n and escaped hex/octal chars
01004 static int checkEscapedChar(const QString& text, int offset, int& len)
01005 {
01006 int i;
01007 if (text[offset] == '\\' && len > 1)
01008 {
01009 offset++;
01010 len--;
01011
01012 switch(text[offset])
01013 {
01014 case 'a': // checks for control chars
01015 case 'b': // we want to fall through
01016 case 'e':
01017 case 'f':
01018
01019 case 'n':
01020 case 'r':
01021 case 't':
01022 case 'v':
01023 case '\'':
01024 case '\"':
01025 case '?' : // added ? ANSI C classifies this as an escaped char
01026 case '\\':
01027 offset++;
01028 len--;
01029 break;
01030
01031 case 'x': // if it's like \xff
01032 offset++; // eat the x
01033 len--;
01034 // these for loops can probably be
01035 // replaced with something else but
01036 // for right now they work
01037 // check for hexdigits
01038 for (i = 0; (len > 0) && (i < 2) && (text[offset] >= '0' && text[offset] <= '9' || (text[offset] & 0xdf) >= 'A' && (text[offset] & 0xdf) <= 'F'); i++)
01039 {
01040 offset++;
01041 len--;
01042 }
01043
01044 if (i == 0)
01045 return 0; // takes care of case '\x'
01046
01047 break;
01048
01049 case '0': case '1': case '2': case '3' :
01050 case '4': case '5': case '6': case '7' :
01051 for (i = 0; (len > 0) && (i < 3) && (text[offset] >='0'&& text[offset] <='7'); i++)
01052 {
01053 offset++;
01054 len--;
01055 }
01056 break;
01057
01058 default:
01059 return 0;
01060 }
01061
01062 return offset;
01063 }
01064
01065 return 0;
01066 }
01067
01068 int KateHlCStringChar::checkHgl(const QString& text, int offset, int len)
01069 {
01070 return checkEscapedChar(text, offset, len);
01071 }
01072 //END
01073
01074 //BEGIN KateHlCChar
01075 KateHlCChar::KateHlCChar(int attribute, int context,signed char regionId,signed char regionId2)
01076 : KateHlItem(attribute,context,regionId,regionId2) {
01077 }
01078
01079 int KateHlCChar::checkHgl(const QString& text, int offset, int len)
01080 {
01081 if ((len > 1) && (text[offset] == '\'') && (text[offset+1] != '\''))
01082 {
01083 int oldl;
01084 oldl = len;
01085
01086 len--;
01087
01088 int offset2 = checkEscapedChar(text, offset + 1, len);
01089
01090 if (!offset2)
01091 {
01092 if (oldl > 2)
01093 {
01094 offset2 = offset + 2;
01095 len = oldl - 2;
01096 }
01097 else
01098 {
01099 return 0;
01100 }
01101 }
01102
01103 if ((len > 0) && (text[offset2] == '\''))
01104 return ++offset2;
01105 }
01106
01107 return 0;
01108 }
01109 //END
01110
01111 //BEGIN KateHl2CharDetect
01112 KateHl2CharDetect::KateHl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, const QChar *s)
01113 : KateHlItem(attribute,context,regionId,regionId2) {
01114 sChar1 = s[0];
01115 sChar2 = s[1];
01116 }
01117 //END KateHl2CharDetect
01118
01119 KateHlItemData::KateHlItemData(const QString name, int defStyleNum)
01120 : name(name), defStyleNum(defStyleNum) {
01121 }
01122
01123 KateHlData::KateHlData(const QString &wildcards, const QString &mimetypes, const QString &identifier, int priority)
01124 : wildcards(wildcards), mimetypes(mimetypes), identifier(identifier), priority(priority)
01125 {
01126 }
01127
01128 //BEGIN KateHlContext
01129 KateHlContext::KateHlContext (const QString &_hlId, int attribute, int lineEndContext, int _lineBeginContext, bool _fallthrough, int _fallthroughContext, bool _dynamic)
01130 {
01131 hlId = _hlId;
01132 attr = attribute;
01133 ctx = lineEndContext;
01134 lineBeginContext = _lineBeginContext;
01135 fallthrough = _fallthrough;
01136 ftctx = _fallthroughContext;
01137 dynamic = _dynamic;
01138 dynamicChild = false;
01139 }
01140
01141 KateHlContext *KateHlContext::clone(const QStringList *args)
01142 {
01143 KateHlContext *ret = new KateHlContext(hlId, attr, ctx, lineBeginContext, fallthrough, ftctx, false);
01144
01145 for (uint n=0; n < items.size(); ++n)
01146 {
01147 KateHlItem *item = items[n];
01148 KateHlItem *i = (item->dynamic ? item->clone(args) : item);
01149 ret->items.append(i);
01150 }
01151
01152 ret->dynamicChild = true;
01153
01154 return ret;
01155 }
01156
01157 KateHlContext::~KateHlContext()
01158 {
01159 if (dynamicChild)
01160 {
01161 for (uint n=0; n < items.size(); ++n)
01162 {
01163 if (items[n]->dynamicChild)
01164 delete items[n];
01165 }
01166 }
01167 }
01168 //END
01169
01170 //BEGIN KateHighlighting
01171 KateHighlighting::KateHighlighting(const KateSyntaxModeListItem *def) : refCount(0)
01172 {
01173 m_attributeArrays.setAutoDelete (true);
01174
01175 errorsAndWarnings = "";
01176 building=false;
01177 noHl = false;
01178 m_foldingIndentationSensitive = false;
01179 folding=false;
01180 internalIDList.setAutoDelete(true);
01181
01182 if (def == 0)
01183 {
01184 noHl = true;
01185 iName = "None"; // not translated internal name (for config and more)
01186 iNameTranslated = i18n("None"); // user visible name
01187 iSection = "";
01188 m_priority = 0;
01189 iHidden = false;
01190 m_additionalData.insert( "none", new HighlightPropertyBag );
01191 m_additionalData["none"]->deliminator = stdDeliminator;
01192 m_additionalData["none"]->wordWrapDeliminator = stdDeliminator;
01193 m_hlIndex[0] = "none";
01194 }
01195 else
01196 {
01197 iName = def->name;
01198 iNameTranslated = def->nameTranslated;
01199 iSection = def->section;
01200 iHidden = def->hidden;
01201 iWildcards = def->extension;
01202 iMimetypes = def->mimetype;
01203 identifier = def->identifier;
01204 iVersion=def->version;
01205 iAuthor=def->author;
01206 iLicense=def->license;
01207 m_priority=def->priority.toInt();
01208 }
01209
01210 deliminator = stdDeliminator;
01211 }
01212
01213 KateHighlighting::~KateHighlighting()
01214 {
01215 for (uint i=0; i < m_contexts.size(); ++i)
01216 delete m_contexts[i];
01217 }
01218
01219 void KateHighlighting::generateContextStack(int *ctxNum, int ctx, QMemArray<short>* ctxs, int *prevLine)
01220 {
01221 //kdDebug(13010)<<QString("Entering generateContextStack with %1").arg(ctx)<<endl;
01222 while (true)
01223 {
01224 if (ctx >= 0)
01225 {
01226 (*ctxNum) = ctx;
01227
01228 ctxs->resize (ctxs->size()+1, QGArray::SpeedOptim);
01229 (*ctxs)[ctxs->size()-1]=(*ctxNum);
01230
01231 return;
01232 }
01233 else
01234 {
01235 if (ctx == -1)
01236 {
01237 (*ctxNum)=( (ctxs->isEmpty() ) ? 0 : (*ctxs)[ctxs->size()-1]);
01238 }
01239 else
01240 {
01241 int size = ctxs->size() + ctx + 1;
01242
01243 if (size > 0)
01244 {
01245 ctxs->resize (size, QGArray::SpeedOptim);
01246 (*ctxNum)=(*ctxs)[size-1];
01247 }
01248 else
01249 {
01250 ctxs->resize (0, QGArray::SpeedOptim);
01251 (*ctxNum)=0;
01252 }
01253
01254 ctx = 0;
01255
01256 if ((*prevLine) >= (int)(ctxs->size()-1))
01257 {
01258 *prevLine=ctxs->size()-1;
01259
01260 if ( ctxs->isEmpty() )
01261 return;
01262
01263 KateHlContext *c = contextNum((*ctxs)[ctxs->size()-1]);
01264 if (c && (c->ctx != -1))
01265 {
01266 //kdDebug(13010)<<"PrevLine > size()-1 and ctx!=-1)"<<endl;
01267 ctx = c->ctx;
01268
01269 continue;
01270 }
01271 }
01272 }
01273
01274 return;
01275 }
01276 }
01277 }
01278
01282 int KateHighlighting::makeDynamicContext(KateHlContext *model, const QStringList *args)
01283 {
01284 QPair<KateHlContext *, QString> key(model, args->front());
01285 short value;
01286
01287 if (dynamicCtxs.contains(key))
01288 value = dynamicCtxs[key];
01289 else
01290 {
01291 kdDebug(13010) << "new stuff: " << startctx << endl;
01292
01293 KateHlContext *newctx = model->clone(args);
01294
01295 m_contexts.push_back (newctx);
01296
01297 value = startctx++;
01298 dynamicCtxs[key] = value;
01299 KateHlManager::self()->incDynamicCtxs();
01300 }
01301
01302 // kdDebug(13010) << "Dynamic context: using context #" << value << " (for model " << model << " with args " << *args << ")" << endl;
01303
01304 return value;
01305 }
01306
01311 void KateHighlighting::dropDynamicContexts()
01312 {
01313 for (uint i=base_startctx; i < m_contexts.size(); ++i)
01314 delete m_contexts[i];
01315
01316 m_contexts.resize (base_startctx);
01317
01318 dynamicCtxs.clear();
01319 startctx = base_startctx;
01320 }
01321
01330 void KateHighlighting::doHighlight ( KateTextLine *prevLine,
01331 KateTextLine *textLine,
01332 QMemArray<uint>* foldingList,
01333 bool *ctxChanged )
01334 {
01335 if (!textLine)
01336 return;
01337
01338 if (noHl)
01339 {
01340 if (textLine->length() > 0)
01341 memset (textLine->attributes(), 0, textLine->length());
01342
01343 return;
01344 }
01345
01346 // duplicate the ctx stack, only once !
01347 QMemArray<short> ctx;
01348 ctx.duplicate (prevLine->ctxArray());
01349
01350 int ctxNum = 0;
01351 int previousLine = -1;
01352 KateHlContext *context;
01353
01354 if (ctx.isEmpty())
01355 {
01356 // If the stack is empty, we assume to be in Context 0 (Normal)
01357 context = contextNum(ctxNum);
01358 }
01359 else
01360 {
01361 // There does an old context stack exist -> find the context at the line start
01362 ctxNum = ctx[ctx.size()-1]; //context ID of the last character in the previous line
01363
01364 //kdDebug(13010) << "\t\tctxNum = " << ctxNum << " contextList[ctxNum] = " << contextList[ctxNum] << endl; // ellis
01365
01366 //if (lineContinue) kdDebug(13010)<<QString("The old context should be %1").arg((int)ctxNum)<<endl;
01367
01368 if (!(context = contextNum(ctxNum)))
01369 context = contextNum(0);
01370
01371 //kdDebug(13010)<<"test1-2-1-text2"<<endl;
01372
01373 previousLine=ctx.size()-1; //position of the last context ID of th previous line within the stack
01374
01375 // hl continue set or not ???
01376 if (prevLine->hlLineContinue())
01377 {
01378 prevLine--;
01379 }
01380 else
01381 {
01382 generateContextStack(&ctxNum, context->ctx, &ctx, &previousLine); //get stack ID to use
01383
01384 if (!(context = contextNum(ctxNum)))
01385 context = contextNum(0);
01386 }
01387
01388 //kdDebug(13010)<<"test1-2-1-text4"<<endl;
01389
01390 //if (lineContinue) kdDebug(13010)<<QString("The new context is %1").arg((int)ctxNum)<<endl;
01391 }
01392
01393 // text, for programming convenience :)
01394 QChar lastChar = ' ';
01395 const QString& text = textLine->string();
01396 const int len = textLine->length();
01397
01398 // calc at which char the first char occurs, set it to lenght of line if never
01399 const int firstChar = textLine->firstChar();
01400 const int startNonSpace = (firstChar == -1) ? len : firstChar;
01401
01402 // last found item
01403 KateHlItem *item = 0;
01404
01405 // loop over the line, offset gives current offset
01406 int offset = 0;
01407 while (offset < len)
01408 {
01409 bool anItemMatched = false;
01410 bool standardStartEnableDetermined = false;
01411 bool customStartEnableDetermined = false;
01412
01413 uint index = 0;
01414 for (item = context->items.empty() ? 0 : context->items[0]; item; item = (++index < context->items.size()) ? context->items[index] : 0 )
01415 {
01416 // does we only match if we are firstNonSpace?
01417 if (item->firstNonSpace && (offset > startNonSpace))
01418 continue;
01419
01420 // have we a column specified? if yes, only match at this column
01421 if ((item->column != -1) && (item->column != offset))
01422 continue;
01423
01424 if (!item->alwaysStartEnable)
01425 {
01426 if (item->customStartEnable)
01427 {
01428 if (customStartEnableDetermined || kateInsideString (m_additionalData[context->hlId]->deliminator, lastChar))
01429 customStartEnableDetermined = true;
01430 else
01431 continue;
01432 }
01433 else
01434 {
01435 if (standardStartEnableDetermined || kateInsideString (stdDeliminator, lastChar))
01436 standardStartEnableDetermined = true;
01437 else
01438 continue;
01439 }
01440 }
01441
01442 int offset2 = item->checkHgl(text, offset, len-offset);
01443
01444 if (offset2 <= offset)
01445 continue;
01446
01447 if (item->region2)
01448 {
01449 // kdDebug(13010)<<QString("Region mark 2 detected: %1").arg(item->region2)<<endl;
01450 if ( !foldingList->isEmpty() && ((item->region2 < 0) && (*foldingList)[foldingList->size()-2] == -item->region2 ) )
01451 {
01452 foldingList->resize (foldingList->size()-2, QGArray::SpeedOptim);
01453 }
01454 else
01455 {
01456 foldingList->resize (foldingList->size()+2, QGArray::SpeedOptim);
01457 (*foldingList)[foldingList->size()-2] = (uint)item->region2;
01458 if (item->region2<0) //check not really needed yet
01459 (*foldingList)[foldingList->size()-1] = offset2;
01460 else
01461 (*foldingList)[foldingList->size()-1] = offset;
01462 }
01463
01464 }
01465
01466 if (item->region)
01467 {
01468 // kdDebug(13010)<<QString("Region mark detected: %1").arg(item->region)<<endl;
01469
01470 /* if ( !foldingList->isEmpty() && ((item->region < 0) && (*foldingList)[foldingList->size()-1] == -item->region ) )
01471 {
01472 foldingList->resize (foldingList->size()-1, QGArray::SpeedOptim);
01473 }
01474 else*/
01475 {
01476 foldingList->resize (foldingList->size()+2, QGArray::SpeedOptim);
01477 (*foldingList)[foldingList->size()-2] = item->region;
01478 if (item->region<0) //check not really needed yet
01479 (*foldingList)[foldingList->size()-1] = offset2;
01480 else
01481 (*foldingList)[foldingList->size()-1] = offset;
01482 }
01483
01484 }
01485
01486 // regenerate context stack if needed
01487 if (item->ctx != -1)
01488 {
01489 generateContextStack (&ctxNum, item->ctx, &ctx, &previousLine);
01490 context = contextNum(ctxNum);
01491 }
01492
01493 // dynamic context: substitute the model with an 'instance'
01494 if (context->dynamic)
01495 {
01496 QStringList *lst = item->capturedTexts();
01497 if (lst != 0)
01498 {
01499 // Replace the top of the stack and the current context
01500 int newctx = makeDynamicContext(context, lst);
01501 if (ctx.size() > 0)
01502 ctx[ctx.size() - 1] = newctx;
01503 ctxNum = newctx;
01504 context = contextNum(ctxNum);
01505 }
01506 delete lst;
01507 }
01508
01509 // dominik: look ahead w/o changing offset?
01510 if (!item->lookAhead)
01511 {
01512 if (offset2 > len)
01513 offset2 = len;
01514
01515 // even set attributes ;)
01516 memset ( textLine->attributes()+offset
01517 , item->onlyConsume ? context->attr : item->attr
01518 , len-offset);
01519
01520 offset = offset2;
01521 lastChar = text[offset-1];
01522 }
01523
01524 anItemMatched = true;
01525 break;
01526 }
01527
01528 // something matched, continue loop
01529 if (anItemMatched)
01530 continue;
01531
01532 // nothing found: set attribute of one char
01533 // anders: unless this context does not want that!
01534 if ( context->fallthrough )
01535 {
01536 // set context to context->ftctx.
01537 generateContextStack(&ctxNum, context->ftctx, &ctx, &previousLine); //regenerate context stack
01538 context=contextNum(ctxNum);
01539 //kdDebug(13010)<<"context num after fallthrough at col "<<z<<": "<<ctxNum<<endl;
01540 // the next is nessecary, as otherwise keyword (or anything using the std delimitor check)
01541 // immediately after fallthrough fails. Is it bad?
01542 // jowenn, can you come up with a nicer way to do this?
01543 /* if (offset)
01544 lastChar = text[offset - 1];
01545 else
01546 lastChar = '\\';*/
01547 continue;
01548 }
01549 else
01550 {
01551 *(textLine->attributes() + offset) = context->attr;
01552 lastChar = text[offset];
01553 offset++;
01554 }
01555 }
01556
01557 // has the context stack changed ?
01558 if (ctx == textLine->ctxArray())
01559 {
01560 if (ctxChanged)
01561 (*ctxChanged) = false;
01562 }
01563 else
01564 {
01565 if (ctxChanged)
01566 (*ctxChanged) = true;
01567
01568 // assign ctx stack !
01569 textLine->setContext(ctx);
01570 }
01571
01572 // write hl continue flag
01573 textLine->setHlLineContinue (item && item->lineContinue());
01574 }
01575
01576 void KateHighlighting::loadWildcards()
01577 {
01578 KConfig *config = KateHlManager::self()->getKConfig();
01579 config->setGroup("Highlighting " + iName);
01580
01581 QString extensionString = config->readEntry("Wildcards", iWildcards);
01582
01583 if (extensionSource != extensionString) {
01584 regexpExtensions.clear();
01585 plainExtensions.clear();
01586
01587 extensionSource = extensionString;
01588
01589 static QRegExp sep("\\s*;\\s*");
01590
01591 QStringList l = QStringList::split( sep, extensionSource );
01592
01593 static QRegExp boringExpression("\\*\\.[\\d\\w]+");
01594
01595 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it )
01596 if (boringExpression.exactMatch(*it))
01597 plainExtensions.append((*it).mid(1));
01598 else
01599 regexpExtensions.append(QRegExp((*it), true, true));
01600 }
01601 }
01602
01603 QValueList<QRegExp>& KateHighlighting::getRegexpExtensions()
01604 {
01605 return regexpExtensions;
01606 }
01607
01608 QStringList& KateHighlighting::getPlainExtensions()
01609 {
01610 return plainExtensions;
01611 }
01612
01613 QString KateHighlighting::getMimetypes()
01614 {
01615 KConfig *config = KateHlManager::self()->getKConfig();
01616 config->setGroup("Highlighting " + iName);
01617
01618 return config->readEntry("Mimetypes", iMimetypes);
01619 }
01620
01621 int KateHighlighting::priority()
01622 {
01623 KConfig *config = KateHlManager::self()->getKConfig();
01624 config->setGroup("Highlighting " + iName);
01625
01626 return config->readNumEntry("Priority", m_priority);
01627 }
01628
01629 KateHlData *KateHighlighting::getData()
01630 {
01631 KConfig *config = KateHlManager::self()->getKConfig();
01632 config->setGroup("Highlighting " + iName);
01633
01634 KateHlData *hlData = new KateHlData(
01635 config->readEntry("Wildcards", iWildcards),
01636 config->readEntry("Mimetypes", iMimetypes),
01637 config->readEntry("Identifier", identifier),
01638 config->readNumEntry("Priority", m_priority));
01639
01640 return hlData;
01641 }
01642
01643 void KateHighlighting::setData(KateHlData *hlData)
01644 {
01645 KConfig *config = KateHlManager::self()->getKConfig();
01646 config->setGroup("Highlighting " + iName);
01647
01648 config->writeEntry("Wildcards",hlData->wildcards);
01649 config->writeEntry("Mimetypes",hlData->mimetypes);
01650 config->writeEntry("Priority",hlData->priority);
01651 }
01652
01653 void KateHighlighting::getKateHlItemDataList (uint schema, KateHlItemDataList &list)
01654 {
01655 KConfig *config = KateHlManager::self()->getKConfig();
01656 config->setGroup("Highlighting " + iName + " - Schema " + KateFactory::self()->schemaManager()->name(schema));
01657
01658 list.clear();
01659 createKateHlItemData(list);
01660
01661 for (KateHlItemData *p = list.first(); p != 0L; p = list.next())
01662 {
01663 QStringList s = config->readListEntry(p->name);
01664
01665 // kdDebug(13010)<<p->name<<s.count()<<endl;
01666 if (s.count()>0)
01667 {
01668
01669 while(s.count()<9) s<<"";
01670 p->clear();
01671
01672 QString tmp=s[0]; if (!tmp.isEmpty()) p->defStyleNum=tmp.toInt();
01673
01674 QRgb col;
01675
01676 tmp=s[1]; if (!tmp.isEmpty()) {
01677 col=tmp.toUInt(0,16); p->setTextColor(col); }
01678
01679 tmp=s[2]; if (!tmp.isEmpty()) {
01680 col=tmp.toUInt(0,16); p->setSelectedTextColor(col); }
01681
01682 tmp=s[3]; if (!tmp.isEmpty()) p->setBold(tmp!="0");
01683
01684 tmp=s[4]; if (!tmp.isEmpty()) p->setItalic(tmp!="0");
01685
01686 tmp=s[5]; if (!tmp.isEmpty()) p->setStrikeOut(tmp!="0");
01687
01688 tmp=s[6]; if (!tmp.isEmpty()) p->setUnderline(tmp!="0");
01689
01690 tmp=s[7]; if (!tmp.isEmpty()) {
01691 col=tmp.toUInt(0,16); p->setBGColor(col); }
01692
01693 tmp=s[8]; if (!tmp.isEmpty()) {
01694 col=tmp.toUInt(0,16); p->setSelectedBGColor(col); }
01695
01696 }
01697 }
01698 }
01699
01706 void KateHighlighting::setKateHlItemDataList(uint schema, KateHlItemDataList &list)
01707 {
01708 KConfig *config = KateHlManager::self()->getKConfig();
01709 config->setGroup("Highlighting " + iName + " - Schema "
01710 + KateFactory::self()->schemaManager()->name(schema));
01711
01712 QStringList settings;
01713
01714 for (KateHlItemData *p = list.first(); p != 0L; p = list.next())
01715 {
01716 settings.clear();
01717 settings<<QString::number(p->defStyleNum,10);
01718 settings<<(p->itemSet(KateAttribute::TextColor)?QString::number(p->textColor().rgb(),16):"");
01719 settings<<(p->itemSet(KateAttribute::SelectedTextColor)?QString::number(p->selectedTextColor().rgb(),16):"");
01720 settings<<(p->itemSet(KateAttribute::Weight)?(p->bold()?"1":"0"):"");
01721 settings<<(p->itemSet(KateAttribute::Italic)?(p->italic()?"1":"0"):"");
01722 settings<<(p->itemSet(KateAttribute::StrikeOut)?(p->strikeOut()?"1":"0"):"");
01723 settings<<(p->itemSet(KateAttribute::Underline)?(p->underline()?"1":"0"):"");
01724 settings<<(p->itemSet(KateAttribute::BGColor)?QString::number(p->bgColor().rgb(),16):"");
01725 settings<<(p->itemSet(KateAttribute::SelectedBGColor)?QString::number(p->selectedBGColor().rgb(),16):"");
01726 settings<<"---";
01727 config->writeEntry(p->name,settings);
01728 }
01729 }
01730
01734 void KateHighlighting::use()
01735 {
01736 if (refCount == 0)
01737 init();
01738
01739 refCount++;
01740 }
01741
01745 void KateHighlighting::release()
01746 {
01747 refCount--;
01748
01749 if (refCount == 0)
01750 done();
01751 }
01752
01757 void KateHighlighting::init()
01758 {
01759 if (noHl)
01760 return;
01761
01762 m_contexts.clear ();
01763 makeContextList();
01764 }
01765
01766
01771 void KateHighlighting::done()
01772 {
01773 if (noHl)
01774 return;
01775
01776 m_contexts.clear ();
01777 internalIDList.clear();
01778 }
01779
01787 void KateHighlighting::createKateHlItemData(KateHlItemDataList &list)
01788 {
01789 // If no highlighting is selected we need only one default.
01790 if (noHl)
01791 {
01792 list.append(new KateHlItemData(i18n("Normal Text"), KateHlItemData::dsNormal));
01793 return;
01794 }
01795
01796 // If the internal list isn't already available read the config file
01797 if (internalIDList.isEmpty())
01798 makeContextList();
01799
01800 list=internalIDList;
01801 }
01802
01806 void KateHighlighting::addToKateHlItemDataList()
01807 {
01808 //Tell the syntax document class which file we want to parse and which data group
01809 KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
01810 KateSyntaxContextData *data = KateHlManager::self()->syntax->getGroupInfo("highlighting","itemData");
01811
01812 //begin with the real parsing
01813 while (KateHlManager::self()->syntax->nextGroup(data))
01814 {
01815 // read all attributes
01816 QString color = KateHlManager::self()->syntax->groupData(data,QString("color"));
01817 QString selColor = KateHlManager::self()->syntax->groupData(data,QString("selColor"));
01818 QString bold = KateHlManager::self()->syntax->groupData(data,QString("bold"));
01819 QString italic = KateHlManager::self()->syntax->groupData(data,QString("italic"));
01820 QString underline = KateHlManager::self()->syntax->groupData(data,QString("underline"));
01821 QString strikeOut = KateHlManager::self()->syntax->groupData(data,QString("strikeOut"));
01822 QString bgColor = KateHlManager::self()->syntax->groupData(data,QString("backgroundColor"));
01823 QString selBgColor = KateHlManager::self()->syntax->groupData(data,QString("selBackgroundColor"));
01824
01825 KateHlItemData* newData = new KateHlItemData(
01826 buildPrefix+KateHlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(),
01827 getDefStyleNum(KateHlManager::self()->syntax->groupData(data,QString("defStyleNum"))));
01828
01829 /* here the custom style overrides are specified, if needed */
01830 if (!color.isEmpty()) newData->setTextColor(QColor(color));
01831 if (!selColor.isEmpty()) newData->setSelectedTextColor(QColor(selColor));
01832 if (!bold.isEmpty()) newData->setBold( IS_TRUE(bold) );
01833 if (!italic.isEmpty()) newData->setItalic( IS_TRUE(italic) );
01834 // new attributes for the new rendering view
01835 if (!underline.isEmpty()) newData->setUnderline( IS_TRUE(underline) );
01836 if (!strikeOut.isEmpty()) newData->setStrikeOut( IS_TRUE(strikeOut) );
01837 if (!bgColor.isEmpty()) newData->setBGColor(QColor(bgColor));
01838 if (!selBgColor.isEmpty()) newData->setSelectedBGColor(QColor(selBgColor));
01839
01840 internalIDList.append(newData);
01841 }
01842
01843 //clean up
01844 if (data)
01845 KateHlManager::self()->syntax->freeGroupInfo(data);
01846 }
01847
01858 int KateHighlighting::lookupAttrName(const QString& name, KateHlItemDataList &iDl)
01859 {
01860 for (uint i = 0; i < iDl.count(); i++)
01861 if (iDl.at(i)->name == buildPrefix+name)
01862 return i;
01863
01864 kdDebug(13010)<<"Couldn't resolve itemDataName:"<<name<<endl;
01865 return 0;
01866 }
01867
01881 KateHlItem *KateHighlighting::createKateHlItem(KateSyntaxContextData *data,
01882 KateHlItemDataList &iDl,
01883 QStringList *RegionList,
01884 QStringList *ContextNameList)
01885 {
01886 // No highlighting -> exit
01887 if (noHl)
01888 return 0;
01889
01890 // get the (tagname) itemd type
01891 QString dataname=KateHlManager::self()->syntax->groupItemData(data,QString(""));
01892
01893 // code folding region handling:
01894 QString beginRegionStr=KateHlManager::self()->syntax->groupItemData(data,QString("beginRegion"));
01895 QString endRegionStr=KateHlManager::self()->syntax->groupItemData(data,QString("endRegion"));
01896
01897 signed char regionId=0;
01898 signed char regionId2=0;
01899
01900 if (!beginRegionStr.isEmpty())
01901 {
01902 regionId = RegionList->findIndex(beginRegionStr);
01903
01904 if (regionId==-1) // if the region name doesn't already exist, add it to the list
01905 {
01906 (*RegionList)<<beginRegionStr;
01907 regionId = RegionList->findIndex(beginRegionStr);
01908 }
01909
01910 regionId++;
01911
01912 kdDebug(13010) << "########### BEG REG: " << beginRegionStr << " NUM: " << regionId << endl;
01913 }
01914
01915 if (!endRegionStr.isEmpty())
01916 {
01917 regionId2 = RegionList->findIndex(endRegionStr);
01918
01919 if (regionId2==-1) // if the region name doesn't already exist, add it to the list
01920 {
01921 (*RegionList)<<endRegionStr;
01922 regionId2 = RegionList->findIndex(endRegionStr);
01923 }
01924
01925 regionId2 = -regionId2 - 1;
01926
01927 kdDebug(13010) << "########### END REG: " << endRegionStr << " NUM: " << regionId2 << endl;
01928 }
01929
01930 int attr = 0;
01931 QString tmpAttr=KateHlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace();
01932 bool onlyConsume = tmpAttr.isEmpty();
01933
01934 // only relevant for non consumer
01935 if (!onlyConsume)
01936 {
01937 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
01938 {
01939 errorsAndWarnings+=i18n(
01940 "<B>%1</B>: Deprecated syntax. Attribute (%2) not addressed by symbolic name<BR>").
01941 arg(buildIdentifier).arg(tmpAttr);
01942 attr=tmpAttr.toInt();
01943 }
01944 else
01945 attr=lookupAttrName(tmpAttr,iDl);
01946 }
01947
01948
01949 int context = -1;
01950 QString unresolvedContext;
01951 QString tmpcontext=KateHlManager::self()->syntax->groupItemData(data,QString("context"));
01952 if (!tmpcontext.isEmpty())
01953 context=getIdFromString(ContextNameList, tmpcontext,unresolvedContext);
01954
01955
01956 char chr;
01957 if (! KateHlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty())
01958 chr= (KateHlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0];
01959 else
01960 chr=0;
01961
01962
01963 QString stringdata=KateHlManager::self()->syntax->groupItemData(data,QString("String"));
01964
01965
01966 char chr1;
01967 if (! KateHlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty())
01968 chr1= (KateHlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0];
01969 else
01970 chr1=0;
01971
01972
01973 bool insensitive = IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("insensitive")) );
01974
01975
01976 bool minimal = IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("minimal")) );
01977
01978
01979 bool lookAhead = IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("lookAhead")) );
01980
01981 bool dynamic= IS_TRUE(KateHlManager::self()->syntax->groupItemData(data,QString("dynamic")) );
01982
01983 bool firstNonSpace = IS_TRUE(KateHlManager::self()->syntax->groupItemData(data,QString("firstNonSpace")) );
01984
01985 int column = -1;
01986 QString colStr = KateHlManager::self()->syntax->groupItemData(data,QString("column"));
01987 if (!colStr.isEmpty())
01988 column = colStr.toInt();
01989
01990
01991 KateHlItem *tmpItem;
01992
01993 if (dataname=="keyword")
01994 {
01995 KateHlKeyword *keyword=new KateHlKeyword(attr,context,regionId,regionId2,casesensitive,
01996 m_additionalData[ buildIdentifier ]->deliminator);
01997
01998
01999 keyword->addList(KateHlManager::self()->syntax->finddata("highlighting",stringdata));
02000 tmpItem=keyword;
02001 }
02002 else if (dataname=="Float") tmpItem= (new KateHlFloat(attr,context,regionId,regionId2));
02003 else if (dataname=="Int") tmpItem=(new KateHlInt(attr,context,regionId,regionId2));
02004 else if (dataname=="DetectChar") tmpItem=(new KateHlCharDetect(attr,context,regionId,regionId2,chr));
02005 else if (dataname=="Detect2Chars") tmpItem=(new KateHl2CharDetect(attr,context,regionId,regionId2,chr,chr1));
02006 else if (dataname=="RangeDetect") tmpItem=(new KateHlRangeDetect(attr,context,regionId,regionId2, chr, chr1));
02007 else if (dataname=="LineContinue") tmpItem=(new KateHlLineContinue(attr,context,regionId,regionId2));
02008 else if (dataname=="StringDetect") tmpItem=(new KateHlStringDetect(attr,context,regionId,regionId2,stringdata,insensitive));
02009 else if (dataname=="AnyChar") tmpItem=(new KateHlAnyChar(attr,context,regionId,regionId2,stringdata));
02010 else if (dataname=="RegExpr") tmpItem=(new KateHlRegExpr(attr,context,regionId,regionId2,stringdata, insensitive, minimal));
02011 else if (dataname=="HlCChar") tmpItem= ( new KateHlCChar(attr,context,regionId,regionId2));
02012 else if (dataname=="HlCHex") tmpItem= (new KateHlCHex(attr,context,regionId,regionId2));
02013 else if (dataname=="HlCOct") tmpItem= (new KateHlCOct(attr,context,regionId,regionId2));
02014 else if (dataname=="HlCFloat") tmpItem= (new KateHlCFloat(attr,context,regionId,regionId2));
02015 else if (dataname=="HlCStringChar") tmpItem= (new KateHlCStringChar(attr,context,regionId,regionId2));
02016 else if (dataname=="DetectSpaces") tmpItem= (new KateHlDetectSpaces(attr,context,regionId,regionId2));
02017 else if (dataname=="DetectIdentifier") tmpItem= (new KateHlDetectIdentifier(attr,context,regionId,regionId2));
02018 else
02019 {
02020
02021 return 0;
02022 }
02023
02024
02025 tmpItem->lookAhead = lookAhead;
02026 tmpItem->dynamic = dynamic;
02027 tmpItem->firstNonSpace = firstNonSpace;
02028 tmpItem->column = column;
02029 tmpItem->onlyConsume = onlyConsume;
02030
02031 if (!unresolvedContext.isEmpty())
02032 {
02033 unresolvedContextReferences.insert(&(tmpItem->ctx),unresolvedContext);
02034 }
02035
02036 return tmpItem;
02037 }
02038
02039 QString KateHighlighting::hlKeyForAttrib( int i ) const
02040 {
02041 int k = 0;
02042 QMap<int,QString>::const_iterator it = m_hlIndex.constEnd();
02043 while ( it != m_hlIndex.constBegin() )
02044 {
02045 --it;
02046 k = it.key();
02047 if ( i >= k )
02048 break;
02049 }
02050 return it.data();
02051 }
02052
02053 bool KateHighlighting::isInWord( QChar c, int attrib ) const
02054 {
02055 static const QString& sq = KGlobal::staticQString(" \"'");
02056 return m_additionalData[ hlKeyForAttrib( attrib ) ]->deliminator.find(c) < 0 && sq.find(c) < 0;
02057 }
02058
02059 bool KateHighlighting::canBreakAt( QChar c, int attrib ) const
02060 {
02061 static const QString& sq = KGlobal::staticQString("\"'");
02062 return (m_additionalData[ hlKeyForAttrib( attrib ) ]->wordWrapDeliminator.find(c) != -1) && (sq.find(c) == -1);
02063 }
02064
02065 signed char KateHighlighting::commentRegion(int attr) const {
02066 QString commentRegion=m_additionalData[ hlKeyForAttrib( attr ) ]->multiLineRegion;
02067 return (commentRegion.isEmpty()?0:(commentRegion.toShort()));
02068 }
02069
02070 bool KateHighlighting::canComment( int startAttrib, int endAttrib ) const
02071 {
02072 QString k = hlKeyForAttrib( startAttrib );
02073 return ( k == hlKeyForAttrib( endAttrib ) &&
02074 ( ( !m_additionalData[k]->multiLineCommentStart.isEmpty() && !m_additionalData[k]->multiLineCommentEnd.isEmpty() ) ||
02075 ! m_additionalData[k]->singleLineCommentMarker.isEmpty() ) );
02076 }
02077
02078 QString KateHighlighting::getCommentStart( int attrib ) const
02079 {
02080 return m_additionalData[ hlKeyForAttrib( attrib) ]->multiLineCommentStart;
02081 }
02082
02083 QString KateHighlighting::getCommentEnd( int attrib ) const
02084 {
02085 return m_additionalData[ hlKeyForAttrib( attrib ) ]->multiLineCommentEnd;
02086 }
02087
02088 QString KateHighlighting::getCommentSingleLineStart( int attrib ) const
02089 {
02090 return m_additionalData[ hlKeyForAttrib( attrib) ]->singleLineCommentMarker;
02091 }
02092
02097 void KateHighlighting::readCommentConfig()
02098 {
02099 KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02100 KateSyntaxContextData *data=KateHlManager::self()->syntax->getGroupInfo("general","comment");
02101
02102 QString cmlStart, cmlEnd, cmlRegion, cslStart ;
02103
02104 if (data)
02105 {
02106 while (KateHlManager::self()->syntax->nextGroup(data))
02107 {
02108 if (KateHlManager::self()->syntax->groupData(data,"name")=="singleLine")
02109 cslStart=KateHlManager::self()->syntax->groupData(data,"start");
02110
02111 if (KateHlManager::self()->syntax->groupData(data,"name")=="multiLine")
02112 {
02113 cmlStart=KateHlManager::self()->syntax->groupData(data,"start");
02114 cmlEnd=KateHlManager::self()->syntax->groupData(data,"end");
02115 cmlRegion=KateHlManager::self()->syntax->groupData(data,"region");
02116 }
02117 }
02118
02119 KateHlManager::self()->syntax->freeGroupInfo(data);
02120 }
02121 else
02122 {
02123 cslStart = "";
02124 cmlStart = "";
02125 cmlEnd = "";
02126 cmlRegion = "";
02127 }
02128 m_additionalData[buildIdentifier]->singleLineCommentMarker = cslStart;
02129 m_additionalData[buildIdentifier]->multiLineCommentStart = cmlStart;
02130 m_additionalData[buildIdentifier]->multiLineCommentEnd = cmlEnd;
02131 m_additionalData[buildIdentifier]->multiLineRegion = cmlRegion;
02132 }
02133
02139 void KateHighlighting::readGlobalKeywordConfig()
02140 {
02141 deliminator = stdDeliminator;
02142
02143 kdDebug(13010)<<"readGlobalKeywordConfig:BEGIN"<<endl;
02144
02145 KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02146 KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","keywords");
02147
02148 if (data)
02149 {
02150 kdDebug(13010)<<"Found global keyword config"<<endl;
02151
02152 if (KateHlManager::self()->syntax->groupItemData(data,QString("casesensitive"))!="0")
02153 casesensitive=true;
02154 else
02155 casesensitive=false;
02156
02157
02158 weakDeliminator=(KateHlManager::self()->syntax->groupItemData(data,QString("weakDeliminator")));
02159
02160 kdDebug(13010)<<"weak delimiters are: "<<weakDeliminator<<endl;
02161
02162
02163 for (uint s=0; s < weakDeliminator.length(); s++)
02164 {
02165 int f = deliminator.find (weakDeliminator[s]);
02166
02167 if (f > -1)
02168 deliminator.remove (f, 1);
02169 }
02170
02171 QString addDelim = (KateHlManager::self()->syntax->groupItemData(data,QString("additionalDeliminator")));
02172
02173 if (!addDelim.isEmpty())
02174 deliminator=deliminator+addDelim;
02175
02176 KateHlManager::self()->syntax->freeGroupInfo(data);
02177 }
02178 else
02179 {
02180
02181 casesensitive=true;
02182 weakDeliminator=QString("");
02183 }
02184
02185 kdDebug(13010)<<"readGlobalKeywordConfig:END"<<endl;
02186
02187 kdDebug(13010)<<"delimiterCharacters are: "<<deliminator<<endl;
02188
02189 m_additionalData[buildIdentifier]->deliminator = deliminator;
02190 }
02191
02202 void KateHighlighting::readWordWrapConfig()
02203 {
02204
02205 kdDebug(13010)<<"readWordWrapConfig:BEGIN"<<endl;
02206
02207 KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02208 KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","keywords");
02209
02210 QString wordWrapDeliminator = stdDeliminator;
02211 if (data)
02212 {
02213 kdDebug(13010)<<"Found global keyword config"<<endl;
02214
02215 wordWrapDeliminator = (KateHlManager::self()->syntax->groupItemData(data,QString("wordWrapDeliminator")));
02216
02217 if ( wordWrapDeliminator.length() == 0 ) wordWrapDeliminator = deliminator;
02218
02219 kdDebug(13010) << "word wrap deliminators are " << wordWrapDeliminator << endl;
02220
02221 KateHlManager::self()->syntax->freeGroupInfo(data);
02222 }
02223
02224 kdDebug(13010)<<"readWordWrapConfig:END"<<endl;
02225
02226 m_additionalData[buildIdentifier]->wordWrapDeliminator = wordWrapDeliminator;
02227 }
02228
02229 void KateHighlighting::readIndentationConfig()
02230 {
02231 m_indentation = "";
02232
02233 KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02234 KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","indentation");
02235
02236 if (data)
02237 {
02238 m_indentation = (KateHlManager::self()->syntax->groupItemData(data,QString("mode")));
02239
02240 KateHlManager::self()->syntax->freeGroupInfo(data);
02241 }
02242 }
02243
02244 void KateHighlighting::readFoldingConfig()
02245 {
02246
02247 kdDebug(13010)<<"readfoldignConfig:BEGIN"<<endl;
02248
02249 KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02250 KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","folding");
02251
02252 if (data)
02253 {
02254 kdDebug(13010)<<"Found global keyword config"<<endl;
02255
02256 if (KateHlManager::self()->syntax->groupItemData(data,QString("indentationsensitive"))!="1")
02257 m_foldingIndentationSensitive=false;
02258 else
02259 m_foldingIndentationSensitive=true;
02260
02261 KateHlManager::self()->syntax->freeGroupInfo(data);
02262 }
02263 else
02264 {
02265
02266 m_foldingIndentationSensitive = false;
02267 }
02268
02269 kdDebug(13010)<<"readfoldingConfig:END"<<endl;
02270
02271 kdDebug(13010)<<"############################ use indent for fold are: "<<m_foldingIndentationSensitive<<endl;
02272 }
02273
02274 void KateHighlighting::createContextNameList(QStringList *ContextNameList,int ctx0)
02275 {
02276 kdDebug(13010)<<"creatingContextNameList:BEGIN"<<endl;
02277
02278 if (ctx0 == 0)
02279 ContextNameList->clear();
02280
02281 KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02282
02283 KateSyntaxContextData *data=KateHlManager::self()->syntax->getGroupInfo("highlighting","context");
02284
02285 int id=ctx0;
02286
02287 if (data)
02288 {
02289 while (KateHlManager::self()->syntax->nextGroup(data))
02290 {
02291 QString tmpAttr=KateHlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace();
02292 if (tmpAttr.isEmpty())
02293 {
02294 tmpAttr=QString("!KATE_INTERNAL_DUMMY! %1").arg(id);
02295 errorsAndWarnings +=i18n("<B>%1</B>: Deprecated syntax. Context %2 has no symbolic name<BR>").arg(buildIdentifier).arg(id-ctx0);
02296 }
02297 else tmpAttr=buildPrefix+tmpAttr;
02298 (*ContextNameList)<<tmpAttr;
02299 id++;
02300 }
02301 KateHlManager::self()->syntax->freeGroupInfo(data);
02302 }
02303 kdDebug(13010)<<"creatingContextNameList:END"<<endl;
02304
02305 }
02306
02307 int KateHighlighting::getIdFromString(QStringList *ContextNameList, QString tmpLineEndContext, QString &unres)
02308 {
02309 unres="";
02310 int context;
02311 if ((tmpLineEndContext=="#stay") || (tmpLineEndContext.simplifyWhiteSpace().isEmpty()))
02312 context=-1;
02313
02314 else if (tmpLineEndContext.startsWith("#pop"))
02315 {
02316 context=-1;
02317 for(;tmpLineEndContext.startsWith("#pop");context--)
02318 {
02319 tmpLineEndContext.remove(0,4);
02320 kdDebug(13010)<<"#pop found"<<endl;
02321 }
02322 }
02323
02324 else if ( tmpLineEndContext.startsWith("##"))
02325 {
02326 QString tmp=tmpLineEndContext.right(tmpLineEndContext.length()-2);
02327 if (!embeddedHls.contains(tmp)) embeddedHls.insert(tmp,KateEmbeddedHlInfo());
02328 unres=tmp;
02329 context=0;
02330 }
02331
02332 else
02333 {
02334 context=ContextNameList->findIndex(buildPrefix+tmpLineEndContext);
02335 if (context==-1)
02336 {
02337 context=tmpLineEndContext.toInt();
02338 errorsAndWarnings+=i18n(
02339 "<B>%1</B>:Deprecated syntax. Context %2 not addressed by a symbolic name"
02340 ).arg(buildIdentifier).arg(tmpLineEndContext);
02341 }
02342
02343
02344 }
02345 return context;
02346 }
02347
02353 void KateHighlighting::makeContextList()
02354 {
02355 if (noHl)
02356 return;
02357
02358 embeddedHls.clear();
02359 unresolvedContextReferences.clear();
02360 RegionList.clear();
02361 ContextNameList.clear();
02362
02363
02364
02365 embeddedHls.insert(iName,KateEmbeddedHlInfo());
02366
02367 bool something_changed;
02368
02369 startctx=base_startctx=0;
02370
02371 building=true;
02372
02373 do
02374 {
02375 kdDebug(13010)<<"**************** Outter loop in make ContextList"<<endl;
02376 kdDebug(13010)<<"**************** Hl List count:"<<embeddedHls.count()<<endl;
02377 something_changed=false;
02378 for (KateEmbeddedHlInfos::const_iterator it=embeddedHls.begin(); it!=embeddedHls.end();++it)
02379 {
02380 if (!it.data().loaded)
02381 {
02382 kdDebug(13010)<<"**************** Inner loop in make ContextList"<<endl;
02383 QString identifierToUse;
02384 kdDebug(13010)<<"Trying to open highlighting definition file: "<< it.key()<<endl;
02385 if (iName==it.key())
02386 identifierToUse=identifier;
02387 else
02388 identifierToUse=KateHlManager::self()->identifierForName(it.key());
02389
02390 kdDebug(13010)<<"Location is:"<< identifierToUse<<endl;
02391
02392 buildPrefix=it.key()+':';
02393
02394
02395 if (identifierToUse.isEmpty() )
02396 kdDebug(13010)<<"OHOH, unknown highlighting description referenced"<<endl;
02397
02398 kdDebug(13010)<<"setting ("<<it.key()<<") to loaded"<<endl;
02399
02400
02401 it=embeddedHls.insert(it.key(),KateEmbeddedHlInfo(true,startctx));
02402
02403 buildContext0Offset=startctx;
02404
02405 startctx=addToContextList(identifierToUse,startctx);
02406
02407 if (noHl) return;
02408
02409 base_startctx = startctx;
02410 something_changed=true;
02411 }
02412 }
02413 } while (something_changed);
02414
02415
02416
02417
02418
02419 kdDebug(13010)<<"Unresolved contexts, which need attention: "<<unresolvedContextReferences.count()<<endl;
02420
02421
02422 for (KateHlUnresolvedCtxRefs::iterator unresIt=unresolvedContextReferences.begin();
02423 unresIt!=unresolvedContextReferences.end();++unresIt)
02424 {
02425
02426 KateEmbeddedHlInfos::const_iterator hlIt=embeddedHls.find(unresIt.data());
02427 if (hlIt!=embeddedHls.end())
02428 *(unresIt.key())=hlIt.data().context0;
02429 }
02430
02431
02432
02433
02434
02435 handleKateHlIncludeRules();
02436
02437 embeddedHls.clear();
02438 unresolvedContextReferences.clear();
02439 RegionList.clear();
02440 ContextNameList.clear();
02441
02442
02443
02444 if (!errorsAndWarnings.isEmpty())
02445 KMessageBox::detailedSorry(0L,i18n(
02446 "There were warning(s) and/or error(s) while parsing the syntax "
02447 "highlighting configuration."),
02448 errorsAndWarnings, i18n("Kate Syntax Highlighting Parser"));
02449
02450
02451 building=false;
02452 }
02453
02454 void KateHighlighting::handleKateHlIncludeRules()
02455 {
02456
02457 kdDebug(13010)<<"KateHlIncludeRules, which need attention: " <<includeRules.count()<<endl;
02458 if (includeRules.isEmpty()) return;
02459
02460 buildPrefix="";
02461 QString dummy;
02462
02463
02464
02465
02466
02467
02468
02469 for (KateHlIncludeRules::iterator it=includeRules.begin();it!=includeRules.end();)
02470 {
02471 if ((*it)->incCtx==-1)
02472 {
02473
02474 if ((*it)->incCtxN.isEmpty())
02475 {
02476
02477
02478 KateHlIncludeRules::iterator it1=it;
02479 ++it1;
02480 delete (*it);
02481 includeRules.remove(it);
02482 it=it1;
02483 }
02484 else
02485 {
02486
02487 (*it)->incCtx=getIdFromString(&ContextNameList,(*it)->incCtxN,dummy);
02488 kdDebug(13010)<<"Resolved "<<(*it)->incCtxN<< " to "<<(*it)->incCtx<<" for include rule"<<endl;
02489
02490 }
02491 }
02492 else ++it;
02493 }
02494
02495
02496
02497
02498
02499
02500
02501 while (!includeRules.isEmpty())
02502 handleKateHlIncludeRulesRecursive(includeRules.begin(),&includeRules);
02503 }
02504
02505 void KateHighlighting::handleKateHlIncludeRulesRecursive(KateHlIncludeRules::iterator it, KateHlIncludeRules *list)
02506 {
02507 if (it==list->end()) return;
02508
02509 KateHlIncludeRules::iterator it1=it;
02510 int ctx=(*it1)->ctx;
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520 while ((it!=list->end()) && ((*it)->ctx==ctx))
02521 {
02522 it1=it;
02523 ++it;
02524 }
02525
02526
02527 while ((it1!=list->end()) && ((*it1)->ctx==ctx))
02528 {
02529 int ctx1=(*it1)->incCtx;
02530
02531
02532 for (KateHlIncludeRules::iterator it2=list->begin();it2!=list->end();++it2)
02533 {
02534 if ((*it2)->ctx==ctx1)
02535 {
02536
02537
02538 handleKateHlIncludeRulesRecursive(it2,list);
02539 break;
02540 }
02541 }
02542
02543
02544 KateHlContext *dest=m_contexts[ctx];
02545 KateHlContext *src=m_contexts[ctx1];
02546
02547
02548
02549
02550
02551 if ( (*it1)->includeAttrib )
02552 dest->attr = src->attr;
02553
02554
02555 int p=(*it1)->pos;
02556
02557
02558 int oldLen = dest->items.size();
02559 uint itemsToInsert = src->items.size();
02560
02561
02562 dest->items.resize (oldLen + itemsToInsert);
02563
02564
02565 for (int i=oldLen-1; i >= p; --i)
02566 dest->items[i+itemsToInsert] = dest->items[i];
02567
02568
02569 for (uint i=0; i < itemsToInsert; ++i )
02570 dest->items[p+i] = src->items[i];
02571
02572 it=it1;
02573 --it1;
02574 delete (*it);
02575 list->remove(it);
02576 }
02577 }
02578
02584 int KateHighlighting::addToContextList(const QString &ident, int ctx0)
02585 {
02586 kdDebug(13010)<<"=== Adding hl with ident '"<<ident<<"'"<<endl;
02587
02588 buildIdentifier=ident;
02589 KateSyntaxContextData *data, *datasub;
02590 KateHlItem *c;
02591
02592 QString dummy;
02593
02594
02595 if (!KateHlManager::self()->syntax->setIdentifier(ident))
02596 {
02597 noHl=true;
02598 KMessageBox::information(0L,i18n(
02599 "Since there has been an error parsing the highlighting description, "
02600 "this highlighting will be disabled"));
02601 return 0;
02602 }
02603
02604
02605 if (identifier == ident)
02606 {
02607 readIndentationConfig ();
02608 }
02609
02610 RegionList<<"!KateInternal_TopLevel!";
02611
02612 m_hlIndex[internalIDList.count()] = ident;
02613 m_additionalData.insert( ident, new HighlightPropertyBag );
02614
02615
02616 readCommentConfig();
02617 readGlobalKeywordConfig();
02618 readWordWrapConfig();
02619
02620 readFoldingConfig ();
02621
02622 QString ctxName;
02623
02624
02625
02626 addToKateHlItemDataList();
02627 KateHlItemDataList iDl = internalIDList;
02628
02629 createContextNameList(&ContextNameList,ctx0);
02630
02631
02632 kdDebug(13010)<<"Parsing Context structure"<<endl;
02633
02634 data=KateHlManager::self()->syntax->getGroupInfo("highlighting","context");
02635 uint i=buildContext0Offset;
02636 if (data)
02637 {
02638 while (KateHlManager::self()->syntax->nextGroup(data))
02639 {
02640 kdDebug(13010)<<"Found a context in file, building structure now"<<endl;
02641
02642 QString tmpAttr=KateHlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace();
02643 int attr;
02644 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
02645 attr=tmpAttr.toInt();
02646 else
02647 attr=lookupAttrName(tmpAttr,iDl);
02648
02649
02650 ctxName=buildPrefix+KateHlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace();
02651
02652 QString tmpLineEndContext=KateHlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace();
02653 int context;
02654
02655 context=getIdFromString(&ContextNameList, tmpLineEndContext,dummy);
02656
02657
02658 bool ft = false;
02659 int ftc = 0;
02660 if ( i > 0 )
02661 {
02662 QString tmpFt = KateHlManager::self()->syntax->groupData(data, QString("fallthrough") );
02663 if ( IS_TRUE(tmpFt) )
02664 ft = true;
02665 if ( ft )
02666 {
02667 QString tmpFtc = KateHlManager::self()->syntax->groupData( data, QString("fallthroughContext") );
02668
02669 ftc=getIdFromString(&ContextNameList, tmpFtc,dummy);
02670 if (ftc == -1) ftc =0;
02671
02672 kdDebug(13010)<<"Setting fall through context (context "<<i<<"): "<<ftc<<endl;
02673 }
02674 }
02675
02676
02677 bool dynamic = false;
02678 QString tmpDynamic = KateHlManager::self()->syntax->groupData(data, QString("dynamic") );
02679 if ( tmpDynamic.lower() == "true" || tmpDynamic.toInt() == 1 )
02680 dynamic = true;
02681
02682 KateHlContext *ctxNew = new KateHlContext (
02683 ident,
02684 attr,
02685 context,
02686 (KateHlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1:
02687 (KateHlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt(),
02688 ft, ftc, dynamic);
02689
02690 m_contexts.push_back (ctxNew);
02691
02692 kdDebug(13010) << "INDEX: " << i << " LENGTH " << m_contexts.size()-1 << endl;
02693
02694
02695 while (KateHlManager::self()->syntax->nextItem(data))
02696 {
02697
02698
02699
02700
02701 QString tag = KateHlManager::self()->syntax->groupItemData(data,QString(""));
02702 if ( tag == "IncludeRules" )
02703 {
02704 QString incCtx = KateHlManager::self()->syntax->groupItemData( data, QString("context"));
02705 QString incAttrib = KateHlManager::self()->syntax->groupItemData( data, QString("includeAttrib"));
02706 bool includeAttrib = ( incAttrib.lower() == "true" || incAttrib.toInt() == 1 );
02707
02708 if (incCtx.startsWith("##") || (!incCtx.startsWith("#")))
02709 {
02710
02711 if (!incCtx.startsWith("#"))
02712 {
02713
02714 incCtx=buildPrefix+incCtx.simplifyWhiteSpace();
02715 includeRules.append(new KateHlIncludeRule(i,m_contexts[i]->items.count(),incCtx, includeAttrib));
02716 }
02717 else
02718 {
02719
02720 kdDebug(13010)<<"Cross highlight reference <IncludeRules>"<<endl;
02721 KateHlIncludeRule *ir=new KateHlIncludeRule(i,m_contexts[i]->items.count(),"",includeAttrib);
02722
02723
02724 if (!embeddedHls.contains(incCtx.right(incCtx.length()-2)))
02725 embeddedHls.insert(incCtx.right(incCtx.length()-2),KateEmbeddedHlInfo());
02726
02727 unresolvedContextReferences.insert(&(ir->incCtx),
02728 incCtx.right(incCtx.length()-2));
02729
02730 includeRules.append(ir);
02731 }
02732 }
02733
02734 continue;
02735 }
02736
02737 #if 0
02738 QString tag = KateHlManager::self()->syntax->groupKateHlItemData(data,QString(""));
02739 if ( tag == "IncludeRules" ) {
02740
02741
02742
02743 int ctxId = getIdFromString(&ContextNameList,
02744 KateHlManager::self()->syntax->groupKateHlItemData( data, QString("context")),dummy);
02745 if ( ctxId > -1) {
02746 kdDebug(13010)<<"makeContextList["<<i<<"]: including all items of context "<<ctxId<<endl;
02747 if ( ctxId < (int) i ) {
02748 for ( c = m_contexts[ctxId]->items.first(); c; c = m_contexts[ctxId]->items.next() )
02749 m_contexts[i]->items.append(c);
02750 }
02751 else
02752 kdDebug(13010)<<"Context "<<ctxId<<"not defined. You can not include the rules of an undefined context"<<endl;
02753 }
02754 continue;
02755 }
02756 #endif
02757 c=createKateHlItem(data,iDl,&RegionList,&ContextNameList);
02758 if (c)
02759 {
02760 m_contexts[i]->items.append(c);
02761
02762
02763
02764 datasub=KateHlManager::self()->syntax->getSubItems(data);
02765 bool tmpbool;
02766 if (tmpbool=KateHlManager::self()->syntax->nextItem(datasub))
02767 {
02768 for (;tmpbool;tmpbool=KateHlManager::self()->syntax->nextItem(datasub))
02769 {
02770 c->subItems.resize (c->subItems.size()+1);
02771 c->subItems[c->subItems.size()-1] = createKateHlItem(datasub,iDl,&RegionList,&ContextNameList);
02772 } }
02773 KateHlManager::self()->syntax->freeGroupInfo(datasub);
02774
02775 }
02776 }
02777 i++;
02778 }
02779 }
02780
02781 KateHlManager::self()->syntax->freeGroupInfo(data);
02782
02783 if (RegionList.count()!=1)
02784 folding=true;
02785
02786 folding = folding || m_foldingIndentationSensitive;
02787
02788
02789 if (!m_additionalData[ ident ]->multiLineRegion.isEmpty()) {
02790 long commentregionid=RegionList.findIndex( m_additionalData[ ident ]->multiLineRegion );
02791 if (-1==commentregionid) {
02792 errorsAndWarnings+=i18n(
02793 "<B>%1</B>: Specified multiline comment region (%2) could not be resolved<BR>"
02794 ).arg(buildIdentifier).arg( m_additionalData[ ident ]->multiLineRegion );
02795 m_additionalData[ ident ]->multiLineRegion = QString();
02796 kdDebug(13010)<<"ERROR comment region attribute could not be resolved"<<endl;
02797
02798 } else {
02799 m_additionalData[ ident ]->multiLineRegion=QString::number(commentregionid+1);
02800 kdDebug(13010)<<"comment region resolved to:"<<m_additionalData[ ident ]->multiLineRegion<<endl;
02801 }
02802 }
02803
02804 return i;
02805 }
02806
02807 void KateHighlighting::clearAttributeArrays ()
02808 {
02809 for ( QIntDictIterator< QMemArray<KateAttribute> > it( m_attributeArrays ); it.current(); ++it )
02810 {
02811
02812 KateAttributeList defaultStyleList;
02813 defaultStyleList.setAutoDelete(true);
02814 KateHlManager::self()->getDefaults(it.currentKey(), defaultStyleList);
02815
02816 KateHlItemDataList itemDataList;
02817 getKateHlItemDataList(it.currentKey(), itemDataList);
02818
02819 uint nAttribs = itemDataList.count();
02820 QMemArray<KateAttribute> *array = it.current();
02821 array->resize (nAttribs);
02822
02823 for (uint z = 0; z < nAttribs; z++)
02824 {
02825 KateHlItemData *itemData = itemDataList.at(z);
02826 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum);
02827
02828 if (itemData && itemData->isSomethingSet())
02829 n += *itemData;
02830
02831 array->at(z) = n;
02832 }
02833 }
02834 }
02835
02836 QMemArray<KateAttribute> *KateHighlighting::attributes (uint schema)
02837 {
02838 QMemArray<KateAttribute> *array;
02839
02840
02841 if ((array = m_attributeArrays[schema]))
02842 return array;
02843
02844
02845 if (!KateFactory::self()->schemaManager()->validSchema(schema))
02846 {
02847
02848 return attributes (0);
02849 }
02850
02851
02852 KateAttributeList defaultStyleList;
02853 defaultStyleList.setAutoDelete(true);
02854 KateHlManager::self()->getDefaults(schema, defaultStyleList);
02855
02856 KateHlItemDataList itemDataList;
02857 getKateHlItemDataList(schema, itemDataList);
02858
02859 uint nAttribs = itemDataList.count();
02860 array = new QMemArray<KateAttribute> (nAttribs);
02861
02862 for (uint z = 0; z < nAttribs; z++)
02863 {
02864 KateHlItemData *itemData = itemDataList.at(z);
02865 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum);
02866
02867 if (itemData && itemData->isSomethingSet())
02868 n += *itemData;
02869
02870 array->at(z) = n;
02871 }
02872
02873 m_attributeArrays.insert(schema, array);
02874
02875 return array;
02876 }
02877
02878 void KateHighlighting::getKateHlItemDataListCopy (uint schema, KateHlItemDataList &outlist)
02879 {
02880 KateHlItemDataList itemDataList;
02881 getKateHlItemDataList(schema, itemDataList);
02882
02883 outlist.clear ();
02884 outlist.setAutoDelete (true);
02885 for (uint z=0; z < itemDataList.count(); z++)
02886 outlist.append (new KateHlItemData (*itemDataList.at(z)));
02887 }
02888
02889
02890
02891
02892 KateHlManager::KateHlManager()
02893 : QObject()
02894 , m_config ("katesyntaxhighlightingrc", false, false)
02895 , commonSuffixes (QStringList::split(";", ".orig;.new;~;.bak;.BAK"))
02896 , syntax (new KateSyntaxDocument())
02897 , dynamicCtxsCount(0)
02898 , forceNoDCReset(false)
02899 {
02900 hlList.setAutoDelete(true);
02901 hlDict.setAutoDelete(false);
02902
02903 KateSyntaxModeList modeList = syntax->modeList();
02904 for (uint i=0; i < modeList.count(); i++)
02905 {
02906 KateHighlighting *hl = new KateHighlighting(modeList[i]);
02907
02908 uint insert = 0;
02909 for (; insert <= hlList.count(); insert++)
02910 {
02911 if (insert == hlList.count())
02912 break;
02913
02914 if ( QString(hlList.at(insert)->section() + hlList.at(insert)->nameTranslated()).lower()
02915 > QString(hl->section() + hl->nameTranslated()).lower() )
02916 break;
02917 }
02918
02919 hlList.insert (insert, hl);
02920 hlDict.insert (hl->name(), hl);
02921 }
02922
02923
02924 KateHighlighting *hl = new KateHighlighting(0);
02925 hlList.prepend (hl);
02926 hlDict.insert (hl->name(), hl);
02927
02928 lastCtxsReset.start();
02929 }
02930
02931 KateHlManager::~KateHlManager()
02932 {
02933 delete syntax;
02934 }
02935
02936 static KStaticDeleter<KateHlManager> sdHlMan;
02937
02938 KateHlManager *KateHlManager::self()
02939 {
02940 if ( !s_self )
02941 sdHlMan.setObject(s_self, new KateHlManager ());
02942
02943 return s_self;
02944 }
02945
02946 KateHighlighting *KateHlManager::getHl(int n)
02947 {
02948 if (n < 0 || n >= (int) hlList.count())
02949 n = 0;
02950
02951 return hlList.at(n);
02952 }
02953
02954 int KateHlManager::nameFind(const QString &name)
02955 {
02956 int z (hlList.count() - 1);
02957 for (; z > 0; z--)
02958 if (hlList.at(z)->name() == name)
02959 return z;
02960
02961 return z;
02962 }
02963
02964 int KateHlManager::detectHighlighting (KateDocument *doc)
02965 {
02966 int hl = wildcardFind( doc->url().filename() );
02967 if ( hl < 0 )
02968 hl = mimeFind ( doc );
02969
02970 return hl;
02971 }
02972
02973 int KateHlManager::wildcardFind(const QString &fileName)
02974 {
02975 int result = -1;
02976 if ((result = realWildcardFind(fileName)) != -1)
02977 return result;
02978
02979 int length = fileName.length();
02980 QString backupSuffix = KateDocumentConfig::global()->backupSuffix();
02981 if (fileName.endsWith(backupSuffix)) {
02982 if ((result = realWildcardFind(fileName.left(length - backupSuffix.length()))) != -1)
02983 return result;
02984 }
02985
02986 for (QStringList::Iterator it = commonSuffixes.begin(); it != commonSuffixes.end(); ++it) {
02987 if (*it != backupSuffix && fileName.endsWith(*it)) {
02988 if ((result = realWildcardFind(fileName.left(length - (*it).length()))) != -1)
02989 return result;
02990 }
02991 }
02992
02993 return -1;
02994 }
02995
02996 int KateHlManager::realWildcardFind(const QString &fileName)
02997 {
02998 static QRegExp sep("\\s*;\\s*");
02999
03000 QPtrList<KateHighlighting> highlights;
03001
03002 for (KateHighlighting *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) {
03003 highlight->loadWildcards();
03004
03005 for (QStringList::Iterator it = highlight->getPlainExtensions().begin(); it != highlight->getPlainExtensions().end(); ++it)
03006 if (fileName.endsWith((*it)))
03007 highlights.append(highlight);
03008
03009 for (int i = 0; i < (int)highlight->getRegexpExtensions().count(); i++) {
03010 QRegExp re = highlight->getRegexpExtensions()[i];
03011 if (re.exactMatch(fileName))
03012 highlights.append(highlight);
03013 }
03014 }
03015
03016 if ( !highlights.isEmpty() )
03017 {
03018 int pri = -1;
03019 int hl = -1;
03020
03021 for (KateHighlighting *highlight = highlights.first(); highlight != 0L; highlight = highlights.next())
03022 {
03023 if (highlight->priority() > pri)
03024 {
03025 pri = highlight->priority();
03026 hl = hlList.findRef (highlight);
03027 }
03028 }
03029 return hl;
03030 }
03031
03032 return -1;
03033 }
03034
03035 int KateHlManager::mimeFind( KateDocument *doc )
03036 {
03037 static QRegExp sep("\\s*;\\s*");
03038
03039 KMimeType::Ptr mt = doc->mimeTypeForContent();
03040
03041 QPtrList<KateHighlighting> highlights;
03042
03043 for (KateHighlighting *highlight = hlList.first(); highlight != 0L; highlight = hlList.next())
03044 {
03045 QStringList l = QStringList::split( sep, highlight->getMimetypes() );
03046
03047 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it )
03048 {
03049 if ( *it == mt->name() )
03050 highlights.append (highlight);
03051 }
03052 }
03053
03054 if ( !highlights.isEmpty() )
03055 {
03056 int pri = -1;
03057 int hl = -1;
03058
03059 for (KateHighlighting *highlight = highlights.first(); highlight != 0L; highlight = highlights.next())
03060 {
03061 if (highlight->priority() > pri)
03062 {
03063 pri = highlight->priority();
03064 hl = hlList.findRef (highlight);
03065 }
03066 }
03067
03068 return hl;
03069 }
03070
03071 return -1;
03072 }
03073
03074 uint KateHlManager::defaultStyles()
03075 {
03076 return 14;
03077 }
03078
03079 QString KateHlManager::defaultStyleName(int n, bool translateNames)
03080 {
03081 static QStringList names;
03082 static QStringList translatedNames;
03083
03084 if (names.isEmpty())
03085 {
03086 names << "Normal";
03087 names << "Keyword";
03088 names << "Data Type";
03089 names << "Decimal/Value";
03090 names << "Base-N Integer";
03091 names << "Floating Point";
03092 names << "Character";
03093 names << "String";
03094 names << "Comment";
03095 names << "Others";
03096 names << "Alert";
03097 names << "Function";
03098
03099 names << "Region Marker";
03100
03101 names << "Error";
03102
03103 translatedNames << i18n("Normal");
03104 translatedNames << i18n("Keyword");
03105 translatedNames << i18n("Data Type");
03106 translatedNames << i18n("Decimal/Value");
03107 translatedNames << i18n("Base-N Integer");
03108 translatedNames << i18n("Floating Point");
03109 translatedNames << i18n("Character");
03110 translatedNames << i18n("String");
03111 translatedNames << i18n("Comment");
03112 translatedNames << i18n("Others");
03113 translatedNames << i18n("Alert");
03114 translatedNames << i18n("Function");
03115
03116 translatedNames << i18n("Region Marker");
03117
03118 translatedNames << i18n("Error");
03119 }
03120
03121 return translateNames ? translatedNames[n] : names[n];
03122 }
03123
03124 void KateHlManager::getDefaults(uint schema, KateAttributeList &list)
03125 {
03126 list.setAutoDelete(true);
03127
03128 KateAttribute* normal = new KateAttribute();
03129 normal->setTextColor(Qt::black);
03130 normal->setSelectedTextColor(Qt::white);
03131 list.append(normal);
03132
03133 KateAttribute* keyword = new KateAttribute();
03134 keyword->setTextColor(Qt::black);
03135 keyword->setSelectedTextColor(Qt::white);
03136 keyword->setBold(true);
03137 list.append(keyword);
03138
03139 KateAttribute* dataType = new KateAttribute();
03140 dataType->setTextColor(Qt::darkRed);
03141 dataType->setSelectedTextColor(Qt::white);
03142 list.append(dataType);
03143
03144 KateAttribute* decimal = new KateAttribute();
03145 decimal->setTextColor(Qt::blue);
03146 decimal->setSelectedTextColor(Qt::cyan);
03147 list.append(decimal);
03148
03149 KateAttribute* basen = new KateAttribute();
03150 basen->setTextColor(Qt::darkCyan);
03151 basen->setSelectedTextColor(Qt::cyan);
03152 list.append(basen);
03153
03154 KateAttribute* floatAttribute = new KateAttribute();
03155 floatAttribute->setTextColor(Qt::darkMagenta);
03156 floatAttribute->setSelectedTextColor(Qt::cyan);
03157 list.append(floatAttribute);
03158
03159 KateAttribute* charAttribute = new KateAttribute();
03160 charAttribute->setTextColor(Qt::magenta);
03161 charAttribute->setSelectedTextColor(Qt::magenta);
03162 list.append(charAttribute);
03163
03164 KateAttribute* string = new KateAttribute();
03165 string->setTextColor(QColor::QColor("#D00"));
03166 string->setSelectedTextColor(Qt::red);
03167 list.append(string);
03168
03169 KateAttribute* comment = new KateAttribute();
03170 comment->setTextColor(Qt::darkGray);
03171 comment->setSelectedTextColor(Qt::gray);
03172 comment->setItalic(true);
03173 list.append(comment);
03174
03175 KateAttribute* others = new KateAttribute();
03176 others->setTextColor(Qt::darkGreen);
03177 others->setSelectedTextColor(Qt::green);
03178 list.append(others);
03179
03180 KateAttribute* alert = new KateAttribute();
03181 alert->setTextColor(Qt::white);
03182 alert->setSelectedTextColor( QColor::QColor("#FCC") );
03183 alert->setBold(true);
03184 alert->setBGColor( QColor::QColor("#FCC") );
03185 list.append(alert);
03186
03187 KateAttribute* functionAttribute = new KateAttribute();
03188 functionAttribute->setTextColor(Qt::darkBlue);
03189 functionAttribute->setSelectedTextColor(Qt::white);
03190 list.append(functionAttribute);
03191
03192 KateAttribute* regionmarker = new KateAttribute();
03193 regionmarker->setTextColor(Qt::white);
03194 regionmarker->setBGColor(Qt::gray);
03195 regionmarker->setSelectedTextColor(Qt::gray);
03196 list.append(regionmarker);
03197
03198 KateAttribute* error = new KateAttribute();
03199 error->setTextColor(Qt::red);
03200 error->setUnderline(true);
03201 error->setSelectedTextColor(Qt::red);
03202 list.append(error);
03203
03204 KConfig *config = KateHlManager::self()->self()->getKConfig();
03205 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema));
03206
03207 for (uint z = 0; z < defaultStyles(); z++)
03208 {
03209 KateAttribute *i = list.at(z);
03210 QStringList s = config->readListEntry(defaultStyleName(z));
03211 if (!s.isEmpty())
03212 {
03213 while( s.count()<8)
03214 s << "";
03215
03216 QString tmp;
03217 QRgb col;
03218
03219 tmp=s[0]; if (!tmp.isEmpty()) {
03220 col=tmp.toUInt(0,16); i->setTextColor(col); }
03221
03222 tmp=s[1]; if (!tmp.isEmpty()) {
03223 col=tmp.toUInt(0,16); i->setSelectedTextColor(col); }
03224
03225 tmp=s[2]; if (!tmp.isEmpty()) i->setBold(tmp!="0");
03226
03227 tmp=s[3]; if (!tmp.isEmpty()) i->setItalic(tmp!="0");
03228
03229 tmp=s[4]; if (!tmp.isEmpty()) i->setStrikeOut(tmp!="0");
03230
03231 tmp=s[5]; if (!tmp.isEmpty()) i->setUnderline(tmp!="0");
03232
03233 tmp=s[6]; if (!tmp.isEmpty()) {
03234 if ( tmp != "-" )
03235 {
03236 col=tmp.toUInt(0,16);
03237 i->setBGColor(col);
03238 }
03239 else
03240 i->clearAttribute(KateAttribute::BGColor);
03241 }
03242 tmp=s[7]; if (!tmp.isEmpty()) {
03243 if ( tmp != "-" )
03244 {
03245 col=tmp.toUInt(0,16);
03246 i->setSelectedBGColor(col);
03247 }
03248 else
03249 i->clearAttribute(KateAttribute::SelectedBGColor);
03250 }
03251 }
03252 }
03253 }
03254
03255 void KateHlManager::setDefaults(uint schema, KateAttributeList &list)
03256 {
03257 KConfig *config = KateHlManager::self()->self()->getKConfig();
03258 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema));
03259
03260 for (uint z = 0; z < defaultStyles(); z++)
03261 {
03262 QStringList settings;
03263 KateAttribute *i = list.at(z);
03264
03265 settings<<(i->itemSet(KateAttribute::TextColor)?QString::number(i->textColor().rgb(),16):"");
03266 settings<<(i->itemSet(KateAttribute::SelectedTextColor)?QString::number(i->selectedTextColor().rgb(),16):"");
03267 settings<<(i->itemSet(KateAttribute::Weight)?(i->bold()?"1":"0"):"");
03268 settings<<(i->itemSet(KateAttribute::Italic)?(i->italic()?"1":"0"):"");
03269 settings<<(i->itemSet(KateAttribute::StrikeOut)?(i->strikeOut()?"1":"0"):"");
03270 settings<<(i->itemSet(KateAttribute::Underline)?(i->underline()?"1":"0"):"");
03271 settings<<(i->itemSet(KateAttribute::BGColor)?QString::number(i->bgColor().rgb(),16):"-");
03272 settings<<(i->itemSet(KateAttribute::SelectedBGColor)?QString::number(i->selectedBGColor().rgb(),16):"-");
03273 settings<<"---";
03274
03275 config->writeEntry(defaultStyleName(z),settings);
03276 }
03277
03278 emit changed();
03279 }
03280
03281 int KateHlManager::highlights()
03282 {
03283 return (int) hlList.count();
03284 }
03285
03286 QString KateHlManager::hlName(int n)
03287 {
03288 return hlList.at(n)->name();
03289 }
03290
03291 QString KateHlManager::hlNameTranslated(int n)
03292 {
03293 return hlList.at(n)->nameTranslated();
03294 }
03295
03296 QString KateHlManager::hlSection(int n)
03297 {
03298 return hlList.at(n)->section();
03299 }
03300
03301 bool KateHlManager::hlHidden(int n)
03302 {
03303 return hlList.at(n)->hidden();
03304 }
03305
03306 QString KateHlManager::identifierForName(const QString& name)
03307 {
03308 KateHighlighting *hl = 0;
03309
03310 if ((hl = hlDict[name]))
03311 return hl->getIdentifier ();
03312
03313 return QString();
03314 }
03315
03316 bool KateHlManager::resetDynamicCtxs()
03317 {
03318 if (forceNoDCReset)
03319 return false;
03320
03321 if (lastCtxsReset.elapsed() < KATE_DYNAMIC_CONTEXTS_RESET_DELAY)
03322 return false;
03323
03324 KateHighlighting *hl;
03325 for (hl = hlList.first(); hl; hl = hlList.next())
03326 hl->dropDynamicContexts();
03327
03328 dynamicCtxsCount = 0;
03329 lastCtxsReset.start();
03330
03331 return true;
03332 }
03333
03334
03335
03336 void KateViewHighlightAction::init()
03337 {
03338 m_doc = 0;
03339 subMenus.setAutoDelete( true );
03340
03341 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow()));
03342 }
03343
03344 void KateViewHighlightAction::updateMenu (Kate::Document *doc)
03345 {
03346 m_doc = doc;
03347 }
03348
03349 void KateViewHighlightAction::slotAboutToShow()
03350 {
03351 Kate::Document *doc=m_doc;
03352 int count = KateHlManager::self()->highlights();
03353
03354 for (int z=0; z<count; z++)
03355 {
03356 QString hlName = KateHlManager::self()->hlNameTranslated (z);
03357 QString hlSection = KateHlManager::self()->hlSection (z);
03358
03359 if (!KateHlManager::self()->hlHidden(z))
03360 {
03361 if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) )
03362 {
03363 if (subMenusName.contains(hlSection) < 1)
03364 {
03365 subMenusName << hlSection;
03366 QPopupMenu *menu = new QPopupMenu ();
03367 subMenus.append(menu);
03368 popupMenu()->insertItem ( '&' + hlSection, menu);
03369 }
03370
03371 int m = subMenusName.findIndex (hlSection);
03372 names << hlName;
03373 subMenus.at(m)->insertItem ( '&' + hlName, this, SLOT(setHl(int)), 0, z);
03374 }
03375 else if (names.contains(hlName) < 1)
03376 {
03377 names << hlName;
03378 popupMenu()->insertItem ( '&' + hlName, this, SLOT(setHl(int)), 0, z);
03379 }
03380 }
03381 }
03382
03383 if (!doc) return;
03384
03385 for (uint i=0;i<subMenus.count();i++)
03386 {
03387 for (uint i2=0;i2<subMenus.at(i)->count();i2++)
03388 {
03389 subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false);
03390 }
03391 }
03392 popupMenu()->setItemChecked (0, false);
03393
03394 int i = subMenusName.findIndex (KateHlManager::self()->hlSection(doc->hlMode()));
03395 if (i >= 0 && subMenus.at(i))
03396 subMenus.at(i)->setItemChecked (doc->hlMode(), true);
03397 else
03398 popupMenu()->setItemChecked (0, true);
03399 }
03400
03401 void KateViewHighlightAction::setHl (int mode)
03402 {
03403 Kate::Document *doc=m_doc;
03404
03405 if (doc)
03406 doc->setHlMode((uint)mode);
03407 }
03408
03409
03410