00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
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 
00051 
00052 
00053 #define KATE_HL_HOWMANY 1024
00054 
00055 
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     
00069     
00070     
00071     
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; 
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 
00290 
00291 
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 
00299 
00300 
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 
00317 
00318 
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   
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   
00337   
00338   Q_ASSERT(false);
00339   return stdDeliminator.find(c) != -1;
00340 }
00341 
00342 
00343 
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 
00357 
00358 
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 
00377 
00378 
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 
00398 
00399 
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 
00423 
00424 
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 
00452 
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 
00482 
00483 
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 
00521 
00522 
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 
00620 
00621 
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 
00658 
00659 
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 
00695 
00696 
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 
00743 
00744 
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 
00759 
00760 
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 )
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 
00782 
00783 
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 
00796 
00797 
00798 HlCStringChar::HlCStringChar(int attribute, int context,signed char regionId,signed char regionId2)
00799   : HlItem(attribute,context,regionId,regionId2) {
00800 }
00801 
00802 
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': 
00814       case  'b': 
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 '?' : 
00825       case '\\':
00826         offset++;
00827         len--;
00828         break;
00829 
00830       case 'x': 
00831         offset++; 
00832         len--;
00833         
00834         
00835         
00836         
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; 
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 
00872 
00873 
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 
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 
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   
00975 
00976   if (lineContinue)
00977   {
00978     if ( !ctxs->isEmpty() )
00979     {
00980       (*ctxNum)=(*ctxs)[ctxs->size()-1];
00981       (*prevLine)--;
00982     }
00983     else
00984     {
00985       
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           
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           
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 
01044 
01045 
01046 
01047 
01048 
01049 
01050 
01051 
01052 
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 
01068 
01069   HlContext *context;
01070 
01071   
01072 
01073   int ctxNum;
01074   int prevLine;
01075 
01076   QMemArray<short> ctx;
01077   ctx.duplicate (oCtx);
01078 
01079   if ( oCtx.isEmpty() )
01080   {
01081     
01082     ctxNum=0;
01083     context=contextNum(ctxNum);
01084     prevLine=-1;
01085   }
01086   else
01087   {
01088     
01089     ctxNum=ctx[oCtx.size()-1]; 
01090 
01091     
01092 
01093     
01094 
01095     if (!(context = contextNum(ctxNum)))
01096       context = contextNum(0);
01097 
01098     
01099 
01100     prevLine=oCtx.size()-1; 
01101 
01102     
01103     generateContextStack(&ctxNum, context->ctx, &ctx, &prevLine, lineContinue); 
01104 
01105     
01106 
01107     if (!(context = contextNum(ctxNum)))
01108       context = contextNum(0);
01109 
01110     
01111   }
01112 
01113   
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           
01161 
01162           if (item->region)
01163           {
01164 
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 
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);  
01195 
01196       
01197     
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     
01212     
01213     if (!found)
01214     {
01215       if ( context->fallthrough )
01216       {
01217         
01218         generateContextStack(&ctxNum, context->ftctx, &ctx, &prevLine);  
01219         context=contextNum(ctxNum);
01220         
01221         
01222         
01223         
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 
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 
01372 
01373 
01374 
01375 
01376 
01377 
01378 
01379 
01380 
01381 
01382 
01383 
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 
01412 
01413 
01414 
01415 
01416 
01417 
01418 
01419 
01420 
01421 void Highlight::use()
01422 {
01423   if (refCount == 0)
01424     init();
01425 
01426   refCount++;
01427 }
01428 
01429 
01430 
01431 
01432 
01433 
01434 
01435 
01436 
01437 
01438 
01439 
01440 void Highlight::release()
01441 {
01442   refCount--;
01443 
01444   if (refCount == 0)
01445     done();
01446 }
01447 
01448 
01449 
01450 
01451 
01452 
01453 
01454 
01455 
01456 
01457 
01458 
01459 void Highlight::init()
01460 {
01461   if (noHl)
01462     return;
01463 
01464   contextList.clear ();
01465   makeContextList();
01466 }
01467 
01468 
01469 
01470 
01471 
01472 
01473 
01474 
01475 
01476 
01477 
01478 
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 
01496 
01497 
01498 
01499 
01500 
01501 
01502 
01503 
01504 
01505 
01506 
01507 
01508 void Highlight::createItemData(ItemDataList &list)
01509 {
01510   
01511   if (noHl)
01512   {
01513     list.append(new ItemData(I18N_NOOP("Normal Text"), dsNormal));
01514     return;
01515   }
01516 
01517   
01518   if (internalIDList.isEmpty())
01519     makeContextList();
01520 
01521   list=internalIDList;
01522 }
01523 
01524 void Highlight::addToItemDataList()
01525 {
01526   
01527   HlManager::self()->syntax->setIdentifier(buildIdentifier);
01528   syntaxContextData *data = HlManager::self()->syntax->getGroupInfo("highlighting","itemData");
01529 
01530   
01531   while (HlManager::self()->syntax->nextGroup(data))
01532   {
01533     
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       
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       
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   
01563   if (data)
01564     HlManager::self()->syntax->freeGroupInfo(data);
01565 }
01566 
01567 
01568 
01569 
01570 
01571 
01572 
01573 
01574 
01575 
01576 
01577 
01578 
01579 
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 
01594 
01595 
01596 
01597 
01598 
01599 
01600 
01601 
01602 
01603 
01604 
01605 
01606 
01607 
01608 
01609 
01610 
01611 HlItem *Highlight::createHlItem(struct syntaxContextData *data, ItemDataList &iDl,QStringList *RegionList, QStringList *ContextNameList)
01612 {
01613   
01614   if (noHl)
01615     return 0;
01616 
01617   
01618   QString dataname=HlManager::self()->syntax->groupItemData(data,QString(""));
01619 
01620   
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   
01632 
01633   
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   
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   
01649   QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String"));
01650 
01651   
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   
01659   bool insensitive=( HlManager::self()->syntax->groupItemData(data,QString("insensitive")).lower() == QString("true") );
01660   
01661 
01662   
01663   bool minimal = ( HlManager::self()->syntax->groupItemData(data,QString("minimal")).lower() == QString("true") );
01664 
01665 
01666   
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) 
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) 
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   
01704   HlItem *tmpItem;
01705 
01706   if (dataname=="keyword")
01707   {
01708     HlKeyword *keyword=new HlKeyword(attr,context,regionId,regionId2,casesensitive,
01709       deliminator);
01710 
01711     
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     
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 
01745 
01746 
01747 
01748 
01749 
01750 
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 
01761 
01762 
01763 
01764 
01765 
01766 
01767 
01768 
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 
01802 
01803 
01804 
01805 
01806 
01807 
01808 
01809 
01810 
01811 
01812 
01813 
01814 void Highlight::readGlobalKeywordConfig()
01815 {
01816   
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     
01832     weakDeliminator=(HlManager::self()->syntax->groupItemData(data,QString("weakDeliminator")));
01833 
01834     kdDebug(13010)<<"weak delimiters are: "<<weakDeliminator<<endl;
01835 
01836     
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     
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   
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     
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,  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 
01959 
01960   }
01961   return context;
01962 }
01963 
01964 
01965 
01966 
01967 
01968 
01969 
01970 
01971 
01972 
01973 
01974 
01975 
01976 
01977 void Highlight::makeContextList()
01978 {
01979   if (noHl)  
01980     return;
01981 
01982   embeddedHls.clear();
01983   unresolvedContextReferences.clear();
01984   RegionList.clear();
01985   ContextNameList.clear();
01986 
01987   
01988   embeddedHls.insert(iName,EmbeddedHlInfo());
01989 
01990   bool something_changed;
01991   int startctx=0;  
01992   building=true;  
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; 
01998   for (EmbeddedHlInfos::const_iterator it=embeddedHls.begin(); it!=embeddedHls.end();++it)
01999   {
02000     if (!it.data().loaded)  
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;  
02006       else
02007         identifierToUse=HlManager::self()->identifierForName(it.key()); 
02008 
02009       kdDebug(13010)<<"Location is:"<< identifierToUse<<endl;
02010 
02011       buildPrefix=it.key()+':';  
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)); 
02017       buildContext0Offset=startctx;  
02018       startctx=addToContextList(identifierToUse,startctx);  
02019       if (noHl) return;  
02020       something_changed=true; 
02021 
02022     }
02023   }
02024   } while (something_changed);  
02025 
02026 
02027   
02028 
02029 
02030   kdDebug(13010)<<"Unresolved contexts, which need attention: "<<unresolvedContextReferences.count()<<endl;
02031 
02032   for (UnresolvedContextReferences::iterator unresIt=unresolvedContextReferences.begin();
02033     unresIt!=unresolvedContextReferences.end();++unresIt)
02034   {
02035     
02036     EmbeddedHlInfos::const_iterator hlIt=embeddedHls.find(unresIt.data());
02037     if (hlIt!=embeddedHls.end())
02038       *(unresIt.key())=hlIt.data().context0;
02039   }
02040 
02041   
02042 
02043 
02044   handleIncludeRules();
02045 
02046   embeddedHls.clear(); 
02047   unresolvedContextReferences.clear(); 
02048   RegionList.clear();  
02049   ContextNameList.clear();
02050 
02051 
02052 
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 
02057   building=false;
02058 }
02059 
02060 void Highlight::handleIncludeRules()
02061 {
02062 
02063   
02064   kdDebug(13010)<<"IncludeRules, which need attention: " <<includeRules.count()<<endl;
02065   if (includeRules.isEmpty()) return;
02066 
02067   buildPrefix="";
02068   QString dummy;
02069 
02070   
02071 
02072 
02073 
02074 
02075   
02076   for (IncludeRules::iterator it=includeRules.begin();it!=includeRules.end();)
02077   {
02078 
02079   if ((*it)->incCtx==-1) 
02080   { 
02081 
02082     if ((*it)->incCtxN.isEmpty())
02083     {
02084       
02085       IncludeRules::iterator it1=it;
02086       ++it1;
02087       delete (*it);
02088       includeRules.remove(it);
02089       it=it1;
02090     }
02091     else
02092     {
02093       
02094       (*it)->incCtx=getIdFromString(&ContextNameList,(*it)->incCtxN,dummy);
02095       kdDebug()<<"Resolved "<<(*it)->incCtxN<< " to "<<(*it)->incCtx<<" for include rule"<<endl;
02096       
02097     }
02098   } else ++it; 
02099   }
02100 
02101   
02102   
02103   
02104 
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;  
02114   IncludeRules::iterator it1=it;
02115   int ctx=(*it1)->ctx;
02116 
02117   
02118 
02119 
02120 
02121 
02122 
02123 
02124 
02125   while ((it!=list->end()) && ((*it)->ctx==ctx))
02126   {
02127     it1=it;
02128     ++it;
02129 
02130   }
02131   
02132   while ((it1!=list->end()) && ((*it1)->ctx==ctx))
02133   {
02134 
02135 
02136 
02137     int ctx1=(*it1)->incCtx;
02138 
02139     
02140     for (IncludeRules::iterator it2=list->begin();it2!=list->end();++it2)
02141     {
02142 
02143 
02144       if ((*it2)->ctx==ctx1)
02145       {
02146         
02147         
02148         handleIncludeRulesRecursive(it2,list);
02149         break;
02150       }
02151     }
02152 
02153     
02154     HlContext *dest=contextList[ctx];
02155     HlContext *src=contextList[ctx1];
02156     uint p=(*it1)->pos; 
02157     for ( HlItem *c = src->items.first(); c; c=src->items.next(), p++ )
02158                         dest->items.insert(p,c);
02159 
02160     it=it1; 
02161     --it1; 
02162     delete (*it); 
02163     list->remove(it); 
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   
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   
02191   addToItemDataList();
02192   ItemDataList iDl = internalIDList;
02193 
02194   createContextNameList(&ContextNameList,ctx0);
02195 
02196   kdDebug(13010)<<"Parsing Context structure"<<endl;
02197   
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           
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           
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           
02222           bool ft = false;
02223           int ftc = 0; 
02224           if ( i > 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           
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             
02249             while (HlManager::self()->syntax->nextItem(data))
02250               {
02251 
02252 
02253                 
02254 
02255                 QString tag = HlManager::self()->syntax->groupItemData(data,QString(""));
02256                 if ( tag == "IncludeRules" ) { 
02257       QString incCtx=HlManager::self()->syntax->groupItemData( data, QString("context"));
02258       
02259       if (incCtx.startsWith("##") || (!incCtx.startsWith("#"))) { 
02260         if (!incCtx.startsWith("#")) { 
02261           incCtx=buildPrefix+incCtx.simplifyWhiteSpace();
02262           includeRules.append(new IncludeRule(i,contextList[i]->items.count(),incCtx));
02263         }
02264         else { 
02265           kdDebug()<<"Cross highlight reference <IncludeRules>"<<endl;
02266           IncludeRule *ir=new IncludeRule(i,contextList[i]->items.count());
02267           
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                   
02281                   int ctxId = getIdFromString(&ContextNameList,
02282       HlManager::self()->syntax->groupItemData( data, QString("context")),dummy); 
02283                   if ( ctxId > -1) { 
02284                     kdDebug(13010)<<"makeContextList["<<i<<"]: including all items of context "<<ctxId<<endl;
02285                     if ( ctxId < (int) i ) { 
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; 
02293                 }
02294 #endif
02295     c=createHlItem(data,iDl,&RegionList,&ContextNameList);
02296     if (c)
02297       {
02298                                 contextList[i]->items.append(c);
02299 
02300                                 
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                                 
02311       }
02312 
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     
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   
02358   if ((array = m_attributeArrays[schema]))
02359     return array;
02360 
02361   
02362   if (!KateFactory::self()->schemaManager()->validSchema(schema))
02363   {
02364     
02365     return attributes (0);
02366   }
02367 
02368   
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 
02407 
02408 
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;