1 // Scintilla source code edit control 2 /** @file PositionCache.h 3 ** Classes for caching layout information. 4 **/ 5 // Copyright 1998-2009 by Neil Hodgson <[email protected]> 6 // The License.txt file describes the conditions under which this software may be distributed. 7 8 #ifndef POSITIONCACHE_H 9 #define POSITIONCACHE_H 10 11 namespace Scintilla { 12 13 inline constexpr bool IsEOLChar(int ch) noexcept { 14 return (ch == '\r') || (ch == '\n'); 15 } 16 17 inline constexpr bool IsSpaceOrTab(int ch) noexcept { 18 return ch == ' ' || ch == '\t'; 19 } 20 21 /** 22 * A point in document space. 23 * Uses double for sufficient resolution in large (>20,000,000 line) documents. 24 */ 25 class PointDocument { 26 public: 27 double x; 28 double y; 29 30 explicit PointDocument(double x_ = 0, double y_ = 0) noexcept : x(x_), y(y_) { 31 } 32 33 // Conversion from Point. 34 explicit PointDocument(Point pt) noexcept : x(pt.x), y(pt.y) { 35 } 36 }; 37 38 // There are two points for some positions and this enumeration 39 // can choose between the end of the first line or subline 40 // and the start of the next line or subline. 41 enum PointEnd { 42 peDefault = 0x0, 43 peLineEnd = 0x1, 44 peSubLineEnd = 0x2 45 }; 46 47 class BidiData { 48 public: 49 std::vector<FontAlias> stylesFonts; 50 std::vector<XYPOSITION> widthReprs; 51 void Resize(size_t maxLineLength_); 52 }; 53 54 /** 55 */ 56 class LineLayout { 57 private: 58 friend class LineLayoutCache; 59 std::unique_ptr<int []>lineStarts; 60 int lenLineStarts; 61 /// Drawing is only performed for @a maxLineLength characters on each line. 62 Sci::Line lineNumber; 63 bool inCache; 64 public: 65 enum { wrapWidthInfinite = 0x7ffffff }; 66 67 int maxLineLength; 68 int numCharsInLine; 69 int numCharsBeforeEOL; 70 enum class ValidLevel { invalid, checkTextAndStyle, positions, lines } validity; 71 int xHighlightGuide; 72 bool highlightColumn; 73 bool containsCaret; 74 int edgeColumn; 75 std::unique_ptr<char[]> chars; 76 std::unique_ptr<unsigned char[]> styles; 77 std::unique_ptr<XYPOSITION[]> positions; 78 char bracePreviousStyles[2]; 79 80 std::unique_ptr<BidiData> bidiData; 81 82 // Hotspot support 83 Range hotspot; 84 85 // Wrapped line support 86 int widthLine; 87 int lines; 88 XYPOSITION wrapIndent; // In pixels 89 90 explicit LineLayout(int maxLineLength_); 91 // Deleted so LineLayout objects can not be copied. 92 LineLayout(const LineLayout &) = delete; 93 LineLayout(LineLayout &&) = delete; 94 void operator=(const LineLayout &) = delete; 95 void operator=(LineLayout &&) = delete; 96 virtual ~LineLayout(); 97 void Resize(int maxLineLength_); 98 void EnsureBidiData(); 99 void Free() noexcept; 100 void Invalidate(ValidLevel validity_) noexcept; 101 int LineStart(int line) const noexcept; 102 int LineLength(int line) const noexcept; 103 enum class Scope { visibleOnly, includeEnd }; 104 int LineLastVisible(int line, Scope scope) const noexcept; 105 Range SubLineRange(int subLine, Scope scope) const noexcept; 106 bool InLine(int offset, int line) const noexcept; 107 int SubLineFromPosition(int posInLine, PointEnd pe) const noexcept; 108 void SetLineStart(int line, int start); 109 void SetBracesHighlight(Range rangeLine, const Sci::Position braces[], 110 char bracesMatchStyle, int xHighlight, bool ignoreStyle); 111 void RestoreBracesHighlight(Range rangeLine, const Sci::Position braces[], bool ignoreStyle); 112 int FindBefore(XYPOSITION x, Range range) const noexcept; 113 int FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const noexcept; 114 Point PointFromPosition(int posInLine, int lineHeight, PointEnd pe) const noexcept; 115 int EndLineStyle() const noexcept; 116 }; 117 118 struct ScreenLine : public IScreenLine { 119 const LineLayout *ll; 120 size_t start; 121 size_t len; 122 XYPOSITION width; 123 XYPOSITION height; 124 int ctrlCharPadding; 125 XYPOSITION tabWidth; 126 int tabWidthMinimumPixels; 127 128 ScreenLine(const LineLayout *ll_, int subLine, const ViewStyle &vs, XYPOSITION width_, int tabWidthMinimumPixels_); 129 // Deleted so ScreenLine objects can not be copied. 130 ScreenLine(const ScreenLine &) = delete; 131 ScreenLine(ScreenLine &&) = delete; 132 void operator=(const ScreenLine &) = delete; 133 void operator=(ScreenLine &&) = delete; 134 virtual ~ScreenLine(); 135 136 std::string_view Text() const override; 137 size_t Length() const override; 138 size_t RepresentationCount() const override; 139 XYPOSITION Width() const override; 140 XYPOSITION Height() const override; 141 XYPOSITION TabWidth() const override; 142 XYPOSITION TabWidthMinimumPixels() const override; 143 const Font *FontOfPosition(size_t position) const override; 144 XYPOSITION RepresentationWidth(size_t position) const override; 145 XYPOSITION TabPositionAfter(XYPOSITION xPosition) const override; 146 }; 147 148 /** 149 */ 150 class LineLayoutCache { 151 int level; 152 std::vector<std::unique_ptr<LineLayout>>cache; 153 bool allInvalidated; 154 int styleClock; 155 int useCount; 156 void Allocate(size_t length_); 157 void AllocateForLevel(Sci::Line linesOnScreen, Sci::Line linesInDoc); 158 public: 159 LineLayoutCache(); 160 // Deleted so LineLayoutCache objects can not be copied. 161 LineLayoutCache(const LineLayoutCache &) = delete; 162 LineLayoutCache(LineLayoutCache &&) = delete; 163 void operator=(const LineLayoutCache &) = delete; 164 void operator=(LineLayoutCache &&) = delete; 165 virtual ~LineLayoutCache(); 166 void Deallocate() noexcept; 167 enum { 168 llcNone=SC_CACHE_NONE, 169 llcCaret=SC_CACHE_CARET, 170 llcPage=SC_CACHE_PAGE, 171 llcDocument=SC_CACHE_DOCUMENT 172 }; 173 void Invalidate(LineLayout::ValidLevel validity_) noexcept; 174 void SetLevel(int level_) noexcept; 175 int GetLevel() const noexcept { return level; } 176 LineLayout *Retrieve(Sci::Line lineNumber, Sci::Line lineCaret, int maxChars, int styleClock_, 177 Sci::Line linesOnScreen, Sci::Line linesInDoc); 178 void Dispose(LineLayout *ll) noexcept; 179 }; 180 181 class PositionCacheEntry { 182 unsigned int styleNumber:8; 183 unsigned int len:8; 184 unsigned int clock:16; 185 std::unique_ptr<XYPOSITION []> positions; 186 public: 187 PositionCacheEntry() noexcept; 188 // Copy constructor not currently used, but needed for being element in std::vector. 189 PositionCacheEntry(const PositionCacheEntry &); 190 PositionCacheEntry(PositionCacheEntry &&) noexcept = default; 191 // Deleted so PositionCacheEntry objects can not be assigned. 192 void operator=(const PositionCacheEntry &) = delete; 193 void operator=(PositionCacheEntry &&) = delete; 194 ~PositionCacheEntry(); 195 void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, const XYPOSITION *positions_, unsigned int clock_); 196 void Clear() noexcept; 197 bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const noexcept; 198 static unsigned int Hash(unsigned int styleNumber_, const char *s, unsigned int len_) noexcept; 199 bool NewerThan(const PositionCacheEntry &other) const noexcept; 200 void ResetClock() noexcept; 201 }; 202 203 class Representation { 204 public: 205 std::string stringRep; 206 explicit Representation(const char *value="") : stringRep(value) { 207 } 208 }; 209 210 typedef std::map<unsigned int, Representation> MapRepresentation; 211 212 class SpecialRepresentations { 213 MapRepresentation mapReprs; 214 short startByteHasReprs[0x100]; 215 public: 216 SpecialRepresentations(); 217 void SetRepresentation(const char *charBytes, const char *value); 218 void ClearRepresentation(const char *charBytes); 219 const Representation *RepresentationFromCharacter(const char *charBytes, size_t len) const; 220 bool Contains(const char *charBytes, size_t len) const; 221 void Clear(); 222 }; 223 224 struct TextSegment { 225 int start; 226 int length; 227 const Representation *representation; 228 TextSegment(int start_=0, int length_=0, const Representation *representation_=nullptr) noexcept : 229 start(start_), length(length_), representation(representation_) { 230 } 231 int end() const noexcept { 232 return start + length; 233 } 234 }; 235 236 // Class to break a line of text into shorter runs at sensible places. 237 class BreakFinder { 238 const LineLayout *ll; 239 Range lineRange; 240 Sci::Position posLineStart; 241 int nextBreak; 242 std::vector<int> selAndEdge; 243 unsigned int saeCurrentPos; 244 int saeNext; 245 int subBreak; 246 const Document *pdoc; 247 EncodingFamily encodingFamily; 248 const SpecialRepresentations *preprs; 249 void Insert(Sci::Position val); 250 public: 251 // If a whole run is longer than lengthStartSubdivision then subdivide 252 // into smaller runs at spaces or punctuation. 253 enum { lengthStartSubdivision = 300 }; 254 // Try to make each subdivided run lengthEachSubdivision or shorter. 255 enum { lengthEachSubdivision = 100 }; 256 BreakFinder(const LineLayout *ll_, const Selection *psel, Range lineRange_, Sci::Position posLineStart_, 257 int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw); 258 // Deleted so BreakFinder objects can not be copied. 259 BreakFinder(const BreakFinder &) = delete; 260 BreakFinder(BreakFinder &&) = delete; 261 void operator=(const BreakFinder &) = delete; 262 void operator=(BreakFinder &&) = delete; 263 ~BreakFinder(); 264 TextSegment Next(); 265 bool More() const noexcept; 266 }; 267 268 class PositionCache { 269 std::vector<PositionCacheEntry> pces; 270 unsigned int clock; 271 bool allClear; 272 public: 273 PositionCache(); 274 // Deleted so PositionCache objects can not be copied. 275 PositionCache(const PositionCache &) = delete; 276 PositionCache(PositionCache &&) = delete; 277 void operator=(const PositionCache &) = delete; 278 void operator=(PositionCache &&) = delete; 279 ~PositionCache(); 280 void Clear() noexcept; 281 void SetSize(size_t size_); 282 size_t GetSize() const noexcept { return pces.size(); } 283 void MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber, 284 const char *s, unsigned int len, XYPOSITION *positions, const Document *pdoc); 285 }; 286 287 } 288 289 #endif 290