summaryrefslogtreecommitdiff
path: root/noncore/apps/tinykate/libkate/document/katehighlight.cpp
Side-by-side diff
Diffstat (limited to 'noncore/apps/tinykate/libkate/document/katehighlight.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/tinykate/libkate/document/katehighlight.cpp1459
1 files changed, 1459 insertions, 0 deletions
diff --git a/noncore/apps/tinykate/libkate/document/katehighlight.cpp b/noncore/apps/tinykate/libkate/document/katehighlight.cpp
new file mode 100644
index 0000000..797968b
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katehighlight.cpp
@@ -0,0 +1,1459 @@
+/*
+ Copyright (C) 1998, 1999 Jochen Wilhelmy
+ digisnap@cs.tu-berlin.de
+ (C) 2002, 2001 The Kate Team <kwrite-devel@kde.org>
+ (C) 2002 Joseph Wenninger <jowenn@kde.org>
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <string.h>
+
+#include <qtextstream.h>
+#include <qpe/config.h>
+#include <kglobal.h>
+//#include <kinstance.h>
+//#include <kmimemagic.h>
+#include <klocale.h>
+//#include <kregexp.h>
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <kstddirs.h>
+
+#include "katehighlight.h"
+
+
+#include "katetextline.h"
+#include "katedocument.h"
+#include "katesyntaxdocument.h"
+
+
+HlManager *HlManager::s_pSelf = 0;
+
+enum Item_styles { dsNormal,dsKeyword,dsDataType,dsDecVal,dsBaseN,dsFloat,dsChar,dsString,dsComment,dsOthers};
+
+static bool trueBool = true;
+static QString stdDeliminator = QString ("!%&()*+,-./:;<=>?[]^{|}~ \t\\");
+
+int getDefStyleNum(QString name)
+{
+ if (name=="dsNormal") return dsNormal;
+ if (name=="dsKeyword") return dsKeyword;
+ if (name=="dsDataType") return dsDataType;
+ if (name=="dsDecVal") return dsDecVal;
+ if (name=="dsBaseN") return dsBaseN;
+ if (name=="dsFloat") return dsFloat;
+ if (name=="dsChar") return dsChar;
+ if (name=="dsString") return dsString;
+ if (name=="dsComment") return dsComment;
+ if (name=="dsOthers") return dsOthers;
+
+ return dsNormal;
+}
+
+bool ustrchr(const QChar *s, uint len, QChar c)
+{
+ for (int z=0; z < len; z++)
+ {
+ if (*s == c) return true;
+ s++;
+ }
+
+ return false;
+}
+
+HlItem::HlItem(int attribute, int context)
+ : attr(attribute), ctx(context) {subItems=0;
+}
+
+HlItem::~HlItem()
+{
+ //kdDebug(13010)<<"In hlItem::~HlItem()"<<endl;
+ if (subItems!=0) {subItems->setAutoDelete(true); subItems->clear(); delete subItems;}
+}
+
+bool HlItem::startEnable(QChar c)
+{
+ return true;
+}
+
+HlCharDetect::HlCharDetect(int attribute, int context, QChar c)
+ : HlItem(attribute,context), sChar(c) {
+}
+
+const QChar *HlCharDetect::checkHgl(const QChar *str, int len, bool) {
+ if (*str == sChar) return str + 1;
+ return 0L;
+}
+
+Hl2CharDetect::Hl2CharDetect(int attribute, int context, QChar ch1, QChar ch2)
+ : HlItem(attribute,context) {
+ sChar1 = ch1;
+ sChar2 = ch2;
+}
+
+const QChar *Hl2CharDetect::checkHgl(const QChar *str, int len, bool) {
+ if (str[0] == sChar1 && str[1] == sChar2) return str + 2;
+ return 0L;
+}
+
+HlStringDetect::HlStringDetect(int attribute, int context, const QString &s, bool inSensitive)
+ : HlItem(attribute, context), str(inSensitive ? s.upper():s), _inSensitive(inSensitive) {
+}
+
+HlStringDetect::~HlStringDetect() {
+}
+
+const QChar *HlStringDetect::checkHgl(const QChar *s, int len, bool) {
+ if (!_inSensitive) {if (memcmp(s, str.unicode(), str.length()*sizeof(QChar)) == 0) return s + str.length();}
+ else
+ {
+ QString tmp=QString(s,str.length()).upper();
+ if (tmp==str) return s+str.length();
+ }
+ return 0L;
+}
+
+
+HlRangeDetect::HlRangeDetect(int attribute, int context, QChar ch1, QChar ch2)
+ : HlItem(attribute,context) {
+ sChar1 = ch1;
+ sChar2 = ch2;
+}
+
+const QChar *HlRangeDetect::checkHgl(const QChar *s, int len, bool) {
+ if (*s == sChar1)
+ {
+ do
+ {
+ s++;
+ len--;
+ if (len == 0) return 0L;
+ }
+ while (*s != sChar2);
+
+ return s + 1;
+ }
+ return 0L;
+}
+
+HlKeyword::HlKeyword (int attribute, int context,bool casesensitive, const QChar *deliminator, uint deliLen)
+ : HlItem(attribute,context), dict (113, casesensitive)
+{
+ deliminatorChars = deliminator;
+ deliminatorLen = deliLen;
+ _caseSensitive=casesensitive;
+}
+
+HlKeyword::~HlKeyword() {
+}
+
+bool HlKeyword::startEnable(QChar c)
+{
+ return ustrchr(deliminatorChars, deliminatorLen, c);
+}
+
+// If we use a dictionary for lookup we don't really need
+// an item as such we are using the key to lookup
+void HlKeyword::addWord(const QString &word)
+{
+ words.append(word);
+ dict.insert(word,&trueBool);
+}
+
+void HlKeyword::addList(const QStringList& list)
+{
+
+ words+=list;
+ for(uint i=0;i<list.count();i++) dict.insert(list[i], &trueBool);
+}
+
+const QChar *HlKeyword::checkHgl(const QChar *s, int len, bool b)
+{
+ if (len == 0) return 0L;
+
+ const QChar *s2 = s;
+
+ while ( (len > 0) && (!ustrchr(deliminatorChars, deliminatorLen, *s2)) )
+ {
+ s2++;
+ len--;
+ }
+
+ if (s2 == s) return 0L;
+
+ QString lookup = QString(s,s2-s);
+
+ if ( dict.find(lookup) ) return s2;
+ return 0L;
+}
+
+HlInt::HlInt(int attribute, int context)
+ : HlItem(attribute,context) {
+}
+
+const QChar *HlInt::checkHgl(const QChar *str, int len, bool) {
+ const QChar *s,*s1;
+
+ s = str;
+ while (s->isDigit()) s++;
+ if (s > str)
+ {
+ if (subItems)
+ {
+ for (HlItem *it=subItems->first();it;it=subItems->next())
+ {
+ s1=it->checkHgl(s, len, false);
+ if (s1) return s1;
+ }
+ }
+ return s;
+ }
+ return 0L;
+}
+
+HlFloat::HlFloat(int attribute, int context)
+ : HlItem(attribute,context) {
+}
+
+const QChar *HlFloat::checkHgl(const QChar *s, int len, bool) {
+ bool b, p;
+ const QChar *s1;
+
+ b = false;
+ while (s->isDigit()){
+ s++;
+ b = true;
+ }
+ if (p = (*s == '.')) {
+ s++;
+ while (s->isDigit()) {
+ s++;
+ b = true;
+ }
+ }
+ if (!b) return 0L;
+ if ((*s&0xdf) == 'E') s++;
+ else
+ if (!p) return 0L;
+ else
+ {
+ if (subItems)
+ {
+ for (HlItem *it=subItems->first();it;it=subItems->next())
+ {
+ s1=it->checkHgl(s, len, false);
+ if (s1) return s1;
+ }
+ }
+ return s;
+ }
+ if ((*s == '-')||(*s =='+')) s++;
+ b = false;
+ while (s->isDigit()) {
+ s++;
+ b = true;
+ }
+ if (b)
+ {
+ if (subItems)
+ {
+ for (HlItem *it=subItems->first();it;it=subItems->next())
+ {
+ s1=it->checkHgl(s, len, false);
+ if (s1) return s1;
+ }
+ }
+ return s;
+ }
+ else return 0L;
+}
+
+
+HlCInt::HlCInt(int attribute, int context)
+ : HlInt(attribute,context) {
+}
+
+const QChar *HlCInt::checkHgl(const QChar *s, int len, bool lineStart) {
+
+// if (*s == '0') s++; else s = HlInt::checkHgl(s);
+ s = HlInt::checkHgl(s, len, lineStart);
+ if (s != 0L) {
+ int l = 0;
+ int u = 0;
+ const QChar *str;
+
+ do {
+ str = s;
+ if ((*s&0xdf) == 'L' ) {
+ l++;
+ if (l > 2) return 0L;
+ s++;
+ }
+ if ((*s&0xdf) == 'U' ){
+ u++;
+ if (u > 1) return 0L;
+ s++;
+ }
+ } while (s != str);
+ }
+ return s;
+}
+
+HlCOct::HlCOct(int attribute, int context)
+ : HlItem(attribute,context) {
+}
+
+const QChar *HlCOct::checkHgl(const QChar *str, int len, bool) {
+ const QChar *s;
+
+ if (*str == '0') {
+ str++;
+ s = str;
+ while (*s >= '0' && *s <= '7') s++;
+ if (s > str) {
+ if ((*s&0xdf) == 'L' || (*s&0xdf) == 'U' ) s++;
+ return s;
+ }
+ }
+ return 0L;
+}
+
+HlCHex::HlCHex(int attribute, int context)
+ : HlItem(attribute,context) {
+}
+
+const QChar *HlCHex::checkHgl(const QChar *str, int len, bool) {
+ const QChar *s=str;
+#if 0
+ int i;
+ for (i=0;(*s)!='\0';s++,i++);
+ QString line(str,i);
+ QRegExp3 rx("0[xX][a-fA-F\\d]+[UuLl]?"); // this matches but is also matching parenthesis
+ int pos=rx.search(line,0);
+ if(pos > -1) return str+rx.matchedLength();
+ else
+ return 0L;
+
+#else
+ if (str[0] == '0' && ((str[1]&0xdf) == 'X' )) {
+ str += 2;
+ s = str;
+ while (s->isDigit() || ((*s&0xdf) >= 'A' && (*s&0xdf) <= 'F') /*|| (*s >= 'a' && *s <= 'f')*/) s++;
+ if (s > str) {
+ if ((*s&0xdf) == 'L' || (*s&0xdf) == 'U' ) s++;
+ return s;
+ }
+ }
+ return 0L;
+#endif
+}
+
+HlCFloat::HlCFloat(int attribute, int context)
+ : HlFloat(attribute,context) {
+}
+
+const QChar *HlCFloat::checkHgl(const QChar *s, int len, bool lineStart) {
+
+ s = HlFloat::checkHgl(s, len, lineStart);
+ if (s && ((*s&0xdf) == 'F' )) s++;
+ return s;
+}
+
+HlAnyChar::HlAnyChar(int attribute, int context, const QChar* charList, uint len)
+ : HlItem(attribute, context) {
+ _charList=charList;
+ _charListLen=len;
+}
+
+const QChar *HlAnyChar::checkHgl(const QChar *s, int len, bool)
+{
+ if (ustrchr(_charList, _charListLen, *s)) return s +1;
+ return 0L;
+}
+
+HlRegExpr::HlRegExpr(int attribute, int context,QString regexp)
+ : HlItem(attribute, context) {
+
+ handlesLinestart=regexp.startsWith("^");
+ if(!handlesLinestart) regexp.prepend("^");
+ Expr=new QRegExp3(regexp);
+}
+
+const QChar *HlRegExpr::checkHgl(const QChar *s, int len, bool lineStart)
+{
+ if ((!lineStart) && handlesLinestart) return 0;
+
+ QString line(s,len);
+ int pos = Expr->search( line, 0 );
+ if (pos==-1) return 0L;
+ else
+ return (s+Expr->matchedLength());
+};
+
+
+HlLineContinue::HlLineContinue(int attribute, int context)
+ : HlItem(attribute,context) {
+}
+
+const QChar *HlLineContinue::checkHgl(const QChar *s, int len, bool) {
+
+ if ((s[0].latin1() == '\\') && (len == 1))
+ {
+ return s + 1;
+ }
+ return 0L;
+}
+
+
+HlCStringChar::HlCStringChar(int attribute, int context)
+ : HlItem(attribute,context) {
+}
+
+//checks for hex and oct (for example \x1b or \033)
+const QChar *checkCharHexOct(const QChar *str) {
+ const QChar *s;
+ s=str;
+ int n;
+ if (*s == 'x') {
+ n = 0;
+ do {
+ s++;
+ n *= 16;
+ if (s->isDigit()) n += *s - '0';
+ else if ((*s&0xdf) >= 'A' && (*s&0xdf) <= 'F') n += (*s&0xdf) - 'A' + 10;
+// else if (*s >= 'a' && *s <= 'f') n += *s - 'a' + 10;
+ else break;
+ if (n >= 256) return 0L;
+ } while (true);
+ if (s - str == 1) return 0L;
+ } else {
+ if (!(*s >= '0' && *s <= '7')) return 0L;
+ n = *s - '0';
+ do {
+ s++;
+ n *= 8;
+ if (*s >= '0' && *s <= '7') n += *s - '0'; else break;
+ if (n >= 256) return s;
+ } while (s - str < 3);
+ }
+ return s;
+}
+// checks for C escaped chars \n and escaped hex/octal chars
+const QChar *checkEscapedChar(const QChar *s, int len) {
+ int i;
+ if (s[0] == '\\' && (len > 1) ) {
+ s++;
+ switch(*s){
+ case 'a': // checks for control chars
+ case 'b': // we want to fall through
+ case 'e':
+ case 'f':
+
+ case 'n':
+ case 'r':
+ case 't':
+ case 'v':
+ case '\'':
+ case '\"':
+ case '?' : // added ? ANSI C classifies this as an escaped char
+ case '\\': s++;
+ break;
+ case 'x': // if it's like \xff
+ s++; // eat the x
+ // these for loops can probably be
+ // replaced with something else but
+ // for right now they work
+ // check for hexdigits
+ for(i=0;i<2 &&(*s >= '0' && *s <= '9' || (*s&0xdf) >= 'A' && (*s&0xdf) <= 'F');i++,s++);
+ if(i==0) return 0L; // takes care of case '\x'
+ break;
+
+ case '0': case '1': case '2': case '3' :
+ case '4': case '5': case '6': case '7' :
+ for(i=0;i < 3 &&(*s >='0'&& *s<='7');i++,s++);
+ break;
+ default: return 0L;
+ }
+ return s;
+ }
+ return 0L;
+}
+
+const QChar *HlCStringChar::checkHgl(const QChar *str, int len, bool) {
+ return checkEscapedChar(str, len);
+}
+
+
+HlCChar::HlCChar(int attribute, int context)
+ : HlItem(attribute,context) {
+}
+
+const QChar *HlCChar::checkHgl(const QChar *str, int len, bool) {
+ const QChar *s;
+
+ if ((len > 1) && (str[0] == '\'') && (str[1] != '\''))
+ {
+ s = checkEscapedChar(&str[1], len); //try to match escaped char
+ if (!s) s = &str[2]; //match single non-escaped char
+ if (*s == '\'') return s + 1;
+ }
+ return 0L;
+}
+
+
+//--------
+ItemStyle::ItemStyle() : selCol(Qt::white), bold(false), italic(false) {
+}
+
+ItemStyle::ItemStyle(const QColor &col, const QColor &selCol,
+ bool bold, bool italic)
+ : col(col), selCol(selCol), bold(bold), italic(italic) {
+}
+
+ItemData::ItemData(const QString name, int defStyleNum)
+ : name(name), defStyleNum(defStyleNum), defStyle(true) {
+}
+
+ItemData::ItemData(const QString name, int defStyleNum,
+ const QColor &col, const QColor &selCol, bool bold, bool italic)
+ : ItemStyle(col,selCol,bold,italic), name(name), defStyleNum(defStyleNum),
+ defStyle(false) {
+}
+
+HlData::HlData(const QString &wildcards, const QString &mimetypes, const QString &identifier)
+ : wildcards(wildcards), mimetypes(mimetypes), identifier(identifier) {
+
+//JW itemDataList.setAutoDelete(true);
+}
+
+HlContext::HlContext(int attribute, int lineEndContext, int _lineBeginContext)
+ : attr(attribute), ctx(lineEndContext),lineBeginContext(_lineBeginContext) {
+ items.setAutoDelete(true);
+}
+
+Hl2CharDetect::Hl2CharDetect(int attribute, int context, const QChar *s)
+ : HlItem(attribute,context) {
+ sChar1 = s[0];
+ sChar2 = s[1];
+}
+
+Highlight::Highlight(syntaxModeListItem *def) : refCount(0)
+{
+ noHl = false;
+
+ if (def == 0)
+ {
+ noHl = true;
+ iName = I18N_NOOP("Normal");
+ iSection = "";
+ }
+ else
+ {
+ iName = def->name;
+ iSection = def->section;
+ iWildcards = def->extension;
+ iMimetypes = def->mimetype;
+ identifier = def->identifier;
+ }
+ deliminator = stdDeliminator;
+ deliminatorChars = deliminator.unicode();
+ deliminatorLen = deliminator.length();
+}
+
+Highlight::~Highlight()
+{
+}
+
+int Highlight::doHighlight(int ctxNum, TextLine *textLine)
+{
+ if (noHl)
+ {
+ textLine->setAttribs(0,0,textLine->length());
+ textLine->setAttr(0);
+ return 0;
+ }
+
+ HlContext *context;
+ const QChar *s2;
+ HlItem *item;
+
+ context = contextList[ctxNum];
+ if (context->lineBeginContext!=-1)
+ {
+ ctxNum=context->lineBeginContext;
+ context=contextList[ctxNum];
+ }
+
+ QChar lastChar = ' ';
+
+ // first char
+ const QChar *str = textLine->getText();
+
+ // non space char - index of that char
+ const QChar *s1 = textLine->firstNonSpace();
+ uint z = textLine->firstChar();
+
+ // length of textline
+ uint len = textLine->length();
+
+ bool found = false;
+ while (z < len)
+ {
+ found = false;
+
+ for (item = context->items.first(); item != 0L; item = context->items.next())
+ {
+ if (item->startEnable(lastChar))
+ {
+ s2 = item->checkHgl(s1, len-z, z==0);
+ if (s2 > s1)
+ {
+ qDebug("An item has been detected");
+ textLine->setAttribs(item->attr,s1 - str,s2 - str);
+ ctxNum = item->ctx;
+ context = contextList[ctxNum];
+ z = z + s2 - s1 - 1;
+ s1 = s2 - 1;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ // nothing found: set attribute of one char
+ if (!found)
+ textLine->setAttribs(context->attr,s1 - str,s1 - str + 1);
+
+ lastChar = *s1;
+ s1++;
+ z++;
+ }
+
+ //set "end of line"-properties
+ textLine->setAttr(context->attr);
+
+ //return new context
+ return context->ctx;
+}
+
+KConfig *Highlight::getKConfig() {
+ KConfig *config;
+ config=KGlobal::config();
+ config->setGroup(iName + QString(" Highlight"));
+ return config;
+}
+
+QString Highlight::getWildcards() {
+ KConfig *config;
+
+ config = getKConfig();
+
+ //if wildcards not yet in config, then use iWildCards as default
+ return config->readEntry("Wildcards", iWildcards);
+}
+
+
+QString Highlight::getMimetypes() {
+ KConfig *config;
+
+ config = getKConfig();
+
+ return config->readEntry("Mimetypes", iMimetypes);
+}
+
+
+HlData *Highlight::getData() {
+ KConfig *config;
+ HlData *hlData;
+
+ config = getKConfig();
+
+// iWildcards = config->readEntry("Wildcards");
+// iMimetypes = config->readEntry("Mimetypes");
+// hlData = new HlData(iWildcards,iMimetypes);
+ hlData = new HlData(
+ config->readEntry("Wildcards", iWildcards),
+ config->readEntry("Mimetypes", iMimetypes),
+ config->readEntry("Identifier", identifier));
+ getItemDataList(hlData->itemDataList, config);
+ return hlData;
+}
+
+void Highlight::setData(HlData *hlData) {
+ KConfig *config;
+
+ config = getKConfig();
+
+// iWildcards = hlData->wildcards;
+// iMimetypes = hlData->mimetypes;
+
+ config->writeEntry("Wildcards",hlData->wildcards);
+ config->writeEntry("Mimetypes",hlData->mimetypes);
+
+ setItemDataList(hlData->itemDataList,config);
+}
+
+void Highlight::getItemDataList(ItemDataList &list) {
+ KConfig *config;
+
+ config = getKConfig();
+ getItemDataList(list, config);
+}
+
+void Highlight::getItemDataList(ItemDataList &list, KConfig *config) {
+ ItemData *p;
+ QString s;
+ QRgb col, selCol;
+
+ list.clear();
+//JW list.setAutoDelete(true);
+ createItemData(list);
+
+ for (p = list.first(); p != 0L; p = list.next()) {
+ s = config->readEntry(p->name);
+ if (!s.isEmpty()) {
+ sscanf(s.latin1(),"%d,%X,%X,%d,%d", &p->defStyle,&col,&selCol,&p->bold,&p->italic);
+ p->col.setRgb(col);
+ p->selCol.setRgb(selCol);
+ }
+ }
+}
+
+/*******************************************************************************************
+ Highlight - setItemDataList
+ saves the ItemData / attribute / style definitions to the apps configfile.
+ Especially needed for user overridden values.
+
+ * input: ItemDataList &list :reference to the list, whose
+ * items should be saved
+ * KConfig *config :Pointer KDE configuration
+ * class, which should be used
+ * as storage
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+void Highlight::setItemDataList(ItemDataList &list, KConfig *config) {
+ ItemData *p;
+ QString s;
+
+ for (p = list.first(); p != 0L; p = list.next()) {
+ s.sprintf("%d,%X,%X,%d,%d",
+ p->defStyle,p->col.rgb(),p->selCol.rgb(),p->bold,p->italic);
+ config->writeEntry(p->name,s);
+ }
+}
+
+
+/*******************************************************************************************
+ Highlight - use
+ Increase the usage count and trigger initialization if needed
+
+ * input: none
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+void Highlight::use()
+{
+ if (refCount == 0) init();
+ refCount++;
+}
+
+
+/*******************************************************************************************
+ Highlight - release
+ Decrease the usage count and trigger a cleanup if needed
+
+ * input: none
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+void Highlight::release()
+{
+ refCount--;
+ if (refCount == 0) done();
+}
+
+/*******************************************************************************************
+ Highlight - init
+ If it's the first time a particular highlighting is used create the needed contextlist
+
+ * input: none
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+void Highlight::init()
+{
+ if (noHl)
+ return;
+
+ for (int z = 0; z < nContexts; z++) contextList[z] = 0L;
+ makeContextList();
+}
+
+
+/*******************************************************************************************
+ Highlight - done
+ If the there is no document using the highlighting style free the complete context
+ structure.
+
+ * input: none
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+void Highlight::done()
+{
+ if (noHl)
+ return;
+
+ for (int z = 0; z < nContexts; z++) delete contextList[z];
+}
+
+
+/*******************************************************************************************
+ Highlight - createItemData
+ This function reads the itemData entries from the config file, which specifies the
+ default attribute styles for matched items/contexts.
+
+ * input: none
+ *************
+ * output: ItemDataList &list :A reference to the internal
+ list containing the parsed
+ default config
+ *************
+ * return value: none
+*******************************************************************************************/
+
+void Highlight::createItemData(ItemDataList &list)
+{
+ qDebug("Highlight::createItemData");
+
+ // If no highlighting is selected we need only one default.
+ if (noHl)
+ {
+ list.append(new ItemData(I18N_NOOP("Normal Text"), dsNormal));
+ return;
+ }
+
+ QString color;
+ QString selColor;
+ QString bold;
+ QString italic;
+
+ // If the internal list isn't already available read the config file
+ if (internalIDList.count()==0)
+ {
+ //if all references to the list are destried the contents will also be deleted
+ internalIDList.setAutoDelete(true);
+ syntaxContextData *data;
+
+ qDebug("Trying to read itemData section");
+
+ //Tell the syntax document class which file we want to parse and which data group
+ HlManager::self()->syntax->setIdentifier(identifier);
+ data=HlManager::self()->syntax->getGroupInfo("highlighting","itemData");
+ //begin with the real parsing
+ while (HlManager::self()->syntax->nextGroup(data))
+ {
+ qDebug("Setting up one itemData element");
+ // read all attributes
+ color=HlManager::self()->syntax->groupData(data,QString("color"));
+ selColor=HlManager::self()->syntax->groupData(data,QString("selColor"));
+ bold=HlManager::self()->syntax->groupData(data,QString("bold"));
+ italic=HlManager::self()->syntax->groupData(data,QString("italic"));
+ //check if the user overrides something
+ if ( (!color.isEmpty()) && (!selColor.isEmpty()) && (!bold.isEmpty()) && (!italic.isEmpty()))
+ {
+ //create a user defined style
+ internalIDList.append(new ItemData(
+ HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(),
+ getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum"))),
+ QColor(color),QColor(selColor),(bold=="true") || (bold=="1"), (italic=="true") || (italic=="1")
+ ));
+ }
+ else
+ {
+ //assign a default style
+ internalIDList.append(new ItemData(
+ HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(),
+ getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum")))));
+
+ }
+ }
+ //clean up
+ if (data) HlManager::self()->syntax->freeGroupInfo(data);
+ }
+
+ //set the ouput reference
+ list=internalIDList;
+}
+
+
+/*******************************************************************************************
+ Highlight - lookupAttrName
+ This function is a helper for makeContextList and createHlItem. It looks the given
+ attribute name in the itemData list up and returns it's index
+
+ * input: QString &name :the attribute name to lookup
+ * ItemDataList &iDl :the list containing all
+ * available attributes
+ *************
+ * output: none
+ *************
+ * return value: int :The index of the attribute
+ * or 0
+*******************************************************************************************/
+
+int Highlight::lookupAttrName(const QString& name, ItemDataList &iDl)
+{
+ for (int i=0;i<iDl.count();i++)
+ {
+ if (iDl.at(i)->name==name) return i;
+ }
+ kdDebug(13010)<<"Couldn't resolve itemDataName"<<endl;
+ return 0;
+}
+
+
+/*******************************************************************************************
+ Highlight - createHlItem
+ This function is a helper for makeContextList. It parses the xml file for
+ information, how single or multi line comments are marked
+
+ * input: syntaxContextData *data : Data about the item read from
+ * the xml file
+ * ItemDataList &iDl : List of all available itemData
+ * entries. Needed for attribute
+ * name->index translation
+ *************
+ * output: none
+ *************
+ * return value: HlItem * : Pointer to the newly created item
+ * object
+*******************************************************************************************/
+
+HlItem *Highlight::createHlItem(syntaxContextData *data, ItemDataList &iDl)
+{
+ // No highlighting -> exit
+ if (noHl)
+ return 0;
+
+ // get the (tagname) itemd type
+ QString dataname=HlManager::self()->syntax->groupItemData(data,QString(""));
+
+ // BEGIN - Translation of the attribute parameter
+ QString tmpAttr=HlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace();
+ int attr;
+ if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
+ attr=tmpAttr.toInt();
+ else
+ attr=lookupAttrName(tmpAttr,iDl);
+ // END - Translation of the attribute parameter
+
+ // Info about context switch
+ int context=((HlManager::self()->syntax->groupItemData(data,QString("context"))).toInt());
+
+ // Get the char parameter (eg DetectChar)
+ char chr;
+ if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty())
+ chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0];
+ else
+ chr=0;
+
+ // Get the String parameter (eg. StringDetect)
+ QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String"));
+
+ // Get a second char parameter (char1) (eg Detect2Chars)
+ char chr1;
+ if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty())
+ chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0];
+ else
+ chr1=0;
+
+ // Will be removed eventuall. Atm used for StringDetect
+ bool insensitive=(HlManager::self()->syntax->groupItemData(data,QString("insensitive"))==QString("TRUE"));
+
+
+ //Create the item corresponding to it's type and set it's parameters
+ if (dataname=="keyword")
+ {
+ HlKeyword *keyword=new HlKeyword(attr,context,casesensitive,
+ deliminatorChars, deliminatorLen);
+
+ //Get the entries for the keyword lookup list
+ keyword->addList(HlManager::self()->syntax->finddata("highlighting",stringdata));
+ return keyword;
+ } else
+ if (dataname=="Float") return (new HlFloat(attr,context)); else
+ if (dataname=="Int") return(new HlInt(attr,context)); else
+ if (dataname=="DetectChar") return(new HlCharDetect(attr,context,chr)); else
+ if (dataname=="Detect2Chars") return(new Hl2CharDetect(attr,context,chr,chr1)); else
+ if (dataname=="RangeDetect") return(new HlRangeDetect(attr,context, chr, chr1)); else
+ if (dataname=="LineContinue") return(new HlLineContinue(attr,context)); else
+ if (dataname=="StringDetect") return(new HlStringDetect(attr,context,stringdata,insensitive)); else
+ if (dataname=="AnyChar") return(new HlAnyChar(attr,context,stringdata.unicode(), stringdata.length())); else
+ if (dataname=="RegExpr") return(new HlRegExpr(attr,context,stringdata)); else
+ if(dataname=="HlCChar") return ( new HlCChar(attr,context));else
+ if(dataname=="HlCHex") return (new HlCHex(attr,context));else
+ if(dataname=="HlCOct") return (new HlCOct(attr,context)); else
+ if(dataname=="HlCStringChar") return (new HlCStringChar(attr,context)); else
+
+ {
+ // oops, unknown type. Perhaps a spelling error in the xml file
+ return 0;
+ }
+
+
+}
+
+
+/*******************************************************************************************
+ Highlight - isInWord
+
+ * input: Qchar c Character to investigate
+ *************
+ * output: none
+ *************
+ * return value: returns true, if c is no deliminator
+*******************************************************************************************/
+
+bool Highlight::isInWord(QChar c)
+{
+ return !ustrchr(deliminatorChars, deliminatorLen, c);
+}
+
+
+
+/*******************************************************************************************
+ Highlight - readCommentConfig
+ This function is a helper for makeContextList. It parses the xml file for
+ information, how single or multi line comments are marked
+
+ * input: none
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+void Highlight::readCommentConfig()
+{
+
+ cslStart = "";
+ HlManager::self()->syntax->setIdentifier(identifier);
+
+ syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("general","comment");
+ if (data)
+ {
+// kdDebug(13010)<<"COMMENT DATA FOUND"<<endl;
+ while (HlManager::self()->syntax->nextGroup(data))
+ {
+
+ if (HlManager::self()->syntax->groupData(data,"name")=="singleLine")
+ cslStart=HlManager::self()->syntax->groupData(data,"start");
+ if (HlManager::self()->syntax->groupData(data,"name")=="multiLine")
+ {
+ cmlStart=HlManager::self()->syntax->groupData(data,"start");
+ cmlEnd=HlManager::self()->syntax->groupData(data,"end");
+ }
+ }
+ HlManager::self()->syntax->freeGroupInfo(data);
+ }
+
+}
+
+/*******************************************************************************************
+ Highlight - readGlobalKeyWordConfig
+ This function is a helper for makeContextList. It parses the xml file for
+ information, if keywords should be treated case(in)sensitive and creates the keyword
+ delimiter list. Which is the default list, without any given weak deliminiators
+
+ * input: none
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+
+void Highlight::readGlobalKeywordConfig()
+{
+ // Tell the syntax document class which file we want to parse
+ HlManager::self()->syntax->setIdentifier(identifier);
+
+ // Get the keywords config entry
+ syntaxContextData * data=HlManager::self()->syntax->getConfig("general","keywords");
+ if (data)
+ {
+ kdDebug(13010)<<"Found global keyword config"<<endl;
+
+ if (HlManager::self()->syntax->groupItemData(data,QString("casesensitive"))!="0")
+ casesensitive=true; else {casesensitive=false; kdDebug(13010)<<"Turning on case insensitiveness"<<endl;}
+ //get the weak deliminators
+ weakDeliminator=(!HlManager::self()->syntax->groupItemData(data,QString("weakDeliminator")));
+
+ // remove any weakDelimitars (if any) from the default list and store this list.
+ int f;
+ for (int s=0; s < weakDeliminator.length(); s++)
+ {
+ f = 0;
+ f = deliminator.find (weakDeliminator[s]);
+
+ if (f > -1)
+ deliminator.remove (f, 1);
+ }
+
+ deliminatorChars = deliminator.unicode();
+ deliminatorLen = deliminator.length();
+
+ HlManager::self()->syntax->freeGroupInfo(data);
+ }
+ else
+ {
+ //Default values
+ casesensitive=true;
+ weakDeliminator=QString("");
+ }
+
+}
+
+/*******************************************************************************************
+ Highlight - makeContextList
+ That's the most important initialization function for each highlighting. It's called
+ each time a document gets a highlighting style assigned. parses the xml file and
+ creates a corresponding internal structure
+
+ * input: none
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+
+void Highlight::makeContextList()
+{
+ if (noHl)
+ return;
+
+ HlKeyword *keyword=0, *dataType=0;
+ syntaxContextData *data, *datasub;
+ HlItem *c;
+
+ readCommentConfig();
+ readGlobalKeywordConfig();
+
+ // Let the syntax document class know, which file we'd like to parse
+ HlManager::self()->syntax->setIdentifier(identifier);
+
+ // This list is needed for the translation of the attribute parameter, if the itemData name is given instead of the index
+ ItemDataList iDl;
+ createItemData(iDl);
+
+ //start the real work
+ data=HlManager::self()->syntax->getGroupInfo("highlighting","context");
+ int i=0;
+ if (data)
+ {
+ while (HlManager::self()->syntax->nextGroup(data))
+ {
+
+ // BEGIN - Translation of the attribute parameter
+ QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace();
+ int attr;
+ if (QString("%1").arg(tmpAttr.toInt())==tmpAttr)
+ attr=tmpAttr.toInt();
+ else
+ attr=lookupAttrName(tmpAttr,iDl);
+ // END - Translation of the attribute parameter
+
+ contextList[i]=new HlContext(
+ attr,
+ (HlManager::self()->syntax->groupData(data,QString("lineEndContext"))).toInt(),
+ (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1:
+ (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt());
+
+
+ //Let's create all items for the context
+ while (HlManager::self()->syntax->nextItem(data))
+ {
+// kdDebug(13010)<< "In make Contextlist: Item:"<<endl;
+ c=createHlItem(data,iDl);
+ if (c)
+ {
+ contextList[i]->items.append(c);
+
+ // Not supported completely atm and only one level. Subitems.(all have to be matched to at once)
+ datasub=HlManager::self()->syntax->getSubItems(data);
+ bool tmpbool;
+ if (tmpbool=HlManager::self()->syntax->nextItem(datasub))
+ {
+ c->subItems=new QList<HlItem>;
+ for (;tmpbool;tmpbool=HlManager::self()->syntax->nextItem(datasub))
+ c->subItems->append(createHlItem(datasub,iDl));
+ }
+ HlManager::self()->syntax->freeGroupInfo(datasub);
+ // end of sublevel
+ }
+// kdDebug(13010)<<"Last line in loop"<<endl;
+ }
+ i++;
+ }
+ }
+
+ HlManager::self()->syntax->freeGroupInfo(data);
+
+
+}
+
+HlManager::HlManager() : QObject(0L)
+{
+ syntax = new SyntaxDocument();
+ SyntaxModeList modeList = syntax->modeList();
+
+ hlList.setAutoDelete(true);
+ hlList.append(new Highlight(0));
+
+ uint i=0;
+ while (i < modeList.count())
+ {
+ hlList.append(new Highlight(modeList.at(i)));
+ i++;
+ }
+}
+
+HlManager::~HlManager() {
+ if(syntax) delete syntax;
+}
+
+HlManager *HlManager::self()
+{
+ if ( !s_pSelf )
+ s_pSelf = new HlManager;
+ return s_pSelf;
+}
+
+Highlight *HlManager::getHl(int n) {
+ if (n < 0 || n >= (int) hlList.count()) n = 0;
+ return hlList.at(n);
+}
+
+int HlManager::defaultHl() {
+ KConfig *config;
+ config = KGlobal::config();
+ config->setGroup("General Options");
+
+#warning fixme return nameFind(config->readEntry("Highlight"));
+
+}
+
+
+int HlManager::nameFind(const QString &name) {
+ int z;
+
+ for (z = hlList.count() - 1; z > 0; z--) {
+ if (hlList.at(z)->iName == name) break;
+ }
+ return z;
+}
+
+int HlManager::wildcardFind(const QString &fileName) {
+ Highlight *highlight;
+ int p1, p2;
+ QString w;
+ for (highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) {
+ p1 = 0;
+ w = highlight->getWildcards();
+ while (p1 < (int) w.length()) {
+ p2 = w.find(';',p1);
+ if (p2 == -1) p2 = w.length();
+ if (p1 < p2) {
+ QRegExp regExp(w.mid(p1,p2 - p1),true,true);
+ if (regExp.match(fileName) == 0) return hlList.at();
+ }
+ p1 = p2 + 1;
+ }
+ }
+ return -1;
+}
+
+
+int HlManager::makeAttribs(Highlight *highlight, Attribute *a, int maxAttribs) {
+ ItemStyleList defaultStyleList;
+ ItemStyle *defaultStyle;
+ ItemDataList itemDataList;
+ ItemData *itemData;
+ int nAttribs, z;
+
+ qDebug("HlManager::makeAttribs");
+
+ defaultStyleList.setAutoDelete(true);
+ getDefaults(defaultStyleList);
+
+// itemDataList.setAutoDelete(true);
+ highlight->getItemDataList(itemDataList);
+ nAttribs = itemDataList.count();
+ for (z = 0; z < nAttribs; z++) {
+ qDebug("HlManager::makeAttribs: createing one attribute definition");
+ itemData = itemDataList.at(z);
+ if (itemData->defStyle) {
+ // default style
+ defaultStyle = defaultStyleList.at(itemData->defStyleNum);
+ a[z].col = defaultStyle->col;
+ a[z].selCol = defaultStyle->selCol;
+ a[z].bold = defaultStyle->bold;
+ a[z].italic = defaultStyle->italic;
+ } else {
+ // custom style
+ a[z].col = itemData->col;
+ a[z].selCol = itemData->selCol;
+ a[z].bold = itemData->bold;
+ a[z].italic = itemData->italic;
+ }
+ }
+
+ for (; z < maxAttribs; z++) {
+ a[z].col = black;
+ a[z].selCol = black;
+ a[z].bold = defaultStyle->bold;
+ a[z].italic = defaultStyle->italic;
+ }
+ return nAttribs;
+}
+
+int HlManager::defaultStyles() {
+ return 10;
+}
+
+QString HlManager::defaultStyleName(int n)
+{
+ static QStringList names;
+
+ if (names.isEmpty())
+ {
+ names << i18n("Normal");
+ names << i18n("Keyword");
+ names << i18n("Data Type");
+ names << i18n("Decimal/Value");
+ names << i18n("Base-N Integer");
+ names << i18n("Floating Point");
+ names << i18n("Character");
+ names << i18n("String");
+ names << i18n("Comment");
+ names << i18n("Others");
+ }
+
+ return names[n];
+}
+
+void HlManager::getDefaults(ItemStyleList &list) {
+ KConfig *config;
+ int z;
+ ItemStyle *i;
+ QString s;
+ QRgb col, selCol;
+
+ list.setAutoDelete(true);
+ //ItemStyle(color, selected color, bold, italic)
+ list.append(new ItemStyle(black,white,false,false)); //normal
+ list.append(new ItemStyle(black,white,true,false)); //keyword
+ list.append(new ItemStyle(darkRed,white,false,false)); //datatype
+ list.append(new ItemStyle(blue,cyan,false,false)); //decimal/value
+ list.append(new ItemStyle(darkCyan,cyan,false,false)); //base n
+ list.append(new ItemStyle(darkMagenta,cyan,false,false));//float
+ list.append(new ItemStyle(magenta,magenta,false,false)); //char
+ list.append(new ItemStyle(red,red,false,false)); //string
+ list.append(new ItemStyle(darkGray,gray,false,true)); //comment
+ list.append(new ItemStyle(darkGreen,green,false,false)); //others
+
+#warning fixme
+/*
+ config = KateFactory::instance()->config();
+ config->setGroup("Default Item Styles");
+ for (z = 0; z < defaultStyles(); z++) {
+ i = list.at(z);
+ s = config->readEntry(defaultStyleName(z));
+ if (!s.isEmpty()) {
+ sscanf(s.latin1(),"%X,%X,%d,%d",&col,&selCol,&i->bold,&i->italic);
+ i->col.setRgb(col);
+ i->selCol.setRgb(selCol);
+ }
+ }
+*/
+}
+
+void HlManager::setDefaults(ItemStyleList &list) {
+ KConfig *config;
+ int z;
+ ItemStyle *i;
+ char s[64];
+#warning fixme
+/*
+ config = KateFactory::instance()->config();
+ config->setGroup("Default Item Styles");
+ for (z = 0; z < defaultStyles(); z++) {
+ i = list.at(z);
+ sprintf(s,"%X,%X,%d,%d",i->col.rgb(),i->selCol.rgb(),i->bold, i->italic);
+ config->writeEntry(defaultStyleName(z),s);
+ }
+*/
+ emit changed();
+}
+
+
+int HlManager::highlights() {
+ return (int) hlList.count();
+}
+
+QString HlManager::hlName(int n) {
+ return hlList.at(n)->iName;
+}
+
+QString HlManager::hlSection(int n) {
+ return hlList.at(n)->iSection;
+}
+
+void HlManager::getHlDataList(HlDataList &list) {
+ int z;
+
+ for (z = 0; z < (int) hlList.count(); z++) {
+ list.append(hlList.at(z)->getData());
+ }
+}
+
+void HlManager::setHlDataList(HlDataList &list) {
+ int z;
+
+ for (z = 0; z < (int) hlList.count(); z++) {
+ hlList.at(z)->setData(list.at(z));
+ }
+ //notify documents about changes in highlight configuration
+ emit changed();
+}