aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Fleischer <calcurse@cryptocrack.de>2014-05-13 20:30:02 +0200
committerLukas Fleischer <calcurse@cryptocrack.de>2014-05-18 11:02:42 +0200
commit27b39a56ef8a2cf94ace5911614d0bd63c26ba06 (patch)
tree92894d27c67f49033cb02c85584986311a4d1e0e
parent7184da0fa364049424f626f55f7c2bc0a7d22929 (diff)
downloadcalcurse-27b39a56ef8a2cf94ace5911614d0bd63c26ba06.tar.gz
calcurse-27b39a56ef8a2cf94ace5911614d0bd63c26ba06.zip
Add a generic list box implementation
This adds a very generic list box implementation. List boxes with items of different heights are supported. Two callback functions to determine the height of every single item and to draw a specific item are used. Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
-rw-r--r--src/Makefile.am1
-rw-r--r--src/calcurse.h26
-rw-r--r--src/listbox.c138
3 files changed, 165 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3559a25..d17da42 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,6 +23,7 @@ calcurse_SOURCES = \
ical.c \
io.c \
keys.c \
+ listbox.c \
llist.c \
note.c \
notify.c \
diff --git a/src/calcurse.h b/src/calcurse.h
index 53610c4..4f5c2c0 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -515,6 +515,20 @@ struct scrollwin {
const char *label;
};
+/* Generic list box structure. */
+typedef int (*listbox_fn_item_height_t) (int, void *);
+typedef void (*listbox_fn_draw_item_t) (int, WINDOW *, int, int, void *);
+
+struct listbox {
+ struct scrollwin sw;
+ unsigned item_count;
+ unsigned item_sel;
+ listbox_fn_item_height_t fn_height;
+ unsigned *ch;
+ listbox_fn_draw_item_t fn_draw;
+ void *cb_data;
+};
+
/* Pad structure to handle scrolling. */
struct pad {
int width;
@@ -802,6 +816,18 @@ void keys_save_bindings(FILE *);
int keys_check_missing_bindings(void);
void keys_fill_missing(void);
+/* listbox.c */
+void listbox_init(struct listbox *, int, int, int, int, const char *, listbox_fn_item_height_t, listbox_fn_draw_item_t);
+void listbox_delete(struct listbox *);
+void listbox_resize(struct listbox *, int, int, int, int);
+void listbox_set_cb_data(struct listbox *, void *);
+void listbox_load_items(struct listbox *, int);
+void listbox_draw_deco(struct listbox *);
+void listbox_display(struct listbox *);
+int listbox_get_sel(struct listbox *);
+void listbox_set_sel(struct listbox *, unsigned);
+void listbox_sel_move(struct listbox *, int);
+
/* mem.c */
void *xmalloc(size_t);
void *xcalloc(size_t, size_t);
diff --git a/src/listbox.c b/src/listbox.c
new file mode 100644
index 0000000..3a31017
--- /dev/null
+++ b/src/listbox.c
@@ -0,0 +1,138 @@
+/*
+ * Calcurse - text-based organizer
+ *
+ * Copyright (c) 2004-2014 calcurse Development Team <misc@calcurse.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Send your feedback or comments to : misc@calcurse.org
+ * Calcurse home page : http://calcurse.org
+ *
+ */
+
+#include "calcurse.h"
+
+void listbox_init(struct listbox *lb, int y, int x, int h, int w,
+ const char *label, listbox_fn_item_height_t fn_height,
+ listbox_fn_draw_item_t fn_draw)
+{
+ EXIT_IF(lb == NULL, "null pointer");
+ wins_scrollwin_init(&(lb->sw), y, x, h, w, label);
+ lb->item_count = lb->item_sel = 0;
+ lb->fn_height = fn_height;
+ lb->ch = NULL;
+ lb->fn_draw = fn_draw;
+ lb->cb_data = NULL;
+}
+
+void listbox_delete(struct listbox *lb)
+{
+ EXIT_IF(lb == NULL, "null pointer");
+ wins_scrollwin_delete(&(lb->sw));
+ free(lb->ch);
+}
+
+void listbox_resize(struct listbox *lb, int y, int x, int h, int w)
+{
+ EXIT_IF(lb == NULL, "null pointer");
+ wins_scrollwin_resize(&(lb->sw), y, x, h, w);
+ wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel]);
+ wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel + 1] - 1);
+}
+
+void listbox_set_cb_data(struct listbox *lb, void *cb_data)
+{
+ lb->cb_data = cb_data;
+}
+
+void listbox_load_items(struct listbox *lb, int item_count)
+{
+ int i, ch;
+
+ lb->item_count = item_count;
+
+ if (lb->item_sel >= item_count)
+ lb->item_sel = item_count - 1;
+
+ free(lb->ch);
+ lb->ch = xmalloc((item_count + 1) * sizeof(unsigned));
+ for (i = 0, ch = 0; i < item_count; i++) {
+ lb->ch[i] = ch;
+ ch += lb->fn_height(i, lb->cb_data);
+ }
+ lb->ch[item_count] = ch;
+
+ wins_scrollwin_set_linecount(&(lb->sw), ch);
+}
+
+void listbox_draw_deco(struct listbox *lb)
+{
+ wins_scrollwin_draw_deco(&(lb->sw));
+}
+
+void listbox_display(struct listbox *lb)
+{
+ int i;
+
+ werase(lb->sw.inner);
+
+ for (i = 0; i < lb->item_count; i++) {
+ int is_sel = (i == lb->item_sel);
+ lb->fn_draw(i, lb->sw.inner, lb->ch[i], is_sel, lb->cb_data);
+ }
+
+ wins_scrollwin_display(&(lb->sw));
+}
+
+int listbox_get_sel(struct listbox *lb)
+{
+ return lb->item_sel;
+}
+
+void listbox_set_sel(struct listbox *lb, unsigned pos)
+{
+ lb->item_sel = pos;
+
+ wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel]);
+ wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel + 1] - 1);
+}
+
+void listbox_sel_move(struct listbox *lb, int delta)
+{
+ if (lb->item_count == 0)
+ return;
+
+ if (delta < 0 && lb->item_sel < -delta)
+ lb->item_sel = 0;
+ else if (delta > 0 && lb->item_sel + delta >= lb->item_count)
+ lb->item_sel = lb->item_count - 1;
+ else
+ lb->item_sel += delta;
+
+ wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel]);
+ wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel + 1] - 1);
+}