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