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