From 7413e52c15bd07c94b031fdca8d34bd4cca08b81 Mon Sep 17 00:00:00 2001
From: David Lawrence Ramsey <pooka109@gmail.com>
Date: Wed, 19 Jul 2017 20:36:48 -0500
Subject: [PATCH] softwrap: save the number of softwrapped chunks before
 firstcolumn

This is much faster than calculating it on the fly every time.
Accordingly, only recalculate it when firstcolumn changes.
---
 src/cut.c    |  2 ++
 src/files.c  |  5 ++++-
 src/nano.c   |  4 +++-
 src/nano.h   |  4 ++++
 src/search.c |  4 +++-
 src/text.c   |  4 ++++
 src/winio.c  | 15 ++++++++++++---
 7 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/src/cut.c b/src/cut.c
index 43f87e2..25ff992 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -225,6 +225,7 @@ void do_copy_text(void)
     /* Remember the current viewport and cursor position. */
     ssize_t is_edittop_lineno = openfile->edittop->lineno;
     size_t is_firstcolumn = openfile->firstcolumn;
+    size_t is_cbf = openfile->chunks_before_firstcolumn;
     ssize_t is_current_lineno = openfile->current->lineno;
     size_t is_current_x = openfile->current_x;
 
@@ -240,6 +241,7 @@ void do_copy_text(void)
 	/* Restore the viewport and cursor position. */
 	openfile->edittop = fsfromline(is_edittop_lineno);
 	openfile->firstcolumn = is_firstcolumn;
+	openfile->chunks_before_firstcolumn = is_cbf;
 	openfile->current = fsfromline(is_current_lineno);
 	openfile->current_x = is_current_x;
     }
diff --git a/src/files.c b/src/files.c
index bac0e1b..59546f9 100644
--- a/src/files.c
+++ b/src/files.c
@@ -125,6 +125,7 @@ void initialize_buffer_text(void)
     openfile->current = openfile->fileage;
 
     openfile->firstcolumn = 0;
+    openfile->chunks_before_firstcolumn = 0;
     openfile->current_x = 0;
     openfile->totsize = 0;
 }
@@ -618,8 +619,10 @@ void switch_to_prevnext_buffer(bool to_next)
     /* When not in softwrap mode, make sure firstcolumn is zero.  It might
      * be nonzero if we had softwrap mode on while in this buffer, and then
      * turned softwrap mode off while in a different buffer. */
-    if (!ISSET(SOFTWRAP))
+    if (!ISSET(SOFTWRAP)) {
 	openfile->firstcolumn = 0;
+	openfile->chunks_before_firstcolumn = 0;
+    }
 #endif
 
     /* Update titlebar and multiline info to match the current buffer. */
diff --git a/src/nano.c b/src/nano.c
index b82245a..f29e06b 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1393,8 +1393,10 @@ void do_toggle(int flag)
 	    signal_init();
 	    break;
 	case SOFTWRAP:
-	    if (!ISSET(SOFTWRAP))
+	    if (!ISSET(SOFTWRAP)) {
 		openfile->firstcolumn = 0;
+		openfile->chunks_before_firstcolumn = 0;
+	    }
 	    refresh_needed = TRUE;
 	    break;
 	case WHITESPACE_DISPLAY:
diff --git a/src/nano.h b/src/nano.h
index c6ea016..674683e 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -362,6 +362,10 @@ typedef struct openfilestruct {
     size_t firstcolumn;
 	/* The starting column of the top line of the edit window.
 	 * When not in softwrap mode, it's always zero. */
+    size_t chunks_before_firstcolumn;
+	/* The number of softwrapped chunks before the starting column of the
+	 * top line of the edit window.  When not in softwrap mode, it's always
+	 * zero. */
     size_t current_x;
 	/* The file's x-coordinate position. */
     size_t placewewant;
diff --git a/src/search.c b/src/search.c
index 4c7ec5c..5b40cc2 100644
--- a/src/search.c
+++ b/src/search.c
@@ -736,7 +736,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
 void do_replace(void)
 {
     filestruct *edittop_save, *begin;
-    size_t firstcolumn_save, begin_x;
+    size_t firstcolumn_save, cbf_save, begin_x;
     ssize_t numreplaced;
     int i;
 
@@ -781,6 +781,7 @@ void do_replace(void)
     /* Save where we are. */
     edittop_save = openfile->edittop;
     firstcolumn_save = openfile->firstcolumn;
+    cbf_save = openfile->chunks_before_firstcolumn;
     begin = openfile->current;
     begin_x = openfile->current_x;
 
@@ -789,6 +790,7 @@ void do_replace(void)
     /* Restore where we were. */
     openfile->edittop = edittop_save;
     openfile->firstcolumn = firstcolumn_save;
+    openfile->chunks_before_firstcolumn = cbf_save;
     openfile->current = begin;
     openfile->current_x = begin_x;
     refresh_needed = TRUE;
diff --git a/src/text.c b/src/text.c
index fda7458..9a68b96 100644
--- a/src/text.c
+++ b/src/text.c
@@ -2163,6 +2163,7 @@ void do_justify(bool full_justify)
      * unjustifies. */
     filestruct *edittop_save = openfile->edittop;
     size_t firstcolumn_save = openfile->firstcolumn;
+    size_t cbf_save = openfile->chunks_before_firstcolumn;
     filestruct *current_save = openfile->current;
     size_t current_x_save = openfile->current_x;
 #ifndef NANO_TINY
@@ -2475,6 +2476,7 @@ void do_justify(bool full_justify)
 	    /* Restore the old position and the mark. */
 	    openfile->edittop = edittop_save;
 	    openfile->firstcolumn = firstcolumn_save;
+	    openfile->chunks_before_firstcolumn = cbf_save;
 	    openfile->current = current_save;
 	    openfile->current_x = current_x_save;
 #ifndef NANO_TINY
@@ -2536,6 +2538,7 @@ bool do_int_spell_fix(const char *word)
 {
     char *save_search;
     size_t firstcolumn_save = openfile->firstcolumn;
+    size_t cbf_save = openfile->chunks_before_firstcolumn;
     size_t current_x_save = openfile->current_x;
     filestruct *edittop_save = openfile->edittop;
     filestruct *current_save = openfile->current;
@@ -2657,6 +2660,7 @@ bool do_int_spell_fix(const char *word)
     /* Restore the viewport to where it was. */
     openfile->edittop = edittop_save;
     openfile->firstcolumn = firstcolumn_save;
+    openfile->chunks_before_firstcolumn = cbf_save;
 
     /* Restore the settings of the global flags. */
     memcpy(flags, stash, sizeof(flags));
diff --git a/src/winio.c b/src/winio.c
index 2d8ffc4..bc7666a 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -2285,7 +2285,7 @@ void place_the_cursor(bool forreal)
 	filestruct *line = openfile->edittop;
 	size_t leftedge;
 
-	row -= chunk_for(openfile->firstcolumn, openfile->edittop);
+	row -= openfile->chunks_before_firstcolumn;
 
 	/* Calculate how many rows the lines from edittop to current use. */
 	while (line != NULL && line != openfile->current) {
@@ -2737,7 +2737,7 @@ int update_softwrapped_line(filestruct *fileptr)
     if (fileptr == openfile->edittop)
 	from_col = openfile->firstcolumn;
     else
-	row -= chunk_for(openfile->firstcolumn, openfile->edittop);
+	row -= openfile->chunks_before_firstcolumn;
 
     /* Find out on which screen row the target line should be shown. */
     while (line != fileptr && line != NULL) {
@@ -2907,6 +2907,8 @@ void edit_scroll(scroll_dir direction, int nrows)
     else
 	nrows -= go_forward_chunks(nrows, &openfile->edittop, &openfile->firstcolumn);
 
+    openfile->chunks_before_firstcolumn = chunk_for(openfile->firstcolumn, openfile->edittop);
+
     /* Don't bother scrolling zero rows, nor more than the window can hold. */
     if (nrows == 0) {
 #ifndef NANO_TINY
@@ -2950,7 +2952,7 @@ void edit_scroll(scroll_dir direction, int nrows)
 
     /* Don't compensate for the chunks that are offscreen. */
     if (line == openfile->edittop)
-	nrows -= chunk_for(openfile->firstcolumn, line);
+	nrows -= openfile->chunks_before_firstcolumn;
 #endif
 
     /* Draw new content on the blank rows inside the scrolled region
@@ -3082,6 +3084,8 @@ void ensure_firstcolumn_is_aligned(void)
 {
     openfile->firstcolumn = leftedge_for(openfile->firstcolumn,
 						openfile->edittop);
+    openfile->chunks_before_firstcolumn = chunk_for(openfile->firstcolumn,
+						openfile->edittop);
 
     /* If smooth scrolling is on, make sure the viewport doesn't center. */
     focusing = FALSE;
@@ -3270,6 +3274,11 @@ void adjust_viewport(update_type manner)
     /* Move edittop back goal rows, starting at current[current_x]. */
     go_back_chunks(goal, &openfile->edittop, &openfile->firstcolumn);
 
+#ifndef NANO_TINY
+    if (ISSET(SOFTWRAP))
+	openfile->chunks_before_firstcolumn = chunk_for(openfile->firstcolumn, openfile->edittop);
+#endif
+
 #ifdef DEBUG
     fprintf(stderr, "adjust_viewport(): setting edittop to lineno %ld\n", (long)openfile->edittop->lineno);
 #endif
-- 
2.9.0

