nano-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] moving: skip combining characters and other zero-width chara


From: Benno Schulenberg
Subject: [PATCH 1/2] moving: skip combining characters and other zero-width characters
Date: Wed, 11 Nov 2020 16:29:36 +0100

This makes the cursor move smoothly left and right -- instead of
"stuttering" when passing over a zero-width character.

Pressing <Delete> on a normal (spacing) character also deletes
any zero-width characters after it.  But pressing <Backspace>
while the cursor is placed after a zero-width character, just
deletes that zero-width character.  The latter behavior allows
deleting and retyping just the combining diacritic of a character
instead of the whole, combined character.

This addresses https://savannah.gnu.org/bugs/?50773.
Requested-by: Mike Frysinger <vapier@gentoo.org>
---
 src/chars.c      |  7 +++++++
 src/cut.c        | 11 ++++++++++-
 src/move.c       | 29 +++++++++++++++++++++++++++++
 src/prototypes.h |  1 +
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/src/chars.c b/src/chars.c
index 93ffde19..cc0ae357 100644
--- a/src/chars.c
+++ b/src/chars.c
@@ -144,6 +144,13 @@ bool is_word_char(const char *c, bool allow_punct)
                return FALSE;
 }
 
+#ifdef ENABLE_UTF8
+bool is_zerowidth(const char *ch)
+{
+       return (use_utf8 && mbwidth(ch) == 0);
+}
+#endif
+
 /* Return the visible representation of control character c. */
 char control_rep(const signed char c)
 {
diff --git a/src/cut.c b/src/cut.c
index 63130c2a..8ad4a3d2 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -121,7 +121,13 @@ void do_delete(void)
                zap_text();
        else
 #endif
+       {
                do_deletion(DEL);
+#ifdef ENABLE_UTF8
+               while (is_zerowidth(openfile->current->data + 
openfile->current_x))
+                       do_deletion(DEL);
+#endif
+       }
 }
 
 /* Backspace over one character.  That is, move the cursor left one
@@ -133,7 +139,10 @@ void do_backspace(void)
                zap_text();
        else
 #endif
-       if (openfile->current_x > 0 || openfile->current != openfile->filetop) {
+       if (openfile->current_x > 0) {
+               openfile->current_x = step_left(openfile->current->data, 
openfile->current_x);
+               do_deletion(BACK);
+       } else if (openfile->current != openfile->filetop) {
                do_left();
                do_deletion(BACK);
        }
diff --git a/src/move.c b/src/move.c
index ba675ba7..9b149855 100644
--- a/src/move.c
+++ b/src/move.c
@@ -291,6 +291,10 @@ void do_prev_word(bool allow_punct)
                        /* If at the head of a line now, this surely is a word 
start. */
                        if (openfile->current_x == 0)
                                break;
+#ifdef ENABLE_UTF8
+               } else if (is_zerowidth(openfile->current->data + 
openfile->current_x)) {
+                       ; /* skip */
+#endif
                } else if (seen_a_word) {
                        /* This is space now: we've overshot the start of the 
word. */
                        step_forward = TRUE;
@@ -339,11 +343,20 @@ bool do_next_word(bool after_ends, bool allow_punct)
                        if (is_word_char(openfile->current->data + 
openfile->current_x,
                                                                allow_punct))
                                seen_word = TRUE;
+#ifdef ENABLE_UTF8
+                       else if (is_zerowidth(openfile->current->data + 
openfile->current_x))
+                               ; /* skip */
+#endif
                        else if (seen_word)
                                break;
                } else
 #endif
                {
+#ifdef ENABLE_UTF8
+                       if (is_zerowidth(openfile->current->data + 
openfile->current_x))
+                               ; /* skip */
+                       else
+#endif
                        /* If this is not a word character, then it's a 
separator; else
                         * if we've already seen a separator, then it's a word 
start. */
                        if (!is_word_char(openfile->current->data + 
openfile->current_x,
@@ -582,8 +595,16 @@ void do_left(void)
        linestruct *was_current = openfile->current;
 
        if (openfile->current_x > 0)
+       {
                openfile->current_x = step_left(openfile->current->data,
                                                                                
                openfile->current_x);
+#ifdef ENABLE_UTF8
+               while (is_zerowidth(openfile->current->data + 
openfile->current_x) &&
+                                                                               
                openfile->current_x > 0)
+                       openfile->current_x = step_left(openfile->current->data,
+                                                                               
                openfile->current_x);
+#endif
+       }
        else if (openfile->current != openfile->filetop) {
                openfile->current = openfile->current->prev;
                openfile->current_x = strlen(openfile->current->data);
@@ -598,8 +619,16 @@ void do_right(void)
        linestruct *was_current = openfile->current;
 
        if (openfile->current->data[openfile->current_x] != '\0')
+       {
                openfile->current_x = step_right(openfile->current->data,
                                                                                
                openfile->current_x);
+#ifdef ENABLE_UTF8
+               while (is_zerowidth(openfile->current->data + 
openfile->current_x) &&
+                                               
openfile->current->data[openfile->current_x] != '\0')
+                       openfile->current_x = 
step_right(openfile->current->data,
+                                                                               
                openfile->current_x);
+#endif
+       }
        else if (openfile->current != openfile->filebot) {
                openfile->current = openfile->current->next;
                openfile->current_x = 0;
diff --git a/src/prototypes.h b/src/prototypes.h
index d1b2ece6..6e5c9f6f 100644
--- a/src/prototypes.h
+++ b/src/prototypes.h
@@ -201,6 +201,7 @@ bool is_alpha_char(const char *c);
 bool is_blank_char(const char *c);
 bool is_cntrl_char(const char *c);
 bool is_word_char(const char *c, bool allow_punct);
+bool is_zerowidth(const char *ch);
 char control_mbrep(const char *c, bool isdata);
 #ifdef ENABLE_UTF8
 int mbwidth(const char *c);
-- 
2.25.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]