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