diff options
Diffstat (limited to 'src/PositionCache.cxx')
| -rw-r--r-- | src/PositionCache.cxx | 88 | 
1 files changed, 78 insertions, 10 deletions
| diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx index 742a226b9..d92d49338 100644 --- a/src/PositionCache.cxx +++ b/src/PositionCache.cxx @@ -13,6 +13,9 @@  #include <string>  #include <vector>  #include <map> +#ifndef SCINTILLA_NO_UNORDERED_MAP +#include <unordered_map> +#endif  #include "Platform.h" @@ -34,6 +37,7 @@  #include "ILexer.h"  #include "CaseFolder.h"  #include "Document.h" +#include "UniConversion.h"  #include "Selection.h"  #include "PositionCache.h" @@ -336,6 +340,62 @@ void LineLayoutCache::Dispose(LineLayout *ll) {  	}  } +// Simply pack the (maximum 4) character bytes into an int +static inline int KeyFromString(const char *charBytes, size_t len) { +	PLATFORM_ASSERT(len <= 4); +	int k=0; +	for (size_t i=0; i<len && charBytes[i]; i++) { +		k = k * 0x100; +		k += charBytes[i]; +	} +	return k; +} + +SpecialRepresentations::SpecialRepresentations() { +	std::fill(startByteHasReprs, startByteHasReprs+0x100, 0); +} + +void SpecialRepresentations::SetRepresentation(const char *charBytes, const char *value) { +	MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, UTF8MaxBytes)); +	if (it == mapReprs.end()) { +		// New entry so increment for first byte +		startByteHasReprs[static_cast<unsigned char>(charBytes[0])]++; +	} +	mapReprs[KeyFromString(charBytes, UTF8MaxBytes)] = value; +} + +void SpecialRepresentations::ClearRepresentation(const char *charBytes) { +	MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, UTF8MaxBytes)); +	if (it != mapReprs.end()) { +		mapReprs.erase(it); +		startByteHasReprs[static_cast<unsigned char>(charBytes[0])]--; +	} +} + +Representation *SpecialRepresentations::RepresentationFromCharacter(const char *charBytes, size_t len) { +	PLATFORM_ASSERT(len <= 4); +	if (!startByteHasReprs[static_cast<unsigned char>(charBytes[0])]) +		return 0; +	MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, len)); +	if (it != mapReprs.end()) { +		return &(it->second); +	} +	return 0; +} + +bool SpecialRepresentations::Contains(const char *charBytes, size_t len) const { +	PLATFORM_ASSERT(len <= 4); +	if (!startByteHasReprs[static_cast<unsigned char>(charBytes[0])]) +		return false; +	MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes, len)); +	return it != mapReprs.end(); +} + +void SpecialRepresentations::Clear() { +	mapReprs.clear(); +	std::fill(startByteHasReprs, startByteHasReprs+0x100, 0); +} +  void BreakFinder::Insert(int val) {  	if (val >= nextBreak) {  		for (std::vector<int>::iterator it = selAndEdge.begin(); it != selAndEdge.end(); ++it) { @@ -352,6 +412,7 @@ void BreakFinder::Insert(int val) {  	}  } +/*  extern bool BadUTF(const char *s, int len, int &trailBytes);  static int NextBadU(const char *s, int p, int len, int &trailBytes) { @@ -362,9 +423,10 @@ static int NextBadU(const char *s, int p, int len, int &trailBytes) {  	}  	return -1;  } +*/  BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, -	int xStart, bool breakForSelection, Document *pdoc_) : +	int xStart, bool breakForSelection, Document *pdoc_, SpecialRepresentations *preprs_) :  	ll(ll_),  	lineStart(lineStart_),  	lineEnd(lineEnd_), @@ -373,7 +435,8 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL  	saeCurrentPos(0),  	saeNext(0),  	subBreak(-1), -	pdoc(pdoc_) { +	pdoc(pdoc_), +	preprs(preprs_) {  	// Search for first visible break  	// First find the first visible character @@ -401,14 +464,19 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL  	Insert(ll->edgeColumn - 1);  	Insert(lineEnd - 1); -	if (pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage)) { -		int trailBytes=0; -		for (int pos = -1;;) { -			pos = NextBadU(ll->chars, pos, lineEnd, trailBytes); -			if (pos < 0) -				break; -			Insert(pos-1); -			Insert(pos); +	if (pdoc && preprs) { +		EncodingFamily encodingFamily = pdoc->CodePageFamily(); +		for (int posRepr=0; posRepr<lineEnd;) { +			int charWidth = 1; +			if (encodingFamily == efUnicode) +				charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(ll->chars) + posRepr, lineEnd - posRepr); +			else if (encodingFamily == efDBCS) +				charWidth = pdoc->IsDBCSLeadByte(ll->chars[posRepr]) ? 2 : 1; +			if (preprs->Contains(ll->chars + posRepr, charWidth)) { +				Insert(posRepr - 1); +				Insert(posRepr + charWidth - 1); +			} +			posRepr += charWidth;  		}  	}  	saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1; | 
