1 // Scintilla source code edit control
\r
2 /** @file ContractionState.cxx
\r
3 ** Manages visibility of lines for folding and wrapping.
\r
5 // Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
\r
6 // The License.txt file describes the conditions under which this software may be distributed.
\r
10 #include "Platform.h"
\r
12 #include "SplitVector.h"
\r
13 #include "Partitioning.h"
\r
14 #include "RunStyles.h"
\r
15 #include "ContractionState.h"
\r
17 #ifdef SCI_NAMESPACE
\r
18 using namespace Scintilla;
\r
21 ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
\r
25 ContractionState::~ContractionState() {
\r
29 void ContractionState::EnsureData() {
\r
31 visible = new RunStyles();
\r
32 expanded = new RunStyles();
\r
33 heights = new RunStyles();
\r
34 displayLines = new Partitioning(4);
\r
35 InsertLines(0, linesInDocument);
\r
39 void ContractionState::Clear() {
\r
46 delete displayLines;
\r
48 linesInDocument = 1;
\r
51 int ContractionState::LinesInDoc() const {
\r
53 return linesInDocument;
\r
55 return displayLines->Partitions() - 1;
\r
59 int ContractionState::LinesDisplayed() const {
\r
61 return linesInDocument;
\r
63 return displayLines->PositionFromPartition(LinesInDoc());
\r
67 int ContractionState::DisplayFromDoc(int lineDoc) const {
\r
71 if (lineDoc > displayLines->Partitions())
\r
72 lineDoc = displayLines->Partitions();
\r
73 return displayLines->PositionFromPartition(lineDoc);
\r
77 int ContractionState::DocFromDisplay(int lineDisplay) const {
\r
81 if (lineDisplay <= 0) {
\r
84 if (lineDisplay > LinesDisplayed()) {
\r
85 return displayLines->PartitionFromPosition(LinesDisplayed());
\r
87 int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
\r
88 PLATFORM_ASSERT(GetVisible(lineDoc));
\r
93 void ContractionState::InsertLine(int lineDoc) {
\r
97 visible->InsertSpace(lineDoc, 1);
\r
98 visible->SetValueAt(lineDoc, 1);
\r
99 expanded->InsertSpace(lineDoc, 1);
\r
100 expanded->SetValueAt(lineDoc, 1);
\r
101 heights->InsertSpace(lineDoc, 1);
\r
102 heights->SetValueAt(lineDoc, 1);
\r
103 int lineDisplay = DisplayFromDoc(lineDoc);
\r
104 displayLines->InsertPartition(lineDoc, lineDisplay);
\r
105 displayLines->InsertText(lineDoc, 1);
\r
109 void ContractionState::InsertLines(int lineDoc, int lineCount) {
\r
110 for (int l = 0; l < lineCount; l++) {
\r
111 InsertLine(lineDoc + l);
\r
116 void ContractionState::DeleteLine(int lineDoc) {
\r
120 if (GetVisible(lineDoc)) {
\r
121 displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
\r
123 displayLines->RemovePartition(lineDoc);
\r
124 visible->DeleteRange(lineDoc, 1);
\r
125 expanded->DeleteRange(lineDoc, 1);
\r
126 heights->DeleteRange(lineDoc, 1);
\r
130 void ContractionState::DeleteLines(int lineDoc, int lineCount) {
\r
131 for (int l = 0; l < lineCount; l++) {
\r
132 DeleteLine(lineDoc);
\r
137 bool ContractionState::GetVisible(int lineDoc) const {
\r
141 if (lineDoc >= visible->Length())
\r
143 return visible->ValueAt(lineDoc) == 1;
\r
147 bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
\r
148 if (OneToOne() && visible_) {
\r
154 if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
\r
155 for (int line = lineDocStart; line <= lineDocEnd; line++) {
\r
156 if (GetVisible(line) != visible_) {
\r
157 int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
\r
158 visible->SetValueAt(line, visible_ ? 1 : 0);
\r
159 displayLines->InsertText(line, difference);
\r
160 delta += difference;
\r
171 bool ContractionState::GetExpanded(int lineDoc) const {
\r
176 return expanded->ValueAt(lineDoc) == 1;
\r
180 bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
\r
181 if (OneToOne() && expanded_) {
\r
185 if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
\r
186 expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
\r
196 int ContractionState::GetHeight(int lineDoc) const {
\r
200 return heights->ValueAt(lineDoc);
\r
204 // Set the number of display lines needed for this line.
\r
205 // Return true if this is a change.
\r
206 bool ContractionState::SetHeight(int lineDoc, int height) {
\r
207 if (OneToOne() && (height == 1)) {
\r
211 if (GetHeight(lineDoc) != height) {
\r
212 if (GetVisible(lineDoc)) {
\r
213 displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
\r
215 heights->SetValueAt(lineDoc, height);
\r
225 void ContractionState::ShowAll() {
\r
226 int lines = LinesInDoc();
\r
228 linesInDocument = lines;
\r
231 // Debugging checks
\r
233 void ContractionState::Check() const {
\r
234 #ifdef CHECK_CORRECTNESS
\r
235 for (int vline = 0;vline < LinesDisplayed(); vline++) {
\r
236 const int lineDoc = DocFromDisplay(vline);
\r
237 PLATFORM_ASSERT(GetVisible(lineDoc));
\r
239 for (int lineDoc = 0;lineDoc < LinesInDoc(); lineDoc++) {
\r
240 const int displayThis = DisplayFromDoc(lineDoc);
\r
241 const int displayNext = DisplayFromDoc(lineDoc + 1);
\r
242 const int height = displayNext - displayThis;
\r
243 PLATFORM_ASSERT(height >= 0);
\r
244 if (GetVisible(lineDoc)) {
\r
245 PLATFORM_ASSERT(GetHeight(lineDoc) == height);
\r
247 PLATFORM_ASSERT(0 == height);
\r