2 * Recent "preference" handling routines
3 * Copyright 2004, Ulf Lamping <ulf.lamping@web.de>
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.
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.
101 find_index_from_string_array(const char *needle
, const char **haystack
, int default_value
)
105 while (haystack
[i
] != NULL
) {
106 if (strcmp(needle
, haystack
[i
]) == 0) {
111 return default_value
;
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
);
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.
132 * @param value the geometry values
133 * @param rfh recent file handle (FILE)
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
,
147 fprintf(rf
, RECENT_GUI_GEOMETRY
"%s.height: %d\n", geom
->key
,
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 */
162 window_geom_save(const gchar
*name
, window_geometry_t
*geom
)
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
);
174 g_hash_table_remove(window_geom_hash
, name
);
179 /* g_malloc and insert the new one */
180 work
= (window_geometry_t
*)g_malloc(sizeof(window_geometry_t
));
182 key
= g_strdup(name
);
184 g_hash_table_insert(window_geom_hash
, key
, work
);
187 /* load the desired geometry for this window from the geometry hashtable */
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
);
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")
215 window_geom_recent_read_pair(const char *name
,
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
;
228 geom
.set_size
= FALSE
;
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);
239 } else if (strcmp(key
, "y") == 0) {
240 geom
.y
= (gint
)strtol(value
, NULL
, 10);
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
;
253 geom
.maximized
= FALSE
;
255 geom
.set_maximized
= TRUE
;
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?
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
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.
304 recent_get_cfilter_list(const gchar
*ifname
)
307 return recent_cfilter_list
;
308 if (per_interface_cfilter_lists_hash
== NULL
) {
309 /* No such lists exist. */
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
323 recent_add_cfilter(const gchar
*ifname
, const gchar
*s
)
327 gchar
*li_filter
, *newfilter
= NULL
;
329 /* Don't add empty filters to the list. */
334 cfilter_list
= recent_cfilter_list
;
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
);
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
);
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
);
364 recent_cfilter_list
= cfilter_list
;
366 g_hash_table_insert(per_interface_cfilter_lists_hash
, g_strdup(ifname
), cfilter_list
);
370 cfilter_recent_write_all_list(FILE *rf
, const gchar
*ifname
, GList
*cfilter_list
)
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
)) {
380 fprintf (rf
, RECENT_KEY_CAPTURE_FILTER
": %s\n", (char *)li
->data
);
382 fprintf (rf
, RECENT_KEY_CAPTURE_FILTER
".%s: %s\n", ifname
, (char *)li
->data
);
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
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. */
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
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
,
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
,
446 fputs("# Recent settings file for Wireshark " VERSION
".\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"
451 "######## Recent capture files (latest last), cannot be altered through command line ########\n"
454 menu_recent_file_write_all(rf
);
457 "######## Recent capture filters (latest last), cannot be altered through command line ########\n"
460 cfilter_recent_write_all(rf
);
463 "######## Recent display filters (latest last), cannot be altered through command line ########\n"
466 dfilter_recent_combo_write_all(rf
);
468 #ifdef HAVE_PCAP_REMOTE
470 "######## Recent remote hosts, cannot be altered through command line ########\n"
473 capture_remote_combo_recent_write_all(rf
);
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
);
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
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. */
537 write_profile_recent(void)
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
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
,
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
,
569 fputs("# Recent settings file for Wireshark " VERSION
".\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"
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");
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");
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");
669 fprintf(rf
, RECENT_GUI_FILEOPEN_REMEMBERED_DIR
": %s\n", u3_contract_device_path(get_last_open_dir()));
671 fprintf(rf
, RECENT_GUI_FILEOPEN_REMEMBERED_DIR
": %s\n", get_last_open_dir());
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
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_
)
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
;
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 */
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 */
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 */
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 */
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 */
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
, '.');
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
;
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
;
772 recent
.privs_warn_if_no_npf
= FALSE
;
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_
)
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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 */
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 */
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
);
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
);
912 /* Make sure the format isn't empty. */
913 if (strcmp((const char *)col_l_elt
->data
, "") == 0) {
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
);
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
);
944 cfmt
->cfmt
= COL_CUSTOM
;
945 cfmt
->cfield
= g_strdup(&fmt
[cust_format_len
+1]); /* add 1 for ':' */
948 if (cfmt
->cfmt
== -1) {
949 g_free(cfmt
->cfield
);
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
);
959 return PREFS_SET_SYNTAX_ERR
; /* number was bad */
963 cfmt
->xalign
= *(++p
);
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
);
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) {
994 add_menu_recent_capture_file(u3_expand_device_path(value
));
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
);
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
1021 recent_set_arg(char *prefarg
)
1026 colonp
= strchr(prefarg
, ':');
1028 return PREFS_SET_SYNTAX_ERR
;
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
1038 while (isspace((guchar
)*p
))
1042 * Put the colon back, so if our caller uses, in an
1043 * error message, the string they passed us, the message
1047 return PREFS_SET_SYNTAX_ERR
;
1050 ret
= read_set_recent_pair_static(prefarg
, p
, NULL
, TRUE
);
1051 *colonp
= ':'; /* put the colon back */
1056 /* opens the user's recent common file and read the first part */
1058 recent_read_static(char **rf_path_return
, int *rf_errno_return
)
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
);
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 */
1107 recent_read_profile_static(char **rf_path_return
, int *rf_errno_return
)
1109 char *rf_path
, *rf_common_path
;
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
);
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
);
1170 g_free(rf_common_path
);
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 */
1186 recent_read_dynamic(char **rf_path_return
, int *rf_errno_return
)
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 */
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
);
1206 /* set dfilter combobox to have an empty line */
1207 dfilter_combo_add_empty();
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
;
1224 recent_get_column_width(gint col
)
1227 col_width_data
*col_w
;
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
);
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
;
1251 recent_set_column_width(gint col
, gint width
)
1254 col_width_data
*col_w
;
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
);
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
;
1274 col_l
= col_l
->next
;
1278 col_w
= (col_width_data
*) g_malloc(sizeof(col_width_data
));
1281 col_w
->cfield
= g_strdup(cfield
);
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
);
1292 recent_get_column_xalign(gint col
)
1295 col_width_data
*col_w
;
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
);
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
;
1319 recent_set_column_xalign(gint col
, gchar xalign
)
1322 col_width_data
*col_w
;
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
);
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
;
1342 col_l
= col_l
->next
;
1346 col_w
= (col_width_data
*) g_malloc(sizeof(col_width_data
));
1349 col_w
->cfield
= g_strdup(cfield
);
1351 col_w
->cfield
= NULL
;
1354 col_w
->xalign
= xalign
;
1355 recent
.col_width_list
= g_list_append(recent
.col_width_list
, col_w
);