• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Kate

katehighlight.cpp

Go to the documentation of this file.
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 insensitive, 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 _insensitive;
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 insensitive, const QString& delims)
00605   : KateHlItem(attribute,context,regionId,regionId2)
00606   , _insensitive(insensitive)
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, !_insensitive);
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       // BUG 144599: Ignore a context change that would push the same context
01456       // without eating anything... this would be an infinite loop!
01457       if ( item->lookAhead && item->ctx == ctxNum )
01458         continue;
01459 
01460       if (item->region2)
01461       {
01462         // kdDebug(13010)<<QString("Region mark 2 detected: %1").arg(item->region2)<<endl;
01463         if ( !foldingList->isEmpty() && ((item->region2 < 0) && (*foldingList)[foldingList->size()-2] == -item->region2 ) )
01464         {
01465           foldingList->resize (foldingList->size()-2, QGArray::SpeedOptim);
01466         }
01467         else
01468         {
01469           foldingList->resize (foldingList->size()+2, QGArray::SpeedOptim);
01470           (*foldingList)[foldingList->size()-2] = (uint)item->region2;
01471           if (item->region2<0) //check not really needed yet
01472             (*foldingList)[foldingList->size()-1] = offset2;
01473           else
01474           (*foldingList)[foldingList->size()-1] = offset;
01475         }
01476 
01477       }
01478 
01479       if (item->region)
01480       {
01481         // kdDebug(13010)<<QString("Region mark detected: %1").arg(item->region)<<endl;
01482 
01483       /* if ( !foldingList->isEmpty() && ((item->region < 0) && (*foldingList)[foldingList->size()-1] == -item->region ) )
01484         {
01485           foldingList->resize (foldingList->size()-1, QGArray::SpeedOptim);
01486         }
01487         else*/
01488         {
01489           foldingList->resize (foldingList->size()+2, QGArray::SpeedOptim);
01490           (*foldingList)[foldingList->size()-2] = item->region;
01491           if (item->region<0) //check not really needed yet
01492             (*foldingList)[foldingList->size()-1] = offset2;
01493           else
01494             (*foldingList)[foldingList->size()-1] = offset;
01495         }
01496 
01497       }
01498 
01499       // regenerate context stack if needed
01500       if (item->ctx != -1)
01501       {
01502         generateContextStack (&ctxNum, item->ctx, &ctx, &previousLine);
01503         context = contextNum(ctxNum);
01504       }
01505 
01506       // dynamic context: substitute the model with an 'instance'
01507       if (context->dynamic)
01508       {
01509         QStringList *lst = item->capturedTexts();
01510         if (lst != 0)
01511         {
01512           // Replace the top of the stack and the current context
01513           int newctx = makeDynamicContext(context, lst);
01514           if (ctx.size() > 0)
01515             ctx[ctx.size() - 1] = newctx;
01516           ctxNum = newctx;
01517           context = contextNum(ctxNum);
01518         }
01519         delete lst;
01520       }
01521 
01522       // dominik: look ahead w/o changing offset?
01523       if (!item->lookAhead)
01524       {
01525         if (offset2 > len)
01526           offset2 = len;
01527 
01528         // even set attributes ;)
01529         memset ( textLine->attributes()+offset
01530                , item->onlyConsume ? context->attr : item->attr
01531                , offset2-offset);
01532 
01533         offset = offset2;
01534         lastChar = text[offset-1];
01535       }
01536 
01537       anItemMatched = true;
01538       break;
01539     }
01540 
01541     // something matched, continue loop
01542     if (anItemMatched)
01543       continue;
01544 
01545     // nothing found: set attribute of one char
01546     // anders: unless this context does not want that!
01547     if ( context->fallthrough )
01548     {
01549     // set context to context->ftctx.
01550       generateContextStack(&ctxNum, context->ftctx, &ctx, &previousLine);  //regenerate context stack
01551       context=contextNum(ctxNum);
01552     //kdDebug(13010)<<"context num after fallthrough at col "<<z<<": "<<ctxNum<<endl;
01553     // the next is nessecary, as otherwise keyword (or anything using the std delimitor check)
01554     // immediately after fallthrough fails. Is it bad?
01555     // jowenn, can you come up with a nicer way to do this?
01556     /*  if (offset)
01557         lastChar = text[offset - 1];
01558       else
01559         lastChar = '\\';*/
01560       continue;
01561     }
01562     else
01563     {
01564       *(textLine->attributes() + offset) = context->attr;
01565       lastChar = text[offset];
01566       offset++;
01567     }
01568   }
01569 
01570   // has the context stack changed ?
01571   if (ctx == textLine->ctxArray())
01572   {
01573     if (ctxChanged)
01574       (*ctxChanged) = false;
01575   }
01576   else
01577   {
01578     if (ctxChanged)
01579       (*ctxChanged) = true;
01580 
01581     // assign ctx stack !
01582     textLine->setContext(ctx);
01583   }
01584 
01585   // write hl continue flag
01586   textLine->setHlLineContinue (item && item->lineContinue());
01587 
01588   if (m_foldingIndentationSensitive) {
01589     bool noindent=false;
01590     for(int i=ctx.size()-1; i>=0; --i) {
01591       if (contextNum(ctx[i])->noIndentationBasedFolding) {
01592         noindent=true;
01593         break;
01594       }
01595     }
01596     textLine->setNoIndentBasedFolding(noindent);
01597   }
01598 }
01599 
01600 void KateHighlighting::loadWildcards()
01601 {
01602   KConfig *config = KateHlManager::self()->getKConfig();
01603   config->setGroup("Highlighting " + iName);
01604 
01605   QString extensionString = config->readEntry("Wildcards", iWildcards);
01606 
01607   if (extensionSource != extensionString) {
01608     regexpExtensions.clear();
01609     plainExtensions.clear();
01610 
01611     extensionSource = extensionString;
01612 
01613     static QRegExp sep("\\s*;\\s*");
01614 
01615     QStringList l = QStringList::split( sep, extensionSource );
01616 
01617     static QRegExp boringExpression("\\*\\.[\\d\\w]+");
01618 
01619     for( QStringList::Iterator it = l.begin(); it != l.end(); ++it )
01620       if (boringExpression.exactMatch(*it))
01621         plainExtensions.append((*it).mid(1));
01622       else
01623         regexpExtensions.append(QRegExp((*it), true, true));
01624   }
01625 }
01626 
01627 QValueList<QRegExp>& KateHighlighting::getRegexpExtensions()
01628 {
01629   return regexpExtensions;
01630 }
01631 
01632 QStringList& KateHighlighting::getPlainExtensions()
01633 {
01634   return plainExtensions;
01635 }
01636 
01637 QString KateHighlighting::getMimetypes()
01638 {
01639   KConfig *config = KateHlManager::self()->getKConfig();
01640   config->setGroup("Highlighting " + iName);
01641 
01642   return config->readEntry("Mimetypes", iMimetypes);
01643 }
01644 
01645 int KateHighlighting::priority()
01646 {
01647   KConfig *config = KateHlManager::self()->getKConfig();
01648   config->setGroup("Highlighting " + iName);
01649 
01650   return config->readNumEntry("Priority", m_priority);
01651 }
01652 
01653 KateHlData *KateHighlighting::getData()
01654 {
01655   KConfig *config = KateHlManager::self()->getKConfig();
01656   config->setGroup("Highlighting " + iName);
01657 
01658   KateHlData *hlData = new KateHlData(
01659   config->readEntry("Wildcards", iWildcards),
01660   config->readEntry("Mimetypes", iMimetypes),
01661   config->readEntry("Identifier", identifier),
01662   config->readNumEntry("Priority", m_priority));
01663 
01664  return hlData;
01665 }
01666 
01667 void KateHighlighting::setData(KateHlData *hlData)
01668 {
01669   KConfig *config = KateHlManager::self()->getKConfig();
01670   config->setGroup("Highlighting " + iName);
01671 
01672   config->writeEntry("Wildcards",hlData->wildcards);
01673   config->writeEntry("Mimetypes",hlData->mimetypes);
01674   config->writeEntry("Priority",hlData->priority);
01675 }
01676 
01677 void KateHighlighting::getKateHlItemDataList (uint schema, KateHlItemDataList &list)
01678 {
01679   KConfig *config = KateHlManager::self()->getKConfig();
01680   config->setGroup("Highlighting " + iName + " - Schema " + KateFactory::self()->schemaManager()->name(schema));
01681 
01682   list.clear();
01683   createKateHlItemData(list);
01684 
01685   for (KateHlItemData *p = list.first(); p != 0L; p = list.next())
01686   {
01687     QStringList s = config->readListEntry(p->name);
01688 
01689 //    kdDebug(13010)<<p->name<<s.count()<<endl;
01690     if (s.count()>0)
01691     {
01692 
01693       while(s.count()<9) s<<"";
01694       p->clear();
01695 
01696       QString tmp=s[0]; if (!tmp.isEmpty()) p->defStyleNum=tmp.toInt();
01697 
01698       QRgb col;
01699 
01700       tmp=s[1]; if (!tmp.isEmpty()) {
01701          col=tmp.toUInt(0,16); p->setTextColor(col); }
01702 
01703       tmp=s[2]; if (!tmp.isEmpty()) {
01704          col=tmp.toUInt(0,16); p->setSelectedTextColor(col); }
01705 
01706       tmp=s[3]; if (!tmp.isEmpty()) p->setBold(tmp!="0");
01707 
01708       tmp=s[4]; if (!tmp.isEmpty()) p->setItalic(tmp!="0");
01709 
01710       tmp=s[5]; if (!tmp.isEmpty()) p->setStrikeOut(tmp!="0");
01711 
01712       tmp=s[6]; if (!tmp.isEmpty()) p->setUnderline(tmp!="0");
01713 
01714       tmp=s[7]; if (!tmp.isEmpty()) {
01715          col=tmp.toUInt(0,16); p->setBGColor(col); }
01716 
01717       tmp=s[8]; if (!tmp.isEmpty()) {
01718          col=tmp.toUInt(0,16); p->setSelectedBGColor(col); }
01719 
01720     }
01721   }
01722 }
01723 
01730 void KateHighlighting::setKateHlItemDataList(uint schema, KateHlItemDataList &list)
01731 {
01732   KConfig *config = KateHlManager::self()->getKConfig();
01733   config->setGroup("Highlighting " + iName + " - Schema "
01734       + KateFactory::self()->schemaManager()->name(schema));
01735 
01736   QStringList settings;
01737 
01738   for (KateHlItemData *p = list.first(); p != 0L; p = list.next())
01739   {
01740     settings.clear();
01741     settings<<QString::number(p->defStyleNum,10);
01742     settings<<(p->itemSet(KateAttribute::TextColor)?QString::number(p->textColor().rgb(),16):"");
01743     settings<<(p->itemSet(KateAttribute::SelectedTextColor)?QString::number(p->selectedTextColor().rgb(),16):"");
01744     settings<<(p->itemSet(KateAttribute::Weight)?(p->bold()?"1":"0"):"");
01745     settings<<(p->itemSet(KateAttribute::Italic)?(p->italic()?"1":"0"):"");
01746     settings<<(p->itemSet(KateAttribute::StrikeOut)?(p->strikeOut()?"1":"0"):"");
01747     settings<<(p->itemSet(KateAttribute::Underline)?(p->underline()?"1":"0"):"");
01748     settings<<(p->itemSet(KateAttribute::BGColor)?QString::number(p->bgColor().rgb(),16):"");
01749     settings<<(p->itemSet(KateAttribute::SelectedBGColor)?QString::number(p->selectedBGColor().rgb(),16):"");
01750     settings<<"---";
01751     config->writeEntry(p->name,settings);
01752   }
01753 }
01754 
01758 void KateHighlighting::use()
01759 {
01760   if (refCount == 0)
01761     init();
01762 
01763   refCount++;
01764 }
01765 
01769 void KateHighlighting::release()
01770 {
01771   refCount--;
01772 
01773   if (refCount == 0)
01774     done();
01775 }
01776 
01781 void KateHighlighting::init()
01782 {
01783   if (noHl)
01784     return;
01785 
01786   // cu contexts
01787   for (uint i=0; i < m_contexts.size(); ++i)
01788     delete m_contexts[i];
01789   m_contexts.clear ();
01790 
01791   makeContextList();
01792 }
01793 
01794 
01799 void KateHighlighting::done()
01800 {
01801   if (noHl)
01802     return;
01803 
01804   // cu contexts
01805   for (uint i=0; i < m_contexts.size(); ++i)
01806     delete m_contexts[i];
01807   m_contexts.clear ();
01808 
01809   internalIDList.clear();
01810 }
01811 
01819 void KateHighlighting::createKateHlItemData(KateHlItemDataList &list)
01820 {
01821   // If no highlighting is selected we need only one default.
01822   if (noHl)
01823   {
01824     list.append(new KateHlItemData(i18n("Normal Text"), KateHlItemData::dsNormal));
01825     return;
01826   }
01827 
01828   // If the internal list isn't already available read the config file
01829   if (internalIDList.isEmpty())
01830     makeContextList();
01831 
01832   list=internalIDList;
01833 }
01834 
01838 void KateHighlighting::addToKateHlItemDataList()
01839 {
01840   //Tell the syntax document class which file we want to parse and which data group
01841   KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
01842   KateSyntaxContextData *data = KateHlManager::self()->syntax->getGroupInfo("highlighting","itemData");
01843 
01844   //begin with the real parsing
01845   while (KateHlManager::self()->syntax->nextGroup(data))
01846   {
01847     // read all attributes
01848     QString color = KateHlManager::self()->syntax->groupData(data,QString("color"));
01849     QString selColor = KateHlManager::self()->syntax->groupData(data,QString("selColor"));
01850     QString bold = KateHlManager::self()->syntax->groupData(data,QString("bold"));
01851     QString italic = KateHlManager::self()->syntax->groupData(data,QString("italic"));
01852     QString underline = KateHlManager::self()->syntax->groupData(data,QString("underline"));
01853     QString strikeOut = KateHlManager::self()->syntax->groupData(data,QString("strikeOut"));
01854     QString bgColor = KateHlManager::self()->syntax->groupData(data,QString("backgroundColor"));
01855     QString selBgColor = KateHlManager::self()->syntax->groupData(data,QString("selBackgroundColor"));
01856 
01857     KateHlItemData* newData = new KateHlItemData(
01858             buildPrefix+KateHlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(),
01859             getDefStyleNum(KateHlManager::self()->syntax->groupData(data,QString("defStyleNum"))));
01860 
01861     /* here the custom style overrides are specified, if needed */
01862     if (!color.isEmpty()) newData->setTextColor(QColor(color));
01863     if (!selColor.isEmpty()) newData->setSelectedTextColor(QColor(selColor));
01864     if (!bold.isEmpty()) newData->setBold( IS_TRUE(bold) );
01865     if (!italic.isEmpty()) newData->setItalic( IS_TRUE(italic) );
01866     // new attributes for the new rendering view
01867     if (!underline.isEmpty()) newData->setUnderline( IS_TRUE(underline) );
01868     if (!strikeOut.isEmpty()) newData->setStrikeOut( IS_TRUE(strikeOut) );
01869     if (!bgColor.isEmpty()) newData->setBGColor(QColor(bgColor));
01870     if (!selBgColor.isEmpty()) newData->setSelectedBGColor(QColor(selBgColor));
01871 
01872     internalIDList.append(newData);
01873   }
01874 
01875   //clean up
01876   if (data)
01877     KateHlManager::self()->syntax->freeGroupInfo(data);
01878 }
01879 
01890 int  KateHighlighting::lookupAttrName(const QString& name, KateHlItemDataList &iDl)
01891 {
01892   for (uint i = 0; i < iDl.count(); i++)
01893     if (iDl.at(i)->name == buildPrefix+name)
01894       return i;
01895 
01896   kdDebug(13010)<<"Couldn't resolve itemDataName:"<<name<<endl;
01897   return 0;
01898 }
01899 
01913 KateHlItem *KateHighlighting::createKateHlItem(KateSyntaxContextData *data,
01914                                                KateHlItemDataList &iDl,
01915                                                QStringList *RegionList,
01916                                                QStringList *ContextNameList)
01917 {
01918   // No highlighting -> exit
01919   if (noHl)
01920     return 0;
01921 
01922   // get the (tagname) itemd type
01923   QString dataname=KateHlManager::self()->syntax->groupItemData(data,QString(""));
01924 
01925   // code folding region handling:
01926   QString beginRegionStr=KateHlManager::self()->syntax->groupItemData(data,QString("beginRegion"));
01927   QString endRegionStr=KateHlManager::self()->syntax->groupItemData(data,QString("endRegion"));
01928 
01929   signed char regionId=0;
01930   signed char regionId2=0;
01931 
01932   if (!beginRegionStr.isEmpty())
01933   {
01934     regionId = RegionList->findIndex(beginRegionStr);
01935 
01936     if (regionId==-1) // if the region name doesn't already exist, add it to the list
01937     {
01938       (*RegionList)<<beginRegionStr;
01939       regionId = RegionList->findIndex(beginRegionStr);
01940     }
01941 
01942     regionId++;
01943 
01944     kdDebug(13010) << "########### BEG REG: "  << beginRegionStr << " NUM: " << regionId << endl;
01945   }
01946 
01947   if (!endRegionStr.isEmpty())
01948   {
01949     regionId2 = RegionList->findIndex(endRegionStr);
01950 
01951     if (regionId2==-1) // if the region name doesn't already exist, add it to the list
01952     {
01953       (*RegionList)<<endRegionStr;
01954       regionId2 = RegionList->findIndex(endRegionStr);
01955     }
01956 
01957     regionId2 = -regionId2 - 1;
01958 
01959     kdDebug(13010) << "########### END REG: "  << endRegionStr << " NUM: " << regionId2 << endl;
01960   }
01961 
01962   int attr = 0;
01963   QString tmpAttr=KateHlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace();
01964   bool onlyConsume = tmpAttr.isEmpty();
01965 
01966   // only relevant for non consumer
01967   if (!onlyConsume)
01968   {
01969     if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
01970     {
01971       errorsAndWarnings+=i18n(
01972           "<B>%1</B>: Deprecated syntax. Attribute (%2) not addressed by symbolic name<BR>").
01973       arg(buildIdentifier).arg(tmpAttr);
01974       attr=tmpAttr.toInt();
01975     }
01976     else
01977       attr=lookupAttrName(tmpAttr,iDl);
01978   }
01979 
01980   // Info about context switch
01981   int context = -1;
01982   QString unresolvedContext;
01983   QString tmpcontext=KateHlManager::self()->syntax->groupItemData(data,QString("context"));
01984   if (!tmpcontext.isEmpty())
01985     context=getIdFromString(ContextNameList, tmpcontext,unresolvedContext);
01986 
01987   // Get the char parameter (eg DetectChar)
01988   char chr;
01989   if (! KateHlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty())
01990     chr= (KateHlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0];
01991   else
01992     chr=0;
01993 
01994   // Get the String parameter (eg. StringDetect)
01995   QString stringdata=KateHlManager::self()->syntax->groupItemData(data,QString("String"));
01996 
01997   // Get a second char parameter (char1) (eg Detect2Chars)
01998   char chr1;
01999   if (! KateHlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty())
02000     chr1= (KateHlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0];
02001   else
02002     chr1=0;
02003 
02004   // Will be removed eventually. Atm used for StringDetect, keyword and RegExp
02005   const QString & insensitive_str = KateHlManager::self()->syntax->groupItemData(data,QString("insensitive"));
02006   bool insensitive = IS_TRUE( insensitive_str );
02007 
02008   // for regexp only
02009   bool minimal = IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("minimal")) );
02010 
02011   // dominik: look ahead and do not change offset. so we can change contexts w/o changing offset1.
02012   bool lookAhead = IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("lookAhead")) );
02013 
02014   bool dynamic= IS_TRUE(KateHlManager::self()->syntax->groupItemData(data,QString("dynamic")) );
02015 
02016   bool firstNonSpace = IS_TRUE(KateHlManager::self()->syntax->groupItemData(data,QString("firstNonSpace")) );
02017 
02018   int column = -1;
02019   QString colStr = KateHlManager::self()->syntax->groupItemData(data,QString("column"));
02020   if (!colStr.isEmpty())
02021     column = colStr.toInt();
02022 
02023   //Create the item corresponding to it's type and set it's parameters
02024   KateHlItem *tmpItem;
02025 
02026   if (dataname=="keyword")
02027   {
02028     bool keywordInsensitive = insensitive_str.isEmpty() ? !casesensitive : insensitive;
02029     KateHlKeyword *keyword=new KateHlKeyword(attr,context,regionId,regionId2,keywordInsensitive,
02030                                              m_additionalData[ buildIdentifier ]->deliminator);
02031 
02032     //Get the entries for the keyword lookup list
02033     keyword->addList(KateHlManager::self()->syntax->finddata("highlighting",stringdata));
02034     tmpItem=keyword;
02035   }
02036   else if (dataname=="Float") tmpItem= (new KateHlFloat(attr,context,regionId,regionId2));
02037   else if (dataname=="Int") tmpItem=(new KateHlInt(attr,context,regionId,regionId2));
02038   else if (dataname=="DetectChar") tmpItem=(new KateHlCharDetect(attr,context,regionId,regionId2,chr));
02039   else if (dataname=="Detect2Chars") tmpItem=(new KateHl2CharDetect(attr,context,regionId,regionId2,chr,chr1));
02040   else if (dataname=="RangeDetect") tmpItem=(new KateHlRangeDetect(attr,context,regionId,regionId2, chr, chr1));
02041   else if (dataname=="LineContinue") tmpItem=(new KateHlLineContinue(attr,context,regionId,regionId2));
02042   else if (dataname=="StringDetect") tmpItem=(new KateHlStringDetect(attr,context,regionId,regionId2,stringdata,insensitive));
02043   else if (dataname=="AnyChar") tmpItem=(new KateHlAnyChar(attr,context,regionId,regionId2,stringdata));
02044   else if (dataname=="RegExpr") tmpItem=(new KateHlRegExpr(attr,context,regionId,regionId2,stringdata, insensitive, minimal));
02045   else if (dataname=="HlCChar") tmpItem= ( new KateHlCChar(attr,context,regionId,regionId2));
02046   else if (dataname=="HlCHex") tmpItem= (new KateHlCHex(attr,context,regionId,regionId2));
02047   else if (dataname=="HlCOct") tmpItem= (new KateHlCOct(attr,context,regionId,regionId2));
02048   else if (dataname=="HlCFloat") tmpItem= (new KateHlCFloat(attr,context,regionId,regionId2));
02049   else if (dataname=="HlCStringChar") tmpItem= (new KateHlCStringChar(attr,context,regionId,regionId2));
02050   else if (dataname=="DetectSpaces") tmpItem= (new KateHlDetectSpaces(attr,context,regionId,regionId2));
02051   else if (dataname=="DetectIdentifier") tmpItem= (new KateHlDetectIdentifier(attr,context,regionId,regionId2));
02052   else
02053   {
02054     // oops, unknown type. Perhaps a spelling error in the xml file
02055     return 0;
02056   }
02057 
02058   // set lookAhead & dynamic properties
02059   tmpItem->lookAhead = lookAhead;
02060   tmpItem->dynamic = dynamic;
02061   tmpItem->firstNonSpace = firstNonSpace;
02062   tmpItem->column = column;
02063   tmpItem->onlyConsume = onlyConsume;
02064 
02065   if (!unresolvedContext.isEmpty())
02066   {
02067     unresolvedContextReferences.insert(&(tmpItem->ctx),unresolvedContext);
02068   }
02069 
02070   return tmpItem;
02071 }
02072 
02073 QString KateHighlighting::hlKeyForAttrib( int i ) const
02074 {
02075   // find entry. This is faster than QMap::find. m_hlIndex always has an entry
02076   // for key '0' (it is "none"), so the result is always valid.
02077   int k = 0;
02078   QMap<int,QString>::const_iterator it = m_hlIndex.constEnd();
02079   while ( it != m_hlIndex.constBegin() )
02080   {
02081     --it;
02082     k = it.key();
02083     if ( i >= k )
02084       break;
02085   }
02086   return it.data();
02087 }
02088 
02089 bool KateHighlighting::isInWord( QChar c, int attrib ) const
02090 {
02091   return m_additionalData[ hlKeyForAttrib( attrib ) ]->deliminator.find(c) < 0
02092       && !c.isSpace() && c != '"' && c != '\'';
02093 }
02094 
02095 bool KateHighlighting::canBreakAt( QChar c, int attrib ) const
02096 {
02097   static const QString& sq = KGlobal::staticQString("\"'");
02098   return (m_additionalData[ hlKeyForAttrib( attrib ) ]->wordWrapDeliminator.find(c) != -1) && (sq.find(c) == -1);
02099 }
02100 
02101 signed char KateHighlighting::commentRegion(int attr) const {
02102   QString commentRegion=m_additionalData[ hlKeyForAttrib( attr ) ]->multiLineRegion;
02103   return (commentRegion.isEmpty()?0:(commentRegion.toShort()));
02104 }
02105 
02106 bool KateHighlighting::canComment( int startAttrib, int endAttrib ) const
02107 {
02108   QString k = hlKeyForAttrib( startAttrib );
02109   return ( k == hlKeyForAttrib( endAttrib ) &&
02110       ( ( !m_additionalData[k]->multiLineCommentStart.isEmpty() && !m_additionalData[k]->multiLineCommentEnd.isEmpty() ) ||
02111        ! m_additionalData[k]->singleLineCommentMarker.isEmpty() ) );
02112 }
02113 
02114 QString KateHighlighting::getCommentStart( int attrib ) const
02115 {
02116   return m_additionalData[ hlKeyForAttrib( attrib) ]->multiLineCommentStart;
02117 }
02118 
02119 QString KateHighlighting::getCommentEnd( int attrib ) const
02120 {
02121   return m_additionalData[ hlKeyForAttrib( attrib ) ]->multiLineCommentEnd;
02122 }
02123 
02124 QString KateHighlighting::getCommentSingleLineStart( int attrib ) const
02125 {
02126   return m_additionalData[ hlKeyForAttrib( attrib) ]->singleLineCommentMarker;
02127 }
02128 
02129 KateHighlighting::CSLPos KateHighlighting::getCommentSingleLinePosition( int attrib ) const
02130 {
02131   return m_additionalData[ hlKeyForAttrib( attrib) ]->singleLineCommentPosition;
02132 }
02133 
02134 
02139 void KateHighlighting::readCommentConfig()
02140 {
02141   KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02142   KateSyntaxContextData *data=KateHlManager::self()->syntax->getGroupInfo("general","comment");
02143 
02144   QString cmlStart="", cmlEnd="", cmlRegion="", cslStart="";
02145   CSLPos cslPosition=CSLPosColumn0;
02146 
02147   if (data)
02148   {
02149     while  (KateHlManager::self()->syntax->nextGroup(data))
02150     {
02151       if (KateHlManager::self()->syntax->groupData(data,"name")=="singleLine")
02152       {
02153         cslStart=KateHlManager::self()->syntax->groupData(data,"start");
02154         QString cslpos=KateHlManager::self()->syntax->groupData(data,"position");
02155         if (cslpos=="afterwhitespace")
02156           cslPosition=CSLPosAfterWhitespace;
02157         else
02158           cslPosition=CSLPosColumn0;
02159       }
02160       else if (KateHlManager::self()->syntax->groupData(data,"name")=="multiLine")
02161       {
02162         cmlStart=KateHlManager::self()->syntax->groupData(data,"start");
02163         cmlEnd=KateHlManager::self()->syntax->groupData(data,"end");
02164         cmlRegion=KateHlManager::self()->syntax->groupData(data,"region");
02165       }
02166     }
02167 
02168     KateHlManager::self()->syntax->freeGroupInfo(data);
02169   }
02170 
02171   m_additionalData[buildIdentifier]->singleLineCommentMarker = cslStart;
02172   m_additionalData[buildIdentifier]->singleLineCommentPosition = cslPosition;
02173   m_additionalData[buildIdentifier]->multiLineCommentStart = cmlStart;
02174   m_additionalData[buildIdentifier]->multiLineCommentEnd = cmlEnd;
02175   m_additionalData[buildIdentifier]->multiLineRegion = cmlRegion;
02176 }
02177 
02183 void KateHighlighting::readGlobalKeywordConfig()
02184 {
02185   deliminator = stdDeliminator;
02186   // Tell the syntax document class which file we want to parse
02187   kdDebug(13010)<<"readGlobalKeywordConfig:BEGIN"<<endl;
02188 
02189   KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02190   KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","keywords");
02191 
02192   if (data)
02193   {
02194     kdDebug(13010)<<"Found global keyword config"<<endl;
02195 
02196     if ( IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("casesensitive")) ) )
02197       casesensitive=true;
02198     else
02199       casesensitive=false;
02200 
02201     //get the weak deliminators
02202     weakDeliminator=(KateHlManager::self()->syntax->groupItemData(data,QString("weakDeliminator")));
02203 
02204     kdDebug(13010)<<"weak delimiters are: "<<weakDeliminator<<endl;
02205 
02206     // remove any weakDelimitars (if any) from the default list and store this list.
02207     for (uint s=0; s < weakDeliminator.length(); s++)
02208     {
02209       int f = deliminator.find (weakDeliminator[s]);
02210 
02211       if (f > -1)
02212         deliminator.remove (f, 1);
02213     }
02214 
02215     QString addDelim = (KateHlManager::self()->syntax->groupItemData(data,QString("additionalDeliminator")));
02216 
02217     if (!addDelim.isEmpty())
02218       deliminator=deliminator+addDelim;
02219 
02220     KateHlManager::self()->syntax->freeGroupInfo(data);
02221   }
02222   else
02223   {
02224     //Default values
02225     casesensitive=true;
02226     weakDeliminator=QString("");
02227   }
02228 
02229   kdDebug(13010)<<"readGlobalKeywordConfig:END"<<endl;
02230 
02231   kdDebug(13010)<<"delimiterCharacters are: "<<deliminator<<endl;
02232 
02233   m_additionalData[buildIdentifier]->deliminator = deliminator;
02234 }
02235 
02246 void KateHighlighting::readWordWrapConfig()
02247 {
02248   // Tell the syntax document class which file we want to parse
02249   kdDebug(13010)<<"readWordWrapConfig:BEGIN"<<endl;
02250 
02251   KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02252   KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","keywords");
02253 
02254   QString wordWrapDeliminator = stdDeliminator;
02255   if (data)
02256   {
02257     kdDebug(13010)<<"Found global keyword config"<<endl;
02258 
02259     wordWrapDeliminator = (KateHlManager::self()->syntax->groupItemData(data,QString("wordWrapDeliminator")));
02260     //when no wordWrapDeliminator is defined use the deliminator list
02261     if ( wordWrapDeliminator.length() == 0 ) wordWrapDeliminator = deliminator;
02262 
02263     kdDebug(13010) << "word wrap deliminators are " << wordWrapDeliminator << endl;
02264 
02265     KateHlManager::self()->syntax->freeGroupInfo(data);
02266   }
02267 
02268   kdDebug(13010)<<"readWordWrapConfig:END"<<endl;
02269 
02270   m_additionalData[buildIdentifier]->wordWrapDeliminator = wordWrapDeliminator;
02271 }
02272 
02273 void KateHighlighting::readIndentationConfig()
02274 {
02275   m_indentation = "";
02276 
02277   KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02278   KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","indentation");
02279 
02280   if (data)
02281   {
02282     m_indentation = (KateHlManager::self()->syntax->groupItemData(data,QString("mode")));
02283 
02284     KateHlManager::self()->syntax->freeGroupInfo(data);
02285   }
02286 }
02287 
02288 void KateHighlighting::readFoldingConfig()
02289 {
02290   // Tell the syntax document class which file we want to parse
02291   kdDebug(13010)<<"readfoldignConfig:BEGIN"<<endl;
02292 
02293   KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02294   KateSyntaxContextData *data = KateHlManager::self()->syntax->getConfig("general","folding");
02295 
02296   if (data)
02297   {
02298     kdDebug(13010)<<"Found global keyword config"<<endl;
02299 
02300     if ( IS_TRUE( KateHlManager::self()->syntax->groupItemData(data,QString("indentationsensitive")) ) )
02301       m_foldingIndentationSensitive=true;
02302     else
02303       m_foldingIndentationSensitive=false;
02304 
02305     KateHlManager::self()->syntax->freeGroupInfo(data);
02306   }
02307   else
02308   {
02309     //Default values
02310     m_foldingIndentationSensitive = false;
02311   }
02312 
02313   kdDebug(13010)<<"readfoldingConfig:END"<<endl;
02314 
02315   kdDebug(13010)<<"############################ use indent for fold are: "<<m_foldingIndentationSensitive<<endl;
02316 }
02317 
02318 void  KateHighlighting::createContextNameList(QStringList *ContextNameList,int ctx0)
02319 {
02320   kdDebug(13010)<<"creatingContextNameList:BEGIN"<<endl;
02321 
02322   if (ctx0 == 0)
02323       ContextNameList->clear();
02324 
02325   KateHlManager::self()->syntax->setIdentifier(buildIdentifier);
02326 
02327   KateSyntaxContextData *data=KateHlManager::self()->syntax->getGroupInfo("highlighting","context");
02328 
02329   int id=ctx0;
02330 
02331   if (data)
02332   {
02333      while (KateHlManager::self()->syntax->nextGroup(data))
02334      {
02335           QString tmpAttr=KateHlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace();
02336     if (tmpAttr.isEmpty())
02337     {
02338      tmpAttr=QString("!KATE_INTERNAL_DUMMY! %1").arg(id);
02339      errorsAndWarnings +=i18n("<B>%1</B>: Deprecated syntax. Context %2 has no symbolic name<BR>").arg(buildIdentifier).arg(id-ctx0);
02340     }
02341           else tmpAttr=buildPrefix+tmpAttr;
02342     (*ContextNameList)<<tmpAttr;
02343           id++;
02344      }
02345      KateHlManager::self()->syntax->freeGroupInfo(data);
02346   }
02347   kdDebug(13010)<<"creatingContextNameList:END"<<endl;
02348 
02349 }
02350 
02351 int KateHighlighting::getIdFromString(QStringList *ContextNameList, QString tmpLineEndContext, /*NO CONST*/ QString &unres)
02352 {
02353   unres="";
02354   int context;
02355   if ((tmpLineEndContext=="#stay") || (tmpLineEndContext.simplifyWhiteSpace().isEmpty()))
02356     context=-1;
02357 
02358   else if (tmpLineEndContext.startsWith("#pop"))
02359   {
02360     context=-1;
02361     for(;tmpLineEndContext.startsWith("#pop");context--)
02362     {
02363       tmpLineEndContext.remove(0,4);
02364       kdDebug(13010)<<"#pop found"<<endl;
02365     }
02366   }
02367 
02368   else if ( tmpLineEndContext.contains("##"))
02369   {
02370     int o = tmpLineEndContext.find("##");
02371     // FIXME at least with 'foo##bar'-style contexts the rules are picked up
02372     // but the default attribute is not
02373     QString tmp=tmpLineEndContext.mid(o+2);
02374     if (!embeddedHls.contains(tmp))  embeddedHls.insert(tmp,KateEmbeddedHlInfo());
02375     unres=tmp+':'+tmpLineEndContext.left(o);
02376     context=0;
02377   }
02378 
02379   else
02380   {
02381     context=ContextNameList->findIndex(buildPrefix+tmpLineEndContext);
02382     if (context==-1)
02383     {
02384       context=tmpLineEndContext.toInt();
02385       errorsAndWarnings+=i18n(
02386         "<B>%1</B>:Deprecated syntax. Context %2 not addressed by a symbolic name"
02387         ).arg(buildIdentifier).arg(tmpLineEndContext);
02388     }
02389 //#warning restructure this the name list storage.
02390 //    context=context+buildContext0Offset;
02391   }
02392   return context;
02393 }
02394 
02400 void KateHighlighting::makeContextList()
02401 {
02402   if (noHl)  // if this a highlighting for "normal texts" only, tere is no need for a context list creation
02403     return;
02404 
02405   embeddedHls.clear();
02406   unresolvedContextReferences.clear();
02407   RegionList.clear();
02408   ContextNameList.clear();
02409 
02410   // prepare list creation. To reuse as much code as possible handle this
02411   // highlighting the same way as embedded onces
02412   embeddedHls.insert(iName,KateEmbeddedHlInfo());
02413 
02414   bool something_changed;
02415   // the context "0" id is 0 for this hl, all embedded context "0"s have offsets
02416   startctx=base_startctx=0;
02417   // inform everybody that we are building the highlighting contexts and itemlists
02418   building=true;
02419 
02420   do
02421   {
02422     kdDebug(13010)<<"**************** Outer loop in make ContextList"<<endl;
02423     kdDebug(13010)<<"**************** Hl List count:"<<embeddedHls.count()<<endl;
02424     something_changed=false; //assume all "embedded" hls have already been loaded
02425     for (KateEmbeddedHlInfos::const_iterator it=embeddedHls.begin(); it!=embeddedHls.end();++it)
02426     {
02427       if (!it.data().loaded)  // we found one, we still have to load
02428       {
02429         kdDebug(13010)<<"**************** Inner loop in make ContextList"<<endl;
02430         QString identifierToUse;
02431         kdDebug(13010)<<"Trying to open highlighting definition file: "<< it.key()<<endl;
02432         if (iName==it.key()) // the own identifier is known
02433           identifierToUse=identifier;
02434         else                 // all others have to be looked up
02435           identifierToUse=KateHlManager::self()->identifierForName(it.key());
02436 
02437         kdDebug(13010)<<"Location is:"<< identifierToUse<<endl;
02438 
02439         buildPrefix=it.key()+':';  // attribute names get prefixed by the names
02440                                    // of the highlighting definitions they belong to
02441 
02442         if (identifierToUse.isEmpty() )
02443           kdDebug(13010)<<"OHOH, unknown highlighting description referenced"<<endl;
02444 
02445         kdDebug(13010)<<"setting ("<<it.key()<<") to loaded"<<endl;
02446 
02447         //mark hl as loaded
02448         it=embeddedHls.insert(it.key(),KateEmbeddedHlInfo(true,startctx));
02449         //set class member for context 0 offset, so we don't need to pass it around
02450         buildContext0Offset=startctx;
02451         //parse one hl definition file
02452         startctx=addToContextList(identifierToUse,startctx);
02453 
02454         if (noHl) return;  // an error occurred
02455 
02456         base_startctx = startctx;
02457         something_changed=true; // something has been loaded
02458       }
02459     }
02460   } while (something_changed);  // as long as there has been another file parsed
02461                   // repeat everything, there could be newly added embedded hls.
02462 
02463 
02464   // at this point all needed highlighing (sub)definitions are loaded. It's time
02465   // to resolve cross file  references (if there are any)
02466   kdDebug(13010)<<"Unresolved contexts, which need attention: "<<unresolvedContextReferences.count()<<endl;
02467 
02468   //optimize this a littlebit
02469   for (KateHlUnresolvedCtxRefs::iterator unresIt=unresolvedContextReferences.begin();
02470     unresIt!=unresolvedContextReferences.end();++unresIt)
02471   {
02472     QString incCtx = unresIt.data();
02473     kdDebug(13010)<<"Context "<<incCtx<<" is unresolved"<<endl;
02474     // only resolve '##Name' contexts here; handleKateHlIncludeRules() can figure
02475     // out 'Name##Name'-style inclusions, but we screw it up
02476     if (incCtx.endsWith(":")) {
02477       kdDebug(13010)<<"Looking up context0 for ruleset "<<incCtx<<endl;
02478       incCtx = incCtx.left(incCtx.length()-1);
02479       //try to find the context0 id for a given unresolvedReference
02480       KateEmbeddedHlInfos::const_iterator hlIt=embeddedHls.find(incCtx);
02481       if (hlIt!=embeddedHls.end())
02482         *(unresIt.key())=hlIt.data().context0;
02483     }
02484   }
02485 
02486   // eventually handle KateHlIncludeRules items, if they exist.
02487   // This has to be done after the cross file references, because it is allowed
02488   // to include the context0 from a different definition, than the one the rule
02489   // belongs to
02490   handleKateHlIncludeRules();
02491 
02492   embeddedHls.clear(); //save some memory.
02493   unresolvedContextReferences.clear(); //save some memory
02494   RegionList.clear();  // I think you get the idea ;)
02495   ContextNameList.clear();
02496 
02497 
02498   // if there have been errors show them
02499   if (!errorsAndWarnings.isEmpty())
02500   KMessageBox::detailedSorry(0L,i18n(
02501         "There were warning(s) and/or error(s) while parsing the syntax "
02502         "highlighting configuration."),
02503         errorsAndWarnings, i18n("Kate Syntax Highlighting Parser"));
02504 
02505   // we have finished
02506   building=false;
02507 }
02508 
02509 void KateHighlighting::handleKateHlIncludeRules()
02510 {
02511   // if there are noe include rules to take care of, just return
02512   kdDebug(13010)<<"KateHlIncludeRules, which need attention: " <<includeRules.count()<<endl;
02513   if (includeRules.isEmpty()) return;
02514 
02515   buildPrefix="";
02516   QString dummy;
02517 
02518   // By now the context0 references are resolved, now more or less only inner
02519   // file references are resolved. If we decide that arbitrary inclusion is
02520   // needed, this doesn't need to be changed, only the addToContextList
02521   // method.
02522 
02523   //resolove context names
02524   for (KateHlIncludeRules::iterator it=includeRules.begin();it!=includeRules.end();)
02525   {
02526     if ((*it)->incCtx==-1) // context unresolved ?
02527     {
02528 
02529       if ((*it)->incCtxN.isEmpty())
02530       {
02531         // no context name given, and no valid context id set, so this item is
02532         // going to be removed
02533         KateHlIncludeRules::iterator it1=it;
02534         ++it1;
02535         delete (*it);
02536         includeRules.remove(it);
02537         it=it1;
02538       }
02539       else
02540       {
02541         // resolve name to id
02542         (*it)->incCtx=getIdFromString(&ContextNameList,(*it)->incCtxN,dummy);
02543         kdDebug(13010)<<"Resolved "<<(*it)->incCtxN<< " to "<<(*it)->incCtx<<" for include rule"<<endl;
02544         // It would be good to look here somehow, if the result is valid
02545       }
02546     }
02547     else ++it; //nothing to do, already resolved (by the cross defintion reference resolver)
02548   }
02549 
02550   // now that all KateHlIncludeRule items should be valid and completely resolved,
02551   // do the real inclusion of the rules.
02552   // recursiveness is needed, because context 0 could include context 1, which
02553   // itself includes context 2 and so on.
02554   //  In that case we have to handle context 2 first, then 1, 0
02555   //TODO: catch circular references: eg 0->1->2->3->1
02556   while (!includeRules.isEmpty())
02557     handleKateHlIncludeRulesRecursive(includeRules.begin(),&includeRules);
02558 }
02559 
02560 void KateHighlighting::handleKateHlIncludeRulesRecursive(KateHlIncludeRules::iterator it, KateHlIncludeRules *list)
02561 {
02562   if (it==list->end()) return;  //invalid iterator, shouldn't happen, but better have a rule prepared ;)
02563 
02564   KateHlIncludeRules::iterator it1=it;
02565   int ctx=(*it1)->ctx;
02566 
02567   // find the last entry for the given context in the KateHlIncludeRules list
02568   // this is need if one context includes more than one. This saves us from
02569   // updating all insert positions:
02570   // eg: context 0:
02571   // pos 3 - include context 2
02572   // pos 5 - include context 3
02573   // During the building of the includeRules list the items are inserted in
02574   // ascending order, now we need it descending to make our life easier.
02575   while ((it!=list->end()) && ((*it)->ctx==ctx))
02576   {
02577     it1=it;
02578     ++it;
02579   }
02580 
02581   // iterate over each include rule for the context the function has been called for.
02582   while ((it1!=list->end()) && ((*it1)->ctx==ctx))
02583   {
02584     int ctx1=(*it1)->incCtx;
02585 
02586     //let's see, if the the included context includes other contexts
02587     for (KateHlIncludeRules::iterator it2=list->begin();it2!=list->end();++it2)
02588     {
02589       if ((*it2)->ctx==ctx1)
02590       {
02591         //yes it does, so first handle that include rules, since we want to
02592         // include those subincludes too
02593         handleKateHlIncludeRulesRecursive(it2,list);
02594         break;
02595       }
02596     }
02597 
02598     // if the context we want to include had sub includes, they are already inserted there.
02599     KateHlContext *dest=m_contexts[ctx];
02600     KateHlContext *src=m_contexts[ctx1];
02601 //     kdDebug(3010)<<"linking included rules from "<<ctx<<" to "<<ctx1<<endl;
02602 
02603     // If so desired, change the dest attribute to the one of the src.
02604     // Required to make commenting work, if text matched by the included context
02605     // is a different highlight than the host context.
02606     if ( (*it1)->includeAttrib )
02607       dest->attr = src->attr;
02608 
02609     // insert the included context's rules starting at position p
02610     int p=(*it1)->pos;
02611 
02612     // remember some stuff
02613     int oldLen = dest->items.size();
02614     uint itemsToInsert = src->items.size();
02615 
02616     // resize target
02617     dest->items.resize (oldLen + itemsToInsert);
02618 
02619     // move old elements
02620     for (int i=oldLen-1; i >= p; --i)
02621       dest->items[i+itemsToInsert] = dest->items[i];
02622 
02623     // insert new stuff
02624     for (uint i=0; i < itemsToInsert; ++i  )
02625       dest->items[p+i] = src->items[i];
02626 
02627     it=it1; //backup the iterator
02628     --it1;  //move to the next entry, which has to be take care of
02629     delete (*it); //free the already handled data structure
02630     list->remove(it); // remove it from the list
02631   }
02632 }
02633 
02639 int KateHighlighting::addToContextList(const QString &ident, int ctx0)
02640 {
02641   kdDebug(13010)<<"=== Adding hl with ident '"<<ident<<"'"<<endl;
02642 
02643   buildIdentifier=ident;
02644   KateSyntaxContextData *data, *datasub;
02645   KateHlItem *c;
02646 
02647   QString dummy;
02648 
02649   // Let the syntax document class know, which file we'd like to parse
02650   if (!KateHlManager::self()->syntax->setIdentifier(ident))
02651   {
02652     noHl=true;
02653     KMessageBox::information(0L,i18n(
02654         "Since there has been an error parsing the highlighting description, "
02655         "this highlighting will be disabled"));
02656     return 0;
02657   }
02658 
02659   // only read for the own stuff
02660   if (identifier == ident)
02661   {
02662     readIndentationConfig ();
02663   }
02664 
02665   RegionList<<"!KateInternal_TopLevel!";
02666 
02667   m_hlIndex[internalIDList.count()] = ident;
02668   m_additionalData.insert( ident, new HighlightPropertyBag );
02669 
02670   // fill out the propertybag
02671   readCommentConfig();
02672   readGlobalKeywordConfig();
02673   readWordWrapConfig();
02674 
02675   readFoldingConfig ();
02676 
02677   QString ctxName;
02678 
02679   // This list is needed for the translation of the attribute parameter,
02680   // if the itemData name is given instead of the index
02681   addToKateHlItemDataList();
02682   KateHlItemDataList iDl = internalIDList;
02683 
02684   createContextNameList(&ContextNameList,ctx0);
02685 
02686 
02687   kdDebug(13010)<<"Parsing Context structure"<<endl;
02688   //start the real work
02689   data=KateHlManager::self()->syntax->getGroupInfo("highlighting","context");
02690   uint i=buildContext0Offset;
02691   if (data)
02692   {
02693     while (KateHlManager::self()->syntax->nextGroup(data))
02694     {
02695       kdDebug(13010)<<"Found a context in file, building structure now"<<endl;
02696       //BEGIN - Translation of the attribute parameter
02697       QString tmpAttr=KateHlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace();
02698       int attr;
02699       if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
02700         attr=tmpAttr.toInt();
02701       else
02702         attr=lookupAttrName(tmpAttr,iDl);
02703       //END - Translation of the attribute parameter
02704 
02705       ctxName=buildPrefix+KateHlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace();
02706 
02707       QString tmpLineEndContext=KateHlManager::self()->syntax->groupData(data,QString("lineEndContext")).simplifyWhiteSpace();
02708       int context;
02709 
02710       context=getIdFromString(&ContextNameList, tmpLineEndContext,dummy);
02711 
02712       QString tmpNIBF = KateHlManager::self()->syntax->groupData(data, QString("noIndentationBasedFolding") );
02713       bool noIndentationBasedFolding=IS_TRUE(tmpNIBF);
02714 
02715       //BEGIN get fallthrough props
02716       bool ft = false;
02717       int ftc = 0; // fallthrough context
02718       if ( i > 0 )  // fallthrough is not smart in context 0
02719       {
02720         QString tmpFt = KateHlManager::self()->syntax->groupData(data, QString("fallthrough") );
02721         if ( IS_TRUE(tmpFt) )
02722           ft = true;
02723         if ( ft )
02724         {
02725           QString tmpFtc = KateHlManager::self()->syntax->groupData( data, QString("fallthroughContext") );
02726 
02727           ftc=getIdFromString(&ContextNameList, tmpFtc,dummy);
02728           if (ftc == -1) ftc =0;
02729 
02730           kdDebug(13010)<<"Setting fall through context (context "<<i<<"): "<<ftc<<endl;
02731         }
02732       }
02733       //END falltrhough props
02734 
02735       bool dynamic = false;
02736       QString tmpDynamic = KateHlManager::self()->syntax->groupData(data, QString("dynamic") );
02737       if ( tmpDynamic.lower() == "true" ||  tmpDynamic.toInt() == 1 )
02738         dynamic = true;
02739 
02740       KateHlContext *ctxNew = new KateHlContext (
02741         ident,
02742         attr,
02743         context,
02744         (KateHlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1:
02745         (KateHlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt(),
02746         ft, ftc, dynamic,noIndentationBasedFolding);
02747 
02748       m_contexts.push_back (ctxNew);
02749 
02750       kdDebug(13010) << "INDEX: " << i << " LENGTH " << m_contexts.size()-1 << endl;
02751 
02752       //Let's create all items for the context
02753       while (KateHlManager::self()->syntax->nextItem(data))
02754       {
02755 //    kdDebug(13010)<< "In make Contextlist: Item:"<<endl;
02756 
02757       // KateHlIncludeRules : add a pointer to each item in that context
02758         // TODO add a attrib includeAttrib
02759       QString tag = KateHlManager::self()->syntax->groupItemData(data,QString(""));
02760       if ( tag == "IncludeRules" ) //if the new item is an Include rule, we have to take special care
02761       {
02762         QString incCtx = KateHlManager::self()->syntax->groupItemData( data, QString("context"));
02763         QString incAttrib = KateHlManager::self()->syntax->groupItemData( data, QString("includeAttrib"));
02764         bool includeAttrib = IS_TRUE( incAttrib );
02765         // only context refernces of type Name, ##Name, and Subname##Name are allowed
02766         if (incCtx.startsWith("##") || (!incCtx.startsWith("#")))
02767         {
02768           int incCtxi = incCtx.find("##");
02769           //#stay, #pop is not interesting here
02770           if (incCtxi >= 0)
02771           {
02772             QString incSet = incCtx.mid(incCtxi + 2);
02773             QString incCtxN = incSet + ":" + incCtx.left(incCtxi);
02774 
02775             //a cross highlighting reference
02776             kdDebug(13010)<<"Cross highlight reference <IncludeRules>, context "<<incCtxN<<endl;
02777             KateHlIncludeRule *ir=new KateHlIncludeRule(i,m_contexts[i]->items.count(),incCtxN,includeAttrib);
02778 
02779             //use the same way to determine cross hl file references as other items do
02780             if (!embeddedHls.contains(incSet))
02781               embeddedHls.insert(incSet,KateEmbeddedHlInfo());
02782             else
02783               kdDebug(13010)<<"Skipping embeddedHls.insert for "<<incCtxN<<endl;
02784 
02785             unresolvedContextReferences.insert(&(ir->incCtx), incCtxN);
02786 
02787             includeRules.append(ir);
02788           }
02789           else
02790           {
02791             // a local reference -> just initialize the include rule structure
02792             incCtx=buildPrefix+incCtx.simplifyWhiteSpace();
02793             includeRules.append(new KateHlIncludeRule(i,m_contexts[i]->items.count(),incCtx, includeAttrib));
02794           }
02795         }
02796 
02797         continue;
02798       }
02799       // TODO -- can we remove the block below??
02800 #if 0
02801                 QString tag = KateHlManager::self()->syntax->groupKateHlItemData(data,QString(""));
02802                 if ( tag == "IncludeRules" ) {
02803                   // attrib context: the index (jowenn, i think using names here
02804                   // would be a cool feat, goes for mentioning the context in
02805                   // any item. a map or dict?)
02806                   int ctxId = getIdFromString(&ContextNameList,
02807                                                KateHlManager::self()->syntax->groupKateHlItemData( data, QString("context")),dummy); // the index is *required*
02808                   if ( ctxId > -1) { // we can even reuse rules of 0 if we want to:)
02809                     kdDebug(13010)<<"makeContextList["<<i<<"]: including all items of context "<<ctxId<<endl;
02810                     if ( ctxId < (int) i ) { // must be defined
02811                       for ( c = m_contexts[ctxId]->items.first(); c; c = m_contexts[ctxId]->items.next() )
02812                         m_contexts[i]->items.append(c);
02813                     }
02814                     else
02815                       kdDebug(13010)<<"Context "<<ctxId<<"not defined. You can not include the rules of an undefined context"<<endl;
02816                   }
02817                   continue; // while nextItem
02818                 }
02819 #endif
02820       c=createKateHlItem(data,iDl,&RegionList,&ContextNameList);
02821       if (c)
02822       {
02823         m_contexts[i]->items.append(c);
02824 
02825         // Not supported completely atm and only one level. Subitems.(all have
02826         // to be matched to at once)
02827         datasub=KateHlManager::self()->syntax->getSubItems(data);
02828         bool tmpbool;
02829         if (tmpbool=KateHlManager::self()->syntax->nextItem(datasub))
02830         {
02831           for (;tmpbool;tmpbool=KateHlManager::self()->syntax->nextItem(datasub))
02832           {
02833             c->subItems.resize (c->subItems.size()+1);
02834             c->subItems[c->subItems.size()-1] = createKateHlItem(datasub,iDl,&RegionList,&ContextNameList);
02835           }                             }
02836           KateHlManager::self()->syntax->freeGroupInfo(datasub);
02837                               // end of sublevel
02838         }
02839       }
02840       i++;
02841     }
02842   }
02843 
02844   KateHlManager::self()->syntax->freeGroupInfo(data);
02845 
02846   if (RegionList.count()!=1)
02847     folding=true;
02848 
02849   folding = folding || m_foldingIndentationSensitive;
02850 
02851   //BEGIN Resolve multiline region if possible
02852   if (!m_additionalData[ ident ]->multiLineRegion.isEmpty()) {
02853     long commentregionid=RegionList.findIndex( m_additionalData[ ident ]->multiLineRegion );
02854     if (-1==commentregionid) {
02855       errorsAndWarnings+=i18n(
02856           "<B>%1</B>: Specified multiline comment region (%2) could not be resolved<BR>"
02857                              ).arg(buildIdentifier).arg( m_additionalData[ ident ]->multiLineRegion );
02858       m_additionalData[ ident ]->multiLineRegion = QString();
02859       kdDebug(13010)<<"ERROR comment region attribute could not be resolved"<<endl;
02860 
02861     } else {
02862       m_additionalData[ ident ]->multiLineRegion=QString::number(commentregionid+1);
02863       kdDebug(13010)<<"comment region resolved to:"<<m_additionalData[ ident ]->multiLineRegion<<endl;
02864     }
02865   }
02866   //END Resolve multiline region if possible
02867   return i;
02868 }
02869 
02870 void KateHighlighting::clearAttributeArrays ()
02871 {
02872   for ( QIntDictIterator< QMemArray<KateAttribute> > it( m_attributeArrays ); it.current(); ++it )
02873   {
02874     // k, schema correct, let create the data
02875     KateAttributeList defaultStyleList;
02876     defaultStyleList.setAutoDelete(true);
02877     KateHlManager::self()->getDefaults(it.currentKey(), defaultStyleList);
02878 
02879     KateHlItemDataList itemDataList;
02880     getKateHlItemDataList(it.currentKey(), itemDataList);
02881 
02882     uint nAttribs = itemDataList.count();
02883     QMemArray<KateAttribute> *array = it.current();
02884     array->resize (nAttribs);
02885 
02886     for (uint z = 0; z < nAttribs; z++)
02887     {
02888       KateHlItemData *itemData = itemDataList.at(z);
02889       KateAttribute n = *defaultStyleList.at(itemData->defStyleNum);
02890 
02891       if (itemData && itemData->isSomethingSet())
02892         n += *itemData;
02893 
02894       array->at(z) = n;
02895     }
02896   }
02897 }
02898 
02899 QMemArray<KateAttribute> *KateHighlighting::attributes (uint schema)
02900 {
02901   QMemArray<KateAttribute> *array;
02902 
02903   // found it, allready floating around
02904   if ((array = m_attributeArrays[schema]))
02905     return array;
02906 
02907   // ohh, not found, check if valid schema number
02908   if (!KateFactory::self()->schemaManager()->validSchema(schema))
02909   {
02910     // uhh, not valid :/, stick with normal default schema, it's always there !
02911     return attributes (0);
02912   }
02913 
02914   // k, schema correct, let create the data
02915   KateAttributeList defaultStyleList;
02916   defaultStyleList.setAutoDelete(true);
02917   KateHlManager::self()->getDefaults(schema, defaultStyleList);
02918 
02919   KateHlItemDataList itemDataList;
02920   getKateHlItemDataList(schema, itemDataList);
02921 
02922   uint nAttribs = itemDataList.count();
02923   array = new QMemArray<KateAttribute> (nAttribs);
02924 
02925   for (uint z = 0; z < nAttribs; z++)
02926   {
02927     KateHlItemData *itemData = itemDataList.at(z);
02928     KateAttribute n = *defaultStyleList.at(itemData->defStyleNum);
02929 
02930     if (itemData && itemData->isSomethingSet())
02931       n += *itemData;
02932 
02933     array->at(z) = n;
02934   }
02935 
02936   m_attributeArrays.insert(schema, array);
02937 
02938   return array;
02939 }
02940 
02941 void KateHighlighting::getKateHlItemDataListCopy (uint schema, KateHlItemDataList &outlist)
02942 {
02943   KateHlItemDataList itemDataList;
02944   getKateHlItemDataList(schema, itemDataList);
02945 
02946   outlist.clear ();
02947   outlist.setAutoDelete (true);
02948   for (uint z=0; z < itemDataList.count(); z++)
02949     outlist.append (new KateHlItemData (*itemDataList.at(z)));
02950 }
02951 
02952 //END
02953 
02954 //BEGIN KateHlManager
02955 KateHlManager::KateHlManager()
02956   : QObject()
02957   , m_config ("katesyntaxhighlightingrc", false, false)
02958   , commonSuffixes (QStringList::split(";", ".orig;.new;~;.bak;.BAK"))
02959   , syntax (new KateSyntaxDocument())
02960   , dynamicCtxsCount(0)
02961   , forceNoDCReset(false)
02962 {
02963   hlList.setAutoDelete(true);
02964   hlDict.setAutoDelete(false);
02965 
02966   KateSyntaxModeList modeList = syntax->modeList();
02967   for (uint i=0; i < modeList.count(); i++)
02968   {
02969     KateHighlighting *hl = new KateHighlighting(modeList[i]);
02970 
02971     uint insert = 0;
02972     for (; insert <= hlList.count(); insert++)
02973     {
02974       if (insert == hlList.count())
02975         break;
02976 
02977       if ( QString(hlList.at(insert)->section() + hlList.at(insert)->nameTranslated()).lower()
02978             > QString(hl->section() + hl->nameTranslated()).lower() )
02979         break;
02980     }
02981 
02982     hlList.insert (insert, hl);
02983     hlDict.insert (hl->name(), hl);
02984   }
02985 
02986   // Normal HL
02987   KateHighlighting *hl = new KateHighlighting(0);
02988   hlList.prepend (hl);
02989   hlDict.insert (hl->name(), hl);
02990 
02991   lastCtxsReset.start();
02992 }
02993 
02994 KateHlManager::~KateHlManager()
02995 {
02996   delete syntax;
02997 }
02998 
02999 static KStaticDeleter<KateHlManager> sdHlMan;
03000 
03001 KateHlManager *KateHlManager::self()
03002 {
03003   if ( !s_self )
03004     sdHlMan.setObject(s_self, new KateHlManager ());
03005 
03006   return s_self;
03007 }
03008 
03009 KateHighlighting *KateHlManager::getHl(int n)
03010 {
03011   if (n < 0 || n >= (int) hlList.count())
03012     n = 0;
03013 
03014   return hlList.at(n);
03015 }
03016 
03017 int KateHlManager::nameFind(const QString &name)
03018 {
03019   int z (hlList.count() - 1);
03020   for (; z > 0; z--)
03021     if (hlList.at(z)->name() == name)
03022       return z;
03023 
03024   return z;
03025 }
03026 
03027 int KateHlManager::detectHighlighting (KateDocument *doc)
03028 {
03029   int hl = wildcardFind( doc->url().filename() );
03030   if ( hl < 0 )
03031     hl = mimeFind ( doc );
03032 
03033   return hl;
03034 }
03035 
03036 int KateHlManager::wildcardFind(const QString &fileName)
03037 {
03038   int result = -1;
03039   if ((result = realWildcardFind(fileName)) != -1)
03040     return result;
03041 
03042   int length = fileName.length();
03043   QString backupSuffix = KateDocumentConfig::global()->backupSuffix();
03044   if (fileName.endsWith(backupSuffix)) {
03045     if ((result = realWildcardFind(fileName.left(length - backupSuffix.length()))) != -1)
03046       return result;
03047   }
03048 
03049   for (QStringList::Iterator it = commonSuffixes.begin(); it != commonSuffixes.end(); ++it) {
03050     if (*it != backupSuffix && fileName.endsWith(*it)) {
03051       if ((result = realWildcardFind(fileName.left(length - (*it).length()))) != -1)
03052         return result;
03053     }
03054   }
03055 
03056   return -1;
03057 }
03058 
03059 int KateHlManager::realWildcardFind(const QString &fileName)
03060 {
03061   static QRegExp sep("\\s*;\\s*");
03062 
03063   QPtrList<KateHighlighting> highlights;
03064 
03065   for (KateHighlighting *highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) {
03066     highlight->loadWildcards();
03067 
03068     for (QStringList::Iterator it = highlight->getPlainExtensions().begin(); it != highlight->getPlainExtensions().end(); ++it)
03069       if (fileName.endsWith((*it)))
03070         highlights.append(highlight);
03071 
03072     for (int i = 0; i < (int)highlight->getRegexpExtensions().count(); i++) {
03073       QRegExp re = highlight->getRegexpExtensions()[i];
03074       if (re.exactMatch(fileName))
03075         highlights.append(highlight);
03076     }
03077   }
03078 
03079   if ( !highlights.isEmpty() )
03080   {
03081     int pri = -1;
03082     int hl = -1;
03083 
03084     for (KateHighlighting *highlight = highlights.first(); highlight != 0L; highlight = highlights.next())
03085     {
03086       if (highlight->priority() > pri)
03087       {
03088         pri = highlight->priority();
03089         hl = hlList.findRef (highlight);
03090       }
03091     }
03092     return hl;
03093   }
03094 
03095   return -1;
03096 }
03097 
03098 int KateHlManager::mimeFind( KateDocument *doc )
03099 {
03100   static QRegExp sep("\\s*;\\s*");
03101 
03102   KMimeType::Ptr mt = doc->mimeTypeForContent();
03103 
03104   QPtrList<KateHighlighting> highlights;
03105 
03106   for (KateHighlighting *highlight = hlList.first(); highlight != 0L; highlight = hlList.next())
03107   {
03108     QStringList l = QStringList::split( sep, highlight->getMimetypes() );
03109 
03110     for( QStringList::Iterator it = l.begin(); it != l.end(); ++it )
03111     {
03112       if ( *it == mt->name() ) // faster than a regexp i guess?
03113         highlights.append (highlight);
03114     }
03115   }
03116 
03117   if ( !highlights.isEmpty() )
03118   {
03119     int pri = -1;
03120     int hl = -1;
03121 
03122     for (KateHighlighting *highlight = highlights.first(); highlight != 0L; highlight = highlights.next())
03123     {
03124       if (highlight->priority() > pri)
03125       {
03126         pri = highlight->priority();
03127         hl = hlList.findRef (highlight);
03128       }
03129     }
03130 
03131     return hl;
03132   }
03133 
03134   return -1;
03135 }
03136 
03137 uint KateHlManager::defaultStyles()
03138 {
03139   return 14;
03140 }
03141 
03142 QString KateHlManager::defaultStyleName(int n, bool translateNames)
03143 {
03144   static QStringList names;
03145   static QStringList translatedNames;
03146 
03147   if (names.isEmpty())
03148   {
03149     names << "Normal";
03150     names << "Keyword";
03151     names << "Data Type";
03152     names << "Decimal/Value";
03153     names << "Base-N Integer";
03154     names << "Floating Point";
03155     names << "Character";
03156     names << "String";
03157     names << "Comment";
03158     names << "Others";
03159     names << "Alert";
03160     names << "Function";
03161     // this next one is for denoting the beginning/end of a user defined folding region
03162     names << "Region Marker";
03163     // this one is for marking invalid input
03164     names << "Error";
03165 
03166     translatedNames << i18n("Normal");
03167     translatedNames << i18n("Keyword");
03168     translatedNames << i18n("Data Type");
03169     translatedNames << i18n("Decimal/Value");
03170     translatedNames << i18n("Base-N Integer");
03171     translatedNames << i18n("Floating Point");
03172     translatedNames << i18n("Character");
03173     translatedNames << i18n("String");
03174     translatedNames << i18n("Comment");
03175     translatedNames << i18n("Others");
03176     translatedNames << i18n("Alert");
03177     translatedNames << i18n("Function");
03178     // this next one is for denoting the beginning/end of a user defined folding region
03179     translatedNames << i18n("Region Marker");
03180     // this one is for marking invalid input
03181     translatedNames << i18n("Error");
03182   }
03183 
03184   return translateNames ? translatedNames[n] : names[n];
03185 }
03186 
03187 void KateHlManager::getDefaults(uint schema, KateAttributeList &list)
03188 {
03189   list.setAutoDelete(true);
03190 
03191   KateAttribute* normal = new KateAttribute();
03192   normal->setTextColor(Qt::black);
03193   normal->setSelectedTextColor(Qt::white);
03194   list.append(normal);
03195 
03196   KateAttribute* keyword = new KateAttribute();
03197   keyword->setTextColor(Qt::black);
03198   keyword->setSelectedTextColor(Qt::white);
03199   keyword->setBold(true);
03200   list.append(keyword);
03201 
03202   KateAttribute* dataType = new KateAttribute();
03203   dataType->setTextColor(Qt::darkRed);
03204   dataType->setSelectedTextColor(Qt::white);
03205   list.append(dataType);
03206 
03207   KateAttribute* decimal = new KateAttribute();
03208   decimal->setTextColor(Qt::blue);
03209   decimal->setSelectedTextColor(Qt::cyan);
03210   list.append(decimal);
03211 
03212   KateAttribute* basen = new KateAttribute();
03213   basen->setTextColor(Qt::darkCyan);
03214   basen->setSelectedTextColor(Qt::cyan);
03215   list.append(basen);
03216 
03217   KateAttribute* floatAttribute = new KateAttribute();
03218   floatAttribute->setTextColor(Qt::darkMagenta);
03219   floatAttribute->setSelectedTextColor(Qt::cyan);
03220   list.append(floatAttribute);
03221 
03222   KateAttribute* charAttribute = new KateAttribute();
03223   charAttribute->setTextColor(Qt::magenta);
03224   charAttribute->setSelectedTextColor(Qt::magenta);
03225   list.append(charAttribute);
03226 
03227   KateAttribute* string = new KateAttribute();
03228   string->setTextColor(QColor("#D00"));
03229   string->setSelectedTextColor(Qt::red);
03230   list.append(string);
03231 
03232   KateAttribute* comment = new KateAttribute();
03233   comment->setTextColor(Qt::darkGray);
03234   comment->setSelectedTextColor(Qt::gray);
03235   comment->setItalic(true);
03236   list.append(comment);
03237 
03238   KateAttribute* others = new KateAttribute();
03239   others->setTextColor(Qt::darkGreen);
03240   others->setSelectedTextColor(Qt::green);
03241   list.append(others);
03242 
03243   KateAttribute* alert = new KateAttribute();
03244   alert->setTextColor(Qt::black);
03245   alert->setSelectedTextColor( QColor("#FCC") );
03246   alert->setBold(true);
03247   alert->setBGColor( QColor("#FCC") );
03248   list.append(alert);
03249 
03250   KateAttribute* functionAttribute = new KateAttribute();
03251   functionAttribute->setTextColor(Qt::darkBlue);
03252   functionAttribute->setSelectedTextColor(Qt::white);
03253   list.append(functionAttribute);
03254 
03255   KateAttribute* regionmarker = new KateAttribute();
03256   regionmarker->setTextColor(Qt::white);
03257   regionmarker->setBGColor(Qt::gray);
03258   regionmarker->setSelectedTextColor(Qt::gray);
03259   list.append(regionmarker);
03260 
03261   KateAttribute* error = new KateAttribute();
03262   error->setTextColor(Qt::red);
03263   error->setUnderline(true);
03264   error->setSelectedTextColor(Qt::red);
03265   list.append(error);
03266 
03267   KConfig *config = KateHlManager::self()->self()->getKConfig();
03268   config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema));
03269 
03270   for (uint z = 0; z < defaultStyles(); z++)
03271   {
03272     KateAttribute *i = list.at(z);
03273     QStringList s = config->readListEntry(defaultStyleName(z));
03274     if (!s.isEmpty())
03275     {
03276       while( s.count()<8)
03277         s << "";
03278 
03279       QString tmp;
03280       QRgb col;
03281 
03282       tmp=s[0]; if (!tmp.isEmpty()) {
03283          col=tmp.toUInt(0,16); i->setTextColor(col); }
03284 
03285       tmp=s[1]; if (!tmp.isEmpty()) {
03286          col=tmp.toUInt(0,16); i->setSelectedTextColor(col); }
03287 
03288       tmp=s[2]; if (!tmp.isEmpty()) i->setBold(tmp!="0");
03289 
03290       tmp=s[3]; if (!tmp.isEmpty()) i->setItalic(tmp!="0");
03291 
03292       tmp=s[4]; if (!tmp.isEmpty()) i->setStrikeOut(tmp!="0");
03293 
03294       tmp=s[5]; if (!tmp.isEmpty()) i->setUnderline(tmp!="0");
03295 
03296       tmp=s[6]; if (!tmp.isEmpty()) {
03297         if ( tmp != "-" )
03298         {
03299           col=tmp.toUInt(0,16);
03300           i->setBGColor(col);
03301         }
03302         else
03303           i->clearAttribute(KateAttribute::BGColor);
03304       }
03305       tmp=s[7]; if (!tmp.isEmpty()) {
03306         if ( tmp != "-" )
03307         {
03308           col=tmp.toUInt(0,16);
03309           i->setSelectedBGColor(col);
03310         }
03311         else
03312           i->clearAttribute(KateAttribute::SelectedBGColor);
03313       }
03314     }
03315   }
03316 }
03317 
03318 void KateHlManager::setDefaults(uint schema, KateAttributeList &list)
03319 {
03320   KConfig *config =  KateHlManager::self()->self()->getKConfig();
03321   config->setGroup("Default Item Styles - Schema " + KateFactory::self()->schemaManager()->name(schema));
03322 
03323   for (uint z = 0; z < defaultStyles(); z++)
03324   {
03325     QStringList settings;
03326     KateAttribute *i = list.at(z);
03327 
03328     settings<<(i->itemSet(KateAttribute::TextColor)?QString::number(i->textColor().rgb(),16):"");
03329     settings<<(i->itemSet(KateAttribute::SelectedTextColor)?QString::number(i->selectedTextColor().rgb(),16):"");
03330     settings<<(i->itemSet(KateAttribute::Weight)?(i->bold()?"1":"0"):"");
03331     settings<<(i->itemSet(KateAttribute::Italic)?(i->italic()?"1":"0"):"");
03332     settings<<(i->itemSet(KateAttribute::StrikeOut)?(i->strikeOut()?"1":"0"):"");
03333     settings<<(i->itemSet(KateAttribute::Underline)?(i->underline()?"1":"0"):"");
03334     settings<<(i->itemSet(KateAttribute::BGColor)?QString::number(i->bgColor().rgb(),16):"-");
03335     settings<<(i->itemSet(KateAttribute::SelectedBGColor)?QString::number(i->selectedBGColor().rgb(),16):"-");
03336     settings<<"---";
03337 
03338     config->writeEntry(defaultStyleName(z),settings);
03339   }
03340 
03341   emit changed();
03342 }
03343 
03344 int KateHlManager::highlights()
03345 {
03346   return (int) hlList.count();
03347 }
03348 
03349 QString KateHlManager::hlName(int n)
03350 {
03351   return hlList.at(n)->name();
03352 }
03353 
03354 QString KateHlManager::hlNameTranslated(int n)
03355 {
03356   return hlList.at(n)->nameTranslated();
03357 }
03358 
03359 QString KateHlManager::hlSection(int n)
03360 {
03361   return hlList.at(n)->section();
03362 }
03363 
03364 bool KateHlManager::hlHidden(int n)
03365 {
03366   return hlList.at(n)->hidden();
03367 }
03368 
03369 QString KateHlManager::identifierForName(const QString& name)
03370 {
03371   KateHighlighting *hl = 0;
03372 
03373   if ((hl = hlDict[name]))
03374     return hl->getIdentifier ();
03375 
03376   return QString();
03377 }
03378 
03379 bool KateHlManager::resetDynamicCtxs()
03380 {
03381   if (forceNoDCReset)
03382     return false;
03383 
03384   if (lastCtxsReset.elapsed() < KATE_DYNAMIC_CONTEXTS_RESET_DELAY)
03385     return false;
03386 
03387   KateHighlighting *hl;
03388   for (hl = hlList.first(); hl; hl = hlList.next())
03389     hl->dropDynamicContexts();
03390 
03391   dynamicCtxsCount = 0;
03392   lastCtxsReset.start();
03393 
03394   return true;
03395 }
03396 //END
03397 
03398 //BEGIN KateHighlightAction
03399 void KateViewHighlightAction::init()
03400 {
03401   m_doc = 0;
03402   subMenus.setAutoDelete( true );
03403 
03404   connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow()));
03405 }
03406 
03407 void KateViewHighlightAction::updateMenu (Kate::Document *doc)
03408 {
03409   m_doc = doc;
03410 }
03411 
03412 void KateViewHighlightAction::slotAboutToShow()
03413 {
03414   Kate::Document *doc=m_doc;
03415   int count = KateHlManager::self()->highlights();
03416 
03417   for (int z=0; z<count; z++)
03418   {
03419     QString hlName = KateHlManager::self()->hlNameTranslated (z);
03420     QString hlSection = KateHlManager::self()->hlSection (z);
03421 
03422     if (!KateHlManager::self()->hlHidden(z))
03423     {
03424       if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) )
03425       {
03426         if (subMenusName.contains(hlSection) < 1)
03427         {
03428           subMenusName << hlSection;
03429           QPopupMenu *menu = new QPopupMenu ();
03430           subMenus.append(menu);
03431           popupMenu()->insertItem ( '&' + hlSection, menu);
03432         }
03433 
03434         int m = subMenusName.findIndex (hlSection);
03435         names << hlName;
03436         subMenus.at(m)->insertItem ( '&' + hlName, this, SLOT(setHl(int)), 0,  z);
03437       }
03438       else if (names.contains(hlName) < 1)
03439       {
03440         names << hlName;
03441         popupMenu()->insertItem ( '&' + hlName, this, SLOT(setHl(int)), 0,  z);
03442       }
03443     }
03444   }
03445 
03446   if (!doc) return;
03447 
03448   for (uint i=0;i<subMenus.count();i++)
03449   {
03450     for (uint i2=0;i2<subMenus.at(i)->count();i2++)
03451     {
03452       subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false);
03453     }
03454   }
03455   popupMenu()->setItemChecked (0, false);
03456 
03457   int i = subMenusName.findIndex (KateHlManager::self()->hlSection(doc->hlMode()));
03458   if (i >= 0 && subMenus.at(i))
03459     subMenus.at(i)->setItemChecked (doc->hlMode(), true);
03460   else
03461     popupMenu()->setItemChecked (0, true);
03462 }
03463 
03464 void KateViewHighlightAction::setHl (int mode)
03465 {
03466   Kate::Document *doc=m_doc;
03467 
03468   if (doc)
03469     doc->setHlMode((uint)mode);
03470 }
03471 //END KateViewHighlightAction
03472 
03473 // kate: space-indent on; indent-width 2; replace-tabs on;

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal