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