From f478b159c09394f201bfa77cfad7e484e8f0b20f 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  | 18 +++++++++++++++---
 7 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/src/cut.c b/src/cut.c
index 8521ad3a..0d80784e 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -221,6 +221,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;
 
@@ -236,6 +237,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 21485a47..06dca50f 100644
--- a/src/files.c
+++ b/src/files.c
@@ -124,6 +124,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;
 }
@@ -603,8 +604,10 @@ void switch_to_adjacent_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 b3888d9d..8d35be87 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1395,8 +1395,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 3fff8401..005b7697 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -371,6 +371,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 4e59b649..dd50dcf2 100644
--- a/src/search.c
+++ b/src/search.c
@@ -723,7 +723,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;
 
@@ -765,6 +765,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;
 
@@ -773,6 +774,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 a7ec9561..4be54aaa 100644
--- a/src/text.c
+++ b/src/text.c
@@ -2195,6 +2195,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
@@ -2504,6 +2505,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
@@ -2565,6 +2567,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;
@@ -2683,6 +2686,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 f7ca5fc8..9c5536ac 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -2378,7 +2378,7 @@ void place_the_cursor(void)
 	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) {
@@ -2826,7 +2826,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) {
@@ -2996,6 +2996,11 @@ void edit_scroll(bool direction, int nrows)
     else
 	nrows -= go_forward_chunks(nrows, &openfile->edittop, &openfile->firstcolumn);
 
+#ifndef NANO_TINY
+    if (ISSET(SOFTWRAP))
+	openfile->chunks_before_firstcolumn = chunk_for(openfile->firstcolumn, openfile->edittop);
+#endif
+
     /* Don't bother scrolling zero rows, nor more than the window can hold. */
     if (nrows == 0) {
 #ifndef NANO_TINY
@@ -3040,7 +3045,7 @@ void edit_scroll(bool 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
 
@@ -3181,6 +3186,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;
@@ -3359,6 +3366,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
 }
 
 /* Unconditionally redraw the entire screen. */
-- 
2.14.1

