From e97a6da57804aa14907dec327fbae71bff9b383e Mon Sep 17 00:00:00 2001 From: jowenn Date: Sun, 10 Nov 2002 21:08:01 +0000 Subject: import of tiny kate. (saving not possible yet) --- (limited to 'noncore/apps/tinykate/libkate/document/katehighlight.cpp') 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 + (C) 2002 Joseph Wenninger + 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 + +#include +#include +#include +//#include +//#include +#include +//#include +#include +#include +#include + +#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()"<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 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;iname==name) return i; + } + kdDebug(13010)<<"Couldn't resolve itemDataName"<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"<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"<syntax->groupItemData(data,QString("casesensitive"))!="0") + casesensitive=true; else {casesensitive=false; kdDebug(13010)<<"Turning on case insensitiveness"<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:"<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; + 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"<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(); +} -- cgit v0.9.0.2