2 * Dialog box for GUI preferences
4 * $Id: gui_prefs.c,v 1.61 2004/01/31 02:25:45 ulfl Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include "gui_prefs.h"
35 #include "gtkglobals.h"
37 #include "supported_protos_dlg.h"
39 #include "prefs_dlg.h"
41 #include "simple_dialog.h"
42 #include "dlg_utils.h"
43 #include "proto_draw.h"
45 #include "packet_list.h"
46 #include "compat_macros.h"
50 static gint fetch_enum_value(gpointer control, const enum_val_t *enumvals);
51 static gint fileopen_dir_changed_cb(GtkWidget *myentry _U_, GdkEvent *event, gpointer parent_w);
52 static void fileopen_selected_cb(GtkWidget *mybutton_rb _U_, gpointer parent_w);
53 static gint recent_files_count_changed_cb(GtkWidget *recent_files_entry _U_,
54 GdkEvent *event _U_, gpointer parent_w);
56 #define SCROLLBAR_PLACEMENT_KEY "scrollbar_placement"
57 #define PLIST_SEL_BROWSE_KEY "plist_sel_browse"
58 #define PTREE_SEL_BROWSE_KEY "ptree_sel_browse"
59 #if GTK_MAJOR_VERSION < 2
60 #define PTREE_LINE_STYLE_KEY "ptree_line_style"
61 #define PTREE_EXPANDER_STYLE_KEY "ptree_expander_style"
63 #define ALTERN_COLORS_KEY "altern_colors"
65 #define HEX_DUMP_HIGHLIGHT_STYLE_KEY "hex_dump_highlight_style"
66 #define GEOMETRY_POSITION_KEY "geometry_position"
67 #define GEOMETRY_SIZE_KEY "geometry_size"
69 #define GUI_FILEOPEN_KEY "fileopen_behavior"
70 #define GUI_RECENT_FILES_COUNT_KEY "recent_files_count"
71 #define GUI_FILEOPEN_DIR_KEY "fileopen_directory"
73 #define GUI_TOOLBAR_STYLE_KEY "toolbar_style"
75 static const enum_val_t scrollbar_placement_vals[] = {
81 static const enum_val_t selection_mode_vals[] = {
87 #if GTK_MAJOR_VERSION < 2
88 static const enum_val_t line_style_vals[] = {
96 static const enum_val_t expander_style_vals[] = {
104 static const enum_val_t altern_colors_vals[] = {
111 static const enum_val_t highlight_style_vals[] = {
117 static const enum_val_t toolbar_style_vals[] = {
118 { "Icons only", TB_STYLE_ICONS },
119 { "Text only", TB_STYLE_TEXT },
120 { "Icons & Text", TB_STYLE_BOTH },
124 static const enum_val_t gui_fileopen_vals[] = {
125 { "Remember last directory", FO_STYLE_LAST_OPENED },
126 { "Always start in directory:", FO_STYLE_SPECIFIED },
130 /* Set to FALSE initially; set to TRUE if the user ever hits "OK" on
131 the "Font..." dialog, so that we know that they (probably) changed
132 the font, and therefore that the "apply" function needs to take care
134 static gboolean font_changed;
136 /* Font name from the font dialog box; if "font_changed" is TRUE, this
137 has been set to the name of the font the user selected. */
138 static gchar *new_font_name;
140 static GtkWidget *font_browse_w;
142 /* Used to contain the string from the Recent Files Count Max pref item */
143 static char recent_files_count_max_str[128] = "";
145 #if GTK_MAJOR_VERSION < 2
146 #define GUI_TABLE_ROWS 10
148 #define GUI_TABLE_ROWS 9
154 GtkWidget *main_tb, *main_vb, *hbox;
155 GtkWidget *scrollbar_om, *plist_browse_om;
156 GtkWidget *ptree_browse_om, *highlight_style_om;
157 GtkWidget *fileopen_rb, *fileopen_dir_te, *toolbar_style_om;
158 GtkWidget *recent_files_count_max_te;
159 GtkWidget *save_position_cb, *save_size_cb;
160 #if GTK_MAJOR_VERSION < 2
161 GtkWidget *expander_style_om, *line_style_om;
163 GtkWidget *altern_colors_om;
166 char current_val_str[128];
168 /* The font haven't been changed yet. */
169 font_changed = FALSE;
171 /* Main vertical box */
172 main_vb = gtk_vbox_new(FALSE, 7);
173 gtk_container_border_width( GTK_CONTAINER(main_vb), 5 );
175 /* Main horizontal box */
176 /* XXX - Is there a better way to center the table? */
177 hbox = gtk_hbox_new(FALSE, 7);
178 gtk_box_pack_start (GTK_BOX(main_vb), hbox, TRUE, FALSE, 0);
181 main_tb = gtk_table_new(GUI_TABLE_ROWS, 2, FALSE);
182 gtk_box_pack_start( GTK_BOX(hbox), main_tb, TRUE, FALSE, 0 );
183 gtk_table_set_row_spacings( GTK_TABLE(main_tb), 10 );
184 gtk_table_set_col_spacings( GTK_TABLE(main_tb), 15 );
185 gtk_table_set_col_spacing( GTK_TABLE(main_tb), 0, 50 );
187 /* Scrollbar placement */
188 scrollbar_om = create_preference_option_menu(main_tb, pos++,
189 "Vertical scrollbar placement:", NULL, scrollbar_placement_vals,
190 prefs.gui_scrollbar_on_right);
191 OBJECT_SET_DATA(main_vb, SCROLLBAR_PLACEMENT_KEY, scrollbar_om);
193 /* Packet list selection browseable */
194 plist_browse_om = create_preference_option_menu(main_tb, pos++,
195 "Packet list selection mode:", NULL, selection_mode_vals,
196 prefs.gui_plist_sel_browse);
197 OBJECT_SET_DATA(main_vb, PLIST_SEL_BROWSE_KEY, plist_browse_om);
199 /* Proto tree selection browseable */
200 ptree_browse_om = create_preference_option_menu(main_tb, pos++,
201 "Protocol tree selection mode:", NULL, selection_mode_vals,
202 prefs.gui_ptree_sel_browse);
203 OBJECT_SET_DATA(main_vb, PTREE_SEL_BROWSE_KEY, ptree_browse_om);
205 #if GTK_MAJOR_VERSION < 2
206 /* Tree line style */
207 line_style_om = create_preference_option_menu(main_tb, pos++,
208 "Tree line style:", NULL, line_style_vals,
209 prefs.gui_ptree_line_style);
210 OBJECT_SET_DATA(main_vb, PTREE_LINE_STYLE_KEY, line_style_om);
212 /* Tree expander style */
213 expander_style_om = create_preference_option_menu(main_tb, pos++,
214 "Tree expander style:", NULL, expander_style_vals,
215 prefs.gui_ptree_expander_style);
216 OBJECT_SET_DATA(main_vb, PTREE_EXPANDER_STYLE_KEY, expander_style_om);
218 /* Alternating row colors in list and tree views */
219 altern_colors_om = create_preference_option_menu(main_tb, pos++,
220 "Alternating row colors in lists and trees:", NULL,
221 altern_colors_vals, prefs.gui_altern_colors);
222 OBJECT_SET_DATA(main_vb, ALTERN_COLORS_KEY, altern_colors_om);
225 /* Hex Dump highlight style */
226 highlight_style_om = create_preference_option_menu(main_tb, pos++,
227 "Hex display highlight style:", NULL, highlight_style_vals,
228 prefs.gui_hex_dump_highlight_style);
229 OBJECT_SET_DATA(main_vb, HEX_DUMP_HIGHLIGHT_STYLE_KEY,
233 toolbar_style_om = create_preference_option_menu(main_tb, pos++,
234 "Toolbar style:", NULL, toolbar_style_vals,
235 prefs.gui_toolbar_main_style);
236 OBJECT_SET_DATA(main_vb, GUI_TOOLBAR_STYLE_KEY,
240 save_position_cb = create_preference_check_button(main_tb, pos++,
241 "Save window position:", NULL, prefs.gui_geometry_save_position);
242 OBJECT_SET_DATA(main_vb, GEOMETRY_POSITION_KEY, save_position_cb);
244 save_size_cb = create_preference_check_button(main_tb, pos++,
245 "Save window size:", NULL, prefs.gui_geometry_save_size);
246 OBJECT_SET_DATA(main_vb, GEOMETRY_SIZE_KEY, save_size_cb);
248 /* Allow user to select where they want the File Open dialog to open to
250 fileopen_rb = create_preference_radio_buttons(main_tb, pos++,
251 "File Open dialog behavior:", NULL, gui_fileopen_vals,
252 prefs.gui_fileopen_style);
254 /* Directory to default File Open dialog to */
255 fileopen_dir_te = create_preference_entry(main_tb, pos++, "Directory:",
256 NULL, prefs.gui_fileopen_dir);
257 OBJECT_SET_DATA(main_vb, GUI_FILEOPEN_KEY, fileopen_rb);
258 OBJECT_SET_DATA(main_vb, GUI_FILEOPEN_DIR_KEY, fileopen_dir_te);
259 SIGNAL_CONNECT(fileopen_rb, "clicked", fileopen_selected_cb, main_vb);
260 SIGNAL_CONNECT(fileopen_dir_te, "focus-out-event",
261 fileopen_dir_changed_cb, main_vb);
263 /* Number of entries in the recent_files list ... */
264 recent_files_count_max_te = create_preference_entry(main_tb, pos++,
265 "Recent Files Count Max:", "Maximum number of recent files", recent_files_count_max_str);
266 sprintf(current_val_str, "%d", prefs.gui_recent_files_count_max);
267 gtk_entry_set_text(GTK_ENTRY(recent_files_count_max_te), current_val_str);
268 OBJECT_SET_DATA(main_vb, GUI_RECENT_FILES_COUNT_KEY, recent_files_count_max_te);
269 SIGNAL_CONNECT(recent_files_count_max_te, "focus_out_event", recent_files_count_changed_cb, main_vb);
271 fileopen_selected_cb(NULL, main_vb);
273 /* Show 'em what we got */
274 gtk_widget_show_all(main_vb);
280 /* Create a font widget for browsing. */
282 gui_font_prefs_show(void)
285 #if GTK_MAJOR_VERSION < 2
286 static gchar *fixedwidths[] = { "c", "m", NULL };
290 /* Now create a new widget. */
291 font_browse_w = (GtkWidget *) gtk_font_selection_new();
293 /*gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(font_browse_w),
294 "WWWWWWWW llllllll (Tip: use a fixed width font)");*/
297 /* GTK (at least version 1.3) has an annoying bug: */
298 /* when using the font selection instead of the dialog, */
299 /* the widget seems to disconnected from the parent, */
300 /* if a filter is used! */
301 #if GTK_MAJOR_VERSION < 2
302 /* Set its filter to show only fixed_width fonts. */
303 gtk_font_selection_set_filter(
304 GTK_FONT_SELECTION(font_browse_w),
305 GTK_FONT_FILTER_BASE, /* user can't change the filter */
306 GTK_FONT_ALL, /* bitmap or scalable are fine */
307 NULL, /* all foundries are OK */
308 NULL, /* all weights are OK (XXX - normal only?) */
309 NULL, /* all slants are OK (XXX - Roman only?) */
310 NULL, /* all setwidths are OK */
311 fixedwidths, /* ONLY fixed-width fonts */
312 NULL); /* all charsets are OK (XXX - ISO 8859/1 only?) */
316 gtk_widget_show(font_browse_w);
318 return font_browse_w;
326 #if GTK_MAJOR_VERSION < 2
327 gchar *bold_font_name;
328 GdkFont *new_r_font, *new_b_font;
330 PangoFontDescription *new_r_font, *new_b_font;
333 font_name = g_strdup(gtk_font_selection_get_font_name(
334 GTK_FONT_SELECTION(font_browse_w)));
335 if (font_name == NULL) {
336 /* No font was selected; let the user know, but don't
337 tear down the font selection dialog, so they can
339 simple_dialog(ESD_TYPE_ERROR | ESD_TYPE_MODAL, NULL,
340 "You have not selected a font.");
344 #if GTK_MAJOR_VERSION < 2
345 /* Get the name that the boldface version of that font would have. */
346 bold_font_name = font_boldify(font_name);
348 /* Now load those fonts, just to make sure we can. */
349 new_r_font = gdk_font_load(font_name);
351 new_r_font = pango_font_description_from_string(font_name);
353 if (new_r_font == NULL) {
354 /* Oops, that font didn't work.
355 Tell the user, but don't tear down the font selection
356 dialog, so that they can try again. */
357 simple_dialog(ESD_TYPE_ERROR | ESD_TYPE_MODAL, NULL,
358 "The font you selected cannot be loaded.");
361 #if GTK_MAJOR_VERSION < 2
362 g_free(bold_font_name);
367 #if GTK_MAJOR_VERSION < 2
368 new_b_font = gdk_font_load(bold_font_name);
370 new_b_font = pango_font_description_copy(new_r_font);
371 pango_font_description_set_weight(new_b_font, PANGO_WEIGHT_BOLD);
373 if (new_b_font == NULL) {
374 /* Oops, that font didn't work.
375 Tell the user, but don't tear down the font selection
376 dialog, so that they can try again. */
377 simple_dialog(ESD_TYPE_ERROR | ESD_TYPE_MODAL, NULL,
378 "The font you selected doesn't have a boldface version.");
381 #if GTK_MAJOR_VERSION < 2
382 g_free(bold_font_name);
383 gdk_font_unref(new_r_font);
385 pango_font_description_free(new_r_font);
390 new_font_name = font_name;
396 fetch_enum_value(gpointer control, const enum_val_t *enumvals)
398 return fetch_preference_option_menu_val(GTK_WIDGET(control), enumvals);
402 gui_prefs_fetch(GtkWidget *w)
404 prefs.gui_scrollbar_on_right = fetch_enum_value(
405 OBJECT_GET_DATA(w, SCROLLBAR_PLACEMENT_KEY),
406 scrollbar_placement_vals);
407 prefs.gui_plist_sel_browse = fetch_enum_value(
408 OBJECT_GET_DATA(w, PLIST_SEL_BROWSE_KEY), selection_mode_vals);
409 prefs.gui_ptree_sel_browse = fetch_enum_value(
410 OBJECT_GET_DATA(w, PTREE_SEL_BROWSE_KEY), selection_mode_vals);
411 #if GTK_MAJOR_VERSION < 2
412 prefs.gui_ptree_line_style = fetch_enum_value(
413 OBJECT_GET_DATA(w, PTREE_LINE_STYLE_KEY), line_style_vals);
414 prefs.gui_ptree_expander_style = fetch_enum_value(
415 OBJECT_GET_DATA(w, PTREE_EXPANDER_STYLE_KEY), expander_style_vals);
417 prefs.gui_altern_colors = fetch_enum_value(
418 OBJECT_GET_DATA(w, ALTERN_COLORS_KEY), altern_colors_vals);
420 prefs.gui_hex_dump_highlight_style = fetch_enum_value(
421 OBJECT_GET_DATA(w, HEX_DUMP_HIGHLIGHT_STYLE_KEY),
422 highlight_style_vals);
423 prefs.gui_toolbar_main_style = fetch_enum_value(
424 OBJECT_GET_DATA(w, GUI_TOOLBAR_STYLE_KEY),
426 prefs.gui_geometry_save_position =
427 gtk_toggle_button_get_active(OBJECT_GET_DATA(w,
428 GEOMETRY_POSITION_KEY));
429 prefs.gui_geometry_save_size =
430 gtk_toggle_button_get_active(OBJECT_GET_DATA(w, GEOMETRY_SIZE_KEY));
431 prefs.gui_fileopen_style = fetch_preference_radio_buttons_val(
432 OBJECT_GET_DATA(w, GUI_FILEOPEN_KEY), gui_fileopen_vals);
434 if (prefs.gui_fileopen_dir != NULL)
435 g_free(prefs.gui_fileopen_dir);
436 prefs.gui_fileopen_dir = g_strdup(gtk_entry_get_text(
437 GTK_ENTRY(OBJECT_GET_DATA(w, GUI_FILEOPEN_DIR_KEY))));
440 * XXX - we need to have a way to fetch the preferences into
441 * local storage and only set the permanent preferences if there
442 * weren't any errors in those fetches, as there are several
443 * places where there *can* be a bad preference value.
446 if (strcmp(new_font_name, prefs.PREFS_GUI_FONT_NAME) != 0) {
448 if (prefs.PREFS_GUI_FONT_NAME != NULL)
449 g_free(prefs.PREFS_GUI_FONT_NAME);
450 prefs.PREFS_GUI_FONT_NAME = g_strdup(new_font_name);
458 gui_prefs_apply(GtkWidget *w _U_)
462 /* This redraws the hex dump windows. */
463 switch (font_apply()) {
468 case FA_FONT_NOT_RESIZEABLE:
469 /* "font_apply()" popped up an alert box. */
470 /* turn off zooming - font can't be resized */
471 recent.gui_zoom_level = 0;
474 case FA_FONT_NOT_AVAILABLE:
475 /* We assume this means that the specified size
477 simple_dialog(ESD_TYPE_ERROR, NULL,
478 "That font font isn't available at the specified zoom level;\n"
479 "turning zooming off.");
480 recent.gui_zoom_level = 0;
484 /* Redraw the hex dump windows, in case the
485 highlight style changed.
486 XXX - do it only if the highlight style *did* change. */
487 redraw_hex_dump_all();
490 /* Redraw the help window(s). */
494 /* XXX: redraw the toolbar only, if style changed */
495 toolbar_redraw_all();
497 set_scrollbar_placement_all();
498 set_plist_sel_browse(prefs.gui_plist_sel_browse);
499 set_ptree_sel_browse_all(prefs.gui_ptree_sel_browse);
500 set_tree_styles_all();
504 gui_prefs_destroy(GtkWidget *w _U_)
506 /* Free up any saved font name. */
507 if (new_font_name != NULL) {
508 g_free(new_font_name);
509 new_font_name = NULL;
515 recent_files_count_changed_cb(GtkWidget *recent_files_entry _U_,
516 GdkEvent *event _U_, gpointer parent_w)
518 GtkWidget *recent_files_count_te;
521 recent_files_count_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_RECENT_FILES_COUNT_KEY);
524 * Now, just convert the string to a number and store it in the prefs
528 newval = strtol(gtk_entry_get_text (GTK_ENTRY(recent_files_count_te)), NULL, 10);
531 prefs.gui_recent_files_count_max = newval;
534 /* We really should pop up a nasty dialog box if newval <= 0 */
540 fileopen_dir_changed_cb(GtkWidget *fileopen_entry _U_, GdkEvent *event _U_, gpointer parent_w)
542 GtkWidget *fileopen_dir_te;
544 gint fileopen_dir_te_length;
546 fileopen_dir_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_FILEOPEN_DIR_KEY);
547 fileopen_dir_te_length = strlen(gtk_entry_get_text (GTK_ENTRY(fileopen_entry)));
548 if (fileopen_dir_te_length == 0)
550 lastchar = gtk_editable_get_chars(GTK_EDITABLE(fileopen_entry), fileopen_dir_te_length-1, -1);
551 if (strcmp(lastchar, G_DIR_SEPARATOR_S) != 0)
552 gtk_entry_append_text(GTK_ENTRY(fileopen_entry), G_DIR_SEPARATOR_S);
557 fileopen_selected_cb(GtkWidget *mybutton_rb _U_, gpointer parent_w)
559 GtkWidget *fileopen_rb, *fileopen_dir_te;
561 fileopen_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_FILEOPEN_KEY);
562 fileopen_dir_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_FILEOPEN_DIR_KEY);
564 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fileopen_rb)))
566 gtk_widget_set_sensitive(GTK_WIDGET(fileopen_dir_te), TRUE);
570 gtk_widget_set_sensitive(GTK_WIDGET(fileopen_dir_te), FALSE);