diff options
author | nyamatongwe <devnull@localhost> | 2000-03-22 12:16:54 +0000 |
---|---|---|
committer | nyamatongwe <devnull@localhost> | 2000-03-22 12:16:54 +0000 |
commit | ff69e140ac7634ab8ec4365f97f0adae27692b53 (patch) | |
tree | 7c44f53d74ea3a4303084e24b5a40e8139bc9a01 /src | |
parent | 06795dc71160ed0b5ff3a2919e6fd9ef7adc8a4c (diff) | |
download | scintilla-mirror-ff69e140ac7634ab8ec4365f97f0adae27692b53.tar.gz |
Split UndoHistory out of CellBuffer.
Fixed coalescing of nodes in the undo history.
Added LineCut, LineDelete, LineTranspose, UpperCase and LowerCase keyboard
commands and added keys for them.
Added UUID lexical class to CPP lexer.
Diffstat (limited to 'src')
-rw-r--r-- | src/CellBuffer.cxx | 316 | ||||
-rw-r--r-- | src/CellBuffer.h | 49 | ||||
-rw-r--r-- | src/Document.cxx | 48 | ||||
-rw-r--r-- | src/Document.h | 5 | ||||
-rw-r--r-- | src/Editor.cxx | 98 | ||||
-rw-r--r-- | src/Editor.h | 2 | ||||
-rw-r--r-- | src/KeyMap.cxx | 45 | ||||
-rw-r--r-- | src/KeyMap.h | 1 | ||||
-rw-r--r-- | src/LexCPP.cxx | 23 |
9 files changed, 420 insertions, 167 deletions
diff --git a/src/CellBuffer.cxx b/src/CellBuffer.cxx index 777688511..4d667dcf4 100644 --- a/src/CellBuffer.cxx +++ b/src/CellBuffer.cxx @@ -344,31 +344,199 @@ void Action::Grab(Action *source) { source->lenData = 0; } -CellBuffer::CellBuffer(int initialLength) { - body = new char[initialLength]; - size = initialLength; - length = 0; - part1len = 0; - gaplen = initialLength; - part2body = body + gaplen; - readOnly = false; +// 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; - collectingUndo = undoCollectAutoStart; undoSequenceDepth = 0; savePoint = 0; actions[currentAction].Create(startAction); } +UndoHistory::~UndoHistory() { + delete []actions; + actions = 0; +} + +void UndoHistory::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 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 (0 == undoSequenceDepth) { + // Top level actions may not always be coalesced + if (currentAction >= 2) { + 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 == removeAction) && + ((position + lengthData * 2) != actPrevious.position)) { + // Removals must be at same position to coalesce + currentAction++; + } else if ((at == insertAction) && + (position != (actPrevious.position + actPrevious.lenData*2))) { + // Insertions must be immediately after to coalesce + currentAction++; + } else { + Platform::DebugPrintf("action coalesced\n"); + } + } else { + currentAction++; + } + } + actions[currentAction].Create(at, position, data, lengthData); + //if ((collectingUndo == undoCollectAutoStart) && (0 == undoSequenceDepth)) { + 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; + } + } + undoSequenceDepth++; +} + +void UndoHistory::EndUndoAction() { + EnsureUndoRoom(); + undoSequenceDepth--; + if (0 == undoSequenceDepth) { + if (actions[currentAction].at != startAction) { + currentAction++; + actions[currentAction].Create(startAction); + maxAction = currentAction; + } + } +} + +void UndoHistory::DropUndoSequence() { + undoSequenceDepth = 0; +} + +void UndoHistory::DeleteUndoHistory() { + for (int i = 1; i < maxAction; i++) + actions[i].Destroy(); + maxAction = 0; + currentAction = 0; + 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::UndoStep() { + return actions[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::RedoStep() { + return actions[currentAction++]; +} + +CellBuffer::CellBuffer(int initialLength) { + body = new char[initialLength]; + size = initialLength; + length = 0; + part1len = 0; + gaplen = initialLength; + part2body = body + gaplen; + readOnly = false; + collectingUndo = undoCollectAutoStart; +} + CellBuffer::~CellBuffer() { delete []body; body = 0; - delete []actions; - actions = 0; } void CellBuffer::GapTo(int position) { @@ -486,7 +654,7 @@ const char *CellBuffer::InsertString(int position, char *s, int insertLength) { for (int i = 0; i < insertLength / 2; i++) { data[i] = s[i * 2]; } - AppendAction(insertAction, position, data, insertLength / 2); + uh.AppendAction(insertAction, position, data, insertLength / 2); } BasicInsertString(position, s, insertLength); @@ -525,48 +693,6 @@ bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mas 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 char *data = 0; @@ -577,7 +703,7 @@ const char *CellBuffer::DeleteChars(int position, int deleteLength) { for (int i = 0; i < deleteLength / 2; i++) { data[i] = ByteAt(position + i * 2); } - AppendAction(removeAction, position, data, deleteLength / 2); + uh.AppendAction(removeAction, position, data, deleteLength / 2); } BasicDeleteChars(position, deleteLength); @@ -616,11 +742,11 @@ void CellBuffer::SetReadOnly(bool set) { } void CellBuffer::SetSavePoint() { - savePoint = currentAction; + uh.SetSavePoint(); } bool CellBuffer::IsSavePoint() { - return savePoint == currentAction; + return uh.IsSavePoint(); } int CellBuffer::AddMark(int line, int markerNum) { @@ -659,7 +785,7 @@ int CellBuffer::LineFromHandle(int markerHandle) { // Without undo void CellBuffer::BasicInsertString(int position, char *s, int insertLength) { - //Platform::DebugPrintf("Inserting at %d for %d\n", position, insertLength); + Platform::DebugPrintf("Inserting at %d for %d\n", position, insertLength); if (insertLength == 0) return; RoomFor(insertLength); @@ -719,7 +845,7 @@ void CellBuffer::BasicInsertString(int position, char *s, int insertLength) { } void CellBuffer::BasicDeleteChars(int position, int deleteLength) { - //Platform::DebugPrintf("Deleting at %d for %d\n", position, deleteLength); + Platform::DebugPrintf("Deleting at %d for %d\n", position, deleteLength); if (deleteLength == 0) return; @@ -792,7 +918,7 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) { undoCollectionType CellBuffer::SetUndoCollection(undoCollectionType collectUndo) { collectingUndo = collectUndo; - undoSequenceDepth = 0; + uh.DropUndoSequence(); return collectingUndo; } @@ -800,69 +926,28 @@ bool CellBuffer::IsCollectingUndo() { 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 (!readOnly) && (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::UndoStep() { - const Action &actionStep = actions[currentAction]; + const Action &actionStep = uh.UndoStep(); if (actionStep.at == insertAction) { BasicDeleteChars(actionStep.position, actionStep.lenData*2); } else if (actionStep.at == removeAction) { @@ -874,29 +959,19 @@ const Action &CellBuffer::UndoStep() { BasicInsertString(actionStep.position, styledData, actionStep.lenData*2); delete []styledData; } - currentAction--; return actionStep; } bool CellBuffer::CanRedo() { - return (!readOnly) && (maxAction > currentAction); + return (!readOnly) && (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::RedoStep() { - const Action &actionStep = actions[currentAction]; + const Action &actionStep = uh.RedoStep(); if (actionStep.at == insertAction) { char *styledData = new char[actionStep.lenData * 2]; for (int i = 0; i < actionStep.lenData; i++) { @@ -908,7 +983,6 @@ const Action &CellBuffer::RedoStep() { } else if (actionStep.at == removeAction) { BasicDeleteChars(actionStep.position, actionStep.lenData*2); } - currentAction++; return actionStep; } diff --git a/src/CellBuffer.h b/src/CellBuffer.h index 5fbe2ea8a..6e052077e 100644 --- a/src/CellBuffer.h +++ b/src/CellBuffer.h @@ -89,6 +89,42 @@ public: enum undoCollectionType { undoCollectNone, undoCollectAutoStart, undoCollectManualStart }; +class UndoHistory { + Action *actions; + int lenActions; + int maxAction; + int currentAction; + int undoSequenceDepth; + int savePoint; + + void EnsureUndoRoom(); + +public: + UndoHistory(); + ~UndoHistory(); + + void AppendAction(actionType at, int position, char *data, int length); + + void BeginUndoAction(); + void EndUndoAction(); + void DropUndoSequence(); + void DeleteUndoHistory(); + + // The save point is a marker in the undo stack where the container has stated that + // the buffer was saved. Undo and redo can move over the save point. + void SetSavePoint(); + bool IsSavePoint() const; + + // To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is + // called that many times. Similarly for redo. + bool CanUndo() const; + int StartUndo(); + const Action &UndoStep(); + bool CanRedo() const; + int StartRedo(); + const Action &RedoStep(); +}; + // Holder for an expandable array of characters that supports undo and line markers // Based on article "Data Structures in a Bit-Mapped Text Editor" // by Wilfred J. Hansen, Byte January 1987, page 183 @@ -102,13 +138,8 @@ private: char *part2body; bool readOnly; - Action *actions; - int lenActions; - int maxAction; - int currentAction; undoCollectionType collectingUndo; - int undoSequenceDepth; - int savePoint; + UndoHistory uh; LineVector lv; @@ -117,9 +148,6 @@ private: void GapTo(int position); void RoomFor(int insertionLength); - void EnsureUndoRoom(); - void AppendAction(actionType at, int position, char *data, int length); - inline char ByteAt(int position); void SetByteAt(int position, char ch); @@ -170,12 +198,11 @@ public: undoCollectionType SetUndoCollection(undoCollectionType collectUndo); bool IsCollectingUndo(); - void AppendUndoStartAction(); void BeginUndoAction(); void EndUndoAction(); void DeleteUndoHistory(); - // To perform an undo, StartUndo is called to retreive the number of steps, then UndoStep is + // To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is // called that many times. Similarly for redo. bool CanUndo(); int StartUndo(); diff --git a/src/Document.cxx b/src/Document.cxx index b50b9691a..bfb52d36e 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -94,22 +94,25 @@ int Document::LineStart(int line) { return cb.LineStart(line); } -int Document::LineFromPosition(int pos) { - return cb.LineFromPosition(pos); -} - -int Document::LineEndPosition(int position) { - int line = LineFromPosition(position); +int Document::LineEnd(int line) { if (line == LinesTotal() - 1) { - position = LineStart(line + 1); + return LineStart(line + 1); } else { - position = LineStart(line + 1) - 1; + int position = LineStart(line + 1) - 1; // When line terminator is CR+LF, may need to go back one more if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) { position--; } + return position; } - return position; +} + +int Document::LineFromPosition(int pos) { + return cb.LineFromPosition(pos); +} + +int Document::LineEndPosition(int position) { + return LineEnd(LineFromPosition(position)); } int Document::VCHomePosition(int position) { @@ -335,6 +338,7 @@ int Document::Undo() { enteredCount++; bool startSavePoint = cb.IsSavePoint(); int steps = cb.StartUndo(); + Platform::DebugPrintf("Steps=%d\n", steps); for (int step=0; step<steps; step++) { int prevLinesTotal = LinesTotal(); const Action &action = cb.UndoStep(); @@ -345,9 +349,11 @@ int Document::Undo() { int modFlags = SC_PERFORMED_UNDO; // With undo, an insertion action becomes a deletion notification if (action.at == removeAction) { + Platform::DebugPrintf("Insert of %d\n", action.lenData); newPos += action.lenData; modFlags |= SC_MOD_INSERTTEXT; } else { + Platform::DebugPrintf("Remove of %d\n", action.lenData); modFlags |= SC_MOD_DELETETEXT; } if (step == steps-1) @@ -423,6 +429,11 @@ void Document::InsertString(int position, const char *s, int insertLength) { } } +void Document::ChangeChar(int pos, char ch) { + DeleteChars(pos, 1); + InsertChar(pos, ch); +} + void Document::DelChar(int pos) { if (IsCrLf(pos)) { DeleteChars(pos, 2); @@ -633,6 +644,25 @@ int Document::LinesTotal() { return cb.Lines(); } +void Document::ChangeCase(Range r, bool makeUpperCase) { + for (int pos=r.start; pos<r.end; pos++) { + char ch = CharAt(pos); + if (dbcsCodePage && IsDBCS(pos)) { + pos++; + } else { + if (makeUpperCase) { + if (islower(ch)) { + ChangeChar(pos, toupper(ch)); + } + } else { + if (isupper(ch)) { + ChangeChar(pos, tolower(ch)); + } + } + } + } +} + void Document::SetWordChars(unsigned char *chars) { int ch; for (ch = 0; ch < 256; ch++) { diff --git a/src/Document.h b/src/Document.h index 59215c75a..4c212b7bd 100644 --- a/src/Document.h +++ b/src/Document.h @@ -111,7 +111,6 @@ public: undoCollectionType SetUndoCollection(undoCollectionType collectUndo) { return cb.SetUndoCollection(collectUndo); } - void AppendUndoStartAction() { cb.AppendUndoStartAction(); } void BeginUndoAction() { cb.BeginUndoAction(); } void EndUndoAction() { cb.EndUndoAction(); } void SetSavePoint(); @@ -123,6 +122,7 @@ public: void InsertChar(int pos, char ch); void InsertString(int position, const char *s); void InsertString(int position, const char *s, int insertLength); + void ChangeChar(int pos, char ch); void DelChar(int pos); int DelCharBack(int pos); @@ -138,6 +138,7 @@ public: void DeleteAllMarks(int markerNum); int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); } int LineStart(int line); + int LineEnd(int line); int LineEndPosition(int position); int VCHomePosition(int position); @@ -154,6 +155,8 @@ public: long FindText(WORD iMessage,WPARAM wParam,LPARAM lParam); int LinesTotal(); + void ChangeCase(Range r, bool makeUpperCase); + void SetWordChars(unsigned char *chars); void SetStylingBits(int bits); void StartStyling(int position, char mask); diff --git a/src/Editor.cxx b/src/Editor.cxx index 8550286ac..226184db2 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -1700,6 +1700,11 @@ void Editor::NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam) { case SCI_VCHOMEEXTEND: case SCI_DELWORDLEFT: case SCI_DELWORDRIGHT: + case SCI_LINECUT: + case SCI_LINEDELETE: + case SCI_LINETRANSPOSE: + case SCI_LOWERCASE: + case SCI_UPPERCASE: break; // Filter out all others (display changes, etc) @@ -1735,6 +1740,60 @@ void Editor::PageMove(int direction, bool extend) { } } +void Editor::ChangeCaseOfSelection(bool makeUpperCase) { + pdoc->BeginUndoAction(); + int startCurrent = currentPos; + int startAnchor = anchor; + if (selType == selRectangle) { + int lineStart = pdoc->LineFromPosition(SelectionStart()); + int lineEnd = pdoc->LineFromPosition(SelectionEnd()); + for (int line=lineStart; line <= lineEnd; line++) { + pdoc->ChangeCase( + Range(SelectionStart(line), SelectionEnd(line)), + makeUpperCase); + } + // Would be nicer to keep the rectangular selection but this is complex + selType = selStream; + SetSelection(startCurrent, startCurrent); + } else { + pdoc->ChangeCase(Range(SelectionStart(), SelectionEnd()), + makeUpperCase); + SetSelection(startCurrent, startAnchor); + } + pdoc->EndUndoAction(); +} + + +void Editor::LineTranspose() { + int line = pdoc->LineFromPosition(currentPos); + if (line > 0) { + int startPrev = pdoc->LineStart(line-1); + int endPrev = pdoc->LineEnd(line-1); + int start = pdoc->LineStart(line); + int end = pdoc->LineEnd(line); + int startNext = pdoc->LineStart(line+1); + if (end < pdoc->Length()) { + end = startNext; + char *thisLine = CopyRange(start, end); + pdoc->DeleteChars(start, end-start); + pdoc->InsertString(startPrev, thisLine, end-start); + MovePositionTo(startPrev+end-start); + delete []thisLine; + } else { + // Last line so line has no line end + char *thisLine = CopyRange(start, end); + char *prevEnd = CopyRange(endPrev, start); + pdoc->DeleteChars(endPrev, end-endPrev); + pdoc->InsertString(startPrev, thisLine, end-start); + pdoc->InsertString(startPrev + end-start, prevEnd, start-endPrev); + MovePositionTo(startPrev + end-endPrev); + delete []thisLine; + delete []prevEnd; + } + + } +} + int Editor::KeyCommand(UINT iMessage) { Point pt = LocationFromPosition(currentPos); @@ -1910,6 +1969,37 @@ int Editor::KeyCommand(UINT iMessage) { MovePositionTo(currentPos); } break; + case SCI_LINECUT: { + int lineStart = pdoc->LineFromPosition(currentPos); + int lineEnd = pdoc->LineFromPosition(anchor); + if (lineStart > lineEnd) { + int t = lineEnd; + lineEnd = lineStart; + lineStart = t; + } + int start = pdoc->LineStart(lineStart); + int end = pdoc->LineStart(lineEnd+1); + SetSelection(start,end); + Cut(); + } + break; + case SCI_LINEDELETE: { + int line = pdoc->LineFromPosition(currentPos); + int start = pdoc->LineStart(line); + int end = pdoc->LineStart(line+1); + pdoc->DeleteChars(start, end-start); + MovePositionTo(start); + } + break; + case SCI_LINETRANSPOSE: + LineTranspose(); + break; + case SCI_LOWERCASE: + ChangeCaseOfSelection(false); + break; + case SCI_UPPERCASE: + ChangeCaseOfSelection(true); + break; } return 0; } @@ -3094,7 +3184,8 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { #ifdef INCLUDE_DEPRECATED_FEATURES case SCI_APPENDUNDOSTARTACTION: - pdoc->AppendUndoStartAction(); + // Not just deprecated - now dead + //pdoc->AppendUndoStartAction(); return 0; #endif @@ -3649,6 +3740,11 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { case SCI_ZOOMOUT: case SCI_DELWORDLEFT: case SCI_DELWORDRIGHT: + case SCI_LINECUT: + case SCI_LINEDELETE: + case SCI_LINETRANSPOSE: + case SCI_LOWERCASE: + case SCI_UPPERCASE: return KeyCommand(iMessage); case SCI_BRACEHIGHLIGHT: diff --git a/src/Editor.h b/src/Editor.h index 16bcd4b22..d1281be5a 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -228,6 +228,8 @@ protected: // ScintillaBase subclass needs access to much of Editor #endif void PageMove(int direction, bool extend=false); + void ChangeCaseOfSelection(bool makeUpperCase); + void LineTranspose(); virtual int KeyCommand(UINT iMessage); virtual int KeyDefault(int /* key */, int /*modifiers*/); int KeyDown(int key, bool shift, bool ctrl, bool alt); diff --git a/src/KeyMap.cxx b/src/KeyMap.cxx index f339cd275..9ab9694df 100644 --- a/src/KeyMap.cxx +++ b/src/KeyMap.cxx @@ -61,36 +61,36 @@ UINT KeyMap::Find(int key, int modifiers) { } KeyToCommand KeyMap::MapDefault[] = { - VK_DOWN, SCI_NORM, SCI_LINEDOWN, - VK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND, - VK_UP, SCI_NORM, SCI_LINEUP, - VK_UP, SCI_SHIFT, SCI_LINEUPEXTEND, + VK_DOWN, SCI_NORM, SCI_LINEDOWN, + VK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND, + VK_UP, SCI_NORM, SCI_LINEUP, + VK_UP, SCI_SHIFT, SCI_LINEUPEXTEND, VK_LEFT, SCI_NORM, SCI_CHARLEFT, VK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND, VK_LEFT, SCI_CTRL, SCI_WORDLEFT, VK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND, - VK_RIGHT, SCI_NORM, SCI_CHARRIGHT, - VK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND, - VK_RIGHT, SCI_CTRL, SCI_WORDRIGHT, - VK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND, - VK_HOME, SCI_NORM, SCI_VCHOME, - VK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND, - VK_HOME, SCI_CTRL, SCI_DOCUMENTSTART, - VK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND, + VK_RIGHT, SCI_NORM, SCI_CHARRIGHT, + VK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND, + VK_RIGHT, SCI_CTRL, SCI_WORDRIGHT, + VK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND, + VK_HOME, SCI_NORM, SCI_VCHOME, + VK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND, + VK_HOME, SCI_CTRL, SCI_DOCUMENTSTART, + VK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND, VK_END, SCI_NORM, SCI_LINEEND, VK_END, SCI_SHIFT, SCI_LINEENDEXTEND, VK_END, SCI_CTRL, SCI_DOCUMENTEND, VK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND, - VK_PRIOR, SCI_NORM, SCI_PAGEUP, - VK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND, - VK_NEXT, SCI_NORM, SCI_PAGEDOWN, - VK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND, + VK_PRIOR, SCI_NORM, SCI_PAGEUP, + VK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND, + VK_NEXT, SCI_NORM, SCI_PAGEDOWN, + VK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND, VK_DELETE, SCI_NORM, WM_CLEAR, VK_DELETE, SCI_SHIFT, WM_CUT, VK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT, - VK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE, - VK_INSERT, SCI_SHIFT, WM_PASTE, - VK_INSERT, SCI_CTRL, WM_COPY, + VK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE, + VK_INSERT, SCI_SHIFT, WM_PASTE, + VK_INSERT, SCI_CTRL, WM_COPY, VK_ESCAPE, SCI_NORM, SCI_CANCEL, VK_BACK, SCI_NORM, SCI_DELETEBACK, VK_BACK, SCI_CTRL, SCI_DELWORDLEFT, @@ -103,9 +103,14 @@ KeyToCommand KeyMap::MapDefault[] = { VK_TAB, SCI_NORM, SCI_TAB, VK_TAB, SCI_SHIFT, SCI_BACKTAB, VK_RETURN, SCI_NORM, SCI_NEWLINE, - 'L', SCI_CTRL, SCI_FORMFEED, VK_ADD, SCI_CTRL, SCI_ZOOMIN, VK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT, + //'L', SCI_CTRL, SCI_FORMFEED, + 'L', SCI_CTRL, SCI_LINECUT, + 'L', SCI_CSHIFT, SCI_LINEDELETE, + 'T', SCI_CTRL, SCI_LINETRANSPOSE, + 'U', SCI_CTRL, SCI_LOWERCASE, + 'U', SCI_CSHIFT, SCI_UPPERCASE, 0,0,0, }; diff --git a/src/KeyMap.h b/src/KeyMap.h index 814f3aa3b..bc435e197 100644 --- a/src/KeyMap.h +++ b/src/KeyMap.h @@ -11,6 +11,7 @@ #define SCI_CTRL LEFT_CTRL_PRESSED #define SCI_ALT LEFT_ALT_PRESSED #define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT) +#define SCI_ASHIFT (SCI_ALT | SCI_SHIFT) class KeyToCommand { public: diff --git a/src/LexCPP.cxx b/src/LexCPP.cxx index c6d56702e..4afae231f 100644 --- a/src/LexCPP.cxx +++ b/src/LexCPP.cxx @@ -17,9 +17,10 @@ #include "Scintilla.h" #include "SciLexer.h" -static void classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) { +static bool classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) { char s[100]; bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.'); + bool wordIsUUID = false; for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { s[i] = styler[start + i]; s[i + 1] = '\0'; @@ -28,10 +29,13 @@ static void classifyWordCpp(unsigned int start, unsigned int end, WordList &keyw if (wordIsNumber) chAttr = SCE_C_NUMBER; else { - if (keywords.InList(s)) + if (keywords.InList(s)) { chAttr = SCE_C_WORD; + wordIsUUID = strcmp(s, "uuid") == 0; + } } styler.ColourTo(end, chAttr); + return wordIsUUID; } static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], @@ -52,6 +56,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo unsigned int lengthDoc = startPos + length; int visChars = 0; styler.StartSegment(startPos); + bool lastWordWasUUID = false; for (unsigned int i = startPos; i <= lengthDoc; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); @@ -86,7 +91,12 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo if (state == SCE_C_DEFAULT) { if (iswordstart(ch)) { styler.ColourTo(i-1, state); - state = SCE_C_WORD; + if (lastWordWasUUID) { + state = SCE_C_UUID; + lastWordWasUUID = false; + } else { + state = SCE_C_WORD; + } } else if (ch == '/' && chNext == '*') { styler.ColourTo(i-1, state); if (styler.SafeGetCharAt(i + 2) == '*') @@ -114,7 +124,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo } } else if (state == SCE_C_WORD) { if (!iswordchar(ch)) { - classifyWordCpp(styler.GetStartSegment(), i - 1, keywords, styler); + lastWordWasUUID = classifyWordCpp(styler.GetStartSegment(), i - 1, keywords, styler); state = SCE_C_DEFAULT; if (ch == '/' && chNext == '*') { if (styler.SafeGetCharAt(i + 2) == '*') @@ -199,6 +209,11 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo ch = chNext; chNext = styler.SafeGetCharAt(i + 1); } + } else if (state == SCE_C_UUID) { + if (ch == '\r' || ch == '\n' || ch == ')') { + styler.ColourTo(i-1, state); + state = SCE_C_DEFAULT; + } } if (state == SCE_C_DEFAULT) { // One of the above succeeded if (ch == '/' && chNext == '*') { |