Code

added scroll-offset option; fixed scrolling bug
authorJeffrey Middleton <jefromi@gmail.com>
Tue, 7 Apr 2009 18:30:43 +0000 (13:30 -0500)
committerJeffrey Middleton <jefromi@gmail.com>
Wed, 8 Apr 2009 23:52:39 +0000 (18:52 -0500)
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.

doc/ncmpc.1
src/conf.c
src/list_window.c
src/options.c
src/options.h

index 3f87cb98a4a07169cbfeb63dc3fcaf8bfb5c20a0..f4ee9810cf73f90ff6c3e1c2b6839dc190c00dbb 100644 (file)
@@ -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 
index 09fa45fe19d57b638ea3031cbba874471038b196..4f171082dec34c03ca5ab1a16bbc85f7826cf3e3 100644 (file)
@@ -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);
index 347c54b4d440fc0f3b704e3ba730d472c37e5b4e..e02d92babc0a64b61804497c97a35fcb4e351622 100644 (file)
@@ -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);
index df1a9da16fff6fca44da8dc780a4155763a18a7d..5d8b1fda448cac033905d64a5ff602a94c6926be 100644 (file)
@@ -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,
index bccd0b22b4fab2217cf1c37bb6c0bf35beaf80b7..cc42493a9a46d614e408b58496383019e6e00556 100644 (file)
@@ -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