// Scintilla source code edit control
-// CellBuffer.cxx - manages a buffer of cells
-// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+/** @file CellBuffer.cxx
+ ** Manages a buffer of cells.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdio.h>
if (mhn->handle == handle) {
*pmhn = mhn->next;
delete mhn;
- return;
+ return ;
}
pmhn = &((*pmhn)->next);
}
}
-void MarkerHandleSet::RemoveNumber(int markerNum) {
+bool MarkerHandleSet::RemoveNumber(int markerNum) {
+ bool performedDeletion = false;
MarkerHandleNumber **pmhn = &root;
while (*pmhn) {
MarkerHandleNumber *mhn = *pmhn;
if (mhn->number == markerNum) {
*pmhn = mhn->next;
delete mhn;
- return;
+ performedDeletion = true;
+ } else {
+ pmhn = &((*pmhn)->next);
}
- pmhn = &((*pmhn)->next);
}
+ return performedDeletion;
}
void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
LineVector::LineVector() {
linesData = 0;
lines = 0;
+ size = 0;
levels = 0;
+ sizeLevels = 0;
+ handleCurrent = 1;
+ growSize = 1000;
+
Init();
}
Platform::DebugPrintf("No memory available\n");
// TODO: Blow up
}
+
}
void LineVector::ExpandLevels(int sizeNew) {
Platform::DebugPrintf("No memory available\n");
// TODO: Blow up
}
+
+}
+
+void LineVector::ClearLevels() {
+ delete []levels;
+ levels = 0;
+ sizeLevels = 0;
}
void LineVector::InsertValue(int pos, int value) {
//Platform::DebugPrintf("InsertValue[%d] = %d\n", pos, value);
if ((lines + 2) >= size) {
+ if (growSize * 6 < size)
+ growSize *= 2;
Expand(size + growSize);
if (levels) {
ExpandLevels(size + growSize);
}
}
lines++;
- for (int i = lines + 1; i > pos; i--) {
+ for (int i = lines; i > pos; i--) {
linesData[i] = linesData[i - 1];
}
linesData[pos].startPosition = value;
linesData[pos].handleSet = 0;
+ if (levels) {
+ for (int j = lines; j > pos; j--) {
+ levels[j] = levels[j - 1];
+ }
+ if (pos == 0) {
+ levels[pos] = SC_FOLDLEVELBASE;
+ } else if (pos == (lines - 1)) { // Last line will not be a folder
+ levels[pos] = SC_FOLDLEVELBASE;
+ } else {
+ levels[pos] = levels[pos - 1];
+ }
+ }
}
void LineVector::SetValue(int pos, int value) {
for (int i = pos; i < lines; i++) {
linesData[i] = linesData[i + 1];
}
+ if (levels) {
+ // Move up following lines but merge header flag from this line
+ // to line before to avoid a temporary disappearence causing expansion.
+ int firstHeader = levels[pos] & SC_FOLDLEVELHEADERFLAG;
+ for (int j = pos; j < lines; j++) {
+ levels[j] = levels[j + 1];
+ }
+ if (pos > 0)
+ levels[pos-1] |= firstHeader;
+ }
lines--;
}
return lines - 1;
int lower = 0;
int upper = lines;
- int middle = 0;
do {
- middle = (upper + lower + 1) / 2; // Round high
+ int middle = (upper + lower + 1) / 2; // Round high
if (pos < linesData[middle].startPosition) {
upper = middle - 1;
} else {
}
void LineVector::MergeMarkers(int pos) {
- if (linesData[pos].handleSet || linesData[pos + 1].handleSet) {
- if (linesData[pos].handleSet && linesData[pos + 1].handleSet) {
- linesData[pos].handleSet->CombineWith(linesData[pos].handleSet);
- linesData[pos].handleSet = 0;
- }
+ if (linesData[pos + 1].handleSet != NULL) {
+ if (linesData[pos].handleSet == NULL )
+ linesData[pos].handleSet = new MarkerHandleSet;
+ linesData[pos].handleSet->CombineWith(linesData[pos + 1].handleSet);
+ delete linesData[pos + 1].handleSet;
+ linesData[pos + 1].handleSet = NULL;
}
}
-void LineVector::DeleteMark(int line, int markerNum) {
+void LineVector::DeleteMark(int line, int markerNum, bool all) {
if (linesData[line].handleSet) {
if (markerNum == -1) {
delete linesData[line].handleSet;
linesData[line].handleSet = 0;
} else {
- linesData[line].handleSet->RemoveNumber(markerNum);
+ bool performedDeletion =
+ linesData[line].handleSet->RemoveNumber(markerNum);
+ while (all && performedDeletion) {
+ performedDeletion =
+ linesData[line].handleSet->RemoveNumber(markerNum);
+ }
if (linesData[line].handleSet->Length() == 0) {
delete linesData[line].handleSet;
linesData[line].handleSet = 0;
Destroy();
}
-void Action::Create(actionType at_, int position_, char *data_, int lenData_) {
+void Action::Create(actionType at_, int position_, char *data_, int lenData_, bool mayCoalesce_) {
delete []data;
position = position_;
at = at_;
data = data_;
lenData = lenData_;
+ mayCoalesce = mayCoalesce_;
}
void Action::Destroy() {
at = source->at;
data = source->data;
lenData = source->lenData;
+ mayCoalesce = source->mayCoalesce;
// Ownership of source data transferred to this
source->position = 0;
source->at = startAction;
source->data = 0;
source->lenData = 0;
+ source->mayCoalesce = true;
+}
+
+// The undo history stores a sequence of user operations that represent the user's view of the
+// commands executed on the text.
+// Each user operation contains a sequence of text insertion and text deletion actions.
+// All the user operations are stored in a list of individual actions with 'start' actions used
+// as delimiters between user operations.
+// Initially there is one start action in the history.
+// As each action is performed, it is recorded in the history. The action may either become
+// part of the current user operation or may start a new user operation. If it is to be part of the
+// current operation, then it overwrites the current last action. If it is to be part of a new
+// operation, it is appended after the current last action.
+// After writing the new action, a new start action is appended at the end of the history.
+// The decision of whether to start a new user operation is based upon two factors. If a
+// compound operation has been explicitly started by calling BeginUndoAction and no matching
+// EndUndoAction (these calls nest) has been called, then the action is coalesced into the current
+// operation. If there is no outstanding BeginUndoAction call then a new operation is started
+// unless it looks as if the new action is caused by the user typing or deleting a stream of text.
+// Sequences that look like typing or deletion are coalesced into a single user operation.
+
+UndoHistory::UndoHistory() {
+
+ lenActions = 100;
+ actions = new Action[lenActions];
+ maxAction = 0;
+ currentAction = 0;
+ undoSequenceDepth = 0;
+ savePoint = 0;
+
+ actions[currentAction].Create(startAction);
+}
+
+UndoHistory::~UndoHistory() {
+ delete []actions;
+ actions = 0;
+}
+
+void UndoHistory::EnsureUndoRoom() {
+ // Have to test that there is room for 2 more actions in the array
+ // as two actions may be created by the calling function
+ if (currentAction >= (lenActions - 2)) {
+ // Run out of undo nodes so extend the array
+ int lenActionsNew = lenActions * 2;
+ Action *actionsNew = new Action[lenActionsNew];
+ if (!actionsNew)
+ return ;
+ for (int act = 0; act <= currentAction; act++)
+ actionsNew[act].Grab(&actions[act]);
+ delete []actions;
+ lenActions = lenActionsNew;
+ actions = actionsNew;
+ }
+}
+
+void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData) {
+ EnsureUndoRoom();
+ //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
+ //Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at,
+ // actions[currentAction - 1].position, actions[currentAction - 1].lenData);
+ if (currentAction < savePoint) {
+ savePoint = -1;
+ }
+ if (currentAction >= 1) {
+ if (0 == undoSequenceDepth) {
+ // Top level actions may not always be coalesced
+ Action &actPrevious = actions[currentAction - 1];
+ // See if current action can be coalesced into previous action
+ // Will work if both are inserts or deletes and position is same
+ if (at != actPrevious.at) {
+ currentAction++;
+ } else if (currentAction == savePoint) {
+ currentAction++;
+ } else if ((at == insertAction) &&
+ (position != (actPrevious.position + actPrevious.lenData))) {
+ // Insertions must be immediately after to coalesce
+ currentAction++;
+ } else if (!actions[currentAction].mayCoalesce) {
+ // Not allowed to coalesce if this set
+ currentAction++;
+ } else if (at == removeAction) {
+ if ((lengthData == 1) || (lengthData == 2)){
+ if ((position + lengthData) == actPrevious.position) {
+ ; // Backspace -> OK
+ } else if (position == actPrevious.position) {
+ ; // Delete -> OK
+ } else {
+ // Removals must be at same position to coalesce
+ currentAction++;
+ }
+ } else {
+ // Removals must be of one character to coalesce
+ currentAction++;
+ }
+ } else {
+ //Platform::DebugPrintf("action coalesced\n");
+ }
+
+ } else {
+ // Actions not at top level are always coalesced unless this is after return to top level
+ if (!actions[currentAction].mayCoalesce)
+ currentAction++;
+ }
+ } else {
+ currentAction++;
+ }
+ actions[currentAction].Create(at, position, data, lengthData);
+ currentAction++;
+ actions[currentAction].Create(startAction);
+ maxAction = currentAction;
+}
+
+void UndoHistory::BeginUndoAction() {
+ EnsureUndoRoom();
+ if (undoSequenceDepth == 0) {
+ if (actions[currentAction].at != startAction) {
+ currentAction++;
+ actions[currentAction].Create(startAction);
+ maxAction = currentAction;
+ }
+ actions[currentAction].mayCoalesce = false;
+ }
+ undoSequenceDepth++;
+}
+
+void UndoHistory::EndUndoAction() {
+ EnsureUndoRoom();
+ undoSequenceDepth--;
+ if (0 == undoSequenceDepth) {
+ if (actions[currentAction].at != startAction) {
+ currentAction++;
+ actions[currentAction].Create(startAction);
+ maxAction = currentAction;
+ }
+ actions[currentAction].mayCoalesce = false;
+ }
+}
+
+void UndoHistory::DropUndoSequence() {
+ undoSequenceDepth = 0;
+}
+
+void UndoHistory::DeleteUndoHistory() {
+ for (int i = 1; i < maxAction; i++)
+ actions[i].Destroy();
+ maxAction = 0;
+ currentAction = 0;
+ actions[currentAction].Create(startAction);
+ savePoint = 0;
+}
+
+void UndoHistory::SetSavePoint() {
+ savePoint = currentAction;
+}
+
+bool UndoHistory::IsSavePoint() const {
+ return savePoint == currentAction;
+}
+
+bool UndoHistory::CanUndo() const {
+ return (currentAction > 0) && (maxAction > 0);
+}
+
+int UndoHistory::StartUndo() {
+ // Drop any trailing startAction
+ if (actions[currentAction].at == startAction && currentAction > 0)
+ currentAction--;
+
+ // Count the steps in this action
+ int act = currentAction;
+ while (actions[act].at != startAction && act > 0) {
+ act--;
+ }
+ return currentAction - act;
+}
+
+const Action &UndoHistory::GetUndoStep() const {
+ return actions[currentAction];
+}
+
+void UndoHistory::CompletedUndoStep() {
+ currentAction--;
+}
+
+bool UndoHistory::CanRedo() const {
+ return maxAction > currentAction;
+}
+
+int UndoHistory::StartRedo() {
+ // Drop any leading startAction
+ if (actions[currentAction].at == startAction && currentAction < maxAction)
+ currentAction++;
+
+ // Count the steps in this action
+ int act = currentAction;
+ while (actions[act].at != startAction && act < maxAction) {
+ act++;
+ }
+ return act - currentAction;
+}
+
+const Action &UndoHistory::GetRedoStep() const {
+ return actions[currentAction];
+}
+
+void UndoHistory::CompletedRedoStep() {
+ currentAction++;
}
CellBuffer::CellBuffer(int initialLength) {
gaplen = initialLength;
part2body = body + gaplen;
readOnly = false;
-
- lenActions = 100;
- actions = new Action[lenActions];
- maxAction = 0;
- currentAction = 0;
- collectingUndo = undoCollectAutoStart;
- undoSequenceDepth = 0;
- savePoint = 0;
-
- actions[currentAction].Create(startAction);
+ collectingUndo = true;
+ growSize = 4000;
}
CellBuffer::~CellBuffer() {
delete []body;
body = 0;
- delete []actions;
- actions = 0;
}
void CellBuffer::GapTo(int position) {
if (position == part1len)
- return;
+ return ;
if (position < part1len) {
int diff = part1len - position;
//Platform::DebugPrintf("Move gap backwards to %d diff = %d part1len=%d length=%d \n", position,diff, part1len, length);
//Platform::DebugPrintf("need room %d %d\n", gaplen, insertionLength);
if (gaplen <= insertionLength) {
//Platform::DebugPrintf("need room %d %d\n", gaplen, insertionLength);
- GapTo(length);
- int newSize = size + insertionLength + 4000;
- //Platform::DebugPrintf("moved gap %d\n", newSize);
- char *newBody = new char[newSize];
- memcpy(newBody, body, size);
- delete []body;
- body = newBody;
- gaplen += newSize - size;
- part2body = body + gaplen;
- size = newSize;
- //Platform::DebugPrintf("end need room %d %d - size=%d length=%d\n", gaplen, insertionLength,size,length);
+ if (growSize * 6 < size)
+ growSize *= 2;
+ int newSize = size + insertionLength + growSize;
+ Allocate(newSize);
}
}
if (position < 0) {
//Platform::DebugPrintf("Bad position %d\n",position);
- return;
+ return ;
}
if (position >= length + 11) {
Platform::DebugPrintf("Very Bad position %d of %d\n", position, length);
//exit(2);
- return;
+ return ;
}
if (position >= length) {
//Platform::DebugPrintf("Bad position %d of %d\n",position,length);
- return;
+ return ;
}
if (position < part1len) {
void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) {
if (lengthRetrieve < 0)
- return;
+ return ;
if (position < 0)
- return;
+ return ;
int bytePos = position * 2;
if ((bytePos + lengthRetrieve * 2) > length) {
- Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n",bytePos,
- lengthRetrieve, length);
- return;
+ Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n", bytePos,
+ lengthRetrieve, length);
+ return ;
}
GapTo(0); // Move the buffer so its easy to subscript into it
char *pb = part2body + bytePos;
while (lengthRetrieve--) {
*buffer++ = *pb;
- pb +=2;
+ pb += 2;
}
}
for (int i = 0; i < insertLength / 2; i++) {
data[i] = s[i * 2];
}
- AppendAction(insertAction, position, data, insertLength / 2);
+ uh.AppendAction(insertAction, position / 2, data, insertLength / 2);
}
BasicInsertString(position, s, insertLength);
return data;
}
-void CellBuffer::InsertCharStyle(int position, char ch, char style) {
- char s[2];
- s[0] = ch;
- s[1] = style;
- InsertString(position*2, s, 2);
-}
-
bool CellBuffer::SetStyleAt(int position, char style, char mask) {
- char curVal = ByteAt(position*2 + 1);
+ style &= mask;
+ char curVal = ByteAt(position * 2 + 1);
if ((curVal & mask) != style) {
- SetByteAt(position*2 + 1, (curVal & ~mask) | style);
+ SetByteAt(position*2 + 1, static_cast<char>((curVal & ~mask) | style));
return true;
} else {
return false;
bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mask) {
int bytePos = position * 2 + 1;
bool changed = false;
+ PLATFORM_ASSERT(lengthStyle == 0 ||
+ (lengthStyle > 0 && lengthStyle + position < length));
while (lengthStyle--) {
char curVal = ByteAt(bytePos);
if ((curVal & mask) != style) {
- SetByteAt(bytePos, (curVal & ~mask) | style);
+ SetByteAt(bytePos, static_cast<char>((curVal & ~mask) | style));
changed = true;
}
bytePos += 2;
return changed;
}
-void CellBuffer::EnsureUndoRoom() {
- //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, length, currentAction);
- if (currentAction >= 2) {
- // Have to test that there is room for 2 more actions in the array
- // as two actions may be created by this function
- if (currentAction >= (lenActions - 2)) {
- // Run out of undo nodes so extend the array
- int lenActionsNew = lenActions * 2;
- Action *actionsNew = new Action[lenActionsNew];
- if (!actionsNew)
- return;
- for (int act = 0; act <= currentAction; act++)
- actionsNew[act].Grab(&actions[act]);
- delete []actions;
- lenActions = lenActionsNew;
- actions = actionsNew;
- }
- }
-}
-
-void CellBuffer::AppendAction(actionType at, int position, char *data, int lengthData) {
- EnsureUndoRoom();
- //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
- if (currentAction >= 2) {
- // See if current action can be coalesced into previous action
- // Will work if both are inserts or deletes and position is same or two different
- if ((at != actions[currentAction - 1].at) || (abs(position - actions[currentAction - 1].position) > 2)) {
- currentAction++;
- } else if (currentAction == savePoint) {
- currentAction++;
- }
- } else {
- currentAction++;
- }
- actions[currentAction].Create(at, position, data, lengthData);
- if ((collectingUndo == undoCollectAutoStart) && (0 == undoSequenceDepth)) {
- currentAction++;
- actions[currentAction].Create(startAction);
- }
- maxAction = currentAction;
-}
-
const char *CellBuffer::DeleteChars(int position, int deleteLength) {
// InsertString and DeleteChars are the bottleneck though which all changes occur
+ PLATFORM_ASSERT(deleteLength > 0);
char *data = 0;
if (!readOnly) {
if (collectingUndo) {
for (int i = 0; i < deleteLength / 2; i++) {
data[i] = ByteAt(position + i * 2);
}
- AppendAction(removeAction, position, data, deleteLength / 2);
+ uh.AppendAction(removeAction, position / 2, data, deleteLength / 2);
}
BasicDeleteChars(position, deleteLength);
return ByteLength() / 2;
}
+void CellBuffer::Allocate(int newSize) {
+ if (newSize > length) {
+ GapTo(length);
+ char *newBody = new char[newSize];
+ memcpy(newBody, body, length);
+ delete []body;
+ body = newBody;
+ gaplen += newSize - size;
+ part2body = body + gaplen;
+ size = newSize;
+ }
+}
+
int CellBuffer::Lines() {
//Platform::DebugPrintf("Lines = %d\n", lv.lines);
return lv.lines;
if (line < 0)
return 0;
else if (line > lv.lines)
- return length;
+ return Length();
else
return lv.linesData[line].startPosition;
}
}
void CellBuffer::SetSavePoint() {
- savePoint = currentAction;
+ uh.SetSavePoint();
}
bool CellBuffer::IsSavePoint() {
- return savePoint == currentAction;
+ return uh.IsSavePoint();
}
int CellBuffer::AddMark(int line, int markerNum) {
void CellBuffer::DeleteMark(int line, int markerNum) {
if ((line >= 0) && (line < lv.lines)) {
- lv.DeleteMark(line, markerNum);
+ lv.DeleteMark(line, markerNum, false);
}
}
void CellBuffer::DeleteAllMarks(int markerNum) {
for (int line = 0; line < lv.lines; line++) {
- lv.DeleteMark(line, markerNum);
+ lv.DeleteMark(line, markerNum, true);
}
}
void CellBuffer::BasicInsertString(int position, char *s, int insertLength) {
//Platform::DebugPrintf("Inserting at %d for %d\n", position, insertLength);
if (insertLength == 0)
- return;
+ return ;
+ PLATFORM_ASSERT(insertLength > 0);
RoomFor(insertLength);
GapTo(position);
void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
//Platform::DebugPrintf("Deleting at %d for %d\n", position, deleteLength);
if (deleteLength == 0)
- return;
+ return ;
if ((position == 0) && (deleteLength == length)) {
// If whole buffer is being deleted, faster to reinitialise lines data
//Platform::DebugPrintf("Removing cr end of line\n");
lv.Remove(lineRemove);
}
- } else if ((ch == '\n') && !ignoreNL) {
- //Platform::DebugPrintf("Removing lf end of line\n");
- lv.Remove(lineRemove);
- ignoreNL = false; // Further \n are not real deletions
+ } else if (ch == '\n') {
+ if (ignoreNL) {
+ ignoreNL = false; // Further \n are real deletions
+ } else {
+ //Platform::DebugPrintf("Removing lf end of line\n");
+ lv.Remove(lineRemove);
+ }
}
ch = chNext;
part2body = body + gaplen;
}
-undoCollectionType CellBuffer::SetUndoCollection(undoCollectionType collectUndo) {
+bool CellBuffer::SetUndoCollection(bool collectUndo) {
collectingUndo = collectUndo;
- undoSequenceDepth = 0;
+ uh.DropUndoSequence();
return collectingUndo;
}
return collectingUndo;
}
-void CellBuffer::AppendUndoStartAction() {
- EnsureUndoRoom();
- // Finish any currently active undo sequence
- undoSequenceDepth = 0;
- if (actions[currentAction].at != startAction) {
- undoSequenceDepth++;
- currentAction++;
- actions[currentAction].Create(startAction);
- maxAction = currentAction;
- }
-}
-
void CellBuffer::BeginUndoAction() {
- EnsureUndoRoom();
- if (undoSequenceDepth == 0) {
- if (actions[currentAction].at != startAction) {
- currentAction++;
- actions[currentAction].Create(startAction);
- maxAction = currentAction;
- }
- }
- undoSequenceDepth++;
+ uh.BeginUndoAction();
}
void CellBuffer::EndUndoAction() {
- EnsureUndoRoom();
- undoSequenceDepth--;
- if (0 == undoSequenceDepth) {
- if (actions[currentAction].at != startAction) {
- currentAction++;
- actions[currentAction].Create(startAction);
- maxAction = currentAction;
- }
- }
+ uh.EndUndoAction();
}
void CellBuffer::DeleteUndoHistory() {
- for (int i = 1; i < maxAction; i++)
- actions[i].Destroy();
- maxAction = 0;
- currentAction = 0;
- savePoint = 0;
+ uh.DeleteUndoHistory();
}
bool CellBuffer::CanUndo() {
- return (!readOnly) && ((currentAction > 0) && (maxAction > 0));
+ return uh.CanUndo();
}
int CellBuffer::StartUndo() {
- // Drop any trailing startAction
- if (actions[currentAction].at == startAction && currentAction > 0)
- currentAction--;
-
- // Count the steps in this action
- int act = currentAction;
- while (actions[act].at != startAction && act > 0) {
- act--;
- }
- return currentAction - act;
+ return uh.StartUndo();
+}
+
+const Action &CellBuffer::GetUndoStep() const {
+ return uh.GetUndoStep();
}
-const Action &CellBuffer::UndoStep() {
- const Action &actionStep = actions[currentAction];
+void CellBuffer::PerformUndoStep() {
+ const Action &actionStep = uh.GetUndoStep();
if (actionStep.at == insertAction) {
- BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+ BasicDeleteChars(actionStep.position*2, actionStep.lenData*2);
} else if (actionStep.at == removeAction) {
char *styledData = new char[actionStep.lenData * 2];
for (int i = 0; i < actionStep.lenData; i++) {
styledData[i*2] = actionStep.data[i];
- styledData[i*2+1] = 0;
+ styledData[i*2 + 1] = 0;
}
- BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+ BasicInsertString(actionStep.position*2, styledData, actionStep.lenData*2);
delete []styledData;
}
- currentAction--;
- return actionStep;
+ uh.CompletedUndoStep();
}
bool CellBuffer::CanRedo() {
- return (!readOnly) && (maxAction > currentAction);
+ return uh.CanRedo();
}
int CellBuffer::StartRedo() {
- // Drop any leading startAction
- if (actions[currentAction].at == startAction && currentAction < maxAction)
- currentAction++;
-
- // Count the steps in this action
- int act = currentAction;
- while (actions[act].at != startAction && act < maxAction) {
- act++;
- }
- return act - currentAction;
+ return uh.StartRedo();
+}
+
+const Action &CellBuffer::GetRedoStep() const {
+ return uh.GetRedoStep();
}
-const Action &CellBuffer::RedoStep() {
- const Action &actionStep = actions[currentAction];
+void CellBuffer::PerformRedoStep() {
+ const Action &actionStep = uh.GetRedoStep();
if (actionStep.at == insertAction) {
char *styledData = new char[actionStep.lenData * 2];
for (int i = 0; i < actionStep.lenData; i++) {
styledData[i*2] = actionStep.data[i];
- styledData[i*2+1] = 0;
+ styledData[i*2 + 1] = 0;
}
- BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+ BasicInsertString(actionStep.position*2, styledData, actionStep.lenData*2);
delete []styledData;
} else if (actionStep.at == removeAction) {
- BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+ BasicDeleteChars(actionStep.position*2, actionStep.lenData*2);
}
- currentAction++;
- return actionStep;
+ uh.CompletedRedoStep();
}
int CellBuffer::SetLineState(int line, int state) {
int CellBuffer::GetMaxLineState() {
return lineStates.Length();
}
-
+
int CellBuffer::SetLevel(int line, int level) {
int prev = 0;
if ((line >= 0) && (line < lv.lines)) {
}
}
+void CellBuffer::ClearLevels() {
+ lv.ClearLevels();
+}