From aa04ad4f83edce506360fe4f378c1dac6d8d10e9 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Mon, 6 Mar 2017 01:34:45 -0600 Subject: [PATCH] replacing: make spotlight() account for varying chunk width spotlight() now displays softwrapped lines chunk by chunk instead of all at once. Since softwrapped lines are no longer of constant width, the latter approach would fail if softwrapping breaks the spotlighted text. Instead of taking a string, spotlight() now takes the starting and ending columns of that string. Also, its handling of softwrapped lines is now split off into a separate function, spotlight_softwrapped(). --- src/proto.h | 5 ++- src/search.c | 13 +++---- src/text.c | 13 +++---- src/winio.c | 107 +++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 105 insertions(+), 33 deletions(-) diff --git a/src/proto.h b/src/proto.h index aabca6ab..605f2cde 100644 --- a/src/proto.h +++ b/src/proto.h @@ -681,7 +681,10 @@ void total_refresh(void); void display_main_list(void); void do_cursorpos(bool force); void do_cursorpos_void(void); -void spotlight(bool active, const char *word); +void spotlight(bool active, size_t from_col, size_t to_col); +#ifndef NANO_TINY +void spotlight_softwrapped(bool active, size_t from_col, size_t to_col); +#endif void xon_complaint(void); void xoff_complaint(void); void do_suspend_void(void); diff --git a/src/search.c b/src/search.c index 6d178200..2c36a5b5 100644 --- a/src/search.c +++ b/src/search.c @@ -614,10 +614,9 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only, numreplaced = 0; if (!replaceall) { - size_t xpt = xplustabs(); - char *exp_word = display_string(openfile->current->data, - xpt, strnlenpt(openfile->current->data, - openfile->current_x + match_len) - xpt, FALSE); + size_t from_col = xplustabs(); + size_t to_col = strnlenpt(openfile->current->data, + openfile->current_x + match_len); /* Refresh the edit window, scrolling it if necessary. */ edit_refresh(); @@ -625,14 +624,12 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only, /* Don't show cursor, to not distract from highlighted match. */ curs_set(0); - spotlight(TRUE, exp_word); + spotlight(TRUE, from_col, to_col); /* TRANSLATORS: This is a prompt. */ i = do_yesno_prompt(TRUE, _("Replace this instance?")); - spotlight(FALSE, exp_word); - - free(exp_word); + spotlight(FALSE, from_col, to_col); if (i == -1) /* The replacing was cancelled. */ break; diff --git a/src/text.c b/src/text.c index 3bb76c08..4a8d38cf 100644 --- a/src/text.c +++ b/src/text.c @@ -2540,7 +2540,7 @@ void do_full_justify(void) * return FALSE if the user cancels. */ bool do_int_spell_fix(const char *word) { - char *save_search, *exp_word; + char *save_search; size_t firstcolumn_save = openfile->firstcolumn; size_t current_x_save = openfile->current_x; filestruct *edittop_save = openfile->edittop; @@ -2605,11 +2605,12 @@ bool do_int_spell_fix(const char *word) proceed = TRUE; napms(2800); } else if (result == 1) { - exp_word = display_string(openfile->current->data, xplustabs(), - strlenpt(word), FALSE); + size_t from_col = xplustabs(); + size_t to_col = from_col + strlenpt(word); + edit_refresh(); - spotlight(TRUE, exp_word); + spotlight(TRUE, from_col, to_col); /* Let the user supply a correctly spelled alternative. */ proceed = (do_prompt(FALSE, FALSE, MSPELL, word, @@ -2618,9 +2619,7 @@ bool do_int_spell_fix(const char *word) #endif edit_refresh, _("Edit a replacement")) != -1); - spotlight(FALSE, exp_word); - - free(exp_word); + spotlight(FALSE, from_col, to_col); /* If a replacement was given, go through all occurrences. */ if (proceed && strcmp(word, answer) != 0) { diff --git a/src/winio.c b/src/winio.c index c8e8cc77..8c1edcfd 100644 --- a/src/winio.c +++ b/src/winio.c @@ -3396,32 +3396,43 @@ void enable_waiting(void) nodelay(edit, FALSE); } -/* Highlight the current word being replaced or spell checked. We - * expect word to have tabs and control characters expanded. */ -void spotlight(bool active, const char *word) +/* Highlight the text between from_col and to_col when active is TRUE. + * Remove the highlight when active is FALSE. */ +void spotlight(bool active, size_t from_col, size_t to_col) { - size_t word_span = strlenpt(word); - size_t room = word_span; + char *word; + size_t word_span, room; - /* Compute the number of columns that are available for the word. */ - if (!ISSET(SOFTWRAP)) { - room = editwincols + get_page_start(xplustabs()) - xplustabs(); - - /* If the word is partially offscreen, reserve space for the "$". */ - if (word_span > room) - room--; +#ifndef NANO_TINY + if (ISSET(SOFTWRAP)) { + spotlight_softwrapped(active, from_col, to_col); + return; } +#endif place_the_cursor(FALSE); + /* This is so we can show zero-length matches. */ + if (to_col == from_col) { + word = mallocstrcpy(NULL, " "); + to_col++; + } else + word = display_string(openfile->current->data, from_col, + to_col - from_col, FALSE); + + word_span = strlenpt(word); + + /* Compute the number of columns that are available for the word. */ + room = editwincols + get_page_start(from_col) - from_col; + + /* If the word is partially offscreen, reserve space for the "$". */ + if (word_span > room) + room--; + if (active) wattron(edit, hilite_attribute); - /* This is so we can show zero-length matches. */ - if (word_span == 0) - waddch(edit, ' '); - else - waddnstr(edit, word, actual_x(word, room)); + waddnstr(edit, word, actual_x(word, room)); if (word_span > room) waddch(edit, '$'); @@ -3429,9 +3440,71 @@ void spotlight(bool active, const char *word) if (active) wattroff(edit, hilite_attribute); + free(word); + wnoutrefresh(edit); } +#ifndef NANO_TINY +/* Highlight the text between from_col and to_col when active is TRUE; remove + * the highlight when active is FALSE. This will not highlight softwrapped + * line breaks, since they're not actually part of the spotlighted text. */ +void spotlight_softwrapped(bool active, size_t from_col, size_t to_col) +{ + ssize_t row; + size_t leftedge = get_chunk_leftedge(openfile->current, from_col); + size_t break_col; + bool end_of_line; + char *word; + + place_the_cursor(FALSE); + + row = openfile->current_y; + + while (row < editwinrows) { + break_col = get_softwrap_breakpoint(openfile->current->data, + leftedge, &end_of_line); + + /* Stop after the end of the word, by pretending the end of the word is + * the end of the line. */ + if (break_col >= to_col) { + end_of_line = TRUE; + break_col = to_col; + } + + /* This is so we can show zero-length matches. */ + if (break_col == from_col) { + word = mallocstrcpy(NULL, " "); + break_col++; + } else + word = display_string(openfile->current->data, from_col, + break_col - from_col, FALSE); + + if (active) + wattron(edit, hilite_attribute); + + waddnstr(edit, word, actual_x(word, break_col)); + + if (active) + wattroff(edit, hilite_attribute); + + free(word); + + if (end_of_line) + break; + + row++; + + wmove(edit, row, 0); + + leftedge = break_col; + from_col = break_col; + } + + wnoutrefresh(edit); +} +#endif + #ifndef DISABLE_EXTRA #define CREDIT_LEN 54 #define XLCREDIT_LEN 9