You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
6.8 KiB
289 lines
6.8 KiB
// Scintilla source code edit control |
|
/** @file ContractionState.cxx |
|
** Manages visibility of lines for folding. |
|
**/ |
|
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> |
|
// 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; |
|
}
|
|
|