/*
Copyright (C) 2000 - 2004 Christian Kreibich <christian@whoop.org>.
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 <config.h>
#endif
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <gtk/gtk.h>
#include <nd.h>
#include <nd_gui.h>
#include <nd_main.h>
#include <nd_trace_registry.h>
#include <nd_dialog.h>
#include <nd_timestamp.h>
#include <callbacks.h>
#include <interface.h>
#include <support.h>
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 <christian.kreibich-AT-cl.cam.ac.uk>\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);
}
syntax highlighted by Code2HTML, v. 0.9.1