katehighlight.cpp

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