kate Library API Documentation

katehighlight.cpp

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