2013-08-28 00:44:27 +00:00
|
|
|
// Scintilla source code edit control
|
|
|
|
/** @file SubStyles.h
|
|
|
|
** Manage substyles for a lexer.
|
|
|
|
**/
|
|
|
|
// Copyright 2012 by Neil Hodgson <neilh@scintilla.org>
|
|
|
|
// The License.txt file describes the conditions under which this software may be distributed.
|
|
|
|
|
|
|
|
#ifndef SUBSTYLES_H
|
|
|
|
#define SUBSTYLES_H
|
|
|
|
|
|
|
|
namespace Scintilla {
|
|
|
|
|
|
|
|
class WordClassifier {
|
2015-06-07 21:19:26 +00:00
|
|
|
int baseStyle;
|
2013-08-28 00:44:27 +00:00
|
|
|
int firstStyle;
|
|
|
|
int lenStyles;
|
|
|
|
std::map<std::string, int> wordToStyle;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2015-06-07 21:19:26 +00:00
|
|
|
explicit WordClassifier(int baseStyle_) : baseStyle(baseStyle_), firstStyle(0), lenStyles(0) {
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Allocate(int firstStyle_, int lenStyles_) {
|
|
|
|
firstStyle = firstStyle_;
|
|
|
|
lenStyles = lenStyles_;
|
|
|
|
wordToStyle.clear();
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
int Base() const noexcept {
|
2015-06-07 21:19:26 +00:00
|
|
|
return baseStyle;
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
int Start() const noexcept {
|
2013-08-28 00:44:27 +00:00
|
|
|
return firstStyle;
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
int Last() const noexcept {
|
2019-05-04 18:14:48 +00:00
|
|
|
return firstStyle + lenStyles - 1;
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
int Length() const noexcept {
|
2013-08-28 00:44:27 +00:00
|
|
|
return lenStyles;
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
void Clear() noexcept {
|
2013-08-28 00:44:27 +00:00
|
|
|
firstStyle = 0;
|
|
|
|
lenStyles = 0;
|
|
|
|
wordToStyle.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ValueFor(const std::string &s) const {
|
|
|
|
std::map<std::string, int>::const_iterator it = wordToStyle.find(s);
|
|
|
|
if (it != wordToStyle.end())
|
|
|
|
return it->second;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
bool IncludesStyle(int style) const noexcept {
|
2013-08-28 00:44:27 +00:00
|
|
|
return (style >= firstStyle) && (style < (firstStyle + lenStyles));
|
|
|
|
}
|
|
|
|
|
2019-07-21 13:26:02 +00:00
|
|
|
void RemoveStyle(int style) {
|
|
|
|
std::map<std::string, int>::iterator it = wordToStyle.begin();
|
|
|
|
while (it != wordToStyle.end()) {
|
|
|
|
if (it->second == style) {
|
|
|
|
it = wordToStyle.erase(it);
|
|
|
|
} else {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
void SetIdentifiers(int style, const char *identifiers) {
|
2019-07-21 13:26:02 +00:00
|
|
|
RemoveStyle(style);
|
2013-08-28 00:44:27 +00:00
|
|
|
while (*identifiers) {
|
|
|
|
const char *cpSpace = identifiers;
|
2015-06-07 21:19:26 +00:00
|
|
|
while (*cpSpace && !(*cpSpace == ' ' || *cpSpace == '\t' || *cpSpace == '\r' || *cpSpace == '\n'))
|
2013-08-28 00:44:27 +00:00
|
|
|
cpSpace++;
|
2015-06-07 21:19:26 +00:00
|
|
|
if (cpSpace > identifiers) {
|
|
|
|
std::string word(identifiers, cpSpace - identifiers);
|
|
|
|
wordToStyle[word] = style;
|
|
|
|
}
|
2013-08-28 00:44:27 +00:00
|
|
|
identifiers = cpSpace;
|
|
|
|
if (*identifiers)
|
|
|
|
identifiers++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SubStyles {
|
|
|
|
int classifications;
|
|
|
|
const char *baseStyles;
|
|
|
|
int styleFirst;
|
|
|
|
int stylesAvailable;
|
|
|
|
int secondaryDistance;
|
|
|
|
int allocated;
|
|
|
|
std::vector<WordClassifier> classifiers;
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
int BlockFromBaseStyle(int baseStyle) const noexcept {
|
2013-08-28 00:44:27 +00:00
|
|
|
for (int b=0; b < classifications; b++) {
|
|
|
|
if (baseStyle == baseStyles[b])
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int BlockFromStyle(int style) const {
|
|
|
|
int b = 0;
|
|
|
|
for (std::vector<WordClassifier>::const_iterator it=classifiers.begin(); it != classifiers.end(); ++it) {
|
|
|
|
if (it->IncludesStyle(style))
|
|
|
|
return b;
|
|
|
|
b++;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
SubStyles(const char *baseStyles_, int styleFirst_, int stylesAvailable_, int secondaryDistance_) :
|
|
|
|
classifications(0),
|
|
|
|
baseStyles(baseStyles_),
|
|
|
|
styleFirst(styleFirst_),
|
|
|
|
stylesAvailable(stylesAvailable_),
|
|
|
|
secondaryDistance(secondaryDistance_),
|
|
|
|
allocated(0) {
|
|
|
|
while (baseStyles[classifications]) {
|
2015-06-07 21:19:26 +00:00
|
|
|
classifiers.push_back(WordClassifier(baseStyles[classifications]));
|
2013-08-28 00:44:27 +00:00
|
|
|
classifications++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Allocate(int styleBase, int numberStyles) {
|
2019-05-04 18:14:48 +00:00
|
|
|
const int block = BlockFromBaseStyle(styleBase);
|
2013-08-28 00:44:27 +00:00
|
|
|
if (block >= 0) {
|
|
|
|
if ((allocated + numberStyles) > stylesAvailable)
|
|
|
|
return -1;
|
2019-05-04 18:14:48 +00:00
|
|
|
const int startBlock = styleFirst + allocated;
|
2013-08-28 00:44:27 +00:00
|
|
|
allocated += numberStyles;
|
|
|
|
classifiers[block].Allocate(startBlock, numberStyles);
|
|
|
|
return startBlock;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
int Start(int styleBase) noexcept {
|
2019-05-04 18:14:48 +00:00
|
|
|
const int block = BlockFromBaseStyle(styleBase);
|
2013-08-28 00:44:27 +00:00
|
|
|
return (block >= 0) ? classifiers[block].Start() : -1;
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
int Length(int styleBase) noexcept {
|
2019-05-04 18:14:48 +00:00
|
|
|
const int block = BlockFromBaseStyle(styleBase);
|
2013-08-28 00:44:27 +00:00
|
|
|
return (block >= 0) ? classifiers[block].Length() : 0;
|
|
|
|
}
|
|
|
|
|
2015-06-07 21:19:26 +00:00
|
|
|
int BaseStyle(int subStyle) const {
|
2019-05-04 18:14:48 +00:00
|
|
|
const int block = BlockFromStyle(subStyle);
|
2015-06-07 21:19:26 +00:00
|
|
|
if (block >= 0)
|
|
|
|
return classifiers[block].Base();
|
|
|
|
else
|
|
|
|
return subStyle;
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
int DistanceToSecondaryStyles() const noexcept {
|
2013-08-28 00:44:27 +00:00
|
|
|
return secondaryDistance;
|
|
|
|
}
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
int FirstAllocated() const {
|
|
|
|
int start = 257;
|
|
|
|
for (std::vector<WordClassifier>::const_iterator it = classifiers.begin(); it != classifiers.end(); ++it) {
|
|
|
|
if (start > it->Start())
|
|
|
|
start = it->Start();
|
|
|
|
}
|
|
|
|
return (start < 256) ? start : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LastAllocated() const {
|
|
|
|
int last = -1;
|
|
|
|
for (std::vector<WordClassifier>::const_iterator it = classifiers.begin(); it != classifiers.end(); ++it) {
|
|
|
|
if (last < it->Last())
|
|
|
|
last = it->Last();
|
|
|
|
}
|
|
|
|
return last;
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
void SetIdentifiers(int style, const char *identifiers) {
|
2019-05-04 18:14:48 +00:00
|
|
|
const int block = BlockFromStyle(style);
|
2013-08-28 00:44:27 +00:00
|
|
|
if (block >= 0)
|
|
|
|
classifiers[block].SetIdentifiers(style, identifiers);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Free() {
|
|
|
|
allocated = 0;
|
|
|
|
for (std::vector<WordClassifier>::iterator it=classifiers.begin(); it != classifiers.end(); ++it)
|
|
|
|
it->Clear();
|
|
|
|
}
|
|
|
|
|
2021-02-21 04:53:09 +00:00
|
|
|
const WordClassifier &Classifier(int baseStyle) const noexcept {
|
2015-06-07 21:19:26 +00:00
|
|
|
const int block = BlockFromBaseStyle(baseStyle);
|
|
|
|
return classifiers[block >= 0 ? block : 0];
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|