mirror of
				https://github.com/notepad-plus-plus/notepad-plus-plus.git
				synced 2025-10-31 03:24:04 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			209 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			5.0 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 Scintilla {
 | |
| 
 | |
| class WordClassifier {
 | |
| 	int baseStyle;
 | |
| 	int firstStyle;
 | |
| 	int lenStyles;
 | |
| 	std::map<std::string, int> wordToStyle;
 | |
| 
 | |
| public:
 | |
| 
 | |
| 	explicit WordClassifier(int baseStyle_) : baseStyle(baseStyle_), firstStyle(0), lenStyles(0) {
 | |
| 	}
 | |
| 
 | |
| 	void Allocate(int firstStyle_, int lenStyles_) {
 | |
| 		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(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;
 | |
| 	}
 | |
| 
 | |
| 	bool IncludesStyle(int style) const noexcept {
 | |
| 		return (style >= firstStyle) && (style < (firstStyle + lenStyles));
 | |
| 	}
 | |
| 
 | |
| 	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;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	void SetIdentifiers(int style, const char *identifiers) {
 | |
| 		RemoveStyle(style);
 | |
| 		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);
 | |
| 				wordToStyle[word] = style;
 | |
| 			}
 | |
| 			identifiers = cpSpace;
 | |
| 			if (*identifiers)
 | |
| 				identifiers++;
 | |
| 		}
 | |
| 	}
 | |
| };
 | |
| 
 | |
| 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 {
 | |
| 		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]) {
 | |
| 			classifiers.push_back(WordClassifier(baseStyles[classifications]));
 | |
| 			classifications++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	int Allocate(int styleBase, int numberStyles) {
 | |
| 		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 {
 | |
| 		const int block = BlockFromStyle(subStyle);
 | |
| 		if (block >= 0)
 | |
| 			return classifiers[block].Base();
 | |
| 		else
 | |
| 			return subStyle;
 | |
| 	}
 | |
| 
 | |
| 	int DistanceToSecondaryStyles() const noexcept {
 | |
| 		return secondaryDistance;
 | |
| 	}
 | |
| 
 | |
| 	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;
 | |
| 	}
 | |
| 
 | |
| 	void SetIdentifiers(int style, const char *identifiers) {
 | |
| 		const int block = BlockFromStyle(style);
 | |
| 		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();
 | |
| 	}
 | |
| 
 | |
| 	const WordClassifier &Classifier(int baseStyle) const noexcept {
 | |
| 		const int block = BlockFromBaseStyle(baseStyle);
 | |
| 		return classifiers[block >= 0 ? block : 0];
 | |
| 	}
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif
 |