mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-23 18:32:50 +00:00
890 lines
20 KiB
C++
890 lines
20 KiB
C++
/* This file is part of the KDE libraries
|
|
Copyright (C) 2003, 2004 Anders Lund <anders@alweb.dk>
|
|
Copyright (C) 2003 Hamish Rodda <rodda@kde.org>
|
|
Copyright (C) 2001,2002 Joseph Wenninger <jowenn@kde.org>
|
|
Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
|
|
Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
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., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
//BEGIN INCLUDES
|
|
#include "katehighlighthelpers.h"
|
|
|
|
#include "katetextline.h"
|
|
#include "katedocument.h"
|
|
#include "katesyntaxdocument.h"
|
|
#include "katerenderer.h"
|
|
#include "kateglobal.h"
|
|
#include "kateschema.h"
|
|
#include "kateconfig.h"
|
|
#include "kateextendedattribute.h"
|
|
|
|
#include <QtCore/QSet>
|
|
//END
|
|
|
|
//BEGIN KateHlItem
|
|
KateHlItem::KateHlItem(int attribute, KateHlContextModification context,signed char regionId,signed char regionId2)
|
|
: attr(attribute),
|
|
ctx(context),
|
|
region(regionId),
|
|
region2(regionId2),
|
|
lookAhead(false),
|
|
dynamic(false),
|
|
dynamicChild(false),
|
|
firstNonSpace(false),
|
|
onlyConsume(false),
|
|
column (-1),
|
|
alwaysStartEnable (true),
|
|
customStartEnable (false),
|
|
haveCache(false),
|
|
cachingHandled(false)
|
|
{
|
|
}
|
|
|
|
KateHlItem::~KateHlItem()
|
|
{
|
|
}
|
|
|
|
void KateHlItem::dynamicSubstitute(QString &str, const QStringList *args)
|
|
{
|
|
for (int i = 0; i < str.length() - 1; ++i)
|
|
{
|
|
if (str[i] == '%')
|
|
{
|
|
char c = str[i + 1].toLatin1();
|
|
if (c == '%')
|
|
str.remove(i, 1);
|
|
else if (c >= '0' && c <= '9')
|
|
{
|
|
if ((int)(c - '0') < args->size())
|
|
{
|
|
str.replace(i, 2, (*args)[c - '0']);
|
|
i += ((*args)[c - '0']).length() - 1;
|
|
}
|
|
else
|
|
{
|
|
str.remove(i, 2);
|
|
--i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlCharDetect
|
|
KateHlCharDetect::KateHlCharDetect(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2, QChar c)
|
|
: KateHlItem(attribute,context,regionId,regionId2)
|
|
, sChar(c)
|
|
{
|
|
}
|
|
|
|
int KateHlCharDetect::checkHgl(const QString& text, int offset, int /*len*/)
|
|
{
|
|
if (text[offset] == sChar)
|
|
return offset + 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
KateHlItem *KateHlCharDetect::clone(const QStringList *args)
|
|
{
|
|
char c = sChar.toLatin1();
|
|
|
|
if (c < '0' || c > '9' || (c - '0') >= args->size())
|
|
return this;
|
|
|
|
KateHlCharDetect *ret = new KateHlCharDetect(attr, ctx, region, region2, (*args)[c - '0'][0]);
|
|
ret->dynamicChild = true;
|
|
return ret;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHl2CharDetect
|
|
KateHl2CharDetect::KateHl2CharDetect(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2)
|
|
: KateHlItem(attribute,context,regionId,regionId2)
|
|
, sChar1 (ch1)
|
|
, sChar2 (ch2)
|
|
{
|
|
}
|
|
|
|
int KateHl2CharDetect::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
if ((len >= 2) && text[offset++] == sChar1 && text[offset++] == sChar2)
|
|
return offset;
|
|
|
|
return 0;
|
|
}
|
|
|
|
KateHlItem *KateHl2CharDetect::clone(const QStringList *args)
|
|
{
|
|
char c1 = sChar1.toLatin1();
|
|
char c2 = sChar2.toLatin1();
|
|
|
|
if (c1 < '0' || c1 > '9' || (c1 - '0') >= args->size())
|
|
return this;
|
|
|
|
if (c2 < '0' || c2 > '9' || (c2 - '0') >= args->size())
|
|
return this;
|
|
|
|
KateHl2CharDetect *ret = new KateHl2CharDetect(attr, ctx, region, region2, (*args)[c1 - '0'][0], (*args)[c2 - '0'][0]);
|
|
ret->dynamicChild = true;
|
|
return ret;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlStringDetect
|
|
KateHlStringDetect::KateHlStringDetect(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2,const QString &s, bool inSensitive)
|
|
: KateHlItem(attribute, context,regionId,regionId2)
|
|
, str(inSensitive ? s.toUpper() : s)
|
|
, strLen (str.length())
|
|
, _inSensitive(inSensitive)
|
|
{
|
|
}
|
|
|
|
int KateHlStringDetect::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
if (len < strLen)
|
|
return 0;
|
|
|
|
if (_inSensitive)
|
|
{
|
|
for (int i=0; i < strLen; i++)
|
|
if (text[offset++].toUpper() != str[i])
|
|
return 0;
|
|
|
|
return offset;
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i < strLen; i++)
|
|
if (text[offset++] != str[i])
|
|
return 0;
|
|
|
|
return offset;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
KateHlItem *KateHlStringDetect::clone(const QStringList *args)
|
|
{
|
|
QString newstr = str;
|
|
|
|
dynamicSubstitute(newstr, args);
|
|
|
|
if (newstr == str)
|
|
return this;
|
|
|
|
KateHlStringDetect *ret = new KateHlStringDetect(attr, ctx, region, region2, newstr, _inSensitive);
|
|
ret->dynamicChild = true;
|
|
return ret;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlWordDetect
|
|
|
|
KateHlWordDetect::KateHlWordDetect(int attribute, KateHlContextModification context, signed char regionId, signed char regionId2, const QString& s, bool inSensitive)
|
|
: KateHlStringDetect(attribute, context, regionId, regionId2, s, inSensitive)
|
|
{
|
|
}
|
|
|
|
inline bool isWordCharacter(const QChar& c)
|
|
{
|
|
// The Qt docs say for word characters:
|
|
// \w - Matches a word character (QChar::isLetterOrNumber(), QChar::isMark(), or '_').
|
|
// see also: http://doc.trolltech.com/qregexp.html
|
|
return c.isLetterOrNumber() || c.isMark() || c.unicode() == '_';
|
|
}
|
|
|
|
int KateHlWordDetect::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
//NOTE: word boundary means: any non-word character.
|
|
|
|
// make sure there is no letter or number before the word starts
|
|
if (offset > 0 && isWordCharacter(text.at(offset - 1))) {
|
|
return 0;
|
|
}
|
|
offset = KateHlStringDetect::checkHgl(text, offset, len);
|
|
// make sure there is no letter or number after the word ends
|
|
if (offset && offset < text.length() && isWordCharacter(text.at(offset))) {
|
|
return 0;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
KateHlItem* KateHlWordDetect::clone(const QStringList* args)
|
|
{
|
|
QString newstr = str;
|
|
|
|
dynamicSubstitute(newstr, args);
|
|
|
|
if (newstr == str)
|
|
return this;
|
|
|
|
KateHlWordDetect *ret = new KateHlWordDetect(attr, ctx, region, region2, newstr, _inSensitive);
|
|
ret->dynamicChild = true;
|
|
return ret;
|
|
}
|
|
|
|
|
|
//END KateHlWordDetect
|
|
|
|
//BEGIN KateHlRangeDetect
|
|
KateHlRangeDetect::KateHlRangeDetect(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2, QChar ch1, QChar ch2)
|
|
: KateHlItem(attribute,context,regionId,regionId2)
|
|
, sChar1 (ch1)
|
|
, sChar2 (ch2)
|
|
{
|
|
}
|
|
|
|
int KateHlRangeDetect::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
if (text[offset] == sChar1)
|
|
{
|
|
do
|
|
{
|
|
offset++;
|
|
len--;
|
|
if (len < 1) return 0;
|
|
}
|
|
while (text[offset] != sChar2);
|
|
|
|
return offset + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlKeyword
|
|
KateHlKeyword::KateHlKeyword (int attribute, KateHlContextModification context, signed char regionId,signed char regionId2, bool insensitive, const QString& delims)
|
|
: KateHlItem(attribute,context,regionId,regionId2)
|
|
, _insensitive(insensitive)
|
|
, minLen (0xFFFFFF)
|
|
, maxLen (0)
|
|
{
|
|
alwaysStartEnable = false;
|
|
customStartEnable = true;
|
|
foreach (const QChar &c, delims)
|
|
deliminators << c;
|
|
}
|
|
|
|
KateHlKeyword::~KateHlKeyword ()
|
|
{
|
|
qDeleteAll(dict);
|
|
}
|
|
|
|
QSet<QString> KateHlKeyword::allKeywords() const
|
|
{
|
|
QSet<QString> result;
|
|
foreach ( const QSet<QString>* v, dict ) {
|
|
if ( ! v ) {
|
|
continue;
|
|
}
|
|
result.unite(*v);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void KateHlKeyword::addList(const QStringList& list)
|
|
{
|
|
for(int i=0; i < list.count(); ++i)
|
|
{
|
|
int len = list[i].length();
|
|
|
|
if (minLen > len)
|
|
minLen = len;
|
|
|
|
if (maxLen < len)
|
|
maxLen = len;
|
|
|
|
if (len >= dict.size())
|
|
{
|
|
uint oldSize = dict.size();
|
|
dict.resize (len+1);
|
|
|
|
for (int m=oldSize; m < dict.size(); ++m)
|
|
dict[m] = 0;
|
|
}
|
|
|
|
if (!dict[len])
|
|
dict[len] = new QSet<QString> ();
|
|
|
|
if (!_insensitive)
|
|
dict[len]->insert(list[i]);
|
|
else
|
|
dict[len]->insert(list[i].toLower());
|
|
}
|
|
}
|
|
|
|
int KateHlKeyword::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
int offset2 = offset;
|
|
int wordLen = 0;
|
|
|
|
while ((len > wordLen) && !deliminators.contains(text[offset2]))
|
|
{
|
|
offset2++;
|
|
wordLen++;
|
|
|
|
if (wordLen > maxLen) return 0;
|
|
}
|
|
|
|
if (wordLen < minLen || !dict[wordLen]) return 0;
|
|
|
|
if (!_insensitive)
|
|
{
|
|
if (dict[wordLen]->contains(QString::fromRawData(text.unicode() + offset, wordLen)) )
|
|
return offset2;
|
|
}
|
|
else
|
|
{
|
|
if (dict[wordLen]->contains(QString::fromRawData(text.unicode() + offset, wordLen).toLower()) )
|
|
return offset2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlInt
|
|
KateHlInt::KateHlInt(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2)
|
|
: KateHlItem(attribute,context,regionId,regionId2)
|
|
{
|
|
alwaysStartEnable = false;
|
|
}
|
|
|
|
int KateHlInt::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
int offset2 = offset;
|
|
|
|
while ((len > 0) && text[offset2].isDigit())
|
|
{
|
|
offset2++;
|
|
len--;
|
|
}
|
|
|
|
if (offset2 > offset)
|
|
{
|
|
if (len > 0)
|
|
{
|
|
for (int i=0; i < subItems.size(); i++)
|
|
{
|
|
if ( (offset = subItems[i]->checkHgl(text, offset2, len)) )
|
|
return offset;
|
|
}
|
|
}
|
|
|
|
return offset2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlFloat
|
|
KateHlFloat::KateHlFloat(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2)
|
|
: KateHlItem(attribute,context, regionId,regionId2)
|
|
{
|
|
alwaysStartEnable = false;
|
|
}
|
|
|
|
int KateHlFloat::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
bool b = false;
|
|
bool p = false;
|
|
|
|
while ((len > 0) && text[offset].isDigit())
|
|
{
|
|
offset++;
|
|
len--;
|
|
b = true;
|
|
}
|
|
|
|
if ((len > 0) && (p = (text[offset] == '.')))
|
|
{
|
|
offset++;
|
|
len--;
|
|
|
|
while ((len > 0) && text[offset].isDigit())
|
|
{
|
|
offset++;
|
|
len--;
|
|
b = true;
|
|
}
|
|
}
|
|
|
|
if (!b)
|
|
return 0;
|
|
|
|
if ((len > 0) && ((text[offset].toAscii() & 0xdf) == 'E'))
|
|
{
|
|
offset++;
|
|
len--;
|
|
}
|
|
else
|
|
{
|
|
if (!p)
|
|
return 0;
|
|
else
|
|
{
|
|
if (len > 0)
|
|
{
|
|
for (int i=0; i < subItems.size(); ++i)
|
|
{
|
|
int offset2 = subItems[i]->checkHgl(text, offset, len);
|
|
|
|
if (offset2)
|
|
return offset2;
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
}
|
|
|
|
if ((len > 0) && (text[offset] == '-' || text[offset] =='+'))
|
|
{
|
|
offset++;
|
|
len--;
|
|
}
|
|
|
|
b = false;
|
|
|
|
while ((len > 0) && text[offset].isDigit())
|
|
{
|
|
offset++;
|
|
len--;
|
|
b = true;
|
|
}
|
|
|
|
if (b)
|
|
{
|
|
if (len > 0)
|
|
{
|
|
for (int i=0; i < subItems.size(); ++i)
|
|
{
|
|
int offset2 = subItems[i]->checkHgl(text, offset, len);
|
|
|
|
if (offset2)
|
|
return offset2;
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlCOct
|
|
KateHlCOct::KateHlCOct(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2)
|
|
: KateHlItem(attribute,context,regionId,regionId2)
|
|
{
|
|
alwaysStartEnable = false;
|
|
}
|
|
|
|
int KateHlCOct::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
if (text[offset].toAscii() == '0')
|
|
{
|
|
offset++;
|
|
len--;
|
|
|
|
int offset2 = offset;
|
|
|
|
while ((len > 0) && (text[offset2].toAscii() >= '0' && text[offset2].toAscii() <= '7'))
|
|
{
|
|
offset2++;
|
|
len--;
|
|
}
|
|
|
|
if (offset2 > offset)
|
|
{
|
|
if ((len > 0) && ((text[offset2].toAscii() & 0xdf) == 'L' || (text[offset].toAscii() & 0xdf) == 'U' ))
|
|
offset2++;
|
|
|
|
return offset2;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlCHex
|
|
KateHlCHex::KateHlCHex(int attribute, KateHlContextModification context,signed char regionId,signed char regionId2)
|
|
: KateHlItem(attribute,context,regionId,regionId2)
|
|
{
|
|
alwaysStartEnable = false;
|
|
}
|
|
|
|
int KateHlCHex::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
if ((len > 1) && (text[offset++].toAscii() == '0') && ((text[offset++].toAscii() & 0xdf) == 'X' ))
|
|
{
|
|
len -= 2;
|
|
|
|
int offset2 = offset;
|
|
|
|
while ((len > 0) && (text[offset2].isDigit() || ((text[offset2].toAscii() & 0xdf) >= 'A' && (text[offset2].toAscii() & 0xdf) <= 'F')))
|
|
{
|
|
offset2++;
|
|
len--;
|
|
}
|
|
|
|
if (offset2 > offset)
|
|
{
|
|
if ((len > 0) && ((text[offset2].toAscii() & 0xdf) == 'L' || (text[offset2].toAscii() & 0xdf) == 'U' ))
|
|
offset2++;
|
|
|
|
return offset2;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlCFloat
|
|
KateHlCFloat::KateHlCFloat(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2)
|
|
: KateHlFloat(attribute,context,regionId,regionId2)
|
|
{
|
|
alwaysStartEnable = false;
|
|
}
|
|
|
|
int KateHlCFloat::checkIntHgl(const QString& text, int offset, int len)
|
|
{
|
|
int offset2 = offset;
|
|
|
|
while ((len > 0) && text[offset].isDigit()) {
|
|
offset2++;
|
|
len--;
|
|
}
|
|
|
|
if (offset2 > offset)
|
|
return offset2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int KateHlCFloat::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
int offset2 = KateHlFloat::checkHgl(text, offset, len);
|
|
|
|
if (offset2)
|
|
{
|
|
if ((text[offset2].toAscii() & 0xdf) == 'F' )
|
|
offset2++;
|
|
|
|
return offset2;
|
|
}
|
|
else
|
|
{
|
|
offset2 = checkIntHgl(text, offset, len);
|
|
|
|
if (offset2 && ((text[offset2].toAscii() & 0xdf) == 'F' ))
|
|
return ++offset2;
|
|
else
|
|
return 0;
|
|
}
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlAnyChar
|
|
KateHlAnyChar::KateHlAnyChar(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2, const QString& charList)
|
|
: KateHlItem(attribute, context,regionId,regionId2)
|
|
, _charList(charList)
|
|
{
|
|
}
|
|
|
|
int KateHlAnyChar::checkHgl(const QString& text, int offset, int)
|
|
{
|
|
if (_charList.contains(text[offset]))
|
|
return ++offset;
|
|
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlRegExpr
|
|
KateHlRegExpr::KateHlRegExpr( int attribute, KateHlContextModification context, signed char regionId,signed char regionId2, const QString ®exp, bool insensitive, bool minimal)
|
|
: KateHlItem(attribute, context, regionId,regionId2)
|
|
, handlesLinestart (regexp.startsWith('^'))
|
|
, _regexp(regexp)
|
|
, _insensitive(insensitive)
|
|
, _minimal(minimal)
|
|
, _lastOffset(-2) // -2 is start value, -1 is "not found at all"
|
|
, Expr (regexp, _insensitive ? Qt::CaseInsensitive : Qt::CaseSensitive)
|
|
{
|
|
// minimal or not ;)
|
|
Expr.setMinimal(_minimal);
|
|
}
|
|
|
|
int KateHlRegExpr::checkHgl(const QString& text, int offset, int /*len*/)
|
|
{
|
|
if (offset && handlesLinestart)
|
|
return 0;
|
|
|
|
// optimization: if we check something on the same text as the last time,
|
|
// try to reuse what we got that time
|
|
if ( haveCache ) {
|
|
if ( offset < _lastOffset || _lastOffset == -1 ) {
|
|
// reuse last match: not found or offset before match
|
|
return 0;
|
|
} else if ( offset == _lastOffset ) {
|
|
// reuse last match: found at this position
|
|
return (_lastOffset + _lastOffsetLength);
|
|
}
|
|
}
|
|
|
|
haveCache = true;
|
|
_lastOffset = Expr.indexIn( text, offset, QRegExp::CaretAtOffset );
|
|
|
|
if (_lastOffset == -1) return 0;
|
|
|
|
_lastOffsetLength = Expr.matchedLength();
|
|
|
|
if ( _lastOffset == offset ) {
|
|
// only valid when we match at the exact offset
|
|
return (_lastOffset + _lastOffsetLength);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void KateHlRegExpr::capturedTexts (QStringList &list)
|
|
{
|
|
list = Expr.capturedTexts();
|
|
}
|
|
|
|
KateHlItem *KateHlRegExpr::clone(const QStringList *args)
|
|
{
|
|
QString regexp = _regexp;
|
|
QStringList escArgs = *args;
|
|
|
|
for (QStringList::Iterator it = escArgs.begin(); it != escArgs.end(); ++it)
|
|
{
|
|
(*it).replace(QRegExp("(\\W)"), "\\\\1");
|
|
}
|
|
|
|
dynamicSubstitute(regexp, &escArgs);
|
|
|
|
if (regexp == _regexp)
|
|
return this;
|
|
|
|
// kDebug (13010) << "clone regexp: " << regexp;
|
|
|
|
KateHlRegExpr *ret = new KateHlRegExpr(attr, ctx, region, region2, regexp, _insensitive, _minimal);
|
|
ret->dynamicChild = true;
|
|
return ret;
|
|
}
|
|
// //END
|
|
|
|
//BEGIN KateHlLineContinue
|
|
KateHlLineContinue::KateHlLineContinue(int attribute, KateHlContextModification context, signed char regionId, signed char regionId2, QChar c)
|
|
: KateHlItem(attribute, context, regionId, regionId2)
|
|
, m_trailer(c.isNull() ? QLatin1Char('\\') : c)
|
|
{
|
|
}
|
|
|
|
int KateHlLineContinue::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
if ((len == 1) && (text[offset] == m_trailer))
|
|
return ++offset;
|
|
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlCStringChar
|
|
KateHlCStringChar::KateHlCStringChar(int attribute, KateHlContextModification context,signed char regionId,signed char regionId2)
|
|
: KateHlItem(attribute,context,regionId,regionId2) {
|
|
}
|
|
|
|
// checks for C escaped chars \n and escaped hex/octal chars
|
|
static int checkEscapedChar(const QString& text, int offset, int& len)
|
|
{
|
|
int i;
|
|
if (text[offset] == '\\' && len > 1)
|
|
{
|
|
offset++;
|
|
len--;
|
|
|
|
switch(text[offset].toAscii())
|
|
{
|
|
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 '\\':
|
|
offset++;
|
|
len--;
|
|
break;
|
|
|
|
case 'x': // if it's like \xff
|
|
offset++; // eat the x
|
|
len--;
|
|
// these for loops can probably be
|
|
// replaced with something else but
|
|
// for right now they work
|
|
// check for hexdigits
|
|
for (i = 0; (len > 0) && (i < 2); i++)
|
|
{
|
|
const char ch = text[offset].toAscii();
|
|
if (((ch >= '0') && (ch <= '9')) || (((ch & 0xdf) >= 'A') && ((ch & 0xdf) <= 'F'))) {
|
|
offset++;
|
|
len--;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == 0)
|
|
return 0; // 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; (len > 0) && (i < 3) && (text[offset] >='0'&& text[offset] <='7'); i++)
|
|
{
|
|
offset++;
|
|
len--;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int KateHlCStringChar::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
return checkEscapedChar(text, offset, len);
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHlCChar
|
|
KateHlCChar::KateHlCChar(int attribute, KateHlContextModification context,signed char regionId,signed char regionId2)
|
|
: KateHlItem(attribute,context,regionId,regionId2) {
|
|
}
|
|
|
|
int KateHlCChar::checkHgl(const QString& text, int offset, int len)
|
|
{
|
|
if ((len > 1) && (text[offset] == '\'') && (text[offset+1] != '\''))
|
|
{
|
|
int oldl;
|
|
oldl = len;
|
|
|
|
len--;
|
|
|
|
int offset2 = checkEscapedChar(text, offset + 1, len);
|
|
|
|
if (!offset2)
|
|
{
|
|
if (oldl > 2)
|
|
{
|
|
offset2 = offset + 2;
|
|
len = oldl - 2;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if ((len > 0) && (text[offset2] == '\''))
|
|
return ++offset2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//END
|
|
|
|
//BEGIN KateHl2CharDetect
|
|
KateHl2CharDetect::KateHl2CharDetect(int attribute, KateHlContextModification context, signed char regionId,signed char regionId2, const QChar *s)
|
|
: KateHlItem(attribute,context,regionId,regionId2) {
|
|
sChar1 = s[0];
|
|
sChar2 = s[1];
|
|
}
|
|
//END KateHl2CharDetect
|
|
|
|
//BEGIN KateHlContext
|
|
KateHlContext::KateHlContext (const QString &_hlId, int attribute, KateHlContextModification _lineEndContext, bool _fallthrough,
|
|
KateHlContextModification _fallthroughContext, bool _dynamic, bool _noIndentationBasedFolding,
|
|
bool _emptyLineContext, KateHlContextModification _emptyLineContextModification)
|
|
{
|
|
hlId = _hlId;
|
|
attr = attribute;
|
|
lineEndContext = _lineEndContext;
|
|
fallthrough = _fallthrough;
|
|
ftctx = _fallthroughContext;
|
|
dynamic = _dynamic;
|
|
dynamicChild = false;
|
|
noIndentationBasedFolding=_noIndentationBasedFolding;
|
|
emptyLineContext = _emptyLineContext;
|
|
emptyLineContextModification = _emptyLineContextModification;
|
|
if (_noIndentationBasedFolding) kDebug(13010)<<QString("**********************_noIndentationBasedFolding is TRUE*****************");
|
|
|
|
}
|
|
|
|
KateHlContext *KateHlContext::clone(const QStringList *args)
|
|
{
|
|
KateHlContext *ret = new KateHlContext(hlId, attr, lineEndContext, fallthrough, ftctx, false,noIndentationBasedFolding
|
|
, emptyLineContext, emptyLineContextModification
|
|
);
|
|
|
|
for (int n=0; n < items.size(); ++n)
|
|
{
|
|
KateHlItem *item = items[n];
|
|
KateHlItem *i = (item->dynamic ? item->clone(args) : item);
|
|
ret->items.append(i);
|
|
}
|
|
|
|
ret->dynamicChild = true;
|
|
|
|
return ret;
|
|
}
|
|
|
|
KateHlContext::~KateHlContext()
|
|
{
|
|
if (dynamicChild)
|
|
{
|
|
for (int n=0; n < items.size(); ++n)
|
|
{
|
|
if (items[n]->dynamicChild)
|
|
delete items[n];
|
|
}
|
|
}
|
|
}
|
|
//END
|
|
|
|
// kate: space-indent on; indent-width 2; replace-tabs on;
|