Ethereal-dev: [Ethereal-dev] [PATCH] Wish list item 17 (packet generator)
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Lanfranco Salinari <lanfranco.salinari@xxxxxxxxxxxxx>
Date: Tue, 02 Sep 2003 21:54:03 +0200
Hello, I post this patch again, hoping that someone notices it. I think that a packet generator would be a useful feature for ethereal, so I hope someone will give me his opinion about the patch and the work that remains to be done, as I have no experience with GTK. Best regards, Lanfranco
diff -urN --exclude='*~' ethereal-0.9.14-orig/gtk/gen_packet.c ethereal-0.9.14/gtk/gen_packet.c
--- ethereal-0.9.14-orig/gtk/gen_packet.c 1970-01-01 01:00:00.000000000 +0100
+++ ethereal-0.9.14/gtk/gen_packet.c 2003-08-25 21:35:46.000000000 +0200
@@ -0,0 +1,358 @@
+/* gen_packet.c
+ * Routines for packet generation
+ * Copyright 2003, L. Salinari <lanfranco.salinari@xxxxxxxxxxxxx>
+ * Network-related code written with L.Rossi
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <pcap.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <linux/if.h>
+#include <linux/if_packet.h>
+
+#include "dlg_utils.h"
+#include "ui_util.h"
+#include "main.h"
+#include "compat_macros.h"
+#include "gtkglobals.h"
+
+#include <string.h>
+#include "prefs.h"
+#include "simple_dialog.h"
+#include "proto_draw.h"
+#include "keys.h"
+#include "gtk_hex.h"
+#include "pcap-util.h"
+#include <epan/epan.h>
+#include <epan/packet.h>
+#include <epan/plugins.h>
+#include <epan/epan_dissect.h>
+#include "gen_packet.h"
+
+/* Data structure holding information about a packet-detail window. */
+struct PacketGenData {
+ frame_data *frame; /* The frame being displayed */
+ union wtap_pseudo_header pseudo_header; /* Pseudo-header for packet */
+ guint8 *pd; /* Data for packet */
+ GtkWidget *main;
+ GtkWidget *tv_scrollw;
+ GtkWidget *tree_view;
+ field_info *finfo_selected;
+ epan_dissect_t *edt;
+ GtkWidget *hex;
+ GtkWidget *interf;
+};
+
+#define E_BYTE_VIEW_TREE_PTR "byte_view_tree_ptr"
+#define E_BYTE_VIEW_TREE_VIEW_PTR "byte_view_tree_view_ptr"
+#define E_BYTE_VIEW_NDIGITS_KEY "byte_view_ndigits"
+#define E_BYTE_VIEW_TVBUFF_KEY "byte_view_tvbuff"
+#define E_BYTE_VIEW_START_KEY "byte_view_start"
+#define E_BYTE_VIEW_END_KEY "byte_view_end"
+#define E_BYTE_VIEW_ENCODE_KEY "byte_view_encode"
+
+
+static void
+byte_view_show_cb(GtkWidget *bv, gpointer data _U_)
+{
+ guint8 *byte_data;
+ guint byte_len;
+ GtkHex *hex = GTK_HEX(bv);
+
+ byte_data = get_byte_view_data_and_length(bv, &byte_len);
+ if (byte_data == NULL) {
+ /* This must be the dummy byte view if no packet is selected. */
+ return;
+ }
+ hex->hex_font = m_r_font;
+ gtk_hex_set_content(hex, byte_data, byte_len);
+}
+
+static gboolean
+on_hex_changed(GtkWidget *widget,
+ int index,
+ int len,
+ gpointer data)
+{
+ struct PacketGenData *DataPtr = (struct PacketGenData *) data;
+ GtkHex *byte_view = GTK_HEX(DataPtr->hex);
+
+ /* TBD: update of protocol view */
+ DataPtr->edt = epan_dissect_new(TRUE, TRUE);
+ epan_dissect_run(DataPtr->edt,
+ &DataPtr->pseudo_header,
+ byte_view->data,
+ DataPtr->frame,
+ &cfile.cinfo);
+ epan_dissect_fill_in_columns(DataPtr->edt);
+ proto_tree_draw(DataPtr->edt->tree, DataPtr->tree_view);
+
+ return TRUE;
+ TOUCH(widget);
+ TOUCH(index);
+ TOUCH(len);
+}
+
+static GtkWidget *
+create_hex_view(epan_dissect_t *edt, GtkWidget *tree_view,
+ GtkWidget *byte_nb_ptr, struct PacketGenData *DataPtr)
+{
+ data_source *src;
+ GtkWidget *byte_view;
+
+ src = edt->pi.data_src->data;
+ byte_view = gtk_hex_new();
+
+ OBJECT_SET_DATA(byte_view, E_BYTE_VIEW_TVBUFF_KEY, src->tvb);
+ gtk_container_add(GTK_CONTAINER(byte_nb_ptr), byte_view);
+
+ SIGNAL_CONNECT(byte_view, "show", byte_view_show_cb, NULL);
+ SIGNAL_CONNECT(byte_view, "changed", on_hex_changed, (gpointer) DataPtr);
+
+ OBJECT_SET_DATA(byte_view, E_BYTE_VIEW_TREE_PTR, edt->tree);
+ OBJECT_SET_DATA(byte_view, E_BYTE_VIEW_TREE_VIEW_PTR, tree_view);
+
+ gtk_widget_show(byte_view);
+
+ return byte_view;
+}
+
+static void
+send_packet (gchar *packet, guint len, gchar *ifname)
+{
+ int sockfd; /* Socket descriptor */
+ int err;
+ struct sockaddr_ll sll;
+ struct ifreq ifr;
+
+
+ /* We want only Ethernet frames containing IP data */
+ sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (sockfd < 0) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "ERROR: socket not created");
+ return;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+ if (ioctl(sockfd, SIOCGIFINDEX, &ifr) == -1) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "ERROR: could not get if index");
+ return;
+ }
+ memset(&sll, 0, sizeof(sll));
+ sll.sll_family = AF_PACKET;
+ sll.sll_ifindex = ifr.ifr_ifindex;
+ sll.sll_protocol = htons(ETH_P_ALL);
+
+#if 0
+ /* Give the socket a name. */
+ if (bind (sockfd, (struct sockaddr *) &sll, sizeof (sll)) < 0) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "ERROR: could not bind socket");
+ return;
+ }
+#endif
+
+ /* Read one packet */
+ err = sendto (sockfd, packet, len, 0, (struct sockaddr *) &sll, sizeof (sll));
+ if (err < 0) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "ERROR: could not write on socket");
+ return;
+ }
+
+ close(sockfd);
+
+ return;
+}
+
+static void
+print_buffer(GtkWidget *widget _U_, gpointer data)
+{
+ struct PacketGenData *PGdata = (struct PacketGenData *)data;
+ GtkHex *byte_view = GTK_HEX(PGdata->hex);
+ GtkCombo *if_combo = GTK_COMBO(PGdata->interf);
+ GtkEntry *if_entry = GTK_ENTRY(if_combo->entry);
+ gchar *if_name;
+ unsigned int i;
+
+#ifdef DEBUG
+ for (i=0; i<byte_view->data_size; i++) {
+ printf ("%02x ", (byte_view->data)[i]);
+ if (i%16 == 15)
+ printf ("\n");
+ }
+ printf ("\n");
+#endif
+ if_name = gtk_entry_get_text(if_entry);
+#ifdef DEBUG
+ printf ("Interface = %s\n", if_name);
+#endif
+ if (strcmp(if_name,"")) {
+ send_packet (byte_view->data, byte_view->data_size, if_name);
+ }
+ else {
+ simple_dialog(ESD_TYPE_WARN, NULL, "No interface selected");
+ }
+ return;
+}
+
+static void
+main_win_destroy(GtkWidget *widget _U_, gpointer data)
+{
+ struct PacketGenData *DataPtr = (struct PacketGenData *)data;
+
+ g_free(DataPtr->pd);
+ g_free(DataPtr);
+
+ return;
+}
+
+
+/* Callback for menu */
+void
+packet_generator(GtkWidget *w _U_, gpointer d _U_)
+{
+ GtkWidget *main_w, *main_vbox, *pane,
+ *tree_view, *tv_scrollw,
+ *send_button, *if_lb, *if_hbox,
+ *if_cb, *hex_view;
+ struct PacketGenData *DataPtr;
+ gint tv_size = 95;
+ GList *if_list;
+ int err;
+ char err_str[PCAP_ERRBUF_SIZE];
+
+
+ /* Allocate data structure to represent this window. */
+ DataPtr = (struct PacketGenData *) g_malloc(sizeof(struct PacketGenData));
+
+ /* Nothing was selected: TBD later */
+ if (cfile.current_frame == NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "No packet selected");
+ return;
+ }
+ else {
+ DataPtr->frame = cfile.current_frame;
+ memcpy(&DataPtr->pseudo_header, &cfile.pseudo_header, sizeof DataPtr->pseudo_header);
+ DataPtr->pd = (guint8 *) g_malloc(DataPtr->frame->cap_len);
+ memcpy(DataPtr->pd, cfile.pd, DataPtr->frame->cap_len);
+ DataPtr->edt = epan_dissect_new(TRUE, TRUE);
+ epan_dissect_run(DataPtr->edt,
+ &DataPtr->pseudo_header,
+ DataPtr->pd,
+ DataPtr->frame,
+ &cfile.cinfo);
+ epan_dissect_fill_in_columns(DataPtr->edt);
+ }
+
+ main_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(main_w), "Ethereal: Packet Generator");
+ gtk_window_set_default_size(GTK_WINDOW(main_w), DEF_WIDTH, -1);
+
+ /* Container for paned windows */
+ main_vbox = gtk_vbox_new(FALSE, 1);
+ gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
+ gtk_container_add(GTK_CONTAINER(main_w), main_vbox);
+ gtk_widget_show(main_vbox);
+
+ /* Panes for the tree and byte view */
+ pane = gtk_vpaned_new();
+ gtk_paned_gutter_size(GTK_PANED(pane), (GTK_PANED(pane))->handle_size);
+ gtk_container_add(GTK_CONTAINER(main_vbox), pane);
+ gtk_widget_show(pane);
+
+ /* Tree view */
+ create_tree_view(tv_size, &prefs, pane, &tv_scrollw, &tree_view);
+
+ gtk_widget_show(tree_view);
+
+ DataPtr->main = main_w;
+ DataPtr->tv_scrollw = tv_scrollw;
+ DataPtr->tree_view = tree_view;
+
+ /* draw the protocol tree & print hex data */
+ hex_view = create_hex_view(DataPtr->edt, tree_view, pane, DataPtr);
+ proto_tree_draw(DataPtr->edt->tree, tree_view);
+
+ DataPtr->hex = hex_view;
+ DataPtr->finfo_selected = NULL;
+
+ /* Interface and buttons box */
+ if_hbox = gtk_hbox_new(FALSE, 1);
+ gtk_container_border_width(GTK_CONTAINER(if_hbox), 0);
+ gtk_box_pack_start(GTK_BOX(main_vbox), if_hbox, FALSE, TRUE, 0);
+ gtk_widget_show(if_hbox);
+
+ /* Send button */
+ send_button = gtk_button_new_with_label("Send");
+ gtk_box_pack_start(GTK_BOX(if_hbox), send_button, FALSE, TRUE, 1);
+ gtk_widget_show(send_button);
+
+ /* Get interfaces'names */
+ if_list = get_interface_list(&err, err_str);
+ if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Can't get list of interfaces: %s",
+ err_str);
+ }
+
+ if_lb = gtk_label_new("Interface:");
+ gtk_box_pack_start(GTK_BOX(if_hbox), if_lb, FALSE, FALSE, 6);
+ gtk_widget_show(if_lb);
+
+
+ if_cb = gtk_combo_new();
+ if (if_list != NULL)
+ gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
+ if (cfile.iface == NULL && prefs.capture_device != NULL) {
+ /* No interface was specified on the command line or in a previous
+ capture, but there is one specified in the preferences file;
+ make the one from the preferences file the default */
+ cfile.iface = g_strdup(prefs.capture_device);
+ }
+ if (cfile.iface != NULL)
+ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cfile.iface);
+ else if (if_list != NULL)
+ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), if_list->data);
+ gtk_box_pack_start(GTK_BOX(if_hbox), if_cb, TRUE, TRUE, 6);
+ gtk_widget_show(if_cb);
+
+ free_interface_list(if_list);
+
+ DataPtr->interf = if_cb;
+
+ SIGNAL_CONNECT(send_button, "clicked", print_buffer, DataPtr);
+ SIGNAL_CONNECT(main_w, "destroy", main_win_destroy, DataPtr);
+
+ gtk_widget_show_all(main_w);
+
+ return;
+}
diff -urN --exclude='*~' ethereal-0.9.14-orig/gtk/gen_packet.h ethereal-0.9.14/gtk/gen_packet.h
--- ethereal-0.9.14-orig/gtk/gen_packet.h 1970-01-01 01:00:00.000000000 +0100
+++ ethereal-0.9.14/gtk/gen_packet.h 2003-07-26 14:44:50.000000000 +0200
@@ -0,0 +1,29 @@
+/* gen_packet.h
+ * Definitions for packet generation code
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GEN_PACKET_H__
+#define __GEN_PACKET_H__
+
+void
+packet_generator(GtkWidget *w _U_, gpointer d _U_);
+
+#endif
diff -urN --exclude='*~' ethereal-0.9.14-orig/gtk/gtk_hex.c ethereal-0.9.14/gtk/gtk_hex.c
--- ethereal-0.9.14-orig/gtk/gtk_hex.c 1970-01-01 01:00:00.000000000 +0100
+++ ethereal-0.9.14/gtk/gtk_hex.c 2003-08-25 21:28:57.000000000 +0200
@@ -0,0 +1,1527 @@
+
+/*
+
+Copyright (C) 2000, 2001, 2002 Christian Kreibich <christian@xxxxxxxxx>.
+
+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.
+
+*/
+#define GTK_ENABLE_BROKEN
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+
+#include "gtk_hex.h"
+
+enum {
+ CHANGED,
+ MOVE_CURSOR,
+ LAST_SIGNAL
+};
+
+static GtkVBoxClass *parent_class = NULL;
+static guint hex_signals[LAST_SIGNAL] = { 0 };
+
+struct _GtkHexPrivate
+{
+ GtkText *null_map;
+};
+
+/* The width of a line of text in the hex-mode view, consisting
+ * of offset, hex view and ascii view:
+ *
+ * 32 + 16 characters per 8 Bytes, twice
+ * (2*7) + Single space between bytes, twice
+ * 4 + Two spaces between 8-byte sets and ascii
+ * 1 + For newline
+ * 17 + For ascii display, with spacer column
+ * 6 For 5-digit offset counter, including spacer
+ */
+#define HEX_LINE_WIDTH 74
+
+#define HEX_LINE_START 6
+#define HEX_LINE_END 53
+#define HEX_LINE_START_ASCII 56
+#define HEX_LINE_START_RIGHT_ASCII 65
+#define HEX_LINE_LEFT_MIDDLE 28
+#define HEX_LINE_RIGHT_MIDDLE 31
+#define HEX_BLOCK_LEN 23
+
+#define NULL_CHAR 0xF8
+#define NONPRINT_CHAR 0xB7
+
+static int hex_get_nowhite_index(GtkHex *hex, int index);
+static gboolean hex_cursor_over_hex(GtkHex *hex);
+static gboolean hex_cursor_over_hex_ascii(GtkHex *hex);
+static gboolean hex_cursor_over_high_nibble(GtkHex *hex);
+static int hex_cursor_index_to_byte_index(GtkHex *hex);
+static void hex_byte_index_to_cursor_indices(int byte_index, int *i1, int *i2);
+static void hex_sync_data_to_ascii(GtkHex *hex);
+static void hex_text_ascii_colorify(GtkHex *hex, guint start, int length);
+static void hex_text_set_cursor(GtkHex *hex, guint index);
+static gboolean hex_is_char_unprintable(guchar val);
+
+
+/* Sets the editor into hex mode
+ */
+static void
+on_mode_hex_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ if (gtk_toggle_button_get_active(togglebutton))
+ gtk_hex_set_mode((GtkHex*) user_data, GTK_RAW_HEX);
+}
+
+
+/* Sets the editor into ascii mode
+ */
+static void
+on_mode_ascii_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ if (gtk_toggle_button_get_active(togglebutton))
+ gtk_hex_set_mode((GtkHex*) user_data, GTK_RAW_ASCII);
+}
+
+
+/* We use the motion notify callback only to kill the object's
+ * handling of text selection -- we use the selection as our
+ * cursor, thus we want to disable it. This works through setting
+ * the pressed button to zero, making the object's handler think
+ * no button was pressed and changing nothing. This handler
+ * thus must be called *before* the object's handler
+ */
+static gboolean
+on_hex_text_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer user_data)
+{
+ GtkHex *hex = GTK_HEX(user_data);
+
+ if (hex->mode == GTK_RAW_HEX)
+ GTK_TEXT(hex->hex_text)->button = 0;
+
+ return FALSE;
+ TOUCH(event);
+ TOUCH(widget);
+}
+
+
+/* This handler takes care of updating the null
+ * map when text is deleted.
+ */
+static gboolean
+on_hex_text_deleted(GtkWidget *widget,
+ gint start,
+ gint end,
+ gpointer user_data)
+{
+ GtkHex *hex = GTK_HEX(user_data);
+
+ if (hex->mode == GTK_RAW_ASCII)
+ {
+ gtk_editable_delete_text(GTK_EDITABLE(hex->priv->null_map),
+ start, end);
+ hex_text_ascii_colorify(hex, start, -ABS(end - start));
+ hex_sync_data_to_ascii(hex);
+
+ gtk_signal_emit(GTK_OBJECT(hex), hex_signals[CHANGED],
+ start, ABS(end - start));
+ }
+
+ return FALSE;
+ TOUCH(widget);
+}
+
+
+/* This handles text insertions *BEFORE* the object's own
+ * handler. We use it to update the contents of the null map.
+ */
+static gboolean
+on_hex_text_inserted(GtkWidget *widget,
+ const gchar *text,
+ gint length,
+ gint *position,
+ gpointer user_data)
+{
+ GtkHex *hex = GTK_HEX(user_data);
+ guint pos;
+ gint i;
+
+ if (hex->mode == GTK_RAW_ASCII)
+ {
+ gchar *whitespace;
+ pos = *position;
+
+ /* Update null_map to reflect changes: */
+
+ if ( (whitespace = g_new0(gchar, length + 1)))
+ {
+ memset(whitespace, ' ', length);
+
+ for (i = 0; i < length + 1; i++)
+ {
+ if (hex_is_char_unprintable(text[i]))
+ {
+ switch (text[i])
+ {
+ case '\n':
+ whitespace[i] = ' ';
+ break;
+
+ case 0:
+ whitespace[i] = '0';
+ break;
+
+ default:
+ whitespace[i] = text[i];
+ }
+ }
+ }
+
+ gtk_editable_insert_text(GTK_EDITABLE(hex->priv->null_map),
+ whitespace, length, &pos);
+ g_free(whitespace);
+ }
+ }
+
+ return FALSE;
+ TOUCH(widget);
+ TOUCH(text);
+}
+
+
+/* This is the text insertion handler that runs *AFTER*
+ * the object's own handler. We use it to cut excess data
+ * at the end of the text buffers and to reflect the changes
+ * in the packet's payload.
+ */
+static gboolean
+on_hex_text_inserted_after(GtkWidget *widget,
+ const gchar *text,
+ gint length,
+ gint *position,
+ gpointer user_data)
+{
+ GtkHex *hex = GTK_HEX(user_data);
+
+ if (hex->mode == GTK_RAW_ASCII)
+ {
+
+ /* Make sure text gets no longer than packet payload,
+ and reflect changes in the null map: */
+
+ hex_text_ascii_colorify(hex, *position - length, ABS(length));
+ hex_sync_data_to_ascii(hex);
+
+ gtk_signal_emit(GTK_OBJECT(hex), hex_signals[CHANGED],
+ *position - length, length);
+ }
+
+
+ return FALSE;
+ TOUCH(widget);
+ TOUCH(text);
+ TOUCH(length);
+ TOUCH(position);
+}
+
+
+static gboolean
+hex_is_char_unprintable(guchar val)
+{
+ return (val < 0x20 || (val >= 0x7f && val < 0xa0));
+}
+
+
+/* This function selects a character in the hex editor (thus placing
+ * the cursor) and also takes care of hilighting the corresponding
+ * character in the ascii or hex field
+ */
+static void
+hex_text_set_cursor(GtkHex *hex, guint index)
+{
+ static guint old_index = 0, old_len = 0;
+
+ GtkEditable *ed;
+ gchar *text;
+ int byte_offset, i1, i2;
+
+ if (!hex || hex->mode != GTK_RAW_HEX)
+ return;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+
+ gtk_editable_select_region(ed, index, index + 1);
+
+ gtk_text_freeze(GTK_TEXT(ed));
+ gtk_signal_handler_block_by_data(GTK_OBJECT(hex->hex_text), hex);
+
+ if (old_len)
+ {
+ text = gtk_editable_get_chars(ed, old_index, old_index + old_len);
+ gtk_editable_delete_text(ed, old_index, old_index + old_len);
+ gtk_text_set_point(GTK_TEXT(hex->hex_text), old_index);
+ gtk_text_insert(GTK_TEXT(hex->hex_text), hex->hex_font, NULL, NULL, text, old_len);
+ g_free(text);
+ }
+
+ gtk_signal_handler_unblock_by_data(GTK_OBJECT(hex->hex_text), hex);
+ gtk_text_thaw(GTK_TEXT(ed));
+
+ byte_offset = hex_cursor_index_to_byte_index(hex);
+ hex_byte_index_to_cursor_indices(byte_offset, &i1, &i2);
+
+ gtk_text_freeze(GTK_TEXT(ed));
+ gtk_signal_handler_block_by_data(GTK_OBJECT(hex->hex_text), hex);
+
+ if (hex_cursor_over_hex(hex))
+ {
+ text = gtk_editable_get_chars(ed, i2, i2 + 1);
+ gtk_editable_delete_text(ed, i2, i2 + 1);
+ gtk_text_set_point(GTK_TEXT(hex->hex_text), i2);
+ gtk_text_insert(GTK_TEXT(hex->hex_text), hex->hex_font, NULL,
+ >K_WIDGET(hex->hex_text)->style->base[GTK_STATE_INSENSITIVE],
+ text, 1);
+ g_free(text);
+ old_index = i2;
+ old_len = 1;
+ }
+ else
+ {
+ text = gtk_editable_get_chars(ed, i1, i1 + 2);
+ gtk_editable_delete_text(ed, i1, i1 + 2);
+ gtk_text_set_point(GTK_TEXT(hex->hex_text), i1);
+ gtk_text_insert(GTK_TEXT(hex->hex_text), hex->hex_font, NULL,
+ >K_WIDGET(hex->hex_text)->style->base[GTK_STATE_INSENSITIVE],
+ text, 2);
+ g_free(text);
+ old_index = i1;
+ old_len = 2;
+ }
+
+ gtk_signal_handler_unblock_by_data(GTK_OBJECT(hex->hex_text), hex);
+ gtk_text_thaw(GTK_TEXT(ed));
+
+ gtk_editable_select_region(ed, index, index + 1);
+}
+
+
+static void
+hex_text_ascii_colorify(GtkHex *hex, guint start, int length)
+{
+ GtkText *hex_text;
+ char *text;
+ guint len, min_len, point;
+
+ if (!hex || hex->mode != GTK_RAW_ASCII)
+ return;
+
+ hex_text = GTK_TEXT(hex->hex_text);
+
+ gtk_signal_handler_block_by_data(GTK_OBJECT(hex->hex_text), hex);
+ gtk_text_freeze(hex_text);
+
+ len = gtk_text_get_length(hex_text);
+ min_len = MIN(hex->data_size - 1, len);
+ text = gtk_editable_get_chars(GTK_EDITABLE(hex_text), 0, -1);
+ point = gtk_editable_get_position(GTK_EDITABLE(hex_text));
+
+ if (length > 0)
+ {
+ if (len > hex->data_size)
+ {
+ gtk_editable_delete_text(GTK_EDITABLE(hex_text), hex->data_size, -1);
+ gtk_text_set_point(hex_text, hex->data_size);
+ gtk_text_insert(hex_text, hex->hex_font,
+ >K_WIDGET(hex_text)->style->text[GTK_STATE_INSENSITIVE],
+ >K_WIDGET(hex_text)->style->base[GTK_STATE_NORMAL],
+ &text[hex->data_size],
+ len - hex->data_size);
+ }
+ }
+ else
+ {
+ if (start >= hex->data_size)
+ {
+ gtk_editable_delete_text(GTK_EDITABLE(hex_text), hex->data_size, -1);
+ gtk_text_set_point(hex_text, hex->data_size);
+ gtk_text_insert(hex_text, hex->hex_font,
+ >K_WIDGET(hex_text)->style->text[GTK_STATE_INSENSITIVE],
+ >K_WIDGET(hex_text)->style->base[GTK_STATE_NORMAL],
+ &text[hex->data_size],
+ len - hex->data_size);
+ }
+ else
+ {
+ gtk_editable_delete_text(GTK_EDITABLE(hex_text), point, -1);
+ gtk_text_insert(hex_text, hex->hex_font, NULL, NULL, &text[point],
+ MIN(hex->data_size - point, len - point));
+
+ if (len > hex->data_size)
+ {
+ gtk_text_set_point(hex_text, hex->data_size);
+ gtk_text_insert(hex_text, hex->hex_font,
+ >K_WIDGET(hex_text)->style->text[GTK_STATE_INSENSITIVE],
+ >K_WIDGET(hex_text)->style->base[GTK_STATE_NORMAL],
+ &text[hex->data_size],
+ len - hex->data_size);
+ }
+ }
+ }
+
+ gtk_text_thaw(hex_text);
+ gtk_signal_handler_unblock_by_data(GTK_OBJECT(hex->hex_text), hex);
+ gtk_editable_set_position(GTK_EDITABLE(hex_text), point);
+
+ g_free(text);
+}
+
+
+/* This function handles the case of cursor-left being
+ * pressed while hex mode is active.
+ */
+static void
+hex_handle_hex_left(GtkHex *hex)
+{
+ int line_offset, line_num;
+ GtkEditable *ed;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+ line_offset = ed->selection_start_pos % HEX_LINE_WIDTH;
+ line_num = ed->selection_start_pos / HEX_LINE_WIDTH;
+
+ /* If we're at the beginning of either hex or ascii data,
+ don't do anything. */
+ if ((ed->selection_start_pos == HEX_LINE_START_ASCII) ||
+ (ed->selection_start_pos == HEX_LINE_START))
+ return;
+
+ /* Check for intervals in the hex display: */
+
+ if (line_offset >= HEX_LINE_START && line_offset <= HEX_LINE_LEFT_MIDDLE)
+ {
+ if (line_offset == HEX_LINE_START)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 27);
+ return;
+ }
+
+ if ((line_offset - HEX_LINE_START) % 3 == 1)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 1);
+ }
+ else
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 2);
+ }
+ return;
+ }
+
+ if (line_offset >= HEX_LINE_RIGHT_MIDDLE && line_offset <= HEX_LINE_END)
+ {
+ if (line_offset == HEX_LINE_RIGHT_MIDDLE)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 3);
+ return;
+ }
+
+ if ((line_offset - HEX_LINE_LEFT_MIDDLE) % 3 == 1)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 1);
+ }
+ else
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 2);
+ }
+ return;
+ }
+
+ /* Still here? Ok, check for intervals in the ascii display */
+
+ if (line_offset == HEX_LINE_START_RIGHT_ASCII)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 2);
+ return;
+ }
+
+ if (line_offset > HEX_LINE_START_ASCII && line_offset <= HEX_LINE_START_RIGHT_ASCII)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 1);
+ return;
+ }
+
+ if (line_offset >= HEX_LINE_START_RIGHT_ASCII && line_offset <= HEX_LINE_START_RIGHT_ASCII + 7)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - 1);
+ return;
+ }
+
+ if (line_offset == HEX_LINE_START_ASCII)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos - HEX_LINE_START_ASCII - 2);
+ return;
+ }
+}
+
+
+/* This function handles the case of cursor-right being
+ * pressed while hex mode is active.
+ */
+static void
+hex_handle_hex_right(GtkHex *hex)
+{
+ int line_offset, line_num;
+ int i;
+ guint byte_index;
+ GtkEditable *ed;
+ guchar s[HEX_LINE_WIDTH+1];
+
+ ed = GTK_EDITABLE(hex->hex_text);
+
+ line_offset = ed->selection_start_pos % HEX_LINE_WIDTH;
+ line_num = ed->selection_start_pos / HEX_LINE_WIDTH;
+ byte_index = hex_cursor_index_to_byte_index(hex);
+
+#if 0
+ /* If we're at the last byte and are using hex display,
+ it depends on whether we've selected the low or high nibble
+ whether we can move any further to the right. */
+ if (byte_index == hex->data_size - 1)
+ {
+ /* We're in hex area */
+ if (line_offset < HEX_LINE_RIGHT_MIDDLE)
+ {
+ if ((line_offset - HEX_LINE_START) % 3 == 0)
+ hex_text_set_cursor(hex, ed->selection_start_pos + 1);
+ }
+ /* We're in ASCII area */
+ else if ((line_offset - HEX_LINE_RIGHT_MIDDLE) % 3 == 0)
+ hex_text_set_cursor(hex, ed->selection_start_pos + 1);
+ return;
+ }
+#endif
+
+ /* First we handle the case of last byte in the last column */
+ if ((byte_index == hex->data_size - 1) &&
+ line_offset == HEX_LINE_END)
+ {
+ gtk_text_freeze(GTK_TEXT(hex->hex_text));
+
+ sprintf (s, "\n%.4x", hex->data_size);
+ for (i = HEX_LINE_START-1; i <= HEX_LINE_WIDTH; i++)
+ {
+ s[i] = ' ';
+ }
+
+ gtk_text_insert(GTK_TEXT(hex->hex_text), hex->hex_font, NULL, NULL,
+ s, sizeof(s)-1);
+ gtk_text_thaw(GTK_TEXT(hex->hex_text));
+ }
+
+
+ /* Check for intervals in the hex display: */
+
+ if (line_offset >= HEX_LINE_START && line_offset <= HEX_LINE_LEFT_MIDDLE)
+ {
+ if (line_offset == HEX_LINE_LEFT_MIDDLE)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 3);
+ return;
+ }
+
+ if ((line_offset - HEX_LINE_START) % 3 == 1)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 2);
+ }
+ else
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 1);
+ }
+
+ return;
+ }
+
+ if (line_offset >= HEX_LINE_RIGHT_MIDDLE && line_offset <= HEX_LINE_END)
+ {
+ if (line_offset == HEX_LINE_END)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 27);
+ return;
+ }
+
+ if ((line_offset - HEX_LINE_LEFT_MIDDLE) % 3 == 1)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 2);
+ }
+ else
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 1);
+ }
+
+ return;
+ }
+
+ /* Check for intervals in the ascii display: */
+
+ if (line_offset == HEX_LINE_START_RIGHT_ASCII - 2)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 2);
+ return;
+ }
+
+ if (line_offset >= HEX_LINE_START_ASCII && line_offset < HEX_LINE_START_RIGHT_ASCII)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 1);
+ return;
+ }
+
+ if (line_offset >= HEX_LINE_START_RIGHT_ASCII && line_offset < HEX_LINE_START_RIGHT_ASCII + 7)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + 1);
+ return;
+ }
+
+ if (line_offset == HEX_LINE_START_RIGHT_ASCII + 7)
+ {
+ hex_text_set_cursor(hex, ed->selection_start_pos + HEX_LINE_START_ASCII + 2);
+ return;
+ }
+}
+
+
+static void
+hex_update_current(GtkHex *hex, int byte_offset)
+{
+ GtkEditable *ed;
+ int old, old2, i1, i2;
+ guchar s[16];
+
+ if (!hex || hex->mode != GTK_RAW_HEX)
+ return;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+
+ hex_byte_index_to_cursor_indices(byte_offset, &i1, &i2);
+ gtk_text_freeze(GTK_TEXT(hex->hex_text));
+ old = old2 = ed->selection_start_pos;
+
+ s[0] = hex->data[byte_offset];
+ s[1] = 0;
+
+ if (hex_is_char_unprintable(s[0]))
+ {
+ if (s[0] == 0)
+ s[0] = NULL_CHAR;
+ else
+ s[0] = NONPRINT_CHAR;
+ }
+
+ gtk_editable_delete_text(ed, i2, i2 + 1);
+ gtk_editable_insert_text(ed, s, 1, &i2);
+
+ g_snprintf(s, 16, "%.2x", hex->data[byte_offset]);
+ gtk_editable_delete_text(ed, i1, i1 + 2);
+ gtk_editable_insert_text(ed, s, 2, &i1);
+
+ gtk_text_thaw(GTK_TEXT(hex->hex_text));
+ hex_text_set_cursor(hex, old);
+}
+
+
+static gboolean
+hex_text_cursor_key_press(GtkHex *hex, GdkEventKey *event, guint byte_offset)
+{
+ GtkEditable *ed;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+
+ if (hex->mode == GTK_RAW_HEX)
+ {
+ switch(event->keyval)
+ {
+ case GDK_Up:
+ if ((int) ed->selection_start_pos - HEX_LINE_WIDTH > 0)
+ hex_text_set_cursor(hex, ed->selection_start_pos - HEX_LINE_WIDTH);
+ return TRUE;
+ break;
+
+ case GDK_Down:
+ if (byte_offset + 16 < hex->data_size)
+ hex_text_set_cursor(hex, ed->selection_start_pos + HEX_LINE_WIDTH);
+ return TRUE;
+ break;
+
+ case GDK_Left:
+ hex_handle_hex_left(hex);
+ return TRUE;
+ break;
+
+ case GDK_Right:
+ hex_handle_hex_right(hex);
+ return TRUE;
+ break;
+
+ case GDK_Return:
+ if (event->string)
+ event->string[0] = '\n';
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+check_buf_limit (GtkHex *hex, int byte_offset)
+{
+ guchar *new_data;
+
+ /*
+ * First case: byte_offset is less than data_size.
+ * Nothing has to be done, since data in that space
+ * was already written
+ */
+ if (byte_offset < hex->data_size)
+ return TRUE;
+
+ /*
+ * Second case: data_size <= byte_offset < buf_size.
+ * Adjust data_size, but don't allocate space
+ */
+ if (byte_offset < hex->buf_size)
+ {
+ hex->data_size = byte_offset + 1;
+ return TRUE;
+ }
+ /*
+ * Third case: byte_offset >= buf_size.
+ * Space has to be reallocated, since there is no room for the new byte
+ */
+ new_data = g_realloc (hex->data, hex->buf_size+16);
+ if (new_data)
+ {
+ hex->data = new_data;
+ hex->data_size = byte_offset + 1;
+ hex->buf_size += 16;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+}
+
+/* LS: handle the case in which byte_offset goes past the end of the buffer */
+static gboolean
+hex_text_data_key_press(GtkHex *hex, GdkEventKey *event, int byte_offset)
+{
+ char val = 0;
+
+ if (!hex)
+ return FALSE;
+
+ if (hex->mode == GTK_RAW_HEX && event->string && strlen(event->string) == 1)
+ {
+ if (hex_cursor_over_hex(hex))
+ {
+ /* Accept only hex characters when editing hex data */
+ if ((event->string[0] >= 'a' && event->string[0] <= 'f') ||
+ (event->string[0] >= 'A' && event->string[0] <= 'F'))
+ {
+ val = tolower(event->string[0]) - 87;
+ }
+ else if (event->string[0] >= '0' && event->string[0] <= '9')
+ {
+ val = event->string[0] - 48;
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ if (!check_buf_limit (hex, byte_offset))
+ return FALSE;
+
+ if (hex_cursor_over_high_nibble(hex))
+ {
+ hex->data[byte_offset] &= 0x0F;
+ hex->data[byte_offset] |= (val << 4);
+ }
+ else
+ {
+ hex->data[byte_offset] &= 0xF0;
+ hex->data[byte_offset] |= val;
+ }
+
+ hex_update_current(hex, byte_offset);
+ hex_handle_hex_right(hex);
+ }
+ else if (hex_cursor_over_hex_ascii(hex))
+ {
+ if (!check_buf_limit (hex, byte_offset))
+ return FALSE;
+
+ hex->data[byte_offset] = event->string[0];
+
+ hex_update_current(hex, byte_offset);
+ hex_handle_hex_right(hex);
+ }
+
+ gtk_signal_emit(GTK_OBJECT(hex), hex_signals[CHANGED],
+ byte_offset, 1);
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+on_hex_text_key_press_event (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data)
+{
+ gboolean done;
+ int byte_offset;
+ GtkHex *hex;
+ GtkEditable *ed;
+
+ if (!user_data)
+ return FALSE;
+
+ hex = GTK_HEX(user_data);
+ ed = GTK_EDITABLE(widget);
+
+ if (hex->mode != GTK_RAW_HEX)
+ return FALSE;
+
+ if (!ed->has_selection)
+ return FALSE;
+
+ byte_offset = hex_cursor_index_to_byte_index(hex);
+
+ /* We'll first check for cursor navigation and delegate handling
+ * to the appropriate handler routines.
+ */
+ done = hex_text_cursor_key_press(hex, event, byte_offset);
+
+ if (!done)
+ hex_text_data_key_press(hex, event, byte_offset);
+
+ byte_offset = hex_cursor_index_to_byte_index(hex);
+ gtk_signal_emit(GTK_OBJECT(hex), hex_signals[MOVE_CURSOR], byte_offset);
+
+ return FALSE;
+}
+
+
+/* This is our callback to indicate cursor placement.
+ * This is called after the object's handler, which
+ * even in non-editable mode sets GtkText->current_pos */
+gboolean
+on_hex_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ int index;
+ GtkHex *hex;
+ GtkEditable *ed;
+
+ ed = GTK_EDITABLE(widget);
+ hex = GTK_HEX(user_data);
+
+ if (hex->mode == GTK_RAW_ASCII)
+ return FALSE;
+
+ index = hex_get_nowhite_index(hex, ed->current_pos);
+ hex_text_set_cursor(hex, index);
+
+ return FALSE;
+ TOUCH(event);
+}
+
+
+/* Assuming the cursor would be placed at INDEX, is that
+ * a feasible (i.e. hex or ascii, but not whitespace) index?
+ * If so, the same index is returned,
+ * otherwise the nearest one that actually contains
+ * non-whitespace.
+ */
+static int
+hex_get_nowhite_index(GtkHex *hex, int index_orig)
+{
+ GtkEditable *ed;
+ int line_offset;
+ int index;
+
+ if (!hex)
+ return FALSE;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+
+ if (hex->mode == GTK_RAW_ASCII)
+ return index_orig;
+
+ line_offset = index_orig % HEX_LINE_WIDTH;
+ index = (index_orig / HEX_LINE_WIDTH) * HEX_LINE_WIDTH + line_offset;
+
+ if (line_offset < HEX_LINE_START)
+ {
+ index += HEX_LINE_START - (line_offset % HEX_LINE_START);
+ return index;
+ }
+
+ if (line_offset >= HEX_LINE_START && line_offset <= HEX_LINE_END)
+ {
+ if (line_offset <= HEX_LINE_LEFT_MIDDLE)
+ {
+ if ((line_offset - HEX_LINE_START) % 3 == 2)
+ index--;
+
+ return index;
+ }
+
+ if (line_offset >= HEX_LINE_RIGHT_MIDDLE)
+ {
+ if ((line_offset - HEX_LINE_RIGHT_MIDDLE) % 3 == 2)
+ index--;
+
+ return index;
+ }
+
+ return index - ((line_offset - HEX_LINE_START) % (HEX_BLOCK_LEN-1));
+ }
+
+ if (line_offset > HEX_LINE_END && line_offset < HEX_LINE_START_ASCII)
+ {
+ index -= (line_offset % HEX_LINE_END);
+ return index;
+ }
+
+ return index;
+}
+
+
+/* Returns TRUE when the editor is in hex mode and the
+ * currently selected character is in the hex area.
+ */
+static gboolean
+hex_cursor_over_hex(GtkHex *hex)
+{
+ GtkEditable *ed;
+ int line_offset;
+
+ if (!hex || hex->mode == GTK_RAW_ASCII)
+ return FALSE;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+ line_offset = ed->selection_start_pos % HEX_LINE_WIDTH;
+
+ if (line_offset >= HEX_LINE_START && line_offset <= HEX_LINE_END)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/* Returns TRUE when the editor is in hex mode and the
+ * currently selected character is in the ascii area.
+ */
+static gboolean
+hex_cursor_over_hex_ascii(GtkHex *hex)
+{
+ GtkEditable *ed;
+ int line_offset;
+
+ if (!hex || hex->mode == GTK_RAW_ASCII)
+ return FALSE;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+ line_offset = ed->selection_start_pos % HEX_LINE_WIDTH;
+
+ if (line_offset >= HEX_LINE_START_ASCII)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/* Returns TRUE when the editor is in hex mode and the
+ * high nibble (i.e. left character) of a byte is selected,
+ * FALSE otherwise.
+ */
+static gboolean
+hex_cursor_over_high_nibble(GtkHex *hex)
+{
+ GtkEditable *ed;
+ int line_offset;
+
+ if (!hex || hex->mode == GTK_RAW_ASCII)
+ return FALSE;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+ line_offset = ed->selection_start_pos % HEX_LINE_WIDTH;
+
+ if (line_offset >= HEX_LINE_START && line_offset <= HEX_LINE_LEFT_MIDDLE)
+ {
+ if ((line_offset - HEX_LINE_START) % 3 == 0)
+ return TRUE;
+ }
+
+ if (line_offset >= HEX_LINE_RIGHT_MIDDLE && line_offset <= HEX_LINE_END)
+ {
+ if ((line_offset - HEX_LINE_RIGHT_MIDDLE) % 3 == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* Calculates and returns the currently selected byte in the
+ * data chunk being displayed from the selected character in
+ * either hex or ascii mode. Blood, sweat & tears.
+ */
+static int
+hex_cursor_index_to_byte_index(GtkHex *hex)
+{
+ GtkEditable *ed = GTK_EDITABLE(hex->hex_text);
+ int line_num;
+ int line_offset;
+
+ if (!hex || hex->mode == GTK_RAW_ASCII)
+ return -1;
+
+ ed = GTK_EDITABLE(hex->hex_text);
+
+ line_num = ed->selection_start_pos / HEX_LINE_WIDTH;
+ line_offset = ed->selection_start_pos % HEX_LINE_WIDTH;
+
+ if (line_offset >= HEX_LINE_START && line_offset <= HEX_LINE_END)
+ {
+ if (line_offset <= HEX_LINE_LEFT_MIDDLE)
+ return line_num * 16 + (line_offset - HEX_LINE_START) / 3;
+ else
+ return line_num * 16 + 8 + (line_offset - HEX_LINE_RIGHT_MIDDLE) / 3;
+ }
+
+ if (line_offset >= HEX_LINE_START_RIGHT_ASCII)
+ return line_num * 16 + 8 + (line_offset - HEX_LINE_START_RIGHT_ASCII);
+
+ if (line_offset >= HEX_LINE_START_ASCII)
+ return line_num * 16 + (line_offset - HEX_LINE_START_ASCII);
+
+ return -1;
+}
+
+
+static void
+hex_byte_index_to_cursor_indices(int byte_index, int *i1, int *i2)
+{
+ int line_num, line_offset;
+
+ if (!i1 || !i2 || byte_index < 0)
+ return;
+
+ line_num = byte_index / 16;
+ line_offset = byte_index % 16;
+
+ (*i1) =
+ line_num * HEX_LINE_WIDTH +
+ HEX_LINE_START + line_offset * 3 + (line_offset >= 8 ? 1 : 0);
+
+ (*i2) =
+ line_num * HEX_LINE_WIDTH +
+ HEX_LINE_START_ASCII + line_offset + (line_offset >= 8 ? 1 : 0);
+}
+
+
+/* The heart of the editor -- creates the hex editor hex-mode
+ * string from the input data and returns it. The string must
+ * be freed when it's not needed any more.
+ */
+static guchar *
+hex_get_hex_text(const guchar *data, int data_size)
+{
+ int x, y, num_lines, len;
+ guchar *hex_data;
+ const guchar *data_ptr;
+ guchar *hex_data_ptr;
+ guchar *ascii_ptr;
+ guchar hex_byte[3];
+ guchar offset[5];
+ guchar ascii_byte;
+
+ if (!data)
+ return NULL;
+
+ num_lines = (data_size / 16) + 1;
+ len = num_lines * HEX_LINE_WIDTH;
+ if (! (hex_data = g_new0(guchar, len + 1)))
+ return NULL;
+
+ memset(hex_data, ' ', len);
+
+ hex_data_ptr = hex_data;
+ ascii_ptr = hex_data_ptr + 50;
+ x = y = 0;
+
+ for (data_ptr = data; data_ptr < data + data_size; data_ptr++)
+ {
+ if (x == 0)
+ {
+ g_snprintf(offset, 5, "%.4x", data_ptr - data);
+ memcpy(hex_data_ptr, offset, 4);
+ hex_data_ptr += 6;
+ ascii_ptr = hex_data_ptr + 50;
+ }
+
+ g_snprintf(hex_byte, 3, "%.2x", (guchar) *data_ptr);
+
+ /* Workaround for a nonsense gcc warning -- char's range is
+ obviously not limited to 128 ... */
+
+ {
+ int val = (guchar) *data_ptr;
+
+ if (hex_is_char_unprintable(val))
+ {
+ if (val == 0)
+ ascii_byte = NULL_CHAR;
+ else
+ ascii_byte = NONPRINT_CHAR;
+ }
+ else
+ {
+ ascii_byte = val;
+ }
+ }
+
+ *hex_data_ptr++ = hex_byte[0];
+ *hex_data_ptr++ = hex_byte[1];
+ *hex_data_ptr++ = ' ';
+ *ascii_ptr++ = ascii_byte;
+
+ if (x == 7)
+ {
+ *hex_data_ptr++ = ' ';
+ *ascii_ptr++ = ' ';
+ }
+
+ x++;
+
+ if (x == 16)
+ {
+ x = 0;
+ *ascii_ptr++ = '\n';
+ hex_data_ptr = ascii_ptr;
+ }
+ }
+
+ return hex_data;
+}
+
+
+/* This one creates and returns the ascii version of
+ * the data being displayed. Zeroes and other non-displayable
+ * characters in the input are substituted with dots.
+ *
+ * The string is returned through the result pointer.
+ * An additional string will be returned through null_map,
+ * that contains a null character "0" wherever the original text
+'* contained a null byte, and whitespace everywhere else.
+ * The strings must be freed when it's no longer needed.
+ */
+void
+hex_get_ascii_text(const guchar *data, int data_size,
+ guchar **result, guchar **null_map)
+{
+ guchar *result_ptr;
+ const guchar *data_ptr;
+ guchar *null_map_ptr;
+
+ if (!data || !result || !null_map)
+ return;
+
+ *result = result_ptr = g_new0(guchar, data_size + 1);
+ *null_map = null_map_ptr = g_new0(guchar, data_size + 1);
+
+ if (!result || !null_map)
+ {
+ g_free(result);
+ g_free(null_map);
+ return;
+ }
+
+ for (data_ptr = data; data_ptr < data + data_size; result_ptr++, data_ptr++, null_map_ptr++)
+ {
+ int val = *data_ptr;
+
+ if (hex_is_char_unprintable(val))
+ {
+ switch (val)
+ {
+ case '\n':
+ *result_ptr = *data_ptr;
+ *null_map_ptr = ' ';
+ break;
+
+ case 0:
+ *result_ptr = NULL_CHAR;
+ *null_map_ptr = '0';
+ break;
+
+ default:
+ *result_ptr = NONPRINT_CHAR;
+ *null_map_ptr = val;
+ }
+ }
+ else
+ {
+ *result_ptr = *data_ptr;
+ *null_map_ptr = ' ';
+ }
+ }
+}
+
+
+static void
+hex_sync_data_to_ascii(GtkHex *hex)
+{
+ guint len, i;
+ gchar *text;
+
+ if (!hex || hex->mode != GTK_RAW_ASCII)
+ return;
+
+ text = gtk_editable_get_chars(GTK_EDITABLE(hex->hex_text), 0, -1);
+ len = strlen(text);
+
+ memset(hex->data, 0, hex->data_size);
+ memcpy(hex->data, text, MIN(len, hex->data_size));
+ g_free(text);
+
+ text = gtk_editable_get_chars(GTK_EDITABLE(hex->priv->null_map), 0, -1);
+
+ for (i = 0; i < MIN(len, hex->data_size); i++)
+ {
+ if (text[i] != ' ')
+ {
+ if (text[i] == '0')
+ {
+ hex->data[i] = 0;
+ }
+ else
+ {
+ hex->data[i] = text[i];
+ }
+ }
+ }
+
+ g_free(text);
+}
+
+
+static void
+gtk_hex_destroy(GtkObject *object)
+{
+ GtkHex *hex;
+
+ g_return_if_fail(object != NULL);
+ g_return_if_fail(GTK_IS_HEX(object));
+
+ hex = GTK_HEX(object);
+
+ gtk_widget_unref(GTK_WIDGET(hex->priv->null_map));
+ g_free(hex->priv);
+
+ if (GTK_OBJECT_CLASS(parent_class)->destroy)
+ (* GTK_OBJECT_CLASS(parent_class)->destroy) (object);
+}
+
+
+static void
+gtk_hex_class_init (GtkHexClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkVBoxClass *vbox_class;
+
+ object_class = (GtkObjectClass *) class;
+ vbox_class = (GtkVBoxClass *) class;
+
+ parent_class = gtk_type_class(gtk_vbox_get_type());
+
+ hex_signals[CHANGED] =
+ gtk_signal_new ("changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkHexClass, changed),
+ gtk_marshal_NONE__INT_INT,
+ GTK_TYPE_NONE, 2,
+ GTK_TYPE_INT,
+ GTK_TYPE_INT);
+
+ hex_signals[MOVE_CURSOR] =
+ gtk_signal_new ("move_cursor",
+ GTK_RUN_LAST | GTK_RUN_ACTION,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkHexClass, move_cursor),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_INT);
+
+ gtk_object_class_add_signals(object_class, hex_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_hex_destroy;
+
+ class->changed = NULL;
+ class->move_cursor = NULL;
+}
+
+
+static void
+gtk_hex_init (GtkHex *hex)
+{
+ GtkHexPrivate *priv;
+ GtkWidget *mode_hbox, *hex_vbox;
+ GtkWidget *scrolledwin;
+ GSList *mode_hbox_group = NULL;
+
+ if (!hex)
+ return;
+
+ hex_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_ref (hex_vbox);
+ gtk_object_set_data_full (GTK_OBJECT (hex), "hex_vbox", hex_vbox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hex_vbox);
+ gtk_container_add (GTK_CONTAINER (hex), hex_vbox);
+
+ mode_hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (mode_hbox);
+ gtk_object_set_data_full (GTK_OBJECT (hex_vbox), "mode_hbox", mode_hbox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (mode_hbox);
+ gtk_box_pack_start (GTK_BOX (hex_vbox), mode_hbox, FALSE, FALSE, 0);
+
+ hex->mode_button_hex = gtk_radio_button_new_with_label (mode_hbox_group, ("Hex/ASCII"));
+ mode_hbox_group = gtk_radio_button_group (GTK_RADIO_BUTTON (hex->mode_button_hex));
+ gtk_widget_ref (hex->mode_button_hex);
+ gtk_object_set_data_full (GTK_OBJECT (hex_vbox), "mode_button_hex", hex->mode_button_hex,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hex->mode_button_hex);
+ gtk_box_pack_start (GTK_BOX (mode_hbox), hex->mode_button_hex, FALSE, FALSE, 0);
+
+ hex->mode_button_ascii = gtk_radio_button_new_with_label (mode_hbox_group, ("ASCII only"));
+ mode_hbox_group = gtk_radio_button_group (GTK_RADIO_BUTTON (hex->mode_button_ascii));
+ gtk_widget_ref (hex->mode_button_ascii);
+ gtk_object_set_data_full (GTK_OBJECT (hex_vbox), "mode_button_ascii", hex->mode_button_ascii,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hex->mode_button_ascii);
+ gtk_box_pack_start (GTK_BOX (mode_hbox), hex->mode_button_ascii, FALSE, FALSE, 0);
+
+ scrolledwin = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_ref (scrolledwin);
+ gtk_object_set_data_full (GTK_OBJECT (hex_vbox), "scrolledwin", scrolledwin,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (scrolledwin);
+ gtk_box_pack_start (GTK_BOX (hex_vbox), scrolledwin, TRUE, TRUE, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+ hex->hex_text = gtk_text_new (NULL, NULL);
+ gtk_widget_ref (hex->hex_text);
+ gtk_object_set_data_full (GTK_OBJECT (hex_vbox), "hex_text", hex->hex_text,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hex->hex_text);
+ gtk_container_add (GTK_CONTAINER (scrolledwin), hex->hex_text);
+
+ gtk_text_set_editable(GTK_TEXT(hex->hex_text), FALSE);
+ gtk_text_set_word_wrap(GTK_TEXT(hex->hex_text), FALSE);
+ gtk_text_set_line_wrap(GTK_TEXT(hex->hex_text), FALSE);
+
+ hex->mode = GTK_RAW_HEX;
+
+ priv = g_new0(GtkHexPrivate, 1);
+ priv->null_map = GTK_TEXT(gtk_text_new(NULL, NULL));
+ gtk_widget_ref(GTK_WIDGET(priv->null_map));
+ gtk_object_set_data_full (GTK_OBJECT (hex_vbox), "null_map", priv->null_map,
+ (GtkDestroyNotify) gtk_widget_unref);
+ hex->priv = priv;
+
+ gtk_signal_connect (GTK_OBJECT (hex->mode_button_ascii), "toggled",
+ GTK_SIGNAL_FUNC (on_mode_ascii_toggled),
+ hex);
+
+ gtk_signal_connect (GTK_OBJECT (hex->mode_button_hex), "toggled",
+ GTK_SIGNAL_FUNC (on_mode_hex_toggled),
+ hex);
+
+ gtk_signal_connect (GTK_OBJECT (hex->hex_text), "key_press_event",
+ GTK_SIGNAL_FUNC (on_hex_text_key_press_event),
+ hex);
+
+ gtk_signal_connect (GTK_OBJECT (hex->hex_text), "motion_notify_event",
+ GTK_SIGNAL_FUNC (on_hex_text_motion_notify_event),
+ hex);
+
+ gtk_signal_connect_after (GTK_OBJECT (hex->hex_text), "button_press_event",
+ GTK_SIGNAL_FUNC (on_hex_button_press_event),
+ hex);
+
+ gtk_signal_connect(GTK_OBJECT (hex->hex_text), "insert_text",
+ GTK_SIGNAL_FUNC (on_hex_text_inserted),
+ hex);
+
+ gtk_signal_connect_after (GTK_OBJECT (hex->hex_text), "insert_text",
+ GTK_SIGNAL_FUNC (on_hex_text_inserted_after),
+ hex);
+
+ gtk_signal_connect_after (GTK_OBJECT (hex->hex_text), "delete_text",
+ GTK_SIGNAL_FUNC (on_hex_text_deleted),
+ hex);
+}
+
+
+guint
+gtk_hex_get_type ()
+{
+ static guint gtk_hex_type = 0;
+
+ if (!gtk_hex_type)
+ {
+ GtkTypeInfo gtk_hex_info =
+ {
+ "GtkHex",
+ sizeof (GtkHex),
+ sizeof (GtkHexClass),
+ (GtkClassInitFunc) gtk_hex_class_init,
+ (GtkObjectInitFunc) gtk_hex_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ gtk_hex_type = gtk_type_unique (gtk_vbox_get_type (), >k_hex_info);
+ }
+
+ return gtk_hex_type;
+}
+
+
+GtkWidget *
+gtk_hex_new(void)
+{
+ return GTK_WIDGET(gtk_type_new(gtk_hex_get_type()));
+}
+
+
+void
+gtk_hex_set_content(GtkHex *hex, char *arg_data, int data_size)
+{
+ guchar *hex_text = NULL;
+ guchar *null_map_text = NULL;
+ guchar *data = NULL;
+
+ if (!hex || !arg_data || !data_size)
+ return;
+
+ /* Make a private copy of the data */
+ data = g_malloc (data_size);
+ if (!data)
+ return;
+ memcpy (data, arg_data, data_size);
+
+ switch (hex->mode)
+ {
+ case GTK_RAW_HEX:
+ hex_text = hex_get_hex_text(data, data_size);
+ if (!hex_text)
+ goto cleanup;
+ break;
+
+ case GTK_RAW_ASCII:
+ hex_get_ascii_text(data, data_size, &hex_text, &null_map_text);
+ if (!hex_text || !null_map_text)
+ goto cleanup;
+
+ gtk_editable_delete_text(GTK_EDITABLE(hex->priv->null_map), 0, -1);
+ gtk_text_insert(GTK_TEXT(hex->priv->null_map), hex->hex_font, NULL, NULL,
+ null_map_text, strlen(null_map_text));
+ break;
+
+ default:
+ goto cleanup;
+ }
+
+ gtk_text_freeze(GTK_TEXT(hex->hex_text));
+ gtk_signal_handler_block_by_data(GTK_OBJECT(hex->hex_text), hex);
+
+ gtk_editable_delete_text(GTK_EDITABLE(hex->hex_text), 0, -1);
+ gtk_text_insert(GTK_TEXT(hex->hex_text), hex->hex_font, NULL, NULL,
+ hex_text, strlen(hex_text));
+
+ gtk_signal_handler_unblock_by_data(GTK_OBJECT(hex->hex_text), hex);
+ gtk_text_thaw(GTK_TEXT(hex->hex_text));
+
+ /* Old data isn't freed -- we don't possess it! */
+ /* No longer true */
+ g_free(hex->data);
+ hex->data = data;
+ hex->data_size = hex->buf_size = data_size;
+
+ cleanup:
+ g_free(hex_text);
+ g_free(null_map_text);
+}
+
+
+void
+gtk_hex_set_mode(GtkHex *hex, GtkRawMode mode)
+{
+ if (!hex)
+ return;
+
+ hex->mode = mode;
+
+ switch(mode)
+ {
+ case GTK_RAW_ASCII:
+ gtk_text_set_line_wrap(GTK_TEXT(hex->hex_text), TRUE);
+ gtk_text_set_editable(GTK_TEXT(hex->hex_text), TRUE);
+ break;
+
+ case GTK_RAW_HEX:
+ gtk_text_set_line_wrap(GTK_TEXT(hex->hex_text), FALSE);
+ gtk_text_set_editable(GTK_TEXT(hex->hex_text), FALSE);
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ gtk_hex_set_content(hex, hex->data, hex->data_size);
+}
diff -urN --exclude='*~' ethereal-0.9.14-orig/gtk/gtk_hex.h ethereal-0.9.14/gtk/gtk_hex.h
--- ethereal-0.9.14-orig/gtk/gtk_hex.h 1970-01-01 01:00:00.000000000 +0100
+++ ethereal-0.9.14/gtk/gtk_hex.h 2003-08-22 00:23:02.000000000 +0200
@@ -0,0 +1,96 @@
+/*
+
+Copyright (C) 2000, 2001, 2002 Christian Kreibich <christian@xxxxxxxxx>.
+
+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.
+
+*/
+#ifndef __gtk_hex_h
+#define __gtk_hex_h
+
+#include <gdk/gdk.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkradiobutton.h>
+#include <gtk/gtktext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define TOUCH(x) { x = 0; }
+
+
+#define GTK_TYPE_HEX (gtk_hex_get_type())
+#define GTK_HEX(obj) GTK_CHECK_CAST (obj, gtk_hex_get_type (), GtkHex)
+#define GTK_HEX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_hex_get_type (), GtkHexClass)
+#define GTK_IS_HEX(obj) GTK_CHECK_TYPE (obj, gtk_hex_get_type ())
+
+
+typedef enum {
+ GTK_RAW_ASCII,
+ GTK_RAW_HEX
+} GtkRawMode;
+
+
+typedef struct _GtkHex GtkHex;
+typedef struct _GtkHexClass GtkHexClass;
+typedef struct _GtkHexPrivate GtkHexPrivate;
+
+struct _GtkHex
+{
+ GtkVBox vbox;
+
+ GtkWidget *mode_button_hex;
+ GtkWidget *mode_button_ascii;
+ GtkWidget *hex_text;
+
+ GtkRawMode mode;
+
+ guchar *data;
+ guint data_size;
+ guint buf_size;
+
+ GtkHexPrivate *priv;
+ GdkFont *hex_font;
+};
+
+struct _GtkHexClass
+{
+ GtkVBoxClass parent_class;
+
+ void (* changed) (GtkHex *hex,
+ gint index,
+ gint value);
+ void (* move_cursor) (GtkEditable *editable,
+ gint index);
+};
+
+
+guint gtk_hex_get_type(void);
+GtkWidget *gtk_hex_new(void);
+void gtk_hex_set_content(GtkHex *hex, char *data, int data_size);
+void gtk_hex_set_mode(GtkHex *hex, GtkRawMode mode);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif
diff -urN --exclude='*~' ethereal-0.9.14-orig/gtk/Makefile.in ethereal-0.9.14/gtk/Makefile.in
--- ethereal-0.9.14-orig/gtk/Makefile.in 2003-07-24 00:37:28.000000000 +0200
+++ ethereal-0.9.14/gtk/Makefile.in 2003-07-26 00:42:38.000000000 +0200
@@ -250,6 +250,10 @@
@USE_GTK2_TRUE@ proto_draw.h \
@USE_GTK2_TRUE@ proto_hier_stats_dlg.h \
@USE_GTK2_TRUE@ proto_hier_stats_dlg.c \
+@USE_GTK2_TRUE@ gtk_hex.c \
+@USE_GTK2_TRUE@ gtk_hex.h \
+@USE_GTK2_TRUE@ gen_packet.c \
+@USE_GTK2_TRUE@ gen_packet.h \
@USE_GTK2_TRUE@ simple_dialog.c \
@USE_GTK2_TRUE@ service_response_time_table.c \
@USE_GTK2_TRUE@ service_response_time_table.h \
@@ -329,6 +333,10 @@
@USE_GTK2_FALSE@ proto_draw.h \
@USE_GTK2_FALSE@ proto_hier_stats_dlg.h \
@USE_GTK2_FALSE@ proto_hier_stats_dlg.c \
+@USE_GTK2_FALSE@ gtk_hex.c \
+@USE_GTK2_FALSE@ gtk_hex.h \
+@USE_GTK2_FALSE@ gen_packet.c \
+@USE_GTK2_FALSE@ gen_packet.h \
@USE_GTK2_FALSE@ service_response_time_table.c \
@USE_GTK2_FALSE@ service_response_time_table.h \
@USE_GTK2_FALSE@ simple_dialog.c \
@@ -379,6 +387,8 @@
@USE_GTK2_TRUE@ print_prefs.$(OBJEXT) progress_dlg.$(OBJEXT) \
@USE_GTK2_TRUE@ proto_dlg.$(OBJEXT) proto_draw.$(OBJEXT) \
@USE_GTK2_TRUE@ proto_hier_stats_dlg.$(OBJEXT) \
+@USE_GTK2_TRUE@ gtk_hex.$(OBJEXT) \
+@USE_GTK2_TRUE@ gen_packet.$(OBJEXT) \
@USE_GTK2_TRUE@ simple_dialog.$(OBJEXT) \
@USE_GTK2_TRUE@ service_response_time_table.$(OBJEXT) \
@USE_GTK2_TRUE@ stream_prefs.$(OBJEXT) summary_dlg.$(OBJEXT) \
@@ -404,6 +414,8 @@
@USE_GTK2_FALSE@ progress_dlg.$(OBJEXT) proto_dlg.$(OBJEXT) \
@USE_GTK2_FALSE@ proto_draw.$(OBJEXT) \
@USE_GTK2_FALSE@ proto_hier_stats_dlg.$(OBJEXT) \
+@USE_GTK2_FALSE@ gtk_hex.$(OBJEXT) \
+@USE_GTK2_FALSE@ gen_packet.$(OBJEXT) \
@USE_GTK2_FALSE@ service_response_time_table.$(OBJEXT) \
@USE_GTK2_FALSE@ simple_dialog.$(OBJEXT) stream_prefs.$(OBJEXT) \
@USE_GTK2_FALSE@ summary_dlg.$(OBJEXT) tcp_graph.$(OBJEXT) \
@@ -445,6 +457,8 @@
@AMDEP_TRUE@ ./$(DEPDIR)/progress_dlg.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/proto_dlg.Po ./$(DEPDIR)/proto_draw.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/proto_hier_stats_dlg.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/gtk_hex.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/gen_packet.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/rpc_progs.Po ./$(DEPDIR)/rpc_stat.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/service_response_time_table.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/simple_dialog.Po \
@@ -526,6 +540,8 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_dlg.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_draw.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_hier_stats_dlg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk_hex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_packet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_progs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_stat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/service_response_time_table.Po@am__quote@
diff -urN --exclude='*~' ethereal-0.9.14-orig/gtk/menu.c ethereal-0.9.14/gtk/menu.c
--- ethereal-0.9.14-orig/gtk/menu.c 2003-05-04 04:24:55.000000000 +0200
+++ ethereal-0.9.14/gtk/menu.c 2003-07-26 17:29:09.000000000 +0200
@@ -53,6 +53,7 @@
#include "help_dlg.h"
#include "proto_dlg.h"
#include "proto_hier_stats_dlg.h"
+#include "gen_packet.h"
#include "keys.h"
#include <epan/plugins.h>
#include "tcp_graph.h"
@@ -231,6 +232,8 @@
ITEM_FACTORY_ENTRY("/Tools/Protocol Hierarchy Statistics", NULL,
proto_hier_stats_cb, 0, NULL, NULL),
ITEM_FACTORY_ENTRY("/Tools/Statistics", NULL, NULL, 0, "<Branch>", NULL),
+ ITEM_FACTORY_ENTRY("/Tools/Packet Generator", NULL,
+ packet_generator, 0, NULL, NULL),
ITEM_FACTORY_ENTRY("/_Help", NULL, NULL, 0, "<LastBranch>", NULL),
ITEM_FACTORY_STOCK_ENTRY("/Help/_Help", NULL, help_cb, 0, GTK_STOCK_HELP),
ITEM_FACTORY_ENTRY("/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL),
- Prev by Date: [Ethereal-dev] Update to packet-m3ua.c
- Next by Date: Re: [Ethereal-dev] [PATCH] Wish list item 17 (packet generator)
- Previous by thread: Re: [Ethereal-dev] Update to packet-m3ua.c
- Next by thread: Re: [Ethereal-dev] [PATCH] Wish list item 17 (packet generator)
- Index(es):





