2 * Dialog box for GUI preferences
4 * $Id: gui_prefs.c,v 1.21 2000/10/09 06:38:36 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include "gui_prefs.h"
34 #include "gtkglobals.h"
35 #include "prefs_dlg.h"
36 #include "follow_dlg.h"
39 #include "prefs-int.h"
41 #include "simple_dialog.h"
42 #include "dlg_utils.h"
43 #include "proto_draw.h"
46 static void create_option_menu(GtkWidget *main_vb, const gchar *key,
47 GtkWidget *main_tb, int table_position,
48 const gchar *label_text, const enum_val *enumvals, gint current_val);
49 static void font_browse_cb(GtkWidget *w, gpointer data);
50 static void font_browse_ok_cb(GtkWidget *w, GtkFontSelectionDialog *fs);
51 static void font_browse_destroy(GtkWidget *win, gpointer data);
52 static gint fetch_enum_value(gpointer control, const enum_val *enumvals);
53 static void color_browse_cb(GtkWidget *w, gpointer data);
54 static void update_text_color(GtkWidget *w, gpointer data);
55 static void update_current_color(GtkWidget *w, gpointer data);
56 static void color_ok_cb(GtkWidget *w, gpointer data);
57 static void color_cancel_cb(GtkWidget *w, gpointer data);
58 static gboolean color_delete_cb(GtkWidget *prefs_w, gpointer dummy);
59 static void color_destroy_cb(GtkWidget *w, gpointer data);
60 static void fetch_colors(void);
62 #define SCROLLBAR_PLACEMENT_KEY "scrollbar_placement"
63 #define PLIST_SEL_BROWSE_KEY "plist_sel_browse"
64 #define PTREE_SEL_BROWSE_KEY "ptree_sel_browse"
65 #define PTREE_LINE_STYLE_KEY "ptree_line_style"
66 #define PTREE_EXPANDER_STYLE_KEY "ptree_expander_style"
67 #define HEX_DUMP_HIGHLIGHT_STYLE_KEY "hex_dump_highlight_style"
69 #define FONT_DIALOG_PTR_KEY "font_dialog_ptr"
70 #define FONT_CALLER_PTR_KEY "font_caller_ptr"
71 #define COLOR_DIALOG_PTR_KEY "color_dialog_ptr"
72 #define COLOR_CALLER_PTR_KEY "color_caller_ptr"
73 #define COLOR_SAMPLE_PTR_KEY "color_sample_ptr"
74 #define COLOR_SELECTION_PTR_KEY "color_selection_ptr"
76 static const enum_val scrollbar_placement_vals[] = {
82 static const enum_val selection_mode_vals[] = {
88 static const enum_val line_style_vals[] = {
96 static const enum_val expander_style_vals[] = {
104 static const enum_val highlight_style_vals[] = {
110 /* Set to FALSE initially; set to TRUE if the user ever hits "OK" on
111 the "Colors..." dialog, so that we know that they (probably) changed
112 colors, and therefore that the "apply" function needs to recolor
113 any marked packets. */
114 static gboolean colors_changed;
116 /* Set to FALSE initially; set to TRUE if the user ever hits "OK" on
117 the "Font..." dialog, so that we know that they (probably) changed
118 the font, and therefore that the "apply" function needs to take care
120 static gboolean font_changed;
122 /* Font name from the font dialog box; if "font_changed" is TRUE, this
123 has been set to the name of the font the user selected. */
124 static gchar *new_font_name;
129 GtkWidget *main_tb, *main_vb, *font_bt, *color_bt;
131 /* The colors or font haven't been changed yet. */
132 colors_changed = FALSE;
133 font_changed = FALSE;
135 /* Main vertical box */
136 main_vb = gtk_vbox_new(FALSE, 7);
137 gtk_container_border_width( GTK_CONTAINER(main_vb), 5 );
140 main_tb = gtk_table_new(7, 2, FALSE);
141 gtk_box_pack_start( GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0 );
142 gtk_table_set_row_spacings( GTK_TABLE(main_tb), 10 );
143 gtk_table_set_col_spacings( GTK_TABLE(main_tb), 15 );
145 /* Scrollbar placement */
146 create_option_menu(main_vb, SCROLLBAR_PLACEMENT_KEY, main_tb, 0,
147 "Vertical Scrollbar Placement:", scrollbar_placement_vals,
148 prefs.gui_scrollbar_on_right);
150 /* Packet list selection browseable */
151 create_option_menu(main_vb, PLIST_SEL_BROWSE_KEY, main_tb, 1,
152 "Packet-list selection bar movement:", selection_mode_vals,
153 prefs.gui_plist_sel_browse);
155 /* Proto tree selection browseable */
156 create_option_menu(main_vb, PTREE_SEL_BROWSE_KEY, main_tb, 2,
157 "Protocol-tree selection bar movement:", selection_mode_vals,
158 prefs.gui_ptree_sel_browse);
160 /* Proto tree line style */
161 create_option_menu(main_vb, PTREE_LINE_STYLE_KEY, main_tb, 3,
162 "Protocol-tree line style:", line_style_vals,
163 prefs.gui_ptree_line_style);
165 /* Proto tree expander style */
166 create_option_menu(main_vb, PTREE_EXPANDER_STYLE_KEY, main_tb, 4,
167 "Protocol-tree expander style:", expander_style_vals,
168 prefs.gui_ptree_expander_style);
170 /* Hex Dump highlight style */
171 create_option_menu(main_vb, HEX_DUMP_HIGHLIGHT_STYLE_KEY, main_tb, 5,
172 "Hex dump highlight style:", highlight_style_vals,
173 prefs.gui_hex_dump_highlight_style);
175 /* "Font..." button - click to open a font selection dialog box. */
176 font_bt = gtk_button_new_with_label("Font...");
177 gtk_signal_connect(GTK_OBJECT(font_bt), "clicked",
178 GTK_SIGNAL_FUNC(font_browse_cb), NULL);
179 gtk_table_attach_defaults( GTK_TABLE(main_tb), font_bt, 1, 2, 6, 7 );
181 /* "Colors..." button - click to open a color selection dialog box. */
182 color_bt = gtk_button_new_with_label("Colors...");
183 gtk_signal_connect(GTK_OBJECT(color_bt), "clicked",
184 GTK_SIGNAL_FUNC(color_browse_cb), NULL);
185 gtk_table_attach_defaults( GTK_TABLE(main_tb), color_bt, 1, 2, 7, 8 );
187 /* Show 'em what we got */
188 gtk_widget_show_all(main_vb);
194 create_option_menu(GtkWidget *main_vb, const gchar *key,
195 GtkWidget *main_tb, int table_position,
196 const gchar *label_text, const enum_val *enumvals, gint current_val)
198 GtkWidget *label, *menu, *menu_item, *option_menu;
199 int menu_index, index;
200 const enum_val *enum_valp;
202 label = gtk_label_new(label_text);
203 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
204 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1,
205 table_position, table_position + 1);
207 /* Create a menu from the enumvals */
208 menu = gtk_menu_new();
210 for (enum_valp = enumvals, index = 0;
211 enum_valp->name != NULL; enum_valp++, index++) {
212 menu_item = gtk_menu_item_new_with_label(enum_valp->name);
213 gtk_menu_append(GTK_MENU(menu), menu_item);
214 if (enum_valp->value == current_val)
216 gtk_widget_show(menu_item);
219 /* Create the option menu from the menu */
220 option_menu = gtk_option_menu_new();
221 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
223 /* Set its current value to the variable's current value */
224 if (menu_index != -1)
225 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu),
228 gtk_table_attach_defaults(GTK_TABLE(main_tb), option_menu,
229 1, 2, table_position, table_position + 1);
231 gtk_object_set_data(GTK_OBJECT(main_vb), key, option_menu);
234 /* Create a font dialog for browsing. */
236 font_browse_cb(GtkWidget *w, gpointer data)
238 GtkWidget *caller = gtk_widget_get_toplevel(w);
239 GtkWidget *font_browse_w;
240 static gchar *fixedwidths[] = { "c", "m", NULL };
242 /* Has a font dialog box already been opened for that top-level
244 font_browse_w = gtk_object_get_data(GTK_OBJECT(caller),
245 FONT_DIALOG_PTR_KEY);
247 if (font_browse_w != NULL) {
248 /* Yes. Just re-activate that dialog box. */
249 reactivate_window(font_browse_w);
253 /* Now create a new dialog. */
254 font_browse_w = gtk_font_selection_dialog_new("Ethereal: Select Font");
255 gtk_window_set_transient_for(GTK_WINDOW(font_browse_w),
256 GTK_WINDOW(top_level));
258 /* Call a handler when we're destroyed, so we can inform
259 our caller, if any, that we've been destroyed. */
260 gtk_signal_connect(GTK_OBJECT(font_browse_w), "destroy",
261 GTK_SIGNAL_FUNC(font_browse_destroy), NULL);
263 /* Set its filter to show only fixed_width fonts. */
264 gtk_font_selection_dialog_set_filter(
265 GTK_FONT_SELECTION_DIALOG(font_browse_w),
266 GTK_FONT_FILTER_BASE, /* user can't change the filter */
267 GTK_FONT_ALL, /* bitmap or scalable are fine */
268 NULL, /* all foundries are OK */
269 NULL, /* all weights are OK (XXX - normal only?) */
270 NULL, /* all slants are OK (XXX - Roman only?) */
271 NULL, /* all setwidths are OK */
272 fixedwidths, /* ONLY fixed-width fonts */
273 NULL); /* all charsets are OK (XXX - ISO 8859/1 only?) */
275 /* Set the font to the current font.
276 XXX - GTK+ 1.2.8, and probably earlier versions, have a bug
277 wherein that doesn't necessarily cause that font to be
278 selected in the dialog box. I've sent to the GTK+ folk
279 a fix; hopefully, it'll show up in 1.2.9 if, as, and when
280 they put out a 1.2.9 release. */
281 gtk_font_selection_dialog_set_font_name(
282 GTK_FONT_SELECTION_DIALOG(font_browse_w), prefs.gui_font_name);
284 /* Set the FONT_CALLER_PTR_KEY for the new dialog to point to
286 gtk_object_set_data(GTK_OBJECT(font_browse_w), FONT_CALLER_PTR_KEY,
289 /* Set the FONT_DIALOG_PTR_KEY for the caller to point to us */
290 gtk_object_set_data(GTK_OBJECT(caller), FONT_DIALOG_PTR_KEY,
293 /* Connect the ok_button to font_browse_ok_cb function and pass along a
294 pointer to the font selection box widget */
296 GTK_OBJECT(GTK_FONT_SELECTION_DIALOG(font_browse_w)->ok_button),
297 "clicked", (GtkSignalFunc)font_browse_ok_cb, font_browse_w);
299 /* Connect the cancel_button to destroy the widget */
300 gtk_signal_connect_object(
301 GTK_OBJECT(GTK_FONT_SELECTION_DIALOG(font_browse_w)->cancel_button),
302 "clicked", (GtkSignalFunc)gtk_widget_destroy,
303 GTK_OBJECT(font_browse_w));
305 /* Catch the "key_press_event" signal in the window, so that we can
306 catch the ESC key being pressed and act as if the "Cancel" button
307 had been selected. */
308 dlg_set_cancel(font_browse_w,
309 GTK_FONT_SELECTION_DIALOG(font_browse_w)->cancel_button);
311 gtk_widget_show(font_browse_w);
315 font_browse_ok_cb(GtkWidget *w, GtkFontSelectionDialog *fs)
317 gchar *font_name, *bold_font_name;
318 GdkFont *new_r_font, *new_b_font;
320 font_name = g_strdup(gtk_font_selection_dialog_get_font_name(
321 GTK_FONT_SELECTION_DIALOG(fs)));
322 if (font_name == NULL) {
323 /* No font was selected; let the user know, but don't
324 tear down the font selection dialog, so they can
326 simple_dialog(ESD_TYPE_CRIT | ESD_TYPE_MODAL, NULL,
327 "You have not selected a font.");
331 /* Get the name that the boldface version of that font would have. */
332 bold_font_name = boldify(font_name);
334 /* Now load those fonts, just to make sure we can. */
335 new_r_font = gdk_font_load(font_name);
336 if (new_r_font == NULL) {
337 /* Oops, that font didn't work.
338 Tell the user, but don't tear down the font selection
339 dialog, so that they can try again. */
340 simple_dialog(ESD_TYPE_CRIT | ESD_TYPE_MODAL, NULL,
341 "The font you selected cannot be loaded.");
344 g_free(bold_font_name);
348 new_b_font = gdk_font_load(bold_font_name);
349 if (new_b_font == NULL) {
350 /* Oops, that font didn't work.
351 Tell the user, but don't tear down the font selection
352 dialog, so that they can try again. */
353 simple_dialog(ESD_TYPE_CRIT | ESD_TYPE_MODAL, NULL,
354 "The font you selected doesn't have a boldface version.");
357 g_free(bold_font_name);
358 gdk_font_unref(new_r_font);
363 new_font_name = font_name;
365 gtk_widget_hide(GTK_WIDGET(fs));
366 gtk_widget_destroy(GTK_WIDGET(fs));
370 font_browse_destroy(GtkWidget *win, gpointer data)
374 /* Get the widget that requested that we be popped up, if any.
375 (It should arrange to destroy us if it's destroyed, so
376 that we don't get a pointer to a non-existent window here.) */
377 caller = gtk_object_get_data(GTK_OBJECT(win), FONT_CALLER_PTR_KEY);
379 if (caller != NULL) {
380 /* Tell it we no longer exist. */
381 gtk_object_set_data(GTK_OBJECT(caller), FONT_DIALOG_PTR_KEY,
385 /* Now nuke this window. */
386 gtk_grab_remove(GTK_WIDGET(win));
387 gtk_widget_destroy(GTK_WIDGET(win));
391 fetch_enum_value(gpointer control, const enum_val *enumvals)
396 /* Get the label for the currently active entry in the option menu.
397 Yes, this is how you do it. See FAQ 6.8 in the GTK+ FAQ. */
398 label = GTK_BIN(control)->child;
400 /* Get the label string, and translate it to a value. */
401 gtk_label_get(GTK_LABEL(label), &label_string);
402 return find_val_for_string(label_string, enumvals, 1);
406 gui_prefs_fetch(GtkWidget *w)
408 prefs.gui_scrollbar_on_right = fetch_enum_value(
409 gtk_object_get_data(GTK_OBJECT(w), SCROLLBAR_PLACEMENT_KEY),
410 scrollbar_placement_vals);
411 prefs.gui_plist_sel_browse = fetch_enum_value(
412 gtk_object_get_data(GTK_OBJECT(w), PLIST_SEL_BROWSE_KEY),
413 selection_mode_vals);
414 prefs.gui_ptree_sel_browse = fetch_enum_value(
415 gtk_object_get_data(GTK_OBJECT(w), PTREE_SEL_BROWSE_KEY),
416 selection_mode_vals);
417 prefs.gui_ptree_line_style = fetch_enum_value(
418 gtk_object_get_data(GTK_OBJECT(w), PTREE_LINE_STYLE_KEY),
420 prefs.gui_ptree_expander_style = fetch_enum_value(
421 gtk_object_get_data(GTK_OBJECT(w), PTREE_EXPANDER_STYLE_KEY),
422 expander_style_vals);
423 prefs.gui_hex_dump_highlight_style = fetch_enum_value(
424 gtk_object_get_data(GTK_OBJECT(w), HEX_DUMP_HIGHLIGHT_STYLE_KEY),
425 highlight_style_vals);
428 if (prefs.gui_font_name != NULL)
429 g_free(prefs.gui_font_name);
430 prefs.gui_font_name = g_strdup(new_font_name);
438 gui_prefs_apply(GtkWidget *w)
440 GdkFont *new_r_font, *new_b_font;
441 char *bold_font_name;
442 GdkFont *old_r_font = NULL, *old_b_font = NULL;
445 /* XXX - what if the world changed out from under
446 us, so that one or both of these fonts cannot
448 new_r_font = gdk_font_load(prefs.gui_font_name);
449 bold_font_name = boldify(prefs.gui_font_name);
450 new_b_font = gdk_font_load(bold_font_name);
451 set_plist_font(new_r_font);
452 set_ptree_font_all(new_r_font);
453 old_r_font = m_r_font;
454 old_b_font = m_b_font;
455 m_r_font = new_r_font;
456 m_b_font = new_b_font;
457 g_free(bold_font_name);
460 /* Redraw the hex dump windows, in case either the font or the
461 highlight style changed. */
462 redraw_hex_dump_all();
464 /* Redraw the help window. */
467 /* Redraw the "Follow TCP Stream" windows, in case either the font
468 or the colors to use changed. */
471 set_scrollbar_placement_all(prefs.gui_scrollbar_on_right);
472 set_plist_sel_browse(prefs.gui_plist_sel_browse);
473 set_ptree_sel_browse_all(prefs.gui_ptree_sel_browse);
474 set_ptree_line_style_all(prefs.gui_ptree_line_style);
475 set_ptree_expander_style_all(prefs.gui_ptree_expander_style);
477 update_marked_frames();
479 /* We're no longer using the old fonts; unreference them. */
480 if (old_r_font != NULL)
481 gdk_font_unref(old_r_font);
482 if (old_b_font != NULL)
483 gdk_font_unref(old_b_font);
487 gui_prefs_destroy(GtkWidget *w)
489 GtkWidget *caller = gtk_widget_get_toplevel(w);
492 /* Is there a font selection dialog associated with this
493 Preferences dialog? */
494 fs = gtk_object_get_data(GTK_OBJECT(caller), FONT_DIALOG_PTR_KEY);
497 /* Yes. Destroy it. */
498 gtk_widget_destroy(fs);
501 /* Is there a color selection dialog associated with this
502 Preferences dialog? */
503 fs = gtk_object_get_data(GTK_OBJECT(caller), COLOR_DIALOG_PTR_KEY);
506 /* Yes. Destroy it. */
507 gtk_widget_destroy(fs);
510 /* Free up any saved font name. */
511 if (new_font_name != NULL)
512 g_free(new_font_name);
515 /* color selection part */
517 #define MAX_HANDLED_COL 2
524 static color_info_t color_info[MAX_HANDLED_COL] = {
526 { {0.0, 0.0, 0.0, 0.0}, "Marked frame foreground" },
528 { {0.0, 0.0, 0.0, 0.0}, "Marked frame background" }
531 #define SAMPLE_MARKED_TEXT "Sample marked frame text\n"
538 static GdkColor *curcolor = NULL;
541 color_browse_cb(GtkWidget *w, gpointer data)
544 GtkWidget *main_vb, *main_tb, *label, *optmenu, *menu, *menuitem;
545 GtkWidget *sample, *colorsel, *bbox, *cancel_bt, *ok_bt, *color_w;
546 int width, height, i;
548 GtkWidget *caller = gtk_widget_get_toplevel(w);
550 /* Has a color dialog box already been opened for that top-level
552 color_w = gtk_object_get_data(GTK_OBJECT(caller),
553 COLOR_DIALOG_PTR_KEY);
555 if (color_w != NULL) {
556 /* Yes. Just re-activate that dialog box. */
557 reactivate_window(color_w);
561 color_info[MFG_IDX].color = prefs.gui_marked_fg;
562 color_info[MBG_IDX].color = prefs.gui_marked_bg;
563 curcolor = &color_info[MFG_IDX].color;
564 scolor[CS_RED] = (gdouble) (curcolor->red) / 65535.0;
565 scolor[CS_GREEN] = (gdouble) (curcolor->green) / 65535.0;
566 scolor[CS_BLUE] = (gdouble) (curcolor->blue) / 65535.0;
567 scolor[CS_OPACITY] = 1.0;
569 /* Now create a new dialog.
570 You can't put your own extra widgets into a color selection
571 dialog, as you can with a file selection dialog, so we have to
572 construct our own dialog and put a color selection widget
574 color_w = dlg_window_new("Ethereal: Select Color");
576 gtk_signal_connect(GTK_OBJECT(color_w), "delete_event",
577 GTK_SIGNAL_FUNC(color_delete_cb), NULL);
579 /* Call a handler when we're destroyed, so we can inform our caller,
580 if any, that we've been destroyed. */
581 gtk_signal_connect(GTK_OBJECT(color_w), "destroy",
582 GTK_SIGNAL_FUNC(color_destroy_cb), NULL);
584 main_vb = gtk_vbox_new(FALSE, 5);
585 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
586 gtk_container_add (GTK_CONTAINER (color_w), main_vb);
587 main_tb = gtk_table_new(3, 3, FALSE);
588 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
589 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
590 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
591 gtk_widget_show(main_tb);
592 label = gtk_label_new("Set:");
593 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
594 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, 0, 1);
595 gtk_widget_show(label);
597 colorsel = gtk_color_selection_new();
598 optmenu = gtk_option_menu_new();
599 menu = gtk_menu_new();
600 for (i = 0; i < MAX_HANDLED_COL; i++){
601 menuitem = gtk_menu_item_new_with_label(color_info[i].label);
602 gtk_object_set_data(GTK_OBJECT(menuitem), COLOR_SELECTION_PTR_KEY,
603 (gpointer) colorsel);
604 gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
605 GTK_SIGNAL_FUNC(update_current_color),
606 &color_info[i].color);
607 gtk_widget_show(menuitem);
608 gtk_menu_append(GTK_MENU (menu), menuitem);
610 gtk_option_menu_set_menu (GTK_OPTION_MENU (optmenu), menu);
611 gtk_table_attach_defaults(GTK_TABLE(main_tb), optmenu, 1, 2, 0, 1);
612 gtk_widget_show(optmenu);
614 sample = gtk_text_new(FALSE, FALSE);
615 height = sample->style->font->ascent + sample->style->font->descent;
616 width = gdk_string_width(sample->style->font, SAMPLE_MARKED_TEXT);
617 gtk_widget_set_usize(GTK_WIDGET(sample), width, height);
618 gtk_text_set_editable(GTK_TEXT(sample), FALSE);
619 gtk_text_insert(GTK_TEXT(sample), NULL,
620 &color_info[MFG_IDX].color,
621 &color_info[MBG_IDX].color,
622 SAMPLE_MARKED_TEXT, -1);
623 gtk_table_attach_defaults(GTK_TABLE(main_tb), sample, 2, 3, 0, 2);
624 gtk_widget_show(sample);
625 gtk_color_selection_set_color(GTK_COLOR_SELECTION(colorsel),
627 gtk_table_attach_defaults(GTK_TABLE(main_tb), colorsel, 0, 3, 2, 3);
628 gtk_object_set_data(GTK_OBJECT(colorsel), COLOR_SAMPLE_PTR_KEY,
630 gtk_signal_connect(GTK_OBJECT(colorsel), "color-changed",
631 GTK_SIGNAL_FUNC(update_text_color), NULL);
632 gtk_widget_show(colorsel);
633 gtk_widget_show(main_vb);
635 gtk_object_set_data(GTK_OBJECT(color_w), COLOR_CALLER_PTR_KEY, caller);
636 gtk_object_set_data(GTK_OBJECT(caller), COLOR_DIALOG_PTR_KEY, color_w);
638 /* Ok, Cancel Buttons */
639 bbox = gtk_hbutton_box_new();
640 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
641 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
642 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
643 gtk_widget_show(bbox);
645 ok_bt = gtk_button_new_with_label ("OK");
646 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
647 GTK_SIGNAL_FUNC(color_ok_cb), color_w);
648 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
649 gtk_box_pack_start(GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
650 gtk_widget_grab_default(ok_bt);
651 gtk_widget_show(ok_bt);
652 cancel_bt = gtk_button_new_with_label ("Cancel");
653 gtk_signal_connect_object(GTK_OBJECT(cancel_bt), "clicked",
654 (GtkSignalFunc)gtk_widget_destroy,
655 GTK_OBJECT(color_w));
656 gtk_box_pack_start(GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
657 gtk_widget_show(cancel_bt);
658 dlg_set_cancel(color_w, cancel_bt);
660 gtk_widget_show(color_w);
664 update_text_color(GtkWidget *w, gpointer data) {
665 GtkText *sample = gtk_object_get_data(GTK_OBJECT(w), COLOR_SAMPLE_PTR_KEY);
668 gtk_color_selection_get_color(GTK_COLOR_SELECTION(w), &scolor[CS_RED]);
670 curcolor->red = (gushort) (scolor[CS_RED] * 65535.0);
671 curcolor->green = (gushort) (scolor[CS_GREEN] * 65535.0);
672 curcolor->blue = (gushort) (scolor[CS_BLUE] * 65535.0);
674 gtk_text_freeze(sample);
675 gtk_text_set_point(sample, 0);
676 gtk_text_forward_delete(sample, gtk_text_get_length(sample));
677 gtk_text_insert(GTK_TEXT(sample), NULL,
678 &color_info[MFG_IDX].color,
679 &color_info[MBG_IDX].color,
680 SAMPLE_MARKED_TEXT, -1);
681 gtk_text_thaw(sample);
685 update_current_color(GtkWidget *w, gpointer data)
687 GtkColorSelection *colorsel;
690 colorsel = GTK_COLOR_SELECTION(gtk_object_get_data(GTK_OBJECT(w),
691 COLOR_SELECTION_PTR_KEY));
692 curcolor = (GdkColor *)data;
693 scolor[CS_RED] = (gdouble) (curcolor->red) / 65535.0;
694 scolor[CS_GREEN] = (gdouble) (curcolor->green) / 65535.0;
695 scolor[CS_BLUE] = (gdouble) (curcolor->blue) / 65535.0;
696 scolor[CS_OPACITY] = 1.0;
698 gtk_color_selection_set_color(colorsel, &scolor[CS_RED]);
702 color_ok_cb(GtkWidget *w, gpointer data)
704 /* We assume the user actually changed a color here. */
705 colors_changed = TRUE;
707 gtk_widget_hide(GTK_WIDGET(data));
708 gtk_widget_destroy(GTK_WIDGET(data));
712 color_cancel_cb(GtkWidget *w, gpointer data)
714 /* Revert the colors to the current preference settings. */
715 color_info[MFG_IDX].color = prefs.gui_marked_fg;
716 color_info[MBG_IDX].color = prefs.gui_marked_bg;
717 gtk_widget_hide(GTK_WIDGET(data));
718 gtk_widget_destroy(GTK_WIDGET(data));
721 /* Treat this as a cancel, by calling "color_cancel_cb()".
722 XXX - that'll destroy the Select Color dialog; will that upset
723 a higher-level handler that says "OK, we've been asked to delete
724 this, so destroy it"? */
726 color_delete_cb(GtkWidget *prefs_w, gpointer dummy)
728 color_cancel_cb(NULL, NULL);
733 color_destroy_cb(GtkWidget *w, gpointer data)
735 GtkWidget *caller = gtk_object_get_data(GTK_OBJECT(w),
736 COLOR_CALLER_PTR_KEY);
737 if (caller != NULL) {
738 gtk_object_set_data(GTK_OBJECT(caller), COLOR_DIALOG_PTR_KEY, NULL);
740 gtk_grab_remove(GTK_WIDGET(w));
741 gtk_widget_destroy(GTK_WIDGET(w));
747 prefs.gui_marked_fg = color_info[MFG_IDX].color;
748 prefs.gui_marked_bg = color_info[MBG_IDX].color;