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
IsEOLChar(int ch)13 inline constexpr bool IsEOLChar(int ch) noexcept {
14 return (ch == '\r') || (ch == '\n');
15 }
16
IsSpaceOrTab(int ch)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
x(x_)30 explicit PointDocument(double x_ = 0, double y_ = 0) noexcept : x(x_), y(y_) {
31 }
32
33 // Conversion from Point.
PointDocument(Point pt)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;
GetLevel()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;
stringRep(value)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 :
startTextSegment229 start(start_), length(length_), representation(representation_) {
230 }
endTextSegment231 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_);
GetSize()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