📄 cellbuffer.cxx
字号:
} undoSequenceDepth++;}void UndoHistory::EndUndoAction() { PLATFORM_ASSERT(undoSequenceDepth > 0); 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() { readOnly = false; collectingUndo = true;}CellBuffer::~CellBuffer() {}char CellBuffer::CharAt(int position) const { return substance.ValueAt(position);}void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) { if (lengthRetrieve < 0) return; if (position < 0) return; if ((position + lengthRetrieve) > substance.Length()) { Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n", position, lengthRetrieve, substance.Length()); return; } for (int i=0; i<lengthRetrieve; i++) { *buffer++ = substance.ValueAt(position + i); }}char CellBuffer::StyleAt(int position) { return style.ValueAt(position);}// The char* returned is to an allocation owned by the undo historyconst char *CellBuffer::InsertString(int position, const char *s, int insertLength, bool &startSequence) { char *data = 0; // InsertString and DeleteChars are the bottleneck though which all changes occur if (!readOnly) { if (collectingUndo) { // Save into the undo/redo stack, but only the characters - not the formatting // This takes up about half load time data = new char[insertLength]; for (int i = 0; i < insertLength; i++) { data[i] = s[i]; } uh.AppendAction(insertAction, position, data, insertLength, startSequence); } BasicInsertString(position, s, insertLength); } return data;}bool CellBuffer::SetStyleAt(int position, char styleValue, char mask) { styleValue &= mask; char curVal = style.ValueAt(position); if ((curVal & mask) != styleValue) { style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue)); return true; } else { return false; }}bool CellBuffer::SetStyleFor(int position, int lengthStyle, char styleValue, char mask) { bool changed = false; PLATFORM_ASSERT(lengthStyle == 0 || (lengthStyle > 0 && lengthStyle + position <= style.Length())); while (lengthStyle--) { char curVal = style.ValueAt(position); if ((curVal & mask) != styleValue) { style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue)); changed = true; } position++; } return changed;}// The char* returned is to an allocation owned by the undo historyconst char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startSequence) { // InsertString and DeleteChars are the bottleneck though which all changes occur PLATFORM_ASSERT(deleteLength > 0); char *data = 0; if (!readOnly) { if (collectingUndo) { // Save into the undo/redo stack, but only the characters - not the formatting data = new char[deleteLength]; for (int i = 0; i < deleteLength; i++) { data[i] = substance.ValueAt(position + i); } uh.AppendAction(removeAction, position, data, deleteLength, startSequence); } BasicDeleteChars(position, deleteLength); } return data;}int CellBuffer::Length() const { return substance.Length();}void CellBuffer::Allocate(int newSize) { substance.ReAllocate(newSize); style.ReAllocate(newSize);}int CellBuffer::Lines() const { return lv.Lines();}int CellBuffer::LineStart(int line) const { if (line < 0) return 0; else if (line >= Lines()) return Length(); else return lv.LineStart(line);}bool CellBuffer::IsReadOnly() { return readOnly;}void CellBuffer::SetReadOnly(bool set) { readOnly = set;}void CellBuffer::SetSavePoint() { uh.SetSavePoint();}bool CellBuffer::IsSavePoint() { return uh.IsSavePoint();}int CellBuffer::AddMark(int line, int markerNum) { if ((line >= 0) && (line < Lines())) { return lv.AddMark(line, markerNum); } return - 1;}void CellBuffer::DeleteMark(int line, int markerNum) { if ((line >= 0) && (line < Lines())) { lv.DeleteMark(line, markerNum, false); }}void CellBuffer::DeleteMarkFromHandle(int markerHandle) { lv.DeleteMarkFromHandle(markerHandle);}int CellBuffer::GetMark(int line) { if ((line >= 0) && (line < Lines())) return lv.MarkValue(line); return 0;}void CellBuffer::DeleteAllMarks(int markerNum) { for (int line = 0; line < Lines(); line++) { lv.DeleteMark(line, markerNum, true); }}int CellBuffer::LineFromHandle(int markerHandle) { return lv.LineFromHandle(markerHandle);}// Without undovoid CellBuffer::InsertLine(int line, int position) { lv.InsertLine(line, position); if (lineStates.Length()) { lineStates.EnsureLength(line); lineStates.Insert(line, 0); }}void CellBuffer::RemoveLine(int line) { lv.RemoveLine(line); if (lineStates.Length() > line) { lineStates.Delete(line); }}void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) { if (insertLength == 0) return; PLATFORM_ASSERT(insertLength > 0); substance.InsertFromArray(position, s, 0, insertLength); style.InsertValue(position, insertLength, 0); int lineInsert = lv.LineFromPosition(position) + 1; // Point all the lines after the insertion point further along in the buffer lv.InsertText(lineInsert-1, insertLength); char chPrev = substance.ValueAt(position - 1); char chAfter = substance.ValueAt(position + insertLength); if (chPrev == '\r' && chAfter == '\n') { // Splitting up a crlf pair at position InsertLine(lineInsert, position); lineInsert++; } char ch = ' '; for (int i = 0; i < insertLength; i++) { ch = s[i]; if (ch == '\r') { InsertLine(lineInsert, (position + i) + 1); lineInsert++; } else if (ch == '\n') { if (chPrev == '\r') { // Patch up what was end of line lv.SetLineStart(lineInsert - 1, (position + i) + 1); } else { InsertLine(lineInsert, (position + i) + 1); lineInsert++; } } chPrev = ch; } // Joining two lines where last insertion is cr and following substance starts with lf if (chAfter == '\n') { if (ch == '\r') { // End of line already in buffer so drop the newly created one RemoveLine(lineInsert - 1); } }}void CellBuffer::BasicDeleteChars(int position, int deleteLength) { if (deleteLength == 0) return; if ((position == 0) && (deleteLength == substance.Length())) { // If whole buffer is being deleted, faster to reinitialise lines data // than to delete each line. lv.Init(); } else { // Have to fix up line positions before doing deletion as looking at text in buffer // to work out which lines have been removed int lineRemove = lv.LineFromPosition(position) + 1; lv.InsertText(lineRemove-1, - (deleteLength)); char chPrev = substance.ValueAt(position - 1); char chBefore = chPrev; char chNext = substance.ValueAt(position); bool ignoreNL = false; if (chPrev == '\r' && chNext == '\n') { // Move back one lv.SetLineStart(lineRemove, position); lineRemove++; ignoreNL = true; // First \n is not real deletion } char ch = chNext; for (int i = 0; i < deleteLength; i++) { chNext = substance.ValueAt(position + i + 1); if (ch == '\r') { if (chNext != '\n') { RemoveLine(lineRemove); } } else if (ch == '\n') { if (ignoreNL) { ignoreNL = false; // Further \n are real deletions } else { RemoveLine(lineRemove); } } ch = chNext; } // May have to fix up end if last deletion causes cr to be next to lf // or removes one of a crlf pair char chAfter = substance.ValueAt(position + deleteLength); if (chBefore == '\r' && chAfter == '\n') { // Using lineRemove-1 as cr ended line before start of deletion RemoveLine(lineRemove - 1); lv.SetLineStart(lineRemove - 1, position + 1); } } substance.DeleteRange(position, deleteLength); style.DeleteRange(position, deleteLength);}bool CellBuffer::SetUndoCollection(bool collectUndo) { collectingUndo = collectUndo; uh.DropUndoSequence(); return collectingUndo;}bool CellBuffer::IsCollectingUndo() { return collectingUndo;}void CellBuffer::BeginUndoAction() { uh.BeginUndoAction();}void CellBuffer::EndUndoAction() { uh.EndUndoAction();}void CellBuffer::DeleteUndoHistory() { uh.DeleteUndoHistory();}bool CellBuffer::CanUndo() { return uh.CanUndo();}int CellBuffer::StartUndo() { return uh.StartUndo();}const Action &CellBuffer::GetUndoStep() const { return uh.GetUndoStep();}void CellBuffer::PerformUndoStep() { const Action &actionStep = uh.GetUndoStep(); if (actionStep.at == insertAction) { BasicDeleteChars(actionStep.position, actionStep.lenData); } else if (actionStep.at == removeAction) { BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData); } uh.CompletedUndoStep();}bool CellBuffer::CanRedo() { return uh.CanRedo();}int CellBuffer::StartRedo() { return uh.StartRedo();}const Action &CellBuffer::GetRedoStep() const { return uh.GetRedoStep();}void CellBuffer::PerformRedoStep() { const Action &actionStep = uh.GetRedoStep(); if (actionStep.at == insertAction) { BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData); } else if (actionStep.at == removeAction) { BasicDeleteChars(actionStep.position, actionStep.lenData); } uh.CompletedRedoStep();}int CellBuffer::SetLineState(int line, int state) { lineStates.EnsureLength(line + 1); int stateOld = lineStates[line]; lineStates[line] = state; return stateOld;}int CellBuffer::GetLineState(int line) { lineStates.EnsureLength(line + 1); return lineStates[line];}int CellBuffer::GetMaxLineState() { return lineStates.Length();}int CellBuffer::SetLevel(int line, int level) { return lv.SetLevel(line, level);}int CellBuffer::GetLevel(int line) { return lv.GetLevel(line);}void CellBuffer::ClearLevels() { lv.ClearLevels();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -