diff options
Diffstat (limited to 'ui/recent.c')
-rw-r--r-- | ui/recent.c | 773 |
1 files changed, 449 insertions, 324 deletions
diff --git a/ui/recent.c b/ui/recent.c index 1906bfba..d019f0f3 100644 --- a/ui/recent.c +++ b/ui/recent.c @@ -57,11 +57,14 @@ #define RECENT_GUI_GEOMETRY_MAIN_WIDTH "gui.geometry_main_width" #define RECENT_GUI_GEOMETRY_MAIN_HEIGHT "gui.geometry_main_height" #define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized" +#define RECENT_GUI_GEOMETRY_MAIN "gui.geometry_main" #define RECENT_GUI_GEOMETRY_LEFTALIGN_ACTIONS "gui.geometry_leftalign_actions" #define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane" #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane" -#define RECENT_GUI_GEOMETRY_WLAN_STATS_PANE "gui.geometry_status_wlan_stats_pane" +#define RECENT_GUI_GEOMETRY_MAIN_MASTER_SPLIT "gui.geometry_main_master_split" +#define RECENT_GUI_GEOMETRY_MAIN_EXTRA_SPLIT "gui.geometry_main_extra_split" #define RECENT_LAST_USED_PROFILE "gui.last_used_profile" +#define RECENT_PROFILE_SWITCH_CHECK_COUNT "gui.profile_switch_check_count" #define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir" #define RECENT_GUI_CONVERSATION_TABS "gui.conversation_tabs" #define RECENT_GUI_CONVERSATION_TABS_COLUMNS "gui.conversation_tabs_columns" @@ -74,8 +77,11 @@ #define RECENT_GUI_SEARCH_IN "gui.search_in" #define RECENT_GUI_SEARCH_CHAR_SET "gui.search_char_set" #define RECENT_GUI_SEARCH_CASE_SENSITIVE "gui.search_case_sensitive" +#define RECENT_GUI_SEARCH_REVERSE_DIR "gui.search_reverse_dir" +#define RECENT_GUI_SEARCH_MULTIPLE_OCCURS "gui.search_multiple_occurs" #define RECENT_GUI_SEARCH_TYPE "gui.search_type" #define RECENT_GUI_FOLLOW_SHOW "gui.follow_show" +#define RECENT_GUI_FOLLOW_DELTA "gui.follow_delta" #define RECENT_GUI_SHOW_BYTES_DECODE "gui.show_bytes_decode" #define RECENT_GUI_SHOW_BYTES_SHOW "gui.show_bytes_show" @@ -184,6 +190,13 @@ static const value_string bytes_show_values[] = { { 0, NULL } }; +static const value_string follow_delta_values[] = { + { FOLLOW_DELTA_NONE, "NONE" }, + { FOLLOW_DELTA_TURN, "TURN" }, + { FOLLOW_DELTA_ALL, "ALL" }, + { 0, NULL } +}; + static const value_string show_bytes_decode_values[] = { { DecodeAsNone, "NONE" }, { DecodeAsBASE64, "BASE64" }, @@ -196,18 +209,16 @@ static const value_string show_bytes_decode_values[] = { }; static void -free_col_width_data(gpointer data, gpointer user_data _U_) +free_col_width_data(void *data) { col_width_data *cfmt = (col_width_data *)data; - g_free(cfmt->cfield); g_free(cfmt); } -static void -free_col_width_info(recent_settings_t *rs) +void +recent_free_column_width_info(recent_settings_t *rs) { - g_list_foreach(rs->col_width_list, free_col_width_data, NULL); - g_list_free(rs->col_width_list); + g_list_free_full(rs->col_width_list, free_col_width_data); rs->col_width_list = NULL; } @@ -218,7 +229,7 @@ free_col_width_info(recent_settings_t *rs) * @param rfh recent file handle (FILE) */ static void -write_recent_geom(gpointer key _U_, gpointer value, gpointer rfh) +write_recent_geom(void *key _U_, void *value, void *rfh) { window_geometry_t *geom = (window_geometry_t *)value; FILE *rf = (FILE *)rfh; @@ -232,33 +243,40 @@ write_recent_geom(gpointer key _U_, gpointer value, gpointer rfh) fprintf(rf, RECENT_GUI_GEOMETRY "%s.height: %d\n", geom->key, geom->height); - fprintf(rf, "# TRUE or FALSE (case-insensitive).\n"); + fprintf(rf, "# true or false (case-insensitive).\n"); fprintf(rf, RECENT_GUI_GEOMETRY "%s.maximized: %s\n", geom->key, - geom->maximized == TRUE ? "TRUE" : "FALSE"); + geom->maximized == true ? "true" : "false"); + fprintf(rf, "# Qt Geometry State (hex byte string).\n"); + fprintf(rf, RECENT_GUI_GEOMETRY "%s.qt_geometry: %s\n", geom->key, + geom->qt_geom); } /* the geometry hashtable for all known window classes, * the window name is the key, and the geometry struct is the value */ -static GHashTable *window_geom_hash = NULL; +static GHashTable *window_geom_hash; + +static GHashTable *window_splitter_hash; + +void +window_geom_free(void *data) +{ + window_geometry_t *geom = (window_geometry_t*)data; + g_free(geom->key); + g_free(geom->qt_geom); + g_free(geom); +} /* save the window and its current geometry into the geometry hashtable */ void -window_geom_save(const gchar *name, window_geometry_t *geom) +window_geom_save(const char *name, window_geometry_t *geom) { - gchar *key; + char *key; window_geometry_t *work; /* init hashtable, if not already done */ if (!window_geom_hash) { - window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal); - } - /* if we have an old one, remove and free it first */ - work = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name); - if (work) { - g_hash_table_remove(window_geom_hash, name); - g_free(work->key); - g_free(work); + window_geom_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, window_geom_free); } /* g_malloc and insert the new one */ @@ -266,39 +284,64 @@ window_geom_save(const gchar *name, window_geometry_t *geom) *work = *geom; key = g_strdup(name); work->key = key; - g_hash_table_insert(window_geom_hash, key, work); + g_hash_table_replace(window_geom_hash, key, work); } /* load the desired geometry for this window from the geometry hashtable */ -gboolean -window_geom_load(const gchar *name, +bool +window_geom_load(const char *name, window_geometry_t *geom) { window_geometry_t *p; /* init hashtable, if not already done */ if (!window_geom_hash) { - window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal); + window_geom_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, window_geom_free); } p = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name); if (p) { *geom = *p; - return TRUE; + return true; } else { - return FALSE; + return false; + } +} + +/* save the window and its splitter state into the splitter hashtable */ +void +window_splitter_save(const char *name, const char *splitter_state) +{ + /* init hashtable, if not already done */ + if (!window_splitter_hash) { + window_splitter_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); } + + g_hash_table_replace(window_splitter_hash, g_strdup(name), g_strdup(splitter_state)); } +/* save the window and its splitter state into the geometry hashtable */ +const char* +window_splitter_load(const char *name) +{ + /* init hashtable, if not already done */ + if (!window_splitter_hash) { + return NULL; + } + + return g_hash_table_lookup(window_splitter_hash, name); +} + + /* parse values of particular types */ static void -parse_recent_boolean(const gchar *val_str, gboolean *valuep) +parse_recent_boolean(const char *val_str, bool *valuep) { if (g_ascii_strcasecmp(val_str, "true") == 0) { - *valuep = TRUE; + *valuep = true; } else { - *valuep = FALSE; + *valuep = false; } } @@ -315,33 +358,41 @@ window_geom_recent_read_pair(const char *name, { window_geometry_t geom; + if (strcmp(key, "splitter") == 0) { + window_splitter_save(name, value); + return; + } + /* find window geometry maybe already in hashtable */ if (!window_geom_load(name, &geom)) { /* not in table, init geom with "basic" values */ geom.key = NULL; /* Will be set in window_geom_save() */ - geom.set_pos = FALSE; + geom.set_pos = false; geom.x = -1; geom.y = -1; - geom.set_size = FALSE; + geom.set_size = false; geom.width = -1; geom.height = -1; + geom.qt_geom = NULL; } if (strcmp(key, "x") == 0) { - geom.x = (gint)strtol(value, NULL, 10); - geom.set_pos = TRUE; + geom.x = (int)strtol(value, NULL, 10); + geom.set_pos = true; } else if (strcmp(key, "y") == 0) { - geom.y = (gint)strtol(value, NULL, 10); - geom.set_pos = TRUE; + geom.y = (int)strtol(value, NULL, 10); + geom.set_pos = true; } else if (strcmp(key, "width") == 0) { - geom.width = (gint)strtol(value, NULL, 10); - geom.set_size = TRUE; + geom.width = (int)strtol(value, NULL, 10); + geom.set_size = true; } else if (strcmp(key, "height") == 0) { - geom.height = (gint)strtol(value, NULL, 10); - geom.set_size = TRUE; + geom.height = (int)strtol(value, NULL, 10); + geom.set_size = true; } else if (strcmp(key, "maximized") == 0) { parse_recent_boolean(value, &geom.maximized); - geom.set_maximized = TRUE; + geom.set_maximized = true; + } else if (strcmp(key, "qt_geometry") == 0) { + geom.qt_geom = g_strdup(value); } else { /* * Silently ignore the bogus key. We shouldn't abort here, @@ -366,12 +417,35 @@ window_geom_recent_write_all(FILE *rf) { /* init hashtable, if not already done */ if (!window_geom_hash) { - window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal); + window_geom_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, window_geom_free); } g_hash_table_foreach(window_geom_hash, write_recent_geom, rf); } +/** Write all known window splitter states to the recent file. + * + * @param rf recent file handle from caller + */ +static void +window_splitter_recent_write_all(FILE *rf) +{ + /* init hashtable, if not already done */ + if (!window_splitter_hash) { + return; + } + + GHashTableIter iter; + void *key, *value; + g_hash_table_iter_init(&iter, window_splitter_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + fprintf(rf, "\n# Splitter state of %s window.\n", (char*)key); + fprintf(rf, "# Qt Splitter state (hex byte string).\n"); + fprintf(rf, RECENT_GUI_GEOMETRY "%s.splitter: %s\n", (char*)key, + (char*)value); + } +} + /* Global list of recent capture filters. */ static GList *recent_cfilter_list; @@ -386,7 +460,7 @@ static GHashTable *per_interface_cfilter_lists_hash; * before the pref, so don't truncate the list when reading * (see the similar #16782 for the recent files.) */ -static guint cfilter_combo_max_recent = 20; +static unsigned cfilter_combo_max_recent = 20; /** * Returns a list of recent capture filters. @@ -394,7 +468,7 @@ static guint cfilter_combo_max_recent = 20; * @param ifname interface name; NULL refers to the global list. */ GList * -recent_get_cfilter_list(const gchar *ifname) +recent_get_cfilter_list(const char *ifname) { if (ifname == NULL) return recent_cfilter_list; @@ -413,11 +487,11 @@ recent_get_cfilter_list(const gchar *ifname) * @param s text of capture filter */ void -recent_add_cfilter(const gchar *ifname, const gchar *s) +recent_add_cfilter(const char *ifname, const char *s) { GList *cfilter_list; GList *li; - gchar *li_filter, *newfilter = NULL; + char *li_filter, *newfilter = NULL; /* Don't add empty filters to the list. */ if (s[0] == '\0') @@ -460,7 +534,13 @@ recent_add_cfilter(const gchar *ifname, const gchar *s) } #ifdef HAVE_PCAP_REMOTE -static GHashTable *remote_host_list=NULL; +/* XXX: use a preference for this setting! */ +/* N.B.: If we use a pref, we will read the recent_common file + * before the pref, so don't truncate the list when reading + * (see the similar #16782 for the recent files.) + */ +static unsigned remote_host_max_recent = 20; +static GList *remote_host_list; int recent_get_remote_host_list_size(void) { @@ -468,40 +548,62 @@ int recent_get_remote_host_list_size(void) /* No entries exist. */ return 0; } - return g_hash_table_size (remote_host_list); + return g_list_length(remote_host_list); } -void recent_add_remote_host(gchar *host, struct remote_host *rh) +static void +free_remote_host(void *value) { - if (remote_host_list == NULL) { - remote_host_list = g_hash_table_new (g_str_hash, g_str_equal); - } - g_hash_table_insert (remote_host_list, g_strdup(host), rh); + struct remote_host* rh = (struct remote_host*)value; + + g_free(rh->r_host); + g_free(rh->remote_port); + g_free(rh->auth_username); + g_free(rh->auth_password); + } -static gboolean -free_remote_host (gpointer key _U_, gpointer value, gpointer user _U_) +static int +remote_host_compare(const void *a, const void *b) { - struct remote_host *rh = (struct remote_host *) value; + const struct remote_host* rh_a = (const struct remote_host*)a; + const struct remote_host* rh_b = (const struct remote_host*)b; - g_free (rh->r_host); - g_free (rh->remote_port); - g_free (rh->auth_username); - g_free (rh->auth_password); + /* We assume only one entry per host (the GUI assumes that too.) */ + return g_strcmp0(rh_a->r_host, rh_b->r_host); +} - return TRUE; +static void +remote_host_reverse(void) +{ + if (remote_host_list) { + remote_host_list = g_list_reverse(remote_host_list); + } +} + +void recent_add_remote_host(char *host _U_, struct remote_host *rh) +{ + GList* li = NULL; + if (remote_host_list) { + li = g_list_find_custom(remote_host_list, rh, remote_host_compare); + if (li != NULL) { + free_remote_host(li->data); + remote_host_list = g_list_delete_link(remote_host_list, li); + } + } + remote_host_list = g_list_prepend(remote_host_list, rh); } void -recent_remote_host_list_foreach(GHFunc func, gpointer user_data) +recent_remote_host_list_foreach(GFunc func, void *user_data) { if (remote_host_list != NULL) { - g_hash_table_foreach(remote_host_list, func, user_data); + g_list_foreach(remote_host_list, func, user_data); } } static void -recent_print_remote_host (gpointer key _U_, gpointer value, gpointer user) +recent_print_remote_host(void *value, void *user) { FILE *rf = (FILE *)user; struct remote_host_info *ri = (struct remote_host_info *)value; @@ -517,28 +619,35 @@ recent_print_remote_host (gpointer key _U_, gpointer value, gpointer user) static void capture_remote_combo_recent_write_all(FILE *rf) { - if (remote_host_list && g_hash_table_size (remote_host_list) > 0) { - /* Write all remote interfaces to the recent file */ - g_hash_table_foreach (remote_host_list, recent_print_remote_host, rf); + unsigned max_count = 0; + GList *li = g_list_first(remote_host_list); + + /* write all non empty remote capture hosts to the recent file (until max count) */ + while (li && (max_count++ <= remote_host_max_recent)) { + recent_print_remote_host(li->data, rf); + li = li->next; } } void recent_free_remote_host_list(void) { - g_hash_table_foreach_remove(remote_host_list, free_remote_host, NULL); + g_list_free_full(remote_host_list, free_remote_host); + remote_host_list = NULL; } struct remote_host * -recent_get_remote_host(const gchar *host) +recent_get_remote_host(const char *host) { if (host == NULL) return NULL; - if (remote_host_list == NULL) { - /* No such host exist. */ - return NULL; + for (GList* li = g_list_first(remote_host_list); li != NULL; li = li->next) { + struct remote_host *rh = (struct remote_host*)li->data; + if (g_strcmp0(host, rh->r_host) == 0) { + return rh; + } } - return (struct remote_host *)g_hash_table_lookup(remote_host_list, host); + return NULL; } /** @@ -547,8 +656,8 @@ recent_get_remote_host(const gchar *host) * @param s String to be filled from the 'recent' file. * @return True, if the list was written successfully, False otherwise. */ -static gboolean -capture_remote_combo_add_recent(const gchar *s) +static bool +capture_remote_combo_add_recent(const char *s) { GList *vals = prefs_get_string_list (s); GList *valp = vals; @@ -557,21 +666,22 @@ capture_remote_combo_add_recent(const gchar *s) struct remote_host *rh; if (valp == NULL) - return FALSE; + return false; - if (remote_host_list == NULL) { - remote_host_list = g_hash_table_new (g_str_hash, g_str_equal); + /* First value is the host */ + if (recent_get_remote_host(valp->data)) { + /* Don't add it, it's already in the list (shouldn't happen). */ + return false; // Should this be true or false? } - - rh =(struct remote_host *) g_malloc (sizeof (*rh)); + rh = (struct remote_host *) g_malloc (sizeof (*rh)); /* First value is the host */ - rh->r_host = (gchar *)g_strdup ((const gchar *)valp->data); + rh->r_host = (char *)g_strdup ((const char *)valp->data); if (strlen(rh->r_host) == 0) { /* Empty remote host */ g_free(rh->r_host); g_free(rh); - return FALSE; + return false; } rh->auth_type = CAPTURE_AUTH_NULL; valp = valp->next; @@ -580,9 +690,9 @@ capture_remote_combo_add_recent(const gchar *s) /* Found value 2, this is the port number */ if (!strcmp((const char*)valp->data, "0")) { /* Port 0 isn't valid, so leave port blank */ - rh->remote_port = (gchar *)g_strdup (""); + rh->remote_port = (char *)g_strdup (""); } else { - rh->remote_port = (gchar *)g_strdup ((const gchar *)valp->data); + rh->remote_port = (char *)g_strdup ((const char *)valp->data); } valp = valp->next; } else { @@ -592,7 +702,7 @@ capture_remote_combo_add_recent(const gchar *s) if (valp) { /* Found value 3, this is the authentication type */ - auth_type = (capture_auth)strtol((const gchar *)valp->data, &p, 0); + auth_type = (capture_auth)strtol((const char *)valp->data, &p, 0); if (p != valp->data && *p == '\0') { rh->auth_type = auth_type; } @@ -604,16 +714,15 @@ capture_remote_combo_add_recent(const gchar *s) prefs_clear_string_list(vals); - g_hash_table_insert (remote_host_list, g_strdup(rh->r_host), rh); - - return TRUE; + remote_host_list = g_list_prepend(remote_host_list, rh); + return true; } #endif static void -cfilter_recent_write_all_list(FILE *rf, const gchar *ifname, GList *cfilter_list) +cfilter_recent_write_all_list(FILE *rf, const char *ifname, GList *cfilter_list) { - guint max_count = 0; + unsigned max_count = 0; GList *li; /* write all non empty capture filter strings to the recent file (until max count) */ @@ -630,9 +739,9 @@ cfilter_recent_write_all_list(FILE *rf, const gchar *ifname, GList *cfilter_list } static void -cfilter_recent_write_all_hash_callback(gpointer key, gpointer value, gpointer user_data) +cfilter_recent_write_all_hash_callback(void *key, void *value, void *user_data) { - cfilter_recent_write_all_list((FILE *)user_data, (const gchar *)key, (GList *)value); + cfilter_recent_write_all_list((FILE *)user_data, (const char *)key, (GList *)value); } /** Write all capture filter values to the recent file. @@ -647,7 +756,7 @@ cfilter_recent_write_all(FILE *rf) /* Write out all the per-interface lists. */ if (per_interface_cfilter_lists_hash != NULL) { - g_hash_table_foreach(per_interface_cfilter_lists_hash, cfilter_recent_write_all_hash_callback, (gpointer)rf); + g_hash_table_foreach(per_interface_cfilter_lists_hash, cfilter_recent_write_all_hash_callback, (void *)rf); } } @@ -664,7 +773,7 @@ cfilter_recent_reverse_all(void) /* Reverse all the per-interface lists. */ if (per_interface_cfilter_lists_hash != NULL) { GHashTableIter iter; - gpointer key, value; + void *key, *value; g_hash_table_iter_init(&iter, per_interface_cfilter_lists_hash); GList *li; while (g_hash_table_iter_next(&iter, &key, &value)) { @@ -681,20 +790,20 @@ cfilter_recent_reverse_all(void) /* Write out recent settings of particular types. */ static void write_recent_boolean(FILE *rf, const char *description, const char *name, - gboolean value) + bool value) { fprintf(rf, "\n# %s.\n", description); - fprintf(rf, "# TRUE or FALSE (case-insensitive).\n"); - fprintf(rf, "%s: %s\n", name, value == TRUE ? "TRUE" : "FALSE"); + fprintf(rf, "# true or false (case-insensitive).\n"); + fprintf(rf, "%s: %s\n", name, value == true ? "true" : "false"); } static void write_recent_enum(FILE *rf, const char *description, const char *name, - const value_string *values, guint value) + const value_string *values, unsigned value) { const char *if_invalid = NULL; const value_string *valp; - const gchar *str_value; + const char *str_value; fprintf(rf, "\n# %s.\n", description); fprintf(rf, "# One of: "); @@ -716,9 +825,9 @@ write_recent_enum(FILE *rf, const char *description, const char *name, } /* Attempt to write out "recent common" to the user's recent_common file. - If we got an error report it with a dialog box and return FALSE, - otherwise return TRUE. */ -gboolean + If we got an error report it with a dialog box and return false, + otherwise return true. */ +bool write_recent(void) { char *pf_dir_path; @@ -739,16 +848,16 @@ write_recent(void) "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path, g_strerror(errno)); g_free(pf_dir_path); - return FALSE; + return false; } - rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE); + rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, false); if ((rf = ws_fopen(rf_path, "w")) == NULL) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Can't open recent file\n\"%s\": %s.", rf_path, g_strerror(errno)); g_free(rf_path); - return FALSE; + return false; } g_free(rf_path); @@ -779,7 +888,7 @@ write_recent(void) #ifdef HAVE_PCAP_REMOTE fputs("\n" - "######## Recent remote hosts, cannot be altered through command line ########\n" + "######## Recent remote hosts (latest first), cannot be altered through command line ########\n" "\n", rf); capture_remote_combo_recent_write_all(rf); @@ -798,6 +907,13 @@ write_recent(void) RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED, recent.gui_geometry_main_maximized); + if (recent.gui_geometry_main != NULL) { + fprintf(rf, "\n# Main window geometry state.\n"); + fprintf(rf, "# Hex byte string.\n"); + fprintf(rf, RECENT_GUI_GEOMETRY_MAIN ": %s\n", + recent.gui_geometry_main); + } + write_recent_boolean(rf, "Leftalign Action Buttons", RECENT_GUI_GEOMETRY_LEFTALIGN_ACTIONS, recent.gui_geometry_leftalign_actions); @@ -805,10 +921,11 @@ write_recent(void) fprintf(rf, "\n# Last used Configuration Profile.\n"); fprintf(rf, RECENT_LAST_USED_PROFILE ": %s\n", get_profile_name()); - fprintf(rf, "\n# WLAN statistics upper pane size.\n"); - fprintf(rf, "# Decimal number.\n"); - fprintf(rf, RECENT_GUI_GEOMETRY_WLAN_STATS_PANE ": %d\n", - recent.gui_geometry_wlan_stats_pane); + fprintf(rf, "\n# Number of packets or events to check for automatic profile switching.\n"); + fprintf(rf, "# Decimal number. Zero disables switching.\n"); + const char * def_prefix = recent.gui_profile_switch_check_count == 1000 ? "#" : ""; + fprintf(rf, "%s" RECENT_PROFILE_SWITCH_CHECK_COUNT ": %d\n", def_prefix, + recent.gui_profile_switch_check_count); write_recent_boolean(rf, "Warn if running with elevated permissions (e.g. as root)", RECENT_KEY_PRIVS_WARN_IF_ELEVATED, @@ -825,6 +942,12 @@ write_recent(void) write_recent_boolean(rf, "Find packet case sensitive search", RECENT_GUI_SEARCH_CASE_SENSITIVE, recent.gui_search_case_sensitive); + write_recent_boolean(rf, "Find packet search reverse direction", + RECENT_GUI_SEARCH_REVERSE_DIR, + recent.gui_search_reverse_dir); + write_recent_boolean(rf, "Find packet search multiple occurrences", + RECENT_GUI_SEARCH_MULTIPLE_OCCURS, + recent.gui_search_multiple_occurs); write_recent_enum(rf, "Find packet search type", RECENT_GUI_SEARCH_TYPE, search_type_values, recent.gui_search_type); @@ -842,14 +965,14 @@ write_recent(void) 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 TRUE; + return true; } /* Attempt to Write out profile "recent" to the user's profile recent file. - If we got an error report it with a dialog box and return FALSE, - otherwise return TRUE. */ -gboolean + If we got an error report it with a dialog box and return false, + otherwise return true. */ +bool write_profile_recent(void) { char *pf_dir_path; @@ -870,16 +993,16 @@ write_profile_recent(void) "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path, g_strerror(errno)); g_free(pf_dir_path); - return FALSE; + return false; } - rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE); + rf_path = get_persconffile_path(RECENT_FILE_NAME, true); if ((rf = ws_fopen(rf_path, "w")) == NULL) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Can't open recent file\n\"%s\": %s.", rf_path, g_strerror(errno)); g_free(rf_path); - return FALSE; + return false; } g_free(rf_path); @@ -953,7 +1076,7 @@ write_profile_recent(void) { const char *if_invalid = NULL; const value_string *valp; - const gchar *str_value; + const char *str_value; fprintf(rf, "\n# %s.\n", "Timestamp display precision"); fprintf(rf, "# One of: "); @@ -1008,6 +1131,10 @@ write_profile_recent(void) RECENT_GUI_FOLLOW_SHOW, bytes_show_values, recent.gui_follow_show); + write_recent_enum(rf, "Follow stream delta times", + RECENT_GUI_FOLLOW_DELTA, follow_delta_values, + recent.gui_follow_delta); + write_recent_enum(rf, "Show packet bytes decode as", RECENT_GUI_SHOW_BYTES_DECODE, show_bytes_decode_values, recent.gui_show_bytes_decode); @@ -1029,6 +1156,22 @@ write_profile_recent(void) recent.gui_geometry_main_lower_pane); } + if (recent.gui_geometry_main_master_split != NULL) { + fprintf(rf, "\n# Main window master splitter state.\n"); + fprintf(rf, "# Hex byte string.\n"); + fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_MASTER_SPLIT ": %s\n", + recent.gui_geometry_main_master_split); + } + + if (recent.gui_geometry_main_extra_split != NULL) { + fprintf(rf, "\n# Main window extra splitter state.\n"); + fprintf(rf, "# Hex byte string.\n"); + fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_EXTRA_SPLIT ": %s\n", + recent.gui_geometry_main_extra_split); + } + + window_splitter_recent_write_all(rf); + fprintf(rf, "\n# Packet list column pixel widths.\n"); fprintf(rf, "# Each pair of strings consists of a column format and its pixel width.\n"); packet_list_recent_write_all(rf); @@ -1084,14 +1227,14 @@ write_profile_recent(void) 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 TRUE; + return true; } /* set one user's recent common file key/value pair */ static prefs_set_pref_e -read_set_recent_common_pair_static(gchar *key, const gchar *value, +read_set_recent_common_pair_static(char *key, const char *value, void *private_data _U_, - gboolean return_range_errors _U_) + bool return_range_errors _U_) { long num; char *p; @@ -1104,37 +1247,40 @@ read_set_recent_common_pair_static(gchar *key, const gchar *value, num = strtol(value, &p, 0); if (p == value || *p != '\0') return PREFS_SET_SYNTAX_ERR; /* number was bad */ - recent.gui_geometry_main_x = (gint)num; + recent.gui_geometry_main_x = (int)num; } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) { num = strtol(value, &p, 0); if (p == value || *p != '\0') return PREFS_SET_SYNTAX_ERR; /* number was bad */ - recent.gui_geometry_main_y = (gint)num; + recent.gui_geometry_main_y = (int)num; } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) { 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 = (gint)num; + recent.gui_geometry_main_width = (int)num; } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) { 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 = (gint)num; + recent.gui_geometry_main_height = (int)num; + } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN) == 0) { + g_free(recent.gui_geometry_main); + recent.gui_geometry_main = g_strdup(value); } else if (strcmp(key, RECENT_LAST_USED_PROFILE) == 0) { - if ((strcmp(value, DEFAULT_PROFILE) != 0) && profile_exists (value, FALSE)) { + if ((strcmp(value, DEFAULT_PROFILE) != 0) && profile_exists (value, false)) { set_profile_name (value); } - } else if (strcmp(key, RECENT_GUI_GEOMETRY_WLAN_STATS_PANE) == 0) { + } else if (strcmp(key, RECENT_PROFILE_SWITCH_CHECK_COUNT) == 0) { 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_wlan_stats_pane = (gint)num; + recent.gui_profile_switch_check_count = (int)num; } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) { /* now have something like "gui.geom.main.x", split it into win and sub_key */ char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1]; @@ -1154,6 +1300,10 @@ read_set_recent_common_pair_static(gchar *key, const gchar *value, recent.gui_search_char_set = (search_char_set_type)str_to_val(value, search_char_set_values, SEARCH_CHAR_SET_NARROW_AND_WIDE); } else if (strcmp(key, RECENT_GUI_SEARCH_CASE_SENSITIVE) == 0) { parse_recent_boolean(value, &recent.gui_search_case_sensitive); + } else if (strcmp(key, RECENT_GUI_SEARCH_REVERSE_DIR) == 0) { + parse_recent_boolean(value, &recent.gui_search_reverse_dir); + } else if (strcmp(key, RECENT_GUI_SEARCH_MULTIPLE_OCCURS) == 0) { + parse_recent_boolean(value, &recent.gui_search_multiple_occurs); } else if (strcmp(key, RECENT_GUI_SEARCH_TYPE) == 0) { recent.gui_search_type = (search_type_type)str_to_val(value, search_type_values, SEARCH_TYPE_DISPLAY_FILTER); } else if (strcmp(key, RECENT_GUI_CUSTOM_COLORS) == 0) { @@ -1165,17 +1315,15 @@ read_set_recent_common_pair_static(gchar *key, const gchar *value, /* set one user's recent file key/value pair */ static prefs_set_pref_e -read_set_recent_pair_static(gchar *key, const gchar *value, +read_set_recent_pair_static(char *key, const char *value, void *private_data _U_, - gboolean return_range_errors _U_) + bool return_range_errors _U_) { long num; - gint32 num_int32; + int32_t num_int32; char *p; GList *col_l, *col_l_elt; col_width_data *cfmt; - const gchar *cust_format = col_format_to_string(COL_CUSTOM); - int cust_format_len = (int) strlen(cust_format); if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) { parse_recent_boolean(value, &recent.main_toolbar_show); @@ -1231,7 +1379,7 @@ read_set_recent_pair_static(gchar *key, const gchar *value, num = strtol(value, &p, 0); if (p == value || *p != '\0') return PREFS_SET_SYNTAX_ERR; /* number was bad */ - recent.gui_zoom_level = (gint)num; + recent.gui_zoom_level = (int)num; } else if (strcmp(key, RECENT_GUI_BYTES_VIEW) == 0) { recent.gui_bytes_view = (bytes_view_type)str_to_val(value, bytes_view_type_values, BYTES_HEX); @@ -1244,33 +1392,52 @@ read_set_recent_pair_static(gchar *key, const gchar *value, parse_recent_boolean(value, &recent.gui_allow_hover_selection); } else if (strcmp(key, RECENT_GUI_FOLLOW_SHOW) == 0) { recent.gui_follow_show = (bytes_show_type)str_to_val(value, bytes_show_values, SHOW_ASCII); + } else if (strcmp(key, RECENT_GUI_FOLLOW_DELTA) == 0) { + recent.gui_follow_delta = (follow_delta_type)str_to_val(value, follow_delta_values, FOLLOW_DELTA_NONE); } else if (strcmp(key, RECENT_GUI_SHOW_BYTES_DECODE) == 0) { recent.gui_show_bytes_decode = (bytes_decode_type)str_to_val(value, show_bytes_decode_values, DecodeAsNone); } else if (strcmp(key, RECENT_GUI_SHOW_BYTES_SHOW) == 0) { recent.gui_show_bytes_show = (bytes_show_type)str_to_val(value, bytes_show_values, SHOW_ASCII); - } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) { - parse_recent_boolean(value, &recent.gui_geometry_main_maximized); } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) { 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 = (gint)num; + recent.gui_geometry_main_upper_pane = (int)num; } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) { 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 = (gint)num; + recent.gui_geometry_main_lower_pane = (int)num; + } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MASTER_SPLIT) == 0) { + g_free(recent.gui_geometry_main_master_split); + recent.gui_geometry_main_master_split = g_strdup(value); + } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_EXTRA_SPLIT) == 0) { + g_free(recent.gui_geometry_main_extra_split); + recent.gui_geometry_main_extra_split = g_strdup(value); + } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) { + /* now have something like "gui.geom.win.sub_key", split it into win and sub_key */ + char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1]; + char *sub_key = strchr(win, '.'); + if (sub_key) { + *sub_key = '\0'; + sub_key++; + window_geom_recent_read_pair(win, sub_key, value); + } } else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS) == 0) { + g_list_free_full(recent.conversation_tabs, g_free); recent.conversation_tabs = prefs_get_string_list(value); } else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS_COLUMNS) == 0) { + g_list_free_full(recent.conversation_tabs_columns, g_free); recent.conversation_tabs_columns = prefs_get_string_list(value); } else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS) == 0) { + g_list_free_full(recent.endpoint_tabs, g_free); recent.endpoint_tabs = prefs_get_string_list(value); } else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS_COLUMNS) == 0) { + g_list_free_full(recent.endpoint_tabs_columns, g_free); recent.endpoint_tabs_columns = prefs_get_string_list(value); } else if (strcmp(key, RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES) == 0) { parse_recent_boolean(value, &recent.gui_rlc_use_pdus_from_mac); @@ -1283,63 +1450,18 @@ read_set_recent_pair_static(gchar *key, const gchar *value, prefs_clear_string_list(col_l); return PREFS_SET_SYNTAX_ERR; } - /* Check to make sure all column formats are valid. */ - col_l_elt = g_list_first(col_l); - while (col_l_elt) { - fmt_data cfmt_check; - - /* Make sure the format isn't empty. */ - if (strcmp((const char *)col_l_elt->data, "") == 0) { - /* It is. */ - prefs_clear_string_list(col_l); - return PREFS_SET_SYNTAX_ERR; - } - - /* Some predefined columns have been migrated to use custom - * columns. We'll convert these silently here */ - try_convert_to_custom_column((char **)&col_l_elt->data); - - /* Check the format. */ - if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) { - /* It's not a valid column format. */ - prefs_clear_string_list(col_l); - return PREFS_SET_SYNTAX_ERR; - } - if (cfmt_check.fmt == COL_CUSTOM) { - /* We don't need the custom column field on this pass. */ - g_free(cfmt_check.custom_fields); - } - - /* Go past the format. */ - col_l_elt = col_l_elt->next; - - /* Go past the width. */ - col_l_elt = col_l_elt->next; - } - free_col_width_info(&recent); + recent_free_column_width_info(&recent); recent.col_width_list = NULL; col_l_elt = g_list_first(col_l); while (col_l_elt) { - gchar *fmt = g_strdup((const gchar *)col_l_elt->data); cfmt = g_new(col_width_data, 1); - if (strncmp(fmt, cust_format, cust_format_len) != 0) { - cfmt->cfmt = get_column_format_from_str(fmt); - cfmt->cfield = NULL; - } else { - cfmt->cfmt = COL_CUSTOM; - cfmt->cfield = g_strdup(&fmt[cust_format_len+1]); /* add 1 for ':' */ - } - g_free (fmt); - if (cfmt->cfmt == -1) { - g_free(cfmt->cfield); - g_free(cfmt); - return PREFS_SET_SYNTAX_ERR; /* string was bad */ - } - + /* Skip the column format, we don't use it anymore because the + * column indices are in sync and the key since 4.4. Format is + * still written for backwards compatibility. + */ col_l_elt = col_l_elt->next; - cfmt->width = (gint)strtol((const char *)col_l_elt->data, &p, 0); + cfmt->width = (int)strtol((const char *)col_l_elt->data, &p, 0); if (p == col_l_elt->data || (*p != '\0' && *p != ':')) { - g_free(cfmt->cfield); g_free(cfmt); return PREFS_SET_SYNTAX_ERR; /* number was bad */ } @@ -1371,15 +1493,15 @@ read_set_recent_pair_static(gchar *key, const gchar *value, /* set one user's recent file key/value pair */ static prefs_set_pref_e -read_set_recent_pair_dynamic(gchar *key, const gchar *value, +read_set_recent_pair_dynamic(char *key, const char *value, void *private_data _U_, - gboolean return_range_errors _U_) + bool return_range_errors _U_) { if (!g_utf8_validate(value, -1, NULL)) { return PREFS_SET_SYNTAX_ERR; } if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) { - add_menu_recent_capture_file(value); + add_menu_recent_capture_file(value, true); } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) { dfilter_combo_add_recent(value); } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER) == 0) { @@ -1406,7 +1528,7 @@ read_set_recent_pair_dynamic(gchar *key, const gchar *value, int recent_set_arg(char *prefarg) { - gchar *p, *colonp; + char *p, *colonp; int ret; colonp = strchr(prefarg, ':'); @@ -1433,14 +1555,14 @@ recent_set_arg(char *prefarg) return PREFS_SET_SYNTAX_ERR; } - ret = read_set_recent_pair_static(prefarg, p, NULL, TRUE); + ret = read_set_recent_pair_static(prefarg, p, NULL, true); *colonp = ':'; /* put the colon back */ return ret; } /* opens the user's recent common file and read the first part */ -gboolean +bool recent_read_static(char **rf_path_return, int *rf_errno_return) { char *rf_path; @@ -1451,20 +1573,22 @@ recent_read_static(char **rf_path_return, int *rf_errno_return) recent.gui_geometry_main_y = 20; recent.gui_geometry_main_width = DEF_WIDTH; recent.gui_geometry_main_height = DEF_HEIGHT; - recent.gui_geometry_main_maximized= FALSE; - - recent.gui_geometry_leftalign_actions = FALSE; + recent.gui_geometry_main_maximized= false; - recent.gui_geometry_wlan_stats_pane = 200; + recent.gui_geometry_leftalign_actions = false; - recent.privs_warn_if_elevated = TRUE; - recent.sys_warn_if_no_capture = TRUE; + recent.privs_warn_if_elevated = true; + recent.sys_warn_if_no_capture = true; recent.col_width_list = NULL; + recent.gui_geometry_main = NULL; + recent.gui_geometry_main_master_split = NULL; + recent.gui_geometry_main_extra_split = NULL; + recent.gui_profile_switch_check_count = 1000; recent.gui_fileopen_remembered_dir = NULL; /* Construct the pathname of the user's recent common file. */ - rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE); + rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, false); /* Read the user's recent common file, if it exists. */ *rf_path_return = NULL; @@ -1480,41 +1604,42 @@ recent_read_static(char **rf_path_return, int *rf_errno_return) if (errno != ENOENT) { *rf_errno_return = errno; *rf_path_return = rf_path; - return FALSE; + return false; } } g_free(rf_path); - return TRUE; + return true; } /* opens the user's recent file and read the first part */ -gboolean +bool recent_read_profile_static(char **rf_path_return, int *rf_errno_return) { char *rf_path, *rf_common_path; FILE *rf; /* set defaults */ - recent.main_toolbar_show = TRUE; - recent.filter_toolbar_show = TRUE; - recent.wireless_toolbar_show = FALSE; - recent.packet_list_show = TRUE; - recent.tree_view_show = TRUE; - recent.byte_view_show = TRUE; - recent.packet_diagram_show = TRUE; - recent.statusbar_show = TRUE; - recent.packet_list_colorize = TRUE; - recent.capture_auto_scroll = TRUE; + recent.main_toolbar_show = true; + recent.filter_toolbar_show = true; + recent.wireless_toolbar_show = false; + recent.packet_list_show = true; + recent.tree_view_show = true; + recent.byte_view_show = true; + recent.packet_diagram_show = true; + recent.statusbar_show = true; + recent.packet_list_colorize = true; + recent.capture_auto_scroll = true; recent.gui_time_format = TS_RELATIVE; recent.gui_time_precision = TS_PREC_AUTO; recent.gui_seconds_format = TS_SECONDS_DEFAULT; recent.gui_zoom_level = 0; recent.gui_bytes_view = BYTES_HEX; recent.gui_bytes_encoding = BYTES_ENC_FROM_PACKET; - recent.gui_allow_hover_selection = TRUE; + recent.gui_allow_hover_selection = true; recent.gui_follow_show = SHOW_ASCII; + recent.gui_follow_delta = FOLLOW_DELTA_NONE; recent.gui_show_bytes_decode = DecodeAsNone; recent.gui_show_bytes_show = SHOW_ASCII; @@ -1522,8 +1647,22 @@ recent_read_profile_static(char **rf_path_return, int *rf_errno_return) recent.gui_geometry_main_upper_pane = 0; recent.gui_geometry_main_lower_pane = 0; + if (recent.gui_geometry_main) { + g_free(recent.gui_geometry_main); + recent.gui_geometry_main = NULL; + } + + if (recent.gui_geometry_main_master_split) { + g_free(recent.gui_geometry_main_master_split); + recent.gui_geometry_main_master_split = NULL; + } + if (recent.gui_geometry_main_extra_split) { + g_free(recent.gui_geometry_main_extra_split); + recent.gui_geometry_main_extra_split = NULL; + } + if (recent.col_width_list) { - free_col_width_info(&recent); + recent_free_column_width_info(&recent); } if (recent.gui_fileopen_remembered_dir) { @@ -1542,7 +1681,7 @@ recent_read_profile_static(char **rf_path_return, int *rf_errno_return) } /* Construct the pathname of the user's profile recent file. */ - rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE); + rf_path = get_persconffile_path(RECENT_FILE_NAME, true); /* Read the user's recent file, if it exists. */ *rf_path_return = NULL; @@ -1559,7 +1698,7 @@ recent_read_profile_static(char **rf_path_return, int *rf_errno_return) * know what's supposed to happen at this point. * ToDo: Determine if the "recent common file" should be read at this point */ - rf_common_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE); + rf_common_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, false); if (!file_exists(rf_common_path)) { /* Read older common settings from recent file */ rf = ws_fopen(rf_path, "r"); @@ -1574,15 +1713,15 @@ recent_read_profile_static(char **rf_path_return, int *rf_errno_return) if (errno != ENOENT) { *rf_errno_return = errno; *rf_path_return = rf_path; - return FALSE; + return false; } } g_free(rf_path); - return TRUE; + return true; } /* opens the user's recent file and read it out */ -gboolean +bool recent_read_dynamic(char **rf_path_return, int *rf_errno_return) { char *rf_path; @@ -1590,11 +1729,11 @@ recent_read_dynamic(char **rf_path_return, int *rf_errno_return) /* Construct the pathname of the user's recent common file. */ - rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE); + rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, false); if (!file_exists (rf_path)) { /* Recent common file does not exist, read from default recent */ g_free (rf_path); - rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE); + rf_path = get_persconffile_path(RECENT_FILE_NAME, false); } /* Read the user's recent file, if it exists. */ @@ -1610,6 +1749,9 @@ recent_read_dynamic(char **rf_path_return, int *rf_errno_return) * all to keep the latest first. */ cfilter_recent_reverse_all(); +#ifdef HAVE_PCAP_REMOTE + remote_host_reverse(); +#endif fclose(rf); } else { /* We failed to open it. If we failed for some reason other than @@ -1618,142 +1760,122 @@ recent_read_dynamic(char **rf_path_return, int *rf_errno_return) if (errno != ENOENT) { *rf_errno_return = errno; *rf_path_return = rf_path; - return FALSE; + return false; } } g_free(rf_path); - return TRUE; + return true; } -gint -recent_get_column_width(gint col) +void +recent_insert_column(int col) { - GList *col_l; col_width_data *col_w; - gint cfmt; - const gchar *cfield = NULL; - cfmt = get_column_format(col); - if (cfmt == COL_CUSTOM) { - cfield = get_column_custom_fields(col); - } - - col_l = g_list_first(recent.col_width_list); - while (col_l) { - col_w = (col_width_data *) col_l->data; - if (col_w->cfmt == cfmt) { - if (cfmt != COL_CUSTOM) { - return col_w->width; - } else if (cfield && strcmp (cfield, col_w->cfield) == 0) { - return col_w->width; - } - } - col_l = col_l->next; - } - - return -1; + col_w = g_new(col_width_data, 1); + col_w->width = -1; + col_w->xalign = COLUMN_XALIGN_DEFAULT; + recent.col_width_list = g_list_insert(recent.col_width_list, col_w, col); } void -recent_set_column_width(gint col, gint width) +recent_remove_column(int col) { - GList *col_l; + GList *col_l = g_list_nth(recent.col_width_list, col); col_width_data *col_w; - gint cfmt; - const gchar *cfield = NULL; - gboolean found = FALSE; - cfmt = get_column_format(col); - if (cfmt == COL_CUSTOM) { - cfield = get_column_custom_fields(col); - } + if (!col_l) return; - col_l = g_list_first(recent.col_width_list); - while (col_l) { - col_w = (col_width_data *) col_l->data; - if (col_w->cfmt == cfmt) { - if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) { - col_w->width = width; - found = TRUE; - break; - } - } - col_l = col_l->next; - } + col_w = (col_width_data*)col_l->data; - if (!found) { - col_w = g_new(col_width_data, 1); - col_w->cfmt = cfmt; - col_w->cfield = g_strdup(cfield); - col_w->width = width; - col_w->xalign = COLUMN_XALIGN_DEFAULT; - recent.col_width_list = g_list_append(recent.col_width_list, col_w); + if (col_w) { + free_col_width_data(col_w); } + + recent.col_width_list = g_list_delete_link(recent.col_width_list, col_l); } -gchar -recent_get_column_xalign(gint col) +int +recent_get_column_width(int col) { - GList *col_l; col_width_data *col_w; - gint cfmt; - const gchar *cfield = NULL; - cfmt = get_column_format(col); - if (cfmt == COL_CUSTOM) { - cfield = get_column_custom_fields(col); - } - - col_l = g_list_first(recent.col_width_list); - while (col_l) { - col_w = (col_width_data *) col_l->data; - if (col_w->cfmt == cfmt) { - if (cfmt != COL_CUSTOM) { - return col_w->xalign; - } else if (cfield && strcmp (cfield, col_w->cfield) == 0) { - return col_w->xalign; - } + col_w = g_list_nth_data(recent.col_width_list, col); + if (col_w) { + return col_w->width; + } else { + /* Make sure the recent column list isn't out of sync with the + * number of columns (e.g., for a brand new profile.) + */ + for (unsigned colnr = g_list_length(recent.col_width_list); colnr < g_list_length(prefs.col_list); colnr++) { + recent_insert_column(colnr); } - col_l = col_l->next; } - return 0; + return -1; } void -recent_set_column_xalign(gint col, gchar xalign) +recent_set_column_width(int col, int width) { - GList *col_l; col_width_data *col_w; - gint cfmt; - const gchar *cfield = NULL; - gboolean found = FALSE; - cfmt = get_column_format(col); - if (cfmt == COL_CUSTOM) { - cfield = get_column_custom_fields(col); + col_w = g_list_nth_data(recent.col_width_list, col); + if (col_w) { + col_w->width = width; + } else { + /* Make sure the recent column list isn't out of sync with the + * number of columns (e.g., for a brand new profile.) + */ + for (unsigned colnr = g_list_length(recent.col_width_list); colnr < g_list_length(prefs.col_list); colnr++) { + recent_insert_column(colnr); + } + col_w = g_list_nth_data(recent.col_width_list, col); + if (col_w) { + col_w->width = width; + } } +} - col_l = g_list_first(recent.col_width_list); - while (col_l) { - col_w = (col_width_data *) col_l->data; - if (col_w->cfmt == cfmt) { - if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) { - col_w->xalign = xalign; - found = TRUE; - break; - } +char +recent_get_column_xalign(int col) +{ + col_width_data *col_w; + + col_w = g_list_nth_data(recent.col_width_list, col); + if (col_w) { + return col_w->xalign; + } else { + /* Make sure the recent column list isn't out of sync with the + * number of columns (e.g., for a brand new profile.) + */ + for (unsigned colnr = g_list_length(recent.col_width_list); colnr < g_list_length(prefs.col_list); colnr++) { + recent_insert_column(colnr); } - col_l = col_l->next; } - if (!found) { - col_w = g_new(col_width_data, 1); - col_w->cfmt = cfmt; - col_w->cfield = g_strdup(cfield); - col_w->width = 40; + return COLUMN_XALIGN_DEFAULT; +} + +void +recent_set_column_xalign(int col, char xalign) +{ + col_width_data *col_w; + + col_w = g_list_nth_data(recent.col_width_list, col); + if (col_w) { col_w->xalign = xalign; - recent.col_width_list = g_list_append(recent.col_width_list, col_w); + } else { + /* Make sure the recent column list isn't out of sync with the + * number of columns (e.g., for a brand new profile.) + */ + for (unsigned colnr = g_list_length(recent.col_width_list); colnr < g_list_length(prefs.col_list); colnr++) { + recent_insert_column(colnr); + } + col_w = g_list_nth_data(recent.col_width_list, col); + if (col_w) { + col_w->xalign = xalign; + } } } @@ -1766,7 +1888,10 @@ recent_init(void) void recent_cleanup(void) { - free_col_width_info(&recent); + recent_free_column_width_info(&recent); + g_free(recent.gui_geometry_main); + g_free(recent.gui_geometry_main_master_split); + g_free(recent.gui_geometry_main_extra_split); g_free(recent.gui_fileopen_remembered_dir); g_list_free_full(recent.gui_additional_toolbars, g_free); g_list_free_full(recent.interface_toolbars, g_free); |