]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/ContractionState.cxx
08de5cf1f7aa9ce89f3417d65b6bbbf921d7960c
[wxWidgets.git] / src / stc / scintilla / src / ContractionState.cxx
1 // Scintilla source code edit control
2 /** @file ContractionState.cxx
3 ** Manages visibility of lines for folding and wrapping.
4 **/
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.
7
8 #include <string.h>
9
10 #include "Platform.h"
11
12 #include "SplitVector.h"
13 #include "Partitioning.h"
14 #include "RunStyles.h"
15 #include "ContractionState.h"
16
17 #ifdef SCI_NAMESPACE
18 using namespace Scintilla;
19 #endif
20
21 ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
22 //InsertLine(0);
23 }
24
25 ContractionState::~ContractionState() {
26 Clear();
27 }
28
29 void ContractionState::EnsureData() {
30 if (OneToOne()) {
31 visible = new RunStyles();
32 expanded = new RunStyles();
33 heights = new RunStyles();
34 displayLines = new Partitioning(4);
35 InsertLines(0, linesInDocument);
36 }
37 }
38
39 void ContractionState::Clear() {
40 delete visible;
41 visible = 0;
42 delete expanded;
43 expanded = 0;
44 delete heights;
45 heights = 0;
46 delete displayLines;
47 displayLines = 0;
48 linesInDocument = 1;
49 }
50
51 int ContractionState::LinesInDoc() const {
52 if (OneToOne()) {
53 return linesInDocument;
54 } else {
55 return displayLines->Partitions() - 1;
56 }
57 }
58
59 int ContractionState::LinesDisplayed() const {
60 if (OneToOne()) {
61 return linesInDocument;
62 } else {
63 return displayLines->PositionFromPartition(LinesInDoc());
64 }
65 }
66
67 int ContractionState::DisplayFromDoc(int lineDoc) const {
68 if (OneToOne()) {
69 return lineDoc;
70 } else {
71 if (lineDoc > displayLines->Partitions())
72 lineDoc = displayLines->Partitions();
73 return displayLines->PositionFromPartition(lineDoc);
74 }
75 }
76
77 int ContractionState::DocFromDisplay(int lineDisplay) const {
78 if (OneToOne()) {
79 return lineDisplay;
80 } else {
81 if (lineDisplay <= 0) {
82 return 0;
83 }
84 if (lineDisplay > LinesDisplayed()) {
85 return displayLines->PartitionFromPosition(LinesDisplayed());
86 }
87 int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
88 PLATFORM_ASSERT(GetVisible(lineDoc));
89 return lineDoc;
90 }
91 }
92
93 void ContractionState::InsertLine(int lineDoc) {
94 if (OneToOne()) {
95 linesInDocument++;
96 } else {
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);
106 }
107 }
108
109 void ContractionState::InsertLines(int lineDoc, int lineCount) {
110 for (int l = 0; l < lineCount; l++) {
111 InsertLine(lineDoc + l);
112 }
113 Check();
114 }
115
116 void ContractionState::DeleteLine(int lineDoc) {
117 if (OneToOne()) {
118 linesInDocument--;
119 } else {
120 if (GetVisible(lineDoc)) {
121 displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
122 }
123 displayLines->RemovePartition(lineDoc);
124 visible->DeleteRange(lineDoc, 1);
125 expanded->DeleteRange(lineDoc, 1);
126 heights->DeleteRange(lineDoc, 1);
127 }
128 }
129
130 void ContractionState::DeleteLines(int lineDoc, int lineCount) {
131 for (int l = 0; l < lineCount; l++) {
132 DeleteLine(lineDoc);
133 }
134 Check();
135 }
136
137 bool ContractionState::GetVisible(int lineDoc) const {
138 if (OneToOne()) {
139 return true;
140 } else {
141 if (lineDoc >= visible->Length())
142 return true;
143 return visible->ValueAt(lineDoc) == 1;
144 }
145 }
146
147 bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
148 if (OneToOne() && visible_) {
149 return false;
150 } else {
151 EnsureData();
152 int delta = 0;
153 Check();
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);
160 delta += difference;
161 }
162 }
163 } else {
164 return false;
165 }
166 Check();
167 return delta != 0;
168 }
169 }
170
171 bool ContractionState::GetExpanded(int lineDoc) const {
172 if (OneToOne()) {
173 return true;
174 } else {
175 Check();
176 return expanded->ValueAt(lineDoc) == 1;
177 }
178 }
179
180 bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
181 if (OneToOne() && expanded_) {
182 return false;
183 } else {
184 EnsureData();
185 if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
186 expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
187 Check();
188 return true;
189 } else {
190 Check();
191 return false;
192 }
193 }
194 }
195
196 int ContractionState::GetHeight(int lineDoc) const {
197 if (OneToOne()) {
198 return 1;
199 } else {
200 return heights->ValueAt(lineDoc);
201 }
202 }
203
204 // Set the number of display lines needed for this line.
205 // Return true if this is a change.
206 bool ContractionState::SetHeight(int lineDoc, int height) {
207 if (OneToOne() && (height == 1)) {
208 return false;
209 } else {
210 EnsureData();
211 if (GetHeight(lineDoc) != height) {
212 if (GetVisible(lineDoc)) {
213 displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
214 }
215 heights->SetValueAt(lineDoc, height);
216 Check();
217 return true;
218 } else {
219 Check();
220 return false;
221 }
222 }
223 }
224
225 void ContractionState::ShowAll() {
226 int lines = LinesInDoc();
227 Clear();
228 linesInDocument = lines;
229 }
230
231 // Debugging checks
232
233 void ContractionState::Check() const {
234 #ifdef CHECK_CORRECTNESS
235 for (int vline = 0;vline < LinesDisplayed(); vline++) {
236 const int lineDoc = DocFromDisplay(vline);
237 PLATFORM_ASSERT(GetVisible(lineDoc));
238 }
239 for (int lineDoc = 0;lineDoc < LinesInDoc(); lineDoc++) {
240 const int displayThis = DisplayFromDoc(lineDoc);
241 const int displayNext = DisplayFromDoc(lineDoc + 1);
242 const int height = displayNext - displayThis;
243 PLATFORM_ASSERT(height >= 0);
244 if (GetVisible(lineDoc)) {
245 PLATFORM_ASSERT(GetHeight(lineDoc) == height);
246 } else {
247 PLATFORM_ASSERT(0 == height);
248 }
249 }
250 #endif
251 }