mirror of https://github.com/stella-emu/stella.git
added single char aggregation for undos
fixed potential bug when moving cursor one word left
This commit is contained in:
parent
d7171b5260
commit
6c315c76be
|
@ -90,7 +90,7 @@ bool EditableWidget::tryInsertChar(char c, int pos)
|
|||
if(_filter(tolower(c)))
|
||||
{
|
||||
_editString.insert(pos, 1, c);
|
||||
myUndoHandler->doo(_editString);
|
||||
myUndoHandler->doChar(); // aggregate single chars
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -140,7 +140,6 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
|||
{
|
||||
bool shift = StellaModTest::isShift(mod);
|
||||
bool handled = true;
|
||||
bool dirty = true;
|
||||
|
||||
switch(key)
|
||||
{
|
||||
|
@ -154,13 +153,13 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
|||
handled = copySelectedText();
|
||||
break;
|
||||
|
||||
case KBDK_E:
|
||||
if(shift)
|
||||
_selectSize += _caretPos - int(_editString.size());
|
||||
else
|
||||
_selectSize = 0;
|
||||
setCaretPos(int(_editString.size()));
|
||||
break;
|
||||
//case KBDK_E:
|
||||
// if(shift)
|
||||
// _selectSize += _caretPos - int(_editString.size());
|
||||
// else
|
||||
// _selectSize = 0;
|
||||
// setCaretPos(int(_editString.size()));
|
||||
// break;
|
||||
|
||||
case KBDK_D:
|
||||
handled = killChar(+1);
|
||||
|
@ -196,13 +195,29 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
|||
|
||||
case KBDK_Y:
|
||||
case KBDK_Z:
|
||||
{
|
||||
string oldString = _editString;
|
||||
|
||||
myUndoHandler->endChars(_editString);
|
||||
// Reverse Y and Z for QWERTZ keyboards
|
||||
if(key == KBDK_Y != instance().eventHandler().isQwertz())
|
||||
dirty = myUndoHandler->redo(_editString);
|
||||
handled = myUndoHandler->redo(_editString);
|
||||
else
|
||||
dirty = myUndoHandler->undo(_editString);
|
||||
_caretPos = int(_editString.size()); // TODO: put at last difference
|
||||
_selectSize = 0;
|
||||
if(shift)
|
||||
handled = myUndoHandler->redo(_editString);
|
||||
else
|
||||
handled = myUndoHandler->undo(_editString);
|
||||
|
||||
if(handled)
|
||||
{
|
||||
// Put caret at last difference
|
||||
myUndoHandler->lastDiff(_editString, oldString);
|
||||
_caretPos = myUndoHandler->lastDiff(_editString, oldString);
|
||||
_selectSize = 0;
|
||||
sendCommand(EditableWidget::kChangedCmd, key, _id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case KBDK_LEFT:
|
||||
handled = moveWord(-1, shift);
|
||||
|
@ -218,11 +233,13 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
|||
|
||||
default:
|
||||
handled = false;
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
if(dirty)
|
||||
if(handled)
|
||||
{
|
||||
myUndoHandler->endChars(_editString);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
@ -271,7 +288,10 @@ bool EditableWidget::handleShiftKeys(StellaKey key)
|
|||
}
|
||||
|
||||
if(handled)
|
||||
{
|
||||
myUndoHandler->endChars(_editString);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
@ -321,7 +341,7 @@ bool EditableWidget::handleNormalKeys(StellaKey key)
|
|||
break;
|
||||
|
||||
case KBDK_LEFT:
|
||||
if (_selectSize)
|
||||
if(_selectSize)
|
||||
handled = setCaretPos(selectStartPos());
|
||||
else if(_caretPos > 0)
|
||||
handled = setCaretPos(_caretPos - 1);
|
||||
|
@ -348,7 +368,10 @@ bool EditableWidget::handleNormalKeys(StellaKey key)
|
|||
}
|
||||
|
||||
if(handled)
|
||||
{
|
||||
myUndoHandler->endChars(_editString);
|
||||
setDirty();
|
||||
}
|
||||
if(!selectMode)
|
||||
_selectSize = 0;
|
||||
|
||||
|
@ -490,6 +513,7 @@ bool EditableWidget::killChar(int direction, bool addEdit)
|
|||
{
|
||||
if(_caretPos > 0)
|
||||
{
|
||||
myUndoHandler->endChars(_editString);
|
||||
_caretPos--;
|
||||
_editString.erase(_caretPos, 1);
|
||||
handled = true;
|
||||
|
@ -501,6 +525,7 @@ bool EditableWidget::killChar(int direction, bool addEdit)
|
|||
}
|
||||
else if(direction == 1) // Delete next character (delete)
|
||||
{
|
||||
myUndoHandler->endChars(_editString);
|
||||
_editString.erase(_caretPos, 1);
|
||||
handled = true;
|
||||
if(_selectSize > 0)
|
||||
|
@ -616,7 +641,7 @@ bool EditableWidget::moveWord(int direction, bool select)
|
|||
{
|
||||
while (currentPos < int(_editString.size()))
|
||||
{
|
||||
if (_editString[currentPos - 1] == ' ')
|
||||
if (currentPos && _editString[currentPos - 1] == ' ')
|
||||
{
|
||||
if (!space)
|
||||
break;
|
||||
|
@ -677,6 +702,7 @@ bool EditableWidget::killSelectedText(bool addEdit)
|
|||
{
|
||||
if(_selectSize)
|
||||
{
|
||||
myUndoHandler->endChars(_editString);
|
||||
if(_selectSize < 0)
|
||||
{
|
||||
_caretPos += _selectSize;
|
||||
|
@ -694,16 +720,7 @@ bool EditableWidget::killSelectedText(bool addEdit)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool EditableWidget::cutSelectedText()
|
||||
{
|
||||
string selected = selectString();
|
||||
|
||||
// only cut and copy if anything is selected, else keep old cut text
|
||||
if(!selected.empty())
|
||||
{
|
||||
instance().eventHandler().copyText(selected);
|
||||
killSelectedText();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return copySelectedText() && killSelectedText();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -726,6 +743,8 @@ bool EditableWidget::pasteSelectedText()
|
|||
bool selected = !selectString().empty();
|
||||
string pasted;
|
||||
|
||||
myUndoHandler->endChars(_editString);
|
||||
|
||||
// retrieve the pasted text
|
||||
instance().eventHandler().pasteText(pasted);
|
||||
// remove the currently selected text
|
||||
|
|
|
@ -21,15 +21,35 @@
|
|||
UndoHandler::UndoHandler(size_t size)
|
||||
: mySize(size)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void UndoHandler::reset()
|
||||
{
|
||||
myBuffer.clear();
|
||||
myCharMode = false;
|
||||
myRedoCount = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void UndoHandler::doChar()
|
||||
{
|
||||
myCharMode = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool UndoHandler::endChars(const string& text)
|
||||
{
|
||||
if(myCharMode)
|
||||
{
|
||||
doo(text);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void UndoHandler::doo(const string& text)
|
||||
{
|
||||
|
@ -43,6 +63,7 @@ void UndoHandler::doo(const string& text)
|
|||
|
||||
// add text to buffer
|
||||
myBuffer.push_front(text);
|
||||
myCharMode = false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -68,3 +89,18 @@ bool UndoHandler::redo(string& text)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 UndoHandler::lastDiff(const string& text, const string& oldText) const
|
||||
{
|
||||
uInt32 pos = uInt32(text.size());
|
||||
|
||||
for(auto itn = text.crbegin(), ito = oldText.crbegin();
|
||||
itn != text.crend() && ito != oldText.crend(); ++itn, ++ito)
|
||||
{
|
||||
if(*itn != *ito)
|
||||
break;
|
||||
pos--;
|
||||
}
|
||||
return uInt32(pos);
|
||||
}
|
|
@ -33,14 +33,31 @@ class UndoHandler
|
|||
UndoHandler(size_t size = 100);
|
||||
~UndoHandler() = default;
|
||||
|
||||
// Reset undo buffer
|
||||
void reset();
|
||||
|
||||
// Add input to undo buffer
|
||||
void doo(const string& text);
|
||||
// Retrieve last input from undo buffer
|
||||
bool undo(string& text);
|
||||
// Retrieve next input from undo buffer
|
||||
bool redo(string& text);
|
||||
|
||||
// Add single char for aggregation
|
||||
void doChar();
|
||||
// Add aggregated single chars to undo buffer
|
||||
bool endChars(const string& text);
|
||||
|
||||
// Get index into text of last different character
|
||||
uInt32 lastDiff(const string& text, const string& oldText) const;
|
||||
|
||||
private:
|
||||
std::deque<string> myBuffer;
|
||||
// Undo buffer size
|
||||
size_t mySize{0};
|
||||
// Aggregated single chars flag
|
||||
bool myCharMode{false};
|
||||
// Number of chars available for redo
|
||||
uInt32 myRedoCount{0};
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue