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_NOOP("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 } 01488 01489 HlContext *Highlight::contextNum (uint n) 01490 { 01491 return contextList[n]; 01492 } 01493 01494 /******************************************************************************************* 01495 Highlight - createItemData 01496 This function reads the itemData entries from the config file, which specifies the 01497 default attribute styles for matched items/contexts. 01498 01499 * input: none 01500 ************* 01501 * output: ItemDataList &list :A reference to the internal 01502 list containing the parsed 01503 default config 01504 ************* 01505 * return value: none 01506 *******************************************************************************************/ 01507 01508 void Highlight::createItemData(ItemDataList &list) 01509 { 01510 // If no highlighting is selected we need only one default. 01511 if (noHl) 01512 { 01513 list.append(new ItemData(I18N_NOOP("Normal Text"), dsNormal)); 01514 return; 01515 } 01516 01517 // If the internal list isn't already available read the config file 01518 if (internalIDList.isEmpty()) 01519 makeContextList(); 01520 01521 list=internalIDList; 01522 } 01523 01524 void Highlight::addToItemDataList() 01525 { 01526 //Tell the syntax document class which file we want to parse and which data group 01527 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01528 syntaxContextData *data = HlManager::self()->syntax->getGroupInfo("highlighting","itemData"); 01529 01530 //begin with the real parsing 01531 while (HlManager::self()->syntax->nextGroup(data)) 01532 { 01533 // read all attributes 01534 QString color = HlManager::self()->syntax->groupData(data,QString("color")); 01535 QString selColor = HlManager::self()->syntax->groupData(data,QString("selColor")); 01536 QString bold = HlManager::self()->syntax->groupData(data,QString("bold")); 01537 QString italic = HlManager::self()->syntax->groupData(data,QString("italic")); 01538 QString underline = HlManager::self()->syntax->groupData(data,QString("underline")); 01539 QString strikeOut = HlManager::self()->syntax->groupData(data,QString("strikeOut")); 01540 QString bgColor = HlManager::self()->syntax->groupData(data,QString("backgroundColor")); 01541 QString selBgColor = HlManager::self()->syntax->groupData(data,QString("selBackgroundColor")); 01542 01543 ItemData* newData = new ItemData( 01544 buildPrefix+HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(), 01545 getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum")))); 01546 01547 01548 /* here the custom style overrides are specified, if needed */ 01549 if (!color.isEmpty()) newData->setTextColor(QColor(color)); 01550 if (!selColor.isEmpty()) newData->setSelectedTextColor(QColor(selColor)); 01551 if (!bold.isEmpty()) newData->setBold(bold=="true" || bold=="1"); 01552 if (!italic.isEmpty()) newData->setItalic(italic=="true" || italic=="1"); 01553 // new attributes for the new rendering view 01554 if (!underline.isEmpty()) newData->setUnderline(underline=="true" || underline=="1"); 01555 if (!strikeOut.isEmpty()) newData->setStrikeOut(strikeOut=="true" || strikeOut=="1"); 01556 if (!bgColor.isEmpty()) newData->setBGColor(QColor(bgColor)); 01557 if (!selBgColor.isEmpty()) newData->setSelectedBGColor(QColor(selBgColor)); 01558 01559 internalIDList.append(newData); 01560 } 01561 01562 //clean up 01563 if (data) 01564 HlManager::self()->syntax->freeGroupInfo(data); 01565 } 01566 01567 /******************************************************************************************* 01568 Highlight - lookupAttrName 01569 This function is a helper for makeContextList and createHlItem. It looks the given 01570 attribute name in the itemData list up and returns it's index 01571 01572 * input: QString &name :the attribute name to lookup 01573 * ItemDataList &iDl :the list containing all 01574 * available attributes 01575 ************* 01576 * output: none 01577 ************* 01578 * return value: int :The index of the attribute 01579 * or 0 01580 *******************************************************************************************/ 01581 01582 int Highlight::lookupAttrName(const QString& name, ItemDataList &iDl) 01583 { 01584 for (uint i = 0; i < iDl.count(); i++) 01585 if (iDl.at(i)->name == buildPrefix+name) 01586 return i; 01587 01588 kdDebug(13010)<<"Couldn't resolve itemDataName"<<endl; 01589 return 0; 01590 } 01591 01592 /******************************************************************************************* 01593 Highlight - createHlItem 01594 This function is a helper for makeContextList. It parses the xml file for 01595 information, how single or multi line comments are marked 01596 01597 * input: syntaxContextData *data : Data about the item read from 01598 * the xml file 01599 * ItemDataList &iDl : List of all available itemData 01600 * entries. Needed for attribute 01601 * name->index translation 01602 * QStringList *RegionList : list of code folding region names 01603 * QStringList ContextList : list of context names 01604 ************* 01605 * output: none 01606 ************* 01607 * return value: HlItem * : Pointer to the newly created item 01608 * object 01609 *******************************************************************************************/ 01610 01611 HlItem *Highlight::createHlItem(struct syntaxContextData *data, ItemDataList &iDl,QStringList *RegionList, QStringList *ContextNameList) 01612 { 01613 // No highlighting -> exit 01614 if (noHl) 01615 return 0; 01616 01617 // get the (tagname) itemd type 01618 QString dataname=HlManager::self()->syntax->groupItemData(data,QString("")); 01619 01620 // BEGIN - Translation of the attribute parameter 01621 QString tmpAttr=HlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace(); 01622 int attr; 01623 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) 01624 { 01625 errorsAndWarnings+=i18n("<B>%1</B>: Deprecated syntax. Attribute (%2) not addressed by symbolic name<BR>"). 01626 arg(buildIdentifier).arg(tmpAttr); 01627 attr=tmpAttr.toInt(); 01628 } 01629 else 01630 attr=lookupAttrName(tmpAttr,iDl); 01631 // END - Translation of the attribute parameter 01632 01633 // Info about context switch 01634 int context; 01635 QString tmpcontext=HlManager::self()->syntax->groupItemData(data,QString("context")); 01636 01637 01638 QString unresolvedContext; 01639 context=getIdFromString(ContextNameList, tmpcontext,unresolvedContext); 01640 01641 // Get the char parameter (eg DetectChar) 01642 char chr; 01643 if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty()) 01644 chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0]; 01645 else 01646 chr=0; 01647 01648 // Get the String parameter (eg. StringDetect) 01649 QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String")); 01650 01651 // Get a second char parameter (char1) (eg Detect2Chars) 01652 char chr1; 01653 if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty()) 01654 chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0]; 01655 else 01656 chr1=0; 01657 01658 // Will be removed eventuall. Atm used for StringDetect 01659 bool insensitive=( HlManager::self()->syntax->groupItemData(data,QString("insensitive")).lower() == QString("true") ); 01660 // anders: very reasonable for regexp too! 01661 01662 // for regexp only 01663 bool minimal = ( HlManager::self()->syntax->groupItemData(data,QString("minimal")).lower() == QString("true") ); 01664 01665 01666 // code folding region handling: 01667 QString beginRegionStr=HlManager::self()->syntax->groupItemData(data,QString("beginRegion")); 01668 QString endRegionStr=HlManager::self()->syntax->groupItemData(data,QString("endRegion")); 01669 01670 signed char regionId=0; 01671 signed char regionId2=0; 01672 01673 if (!beginRegionStr.isEmpty()) 01674 { 01675 regionId = RegionList->findIndex(beginRegionStr); 01676 01677 if (regionId==-1) // if the region name doesn't already exist, add it to the list 01678 { 01679 (*RegionList)<<beginRegionStr; 01680 regionId = RegionList->findIndex(beginRegionStr); 01681 } 01682 01683 regionId++; 01684 01685 kdDebug () << "########### BEG REG: " << beginRegionStr << " NUM: " << regionId << endl; 01686 } 01687 01688 if (!endRegionStr.isEmpty()) 01689 { 01690 regionId2 = RegionList->findIndex(endRegionStr); 01691 01692 if (regionId2==-1) // if the region name doesn't already exist, add it to the list 01693 { 01694 (*RegionList)<<endRegionStr; 01695 regionId2 = RegionList->findIndex(endRegionStr); 01696 } 01697 01698 regionId2 = -regionId2 - 1; 01699 01700 kdDebug () << "########### END REG: " << endRegionStr << " NUM: " << regionId2 << endl; 01701 } 01702 01703 //Create the item corresponding to it's type and set it's parameters 01704 HlItem *tmpItem; 01705 01706 if (dataname=="keyword") 01707 { 01708 HlKeyword *keyword=new HlKeyword(attr,context,regionId,regionId2,casesensitive, 01709 deliminator); 01710 01711 //Get the entries for the keyword lookup list 01712 keyword->addList(HlManager::self()->syntax->finddata("highlighting",stringdata)); 01713 tmpItem=keyword; 01714 } else 01715 if (dataname=="Float") tmpItem= (new HlFloat(attr,context,regionId,regionId2)); else 01716 if (dataname=="Int") tmpItem=(new HlInt(attr,context,regionId,regionId2)); else 01717 if (dataname=="DetectChar") tmpItem=(new HlCharDetect(attr,context,regionId,regionId2,chr)); else 01718 if (dataname=="Detect2Chars") tmpItem=(new Hl2CharDetect(attr,context,regionId,regionId2,chr,chr1)); else 01719 if (dataname=="RangeDetect") tmpItem=(new HlRangeDetect(attr,context,regionId,regionId2, chr, chr1)); else 01720 if (dataname=="LineContinue") tmpItem=(new HlLineContinue(attr,context,regionId,regionId2)); else 01721 if (dataname=="StringDetect") tmpItem=(new HlStringDetect(attr,context,regionId,regionId2,stringdata,insensitive)); else 01722 if (dataname=="AnyChar") tmpItem=(new HlAnyChar(attr,context,regionId,regionId2,stringdata)); else 01723 if (dataname=="RegExpr") tmpItem=(new HlRegExpr(attr,context,regionId,regionId2,stringdata, insensitive, minimal)); else 01724 if (dataname=="HlCChar") tmpItem= ( new HlCChar(attr,context,regionId,regionId2));else 01725 if (dataname=="HlCHex") tmpItem= (new HlCHex(attr,context,regionId,regionId2));else 01726 if (dataname=="HlCOct") tmpItem= (new HlCOct(attr,context,regionId,regionId2)); else 01727 if (dataname=="HlCFloat") tmpItem= (new HlCFloat(attr,context,regionId,regionId2)); else 01728 if (dataname=="HlCStringChar") tmpItem= (new HlCStringChar(attr,context,regionId,regionId2)); else 01729 01730 { 01731 // oops, unknown type. Perhaps a spelling error in the xml file 01732 return 0; 01733 } 01734 01735 if (!unresolvedContext.isEmpty()) 01736 { 01737 unresolvedContextReferences.insert(&(tmpItem->ctx),unresolvedContext); 01738 } 01739 return tmpItem; 01740 } 01741 01742 01743 /******************************************************************************************* 01744 Highlight - isInWord 01745 01746 * input: Qchar c Character to investigate 01747 ************* 01748 * output: none 01749 ************* 01750 * return value: returns true, if c is no deliminator 01751 *******************************************************************************************/ 01752 01753 bool Highlight::isInWord(QChar c) 01754 { 01755 static const QString sq("\"'"); 01756 return deliminator.find(c) == -1 && sq.find(c) == -1; 01757 } 01758 01759 /******************************************************************************************* 01760 Highlight - readCommentConfig 01761 This function is a helper for makeContextList. It parses the xml file for 01762 information, how single or multi line comments are marked 01763 01764 * input: none 01765 ************* 01766 * output: none 01767 ************* 01768 * return value: none 01769 *******************************************************************************************/ 01770 01771 void Highlight::readCommentConfig() 01772 { 01773 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01774 syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("general","comment"); 01775 01776 if (data) 01777 { 01778 while (HlManager::self()->syntax->nextGroup(data)) 01779 { 01780 if (HlManager::self()->syntax->groupData(data,"name")=="singleLine") 01781 cslStart=HlManager::self()->syntax->groupData(data,"start"); 01782 01783 if (HlManager::self()->syntax->groupData(data,"name")=="multiLine") 01784 { 01785 cmlStart=HlManager::self()->syntax->groupData(data,"start"); 01786 cmlEnd=HlManager::self()->syntax->groupData(data,"end"); 01787 } 01788 } 01789 01790 HlManager::self()->syntax->freeGroupInfo(data); 01791 } 01792 else 01793 { 01794 cslStart = ""; 01795 cmlStart = ""; 01796 cmlEnd = ""; 01797 } 01798 } 01799 01800 /******************************************************************************************* 01801 Highlight - readGlobalKeyWordConfig 01802 This function is a helper for makeContextList. It parses the xml file for 01803 information, if keywords should be treated case(in)sensitive and creates the keyword 01804 delimiter list. Which is the default list, without any given weak deliminiators 01805 01806 * input: none 01807 ************* 01808 * output: none 01809 ************* 01810 * return value: none 01811 *******************************************************************************************/ 01812 01813 01814 void Highlight::readGlobalKeywordConfig() 01815 { 01816 // Tell the syntax document class which file we want to parse 01817 kdDebug(13010)<<"readGlobalKeywordConfig:BEGIN"<<endl; 01818 01819 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01820 syntaxContextData *data = HlManager::self()->syntax->getConfig("general","keywords"); 01821 01822 if (data) 01823 { 01824 kdDebug(13010)<<"Found global keyword config"<<endl; 01825 01826 if (HlManager::self()->syntax->groupItemData(data,QString("casesensitive"))!="0") 01827 casesensitive=true; 01828 else 01829 casesensitive=false; 01830 01831 //get the weak deliminators 01832 weakDeliminator=(HlManager::self()->syntax->groupItemData(data,QString("weakDeliminator"))); 01833 01834 kdDebug(13010)<<"weak delimiters are: "<<weakDeliminator<<endl; 01835 01836 // remove any weakDelimitars (if any) from the default list and store this list. 01837 for (uint s=0; s < weakDeliminator.length(); s++) 01838 { 01839 int f = deliminator.find (weakDeliminator[s]); 01840 01841 if (f > -1) 01842 deliminator.remove (f, 1); 01843 } 01844 01845 QString addDelim = (HlManager::self()->syntax->groupItemData(data,QString("additionalDeliminator"))); 01846 01847 if (!addDelim.isEmpty()) 01848 deliminator=deliminator+addDelim; 01849 01850 HlManager::self()->syntax->freeGroupInfo(data); 01851 } 01852 else 01853 { 01854 //Default values 01855 casesensitive=true; 01856 weakDeliminator=QString(""); 01857 } 01858 01859 kdDebug(13010)<<"readGlobalKeywordConfig:END"<<endl; 01860 01861 kdDebug(13010)<<"delimiterCharacters are: "<<deliminator<<endl; 01862 } 01863 01864 01865 void Highlight::readFoldingConfig() 01866 { 01867 // Tell the syntax document class which file we want to parse 01868 kdDebug(13010)<<"readfoldignConfig:BEGIN"<<endl; 01869 01870 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01871 syntaxContextData *data = HlManager::self()->syntax->getConfig("general","folding"); 01872 01873 if (data) 01874 { 01875 kdDebug(13010)<<"Found global keyword config"<<endl; 01876 01877 if (HlManager::self()->syntax->groupItemData(data,QString("indentationsensitive"))!="1") 01878 m_foldingIndentationSensitive=false; 01879 else 01880 m_foldingIndentationSensitive=true; 01881 01882 HlManager::self()->syntax->freeGroupInfo(data); 01883 } 01884 else 01885 { 01886 //Default values 01887 m_foldingIndentationSensitive = false; 01888 } 01889 01890 kdDebug(13010)<<"readfoldingConfig:END"<<endl; 01891 01892 kdDebug(13010)<<"############################ use indent for fold are: "<<m_foldingIndentationSensitive<<endl; 01893 } 01894 01895 void Highlight::createContextNameList(QStringList *ContextNameList,int ctx0) 01896 { 01897 kdDebug(13010)<<"creatingContextNameList:BEGIN"<<endl; 01898 01899 if (ctx0 == 0) 01900 ContextNameList->clear(); 01901 01902 HlManager::self()->syntax->setIdentifier(buildIdentifier); 01903 01904 syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("highlighting","context"); 01905 01906 int id=ctx0; 01907 01908 if (data) 01909 { 01910 while (HlManager::self()->syntax->nextGroup(data)) 01911 { 01912 QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(); 01913 if (tmpAttr.isEmpty()) 01914 { 01915 tmpAttr=QString("!KATE_INTERNAL_DUMMY! %1").arg(id); 01916 errorsAndWarnings +=i18n("<B>%1</B>: Deprecated syntax. Context %2 has no symbolic name<BR>").arg(buildIdentifier).arg(id-ctx0); 01917 } 01918 else tmpAttr=buildPrefix+tmpAttr; 01919 (*ContextNameList)<<tmpAttr; 01920 id++; 01921 } 01922 HlManager::self()->syntax->freeGroupInfo(data); 01923 } 01924 kdDebug(13010)<<"creatingContextNameList:END"<<endl; 01925 01926 } 01927 01928 int Highlight::getIdFromString(QStringList *ContextNameList, QString tmpLineEndContext, /*NO CONST*/ QString &unres) 01929 { 01930 unres=""; 01931 int context; 01932 if ((tmpLineEndContext=="#stay") || (tmpLineEndContext.simplifyWhiteSpace().isEmpty())) context=-1; 01933 else if (tmpLineEndContext.startsWith("#pop")) 01934 { 01935 context=-1; 01936 for(;tmpLineEndContext.startsWith("#pop");context--) 01937 { 01938 tmpLineEndContext.remove(0,4); 01939 kdDebug(13010)<<"#pop found"<<endl; 01940 } 01941 } 01942 else 01943 if ( tmpLineEndContext.startsWith("##")) 01944 { 01945 QString tmp=tmpLineEndContext.right(tmpLineEndContext.length()-2); 01946 if (!embeddedHls.contains(tmp)) embeddedHls.insert(tmp,EmbeddedHlInfo()); 01947 unres=tmp; 01948 context=0; 01949 } 01950 else 01951 { 01952 context=ContextNameList->findIndex(buildPrefix+tmpLineEndContext); 01953 if (context==-1) 01954 { 01955 context=tmpLineEndContext.toInt(); 01956 errorsAndWarnings+=i18n("<B>%1</B>:Deprecated syntax. Context %2 not addressed by a symbolic name").arg(buildIdentifier).arg(tmpLineEndContext); 01957 } 01958 //#warning restructure this the name list storage. 01959 // context=context+buildContext0Offset; 01960 } 01961 return context; 01962 } 01963 01964 /******************************************************************************************* 01965 Highlight - makeContextList 01966 That's the most important initialization function for each highlighting. It's called 01967 each time a document gets a highlighting style assigned. parses the xml file and 01968 creates a corresponding internal structure 01969 01970 * input: none 01971 ************* 01972 * output: none 01973 ************* 01974 * return value: none 01975 *******************************************************************************************/ 01976 01977 void Highlight::makeContextList() 01978 { 01979 if (noHl) // if this a highlighting for "normal texts" only, tere is no need for a context list creation 01980 return; 01981 01982 embeddedHls.clear(); 01983 unresolvedContextReferences.clear(); 01984 RegionList.clear(); 01985 ContextNameList.clear(); 01986 01987 // prepare list creation. To reuse as much code as possible handle this highlighting the same way as embedded onces 01988 embeddedHls.insert(iName,EmbeddedHlInfo()); 01989 01990 bool something_changed; 01991 int startctx=0; // the context "0" id is 0 for this hl, all embedded context "0"s have offsets 01992 building=true; // inform everybody that we are building the highlighting contexts and itemlists 01993 do 01994 { 01995 kdDebug(13010)<<"**************** Outter loop in make ContextList"<<endl; 01996 kdDebug(13010)<<"**************** Hl List count:"<<embeddedHls.count()<<endl; 01997 something_changed=false; //assume all "embedded" hls have already been loaded 01998 for (EmbeddedHlInfos::const_iterator it=embeddedHls.begin(); it!=embeddedHls.end();++it) 01999 { 02000 if (!it.data().loaded) // we found one, we still have to load 02001 { 02002 kdDebug(13010)<<"**************** Inner loop in make ContextList"<<endl; 02003 QString identifierToUse; 02004 kdDebug(13010)<<"Trying to open highlighting definition file: "<< it.key()<<endl; 02005 if (iName==it.key()) identifierToUse=identifier; // the own identifier is known 02006 else 02007 identifierToUse=HlManager::self()->identifierForName(it.key()); // all others have to be looked up 02008 02009 kdDebug(13010)<<"Location is:"<< identifierToUse<<endl; 02010 02011 buildPrefix=it.key()+':'; // attribute names get prefixed by the names of the highlighting definitions they belong to 02012 02013 if (identifierToUse.isEmpty() ) kdDebug()<<"OHOH, unknown highlighting description referenced"<<endl; 02014 02015 kdDebug()<<"setting ("<<it.key()<<") to loaded"<<endl; 02016 it=embeddedHls.insert(it.key(),EmbeddedHlInfo(true,startctx)); //mark hl as loaded 02017 buildContext0Offset=startctx; //set class member for context 0 offset, so we don't need to pass it around 02018 startctx=addToContextList(identifierToUse,startctx); //parse one hl definition file 02019 if (noHl) return; // an error occurred 02020 something_changed=true; // something has been loaded 02021 02022 } 02023 } 02024 } while (something_changed); // as long as there has been another file parsed repeat everything, there could be newly added embedded hls. 02025 02026 02027 /* at this point all needed highlighing (sub)definitions are loaded. It's time to resolve cross file 02028 references (if there are some 02029 */ 02030 kdDebug(13010)<<"Unresolved contexts, which need attention: "<<unresolvedContextReferences.count()<<endl; 02031 //optimize this a littlebit 02032 for (UnresolvedContextReferences::iterator unresIt=unresolvedContextReferences.begin(); 02033 unresIt!=unresolvedContextReferences.end();++unresIt) 02034 { 02035 //try to find the context0 id for a given unresolvedReference 02036 EmbeddedHlInfos::const_iterator hlIt=embeddedHls.find(unresIt.data()); 02037 if (hlIt!=embeddedHls.end()) 02038 *(unresIt.key())=hlIt.data().context0; 02039 } 02040 02041 /*eventually handle IncludeRules items, if they exist. 02042 This has to be done after the cross file references, because it is allowed 02043 to include the context0 from a different definition, than the one the rule belongs to */ 02044 handleIncludeRules(); 02045 02046 embeddedHls.clear(); //save some memory. 02047 unresolvedContextReferences.clear(); //save some memory 02048 RegionList.clear(); // I think you get the idea ;) 02049 ContextNameList.clear(); 02050 02051 02052 // if there have been errors show them 02053 if (!errorsAndWarnings.isEmpty()) 02054 KMessageBox::detailedSorry(0L,i18n("There were warning(s) and/or error(s) while parsing the syntax highlighting configuration."), errorsAndWarnings, i18n("Kate Syntax Highlight Parser")); 02055 02056 // we have finished 02057 building=false; 02058 } 02059 02060 void Highlight::handleIncludeRules() 02061 { 02062 02063 // if there are noe include rules to take care of, just return 02064 kdDebug(13010)<<"IncludeRules, which need attention: " <<includeRules.count()<<endl; 02065 if (includeRules.isEmpty()) return; 02066 02067 buildPrefix=""; 02068 QString dummy; 02069 02070 /*by now the context0 references are resolved, now more or less only inner file references are resolved. 02071 If we decide that arbitrary inclusion is needed, this doesn't need to be changed, only the addToContextList 02072 method 02073 */ 02074 02075 //resolove context names 02076 for (IncludeRules::iterator it=includeRules.begin();it!=includeRules.end();) 02077 { 02078 02079 if ((*it)->incCtx==-1) // context unresolved ? 02080 { //yes 02081 02082 if ((*it)->incCtxN.isEmpty()) 02083 { 02084 // no context name given, and no valid context id set, so this item is going to be removed 02085 IncludeRules::iterator it1=it; 02086 ++it1; 02087 delete (*it); 02088 includeRules.remove(it); 02089 it=it1; 02090 } 02091 else 02092 { 02093 // resolve name to id 02094 (*it)->incCtx=getIdFromString(&ContextNameList,(*it)->incCtxN,dummy); 02095 kdDebug()<<"Resolved "<<(*it)->incCtxN<< " to "<<(*it)->incCtx<<" for include rule"<<endl; 02096 // It would be good to look here somehow, if the result is valid 02097 } 02098 } else ++it; //nothing to do, already resolved (by the cross defintion reference resolver 02099 } 02100 02101 // now that all IncludeRule items should be valid and completely resolved, do the real inclusion of the rules. 02102 // recursiveness is needed, because context 0 could include context 1, which itself includes context 2 and so on. 02103 // In that case we have to handle context 2 first, then 1, 0 02104 //TODO: catch circular references: eg 0->1->2->3->1 02105 while (!includeRules.isEmpty()) 02106 handleIncludeRulesRecursive(includeRules.begin(),&includeRules); 02107 02108 02109 } 02110 02111 void Highlight::handleIncludeRulesRecursive(IncludeRules::iterator it, IncludeRules *list) 02112 { 02113 if (it==list->end()) return; //invalid iterator, shouldn't happen, but better have a rule prepared ;) 02114 IncludeRules::iterator it1=it; 02115 int ctx=(*it1)->ctx; 02116 02117 /*find the last entry for the given context in the IncludeRules list 02118 this is need if one context includes more than one. This saves us from updating all insert positions: 02119 eg: context 0: 02120 pos 3 - include context 2 02121 pos 5 - include context 3 02122 During the building of the includeRules list the items are inserted in ascending order, now we need it 02123 descending to make our life easier. 02124 */ 02125 while ((it!=list->end()) && ((*it)->ctx==ctx)) 02126 { 02127 it1=it; 02128 ++it; 02129 // kdDebug()<<"loop1"<<endl; 02130 } 02131 // iterate over each include rule for the context the function has been called for. 02132 while ((it1!=list->end()) && ((*it1)->ctx==ctx)) 02133 { 02134 // kdDebug()<<"loop2"<<endl; 02135 02136 02137 int ctx1=(*it1)->incCtx; 02138 02139 //let's see, if the the included context includes other contexts 02140 for (IncludeRules::iterator it2=list->begin();it2!=list->end();++it2) 02141 { 02142 // kdDebug()<<"loop3"<<endl; 02143 02144 if ((*it2)->ctx==ctx1) 02145 { 02146 //yes it does, so first handle that include rules, since we want to 02147 // include those subincludes too 02148 handleIncludeRulesRecursive(it2,list); 02149 break; 02150 } 02151 } 02152 02153 // if the context we want to include had sub includes, they are already inserted there. 02154 HlContext *dest=contextList[ctx]; 02155 HlContext *src=contextList[ctx1]; 02156 uint p=(*it1)->pos; //insert the included context's rules starting at position p 02157 for ( HlItem *c = src->items.first(); c; c=src->items.next(), p++ ) 02158 dest->items.insert(p,c); 02159 02160 it=it1; //backup the iterator 02161 --it1; //move to the next entry, which has to be take care of 02162 delete (*it); //free the already handled data structure 02163 list->remove(it); // remove it from the list 02164 } 02165 } 02166 02167 int Highlight::addToContextList(const QString &ident, int ctx0) 02168 { 02169 buildIdentifier=ident; 02170 syntaxContextData *data, *datasub; 02171 HlItem *c; 02172 02173 QString dummy; 02174 02175 // Let the syntax document class know, which file we'd like to parse 02176 if (!HlManager::self()->syntax->setIdentifier(ident)) 02177 { 02178 noHl=true; 02179 KMessageBox::information(0L,i18n("Since there has been an error parsing the highlighting description, this highlighting will be disabled")); 02180 return 0; 02181 } 02182 02183 RegionList<<"!KateInternal_TopLevel!"; 02184 readCommentConfig(); 02185 readGlobalKeywordConfig(); 02186 readFoldingConfig (); 02187 02188 QString ctxName; 02189 02190 // This list is needed for the translation of the attribute parameter, if the itemData name is given instead of the index 02191 addToItemDataList(); 02192 ItemDataList iDl = internalIDList; 02193 02194 createContextNameList(&ContextNameList,ctx0); 02195 02196 kdDebug(13010)<<"Parsing Context structure"<<endl; 02197 //start the real work 02198 data=HlManager::self()->syntax->getGroupInfo("highlighting","context"); 02199 uint i=buildContext0Offset; 02200 if (data) 02201 { 02202 while (HlManager::self()->syntax->nextGroup(data)) 02203 { 02204 kdDebug(13010)<<"Found a context in file, building structure now"<<endl; 02205 // BEGIN - Translation of the attribute parameter 02206 QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace(); 02207 int attr; 02208 if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) 02209 attr=tmpAttr.toInt(); 02210 else 02211 attr=lookupAttrName(tmpAttr,iDl); 02212 // END - Translation of the attribute parameter 02213 02214 ctxName=buildPrefix+HlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace(); 02215 02216 QString tmpLineEndContext=HlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace(); 02217 int context; 02218 02219 context=getIdFromString(&ContextNameList, tmpLineEndContext,dummy); 02220 02221 // BEGIN get fallthrough props 02222 bool ft = false; 02223 int ftc = 0; // fallthrough context 02224 if ( i > 0 ) { // fallthrough is not smart in context 0 02225 QString tmpFt = HlManager::self()->syntax->groupData(data, QString("fallthrough") ); 02226 if ( tmpFt.lower() == "true" || tmpFt.toInt() == 1 ) 02227 ft = true; 02228 if ( ft ) { 02229 QString tmpFtc = HlManager::self()->syntax->groupData( data, QString("fallthroughContext") ); 02230 02231 ftc=getIdFromString(&ContextNameList, tmpFtc,dummy); 02232 if (ftc == -1) ftc =0; 02233 02234 kdDebug(13010)<<"Setting fall through context (context "<<i<<"): "<<ftc<<endl; 02235 } 02236 } 02237 02238 // END falltrhough props 02239 contextList.insert (i, new HlContext ( 02240 attr, 02241 context, 02242 (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1: 02243 (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt(), 02244 ft, ftc 02245 )); 02246 02247 02248 //Let's create all items for the context 02249 while (HlManager::self()->syntax->nextItem(data)) 02250 { 02251 // kdDebug(13010)<< "In make Contextlist: Item:"<<endl; 02252 02253 // IncludeRules : add a pointer to each item in that context 02254 02255 QString tag = HlManager::self()->syntax->groupItemData(data,QString("")); 02256 if ( tag == "IncludeRules" ) { //if the new item is an Include rule, we have to take special care 02257 QString incCtx=HlManager::self()->syntax->groupItemData( data, QString("context")); 02258 // only context refernces of type NAME and ##Name are allowed 02259 if (incCtx.startsWith("##") || (!incCtx.startsWith("#"))) { //#stay, #pop is not interesting here 02260 if (!incCtx.startsWith("#")) { // a local reference -> just initialize the include rule structure 02261 incCtx=buildPrefix+incCtx.simplifyWhiteSpace(); 02262 includeRules.append(new IncludeRule(i,contextList[i]->items.count(),incCtx)); 02263 } 02264 else { //a cross highlighting reference 02265 kdDebug()<<"Cross highlight reference <IncludeRules>"<<endl; 02266 IncludeRule *ir=new IncludeRule(i,contextList[i]->items.count()); 02267 //use the same way to determine cross hl file references as other items do 02268 if (!embeddedHls.contains(incCtx.right(incCtx.length()-2))) 02269 embeddedHls.insert(incCtx.right(incCtx.length()-2),EmbeddedHlInfo()); 02270 unresolvedContextReferences.insert(&(ir->incCtx), 02271 incCtx.right(incCtx.length()-2)); 02272 includeRules.append(ir); 02273 } 02274 } 02275 continue; 02276 } 02277 #if 0 02278 QString tag = HlManager::self()->syntax->groupItemData(data,QString("")); 02279 if ( tag == "IncludeRules" ) { 02280 // 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?) 02281 int ctxId = getIdFromString(&ContextNameList, 02282 HlManager::self()->syntax->groupItemData( data, QString("context")),dummy); // the index is *required* 02283 if ( ctxId > -1) { // we can even reuse rules of 0 if we want to:) 02284 kdDebug(13010)<<"makeContextList["<<i<<"]: including all items of context "<<ctxId<<endl; 02285 if ( ctxId < (int) i ) { // must be defined 02286 for ( c = contextList[ctxId]->items.first(); c; c = contextList[ctxId]->items.next() ) 02287 contextList[i]->items.append(c); 02288 } 02289 else 02290 kdDebug(13010)<<"Context "<<ctxId<<"not defined. You can not include the rules of an undefined context"<<endl; 02291 } 02292 continue; // while nextItem 02293 } 02294 #endif 02295 c=createHlItem(data,iDl,&RegionList,&ContextNameList); 02296 if (c) 02297 { 02298 contextList[i]->items.append(c); 02299 02300 // Not supported completely atm and only one level. Subitems.(all have to be matched to at once) 02301 datasub=HlManager::self()->syntax->getSubItems(data); 02302 bool tmpbool; 02303 if (tmpbool=HlManager::self()->syntax->nextItem(datasub)) 02304 { 02305 c->subItems=new QPtrList<HlItem>; 02306 for (;tmpbool;tmpbool=HlManager::self()->syntax->nextItem(datasub)) 02307 c->subItems->append(createHlItem(datasub,iDl,&RegionList,&ContextNameList)); 02308 } 02309 HlManager::self()->syntax->freeGroupInfo(datasub); 02310 // end of sublevel 02311 } 02312 // kdDebug(13010)<<"Last line in loop"<<endl; 02313 } 02314 i++; 02315 } 02316 } 02317 02318 HlManager::self()->syntax->freeGroupInfo(data); 02319 if (RegionList.count()!=1) folding=true; 02320 folding = folding || m_foldingIndentationSensitive; 02321 return i; 02322 } 02323 02324 void Highlight::clearAttributeArrays () 02325 { 02326 for ( QIntDictIterator< QMemArray<KateAttribute> > it( m_attributeArrays ); it.current(); ++it ) 02327 { 02328 // k, schema correct, let create the data 02329 KateAttributeList defaultStyleList; 02330 defaultStyleList.setAutoDelete(true); 02331 HlManager::self()->getDefaults(it.currentKey(), defaultStyleList); 02332 02333 ItemDataList itemDataList; 02334 getItemDataList(it.currentKey(), itemDataList); 02335 02336 uint nAttribs = itemDataList.count(); 02337 QMemArray<KateAttribute> *array = it.current(); 02338 array->resize (nAttribs); 02339 02340 for (uint z = 0; z < nAttribs; z++) 02341 { 02342 ItemData *itemData = itemDataList.at(z); 02343 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum); 02344 02345 if (itemData && itemData->isSomethingSet()) 02346 n += *itemData; 02347 02348 array->at(z) = n; 02349 } 02350 } 02351 } 02352 02353 QMemArray<KateAttribute> *Highlight::attributes (uint schema) 02354 { 02355 QMemArray<KateAttribute> *array; 02356 02357 // found it, allready floating around 02358 if ((array = m_attributeArrays[schema])) 02359 return array; 02360 02361 // ohh, not found, check if valid schema number 02362 if (!KateFactory::self()->schemaManager()->validSchema(schema)) 02363 { 02364 // uhh, not valid :/, stick with normal default schema, it's always there ! 02365 return attributes (0); 02366 } 02367 02368 // k, schema correct, let create the data 02369 KateAttributeList defaultStyleList; 02370 defaultStyleList.setAutoDelete(true); 02371 HlManager::self()->getDefaults(schema, defaultStyleList); 02372 02373 ItemDataList itemDataList; 02374 getItemDataList(schema, itemDataList); 02375 02376 uint nAttribs = itemDataList.count(); 02377 array = new QMemArray<KateAttribute> (nAttribs); 02378 02379 for (uint z = 0; z < nAttribs; z++) 02380 { 02381 ItemData *itemData = itemDataList.at(z); 02382 KateAttribute n = *defaultStyleList.at(itemData->defStyleNum); 02383 02384 if (itemData && itemData->isSomethingSet()) 02385 n += *itemData; 02386 02387 array->at(z) = n; 02388 } 02389 02390 m_attributeArrays.insert(schema, array); 02391 02392 return array; 02393 } 02394 02395 void Highlight::getItemDataListCopy (uint schema, ItemDataList &outlist) 02396 { 02397 ItemDataList itemDataList; 02398 getItemDataList(schema, itemDataList); 02399 02400 outlist.clear (); 02401 outlist.setAutoDelete (true); 02402 for (uint z=0; z < itemDataList.count(); z++) 02403 outlist.append (new ItemData (*itemDataList.at(z))); 02404 } 02405 02406 //END 02407 02408 //BEGIN HlManager 02409 HlManager::HlManager() 02410 : QObject() 02411 , m_config ("katesyntaxhighlightingrc", false, false) 02412 , commonSuffixes (QStringList::split(";", ".orig;.new;~;.bak;.BAK")) 02413 , syntax (new SyntaxDocument()) 02414 { 02415 hlList.setAutoDelete(true); 02416 hlDict.setAutoDelete(false); 02417 02418 SyntaxModeList modeList = syntax->modeList(); 02419 for (uint i=0; i < modeList.count(); i++) 02420 { 02421 Highlight *hl = new Highlight(modeList.at(i)); 02422 02423 uint insert = 0; 02424 for (; insert <= hlList.count(); insert++) 02425 { 02426 if (insert == hlList.count()) 02427 break; 02428 02429 if ( QString(hlList.at(insert)->section() + hlList.at(insert)->name()).lower() 02430 > QString(hl->section() + hl->name()).lower() ) 02431 break; 02432 } 02433 02434 hlList.insert (insert, hl); 02435 hlDict.insert (hl->name(), hl); 02436 } 02437 02438 // Normal HL 02439 Highlight *hl = new Highlight(0); 02440 hlList.prepend (hl); 02441 hlDict.insert (hl->name(), hl); 02442 } 02443 02444 HlManager::~HlManager() 02445 { 02446 delete syntax; 02447 } 02448 02449 static KStaticDeleter<HlManager> sdHlMan; 02450 02451 HlManager *HlManager::self() 02452 { 02453 if ( !s_self ) 02454 sdHlMan.setObject(s_self, new HlManager ()); 02455 02456 return s_self; 02457 } 02458 02459 Highlight *HlManager::getHl(int n) 02460 { 02461 if (n < 0 || n >= (int) hlList.count()) 02462 n = 0; 02463 02464 return hlList.at(n); 02465 } 02466 02467 int HlManager::nameFind(const QString &name) 02468 { 02469 int z (hlList.count() - 1); 02470 for (; z > 0; z--) 02471 if (hlList.at(z)->name() == name) 02472 return z; 02473 02474 return z; 02475 } 02476 02477 int HlManager::detectHighlighting (KateDocument *doc) 02478 { 02479 int hl = wildcardFind( doc->url().filename() ); 02480 02481 if (hl == -1) 02482 { 02483 QByteArray buf (KATE_HL_HOWMANY); 02484 uint bufpos = 0; 02485 for (uint i=0; i < doc->numLines(); i++) 02486 { 02487 QString line = doc->textLine( i ); 02488 uint len = line.length() + 1; 02489 02490 if (bufpos + len > KATE_HL_HOWMANY) 02491 len = KATE_HL_HOWMANY - bufpos; 02492 02493 memcpy(&buf[bufpos], (line + "\n").latin1(), len); 02494 02495 bufpos += len; 02496 02497 if (bufpos >= KATE_HL_HOWMANY) 02498 break; 02499 } 02500 buf.resize( bufpos ); 02501 02502 hl = mimeFind (buf); 02503 } 02504 02505 return hl; 02506 } 02507 02508 int HlManager::wildcardFind(const QString &fileName) 02509 { 02510 int result = -1; 02511 if ((result = realWildcardFind(fileName)) != -1) 02512 return result; 02513 02514 int length = fileName.length(); 02515 QString backupSuffix = KateDocumentConfig::global()->backupSuffix(); 02516 if (fileName.endsWith(backupSuffix)) { 02517 if ((result = realWildcardFind(fileName.left(length - backupSuffix.length()))) != -1) 02518 return result; 02519 } 02520 02521 for (QStringList::Iterator it = commonSuffixes.begin(); it != commonSuffixes.end(); ++it) { 02522 if (*it != backupSuffix && fileName.endsWith(*it)) { 02523 if ((result = realWildcardFind(fileName.left(length - (*it).length()))) != -1) 02524 return result; 02525 } 02526 } 02527 02528 return -1; 02529 } 02530 02531 int HlManager::realWildcardFind(const QString &fileName) 02532 { 02533 static QRegExp sep("\\s*;\\s*"); 02534 02535 QPtrList<Highlight> highlights; 02536 02537 for (Highlight *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) { 02538 highlight->loadWildcards(); 02539 02540 for (QStringList::Iterator it = highlight->getPlainExtensions().begin(); it != highlight->getPlainExtensions().end(); ++it) 02541 if (fileName.endsWith((*it))) 02542 highlights.append(highlight); 02543 02544 for (int i = 0; i < (int)highlight->getRegexpExtensions().count(); i++) { 02545 QRegExp re = highlight->getRegexpExtensions()[i]; 02546 if (re.exactMatch(fileName)) 02547 highlights.append(highlight); 02548 } 02549 } 02550 02551 if ( !highlights.isEmpty() ) 02552 { 02553 int pri = -1; 02554 int hl = -1; 02555 02556 for (Highlight *highlight = highlights.first(); highlight != 0L; highlight = highlights.next()) 02557 { 02558 if (highlight->priority() > pri) 02559 { 02560 pri = highlight->priority(); 02561 hl = hlList.findRef (highlight); 02562 } 02563 } 02564 02565 return hl; 02566 } 02567 02568 return -1; 02569 } 02570 02571 int HlManager::mimeFind(const QByteArray &contents) 02572 { 02573 static QRegExp sep("\\s*;\\s*"); 02574 02575 int accuracy = 0; 02576 KMimeType::Ptr mt = KMimeType::findByContent( contents, &accuracy ); 02577 02578 QPtrList<Highlight> highlights; 02579 02580 for (Highlight *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) 02581 { 02582 QStringList l = QStringList::split( sep, highlight->getMimetypes() ); 02583 02584 for( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) 02585 { 02586 if ( *it == mt->name() ) // faster than a regexp i guess? 02587 highlights.append (highlight); 02588 } 02589 } 02590 02591 if ( !highlights.isEmpty() ) 02592 { 02593 int pri = -1; 02594 int hl = -1; 02595 02596 for (Highlight *highlight = highlights.first(); highlight != 0L; highlight = highlights.next()) 02597 { 02598 if (highlight->priority() > pri) 02599 { 02600 pri = highlight->priority(); 02601 hl = hlList.findRef (highlight); 02602 } 02603 } 02604 02605 return hl; 02606 } 02607 02608 return -1; 02609 } 02610 02611 uint HlManager::defaultStyles() 02612 { 02613 return 10; 02614 } 02615 02616 QString HlManager::defaultStyleName(int n) 02617 { 02618 static QStringList names; 02619 02620 if (names.isEmpty()) 02621 { 02622 names << i18n("Normal"); 02623 names << i18n("Keyword"); 02624 names << i18n("Data Type"); 02625 names << i18n("Decimal/Value"); 02626 names << i18n("Base-N Integer"); 02627 names << i18n("Floating Point"); 02628 names << i18n("Character"); 02629 names << i18n("String"); 02630 names << i18n("Comment"); 02631 names << i18n("Others"); 02632 } 02633 02634 return names[n]; 02635 } 02636 02637 void HlManager::getDefaults(uint schema, KateAttributeList &list) 02638 { 02639 list.setAutoDelete(true); 02640 02641 KateAttribute* normal = new KateAttribute(); 02642 normal->setTextColor(Qt::black); 02643 normal->setSelectedTextColor(Qt::white); 02644 list.append(normal); 02645 02646 KateAttribute* keyword = new KateAttribute(); 02647 keyword->setTextColor(Qt::black); 02648 keyword->setSelectedTextColor(Qt::white); 02649 keyword->setBold(true); 02650 list.append(keyword); 02651 02652 KateAttribute* dataType = new KateAttribute(); 02653 dataType->setTextColor(Qt::darkRed); 02654 dataType->setSelectedTextColor(Qt::white); 02655 list.append(dataType); 02656 02657 KateAttribute* decimal = new KateAttribute(); 02658 decimal->setTextColor(Qt::blue); 02659 decimal->setSelectedTextColor(Qt::cyan); 02660 list.append(decimal); 02661 02662 KateAttribute* basen = new KateAttribute(); 02663 basen->setTextColor(Qt::darkCyan); 02664 basen->setSelectedTextColor(Qt::cyan); 02665 list.append(basen); 02666 02667 KateAttribute* floatAttribute = new KateAttribute(); 02668 floatAttribute->setTextColor(Qt::darkMagenta); 02669 floatAttribute->setSelectedTextColor(Qt::cyan); 02670 list.append(floatAttribute); 02671 02672 KateAttribute* charAttribute = new KateAttribute(); 02673 charAttribute->setTextColor(Qt::magenta); 02674 charAttribute->setSelectedTextColor(Qt::magenta); 02675 list.append(charAttribute); 02676 02677 KateAttribute* string = new KateAttribute(); 02678 string->setTextColor(Qt::red); 02679 string->setSelectedTextColor(Qt::red); 02680 list.append(string); 02681 02682 KateAttribute* comment = new KateAttribute(); 02683 comment->setTextColor(Qt::darkGray); 02684 comment->setSelectedTextColor(Qt::gray); 02685 comment->setItalic(true); 02686 list.append(comment); 02687 02688 KateAttribute* others = new KateAttribute(); 02689 others->setTextColor(Qt::darkGreen); 02690 others->setSelectedTextColor(Qt::green); 02691 list.append(others); 02692 02693 KConfig *config = HlManager::self()->self()->getKConfig(); 02694 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema)); 02695 02696 for (uint z = 0; z < defaultStyles(); z++) 02697 { 02698 KateAttribute *i = list.at(z); 02699 QStringList s = config->readListEntry(defaultStyleName(z)); 02700 02701 if (!s.isEmpty()) 02702 { 02703 while( s.count()<8) 02704 s << ""; 02705 02706 QString tmp; 02707 QRgb col; 02708 02709 tmp=s[0]; if (!tmp.isEmpty()) { 02710 col=tmp.toUInt(0,16); i->setTextColor(col); } 02711 02712 tmp=s[1]; if (!tmp.isEmpty()) { 02713 col=tmp.toUInt(0,16); i->setSelectedTextColor(col); } 02714 02715 tmp=s[2]; if (!tmp.isEmpty()) i->setBold(tmp!="0"); 02716 02717 tmp=s[3]; if (!tmp.isEmpty()) i->setItalic(tmp!="0"); 02718 02719 tmp=s[4]; if (!tmp.isEmpty()) i->setStrikeOut(tmp!="0"); 02720 02721 tmp=s[5]; if (!tmp.isEmpty()) i->setUnderline(tmp!="0"); 02722 02723 tmp=s[6]; if (!tmp.isEmpty()) { 02724 col=tmp.toUInt(0,16); i->setBGColor(col); } 02725 02726 tmp=s[7]; if (!tmp.isEmpty()) { 02727 col=tmp.toUInt(0,16); i->setSelectedBGColor(col); } 02728 02729 } 02730 02731 } 02732 } 02733 02734 void HlManager::setDefaults(uint schema, KateAttributeList &list) 02735 { 02736 KConfig *config = HlManager::self()->self()->getKConfig(); 02737 config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema)); 02738 02739 for (uint z = 0; z < defaultStyles(); z++) 02740 { 02741 QStringList settings; 02742 KateAttribute *i = list.at(z); 02743 02744 settings<<(i->itemSet(KateAttribute::TextColor)?QString::number(i->textColor().rgb(),16):""); 02745 settings<<(i->itemSet(KateAttribute::SelectedTextColor)?QString::number(i->selectedTextColor().rgb(),16):""); 02746 settings<<(i->itemSet(KateAttribute::Weight)?(i->bold()?"1":"0"):""); 02747 settings<<(i->itemSet(KateAttribute::Italic)?(i->italic()?"1":"0"):""); 02748 settings<<(i->itemSet(KateAttribute::StrikeOut)?(i->strikeOut()?"1":"0"):""); 02749 settings<<(i->itemSet(KateAttribute::Underline)?(i->underline()?"1":"0"):""); 02750 settings<<(i->itemSet(KateAttribute::BGColor)?QString::number(i->bgColor().rgb(),16):""); 02751 settings<<(i->itemSet(KateAttribute::SelectedBGColor)?QString::number(i->selectedBGColor().rgb(),16):""); 02752 settings<<"---"; 02753 02754 config->writeEntry(defaultStyleName(z),settings); 02755 } 02756 02757 emit changed(); 02758 } 02759 02760 int HlManager::highlights() 02761 { 02762 return (int) hlList.count(); 02763 } 02764 02765 QString HlManager::hlName(int n) 02766 { 02767 return hlList.at(n)->name(); 02768 } 02769 02770 QString HlManager::hlSection(int n) 02771 { 02772 return hlList.at(n)->section(); 02773 } 02774 02775 QString HlManager::identifierForName(const QString& name) 02776 { 02777 Highlight *hl = 0; 02778 02779 if ((hl = hlDict[name])) 02780 return hl->getIdentifier (); 02781 02782 return QString(); 02783 } 02784 //END 02785 02786 void KateViewHighlightAction::init() 02787 { 02788 m_doc = 0; 02789 subMenus.setAutoDelete( true ); 02790 02791 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow())); 02792 } 02793 02794 void KateViewHighlightAction::updateMenu (Kate::Document *doc) 02795 { 02796 m_doc = doc; 02797 } 02798 02799 void KateViewHighlightAction::slotAboutToShow() 02800 { 02801 Kate::Document *doc=m_doc; 02802 int count = HlManager::self()->highlights(); 02803 02804 for (int z=0; z<count; z++) 02805 { 02806 QString hlName = HlManager::self()->hlName (z); 02807 QString hlSection = HlManager::self()->hlSection (z); 02808 02809 if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) ) 02810 { 02811 if (subMenusName.contains(hlSection) < 1) 02812 { 02813 subMenusName << hlSection; 02814 QPopupMenu *menu = new QPopupMenu (); 02815 subMenus.append(menu); 02816 popupMenu()->insertItem (hlSection, menu); 02817 } 02818 02819 int m = subMenusName.findIndex (hlSection); 02820 names << hlName; 02821 subMenus.at(m)->insertItem ( hlName, this, SLOT(setHl(int)), 0, z); 02822 } 02823 else if (names.contains(hlName) < 1) 02824 { 02825 names << hlName; 02826 popupMenu()->insertItem ( hlName, this, SLOT(setHl(int)), 0, z); 02827 } 02828 } 02829 02830 if (!doc) return; 02831 02832 for (uint i=0;i<subMenus.count();i++) 02833 { 02834 for (uint i2=0;i2<subMenus.at(i)->count();i2++) 02835 subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false); 02836 } 02837 popupMenu()->setItemChecked (0, false); 02838 02839 int i = subMenusName.findIndex (HlManager::self()->hlSection(doc->hlMode())); 02840 if (i >= 0 && subMenus.at(i)) 02841 subMenus.at(i)->setItemChecked (doc->hlMode(), true); 02842 else 02843 popupMenu()->setItemChecked (0, true); 02844 } 02845 02846 void KateViewHighlightAction::setHl (int mode) 02847 { 02848 Kate::Document *doc=m_doc; 02849 02850 if (doc) 02851 doc->setHlMode((uint)mode); 02852 } 02853 02854 // 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 Wed Mar 16 17:24:01 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003