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