diff --git a/src/cut.c b/src/cut.c index 3c0a8533..35c38841 100644 --- a/src/cut.c +++ b/src/cut.c @@ -34,7 +34,7 @@ void do_deletion(undo_type action) int charlen = char_length(openfile->current->data + openfile->current_x); size_t line_len = strlen(openfile->current->data + openfile->current_x); #ifndef NANO_TINY - size_t old_amount = 0; + size_t old_amount = openfile->current->extrarows; /* If the type of action changed or the cursor moved to a different * line, create a new undo item, otherwise update the existing item. */ @@ -43,20 +43,18 @@ void do_deletion(undo_type action) add_undo(action, NULL); else update_undo(action); - - if (ISSET(SOFTWRAP)) - old_amount = extra_chunks_in(openfile->current); #endif /* Move the remainder of the line "in", over the current character. */ memmove(&openfile->current->data[openfile->current_x], &openfile->current->data[openfile->current_x + charlen], line_len - charlen + 1); #ifndef NANO_TINY - /* When softwrapping and the number of chunks in the current line has - * changed, the chunks must be renumbered and the screen refreshed. */ - if (ISSET(SOFTWRAP) && extra_chunks_in(openfile->current) != old_amount) { - renumber_from(openfile->current); - refresh_needed = TRUE; + /* When softwrapping, recompute the number of chunks in the line, + * and schedule a refresh if the number changed. */ + if (ISSET(SOFTWRAP)) { + openfile->current->extrarows = extra_chunks_in(openfile->current); + if (openfile->current->extrarows != old_amount) + refresh_needed = TRUE; } /* Adjust the mark if it is after the cursor on the current line. */ diff --git a/src/files.c b/src/files.c index b1674e95..e21761fe 100644 --- a/src/files.c +++ b/src/files.c @@ -356,6 +356,16 @@ bool has_valid_path(const char *filename) return validity; } +/* Compute and store how many extra rows each line needs when softwrapping. */ +void compute_the_extra_rows_per_line(void) +{ +#ifndef NANO_TINY + if (ISSET(SOFTWRAP)) + for (linestruct *ln = openfile->filetop; ln != NULL; ln = ln->next) + ln->extrarows = extra_chunks_in(ln); +#endif +} + /* This does one of three things. If the filename is "", it just creates * a new empty buffer. When the filename is not empty, it reads that file * into a new buffer when requested, otherwise into the existing buffer. */ @@ -453,6 +463,8 @@ bool open_buffer(const char *filename, bool new_one) openfile->placewewant = 0; } + compute_the_extra_rows_per_line(); + #ifdef ENABLE_COLOR /* If a new buffer was opened, check whether a syntax can be applied. */ if (new_one) @@ -527,6 +539,8 @@ void redecorate_after_switch(void) * or softwrap mode may have been toggled, so make sure that the * starting column for the first row gets an appropriate value. */ ensure_firstcolumn_is_aligned(); + + compute_the_extra_rows_per_line(); #endif /* Update title bar and multiline info to match the current buffer. */ diff --git a/src/nano.c b/src/nano.c index b3296113..0f961b7f 100644 --- a/src/nano.c +++ b/src/nano.c @@ -76,9 +76,7 @@ linestruct *make_new_node(linestruct *prevnode) #endif newnode->lineno = (prevnode) ? prevnode->lineno + 1 : 1; #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) - newnode->chunk_nr = (prevnode) ? - prevnode->chunk_nr + extra_chunks_in(prevnode) + 1 : 1; + newnode->extrarows = -2; /* Bad value, to make it easier to find bugs. */ newnode->has_anchor = FALSE; #endif @@ -154,7 +152,7 @@ linestruct *copy_node(const linestruct *src) #endif dst->lineno = src->lineno; #ifndef NANO_TINY - dst->chunk_nr = src->chunk_nr; + dst->extrarows = src->extrarows; dst->has_anchor = FALSE; #endif @@ -190,21 +188,8 @@ void renumber_from(linestruct *line) { ssize_t number = (line->prev == NULL) ? 0 : line->prev->lineno; -#ifndef NANO_TINY - if (ISSET(SOFTWRAP) && line->prev == NULL) { - line->lineno = ++number; - line->chunk_nr = 1; - line = line->next; - } -#endif - while (line != NULL) { line->lineno = ++number; -#ifndef NANO_TINY - if (ISSET(SOFTWRAP)) - line->chunk_nr = line->prev->chunk_nr + - extra_chunks_in(line->prev) + 1; -#endif line = line->next; } } @@ -1095,7 +1080,7 @@ void do_toggle(int flag) break; case SOFTWRAP: if (ISSET(SOFTWRAP)) - renumber_from(openfile->filetop); + compute_the_extra_rows_per_line(); else openfile->firstcolumn = 0; refresh_needed = TRUE; @@ -1426,12 +1411,12 @@ void inject(char *burst, size_t count) linestruct *thisline = openfile->current; size_t datalen = strlen(thisline->data); #ifndef NANO_TINY - size_t original_row = 0, old_amount = 0; + size_t old_amount = openfile->current->extrarows; + size_t original_row = 0; if (ISSET(SOFTWRAP)) { if (openfile->current_y == editwinrows - 1) original_row = chunk_for(xplustabs(), thisline); - old_amount = extra_chunks_in(thisline); } #endif @@ -1492,15 +1477,17 @@ void inject(char *burst, size_t count) #endif #ifndef NANO_TINY - /* If we were on the last row of the edit window and moved to a new chunk, - * or if the number of chunks that the current softwrapped line occupies - * changed, we need a full refresh. */ - if (ISSET(SOFTWRAP) && ((openfile->current_y == editwinrows - 1 && - chunk_for(xplustabs(), openfile->current) > original_row) || - extra_chunks_in(openfile->current) != old_amount)) { - renumber_from(openfile->current); - refresh_needed = TRUE; - focusing = FALSE; + /* When softwrapping and the number of chunks in the current line changed, + * or we were on the last row of the edit window and moved to a new chunk, + * we need a full refresh. */ + if (ISSET(SOFTWRAP)) { + openfile->current->extrarows = extra_chunks_in(openfile->current); + if (openfile->current->extrarows != old_amount || + (openfile->current_y == editwinrows - 1 && + chunk_for(xplustabs(), openfile->current) > original_row)) { + refresh_needed = TRUE; + focusing = FALSE; + } } #endif diff --git a/src/nano.h b/src/nano.h index b14296e1..7df938ff 100644 --- a/src/nano.h +++ b/src/nano.h @@ -285,8 +285,8 @@ typedef struct linestruct { ssize_t lineno; /* The number of this line. */ #ifndef NANO_TINY - ssize_t chunk_nr; - /* The ordinal number of the first chunk in this line. */ + ssize_t extrarows; + /* The extra rows that this line occupies when softwrapping. */ #endif struct linestruct *next; /* Next node. */ diff --git a/src/proto.h b/src/proto.h index fc0e3272..d59be1b8 100644 --- a/src/proto.h +++ b/src/proto.h @@ -283,6 +283,7 @@ void make_new_buffer(void); #ifndef NANO_TINY bool delete_lockfile(const char *lockfilename); #endif +void compute_the_extra_rows_per_line(void); bool open_buffer(const char *filename, bool new_buffer); void set_modified(void); void prepare_for_display(void); diff --git a/src/search.c b/src/search.c index 0570a482..6ffa9693 100644 --- a/src/search.c +++ b/src/search.c @@ -654,6 +654,10 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only, free(openfile->current->data); openfile->current->data = copy; +#ifndef NANO_TINY + if (ISSET(SOFTWRAP)) + openfile->current->extrarows = extra_chunks_in(openfile->current); +#endif #ifdef ENABLE_COLOR /* Check whether the replacement requires a change in the coloring. */ check_the_multis(openfile->current); diff --git a/src/text.c b/src/text.c index adab2631..6f5feae8 100644 --- a/src/text.c +++ b/src/text.c @@ -102,6 +102,9 @@ void indent_a_line(linestruct *line, char *indentation) openfile->totsize += indent_len; + if (ISSET(SOFTWRAP)) + line->extrarows = extra_chunks_in(line); + /* Compensate for the change in the current line. */ if (line == openfile->mark && openfile->mark_x > 0) openfile->mark_x += indent_len; @@ -230,6 +233,9 @@ void unindent_a_line(linestruct *line, size_t indent_len) openfile->totsize -= indent_len; + if (ISSET(SOFTWRAP)) + line->extrarows = extra_chunks_in(line); + /* Adjust the positions of mark and cursor, when they are affected. */ compensate_leftward(line, indent_len); } @@ -418,8 +424,13 @@ void do_comment(void) /* Comment/uncomment each of the selected lines when possible, and * store undo data when a line changed. */ for (line = top; line != bot->next; line = line->next) { - if (comment_line(action, line, comment_seq)) + if (comment_line(action, line, comment_seq)) { +#ifndef NANO_TINY + if (ISSET(SOFTWRAP)) + line->extrarows = extra_chunks_in(line); +#endif update_multiline_undo(line->lineno, ""); + } } set_modified(); @@ -660,6 +671,9 @@ void do_undo(void) openfile->mark = NULL; openfile->placewewant = xplustabs(); + if (ISSET(SOFTWRAP)) + openfile->current->extrarows = extra_chunks_in(openfile->current); + openfile->totsize = u->wassize; /* When at the point where the file was last saved, unset "Modified". */ @@ -818,6 +832,9 @@ void do_redo(void) openfile->mark = NULL; openfile->placewewant = xplustabs(); + if (ISSET(SOFTWRAP)) + openfile->current->extrarows = extra_chunks_in(openfile->current); + openfile->totsize = u->newsize; /* When at the point where the file was last saved, unset "Modified". */ diff --git a/src/winio.c b/src/winio.c index af25a144..376ae5a1 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2957,10 +2957,12 @@ void draw_scrollbar(void) int first_row = openfile->edittop->lineno; if (ISSET(SOFTWRAP)) { - totalrows = openfile->filebot->chunk_nr + - extra_chunks_in(openfile->filebot); - first_row = openfile->edittop->chunk_nr + - chunk_for(openfile->firstcolumn, openfile->edittop); + for (linestruct *ln = openfile->filetop; ln != openfile->edittop; ln = ln->next) + first_row += ln->extrarows; + first_row += chunk_for(openfile->firstcolumn, openfile->edittop); + + for (linestruct *ln = openfile->filetop; ln != NULL; ln = ln->next) + totalrows += ln->extrarows; } int lowest = ((first_row - 1) * editwinrows) / totalrows; @@ -3142,11 +3144,10 @@ size_t leftedge_for(size_t column, linestruct *line) * has changed, because then the width of softwrapped chunks has changed. */ void ensure_firstcolumn_is_aligned(void) { - if (ISSET(SOFTWRAP)) { + if (ISSET(SOFTWRAP)) openfile->firstcolumn = leftedge_for(openfile->firstcolumn, openfile->edittop); - renumber_from(openfile->filetop); - } else + else openfile->firstcolumn = 0; /* If smooth scrolling is on, make sure the viewport doesn't center. */