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>
39 #include <epan/prefs.h>
40 #include <epan/prefs-int.h>
42 #include "dlg_utils.h"
43 #include "cfilter_combo_utils.h"
44 #include "simple_dialog.h"
46 #define RECENT_KEY_MAIN_TOOLBAR_SHOW "gui.toolbar_main_show"
47 #define RECENT_KEY_FILTER_TOOLBAR_SHOW "gui.filter_toolbar_show"
48 #define RECENT_KEY_PACKET_LIST_SHOW "gui.packet_list_show"
49 #define RECENT_KEY_TREE_VIEW_SHOW "gui.tree_view_show"
50 #define RECENT_KEY_BYTE_VIEW_SHOW "gui.byte_view_show"
51 #define RECENT_KEY_STATUSBAR_SHOW "gui.statusbar_show"
52 #define RECENT_KEY_PACKET_LIST_COLORIZE "gui.packet_list_colorize"
53 #define RECENT_GUI_TIME_FORMAT "gui.time_format"
54 #define RECENT_GUI_ZOOM_LEVEL "gui.zoom_level"
55 #define RECENT_GUI_GEOMETRY_MAIN_X "gui.geometry_main_x"
56 #define RECENT_GUI_GEOMETRY_MAIN_Y "gui.geometry_main_y"
57 #define RECENT_GUI_GEOMETRY_MAIN_WIDTH "gui.geometry_main_width"
58 #define RECENT_GUI_GEOMETRY_MAIN_HEIGHT "gui.geometry_main_height"
59 #define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized"
60 #define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane"
61 #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane"
62 #define RECENT_GUI_GEOMETRY_STATUS_PANE "gui.geometry_status_pane"
63 #define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir"
64 #define RECENT_GUI_GEOMETRY "gui.geom."
66 #define RECENT_FILE_NAME "recent"
69 /* #include "../menu.h" */
70 extern void add_menu_recent_capture_file(gchar *file);
72 recent_settings_t recent;
74 static char *ts_type_text[] =
75 { "RELATIVE", "ABSOLUTE", "ABSOLUTE_WITH_DATE", "DELTA", NULL };
77 /* Takes an string and a pointer to an array of strings, and a default int value.
78 * The array must be terminated by a NULL string. If the string is found in the array
79 * of strings, the index of that string in the array is returned. Otherwise, the
80 * default value that was passed as the third argument is returned.
83 find_index_from_string_array(char *needle, char **haystack, int default_value)
87 while (haystack[i] != NULL) {
88 if (strcmp(needle, haystack[i]) == 0) {
96 /* Attempt to Write out "recent" to the user's recent file.
97 If we got an error report it with a dialog box and return FALSE,
98 otherwise return TRUE. */
107 * - Split output lines longer than MAX_VAL_LEN
108 * - Create a function for the preference directory check/creation
109 * so that duplication can be avoided with filter.c
112 /* Create the directory that holds personal configuration files, if
114 if (create_persconffile_dir(&pf_dir_path) == -1) {
115 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
116 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
122 rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
123 if ((rf = fopen(rf_path, "w")) == NULL) {
124 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
125 "Can't open recent file\n\"%s\": %s.", rf_path,
131 fputs("# Recent settings file for Ethereal " VERSION ".\n"
133 "# This file is regenerated each time Ethereal is quit.\n"
134 "# So be careful, if you want to make manual changes here.\n"
136 "######## Recent capture files (latest last) ########\n"
139 menu_recent_file_write_all(rf);
142 "######## Recent capture filters (latest last) ########\n"
145 cfilter_combo_recent_write_all(rf);
148 "######## Recent display filters (latest last) ########\n"
151 dfilter_recent_combo_write_all(rf);
153 fprintf(rf, "\n# Main Toolbar show (hide).\n");
154 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
155 fprintf(rf, RECENT_KEY_MAIN_TOOLBAR_SHOW ": %s\n",
156 recent.main_toolbar_show == TRUE ? "TRUE" : "FALSE");
158 fprintf(rf, "\n# Filter Toolbar show (hide).\n");
159 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
160 fprintf(rf, RECENT_KEY_FILTER_TOOLBAR_SHOW ": %s\n",
161 recent.filter_toolbar_show == TRUE ? "TRUE" : "FALSE");
163 fprintf(rf, "\n# Packet list show (hide).\n");
164 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
165 fprintf(rf, RECENT_KEY_PACKET_LIST_SHOW ": %s\n",
166 recent.packet_list_show == TRUE ? "TRUE" : "FALSE");
168 fprintf(rf, "\n# Tree view show (hide).\n");
169 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
170 fprintf(rf, RECENT_KEY_TREE_VIEW_SHOW ": %s\n",
171 recent.tree_view_show == TRUE ? "TRUE" : "FALSE");
173 fprintf(rf, "\n# Byte view show (hide).\n");
174 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
175 fprintf(rf, RECENT_KEY_BYTE_VIEW_SHOW ": %s\n",
176 recent.byte_view_show == TRUE ? "TRUE" : "FALSE");
178 fprintf(rf, "\n# Statusbar show (hide).\n");
179 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
180 fprintf(rf, RECENT_KEY_STATUSBAR_SHOW ": %s\n",
181 recent.statusbar_show == TRUE ? "TRUE" : "FALSE");
183 fprintf(rf, "\n# Packet list colorize (hide).\n");
184 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
185 fprintf(rf, RECENT_KEY_PACKET_LIST_COLORIZE ": %s\n",
186 recent.packet_list_colorize == TRUE ? "TRUE" : "FALSE");
188 fprintf(rf, "\n# Timestamp display format.\n");
189 fprintf(rf, "# One of: RELATIVE, ABSOLUTE, ABSOLUTE_WITH_DATE, DELTA\n");
190 fprintf(rf, RECENT_GUI_TIME_FORMAT ": %s\n",
191 ts_type_text[recent.gui_time_format]);
193 fprintf(rf, "\n# Zoom level.\n");
194 fprintf(rf, "# A decimal number.\n");
195 fprintf(rf, RECENT_GUI_ZOOM_LEVEL ": %d\n",
196 recent.gui_zoom_level);
198 fprintf(rf, "\n# Main window geometry.\n");
199 fprintf(rf, "# Decimal integers.\n");
200 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X ": %d\n", recent.gui_geometry_main_x);
201 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y ": %d\n", recent.gui_geometry_main_y);
202 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH ": %d\n",
203 recent.gui_geometry_main_width);
204 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT ": %d\n",
205 recent.gui_geometry_main_height);
207 fprintf(rf, "\n# Main window maximized (GTK2 only).\n");
208 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
209 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED ": %s\n",
210 recent.gui_geometry_main_maximized == TRUE ? "TRUE" : "FALSE");
212 fprintf(rf, "\n# Main window panes (GTK2 only).\n");
213 fprintf(rf, "# Decimal numbers.\n");
214 if (recent.gui_geometry_main_upper_pane != 0) {
215 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
216 recent.gui_geometry_main_upper_pane);
218 if (recent.gui_geometry_main_lower_pane != 0) {
219 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
220 recent.gui_geometry_main_lower_pane);
222 if (recent.gui_geometry_status_pane != 0) {
223 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE ": %d\n",
224 recent.gui_geometry_status_pane);
227 if (get_last_open_dir() != NULL) {
228 fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
229 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", get_last_open_dir());
232 window_geom_recent_write_all(rf);
236 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
237 an error indication, or maybe write to a new recent file and
238 rename that file on top of the old one only if there are not I/O
244 /* write the geometry values of a window to recent file */
246 write_recent_geom(gpointer key _U_, gpointer value, gpointer rf)
248 window_geometry_t *geom = value;
250 fprintf(rf, "\n# Geometry and maximized state (GTK2 only) of %s window.\n", geom->key);
251 fprintf(rf, "# Decimal integers.\n");
252 fprintf(rf, RECENT_GUI_GEOMETRY "%s.x: %d\n", geom->key, geom->x);
253 fprintf(rf, RECENT_GUI_GEOMETRY "%s.y: %d\n", geom->key, geom->y);
254 fprintf(rf, RECENT_GUI_GEOMETRY "%s.width: %d\n", geom->key,
256 fprintf(rf, RECENT_GUI_GEOMETRY "%s.height: %d\n", geom->key,
259 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
260 fprintf(rf, RECENT_GUI_GEOMETRY "%s.maximized: %s\n", geom->key,
261 geom->maximized == TRUE ? "TRUE" : "FALSE");
266 /* set one user's recent file key/value pair */
268 read_set_recent_pair(gchar *key, gchar *value)
273 if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
274 add_menu_recent_capture_file(value);
275 } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
276 dfilter_combo_add_recent(value);
277 } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER) == 0) {
278 cfilter_combo_add_recent(value);
279 } else if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
280 if (strcasecmp(value, "true") == 0) {
281 recent.main_toolbar_show = TRUE;
284 recent.main_toolbar_show = FALSE;
286 } else if (strcmp(key, RECENT_KEY_FILTER_TOOLBAR_SHOW) == 0) {
287 if (strcasecmp(value, "true") == 0) {
288 recent.filter_toolbar_show = TRUE;
291 recent.filter_toolbar_show = FALSE;
293 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_SHOW) == 0) {
294 if (strcasecmp(value, "true") == 0) {
295 recent.packet_list_show = TRUE;
298 recent.packet_list_show = FALSE;
300 } else if (strcmp(key, RECENT_KEY_TREE_VIEW_SHOW) == 0) {
301 if (strcasecmp(value, "true") == 0) {
302 recent.tree_view_show = TRUE;
305 recent.tree_view_show = FALSE;
307 } else if (strcmp(key, RECENT_KEY_BYTE_VIEW_SHOW) == 0) {
308 if (strcasecmp(value, "true") == 0) {
309 recent.byte_view_show = TRUE;
312 recent.byte_view_show = FALSE;
314 } else if (strcmp(key, RECENT_KEY_STATUSBAR_SHOW) == 0) {
315 if (strcasecmp(value, "true") == 0) {
316 recent.statusbar_show = TRUE;
319 recent.statusbar_show = FALSE;
321 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_COLORIZE) == 0) {
322 if (strcasecmp(value, "true") == 0) {
323 recent.packet_list_colorize = TRUE;
326 recent.packet_list_colorize = FALSE;
328 } else if (strcmp(key, RECENT_GUI_TIME_FORMAT) == 0) {
329 recent.gui_time_format =
330 find_index_from_string_array(value, ts_type_text, TS_RELATIVE);
331 } else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL) == 0) {
332 num = strtol(value, &p, 0);
333 if (p == value || *p != '\0')
334 return PREFS_SET_SYNTAX_ERR; /* number was bad */
335 recent.gui_zoom_level = num;
336 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
337 if (strcasecmp(value, "true") == 0) {
338 recent.gui_geometry_main_maximized = TRUE;
341 recent.gui_geometry_main_maximized = FALSE;
344 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
345 num = strtol(value, &p, 0);
346 if (p == value || *p != '\0')
347 return PREFS_SET_SYNTAX_ERR; /* number was bad */
348 recent.gui_geometry_main_x = num;
349 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) {
350 num = strtol(value, &p, 0);
351 if (p == value || *p != '\0')
352 return PREFS_SET_SYNTAX_ERR; /* number was bad */
353 recent.gui_geometry_main_y = num;
354 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) {
355 num = strtol(value, &p, 0);
356 if (p == value || *p != '\0')
357 return PREFS_SET_SYNTAX_ERR; /* number was bad */
359 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
360 recent.gui_geometry_main_width = num;
361 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {
362 num = strtol(value, &p, 0);
363 if (p == value || *p != '\0')
364 return PREFS_SET_SYNTAX_ERR; /* number was bad */
366 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
367 recent.gui_geometry_main_height = num;
368 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) {
369 num = strtol(value, &p, 0);
370 if (p == value || *p != '\0')
371 return PREFS_SET_SYNTAX_ERR; /* number was bad */
373 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
374 recent.gui_geometry_main_upper_pane = num;
375 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) {
376 num = strtol(value, &p, 0);
377 if (p == value || *p != '\0')
378 return PREFS_SET_SYNTAX_ERR; /* number was bad */
380 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
381 recent.gui_geometry_main_lower_pane = num;
382 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE) == 0) {
383 num = strtol(value, &p, 0);
384 if (p == value || *p != '\0')
385 return PREFS_SET_SYNTAX_ERR; /* number was bad */
387 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
388 recent.gui_geometry_status_pane = num;
389 } else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
390 set_last_open_dir(value);
391 } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) {
392 /* now have something like "gui.geom.main.x", split it into win and sub_key */
393 char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1];
394 char *sub_key = strchr(win, '.');
398 window_geom_recent_read_pair(win, sub_key, value);
406 /* opens the user's recent file and read it out */
408 read_recent(char **rf_path_return, int *rf_errno_return)
415 recent.main_toolbar_show = TRUE;
416 recent.filter_toolbar_show = TRUE;
417 recent.packet_list_show = TRUE;
418 recent.tree_view_show = TRUE;
419 recent.byte_view_show = TRUE;
420 recent.statusbar_show = TRUE;
421 recent.packet_list_colorize = TRUE;
422 recent.gui_time_format = TS_RELATIVE;
423 recent.gui_zoom_level = 0;
425 recent.gui_geometry_main_x = 20;
426 recent.gui_geometry_main_y = 20;
427 recent.gui_geometry_main_width = DEF_WIDTH;
428 recent.gui_geometry_main_height = DEF_HEIGHT;
429 recent.gui_geometry_main_maximized= FALSE;
431 /* pane size of zero will autodetect */
432 recent.gui_geometry_main_upper_pane = 0;
433 recent.gui_geometry_main_lower_pane = 0;
434 recent.gui_geometry_status_pane = 0;
436 /* Construct the pathname of the user's recent file. */
437 rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
439 /* Read the user's recent file, if it exists. */
440 *rf_path_return = NULL;
441 if ((rf = fopen(rf_path, "r")) != NULL) {
442 /* We succeeded in opening it; read it. */
443 read_prefs_file(rf_path, rf, read_set_recent_pair);
444 /* set dfilter combobox to have an empty line */
445 dfilter_combo_add_empty();
450 /* We failed to open it. If we failed for some reason other than
451 "it doesn't exist", return the errno and the pathname, so our
452 caller can report the error. */
453 if (errno != ENOENT) {
454 *rf_errno_return = errno;
455 *rf_path_return = rf_path;