Support putting preferences into arbitrary places in a tree, which is
used to construct the "Edit->Preferences" dialog box; this includes the ability to register a "subtree" for preferences. Instead of special-casing protocol preferences, have a subtree "Protocols" for protocol preferences. svn path=/trunk/; revision=6808
This commit is contained in:
parent
e4633bc783
commit
392fee6d7a
177
gtk/prefs_dlg.c
177
gtk/prefs_dlg.c
|
@ -1,7 +1,7 @@
|
||||||
/* prefs_dlg.c
|
/* prefs_dlg.c
|
||||||
* Routines for handling preferences
|
* Routines for handling preferences
|
||||||
*
|
*
|
||||||
* $Id: prefs_dlg.c,v 1.56 2002/11/28 01:58:27 guy Exp $
|
* $Id: prefs_dlg.c,v 1.57 2002/12/20 01:48:57 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -78,7 +78,7 @@ static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
|
||||||
#define E_NAMERES_PAGE_KEY "nameres_options_page"
|
#define E_NAMERES_PAGE_KEY "nameres_options_page"
|
||||||
#define E_TOOLTIPS_KEY "tooltips"
|
#define E_TOOLTIPS_KEY "tooltips"
|
||||||
|
|
||||||
#define FIRST_PROTO_PREFS_PAGE 6
|
static int first_proto_prefs_page = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep a static pointer to the notebook to be able to choose the
|
* Keep a static pointer to the notebook to be able to choose the
|
||||||
|
@ -102,14 +102,17 @@ static GtkWidget *prefs_w;
|
||||||
static e_prefs saved_prefs;
|
static e_prefs saved_prefs;
|
||||||
|
|
||||||
struct ct_struct {
|
struct ct_struct {
|
||||||
|
GtkWidget *main_vb;
|
||||||
GtkWidget *notebook;
|
GtkWidget *notebook;
|
||||||
GtkWidget *tree;
|
GtkWidget *tree;
|
||||||
#if GTK_MAJOR_VERSION >= 2
|
#if GTK_MAJOR_VERSION < 2
|
||||||
GtkTreeIter proto_iter;
|
|
||||||
#endif
|
|
||||||
GtkCTreeNode *node;
|
GtkCTreeNode *node;
|
||||||
|
#else
|
||||||
|
GtkTreeIter iter;
|
||||||
|
#endif
|
||||||
GtkTooltips *tooltips;
|
GtkTooltips *tooltips;
|
||||||
gint page;
|
gint page;
|
||||||
|
gboolean is_protocol;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -203,57 +206,108 @@ static void
|
||||||
module_prefs_show(module_t *module, gpointer user_data)
|
module_prefs_show(module_t *module, gpointer user_data)
|
||||||
{
|
{
|
||||||
struct ct_struct *cts = user_data;
|
struct ct_struct *cts = user_data;
|
||||||
|
struct ct_struct child_cts;
|
||||||
GtkWidget *main_vb, *main_tb, *frame;
|
GtkWidget *main_vb, *main_tb, *frame;
|
||||||
gchar label_str[MAX_TREE_NODE_NAME_LEN];
|
gchar label_str[MAX_TREE_NODE_NAME_LEN];
|
||||||
#if GTK_MAJOR_VERSION < 2
|
#if GTK_MAJOR_VERSION < 2
|
||||||
gchar *label_ptr = label_str;
|
gchar *label_ptr = label_str;
|
||||||
GtkCTreeNode *ct_node;
|
GtkCTreeNode *ct_node;
|
||||||
#else
|
#else
|
||||||
GtkTreeStore *model;
|
GtkTreeStore *model;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Frame */
|
/*
|
||||||
frame = gtk_frame_new(module->title);
|
* Add this module to the tree.
|
||||||
gtk_widget_show(frame);
|
*/
|
||||||
|
|
||||||
/* Main vertical box */
|
|
||||||
main_vb = gtk_vbox_new(FALSE, 5);
|
|
||||||
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
|
|
||||||
gtk_container_add(GTK_CONTAINER(frame), main_vb);
|
|
||||||
|
|
||||||
/* Main table */
|
|
||||||
main_tb = gtk_table_new(module->numprefs, 2, FALSE);
|
|
||||||
gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
|
|
||||||
gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
|
|
||||||
gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
|
|
||||||
OBJECT_SET_DATA(main_tb, E_TOOLTIPS_KEY, cts->tooltips);
|
|
||||||
|
|
||||||
/* Add items for each of the preferences */
|
|
||||||
prefs_pref_foreach(module, pref_show, main_tb);
|
|
||||||
|
|
||||||
gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), frame, NULL);
|
|
||||||
strcpy(label_str, module->title);
|
strcpy(label_str, module->title);
|
||||||
#if GTK_MAJOR_VERSION < 2
|
#if GTK_MAJOR_VERSION < 2
|
||||||
ct_node = gtk_ctree_insert_node(GTK_CTREE(cts->tree), cts->node, NULL,
|
ct_node = gtk_ctree_insert_node(GTK_CTREE(cts->tree), cts->node, NULL,
|
||||||
&label_ptr, 5, NULL, NULL, NULL, NULL, TRUE, TRUE);
|
&label_ptr, 5, NULL, NULL, NULL, NULL, !module->is_subtree,
|
||||||
gtk_ctree_node_set_row_data(GTK_CTREE(cts->tree), ct_node,
|
FALSE);
|
||||||
GINT_TO_POINTER(cts->page));
|
|
||||||
#else
|
#else
|
||||||
model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
|
model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
|
||||||
gtk_tree_store_append(model, &iter, &cts->proto_iter);
|
gtk_tree_store_append(model, &iter, &cts->iter);
|
||||||
gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
|
|
||||||
#endif
|
#endif
|
||||||
cts->page++;
|
|
||||||
|
|
||||||
/* Show 'em what we got */
|
/*
|
||||||
gtk_widget_show_all(main_vb);
|
* Is this a subtree?
|
||||||
|
*/
|
||||||
|
if (module->is_subtree) {
|
||||||
|
/*
|
||||||
|
* Yes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Note that there's no page attached to this item */
|
||||||
|
#if GTK_MAJOR_VERSION < 2
|
||||||
|
gtk_ctree_node_set_row_data(GTK_CTREE(cts->tree), ct_node,
|
||||||
|
GINT_TO_POINTER(-1));
|
||||||
|
#else
|
||||||
|
gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the subtree and attach stuff to it.
|
||||||
|
*/
|
||||||
|
child_cts = *cts;
|
||||||
|
#if GTK_MAJOR_VERSION < 2
|
||||||
|
child_cts.node = ct_node;
|
||||||
|
#else
|
||||||
|
child_cts.iter = iter;
|
||||||
|
#endif
|
||||||
|
if (module == protocols_module)
|
||||||
|
child_cts.is_protocol = TRUE;
|
||||||
|
prefs_module_list_foreach(module->prefs, module_prefs_show, &child_cts);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* No.
|
||||||
|
* Create a notebook page for it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Frame */
|
||||||
|
frame = gtk_frame_new(module->title);
|
||||||
|
gtk_widget_show(frame);
|
||||||
|
|
||||||
|
/* Main vertical box */
|
||||||
|
main_vb = gtk_vbox_new(FALSE, 5);
|
||||||
|
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
|
||||||
|
gtk_container_add(GTK_CONTAINER(frame), main_vb);
|
||||||
|
|
||||||
|
/* Main table */
|
||||||
|
main_tb = gtk_table_new(module->numprefs, 2, FALSE);
|
||||||
|
gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
|
||||||
|
gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
|
||||||
|
gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
|
||||||
|
OBJECT_SET_DATA(main_tb, E_TOOLTIPS_KEY, cts->tooltips);
|
||||||
|
|
||||||
|
/* Add items for each of the preferences */
|
||||||
|
prefs_pref_foreach(module, pref_show, main_tb);
|
||||||
|
|
||||||
|
/* Add the page to the notebook */
|
||||||
|
gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), frame, NULL);
|
||||||
|
|
||||||
|
/* Attach the page to the tree item */
|
||||||
|
#if GTK_MAJOR_VERSION < 2
|
||||||
|
gtk_ctree_node_set_row_data(GTK_CTREE(cts->tree), ct_node,
|
||||||
|
GINT_TO_POINTER(cts->page));
|
||||||
|
#else
|
||||||
|
gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If this is the first protocol page, remember its page number */
|
||||||
|
if (first_proto_prefs_page == -1)
|
||||||
|
first_proto_prefs_page = cts->page;
|
||||||
|
cts->page++;
|
||||||
|
|
||||||
|
/* Show 'em what we got */
|
||||||
|
gtk_widget_show_all(main_vb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
|
prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
|
||||||
{
|
{
|
||||||
GtkWidget *main_vb, *top_hb, *bbox, *prefs_nb, *ct_sb, *frame,
|
GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb, *frame,
|
||||||
*ok_bt, *apply_bt, *save_bt, *cancel_bt;
|
*ok_bt, *apply_bt, *save_bt, *cancel_bt;
|
||||||
GtkWidget *print_pg, *column_pg, *stream_pg, *gui_pg;
|
GtkWidget *print_pg, *column_pg, *stream_pg, *gui_pg;
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
|
@ -266,7 +320,6 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
|
||||||
gchar *label_ptr = label_str;
|
gchar *label_ptr = label_str;
|
||||||
GtkCTreeNode *ct_node;
|
GtkCTreeNode *ct_node;
|
||||||
#else
|
#else
|
||||||
GtkTreeStore *store;
|
|
||||||
GtkTreeSelection *selection;
|
GtkTreeSelection *selection;
|
||||||
GtkCellRenderer *renderer;
|
GtkCellRenderer *renderer;
|
||||||
GtkTreeViewColumn *column;
|
GtkTreeViewColumn *column;
|
||||||
|
@ -297,14 +350,14 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
|
||||||
cts.tooltips = gtk_tooltips_new();
|
cts.tooltips = gtk_tooltips_new();
|
||||||
|
|
||||||
/* Container for each row of widgets */
|
/* Container for each row of widgets */
|
||||||
main_vb = gtk_vbox_new(FALSE, 5);
|
cts.main_vb = gtk_vbox_new(FALSE, 5);
|
||||||
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
|
gtk_container_border_width(GTK_CONTAINER(cts.main_vb), 5);
|
||||||
gtk_container_add(GTK_CONTAINER(prefs_w), main_vb);
|
gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
|
||||||
gtk_widget_show(main_vb);
|
gtk_widget_show(cts.main_vb);
|
||||||
|
|
||||||
/* Top row: Preferences tree and notebook */
|
/* Top row: Preferences tree and notebook */
|
||||||
top_hb = gtk_hbox_new(FALSE, 10);
|
top_hb = gtk_hbox_new(FALSE, 10);
|
||||||
gtk_container_add(GTK_CONTAINER(main_vb), top_hb);
|
gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
|
||||||
gtk_widget_show(top_hb);
|
gtk_widget_show(top_hb);
|
||||||
|
|
||||||
/* Place a Ctree on the left for preference categories */
|
/* Place a Ctree on the left for preference categories */
|
||||||
|
@ -331,7 +384,8 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
|
||||||
gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
|
gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
|
||||||
GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
||||||
#endif
|
#endif
|
||||||
cts.page = 0;
|
cts.page = 0;
|
||||||
|
cts.node = NULL;
|
||||||
gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
|
gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
|
||||||
|
|
||||||
#if GTK_MAJOR_VERSION < 2
|
#if GTK_MAJOR_VERSION < 2
|
||||||
|
@ -344,8 +398,8 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
|
||||||
|
|
||||||
/* A notebook widget sans tabs is used to flip between prefs */
|
/* A notebook widget sans tabs is used to flip between prefs */
|
||||||
notebook = prefs_nb = gtk_notebook_new();
|
notebook = prefs_nb = gtk_notebook_new();
|
||||||
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
|
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
|
||||||
gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
|
gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
|
||||||
gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
|
gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
|
||||||
gtk_widget_show(prefs_nb);
|
gtk_widget_show(prefs_nb);
|
||||||
|
|
||||||
|
@ -474,26 +528,14 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
|
||||||
|
|
||||||
/* Registered prefs */
|
/* Registered prefs */
|
||||||
cts.notebook = prefs_nb;
|
cts.notebook = prefs_nb;
|
||||||
strcpy(label_str, "Protocols");
|
cts.is_protocol = FALSE;
|
||||||
#if GTK_MAJOR_VERSION < 2
|
prefs_module_list_foreach(NULL, module_prefs_show, &cts);
|
||||||
cts.node = gtk_ctree_insert_node(GTK_CTREE(cts.tree), NULL, NULL,
|
|
||||||
&label_ptr, 5, NULL, NULL, NULL, NULL, FALSE, FALSE);
|
|
||||||
gtk_ctree_node_set_row_data(GTK_CTREE(cts.tree), cts.node,
|
|
||||||
GINT_TO_POINTER(-1));
|
|
||||||
gtk_ctree_node_set_selectable(GTK_CTREE(cts.tree), cts.node, FALSE);
|
|
||||||
#else
|
|
||||||
gtk_tree_store_append(store, &cts.proto_iter, NULL);
|
|
||||||
gtk_tree_store_set(store, &cts.proto_iter, 0, label_str, 1, -1, -1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
prefs_module_foreach(module_prefs_show, &cts);
|
|
||||||
|
|
||||||
|
|
||||||
/* Button row: OK and cancel buttons */
|
/* Button row: OK and cancel buttons */
|
||||||
bbox = gtk_hbutton_box_new();
|
bbox = gtk_hbutton_box_new();
|
||||||
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
|
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
|
||||||
gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
|
gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
|
||||||
gtk_container_add(GTK_CONTAINER(main_vb), bbox);
|
gtk_container_add(GTK_CONTAINER(cts.main_vb), bbox);
|
||||||
gtk_widget_show(bbox);
|
gtk_widget_show(bbox);
|
||||||
|
|
||||||
#if GTK_MAJOR_VERSION < 2
|
#if GTK_MAJOR_VERSION < 2
|
||||||
|
@ -914,7 +956,7 @@ prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
#endif /* HAVE_LIBPCAP */
|
#endif /* HAVE_LIBPCAP */
|
||||||
nameres_prefs_fetch(OBJECT_GET_DATA(parent_w, E_NAMERES_PAGE_KEY));
|
nameres_prefs_fetch(OBJECT_GET_DATA(parent_w, E_NAMERES_PAGE_KEY));
|
||||||
prefs_module_foreach(module_prefs_fetch, &must_redissect);
|
prefs_modules_foreach(module_prefs_fetch, &must_redissect);
|
||||||
|
|
||||||
/* Now apply those preferences. */
|
/* Now apply those preferences. */
|
||||||
printer_prefs_apply(OBJECT_GET_DATA(parent_w, E_PRINT_PAGE_KEY));
|
printer_prefs_apply(OBJECT_GET_DATA(parent_w, E_PRINT_PAGE_KEY));
|
||||||
|
@ -966,7 +1008,7 @@ prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
#endif /* HAVE_LIBPCAP */
|
#endif /* HAVE_LIBPCAP */
|
||||||
nameres_prefs_fetch(OBJECT_GET_DATA(parent_w, E_NAMERES_PAGE_KEY));
|
nameres_prefs_fetch(OBJECT_GET_DATA(parent_w, E_NAMERES_PAGE_KEY));
|
||||||
prefs_module_foreach(module_prefs_fetch, &must_redissect);
|
prefs_modules_foreach(module_prefs_fetch, &must_redissect);
|
||||||
|
|
||||||
/* Now apply those preferences. */
|
/* Now apply those preferences. */
|
||||||
printer_prefs_apply(OBJECT_GET_DATA(parent_w, E_PRINT_PAGE_KEY));
|
printer_prefs_apply(OBJECT_GET_DATA(parent_w, E_PRINT_PAGE_KEY));
|
||||||
|
@ -1018,7 +1060,7 @@ prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
#endif /* HAVE_LIBPCAP */
|
#endif /* HAVE_LIBPCAP */
|
||||||
nameres_prefs_fetch(OBJECT_GET_DATA(parent_w, E_NAMERES_PAGE_KEY));
|
nameres_prefs_fetch(OBJECT_GET_DATA(parent_w, E_NAMERES_PAGE_KEY));
|
||||||
prefs_module_foreach(module_prefs_fetch, &must_redissect);
|
prefs_modules_foreach(module_prefs_fetch, &must_redissect);
|
||||||
|
|
||||||
/* Create the directory that holds personal configuration files, if
|
/* Create the directory that holds personal configuration files, if
|
||||||
necessary. */
|
necessary. */
|
||||||
|
@ -1151,7 +1193,7 @@ prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
|
||||||
copy_prefs(&prefs, &saved_prefs);
|
copy_prefs(&prefs, &saved_prefs);
|
||||||
|
|
||||||
/* Now revert the registered preferences. */
|
/* Now revert the registered preferences. */
|
||||||
prefs_module_foreach(module_prefs_revert, &must_redissect);
|
prefs_modules_foreach(module_prefs_revert, &must_redissect);
|
||||||
|
|
||||||
/* Now apply the reverted-to preferences. */
|
/* Now apply the reverted-to preferences. */
|
||||||
printer_prefs_apply(OBJECT_GET_DATA(parent_w, E_PRINT_PAGE_KEY));
|
printer_prefs_apply(OBJECT_GET_DATA(parent_w, E_PRINT_PAGE_KEY));
|
||||||
|
@ -1203,10 +1245,11 @@ prefs_main_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
|
||||||
/* Free up the saved preferences (both for "prefs" and for registered
|
/* Free up the saved preferences (both for "prefs" and for registered
|
||||||
preferences). */
|
preferences). */
|
||||||
free_prefs(&saved_prefs);
|
free_prefs(&saved_prefs);
|
||||||
prefs_module_foreach(module_prefs_clean, NULL);
|
prefs_modules_foreach(module_prefs_clean, NULL);
|
||||||
|
|
||||||
/* Note that we no longer have a "Preferences" dialog box. */
|
/* Note that we no longer have a "Preferences" dialog box. */
|
||||||
prefs_w = NULL;
|
prefs_w = NULL;
|
||||||
|
first_proto_prefs_page = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct properties_data {
|
struct properties_data {
|
||||||
|
@ -1258,11 +1301,11 @@ properties_cb(GtkWidget *w, gpointer dummy)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.w = notebook;
|
p.w = notebook;
|
||||||
p.page_num = FIRST_PROTO_PREFS_PAGE;
|
p.page_num = first_proto_prefs_page;
|
||||||
p.title = title;
|
p.title = title;
|
||||||
|
|
||||||
prefs_module_foreach(module_search_properties, &p);
|
prefs_module_list_foreach(protocols_module->prefs, module_search_properties,
|
||||||
|
&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prefs tree selection callback. The node data has been loaded with
|
/* Prefs tree selection callback. The node data has been loaded with
|
||||||
|
|
10
prefs-int.h
10
prefs-int.h
|
@ -2,7 +2,7 @@
|
||||||
* Definitions for implementation of preference handling routines;
|
* Definitions for implementation of preference handling routines;
|
||||||
* used by "friends" of the preferences type.
|
* used by "friends" of the preferences type.
|
||||||
*
|
*
|
||||||
* $Id: prefs-int.h,v 1.9 2002/08/28 21:00:40 jmayer Exp $
|
* $Id: prefs-int.h,v 1.10 2002/12/20 01:48:54 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -29,14 +29,20 @@
|
||||||
struct pref_module {
|
struct pref_module {
|
||||||
const char *name; /* name of module */
|
const char *name; /* name of module */
|
||||||
const char *title; /* title of module (displayed in preferences notebook) */
|
const char *title; /* title of module (displayed in preferences notebook) */
|
||||||
|
gboolean is_subtree; /* if TRUE, this has other modules, not preferences, under it */
|
||||||
void (*apply_cb)(void); /* routine to call when preferences applied */
|
void (*apply_cb)(void); /* routine to call when preferences applied */
|
||||||
GList *prefs; /* list of its preferences */
|
GList *prefs; /* list of its preferences or submodules */
|
||||||
int numprefs; /* number of non-obsolete preferences */
|
int numprefs; /* number of non-obsolete preferences */
|
||||||
gboolean prefs_changed; /* if TRUE, a preference has changed since we last checked */
|
gboolean prefs_changed; /* if TRUE, a preference has changed since we last checked */
|
||||||
gboolean obsolete; /* if TRUE, this is a module that used to
|
gboolean obsolete; /* if TRUE, this is a module that used to
|
||||||
exist but no longer does */
|
exist but no longer does */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module used for protocol preferences.
|
||||||
|
*/
|
||||||
|
extern module_t *protocols_module;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PREF_OBSOLETE is used for preferences that a module used to support
|
* PREF_OBSOLETE is used for preferences that a module used to support
|
||||||
* but no longer supports; we give different error messages for them.
|
* but no longer supports; we give different error messages for them.
|
||||||
|
|
196
prefs.c
196
prefs.c
|
@ -1,7 +1,7 @@
|
||||||
/* prefs.c
|
/* prefs.c
|
||||||
* Routines for handling preferences
|
* Routines for handling preferences
|
||||||
*
|
*
|
||||||
* $Id: prefs.c,v 1.91 2002/09/28 15:23:13 gerald Exp $
|
* $Id: prefs.c,v 1.92 2002/12/20 01:48:54 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -51,6 +51,9 @@
|
||||||
|
|
||||||
/* Internal functions */
|
/* Internal functions */
|
||||||
static module_t *find_module(const char *name);
|
static module_t *find_module(const char *name);
|
||||||
|
static module_t *prefs_register_module_or_subtree(module_t *parent,
|
||||||
|
const char *name, const char *title, gboolean is_subtree,
|
||||||
|
void (*apply_cb)(void));
|
||||||
static struct preference *find_preference(module_t *, const char *);
|
static struct preference *find_preference(module_t *, const char *);
|
||||||
static int set_pref(gchar*, gchar*);
|
static int set_pref(gchar*, gchar*);
|
||||||
static GList *get_string_list(gchar *);
|
static GList *get_string_list(gchar *);
|
||||||
|
@ -85,10 +88,16 @@ gchar *gui_hex_dump_highlight_style_text[] =
|
||||||
{ "BOLD", "INVERSE", NULL };
|
{ "BOLD", "INVERSE", NULL };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of modules with preference settings.
|
* List of all modules with preference settings.
|
||||||
*/
|
*/
|
||||||
static GList *modules;
|
static GList *modules;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of all modules that should show up at the top level of the
|
||||||
|
* tree in the preference dialog box.
|
||||||
|
*/
|
||||||
|
static GList *top_level_modules;
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
module_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
|
module_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
|
||||||
{
|
{
|
||||||
|
@ -98,15 +107,46 @@ module_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
|
||||||
return g_strcasecmp(p1->name, p2->name);
|
return g_strcasecmp(p1->name, p2->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
module_compare_title(gconstpointer p1_arg, gconstpointer p2_arg)
|
||||||
|
{
|
||||||
|
const module_t *p1 = p1_arg;
|
||||||
|
const module_t *p2 = p2_arg;
|
||||||
|
|
||||||
|
return g_strcasecmp(p1->title, p2->title);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register a module that will have preferences.
|
* Register a module that will have preferences.
|
||||||
* Specify the name used for the module in the preferences file, the
|
* Specify the module under which to register it or NULL to register it
|
||||||
* title used in the tab for it in a preferences dialog box, and a
|
* at the top level, the name used for the module in the preferences file,
|
||||||
|
* the title used in the tab for it in a preferences dialog box, and a
|
||||||
* routine to call back when we apply the preferences.
|
* routine to call back when we apply the preferences.
|
||||||
*/
|
*/
|
||||||
module_t *
|
module_t *
|
||||||
prefs_register_module(const char *name, const char *title,
|
prefs_register_module(module_t *parent, const char *name, const char *title,
|
||||||
void (*apply_cb)(void))
|
void (*apply_cb)(void))
|
||||||
|
{
|
||||||
|
return prefs_register_module_or_subtree(parent, name, title, FALSE,
|
||||||
|
apply_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a subtree that will have modules under it.
|
||||||
|
* Specify the module under which to register it or NULL to register it
|
||||||
|
* at the top level and the title used in the tab for it in a preferences
|
||||||
|
* dialog box.
|
||||||
|
*/
|
||||||
|
module_t *
|
||||||
|
prefs_register_subtree(module_t *parent, const char *title)
|
||||||
|
{
|
||||||
|
return prefs_register_module_or_subtree(parent, NULL, title, TRUE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static module_t *
|
||||||
|
prefs_register_module_or_subtree(module_t *parent, const char *name,
|
||||||
|
const char *title, gboolean is_subtree, void (*apply_cb)(void))
|
||||||
{
|
{
|
||||||
module_t *module;
|
module_t *module;
|
||||||
const guchar *p;
|
const guchar *p;
|
||||||
|
@ -114,6 +154,7 @@ prefs_register_module(const char *name, const char *title,
|
||||||
module = g_malloc(sizeof (module_t));
|
module = g_malloc(sizeof (module_t));
|
||||||
module->name = name;
|
module->name = name;
|
||||||
module->title = title;
|
module->title = title;
|
||||||
|
module->is_subtree = is_subtree;
|
||||||
module->apply_cb = apply_cb;
|
module->apply_cb = apply_cb;
|
||||||
module->prefs = NULL; /* no preferences, to start */
|
module->prefs = NULL; /* no preferences, to start */
|
||||||
module->numprefs = 0;
|
module->numprefs = 0;
|
||||||
|
@ -121,28 +162,69 @@ prefs_register_module(const char *name, const char *title,
|
||||||
module->obsolete = FALSE;
|
module->obsolete = FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure that only lower-case ASCII letters, numbers,
|
* Do we have a module name?
|
||||||
* underscores, and dots appear in the module name.
|
|
||||||
*
|
|
||||||
* Crash if there is, as that's an error in the code;
|
|
||||||
* you can make the title a nice string with capitalization,
|
|
||||||
* white space, punctuation, etc., but the name can be used
|
|
||||||
* on the command line, and shouldn't require quoting,
|
|
||||||
* shifting, etc.
|
|
||||||
*/
|
*/
|
||||||
for (p = name; *p != '\0'; p++)
|
if (name != NULL) {
|
||||||
g_assert(isascii(*p) &&
|
/*
|
||||||
(islower(*p) || isdigit(*p) || *p == '_' || *p == '.'));
|
* Yes.
|
||||||
|
* Make sure that only lower-case ASCII letters, numbers,
|
||||||
|
* underscores, and dots appear in the name.
|
||||||
|
*
|
||||||
|
* Crash if there is, as that's an error in the code;
|
||||||
|
* you can make the title a nice string with capitalization,
|
||||||
|
* white space, punctuation, etc., but the name can be used
|
||||||
|
* on the command line, and shouldn't require quoting,
|
||||||
|
* shifting, etc.
|
||||||
|
*/
|
||||||
|
for (p = name; *p != '\0'; p++)
|
||||||
|
g_assert(isascii(*p) &&
|
||||||
|
(islower(*p) || isdigit(*p) || *p == '_' ||
|
||||||
|
*p == '.'));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure there's not already a module with that
|
||||||
|
* name. Crash if there is, as that's an error in the
|
||||||
|
* code, and the code has to be fixed not to register
|
||||||
|
* more than one module with the same name.
|
||||||
|
*
|
||||||
|
* We search the list of all modules; the subtree stuff
|
||||||
|
* doesn't require preferences in subtrees to have names
|
||||||
|
* that reflect the subtree they're in (that would require
|
||||||
|
* protocol preferences to have a bogus "protocol.", or
|
||||||
|
* something such as that, to be added to all their names).
|
||||||
|
*/
|
||||||
|
g_assert(find_module(name) == NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert this module in the list of all modules.
|
||||||
|
*/
|
||||||
|
modules = g_list_insert_sorted(modules, module,
|
||||||
|
module_compare_name);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This has no name, just a title; check to make sure it's a
|
||||||
|
* subtree, and crash if it's not.
|
||||||
|
*/
|
||||||
|
g_assert(is_subtree);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure there's not already a module with that
|
* Insert this module into the appropriate place in the display
|
||||||
* name. Crash if there is, as that's an error in the
|
* tree.
|
||||||
* code, and the code has to be fixed not to register
|
|
||||||
* more than one module with the same name.
|
|
||||||
*/
|
*/
|
||||||
g_assert(find_module(name) == NULL);
|
if (parent == NULL) {
|
||||||
|
/*
|
||||||
modules = g_list_insert_sorted(modules, module, module_compare_name);
|
* It goes at the top.
|
||||||
|
*/
|
||||||
|
top_level_modules = g_list_insert_sorted(top_level_modules,
|
||||||
|
module, module_compare_title);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* It goes into the list for this module.
|
||||||
|
*/
|
||||||
|
parent->prefs = g_list_insert_sorted(parent->prefs, module,
|
||||||
|
module_compare_title);
|
||||||
|
}
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
@ -150,12 +232,23 @@ prefs_register_module(const char *name, const char *title,
|
||||||
/*
|
/*
|
||||||
* Register that a protocol has preferences.
|
* Register that a protocol has preferences.
|
||||||
*/
|
*/
|
||||||
|
module_t *protocols_module;
|
||||||
|
|
||||||
module_t *
|
module_t *
|
||||||
prefs_register_protocol(int id, void (*apply_cb)(void))
|
prefs_register_protocol(int id, void (*apply_cb)(void))
|
||||||
{
|
{
|
||||||
return prefs_register_module(proto_get_protocol_filter_name(id),
|
/*
|
||||||
proto_get_protocol_short_name(id),
|
* Have we yet created the "Protocols" subtree?
|
||||||
apply_cb);
|
*/
|
||||||
|
if (protocols_module == NULL) {
|
||||||
|
/*
|
||||||
|
* No. Do so.
|
||||||
|
*/
|
||||||
|
protocols_module = prefs_register_subtree(NULL, "Protocols");
|
||||||
|
}
|
||||||
|
return prefs_register_module(protocols_module,
|
||||||
|
proto_get_protocol_filter_name(id),
|
||||||
|
proto_get_protocol_short_name(id), apply_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -167,9 +260,18 @@ prefs_register_protocol_obsolete(int id)
|
||||||
{
|
{
|
||||||
module_t *module;
|
module_t *module;
|
||||||
|
|
||||||
module = prefs_register_module(proto_get_protocol_filter_name(id),
|
/*
|
||||||
proto_get_protocol_short_name(id),
|
* Have we yet created the "Protocols" subtree?
|
||||||
NULL);
|
*/
|
||||||
|
if (protocols_module == NULL) {
|
||||||
|
/*
|
||||||
|
* No. Do so.
|
||||||
|
*/
|
||||||
|
protocols_module = prefs_register_subtree(NULL, "Protocols");
|
||||||
|
}
|
||||||
|
module = prefs_register_module(protocols_module,
|
||||||
|
proto_get_protocol_filter_name(id),
|
||||||
|
proto_get_protocol_short_name(id), NULL);
|
||||||
module->obsolete = TRUE;
|
module->obsolete = TRUE;
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
@ -213,19 +315,41 @@ do_module_callback(gpointer data, gpointer user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call a callback function, with a specified argument, for each module.
|
* Call a callback function, with a specified argument, for each module
|
||||||
|
* in a list of modules. If the list is NULL, searches the top-level
|
||||||
|
* list in the display tree of modules.
|
||||||
|
*
|
||||||
|
* Ignores "obsolete" modules; their sole purpose is to allow old
|
||||||
|
* preferences for dissectors that no longer have preferences to be
|
||||||
|
* silently ignored in preference files. Does not ignore subtrees,
|
||||||
|
* as this can be used when walking the display tree of modules.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prefs_module_list_foreach(GList *module_list, module_cb callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
module_cb_arg_t arg;
|
||||||
|
|
||||||
|
if (module_list == NULL)
|
||||||
|
module_list = top_level_modules;
|
||||||
|
|
||||||
|
arg.callback = callback;
|
||||||
|
arg.user_data = user_data;
|
||||||
|
g_list_foreach(module_list, do_module_callback, &arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call a callback function, with a specified argument, for each module
|
||||||
|
* in the list of all modules. (This list does not include subtrees.)
|
||||||
|
*
|
||||||
* Ignores "obsolete" modules; their sole purpose is to allow old
|
* Ignores "obsolete" modules; their sole purpose is to allow old
|
||||||
* preferences for dissectors that no longer have preferences to be
|
* preferences for dissectors that no longer have preferences to be
|
||||||
* silently ignored in preference files.
|
* silently ignored in preference files.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
prefs_module_foreach(module_cb callback, gpointer user_data)
|
prefs_modules_foreach(module_cb callback, gpointer user_data)
|
||||||
{
|
{
|
||||||
module_cb_arg_t arg;
|
prefs_module_list_foreach(modules, callback, user_data);
|
||||||
|
|
||||||
arg.callback = callback;
|
|
||||||
arg.user_data = user_data;
|
|
||||||
g_list_foreach(modules, do_module_callback, &arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
53
prefs.h
53
prefs.h
|
@ -1,7 +1,7 @@
|
||||||
/* prefs.h
|
/* prefs.h
|
||||||
* Definitions for preference handling routines
|
* Definitions for preference handling routines
|
||||||
*
|
*
|
||||||
* $Id: prefs.h,v 1.41 2002/09/14 10:07:37 oabad Exp $
|
* $Id: prefs.h,v 1.42 2002/12/20 01:48:54 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -88,18 +88,27 @@ typedef struct pref_module module_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register a module that will have preferences.
|
* Register a module that will have preferences.
|
||||||
* Specify the name used for the module in the preferences file, the
|
* Specify the module under which to register it or NULL to register it
|
||||||
* title used in the tab for it in a preferences dialog box, and a
|
* at the top level, the name used for the module in the preferences file,
|
||||||
|
* the title used in the tab for it in a preferences dialog box, and a
|
||||||
* routine to call back when we apply the preferences.
|
* routine to call back when we apply the preferences.
|
||||||
* Note:
|
*
|
||||||
* In case of dissectors, the specified name should be the protocol
|
* This should not be used for dissector preferences;
|
||||||
* name specified at the proto_register_protocol() call in order to
|
* "prefs_register_protocol()" should be used for that, so that the
|
||||||
* make the "Protocol Properties..." menu item work.
|
* preferences go under the "Protocols" subtree, and so that the
|
||||||
|
* name is the protocol name specified at the "proto_register_protocol()"
|
||||||
|
* call so that the "Protocol Properties..." menu item works.
|
||||||
*/
|
*/
|
||||||
extern module_t *prefs_register_module(const char *name, const char *title,
|
extern module_t *prefs_register_module(module_t *parent, const char *name,
|
||||||
void (*apply_cb)(void));
|
const char *title, void (*apply_cb)(void));
|
||||||
|
|
||||||
typedef void (*module_cb)(module_t *module, gpointer user_data);
|
/*
|
||||||
|
* Register a subtree that will have modules under it.
|
||||||
|
* Specify the module under which to register it or NULL to register it
|
||||||
|
* at the top level and the title used in the tab for it in a preferences
|
||||||
|
* dialog box.
|
||||||
|
*/
|
||||||
|
extern module_t *prefs_register_subtree(module_t *parent, const char *title);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register that a protocol has preferences.
|
* Register that a protocol has preferences.
|
||||||
|
@ -113,12 +122,32 @@ extern module_t *prefs_register_protocol(int id, void (*apply_cb)(void));
|
||||||
extern module_t *prefs_register_protocol_obsolete(int id);
|
extern module_t *prefs_register_protocol_obsolete(int id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call a callback function, with a specified argument, for each module.
|
* Callback function for module list scanners.
|
||||||
|
*/
|
||||||
|
typedef void (*module_cb)(module_t *module, gpointer user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call a callback function, with a specified argument, for each module
|
||||||
|
* in a list of modules. If the list is NULL, searches the top-level
|
||||||
|
* list in the display tree of modules.
|
||||||
|
*
|
||||||
|
* Ignores "obsolete" modules; their sole purpose is to allow old
|
||||||
|
* preferences for dissectors that no longer have preferences to be
|
||||||
|
* silently ignored in preference files. Does not ignore subtrees,
|
||||||
|
* as this can be used when walking the display tree of modules.
|
||||||
|
*/
|
||||||
|
extern void prefs_module_list_foreach(GList *module_list, module_cb callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call a callback function, with a specified argument, for each module
|
||||||
|
* in the list of all modules. (This list does not include subtrees.)
|
||||||
|
*
|
||||||
* Ignores "obsolete" modules; their sole purpose is to allow old
|
* Ignores "obsolete" modules; their sole purpose is to allow old
|
||||||
* preferences for dissectors that no longer have preferences to be
|
* preferences for dissectors that no longer have preferences to be
|
||||||
* silently ignored in preference files.
|
* silently ignored in preference files.
|
||||||
*/
|
*/
|
||||||
extern void prefs_module_foreach(module_cb callback, gpointer user_data);
|
extern void prefs_modules_foreach(module_cb callback, gpointer user_data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the "apply" callback function for each module if any of its
|
* Call the "apply" callback function for each module if any of its
|
||||||
|
|
Loading…
Reference in New Issue