* Recent "preference" handling routines
* Copyright 2004, Ulf Lamping <ulf.lamping@web.de>
*
- * $Id: recent.c,v 1.17 2004/06/01 17:33:37 ulfl Exp $
+ * $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include "recent.h"
#include <epan/epan.h>
#include <epan/filesystem.h>
#include "menu.h"
#include "main.h"
-#include "prefs.h"
-#include "prefs-int.h"
-#include "ui_util.h"
+#include <epan/prefs.h>
+#include <epan/prefs-int.h>
+#include "gui_utils.h"
#include "dlg_utils.h"
-
+#include "cfilter_combo_utils.h"
+#include "simple_dialog.h"
+#include "file_util.h"
#define RECENT_KEY_MAIN_TOOLBAR_SHOW "gui.toolbar_main_show"
#define RECENT_KEY_FILTER_TOOLBAR_SHOW "gui.filter_toolbar_show"
#define RECENT_KEY_TREE_VIEW_SHOW "gui.tree_view_show"
#define RECENT_KEY_BYTE_VIEW_SHOW "gui.byte_view_show"
#define RECENT_KEY_STATUSBAR_SHOW "gui.statusbar_show"
+#define RECENT_KEY_PACKET_LIST_COLORIZE "gui.packet_list_colorize"
#define RECENT_GUI_TIME_FORMAT "gui.time_format"
+#define RECENT_GUI_TIME_PRECISION "gui.time_precision"
#define RECENT_GUI_ZOOM_LEVEL "gui.zoom_level"
#define RECENT_GUI_GEOMETRY_MAIN_X "gui.geometry_main_x"
#define RECENT_GUI_GEOMETRY_MAIN_Y "gui.geometry_main_y"
#define RECENT_FILE_NAME "recent"
-
-/* #include "../menu.h" */
-extern void add_menu_recent_capture_file(gchar *file);
-
recent_settings_t recent;
-static char *ts_type_text[] =
+static const char *ts_type_text[] =
{ "RELATIVE", "ABSOLUTE", "ABSOLUTE_WITH_DATE", "DELTA", NULL };
+static const char *ts_precision_text[] =
+ { "AUTO", "SEC", "DSEC", "CSEC", "MSEC", "USEC", "NSEC", NULL };
+
/* Takes an string and a pointer to an array of strings, and a default int value.
* The array must be terminated by a NULL string. If the string is found in the array
* of strings, the index of that string in the array is returned. Otherwise, the
* default value that was passed as the third argument is returned.
*/
static int
-find_index_from_string_array(char *needle, char **haystack, int default_value)
+find_index_from_string_array(const char *needle, const char **haystack, int default_value)
{
int i = 0;
return default_value;
}
-/* Write out "recent" to the user's recent file, and return 0.
- If we got an error, stuff a pointer to the path of the recent file
- into "*pf_path_return", and return the errno. */
-int
-write_recent(char **rf_path_return)
+/* Attempt to Write out "recent" to the user's recent file.
+ If we got an error report it with a dialog box and return FALSE,
+ otherwise return TRUE. */
+gboolean
+write_recent(void)
{
+ char *pf_dir_path;
char *rf_path;
FILE *rf;
* so that duplication can be avoided with filter.c
*/
+ /* Create the directory that holds personal configuration files, if
+ necessary. */
+ if (create_persconffile_dir(&pf_dir_path) == -1) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
+ strerror(errno));
+ g_free(pf_dir_path);
+ return FALSE;
+ }
+
rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
- if ((rf = fopen(rf_path, "w")) == NULL) {
- *rf_path_return = rf_path;
- return errno;
+ if ((rf = eth_fopen(rf_path, "w")) == NULL) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Can't open recent file\n\"%s\": %s.", rf_path,
+ strerror(errno));
+ g_free(rf_path);
+ return FALSE;
}
fputs("# Recent settings file for Ethereal " VERSION ".\n"
"# This file is regenerated each time Ethereal is quit.\n"
"# So be careful, if you want to make manual changes here.\n"
"\n"
- "######## Recent capture files (latest last) ########\n"
+ "######## Recent capture files (latest last), cannot be altered through command line ########\n"
"\n", rf);
menu_recent_file_write_all(rf);
fputs("\n"
- "######## Recent display filters (latest last) ########\n"
+ "######## Recent capture filters (latest last), cannot be altered through command line ########\n"
+ "\n", rf);
+
+ cfilter_combo_recent_write_all(rf);
+
+ fputs("\n"
+ "######## Recent display filters (latest last), cannot be altered through command line ########\n"
"\n", rf);
dfilter_recent_combo_write_all(rf);
fprintf(rf, RECENT_KEY_STATUSBAR_SHOW ": %s\n",
recent.statusbar_show == TRUE ? "TRUE" : "FALSE");
+ fprintf(rf, "\n# Packet list colorize (hide).\n");
+ fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
+ fprintf(rf, RECENT_KEY_PACKET_LIST_COLORIZE ": %s\n",
+ recent.packet_list_colorize == TRUE ? "TRUE" : "FALSE");
+
fprintf(rf, "\n# Timestamp display format.\n");
fprintf(rf, "# One of: RELATIVE, ABSOLUTE, ABSOLUTE_WITH_DATE, DELTA\n");
fprintf(rf, RECENT_GUI_TIME_FORMAT ": %s\n",
ts_type_text[recent.gui_time_format]);
+ fprintf(rf, "\n# Timestamp display precision.\n");
+ fprintf(rf, "# One of: AUTO, SEC, DSEC, CSEC, MSEC, USEC, NSEC\n");
+ fprintf(rf, RECENT_GUI_TIME_PRECISION ": %s\n",
+ ts_precision_text[recent.gui_time_precision]);
+
fprintf(rf, "\n# Zoom level.\n");
fprintf(rf, "# A decimal number.\n");
fprintf(rf, RECENT_GUI_ZOOM_LEVEL ": %d\n",
recent.gui_zoom_level);
fprintf(rf, "\n# Main window geometry.\n");
- fprintf(rf, "# Decimal integers.\n");
+ fprintf(rf, "# Decimal numbers.\n");
fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X ": %d\n", recent.gui_geometry_main_x);
fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y ": %d\n", recent.gui_geometry_main_y);
fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH ": %d\n",
fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT ": %d\n",
recent.gui_geometry_main_height);
- fprintf(rf, "\n# Main window maximized (GTK2 only).\n");
+ fprintf(rf, "\n# Main window maximized (GTK2 only!).\n");
fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED ": %s\n",
recent.gui_geometry_main_maximized == TRUE ? "TRUE" : "FALSE");
- fprintf(rf, "\n# Main window panes (GTK2 only).\n");
- fprintf(rf, "# Decimal numbers.\n");
- fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
+ fprintf(rf, "\n# Main window upper (or leftmost) pane size.\n");
+ fprintf(rf, "# (GTK1: has no effect here, command line -o usage only).\n");
+ fprintf(rf, "# Decimal number.\n");
+ if (recent.gui_geometry_main_upper_pane != 0) {
+ fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
recent.gui_geometry_main_upper_pane);
- fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
+ }
+ fprintf(rf, "\n# Main window middle pane size.\n");
+ fprintf(rf, "# (GTK1: has no effect here, command line -o usage only).\n");
+ fprintf(rf, "# Decimal number.\n");
+ if (recent.gui_geometry_main_lower_pane != 0) {
+ fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
recent.gui_geometry_main_lower_pane);
- fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE ": %d\n",
+ }
+ fprintf(rf, "\n# Statusbar left pane size.\n");
+ fprintf(rf, "# (GTK1: has no effect here, command line -o usage only).\n");
+ fprintf(rf, "# Decimal number.\n");
+ if (recent.gui_geometry_status_pane != 0) {
+ fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE ": %d\n",
recent.gui_geometry_status_pane);
+ }
if (get_last_open_dir() != NULL) {
fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
fclose(rf);
/* XXX - catch I/O errors (e.g. "ran out of disk space") and return
- an error indication, or maybe write to a new preferences file and
+ an error indication, or maybe write to a new recent file and
rename that file on top of the old one only if there are not I/O
errors. */
- return 0;
+ return TRUE;
}
/* set one user's recent file key/value pair */
static int
-read_set_recent_pair(gchar *key, gchar *value)
+read_set_recent_pair_static(gchar *key, gchar *value)
{
+ long num;
+ char *p;
- if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
- add_menu_recent_capture_file(value);
- } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
- dfilter_combo_add_recent(value);
- } else if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
+ if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
if (strcasecmp(value, "true") == 0) {
recent.main_toolbar_show = TRUE;
}
else {
recent.statusbar_show = FALSE;
}
+ } else if (strcmp(key, RECENT_KEY_PACKET_LIST_COLORIZE) == 0) {
+ if (strcasecmp(value, "true") == 0) {
+ recent.packet_list_colorize = TRUE;
+ }
+ else {
+ recent.packet_list_colorize = FALSE;
+ }
} else if (strcmp(key, RECENT_GUI_TIME_FORMAT) == 0) {
recent.gui_time_format =
find_index_from_string_array(value, ts_type_text, TS_RELATIVE);
+ } else if (strcmp(key, RECENT_GUI_TIME_PRECISION) == 0) {
+ recent.gui_time_precision =
+ find_index_from_string_array(value, ts_precision_text, TS_PREC_AUTO);
} else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL) == 0) {
- recent.gui_zoom_level = strtol(value, NULL, 0);
-
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ recent.gui_zoom_level = num;
} else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
if (strcasecmp(value, "true") == 0) {
recent.gui_geometry_main_maximized = TRUE;
}
} else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
- recent.gui_geometry_main_x = strtol(value, NULL, 10);
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ recent.gui_geometry_main_x = num;
} else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) {
- recent.gui_geometry_main_y = strtol(value, NULL, 10);
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ recent.gui_geometry_main_y = num;
} else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) {
- recent.gui_geometry_main_width = strtol(value, NULL, 10);
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ if (num <= 0)
+ return PREFS_SET_SYNTAX_ERR; /* number must be positive */
+ recent.gui_geometry_main_width = num;
} else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {
- recent.gui_geometry_main_height = strtol(value, NULL, 10);
-
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ if (num <= 0)
+ return PREFS_SET_SYNTAX_ERR; /* number must be positive */
+ recent.gui_geometry_main_height = num;
} else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) {
- recent.gui_geometry_main_upper_pane = strtol(value, NULL, 10);
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ if (num <= 0)
+ return PREFS_SET_SYNTAX_ERR; /* number must be positive */
+ recent.gui_geometry_main_upper_pane = num;
+ recent.has_gui_geometry_main_upper_pane = TRUE;
} else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) {
- recent.gui_geometry_main_lower_pane = strtol(value, NULL, 10);
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ if (num <= 0)
+ return PREFS_SET_SYNTAX_ERR; /* number must be positive */
+ recent.gui_geometry_main_lower_pane = num;
+ recent.has_gui_geometry_main_lower_pane = TRUE;
} else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE) == 0) {
- recent.gui_geometry_status_pane = strtol(value, NULL, 10);
-
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ if (num <= 0)
+ return PREFS_SET_SYNTAX_ERR; /* number must be positive */
+ recent.gui_geometry_status_pane = num;
+ recent.has_gui_geometry_status_pane = TRUE;
} else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
set_last_open_dir(value);
} else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) {
}
-/* opens the user's recent file and read it out */
+/* set one user's recent file key/value pair */
+static int
+read_set_recent_pair_dynamic(gchar *key, gchar *value)
+{
+ if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
+ add_menu_recent_capture_file(value);
+ } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
+ dfilter_combo_add_recent(value);
+ } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER) == 0) {
+ cfilter_combo_add_recent(value);
+ }
+
+ return PREFS_SET_OK;
+}
+
+
+/*
+ * Given a string of the form "<recent name>:<recent value>", as might appear
+ * as an argument to a "-o" option, parse it and set the recent value in
+ * question. Return an indication of whether it succeeded or failed
+ * in some fashion.
+ */
+int
+recent_set_arg(char *prefarg)
+{
+ guchar *p, *colonp;
+ int ret;
+
+ colonp = strchr(prefarg, ':');
+ if (colonp == NULL)
+ return PREFS_SET_SYNTAX_ERR;
+
+ p = colonp;
+ *p++ = '\0';
+
+ /*
+ * Skip over any white space (there probably won't be any, but
+ * as we allow it in the preferences file, we might as well
+ * allow it here).
+ */
+ while (isspace(*p))
+ p++;
+ if (*p == '\0') {
+ /*
+ * Put the colon back, so if our caller uses, in an
+ * error message, the string they passed us, the message
+ * looks correct.
+ */
+ *colonp = ':';
+ return PREFS_SET_SYNTAX_ERR;
+ }
+
+ ret = read_set_recent_pair_static(prefarg, p);
+ *colonp = ':'; /* put the colon back */
+ return ret;
+}
+
+
+/* opens the user's recent file and read the first part */
void
-read_recent(char **rf_path_return, int *rf_errno_return)
+recent_read_static(char **rf_path_return, int *rf_errno_return)
{
char *rf_path;
FILE *rf;
recent.tree_view_show = TRUE;
recent.byte_view_show = TRUE;
recent.statusbar_show = TRUE;
+ recent.packet_list_colorize = TRUE;
recent.gui_time_format = TS_RELATIVE;
+ recent.gui_time_precision = TS_PREC_AUTO;
recent.gui_zoom_level = 0;
recent.gui_geometry_main_x = 20;
recent.gui_geometry_main_y = 20;
recent.gui_geometry_main_width = DEF_WIDTH;
- recent.gui_geometry_main_height = -1;
+ recent.gui_geometry_main_height = DEF_HEIGHT;
recent.gui_geometry_main_maximized= FALSE;
/* pane size of zero will autodetect */
recent.gui_geometry_main_lower_pane = 0;
recent.gui_geometry_status_pane = 0;
+ /* the following are only used if GTK2 is used (as GTK1 cannot read these geometry values) */
+ /* or if set through command line */
+#if GTK_MAJOR_VERSION >= 2
+ recent.has_gui_geometry_main_upper_pane = TRUE;
+ recent.has_gui_geometry_main_lower_pane = TRUE;
+ recent.has_gui_geometry_status_pane = TRUE;
+#else
+ recent.has_gui_geometry_main_upper_pane = FALSE;
+ recent.has_gui_geometry_main_lower_pane = FALSE;
+ recent.has_gui_geometry_status_pane = FALSE;
+#endif
+
+ /* Construct the pathname of the user's recent file. */
+ rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
+
+ /* Read the user's recent file, if it exists. */
+ *rf_path_return = NULL;
+ if ((rf = eth_fopen(rf_path, "r")) != NULL) {
+ /* We succeeded in opening it; read it. */
+ read_prefs_file(rf_path, rf, read_set_recent_pair_static);
+ fclose(rf);
+ g_free(rf_path);
+ rf_path = NULL;
+ } else {
+ /* We failed to open it. If we failed for some reason other than
+ "it doesn't exist", return the errno and the pathname, so our
+ caller can report the error. */
+ if (errno != ENOENT) {
+ *rf_errno_return = errno;
+ *rf_path_return = rf_path;
+ }
+ }
+}
+
+
+
+/* opens the user's recent file and read it out */
+void
+recent_read_dynamic(char **rf_path_return, int *rf_errno_return)
+{
+ char *rf_path;
+ FILE *rf;
+
+
/* Construct the pathname of the user's recent file. */
rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
/* Read the user's recent file, if it exists. */
*rf_path_return = NULL;
- if ((rf = fopen(rf_path, "r")) != NULL) {
+ if ((rf = eth_fopen(rf_path, "r")) != NULL) {
/* We succeeded in opening it; read it. */
- read_prefs_file(rf_path, rf, read_set_recent_pair);
+ read_prefs_file(rf_path, rf, read_set_recent_pair_dynamic);
/* set dfilter combobox to have an empty line */
dfilter_combo_add_empty();
fclose(rf);