MSWSP: add parse_CNatLanguageRestriction()
[wireshark-wip.git] / ui / recent.c
blob41f5f9326331b16802685d459e609b5d6fb05602
1 /* recent.c
2 * Recent "preference" handling routines
3 * Copyright 2004, Ulf Lamping <ulf.lamping@web.de>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <errno.h>
33 #include <epan/epan.h>
34 #include <epan/filesystem.h>
35 #include <epan/emem.h>
36 #include <epan/prefs.h>
37 #include <epan/prefs-int.h>
38 #include <epan/column.h>
39 #include <epan/timestamp.h>
41 #include "ui/last_open_dir.h"
42 #include "ui/recent.h"
43 #include "ui/recent_utils.h"
44 #include "ui/simple_dialog.h"
45 #include "ui/ui_util.h"
47 #include <wsutil/u3.h>
48 #include <wsutil/file_util.h>
49 #include <wsutil/str_util.h>
51 #define RECENT_KEY_MAIN_TOOLBAR_SHOW "gui.toolbar_main_show"
52 #define RECENT_KEY_FILTER_TOOLBAR_SHOW "gui.filter_toolbar_show"
53 #define RECENT_KEY_WIRELESS_TOOLBAR_SHOW "gui.wireless_toolbar_show"
54 #define RECENT_KEY_DRIVER_CHECK_SHOW "gui.airpcap_driver_check_show"
55 #define RECENT_KEY_PACKET_LIST_SHOW "gui.packet_list_show"
56 #define RECENT_KEY_TREE_VIEW_SHOW "gui.tree_view_show"
57 #define RECENT_KEY_BYTE_VIEW_SHOW "gui.byte_view_show"
58 #define RECENT_KEY_STATUSBAR_SHOW "gui.statusbar_show"
59 #define RECENT_KEY_PACKET_LIST_COLORIZE "gui.packet_list_colorize"
60 #define RECENT_GUI_TIME_FORMAT "gui.time_format"
61 #define RECENT_GUI_TIME_PRECISION "gui.time_precision"
62 #define RECENT_GUI_SECONDS_FORMAT "gui.seconds_format"
63 #define RECENT_GUI_ZOOM_LEVEL "gui.zoom_level"
64 #define RECENT_GUI_BYTES_VIEW "gui.bytes_view"
65 #define RECENT_GUI_GEOMETRY_MAIN_X "gui.geometry_main_x"
66 #define RECENT_GUI_GEOMETRY_MAIN_Y "gui.geometry_main_y"
67 #define RECENT_GUI_GEOMETRY_MAIN_WIDTH "gui.geometry_main_width"
68 #define RECENT_GUI_GEOMETRY_MAIN_HEIGHT "gui.geometry_main_height"
69 #define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized"
70 #define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane"
71 #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane"
72 #define RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT "gui.geometry_status_pane"
73 #define RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT "gui.geometry_status_pane_right"
74 #define RECENT_GUI_GEOMETRY_WLAN_STATS_PANE "gui.geometry_status_wlan_stats_pane"
75 #define RECENT_LAST_USED_PROFILE "gui.last_used_profile"
76 #define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir"
77 #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 char *ts_type_text[] =
87 { "RELATIVE", "ABSOLUTE", "ABSOLUTE_WITH_DATE", "DELTA", "DELTA_DIS", "EPOCH", "UTC", "UTC_WITH_DATE", NULL };
89 static const char *ts_precision_text[] =
90 { "AUTO", "SEC", "DSEC", "CSEC", "MSEC", "USEC", "NSEC", NULL };
92 static const char *ts_seconds_text[] =
93 { "SECONDS", "HOUR_MIN_SEC", NULL };
95 /* Takes an string and a pointer to an array of strings, and a default int value.
96 * The array must be terminated by a NULL string. If the string is found in the array
97 * of strings, the index of that string in the array is returned. Otherwise, the
98 * default value that was passed as the third argument is returned.
100 static int
101 find_index_from_string_array(const char *needle, const char **haystack, int default_value)
103 int i = 0;
105 while (haystack[i] != NULL) {
106 if (strcmp(needle, haystack[i]) == 0) {
107 return i;
109 i++;
111 return default_value;
114 static void
115 free_col_width_info(recent_settings_t *rs)
117 col_width_data *cfmt;
119 while (rs->col_width_list != NULL) {
120 cfmt = (col_width_data *)rs->col_width_list->data;
121 g_free(cfmt->cfield);
122 g_free(cfmt);
123 rs->col_width_list = g_list_remove_link(rs->col_width_list, rs->col_width_list);
125 g_list_free(rs->col_width_list);
126 rs->col_width_list = NULL;
129 /** Write the geometry values of a single window to the recent file.
131 * @param key unused
132 * @param value the geometry values
133 * @param rfh recent file handle (FILE)
135 static void
136 write_recent_geom(gpointer key _U_, gpointer value, gpointer rfh)
138 window_geometry_t *geom = (window_geometry_t *)value;
139 FILE *rf = (FILE *)rfh;
141 fprintf(rf, "\n# Geometry and maximized state of %s window.\n", geom->key);
142 fprintf(rf, "# Decimal integers.\n");
143 fprintf(rf, RECENT_GUI_GEOMETRY "%s.x: %d\n", geom->key, geom->x);
144 fprintf(rf, RECENT_GUI_GEOMETRY "%s.y: %d\n", geom->key, geom->y);
145 fprintf(rf, RECENT_GUI_GEOMETRY "%s.width: %d\n", geom->key,
146 geom->width);
147 fprintf(rf, RECENT_GUI_GEOMETRY "%s.height: %d\n", geom->key,
148 geom->height);
150 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
151 fprintf(rf, RECENT_GUI_GEOMETRY "%s.maximized: %s\n", geom->key,
152 geom->maximized == TRUE ? "TRUE" : "FALSE");
156 /* the geometry hashtable for all known window classes,
157 * the window name is the key, and the geometry struct is the value */
158 static GHashTable *window_geom_hash = NULL;
160 /* save the window and its current geometry into the geometry hashtable */
161 void
162 window_geom_save(const gchar *name, window_geometry_t *geom)
164 gchar *key;
165 window_geometry_t *work;
167 /* init hashtable, if not already done */
168 if(!window_geom_hash) {
169 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
171 /* if we have an old one, remove and free it first */
172 work = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name);
173 if(work) {
174 g_hash_table_remove(window_geom_hash, name);
175 g_free(work->key);
176 g_free(work);
179 /* g_malloc and insert the new one */
180 work = (window_geometry_t *)g_malloc(sizeof(window_geometry_t));
181 *work = *geom;
182 key = g_strdup(name);
183 work->key = key;
184 g_hash_table_insert(window_geom_hash, key, work);
187 /* load the desired geometry for this window from the geometry hashtable */
188 gboolean
189 window_geom_load(const gchar *name,
190 window_geometry_t *geom)
192 window_geometry_t *p;
194 /* init hashtable, if not already done */
195 if(!window_geom_hash) {
196 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
199 p = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name);
200 if(p) {
201 *geom = *p;
202 return TRUE;
203 } else {
204 return FALSE;
208 /** Read in a single geometry key value pair from the recent file.
210 * @param name the geom_name of the window
211 * @param key the subkey of this pair (e.g. "x")
212 * @param value the new value (e.g. "123")
214 static void
215 window_geom_recent_read_pair(const char *name,
216 const char *key,
217 const char *value)
219 window_geometry_t geom;
221 /* find window geometry maybe already in hashtable */
222 if(!window_geom_load(name, &geom)) {
223 /* not in table, init geom with "basic" values */
224 geom.key = NULL; /* Will be set in window_geom_save() */
225 geom.set_pos = FALSE;
226 geom.x = -1;
227 geom.y = -1;
228 geom.set_size = FALSE;
229 geom.width = -1;
230 geom.height = -1;
232 geom.set_maximized = FALSE;/* this is valid in GTK2 only */
233 geom.maximized = FALSE; /* this is valid in GTK2 only */
236 if (strcmp(key, "x") == 0) {
237 geom.x = (gint)strtol(value, NULL, 10);
238 geom.set_pos = TRUE;
239 } else if (strcmp(key, "y") == 0) {
240 geom.y = (gint)strtol(value, NULL, 10);
241 geom.set_pos = TRUE;
242 } else if (strcmp(key, "width") == 0) {
243 geom.width = (gint)strtol(value, NULL, 10);
244 geom.set_size = TRUE;
245 } else if (strcmp(key, "height") == 0) {
246 geom.height = (gint)strtol(value, NULL, 10);
247 geom.set_size = TRUE;
248 } else if (strcmp(key, "maximized") == 0) {
249 if (g_ascii_strcasecmp(value, "true") == 0) {
250 geom.maximized = TRUE;
252 else {
253 geom.maximized = FALSE;
255 geom.set_maximized = TRUE;
256 } else {
258 * Silently ignore the bogus key. We shouldn't abort here,
259 * as this could be due to a corrupt recent file.
261 * XXX - should we print a message about this?
263 return;
266 /* save / replace geometry in hashtable */
267 window_geom_save(name, &geom);
270 /** Write all geometry values of all windows to the recent file.
271 * Will call write_recent_geom() for every existing window type.
273 * @param rf recent file handle from caller
275 static void
276 window_geom_recent_write_all(FILE *rf)
278 /* init hashtable, if not already done */
279 if(!window_geom_hash) {
280 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
283 g_hash_table_foreach(window_geom_hash, write_recent_geom, rf);
286 /* Global list of recent capture filters. */
287 static GList *recent_cfilter_list;
290 * Per-interface lists of recent capture filters; stored in a hash
291 * table indexed by interface name.
293 static GHashTable *per_interface_cfilter_lists_hash;
295 /* XXX: use a preference for this setting! */
296 static guint cfilter_combo_max_recent = 20;
299 * Returns a list of recent capture filters.
301 * @param ifname interface name; NULL refers to the global list.
303 GList *
304 recent_get_cfilter_list(const gchar *ifname)
306 if (ifname == NULL)
307 return recent_cfilter_list;
308 if (per_interface_cfilter_lists_hash == NULL) {
309 /* No such lists exist. */
310 return NULL;
312 return (GList *)g_hash_table_lookup(per_interface_cfilter_lists_hash, ifname);
316 * Add a capture filter to the global recent capture filter list or
317 * the recent capture filter list for an interface.
319 * @param ifname interface name; NULL refers to the global list.
320 * @param s text of capture filter
322 void
323 recent_add_cfilter(const gchar *ifname, const gchar *s)
325 GList *cfilter_list;
326 GList *li;
327 gchar *li_filter, *newfilter = NULL;
329 /* Don't add empty filters to the list. */
330 if (s[0] == '\0')
331 return;
333 if (ifname == NULL)
334 cfilter_list = recent_cfilter_list;
335 else {
336 /* If we don't yet have a hash table for per-interface recent
337 capture filter lists, create one. Have it free the new key
338 if we're updating an entry rather than creating it below. */
339 if (per_interface_cfilter_lists_hash == NULL)
340 per_interface_cfilter_lists_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
341 cfilter_list = (GList *)g_hash_table_lookup(per_interface_cfilter_lists_hash, ifname);
344 li = g_list_first(cfilter_list);
345 while (li) {
346 /* If the filter is already in the list, remove the old one and
347 * append the new one at the latest position (at g_list_append() below) */
348 li_filter = (char *)li->data;
349 if (strcmp(s, li_filter) == 0) {
350 /* No need to copy the string, we're just moving it. */
351 newfilter = li_filter;
352 cfilter_list = g_list_remove(cfilter_list, li->data);
353 break;
355 li = li->next;
357 if (newfilter == NULL) {
358 /* The filter wasn't already in the list; make a copy to add. */
359 newfilter = g_strdup(s);
361 cfilter_list = g_list_append(cfilter_list, newfilter);
363 if (ifname == NULL)
364 recent_cfilter_list = cfilter_list;
365 else
366 g_hash_table_insert(per_interface_cfilter_lists_hash, g_strdup(ifname), cfilter_list);
369 static void
370 cfilter_recent_write_all_list(FILE *rf, const gchar *ifname, GList *cfilter_list)
372 guint max_count = 0;
373 GList *li;
375 /* write all non empty capture filter strings to the recent file (until max count) */
376 li = g_list_first(cfilter_list);
377 while (li && (max_count++ <= cfilter_combo_max_recent) ) {
378 if (li->data && strlen((const char *)li->data)) {
379 if (ifname == NULL)
380 fprintf (rf, RECENT_KEY_CAPTURE_FILTER ": %s\n", (char *)li->data);
381 else
382 fprintf (rf, RECENT_KEY_CAPTURE_FILTER ".%s: %s\n", ifname, (char *)li->data);
384 li = li->next;
388 static void
389 cfilter_recent_write_all_hash_callback(gpointer key, gpointer value, gpointer user_data)
391 cfilter_recent_write_all_list((FILE *)user_data, (const gchar *)key, (GList *)value);
394 /** Write all capture filter values to the recent file.
396 * @param rf recent file handle from caller
398 static void
399 cfilter_recent_write_all(FILE *rf)
401 /* Write out the global list. */
402 cfilter_recent_write_all_list(rf, NULL, recent_cfilter_list);
404 /* Write out all the per-interface lists. */
405 if (per_interface_cfilter_lists_hash != NULL) {
406 g_hash_table_foreach(per_interface_cfilter_lists_hash, cfilter_recent_write_all_hash_callback, (gpointer)rf);
410 /* Attempt to Write out "recent common" to the user's recent common file.
411 If we got an error report it with a dialog box and return FALSE,
412 otherwise return TRUE. */
413 gboolean
414 write_recent(void)
416 char *pf_dir_path;
417 char *rf_path;
418 FILE *rf;
420 /* To do:
421 * - Split output lines longer than MAX_VAL_LEN
422 * - Create a function for the preference directory check/creation
423 * so that duplication can be avoided with filter.c
426 /* Create the directory that holds personal configuration files, if
427 necessary. */
428 if (create_persconffile_dir(&pf_dir_path) == -1) {
429 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
430 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
431 g_strerror(errno));
432 g_free(pf_dir_path);
433 return FALSE;
436 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
437 if ((rf = ws_fopen(rf_path, "w")) == NULL) {
438 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
439 "Can't open recent file\n\"%s\": %s.", rf_path,
440 g_strerror(errno));
441 g_free(rf_path);
442 return FALSE;
444 g_free(rf_path);
446 fputs("# Recent settings file for Wireshark " VERSION ".\n"
447 "#\n"
448 "# This file is regenerated each time Wireshark is quit.\n"
449 "# So be careful, if you want to make manual changes here.\n"
450 "\n"
451 "######## Recent capture files (latest last), cannot be altered through command line ########\n"
452 "\n", rf);
454 menu_recent_file_write_all(rf);
456 fputs("\n"
457 "######## Recent capture filters (latest last), cannot be altered through command line ########\n"
458 "\n", rf);
460 cfilter_recent_write_all(rf);
462 fputs("\n"
463 "######## Recent display filters (latest last), cannot be altered through command line ########\n"
464 "\n", rf);
466 dfilter_recent_combo_write_all(rf);
468 #ifdef HAVE_PCAP_REMOTE
469 fputs("\n"
470 "######## Recent remote hosts, cannot be altered through command line ########\n"
471 "\n", rf);
473 capture_remote_combo_recent_write_all(rf);
474 #endif
476 fprintf(rf, "\n# Main window geometry.\n");
477 fprintf(rf, "# Decimal numbers.\n");
478 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X ": %d\n", recent.gui_geometry_main_x);
479 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y ": %d\n", recent.gui_geometry_main_y);
480 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH ": %d\n",
481 recent.gui_geometry_main_width);
482 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT ": %d\n",
483 recent.gui_geometry_main_height);
485 fprintf(rf, "\n# Main window maximized.\n");
486 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
487 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED ": %s\n",
488 recent.gui_geometry_main_maximized == TRUE ? "TRUE" : "FALSE");
490 fprintf(rf, "\n# Statusbar left pane size.\n");
491 fprintf(rf, "# Decimal number.\n");
492 if (recent.gui_geometry_status_pane_left != 0) {
493 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT ": %d\n",
494 recent.gui_geometry_status_pane_left);
496 fprintf(rf, "\n# Statusbar middle pane size.\n");
497 fprintf(rf, "# Decimal number.\n");
498 if (recent.gui_geometry_status_pane_right != 0) {
499 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT ": %d\n",
500 recent.gui_geometry_status_pane_right);
503 fprintf(rf, "\n# Last used Configuration Profile.\n");
504 fprintf(rf, RECENT_LAST_USED_PROFILE ": %s\n", get_profile_name());
506 fprintf(rf, "\n# WLAN statistics upper pane size.\n");
507 fprintf(rf, "# Decimal number.\n");
508 fprintf(rf, RECENT_GUI_GEOMETRY_WLAN_STATS_PANE ": %d\n",
509 recent.gui_geometry_wlan_stats_pane);
511 fprintf(rf, "\n# Warn if running with elevated permissions (e.g. as root).\n");
512 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
513 fprintf(rf, RECENT_KEY_PRIVS_WARN_IF_ELEVATED ": %s\n",
514 recent.privs_warn_if_elevated == TRUE ? "TRUE" : "FALSE");
516 fprintf(rf, "\n# Warn if npf.sys isn't loaded on Windows >= 6.0.\n");
517 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
518 fprintf(rf, RECENT_KEY_PRIVS_WARN_IF_NO_NPF ": %s\n",
519 recent.privs_warn_if_no_npf == TRUE ? "TRUE" : "FALSE");
521 window_geom_recent_write_all(rf);
523 fclose(rf);
525 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
526 an error indication, or maybe write to a new recent file and
527 rename that file on top of the old one only if there are not I/O
528 errors. */
529 return TRUE;
533 /* Attempt to Write out profile "recent" to the user's profile recent file.
534 If we got an error report it with a dialog box and return FALSE,
535 otherwise return TRUE. */
536 gboolean
537 write_profile_recent(void)
539 char *pf_dir_path;
540 char *rf_path;
541 FILE *rf;
543 /* To do:
544 * - Split output lines longer than MAX_VAL_LEN
545 * - Create a function for the preference directory check/creation
546 * so that duplication can be avoided with filter.c
549 /* Create the directory that holds personal configuration files, if
550 necessary. */
551 if (create_persconffile_dir(&pf_dir_path) == -1) {
552 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
553 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
554 g_strerror(errno));
555 g_free(pf_dir_path);
556 return FALSE;
559 rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
560 if ((rf = ws_fopen(rf_path, "w")) == NULL) {
561 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
562 "Can't open recent file\n\"%s\": %s.", rf_path,
563 g_strerror(errno));
564 g_free(rf_path);
565 return FALSE;
567 g_free(rf_path);
569 fputs("# Recent settings file for Wireshark " VERSION ".\n"
570 "#\n"
571 "# This file is regenerated each time Wireshark is quit\n"
572 "# and when changing configuration profile.\n"
573 "# So be careful, if you want to make manual changes here.\n"
574 "\n", rf);
576 fprintf(rf, "\n# Main Toolbar show (hide).\n");
577 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
578 fprintf(rf, RECENT_KEY_MAIN_TOOLBAR_SHOW ": %s\n",
579 recent.main_toolbar_show == TRUE ? "TRUE" : "FALSE");
581 fprintf(rf, "\n# Filter Toolbar show (hide).\n");
582 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
583 fprintf(rf, RECENT_KEY_FILTER_TOOLBAR_SHOW ": %s\n",
584 recent.filter_toolbar_show == TRUE ? "TRUE" : "FALSE");
586 fprintf(rf, "\n# Wireless Settings Toolbar show (hide).\n");
587 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
588 fprintf(rf, RECENT_KEY_WIRELESS_TOOLBAR_SHOW ": %s\n",
589 recent.wireless_toolbar_show == TRUE ? "TRUE" : "FALSE");
591 #ifdef HAVE_AIRPCAP
592 fprintf(rf, "\n# Show (hide) old AirPcap driver warning dialog box.\n");
593 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
594 fprintf(rf, RECENT_KEY_DRIVER_CHECK_SHOW ": %s\n",
595 recent.airpcap_driver_check_show == TRUE ? "TRUE" : "FALSE");
596 #endif
598 fprintf(rf, "\n# Packet list show (hide).\n");
599 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
600 fprintf(rf, RECENT_KEY_PACKET_LIST_SHOW ": %s\n",
601 recent.packet_list_show == TRUE ? "TRUE" : "FALSE");
603 fprintf(rf, "\n# Tree view show (hide).\n");
604 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
605 fprintf(rf, RECENT_KEY_TREE_VIEW_SHOW ": %s\n",
606 recent.tree_view_show == TRUE ? "TRUE" : "FALSE");
608 fprintf(rf, "\n# Byte view show (hide).\n");
609 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
610 fprintf(rf, RECENT_KEY_BYTE_VIEW_SHOW ": %s\n",
611 recent.byte_view_show == TRUE ? "TRUE" : "FALSE");
613 fprintf(rf, "\n# Statusbar show (hide).\n");
614 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
615 fprintf(rf, RECENT_KEY_STATUSBAR_SHOW ": %s\n",
616 recent.statusbar_show == TRUE ? "TRUE" : "FALSE");
618 fprintf(rf, "\n# Packet list colorize (hide).\n");
619 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
620 fprintf(rf, RECENT_KEY_PACKET_LIST_COLORIZE ": %s\n",
621 recent.packet_list_colorize == TRUE ? "TRUE" : "FALSE");
623 fprintf(rf, "\n# Timestamp display format.\n");
624 fprintf(rf, "# One of: RELATIVE, ABSOLUTE, ABSOLUTE_WITH_DATE, DELTA, DELTA_DIS, EPOCH, UTC, UTC_WITH_DATE\n");
625 fprintf(rf, RECENT_GUI_TIME_FORMAT ": %s\n",
626 ts_type_text[recent.gui_time_format]);
628 fprintf(rf, "\n# Timestamp display precision.\n");
629 fprintf(rf, "# One of: AUTO, SEC, DSEC, CSEC, MSEC, USEC, NSEC\n");
630 fprintf(rf, RECENT_GUI_TIME_PRECISION ": %s\n",
631 ts_precision_text[recent.gui_time_precision]);
633 fprintf(rf, "\n# Seconds display format.\n");
634 fprintf(rf, "# One of: SECONDS, HOUR_MIN_SEC\n");
635 fprintf(rf, RECENT_GUI_SECONDS_FORMAT ": %s\n",
636 ts_seconds_text[recent.gui_seconds_format]);
638 fprintf(rf, "\n# Zoom level.\n");
639 fprintf(rf, "# A decimal number.\n");
640 fprintf(rf, RECENT_GUI_ZOOM_LEVEL ": %d\n",
641 recent.gui_zoom_level);
643 fprintf(rf, "\n# Bytes view.\n");
644 fprintf(rf, "# A decimal number.\n");
645 fprintf(rf, RECENT_GUI_BYTES_VIEW ": %d\n",
646 recent.gui_bytes_view);
648 fprintf(rf, "\n# Main window upper (or leftmost) pane size.\n");
649 fprintf(rf, "# Decimal number.\n");
650 if (recent.gui_geometry_main_upper_pane != 0) {
651 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
652 recent.gui_geometry_main_upper_pane);
654 fprintf(rf, "\n# Main window middle pane size.\n");
655 fprintf(rf, "# Decimal number.\n");
656 if (recent.gui_geometry_main_lower_pane != 0) {
657 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
658 recent.gui_geometry_main_lower_pane);
661 fprintf(rf, "\n# Packet list column pixel widths.\n");
662 fprintf(rf, "# Each pair of strings consists of a column format and its pixel width.\n");
663 packet_list_recent_write_all(rf);
665 if (get_last_open_dir() != NULL) {
666 fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
668 if(u3_active())
669 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", u3_contract_device_path(get_last_open_dir()));
670 else
671 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", get_last_open_dir());
674 fclose(rf);
676 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
677 an error indication, or maybe write to a new recent file and
678 rename that file on top of the old one only if there are not I/O
679 errors. */
680 return TRUE;
683 /* set one user's recent common file key/value pair */
684 static prefs_set_pref_e
685 read_set_recent_common_pair_static(gchar *key, const gchar *value,
686 void *private_data _U_,
687 gboolean return_range_errors _U_)
689 long num;
690 char *p;
692 if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
693 if (g_ascii_strcasecmp(value, "true") == 0) {
694 recent.gui_geometry_main_maximized = TRUE;
696 else {
697 recent.gui_geometry_main_maximized = FALSE;
700 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
701 num = strtol(value, &p, 0);
702 if (p == value || *p != '\0')
703 return PREFS_SET_SYNTAX_ERR; /* number was bad */
704 recent.gui_geometry_main_x = (gint)num;
705 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) {
706 num = strtol(value, &p, 0);
707 if (p == value || *p != '\0')
708 return PREFS_SET_SYNTAX_ERR; /* number was bad */
709 recent.gui_geometry_main_y = (gint)num;
710 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) {
711 num = strtol(value, &p, 0);
712 if (p == value || *p != '\0')
713 return PREFS_SET_SYNTAX_ERR; /* number was bad */
714 if (num <= 0)
715 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
716 recent.gui_geometry_main_width = (gint)num;
717 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {
718 num = strtol(value, &p, 0);
719 if (p == value || *p != '\0')
720 return PREFS_SET_SYNTAX_ERR; /* number was bad */
721 if (num <= 0)
722 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
723 recent.gui_geometry_main_height = (gint)num;
724 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT) == 0) {
725 num = strtol(value, &p, 0);
726 if (p == value || *p != '\0')
727 return PREFS_SET_SYNTAX_ERR; /* number was bad */
728 if (num <= 0)
729 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
730 recent.gui_geometry_status_pane_right = (gint)num;
731 recent.has_gui_geometry_status_pane = TRUE;
732 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT) == 0) {
733 num = strtol(value, &p, 0);
734 if (p == value || *p != '\0')
735 return PREFS_SET_SYNTAX_ERR; /* number was bad */
736 if (num <= 0)
737 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
738 recent.gui_geometry_status_pane_left = (gint)num;
739 recent.has_gui_geometry_status_pane = TRUE;
740 } else if (strcmp(key, RECENT_LAST_USED_PROFILE) == 0) {
741 if ((strcmp(value, DEFAULT_PROFILE) != 0) && profile_exists (value, FALSE)) {
742 set_profile_name (value);
744 } else if (strcmp(key, RECENT_GUI_GEOMETRY_WLAN_STATS_PANE) == 0) {
745 num = strtol(value, &p, 0);
746 if (p == value || *p != '\0')
747 return PREFS_SET_SYNTAX_ERR; /* number was bad */
748 if (num <= 0)
749 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
750 recent.gui_geometry_wlan_stats_pane = (gint)num;
751 } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) {
752 /* now have something like "gui.geom.main.x", split it into win and sub_key */
753 char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1];
754 char *sub_key = strchr(win, '.');
755 if(sub_key) {
756 *sub_key = '\0';
757 sub_key++;
758 window_geom_recent_read_pair(win, sub_key, value);
760 } else if (strcmp(key, RECENT_KEY_PRIVS_WARN_IF_ELEVATED) == 0) {
761 if (g_ascii_strcasecmp(value, "true") == 0) {
762 recent.privs_warn_if_elevated = TRUE;
764 else {
765 recent.privs_warn_if_elevated = FALSE;
767 } else if (strcmp(key, RECENT_KEY_PRIVS_WARN_IF_NO_NPF) == 0) {
768 if (g_ascii_strcasecmp(value, "true") == 0) {
769 recent.privs_warn_if_no_npf = TRUE;
771 else {
772 recent.privs_warn_if_no_npf = FALSE;
776 return PREFS_SET_OK;
779 /* set one user's recent file key/value pair */
780 static prefs_set_pref_e
781 read_set_recent_pair_static(gchar *key, const gchar *value,
782 void *private_data _U_,
783 gboolean return_range_errors _U_)
785 long num;
786 char *p;
787 GList *col_l, *col_l_elt;
788 col_width_data *cfmt;
789 const gchar *cust_format = col_format_to_string(COL_CUSTOM);
790 int cust_format_len = (int) strlen(cust_format);
792 if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
793 if (g_ascii_strcasecmp(value, "true") == 0) {
794 recent.main_toolbar_show = TRUE;
796 else {
797 recent.main_toolbar_show = FALSE;
799 } else if (strcmp(key, RECENT_KEY_FILTER_TOOLBAR_SHOW) == 0) {
800 if (g_ascii_strcasecmp(value, "true") == 0) {
801 recent.filter_toolbar_show = TRUE;
803 else {
804 recent.filter_toolbar_show = FALSE;
806 /* check both the old and the new keyword */
807 } else if (strcmp(key, RECENT_KEY_WIRELESS_TOOLBAR_SHOW) == 0 || (strcmp(key, "gui.airpcap_toolbar_show") == 0)) {
808 if (g_ascii_strcasecmp(value, "true") == 0) {
809 recent.wireless_toolbar_show = TRUE;
811 else {
812 recent.wireless_toolbar_show = FALSE;
814 } else if (strcmp(key, RECENT_KEY_DRIVER_CHECK_SHOW) == 0) {
815 if (g_ascii_strcasecmp(value, "true") == 0) {
816 recent.airpcap_driver_check_show = TRUE;
818 else {
819 recent.airpcap_driver_check_show = FALSE;
821 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_SHOW) == 0) {
822 if (g_ascii_strcasecmp(value, "true") == 0) {
823 recent.packet_list_show = TRUE;
825 else {
826 recent.packet_list_show = FALSE;
828 } else if (strcmp(key, RECENT_KEY_TREE_VIEW_SHOW) == 0) {
829 if (g_ascii_strcasecmp(value, "true") == 0) {
830 recent.tree_view_show = TRUE;
832 else {
833 recent.tree_view_show = FALSE;
835 } else if (strcmp(key, RECENT_KEY_BYTE_VIEW_SHOW) == 0) {
836 if (g_ascii_strcasecmp(value, "true") == 0) {
837 recent.byte_view_show = TRUE;
839 else {
840 recent.byte_view_show = FALSE;
842 } else if (strcmp(key, RECENT_KEY_STATUSBAR_SHOW) == 0) {
843 if (g_ascii_strcasecmp(value, "true") == 0) {
844 recent.statusbar_show = TRUE;
846 else {
847 recent.statusbar_show = FALSE;
849 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_COLORIZE) == 0) {
850 if (g_ascii_strcasecmp(value, "true") == 0) {
851 recent.packet_list_colorize = TRUE;
853 else {
854 recent.packet_list_colorize = FALSE;
856 } else if (strcmp(key, RECENT_GUI_TIME_FORMAT) == 0) {
857 recent.gui_time_format =
858 (ts_type)find_index_from_string_array(value, ts_type_text, TS_RELATIVE);
859 } else if (strcmp(key, RECENT_GUI_TIME_PRECISION) == 0) {
860 recent.gui_time_precision =
861 find_index_from_string_array(value, ts_precision_text, TS_PREC_AUTO);
862 } else if (strcmp(key, RECENT_GUI_SECONDS_FORMAT) == 0) {
863 recent.gui_seconds_format =
864 (ts_seconds_type)find_index_from_string_array(value, ts_seconds_text, TS_SECONDS_DEFAULT);
865 } else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL) == 0) {
866 num = strtol(value, &p, 0);
867 if (p == value || *p != '\0')
868 return PREFS_SET_SYNTAX_ERR; /* number was bad */
869 recent.gui_zoom_level = (gint)num;
870 } else if (strcmp(key, RECENT_GUI_BYTES_VIEW) == 0) {
871 num = strtol(value, &p, 0);
872 if (p == value || *p != '\0')
873 return PREFS_SET_SYNTAX_ERR; /* number was bad */
874 recent.gui_bytes_view = (gint)num;
875 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
876 if (g_ascii_strcasecmp(value, "true") == 0) {
877 recent.gui_geometry_main_maximized = TRUE;
879 else {
880 recent.gui_geometry_main_maximized = FALSE;
883 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) {
884 num = strtol(value, &p, 0);
885 if (p == value || *p != '\0')
886 return PREFS_SET_SYNTAX_ERR; /* number was bad */
887 if (num <= 0)
888 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
889 recent.gui_geometry_main_upper_pane = (gint)num;
890 recent.has_gui_geometry_main_upper_pane = TRUE;
891 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) {
892 num = strtol(value, &p, 0);
893 if (p == value || *p != '\0')
894 return PREFS_SET_SYNTAX_ERR; /* number was bad */
895 if (num <= 0)
896 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
897 recent.gui_geometry_main_lower_pane = (gint)num;
898 recent.has_gui_geometry_main_lower_pane = TRUE;
900 else if (strcmp(key, RECENT_KEY_COL_WIDTH) == 0) {
901 col_l = prefs_get_string_list(value);
902 if (col_l == NULL)
903 return PREFS_SET_SYNTAX_ERR;
904 if ((g_list_length(col_l) % 2) != 0) {
905 /* A title didn't have a matching width. */
906 prefs_clear_string_list(col_l);
907 return PREFS_SET_SYNTAX_ERR;
909 /* Check to make sure all column formats are valid. */
910 col_l_elt = g_list_first(col_l);
911 while(col_l_elt) {
912 /* Make sure the format isn't empty. */
913 if (strcmp((const char *)col_l_elt->data, "") == 0) {
914 /* It is. */
915 prefs_clear_string_list(col_l);
916 return PREFS_SET_SYNTAX_ERR;
919 /* Check the format. */
920 if (strncmp((const char *)col_l_elt->data, cust_format, cust_format_len) != 0) {
921 if (get_column_format_from_str((const gchar *)col_l_elt->data) == -1) {
922 /* It's not a valid column format. */
923 prefs_clear_string_list(col_l);
924 return PREFS_SET_SYNTAX_ERR;
928 /* Go past the format. */
929 col_l_elt = col_l_elt->next;
931 /* Go past the width. */
932 col_l_elt = col_l_elt->next;
934 free_col_width_info(&recent);
935 recent.col_width_list = NULL;
936 col_l_elt = g_list_first(col_l);
937 while(col_l_elt) {
938 gchar *fmt = g_strdup((const gchar *)col_l_elt->data);
939 cfmt = (col_width_data *) g_malloc(sizeof(col_width_data));
940 if (strncmp(fmt, cust_format, cust_format_len) != 0) {
941 cfmt->cfmt = get_column_format_from_str(fmt);
942 cfmt->cfield = NULL;
943 } else {
944 cfmt->cfmt = COL_CUSTOM;
945 cfmt->cfield = g_strdup(&fmt[cust_format_len+1]); /* add 1 for ':' */
947 g_free (fmt);
948 if (cfmt->cfmt == -1) {
949 g_free(cfmt->cfield);
950 g_free(cfmt);
951 return PREFS_SET_SYNTAX_ERR; /* string was bad */
954 col_l_elt = col_l_elt->next;
955 cfmt->width = (gint)strtol((const char *)col_l_elt->data, &p, 0);
956 if (p == col_l_elt->data || (*p != '\0' && *p != ':')) {
957 g_free(cfmt->cfield);
958 g_free(cfmt);
959 return PREFS_SET_SYNTAX_ERR; /* number was bad */
962 if (*p == ':') {
963 cfmt->xalign = *(++p);
964 } else {
965 cfmt->xalign = COLUMN_XALIGN_DEFAULT;
968 col_l_elt = col_l_elt->next;
969 recent.col_width_list = g_list_append(recent.col_width_list, cfmt);
971 prefs_clear_string_list(col_l);
972 } else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
973 if (recent.gui_fileopen_remembered_dir) {
974 g_free (recent.gui_fileopen_remembered_dir);
976 recent.gui_fileopen_remembered_dir = g_strdup(value);
979 return PREFS_SET_OK;
983 /* set one user's recent file key/value pair */
984 static prefs_set_pref_e
985 read_set_recent_pair_dynamic(gchar *key, const gchar *value,
986 void *private_data _U_,
987 gboolean return_range_errors _U_)
989 if (!isprint_string(value)) {
990 return PREFS_SET_SYNTAX_ERR;
992 if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
993 if (u3_active())
994 add_menu_recent_capture_file(u3_expand_device_path(value));
995 else
996 add_menu_recent_capture_file(value);
997 } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
998 dfilter_combo_add_recent(value);
999 } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER) == 0) {
1000 recent_add_cfilter(NULL, value);
1001 } else if (g_str_has_prefix(key, RECENT_KEY_CAPTURE_FILTER ".")) {
1002 /* strrchr() can't fail - string has a prefix that ends with a "." */
1003 recent_add_cfilter(strrchr(key, '.') + 1, value);
1004 #ifdef HAVE_PCAP_REMOTE
1005 } else if (strcmp(key, RECENT_KEY_REMOTE_HOST) == 0) {
1006 capture_remote_combo_add_recent(value);
1007 #endif
1010 return PREFS_SET_OK;
1015 * Given a string of the form "<recent name>:<recent value>", as might appear
1016 * as an argument to a "-o" option, parse it and set the recent value in
1017 * question. Return an indication of whether it succeeded or failed
1018 * in some fashion.
1021 recent_set_arg(char *prefarg)
1023 gchar *p, *colonp;
1024 int ret;
1026 colonp = strchr(prefarg, ':');
1027 if (colonp == NULL)
1028 return PREFS_SET_SYNTAX_ERR;
1030 p = colonp;
1031 *p++ = '\0';
1034 * Skip over any white space (there probably won't be any, but
1035 * as we allow it in the preferences file, we might as well
1036 * allow it here).
1038 while (isspace((guchar)*p))
1039 p++;
1040 if (*p == '\0') {
1042 * Put the colon back, so if our caller uses, in an
1043 * error message, the string they passed us, the message
1044 * looks correct.
1046 *colonp = ':';
1047 return PREFS_SET_SYNTAX_ERR;
1050 ret = read_set_recent_pair_static(prefarg, p, NULL, TRUE);
1051 *colonp = ':'; /* put the colon back */
1052 return ret;
1056 /* opens the user's recent common file and read the first part */
1057 void
1058 recent_read_static(char **rf_path_return, int *rf_errno_return)
1060 char *rf_path;
1061 FILE *rf;
1063 /* set defaults */
1064 recent.gui_geometry_main_x = 20;
1065 recent.gui_geometry_main_y = 20;
1066 recent.gui_geometry_main_width = DEF_WIDTH;
1067 recent.gui_geometry_main_height = DEF_HEIGHT;
1068 recent.gui_geometry_main_maximized= FALSE;
1070 recent.gui_geometry_status_pane_left = (DEF_WIDTH/3);
1071 recent.gui_geometry_status_pane_right = (DEF_WIDTH/3);
1072 recent.gui_geometry_wlan_stats_pane = 200;
1074 recent.privs_warn_if_elevated = TRUE;
1075 recent.privs_warn_if_no_npf = TRUE;
1077 recent.col_width_list = NULL;
1078 recent.gui_fileopen_remembered_dir = NULL;
1080 /* Construct the pathname of the user's recent common file. */
1081 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1083 /* Read the user's recent common file, if it exists. */
1084 *rf_path_return = NULL;
1085 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1086 /* We succeeded in opening it; read it. */
1087 read_prefs_file(rf_path, rf, read_set_recent_common_pair_static, NULL);
1089 fclose(rf);
1090 g_free(rf_path);
1091 rf_path = NULL;
1092 } else {
1093 /* We failed to open it. If we failed for some reason other than
1094 "it doesn't exist", return the errno and the pathname, so our
1095 caller can report the error. */
1096 if (errno != ENOENT) {
1097 *rf_errno_return = errno;
1098 *rf_path_return = rf_path;
1105 /* opens the user's recent file and read the first part */
1106 void
1107 recent_read_profile_static(char **rf_path_return, int *rf_errno_return)
1109 char *rf_path, *rf_common_path;
1110 FILE *rf;
1112 /* set defaults */
1113 recent.main_toolbar_show = TRUE;
1114 recent.filter_toolbar_show = TRUE;
1115 recent.wireless_toolbar_show = FALSE;
1116 recent.airpcap_driver_check_show = TRUE;
1117 recent.packet_list_show = TRUE;
1118 recent.tree_view_show = TRUE;
1119 recent.byte_view_show = TRUE;
1120 recent.statusbar_show = TRUE;
1121 recent.packet_list_colorize = TRUE;
1122 recent.gui_time_format = TS_RELATIVE;
1123 recent.gui_time_precision = TS_PREC_AUTO;
1124 recent.gui_seconds_format = TS_SECONDS_DEFAULT;
1125 recent.gui_zoom_level = 0;
1126 recent.gui_bytes_view = 0;
1128 /* pane size of zero will autodetect */
1129 recent.gui_geometry_main_upper_pane = 0;
1130 recent.gui_geometry_main_lower_pane = 0;
1132 recent.has_gui_geometry_main_upper_pane = TRUE;
1133 recent.has_gui_geometry_main_lower_pane = TRUE;
1134 recent.has_gui_geometry_status_pane = TRUE;
1136 if (recent.col_width_list) {
1137 free_col_width_info(&recent);
1140 if (recent.gui_fileopen_remembered_dir) {
1141 g_free (recent.gui_fileopen_remembered_dir);
1142 recent.gui_fileopen_remembered_dir = NULL;
1145 /* Construct the pathname of the user's profile recent file. */
1146 rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
1148 /* Read the user's recent file, if it exists. */
1149 *rf_path_return = NULL;
1150 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1151 /* We succeeded in opening it; read it. */
1152 read_prefs_file(rf_path, rf, read_set_recent_pair_static, NULL);
1153 fclose(rf);
1155 /* XXX: The following code doesn't actually do anything since
1156 * the "recent common file" always exists. Presumably the
1157 * "if (!file_exists())" should actually be "if (file_exists())".
1158 * However, I've left the code as is because this
1159 * behaviour has existed for quite some time and I don't
1160 * know what's supposed to happen at this point.
1161 * ToDo: Determine if the "recent common file" should be read at this point
1163 rf_common_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1164 if (!file_exists(rf_common_path)) {
1165 /* Read older common settings from recent file */
1166 rf = ws_fopen(rf_path, "r");
1167 read_prefs_file(rf_path, rf, read_set_recent_common_pair_static, NULL);
1168 fclose(rf);
1170 g_free(rf_common_path);
1171 g_free(rf_path);
1172 rf_path = NULL;
1173 } else {
1174 /* We failed to open it. If we failed for some reason other than
1175 "it doesn't exist", return the errno and the pathname, so our
1176 caller can report the error. */
1177 if (errno != ENOENT) {
1178 *rf_errno_return = errno;
1179 *rf_path_return = rf_path;
1184 /* opens the user's recent file and read it out */
1185 void
1186 recent_read_dynamic(char **rf_path_return, int *rf_errno_return)
1188 char *rf_path;
1189 FILE *rf;
1192 /* Construct the pathname of the user's recent common file. */
1193 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1194 if (!file_exists (rf_path)) {
1195 /* Recent common file does not exist, read from default recent */
1196 g_free (rf_path);
1197 rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
1200 /* Read the user's recent file, if it exists. */
1201 *rf_path_return = NULL;
1202 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1203 /* We succeeded in opening it; read it. */
1204 read_prefs_file(rf_path, rf, read_set_recent_pair_dynamic, NULL);
1205 #if 0
1206 /* set dfilter combobox to have an empty line */
1207 dfilter_combo_add_empty();
1208 #endif
1209 fclose(rf);
1210 g_free(rf_path);
1211 rf_path = NULL;
1212 } else {
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;
1223 gint
1224 recent_get_column_width(gint col)
1226 GList *col_l;
1227 col_width_data *col_w;
1228 gint cfmt;
1229 const gchar *cfield = NULL;
1231 cfmt = get_column_format(col);
1232 if (cfmt == COL_CUSTOM) {
1233 cfield = get_column_custom_field(col);
1236 col_l = g_list_first(recent.col_width_list);
1237 while (col_l) {
1238 col_w = (col_width_data *) col_l->data;
1239 if (col_w->cfmt == cfmt) {
1240 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1241 return col_w->width;
1244 col_l = col_l->next;
1247 return -1;
1250 void
1251 recent_set_column_width(gint col, gint width)
1253 GList *col_l;
1254 col_width_data *col_w;
1255 gint cfmt;
1256 const gchar *cfield = NULL;
1257 gboolean found = FALSE;
1259 cfmt = get_column_format(col);
1260 if (cfmt == COL_CUSTOM) {
1261 cfield = get_column_custom_field(col);
1264 col_l = g_list_first(recent.col_width_list);
1265 while (col_l) {
1266 col_w = (col_width_data *) col_l->data;
1267 if (col_w->cfmt == cfmt) {
1268 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1269 col_w->width = width;
1270 found = TRUE;
1271 break;
1274 col_l = col_l->next;
1277 if (!found) {
1278 col_w = (col_width_data *) g_malloc(sizeof(col_width_data));
1279 col_w->cfmt = cfmt;
1280 if (cfield) {
1281 col_w->cfield = g_strdup(cfield);
1282 } else {
1283 col_w->cfield = NULL;
1285 col_w->width = width;
1286 col_w->xalign = COLUMN_XALIGN_DEFAULT;
1287 recent.col_width_list = g_list_append(recent.col_width_list, col_w);
1291 gchar
1292 recent_get_column_xalign(gint col)
1294 GList *col_l;
1295 col_width_data *col_w;
1296 gint cfmt;
1297 const gchar *cfield = NULL;
1299 cfmt = get_column_format(col);
1300 if (cfmt == COL_CUSTOM) {
1301 cfield = get_column_custom_field(col);
1304 col_l = g_list_first(recent.col_width_list);
1305 while (col_l) {
1306 col_w = (col_width_data *) col_l->data;
1307 if (col_w->cfmt == cfmt) {
1308 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1309 return col_w->xalign;
1312 col_l = col_l->next;
1315 return 0;
1318 void
1319 recent_set_column_xalign(gint col, gchar xalign)
1321 GList *col_l;
1322 col_width_data *col_w;
1323 gint cfmt;
1324 const gchar *cfield = NULL;
1325 gboolean found = FALSE;
1327 cfmt = get_column_format(col);
1328 if (cfmt == COL_CUSTOM) {
1329 cfield = get_column_custom_field(col);
1332 col_l = g_list_first(recent.col_width_list);
1333 while (col_l) {
1334 col_w = (col_width_data *) col_l->data;
1335 if (col_w->cfmt == cfmt) {
1336 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1337 col_w->xalign = xalign;
1338 found = TRUE;
1339 break;
1342 col_l = col_l->next;
1345 if (!found) {
1346 col_w = (col_width_data *) g_malloc(sizeof(col_width_data));
1347 col_w->cfmt = cfmt;
1348 if (cfield) {
1349 col_w->cfield = g_strdup(cfield);
1350 } else {
1351 col_w->cfield = NULL;
1353 col_w->width = 40;
1354 col_w->xalign = xalign;
1355 recent.col_width_list = g_list_append(recent.col_width_list, col_w);