aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authornyamatongwe <unknown>2009-07-10 04:24:46 +0000
committernyamatongwe <unknown>2009-07-10 04:24:46 +0000
commitb9c0ee83ce4b36dd6bdb121cf80ec2a95359e16e (patch)
tree7dfdab1ffa28fd8f49bb447e5ecf7b3a240d92e9 /src
parentd97f2a1f599a6fdfa408a5a6c01411c03569a899 (diff)
downloadscintilla-mirror-b9c0ee83ce4b36dd6bdb121cf80ec2a95359e16e.tar.gz
Duplicate works on discontiguous selections by duplicating each selection.
UndoGroup class simplifies grouping actions together in the undo history.
Diffstat (limited to 'src')
-rw-r--r--src/Document.cxx6
-rw-r--r--src/Document.h21
-rw-r--r--src/Editor.cxx182
-rw-r--r--src/ScintillaBase.cxx3
4 files changed, 102 insertions, 110 deletions
diff --git a/src/Document.cxx b/src/Document.cxx
index eca4511de..5fd2749a0 100644
--- a/src/Document.cxx
+++ b/src/Document.cxx
@@ -761,10 +761,9 @@ void Document::SetLineIndentation(int line, int indent) {
CreateIndentation(linebuf, sizeof(linebuf), indent, tabInChars, !useTabs);
int thisLineStart = LineStart(line);
int indentPos = GetLineIndentPosition(line);
- BeginUndoAction();
+ UndoGroup ug(this);
DeleteChars(thisLineStart, indentPos - thisLineStart);
InsertCString(thisLineStart, linebuf);
- EndUndoAction();
}
}
@@ -871,7 +870,7 @@ char *Document::TransformLineEnds(int *pLenOut, const char *s, size_t len, int e
}
void Document::ConvertLineEnds(int eolModeSet) {
- BeginUndoAction();
+ UndoGroup ug(this);
for (int pos = 0; pos < Length(); pos++) {
if (cb.CharAt(pos) == '\r') {
@@ -906,7 +905,6 @@ void Document::ConvertLineEnds(int eolModeSet) {
}
}
- EndUndoAction();
}
bool Document::IsWhiteLine(int line) const {
diff --git a/src/Document.h b/src/Document.h
index 4751cd2c8..240d59e39 100644
--- a/src/Document.h
+++ b/src/Document.h
@@ -320,6 +320,27 @@ private:
void NotifyModified(DocModification mh);
};
+class UndoGroup {
+ Document *pdoc;
+ bool groupNeeded;
+public:
+ UndoGroup(Document *pdoc_, bool groupNeeded_=true) :
+ pdoc(pdoc_), groupNeeded(groupNeeded_) {
+ if (groupNeeded) {
+ pdoc->BeginUndoAction();
+ }
+ }
+ ~UndoGroup() {
+ if (groupNeeded) {
+ pdoc->EndUndoAction();
+ }
+ }
+ bool Needed() const {
+ return groupNeeded;
+ }
+};
+
+
/**
* To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
* scope of the change.
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 1cfa6df02..976ec0c7c 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -1415,7 +1415,7 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) {
void Editor::LinesJoin() {
if (!RangeContainsProtected(targetStart, targetEnd)) {
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
bool prevNonWS = true;
for (int pos = targetStart; pos < targetEnd; pos++) {
if (IsEOLChar(pdoc->CharAt(pos))) {
@@ -1430,7 +1430,6 @@ void Editor::LinesJoin() {
prevNonWS = pdoc->CharAt(pos) != ' ';
}
}
- pdoc->EndUndoAction();
}
}
@@ -1453,7 +1452,7 @@ void Editor::LinesSplit(int pixelWidth) {
int lineStart = pdoc->LineFromPosition(targetStart);
int lineEnd = pdoc->LineFromPosition(targetEnd);
const char *eol = StringFromEOLMode(pdoc->eolMode);
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
for (int line = lineStart; line <= lineEnd; line++) {
AutoSurface surface(this);
AutoLineLayout ll(llc, RetrieveLineLayout(line));
@@ -1468,7 +1467,6 @@ void Editor::LinesSplit(int pixelWidth) {
}
lineEnd = pdoc->LineFromPosition(targetEnd);
}
- pdoc->EndUndoAction();
}
}
@@ -3649,46 +3647,44 @@ void Editor::AddChar(char ch) {
// AddCharUTF inserts an array of bytes which may or may not be in UTF-8.
void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
- const bool undoBracketNeeded = (sel.Count() > 1) || !sel.Empty() || inOverstrike;
- if (undoBracketNeeded)
- pdoc->BeginUndoAction();
- for (size_t r=0; r<sel.Count(); r++) {
- if (!RangeContainsProtected(sel.Range(r).Start().Position(),
- sel.Range(r).End().Position())) {
- int positionInsert = sel.Range(r).Start().Position();
- if (!sel.Range(r).Empty()) {
- if (sel.Range(r).Length()) {
- pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
- sel.ClearVirtualSpace(r);
- } else {
- // Range is all virtual so collapse to start of virtual space
- sel.Range(r).MinimizeVirtualSpace();
- }
- } else if (inOverstrike) {
- if (positionInsert < pdoc->Length()) {
- if (!IsEOLChar(pdoc->CharAt(positionInsert))) {
- pdoc->DelChar(positionInsert);
+ {
+ UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!RangeContainsProtected(sel.Range(r).Start().Position(),
+ sel.Range(r).End().Position())) {
+ int positionInsert = sel.Range(r).Start().Position();
+ if (!sel.Range(r).Empty()) {
+ if (sel.Range(r).Length()) {
+ pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
sel.ClearVirtualSpace(r);
+ } else {
+ // Range is all virtual so collapse to start of virtual space
+ sel.Range(r).MinimizeVirtualSpace();
+ }
+ } else if (inOverstrike) {
+ if (positionInsert < pdoc->Length()) {
+ if (!IsEOLChar(pdoc->CharAt(positionInsert))) {
+ pdoc->DelChar(positionInsert);
+ sel.ClearVirtualSpace(r);
+ }
}
}
- }
- positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
- if (pdoc->InsertString(positionInsert, s, len)) {
- sel.Range(r).caret.SetPosition(positionInsert + len);
- sel.Range(r).anchor.SetPosition(positionInsert + len);
- }
- sel.ClearVirtualSpace(r);
- // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
- if (wrapState != eWrapNone) {
- AutoSurface surface(this);
- if (surface) {
- WrapOneLine(surface, pdoc->LineFromPosition(positionInsert));
+ positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
+ if (pdoc->InsertString(positionInsert, s, len)) {
+ sel.Range(r).caret.SetPosition(positionInsert + len);
+ sel.Range(r).anchor.SetPosition(positionInsert + len);
+ }
+ sel.ClearVirtualSpace(r);
+ // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
+ if (wrapState != eWrapNone) {
+ AutoSurface surface(this);
+ if (surface) {
+ WrapOneLine(surface, pdoc->LineFromPosition(positionInsert));
+ }
}
}
}
}
- if (undoBracketNeeded)
- pdoc->EndUndoAction();
if (wrapState != eWrapNone) {
SetScrollBars();
}
@@ -3743,7 +3739,7 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
}
void Editor::ClearSelection() {
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
for (size_t r=0; r<sel.Count(); r++) {
if (!sel.Range(r).Empty()) {
if (!RangeContainsProtected(sel.Range(r).Start().Position(),
@@ -3754,21 +3750,20 @@ void Editor::ClearSelection() {
}
}
}
- pdoc->EndUndoAction();
-
}
void Editor::ClearAll() {
- pdoc->BeginUndoAction();
- if (0 != pdoc->Length()) {
- pdoc->DeleteChars(0, pdoc->Length());
- }
- if (!pdoc->IsReadOnly()) {
- cs.Clear();
- pdoc->AnnotationClearAll();
- pdoc->MarginClearAll();
+ {
+ UndoGroup ug(pdoc);
+ if (0 != pdoc->Length()) {
+ pdoc->DeleteChars(0, pdoc->Length());
+ }
+ if (!pdoc->IsReadOnly()) {
+ cs.Clear();
+ pdoc->AnnotationClearAll();
+ pdoc->MarginClearAll();
+ }
}
- pdoc->EndUndoAction();
sel.Clear();
SetTopLine(0);
SetVerticalScrollPos();
@@ -3813,7 +3808,7 @@ void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) {
sel.Clear();
sel.RangeMain() = SelectionRange(pos);
int line = pdoc->LineFromPosition(sel.MainCaret());
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
sel.RangeMain().caret = SelectionPosition(
InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
int xInsert = XFromPosition(sel.RangeMain().caret);
@@ -3843,7 +3838,6 @@ void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) {
prevCr = false;
}
}
- pdoc->EndUndoAction();
SetEmptySelection(pos);
}
@@ -3852,12 +3846,9 @@ bool Editor::CanPaste() {
}
void Editor::Clear() {
- const bool undoBracketNeeded = (sel.Count() > 1) || !sel.Empty();
+ UndoGroup ug(pdoc);
// If multiple selections, don't delete EOLS
- if (undoBracketNeeded)
- pdoc->BeginUndoAction();
if (sel.Empty()) {
- pdoc->BeginUndoAction();
for (size_t r=0; r<sel.Count(); r++) {
if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) {
if ((sel.Count() == 1) || !IsEOLChar(pdoc->CharAt(sel.Range(r).caret.Position()))) {
@@ -3868,12 +3859,9 @@ void Editor::Clear() {
sel.ClearVirtualSpace(r);
}
}
- pdoc->EndUndoAction();
} else {
ClearSelection();
}
- if (undoBracketNeeded)
- pdoc->EndUndoAction();
}
void Editor::SelectAll() {
@@ -3911,9 +3899,7 @@ void Editor::DelChar() {
void Editor::DelCharBack(bool allowLineStartDeletion) {
if (sel.IsRectangular())
allowLineStartDeletion = false;
- const bool undoBracketNeeded = (sel.Count() > 1) || !sel.Empty();
- if (undoBracketNeeded)
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty());
if (sel.Empty()) {
for (size_t r=0; r<sel.Count(); r++) {
if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) {
@@ -3925,8 +3911,7 @@ void Editor::DelCharBack(bool allowLineStartDeletion) {
if (allowLineStartDeletion || (pdoc->LineStart(lineCurrentPos) != sel.Range(r).caret.Position())) {
if (pdoc->GetColumn(sel.Range(r).caret.Position()) <= pdoc->GetLineIndentation(lineCurrentPos) &&
pdoc->GetColumn(sel.Range(r).caret.Position()) > 0 && pdoc->backspaceUnindents) {
- if (!undoBracketNeeded)
- pdoc->BeginUndoAction();
+ UndoGroup ugInner(pdoc, !ug.Needed());
int indentation = pdoc->GetLineIndentation(lineCurrentPos);
int indentationStep = pdoc->IndentSize();
if (indentation % indentationStep == 0) {
@@ -3937,8 +3922,6 @@ void Editor::DelCharBack(bool allowLineStartDeletion) {
// SetEmptySelection
sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos),
pdoc->GetLineIndentPosition(lineCurrentPos));
- if (!undoBracketNeeded)
- pdoc->EndUndoAction();
} else {
pdoc->DelCharBack(sel.Range(r).caret.Position());
}
@@ -3956,8 +3939,6 @@ void Editor::DelCharBack(bool allowLineStartDeletion) {
}
//SetEmptySelection(sel.MainCaret());
}
- if (undoBracketNeeded)
- pdoc->EndUndoAction();
// Avoid blinking during rapid typing:
ShowCaretAtCurrentPosition();
}
@@ -4457,7 +4438,7 @@ void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) {
}
void Editor::ChangeCaseOfSelection(bool makeUpperCase) {
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
for (size_t r=0; r<sel.Count(); r++) {
SelectionRange current = sel.Range(r);
pdoc->ChangeCase(Range(current.Start().Position(), current.End().Position()),
@@ -4465,13 +4446,12 @@ void Editor::ChangeCaseOfSelection(bool makeUpperCase) {
// Automatic movement cuts off last character so reset to exactly the same as it was.
sel.Range(r) = current;
}
- pdoc->EndUndoAction();
}
void Editor::LineTranspose() {
int line = pdoc->LineFromPosition(sel.MainCaret());
if (line > 0) {
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
int startPrev = pdoc->LineStart(line - 1);
int endPrev = pdoc->LineEnd(line - 1);
int start = pdoc->LineStart(line);
@@ -4487,31 +4467,32 @@ void Editor::LineTranspose() {
MovePositionTo(SelectionPosition(start - len1 + len2));
delete []line1;
delete []line2;
- pdoc->EndUndoAction();
}
}
void Editor::Duplicate(bool forLine) {
- // TODO: multiple selection by duplicating each selection
- SelectionPosition start = SelectionStart();
- SelectionPosition end = SelectionEnd();
if (sel.Empty()) {
forLine = true;
}
- if (forLine) {
- int line = pdoc->LineFromPosition(sel.MainCaret());
- start = SelectionPosition(pdoc->LineStart(line));
- end = SelectionPosition(pdoc->LineEnd(line));
- }
- char *text = CopyRange(start.Position(), end.Position());
- if (forLine) {
- const char *eol = StringFromEOLMode(pdoc->eolMode);
- pdoc->InsertCString(end.Position(), eol);
- pdoc->InsertString(end.Position() + istrlen(eol), text, SelectionRange(end, start).Length());
- } else {
- pdoc->InsertString(end.Position(), text, SelectionRange(end, start).Length());
+ UndoGroup ug(pdoc, sel.Count() > 1);
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionPosition start = sel.Range(r).Start();
+ SelectionPosition end = sel.Range(r).End();
+ if (forLine) {
+ int line = pdoc->LineFromPosition(sel.Range(r).caret.Position());
+ start = SelectionPosition(pdoc->LineStart(line));
+ end = SelectionPosition(pdoc->LineEnd(line));
+ }
+ char *text = CopyRange(start.Position(), end.Position());
+ if (forLine) {
+ const char *eol = StringFromEOLMode(pdoc->eolMode);
+ pdoc->InsertCString(end.Position(), eol);
+ pdoc->InsertString(end.Position() + istrlen(eol), text, SelectionRange(end, start).Length());
+ } else {
+ pdoc->InsertString(end.Position(), text, SelectionRange(end, start).Length());
+ }
+ delete []text;
}
- delete []text;
}
void Editor::CancelModes() {
@@ -5098,7 +5079,7 @@ void Editor::Indent(bool forwards) {
int lineCurrentPos = pdoc->LineFromPosition(caretPosition);
if (lineOfAnchor == lineCurrentPos) {
if (forwards) {
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
pdoc->DeleteChars(sel.Range(r).Start().Position(), sel.Range(r).Length());
caretPosition = sel.Range(r).caret.Position();
if (pdoc->GetColumn(caretPosition) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) &&
@@ -5122,16 +5103,14 @@ void Editor::Indent(bool forwards) {
sel.Range(r) = SelectionRange(caretPosition+numSpaces);
}
}
- pdoc->EndUndoAction();
} else {
if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) &&
pdoc->tabIndents) {
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
int indentation = pdoc->GetLineIndentation(lineCurrentPos);
int indentationStep = pdoc->IndentSize();
pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
SetEmptySelection(pdoc->GetLineIndentPosition(lineCurrentPos));
- pdoc->EndUndoAction();
} else {
int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) *
pdoc->tabInChars;
@@ -5151,9 +5130,10 @@ void Editor::Indent(bool forwards) {
int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos);
if (pdoc->LineStart(lineBottomSel) == sel.Range(r).anchor.Position() || pdoc->LineStart(lineBottomSel) == caretPosition)
lineBottomSel--; // If not selecting any characters on a line, do not indent
- pdoc->BeginUndoAction();
- pdoc->Indent(forwards, lineBottomSel, lineTopSel);
- pdoc->EndUndoAction();
+ {
+ UndoGroup ug(pdoc);
+ pdoc->Indent(forwards, lineBottomSel, lineTopSel);
+ }
if (lineOfAnchor < lineCurrentPos) {
if (currentPosPosOnLine == 0)
sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
@@ -5424,7 +5404,7 @@ void Editor::DropAt(SelectionPosition position, const char *value, bool moving,
SelectionPosition selStart = SelectionStart();
SelectionPosition selEnd = SelectionEnd();
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
SelectionPosition positionAfterDeletion = position;
if ((inDragDrop == ddDragging) && moving) {
@@ -5450,7 +5430,6 @@ void Editor::DropAt(SelectionPosition position, const char *value, bool moving,
if (rectangular) {
PasteRectangular(position, value, istrlen(value));
- pdoc->EndUndoAction();
// Should try to select new rectangle but it may not be a rectangle now so just select the drop position
SetEmptySelection(position);
} else {
@@ -5461,7 +5440,6 @@ void Editor::DropAt(SelectionPosition position, const char *value, bool moving,
posAfterInsertion.Add(istrlen(value));
SetSelection(posAfterInsertion, position);
}
- pdoc->EndUndoAction();
}
} else if (inDragDrop == ddDragging) {
SetEmptySelection(position);
@@ -6176,13 +6154,12 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
}
int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) {
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
if (length == -1)
length = istrlen(text);
if (replacePatterns) {
text = pdoc->SubstituteByPosition(text, &length);
if (!text) {
- pdoc->EndUndoAction();
return 0;
}
}
@@ -6191,7 +6168,6 @@ int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) {
targetEnd = targetStart;
pdoc->InsertString(targetStart, text, length);
targetEnd = targetStart + length;
- pdoc->EndUndoAction();
return length;
}
@@ -6354,11 +6330,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_SETTEXT: {
if (lParam == 0)
return 0;
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
pdoc->DeleteChars(0, pdoc->Length());
SetEmptySelection(0);
pdoc->InsertCString(0, CharPtrFromSPtr(lParam));
- pdoc->EndUndoAction();
return 1;
}
@@ -6507,11 +6482,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_REPLACESEL: {
if (lParam == 0)
return 0;
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
ClearSelection();
char *replacement = CharPtrFromSPtr(lParam);
pdoc->InsertCString(sel.MainCaret(), replacement);
- pdoc->EndUndoAction();
SetEmptySelection(sel.MainCaret() + istrlen(replacement));
EnsureCaretVisible();
}
diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx
index 0a8912c7b..0d25b248c 100644
--- a/src/ScintillaBase.cxx
+++ b/src/ScintillaBase.cxx
@@ -373,7 +373,7 @@ void ScintillaBase::AutoCompleteCompleted() {
endPos = pdoc->ExtendWordSelect(endPos, 1, true);
if (endPos < firstPos)
return;
- pdoc->BeginUndoAction();
+ UndoGroup ug(pdoc);
if (endPos != firstPos) {
pdoc->DeleteChars(firstPos, endPos - firstPos);
}
@@ -383,7 +383,6 @@ void ScintillaBase::AutoCompleteCompleted() {
pdoc->InsertCString(firstPos, piece.c_str());
SetEmptySelection(firstPos + static_cast<int>(piece.length()));
}
- pdoc->EndUndoAction();
}
int ScintillaBase::AutoCompleteGetCurrent() {