some more : try to make read/write not break the build if the return value is not...
[obnox/wireshark/wip.git] / gtk / layout_prefs.c
1 /* layout_prefs.c
2  * Dialog box for layout 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 "globals.h"
32 #include "layout_prefs.h"
33 #include "gtkglobals.h"
34 #include <epan/prefs.h>
35 #include "prefs_dlg.h"
36 #include "gui_utils.h"
37 #include "main.h"
38 #include "compat_macros.h"
39 #include "dlg_utils.h"
40 #include "../ui_util.h"
41
42 #include "../image/icon_layout_1.xpm"
43 #include "../image/icon_layout_2.xpm"
44 #include "../image/icon_layout_3.xpm"
45 #include "../image/icon_layout_4.xpm"
46 #include "../image/icon_layout_5.xpm"
47 #include "../image/icon_layout_6.xpm"
48
49 #define LAYOUT_QTY (layout_type_max - 1)
50
51
52 static void layout_validate_cb(GtkWidget *w _U_, gpointer data);
53 static gint fetch_enum_value(gpointer control, const enum_val_t *enumvals);
54
55
56 typedef struct {
57     layout_type_e           type;
58     layout_pane_content_e   content[3];
59 } layout_t;
60
61
62 #define LAYOUT_TYPE_BUTTONS_KEY     "layout_type_buttons"
63
64 #define LAYOUT_NONE_RB_KEY          "layout_none_radio_button"
65 #define LAYOUT_PLIST_RB_KEY         "layout_plist_radio_button"
66 #define LAYOUT_PDETAILS_RB_KEY      "layout_pdetails_radio_button"
67 #define LAYOUT_PBYTES_RB_KEY        "layout_pbytes_radio_button"
68
69 #define LAYOUT_CONTENT1_VB_KEY      "layout_content1_vbox"
70 #define LAYOUT_CONTENT2_VB_KEY      "layout_content2_vbox"
71 #define LAYOUT_CONTENT3_VB_KEY      "layout_content3_vbox"
72
73
74 static GtkWidget *layout_content_radio_vbox(GtkWidget *main_vb, GtkTooltips *tooltips, int i, layout_pane_content_e content) {
75     GtkWidget   *radio_vb, *radio_lb;
76     GtkWidget   *radio_none_rb, *radio_plist_rb, *radio_pdetails_rb, *radio_pbytes_rb;
77     char buf[64];
78
79
80     /* radio vbox */
81     radio_vb = gtk_vbox_new(FALSE, 0);
82     gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
83
84     g_snprintf (buf, sizeof(buf), "Pane %d:", i);
85     radio_lb = gtk_label_new(buf);
86     gtk_misc_set_alignment(GTK_MISC(radio_lb), 0.0, 0.5);
87     gtk_container_add(GTK_CONTAINER(radio_vb), radio_lb);
88
89     radio_none_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "None", NULL);
90     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(radio_none_rb), content == layout_pane_content_none);
91     gtk_tooltips_set_tip (tooltips, radio_none_rb, "Put nothing in this pane.", NULL);
92     gtk_container_add(GTK_CONTAINER(radio_vb), radio_none_rb);
93
94     radio_plist_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(radio_none_rb, "Packet List", NULL);
95     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(radio_plist_rb), content == layout_pane_content_plist);
96     gtk_tooltips_set_tip (tooltips, radio_plist_rb, "Put the packet list in this pane.", NULL);
97     gtk_container_add(GTK_CONTAINER(radio_vb), radio_plist_rb);
98
99     radio_pdetails_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(radio_none_rb, "Packet Details", NULL);
100     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(radio_pdetails_rb), content == layout_pane_content_pdetails);
101     gtk_tooltips_set_tip (tooltips, radio_pdetails_rb, "Put the packet details tree in this pane.", NULL);
102     gtk_container_add(GTK_CONTAINER(radio_vb), radio_pdetails_rb);
103
104     radio_pbytes_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(radio_none_rb, "Packet Bytes", NULL);
105     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(radio_pbytes_rb), content == layout_pane_content_pbytes);
106     gtk_tooltips_set_tip (tooltips, radio_pbytes_rb, "Put the packet bytes hexdump in this pane.", NULL);
107     gtk_container_add(GTK_CONTAINER(radio_vb), radio_pbytes_rb);
108
109     OBJECT_SET_DATA(radio_vb, LAYOUT_NONE_RB_KEY,       radio_none_rb);
110     OBJECT_SET_DATA(radio_vb, LAYOUT_PLIST_RB_KEY,      radio_plist_rb);
111     OBJECT_SET_DATA(radio_vb, LAYOUT_PDETAILS_RB_KEY,   radio_pdetails_rb);
112     OBJECT_SET_DATA(radio_vb, LAYOUT_PBYTES_RB_KEY,     radio_pbytes_rb);
113
114     SIGNAL_CONNECT(radio_none_rb,       "toggled", layout_validate_cb, main_vb);
115     SIGNAL_CONNECT(radio_plist_rb,      "toggled", layout_validate_cb, main_vb);
116     SIGNAL_CONNECT(radio_pdetails_rb,   "toggled", layout_validate_cb, main_vb);
117     SIGNAL_CONNECT(radio_pbytes_rb,     "toggled", layout_validate_cb, main_vb);
118
119     return radio_vb;
120 }
121
122 static void
123 layout_type_changed_cb (GtkToggleButton * togglebutton, gpointer user_data)
124 {
125         GtkWidget ** layout_type_buttons = (GtkWidget**) user_data;
126         static gboolean dampen_feedback_loop = FALSE;
127
128         if (!dampen_feedback_loop) {
129                 int i;
130                 dampen_feedback_loop = TRUE;
131                 for (i=0; i<LAYOUT_QTY; ++i) {
132                         GtkToggleButton * tb = GTK_TOGGLE_BUTTON(layout_type_buttons[i]);
133                         gboolean active = togglebutton==tb;
134                         if (gtk_toggle_button_get_active(tb) != active)
135                                 gtk_toggle_button_set_active (tb, active);
136                 }
137                 dampen_feedback_loop = FALSE;
138         }
139 }
140
141
142 static layout_pane_content_e  layout_pane_get_content(GtkWidget * radio_vb) {
143
144     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_NONE_RB_KEY))))
145         return layout_pane_content_none;
146     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PLIST_RB_KEY))))
147         return layout_pane_content_plist;
148     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PDETAILS_RB_KEY))))
149         return layout_pane_content_pdetails;
150     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PBYTES_RB_KEY))))
151         return layout_pane_content_pbytes;
152
153     g_assert_not_reached();
154     return -1;
155 }
156
157 static void layout_pane_set_content(GtkWidget * radio_vb, layout_pane_content_e pane_content) {
158
159
160     switch(pane_content) {
161     case(layout_pane_content_none):
162         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_NONE_RB_KEY)), TRUE);
163         break;
164     case(layout_pane_content_plist):
165         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PLIST_RB_KEY)), TRUE);
166         break;
167     case(layout_pane_content_pdetails):
168         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PDETAILS_RB_KEY)), TRUE);
169         break;
170     case(layout_pane_content_pbytes):
171         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PBYTES_RB_KEY)), TRUE);
172         break;
173     default:
174         g_assert_not_reached();
175     }
176 }
177
178
179
180 static void layout_set(GtkWidget * main_vb, layout_t *layout) {
181     GtkWidget   *radio_vb;
182     GtkWidget ** layout_type_buttons = OBJECT_GET_DATA(main_vb, LAYOUT_TYPE_BUTTONS_KEY);
183
184     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(layout_type_buttons[layout->type - 1]), TRUE);
185
186     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT1_VB_KEY);
187     layout_pane_set_content(radio_vb, layout->content[0]);
188     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT2_VB_KEY);
189     layout_pane_set_content(radio_vb, layout->content[1]);
190     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT3_VB_KEY);
191     layout_pane_set_content(radio_vb, layout->content[2]);
192 }
193
194 static void layout_get(GtkWidget * main_vb, layout_t *layout_out) {
195     GtkWidget   *radio_vb;
196     GtkWidget ** layout_type_buttons = OBJECT_GET_DATA(main_vb, LAYOUT_TYPE_BUTTONS_KEY);
197     int i;
198
199     for (i=0; i<LAYOUT_QTY; ++i) {
200         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(layout_type_buttons[i]))) {
201             layout_out->type = i + 1;
202             break;
203         }
204     }
205
206     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT1_VB_KEY);
207     layout_out->content[0] = layout_pane_get_content(radio_vb);
208     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT2_VB_KEY);
209     layout_out->content[1] = layout_pane_get_content(radio_vb);
210     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT3_VB_KEY);
211     layout_out->content[2] = layout_pane_get_content(radio_vb);
212 }
213
214 static void layout_validate(layout_t *layout) {
215
216     if(layout->content[1] == layout->content[0]) {
217         layout->content[1] = layout_pane_content_none;
218     }
219     if(layout->content[2] == layout->content[0] || layout->content[2] == layout->content[1]) {
220         layout->content[2] = layout_pane_content_none;
221     }
222 }
223
224
225 static void layout_validate_cb(GtkWidget *w _U_, gpointer data) {
226     layout_t    layout;
227
228     layout_get(data, &layout);
229     layout_validate(&layout);
230     layout_set(data, &layout);
231 }
232
233 static void
234 layout_defaults_cb (GtkWidget * w _U_, gpointer data _U_)
235 {
236     layout_t default_layout = { 
237         layout_type_5,
238         {
239             layout_pane_content_plist,
240             layout_pane_content_pdetails,
241             layout_pane_content_pbytes
242         }
243     };
244
245     layout_set(data, &default_layout);
246 }
247
248 #define SCROLLBAR_PLACEMENT_KEY         "scrollbar_placement"
249 #if GTK_MAJOR_VERSION < 2
250 #define PTREE_LINE_STYLE_KEY            "ptree_line_style"
251 #define PTREE_EXPANDER_STYLE_KEY        "ptree_expander_style"
252 #else
253 #define ALTERN_COLORS_KEY               "altern_colors"
254 #endif
255 #define HEX_DUMP_HIGHLIGHT_STYLE_KEY    "hex_dump_highlight_style"
256 #define FILTER_TOOLBAR_PLACEMENT_KEY    "filter_toolbar_show_in_statusbar"
257 #define GUI_TOOLBAR_STYLE_KEY           "toolbar_style"
258 #define GUI_WINDOW_TITLE_KEY            "window_title"
259
260
261 #if GTK_MAJOR_VERSION < 2
262 #define GUI_TABLE_ROWS 6
263 #else
264 #define GUI_TABLE_ROWS 5
265 #endif
266
267 static const enum_val_t scrollbar_placement_vals[] = {
268     { "FALSE", "Left", FALSE },
269     { "TRUE",  "Right", TRUE },
270     { NULL,    NULL,    0 }
271 };
272 #if GTK_MAJOR_VERSION < 2
273 static const enum_val_t line_style_vals[] = {
274     { "NONE",   "None",   0 },
275     { "SOLID",  "Solid",  1 },
276     { "DOTTED", "Dotted", 2 },
277     { "TABBED", "Tabbed", 3 },
278     { NULL,     NULL,     0 }
279 };
280
281 static const enum_val_t expander_style_vals[] = {
282     { "NONE",     "None",     0 },
283     { "SQUARE",   "Square",   1 },
284     { "TRIANGLE", "Triangle", 2 },
285     { "CIRCULAR", "Circular", 3 },
286     { NULL,       NULL,       0 }
287 };
288 #else
289 static const enum_val_t altern_colors_vals[] = {
290     { "FALSE", "No",  FALSE },
291     { "TRUE",  "Yes", TRUE },
292     { NULL,    NULL,  0 }
293 };
294 #endif
295 static const enum_val_t highlight_style_vals[] = {
296     { "FALSE", "Bold",     FALSE },
297     { "TRUE",  "Inverse",  TRUE },
298     { NULL,    NULL,       0 }
299 };
300 static const enum_val_t filter_toolbar_placement_vals[] = {
301     { "FALSE", "Below the main toolbar", FALSE },
302     { "TRUE",  "Insert into statusbar",  TRUE },
303     { NULL,    NULL,                     0 }
304 };
305 static const enum_val_t toolbar_style_vals[] = {
306     { "ICONS", "Icons only",     TB_STYLE_ICONS },
307     { "TEXT",  "Text only",      TB_STYLE_TEXT },
308     { "BOTH",  "Icons & Text",   TB_STYLE_BOTH },
309     { NULL,    NULL,             0 }
310 };
311
312
313 GtkWidget*
314 layout_prefs_show(void)
315 {
316 #if GTK_MAJOR_VERSION < 2
317     GtkAccelGroup *accel_group;
318 #endif
319
320     GtkWidget   *main_vb, *button_hb, *type_tb;
321     GtkWidget   *pane_fr, *pane_vb;
322     GtkWidget   *radio_hb, *radio_vb;
323     GtkWidget   *default_vb, *default_bt;
324     GtkWidget   *main_tb, *hbox;
325     GtkWidget   *scrollbar_om;
326 #if GTK_MAJOR_VERSION < 2
327     GtkWidget *expander_style_om, *line_style_om;
328 #else
329     GtkWidget *altern_colors_om;
330 #endif
331     GtkWidget *highlight_style_om;
332     GtkWidget *toolbar_style_om;
333     GtkWidget *filter_toolbar_placement_om;
334     GtkWidget *window_title_te;
335
336     GtkTooltips   *tooltips = gtk_tooltips_new();
337
338     const char ** inline_txt [LAYOUT_QTY] = {
339                 icon_layout_5_xpm, icon_layout_2_xpm, icon_layout_1_xpm,
340                 icon_layout_4_xpm, icon_layout_3_xpm, icon_layout_6_xpm };
341     GtkWidget ** layout_type_buttons = g_malloc (sizeof(GtkWidget*) * LAYOUT_QTY);
342
343     int        pos = 0;
344     int i;
345
346
347     /* main vertical box */
348     main_vb = gtk_vbox_new(FALSE, 7);
349     gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
350
351 #if GTK_MAJOR_VERSION < 2
352     /* Accelerator group for the accelerators (or, as they're called in
353      Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
354      Ctrl+<key> is an accelerator). */
355     accel_group = gtk_accel_group_new();
356     /*gtk_window_add_accel_group(GTK_WINDOW(main_win), accel_group);*/
357 #endif
358
359     /* pane frame */
360     pane_fr = gtk_frame_new("Panes");
361     gtk_box_pack_start(GTK_BOX(main_vb), pane_fr, FALSE, FALSE, 0);
362     gtk_widget_show(pane_fr);
363
364     /* pane vertical box */
365     pane_vb = gtk_vbox_new(FALSE, 7);
366     gtk_container_set_border_width(GTK_CONTAINER(pane_vb), 5);
367     gtk_container_add(GTK_CONTAINER(pane_fr), pane_vb);
368     gtk_widget_show(pane_vb);
369
370     /* button hbox */
371     button_hb = gtk_hbox_new(FALSE, 0);
372     gtk_container_set_border_width(GTK_CONTAINER(button_hb), 6);
373     gtk_box_pack_start (GTK_BOX(pane_vb), button_hb, FALSE, FALSE, 0);
374
375     /* pane layout */
376     for (i=0; i<LAYOUT_QTY; ++i)
377     {
378         type_tb = gtk_toggle_button_new ();
379         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(type_tb),
380             (layout_type_e)(i + 1) == prefs.gui_layout_type);
381
382         gtk_container_add (GTK_CONTAINER(type_tb), xpm_to_widget(inline_txt[i]));
383
384         SIGNAL_CONNECT(type_tb, "toggled", layout_type_changed_cb, layout_type_buttons);
385         layout_type_buttons[i] = type_tb;
386         gtk_box_pack_start (GTK_BOX(button_hb), type_tb, TRUE, FALSE, 0);
387     }
388
389     OBJECT_SET_DATA(main_vb, LAYOUT_TYPE_BUTTONS_KEY, layout_type_buttons);
390
391     /* radio hbox */
392     radio_hb = gtk_hbox_new(FALSE, 0);
393     gtk_container_set_border_width(GTK_CONTAINER(radio_hb), 6);
394     gtk_box_pack_start (GTK_BOX(pane_vb), radio_hb, FALSE, FALSE, 0);
395
396     radio_vb = layout_content_radio_vbox(main_vb, tooltips, 1, prefs.gui_layout_content_1);
397     gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
398     gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
399     OBJECT_SET_DATA(main_vb, LAYOUT_CONTENT1_VB_KEY, radio_vb);
400
401     radio_vb = layout_content_radio_vbox(main_vb, tooltips, 2, prefs.gui_layout_content_2);
402     gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
403     gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
404     OBJECT_SET_DATA(main_vb, LAYOUT_CONTENT2_VB_KEY, radio_vb);
405
406     radio_vb = layout_content_radio_vbox(main_vb, tooltips, 3, prefs.gui_layout_content_3);
407     gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
408     gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
409     OBJECT_SET_DATA(main_vb, LAYOUT_CONTENT3_VB_KEY, radio_vb);
410
411     default_vb = gtk_vbox_new(FALSE, 0);
412     default_bt = gtk_button_new_with_label("Default panes");
413     gtk_tooltips_set_tip (tooltips, default_bt, 
414         "Reset the pane layout settings to default values.", NULL);
415     SIGNAL_CONNECT(default_bt, "clicked", layout_defaults_cb, main_vb);
416     gtk_box_pack_end(GTK_BOX(default_vb), default_bt, FALSE, FALSE, 0);
417     gtk_box_pack_end(GTK_BOX(radio_hb), default_vb, FALSE, FALSE, 0);
418
419     /* Main horizontal box  */
420     /* XXX - Is there a better way to center the table? */
421     hbox = gtk_hbox_new(FALSE, 7);
422     gtk_box_pack_start (GTK_BOX(main_vb), hbox, TRUE, FALSE, 0);
423
424     /* Main table */
425     main_tb = gtk_table_new(GUI_TABLE_ROWS, 2, FALSE);
426     gtk_box_pack_start( GTK_BOX(hbox), main_tb, FALSE, FALSE, 0 );
427     gtk_table_set_row_spacings( GTK_TABLE(main_tb), 10 );
428     gtk_table_set_col_spacings( GTK_TABLE(main_tb), 15 );
429
430     /* Scrollbar placement */
431     scrollbar_om = create_preference_option_menu(main_tb, pos++,
432         "Vertical scrollbar placement:", NULL, scrollbar_placement_vals,
433         prefs.gui_scrollbar_on_right);
434     gtk_tooltips_set_tip(tooltips, scrollbar_om, 
435         "Select where the vertical scrollbar "
436         "will be displayed in the panes.", NULL);
437     OBJECT_SET_DATA(main_vb, SCROLLBAR_PLACEMENT_KEY, scrollbar_om);
438
439 #if GTK_MAJOR_VERSION < 2
440     /* Tree line style */
441     line_style_om = create_preference_option_menu(main_tb, pos++,
442         "Tree line style:", NULL, line_style_vals,
443         prefs.gui_ptree_line_style);
444     gtk_tooltips_set_tip(tooltips, line_style_om, 
445         "Select the style in which trees "
446         "will be displayed in the packet "
447         "detail pane.", NULL);
448     OBJECT_SET_DATA(main_vb, PTREE_LINE_STYLE_KEY, line_style_om);
449
450     /* Tree expander style */
451     expander_style_om = create_preference_option_menu(main_tb, pos++,
452         "Tree expander style:", NULL, expander_style_vals,
453         prefs.gui_ptree_expander_style);
454     gtk_tooltips_set_tip(tooltips, expander_style_om, 
455         "Select the style in which the "
456         "expander will be displayed in "
457         "the panes displayed.", NULL);
458     OBJECT_SET_DATA(main_vb, PTREE_EXPANDER_STYLE_KEY, expander_style_om);
459 #else
460     /* Alternating row colors in list and tree views */
461     altern_colors_om = create_preference_option_menu(main_tb, pos++,
462         "Alternating row colors in lists and trees:", NULL,
463         altern_colors_vals, prefs.gui_altern_colors);
464     gtk_tooltips_set_tip(tooltips, altern_colors_om, 
465         "Select whether or not the rows of "
466         "lists and trees have alternating color.", NULL);
467     OBJECT_SET_DATA(main_vb, ALTERN_COLORS_KEY, altern_colors_om);
468 #endif
469
470     /* Hex Dump highlight style */
471     highlight_style_om = create_preference_option_menu(main_tb, pos++,
472         "Hex display highlight style:", NULL, highlight_style_vals,
473          prefs.gui_hex_dump_highlight_style);
474     gtk_tooltips_set_tip(tooltips, highlight_style_om, 
475         "Select the style in which the "
476         "hex dump will be displayed.", NULL);
477     OBJECT_SET_DATA(main_vb, HEX_DUMP_HIGHLIGHT_STYLE_KEY, highlight_style_om);
478
479     /* Toolbar prefs */
480     toolbar_style_om = create_preference_option_menu(main_tb, pos++,
481         "Toolbar style:", NULL, toolbar_style_vals,
482         prefs.gui_toolbar_main_style);
483     gtk_tooltips_set_tip(tooltips, toolbar_style_om, 
484         "Select the style in which the "
485         "toolbar will be displayed.", NULL);
486     OBJECT_SET_DATA(main_vb, GUI_TOOLBAR_STYLE_KEY, toolbar_style_om);
487
488     /* Placement of Filter toolbar */
489     filter_toolbar_placement_om = create_preference_option_menu(main_tb, pos++,
490         "Filter toolbar placement:", NULL,
491         filter_toolbar_placement_vals, prefs.filter_toolbar_show_in_statusbar);
492     gtk_tooltips_set_tip(tooltips, filter_toolbar_placement_om, 
493         "Select where the filter "
494         "toolbar will be displayed." , NULL);
495     OBJECT_SET_DATA(main_vb, FILTER_TOOLBAR_PLACEMENT_KEY, filter_toolbar_placement_om);
496
497     /* Window title */
498     window_title_te = create_preference_entry(main_tb, pos++,
499         "Custom window title (prepended to existing titles):", 
500         NULL, prefs.gui_window_title);
501     gtk_entry_set_text(GTK_ENTRY(window_title_te), prefs.gui_window_title);
502     gtk_tooltips_set_tip(tooltips, window_title_te, 
503         "Enter the text to be prepended to the "
504         "window title.", NULL);
505     OBJECT_SET_DATA(main_vb, GUI_WINDOW_TITLE_KEY, window_title_te);
506
507     /* Show 'em what we got */
508     gtk_widget_show_all(main_vb);
509
510     return(main_vb);
511 }
512
513 static gint
514 fetch_enum_value(gpointer control, const enum_val_t *enumvals)
515 {
516     return fetch_preference_option_menu_val(GTK_WIDGET(control), enumvals);
517 }
518
519 void
520 layout_prefs_fetch(GtkWidget *w)
521 {
522     layout_t layout_fetched;
523
524     layout_get(w, &layout_fetched);
525
526     prefs.gui_layout_type = layout_fetched.type;
527     prefs.gui_layout_content_1 = layout_fetched.content[0];
528     prefs.gui_layout_content_2 = layout_fetched.content[1];
529     prefs.gui_layout_content_3 = layout_fetched.content[2];
530
531     prefs.gui_scrollbar_on_right = fetch_enum_value(
532         OBJECT_GET_DATA(w, SCROLLBAR_PLACEMENT_KEY),
533         scrollbar_placement_vals);
534
535 #if GTK_MAJOR_VERSION < 2
536     prefs.gui_ptree_line_style = fetch_enum_value(
537         OBJECT_GET_DATA(w, PTREE_LINE_STYLE_KEY), line_style_vals);
538     prefs.gui_ptree_expander_style = fetch_enum_value(
539         OBJECT_GET_DATA(w, PTREE_EXPANDER_STYLE_KEY), expander_style_vals);
540 #else
541     prefs.gui_altern_colors = fetch_enum_value(
542         OBJECT_GET_DATA(w, ALTERN_COLORS_KEY), altern_colors_vals);
543 #endif
544     prefs.filter_toolbar_show_in_statusbar = fetch_enum_value(
545         OBJECT_GET_DATA(w, FILTER_TOOLBAR_PLACEMENT_KEY), filter_toolbar_placement_vals);
546     prefs.gui_hex_dump_highlight_style = fetch_enum_value(
547         OBJECT_GET_DATA(w, HEX_DUMP_HIGHLIGHT_STYLE_KEY),  highlight_style_vals);
548     prefs.gui_toolbar_main_style = fetch_enum_value(
549         OBJECT_GET_DATA(w, GUI_TOOLBAR_STYLE_KEY), toolbar_style_vals);
550
551     if (prefs.gui_window_title != NULL)
552         g_free(prefs.gui_window_title);
553     prefs.gui_window_title = g_strdup(gtk_entry_get_text(
554         GTK_ENTRY(OBJECT_GET_DATA(w, GUI_WINDOW_TITLE_KEY))));
555 }
556
557 void
558 layout_prefs_apply(GtkWidget *w _U_)
559 {
560     set_main_window_name("The Wireshark Network Analyzer");
561     main_widgets_rearrange();
562 }
563
564 void
565 layout_prefs_destroy(GtkWidget *main_vb)
566 {
567     GtkWidget ** layout_type_buttons = OBJECT_GET_DATA(main_vb, LAYOUT_TYPE_BUTTONS_KEY);
568
569     g_free(layout_type_buttons);
570 }
571