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:
Guy Harris 2002-12-20 01:48:57 +00:00
parent e4633bc783
commit 392fee6d7a
4 changed files with 319 additions and 117 deletions

View File

@ -1,7 +1,7 @@
/* prefs_dlg.c
* 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
* 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_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
@ -102,14 +102,17 @@ static GtkWidget *prefs_w;
static e_prefs saved_prefs;
struct ct_struct {
GtkWidget *main_vb;
GtkWidget *notebook;
GtkWidget *tree;
#if GTK_MAJOR_VERSION >= 2
GtkTreeIter proto_iter;
#endif
#if GTK_MAJOR_VERSION < 2
GtkCTreeNode *node;
#else
GtkTreeIter iter;
#endif
GtkTooltips *tooltips;
gint page;
gboolean is_protocol;
};
static void
@ -203,57 +206,108 @@ static void
module_prefs_show(module_t *module, gpointer user_data)
{
struct ct_struct *cts = user_data;
struct ct_struct child_cts;
GtkWidget *main_vb, *main_tb, *frame;
gchar label_str[MAX_TREE_NODE_NAME_LEN];
#if GTK_MAJOR_VERSION < 2
gchar *label_ptr = label_str;
gchar *label_ptr = label_str;
GtkCTreeNode *ct_node;
#else
GtkTreeStore *model;
GtkTreeIter iter;
#endif
/* 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);
gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), frame, NULL);
/*
* Add this module to the tree.
*/
strcpy(label_str, module->title);
#if GTK_MAJOR_VERSION < 2
ct_node = gtk_ctree_insert_node(GTK_CTREE(cts->tree), cts->node, NULL,
&label_ptr, 5, NULL, NULL, NULL, NULL, TRUE, TRUE);
gtk_ctree_node_set_row_data(GTK_CTREE(cts->tree), ct_node,
GINT_TO_POINTER(cts->page));
&label_ptr, 5, NULL, NULL, NULL, NULL, !module->is_subtree,
FALSE);
#else
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_set(model, &iter, 0, label_str, 1, cts->page, -1);
gtk_tree_store_append(model, &iter, &cts->iter);
#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
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;
GtkWidget *print_pg, *column_pg, *stream_pg, *gui_pg;
#ifdef HAVE_LIBPCAP
@ -266,7 +320,6 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
gchar *label_ptr = label_str;
GtkCTreeNode *ct_node;
#else
GtkTreeStore *store;
GtkTreeSelection *selection;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
@ -297,14 +350,14 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
cts.tooltips = gtk_tooltips_new();
/* Container for each row of widgets */
main_vb = gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
gtk_container_add(GTK_CONTAINER(prefs_w), main_vb);
gtk_widget_show(main_vb);
cts.main_vb = gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(cts.main_vb), 5);
gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
gtk_widget_show(cts.main_vb);
/* Top row: Preferences tree and notebook */
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);
/* 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_AUTOSIZE);
#endif
cts.page = 0;
cts.page = 0;
cts.node = NULL;
gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
#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 */
notebook = prefs_nb = gtk_notebook_new();
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
gtk_widget_show(prefs_nb);
@ -474,26 +528,14 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
/* Registered prefs */
cts.notebook = prefs_nb;
strcpy(label_str, "Protocols");
#if GTK_MAJOR_VERSION < 2
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);
cts.is_protocol = FALSE;
prefs_module_list_foreach(NULL, module_prefs_show, &cts);
/* Button row: OK and cancel buttons */
bbox = gtk_hbutton_box_new();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
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);
#if GTK_MAJOR_VERSION < 2
@ -914,7 +956,7 @@ prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
#endif /* _WIN32 */
#endif /* HAVE_LIBPCAP */
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. */
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 /* HAVE_LIBPCAP */
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. */
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 /* HAVE_LIBPCAP */
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
necessary. */
@ -1151,7 +1193,7 @@ prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
copy_prefs(&prefs, &saved_prefs);
/* 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. */
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
preferences). */
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. */
prefs_w = NULL;
first_proto_prefs_page = -1;
}
struct properties_data {
@ -1258,11 +1301,11 @@ properties_cb(GtkWidget *w, gpointer dummy)
}
p.w = notebook;
p.page_num = FIRST_PROTO_PREFS_PAGE;
p.page_num = first_proto_prefs_page;
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

View File

@ -2,7 +2,7 @@
* Definitions for implementation of preference handling routines;
* 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
* By Gerald Combs <gerald@ethereal.com>
@ -29,14 +29,20 @@
struct pref_module {
const char *name; /* name of module */
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 */
GList *prefs; /* list of its preferences */
GList *prefs; /* list of its preferences or submodules */
int numprefs; /* number of non-obsolete preferences */
gboolean prefs_changed; /* if TRUE, a preference has changed since we last checked */
gboolean obsolete; /* if TRUE, this is a module that used to
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
* but no longer supports; we give different error messages for them.

196
prefs.c
View File

@ -1,7 +1,7 @@
/* prefs.c
* 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
* By Gerald Combs <gerald@ethereal.com>
@ -51,6 +51,9 @@
/* Internal functions */
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 int set_pref(gchar*, gchar*);
static GList *get_string_list(gchar *);
@ -85,10 +88,16 @@ gchar *gui_hex_dump_highlight_style_text[] =
{ "BOLD", "INVERSE", NULL };
/*
* List of modules with preference settings.
* List of all modules with preference settings.
*/
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
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);
}
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.
* Specify 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
* Specify the module under which to register it or NULL to register it
* 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.
*/
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))
{
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;
const guchar *p;
@ -114,6 +154,7 @@ prefs_register_module(const char *name, const char *title,
module = g_malloc(sizeof (module_t));
module->name = name;
module->title = title;
module->is_subtree = is_subtree;
module->apply_cb = apply_cb;
module->prefs = NULL; /* no preferences, to start */
module->numprefs = 0;
@ -121,28 +162,69 @@ prefs_register_module(const char *name, const char *title,
module->obsolete = FALSE;
/*
* Make sure that only lower-case ASCII letters, numbers,
* 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.
* Do we have a module name?
*/
for (p = name; *p != '\0'; p++)
g_assert(isascii(*p) &&
(islower(*p) || isdigit(*p) || *p == '_' || *p == '.'));
if (name != NULL) {
/*
* 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
* 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.
* Insert this module into the appropriate place in the display
* tree.
*/
g_assert(find_module(name) == NULL);
modules = g_list_insert_sorted(modules, module, module_compare_name);
if (parent == NULL) {
/*
* 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;
}
@ -150,12 +232,23 @@ prefs_register_module(const char *name, const char *title,
/*
* Register that a protocol has preferences.
*/
module_t *protocols_module;
module_t *
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),
apply_cb);
/*
* Have we yet created the "Protocols" subtree?
*/
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 = prefs_register_module(proto_get_protocol_filter_name(id),
proto_get_protocol_short_name(id),
NULL);
/*
* Have we yet created the "Protocols" subtree?
*/
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;
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
* preferences for dissectors that no longer have preferences to be
* silently ignored in preference files.
*/
void
prefs_module_foreach(module_cb callback, gpointer user_data)
prefs_modules_foreach(module_cb callback, gpointer user_data)
{
module_cb_arg_t arg;
arg.callback = callback;
arg.user_data = user_data;
g_list_foreach(modules, do_module_callback, &arg);
prefs_module_list_foreach(modules, callback, user_data);
}
static void

53
prefs.h
View File

@ -1,7 +1,7 @@
/* prefs.h
* 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
* By Gerald Combs <gerald@ethereal.com>
@ -88,18 +88,27 @@ typedef struct pref_module module_t;
/*
* Register a module that will have preferences.
* Specify 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
* Specify the module under which to register it or NULL to register it
* 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.
* Note:
* In case of dissectors, the specified name should be the protocol
* name specified at the proto_register_protocol() call in order to
* make the "Protocol Properties..." menu item work.
*
* This should not be used for dissector preferences;
* "prefs_register_protocol()" should be used for that, so that the
* 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,
void (*apply_cb)(void));
extern module_t *prefs_register_module(module_t *parent, const char *name,
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.
@ -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);
/*
* 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
* preferences for dissectors that no longer have preferences to be
* 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