From 80bfdcf409b4bd694f19fdb24a287d31bf8c26b1 Mon Sep 17 00:00:00 2001
From: David Lawrence Ramsey <pooka109@gmail.com>
Date: Sun, 26 Aug 2018 21:46:44 -0500
Subject: [PATCH 02/16] justify: make justify_paragraph() work on its own
 buffer

It shouldn't only work on the current buffer.  This flexibility is
needed to make it undoable eventually.

This temporarily breaks justify somewhat.  The operations on the text
still work, and current is still moved to the line following the
paragraph, but edittop, totsize, and the mark are no longer handled.
Fixes for these are forthcoming.
---
 src/text.c | 147 +++++++++++++++++++++--------------------------------
 1 file changed, 59 insertions(+), 88 deletions(-)

diff --git a/src/text.c b/src/text.c
index 4c813e0d..a7d5298c 100644
--- a/src/text.c
+++ b/src/text.c
@@ -2153,17 +2153,20 @@ bool find_paragraph(size_t *const quote, size_t *const par)
 	return TRUE;
 }
 
-/* Run every line of the current paragraph through justify_format().  Assume
- * that current is at the beginning of the paragraph, quote_len is the length
+/* Run every line of par through justify_format().  Assume
+ * that firstline is at the beginning of the paragraph, quote_len is the length
  * of the paragraph's quote string, and par_len is the number of lines in the
- * paragraph. */
-void justify_paragraph(size_t quote_len, size_t par_len)
+ * paragraph.  Return the line following the justified paragraph in firstline,
+ * and return whether the last line of the paragraph is part of the paragraph
+ * (instead of the line following the paragraph). */
+bool justify_paragraph(filestruct **firstline, size_t quote_len,
+						size_t par_len)
 {
-	filestruct *firstline;
-		/* The first line of the current paragraph. */
 	filestruct *sampleline;
 		/* The line from which the indentation is copied -- either
 		 * the first and only or the second line of the paragraph. */
+	filestruct *jusline;
+		/* The line of the current paragraph that we're justifying. */
 	size_t lead_len;
 		/* Length of the quote part plus the indentation part. */
 	ssize_t break_pos;
@@ -2171,68 +2174,55 @@ void justify_paragraph(size_t quote_len, size_t par_len)
 	char *lead_string;
 		/* The quote+indent stuff that is copied from the sample line. */
 
-	/* Remember the first line of the current paragraph. */
-	firstline = openfile->current;
-
 	/* The sample line is either the only line or the second line. */
-	sampleline = (par_len == 1 ? firstline : firstline->next);
+	sampleline = (par_len == 1 ? *firstline : (*firstline)->next);
 
 	/* Copy the leading part (quoting + indentation) of the sample line. */
 	lead_len = quote_len + indent_length(sampleline->data + quote_len);
 	lead_string = mallocstrncpy(NULL, sampleline->data, lead_len + 1);
 	lead_string[lead_len] = '\0';
 
+	/* Start justifying on the first line. */
+	jusline = *firstline;
+
 	/* Now tack all the lines of the paragraph together, skipping
 	 * the quoting and indentation on all lines after the first. */
 	while (par_len > 1) {
-		filestruct *next_line = openfile->current->next;
-		size_t line_len = strlen(openfile->current->data);
+		filestruct *next_line = jusline->next;
+		size_t line_len = strlen(jusline->data);
 		size_t next_line_len = strlen(next_line->data);
 
 		lead_len = quote_len + indent_length(next_line->data + quote_len);
 
 		/* We're just about to tack the next line onto this one.  If
 		 * this line isn't empty, make sure it ends in a space. */
-		if (line_len > 0 && openfile->current->data[line_len - 1] != ' ') {
-			openfile->current->data =
-						charealloc(openfile->current->data, line_len + 2);
-			openfile->current->data[line_len++] = ' ';
-			openfile->current->data[line_len] = '\0';
-			openfile->totsize++;
+		if (line_len > 0 && jusline->data[line_len - 1] != ' ') {
+			jusline->data =
+						charealloc(jusline->data, line_len + 2);
+			jusline->data[line_len++] = ' ';
+			jusline->data[line_len] = '\0';
 		}
 
-		openfile->current->data = charealloc(openfile->current->data,
+		jusline->data = charealloc(jusline->data,
 									line_len + next_line_len - lead_len + 1);
-		strcat(openfile->current->data, next_line->data + lead_len);
-
-#ifndef NANO_TINY
-		/* If needed, adjust the coordinates of the mark. */
-		if (openfile->mark == next_line) {
-			openfile->mark = openfile->current;
-			openfile->mark_x += line_len - lead_len;
-		}
-#endif
-		/* Don't destroy edittop! */
-		if (next_line == openfile->edittop)
-			openfile->edittop = openfile->current;
+		strcat(jusline->data, next_line->data + lead_len);
 
 		unlink_node(next_line);
-		openfile->totsize -= lead_len + 1;
 		par_len--;
 	}
 
 	/* Call justify_format() on the paragraph, which will remove excess
 	 * spaces from it and change all blank characters to spaces. */
-	justify_format(openfile->current, quote_len +
-					indent_length(openfile->current->data + quote_len));
+	justify_format(jusline, quote_len +
+					indent_length(jusline->data + quote_len));
 
-	while (par_len > 0 && strlenpt(openfile->current->data) > wrap_at) {
-		size_t line_len = strlen(openfile->current->data);
+	while (par_len > 0 && strlenpt(jusline->data) > wrap_at) {
+		size_t line_len = strlen(jusline->data);
 
 		/* If this line is too long, try to wrap it to the next line
 		 * to make it short enough. */
-		break_pos = break_line(openfile->current->data + lead_len,
-				wrap_at - strnlenpt(openfile->current->data, lead_len), FALSE);
+		break_pos = break_line(jusline->data + lead_len,
+				wrap_at - strnlenpt(jusline->data, lead_len), FALSE);
 
 		/* If we can't break the line, or don't need to, we're done. */
 		if (break_pos == -1 || break_pos + lead_len == line_len)
@@ -2243,57 +2233,48 @@ void justify_paragraph(size_t quote_len, size_t par_len)
 		break_pos += lead_len + 1;
 
 		/* Insert a new line after the current one and allocate it. */
-		splice_node(openfile->current, make_new_node(openfile->current));
-		openfile->current->next->data = charalloc(lead_len + 1 +
+		splice_node(jusline, make_new_node(jusline));
+		jusline->next->data = charalloc(lead_len + 1 +
 													line_len - break_pos);
 
 		/* Copy the leading part and the text after the breaking point
 		 * into the next line. */
-		strncpy(openfile->current->next->data, lead_string, lead_len);
-		strcpy(openfile->current->next->data + lead_len,
-										openfile->current->data + break_pos);
+		strncpy(jusline->next->data, lead_string, lead_len);
+		strcpy(jusline->next->data + lead_len,
+										jusline->data + break_pos);
 
-		openfile->totsize += lead_len + 1;
 		par_len++;
 
-#ifndef NANO_TINY
-		/* If needed, compensate the mark coordinates for the change
-		 * in the current line. */
-		if (openfile->mark == openfile->current &&
-					openfile->mark_x > break_pos) {
-			openfile->mark = openfile->current->next;
-			openfile->mark_x -= break_pos - lead_len;
-		}
-#endif
 		/* When requested, snip all trailing blanks. */
 		if (ISSET(TRIM_BLANKS)) {
 			while (break_pos > 0 &&
-					is_blank_mbchar(&openfile->current->data[break_pos - 1])) {
+					is_blank_mbchar(&jusline->data[break_pos - 1])) {
 				break_pos--;
-				openfile->totsize--;
 			}
 		}
 
 		/* Break the current line. */
-		null_at(&openfile->current->data, break_pos);
+		null_at(&jusline->data, break_pos);
 
 		/* Go to the next line. */
-		openfile->current = openfile->current->next;
+		jusline = jusline->next;
 		par_len--;
 	}
 
 	free(lead_string);
 
+	/* We're on the last line of the paragraph.  Save it. */
+	*firstline = jusline;
+
 	/* Go to the next line, if possible.  If there is no next line,
-	 * move to the end of the current line. */
-	if (openfile->current != openfile->filebot)
-		openfile->current = openfile->current->next;
-	else
-		openfile->current_x = strlen(openfile->current->data);
+	 * the last line is part of the paragraph (instead of the line following
+	 * the paragraph). */
+	if ((*firstline)->next != NULL) {
+		*firstline = (*firstline)->next;
+		return FALSE;
+	}
 
-	/* Renumber the now-justified paragraph, since both refreshing the
-	 * edit window and finding a paragraph need correct line numbers. */
-	renumber(firstline);
+	return TRUE;
 }
 
 /* Justify the current paragraph, and justify the entire file when
@@ -2322,10 +2303,6 @@ void do_justify(bool full_justify)
 	size_t firstcolumn_save = openfile->firstcolumn;
 	filestruct *current_save = openfile->current;
 	size_t current_x_save = openfile->current_x;
-#ifndef NANO_TINY
-	filestruct *was_mark = openfile->mark;
-	size_t was_mark_x = openfile->mark_x;
-#endif
 	bool modified_save = openfile->modified;
 
 	/* Move to the beginning of the current line, so that justifying at
@@ -2357,14 +2334,20 @@ void do_justify(bool full_justify)
 	/* Search for a paragraph(s) and justify them.  If we're justifying the
 	 * whole file, loop until we've found every paragraph. */
 	do {
-		/* par_len will be one greater than the number of lines between
-		 * current and filebot if filebot is the last line in the
-		 * paragraph.  Set filebot_inpar to TRUE if this is the case. */
-		filebot_inpar = (openfile->current->lineno + par_len ==
-								openfile->filebot->lineno + 1);
+		filestruct *current_save = openfile->current;
 
 		/* Justify the current paragraph. */
-		justify_paragraph(quote_len, par_len);
+		filebot_inpar = justify_paragraph(&openfile->current, quote_len,
+											par_len);
+
+		/* Renumber the now-justified paragraph, since both refreshing the
+		 * edit window and finding a paragraph need correct line numbers. */
+		renumber(current_save);
+
+		/* If the last line of the paragraph is the last line of the file, move
+		 * to the end of that line. */
+		if (filebot_inpar)
+			openfile->current_x = strlen(openfile->current->data);
 
 	/* If we're justifying the entire file,
 	 * find the next line of the paragraph(s) to be justified.
@@ -2379,12 +2362,6 @@ void do_justify(bool full_justify)
 	 * this should be the last line of the file. */
 	last_par_line = openfile->current;
 
-#ifndef NANO_TINY
-	/* Let a justification cancel a soft mark. */
-	if (openfile->mark && openfile->kind_of_mark == SOFTMARK)
-		openfile->mark = NULL;
-#endif
-
 	edit_refresh();
 
 	/* Show "Unjustify" in the help lines. */
@@ -2425,17 +2402,11 @@ void do_justify(bool full_justify)
 		free_filestruct(trash);
 		ingraft_buffer(jusbuffer);
 
-		/* Restore the old position and the mark. */
+		/* Restore the old position. */
 		openfile->edittop = edittop_save;
 		openfile->firstcolumn = firstcolumn_save;
 		openfile->current = current_save;
 		openfile->current_x = current_x_save;
-#ifndef NANO_TINY
-		if (openfile->mark) {
-			openfile->mark = was_mark;
-			openfile->mark_x = was_mark_x;
-		}
-#endif
 		openfile->modified = modified_save;
 		if (!openfile->modified)
 			titlebar(NULL);
-- 
2.17.1

