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

// 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;
}