diff options
| -rw-r--r-- | doc/ScintillaRelated.html | 5 | ||||
| -rw-r--r-- | include/SciLexer.h | 1 | ||||
| -rw-r--r-- | include/Scintilla.h | 5 | ||||
| -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 | 
12 files changed, 428 insertions, 170 deletions
| diff --git a/doc/ScintillaRelated.html b/doc/ScintillaRelated.html index 2aa6e0f65..e56fd1690 100644 --- a/doc/ScintillaRelated.html +++ b/doc/ScintillaRelated.html @@ -81,9 +81,8 @@         Development Tools      </h3>      <p> -       Scintilla and SciTE were developed using the Mingw32 version of GCC. <a -      href="http://www.xraylith.wisc.edu/~khan/software/gnu-win32/"> Mumit Khan's GNU Win32 -      site</a> is a good starting point for GCC and Mingw32 information and downloads. +       Scintilla and SciTE were developed using the  +       <a href="http://www.mingw.org/">Mingw version of GCC</a>.      </p>      <p>         <a href="http://astyle.sourceforge.net/">AStyle</a> is a source code formatter for C++ and diff --git a/include/SciLexer.h b/include/SciLexer.h index f3f97b7ae..1e6542219 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -52,6 +52,7 @@  #define SCE_C_OPERATOR 10  #define SCE_C_IDENTIFIER 11  #define SCE_C_STRINGEOL 12 +#define SCE_C_UUID 13  // Lexical states for SCLEX_HTML, SCLEX_xML  #define SCE_H_DEFAULT 0 diff --git a/include/Scintilla.h b/include/Scintilla.h index a320fccbd..822b2ea9d 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -279,6 +279,11 @@ extern "C" {  #define SCI_ZOOMOUT SCI_START + 334  #define SCI_DELWORDLEFT SCI_START + 335  #define SCI_DELWORDRIGHT SCI_START + 336 +#define SCI_LINECUT SCI_START + 337 +#define SCI_LINEDELETE SCI_START + 338 +#define SCI_LINETRANSPOSE SCI_START + 339 +#define SCI_LOWERCASE SCI_START + 340 +#define SCI_UPPERCASE SCI_START + 341  #define SCI_LINELENGTH SCI_START + 350  #define SCI_BRACEHIGHLIGHT SCI_START + 351 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 == '*') { | 
