Fix action icons in the log dialog being clipped on High-DPI displays
[TortoiseGit.git] / ext / scintilla / src / ContractionState.cxx
blob289e66920346b55bc968ee175cb02e75d9bbe18a
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>
9 #include <assert.h>
11 #include <stdexcept>
12 #include <algorithm>
14 #include "Platform.h"
16 #include "Position.h"
17 #include "SplitVector.h"
18 #include "Partitioning.h"
19 #include "RunStyles.h"
20 #include "SparseVector.h"
21 #include "ContractionState.h"
23 #ifdef SCI_NAMESPACE
24 using namespace Scintilla;
25 #endif
27 ContractionState::ContractionState() : visible(0), expanded(0), heights(0), foldDisplayTexts(0), displayLines(0), linesInDocument(1) {
28 //InsertLine(0);
31 ContractionState::~ContractionState() {
32 Clear();
35 void ContractionState::EnsureData() {
36 if (OneToOne()) {
37 visible = new RunStyles();
38 expanded = new RunStyles();
39 heights = new RunStyles();
40 foldDisplayTexts = new SparseVector<const char *>();
41 displayLines = new Partitioning(4);
42 InsertLines(0, linesInDocument);
46 void ContractionState::Clear() {
47 delete visible;
48 visible = 0;
49 delete expanded;
50 expanded = 0;
51 delete heights;
52 heights = 0;
53 delete foldDisplayTexts;
54 foldDisplayTexts = 0;
55 delete displayLines;
56 displayLines = 0;
57 linesInDocument = 1;
60 int ContractionState::LinesInDoc() const {
61 if (OneToOne()) {
62 return linesInDocument;
63 } else {
64 return displayLines->Partitions() - 1;
68 int ContractionState::LinesDisplayed() const {
69 if (OneToOne()) {
70 return linesInDocument;
71 } else {
72 return displayLines->PositionFromPartition(LinesInDoc());
76 int ContractionState::DisplayFromDoc(int lineDoc) const {
77 if (OneToOne()) {
78 return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument;
79 } else {
80 if (lineDoc > displayLines->Partitions())
81 lineDoc = displayLines->Partitions();
82 return displayLines->PositionFromPartition(lineDoc);
86 int ContractionState::DisplayLastFromDoc(int lineDoc) const {
87 return DisplayFromDoc(lineDoc) + GetHeight(lineDoc) - 1;
90 int ContractionState::DocFromDisplay(int lineDisplay) const {
91 if (OneToOne()) {
92 return lineDisplay;
93 } else {
94 if (lineDisplay <= 0) {
95 return 0;
97 if (lineDisplay > LinesDisplayed()) {
98 return displayLines->PartitionFromPosition(LinesDisplayed());
100 int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
101 PLATFORM_ASSERT(GetVisible(lineDoc));
102 return lineDoc;
106 void ContractionState::InsertLine(int lineDoc) {
107 if (OneToOne()) {
108 linesInDocument++;
109 } else {
110 visible->InsertSpace(lineDoc, 1);
111 visible->SetValueAt(lineDoc, 1);
112 expanded->InsertSpace(lineDoc, 1);
113 expanded->SetValueAt(lineDoc, 1);
114 heights->InsertSpace(lineDoc, 1);
115 heights->SetValueAt(lineDoc, 1);
116 foldDisplayTexts->InsertSpace(lineDoc, 1);
117 foldDisplayTexts->SetValueAt(lineDoc, NULL);
118 int lineDisplay = DisplayFromDoc(lineDoc);
119 displayLines->InsertPartition(lineDoc, lineDisplay);
120 displayLines->InsertText(lineDoc, 1);
124 void ContractionState::InsertLines(int lineDoc, int lineCount) {
125 for (int l = 0; l < lineCount; l++) {
126 InsertLine(lineDoc + l);
128 Check();
131 void ContractionState::DeleteLine(int lineDoc) {
132 if (OneToOne()) {
133 linesInDocument--;
134 } else {
135 if (GetVisible(lineDoc)) {
136 displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
138 displayLines->RemovePartition(lineDoc);
139 visible->DeleteRange(lineDoc, 1);
140 expanded->DeleteRange(lineDoc, 1);
141 heights->DeleteRange(lineDoc, 1);
142 foldDisplayTexts->DeletePosition(lineDoc);
146 void ContractionState::DeleteLines(int lineDoc, int lineCount) {
147 for (int l = 0; l < lineCount; l++) {
148 DeleteLine(lineDoc);
150 Check();
153 bool ContractionState::GetVisible(int lineDoc) const {
154 if (OneToOne()) {
155 return true;
156 } else {
157 if (lineDoc >= visible->Length())
158 return true;
159 return visible->ValueAt(lineDoc) == 1;
163 bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool isVisible) {
164 if (OneToOne() && isVisible) {
165 return false;
166 } else {
167 EnsureData();
168 int delta = 0;
169 Check();
170 if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
171 for (int line = lineDocStart; line <= lineDocEnd; line++) {
172 if (GetVisible(line) != isVisible) {
173 int difference = isVisible ? heights->ValueAt(line) : -heights->ValueAt(line);
174 visible->SetValueAt(line, isVisible ? 1 : 0);
175 displayLines->InsertText(line, difference);
176 delta += difference;
179 } else {
180 return false;
182 Check();
183 return delta != 0;
187 bool ContractionState::HiddenLines() const {
188 if (OneToOne()) {
189 return false;
190 } else {
191 return !visible->AllSameAs(1);
195 const char *ContractionState::GetFoldDisplayText(int lineDoc) const {
196 Check();
197 return foldDisplayTexts->ValueAt(lineDoc);
200 bool ContractionState::SetFoldDisplayText(int lineDoc, const char *text) {
201 EnsureData();
202 const char *foldText = foldDisplayTexts->ValueAt(lineDoc);
203 if (!foldText || 0 != strcmp(text, foldText)) {
204 foldDisplayTexts->SetValueAt(lineDoc, text);
205 Check();
206 return true;
207 } else {
208 Check();
209 return false;
213 bool ContractionState::GetExpanded(int lineDoc) const {
214 if (OneToOne()) {
215 return true;
216 } else {
217 Check();
218 return expanded->ValueAt(lineDoc) == 1;
222 bool ContractionState::SetExpanded(int lineDoc, bool isExpanded) {
223 if (OneToOne() && isExpanded) {
224 return false;
225 } else {
226 EnsureData();
227 if (isExpanded != (expanded->ValueAt(lineDoc) == 1)) {
228 expanded->SetValueAt(lineDoc, isExpanded ? 1 : 0);
229 Check();
230 return true;
231 } else {
232 Check();
233 return false;
238 bool ContractionState::GetFoldDisplayTextShown(int lineDoc) const {
239 return !GetExpanded(lineDoc) && GetFoldDisplayText(lineDoc);
242 int ContractionState::ContractedNext(int lineDocStart) const {
243 if (OneToOne()) {
244 return -1;
245 } else {
246 Check();
247 if (!expanded->ValueAt(lineDocStart)) {
248 return lineDocStart;
249 } else {
250 int lineDocNextChange = expanded->EndRun(lineDocStart);
251 if (lineDocNextChange < LinesInDoc())
252 return lineDocNextChange;
253 else
254 return -1;
259 int ContractionState::GetHeight(int lineDoc) const {
260 if (OneToOne()) {
261 return 1;
262 } else {
263 return heights->ValueAt(lineDoc);
267 // Set the number of display lines needed for this line.
268 // Return true if this is a change.
269 bool ContractionState::SetHeight(int lineDoc, int height) {
270 if (OneToOne() && (height == 1)) {
271 return false;
272 } else if (lineDoc < LinesInDoc()) {
273 EnsureData();
274 if (GetHeight(lineDoc) != height) {
275 if (GetVisible(lineDoc)) {
276 displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
278 heights->SetValueAt(lineDoc, height);
279 Check();
280 return true;
281 } else {
282 Check();
283 return false;
285 } else {
286 return false;
290 void ContractionState::ShowAll() {
291 int lines = LinesInDoc();
292 Clear();
293 linesInDocument = lines;
296 // Debugging checks
298 void ContractionState::Check() const {
299 #ifdef CHECK_CORRECTNESS
300 for (int vline = 0; vline < LinesDisplayed(); vline++) {
301 const int lineDoc = DocFromDisplay(vline);
302 PLATFORM_ASSERT(GetVisible(lineDoc));
304 for (int lineDoc = 0; lineDoc < LinesInDoc(); lineDoc++) {
305 const int displayThis = DisplayFromDoc(lineDoc);
306 const int displayNext = DisplayFromDoc(lineDoc + 1);
307 const int height = displayNext - displayThis;
308 PLATFORM_ASSERT(height >= 0);
309 if (GetVisible(lineDoc)) {
310 PLATFORM_ASSERT(GetHeight(lineDoc) == height);
311 } else {
312 PLATFORM_ASSERT(0 == height);
315 #endif