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.
14 #include "SplitVector.h"
15 #include "Partitioning.h"
16 #include "RunStyles.h"
17 #include "ContractionState.h"
20 using namespace Scintilla
;
23 ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
27 ContractionState::~ContractionState() {
31 void ContractionState::EnsureData() {
33 visible
= new RunStyles();
34 expanded
= new RunStyles();
35 heights
= new RunStyles();
36 displayLines
= new Partitioning(4);
37 InsertLines(0, linesInDocument
);
41 void ContractionState::Clear() {
53 int ContractionState::LinesInDoc() const {
55 return linesInDocument
;
57 return displayLines
->Partitions() - 1;
61 int ContractionState::LinesDisplayed() const {
63 return linesInDocument
;
65 return displayLines
->PositionFromPartition(LinesInDoc());
69 int ContractionState::DisplayFromDoc(int lineDoc
) const {
71 return (lineDoc
<= linesInDocument
) ? lineDoc
: linesInDocument
;
73 if (lineDoc
> displayLines
->Partitions())
74 lineDoc
= displayLines
->Partitions();
75 return displayLines
->PositionFromPartition(lineDoc
);
79 int ContractionState::DisplayLastFromDoc(int lineDoc
) const {
80 return DisplayFromDoc(lineDoc
) + GetHeight(lineDoc
) - 1;
83 int ContractionState::DocFromDisplay(int lineDisplay
) const {
87 if (lineDisplay
<= 0) {
90 if (lineDisplay
> LinesDisplayed()) {
91 return displayLines
->PartitionFromPosition(LinesDisplayed());
93 int lineDoc
= displayLines
->PartitionFromPosition(lineDisplay
);
94 PLATFORM_ASSERT(GetVisible(lineDoc
));
99 void ContractionState::InsertLine(int lineDoc
) {
103 visible
->InsertSpace(lineDoc
, 1);
104 visible
->SetValueAt(lineDoc
, 1);
105 expanded
->InsertSpace(lineDoc
, 1);
106 expanded
->SetValueAt(lineDoc
, 1);
107 heights
->InsertSpace(lineDoc
, 1);
108 heights
->SetValueAt(lineDoc
, 1);
109 int lineDisplay
= DisplayFromDoc(lineDoc
);
110 displayLines
->InsertPartition(lineDoc
, lineDisplay
);
111 displayLines
->InsertText(lineDoc
, 1);
115 void ContractionState::InsertLines(int lineDoc
, int lineCount
) {
116 for (int l
= 0; l
< lineCount
; l
++) {
117 InsertLine(lineDoc
+ l
);
122 void ContractionState::DeleteLine(int lineDoc
) {
126 if (GetVisible(lineDoc
)) {
127 displayLines
->InsertText(lineDoc
, -heights
->ValueAt(lineDoc
));
129 displayLines
->RemovePartition(lineDoc
);
130 visible
->DeleteRange(lineDoc
, 1);
131 expanded
->DeleteRange(lineDoc
, 1);
132 heights
->DeleteRange(lineDoc
, 1);
136 void ContractionState::DeleteLines(int lineDoc
, int lineCount
) {
137 for (int l
= 0; l
< lineCount
; l
++) {
143 bool ContractionState::GetVisible(int lineDoc
) const {
147 if (lineDoc
>= visible
->Length())
149 return visible
->ValueAt(lineDoc
) == 1;
153 bool ContractionState::SetVisible(int lineDocStart
, int lineDocEnd
, bool isVisible
) {
154 if (OneToOne() && isVisible
) {
160 if ((lineDocStart
<= lineDocEnd
) && (lineDocStart
>= 0) && (lineDocEnd
< LinesInDoc())) {
161 for (int line
= lineDocStart
; line
<= lineDocEnd
; line
++) {
162 if (GetVisible(line
) != isVisible
) {
163 int difference
= isVisible
? heights
->ValueAt(line
) : -heights
->ValueAt(line
);
164 visible
->SetValueAt(line
, isVisible
? 1 : 0);
165 displayLines
->InsertText(line
, difference
);
177 bool ContractionState::HiddenLines() const {
181 return !visible
->AllSameAs(1);
185 bool ContractionState::GetExpanded(int lineDoc
) const {
190 return expanded
->ValueAt(lineDoc
) == 1;
194 bool ContractionState::SetExpanded(int lineDoc
, bool isExpanded
) {
195 if (OneToOne() && isExpanded
) {
199 if (isExpanded
!= (expanded
->ValueAt(lineDoc
) == 1)) {
200 expanded
->SetValueAt(lineDoc
, isExpanded
? 1 : 0);
210 int ContractionState::ContractedNext(int lineDocStart
) const {
215 if (!expanded
->ValueAt(lineDocStart
)) {
218 int lineDocNextChange
= expanded
->EndRun(lineDocStart
);
219 if (lineDocNextChange
< LinesInDoc())
220 return lineDocNextChange
;
227 int ContractionState::GetHeight(int lineDoc
) const {
231 return heights
->ValueAt(lineDoc
);
235 // Set the number of display lines needed for this line.
236 // Return true if this is a change.
237 bool ContractionState::SetHeight(int lineDoc
, int height
) {
238 if (OneToOne() && (height
== 1)) {
240 } else if (lineDoc
< LinesInDoc()) {
242 if (GetHeight(lineDoc
) != height
) {
243 if (GetVisible(lineDoc
)) {
244 displayLines
->InsertText(lineDoc
, height
- GetHeight(lineDoc
));
246 heights
->SetValueAt(lineDoc
, height
);
258 void ContractionState::ShowAll() {
259 int lines
= LinesInDoc();
261 linesInDocument
= lines
;
266 void ContractionState::Check() const {
267 #ifdef CHECK_CORRECTNESS
268 for (int vline
= 0; vline
< LinesDisplayed(); vline
++) {
269 const int lineDoc
= DocFromDisplay(vline
);
270 PLATFORM_ASSERT(GetVisible(lineDoc
));
272 for (int lineDoc
= 0; lineDoc
< LinesInDoc(); lineDoc
++) {
273 const int displayThis
= DisplayFromDoc(lineDoc
);
274 const int displayNext
= DisplayFromDoc(lineDoc
+ 1);
275 const int height
= displayNext
- displayThis
;
276 PLATFORM_ASSERT(height
>= 0);
277 if (GetVisible(lineDoc
)) {
278 PLATFORM_ASSERT(GetHeight(lineDoc
) == height
);
280 PLATFORM_ASSERT(0 == height
);