[Scummvm-git-logs] scummvm master -> e101f5397c264b54b88a6fdcb3dba502cebf66eb
sev-
noreply at scummvm.org
Wed Mar 1 17:42:41 UTC 2023
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
bd52062fa7 GUI: Make text selectable
8dcf2ec58e GUI: Add selection rendering function to EditTextWidget
e101f5397c GUI: Limit text selection feature for RTL languages
Commit: bd52062fa7dd267b0a927bcf1bc6daa022bfe641
https://github.com/scummvm/scummvm/commit/bd52062fa7dd267b0a927bcf1bc6daa022bfe641
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-01T18:42:34+01:00
Commit Message:
GUI: Make text selectable
Changed paths:
gui/widgets/editable.cpp
gui/widgets/editable.h
diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp
index 61b831216c1..7fa42d7eead 100644
--- a/gui/widgets/editable.cpp
+++ b/gui/widgets/editable.cpp
@@ -30,11 +30,13 @@ namespace GUI {
EditableWidget::EditableWidget(GuiObject *boss, int x, int y, int w, int h, const Common::U32String &tooltip, uint32 cmd)
: Widget(boss, x, y, w, h, tooltip), CommandSender(boss), _cmd(cmd) {
+ setFlags(WIDGET_TRACK_MOUSE);
init();
}
EditableWidget::EditableWidget(GuiObject *boss, const Common::String &name, const Common::U32String &tooltip, uint32 cmd)
: Widget(boss, name, tooltip), CommandSender(boss), _cmd(cmd) {
+ setFlags(WIDGET_TRACK_MOUSE);
init();
}
@@ -47,6 +49,11 @@ void EditableWidget::init() {
_editScrollOffset = 0;
+ _selCaretPos = -1;
+ _selOffset = 0;
+
+ _shiftPressed = _isDragging = false;
+
_align = g_gui.useRTL() ? Graphics::kTextAlignRight : Graphics::kTextAlignLeft;
_drawAlign = _align;
@@ -104,6 +111,92 @@ void EditableWidget::handleTickle() {
}
}
+void EditableWidget::handleMouseDown(int x, int y, int button, int clickCount) {
+ if (!isEnabled())
+ return;
+
+ _isDragging = true;
+ // Select all text incase of double press
+ if (clickCount > 1) {
+ _selCaretPos = 0;
+ setCaretPos(caretVisualPos(_editString.size()));
+ setSelectionOffset(_editString.size() - _selCaretPos);
+ markAsDirty();
+ return;
+ }
+
+ // Clear any selection
+ if (_selOffset != 0 && !_shiftPressed)
+ clearSelection();
+ else if (_shiftPressed && _selCaretPos < 0)
+ _selCaretPos = _caretPos;
+
+ if (g_gui.useRTL()) {
+ x = _w - x;
+ }
+
+ x += _editScrollOffset;
+ int width = 0;
+ if (_drawAlign == Graphics::kTextAlignRight)
+ width = _editScrollOffset + getEditRect().width() - g_gui.getStringWidth(_editString, _font);
+
+ uint i, last = 0;
+ for (i = 0; i < _editString.size(); ++i) {
+ const uint cur = _editString[i];
+ width += g_gui.getCharWidth(cur, _font) + g_gui.getKerningOffset(last, cur, _font);
+ if (width >= x && width > _editScrollOffset)
+ break;
+ last = cur;
+ }
+ setCaretPos(i);
+ if(_selCaretPos >= 0) setSelectionOffset(i - _selCaretPos);
+ markAsDirty();
+}
+
+void EditableWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ if(isEnabled())
+ _isDragging = false;
+}
+
+void EditableWidget::handleMouseMoved(int x, int y, int button) {
+ if(_isDragging && isEnabled()) {
+ if(_selCaretPos < 0)
+ _selCaretPos = _caretPos;
+
+ if (g_gui.useRTL()) {
+ x = _w - x;
+ }
+
+ if (x < 0 && _editScrollOffset > 0) {
+ _editScrollOffset += x;
+ if(_editScrollOffset < 0)
+ _editScrollOffset = 0;
+ }
+
+ x += _editScrollOffset;
+ int width = 0;
+ if (_drawAlign == Graphics::kTextAlignRight)
+ width = _editScrollOffset + getEditRect().width() - g_gui.getStringWidth(_editString, _font);
+ uint i, last = 0;
+ for (i = 0; i < _editString.size(); ++i) {
+ const uint cur = _editString[i];
+ width += g_gui.getCharWidth(cur, _font) + g_gui.getKerningOffset(last, cur, _font);
+ if (width >= x && width > _editScrollOffset)
+ break;
+ last = cur;
+ }
+
+ setCaretPos(i);
+ if(_selCaretPos >= 0) setSelectionOffset(i - _selCaretPos);
+ markAsDirty();
+ }
+}
+
+bool EditableWidget::handleKeyUp(Common::KeyState state) {
+ _shiftPressed = state.hasFlags(Common::KBD_SHIFT);
+ return false;
+}
+
bool EditableWidget::handleKeyDown(Common::KeyState state) {
bool handled = true;
bool dirty = false;
@@ -117,6 +210,8 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
if (_caretVisible)
drawCaret(true);
+ _shiftPressed = state.hasFlags(Common::KBD_SHIFT);
+
// Remap numeric keypad if NUM lock is *not* active.
// This code relies on the fact that the various KEYCODE_KP* values are
// consecutive.
@@ -154,12 +249,24 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_BACKSPACE:
deleteIndex = caretLogicalPos();
- if (deleteIndex > 0) {
+ if (deleteIndex > 0 && _selOffset == 0) {
deleteIndex--;
_editString.deleteChar(deleteIndex);
setCaretPos(caretVisualPos(deleteIndex));
dirty = true;
+ sendCommand(_cmd, 0);
+ } else if (deleteIndex >= 0 && _selOffset != 0) {
+ int selBegin = _selCaretPos;
+ int selEnd = _selCaretPos + _selOffset;
+ if (selBegin > selEnd)
+ SWAP(selBegin, selEnd);
+ _editString.erase(selBegin, selEnd - selBegin);
+ setCaretPos(caretVisualPos(selBegin));
+ _selCaretPos = -1;
+ _selOffset = 0;
+ dirty = true;
+
sendCommand(_cmd, 0);
}
forcecaret = true;
@@ -181,11 +288,23 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_END:
// Move caret to end
setCaretPos(caretVisualPos(_editString.size()));
+ if (state.flags & Common::KBD_SHIFT)
+ setSelectionOffset(_editString.size() - _selCaretPos);
+ else
+ clearSelection();
forcecaret = true;
dirty = true;
break;
case Common::KEYCODE_LEFT:
+ if(state.hasFlags(Common::KBD_SHIFT)) {
+ if(_selCaretPos < 0)
+ _selCaretPos = _caretPos;
+ if(_caretPos > 0)
+ _selOffset--;
+ } else {
+ clearSelection();
+ }
// Move caret one left (if possible)
if (_caretPos > 0) {
dirty = setCaretPos(_caretPos - 1);
@@ -195,6 +314,14 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
break;
case Common::KEYCODE_RIGHT:
+ if(state.hasFlags(Common::KBD_SHIFT)) {
+ if(_selCaretPos < 0)
+ _selCaretPos = _caretPos;
+ if(_selOffset + _selCaretPos < (int)_editString.size())
+ _selOffset++;
+ } else {
+ clearSelection();
+ }
// Move caret one right (if possible)
if (_caretPos < (int)_editString.size()) {
dirty = setCaretPos(_caretPos + 1);
@@ -207,6 +334,10 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_HOME:
// Move caret to start
setCaretPos(caretVisualPos(0));
+ if (state.flags & Common::KBD_SHIFT)
+ setSelectionOffset(0 - _selCaretPos);
+ else
+ clearSelection();
forcecaret = true;
dirty = true;
break;
@@ -229,8 +360,14 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_c:
if (state.flags & Common::KBD_CTRL) {
- if (!getEditString().empty())
- g_system->setTextInClipboard(getEditString());
+ if (!getEditString().empty()) {
+ int selBegin = _selCaretPos;
+ int selEnd = _selCaretPos + _selOffset;
+ if (selBegin > selEnd)
+ SWAP(selBegin, selEnd);
+ const Common::U32String selected(getEditString().begin() + selBegin, getEditString().begin() + selEnd);
+ g_system->setTextInClipboard(selected);
+ }
} else {
defaultKeyDownHandler(state, dirty, forcecaret, handled);
}
@@ -262,6 +399,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
dirty = setCaretPos(_editString.size());
forcecaret = true;
}
+ clearSelection();
break;
}
#endif
@@ -280,12 +418,27 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
}
void EditableWidget::defaultKeyDownHandler(Common::KeyState &state, bool &dirty, bool &forcecaret, bool &handled) {
- const int logicalPosition = caretLogicalPos();
- if (tryInsertChar(state.ascii, logicalPosition)) {
- setCaretPos(caretVisualPos(logicalPosition + 1));
+ if (isCharAllowed(state.ascii)) {
+ // Incase of a selection, replace the selection with the character
+ if (_selCaretPos >= 0) {
+ int selBegin = _selCaretPos;
+ int selEnd = _selCaretPos + _selOffset;
+ if (selBegin > selEnd)
+ SWAP(selBegin, selEnd);
+ _editString.replace(selBegin, selEnd - selBegin, Common::U32String(state.ascii));
+ if(_editString.size() > 0)
+ selBegin++;
+ setCaretPos(caretVisualPos(selBegin));
+ _selCaretPos = -1;
+ _selOffset = 0;
+ } else {
+ // Insert char normally at caretPos
+ const int logicalPosition = caretLogicalPos();
+ _editString.insertChar(state.ascii, logicalPosition);
+ setCaretPos(caretVisualPos(logicalPosition + 1));
+ }
dirty = true;
forcecaret = true;
-
sendCommand(_cmd, 0);
} else {
handled = false;
@@ -298,6 +451,12 @@ int EditableWidget::getCaretOffset() const {
return g_gui.getStringWidth(substr, _font) - _editScrollOffset;
}
+int EditableWidget::getSelectionCarretOffset() const {
+ Common::UnicodeBiDiText utxt(_editString);
+ Common::U32String substr(utxt.visual.begin(), utxt.visual.begin() + _selCaretPos);
+ return g_gui.getStringWidth(substr, _font) - _editScrollOffset;
+}
+
void EditableWidget::drawCaret(bool erase) {
// Only draw if item is visible
if (!isVisible() || !_boss->isVisible())
@@ -359,6 +518,10 @@ void EditableWidget::drawCaret(bool erase) {
// EditTextWidget uses that but not ListWidget. Thus, one should check
// whether we can unify the drawing in the text area first to avoid
// possible glitches due to different methods used.
+ if (_selOffset < 0)
+ _inversion = ThemeEngine::kTextInversionFocus;
+ else
+ _inversion = ThemeEngine::kTextInversionNone;
width = MIN(editRect.width() - caretOffset, width);
if (width > 0) {
g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character,
@@ -410,4 +573,14 @@ void EditableWidget::makeCaretVisible() {
drawCaret(false);
}
+void EditableWidget::clearSelection() {
+ _selCaretPos = -1;
+ _selOffset = 0;
+ markAsDirty();
+}
+
+void EditableWidget::setSelectionOffset(int newOffset) {
+ _selOffset = newOffset;
+}
+
} // End of namespace GUI
diff --git a/gui/widgets/editable.h b/gui/widgets/editable.h
index bdc9213d553..8c43347b66e 100644
--- a/gui/widgets/editable.h
+++ b/gui/widgets/editable.h
@@ -52,6 +52,12 @@ protected:
int _editScrollOffset;
+ int _selCaretPos;
+ int _selOffset;
+ bool _shiftPressed;
+ bool _isDragging;
+ bool _disableSelection;
+
Graphics::TextAlign _align;
Graphics::TextAlign _drawAlign;
@@ -70,10 +76,15 @@ public:
virtual const Common::U32String &getEditString() const { return _editString; }
void handleTickle() override;
+ void handleMouseDown(int x, int y, int button, int clickCount) override;
+ void handleMouseUp(int x, int y, int button, int clickCount) override;
+ void handleMouseMoved(int x, int y, int button) override;
bool handleKeyDown(Common::KeyState state) override;
+ bool handleKeyUp(Common::KeyState state) override;
void reflowLayout() override;
bool setCaretPos(int newPos);
+ void setSelectionOffset(int newOffset);
protected:
virtual void startEditMode() = 0;
@@ -86,6 +97,7 @@ protected:
*/
virtual Common::Rect getEditRect() const = 0;
virtual int getCaretOffset() const;
+ virtual int getSelectionCarretOffset() const;
void drawCaret(bool erase);
bool adjustOffset();
void makeCaretVisible();
@@ -99,6 +111,8 @@ protected:
int caretVisualPos(int logicalPos);
int caretLogicalPos() const;
+
+ void clearSelection();
};
} // End of namespace GUI
Commit: 8dcf2ec58eaff516e396cd96cb5688c49f7607cf
https://github.com/scummvm/scummvm/commit/8dcf2ec58eaff516e396cd96cb5688c49f7607cf
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-01T18:42:34+01:00
Commit Message:
GUI: Add selection rendering function to EditTextWidget
This code has been written by @sev-
TODOs:
1. Investigate and fix characters jumping/shaking during selection.
2. Make code compatible with RTL languages such as hebrew.
Changed paths:
gui/widgets/edittext.cpp
gui/widgets/edittext.h
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index 9ed0f984367..1df81800d4b 100644
--- a/gui/widgets/edittext.cpp
+++ b/gui/widgets/edittext.cpp
@@ -20,6 +20,7 @@
*/
#include "common/system.h"
+#include "common/unicode-bidi.h"
#include "gui/widgets/edittext.h"
#include "gui/gui-manager.h"
@@ -46,6 +47,7 @@ EditTextWidget::EditTextWidget(GuiObject *boss, const Common::String &name, cons
_finishCmd = finishCmd;
_leftPadding = _rightPadding = 0;
+ _shiftPressed = _isDragging = false;
setEditString(text);
setFontStyle(font);
@@ -63,38 +65,6 @@ void EditTextWidget::reflowLayout() {
EditableWidget::reflowLayout();
}
-void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
- if (!isEnabled())
- return;
-
- // First remove caret
- if (_caretVisible)
- drawCaret(true);
-
- if (g_gui.useRTL()) {
- x = _w - x;
- }
-
- x += _editScrollOffset;
- int width = 0;
- if (_drawAlign == Graphics::kTextAlignRight)
- width = _editScrollOffset + getEditRect().width() - g_gui.getStringWidth(_editString, _font);
-
- uint i;
-
- uint last = 0;
- for (i = 0; i < _editString.size(); ++i) {
- const uint cur = _editString[i];
- width += g_gui.getCharWidth(cur, _font) + g_gui.getKerningOffset(last, cur, _font);
- if (width >= x && width > _editScrollOffset + _leftPadding)
- break;
- last = cur;
- }
-
- setCaretPos(i);
- markAsDirty();
-}
-
void EditTextWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h),
ThemeEngine::kWidgetBackgroundEditText);
@@ -105,10 +75,38 @@ void EditTextWidget::drawWidget() {
drawRect.translate(_x, _y);
setTextDrawableArea(drawRect);
- g_gui.theme()->drawText(
- drawRect,
- _editString, _state, _drawAlign, ThemeEngine::kTextInversionNone,
- -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
+ int x = -_editScrollOffset;
+ int y = drawRect.top;
+
+ int selBegin = _selCaretPos;
+ int selEnd = _selOffset + _selCaretPos;
+ if (selBegin > selEnd)
+ SWAP(selBegin, selEnd);
+ selBegin = MAX(selBegin, 0);
+ selEnd = MAX(selEnd, 0);
+
+ Common::UnicodeBiDiText utxt(_editString);
+ Common::U32String left = Common::U32String(utxt.visual.c_str(), utxt.visual.c_str() + selBegin);
+ Common::U32String selected = Common::U32String(utxt.visual.c_str() + selBegin, selEnd - selBegin);
+ Common::U32String right = Common::U32String(utxt.visual.c_str() + selEnd);
+ Common::U32StringArray parts {left, selected, right};
+ int scrollOffset = _editScrollOffset;
+ for (int i = 0; i < parts.size(); i++) {
+ if (!parts[i].size())
+ continue;
+ Common::U32String part = parts[i];
+ int partW = g_gui.getStringWidth(part, _font);
+ int clipL = drawRect.left + (scrollOffset < 0 ? -scrollOffset : 0);
+ if (x + partW > 0 && x < _w && clipL < drawRect.right) {
+ int sO = scrollOffset < 0 ? 0 : -scrollOffset;
+ _inversion = i == 1 ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
+ g_gui.theme()->drawText(Common::Rect(clipL, y, drawRect.right, y + drawRect.height()), part, _state,
+ _drawAlign, _inversion, sO, false, _font, ThemeEngine::kFontColorNormal, true,
+ _textDrawableArea);
+ }
+ x += partW;
+ scrollOffset -= partW;
+ }
}
Common::Rect EditTextWidget::getEditRect() const {
@@ -133,9 +131,10 @@ void EditTextWidget::receivedFocusWidget() {
}
void EditTextWidget::lostFocusWidget() {
- // If we lose focus, 'commit' the user changes
+ // If we lose focus, 'commit' the user changes and clear selection
_backupString = _editString;
drawCaret(true);
+ clearSelection();
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
}
diff --git a/gui/widgets/edittext.h b/gui/widgets/edittext.h
index 7177c9278cd..9b8fa682e2b 100644
--- a/gui/widgets/edittext.h
+++ b/gui/widgets/edittext.h
@@ -42,8 +42,6 @@ public:
void setEditString(const Common::U32String &str) override;
- void handleMouseDown(int x, int y, int button, int clickCount) override;
-
bool wantsFocus() override { return true; }
void reflowLayout() override;
Commit: e101f5397c264b54b88a6fdcb3dba502cebf66eb
https://github.com/scummvm/scummvm/commit/e101f5397c264b54b88a6fdcb3dba502cebf66eb
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-01T18:42:34+01:00
Commit Message:
GUI: Limit text selection feature for RTL languages
Changed paths:
gui/widgets/editable.cpp
gui/widgets/edittext.cpp
diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp
index 7fa42d7eead..d968f458f0a 100644
--- a/gui/widgets/editable.cpp
+++ b/gui/widgets/editable.cpp
@@ -53,6 +53,7 @@ void EditableWidget::init() {
_selOffset = 0;
_shiftPressed = _isDragging = false;
+ _disableSelection = g_gui.useRTL();
_align = g_gui.useRTL() ? Graphics::kTextAlignRight : Graphics::kTextAlignLeft;
_drawAlign = _align;
@@ -128,7 +129,7 @@ void EditableWidget::handleMouseDown(int x, int y, int button, int clickCount) {
// Clear any selection
if (_selOffset != 0 && !_shiftPressed)
clearSelection();
- else if (_shiftPressed && _selCaretPos < 0)
+ else if (_shiftPressed && _selCaretPos < 0 && !_disableSelection)
_selCaretPos = _caretPos;
if (g_gui.useRTL()) {
@@ -149,7 +150,8 @@ void EditableWidget::handleMouseDown(int x, int y, int button, int clickCount) {
last = cur;
}
setCaretPos(i);
- if(_selCaretPos >= 0) setSelectionOffset(i - _selCaretPos);
+ if (_selCaretPos >= 0 && !_disableSelection)
+ setSelectionOffset(i - _selCaretPos);
markAsDirty();
}
@@ -159,8 +161,8 @@ void EditableWidget::handleMouseUp(int x, int y, int button, int clickCount) {
}
void EditableWidget::handleMouseMoved(int x, int y, int button) {
- if(_isDragging && isEnabled()) {
- if(_selCaretPos < 0)
+ if (_isDragging && isEnabled() && !_disableSelection) {
+ if (_selCaretPos < 0)
_selCaretPos = _caretPos;
if (g_gui.useRTL()) {
@@ -187,7 +189,8 @@ void EditableWidget::handleMouseMoved(int x, int y, int button) {
}
setCaretPos(i);
- if(_selCaretPos >= 0) setSelectionOffset(i - _selCaretPos);
+ if(_selCaretPos >= 0)
+ setSelectionOffset(i - _selCaretPos);
markAsDirty();
}
}
@@ -288,7 +291,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_END:
// Move caret to end
setCaretPos(caretVisualPos(_editString.size()));
- if (state.flags & Common::KBD_SHIFT)
+ if (state.hasFlags(Common::KBD_SHIFT))
setSelectionOffset(_editString.size() - _selCaretPos);
else
clearSelection();
@@ -297,11 +300,13 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
break;
case Common::KEYCODE_LEFT:
- if(state.hasFlags(Common::KBD_SHIFT)) {
- if(_selCaretPos < 0)
+ if (state.hasFlags(Common::KBD_SHIFT)) {
+ if (_disableSelection)
+ break;
+ if (_selCaretPos < 0)
_selCaretPos = _caretPos;
- if(_caretPos > 0)
- _selOffset--;
+ if (_caretPos > 0)
+ _selOffset--;
} else {
clearSelection();
}
@@ -314,11 +319,13 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
break;
case Common::KEYCODE_RIGHT:
- if(state.hasFlags(Common::KBD_SHIFT)) {
- if(_selCaretPos < 0)
+ if (state.hasFlags(Common::KBD_SHIFT)) {
+ if (_disableSelection)
+ break;
+ if (_selCaretPos < 0)
_selCaretPos = _caretPos;
- if(_selOffset + _selCaretPos < (int)_editString.size())
- _selOffset++;
+ if (_selOffset + _selCaretPos < (int)_editString.size())
+ _selOffset++;
} else {
clearSelection();
}
@@ -334,7 +341,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_HOME:
// Move caret to start
setCaretPos(caretVisualPos(0));
- if (state.flags & Common::KBD_SHIFT)
+ if (state.hasFlags(Common::KBD_SHIFT))
setSelectionOffset(0 - _selCaretPos);
else
clearSelection();
@@ -346,10 +353,22 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
if (state.flags & Common::KBD_CTRL) {
if (g_system->hasTextInClipboard()) {
Common::U32String text = g_system->getTextFromClipboard();
- for (uint32 i = 0; i < text.size(); ++i) {
+ if (_selOffset != 0) {
+ int selBegin = _selCaretPos;
+ int selEnd = _selCaretPos + _selOffset;
+ if (selBegin > selEnd)
+ SWAP(selBegin, selEnd);
+ _editString.replace(selBegin, selEnd - selBegin, text);
+ setCaretPos(caretVisualPos(selBegin));
+ const int logicalPosition = caretLogicalPos();
+ setCaretPos(caretVisualPos(logicalPosition + text.size()));
+ clearSelection();
+ } else {
+ for (uint32 i = 0; i < text.size(); ++i) {
const int logicalPosition = caretLogicalPos();
if (tryInsertChar(text[i], logicalPosition))
setCaretPos(caretVisualPos(logicalPosition + 1));
+ }
}
dirty = true;
}
@@ -518,10 +537,7 @@ void EditableWidget::drawCaret(bool erase) {
// EditTextWidget uses that but not ListWidget. Thus, one should check
// whether we can unify the drawing in the text area first to avoid
// possible glitches due to different methods used.
- if (_selOffset < 0)
- _inversion = ThemeEngine::kTextInversionFocus;
- else
- _inversion = ThemeEngine::kTextInversionNone;
+ _inversion = (_selOffset < 0) ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
width = MIN(editRect.width() - caretOffset, width);
if (width > 0) {
g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character,
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index 1df81800d4b..2e17d7b31ad 100644
--- a/gui/widgets/edittext.cpp
+++ b/gui/widgets/edittext.cpp
@@ -85,27 +85,38 @@ void EditTextWidget::drawWidget() {
selBegin = MAX(selBegin, 0);
selEnd = MAX(selEnd, 0);
- Common::UnicodeBiDiText utxt(_editString);
- Common::U32String left = Common::U32String(utxt.visual.c_str(), utxt.visual.c_str() + selBegin);
- Common::U32String selected = Common::U32String(utxt.visual.c_str() + selBegin, selEnd - selBegin);
- Common::U32String right = Common::U32String(utxt.visual.c_str() + selEnd);
- Common::U32StringArray parts {left, selected, right};
- int scrollOffset = _editScrollOffset;
- for (int i = 0; i < parts.size(); i++) {
- if (!parts[i].size())
- continue;
- Common::U32String part = parts[i];
- int partW = g_gui.getStringWidth(part, _font);
- int clipL = drawRect.left + (scrollOffset < 0 ? -scrollOffset : 0);
- if (x + partW > 0 && x < _w && clipL < drawRect.right) {
- int sO = scrollOffset < 0 ? 0 : -scrollOffset;
- _inversion = i == 1 ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
- g_gui.theme()->drawText(Common::Rect(clipL, y, drawRect.right, y + drawRect.height()), part, _state,
- _drawAlign, _inversion, sO, false, _font, ThemeEngine::kFontColorNormal, true,
- _textDrawableArea);
+ if (!g_gui.useRTL()) {
+ Common::UnicodeBiDiText utxt(_editString);
+ Common::U32String left = Common::U32String(utxt.visual.c_str(), utxt.visual.c_str() + selBegin);
+ Common::U32String selected = Common::U32String(utxt.visual.c_str() + selBegin, selEnd - selBegin);
+ Common::U32String right = Common::U32String(utxt.visual.c_str() + selEnd);
+ Common::U32StringArray parts {left, selected, right};
+ int scrollOffset = _editScrollOffset;
+ for (uint i = 0; i < parts.size(); i++) {
+ if (!parts[i].size())
+ continue;
+ Common::U32String part = parts[i];
+ int partW = g_gui.getStringWidth(part, _font);
+ int clipL = drawRect.left + (scrollOffset < 0 ? -scrollOffset : 0);
+ int clipR = MIN(clipL + partW, (int)drawRect.right);
+ if (x + partW > 0 && x < _w && clipL < drawRect.right) {
+ int sO = scrollOffset < 0 ? 0 : -scrollOffset;
+ _inversion = i == 1 ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
+ g_gui.theme()->drawText(Common::Rect(clipL, y, clipR, y + drawRect.height()), part, _state,
+ _drawAlign, _inversion, sO, false, _font, ThemeEngine::kFontColorNormal,
+ true, _textDrawableArea);
+ }
+ x += partW;
+ scrollOffset -= partW;
}
- x += partW;
- scrollOffset -= partW;
+ } else {
+ // The above method does not render RTL languages correctly, so fallback to default method
+ // There are only two possible cases, either the whole string has been selected
+ // or nothing has been selected.
+ _inversion = _selOffset ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
+ g_gui.theme()->drawText(drawRect, _editString, _state, _drawAlign, _inversion,
+ -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true,
+ _textDrawableArea);
}
}
More information about the Scummvm-git-logs
mailing list