2 * Recent "preference" handling routines
3 * Copyright 2004, Ulf Lamping <ulf.lamping@web.de>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "capture_opts.h"
31 #include <wsutil/filesystem.h>
32 #include <epan/prefs.h>
33 #include <epan/prefs-int.h>
34 #include <epan/column.h>
35 #include <epan/value_string.h>
37 #include "ui/last_open_dir.h"
38 #include "ui/recent.h"
39 #include "ui/recent_utils.h"
40 #include "ui/simple_dialog.h"
42 #include <wsutil/u3.h>
43 #include <wsutil/file_util.h>
45 #define RECENT_KEY_MAIN_TOOLBAR_SHOW "gui.toolbar_main_show"
46 #define RECENT_KEY_FILTER_TOOLBAR_SHOW "gui.filter_toolbar_show"
47 #define RECENT_KEY_WIRELESS_TOOLBAR_SHOW "gui.wireless_toolbar_show"
48 #define RECENT_KEY_DRIVER_CHECK_SHOW "gui.airpcap_driver_check_show"
49 #define RECENT_KEY_PACKET_LIST_SHOW "gui.packet_list_show"
50 #define RECENT_KEY_TREE_VIEW_SHOW "gui.tree_view_show"
51 #define RECENT_KEY_BYTE_VIEW_SHOW "gui.byte_view_show"
52 #define RECENT_KEY_STATUSBAR_SHOW "gui.statusbar_show"
53 #define RECENT_KEY_PACKET_LIST_COLORIZE "gui.packet_list_colorize"
54 #define RECENT_GUI_TIME_FORMAT "gui.time_format"
55 #define RECENT_GUI_TIME_PRECISION "gui.time_precision"
56 #define RECENT_GUI_SECONDS_FORMAT "gui.seconds_format"
57 #define RECENT_GUI_ZOOM_LEVEL "gui.zoom_level"
58 #define RECENT_GUI_BYTES_VIEW "gui.bytes_view"
59 #define RECENT_GUI_GEOMETRY_MAIN_X "gui.geometry_main_x"
60 #define RECENT_GUI_GEOMETRY_MAIN_Y "gui.geometry_main_y"
61 #define RECENT_GUI_GEOMETRY_MAIN_WIDTH "gui.geometry_main_width"
62 #define RECENT_GUI_GEOMETRY_MAIN_HEIGHT "gui.geometry_main_height"
63 #define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized"
64 #define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane"
65 #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane"
66 #define RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT "gui.geometry_status_pane"
67 #define RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT "gui.geometry_status_pane_right"
68 #define RECENT_GUI_GEOMETRY_WLAN_STATS_PANE "gui.geometry_status_wlan_stats_pane"
69 #define RECENT_LAST_USED_PROFILE "gui.last_used_profile"
70 #define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir"
71 #define RECENT_GUI_CONVERSATION_TABS "gui.conversation_tabs"
72 #define RECENT_GUI_ENDPOINT_TABS "gui.endpoint_tabs"
73 #define RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES "gui.rlc_pdus_from_mac_frames"
74 #define RECENT_GUI_CUSTOM_COLORS "gui.custom_colors"
76 #define RECENT_GUI_GEOMETRY "gui.geom."
78 #define RECENT_KEY_PRIVS_WARN_IF_ELEVATED "privs.warn_if_elevated"
79 #define RECENT_KEY_PRIVS_WARN_IF_NO_NPF "privs.warn_if_no_npf"
81 #define RECENT_FILE_NAME "recent"
82 #define RECENT_COMMON_FILE_NAME "recent_common"
84 recent_settings_t recent;
86 static const value_string ts_type_values[] = {
87 { TS_RELATIVE, "RELATIVE" },
88 { TS_ABSOLUTE, "ABSOLUTE" },
89 { TS_ABSOLUTE_WITH_YMD, "ABSOLUTE_WITH_YMD" },
90 { TS_ABSOLUTE_WITH_YDOY, "ABSOLUTE_WITH_YDOY" },
91 { TS_ABSOLUTE_WITH_YMD, "ABSOLUTE_WITH_DATE" }, /* Backward compability */
92 { TS_DELTA, "DELTA" },
93 { TS_DELTA_DIS, "DELTA_DIS" },
94 { TS_EPOCH, "EPOCH" },
96 { TS_UTC_WITH_YMD, "UTC_WITH_YMD" },
97 { TS_UTC_WITH_YDOY, "UTC_WITH_YDOY" },
98 { TS_UTC_WITH_YMD, "UTC_WITH_DATE" }, /* Backward compability */
102 static const value_string ts_precision_values[] = {
103 { TS_PREC_AUTO, "AUTO" },
104 { TS_PREC_FIXED_SEC, "SEC" },
105 { TS_PREC_FIXED_DSEC, "DSEC" },
106 { TS_PREC_FIXED_CSEC, "CSEC" },
107 { TS_PREC_FIXED_MSEC, "MSEC" },
108 { TS_PREC_FIXED_USEC, "USEC" },
109 { TS_PREC_FIXED_NSEC, "NSEC" },
113 static const value_string ts_seconds_values[] = {
114 { TS_SECONDS_DEFAULT, "SECONDS" },
115 { TS_SECONDS_HOUR_MIN_SEC, "HOUR_MIN_SEC" },
120 free_col_width_info(recent_settings_t *rs)
122 col_width_data *cfmt;
124 while (rs->col_width_list != NULL) {
125 cfmt = (col_width_data *)rs->col_width_list->data;
126 g_free(cfmt->cfield);
128 rs->col_width_list = g_list_remove_link(rs->col_width_list, rs->col_width_list);
130 g_list_free(rs->col_width_list);
131 rs->col_width_list = NULL;
134 /** Write the geometry values of a single window to the recent file.
137 * @param value the geometry values
138 * @param rfh recent file handle (FILE)
141 write_recent_geom(gpointer key _U_, gpointer value, gpointer rfh)
143 window_geometry_t *geom = (window_geometry_t *)value;
144 FILE *rf = (FILE *)rfh;
146 fprintf(rf, "\n# Geometry and maximized state of %s window.\n", geom->key);
147 fprintf(rf, "# Decimal integers.\n");
148 fprintf(rf, RECENT_GUI_GEOMETRY "%s.x: %d\n", geom->key, geom->x);
149 fprintf(rf, RECENT_GUI_GEOMETRY "%s.y: %d\n", geom->key, geom->y);
150 fprintf(rf, RECENT_GUI_GEOMETRY "%s.width: %d\n", geom->key,
152 fprintf(rf, RECENT_GUI_GEOMETRY "%s.height: %d\n", geom->key,
155 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
156 fprintf(rf, RECENT_GUI_GEOMETRY "%s.maximized: %s\n", geom->key,
157 geom->maximized == TRUE ? "TRUE" : "FALSE");
161 /* the geometry hashtable for all known window classes,
162 * the window name is the key, and the geometry struct is the value */
163 static GHashTable *window_geom_hash = NULL;
165 /* save the window and its current geometry into the geometry hashtable */
167 window_geom_save(const gchar *name, window_geometry_t *geom)
170 window_geometry_t *work;
172 /* init hashtable, if not already done */
173 if (!window_geom_hash) {
174 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
176 /* if we have an old one, remove and free it first */
177 work = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name);
179 g_hash_table_remove(window_geom_hash, name);
184 /* g_malloc and insert the new one */
185 work = (window_geometry_t *)g_malloc(sizeof(window_geometry_t));
187 key = g_strdup(name);
189 g_hash_table_insert(window_geom_hash, key, work);
192 /* load the desired geometry for this window from the geometry hashtable */
194 window_geom_load(const gchar *name,
195 window_geometry_t *geom)
197 window_geometry_t *p;
199 /* init hashtable, if not already done */
200 if (!window_geom_hash) {
201 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
204 p = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name);
213 /* parse values of particular types */
215 parse_recent_boolean(const gchar *val_str, gboolean *valuep)
217 if (g_ascii_strcasecmp(val_str, "true") == 0) {
225 /** Read in a single geometry key value pair from the recent file.
227 * @param name the geom_name of the window
228 * @param key the subkey of this pair (e.g. "x")
229 * @param value the new value (e.g. "123")
232 window_geom_recent_read_pair(const char *name,
236 window_geometry_t geom;
238 /* find window geometry maybe already in hashtable */
239 if (!window_geom_load(name, &geom)) {
240 /* not in table, init geom with "basic" values */
241 geom.key = NULL; /* Will be set in window_geom_save() */
242 geom.set_pos = FALSE;
245 geom.set_size = FALSE;
249 geom.set_maximized = FALSE;/* this is valid in GTK2 only */
250 geom.maximized = FALSE; /* this is valid in GTK2 only */
253 if (strcmp(key, "x") == 0) {
254 geom.x = (gint)strtol(value, NULL, 10);
256 } else if (strcmp(key, "y") == 0) {
257 geom.y = (gint)strtol(value, NULL, 10);
259 } else if (strcmp(key, "width") == 0) {
260 geom.width = (gint)strtol(value, NULL, 10);
261 geom.set_size = TRUE;
262 } else if (strcmp(key, "height") == 0) {
263 geom.height = (gint)strtol(value, NULL, 10);
264 geom.set_size = TRUE;
265 } else if (strcmp(key, "maximized") == 0) {
266 parse_recent_boolean(value, &geom.maximized);
267 geom.set_maximized = TRUE;
270 * Silently ignore the bogus key. We shouldn't abort here,
271 * as this could be due to a corrupt recent file.
273 * XXX - should we print a message about this?
278 /* save / replace geometry in hashtable */
279 window_geom_save(name, &geom);
282 /** Write all geometry values of all windows to the recent file.
283 * Will call write_recent_geom() for every existing window type.
285 * @param rf recent file handle from caller
288 window_geom_recent_write_all(FILE *rf)
290 /* init hashtable, if not already done */
291 if (!window_geom_hash) {
292 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
295 g_hash_table_foreach(window_geom_hash, write_recent_geom, rf);
298 /* Global list of recent capture filters. */
299 static GList *recent_cfilter_list;
302 * Per-interface lists of recent capture filters; stored in a hash
303 * table indexed by interface name.
305 static GHashTable *per_interface_cfilter_lists_hash;
307 /* XXX: use a preference for this setting! */
308 static guint cfilter_combo_max_recent = 20;
311 * Returns a list of recent capture filters.
313 * @param ifname interface name; NULL refers to the global list.
316 recent_get_cfilter_list(const gchar *ifname)
319 return recent_cfilter_list;
320 if (per_interface_cfilter_lists_hash == NULL) {
321 /* No such lists exist. */
324 return (GList *)g_hash_table_lookup(per_interface_cfilter_lists_hash, ifname);
328 * Add a capture filter to the global recent capture filter list or
329 * the recent capture filter list for an interface.
331 * @param ifname interface name; NULL refers to the global list.
332 * @param s text of capture filter
335 recent_add_cfilter(const gchar *ifname, const gchar *s)
339 gchar *li_filter, *newfilter = NULL;
341 /* Don't add empty filters to the list. */
346 cfilter_list = recent_cfilter_list;
348 /* If we don't yet have a hash table for per-interface recent
349 capture filter lists, create one. Have it free the new key
350 if we're updating an entry rather than creating it below. */
351 if (per_interface_cfilter_lists_hash == NULL)
352 per_interface_cfilter_lists_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
353 cfilter_list = (GList *)g_hash_table_lookup(per_interface_cfilter_lists_hash, ifname);
356 li = g_list_first(cfilter_list);
358 /* If the filter is already in the list, remove the old one and
359 * append the new one at the latest position (at g_list_append() below) */
360 li_filter = (char *)li->data;
361 if (strcmp(s, li_filter) == 0) {
362 /* No need to copy the string, we're just moving it. */
363 newfilter = li_filter;
364 cfilter_list = g_list_remove(cfilter_list, li->data);
369 if (newfilter == NULL) {
370 /* The filter wasn't already in the list; make a copy to add. */
371 newfilter = g_strdup(s);
373 cfilter_list = g_list_append(cfilter_list, newfilter);
376 recent_cfilter_list = cfilter_list;
378 g_hash_table_insert(per_interface_cfilter_lists_hash, g_strdup(ifname), cfilter_list);
381 #ifdef HAVE_PCAP_REMOTE
382 static GHashTable *remote_host_list=NULL;
384 int recent_get_remote_host_list_size(void)
386 return g_hash_table_size (remote_host_list);
389 void recent_add_remote_host(gchar *host, struct remote_host *rh)
391 if (remote_host_list == NULL) {
392 remote_host_list = g_hash_table_new (g_str_hash, g_str_equal);
394 g_hash_table_insert (remote_host_list, g_strdup(host), rh);
398 free_remote_host (gpointer key _U_, gpointer value, gpointer user _U_)
400 struct remote_host *rh = value;
403 g_free (rh->remote_port);
404 g_free (rh->auth_username);
405 g_free (rh->auth_password);
410 GHashTable *get_remote_host_list(void)
412 return remote_host_list;
416 recent_print_remote_host (gpointer key _U_, gpointer value, gpointer user)
419 struct remote_host_info *ri = value;
421 fprintf (rf, RECENT_KEY_REMOTE_HOST ": %s,%s,%d\n", ri->remote_host, ri->remote_port, ri->auth_type);
425 capture_remote_combo_recent_write_all(FILE *rf)
427 if (remote_host_list && g_hash_table_size (remote_host_list) > 0) {
428 /* Write all remote interfaces to the recent file */
429 g_hash_table_foreach (remote_host_list, recent_print_remote_host, rf);
434 void free_remote_host_list(void)
436 g_hash_table_foreach_remove(remote_host_list, free_remote_host, NULL);
440 recent_get_remote_host(const gchar *host)
444 if (remote_host_list == NULL) {
445 /* No such host exist. */
448 return (struct remote_host *)g_hash_table_lookup(remote_host_list, host);
452 capture_remote_combo_add_recent(const gchar *s)
454 GList *vals = prefs_get_string_list (s);
458 struct remote_host *rh;
463 if (remote_host_list == NULL) {
464 remote_host_list = g_hash_table_new (g_str_hash, g_str_equal);
467 rh = g_malloc (sizeof (*rh));
469 /* First value is the host */
470 rh->r_host = g_strdup (valp->data);
471 if (strlen(rh->r_host) == 0) {
472 /* Empty remote host */
477 rh->auth_type = CAPTURE_AUTH_NULL;
481 /* Found value 2, this is the port number */
482 rh->remote_port = g_strdup (valp->data);
485 /* Did not find a port number */
486 rh->remote_port = g_strdup ("");
490 /* Found value 3, this is the authentication type */
491 auth_type = strtol(valp->data, &p, 0);
492 if (p != valp->data && *p == '\0') {
493 rh->auth_type = auth_type;
497 /* Do not store username and password */
498 rh->auth_username = g_strdup ("");
499 rh->auth_password = g_strdup ("");
501 prefs_clear_string_list(vals);
503 g_hash_table_insert (remote_host_list, g_strdup(rh->r_host), rh);
510 cfilter_recent_write_all_list(FILE *rf, const gchar *ifname, GList *cfilter_list)
515 /* write all non empty capture filter strings to the recent file (until max count) */
516 li = g_list_first(cfilter_list);
517 while (li && (max_count++ <= cfilter_combo_max_recent) ) {
518 if (li->data && strlen((const char *)li->data)) {
520 fprintf (rf, RECENT_KEY_CAPTURE_FILTER ": %s\n", (char *)li->data);
522 fprintf (rf, RECENT_KEY_CAPTURE_FILTER ".%s: %s\n", ifname, (char *)li->data);
529 cfilter_recent_write_all_hash_callback(gpointer key, gpointer value, gpointer user_data)
531 cfilter_recent_write_all_list((FILE *)user_data, (const gchar *)key, (GList *)value);
534 /** Write all capture filter values to the recent file.
536 * @param rf recent file handle from caller
539 cfilter_recent_write_all(FILE *rf)
541 /* Write out the global list. */
542 cfilter_recent_write_all_list(rf, NULL, recent_cfilter_list);
544 /* Write out all the per-interface lists. */
545 if (per_interface_cfilter_lists_hash != NULL) {
546 g_hash_table_foreach(per_interface_cfilter_lists_hash, cfilter_recent_write_all_hash_callback, (gpointer)rf);
550 /* Write out recent settings of particular types. */
552 write_recent_boolean(FILE *rf, const char *description, const char *name,
555 fprintf(rf, "\n# %s.\n", description);
556 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
557 fprintf(rf, "%s: %s\n", name, value == TRUE ? "TRUE" : "FALSE");
561 write_recent_enum(FILE *rf, const char *description, const char *name,
562 const value_string *values, guint value)
564 const char *if_invalid = NULL;
565 const value_string *valp;
567 fprintf(rf, "\n# %s.\n", description);
568 fprintf(rf, "# One of: ");
570 while (valp->strptr != NULL) {
571 if (if_invalid == NULL)
572 if_invalid = valp->strptr;
573 fprintf(rf, "%s", valp->strptr);
575 if (valp->strptr != NULL)
579 fprintf(rf, "%s: %s\n", name,
580 val_to_str(value, values, if_invalid != NULL ? if_invalid : "Unknown"));
583 /* Attempt to write out "recent common" to the user's recent common file.
584 If we got an error report it with a dialog box and return FALSE,
585 otherwise return TRUE. */
595 * - Split output lines longer than MAX_VAL_LEN
596 * - Create a function for the preference directory check/creation
597 * so that duplication can be avoided with filter.c
600 /* Create the directory that holds personal configuration files, if
602 if (create_persconffile_dir(&pf_dir_path) == -1) {
603 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
604 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
610 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
611 if ((rf = ws_fopen(rf_path, "w")) == NULL) {
612 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
613 "Can't open recent file\n\"%s\": %s.", rf_path,
620 fputs("# Recent settings file for Wireshark " VERSION ".\n"
622 "# This file is regenerated each time Wireshark is quit.\n"
623 "# So be careful, if you want to make manual changes here.\n"
625 "######## Recent capture files (latest last), cannot be altered through command line ########\n"
628 menu_recent_file_write_all(rf);
631 "######## Recent capture filters (latest last), cannot be altered through command line ########\n"
634 cfilter_recent_write_all(rf);
637 "######## Recent display filters (latest last), cannot be altered through command line ########\n"
640 dfilter_recent_combo_write_all(rf);
642 #ifdef HAVE_PCAP_REMOTE
644 "######## Recent remote hosts, cannot be altered through command line ########\n"
647 capture_remote_combo_recent_write_all(rf);
650 fprintf(rf, "\n# Main window geometry.\n");
651 fprintf(rf, "# Decimal numbers.\n");
652 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X ": %d\n", recent.gui_geometry_main_x);
653 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y ": %d\n", recent.gui_geometry_main_y);
654 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH ": %d\n",
655 recent.gui_geometry_main_width);
656 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT ": %d\n",
657 recent.gui_geometry_main_height);
659 write_recent_boolean(rf, "Main window maximized",
660 RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED,
661 recent.gui_geometry_main_maximized);
663 fprintf(rf, "\n# Statusbar left pane size.\n");
664 fprintf(rf, "# Decimal number.\n");
665 if (recent.gui_geometry_status_pane_left != 0) {
666 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT ": %d\n",
667 recent.gui_geometry_status_pane_left);
669 fprintf(rf, "\n# Statusbar middle pane size.\n");
670 fprintf(rf, "# Decimal number.\n");
671 if (recent.gui_geometry_status_pane_right != 0) {
672 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT ": %d\n",
673 recent.gui_geometry_status_pane_right);
676 fprintf(rf, "\n# Last used Configuration Profile.\n");
677 fprintf(rf, RECENT_LAST_USED_PROFILE ": %s\n", get_profile_name());
679 fprintf(rf, "\n# WLAN statistics upper pane size.\n");
680 fprintf(rf, "# Decimal number.\n");
681 fprintf(rf, RECENT_GUI_GEOMETRY_WLAN_STATS_PANE ": %d\n",
682 recent.gui_geometry_wlan_stats_pane);
684 write_recent_boolean(rf, "Warn if running with elevated permissions (e.g. as root)",
685 RECENT_KEY_PRIVS_WARN_IF_ELEVATED,
686 recent.privs_warn_if_elevated);
688 write_recent_boolean(rf, "Warn if npf.sys isn't loaded on Windows >= 6.0",
689 RECENT_KEY_PRIVS_WARN_IF_NO_NPF,
690 recent.privs_warn_if_no_npf);
692 window_geom_recent_write_all(rf);
694 fprintf(rf, "\n# Custom colors.\n");
695 fprintf(rf, "# List of custom colors selected in Qt color picker.\n");
696 string_list = join_string_list(recent.custom_colors);
697 fprintf(rf, RECENT_GUI_CUSTOM_COLORS ": %s\n", string_list);
702 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
703 an error indication, or maybe write to a new recent file and
704 rename that file on top of the old one only if there are not I/O
710 /* Attempt to Write out profile "recent" to the user's profile recent file.
711 If we got an error report it with a dialog box and return FALSE,
712 otherwise return TRUE. */
714 write_profile_recent(void)
722 * - Split output lines longer than MAX_VAL_LEN
723 * - Create a function for the preference directory check/creation
724 * so that duplication can be avoided with filter.c
727 /* Create the directory that holds personal configuration files, if
729 if (create_persconffile_dir(&pf_dir_path) == -1) {
730 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
731 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
737 rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
738 if ((rf = ws_fopen(rf_path, "w")) == NULL) {
739 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
740 "Can't open recent file\n\"%s\": %s.", rf_path,
747 fputs("# Recent settings file for Wireshark " VERSION ".\n"
749 "# This file is regenerated each time Wireshark is quit\n"
750 "# and when changing configuration profile.\n"
751 "# So be careful, if you want to make manual changes here.\n"
754 write_recent_boolean(rf, "Main Toolbar show (hide)",
755 RECENT_KEY_MAIN_TOOLBAR_SHOW,
756 recent.main_toolbar_show);
758 write_recent_boolean(rf, "Filter Toolbar show (hide)",
759 RECENT_KEY_FILTER_TOOLBAR_SHOW,
760 recent.filter_toolbar_show);
762 write_recent_boolean(rf, "Wireless Settings Toolbar show (hide)",
763 RECENT_KEY_WIRELESS_TOOLBAR_SHOW,
764 recent.wireless_toolbar_show);
767 write_recent_boolean(rf, "Show (hide) old AirPcap driver warning dialog box",
768 RECENT_KEY_DRIVER_CHECK_SHOW,
769 recent.airpcap_driver_check_show);
772 write_recent_boolean(rf, "Packet list show (hide)",
773 RECENT_KEY_PACKET_LIST_SHOW,
774 recent.packet_list_show);
776 write_recent_boolean(rf, "Tree view show (hide)",
777 RECENT_KEY_TREE_VIEW_SHOW,
778 recent.tree_view_show);
780 write_recent_boolean(rf, "Byte view show (hide)",
781 RECENT_KEY_BYTE_VIEW_SHOW,
782 recent.byte_view_show);
784 write_recent_boolean(rf, "Statusbar show (hide)",
785 RECENT_KEY_STATUSBAR_SHOW,
786 recent.statusbar_show);
788 write_recent_boolean(rf, "Packet list colorize (hide)",
789 RECENT_KEY_PACKET_LIST_COLORIZE,
790 recent.packet_list_colorize);
792 write_recent_enum(rf, "Timestamp display format",
793 RECENT_GUI_TIME_FORMAT, ts_type_values,
794 recent.gui_time_format);
796 write_recent_enum(rf, "Timestamp display precision",
797 RECENT_GUI_TIME_PRECISION, ts_precision_values,
798 recent.gui_time_precision);
800 write_recent_enum(rf, "Seconds display format",
801 RECENT_GUI_SECONDS_FORMAT, ts_seconds_values,
802 recent.gui_seconds_format);
804 fprintf(rf, "\n# Zoom level.\n");
805 fprintf(rf, "# A decimal number.\n");
806 fprintf(rf, RECENT_GUI_ZOOM_LEVEL ": %d\n",
807 recent.gui_zoom_level);
809 fprintf(rf, "\n# Bytes view.\n");
810 fprintf(rf, "# A decimal number.\n");
811 fprintf(rf, RECENT_GUI_BYTES_VIEW ": %d\n",
812 recent.gui_bytes_view);
814 fprintf(rf, "\n# Main window upper (or leftmost) pane size.\n");
815 fprintf(rf, "# Decimal number.\n");
816 if (recent.gui_geometry_main_upper_pane != 0) {
817 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
818 recent.gui_geometry_main_upper_pane);
820 fprintf(rf, "\n# Main window middle pane size.\n");
821 fprintf(rf, "# Decimal number.\n");
822 if (recent.gui_geometry_main_lower_pane != 0) {
823 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
824 recent.gui_geometry_main_lower_pane);
827 fprintf(rf, "\n# Packet list column pixel widths.\n");
828 fprintf(rf, "# Each pair of strings consists of a column format and its pixel width.\n");
829 packet_list_recent_write_all(rf);
831 fprintf(rf, "\n# Open conversation dialog tabs.\n");
832 fprintf(rf, "# List of conversation names, e.g. \"TCP\", \"IPv6\".\n");
833 string_list = join_string_list(recent.conversation_tabs);
834 fprintf(rf, RECENT_GUI_CONVERSATION_TABS ": %s\n", string_list);
837 fprintf(rf, "\n# Open endpoint dialog tabs.\n");
838 fprintf(rf, "# List of endpoint names, e.g. \"TCP\", \"IPv6\".\n");
839 string_list = join_string_list(recent.endpoint_tabs);
840 fprintf(rf, RECENT_GUI_ENDPOINT_TABS ": %s\n", string_list);
843 write_recent_boolean(rf, "For RLC stats, whether to use RLC PDUs found inside MAC frames",
844 RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES,
845 recent.gui_rlc_use_pdus_from_mac);
847 if (get_last_open_dir() != NULL) {
848 fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
851 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", u3_contract_device_path(get_last_open_dir()));
853 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", get_last_open_dir());
858 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
859 an error indication, or maybe write to a new recent file and
860 rename that file on top of the old one only if there are not I/O
865 /* set one user's recent common file key/value pair */
866 static prefs_set_pref_e
867 read_set_recent_common_pair_static(gchar *key, const gchar *value,
868 void *private_data _U_,
869 gboolean return_range_errors _U_)
874 if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
875 parse_recent_boolean(value, &recent.gui_geometry_main_maximized);
876 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
877 num = strtol(value, &p, 0);
878 if (p == value || *p != '\0')
879 return PREFS_SET_SYNTAX_ERR; /* number was bad */
880 recent.gui_geometry_main_x = (gint)num;
881 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) {
882 num = strtol(value, &p, 0);
883 if (p == value || *p != '\0')
884 return PREFS_SET_SYNTAX_ERR; /* number was bad */
885 recent.gui_geometry_main_y = (gint)num;
886 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) {
887 num = strtol(value, &p, 0);
888 if (p == value || *p != '\0')
889 return PREFS_SET_SYNTAX_ERR; /* number was bad */
891 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
892 recent.gui_geometry_main_width = (gint)num;
893 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {
894 num = strtol(value, &p, 0);
895 if (p == value || *p != '\0')
896 return PREFS_SET_SYNTAX_ERR; /* number was bad */
898 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
899 recent.gui_geometry_main_height = (gint)num;
900 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT) == 0) {
901 num = strtol(value, &p, 0);
902 if (p == value || *p != '\0')
903 return PREFS_SET_SYNTAX_ERR; /* number was bad */
905 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
906 recent.gui_geometry_status_pane_right = (gint)num;
907 recent.has_gui_geometry_status_pane = TRUE;
908 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT) == 0) {
909 num = strtol(value, &p, 0);
910 if (p == value || *p != '\0')
911 return PREFS_SET_SYNTAX_ERR; /* number was bad */
913 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
914 recent.gui_geometry_status_pane_left = (gint)num;
915 recent.has_gui_geometry_status_pane = TRUE;
916 } else if (strcmp(key, RECENT_LAST_USED_PROFILE) == 0) {
917 if ((strcmp(value, DEFAULT_PROFILE) != 0) && profile_exists (value, FALSE)) {
918 set_profile_name (value);
920 } else if (strcmp(key, RECENT_GUI_GEOMETRY_WLAN_STATS_PANE) == 0) {
921 num = strtol(value, &p, 0);
922 if (p == value || *p != '\0')
923 return PREFS_SET_SYNTAX_ERR; /* number was bad */
925 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
926 recent.gui_geometry_wlan_stats_pane = (gint)num;
927 } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) {
928 /* now have something like "gui.geom.main.x", split it into win and sub_key */
929 char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1];
930 char *sub_key = strchr(win, '.');
934 window_geom_recent_read_pair(win, sub_key, value);
936 } else if (strcmp(key, RECENT_KEY_PRIVS_WARN_IF_ELEVATED) == 0) {
937 parse_recent_boolean(value, &recent.privs_warn_if_elevated);
938 } else if (strcmp(key, RECENT_KEY_PRIVS_WARN_IF_NO_NPF) == 0) {
939 parse_recent_boolean(value, &recent.privs_warn_if_no_npf);
940 } else if (strcmp(key, RECENT_GUI_CUSTOM_COLORS) == 0) {
941 recent.custom_colors = prefs_get_string_list(value);
947 /* set one user's recent file key/value pair */
948 static prefs_set_pref_e
949 read_set_recent_pair_static(gchar *key, const gchar *value,
950 void *private_data _U_,
951 gboolean return_range_errors _U_)
955 GList *col_l, *col_l_elt;
956 col_width_data *cfmt;
957 const gchar *cust_format = col_format_to_string(COL_CUSTOM);
958 int cust_format_len = (int) strlen(cust_format);
960 if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
961 parse_recent_boolean(value, &recent.main_toolbar_show);
962 } else if (strcmp(key, RECENT_KEY_FILTER_TOOLBAR_SHOW) == 0) {
963 parse_recent_boolean(value, &recent.filter_toolbar_show);
964 /* check both the old and the new keyword */
965 } else if (strcmp(key, RECENT_KEY_WIRELESS_TOOLBAR_SHOW) == 0 || (strcmp(key, "gui.airpcap_toolbar_show") == 0)) {
966 parse_recent_boolean(value, &recent.wireless_toolbar_show);
967 } else if (strcmp(key, RECENT_KEY_DRIVER_CHECK_SHOW) == 0) {
968 parse_recent_boolean(value, &recent.airpcap_driver_check_show);
969 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_SHOW) == 0) {
970 parse_recent_boolean(value, &recent.packet_list_show);
971 } else if (strcmp(key, RECENT_KEY_TREE_VIEW_SHOW) == 0) {
972 parse_recent_boolean(value, &recent.tree_view_show);
973 } else if (strcmp(key, RECENT_KEY_BYTE_VIEW_SHOW) == 0) {
974 parse_recent_boolean(value, &recent.byte_view_show);
975 } else if (strcmp(key, RECENT_KEY_STATUSBAR_SHOW) == 0) {
976 parse_recent_boolean(value, &recent.statusbar_show);
977 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_COLORIZE) == 0) {
978 parse_recent_boolean(value, &recent.packet_list_colorize);
979 } else if (strcmp(key, RECENT_GUI_TIME_FORMAT) == 0) {
980 recent.gui_time_format =
981 (ts_type)str_to_val(value, ts_type_values, TS_RELATIVE);
982 } else if (strcmp(key, RECENT_GUI_TIME_PRECISION) == 0) {
983 recent.gui_time_precision =
984 (ts_precision)str_to_val(value, ts_precision_values, TS_PREC_AUTO);
985 } else if (strcmp(key, RECENT_GUI_SECONDS_FORMAT) == 0) {
986 recent.gui_seconds_format =
987 (ts_seconds_type)str_to_val(value, ts_seconds_values, TS_SECONDS_DEFAULT);
988 } else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL) == 0) {
989 num = strtol(value, &p, 0);
990 if (p == value || *p != '\0')
991 return PREFS_SET_SYNTAX_ERR; /* number was bad */
992 recent.gui_zoom_level = (gint)num;
993 } else if (strcmp(key, RECENT_GUI_BYTES_VIEW) == 0) {
994 num = strtol(value, &p, 0);
995 if (p == value || *p != '\0')
996 return PREFS_SET_SYNTAX_ERR; /* number was bad */
997 recent.gui_bytes_view = (bytes_view_type)num;
998 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
999 parse_recent_boolean(value, &recent.gui_geometry_main_maximized);
1000 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) {
1001 num = strtol(value, &p, 0);
1002 if (p == value || *p != '\0')
1003 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1005 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1006 recent.gui_geometry_main_upper_pane = (gint)num;
1007 recent.has_gui_geometry_main_upper_pane = TRUE;
1008 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) {
1009 num = strtol(value, &p, 0);
1010 if (p == value || *p != '\0')
1011 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1013 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1014 recent.gui_geometry_main_lower_pane = (gint)num;
1015 recent.has_gui_geometry_main_lower_pane = TRUE;
1016 } else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS) == 0) {
1017 recent.conversation_tabs = prefs_get_string_list(value);
1018 } else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS) == 0) {
1019 recent.endpoint_tabs = prefs_get_string_list(value);
1020 } else if (strcmp(key, RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES) == 0) {
1021 parse_recent_boolean(value, &recent.gui_rlc_use_pdus_from_mac);
1022 } else if (strcmp(key, RECENT_KEY_COL_WIDTH) == 0) {
1023 col_l = prefs_get_string_list(value);
1025 return PREFS_SET_SYNTAX_ERR;
1026 if ((g_list_length(col_l) % 2) != 0) {
1027 /* A title didn't have a matching width. */
1028 prefs_clear_string_list(col_l);
1029 return PREFS_SET_SYNTAX_ERR;
1031 /* Check to make sure all column formats are valid. */
1032 col_l_elt = g_list_first(col_l);
1034 /* Make sure the format isn't empty. */
1035 if (strcmp((const char *)col_l_elt->data, "") == 0) {
1037 prefs_clear_string_list(col_l);
1038 return PREFS_SET_SYNTAX_ERR;
1041 /* Check the format. */
1042 if (strncmp((const char *)col_l_elt->data, cust_format, cust_format_len) != 0) {
1043 if (get_column_format_from_str((const gchar *)col_l_elt->data) == -1) {
1044 /* It's not a valid column format. */
1045 prefs_clear_string_list(col_l);
1046 return PREFS_SET_SYNTAX_ERR;
1050 /* Go past the format. */
1051 col_l_elt = col_l_elt->next;
1053 /* Go past the width. */
1054 col_l_elt = col_l_elt->next;
1056 free_col_width_info(&recent);
1057 recent.col_width_list = NULL;
1058 col_l_elt = g_list_first(col_l);
1060 gchar *fmt = g_strdup((const gchar *)col_l_elt->data);
1061 cfmt = (col_width_data *) g_malloc(sizeof(col_width_data));
1062 if (strncmp(fmt, cust_format, cust_format_len) != 0) {
1063 cfmt->cfmt = get_column_format_from_str(fmt);
1064 cfmt->cfield = NULL;
1066 cfmt->cfmt = COL_CUSTOM;
1067 cfmt->cfield = g_strdup(&fmt[cust_format_len+1]); /* add 1 for ':' */
1070 if (cfmt->cfmt == -1) {
1071 g_free(cfmt->cfield);
1073 return PREFS_SET_SYNTAX_ERR; /* string was bad */
1076 col_l_elt = col_l_elt->next;
1077 cfmt->width = (gint)strtol((const char *)col_l_elt->data, &p, 0);
1078 if (p == col_l_elt->data || (*p != '\0' && *p != ':')) {
1079 g_free(cfmt->cfield);
1081 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1085 cfmt->xalign = *(++p);
1087 cfmt->xalign = COLUMN_XALIGN_DEFAULT;
1090 col_l_elt = col_l_elt->next;
1091 recent.col_width_list = g_list_append(recent.col_width_list, cfmt);
1093 prefs_clear_string_list(col_l);
1094 } else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
1095 if (recent.gui_fileopen_remembered_dir) {
1096 g_free (recent.gui_fileopen_remembered_dir);
1098 recent.gui_fileopen_remembered_dir = g_strdup(value);
1101 return PREFS_SET_OK;
1105 /* set one user's recent file key/value pair */
1106 static prefs_set_pref_e
1107 read_set_recent_pair_dynamic(gchar *key, const gchar *value,
1108 void *private_data _U_,
1109 gboolean return_range_errors _U_)
1111 if (!g_utf8_validate(value, -1, NULL)) {
1112 return PREFS_SET_SYNTAX_ERR;
1114 if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
1116 add_menu_recent_capture_file(u3_expand_device_path(value));
1118 add_menu_recent_capture_file(value);
1119 } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
1120 dfilter_combo_add_recent(value);
1121 } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER) == 0) {
1122 recent_add_cfilter(NULL, value);
1123 } else if (g_str_has_prefix(key, RECENT_KEY_CAPTURE_FILTER ".")) {
1124 /* strrchr() can't fail - string has a prefix that ends with a "." */
1125 recent_add_cfilter(strrchr(key, '.') + 1, value);
1126 #ifdef HAVE_PCAP_REMOTE
1127 } else if (strcmp(key, RECENT_KEY_REMOTE_HOST) == 0) {
1128 capture_remote_combo_add_recent(value);
1132 return PREFS_SET_OK;
1137 * Given a string of the form "<recent name>:<recent value>", as might appear
1138 * as an argument to a "-o" option, parse it and set the recent value in
1139 * question. Return an indication of whether it succeeded or failed
1143 recent_set_arg(char *prefarg)
1148 colonp = strchr(prefarg, ':');
1150 return PREFS_SET_SYNTAX_ERR;
1156 * Skip over any white space (there probably won't be any, but
1157 * as we allow it in the preferences file, we might as well
1160 while (g_ascii_isspace(*p))
1164 * Put the colon back, so if our caller uses, in an
1165 * error message, the string they passed us, the message
1169 return PREFS_SET_SYNTAX_ERR;
1172 ret = read_set_recent_pair_static(prefarg, p, NULL, TRUE);
1173 *colonp = ':'; /* put the colon back */
1178 /* opens the user's recent common file and read the first part */
1180 recent_read_static(char **rf_path_return, int *rf_errno_return)
1186 recent.gui_geometry_main_x = 20;
1187 recent.gui_geometry_main_y = 20;
1188 recent.gui_geometry_main_width = DEF_WIDTH;
1189 recent.gui_geometry_main_height = DEF_HEIGHT;
1190 recent.gui_geometry_main_maximized= FALSE;
1192 recent.gui_geometry_status_pane_left = (DEF_WIDTH/3);
1193 recent.gui_geometry_status_pane_right = (DEF_WIDTH/3);
1194 recent.gui_geometry_wlan_stats_pane = 200;
1196 recent.privs_warn_if_elevated = TRUE;
1197 recent.privs_warn_if_no_npf = TRUE;
1199 recent.col_width_list = NULL;
1200 recent.gui_fileopen_remembered_dir = NULL;
1202 /* Construct the pathname of the user's recent common file. */
1203 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1205 /* Read the user's recent common file, if it exists. */
1206 *rf_path_return = NULL;
1207 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1208 /* We succeeded in opening it; read it. */
1209 read_prefs_file(rf_path, rf, read_set_recent_common_pair_static, NULL);
1213 /* We failed to open it. If we failed for some reason other than
1214 "it doesn't exist", return the errno and the pathname, so our
1215 caller can report the error. */
1216 if (errno != ENOENT) {
1217 *rf_errno_return = errno;
1218 *rf_path_return = rf_path;
1228 /* opens the user's recent file and read the first part */
1230 recent_read_profile_static(char **rf_path_return, int *rf_errno_return)
1232 char *rf_path, *rf_common_path;
1236 recent.main_toolbar_show = TRUE;
1237 recent.filter_toolbar_show = TRUE;
1238 recent.wireless_toolbar_show = FALSE;
1239 recent.airpcap_driver_check_show = TRUE;
1240 recent.packet_list_show = TRUE;
1241 recent.tree_view_show = TRUE;
1242 recent.byte_view_show = TRUE;
1243 recent.statusbar_show = TRUE;
1244 recent.packet_list_colorize = TRUE;
1245 recent.gui_time_format = TS_RELATIVE;
1246 recent.gui_time_precision = TS_PREC_AUTO;
1247 recent.gui_seconds_format = TS_SECONDS_DEFAULT;
1248 recent.gui_zoom_level = 0;
1249 recent.gui_bytes_view = BYTES_HEX;
1251 /* pane size of zero will autodetect */
1252 recent.gui_geometry_main_upper_pane = 0;
1253 recent.gui_geometry_main_lower_pane = 0;
1255 recent.has_gui_geometry_main_upper_pane = TRUE;
1256 recent.has_gui_geometry_main_lower_pane = TRUE;
1257 recent.has_gui_geometry_status_pane = TRUE;
1259 if (recent.col_width_list) {
1260 free_col_width_info(&recent);
1263 if (recent.gui_fileopen_remembered_dir) {
1264 g_free (recent.gui_fileopen_remembered_dir);
1265 recent.gui_fileopen_remembered_dir = NULL;
1268 /* Construct the pathname of the user's profile recent file. */
1269 rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
1271 /* Read the user's recent file, if it exists. */
1272 *rf_path_return = NULL;
1273 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1274 /* We succeeded in opening it; read it. */
1275 read_prefs_file(rf_path, rf, read_set_recent_pair_static, NULL);
1278 /* XXX: The following code doesn't actually do anything since
1279 * the "recent common file" always exists. Presumably the
1280 * "if (!file_exists())" should actually be "if (file_exists())".
1281 * However, I've left the code as is because this
1282 * behaviour has existed for quite some time and I don't
1283 * know what's supposed to happen at this point.
1284 * ToDo: Determine if the "recent common file" should be read at this point
1286 rf_common_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1287 if (!file_exists(rf_common_path)) {
1288 /* Read older common settings from recent file */
1289 rf = ws_fopen(rf_path, "r");
1290 read_prefs_file(rf_path, rf, read_set_recent_common_pair_static, NULL);
1293 g_free(rf_common_path);
1295 /* We failed to open it. If we failed for some reason other than
1296 "it doesn't exist", return the errno and the pathname, so our
1297 caller can report the error. */
1298 if (errno != ENOENT) {
1299 *rf_errno_return = errno;
1300 *rf_path_return = rf_path;
1308 /* opens the user's recent file and read it out */
1310 recent_read_dynamic(char **rf_path_return, int *rf_errno_return)
1316 /* Construct the pathname of the user's recent common file. */
1317 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1318 if (!file_exists (rf_path)) {
1319 /* Recent common file does not exist, read from default recent */
1321 rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
1324 /* Read the user's recent file, if it exists. */
1325 *rf_path_return = NULL;
1326 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1327 /* We succeeded in opening it; read it. */
1328 read_prefs_file(rf_path, rf, read_set_recent_pair_dynamic, NULL);
1330 /* set dfilter combobox to have an empty line */
1331 dfilter_combo_add_empty();
1335 /* We failed to open it. If we failed for some reason other than
1336 "it doesn't exist", return the errno and the pathname, so our
1337 caller can report the error. */
1338 if (errno != ENOENT) {
1339 *rf_errno_return = errno;
1340 *rf_path_return = rf_path;
1349 recent_get_column_width(gint col)
1352 col_width_data *col_w;
1354 const gchar *cfield = NULL;
1356 cfmt = get_column_format(col);
1357 if (cfmt == COL_CUSTOM) {
1358 cfield = get_column_custom_fields(col);
1361 col_l = g_list_first(recent.col_width_list);
1363 col_w = (col_width_data *) col_l->data;
1364 if (col_w->cfmt == cfmt) {
1365 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1366 return col_w->width;
1369 col_l = col_l->next;
1376 recent_set_column_width(gint col, gint width)
1379 col_width_data *col_w;
1381 const gchar *cfield = NULL;
1382 gboolean found = FALSE;
1384 cfmt = get_column_format(col);
1385 if (cfmt == COL_CUSTOM) {
1386 cfield = get_column_custom_fields(col);
1389 col_l = g_list_first(recent.col_width_list);
1391 col_w = (col_width_data *) col_l->data;
1392 if (col_w->cfmt == cfmt) {
1393 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1394 col_w->width = width;
1399 col_l = col_l->next;
1403 col_w = (col_width_data *) g_malloc(sizeof(col_width_data));
1406 col_w->cfield = g_strdup(cfield);
1408 col_w->cfield = NULL;
1410 col_w->width = width;
1411 col_w->xalign = COLUMN_XALIGN_DEFAULT;
1412 recent.col_width_list = g_list_append(recent.col_width_list, col_w);
1417 recent_get_column_xalign(gint col)
1420 col_width_data *col_w;
1422 const gchar *cfield = NULL;
1424 cfmt = get_column_format(col);
1425 if (cfmt == COL_CUSTOM) {
1426 cfield = get_column_custom_fields(col);
1429 col_l = g_list_first(recent.col_width_list);
1431 col_w = (col_width_data *) col_l->data;
1432 if (col_w->cfmt == cfmt) {
1433 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1434 return col_w->xalign;
1437 col_l = col_l->next;
1444 recent_set_column_xalign(gint col, gchar xalign)
1447 col_width_data *col_w;
1449 const gchar *cfield = NULL;
1450 gboolean found = FALSE;
1452 cfmt = get_column_format(col);
1453 if (cfmt == COL_CUSTOM) {
1454 cfield = get_column_custom_fields(col);
1457 col_l = g_list_first(recent.col_width_list);
1459 col_w = (col_width_data *) col_l->data;
1460 if (col_w->cfmt == cfmt) {
1461 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1462 col_w->xalign = xalign;
1467 col_l = col_l->next;
1471 col_w = (col_width_data *) g_malloc(sizeof(col_width_data));
1474 col_w->cfield = g_strdup(cfield);
1476 col_w->cfield = NULL;
1479 col_w->xalign = xalign;
1480 recent.col_width_list = g_list_append(recent.col_width_list, col_w);
1485 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1490 * indent-tabs-mode: nil
1493 * ex: set shiftwidth=2 tabstop=8 expandtab:
1494 * :indentSize=2:tabSize=8:noTabs=true: