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
11namespace Scintilla::Internal {
12
13/**
14* A point in document space.
15* Uses double for sufficient resolution in large (>20,000,000 line) documents.
16*/
17class PointDocument {
18public:
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.
33enum class PointEnd {
34 start = 0x0,
35 lineEnd = 0x1,
36 subLineEnd = 0x2,
37 endEither = lineEnd | subLineEnd,
38};
39
40class BidiData {
41public:
42 std::vector<std::shared_ptr<Font>> stylesFonts;
43 std::vector<XYPOSITION> widthReprs;
44 void Resize(size_t maxLineLength_);
45};
46
47/**
48 */
49class LineLayout {
50private:
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;
56public:
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
109struct 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 */
141class LineLayoutCache {
142public:
143private:
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);
150public:
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
166class PositionCacheEntry {
167 uint16_t styleNumber;
168 uint16_t len;
169 uint16_t clock;
170 std::unique_ptr<XYPOSITION []> positions;
171public:
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
188class Representation {
189public:
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
199typedef std::map<unsigned int, Representation> MapRepresentation;
200
201class SpecialRepresentations {
202 MapRepresentation mapReprs;
203 unsigned short startByteHasReprs[0x100] {};
204 unsigned int maxKey = 0;
205 bool crlf = false;
206public:
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
222struct 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.
235class 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);
248public:
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
272class PositionCache {
273 std::vector<PositionCacheEntry> pces;
274 uint16_t clock;
275 bool allClear;
276public:
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