From: Jeffrey Middleton Date: Tue, 7 Apr 2009 18:30:43 +0000 (-0500) Subject: added scroll-offset option; fixed scrolling bug X-Git-Tag: release-0.14~24 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=abd152996b9d591f80a6160867ed72f8448afd28;p=ncmpc.git added scroll-offset option; fixed scrolling bug scroll-offset (default 0) is the number of entries to be displayed on either side of the cursor; this helps the user avoid overshooting when moving the cursor to a desired entry past the end of the window. The exact behavior is copied from Vim, as detailed below. The interaction with the top/bottom (H/L) commands is the same as in Vim: they jump to the top+offset/bottom-offset, unless the top/bottom is the beginning/end of the list, in which case they jump all the way to the edge. Large values of the offset (at least half the screen height) also work the same as in Vim, causing the cursor to always be centered. Finally, there is some slightly odd behavior when using scrolling commands while the cursor is in the offset range at the edge of the list. For example, if the screen is scrolled to the top, and the cursor is also on the first item, scrolling down by a line causes the cursor to jump down to the offset position. This is also the same as Vim and I don't really see a better (but simple) alternative. The behavior of the scroll down command at the bottom of the list was also broken; this was fixed here instead of separately since the relevant code was modified for this update anyway. --- diff --git a/doc/ncmpc.1 b/doc/ncmpc.1 index 3f87cb9..f4ee981 100644 --- a/doc/ncmpc.1 +++ b/doc/ncmpc.1 @@ -88,6 +88,9 @@ Default search mode for the search screen. The mode is an integer index, with 0 Enable/disable auto center mode. When auto center mode is enabled ncmpc centers the current track in the playlist window. .TP +.B scroll-offset = NUM +Keep at least NUM lines above and below the cursor on list windows, if possible. +.TP .B find\-show\-last = yes|no Show the most recent query instead of a blank line for a find. .TP diff --git a/src/conf.c b/src/conf.c index 09fa45f..4f17108 100644 --- a/src/conf.c +++ b/src/conf.c @@ -41,6 +41,7 @@ /* configuration field names */ #define CONF_ENABLE_COLORS "enable-colors" +#define CONF_SCROLL_OFFSET "scroll-offset" #define CONF_AUTO_CENTER "auto-center" #define CONF_WIDE_CURSOR "wide-cursor" #define CONF_KEY_DEFINITION "key" @@ -404,6 +405,8 @@ parse_line(char *line) #else {} #endif + else if (!strcasecmp(CONF_SCROLL_OFFSET, name)) + options.scroll_offset = atoi(value); /* auto center */ else if (!strcasecmp(CONF_AUTO_CENTER, name)) options.auto_center = str2bool(value); diff --git a/src/list_window.c b/src/list_window.c index 347c54b..e02d92b 100644 --- a/src/list_window.c +++ b/src/list_window.c @@ -161,7 +161,13 @@ list_window_previous(struct list_window *lw, unsigned length) static void list_window_top(struct list_window *lw) { - list_window_set_selected(lw, lw->start); + if (lw->start == 0) + list_window_set_selected(lw, lw->start); + else + if ((unsigned) options.scroll_offset * 2 >= lw->rows) + list_window_set_selected(lw, lw->start + lw->rows / 2); + else + list_window_set_selected(lw, lw->start + options.scroll_offset); } static void @@ -177,7 +183,13 @@ static void list_window_bottom(struct list_window *lw, unsigned length) { if (length >= lw->rows) - list_window_set_selected(lw, lw->start + lw->rows - 1); + if ((unsigned) options.scroll_offset * 2 >= lw->rows) + list_window_set_selected(lw, lw->start + lw->rows / 2); + else + if (lw->start + lw->rows == length) + list_window_set_selected(lw, length - 1); + else + list_window_set_selected(lw, lw->start + lw->rows - 1 - options.scroll_offset); else list_window_set_selected(lw, length - 1); } @@ -229,8 +241,8 @@ list_window_scroll_up(struct list_window *lw, unsigned n) lw->start = 0; else lw->start -= n; - if (lw->selected > lw->start + lw->rows - 1) { - lw->selected = lw->start + lw->rows - 1; + if (lw->selected > lw->start + lw->rows - 1 - options.scroll_offset) { + lw->selected = lw->start + lw->rows - 1 - options.scroll_offset; if (lw->range_selection) { if (lw->selected < lw->range_base) { lw->selected_start = lw->selected; @@ -249,14 +261,14 @@ list_window_scroll_up(struct list_window *lw, unsigned n) static void list_window_scroll_down(struct list_window *lw, unsigned length, unsigned n) { - if (lw->start + lw->rows < length - 1) + if (lw->start + lw->rows < length) { if ( lw->start + lw->rows + n > length - 1) - lw->start = length-1; + lw->start = length - lw->rows; else lw->start += n; - if (lw->selected < lw->start) { - lw->selected = lw->start; + if (lw->selected < lw->start + options.scroll_offset) { + lw->selected = lw->start + options.scroll_offset; if (lw->range_selection) { if (lw->selected > lw->range_base) { lw->selected_end = lw->selected; @@ -280,18 +292,36 @@ list_window_paint(struct list_window *lw, unsigned i; bool fill = options.wide_cursor; bool show_cursor = !lw->hide_cursor; + bool highlight = false; if (show_cursor) { - if (lw->selected < lw->start) - lw->start = lw->selected; + int start = lw->start; + if ((unsigned) options.scroll_offset * 2 >= lw->rows) + // Center if the offset is more than half the screen + start = lw->selected - lw->rows / 2; + else + { + if (lw->selected < lw->start + options.scroll_offset) + start = lw->selected - options.scroll_offset; - if (lw->selected >= lw->start + lw->rows) - lw->start = lw->selected - lw->rows + 1; + if (lw->selected >= lw->start + lw->rows - options.scroll_offset) + { + start = lw->selected - lw->rows + 1 + options.scroll_offset; + } + } + if (start < 0) + lw->start = 0; + else + { + while ( start > 0 && callback(start + lw->rows - 1, &highlight, callback_data) == NULL) + start--; + lw->start = start; + } } for (i = 0; i < lw->rows; i++) { - bool highlight = false; const char *label; + highlight = false; label = callback(lw->start + i, &highlight, callback_data); wmove(lw->w, i, 0); diff --git a/src/options.c b/src/options.c index df1a9da..5d8b1fd 100644 --- a/src/options.c +++ b/src/options.c @@ -56,6 +56,7 @@ options_t options = { .lyrics_timeout = DEFAULT_LYRICS_TIMEOUT, #endif .find_wrap = true, + .scroll_offset = 0, .wide_cursor = true, .audible_bell = true, .bell_on_wrap = true, diff --git a/src/options.h b/src/options.h index bccd0b2..cc42493 100644 --- a/src/options.h +++ b/src/options.h @@ -53,6 +53,7 @@ typedef struct { bool find_wrap; bool find_show_last_pattern; bool list_wrap; + int scroll_offset; bool auto_center; bool wide_cursor; #ifdef ENABLE_COLORS