1 // Scintilla source code edit control
2 /** @file ContractionState.cxx
3 ** Manages visibility of lines for folding and wrapping.
5 // Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
17 #include "SplitVector.h"
18 #include "Partitioning.h"
19 #include "RunStyles.h"
20 #include "SparseVector.h"
21 #include "ContractionState.h"
24 using namespace Scintilla
;
27 ContractionState::ContractionState() : visible(0), expanded(0), heights(0), foldDisplayTexts(0), displayLines(0), linesInDocument(1) {
31 ContractionState::~ContractionState() {
35 void ContractionState::EnsureData() {
37 visible
= new RunStyles();
38 expanded
= new RunStyles();
39 heights
= new RunStyles();
40 foldDisplayTexts
= new SparseVector
<const char *>();
41 displayLines
= new Partitioning(4);
42 InsertLines(0, linesInDocument
);
46 void ContractionState::Clear() {
53 delete foldDisplayTexts
;
60 int ContractionState::LinesInDoc() const {
62 return linesInDocument
;
64 return displayLines
->Partitions() - 1;
68 int ContractionState::LinesDisplayed() const {
70 return linesInDocument
;
72 return displayLines
->PositionFromPartition(LinesInDoc());
76 int ContractionState::DisplayFromDoc(int lineDoc
) const {
78 return (lineDoc
<= linesInDocument
) ? lineDoc
: linesInDocument
;
80 if (lineDoc
> displayLines
->Partitions())
81 lineDoc
= displayLines
->Partitions();
82 return displayLines
->PositionFromPartition(lineDoc
);
86 int ContractionState::DisplayLastFromDoc(int lineDoc
) const {
87 return DisplayFromDoc(lineDoc
) + GetHeight(lineDoc
) - 1;
90 int ContractionState::DocFromDisplay(int lineDisplay
) const {
94 if (lineDisplay
<= 0) {
97 if (lineDisplay
> LinesDisplayed()) {
98 return displayLines
->PartitionFromPosition(LinesDisplayed());
100 int lineDoc
= displayLines
->PartitionFromPosition(lineDisplay
);
101 PLATFORM_ASSERT(GetVisible(lineDoc
));
106 void ContractionState::InsertLine(int lineDoc
) {
110 visible
->InsertSpace(lineDoc
, 1);
111 visible
->SetValueAt(lineDoc
, 1);
112 expanded
->InsertSpace(lineDoc
, 1);
113 expanded
->SetValueAt(lineDoc
, 1);
114 heights
->InsertSpace(lineDoc
, 1);
115 heights
->SetValueAt(lineDoc
, 1);
116 foldDisplayTexts
->InsertSpace(lineDoc
, 1);
117 foldDisplayTexts
->SetValueAt(lineDoc
, NULL
);
118 int lineDisplay
= DisplayFromDoc(lineDoc
);
119 displayLines
->InsertPartition(lineDoc
, lineDisplay
);
120 displayLines
->InsertText(lineDoc
, 1);
124 void ContractionState::InsertLines(int lineDoc
, int lineCount
) {
125 for (int l
= 0; l
< lineCount
; l
++) {
126 InsertLine(lineDoc
+ l
);
131 void ContractionState::DeleteLine(int lineDoc
) {
135 if (GetVisible(lineDoc
)) {
136 displayLines
->InsertText(lineDoc
, -heights
->ValueAt(lineDoc
));
138 displayLines
->RemovePartition(lineDoc
);
139 visible
->DeleteRange(lineDoc
, 1);
140 expanded
->DeleteRange(lineDoc
, 1);
141 heights
->DeleteRange(lineDoc
, 1);
142 foldDisplayTexts
->DeletePosition(lineDoc
);
146 void ContractionState::DeleteLines(int lineDoc
, int lineCount
) {
147 for (int l
= 0; l
< lineCount
; l
++) {
153 bool ContractionState::GetVisible(int lineDoc
) const {
157 if (lineDoc
>= visible
->Length())
159 return visible
->ValueAt(lineDoc
) == 1;
163 bool ContractionState::SetVisible(int lineDocStart
, int lineDocEnd
, bool isVisible
) {
164 if (OneToOne() && isVisible
) {
170 if ((lineDocStart
<= lineDocEnd
) && (lineDocStart
>= 0) && (lineDocEnd
< LinesInDoc())) {
171 for (int line
= lineDocStart
; line
<= lineDocEnd
; line
++) {
172 if (GetVisible(line
) != isVisible
) {
173 int difference
= isVisible
? heights
->ValueAt(line
) : -heights
->ValueAt(line
);
174 visible
->SetValueAt(line
, isVisible
? 1 : 0);
175 displayLines
->InsertText(line
, difference
);
187 bool ContractionState::HiddenLines() const {
191 return !visible
->AllSameAs(1);
195 const char *ContractionState::GetFoldDisplayText(int lineDoc
) const {
197 return foldDisplayTexts
->ValueAt(lineDoc
);
200 bool ContractionState::SetFoldDisplayText(int lineDoc
, const char *text
) {
202 const char *foldText
= foldDisplayTexts
->ValueAt(lineDoc
);
203 if (!foldText
|| 0 != strcmp(text
, foldText
)) {
204 foldDisplayTexts
->SetValueAt(lineDoc
, text
);
213 bool ContractionState::GetExpanded(int lineDoc
) const {
218 return expanded
->ValueAt(lineDoc
) == 1;
222 bool ContractionState::SetExpanded(int lineDoc
, bool isExpanded
) {
223 if (OneToOne() && isExpanded
) {
227 if (isExpanded
!= (expanded
->ValueAt(lineDoc
) == 1)) {
228 expanded
->SetValueAt(lineDoc
, isExpanded
? 1 : 0);
238 bool ContractionState::GetFoldDisplayTextShown(int lineDoc
) const {
239 return !GetExpanded(lineDoc
) && GetFoldDisplayText(lineDoc
);
242 int ContractionState::ContractedNext(int lineDocStart
) const {
247 if (!expanded
->ValueAt(lineDocStart
)) {
250 int lineDocNextChange
= expanded
->EndRun(lineDocStart
);
251 if (lineDocNextChange
< LinesInDoc())
252 return lineDocNextChange
;
259 int ContractionState::GetHeight(int lineDoc
) const {
263 return heights
->ValueAt(lineDoc
);
267 // Set the number of display lines needed for this line.
268 // Return true if this is a change.
269 bool ContractionState::SetHeight(int lineDoc
, int height
) {
270 if (OneToOne() && (height
== 1)) {
272 } else if (lineDoc
< LinesInDoc()) {
274 if (GetHeight(lineDoc
) != height
) {
275 if (GetVisible(lineDoc
)) {
276 displayLines
->InsertText(lineDoc
, height
- GetHeight(lineDoc
));
278 heights
->SetValueAt(lineDoc
, height
);
290 void ContractionState::ShowAll() {
291 int lines
= LinesInDoc();
293 linesInDocument
= lines
;
298 void ContractionState::Check() const {
299 #ifdef CHECK_CORRECTNESS
300 for (int vline
= 0; vline
< LinesDisplayed(); vline
++) {
301 const int lineDoc
= DocFromDisplay(vline
);
302 PLATFORM_ASSERT(GetVisible(lineDoc
));
304 for (int lineDoc
= 0; lineDoc
< LinesInDoc(); lineDoc
++) {
305 const int displayThis
= DisplayFromDoc(lineDoc
);
306 const int displayNext
= DisplayFromDoc(lineDoc
+ 1);
307 const int height
= displayNext
- displayThis
;
308 PLATFORM_ASSERT(height
>= 0);
309 if (GetVisible(lineDoc
)) {
310 PLATFORM_ASSERT(GetHeight(lineDoc
) == height
);
312 PLATFORM_ASSERT(0 == height
);