// Scintilla source code edit control /** @file PositionCache.h ** Classes for caching layout information. **/ // Copyright 1998-2009 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef POSITIONCACHE_H #define POSITIONCACHE_H #ifdef SCI_NAMESPACE namespace Scintilla { #endif static inline bool IsEOLChar(char ch) { return (ch == '\r') || (ch == '\n'); } /** */ class LineLayout { private: friend class LineLayoutCache; int *lineStarts; int lenLineStarts; /// Drawing is only performed for @a maxLineLength characters on each line. int lineNumber; bool inCache; // no copy ctr or assignment op LineLayout(const LineLayout &); LineLayout &operator =(const LineLayout &); public: enum { wrapWidthInfinite = 0x7ffffff }; int maxLineLength; int numCharsInLine; int numCharsBeforeEOL; enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity; int xHighlightGuide; bool highlightColumn; Selection *psel; bool containsCaret; int edgeColumn; char *chars; unsigned char *styles; int styleBitsSet; char *indicators; XYPOSITION *positions; char bracePreviousStyles[2]; // Hotspot support int hsStart; int hsEnd; // Wrapped line support int widthLine; int lines; XYPOSITION wrapIndent; // In pixels explicit LineLayout(int maxLineLength_); virtual ~LineLayout(); void Resize(int maxLineLength_); void Free(); void Invalidate(validLevel validity_); int LineStart(int line) const; int LineLastVisible(int line) const; Range SubLineRange(int line) const; bool InLine(int offset, int line) const; void SetLineStart(int line, int start); void SetBracesHighlight(Range rangeLine, Position braces[], char bracesMatchStyle, int xHighlight, bool ignoreStyle); void RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle); int FindBefore(XYPOSITION x, int lower, int upper) const; int FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const; Point PointFromPosition(int posInLine, int lineHeight) const; int EndLineStyle() const; }; /** */ class LineLayoutCache { int level; std::vectorcache; bool allInvalidated; int styleClock; int useCount; void Allocate(size_t length_); void AllocateForLevel(int linesOnScreen, int linesInDoc); public: LineLayoutCache(); virtual ~LineLayoutCache(); void Deallocate(); enum { llcNone=SC_CACHE_NONE, llcCaret=SC_CACHE_CARET, llcPage=SC_CACHE_PAGE, llcDocument=SC_CACHE_DOCUMENT }; void Invalidate(LineLayout::validLevel validity_); void SetLevel(int level_); int GetLevel() const { return level; } LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_, int linesOnScreen, int linesInDoc); void Dispose(LineLayout *ll); }; class PositionCacheEntry { unsigned int styleNumber:8; unsigned int len:8; unsigned int clock:16; XYPOSITION *positions; public: PositionCacheEntry(); ~PositionCacheEntry(); void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock); void Clear(); bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const; static unsigned int Hash(unsigned int styleNumber_, const char *s, unsigned int len); bool NewerThan(const PositionCacheEntry &other) const; void ResetClock(); }; class Representation { public: std::string stringRep; explicit Representation(const char *value="") : stringRep(value) { } }; typedef std::map MapRepresentation; class SpecialRepresentations { MapRepresentation mapReprs; short startByteHasReprs[0x100]; public: SpecialRepresentations(); void SetRepresentation(const char *charBytes, const char *value); void ClearRepresentation(const char *charBytes); Representation *RepresentationFromCharacter(const char *charBytes, size_t len); bool Contains(const char *charBytes, size_t len) const; void Clear(); }; struct TextSegment { int start; int length; Representation *representation; TextSegment(int start_=0, int length_=0, Representation *representation_=0) : start(start_), length(length_), representation(representation_) { } int end() const { return start + length; } }; // Class to break a line of text into shorter runs at sensible places. class BreakFinder { LineLayout *ll; int lineStart; int lineEnd; int posLineStart; int nextBreak; std::vector selAndEdge; unsigned int saeCurrentPos; int saeNext; int subBreak; Document *pdoc; EncodingFamily encodingFamily; SpecialRepresentations *preprs; void Insert(int val); // no copy ctr or assignment op BreakFinder(const BreakFinder &); BreakFinder &operator =(const BreakFinder &); public: // If a whole run is longer than lengthStartSubdivision then subdivide // into smaller runs at spaces or punctuation. enum { lengthStartSubdivision = 300 }; // Try to make each subdivided run lengthEachSubdivision or shorter. enum { lengthEachSubdivision = 100 }; BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, int xStart, bool breakForSelection, Document *pdoc_, SpecialRepresentations *preprs_); ~BreakFinder(); TextSegment Next(); bool More() const; }; class PositionCache { std::vector pces; unsigned int clock; bool allClear; // no copy ctr or assignment op PositionCache(const PositionCache &); PositionCache &operator =(const PositionCache &); public: PositionCache(); ~PositionCache(); void Clear(); void SetSize(size_t size_); size_t GetSize() const { return pces.size(); } void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber, const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc); }; inline bool IsSpaceOrTab(int ch) { return ch == ' ' || ch == '\t'; } #ifdef SCI_NAMESPACE } #endif #endif