Clean up indentation.
[obnox/wireshark/wip.git] / gtk / gui_prefs.c
1 /* gui_prefs.c
2  * Dialog box for GUI preferences
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include <string.h>
32
33 #include "globals.h"
34 #include "gui_prefs.h"
35 #include "gtkglobals.h"
36 #include "help_dlg.h"
37 #include "supported_protos_dlg.h"
38 #include <epan/prefs.h>
39 #include "prefs_dlg.h"
40 #include "ui_util.h"
41 #include "simple_dialog.h"
42 #include "dlg_utils.h"
43 #include "proto_draw.h"
44 #include "main.h"
45 #include "compat_macros.h"
46 #include "font_utils.h"
47 #include "packet_list.h"
48 #include "toolbar.h"
49 #include "recent.h"
50 #include "webbrowser.h"
51
52
53 static gint fetch_enum_value(gpointer control, const enum_val_t *enumvals);
54 static gint fileopen_dir_changed_cb(GtkWidget *myentry _U_, GdkEvent *event, gpointer parent_w);
55 static gint fileopen_preview_changed_cb(GtkWidget *myentry _U_, GdkEvent *event, gpointer parent_w);
56 static void fileopen_selected_cb(GtkWidget *mybutton_rb _U_, gpointer parent_w);
57 static gint recent_files_count_changed_cb(GtkWidget *recent_files_entry _U_, 
58                                           GdkEvent *event _U_, gpointer parent_w);
59
60 #define SCROLLBAR_PLACEMENT_KEY         "scrollbar_placement"
61 #define PLIST_SEL_BROWSE_KEY            "plist_sel_browse"
62 #define PTREE_SEL_BROWSE_KEY            "ptree_sel_browse"
63 #if GTK_MAJOR_VERSION < 2
64 #define PTREE_LINE_STYLE_KEY            "ptree_line_style"
65 #define PTREE_EXPANDER_STYLE_KEY        "ptree_expander_style"
66 #else
67 #define ALTERN_COLORS_KEY               "altern_colors"
68 #endif
69 #define FILTER_TOOLBAR_PLACEMENT_KEY    "filter_toolbar_show_in_statusbar"
70 #define HEX_DUMP_HIGHLIGHT_STYLE_KEY    "hex_dump_highlight_style"
71 #define GEOMETRY_POSITION_KEY           "geometry_position"
72 #define GEOMETRY_SIZE_KEY               "geometry_size"
73 #define GEOMETRY_MAXIMIZED_KEY          "geometry_maximized"
74
75 #define GUI_CONSOLE_OPEN_KEY "console_open"
76 #define GUI_FILEOPEN_KEY        "fileopen_behavior"
77 #define GUI_FILEOPEN_PREVIEW_KEY "fileopen_preview_timeout"
78 #define GUI_RECENT_FILES_COUNT_KEY "recent_files_count"
79 #define GUI_FILEOPEN_DIR_KEY    "fileopen_directory"
80 #define GUI_ASK_UNSAVED_KEY     "ask_unsaved"
81 #define GUI_WEBBROWSER_KEY          "webbrowser"
82 #define GUI_FIND_WRAP_KEY       "find_wrap"
83 #define GUI_WINDOW_TITLE_KEY    "window_title"
84
85 #define GUI_TOOLBAR_STYLE_KEY   "toolbar_style"
86
87 static const enum_val_t scrollbar_placement_vals[] = {
88         { "FALSE", "Left", FALSE },
89         { "TRUE",  "Right", TRUE },
90         { NULL,    NULL,    0 }
91 };
92
93 static const enum_val_t selection_mode_vals[] = {
94         { "FALSE", "Selects", FALSE },
95         { "TRUE",  "Browses", TRUE },
96         { NULL,    NULL,      0 }
97 };
98
99 #if GTK_MAJOR_VERSION < 2
100 static const enum_val_t line_style_vals[] = {
101         { "NONE",   "None",   0 },
102         { "SOLID",  "Solid",  1 },
103         { "DOTTED", "Dotted", 2 },
104         { "TABBED", "Tabbed", 3 },
105         { NULL,     NULL,     0 }
106 };
107
108 static const enum_val_t expander_style_vals[] = {
109         { "NONE",     "None",     0 },
110         { "SQUARE",   "Square",   1 },
111         { "TRIANGLE", "Triangle", 2 },
112         { "CIRCULAR", "Circular", 3 },
113         { NULL,       NULL,       0 }
114 };
115 #else
116 static const enum_val_t altern_colors_vals[] = {
117         { "FALSE", "No",  FALSE },
118         { "TRUE",  "Yes", TRUE },
119         { NULL,    NULL,  0 }
120 };
121 #endif
122
123 static const enum_val_t filter_toolbar_placement_vals[] = {
124         { "FALSE", "Below the main toolbar", FALSE },
125         { "TRUE",  "Insert into statusbar",  TRUE },
126         { NULL,    NULL,                     0 }
127 };
128
129 static const enum_val_t highlight_style_vals[] = {
130         { "FALSE", "Bold",     FALSE },
131         { "TRUE",  "Inverse",  TRUE },
132         { NULL,    NULL,       0 }
133 };
134
135
136 static const enum_val_t toolbar_style_vals[] = {
137         { "ICONS", "Icons only",     TB_STYLE_ICONS },
138         { "TEXT",  "Text only",      TB_STYLE_TEXT },
139         { "BOTH",  "Icons & Text",   TB_STYLE_BOTH },
140         { NULL,    NULL,             0 }
141 };
142
143 #ifdef _WIN32
144 static const enum_val_t gui_console_open_vals[] = {
145         { "NEVER",     "Never",                      console_open_never },
146         { "AUTOMATIC", "Automatic (advanced user)",  console_open_auto },
147         { "ALWAYS",    "Always (debugging)",         console_open_always },
148         { NULL,        NULL,                         0 }
149 };
150 #endif
151
152 static const enum_val_t gui_fileopen_vals[] = {
153         { "LAST_OPENED", "Remember last directory", FO_STYLE_LAST_OPENED },
154         { "SPECIFIED",   "Always start in:",        FO_STYLE_SPECIFIED },
155         { NULL,          NULL,                      0 }
156 };
157
158 /* Set to FALSE initially; set to TRUE if the user ever hits "OK" on
159    the "Font..." dialog, so that we know that they (probably) changed
160    the font, and therefore that the "apply" function needs to take care
161    of that */
162 static gboolean font_changed;
163
164 /* Font name from the font dialog box; if "font_changed" is TRUE, this
165    has been set to the name of the font the user selected. */
166 static gchar *new_font_name;
167
168 static GtkWidget *font_browse_w;
169
170 /* Used to contain the string from the Recent Files Count Max pref item */
171 static char recent_files_count_max_str[128] = "";
172
173 /* Used to contain the string from the Open File preview timeout pref item */
174 static char open_file_preview_str[128] = "";
175
176 #if GTK_MAJOR_VERSION < 2
177 #define GUI_TABLE_ROWS 11
178 #else
179 #define GUI_TABLE_ROWS 10
180 #endif
181
182 GtkWidget*
183 gui_prefs_show(void)
184 {
185         GtkWidget *main_tb, *main_vb, *hbox;
186         GtkWidget *scrollbar_om, *plist_browse_om;
187         GtkWidget *ptree_browse_om, *highlight_style_om;
188 #ifdef _WIN32
189         GtkWidget *console_open_om;
190 #endif
191         GtkWidget *fileopen_rb, *fileopen_dir_te, *fileopen_preview_te;
192         GtkWidget *toolbar_style_om;
193     GtkWidget *filter_toolbar_placement_om;
194         GtkWidget *recent_files_count_max_te, *ask_unsaved_cb, *find_wrap_cb;
195     GtkWidget *webbrowser_te;
196     GtkWidget *window_title_te;
197         GtkWidget *save_position_cb, *save_size_cb, *save_maximized_cb;
198 #if GTK_MAJOR_VERSION < 2
199         GtkWidget *expander_style_om, *line_style_om;
200 #else
201         GtkWidget *altern_colors_om;
202 #endif
203         int        pos = 0;
204         char       current_val_str[128];
205
206         /* The font haven't been changed yet. */
207         font_changed = FALSE;
208
209         /* Main vertical box */
210         main_vb = gtk_vbox_new(FALSE, 7);
211         gtk_container_border_width( GTK_CONTAINER(main_vb), 5 );
212
213         /* Main horizontal box  */
214         /* XXX - Is there a better way to center the table? */
215         hbox = gtk_hbox_new(FALSE, 7);
216         gtk_box_pack_start (GTK_BOX(main_vb), hbox, TRUE, FALSE, 0);
217
218         /* Main table */
219         main_tb = gtk_table_new(GUI_TABLE_ROWS, 2, FALSE);
220         gtk_box_pack_start( GTK_BOX(hbox), main_tb, TRUE, FALSE, 0 );
221         gtk_table_set_row_spacings( GTK_TABLE(main_tb), 10 );
222         gtk_table_set_col_spacings( GTK_TABLE(main_tb), 15 );
223         gtk_table_set_col_spacing( GTK_TABLE(main_tb), 0, 50 );
224
225         /* Scrollbar placement */
226         scrollbar_om = create_preference_option_menu(main_tb, pos++,
227             "Vertical scrollbar placement:", NULL, scrollbar_placement_vals,
228             prefs.gui_scrollbar_on_right);
229         OBJECT_SET_DATA(main_vb, SCROLLBAR_PLACEMENT_KEY, scrollbar_om);
230
231         /* Packet list selection browseable */
232         plist_browse_om = create_preference_option_menu(main_tb, pos++,
233             "Packet list selection mode:", NULL, selection_mode_vals,
234             prefs.gui_plist_sel_browse);
235         OBJECT_SET_DATA(main_vb, PLIST_SEL_BROWSE_KEY, plist_browse_om);
236
237         /* Proto tree selection browseable */
238         ptree_browse_om = create_preference_option_menu(main_tb, pos++,
239             "Protocol tree selection mode:", NULL, selection_mode_vals,
240             prefs.gui_ptree_sel_browse);
241         OBJECT_SET_DATA(main_vb, PTREE_SEL_BROWSE_KEY, ptree_browse_om);
242
243 #if GTK_MAJOR_VERSION < 2
244         /* Tree line style */
245         line_style_om = create_preference_option_menu(main_tb, pos++,
246             "Tree line style:", NULL, line_style_vals,
247             prefs.gui_ptree_line_style);
248         OBJECT_SET_DATA(main_vb, PTREE_LINE_STYLE_KEY, line_style_om);
249
250         /* Tree expander style */
251         expander_style_om = create_preference_option_menu(main_tb, pos++,
252             "Tree expander style:", NULL, expander_style_vals,
253             prefs.gui_ptree_expander_style);
254         OBJECT_SET_DATA(main_vb, PTREE_EXPANDER_STYLE_KEY, expander_style_om);
255 #else
256         /* Alternating row colors in list and tree views */
257         altern_colors_om = create_preference_option_menu(main_tb, pos++,
258             "Alternating row colors in lists and trees:", NULL,
259             altern_colors_vals, prefs.gui_altern_colors);
260         OBJECT_SET_DATA(main_vb, ALTERN_COLORS_KEY, altern_colors_om);
261 #endif
262
263         /* Hex Dump highlight style */
264         highlight_style_om = create_preference_option_menu(main_tb, pos++,
265             "Hex display highlight style:", NULL, highlight_style_vals,
266             prefs.gui_hex_dump_highlight_style);
267         OBJECT_SET_DATA(main_vb, HEX_DUMP_HIGHLIGHT_STYLE_KEY,
268             highlight_style_om);
269
270         /* Toolbar prefs */
271         toolbar_style_om = create_preference_option_menu(main_tb, pos++,
272             "Toolbar style:", NULL, toolbar_style_vals,
273             prefs.gui_toolbar_main_style);
274         OBJECT_SET_DATA(main_vb, GUI_TOOLBAR_STYLE_KEY,
275             toolbar_style_om);
276
277     /* Placement of Filter toolbar */
278     filter_toolbar_placement_om = create_preference_option_menu(main_tb, pos++,
279        "Filter toolbar placement:", NULL,
280        filter_toolbar_placement_vals, prefs.filter_toolbar_show_in_statusbar);
281     OBJECT_SET_DATA(main_vb, FILTER_TOOLBAR_PLACEMENT_KEY, filter_toolbar_placement_om);
282
283         /* Geometry prefs */
284         save_position_cb = create_preference_check_button(main_tb, pos++,
285             "Save window position:", NULL, prefs.gui_geometry_save_position);
286         OBJECT_SET_DATA(main_vb, GEOMETRY_POSITION_KEY, save_position_cb);
287
288         save_size_cb = create_preference_check_button(main_tb, pos++,
289             "Save window size:", NULL, prefs.gui_geometry_save_size);
290         OBJECT_SET_DATA(main_vb, GEOMETRY_SIZE_KEY, save_size_cb);
291
292         save_maximized_cb = create_preference_check_button(main_tb, pos++,
293             "Save maximized state:", NULL, prefs.gui_geometry_save_maximized);
294         OBJECT_SET_DATA(main_vb, GEOMETRY_MAXIMIZED_KEY, save_maximized_cb);
295
296 #ifdef _WIN32
297         /* How the console window should be opened */
298     console_open_om = create_preference_option_menu(main_tb, pos++,
299        "Open a console window", NULL,
300        gui_console_open_vals, prefs.gui_console_open);
301         OBJECT_SET_DATA(main_vb, GUI_CONSOLE_OPEN_KEY, console_open_om);
302 #endif
303
304         /* Allow user to select where they want the File Open dialog to open to
305          * by default */
306         fileopen_rb = create_preference_radio_buttons(main_tb, pos++,
307             "\"File Open\" dialog behavior:", NULL, gui_fileopen_vals,
308             prefs.gui_fileopen_style);
309
310         /* Directory to default File Open dialog to */
311         fileopen_dir_te = create_preference_entry(main_tb, pos++, 
312         "Directory:", NULL, prefs.gui_fileopen_dir);
313         OBJECT_SET_DATA(main_vb, GUI_FILEOPEN_KEY, fileopen_rb);
314         OBJECT_SET_DATA(main_vb, GUI_FILEOPEN_DIR_KEY, fileopen_dir_te);
315         SIGNAL_CONNECT(fileopen_rb, "clicked", fileopen_selected_cb, main_vb);
316         SIGNAL_CONNECT(fileopen_dir_te, "focus-out-event",
317             fileopen_dir_changed_cb, main_vb);
318
319         /* File Open dialog preview timeout */
320         fileopen_preview_te = create_preference_entry(main_tb, pos++,
321             "\"File Open\" preview timeout:", "Timeout, until preview gives up scanning the capture file content.", open_file_preview_str);
322         g_snprintf(current_val_str, 128, "%d", prefs.gui_fileopen_preview);
323         gtk_entry_set_text(GTK_ENTRY(fileopen_preview_te), current_val_str);
324         OBJECT_SET_DATA(main_vb, GUI_FILEOPEN_PREVIEW_KEY, fileopen_preview_te);
325         SIGNAL_CONNECT(fileopen_preview_te, "focus_out_event", fileopen_preview_changed_cb, main_vb);
326
327         /* Number of entries in the recent_files list ... */
328         recent_files_count_max_te = create_preference_entry(main_tb, pos++,
329             "\"Open Recent\" max. list entries:", "Maximum number of recent files", recent_files_count_max_str);
330         g_snprintf(current_val_str, 128, "%d", prefs.gui_recent_files_count_max);
331         gtk_entry_set_text(GTK_ENTRY(recent_files_count_max_te), current_val_str);
332         OBJECT_SET_DATA(main_vb, GUI_RECENT_FILES_COUNT_KEY, recent_files_count_max_te);
333         SIGNAL_CONNECT(recent_files_count_max_te, "focus_out_event", recent_files_count_changed_cb, main_vb);
334
335         fileopen_selected_cb(NULL, main_vb);        
336
337     /* ask for unsaved capture files? */
338         ask_unsaved_cb = create_preference_check_button(main_tb, pos++,
339             "Ask for unsaved capture files:", NULL, prefs.gui_ask_unsaved);
340         OBJECT_SET_DATA(main_vb, GUI_ASK_UNSAVED_KEY, ask_unsaved_cb);
341
342     /* do we want to wrap when searching for data? */
343         find_wrap_cb = create_preference_check_button(main_tb, pos++,
344             "Wrap to end/beginning of file during a find:", NULL, prefs.gui_find_wrap);
345         OBJECT_SET_DATA(main_vb, GUI_FIND_WRAP_KEY, find_wrap_cb);
346
347         /* Webbrowser */
348     if (browser_needs_pref()) {
349             webbrowser_te = create_preference_entry(main_tb, pos++, 
350             "Web browser command:", NULL, prefs.gui_webbrowser);
351             gtk_entry_set_text(GTK_ENTRY(webbrowser_te), prefs.gui_webbrowser);
352             OBJECT_SET_DATA(main_vb, GUI_WEBBROWSER_KEY, webbrowser_te);
353     }
354
355         /* Window title */
356     window_title_te = create_preference_entry(main_tb, pos++,
357         "Custom window title (prepended to existing titles):", NULL, prefs.gui_window_title);
358     gtk_entry_set_text(GTK_ENTRY(window_title_te), prefs.gui_window_title);
359     OBJECT_SET_DATA(main_vb, GUI_WINDOW_TITLE_KEY, window_title_te);
360
361         /* Show 'em what we got */
362         gtk_widget_show_all(main_vb);
363
364         return(main_vb);
365 }
366
367
368 /* Create a font widget for browsing. */
369 GtkWidget *
370 gui_font_prefs_show(void)
371 {
372         /* Create the font selection widget. */
373         font_browse_w = (GtkWidget *) gtk_font_selection_new();
374         gtk_widget_show(font_browse_w);
375
376         return font_browse_w;
377 }
378
379
380 static gboolean
381 font_fetch(void)
382 {
383         gchar   *font_name;
384
385         font_name = g_strdup(gtk_font_selection_get_font_name(
386               GTK_FONT_SELECTION(font_browse_w)));
387         if (font_name == NULL) {
388                 /* No font was selected; let the user know, but don't
389                    tear down the font selection dialog, so they can
390                    try again. */
391                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
392                    "You have not selected a font.");
393                 return FALSE;
394         }
395
396         if (!user_font_test(font_name)) {
397                 /* The font isn't usable; "user_font_test()" has already
398                    told the user why.  Don't tear down the font selection
399                    dialog. */
400                 g_free(font_name);
401                 return FALSE;
402         }
403         new_font_name = font_name;
404         return TRUE;
405 }
406
407
408 static gint
409 fetch_enum_value(gpointer control, const enum_val_t *enumvals)
410 {
411         return fetch_preference_option_menu_val(GTK_WIDGET(control), enumvals);
412 }
413
414 void
415 gui_prefs_fetch(GtkWidget *w)
416 {
417         prefs.gui_scrollbar_on_right = fetch_enum_value(
418             OBJECT_GET_DATA(w, SCROLLBAR_PLACEMENT_KEY),
419             scrollbar_placement_vals);
420         prefs.gui_plist_sel_browse = fetch_enum_value(
421             OBJECT_GET_DATA(w, PLIST_SEL_BROWSE_KEY), selection_mode_vals);
422         prefs.gui_ptree_sel_browse = fetch_enum_value(
423             OBJECT_GET_DATA(w, PTREE_SEL_BROWSE_KEY), selection_mode_vals);
424 #if GTK_MAJOR_VERSION < 2
425         prefs.gui_ptree_line_style = fetch_enum_value(
426             OBJECT_GET_DATA(w, PTREE_LINE_STYLE_KEY), line_style_vals);
427         prefs.gui_ptree_expander_style = fetch_enum_value(
428             OBJECT_GET_DATA(w, PTREE_EXPANDER_STYLE_KEY), expander_style_vals);
429 #else
430         prefs.gui_altern_colors = fetch_enum_value(
431             OBJECT_GET_DATA(w, ALTERN_COLORS_KEY), altern_colors_vals);
432 #endif
433     prefs.filter_toolbar_show_in_statusbar = fetch_enum_value(
434         OBJECT_GET_DATA(w, FILTER_TOOLBAR_PLACEMENT_KEY), filter_toolbar_placement_vals);
435         prefs.gui_hex_dump_highlight_style = fetch_enum_value(
436             OBJECT_GET_DATA(w, HEX_DUMP_HIGHLIGHT_STYLE_KEY),
437             highlight_style_vals);
438         prefs.gui_toolbar_main_style = fetch_enum_value(
439             OBJECT_GET_DATA(w, GUI_TOOLBAR_STYLE_KEY),
440             toolbar_style_vals);        
441         prefs.gui_geometry_save_position =
442             gtk_toggle_button_get_active(OBJECT_GET_DATA(w,
443                 GEOMETRY_POSITION_KEY));
444         prefs.gui_geometry_save_size =
445             gtk_toggle_button_get_active(OBJECT_GET_DATA(w, GEOMETRY_SIZE_KEY));
446         prefs.gui_geometry_save_maximized =
447             gtk_toggle_button_get_active(OBJECT_GET_DATA(w, GEOMETRY_MAXIMIZED_KEY));
448 #ifdef _WIN32
449         prefs.gui_console_open = fetch_enum_value(
450             OBJECT_GET_DATA(w, GUI_CONSOLE_OPEN_KEY), gui_console_open_vals);
451 #endif
452         prefs.gui_fileopen_style = fetch_preference_radio_buttons_val(
453             OBJECT_GET_DATA(w, GUI_FILEOPEN_KEY), gui_fileopen_vals);
454             
455         if (prefs.gui_fileopen_dir != NULL)
456                 g_free(prefs.gui_fileopen_dir);
457         prefs.gui_fileopen_dir = g_strdup(gtk_entry_get_text(
458                 GTK_ENTRY(OBJECT_GET_DATA(w, GUI_FILEOPEN_DIR_KEY))));
459
460     prefs.gui_ask_unsaved = 
461             gtk_toggle_button_get_active(OBJECT_GET_DATA(w, GUI_ASK_UNSAVED_KEY));
462
463     prefs.gui_find_wrap = 
464             gtk_toggle_button_get_active(OBJECT_GET_DATA(w, GUI_FIND_WRAP_KEY));
465     
466     if (browser_needs_pref()) {
467                 g_free(prefs.gui_webbrowser);
468             prefs.gui_webbrowser = g_strdup(gtk_entry_get_text(
469                     GTK_ENTRY(OBJECT_GET_DATA(w, GUI_WEBBROWSER_KEY))));
470     }
471
472     if (prefs.gui_window_title != NULL)
473                 g_free(prefs.gui_window_title);
474         prefs.gui_window_title = g_strdup(gtk_entry_get_text(
475                 GTK_ENTRY(OBJECT_GET_DATA(w, GUI_WINDOW_TITLE_KEY))));
476
477         /*
478          * XXX - we need to have a way to fetch the preferences into
479          * local storage and only set the permanent preferences if there
480          * weren't any errors in those fetches, as there are several
481          * places where there *can* be a bad preference value.
482          */
483         if (font_fetch()) {
484                 if (strcmp(new_font_name, prefs.PREFS_GUI_FONT_NAME) != 0) {
485                         font_changed = TRUE;
486                         if (prefs.PREFS_GUI_FONT_NAME != NULL)
487                                 g_free(prefs.PREFS_GUI_FONT_NAME);
488                         prefs.PREFS_GUI_FONT_NAME = g_strdup(new_font_name);
489                 }
490         }
491 }
492
493
494
495 void
496 gui_prefs_apply(GtkWidget *w _U_)
497 {
498
499 #ifdef _WIN32
500     /* user immediately wants to see a console */
501     if (prefs.gui_console_open == console_open_always) {
502         create_console();
503     }
504 #endif
505
506         if (font_changed) {
507                 /* This redraws the hex dump windows. */
508                 switch (user_font_apply()) {
509
510                 case FA_SUCCESS:
511                         break;
512
513                 case FA_FONT_NOT_RESIZEABLE:
514                         /* "user_font_apply()" popped up an alert box. */
515                         /* turn off zooming - font can't be resized */
516                         recent.gui_zoom_level = 0;
517                         break;
518
519                 case FA_FONT_NOT_AVAILABLE:
520                         /* We assume this means that the specified size
521                            isn't available. */
522                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
523                             "That font isn't available at the specified zoom level;\n"
524                             "turning zooming off.");
525                         recent.gui_zoom_level = 0;
526                         break;
527                 }
528         } else {
529                 /* Redraw the hex dump windows, in case the
530                    highlight style changed.
531                    XXX - do it only if the highlight style *did* change. */
532                 redraw_hex_dump_all();
533         }
534
535         /* Redraw the help window(s). */
536         supported_redraw();
537         help_redraw();
538
539         /* XXX: redraw the toolbar only, if style changed */
540         toolbar_redraw_all();
541         
542         set_scrollbar_placement_all();
543         set_plist_sel_browse(prefs.gui_plist_sel_browse);
544         set_ptree_sel_browse_all(prefs.gui_ptree_sel_browse);
545         set_tree_styles_all();
546     main_widgets_rearrange();
547 }
548
549 void
550 gui_prefs_destroy(GtkWidget *w _U_)
551 {
552         /* Free up any saved font name. */
553         if (new_font_name != NULL) {
554                 g_free(new_font_name);
555                 new_font_name = NULL;
556         }
557 }
558
559
560 static gint
561 recent_files_count_changed_cb(GtkWidget *recent_files_entry _U_, 
562                               GdkEvent *event _U_, gpointer parent_w)
563 {
564     GtkWidget   *recent_files_count_te;
565     guint newval;
566     
567     recent_files_count_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_RECENT_FILES_COUNT_KEY);
568
569     /*
570      * Now, just convert the string to a number and store it in the prefs
571      * filed ...
572      */
573
574     newval = strtol(gtk_entry_get_text (GTK_ENTRY(recent_files_count_te)), NULL, 10);
575
576     if (newval > 0) {
577       prefs.gui_recent_files_count_max = newval;
578     }
579
580     /* We really should pop up a nasty dialog box if newval <= 0 */
581
582     return FALSE;
583 }
584
585 static gint
586 fileopen_preview_changed_cb(GtkWidget *recent_files_entry _U_, 
587                               GdkEvent *event _U_, gpointer parent_w)
588 {
589     GtkWidget   *fileopen_preview_te;
590     guint newval;
591     
592     fileopen_preview_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_FILEOPEN_PREVIEW_KEY);
593
594     /*
595      * Now, just convert the string to a number and store it in the prefs
596      * filed ...
597      */
598
599     newval = strtol(gtk_entry_get_text (GTK_ENTRY(fileopen_preview_te)), NULL, 10);
600
601     if (newval > 0) {
602       prefs.gui_fileopen_preview = newval;
603     }
604
605     /* We really should pop up a nasty dialog box if newval <= 0 */
606
607     return FALSE;
608 }
609
610 static gint
611 fileopen_dir_changed_cb(GtkWidget *fileopen_entry _U_, GdkEvent *event _U_, gpointer parent_w)
612 {
613     GtkWidget   *fileopen_dir_te;
614     char *lastchar;
615     gint fileopen_dir_te_length;
616     
617     fileopen_dir_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_FILEOPEN_DIR_KEY);
618     fileopen_dir_te_length = strlen(gtk_entry_get_text (GTK_ENTRY(fileopen_entry)));
619     if (fileopen_dir_te_length == 0)
620         return FALSE;
621     lastchar = gtk_editable_get_chars(GTK_EDITABLE(fileopen_entry), fileopen_dir_te_length-1, -1);
622     if (strcmp(lastchar, G_DIR_SEPARATOR_S) != 0)
623         gtk_entry_append_text(GTK_ENTRY(fileopen_entry), G_DIR_SEPARATOR_S);
624     return FALSE;
625 }
626
627 static void
628 fileopen_selected_cb(GtkWidget *mybutton_rb _U_, gpointer parent_w)
629 {
630     GtkWidget   *fileopen_rb, *fileopen_dir_te;
631     
632     fileopen_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_FILEOPEN_KEY);
633     fileopen_dir_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, GUI_FILEOPEN_DIR_KEY);
634     
635     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fileopen_rb)))
636     {
637         gtk_widget_set_sensitive(GTK_WIDGET(fileopen_dir_te), TRUE);
638     }
639     else
640     {
641         gtk_widget_set_sensitive(GTK_WIDGET(fileopen_dir_te), FALSE);
642     }
643     return;
644 }
645