katehighlight.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2003, 2004 Anders Lund <anders@alweb.dk> 00003 Copyright (C) 2003 Hamish Rodda <rodda@kde.org> 00004 Copyright (C) 2001,2002 Joseph Wenninger <jowenn@kde.org> 00005 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 00006 Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License version 2 as published by the Free Software Foundation. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 00023 //BEGIN INCLUDES 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 //END 00052 00053 //BEGIN defines 00054 // same as in kmimemagic, no need to feed more data 00055 #define KATE_HL_HOWMANY 1024 00056 00057 // min. x seconds between two dynamic contexts reset 00058 static const int KATE_DYNAMIC_CONTEXTS_RESET_DELAY = 30 * 1000; 00059 00060 // x is a QString. if x is "true" or "1" this expression returns "true" 00061 #define IS_TRUE(x) x.lower() == QString("true") || x.toInt() == 1 00062 //END defines 00063 00064 //BEGIN Prviate HL classes 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 // caller must keep in mind: LEN > 0 is a must !!!!!!!!!!!!!!!!!!!!!1 00085 // Now, the function returns the offset detected, or 0 if no match is found. 00086 // bool linestart isn't needed, this is equivalent to offset == 0. 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 // start enable flags, nicer than the virtual methodes 00111 // saves function calls 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; // where to go after no rules matched 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 //KateHlIncludeRule(int ctx_, uint pos_, bool incAttrib) {ctx=ctx_;pos=pos_;incCtx=-1;incCtxN="";includeAttrib=incAttrib} 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 insensitive, 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 _insensitive; 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 // first char should be a letter or underscore 00363 if ( text[offset].isLetter() || text[offset] == QChar ('_') ) 00364 { 00365 // memorize length 00366 int len2 = offset+len; 00367 00368 // one char seen 00369 offset++; 00370 00371 // now loop for all other thingies 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 //END 00386 00387 //BEGIN STATICS 00388 KateHlManager *KateHlManager::s_self = 0; 00389 00390 static const bool trueBool = true; 00391 static const QString stdDeliminator = QString (" \t.():!+,-<=>%&*/;?[]^{|}~\\"); 00392 //END 00393 00394 //BEGIN NON MEMBER FUNCTIONS 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 //END 00415 00416 //BEGIN KateHlItem 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 //kdDebug(13010)<<"In hlItem::~KateHlItem()"<<endl; 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 //END 00466 00467 //BEGIN KateHlCharDetect 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 /*len*/) 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 //END 00494 00495 //BEGIN KateHl2CharDetect 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 //END 00527 00528 //BEGIN KateHlStringDetect 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 //END 00576 00577 //BEGIN KateHlRangeDetect 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 //END 00602 00603 //BEGIN KateHlKeyword 00604 KateHlKeyword::KateHlKeyword (int attribute, int context, signed char regionId,signed char regionId2, bool insensitive, const QString& delims) 00605 : KateHlItem(attribute,context,regionId,regionId2) 00606 , _insensitive(insensitive) 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, !_insensitive); 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 //END 00670 00671 //BEGIN KateHlInt 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 //END 00705 00706 //BEGIN KateHlFloat 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 //END 00801 00802 //BEGIN KateHlCOct 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 //END 00836 00837 //BEGIN KateHlCHex 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 //END 00870 00871 //BEGIN KateHlCFloat 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 //END 00915 00916 //BEGIN KateHlAnyChar 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 //END 00931 00932 //BEGIN KateHlRegExpr 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 /*len*/) 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 // kdDebug (13010) << "clone regexp: " << regexp << endl; 00980 00981 KateHlRegExpr *ret = new KateHlRegExpr(attr, ctx, region, region2, regexp, _insensitive, _minimal); 00982 ret->dynamicChild = true; 00983 return ret; 00984 } 00985 //END 00986 00987 //BEGIN KateHlLineContinue 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 //END 01000 01001 //BEGIN KateHlCStringChar 01002 KateHlCStringChar::KateHlCStringChar(int attribute, int context,signed char regionId,signed char regionId2) 01003 : KateHlItem(attribute,context,regionId,regionId2) { 01004 } 01005 01006 // checks for C escaped chars \n and escaped hex/octal chars 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': // checks for control chars 01018 case 'b': // we want to fall through 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 '?' : // added ? ANSI C classifies this as an escaped char 01029 case '\\': 01030 offset++; 01031 len--; 01032 break; 01033 01034 case 'x': // if it's like \xff 01035 offset++; // eat the x 01036 len--; 01037 // these for loops can probably be 01038 // replaced with something else but 01039 // for right now they work 01040 // check for hexdigits 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; // takes care of case '\x' 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 //END 01076 01077 //BEGIN KateHlCChar 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 //END 01113 01114 //BEGIN KateHl2CharDetect 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 //END KateHl2CharDetect 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 //BEGIN KateHlContext 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 //END 01176 01177 //BEGIN KateHighlighting 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"; // not translated internal name (for config and more) 01193 iNameTranslated = i18n("None"); // user visible name 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 // cu contexts 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 //kdDebug(13010)<<QString("Entering generateContextStack with %1").arg(ctx)<<endl; 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 //kdDebug(13010)<<"PrevLine > size()-1 and ctx!=-1)"<<endl; 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 // kdDebug(13010) << "Dynamic context: using context #" << value << " (for model " << model << " with args " << *args << ")" << endl; 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 } 01354 01355 // duplicate the ctx stack, only once ! 01356 QMemArray<short> ctx; 01357 ctx.duplicate (prevLine->ctxArray()); 01358 01359 int ctxNum = 0; 01360 int previousLine = -1; 01361 KateHlContext *context; 01362 01363 if (ctx.isEmpty()) 01364 { 01365 // If the stack is empty, we assume to be in Context 0 (Normal) 01366 context = contextNum(ctxNum); 01367 } 01368 else 01369 { 01370 // There does an old context stack exist -> find the context at the line start 01371 ctxNum = ctx[ctx.size()-1]; //context ID of the last character in the previous line 01372 01373 //kdDebug(13010) << "\t\tctxNum = " << ctxNum << " contextList[ctxNum] = " << contextList[ctxNum] << endl; // ellis 01374 01375 //if (lineContinue) kdDebug(13010)<<QString("The old context should be %1").arg((int)ctxNum)<<endl; 01376 01377 if (!(context = contextNum(ctxNum))) 01378 context = contextNum(0); 01379 01380 //kdDebug(13010)<<"test1-2-1-text2"<<endl; 01381 01382 previousLine=ctx.size()-1; //position of the last context ID of th previous line within the stack 01383 01384 // hl continue set or not ??? 01385 if (prevLine->hlLineContinue()) 01386 { 01387 prevLine--; 01388 } 01389 else 01390 { 01391 generateContextStack(&ctxNum, context->ctx, &ctx, &previousLine); //get stack ID to use 01392 01393 if (!(context = contextNum(ctxNum))) 01394 context = contextNum(0); 01395 } 01396 01397 //kdDebug(13010)<<"test1-2-1-text4"<<endl; 01398 01399 //if (lineContinue) kdDebug(13010)<<QString("The new context is %1").arg((int)ctxNum)<<endl; 01400 } 01401 01402 // text, for programming convenience :) 01403 QChar lastChar = ' '; 01404 const QString& text = textLine->string(); 01405 const int len = textLine->length(); 01406 01407 // calc at which char the first char occurs, set it to lenght of line if never 01408 const int firstChar = textLine->firstChar(); 01409 const int startNonSpace = (firstChar == -1) ? len : firstChar; 01410 01411 // last found item 01412 KateHlItem *item = 0; 01413 01414 // loop over the line, offset gives current offset 01415 int offset = 0; 01416 while (offset < len) 01417 { 01418 bool anItemMatched = false; 01419 bool standardStartEnableDetermined = false; 01420 bool customStartEnableDetermined = false; 01421 01422 uint index = 0; 01423 for (item = context->items.empty() ? 0 : context->items[0]; item; item = (++index < context->items.size()) ? context->items[index] : 0 ) 01424 { 01425 // does we only match if we are firstNonSpace? 01426 if (item->firstNonSpace && (offset > startNonSpace)) 01427 continue; 01428 01429 // have we a column specified? if yes, only match at this column 01430 if ((item->column != -1) && (item->column != offset)) 01431 continue; 01432 01433 if (!item->alwaysStartEnable) 01434 { 01435 if (item->customStartEnable) 01436 { 01437 if (customStartEnableDetermined || kateInsideString (m_additionalData[context->hlId]->deliminator, lastChar)) 01438 customStartEnableDetermined = true; 01439 else 01440 continue; 01441 } 01442 else 01443 { 01444 if (standardStartEnableDetermined || kateInsideString (stdDeliminator, lastChar)) 01445 standardStartEnableDetermined = true; 01446 else 01447 continue; 01448 } 01449 } 01450 01451 int offset2 = item->checkHgl(text, offset, len-offset); 01452 01453 if (offset2 <= offset) 01454 continue; 01455 // BUG 144599: Ignore a context change that would push the same context 01456 // without eating anything... this would be an infinite loop! 01457 if ( item->lookAhead && item->ctx == ctxNum ) 01458 continue; 01459 01460 if (item->region2) 01461 { 01462 // kdDebug(13010)<<QString("Region mark 2 detected: %1").arg(item->region2)<<endl; 01463 if ( !foldingList->isEmpty() && ((item->region2 < 0) && (*foldingList)[foldingList->size()-2] == -item->region2 ) ) 01464 { 01465 foldingList->resize (foldingList->size()-2, QGArray::SpeedOptim); 01466 } 01467 else 01468 { 01469 foldingList->resize (foldingList->size()+2, QGArray::SpeedOptim); 01470 (*foldingList)[foldingList->size()-2] = (uint)item->region2; 01471 if (item->region2<0) //check not really needed yet 01472 (*foldingList)[foldingList->size()-1] = offset2; 01473 else 01474 (*foldingList)[foldingList->size()-1] = offset; 01475 } 01476 01477 } 01478 01479 if (item->region) 01480 { 01481 // kdDebug(13010)<<QString("Region mark detected: %1").arg(item->region)<<endl; 01482 01483 /* if ( !foldingList->isEmpty() && ((item->region < 0) && (*foldingList)[foldingList->size()-1] == -item->region ) ) 01484 { 01485 foldingList->resize (foldingList->size()-1, QGArray::SpeedOptim); 01486 } 01487 else*/ 01488 { 01489 foldingList->resize (foldingList->size()+2, QGArray::SpeedOptim); 01490 (*foldingList)[foldingList->size()-2] = item->region; 01491 if (item->region<0) //check not really needed yet 01492 (*foldingList)[foldingList->size()-1] = offset2; 01493 else 01494 (*foldingList)[foldingList->size()-1] = offset; 01495 } 01496 01497 } 01498 01499 // regenerate context stack if needed 01500 if (item->ctx != -1) 01501 { 01502 generateContextStack (&ctxNum, item->ctx, &ctx, &previousLine); 01503 context = contextNum(ctxNum); 01504 } 01505 01506 // dynamic context: substitute the model with an 'instance' 01507 if (context->dynamic) 01508 { 01509 QStringList *lst = item->capturedTexts(); 01510 if (lst != 0) 01511 { 01512 // Replace the top of the stack and the current context 01513 int newctx = makeDynamicContext(context, lst); 01514 if (ctx.size() > 0) 01515 ctx[ctx.size() - 1] = newctx; 01516 ctxNum = newctx; 01517 context = contextNum(ctxNum); 01518 } 01519 delete lst; 01520 } 01521 01522 // dominik: look ahead w/o changing offset? 01523 if (!item->lookAhead) 01524 { 01525 if (offset2 > len) 01526 offset2 = len; 01527 01528 // even set attributes ;) 01529 memset ( textLine->attributes()+offset 01530 , item->onlyConsume ? context->attr : item->attr 01531 , offset2-offset); 01532 01533 offset = offset2; 01534 lastChar = text[offset-1]; 01535 } 01536 01537 anItemMatched = true; 01538 break; 01539 } 01540 01541 // something matched, continue loop 01542 if (anItemMatched) 01543 continue; 01544 01545 // nothing found: set attribute of one char 01546 // anders: unless this context does not want that! 01547 if ( context->fallthrough ) 01548 { 01549 // set context to context->ftctx. 01550 generateContextStack(&ctxNum, context->ftctx, &ctx, &previousLine); //regenerate context stack 01551 context=contextNum(ctxNum); 01552 //kdDebug(13010)<<"context num after fallthrough at col "<<z<<": "<<ctxNum<<endl; 01553 // the next is nessecary, as otherwise keyword (or anything using the std delimitor check) 01554 // immediately after fallthrough fails. Is it bad? 01555 // jowenn, can you come up with a nicer way to do this? 01556 /* if (offset) 01557 lastChar = text[offset - 1]; 01558 else 01559 lastChar = '\\';*/ 01560 continue; 01561 } 01562 else 01563 { 01564 *(textLine->attributes() + offset) = context->attr; 01565 lastChar = text[offset]; 01566 offset++; 01567 } 01568 } 01569 01570 // has the context stack changed ? 01571 if (ctx == textLine->ctxArray()) 01572 { 01573 if (ctxChanged) 01574 (*ctxChanged) = false; 01575 } 01576 else 01577 { 01578 if (ctxChanged) 01579 (*ctxChanged) = true; 01580 01581 // assign ctx stack ! 01582 textLine->setContext(ctx); 01583 } 01584 01585 // write hl continue flag 01586 textLine->setHlLineContinue (item && item->lineContinue()); 01587 01588 if (m_foldingIndentationSensitive) { 01589 bool noindent=false; 01590 for(int i=ctx.size()-1; i>=0; --i) { 01591 if (contextNum(ctx[i])->noIndentationBasedFolding) { 01592 noindent=true; 01593 break; 01594 } 01595 } 01596 textLine->setNoIndentBasedFolding(noindent); 01597 } 01598 } 01599 01600 void KateHighlighting::loadWildcards() 01601 { 01602 KConfig *config = KateHlManager::self()->getKConfig(); 01603 config->setGroup("Highlighting " + iName); 01604 01605 QString extensionString = config->readEntry("Wildcards", iWildcards); 01606 01607 if (extensionSource != extensionString) { 01608 regexpExtensions.clear(); 01609 plainExtensions.clear(); 01610 01611 extensionSource = extensionString; 01612 01613 static QRegExp sep("\\s*;\\s*"); 01614 01615 QStringList l = QStringList::split( sep, extensionSource ); 01616 01617 static QRegExp boringExpression("\\*\\.[\\d\\w]+"); 01618 01619 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) 01620 if (boringExpression.exactMatch(*it)) 01621 plainExtensions.append((*it).mid(1)); 01622 else 01623 regexpExtensions.append(QRegExp((*it), true, true)); 01624 } 01625 } 01626 01627 QValueList<QRegExp>& KateHighlighting::getRegexpExtensions() 01628 { 01629 return regexpExtensions; 01630 } 01631 01632 QStringList& KateHighlighting::getPlainExtensions() 01633 { 01634 return plainExtensions; 01635 } 01636 01637 QString KateHighlighting::getMimetypes() 01638 { 01639 KConfig *config = KateHlManager::self()->getKConfig(); 01640 config->setGroup("Highlighting " + iName); 01641 01642 return config->readEntry("Mimetypes", iMimetypes); 01643 } 01644 01645 int KateHighlighting::priority() 01646 { 01647 KConfig *config = KateHlManager::self()->getKConfig(); 01648 config->setGroup("Highlighting " + iName); 01649 01650 return config->readNumEntry("Priority", m_priority); 01651 } 01652 01653 KateHlData *KateHighlighting::getData() 01654 { 01655 KConfig *config = KateHlManager::self()->getKConfig(); 01656 config->setGroup("Highlighting " + iName); 01657 01658 KateHlData *hlData = new KateHlData( 01659 config->readEntry("Wildcards", iWildcards), 01660 config->readEntry("Mimetypes", iMimetypes), 01661 config->readEntry("Identifier", identifier), 01662 config->readNumEntry("Priority", m_priority)); 01663 01664 return hlData; 01665 } 01666 01667 void KateHighlighting::setData(KateHlData *hlData) 01668 { 01669 KConfig *config = KateHlManager::self()->getKConfig(); 01670 config->setGroup("Highlighting " + iName); 01671 01672 config->writeEntry("Wildcards",hlData->wildcards); 01673 config->writeEntry("Mimetypes",hlData->mimetypes); 01674 config->writeEntry("Priority",hlData->priority); 01675 } 01676 01677 void KateHighlighting::getKateHlItemDataList (uint schema, KateHlItemDataList &list) 01678 { 01679 KConfig *config = KateHlManager::self()->getKConfig(); 01680 config->setGroup("Highlighting " + iName + " - Schema " + KateFactory::self()->schemaManager()->name(schema)); 01681 01682 list.clear(); 01683 createKateHlItemData(list); 01684 01685 for (KateHlItemData *p = list.first(); p != 0L; p = list.next()) 01686 { 01687 QStringList s = config->readListEntry(p->name); 01688 01689 // kdDebug(13010)<<p->name<<s.count()<<endl; 01690 if (s.count()>0) 01691 { 01692 01693 while(s.count()<9) s<<""; 01694 p->clear(); 01695 01696 QString tmp=s[0]; if (!tmp.isEmpty()) p->defStyleNum=tmp.toInt(); 01697 01698 QRgb col; 01699 01700 tmp=s[1]; if (!tmp.isEmpty()) { 01701 col=tmp.toUInt(0,16); p->setTextColor(col); } 01702 01703 tmp=s[2]; if (!tmp.isEmpty()) { 01704 col=tmp.toUInt(0,16); p->setSelectedTextColor(col); } 01705 01706 tmp=s[3]; if (!tmp.isEmpty()) p->setBold(tmp!="0"); 01707 01708 tmp=s[4]; if (!tmp.isEmpty()) p->setItalic(tmp!="0"); 01709 01710 tmp=s[5]; if (!tmp.isEmpty()) p->setStrikeOut(tmp!="0"); 01711 01712 tmp=s[6]; if (!tmp.isEmpty()) p->setUnderline(tmp!="0"); 01713 01714 tmp=s[7]; if (!tmp.isEmpty()) { 01715 col=tmp.toUInt(0,16); p->setBGColor(col); } 01716 01717 tmp=s[8]; if (!tmp.isEmpty()) { 01718 col=tmp.toUInt(0,16); p->setSelectedBGColor(col); } 01719 01720 } 01721 } 01722 } 01723 01730 void KateHighlighting::setKateHlItemDataList(uint schema, KateHlItemDataList &list) 01731 { 01732 KConfig *config = KateHlManager::self()->getKConfig(); 01733 config->setGroup("Highlighting " + iName + " - Schema " 01734 + KateFactory::self()->schemaManager()->name(schema)); 01735 01736 QStringList settings; 01737 01738 for (KateHlItemData *p = list.first(); p != 0L; p = list.next()) 01739 { 01740 settings.clear(); 01741 settings<<QString::number(p->defStyleNum,10); 01742 settings<<(p->itemSet(KateAttribute::TextColor)?QString::number(p->textColor().rgb(),16):""); 01743 settings<<(p->itemSet(KateAttribute::SelectedTextColor)?QString::number(p->selectedTextColor().rgb(),16):""); 01744 settings<<(p->itemSet(KateAttribute::Weight)?(p->bold()?"1":"0"):""); 01745 settings<<(p->itemSet(KateAttribute::Italic)?(p->italic()?"1":"0"):""); 01746 settings<<(p->itemSet(KateAttribute::StrikeOut)?(p->strikeOut()?"1":"0"):""); 01747 settings<<(p->itemSet(KateAttribute::Underline)?(p->underline()?"1":"0"):""); 01748 settings<<(p->itemSet(KateAttribute::BGColor)?QString::number(p->bgColor().rgb(),16):""); 01749 settings<<(p->itemSet(KateAttribute::SelectedBGColor)?QString::number(p->selectedBGColor().rgb(),16):""); 01750 settings<<"---"; 01751 config->writeEntry(p->name,settings); 01752 } 01753 } 01754 01758 void KateHighlighting::use() 01759 { 01760 if (refCount == 0) 01761 init(); 01762 01763 refCount++; 01764 } 01765 01769 void KateHighlighting::release() 01770 { 01771 refCount--; 01772 01773 if (refCount == 0) 01774 done(); 01775 } 01776 01781 void KateHighlighting::init() 01782 { 01783 if (noHl) 01784 return; 01785 01786 // cu contexts 01787 for (uint i=0; i < m_contexts.size(); ++i) 01788 delete m_contexts[i]; 01789 m_contexts.clear (); 01790 01791 makeContextList(); 01792 } 01793 01794 01799 void KateHighlighting::done() 01800 { 01801 if (noHl) 01802 return; 01803 01804 // cu contexts 01805 for (uint i=0; i < m_contexts.size(); ++i) 01806 delete m_contexts[i]; 01807 m_contexts.clear (); 01808 01809 internalIDList.clear(); 01810 } 01811 01819 void KateHighlighting::createKateHlItemData(KateHlItemDataList &list) 01820 { 01821 // If no highlighting is selected we need only one default. 01822 if (noHl) 01823 { 01824 list.append(new KateHlItemData(i18n("Normal Text"), KateHlItemData::dsNormal)); 01825 return; 01826 } 01827 01828 // If the internal list isn't already available read the config file 01829 if (internalIDList.isEmpty()) 01830 makeContextList(); 01831 01832 list=internalIDList; 01833 } 01834 01838 void KateHighlighting::addToKateHlItemDataList() 01839 { 01840 //Tell the syntax document class which file we want to parse and which data group 01841 KateHlManager::self()->syntax->setIdentifier(buildIdentifier); 01842 KateSyntaxContextData *data = KateHlManager::self()->syntax->getGroupInfo("highlighting","itemData"); 01843 01844 //begin with the real parsing 01845 while (KateHlManager::self()->syntax->nextGroup(data)) 01846 { 01847 // read all attributes 01848 QString color = KateHlManager::self()->syntax->groupData(data,QString("color")); 01849 QString selColor = KateHlManager::self()->syntax->groupData(data,QString("selColor")); 01850 QString bold = KateHlManager::self()->syntax->groupData(data,QString("bold")); 01851 QString italic = KateHlManager::self()->syntax->groupData(data,QString("italic")); 01852 QString underline = KateHlManager::self()->syntax->groupData(data,QString("underline")); 01853 QString strikeOut = KateHlManager::self()->syntax->groupData(data,QString("strikeOut")); 01854 QString bgColor = KateHlManager::self()->syntax->groupData(data,QString("backgroundColor")); 01855 QString selBgColor = KateHlManager::self()->syntax->groupData(data,QString("selBackgroundColor")); 01856 01857 KateHlItemData* newData = new KateHlItemData( 01858 buildPrefix+KateHlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(), 01859 getDefStyleNum(KateHlManager::self()->syntax->groupData(data,QString("defStyleNum")))); 01860 01861 /* here the custom style overrides are specified, if needed */ 01862 if (!color.isEmpty()) newData->setTextColor(QColor(color)); 01863 if (!selColor.isEmpty()) newData->setSelectedTextColor(QColor(selColor)); 01864 if (!bold.isEmpty()) newData->setBold( IS_TRUE(bold) ); 01865 if (!italic.isEmpty()) newData->setItalic( IS_TRUE(italic) ); 01866 // new attributes for the new rendering view 01867 if (!underline.isEmpty()) newData->setUnderline( IS_TRUE(underline) ); 01868 if (!strikeOut.isEmpty()) newData->setStrikeOut( IS_TRUE(strikeOut) ); 01869 if (!bgColor.isEmpty()) newData->setBGColor(QColor(bgColor)); 01870 if (!selBgColor.isEmpty()) newData->setSelectedBGColor(QColor(selBgColor)); 01871 01872 internalIDList.append(newData); 01873 } 01874 01875 //clean up 01876 if (data) 01877 KateHlManager::self()->syntax->freeGroupInfo(data); 01878 } 01879 01890 int KateHighlighting::lookupAttrName(const QString& name, KateHlItemDataList &iDl) 01891 { 01892 for (uint i = 0; i < iDl.count(); i++) 01893 if (iDl.at(i)->name == buildPrefix+name) 01894 return i; 01895 01896 kdDebug(13010)<<"Couldn't resolve itemDataName:"<<name<<endl; 01897 return 0; 01898 } 01899 01913 KateHlItem *KateHighlighting::createKateHlItem(KateSyntaxContextData *data, 01914 KateHlItemDataList &iDl, 01915 QStringList *RegionList, 01916 QStringList *ContextNameList) 01917 { 01918 // No highlighting -> exit 01919 if (noHl) 01920 return 0; 01921 01922 // get the (tagname) itemd type 01923 QString dataname=KateHlManager::self()->syntax->groupItemData(data,QString("")); 01924 01925 // code folding region handling: 01926 QString beginRegionStr=KateHlManager::self()->syntax->groupItemData(data,QString("beginRegion")); 01927 QString endRegionStr=KateHlManager::self()->syntax->groupItemData(data,QString("endRegion")); 01928 01929 signed char regionId=0; 01930 signed char regionId2=0; 01931 01932 if (!beginRegionStr.isEmpty()) 01933 { 01934 regionId = RegionList->findIndex(beginRegionStr); 01935 01936 if (regionId==-1) // if the region name doesn't already exist, add it to the list 01937 { 01938 (*RegionList)<<beginRegionStr; 01939 regionId = RegionList->findIndex(beginRegionStr); 01940 } 01941 01942 regionId++; 01943 01944 kdDebug(13010) << "########### BEG REG: " << beginRegionStr << " NUM: " << regionId << endl; 01945 } 01946 01947 if (!endRegionStr.isEmpty()) 01948 { 01949 regionId2 = RegionList->findIndex(endRegionStr); 01950 01951 if (regionId2==-1) // if the region name doesn't already exist, add it to the list 01952 { 01953 (*RegionList)<<endRegionStr; 01954 regionId2 = RegionList->findIndex(endRegionStr); 01955 } 01956 01957 regionId2 = -regionId2 - 1; 01958 01959 kdDebug(13010) << "########### END REG: " << endRegionStr << " NUM: " << regionId2 << endl; 01960 } 01961 01962 int attr = 0; 01963 QString tmpAttr=KateHlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace(); 01964 bool onlyConsume = tmpAttr.isEmpty(); 01965 01966 // only relevant for non consumer 01967 if (!onlyConsume) 01968 { 01969 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) 01970 { 01971 errorsAndWarnings+=i18n( 01972 "<B>%1</B>: Deprecated syntax. Attribute (%2) not addressed by symbolic name<BR>"). 01973 arg(buildIdentifier).arg(tmpAttr); 01974 attr=tmpAttr.toInt(); 01975 } 01976 else 01977 attr=lookupAttrName(tmpAttr,iDl); 01978 } 01979 01980 // Info about context switch 01981 int context = -1; 01982 QString unresolvedContext; 01983 QString tmpcontext=KateHlManager::self()->syntax->groupItemData(data,QString("context")); 01984 if (!tmpcontext.isEmpty()) 01985 context=getIdFromString(ContextNameList, tmpcontext,unresolvedContext); 01986 01987 // Get the char parameter (eg DetectChar) 01988 char chr; 01989 if (! KateHlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty()) 01990 chr= (KateHlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0]; 01991 else 01992 chr=0; 01993 01994 // Get the String parameter (eg. StringDetect) 01995 QString stringdata=KateHlManager::self()->syntax->groupItemData(data,QString("String")); 01996 01997 // Get a second char parameter (char1) (eg Detect2Chars) 01998 char chr1; 01999 if (! KateHlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty()) 02000 chr1= (KateHlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0]; 02001 else 02002 chr1=0; 02003 02004 // Will be removed eventually. Atm used for StringDetect, keyword and RegExp 02005 const QString & insensitive_str = KateHlManager::self()->syntax->groupItemData(data,QString("insensitive")); 02006 bool insensitive = IS_TRUE( insensitive_str ); 02007 02008 // for regexp only 02009 bool minimal = IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("minimal")) ); 02010 02011 // dominik: look ahead and do not change offset. so we can change contexts w/o changing offset1. 02012 bool lookAhead = IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("lookAhead")) ); 02013 02014 bool dynamic= IS_TRUE(KateHlManager::self()->syntax->groupItemData(data,QString("dynamic")) ); 02015 02016 bool firstNonSpace = IS_TRUE(KateHlManager::self()->syntax->groupItemData(data,QString("firstNonSpace")) ); 02017 02018 int column = -1; 02019 QString colStr = KateHlManager::self()->syntax->groupItemData(data,QString("column")); 02020 if (!colStr.isEmpty()) 02021 column = colStr.toInt(); 02022 02023 //Create the item corresponding to it's type and set it's parameters 02024 KateHlItem *tmpItem; 02025 02026 if (dataname=="keyword") 02027 { 02028 bool keywordInsensitive = insensitive_str.isEmpty() ? !casesensitive : insensitive; 02029 KateHlKeyword *keyword=new KateHlKeyword(attr,context,regionId,regionId2,keywordInsensitive, 02030 m_additionalData[ buildIdentifier ]->deliminator); 02031 02032 //Get the entries for the keyword lookup list 02033 keyword->addList(KateHlManager::self()->syntax->finddata("highlighting",stringdata)); 02034 tmpItem=keyword; 02035 } 02036 else if (dataname=="Float") tmpItem= (new KateHlFloat(attr,context,regionId,regionId2)); 02037 else if (dataname=="Int") tmpItem=(new KateHlInt(attr,context,regionId,regionId2)); 02038 else if (dataname=="DetectChar") tmpItem=(new KateHlCharDetect(attr,context,regionId,regionId2,chr)); 02039 else if (dataname=="Detect2Chars") tmpItem=(new KateHl2CharDetect(attr,context,regionId,regionId2,chr,chr1)); 02040 else if (dataname=="RangeDetect") tmpItem=(new KateHlRangeDetect(attr,context,regionId,regionId2, chr, chr1)); 02041 else if (dataname=="LineContinue") tmpItem=(new KateHlLineContinue(attr,context,regionId,regionId2)); 02042 else if (dataname=="StringDetect") tmpItem=(new KateHlStringDetect(attr,context,regionId,regionId2,stringdata,insensitive)); 02043 else if (dataname=="AnyChar") tmpItem=(new KateHlAnyChar(attr,context,regionId,regionId2,stringdata)); 02044 else if (dataname=="RegExpr") tmpItem=(new KateHlRegExpr(attr,context,regionId,regionId2,stringdata, insensitive, minimal)); 02045 else if (dataname=="HlCChar") tmpItem= ( new KateHlCChar(attr,context,regionId,regionId2)); 02046 else if (dataname=="HlCHex") tmpItem= (new KateHlCHex(attr,context,regionId,regionId2)); 02047 else if (dataname=="HlCOct") tmpItem= (new KateHlCOct(attr,context,regionId,regionId2)); 02048 else if (dataname=="HlCFloat") tmpItem= (new KateHlCFloat(attr,context,regionId,regionId2)); 02049 else if (dataname=="HlCStringChar") tmpItem= (new KateHlCStringChar(attr,context,regionId,regionId2)); 02050 else if (dataname=="DetectSpaces") tmpItem= (new KateHlDetectSpaces(attr,context,regionId,regionId2)); 02051 else if (dataname=="DetectIdentifier") tmpItem= (new KateHlDetectIdentifier(attr,context,regionId,regionId2)); 02052 else 02053 { 02054 // oops, unknown type. Perhaps a spelling error in the xml file 02055 return 0; 02056 } 02057 02058 // set lookAhead & dynamic properties 02059 tmpItem->lookAhead = lookAhead; 02060 tmpItem->dynamic = dynamic; 02061 tmpItem->firstNonSpace = firstNonSpace; 02062 tmpItem->column = column; 02063 tmpItem->onlyConsume = onlyConsume; 02064 02065 if (!unresolvedContext.isEmpty()) 02066 { 02067 unresolvedContextReferences.insert(&(tmpItem->ctx),unresolvedContext); 02068 } 02069 02070 return tmpItem; 02071 } 02072 02073 QString KateHighlighting::hlKeyForAttrib( int i ) const 02074 { 02075 // find entry. This is faster than QMap::find. m_hlIndex always has an entry 02076 // for key '0' (it is "none"), so the result is always valid. 02077 int k = 0; 02078 QMap<int,QString>::const_iterator it = m_hlIndex.constEnd(); 02079 while ( it != m_hlIndex.constBegin() ) 02080 { 02081 --it; 02082 k = it.key(); 02083 if ( i >= k ) 02084 break; 02085 } 02086 return it.data(); 02087 } 02088 02089 bool KateHighlighting::isInWord( QChar c, int attrib ) const 02090 { 02091 return m_additionalData[ hlKeyForAttrib( attrib ) ]->deliminator.find(c) < 0 02092 && !c.isSpace() && c != '"' && c != '\''; 02093 } 02094 02095 bool KateHighlighting::canBreakAt( QChar c, int attrib ) const 02096 { 02097 static const QString& sq = KGlobal::staticQString("\"'"); 02098 return (m_additionalData[ hlKeyForAttrib( attrib ) ]->wordWrapDeliminator.find(c) != -1) && (sq.find(c) == -1); 02099 } 02100 02101 signed char KateHighlighting::commentRegion(int attr) const { 02102 QString commentRegion=m_additionalData[ hlKeyForAttrib( attr ) ]->multiLineRegion; 02103 return (commentRegion.isEmpty()?0:(commentRegion.toShort())); 02104 } 02105 02106 bool KateHighlighting::canComment( int startAttrib, int endAttrib ) const 02107 { 02108 QString k = hlKeyForAttrib( startAttrib ); 02109 return ( k == hlKeyForAttrib( endAttrib ) && 02110 ( ( !m_additionalData[k]->multiLineCommentStart.isEmpty() && !m_additionalData[k]->multiLineCommentEnd.isEmpty() ) || 02111 ! m_additionalData[k]->singleLineCommentMarker.isEmpty() ) ); 02112 } 02113 02114 QString KateHighlighting::getCommentStart( int attrib ) const 02115 { 02116 return m_additionalData[ hlKeyForAttrib( attrib) ]->multiLineCommentStart; 02117 } 02118 02119 QString KateHighlighting::getCommentEnd( int attrib ) const 02120 { 02121 return m_additionalData[ hlKeyForAttrib( attrib ) ]->multiLineCommentEnd; 02122 } 02123 02124 QString KateHighlighting::getCommentSingleLineStart( int attrib ) const 02125 { 02126 return m_additionalData[ hlKeyForAttrib( attrib) ]->singleLineCommentMarker; 02127 } 02128 02129 KateHighlighting::CSLPos KateHighlighting::getCommentSingleLinePosition( int attrib ) const 02130 { 02131 return m_additionalData[ hlKeyForAttrib( attrib) ]->singleLineCommentPosition; 02132 } 02133 02134 02139 void KateHighlighting::readCommentConfig() 02140 { 02141 KateHlManager::self()->syntax->setIdentifier(buildIdentifier); 02142 KateSyntaxContextData *data=KateHlManager::self()->syntax->getGroupInfo("general","comment"); 02143 02144 QString cmlStart="", cmlEnd="", cmlRegion="", cslStart=""; 02145 CSLPos cslPosition=CSLPosColumn0; 02146 02147 if (data) 02148 { 02149 while (KateHlManager::self()->syntax->nextGroup(data)) 02150 { 02151 if (KateHlManager::self()->syntax->groupData(data,"name")=="singleLine") 02152 { 02153 cslStart=KateHlManager::self()->syntax->groupData(data,"start"); 02154 QString cslpos=KateHlManager::self()->syntax->groupData(data,"position"); 02155 if (cslpos=="afterwhitespace") 02156 cslPosition=CSLPosAfterWhitespace; 02157 else 02158 cslPosition=CSLPosColumn0; 02159 } 02160 else if (KateHlManager::self()->syntax->groupData(data,"name")=="multiLine") 02161 { 02162 cmlStart=KateHlManager::self()->syntax->groupData(data,"start"); 02163 cmlEnd=KateHlManager::self()->syntax->groupData(data,"end"); 02164 cmlRegion=KateHlManager::self()->syntax->groupData(data,"region"); 02165 } 02166 } 02167 02168 KateHlManager::self()->syntax->freeGroupInfo(data); 02169 } 02170 02171 m_additionalData[buildIdentifier]->singleLineCommentMarker = cslStart; 02172 m_additionalData[buildIdentifier]->singleLineCommentPosition = cslPosition; 02173 m_additionalData[buildIdentifier]->multiLineCommentStart = cmlStart; 02174 m_additionalData[buildIdentifier]->multiLineCommentEnd = cmlEnd; 02175 m_additionalData[buildIdentifier]->multiLineRegion = cmlRegion; 02176 } 02177 02183 void KateHighlighting::readGlobalKeywordConfig() 02184 { 02185 deliminator = stdDeliminator; 02186 // Tell the syntax document class which file we want to parse 02187 kdDebug(13010)<<"readGlobalKeywordConfig:BEGIN"<<endl; 02188 02189 KateHlManager::self()->syntax->setIdentifier(buildIdentifier); 02190 KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","keywords"); 02191 02192 if (data) 02193 { 02194 kdDebug(13010)<<"Found global keyword config"<<endl; 02195 02196 if ( IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("casesensitive")) ) ) 02197 casesensitive=true; 02198 else 02199 casesensitive=false; 02200 02201 //get the weak deliminators 02202 weakDeliminator=(KateHlManager::self()->syntax->groupItemData(data,QString("weakDeliminator"))); 02203 02204 kdDebug(13010)<<"weak delimiters are: "<<weakDeliminator<<endl; 02205 02206 // remove any weakDelimitars (if any) from the default list and store this list. 02207 for (uint s=0; s < weakDeliminator.length(); s++) 02208 { 02209 int f = deliminator.find (weakDeliminator[s]); 02210 02211 if (f > -1) 02212 deliminator.remove (f, 1); 02213 } 02214 02215 QString addDelim = (KateHlManager::self()->syntax->groupItemData(data,QString("additionalDeliminator"))); 02216 02217 if (!addDelim.isEmpty()) 02218 deliminator=deliminator+addDelim; 02219 02220 KateHlManager::self()->syntax->freeGroupInfo(data); 02221 } 02222 else 02223 { 02224 //Default values 02225 casesensitive=true; 02226 weakDeliminator=QString(""); 02227 } 02228 02229 kdDebug(13010)<<"readGlobalKeywordConfig:END"<<endl; 02230 02231 kdDebug(13010)<<"delimiterCharacters are: "<<deliminator<<endl; 02232 02233 m_additionalData[buildIdentifier]->deliminator = deliminator; 02234 } 02235 02246 void KateHighlighting::readWordWrapConfig() 02247 { 02248 // Tell the syntax document class which file we want to parse 02249 kdDebug(13010)<<"readWordWrapConfig:BEGIN"<<endl; 02250 02251 KateHlManager::self()->syntax->setIdentifier(buildIdentifier); 02252 KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","keywords"); 02253 02254 QString wordWrapDeliminator = stdDeliminator; 02255 if (data) 02256 { 02257 kdDebug(13010)<<"Found global keyword config"<<endl; 02258 02259 wordWrapDeliminator = (KateHlManager::self()->syntax->groupItemData(data,QString("wordWrapDeliminator"))); 02260 //when no wordWrapDeliminator is defined use the deliminator list 02261 if ( wordWrapDeliminator.length() == 0 ) wordWrapDeliminator = deliminator; 02262 02263 kdDebug(13010) << "word wrap deliminators are " << wordWrapDeliminator << endl; 02264 02265 KateHlManager::self()->syntax->freeGroupInfo(data); 02266 } 02267 02268 kdDebug(13010)<<"readWordWrapConfig:END"<<endl; 02269 02270 m_additionalData[buildIdentifier]->wordWrapDeliminator = wordWrapDeliminator; 02271 } 02272 02273 void KateHighlighting::readIndentationConfig() 02274 { 02275 m_indentation = ""; 02276 02277 KateHlManager::self()->syntax->setIdentifier(buildIdentifier); 02278 KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","indentation"); 02279 02280 if (data) 02281 { 02282 m_indentation = (KateHlManager::self()->syntax->groupItemData(data,QString("mode"))); 02283 02284 KateHlManager::self()->syntax->freeGroupInfo(data); 02285 } 02286 } 02287 02288 void KateHighlighting::readFoldingConfig() 02289 { 02290 // Tell the syntax document class which file we want to parse 02291 kdDebug(13010)<<"readfoldignConfig:BEGIN"<<endl; 02292 02293 KateHlManager::self()->syntax->setIdentifier(buildIdentifier); 02294 KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","folding"); 02295 02296 if (data) 02297 { 02298 kdDebug(13010)<<"Found global keyword config"<<endl; 02299 02300 if ( IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("indentationsensitive")) ) ) 02301 m_foldingIndentationSensitive=true; 02302 else 02303 m_foldingIndentationSensitive=false; 02304 02305 KateHlManager::self()->syntax->freeGroupInfo(data); 02306 } 02307 else 02308 { 02309 //Default values 02310 m_foldingIndentationSensitive = false; 02311 } 02312 02313 kdDebug(13010)<<"readfoldingConfig:END"<<endl; 02314 02315 kdDebug(13010)<<"############################ use indent for fold are: "<<m_foldingIndentationSensitive<<endl; 02316 } 02317 02318 void KateHighlighting::createContextNameList(QStringList *ContextNameList,int ctx0) 02319 { 02320 kdDebug(13010)<<"creatingContextNameList:BEGIN"<<endl; 02321 02322 if (ctx0 == 0) 02323 ContextNameList->clear(); 02324 02325 KateHlManager::self()->syntax->setIdentifier(buildIdentifier); 02326 02327 KateSyntaxContextData *data=KateHlManager::self()->syntax->getGroupInfo("highlighting","context"); 02328 02329 int id=ctx0; 02330 02331 if (data) 02332 { 02333 while (KateHlManager::self()->syntax->nextGroup(data)) 02334 { 02335 QString tmpAttr=KateHlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(); 02336 if (tmpAttr.isEmpty()) 02337 { 02338 tmpAttr=QString("!KATE_INTERNAL_DUMMY! %1").arg(id); 02339 errorsAndWarnings +=i18n("<B>%1</B>: Deprecated syntax. Context %2 has no symbolic name<BR>").arg(buildIdentifier).arg(id-ctx0); 02340 } 02341 else tmpAttr=buildPrefix+tmpAttr; 02342 (*ContextNameList)<<tmpAttr; 02343 id++; 02344 } 02345 KateHlManager::self()->syntax->freeGroupInfo(data); 02346 } 02347 kdDebug(13010)<<"creatingContextNameList:END"<<endl; 02348 02349 } 02350 02351 int KateHighlighting::getIdFromString(QStringList *ContextNameList, QString tmpLineEndContext, /*NO CONST*/ QString &unres) 02352 { 02353 unres=""; 02354 int context; 02355 if ((tmpLineEndContext=="#stay") || (tmpLineEndContext.simplifyWhiteSpace().isEmpty())) 02356 context=-1; 02357 02358 else if (tmpLineEndContext.startsWith("#pop")) 02359 { 02360 context=-1; 02361 for(;tmpLineEndContext.startsWith("#pop");context--) 02362 { 02363 tmpLineEndContext.remove(0,4); 02364 kdDebug(13010)<<"#pop found"<<endl; 02365 } 02366 } 02367 02368 else if ( tmpLineEndContext.contains("##")) 02369 { 02370 int o = tmpLineEndContext.find("##"); 02371 // FIXME at least with 'foo##bar'-style contexts the rules are picked up 02372 // but the default attribute is not 02373 QString tmp=tmpLineEndContext.mid(o+2); 02374 if (!embeddedHls.contains(tmp)) embeddedHls.insert(tmp,KateEmbeddedHlInfo()); 02375 unres=tmp+':'+tmpLineEndContext.left(o); 02376 context=0; 02377 } 02378 02379 else 02380 { 02381 context=ContextNameList->findIndex(buildPrefix+tmpLineEndContext); 02382 if (context==-1) 02383 { 02384 context=tmpLineEndContext.toInt(); 02385 errorsAndWarnings+=i18n( 02386 "<B>%1</B>:Deprecated syntax. Context %2 not addressed by a symbolic name" 02387 ).arg(buildIdentifier).arg(tmpLineEndContext); 02388 } 02389 //#warning restructure this the name list storage. 02390 // context=context+buildContext0Offset; 02391 } 02392 return context; 02393 } 02394 02400 void KateHighlighting::makeContextList() 02401 { 02402 if (noHl) // if this a highlighting for "normal texts" only, tere is no need for a context list creation 02403 return; 02404 02405 embeddedHls.clear(); 02406 unresolvedContextReferences.clear(); 02407 RegionList.clear(); 02408 ContextNameList.clear(); 02409 02410 // prepare list creation. To reuse as much code as possible handle this 02411 // highlighting the same way as embedded onces 02412 embeddedHls.insert(iName,KateEmbeddedHlInfo()); 02413 02414 bool something_changed; 02415 // the context "0" id is 0 for this hl, all embedded context "0"s have offsets 02416 startctx=base_startctx=0; 02417 // inform everybody that we are building the highlighting contexts and itemlists 02418 building=true; 02419 02420 do 02421 { 02422 kdDebug(13010)<<"**************** Outer loop in make ContextList"<<endl; 02423 kdDebug(13010)<<"**************** Hl List count:"<<embeddedHls.count()<<endl; 02424 something_changed=false; //assume all "embedded" hls have already been loaded 02425 for (KateEmbeddedHlInfos::const_iterator it=embeddedHls.begin(); it!=embeddedHls.end();++it) 02426 { 02427 if (!it.data().loaded) // we found one, we still have to load 02428 { 02429 kdDebug(13010)<<"**************** Inner loop in make ContextList"<<endl; 02430 QString identifierToUse; 02431 kdDebug(13010)<<"Trying to open highlighting definition file: "<< it.key()<<endl; 02432 if (iName==it.key()) // the own identifier is known 02433 identifierToUse=identifier; 02434 else // all others have to be looked up 02435 identifierToUse=KateHlManager::self()->identifierForName(it.key()); 02436 02437 kdDebug(13010)<<"Location is:"<< identifierToUse<<endl; 02438 02439 buildPrefix=it.key()+':'; // attribute names get prefixed by the names 02440 // of the highlighting definitions they belong to 02441 02442 if (identifierToUse.isEmpty() ) 02443 kdDebug(13010)<<"OHOH, unknown highlighting description referenced"<<endl; 02444 02445 kdDebug(13010)<<"setting ("<<it.key()<<") to loaded"<<endl; 02446 02447 //mark hl as loaded 02448 it=embeddedHls.insert(it.key(),KateEmbeddedHlInfo(true,startctx)); 02449 //set class member for context 0 offset, so we don't need to pass it around 02450 buildContext0Offset=startctx; 02451 //parse one hl definition file 02452 startctx=addToContextList(identifierToUse,startctx); 02453 02454 if (noHl) return; // an error occurred 02455 02456 base_startctx = startctx; 02457 something_changed=true; // something has been loaded 02458 } 02459 } 02460 } while (something_changed); // as long as there has been another file parsed 02461 // repeat everything, there could be newly added embedded hls. 02462 02463 02464 // at this point all needed highlighing (sub)definitions are loaded. It's time 02465 // to resolve cross file references (if there are any) 02466 kdDebug(13010)<<"Unresolved contexts, which need attention: "<<unresolvedContextReferences.count()<<endl; 02467 02468 //optimize this a littlebit 02469 for (KateHlUnresolvedCtxRefs::iterator unresIt=unresolvedContextReferences.begin(); 02470 unresIt!=unresolvedContextReferences.end();++unresIt) 02471 { 02472 QString incCtx = unresIt.data(); 02473 kdDebug(13010)<<"Context "<<incCtx<<" is unresolved"<<endl; 02474 // only resolve '##Name' contexts here; handleKateHlIncludeRules() can figure 02475 // out 'Name##Name'-style inclusions, but we screw it up 02476 if (incCtx.endsWith(":")) { 02477 kdDebug(13010)<<"Looking up context0 for ruleset "<<incCtx<<endl; 02478 incCtx = incCtx.left(incCtx.length()-1); 02479 //try to find the context0 id for a given unresolvedReference 02480 KateEmbeddedHlInfos::const_iterator hlIt=embeddedHls.find(incCtx); 02481 if (hlIt!=embeddedHls.end()) 02482 *(unresIt.key())=hlIt.data().context0; 02483 } 02484 } 02485 02486 // eventually handle KateHlIncludeRules items, if they exist. 02487 // This has to be done after the cross file references, because it is allowed 02488 // to include the context0 from a different definition, than the one the rule 02489 // belongs to 02490 handleKateHlIncludeRules(); 02491 02492 embeddedHls.clear(); //save some memory. 02493 unresolvedContextReferences.clear(); //save some memory 02494 RegionList.clear(); // I think you get the idea ;) 02495 ContextNameList.clear(); 02496 02497 02498 // if there have been errors show them 02499 if (!errorsAndWarnings.isEmpty()) 02500 KMessageBox::detailedSorry(0L,i18n( 02501 "There were warning(s) and/or error(s) while parsing the syntax " 02502 "highlighting configuration."), 02503 errorsAndWarnings, i18n("Kate Syntax Highlighting Parser")); 02504 02505 // we have finished 02506 building=false; 02507 } 02508 02509 void KateHighlighting::handleKateHlIncludeRules() 02510 { 02511 // if there are noe include rules to take care of, just return 02512 kdDebug(13010)<<"KateHlIncludeRules, which need attention: " <<includeRules.count()<<endl; 02513 if (includeRules.isEmpty()) return; 02514 02515 buildPrefix=""; 02516 QString dummy; 02517 02518 // By now the context0 references are resolved, now more or less only inner 02519 // file references are resolved. If we decide that arbitrary inclusion is 02520 // needed, this doesn't need to be changed, only the addToContextList 02521 // method. 02522 02523 //resolove context names 02524 for (KateHlIncludeRules::iterator it=includeRules.begin();it!=includeRules.end();) 02525 { 02526 if ((*it)->incCtx==-1) // context unresolved ? 02527 { 02528 02529 if ((*it)->incCtxN.isEmpty()) 02530 { 02531 // no context name given, and no valid context id set, so this item is 02532 // going to be removed 02533 KateHlIncludeRules::iterator it1=it; 02534 ++it1; 02535 delete (*it); 02536 includeRules.remove(it); 02537 it=it1; 02538 } 02539 else 02540 { 02541 // resolve name to id 02542 (*it)->incCtx=getIdFromString(&ContextNameList,(*it)->incCtxN,dummy); 02543 kdDebug(13010)<<"Resolved "<<(*it)->incCtxN<< " to "<<(*it)->incCtx<<" for include rule"<<endl; 02544 // It would be good to look here somehow, if the result is valid 02545 } 02546 } 02547 else ++it; //nothing to do, already resolved (by the cross defintion reference resolver) 02548 } 02549 02550 // now that all KateHlIncludeRule items should be valid and completely resolved, 02551 // do the real inclusion of the rules. 02552 // recursiveness is needed, because context 0 could include context 1, which 02553 // itself includes context 2 and so on. 02554 // In that case we have to handle context 2 first, then 1, 0 02555 //TODO: catch circular references: eg 0->1->2->3->1 02556 while (!includeRules.isEmpty()) 02557 handleKateHlIncludeRulesRecursive(includeRules.begin(),&includeRules); 02558 } 02559 02560 void KateHighlighting::handleKateHlIncludeRulesRecursive(KateHlIncludeRules::iterator it, KateHlIncludeRules *list) 02561 { 02562 if (it==list->end()) return; //invalid iterator, shouldn't happen, but better have a rule prepared ;) 02563 02564 KateHlIncludeRules::iterator it1=it; 02565 int ctx=(*it1)->ctx; 02566 02567 // find the last entry for the given context in the KateHlIncludeRules list 02568 // this is need if one context includes more than one. This saves us from 02569 // updating all insert positions: 02570 // eg: context 0: 02571 // pos 3 - include context 2 02572 // pos 5 - include context 3 02573 // During the building of the includeRules list the items are inserted in 02574 // ascending order, now we need it descending to make our life easier. 02575 while ((it!=list->end()) && ((*it)->ctx==ctx)) 02576 { 02577 it1=it; 02578 ++it; 02579 } 02580 02581 // iterate over each include rule for the context the function has been called for. 02582 while ((it1!=list->end()) && ((*it1)->ctx==ctx)) 02583 { 02584 int ctx1=(*it1)->incCtx; 02585 02586 //let's see, if the the included context includes other contexts 02587 for (KateHlIncludeRules::iterator it2=list->begin();it2!=list->end();++it2) 02588 { 02589 if ((*it2)->ctx==ctx1) 02590 { 02591 //yes it does, so first handle that include rules, since we want to 02592 // include those subincludes too 02593 handleKateHlIncludeRulesRecursive(it2,list); 02594 break; 02595 } 02596 } 02597 02598 // if the context we want to include had sub includes, they are already inserted there. 02599 KateHlContext *dest=m_contexts[ctx]; 02600 KateHlContext *src=m_contexts[ctx1]; 02601 // kdDebug(3010)<<"linking included rules from "<<ctx<<" to "<<ctx1<<endl; 02602 02603 // If so desired, change the dest attribute to the one of the src. 02604 // Required to make commenting work, if text matched by the included context 02605 // is a different highlight than the host context. 02606 if ( (*it1)->includeAttrib ) 02607 dest->attr = src->attr; 02608 02609 // insert the included context's rules starting at position p 02610 int p=(*it1)->pos; 02611 02612 // remember some stuff 02613 int oldLen = dest->items.size(); 02614 uint itemsToInsert = src->items.size(); 02615 02616 // resize target 02617 dest->items.resize (oldLen + itemsToInsert); 02618 02619 // move old elements 02620 for (int i=oldLen-1; i >= p; --i) 02621 dest->items[i+itemsToInsert] = dest->items[i]; 02622 02623 // insert new stuff 02624 for (uint i=0; i < itemsToInsert; ++i ) 02625 dest->items[p+i] = src->items[i]; 02626 02627 it=it1; //backup the iterator 02628 --it1; //move to the next entry, which has to be take care of 02629 delete (*it); //free the already handled data structure 02630 list->remove(it); // remove it from the list 02631 } 02632 } 02633 02639 int KateHighlighting::addToContextList(const QString &ident, int ctx0) 02640 { 02641 kdDebug(13010)<<"=== Adding hl with ident '"<<ident<<"'"<<endl; 02642 02643 buildIdentifier=ident; 02644 KateSyntaxContextData *data, *datasub; 02645 KateHlItem *c; 02646 02647 QString dummy; 02648 02649 // Let the syntax document class know, which file we'd like to parse 02650 if (!KateHlManager::self()->syntax->setIdentifier(ident)) 02651 { 02652 noHl=true; 02653 KMessageBox::information(0L,i18n( 02654 "Since there has been an error parsing the highlighting description, " 02655 "this highlighting will be disabled")); 02656 return 0; 02657 } 02658 02659 // only read for the own stuff 02660 if (identifier == ident) 02661 { 02662 readIndentationConfig (); 02663 } 02664 02665 RegionList<<"!KateInternal_TopLevel!"; 02666 02667 m_hlIndex[internalIDList.count()] = ident; 02668 m_additionalData.insert( ident, new HighlightPropertyBag ); 02669 02670 // fill out the propertybag 02671 readCommentConfig(); 02672 readGlobalKeywordConfig(); 02673 readWordWrapConfig(); 02674 02675 readFoldingConfig (); 02676 02677 QString ctxName; 02678 02679 // This list is needed for the translation of the attribute parameter, 02680 // if the itemData name is given instead of the index 02681 addToKateHlItemDataList(); 02682 KateHlItemDataList iDl = internalIDList; 02683 02684 createContextNameList(&ContextNameList,ctx0); 02685 02686 02687 kdDebug(13010)<<"Parsing Context structure"<<endl; 02688 //start the real work 02689 data=KateHlManager::self()->syntax->getGroupInfo("highlighting","context"); 02690 uint i=buildContext0Offset; 02691 if (data) 02692 { 02693 while (KateHlManager::self()->syntax->nextGroup(data)) 02694 { 02695 kdDebug(13010)<<"Found a context in file, building structure now"<<endl; 02696 //BEGIN - Translation of the attribute parameter 02697 QString tmpAttr=KateHlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace(); 02698 int attr; 02699 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) 02700 attr=tmpAttr.toInt(); 02701 else 02702 attr=lookupAttrName(tmpAttr,iDl); 02703 //END - Translation of the attribute parameter 02704 02705 ctxName=buildPrefix+KateHlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace(); 02706 02707 QString tmpLineEndContext=KateHlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace(); 02708 int context; 02709 02710 context=getIdFromString(&ContextNameList, tmpLineEndContext,dummy); 02711 02712 QString tmpNIBF = KateHlManager::self()->syntax->groupData(data, QString("noIndentationBasedFolding") ); 02713 bool noIndentationBasedFolding=IS_TRUE(tmpNIBF); 02714 02715 //BEGIN get fallthrough props 02716 bool ft = false; 02717 int ftc = 0; // fallthrough context 02718 if ( i > 0 ) // fallthrough is not smart in context 0 02719 { 02720 QString tmpFt = KateHlManager::self()->syntax->groupData(data, QString("fallthrough") ); 02721 if ( IS_TRUE(tmpFt) ) 02722 ft = true; 02723 if ( ft ) 02724 { 02725 QString tmpFtc = KateHlManager::self()->syntax->groupData( data, QString("fallthroughContext") ); 02726 02727 ftc=getIdFromString(&ContextNameList, tmpFtc,dummy); 02728 if (ftc == -1) ftc =0; 02729 02730 kdDebug(13010)<<"Setting fall through context (context "<<i<<"): "<<ftc<<endl; 02731 } 02732 } 02733 //END falltrhough props 02734 02735 bool dynamic = false; 02736 QString tmpDynamic = KateHlManager::self()->syntax->groupData(data, QString("dynamic") ); 02737 if ( tmpDynamic.lower() == "true" || tmpDynamic.toInt() == 1 ) 02738 dynamic = true; 02739 02740 KateHlContext *ctxNew = new KateHlContext ( 02741 ident, 02742 attr, 02743 context, 02744 (KateHlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1: 02745 (KateHlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt(), 02746 ft, ftc, dynamic,noIndentationBasedFolding); 02747 02748 m_contexts.push_back (ctxNew); 02749 02750 kdDebug(13010) << "INDEX: " << i << " LENGTH " << m_contexts.size()-1 << endl; 02751 02752 //Let's create all items for the context 02753 while (KateHlManager::self()->syntax->nextItem(data)) 02754 { 02755 // kdDebug(13010)<< "In make Contextlist: Item:"<<endl; 02756 02757 // KateHlIncludeRules : add a pointer to each item in that context 02758 // TODO add a attrib includeAttrib 02759 QString tag = KateHlManager::self()->syntax->groupItemData(data,QString("")); 02760 if ( tag == "IncludeRules" ) //if the new item is an Include rule, we have to take special care 02761 { 02762 QString incCtx = KateHlManager::self()->syntax->groupItemData( data, QString("context")); 02763 QString incAttrib = KateHlManager::self()->syntax->groupItemData( data, QString("includeAttrib")); 02764 bool includeAttrib = IS_TRUE( incAttrib ); 02765 // only context refernces of type Name, ##Name, and Subname##Name are allowed 02766 if (incCtx.startsWith("##") || (!incCtx.startsWith("#"))) 02767 { 02768 int incCtxi = incCtx.find("##"); 02769 //#stay, #pop is not interesting here 02770 if (incCtxi >= 0) 02771 { 02772 QString incSet = incCtx.mid(incCtxi + 2); 02773 QString incCtxN = incSet + ":" + incCtx.left(incCtxi); 02774 02775 //a cross highlighting reference 02776 kdDebug(13010)<<"Cross highlight reference <IncludeRules>, context "<<incCtxN<<endl; 02777 KateHlIncludeRule *ir=new KateHlIncludeRule(i,m_contexts[i]->items.count(),incCtxN,includeAttrib); 02778 02779 //use the same way to determine cross hl file references as other items do 02780 if (!embeddedHls.contains(incSet)) 02781 embeddedHls.insert(incSet,KateEmbeddedHlInfo()); 02782 else 02783 kdDebug(13010)<<"Skipping embeddedHls.insert for "<<incCtxN<<endl; 02784 02785 unresolvedContextReferences.insert(&(ir->incCtx), incCtxN); 02786 02787 includeRules.append(ir); 02788 } 02789 else 02790 { 02791 // a local reference -> just initialize the include rule structure 02792 incCtx=buildPrefix+incCtx.simplifyWhiteSpace(); 02793 includeRules.append(new KateHlIncludeRule(i,m_contexts[i]->items.count(),incCtx, includeAttrib)); 02794 } 02795 } 02796 02797 continue; 02798 } 02799 // TODO -- can we remove the block below?? 02800 #if 0 02801 QString tag = KateHlManager::self()->syntax->groupKateHlItemData(data,QString("")); 02802 if ( tag == "IncludeRules" ) { 02803 // attrib context: the index (jowenn, i think using names here 02804 // would be a cool feat, goes for mentioning the context in 02805 // any item. a map or dict?) 02806 int ctxId = getIdFromString(&ContextNameList, 02807 KateHlManager::self()->syntax->groupKateHlItemData( data, QString("context")),dummy); // the index is *required* 02808 if ( ctxId > -1) { // we can even reuse rules of 0 if we want to:) 02809 kdDebug(13010)<<"makeContextList["<<i<<"]: including all items of context "<<ctxId<<endl; 02810 if ( ctxId < (int) i ) { // must be defined 02811 for ( c = m_contexts[ctxId]->items.first(); c; c = m_contexts[ctxId]->items.next() ) 02812 m_contexts[i]->items.append(c); 02813 } 02814 else 02815 kdDebug(13010)<<"Context "<<ctxId<<"not defined. You can not include the rules of an undefined context"<<endl; 02816 } 02817 continue; // while nextItem 02818 } 02819 #endif 02820 c=createKateHlItem(data,iDl,&RegionList,&ContextNameList); 02821 if (c) 02822 { 02823 m_contexts[i]->items.append(c); 02824 02825 // Not supported completely atm and only one level. Subitems.(all have 02826 // to be matched to at once) 02827 datasub=KateHlManager::self()->syntax->getSubItems(data); 02828 bool tmpbool; 02829 if (tmpbool=KateHlManager::self()->syntax->nextItem(datasub)) 02830 { 02831 for (;tmpbool;tmpbool=KateHlManager::self()->syntax->nextItem(datasub)) 02832 { 02833 c->subItems.resize (c->subItems.size()+1); 02834 c->subItems[c->subItems.size()-1] = createKateHlItem(datasub,iDl,&RegionList,&ContextNameList); 02835 } } 02836 KateHlManager::self()->syntax->freeGroupInfo(datasub); 02837 // end of sublevel 02838 } 02839 } 02840 i++; 02841 } 02842 } 02843 02844 KateHlManager::self()->syntax->freeGroupInfo(data); 02845 02846 if (RegionList.count()!=1) 02847 folding=true; 02848 02849 folding = folding || m_foldingIndentationSensitive; 02850 02851 //BEGIN Resolve multiline region if possible 02852 if (!m_additionalData[ ident ]->multiLineRegion.isEmpty()) { 02853 long commentregionid=RegionList.findIndex( m_additionalData[ ident ]->multiLineRegion ); 02854 if (-1==commentregionid) { 02855 errorsAndWarnings+=i18n( 02856 "<B>%1</B>: Specified multiline comment region (%2) could not be resolved<BR>" 02857 ).arg(buildIdentifier).arg( m_additionalData[ ident ]->multiLineRegion ); 02858 m_additionalData[ ident ]->multiLineRegion = QString(); 02859 kdDebug(13010)<<"ERROR comment region attribute could not be resolved"<<endl; 02860 02861 } else { 02862 m_additionalData[ ident ]->multiLineRegion=QString::number(commentregionid+1); 02863 kdDebug(13010)<<"comment region resolved to:"<<m_additionalData[ ident ]->multiLineRegion<<endl; 02864 } 02865 } 02866 //END Resolve multiline region if possible 02867 return i; 02868 } 02869 02870 void KateHighlighting::clearAttributeArrays () 02871 { 02872 for ( QIntDictIterator< QMemArray<KateAttribute> > it( m_attributeArrays ); it.current(); ++it ) 02873 { 02874 // k, schema correct, let create the data 02875 KateAttributeList defaultStyleList; 02876 defaultStyleList.setAutoDelete(true); 02877 KateHlManager::self()->getDefaults(it.currentKey(), defaultStyleList); 02878 02879 KateHlItemDataList itemDataList; 02880 getKateHlItemDataList(it.currentKey(), itemDataList); 02881 02882 uint nAttribs = itemDataList.count(); 02883 QMemArray<KateAttribute> *array = it.current(); 02884 array->resize (nAttribs); 02885 02886 for (uint z = 0; z < nAttribs; z++) 02887 { 02888 KateHlItemData *itemData = itemDataList.at(z); 02889 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum); 02890 02891 if (itemData && itemData->isSomethingSet()) 02892 n += *itemData; 02893 02894 array->at(z) = n; 02895 } 02896 } 02897 } 02898 02899 QMemArray<KateAttribute> *KateHighlighting::attributes (uint schema) 02900 { 02901 QMemArray<KateAttribute> *array; 02902 02903 // found it, allready floating around 02904 if ((array = m_attributeArrays[schema])) 02905 return array; 02906 02907 // ohh, not found, check if valid schema number 02908 if (!KateFactory::self()->schemaManager()->validSchema(schema)) 02909 { 02910 // uhh, not valid :/, stick with normal default schema, it's always there ! 02911 return attributes (0); 02912 } 02913 02914 // k, schema correct, let create the data 02915 KateAttributeList defaultStyleList; 02916 defaultStyleList.setAutoDelete(true); 02917 KateHlManager::self()->getDefaults(schema, defaultStyleList); 02918 02919 KateHlItemDataList itemDataList; 02920 getKateHlItemDataList(schema, itemDataList); 02921 02922 uint nAttribs = itemDataList.count(); 02923 array = new QMemArray<KateAttribute> (nAttribs); 02924 02925 for (uint z = 0; z < nAttribs; z++) 02926 { 02927 KateHlItemData *itemData = itemDataList.at(z); 02928 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum); 02929 02930 if (itemData && itemData->isSomethingSet()) 02931 n += *itemData; 02932 02933 array->at(z) = n; 02934 } 02935 02936 m_attributeArrays.insert(schema, array); 02937 02938 return array; 02939 } 02940 02941 void KateHighlighting::getKateHlItemDataListCopy (uint schema, KateHlItemDataList &outlist) 02942 { 02943 KateHlItemDataList itemDataList; 02944 getKateHlItemDataList(schema, itemDataList); 02945 02946 outlist.clear (); 02947 outlist.setAutoDelete (true); 02948 for (uint z=0; z < itemDataList.count(); z++) 02949 outlist.append (new KateHlItemData (*itemDataList.at(z))); 02950 } 02951 02952 //END 02953 02954 //BEGIN KateHlManager 02955 KateHlManager::KateHlManager() 02956 : QObject() 02957 , m_config ("katesyntaxhighlightingrc", false, false) 02958 , commonSuffixes (QStringList::split(";", ".orig;.new;~;.bak;.BAK")) 02959 , syntax (new KateSyntaxDocument()) 02960 , dynamicCtxsCount(0) 02961 , forceNoDCReset(false) 02962 { 02963 hlList.setAutoDelete(true); 02964 hlDict.setAutoDelete(false); 02965 02966 KateSyntaxModeList modeList = syntax->modeList(); 02967 for (uint i=0; i < modeList.count(); i++) 02968 { 02969 KateHighlighting *hl = new KateHighlighting(modeList[i]); 02970 02971 uint insert = 0; 02972 for (; insert <= hlList.count(); insert++) 02973 { 02974 if (insert == hlList.count()) 02975 break; 02976 02977 if ( QString(hlList.at(insert)->section() + hlList.at(insert)->nameTranslated()).lower() 02978 > QString(hl->section() + hl->nameTranslated()).lower() ) 02979 break; 02980 } 02981 02982 hlList.insert (insert, hl); 02983 hlDict.insert (hl->name(), hl); 02984 } 02985 02986 // Normal HL 02987 KateHighlighting *hl = new KateHighlighting(0); 02988 hlList.prepend (hl); 02989 hlDict.insert (hl->name(), hl); 02990 02991 lastCtxsReset.start(); 02992 } 02993 02994 KateHlManager::~KateHlManager() 02995 { 02996 delete syntax; 02997 } 02998 02999 static KStaticDeleter<KateHlManager> sdHlMan; 03000 03001 KateHlManager *KateHlManager::self() 03002 { 03003 if ( !s_self ) 03004 sdHlMan.setObject(s_self, new KateHlManager ()); 03005 03006 return s_self; 03007 } 03008 03009 KateHighlighting *KateHlManager::getHl(int n) 03010 { 03011 if (n < 0 || n >= (int) hlList.count()) 03012 n = 0; 03013 03014 return hlList.at(n); 03015 } 03016 03017 int KateHlManager::nameFind(const QString &name) 03018 { 03019 int z (hlList.count() - 1); 03020 for (; z > 0; z--) 03021 if (hlList.at(z)->name() == name) 03022 return z; 03023 03024 return z; 03025 } 03026 03027 int KateHlManager::detectHighlighting (KateDocument *doc) 03028 { 03029 int hl = wildcardFind( doc->url().filename() ); 03030 if ( hl < 0 ) 03031 hl = mimeFind ( doc ); 03032 03033 return hl; 03034 } 03035 03036 int KateHlManager::wildcardFind(const QString &fileName) 03037 { 03038 int result = -1; 03039 if ((result = realWildcardFind(fileName)) != -1) 03040 return result; 03041 03042 int length = fileName.length(); 03043 QString backupSuffix = KateDocumentConfig::global()->backupSuffix(); 03044 if (fileName.endsWith(backupSuffix)) { 03045 if ((result = realWildcardFind(fileName.left(length - backupSuffix.length()))) != -1) 03046 return result; 03047 } 03048 03049 for (QStringList::Iterator it = commonSuffixes.begin(); it != commonSuffixes.end(); ++it) { 03050 if (*it != backupSuffix && fileName.endsWith(*it)) { 03051 if ((result = realWildcardFind(fileName.left(length - (*it).length()))) != -1) 03052 return result; 03053 } 03054 } 03055 03056 return -1; 03057 } 03058 03059 int KateHlManager::realWildcardFind(const QString &fileName) 03060 { 03061 static QRegExp sep("\\s*;\\s*"); 03062 03063 QPtrList<KateHighlighting> highlights; 03064 03065 for (KateHighlighting *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) { 03066 highlight->loadWildcards(); 03067 03068 for (QStringList::Iterator it = highlight->getPlainExtensions().begin(); it != highlight->getPlainExtensions().end(); ++it) 03069 if (fileName.endsWith((*it))) 03070 highlights.append(highlight); 03071 03072 for (int i = 0; i < (int)highlight->getRegexpExtensions().count(); i++) { 03073 QRegExp re = highlight->getRegexpExtensions()[i]; 03074 if (re.exactMatch(fileName)) 03075 highlights.append(highlight); 03076 } 03077 } 03078 03079 if ( !highlights.isEmpty() ) 03080 { 03081 int pri = -1; 03082 int hl = -1; 03083 03084 for (KateHighlighting *highlight = highlights.first(); highlight != 0L; highlight = highlights.next()) 03085 { 03086 if (highlight->priority() > pri) 03087 { 03088 pri = highlight->priority(); 03089 hl = hlList.findRef (highlight); 03090 } 03091 } 03092 return hl; 03093 } 03094 03095 return -1; 03096 } 03097 03098 int KateHlManager::mimeFind( KateDocument *doc ) 03099 { 03100 static QRegExp sep("\\s*;\\s*"); 03101 03102 KMimeType::Ptr mt = doc->mimeTypeForContent(); 03103 03104 QPtrList<KateHighlighting> highlights; 03105 03106 for (KateHighlighting *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) 03107 { 03108 QStringList l = QStringList::split( sep, highlight->getMimetypes() ); 03109 03110 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) 03111 { 03112 if ( *it == mt->name() ) // faster than a regexp i guess? 03113 highlights.append (highlight); 03114 } 03115 } 03116 03117 if ( !highlights.isEmpty() ) 03118 { 03119 int pri = -1; 03120 int hl = -1; 03121 03122 for (KateHighlighting *highlight = highlights.first(); highlight != 0L; highlight = highlights.next()) 03123 { 03124 if (highlight->priority() > pri) 03125 { 03126 pri = highlight->priority(); 03127 hl = hlList.findRef (highlight); 03128 } 03129 } 03130 03131 return hl; 03132 } 03133 03134 return -1; 03135 } 03136 03137 uint KateHlManager::defaultStyles() 03138 { 03139 return 14; 03140 } 03141 03142 QString KateHlManager::defaultStyleName(int n, bool translateNames) 03143 { 03144 static QStringList names; 03145 static QStringList translatedNames; 03146 03147 if (names.isEmpty()) 03148 { 03149 names << "Normal"; 03150 names << "Keyword"; 03151 names << "Data Type"; 03152 names << "Decimal/Value"; 03153 names << "Base-N Integer"; 03154 names << "Floating Point"; 03155 names << "Character"; 03156 names << "String"; 03157 names << "Comment"; 03158 names << "Others"; 03159 names << "Alert"; 03160 names << "Function"; 03161 // this next one is for denoting the beginning/end of a user defined folding region 03162 names << "Region Marker"; 03163 // this one is for marking invalid input 03164 names << "Error"; 03165 03166 translatedNames << i18n("Normal"); 03167 translatedNames << i18n("Keyword"); 03168 translatedNames << i18n("Data Type"); 03169 translatedNames << i18n("Decimal/Value"); 03170 translatedNames << i18n("Base-N Integer"); 03171 translatedNames << i18n("Floating Point"); 03172 translatedNames << i18n("Character"); 03173 translatedNames << i18n("String"); 03174 translatedNames << i18n("Comment"); 03175 translatedNames << i18n("Others"); 03176 translatedNames << i18n("Alert"); 03177 translatedNames << i18n("Function"); 03178 // this next one is for denoting the beginning/end of a user defined folding region 03179 translatedNames << i18n("Region Marker"); 03180 // this one is for marking invalid input 03181 translatedNames << i18n("Error"); 03182 } 03183 03184 return translateNames ? translatedNames[n] : names[n]; 03185 } 03186 03187 void KateHlManager::getDefaults(uint schema, KateAttributeList &list) 03188 { 03189 list.setAutoDelete(true); 03190 03191 KateAttribute* normal = new KateAttribute(); 03192 normal->setTextColor(Qt::black); 03193 normal->setSelectedTextColor(Qt::white); 03194 list.append(normal); 03195 03196 KateAttribute* keyword = new KateAttribute(); 03197 keyword->setTextColor(Qt::black); 03198 keyword->setSelectedTextColor(Qt::white); 03199 keyword->setBold(true); 03200 list.append(keyword); 03201 03202 KateAttribute* dataType = new KateAttribute(); 03203 dataType->setTextColor(Qt::darkRed); 03204 dataType->setSelectedTextColor(Qt::white); 03205 list.append(dataType); 03206 03207 KateAttribute* decimal = new KateAttribute(); 03208 decimal->setTextColor(Qt::blue); 03209 decimal->setSelectedTextColor(Qt::cyan); 03210 list.append(decimal); 03211 03212 KateAttribute* basen = new KateAttribute(); 03213 basen->setTextColor(Qt::darkCyan); 03214 basen->setSelectedTextColor(Qt::cyan); 03215 list.append(basen); 03216 03217 KateAttribute* floatAttribute = new KateAttribute(); 03218 floatAttribute->setTextColor(Qt::darkMagenta); 03219 floatAttribute->setSelectedTextColor(Qt::cyan); 03220 list.append(floatAttribute); 03221 03222 KateAttribute* charAttribute = new KateAttribute(); 03223 charAttribute->setTextColor(Qt::magenta); 03224 charAttribute->setSelectedTextColor(Qt::magenta); 03225 list.append(charAttribute); 03226 03227 KateAttribute* string = new KateAttribute(); 03228 string->setTextColor(QColor("#D00")); 03229 string->setSelectedTextColor(Qt::red); 03230 list.append(string); 03231 03232 KateAttribute* comment = new KateAttribute(); 03233 comment->setTextColor(Qt::darkGray); 03234 comment->setSelectedTextColor(Qt::gray); 03235 comment->setItalic(true); 03236 list.append(comment); 03237 03238 KateAttribute* others = new KateAttribute(); 03239 others->setTextColor(Qt::darkGreen); 03240 others->setSelectedTextColor(Qt::green); 03241 list.append(others); 03242 03243 KateAttribute* alert = new KateAttribute(); 03244 alert->setTextColor(Qt::black); 03245 alert->setSelectedTextColor( QColor("#FCC") ); 03246 alert->setBold(true); 03247 alert->setBGColor( QColor("#FCC") ); 03248 list.append(alert); 03249 03250 KateAttribute* functionAttribute = new KateAttribute(); 03251 functionAttribute->setTextColor(Qt::darkBlue); 03252 functionAttribute->setSelectedTextColor(Qt::white); 03253 list.append(functionAttribute); 03254 03255 KateAttribute* regionmarker = new KateAttribute(); 03256 regionmarker->setTextColor(Qt::white); 03257 regionmarker->setBGColor(Qt::gray); 03258 regionmarker->setSelectedTextColor(Qt::gray); 03259 list.append(regionmarker); 03260 03261 KateAttribute* error = new KateAttribute(); 03262 error->setTextColor(Qt::red); 03263 error->setUnderline(true); 03264 error->setSelectedTextColor(Qt::red); 03265 list.append(error); 03266 03267 KConfig *config = KateHlManager::self()->self()->getKConfig(); 03268 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema)); 03269 03270 for (uint z = 0; z < defaultStyles(); z++) 03271 { 03272 KateAttribute *i = list.at(z); 03273 QStringList s = config->readListEntry(defaultStyleName(z)); 03274 if (!s.isEmpty()) 03275 { 03276 while( s.count()<8) 03277 s << ""; 03278 03279 QString tmp; 03280 QRgb col; 03281 03282 tmp=s[0]; if (!tmp.isEmpty()) { 03283 col=tmp.toUInt(0,16); i->setTextColor(col); } 03284 03285 tmp=s[1]; if (!tmp.isEmpty()) { 03286 col=tmp.toUInt(0,16); i->setSelectedTextColor(col); } 03287 03288 tmp=s[2]; if (!tmp.isEmpty()) i->setBold(tmp!="0"); 03289 03290 tmp=s[3]; if (!tmp.isEmpty()) i->setItalic(tmp!="0"); 03291 03292 tmp=s[4]; if (!tmp.isEmpty()) i->setStrikeOut(tmp!="0"); 03293 03294 tmp=s[5]; if (!tmp.isEmpty()) i->setUnderline(tmp!="0"); 03295 03296 tmp=s[6]; if (!tmp.isEmpty()) { 03297 if ( tmp != "-" ) 03298 { 03299 col=tmp.toUInt(0,16); 03300 i->setBGColor(col); 03301 } 03302 else 03303 i->clearAttribute(KateAttribute::BGColor); 03304 } 03305 tmp=s[7]; if (!tmp.isEmpty()) { 03306 if ( tmp != "-" ) 03307 { 03308 col=tmp.toUInt(0,16); 03309 i->setSelectedBGColor(col); 03310 } 03311 else 03312 i->clearAttribute(KateAttribute::SelectedBGColor); 03313 } 03314 } 03315 } 03316 } 03317 03318 void KateHlManager::setDefaults(uint schema, KateAttributeList &list) 03319 { 03320 KConfig *config = KateHlManager::self()->self()->getKConfig(); 03321 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema)); 03322 03323 for (uint z = 0; z < defaultStyles(); z++) 03324 { 03325 QStringList settings; 03326 KateAttribute *i = list.at(z); 03327 03328 settings<<(i->itemSet(KateAttribute::TextColor)?QString::number(i->textColor().rgb(),16):""); 03329 settings<<(i->itemSet(KateAttribute::SelectedTextColor)?QString::number(i->selectedTextColor().rgb(),16):""); 03330 settings<<(i->itemSet(KateAttribute::Weight)?(i->bold()?"1":"0"):""); 03331 settings<<(i->itemSet(KateAttribute::Italic)?(i->italic()?"1":"0"):""); 03332 settings<<(i->itemSet(KateAttribute::StrikeOut)?(i->strikeOut()?"1":"0"):""); 03333 settings<<(i->itemSet(KateAttribute::Underline)?(i->underline()?"1":"0"):""); 03334 settings<<(i->itemSet(KateAttribute::BGColor)?QString::number(i->bgColor().rgb(),16):"-"); 03335 settings<<(i->itemSet(KateAttribute::SelectedBGColor)?QString::number(i->selectedBGColor().rgb(),16):"-"); 03336 settings<<"---"; 03337 03338 config->writeEntry(defaultStyleName(z),settings); 03339 } 03340 03341 emit changed(); 03342 } 03343 03344 int KateHlManager::highlights() 03345 { 03346 return (int) hlList.count(); 03347 } 03348 03349 QString KateHlManager::hlName(int n) 03350 { 03351 return hlList.at(n)->name(); 03352 } 03353 03354 QString KateHlManager::hlNameTranslated(int n) 03355 { 03356 return hlList.at(n)->nameTranslated(); 03357 } 03358 03359 QString KateHlManager::hlSection(int n) 03360 { 03361 return hlList.at(n)->section(); 03362 } 03363 03364 bool KateHlManager::hlHidden(int n) 03365 { 03366 return hlList.at(n)->hidden(); 03367 } 03368 03369 QString KateHlManager::identifierForName(const QString& name) 03370 { 03371 KateHighlighting *hl = 0; 03372 03373 if ((hl = hlDict[name])) 03374 return hl->getIdentifier (); 03375 03376 return QString(); 03377 } 03378 03379 bool KateHlManager::resetDynamicCtxs() 03380 { 03381 if (forceNoDCReset) 03382 return false; 03383 03384 if (lastCtxsReset.elapsed() < KATE_DYNAMIC_CONTEXTS_RESET_DELAY) 03385 return false; 03386 03387 KateHighlighting *hl; 03388 for (hl = hlList.first(); hl; hl = hlList.next()) 03389 hl->dropDynamicContexts(); 03390 03391 dynamicCtxsCount = 0; 03392 lastCtxsReset.start(); 03393 03394 return true; 03395 } 03396 //END 03397 03398 //BEGIN KateHighlightAction 03399 void KateViewHighlightAction::init() 03400 { 03401 m_doc = 0; 03402 subMenus.setAutoDelete( true ); 03403 03404 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow())); 03405 } 03406 03407 void KateViewHighlightAction::updateMenu (Kate::Document *doc) 03408 { 03409 m_doc = doc; 03410 } 03411 03412 void KateViewHighlightAction::slotAboutToShow() 03413 { 03414 Kate::Document *doc=m_doc; 03415 int count = KateHlManager::self()->highlights(); 03416 03417 for (int z=0; z<count; z++) 03418 { 03419 QString hlName = KateHlManager::self()->hlNameTranslated (z); 03420 QString hlSection = KateHlManager::self()->hlSection (z); 03421 03422 if (!KateHlManager::self()->hlHidden(z)) 03423 { 03424 if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) ) 03425 { 03426 if (subMenusName.contains(hlSection) < 1) 03427 { 03428 subMenusName << hlSection; 03429 QPopupMenu *menu = new QPopupMenu (); 03430 subMenus.append(menu); 03431 popupMenu()->insertItem ( '&' + hlSection, menu); 03432 } 03433 03434 int m = subMenusName.findIndex (hlSection); 03435 names << hlName; 03436 subMenus.at(m)->insertItem ( '&' + hlName, this, SLOT(setHl(int)), 0, z); 03437 } 03438 else if (names.contains(hlName) < 1) 03439 { 03440 names << hlName; 03441 popupMenu()->insertItem ( '&' + hlName, this, SLOT(setHl(int)), 0, z); 03442 } 03443 } 03444 } 03445 03446 if (!doc) return; 03447 03448 for (uint i=0;i<subMenus.count();i++) 03449 { 03450 for (uint i2=0;i2<subMenus.at(i)->count();i2++) 03451 { 03452 subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false); 03453 } 03454 } 03455 popupMenu()->setItemChecked (0, false); 03456 03457 int i = subMenusName.findIndex (KateHlManager::self()->hlSection(doc->hlMode())); 03458 if (i >= 0 && subMenus.at(i)) 03459 subMenus.at(i)->setItemChecked (doc->hlMode(), true); 03460 else 03461 popupMenu()->setItemChecked (0, true); 03462 } 03463 03464 void KateViewHighlightAction::setHl (int mode) 03465 { 03466 Kate::Document *doc=m_doc; 03467 03468 if (doc) 03469 doc->setHlMode((uint)mode); 03470 } 03471 //END KateViewHighlightAction 03472 03473 // kate: space-indent on; indent-width 2; replace-tabs on;