Logo Search packages:      
Sourcecode: wxwindows2.4 version File versions  Download package

ContractionState.cxx

Go to the documentation of this file.
// 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;
      }
      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;
}

Generated by  Doxygen 1.6.0   Back to index