>From d175520fa6477c686ae94a59ee67e64d08a86c78 Mon Sep 17 00:00:00 2001 From: Brand Huntsman Date: Fri, 17 Aug 2018 03:47:31 -0600 Subject: [PATCH] only newline "words" span lines when cutting prevword, nextword and nextword+afterends behavior is unchanged. cutwordright stops at end of line. if started at end of line, it cuts to the start of the next non-blank line. cutwordleft stops at start of line. if started at start of line, it cuts to the end of the previous non-blank line. Signed-off-by: Brand Huntsman --- src/move.c | 150 +++++++++++++++++++++++++++++++++++++++++------------------- src/proto.h | 5 +- src/text.c | 6 +-- 3 files changed, 108 insertions(+), 53 deletions(-) diff --git a/src/move.c b/src/move.c index bf6a0c11..c0c8b14a 100644 --- a/src/move.c +++ b/src/move.c @@ -271,17 +271,33 @@ void do_next_block(void) edit_redraw(was_current, CENTERING); } -/* Move to the previous word. If allow_punct is TRUE, treat punctuation - * as part of a word. When requested, update the screen afterwards. */ -void do_prev_word(bool allow_punct, bool update_screen) +/* Move to the previous word. If at_line_ends is TRUE, stop at start and + * end of lines. If allow_punct is TRUE, treat punctuation as part of a + * word. When requested, update the screen afterwards. */ +void do_prev_word(bool at_line_ends, bool allow_punct, bool update_screen) { filestruct *was_current = openfile->current; - bool seen_a_word = FALSE, step_forward = FALSE; - /* Move backward until we pass over the start of a word. */ + /* Move backward until we reach the end of a non-empty line. */ + if (at_line_ends && openfile->current_x == 0) { + do { + if (openfile->current->prev == NULL) + break; + openfile->current = openfile->current->prev; + openfile->current_x = strlen(openfile->current->data); + } while(openfile->current_x == 0); + + goto update_screen_and_return; + } + + /* Move backward over all non-word characters and newlines. */ while (TRUE) { /* If at the head of a line, move to the end of the preceding one. */ if (openfile->current_x == 0) { + /* Stop at start of line. */ + if (at_line_ends) + break; + /* When at start of file, stop. */ if (openfile->current->prev == NULL) break; openfile->current = openfile->current->prev; @@ -290,45 +306,87 @@ void do_prev_word(bool allow_punct, bool update_screen) /* Step back one character. */ openfile->current_x = move_mbleft(openfile->current->data, - openfile->current_x); + openfile->current_x); + /* Stop if word character. */ if (is_word_mbchar(openfile->current->data + openfile->current_x, - allow_punct)) { - seen_a_word = TRUE; - /* If at the head of a line now, this surely is a word start. */ - if (openfile->current_x == 0) - break; - } else if (seen_a_word) { - /* This is space now: we've overshot the start of the word. */ - step_forward = TRUE; + allow_punct)) break; - } } - if (step_forward) - /* Move one character forward again to sit on the start of the word. */ - openfile->current_x = move_mbright(openfile->current->data, + if (openfile->current_x > 0) { + /* Move backward until we reach the start of a word. */ + do { + openfile->current_x = move_mbleft(openfile->current->data, openfile->current_x); + } while (openfile->current_x > 0 && + is_word_mbchar(openfile->current->data + + openfile->current_x, allow_punct)); + /* Move one character forward again to sit on the start of the word. */ + if (!is_word_mbchar(openfile->current->data + openfile->current_x, + allow_punct)) + openfile->current_x = move_mbright(openfile->current->data, + openfile->current_x); + } + + update_screen_and_return: if (update_screen) edit_redraw(was_current, FLOWING); } /* Move to the next word. If after_ends is TRUE, stop at the ends of words - * instead of their beginnings. If allow_punct is TRUE, treat punctuation - * as part of a word. When requested, update the screen afterwards. - * Return TRUE if we started on a word, and FALSE otherwise. */ -bool do_next_word(bool after_ends, bool allow_punct, bool update_screen) + * instead of their beginnings. If at_line_ends is TRUE, stop at start and + * end of lines. If allow_punct is TRUE, treat punctuation as part of a + * word. When requested, update the screen afterwards. Return TRUE if + * we started on a word, and FALSE otherwise. */ +bool do_next_word(bool after_ends, bool at_line_ends, bool allow_punct, + bool update_screen) { filestruct *was_current = openfile->current; bool started_on_word = is_word_mbchar(openfile->current->data + openfile->current_x, allow_punct); - bool seen_space = !started_on_word; + + /* Move forward until we reach the start of a non-empty line. */ + if (at_line_ends && openfile->current->data[openfile->current_x] == '\0') { + do { + /* When at end of file, stop. */ + if (openfile->current->next == NULL) + break; + openfile->current = openfile->current->next; + openfile->current_x = 0; + } while (openfile->current->data[openfile->current_x] == '\0'); + + goto update_screen_and_return; + } + #ifndef NANO_TINY - bool seen_word = started_on_word; + if (!after_ends) { +#endif + /* Move forward until we reach the end of a word. */ + while (openfile->current->data[openfile->current_x] != '\0' && + is_word_mbchar(openfile->current->data + openfile->current_x, + allow_punct)) { + openfile->current_x = move_mbright(openfile->current->data, + openfile->current_x); + } +#ifndef NANO_TINY + } #endif - /* Move forward until we reach the start of a word. */ + /* Move forward over all non-word characters, stop at end of line. */ + if (at_line_ends) { + while (openfile->current->data[openfile->current_x] != '\0' && + !is_word_mbchar(openfile->current->data + + openfile->current_x, allow_punct)) { + openfile->current_x = move_mbright(openfile->current->data, + openfile->current_x); + } + + goto update_screen_and_return; + } + + /* Move forward over all non-word characters and newlines. */ while (TRUE) { /* If at the end of a line, move to the beginning of the next one. */ if (openfile->current->data[openfile->current_x] == '\0') { @@ -337,35 +395,31 @@ bool do_next_word(bool after_ends, bool allow_punct, bool update_screen) break; openfile->current = openfile->current->next; openfile->current_x = 0; - seen_space = TRUE; } else { /* Step forward one character. */ openfile->current_x = move_mbright(openfile->current->data, openfile->current_x); } -#ifndef NANO_TINY - if (after_ends) { - /* If this is a word character, continue; else it's a separator, - * and if we've already seen a word, then it's a word end. */ - if (is_word_mbchar(openfile->current->data + openfile->current_x, - allow_punct)) - seen_word = TRUE; - else if (seen_word) - break; - } 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_mbchar(openfile->current->data + openfile->current_x, - allow_punct)) - seen_space = TRUE; - else if (seen_space) - break; - } + /* Stop if word character. */ + if (is_word_mbchar(openfile->current->data + openfile->current_x, + allow_punct)) + break; } +#ifndef NANO_TINY + if (after_ends) { + /* Move forward until we reach the end of a word. */ + while (openfile->current->data[openfile->current_x] != '\0' && + is_word_mbchar(openfile->current->data + openfile->current_x, + allow_punct)) { + openfile->current_x = move_mbright(openfile->current->data, + openfile->current_x); + } + } +#endif + + update_screen_and_return: if (update_screen) edit_redraw(was_current, FLOWING); @@ -377,7 +431,7 @@ bool do_next_word(bool after_ends, bool allow_punct, bool update_screen) * word if the WORD_BOUNDS flag is set, and update the screen afterwards. */ void do_prev_word_void(void) { - do_prev_word(ISSET(WORD_BOUNDS), TRUE); + do_prev_word(FALSE, ISSET(WORD_BOUNDS), TRUE); } /* Move to the next word in the file. If the AFTER_ENDS flag is set, stop @@ -385,7 +439,7 @@ void do_prev_word_void(void) * punctuation as part of a word. Update the screen afterwards. */ void do_next_word_void(void) { - do_next_word(ISSET(AFTER_ENDS), ISSET(WORD_BOUNDS), TRUE); + do_next_word(ISSET(AFTER_ENDS), FALSE, ISSET(WORD_BOUNDS), TRUE); } /* Move to the beginning of the current line (or softwrapped chunk). diff --git a/src/proto.h b/src/proto.h index b59ba0b4..45979c84 100644 --- a/src/proto.h +++ b/src/proto.h @@ -380,8 +380,9 @@ void do_para_end_void(void); #endif void do_prev_block(void); void do_next_block(void); -void do_prev_word(bool allow_punct, bool update_screen); -bool do_next_word(bool after_ends, bool allow_punct, bool update_screen); +void do_prev_word(bool at_line_ends, bool allow_punct, bool update_screen); +bool do_next_word(bool after_ends, bool at_line_ends, bool allow_punct, + bool update_screen); void do_prev_word_void(void); void do_next_word_void(void); void do_home(void); diff --git a/src/text.c b/src/text.c index b5269029..394c2151 100644 --- a/src/text.c +++ b/src/text.c @@ -207,9 +207,9 @@ void do_cutword(bool backward) /* Move the cursor to a word start, to the left or to the right. */ if (backward) - do_prev_word(ISSET(WORD_BOUNDS), FALSE); + do_prev_word(TRUE, ISSET(WORD_BOUNDS), FALSE); else - do_next_word(FALSE, ISSET(WORD_BOUNDS), FALSE); + do_next_word(FALSE, TRUE, ISSET(WORD_BOUNDS), FALSE); /* Set the mark at the start of that word. */ openfile->mark = openfile->current; @@ -3344,7 +3344,7 @@ void do_wordlinechar_count(void) * count whenever we're on a word just before moving. */ while (openfile->current != openfile->filebot || openfile->current->data[openfile->current_x] != '\0') { - if (do_next_word(FALSE, TRUE, FALSE)) + if (do_next_word(FALSE, FALSE, TRUE, FALSE)) words++; } -- 2.16.4