# HG changeset patch # User Sadrul Habib Chowdhury # Date 1150965234 0 # Node ID 0e1e59770cb0685d3b93630ee63c3e76ad1cdbcd # Parent 8d1c55309e3cdaf1930c1a53ce1d6f0e51ebeca1 [gaim-migrate @ 16308] This is my first commit here. So don't yell at me if things get borked. Also, I haven't looked at the auto-thingies yet. So don't puke at the Makefiles. Files in console/libgnt/ are for the 'Gaim/GObjectified Ncurses Toolkit' library. Files in console/ uses libgaim and libgnt. Currently, only the buddylist-ui is 'functional', ie. the buddy-list updates when someone logs on or logs off. It still needs a lot of work. committer: Tailor Script diff -r 8d1c55309e3c -r 0e1e59770cb0 console/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/Makefile Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,27 @@ +CFLAGS=`pkg-config --cflags gaim gobject-2.0` -g -I./libgnt/ +LDFLAGS=`pkg-config --libs gaim gobject-2.0 gthread-2.0 libxml-2.0` -lncursesw -L./libgnt/ -lgnt + +GG_SOURCES = \ + gntblist.c \ + gntui.c + +GG_HEADERS = \ + gntblist.h \ + gntui.h + +GG_OBJECTS = \ + gntblist.o \ + gntui.o + +all: gntgaim + +gntgaim: gntgaim.o $(GG_OBJECTS) + $(CC) -o gntgaim gntgaim.o $(GG_OBJECTS) $(LDFLAGS) +gntblist.o: gntblist.c $(GG_HEADERS) +gntgaim.o: gntgaim.c gntgaim.h $(GG_HEADERS) +gntui.o: gntui.c $(GG_HEADERS) + +clean: + rm *.o + rm gntgaim + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/gntblist.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/gntblist.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include + +#include "gntgaim.h" +#include "gntbox.h" +#include "gnttree.h" + +#define TAB_SIZE 3 + +/** + * NOTES: + * + * 1. signal-callbacks should check for module_in_focus() before redrawing anything. + * 2. call module_lost_focus() before opening a new window, and module_gained_focus() when + * the new window is closed. This is to make sure the signal callbacks don't screw up + * the display. + */ + +static GaimBlistUiOps blist_ui_ops = +{ + NULL, + NULL, + NULL, + NULL, /* This doesn't do crap */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +typedef struct +{ + GntWidget *window; + GntWidget *tree; +} GGBlist; + +GGBlist *ggblist; + +static gpointer +gg_blist_get_handle() +{ + static int handle; + + return &handle; +} + +static void +add_group(GaimGroup *group, GGBlist *ggblist) +{ + GaimBlistNode *node = (GaimBlistNode *)group; + if (node->ui_data) + return; + gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group, + group->name, NULL, NULL); + node->ui_data = GINT_TO_POINTER(TRUE); +} + +static void +buddy_signed_on(GaimBuddy *buddy, GGBlist *ggblist) +{ + GaimGroup *group = gaim_buddy_get_group(buddy); + char *text; + + add_group(group, ggblist); + + text = g_strdup_printf("%*s%s", TAB_SIZE, "", gaim_buddy_get_alias(buddy)); + gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy, text, group, NULL); + g_free(text); +} + +static void +buddy_signed_off(GaimBuddy *buddy, GGBlist *ggblist) +{ + gnt_tree_remove(GNT_TREE(ggblist->tree), buddy); +} + +GaimBlistUiOps *gg_get_blist_ui_ops() +{ + return &blist_ui_ops; +} + +static void +selection_activate(GntWidget *widget, GGBlist *ggblist) +{ + gnt_widget_set_focus(widget, FALSE); +} + +void gg_blist_init() +{ + ggblist = g_new0(GGBlist, 1); + + ggblist->window = gnt_box_new(FALSE, FALSE); + gnt_box_set_title(GNT_BOX(ggblist->window), _("Buddy List")); + + ggblist->tree = gnt_tree_new(); + gnt_widget_set_size(ggblist->tree, 25, getmaxy(stdscr)); + + gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->tree); + gnt_widget_show(ggblist->window); + + gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", gg_blist_get_handle(), + GAIM_CALLBACK(buddy_signed_on), ggblist); + gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", gg_blist_get_handle(), + GAIM_CALLBACK(buddy_signed_off), ggblist); + + g_signal_connect(G_OBJECT(ggblist->tree), "activate", G_CALLBACK(selection_activate), ggblist); + + /*gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", gg_blist_get_handle(),*/ + /*GAIM_CALLBACK(received_im_msg), list);*/ + /*gaim_signal_connect(gaim_conversations_get_handle(), "sent-im-msg", gg_blist_get_handle(),*/ + /*GAIM_CALLBACK(sent_im_msg), NULL);*/ + + /*gaim_signal_connect(gaim_conversations_get_handle(), "received-chat-msg", gg_blist_get_handle(),*/ + /*GAIM_CALLBACK(received_chat_msg), list);*/ +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/gntblist.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/gntblist.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,5 @@ +#include "blist.h" + +GaimBlistUiOps * gg_get_blist_ui_ops(); + +void gg_blist_init(); diff -r 8d1c55309e3c -r 0e1e59770cb0 console/gntgaim.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/gntgaim.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,193 @@ +#include "account.h" +#include "conversation.h" +#include "core.h" +#include "debug.h" +#include "eventloop.h" +#include "ft.h" +#include "log.h" +#include "notify.h" +#include "prefs.h" +#include "prpl.h" +#include "pounce.h" +#include "savedstatuses.h" +#include "sound.h" +#include "status.h" +#include "util.h" +#include "whiteboard.h" + +#include "gntgaim.h" + +/* Anything IO-related is directly copied from gtkgaim's source tree */ + +static GaimCoreUiOps core_ops = +{ + NULL, /*gaim_gtk_prefs_init,*/ + NULL, /*debug_init,*/ + NULL, /*gaim_gtk_ui_init,*/ + NULL, /*gaim_gtk_quit*/ +}; + +static GaimCoreUiOps * +gnt_core_get_ui_ops() +{ + return &core_ops; +} + +#define GAIM_GTK_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) +#define GAIM_GTK_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) + +typedef struct _GaimGtkIOClosure { + GaimInputFunction function; + guint result; + gpointer data; + +} GaimGtkIOClosure; + +static void gaim_gtk_io_destroy(gpointer data) +{ + g_free(data); +} + +static gboolean gaim_gtk_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) +{ + GaimGtkIOClosure *closure = data; + GaimInputCondition gaim_cond = 0; + + if (condition & GAIM_GTK_READ_COND) + gaim_cond |= GAIM_INPUT_READ; + if (condition & GAIM_GTK_WRITE_COND) + gaim_cond |= GAIM_INPUT_WRITE; + +#if 0 + gaim_debug(GAIM_DEBUG_MISC, "gtk_eventloop", + "CLOSURE: callback for %d, fd is %d\n", + closure->result, g_io_channel_unix_get_fd(source)); +#endif + +#ifdef _WIN32 + if(! gaim_cond) { +#if DEBUG + gaim_debug(GAIM_DEBUG_MISC, "gtk_eventloop", + "CLOSURE received GIOCondition of 0x%x, which does not" + " match 0x%x (READ) or 0x%x (WRITE)\n", + condition, GAIM_GTK_READ_COND, GAIM_GTK_WRITE_COND); +#endif /* DEBUG */ + + return TRUE; + } +#endif /* _WIN32 */ + + closure->function(closure->data, g_io_channel_unix_get_fd(source), + gaim_cond); + + return TRUE; +} + +static guint gnt_input_add(gint fd, GaimInputCondition condition, GaimInputFunction function, + gpointer data) +{ + GaimGtkIOClosure *closure = g_new0(GaimGtkIOClosure, 1); + GIOChannel *channel; + GIOCondition cond = 0; + + closure->function = function; + closure->data = data; + + if (condition & GAIM_INPUT_READ) + cond |= GAIM_GTK_READ_COND; + if (condition & GAIM_INPUT_WRITE) + cond |= GAIM_GTK_WRITE_COND; + + channel = g_io_channel_unix_new(fd); + closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, + gaim_gtk_io_invoke, closure, gaim_gtk_io_destroy); + +#if 0 + gaim_debug(GAIM_DEBUG_MISC, "gtk_eventloop", + "CLOSURE: adding input watcher %d for fd %d\n", + closure->result, fd); +#endif + + g_io_channel_unref(channel); + return closure->result; +} + +static GaimEventLoopUiOps eventloop_ops = +{ + g_timeout_add, + (guint (*)(guint))g_source_remove, + gnt_input_add, + (guint (*)(guint))g_source_remove +}; + +GaimEventLoopUiOps * +gnt_eventloop_get_ui_ops(void) +{ + return &eventloop_ops; +} + +/* This is mostly copied from gtkgaim's source tree */ +static void +init_libgaim() +{ + char *path; + + gaim_debug_set_enabled(FALSE); + + gaim_core_set_ui_ops(gnt_core_get_ui_ops()); + gaim_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops()); + + gaim_util_set_user_dir("/tmp/tmp/"); /* XXX: */ + + path = g_build_filename(gaim_user_dir(), "plugins", NULL); + gaim_plugins_add_search_path(path); + g_free(path); + gaim_plugins_add_search_path("/usr/local/lib/gaim"); /* XXX: */ + + if (!gaim_core_init(GAIM_GNT_UI)) + { + fprintf(stderr, "OOPSSS!!\n"); + abort(); + } + + /* TODO: Move blist loading into gaim_blist_init() */ + gaim_set_blist(gaim_blist_new()); + gaim_blist_load(); + + /* TODO: Move prefs loading into gaim_prefs_init() */ + gaim_prefs_load(); + gaim_prefs_update_old(); + + /* load plugins we had when we quit */ + gaim_plugins_load_saved("/gaim/gtk/plugins/loaded"); + + /* TODO: Move pounces loading into gaim_pounces_init() */ + gaim_pounces_load(); + +} + +int main(int argc, char **argv) +{ + GMainLoop *loop; + + /* Initialize the libgaim stuff */ + init_libgaim(); + + /* Connect to the signals */ + + /* Enable the accounts and restore the status */ + gaim_accounts_restore_current_statuses(); + + /* Main loop */ + g_thread_init(NULL); + loop = g_main_loop_new(NULL, TRUE); + g_thread_create((GThreadFunc)g_main_loop_run, loop, FALSE, NULL); + + /* Initialize the UI */ + init_gnt_ui(); + + gaim_core_quit(); + + return 0; +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/gntgaim.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/gntgaim.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,5 @@ +#include + +#define GAIM_GNT_UI "gnt-gaim" + +#define _(x) x diff -r 8d1c55309e3c -r 0e1e59770cb0 console/gntui.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/gntui.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,18 @@ +#include "gntui.h" + +void init_gnt_ui() +{ + gnt_init(); + + wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + werase(stdscr); + /*box(stdscr, ACS_VLINE, ACS_HLINE);*/ + wrefresh(stdscr); + + /* Initialize the buddy list */ + gg_blist_init(); + gaim_blist_set_ui_ops(gg_get_blist_ui_ops()); + + gnt_main(); +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/gntui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/gntui.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,3 @@ +#include "gnt.h" + +void init_gnt_ui(); diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/Makefile Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,53 @@ +CFLAGS=`pkg-config --cflags gobject-2.0` -g +LDFLAGS=`pkg-config --libs gobject-2.0` -lncursesw + +HEADERS = \ + gntwidget.h \ + gntbox.h \ + gntbutton.h \ + gntcolors.h \ + gntlabel.h \ + gnttree.h \ + gntutils.h \ + gnt.h + +SOURCES = \ + gntwidget.c \ + gntbox.c \ + gntbutton.c \ + gntcolors.c \ + gntlabel.c \ + gnttree.c \ + gntutils.c \ + gntmain.c + +OBJECTS = \ + gntwidget.o \ + gntbox.o \ + gntbutton.o \ + gntcolors.o \ + gntlabel.o \ + gnttree.o \ + gntutils.o \ + gntmain.o + +all: libgnt + +test: $(OBJECTS) + +gntwidget.o: gntwidget.c $(HEADERS) +gntbox.o: gntbox.c $(HEADERS) +gntbutton.o: gntbutton.c $(HEADERS) +gntcolors.o: gntcolors.c $(HEADERS) +gntlabel.o: gntlabel.c $(HEADERS) +gnttree.o: gnttree.c $(HEADERS) +gntutils.o: gntutils.c $(HEADERS) +gntmain.o: gntmain.c $(HEADERS) + +libgnt: $(OBJECTS) + $(CC) --shared -o libgnt.so $(OBJECTS) + +clean: + rm *.o + rm libgnt.so + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gnt-skel.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gnt-skel.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,93 @@ +#include "gn-skel.h" + +enum +{ + SIGS = 1, +}; + +static GntWidgetClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; + +static void +gnt_skel_draw(GntWidget *widget) +{ + DEBUG; +} + +static void +gnt_skel_size_request(GntWidget *widget) +{ +} + +static void +gnt_skel_map(GntWidget *widget) +{ + if (widget->priv.width == 0 || widget->priv.height == 0) + gnt_widget_size_request(widget); + DEBUG; +} + +static gboolean +gnt_skel_key_pressed(GntWidget *widget, const char *text) +{ + return FALSE; +} + +static void +gnt_skel_class_init(GntWidgetClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = GNT_WIDGET_CLASS(klass); + parent_class->draw = gnt_skel_draw; + parent_class->map = gnt_skel_map; + parent_class->size_request = gnt_skel_size_request; + parent_class->key_pressed = gnt_skel_key_pressed; + + DEBUG; +} + +static void +gnt_skel_init(GTypeInstance *instance, gpointer class) +{ + DEBUG; +} + +/****************************************************************************** + * GntSkel API + *****************************************************************************/ +GType +gnt_skel_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntSkelClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_skel_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntSkel), + 0, /* n_preallocs */ + gnt_skel_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntSkel", + &info, 0); + } + + return type; +} + +GntWidget *gnt_skel_new() +{ + GntWidget *widget = g_object_new(GNT_TYPE_SKEL, NULL); + GntSkel *skel = GNT_SKEL(widget); + + return widget; +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gnt-skel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gnt-skel.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,47 @@ +#ifndef GNT_SKEL_H +#define GNT_SKEL_H + +#include "gnwidget.h" +#include "gn.h" +#include "gncolors.h" +#include "gnkeys.h" + +#define GNT_TYPE_SKEL (gnt_skel_get_gtype()) +#define GNT_SKEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_SKEL, GntSkel)) +#define GNT_SKEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_SKEL, GntSkelClass)) +#define GNT_IS_SKEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_SKEL)) +#define GNT_IS_SKEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_SKEL)) +#define GNT_SKEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_SKEL, GntSkelClass)) + +#define GNT_SKEL_FLAGS(obj) (GNT_SKEL(obj)->priv.flags) +#define GNT_SKEL_SET_FLAGS(obj, flags) (GNT_SKEL_FLAGS(obj) |= flags) +#define GNT_SKEL_UNSET_FLAGS(obj, flags) (GNT_SKEL_FLAGS(obj) &= ~(flags)) + +typedef struct _GnSkel GntSkel; +typedef struct _GnSkelPriv GntSkelPriv; +typedef struct _GnSkelClass GntSkelClass; + +struct _GnSkel +{ + GntWidget parent; +}; + +struct _GnSkelClass +{ + GntWidgetClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_skel_get_gtype(void); + +GntWidget *gnt_skel_new(); + +G_END_DECLS + +#endif /* GNT_SKEL_H */ diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gnt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gnt.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,17 @@ +#include +#include "gntwidget.h" +#include "gntcolors.h" +#include "gntkeys.h" + +/* XXX: Find a better place for this */ +#define SCROLL_HEIGHT 4096 +#define SCROLL_WIDTH 512 + +void gnt_init(); + +void gnt_main(); + +void gnt_screen_take_focus(GntWidget *widget); + +void gnt_screen_remove_widget(GntWidget *widget); + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntbox.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntbox.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,323 @@ +#include "gntbox.h" + +enum +{ + SIGS = 1, +}; + +static GntWidgetClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; + +static void +gnt_box_draw(GntWidget *widget) +{ + GntBox *box = GNT_BOX(widget); + GList *iter; + + for (iter = box->list; iter; iter = iter->next) + { + gnt_widget_draw(GNT_WIDGET(iter->data)); + } + + if (box->title) + { + gchar *title = g_strdup(box->title); + int pos = g_utf8_strlen(title, -1); + + if (pos >= widget->priv.width - 2) + { + g_utf8_strncpy(title, box->title, widget->priv.width - 2); + pos = 1; + } + else + { + pos = (widget->priv.width - pos - 2) / 2; + /*pos = 2;*/ + } + wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE)); + mvwprintw(widget->window, 0, pos, title); + g_free(title); + } + wrefresh(widget->window); + + DEBUG; +} + +static void +reposition_children(GntWidget *widget) +{ + GList *iter; + GntBox *box = GNT_BOX(widget); + int w, h, curx, cury, max; + gboolean has_border = FALSE; + int x, y; + + x = widget->priv.x; + y = widget->priv.y; + w = h = 0; + max = -1; + curx = widget->priv.x; + cury = widget->priv.y; + if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER)) + { + has_border = TRUE; + curx += 1; + cury += 1; + if (!box->vertical) + curx++; + } + + for (iter = box->list; iter; iter = iter->next) + { + gnt_widget_set_position(GNT_WIDGET(iter->data), curx, cury); + gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h); + if (box->vertical) + { + cury += h + 1; + if (max < w) + max = w; + } + else + { + curx += w + 2; + if (max < h) + max = h; + } + } + + if (has_border) + { + curx += 2; + cury += 1; + max += 2; + } + + if (box->vertical) + { + widget->priv.width = max; + widget->priv.height = cury - widget->priv.y; + } + else + { + widget->priv.width = curx - widget->priv.x; + widget->priv.height = max; + } +} + +static void +gnt_box_set_position(GntWidget *widget, int x, int y) +{ + gnt_widget_size_request(widget); + reposition_children(widget); +} + +static void +gnt_box_size_request(GntWidget *widget) +{ + GntBox *box = GNT_BOX(widget); + GList *iter; + + g_list_foreach(box->list, (GFunc)gnt_widget_size_request, NULL); + + if (box->homogeneous) + { + int max = -1, w, h; + + /* XXX: should probably be changed based on vertical-ness */ + for (iter = box->list; iter; iter = iter->next) + { + gnt_widget_get_size(GNT_WIDGET(iter->data), &w, NULL); + if (max < w) + max = w; + } + + for (iter = box->list; iter; iter = iter->next) + { + gnt_widget_get_size(GNT_WIDGET(iter->data), NULL, &h); + gnt_widget_set_size(GNT_WIDGET(iter->data), max, h); + } + } + + reposition_children(widget); +} + +static void +gnt_box_map(GntWidget *widget) +{ + if (widget->priv.width == 0 || widget->priv.height == 0) + gnt_widget_size_request(widget); + DEBUG; +} + +static gboolean +gnt_box_key_pressed(GntWidget *widget, const char *text) +{ + GntBox *box = GNT_BOX(widget); + + /*if (box->list == NULL)*/ + /*return FALSE;*/ + + if (box->active == NULL) + box->active = box->list; + + if (gnt_widget_key_pressed(box->active->data, text)) + return TRUE; + + if (text[0] == 27) + { + GList *now = NULL; + if (strcmp(text+1, GNT_KEY_LEFT) == 0) + { + now = box->active->prev; + if (now == NULL) + now = g_list_last(box->list); + } + else if (strcmp(text+1, GNT_KEY_RIGHT) == 0) + { + now = box->active->next; + if (now == NULL) + now = box->list; + } + + if (now) + { + gnt_widget_set_focus(box->active->data, FALSE); + box->active = now; + gnt_widget_set_focus(box->active->data, TRUE); + + return TRUE; + } + } + + return FALSE; +} + +static GntWidget *find_focused_widget(GntBox *box) +{ + GList *iter; + + for (iter = box->list; iter; iter = iter->next) + { + GntWidget *w = iter->data; + + if (GNT_IS_BOX(w)) + { + if ((w = find_focused_widget(GNT_BOX(w))) != NULL) + return w; + } + else + { + if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_CAN_TAKE_FOCUS) && + GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_HAS_FOCUS)) + return w; + } + } + return NULL; +} + +static void +gnt_box_lost_focus(GntWidget *widget) +{ + GntBox *box = GNT_BOX(widget); + GntWidget *p = widget; + + while (p->parent) + p = p->parent; + + p = find_focused_widget(GNT_BOX(p)); + if (p) + gnt_widget_set_focus(p, FALSE); +} + +static void +gnt_box_destroy(GntWidget *w) +{ + GntBox *box = GNT_BOX(w); + GList *iter; + + for (iter = box->list; iter; iter = iter->next) + { + gnt_widget_destroy(iter->data); + } + + g_list_free(box->list); +} + +static void +gnt_box_class_init(GntWidgetClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = GNT_WIDGET_CLASS(klass); + parent_class->destroy = gnt_box_destroy; + parent_class->draw = gnt_box_draw; + parent_class->map = gnt_box_map; + parent_class->size_request = gnt_box_size_request; + parent_class->set_position = gnt_box_set_position; + parent_class->key_pressed = gnt_box_key_pressed; + parent_class->lost_focus = gnt_box_lost_focus; + + DEBUG; +} + +static void +gnt_box_init(GTypeInstance *instance, gpointer class) +{ + DEBUG; +} + +/****************************************************************************** + * GntBox API + *****************************************************************************/ +GType +gnt_box_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntBoxClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_box_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntBox), + 0, /* n_preallocs */ + gnt_box_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntBox", + &info, 0); + } + + return type; +} + +GntWidget *gnt_box_new(gboolean homo, gboolean vert) +{ + GntWidget *widget = g_object_new(GNT_TYPE_BOX, NULL); + GntBox *box = GNT_BOX(widget); + + box->homogeneous = homo; + box->vertical = vert; + gnt_widget_set_take_focus(widget, TRUE); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); + + return widget; +} + +void gnt_box_add_widget(GntBox *b, GntWidget *widget) +{ + b->list = g_list_append(b->list, widget); + widget->parent = GNT_WIDGET(b); +} + +void gnt_box_set_title(GntBox *b, const char *title) +{ + g_free(b->title); + b->title = g_strdup(title); +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntbox.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntbox.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,58 @@ +#ifndef GNT_BOX_H +#define GNT_BOX_H + +#include "gnt.h" +#include "gntwidget.h" + +#define GNT_TYPE_BOX (gnt_box_get_gtype()) +#define GNT_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_BOX, GntBox)) +#define GNT_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_BOX, GntBoxClass)) +#define GNT_IS_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_BOX)) +#define GNT_IS_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_BOX)) +#define GNT_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_BOX, GntBoxClass)) + +typedef struct _GnBox GntBox; +typedef struct _GnBoxClass GntBoxClass; + +struct _GnBox +{ + GntWidget parent; + + gboolean vertical; + gboolean homogeneous; + GList *list; /* List of widgets */ + + GList *active; + + char *title; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +struct _GnBoxClass +{ + GntWidgetClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_box_get_gtype(void); + +GntWidget *gnt_box_new(gboolean homo, gboolean vert); + +void gnt_box_add_widget(GntBox *box, GntWidget *widget); + +void gnt_box_set_title(GntBox *box, const char *title); + +G_END_DECLS + +#endif /* GNT_BOX_H */ + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntbutton.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntbutton.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,116 @@ +#include "gntbutton.h" + +enum +{ + SIGS = 1, +}; + +static GntWidgetClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; + +static void +gnt_button_draw(GntWidget *widget) +{ + GntButton *button = GNT_BUTTON(widget); + GntColorType type; + + if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_HAS_FOCUS) + type = GNT_COLOR_HIGHLIGHT; + else + type = GNT_COLOR_NORMAL; + wbkgdset(widget->window, '\0' | COLOR_PAIR(type)); + mvwprintw(widget->window, 1, 1, button->priv->text); + + wrefresh(widget->window); + + DEBUG; +} + +static void +gnt_button_size_request(GntWidget *widget) +{ + GntButton *button = GNT_BUTTON(widget); + widget->priv.width = g_utf8_strlen(button->priv->text, -1) + 2; + widget->priv.height = 3; +} + +static void +gnt_button_map(GntWidget *widget) +{ + if (widget->priv.width == 0 || widget->priv.height == 0) + gnt_widget_size_request(widget); + DEBUG; +} + +static gboolean +gnt_button_key_pressed(GntWidget *widget, const char *key) +{ + if (strcmp(key, GNT_KEY_ENTER) == 0) + { + gnt_widget_activate(widget); + return TRUE; + } + return FALSE; +} + +static void +gnt_button_class_init(GntWidgetClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = GNT_WIDGET_CLASS(klass); + parent_class->draw = gnt_button_draw; + parent_class->map = gnt_button_map; + parent_class->size_request = gnt_button_size_request; + parent_class->key_pressed = gnt_button_key_pressed; + + DEBUG; +} + +static void +gnt_button_init(GTypeInstance *instance, gpointer class) +{ + GntButton *button = GNT_BUTTON(instance); + button->priv = g_new0(GntButtonPriv, 1); + DEBUG; +} + +/****************************************************************************** + * GntButton API + *****************************************************************************/ +GType +gnt_button_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(GntButtonClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_button_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntButton), + 0, /* n_preallocs */ + gnt_button_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntButton", + &info, 0); + } + + return type; +} + +GntWidget *gnt_button_new(const char *text) +{ + GntWidget *widget = g_object_new(GNT_TYPE_BUTTON, NULL); + GntButton *button = GNT_BUTTON(widget); + + button->priv->text = g_strdup(text); + gnt_widget_set_take_focus(widget, TRUE); + + return widget; +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntbutton.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntbutton.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,55 @@ +#ifndef GNT_BUTTON_H +#define GNT_BUTTON_H + +#include +#include +#include "gnt.h" +#include "gntwidget.h" + +#define GNT_TYPE_BUTTON (gnt_button_get_gtype()) +#define GNT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_BUTTON, GntButton)) +#define GNT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_BUTTON, GntButtonClass)) +#define GNT_IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_BUTTON)) +#define GNT_IS_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_BUTTON)) +#define GNT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_BUTTON, GntButtonClass)) + +typedef struct _GnButton GntButton; +typedef struct _GnButtonPriv GntButtonPriv; +typedef struct _GnButtonClass GntButtonClass; + +struct _GnButtonPriv +{ + char *text; +}; + +struct _GnButton +{ + GntWidget parent; + + GntButtonPriv *priv; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +struct _GnButtonClass +{ + GntWidgetClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_button_get_gtype(void); + +GntWidget *gnt_button_new(const char *text); + +G_END_DECLS + +#endif /* GNT_BUTTON_H */ diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntcolors.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntcolors.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,21 @@ +#include +#include "gntcolors.h" + +void gnt_init_colors() +{ + /* XXX: Do some init_color()s */ + init_color(GNT_COLOR_BLACK, 0, 0, 0); + init_color(GNT_COLOR_RED, 1000, 0, 0); + init_color(GNT_COLOR_GREEN, 0, 1000, 0); + init_color(GNT_COLOR_BLUE, 0, 0, 1000); + init_color(GNT_COLOR_WHITE, 1000, 1000, 1000); + init_color(GNT_COLOR_GRAY, 799, 799, 799); + init_color(GNT_COLOR_DARK_GRAY, 256, 256, 256); + + /* Now some init_pair()s */ + init_pair(GNT_COLOR_NORMAL, GNT_COLOR_BLACK, GNT_COLOR_WHITE); + init_pair(GNT_COLOR_HIGHLIGHT, GNT_COLOR_BLUE, GNT_COLOR_GRAY); + init_pair(GNT_COLOR_SHADOW, GNT_COLOR_BLACK, GNT_COLOR_DARK_GRAY); + init_pair(GNT_COLOR_TITLE, GNT_COLOR_WHITE, GNT_COLOR_DARK_GRAY); +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntcolors.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntcolors.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,34 @@ +#ifndef GNT_COLORS_H +#define GNT_COLORS_H + +typedef enum +{ + GNT_COLOR_NORMAL = 1, + GNT_COLOR_HIGHLIGHT, /* eg. when a button is selected */ + GNT_COLOR_DISABLED, /* eg. when a button is disabled */ + GNT_COLOR_HIGHLIGHT_D, /* eg. when a button is selected, but some other window is in focus */ + GNT_COLOR_TEXT_NORMAL, + GNT_COLOR_TEXT_INACTIVE, /* when the entry is out of focus */ + GNT_COLOR_MNEMONIC, + GNT_COLOR_MNEMONIC_D, + GNT_COLOR_SHADOW, + GNT_COLOR_TITLE, + GNT_COLORS +} GntColorType; + +enum +{ + GNT_COLOR_BLACK = 1, + GNT_COLOR_RED, + GNT_COLOR_GREEN, + GNT_COLOR_BLUE, + GNT_COLOR_WHITE, + GNT_COLOR_GRAY, + GNT_COLOR_DARK_GRAY, + GNT_TOTAL_COLORS +}; + +/* populate some default colors */ +void gnt_init_colors(); + +#endif diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntkeys.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntkeys.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,14 @@ +#ifndef GNT_KEYS_H +#define GNT_KEYS_H + +#define GNT_KEY_POPUP "[29~" + +/* Arrow keys */ +#define GNT_KEY_LEFT "[D" +#define GNT_KEY_RIGHT "[C" +#define GNT_KEY_UP "[A" +#define GNT_KEY_DOWN "[B" + +#define GNT_KEY_ENTER "\r" + +#endif diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntlabel.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntlabel.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,120 @@ +#include "gntlabel.h" + +#include + +enum +{ + SIGS = 1, +}; + +static GntWidgetClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; + +static void +gnt_label_destroy(GntWidget *widget) +{ + GntLabel *label = GNT_LABEL(widget); + g_free(label->text); +} + +static void +gnt_label_draw(GntWidget *widget) +{ + GntLabel *label = GNT_LABEL(widget); + + wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + mvwprintw(widget->window, 0, 0, label->text); + wrefresh(widget->window); + + DEBUG; +} + +static void +gnt_label_size_request(GntWidget *widget) +{ + GntLabel *label = GNT_LABEL(widget); + char *s = label->text, *last = s; + int count = 1; + int max = 0; + + /* XXX: ew ... everyone look away */ + while (*s) + { + if (*s == '\n' || *s == '\r') + { + count++; + if (max < s - last + 1) + max = s - last + 1; + last = s + 1; + } + s++; + } + if (max < s - last + 1) + max = s - last + 1; + widget->priv.height = count; + + widget->priv.width = max; +} + +static void +gnt_label_class_init(GntWidgetClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = GNT_WIDGET_CLASS(klass); + parent_class->destroy = gnt_label_destroy; + parent_class->draw = gnt_label_draw; + parent_class->map = NULL; + parent_class->size_request = gnt_label_size_request; + + DEBUG; +} + +static void +gnt_label_init(GTypeInstance *instance, gpointer class) +{ + DEBUG; +} + +/****************************************************************************** + * GntLabel API + *****************************************************************************/ +GType +gnt_label_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntLabelClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_label_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntLabel), + 0, /* n_preallocs */ + gnt_label_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntLabel", + &info, 0); + } + + return type; +} + +GntWidget *gnt_label_new(const char *text) +{ + GntWidget *widget = g_object_new(GNT_TYPE_LABEL, NULL); + GntLabel *label = GNT_LABEL(widget); + + label->text = g_strdup(text); + gnt_widget_set_take_focus(widget, FALSE); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); + + return widget; +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntlabel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntlabel.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,48 @@ +#ifndef GNT_LABEL_H +#define GNT_LABEL_H + +#include "gnt.h" +#include "gntwidget.h" + +#define GNT_TYPE_LABEL (gnt_label_get_gtype()) +#define GNT_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_LABEL, GntLabel)) +#define GNT_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_LABEL, GntLabelClass)) +#define GNT_IS_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_LABEL)) +#define GNT_IS_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_LABEL)) +#define GNT_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_LABEL, GntLabelClass)) + +typedef struct _GnLabel GntLabel; +typedef struct _GnLabelClass GntLabelClass; + +struct _GnLabel +{ + GntWidget parent; + + char *text; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +struct _GnLabelClass +{ + GntWidgetClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_label_get_gtype(void); + +GntWidget *gnt_label_new(const char *text); + +G_END_DECLS + +#endif /* GNT_LABEL_H */ + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntmain.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntmain.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,111 @@ +#include "gnt.h" +#include "gntkeys.h" +#include "gntcolors.h" +#include +#include +#include + +static GList *focus_list; +static int max_x; +static int max_y; + +void gnt_screen_take_focus(GntWidget *widget) +{ + focus_list = g_list_prepend(focus_list, widget); +} + +void gnt_screen_remove_widget(GntWidget *widget) +{ + focus_list = g_list_remove(focus_list, widget); + if (focus_list) + gnt_widget_draw(focus_list->data); +} + +static gboolean +io_invoke(GIOChannel *source, GIOCondition cond, gpointer null) +{ + char buffer[256]; + + int rd = read(0, buffer, sizeof(buffer) - 1); + if (rd < 0) + { + endwin(); + printf("ERROR!\n"); + exit(1); + } + else if (rd == 0) + { + endwin(); + printf("EOF\n"); + exit(1); + } + + buffer[rd] = 0; + + if (focus_list) + { + gboolean ret = FALSE; + /*g_signal_emit_by_name(focus_list->data, "key_pressed", buffer, &ret);*/ + ret = gnt_widget_key_pressed(focus_list->data, buffer); + } + + if (buffer[0] == 27) + { + /* Some special key has been pressed */ + if (strcmp(buffer+1, GNT_KEY_POPUP) == 0) + { + /*printf("popup\n");*/ + } + else + { + /*printf("Unknown: %s\n", buffer+1);*/ + } + } + else + { + if (buffer[0] == 'q') + { + endwin(); + exit(1); + } + /*printf("%s\n", buffer);*/ + } + refresh(); + + return TRUE; +} + +void gnt_init() +{ + GIOChannel *channel = g_io_channel_unix_new(0); + + g_io_channel_set_encoding(channel, NULL, NULL); + g_io_channel_set_buffered(channel, FALSE); + g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL ); + + int result = g_io_add_watch(channel, + (G_IO_IN | G_IO_HUP | G_IO_ERR), + io_invoke, NULL); + + setlocale(LC_ALL, ""); + initscr(); + start_color(); + /*use_default_colors();*/ + gnt_init_colors(); + + max_x = getmaxx(stdscr); + max_y = getmaxy(stdscr); + + wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + noecho(); + refresh(); + mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); + g_type_init(); +} + +void gnt_main() +{ + GMainLoop *loop = g_main_new(FALSE); + g_main_run(loop); +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gnttree.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gnttree.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,346 @@ +#include "gnttree.h" + +enum +{ + SIGS = 1, +}; + +/* XXX: Make this one into a GObject? + * ... Probably not */ +struct _GnTreeRow +{ + void *key; + char *text; + void *data; /* XXX: unused */ + + GntTreeRow *parent; + GntTreeRow *child; + GntTreeRow *next; +}; + +static GntWidgetClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; + +/* XXX: This is ugly, but what can you do ... */ +static void +gnt_tree_refresh(GntTree *tree) +{ + GntWidget *widget = GNT_WIDGET(tree); + int pos; + + if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) + pos = 0; + else + pos = 1; + + copywin(tree->scroll, widget->window, tree->top, 0, + pos, pos, widget->priv.height - pos - 1, widget->priv.width - pos - 1, FALSE); + wrefresh(widget->window); +} + +static void +redraw_tree(GntTree *tree) +{ + int start; + GntWidget *widget = GNT_WIDGET(tree); + GList *iter; + + wbkgd(tree->scroll, COLOR_PAIR(GNT_COLOR_NORMAL)); + + /* XXX: Add the rows */ + for (start = tree->top, iter = g_list_nth(tree->list, tree->top); + iter && start < tree->bottom; start++, iter = iter->next) + { + char str[2096]; /* XXX: This should be safe for any terminal */ + GntTreeRow *row = g_hash_table_lookup(tree->hash, iter->data); + + snprintf(str, widget->priv.width - 2, "%s\n", row->text); + + if (start == tree->current) + { + wbkgdset(tree->scroll, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + mvwprintw(tree->scroll, start, 0, str); + wbkgdset(tree->scroll, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + } + else + mvwprintw(tree->scroll, start, 0, str); + } + + while (start < tree->bottom) + { + wmove(tree->scroll, start, 0); + wclrtoeol(tree->scroll); + start++; + } + + gnt_tree_refresh(tree); +} + +static void +gnt_tree_draw(GntWidget *widget) +{ + GntTree *tree = GNT_TREE(widget); + + /* For the Tree (or anything that scrolls), we will create a 'hidden' window + * of 'large enough' size. We never wrefresh that hidden-window, instead we + * just 'scroll' it, and wrefresh the subwindow */ + + if (tree->scroll == NULL) + { + tree->scroll = newwin(SCROLL_HEIGHT, widget->priv.width, widget->priv.y, widget->priv.x); + scrollok(tree->scroll, TRUE); + wsetscrreg(tree->scroll, 0, SCROLL_HEIGHT - 1); + + tree->top = 0; + tree->bottom = widget->priv.height - + (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER) ? 0 : 2); + } + + redraw_tree(tree); + + DEBUG; +} + +static void +gnt_tree_size_request(GntWidget *widget) +{ + if (widget->priv.height == 0) + widget->priv.height = 10; /* XXX: Why?! */ + if (widget->priv.width == 0) + widget->priv.width = 20; /* YYY: 'cuz ... */ +} + +static void +gnt_tree_map(GntWidget *widget) +{ + if (widget->priv.width == 0 || widget->priv.height == 0) + gnt_widget_size_request(widget); + DEBUG; +} + +static gboolean +gnt_tree_key_pressed(GntWidget *widget, const char *text) +{ + GntTree *tree = GNT_TREE(widget); + if (text[0] == 27) + { + if (strcmp(text+1, GNT_KEY_DOWN) == 0 && tree->current < g_list_length(tree->list) - 1) + { + tree->current++; + if (tree->current >= tree->bottom) + gnt_tree_scroll(tree, 1 + tree->current - tree->bottom); + redraw_tree(tree); + } + else if (strcmp(text+1, GNT_KEY_UP) == 0 && tree->current > 0) + { + tree->current--; + if (tree->current < tree->top) + gnt_tree_scroll(tree, tree->current - tree->top); + redraw_tree(tree); + } + } + else if (text[0] == '\r') + { + gnt_widget_activate(widget); + } + + return FALSE; +} + +static void +gnt_tree_destroy(GntWidget *widget) +{ + GntTree *tree = GNT_TREE(widget); + + g_hash_table_destroy(tree->hash); + g_list_free(tree->list); +} + +static void +gnt_tree_class_init(GntWidgetClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = GNT_WIDGET_CLASS(klass); + parent_class->destroy = gnt_tree_destroy; + parent_class->draw = gnt_tree_draw; + parent_class->map = gnt_tree_map; + parent_class->size_request = gnt_tree_size_request; + parent_class->key_pressed = gnt_tree_key_pressed; + + DEBUG; +} + +static void +gnt_tree_init(GTypeInstance *instance, gpointer class) +{ + DEBUG; +} + +/****************************************************************************** + * GntTree API + *****************************************************************************/ +GType +gnt_tree_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntTreeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_tree_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntTree), + 0, /* n_preallocs */ + gnt_tree_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntTree", + &info, 0); + } + + return type; +} + +GntWidget *gnt_tree_new() +{ + GntWidget *widget = g_object_new(GNT_TYPE_TREE, NULL); + GntTree *tree = GNT_TREE(widget); + + tree->hash = g_hash_table_new(g_direct_hash, g_direct_equal); + + return widget; +} + +void gnt_tree_set_visible_rows(GntTree *tree, int rows) +{ + GntWidget *widget = GNT_WIDGET(tree); + widget->priv.height = rows; + if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) + widget->priv.height += 2; +} + +int gnt_tree_get_visible_rows(GntTree *tree) +{ + GntWidget *widget = GNT_WIDGET(tree); + int ret = widget->priv.height; + if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) + widget->priv.height -= 2; +} + +void gnt_tree_scroll(GntTree *tree, int count) +{ + if (tree->top == 0 && count < 0) + return; + + if (count > 0 && tree->bottom + count >= g_list_length(tree->list)) + count = g_list_length(tree->list) - tree->bottom; + else if (count < 0 && tree->top + count < 0) + count = -tree->top; + + tree->top += count; + tree->bottom += count; + + /*wscrl(tree->scroll, count);*/ + gnt_tree_refresh(tree); +} + +void gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro) +{ + GntTreeRow *row = g_new0(GntTreeRow, 1), *pr = NULL; + + row->key = key; + row->text = g_strdup(text); + row->data = NULL; + + g_hash_table_insert(tree->hash, key, row); + + if (tree->root == NULL) + { + tree->root = row; + tree->list = g_list_prepend(tree->list, key); + } + else + { + int position; + + if (bigbro) + { + pr = g_hash_table_lookup(tree->hash, bigbro); + if (pr) + { + row->next = pr->next; + pr->next = row; + row->parent = pr->parent; + + position = g_list_index(tree->list, bigbro); + } + } + + if (pr == NULL && parent) + { + pr = g_hash_table_lookup(tree->hash, parent); + if (pr) + { + row->next = pr->child; + pr->child = row; + row->parent = pr; + + position = g_list_index(tree->list, parent); + } + } + + if (pr == NULL) + { + row->next = tree->root; + tree->root = row; + + tree->list = g_list_prepend(tree->list, key); + } + else + { + tree->list = g_list_insert(tree->list, key, position + 1); + } + } + + if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED)) + redraw_tree(tree); +} + +gpointer gnt_tree_get_selection_data(GntTree *tree) +{ + return g_list_nth(tree->list, tree->current); +} + +int gnt_tree_get_selection_index(GntTree *tree) +{ + return tree->current; +} + +void gnt_tree_remove(GntTree *tree, gpointer key) +{ + GntTreeRow *row = g_hash_table_lookup(tree->hash, key); + if (row) + { + int len, pos; + + g_free(row->text); + g_free(row); + + pos = g_list_index(tree->list, key); + + g_hash_table_remove(tree->hash, key); + tree->list = g_list_remove(tree->list, key); + + if (pos >= tree->top && pos < tree->bottom) + { + redraw_tree(tree); + } + } +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gnttree.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gnttree.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,75 @@ +#ifndef GNT_TREE_H +#define GNT_TREE_H + +#include "gntwidget.h" +#include "gnt.h" +#include "gntcolors.h" +#include "gntkeys.h" + +#define GNT_TYPE_TREE (gnt_tree_get_gtype()) +#define GNT_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_TREE, GntTree)) +#define GNT_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_TREE, GntTreeClass)) +#define GNT_IS_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_TREE)) +#define GNT_IS_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_TREE)) +#define GNT_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_TREE, GntTreeClass)) + +#define GNT_TREE_FLAGS(obj) (GNT_TREE(obj)->priv.flags) +#define GNT_TREE_SET_FLAGS(obj, flags) (GNT_TREE_FLAGS(obj) |= flags) +#define GNT_TREE_UNSET_FLAGS(obj, flags) (GNT_TREE_FLAGS(obj) &= ~(flags)) + +typedef struct _GnTree GntTree; +typedef struct _GnTreePriv GntTreePriv; +typedef struct _GnTreeClass GntTreeClass; + +typedef struct _GnTreeRow GntTreeRow; + +struct _GnTree +{ + GntWidget parent; + + WINDOW *scroll; + + int current; /* current selection */ + + int top; /* The index in 'list' of the topmost visible item */ + int bottom; /* The index in 'list' of the bottommost visible item */ + + GntTreeRow *root; /* The root of all evil */ + + GList *list; /* List of GntTreeRow s */ + GHashTable *hash; /* XXX: We may need this for quickly referencing the rows */ +}; + +struct _GnTreeClass +{ + GntWidgetClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_tree_get_gtype(void); + +GntWidget *gnt_tree_new(); + +void gnt_tree_set_visible_rows(GntTree *tree, int rows); + +int gnt_tree_get_visible_rows(GntTree *tree); + +void gnt_tree_scroll(GntTree *tree, int count); + +void gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro); + +gpointer gnt_tree_get_selection_data(GntTree *tree); + +int gnt_tree_get_selection_index(GntTree *tree); + +void gnt_tree_remove(GntTree *tree, gpointer key); + +G_END_DECLS + +#endif /* GNT_TREE_H */ diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntutils.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntutils.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,100 @@ +#include "gntutils.h" + +void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*func) (gpointer data1, const char *arg1, gpointer data2); + register func callback; + register GCClosure *cc = (GCClosure*)closure; + register gpointer data1, data2; + gboolean ret; + + g_return_if_fail(ret_value != NULL); + g_return_if_fail(n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA(closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (func) (marshal_data ? marshal_data : cc->callback); + ret = callback(data1, g_value_get_string(param_values + 1) , data2); + g_value_set_boolean(ret_value, ret); +} + +void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*func) (gpointer data1, int, int, int, int, gpointer data2); + register func callback; + register GCClosure *cc = (GCClosure*)closure; + register gpointer data1, data2; + + g_return_if_fail(n_param_values == 5); + + if (G_CCLOSURE_SWAP_DATA(closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (func) (marshal_data ? marshal_data : cc->callback); + callback(data1, + g_value_get_int(param_values + 1) , + g_value_get_int(param_values + 2) , + g_value_get_int(param_values + 3) , + g_value_get_int(param_values + 4) , + data2); +} + +void gnt_closure_marshal_VOID__INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*func) (gpointer data1, int, int, gpointer data2); + register func callback; + register GCClosure *cc = (GCClosure*)closure; + register gpointer data1, data2; + + g_return_if_fail(n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA(closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (func) (marshal_data ? marshal_data : cc->callback); + callback(data1, + g_value_get_int(param_values + 1) , + g_value_get_int(param_values + 2) , + data2); +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntutils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntutils.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,23 @@ +#include "gntwidget.h" + +void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +void gnt_closure_marshal_VOID__INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntwidget.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntwidget.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,386 @@ +/* Stuff brutally ripped from Gflib */ + +#include "gntwidget.h" +#include "gntutils.h" +#include "gnt.h" + +enum +{ + SIG_DESTROY, + SIG_DRAW, + SIG_GIVE_FOCUS, + SIG_LOST_FOCUS, + SIG_KEY_PRESSED, + SIG_MAP, + SIG_ACTIVATE, + SIG_EXPOSE, + SIG_SIZE_REQUEST, + SIG_POSITION, + SIGS +}; + +static GObjectClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; + +static void +gnt_widget_init(GTypeInstance *instance, gpointer class) +{ + GntWidget *widget = GNT_WIDGET(instance); + widget->priv.name = NULL; + DEBUG; +} + +static void +gnt_widget_map(GntWidget *widget) +{ + /* Get some default size for the widget */ + DEBUG; + g_signal_emit(widget, signals[SIG_MAP], 0); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_MAPPED); +} + +static void +gnt_widget_dispose(GObject *obj) +{ + GntWidget *self = GNT_WIDGET(obj); + + if(!(GNT_WIDGET_FLAGS(self) & GNT_WIDGET_DESTROYING)) { + GNT_WIDGET_SET_FLAGS(self, GNT_WIDGET_DESTROYING); + + g_signal_emit(self, signals[SIG_DESTROY], 0); + + GNT_WIDGET_UNSET_FLAGS(self, GNT_WIDGET_DESTROYING); + } + + parent_class->dispose(obj); + DEBUG; +} + +static void +gnt_widget_focus_change(GntWidget *widget) +{ + if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED) + gnt_widget_draw(widget); +} + +static void +gnt_widget_class_init(GntWidgetClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = gnt_widget_dispose; + + klass->destroy = gnt_widget_destroy; + klass->show = gnt_widget_show; + klass->draw = gnt_widget_draw; + klass->expose = gnt_widget_expose; + klass->map = gnt_widget_map; + klass->lost_focus = gnt_widget_focus_change; + klass->gained_focus = gnt_widget_focus_change; + + klass->key_pressed = NULL; + klass->activate = NULL; + + signals[SIG_DESTROY] = + g_signal_new("destroy", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, destroy), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[SIG_GIVE_FOCUS] = + g_signal_new("gained-focus", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, gained_focus), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[SIG_LOST_FOCUS] = + g_signal_new("lost-focus", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, lost_focus), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[SIG_ACTIVATE] = + g_signal_new("activate", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, activate), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[SIG_MAP] = + g_signal_new("map", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, map), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[SIG_DRAW] = + g_signal_new("draw", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, draw), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[SIG_EXPOSE] = + g_signal_new("expose", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, expose), + NULL, NULL, + gnt_closure_marshal_VOID__INT_INT_INT_INT, + G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); + signals[SIG_POSITION] = + g_signal_new("position-set", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, set_position), + NULL, NULL, + gnt_closure_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); + signals[SIG_SIZE_REQUEST] = + g_signal_new("size_request", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, size_request), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[SIG_KEY_PRESSED] = + g_signal_new("key_pressed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWidgetClass, key_pressed), + NULL, NULL, + gnt_closure_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, G_TYPE_STRING); + DEBUG; +} + +/****************************************************************************** + * GntWidget API + *****************************************************************************/ +GType +gnt_widget_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(GntWidgetClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_widget_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntWidget), + 0, /* n_preallocs */ + gnt_widget_init, /* instance_init */ + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "GntWidget", + &info, G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +static void +gnt_widget_take_focus(GntWidget *widget) +{ + gnt_screen_take_focus(widget); +} + +void gnt_widget_set_take_focus(GntWidget *widget, gboolean can) +{ + if (can) + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); + else + GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); +} + +/** + * gnt_widget_destroy: + * @obj: The #GntWidget instance. + * + * Emits the "destroy" signal notifying all reference holders that they + * should release @obj. + */ +void +gnt_widget_destroy(GntWidget *obj) +{ + g_return_if_fail(GNT_IS_WIDGET(obj)); + + delwin(obj->window); + if(!(GNT_WIDGET_FLAGS(obj) & GNT_WIDGET_DESTROYING)) + g_object_run_dispose(G_OBJECT(obj)); + gnt_screen_remove_widget(obj); + DEBUG; +} + +void +gnt_widget_show(GntWidget *widget) +{ + /* Draw the widget and take focus */ + gnt_widget_draw(widget); + if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_CAN_TAKE_FOCUS) + { + gnt_widget_take_focus(widget); + } +} + +void +gnt_widget_draw(GntWidget *widget) +{ + /* Draw the widget */ + DEBUG; + if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED)) + gnt_widget_map(widget); + + if (widget->window) + { + delwin(widget->window); + } + + widget->window = newwin(widget->priv.height, widget->priv.width, + widget->priv.y, widget->priv.x); + wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL)); + if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER)) + { + box(widget->window, 0, 0); + } + else + werase(widget->window); + + if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_SHADOW)) + { + /* XXX: Find out the actual windows beneath this window, and + * draw the shadow on them */ + /* XXX: Or perhaps do all these from a psedo-WM! */ + widget->back = newwin(widget->priv.height, widget->priv.width, + widget->priv.y + 1, widget->priv.x + 1); + wbkgd(widget->back, COLOR_PAIR(GNT_COLOR_SHADOW)); + werase(widget->back); + + mvwchgat(widget->back, 0, 0, widget->priv.height, + A_REVERSE | A_BLINK, 0, 0); + touchline(widget->back, 0, widget->priv.height); + wrefresh(widget->back); + } + + wrefresh(widget->window); + g_signal_emit(widget, signals[SIG_DRAW], 0); +} + +gboolean +gnt_widget_key_pressed(GntWidget *widget, const char *keys) +{ + gboolean ret; + g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret); + return ret; +} + +void +gnt_widget_expose(GntWidget *widget, int x, int y, int width, int height) +{ + g_signal_emit(widget, signals[SIG_EXPOSE], 0, x, y, width, height); +} + +void +gnt_widget_hide(GntWidget *widget) +{ + int i; + + /* XXX: Currently it simply empties the window. Ideally, it will + * detect what windows are immediately beneath this one, and cause + * those windows to redraw themselves by emitting the approrpiate + * expose signal. */ + + werase(widget->window); + wrefresh(widget->window); +} + +void +gnt_widget_set_position(GntWidget *wid, int x, int y) +{ + /* XXX: Need to install properties for these and g_object_notify */ + wid->priv.x = x; + wid->priv.y = y; + g_signal_emit(wid, signals[SIG_POSITION], 0, x, y); +} + +void +gnt_widget_get_position(GntWidget *wid, int *x, int *y) +{ + if (x) + *x = wid->priv.x; + if (y) + *y = wid->priv.y; +} + +void +gnt_widget_size_request(GntWidget *widget) +{ + g_signal_emit(widget, signals[SIG_SIZE_REQUEST], 0); +} + +void +gnt_widget_get_size(GntWidget *wid, int *width, int *height) +{ + if (width) + *width = wid->priv.width; + if (height) + *height = wid->priv.height; +} + +void +gnt_widget_set_size(GntWidget *widget, int width, int height) +{ + widget->priv.width = width; + widget->priv.height = height; +} + +gboolean +gnt_widget_set_focus(GntWidget *widget, gboolean set) +{ + if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_CAN_TAKE_FOCUS)) + return FALSE; + + if (set && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_HAS_FOCUS)) + { + g_signal_emit(widget->parent, signals[SIG_LOST_FOCUS], 0); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS); + g_signal_emit(widget, signals[SIG_GIVE_FOCUS], 0); + } + else if (!set) + { + GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS); + g_signal_emit(widget, signals[SIG_LOST_FOCUS], 0); + } + else + return FALSE; + + return TRUE; +} + +void gnt_widget_set_name(GntWidget *widget, const char *name) +{ + g_free(widget->priv.name); + widget->priv.name = g_strdup(name); +} + +void gnt_widget_activate(GntWidget *widget) +{ + g_signal_emit(widget, signals[SIG_ACTIVATE], 0); +} + diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/gntwidget.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntwidget.h Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,117 @@ +#ifndef GNT_WIDGET_H +#define GNT_WIDGET_H + +#include +#include +#include +#include + +#define GNT_TYPE_WIDGET (gnt_widget_get_gtype()) +#define GNT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WIDGET, GntWidget)) +#define GNT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_WIDGET, GntWidgetClass)) +#define GNT_IS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WIDGET)) +#define GNT_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WIDGET)) +#define GNT_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WIDGET, GntWidgetClass)) + +#define GNT_WIDGET_FLAGS(obj) (GNT_WIDGET(obj)->priv.flags) +#define GNT_WIDGET_SET_FLAGS(obj, flags) (GNT_WIDGET_FLAGS(obj) |= flags) +#define GNT_WIDGET_UNSET_FLAGS(obj, flags) (GNT_WIDGET_FLAGS(obj) &= ~(flags)) +#define GNT_WIDGET_IS_FLAG_SET(obj, flags) (GNT_WIDGET_FLAGS(obj) & (flags)) +#define DEBUG +//#define DEBUG printf("%s\n", __FUNCTION__) + +typedef struct _GnWidget GntWidget; +typedef struct _GnWidgetPriv GntWidgetPriv; +typedef struct _GnWidgetClass GntWidgetClass; + +#define N_(X) X + +typedef enum _GnWidgetFlags +{ + GNT_WIDGET_DESTROYING = 1 << 0, + GNT_WIDGET_CAN_TAKE_FOCUS= 1 << 1, + GNT_WIDGET_MAPPED = 1 << 2, + /* XXX: Need to set the following two as properties, and setup a callback whenever these + * get chnaged. */ + GNT_WIDGET_NO_BORDER = 1 << 3, + GNT_WIDGET_NO_SHADOW = 1 << 4, + GNT_WIDGET_HAS_FOCUS = 1 << 5 +} GntWidgetFlags; + +typedef enum _GnParamFlags +{ + GNT_PARAM_SERIALIZABLE = 1 << G_PARAM_USER_SHIFT +} GntParamFlags; + +struct _GnWidgetPriv +{ + int x, y; + int width, height; + GntWidgetFlags flags; + char *name; +}; + +struct _GnWidget +{ + GObject inherit; + + GntWidget *parent; + + GntWidgetPriv priv; + WINDOW *window; + WINDOW *back; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +struct _GnWidgetClass +{ + GObjectClass parent; + + void (*map)(GntWidget *obj); + void (*show)(GntWidget *obj); /* This will call draw() and take focus (if it can take focus) */ + void (*destroy)(GntWidget *obj); + void (*draw)(GntWidget *obj); /* This will draw the widget */ + void (*expose)(GntWidget *widget, int x, int y, int width, int height); + void (*gained_focus)(GntWidget *widget); + void (*lost_focus)(GntWidget *widget); + + void (*size_request)(GntWidget *widget); + void (*set_position)(GntWidget *widget, int x, int y); + gboolean (*key_pressed)(GntWidget *widget, const char *key); + void (*activate)(GntWidget *widget); + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_widget_get_gtype(void); +void gnt_widget_destroy(GntWidget *widget); +void gnt_widget_show(GntWidget *widget); +void gnt_widget_draw(GntWidget *widget); +void gnt_widget_expose(GntWidget *widget, int x, int y, int width, int height); +void gnt_widget_hide(GntWidget *widget); + +void gnt_widget_get_position(GntWidget *widget, int *x, int *y); +void gnt_widget_set_position(GntWidget *widget, int x, int y); +void gnt_widget_size_request(GntWidget *widget); +void gnt_widget_get_size(GntWidget *widget, int *width, int *height); +void gnt_widget_set_size(GntWidget *widget, int width, int height); + +gboolean gnt_widget_key_pressed(GntWidget *widget, const char *keys); + +gboolean gnt_widget_set_focus(GntWidget *widget, gboolean set); +void gnt_widget_activate(GntWidget *widget); + +void gnt_widget_set_name(GntWidget *widget, const char *name); + +G_END_DECLS + +#endif /* GNT_WIDGET_H */ diff -r 8d1c55309e3c -r 0e1e59770cb0 console/libgnt/test.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/test.c Thu Jun 22 08:33:54 2006 +0000 @@ -0,0 +1,112 @@ +#include "gntbutton.h" +#include "gnt.h" +#include "gntkeys.h" +#include "gnttree.h" + +static gboolean +key_pressed(GntWidget *widget, const char *text, gpointer null) +{ + GntWidget *w = null; + + gnt_widget_set_focus(w, TRUE); + + /* XXX: This is to just test stuff */ + if (text[0] == 27) + { + if (strcmp(text+1, GNT_KEY_LEFT) == 0 && w->priv.x) + (w->priv.x)--; + else if (strcmp(text+1, GNT_KEY_RIGHT) == 0) + (w->priv.x)++; + else if (strcmp(text+1, GNT_KEY_UP) == 0 && w->priv.y) + (w->priv.y)--; + else if (strcmp(text+1, GNT_KEY_DOWN) == 0) + (w->priv.y)++; + } + + gnt_widget_draw(w); + + return FALSE; +} + +static void +button1(GntWidget *widget, gpointer null) +{ + printf("OLAAA"); + gnt_widget_destroy(null); +} + +static void +button2(GntWidget *widget, gpointer null) +{ + printf("BOOYAA"); +} + +static gboolean +w_scroll(GntWidget *tree) +{ + g_return_val_if_fail(GNT_IS_TREE(tree), FALSE); + gnt_tree_scroll(GNT_TREE(tree), 1); + /*wscrl(tree->window, 1);*/ + /*box(tree->window, ACS_VLINE, ACS_HLINE);*/ + /*wrefresh(tree->window);*/ + /*char *s = 0;*/ + /**s = 'a';*/ + return TRUE; +} + +int main() +{ + gnt_init(); + + GntWidget *widget = gnt_button_new("Button 1"); + GntWidget *widget2 = gnt_button_new("Button 2 has a longish text with a UTF-8 thing …"); + GntWidget *label = gnt_label_new("So wassup dudes and dudettes!!\nSo this is, like,\nthe third line!! \\o/"); + GntWidget *vbox, *hbox, *tree; + WINDOW *test; + + box(stdscr, 0, 0); + wrefresh(stdscr); + + vbox = gnt_box_new(FALSE, FALSE); + hbox = gnt_box_new(FALSE, TRUE); + + gnt_widget_set_name(vbox, "vbox"); + gnt_widget_set_name(hbox, "hbox"); + gnt_widget_set_name(widget, "widget"); + gnt_widget_set_name(widget2, "widget2"); + + gnt_box_add_widget(vbox, widget); + gnt_box_add_widget(vbox, widget2); + + gnt_box_add_widget(hbox, label); + gnt_box_add_widget(hbox, vbox); + + tree = gnt_tree_new(); + gnt_box_add_widget(hbox, tree); + + gnt_tree_add_row_after(GNT_TREE(tree), "a", "a", NULL, NULL); + gnt_tree_add_row_after(GNT_TREE(tree), "c", "c", NULL, NULL); + gnt_tree_add_row_after(GNT_TREE(tree), "d", "d", NULL, NULL); + gnt_tree_add_row_after(GNT_TREE(tree), "e", "e", "a", NULL); + gnt_tree_add_row_after(GNT_TREE(tree), "b", "b", "d", NULL); + + GNT_WIDGET_UNSET_FLAGS(hbox, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); + gnt_box_set_title(hbox, "111111111111111111111111111111111111111111111111111111111111111This is the title …"); + + /*gnt_widget_set_take_focus(vbox, TRUE);*/ + /*gnt_widget_set_take_focus(hbox, TRUE);*/ + gnt_widget_set_position(hbox, 10, 10); + + gnt_widget_show(hbox); + + g_signal_connect(hbox, "key_pressed", G_CALLBACK(key_pressed), widget); + g_signal_connect(widget, "activate", G_CALLBACK(button1), hbox); + g_signal_connect(widget2, "activate", G_CALLBACK(button2), hbox); + + /*g_timeout_add(1000, (GSourceFunc)w_scroll, tree);*/ + + gnt_main(); + + return 0; +} +