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.
12 #include "SplitVector.h"
13 #include "Partitioning.h"
14 #include "RunStyles.h"
15 #include "ContractionState.h"
18 using namespace Scintilla
;
21 ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
25 ContractionState::~ContractionState() {
29 void ContractionState::EnsureData() {
31 visible
= new RunStyles();
32 expanded
= new RunStyles();
33 heights
= new RunStyles();
34 displayLines
= new Partitioning(4);
35 InsertLines(0, linesInDocument
);
39 void ContractionState::Clear() {
51 int ContractionState::LinesInDoc() const {
53 return linesInDocument
;
55 return displayLines
->Partitions() - 1;
59 int ContractionState::LinesDisplayed() const {
61 return linesInDocument
;
63 return displayLines
->PositionFromPartition(LinesInDoc());
67 int ContractionState::DisplayFromDoc(int lineDoc
) const {
71 if (lineDoc
> displayLines
->Partitions())
72 lineDoc
= displayLines
->Partitions();
73 return displayLines
->PositionFromPartition(lineDoc
);
77 int ContractionState::DocFromDisplay(int lineDisplay
) const {
81 if (lineDisplay
<= 0) {
84 if (lineDisplay
> LinesDisplayed()) {
85 return displayLines
->PartitionFromPosition(LinesDisplayed());
87 int lineDoc
= displayLines
->PartitionFromPosition(lineDisplay
);
88 PLATFORM_ASSERT(GetVisible(lineDoc
));
93 void ContractionState::InsertLine(int lineDoc
) {
97 visible
->InsertSpace(lineDoc
, 1);
98 visible
->SetValueAt(lineDoc
, 1);
99 expanded
->InsertSpace(lineDoc
, 1);
100 expanded
->SetValueAt(lineDoc
, 1);
101 heights
->InsertSpace(lineDoc
, 1);
102 heights
->SetValueAt(lineDoc
, 1);
103 int lineDisplay
= DisplayFromDoc(lineDoc
);
104 displayLines
->InsertPartition(lineDoc
, lineDisplay
);
105 displayLines
->InsertText(lineDoc
, 1);
109 void ContractionState::InsertLines(int lineDoc
, int lineCount
) {
110 for (int l
= 0; l
< lineCount
; l
++) {
111 InsertLine(lineDoc
+ l
);
116 void ContractionState::DeleteLine(int lineDoc
) {
120 if (GetVisible(lineDoc
)) {
121 displayLines
->InsertText(lineDoc
, -heights
->ValueAt(lineDoc
));
123 displayLines
->RemovePartition(lineDoc
);
124 visible
->DeleteRange(lineDoc
, 1);
125 expanded
->DeleteRange(lineDoc
, 1);
126 heights
->DeleteRange(lineDoc
, 1);
130 void ContractionState::DeleteLines(int lineDoc
, int lineCount
) {
131 for (int l
= 0; l
< lineCount
; l
++) {
137 bool ContractionState::GetVisible(int lineDoc
) const {
141 if (lineDoc
>= visible
->Length())
143 return visible
->ValueAt(lineDoc
) == 1;
147 bool ContractionState::SetVisible(int lineDocStart
, int lineDocEnd
, bool visible_
) {
148 if (OneToOne() && visible_
) {
154 if ((lineDocStart
<= lineDocEnd
) && (lineDocStart
>= 0) && (lineDocEnd
< LinesInDoc())) {
155 for (int line
= lineDocStart
; line
<= lineDocEnd
; line
++) {
156 if (GetVisible(line
) != visible_
) {
157 int difference
= visible_
? heights
->ValueAt(line
) : -heights
->ValueAt(line
);
158 visible
->SetValueAt(line
, visible_
? 1 : 0);
159 displayLines
->InsertText(line
, difference
);
171 bool ContractionState::HiddenLines() const {
175 return !visible
->AllSameAs(1);
179 bool ContractionState::GetExpanded(int lineDoc
) const {
184 return expanded
->ValueAt(lineDoc
) == 1;
188 bool ContractionState::SetExpanded(int lineDoc
, bool expanded_
) {
189 if (OneToOne() && expanded_
) {
193 if (expanded_
!= (expanded
->ValueAt(lineDoc
) == 1)) {
194 expanded
->SetValueAt(lineDoc
, expanded_
? 1 : 0);
204 int ContractionState::ContractedNext(int lineDocStart
) const {
209 if (!expanded
->ValueAt(lineDocStart
)) {
212 int lineDocNextChange
= expanded
->EndRun(lineDocStart
);
213 if (lineDocNextChange
< LinesInDoc())
214 return lineDocNextChange
;
221 int ContractionState::GetHeight(int lineDoc
) const {
225 return heights
->ValueAt(lineDoc
);
229 // Set the number of display lines needed for this line.
230 // Return true if this is a change.
231 bool ContractionState::SetHeight(int lineDoc
, int height
) {
232 if (OneToOne() && (height
== 1)) {
234 } else if (lineDoc
< LinesInDoc()) {
236 if (GetHeight(lineDoc
) != height
) {
237 if (GetVisible(lineDoc
)) {
238 displayLines
->InsertText(lineDoc
, height
- GetHeight(lineDoc
));
240 heights
->SetValueAt(lineDoc
, height
);
252 void ContractionState::ShowAll() {
253 int lines
= LinesInDoc();
255 linesInDocument
= lines
;
260 void ContractionState::Check() const {
261 #ifdef CHECK_CORRECTNESS
262 for (int vline
= 0; vline
< LinesDisplayed(); vline
++) {
263 const int lineDoc
= DocFromDisplay(vline
);
264 PLATFORM_ASSERT(GetVisible(lineDoc
));
266 for (int lineDoc
= 0; lineDoc
< LinesInDoc(); lineDoc
++) {
267 const int displayThis
= DisplayFromDoc(lineDoc
);
268 const int displayNext
= DisplayFromDoc(lineDoc
+ 1);
269 const int height
= displayNext
- displayThis
;
270 PLATFORM_ASSERT(height
>= 0);
271 if (GetVisible(lineDoc
)) {
272 PLATFORM_ASSERT(GetHeight(lineDoc
) == height
);
274 PLATFORM_ASSERT(0 == height
);