Ethereal-dev: [Ethereal-dev] [patch] Packet Fence (1.1)

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Paul Schulz <pschulz@xxxxxxxxxxxxxxxxx>
Date: Sat, 19 May 2001 18:02:26 +0930
Greetings,

The following adds packet fence 1.1 functionality to the current CVS
version of ethereal (2001-05-19)

----------------------------------------------------------------------
diff -urN ethereal-0.8.18/globals.h ethereal-0.8.18-pf-1.1/globals.h
--- ethereal-0.8.18/globals.h	Sat May 19 11:02:39 2001
+++ ethereal-0.8.18-pf-1.1/globals.h	Sat May 19 14:19:05 2001
@@ -36,6 +36,7 @@
 extern guint        main_ctx, file_ctx;
 extern gchar       *ethereal_path;
 extern gchar       *last_open_dir;
+extern gboolean     packet_fence_active; /* do we update the packet fence */
 extern field_info  *finfo_selected;
 
 extern ts_type timestamp_type;
diff -urN ethereal-0.8.18/gtk/Makefile.am ethereal-0.8.18-pf-1.1/gtk/Makefile.am
--- ethereal-0.8.18/gtk/Makefile.am	Sat Mar 24 12:53:08 2001
+++ ethereal-0.8.18-pf-1.1/gtk/Makefile.am	Sat May 19 14:20:52 2001
@@ -90,7 +90,9 @@
 	summary_dlg.c   \
 	summary_dlg.h   \
 	ui_util.c       \
-	ui_util.h
+	ui_util.h	\
+	packet_fence.c	\
+	packet_fence.h	
 
 EXTRA_DIST = \
 	Makefile.nmake
diff -urN ethereal-0.8.18/gtk/Makefile.nmake ethereal-0.8.18-pf-1.1/gtk/Makefile.nmake
--- ethereal-0.8.18/gtk/Makefile.nmake	Thu Apr  5 15:28:05 2001
+++ ethereal-0.8.18-pf-1.1/gtk/Makefile.nmake	Sat May 19 14:16:06 2001
@@ -46,7 +46,8 @@
 	simple_dialog.obj \
 	stream_prefs.obj \
 	summary_dlg.obj \
-	ui_util.obj
+	ui_util.obj \
+	packet_fence.obj
 
 
 libui.lib	: ..\config.h $(OBJECTS)
diff -urN ethereal-0.8.18/gtk/display_opts.c ethereal-0.8.18-pf-1.1/gtk/display_opts.c
--- ethereal-0.8.18/gtk/display_opts.c	Sat May 19 11:03:31 2001
+++ ethereal-0.8.18-pf-1.1/gtk/display_opts.c	Sat May 19 14:24:08 2001
@@ -72,6 +72,7 @@
 #define E_DISPLAY_TIME_DELTA_KEY "display_time_delta"
 #define E_DISPLAY_AUTO_SCROLL_KEY "display_auto_scroll"
 #define E_DISPLAY_NAME_RESOLUTION_KEY "display_name_resolution"
+#define E_DISPLAY_PACKET_FENCE "display_packet_fence"
 
 static void display_opt_ok_cb(GtkWidget *, gpointer);
 static void display_opt_apply_cb(GtkWidget *, gpointer);
@@ -185,6 +186,13 @@
   gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
   gtk_widget_show(button);
     
+  button = dlg_check_button_new_with_label_with_mnemonic(
+  		"Packet _fence graph", accel_group);
+  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), packet_fence_active);
+  gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_PACKET_FENCE,
+		      button);
+  gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
+  gtk_widget_show(button);
   /* Button row: OK, Apply, and Cancel buttons */
   bbox = gtk_hbutton_box_new();
   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
@@ -270,6 +278,10 @@
   button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
 					     E_DISPLAY_NAME_RESOLUTION_KEY);
   prefs.name_resolve = (GTK_TOGGLE_BUTTON (button)->active);
+
+  button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
+					     E_DISPLAY_PACKET_FENCE);
+  packet_fence_active = (GTK_TOGGLE_BUTTON (button)->active);
 
 }
 
diff -urN ethereal-0.8.18/gtk/gtkclist.c ethereal-0.8.18-pf-1.1/gtk/gtkclist.c
--- ethereal-0.8.18/gtk/gtkclist.c	Sat May 19 11:03:31 2001
+++ ethereal-0.8.18-pf-1.1/gtk/gtkclist.c	Sat May 19 14:16:06 2001
@@ -3143,6 +3143,23 @@
   return GTK_VISIBILITY_FULL;
 }
 
+/* needed by packet_fence.c to be able determine colors for packet display */
+GtkCListRow *
+gtk_clist_get_clistrow (GtkCList *clist,
+			  gint      row)
+{
+  GtkCListRow *clist_row;
+
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return NULL;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+  return clist_row;
+}  
+
 void
 gtk_clist_set_foreground (GtkCList *clist,
 			  gint      row,
diff -urN ethereal-0.8.18/gtk/gtkclist.h ethereal-0.8.18-pf-1.1/gtk/gtkclist.h
--- ethereal-0.8.18/gtk/gtkclist.h	Fri May 26 17:17:47 2000
+++ ethereal-0.8.18-pf-1.1/gtk/gtkclist.h	Sat May 19 14:16:06 2001
@@ -626,6 +626,10 @@
 			    GdkPixmap **pixmap,
 			    GdkBitmap **mask);
 
+/* return row info*/
+
+GtkCListRow * gtk_clist_get_clistrow (GtkCList *clist,
+			  gint      row);
 /* sets the foreground color of a row, the color must already
  * be allocated
  */
diff -urN ethereal-0.8.18/gtk/main.c ethereal-0.8.18-pf-1.1/gtk/main.c
--- ethereal-0.8.18/gtk/main.c	Sat May 19 11:03:32 2001
+++ ethereal-0.8.18-pf-1.1/gtk/main.c	Sat May 19 14:16:06 2001
@@ -11,6 +11,8 @@
  * Jeff Foster,    2001/03/12,  added support tabbed hex display windowss
  * 
  * 
+ * Martin Visser, 15-Nov-2000, added support to allow packet fence  
+ * 
  * 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
@@ -133,6 +135,7 @@
 #include "packet_win.h"
 #include "gtkglobals.h"
 #include "plugins.h"
+#include "packet_fence.h"
 #include "colors.h"
 #include "strutil.h"
 #include "register.h"
@@ -325,7 +328,6 @@
     return strcmp(text1, text2);
   }
 }
-
 /* What to do when a column is clicked */
 static void 
 packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
@@ -430,6 +432,7 @@
     gtk_notebook_remove_page( GTK_NOTEBOOK(byte_nb_ptr), 0);
 
   select_packet(&cfile, row);
+  packet_fence_row_select(row);
 }
 
 
@@ -1578,6 +1581,7 @@
 {
   GtkWidget           *main_vbox, *menubar, *u_pane, *l_pane,
                       *stat_hbox,
+		      *packet_pane,
                       *filter_bt, *filter_cm, *filter_te,
                       *filter_reset;
   GList               *filter_list = NULL;
@@ -1623,6 +1627,14 @@
   gtk_paned_add2(GTK_PANED(u_pane), l_pane);
   gtk_widget_show(u_pane);
 
+  packet_pane = gtk_hpaned_new(); /* create a horizontal pane to hold packet list and packet fence */
+  gtk_paned_gutter_size(GTK_PANED(packet_pane), (GTK_PANED(packet_pane))->handle_size);
+/*  gtk_container_border_width(GTK_CONTAINER(packet_pane), 0);*/
+  gtk_paned_add1(GTK_PANED(u_pane), packet_pane);
+  gtk_widget_show(packet_pane);
+  pf = packet_fence_new(); /* create a packet fence */
+  gtk_widget_show(pf->box);/* show it */
+  
   /* Packet list */
   pkt_scrollw = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(pkt_scrollw),
@@ -1630,7 +1642,8 @@
   set_scrollbar_placement_scrollw(pkt_scrollw, prefs->gui_scrollbar_on_right);
   remember_scrolled_window(pkt_scrollw);
   gtk_widget_show(pkt_scrollw);
-  gtk_paned_add1(GTK_PANED(u_pane), pkt_scrollw);
+  gtk_paned_add1(GTK_PANED(packet_pane), pf->box); /* add the packet fence */
+  gtk_paned_add2(GTK_PANED(packet_pane), pkt_scrollw); /* add the packet list */
 
   packet_list = gtk_clist_new_with_titles(cfile.cinfo.num_cols, cfile.cinfo.col_title);
   gtk_container_add(GTK_CONTAINER(pkt_scrollw), packet_list);
@@ -1644,6 +1657,10 @@
     GTK_SIGNAL_FUNC(packet_list_select_cb), NULL);
   gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
     GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
+  gtk_signal_connect(GTK_OBJECT(GTK_CLIST(packet_list)->vadjustment), "value_changed",
+    GTK_SIGNAL_FUNC(packet_list_value_changed), (gpointer) pf); /* packet fence wants to know somethings changed */
+  gtk_signal_connect(GTK_OBJECT(GTK_CLIST(packet_list)->vadjustment), "changed",
+    GTK_SIGNAL_FUNC(packet_list_changed), (gpointer) pf);
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
     if (get_column_resize_type(cfile.cinfo.col_fmt[i]) != RESIZE_MANUAL)
       gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
diff -urN ethereal-0.8.18/gtk/packet_fence.c ethereal-0.8.18-pf-1.1/gtk/packet_fence.c
--- ethereal-0.8.18/gtk/packet_fence.c	Thu Jan  1 09:30:00 1970
+++ ethereal-0.8.18-pf-1.1/gtk/packet_fence.c	Sat May 19 14:31:03 2001
@@ -0,0 +1,597 @@
+/* packet_fence.c
+ * Routines for displaying Packet Fence
+ *
+ * $Id: packet_fence.c,v 1.1 $
+ *
+ * Copyright (c) 2000 by Martin Visser <martin.visser@xxxxxxxxxx>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs
+ * Copyright 1999 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_IO_H
+#include <io.h> /* open/close on win32 */
+#endif
+
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include <signal.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#if defined(HAVE_UCD_SNMP_SNMP_H)
+#ifdef HAVE_UCD_SNMP_VERSION_H
+#include <ucd-snmp/version.h>
+#endif /* HAVE_UCD_SNMP_VERSION_H */
+#elif defined(HAVE_SNMP_SNMP_H)
+#ifdef HAVE_SNMP_VERSION_H
+#include <snmp/version.h>
+#endif /* HAVE_SNMP_VERSION_H */
+#endif /* SNMP */
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#ifdef NEED_GETOPT_H
+#include "getopt.h"
+#endif
+
+#include "main.h"
+#include "timestamp.h"
+#include "packet.h"
+#include "capture.h"
+#include "summary.h"
+#include "file.h"
+#include "menu.h"
+#include "../menu.h"
+#include "filter_prefs.h"
+#include "prefs_dlg.h"
+#include "column.h"
+#include "print.h"
+#include "resolv.h"
+#include "util.h"
+#include "simple_dialog.h"
+#include "proto_draw.h"
+#include "epan/dfilter/dfilter.h"
+#include "keys.h"
+#include "packet_win.h"
+#include "gtkglobals.h"
+#include "plugins.h"
+#include "packet_fence.h"
+
+
+enum zoomed_func {
+	ZOOMEDOUT,
+	ZOOMEDIN
+};
+enum pf_returns {
+	PF_COOL,
+	PF_REDRAW,
+	PF_END,
+	PF_BOTTOM,
+	PF_TOP
+};
+enum pf_updates {
+	PF_POSCHANGED,
+	PF_DRAWAGAIN
+};
+
+
+static void packet_fence_update(packet_fence *);
+
+/* ON/OFF SWITCH */
+gboolean packet_fence_active = TRUE;
+packet_fence *pf = NULL;
+	
+/* Zoom in and out callback */
+static void
+packet_fence_zoomed(GtkWidget *w, gpointer data){
+	static int zoom[] = { 1,2,5,10,20,50,100,200,500,1000,2000,5000,10000,20000,50000,100000,200000,500000,1000000};/* simpler than an algorithm!*/
+	static int idx = 12; /* where we start off */
+	int zoomnum = sizeof(zoom)/sizeof(int);/* number of levels*/
+	char str[30];
+	
+	switch ((int)data ) {
+		case ZOOMEDOUT:
+			idx++;
+			if (idx >= zoomnum ) idx = zoomnum - 1; 
+			break;
+		case ZOOMEDIN:
+			idx--;
+			if (idx <= 0 ) idx = 0; 
+			break;
+	}
+	pf->usecpix = zoom[idx];
+	sprintf(str, "%d usec/pixel",pf->usecpix);
+	gtk_label_set_text( GTK_LABEL(pf->zoomlevel), str);
+	pf->update = PF_DRAWAGAIN;
+	packet_fence_update(pf);
+}
+
+static void
+calc_bytepix(packet_fence *pf)
+{
+	int availpix;
+	availpix = pf->pixwidth - pf->lmargin - pf->rmargin;
+	if (availpix <=0) availpix = 10;
+	pf->bytepix = (float)pf->maxpacketlength/(float)availpix; /*bytes per pixel */
+}
+			
+
+/* callback for config event*/
+static gint 
+packet_fence_config( GtkWidget         *widget,
+                             gpointer user_data )
+{
+GdkColor zoomwinfg = {0,0xc000,0xc000,0xc000};/*grey*/
+GdkColor selectfg = {0,0x0000,0x0000,0xffff};/*blue*/
+  if (!widget->window) return TRUE;/* too soo yet */
+  if (pf->pixmap)
+    gdk_pixmap_unref(pf->pixmap);/* destroy the old one*/
+
+
+  pf->pixmap = gdk_pixmap_new(widget->window,
+			  widget->allocation.width,
+			  widget->allocation.height,
+			  -1);/* create a pixmap the size of drawing area*/
+  gdk_draw_rectangle (pf->pixmap,
+		      widget->style->white_gc,
+		      TRUE,
+		      0, 0,
+		      widget->allocation.width,
+		      widget->allocation.height); /* white out*/
+  pf->pixwidth = widget->allocation.width; /* save width of pf drawing area */
+  pf->pixheight = widget->allocation.height; /* save height */
+  calc_bytepix(pf);
+  /*
+   * I need a better way of scaling this. Maybe I should size to maximum size
+   * that I've seen??
+  */
+  pf->pixtimeorigin = pf->pixheight/2; /* centre the time to middle of widget */
+  pf->gc = gdk_gc_new(widget->window);/* generic gc*/
+  pf->selectgc = gdk_gc_new(widget->window);/* gc for drawing selected packet*/
+  pf->zoomwingc = gdk_gc_new(widget->window);/*gc for drawing the zoom window */
+  gdk_colormap_alloc_color(gtk_widget_get_colormap(widget),&zoomwinfg,FALSE,TRUE);
+  gdk_gc_set_foreground(pf->zoomwingc,&zoomwinfg);
+  gdk_colormap_alloc_color(gtk_widget_get_colormap(widget),&selectfg,FALSE,TRUE);
+  gdk_gc_set_foreground(pf->selectgc,&selectfg);
+
+  if (pf->framearray) {
+	  pf->framearray = (frame_data**)g_realloc(pf->framearray,pf->pixheight * sizeof (frame_data *));
+	  /* allocate room to store a widget-ful of frame pointers*/
+  }
+  else {
+	  pf->framearray = (frame_data**)g_malloc(pf->pixheight * sizeof (frame_data *));
+  }
+  pf->update = PF_DRAWAGAIN;
+  packet_fence_update(pf);
+  return TRUE;
+}
+
+/* Redraw the screen from the backing pixmap */
+static gint packet_fence_expose( GtkWidget      *widget,
+                          GdkEventExpose *event )
+{
+  gdk_draw_pixmap(widget->window,
+		  widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+		  pf->pixmap,
+		  event->area.x, event->area.y,
+		  event->area.x, event->area.y,
+		  event->area.width, event->area.height);
+
+  return FALSE;
+}
+/* callback for a row being selected in the packet list*/
+void
+packet_fence_row_select(gint row)
+{
+	if (pf->selectedrow != row ) {/* only bother updating if different*/
+		pf->selectedrow = row;/* save the new row*/
+		pf->update = PF_DRAWAGAIN;
+		packet_fence_update(pf);/* update */
+	}
+}
+
+/* callback for clicking on the packet fence */
+gint
+packet_fence_pressed_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+	GdkEventButton * event_button;
+	frame_data * fdata;
+	int i,pos,sign = 1;
+	if(widget == NULL || event == NULL ) {
+		return FALSE;
+	}
+	if(event->type == GDK_BUTTON_PRESS) {
+		event_button = (GdkEventButton *) event;
+		
+		if(event_button->button == 1) {
+			for (i=0;i< 8; i++) {/*look for nearest frame +/- 8 pixels */
+				for (sign = -1; sign<=1;sign+=2) {
+					pos = (sign * i ) + (int)event_button->y;/*alternate 0,-1,1,-2,2.... */
+					if (pos<0 || pos >=pf->pixheight) return TRUE; /* gone over the edge */
+					if ((fdata = (frame_data*)pf->framearray[pos]))
+					{
+						goto_frame(&cfile,fdata->num); /* goto this frame in clist */
+						return TRUE;
+					}
+				}
+			}
+			return TRUE;
+		}
+	}
+	return FALSE;/*not one of ours */
+}
+
+
+/*
+static void        
+packet_fence_size_request_cb              (GtkWidget *widget,
+                                              GtkRequisition *requisition,
+                                              gpointer user_data)
+{
+	printf("got size\n");
+}
+*/
+
+static void        
+packet_fence_config_event_cb              (GtkWidget *widget,
+                                              GdkEventConfigure *event,
+                                              gpointer user_data)
+{
+	packet_fence_config(widget,user_data);
+}
+	
+			
+/* create the packet fence */
+packet_fence *
+packet_fence_new()
+{
+	GtkWidget *zoomin;
+	GtkWidget *zoomout;
+	GtkWidget *bbox;
+	pf = (packet_fence*) g_malloc(sizeof(packet_fence));
+	pf->pixwidth = 50;
+	pf->pixheight = 10;
+	pf->lmargin = 10 ;
+	pf->rmargin = 20 ;
+	pf->hmargin = 20 ;
+	pf->maxpacketlength = 1518;/* till we know better */
+	calc_bytepix(pf);
+	pf->usecpix =  10000 ; /* usecs per pixel */
+	pf->timeorigin = 0;
+	pf->pixtimeorigin = 0;
+	pf->adj_seq = 0;
+	pf->started = FALSE;
+	pf->update = FALSE;
+	pf->box = gtk_table_new (2,2, FALSE); /* create 2 x 2 table */
+	gtk_widget_set_usize(pf->box, 100 ,100);
+	gtk_widget_show (pf->box);
+	pf->ruler = gtk_vruler_new();
+	gtk_ruler_set_metric(GTK_RULER(pf->ruler),GTK_PIXELS);
+	gtk_widget_set_usize(pf->ruler, 16 ,0);
+	gtk_table_attach (GTK_TABLE (pf->box), pf->ruler, 0,1,0,1,GTK_FILL,GTK_FILL|GTK_EXPAND,0,0); /* put a 20 pixel wide ruler down left */
+	gtk_widget_show (pf->ruler);
+	pf->drawing_area = gtk_drawing_area_new ();
+  	gtk_drawing_area_size (GTK_DRAWING_AREA (pf->drawing_area), pf->pixwidth, pf->pixheight);
+	gtk_table_attach (GTK_TABLE (pf->box), pf->drawing_area, 1,2,0,1,GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL|GTK_EXPAND,0,0); /* put a drawing area up on the right */
+	gtk_widget_show (pf->drawing_area);
+	bbox = gtk_hbox_new(FALSE,1);
+	zoomout = gtk_button_new_with_label("<");
+	gtk_signal_connect(GTK_OBJECT(zoomout), "clicked",
+		     GTK_SIGNAL_FUNC(packet_fence_zoomed), (gpointer) ZOOMEDOUT);
+	zoomin = gtk_button_new_with_label(">");
+	gtk_signal_connect(GTK_OBJECT(zoomin), "clicked",
+		     GTK_SIGNAL_FUNC(packet_fence_zoomed), (gpointer) ZOOMEDIN);
+	pf->zoomlevel = gtk_label_new("10000 usec/pixel");
+	gtk_widget_set_usize(zoomin, 14 ,14);
+	gtk_widget_set_usize(zoomout, 14 ,14);
+	gtk_widget_set_usize(pf->zoomlevel, 0 ,14);
+	gtk_label_set_justify(GTK_LABEL(pf->zoomlevel),GTK_JUSTIFY_LEFT);
+
+	gtk_box_pack_start(GTK_BOX(bbox), zoomout, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(bbox), zoomin, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(bbox), pf->zoomlevel, FALSE, FALSE, 0);
+	gtk_table_attach (GTK_TABLE (pf->box), bbox, 1,2,1,2,GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL,0,0); /* add the zoom box with two buttons and label to bottom right */
+	gtk_widget_show(zoomin);
+	gtk_widget_show(zoomout);
+	gtk_widget_show(pf->zoomlevel);
+	gtk_widget_show(bbox);
+	gtk_signal_connect (GTK_OBJECT (pf->drawing_area), "expose_event",
+	      (GtkSignalFunc) packet_fence_expose, NULL);
+	gtk_signal_connect (GTK_OBJECT(pf->drawing_area),"configure_event",
+		(GtkSignalFunc) packet_fence_config_event_cb, NULL);
+/*	gtk_signal_connect (GTK_OBJECT(pf->drawing_area),"size_request",
+		(GtkSignalFunc) packet_fence_size_request_cb, NULL);
+*/ 
+	gtk_signal_connect(GTK_OBJECT(pf->drawing_area), "button_press_event",
+		     GTK_SIGNAL_FUNC(packet_fence_pressed_cb), NULL);
+	gtk_widget_set_events (pf->drawing_area, GDK_EXPOSURE_MASK|GDK_BUTTON_PRESS_MASK );
+	return pf;
+
+}
+
+/* return the relative time, in usecs, a frame was grabbed */
+static int 
+framereltime( frame_data * fdata) 
+/*	compute  total relative time */
+{
+	return  fdata->rel_secs * 1000000 + fdata->rel_usecs; 
+}
+
+/* convert time to pixels*/
+static int
+timetopix( packet_fence * pf, int time ) 
+/* convert time to pixel position */
+{
+	int timeoffset;
+	int pixtime;
+	timeoffset = time - pf->timeorigin;/* diff between now and origin */
+	pixtime = timeoffset / pf->usecpix + pf->pixtimeorigin;/* pixels down relative to 0 */
+	
+	return pixtime;
+}
+
+/* convert pixels to time*/
+static int
+pixtotime( packet_fence * pf, int pix ) 
+/* convert pixel position to time in usecs */
+{
+	int pixoffset;
+	int time;
+	pixoffset = pix - pf->pixtimeorigin;/* diff between centre and position */
+	time = pixoffset * pf->usecpix + pf->timeorigin;/* relative to time  */
+	
+	return time;
+}
+
+/* draw a packet in the right spot */
+gboolean
+packet_fence_draw_packet(gint row )
+{
+  frame_data * fdata;
+  gint pixlen,time,pixdown;
+  GdkGC * packetgc;
+  GtkCListRow *clistrow;
+	fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
+	if (fdata == NULL ) return PF_END; /* might not be loaded yet */
+	if (fdata->pkt_len > pf->maxpacketlength ) {
+		pf->maxpacketlength = fdata->pkt_len + 100; /* don't want to it toom often */
+		calc_bytepix(pf);
+		return PF_REDRAW;
+	}
+		
+	pixlen =   fdata->pkt_len / pf->bytepix; /* set packet length  */
+	time = framereltime(fdata);
+	pixdown = timetopix(pf,time);
+	if (pixdown <0 ) return PF_BOTTOM; /* reached a limit */
+	if (pixdown >= pf->pixheight) return PF_TOP; /* reached a limit */
+	if (pf->selectedrow == row) /* if it is selected in list add the blue bits*/
+	{
+		gdk_draw_line(pf->pixmap,pf->selectgc,0,pixdown,pf->lmargin-2,pixdown);
+		gdk_draw_line(pf->pixmap,pf->selectgc,pf->pixwidth-pf->rmargin+1,pixdown,pf->pixwidth,pixdown);
+	}
+
+	clistrow = gtk_clist_get_clistrow(GTK_CLIST(packet_list),row);/* this is the call to my hacked function to get the GtkCListRow info */
+	if (!clistrow) return PF_END; /* reached a limit */
+		
+	if (clistrow->fg_set) {/* its not default*/
+		gdk_gc_set_foreground(pf->gc,&(clistrow->foreground));
+		packetgc = pf->gc;
+	} else { /* its default colour*/
+		packetgc = pf->drawing_area->style->black_gc ;
+	}
+	gdk_draw_line(pf->pixmap,packetgc,pf->lmargin,pixdown,pf->lmargin + pixlen,pixdown);
+	pf->framearray[pixdown] = fdata; /* save the (frame_data *) where we drew it for later */
+	if (row <=0) return PF_BOTTOM;
+	return PF_COOL; /* sucessfully drawn */
+}
+static int
+packet_fence_clear_bg(packet_fence *pf)
+{
+	  if(!pf || !pf->pixmap || !pf->drawing_area) return FALSE;
+	  
+	  gdk_draw_rectangle (pf->pixmap,
+		      pf->drawing_area->style->white_gc,
+		      TRUE,
+		      0, 0,
+		      pf->drawing_area->allocation.width,
+		      pf->drawing_area->allocation.height);/*make a clean slate */
+	  return TRUE;
+}
+static int
+packet_fence_draw_zoomrect(packet_fence *pf)
+{
+  frame_data *fdata;
+  int time,zoomrecttop,zoomrectbot;
+	  if(!pf || !pf->pixmap) return FALSE;
+	/* now print zoom rectangle. This shows where the displayed packet list  is relative to the displayed packet fence*/
+	if ((fdata = ((frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), pf->firstrow)) )){
+		time = framereltime(fdata);
+		zoomrecttop = timetopix(pf,time) - 1;   
+		} 
+	else zoomrecttop = 0;
+	if ((fdata = ((frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), pf->lastrow)) )){
+		time = framereltime(fdata);
+		zoomrectbot = timetopix(pf,time);
+		} 
+	else zoomrectbot = pf->pixheight;
+	gdk_draw_rectangle(pf->pixmap,pf->zoomwingc,TRUE,pf->lmargin,zoomrecttop,pf->pixwidth - pf->lmargin - pf->rmargin, zoomrectbot - zoomrecttop + 2); /* draw it in */
+	return TRUE;
+}
+static int
+packet_fence_new_position(packet_fence *pf)
+{
+  frame_data *fdata;
+  GtkAdjustment *adj;
+  int i;
+
+  
+  	if (!pf || !packet_fence_active || !pf->framearray) { /* only update if we are ready, willing and able */
+		return FALSE;
+	}
+	adj = GTK_CLIST(packet_list)->vadjustment;
+	for (i=0;i<pf->pixheight;i++) pf->framearray[i] = NULL; /* clear out the stored data as it will be all wrong */
+	pf->adjvalue = adj->value;
+	pf->adjpagesize = adj->page_size;
+	pf->firstrow = (int)(adj->value)/(GTK_CLIST(packet_list)->row_height+1); /* get the first row in the packet list. (The +1 works for me) */
+	pf->lastrow = pf->firstrow - 1 + (int)(adj->page_size)/(GTK_CLIST(packet_list)->row_height);/* work out what the last row should be. page_size and row_height are in pixels*/	
+	pf->midrow = (pf->firstrow + pf->lastrow) / 2; /* find the middle*/
+	fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), pf->midrow);
+	if (fdata == NULL ) {
+		return FALSE;
+	}
+	pf->timeorigin = framereltime(fdata); /* this is the time in the mid of widget */
+	return TRUE;
+}
+static int
+packet_fence_refresh_drawing_area(packet_fence *pf)
+{
+	GdkRectangle update_rect;
+	if(!pf || !pf->drawing_area) return FALSE;
+	update_rect.x = 0;
+	update_rect.y = 0;
+	update_rect.width = pf->drawing_area->allocation.width;
+	update_rect.height = pf->drawing_area->allocation.height;
+	gtk_widget_draw( pf->drawing_area, &update_rect);/* we can draw to screen now */
+	return TRUE;
+}
+static int
+packet_fence_update_ruler(packet_fence *pf)
+{
+	int firsttime,lasttime;
+	firsttime = pixtotime(pf,0);
+	lasttime = pixtotime(pf,pf->pixheight);
+	gtk_ruler_set_range( GTK_RULER(pf->ruler), firsttime/1000000.0,  lasttime/1000000.0  ,pf->timeorigin/1000000.0,10000); /* set the ruler limits */
+	return TRUE;
+}
+static int
+packet_fence_update_packets(packet_fence *pf)
+{
+	int flag = TRUE;
+	int ret = 0;
+	int static draw_count=0;
+	while(flag) {
+		ret = packet_fence_draw_packet(pf->currentrow) ;  /* draw until none left */
+		if (ret == PF_BOTTOM)  {
+			pf->currentrow = pf->midrow + 1;
+			continue;
+		} else if (ret == PF_REDRAW ) { 
+			pf->currentrow = pf->midrow;
+			continue;
+		} else if (ret == PF_END || ret == PF_TOP ) { 
+			flag = FALSE;
+			continue;
+		}
+		if(draw_count++>200) {
+			draw_count = 0;
+			packet_fence_refresh_drawing_area(pf);
+			if (gtk_events_pending()) {/* someone wants some time */
+				pf->idleid = gtk_idle_add((GtkFunction)&packet_fence_update,pf);/* wait for someone else */
+				return FALSE;
+			}
+		}
+		
+		if(pf->currentrow <= pf->midrow ){
+			pf->currentrow--;
+		}
+		else if(pf->currentrow > pf->midrow ){
+			pf->currentrow++;
+		}
+	}
+	return TRUE;
+		
+			
+}
+/* update the packet fence */
+static void 
+packet_fence_update(packet_fence * pf){
+	
+	if(!pf) return ;
+	if(pf->idleid) {/* this is a return from being interrupted */
+		gtk_idle_remove(pf->idleid);
+		pf->idleid = 0;
+	}
+	if(!packet_fence_new_position(pf)) return;
+	if(!packet_fence_clear_bg(pf)) return;
+	if(!packet_fence_draw_zoomrect(pf)) return;
+	pf->currentrow = pf->midrow;
+	pf->started = TRUE;
+	if(!packet_fence_update_packets(pf)) return;
+		pf->started = FALSE;
+		if(!packet_fence_refresh_drawing_area(pf)) return;
+		if(!packet_fence_update_ruler(pf))return;
+	return;
+}
+
+/* packet list value has changed */
+void 
+packet_list_value_changed(GtkAdjustment *adj, gpointer user_data)
+{
+	packet_fence * pf;
+	pf = (packet_fence *)user_data;
+	if (!pf) return;
+	pf->adj_seq++;
+	pf->update = PF_POSCHANGED;
+	packet_fence_update(pf);
+}
+/* packet list has changed, might be resize */
+void 
+packet_list_changed(GtkAdjustment *adj, gpointer user_data)
+{
+	packet_fence * pf;
+	pf = (packet_fence *)user_data;
+	if (!pf) return;
+	if (adj->value == pf->adjvalue && adj->page_size == pf->adjpagesize) {
+		return; /* nothing really changed, the clist just got nudged. Probably by us writing to the zoom label */
+	}
+	pf->update = PF_POSCHANGED;
+	packet_fence_update(pf);
+}
diff -urN ethereal-0.8.18/gtk/packet_fence.h ethereal-0.8.18-pf-1.1/gtk/packet_fence.h
--- ethereal-0.8.18/gtk/packet_fence.h	Thu Jan  1 09:30:00 1970
+++ ethereal-0.8.18-pf-1.1/gtk/packet_fence.h	Sat May 19 14:16:06 2001
@@ -0,0 +1,69 @@
+
+/* packet_fence.h
+ * Definitions for Packet Fence
+ *
+ * $Id: packet_fence.h,v 1.1 $
+ *
+ * Copyright (c) 2000 by Martin Visser <martin.visser@xxxxxxxxxx>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs
+ * Copyright 1999 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.
+ */
+
+typedef struct _packet_fence {
+	GtkWidget *box ;
+	GtkWidget *drawing_area;
+	GtkWidget *ruler;
+	GtkWidget *zoomlevel;
+	GdkPixmap * pixmap;
+	GdkGC * gc;
+	GdkGC * zoomwingc;
+	GdkGC * selectgc;
+	int pixwidth;
+	int pixheight;
+	int hmargin;
+	int lmargin;
+	int rmargin;
+	float bytepix;
+	int usecpix;
+	int timeorigin;
+	int pixtimeorigin;
+	int selectedrow;
+	int currentrow;
+	int firstrow;
+	int lastrow;
+	int midrow;
+	int maxpacketlength;
+	int adj_seq;
+	int started;
+	int interrupted;
+	int update;
+	int idleid;
+	float begintime;
+	float endtime;
+	gfloat adjvalue;
+	gfloat adjpagesize;
+	frame_data **framearray;
+} packet_fence;
+
+
+packet_fence *packet_fence_new();
+void packet_list_value_changed(GtkAdjustment * adj, gpointer user_data);
+void packet_list_changed(GtkAdjustment * adj, gpointer user_data);
+void packet_fence_row_select(gint row);
+
+extern packet_fence * pf;