diff options
Diffstat (limited to 'src/ContractionState.cpp')
-rwxr-xr-x | src/ContractionState.cpp | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/src/ContractionState.cpp b/src/ContractionState.cpp new file mode 100755 index 0000000..3d021b0 --- /dev/null +++ b/src/ContractionState.cpp @@ -0,0 +1,289 @@ +// Scintilla source code edit control +/** @file ContractionState.cxx + ** Manages visibility of lines for folding. + **/ +// Copyright 1998-2001 by Neil Hodgson <[email protected]> +// The License.txt file describes the conditions under which this software may be distributed. + +#include "Platform.h" + +#include "ContractionState.h" + +OneLine::OneLine() { + displayLine = 0; + //docLine = 0; + visible = true; + height = 1; + expanded = true; +} + +ContractionState::ContractionState() { + lines = 0; + size = 0; + linesInDoc = 1; + linesInDisplay = 1; + valid = false; + docLines = 0; + sizeDocLines = 0; +} + +ContractionState::~ContractionState() { + Clear(); +} + +void ContractionState::MakeValid() const { + if (!valid) { + // Could be cleverer by keeping the index of the last still valid entry + // rather than invalidating all. + linesInDisplay = 0; + for (int lineInDoc=0; lineInDoc<linesInDoc; lineInDoc++) { + lines[lineInDoc].displayLine = linesInDisplay; + if (lines[lineInDoc].visible) { + linesInDisplay += lines[lineInDoc].height; + } + } + if (sizeDocLines < linesInDisplay) { + delete []docLines; + int *docLinesNew = new int[linesInDisplay + growSize]; + if (!docLinesNew) { + docLines = 0; + sizeDocLines = 0; + return; + } + docLines = docLinesNew; + sizeDocLines = linesInDisplay + growSize; + } + + int lineInDisplay=0; + for (int line=0; line<linesInDoc; line++) { + if (lines[line].visible) { + for (int linePiece=0; linePiece<lines[line].height; linePiece++) { + docLines[lineInDisplay] = line; + lineInDisplay++; + } + } + } + valid = true; + } +} + +void ContractionState::Clear() { + delete []lines; + lines = 0; + size = 0; + linesInDoc = 1; + linesInDisplay = 1; + delete []docLines; + docLines = 0; + sizeDocLines = 0; +} + +int ContractionState::LinesInDoc() const { + return linesInDoc; +} + +int ContractionState::LinesDisplayed() const { + if (size != 0) { + MakeValid(); + } + return linesInDisplay; +} + +int ContractionState::DisplayFromDoc(int lineDoc) const { + if (size == 0) { + return lineDoc; + } + MakeValid(); + if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { + return lines[lineDoc].displayLine; + } + return -1; +} + +int ContractionState::DocFromDisplay(int lineDisplay) const { + if (lineDisplay <= 0) + return 0; + if (lineDisplay >= linesInDisplay) + return linesInDoc; + if (size == 0) + return lineDisplay; + MakeValid(); + if (docLines) { // Valid allocation + return docLines[lineDisplay]; + } else { + return 0; + } +} + +void ContractionState::Grow(int sizeNew) { + OneLine *linesNew = new OneLine[sizeNew]; + if (linesNew) { + int i = 0; + for (; i < size; i++) { + linesNew[i] = lines[i]; + } + for (; i < sizeNew; i++) { + linesNew[i].displayLine = i; + } + delete []lines; + lines = linesNew; + size = sizeNew; + valid = false; + } else { + Platform::DebugPrintf("No memory available\n"); + // TODO: Blow up + } +} + +void ContractionState::InsertLines(int lineDoc, int lineCount) { + if (size == 0) { + linesInDoc += lineCount; + linesInDisplay += lineCount; + return; + } + //Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc); + if ((linesInDoc + lineCount + 2) >= size) { + Grow(linesInDoc + lineCount + growSize); + } + linesInDoc += lineCount; + for (int i = linesInDoc; i >= lineDoc + lineCount; i--) { + lines[i].visible = lines[i - lineCount].visible; + lines[i].height = lines[i - lineCount].height; + linesInDisplay += lines[i].height; + lines[i].expanded = lines[i - lineCount].expanded; + } + for (int d=0;d<lineCount;d++) { + lines[lineDoc+d].visible = true; // Should inherit visibility from context ? + lines[lineDoc+d].height = 1; + lines[lineDoc+d].expanded = true; + } + valid = false; +} + +void ContractionState::DeleteLines(int lineDoc, int lineCount) { + if (size == 0) { + linesInDoc -= lineCount; + linesInDisplay -= lineCount; + return; + } + int deltaDisplayed = 0; + for (int d=0;d<lineCount;d++) { + if (lines[lineDoc+d].visible) + deltaDisplayed -= lines[lineDoc+d].height; + } + for (int i = lineDoc; i < linesInDoc-lineCount; i++) { + if (i != 0) // Line zero is always visible + lines[i].visible = lines[i + lineCount].visible; + lines[i].expanded = lines[i + lineCount].expanded; + lines[i].height = lines[i + lineCount].height; + } + linesInDoc -= lineCount; + linesInDisplay += deltaDisplayed; + valid = false; +} + +bool ContractionState::GetVisible(int lineDoc) const { + if (size == 0) + return true; + if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { + return lines[lineDoc].visible; + } else { + return false; + } +} + +bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) { + if (lineDocStart == 0) + lineDocStart++; + if (lineDocStart > lineDocEnd) + return false; + if (size == 0) { + Grow(linesInDoc + growSize); + } + // TODO: modify docLine members to mirror displayLine + int delta = 0; + // Change lineDocs + if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) { + for (int line=lineDocStart; line <= lineDocEnd; line++) { + if (lines[line].visible != visible) { + delta += visible ? lines[line].height : -lines[line].height; + lines[line].visible = visible; + } + } + } + linesInDisplay += delta; + valid = false; + return delta != 0; +} + +bool ContractionState::GetExpanded(int lineDoc) const { + if (size == 0) + return true; + if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { + return lines[lineDoc].expanded; + } else { + return false; + } +} + +bool ContractionState::SetExpanded(int lineDoc, bool expanded) { + if (size == 0) { + if (expanded) { + // If in completely expanded state then setting + // one line to expanded has no effect. + return false; + } + Grow(linesInDoc + growSize); + } + if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { + if (lines[lineDoc].expanded != expanded) { + lines[lineDoc].expanded = expanded; + return true; + } + } + return false; +} + +int ContractionState::GetHeight(int lineDoc) const { + if (size == 0) + return 1; + if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { + return lines[lineDoc].height; + } else { + return 1; + } +} + +// Set the number of display lines needed for this line. +// Return true if this is a change. +bool ContractionState::SetHeight(int lineDoc, int height) { + if (lineDoc > linesInDoc) + return false; + if (size == 0) { + if (height == 1) { + // If in completely expanded state then all lines + // assumed to have height of one so no effect here. + return false; + } + Grow(linesInDoc + growSize); + } + if (lines[lineDoc].height != height) { + lines[lineDoc].height = height; + valid = false; + return true; + } else { + return false; + } +} + +void ContractionState::ShowAll() { + delete []lines; + lines = 0; + size = 0; + + delete []docLines; + docLines = 0; + sizeDocLines = 0; + + linesInDisplay = linesInDoc; +} |