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