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 {
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 /**
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 	bool inCache;
57 public:
58 	enum { wrapWidthInfinite = 0x7ffffff };
59 
60 	int maxLineLength;
61 	int numCharsInLine;
62 	int numCharsBeforeEOL;
63 	enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity;
64 	int xHighlightGuide;
65 	bool highlightColumn;
66 	bool containsCaret;
67 	int edgeColumn;
68 	std::unique_ptr<char[]> chars;
69 	std::unique_ptr<unsigned char[]> styles;
70 	std::unique_ptr<XYPOSITION[]> positions;
71 	char bracePreviousStyles[2];
72 
73 	// Hotspot support
74 	Range hotspot;
75 
76 	// Wrapped line support
77 	int widthLine;
78 	int lines;
79 	XYPOSITION wrapIndent; // In pixels
80 
81 	explicit LineLayout(int maxLineLength_);
82 	// Deleted so LineLayout objects can not be copied.
83 	LineLayout(const LineLayout &) = delete;
84 	LineLayout(LineLayout &&) = delete;
85 	void operator=(const LineLayout &) = delete;
86 	void operator=(LineLayout &&) = delete;
87 	virtual ~LineLayout();
88 	void Resize(int maxLineLength_);
89 	void Free();
90 	void Invalidate(validLevel validity_);
91 	int LineStart(int line) const;
92 	enum class Scope { visibleOnly, includeEnd };
93 	int LineLastVisible(int line, Scope scope) const;
94 	Range SubLineRange(int subLine, Scope scope) const;
95 	bool InLine(int offset, int line) const;
96 	void SetLineStart(int line, int start);
97 	void SetBracesHighlight(Range rangeLine, const Sci::Position braces[],
98 		char bracesMatchStyle, int xHighlight, bool ignoreStyle);
99 	void RestoreBracesHighlight(Range rangeLine, const Sci::Position braces[], bool ignoreStyle);
100 	int FindBefore(XYPOSITION x, Range range) const;
101 	int FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const;
102 	Point PointFromPosition(int posInLine, int lineHeight, PointEnd pe) const;
103 	int EndLineStyle() const;
104 };
105 
106 /**
107  */
108 class LineLayoutCache {
109 	int level;
110 	std::vector<std::unique_ptr<LineLayout>>cache;
111 	bool allInvalidated;
112 	int styleClock;
113 	int useCount;
114 	void Allocate(size_t length_);
115 	void AllocateForLevel(Sci::Line linesOnScreen, Sci::Line linesInDoc);
116 public:
117 	LineLayoutCache();
118 	// Deleted so LineLayoutCache objects can not be copied.
119 	LineLayoutCache(const LineLayoutCache &) = delete;
120 	LineLayoutCache(LineLayoutCache &&) = delete;
121 	void operator=(const LineLayoutCache &) = delete;
122 	void operator=(LineLayoutCache &&) = delete;
123 	virtual ~LineLayoutCache();
124 	void Deallocate();
125 	enum {
126 		llcNone=SC_CACHE_NONE,
127 		llcCaret=SC_CACHE_CARET,
128 		llcPage=SC_CACHE_PAGE,
129 		llcDocument=SC_CACHE_DOCUMENT
130 	};
131 	void Invalidate(LineLayout::validLevel validity_);
132 	void SetLevel(int level_);
GetLevel()133 	int GetLevel() const { return level; }
134 	LineLayout *Retrieve(Sci::Line lineNumber, Sci::Line lineCaret, int maxChars, int styleClock_,
135 		Sci::Line linesOnScreen, Sci::Line linesInDoc);
136 	void Dispose(LineLayout *ll);
137 };
138 
139 class PositionCacheEntry {
140 	unsigned int styleNumber:8;
141 	unsigned int len:8;
142 	unsigned int clock:16;
143 	std::unique_ptr<XYPOSITION []> positions;
144 public:
145 	PositionCacheEntry();
146 	// Copy constructor not currently used, but needed for being element in std::vector.
147 	PositionCacheEntry(const PositionCacheEntry &);
148 	// PositionCacheEntry objects should not be moved but MSVC 2015 requires this.
149 	PositionCacheEntry(PositionCacheEntry &&) = default;
150 	void operator=(const PositionCacheEntry &) = delete;
151 	void operator=(PositionCacheEntry &&) = delete;
152 	~PositionCacheEntry();
153 	void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock_);
154 	void Clear();
155 	bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const;
156 	static unsigned int Hash(unsigned int styleNumber_, const char *s, unsigned int len_);
157 	bool NewerThan(const PositionCacheEntry &other) const;
158 	void ResetClock();
159 };
160 
161 class Representation {
162 public:
163 	std::string stringRep;
stringRep(value)164 	explicit Representation(const char *value="") : stringRep(value) {
165 	}
166 };
167 
168 typedef std::map<unsigned int, Representation> MapRepresentation;
169 
170 class SpecialRepresentations {
171 	MapRepresentation mapReprs;
172 	short startByteHasReprs[0x100];
173 public:
174 	SpecialRepresentations();
175 	void SetRepresentation(const char *charBytes, const char *value);
176 	void ClearRepresentation(const char *charBytes);
177 	const Representation *RepresentationFromCharacter(const char *charBytes, size_t len) const;
178 	bool Contains(const char *charBytes, size_t len) const;
179 	void Clear();
180 };
181 
182 struct TextSegment {
183 	int start;
184 	int length;
185 	const Representation *representation;
186 	TextSegment(int start_=0, int length_=0, const Representation *representation_=nullptr) noexcept :
startTextSegment187 		start(start_), length(length_), representation(representation_) {
188 	}
endTextSegment189 	int end() const noexcept {
190 		return start + length;
191 	}
192 };
193 
194 // Class to break a line of text into shorter runs at sensible places.
195 class BreakFinder {
196 	const LineLayout *ll;
197 	Range lineRange;
198 	Sci::Position posLineStart;
199 	int nextBreak;
200 	std::vector<int> selAndEdge;
201 	unsigned int saeCurrentPos;
202 	int saeNext;
203 	int subBreak;
204 	const Document *pdoc;
205 	EncodingFamily encodingFamily;
206 	const SpecialRepresentations *preprs;
207 	void Insert(Sci::Position val);
208 public:
209 	// If a whole run is longer than lengthStartSubdivision then subdivide
210 	// into smaller runs at spaces or punctuation.
211 	enum { lengthStartSubdivision = 300 };
212 	// Try to make each subdivided run lengthEachSubdivision or shorter.
213 	enum { lengthEachSubdivision = 100 };
214 	BreakFinder(const LineLayout *ll_, const Selection *psel, Range lineRange_, Sci::Position posLineStart_,
215 		int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw);
216 	// Deleted so BreakFinder objects can not be copied.
217 	BreakFinder(const BreakFinder &) = delete;
218 	BreakFinder(BreakFinder &&) = delete;
219 	void operator=(const BreakFinder &) = delete;
220 	void operator=(BreakFinder &&) = delete;
221 	~BreakFinder();
222 	TextSegment Next();
223 	bool More() const;
224 };
225 
226 class PositionCache {
227 	std::vector<PositionCacheEntry> pces;
228 	unsigned int clock;
229 	bool allClear;
230 public:
231 	PositionCache();
232 	// Deleted so PositionCache objects can not be copied.
233 	PositionCache(const PositionCache &) = delete;
234 	PositionCache(PositionCache &&) = delete;
235 	void operator=(const PositionCache &) = delete;
236 	void operator=(PositionCache &&) = delete;
237 	~PositionCache();
238 	void Clear();
239 	void SetSize(size_t size_);
GetSize()240 	size_t GetSize() const { return pces.size(); }
241 	void MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber,
242 		const char *s, unsigned int len, XYPOSITION *positions, const Document *pdoc);
243 };
244 
245 }
246 
247 #endif
248