From ca0995bdec7c96452291639c9736ed7212f96ca2 Mon Sep 17 00:00:00 2001
From: Pete Beardmore <pete.beardmore@msn.com>
Date: Sun, 4 Mar 2018 22:49:44 +0000
Subject: fbtk, textbox, overflow selection deselection

changes the selection's deselection mechanism for oversized (e.g
larger than window width) text

new behaviour ensures the maximum selection width remains whilst
the selection length is 'oversized'. only when the selection length
has a width less than the window width will the selection (i.e. the
highlight / inverted colours) reduce in size

this is in contrast to the existing approach which would immediately
decrease an oversized selection down to nothing visually, leaving
the remainder of the selection 'off screen'. this 'looks like nothing
is selected' when in fact it is, gives a poor UX
---
 src/FbTk/TextBox.cc | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/src/FbTk/TextBox.cc b/src/FbTk/TextBox.cc
index dcd51a7..a83347d 100644
--- a/src/FbTk/TextBox.cc
+++ b/src/FbTk/TextBox.cc
@@ -123,6 +123,18 @@ void TextBox::cursorEnd() {
 void TextBox::cursorForward() {
     StringRange r = charRange(m_start_pos + cursorPosition());
     const std::string::size_type s = r.end - r.begin + 1;
+
+    if (hasSelection()) {
+        int start = std::max(m_start_pos, std::min(m_start_pos + m_cursor_pos, m_select_pos));
+        int select_length = std::max(m_start_pos + m_cursor_pos, m_select_pos) - start;
+        if (select_length > static_cast<signed>(m_end_pos - m_start_pos)) {
+            // shift range
+            m_start_pos += s;
+            m_end_pos += s;
+            adjustPos();
+        }
+    }
+
     if (r.end < m_end_pos)
         m_cursor_pos = r.end + 1 - m_start_pos;
     else if (m_end_pos < text().size()) {
@@ -133,9 +145,22 @@ void TextBox::cursorForward() {
 }
 
 void TextBox::cursorBackward() {
+
+    StringRange r = charRange(m_start_pos + cursorPosition() - 1);
+    const std::string::size_type s = r.end - r.begin + 1;
+
+    if (hasSelection()) {
+       int end = std::max(m_end_pos, std::min(m_end_pos - m_cursor_pos, m_select_pos));
+       int select_length = end - std::min(m_end_pos - m_cursor_pos, m_select_pos);
+       if (select_length > static_cast<signed>(m_end_pos - m_start_pos)) {
+           // shift range
+           m_start_pos -= s;
+           m_end_pos -= s;
+           adjustPos();
+       }
+    }
+
     if (m_start_pos || cursorPosition()) {
-        StringRange r = charRange(m_start_pos + cursorPosition() - 1);
-        const std::string::size_type s = r.end - r.begin + 1;
         if (cursorPosition())
             m_cursor_pos = r.begin - m_start_pos;
         else if (m_start_pos) {
-- 
cgit v0.11.2