[utilities/konsole] /: Make behaviour of characters with problematic width configurable

Kurt Hindenburg null at kde.org
Fri Feb 24 01:03:21 GMT 2023


Git commit feb44c226fc6ca8e57f37a189442474e63383688 by Kurt Hindenburg, on behalf of Matan Ziv-Av.
Committed on 24/02/2023 at 00:46.
Pushed by hindenburg into branch 'master'.

Make behaviour of characters with problematic width configurable

Add a profile option to follow Unicode standard for the display width of
characters, where this width differs from glibc's wcwidth.

Currently the only character affected by this is soft hyphen (unicode 0x00ad).

Konsole generally follows wcwidth() function when determining the display
width of characters, since this is behaviour expected by libreadline, and
doing otherwise corrupts lines containing problematic characters. When such
characters are used more for display, then on the command line, following
the Unicode standard may be prefferable.

The default for this option is disabled - that is follow wcwidth().

CCBUG: 464823

M  +6    -0    doc/manual/index.docbook
M  +8    -2    src/Screen.cpp
M  +4    -0    src/Screen.h
M  +1    -0    src/profile/Profile.cpp
M  +4    -0    src/profile/Profile.h
M  +3    -1    src/session/SessionManager.cpp
M  +1    -0    src/terminalDisplay/TerminalDisplay.cpp
M  +16   -0    src/widgets/EditProfileAppearancePage.ui
M  +8    -0    src/widgets/EditProfileDialog.cpp
M  +1    -0    src/widgets/EditProfileDialog.h

https://invent.kde.org/utilities/konsole/commit/feb44c226fc6ca8e57f37a189442474e63383688

diff --git a/doc/manual/index.docbook b/doc/manual/index.docbook
index 016b7edd2..2137d8227 100644
--- a/doc/manual/index.docbook
+++ b/doc/manual/index.docbook
@@ -485,6 +485,12 @@ Lines are always Left to right. Without this, each line's direction is determine
 Consider graphic table characters as strong LTR characters. This allows table containing RTL characters to display correctly, but might cause incorrect order if those characters are used in RTL texts.
 </para></listitem>
 
+<listitem><para>
+<guilabel>Override wcwidth</guilabel> -
+Problematic characters follow Unicode standard, rather than glibc's wcwidth(). Currently only soft hyphen (Unicode 0x00AD) which has wcwidth of 1 and Unicode width of 0 is affected by this option. Generally, this option should be disabled when mainly using those characters on the command line, and enabled when they are only displayed.
+</para></listitem>
+
+
 </itemizedlist>
 </para>
 </sect1>
diff --git a/src/Screen.cpp b/src/Screen.cpp
index d3f538861..8492cc302 100644
--- a/src/Screen.cpp
+++ b/src/Screen.cpp
@@ -91,6 +91,7 @@ Screen::Screen(int lines, int columns)
     , _lastPos(-1)
     , _lastDrawnChar(0)
     , _escapeSequenceUrlExtractor(nullptr)
+    , _ignoreWcWidth(false)
 {
     std::fill(_lineProperties.begin(), _lineProperties.end(), LineProperty());
 
@@ -551,6 +552,11 @@ void Screen::setReflowLines(bool enable)
     _enableReflowLines = enable;
 }
 
+void Screen::setIgnoreWcWidth(bool ignore)
+{
+    _ignoreWcWidth = ignore;
+}
+
 /* Note that if you use these debugging functions, it will
    fail to compile on gcc 8.3.1 as of Feb 2021 due to for_each_n().
    See BKO: 432639
@@ -1074,10 +1080,10 @@ void Screen::displayCharacter(uint c)
     if (w < 0) {
         // Non-printable character
         return;
-    } else if (category == QChar::Mark_SpacingCombining || w == 0 || Character::emoji(c) || c == 0x20E3) {
+    } else if (category == QChar::Mark_SpacingCombining || w == 0 || Character::emoji(c) || c == 0x20E3 || (_ignoreWcWidth && c == 0x00AD)) {
         bool emoji = Character::emoji(c);
         if (category != QChar::Mark_SpacingCombining && category != QChar::Mark_NonSpacing && category != QChar::Letter_Other && category != QChar::Other_Format
-            && !emoji && c != 0x20E3) {
+            && !emoji && c != 0x20E3 && c != 0x00AD) {
             return;
         }
         // Find previous "real character" to try to combine with
diff --git a/src/Screen.h b/src/Screen.h
index 45552193c..a27d3283b 100644
--- a/src/Screen.h
+++ b/src/Screen.h
@@ -703,6 +703,7 @@ public:
     {
         return _hasGraphics;
     }
+    void setIgnoreWcWidth(bool ignore);
 
 private:
     // copies a line of text from the screen or history into a stream using a
@@ -899,6 +900,9 @@ private:
     std::vector<std::unique_ptr<TerminalGraphicsPlacement_t>> _graphicsPlacements;
     void scrollPlacements(int n, qint64 below = INT64_MAX, qint64 above = INT64_MAX);
     bool _hasGraphics;
+
+    //
+    bool _ignoreWcWidth;
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(Screen::DecodingOptions)
diff --git a/src/profile/Profile.cpp b/src/profile/Profile.cpp
index 6df96dc6b..a96bb5b16 100644
--- a/src/profile/Profile.cpp
+++ b/src/profile/Profile.cpp
@@ -99,6 +99,7 @@ const std::vector<Profile::PropertyInfo> Profile::DefaultProperties = {
     {WordModeAttr, "WordModeAttr", APPEARANCE_GROUP, false},
     {WordModeAscii, "WordModeAscii", APPEARANCE_GROUP, true},
     {WordModeBrahmic, "WordModeBrahmic", APPEARANCE_GROUP, false},
+    {IgnoreWcWidth, "IgnoreWcWidth", APPEARANCE_GROUP, false},
 
 // Keyboard
 #ifdef Q_OS_MACOS
diff --git a/src/profile/Profile.h b/src/profile/Profile.h
index 66adea04e..8af8ff112 100644
--- a/src/profile/Profile.h
+++ b/src/profile/Profile.h
@@ -403,6 +403,10 @@ public:
          * Improves display when the font is not strictly monospace
          */
         WordModeBrahmic,
+        /** Use wcwidth() for problematic characters
+         * soft hyphen (\u00ad) has wcwidth=1, but should not be displayed per Unicode.
+         */
+        IgnoreWcWidth,
     };
 
     Q_ENUM(Property)
diff --git a/src/session/SessionManager.cpp b/src/session/SessionManager.cpp
index 8725962b6..51d9b7c07 100644
--- a/src/session/SessionManager.cpp
+++ b/src/session/SessionManager.cpp
@@ -272,11 +272,13 @@ void SessionManager::applyProfile(Session *session, const Profile::Ptr &profile,
     if (apply.shouldApply(Profile::SilenceSeconds)) {
         session->setMonitorSilenceSeconds(profile->silenceSeconds());
     }
-    if (apply.shouldApply(Profile::AllowEscapedLinks) || apply.shouldApply(Profile::ReflowLines)) {
+    if (apply.shouldApply(Profile::AllowEscapedLinks) || apply.shouldApply(Profile::ReflowLines) || apply.shouldApply(Profile::IgnoreWcWidth)) {
         const bool shouldEnableUrlExtractor = profile->allowEscapedLinks();
         const bool enableReflowLines = profile->property<bool>(Profile::ReflowLines);
+        const bool ignoreWcWidth = profile->property<bool>(Profile::IgnoreWcWidth);
         for (TerminalDisplay *view : session->views()) {
             view->screenWindow()->screen()->setReflowLines(enableReflowLines);
+            view->screenWindow()->screen()->setIgnoreWcWidth(ignoreWcWidth);
             view->screenWindow()->screen()->setEnableUrlExtractor(shouldEnableUrlExtractor);
             if (shouldEnableUrlExtractor) {
                 view->screenWindow()->screen()->urlExtractor()->setAllowedLinkSchema(profile->escapedLinksSchema());
diff --git a/src/terminalDisplay/TerminalDisplay.cpp b/src/terminalDisplay/TerminalDisplay.cpp
index dc2e42079..d84e653f5 100644
--- a/src/terminalDisplay/TerminalDisplay.cpp
+++ b/src/terminalDisplay/TerminalDisplay.cpp
@@ -149,6 +149,7 @@ void TerminalDisplay::setScreenWindow(ScreenWindow *window)
 
         auto profile = SessionManager::instance()->sessionProfile(_sessionController->session());
         _screenWindow->screen()->setReflowLines(profile->property<bool>(Profile::ReflowLines));
+        _screenWindow->screen()->setIgnoreWcWidth(profile->property<bool>(Profile::IgnoreWcWidth));
 
         if (_screenWindow->screen()->urlExtractor()) {
             _screenWindow->screen()->urlExtractor()->setAllowedLinkSchema(profile->escapedLinksSchema());
diff --git a/src/widgets/EditProfileAppearancePage.ui b/src/widgets/EditProfileAppearancePage.ui
index f1690735f..6fb5367ea 100644
--- a/src/widgets/EditProfileAppearancePage.ui
+++ b/src/widgets/EditProfileAppearancePage.ui
@@ -917,6 +917,22 @@
           </property>
          </widget>
         </item>
+        <item row="110" column="1">
+         <widget class="QCheckBox" name="ignoreWcWidth">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="toolTip">
+           <string>Ignore wcwidth of problematic characters</string>
+          </property>
+          <property name="text">
+           <string>Override wcwidth</string>
+          </property>
+         </widget>
+        </item>
         <item row="1000" column="0" colspan="2">
          <spacer>
           <property name="orientation">
diff --git a/src/widgets/EditProfileDialog.cpp b/src/widgets/EditProfileDialog.cpp
index 6f00cbbee..95a1ae8f7 100644
--- a/src/widgets/EditProfileDialog.cpp
+++ b/src/widgets/EditProfileDialog.cpp
@@ -876,6 +876,9 @@ void EditProfileDialog::setupAppearancePage(const Profile::Ptr &profile)
 
     _appearanceUi->wordModeBrahmic->setChecked(profile->property<bool>(Profile::WordModeBrahmic));
     connect(_appearanceUi->wordModeBrahmic, &QPushButton::toggled, this, &EditProfileDialog::toggleWordModeBrahmic);
+
+    _appearanceUi->ignoreWcWidth->setChecked(profile->property<bool>(Profile::IgnoreWcWidth));
+    connect(_appearanceUi->ignoreWcWidth, &QPushButton::toggled, this, &EditProfileDialog::toggleIgnoreWcWidth);
 }
 
 void EditProfileDialog::setAntialiasText(bool enable)
@@ -2083,3 +2086,8 @@ void EditProfileDialog::toggleWordModeBrahmic(bool mode)
 {
     updateTempProfileProperty(Profile::WordModeBrahmic, mode);
 }
+
+void EditProfileDialog::toggleIgnoreWcWidth(bool ignore)
+{
+    updateTempProfileProperty(Profile::IgnoreWcWidth, ignore);
+}
diff --git a/src/widgets/EditProfileDialog.h b/src/widgets/EditProfileDialog.h
index 841d9ced0..58aca14d5 100644
--- a/src/widgets/EditProfileDialog.h
+++ b/src/widgets/EditProfileDialog.h
@@ -231,6 +231,7 @@ private Q_SLOTS:
     void toggleWordModeAttr(bool mode);
     void toggleWordModeAscii(bool mode);
     void toggleWordModeBrahmic(bool mode);
+    void toggleIgnoreWcWidth(bool ignore);
 
 private:
     Q_DISABLE_COPY(EditProfileDialog)


More information about the kde-doc-english mailing list