[Scummvm-git-logs] scummvm master -> b67b88e6d99072d23dd978bf22b066d56496b33c
sev-
noreply at scummvm.org
Tue Aug 2 20:04:57 UTC 2022
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
b67b88e6d9 GUI: Support unicode and BiDi in editable widget
Commit: b67b88e6d99072d23dd978bf22b066d56496b33c
https://github.com/scummvm/scummvm/commit/b67b88e6d99072d23dd978bf22b066d56496b33c
Author: BLooperZ (blooperz at users.noreply.github.com)
Date: 2022-08-02T22:04:54+02:00
Commit Message:
GUI: Support unicode and BiDi in editable widget
Changed paths:
gui/ThemeEngine.cpp
gui/ThemeEngine.h
gui/editgamedialog.cpp
gui/gui-manager.h
gui/widgets/editable.cpp
gui/widgets/editable.h
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 9eda4286ff3..6a926d19080 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1665,11 +1665,11 @@ int ThemeEngine::getStringWidth(const Common::U32String &str, FontStyle font) co
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getStringWidth(str) : 0;
}
-int ThemeEngine::getCharWidth(byte c, FontStyle font) const {
+int ThemeEngine::getCharWidth(uint32 c, FontStyle font) const {
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getCharWidth(c) : 0;
}
-int ThemeEngine::getKerningOffset(byte left, byte right, FontStyle font) const {
+int ThemeEngine::getKerningOffset(uint32 left, uint32 right, FontStyle font) const {
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getKerningOffset(left, right) : 0;
}
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 0c0b5fdaa95..2e21abd0e17 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -432,9 +432,9 @@ public:
int getStringWidth(const Common::U32String &str, FontStyle font = kFontStyleBold) const;
- int getCharWidth(byte c, FontStyle font = kFontStyleBold) const;
+ int getCharWidth(uint32 c, FontStyle font = kFontStyleBold) const;
- int getKerningOffset(byte left, byte right, FontStyle font = kFontStyleBold) const;
+ int getKerningOffset(uint32 left, uint32 right, FontStyle font = kFontStyleBold) const;
//@}
diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp
index 259f7b2e7c1..7b3bdf5d147 100644
--- a/gui/editgamedialog.cpp
+++ b/gui/editgamedialog.cpp
@@ -92,7 +92,7 @@ public:
: EditTextWidget(boss, name, text, tooltip) {}
protected:
- bool tryInsertChar(byte c, int pos) override {
+ bool tryInsertChar(Common::u32char_type_t c, int pos) override {
if (Common::isAlnum(c) || c == '-' || c == '_') {
_editString.insertChar(c, pos);
return true;
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index 3127788b3e0..66df2f6acdb 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -115,8 +115,8 @@ public:
int getFontHeight(ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getFontHeight(style); }
int getStringWidth(const Common::String &str, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getStringWidth(str, style); }
int getStringWidth(const Common::U32String &str, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getStringWidth(str, style); }
- int getCharWidth(byte c, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getCharWidth(c, style); }
- int getKerningOffset(byte left, byte right, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold) const { return _theme->getKerningOffset(left, right, font); }
+ int getCharWidth(uint32 c, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getCharWidth(c, style); }
+ int getKerningOffset(uint32 left, uint32 right, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold) const { return _theme->getKerningOffset(left, right, font); }
/**
* Tell the GuiManager to check whether the screen resolution has changed.
diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp
index 8591911c9cf..7c0f384a505 100644
--- a/gui/widgets/editable.cpp
+++ b/gui/widgets/editable.cpp
@@ -21,6 +21,7 @@
#include "common/rect.h"
#include "common/system.h"
+#include "common/unicode-bidi.h"
#include "gui/widgets/editable.h"
#include "gui/gui-manager.h"
#include "graphics/font.h"
@@ -75,7 +76,7 @@ void EditableWidget::setEditString(const Common::U32String &str) {
_caretPos = 0;
}
-bool EditableWidget::tryInsertChar(byte c, int pos) {
+bool EditableWidget::tryInsertChar(Common::u32char_type_t c, int pos) {
if ((c >= 32 && c <= 127) || c >= 160) {
_editString.insertChar(c, pos);
return true;
@@ -83,6 +84,14 @@ bool EditableWidget::tryInsertChar(byte c, int pos) {
return false;
}
+int EditableWidget::caretVisualPos(int logicalPos) {
+ return Common::convertBiDiU32String(_editString + " ").getVisualPosition(logicalPos);
+}
+
+int EditableWidget::caretLogicalPos() const {
+ return Common::convertBiDiU32String(_editString + " ").getLogicalPosition(_caretPos);
+}
+
void EditableWidget::handleTickle() {
uint32 time = g_system->getMillis();
if (_caretTime < time && isEnabled()) {
@@ -95,6 +104,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
bool handled = true;
bool dirty = false;
bool forcecaret = false;
+ int deleteIndex;
if (!isEnabled())
return false;
@@ -139,9 +149,11 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
break;
case Common::KEYCODE_BACKSPACE:
- if (_caretPos > 0) {
- _caretPos--;
- _editString.deleteChar(_caretPos);
+ deleteIndex = caretLogicalPos();
+ if (deleteIndex > 0) {
+ deleteIndex--;
+ _editString.deleteChar(deleteIndex);
+ setCaretPos(caretVisualPos(deleteIndex));
dirty = true;
sendCommand(_cmd, 0);
@@ -150,8 +162,10 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
break;
case Common::KEYCODE_DELETE:
- if (_caretPos < (int)_editString.size()) {
- _editString.deleteChar(_caretPos);
+ deleteIndex = caretLogicalPos();
+ if (deleteIndex < (int)_editString.size()) {
+ _editString.deleteChar(deleteIndex);
+ setCaretPos(caretVisualPos(deleteIndex));
dirty = true;
sendCommand(_cmd, 0);
@@ -162,7 +176,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_DOWN:
case Common::KEYCODE_END:
// Move caret to end
- setCaretPos(_editString.size());
+ setCaretPos(caretVisualPos(_editString.size()));
forcecaret = true;
dirty = true;
break;
@@ -188,7 +202,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_UP:
case Common::KEYCODE_HOME:
// Move caret to start
- setCaretPos(0);
+ setCaretPos(caretVisualPos(0));
forcecaret = true;
dirty = true;
break;
@@ -198,8 +212,9 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
if (g_system->hasTextInClipboard()) {
Common::U32String text = g_system->getTextFromClipboard();
for (uint32 i = 0; i < text.size(); ++i) {
- if (tryInsertChar(text[i], _caretPos))
- ++_caretPos;
+ const int logicalPosition = caretLogicalPos();
+ if (tryInsertChar(text[i], logicalPosition))
+ setCaretPos(caretVisualPos(logicalPosition + 1));
}
dirty = true;
}
@@ -261,8 +276,9 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
}
void EditableWidget::defaultKeyDownHandler(Common::KeyState &state, bool &dirty, bool &forcecaret, bool &handled) {
- if (state.ascii < 256 && tryInsertChar((byte)state.ascii, _caretPos)) {
- _caretPos++;
+ const int logicalPosition = caretLogicalPos();
+ if (tryInsertChar(state.ascii, logicalPosition)) {
+ setCaretPos(caretVisualPos(logicalPosition + 1));
dirty = true;
forcecaret = true;
@@ -273,7 +289,8 @@ void EditableWidget::defaultKeyDownHandler(Common::KeyState &state, bool &dirty,
}
int EditableWidget::getCaretOffset() const {
- Common::U32String substr(_editString.begin(), _editString.begin() + _caretPos);
+ Common::UnicodeBiDiText utxt(_editString);
+ Common::U32String substr(utxt.visual.begin(), utxt.visual.begin() + _caretPos);
return g_gui.getStringWidth(substr, _font) - _editScrollOffset;
}
@@ -313,15 +330,16 @@ void EditableWidget::drawCaret(bool erase) {
g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height()), erase);
if (erase) {
- Common::String character;
+ Common::U32String character;
int width;
if ((uint)_caretPos < _editString.size()) {
- const byte chr = _editString[_caretPos];
+ Common::UnicodeBiDiText utxt(_editString);
+ const Common::u32char_type_t chr = utxt.visual[_caretPos];
width = g_gui.getCharWidth(chr, _font);
- character = chr;
+ character = Common::U32String(chr);
- const uint last = (_caretPos > 0) ? _editString[_caretPos - 1] : 0;
+ const uint32 last = (_caretPos > 0) ? utxt.visual[_caretPos - 1] : 0;
x += g_gui.getKerningOffset(last, chr, _font);
} else {
// We draw a fake space here to assure that removing the caret
diff --git a/gui/widgets/editable.h b/gui/widgets/editable.h
index 551c0175a68..d64eb317214 100644
--- a/gui/widgets/editable.h
+++ b/gui/widgets/editable.h
@@ -94,7 +94,10 @@ protected:
void setFontStyle(ThemeEngine::FontStyle font) { _font = font; }
- virtual bool tryInsertChar(byte c, int pos);
+ virtual bool tryInsertChar(Common::u32char_type_t c, int pos);
+
+ int caretVisualPos(int logicalPos);
+ int caretLogicalPos() const;
};
} // End of namespace GUI
More information about the Scummvm-git-logs
mailing list