xref: /MusicPlayer2/scintilla/src/ContractionState.cxx (revision 8af74909132ed5e696cb05b6689ae4baf14c1c96)
1*8af74909SZhong Yang // Scintilla source code edit control
2*8af74909SZhong Yang /** @file ContractionState.cxx
3*8af74909SZhong Yang  ** Manages visibility of lines for folding and wrapping.
4*8af74909SZhong Yang  **/
5*8af74909SZhong Yang // Copyright 1998-2007 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 #include <cstddef>
9*8af74909SZhong Yang #include <cassert>
10*8af74909SZhong Yang #include <cstring>
11*8af74909SZhong Yang 
12*8af74909SZhong Yang #include <stdexcept>
13*8af74909SZhong Yang #include <string_view>
14*8af74909SZhong Yang #include <vector>
15*8af74909SZhong Yang #include <algorithm>
16*8af74909SZhong Yang #include <memory>
17*8af74909SZhong Yang 
18*8af74909SZhong Yang #include "Platform.h"
19*8af74909SZhong Yang 
20*8af74909SZhong Yang #include "Position.h"
21*8af74909SZhong Yang #include "UniqueString.h"
22*8af74909SZhong Yang #include "SplitVector.h"
23*8af74909SZhong Yang #include "Partitioning.h"
24*8af74909SZhong Yang #include "RunStyles.h"
25*8af74909SZhong Yang #include "SparseVector.h"
26*8af74909SZhong Yang #include "ContractionState.h"
27*8af74909SZhong Yang 
28*8af74909SZhong Yang using namespace Scintilla;
29*8af74909SZhong Yang 
30*8af74909SZhong Yang namespace {
31*8af74909SZhong Yang 
32*8af74909SZhong Yang template <typename LINE>
33*8af74909SZhong Yang class ContractionState final : public IContractionState {
34*8af74909SZhong Yang 	// These contain 1 element for every document line.
35*8af74909SZhong Yang 	std::unique_ptr<RunStyles<LINE, char>> visible;
36*8af74909SZhong Yang 	std::unique_ptr<RunStyles<LINE, char>> expanded;
37*8af74909SZhong Yang 	std::unique_ptr<RunStyles<LINE, int>> heights;
38*8af74909SZhong Yang 	std::unique_ptr<SparseVector<UniqueString>> foldDisplayTexts;
39*8af74909SZhong Yang 	std::unique_ptr<Partitioning<LINE>> displayLines;
40*8af74909SZhong Yang 	LINE linesInDocument;
41*8af74909SZhong Yang 
42*8af74909SZhong Yang 	void EnsureData();
43*8af74909SZhong Yang 
OneToOne() const44*8af74909SZhong Yang 	bool OneToOne() const noexcept {
45*8af74909SZhong Yang 		// True when each document line is exactly one display line so need for
46*8af74909SZhong Yang 		// complex data structures.
47*8af74909SZhong Yang 		return visible == nullptr;
48*8af74909SZhong Yang 	}
49*8af74909SZhong Yang 
50*8af74909SZhong Yang 	void InsertLine(Sci::Line lineDoc);
51*8af74909SZhong Yang 	void DeleteLine(Sci::Line lineDoc);
52*8af74909SZhong Yang 
53*8af74909SZhong Yang public:
54*8af74909SZhong Yang 	ContractionState() noexcept;
55*8af74909SZhong Yang 	// Deleted so ContractionState objects can not be copied.
56*8af74909SZhong Yang 	ContractionState(const ContractionState &) = delete;
57*8af74909SZhong Yang 	void operator=(const ContractionState &) = delete;
58*8af74909SZhong Yang 	ContractionState(ContractionState &&) = delete;
59*8af74909SZhong Yang 	void operator=(ContractionState &&) = delete;
60*8af74909SZhong Yang 	~ContractionState() override;
61*8af74909SZhong Yang 
62*8af74909SZhong Yang 	void Clear() noexcept override;
63*8af74909SZhong Yang 
64*8af74909SZhong Yang 	Sci::Line LinesInDoc() const noexcept override;
65*8af74909SZhong Yang 	Sci::Line LinesDisplayed() const noexcept override;
66*8af74909SZhong Yang 	Sci::Line DisplayFromDoc(Sci::Line lineDoc) const noexcept override;
67*8af74909SZhong Yang 	Sci::Line DisplayLastFromDoc(Sci::Line lineDoc) const noexcept override;
68*8af74909SZhong Yang 	Sci::Line DocFromDisplay(Sci::Line lineDisplay) const noexcept override;
69*8af74909SZhong Yang 
70*8af74909SZhong Yang 	void InsertLines(Sci::Line lineDoc, Sci::Line lineCount) override;
71*8af74909SZhong Yang 	void DeleteLines(Sci::Line lineDoc, Sci::Line lineCount) override;
72*8af74909SZhong Yang 
73*8af74909SZhong Yang 	bool GetVisible(Sci::Line lineDoc) const noexcept override;
74*8af74909SZhong Yang 	bool SetVisible(Sci::Line lineDocStart, Sci::Line lineDocEnd, bool isVisible) override;
75*8af74909SZhong Yang 	bool HiddenLines() const noexcept override;
76*8af74909SZhong Yang 
77*8af74909SZhong Yang 	const char *GetFoldDisplayText(Sci::Line lineDoc) const noexcept override;
78*8af74909SZhong Yang 	bool SetFoldDisplayText(Sci::Line lineDoc, const char *text) override;
79*8af74909SZhong Yang 
80*8af74909SZhong Yang 	bool GetExpanded(Sci::Line lineDoc) const noexcept override;
81*8af74909SZhong Yang 	bool SetExpanded(Sci::Line lineDoc, bool isExpanded) override;
82*8af74909SZhong Yang 	Sci::Line ContractedNext(Sci::Line lineDocStart) const noexcept override;
83*8af74909SZhong Yang 
84*8af74909SZhong Yang 	int GetHeight(Sci::Line lineDoc) const noexcept override;
85*8af74909SZhong Yang 	bool SetHeight(Sci::Line lineDoc, int height) override;
86*8af74909SZhong Yang 
87*8af74909SZhong Yang 	void ShowAll() noexcept override;
88*8af74909SZhong Yang 
89*8af74909SZhong Yang 	void Check() const noexcept;
90*8af74909SZhong Yang };
91*8af74909SZhong Yang 
92*8af74909SZhong Yang template <typename LINE>
ContractionState()93*8af74909SZhong Yang ContractionState<LINE>::ContractionState() noexcept : linesInDocument(1) {
94*8af74909SZhong Yang }
95*8af74909SZhong Yang 
96*8af74909SZhong Yang template <typename LINE>
~ContractionState()97*8af74909SZhong Yang ContractionState<LINE>::~ContractionState() {
98*8af74909SZhong Yang 	Clear();
99*8af74909SZhong Yang }
100*8af74909SZhong Yang 
101*8af74909SZhong Yang template <typename LINE>
EnsureData()102*8af74909SZhong Yang void ContractionState<LINE>::EnsureData() {
103*8af74909SZhong Yang 	if (OneToOne()) {
104*8af74909SZhong Yang 		visible = std::make_unique<RunStyles<LINE, char>>();
105*8af74909SZhong Yang 		expanded = std::make_unique<RunStyles<LINE, char>>();
106*8af74909SZhong Yang 		heights = std::make_unique<RunStyles<LINE, int>>();
107*8af74909SZhong Yang 		foldDisplayTexts = std::make_unique<SparseVector<UniqueString>>();
108*8af74909SZhong Yang 		displayLines = std::make_unique<Partitioning<LINE>>(4);
109*8af74909SZhong Yang 		InsertLines(0, linesInDocument);
110*8af74909SZhong Yang 	}
111*8af74909SZhong Yang }
112*8af74909SZhong Yang 
113*8af74909SZhong Yang template <typename LINE>
InsertLine(Sci::Line lineDoc)114*8af74909SZhong Yang void ContractionState<LINE>::InsertLine(Sci::Line lineDoc) {
115*8af74909SZhong Yang 	if (OneToOne()) {
116*8af74909SZhong Yang 		linesInDocument++;
117*8af74909SZhong Yang 	} else {
118*8af74909SZhong Yang 		const LINE lineDocCast = static_cast<LINE>(lineDoc);
119*8af74909SZhong Yang 		visible->InsertSpace(lineDocCast, 1);
120*8af74909SZhong Yang 		visible->SetValueAt(lineDocCast, 1);
121*8af74909SZhong Yang 		expanded->InsertSpace(lineDocCast, 1);
122*8af74909SZhong Yang 		expanded->SetValueAt(lineDocCast, 1);
123*8af74909SZhong Yang 		heights->InsertSpace(lineDocCast, 1);
124*8af74909SZhong Yang 		heights->SetValueAt(lineDocCast, 1);
125*8af74909SZhong Yang 		foldDisplayTexts->InsertSpace(lineDocCast, 1);
126*8af74909SZhong Yang 		foldDisplayTexts->SetValueAt(lineDocCast, nullptr);
127*8af74909SZhong Yang 		const Sci::Line lineDisplay = DisplayFromDoc(lineDoc);
128*8af74909SZhong Yang 		displayLines->InsertPartition(lineDocCast, static_cast<LINE>(lineDisplay));
129*8af74909SZhong Yang 		displayLines->InsertText(lineDocCast, 1);
130*8af74909SZhong Yang 	}
131*8af74909SZhong Yang }
132*8af74909SZhong Yang 
133*8af74909SZhong Yang template <typename LINE>
DeleteLine(Sci::Line lineDoc)134*8af74909SZhong Yang void ContractionState<LINE>::DeleteLine(Sci::Line lineDoc) {
135*8af74909SZhong Yang 	if (OneToOne()) {
136*8af74909SZhong Yang 		linesInDocument--;
137*8af74909SZhong Yang 	} else {
138*8af74909SZhong Yang 		const LINE lineDocCast = static_cast<LINE>(lineDoc);
139*8af74909SZhong Yang 		if (GetVisible(lineDoc)) {
140*8af74909SZhong Yang 			displayLines->InsertText(lineDocCast, -heights->ValueAt(lineDocCast));
141*8af74909SZhong Yang 		}
142*8af74909SZhong Yang 		displayLines->RemovePartition(lineDocCast);
143*8af74909SZhong Yang 		visible->DeleteRange(lineDocCast, 1);
144*8af74909SZhong Yang 		expanded->DeleteRange(lineDocCast, 1);
145*8af74909SZhong Yang 		heights->DeleteRange(lineDocCast, 1);
146*8af74909SZhong Yang 		foldDisplayTexts->DeletePosition(lineDocCast);
147*8af74909SZhong Yang 	}
148*8af74909SZhong Yang }
149*8af74909SZhong Yang 
150*8af74909SZhong Yang template <typename LINE>
Clear()151*8af74909SZhong Yang void ContractionState<LINE>::Clear() noexcept {
152*8af74909SZhong Yang 	visible.reset();
153*8af74909SZhong Yang 	expanded.reset();
154*8af74909SZhong Yang 	heights.reset();
155*8af74909SZhong Yang 	foldDisplayTexts.reset();
156*8af74909SZhong Yang 	displayLines.reset();
157*8af74909SZhong Yang 	linesInDocument = 1;
158*8af74909SZhong Yang }
159*8af74909SZhong Yang 
160*8af74909SZhong Yang template <typename LINE>
LinesInDoc() const161*8af74909SZhong Yang Sci::Line ContractionState<LINE>::LinesInDoc() const noexcept {
162*8af74909SZhong Yang 	if (OneToOne()) {
163*8af74909SZhong Yang 		return linesInDocument;
164*8af74909SZhong Yang 	} else {
165*8af74909SZhong Yang 		return displayLines->Partitions() - 1;
166*8af74909SZhong Yang 	}
167*8af74909SZhong Yang }
168*8af74909SZhong Yang 
169*8af74909SZhong Yang template <typename LINE>
LinesDisplayed() const170*8af74909SZhong Yang Sci::Line ContractionState<LINE>::LinesDisplayed() const noexcept {
171*8af74909SZhong Yang 	if (OneToOne()) {
172*8af74909SZhong Yang 		return linesInDocument;
173*8af74909SZhong Yang 	} else {
174*8af74909SZhong Yang 		return displayLines->PositionFromPartition(static_cast<LINE>(LinesInDoc()));
175*8af74909SZhong Yang 	}
176*8af74909SZhong Yang }
177*8af74909SZhong Yang 
178*8af74909SZhong Yang template <typename LINE>
DisplayFromDoc(Sci::Line lineDoc) const179*8af74909SZhong Yang Sci::Line ContractionState<LINE>::DisplayFromDoc(Sci::Line lineDoc) const noexcept {
180*8af74909SZhong Yang 	if (OneToOne()) {
181*8af74909SZhong Yang 		return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument;
182*8af74909SZhong Yang 	} else {
183*8af74909SZhong Yang 		if (lineDoc > displayLines->Partitions())
184*8af74909SZhong Yang 			lineDoc = displayLines->Partitions();
185*8af74909SZhong Yang 		return displayLines->PositionFromPartition(static_cast<LINE>(lineDoc));
186*8af74909SZhong Yang 	}
187*8af74909SZhong Yang }
188*8af74909SZhong Yang 
189*8af74909SZhong Yang template <typename LINE>
DisplayLastFromDoc(Sci::Line lineDoc) const190*8af74909SZhong Yang Sci::Line ContractionState<LINE>::DisplayLastFromDoc(Sci::Line lineDoc) const noexcept {
191*8af74909SZhong Yang 	return DisplayFromDoc(lineDoc) + GetHeight(lineDoc) - 1;
192*8af74909SZhong Yang }
193*8af74909SZhong Yang 
194*8af74909SZhong Yang template <typename LINE>
DocFromDisplay(Sci::Line lineDisplay) const195*8af74909SZhong Yang Sci::Line ContractionState<LINE>::DocFromDisplay(Sci::Line lineDisplay) const noexcept {
196*8af74909SZhong Yang 	if (OneToOne()) {
197*8af74909SZhong Yang 		return lineDisplay;
198*8af74909SZhong Yang 	} else {
199*8af74909SZhong Yang 		if (lineDisplay <= 0) {
200*8af74909SZhong Yang 			return 0;
201*8af74909SZhong Yang 		}
202*8af74909SZhong Yang 		if (lineDisplay > LinesDisplayed()) {
203*8af74909SZhong Yang 			return displayLines->PartitionFromPosition(static_cast<LINE>(LinesDisplayed()));
204*8af74909SZhong Yang 		}
205*8af74909SZhong Yang 		const Sci::Line lineDoc = displayLines->PartitionFromPosition(static_cast<LINE>(lineDisplay));
206*8af74909SZhong Yang 		PLATFORM_ASSERT(GetVisible(lineDoc));
207*8af74909SZhong Yang 		return lineDoc;
208*8af74909SZhong Yang 	}
209*8af74909SZhong Yang }
210*8af74909SZhong Yang 
211*8af74909SZhong Yang template <typename LINE>
InsertLines(Sci::Line lineDoc,Sci::Line lineCount)212*8af74909SZhong Yang void ContractionState<LINE>::InsertLines(Sci::Line lineDoc, Sci::Line lineCount) {
213*8af74909SZhong Yang 	if (OneToOne()) {
214*8af74909SZhong Yang 		linesInDocument += static_cast<LINE>(lineCount);
215*8af74909SZhong Yang 	} else {
216*8af74909SZhong Yang 		for (Sci::Line l = 0; l < lineCount; l++) {
217*8af74909SZhong Yang 			InsertLine(lineDoc + l);
218*8af74909SZhong Yang 		}
219*8af74909SZhong Yang 	}
220*8af74909SZhong Yang 	Check();
221*8af74909SZhong Yang }
222*8af74909SZhong Yang 
223*8af74909SZhong Yang template <typename LINE>
DeleteLines(Sci::Line lineDoc,Sci::Line lineCount)224*8af74909SZhong Yang void ContractionState<LINE>::DeleteLines(Sci::Line lineDoc, Sci::Line lineCount) {
225*8af74909SZhong Yang 	if (OneToOne()) {
226*8af74909SZhong Yang 		linesInDocument -= static_cast<LINE>(lineCount);
227*8af74909SZhong Yang 	} else {
228*8af74909SZhong Yang 		for (Sci::Line l = 0; l < lineCount; l++) {
229*8af74909SZhong Yang 			DeleteLine(lineDoc);
230*8af74909SZhong Yang 		}
231*8af74909SZhong Yang 	}
232*8af74909SZhong Yang 	Check();
233*8af74909SZhong Yang }
234*8af74909SZhong Yang 
235*8af74909SZhong Yang template <typename LINE>
GetVisible(Sci::Line lineDoc) const236*8af74909SZhong Yang bool ContractionState<LINE>::GetVisible(Sci::Line lineDoc) const noexcept {
237*8af74909SZhong Yang 	if (OneToOne()) {
238*8af74909SZhong Yang 		return true;
239*8af74909SZhong Yang 	} else {
240*8af74909SZhong Yang 		if (lineDoc >= visible->Length())
241*8af74909SZhong Yang 			return true;
242*8af74909SZhong Yang 		return visible->ValueAt(static_cast<LINE>(lineDoc)) == 1;
243*8af74909SZhong Yang 	}
244*8af74909SZhong Yang }
245*8af74909SZhong Yang 
246*8af74909SZhong Yang template <typename LINE>
SetVisible(Sci::Line lineDocStart,Sci::Line lineDocEnd,bool isVisible)247*8af74909SZhong Yang bool ContractionState<LINE>::SetVisible(Sci::Line lineDocStart, Sci::Line lineDocEnd, bool isVisible) {
248*8af74909SZhong Yang 	if (OneToOne() && isVisible) {
249*8af74909SZhong Yang 		return false;
250*8af74909SZhong Yang 	} else {
251*8af74909SZhong Yang 		EnsureData();
252*8af74909SZhong Yang 		Sci::Line delta = 0;
253*8af74909SZhong Yang 		Check();
254*8af74909SZhong Yang 		if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
255*8af74909SZhong Yang 			for (Sci::Line line = lineDocStart; line <= lineDocEnd; line++) {
256*8af74909SZhong Yang 				if (GetVisible(line) != isVisible) {
257*8af74909SZhong Yang 					const int heightLine = heights->ValueAt(static_cast<LINE>(line));
258*8af74909SZhong Yang 					const int difference = isVisible ? heightLine : -heightLine;
259*8af74909SZhong Yang 					visible->SetValueAt(static_cast<LINE>(line), isVisible ? 1 : 0);
260*8af74909SZhong Yang 					displayLines->InsertText(static_cast<LINE>(line), difference);
261*8af74909SZhong Yang 					delta += difference;
262*8af74909SZhong Yang 				}
263*8af74909SZhong Yang 			}
264*8af74909SZhong Yang 		} else {
265*8af74909SZhong Yang 			return false;
266*8af74909SZhong Yang 		}
267*8af74909SZhong Yang 		Check();
268*8af74909SZhong Yang 		return delta != 0;
269*8af74909SZhong Yang 	}
270*8af74909SZhong Yang }
271*8af74909SZhong Yang 
272*8af74909SZhong Yang template <typename LINE>
HiddenLines() const273*8af74909SZhong Yang bool ContractionState<LINE>::HiddenLines() const noexcept {
274*8af74909SZhong Yang 	if (OneToOne()) {
275*8af74909SZhong Yang 		return false;
276*8af74909SZhong Yang 	} else {
277*8af74909SZhong Yang 		return !visible->AllSameAs(1);
278*8af74909SZhong Yang 	}
279*8af74909SZhong Yang }
280*8af74909SZhong Yang 
281*8af74909SZhong Yang template <typename LINE>
GetFoldDisplayText(Sci::Line lineDoc) const282*8af74909SZhong Yang const char *ContractionState<LINE>::GetFoldDisplayText(Sci::Line lineDoc) const noexcept {
283*8af74909SZhong Yang 	Check();
284*8af74909SZhong Yang 	return foldDisplayTexts->ValueAt(lineDoc).get();
285*8af74909SZhong Yang }
286*8af74909SZhong Yang 
287*8af74909SZhong Yang template <typename LINE>
SetFoldDisplayText(Sci::Line lineDoc,const char * text)288*8af74909SZhong Yang bool ContractionState<LINE>::SetFoldDisplayText(Sci::Line lineDoc, const char *text) {
289*8af74909SZhong Yang 	EnsureData();
290*8af74909SZhong Yang 	const char *foldText = foldDisplayTexts->ValueAt(lineDoc).get();
291*8af74909SZhong Yang 	if (!foldText || !text || 0 != strcmp(text, foldText)) {
292*8af74909SZhong Yang 		UniqueString uns = IsNullOrEmpty(text) ? UniqueString() : UniqueStringCopy(text);
293*8af74909SZhong Yang 		foldDisplayTexts->SetValueAt(lineDoc, std::move(uns));
294*8af74909SZhong Yang 		Check();
295*8af74909SZhong Yang 		return true;
296*8af74909SZhong Yang 	} else {
297*8af74909SZhong Yang 		Check();
298*8af74909SZhong Yang 		return false;
299*8af74909SZhong Yang 	}
300*8af74909SZhong Yang }
301*8af74909SZhong Yang 
302*8af74909SZhong Yang template <typename LINE>
GetExpanded(Sci::Line lineDoc) const303*8af74909SZhong Yang bool ContractionState<LINE>::GetExpanded(Sci::Line lineDoc) const noexcept {
304*8af74909SZhong Yang 	if (OneToOne()) {
305*8af74909SZhong Yang 		return true;
306*8af74909SZhong Yang 	} else {
307*8af74909SZhong Yang 		Check();
308*8af74909SZhong Yang 		return expanded->ValueAt(static_cast<LINE>(lineDoc)) == 1;
309*8af74909SZhong Yang 	}
310*8af74909SZhong Yang }
311*8af74909SZhong Yang 
312*8af74909SZhong Yang template <typename LINE>
SetExpanded(Sci::Line lineDoc,bool isExpanded)313*8af74909SZhong Yang bool ContractionState<LINE>::SetExpanded(Sci::Line lineDoc, bool isExpanded) {
314*8af74909SZhong Yang 	if (OneToOne() && isExpanded) {
315*8af74909SZhong Yang 		return false;
316*8af74909SZhong Yang 	} else {
317*8af74909SZhong Yang 		EnsureData();
318*8af74909SZhong Yang 		if (isExpanded != (expanded->ValueAt(static_cast<LINE>(lineDoc)) == 1)) {
319*8af74909SZhong Yang 			expanded->SetValueAt(static_cast<LINE>(lineDoc), isExpanded ? 1 : 0);
320*8af74909SZhong Yang 			Check();
321*8af74909SZhong Yang 			return true;
322*8af74909SZhong Yang 		} else {
323*8af74909SZhong Yang 			Check();
324*8af74909SZhong Yang 			return false;
325*8af74909SZhong Yang 		}
326*8af74909SZhong Yang 	}
327*8af74909SZhong Yang }
328*8af74909SZhong Yang 
329*8af74909SZhong Yang template <typename LINE>
ContractedNext(Sci::Line lineDocStart) const330*8af74909SZhong Yang Sci::Line ContractionState<LINE>::ContractedNext(Sci::Line lineDocStart) const noexcept {
331*8af74909SZhong Yang 	if (OneToOne()) {
332*8af74909SZhong Yang 		return -1;
333*8af74909SZhong Yang 	} else {
334*8af74909SZhong Yang 		Check();
335*8af74909SZhong Yang 		if (!expanded->ValueAt(static_cast<LINE>(lineDocStart))) {
336*8af74909SZhong Yang 			return lineDocStart;
337*8af74909SZhong Yang 		} else {
338*8af74909SZhong Yang 			const Sci::Line lineDocNextChange = expanded->EndRun(static_cast<LINE>(lineDocStart));
339*8af74909SZhong Yang 			if (lineDocNextChange < LinesInDoc())
340*8af74909SZhong Yang 				return lineDocNextChange;
341*8af74909SZhong Yang 			else
342*8af74909SZhong Yang 				return -1;
343*8af74909SZhong Yang 		}
344*8af74909SZhong Yang 	}
345*8af74909SZhong Yang }
346*8af74909SZhong Yang 
347*8af74909SZhong Yang template <typename LINE>
GetHeight(Sci::Line lineDoc) const348*8af74909SZhong Yang int ContractionState<LINE>::GetHeight(Sci::Line lineDoc) const noexcept {
349*8af74909SZhong Yang 	if (OneToOne()) {
350*8af74909SZhong Yang 		return 1;
351*8af74909SZhong Yang 	} else {
352*8af74909SZhong Yang 		return heights->ValueAt(static_cast<LINE>(lineDoc));
353*8af74909SZhong Yang 	}
354*8af74909SZhong Yang }
355*8af74909SZhong Yang 
356*8af74909SZhong Yang // Set the number of display lines needed for this line.
357*8af74909SZhong Yang // Return true if this is a change.
358*8af74909SZhong Yang template <typename LINE>
SetHeight(Sci::Line lineDoc,int height)359*8af74909SZhong Yang bool ContractionState<LINE>::SetHeight(Sci::Line lineDoc, int height) {
360*8af74909SZhong Yang 	if (OneToOne() && (height == 1)) {
361*8af74909SZhong Yang 		return false;
362*8af74909SZhong Yang 	} else if (lineDoc < LinesInDoc()) {
363*8af74909SZhong Yang 		EnsureData();
364*8af74909SZhong Yang 		if (GetHeight(lineDoc) != height) {
365*8af74909SZhong Yang 			if (GetVisible(lineDoc)) {
366*8af74909SZhong Yang 				displayLines->InsertText(static_cast<LINE>(lineDoc), height - GetHeight(lineDoc));
367*8af74909SZhong Yang 			}
368*8af74909SZhong Yang 			heights->SetValueAt(static_cast<LINE>(lineDoc), height);
369*8af74909SZhong Yang 			Check();
370*8af74909SZhong Yang 			return true;
371*8af74909SZhong Yang 		} else {
372*8af74909SZhong Yang 			Check();
373*8af74909SZhong Yang 			return false;
374*8af74909SZhong Yang 		}
375*8af74909SZhong Yang 	} else {
376*8af74909SZhong Yang 		return false;
377*8af74909SZhong Yang 	}
378*8af74909SZhong Yang }
379*8af74909SZhong Yang 
380*8af74909SZhong Yang template <typename LINE>
ShowAll()381*8af74909SZhong Yang void ContractionState<LINE>::ShowAll() noexcept {
382*8af74909SZhong Yang 	const LINE lines = static_cast<LINE>(LinesInDoc());
383*8af74909SZhong Yang 	Clear();
384*8af74909SZhong Yang 	linesInDocument = lines;
385*8af74909SZhong Yang }
386*8af74909SZhong Yang 
387*8af74909SZhong Yang // Debugging checks
388*8af74909SZhong Yang 
389*8af74909SZhong Yang template <typename LINE>
Check() const390*8af74909SZhong Yang void ContractionState<LINE>::Check() const noexcept {
391*8af74909SZhong Yang #ifdef CHECK_CORRECTNESS
392*8af74909SZhong Yang 	for (Sci::Line vline = 0; vline < LinesDisplayed(); vline++) {
393*8af74909SZhong Yang 		const Sci::Line lineDoc = DocFromDisplay(vline);
394*8af74909SZhong Yang 		PLATFORM_ASSERT(GetVisible(lineDoc));
395*8af74909SZhong Yang 	}
396*8af74909SZhong Yang 	for (Sci::Line lineDoc = 0; lineDoc < LinesInDoc(); lineDoc++) {
397*8af74909SZhong Yang 		const Sci::Line displayThis = DisplayFromDoc(lineDoc);
398*8af74909SZhong Yang 		const Sci::Line displayNext = DisplayFromDoc(lineDoc + 1);
399*8af74909SZhong Yang 		const Sci::Line height = displayNext - displayThis;
400*8af74909SZhong Yang 		PLATFORM_ASSERT(height >= 0);
401*8af74909SZhong Yang 		if (GetVisible(lineDoc)) {
402*8af74909SZhong Yang 			PLATFORM_ASSERT(GetHeight(lineDoc) == height);
403*8af74909SZhong Yang 		} else {
404*8af74909SZhong Yang 			PLATFORM_ASSERT(0 == height);
405*8af74909SZhong Yang 		}
406*8af74909SZhong Yang 	}
407*8af74909SZhong Yang #endif
408*8af74909SZhong Yang }
409*8af74909SZhong Yang 
410*8af74909SZhong Yang }
411*8af74909SZhong Yang 
412*8af74909SZhong Yang namespace Scintilla {
413*8af74909SZhong Yang 
ContractionStateCreate(bool largeDocument)414*8af74909SZhong Yang std::unique_ptr<IContractionState> ContractionStateCreate(bool largeDocument) {
415*8af74909SZhong Yang 	if (largeDocument)
416*8af74909SZhong Yang 		return std::make_unique<ContractionState<Sci::Line>>();
417*8af74909SZhong Yang 	else
418*8af74909SZhong Yang 		return std::make_unique<ContractionState<int>>();
419*8af74909SZhong Yang }
420*8af74909SZhong Yang 
421*8af74909SZhong Yang }
422