From 936486cb1ccaba88add3b7caa984cdf841e019f1 Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Sat, 17 Dec 2016 07:42:54 +0000 Subject: [PATCH] Handle non-ASCII characters when selecting a word or moving the cursor by one word. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12149 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Text_Buffer.H | 1 + src/Fl_Text_Buffer.cxx | 28 +++++++++++++++++++--------- src/Fl_Text_Display.cxx | 17 +++++------------ 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/FL/Fl_Text_Buffer.H b/FL/Fl_Text_Buffer.H index 4c6cf31a6..ee02322db 100644 --- a/FL/Fl_Text_Buffer.H +++ b/FL/Fl_Text_Buffer.H @@ -699,6 +699,7 @@ public: to be informed if file input required transcoding to UTF-8. */ void (*transcoding_warning_action)(Fl_Text_Buffer*); + bool is_word_separator(int pos) const; protected: diff --git a/src/Fl_Text_Buffer.cxx b/src/Fl_Text_Buffer.cxx index 9efcd6609..1b42234f3 100644 --- a/src/Fl_Text_Buffer.cxx +++ b/src/Fl_Text_Buffer.cxx @@ -825,17 +825,29 @@ int Fl_Text_Buffer::line_end(int pos) const { } +/** Returns whether character at position \p pos is a word separator. + Pos must be at a character boundary. + */ +bool Fl_Text_Buffer::is_word_separator(int pos) const { + int c = char_at(pos); + if (c < 128) { + return !(isalnum(c) || c == '_'); // non alphanumeric ASCII + } + return (c == 0xA0 || // NO-BREAK SPACE + (c >= 0x3000 && c <= 0x301F) // IDEOGRAPHIC punctuation + ); +} + + /* Find the beginning of a word. - NOT UNICODE SAFE. */ int Fl_Text_Buffer::word_start(int pos) const { - // FIXME: character is ucs-4 - while (pos>0 && (isalnum(char_at(pos)) || char_at(pos) == '_')) { + while (pos > 0 && !is_word_separator(pos)) + { pos = prev_char(pos); - } - // FIXME: character is ucs-4 - if (!(isalnum(char_at(pos)) || char_at(pos) == '_')) + } + if (is_word_separator(pos)) pos = next_char(pos); return pos; } @@ -843,11 +855,9 @@ int Fl_Text_Buffer::word_start(int pos) const { /* Find the end of a word. - NOT UNICODE SAFE. */ int Fl_Text_Buffer::word_end(int pos) const { - // FIXME: character is ucs-4 - while (pos < length() && (isalnum(char_at(pos)) || char_at(pos) == '_')) + while (pos < length() && !is_word_separator(pos)) { pos = next_char(pos); } diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx index 52c506715..aacee88e6 100644 --- a/src/Fl_Text_Display.cxx +++ b/src/Fl_Text_Display.cxx @@ -1537,24 +1537,17 @@ int Fl_Text_Display::rewind_lines(int startPos, int nLines) { -static inline int fl_isseparator(unsigned int c) { - // FIXME: this does not take UCS-4 encoding into account - return c != '$' && c != '_' && (isspace(c) || ispunct(c)); -} - - - /** \brief Moves the current insert position right one word. */ void Fl_Text_Display::next_word() { int pos = insert_position(); - while (pos < buffer()->length() && !fl_isseparator(buffer()->char_at(pos))) { + while (pos < buffer()->length() && !buffer()->is_word_separator(pos)) { pos = buffer()->next_char(pos); } - while (pos < buffer()->length() && fl_isseparator(buffer()->char_at(pos))) { + while (pos < buffer()->length() && buffer()->is_word_separator(pos)) { pos = buffer()->next_char(pos); } @@ -1571,15 +1564,15 @@ void Fl_Text_Display::previous_word() { if (pos==0) return; pos = buffer()->prev_char(pos); - while (pos && fl_isseparator(buffer()->char_at(pos))) { + while (pos && buffer()->is_word_separator(pos)) { pos = buffer()->prev_char(pos); } - while (pos && !fl_isseparator(buffer()->char_at(pos))) { + while (pos && !buffer()->is_word_separator(pos)) { pos = buffer()->prev_char(pos); } - if (fl_isseparator(buffer()->char_at(pos))) { + if (buffer()->is_word_separator(pos)) { pos = buffer()->next_char(pos); }