]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/ContractionState.cxx
8833b07bc0e7c72a97c042737b005c4cb56c80ff
[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.
4 **/
5 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
7
8 #include "Platform.h"
9
10 #include "ContractionState.h"
11
12 OneLine::OneLine() {
13 displayLine = 0;
14 //docLine = 0;
15 visible = true;
16 height = 1;
17 expanded = true;
18 }
19
20 ContractionState::ContractionState() {
21 lines = 0;
22 size = 0;
23 linesInDoc = 1;
24 linesInDisplay = 1;
25 valid = false;
26 docLines = 0;
27 sizeDocLines = 0;
28 }
29
30 ContractionState::~ContractionState() {
31 Clear();
32 }
33
34 void ContractionState::MakeValid() const {
35 if (!valid) {
36 // Could be cleverer by keeping the index of the last still valid entry
37 // rather than invalidating all.
38 linesInDisplay = 0;
39 for (int lineInDoc=0; lineInDoc<linesInDoc; lineInDoc++) {
40 lines[lineInDoc].displayLine = linesInDisplay;
41 if (lines[lineInDoc].visible) {
42 linesInDisplay += lines[lineInDoc].height;
43 }
44 }
45 if (sizeDocLines < linesInDisplay) {
46 delete []docLines;
47 int *docLinesNew = new int[linesInDisplay + growSize];
48 if (!docLinesNew) {
49 docLines = 0;
50 sizeDocLines = 0;
51 return;
52 }
53 docLines = docLinesNew;
54 sizeDocLines = linesInDisplay + growSize;
55 }
56
57 int lineInDisplay=0;
58 for (int line=0; line<linesInDoc; line++) {
59 if (lines[line].visible) {
60 for (int linePiece=0; linePiece<lines[line].height; linePiece++) {
61 docLines[lineInDisplay] = line;
62 lineInDisplay++;
63 }
64 }
65 }
66 valid = true;
67 }
68 }
69
70 void ContractionState::Clear() {
71 delete []lines;
72 lines = 0;
73 size = 0;
74 linesInDoc = 1;
75 linesInDisplay = 1;
76 delete []docLines;
77 docLines = 0;
78 sizeDocLines = 0;
79 }
80
81 int ContractionState::LinesInDoc() const {
82 return linesInDoc;
83 }
84
85 int ContractionState::LinesDisplayed() const {
86 if (size != 0) {
87 MakeValid();
88 }
89 return linesInDisplay;
90 }
91
92 int ContractionState::DisplayFromDoc(int lineDoc) const {
93 if (size == 0) {
94 return lineDoc;
95 }
96 MakeValid();
97 if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
98 return lines[lineDoc].displayLine;
99 }
100 return -1;
101 }
102
103 int ContractionState::DocFromDisplay(int lineDisplay) const {
104 if (lineDisplay <= 0)
105 return 0;
106 if (lineDisplay >= linesInDisplay)
107 return linesInDoc;
108 if (size == 0)
109 return lineDisplay;
110 MakeValid();
111 if (docLines) { // Valid allocation
112 return docLines[lineDisplay];
113 } else {
114 return 0;
115 }
116 }
117
118 void ContractionState::Grow(int sizeNew) {
119 OneLine *linesNew = new OneLine[sizeNew];
120 if (linesNew) {
121 int i = 0;
122 for (; i < size; i++) {
123 linesNew[i] = lines[i];
124 }
125 for (; i < sizeNew; i++) {
126 linesNew[i].displayLine = i;
127 }
128 delete []lines;
129 lines = linesNew;
130 size = sizeNew;
131 valid = false;
132 } else {
133 Platform::DebugPrintf("No memory available\n");
134 // TODO: Blow up
135 }
136 }
137
138 void ContractionState::InsertLines(int lineDoc, int lineCount) {
139 if (size == 0) {
140 linesInDoc += lineCount;
141 linesInDisplay += lineCount;
142 return;
143 }
144 //Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc);
145 if ((linesInDoc + lineCount + 2) >= size) {
146 Grow(linesInDoc + lineCount + growSize);
147 }
148 linesInDoc += lineCount;
149 for (int i = linesInDoc; i >= lineDoc + lineCount; i--) {
150 lines[i].visible = lines[i - lineCount].visible;
151 lines[i].height = lines[i - lineCount].height;
152 linesInDisplay += lines[i].height;
153 lines[i].expanded = lines[i - lineCount].expanded;
154 }
155 for (int d=0;d<lineCount;d++) {
156 lines[lineDoc+d].visible = true; // Should inherit visibility from context ?
157 lines[lineDoc+d].height = 1;
158 lines[lineDoc+d].expanded = true;
159 }
160 valid = false;
161 }
162
163 void ContractionState::DeleteLines(int lineDoc, int lineCount) {
164 if (size == 0) {
165 linesInDoc -= lineCount;
166 linesInDisplay -= lineCount;
167 return;
168 }
169 int deltaDisplayed = 0;
170 for (int d=0;d<lineCount;d++) {
171 if (lines[lineDoc+d].visible)
172 deltaDisplayed -= lines[lineDoc+d].height;
173 }
174 for (int i = lineDoc; i < linesInDoc-lineCount; i++) {
175 if (i != 0) // Line zero is always visible
176 lines[i].visible = lines[i + lineCount].visible;
177 lines[i].expanded = lines[i + lineCount].expanded;
178 lines[i].height = lines[i + lineCount].height;
179 }
180 linesInDoc -= lineCount;
181 linesInDisplay += deltaDisplayed;
182 valid = false;
183 }
184
185 bool ContractionState::GetVisible(int lineDoc) const {
186 if (size == 0)
187 return true;
188 if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
189 return lines[lineDoc].visible;
190 } else {
191 return false;
192 }
193 }
194
195 bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) {
196 if (lineDocStart == 0)
197 lineDocStart++;
198 if (lineDocStart > lineDocEnd)
199 return false;
200 if (size == 0) {
201 Grow(linesInDoc + growSize);
202 }
203 // TODO: modify docLine members to mirror displayLine
204 int delta = 0;
205 // Change lineDocs
206 if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) {
207 for (int line=lineDocStart; line <= lineDocEnd; line++) {
208 if (lines[line].visible != visible) {
209 delta += visible ? lines[line].height : -lines[line].height;
210 lines[line].visible = visible;
211 }
212 }
213 }
214 linesInDisplay += delta;
215 valid = false;
216 return delta != 0;
217 }
218
219 bool ContractionState::GetExpanded(int lineDoc) const {
220 if (size == 0)
221 return true;
222 if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
223 return lines[lineDoc].expanded;
224 } else {
225 return false;
226 }
227 }
228
229 bool ContractionState::SetExpanded(int lineDoc, bool expanded) {
230 if (size == 0) {
231 if (expanded) {
232 // If in completely expanded state then setting
233 // one line to expanded has no effect.
234 return false;
235 }
236 Grow(linesInDoc + growSize);
237 }
238 if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
239 if (lines[lineDoc].expanded != expanded) {
240 lines[lineDoc].expanded = expanded;
241 return true;
242 }
243 }
244 return false;
245 }
246
247 int ContractionState::GetHeight(int lineDoc) const {
248 if (size == 0)
249 return 1;
250 if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
251 return lines[lineDoc].height;
252 } else {
253 return 1;
254 }
255 }
256
257 // Set the number of display lines needed for this line.
258 // Return true if this is a change.
259 bool ContractionState::SetHeight(int lineDoc, int height) {
260 if (lineDoc > linesInDoc)
261 return false;
262 if (size == 0) {
263 if (height == 1) {
264 // If in completely expanded state then all lines
265 // assumed to have height of one so no effect here.
266 return false;
267 }
268 Grow(linesInDoc + growSize);
269 }
270 if (lines[lineDoc].height != height) {
271 lines[lineDoc].height = height;
272 valid = false;
273 return true;
274 } else {
275 return false;
276 }
277 }
278
279 void ContractionState::ShowAll() {
280 delete []lines;
281 lines = 0;
282 size = 0;
283 }