Mercurial > pidgin
changeset 13855:5b288502a382
[gaim-migrate @ 16314]
New widget GntEntry. It's mostly functional.
Some minor improvements to the box-packing code.
Minor improvements to the skeleton code for gnt, and completely change the name from my initial choice of GN (Glib and Ncurses) to GNT (Gaim Ncurses Toolkit).
committer: Tailor Script <tailor@pidgin.im>
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Fri, 23 Jun 2006 06:24:25 +0000 |
parents | a4c30c1d9de8 |
children | 3cdd05b9830a |
files | console/libgnt/Makefile console/libgnt/gnt-skel.c console/libgnt/gnt-skel.h console/libgnt/gntbox.c console/libgnt/gntcolors.c console/libgnt/gntentry.c console/libgnt/gntentry.h console/libgnt/gntkeys.h console/libgnt/gnttree.c console/libgnt/gntwidget.c console/libgnt/test.c |
diffstat | 11 files changed, 404 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/console/libgnt/Makefile Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/Makefile Fri Jun 23 06:24:25 2006 +0000 @@ -6,6 +6,7 @@ gntbox.h \ gntbutton.h \ gntcolors.h \ + gntentry.h \ gntlabel.h \ gnttree.h \ gntutils.h \ @@ -16,6 +17,7 @@ gntbox.c \ gntbutton.c \ gntcolors.c \ + gntentry.c \ gntlabel.c \ gnttree.c \ gntutils.c \ @@ -26,6 +28,7 @@ gntbox.o \ gntbutton.o \ gntcolors.o \ + gntentry.o \ gntlabel.o \ gnttree.o \ gntutils.o \ @@ -34,11 +37,13 @@ all: libgnt test: $(OBJECTS) +key: $(OBJECTS) gntwidget.o: gntwidget.c $(HEADERS) gntbox.o: gntbox.c $(HEADERS) gntbutton.o: gntbutton.c $(HEADERS) gntcolors.o: gntcolors.c $(HEADERS) +gntentry.o: gntentry.c $(HEADERS) gntlabel.o: gntlabel.c $(HEADERS) gnttree.o: gnttree.c $(HEADERS) gntutils.o: gntutils.c $(HEADERS)
--- a/console/libgnt/gnt-skel.c Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/gnt-skel.c Fri Jun 23 06:24:25 2006 +0000 @@ -1,4 +1,4 @@ -#include "gn-skel.h" +#include "gnt-skel.h" enum { @@ -34,11 +34,17 @@ } static void +gnt_skel_destroy(GntWidget *widget) +{ +} + +static void gnt_skel_class_init(GntWidgetClass *klass) { GObjectClass *obj_class = G_OBJECT_CLASS(klass); parent_class = GNT_WIDGET_CLASS(klass); + parent_class->destroy = gnt_skel_destroy; parent_class->draw = gnt_skel_draw; parent_class->map = gnt_skel_map; parent_class->size_request = gnt_skel_size_request;
--- a/console/libgnt/gnt-skel.h Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/gnt-skel.h Fri Jun 23 06:24:25 2006 +0000 @@ -1,10 +1,10 @@ #ifndef GNT_SKEL_H #define GNT_SKEL_H -#include "gnwidget.h" -#include "gn.h" -#include "gncolors.h" -#include "gnkeys.h" +#include "gntwidget.h" +#include "gnt.h" +#include "gntcolors.h" +#include "gntkeys.h" #define GNT_TYPE_SKEL (gnt_skel_get_gtype()) #define GNT_SKEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_SKEL, GntSkel))
--- a/console/libgnt/gntbox.c Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/gntbox.c Fri Jun 23 06:24:25 2006 +0000 @@ -53,15 +53,13 @@ w = h = 0; max = -1; - curx = widget->priv.x + 1; - cury = widget->priv.y + 1; + curx = widget->priv.x; + cury = widget->priv.y; if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER)) { has_border = TRUE; - curx += box->pad; - cury += box->pad; - if (!box->vertical) - curx++; + curx += 1; + cury += 1; } for (iter = box->list; iter; iter = iter->next) @@ -84,7 +82,7 @@ if (has_border) { - curx += 2; + curx += 1; cury += 1; max += 2; } @@ -146,16 +144,44 @@ DEBUG; } +/* Ensures that the current widget can take focus */ +static void +ensure_active(GntBox *box) +{ + int investigated = 0; + int total; + + if (box->active == NULL) + box->active = box->list; + + total = g_list_length(box->list); + + while (box->active && !GNT_WIDGET_IS_FLAG_SET(box->active->data, GNT_WIDGET_CAN_TAKE_FOCUS)) + { + box->active = box->active->next; + investigated++; + } + + /* Rotate if necessary */ + if (!box->active && investigated < total) + { + box->active = box->list; + while (investigated < total && !GNT_WIDGET_IS_FLAG_SET(box->active->data, GNT_WIDGET_CAN_TAKE_FOCUS)) + { + box->active = box->active->next; + investigated++; + } + } +} + static gboolean gnt_box_key_pressed(GntWidget *widget, const char *text) { GntBox *box = GNT_BOX(widget); - /*if (box->list == NULL)*/ - /*return FALSE;*/ - + ensure_active(box); if (box->active == NULL) - box->active = box->list; + return FALSE; if (gnt_widget_key_pressed(box->active->data, text)) return TRUE;
--- a/console/libgnt/gntcolors.c Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/gntcolors.c Fri Jun 23 06:24:25 2006 +0000 @@ -19,6 +19,7 @@ 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); + init_pair(GNT_COLOR_TEXT_NORMAL, GNT_COLOR_BLACK, GNT_COLOR_GRAY); } else { @@ -26,6 +27,7 @@ init_pair(GNT_COLOR_HIGHLIGHT, COLOR_CYAN, COLOR_BLACK); init_pair(GNT_COLOR_SHADOW, COLOR_BLACK, COLOR_BLACK); init_pair(GNT_COLOR_TITLE, COLOR_WHITE, COLOR_BLACK); + init_pair(GNT_COLOR_TEXT_NORMAL, COLOR_BLACK, COLOR_WHITE); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntentry.c Fri Jun 23 06:24:25 2006 +0000 @@ -0,0 +1,251 @@ +#include <string.h> +#include "gntentry.h" + +enum +{ + SIGS = 1, +}; + +static GntWidgetClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; + +static void +gnt_entry_draw(GntWidget *widget) +{ + GntEntry *entry = GNT_ENTRY(widget); + int stop; + + wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TEXT_NORMAL)); + mvwprintw(widget->window, 0, 0, entry->scroll); + + stop = entry->end - entry->scroll; + if (stop < widget->priv.width) + mvwhline(widget->window, 0, stop, ENTRY_CHAR, widget->priv.width - stop); + + wrefresh(widget->window); + + DEBUG; +} + +static void +gnt_entry_size_request(GntWidget *widget) +{ + GntEntry *entry = GNT_ENTRY(widget); + widget->priv.height = 1; + widget->priv.width = 20; +} + +static void +gnt_entry_map(GntWidget *widget) +{ + if (widget->priv.width == 0 || widget->priv.height == 0) + gnt_widget_size_request(widget); + DEBUG; +} + +static gboolean +gnt_entry_key_pressed(GntWidget *widget, const char *text) +{ + GntEntry *entry = GNT_ENTRY(widget); + + if (text[0] == 27) + { + if (strcmp(text + 1, GNT_KEY_DEL) == 0 && entry->cursor < entry->end) + { + memmove(entry->cursor, entry->cursor + 1, entry->end - entry->cursor + 1); + entry->end--; + gnt_entry_draw(widget); + } + else if (strcmp(text + 1, GNT_KEY_LEFT) == 0 && entry->cursor > entry->start) + { + entry->cursor--; + if (entry->cursor < entry->scroll) + entry->scroll--; + gnt_entry_draw(widget); + } + else if (strcmp(text + 1, GNT_KEY_RIGHT) == 0 && entry->cursor < entry->end) + { + entry->cursor++; + if (entry->cursor - entry->scroll > widget->priv.width) + entry->scroll++; + gnt_entry_draw(widget); + } + /* XXX: handle other keys, like home/end, and ctrl+ goodness */ + } + else + { + if (!iscntrl(text[0])) + { + int i; + + for (i = 0; text[i]; i++) + { + /* Valid input? */ + if (ispunct(text[i]) && (entry->flag & GNT_ENTRY_FLAG_NO_PUNCT)) + continue; + if (isspace(text[i]) && (entry->flag & GNT_ENTRY_FLAG_NO_SPACE)) + continue; + if (isalpha(text[i]) && !(entry->flag & GNT_ENTRY_FLAG_ALPHA)) + continue; + if (isdigit(text[i]) && !(entry->flag & GNT_ENTRY_FLAG_INT)) + continue; + + /* Reached the max? */ + if (entry->max && entry->end - entry->start >= entry->max) + continue; + + if (entry->end - entry->start >= entry->buffer) + { + char *tmp = g_strdup_printf(entry->start); + gnt_entry_set_text(entry, tmp); + g_free(tmp); + } + + *(entry->cursor) = text[i]; + entry->cursor++; + + entry->end++; + if (entry->cursor - entry->scroll > widget->priv.width) + entry->scroll++; + } + gnt_entry_draw(widget); + } + else + { + /* Backspace is here */ + if (strcmp(text, GNT_KEY_BACKSPACE) == 0 && entry->cursor > entry->start) + { + entry->cursor--; + memmove(entry->cursor, entry->cursor + 1, entry->end - entry->cursor); + entry->end--; + + if (entry->scroll > entry->start) + entry->scroll--; + + gnt_entry_draw(widget); + } + } + } + + return FALSE; +} + +static void +gnt_entry_destroy(GntWidget *widget) +{ + GntEntry *entry = GNT_ENTRY(widget); + g_free(entry->start); +} + +static void +gnt_entry_class_init(GntWidgetClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = GNT_WIDGET_CLASS(klass); + parent_class->destroy = gnt_entry_destroy; + parent_class->draw = gnt_entry_draw; + parent_class->map = gnt_entry_map; + parent_class->size_request = gnt_entry_size_request; + parent_class->key_pressed = gnt_entry_key_pressed; + + DEBUG; +} + +static void +gnt_entry_init(GTypeInstance *instance, gpointer class) +{ + GntEntry *entry = GNT_ENTRY(instance); + + entry->flag = GNT_ENTRY_FLAG_ALL; + entry->max = 0; + + GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), + GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW | GNT_WIDGET_CAN_TAKE_FOCUS); + + DEBUG; +} + +/****************************************************************************** + * GntEntry API + *****************************************************************************/ +GType +gnt_entry_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntEntryClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_entry_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntEntry), + 0, /* n_preallocs */ + gnt_entry_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntEntry", + &info, 0); + } + + return type; +} + +GntWidget *gnt_entry_new(const char *text) +{ + GntWidget *widget = g_object_new(GNT_TYPE_ENTRY, NULL); + GntEntry *entry = GNT_ENTRY(widget); + + gnt_entry_set_text(entry, text); + + return widget; +} + +void gnt_entry_set_text(GntEntry *entry, const char *text) +{ + int len; + int scroll, cursor; + + g_free(entry->start); + + if (text && text[0]) + { + len = g_utf8_strlen(text, -1); + entry->buffer = len * 2; + } + else + { + entry->buffer = 128; + len = 0; + } + + scroll = entry->scroll - entry->start; + cursor = entry->end - entry->cursor; + + entry->start = g_new0(char, entry->buffer); + if (text) + snprintf(entry->start, len + 1, "%s", text); + entry->end = entry->start + len; + + entry->scroll = entry->start + scroll; + entry->cursor = entry->end - cursor; + + /* XXX: redraw if necessary? */ +} + +void gnt_entry_set_max(GntEntry *entry, int max) +{ + entry->max = max; +} + +void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag) +{ + entry->flag = flag; + /* XXX: Check the existing string to make sure the flags are respected? */ +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntentry.h Fri Jun 23 06:24:25 2006 +0000 @@ -0,0 +1,78 @@ +#ifndef GNT_ENTRY_H +#define GNT_ENTRY_H + +#include "gntwidget.h" +#include "gnt.h" +#include "gntcolors.h" +#include "gntkeys.h" + +#define GNT_TYPE_ENTRY (gnt_entry_get_gtype()) +#define GNT_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_ENTRY, GntEntry)) +#define GNT_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_ENTRY, GntEntryClass)) +#define GNT_IS_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_ENTRY)) +#define GNT_IS_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_ENTRY)) +#define GNT_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_ENTRY, GntEntryClass)) + +#define GNT_ENTRY_FLAGS(obj) (GNT_ENTRY(obj)->priv.flags) +#define GNT_ENTRY_SET_FLAGS(obj, flags) (GNT_ENTRY_FLAGS(obj) |= flags) +#define GNT_ENTRY_UNSET_FLAGS(obj, flags) (GNT_ENTRY_FLAGS(obj) &= ~(flags)) + +#define ENTRY_CHAR '_' /* The character to use to fill in the blank places */ + +typedef struct _GnEntry GntEntry; +typedef struct _GnEntryPriv GntEntryPriv; +typedef struct _GnEntryClass GntEntryClass; + +typedef enum +{ + GNT_ENTRY_FLAG_ALPHA = 1 << 0, /* Only alpha */ + GNT_ENTRY_FLAG_INT = 1 << 1, /* Only integer */ + GNT_ENTRY_FLAG_NO_SPACE = 1 << 2, /* No blank space is allowed */ + GNT_ENTRY_FLAG_NO_PUNCT = 1 << 3, /* No punctuations */ + GNT_ENTRY_FLAG_MASK = 1 << 4, /* Mask the inputs */ +} GntEntryFlag; + +#define GNT_ENTRY_FLAG_ALL (GNT_ENTRY_FLAG_ALPHA | GNT_ENTRY_FLAG_INT) + +struct _GnEntry +{ + GntWidget parent; + + GntEntryFlag flag; + + char *start; + char *end; + char *scroll; /* Current scrolling position */ + char *cursor; /* Cursor location */ + /* 0 <= cursor - scroll < widget-width */ + + size_t buffer; /* Size of the buffer */ + + int max; /* 0 means infinite */ +}; + +struct _GnEntryClass +{ + GntWidgetClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_entry_get_gtype(void); + +GntWidget *gnt_entry_new(const char *text); + +void gnt_entry_set_max(GntEntry *entry, int max); + +void gnt_entry_set_text(GntEntry *entry, const char *text); + +void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag); + +G_END_DECLS + +#endif /* GNT_ENTRY_H */
--- a/console/libgnt/gntkeys.h Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/gntkeys.h Fri Jun 23 06:24:25 2006 +0000 @@ -1,14 +1,17 @@ #ifndef GNT_KEYS_H #define GNT_KEYS_H -#define GNT_KEY_POPUP "[29~" +#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_LEFT "[D" +#define GNT_KEY_RIGHT "[C" +#define GNT_KEY_UP "[A" +#define GNT_KEY_DOWN "[B" -#define GNT_KEY_ENTER "\r" +#define GNT_KEY_ENTER "\r" + +#define GNT_KEY_BACKSPACE "\177" +#define GNT_KEY_DEL "[3~" #endif
--- a/console/libgnt/gnttree.c Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/gnttree.c Fri Jun 23 06:24:25 2006 +0000 @@ -46,11 +46,11 @@ if ((wr = snprintf(str, widget->priv.width, "%s", row->text)) >= widget->priv.width) { /* XXX: ellipsize */ - str[widget->priv.width - 1] = 0; + str[widget->priv.width - 1 - pos] = 0; } else { - while (wr < widget->priv.width - 1) + while (wr < widget->priv.width - 1 - pos) str[wr++] = ' '; str[wr] = 0; } @@ -67,8 +67,8 @@ while (start < tree->bottom) { - wmove(widget->window, start - tree->top + pos, pos); - wclrtoeol(widget->window); + mvwhline(widget->window, start - tree->top + pos, pos, ' ', + widget->priv.width - pos * 2); start++; }
--- a/console/libgnt/gntwidget.c Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/gntwidget.c Fri Jun 23 06:24:25 2006 +0000 @@ -286,6 +286,8 @@ gnt_widget_key_pressed(GntWidget *widget, const char *keys) { gboolean ret; + if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)) + return FALSE; g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret); return ret; }
--- a/console/libgnt/test.c Fri Jun 23 00:57:30 2006 +0000 +++ b/console/libgnt/test.c Fri Jun 23 06:24:25 2006 +0000 @@ -90,7 +90,9 @@ gnt_box_add_widget(GNT_BOX(vbox), widget2); gnt_box_add_widget(GNT_BOX(hbox), label); - gnt_box_add_widget(GNT_BOX(hbox), vbox); + /*gnt_box_add_widget(GNT_BOX(hbox), vbox);*/ + + gnt_box_add_widget(GNT_BOX(hbox), gnt_entry_new("a")); tree = gnt_tree_new(); gnt_box_add_widget(GNT_BOX(hbox), tree); @@ -106,11 +108,11 @@ /*gnt_widget_set_take_focus(vbox, TRUE);*/ /*gnt_widget_set_take_focus(hbox, TRUE);*/ - gnt_widget_set_position(hbox, 10, 10); + /*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(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);