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 const QChar *unicode = str.unicode();
00069 const uint len = str.length();
00070 for (uint i=0; i < len; i++)
00071 if (unicode[i] == ch)
00072 return true;
00073
00074 return false;
00075 }
00076
00077 class KateHlItem
00078 {
00079 public:
00080 KateHlItem(int attribute, int context,signed char regionId, signed char regionId2);
00081 virtual ~KateHlItem();
00082
00083 public:
00084
00085
00086
00087 virtual int checkHgl(const QString& text, int offset, int len) = 0;
00088
00089 virtual bool lineContinue(){return false;}
00090
00091 virtual QStringList *capturedTexts() {return 0;}
00092 virtual KateHlItem *clone(const QStringList *) {return this;}
00093
00094 static void dynamicSubstitute(QString& str, const QStringList *args);
00095
00096 QMemArray<KateHlItem*> subItems;
00097 int attr;
00098 int ctx;
00099 signed char region;
00100 signed char region2;
00101
00102 bool lookAhead;
00103
00104 bool dynamic;
00105 bool dynamicChild;
00106 bool firstNonSpace;
00107 bool onlyConsume;
00108 int column;
00109
00110
00111
00112 bool alwaysStartEnable;
00113 bool customStartEnable;
00114 };
00115
00116 class KateHlContext
00117 {
00118 public:
00119 KateHlContext(const QString &_hlId, int attribute, int lineEndContext,int _lineBeginContext,
00120 bool _fallthrough, int _fallthroughContext, bool _dynamic,bool _noIndentationBasedFolding);
00121 virtual ~KateHlContext();
00122 KateHlContext *clone(const QStringList *args);
00123
00124 QValueVector<KateHlItem*> items;
00125 QString hlId;
00126 int attr;
00127 int ctx;
00128 int lineBeginContext;
00134 bool fallthrough;
00135 int ftctx;
00136
00137 bool dynamic;
00138 bool dynamicChild;
00139 bool noIndentationBasedFolding;
00140 };
00141
00142 class KateEmbeddedHlInfo
00143 {
00144 public:
00145 KateEmbeddedHlInfo() {loaded=false;context0=-1;}
00146 KateEmbeddedHlInfo(bool l, int ctx0) {loaded=l;context0=ctx0;}
00147
00148 public:
00149 bool loaded;
00150 int context0;
00151 };
00152
00153 class KateHlIncludeRule
00154 {
00155 public:
00156 KateHlIncludeRule(int ctx_=0, uint pos_=0, const QString &incCtxN_="", bool incAttrib=false)
00157 : ctx(ctx_)
00158 , pos( pos_)
00159 , incCtxN( incCtxN_ )
00160 , includeAttrib( incAttrib )
00161 {
00162 incCtx=-1;
00163 }
00164
00165
00166 public:
00167 int ctx;
00168 uint pos;
00169 int incCtx;
00170 QString incCtxN;
00171 bool includeAttrib;
00172 };
00173
00174 class KateHlCharDetect : public KateHlItem
00175 {
00176 public:
00177 KateHlCharDetect(int attribute, int context,signed char regionId,signed char regionId2, QChar);
00178
00179 virtual int checkHgl(const QString& text, int offset, int len);
00180 virtual KateHlItem *clone(const QStringList *args);
00181
00182 private:
00183 QChar sChar;
00184 };
00185
00186 class KateHl2CharDetect : public KateHlItem
00187 {
00188 public:
00189 KateHl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2);
00190 KateHl2CharDetect(int attribute, int context,signed char regionId,signed char regionId2, const QChar *ch);
00191
00192 virtual int checkHgl(const QString& text, int offset, int len);
00193 virtual KateHlItem *clone(const QStringList *args);
00194
00195 private:
00196 QChar sChar1;
00197 QChar sChar2;
00198 };
00199
00200 class KateHlStringDetect : public KateHlItem
00201 {
00202 public:
00203 KateHlStringDetect(int attribute, int context, signed char regionId,signed char regionId2, const QString &, bool inSensitive=false);
00204
00205 virtual int checkHgl(const QString& text, int offset, int len);
00206 virtual KateHlItem *clone(const QStringList *args);
00207
00208 private:
00209 const QString str;
00210 const int strLen;
00211 const bool _inSensitive;
00212 };
00213
00214 class KateHlRangeDetect : public KateHlItem
00215 {
00216 public:
00217 KateHlRangeDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2);
00218
00219 virtual int checkHgl(const QString& text, int offset, int len);
00220
00221 private:
00222 QChar sChar1;
00223 QChar sChar2;
00224 };
00225
00226 class KateHlKeyword : public KateHlItem
00227 {
00228 public:
00229 KateHlKeyword(int attribute, int context,signed char regionId,signed char regionId2, bool casesensitive, const QString& delims);
00230 virtual ~KateHlKeyword ();
00231
00232 void addList(const QStringList &);
00233 virtual int checkHgl(const QString& text, int offset, int len);
00234
00235 private:
00236 QMemArray< QDict<bool>* > dict;
00237 bool _caseSensitive;
00238 const QString& deliminators;
00239 int minLen;
00240 int maxLen;
00241 };
00242
00243 class KateHlInt : public KateHlItem
00244 {
00245 public:
00246 KateHlInt(int attribute, int context, signed char regionId,signed char regionId2);
00247
00248 virtual int checkHgl(const QString& text, int offset, int len);
00249 };
00250
00251 class KateHlFloat : public KateHlItem
00252 {
00253 public:
00254 KateHlFloat(int attribute, int context, signed char regionId,signed char regionId2);
00255 virtual ~KateHlFloat () {}
00256
00257 virtual int checkHgl(const QString& text, int offset, int len);
00258 };
00259
00260 class KateHlCFloat : public KateHlFloat
00261 {
00262 public:
00263 KateHlCFloat(int attribute, int context, signed char regionId,signed char regionId2);
00264
00265 virtual int checkHgl(const QString& text, int offset, int len);
00266 int checkIntHgl(const QString& text, int offset, int len);
00267 };
00268
00269 class KateHlCOct : public KateHlItem
00270 {
00271 public:
00272 KateHlCOct(int attribute, int context, signed char regionId,signed char regionId2);
00273
00274 virtual int checkHgl(const QString& text, int offset, int len);
00275 };
00276
00277 class KateHlCHex : public KateHlItem
00278 {
00279 public:
00280 KateHlCHex(int attribute, int context, signed char regionId,signed char regionId2);
00281
00282 virtual int checkHgl(const QString& text, int offset, int len);
00283 };
00284
00285 class KateHlLineContinue : public KateHlItem
00286 {
00287 public:
00288 KateHlLineContinue(int attribute, int context, signed char regionId,signed char regionId2);
00289
00290 virtual bool endEnable(QChar c) {return c == '\0';}
00291 virtual int checkHgl(const QString& text, int offset, int len);
00292 virtual bool lineContinue(){return true;}
00293 };
00294
00295 class KateHlCStringChar : public KateHlItem
00296 {
00297 public:
00298 KateHlCStringChar(int attribute, int context, signed char regionId,signed char regionId2);
00299
00300 virtual int checkHgl(const QString& text, int offset, int len);
00301 };
00302
00303 class KateHlCChar : public KateHlItem
00304 {
00305 public:
00306 KateHlCChar(int attribute, int context,signed char regionId,signed char regionId2);
00307
00308 virtual int checkHgl(const QString& text, int offset, int len);
00309 };
00310
00311 class KateHlAnyChar : public KateHlItem
00312 {
00313 public:
00314 KateHlAnyChar(int attribute, int context, signed char regionId,signed char regionId2, const QString& charList);
00315
00316 virtual int checkHgl(const QString& text, int offset, int len);
00317
00318 private:
00319 const QString _charList;
00320 };
00321
00322 class KateHlRegExpr : public KateHlItem
00323 {
00324 public:
00325 KateHlRegExpr(int attribute, int context,signed char regionId,signed char regionId2 ,QString expr, bool insensitive, bool minimal);
00326 ~KateHlRegExpr() { delete Expr; };
00327
00328 virtual int checkHgl(const QString& text, int offset, int len);
00329 virtual QStringList *capturedTexts();
00330 virtual KateHlItem *clone(const QStringList *args);
00331
00332 private:
00333 QRegExp *Expr;
00334 bool handlesLinestart;
00335 QString _regexp;
00336 bool _insensitive;
00337 bool _minimal;
00338 };
00339
00340 class KateHlDetectSpaces : public KateHlItem
00341 {
00342 public:
00343 KateHlDetectSpaces (int attribute, int context,signed char regionId,signed char regionId2)
00344 : KateHlItem(attribute,context,regionId,regionId2) {}
00345
00346 virtual int checkHgl(const QString& text, int offset, int len)
00347 {
00348 int len2 = offset + len;
00349 while ((offset < len2) && text[offset].isSpace()) offset++;
00350 return offset;
00351 }
00352 };
00353
00354 class KateHlDetectIdentifier : public KateHlItem
00355 {
00356 public:
00357 KateHlDetectIdentifier (int attribute, int context,signed char regionId,signed char regionId2)
00358 : KateHlItem(attribute,context,regionId,regionId2) { alwaysStartEnable = false; }
00359
00360 virtual int checkHgl(const QString& text, int offset, int len)
00361 {
00362
00363 if ( text[offset].isLetter() || text[offset] == QChar ('_') )
00364 {
00365
00366 int len2 = offset+len;
00367
00368
00369 offset++;
00370
00371
00372 while (
00373 (offset < len2)
00374 && (text[offset].isLetterOrNumber() || (text[offset] == QChar ('_')))
00375 )
00376 offset++;
00377
00378 return offset;
00379 }
00380
00381 return 0;
00382 }
00383 };
00384
00385
00386
00387
00388 KateHlManager *KateHlManager::s_self = 0;
00389
00390 static const bool trueBool = true;
00391 static const QString stdDeliminator = QString (" \t.():!+,-<=>%&*/;?[]^{|}~\\");
00392
00393
00394
00395 static KateHlItemData::ItemStyles getDefStyleNum(QString name)
00396 {
00397 if (name=="dsNormal") return KateHlItemData::dsNormal;
00398 else if (name=="dsKeyword") return KateHlItemData::dsKeyword;
00399 else if (name=="dsDataType") return KateHlItemData::dsDataType;
00400 else if (name=="dsDecVal") return KateHlItemData::dsDecVal;
00401 else if (name=="dsBaseN") return KateHlItemData::dsBaseN;
00402 else if (name=="dsFloat") return KateHlItemData::dsFloat;
00403 else if (name=="dsChar") return KateHlItemData::dsChar;
00404 else if (name=="dsString") return KateHlItemData::dsString;
00405 else if (name=="dsComment") return KateHlItemData::dsComment;
00406 else if (name=="dsOthers") return KateHlItemData::dsOthers;
00407 else if (name=="dsAlert") return KateHlItemData::dsAlert;
00408 else if (name=="dsFunction") return KateHlItemData::dsFunction;
00409 else if (name=="dsRegionMarker") return KateHlItemData::dsRegionMarker;
00410 else if (name=="dsError") return KateHlItemData::dsError;
00411
00412 return KateHlItemData::dsNormal;
00413 }
00414
00415
00416
00417 KateHlItem::KateHlItem(int attribute, int context,signed char regionId,signed char regionId2)
00418 : attr(attribute),
00419 ctx(context),
00420 region(regionId),
00421 region2(regionId2),
00422 lookAhead(false),
00423 dynamic(false),
00424 dynamicChild(false),
00425 firstNonSpace(false),
00426 onlyConsume(false),
00427 column (-1),
00428 alwaysStartEnable (true),
00429 customStartEnable (false)
00430 {
00431 }
00432
00433 KateHlItem::~KateHlItem()
00434 {
00435
00436 for (uint i=0; i < subItems.size(); i++)
00437 delete subItems[i];
00438 }
00439
00440 void KateHlItem::dynamicSubstitute(QString &str, const QStringList *args)
00441 {
00442 for (uint i = 0; i < str.length() - 1; ++i)
00443 {
00444 if (str[i] == '%')
00445 {
00446 char c = str[i + 1].latin1();
00447 if (c == '%')
00448 str.replace(i, 1, "");
00449 else if (c >= '0' && c <= '9')
00450 {
00451 if ((uint)(c - '0') < args->size())
00452 {
00453 str.replace(i, 2, (*args)[c - '0']);
00454 i += ((*args)[c - '0']).length() - 1;
00455 }
00456 else
00457 {
00458 str.replace(i, 2, "");
00459 --i;
00460 }
00461 }
00462 }
00463 }
00464 }
00465
00466
00467
00468 KateHlCharDetect::KateHlCharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar c)
00469 : KateHlItem(attribute,context,regionId,regionId2)
00470 , sChar(c)
00471 {
00472 }
00473
00474 int KateHlCharDetect::checkHgl(const QString& text, int offset, int )
00475 {
00476 if (text[offset] == sChar)
00477 return offset + 1;
00478
00479 return 0;
00480 }
00481
00482 KateHlItem *KateHlCharDetect::clone(const QStringList *args)
00483 {
00484 char c = sChar.latin1();
00485
00486 if (c < '0' || c > '9' || (unsigned)(c - '0') >= args->size())
00487 return this;
00488
00489 KateHlCharDetect *ret = new KateHlCharDetect(attr, ctx, region, region2, (*args)[c - '0'][0]);
00490 ret->dynamicChild = true;
00491 return ret;
00492 }
00493
00494
00495
00496 KateHl2CharDetect::KateHl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2)
00497 : KateHlItem(attribute,context,regionId,regionId2)
00498 , sChar1 (ch1)
00499 , sChar2 (ch2)
00500 {
00501 }
00502
00503 int KateHl2CharDetect::checkHgl(const QString& text, int offset, int len)
00504 {
00505 if ((len >= 2) && text[offset++] == sChar1 && text[offset++] == sChar2)
00506 return offset;
00507
00508 return 0;
00509 }
00510
00511 KateHlItem *KateHl2CharDetect::clone(const QStringList *args)
00512 {
00513 char c1 = sChar1.latin1();
00514 char c2 = sChar2.latin1();
00515
00516 if (c1 < '0' || c1 > '9' || (unsigned)(c1 - '0') >= args->size())
00517 return this;
00518
00519 if (c2 < '0' || c2 > '9' || (unsigned)(c2 - '0') >= args->size())
00520 return this;
00521
00522 KateHl2CharDetect *ret = new KateHl2CharDetect(attr, ctx, region, region2, (*args)[c1 - '0'][0], (*args)[c2 - '0'][0]);
00523 ret->dynamicChild = true;
00524 return ret;
00525 }
00526
00527
00528
00529 KateHlStringDetect::KateHlStringDetect(int attribute, int context, signed char regionId,signed char regionId2,const QString &s, bool inSensitive)
00530 : KateHlItem(attribute, context,regionId,regionId2)
00531 , str(inSensitive ? s.upper() : s)
00532 , strLen (str.length())
00533 , _inSensitive(inSensitive)
00534 {
00535 }
00536
00537 int KateHlStringDetect::checkHgl(const QString& text, int offset, int len)
00538 {
00539 if (len < strLen)
00540 return 0;
00541
00542 if (_inSensitive)
00543 {
00544 for (int i=0; i < strLen; i++)
00545 if (text[offset++].upper() != str[i])
00546 return 0;
00547
00548 return offset;
00549 }
00550 else
00551 {
00552 for (int i=0; i < strLen; i++)
00553 if (text[offset++] != str[i])
00554 return 0;
00555
00556 return offset;
00557 }
00558
00559 return 0;
00560 }
00561
00562 KateHlItem *KateHlStringDetect::clone(const QStringList *args)
00563 {
00564 QString newstr = str;
00565
00566 dynamicSubstitute(newstr, args);
00567
00568 if (newstr == str)
00569 return this;
00570
00571 KateHlStringDetect *ret = new KateHlStringDetect(attr, ctx, region, region2, newstr, _inSensitive);
00572 ret->dynamicChild = true;
00573 return ret;
00574 }
00575
00576
00577
00578 KateHlRangeDetect::KateHlRangeDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2)
00579 : KateHlItem(attribute,context,regionId,regionId2)
00580 , sChar1 (ch1)
00581 , sChar2 (ch2)
00582 {
00583 }
00584
00585 int KateHlRangeDetect::checkHgl(const QString& text, int offset, int len)
00586 {
00587 if (text[offset] == sChar1)
00588 {
00589 do
00590 {
00591 offset++;
00592 len--;
00593 if (len < 1) return 0;
00594 }
00595 while (text[offset] != sChar2);
00596
00597 return offset + 1;
00598 }
00599 return 0;
00600 }
00601
00602
00603
00604 KateHlKeyword::KateHlKeyword (int attribute, int context, signed char regionId,signed char regionId2, bool casesensitive, const QString& delims)
00605 : KateHlItem(attribute,context,regionId,regionId2)
00606 , _caseSensitive(casesensitive)
00607 , deliminators(delims)
00608 , minLen (0xFFFFFF)
00609 , maxLen (0)
00610 {
00611 alwaysStartEnable = false;
00612 customStartEnable = true;
00613 }
00614
00615 KateHlKeyword::~KateHlKeyword ()
00616 {
00617 for (uint i=0; i < dict.size(); ++i)
00618 delete dict[i];
00619 }
00620
00621 void KateHlKeyword::addList(const QStringList& list)
00622 {
00623 for(uint i=0; i < list.count(); ++i)
00624 {
00625 int len = list[i].length();
00626
00627 if (minLen > len)
00628 minLen = len;
00629
00630 if (maxLen < len)
00631 maxLen = len;
00632
00633 if ((uint)len >= dict.size())
00634 {
00635 uint oldSize = dict.size();
00636 dict.resize (len+1);
00637
00638 for (uint m=oldSize; m < dict.size(); ++m)
00639 dict[m] = 0;
00640 }
00641
00642 if (!dict[len])
00643 dict[len] = new QDict<bool> (17, _caseSensitive);
00644
00645 dict[len]->insert(list[i], &trueBool);
00646 }
00647 }
00648
00649 int KateHlKeyword::checkHgl(const QString& text, int offset, int len)
00650 {
00651 int offset2 = offset;
00652 int wordLen = 0;
00653
00654 while ((len > wordLen) && !kateInsideString (deliminators, text[offset2]))
00655 {
00656 offset2++;
00657 wordLen++;
00658
00659 if (wordLen > maxLen) return 0;
00660 }
00661
00662 if (wordLen < minLen) return 0;
00663
00664 if ( dict[wordLen] && dict[wordLen]->find(QConstString(text.unicode() + offset, wordLen).string()) )
00665 return offset2;
00666
00667 return 0;
00668 }
00669
00670
00671
00672 KateHlInt::KateHlInt(int attribute, int context, signed char regionId,signed char regionId2)
00673 : KateHlItem(attribute,context,regionId,regionId2)
00674 {
00675 alwaysStartEnable = false;
00676 }
00677
00678 int KateHlInt::checkHgl(const QString& text, int offset, int len)
00679 {
00680 int offset2 = offset;
00681
00682 while ((len > 0) && text[offset2].isDigit())
00683 {
00684 offset2++;
00685 len--;
00686 }
00687
00688 if (offset2 > offset)
00689 {
00690 if (len > 0)
00691 {
00692 for (uint i=0; i < subItems.size(); i++)
00693 {
00694 if ( (offset = subItems[i]->checkHgl(text, offset2, len)) )
00695 return offset;
00696 }
00697 }
00698
00699 return offset2;
00700 }
00701
00702 return 0;
00703 }
00704
00705
00706
00707 KateHlFloat::KateHlFloat(int attribute, int context, signed char regionId,signed char regionId2)
00708 : KateHlItem(attribute,context, regionId,regionId2)
00709 {
00710 alwaysStartEnable = false;
00711 }
00712
00713 int KateHlFloat::checkHgl(const QString& text, int offset, int len)
00714 {
00715 bool b = false;
00716 bool p = false;
00717
00718 while ((len > 0) && text[offset].isDigit())
00719 {
00720 offset++;
00721 len--;
00722 b = true;
00723 }
00724
00725 if ((len > 0) && (p = (text[offset] == '.')))
00726 {
00727 offset++;
00728 len--;
00729
00730 while ((len > 0) && text[offset].isDigit())
00731 {
00732 offset++;
00733 len--;
00734 b = true;
00735 }
00736 }
00737
00738 if (!b)
00739 return 0;
00740
00741 if ((len > 0) && ((text[offset] & 0xdf) == 'E'))
00742 {
00743 offset++;
00744 len--;
00745 }
00746 else
00747 {
00748 if (!p)
00749 return 0;
00750 else
00751 {
00752 if (len > 0)
00753 {
00754 for (uint i=0; i < subItems.size(); i++)
00755 {
00756 int offset2 = subItems[i]->checkHgl(text, offset, len);
00757
00758 if (offset2)
00759 return offset2;
00760 }
00761 }
00762
00763 return offset;
00764 }
00765 }
00766
00767 if ((len > 0) && (text[offset] == '-' || text[offset] =='+'))
00768 {
00769 offset++;
00770 len--;
00771 }
00772
00773 b = false;
00774
00775 while ((len > 0) && text[offset].isDigit())
00776 {
00777 offset++;
00778 len--;
00779 b = true;
00780 }
00781
00782 if (b)
00783 {
00784 if (len > 0)
00785 {
00786 for (uint i=0; i < subItems.size(); i++)
00787 {
00788 int offset2 = subItems[i]->checkHgl(text, offset, len);
00789
00790 if (offset2)
00791 return offset2;
00792 }
00793 }
00794
00795 return offset;
00796 }
00797
00798 return 0;
00799 }
00800
00801
00802
00803 KateHlCOct::KateHlCOct(int attribute, int context, signed char regionId,signed char regionId2)
00804 : KateHlItem(attribute,context,regionId,regionId2)
00805 {
00806 alwaysStartEnable = false;
00807 }
00808
00809 int KateHlCOct::checkHgl(const QString& text, int offset, int len)
00810 {
00811 if (text[offset] == '0')
00812 {
00813 offset++;
00814 len--;
00815
00816 int offset2 = offset;
00817
00818 while ((len > 0) && (text[offset2] >= '0' && text[offset2] <= '7'))
00819 {
00820 offset2++;
00821 len--;
00822 }
00823
00824 if (offset2 > offset)
00825 {
00826 if ((len > 0) && ((text[offset2] & 0xdf) == 'L' || (text[offset] & 0xdf) == 'U' ))
00827 offset2++;
00828
00829 return offset2;
00830 }
00831 }
00832
00833 return 0;
00834 }
00835
00836
00837
00838 KateHlCHex::KateHlCHex(int attribute, int context,signed char regionId,signed char regionId2)
00839 : KateHlItem(attribute,context,regionId,regionId2)
00840 {
00841 alwaysStartEnable = false;
00842 }
00843
00844 int KateHlCHex::checkHgl(const QString& text, int offset, int len)
00845 {
00846 if ((len > 1) && (text[offset++] == '0') && ((text[offset++] & 0xdf) == 'X' ))
00847 {
00848 len -= 2;
00849
00850 int offset2 = offset;
00851
00852 while ((len > 0) && (text[offset2].isDigit() || ((text[offset2] & 0xdf) >= 'A' && (text[offset2] & 0xdf) <= 'F')))
00853 {
00854 offset2++;
00855 len--;
00856 }
00857
00858 if (offset2 > offset)
00859 {
00860 if ((len > 0) && ((text[offset2] & 0xdf) == 'L' || (text[offset2] & 0xdf) == 'U' ))
00861 offset2++;
00862
00863 return offset2;
00864 }
00865 }
00866
00867 return 0;
00868 }
00869
00870
00871
00872 KateHlCFloat::KateHlCFloat(int attribute, int context, signed char regionId,signed char regionId2)
00873 : KateHlFloat(attribute,context,regionId,regionId2)
00874 {
00875 alwaysStartEnable = false;
00876 }
00877
00878 int KateHlCFloat::checkIntHgl(const QString& text, int offset, int len)
00879 {
00880 int offset2 = offset;
00881
00882 while ((len > 0) && text[offset].isDigit()) {
00883 offset2++;
00884 len--;
00885 }
00886
00887 if (offset2 > offset)
00888 return offset2;
00889
00890 return 0;
00891 }
00892
00893 int KateHlCFloat::checkHgl(const QString& text, int offset, int len)
00894 {
00895 int offset2 = KateHlFloat::checkHgl(text, offset, len);
00896
00897 if (offset2)
00898 {
00899 if ((text[offset2] & 0xdf) == 'F' )
00900 offset2++;
00901
00902 return offset2;
00903 }
00904 else
00905 {
00906 offset2 = checkIntHgl(text, offset, len);
00907
00908 if (offset2 && ((text[offset2] & 0xdf) == 'F' ))
00909 return ++offset2;
00910 else
00911 return 0;
00912 }
00913 }
00914
00915
00916
00917 KateHlAnyChar::KateHlAnyChar(int attribute, int context, signed char regionId,signed char regionId2, const QString& charList)
00918 : KateHlItem(attribute, context,regionId,regionId2)
00919 , _charList(charList)
00920 {
00921 }
00922
00923 int KateHlAnyChar::checkHgl(const QString& text, int offset, int)
00924 {
00925 if (kateInsideString (_charList, text[offset]))
00926 return ++offset;
00927
00928 return 0;
00929 }
00930
00931
00932
00933 KateHlRegExpr::KateHlRegExpr( int attribute, int context, signed char regionId,signed char regionId2, QString regexp, bool insensitive, bool minimal)
00934 : KateHlItem(attribute, context, regionId,regionId2)
00935 , handlesLinestart (regexp.startsWith("^"))
00936 , _regexp(regexp)
00937 , _insensitive(insensitive)
00938 , _minimal(minimal)
00939 {
00940 if (!handlesLinestart)
00941 regexp.prepend("^");
00942
00943 Expr = new QRegExp(regexp, !_insensitive);
00944 Expr->setMinimal(_minimal);
00945 }
00946
00947 int KateHlRegExpr::checkHgl(const QString& text, int offset, int )
00948 {
00949 if (offset && handlesLinestart)
00950 return 0;
00951
00952 int offset2 = Expr->search( text, offset, QRegExp::CaretAtOffset );
00953
00954 if (offset2 == -1) return 0;
00955
00956 return (offset + Expr->matchedLength());
00957 }
00958
00959 QStringList *KateHlRegExpr::capturedTexts()
00960 {
00961 return new QStringList(Expr->capturedTexts());
00962 }
00963
00964 KateHlItem *KateHlRegExpr::clone(const QStringList *args)
00965 {
00966 QString regexp = _regexp;
00967 QStringList escArgs = *args;
00968
00969 for (QStringList::Iterator it = escArgs.begin(); it != escArgs.end(); ++it)
00970 {
00971 (*it).replace(QRegExp("(\\W)"), "\\\\1");
00972 }
00973
00974 dynamicSubstitute(regexp, &escArgs);
00975
00976 if (regexp == _regexp)
00977 return this;
00978
00979
00980
00981 KateHlRegExpr *ret = new KateHlRegExpr(attr, ctx, region, region2, regexp, _insensitive, _minimal);
00982 ret->dynamicChild = true;
00983 return ret;
00984 }
00985
00986
00987
00988 KateHlLineContinue::KateHlLineContinue(int attribute, int context, signed char regionId,signed char regionId2)
00989 : KateHlItem(attribute,context,regionId,regionId2) {
00990 }
00991
00992 int KateHlLineContinue::checkHgl(const QString& text, int offset, int len)
00993 {
00994 if ((len == 1) && (text[offset] == '\\'))
00995 return ++offset;
00996
00997 return 0;
00998 }
00999
01000
01001
01002 KateHlCStringChar::KateHlCStringChar(int attribute, int context,signed char regionId,signed char regionId2)
01003 : KateHlItem(attribute,context,regionId,regionId2) {
01004 }
01005
01006
01007 static int checkEscapedChar(const QString& text, int offset, int& len)
01008 {
01009 int i;
01010 if (text[offset] == '\\' && len > 1)
01011 {
01012 offset++;
01013 len--;
01014
01015 switch(text[offset])
01016 {
01017 case 'a':
01018 case 'b':
01019 case 'e':
01020 case 'f':
01021
01022 case 'n':
01023 case 'r':
01024 case 't':
01025 case 'v':
01026 case '\'':
01027 case '\"':
01028 case '?' :
01029 case '\\':
01030 offset++;
01031 len--;
01032 break;
01033
01034 case 'x':
01035 offset++;
01036 len--;
01037
01038
01039
01040
01041 for (i = 0; (len > 0) && (i < 2) && (text[offset] >= '0' && text[offset] <= '9' || (text[offset] & 0xdf) >= 'A' && (text[offset] & 0xdf) <= 'F'); i++)
01042 {
01043 offset++;
01044 len--;
01045 }
01046
01047 if (i == 0)
01048 return 0;
01049
01050 break;
01051
01052 case '0': case '1': case '2': case '3' :
01053 case '4': case '5': case '6': case '7' :
01054 for (i = 0; (len > 0) && (i < 3) && (text[offset] >='0'&& text[offset] <='7'); i++)
01055 {
01056 offset++;
01057 len--;
01058 }
01059 break;
01060
01061 default:
01062 return 0;
01063 }
01064
01065 return offset;
01066 }
01067
01068 return 0;
01069 }
01070
01071 int KateHlCStringChar::checkHgl(const QString& text, int offset, int len)
01072 {
01073 return checkEscapedChar(text, offset, len);
01074 }
01075
01076
01077
01078 KateHlCChar::KateHlCChar(int attribute, int context,signed char regionId,signed char regionId2)
01079 : KateHlItem(attribute,context,regionId,regionId2) {
01080 }
01081
01082 int KateHlCChar::checkHgl(const QString& text, int offset, int len)
01083 {
01084 if ((len > 1) && (text[offset] == '\'') && (text[offset+1] != '\''))
01085 {
01086 int oldl;
01087 oldl = len;
01088
01089 len--;
01090
01091 int offset2 = checkEscapedChar(text, offset + 1, len);
01092
01093 if (!offset2)
01094 {
01095 if (oldl > 2)
01096 {
01097 offset2 = offset + 2;
01098 len = oldl - 2;
01099 }
01100 else
01101 {
01102 return 0;
01103 }
01104 }
01105
01106 if ((len > 0) && (text[offset2] == '\''))
01107 return ++offset2;
01108 }
01109
01110 return 0;
01111 }
01112
01113
01114
01115 KateHl2CharDetect::KateHl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, const QChar *s)
01116 : KateHlItem(attribute,context,regionId,regionId2) {
01117 sChar1 = s[0];
01118 sChar2 = s[1];
01119 }
01120
01121
01122 KateHlItemData::KateHlItemData(const QString name, int defStyleNum)
01123 : name(name), defStyleNum(defStyleNum) {
01124 }
01125
01126 KateHlData::KateHlData(const QString &wildcards, const QString &mimetypes, const QString &identifier, int priority)
01127 : wildcards(wildcards), mimetypes(mimetypes), identifier(identifier), priority(priority)
01128 {
01129 }
01130
01131
01132 KateHlContext::KateHlContext (const QString &_hlId, int attribute, int lineEndContext, int _lineBeginContext, bool _fallthrough,
01133 int _fallthroughContext, bool _dynamic, bool _noIndentationBasedFolding)
01134 {
01135 hlId = _hlId;
01136 attr = attribute;
01137 ctx = lineEndContext;
01138 lineBeginContext = _lineBeginContext;
01139 fallthrough = _fallthrough;
01140 ftctx = _fallthroughContext;
01141 dynamic = _dynamic;
01142 dynamicChild = false;
01143 noIndentationBasedFolding=_noIndentationBasedFolding;
01144 if (_noIndentationBasedFolding) kdDebug(13010)<<QString("**********************_noIndentationBasedFolding is TRUE*****************")<<endl;
01145
01146 }
01147
01148 KateHlContext *KateHlContext::clone(const QStringList *args)
01149 {
01150 KateHlContext *ret = new KateHlContext(hlId, attr, ctx, lineBeginContext, fallthrough, ftctx, false,noIndentationBasedFolding);
01151
01152 for (uint n=0; n < items.size(); ++n)
01153 {
01154 KateHlItem *item = items[n];
01155 KateHlItem *i = (item->dynamic ? item->clone(args) : item);
01156 ret->items.append(i);
01157 }
01158
01159 ret->dynamicChild = true;
01160
01161 return ret;
01162 }
01163
01164 KateHlContext::~KateHlContext()
01165 {
01166 if (dynamicChild)
01167 {
01168 for (uint n=0; n < items.size(); ++n)
01169 {
01170 if (items[n]->dynamicChild)
01171 delete items[n];
01172 }
01173 }
01174 }
01175
01176
01177
01178 KateHighlighting::KateHighlighting(const KateSyntaxModeListItem *def) : refCount(0)
01179 {
01180 m_attributeArrays.setAutoDelete (true);
01181
01182 errorsAndWarnings = "";
01183 building=false;
01184 noHl = false;
01185 m_foldingIndentationSensitive = false;
01186 folding=false;
01187 internalIDList.setAutoDelete(true);
01188
01189 if (def == 0)
01190 {
01191 noHl = true;
01192 iName = "None";
01193 iNameTranslated = i18n("None");
01194 iSection = "";
01195 m_priority = 0;
01196 iHidden = false;
01197 m_additionalData.insert( "none", new HighlightPropertyBag );
01198 m_additionalData["none"]->deliminator = stdDeliminator;
01199 m_additionalData["none"]->wordWrapDeliminator = stdDeliminator;
01200 m_hlIndex[0] = "none";
01201 }
01202 else
01203 {
01204 iName = def->name;
01205 iNameTranslated = def->nameTranslated;
01206 iSection = def->section;
01207 iHidden = def->hidden;
01208 iWildcards = def->extension;
01209 iMimetypes = def->mimetype;
01210 identifier = def->identifier;
01211 iVersion=def->version;
01212 iAuthor=def->author;
01213 iLicense=def->license;
01214 m_priority=def->priority.toInt();
01215 }
01216
01217 deliminator = stdDeliminator;
01218 }
01219
01220 KateHighlighting::~KateHighlighting()
01221 {
01222
01223 for (uint i=0; i < m_contexts.size(); ++i)
01224 delete m_contexts[i];
01225 m_contexts.clear ();
01226 }
01227
01228 void KateHighlighting::generateContextStack(int *ctxNum, int ctx, QMemArray<short>* ctxs, int *prevLine)
01229 {
01230
01231 while (true)
01232 {
01233 if (ctx >= 0)
01234 {
01235 (*ctxNum) = ctx;
01236
01237 ctxs->resize (ctxs->size()+1, QGArray::SpeedOptim);
01238 (*ctxs)[ctxs->size()-1]=(*ctxNum);
01239
01240 return;
01241 }
01242 else
01243 {
01244 if (ctx == -1)
01245 {
01246 (*ctxNum)=( (ctxs->isEmpty() ) ? 0 : (*ctxs)[ctxs->size()-1]);
01247 }
01248 else
01249 {
01250 int size = ctxs->size() + ctx + 1;
01251
01252 if (size > 0)
01253 {
01254 ctxs->resize (size, QGArray::SpeedOptim);
01255 (*ctxNum)=(*ctxs)[size-1];
01256 }
01257 else
01258 {
01259 ctxs->resize (0, QGArray::SpeedOptim);
01260 (*ctxNum)=0;
01261 }
01262
01263 ctx = 0;
01264
01265 if ((*prevLine) >= (int)(ctxs->size()-1))
01266 {
01267 *prevLine=ctxs->size()-1;
01268
01269 if ( ctxs->isEmpty() )
01270 return;
01271
01272 KateHlContext *c = contextNum((*ctxs)[ctxs->size()-1]);
01273 if (c && (c->ctx != -1))
01274 {
01275
01276 ctx = c->ctx;
01277
01278 continue;
01279 }
01280 }
01281 }
01282
01283 return;
01284 }
01285 }
01286 }
01287
01291 int KateHighlighting::makeDynamicContext(KateHlContext *model, const QStringList *args)
01292 {
01293 QPair<KateHlContext *, QString> key(model, args->front());
01294 short value;
01295
01296 if (dynamicCtxs.contains(key))
01297 value = dynamicCtxs[key];
01298 else
01299 {
01300 kdDebug(13010) << "new stuff: " << startctx << endl;
01301
01302 KateHlContext *newctx = model->clone(args);
01303
01304 m_contexts.push_back (newctx);
01305
01306 value = startctx++;
01307 dynamicCtxs[key] = value;
01308 KateHlManager::self()->incDynamicCtxs();
01309 }
01310
01311
01312
01313 return value;
01314 }
01315
01320 void KateHighlighting::dropDynamicContexts()
01321 {
01322 for (uint i=base_startctx; i < m_contexts.size(); ++i)
01323 delete m_contexts[i];
01324
01325 m_contexts.resize (base_startctx);
01326
01327 dynamicCtxs.clear();
01328 startctx = base_startctx;
01329 }
01330
01339 void KateHighlighting::doHighlight ( KateTextLine *prevLine,
01340 KateTextLine *textLine,
01341 QMemArray<uint>* foldingList,
01342 bool *ctxChanged )
01343 {
01344 if (!textLine)
01345 return;
01346
01347 if (noHl)
01348 {
01349 if (textLine->length() > 0)
01350 memset (textLine->attributes(), 0, textLine->length());
01351
01352 return;
01353 }