Ethereal-dev: Re: [ethereal-dev] Popup packet window

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

From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Fri, 18 Feb 2000 10:16:34 -0800
Here's a version of the code that should clear up the various issues
I've mentioned - it changes the menu item to be "Show Packet In New
Window" to make it clearer what it does (and also adds it to the
"Display" menu, and renames the source file to "packet_win.c"), gets rid
of the extra empty pane, gives each packet window its own copy of the
packet data and protocol tree, and builds a list of all the packet
windows so that if you change settings in the "GUI" tab of the
"Edit:Preferences" window, it affects all windows (well, it doesn't, I
suspect, affect the "Follow TCP Stream" window - but that's a bug as
well, and probably a long-standing one).

It's a patch plus "gtk/packet_win.c" and "gtk/packet_win.h".
Index: file.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/file.c,v
retrieving revision 1.163
diff -c -r1.163 file.c
*** file.c	2000/02/14 04:57:30	1.163
--- file.c	2000/02/18 18:11:31
***************
*** 77,82 ****
--- 77,83 ----
  #include "util.h"
  #include "simple_dialog.h"
  #include "ui_util.h"
+ #include "prefs.h"
  #include "gtk/proto_draw.h"
  #include "dfilter.h"
  #include "conversation.h"
Index: gtk/Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/Makefile.am,v
retrieving revision 1.24
diff -c -r1.24 Makefile.am
*** Makefile.am	2000/02/12 08:31:45	1.24
--- Makefile.am	2000/02/18 18:11:32
***************
*** 57,62 ****
--- 57,64 ----
  	main.h		\
  	menu.c		\
  	menu.h		\
+ 	packet_win.c	\
+ 	packet_win.h	\
  	plugins_dlg.c	\
  	prefs_dlg.c	\
  	prefs_dlg.h	\
Index: gtk/Makefile.nmake
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/Makefile.nmake,v
retrieving revision 1.5
diff -c -r1.5 Makefile.nmake
*** Makefile.nmake	2000/02/12 08:44:43	1.5
--- Makefile.nmake	2000/02/18 18:11:32
***************
*** 23,29 ****
  	gui_prefs.obj \
  	main.obj 	\
  	menu.obj 	\
! 	plugins_dlg.obj \
  	prefs_dlg.obj \
  	print_dlg.obj \
  	print_prefs.obj  \
--- 23,30 ----
  	gui_prefs.obj \
  	main.obj 	\
  	menu.obj 	\
! 	packet_win.obj	\
! 	plugins_dlg.obj	\
  	prefs_dlg.obj \
  	print_dlg.obj \
  	print_prefs.obj  \
Index: gtk/gtkglobals.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/gtkglobals.h,v
retrieving revision 1.5
diff -c -r1.5 gtkglobals.h
*** gtkglobals.h	1999/12/30 23:02:54	1.5
--- gtkglobals.h	2000/02/18 18:11:32
***************
*** 36,45 ****
  
  extern GtkStyle *item_style;
  
! void set_scrollbar_placement(int); /* 1=right, 0=left */
  void set_plist_sel_browse(gboolean);
! void set_ptree_sel_browse(gboolean);
! void set_ptree_line_style(gint style);
! void set_ptree_expander_style(gint style);
  
  #endif
--- 36,50 ----
  
  extern GtkStyle *item_style;
  
! void set_scrollbar_placement_scrollw(GtkWidget *, int); /* 0=left, 1=right */
! void set_scrollbar_placement_textw(GtkWidget *, GtkWidget *, int pos); /* 0=left, 1=right */
! void set_scrollbar_placement_all(int); /* 1=right, 0=left */
  void set_plist_sel_browse(gboolean);
! void set_ptree_sel_browse(GtkWidget *, gboolean);
! void set_ptree_sel_browse_all(gboolean);
! void set_ptree_line_style(GtkWidget *, gint style);
! void set_ptree_line_style_all(gint style);
! void set_ptree_expander_style(GtkWidget *, gint style);
! void set_ptree_expander_style_all(gint style);
  
  #endif
Index: gtk/gui_prefs.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/gui_prefs.c,v
retrieving revision 1.3
diff -c -r1.3 gui_prefs.c
*** gui_prefs.c	1999/12/30 23:02:55	1.3
--- gui_prefs.c	2000/02/18 18:11:34
***************
*** 241,247 ****
  	gboolean	value = GPOINTER_TO_INT(data);
  
  	temp_gui_scrollbar_on_right = value;
! 	set_scrollbar_placement(value);
  }
  
  static void
--- 241,247 ----
  	gboolean	value = GPOINTER_TO_INT(data);
  
  	temp_gui_scrollbar_on_right = value;
! 	set_scrollbar_placement_all(value);
  }
  
  static void
***************
*** 259,265 ****
  	gboolean	value = GPOINTER_TO_INT(data);
  
  	temp_gui_ptree_sel_browse = value;
! 	set_ptree_sel_browse(value);
  }
  
  static void
--- 259,265 ----
  	gboolean	value = GPOINTER_TO_INT(data);
  
  	temp_gui_ptree_sel_browse = value;
! 	set_ptree_sel_browse_all(value);
  }
  
  static void
***************
*** 268,274 ****
  	gint	value = GPOINTER_TO_INT(data);
  
  	temp_gui_ptree_line_style = value;
! 	set_ptree_line_style(value);
  }
  
  static void
--- 268,274 ----
  	gint	value = GPOINTER_TO_INT(data);
  
  	temp_gui_ptree_line_style = value;
! 	set_ptree_line_style_all(value);
  }
  
  static void
***************
*** 277,283 ****
  	gint	value = GPOINTER_TO_INT(data);
  
  	temp_gui_ptree_expander_style = value;
! 	set_ptree_expander_style(value);
  }
  
  
--- 277,283 ----
  	gint	value = GPOINTER_TO_INT(data);
  
  	temp_gui_ptree_expander_style = value;
! 	set_ptree_expander_style_all(value);
  }
  
  
***************
*** 302,320 ****
  void
  gui_prefs_cancel(GtkWidget *w)
  {
! 	/* Reset scrollbar placement value back to what the
! 	 * current preferences says it should be */
  	temp_gui_scrollbar_on_right = prefs.gui_scrollbar_on_right;
  	temp_gui_plist_sel_browse = prefs.gui_plist_sel_browse;
  	temp_gui_ptree_sel_browse = prefs.gui_ptree_sel_browse;
  	temp_gui_ptree_line_style = prefs.gui_ptree_line_style;
  	temp_gui_ptree_expander_style = prefs.gui_ptree_expander_style;
  
! 	set_scrollbar_placement(prefs.gui_scrollbar_on_right);
  	set_plist_sel_browse(prefs.gui_plist_sel_browse);
! 	set_ptree_sel_browse(prefs.gui_ptree_sel_browse);
! 	set_ptree_line_style(prefs.gui_ptree_line_style);
! 	set_ptree_expander_style(prefs.gui_ptree_expander_style);
  
  	gui_prefs_delete(w);
  }
--- 302,320 ----
  void
  gui_prefs_cancel(GtkWidget *w)
  {
! 	/* Reset GUI preference values back to what the
! 	 * current preferences says they should be */
  	temp_gui_scrollbar_on_right = prefs.gui_scrollbar_on_right;
  	temp_gui_plist_sel_browse = prefs.gui_plist_sel_browse;
  	temp_gui_ptree_sel_browse = prefs.gui_ptree_sel_browse;
  	temp_gui_ptree_line_style = prefs.gui_ptree_line_style;
  	temp_gui_ptree_expander_style = prefs.gui_ptree_expander_style;
  
! 	set_scrollbar_placement_all(prefs.gui_scrollbar_on_right);
  	set_plist_sel_browse(prefs.gui_plist_sel_browse);
! 	set_ptree_sel_browse_all(prefs.gui_ptree_sel_browse);
! 	set_ptree_line_style_all(prefs.gui_ptree_line_style);
! 	set_ptree_expander_style_all(prefs.gui_ptree_expander_style);
  
  	gui_prefs_delete(w);
  }
Index: gtk/main.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/main.c,v
retrieving revision 1.105
diff -c -r1.105 main.c
*** main.c	2000/02/13 10:36:06	1.105
--- main.c	2000/02/18 18:11:37
***************
*** 109,114 ****
--- 109,115 ----
  #include "proto_draw.h"
  #include "dfilter.h"
  #include "keys.h"
+ #include "packet_win.h"
  #include "gtkglobals.h"
  #include "plugins.h"
  
***************
*** 138,143 ****
--- 139,145 ----
  static void follow_load_text(GtkWidget *text, char *filename, guint8 show_type);
  static void follow_print_stream(GtkWidget *w, gpointer parent_w);
  static char* hfinfo_numeric_format(header_field_info *hfinfo);
+ static void set_scrollbar_placement_main_window(int pos); /* 0=left, 1=right */
  static void create_main_window(gint, gint, gint, e_prefs*);
  
  /* About Ethereal window */
***************
*** 853,871 ****
  tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column, gpointer user_data)
  {
  	field_info	*finfo;
- 	int		tree_selected_start = -1;
- 	int		tree_selected_len = -1;
  
  	g_assert(node);
  	finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
  	if (!finfo) return;
  
  	finfo_selected = finfo;
- 	tree_selected_start = finfo->start;
- 	tree_selected_len   = finfo->length;
  
  	packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.current_frame->cap_len, 
! 		tree_selected_start, tree_selected_len, cf.current_frame->encoding);
  }
  
  static void
--- 855,869 ----
  tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column, gpointer user_data)
  {
  	field_info	*finfo;
  
  	g_assert(node);
  	finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
  	if (!finfo) return;
  
  	finfo_selected = finfo;
  
  	packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.current_frame->cap_len, 
! 		finfo->start, finfo->length, cf.current_frame->encoding);
  }
  
  static void
***************
*** 886,912 ****
      expand_all_tree(cf.protocol_tree, tree_view);
  }
  
  void
! set_scrollbar_placement(int pos) /* 0=left, 1=right */
  {
  	if (pos) {
! 		gtk_scrolled_window_set_placement( GTK_SCROLLED_WINDOW(pkt_scrollw),
! 				GTK_CORNER_TOP_LEFT );
! 		gtk_scrolled_window_set_placement( GTK_SCROLLED_WINDOW(tv_scrollw),
! 				GTK_CORNER_TOP_LEFT );
! 		gtk_widget_hide(bv_vscroll_left);
! 		gtk_widget_show(bv_vscroll_right);
  	}
! 	else {
! 		gtk_scrolled_window_set_placement( GTK_SCROLLED_WINDOW(pkt_scrollw),
! 				GTK_CORNER_TOP_RIGHT );
! 		gtk_scrolled_window_set_placement( GTK_SCROLLED_WINDOW(tv_scrollw),
! 				GTK_CORNER_TOP_RIGHT );
! 		gtk_widget_hide(bv_vscroll_right);
! 		gtk_widget_show(bv_vscroll_left);
  	}
  }
  
  void
  set_plist_sel_browse(gboolean val)
  {
--- 884,938 ----
      expand_all_tree(cf.protocol_tree, tree_view);
  }
  
+ /* Set the scrollbar placement of a scrolled window based upon pos value:
+    0 = left, 1 = right */
  void
! set_scrollbar_placement_scrollw(GtkWidget *scrollw, int pos) /* 0=left, 1=right */
  {
  	if (pos) {
! 		gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(scrollw),
! 				GTK_CORNER_TOP_LEFT);
! 	} else {
! 		gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(scrollw),
! 				GTK_CORNER_TOP_RIGHT);
  	}
! }
! 
! /* Set the scrollbar placement of a 3-box text window (hex display) based
!    upon pos value: 0 = left, 1 = right */
! void
! set_scrollbar_placement_textw(GtkWidget *vscroll_left, GtkWidget *vscroll_right,
!     int pos)
! {
! 	if (pos) {
! 		gtk_widget_hide(vscroll_left);
! 		gtk_widget_show(vscroll_right);
! 	} else {
! 		gtk_widget_hide(vscroll_right);
! 		gtk_widget_show(vscroll_left);
  	}
  }
  
+ /* Set the scrollbar placement of all the subwindows of the main window
+    based on pos value: 0 = left, 1 = right */
+ static void
+ set_scrollbar_placement_main_window(int pos)
+ {
+ 	set_scrollbar_placement_scrollw(pkt_scrollw, pos);
+ 	set_scrollbar_placement_scrollw(tv_scrollw, pos);
+ 	set_scrollbar_placement_textw(bv_vscroll_left, bv_vscroll_right, pos);
+ }
+ 
+ /* Set the scrollbar placement of all windows based on pos value:
+    0 = left, 1 = right */
+ void
+ set_scrollbar_placement_all(int pos)
+ {
+ 	set_scrollbar_placement_main_window(pos);
+ 	set_scrollbar_placement_packet_wins(pos);
+ }
+ 
+ /* Set the selection mode of the packet list window. */
  void
  set_plist_sel_browse(gboolean val)
  {
***************
*** 923,963 ****
  	}
  }
  
  void
! set_ptree_sel_browse(gboolean val)
  {
  	/* Yeah, GTK uses "browse" in the case where we do not, but oh well. I think
  	 * "browse" in Ethereal makes more sense than "SINGLE" in GTK+ */
  	if (val) {
! 		gtk_clist_set_selection_mode(GTK_CLIST(tree_view), GTK_SELECTION_SINGLE);
  	}
  	else {
! 		gtk_clist_set_selection_mode(GTK_CLIST(tree_view), GTK_SELECTION_BROWSE);
  	}
  }
  
  void
! set_ptree_line_style(gint style)
  {
  	/* I'm using an assert here since the preferences code limits
  	 * the user input, both in the GUI and when reading the preferences file.
  	 * If the value is incorrect, it's a program error, not a user-initiated error.
  	 */
  	g_assert(style >= GTK_CTREE_LINES_NONE && style <= GTK_CTREE_LINES_TABBED);
! 	gtk_ctree_set_line_style( GTK_CTREE(tree_view), style );
  }
  
  void
! set_ptree_expander_style(gint style)
  {
  	/* I'm using an assert here since the preferences code limits
  	 * the user input, both in the GUI and when reading the preferences file.
  	 * If the value is incorrect, it's a program error, not a user-initiated error.
  	 */
  	g_assert(style >= GTK_CTREE_EXPANDER_NONE && style <= GTK_CTREE_EXPANDER_CIRCULAR);
! 	gtk_ctree_set_expander_style( GTK_CTREE(tree_view), style );
  }
  	
  
  void
  file_quit_cmd_cb (GtkWidget *widget, gpointer data)
--- 949,1014 ----
  	}
  }
  
+ /* Set the selection mode of a given packet tree window. */
  void
! set_ptree_sel_browse(GtkWidget *tv, gboolean val)
  {
  	/* Yeah, GTK uses "browse" in the case where we do not, but oh well. I think
  	 * "browse" in Ethereal makes more sense than "SINGLE" in GTK+ */
  	if (val) {
! 		gtk_clist_set_selection_mode(GTK_CLIST(tv), GTK_SELECTION_SINGLE);
  	}
  	else {
! 		gtk_clist_set_selection_mode(GTK_CLIST(tv), GTK_SELECTION_BROWSE);
  	}
  }
  
+ /* Set the selection mode of all packet tree windows. */
  void
! set_ptree_sel_browse_all(gboolean val)
  {
+ 	set_ptree_sel_browse(tree_view, val);
+ 	set_ptree_sel_browse_packet_wins(val);
+ }
+ 
+ /* Set the line style of a given packet tree window. */
+ void
+ set_ptree_line_style(GtkWidget *tv, gint style)
+ {
  	/* I'm using an assert here since the preferences code limits
  	 * the user input, both in the GUI and when reading the preferences file.
  	 * If the value is incorrect, it's a program error, not a user-initiated error.
  	 */
  	g_assert(style >= GTK_CTREE_LINES_NONE && style <= GTK_CTREE_LINES_TABBED);
! 	gtk_ctree_set_line_style( GTK_CTREE(tv), style );
! }
! 
! /* Set the line style of all packet tree window. */
! void
! set_ptree_line_style_all(gint style)
! {
! 	set_ptree_line_style(tree_view, style);
! 	set_ptree_line_style_packet_wins(style);
  }
  
+ /* Set the expander style of a given packet tree window. */
  void
! set_ptree_expander_style(GtkWidget *tv, gint style)
  {
  	/* I'm using an assert here since the preferences code limits
  	 * the user input, both in the GUI and when reading the preferences file.
  	 * If the value is incorrect, it's a program error, not a user-initiated error.
  	 */
  	g_assert(style >= GTK_CTREE_EXPANDER_NONE && style <= GTK_CTREE_EXPANDER_CIRCULAR);
! 	gtk_ctree_set_expander_style( GTK_CTREE(tv), style );
  }
  	
+ void
+ set_ptree_expander_style_all(gint style)
+ {
+ 	set_ptree_expander_style(tree_view, style);
+ 	set_ptree_expander_style_packet_wins(style);
+ }
  
  void
  file_quit_cmd_cb (GtkWidget *widget, gpointer data)
***************
*** 1480,1486 ****
  create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
  {
    GtkWidget           *main_vbox, *menubar, *u_pane, *l_pane,
!                       *bv_table, *stat_hbox,
                        *filter_bt, *filter_cm, *filter_te,
                        *filter_reset;
    GList               *filter_list = NULL;
--- 1531,1537 ----
  create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
  {
    GtkWidget           *main_vbox, *menubar, *u_pane, *l_pane,
!                       *stat_hbox,
                        *filter_bt, *filter_cm, *filter_te,
                        *filter_reset;
    GList               *filter_list = NULL;
***************
*** 1516,1525 ****
    gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
    l_pane = gtk_vpaned_new();
    gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
!   gtk_container_add(GTK_CONTAINER(main_vbox), l_pane);
!   gtk_widget_show(u_pane);
!   gtk_paned_add1 (GTK_PANED(l_pane), u_pane);
    gtk_widget_show(l_pane);
  
    /* Packet list */
    pkt_scrollw = gtk_scrolled_window_new(NULL, NULL);
--- 1567,1576 ----
    gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
    l_pane = gtk_vpaned_new();
    gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
!   gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
    gtk_widget_show(l_pane);
+   gtk_paned_add2(GTK_PANED(u_pane), l_pane);
+   gtk_widget_show(u_pane);
  
    /* Packet list */
    pkt_scrollw = gtk_scrolled_window_new(NULL, NULL);
***************
*** 1559,1582 ****
    gtk_signal_connect_object(GTK_OBJECT(packet_list), "button_press_event",
      GTK_SIGNAL_FUNC(popup_menu_handler), gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY));
    gtk_widget_show(packet_list);
-   
-   /* Tree view */
-   tv_scrollw = gtk_scrolled_window_new(NULL, NULL);
-   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tv_scrollw),
-     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-   gtk_paned_add2(GTK_PANED(u_pane), tv_scrollw);
-   gtk_widget_set_usize(tv_scrollw, -1, tv_size);
-   gtk_widget_show(tv_scrollw);
-   
-   tree_view = gtk_ctree_new(1, 0);
-   /* I need this next line to make the widget work correctly with hidden
-    * column titles and GTK_SELECTION_BROWSE */
-   gtk_clist_set_column_auto_resize( GTK_CLIST(tree_view), 0, TRUE );
-   gtk_container_add( GTK_CONTAINER(tv_scrollw), tree_view );
-   set_ptree_sel_browse(prefs->gui_ptree_sel_browse);
-   set_ptree_line_style(prefs->gui_ptree_line_style);
-   set_ptree_expander_style(prefs->gui_ptree_expander_style);
  
    gtk_signal_connect(GTK_OBJECT(tree_view), "tree-select-row",
      GTK_SIGNAL_FUNC(tree_view_select_row_cb), NULL);
    gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
--- 1610,1618 ----
    gtk_signal_connect_object(GTK_OBJECT(packet_list), "button_press_event",
      GTK_SIGNAL_FUNC(popup_menu_handler), gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY));
    gtk_widget_show(packet_list);
  
+   /* Tree view */
+   create_tree_view(tv_size, prefs, l_pane, &tv_scrollw, &tree_view);
    gtk_signal_connect(GTK_OBJECT(tree_view), "tree-select-row",
      GTK_SIGNAL_FUNC(tree_view_select_row_cb), NULL);
    gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
***************
*** 1588,1631 ****
    item_style = gtk_style_new();
    gdk_font_unref(item_style->font);
    item_style->font = m_r_font;
  
-   /* Byte view. The table is only one row high, but 3 columns
-    * wide. The middle column contains the GtkText with the hex dump.
-    * The left and right columns contain vertical scrollbars. They both
-    * do the same thing, but only one will be shown at a time, in accordance
-    * with where the user wants the other vertical scrollbars places
-    * (on the left or the right).
-    */
-   bv_table = gtk_table_new (1, 3, FALSE);
-   gtk_paned_pack2(GTK_PANED(l_pane), bv_table, FALSE, FALSE);
-   gtk_widget_set_usize(bv_table, -1, bv_size);
-   gtk_widget_show(bv_table);
- 
-   byte_view = gtk_text_new(NULL, NULL);
-   gtk_text_set_editable(GTK_TEXT(byte_view), FALSE);
-   gtk_text_set_word_wrap(GTK_TEXT(byte_view), FALSE);
-   gtk_table_attach (GTK_TABLE (bv_table), byte_view, 1, 2, 0, 1,
-     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
-   gtk_widget_show(byte_view);
- 
-   /* The gtk_text widget doesn't scroll horizontally (see gtktext.c)
-    * in the GTK+ distribution, so I removed the horizontal scroll bar
-    * that used to be here. I tried the gtk_text widget with a 
-    * gtk_scrolled_window w/ viewport, but the vertical scrollowing
-    * did not work well, and sometimes a few pixels were cut off on
-    * the bottom. */
- 
-   bv_vscroll_left = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
-   gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll_left, 0, 1, 0, 1,
-     GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
- 
-   bv_vscroll_right = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
-   gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll_right, 2, 3, 0, 1,
-     GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
-  
    /* Now that the 3 panes are created, set the vertical scrollbar
     * on the left or right according to the user's preference */
!   set_scrollbar_placement(prefs->gui_scrollbar_on_right);
  
    /* Progress/filter/info box */
    stat_hbox = gtk_hbox_new(FALSE, 1);
--- 1624,1637 ----
    item_style = gtk_style_new();
    gdk_font_unref(item_style->font);
    item_style->font = m_r_font;
+ 
+   /* Byte view. */
+   create_byte_view(bv_size, l_pane, &byte_view, &bv_vscroll_left,
+ 			&bv_vscroll_right);
  
    /* Now that the 3 panes are created, set the vertical scrollbar
     * on the left or right according to the user's preference */
!   set_scrollbar_placement_main_window(prefs->gui_scrollbar_on_right);
  
    /* Progress/filter/info box */
    stat_hbox = gtk_hbox_new(FALSE, 1);
Index: gtk/menu.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/menu.c,v
retrieving revision 1.24
diff -c -r1.24 menu.c
*** menu.c	2000/02/12 08:31:49	1.24
--- menu.c	2000/02/18 18:11:38
***************
*** 51,56 ****
--- 51,57 ----
  #include "summary_dlg.h"
  #include "display_opts.h"
  #include "prefs_dlg.h"
+ #include "packet_win.h"
  #include "print.h"
  #include "follow.h"
  #include "keys.h"
***************
*** 120,125 ****
--- 121,127 ----
    {"/Display/_Go To Frame...", NULL, GTK_MENU_FUNC(goto_frame_cb), 0, NULL},
    {"/Display/Collapse _All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
    {"/Display/_Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL},
+   {"/Display/_Show Packet In New Window", NULL, GTK_MENU_FUNC(new_window_cb), 0, NULL},
    {"/_Tools", NULL, NULL, 0, "<Branch>" },
  #ifdef HAVE_PLUGINS
    {"/Tools/_Plugins...", NULL, GTK_MENU_FUNC(tools_plugins_cmd_cb), 0, NULL},
***************
*** 144,149 ****
--- 146,152 ----
  	{"/Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
  	{"/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
    	{"/Print Packet", NULL, GTK_MENU_FUNC(file_print_packet_cmd_cb), 0, NULL},
+   	{"/Show Packet In New Window", NULL, GTK_MENU_FUNC(new_window_cb), 0, NULL}, 
  };
  
  static GtkItemFactoryEntry tree_view_menu_items[] =
***************
*** 327,332 ****
--- 330,336 ----
    set_menu_sensitivity("/File/Print Packet", have_selected_packet);
    set_menu_sensitivity("/Display/Collapse All", have_selected_packet);
    set_menu_sensitivity("/Display/Expand All", have_selected_packet);
+   set_menu_sensitivity("/Display/Show Packet In New Window", have_selected_packet);
    set_menu_sensitivity("/Tools/Follow TCP Stream",
        have_selected_packet ? (pi.ipproto == 6) : FALSE);
  }
Index: gtk/proto_draw.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/proto_draw.c,v
retrieving revision 1.13
diff -c -r1.13 proto_draw.c
*** proto_draw.c	2000/01/25 03:45:45	1.13
--- proto_draw.c	2000/02/18 18:11:39
***************
*** 45,51 ****
--- 45,53 ----
  #include "packet.h"
  #include "util.h"
  
+ #include "prefs.h"
  #include "proto_draw.h"
+ #include "gtkglobals.h"
  
  #define BYTE_VIEW_WIDTH    16
  #define BYTE_VIEW_SEP      8
***************
*** 56,61 ****
--- 58,108 ----
  proto_tree_draw_node(GNode *node, gpointer data);
  
  void
+ create_byte_view(gint bv_size, GtkWidget *pane, GtkWidget **byte_view_p,
+ 		GtkWidget **bv_vscroll_left_p, GtkWidget **bv_vscroll_right_p)
+ {
+   GtkWidget *bv_table, *byte_view, *bv_vscroll_left, *bv_vscroll_right;
+ 
+   /* Byte view. The table is only one row high, but 3 columns
+    * wide. The middle column contains the GtkText with the hex dump.
+    * The left and right columns contain vertical scrollbars. They both
+    * do the same thing, but only one will be shown at a time, in accordance
+    * with where the user wants the other vertical scrollbars places
+    * (on the left or the right).
+    */
+   bv_table = gtk_table_new (1, 3, FALSE);
+   gtk_paned_pack2(GTK_PANED(pane), bv_table, FALSE, FALSE);
+   gtk_widget_set_usize(bv_table, -1, bv_size);
+   gtk_widget_show(bv_table);
+ 
+   byte_view = gtk_text_new(NULL, NULL);
+   gtk_text_set_editable(GTK_TEXT(byte_view), FALSE);
+   gtk_text_set_word_wrap(GTK_TEXT(byte_view), FALSE);
+   gtk_table_attach (GTK_TABLE (bv_table), byte_view, 1, 2, 0, 1,
+     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
+   gtk_widget_show(byte_view);
+ 
+   /* The gtk_text widget doesn't scroll horizontally (see gtktext.c)
+    * in the GTK+ distribution, so I removed the horizontal scroll bar
+    * that used to be here. I tried the gtk_text widget with a 
+    * gtk_scrolled_window w/ viewport, but the vertical scrolling
+    * did not work well, and sometimes a few pixels were cut off on
+    * the bottom. */
+ 
+   bv_vscroll_left = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
+   gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll_left, 0, 1, 0, 1,
+     GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
+ 
+   bv_vscroll_right = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
+   gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll_right, 2, 3, 0, 1,
+     GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
+ 
+   *byte_view_p = byte_view;
+   *bv_vscroll_left_p = bv_vscroll_left;
+   *bv_vscroll_right_p = bv_vscroll_right;
+ }
+ 
+ void
  packet_hex_print(GtkText *bv, guint8 *pd, gint len, gint bstart, gint blen,
  		char_enc encoding) {
    gint     i = 0, j, k, cur;
***************
*** 159,164 ****
--- 206,238 ----
  
      gtk_adjustment_set_value(bv->vadj, scrollval);
    }
+ }
+ 
+ void
+ create_tree_view(gint tv_size, e_prefs *prefs, GtkWidget *pane,
+ 		GtkWidget **tv_scrollw_p, GtkWidget **tree_view_p)
+ {
+   GtkWidget *tv_scrollw, *tree_view;
+ 
+   /* Tree view */
+   tv_scrollw = gtk_scrolled_window_new(NULL, NULL);
+   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tv_scrollw),
+     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+   gtk_paned_pack1(GTK_PANED(pane), tv_scrollw, TRUE, TRUE);
+   gtk_widget_set_usize(tv_scrollw, -1, tv_size);
+   gtk_widget_show(tv_scrollw);
+   
+   tree_view = gtk_ctree_new(1, 0);
+   /* I need this next line to make the widget work correctly with hidden
+    * column titles and GTK_SELECTION_BROWSE */
+   gtk_clist_set_column_auto_resize( GTK_CLIST(tree_view), 0, TRUE );
+   gtk_container_add( GTK_CONTAINER(tv_scrollw), tree_view );
+   set_ptree_sel_browse(tree_view, prefs->gui_ptree_sel_browse);
+   set_ptree_line_style(tree_view, prefs->gui_ptree_line_style);
+   set_ptree_expander_style(tree_view, prefs->gui_ptree_expander_style);
+ 
+   *tree_view_p = tree_view;
+   *tv_scrollw_p = tv_scrollw;
  }
  
  void expand_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view) {
Index: gtk/proto_draw.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/proto_draw.h,v
retrieving revision 1.4
diff -c -r1.4 proto_draw.h
*** proto_draw.h	1999/11/22 06:24:56	1.4
--- proto_draw.h	2000/02/18 18:11:39
***************
*** 27,36 ****
--- 27,40 ----
  #ifndef __GTKPACKET_H__
  #define __GTKPACKET_H__
  
+ void create_byte_view(gint bv_size, GtkWidget *pane, GtkWidget **byte_view_p,
+ 		GtkWidget **bv_vscroll_left_p, GtkWidget **bv_vscroll_right_p);
  void packet_hex_print(GtkText *, guint8 *, gint, gint, gint, char_enc);
  
  #define E_TREEINFO_FIELD_INFO_KEY "tree_info_finfo"
  
+ void create_tree_view(gint tv_size, e_prefs *prefs, GtkWidget *pane,
+ 		GtkWidget **tv_scrollw_p, GtkWidget **tree_view_p);
  void proto_tree_draw(proto_tree *protocol_tree, GtkWidget *tree_view);
  void expand_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view);
  void collapse_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view);
/* packet_win.c
 * Routines for popping a window to display current packet
 *
 * Copyright 2000, Jeffrey C. Foster <jfoste@xxxxxxxxxxxx>
 *
 * $Id$
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * Copied from main.c
 * 
 * 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.
 *
 * To do:
 * - Add close button to bottom.
 * - improve the window Title and allow user to config it
 * - Add print support ? ( could be a mess)
 * - Add button to have main window jump to this packet ?
 *
 */


#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 "main.h"
#include "timestamp.h"
#include "packet.h"
#include "capture.h"
#include "summary.h"
#include "file.h"
#include "menu.h"
#include "../menu.h"
#include "prefs_dlg.h"
#include "column.h"
#include "print.h"
#include "resolv.h"
#include "follow.h"
#include "util.h"
#include "packet_win.h"
#include "simple_dialog.h"
#include "proto_draw.h"
#include "dfilter.h"
#include "keys.h"
#include "gtkglobals.h"
#include "plugins.h"

struct NewWinData {
	gint        cap_len;
	gint        encoding;
	guint8     *pd;		   /* Data for packet */
	proto_tree *protocol_tree; /* Protocol tree for packet */
	GtkWidget  *tv_scrollw;
	GtkWidget  *tree_view;
 	GtkWidget  *byte_view;
 	GtkWidget  *bv_vscroll_left;
 	GtkWidget  *bv_vscroll_right;
};

/* List of all the packet-detail windows popped up. */
static GList *detail_windows;

static void new_tree_view_select_row_cb( GtkCTree *ctree, GList *node,
	gint column, gpointer user_data);

static void new_tree_view_unselect_row_cb( GtkCTree *ctree, GList *node,
	gint column, gpointer user_data);

static void create_new_window( char *Title, gint tv_size, gint bv_size);
static void destroy_new_window(gpointer data);

static void set_scrollbar_placement_packet_win(struct NewWinData *DataPtr,
    int pos);

void new_window_cb(GtkWidget *w){

	#define NewWinTitleLen 1000
	
  	gint	tv_size = 95, bv_size = 75;
	int i;
	char Title[ NewWinTitleLen] = "";
	char *TextPtr;

					/* build title of window by getting */
					/* data from the packet_list GtkCList */
	for( i = 0; i < cf.cinfo.num_cols; ++i){
					
		if ( gtk_clist_get_text(GTK_CLIST( packet_list), 
				cf.current_frame->row, i, &TextPtr)){
		
			if (( strlen( Title) + strlen( TextPtr))
					< ( NewWinTitleLen - 1)){

				strcat( Title, TextPtr);
				strcat( Title, " ");
			}
		}		
	}	
	
	create_new_window ( Title, tv_size, bv_size);
}


static void
create_new_window ( char *Title, gint tv_size, gint bv_size){

  GtkWidget *main_w, *main_vbox, *pane,
                      *tree_view, *byte_view, *tv_scrollw,
                      *bv_vscroll_left, *bv_vscroll_right;
  struct NewWinData *DataPtr;
	
  main_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  gtk_window_set_title(GTK_WINDOW(main_w), Title);
  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);

  /* Byte view */
  create_byte_view(bv_size, pane, &byte_view, &bv_vscroll_left,
			&bv_vscroll_right);

  /* Allocate data structure to represent this window. */
  DataPtr = (struct NewWinData *) g_malloc(sizeof(struct NewWinData));

  DataPtr->cap_len = cf.current_frame->cap_len;
  DataPtr->encoding = cf.current_frame->encoding;
  DataPtr->pd = g_malloc(DataPtr->cap_len);
  memcpy(DataPtr->pd, cf.pd, DataPtr->cap_len);
  DataPtr->protocol_tree = proto_tree_create_root();
  dissect_packet(DataPtr->pd, cf.current_frame, DataPtr->protocol_tree);
  DataPtr->tv_scrollw = tv_scrollw;
  DataPtr->tree_view = tree_view;
  DataPtr->byte_view = byte_view;
  DataPtr->bv_vscroll_left = bv_vscroll_left;
  DataPtr->bv_vscroll_right = bv_vscroll_right;
  detail_windows = g_list_append(detail_windows, DataPtr);

  /* Now that the 2 panes are created, set the vertical scrollbar
   * on the left or right according to the user's preference */
  set_scrollbar_placement_packet_win(DataPtr, prefs.gui_scrollbar_on_right);

  /* load callback handlers */
  gtk_signal_connect(GTK_OBJECT(tree_view), "tree-select-row",
		GTK_SIGNAL_FUNC(new_tree_view_select_row_cb), DataPtr);

  /* This handler needs a destroy function */
  /* to remove the stored packet data	 */
  gtk_signal_connect_full(GTK_OBJECT(tree_view), "tree-unselect-row",
    		GTK_SIGNAL_FUNC(new_tree_view_unselect_row_cb), NULL, DataPtr,
    		&destroy_new_window, FALSE, FALSE);
    

  /* draw the protocol tree & print hex data */
  proto_tree_draw(DataPtr->protocol_tree, tree_view);
  packet_hex_print( GTK_TEXT(byte_view), DataPtr->pd,
		DataPtr->cap_len, -1, -1, DataPtr->encoding);
		
  gtk_widget_show(main_w);
}

static void
destroy_new_window(gpointer data)
{
  struct NewWinData *DataPtr = data;

  detail_windows = g_list_remove(detail_windows, DataPtr);
  proto_tree_free(DataPtr->protocol_tree);
  g_free(DataPtr->pd);
  g_free(DataPtr);
}

static void
new_tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column,
	gpointer user_data){
	
/* called when a tree row is selected in the popup packet window */	

	field_info	*finfo;

	struct NewWinData *DataPtr = (struct NewWinData*)user_data;

	g_assert(node);
	finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
	if (!finfo) return;

	finfo_selected = finfo;

	packet_hex_print(GTK_TEXT(DataPtr->byte_view), DataPtr->pd,
		DataPtr->cap_len, finfo->start, finfo->length,
		DataPtr->encoding);

}

static void
new_tree_view_unselect_row_cb(GtkCTree *ctree, GList *node, gint column,
	gpointer user_data){

/* called when a tree row is unselected in the popup packet window */	
	
	
	
	struct NewWinData *DataPtr = (struct NewWinData*)user_data;

	packet_hex_print(GTK_TEXT(DataPtr->byte_view), DataPtr->pd,
		DataPtr->cap_len, -1, -1, DataPtr->encoding);
}

/* Set the scrollbar position of a given popup packet window based upon
   pos value: 0 = left, 1 = right */
static void
set_scrollbar_placement_packet_win(struct NewWinData *DataPtr, int pos)
{
	set_scrollbar_placement_scrollw(DataPtr->tv_scrollw, pos);
	set_scrollbar_placement_textw(DataPtr->bv_vscroll_left,
	    DataPtr->bv_vscroll_right, pos);
}

static void
set_scrollbar_placement_cb(gpointer data, gpointer user_data)
{
	set_scrollbar_placement_packet_win((struct NewWinData *)data,
	    *(int *)user_data);
}

/* Set the scrollbar position of all the popup packet windows based upon
   pos value: 0 = left, 1 = right */
void
set_scrollbar_placement_packet_wins(int pos)
{
	g_list_foreach(detail_windows, set_scrollbar_placement_cb, &pos);
}

static void
set_ptree_sel_browse_cb(gpointer data, gpointer user_data)
{
	struct NewWinData *DataPtr = (struct NewWinData *)data;

	set_ptree_sel_browse(DataPtr->tree_view, *(gboolean *)user_data);
}

/* Set the selection mode of all the popup packet windows. */
void
set_ptree_sel_browse_packet_wins(gboolean val)
{
	g_list_foreach(detail_windows, set_ptree_sel_browse_cb, &val);
}

static void
set_ptree_line_style_cb(gpointer data, gpointer user_data)
{
	struct NewWinData *DataPtr = (struct NewWinData *)data;

	set_ptree_line_style(DataPtr->tree_view, *(gint *)user_data);
}

/* Set the selection mode of all the popup packet windows. */
void
set_ptree_line_style_packet_wins(gint style)
{
	g_list_foreach(detail_windows, set_ptree_line_style_cb, &style);
}

static void
set_ptree_expander_style_cb(gpointer data, gpointer user_data)
{
	struct NewWinData *DataPtr = (struct NewWinData *)data;

	set_ptree_expander_style(DataPtr->tree_view, *(gint *)user_data);
}

/* Set the selection mode of all the popup packet windows. */
void
set_ptree_expander_style_packet_wins(gint style)
{
	g_list_foreach(detail_windows, set_ptree_expander_style_cb, &style);
}
/* packet_win.h
 * Declarations for popping a window to display current packet
 *
 * Copyright 2000, Jeffrey C. Foster <jfoste@xxxxxxxxxxxx>
 *
 * $Id$
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxx>
 * 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.
 */

extern void new_window_cb(GtkWidget *w);
void set_scrollbar_placement_packet_wins(int pos);
void set_ptree_sel_browse_packet_wins(gboolean val);
void set_ptree_line_style_packet_wins(gint style);
void set_ptree_expander_style_packet_wins(gint style);