[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
- [PATCH 1/2] moving: skip combining characters and other zero-width characters,
Benno Schulenberg <=