kate Library API Documentation

katehighlight.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2003 Hamish Rodda <rodda@kde.org> 00003 Copyright (C) 2001,2002 Joseph Wenninger <jowenn@kde.org> 00004 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 00005 Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License version 2 as published by the Free Software Foundation. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 00020 */ 00021 00022 //BEGIN INCLUDES 00023 #include "katehighlight.h" 00024 #include "katehighlight.moc" 00025 00026 #include "katetextline.h" 00027 #include "katedocument.h" 00028 #include "katesyntaxdocument.h" 00029 #include "katerenderer.h" 00030 #include "katefactory.h" 00031 #include "kateschema.h" 00032 #include "kateconfig.h" 00033 00034 #include <kconfig.h> 00035 #include <kglobal.h> 00036 #include <kinstance.h> 00037 #include <kmimetype.h> 00038 #include <klocale.h> 00039 #include <kregexp.h> 00040 #include <kpopupmenu.h> 00041 #include <kglobalsettings.h> 00042 #include <kdebug.h> 00043 #include <kstandarddirs.h> 00044 #include <kmessagebox.h> 00045 #include <kstaticdeleter.h> 00046 #include <kapplication.h> 00047 00048 #include <qstringlist.h> 00049 #include <qtextstream.h> 00050 //END 00051 00052 // same as in kmimemagic, no need to feed more data 00053 #define KATE_HL_HOWMANY 1024 00054 00055 //BEGIN Prviate HL classes 00056 00057 class HlItem 00058 { 00059 public: 00060 HlItem(int attribute, int context,signed char regionId, signed char regionId2); 00061 virtual ~HlItem(); 00062 00063 public: 00064 virtual bool alwaysStartEnable() const { return true; }; 00065 virtual bool hasCustomStartEnable() const { return false; }; 00066 virtual bool startEnable(const QChar&); 00067 00068 // Changed from using QChar*, because it makes the regular expression check very 00069 // inefficient (forces it to copy the string, very bad for long strings) 00070 // Now, the function returns the offset detected, or 0 if no match is found. 00071 // bool linestart isn't needed, this is equivalent to offset == 0. 00072 virtual int checkHgl(const QString& text, int offset, int len) = 0; 00073 00074 virtual bool lineContinue(){return false;} 00075 00076 QPtrList<HlItem> *subItems; 00077 int attr; 00078 int ctx; 00079 signed char region; 00080 signed char region2; 00081 }; 00082 00083 class HlContext 00084 { 00085 public: 00086 HlContext (int attribute, int lineEndContext,int _lineBeginContext, 00087 bool _fallthrough, int _fallthroughContext); 00088 00089 QPtrList<HlItem> items; 00090 int attr; 00091 int ctx; 00092 int lineBeginContext; 00098 bool fallthrough; 00099 int ftctx; // where to go after no rules matched 00100 }; 00101 00102 class EmbeddedHlInfo 00103 { 00104 public: 00105 EmbeddedHlInfo() {loaded=false;context0=-1;} 00106 EmbeddedHlInfo(bool l, int ctx0) {loaded=l;context0=ctx0;} 00107 00108 public: 00109 bool loaded; 00110 int context0; 00111 }; 00112 00113 class IncludeRule 00114 { 00115 public: 00116 IncludeRule(int ctx_, uint pos_, const QString &incCtxN_) {ctx=ctx_;pos=pos_;incCtxN=incCtxN_;incCtx=-1;} 00117 IncludeRule(int ctx_, uint pos_) {ctx=ctx_;pos=pos_;incCtx=-1;incCtxN="";} 00118 00119 public: 00120 uint pos; 00121 int ctx; 00122 int incCtx; 00123 QString incCtxN; 00124 }; 00125 00126 class HlCharDetect : public HlItem 00127 { 00128 public: 00129 HlCharDetect(int attribute, int context,signed char regionId,signed char regionId2, QChar); 00130 virtual int checkHgl(const QString& text, int offset, int len); 00131 00132 private: 00133 QChar sChar; 00134 }; 00135 00136 class Hl2CharDetect : public HlItem 00137 { 00138 public: 00139 Hl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2); 00140 Hl2CharDetect(int attribute, int context,signed char regionId,signed char regionId2, const QChar *ch); 00141 00142 virtual int checkHgl(const QString& text, int offset, int len); 00143 00144 private: 00145 QChar sChar1; 00146 QChar sChar2; 00147 }; 00148 00149 class HlStringDetect : public HlItem 00150 { 00151 public: 00152 HlStringDetect(int attribute, int context, signed char regionId,signed char regionId2, const QString &, bool inSensitive=false); 00153 00154 virtual ~HlStringDetect(); 00155 virtual int checkHgl(const QString& text, int offset, int len); 00156 00157 private: 00158 const QString str; 00159 bool _inSensitive; 00160 }; 00161 00162 class HlRangeDetect : public HlItem 00163 { 00164 public: 00165 HlRangeDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2); 00166 00167 virtual int checkHgl(const QString& text, int offset, int len); 00168 00169 private: 00170 QChar sChar1; 00171 QChar sChar2; 00172 }; 00173 00174 class HlKeyword : public HlItem 00175 { 00176 public: 00177 HlKeyword(int attribute, int context,signed char regionId,signed char regionId2, bool casesensitive, const QString& delims); 00178 virtual ~HlKeyword(); 00179 00180 virtual void addWord(const QString &); 00181 virtual void addList(const QStringList &); 00182 virtual int checkHgl(const QString& text, int offset, int len); 00183 virtual bool startEnable(const QChar& c); 00184 virtual bool alwaysStartEnable() const; 00185 virtual bool hasCustomStartEnable() const; 00186 00187 private: 00188 QDict<bool> dict; 00189 bool _caseSensitive; 00190 const QString& deliminators; 00191 }; 00192 00193 class HlInt : public HlItem 00194 { 00195 public: 00196 HlInt(int attribute, int context, signed char regionId,signed char regionId2); 00197 00198 virtual int checkHgl(const QString& text, int offset, int len); 00199 virtual bool alwaysStartEnable() const; 00200 }; 00201 00202 class HlFloat : public HlItem 00203 { 00204 public: 00205 HlFloat(int attribute, int context, signed char regionId,signed char regionId2); 00206 00207 virtual int checkHgl(const QString& text, int offset, int len); 00208 virtual bool alwaysStartEnable() const; 00209 }; 00210 00211 class HlCOct : public HlItem 00212 { 00213 public: 00214 HlCOct(int attribute, int context, signed char regionId,signed char regionId2); 00215 00216 virtual int checkHgl(const QString& text, int offset, int len); 00217 virtual bool alwaysStartEnable() const; 00218 }; 00219 00220 class HlCHex : public HlItem 00221 { 00222 public: 00223 HlCHex(int attribute, int context, signed char regionId,signed char regionId2); 00224 00225 virtual int checkHgl(const QString& text, int offset, int len); 00226 virtual bool alwaysStartEnable() const; 00227 }; 00228 00229 class HlCFloat : public HlFloat 00230 { 00231 public: 00232 HlCFloat(int attribute, int context, signed char regionId,signed char regionId2); 00233 00234 virtual int checkHgl(const QString& text, int offset, int len); 00235 int checkIntHgl(const QString& text, int offset, int len); 00236 virtual bool alwaysStartEnable() const; 00237 }; 00238 00239 class HlLineContinue : public HlItem 00240 { 00241 public: 00242 HlLineContinue(int attribute, int context, signed char regionId,signed char regionId2); 00243 00244 virtual bool endEnable(QChar c) {return c == '\0';} 00245 virtual int checkHgl(const QString& text, int offset, int len); 00246 virtual bool lineContinue(){return true;} 00247 }; 00248 00249 class HlCStringChar : public HlItem 00250 { 00251 public: 00252 HlCStringChar(int attribute, int context, signed char regionId,signed char regionId2); 00253 00254 virtual int checkHgl(const QString& text, int offset, int len); 00255 }; 00256 00257 class HlCChar : public HlItem 00258 { 00259 public: 00260 HlCChar(int attribute, int context,signed char regionId,signed char regionId2); 00261 00262 virtual int checkHgl(const QString& text, int offset, int len); 00263 }; 00264 00265 class HlAnyChar : public HlItem 00266 { 00267 public: 00268 HlAnyChar(int attribute, int context, signed char regionId,signed char regionId2, const QString& charList); 00269 00270 virtual int checkHgl(const QString& text, int offset, int len); 00271 00272 private: 00273 const QString _charList; 00274 }; 00275 00276 class HlRegExpr : public HlItem 00277 { 00278 public: 00279 HlRegExpr(int attribute, int context,signed char regionId,signed char regionId2 ,QString expr, bool insensitive, bool minimal); 00280 ~HlRegExpr(){delete Expr;}; 00281 00282 virtual int checkHgl(const QString& text, int offset, int len); 00283 00284 private: 00285 QRegExp *Expr; 00286 bool handlesLinestart; 00287 }; 00288 00289 //END 00290 00291 //BEGIN STATICS 00292 HlManager *HlManager::s_self = 0; 00293 00294 enum Item_styles { dsNormal,dsKeyword,dsDataType,dsDecVal,dsBaseN,dsFloat,dsChar,dsString,dsComment,dsOthers}; 00295 00296 static const bool trueBool = true; 00297 static const QString stdDeliminator = QString (" \t.():!+,-<=>%&*/;?[]^{|}~\\"); 00298 //END 00299 00300 //BEGIN NON MEMBER FUNCTIONS 00301 static int getDefStyleNum(QString name) 00302 { 00303 if (name=="dsNormal") return dsNormal; 00304 else if (name=="dsKeyword") return dsKeyword; 00305 else if (name=="dsDataType") return dsDataType; 00306 else if (name=="dsDecVal") return dsDecVal; 00307 else if (name=="dsBaseN") return dsBaseN; 00308 else if (name=="dsFloat") return dsFloat; 00309 else if (name=="dsChar") return dsChar; 00310 else if (name=="dsString") return dsString; 00311 else if (name=="dsComment") return dsComment; 00312 else if (name=="dsOthers") return dsOthers; 00313 00314 return dsNormal; 00315 } 00316 //END 00317 00318 //BEGIN HlItem 00319 HlItem::HlItem(int attribute, int context,signed char regionId,signed char regionId2) 00320 : attr(attribute), ctx(context),region(regionId),region2(regionId2) {subItems=0; 00321 } 00322 00323 HlItem::~HlItem() 00324 { 00325 //kdDebug(13010)<<"In hlItem::~HlItem()"<<endl; 00326 if (subItems!=0) 00327 { 00328 subItems->setAutoDelete(true); 00329 subItems->clear(); 00330 delete subItems; 00331 } 00332 } 00333 00334 bool HlItem::startEnable(const QChar& c) 00335 { 00336 // ONLY called when alwaysStartEnable() overridden 00337 // IN FACT not called at all, copied into doHighlight()... 00338 Q_ASSERT(false); 00339 return stdDeliminator.find(c) != -1; 00340 } 00341 //END 00342 00343 //BEGIN HLCharDetect 00344 HlCharDetect::HlCharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar c) 00345 : HlItem(attribute,context,regionId,regionId2), sChar(c) 00346 { 00347 } 00348 00349 int HlCharDetect::checkHgl(const QString& text, int offset, int len) 00350 { 00351 if (len && text[offset] == sChar) 00352 return offset + 1; 00353 00354 return 0; 00355 } 00356 //END 00357 00358 //BEGIN Hl2CharDetect 00359 Hl2CharDetect::Hl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2) 00360 : HlItem(attribute,context,regionId,regionId2) 00361 { 00362 sChar1 = ch1; 00363 sChar2 = ch2; 00364 } 00365 00366 int Hl2CharDetect::checkHgl(const QString& text, int offset, int len) 00367 { 00368 if (len < 2) 00369 return offset; 00370 00371 if (text[offset++] == sChar1 && text[offset++] == sChar2) 00372 return offset; 00373 00374 return 0; 00375 } 00376 //END 00377 00378 //BEGIN HlStringDetect 00379 HlStringDetect::HlStringDetect(int attribute, int context, signed char regionId,signed char regionId2,const QString &s, bool inSensitive) 00380 : HlItem(attribute, context,regionId,regionId2), str(inSensitive ? s.upper():s), _inSensitive(inSensitive) { 00381 } 00382 00383 HlStringDetect::~HlStringDetect() { 00384 } 00385 00386 int HlStringDetect::checkHgl(const QString& text, int offset, int len) 00387 { 00388 if (len < (int)str.length()) 00389 return 0; 00390 00391 if (QConstString(text.unicode() + offset, str.length()).string().find(str, 0, !_inSensitive) == 0) 00392 return offset + str.length(); 00393 00394 return 0; 00395 } 00396 00397 //END 00398 00399 //BEGIN HLRangeDetect 00400 HlRangeDetect::HlRangeDetect(int attribute, int context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2) 00401 : HlItem(attribute,context,regionId,regionId2) { 00402 sChar1 = ch1; 00403 sChar2 = ch2; 00404 } 00405 00406 int HlRangeDetect::checkHgl(const QString& text, int offset, int len) 00407 { 00408 if ((len > 0) && (text[offset] == sChar1)) 00409 { 00410 do 00411 { 00412 offset++; 00413 len--; 00414 if (len < 1) return 0; 00415 } 00416 while (text[offset] != sChar2); 00417 00418 return offset + 1; 00419 } 00420 return 0; 00421 } 00422 //END 00423 00424 //BEGIN HlKeyword 00425 HlKeyword::HlKeyword (int attribute, int context, signed char regionId,signed char regionId2, bool casesensitive, const QString& delims) 00426 : HlItem(attribute,context,regionId,regionId2) 00427 , dict (113, casesensitive) 00428 , _caseSensitive(casesensitive) 00429 , deliminators(delims) 00430 { 00431 } 00432 00433 HlKeyword::~HlKeyword() { 00434 } 00435 00436 bool HlKeyword::alwaysStartEnable() const 00437 { 00438 return false; 00439 } 00440 00441 bool HlKeyword::hasCustomStartEnable() const 00442 { 00443 return true; 00444 } 00445 00446 bool HlKeyword::startEnable(const QChar& c) 00447 { 00448 return deliminators.find(c) != -1; 00449 } 00450 00451 // If we use a dictionary for lookup we don't really need 00452 // an item as such we are using the key to lookup 00453 void HlKeyword::addWord(const QString &word) 00454 { 00455 dict.insert(word,&trueBool); 00456 } 00457 00458 void HlKeyword::addList(const QStringList& list) 00459 { 00460 for(uint i=0;i<list.count();i++) dict.insert(list[i], &trueBool); 00461 } 00462 00463 int HlKeyword::checkHgl(const QString& text, int offset, int len) 00464 { 00465 if (len == 0 || dict.isEmpty()) return 0; 00466 00467 int offset2 = offset; 00468 00469 while (len > 0 && deliminators.find(text[offset2]) == -1 ) 00470 { 00471 offset2++; 00472 len--; 00473 } 00474 00475 if (offset2 == offset) return 0; 00476 00477 if ( dict.find(text.mid(offset, offset2 - offset)) ) return offset2; 00478 00479 return 0; 00480 } 00481 //END 00482 00483 //BEGIN HlInt 00484 HlInt::HlInt(int attribute, int context, signed char regionId,signed char regionId2) 00485 : HlItem(attribute,context,regionId,regionId2) 00486 { 00487 } 00488 00489 bool HlInt::alwaysStartEnable() const 00490 { 00491 return false; 00492 } 00493 00494 int HlInt::checkHgl(const QString& text, int offset, int len) 00495 { 00496 int offset2 = offset; 00497 00498 while ((len > 0) && text[offset2].isDigit()) 00499 { 00500 offset2++; 00501 len--; 00502 } 00503 00504 if (offset2 > offset) 00505 { 00506 if (subItems) 00507 { 00508 for (HlItem *it = subItems->first(); it; it = subItems->next()) 00509 { 00510 if ( (offset = it->checkHgl(text, offset2, len)) ) 00511 return offset; 00512 } 00513 } 00514 00515 return offset2; 00516 } 00517 00518 return 0; 00519 } 00520 //END 00521 00522 //BEGIN HlFloat 00523 HlFloat::HlFloat(int attribute, int context, signed char regionId,signed char regionId2) 00524 : HlItem(attribute,context, regionId,regionId2) { 00525 } 00526 00527 bool HlFloat::alwaysStartEnable() const 00528 { 00529 return false; 00530 } 00531 00532 int HlFloat::checkHgl(const QString& text, int offset, int len) 00533 { 00534 bool b = false; 00535 bool p = false; 00536 00537 while ((len > 0) && text[offset].isDigit()) 00538 { 00539 offset++; 00540 len--; 00541 b = true; 00542 } 00543 00544 if ((len > 0) && (p = (text[offset] == '.'))) 00545 { 00546 offset++; 00547 len--; 00548 00549 while ((len > 0) && text[offset].isDigit()) 00550 { 00551 offset++; 00552 len--; 00553 b = true; 00554 } 00555 } 00556 00557 if (!b) 00558 return 0; 00559 00560 if ((len > 0) && ((text[offset] & 0xdf) == 'E')) 00561 { 00562 offset++; 00563 len--; 00564 } 00565 else 00566 { 00567 if (!p) 00568 return 0; 00569 else 00570 { 00571 if (subItems) 00572 { 00573 for (HlItem *it = subItems->first(); it; it = subItems->next()) 00574 { 00575 int offset2 = it->checkHgl(text, offset, len); 00576 00577 if (offset2) 00578 return offset2; 00579 } 00580 } 00581 00582 return offset; 00583 } 00584 } 00585 00586 if ((len > 0) && (text[offset] == '-' || text[offset] =='+')) 00587 { 00588 offset++; 00589 len--; 00590 } 00591 00592 b = false; 00593 00594 while ((len > 0) && text[offset].isDigit()) 00595 { 00596 offset++; 00597 len--; 00598 b = true; 00599 } 00600 00601 if (b) 00602 { 00603 if (subItems) 00604 { 00605 for (HlItem *it = subItems->first(); it; it = subItems->next()) 00606 { 00607 int offset2 = it->checkHgl(text, offset, len); 00608 00609 if (offset2) 00610 return offset2; 00611 } 00612 } 00613 00614 return offset; 00615 } 00616 00617 return 0; 00618 } 00619 //END 00620 00621 //BEGIN HlCOct 00622 HlCOct::HlCOct(int attribute, int context, signed char regionId,signed char regionId2) 00623 : HlItem(attribute,context,regionId,regionId2) { 00624 } 00625 00626 bool HlCOct::alwaysStartEnable() const 00627 { 00628 return false; 00629 } 00630 00631 int HlCOct::checkHgl(const QString& text, int offset, int len) 00632 { 00633 if ((len > 0) && text[offset] == '0') 00634 { 00635 offset++; 00636 len--; 00637 00638 int offset2 = offset; 00639 00640 while ((len > 0) && (text[offset2] >= '0' && text[offset2] <= '7')) 00641 { 00642 offset2++; 00643 len--; 00644 } 00645 00646 if (offset2 > offset) 00647 { 00648 if ((len > 0) && ((text[offset2] & 0xdf) == 'L' || (text[offset] & 0xdf) == 'U' )) 00649 offset2++; 00650 00651 return offset2; 00652 } 00653 } 00654 00655 return 0; 00656 } 00657 //END 00658 00659 //BEGIN HlCHex 00660 HlCHex::HlCHex(int attribute, int context,signed char regionId,signed char regionId2) 00661 : HlItem(attribute,context,regionId,regionId2) { 00662 } 00663 00664 bool HlCHex::alwaysStartEnable() const 00665 { 00666 return false; 00667 } 00668 00669 int HlCHex::checkHgl(const QString& text, int offset, int len) 00670 { 00671 if ((len > 1) && (text[offset++] == '0') && ((text[offset++] & 0xdf) == 'X' )) 00672 { 00673 len -= 2; 00674 00675 int offset2 = offset; 00676 00677 while ((len > 0) && (text[offset2].isDigit() || ((text[offset2] & 0xdf) >= 'A' && (text[offset2] & 0xdf) <= 'F'))) 00678 { 00679 offset2++; 00680 len--; 00681 } 00682 00683 if (offset2 > offset) 00684 { 00685 if ((len > 0) && ((text[offset2] & 0xdf) == 'L' || (text[offset2] & 0xdf) == 'U' )) 00686 offset2++; 00687 00688 return offset2; 00689 } 00690 } 00691 00692 return 0; 00693 } 00694 //END 00695 00696 //BEGIN HlCFloat 00697 HlCFloat::HlCFloat(int attribute, int context, signed char regionId,signed char regionId2) 00698 : HlFloat(attribute,context,regionId,regionId2) { 00699 } 00700 00701 bool HlCFloat::alwaysStartEnable() const 00702 { 00703 return false; 00704 } 00705 00706 int HlCFloat::checkIntHgl(const QString& text, int offset, int len) 00707 { 00708 int offset2 = offset; 00709 00710 while ((len > 0) && text[offset].isDigit()) { 00711 offset2++; 00712 len--; 00713 } 00714 00715 if (offset2 > offset) 00716 return offset2; 00717 00718 return 0; 00719 } 00720 00721 int HlCFloat::checkHgl(const QString& text, int offset, int len) 00722 { 00723 int offset2 = HlFloat::checkHgl(text, offset, len); 00724 00725 if (offset2) 00726 { 00727 if ((text[offset2] & 0xdf) == 'F' ) 00728 offset2++; 00729 00730 return offset2; 00731 } 00732 else 00733 { 00734 offset2 = checkIntHgl(text, offset, len); 00735 00736 if (offset2 && ((text[offset2] & 0xdf) == 'F' )) 00737 return ++offset2; 00738 else 00739 return 0; 00740 } 00741 } 00742 //END 00743 00744 //BEGIN HlAnyChar 00745 HlAnyChar::HlAnyChar(int attribute, int context, signed char regionId,signed char regionId2, const QString& charList) 00746 : HlItem(attribute, context,regionId,regionId2) 00747 , _charList(charList) 00748 { 00749 } 00750 00751 int HlAnyChar::checkHgl(const QString& text, int offset, int len) 00752 { 00753 if ((len > 0) && _charList.find(text[offset]) != -1) 00754 return ++offset; 00755 00756 return 0; 00757 } 00758 //END 00759 00760 //BEGIN HlRegExpr 00761 HlRegExpr::HlRegExpr( int attribute, int context, signed char regionId,signed char regionId2, QString regexp, bool insensitive, bool minimal ) 00762 : HlItem(attribute, context, regionId,regionId2) 00763 { 00764 handlesLinestart=regexp.startsWith("^"); 00765 if(!handlesLinestart) regexp.prepend("^"); 00766 Expr=new QRegExp(regexp, !insensitive); 00767 Expr->setMinimal(minimal); 00768 } 00769 00770 int HlRegExpr::checkHgl(const QString& text, int offset, int /*len*/) 00771 { 00772 if (offset && handlesLinestart) 00773 return 0; 00774 00775 int offset2 = Expr->search( text, offset, QRegExp::CaretAtOffset ); 00776 00777 if (offset2 == -1) return 0; 00778 00779 return (offset + Expr->matchedLength()); 00780 } 00781 //END 00782 00783 //BEGIN HlLineContinue 00784 HlLineContinue::HlLineContinue(int attribute, int context, signed char regionId,signed char regionId2) 00785 : HlItem(attribute,context,regionId,regionId2) { 00786 } 00787 00788 int HlLineContinue::checkHgl(const QString& text, int offset, int len) 00789 { 00790 if ((len == 1) && (text[offset] == '\\')) 00791 return ++offset; 00792 00793 return 0; 00794 } 00795 //END 00796 00797 //BEGIN HlCStringChar 00798 HlCStringChar::HlCStringChar(int attribute, int context,signed char regionId,signed char regionId2) 00799 : HlItem(attribute,context,regionId,regionId2) { 00800 } 00801 00802 // checks for C escaped chars \n and escaped hex/octal chars 00803 static int checkEscapedChar(const QString& text, int offset, int& len) 00804 { 00805 int i; 00806 if (text[offset] == '\\' && len > 1) 00807 { 00808 offset++; 00809 len--; 00810 00811 switch(text[offset]) 00812 { 00813 case 'a': // checks for control chars 00814 case 'b': // we want to fall through 00815 case 'e': 00816 case 'f': 00817 00818 case 'n': 00819 case 'r': 00820 case 't': 00821 case 'v': 00822 case '\'': 00823 case '\"': 00824 case '?' : // added ? ANSI C classifies this as an escaped char 00825 case '\\': 00826 offset++; 00827 len--; 00828 break; 00829 00830 case 'x': // if it's like \xff 00831 offset++; // eat the x 00832 len--; 00833 // these for loops can probably be 00834 // replaced with something else but 00835 // for right now they work 00836 // check for hexdigits 00837 for (i = 0; (len > 0) && (i < 2) && (text[offset] >= '0' && text[offset] <= '9' || (text[offset] & 0xdf) >= 'A' && (text[offset] & 0xdf) <= 'F'); i++) 00838 { 00839 offset++; 00840 len--; 00841 } 00842 00843 if (i == 0) 00844 return 0; // takes care of case '\x' 00845 00846 break; 00847 00848 case '0': case '1': case '2': case '3' : 00849 case '4': case '5': case '6': case '7' : 00850 for (i = 0; (len > 0) && (i < 3) && (text[offset] >='0'&& text[offset] <='7'); i++) 00851 { 00852 offset++; 00853 len--; 00854 } 00855 break; 00856 00857 default: 00858 return 0; 00859 } 00860 00861 return offset; 00862 } 00863 00864 return 0; 00865 } 00866 00867 int HlCStringChar::checkHgl(const QString& text, int offset, int len) 00868 { 00869 return checkEscapedChar(text, offset, len); 00870 } 00871 //END 00872 00873 //BEGIN HlCChar 00874 HlCChar::HlCChar(int attribute, int context,signed char regionId,signed char regionId2) 00875 : HlItem(attribute,context,regionId,regionId2) { 00876 } 00877 00878 int HlCChar::checkHgl(const QString& text, int offset, int len) 00879 { 00880 if ((len > 1) && (text[offset] == '\'') && (text[offset+1] != '\'')) 00881 { 00882 int oldl; 00883 oldl = len; 00884 00885 len--; 00886 00887 int offset2 = checkEscapedChar(text, offset + 1, len); 00888 00889 if (!offset2) 00890 { 00891 if (oldl > 2) 00892 { 00893 offset2 = offset + 2; 00894 len = oldl - 2; 00895 } 00896 else 00897 { 00898 return 0; 00899 } 00900 } 00901 00902 if ((len > 0) && (text[offset2] == '\'')) 00903 return ++offset2; 00904 } 00905 00906 return 0; 00907 } 00908 //END 00909 00910 ItemData::ItemData(const QString name, int defStyleNum) 00911 : name(name), defStyleNum(defStyleNum) { 00912 } 00913 00914 HlData::HlData(const QString &wildcards, const QString &mimetypes, const QString &identifier, int priority) 00915 : wildcards(wildcards), mimetypes(mimetypes), identifier(identifier), priority(priority) 00916 { 00917 } 00918 00919 HlContext::HlContext (int attribute, int lineEndContext, int _lineBeginContext, bool _fallthrough, int _fallthroughContext) 00920 { 00921 attr = attribute; 00922 ctx = lineEndContext; 00923 lineBeginContext = _lineBeginContext; 00924 fallthrough = _fallthrough; 00925 ftctx = _fallthroughContext; 00926 } 00927 00928 Hl2CharDetect::Hl2CharDetect(int attribute, int context, signed char regionId,signed char regionId2, const QChar *s) 00929 : HlItem(attribute,context,regionId,regionId2) { 00930 sChar1 = s[0]; 00931 sChar2 = s[1]; 00932 } 00933 00934 //BEGIN Highlight 00935 Highlight::Highlight(const syntaxModeListItem *def) : refCount(0) 00936 { 00937 m_attributeArrays.setAutoDelete (true); 00938 00939 errorsAndWarnings = ""; 00940 building=false; 00941 noHl = false; 00942 m_foldingIndentationSensitive = false; 00943 folding=false; 00944 internalIDList.setAutoDelete(true); 00945 00946 if (def == 0) 00947 { 00948 noHl = true; 00949 iName = i18n("None"); 00950 iSection = ""; 00951 m_priority = 0; 00952 } 00953 else 00954 { 00955 iName = def->name; 00956 iSection = def->section; 00957 iWildcards = def->extension; 00958 iMimetypes = def->mimetype; 00959 identifier = def->identifier; 00960 iVersion=def->version; 00961 m_priority=def->priority.toInt(); 00962 } 00963 00964 deliminator = stdDeliminator; 00965 } 00966 00967 Highlight::~Highlight() 00968 { 00969 contextList.setAutoDelete( true ); 00970 } 00971 00972 void Highlight::generateContextStack(int *ctxNum, int ctx, QMemArray<short>* ctxs, int *prevLine, bool lineContinue) 00973 { 00974 //kdDebug(13010)<<QString("Entering generateContextStack with %1").arg(ctx)<<endl; 00975 00976 if (lineContinue) 00977 { 00978 if ( !ctxs->isEmpty() ) 00979 { 00980 (*ctxNum)=(*ctxs)[ctxs->size()-1]; 00981 (*prevLine)--; 00982 } 00983 else 00984 { 00985 //kdDebug(13010)<<QString("generateContextStack: line continue: len ==0"); 00986 (*ctxNum)=0; 00987 } 00988 00989 return; 00990 } 00991 00992 if (ctx >= 0) 00993 { 00994 (*ctxNum) = ctx; 00995 00996 ctxs->resize (ctxs->size()+1); 00997 (*ctxs)[ctxs->size()-1]=(*ctxNum); 00998 } 00999 else 01000 { 01001 if (ctx < -1) 01002 { 01003 while (ctx < -1) 01004 { 01005 if ( ctxs->isEmpty() ) 01006 (*ctxNum)=0; 01007 else 01008 { 01009 ctxs->truncate (ctxs->size()-1); 01010 //kdDebug(13010)<<QString("generate context stack: truncated stack to :%1").arg(ctxs->size())<<endl; 01011 (*ctxNum) = ( (ctxs->isEmpty() ) ? 0 : (*ctxs)[ctxs->size()-1]); 01012 } 01013 01014 ctx++; 01015 } 01016 01017 ctx = 0; 01018 01019 if ((*prevLine) >= (int)(ctxs->size()-1)) 01020 { 01021 *prevLine=ctxs->size()-1; 01022 01023 if ( ctxs->isEmpty() ) 01024 return; 01025 01026 if (contextNum((*ctxs)[ctxs->size()-1]) && (contextNum((*ctxs)[ctxs->size()-1])->ctx != -1)) 01027 { 01028 //kdDebug(13010)<<"PrevLine > size()-1 and ctx!=-1)"<<endl; 01029 generateContextStack(ctxNum, contextNum((*ctxs)[ctxs->size()-1])->ctx,ctxs, prevLine); 01030 return; 01031 } 01032 } 01033 } 01034 else 01035 { 01036 if (ctx == -1) 01037 (*ctxNum)=( (ctxs->isEmpty() ) ? 0 : (*ctxs)[ctxs->size()-1]); 01038 } 01039 } 01040 } 01041 01042 /******************************************************************************************* 01043 Highlight - doHighlight 01044 Increase the usage count and trigger initialization if needed 01045 01046 * input: signed char *oCtx Pointer to the "stack" of the previous line 01047 uint *oCtxLen Size of the stack 01048 TextLine *textline Current textline to work on 01049 ************* 01050 * output: (TextLine *textline) 01051 ************* 01052 * return value: signed char* new context stack at the end of the line 01053 *******************************************************************************************/ 01054 01055 void Highlight::doHighlight(QMemArray<short> oCtx, TextLine *textLine,bool lineContinue, 01056 QMemArray<signed char>* foldingList) 01057 { 01058 if (!textLine) 01059 return; 01060 01061 if (noHl) 01062 { 01063 textLine->setAttribs(0,0,textLine->length()); 01064 return; 01065 } 01066 01067 // kdDebug(13010)<<QString("The context stack length is: %1").arg(oCtx.size())<<endl; 01068 01069 HlContext *context; 01070 01071 // if (lineContinue) kdDebug(13010)<<"Entering with lineContinue flag set"<<endl; 01072 01073 int ctxNum; 01074 int prevLine; 01075 01076 QMemArray<short> ctx; 01077 ctx.duplicate (oCtx); 01078 01079 if ( oCtx.isEmpty() ) 01080 { 01081 // If the stack is empty, we assume to be in Context 0 (Normal) 01082 ctxNum=0; 01083 context=contextNum(ctxNum); 01084 prevLine=-1; 01085 } 01086 else 01087 { 01088 // There does an old context stack exist -> find the context at the line start 01089 ctxNum=ctx[oCtx.size()-1]; //context ID of the last character in the previous line 01090 01091 //kdDebug(13010) << "\t\tctxNum = " << ctxNum << " contextList[ctxNum] = " << contextList[ctxNum] << endl; // ellis 01092 01093 //if (lineContinue) kdDebug(13010)<<QString("The old context should be %1").arg((int)ctxNum)<<endl; 01094 01095 if (!(context = contextNum(ctxNum))) 01096 context = contextNum(0); 01097 01098 //kdDebug(13010)<<"test1-2-1-text2"<<endl; 01099 01100 prevLine=oCtx.size()-1; //position of the last context ID of th previous line within the stack 01101 01102 //kdDebug(13010)<<"test1-2-1-text3"<<endl; 01103 generateContextStack(&ctxNum, context->ctx, &ctx, &prevLine, lineContinue); //get stack ID to use 01104 01105 //kdDebug(13010)<<"test1-2-1-text4"<<endl; 01106 01107 if (!(context = contextNum(ctxNum))) 01108 context = contextNum(0); 01109 01110 //if (lineContinue) kdDebug(13010)<<QString("The new context is %1").arg((int)ctxNum)<<endl; 01111 } 01112 01113 // text, for programming convenience :) 01114 QChar lastChar = ' '; 01115 const QString& text = textLine->string(); 01116 uint len = textLine->length(); 01117 01118 int offset1 = 0; 01119 uint z = 0; 01120 HlItem *item = 0; 01121 bool found = false; 01122 01123 while (z < len) 01124 { 01125 found = false; 01126 01127 bool standardStartEnableDetermined = false; 01128 bool standardStartEnable = false; 01129 01130 for (item = context->items.first(); item != 0L; item = context->items.next()) 01131 { 01132 bool thisStartEnabled = false; 01133 01134 if (item->alwaysStartEnable()) 01135 { 01136 thisStartEnabled = true; 01137 } 01138 else if (!item->hasCustomStartEnable()) 01139 { 01140 if (!standardStartEnableDetermined) 01141 { 01142 standardStartEnable = stdDeliminator.find(lastChar) != -1; 01143 standardStartEnableDetermined = true; 01144 } 01145 01146 thisStartEnabled = standardStartEnable; 01147 } 01148 else if (item->startEnable(lastChar)) 01149 { 01150 thisStartEnabled = true; 01151 } 01152 01153 if (thisStartEnabled) 01154 { 01155 int offset2 = item->checkHgl(text, offset1, len-z); 01156 01157 if (offset2 > offset1) 01158 { 01159 textLine->setAttribs(item->attr,offset1,offset2); 01160 //kdDebug(13010)<<QString("item->ctx: %1").arg(item->ctx)<<endl; 01161 01162 if (item->region) 01163 { 01164 // kdDebug(13010)<<QString("Region mark detected: %1").arg(item->region)<<endl; 01165 01166 if ( !foldingList->isEmpty() && ((item->region < 0) && (*foldingList)[foldingList->size()-1] == -item->region ) ) 01167 { 01168 foldingList->resize (foldingList->size()-1); 01169 } 01170 else 01171 { 01172 foldingList->resize (foldingList->size()+1); 01173 (*foldingList)[foldingList->size()-1] = item->region; 01174 } 01175 01176 } 01177 01178 if (item->region2) 01179 { 01180 // kdDebug(13010)<<QString("Region mark 2 detected: %1").arg(item->region2)<<endl; 01181 01182 if ( !foldingList->isEmpty() && ((item->region2 < 0) && (*foldingList)[foldingList->size()-1] == -item->region2 ) ) 01183 { 01184 foldingList->resize (foldingList->size()-1); 01185 } 01186 else 01187 { 01188 foldingList->resize (foldingList->size()+1); 01189 (*foldingList)[foldingList->size()-1] = item->region2; 01190 } 01191 01192 } 01193 01194 generateContextStack(&ctxNum, item->ctx, &ctx, &prevLine); //regenerate context stack 01195 01196 //kdDebug(13010)<<QString("generateContextStack has been left in item loop, size: %1").arg(ctx.size())<<endl; 01197 // kdDebug(13010)<<QString("current ctxNum==%1").arg(ctxNum)<<endl; 01198 01199 context=contextNum(ctxNum); 01200 01201 z = z + offset2 - offset1 - 1; 01202 offset1 = offset2 - 1; 01203 found = true; 01204 break; 01205 } 01206 } 01207 } 01208 01209 lastChar = text[offset1]; 01210 01211 // nothing found: set attribute of one char 01212 // anders: unless this context does not want that! 01213 if (!found) 01214 { 01215 if ( context->fallthrough ) 01216 { 01217 // set context to context->ftctx. 01218 generateContextStack(&ctxNum, context->ftctx, &ctx, &prevLine); //regenerate context stack 01219 context=contextNum(ctxNum); 01220 //kdDebug(13010)<<"context num after fallthrough at col "<<z<<": "<<ctxNum<<endl; 01221 // the next is nessecary, as otherwise keyword (or anything using the std delimitor check) 01222 // immediately after fallthrough fails. Is it bad? 01223 // jowenn, can you come up with a nicer way to do this? 01224 if (z) 01225 lastChar = text[offset1 - 1]; 01226 else 01227 lastChar = '\\'; 01228 continue; 01229 } 01230 else 01231 textLine->setAttribs(context->attr,offset1,offset1 + 1); 01232 } 01233 01234 offset1++; 01235 z++; 01236 } 01237 01238 if (item==0) 01239 textLine->setHlLineContinue(false); 01240 else 01241 textLine->setHlLineContinue(item->lineContinue()); 01242 01243 textLine->setContext(ctx.data(), ctx.size()); 01244 } 01245 01246 void Highlight::loadWildcards() 01247 { 01248 KConfig *config = HlManager::self()->getKConfig(); 01249 config->setGroup("Highlighting " + iName); 01250 01251 QString extensionString = config->readEntry("Wildcards", iWildcards); 01252 01253 if (extensionSource != extensionString) { 01254 regexpExtensions.clear(); 01255 plainExtensions.clear(); 01256 01257 extensionSource = extensionString; 01258 01259 static QRegExp sep("\\s*;\\s*"); 01260 01261 QStringList l = QStringList::split( sep, extensionSource ); 01262 01263 static QRegExp boringExpression("\\*\\.[\\d\\w]+"); 01264 01265 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) 01266 if (boringExpression.exactMatch(*it)) 01267 plainExtensions.append((*it).mid(1)); 01268 else 01269 regexpExtensions.append(QRegExp((*it), true, true)); 01270 } 01271 } 01272 01273 QValueList<QRegExp>& Highlight::getRegexpExtensions() 01274 { 01275 return regexpExtensions; 01276 } 01277 01278 QStringList& Highlight::getPlainExtensions() 01279 { 01280 return plainExtensions; 01281 } 01282 01283 QString Highlight::getMimetypes() 01284 { 01285 KConfig *config = HlManager::self()->getKConfig(); 01286 config->setGroup("Highlighting " + iName); 01287 01288 return config->readEntry("Mimetypes", iMimetypes); 01289 } 01290 01291 int Highlight::priority() 01292 { 01293 KConfig *config = HlManager::self()->getKConfig(); 01294 config->setGroup("Highlighting " + iName); 01295 01296 return config->readNumEntry("Priority", m_priority); 01297 } 01298 01299 HlData *Highlight::getData() 01300 { 01301 KConfig *config = HlManager::self()->getKConfig(); 01302 config->setGroup("Highlighting " + iName); 01303 01304 HlData *hlData = new HlData( 01305 config->readEntry("Wildcards", iWildcards), 01306 config->readEntry("Mimetypes", iMimetypes), 01307 config->readEntry("Identifier", identifier), 01308 config->readNumEntry("Priority", m_priority)); 01309 01310 return hlData; 01311 } 01312 01313 void Highlight::setData(HlData *hlData) 01314 { 01315 KConfig *config = HlManager::self()->getKConfig(); 01316 config->setGroup("Highlighting " + iName); 01317 01318 config->writeEntry("Wildcards",hlData->wildcards); 01319 config->writeEntry("Mimetypes",hlData->mimetypes); 01320 config->writeEntry("Priority",hlData->priority); 01321 } 01322 01323 void Highlight::getItemDataList (uint schema, ItemDataList &list) 01324 { 01325 KConfig *config = HlManager::self()->getKConfig(); 01326 config->setGroup("Highlighting " + iName + " - Schema " + KateFactory::self()->schemaManager()->name(schema)); 01327 01328 list.clear(); 01329 createItemData(list); 01330 01331 for (ItemData *p = list.first(); p != 0L; p = list.next()) 01332 { 01333 QStringList s = config->readListEntry(p->name); 01334 01335 // kdDebug()<<p->name<<s.count()<<endl; 01336 if (s.count()>0) 01337 { 01338 01339 while(s.count()<9) s<<""; 01340 p->clear(); 01341 01342 QString tmp=s[0]; if (!tmp.isEmpty()) p->defStyleNum=tmp.toInt(); 01343 01344 QRgb col; 01345 01346 tmp=s[1]; if (!tmp.isEmpty()) { 01347 col=tmp.toUInt(0,16); p->setTextColor(col); } 01348 01349 tmp=s[2]; if (!tmp.isEmpty()) { 01350 col=tmp.toUInt(0,16); p->setSelectedTextColor(col); } 01351 01352 tmp=s[3]; if (!tmp.isEmpty()) p->setBold(tmp!="0"); 01353 01354 tmp=s[4]; if (!tmp.isEmpty()) p->setItalic(tmp!="0"); 01355 01356 tmp=s[5]; if (!tmp.isEmpty()) p->setStrikeOut(tmp!="0"); 01357 01358 tmp=s[6]; if (!tmp.isEmpty()) p->setUnderline(tmp!="0"); 01359 01360 tmp=s[7]; if (!tmp.isEmpty()) { 01361 col=tmp.toUInt(0,16); p->setBGColor(col); } 01362 01363 tmp=s[8]; if (!tmp.isEmpty()) { 01364 col=tmp.toUInt(0,16); p->setSelectedBGColor(col); } 01365 01366 } 01367 } 01368 } 01369 01370 /******************************************************************************************* 01371 Highlight - setItemDataList 01372 saves the ItemData / attribute / style definitions to the apps configfile. 01373 Especially needed for user overridden values. 01374 01375 * input: ItemDataList &list :reference to the list, whose 01376 * items should be saved 01377 * KConfig *config :Pointer KDE configuration 01378 * class, which should be used 01379 * as storage 01380 ************* 01381 * output: none 01382 ************* 01383 * return value: none 01384 *******************************************************************************************/ 01385 01386 void Highlight::setItemDataList(uint schema, ItemDataList &list) 01387 { 01388 KConfig *config = HlManager::self()->getKConfig(); 01389 config->setGroup("Highlighting " + iName + " - Schema " + KateFactory::self()->schemaManager()->name(schema)); 01390 01391 QStringList settings; 01392 01393 for (ItemData *p = list.first(); p != 0L; p = list.next()) 01394 { 01395 settings.clear(); 01396 settings<<QString::number(p->defStyleNum,10); 01397 settings<<(p->itemSet(KateAttribute::TextColor)?QString::number(p->textColor().rgb(),16):""); 01398 settings<<(p->itemSet(KateAttribute::SelectedTextColor)?QString::number(p->selectedTextColor().rgb(),16):""); 01399 settings<<(p->itemSet(KateAttribute::Weight)?(p->bold()?"1":"0"):""); 01400 settings<<(p->itemSet(KateAttribute::Italic)?(p->italic()?"1":"0"):""); 01401 settings<<(p->itemSet(KateAttribute::StrikeOut)?(p->strikeOut()?"1":"0"):""); 01402 settings<<(p->itemSet(KateAttribute::Underline)?(p->underline()?"1":"0"):""); 01403 settings<<(p->itemSet(KateAttribute::BGColor)?QString::number(p->bgColor().rgb(),16):""); 01404 settings<<(p->itemSet(KateAttribute::SelectedBGColor)?QString::number(p->selectedBGColor().rgb(),16):""); 01405 settings<<"---"; 01406 config->writeEntry(p->name,settings); 01407 } 01408 } 01409 01410 /******************************************************************************************* 01411 Highlight - use 01412 Increase the usage count and trigger initialization if needed 01413 01414 * input: none 01415 ************* 01416 * output: none 01417 ************* 01418 * return value: none 01419 *******************************************************************************************/ 01420 01421 void Highlight::use() 01422 { 01423 if (refCount == 0) 01424 init(); 01425 01426 refCount++; 01427 } 01428 01429 /******************************************************************************************* 01430 Highlight - release 01431 Decrease the usage count and trigger a cleanup if needed 01432 01433 * input: none 01434 ************* 01435 * output: none 01436 ************* 01437 * return value: none 01438 *******************************************************************************************/ 01439 01440 void Highlight::release() 01441 { 01442 refCount--; 01443 01444 if (refCount == 0) 01445 done(); 01446 } 01447 01448 /******************************************************************************************* 01449 Highlight - init 01450 If it's the first time a particular highlighting is used create the needed contextlist 01451 01452 * input: none 01453 ************* 01454 * output: none 01455 ************* 01456 * return value: none 01457 *******************************************************************************************/ 01458 01459 void Highlight::init() 01460 { 01461 if (noHl) 01462 return; 01463 01464 contextList.clear (); 01465 makeContextList(); 01466 } 01467 01468 01469 /******************************************************************************************* 01470 Highlight - done 01471 If the there is no document using the highlighting style free the complete context 01472 structure. 01473 01474 * input: none 01475 ************* 01476 * output: none 01477 ************* 01478 * return value: none 01479 *******************************************************************************************/ 01480 01481 void Highlight::done() 01482 { 01483 if (noHl) 01484 return; 01485 01486 contextList.clear (); 01487 internalIDList.clear(); 01488 } 01489 01490 HlContext *Highlight::contextNum (uint n) 01491 { 01492 return contextList[n]; 01493 } 01494 01495 /******************************************************************************************* 01496 Highlight - createItemData 01497 This function reads the itemData entries from the config file, which specifies the 01498 default attribute styles for matched items/contexts. 01499 01500 * input: none 01501 ************* 01502 * output: ItemDataList &list :A reference to the internal 01503 list containing the parsed 01504 default config 01505 ************* 01506 * return value: none 01507 *******************************************************************************************/ 01508 01509 void Highlight::createItemData(ItemDataList &list) 01510 { 01511 // If no highlighting is selected we need only one default. 01512 if (noHl) 01513 { 01514 list.append(new ItemData(I18N_NOOP("Normal Text"), dsNormal)); 01515 return; 01516 } 01517 01518 // If the internal list isn't already available read the config file 01519 if (internalIDList.isEmpty()) 01520 makeContextList(); 01521 01522 list=internalIDList; 01523 } 01524 01525 void Highlight::addToItemDataList() 01526 { 01527 //Tell the syntax document class which file we want to parse and which data group 01528 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01529 syntaxContextData *data = HlManager::self()->syntax->getGroupInfo("highlighting","itemData"); 01530 01531 //begin with the real parsing 01532 while (HlManager::self()->syntax->nextGroup(data)) 01533 { 01534 // read all attributes 01535 QString color = HlManager::self()->syntax->groupData(data,QString("color")); 01536 QString selColor = HlManager::self()->syntax->groupData(data,QString("selColor")); 01537 QString bold = HlManager::self()->syntax->groupData(data,QString("bold")); 01538 QString italic = HlManager::self()->syntax->groupData(data,QString("italic")); 01539 QString underline = HlManager::self()->syntax->groupData(data,QString("underline")); 01540 QString strikeOut = HlManager::self()->syntax->groupData(data,QString("strikeOut")); 01541 QString bgColor = HlManager::self()->syntax->groupData(data,QString("backgroundColor")); 01542 QString selBgColor = HlManager::self()->syntax->groupData(data,QString("selBackgroundColor")); 01543 01544 ItemData* newData = new ItemData( 01545 buildPrefix+HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(), 01546 getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum")))); 01547 01548 01549 /* here the custom style overrides are specified, if needed */ 01550 if (!color.isEmpty()) newData->setTextColor(QColor(color)); 01551 if (!selColor.isEmpty()) newData->setSelectedTextColor(QColor(selColor)); 01552 if (!bold.isEmpty()) newData->setBold(bold=="true" || bold=="1"); 01553 if (!italic.isEmpty()) newData->setItalic(italic=="true" || italic=="1"); 01554 // new attributes for the new rendering view 01555 if (!underline.isEmpty()) newData->setUnderline(underline=="true" || underline=="1"); 01556 if (!strikeOut.isEmpty()) newData->setStrikeOut(strikeOut=="true" || strikeOut=="1"); 01557 if (!bgColor.isEmpty()) newData->setBGColor(QColor(bgColor)); 01558 if (!selBgColor.isEmpty()) newData->setSelectedBGColor(QColor(selBgColor)); 01559 01560 internalIDList.append(newData); 01561 } 01562 01563 //clean up 01564 if (data) 01565 HlManager::self()->syntax->freeGroupInfo(data); 01566 } 01567 01568 /******************************************************************************************* 01569 Highlight - lookupAttrName 01570 This function is a helper for makeContextList and createHlItem. It looks the given 01571 attribute name in the itemData list up and returns it's index 01572 01573 * input: QString &name :the attribute name to lookup 01574 * ItemDataList &iDl :the list containing all 01575 * available attributes 01576 ************* 01577 * output: none 01578 ************* 01579 * return value: int :The index of the attribute 01580 * or 0 01581 *******************************************************************************************/ 01582 01583 int Highlight::lookupAttrName(const QString& name, ItemDataList &iDl) 01584 { 01585 for (uint i = 0; i < iDl.count(); i++) 01586 if (iDl.at(i)->name == buildPrefix+name) 01587 return i; 01588 01589 kdDebug(13010)<<"Couldn't resolve itemDataName"<<endl; 01590 return 0; 01591 } 01592 01593 /******************************************************************************************* 01594 Highlight - createHlItem 01595 This function is a helper for makeContextList. It parses the xml file for 01596 information, how single or multi line comments are marked 01597 01598 * input: syntaxContextData *data : Data about the item read from 01599 * the xml file 01600 * ItemDataList &iDl : List of all available itemData 01601 * entries. Needed for attribute 01602 * name->index translation 01603 * QStringList *RegionList : list of code folding region names 01604 * QStringList ContextList : list of context names 01605 ************* 01606 * output: none 01607 ************* 01608 * return value: HlItem * : Pointer to the newly created item 01609 * object 01610 *******************************************************************************************/ 01611 01612 HlItem *Highlight::createHlItem(struct syntaxContextData *data, ItemDataList &iDl,QStringList *RegionList, QStringList *ContextNameList) 01613 { 01614 // No highlighting -> exit 01615 if (noHl) 01616 return 0; 01617 01618 // get the (tagname) itemd type 01619 QString dataname=HlManager::self()->syntax->groupItemData(data,QString("")); 01620 01621 // BEGIN - Translation of the attribute parameter 01622 QString tmpAttr=HlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace(); 01623 int attr; 01624 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) 01625 { 01626 errorsAndWarnings+=i18n("<B>%1</B>: Deprecated syntax. Attribute (%2) not addressed by symbolic name<BR>"). 01627 arg(buildIdentifier).arg(tmpAttr); 01628 attr=tmpAttr.toInt(); 01629 } 01630 else 01631 attr=lookupAttrName(tmpAttr,iDl); 01632 // END - Translation of the attribute parameter 01633 01634 // Info about context switch 01635 int context; 01636 QString tmpcontext=HlManager::self()->syntax->groupItemData(data,QString("context")); 01637 01638 01639 QString unresolvedContext; 01640 context=getIdFromString(ContextNameList, tmpcontext,unresolvedContext); 01641 01642 // Get the char parameter (eg DetectChar) 01643 char chr; 01644 if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty()) 01645 chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0]; 01646 else 01647 chr=0; 01648 01649 // Get the String parameter (eg. StringDetect) 01650 QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String")); 01651 01652 // Get a second char parameter (char1) (eg Detect2Chars) 01653 char chr1; 01654 if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty()) 01655 chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0]; 01656 else 01657 chr1=0; 01658 01659 // Will be removed eventuall. Atm used for StringDetect 01660 bool insensitive=( HlManager::self()->syntax->groupItemData(data,QString("insensitive")).lower() == QString("true") ); 01661 // anders: very reasonable for regexp too! 01662 01663 // for regexp only 01664 bool minimal = ( HlManager::self()->syntax->groupItemData(data,QString("minimal")).lower() == QString("true") ); 01665 01666 01667 // code folding region handling: 01668 QString beginRegionStr=HlManager::self()->syntax->groupItemData(data,QString("beginRegion")); 01669 QString endRegionStr=HlManager::self()->syntax->groupItemData(data,QString("endRegion")); 01670 01671 signed char regionId=0; 01672 signed char regionId2=0; 01673 01674 if (!beginRegionStr.isEmpty()) 01675 { 01676 regionId = RegionList->findIndex(beginRegionStr); 01677 01678 if (regionId==-1) // if the region name doesn't already exist, add it to the list 01679 { 01680 (*RegionList)<<beginRegionStr; 01681 regionId = RegionList->findIndex(beginRegionStr); 01682 } 01683 01684 regionId++; 01685 01686 kdDebug () << "########### BEG REG: " << beginRegionStr << " NUM: " << regionId << endl; 01687 } 01688 01689 if (!endRegionStr.isEmpty()) 01690 { 01691 regionId2 = RegionList->findIndex(endRegionStr); 01692 01693 if (regionId2==-1) // if the region name doesn't already exist, add it to the list 01694 { 01695 (*RegionList)<<endRegionStr; 01696 regionId2 = RegionList->findIndex(endRegionStr); 01697 } 01698 01699 regionId2 = -regionId2 - 1; 01700 01701 kdDebug () << "########### END REG: " << endRegionStr << " NUM: " << regionId2 << endl; 01702 } 01703 01704 //Create the item corresponding to it's type and set it's parameters 01705 HlItem *tmpItem; 01706 01707 if (dataname=="keyword") 01708 { 01709 HlKeyword *keyword=new HlKeyword(attr,context,regionId,regionId2,casesensitive, 01710 deliminator); 01711 01712 //Get the entries for the keyword lookup list 01713 keyword->addList(HlManager::self()->syntax->finddata("highlighting",stringdata)); 01714 tmpItem=keyword; 01715 } else 01716 if (dataname=="Float") tmpItem= (new HlFloat(attr,context,regionId,regionId2)); else 01717 if (dataname=="Int") tmpItem=(new HlInt(attr,context,regionId,regionId2)); else 01718 if (dataname=="DetectChar") tmpItem=(new HlCharDetect(attr,context,regionId,regionId2,chr)); else 01719 if (dataname=="Detect2Chars") tmpItem=(new Hl2CharDetect(attr,context,regionId,regionId2,chr,chr1)); else 01720 if (dataname=="RangeDetect") tmpItem=(new HlRangeDetect(attr,context,regionId,regionId2, chr, chr1)); else 01721 if (dataname=="LineContinue") tmpItem=(new HlLineContinue(attr,context,regionId,regionId2)); else 01722 if (dataname=="StringDetect") tmpItem=(new HlStringDetect(attr,context,regionId,regionId2,stringdata,insensitive)); else 01723 if (dataname=="AnyChar") tmpItem=(new HlAnyChar(attr,context,regionId,regionId2,stringdata)); else 01724 if (dataname=="RegExpr") tmpItem=(new HlRegExpr(attr,context,regionId,regionId2,stringdata, insensitive, minimal)); else 01725 if (dataname=="HlCChar") tmpItem= ( new HlCChar(attr,context,regionId,regionId2));else 01726 if (dataname=="HlCHex") tmpItem= (new HlCHex(attr,context,regionId,regionId2));else 01727 if (dataname=="HlCOct") tmpItem= (new HlCOct(attr,context,regionId,regionId2)); else 01728 if (dataname=="HlCFloat") tmpItem= (new HlCFloat(attr,context,regionId,regionId2)); else 01729 if (dataname=="HlCStringChar") tmpItem= (new HlCStringChar(attr,context,regionId,regionId2)); else 01730 01731 { 01732 // oops, unknown type. Perhaps a spelling error in the xml file 01733 return 0; 01734 } 01735 01736 if (!unresolvedContext.isEmpty()) 01737 { 01738 unresolvedContextReferences.insert(&(tmpItem->ctx),unresolvedContext); 01739 } 01740 return tmpItem; 01741 } 01742 01743 01744 /******************************************************************************************* 01745 Highlight - isInWord 01746 01747 * input: Qchar c Character to investigate 01748 ************* 01749 * output: none 01750 ************* 01751 * return value: returns true, if c is no deliminator 01752 *******************************************************************************************/ 01753 01754 bool Highlight::isInWord(QChar c) 01755 { 01756 static const QString sq("\"'"); 01757 return deliminator.find(c) == -1 && sq.find(c) == -1; 01758 } 01759 01760 /******************************************************************************************* 01761 Highlight - readCommentConfig 01762 This function is a helper for makeContextList. It parses the xml file for 01763 information, how single or multi line comments are marked 01764 01765 * input: none 01766 ************* 01767 * output: none 01768 ************* 01769 * return value: none 01770 *******************************************************************************************/ 01771 01772 void Highlight::readCommentConfig() 01773 { 01774 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01775 syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("general","comment"); 01776 01777 if (data) 01778 { 01779 while (HlManager::self()->syntax->nextGroup(data)) 01780 { 01781 if (HlManager::self()->syntax->groupData(data,"name")=="singleLine") 01782 cslStart=HlManager::self()->syntax->groupData(data,"start"); 01783 01784 if (HlManager::self()->syntax->groupData(data,"name")=="multiLine") 01785 { 01786 cmlStart=HlManager::self()->syntax->groupData(data,"start"); 01787 cmlEnd=HlManager::self()->syntax->groupData(data,"end"); 01788 } 01789 } 01790 01791 HlManager::self()->syntax->freeGroupInfo(data); 01792 } 01793 else 01794 { 01795 cslStart = ""; 01796 cmlStart = ""; 01797 cmlEnd = ""; 01798 } 01799 } 01800 01801 /******************************************************************************************* 01802 Highlight - readGlobalKeyWordConfig 01803 This function is a helper for makeContextList. It parses the xml file for 01804 information, if keywords should be treated case(in)sensitive and creates the keyword 01805 delimiter list. Which is the default list, without any given weak deliminiators 01806 01807 * input: none 01808 ************* 01809 * output: none 01810 ************* 01811 * return value: none 01812 *******************************************************************************************/ 01813 01814 01815 void Highlight::readGlobalKeywordConfig() 01816 { 01817 // Tell the syntax document class which file we want to parse 01818 kdDebug(13010)<<"readGlobalKeywordConfig:BEGIN"<<endl; 01819 01820 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01821 syntaxContextData *data = HlManager::self()->syntax->getConfig("general","keywords"); 01822 01823 if (data) 01824 { 01825 kdDebug(13010)<<"Found global keyword config"<<endl; 01826 01827 if (HlManager::self()->syntax->groupItemData(data,QString("casesensitive"))!="0") 01828 casesensitive=true; 01829 else 01830 casesensitive=false; 01831 01832 //get the weak deliminators 01833 weakDeliminator=(HlManager::self()->syntax->groupItemData(data,QString("weakDeliminator"))); 01834 01835 kdDebug(13010)<<"weak delimiters are: "<<weakDeliminator<<endl; 01836 01837 // remove any weakDelimitars (if any) from the default list and store this list. 01838 for (uint s=0; s < weakDeliminator.length(); s++) 01839 { 01840 int f = deliminator.find (weakDeliminator[s]); 01841 01842 if (f > -1) 01843 deliminator.remove (f, 1); 01844 } 01845 01846 QString addDelim = (HlManager::self()->syntax->groupItemData(data,QString("additionalDeliminator"))); 01847 01848 if (!addDelim.isEmpty()) 01849 deliminator=deliminator+addDelim; 01850 01851 HlManager::self()->syntax->freeGroupInfo(data); 01852 } 01853 else 01854 { 01855 //Default values 01856 casesensitive=true; 01857 weakDeliminator=QString(""); 01858 } 01859 01860 kdDebug(13010)<<"readGlobalKeywordConfig:END"<<endl; 01861 01862 kdDebug(13010)<<"delimiterCharacters are: "<<deliminator<<endl; 01863 } 01864 01865 01866 void Highlight::readFoldingConfig() 01867 { 01868 // Tell the syntax document class which file we want to parse 01869 kdDebug(13010)<<"readfoldignConfig:BEGIN"<<endl; 01870 01871 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01872 syntaxContextData *data = HlManager::self()->syntax->getConfig("general","folding"); 01873 01874 if (data) 01875 { 01876 kdDebug(13010)<<"Found global keyword config"<<endl; 01877 01878 if (HlManager::self()->syntax->groupItemData(data,QString("indentationsensitive"))!="1") 01879 m_foldingIndentationSensitive=false; 01880 else 01881 m_foldingIndentationSensitive=true; 01882 01883 HlManager::self()->syntax->freeGroupInfo(data); 01884 } 01885 else 01886 { 01887 //Default values 01888 m_foldingIndentationSensitive = false; 01889 } 01890 01891 kdDebug(13010)<<"readfoldingConfig:END"<<endl; 01892 01893 kdDebug(13010)<<"############################ use indent for fold are: "<<m_foldingIndentationSensitive<<endl; 01894 } 01895 01896 void Highlight::createContextNameList(QStringList *ContextNameList,int ctx0) 01897 { 01898 kdDebug(13010)<<"creatingContextNameList:BEGIN"<<endl; 01899 01900 if (ctx0 == 0) 01901 ContextNameList->clear(); 01902 01903 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01904 01905 syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("highlighting","context"); 01906 01907 int id=ctx0; 01908 01909 if (data) 01910 { 01911 while (HlManager::self()->syntax->nextGroup(data)) 01912 { 01913 QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(); 01914 if (tmpAttr.isEmpty()) 01915 { 01916 tmpAttr=QString("!KATE_INTERNAL_DUMMY! %1").arg(id); 01917 errorsAndWarnings +=i18n("<B>%1</B>: Deprecated syntax. Context %2 has no symbolic name<BR>").arg(buildIdentifier).arg(id-ctx0); 01918 } 01919 else tmpAttr=buildPrefix+tmpAttr; 01920 (*ContextNameList)<<tmpAttr; 01921 id++; 01922 } 01923 HlManager::self()->syntax->freeGroupInfo(data); 01924 } 01925 kdDebug(13010)<<"creatingContextNameList:END"<<endl; 01926 01927 } 01928 01929 int Highlight::getIdFromString(QStringList *ContextNameList, QString tmpLineEndContext, /*NO CONST*/ QString &unres) 01930 { 01931 unres=""; 01932 int context; 01933 if ((tmpLineEndContext=="#stay") || (tmpLineEndContext.simplifyWhiteSpace().isEmpty())) context=-1; 01934 else if (tmpLineEndContext.startsWith("#pop")) 01935 { 01936 context=-1; 01937 for(;tmpLineEndContext.startsWith("#pop");context--) 01938 { 01939 tmpLineEndContext.remove(0,4); 01940 kdDebug(13010)<<"#pop found"<<endl; 01941 } 01942 } 01943 else 01944 if ( tmpLineEndContext.startsWith("##")) 01945 { 01946 QString tmp=tmpLineEndContext.right(tmpLineEndContext.length()-2); 01947 if (!embeddedHls.contains(tmp)) embeddedHls.insert(tmp,EmbeddedHlInfo()); 01948 unres=tmp; 01949 context=0; 01950 } 01951 else 01952 { 01953 context=ContextNameList->findIndex(buildPrefix+tmpLineEndContext); 01954 if (context==-1) 01955 { 01956 context=tmpLineEndContext.toInt(); 01957 errorsAndWarnings+=i18n("<B>%1</B>:Deprecated syntax. Context %2 not addressed by a symbolic name").arg(buildIdentifier).arg(tmpLineEndContext); 01958 } 01959 //#warning restructure this the name list storage. 01960 // context=context+buildContext0Offset; 01961 } 01962 return context; 01963 } 01964 01965 /******************************************************************************************* 01966 Highlight - makeContextList 01967 That's the most important initialization function for each highlighting. It's called 01968 each time a document gets a highlighting style assigned. parses the xml file and 01969 creates a corresponding internal structure 01970 01971 * input: none 01972 ************* 01973 * output: none 01974 ************* 01975 * return value: none 01976 *******************************************************************************************/ 01977 01978 void Highlight::makeContextList() 01979 { 01980 if (noHl) // if this a highlighting for "normal texts" only, tere is no need for a context list creation 01981 return; 01982 01983 embeddedHls.clear(); 01984 unresolvedContextReferences.clear(); 01985 RegionList.clear(); 01986 ContextNameList.clear(); 01987 01988 // prepare list creation. To reuse as much code as possible handle this highlighting the same way as embedded onces 01989 embeddedHls.insert(iName,EmbeddedHlInfo()); 01990 01991 bool something_changed; 01992 int startctx=0; // the context "0" id is 0 for this hl, all embedded context "0"s have offsets 01993 building=true; // inform everybody that we are building the highlighting contexts and itemlists 01994 do 01995 { 01996 kdDebug(13010)<<"**************** Outter loop in make ContextList"<<endl; 01997 kdDebug(13010)<<"**************** Hl List count:"<<embeddedHls.count()<<endl; 01998 something_changed=false; //assume all "embedded" hls have already been loaded 01999 for (EmbeddedHlInfos::const_iterator it=embeddedHls.begin(); it!=embeddedHls.end();++it) 02000 { 02001 if (!it.data().loaded) // we found one, we still have to load 02002 { 02003 kdDebug(13010)<<"**************** Inner loop in make ContextList"<<endl; 02004 QString identifierToUse; 02005 kdDebug(13010)<<"Trying to open highlighting definition file: "<< it.key()<<endl; 02006 if (iName==it.key()) identifierToUse=identifier; // the own identifier is known 02007 else 02008 identifierToUse=HlManager::self()->identifierForName(it.key()); // all others have to be looked up 02009 02010 kdDebug(13010)<<"Location is:"<< identifierToUse<<endl; 02011 02012 buildPrefix=it.key()+':'; // attribute names get prefixed by the names of the highlighting definitions they belong to 02013 02014 if (identifierToUse.isEmpty() ) kdDebug()<<"OHOH, unknown highlighting description referenced"<<endl; 02015 02016 kdDebug()<<"setting ("<<it.key()<<") to loaded"<<endl; 02017 it=embeddedHls.insert(it.key(),EmbeddedHlInfo(true,startctx)); //mark hl as loaded 02018 buildContext0Offset=startctx; //set class member for context 0 offset, so we don't need to pass it around 02019 startctx=addToContextList(identifierToUse,startctx); //parse one hl definition file 02020 if (noHl) return; // an error occurred 02021 something_changed=true; // something has been loaded 02022 02023 } 02024 } 02025 } while (something_changed); // as long as there has been another file parsed repeat everything, there could be newly added embedded hls. 02026 02027 02028 /* at this point all needed highlighing (sub)definitions are loaded. It's time to resolve cross file 02029 references (if there are some 02030 */ 02031 kdDebug(13010)<<"Unresolved contexts, which need attention: "<<unresolvedContextReferences.count()<<endl; 02032 //optimize this a littlebit 02033 for (UnresolvedContextReferences::iterator unresIt=unresolvedContextReferences.begin(); 02034 unresIt!=unresolvedContextReferences.end();++unresIt) 02035 { 02036 //try to find the context0 id for a given unresolvedReference 02037 EmbeddedHlInfos::const_iterator hlIt=embeddedHls.find(unresIt.data()); 02038 if (hlIt!=embeddedHls.end()) 02039 *(unresIt.key())=hlIt.data().context0; 02040 } 02041 02042 /*eventually handle IncludeRules items, if they exist. 02043 This has to be done after the cross file references, because it is allowed 02044 to include the context0 from a different definition, than the one the rule belongs to */ 02045 handleIncludeRules(); 02046 02047 embeddedHls.clear(); //save some memory. 02048 unresolvedContextReferences.clear(); //save some memory 02049 RegionList.clear(); // I think you get the idea ;) 02050 ContextNameList.clear(); 02051 02052 02053 // if there have been errors show them 02054 if (!errorsAndWarnings.isEmpty()) 02055 KMessageBox::detailedSorry(0L,i18n("There were warning(s) and/or error(s) while parsing the syntax highlighting configuration."), errorsAndWarnings, i18n("Kate Syntax Highlight Parser")); 02056 02057 // we have finished 02058 building=false; 02059 } 02060 02061 void Highlight::handleIncludeRules() 02062 { 02063 02064 // if there are noe include rules to take care of, just return 02065 kdDebug(13010)<<"IncludeRules, which need attention: " <<includeRules.count()<<endl; 02066 if (includeRules.isEmpty()) return; 02067 02068 buildPrefix=""; 02069 QString dummy; 02070 02071 /*by now the context0 references are resolved, now more or less only inner file references are resolved. 02072 If we decide that arbitrary inclusion is needed, this doesn't need to be changed, only the addToContextList 02073 method 02074 */ 02075 02076 //resolove context names 02077 for (IncludeRules::iterator it=includeRules.begin();it!=includeRules.end();) 02078 { 02079 02080 if ((*it)->incCtx==-1) // context unresolved ? 02081 { //yes 02082 02083 if ((*it)->incCtxN.isEmpty()) 02084 { 02085 // no context name given, and no valid context id set, so this item is going to be removed 02086 IncludeRules::iterator it1=it; 02087 ++it1; 02088 delete (*it); 02089 includeRules.remove(it); 02090 it=it1; 02091 } 02092 else 02093 { 02094 // resolve name to id 02095 (*it)->incCtx=getIdFromString(&ContextNameList,(*it)->incCtxN,dummy); 02096 kdDebug()<<"Resolved "<<(*it)->incCtxN<< " to "<<(*it)->incCtx<<" for include rule"<<endl; 02097 // It would be good to look here somehow, if the result is valid 02098 } 02099 } else ++it; //nothing to do, already resolved (by the cross defintion reference resolver 02100 } 02101 02102 // now that all IncludeRule items should be valid and completely resolved, do the real inclusion of the rules. 02103 // recursiveness is needed, because context 0 could include context 1, which itself includes context 2 and so on. 02104 // In that case we have to handle context 2 first, then 1, 0 02105 //TODO: catch circular references: eg 0->1->2->3->1 02106 while (!includeRules.isEmpty()) 02107 handleIncludeRulesRecursive(includeRules.begin(),&includeRules); 02108 02109 02110 } 02111 02112 void Highlight::handleIncludeRulesRecursive(IncludeRules::iterator it, IncludeRules *list) 02113 { 02114 if (it==list->end()) return; //invalid iterator, shouldn't happen, but better have a rule prepared ;) 02115 IncludeRules::iterator it1=it; 02116 int ctx=(*it1)->ctx; 02117 02118 /*find the last entry for the given context in the IncludeRules list 02119 this is need if one context includes more than one. This saves us from updating all insert positions: 02120 eg: context 0: 02121 pos 3 - include context 2 02122 pos 5 - include context 3 02123 During the building of the includeRules list the items are inserted in ascending order, now we need it 02124 descending to make our life easier. 02125 */ 02126 while ((it!=list->end()) && ((*it)->ctx==ctx)) 02127 { 02128 it1=it; 02129 ++it; 02130 // kdDebug()<<"loop1"<<endl; 02131 } 02132 // iterate over each include rule for the context the function has been called for. 02133 while ((it1!=list->end()) && ((*it1)->ctx==ctx)) 02134 { 02135 // kdDebug()<<"loop2"<<endl; 02136 02137 02138 int ctx1=(*it1)->incCtx; 02139 02140 //let's see, if the the included context includes other contexts 02141 for (IncludeRules::iterator it2=list->begin();it2!=list->end();++it2) 02142 { 02143 // kdDebug()<<"loop3"<<endl; 02144 02145 if ((*it2)->ctx==ctx1) 02146 { 02147 //yes it does, so first handle that include rules, since we want to 02148 // include those subincludes too 02149 handleIncludeRulesRecursive(it2,list); 02150 break; 02151 } 02152 } 02153 02154 // if the context we want to include had sub includes, they are already inserted there. 02155 HlContext *dest=contextList[ctx]; 02156 HlContext *src=contextList[ctx1]; 02157 uint p=(*it1)->pos; //insert the included context's rules starting at position p 02158 for ( HlItem *c = src->items.first(); c; c=src->items.next(), p++ ) 02159 dest->items.insert(p,c); 02160 02161 it=it1; //backup the iterator 02162 --it1; //move to the next entry, which has to be take care of 02163 delete (*it); //free the already handled data structure 02164 list->remove(it); // remove it from the list 02165 } 02166 } 02167 02168 int Highlight::addToContextList(const QString &ident, int ctx0) 02169 { 02170 buildIdentifier=ident; 02171 syntaxContextData *data, *datasub; 02172 HlItem *c; 02173 02174 QString dummy; 02175 02176 // Let the syntax document class know, which file we'd like to parse 02177 if (!HlManager::self()->syntax->setIdentifier(ident)) 02178 { 02179 noHl=true; 02180 KMessageBox::information(0L,i18n("Since there has been an error parsing the highlighting description, this highlighting will be disabled")); 02181 return 0; 02182 } 02183 02184 RegionList<<"!KateInternal_TopLevel!"; 02185 readCommentConfig(); 02186 readGlobalKeywordConfig(); 02187 readFoldingConfig (); 02188 02189 QString ctxName; 02190 02191 // This list is needed for the translation of the attribute parameter, if the itemData name is given instead of the index 02192 addToItemDataList(); 02193 ItemDataList iDl = internalIDList; 02194 02195 createContextNameList(&ContextNameList,ctx0); 02196 02197 kdDebug(13010)<<"Parsing Context structure"<<endl; 02198 //start the real work 02199 data=HlManager::self()->syntax->getGroupInfo("highlighting","context"); 02200 uint i=buildContext0Offset; 02201 if (data) 02202 { 02203 while (HlManager::self()->syntax->nextGroup(data)) 02204 { 02205 kdDebug(13010)<<"Found a context in file, building structure now"<<endl; 02206 // BEGIN - Translation of the attribute parameter 02207 QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace(); 02208 int attr; 02209 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) 02210 attr=tmpAttr.toInt(); 02211 else 02212 attr=lookupAttrName(tmpAttr,iDl); 02213 // END - Translation of the attribute parameter 02214 02215 ctxName=buildPrefix+HlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace(); 02216 02217 QString tmpLineEndContext=HlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace(); 02218 int context; 02219 02220 context=getIdFromString(&ContextNameList, tmpLineEndContext,dummy); 02221 02222 // BEGIN get fallthrough props 02223 bool ft = false; 02224 int ftc = 0; // fallthrough context 02225 if ( i > 0 ) { // fallthrough is not smart in context 0 02226 QString tmpFt = HlManager::self()->syntax->groupData(data, QString("fallthrough") ); 02227 if ( tmpFt.lower() == "true" || tmpFt.toInt() == 1 ) 02228 ft = true; 02229 if ( ft ) { 02230 QString tmpFtc = HlManager::self()->syntax->groupData( data, QString("fallthroughContext") ); 02231 02232 ftc=getIdFromString(&ContextNameList, tmpFtc,dummy); 02233 if (ftc == -1) ftc =0; 02234 02235 kdDebug(13010)<<"Setting fall through context (context "<<i<<"): "<<ftc<<endl; 02236 } 02237 } 02238 02239 // END falltrhough props 02240 contextList.insert (i, new HlContext ( 02241 attr, 02242 context, 02243 (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1: 02244 (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt(), 02245 ft, ftc 02246 )); 02247 02248 02249 //Let's create all items for the context 02250 while (HlManager::self()->syntax->nextItem(data)) 02251 { 02252 // kdDebug(13010)<< "In make Contextlist: Item:"<<endl; 02253 02254 // IncludeRules : add a pointer to each item in that context 02255 02256 QString tag = HlManager::self()->syntax->groupItemData(data,QString("")); 02257 if ( tag == "IncludeRules" ) { //if the new item is an Include rule, we have to take special care 02258 QString incCtx=HlManager::self()->syntax->groupItemData( data, QString("context")); 02259 // only context refernces of type NAME and ##Name are allowed 02260 if (incCtx.startsWith("##") || (!incCtx.startsWith("#"))) { //#stay, #pop is not interesting here 02261 if (!incCtx.startsWith("#")) { // a local reference -> just initialize the include rule structure 02262 incCtx=buildPrefix+incCtx.simplifyWhiteSpace(); 02263 includeRules.append(new IncludeRule(i,contextList[i]->items.count(),incCtx)); 02264 } 02265 else { //a cross highlighting reference 02266 kdDebug()<<"Cross highlight reference <IncludeRules>"<<endl; 02267 IncludeRule *ir=new IncludeRule(i,contextList[i]->items.count()); 02268 //use the same way to determine cross hl file references as other items do 02269 if (!embeddedHls.contains(incCtx.right(incCtx.length()-2))) 02270 embeddedHls.insert(incCtx.right(incCtx.length()-2),EmbeddedHlInfo()); 02271 unresolvedContextReferences.insert(&(ir->incCtx), 02272 incCtx.right(incCtx.length()-2)); 02273 includeRules.append(ir); 02274 } 02275 } 02276 continue; 02277 } 02278 #if 0 02279 QString tag = HlManager::self()->syntax->groupItemData(data,QString("")); 02280 if ( tag == "IncludeRules" ) { 02281 // 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?) 02282 int ctxId = getIdFromString(&ContextNameList, 02283 HlManager::self()->syntax->groupItemData( data, QString("context")),dummy); // the index is *required* 02284 if ( ctxId > -1) { // we can even reuse rules of 0 if we want to:) 02285 kdDebug(13010)<<"makeContextList["<<i<<"]: including all items of context "<<ctxId<<endl; 02286 if ( ctxId < (int) i ) { // must be defined 02287 for ( c = contextList[ctxId]->items.first(); c; c = contextList[ctxId]->items.next() ) 02288 contextList[i]->items.append(c); 02289 } 02290 else 02291 kdDebug(13010)<<"Context "<<ctxId<<"not defined. You can not include the rules of an undefined context"<<endl; 02292 } 02293 continue; // while nextItem 02294 } 02295 #endif 02296 c=createHlItem(data,iDl,&RegionList,&ContextNameList); 02297 if (c) 02298 { 02299 contextList[i]->items.append(c); 02300 02301 // Not supported completely atm and only one level. Subitems.(all have to be matched to at once) 02302 datasub=HlManager::self()->syntax->getSubItems(data); 02303 bool tmpbool; 02304 if (tmpbool=HlManager::self()->syntax->nextItem(datasub)) 02305 { 02306 c->subItems=new QPtrList<HlItem>; 02307 for (;tmpbool;tmpbool=HlManager::self()->syntax->nextItem(datasub)) 02308 c->subItems->append(createHlItem(datasub,iDl,&RegionList,&ContextNameList)); 02309 } 02310 HlManager::self()->syntax->freeGroupInfo(datasub); 02311 // end of sublevel 02312 } 02313 // kdDebug(13010)<<"Last line in loop"<<endl; 02314 } 02315 i++; 02316 } 02317 } 02318 02319 HlManager::self()->syntax->freeGroupInfo(data); 02320 if (RegionList.count()!=1) folding=true; 02321 folding = folding || m_foldingIndentationSensitive; 02322 return i; 02323 } 02324 02325 void Highlight::clearAttributeArrays () 02326 { 02327 for ( QIntDictIterator< QMemArray<KateAttribute> > it( m_attributeArrays ); it.current(); ++it ) 02328 { 02329 // k, schema correct, let create the data 02330 KateAttributeList defaultStyleList; 02331 defaultStyleList.setAutoDelete(true); 02332 HlManager::self()->getDefaults(it.currentKey(), defaultStyleList); 02333 02334 ItemDataList itemDataList; 02335 getItemDataList(it.currentKey(), itemDataList); 02336 02337 uint nAttribs = itemDataList.count(); 02338 QMemArray<KateAttribute> *array = it.current(); 02339 array->resize (nAttribs); 02340 02341 for (uint z = 0; z < nAttribs; z++) 02342 { 02343 ItemData *itemData = itemDataList.at(z); 02344 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum); 02345 02346 if (itemData && itemData->isSomethingSet()) 02347 n += *itemData; 02348 02349 array->at(z) = n; 02350 } 02351 } 02352 } 02353 02354 QMemArray<KateAttribute> *Highlight::attributes (uint schema) 02355 { 02356 QMemArray<KateAttribute> *array; 02357 02358 // found it, allready floating around 02359 if ((array = m_attributeArrays[schema])) 02360 return array; 02361 02362 // ohh, not found, check if valid schema number 02363 if (!KateFactory::self()->schemaManager()->validSchema(schema)) 02364 { 02365 // uhh, not valid :/, stick with normal default schema, it's always there ! 02366 return attributes (0); 02367 } 02368 02369 // k, schema correct, let create the data 02370 KateAttributeList defaultStyleList; 02371 defaultStyleList.setAutoDelete(true); 02372 HlManager::self()->getDefaults(schema, defaultStyleList); 02373 02374 ItemDataList itemDataList; 02375 getItemDataList(schema, itemDataList); 02376 02377 uint nAttribs = itemDataList.count(); 02378 array = new QMemArray<KateAttribute> (nAttribs); 02379 02380 for (uint z = 0; z < nAttribs; z++) 02381 { 02382 ItemData *itemData = itemDataList.at(z); 02383 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum); 02384 02385 if (itemData && itemData->isSomethingSet()) 02386 n += *itemData; 02387 02388 array->at(z) = n; 02389 } 02390 02391 m_attributeArrays.insert(schema, array); 02392 02393 return array; 02394 } 02395 02396 void Highlight::getItemDataListCopy (uint schema, ItemDataList &outlist) 02397 { 02398 ItemDataList itemDataList; 02399 getItemDataList(schema, itemDataList); 02400 02401 outlist.clear (); 02402 outlist.setAutoDelete (true); 02403 for (uint z=0; z < itemDataList.count(); z++) 02404 outlist.append (new ItemData (*itemDataList.at(z))); 02405 } 02406 02407 //END 02408 02409 //BEGIN HlManager 02410 HlManager::HlManager() 02411 : QObject() 02412 , m_config ("katesyntaxhighlightingrc", false, false) 02413 , commonSuffixes (QStringList::split(";", ".orig;.new;~;.bak;.BAK")) 02414 , syntax (new SyntaxDocument()) 02415 { 02416 hlList.setAutoDelete(true); 02417 hlDict.setAutoDelete(false); 02418 02419 SyntaxModeList modeList = syntax->modeList(); 02420 for (uint i=0; i < modeList.count(); i++) 02421 { 02422 Highlight *hl = new Highlight(modeList.at(i)); 02423 02424 uint insert = 0; 02425 for (; insert <= hlList.count(); insert++) 02426 { 02427 if (insert == hlList.count()) 02428 break; 02429 02430 if ( QString(hlList.at(insert)->section() + hlList.at(insert)->name()).lower() 02431 > QString(hl->section() + hl->name()).lower() ) 02432 break; 02433 } 02434 02435 hlList.insert (insert, hl); 02436 hlDict.insert (hl->name(), hl); 02437 } 02438 02439 // Normal HL 02440 Highlight *hl = new Highlight(0); 02441 hlList.prepend (hl); 02442 hlDict.insert (hl->name(), hl); 02443 } 02444 02445 HlManager::~HlManager() 02446 { 02447 delete syntax; 02448 } 02449 02450 static KStaticDeleter<HlManager> sdHlMan; 02451 02452 HlManager *HlManager::self() 02453 { 02454 if ( !s_self ) 02455 sdHlMan.setObject(s_self, new HlManager ()); 02456 02457 return s_self; 02458 } 02459 02460 Highlight *HlManager::getHl(int n) 02461 { 02462 if (n < 0 || n >= (int) hlList.count()) 02463 n = 0; 02464 02465 return hlList.at(n); 02466 } 02467 02468 int HlManager::nameFind(const QString &name) 02469 { 02470 int z (hlList.count() - 1); 02471 for (; z > 0; z--) 02472 if (hlList.at(z)->name() == name) 02473 return z; 02474 02475 return z; 02476 } 02477 02478 int HlManager::detectHighlighting (KateDocument *doc) 02479 { 02480 int hl = wildcardFind( doc->url().filename() ); 02481 02482 if (hl == -1) 02483 { 02484 QByteArray buf (KATE_HL_HOWMANY); 02485 uint bufpos = 0; 02486 for (uint i=0; i < doc->numLines(); i++) 02487 { 02488 QString line = doc->textLine( i ); 02489 uint len = line.length() + 1; 02490 02491 if (bufpos + len > KATE_HL_HOWMANY) 02492 len = KATE_HL_HOWMANY - bufpos; 02493 02494 memcpy(&buf[bufpos], (line + "\n").latin1(), len); 02495 02496 bufpos += len; 02497 02498 if (bufpos >= KATE_HL_HOWMANY) 02499 break; 02500 } 02501 buf.resize( bufpos ); 02502 02503 hl = mimeFind (buf); 02504 } 02505 02506 return hl; 02507 } 02508 02509 int HlManager::wildcardFind(const QString &fileName) 02510 { 02511 int result = -1; 02512 if ((result = realWildcardFind(fileName)) != -1) 02513 return result; 02514 02515 int length = fileName.length(); 02516 QString backupSuffix = KateDocumentConfig::global()->backupSuffix(); 02517 if (fileName.endsWith(backupSuffix)) { 02518 if ((result = realWildcardFind(fileName.left(length - backupSuffix.length()))) != -1) 02519 return result; 02520 } 02521 02522 for (QStringList::Iterator it = commonSuffixes.begin(); it != commonSuffixes.end(); ++it) { 02523 if (*it != backupSuffix && fileName.endsWith(*it)) { 02524 if ((result = realWildcardFind(fileName.left(length - (*it).length()))) != -1) 02525 return result; 02526 } 02527 } 02528 02529 return -1; 02530 } 02531 02532 int HlManager::realWildcardFind(const QString &fileName) 02533 { 02534 static QRegExp sep("\\s*;\\s*"); 02535 02536 QPtrList<Highlight> highlights; 02537 02538 for (Highlight *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) { 02539 highlight->loadWildcards(); 02540 02541 for (QStringList::Iterator it = highlight->getPlainExtensions().begin(); it != highlight->getPlainExtensions().end(); ++it) 02542 if (fileName.endsWith((*it))) 02543 highlights.append(highlight); 02544 02545 for (int i = 0; i < (int)highlight->getRegexpExtensions().count(); i++) { 02546 QRegExp re = highlight->getRegexpExtensions()[i]; 02547 if (re.exactMatch(fileName)) 02548 highlights.append(highlight); 02549 } 02550 } 02551 02552 if ( !highlights.isEmpty() ) 02553 { 02554 int pri = -1; 02555 int hl = -1; 02556 02557 for (Highlight *highlight = highlights.first(); highlight != 0L; highlight = highlights.next()) 02558 { 02559 if (highlight->priority() > pri) 02560 { 02561 pri = highlight->priority(); 02562 hl = hlList.findRef (highlight); 02563 } 02564 } 02565 02566 return hl; 02567 } 02568 02569 return -1; 02570 } 02571 02572 int HlManager::mimeFind(const QByteArray &contents) 02573 { 02574 static QRegExp sep("\\s*;\\s*"); 02575 02576 int accuracy = 0; 02577 KMimeType::Ptr mt = KMimeType::findByContent( contents, &accuracy ); 02578 02579 QPtrList<Highlight> highlights; 02580 02581 for (Highlight *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) 02582 { 02583 QStringList l = QStringList::split( sep, highlight->getMimetypes() ); 02584 02585 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) 02586 { 02587 if ( *it == mt->name() ) // faster than a regexp i guess? 02588 highlights.append (highlight); 02589 } 02590 } 02591 02592 if ( !highlights.isEmpty() ) 02593 { 02594 int pri = -1; 02595 int hl = -1; 02596 02597 for (Highlight *highlight = highlights.first(); highlight != 0L; highlight = highlights.next()) 02598 { 02599 if (highlight->priority() > pri) 02600 { 02601 pri = highlight->priority(); 02602 hl = hlList.findRef (highlight); 02603 } 02604 } 02605 02606 return hl; 02607 } 02608 02609 return -1; 02610 } 02611 02612 uint HlManager::defaultStyles() 02613 { 02614 return 10; 02615 } 02616 02617 QString HlManager::defaultStyleName(int n) 02618 { 02619 static QStringList names; 02620 02621 if (names.isEmpty()) 02622 { 02623 names << i18n("Normal"); 02624 names << i18n("Keyword"); 02625 names << i18n("Data Type"); 02626 names << i18n("Decimal/Value"); 02627 names << i18n("Base-N Integer"); 02628 names << i18n("Floating Point"); 02629 names << i18n("Character"); 02630 names << i18n("String"); 02631 names << i18n("Comment"); 02632 names << i18n("Others"); 02633 } 02634 02635 return names[n]; 02636 } 02637 02638 void HlManager::getDefaults(uint schema, KateAttributeList &list) 02639 { 02640 list.setAutoDelete(true); 02641 02642 KateAttribute* normal = new KateAttribute(); 02643 normal->setTextColor(Qt::black); 02644 normal->setSelectedTextColor(Qt::white); 02645 list.append(normal); 02646 02647 KateAttribute* keyword = new KateAttribute(); 02648 keyword->setTextColor(Qt::black); 02649 keyword->setSelectedTextColor(Qt::white); 02650 keyword->setBold(true); 02651 list.append(keyword); 02652 02653 KateAttribute* dataType = new KateAttribute(); 02654 dataType->setTextColor(Qt::darkRed); 02655 dataType->setSelectedTextColor(Qt::white); 02656 list.append(dataType); 02657 02658 KateAttribute* decimal = new KateAttribute(); 02659 decimal->setTextColor(Qt::blue); 02660 decimal->setSelectedTextColor(Qt::cyan); 02661 list.append(decimal); 02662 02663 KateAttribute* basen = new KateAttribute(); 02664 basen->setTextColor(Qt::darkCyan); 02665 basen->setSelectedTextColor(Qt::cyan); 02666 list.append(basen); 02667 02668 KateAttribute* floatAttribute = new KateAttribute(); 02669 floatAttribute->setTextColor(Qt::darkMagenta); 02670 floatAttribute->setSelectedTextColor(Qt::cyan); 02671 list.append(floatAttribute); 02672 02673 KateAttribute* charAttribute = new KateAttribute(); 02674 charAttribute->setTextColor(Qt::magenta); 02675 charAttribute->setSelectedTextColor(Qt::magenta); 02676 list.append(charAttribute); 02677 02678 KateAttribute* string = new KateAttribute(); 02679 string->setTextColor(Qt::red); 02680 string->setSelectedTextColor(Qt::red); 02681 list.append(string); 02682 02683 KateAttribute* comment = new KateAttribute(); 02684 comment->setTextColor(Qt::darkGray); 02685 comment->setSelectedTextColor(Qt::gray); 02686 comment->setItalic(true); 02687 list.append(comment); 02688 02689 KateAttribute* others = new KateAttribute(); 02690 others->setTextColor(Qt::darkGreen); 02691 others->setSelectedTextColor(Qt::green); 02692 list.append(others); 02693 02694 KConfig *config = HlManager::self()->self()->getKConfig(); 02695 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema)); 02696 02697 for (uint z = 0; z < defaultStyles(); z++) 02698 { 02699 KateAttribute *i = list.at(z); 02700 QStringList s = config->readListEntry(defaultStyleName(z)); 02701 02702 if (!s.isEmpty()) 02703 { 02704 while( s.count()<8) 02705 s << ""; 02706 02707 QString tmp; 02708 QRgb col; 02709 02710 tmp=s[0]; if (!tmp.isEmpty()) { 02711 col=tmp.toUInt(0,16); i->setTextColor(col); } 02712 02713 tmp=s[1]; if (!tmp.isEmpty()) { 02714 col=tmp.toUInt(0,16); i->setSelectedTextColor(col); } 02715 02716 tmp=s[2]; if (!tmp.isEmpty()) i->setBold(tmp!="0"); 02717 02718 tmp=s[3]; if (!tmp.isEmpty()) i->setItalic(tmp!="0"); 02719 02720 tmp=s[4]; if (!tmp.isEmpty()) i->setStrikeOut(tmp!="0"); 02721 02722 tmp=s[5]; if (!tmp.isEmpty()) i->setUnderline(tmp!="0"); 02723 02724 tmp=s[6]; if (!tmp.isEmpty()) { 02725 col=tmp.toUInt(0,16); i->setBGColor(col); } 02726 02727 tmp=s[7]; if (!tmp.isEmpty()) { 02728 col=tmp.toUInt(0,16); i->setSelectedBGColor(col); } 02729 02730 } 02731 02732 } 02733 } 02734 02735 void HlManager::setDefaults(uint schema, KateAttributeList &list) 02736 { 02737 KConfig *config = HlManager::self()->self()->getKConfig(); 02738 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema)); 02739 02740 for (uint z = 0; z < defaultStyles(); z++) 02741 { 02742 QStringList settings; 02743 KateAttribute *i = list.at(z); 02744 02745 settings<<(i->itemSet(KateAttribute::TextColor)?QString::number(i->textColor().rgb(),16):""); 02746 settings<<(i->itemSet(KateAttribute::SelectedTextColor)?QString::number(i->selectedTextColor().rgb(),16):""); 02747 settings<<(i->itemSet(KateAttribute::Weight)?(i->bold()?"1":"0"):""); 02748 settings<<(i->itemSet(KateAttribute::Italic)?(i->italic()?"1":"0"):""); 02749 settings<<(i->itemSet(KateAttribute::StrikeOut)?(i->strikeOut()?"1":"0"):""); 02750 settings<<(i->itemSet(KateAttribute::Underline)?(i->underline()?"1":"0"):""); 02751 settings<<(i->itemSet(KateAttribute::BGColor)?QString::number(i->bgColor().rgb(),16):""); 02752 settings<<(i->itemSet(KateAttribute::SelectedBGColor)?QString::number(i->selectedBGColor().rgb(),16):""); 02753 settings<<"---"; 02754 02755 config->writeEntry(defaultStyleName(z),settings); 02756 } 02757 02758 emit changed(); 02759 } 02760 02761 int HlManager::highlights() 02762 { 02763 return (int) hlList.count(); 02764 } 02765 02766 QString HlManager::hlName(int n) 02767 { 02768 return hlList.at(n)->name(); 02769 } 02770 02771 QString HlManager::hlSection(int n) 02772 { 02773 return hlList.at(n)->section(); 02774 } 02775 02776 QString HlManager::identifierForName(const QString& name) 02777 { 02778 Highlight *hl = 0; 02779 02780 if ((hl = hlDict[name])) 02781 return hl->getIdentifier (); 02782 02783 return QString(); 02784 } 02785 //END 02786 02787 void KateViewHighlightAction::init() 02788 { 02789 m_doc = 0; 02790 subMenus.setAutoDelete( true ); 02791 02792 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow())); 02793 } 02794 02795 void KateViewHighlightAction::updateMenu (Kate::Document *doc) 02796 { 02797 m_doc = doc; 02798 } 02799 02800 void KateViewHighlightAction::slotAboutToShow() 02801 { 02802 Kate::Document *doc=m_doc; 02803 int count = HlManager::self()->highlights(); 02804 02805 for (int z=0; z<count; z++) 02806 { 02807 QString hlName = HlManager::self()->hlName (z); 02808 QString hlSection = HlManager::self()->hlSection (z); 02809 02810 if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) ) 02811 { 02812 if (subMenusName.contains(hlSection) < 1) 02813 { 02814 subMenusName << hlSection; 02815 QPopupMenu *menu = new QPopupMenu (); 02816 subMenus.append(menu); 02817 popupMenu()->insertItem (hlSection, menu); 02818 } 02819 02820 int m = subMenusName.findIndex (hlSection); 02821 names << hlName; 02822 subMenus.at(m)->insertItem ( hlName, this, SLOT(setHl(int)), 0, z); 02823 } 02824 else if (names.contains(hlName) < 1) 02825 { 02826 names << hlName; 02827 popupMenu()->insertItem ( hlName, this, SLOT(setHl(int)), 0, z); 02828 } 02829 } 02830 02831 if (!doc) return; 02832 02833 for (uint i=0;i<subMenus.count();i++) 02834 { 02835 for (uint i2=0;i2<subMenus.at(i)->count();i2++) 02836 subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false); 02837 } 02838 popupMenu()->setItemChecked (0, false); 02839 02840 int i = subMenusName.findIndex (HlManager::self()->hlSection(doc->hlMode())); 02841 if (i >= 0 && subMenus.at(i)) 02842 subMenus.at(i)->setItemChecked (doc->hlMode(), true); 02843 else 02844 popupMenu()->setItemChecked (0, true); 02845 } 02846 02847 void KateViewHighlightAction::setHl (int mode) 02848 { 02849 Kate::Document *doc=m_doc; 02850 02851 if (doc) 02852 doc->setHlMode((uint)mode); 02853 } 02854 02855 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:16:26 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003