2 * Recent "preference" handling routines
3 * Copyright 2004, Ulf Lamping <ulf.lamping@web.de>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include <epan/epan.h>
36 #include <epan/filesystem.h>
40 #include "prefs-int.h"
42 #include "dlg_utils.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_PACKET_LIST_SHOW "gui.packet_list_show"
48 #define RECENT_KEY_TREE_VIEW_SHOW "gui.tree_view_show"
49 #define RECENT_KEY_BYTE_VIEW_SHOW "gui.byte_view_show"
50 #define RECENT_KEY_STATUSBAR_SHOW "gui.statusbar_show"
51 #define RECENT_GUI_TIME_FORMAT "gui.time_format"
52 #define RECENT_GUI_ZOOM_LEVEL "gui.zoom_level"
53 #define RECENT_GUI_GEOMETRY_MAIN_X "gui.geometry_main_x"
54 #define RECENT_GUI_GEOMETRY_MAIN_Y "gui.geometry_main_y"
55 #define RECENT_GUI_GEOMETRY_MAIN_WIDTH "gui.geometry_main_width"
56 #define RECENT_GUI_GEOMETRY_MAIN_HEIGHT "gui.geometry_main_height"
57 #define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized"
58 #define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane"
59 #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane"
60 #define RECENT_GUI_GEOMETRY_STATUS_PANE "gui.geometry_status_pane"
61 #define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir"
62 #define RECENT_GUI_GEOMETRY "gui.geom."
64 #define RECENT_FILE_NAME "recent"
67 /* #include "../menu.h" */
68 extern void add_menu_recent_capture_file(gchar *file);
70 recent_settings_t recent;
72 static char *ts_type_text[] =
73 { "RELATIVE", "ABSOLUTE", "ABSOLUTE_WITH_DATE", "DELTA", NULL };
75 /* Takes an string and a pointer to an array of strings, and a default int value.
76 * The array must be terminated by a NULL string. If the string is found in the array
77 * of strings, the index of that string in the array is returned. Otherwise, the
78 * default value that was passed as the third argument is returned.
81 find_index_from_string_array(char *needle, char **haystack, int default_value)
85 while (haystack[i] != NULL) {
86 if (strcmp(needle, haystack[i]) == 0) {
94 /* Write out "recent" to the user's recent file, and return 0.
95 If we got an error, stuff a pointer to the path of the recent file
96 into "*pf_path_return", and return the errno. */
98 write_recent(char **rf_path_return)
104 * - Split output lines longer than MAX_VAL_LEN
105 * - Create a function for the preference directory check/creation
106 * so that duplication can be avoided with filter.c
109 rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
110 if ((rf = fopen(rf_path, "w")) == NULL) {
111 *rf_path_return = rf_path;
115 fputs("# Recent settings file for Ethereal " VERSION ".\n"
117 "# This file is regenerated each time Ethereal is quit.\n"
118 "# So be careful, if you want to make manual changes here.\n"
120 "######## Recent capture files (latest last) ########\n"
123 menu_recent_file_write_all(rf);
126 "######## Recent display filters (latest last) ########\n"
129 dfilter_recent_combo_write_all(rf);
131 fprintf(rf, "\n# Main Toolbar show (hide).\n");
132 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
133 fprintf(rf, RECENT_KEY_MAIN_TOOLBAR_SHOW ": %s\n",
134 recent.main_toolbar_show == TRUE ? "TRUE" : "FALSE");
136 fprintf(rf, "\n# Filter Toolbar show (hide).\n");
137 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
138 fprintf(rf, RECENT_KEY_FILTER_TOOLBAR_SHOW ": %s\n",
139 recent.filter_toolbar_show == TRUE ? "TRUE" : "FALSE");
141 fprintf(rf, "\n# Packet list show (hide).\n");
142 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
143 fprintf(rf, RECENT_KEY_PACKET_LIST_SHOW ": %s\n",
144 recent.packet_list_show == TRUE ? "TRUE" : "FALSE");
146 fprintf(rf, "\n# Tree view show (hide).\n");
147 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
148 fprintf(rf, RECENT_KEY_TREE_VIEW_SHOW ": %s\n",
149 recent.tree_view_show == TRUE ? "TRUE" : "FALSE");
151 fprintf(rf, "\n# Byte view show (hide).\n");
152 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
153 fprintf(rf, RECENT_KEY_BYTE_VIEW_SHOW ": %s\n",
154 recent.byte_view_show == TRUE ? "TRUE" : "FALSE");
156 fprintf(rf, "\n# Statusbar show (hide).\n");
157 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
158 fprintf(rf, RECENT_KEY_STATUSBAR_SHOW ": %s\n",
159 recent.statusbar_show == TRUE ? "TRUE" : "FALSE");
161 fprintf(rf, "\n# Timestamp display format.\n");
162 fprintf(rf, "# One of: RELATIVE, ABSOLUTE, ABSOLUTE_WITH_DATE, DELTA\n");
163 fprintf(rf, RECENT_GUI_TIME_FORMAT ": %s\n",
164 ts_type_text[recent.gui_time_format]);
166 fprintf(rf, "\n# Zoom level.\n");
167 fprintf(rf, "# A decimal number.\n");
168 fprintf(rf, RECENT_GUI_ZOOM_LEVEL ": %d\n",
169 recent.gui_zoom_level);
171 fprintf(rf, "\n# Main window geometry.\n");
172 fprintf(rf, "# Decimal integers.\n");
173 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X ": %d\n", recent.gui_geometry_main_x);
174 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y ": %d\n", recent.gui_geometry_main_y);
175 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH ": %d\n",
176 recent.gui_geometry_main_width);
177 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT ": %d\n",
178 recent.gui_geometry_main_height);
180 fprintf(rf, "\n# Main window maximized (GTK2 only).\n");
181 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
182 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED ": %s\n",
183 recent.gui_geometry_main_maximized == TRUE ? "TRUE" : "FALSE");
185 fprintf(rf, "\n# Main window panes (GTK2 only).\n");
186 fprintf(rf, "# Decimal numbers.\n");
187 if (recent.gui_geometry_main_upper_pane != 0) {
188 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
189 recent.gui_geometry_main_upper_pane);
191 if (recent.gui_geometry_main_lower_pane != 0) {
192 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
193 recent.gui_geometry_main_lower_pane);
195 if (recent.gui_geometry_status_pane != 0) {
196 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE ": %d\n",
197 recent.gui_geometry_status_pane);
200 if (get_last_open_dir() != NULL) {
201 fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
202 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", get_last_open_dir());
205 window_geom_recent_write_all(rf);
209 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
210 an error indication, or maybe write to a new preferences file and
211 rename that file on top of the old one only if there are not I/O
217 /* write the geometry values of a window to recent file */
219 write_recent_geom(gpointer key _U_, gpointer value, gpointer rf)
221 window_geometry_t *geom = value;
223 fprintf(rf, "\n# Geometry and maximized state (GTK2 only) of %s window.\n", geom->key);
224 fprintf(rf, "# Decimal integers.\n");
225 fprintf(rf, RECENT_GUI_GEOMETRY "%s.x: %d\n", geom->key, geom->x);
226 fprintf(rf, RECENT_GUI_GEOMETRY "%s.y: %d\n", geom->key, geom->y);
227 fprintf(rf, RECENT_GUI_GEOMETRY "%s.width: %d\n", geom->key,
229 fprintf(rf, RECENT_GUI_GEOMETRY "%s.height: %d\n", geom->key,
232 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
233 fprintf(rf, RECENT_GUI_GEOMETRY "%s.maximized: %s\n", geom->key,
234 geom->maximized == TRUE ? "TRUE" : "FALSE");
239 /* set one user's recent file key/value pair */
241 read_set_recent_pair(gchar *key, gchar *value)
246 if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
247 add_menu_recent_capture_file(value);
248 } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
249 dfilter_combo_add_recent(value);
250 } else if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
251 if (strcasecmp(value, "true") == 0) {
252 recent.main_toolbar_show = TRUE;
255 recent.main_toolbar_show = FALSE;
257 } else if (strcmp(key, RECENT_KEY_FILTER_TOOLBAR_SHOW) == 0) {
258 if (strcasecmp(value, "true") == 0) {
259 recent.filter_toolbar_show = TRUE;
262 recent.filter_toolbar_show = FALSE;
264 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_SHOW) == 0) {
265 if (strcasecmp(value, "true") == 0) {
266 recent.packet_list_show = TRUE;
269 recent.packet_list_show = FALSE;
271 } else if (strcmp(key, RECENT_KEY_TREE_VIEW_SHOW) == 0) {
272 if (strcasecmp(value, "true") == 0) {
273 recent.tree_view_show = TRUE;
276 recent.tree_view_show = FALSE;
278 } else if (strcmp(key, RECENT_KEY_BYTE_VIEW_SHOW) == 0) {
279 if (strcasecmp(value, "true") == 0) {
280 recent.byte_view_show = TRUE;
283 recent.byte_view_show = FALSE;
285 } else if (strcmp(key, RECENT_KEY_STATUSBAR_SHOW) == 0) {
286 if (strcasecmp(value, "true") == 0) {
287 recent.statusbar_show = TRUE;
290 recent.statusbar_show = FALSE;
292 } else if (strcmp(key, RECENT_GUI_TIME_FORMAT) == 0) {
293 recent.gui_time_format =
294 find_index_from_string_array(value, ts_type_text, TS_RELATIVE);
295 } else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL) == 0) {
296 num = strtol(value, &p, 0);
297 if (p == value || *p != '\0')
298 return PREFS_SET_SYNTAX_ERR; /* number was bad */
299 recent.gui_zoom_level = num;
300 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
301 if (strcasecmp(value, "true") == 0) {
302 recent.gui_geometry_main_maximized = TRUE;
305 recent.gui_geometry_main_maximized = FALSE;
308 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
309 num = strtol(value, &p, 0);
310 if (p == value || *p != '\0')
311 return PREFS_SET_SYNTAX_ERR; /* number was bad */
312 recent.gui_geometry_main_x = num;
313 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) {
314 num = strtol(value, &p, 0);
315 if (p == value || *p != '\0')
316 return PREFS_SET_SYNTAX_ERR; /* number was bad */
317 recent.gui_geometry_main_y = num;
318 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) {
319 num = strtol(value, &p, 0);
320 if (p == value || *p != '\0')
321 return PREFS_SET_SYNTAX_ERR; /* number was bad */
323 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
324 recent.gui_geometry_main_width = num;
325 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {
326 num = strtol(value, &p, 0);
327 if (p == value || *p != '\0')
328 return PREFS_SET_SYNTAX_ERR; /* number was bad */
330 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
331 recent.gui_geometry_main_height = num;
332 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) {
333 num = strtol(value, &p, 0);
334 if (p == value || *p != '\0')
335 return PREFS_SET_SYNTAX_ERR; /* number was bad */
337 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
338 recent.gui_geometry_main_upper_pane = num;
339 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) {
340 num = strtol(value, &p, 0);
341 if (p == value || *p != '\0')
342 return PREFS_SET_SYNTAX_ERR; /* number was bad */
344 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
345 recent.gui_geometry_main_lower_pane = num;
346 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE) == 0) {
347 num = strtol(value, &p, 0);
348 if (p == value || *p != '\0')
349 return PREFS_SET_SYNTAX_ERR; /* number was bad */
351 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
352 recent.gui_geometry_status_pane = num;
353 } else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
354 set_last_open_dir(value);
355 } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) {
356 /* now have something like "gui.geom.main.x", split it into win and sub_key */
357 char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1];
358 char *sub_key = strchr(win, '.');
362 window_geom_recent_read_pair(win, sub_key, value);
370 /* opens the user's recent file and read it out */
372 read_recent(char **rf_path_return, int *rf_errno_return)
379 recent.main_toolbar_show = TRUE;
380 recent.filter_toolbar_show = TRUE;
381 recent.packet_list_show = TRUE;
382 recent.tree_view_show = TRUE;
383 recent.byte_view_show = TRUE;
384 recent.statusbar_show = TRUE;
385 recent.gui_time_format = TS_RELATIVE;
386 recent.gui_zoom_level = 0;
388 recent.gui_geometry_main_x = 20;
389 recent.gui_geometry_main_y = 20;
390 recent.gui_geometry_main_width = DEF_WIDTH;
391 recent.gui_geometry_main_height = DEF_HEIGHT;
392 recent.gui_geometry_main_maximized= FALSE;
394 /* pane size of zero will autodetect */
395 recent.gui_geometry_main_upper_pane = 0;
396 recent.gui_geometry_main_lower_pane = 0;
397 recent.gui_geometry_status_pane = 0;
399 /* Construct the pathname of the user's recent file. */
400 rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
402 /* Read the user's recent file, if it exists. */
403 *rf_path_return = NULL;
404 if ((rf = fopen(rf_path, "r")) != NULL) {
405 /* We succeeded in opening it; read it. */
406 read_prefs_file(rf_path, rf, read_set_recent_pair);
407 /* set dfilter combobox to have an empty line */
408 dfilter_combo_add_empty();
413 /* We failed to open it. If we failed for some reason other than
414 "it doesn't exist", return the errno and the pathname, so our
415 caller can report the error. */
416 if (errno != ENOENT) {
417 *rf_errno_return = errno;
418 *rf_path_return = rf_path;