Code

screen_browser: check connection in screen_file_cmd()
[ncmpc.git] / src / list_window.c
index 40f2e14250196106735632d483ce1c2633d87580..ca857b8a06ec60185e3d9d334c318d084b881b55 100644 (file)
@@ -24,7 +24,7 @@
 #include "match.h"
 #include "command.h"
 #include "colors.h"
-#include "screen.h"
+#include "screen_message.h"
 #include "i18n.h"
 
 #include <assert.h>
@@ -64,7 +64,6 @@ list_window_reset(struct list_window *lw)
        lw->selected_end = 0;
        lw->range_selection = false;
        lw->range_base = 0;
-       lw->xoffset = 0;
        lw->start = 0;
 }
 
@@ -88,6 +87,19 @@ list_window_check_selected(struct list_window *lw, unsigned length)
 
        if(lw->range_selection)
        {
+               if (length == 0) {
+                       lw->selected_start = 0;
+                       lw->selected_end = 0;
+                       lw->range_base = 0;
+               } else {
+                       if (lw->selected_start >= length)
+                               lw->selected_start = length - 1;
+                       if (lw->selected_end >= length)
+                               lw->selected_end = length - 1;
+                       if (lw->range_base >= length)
+                               lw->range_base = length - 1;
+               }
+
                if(lw->range_base > lw->selected_end)
                          lw->selected_end = lw->selected;
                if(lw->range_base < lw->selected_start)
@@ -161,7 +173,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 +195,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);
 }
@@ -185,14 +209,12 @@ list_window_bottom(struct list_window *lw, unsigned length)
 static void
 list_window_first(struct list_window *lw)
 {
-       lw->xoffset = 0;
        list_window_set_selected(lw, 0);
 }
 
 static void
 list_window_last(struct list_window *lw, unsigned length)
 {
-       lw->xoffset = 0;
        if (length > 0)
                list_window_set_selected(lw, length - 1);
        else
@@ -229,8 +251,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 +271,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,20 +302,39 @@ 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, NULL, callback_data) == NULL)
+                               start--;
+                       lw->start = start;
+               }
        }
 
        for (i = 0; i < lw->rows; i++) {
-               bool highlight = false;
                const char *label;
+               char *second_column = NULL;
+               highlight = false;
 
-               label = callback(lw->start + i, &highlight, callback_data);
+               label = callback(lw->start + i, &highlight, &second_column, callback_data);
                wmove(lw->w, i, 0);
 
                if (label) {
@@ -305,7 +346,8 @@ list_window_paint(struct list_window *lw,
                        else
                                colors_use(lw->w, COLOR_LIST);
 
-                       if (show_cursor && selected)
+                       if (show_cursor && selected &&
+                           (!options.hardware_cursor || lw->range_selection))
                                wattron(lw->w, A_REVERSE);
 
                        //waddnstr(lw->w, label, lw->cols);
@@ -313,6 +355,19 @@ list_window_paint(struct list_window *lw,
                        if (fill && len < lw->cols)
                                whline(lw->w,  ' ', lw->cols-len);
 
+                       if(second_column)
+                       {
+                               unsigned sc_len = utf8_width(second_column) + 1;
+                               if(lw->cols > sc_len)
+                               {
+                                       wmove(lw->w, i, lw->cols - sc_len);
+                                       waddstr(lw->w, " ");
+                                       wmove(lw->w, i, lw->cols - sc_len + 1);
+                                       waddstr(lw->w, second_column);
+                               }
+                               g_free(second_column);
+                       }
+
                        if (selected)
                                wattroff(lw->w, A_REVERSE);
 
@@ -321,6 +376,12 @@ list_window_paint(struct list_window *lw,
                } else
                        wclrtoeol(lw->w);
        }
+
+       if (options.hardware_cursor && lw->selected >= lw->start &&
+           lw->selected < lw->start + lw->rows) {
+               curs_set(1);
+               wmove(lw->w, lw->selected - lw->start, 0);
+       }
 }
 
 bool
@@ -336,7 +397,7 @@ list_window_find(struct list_window *lw,
        const char *label;
 
        do {
-               while ((label = callback(i,&h,callback_data))) {
+               while ((label = callback(i,&h,NULL,callback_data))) {
                        if (str && label && match_line(label, str)) {
                                lw->selected = i;
                                if(!lw->range_selection || i > lw->selected_end)
@@ -379,7 +440,7 @@ list_window_rfind(struct list_window *lw,
                return false;
 
        do {
-               while (i >= 0 && (label = callback(i,&h,callback_data))) {
+               while (i >= 0 && (label = callback(i,&h,NULL,callback_data))) {
                        if( str && label && match_line(label, str) ) {
                                lw->selected = i;
                                if(!lw->range_selection || i > (int)lw->selected_end)
@@ -413,26 +474,24 @@ list_window_jump(struct list_window *lw,
        unsigned i = 0;
        const char *label;
 
-       while ((label = callback(i,&h,callback_data))) {
-               if (label && label[0] != '[')
+       while ((label = callback(i,&h,NULL,callback_data))) {
+               if (label && label[0] == '[')
+                       label++;
+#ifndef NCMPC_MINI
+               if (str && label &&
+                               ((options.jump_prefix_only && g_ascii_strncasecmp(label, str, strlen(str)) == 0) ||
+                                (!options.jump_prefix_only && match_line(label, str))) )
+#else
+               if (str && label && g_ascii_strncasecmp(label, str, strlen(str)) == 0)
+#endif
                {
-                       if (str && label && find_occurence(label, str, strlen(str)) == 0) {
-                               lw->selected = i;
-                               if(!lw->range_selection || i > lw->selected_end)
-                                         lw->selected_end = i;
-                               if(!lw->range_selection || i < lw->selected_start)
-                                         lw->selected_start = i;
-                               return true;
-                       }
+                       lw->selected = i;
+                       if(!lw->range_selection || i > lw->selected_end)
+                               lw->selected_end = i;
+                       if(!lw->range_selection || i < lw->selected_start)
+                               lw->selected_start = i;
+                       return true;
                }
-               else if (str && label && find_occurence(label+1, str, strlen(str)) == 0) {
-                               lw->selected = i;
-                               if(!lw->range_selection || i > lw->selected_end)
-                                         lw->selected_end = i;
-                               if(!lw->range_selection || i < lw->selected_start)
-                                         lw->selected_start = i;
-                               return true;
-                       }
                i++;
        }
        return false;