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