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"
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 capture filters (latest last) ########\n"
129 cfilter_combo_recent_write_all(rf);
132 "######## Recent display filters (latest last) ########\n"
135 dfilter_recent_combo_write_all(rf);
137 fprintf(rf, "\n# Main Toolbar show (hide).\n");
138 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
139 fprintf(rf, RECENT_KEY_MAIN_TOOLBAR_SHOW ": %s\n",
140 recent.main_toolbar_show == TRUE ? "TRUE" : "FALSE");
142 fprintf(rf, "\n# Filter Toolbar show (hide).\n");
143 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
144 fprintf(rf, RECENT_KEY_FILTER_TOOLBAR_SHOW ": %s\n",
145 recent.filter_toolbar_show == TRUE ? "TRUE" : "FALSE");
147 fprintf(rf, "\n# Packet list show (hide).\n");
148 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
149 fprintf(rf, RECENT_KEY_PACKET_LIST_SHOW ": %s\n",
150 recent.packet_list_show == TRUE ? "TRUE" : "FALSE");
152 fprintf(rf, "\n# Tree view show (hide).\n");
153 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
154 fprintf(rf, RECENT_KEY_TREE_VIEW_SHOW ": %s\n",
155 recent.tree_view_show == TRUE ? "TRUE" : "FALSE");
157 fprintf(rf, "\n# Byte view show (hide).\n");
158 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
159 fprintf(rf, RECENT_KEY_BYTE_VIEW_SHOW ": %s\n",
160 recent.byte_view_show == TRUE ? "TRUE" : "FALSE");
162 fprintf(rf, "\n# Statusbar show (hide).\n");
163 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
164 fprintf(rf, RECENT_KEY_STATUSBAR_SHOW ": %s\n",
165 recent.statusbar_show == TRUE ? "TRUE" : "FALSE");
167 fprintf(rf, "\n# Timestamp display format.\n");
168 fprintf(rf, "# One of: RELATIVE, ABSOLUTE, ABSOLUTE_WITH_DATE, DELTA\n");
169 fprintf(rf, RECENT_GUI_TIME_FORMAT ": %s\n",
170 ts_type_text[recent.gui_time_format]);
172 fprintf(rf, "\n# Zoom level.\n");
173 fprintf(rf, "# A decimal number.\n");
174 fprintf(rf, RECENT_GUI_ZOOM_LEVEL ": %d\n",
175 recent.gui_zoom_level);
177 fprintf(rf, "\n# Main window geometry.\n");
178 fprintf(rf, "# Decimal integers.\n");
179 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X ": %d\n", recent.gui_geometry_main_x);
180 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y ": %d\n", recent.gui_geometry_main_y);
181 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH ": %d\n",
182 recent.gui_geometry_main_width);
183 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT ": %d\n",
184 recent.gui_geometry_main_height);
186 fprintf(rf, "\n# Main window maximized (GTK2 only).\n");
187 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
188 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED ": %s\n",
189 recent.gui_geometry_main_maximized == TRUE ? "TRUE" : "FALSE");
191 fprintf(rf, "\n# Main window panes (GTK2 only).\n");
192 fprintf(rf, "# Decimal numbers.\n");
193 if (recent.gui_geometry_main_upper_pane != 0) {
194 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
195 recent.gui_geometry_main_upper_pane);
197 if (recent.gui_geometry_main_lower_pane != 0) {
198 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
199 recent.gui_geometry_main_lower_pane);
201 if (recent.gui_geometry_status_pane != 0) {
202 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE ": %d\n",
203 recent.gui_geometry_status_pane);
206 if (get_last_open_dir() != NULL) {
207 fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
208 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", get_last_open_dir());
211 window_geom_recent_write_all(rf);
215 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
216 an error indication, or maybe write to a new preferences file and
217 rename that file on top of the old one only if there are not I/O
223 /* write the geometry values of a window to recent file */
225 write_recent_geom(gpointer key _U_, gpointer value, gpointer rf)
227 window_geometry_t *geom = value;
229 fprintf(rf, "\n# Geometry and maximized state (GTK2 only) of %s window.\n", geom->key);
230 fprintf(rf, "# Decimal integers.\n");
231 fprintf(rf, RECENT_GUI_GEOMETRY "%s.x: %d\n", geom->key, geom->x);
232 fprintf(rf, RECENT_GUI_GEOMETRY "%s.y: %d\n", geom->key, geom->y);
233 fprintf(rf, RECENT_GUI_GEOMETRY "%s.width: %d\n", geom->key,
235 fprintf(rf, RECENT_GUI_GEOMETRY "%s.height: %d\n", geom->key,
238 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
239 fprintf(rf, RECENT_GUI_GEOMETRY "%s.maximized: %s\n", geom->key,
240 geom->maximized == TRUE ? "TRUE" : "FALSE");
245 /* set one user's recent file key/value pair */
247 read_set_recent_pair(gchar *key, gchar *value)
252 if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
253 add_menu_recent_capture_file(value);
254 } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
255 dfilter_combo_add_recent(value);
256 } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER) == 0) {
257 cfilter_combo_add_recent(value);
258 } else if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
259 if (strcasecmp(value, "true") == 0) {
260 recent.main_toolbar_show = TRUE;
263 recent.main_toolbar_show = FALSE;
265 } else if (strcmp(key, RECENT_KEY_FILTER_TOOLBAR_SHOW) == 0) {
266 if (strcasecmp(value, "true") == 0) {
267 recent.filter_toolbar_show = TRUE;
270 recent.filter_toolbar_show = FALSE;
272 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_SHOW) == 0) {
273 if (strcasecmp(value, "true") == 0) {
274 recent.packet_list_show = TRUE;
277 recent.packet_list_show = FALSE;
279 } else if (strcmp(key, RECENT_KEY_TREE_VIEW_SHOW) == 0) {
280 if (strcasecmp(value, "true") == 0) {
281 recent.tree_view_show = TRUE;
284 recent.tree_view_show = FALSE;
286 } else if (strcmp(key, RECENT_KEY_BYTE_VIEW_SHOW) == 0) {
287 if (strcasecmp(value, "true") == 0) {
288 recent.byte_view_show = TRUE;
291 recent.byte_view_show = FALSE;
293 } else if (strcmp(key, RECENT_KEY_STATUSBAR_SHOW) == 0) {
294 if (strcasecmp(value, "true") == 0) {
295 recent.statusbar_show = TRUE;
298 recent.statusbar_show = FALSE;
300 } else if (strcmp(key, RECENT_GUI_TIME_FORMAT) == 0) {
301 recent.gui_time_format =
302 find_index_from_string_array(value, ts_type_text, TS_RELATIVE);
303 } else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL) == 0) {
304 num = strtol(value, &p, 0);
305 if (p == value || *p != '\0')
306 return PREFS_SET_SYNTAX_ERR; /* number was bad */
307 recent.gui_zoom_level = num;
308 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
309 if (strcasecmp(value, "true") == 0) {
310 recent.gui_geometry_main_maximized = TRUE;
313 recent.gui_geometry_main_maximized = FALSE;
316 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
317 num = strtol(value, &p, 0);
318 if (p == value || *p != '\0')
319 return PREFS_SET_SYNTAX_ERR; /* number was bad */
320 recent.gui_geometry_main_x = num;
321 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) {
322 num = strtol(value, &p, 0);
323 if (p == value || *p != '\0')
324 return PREFS_SET_SYNTAX_ERR; /* number was bad */
325 recent.gui_geometry_main_y = num;
326 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) {
327 num = strtol(value, &p, 0);
328 if (p == value || *p != '\0')
329 return PREFS_SET_SYNTAX_ERR; /* number was bad */
331 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
332 recent.gui_geometry_main_width = num;
333 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {
334 num = strtol(value, &p, 0);
335 if (p == value || *p != '\0')
336 return PREFS_SET_SYNTAX_ERR; /* number was bad */
338 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
339 recent.gui_geometry_main_height = num;
340 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) {
341 num = strtol(value, &p, 0);
342 if (p == value || *p != '\0')
343 return PREFS_SET_SYNTAX_ERR; /* number was bad */
345 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
346 recent.gui_geometry_main_upper_pane = num;
347 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) {
348 num = strtol(value, &p, 0);
349 if (p == value || *p != '\0')
350 return PREFS_SET_SYNTAX_ERR; /* number was bad */
352 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
353 recent.gui_geometry_main_lower_pane = num;
354 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE) == 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_status_pane = num;
361 } else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
362 set_last_open_dir(value);
363 } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) {
364 /* now have something like "gui.geom.main.x", split it into win and sub_key */
365 char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1];
366 char *sub_key = strchr(win, '.');
370 window_geom_recent_read_pair(win, sub_key, value);
378 /* opens the user's recent file and read it out */
380 read_recent(char **rf_path_return, int *rf_errno_return)
387 recent.main_toolbar_show = TRUE;
388 recent.filter_toolbar_show = TRUE;
389 recent.packet_list_show = TRUE;
390 recent.tree_view_show = TRUE;
391 recent.byte_view_show = TRUE;
392 recent.statusbar_show = TRUE;
393 recent.gui_time_format = TS_RELATIVE;
394 recent.gui_zoom_level = 0;
396 recent.gui_geometry_main_x = 20;
397 recent.gui_geometry_main_y = 20;
398 recent.gui_geometry_main_width = DEF_WIDTH;
399 recent.gui_geometry_main_height = DEF_HEIGHT;
400 recent.gui_geometry_main_maximized= FALSE;
402 /* pane size of zero will autodetect */
403 recent.gui_geometry_main_upper_pane = 0;
404 recent.gui_geometry_main_lower_pane = 0;
405 recent.gui_geometry_status_pane = 0;
407 /* Construct the pathname of the user's recent file. */
408 rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
410 /* Read the user's recent file, if it exists. */
411 *rf_path_return = NULL;
412 if ((rf = fopen(rf_path, "r")) != NULL) {
413 /* We succeeded in opening it; read it. */
414 read_prefs_file(rf_path, rf, read_set_recent_pair);
415 /* set dfilter combobox to have an empty line */
416 dfilter_combo_add_empty();
421 /* We failed to open it. If we failed for some reason other than
422 "it doesn't exist", return the errno and the pathname, so our
423 caller can report the error. */
424 if (errno != ENOENT) {
425 *rf_errno_return = errno;
426 *rf_path_return = rf_path;