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