diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/calcurse.h | 9 | ||||
-rw-r--r-- | src/listbox.c | 75 | ||||
-rw-r--r-- | src/wins.c | 5 |
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; } @@ -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; } |