kate Library API Documentation

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