Update Scintilla to version 3.5.1
[TortoiseGit.git] / ext / scintilla / src / ContractionState.cxx
blob7d19b57d9729efbd987051e441f70b08aa24ca9c
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.
8 #include <string.h>
10 #include <algorithm>
12 #include "Platform.h"
14 #include "SplitVector.h"
15 #include "Partitioning.h"
16 #include "RunStyles.h"
17 #include "ContractionState.h"
19 #ifdef SCI_NAMESPACE
20 using namespace Scintilla;
21 #endif
23 ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
24 //InsertLine(0);
27 ContractionState::~ContractionState() {
28 Clear();
31 void ContractionState::EnsureData() {
32 if (OneToOne()) {
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() {
42 delete visible;
43 visible = 0;
44 delete expanded;
45 expanded = 0;
46 delete heights;
47 heights = 0;
48 delete displayLines;
49 displayLines = 0;
50 linesInDocument = 1;
53 int ContractionState::LinesInDoc() const {
54 if (OneToOne()) {
55 return linesInDocument;
56 } else {
57 return displayLines->Partitions() - 1;
61 int ContractionState::LinesDisplayed() const {
62 if (OneToOne()) {
63 return linesInDocument;
64 } else {
65 return displayLines->PositionFromPartition(LinesInDoc());
69 int ContractionState::DisplayFromDoc(int lineDoc) const {
70 if (OneToOne()) {
71 return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument;
72 } else {
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 {
84 if (OneToOne()) {
85 return lineDisplay;
86 } else {
87 if (lineDisplay <= 0) {
88 return 0;
90 if (lineDisplay > LinesDisplayed()) {
91 return displayLines->PartitionFromPosition(LinesDisplayed());
93 int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
94 PLATFORM_ASSERT(GetVisible(lineDoc));
95 return lineDoc;
99 void ContractionState::InsertLine(int lineDoc) {
100 if (OneToOne()) {
101 linesInDocument++;
102 } else {
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);
119 Check();
122 void ContractionState::DeleteLine(int lineDoc) {
123 if (OneToOne()) {
124 linesInDocument--;
125 } else {
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++) {
138 DeleteLine(lineDoc);
140 Check();
143 bool ContractionState::GetVisible(int lineDoc) const {
144 if (OneToOne()) {
145 return true;
146 } else {
147 if (lineDoc >= visible->Length())
148 return true;
149 return visible->ValueAt(lineDoc) == 1;
153 bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool isVisible) {
154 if (OneToOne() && isVisible) {
155 return false;
156 } else {
157 EnsureData();
158 int delta = 0;
159 Check();
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);
166 delta += difference;
169 } else {
170 return false;
172 Check();
173 return delta != 0;
177 bool ContractionState::HiddenLines() const {
178 if (OneToOne()) {
179 return false;
180 } else {
181 return !visible->AllSameAs(1);
185 bool ContractionState::GetExpanded(int lineDoc) const {
186 if (OneToOne()) {
187 return true;
188 } else {
189 Check();
190 return expanded->ValueAt(lineDoc) == 1;
194 bool ContractionState::SetExpanded(int lineDoc, bool isExpanded) {
195 if (OneToOne() && isExpanded) {
196 return false;
197 } else {
198 EnsureData();
199 if (isExpanded != (expanded->ValueAt(lineDoc) == 1)) {
200 expanded->SetValueAt(lineDoc, isExpanded ? 1 : 0);
201 Check();
202 return true;
203 } else {
204 Check();
205 return false;
210 int ContractionState::ContractedNext(int lineDocStart) const {
211 if (OneToOne()) {
212 return -1;
213 } else {
214 Check();
215 if (!expanded->ValueAt(lineDocStart)) {
216 return lineDocStart;
217 } else {
218 int lineDocNextChange = expanded->EndRun(lineDocStart);
219 if (lineDocNextChange < LinesInDoc())
220 return lineDocNextChange;
221 else
222 return -1;
227 int ContractionState::GetHeight(int lineDoc) const {
228 if (OneToOne()) {
229 return 1;
230 } else {
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)) {
239 return false;
240 } else if (lineDoc < LinesInDoc()) {
241 EnsureData();
242 if (GetHeight(lineDoc) != height) {
243 if (GetVisible(lineDoc)) {
244 displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
246 heights->SetValueAt(lineDoc, height);
247 Check();
248 return true;
249 } else {
250 Check();
251 return false;
253 } else {
254 return false;
258 void ContractionState::ShowAll() {
259 int lines = LinesInDoc();
260 Clear();
261 linesInDocument = lines;
264 // Debugging checks
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);
279 } else {
280 PLATFORM_ASSERT(0 == height);
283 #endif