Index: src/files.c =================================================================== --- src/files.c (revision 5057) +++ src/files.c (working copy) @@ -560,6 +560,7 @@ assert(openfile->fileage != NULL && strlen(buf) == buf_len); fileptr->data = mallocstrcpy(NULL, buf); + fileptr->extra_lines = 0; #ifndef NANO_TINY /* If it's a DOS file ("\r\n"), and file conversion isn't disabled, Index: src/move.c =================================================================== --- src/move.c (revision 5057) +++ src/move.c (working copy) @@ -80,7 +80,7 @@ openfile->current = openfile->current->prev; #ifndef NANO_TINY if (ISSET(SOFTWRAP) && openfile->current) { - skipped += strlenpt(openfile->current->data) / COLS; + skipped += openfile->current->extra_lines; #ifdef DEBUG fprintf(stderr, "do_page_up: i = %d, skipped = %d based on line %ld len %lu\n", i, skipped, (long)openfile->current->lineno, (unsigned long)strlenpt(openfile->current->data)); @@ -587,16 +587,16 @@ #ifndef NANO_TINY if (ISSET(SOFTWRAP)) { /* Compute the amount to scroll. */ - amount = (strlenpt(openfile->current->data) / COLS + openfile->current_y + 2 - + strlenpt(openfile->current->prev->data) / COLS - editwinrows); + amount = (openfile->current->extra_lines + openfile->current_y + 2 + + openfile->current->prev->extra_lines - editwinrows); topline = openfile->edittop; /* Reduce the amount when there are overlong lines at the top. */ for (enough = 1; enough < amount; enough++) { - if (amount <= strlenpt(topline->data) / COLS) { + if (amount <= topline->extra_lines) { amount = enough; break; } - amount -= strlenpt(topline->data) / COLS; + amount -= topline->extra_lines; topline = topline->next; } } Index: src/nano.c =================================================================== --- src/nano.c (revision 5057) +++ src/nano.c (working copy) @@ -67,6 +67,7 @@ newnode->prev = prevnode; newnode->next = NULL; newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1; + newnode->extra_lines = 0; #ifndef DISABLE_COLOR newnode->multidata = NULL; @@ -88,6 +89,7 @@ dst->next = src->next; dst->prev = src->prev; dst->lineno = src->lineno; + dst->extra_lines = src->extra_lines; #ifndef DISABLE_COLOR dst->multidata = NULL; #endif @@ -370,6 +372,7 @@ * filestruct. */ openfile->fileage = (filestruct *)nmalloc(sizeof(filestruct)); openfile->fileage->data = mallocstrcpy(NULL, ""); + openfile->fileage->extra_lines = 0; openfile->filebot = openfile->fileage; #ifndef DISABLE_COLOR @@ -1786,7 +1789,7 @@ openfile->current->next && i < mouse_y; openfile->current = openfile->current->next, i++) { openfile->current_y = i; - i += strlenpt(openfile->current->data) / COLS; + i += openfile->current->extra_lines; } #ifdef DEBUG fprintf(stderr, "do_mouse(): moving to current_y = %ld, index i = %lu\n", @@ -1796,7 +1799,16 @@ if (i > mouse_y) { openfile->current = openfile->current->prev; - openfile->current_x = actual_x(openfile->current->data, mouse_x + (mouse_y - openfile->current_y) * COLS); + + size_t columns = 0; + const char *line_pos = openfile->current->data; + while (mouse_y - openfile->current_y > 0){ + columns += find_break_col(&line_pos, COLS, NULL); + openfile->current_y++; + } + + openfile->current_x = actual_x(openfile->current->data, mouse_x + columns); + #ifdef DEBUG fprintf(stderr, "do_mouse(): i > mouse_y, mouse_x = %d, current_x to = %lu\n", mouse_x, (unsigned long)openfile->current_x); @@ -1985,7 +1997,7 @@ { size_t current_len, i = 0; #ifndef NANO_TINY - size_t orig_lenpt = 0; + size_t orig_extra_lines = 0; #endif char *char_buf = charalloc(mb_cur_max()); @@ -1997,7 +2009,7 @@ #ifndef NANO_TINY if (ISSET(SOFTWRAP)) - orig_lenpt = strlenpt(openfile->current->data); + orig_extra_lines = openfile->current->extra_lines; #endif while (i < output_len) { @@ -2079,14 +2091,6 @@ #endif } -#ifndef NANO_TINY - /* Well, we might also need a full refresh if we've changed the - * line length to be a new multiple of COLS. */ - if (ISSET(SOFTWRAP) && edit_refresh_needed == FALSE) - if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS) - edit_refresh_needed = TRUE; -#endif - free(char_buf); openfile->placewewant = xplustabs(); @@ -2097,9 +2101,18 @@ if (edit_refresh_needed == TRUE) { edit_refresh(); edit_refresh_needed = FALSE; - } else + } else { update_line(openfile->current, openfile->current_x); + +#ifndef NANO_TINY + /* Well, we might also need a full refresh if we've changed the + * line length to be a new multiple of COLS. */ + if (ISSET(SOFTWRAP)) + if (openfile->current->extra_lines != orig_extra_lines) + edit_refresh_needed = TRUE; +#endif } +} int main(int argc, char **argv) { Index: src/nano.h =================================================================== --- src/nano.h (revision 5057) +++ src/nano.h (working copy) @@ -299,6 +299,8 @@ /* Next node. */ struct filestruct *prev; /* Previous node. */ + size_t extra_lines; + /* number of screen lines required. Equals 1 if not in softwrap mode */ #ifndef DISABLE_COLOR short *multidata; /* Array of which multi-line regexes apply to this line. */ Index: src/proto.h =================================================================== --- src/proto.h (revision 5057) +++ src/proto.h (working copy) @@ -787,7 +787,8 @@ void reset_cursor(void); void edit_draw(filestruct *fileptr, const char *converted, int line, size_t start); -int update_line(filestruct *fileptr, size_t index); +size_t find_break_col(const char **line, ssize_t goal, size_t *index); +size_t update_line(filestruct *fileptr, size_t index); bool need_horizontal_update(size_t pww_save); bool need_vertical_update(size_t pww_save); void edit_scroll(scroll_dir direction, ssize_t nlines); Index: src/text.c =================================================================== --- src/text.c (revision 5057) +++ src/text.c (working copy) @@ -67,7 +67,7 @@ void do_deletion(undo_type action) { #ifndef NANO_TINY - size_t orig_lenpt = 0; + size_t orig_extra_lines = 0; #endif assert(openfile->current != NULL && openfile->current->data != NULL && openfile->current_x <= strlen(openfile->current->data)); @@ -86,7 +86,7 @@ update_undo(action); if (ISSET(SOFTWRAP)) - orig_lenpt = strlenpt(openfile->current->data); + orig_extra_lines = openfile->current->extra_lines; #endif /* Let's get dangerous. */ @@ -143,16 +143,16 @@ } else return; + if (edit_refresh_needed == FALSE) + update_line(openfile->current, openfile->current_x); + #ifndef NANO_TINY if (ISSET(SOFTWRAP) && edit_refresh_needed == FALSE) - if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS) + if (openfile->current->extra_lines != orig_extra_lines) edit_refresh_needed = TRUE; #endif set_modified(); - - if (edit_refresh_needed == FALSE) - update_line(openfile->current, openfile->current_x); } void do_delete(void) @@ -1300,6 +1300,7 @@ /* Current column position in line. */ int char_len = 0; /* Length of current character, in bytes. */ + bool non_blank_found = FALSE; assert(line != NULL); @@ -1311,13 +1312,15 @@ || (newln && *line == '\n') #endif ) { + if(non_blank_found) blank_loc = cur_loc; #ifndef DISABLE_HELP if (newln && *line == '\n') break; #endif - } + } else + non_blank_found = TRUE; line += char_len; cur_loc += char_len; Index: src/utils.c =================================================================== --- src/utils.c (revision 5057) +++ src/utils.c (working copy) @@ -464,7 +464,7 @@ * get_page_start(column) < COLS). */ size_t get_page_start(size_t column) { - if (column == 0 || column < COLS - 1) + if (ISSET(SOFTWRAP) || column == 0 || column < COLS - 1) return 0; else if (COLS > 8) return column - 7 - (column - 7) % (COLS - 8); @@ -550,6 +550,7 @@ openfile->filebot->next->prev = openfile->filebot; openfile->filebot->next->next = NULL; openfile->filebot->next->lineno = openfile->filebot->lineno + 1; + openfile->filebot->extra_lines = 0; #ifndef DISABLE_COLOR openfile->filebot->next->multidata = NULL; #endif Index: src/winio.c =================================================================== --- src/winio.c (revision 5057) +++ src/winio.c (working copy) @@ -2435,12 +2435,38 @@ wattroff(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum); } } +/* Get the current row and column of current line wrt current_x. + Assumes the function is called with softwrap enabled + doesn't fail otherwise, however */ +size_t get_softwrap_row(ssize_t *current_y) +{ + size_t line_col; + filestruct *tmp; + openfile->current_y = 0; + for (tmp = openfile->edittop; tmp && tmp != openfile->current; tmp = tmp->next) + openfile->current_y += tmp->extra_lines + 1; + + size_t index = 0, lines = 0; + const char *line_pos = openfile->current->data; + size_t length = 0; + while(lines <= openfile->current->extra_lines && length <= openfile->current_x){ + lines++; + find_break_col(&line_pos, COLS, &index); + length += (index); + } + + line_pos-=index; + length -= index ; + length = openfile->current_x - length ; + line_col = strnlenpt(line_pos, length); + openfile->current_y+= (lines-1); + return line_col; +} /* Reset current_y, based on the position of current, and put the cursor * in the edit window at (current_y, current_x). */ void reset_cursor(void) { - size_t xpt; /* If we haven't opened any files yet, put the cursor in the top * left corner of the edit window and get out. */ if (openfile == NULL) { @@ -2448,22 +2474,15 @@ return; } - xpt = xplustabs(); - #ifndef NANO_TINY if (ISSET(SOFTWRAP)) { - filestruct *tmp; - openfile->current_y = 0; - - for (tmp = openfile->edittop; tmp && tmp != openfile->current; tmp = tmp->next) - openfile->current_y += (strlenpt(tmp->data) / COLS) + 1; - - openfile->current_y += xplustabs() / COLS; + size_t line_col = get_softwrap_row(&openfile->current_y); if (openfile->current_y < editwinrows) - wmove(edit, openfile->current_y, xpt % COLS); + wmove(edit, openfile->current_y, line_col); } else #endif { + size_t xpt = xplustabs(); openfile->current_y = openfile->current->lineno - openfile->edittop->lineno; @@ -2851,28 +2870,56 @@ #endif /* !NANO_TINY */ } +size_t find_break_col(const char **line, ssize_t goal, size_t *location) +{ + size_t column; + size_t index = break_line(*line, goal +#ifndef DISABLE_HELP + , FALSE +#endif + ); + + if(index==-1 || strnlenpt(*line,index) >=goal){ + column = goal; + index = actual_x(*line, goal); + }else{ + /*move forward to the character just after the blank. */ + index += parse_mbchar(*line+index, NULL, NULL); + column = strnlenpt(*line, index); + } + + *line += index; + + if(location) + *location=index; + + return column; +} + /* Just update one line in the edit buffer. This is basically a wrapper * for edit_draw(). The line will be displayed starting with * fileptr->data[index]. Likely arguments are current_x or zero. * Returns: Number of additional lines consumed (needed for SOFTWRAP). */ -int update_line(filestruct *fileptr, size_t index) +size_t update_line(filestruct *fileptr, size_t index) { int line = 0; /* The line in the edit window that we want to update. */ - int extralinesused = 0; char *converted; /* fileptr->data converted to have tabs and control characters * expanded. */ - size_t page_start; + size_t page_start=0; + size_t end_col = COLS; assert(fileptr != NULL); + fileptr->extra_lines = 0; #ifndef NANO_TINY + const char* line_pos; if (ISSET(SOFTWRAP)) { filestruct *tmp; for (tmp = openfile->edittop; tmp && tmp != fileptr; tmp = tmp->next) - line += (strlenpt(tmp->data) / COLS) + 1; + line += tmp->extra_lines + 1; } else #endif line = fileptr->lineno - openfile->edittop->lineno; @@ -2886,19 +2933,21 @@ /* Next, convert variables that index the line to their equivalent * positions in the expanded line. */ #ifndef NANO_TINY - if (ISSET(SOFTWRAP)) - index = 0; - else + if (ISSET(SOFTWRAP)){ + line_pos = fileptr->data; + end_col = find_break_col(&line_pos, COLS, &index); + } else #endif + { index = strnlenpt(fileptr->data, index); page_start = get_page_start(index); - + } /* Expand the line, replacing tabs with spaces, and control * characters with their displayed forms. */ #ifdef NANO_TINY converted = display_string(fileptr->data, page_start, COLS, TRUE); #else - converted = display_string(fileptr->data, page_start, COLS, !ISSET(SOFTWRAP)); + converted = display_string(fileptr->data, page_start, end_col, !ISSET(SOFTWRAP)); #ifdef DEBUG if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2) fprintf(stderr, "update_line(): converted(1) line = %s\n", converted); @@ -2918,9 +2967,12 @@ mvwaddch(edit, line, COLS - 1, '$'); #ifndef NANO_TINY } else { - size_t full_length = strlenpt(fileptr->data); - for (index += COLS; index <= full_length && line < editwinrows; index += COLS) { + size_t length = strlen(fileptr->data)-(index-1); + while(length>0){ + page_start += end_col; line++; + end_col = find_break_col(&line_pos, COLS, &index); + length -= (index); #ifdef DEBUG fprintf(stderr, "update_line(): softwrap code, moving to %d index %lu\n", line, (unsigned long)index); #endif @@ -2928,20 +2980,21 @@ /* Expand the line, replacing tabs with spaces, and control * characters with their displayed forms. */ - converted = display_string(fileptr->data, index, COLS, !ISSET(SOFTWRAP)); + converted = display_string(line_pos-index, 0, end_col, FALSE); #ifdef DEBUG if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2) fprintf(stderr, "update_line(): converted(2) line = %s\n", converted); #endif /* Paint the line. */ - edit_draw(fileptr, converted, line, index); + edit_draw(fileptr, converted, line, page_start); free(converted); - extralinesused++; + fileptr->extra_lines++; } } #endif /* !NANO_TINY */ - return extralinesused; + + return fileptr->extra_lines; } /* Return TRUE if we need an update after moving horizontally, and FALSE @@ -2985,7 +3038,7 @@ maxrows = 0; for (n = 0; n < editwinrows && foo; n++) { maxrows++; - n += strlenpt(foo->data) / COLS; + n += foo->extra_lines; foo = foo->next; } @@ -3036,7 +3089,7 @@ #ifndef NANO_TINY /* Don't over-scroll on long lines. */ if (ISSET(SOFTWRAP) && direction == UPWARD) { - ssize_t len = strlenpt(openfile->edittop->data) / COLS; + ssize_t len = openfile->edittop->extra_lines; i -= len; if (len > 0) do_redraw = TRUE; @@ -3284,7 +3337,7 @@ foo = foo->prev; #ifndef NANO_TINY if (ISSET(SOFTWRAP) && foo) - goal -= strlenpt(foo->data) / COLS; + goal -= foo->extra_lines; #endif } openfile->edittop = foo;