From ce0451348c775d5afb07e4b6e48d93c1693a9865 Mon Sep 17 00:00:00 2001
From: David Lawrence Ramsey <pooka109@gmail.com>
Date: Sat, 15 Jan 2005 00:34:57 +0000
Subject: [PATCH] make do_prev_word() work with multibyte strings, and update
 various comments in do_next_word() and do_prev_word()

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2273 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
---
 ChangeLog  |   4 +-
 src/nano.c | 112 +++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 97 insertions(+), 19 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f141a531..f3d3fa66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -104,8 +104,8 @@ CVS code -
 	  move_mbleft() and moved to chars.c), move_right() (renamed
 	  move_mbright() and moved to chars.c), do_home(),
 	  do_verbatim_input(), do_delete(), do_tab(), do_next_word(),
-	  do_input(), do_output(), get_buffer(), unget_input(),
-	  unget_kbinput(), get_input(), parse_kbinput(),
+	  do_prev_word(), do_input(), do_output(), get_buffer(),
+	  unget_input(), unget_kbinput(), get_input(), parse_kbinput(),
 	  unparse_kbinput(), parse_verbatim_kbinput(),
 	  do_statusbar_input(), do_statusbar_home(),
 	  do_statusbar_verbatim_kbinput(), do_statusbar_output(), and
diff --git a/src/nano.c b/src/nano.c
index 6c8ad362..6ca25b22 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1325,7 +1325,8 @@ void do_next_word(void)
 
     assert(current != NULL && current->data != NULL);
 
-    /* Skip letters in this word first. */
+    /* Move forward until we find the character after the last letter of
+     * the current word. */
     while (current->data[current_x] != '\0') {
 	char_mb_len = parse_mbchar(current->data + current_x,
 		char_mb
@@ -1334,13 +1335,15 @@ void do_next_word(void)
 #endif
 		, NULL);
 
+	/* If we've found it, stop moving forward through the current
+	 * line. */
 	if (!is_alnum_mbchar(char_mb))
 	    break;
 
 	current_x += char_mb_len;
     }
 
-    /* Go until we find the first letter of the next word. */
+    /* Move forward until we find the first letter of the next word. */
     for (; current != NULL; current = current->next) {
 	while (current->data[current_x] != '\0') {
 	    char_mb_len = parse_mbchar(current->data + current_x,
@@ -1350,12 +1353,16 @@ void do_next_word(void)
 #endif
 		, NULL);
 
+	    /* If we've found it, stop moving forward through the
+	     * current line. */
 	    if (is_alnum_mbchar(char_mb))
 		break;
 
 	    current_x += char_mb_len;
 	}
 
+	/* If we've found it, stop moving forward to the beginnings of
+	 * subsequent lines. */
 	if (current->data[current_x] != '\0')
 	    break;
 
@@ -1364,6 +1371,8 @@ void do_next_word(void)
 
     free(char_mb);
 
+    /* If we haven't found it, leave the cursor at the end of the
+     * file. */
     if (current == NULL)
 	current = filebot;
 
@@ -1378,37 +1387,106 @@ void do_prev_word(void)
 {
     size_t pww_save = placewewant;
     const filestruct *current_save = current;
+    char *char_mb = charalloc(mb_cur_max());
+    int char_mb_len;
+    bool begin_line = FALSE;
 
     assert(current != NULL && current->data != NULL);
 
-    current_x++;
+    /* Move backward until we find the character before the first letter
+     * of the current word. */
+    while (!begin_line) {
+	char_mb_len = parse_mbchar(current->data + current_x,
+		char_mb
+#ifdef NANO_WIDE
+		, NULL
+#endif
+		, NULL);
+
+	/* If we've found it, stop moving backward through the current
+	 * line. */
+	if (!is_alnum_mbchar(char_mb))
+	    break;
 
-    /* Skip letters in this word first. */
-    while (current_x > 0 && isalnum(current->data[current_x - 1]))
-	current_x--;
+	if (current_x == 0)
+	    begin_line = TRUE;
+	else
+	    current_x = move_mbleft(current->data, current_x);
+    }
 
-    /* Go until we find the first letter of the previous word. */
+    /* Move backward until we find the last letter of the previous
+     * word. */
     for (; current != NULL; current = current->prev) {
-	while (current_x > 0 && !isalnum(current->data[current_x - 1]))
-	    current_x--;
+	while (!begin_line) {
+	    char_mb_len = parse_mbchar(current->data + current_x,
+		char_mb
+#ifdef NANO_WIDE
+		, NULL
+#endif
+		, NULL);
+
+	    /* If we've found it, stop moving backward through the
+	     * current line. */
+	    if (is_alnum_mbchar(char_mb))
+		break;
 
-	if (current_x > 0)
+	    if (current_x == 0)
+		begin_line = TRUE;
+	    else
+		current_x = move_mbleft(current->data, current_x);
+	}
+
+	/* If we've found it, stop moving backward to the ends of
+	 * previous lines. */
+	if (!begin_line)
 	    break;
 
-	if (current->prev != NULL)
-	    current_x = strlen(current->prev->data) + 1;
+	if (current->prev != NULL) {
+	    begin_line = FALSE;
+	    current_x = strlen(current->prev->data);
+	}
     }
 
-    current_x--;
-
+    /* If we haven't found it, leave the cursor at the beginning of the
+     * file. */
     if (current == NULL) {
 	current = fileage;
 	current_x = 0;
-    } else {
-	while (current_x > 0 && isalnum(current->data[current_x - 1]))
-	    current_x--;
+    /* If we've found it, move backward until we find the character
+     * before the first letter of the previous word. */
+    } else if (!begin_line) {
+	if (current_x == 0)
+	    begin_line = TRUE;
+	else
+	    current_x = move_mbleft(current->data, current_x);
+
+	while (!begin_line) {
+	    char_mb_len = parse_mbchar(current->data + current_x,
+		char_mb
+#ifdef NANO_WIDE
+		, NULL
+#endif
+		, NULL);
+
+	    /* If we've found it, stop moving backward through the
+	     * current line. */
+	    if (!is_alnum_mbchar(char_mb))
+		break;
+
+	    if (current_x == 0)
+		begin_line = TRUE;
+	    else
+		current_x = move_mbleft(current->data, current_x);
+	}
+
+	/* If we've found it, move forward to the first letter of the
+	 * previous word. */
+	if (!begin_line)
+	    current_x += char_mb_len;
     }
 
+    free(char_mb);
+
     placewewant = xplustabs();
 
     /* Update the screen. */
-- 
GitLab