aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/calcurse.h9
-rw-r--r--src/listbox.c75
-rw-r--r--src/wins.c5
3 files changed, 49 insertions, 40 deletions
diff --git a/src/calcurse.h b/src/calcurse.h
index c568e89..3c9986f 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -580,8 +580,8 @@ struct window {
/* Generic scrolling window structure. */
struct scrollwin {
- WINDOW *win;
- WINDOW *inner;
+ WINDOW *win; /* viewport */
+ WINDOW *inner; /* pad */
int y;
int x;
int h;
@@ -936,7 +936,8 @@ void listbox_draw_deco(struct listbox *, int);
void listbox_display(struct listbox *, int);
int listbox_get_sel(struct listbox *);
void listbox_set_sel(struct listbox *, unsigned);
-void listbox_sel_move(struct listbox *, int);
+void listbox_item_in_view(struct listbox *, int);
+int listbox_sel_move(struct listbox *, int);
/* mem.c */
void *xmalloc(size_t);
@@ -1271,7 +1272,7 @@ void wins_scrollwin_draw_deco(struct scrollwin *, int);
void wins_scrollwin_display(struct scrollwin *, int);
void wins_scrollwin_up(struct scrollwin *, int);
void wins_scrollwin_down(struct scrollwin *, int);
-void wins_scrollwin_ensure_visible(struct scrollwin *, unsigned);
+void wins_scrollwin_in_view(struct scrollwin *, unsigned);
void wins_resize(void);
void wins_resize_panels(void);
void wins_show(WINDOW *, const char *);
diff --git a/src/listbox.c b/src/listbox.c
index 38e7647..12c45cc 100644
--- a/src/listbox.c
+++ b/src/listbox.c
@@ -36,6 +36,9 @@
#include "calcurse.h"
+static void listbox_fix_sel(struct listbox *, int);
+static void listbox_sel_in_view(struct listbox *);
+
void listbox_init(struct listbox *lb, int y, int x, int h, int w,
const char *label, listbox_fn_item_type_t fn_type,
listbox_fn_item_height_t fn_height,
@@ -60,21 +63,6 @@ void listbox_delete(struct listbox *lb)
mem_free(lb->ch);
}
-static void listbox_fix_visible_region(struct listbox *lb)
-{
- int i;
-
- wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel]);
- wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel + 1] - 1);
-
- i = lb->item_sel - 1;
- while (i >= 0 && lb->type[i] != LISTBOX_ROW_TEXT) {
- wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[i]);
- wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[i + 1] - 1);
- i++;
- }
-}
-
void listbox_resize(struct listbox *lb, int y, int x, int h, int w)
{
EXIT_IF(lb == NULL, "null pointer");
@@ -83,7 +71,7 @@ void listbox_resize(struct listbox *lb, int y, int x, int h, int w)
if (lb->item_sel < 0)
return;
- listbox_fix_visible_region(lb);
+ listbox_sel_in_view(lb);
}
void listbox_set_cb_data(struct listbox *lb, void *cb_data)
@@ -91,14 +79,11 @@ void listbox_set_cb_data(struct listbox *lb, void *cb_data)
lb->cb_data = cb_data;
}
-static void listbox_fix_sel(struct listbox *, int);
-
void listbox_load_items(struct listbox *lb, int item_count)
{
int i, ch;
lb->item_count = item_count;
-
if (item_count == 0) {
lb->item_sel = -1;
return;
@@ -114,14 +99,13 @@ void listbox_load_items(struct listbox *lb, int item_count)
ch += lb->fn_height(i, lb->cb_data);
}
lb->ch[item_count] = ch;
+
+ /* The pad lines: 0,.., ch - 1. */
wins_scrollwin_set_pad(&(lb->sw), ch);
- if (item_count > 0 && lb->item_sel < 0)
- lb->item_sel = 0;
- else if (lb->item_sel >= item_count)
- lb->item_sel = item_count - 1;
+ /* Adjust the selection. */
listbox_fix_sel(lb, 1);
- listbox_fix_visible_region(lb);
+ listbox_sel_in_view(lb);
}
void listbox_draw_deco(struct listbox *lb, int hilt)
@@ -148,6 +132,7 @@ int listbox_get_sel(struct listbox *lb)
return lb->item_sel;
}
+/* Avoid non-text items. */
static void listbox_fix_sel(struct listbox *lb, int direction)
{
int did_flip = 0;
@@ -157,6 +142,11 @@ static void listbox_fix_sel(struct listbox *lb, int direction)
direction = direction > 0 ? 1 : -1;
+ if (lb->item_sel < 0)
+ lb->item_sel = 0;
+ else if (lb->item_sel >= lb->item_count)
+ lb->item_sel = lb->item_count - 1;
+
while (lb->type[lb->item_sel] != LISTBOX_ROW_TEXT) {
if ((direction == -1 && lb->item_sel == 0) ||
(direction == 1 && lb->item_sel == lb->item_count - 1)) {
@@ -179,23 +169,40 @@ void listbox_set_sel(struct listbox *lb, unsigned pos)
if (lb->item_sel < 0)
return;
- listbox_fix_visible_region(lb);
+ listbox_sel_in_view(lb);
+}
+
+void listbox_item_in_view(struct listbox *lb, int item)
+{
+ int first_line = lb->ch[item];
+ int last_line = lb->ch[item + 1] - 1;
+
+ wins_scrollwin_in_view(&(lb->sw), first_line);
+ if (last_line != first_line)
+ wins_scrollwin_in_view(&(lb->sw), last_line);
}
-void listbox_sel_move(struct listbox *lb, int delta)
+/* Keep the selection in view. */
+static void listbox_sel_in_view(struct listbox *lb)
{
+ listbox_item_in_view(lb, lb->item_sel);
+}
+
+/* Returns true if the move succeeded. */
+int listbox_sel_move(struct listbox *lb, int delta)
+{
+
+ int saved_sel = lb->item_sel;
+
if (lb->item_count == 0)
- return;
+ return 0;
lb->item_sel += delta;
- if (lb->item_sel < 0)
- lb->item_sel = 0;
- else if (lb->item_sel >= lb->item_count)
- lb->item_sel = lb->item_count - 1;
-
listbox_fix_sel(lb, delta);
if (lb->item_sel < 0)
- return;
+ return 0;
+
+ listbox_sel_in_view(lb);
- listbox_fix_visible_region(lb);
+ return lb->item_sel != saved_sel;
}
diff --git a/src/wins.c b/src/wins.c
index 0cc7ff7..51d8072 100644
--- a/src/wins.c
+++ b/src/wins.c
@@ -415,13 +415,14 @@ void wins_scrollwin_down(struct scrollwin *sw, int amount)
sw->line_off = sw->line_num - inner_h;
}
-void wins_scrollwin_ensure_visible(struct scrollwin *sw, unsigned line)
+/* Keep 'line' in the viewport of a scrollwindow. */
+void wins_scrollwin_in_view(struct scrollwin *sw, unsigned line)
{
int inner_h = sw->h - (conf.compact_panels ? 2 : 4);
if (line < sw->line_off)
sw->line_off = line;
- else if (line >= sw->line_off + inner_h)
+ else if (line > sw->line_off + inner_h - 1)
sw->line_off = line - inner_h + 1;
}