Give a better error message for invalid characters in preference module names.
[metze/wireshark/wip.git] / epan / prefs.c
1 /* prefs.c
2  * Routines for handling preferences
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28
29 #include <glib.h>
30
31 #include <stdio.h>
32 #include <wsutil/filesystem.h>
33 #include <epan/address.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/oids.h>
36 #ifdef HAVE_GEOIP
37 #include <epan/geoip_db.h>
38 #endif
39 #include <epan/packet.h>
40 #include <epan/prefs.h>
41 #include <epan/proto.h>
42 #include <epan/strutil.h>
43 #include <epan/column.h>
44 #include <epan/decode_as.h>
45 #include "print.h"
46 #include <wsutil/file_util.h>
47 #include <wsutil/ws_printf.h> /* ws_g_warning */
48 #include <wsutil/report_message.h>
49
50 #include <epan/prefs-int.h>
51 #include <epan/uat-int.h>
52
53 #include "epan/filter_expressions.h"
54
55 #include "epan/wmem/wmem.h"
56 #include <epan/stats_tree.h>
57
58 /* Internal functions */
59 static module_t *find_subtree(module_t *parent, const char *tilte);
60 static module_t *prefs_register_module_or_subtree(module_t *parent,
61     const char *name, const char *title, const char *description, gboolean is_subtree,
62     void (*apply_cb)(void), gboolean use_gui);
63 static void prefs_register_modules(void);
64 static prefs_set_pref_e set_pref(gchar*, const gchar*, void *, gboolean);
65 static void free_col_info(GList *);
66 static void pre_init_prefs(void);
67 static gboolean prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt);
68 static gboolean parse_column_format(fmt_data *cfmt, const char *fmt);
69 static void try_convert_to_custom_column(gpointer *el_data);
70
71 #define IS_PREF_OBSOLETE(p) ((p) & PREF_OBSOLETE)
72 #define SET_PREF_OBSOLETE(p) ((p) |= PREF_OBSOLETE)
73 #define RESET_PREF_OBSOLETE(p) ((p) &= ~PREF_OBSOLETE)
74
75 #define PF_NAME         "preferences"
76 #define OLD_GPF_NAME    "wireshark.conf" /* old name for global preferences file */
77
78 static gboolean prefs_initialized = FALSE;
79 static gchar *gpf_path = NULL;
80 static gchar *cols_hidden_list = NULL;
81
82 /*
83  * XXX - variables to allow us to attempt to interpret the first
84  * "mgcp.{tcp,udp}.port" in a preferences file as
85  * "mgcp.{tcp,udp}.gateway_port" and the second as
86  * "mgcp.{tcp,udp}.callagent_port".
87  */
88 static int mgcp_tcp_port_count;
89 static int mgcp_udp_port_count;
90
91 e_prefs prefs;
92
93 static const enum_val_t gui_ptree_line_style[] = {
94     {"NONE", "NONE", 0},
95     {"SOLID", "SOLID", 1},
96     {"DOTTED", "DOTTED", 2},
97     {"TABBED", "TABBED", 3},
98     {NULL, NULL, -1}
99 };
100
101 static const enum_val_t gui_ptree_expander_style[] = {
102     {"NONE", "NONE", 0},
103     {"SQUARE", "SQUARE", 1},
104     {"TRIANGLE", "TRIANGLE", 2},
105     {"CIRCULAR", "CIRCULAR", 3},
106     {NULL, NULL, -1}
107 };
108
109 static const enum_val_t gui_hex_dump_highlight_style[] = {
110     {"BOLD", "BOLD", 0},
111     {"INVERSE", "INVERSE", 1},
112     {NULL, NULL, -1}
113 };
114
115 static const enum_val_t gui_console_open_type[] = {
116     {"NEVER", "NEVER", console_open_never},
117     {"AUTOMATIC", "AUTOMATIC", console_open_auto},
118     {"ALWAYS", "ALWAYS", console_open_always},
119     {NULL, NULL, -1}
120 };
121
122 static const enum_val_t gui_version_placement_type[] = {
123     {"WELCOME", "WELCOME", version_welcome_only},
124     {"TITLE", "TITLE", version_title_only},
125     {"BOTH", "BOTH", version_both},
126     {"NEITHER", "NEITHER", version_neither},
127     {NULL, NULL, -1}
128 };
129
130 static const enum_val_t gui_fileopen_style[] = {
131     {"LAST_OPENED", "LAST_OPENED", 0},
132     {"SPECIFIED", "SPECIFIED", 1},
133     {NULL, NULL, -1}
134 };
135
136 /* GTK knows of two ways representing "both", vertical and horizontal aligned.
137  * as this may not work on other guis, we use only "both" in general here */
138 static const enum_val_t gui_toolbar_style[] = {
139     {"ICONS", "ICONS", 0},
140     {"TEXT", "TEXT", 1},
141     {"BOTH", "BOTH", 2},
142     {NULL, NULL, -1}
143 };
144
145 static const enum_val_t gui_layout_content[] = {
146     {"NONE", "NONE", 0},
147     {"PLIST", "PLIST", 1},
148     {"PDETAILS", "PDETAILS", 2},
149     {"PBYTES", "PBYTES", 3},
150     {NULL, NULL, -1}
151 };
152
153 static const enum_val_t gui_update_channel[] = {
154     {"DEVELOPMENT", "DEVELOPMENT", UPDATE_CHANNEL_DEVELOPMENT},
155     {"STABLE", "STABLE", UPDATE_CHANNEL_STABLE},
156     {NULL, NULL, -1}
157 };
158
159 #if defined(HAVE_PCAP_CREATE)
160 /* Can set monitor mode and buffer size. */
161 static gint num_capture_cols = 7;
162 static const gchar *capture_cols[7] = {
163     "INTERFACE",
164     "LINK",
165     "PMODE",
166     "SNAPLEN",
167     "MONITOR",
168     "BUFFER",
169     "FILTER"
170 };
171 #define CAPTURE_COL_TYPE_DESCRIPTION \
172     "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
173 #elif defined(CAN_SET_CAPTURE_BUFFER_SIZE)
174 /* Can set buffer size but not monitor mode. */
175 static gint num_capture_cols = 6;
176 static const gchar *capture_cols[6] = {
177     "INTERFACE",
178     "LINK",
179     "PMODE",
180     "SNAPLEN",
181     "BUFFER",
182     "FILTER"
183 };
184 #define CAPTURE_COL_TYPE_DESCRIPTION \
185     "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, BUFFER, FILTER\n"
186 #else
187 /* Can neither set buffer size nor monitor mode. */
188 static gint num_capture_cols = 5;
189 static const gchar *capture_cols[5] = {
190     "INTERFACE",
191     "LINK",
192     "PMODE",
193     "SNAPLEN",
194     "FILTER"
195 };
196 #define CAPTURE_COL_TYPE_DESCRIPTION \
197     "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, FILTER\n"
198 #endif
199
200 static const enum_val_t gui_packet_list_elide_mode[] = {
201     {"LEFT", "LEFT", ELIDE_LEFT},
202     {"RIGHT", "RIGHT", ELIDE_RIGHT},
203     {"MIDDLE", "MIDDLE", ELIDE_MIDDLE},
204     {"NONE", "NONE", ELIDE_NONE},
205     {NULL, NULL, -1}
206 };
207
208 /** Struct to hold preference data */
209 struct preference {
210     const char *name;                /**< name of preference */
211     const char *title;               /**< title to use in GUI */
212     const char *description;         /**< human-readable description of preference */
213     int ordinal;                     /**< ordinal number of this preference */
214     int type;                        /**< type of that preference */
215     gui_type_t gui;                  /**< type of the GUI (QT, GTK or both) the preference is registered for */
216     union {                          /* The Qt preference code assumes that these will all be pointers (and unique) */
217         guint *uint;
218         gboolean *boolp;
219         gint *enump;
220         char **string;
221         range_t **range;
222         struct epan_uat* uat;
223         color_t *colorp;
224         GList** list;
225     } varp;                          /**< pointer to variable storing the value */
226     union {
227         guint uint;
228         gboolean boolval;
229         gint enumval;
230         char *string;
231         range_t *range;
232         color_t color;
233         GList* list;
234     } stashed_val;                     /**< original value, when editing from the GUI */
235     union {
236         guint uint;
237         gboolean boolval;
238         gint enumval;
239         char *string;
240         range_t *range;
241         color_t color;
242         GList* list;
243     } default_val;                   /**< the default value of the preference */
244     union {
245       guint base;                    /**< input/output base, for PREF_UINT */
246       guint32 max_value;             /**< maximum value of a range */
247       struct {
248         const enum_val_t *enumvals;  /**< list of name & values */
249         gboolean radio_buttons;      /**< TRUE if it should be shown as
250                                           radio buttons rather than as an
251                                           option menu or combo box in
252                                           the preferences tab */
253       } enum_info;                   /**< for PREF_ENUM */
254     } info;                          /**< display/text file information */
255     struct pref_custom_cbs custom_cbs;   /**< for PREF_CUSTOM */
256     void    *control;                /**< handle for GUI control for this preference. GTK+ only? */
257 };
258
259 const char* prefs_get_description(pref_t *pref)
260 {
261     return pref->description;
262 }
263
264 const char* prefs_get_title(pref_t *pref)
265 {
266     return pref->title;
267 }
268
269 int prefs_get_type(pref_t *pref)
270 {
271     return pref->type;
272 }
273
274 gui_type_t prefs_get_gui_type(pref_t *pref)
275 {
276     return pref->gui;
277 }
278
279 const char* prefs_get_name(pref_t *pref)
280 {
281     return pref->name;
282 }
283
284 guint32 prefs_get_max_value(pref_t *pref)
285 {
286     return pref->info.max_value;
287 }
288
289 void* prefs_get_control(pref_t *pref)
290 {
291     return pref->control;
292 }
293
294 void prefs_set_control(pref_t *pref, void* control)
295 {
296     pref->control = control;
297 }
298
299 int prefs_get_ordinal(pref_t *pref)
300 {
301     return pref->ordinal;
302 }
303
304 /*
305  * List of all modules with preference settings.
306  */
307 static wmem_tree_t *prefs_modules = NULL;
308
309 /*
310  * List of all modules that should show up at the top level of the
311  * tree in the preference dialog box.
312  */
313 static wmem_tree_t *prefs_top_level_modules = NULL;
314
315 /** Sets up memory used by proto routines. Called at program startup */
316 void
317 prefs_init(void)
318 {
319     memset(&prefs, 0, sizeof(prefs));
320     prefs_modules = wmem_tree_new(wmem_epan_scope());
321     prefs_top_level_modules = wmem_tree_new(wmem_epan_scope());
322 }
323
324 /*
325  * Free the strings for a string-like preference.
326  */
327 static void
328 free_string_like_preference(pref_t *pref)
329 {
330     g_free(*pref->varp.string);
331     *pref->varp.string = NULL;
332     g_free(pref->default_val.string);
333     pref->default_val.string = NULL;
334 }
335
336 static void
337 free_pref(gpointer data, gpointer user_data _U_)
338 {
339     pref_t *pref = (pref_t *)data;
340     int type = pref->type;
341
342     /* we reset the PREF_OBSOLETE bit in order to allow the original preference to be freed */
343     RESET_PREF_OBSOLETE(type);
344
345     switch (type) {
346     case PREF_BOOL:
347     case PREF_ENUM:
348     case PREF_UINT:
349     case PREF_DECODE_AS_UINT:
350     case PREF_STATIC_TEXT:
351     case PREF_UAT:
352     case PREF_COLOR:
353         break;
354     case PREF_STRING:
355     case PREF_FILENAME:
356     case PREF_DIRNAME:
357         g_free(*pref->varp.string);
358         *pref->varp.string = NULL;
359         g_free(pref->default_val.string);
360         pref->default_val.string = NULL;
361         break;
362     case PREF_RANGE:
363     case PREF_DECODE_AS_RANGE:
364         wmem_free(wmem_epan_scope(), *pref->varp.range);
365         *pref->varp.range = NULL;
366         wmem_free(wmem_epan_scope(), pref->default_val.range);
367         pref->default_val.range = NULL;
368         break;
369     case PREF_CUSTOM:
370         if (strcmp(pref->name, "columns") == 0)
371           pref->stashed_val.boolval = TRUE;
372         pref->custom_cbs.free_cb(pref);
373         break;
374     }
375
376     g_free(pref);
377 }
378
379 static guint
380 free_module_prefs(module_t *module, gpointer data _U_)
381 {
382     if (module->prefs) {
383         g_list_foreach(module->prefs, free_pref, NULL);
384         g_list_free(module->prefs);
385     }
386     module->prefs = NULL;
387     module->numprefs = 0;
388     if (module->submodules) {
389         prefs_modules_foreach_submodules(module, free_module_prefs, NULL);
390     }
391     /*  We don't free the actual module: its submodules pointer points to
392         a wmem_tree and the module itself is stored in a wmem_tree
393      */
394
395     return 0;
396 }
397
398 /** Frees memory used by proto routines. Called at program shutdown */
399 void
400 prefs_cleanup(void)
401 {
402     /*  This isn't strictly necessary since we're exiting anyway, but let's
403      *  do what clean up we can.
404      */
405     prefs_modules_foreach(free_module_prefs, NULL);
406
407     /* Clean the uats */
408     uat_cleanup();
409
410     g_free(prefs.saved_at_version);
411     g_free(gpf_path);
412     gpf_path = NULL;
413 }
414
415 /*
416  * Register a module that will have preferences.
417  * Specify the module under which to register it or NULL to register it
418  * at the top level, the name used for the module in the preferences file,
419  * the title used in the tab for it in a preferences dialog box, and a
420  * routine to call back when we apply the preferences.
421  */
422 module_t *
423 prefs_register_module(module_t *parent, const char *name, const char *title,
424                       const char *description, void (*apply_cb)(void),
425                       const gboolean use_gui)
426 {
427     return prefs_register_module_or_subtree(parent, name, title, description,
428                                             FALSE, apply_cb, use_gui);
429 }
430
431 static void
432 prefs_deregister_module(module_t *parent, const char *name, const char *title)
433 {
434     /* Remove this module from the list of all modules */
435     module_t *module = (module_t *)wmem_tree_remove_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
436
437     if (!module)
438         return;
439
440     if (parent == NULL) {
441         /* Remove from top */
442         wmem_tree_remove_string(prefs_top_level_modules, title, WMEM_TREE_STRING_NOCASE);
443     } else if (parent->submodules) {
444         /* Remove from parent */
445         wmem_tree_remove_string(parent->submodules, title, WMEM_TREE_STRING_NOCASE);
446     }
447
448     free_module_prefs(module, NULL);
449     wmem_free(wmem_epan_scope(), module);
450 }
451
452 /*
453  * Register a subtree that will have modules under it.
454  * Specify the module under which to register it or NULL to register it
455  * at the top level and the title used in the tab for it in a preferences
456  * dialog box.
457  */
458 module_t *
459 prefs_register_subtree(module_t *parent, const char *title, const char *description,
460                        void (*apply_cb)(void))
461 {
462     return prefs_register_module_or_subtree(parent, NULL, title, description,
463                                             TRUE, apply_cb,
464                                             parent ? parent->use_gui : FALSE);
465 }
466
467 static module_t *
468 prefs_register_module_or_subtree(module_t *parent, const char *name,
469                                  const char *title, const char *description,
470                                  gboolean is_subtree, void (*apply_cb)(void),
471                                  gboolean use_gui)
472 {
473     module_t *module;
474     const char *p;
475     guchar c;
476
477     /* this module may have been created as a subtree item previously */
478     if ((module = find_subtree(parent, title))) {
479         /* the module is currently a subtree */
480         module->name = name;
481         module->apply_cb = apply_cb;
482         module->description = description;
483
484         if (prefs_find_module(name) == NULL) {
485             wmem_tree_insert_string(prefs_modules, name, module,
486                                   WMEM_TREE_STRING_NOCASE);
487         }
488
489         return module;
490     }
491
492     module = wmem_new(wmem_epan_scope(), module_t);
493     module->name = name;
494     module->title = title;
495     module->description = description;
496     module->apply_cb = apply_cb;
497     module->prefs = NULL;    /* no preferences, to start */
498     module->parent = parent;
499     module->submodules = NULL;    /* no submodules, to start */
500     module->numprefs = 0;
501     module->prefs_changed = FALSE;
502     module->obsolete = FALSE;
503     module->use_gui = use_gui;
504
505     /*
506      * Do we have a module name?
507      */
508     if (name != NULL) {
509         /*
510          * Yes.
511          * Make sure that only lower-case ASCII letters, numbers,
512          * underscores, hyphens, and dots appear in the name.
513          *
514          * Crash if there is, as that's an error in the code;
515          * you can make the title a nice string with capitalization,
516          * white space, punctuation, etc., but the name can be used
517          * on the command line, and shouldn't require quoting,
518          * shifting, etc.
519          */
520         for (p = name; (c = *p) != '\0'; p++) {
521             if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '_' ||
522                   c == '-' || c == '.'))
523                 g_error("Preference module \"%s\" contains invalid characters", name);
524         }
525
526         /*
527          * Make sure there's not already a module with that
528          * name.  Crash if there is, as that's an error in the
529          * code, and the code has to be fixed not to register
530          * more than one module with the same name.
531          *
532          * We search the list of all modules; the subtree stuff
533          * doesn't require preferences in subtrees to have names
534          * that reflect the subtree they're in (that would require
535          * protocol preferences to have a bogus "protocol.", or
536          * something such as that, to be added to all their names).
537          */
538         g_assert(prefs_find_module(name) == NULL);
539
540         /*
541          * Insert this module in the list of all modules.
542          */
543         wmem_tree_insert_string(prefs_modules, name, module, WMEM_TREE_STRING_NOCASE);
544     } else {
545         /*
546          * This has no name, just a title; check to make sure it's a
547          * subtree, and crash if it's not.
548          */
549         g_assert(is_subtree);
550     }
551
552     /*
553      * Insert this module into the appropriate place in the display
554      * tree.
555      */
556     if (parent == NULL) {
557         /*
558          * It goes at the top.
559          */
560         wmem_tree_insert_string(prefs_top_level_modules, title, module, WMEM_TREE_STRING_NOCASE);
561     } else {
562         /*
563          * It goes into the list for this module.
564          */
565
566         if (parent->submodules == NULL)
567             parent->submodules = wmem_tree_new(wmem_epan_scope());
568
569         wmem_tree_insert_string(parent->submodules, title, module, WMEM_TREE_STRING_NOCASE);
570     }
571
572     return module;
573 }
574
575 /*
576  * Register that a protocol has preferences.
577  */
578 module_t *protocols_module = NULL;
579
580 module_t *
581 prefs_register_protocol(int id, void (*apply_cb)(void))
582 {
583     protocol_t *protocol;
584
585     /*
586      * Have we yet created the "Protocols" subtree?
587      */
588     if (protocols_module == NULL) {
589         /*
590          * No.  Register Protocols subtree as well as any preferences
591          * for non-dissector modules.
592          */
593         pre_init_prefs();
594         prefs_register_modules();
595     }
596     protocol = find_protocol_by_id(id);
597     return prefs_register_module(protocols_module,
598                                  proto_get_protocol_filter_name(id),
599                                  proto_get_protocol_short_name(protocol),
600                                  proto_get_protocol_name(id), apply_cb, TRUE);
601 }
602
603 void
604 prefs_deregister_protocol (int id)
605 {
606     protocol_t *protocol = find_protocol_by_id(id);
607     prefs_deregister_module (protocols_module,
608                              proto_get_protocol_filter_name(id),
609                              proto_get_protocol_short_name(protocol));
610 }
611
612 module_t *
613 prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
614 {
615     protocol_t *protocol;
616     module_t   *subtree_module;
617     module_t   *new_module;
618     char       *sep = NULL, *ptr = NULL, *orig = NULL;
619
620     /*
621      * Have we yet created the "Protocols" subtree?
622      * XXX - can we just do this by registering Protocols/{subtree}?
623      * If not, why not?
624      */
625     if (protocols_module == NULL) {
626         /*
627          * No.  Register Protocols subtree as well as any preferences
628          * for non-dissector modules.
629          */
630         pre_init_prefs();
631         prefs_register_modules();
632     }
633
634     subtree_module = protocols_module;
635
636     if (subtree) {
637         /* take a copy of the buffer, orig keeps a base pointer while ptr
638          * walks through the string */
639         orig = ptr = g_strdup(subtree);
640
641         while (ptr && *ptr) {
642
643             if ((sep = strchr(ptr, '/')))
644                 *sep++ = '\0';
645
646             if (!(new_module = find_subtree(subtree_module, ptr))) {
647                 /*
648                  * There's no such module; create it, with the description
649                  * being the name (if it's later registered explicitly
650                  * with a description, that will override it).
651                  */
652                 ptr = wmem_strdup(wmem_epan_scope(), ptr),
653                 new_module = prefs_register_subtree(subtree_module, ptr, ptr, NULL);
654             }
655
656             subtree_module = new_module;
657             ptr = sep;
658
659         }
660
661         g_free(orig);
662     }
663
664     protocol = find_protocol_by_id(id);
665     return prefs_register_module(subtree_module,
666                                  proto_get_protocol_filter_name(id),
667                                  proto_get_protocol_short_name(protocol),
668                                  proto_get_protocol_name(id), apply_cb, TRUE);
669 }
670
671
672 /*
673  * Register that a protocol used to have preferences but no longer does,
674  * by creating an "obsolete" module for it.
675  */
676 module_t *
677 prefs_register_protocol_obsolete(int id)
678 {
679     module_t *module;
680     protocol_t *protocol;
681
682     /*
683      * Have we yet created the "Protocols" subtree?
684      */
685     if (protocols_module == NULL) {
686         /*
687          * No.  Register Protocols subtree as well as any preferences
688          * for non-dissector modules.
689          */
690         pre_init_prefs();
691         prefs_register_modules();
692     }
693     protocol = find_protocol_by_id(id);
694     module = prefs_register_module(protocols_module,
695                                    proto_get_protocol_filter_name(id),
696                                    proto_get_protocol_short_name(protocol),
697                                    proto_get_protocol_name(id), NULL, TRUE);
698     module->obsolete = TRUE;
699     return module;
700 }
701
702 /*
703  * Register that a statistical tap has preferences.
704  *
705  * "name" is a name for the tap to use on the command line with "-o"
706  * and in preference files.
707  *
708  * "title" is a short human-readable name for the tap.
709  *
710  * "description" is a longer human-readable description of the tap.
711  */
712 module_t *stats_module = NULL;
713
714 module_t *
715 prefs_register_stat(const char *name, const char *title,
716                     const char *description, void (*apply_cb)(void))
717 {
718     /*
719      * Have we yet created the "Statistics" subtree?
720      */
721     if (stats_module == NULL) {
722         /*
723          * No.  Register Statistics subtree as well as any preferences
724          * for non-dissector modules.
725          */
726         pre_init_prefs();
727         prefs_register_modules();
728     }
729
730     return prefs_register_module(stats_module, name, title, description,
731                                  apply_cb, TRUE);
732 }
733
734 module_t *
735 prefs_find_module(const char *name)
736 {
737     return (module_t *)wmem_tree_lookup_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
738 }
739
740 static module_t *
741 find_subtree(module_t *parent, const char *name)
742 {
743     return (module_t *)wmem_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, WMEM_TREE_STRING_NOCASE);
744 }
745
746 /*
747  * Call a callback function, with a specified argument, for each module
748  * in a list of modules.  If the list is NULL, searches the top-level
749  * list in the display tree of modules.  If any callback returns a
750  * non-zero value, we stop and return that value, otherwise we
751  * return 0.
752  *
753  * Ignores "obsolete" modules; their sole purpose is to allow old
754  * preferences for dissectors that no longer have preferences to be
755  * silently ignored in preference files.  Does not ignore subtrees,
756  * as this can be used when walking the display tree of modules.
757  */
758
759 typedef struct {
760     module_cb callback;
761     gpointer user_data;
762     guint ret;
763 } call_foreach_t;
764
765 static gboolean
766 call_foreach_cb(const void *key _U_, void *value, void *data)
767 {
768     module_t *module = (module_t*)value;
769     call_foreach_t *call_data = (call_foreach_t*)data;
770
771     if (!module->obsolete)
772         call_data->ret = (*call_data->callback)(module, call_data->user_data);
773
774     return (call_data->ret != 0);
775 }
776
777 static guint
778 prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
779                           gpointer user_data)
780 {
781     call_foreach_t call_data;
782
783     if (module_list == NULL)
784         module_list = prefs_top_level_modules;
785
786     call_data.callback = callback;
787     call_data.user_data = user_data;
788     call_data.ret = 0;
789     wmem_tree_foreach(module_list, call_foreach_cb, &call_data);
790     return call_data.ret;
791 }
792
793 /*
794  * Returns TRUE if module has any submodules
795  */
796 gboolean
797 prefs_module_has_submodules(module_t *module)
798 {
799     if (module->submodules == NULL) {
800         return FALSE;
801     }
802
803     if (wmem_tree_is_empty(module->submodules)) {
804         return FALSE;
805     }
806
807     return TRUE;
808 }
809
810 /*
811  * Call a callback function, with a specified argument, for each module
812  * in the list of all modules.  (This list does not include subtrees.)
813  *
814  * Ignores "obsolete" modules; their sole purpose is to allow old
815  * preferences for dissectors that no longer have preferences to be
816  * silently ignored in preference files.
817  */
818 guint
819 prefs_modules_foreach(module_cb callback, gpointer user_data)
820 {
821     return prefs_module_list_foreach(prefs_modules, callback, user_data);
822 }
823
824 /*
825  * Call a callback function, with a specified argument, for each submodule
826  * of specified modules.  If the module is NULL, goes through the top-level
827  * list in the display tree of modules.
828  *
829  * Ignores "obsolete" modules; their sole purpose is to allow old
830  * preferences for dissectors that no longer have preferences to be
831  * silently ignored in preference files.  Does not ignore subtrees,
832  * as this can be used when walking the display tree of modules.
833  */
834 guint
835 prefs_modules_foreach_submodules(module_t *module, module_cb callback,
836                                  gpointer user_data)
837 {
838     return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data);
839 }
840
841 static gboolean
842 call_apply_cb(const void *key _U_, void *value, void *data _U_)
843 {
844     module_t *module = (module_t *)value;
845
846     if (module->obsolete)
847         return FALSE;
848     if (module->prefs_changed) {
849         if (module->apply_cb != NULL)
850             (*module->apply_cb)();
851         module->prefs_changed = FALSE;
852     }
853     if (module->submodules)
854         wmem_tree_foreach(module->submodules, call_apply_cb, NULL);
855     return FALSE;
856 }
857
858 /*
859  * Call the "apply" callback function for each module if any of its
860  * preferences have changed, and then clear the flag saying its
861  * preferences have changed, as the module has been notified of that
862  * fact.
863  */
864 void
865 prefs_apply_all(void)
866 {
867     wmem_tree_foreach(prefs_modules, call_apply_cb, NULL);
868 }
869
870 /*
871  * Call the "apply" callback function for a specific module if any of
872  * its preferences have changed, and then clear the flag saying its
873  * preferences have changed, as the module has been notified of that
874  * fact.
875  */
876 void
877 prefs_apply(module_t *module)
878 {
879     if (module && module->prefs_changed)
880         call_apply_cb(NULL, module, NULL);
881 }
882
883 /*
884  * Register a preference in a module's list of preferences.
885  * If it has a title, give it an ordinal number; otherwise, it's a
886  * preference that won't show up in the UI, so it shouldn't get an
887  * ordinal number (the ordinal should be the ordinal in the set of
888  * *visible* preferences).
889  */
890 static pref_t *
891 register_preference(module_t *module, const char *name, const char *title,
892                     const char *description, int type)
893 {
894     pref_t *preference;
895     const gchar *p;
896     const char *name_prefix = (module->name != NULL) ? module->name : module->parent->name;
897
898     preference = g_new(pref_t,1);
899     preference->name = name;
900     preference->title = title;
901     preference->description = description;
902     preference->type = type;
903     preference->gui = GUI_ALL;  /* default */
904     if (title != NULL)
905         preference->ordinal = module->numprefs;
906     else
907         preference->ordinal = -1;    /* no ordinal for you */
908
909     /*
910      * Make sure that only lower-case ASCII letters, numbers,
911      * underscores, and dots appear in the preference name.
912      *
913      * Crash if there is, as that's an error in the code;
914      * you can make the title and description nice strings
915      * with capitalization, white space, punctuation, etc.,
916      * but the name can be used on the command line,
917      * and shouldn't require quoting, shifting, etc.
918      */
919     for (p = name; *p != '\0'; p++)
920         if (!(g_ascii_islower(*p) || g_ascii_isdigit(*p) || *p == '_' || *p == '.'))
921             g_error("Preference \"%s.%s\" contains invalid characters", module->name, name);
922
923     /*
924      * Make sure there's not already a preference with that
925      * name.  Crash if there is, as that's an error in the
926      * code, and the code has to be fixed not to register
927      * more than one preference with the same name.
928      */
929     if (prefs_find_preference(module, name) != NULL)
930         g_error("Preference %s has already been registered", name);
931
932     if ((!IS_PREF_OBSOLETE(type)) &&
933         /* Don't compare if it's a subtree */
934         (module->name != NULL)) {
935         /*
936          * Make sure the preference name doesn't begin with the
937          * module name, as that's redundant and Just Silly.
938          */
939         if (!((strncmp(name, module->name, strlen(module->name)) != 0) ||
940             (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_'))))
941             g_error("Preference %s begins with the module name", name);
942     }
943
944     /* The title shows up in the preferences dialog. Make sure it's UI-friendly. */
945     if (preference->title) {
946         const char *cur_char;
947         if (preference->type != PREF_STATIC_TEXT && g_utf8_strlen(preference->title, -1) > 80) { // Arbitrary.
948             g_error("Title for preference %s.%s is too long: %s", name_prefix, preference->name, preference->title);
949         }
950
951         if (!g_utf8_validate(preference->title, -1, NULL)) {
952             g_error("Title for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
953         }
954
955         for (cur_char = preference->title; *cur_char; cur_char = g_utf8_next_char(cur_char)) {
956             if (!g_unichar_isprint(g_utf8_get_char(cur_char))) {
957                 g_error("Title for preference %s.%s isn't printable UTF-8.", name_prefix, preference->name);
958             }
959         }
960     }
961
962     if (preference->description) {
963         if (!g_utf8_validate(preference->description, -1, NULL)) {
964             g_error("Description for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
965         }
966     }
967
968     /*
969      * We passed all of our checks. Add the preference.
970      */
971     module->prefs = g_list_append(module->prefs, preference);
972     if (title != NULL)
973         module->numprefs++;
974
975     return preference;
976 }
977
978 /*
979  * Find a preference in a module's list of preferences, given the module
980  * and the preference's name.
981  */
982 typedef struct {
983     GList *list_entry;
984     const char *name;
985     module_t *submodule;
986 } find_pref_arg_t;
987
988 static gint
989 preference_match(gconstpointer a, gconstpointer b)
990 {
991     const pref_t *pref = (const pref_t *)a;
992     const char *name = (const char *)b;
993
994     return strcmp(name, pref->name);
995 }
996
997 static gboolean
998 module_find_pref_cb(const void *key _U_, void *value, void *data)
999 {
1000     find_pref_arg_t* arg = (find_pref_arg_t*)data;
1001     GList *list_entry;
1002     module_t *module = (module_t *)value;
1003
1004     if (module == NULL)
1005         return FALSE;
1006
1007     list_entry = g_list_find_custom(module->prefs, arg->name,
1008         preference_match);
1009
1010     if (list_entry == NULL)
1011         return FALSE;
1012
1013     arg->list_entry = list_entry;
1014     arg->submodule = module;
1015     return TRUE;
1016 }
1017
1018 /* Tries to find a preference, setting containing_module to the (sub)module
1019  * holding this preference. */
1020 static struct preference *
1021 prefs_find_preference_with_submodule(module_t *module, const char *name,
1022         module_t **containing_module)
1023 {
1024     find_pref_arg_t arg;
1025     GList *list_entry;
1026
1027     if (module == NULL)
1028         return NULL;    /* invalid parameters */
1029
1030     list_entry = g_list_find_custom(module->prefs, name,
1031         preference_match);
1032     arg.submodule = NULL;
1033
1034     if (list_entry == NULL)
1035     {
1036         arg.list_entry = NULL;
1037         if (module->submodules != NULL)
1038         {
1039             arg.name = name;
1040             wmem_tree_foreach(module->submodules, module_find_pref_cb, &arg);
1041         }
1042
1043         list_entry = arg.list_entry;
1044     }
1045
1046     if (list_entry == NULL)
1047         return NULL;    /* no such preference */
1048
1049     if (containing_module)
1050         *containing_module = arg.submodule ? arg.submodule : module;
1051
1052     return (struct preference *) list_entry->data;
1053 }
1054
1055 struct preference *
1056 prefs_find_preference(module_t *module, const char *name)
1057 {
1058     return prefs_find_preference_with_submodule(module, name, NULL);
1059 }
1060
1061 /*
1062  * Returns TRUE if the given protocol has registered preferences
1063  */
1064 gboolean
1065 prefs_is_registered_protocol(const char *name)
1066 {
1067     module_t *m = prefs_find_module(name);
1068
1069     return (m != NULL && !m->obsolete);
1070 }
1071
1072 /*
1073  * Returns the module title of a registered protocol
1074  */
1075 const char *
1076 prefs_get_title_by_name(const char *name)
1077 {
1078     module_t *m = prefs_find_module(name);
1079
1080     return (m != NULL && !m->obsolete) ? m->title : NULL;
1081 }
1082
1083 /*
1084  * Register a preference with an unsigned integral value.
1085  */
1086 void
1087 prefs_register_uint_preference(module_t *module, const char *name,
1088                                const char *title, const char *description,
1089                                guint base, guint *var)
1090 {
1091     pref_t *preference;
1092
1093     preference = register_preference(module, name, title, description,
1094                                      PREF_UINT);
1095     preference->varp.uint = var;
1096     preference->default_val.uint = *var;
1097     g_assert(base > 0 && base != 1 && base < 37);
1098     preference->info.base = base;
1099 }
1100
1101 /*
1102  * XXX Add a prefs_register_{uint16|port}_preference which sets max_value?
1103  */
1104
1105
1106 /*
1107  * Register a "custom" preference with a unsigned integral value.
1108  * XXX - This should be temporary until we can find a better way
1109  * to do "custom" preferences
1110  */
1111 static void
1112 prefs_register_uint_custom_preference(module_t *module, const char *name,
1113                                       const char *title, const char *description,
1114                                       struct pref_custom_cbs* custom_cbs, guint *var)
1115 {
1116     pref_t *preference;
1117
1118     preference = register_preference(module, name, title, description,
1119                                      PREF_CUSTOM);
1120
1121     preference->custom_cbs = *custom_cbs;
1122     preference->varp.uint = var;
1123     preference->default_val.uint = *var;
1124 }
1125
1126 /*
1127  * Register a preference with an Boolean value.
1128  */
1129 void
1130 prefs_register_bool_preference(module_t *module, const char *name,
1131                                const char *title, const char *description,
1132                                gboolean *var)
1133 {
1134     pref_t *preference;
1135
1136     preference = register_preference(module, name, title, description,
1137                                      PREF_BOOL);
1138     preference->varp.boolp = var;
1139     preference->default_val.boolval = *var;
1140 }
1141
1142 gboolean prefs_set_bool_value(pref_t *pref, gboolean value, pref_source_t source)
1143 {
1144     gboolean changed = FALSE;
1145
1146     switch (source)
1147     {
1148     case pref_default:
1149         if (pref->default_val.boolval != value) {
1150             pref->default_val.boolval = value;
1151             changed = TRUE;
1152         }
1153         break;
1154     case pref_stashed:
1155         if (pref->stashed_val.boolval != value) {
1156             pref->stashed_val.boolval = value;
1157             changed = TRUE;
1158         }
1159         break;
1160     case pref_current:
1161         if (*pref->varp.boolp != value) {
1162             *pref->varp.boolp = value;
1163             changed = TRUE;
1164         }
1165         break;
1166     default:
1167         g_assert_not_reached();
1168         break;
1169     }
1170
1171     return changed;
1172 }
1173
1174 void prefs_invert_bool_value(pref_t *pref, pref_source_t source)
1175 {
1176     switch (source)
1177     {
1178     case pref_default:
1179         pref->default_val.boolval = !pref->default_val.boolval;
1180         break;
1181     case pref_stashed:
1182         pref->stashed_val.boolval = !pref->stashed_val.boolval;
1183         break;
1184     case pref_current:
1185         *pref->varp.boolp = !(*pref->varp.boolp);
1186         break;
1187     default:
1188         g_assert_not_reached();
1189         break;
1190     }
1191 }
1192
1193 gboolean prefs_get_bool_value(pref_t *pref, pref_source_t source)
1194 {
1195     switch (source)
1196     {
1197     case pref_default:
1198         return pref->default_val.boolval;
1199         break;
1200     case pref_stashed:
1201         return pref->stashed_val.boolval;
1202         break;
1203     case pref_current:
1204         return *pref->varp.boolp;
1205         break;
1206     default:
1207         g_assert_not_reached();
1208         break;
1209     }
1210
1211     return FALSE;
1212 }
1213
1214 /*
1215  * Register a preference with an enumerated value.
1216  */
1217 /*
1218  * XXX Should we get rid of the radio_buttons parameter and make that
1219  * behavior automatic depending on the number of items?
1220  */
1221 void
1222 prefs_register_enum_preference(module_t *module, const char *name,
1223                                const char *title, const char *description,
1224                                gint *var, const enum_val_t *enumvals,
1225                                gboolean radio_buttons)
1226 {
1227     pref_t *preference;
1228
1229     preference = register_preference(module, name, title, description,
1230                                      PREF_ENUM);
1231     preference->varp.enump = var;
1232     preference->default_val.enumval = *var;
1233     preference->info.enum_info.enumvals = enumvals;
1234     preference->info.enum_info.radio_buttons = radio_buttons;
1235 }
1236
1237 gboolean prefs_set_enum_value(pref_t *pref, gint value, pref_source_t source)
1238 {
1239     gboolean changed = FALSE;
1240
1241     switch (source)
1242     {
1243     case pref_default:
1244         if (pref->default_val.enumval != value) {
1245             pref->default_val.enumval = value;
1246             changed = TRUE;
1247         }
1248         break;
1249     case pref_stashed:
1250         if (pref->stashed_val.enumval != value) {
1251             pref->stashed_val.enumval = value;
1252             changed = TRUE;
1253         }
1254         break;
1255     case pref_current:
1256         if (*pref->varp.enump != value) {
1257             *pref->varp.enump = value;
1258             changed = TRUE;
1259         }
1260         break;
1261     default:
1262         g_assert_not_reached();
1263         break;
1264     }
1265
1266     return changed;
1267 }
1268
1269 gint prefs_get_enum_value(pref_t *pref, pref_source_t source)
1270 {
1271     switch (source)
1272     {
1273     case pref_default:
1274         return pref->default_val.enumval;
1275         break;
1276     case pref_stashed:
1277         return pref->stashed_val.enumval;
1278         break;
1279     case pref_current:
1280         return *pref->varp.enump;
1281         break;
1282     default:
1283         g_assert_not_reached();
1284         break;
1285     }
1286
1287     return 0;
1288 }
1289
1290 const enum_val_t* prefs_get_enumvals(pref_t *pref)
1291 {
1292     return pref->info.enum_info.enumvals;
1293 }
1294
1295 gboolean prefs_get_enum_radiobuttons(pref_t *pref)
1296 {
1297     return pref->info.enum_info.radio_buttons;
1298 }
1299
1300 static void
1301 register_string_like_preference(module_t *module, const char *name,
1302                                 const char *title, const char *description,
1303                                 char **var, int type,
1304                                 struct pref_custom_cbs* custom_cbs,
1305                                 gboolean free_tmp)
1306 {
1307     pref_t *pref;
1308     gchar *tmp;
1309
1310     pref = register_preference(module, name, title, description, type);
1311
1312     /*
1313      * String preference values should be non-null (as you can't
1314      * keep them null after using the preferences GUI, you can at best
1315      * have them be null strings) and freeable (as we free them
1316      * if we change them).
1317      *
1318      * If the value is a null pointer, make it a copy of a null
1319      * string, otherwise make it a copy of the value.
1320      */
1321     tmp = *var;
1322     if (*var == NULL) {
1323         *var = g_strdup("");
1324     } else {
1325         *var = g_strdup(*var);
1326     }
1327     if (free_tmp) {
1328         g_free(tmp);
1329     }
1330     pref->varp.string = var;
1331     pref->default_val.string = g_strdup(*var);
1332     pref->stashed_val.string = NULL;
1333     if (type == PREF_CUSTOM) {
1334         g_assert(custom_cbs);
1335         pref->custom_cbs = *custom_cbs;
1336     }
1337 }
1338
1339 /*
1340  * For use by UI code that sets preferences.
1341  */
1342 gboolean
1343 prefs_set_string_value(pref_t *pref, const char* value, pref_source_t source)
1344 {
1345     gboolean changed = FALSE;
1346
1347     switch (source)
1348     {
1349     case pref_default:
1350         if (*pref->default_val.string) {
1351             if (strcmp(pref->default_val.string, value) != 0) {
1352                 changed = TRUE;
1353                 g_free(pref->default_val.string);
1354                 pref->default_val.string = g_strdup(value);
1355             }
1356         } else if (value) {
1357             pref->default_val.string = g_strdup(value);
1358         }
1359         break;
1360     case pref_stashed:
1361         if (pref->stashed_val.string) {
1362             if (strcmp(pref->stashed_val.string, value) != 0) {
1363                 changed = TRUE;
1364                 g_free(pref->stashed_val.string);
1365                 pref->stashed_val.string = g_strdup(value);
1366             }
1367         } else if (value) {
1368             pref->stashed_val.string = g_strdup(value);
1369         }
1370         break;
1371     case pref_current:
1372         if (*pref->varp.string) {
1373             if (strcmp(*pref->varp.string, value) != 0) {
1374                 changed = TRUE;
1375                 g_free(*pref->varp.string);
1376                 *pref->varp.string = g_strdup(value);
1377             }
1378         } else if (value) {
1379             *pref->varp.string = g_strdup(value);
1380         }
1381         break;
1382     default:
1383         g_assert_not_reached();
1384         break;
1385     }
1386
1387     return changed;
1388 }
1389
1390 char* prefs_get_string_value(pref_t *pref, pref_source_t source)
1391 {
1392     switch (source)
1393     {
1394     case pref_default:
1395         return pref->default_val.string;
1396     case pref_stashed:
1397         return pref->stashed_val.string;
1398     case pref_current:
1399         return *pref->varp.string;
1400     default:
1401         g_assert_not_reached();
1402         break;
1403     }
1404
1405     return NULL;
1406 }
1407
1408 /*
1409  * Reset the value of a string-like preference.
1410  */
1411 static void
1412 reset_string_like_preference(pref_t *pref)
1413 {
1414     g_free(*pref->varp.string);
1415     *pref->varp.string = g_strdup(pref->default_val.string);
1416 }
1417
1418 /*
1419  * Register a preference with a character-string value.
1420  */
1421 void
1422 prefs_register_string_preference(module_t *module, const char *name,
1423                                  const char *title, const char *description,
1424                                  const char **var)
1425 {
1426 DIAG_OFF(cast-qual)
1427     register_string_like_preference(module, name, title, description,
1428                                     (char **)var, PREF_STRING, NULL, FALSE);
1429 DIAG_ON(cast-qual)
1430 }
1431
1432 /*
1433  * Register a preference with a file name (string) value.
1434  */
1435 void
1436 prefs_register_filename_preference(module_t *module, const char *name,
1437                                    const char *title, const char *description,
1438                                    const char **var)
1439 {
1440 DIAG_OFF(cast-qual)
1441     register_string_like_preference(module, name, title, description,
1442                                     (char **)var, PREF_FILENAME, NULL, FALSE);
1443 DIAG_ON(cast-qual)
1444 }
1445
1446 /*
1447  * Register a preference with a directory name (string) value.
1448  */
1449 void
1450 prefs_register_directory_preference(module_t *module, const char *name,
1451                                    const char *title, const char *description,
1452                                    const char **var)
1453 {
1454 DIAG_OFF(cast-qual)
1455     register_string_like_preference(module, name, title, description,
1456                                     (char **)var, PREF_DIRNAME, NULL, FALSE);
1457 DIAG_ON(cast-qual)
1458 }
1459
1460 /* Refactoring to handle both PREF_RANGE and PREF_DECODE_AS_RANGE */
1461 static void
1462 prefs_register_range_preference_common(module_t *module, const char *name,
1463                                 const char *title, const char *description,
1464                                 range_t **var, guint32 max_value, int type)
1465 {
1466     pref_t *preference;
1467
1468     preference = register_preference(module, name, title, description, type);
1469     preference->info.max_value = max_value;
1470
1471     /*
1472      * Range preference values should be non-null (as you can't
1473      * keep them null after using the preferences GUI, you can at best
1474      * have them be empty ranges) and freeable (as we free them
1475      * if we change them).
1476      *
1477      * If the value is a null pointer, make it an empty range.
1478      */
1479     if (*var == NULL)
1480         *var = range_empty(wmem_epan_scope());
1481     preference->varp.range = var;
1482     preference->default_val.range = range_copy(wmem_epan_scope(), *var);
1483     preference->stashed_val.range = NULL;
1484 }
1485
1486 /*
1487  * Register a preference with a ranged value.
1488  */
1489 void
1490 prefs_register_range_preference(module_t *module, const char *name,
1491                                 const char *title, const char *description,
1492                                 range_t **var, guint32 max_value)
1493 {
1494     prefs_register_range_preference_common(module, name, title,
1495                 description, var, max_value, PREF_RANGE);
1496 }
1497
1498 gboolean
1499 prefs_set_range_value_work(pref_t *pref, const gchar *value,
1500                            gboolean return_range_errors, gboolean *changed)
1501 {
1502     range_t *newrange;
1503
1504     if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1505                                return_range_errors) != CVT_NO_ERROR) {
1506         return FALSE;        /* number was bad */
1507     }
1508
1509     if (!ranges_are_equal(*pref->varp.range, newrange)) {
1510         *changed = TRUE;
1511         wmem_free(wmem_epan_scope(), *pref->varp.range);
1512         *pref->varp.range = newrange;
1513     } else {
1514         wmem_free(wmem_epan_scope(), newrange);
1515     }
1516     return TRUE;
1517 }
1518
1519 /*
1520  * For use by UI code that sets preferences.
1521  */
1522 gboolean
1523 prefs_set_stashed_range_value(pref_t *pref, const gchar *value)
1524 {
1525     range_t *newrange;
1526
1527     if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1528                                TRUE) != CVT_NO_ERROR) {
1529         return FALSE;        /* number was bad */
1530     }
1531
1532     if (!ranges_are_equal(pref->stashed_val.range, newrange)) {
1533         wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1534         pref->stashed_val.range = newrange;
1535     } else {
1536         wmem_free(wmem_epan_scope(), newrange);
1537     }
1538     return TRUE;
1539
1540 }
1541
1542 gboolean prefs_set_range_value(pref_t *pref, range_t *value, pref_source_t source)
1543 {
1544     gboolean changed = FALSE;
1545
1546     switch (source)
1547     {
1548     case pref_default:
1549         if (!ranges_are_equal(pref->default_val.range, value)) {
1550             wmem_free(wmem_epan_scope(), pref->default_val.range);
1551             pref->default_val.range = range_copy(wmem_epan_scope(), value);
1552             changed = TRUE;
1553         }
1554         break;
1555     case pref_stashed:
1556         if (!ranges_are_equal(pref->stashed_val.range, value)) {
1557             wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1558             pref->stashed_val.range = range_copy(wmem_epan_scope(), value);
1559             changed = TRUE;
1560         }
1561         break;
1562     case pref_current:
1563         if (!ranges_are_equal(*pref->varp.range, value)) {
1564             wmem_free(wmem_epan_scope(), *pref->varp.range);
1565             *pref->varp.range = range_copy(wmem_epan_scope(), value);
1566             changed = TRUE;
1567         }
1568         break;
1569     default:
1570         g_assert_not_reached();
1571         break;
1572     }
1573
1574     return changed;
1575 }
1576
1577 range_t* prefs_get_range_value_real(pref_t *pref, pref_source_t source)
1578 {
1579     switch (source)
1580     {
1581     case pref_default:
1582         return pref->default_val.range;
1583     case pref_stashed:
1584         return pref->stashed_val.range;
1585         break;
1586     case pref_current:
1587         return *pref->varp.range;
1588         break;
1589     default:
1590         g_assert_not_reached();
1591         break;
1592     }
1593
1594     return NULL;
1595 }
1596
1597 range_t* prefs_get_range_value(const char *module_name, const char* pref_name)
1598 {
1599     return prefs_get_range_value_real(prefs_find_preference(prefs_find_module(module_name), pref_name), pref_current);
1600 }
1601
1602 void
1603 prefs_range_add_value(pref_t *pref, guint32 val)
1604 {
1605     range_add_value(wmem_epan_scope(), pref->varp.range, val);
1606 }
1607
1608 void
1609 prefs_range_remove_value(pref_t *pref, guint32 val)
1610 {
1611     range_remove_value(wmem_epan_scope(), pref->varp.range, val);
1612 }
1613
1614 /*
1615  * Register a static text 'preference'.  It can be used to add explanatory
1616  * text inline with other preferences in the GUI.
1617  * Note: Static preferences are not saved to the preferences file.
1618  */
1619 void
1620 prefs_register_static_text_preference(module_t *module, const char *name,
1621                                       const char *title,
1622                                       const char *description)
1623 {
1624     register_preference(module, name, title, description, PREF_STATIC_TEXT);
1625 }
1626
1627 /*
1628  * Register a uat 'preference'. It adds a button that opens the uat's window in the
1629  * preferences tab of the module.
1630  */
1631 extern void
1632 prefs_register_uat_preference(module_t *module, const char *name,
1633                               const char *title, const char *description,
1634                               uat_t* uat)
1635 {
1636
1637     pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1638
1639     preference->varp.uat = uat;
1640 }
1641
1642 /*
1643  * Register a uat 'preference' for QT only. It adds a button that opens the uat's window in the
1644  * preferences tab of the module.
1645  */
1646 extern void
1647 prefs_register_uat_preference_qt(module_t *module, const char *name,
1648                               const char *title, const char *description,
1649                               uat_t* uat)
1650 {
1651
1652     pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1653
1654     preference->varp.uat = uat;
1655
1656     preference->gui = GUI_QT;
1657 }
1658
1659 struct epan_uat* prefs_get_uat_value(pref_t *pref)
1660 {
1661     return pref->varp.uat;
1662 }
1663
1664 /*
1665  * Register a color preference.
1666  */
1667 void
1668 prefs_register_color_preference(module_t *module, const char *name,
1669                                 const char *title, const char *description,
1670                                 color_t *color)
1671 {
1672     pref_t* preference = register_preference(module, name, title, description, PREF_COLOR);
1673
1674     preference->varp.colorp = color;
1675     preference->default_val.color = *color;
1676 }
1677
1678 gboolean prefs_set_color_value(pref_t *pref, color_t value, pref_source_t source)
1679 {
1680     gboolean changed = FALSE;
1681
1682     switch (source)
1683     {
1684     case pref_default:
1685         if ((pref->default_val.color.red != value.red) &&
1686             (pref->default_val.color.green != value.green) &&
1687             (pref->default_val.color.blue != value.blue)) {
1688             changed = TRUE;
1689             pref->default_val.color = value;
1690         }
1691         break;
1692     case pref_stashed:
1693         if ((pref->stashed_val.color.red != value.red) &&
1694             (pref->stashed_val.color.green != value.green) &&
1695             (pref->stashed_val.color.blue != value.blue)) {
1696             changed = TRUE;
1697             pref->stashed_val.color = value;
1698         }
1699         break;
1700     case pref_current:
1701         if ((pref->varp.colorp->red != value.red) &&
1702             (pref->varp.colorp->green != value.green) &&
1703             (pref->varp.colorp->blue != value.blue)) {
1704             changed = TRUE;
1705             *pref->varp.colorp = value;
1706         }
1707         break;
1708     default:
1709         g_assert_not_reached();
1710         break;
1711     }
1712
1713     return changed;
1714 }
1715
1716 color_t* prefs_get_color_value(pref_t *pref, pref_source_t source)
1717 {
1718     switch (source)
1719     {
1720     case pref_default:
1721         return &pref->default_val.color;
1722     case pref_stashed:
1723         return &pref->stashed_val.color;
1724         break;
1725     case pref_current:
1726         return pref->varp.colorp;
1727         break;
1728     default:
1729         g_assert_not_reached();
1730         break;
1731     }
1732
1733     return NULL;
1734 }
1735
1736 /*
1737  * Register a "custom" preference with a list.
1738  * XXX - This should be temporary until we can find a better way
1739  * to do "custom" preferences
1740  */
1741 typedef void (*pref_custom_list_init_cb) (pref_t* pref, GList** value);
1742
1743 static void
1744 prefs_register_list_custom_preference(module_t *module, const char *name,
1745                                       const char *title, const char *description,
1746                                       struct pref_custom_cbs* custom_cbs,
1747                                       pref_custom_list_init_cb init_cb,
1748                                       GList** list)
1749 {
1750     pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1751
1752     preference->custom_cbs = *custom_cbs;
1753     init_cb(preference, list);
1754 }
1755
1756 /*
1757  * Register a custom preference.
1758  */
1759 void
1760 prefs_register_custom_preference(module_t *module, const char *name,
1761                                  const char *title, const char *description,
1762                                  struct pref_custom_cbs* custom_cbs,
1763                                  void **custom_data _U_)
1764 {
1765     pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1766
1767     preference->custom_cbs = *custom_cbs;
1768     /* XXX - wait until we can handle void** pointers
1769     preference->custom_cbs.init_cb(preference, custom_data);
1770     */
1771 }
1772
1773 /*
1774  * Register a (internal) "Decode As" preference with a ranged value.
1775  */
1776 void prefs_register_decode_as_range_preference(module_t *module, const char *name,
1777     const char *title, const char *description, range_t **var,
1778     guint32 max_value)
1779 {
1780     prefs_register_range_preference_common(module, name, title,
1781                 description, var, max_value, PREF_DECODE_AS_RANGE);
1782 }
1783
1784 /*
1785  * Register a (internal) "Decode As" preference with an unsigned integral value
1786  * for a dissector table.
1787  */
1788 void prefs_register_decode_as_preference(module_t *module, const char *name,
1789     const char *title, const char *description, guint *var)
1790 {
1791     pref_t *preference;
1792
1793     preference = register_preference(module, name, title, description,
1794                                      PREF_DECODE_AS_UINT);
1795     preference->varp.uint = var;
1796     preference->default_val.uint = *var;
1797     /* XXX - Presume base 10 for now */
1798     preference->info.base = 10;
1799 }
1800
1801 gboolean prefs_add_decode_as_value(pref_t *pref, guint value, gboolean replace)
1802 {
1803     switch(pref->type)
1804     {
1805     case PREF_DECODE_AS_UINT:
1806         /* This doesn't support multiple values for a dissector in Decode As because the
1807             preference only supports a single value. This leads to a "last port for
1808             dissector in Decode As wins" */
1809         *pref->varp.uint = value;
1810         break;
1811     case PREF_DECODE_AS_RANGE:
1812         if (replace)
1813         {
1814             /* If range has single value, replace it */
1815             if (((*pref->varp.range)->nranges == 1) &&
1816                 ((*pref->varp.range)->ranges[0].low == (*pref->varp.range)->ranges[0].high)) {
1817                 wmem_free(wmem_epan_scope(), *pref->varp.range);
1818                 *pref->varp.range = range_empty(wmem_epan_scope());
1819             }
1820         }
1821
1822         prefs_range_add_value(pref, value);
1823         break;
1824     default:
1825         /* XXX - Worth asserting over? */
1826         break;
1827     }
1828
1829     return TRUE;
1830 }
1831
1832 gboolean prefs_remove_decode_as_value(pref_t *pref, guint value, gboolean set_default)
1833 {
1834     switch(pref->type)
1835     {
1836     case PREF_DECODE_AS_UINT:
1837         if (set_default) {
1838             *pref->varp.uint = pref->default_val.uint;
1839         } else {
1840             *pref->varp.uint = 0;
1841         }
1842         break;
1843     case PREF_DECODE_AS_RANGE:
1844         prefs_range_remove_value(pref, value);
1845         break;
1846     default:
1847         break;
1848     }
1849
1850     return TRUE;
1851 }
1852
1853 /*
1854  * Register a preference that used to be supported but no longer is.
1855  */
1856 void
1857 prefs_register_obsolete_preference(module_t *module, const char *name)
1858 {
1859     register_preference(module, name, NULL, NULL, PREF_OBSOLETE);
1860 }
1861
1862 /*
1863  * Check to see if a preference is obsolete.
1864  */
1865 extern gboolean
1866 prefs_get_preference_obsolete(pref_t *pref)
1867 {
1868     if (pref)
1869         return (IS_PREF_OBSOLETE(pref->type) ? TRUE : FALSE);
1870
1871     return TRUE;
1872 }
1873
1874 /*
1875  * Make a preference obsolete.
1876  */
1877 extern prefs_set_pref_e
1878 prefs_set_preference_obsolete(pref_t *pref)
1879 {
1880     if (pref) {
1881         SET_PREF_OBSOLETE(pref->type);
1882         return PREFS_SET_OK;
1883     }
1884     return PREFS_SET_NO_SUCH_PREF;
1885 }
1886
1887 guint
1888 pref_stash(pref_t *pref, gpointer unused _U_)
1889 {
1890     switch (pref->type) {
1891
1892     case PREF_DECODE_AS_UINT:
1893         pref->stashed_val.uint = *pref->varp.uint;
1894         break;
1895
1896     case PREF_UINT:
1897         pref->stashed_val.uint = *pref->varp.uint;
1898         break;
1899
1900     case PREF_BOOL:
1901         pref->stashed_val.boolval = *pref->varp.boolp;
1902         break;
1903
1904     case PREF_ENUM:
1905         pref->stashed_val.enumval = *pref->varp.enump;
1906         break;
1907
1908     case PREF_STRING:
1909     case PREF_FILENAME:
1910     case PREF_DIRNAME:
1911         g_free(pref->stashed_val.string);
1912         pref->stashed_val.string = g_strdup(*pref->varp.string);
1913         break;
1914
1915     case PREF_DECODE_AS_RANGE:
1916     case PREF_RANGE:
1917         wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1918         pref->stashed_val.range = range_copy(wmem_epan_scope(), *pref->varp.range);
1919         break;
1920
1921     case PREF_COLOR:
1922         pref->stashed_val.color = *pref->varp.colorp;
1923         break;
1924
1925     case PREF_STATIC_TEXT:
1926     case PREF_UAT:
1927     case PREF_CUSTOM:
1928         break;
1929
1930     case PREF_OBSOLETE:
1931         g_assert_not_reached();
1932         break;
1933     }
1934     return 0;
1935 }
1936
1937 guint
1938 pref_unstash(pref_t *pref, gpointer unstash_data_p)
1939 {
1940     pref_unstash_data_t *unstash_data = (pref_unstash_data_t *)unstash_data_p;
1941     dissector_table_t sub_dissectors = NULL;
1942     dissector_handle_t handle = NULL;
1943
1944     /* Revert the preference to its saved value. */
1945     switch (pref->type) {
1946
1947     case PREF_DECODE_AS_UINT:
1948         if (*pref->varp.uint != pref->stashed_val.uint) {
1949             unstash_data->module->prefs_changed = TRUE;
1950
1951             if (unstash_data->handle_decode_as) {
1952                 if (*pref->varp.uint != pref->default_val.uint) {
1953                     dissector_reset_uint(pref->name, *pref->varp.uint);
1954                 }
1955             }
1956
1957             *pref->varp.uint = pref->stashed_val.uint;
1958
1959             if (unstash_data->handle_decode_as) {
1960                 sub_dissectors = find_dissector_table(pref->name);
1961                 if (sub_dissectors != NULL) {
1962                     handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)unstash_data->module->title);
1963                     if (handle != NULL) {
1964                         dissector_change_uint(pref->name, *pref->varp.uint, handle);
1965                     }
1966                 }
1967             }
1968         }
1969         break;
1970
1971     case PREF_UINT:
1972         if (*pref->varp.uint != pref->stashed_val.uint) {
1973             unstash_data->module->prefs_changed = TRUE;
1974             *pref->varp.uint = pref->stashed_val.uint;
1975         }
1976         break;
1977
1978     case PREF_BOOL:
1979         if (*pref->varp.boolp != pref->stashed_val.boolval) {
1980             unstash_data->module->prefs_changed = TRUE;
1981             *pref->varp.boolp = pref->stashed_val.boolval;
1982         }
1983         break;
1984
1985     case PREF_ENUM:
1986         if (*pref->varp.enump != pref->stashed_val.enumval) {
1987             unstash_data->module->prefs_changed = TRUE;
1988             *pref->varp.enump = pref->stashed_val.enumval;
1989         }
1990         break;
1991
1992     case PREF_STRING:
1993     case PREF_FILENAME:
1994     case PREF_DIRNAME:
1995         if (strcmp(*pref->varp.string, pref->stashed_val.string) != 0) {
1996             unstash_data->module->prefs_changed = TRUE;
1997             g_free(*pref->varp.string);
1998             *pref->varp.string = g_strdup(pref->stashed_val.string);
1999         }
2000         break;
2001
2002     case PREF_DECODE_AS_RANGE:
2003         if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2004             guint32 i, j;
2005             unstash_data->module->prefs_changed = TRUE;
2006
2007             if (unstash_data->handle_decode_as) {
2008                 sub_dissectors = find_dissector_table(pref->name);
2009                 if (sub_dissectors != NULL) {
2010                     handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)unstash_data->module->title);
2011                     if (handle != NULL) {
2012                         /* Delete all of the old values from the dissector table */
2013                         for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2014                             for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2015                                 dissector_delete_uint(pref->name, j, handle);
2016                                 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
2017                             }
2018
2019                             dissector_delete_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
2020                             decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
2021                         }
2022                     }
2023                 }
2024             }
2025
2026             wmem_free(wmem_epan_scope(), *pref->varp.range);
2027             *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2028
2029             if (unstash_data->handle_decode_as) {
2030                 if ((sub_dissectors != NULL) && (handle != NULL)) {
2031
2032                     /* Add new values to the dissector table */
2033                     for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2034
2035                         for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2036                             dissector_change_uint(pref->name, j, handle);
2037                             decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
2038                         }
2039
2040                         dissector_change_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
2041                         decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
2042                     }
2043                 }
2044             }
2045         }
2046         break;
2047
2048     case PREF_RANGE:
2049         if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2050             unstash_data->module->prefs_changed = TRUE;
2051             wmem_free(wmem_epan_scope(), *pref->varp.range);
2052             *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2053         }
2054     break;
2055
2056     case PREF_COLOR:
2057         *pref->varp.colorp = pref->stashed_val.color;
2058         break;
2059
2060     case PREF_STATIC_TEXT:
2061     case PREF_UAT:
2062     case PREF_CUSTOM:
2063         break;
2064
2065     case PREF_OBSOLETE:
2066         g_assert_not_reached();
2067         break;
2068     }
2069     return 0;
2070 }
2071
2072 void
2073 reset_stashed_pref(pref_t *pref) {
2074     switch (pref->type) {
2075
2076     case PREF_DECODE_AS_UINT:
2077         pref->stashed_val.uint = pref->default_val.uint;
2078         break;
2079
2080     case PREF_UINT:
2081         pref->stashed_val.uint = pref->default_val.uint;
2082         break;
2083
2084     case PREF_BOOL:
2085         pref->stashed_val.boolval = pref->default_val.boolval;
2086         break;
2087
2088     case PREF_ENUM:
2089         pref->stashed_val.enumval = pref->default_val.enumval;
2090         break;
2091
2092     case PREF_STRING:
2093     case PREF_FILENAME:
2094     case PREF_DIRNAME:
2095         g_free(pref->stashed_val.string);
2096         pref->stashed_val.string = g_strdup(pref->default_val.string);
2097         break;
2098
2099     case PREF_DECODE_AS_RANGE:
2100     case PREF_RANGE:
2101         wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2102         pref->stashed_val.range = range_copy(wmem_epan_scope(), pref->default_val.range);
2103         break;
2104
2105     case PREF_COLOR:
2106         memcpy(&pref->stashed_val.color, &pref->default_val.color, sizeof(color_t));
2107         break;
2108
2109     case PREF_STATIC_TEXT:
2110     case PREF_UAT:
2111     case PREF_CUSTOM:
2112         break;
2113
2114     case PREF_OBSOLETE:
2115         g_assert_not_reached();
2116         break;
2117     }
2118 }
2119
2120 guint
2121 pref_clean_stash(pref_t *pref, gpointer unused _U_)
2122 {
2123     switch (pref->type) {
2124
2125     case PREF_UINT:
2126     case PREF_DECODE_AS_UINT:
2127         break;
2128
2129     case PREF_BOOL:
2130         break;
2131
2132     case PREF_ENUM:
2133         break;
2134
2135     case PREF_STRING:
2136     case PREF_FILENAME:
2137     case PREF_DIRNAME:
2138         if (pref->stashed_val.string != NULL) {
2139             g_free(pref->stashed_val.string);
2140             pref->stashed_val.string = NULL;
2141         }
2142         break;
2143
2144     case PREF_DECODE_AS_RANGE:
2145     case PREF_RANGE:
2146         if (pref->stashed_val.range != NULL) {
2147             wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2148             pref->stashed_val.range = NULL;
2149         }
2150         break;
2151
2152     case PREF_STATIC_TEXT:
2153     case PREF_UAT:
2154     case PREF_COLOR:
2155     case PREF_CUSTOM:
2156         break;
2157
2158     case PREF_OBSOLETE:
2159         g_assert_not_reached();
2160         break;
2161     }
2162     return 0;
2163 }
2164
2165 #if 0
2166 /* Return the value assigned to the given uint preference. */
2167 guint
2168 prefs_get_uint_preference(pref_t *pref)
2169 {
2170     if (pref && pref->type == PREF_UINT)
2171         return *pref->varp.uint;
2172     return 0;
2173 }
2174 #endif
2175
2176 /*
2177  * Call a callback function, with a specified argument, for each preference
2178  * in a given module.
2179  *
2180  * If any of the callbacks return a non-zero value, stop and return that
2181  * value, otherwise return 0.
2182  */
2183 guint
2184 prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
2185 {
2186     GList *elem;
2187     pref_t *pref;
2188     guint ret;
2189
2190     for (elem = g_list_first(module->prefs); elem != NULL; elem = g_list_next(elem)) {
2191         pref = (pref_t *)elem->data;
2192         if (IS_PREF_OBSOLETE(pref->type)) {
2193             /*
2194              * This preference is no longer supported; it's
2195              * not a real preference, so we don't call the
2196              * callback for it (i.e., we treat it as if it
2197              * weren't found in the list of preferences,
2198              * and we weren't called in the first place).
2199              */
2200             continue;
2201         }
2202
2203         ret = (*callback)(pref, user_data);
2204         if (ret != 0)
2205             return ret;
2206     }
2207     return 0;
2208 }
2209
2210 static const enum_val_t print_format_vals[] = {
2211     { "text",       "Plain Text", PR_FMT_TEXT },
2212     { "postscript", "Postscript", PR_FMT_PS },
2213     { NULL,         NULL,         0 }
2214 };
2215
2216 static const enum_val_t print_dest_vals[] = {
2217 #ifdef _WIN32
2218     /* "PR_DEST_CMD" means "to printer" on Windows */
2219     { "command", "Printer", PR_DEST_CMD },
2220 #else
2221     { "command", "Command", PR_DEST_CMD },
2222 #endif
2223     { "file",    "File",    PR_DEST_FILE },
2224     { NULL,      NULL,      0 }
2225 };
2226
2227 static const enum_val_t st_sort_col_vals[] = {
2228     { "name",    "Node name (topic/item)", ST_SORT_COL_NAME },
2229     { "count",   "Item count", ST_SORT_COL_COUNT },
2230     { "average", "Average value of the node", ST_SORT_COL_AVG },
2231     { "min",     "Minimum value of the node", ST_SORT_COL_MIN },
2232     { "max",     "Maximum value of the node", ST_SORT_COL_MAX },
2233     { "burst",   "Burst rate of the node", ST_SORT_COL_BURSTRATE },
2234     { NULL,      NULL,         0 }
2235 };
2236
2237 static void
2238 stats_callback(void)
2239 {
2240     /* Test for a sane tap update interval */
2241     if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000)
2242         prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
2243
2244 #ifdef HAVE_LIBPORTAUDIO
2245     /* Test for a sane max channels entry */
2246     if (prefs.rtp_player_max_visible < 1 || prefs.rtp_player_max_visible > 10)
2247         prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
2248 #endif
2249
2250     /* burst resolution can't be less than 1 (ms) */
2251     if (prefs.st_burst_resolution < 1) {
2252         prefs.st_burst_resolution = 1;
2253     }
2254     else if (prefs.st_burst_resolution > ST_MAX_BURSTRES) {
2255         prefs.st_burst_resolution = ST_MAX_BURSTRES;
2256     }
2257     /* make sure burst window value makes sense */
2258     if (prefs.st_burst_windowlen < prefs.st_burst_resolution) {
2259         prefs.st_burst_windowlen = prefs.st_burst_resolution;
2260     }
2261     /* round burst window down to multiple of resolution */
2262     prefs.st_burst_windowlen -= prefs.st_burst_windowlen%prefs.st_burst_resolution;
2263     if ((prefs.st_burst_windowlen/prefs.st_burst_resolution) > ST_MAX_BURSTBUCKETS) {
2264         prefs.st_burst_windowlen = prefs.st_burst_resolution*ST_MAX_BURSTBUCKETS;
2265     }
2266 }
2267
2268 static void
2269 gui_callback(void)
2270 {
2271     /* Ensure there is at least one file count */
2272     if (prefs.gui_recent_files_count_max == 0)
2273       prefs.gui_recent_files_count_max = 10;
2274
2275     /* Ensure there is at least one display filter entry */
2276     if (prefs.gui_recent_df_entries_max == 0)
2277       prefs.gui_recent_df_entries_max = 10;
2278 }
2279
2280 static void
2281 gui_layout_callback(void)
2282 {
2283     if (prefs.gui_layout_type == layout_unused ||
2284         prefs.gui_layout_type >= layout_type_max) {
2285       /* XXX - report an error?  It's not a syntax error - we'd need to
2286          add a way of reporting a *semantic* error. */
2287       prefs.gui_layout_type = layout_type_5;
2288     }
2289 }
2290
2291 /******************************************************
2292  * All custom preference function callbacks
2293  ******************************************************/
2294 static void custom_pref_no_cb(pref_t* pref _U_) {}
2295
2296
2297 /*
2298  * Console log level custom preference functions
2299  */
2300 static void
2301 console_log_level_reset_cb(pref_t* pref)
2302 {
2303     *pref->varp.uint = pref->default_val.uint;
2304 }
2305
2306 static prefs_set_pref_e
2307 console_log_level_set_cb(pref_t* pref, const gchar* value, gboolean* changed)
2308 {
2309     guint    uval;
2310
2311     uval = (guint)strtoul(value, NULL, 10);
2312
2313     if (*pref->varp.uint != uval) {
2314         *changed = TRUE;
2315         *pref->varp.uint = uval;
2316     }
2317
2318     if (*pref->varp.uint & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG)) {
2319       /*
2320        * GLib >= 2.32 drops INFO and DEBUG messages by default. Tell
2321        * it not to do that.
2322        */
2323        g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
2324     }
2325
2326     return PREFS_SET_OK;
2327 }
2328
2329 static const char * console_log_level_type_name_cb(void) {
2330     return "Log level";
2331 }
2332
2333 static char * console_log_level_type_description_cb(void) {
2334     return g_strdup_printf(
2335         "Console log level (for debugging)\n"
2336         "A bitmask of log levels:\n"
2337         "ERROR    = 4\n"
2338         "CRITICAL = 8\n"
2339         "WARNING  = 16\n"
2340         "MESSAGE  = 32\n"
2341         "INFO     = 64\n"
2342         "DEBUG    = 128");
2343 }
2344
2345 static gboolean console_log_level_is_default_cb(pref_t* pref) {
2346     return *pref->varp.uint == pref->default_val.uint;
2347 }
2348
2349 static char * console_log_level_to_str_cb(pref_t* pref, gboolean default_val) {
2350     return g_strdup_printf("%u",  default_val ? pref->default_val.uint : *pref->varp.uint);
2351 }
2352
2353 /*
2354  * Column preference functions
2355  */
2356 #define PRS_COL_HIDDEN                   "column.hidden"
2357 #define PRS_COL_FMT                      "column.format"
2358 #define PRS_COL_NUM                      "column.number"
2359 static module_t *gui_column_module = NULL;
2360
2361 static prefs_set_pref_e
2362 column_hidden_set_cb(pref_t* pref, const gchar* value, gboolean* changed)
2363 {
2364     GList       *clp;
2365     fmt_data    *cfmt;
2366     pref_t  *format_pref;
2367
2368     (*changed) |= prefs_set_string_value(pref, value, pref_current);
2369
2370     /*
2371      * Set the "visible" flag for the existing columns; we need to
2372      * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
2373      * after setting it (which might be the case if, for example, we
2374      * set PRS_COL_HIDDEN on the command line).
2375      */
2376     format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2377     for (clp = *format_pref->varp.list; clp != NULL; clp = clp->next) {
2378       cfmt = (fmt_data *)clp->data;
2379       cfmt->visible = prefs_is_column_visible(*pref->varp.string, cfmt);
2380     }
2381
2382     return PREFS_SET_OK;
2383 }
2384
2385 static const char *
2386 column_hidden_type_name_cb(void)
2387 {
2388     return "Packet list hidden columns";
2389 }
2390
2391 static char *
2392 column_hidden_type_description_cb(void)
2393 {
2394     return g_strdup("List all columns to hide in the packet list.");
2395 }
2396
2397 static char *
2398 column_hidden_to_str_cb(pref_t* pref, gboolean default_val)
2399 {
2400     GString     *cols_hidden = g_string_new ("");
2401     GList       *clp;
2402     fmt_data    *cfmt;
2403     pref_t  *format_pref;
2404
2405     if (default_val)
2406         return g_strdup(pref->default_val.string);
2407
2408     format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2409     clp = (format_pref) ? *format_pref->varp.list : NULL;
2410     while (clp) {
2411         gchar *prefs_fmt;
2412         cfmt = (fmt_data *) clp->data;
2413         if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) {
2414             prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
2415                     col_format_to_string(cfmt->fmt),
2416                     cfmt->custom_fields,
2417                     cfmt->custom_occurrence,
2418                     cfmt->resolved ? 'R' : 'U');
2419         } else {
2420             prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
2421         }
2422         if (!cfmt->visible) {
2423             if (cols_hidden->len)
2424                 g_string_append (cols_hidden, ",");
2425             g_string_append (cols_hidden, prefs_fmt);
2426         }
2427         g_free(prefs_fmt);
2428         clp = clp->next;
2429     }
2430
2431     return g_string_free (cols_hidden, FALSE);
2432 }
2433
2434 static gboolean
2435 column_hidden_is_default_cb(pref_t* pref)
2436 {
2437     char *cur_hidden_str = column_hidden_to_str_cb(pref, FALSE);
2438     gboolean is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2439
2440     g_free(cur_hidden_str);
2441     return is_default;
2442 }
2443
2444
2445 /* Number of columns "preference".  This is only used internally and is not written to the
2446  * preference file
2447  */
2448 static void
2449 column_num_reset_cb(pref_t* pref)
2450 {
2451     *pref->varp.uint = pref->default_val.uint;
2452 }
2453
2454 static prefs_set_pref_e
2455 column_num_set_cb(pref_t* pref _U_, const gchar* value _U_, gboolean* changed _U_)
2456 {
2457     /* Don't write this to the preferences file */
2458     return PREFS_SET_OK;
2459 }
2460
2461 static const char *
2462 column_num_type_name_cb(void)
2463 {
2464     return NULL;
2465 }
2466
2467 static char *
2468 column_num_type_description_cb(void)
2469 {
2470     return g_strdup("");
2471 }
2472
2473 static gboolean
2474 column_num_is_default_cb(pref_t* pref _U_)
2475 {
2476     return TRUE;
2477 }
2478
2479 static char *
2480 column_num_to_str_cb(pref_t* pref _U_, gboolean default_val _U_)
2481 {
2482     return g_strdup("");
2483 }
2484
2485 /*
2486  * Column format custom preference functions
2487  */
2488 static void
2489 column_format_init_cb(pref_t* pref, GList** value)
2490 {
2491     fmt_data *src_cfmt, *dest_cfmt;
2492     GList *entry;
2493
2494     pref->varp.list = value;
2495
2496     pref->default_val.list = NULL;
2497     for (entry = *pref->varp.list; entry != NULL; entry = g_list_next(entry)) {
2498         src_cfmt = (fmt_data *)entry->data;
2499         dest_cfmt = g_new(fmt_data,1);
2500         dest_cfmt->title = g_strdup(src_cfmt->title);
2501         dest_cfmt->fmt = src_cfmt->fmt;
2502         if (src_cfmt->custom_fields) {
2503             dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
2504             dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2505         } else {
2506             dest_cfmt->custom_fields = NULL;
2507             dest_cfmt->custom_occurrence = 0;
2508         }
2509         dest_cfmt->visible = src_cfmt->visible;
2510         dest_cfmt->resolved = src_cfmt->resolved;
2511         pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
2512     }
2513 }
2514
2515 static void
2516 column_format_free_cb(pref_t* pref)
2517 {
2518     free_col_info(*pref->varp.list);
2519     free_col_info(pref->default_val.list);
2520 }
2521
2522 static void
2523 column_format_reset_cb(pref_t* pref)
2524 {
2525     fmt_data *src_cfmt, *dest_cfmt;
2526     GList *entry;
2527     pref_t  *col_num_pref;
2528
2529     free_col_info(*pref->varp.list);
2530     *pref->varp.list = NULL;
2531
2532     for (entry = pref->default_val.list; entry != NULL; entry = g_list_next(entry)) {
2533         src_cfmt = (fmt_data *)entry->data;
2534         dest_cfmt = g_new(fmt_data,1);
2535         dest_cfmt->title = g_strdup(src_cfmt->title);
2536         dest_cfmt->fmt = src_cfmt->fmt;
2537         if (src_cfmt->custom_fields) {
2538             dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
2539             dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2540         } else {
2541             dest_cfmt->custom_fields = NULL;
2542             dest_cfmt->custom_occurrence = 0;
2543         }
2544         dest_cfmt->visible = src_cfmt->visible;
2545         dest_cfmt->resolved = src_cfmt->resolved;
2546         *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
2547     }
2548
2549     col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2550     g_assert(col_num_pref != NULL); /* Should never happen */
2551     column_num_reset_cb(col_num_pref);
2552 }
2553
2554 static prefs_set_pref_e
2555 column_format_set_cb(pref_t* pref, const gchar* value, gboolean* changed _U_)
2556 {
2557     GList    *col_l, *col_l_elt;
2558     fmt_data *cfmt;
2559     gint     llen;
2560     pref_t   *hidden_pref, *col_num_pref;
2561
2562     col_l = prefs_get_string_list(value);
2563     if (col_l == NULL)
2564       return PREFS_SET_SYNTAX_ERR;
2565     if ((g_list_length(col_l) % 2) != 0) {
2566       /* A title didn't have a matching format.  */
2567       prefs_clear_string_list(col_l);
2568       return PREFS_SET_SYNTAX_ERR;
2569     }
2570     /* Check to make sure all column formats are valid.  */
2571     col_l_elt = g_list_first(col_l);
2572     while (col_l_elt) {
2573       fmt_data cfmt_check;
2574
2575       /* Go past the title.  */
2576       col_l_elt = col_l_elt->next;
2577
2578       /* Parse the format to see if it's valid.  */
2579       if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) {
2580         /* It's not a valid column format.  */
2581         prefs_clear_string_list(col_l);
2582         return PREFS_SET_SYNTAX_ERR;
2583       }
2584       if (cfmt_check.fmt != COL_CUSTOM) {
2585         /* Some predefined columns have been migrated to use custom columns.
2586          * We'll convert these silently here */
2587         try_convert_to_custom_column(&col_l_elt->data);
2588       } else {
2589         /* We don't need the custom column field on this pass. */
2590         g_free(cfmt_check.custom_fields);
2591       }
2592
2593       /* Go past the format.  */
2594       col_l_elt = col_l_elt->next;
2595     }
2596
2597     /* They're all valid; process them. */
2598     free_col_info(*pref->varp.list);
2599     *pref->varp.list = NULL;
2600     hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN);
2601     g_assert(hidden_pref != NULL); /* Should never happen */
2602     col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2603     g_assert(col_num_pref != NULL); /* Should never happen */
2604     llen             = g_list_length(col_l);
2605     *col_num_pref->varp.uint = llen / 2;
2606     col_l_elt = g_list_first(col_l);
2607     while (col_l_elt) {
2608       cfmt           = g_new(fmt_data,1);
2609       cfmt->title    = g_strdup((gchar *)col_l_elt->data);
2610       col_l_elt      = col_l_elt->next;
2611       parse_column_format(cfmt, (char *)col_l_elt->data);
2612       cfmt->visible   = prefs_is_column_visible(*hidden_pref->varp.string, cfmt);
2613       col_l_elt      = col_l_elt->next;
2614       *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
2615     }
2616
2617     prefs_clear_string_list(col_l);
2618     free_string_like_preference(hidden_pref);
2619     return PREFS_SET_OK;
2620 }
2621
2622
2623 static const char *
2624 column_format_type_name_cb(void)
2625 {
2626     return "Packet list column format";
2627 }
2628
2629 static char *
2630 column_format_type_description_cb(void)
2631 {
2632     return g_strdup("Each pair of strings consists of a column title and its format");
2633 }
2634
2635 static gboolean
2636 column_format_is_default_cb(pref_t* pref)
2637 {
2638     GList       *clp = *pref->varp.list,
2639                 *pref_col = g_list_first(clp),
2640                 *def_col = g_list_first(pref->default_val.list);
2641     fmt_data    *cfmt, *def_cfmt;
2642     gboolean    is_default = TRUE;
2643     pref_t      *col_num_pref;
2644
2645     /* See if the column data has changed from the default */
2646     col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2647     if (col_num_pref && *col_num_pref->varp.uint != col_num_pref->default_val.uint) {
2648         is_default = FALSE;
2649     } else {
2650         while (pref_col && def_col) {
2651             cfmt = (fmt_data *) pref_col->data;
2652             def_cfmt = (fmt_data *) def_col->data;
2653             if ((g_strcmp0(cfmt->title, def_cfmt->title) != 0) ||
2654                     (cfmt->fmt != def_cfmt->fmt) ||
2655                     (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) &&
2656                      ((g_strcmp0(cfmt->custom_fields, def_cfmt->custom_fields) != 0) ||
2657                       (cfmt->resolved != def_cfmt->resolved)))) {
2658                 is_default = FALSE;
2659                 break;
2660             }
2661
2662             pref_col = pref_col->next;
2663             def_col = def_col->next;
2664         }
2665     }
2666
2667     return is_default;
2668 }
2669
2670 static char *
2671 column_format_to_str_cb(pref_t* pref, gboolean default_val)
2672 {
2673     GList       *pref_l = default_val ? pref->default_val.list : *pref->varp.list;
2674     GList       *clp = g_list_first(pref_l);
2675     GList       *col_l;
2676     fmt_data    *cfmt;
2677     gchar       *prefs_fmt;
2678     char        *column_format_str;
2679
2680     col_l = NULL;
2681     while (clp) {
2682         cfmt = (fmt_data *) clp->data;
2683         col_l = g_list_append(col_l, g_strdup(cfmt->title));
2684         if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) {
2685             prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
2686                     col_format_to_string(cfmt->fmt),
2687                     cfmt->custom_fields,
2688                     cfmt->custom_occurrence,
2689                     cfmt->resolved ? 'R' : 'U');
2690         } else {
2691             prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
2692         }
2693         col_l = g_list_append(col_l, prefs_fmt);
2694         clp = clp->next;
2695     }
2696
2697     column_format_str = join_string_list(col_l);
2698     prefs_clear_string_list(col_l);
2699     return column_format_str;
2700 }
2701
2702
2703 /******  Capture column custom preference functions  ******/
2704
2705 /* This routine is only called when Wireshark is started, NOT when another profile is selected.
2706    Copy the pref->capture_columns list (just loaded with the capture_cols[] struct values)
2707    to prefs->default_val.list.
2708 */
2709 static void
2710 capture_column_init_cb(pref_t* pref, GList** capture_cols_values)
2711 {
2712     GList   *ccv_list = *capture_cols_values,
2713             *dlist = NULL;
2714
2715     /*  */
2716     while (ccv_list) {
2717         dlist = g_list_append(dlist, g_strdup((gchar *)ccv_list->data));
2718         ccv_list = ccv_list->next;
2719     }
2720
2721     pref->default_val.list = dlist;
2722     pref->varp.list = &prefs.capture_columns;
2723     pref->stashed_val.boolval = FALSE;
2724 }
2725
2726 /* Free the prefs->capture_columns list strings and remove the list entries.
2727    Note that since pref->varp.list points to &prefs.capture_columns, it is
2728    also freed.
2729 */
2730 static void
2731 capture_column_free_cb(pref_t* pref)
2732 {
2733     prefs_clear_string_list(prefs.capture_columns);
2734     prefs.capture_columns = NULL;
2735
2736     if (pref->stashed_val.boolval == TRUE) {
2737       prefs_clear_string_list(pref->default_val.list);
2738       pref->default_val.list = NULL;
2739     }
2740 }
2741
2742 /* Copy pref->default_val.list to *pref->varp.list.
2743 */
2744 static void
2745 capture_column_reset_cb(pref_t* pref)
2746 {
2747     GList *vlist = NULL, *dlist;
2748
2749     /* Free the column name strings and remove the links from *pref->varp.list */
2750     prefs_clear_string_list(*pref->varp.list);
2751
2752     for (dlist = pref->default_val.list; dlist != NULL; dlist = g_list_next(dlist)) {
2753       vlist = g_list_append(vlist, g_strdup((gchar *)dlist->data));
2754     }
2755     *pref->varp.list = vlist;
2756 }
2757
2758 static prefs_set_pref_e
2759 capture_column_set_cb(pref_t* pref, const gchar* value, gboolean* changed _U_)
2760 {
2761     GList *col_l  = prefs_get_string_list(value);
2762     GList *col_l_elt;
2763     gchar *col_name;
2764     int i;
2765
2766     if (col_l == NULL)
2767       return PREFS_SET_SYNTAX_ERR;
2768
2769     capture_column_free_cb(pref);
2770
2771     /* If value (the list of capture.columns read from preferences) is empty, set capture.columns
2772        to the full list of valid capture column names. */
2773     col_l_elt = g_list_first(col_l);
2774     if (!(*(gchar *)col_l_elt->data)) {
2775         for (i = 0; i < num_capture_cols; i++) {
2776           col_name = g_strdup(capture_cols[i]);
2777           prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2778         }
2779     }
2780
2781     /* Verify that all the column names are valid. If not, use the entire list of valid columns.
2782      */
2783     while (col_l_elt) {
2784       gboolean found_match = FALSE;
2785       col_name = (gchar *)col_l_elt->data;
2786
2787       for (i = 0; i < num_capture_cols; i++) {
2788         if (strcmp(col_name, capture_cols[i])==0) {
2789           found_match = TRUE;
2790           break;
2791         }
2792       }
2793       if (!found_match) {
2794         /* One or more cols are invalid so use the entire list of valid cols. */
2795         for (i = 0; i < num_capture_cols; i++) {
2796           col_name = g_strdup(capture_cols[i]);
2797           prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2798         }
2799         pref->varp.list = &prefs.capture_columns;
2800         prefs_clear_string_list(col_l);
2801         return PREFS_SET_SYNTAX_ERR;
2802       }
2803       col_l_elt = col_l_elt->next;
2804     }
2805
2806     col_l_elt = g_list_first(col_l);
2807     while (col_l_elt) {
2808       col_name = (gchar *)col_l_elt->data;
2809       prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2810       col_l_elt = col_l_elt->next;
2811     }
2812     pref->varp.list = &prefs.capture_columns;
2813     g_list_free(col_l);
2814     return PREFS_SET_OK;
2815 }
2816
2817
2818 static const char *
2819 capture_column_type_name_cb(void)
2820 {
2821     return "Column list";
2822 }
2823
2824 static char *
2825 capture_column_type_description_cb(void)
2826 {
2827     return g_strdup(
2828         "List of columns to be displayed in the capture options dialog.\n"
2829         CAPTURE_COL_TYPE_DESCRIPTION);
2830 }
2831
2832 static gboolean
2833 capture_column_is_default_cb(pref_t* pref)
2834 {
2835     GList   *pref_col = g_list_first(prefs.capture_columns),
2836             *def_col = g_list_first(pref->default_val.list);
2837     gboolean is_default = TRUE;
2838
2839     /* See if the column data has changed from the default */
2840     while (pref_col && def_col) {
2841         if (strcmp((gchar *)pref_col->data, (gchar *)def_col->data) != 0) {
2842             is_default = FALSE;
2843             break;
2844         }
2845         pref_col = pref_col->next;
2846         def_col = def_col->next;
2847     }
2848
2849     /* Ensure the same column count */
2850     if (((pref_col == NULL) && (def_col != NULL)) ||
2851         ((pref_col != NULL) && (def_col == NULL)))
2852         is_default = FALSE;
2853
2854     return is_default;
2855 }
2856
2857 static char *
2858 capture_column_to_str_cb(pref_t* pref, gboolean default_val)
2859 {
2860
2861     GList       *pref_l = default_val ? pref->default_val.list : prefs.capture_columns;
2862     GList       *clp = g_list_first(pref_l);
2863     GList       *col_l = NULL;
2864     gchar       *col;
2865     char        *capture_column_str;
2866
2867     while (clp) {
2868         col = (gchar *) clp->data;
2869         col_l = g_list_append(col_l, g_strdup(col));
2870         clp = clp->next;
2871     }
2872
2873     capture_column_str = join_string_list(col_l);
2874     prefs_clear_string_list(col_l);
2875     return capture_column_str;
2876 }
2877
2878 static prefs_set_pref_e
2879 colorized_frame_set_cb(pref_t* pref, const gchar* value, gboolean* changed)
2880 {
2881     (*changed) |= prefs_set_string_value(pref, value, pref_current);
2882     return PREFS_SET_OK;
2883 }
2884
2885 static const char *
2886 colorized_frame_type_name_cb(void)
2887 {
2888    /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
2889     * file until the colors can be changed in the GUI. Currently this is not really
2890     * possible since the STOCK-icons for these colors are hardcoded.
2891     *
2892     * XXX Find a way to change the colors of the STOCK-icons on the fly and then
2893     *     add these 10 colors to the list of colors that can be changed through
2894     *     the preferences.
2895     *
2896     */
2897     return NULL;
2898 }
2899
2900 static char *
2901 colorized_frame_type_description_cb(void)
2902 {
2903     return g_strdup("");
2904 }
2905
2906 static gboolean
2907 colorized_frame_is_default_cb(pref_t* pref _U_)
2908 {
2909     return TRUE;
2910 }
2911
2912 static char *
2913 colorized_frame_to_str_cb(pref_t* pref _U_, gboolean default_val _U_)
2914 {
2915     return g_strdup("");
2916 }
2917
2918 /*
2919  * Register all non-dissector modules' preferences.
2920  */
2921 static module_t *gui_module = NULL;
2922 static module_t *gui_color_module = NULL;
2923 static module_t *nameres_module = NULL;
2924
2925 static void
2926 prefs_register_modules(void)
2927 {
2928     module_t *printing, *capture_module, *console_module,
2929         *gui_layout_module, *gui_font_module;
2930 #ifdef HAVE_EXTCAP
2931     module_t *extcap_module;
2932 #endif
2933
2934     struct pref_custom_cbs custom_cbs;
2935
2936     if (protocols_module != NULL) {
2937         /* Already setup preferences */
2938         return;
2939     }
2940
2941 #ifdef HAVE_EXTCAP
2942     /* GUI
2943      * These are "simple" GUI preferences that can be read/written using the
2944      * preference module API.  These preferences still use their own
2945      * configuration screens for access, but this cuts down on the
2946      * preference "string compare list" in set_pref()
2947      */
2948     extcap_module = prefs_register_module(NULL, "extcap", "Extcap Utilities",
2949         "Extcap Utilities", NULL, FALSE);
2950
2951     /* Setting default value to true */
2952     prefs.extcap_save_on_start = TRUE;
2953     prefs_register_bool_preference(extcap_module, "gui_save_on_start",
2954                                    "Save arguments on start of capture",
2955                                    "Save arguments on start of capture",
2956                                    &prefs.extcap_save_on_start);
2957 #endif
2958
2959     /* GUI
2960      * These are "simple" GUI preferences that can be read/written using the
2961      * preference module API.  These preferences still use their own
2962      * configuration screens for access, but this cuts down on the
2963      * preference "string compare list" in set_pref()
2964      */
2965     gui_module = prefs_register_module(NULL, "gui", "User Interface",
2966         "User Interface", &gui_callback, FALSE);
2967
2968     /* gui.console_open is placed first in the list so that any problems encountered
2969      *  in the following prefs can be displayed in the console window.
2970      */
2971     prefs_register_enum_preference(gui_module, "console_open",
2972                        "Open a console window",
2973                        "Open a console window (Windows only)",
2974                        (gint*)(void*)(&prefs.gui_console_open), gui_console_open_type, FALSE);
2975
2976     prefs_register_obsolete_preference(gui_module, "scrollbar_on_right");
2977     prefs_register_obsolete_preference(gui_module, "packet_list_sel_browse");
2978     prefs_register_obsolete_preference(gui_module, "protocol_tree_sel_browse");
2979
2980     prefs_register_bool_preference(gui_module, "tree_view_altern_colors",
2981                                    "Alternating colors in TreeViews",
2982                                    "Alternating colors in TreeViews?",
2983                                    &prefs.gui_altern_colors);
2984
2985     prefs_register_bool_preference(gui_module, "expert_composite_eyecandy",
2986                                    "Display Icons on Expert Composite Dialog Tabs",
2987                                    "Display Icons on Expert Composite Dialog Tabs?",
2988                                    &prefs.gui_expert_composite_eyecandy);
2989
2990     prefs_register_bool_preference(gui_module, "filter_toolbar_show_in_statusbar",
2991                                    "Place filter toolbar inside the statusbar",
2992                                    "Place filter toolbar inside the statusbar?",
2993                                    &prefs.filter_toolbar_show_in_statusbar);
2994
2995     prefs_register_enum_preference(gui_module, "protocol_tree_line_style",
2996                        "Protocol-tree line style",
2997                        "Protocol-tree line style",
2998                        &prefs.gui_ptree_line_style, gui_ptree_line_style, FALSE);
2999
3000     prefs_register_enum_preference(gui_module, "protocol_tree_expander_style",
3001                        "Protocol-tree expander style",
3002                        "Protocol-tree expander style",
3003                        &prefs.gui_ptree_expander_style, gui_ptree_expander_style, FALSE);
3004
3005     prefs_register_enum_preference(gui_module, "hex_dump_highlight_style",
3006                        "Hex dump highlight style",
3007                        "Hex dump highlight style",
3008                        &prefs.gui_hex_dump_highlight_style, gui_hex_dump_highlight_style, FALSE);
3009
3010     gui_column_module = prefs_register_subtree(gui_module, "Columns", "Columns", NULL);
3011
3012     custom_cbs.free_cb = free_string_like_preference;
3013     custom_cbs.reset_cb = reset_string_like_preference;
3014     custom_cbs.set_cb = column_hidden_set_cb;
3015     custom_cbs.type_name_cb = column_hidden_type_name_cb;
3016     custom_cbs.type_description_cb = column_hidden_type_description_cb;
3017     custom_cbs.is_default_cb = column_hidden_is_default_cb;
3018     custom_cbs.to_str_cb = column_hidden_to_str_cb;
3019     register_string_like_preference(gui_column_module, PRS_COL_HIDDEN, "Packet list hidden columns",
3020         "List all columns to hide in the packet list",
3021         &cols_hidden_list, PREF_CUSTOM, &custom_cbs, FALSE);
3022
3023     custom_cbs.free_cb = column_format_free_cb;
3024     custom_cbs.reset_cb = column_format_reset_cb;
3025     custom_cbs.set_cb = column_format_set_cb;
3026     custom_cbs.type_name_cb = column_format_type_name_cb;
3027     custom_cbs.type_description_cb = column_format_type_description_cb;
3028     custom_cbs.is_default_cb = column_format_is_default_cb;
3029     custom_cbs.to_str_cb = column_format_to_str_cb;
3030
3031     prefs_register_list_custom_preference(gui_column_module, PRS_COL_FMT, "Packet list column format",
3032         "Each pair of strings consists of a column title and its format", &custom_cbs,
3033         column_format_init_cb, &prefs.col_list);
3034
3035     /* Number of columns.  This is only used internally and is not written to the
3036      * preference file
3037      */
3038     custom_cbs.free_cb = custom_pref_no_cb;
3039     custom_cbs.reset_cb = column_num_reset_cb;
3040     custom_cbs.set_cb = column_num_set_cb;
3041     custom_cbs.type_name_cb = column_num_type_name_cb;
3042     custom_cbs.type_description_cb = column_num_type_description_cb;
3043     custom_cbs.is_default_cb = column_num_is_default_cb;
3044     custom_cbs.to_str_cb = column_num_to_str_cb;
3045     prefs_register_uint_custom_preference(gui_column_module, PRS_COL_NUM, "Number of columns",
3046         "Number of columns in col_list", &custom_cbs, &prefs.num_cols);
3047
3048     /* User Interface : Font */
3049     gui_font_module = prefs_register_subtree(gui_module, "Font", "Font", NULL);
3050
3051     prefs_register_obsolete_preference(gui_font_module, "font_name");
3052
3053     register_string_like_preference(gui_font_module, "gtk2.font_name", "Font name",
3054         "Font name for packet list, protocol tree, and hex dump panes. (GTK+)",
3055         &prefs.gui_gtk2_font_name, PREF_STRING, NULL, TRUE);
3056
3057     register_string_like_preference(gui_font_module, "qt.font_name", "Font name",
3058         "Font name for packet list, protocol tree, and hex dump panes. (Qt)",
3059         &prefs.gui_qt_font_name, PREF_STRING, NULL, TRUE);
3060
3061     /* User Interface : Colors */
3062     gui_color_module = prefs_register_subtree(gui_module, "Colors", "Colors", NULL);
3063
3064     prefs_register_color_preference(gui_color_module, "marked_frame.fg", "Color preferences for a marked frame",
3065         "Color preferences for a marked frame", &prefs.gui_marked_fg);
3066
3067     prefs_register_color_preference(gui_color_module, "marked_frame.bg", "Color preferences for a marked frame",
3068         "Color preferences for a marked frame", &prefs.gui_marked_bg);
3069
3070     prefs_register_color_preference(gui_color_module, "ignored_frame.fg", "Color preferences for a ignored frame",
3071         "Color preferences for a ignored frame", &prefs.gui_ignored_fg);
3072
3073     prefs_register_color_preference(gui_color_module, "ignored_frame.bg", "Color preferences for a ignored frame",
3074         "Color preferences for a ignored frame", &prefs.gui_ignored_bg);
3075
3076     prefs_register_color_preference(gui_color_module, "stream.client.fg", "TCP stream window color preference",
3077         "TCP stream window color preference", &prefs.st_client_fg);
3078
3079     prefs_register_color_preference(gui_color_module, "stream.client.bg", "TCP stream window color preference",
3080         "TCP stream window color preference", &prefs.st_client_bg);
3081
3082     prefs_register_color_preference(gui_color_module, "stream.server.fg", "TCP stream window color preference",
3083         "TCP stream window color preference", &prefs.st_server_fg);
3084
3085     prefs_register_color_preference(gui_color_module, "stream.server.bg", "TCP stream window color preference",
3086         "TCP stream window color preference", &prefs.st_server_bg);
3087
3088     custom_cbs.free_cb = free_string_like_preference;
3089     custom_cbs.reset_cb = reset_string_like_preference;
3090     custom_cbs.set_cb = colorized_frame_set_cb;
3091     custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3092     custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3093     custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3094     custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3095     register_string_like_preference(gui_column_module, "colorized_frame.fg", "Colorized Foreground",
3096         "Filter Colorized Foreground",
3097         &prefs.gui_colorized_fg, PREF_CUSTOM, &custom_cbs, TRUE);
3098
3099     custom_cbs.free_cb = free_string_like_preference;
3100     custom_cbs.reset_cb = reset_string_like_preference;
3101     custom_cbs.set_cb = colorized_frame_set_cb;
3102     custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3103     custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3104     custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3105     custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3106     register_string_like_preference(gui_column_module, "colorized_frame.bg", "Colorized Background",
3107         "Filter Colorized Background",
3108         &prefs.gui_colorized_bg, PREF_CUSTOM, &custom_cbs, TRUE);
3109
3110     prefs_register_color_preference(gui_color_module, "color_filter_bg.valid", "Valid color filter background",
3111         "Valid color filter background", &prefs.gui_text_valid);
3112
3113     prefs_register_color_preference(gui_color_module, "color_filter_bg.invalid", "Invalid color filter background",
3114         "Invalid color filter background", &prefs.gui_text_invalid);
3115
3116     prefs_register_color_preference(gui_color_module, "color_filter_bg.deprecated", "Deprecated color filter background",
3117         "Deprecated color filter background", &prefs.gui_text_deprecated);
3118
3119     prefs_register_enum_preference(gui_module, "fileopen.style",
3120                        "Where to start the File Open dialog box",
3121                        "Where to start the File Open dialog box",
3122                        &prefs.gui_fileopen_style, gui_fileopen_style, FALSE);
3123
3124     prefs_register_uint_preference(gui_module, "recent_files_count.max",
3125                                    "The max. number of items in the open recent files list",
3126                                    "The max. number of items in the open recent files list",
3127                                    10,
3128                                    &prefs.gui_recent_files_count_max);
3129
3130     prefs_register_uint_preference(gui_module, "recent_display_filter_entries.max",
3131                                    "The max. number of entries in the display filter list",
3132                                    "The max. number of entries in the display filter list",
3133                                    10,
3134                                    &prefs.gui_recent_df_entries_max);
3135
3136     register_string_like_preference(gui_module, "fileopen.dir", "Start Directory",
3137         "Directory to start in when opening File Open dialog.",
3138         &prefs.gui_fileopen_dir, PREF_DIRNAME, NULL, TRUE);
3139
3140     prefs_register_obsolete_preference(gui_module, "fileopen.remembered_dir");
3141
3142     prefs_register_uint_preference(gui_module, "fileopen.preview",
3143                                    "The preview timeout in the File Open dialog",
3144                                    "The preview timeout in the File Open dialog",
3145                                    10,
3146                                    &prefs.gui_fileopen_preview);
3147
3148     prefs_register_bool_preference(gui_module, "ask_unsaved",
3149                                    "Ask to save unsaved capture files",
3150                                    "Ask to save unsaved capture files?",
3151                                    &prefs.gui_ask_unsaved);
3152
3153     prefs_register_bool_preference(gui_module, "find_wrap",
3154                                    "Wrap to beginning/end of file during search",
3155                                    "Wrap to beginning/end of file during search?",
3156                                    &prefs.gui_find_wrap);
3157
3158     prefs_register_bool_preference(gui_module, "use_pref_save",
3159                                    "Settings dialogs use a save button",
3160                                    "Settings dialogs use a save button?",
3161                                    &prefs.gui_use_pref_save);
3162
3163     prefs_register_bool_preference(gui_module, "geometry.save.position",
3164                                    "Save window position at exit",
3165                                    "Save window position at exit?",
3166                                    &prefs.gui_geometry_save_position);
3167
3168     prefs_register_bool_preference(gui_module, "geometry.save.size",
3169                                    "Save window size at exit",
3170                                    "Save window size at exit?",
3171                                    &prefs.gui_geometry_save_size);
3172
3173     prefs_register_bool_preference(gui_module, "geometry.save.maximized",
3174                                    "Save window maximized state at exit",
3175                                    "Save window maximized state at exit?",
3176                                    &prefs.gui_geometry_save_maximized);
3177
3178     /* GTK+ only */
3179     prefs_register_bool_preference(gui_module, "macosx_style",
3180                                    "Use macOS style",
3181                                    "Use macOS style (macOS with native GTK only)?",
3182                                    &prefs.gui_macosx_style);
3183
3184     prefs_register_obsolete_preference(gui_module, "geometry.main.x");
3185     prefs_register_obsolete_preference(gui_module, "geometry.main.y");
3186     prefs_register_obsolete_preference(gui_module, "geometry.main.width");
3187     prefs_register_obsolete_preference(gui_module, "geometry.main.height");
3188     prefs_register_obsolete_preference(gui_module, "toolbar_main_show");
3189
3190     prefs_register_enum_preference(gui_module, "toolbar_main_style",
3191                        "Main Toolbar style",
3192                        "Main Toolbar style",
3193                        &prefs.gui_toolbar_main_style, gui_toolbar_style, FALSE);
3194
3195     prefs_register_enum_preference(gui_module, "toolbar_filter_style",
3196                        "Filter Toolbar style",
3197                        "Filter Toolbar style",
3198                        &prefs.gui_toolbar_filter_style, gui_toolbar_style, FALSE);
3199
3200     register_string_like_preference(gui_module, "webbrowser", "The path to the webbrowser",
3201         "The path to the webbrowser (Ex: mozilla)",
3202         &prefs.gui_webbrowser, PREF_STRING, NULL, TRUE);
3203
3204     prefs_register_bool_preference(gui_module, "update.enabled",
3205                                    "Check for updates",
3206                                    "Check for updates (Windows only)",
3207                                    &prefs.gui_update_enabled);
3208
3209     prefs_register_enum_preference(gui_module, "update.channel",
3210                        "Update channel",
3211                        "The type of update to fetch. You should probably leave this set to UPDATE_CHANNEL_STABLE.",
3212                        (gint*)(void*)(&prefs.gui_update_channel), gui_update_channel, FALSE);
3213
3214     prefs_register_uint_preference(gui_module, "update.interval",
3215                                    "How often to check for software updates",
3216                                    "How often to check for software updates in seconds",
3217                                    10,
3218                                    &prefs.gui_update_interval);
3219
3220     register_string_like_preference(gui_module, "window_title", "Custom window title",
3221         "Custom window title to be appended to the existing title\n%P = profile name\n%V = version info",
3222         &prefs.gui_window_title, PREF_STRING, NULL, TRUE);
3223
3224     register_string_like_preference(gui_module, "prepend_window_title", "Custom window title prefix",
3225         "Custom window title to be prepended to the existing title\n%P = profile name\n%V = version info",
3226         &prefs.gui_prepend_window_title, PREF_STRING, NULL, TRUE);
3227
3228     register_string_like_preference(gui_module, "start_title", "Custom start page title",
3229         "Custom start page title",
3230         &prefs.gui_start_title, PREF_STRING, NULL, TRUE);
3231
3232     prefs_register_enum_preference(gui_module, "version_placement",
3233                        "Show version in the start page and/or main screen's title bar",
3234                        "Show version in the start page and/or main screen's title bar",
3235                        (gint*)(void*)(&prefs.gui_version_placement), gui_version_placement_type, FALSE);
3236
3237     prefs_register_bool_preference(gui_module, "auto_scroll_on_expand",
3238                                    "Automatically scroll packet details",
3239                                    "When selecting a new packet, automatically scroll"
3240                                    "to the packet detail item that matches the most"
3241                                    "recently selected item",
3242                                    &prefs.gui_auto_scroll_on_expand);
3243
3244     prefs_register_uint_preference(gui_module, "auto_scroll_percentage",
3245                                    "Packet detail scroll percentage",
3246                                    "The percentage down the view the recently expanded detail item should be scrolled",
3247                                    10,
3248                                    &prefs.gui_auto_scroll_percentage);
3249
3250     /* User Interface : Layout */
3251     gui_layout_module = prefs_register_subtree(gui_module, "Layout", "Layout", gui_layout_callback);
3252
3253     prefs_register_uint_preference(gui_layout_module, "layout_type",
3254                                    "Layout type",
3255                                    "Layout type (1-6)",
3256                                    10,
3257                                    (guint*)(void*)(&prefs.gui_layout_type));
3258
3259     prefs_register_enum_preference(gui_layout_module, "layout_content_1",
3260                        "Layout content of the pane 1",
3261                        "Layout content of the pane 1",
3262                        (gint*)(void*)(&prefs.gui_layout_content_1), gui_layout_content, FALSE);
3263
3264     prefs_register_enum_preference(gui_layout_module, "layout_content_2",
3265                        "Layout content of the pane 2",
3266                        "Layout content of the pane 2",
3267                        (gint*)(void*)(&prefs.gui_layout_content_2), gui_layout_content, FALSE);
3268
3269     prefs_register_enum_preference(gui_layout_module, "layout_content_3",
3270                        "Layout content of the pane 3",
3271                        "Layout content of the pane 3",
3272                        (gint*)(void*)(&prefs.gui_layout_content_3), gui_layout_content, FALSE);
3273
3274     prefs_register_bool_preference(gui_layout_module, "packet_list_separator.enabled",
3275                                    "Enable Packet List Separator",
3276                                    "Enable Packet List Separator",
3277                                    &prefs.gui_qt_packet_list_separator);
3278
3279     prefs_register_bool_preference(gui_module, "packet_editor.enabled",
3280                                    "Enable Packet Editor",
3281                                    "Enable Packet Editor (Experimental)",
3282                                    &prefs.gui_packet_editor);
3283
3284     prefs_register_enum_preference(gui_module, "packet_list_elide_mode",
3285                        "Elide mode",
3286                        "The position of \"...\" in packet list text.",
3287                        (gint*)(void*)(&prefs.gui_packet_list_elide_mode), gui_packet_list_elide_mode, FALSE);
3288
3289     prefs_register_bool_preference(gui_layout_module, "packet_list_show_related",
3290                                    "Show Related Packets",
3291                                    "Show related packet indicators in the first column",
3292                                    &prefs.gui_packet_list_show_related);
3293
3294     prefs_register_bool_preference(gui_layout_module, "packet_list_show_minimap",
3295                                    "Enable Intelligent Scroll Bar",
3296                                    "Show the intelligent scroll bar (a minimap of packet list colors in the scrollbar)",
3297                                    &prefs.gui_packet_list_show_minimap);
3298
3299
3300     prefs_register_bool_preference(gui_module, "interfaces_show_hidden",
3301                                    "Show hidden interfaces",
3302                                    "Show all interfaces, including interfaces marked as hidden",
3303                                    &prefs.gui_interfaces_show_hidden);
3304
3305 #ifdef HAVE_PCAP_REMOTE
3306     prefs_register_bool_preference(gui_module, "interfaces_remote_display",
3307                                    "Show Remote interfaces",
3308                                    "Show remote interfaces in the interface selection",
3309                                    &prefs.gui_interfaces_remote_display);
3310 #endif
3311
3312     register_string_like_preference(gui_module, "interfaces_hidden_types", "Hide interface types in list",
3313         "Hide the given interface types in the startup list",
3314         &prefs.gui_interfaces_hide_types, PREF_STRING, NULL, TRUE);
3315
3316     /* Console
3317      * These are preferences that can be read/written using the
3318      * preference module API.  These preferences still use their own
3319      * configuration screens for access, but this cuts down on the
3320      * preference "string compare list" in set_pref()
3321      */
3322     console_module = prefs_register_module(NULL, "console", "Console",
3323         "Console logging and debugging output", NULL, FALSE);
3324
3325     custom_cbs.free_cb = custom_pref_no_cb;
3326     custom_cbs.reset_cb = console_log_level_reset_cb;
3327     custom_cbs.set_cb = console_log_level_set_cb;
3328     custom_cbs.type_name_cb = console_log_level_type_name_cb;
3329     custom_cbs.type_description_cb = console_log_level_type_description_cb;
3330     custom_cbs.is_default_cb = console_log_level_is_default_cb;
3331     custom_cbs.to_str_cb = console_log_level_to_str_cb;
3332     prefs_register_uint_custom_preference(console_module, "log.level", "logging level",
3333         "A bitmask of GLib log levels", &custom_cbs, &prefs.console_log_level);
3334
3335     prefs_register_bool_preference(console_module, "incomplete_dissectors_check_debug",
3336                                    "Print debug line for incomplete dissectors",
3337                                    "Look for dissectors that left some bytes undecoded (debug)",
3338                                    &prefs.incomplete_dissectors_check_debug);
3339
3340     /* Capture
3341      * These are preferences that can be read/written using the
3342      * preference module API.  These preferences still use their own
3343      * configuration screens for access, but this cuts down on the
3344      * preference "string compare list" in set_pref()
3345      */
3346     capture_module = prefs_register_module(NULL, "capture", "Capture",
3347         "Capture preferences", NULL, FALSE);
3348
3349     register_string_like_preference(capture_module, "device", "Default capture device",
3350         "Default capture device",
3351         &prefs.capture_device, PREF_STRING, NULL, FALSE);
3352
3353     register_string_like_preference(capture_module, "devices_linktypes", "Interface link-layer header type",
3354         "Interface link-layer header types (Ex: en0(1),en1(143),...)",
3355         &prefs.capture_devices_linktypes, PREF_STRING, NULL, FALSE);
3356
3357     register_string_like_preference(capture_module, "devices_descr", "Interface descriptions",
3358         "Interface descriptions (Ex: eth0(eth0 descr),eth1(eth1 descr),...)",
3359         &prefs.capture_devices_descr, PREF_STRING, NULL, FALSE);
3360
3361     register_string_like_preference(capture_module, "devices_hide", "Hide interface",
3362         "Hide interface? (Ex: eth0,eth3,...)",
3363         &prefs.capture_devices_hide, PREF_STRING, NULL, FALSE);
3364
3365     register_string_like_preference(capture_module, "devices_monitor_mode", "Capture in monitor mode",
3366         "By default, capture in monitor mode on interface? (Ex: eth0,eth3,...)",
3367         &prefs.capture_devices_monitor_mode, PREF_STRING, NULL, FALSE);
3368
3369 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
3370     register_string_like_preference(capture_module, "devices_buffersize", "Interface buffer size",
3371         "Interface buffer size (Ex: en0(1),en1(143),...)",
3372         &prefs.capture_devices_buffersize, PREF_STRING, NULL, FALSE);
3373 #endif
3374
3375     register_string_like_preference(capture_module, "devices_snaplen", "Interface snap length",
3376         "Interface snap length (Ex: en0(65535),en1(1430),...)",
3377         &prefs.capture_devices_snaplen, PREF_STRING, NULL, FALSE);
3378
3379     register_string_like_preference(capture_module, "devices_pmode", "Interface promiscuous mode",
3380         "Interface promiscuous mode (Ex: en0(0),en1(1),...)",
3381         &prefs.capture_devices_pmode, PREF_STRING, NULL, FALSE);
3382
3383     prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode",
3384         "Capture in promiscuous mode?", &prefs.capture_prom_mode);
3385
3386     register_string_like_preference(capture_module, "devices_filter", "Interface capture filter",
3387         "Interface capture filter (Ex: en0(tcp),en1(udp),...)",
3388         &prefs.capture_devices_filter, PREF_STRING, NULL, FALSE);
3389
3390     prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in Pcap-NG format",
3391         "Capture in Pcap-NG format?", &prefs.capture_pcap_ng);
3392
3393     prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture",
3394         "Update packet list in real time during capture?", &prefs.capture_real_time);
3395
3396     /* We might want to make this a "recent" setting. */
3397     prefs_register_bool_preference(capture_module, "auto_scroll", "Scroll packet list during capture",
3398         "Scroll packet list during capture?", &prefs.capture_auto_scroll);
3399
3400     /* GTK+ only */
3401     prefs_register_bool_preference(capture_module, "show_info", "Show capture info dialog while capturing",
3402         "Show capture info dialog while capturing?", &prefs.capture_show_info);
3403
3404     prefs_register_obsolete_preference(capture_module, "syntax_check_filter");
3405
3406     custom_cbs.free_cb = capture_column_free_cb;
3407     custom_cbs.reset_cb = capture_column_reset_cb;
3408     custom_cbs.set_cb = capture_column_set_cb;
3409     custom_cbs.type_name_cb = capture_column_type_name_cb;
3410     custom_cbs.type_description_cb = capture_column_type_description_cb;
3411     custom_cbs.is_default_cb = capture_column_is_default_cb;
3412     custom_cbs.to_str_cb = capture_column_to_str_cb;
3413     prefs_register_list_custom_preference(capture_module, "columns", "Capture options dialog column list",
3414         "List of columns to be displayed", &custom_cbs, capture_column_init_cb, &prefs.capture_columns);
3415
3416     /* Name Resolution */
3417     nameres_module = prefs_register_module(NULL, "nameres", "Name Resolution",
3418         "Name Resolution", NULL, TRUE);
3419     addr_resolve_pref_init(nameres_module);
3420     oid_pref_init(nameres_module);
3421 #ifdef HAVE_GEOIP
3422     geoip_db_pref_init(nameres_module);
3423 #endif
3424
3425     /* Printing */
3426     printing = prefs_register_module(NULL, "print", "Printing",
3427         "Printing", NULL, TRUE);
3428
3429     prefs_register_enum_preference(printing, "format",
3430                                    "Format", "Can be one of \"text\" or \"postscript\"",
3431                                    &prefs.pr_format, print_format_vals, TRUE);
3432
3433     prefs_register_enum_preference(printing, "destination",
3434                                    "Print to", "Can be one of \"command\" or \"file\"",
3435                                    &prefs.pr_dest, print_dest_vals, TRUE);
3436
3437 #ifndef _WIN32
3438     register_string_like_preference(printing, "command", "Command",
3439         "Output gets piped to this command when the destination is set to \"command\"",
3440         &prefs.pr_cmd, PREF_STRING, NULL, TRUE);
3441 #endif
3442
3443     register_string_like_preference(printing, "file", "File",
3444         "This is the file that gets written to when the destination is set to \"file\"",
3445         &prefs.pr_file, PREF_FILENAME, NULL, TRUE);
3446
3447     /* Statistics */
3448     stats_module = prefs_register_module(NULL, "statistics", "Statistics",
3449         "Statistics", &stats_callback, TRUE);
3450
3451     prefs_register_uint_preference(stats_module, "update_interval",
3452                                    "Tap update interval in ms",
3453                                    "Determines time between tap updates",
3454                                    10,
3455                                    &prefs.tap_update_interval);
3456
3457 #ifdef HAVE_LIBPORTAUDIO
3458     prefs_register_uint_preference(stats_module, "rtp_player_max_visible",
3459                                    "Max visible channels in RTP Player",
3460                                    "Determines maximum height of RTP Player window",
3461                                    10,
3462                                    &prefs.rtp_player_max_visible);
3463 #endif
3464
3465     prefs_register_bool_preference(stats_module, "st_enable_burstinfo",
3466             "Enable the calculation of burst information",
3467             "If enabled burst rates will be calcuted for statistics that use the stats_tree system. "
3468             "Burst rates are calculated over a much shorter time interval than the rate column.",
3469             &prefs.st_enable_burstinfo);
3470
3471     prefs_register_bool_preference(stats_module, "st_burst_showcount",
3472             "Show burst count for item rather than rate",
3473             "If selected the stats_tree statistics nodes will show the count of events "
3474             "within the burst window instead of a burst rate. Burst rate is calculated "
3475             "as number of events within burst window divided by the burst windown length.",
3476             &prefs.st_burst_showcount);
3477
3478     prefs_register_uint_preference(stats_module, "st_burst_resolution",
3479             "Burst rate resolution (ms)",
3480             "Sets the duration of the time interval into which events are grouped when calculating "
3481             "the burst rate. Higher resolution (smaller number) increases processing overhead.",
3482             10,&prefs.st_burst_resolution);
3483
3484     prefs_register_uint_preference(stats_module, "st_burst_windowlen",
3485             "Burst rate window size (ms)",
3486             "Sets the duration of the sliding window during which the burst rate is "
3487             "measured. Longer window relative to burst rate resolution increases "
3488             "processing overhead. Will be truncated to a multiple of burst resolution.",
3489             10,&prefs.st_burst_windowlen);
3490
3491     prefs_register_enum_preference(stats_module, "st_sort_defcolflag",
3492             "Default sort column for stats_tree stats",
3493             "Sets the default column by which stats based on the stats_tree "
3494             "system is sorted.",
3495             &prefs.st_sort_defcolflag, st_sort_col_vals, FALSE);
3496
3497      prefs_register_bool_preference(stats_module, "st_sort_defdescending",
3498             "Default stats_tree sort order is descending",
3499             "When selected, statistics based on the stats_tree system will by default "
3500             "be sorted in descending order.",
3501             &prefs.st_sort_defdescending);
3502
3503      prefs_register_bool_preference(stats_module, "st_sort_casesensitve",
3504             "Case sensitive sort of stats_tree item names",
3505             "When selected, the item/node names of statistics based on the stats_tree "
3506             "system will be sorted taking case into account. Else the case of the name "
3507             "will be ignored.",
3508             &prefs.st_sort_casesensitve);
3509
3510      prefs_register_bool_preference(stats_module, "st_sort_rng_nameonly",
3511             "Always sort 'range' nodes by name",
3512             "When selected, the stats_tree nodes representing a range of values "
3513             "(0-49, 50-100, etc.) will always be sorted by name (the range of the "
3514             "node). Else range nodes are sorted by the same column as the rest of "
3515             " the tree.",
3516             &prefs.st_sort_rng_nameonly);
3517
3518      prefs_register_bool_preference(stats_module, "st_sort_rng_fixorder",
3519             "Always sort 'range' nodes in ascending order",
3520             "When selected, the stats_tree nodes representing a range of values "
3521             "(0-49, 50-100, etc.) will always be sorted ascending; else it follows "
3522             "the sort direction of the tree. Only effective if \"Always sort "
3523             "'range' nodes by name\" is also selected.",
3524             &prefs.st_sort_rng_fixorder);
3525
3526      prefs_register_bool_preference(stats_module, "st_sort_showfullname",
3527             "Display the full stats_tree plug-in name",
3528             "When selected, the full name (including menu path) of the stats_tree "
3529             "plug-in is show in windows. If cleared the plug-in name is shown "
3530             "without menu path (only the part of the name after last '/' character.)",
3531             &prefs.st_sort_showfullname);
3532
3533     /* Protocols */
3534     protocols_module = prefs_register_module(NULL, "protocols", "Protocols",
3535                                              "Protocols", NULL, TRUE);
3536
3537     prefs_register_bool_preference(protocols_module, "display_hidden_proto_items",
3538                                    "Display hidden protocol items",
3539                                    "Display all hidden protocol items in the packet list.",
3540                                    &prefs.display_hidden_proto_items);
3541
3542     prefs_register_bool_preference(protocols_module, "display_byte_fields_with_spaces",
3543                                    "Display byte fields with a space character between bytes",
3544                                    "Display all byte fields with a space character between each byte in the packet list.",
3545                                    &prefs.display_byte_fields_with_spaces);
3546
3547     prefs_register_bool_preference(protocols_module, "enable_incomplete_dissectors_check",
3548                                    "Look for incomplete dissectors",
3549                                    "Look for dissectors that left some bytes undecoded.",
3550                                    &prefs.enable_incomplete_dissectors_check);
3551
3552     /* Obsolete preferences
3553      * These "modules" were reorganized/renamed to correspond to their GUI
3554      * configuration screen within the preferences dialog
3555      */
3556
3557     /* taps is now part of the stats module */
3558     prefs_register_module(NULL, "taps", "TAPS", "TAPS", NULL, FALSE);
3559     /* packet_list is now part of the protocol (parent) module */
3560     prefs_register_module(NULL, "packet_list", "PACKET_LIST", "PACKET_LIST", NULL, FALSE);
3561     /* stream is now part of the gui module */
3562     prefs_register_module(NULL, "stream", "STREAM", "STREAM", NULL, FALSE);
3563
3564 }
3565
3566 /* Parse through a list of comma-separated, possibly quoted strings.
3567    Return a list of the string data. */
3568 GList *
3569 prefs_get_string_list(const gchar *str)
3570 {
3571     enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
3572
3573     gint      state = PRE_STRING, i = 0, j = 0;
3574     gboolean  backslash = FALSE;
3575     guchar    cur_c;
3576     gchar    *slstr = NULL;
3577     GList    *sl = NULL;
3578
3579     /* Allocate a buffer for the first string.   */
3580     slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
3581     j = 0;
3582
3583     for (;;) {
3584         cur_c = str[i];
3585         if (cur_c == '\0') {
3586             /* It's the end of the input, so it's the end of the string we
3587                were working on, and there's no more input. */
3588             if (state == IN_QUOT || backslash) {
3589                 /* We were in the middle of a quoted string or backslash escape,
3590                    and ran out of characters; that's an error.  */
3591                 g_free(slstr);
3592                 prefs_clear_string_list(sl);
3593                 return NULL;
3594             }
3595             slstr[j] = '\0';
3596             sl = g_list_append(sl, slstr);
3597             break;
3598         }
3599         if (cur_c == '"' && ! backslash) {
3600             switch (state) {
3601             case PRE_STRING:
3602                 /* We hadn't yet started processing a string; this starts the
3603                    string, and we're now quoting.  */
3604                 state = IN_QUOT;
3605                 break;
3606             case IN_QUOT:
3607                 /* We're in the middle of a quoted string, and we saw a quotation
3608                    mark; we're no longer quoting.   */
3609                 state = NOT_IN_QUOT;
3610                 break;
3611             case NOT_IN_QUOT:
3612                 /* We're working on a string, but haven't seen a quote; we're
3613                    now quoting.  */
3614                 state = IN_QUOT;
3615                 break;
3616             default:
3617                 break;
3618             }
3619         } else if (cur_c == '\\' && ! backslash) {
3620             /* We saw a backslash, and the previous character wasn't a
3621                backslash; escape the next character.
3622
3623                This also means we've started a new string. */
3624             backslash = TRUE;
3625             if (state == PRE_STRING)
3626                 state = NOT_IN_QUOT;
3627         } else if (cur_c == ',' && state != IN_QUOT && ! backslash) {
3628             /* We saw a comma, and we're not in the middle of a quoted string
3629                and it wasn't preceded by a backslash; it's the end of
3630                the string we were working on...  */
3631             slstr[j] = '\0';
3632             sl = g_list_append(sl, slstr);
3633
3634             /* ...and the beginning of a new string.  */
3635             state = PRE_STRING;
3636             slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
3637             j = 0;
3638         } else if (!g_ascii_isspace(cur_c) || state != PRE_STRING) {
3639             /* Either this isn't a white-space character, or we've started a
3640                string (i.e., already seen a non-white-space character for that
3641                string and put it into the string).
3642
3643                The character is to be put into the string; do so if there's
3644                room.  */
3645             if (j < COL_MAX_LEN) {
3646                 slstr[j] = cur_c;
3647                 j++;
3648             }
3649
3650             /* If it was backslash-escaped, we're done with the backslash escape.  */
3651             backslash = FALSE;
3652         }
3653         i++;
3654     }
3655     return(sl);
3656 }
3657
3658 char *join_string_list(GList *sl)
3659 {
3660     GString      *joined_str = g_string_new("");
3661     GList        *cur, *first;
3662     gchar        *str;
3663     guint         item_count = 0;
3664
3665     cur = first = g_list_first(sl);
3666     while (cur) {
3667         item_count++;
3668         str = (gchar *)cur->data;
3669
3670         if (cur != first)
3671             g_string_append_c(joined_str, ',');
3672
3673         if (item_count % 2) {
3674             /* Wrap the line.  */
3675             g_string_append(joined_str, "\n\t");
3676         } else
3677             g_string_append_c(joined_str, ' ');
3678
3679         g_string_append_c(joined_str, '"');
3680         while (*str) {
3681             gunichar uc = g_utf8_get_char (str);
3682
3683             if (uc == '"' || uc == '\\')
3684                 g_string_append_c(joined_str, '\\');
3685
3686             if (g_unichar_isprint(uc))
3687                 g_string_append_unichar (joined_str, uc);
3688
3689             str = g_utf8_next_char (str);
3690         }
3691
3692         g_string_append_c(joined_str, '"');
3693
3694         cur = cur->next;
3695     }
3696     return g_string_free(joined_str, FALSE);
3697 }
3698
3699 void
3700 prefs_clear_string_list(GList *sl)
3701 {
3702     /* g_list_free_full() only exists since 2.28. */
3703     g_list_foreach(sl, (GFunc)g_free, NULL);
3704     g_list_free(sl);
3705 }
3706
3707 /*
3708  * Takes a string, a pointer to an array of "enum_val_t"s, and a default gint
3709  * value.
3710  * The array must be terminated by an entry with a null "name" string.
3711  *
3712  * If the string matches a "name" string in an entry, the value from that
3713  * entry is returned.
3714  *
3715  * Otherwise, if a string matches a "description" string in an entry, the
3716  * value from that entry is returned; we do that for backwards compatibility,
3717  * as we used to have only a "name" string that was used both for command-line
3718  * and configuration-file values and in the GUI (which meant either that
3719  * the GUI had what might be somewhat cryptic values to select from or that
3720  * the "-o" flag took long strings, often with spaces in them).
3721  *
3722  * Otherwise, the default value that was passed as the third argument is
3723  * returned.
3724  */
3725 static gint
3726 find_val_for_string(const char *needle, const enum_val_t *haystack,
3727                     gint default_value)
3728 {
3729     int i;
3730
3731     for (i = 0; haystack[i].name != NULL; i++) {
3732         if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
3733             return haystack[i].value;
3734         }
3735     }
3736     for (i = 0; haystack[i].name != NULL; i++) {
3737         if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
3738             return haystack[i].value;
3739         }
3740     }
3741     return default_value;
3742 }
3743
3744
3745 /* Array of columns that have been migrated to custom columns */
3746 struct deprecated_columns {
3747     const gchar *col_fmt;
3748     const gchar *col_expr;
3749 };
3750 static struct deprecated_columns migrated_columns[] = {
3751     { /* COL_COS_VALUE */ "%U", "vlan.priority" },
3752     { /* COL_CIRCUIT_ID */ "%c", "iax2.call" },
3753     { /* COL_BSSGP_TLLI */ "%l", "bssgp.tlli" },
3754     { /* COL_HPUX_SUBSYS */ "%H", "nettl.subsys" },
3755     { /* COL_HPUX_DEVID */ "%P", "nettl.devid" },
3756     { /* COL_FR_DLCI */ "%C", "fr.dlci" },
3757     { /* COL_REL_CONV_TIME */ "%rct", "tcp.time_relative" },
3758     { /* COL_DELTA_CONV_TIME */ "%dct", "tcp.time_delta" },
3759     { /* COL_OXID */ "%XO", "fc.ox_id" },
3760     { /* COL_RXID */ "%XR", "fc.rx_id" },
3761     { /* COL_SRCIDX */ "%Xd", "mdshdr.srcidx" },
3762     { /* COL_DSTIDX */ "%Xs", "mdshdr.dstidx" },
3763     { /* COL_DCE_CTX */ "%z", "dcerpc.cn_ctx_id" }
3764 };
3765
3766 static gboolean
3767 is_deprecated_column_format(const gchar* fmt)
3768 {
3769     guint haystack_idx;
3770
3771     for (haystack_idx = 0;
3772          haystack_idx < G_N_ELEMENTS(migrated_columns);
3773          ++haystack_idx) {
3774
3775         if (strcmp(migrated_columns[haystack_idx].col_fmt, fmt) == 0) {
3776             return TRUE;
3777         }
3778     }
3779
3780     return FALSE;
3781 }
3782
3783 /* Preferences file format:
3784  * - Configuration directives start at the beginning of the line, and
3785  *   are terminated with a colon.
3786  * - Directives can be continued on the next line by preceding them with
3787  *   whitespace.
3788  *
3789  * Example:
3790
3791 # This is a comment line
3792 print.command: lpr
3793 print.file: /a/very/long/path/
3794             to/wireshark-out.ps
3795  *
3796  */
3797
3798 #define DEF_NUM_COLS    7
3799
3800 /*
3801  * Parse a column format, filling in the relevant fields of a fmt_data.
3802  */
3803 static gboolean
3804 parse_column_format(fmt_data *cfmt, const char *fmt)
3805 {
3806     const gchar *cust_format = col_format_to_string(COL_CUSTOM);
3807     size_t cust_format_len = strlen(cust_format);
3808     gchar **cust_format_info;
3809     char *p;
3810     int col_fmt;
3811     gchar *col_custom_fields = NULL;
3812     long col_custom_occurrence = 0;
3813     gboolean col_resolved = TRUE;
3814
3815     /*
3816      * Is this a custom column?
3817      */
3818     if ((strlen(fmt) > cust_format_len) && (fmt[cust_format_len] == ':') &&
3819         strncmp(fmt, cust_format, cust_format_len) == 0) {
3820         /* Yes. */
3821         col_fmt = COL_CUSTOM;
3822         cust_format_info = g_strsplit(&fmt[cust_format_len+1],":",3); /* add 1 for ':' */
3823         col_custom_fields = g_strdup(cust_format_info[0]);
3824         if (col_custom_fields && cust_format_info[1]) {
3825             col_custom_occurrence = strtol(cust_format_info[1], &p, 10);
3826             if (p == cust_format_info[1] || *p != '\0') {
3827                 /* Not a valid number. */
3828                 g_free(col_custom_fields);
3829                 g_strfreev(cust_format_info);
3830                 return FALSE;
3831             }
3832         }
3833         if (col_custom_fields && cust_format_info[1] && cust_format_info[2]) {
3834             col_resolved = (cust_format_info[2][0] == 'U') ? FALSE : TRUE;
3835         }
3836         g_strfreev(cust_format_info);
3837     } else {
3838         col_fmt = get_column_format_from_str(fmt);
3839         if ((col_fmt == -1) && (!is_deprecated_column_format(fmt)))
3840             return FALSE;
3841     }
3842
3843     cfmt->fmt = col_fmt;
3844     cfmt->custom_fields = col_custom_fields;
3845     cfmt->custom_occurrence = (int)col_custom_occurrence;
3846     cfmt->resolved = col_resolved;
3847     return TRUE;
3848 }
3849
3850 /* Initialize non-dissector preferences to wired-in default values Called
3851  * at program startup and any time the profile changes. (The dissector
3852  * preferences are assumed to be set to those values by the dissectors.)
3853  * They may be overridden by the global preferences file or the user's
3854  * preferences file.
3855  */
3856 static void
3857 init_prefs(void)
3858 {
3859     if (prefs_initialized)
3860         return;
3861
3862     uat_load_all();
3863
3864     /*
3865      * Ensure the "global" preferences have been initialized so the
3866      * preference API has the proper default values to work from
3867      */
3868     pre_init_prefs();
3869
3870     prefs_register_modules();
3871
3872     filter_expression_init();
3873
3874     prefs_initialized = TRUE;
3875 }
3876
3877 /*
3878  * Initialize non-dissector preferences used by the "register preference" API
3879  * to default values so the default values can be used when registered.
3880  *
3881  * String, filename, and directory preferences will be g_freed so they must
3882  * be g_mallocated.
3883  */
3884 static void
3885 pre_init_prefs(void)
3886 {
3887     int         i;
3888     gchar       *col_name;
3889     fmt_data    *cfmt;
3890     static const gchar *col_fmt[DEF_NUM_COLS*2] = {
3891         "No.",      "%m", "Time",        "%t",
3892         "Source",   "%s", "Destination", "%d",
3893         "Protocol", "%p", "Length",      "%L",
3894         "Info",     "%i"};
3895
3896     prefs.pr_format  = PR_FMT_TEXT;
3897     prefs.pr_dest    = PR_DEST_CMD;
3898     if (prefs.pr_file) g_free(prefs.pr_file);
3899     prefs.pr_file    = g_strdup("wireshark.out");
3900     if (prefs.pr_cmd) g_free(prefs.pr_cmd);
3901     prefs.pr_cmd     = g_strdup("lpr");
3902
3903     prefs.gui_altern_colors = FALSE;
3904     prefs.gui_expert_composite_eyecandy = FALSE;
3905     prefs.gui_ptree_line_style = 0;
3906     prefs.gui_ptree_expander_style = 1;
3907     prefs.gui_hex_dump_highlight_style = 1;
3908     prefs.filter_toolbar_show_in_statusbar = FALSE;
3909     prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
3910     prefs.gui_toolbar_filter_style = TB_STYLE_TEXT;
3911     /* These will be g_freed, so they must be g_mallocated. */
3912     if (prefs.gui_gtk2_font_name) g_free(prefs.gui_gtk2_font_name);
3913 #ifdef _WIN32
3914     prefs.gui_gtk2_font_name         = g_strdup("Lucida Console 10");
3915 #else
3916     prefs.gui_gtk2_font_name         = g_strdup("Monospace 10");
3917 #endif
3918     /* We try to find the best font in the Qt code */
3919     if (prefs.gui_qt_font_name) g_free(prefs.gui_qt_font_name);
3920     prefs.gui_qt_font_name           = g_strdup("");
3921     prefs.gui_marked_fg.red          =     65535;
3922     prefs.gui_marked_fg.green        =     65535;
3923     prefs.gui_marked_fg.blue         =     65535;
3924     prefs.gui_marked_bg.red          =         0;
3925     prefs.gui_marked_bg.green        =      8224;
3926     prefs.gui_marked_bg.blue         =     10794;
3927     prefs.gui_ignored_fg.red         =     32767;
3928     prefs.gui_ignored_fg.green       =     32767;
3929     prefs.gui_ignored_fg.blue        =     32767;
3930     prefs.gui_ignored_bg.red         =     65535;
3931     prefs.gui_ignored_bg.green       =     65535;
3932     prefs.gui_ignored_bg.blue        =     65535;
3933     if (prefs.gui_colorized_fg) g_free(prefs.gui_colorized_fg);
3934     prefs.gui_colorized_fg           = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
3935     if (prefs.gui_colorized_bg) g_free(prefs.gui_colorized_bg);
3936     prefs.gui_colorized_bg           = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
3937     prefs.st_client_fg.red           = 32767;
3938     prefs.st_client_fg.green         =     0;
3939     prefs.st_client_fg.blue          =     0;
3940     prefs.st_client_bg.red           = 64507;
3941     prefs.st_client_bg.green         = 60909;
3942     prefs.st_client_bg.blue          = 60909;
3943     prefs.st_server_fg.red           =     0;
3944     prefs.st_server_fg.green         =     0;
3945     prefs.st_server_fg.blue          = 32767;
3946     prefs.st_server_bg.red           = 60909;
3947     prefs.st_server_bg.green         = 60909;
3948     prefs.st_server_bg.blue          = 64507;
3949     prefs.gui_text_valid.red         = 0xAFFF; /* light green */
3950     prefs.gui_text_valid.green       = 0xFFFF;
3951     prefs.gui_text_valid.blue        = 0xAFFF;
3952     prefs.gui_text_invalid.red       = 0xFFFF; /* light red */
3953     prefs.gui_text_invalid.green     = 0xAFFF;
3954     prefs.gui_text_invalid.blue      = 0xAFFF;
3955     prefs.gui_text_deprecated.red    = 0xFFFF; /* light yellow */
3956     prefs.gui_text_deprecated.green  = 0xFFFF;
3957     prefs.gui_text_deprecated.blue   = 0xAFFF;
3958     prefs.gui_geometry_save_position = TRUE;
3959     prefs.gui_geometry_save_size     = TRUE;
3960     prefs.gui_geometry_save_maximized= TRUE;
3961     prefs.gui_macosx_style           = TRUE;
3962     prefs.gui_console_open           = console_open_never;
3963     prefs.gui_fileopen_style         = FO_STYLE_LAST_OPENED;
3964     prefs.gui_recent_df_entries_max  = 10;
3965     prefs.gui_recent_files_count_max = 10;
3966     if (prefs.gui_fileopen_dir) g_free(prefs.gui_fileopen_dir);
3967     prefs.gui_fileopen_dir           = g_strdup(get_persdatafile_dir());
3968     prefs.gui_fileopen_preview       = 3;
3969     prefs.gui_ask_unsaved            = TRUE;
3970     prefs.gui_find_wrap              = TRUE;
3971     prefs.gui_use_pref_save          = FALSE;
3972     prefs.gui_update_enabled         = TRUE;
3973     prefs.gui_update_channel         = UPDATE_CHANNEL_STABLE;
3974     prefs.gui_update_interval        = 60*60*24; /* Seconds */
3975     if (prefs.gui_webbrowser) g_free(prefs.gui_webbrowser);
3976     prefs.gui_webbrowser             = g_strdup("");
3977     if (prefs.gui_window_title) g_free(prefs.gui_window_title);
3978     prefs.gui_window_title           = g_strdup("");
3979     if (prefs.gui_prepend_window_title) g_free(prefs.gui_prepend_window_title);
3980     prefs.gui_prepend_window_title   = g_strdup("");
3981     if (prefs.gui_start_title) g_free(prefs.gui_start_title);
3982     prefs.gui_start_title            = g_strdup("The World's Most Popular Network Protocol Analyzer");
3983     prefs.gui_version_placement      = version_both;
3984     prefs.gui_auto_scroll_on_expand  = FALSE;
3985     prefs.gui_auto_scroll_percentage = 0;
3986     prefs.gui_layout_type            = layout_type_5;
3987     prefs.gui_layout_content_1       = layout_pane_content_plist;
3988     prefs.gui_layout_content_2       = layout_pane_content_pdetails;
3989     prefs.gui_layout_content_3       = layout_pane_content_pbytes;
3990     prefs.gui_packet_editor          = FALSE;
3991     prefs.gui_packet_list_elide_mode = ELIDE_RIGHT;
3992     prefs.gui_packet_list_show_related = TRUE;
3993     prefs.gui_packet_list_show_minimap = TRUE;
3994     if (prefs.gui_interfaces_hide_types) g_free (prefs.gui_interfaces_hide_types);
3995     prefs.gui_interfaces_hide_types = g_strdup("");
3996     prefs.gui_interfaces_show_hidden = FALSE;
3997 #ifdef HAVE_PCAP_REMOTE
3998     prefs.gui_interfaces_remote_display = TRUE;
3999 #endif
4000
4001     prefs.gui_qt_packet_list_separator = FALSE;
4002
4003     if (prefs.col_list) {
4004         free_col_info(prefs.col_list);
4005         prefs.col_list = NULL;
4006     }
4007     for (i = 0; i < DEF_NUM_COLS; i++) {
4008         cfmt = g_new(fmt_data,1);
4009         cfmt->title = g_strdup(col_fmt[i * 2]);
4010         parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
4011         cfmt->visible = TRUE;
4012         cfmt->resolved = TRUE;
4013         cfmt->custom_fields = NULL;
4014         cfmt->custom_occurrence = 0;
4015         prefs.col_list = g_list_append(prefs.col_list, cfmt);
4016     }
4017     prefs.num_cols  = DEF_NUM_COLS;
4018
4019 /* set the default values for the capture dialog box */
4020     prefs.capture_prom_mode             = TRUE;
4021 #ifdef PCAP_NG_DEFAULT
4022     prefs.capture_pcap_ng               = TRUE;
4023 #else
4024     prefs.capture_pcap_ng               = FALSE;
4025 #endif
4026     prefs.capture_real_time             = TRUE;
4027     prefs.capture_auto_scroll           = TRUE;
4028     prefs.capture_show_info             = FALSE;
4029
4030     if (!prefs.capture_columns) {
4031         /* First time through */
4032         for (i = 0; i < num_capture_cols; i++) {
4033             col_name = g_strdup(capture_cols[i]);
4034             prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
4035         }
4036     }
4037
4038     prefs.console_log_level          =
4039         G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
4040
4041 /* set the default values for the tap/statistics dialog box */
4042     prefs.tap_update_interval    = TAP_UPDATE_DEFAULT_INTERVAL;
4043     prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
4044     prefs.st_enable_burstinfo = TRUE;
4045     prefs.st_burst_showcount = FALSE;
4046     prefs.st_burst_resolution = ST_DEF_BURSTRES;
4047     prefs.st_burst_windowlen = ST_DEF_BURSTLEN;
4048     prefs.st_sort_casesensitve = TRUE;
4049     prefs.st_sort_rng_fixorder = TRUE;
4050     prefs.st_sort_rng_nameonly = TRUE;
4051     prefs.st_sort_defcolflag = ST_SORT_COL_COUNT;
4052     prefs.st_sort_defdescending = TRUE;
4053     prefs.st_sort_showfullname = FALSE;
4054     prefs.display_hidden_proto_items = FALSE;
4055     prefs.display_byte_fields_with_spaces = FALSE;
4056 }
4057
4058 /*
4059  * Reset a single dissector preference.
4060  */
4061 void
4062 reset_pref(pref_t *pref)
4063 {
4064     int type;
4065     if (!pref) return;
4066
4067     type = pref->type;
4068
4069     /*
4070      * This preference is no longer supported; it's not a
4071      * real preference, so we don't reset it (i.e., we
4072      * treat it as if it weren't found in the list of
4073      * preferences, and we weren't called in the first place).
4074      */
4075     if (IS_PREF_OBSOLETE(type))
4076         return;
4077     else
4078         RESET_PREF_OBSOLETE(type);
4079
4080     switch (type) {
4081
4082     case PREF_UINT:
4083     case PREF_DECODE_AS_UINT:
4084         *pref->varp.uint = pref->default_val.uint;
4085         break;
4086
4087     case PREF_BOOL:
4088         *pref->varp.boolp = pref->default_val.boolval;
4089         break;
4090
4091     case PREF_ENUM:
4092         /*
4093          * For now, we save the "description" value, so that if we
4094          * save the preferences older versions of Wireshark can at
4095          * least read preferences that they supported; we support
4096          * either the short name or the description when reading
4097          * the preferences file or a "-o" option.
4098          */
4099         *pref->varp.enump = pref->default_val.enumval;
4100         break;
4101
4102     case PREF_STRING:
4103     case PREF_FILENAME:
4104     case PREF_DIRNAME:
4105         reset_string_like_preference(pref);
4106         break;
4107
4108     case PREF_RANGE:
4109     case PREF_DECODE_AS_RANGE:
4110         wmem_free(wmem_epan_scope(), *pref->varp.range);
4111         *pref->varp.range = range_copy(wmem_epan_scope(), pref->default_val.range);
4112         break;
4113
4114     case PREF_STATIC_TEXT:
4115     case PREF_UAT:
4116         /* Nothing to do */
4117         break;
4118
4119     case PREF_COLOR:
4120         *pref->varp.colorp = pref->default_val.color;
4121         break;
4122
4123     case PREF_CUSTOM:
4124         pref->custom_cbs.reset_cb(pref);
4125         break;
4126     }
4127 }
4128
4129 static void
4130 reset_pref_cb(gpointer data, gpointer user_data _U_)
4131 {
4132     pref_t *pref = (pref_t *) data;
4133     reset_pref(pref);
4134 }
4135
4136 typedef struct {
4137     module_t *module;
4138 } reset_pref_arg_t;
4139
4140 /*
4141  * Reset all preferences for a module.
4142  */
4143 static gboolean
4144 reset_module_prefs(const void *key _U_, void *value, void *data _U_)
4145 {
4146     reset_pref_arg_t arg;
4147
4148     arg.module = (module_t *)value;
4149     g_list_foreach(arg.module->prefs, reset_pref_cb, &arg);
4150     return FALSE;
4151 }
4152
4153 /* Reset preferences */
4154 void
4155 prefs_reset(void)
4156 {
4157     prefs_initialized = FALSE;
4158     g_free(prefs.saved_at_version);
4159     prefs.saved_at_version = NULL;
4160
4161     /*
4162      * Unload all UAT preferences.
4163      */
4164     uat_unload_all();
4165
4166     /*
4167      * Unload any loaded MIBs.
4168      */
4169     oids_cleanup();
4170
4171     /*
4172      * Free the filter expression list.
4173      */
4174     filter_expression_free(*pfilter_expression_head);
4175     *pfilter_expression_head = NULL;
4176
4177     /*
4178      * Reset the non-dissector preferences.
4179      */
4180     init_prefs();
4181
4182     /*
4183      * Reset the non-UAT dissector preferences.
4184      */
4185     wmem_tree_foreach(prefs_modules, reset_module_prefs, NULL);
4186 }
4187
4188 /* Read the preferences file, fill in "prefs", and return a pointer to it.
4189
4190    If we got an error (other than "it doesn't exist") we report it through
4191    the UI. */
4192 e_prefs *
4193 read_prefs(void)
4194 {
4195     int         err;
4196     char        *pf_path;
4197     FILE        *pf;
4198
4199     /* clean up libsmi structures before reading prefs */
4200     oids_cleanup();
4201
4202     init_prefs();
4203
4204     /*
4205      * If we don't already have the pathname of the global preferences
4206      * file, construct it.  Then, in either case, try to open the file.
4207      */
4208     if (gpf_path == NULL) {
4209         /*
4210          * We don't have the path; try the new path first, and, if that
4211          * file doesn't exist, try the old path.
4212          */
4213         gpf_path = get_datafile_path(PF_NAME);
4214         if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
4215             /*
4216              * It doesn't exist by the new name; try the old name.
4217              */
4218             g_free(gpf_path);
4219             gpf_path = get_datafile_path(OLD_GPF_NAME);
4220             pf = ws_fopen(gpf_path, "r");
4221         }
4222     } else {
4223         /*
4224          * We have the path; try it.
4225          */
4226         pf = ws_fopen(gpf_path, "r");
4227     }
4228
4229     /*
4230      * If we were able to open the file, read it.
4231      * XXX - if it failed for a reason other than "it doesn't exist",
4232      * report the error.
4233      */
4234     if (pf != NULL) {
4235         /*
4236          * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4237          * seen.
4238          */
4239         mgcp_tcp_port_count = 0;
4240         mgcp_udp_port_count = 0;
4241
4242         /* We succeeded in opening it; read it. */
4243         err = read_prefs_file(gpf_path, pf, set_pref, NULL);
4244         if (err != 0) {
4245             /* We had an error reading the file; report it. */
4246             report_warning("Error reading global preferences file \"%s\": %s.",
4247                            gpf_path, g_strerror(err));
4248         }
4249         fclose(pf);
4250     } else {
4251         /* We failed to open it.  If we failed for some reason other than
4252            "it doesn't exist", report the error. */
4253         if (errno != ENOENT) {
4254             if (errno != 0) {
4255                 report_warning("Can't open global preferences file \"%s\": %s.",
4256                                gpf_path, g_strerror(errno));
4257             }
4258         }
4259     }
4260
4261     /* Construct the pathname of the user's preferences file. */
4262     pf_path = get_persconffile_path(PF_NAME, TRUE);
4263
4264     /* Read the user's preferences file, if it exists. *