/* Copyright (C) 2000 - 2004 Christian Kreibich . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct nd_hardware_dialog_data { int address_len; ND_AddressCallback callback_okay; ND_DialogCallback callback_cancel; LND_Packet *packet; void *user_data; } ND_HardwareDialogData; static GtkWidget *number_dialog = NULL; static GtkWidget *ip_dialog = NULL; static GtkWidget *filesel_dialog = NULL; static void dialog_largenumber(const char *message, guint value, ND_NumberCallback callback_okay, ND_DialogCallback callback_cancel, LND_Packet *packet, void *user_data); static void hw_okay_clicked (GtkButton *button, gpointer user_data) { GtkWidget *dialog, *entry; int i; guchar *address; char key[MAXPATHLEN]; ND_HardwareDialogData *dialog_data; dialog = gtk_widget_get_toplevel(GTK_WIDGET(button)); D_ASSERT_PTR(dialog); dialog_data = (ND_HardwareDialogData *) user_data; D_ASSERT_PTR(dialog_data); if (!dialog_data) return; address = g_new0(guchar, dialog_data->address_len); D_ASSERT_PTR(address); if (!address) return; /* Read each entry's value, convert to numerical value and place it in the address array. */ for (i = 0; i < dialog_data->address_len; i++) { g_snprintf(key, MAXPATHLEN, "hw_byte_%i", i); ND_GTK_GET(entry, dialog, key); address[i] = (guchar) strtoul(gtk_entry_get_text(GTK_ENTRY(entry)), NULL, 16); } gtk_widget_destroy(dialog); /* Call user-defined hook */ if (dialog_data->callback_okay) dialog_data->callback_okay(address, dialog_data->address_len, dialog_data->packet, dialog_data->user_data); g_free(dialog_data); g_free(address); } static void hw_cancel_clicked (GtkButton *button, gpointer user_data) { GtkWidget *w; ND_HardwareDialogData *dialog_data = (ND_HardwareDialogData *) user_data; if (dialog_data->callback_cancel) dialog_data->callback_cancel(dialog_data->user_data); w = gtk_widget_get_toplevel(GTK_WIDGET(button)); g_free(dialog_data); gtk_widget_destroy(w); return; TOUCH(user_data); } static void generic_button_clicked(GtkButton *button, gpointer cb) { ND_DialogCallback callback; GtkWidget *dialog; void *user_data; dialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button))); user_data = gtk_object_get_data(GTK_OBJECT(dialog), "user_data"); gtk_widget_destroy(dialog); if (cb) { callback = (ND_DialogCallback) cb; callback(user_data); } } static GtkWidget * dialog_create_hardware_address(const char *message, ND_HardwareDialogData *data) { int i; char key[MAXPATHLEN]; GtkWidget *hw_entry_dialog; GtkWidget *vbox1, *vbox2; GtkWidget *hw_entry_label; GtkWidget *hbox1, *hbox2, *hbox3; GtkWidget *hw_byte; GtkWidget *label; GtkWidget *hw_okay; GtkWidget *hw_cancel; hw_entry_dialog = gtk_dialog_new (); gtk_object_set_data (GTK_OBJECT (hw_entry_dialog), "hw_entry_dialog", hw_entry_dialog); gtk_widget_set_usize (hw_entry_dialog, 240, -2); gtk_window_set_title (GTK_WINDOW (hw_entry_dialog), _("Hardware Address Entry Dialog")); GTK_WINDOW (hw_entry_dialog)->type = GTK_WINDOW_DIALOG; gtk_window_set_position (GTK_WINDOW (hw_entry_dialog), GTK_WIN_POS_CENTER); gtk_window_set_modal (GTK_WINDOW (hw_entry_dialog), TRUE); gtk_window_set_default_size (GTK_WINDOW (hw_entry_dialog), 20, -1); gtk_window_set_policy (GTK_WINDOW (hw_entry_dialog), FALSE, FALSE, FALSE); vbox1 = GTK_DIALOG (hw_entry_dialog)->vbox; gtk_object_set_data (GTK_OBJECT (hw_entry_dialog), "vbox1", vbox1); gtk_widget_show (vbox1); vbox2 = gtk_vbox_new (FALSE, 0); gtk_widget_ref (vbox2); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), "vbox2", vbox2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (vbox2); gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER (vbox2), 10); hw_entry_label = gtk_label_new (message); gtk_widget_ref (hw_entry_label); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), "hw_entry_label", hw_entry_label, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hw_entry_label); gtk_box_pack_start (GTK_BOX (vbox2), hw_entry_label, FALSE, FALSE, 0); gtk_label_set_justify (GTK_LABEL (hw_entry_label), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment (GTK_MISC (hw_entry_label), 0, 0.5); gtk_misc_set_padding (GTK_MISC (hw_entry_label), 2, 2); hbox1 = gtk_hbox_new (FALSE, 0); gtk_widget_ref (hbox1); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), "hbox1", hbox1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hbox1); gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 0); for (i = 0; i < data->address_len - 1; i++) { hw_byte = gtk_entry_new_with_max_length (2); gtk_widget_ref (hw_byte); g_snprintf(key, MAXPATHLEN, "hw_byte_%i", i); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), key, hw_byte, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hw_byte); gtk_box_pack_start (GTK_BOX (hbox1), hw_byte, TRUE, TRUE, 0); label = gtk_label_new (_(" : ")); gtk_widget_ref (label); g_snprintf(key, MAXPATHLEN, "label_%i", i); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), key, label, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0); } hw_byte = gtk_entry_new_with_max_length (2); gtk_widget_ref (hw_byte); g_snprintf(key, MAXPATHLEN, "hw_byte_%i", data->address_len - 1); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), key, hw_byte, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hw_byte); gtk_box_pack_start (GTK_BOX (hbox1), hw_byte, TRUE, TRUE, 0); hbox2 = GTK_DIALOG (hw_entry_dialog)->action_area; gtk_object_set_data (GTK_OBJECT (hw_entry_dialog), "hbox2", hbox2); gtk_widget_show (hbox2); gtk_container_set_border_width (GTK_CONTAINER (hbox2), 10); hbox3 = gtk_hbutton_box_new (); gtk_widget_ref (hbox3); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), "hbox3", hbox3, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hbox3); gtk_box_pack_start (GTK_BOX(hbox2), hbox3, TRUE, TRUE, 0); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox3), GTK_BUTTONBOX_END); hw_okay = gtk_button_new_with_label (_("OK")); gtk_widget_ref (hw_okay); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), "hw_okay", hw_okay, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hw_okay); /* gtk_widget_set_usize (hw_okay, 80, -2); */ gtk_container_add (GTK_CONTAINER (hbox2), hw_okay); GTK_WIDGET_SET_FLAGS (hw_okay, GTK_CAN_DEFAULT); hw_cancel = gtk_button_new_with_label (_("Cancel")); gtk_widget_ref (hw_cancel); gtk_object_set_data_full (GTK_OBJECT (hw_entry_dialog), "hw_cancel", hw_cancel, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hw_cancel); gtk_container_add (GTK_CONTAINER (hbox2), hw_cancel); GTK_WIDGET_SET_FLAGS (hw_cancel, GTK_CAN_DEFAULT); gtk_signal_connect (GTK_OBJECT (hw_okay), "clicked", GTK_SIGNAL_FUNC (hw_okay_clicked), data); gtk_signal_connect (GTK_OBJECT (hw_cancel), "clicked", GTK_SIGNAL_FUNC (hw_cancel_clicked), data); gtk_widget_grab_default (hw_okay); return hw_entry_dialog; } void nd_dialog_ync(const char *title, const char *message, ND_DialogCallback yes_cb, ND_DialogCallback no_cb, ND_DialogCallback cancel_cb, void *user_data) { nd_dialog_generic(ND_DIALOG_QUESTION, title, message, TRUE, NULL, user_data, 3, _("Yes"), yes_cb, _("No"), no_cb, _("Cancel"), cancel_cb); } void nd_dialog_message(const char *title, const char *message, gboolean modal) { nd_dialog_generic(ND_DIALOG_WARNING, title, message, modal, NULL, NULL, 1, _("OK"), NULL); } void nd_dialog_generic(ND_DialogType type, const char *title, const char *message, gboolean modal, GtkWidget *extra_area, void *user_data, int num_buttons, ...) { va_list button_args; int i; GtkWidget *dialog; GtkWidget *vbox; GtkWidget *hbox1, *hbox2, *hbox3; GtkWidget *label; GtkWidget *button; GtkWidget *pixmap = NULL; GtkWidget *frame; dialog = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (dialog), title); GTK_WINDOW (dialog)->type = GTK_WINDOW_DIALOG; gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER); gtk_window_set_modal (GTK_WINDOW (dialog), modal); gtk_window_set_default_size (GTK_WINDOW (dialog), 20, -1); gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, FALSE); if (user_data) gtk_object_set_data(GTK_OBJECT(dialog), "user_data", user_data); frame = gtk_frame_new (NULL); gtk_widget_ref (frame); gtk_object_set_data_full (GTK_OBJECT (dialog), "frame", frame, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (frame); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, TRUE, TRUE, 0); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_container_set_border_width (GTK_CONTAINER (frame), 15); vbox = gtk_vbox_new (FALSE, 0); gtk_widget_ref(vbox); gtk_object_set_data (GTK_OBJECT (dialog), "vbox", vbox); gtk_widget_show (vbox); gtk_object_set_data_full (GTK_OBJECT (dialog), "vbox", vbox, (GtkDestroyNotify) gtk_widget_unref); gtk_container_add (GTK_CONTAINER (frame), vbox); gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); hbox3 = gtk_hbox_new (FALSE, 0); gtk_widget_ref (hbox3); gtk_object_set_data_full (GTK_OBJECT (dialog), "hbox3", hbox3, (GtkDestroyNotify) gtk_widget_unref); gtk_container_set_border_width (GTK_CONTAINER (hbox3), 5); gtk_widget_show (hbox3); gtk_box_pack_start (GTK_BOX (vbox), hbox3, TRUE, TRUE, 0); switch (type) { case ND_DIALOG_QUESTION: pixmap = create_pixmap (dialog, "question.xpm"); break; case ND_DIALOG_WARNING: default: pixmap = create_pixmap (dialog, "exclamation.xpm"); } gtk_widget_ref (pixmap); gtk_object_set_data_full (GTK_OBJECT (dialog), "pixmap", pixmap, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (pixmap); gtk_box_pack_start (GTK_BOX (hbox3), pixmap, FALSE, TRUE, 0); gtk_misc_set_padding (GTK_MISC (pixmap), 5, 5); gtk_pixmap_set_build_insensitive (GTK_PIXMAP (pixmap), FALSE); label = gtk_label_new(message); gtk_widget_ref (label); gtk_object_set_data_full (GTK_OBJECT (dialog), "label", label, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (label); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); gtk_box_pack_start (GTK_BOX (hbox3), label, TRUE, TRUE, 0); if (extra_area) { GtkWidget *line; line = gtk_hseparator_new (); gtk_widget_ref (line); gtk_object_set_data_full (GTK_OBJECT (dialog), "line", line, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (line); gtk_box_pack_start (GTK_BOX (vbox), line, FALSE, FALSE, 0); gtk_object_set_data_full (GTK_OBJECT (dialog), "extra_area", extra_area, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (extra_area); gtk_box_pack_start (GTK_BOX (vbox), extra_area, TRUE, TRUE, 0); } hbox1 = GTK_DIALOG (dialog)->action_area; gtk_object_set_data (GTK_OBJECT (dialog), "hbox1", hbox1); gtk_widget_show (hbox1); gtk_container_set_border_width (GTK_CONTAINER (hbox1), 10); gtk_hbutton_box_set_spacing_default (5); hbox2 = gtk_hbutton_box_new (); gtk_widget_ref (hbox2); gtk_object_set_data_full (GTK_OBJECT (dialog), "hbox2", hbox2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hbox2); gtk_box_pack_start (GTK_BOX (hbox1), hbox2, TRUE, TRUE, 0); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox2), GTK_BUTTONBOX_END); va_start (button_args, num_buttons); for (i = 0; i < num_buttons; i++) { char *button_label; ND_DialogCallback callback; button_label = va_arg(button_args, char*); callback = va_arg(button_args, ND_DialogCallback); button = gtk_button_new_with_label (button_label); gtk_widget_ref (button); gtk_object_set_data_full (GTK_OBJECT (dialog), "", button, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (button); gtk_container_add (GTK_CONTAINER (hbox2), button); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (generic_button_clicked), callback); if (i == 0) gtk_widget_grab_default (button); } va_end (button_args); gtk_widget_show(dialog); } void nd_dialog_number(const char *message, ND_Base base, guint value, guint max, ND_NumberCallback callback_okay, ND_DialogCallback callback_cancel, LND_Packet *packet, void *user_data) { LND_Trace *trace; GtkWidget *w; GtkObject *adj; return_if_no_current_trace(trace); D_ENTER; if (max > 65535) { dialog_largenumber(message, value, callback_okay, callback_cancel, packet, user_data); return; } /* If we've not created this dialog before, create it first */ if (!number_dialog) { number_dialog = create_generic_number_dialog (); D_ASSERT_PTR(number_dialog); adj = gtk_adjustment_new(0, 0, max, 1, 1, 1); gtk_object_set_data(GTK_OBJECT(number_dialog), "adj", adj); } else { ND_GTK_GET(adj, number_dialog, "adj"); GTK_ADJUSTMENT(adj)->upper = max; } ND_GTK_GET(w, number_dialog, "data_entry_label"); gtk_label_set_text(GTK_LABEL(w), message); gtk_object_set_data(GTK_OBJECT(number_dialog), "callback_okay", callback_okay); gtk_object_set_data(GTK_OBJECT(number_dialog), "callback_cancel", callback_cancel); gtk_object_set_data(GTK_OBJECT(number_dialog), "packet", packet); gtk_object_set_data(GTK_OBJECT(number_dialog), "user_data", user_data); gtk_object_set_data(GTK_OBJECT(number_dialog), "value", GINT_TO_POINTER(value)); nd_dialog_number_update(); nd_dialog_number_set_base(base); gtk_widget_show(number_dialog); D_RETURN; } void nd_dialog_number_update(void) { char s[MAXPATHLEN]; guint value; GtkWidget *w; GtkObject *adj; D_ASSERT_PTR(number_dialog); if (!number_dialog) return; D_ENTER; value = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(number_dialog), "value")); adj = gtk_object_get_data(GTK_OBJECT(number_dialog), "adj"); if (GTK_ADJUSTMENT(adj)->upper < 256) g_snprintf(s, MAXPATHLEN, "0x%.2x", value); else if (GTK_ADJUSTMENT(adj)->upper < 65536) g_snprintf(s, MAXPATHLEN, "0x%.4x", value); else g_snprintf(s, MAXPATHLEN, "0x%x", value); ND_GTK_GET(w, number_dialog, "generic_entry"); gtk_entry_set_text(GTK_ENTRY(w), s); ND_GTK_GET(w, number_dialog, "generic_spin"); gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(w), GTK_ADJUSTMENT(adj)); gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), value); D_RETURN; } void nd_dialog_number_set_base(ND_Base base) { GtkWidget *spin, *entry, *dec_toggle, *hex_toggle; D_ASSERT_PTR(number_dialog); if (!number_dialog) return; D_ENTER; gtk_object_set_data(GTK_OBJECT(number_dialog), "base", GINT_TO_POINTER(base)); ND_GTK_GET(spin, number_dialog, "generic_spin"); ND_GTK_GET(entry, number_dialog, "generic_entry"); ND_GTK_GET(dec_toggle, number_dialog, "generic_decimal"); ND_GTK_GET(hex_toggle, number_dialog, "generic_hex"); switch (base) { case ND_BASE_HEX: gtk_widget_hide(spin); gtk_widget_show(entry); gtk_signal_handler_block_by_func(GTK_OBJECT(dec_toggle), on_number_decimal_toggled, NULL); gtk_signal_handler_block_by_func(GTK_OBJECT(hex_toggle), on_number_hex_toggled, NULL); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hex_toggle), TRUE); gtk_signal_handler_unblock_by_func(GTK_OBJECT(dec_toggle), on_number_decimal_toggled, NULL); gtk_signal_handler_unblock_by_func(GTK_OBJECT(hex_toggle), on_number_hex_toggled, NULL); break; case ND_BASE_DEC: default: gtk_widget_hide(entry); gtk_widget_show(spin); gtk_signal_handler_block_by_func(GTK_OBJECT(dec_toggle), on_number_decimal_toggled, NULL); gtk_signal_handler_block_by_func(GTK_OBJECT(hex_toggle), on_number_hex_toggled, NULL); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dec_toggle), TRUE); gtk_signal_handler_unblock_by_func(GTK_OBJECT(dec_toggle), on_number_decimal_toggled, NULL); gtk_signal_handler_unblock_by_func(GTK_OBJECT(hex_toggle), on_number_hex_toggled, NULL); } D_RETURN; } void nd_dialog_number_ok(GtkWidget *dialog) { ND_Base base; ND_NumberCallback callback; LND_Packet *packet; GtkWidget *w; GtkWidget *entry; void *user; guint value; char *errptr = NULL; D_ENTER; ND_GTK_GET(w, dialog, "generic_spin"); callback = gtk_object_get_data(GTK_OBJECT(dialog), "callback_okay"); user = gtk_object_get_data(GTK_OBJECT(dialog), "user_data"); packet = gtk_object_get_data(GTK_OBJECT(dialog), "packet"); base = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(dialog), "base")); switch(base) { case ND_BASE_HEX: ND_GTK_GET(entry, dialog, "generic_entry"); value = strtol(gtk_entry_get_text(GTK_ENTRY(entry)), &errptr, 16); break; case ND_BASE_DEC: default: ND_GTK_GET(entry, dialog, "generic_spin"); value = strtol(gtk_entry_get_text(GTK_ENTRY(entry)), &errptr, 10); } if (*errptr == '\0') { D(("Calling callback with value %u\n", value)); gtk_widget_hide(dialog); if (callback) callback(packet, user, value); } D_RETURN; } void nd_dialog_number_cancel(GtkWidget *dialog) { ND_DialogCallback callback; void *user; callback = gtk_object_get_data(GTK_OBJECT(dialog), "callback_cancel"); user = gtk_object_get_data(GTK_OBJECT(dialog), "user_data"); if (callback) callback(user); gtk_widget_hide(dialog); } static void dialog_largenumber(const char *message, guint value, ND_NumberCallback callback_ok, ND_DialogCallback callback_cancel, LND_Packet *packet, void *user_data) { static GtkWidget *dialog = NULL; GtkWidget *w, *entry, *arrow; char s[MAXPATHLEN]; if (!dialog) { dialog = create_largenumber_dialog (); ND_GTK_GET(w, dialog, "largenumber_up"); arrow = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_NONE); gtk_widget_show(arrow); gtk_widget_ref(arrow); gtk_object_set_data_full (GTK_OBJECT (dialog), "arrow1", arrow, (GtkDestroyNotify) gtk_widget_unref); gtk_container_remove(GTK_CONTAINER(w), GTK_BIN(w)->child); gtk_container_add(GTK_CONTAINER(w), arrow); ND_GTK_GET(w, dialog, "largenumber_down"); arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE); gtk_widget_show(arrow); gtk_widget_ref(arrow); gtk_object_set_data_full (GTK_OBJECT (dialog), "arrow2", arrow, (GtkDestroyNotify) gtk_widget_unref); gtk_container_remove(GTK_CONTAINER(w), GTK_BIN(w)->child); gtk_container_add(GTK_CONTAINER(w), arrow); } if (message) { ND_GTK_GET(w, dialog, "largenumber_label"); gtk_label_set_text(GTK_LABEL(w), message); } g_snprintf(s, MAXPATHLEN, "%u", value); ND_GTK_GET(entry, dialog, "largenumber_entry"); gtk_entry_set_text(GTK_ENTRY(entry), s); gtk_object_set_data(GTK_OBJECT(dialog), "callback_okay", callback_ok); gtk_object_set_data(GTK_OBJECT(dialog), "callback_cancel", callback_cancel); gtk_object_set_data(GTK_OBJECT(dialog), "user_data", user_data); gtk_object_set_data(GTK_OBJECT(dialog), "packet", packet); gtk_widget_show(dialog); } void nd_dialog_largenumber_ok(GtkWidget *dialog) { ND_NumberCallback callback_okay; LND_Packet *packet; GtkWidget *entry; char *errptr; guint value; void *user_data; if (!dialog) return; callback_okay = gtk_object_get_data(GTK_OBJECT(dialog), "callback_okay"); user_data = gtk_object_get_data(GTK_OBJECT(dialog), "user_data"); packet = gtk_object_get_data(GTK_OBJECT(dialog), "packet"); ND_GTK_GET(entry, dialog, "largenumber_entry"); value = strtoul(gtk_entry_get_text(GTK_ENTRY(entry)), &errptr, 10); if ((*errptr != '\0') || (errno == ERANGE)) return; if (callback_okay) callback_okay(packet, user_data, value); gtk_widget_hide(dialog); } void nd_dialog_largenumber_up(GtkWidget *dialog) { GtkWidget *entry; char *errptr; char s[256]; guint value; if (!dialog) return; ND_GTK_GET(entry, dialog, "largenumber_entry"); value = strtoul(gtk_entry_get_text(GTK_ENTRY(entry)), &errptr, 10); if ((*errptr != '\0') || (errno == ERANGE)) return; g_snprintf(s, 256, "%u", value + 1); gtk_entry_set_text(GTK_ENTRY(entry), s); } void nd_dialog_largenumber_down(GtkWidget *dialog) { GtkWidget *entry; char *errptr; char s[256]; guint value; if (!dialog) return; ND_GTK_GET(entry, dialog, "largenumber_entry"); value = strtoul(gtk_entry_get_text(GTK_ENTRY(entry)), &errptr, 10); if ((*errptr != '\0') || (errno == ERANGE)) return; g_snprintf(s, 256, "%u", value - 1); gtk_entry_set_text(GTK_ENTRY(entry), s); } void nd_dialog_string(const char *title, const char *message, ND_StringCallback callback_okay, ND_DialogCallback callback_cancel, void *user_data) { static GtkWidget *string_dialog; GtkWidget *w; if (!string_dialog) string_dialog = create_string_dialog(); /* Reset entry field */ ND_GTK_GET(w, string_dialog, "string_entry"); gtk_entry_set_text(GTK_ENTRY(w), ""); /* Make sure the entry area has the focus: */ gtk_widget_grab_focus(w); /* Set dialog title, if given */ if (title) gtk_window_set_title(GTK_WINDOW(string_dialog), title); /* Set dialog message, if given */ if (message) { ND_GTK_GET(w, string_dialog, "data_entry_label"); gtk_label_set_text(GTK_LABEL(w), message); } gtk_object_set_data(GTK_OBJECT(string_dialog), "callback_okay", callback_okay); gtk_object_set_data(GTK_OBJECT(string_dialog), "callback_cancel", callback_cancel); gtk_object_set_data(GTK_OBJECT(string_dialog), "user_data", user_data); gtk_widget_show(string_dialog); } void nd_dialog_string_ok(GtkWidget *dialog) { ND_StringCallback callback; void *user; char *string; GtkWidget *w; ND_GTK_GET(w, dialog, "string_entry"); callback = gtk_object_get_data(GTK_OBJECT(dialog), "callback_okay"); user = gtk_object_get_data(GTK_OBJECT(dialog), "user_data"); string = gtk_entry_get_text(GTK_ENTRY(w)); if (!string || strlen(string) == 0) return; if (callback) callback(string, user); gtk_widget_hide(dialog); } void nd_dialog_string_cancel(GtkWidget *dialog) { ND_DialogCallback callback; void *user; callback = gtk_object_get_data(GTK_OBJECT(dialog), "callback_cancel"); user = gtk_object_get_data(GTK_OBJECT(dialog), "user_data"); if (callback) callback(user); gtk_widget_hide(dialog); } void nd_dialog_hardware_address(const char *message, guchar *address, int address_len, ND_AddressCallback callback_okay, ND_DialogCallback callback_cancel, LND_Packet *packet, void *user_data) { ND_HardwareDialogData *data; GtkWidget *dialog, *w; char key[MAXPATHLEN]; char val[MAXPATHLEN]; int i; data = g_new0(ND_HardwareDialogData, 1); D_ASSERT_PTR(data); if (!data) return; data->address_len = address_len; data->callback_okay = callback_okay; data->callback_cancel = callback_cancel; data->packet = packet; data->user_data = user_data; dialog = dialog_create_hardware_address(message, data); for (i = 0; i < address_len; i++) { g_snprintf(key, MAXPATHLEN, "hw_byte_%i", i); ND_GTK_GET(w, dialog, key); sprintf(val, "%.2x", address[i]); gtk_entry_set_text(GTK_ENTRY(w), val); } gtk_widget_show(dialog); } void nd_dialog_ip(const char *message, guchar *ip_address, ND_AddressCallback callback_ok, ND_DialogCallback callback_cancel, LND_Packet *packet, void *user_data) { GtkLabel *label; GtkSpinButton *sb; guchar *ip_address_buf; if (!ip_address) return; if (!ip_dialog) { ip_address_buf = g_new0(guchar, 4); ip_dialog = create_ip_dialog(); gtk_object_set_data(GTK_OBJECT(ip_dialog), "ip_address", ip_address_buf); } ND_GTK_GET(ip_address_buf, ip_dialog, "ip_address"); memcpy(ip_address_buf, ip_address, 4*sizeof(char)); ND_GTK_GET(label, ip_dialog, "ip_label"); gtk_label_set_text(label, message); ND_GTK_GET(sb, ip_dialog, "spinbutton1"); gtk_spin_button_set_value(sb, ip_address[0]); ND_GTK_GET(sb, ip_dialog, "spinbutton2"); gtk_spin_button_set_value(sb, ip_address[1]); ND_GTK_GET(sb, ip_dialog, "spinbutton3"); gtk_spin_button_set_value(sb, ip_address[2]); ND_GTK_GET(sb, ip_dialog, "spinbutton4"); gtk_spin_button_set_value(sb, ip_address[3]); gtk_object_set_data(GTK_OBJECT(ip_dialog), "data", user_data); gtk_object_set_data(GTK_OBJECT(ip_dialog), "packet", packet); gtk_object_set_data(GTK_OBJECT(ip_dialog), "callback_ok", callback_ok); gtk_object_set_data(GTK_OBJECT(ip_dialog), "callback_cancel", callback_cancel); gtk_widget_show(ip_dialog); } void nd_dialog_ip_ok(void) { ND_AddressCallback callback_ok; void *data; LND_Packet *packet; guchar *ip_address_buf; GtkSpinButton *sb; if (!ip_dialog || !GTK_WIDGET_VISIBLE(ip_dialog)) return; data = gtk_object_get_data(GTK_OBJECT(ip_dialog), "data"); packet = gtk_object_get_data(GTK_OBJECT(ip_dialog), "packet"); callback_ok = gtk_object_get_data(GTK_OBJECT(ip_dialog), "callback_ok"); ip_address_buf = gtk_object_get_data(GTK_OBJECT(ip_dialog), "ip_address"); ND_GTK_GET(sb, ip_dialog, "spinbutton1"); ip_address_buf[0] = (guchar) gtk_spin_button_get_value_as_int(sb); ND_GTK_GET(sb, ip_dialog, "spinbutton2"); ip_address_buf[1] = (guchar) gtk_spin_button_get_value_as_int(sb); ND_GTK_GET(sb, ip_dialog, "spinbutton3"); ip_address_buf[2] = (guchar) gtk_spin_button_get_value_as_int(sb); ND_GTK_GET(sb, ip_dialog, "spinbutton4"); ip_address_buf[3] = (guchar) gtk_spin_button_get_value_as_int(sb); gtk_widget_hide(ip_dialog); if (callback_ok) callback_ok(ip_address_buf, 4, packet, data); } void nd_dialog_ip_cancel(void) { ND_DialogCallback callback_cancel; void *data; if (!ip_dialog || !GTK_WIDGET_VISIBLE(ip_dialog)) return; data = gtk_object_get_data(GTK_OBJECT(ip_dialog), "data"); callback_cancel = gtk_object_get_data(GTK_OBJECT(ip_dialog), "callback_cancel"); gtk_widget_hide(ip_dialog); if (callback_cancel) callback_cancel(data); } void nd_dialog_filesel(const char *title, const char *fname, ND_StringCallback callback_fname, void *user_data) { if (!callback_fname) return; if (!filesel_dialog) filesel_dialog = create_filesel(); gtk_window_set_title(GTK_WINDOW(filesel_dialog), title); gtk_object_set_data(GTK_OBJECT(filesel_dialog), "callback", callback_fname); gtk_object_set_data(GTK_OBJECT(filesel_dialog), "user_data", user_data); if (fname) gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel_dialog), fname); gtk_widget_show(filesel_dialog); } void nd_dialog_filesel_ok(GtkWidget *dialog) { ND_StringCallback callback; char *filename; void *user_data; if (!dialog) return; filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(dialog))); callback = gtk_object_get_data(GTK_OBJECT(dialog), "callback"); user_data = gtk_object_get_data(GTK_OBJECT(dialog), "user_data"); if (callback) callback(filename, user_data); g_free(filename); } void nd_dialog_filesel_close(void) { if (!filesel_dialog) return; gtk_widget_hide(filesel_dialog); } /* This callback is called when a trace has been saved successfully. */ static void dialog_exit_trace_saved(void *user_data) { GtkWidget *entry_hbox; ND_GTK_GET(entry_hbox, user_data, "entry_hbox"); gtk_widget_set_sensitive(entry_hbox, FALSE); } /* This callback is called when the user presses the "Save ..." button to save one of the modified traces. */ static void dialog_exit_save_clicked(GtkButton *button, gpointer user_data) { LND_Trace *trace = (LND_Trace *) user_data; nd_trace_save_as_dialog(trace, dialog_exit_trace_saved, button); return; TOUCH(button); } static GtkWidget * dialog_exit_create_entry(LND_Trace *trace) { GtkWidget *entry_hbox; GtkWidget *filename_label; GtkWidget *save_button; entry_hbox = gtk_hbox_new (FALSE, 5); gtk_widget_ref (entry_hbox); gtk_widget_show (entry_hbox); filename_label = gtk_label_new (libnd_trace_get_name(trace)); gtk_widget_ref (filename_label); gtk_object_set_data_full (GTK_OBJECT (entry_hbox), "filename_label", filename_label, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (filename_label); gtk_box_pack_start (GTK_BOX (entry_hbox), filename_label, TRUE, TRUE, 0); gtk_label_set_justify (GTK_LABEL (filename_label), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment (GTK_MISC (filename_label), 0.0, 0.5); save_button = gtk_button_new_with_label (_("Save ...")); gtk_widget_ref (save_button); gtk_object_set_data_full (GTK_OBJECT (entry_hbox), "save_button", save_button, (GtkDestroyNotify) gtk_widget_unref); /* Make hbox available from button: */ gtk_object_set_data(GTK_OBJECT(save_button), "entry_hbox", entry_hbox); gtk_widget_show (save_button); gtk_box_pack_start (GTK_BOX (entry_hbox), save_button, FALSE, FALSE, 0); gtk_signal_connect (GTK_OBJECT (save_button), "clicked", GTK_SIGNAL_FUNC (dialog_exit_save_clicked), trace); return entry_hbox; } /* This is called once for each loaded trace, to set up the vbox containing all the modified traces. */ static void dialog_exit_trace_cb(LND_Trace *trace, void *user_data) { GtkWidget *vbox = (GtkWidget *) user_data; GtkWidget *entry_hbox; if (!trace->dirty) return; entry_hbox = dialog_exit_create_entry(trace); gtk_box_pack_start (GTK_BOX (vbox), entry_hbox, TRUE, FALSE, 5); gtk_object_set_data_full (GTK_OBJECT (vbox), "", entry_hbox, (GtkDestroyNotify) gtk_widget_unref); } /* This callback is called when the user clicks the Exit button in the exit dialog. */ static void dialog_unsafe_exit_cb(void *user_data) { libnd_prefs_save(); exit(0); TOUCH(user_data); } void nd_dialog_exit(void) { GtkWidget *entry_vbox; entry_vbox = gtk_vbox_new (FALSE, 0); gtk_widget_ref (entry_vbox); gtk_widget_show (entry_vbox); nd_trace_registry_foreach(dialog_exit_trace_cb, entry_vbox); nd_dialog_generic(ND_DIALOG_WARNING, _("Unsaved files."), _("Some traces have changed but have not been saved yet.\n" "Select traces you want to save as desired, then exit.\n"), FALSE, entry_vbox, entry_vbox, 2, _("Exit"), dialog_unsafe_exit_cb, _("Cancel"), NULL); } void nd_dialog_about(void) { static GtkWidget *dialog = NULL; static char *about_text =N_("\n" " Programming:\n" " Christian Kreibich \n" "\n" " Help, Feedback,\n" " Suggestions, Inspiration:\n" " Mark Handley\n" " Vern Paxson\n" " Daniel Stodden\n" " Euan Harris\n" " Andrew Moore\n" "\n" " Yet Another SRG Production\n" " http://www.cl.cam.ac.uk/Research/SRG\n\n" " "); GtkWidget *label; if (!dialog) { GtkWidget *w; int pos = 0; dialog = create_about_dialog(); /* HORRIBLE workaround for glade segfault! */ ND_GTK_GET(w, dialog, "about_text"); gtk_editable_insert_text(GTK_EDITABLE(w), about_text, strlen(about_text), &pos); } if ((label = gtk_object_get_data(GTK_OBJECT(dialog), "about_version_label"))) { char label_string[MAXPATHLEN]; #ifdef RELEASE g_snprintf(label_string, MAXPATHLEN, _("Version %s"), VERSION); #else g_snprintf(label_string, MAXPATHLEN, "%s %s,\n%s %s", _("Development Version"), VERSION, _("last commit on"), LAST_UPDATE); #endif gtk_label_set_text(GTK_LABEL(label), label_string); } gtk_widget_show(dialog); } void nd_dialog_fontsel(const char *title, const char *font_name, ND_StringCallback callback_ok, void *user_data) { static GtkWidget *dialog = NULL; if (!dialog) dialog = create_font_sel(); gtk_window_set_title(GTK_WINDOW(dialog), title); if (font_name) gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), font_name); gtk_object_set_data(GTK_OBJECT(dialog), "callback", callback_ok); gtk_object_set_data(GTK_OBJECT(dialog), "user_data", user_data); gtk_widget_show(dialog); } void nd_dialog_fontsel_ok(GtkFontSelectionDialog *dialog) { if (!dialog) return; nd_dialog_fontsel_apply(dialog); gtk_widget_hide(GTK_WIDGET(dialog)); } void nd_dialog_fontsel_cancel(GtkFontSelectionDialog *dialog) { gtk_widget_hide(GTK_WIDGET(dialog)); } void nd_dialog_fontsel_apply(GtkFontSelectionDialog *dialog) { ND_StringCallback callback; void *user_data; char *font_name; if (!dialog) return; font_name = gtk_font_selection_dialog_get_font_name(dialog); callback = gtk_object_get_data(GTK_OBJECT(dialog), "callback"); user_data = gtk_object_get_data(GTK_OBJECT(dialog), "user_data"); if (callback) callback(font_name, user_data); g_free(font_name); }