mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-04-08 17:15:37 +02:00
Release 5.5.2 ( https://www.scintilla.org/scintilla552.zip ) Released 21 August 2024. Add SCI_SETCOPYSEPARATOR for separator between parts of a multiple selection when copied to the clipboard. Feature #1530. Add SCI_GETUNDOSEQUENCE to determine whether an undo sequence is active and its nesting depth. Add SCI_STYLESETSTRETCH to support condensed and expanded text styles. Add SCI_LINEINDENT and SCI_LINEDEDENT. Feature #1524. Fix bug on Cocoa where double-click stopped working when system had been running for a long time. On Cocoa implement more values of font weight and stretch. Release 5.4.0 ( https://www.scintilla.org/lexilla540.zip ) Released 21 August 2024. Inside Lexilla, LexerModule instances are now const. This will require changes to applications that modify Lexilla.cxx, which may be done to add custom lexers. Lexer added for TOML "toml". Bash: Handle backslash in heredoc delimiter. Issue #257. Progress: Fix lexing of nested comments. Pull request #258. Force lower-casing of case-insensitive keyword lists so keywords match in some lexers. Issue #259. Close #15564
222 lines
5.1 KiB
C++
222 lines
5.1 KiB
C++
// 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 Lexilla {
|
|
|
|
class WordClassifier {
|
|
int baseStyle;
|
|
int firstStyle;
|
|
int lenStyles;
|
|
using WordStyleMap = std::map<std::string, int, std::less<>>;
|
|
WordStyleMap wordToStyle;
|
|
|
|
public:
|
|
|
|
explicit WordClassifier(int baseStyle_) : baseStyle(baseStyle_), firstStyle(0), lenStyles(0) {
|
|
}
|
|
|
|
void Allocate(int firstStyle_, int lenStyles_) noexcept {
|
|
firstStyle = firstStyle_;
|
|
lenStyles = lenStyles_;
|
|
wordToStyle.clear();
|
|
}
|
|
|
|
int Base() const noexcept {
|
|
return baseStyle;
|
|
}
|
|
|
|
int Start() const noexcept {
|
|
return firstStyle;
|
|
}
|
|
|
|
int Last() const noexcept {
|
|
return firstStyle + lenStyles - 1;
|
|
}
|
|
|
|
int Length() const noexcept {
|
|
return lenStyles;
|
|
}
|
|
|
|
void Clear() noexcept {
|
|
firstStyle = 0;
|
|
lenStyles = 0;
|
|
wordToStyle.clear();
|
|
}
|
|
|
|
int ValueFor(std::string_view s) const {
|
|
WordStyleMap::const_iterator const it = wordToStyle.find(s);
|
|
if (it != wordToStyle.end())
|
|
return it->second;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
bool IncludesStyle(int style) const noexcept {
|
|
return (style >= firstStyle) && (style < (firstStyle + lenStyles));
|
|
}
|
|
|
|
void RemoveStyle(int style) noexcept {
|
|
WordStyleMap::iterator it = wordToStyle.begin();
|
|
while (it != wordToStyle.end()) {
|
|
if (it->second == style) {
|
|
it = wordToStyle.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetIdentifiers(int style, const char *identifiers, bool lowerCase) {
|
|
RemoveStyle(style);
|
|
if (!identifiers)
|
|
return;
|
|
while (*identifiers) {
|
|
const char *cpSpace = identifiers;
|
|
while (*cpSpace && !(*cpSpace == ' ' || *cpSpace == '\t' || *cpSpace == '\r' || *cpSpace == '\n'))
|
|
cpSpace++;
|
|
if (cpSpace > identifiers) {
|
|
std::string word(identifiers, cpSpace - identifiers);
|
|
if (lowerCase) {
|
|
for (char &ch : word) {
|
|
ch = MakeLowerCase(ch);
|
|
}
|
|
}
|
|
wordToStyle[word] = style;
|
|
}
|
|
identifiers = cpSpace;
|
|
if (*identifiers)
|
|
identifiers++;
|
|
}
|
|
}
|
|
};
|
|
|
|
// This is the common configuration: 64 sub-styles allocated from 128 to 191
|
|
constexpr int SubStylesFirst = 0x80;
|
|
constexpr int SubStylesAvailable = 0x40;
|
|
|
|
class SubStyles {
|
|
int classifications;
|
|
const char *baseStyles;
|
|
int styleFirst;
|
|
int stylesAvailable;
|
|
int secondaryDistance;
|
|
int allocated;
|
|
std::vector<WordClassifier> classifiers;
|
|
|
|
int BlockFromBaseStyle(int baseStyle) const noexcept {
|
|
for (int b=0; b < classifications; b++) {
|
|
if (baseStyle == baseStyles[b])
|
|
return b;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int BlockFromStyle(int style) const noexcept {
|
|
int b = 0;
|
|
for (const WordClassifier &wc : classifiers) {
|
|
if (wc.IncludesStyle(style))
|
|
return b;
|
|
b++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public:
|
|
|
|
SubStyles(const char *baseStyles_, int styleFirst_=SubStylesFirst, int stylesAvailable_=SubStylesAvailable, int secondaryDistance_=0) :
|
|
classifications(0),
|
|
baseStyles(baseStyles_),
|
|
styleFirst(styleFirst_),
|
|
stylesAvailable(stylesAvailable_),
|
|
secondaryDistance(secondaryDistance_),
|
|
allocated(0) {
|
|
while (baseStyles[classifications]) {
|
|
classifiers.push_back(WordClassifier(baseStyles[classifications]));
|
|
classifications++;
|
|
}
|
|
}
|
|
|
|
int Allocate(int styleBase, int numberStyles) noexcept {
|
|
const int block = BlockFromBaseStyle(styleBase);
|
|
if (block >= 0) {
|
|
if ((allocated + numberStyles) > stylesAvailable)
|
|
return -1;
|
|
const int startBlock = styleFirst + allocated;
|
|
allocated += numberStyles;
|
|
classifiers[block].Allocate(startBlock, numberStyles);
|
|
return startBlock;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int Start(int styleBase) noexcept {
|
|
const int block = BlockFromBaseStyle(styleBase);
|
|
return (block >= 0) ? classifiers[block].Start() : -1;
|
|
}
|
|
|
|
int Length(int styleBase) noexcept {
|
|
const int block = BlockFromBaseStyle(styleBase);
|
|
return (block >= 0) ? classifiers[block].Length() : 0;
|
|
}
|
|
|
|
int BaseStyle(int subStyle) const noexcept {
|
|
const int block = BlockFromStyle(subStyle);
|
|
if (block >= 0)
|
|
return classifiers[block].Base();
|
|
else
|
|
return subStyle;
|
|
}
|
|
|
|
int DistanceToSecondaryStyles() const noexcept {
|
|
return secondaryDistance;
|
|
}
|
|
|
|
int FirstAllocated() const noexcept {
|
|
int start = 257;
|
|
for (const WordClassifier &wc : classifiers) {
|
|
if ((wc.Length() > 0) && (start > wc.Start()))
|
|
start = wc.Start();
|
|
}
|
|
return (start < 256) ? start : -1;
|
|
}
|
|
|
|
int LastAllocated() const noexcept {
|
|
int last = -1;
|
|
for (const WordClassifier &wc : classifiers) {
|
|
if ((wc.Length() > 0) && (last < wc.Last()))
|
|
last = wc.Last();
|
|
}
|
|
return last;
|
|
}
|
|
|
|
void SetIdentifiers(int style, const char *identifiers, bool lowerCase=false) {
|
|
const int block = BlockFromStyle(style);
|
|
if (block >= 0)
|
|
classifiers[block].SetIdentifiers(style, identifiers, lowerCase);
|
|
}
|
|
|
|
void Free() noexcept {
|
|
allocated = 0;
|
|
for (WordClassifier &wc : classifiers) {
|
|
wc.Clear();
|
|
}
|
|
}
|
|
|
|
const WordClassifier &Classifier(int baseStyle) const noexcept {
|
|
const int block = BlockFromBaseStyle(baseStyle);
|
|
return classifiers[block >= 0 ? block : 0];
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|