From 770dfddfd21646f00bb81ddbf00a99a4dfc6bcc8 Mon Sep 17 00:00:00 2001
From: Benno Schulenberg <bensberg@telfort.nl>
Date: Sat, 25 Apr 2020 17:19:03 +0200
Subject: [PATCH] possible new feature: a position+portion indicator on the
 righthand side
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

V2: Use an array to remember what character plus attribute
    each scrollbar cell should contain.

[This scrollbar is optionless for the moment, for ease of testing.]

[The scrollbar is suppressed in softwrap mode, because it costs
too much computation to determine the total number of chunks, and
the number of displayed chunks is known only after the screen is
fully drawn, not while drawing it.]

This fulfills https://savannah.gnu.org/bugs/?57956.

Original-patch-by: Marco Diego Aurélio Mesquita <marcodiegomesquita@gmail.com>
---
 src/global.c |  4 ++++
 src/help.c   | 10 +++++-----
 src/nano.c   | 21 +++++++++++++++++----
 src/proto.h  |  2 ++
 src/winio.c  | 45 ++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/src/global.c b/src/global.c
index a6999e72..7e0a6e30 100644
--- a/src/global.c
+++ b/src/global.c
@@ -131,7 +131,11 @@ int editwincols = -1;
 		/* The number of usable columns in the edit window: COLS - margin. */
 int margin = 0;
 		/* The amount of space reserved at the left for line numbers. */
+int thebar = 0;
+		/* Becomes 1 when a scrollbar is shown. */
 #ifndef NANO_TINY
+int *bardata = NULL;
+		/* An array of characters that together depict the scrollbar. */
 ssize_t stripe_column = 0;
 		/* The column at which a vertical bar will be drawn. */
 #endif
diff --git a/src/help.c b/src/help.c
index 59a45a4d..664ade00 100644
--- a/src/help.c
+++ b/src/help.c
@@ -44,7 +44,7 @@ void wrap_help_text_into_buffer(void)
 {
 	size_t sum = 0;
 	/* Avoid overtight and overwide paragraphs in the introductory text. */
-	size_t wrapping_point = (COLS < 40) ? 40 : (COLS > 74) ? 74 : COLS;
+	size_t wrapping_point = ((COLS < 40) ? 40 : (COLS > 74) ? 74 : COLS) - thebar;
 	const char *ptr = start_of_body;
 
 	make_new_buffer();
@@ -55,7 +55,7 @@ void wrap_help_text_into_buffer(void)
 		char *oneline;
 
 		if (ptr == end_of_intro)
-			wrapping_point = (COLS < 40) ? 40 : COLS;
+			wrapping_point = ((COLS < 40) ? 40 : COLS) - thebar;
 
 		if (ptr < end_of_intro || *(ptr - 1) == '\n') {
 			length = break_line(ptr, wrapping_point, TRUE);
@@ -63,7 +63,7 @@ void wrap_help_text_into_buffer(void)
 			shim = (*(ptr + length - 1) == ' ') ? 0 : 1;
 			snprintf(oneline, length + shim, "%s", ptr);
 		} else {
-			length = break_line(ptr, (COLS < 40) ? 22 : COLS - 18, TRUE);
+			length = break_line(ptr, ((COLS < 40) ? 22 : COLS - 18) - thebar, TRUE);
 			oneline = nmalloc(length + 5);
 			snprintf(oneline, length + 5, "\t\t  %s", ptr);
 		}
@@ -145,7 +145,7 @@ void show_help(void)
 
 #ifdef ENABLE_LINENUMBERS
 	UNSET(LINE_NUMBERS);
-	editwincols = COLS;
+	editwincols = COLS - thebar;
 	margin = 0;
 #endif
 	tabsize = 8;
@@ -250,7 +250,7 @@ void show_help(void)
 
 #ifdef ENABLE_LINENUMBERS
 	margin = was_margin;
-	editwincols = COLS - margin;
+	editwincols = COLS - margin - thebar;
 #endif
 	tabsize = was_tabsize;
 #ifdef ENABLE_COLOR
diff --git a/src/nano.c b/src/nano.c
index 024a5f19..1f37bf1a 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1041,7 +1041,11 @@ void regenerate_screen(void)
 	COLS = win.ws_col;
 	LINES = win.ws_row;
 #endif
-	editwincols = COLS - margin;
+#ifndef NANO_TINY
+	thebar = (LINES > 5 && COLS > 9 && !ISSET(SOFTWRAP)) ? 1 : 0;
+	bardata = nrealloc(bardata, LINES * sizeof(int));
+#endif
+	editwincols = COLS - margin - thebar;
 
 	/* Ensure that firstcolumn is the starting column of its chunk. */
 	ensure_firstcolumn_is_aligned();
@@ -1082,8 +1086,13 @@ void do_toggle(int flag)
 			signal_init();
 			break;
 		case SOFTWRAP:
-			if (!ISSET(SOFTWRAP))
+			if (!ISSET(SOFTWRAP)) {
+				thebar = (LINES > 5 && COLS > 9) ? 1 : 0;
+				bardata = nrealloc(bardata, LINES * sizeof(int));
 				openfile->firstcolumn = 0;
+			} else
+				thebar  = 0;
+			editwincols = COLS - margin - thebar;
 			refresh_needed = TRUE;
 			break;
 		case WHITESPACE_DISPLAY:
@@ -1245,7 +1254,7 @@ void confirm_margin(void)
 
 	if (needed_margin != margin) {
 		margin = needed_margin;
-		editwincols = COLS - margin;
+		editwincols = COLS - margin - thebar;
 
 #ifndef NANO_TINY
 		/* Ensure that firstcolumn is the starting column of its chunk. */
@@ -2273,7 +2282,11 @@ int main(int argc, char **argv)
 	window_init();
 	curs_set(0);
 
-	editwincols = COLS;
+#ifndef NANO_TINY
+	thebar = (LINES > 5 && COLS > 9 && !ISSET(SOFTWRAP)) ? 1 : 0;
+	bardata = nrealloc(bardata, LINES * sizeof(int));
+#endif
+	editwincols = COLS - thebar;
 
 	/* Set up the signal handlers. */
 	signal_init();
diff --git a/src/proto.h b/src/proto.h
index 9ee22d6d..fbfc04b6 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -93,7 +93,9 @@ extern WINDOW *bottomwin;
 extern int editwinrows;
 extern int editwincols;
 extern int margin;
+extern int thebar;
 #ifndef NANO_TINY
+extern int *bardata;
 extern ssize_t stripe_column;
 #endif
 
diff --git a/src/winio.c b/src/winio.c
index eb89e16d..3eb836d3 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -2412,6 +2412,9 @@ void draw_row(int row, const char *converted, linestruct *line, size_t from_col)
 	if (is_shorter || ISSET(SOFTWRAP))
 		wclrtoeol(edit);
 
+	if (is_shorter && thebar)
+		mvwaddch(edit, row, COLS - 1, bardata[row]);
+
 #ifdef USING_OLD_NCURSES
 	/* Tell ncurses to really redraw the line without trying to optimize
 	 * for what it thinks is already there, because it gets it wrong in
@@ -2780,7 +2783,7 @@ int update_line(linestruct *line, size_t index)
 	}
 	if (has_more) {
 		wattron(edit, hilite_attribute);
-		mvwaddch(edit, row, COLS - 1, '>');
+		mvwaddch(edit, row, COLS - 1 - thebar, '>');
 		wattroff(edit, hilite_attribute);
 	}
 
@@ -2960,6 +2963,28 @@ bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge)
 		return (openfile->current->lineno - was_lineno < editwinrows);
 }
 
+#ifndef NANO_TINY
+/* Draw a scroll bar on the righthand side of the screen. */
+void draw_scrollbar(void)
+{
+	int totalrows = openfile->filebot->lineno;
+	int lowest = ((openfile->edittop->lineno - 1) * editwinrows) / totalrows;
+	int highest = lowest + (editwinrows * editwinrows) / totalrows;
+
+	if (editwinrows > totalrows)
+		highest = editwinrows;
+
+	for (int row = 0; row < editwinrows; row++) {
+		if (row >= lowest && row <= highest)
+			bardata[row] = ' '|A_REVERSE;
+		else
+			bardata[row] = ' '|A_REVERSE|A_DIM;
+
+		mvwaddch(edit, row, COLS - 1, bardata[row]);
+	}
+}
+#endif
+
 /* Scroll the edit window one row in the given direction, and
  * draw the relevant content on the resultant blank row. */
 void edit_scroll(bool direction)
@@ -3010,6 +3035,11 @@ void edit_scroll(bool direction)
 										openfile->current_x : 0);
 		line = line->next;
 	}
+
+#ifndef NANO_TINY
+	if (thebar)
+		draw_scrollbar();
+#endif
 }
 
 #ifndef NANO_TINY
@@ -3246,8 +3276,13 @@ void edit_redraw(linestruct *old_current, update_type manner)
 	 * differs from old_current and needs to be horizontally scrolled. */
 	if (line_needs_update(was_pww, openfile->placewewant) ||
 						(old_current != openfile->current &&
-						get_page_start(openfile->placewewant) > 0))
+						get_page_start(openfile->placewewant) > 0)) {
 		update_line(openfile->current, openfile->current_x);
+#ifndef NANO_TINY
+		if (thebar)
+			draw_scrollbar();
+#endif
+	}
 }
 
 /* Refresh the screen without changing the position of lines.  Use this
@@ -3280,6 +3315,10 @@ void edit_refresh(void)
 	while (row < editwinrows)
 		blank_row(edit, row++);
 
+#ifndef NANO_TINY
+	if (thebar)
+		draw_scrollbar();
+#endif
 	place_the_cursor();
 	wnoutrefresh(edit);
 
@@ -3426,7 +3465,7 @@ void spotlight(size_t from_col, size_t to_col)
 	wattron(edit, interface_color_pair[SELECTED_TEXT]);
 	waddnstr(edit, word, actual_x(word, to_col));
 	if (overshoots)
-		mvwaddch(edit, openfile->current_y, COLS - 1, '>');
+		mvwaddch(edit, openfile->current_y, COLS - 1 - thebar, '>');
 	wattroff(edit, interface_color_pair[SELECTED_TEXT]);
 
 	free(word);
-- 
2.25.4

