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