diff options
-rw-r--r-- | filter/ChangeLog | 18 | ||||
-rw-r--r-- | filter/Makefile | 15 | ||||
-rw-r--r-- | filter/filter-arg-types.c | 103 | ||||
-rw-r--r-- | filter/filter-arg.c | 251 | ||||
-rw-r--r-- | filter/filter-arg.h | 8 | ||||
-rw-r--r-- | filter/filter-driver.c | 20 | ||||
-rw-r--r-- | filter/filter-druid.c | 848 | ||||
-rw-r--r-- | filter/filter-druid.h | 57 | ||||
-rw-r--r-- | filter/filter-format.c | 28 | ||||
-rw-r--r-- | filter/filter-xml.c | 66 | ||||
-rw-r--r-- | filter/filter-xml.h | 5 |
11 files changed, 1392 insertions, 27 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog index 3bc1fc7311..d7e51cb53d 100644 --- a/filter/ChangeLog +++ b/filter/ChangeLog @@ -1,3 +1,21 @@ +2000-02-22 NotZed <NotZed@HelixCode.com> + + * filter-xml.c (filter_clone_optionrule): + (filter_clone_optionrule_free): + (filter_optionrule_new_from_rule): New utility functions for + working with the internal rule format. + + * filter-arg.[ch]: Added new callbacks for editing a single value, + and a new editor which shows all items in a list, and allows you + to edit them via the single-edit method. This needs some cleanup + for some unused/unusable virtual methods (edit_values, + write_html?). + + * Makefile: Add the druid for build. + + * filter-druid.c: A 'druid' widget for editing a single filter + rule. + 2000-02-21 Matt Loper <matt@helixcode.com> * .cvsignore: New file. diff --git a/filter/Makefile b/filter/Makefile index 745574c108..04c6b33405 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -1,18 +1,22 @@ -OBJS = filter-arg-types.lo filter-arg.lo filter-xml.lo filter-driver.lo filter-format.lo -SRCS = filter-arg-types.c filter-arg.c filter-xml.c filter-driver.c filter-format.c +OBJS = filter-arg-types.lo filter-arg.lo filter-xml.lo filter-format.lo +SRCS = filter-arg-types.c filter-arg.c filter-xml.c filter-format.c LIBFILTEROBJS = filter-sexp.lo LIBFILTERSRCS = filter-sexp.c LIBTOOL=sh ../libtool +#CC=insure gcc CFLAGS = `gnome-config --cflags xml gnome gtk gtkhtml gnomeui` -g -I../camel -I .. -I../libibex LDFLAGS = `gnome-config --libs xml gnome gtk gtkhtml gnomeui` ../camel/libcamel.la -lpthread -all: libfilter.la filter-driver +all: libfilter.la filter-driver filter-druid -filter-driver: $(OBJS) libfilter.la +filter-druid: $(OBJS) filter-druid.lo libfilter.la + $(LIBTOOL) --mode link $(CC) $^ -o $@ $(LDFLAGS) + +filter-driver: $(OBJS) filter-driver.lo libfilter.la $(LIBTOOL) --mode link $(CC) $^ -o $@ $(LDFLAGS) libfilter.la: $(LIBFILTEROBJS) @@ -20,3 +24,6 @@ libfilter.la: $(LIBFILTEROBJS) %.lo: %.c $(LIBTOOL) --mode compile $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -rf *.o *.lo core .libs diff --git a/filter/filter-arg-types.c b/filter/filter-arg-types.c index ce6eac7003..ea58bf36ae 100644 --- a/filter/filter-arg-types.c +++ b/filter/filter-arg-types.c @@ -89,7 +89,51 @@ arg_string_write_text(FilterArg *argin, GString *string) static void arg_string_edit_values(FilterArg *arg) { - printf("edit string value!\n"); + printf("edit string values!\n"); +} + +/* pop up a dialogue, asking for a new string value */ +static int +arg_string_edit_value(FilterArg *arg, int index) +{ + GnomeDialog *dialogue; + GtkHBox *hbox; + GtkLabel *label; + GtkEntry *entry; + char *text = NULL; + char *newtext; + + dialogue = (GnomeDialog *)gnome_dialog_new("Edit value", "Ok", "Cancel", 0); + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 0); + label = (GtkLabel *)gtk_label_new("Folder name"); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)label, FALSE, FALSE, 0); + entry = (GtkEntry *)gtk_entry_new(); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)entry, TRUE, TRUE, 0); + if (index>=0) { + text = filter_arg_get_value(arg, index); + } + if (text) { + gtk_entry_set_text(entry, text); + } + gtk_box_pack_start((GtkBox *)dialogue->vbox, (GtkWidget *)hbox, TRUE, TRUE, 0); + gtk_widget_show_all((GtkWidget *)hbox); + gtk_object_ref((GtkObject *)entry); /* so we can get the text back afterwards */ + if (gnome_dialog_run_and_close(dialogue) == 0) { + GList *node; + + newtext = g_strdup(gtk_entry_get_text(entry)); + gtk_object_unref((GtkObject *)entry); + if (index>=0 + && (node = g_list_find(arg->values, text))) { + node->data = newtext; + } else { + arg->values = g_list_append(arg->values, newtext); + } + g_free(text); + return g_list_index(arg->values, newtext); + } + return -1; } static xmlNodePtr @@ -161,7 +205,9 @@ filter_arg_string_class_init (FilterArgStringClass *class) class->parent_class.write_html = arg_string_write_html; class->parent_class.write_text = arg_string_write_text; class->parent_class.edit_values = arg_string_edit_values; + class->parent_class.edit_value = arg_string_edit_value; class->parent_class.free_value = arg_string_free_value; + class->parent_class.get_value_as_string = arg_string_get_value_as_string; class->parent_class.values_get_xml = arg_string_values_get_xml; class->parent_class.values_add_xml = arg_string_values_add_xml; @@ -267,6 +313,54 @@ arg_address_edit_values(FilterArg *arg) printf("edit it!\n"); } +static int +arg_address_edit_value(FilterArg *arg, int index) +{ + GnomeDialog *dialogue; + GtkHBox *hbox; + GtkLabel *label; + GtkEntry *entry; + char *text = NULL; + char *newtext; + struct filter_arg_address *ad; + + dialogue = (GnomeDialog *)gnome_dialog_new("Edit value", "Ok", "Cancel", 0); + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 0); + label = (GtkLabel *)gtk_label_new("Folder name"); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)label, FALSE, FALSE, 0); + entry = (GtkEntry *)gtk_entry_new(); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)entry, TRUE, TRUE, 0); + if (index>=0 + && (ad = filter_arg_get_value(arg, index))) { + text = ad->email; + } + if (text) { + gtk_entry_set_text(entry, text); + } + gtk_box_pack_start((GtkBox *)dialogue->vbox, (GtkWidget *)hbox, TRUE, TRUE, 0); + gtk_widget_show_all((GtkWidget *)hbox); + gtk_object_ref((GtkObject *)entry); /* so we can get the text back afterwards */ + if (gnome_dialog_run_and_close(dialogue) == 0) { + GList *node; + + newtext = g_strdup(gtk_entry_get_text(entry)); + gtk_object_unref((GtkObject *)entry); + if (index>=0 + && (node = g_list_find(arg->values, text))) { + ad = node->data; + ad->email = newtext; + } else { + ad = g_malloc0(sizeof(*ad)); + ad->email = newtext; + arg->values = g_list_append(arg->values, ad); + } + g_free(text); + return g_list_index(arg->values, ad); + } + return -1; +} + static xmlNodePtr arg_address_values_get_xml(FilterArg *argin) { @@ -319,6 +413,8 @@ arg_address_get_value_as_string(FilterArg *argin, void *data) FilterArgAddress *arg = (FilterArgAddress *)argin; struct filter_arg_address *a = (struct filter_arg_address *)data; + printf("geting address as string : %s %s\n", a->email, a->name); + if (a->email == NULL || a->email[0] == '\0') { if (a->name == NULL @@ -348,7 +444,8 @@ filter_arg_address_class_init (FilterArgAddressClass *class) class->parent_class.write_html = arg_address_write_html; class->parent_class.write_text = arg_address_write_text; - class->parent_class.edit_values = arg_address_edit_values; + class->parent_class.edit_values= arg_address_edit_values; + class->parent_class.edit_value= arg_address_edit_value; class->parent_class.free_value = arg_address_free_value; class->parent_class.values_get_xml = arg_address_values_get_xml; @@ -470,7 +567,7 @@ arg_folder_edit_values(FilterArg *argin) dialogue = gnome_dialog_new("Edit addresses", "Ok", "Cancel", NULL); text = gtk_text_new(NULL, NULL); - gtk_object_ref(text); + gtk_object_ref((GtkObject *)text); l = argin->values; while (l) { diff --git a/filter/filter-arg.c b/filter/filter-arg.c index 55bc09c6a0..1d8affaadc 100644 --- a/filter/filter-arg.c +++ b/filter/filter-arg.c @@ -20,6 +20,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <gtk/gtk.h> +#include <gnome.h> + #include "filter-arg.h" @@ -57,6 +60,21 @@ filter_arg_get_type (void) return type; } +static FilterArg * +clone_default(FilterArg *a) +{ + xmlNodePtr values; + FilterArg *new = FILTER_ARG ( gtk_type_new (((GtkObject *)a)->klass->type) ); + + /* clone values */ + new->name = g_strdup(a->name); + values = filter_arg_values_get_xml(a); + filter_arg_values_add_xml(new, values); + xmlFreeNodeList(values); + + return new; +} + static void write_html_nothing(FilterArg *arg, GtkHTML *html, GtkHTMLStreamHandle *stream) { @@ -75,6 +93,12 @@ edit_values_nothing(FilterArg *arg) /* empty */ } +static void * +edit_value_nothing(FilterArg *arg, void *v) +{ + return v; +} + static void free_value_nothing(FilterArg *arg, void *v) { @@ -98,7 +122,9 @@ filter_arg_class_init (FilterArgClass *class) class->write_html = write_html_nothing; class->write_text = write_text_nothing; class->edit_values = edit_values_nothing; + class->edit_value = edit_value_nothing; class->free_value = free_value_nothing; + class->clone = clone_default; signals[CHANGED] = gtk_signal_new ("changed", @@ -132,6 +158,12 @@ filter_arg_new (char *name) return a; } +FilterArg * +filter_arg_clone (FilterArg *arg) +{ + return ((FilterArgClass *)(arg->object.klass))->clone(arg); +} + void filter_arg_add(FilterArg *arg, void *v) { @@ -157,17 +189,46 @@ filter_arg_write_html(FilterArg *arg, GtkHTML *html, GtkHTMLStreamHandle *stream void filter_arg_write_text(FilterArg *arg, GString *string) { + int count, i; + + count = filter_arg_get_count(arg); + for (i=0;i<count;i++) { + g_string_append(string, filter_arg_get_value_as_string(arg, i)); + if (i<count-1) { + g_string_append(string, ", "); + } + if (i==count-2 && count>1) { + g_string_append(string, "or "); + } + } + +#if 0 ((FilterArgClass *)(arg->object.klass))->write_text(arg, string); +#endif } void filter_arg_edit_values(FilterArg *arg) { + void filter_arg_edit_values_1(FilterArg *arg); + g_return_if_fail(arg != NULL); + +#if 1 + filter_arg_edit_values_1(arg); +#else + if (((FilterArgClass *)(arg->object.klass))->edit_values) ((FilterArgClass *)(arg->object.klass))->edit_values(arg); else g_warning("No implementation of virtual method edit_values"); +#endif +} + +int +filter_arg_edit_value(FilterArg *arg, int index) +{ + ((FilterArgClass *)(arg->object.klass))->edit_value(arg, index); } xmlNodePtr @@ -222,3 +283,193 @@ filter_arg_get_value_as_string(FilterArg *arg, int index) } +struct filter_arg_edit { + FilterArg *arg; + GtkList *list; + GList *items; + GnomeDialog *dialogue; + GtkWidget *add, *remove, *edit; + GtkWidget *item_current; +}; + +static void +filter_arg_edit_add(GtkWidget *w, struct filter_arg_edit *edata) +{ + GtkListItem *listitem; + GList *items = NULL; + int i; + + printf("adding new item\n"); + + i = filter_arg_edit_value(edata->arg, -1); + if (i>=0) { + gtk_list_remove_items_no_unref(edata->list, edata->items); + listitem = (GtkListItem *)gtk_list_item_new_with_label(filter_arg_get_value_as_string(edata->arg, i)); + gtk_object_set_data((GtkObject *)listitem, "arg_i", filter_arg_get_value(edata->arg, i)); + edata->items = g_list_append(edata->items, listitem); + gtk_widget_show((GtkWidget *)listitem); + + /* this api is nonsense */ + gtk_list_append_items(edata->list, g_list_copy(edata->items)); + } +} + +void dump_list(GList *list) +{ + printf("dumping list:\n"); + for (;list;list = g_list_next(list)) { + printf(" %p %p\n", list, list->data); + } +} + +static void +fill_list(struct filter_arg_edit *edata) +{ + GList *items = NULL; + int i, count; + GtkListItem *listitem; + + gtk_list_remove_items(edata->list, edata->items); + g_list_free(edata->items); + + count = filter_arg_get_count(edata->arg); + for (i=0;i<count;i++) { + char *labeltext; + labeltext = filter_arg_get_value_as_string(edata->arg, i); + listitem = (GtkListItem *)gtk_list_item_new_with_label(labeltext); + gtk_object_set_data((GtkObject *)listitem, "arg_i", filter_arg_get_value(edata->arg, i)); + items = g_list_append(items, listitem); + gtk_widget_show(GTK_WIDGET(listitem)); + printf("adding item %d\n", i); + } + + printf("items re-added\n"); + + edata->item_current = NULL; + edata->items = items; + + gtk_list_append_items(edata->list, g_list_copy(edata->items)); +} + +static void +filter_arg_edit_edit(GtkWidget *w, struct filter_arg_edit *edata) +{ + char *name; + int i; + + /* yurck */ + if (edata->item_current + && (name = gtk_object_get_data((GtkObject *)edata->item_current, "arg_i")) + && (i = g_list_index(edata->arg->values, name)) >= 0 + && (i = filter_arg_edit_value(edata->arg, i)) >= 0) { + + fill_list(edata); + } +} + +static void +filter_arg_edit_delete(GtkWidget *w, struct filter_arg_edit *edata) +{ + GtkListItem *listitem; + char *name; + + /* yurck */ + if (edata->item_current + && (name = gtk_object_get_data((GtkObject *)edata->item_current, "arg_i"))) { + filter_arg_remove(edata->arg, name); + fill_list(edata); + } +} + +static void +edit_sensitise(struct filter_arg_edit *edata) +{ + int state = edata->item_current != NULL; + gtk_widget_set_sensitive(edata->remove, state); + gtk_widget_set_sensitive(edata->edit, state); +} + +static void +filter_arg_edit_select(GtkWidget *w, GtkListItem *list, struct filter_arg_edit *edata) +{ + edata->item_current = list; + edit_sensitise(edata); + + printf ("node = %p\n", g_list_find(edata->items, edata->item_current)); +} + +static void +filter_arg_edit_unselect(GtkWidget *w, GtkListItem *list, struct filter_arg_edit *edata) +{ + edata->item_current = NULL; + edit_sensitise(edata); +} + +void +filter_arg_edit_values_1(FilterArg *arg) +{ + GList *vales; + GtkList *list; + GtkListItem *listitem; + int count, i; + GnomeDialog *dialogue; + GtkHBox *hbox; + GtkVBox *vbox; + GtkWidget *button; + GtkWidget *scrolled_window, *frame; + struct filter_arg_edit edata; + + edata.item_current = NULL; + edata.arg = arg; + + dialogue = (GnomeDialog *)gnome_dialog_new("Edit values", "Ok", "Cancel", 0); + edata.dialogue = dialogue; + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 0); + + list = (GtkList *)gtk_list_new(); + edata.list = list; + edata.items = NULL; + fill_list(&edata); + + scrolled_window = gtk_scrolled_window_new(NULL, NULL); + frame = gtk_frame_new("Option values"); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), (GtkWidget *)list); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_container_set_focus_vadjustment(GTK_CONTAINER (list), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window))); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_widget_set_usize(frame, 200, 300); + gtk_box_pack_start((GtkBox *)hbox, frame, TRUE, TRUE, 0); + + /* buttons */ + vbox = (GtkVBox *)gtk_vbox_new(FALSE, 0); + + button = gtk_button_new_with_label ("Add"); + gtk_box_pack_start((GtkBox *)vbox, button, FALSE, TRUE, 0); + edata.add = button; + button = gtk_button_new_with_label ("Remove"); + gtk_box_pack_start((GtkBox *)vbox, button, FALSE, TRUE, 0); + edata.remove = button; + button = gtk_button_new_with_label ("Edit"); + gtk_box_pack_start((GtkBox *)vbox, button, FALSE, TRUE, 0); + edata.edit = button; + + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)vbox, FALSE, FALSE, 0); + + gtk_signal_connect((GtkObject *)edata.add, "clicked", filter_arg_edit_add, &edata); + gtk_signal_connect((GtkObject *)edata.edit, "clicked", filter_arg_edit_edit, &edata); + gtk_signal_connect((GtkObject *)edata.remove, "clicked", filter_arg_edit_delete, &edata); + gtk_signal_connect((GtkObject *)edata.list, "select_child", filter_arg_edit_select, &edata); + gtk_signal_connect((GtkObject *)edata.list, "unselect_child", filter_arg_edit_unselect, &edata); + + gtk_widget_show(GTK_WIDGET(list)); + gtk_widget_show_all(GTK_WIDGET(hbox)); + gtk_box_pack_start((GtkBox *)dialogue->vbox, (GtkWidget *)hbox, TRUE, TRUE, 0); + + edit_sensitise(&edata); + + gnome_dialog_run_and_close(dialogue); +} + + diff --git a/filter/filter-arg.h b/filter/filter-arg.h index 95e7d1caea..bf9448a17a 100644 --- a/filter/filter-arg.h +++ b/filter/filter-arg.h @@ -44,11 +44,16 @@ struct _FilterArg { struct _FilterArgClass { GtkObjectClass parent_class; + /* make a copy of yourself */ + struct _FilterArg * (*clone)(FilterArg *arg); + /* virtual methods */ void (*write_html)(FilterArg *arg, GtkHTML *html, GtkHTMLStreamHandle *stream); void (*write_text)(FilterArg *arg, GString *string); void (*free_value)(FilterArg *arg, void *v); + void (*edit_values)(FilterArg *arg); + int (*edit_value)(FilterArg *arg, int index); void (*values_add_xml)(FilterArg *arg, xmlNodePtr node); xmlNodePtr (*values_get_xml)(FilterArg *arg); @@ -61,9 +66,11 @@ struct _FilterArgClass { guint filter_arg_get_type (void); FilterArg *filter_arg_new (char *name); +FilterArg *filter_arg_clone(FilterArg *arg); void filter_arg_value_add(FilterArg *a, void *v); void filter_arg_edit_values(FilterArg *arg); +int filter_arg_edit_value(FilterArg *arg, int index); xmlNodePtr filter_arg_values_get_xml(FilterArg *arg); void filter_arg_values_add_xml(FilterArg *arg, xmlNodePtr node); @@ -72,3 +79,4 @@ void *filter_arg_get_value(FilterArg *arg, int index); char *filter_arg_get_value_as_string(FilterArg *arg, int index); #endif /* ! _FILTER_ARG_H */ + diff --git a/filter/filter-driver.c b/filter/filter-driver.c index b51e3f0705..c2759fe9d8 100644 --- a/filter/filter-driver.c +++ b/filter/filter-driver.c @@ -138,6 +138,8 @@ find_optionrule(struct filter_option *option, char *name) return NULL; } +static char nooption[] = "<h1>Select option</h1><p>Select an option type from the list above.</p>"; + void html_write_options(GtkHTML *html, struct filter_option *option) { @@ -146,13 +148,17 @@ html_write_options(GtkHTML *html, struct filter_option *option) stream = gtk_html_begin(html, ""); gtk_html_write(html, stream, "<body bgcolor=white alink=blue>", strlen("<body bgcolor=white alink=blue>")); - optionrulel = option->options; - while (optionrulel) { - struct filter_optionrule *or = optionrulel->data; - - filter_description_html_write(or->rule->description, or->args, html, stream); - gtk_html_write(html, stream, "<br>", strlen("<br>")); - optionrulel = g_list_next(optionrulel); + if (option) { + optionrulel = option->options; + while (optionrulel) { + struct filter_optionrule *or = optionrulel->data; + + filter_description_html_write(or->rule->description, or->args, html, stream); + gtk_html_write(html, stream, "<br>", strlen("<br>")); + optionrulel = g_list_next(optionrulel); + } + } else { + gtk_html_write(html, stream, nooption, strlen(nooption)); } gtk_html_end(html, stream, GTK_HTML_STREAM_OK); } diff --git a/filter/filter-druid.c b/filter/filter-druid.c new file mode 100644 index 0000000000..16efdf8319 --- /dev/null +++ b/filter/filter-druid.c @@ -0,0 +1,848 @@ +/* + * Copyright (C) 2000 Helix Code Inc. + * + * Authors: Michael Zucchi <notzed@helixcode.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <glib.h> +#include <gtk/gtk.h> +#include <gnome.h> +#include <gtkhtml/gtkhtml.h> +#include <string.h> + +#include <gnome-xml/tree.h> +#include <gnome-xml/parser.h> + +#include "filter-arg-types.h" +#include "filter-xml.h" +#include "filter-sexp.h" +#include "filter-format.h" + + +#include "filter-druid.h" + +static void filter_druid_class_init (FilterDruidClass *klass); +static void filter_druid_init (FilterDruid *obj); + +#define _PRIVATE(x) (((FilterDruid *)(x))->priv) + +struct _FilterDruidPrivate { + GtkWidget *notebook; + int page; + + /* page 0 */ + GtkWidget *list0; + GtkWidget *html0; + GtkWidget *add0, *remove0, *up0, *down0; + GList *items0; + GtkFrame *listframe0; + + /* page 1 */ + GtkWidget *name1; + GtkWidget *activate1; + GtkHTML *html1; +}; + +/* forward ref's */ +static void build_druid(FilterDruid *d); +static void update_display(FilterDruid *f, int initial); + +/* globals */ +static GnomeDialogClass *filter_druid_parent; + +enum SIGNALS { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_druid_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterDruid", + sizeof (FilterDruid), + sizeof (FilterDruidClass), + (GtkClassInitFunc) filter_druid_class_init, + (GtkObjectInitFunc) filter_druid_init, + (GtkArgSetFunc) NULL, + (GtkArgGetFunc) NULL + }; + + type = gtk_type_unique (gnome_dialog_get_type (), &type_info); + } + + return type; +} + +static void +filter_druid_class_init (FilterDruidClass *klass) +{ + GtkObjectClass *object_class = (GtkObjectClass *) klass; + + filter_druid_parent = gtk_type_class (gnome_dialog_get_type ()); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +filter_druid_init (FilterDruid *obj) +{ + struct _FilterDruidPrivate *priv; + + obj->priv = g_malloc0(sizeof(*obj->priv)); + priv = _PRIVATE(obj); +} + +/** + * filter_druid_new: + * + * Create a new FilterDruid object. + * + * Return value: A new FilterDruid widget. + **/ +FilterDruid * +filter_druid_new (void) +{ + FilterDruid *new = FILTER_DRUID ( gtk_type_new (filter_druid_get_type ())); + + build_druid(new); + + return new; +} + + +extern int filter_find_arg(FilterArg *a, char *name); + +#include "check.xpm" +#include "blank.xpm" + + +struct filter_optionrule * +find_optionrule(struct filter_option *option, char *name) +{ + GList *optionrulel; + struct filter_optionrule *or; + + optionrulel = option->options; + while (optionrulel) { + or = optionrulel->data; + if (!strcmp(or->rule->name, name)) { + return or; + } + optionrulel = g_list_next(optionrulel); + } + return NULL; +} + +static char nooption[] = "<h2>Select option</h2><p>Select an option type from the list above.</p>" +"<p>This will set the basic rule options for your new filtering rule.</p>"; +static int display_order[] = { + FILTER_XML_MATCH, + FILTER_XML_EXCEPT, + FILTER_XML_ACTION, +}; +static char *display_pretext[] = { + "<b>For messages matching:</b><br><ul>", + "<b>Unless:</b><br><ul>", + "<b>Perform these actions:</b><br><ul>", +}; +static char *display_posttext[] = { + "</ul>", + "</ul>", + "</ul>", +}; + +void +html_write_options(GtkHTML *html, struct filter_option *option) +{ + GtkHTMLStreamHandle *stream; + GList *optionrulel; + int i; + + stream = gtk_html_begin(html, ""); + gtk_html_write(html, stream, "<body bgcolor=white alink=blue>", strlen("<body bgcolor=white alink=blue>")); + if (option) { + char *t; + + if (option->type == FILTER_XML_SEND) { + t = "<p>When a message is <i>sent</i>.</p>"; + } else { + t = "<p>When a message is <i>received</i>.</p>"; + } + gtk_html_write(html, stream, t, strlen(t)); + + for (i=0;i<sizeof(display_order)/sizeof(display_order[0]);i++) { + int doneheader = FALSE; + optionrulel = option->options; + while (optionrulel) { + struct filter_optionrule *or = optionrulel->data; + + if (or->rule->type == display_order[i]) { + if (!doneheader) { + gtk_html_write(html, stream, display_pretext[i], strlen(display_pretext[i])); + doneheader = TRUE; + } + + filter_description_html_write(or->rule->description, or->args, html, stream); + gtk_html_write(html, stream, "<br>", strlen("<br>")); + } + optionrulel = g_list_next(optionrulel); + } + if (doneheader) { + gtk_html_write(html, stream, display_posttext[i], strlen(display_posttext[i])); + } + } + } else { + gtk_html_write(html, stream, nooption, strlen(nooption)); + } + gtk_html_end(html, stream, GTK_HTML_STREAM_OK); +} + +GList * +fill_rules(GList *rules, struct filter_option *option, int type) +{ + GList *optionl, *rulel; + GtkWidget *listitem, *hbox, *checkbox, *label; + GList *items = NULL; + + rulel = rules; + while (rulel) { + struct filter_rule *fr = rulel->data; + char *labeltext; + + if (fr->type == type) { + int state; + + state = find_optionrule(option, fr->name) != NULL; + + labeltext = filter_description_text(fr->description, NULL); + + printf("adding rule %s\n", labeltext); + + hbox = gtk_hbox_new(FALSE, 3); + checkbox = gnome_pixmap_new_from_xpm_d(state?check_xpm:blank_xpm); + gtk_box_pack_start(GTK_BOX(hbox), checkbox, FALSE, FALSE, 0); + label = gtk_label_new(labeltext); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0); + listitem = gtk_list_item_new(); + gtk_container_add(GTK_CONTAINER(listitem), hbox); + gtk_widget_show_all(listitem); + + gtk_object_set_data(GTK_OBJECT(listitem), "checkbox", checkbox); + gtk_object_set_data(GTK_OBJECT(listitem), "checkstate", (void *)state); + gtk_object_set_data(GTK_OBJECT(listitem), "rule", fr); + + items = g_list_append(items, listitem); + } + rulel = g_list_next(rulel); + } + return items; +} + +GList * +fill_options(GList *options) +{ + GList *optionl, *rulel, *optionrulel; + GtkWidget *listitem, *hbox, *checkbox, *label; + GList *items = NULL; + + optionl = options; + while (optionl) { + struct filter_option *op = optionl->data; + char *labeltext; + + labeltext = filter_description_text(op->description, NULL); + listitem = gtk_list_item_new_with_label(labeltext); + g_free(labeltext); + gtk_widget_show_all(listitem); + + gtk_object_set_data(GTK_OBJECT(listitem), "option", op); + + items = g_list_append(items, listitem); + optionl = g_list_next(optionl); + } + return items; +} + +GtkWidget *list_global, *html_global; +struct filter_option *option_current; + +static void +select_rule_child(GtkList *list, GtkWidget *child, FilterDruid *f) +{ + GtkWidget *w; + struct filter_rule *fr = gtk_object_get_data(GTK_OBJECT(child), "rule"); + int state; + struct filter_optionrule *rule; + struct _FilterDruidPrivate *p = _PRIVATE(f); + + w = gtk_object_get_data(GTK_OBJECT(child), "checkbox"); + state = !(int) gtk_object_get_data(GTK_OBJECT(child), "checkstate"); + + gnome_pixmap_load_xpm_d(GNOME_PIXMAP(w), state?check_xpm:blank_xpm); + gtk_object_set_data(GTK_OBJECT(child), "checkstate", (void *)state); + + if (state) { + printf("adding rule %p\n", fr); + rule = filter_optionrule_new_from_rule(fr); + f->option_current->options = g_list_append(f->option_current->options, rule); + } else { + rule = find_optionrule(f->option_current, fr->name); + if (rule) { + f->option_current->options = g_list_remove(f->option_current->options, rule); + filter_clone_optionrule_free(rule); + } + } + + update_display(f, 0); +} + + + +static void +select_option_child(GtkList *list, GtkWidget *child, FilterDruid *f) +{ + struct filter_option *op; + struct filter_option *new; + GList *optionsl; + struct _FilterDruidPrivate *p = _PRIVATE(f); + + switch (p->page) { + case 1: + case 2: + case 3: + select_rule_child(list, child, f); + default: + return; + case 0: + break; + } + + if (f->option_current) { + /* free option_current copy */ + optionsl = f->option_current->options; + while (optionsl) { + GList *op = optionsl; + optionsl = g_list_next(optionsl); + g_free(op->data); + } + g_list_free(f->option_current->options); + g_free(f->option_current); + f->option_current = NULL; + } + + if (child) { + op = gtk_object_get_data(GTK_OBJECT(child), "option"); + + /* clone the option */ + new = g_malloc(sizeof(*new)); + new->type = op->type; + new->description = op->description; + new->options = NULL; + optionsl = op->options; + while (optionsl) { + struct filter_optionrule *ornew, + *or = optionsl->data; + ornew = filter_clone_optionrule(or); + new->options = g_list_append(new->options, ornew); + optionsl = g_list_next(optionsl); + } + f->option_current = new; + } + + update_display(f, 0); +} + +static void +unselect_option_child(GtkList *list, GtkWidget *child, FilterDruid *f) +{ + select_option_child(list, NULL, f); +} + +static void +arg_link_clicked(GtkHTML *html, const char *url, FilterDruid *f) +{ + printf("url clicked: %s\n", url); + if (!strncmp(url, "arg:", 4)) { + FilterArg *arg; + void *dummy; + + if (sscanf(url+4, "%p %p", &dummy, &arg)==2 + && arg) { + printf("arg = %p\n", arg); + filter_arg_edit_values(arg); + /* should have a changed signal which propagates the rewrite */ + update_display(f, 0); + } + } +} + +static void +dialogue_clicked(FilterDruid *d, int button, void *data) +{ + GString *s = g_string_new(""); + struct _FilterDruidPrivate *p = _PRIVATE(d); + int initial=0; + + printf("button %d clicked ...\n", button); + + g_string_free(s, TRUE); + + switch(button) { + case 1: + if (p->page<4) { + p->page++; + initial =1; + } + break; + case 0: + if (p->page>0) { + p->page--; + initial = 1; + } + break; + } + update_display(d, initial); +} + +static int filter_types[] = { FILTER_XML_MATCH, FILTER_XML_EXCEPT, FILTER_XML_ACTION }; +static char *filter_titles[] = { + "Select rule(s), where messages match", + "Select rule(s), where messages do not match", + "Select action(s) to apply to messages" + +}; +static void +update_display(FilterDruid *f, int initial) +{ + struct _FilterDruidPrivate *p = _PRIVATE(f); + + printf("rending page %d options\n", p->page); + + switch (p->page) { + case 0: + printf("option_current = %p <###################\n", f->option_current); + gnome_dialog_set_sensitive((GnomeDialog *)f, 0, FALSE); + gnome_dialog_set_sensitive((GnomeDialog *)f, 1, f->option_current != NULL); + + if (initial) { + printf("adding options\n"); + gtk_signal_handler_block_by_data((GtkObject *)p->list0, f); + gtk_list_remove_items((GtkList *)p->list0, p->items0); + p->items0 = fill_options(f->options); + gtk_list_append_items((GtkList *)p->list0, p->items0); + gtk_signal_handler_unblock_by_data((GtkObject *)p->list0, f); + gtk_frame_set_label(p->listframe0, "Select rule type"); + } + + html_write_options((GtkHTML *)p->html0, f->option_current); + break; + case 1: + case 2: + case 3: + gnome_dialog_set_sensitive((GnomeDialog *)f, 1, TRUE); + gnome_dialog_set_sensitive((GnomeDialog *)f, 0, TRUE); + gnome_dialog_set_sensitive((GnomeDialog *)f, 2, FALSE); + + if (initial) { + printf("adding rules\n"); + gtk_signal_handler_block_by_data((GtkObject *)p->list0, f); + gtk_list_remove_items((GtkList *)p->list0, p->items0); + p->items0 = fill_rules(f->rules, f->option_current, filter_types[p->page-1]); + gtk_list_append_items((GtkList *)p->list0, p->items0); + gtk_signal_handler_unblock_by_data((GtkObject *)p->list0, f); + gtk_frame_set_label(p->listframe0, filter_titles[p->page-1]); + gtk_notebook_set_page(GTK_NOTEBOOK(p->notebook), 0); + } + + html_write_options((GtkHTML *)p->html0, f->option_current); + break; + case 4: + gnome_dialog_set_sensitive((GnomeDialog *)f, 1, FALSE); + gnome_dialog_set_sensitive((GnomeDialog *)f, 0, TRUE); + gnome_dialog_set_sensitive((GnomeDialog *)f, 2, TRUE); + + if (initial) { + char *text; + text = filter_description_text(f->option_current->description, NULL); + if (text == NULL) { + /* maybe this could fudge something out of the first + bits of the rule */ + if (f->option_current->type == FILTER_XML_SEND) { + text = "Filter messages sent"; + } else { + text = " Filter messages received"; + } + gtk_entry_set_text(GTK_ENTRY(p->name1), text); + } else { + gtk_entry_set_text(GTK_ENTRY(p->name1), text); + g_free(text); + } + gtk_notebook_set_page(GTK_NOTEBOOK(p->notebook), 1); + } + + html_write_options((GtkHTML *)p->html1, f->option_current); + break; + + } +} + +void +filter_druid_set_rules(FilterDruid *f, GList *options, GList *rules, struct filter_option *current) +{ + f->options = options; + f->rules = rules; + f->user = NULL; + + /* FIXME: free this list if it isn't empty ... */ + f->option_current = current; + + update_display(f, 1); +} + +static void +build_druid(FilterDruid *d) +{ + GtkWidget *vbox, *frame, *scrolled_window, *list, *html, *hbox, *label, *vbox1; + struct _FilterDruidPrivate *p = _PRIVATE(d); + + gnome_dialog_append_buttons((GnomeDialog *)d, "Prev", "Next", "Finish", "Cancel", 0); + gnome_dialog_set_close((GnomeDialog *)d, FALSE); + gnome_dialog_set_sensitive((GnomeDialog *)d, 0, FALSE); + gnome_dialog_set_sensitive((GnomeDialog *)d, 1, FALSE); + gnome_dialog_set_sensitive((GnomeDialog *)d, 2, FALSE); + gnome_dialog_set_default((GnomeDialog *)d, 1); + + p->notebook = gtk_notebook_new(); + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(p->notebook), FALSE); + + /* page0, initial setup page */ + vbox = gtk_vbox_new(FALSE, 3); + frame = gtk_frame_new("Filters"); + p->listframe0 = (GtkFrame *)frame; + + list = gtk_list_new(); + scrolled_window = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_set_usize(scrolled_window, 400, 150); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_set_focus_vadjustment + (GTK_CONTAINER (list), + gtk_scrolled_window_get_vadjustment + (GTK_SCROLLED_WINDOW (scrolled_window))); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); + + frame = gtk_frame_new("Filter Description (click on values to edit)"); + html = gtk_html_new(); + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_set_usize(scrolled_window, 400, 150); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(scrolled_window), html); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); + + p->html0 = html; + p->list0 = list; + + gtk_signal_connect(GTK_OBJECT(list), "select_child", select_option_child, d); + gtk_signal_connect(GTK_OBJECT(list), "unselect_child", select_option_child, d); +/* gtk_signal_connect(GTK_OBJECT(list), "unselect_child", unselect_option_child, d); */ + gtk_signal_connect(GTK_OBJECT(d), "clicked", dialogue_clicked, d); + + gtk_signal_connect(GTK_OBJECT(html), "link_clicked", arg_link_clicked, d); + + gtk_notebook_append_page(GTK_NOTEBOOK(p->notebook), vbox, NULL); + + + /* page1, used for the final page display */ + vbox = gtk_vbox_new(FALSE, 3); + + frame = gtk_frame_new("Rule options"); + vbox1 = gtk_vbox_new(FALSE, 3); + + hbox = gtk_hbox_new(FALSE, 3); + label = gtk_label_new("Name of rule"); + p->name1 = gtk_entry_new(); + gtk_box_pack_start((GtkBox *)hbox, label, FALSE, FALSE, 0); + gtk_box_pack_start((GtkBox *)hbox, p->name1, TRUE, TRUE, 0); + gtk_box_pack_start((GtkBox *)vbox1, hbox, TRUE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(frame), vbox1); + + p->activate1 = gtk_check_button_new_with_label("Activate rule?"); + gtk_box_pack_start((GtkBox *)vbox1, p->activate1, TRUE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->activate1), TRUE); + + gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); + + /* another copy of the filter thingy */ + frame = gtk_frame_new("Filter Description (click on values to edit)"); + html = gtk_html_new(); + p->html1 = (GtkHTML *)html; + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_set_usize(scrolled_window, 400, 150); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(scrolled_window), html); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); + + /* finish off */ + gtk_notebook_append_page(GTK_NOTEBOOK(p->notebook), vbox, NULL); + + gtk_signal_connect(GTK_OBJECT(html), "link_clicked", arg_link_clicked, d); + + gtk_widget_show_all(p->notebook); + + gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(d)->vbox), p->notebook, TRUE, TRUE, 0); +} + +#if 0 +/* crappo */ +static void +build_first(FilterDruid *d) +{ + GtkWidget *vbox, *frame, *scrolled_window, *list, *html, *hbox; + struct _FilterDruidPrivate *p = _PRIVATE(d); + + gnome_dialog_append_buttons((GnomeDialog *)d, "Prev", "Next", "Finish", "Cancel", 0); + gnome_dialog_set_close((GnomeDialog *)d, FALSE); + + p->notebook = gtk_notebook_new(); + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(p->notebook), FALSE); + + /* page0, initial setup page */ + hbox = gtk_hbox_new(FALSE, 0); + + vbox = gtk_vbox_new(FALSE, 0); + frame = gtk_frame_new("Filters"); + list = gtk_list_new(); + scrolled_window = gtk_scrolled_window_new(NULL, NULL); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_set_focus_vadjustment + (GTK_CONTAINER (list), + gtk_scrolled_window_get_vadjustment + (GTK_SCROLLED_WINDOW (scrolled_window))); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); + + frame = gtk_frame_new("Filter Description"); + html = gtk_html_new(); + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(scrolled_window), html); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); + + p->html0 = html; + p->list0 = list; + + gtk_widget_set_usize(html, 300, 200); + gtk_widget_set_usize(list, 300, 200); + + gtk_box_pack_start((GtkBox *)hbox, vbox, TRUE, TRUE, 0); + + /* buttons */ + vbox = gtk_vbox_new(FALSE, 0); + + p->add0 = gtk_button_new_with_label ("Add"); + p->remove0 = gtk_button_new_with_label ("Remove"); + p->up0 = gtk_button_new_with_label ("Up"); + p->down0 = gtk_button_new_with_label ("Down"); + + gtk_box_pack_start((GtkBox *)vbox, p->add0, FALSE, TRUE, 0); + gtk_box_pack_start((GtkBox *)vbox, p->remove0, FALSE, TRUE, 0); + gtk_box_pack_start((GtkBox *)vbox, p->up0, FALSE, TRUE, 0); + gtk_box_pack_start((GtkBox *)vbox, p->down0, FALSE, TRUE, 0); + + gtk_box_pack_start((GtkBox *)hbox, vbox, FALSE, FALSE, 0); + + gtk_notebook_append_page(GTK_NOTEBOOK(p->notebook), hbox, NULL); + + gtk_widget_show_all(p->notebook); + + gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(d)->vbox), p->notebook, TRUE, TRUE, 0); +} +#endif + +void create_dialogue(void) +{ + GtkWidget *dialogue, + *scrolled_window, + *list, + *html, + *frame; + + dialogue = gnome_dialog_new("Filter Rules", + GNOME_STOCK_BUTTON_PREV , GNOME_STOCK_BUTTON_NEXT, + "Finish", GNOME_STOCK_BUTTON_CANCEL, 0); + + list = gtk_list_new(); + frame = gtk_frame_new("Filter Type"); + scrolled_window = gtk_scrolled_window_new(NULL, NULL); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_set_focus_vadjustment + (GTK_CONTAINER (list), + gtk_scrolled_window_get_vadjustment + (GTK_SCROLLED_WINDOW (scrolled_window))); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialogue)->vbox), frame, TRUE, TRUE, GNOME_PAD); + +#if 0 + gtk_signal_connect(GTK_OBJECT(list), "select_child", select_rule_child, NULL); + gtk_signal_connect(GTK_OBJECT(list), "unselect_child", select_rule_child, NULL); +#else + gtk_signal_connect(GTK_OBJECT(list), "select_child", select_option_child, NULL); + gtk_signal_connect(GTK_OBJECT(list), "unselect_child", select_option_child, NULL); +#endif + + frame = gtk_frame_new("Filter Description"); + html = gtk_html_new(); + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(scrolled_window), html); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialogue)->vbox), frame, TRUE, TRUE, GNOME_PAD); + + gtk_signal_connect(GTK_OBJECT(html), "link_clicked", arg_link_clicked, NULL); + gtk_signal_connect(GTK_OBJECT(dialogue), "clicked", dialogue_clicked, NULL); + + list_global = list; + html_global = html; + + gtk_widget_show_all(dialogue); +} + +int main(int argc, char **argv) +{ + FilterSEXP *f; + FilterSEXPResult *r; + GList *rules, *options, *options2; + xmlDocPtr doc, out, optionset, filteroptions; + GString *s; + + gnome_init("Test", "0.0", argc, argv); + gdk_rgb_init (); + gtk_widget_set_default_colormap (gdk_rgb_get_cmap ()); + gtk_widget_set_default_visual (gdk_rgb_get_visual ()); + + { + GtkWidget *d = (GtkWidget *)filter_druid_new(); + + doc = xmlParseFile("filterdescription.xml"); + rules = filter_load_ruleset(doc); + options = filter_load_optionset(doc, rules); + options2 = options; + out = xmlParseFile("saveoptions.xml"); + options = filter_load_optionset(out, rules); + + filter_druid_set_rules((FilterDruid *)d, options2, rules, options->data); +/* filter_druid_set_rules((FilterDruid *)d, options2, rules, NULL);*/ + + gtk_widget_show(d); + gtk_main(); + } +#if 0 + + create_dialogue(); + + doc = xmlParseFile("filterdescription.xml"); + rules = filter_load_ruleset(doc); + options = filter_load_optionset(doc, rules); + options2 = options; + out = xmlParseFile("saveoptions.xml"); + options = filter_load_optionset(out, rules); + +#if 0 + option_current = options->data; + fill_rules(list_global, rules, options->data, FILTER_XML_MATCH); +#else + option_current = NULL; + fill_options(list_global, options2); +#endif + gtk_main(); + + while (options) { + struct filter_option *fo = options->data; + GList *optionrulel; + + optionrulel = fo->options; + while (optionrulel) { + struct filter_optionrule *or = optionrulel->data; + + printf("formatting rule: %s\n", or->rule->name); + + /*filter_description_text(or->rule->description, or->args);*/ + filter_description_html_write(or->rule->description, or->args, NULL, NULL); + + optionrulel = g_list_next(optionrulel); + } + options = g_list_next(options); + } + + return 0; + + s = g_string_new(""); + g_string_append(s, ""); + + printf("total rule = '%s'\n", s->str); + + f = filter_sexp_new(); + filter_sexp_add_variable(f, 0, "sender", NULL); + filter_sexp_add_variable(f, 0, "receipient", NULL); + filter_sexp_add_variable(f, 0, "folder", NULL); + + /* simple functions */ + filter_sexp_add_function(f, 0, "header-get", NULL, NULL); + filter_sexp_add_function(f, 0, "header-contains", NULL, NULL); + filter_sexp_add_function(f, 0, "copy-to", NULL, NULL); + + filter_sexp_add_ifunction(f, 0, "set", NULL, NULL); + + /* control functions */ + filter_sexp_add_ifunction(f, 0, "match-all", NULL, NULL); + filter_sexp_add_ifunction(f, 0, "match", NULL, NULL); + filter_sexp_add_ifunction(f, 0, "action", NULL, NULL); + filter_sexp_add_ifunction(f, 0, "except", NULL, NULL); + + filter_sexp_input_text(f, s->str, strlen(s->str)); + filter_sexp_parse(f); +#endif + +} diff --git a/filter/filter-druid.h b/filter/filter-druid.h new file mode 100644 index 0000000000..1b88847041 --- /dev/null +++ b/filter/filter-druid.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2000 Helix Code Inc. + * + * Authors: Michael Zucchi <notzed@helixcode.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _FILTER_DRUID_H +#define _FILTER_DRUID_H + +#include <gtk/gtk.h> + +#include "filter-xml.h" + +#define FILTER_DRUID(obj) GTK_CHECK_CAST (obj, filter_druid_get_type (), FilterDruid) +#define FILTER_DRUID_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_druid_get_type (), FilterDruidClass) +#define IS_FILTER_DRUID(obj) GTK_CHECK_TYPE (obj, filter_druid_get_type ()) + +typedef struct _FilterDruid FilterDruid; +typedef struct _FilterDruidClass FilterDruidClass; + +struct _FilterDruid { + GnomeDialog parent; + + GList *options; /* all options */ + GList *rules; /* all rules */ + GList *user; /* current user options */ + + struct filter_option *option_current; + + struct _FilterDruidPrivate *priv; +}; + +struct _FilterDruidClass { + GnomeDialogClass parent_class; +}; + +guint filter_druid_get_type (void); +FilterDruid *filter_druid_new (void); + +/* Hmm, glists suck, no typesafety */ +void filter_druid_set_rules(FilterDruid *f, GList *options, GList *rules, struct filter_option *userrule); + +#endif /* ! _FILTER_DRUID_H */ diff --git a/filter/filter-format.c b/filter/filter-format.c index 00dcba00d3..8f0f67b16e 100644 --- a/filter/filter-format.c +++ b/filter/filter-format.c @@ -11,18 +11,20 @@ #include "filter-arg-types.h" #include "filter-xml.h" +#define d(x) + /* FIXME: remove static, this is defined in filter-xml */ static int filter_find_rule(struct filter_rule *a, char *name) { - printf("finding, is %s = %s?\n", a->name, name); + d(printf("finding, is %s = %s?\n", a->name, name)); return strcmp(a->name, name); } static int filter_find_arg(FilterArg *a, char *name) { - printf("finding, is %s = %s?\n", a->name, name); + d(printf("finding, is %s = %s?\n", a->name, name)); return strcmp(a->name, name); } @@ -67,11 +69,11 @@ arg_text(FilterArg *arg) value = arg->values; - printf("getting text from arg %s\n", arg->name); + d(printf("getting text from arg %s\n", arg->name)); if (value == NULL) return NULL; - + str = g_string_new(""); filter_arg_write_text(arg, str); out = str->str; @@ -84,14 +86,14 @@ description_decode_text(struct filter_desc *d, struct description_decode_lambda { GList *list; char *txt; - + switch (d->type) { case FILTER_XML_TEXT: case FILTER_XML_DESC: dotext: - printf("appending '%s'\n", d->data); + d(printf("appending '%s'\n", d->data)); /* printf("vartype = %s\n", detokenise(d->vartype)); */ - printf("varname = %s\n", d->varname); + d(printf("varname = %s\n", d->varname)); if (d->vartype !=-1 && d->varname && (list = g_list_find_custom(l->args, d->varname, (GCompareFunc) filter_find_arg)) && (txt = arg_text(list->data))) { @@ -112,13 +114,13 @@ filter_description_text(GList *description, GList *args) char *txt; struct description_decode_lambda l; - printf("\ndecoding ...\n"); + d(printf("\ndecoding ...\n")); l.str = g_string_new(""); l.args = args; g_list_foreach(description, (GFunc) description_decode_text, &l); - printf("string is '%s'\n", l.str->str); + d(printf("string is '%s'\n", l.str->str)); txt = l.str->str; g_string_free(l.str, FALSE); @@ -129,7 +131,7 @@ filter_description_text(GList *description, GList *args) static void html_write(GtkHTML *html, GtkHTMLStreamHandle *stream, char *s) { - printf("appending html '%s'\n", s); + d(printf("appending html '%s'\n", s)); gtk_html_write(html, stream, s, strlen(s)); } @@ -145,9 +147,9 @@ description_decode_html(struct filter_desc *d, struct description_decode_lambda case FILTER_XML_TEXT: case FILTER_XML_DESC: dotext: - printf("appending '%s'\n", d->data); + d(printf("appending '%s'\n", d->data)); /*printf("vartype = %s\n", detokenise(d->vartype));*/ - printf("varname = %s\n", d->varname); + d(printf("varname = %s\n", d->varname)); free = FALSE; if (d->vartype !=-1 && d->varname) { char *link; @@ -190,7 +192,7 @@ filter_description_html_write(GList *description, GList *args, GtkHTML *html, Gt char *txt; struct description_decode_lambda l; - printf("\ndecoding ...\n"); + d(printf("\ndecoding ...\n")); l.str = NULL; l.args = args; diff --git a/filter/filter-xml.c b/filter/filter-xml.c index 144bd88f0d..2371acc5a1 100644 --- a/filter/filter-xml.c +++ b/filter/filter-xml.c @@ -388,6 +388,72 @@ filter_write_optionset(xmlDocPtr doc, GList *optionl) return root; } +/* utility functions */ +struct filter_optionrule * +filter_clone_optionrule(struct filter_optionrule *or) +{ + GList *arg; + struct filter_optionrule *rule; + + rule = g_malloc0(sizeof(*rule)); + + rule->rule = or->rule; + arg = or->args; + while (arg) { + rule->args = g_list_append(rule->args, filter_arg_clone(FILTER_ARG(arg->data))); + arg = g_list_next(arg); + } + return rule; +} + +void +filter_clone_optionrule_free(struct filter_optionrule *or) +{ + GList *argl; + struct filter_optionrule *rule; + + argl = or->args; + while (argl) { + gtk_object_unref(GTK_OBJECT(argl->data)); + argl = g_list_next(argl); + } + g_list_free(or->args); + g_free(or); +} + +struct filter_optionrule * +filter_optionrule_new_from_rule(struct filter_rule *rule) +{ + struct filter_optionrule *or; + GList *descl; + + or = g_malloc0(sizeof(*or)); + + or->rule = rule; + + descl = rule->description; + while (descl) { + struct filter_desc *desc = descl->data; + if (desc->varname && desc->vartype != -1) { + FilterArg *arg = NULL; + switch (desc->vartype) { + case FILTER_XML_ADDRESS: + arg = filter_arg_address_new(desc->varname); + break; + case FILTER_XML_FOLDER: + arg = filter_arg_folder_new(desc->varname); + break; + } + if (arg) { + or->args = g_list_append(or->args, arg); + } + } + descl = g_list_next(descl); + } + return or; +} + + #ifdef TESTER int main(int argc, char **argv) { diff --git a/filter/filter-xml.h b/filter/filter-xml.h index 1ff353bd20..b5d3255560 100644 --- a/filter/filter-xml.h +++ b/filter/filter-xml.h @@ -59,4 +59,9 @@ xmlNodePtr filter_write_optionset(xmlDocPtr doc, GList *optionl); int filter_find_rule(struct filter_rule *a, char *name); int filter_find_arg(FilterArg *a, char *name); +/* utility functions */ +struct filter_optionrule *filter_clone_optionrule(struct filter_optionrule *or); +void filter_clone_optionrule_free(struct filter_optionrule *or); +struct filter_optionrule *filter_optionrule_new_from_rule(struct filter_rule *rule); + #endif /* ! _FILTER_XML_H */ |