[misc] [PATCH] Support page scroll in the key configuration window.

Add generic-scroll-up/down to key bindings in the key configuration
window and implement support for them.

Minor fixes in arrow key (up/down) scrolling.
---
In calcurse, windows scrollling is done with the arrow keys up/down, or
whichever keys are bound to the actions move-up/down. But calcurse also has
the actions generic-scroll-up/down. They are only supported by the calendar
and todo windows and really act as a toggle between two states; there is
no difference between scrolling up and down.

The key configuration window is by far the one with the most entries. If you
look closely, you will notice that the scrolling is not quite accurate and
different from the other windows with scrolling. It becomes more noticeable
with compact panels enabled. The patch fixes this, but the major change is
scrolling by page.

Maybe a new action, generic-toggle, should be introduced for the action in the
calendar and todo windows?

 src/custom.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 87 insertions(+), 18 deletions(-)

diff --git a/src/custom.c b/src/custom.c
index 52bdd5b..2338dcb 100644
--- a/src/custom.c
+++ b/src/custom.c
@@ -917,7 +917,8 @@ static void custom_keys_config_bar(void)
 {
 	static int bindings[] = {
 		KEY_GENERIC_QUIT, KEY_GENERIC_HELP, KEY_ADD_ITEM, KEY_DEL_ITEM,
-		KEY_MOVE_UP, KEY_MOVE_DOWN, KEY_MOVE_LEFT, KEY_MOVE_RIGHT
+		KEY_MOVE_UP, KEY_MOVE_DOWN, KEY_MOVE_LEFT, KEY_MOVE_RIGHT,
+		KEY_GENERIC_SCROLL_UP, KEY_GENERIC_SCROLL_DOWN
 	};
 	int bindings_size = ARRAY_SIZE(bindings);
 
@@ -933,10 +934,21 @@ void custom_keys_config(void)
 	const char *keystr;
 	WINDOW *grabwin;
 	const int LINESPERKEY = 2;
-	const int LABELLINES = 3;
+	int ROWS, hiddenrows, scrollrows;
 
 	clear();
-	nbdisplayed = ((notify_bar() ? row - 3 : row - 2) - LABELLINES) / LINESPERKEY;
+	ROWS = row - STATUSHEIGHT
+		   - (notify_bar() ? 1 : 0)
+		   - (conf.compact_panels ? 2 : 4);
+	/*
+	 * The integer hiddenrows counts the number of lines per
+	 * key not visible: 0, > 0 (at the top) or < 0 (at the bottom).
+	 * Initially they will be at the bottom, if any.
+	 */
+	hiddenrows = -1 * (LINESPERKEY - ROWS % LINESPERKEY) % LINESPERKEY;
+	nbdisplayed =  ROWS / LINESPERKEY + (hiddenrows ? 1 : 0);
+	firstrow = 0;
+	lastrow = firstrow + nbdisplayed - 1;
 	wins_scrollwin_init(&kwin, 0, 0, notify_bar() ? row - 3 : row - 2, col, _("keys configuration"));
 	wins_scrollwin_set_linecount(&kwin, NBKEYS * LINESPERKEY);
 	wins_scrollwin_draw_deco(&kwin, 0);
@@ -944,35 +956,93 @@ void custom_keys_config(void)
 	selrow = selelm = 0;
 	nbrowelm = print_keys_bindings(kwin.inner, selrow, selelm, LINESPERKEY);
 	wins_scrollwin_display(&kwin);
-	firstrow = 0;
-	lastrow = firstrow + nbdisplayed - 1;
 	for (;;) {
 		int key = keys_get(win[KEY].p, NULL, NULL);
 
 		switch (key) {
 		case KEY_MOVE_UP:
 			if (selrow > 0) {
-				selrow--;
-				selelm = 0;
 				if (selrow == firstrow) {
 					firstrow--;
-					lastrow--;
-					wins_scrollwin_up(&kwin,
-							  LINESPERKEY);
+					if (hiddenrows > 0) {
+						scrollrows = hiddenrows;
+						hiddenrows *= -1;
+					} else {
+						scrollrows = LINESPERKEY;
+						lastrow--;
+					}
+					wins_scrollwin_up(&kwin, scrollrows);
 				}
+				selrow--;
+				selelm = 0;
 			}
 			break;
 		case KEY_MOVE_DOWN:
 			if (selrow < NBKEYS - 1) {
+				if ((selrow + 1 == lastrow && hiddenrows < 0) || selrow == lastrow) {
+					firstrow++;
+					if (hiddenrows < 0) {
+						hiddenrows *= -1;
+						scrollrows = hiddenrows;
+					} else {
+						scrollrows = LINESPERKEY;
+						lastrow++;
+					}
+					wins_scrollwin_down(&kwin, scrollrows);
+				}
 				selrow++;
 				selelm = 0;
-				if (selrow == lastrow) {
-					firstrow++;
-					lastrow++;
-					wins_scrollwin_down(&kwin,
-							    LINESPERKEY);
+			}
+			break;
+		case KEY_GENERIC_SCROLL_UP:
+			if (firstrow < nbdisplayed) {
+				if (hiddenrows > 0) {
+					scrollrows = (firstrow - 1) * LINESPERKEY + hiddenrows;
+					hiddenrows *= -1;
+					lastrow -= (firstrow - 1);
+					selrow -= firstrow;
+					selelm = 0;
+					firstrow = 0;
+				} else {
+					scrollrows = firstrow * LINESPERKEY;
+					lastrow -= firstrow;
+					selrow -= firstrow;
+					selelm = 0;
+					firstrow = 0;
+				}
+			} else {
+				scrollrows = nbdisplayed * LINESPERKEY;
+				firstrow -= nbdisplayed;
+				lastrow -= nbdisplayed;
+				selrow -= nbdisplayed;
+				selelm = 0;
+			}
+			wins_scrollwin_up(&kwin, scrollrows);
+			break;
+		case KEY_GENERIC_SCROLL_DOWN:
+			if (lastrow > NBKEYS - nbdisplayed - 1) {
+				if (hiddenrows < 0) {
+					hiddenrows *= -1;
+					scrollrows = (NBKEYS - 1 - lastrow) * LINESPERKEY + hiddenrows;
+					firstrow += (NBKEYS - lastrow);
+					selrow += (NBKEYS - lastrow);
+					selelm = 0;
+					lastrow = NBKEYS - 1;
+				} else {
+					scrollrows = (NBKEYS - 1 - lastrow) * LINESPERKEY;
+					firstrow += (NBKEYS - 1 - lastrow);
+					selrow += (NBKEYS - 1 - lastrow);
+					selelm = 0;
+					lastrow = NBKEYS - 1;
 				}
+			} else {
+				scrollrows = nbdisplayed * LINESPERKEY;
+				firstrow += nbdisplayed;
+				lastrow += nbdisplayed;
+				selrow += nbdisplayed;
+				selelm = 0;
 			}
+			wins_scrollwin_down(&kwin, scrollrows);
 			break;
 		case KEY_MOVE_LEFT:
 			if (selelm > 0)
@@ -1040,13 +1110,12 @@ void custom_keys_config(void)
 			wins_scrollwin_delete(&kwin);
 			return;
 		}
+		nbdisplayed = lastrow - firstrow + 1;
 
 		if (resize) {
 			resize = 0;
 			wins_reset_noupdate();
-			nbdisplayed = ((notify_bar() ? row - 3 : row - 2) -
-					LABELLINES) / LINESPERKEY;
-			lastrow = firstrow + nbdisplayed - 1;
+			nbdisplayed = lastrow - firstrow + 1;
 			wins_scrollwin_resize(&kwin, 0, 0,
 					notify_bar() ? row - 3 : row - 2, col);
 			wins_scrollwin_draw_deco(&kwin, 0);
-- 
2.14.2.666.gea220ee40

Links