diff --git a/ChangeLog b/ChangeLog
index 17000b88d52b2488f48e8d62474f4440c40c54ec..75acea224491ac973f2dfc641586dcf30a30cc66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -93,20 +93,22 @@ CVS code -
 	  them to work with multibyte strings as much as possible, add
 	  support to a few more functions as well, and move multibyte
 	  character-specific functions to their own source file.  New
-	  file chars.c; new functions is_blank_mbchar(),
+	  file chars.c; new functions is_alnum_char(),
+	  is_alnum_mbchar(), is_alnum_wchar(), is_blank_mbchar(),
 	  is_blank_wchar(), is_cntrl_mbchar(), is_cntrl_wchar(),
 	  mbstrnlen(), control_mbrep(), control_wrep(), mbwidth(),
 	  mb_cur_max(), and make_mbchar(); changes to is_blank_char()
 	  (moved to chars.c), is_cntrl_char() (moved to chars.c),
 	  nstrnlen() (moved to chars.c), parse_char() (renamed
 	  parse_mbchar() and moved to chars.c), do_home(),
-	  do_verbatim_input(), do_delete(), do_tab(), 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 display_string(); removal of
-	  buffer_to_keys() and keys_to_buffer(). (DLR)
+	  do_verbatim_input(), do_delete(), do_tab(), do_next_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
+	  display_string(); removal of buffer_to_keys() and
+	  keys_to_buffer(). (DLR)
 - cut.c:
   do_cut_text()
 	- If keep_cutbuffer is FALSE, only blow away the text in the
diff --git a/src/chars.c b/src/chars.c
index 5834e59b0267008ba4fe4f3eb4c7a1b329616f6d..02a1ca95effefe8aee63c69c0b8f94e925dcbdab 100644
--- a/src/chars.c
+++ b/src/chars.c
@@ -38,6 +38,41 @@
 #include <wctype.h>
 #endif
 
+/* This function is equivalent to isalnum(). */
+bool is_alnum_char(unsigned int c)
+{
+    return isalnum(c);
+}
+
+/* This function is equivalent to isalnum() for multibyte characters. */
+bool is_alnum_mbchar(const char *c)
+{
+    assert(c != NULL);
+
+#ifdef NANO_WIDE
+    if (!ISSET(NO_UTF8)) {
+	wchar_t wc;
+	int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX);
+
+	if (c_mb_len <= 0) {
+	    mbtowc(NULL, NULL, 0);
+	    wc = (unsigned char)*c;
+	}
+
+	return is_alnum_wchar(wc);
+    } else
+#endif
+	return is_alnum_char((unsigned char)*c);
+}
+
+#ifdef NANO_WIDE
+/* This function is equivalent to isalnum() for wide characters. */
+bool is_alnum_wchar(wchar_t wc)
+{
+    return iswalnum(wc);
+}
+#endif
+
 /* This function is equivalent to isblank(). */
 bool is_blank_char(unsigned int c)
 {
diff --git a/src/move.c b/src/move.c
index 3a81159248a92c0aa2433fb4c80fd9ac77c1d8e5..cdd88e1446f7ec183848126ee044816d2a805617 100644
--- a/src/move.c
+++ b/src/move.c
@@ -58,13 +58,11 @@ void do_home(void)
     if (ISSET(SMART_HOME)) {
 	size_t current_x_save = current_x;
 	char *blank_mb = charalloc(mb_cur_max());
-	int blank_mb_len;
 
 	current_x = 0;
 
 	while (current->data[current_x] != '\0') {
-	    blank_mb_len = parse_mbchar(current->data + current_x,
-		blank_mb
+	    parse_mbchar(current->data + current_x, blank_mb
 #ifdef NANO_WIDE
 		, NULL
 #endif
@@ -73,7 +71,7 @@ void do_home(void)
 	    if (!is_blank_mbchar(blank_mb))
 		break;
 
-	    current_x += blank_mb_len;
+	    current_x = move_right(current->data, current_x);
 	}
 
 	free(blank_mb);
diff --git a/src/nano.c b/src/nano.c
index 00c0fd5feebc859c6858a22e153b126a1b72803e..7518e0de8f4c577b9595bdd606a9e8cb578f27b2 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1315,41 +1315,65 @@ void do_enter(void)
 }
 
 #ifndef NANO_SMALL
+/* Move to the next word. */
 void do_next_word(void)
 {
-    size_t old_pww = placewewant;
-    const filestruct *old_current = current;
+    size_t pww_save = placewewant;
+    const filestruct *current_save = current;
+    char *char_mb = charalloc(mb_cur_max());
+
     assert(current != NULL && current->data != NULL);
 
     /* Skip letters in this word first. */
-    while (current->data[current_x] != '\0' &&
-	isalnum(current->data[current_x]))
-	current_x++;
+    while (current->data[current_x] != '\0') {
+	parse_mbchar(current->data + current_x, char_mb
+#ifdef NANO_WIDE
+		, NULL
+#endif
+		, NULL);
 
+	if (!is_alnum_mbchar(char_mb))
+	    break;
+
+	current_x = move_right(current->data, current_x);
+    }
+
+    /* Go until we find the first letter of the next word. */
     for (; current != NULL; current = current->next) {
-	while (current->data[current_x] != '\0' &&
-		!isalnum(current->data[current_x]))
-	    current_x++;
+	while (current->data[current_x] != '\0') {
+	    parse_mbchar(current->data + current_x, char_mb
+#ifdef NANO_WIDE
+		, NULL
+#endif
+		, NULL);
+
+	    if (is_alnum_mbchar(char_mb))
+		break;
+
+	    current_x = move_right(current->data, current_x);
+	}
 
 	if (current->data[current_x] != '\0')
 	    break;
 
 	current_x = 0;
     }
+
     if (current == NULL)
 	current = filebot;
 
     placewewant = xplustabs();
 
     /* Update the screen. */
-    edit_redraw(old_current, old_pww);
+    edit_redraw(current_save, pww_save);
 }
 
-/* The same thing for backwards. */
+/* Move to the previous word. */
 void do_prev_word(void)
 {
-    size_t old_pww = placewewant;
-    const filestruct *old_current = current;
+    size_t pww_save = placewewant;
+    const filestruct *current_save = current;
+
     assert(current != NULL && current->data != NULL);
 
     current_x++;
@@ -1358,6 +1382,7 @@ void do_prev_word(void)
     while (current_x > 0 && isalnum(current->data[current_x - 1]))
 	current_x--;
 
+    /* Go until we find the first letter of the previous word. */
     for (; current != NULL; current = current->prev) {
 	while (current_x > 0 && !isalnum(current->data[current_x - 1]))
 	    current_x--;
@@ -1382,7 +1407,7 @@ void do_prev_word(void)
     placewewant = xplustabs();
 
     /* Update the screen. */
-    edit_redraw(old_current, old_pww);
+    edit_redraw(current_save, pww_save);
 }
 
 void do_mark(void)
diff --git a/src/proto.h b/src/proto.h
index 0dfbfc344f78c7c597fcfc2cca41c7eccb79837b..10b452a34c8822f18463421344b723cdbc924325 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -151,6 +151,11 @@ extern char *homedir;
 /* Functions we want available. */
 
 /* Public functions in chars.c. */
+bool is_alnum_char(unsigned int c);
+bool is_alnum_mbchar(const char *c);
+#ifdef NANO_WIDE
+bool is_alnum_wchar(wchar_t wc);
+#endif
 bool is_blank_char(unsigned int c);
 bool is_blank_mbchar(const char *c);
 #ifdef NANO_WIDE
diff --git a/src/winio.c b/src/winio.c
index faa15adfd7308243b48d834911f5edd390885315..5ae85bb6f779312ba64d98bf7a630fdb274442e4 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -1804,12 +1804,11 @@ void do_statusbar_home(void)
     if (ISSET(SMART_HOME)) {
 	size_t statusbar_x_save = statusbar_x;
 	char *blank_mb = charalloc(mb_cur_max());
-	int blank_mb_len;
 
 	statusbar_x = 0;
 
 	while (statusbar_x < statusbar_xend) {
-	    blank_mb_len = parse_mbchar(answer + statusbar_x,
+	    parse_mbchar(answer + statusbar_x,
 		blank_mb
 #ifdef NANO_WIDE
 		, NULL
@@ -1819,7 +1818,7 @@ void do_statusbar_home(void)
 	    if (!is_blank_mbchar(blank_mb))
 		break;
 
-	    statusbar_x += blank_mb_len;
+	    statusbar_x = move_right(answer, statusbar_x);
 	}
 
 	free(blank_mb);