From 7c113340005e40b182076b765b675e8db7c85c4c Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Tue, 29 Feb 2000 06:24:41 +0000 Subject: [PATCH] Jeff Foster's changes, with my additions, to allow the user to pop up a window showing the protocol tree and hex/ASCII data for the currently selected packet. svn path=/trunk/; revision=1670 --- AUTHORS | 2 + doc/ethereal.pod.template | 11 ++ file.c | 7 +- gtk/Makefile.am | 4 +- gtk/Makefile.nmake | 3 +- gtk/gtkglobals.h | 15 +- gtk/gui_prefs.c | 22 +-- gtk/main.c | 172 +++++++++---------- gtk/menu.c | 6 +- gtk/packet_win.c | 339 ++++++++++++++++++++++++++++++++++++++ gtk/packet_win.h | 31 ++++ gtk/proto_draw.c | 76 ++++++++- gtk/proto_draw.h | 6 +- ui_util.h | 5 +- 14 files changed, 593 insertions(+), 106 deletions(-) create mode 100644 gtk/packet_win.c create mode 100644 gtk/packet_win.h diff --git a/AUTHORS b/AUTHORS index 08f587ef95..c9ad7eff93 100644 --- a/AUTHORS +++ b/AUTHORS @@ -60,6 +60,7 @@ Guy Harris { NNTP support ATM and LANE decoding Q.931 decoding + Changes to the popup packet windows Miscellaneous enhancements and fixes } @@ -141,6 +142,7 @@ Jeff Foster { NetBEUI/NBF support (NetBIOS atop 802.2 LLC, the original NetBIOS encapsulation) SMB Mailslot and Netlogin protocol support + Popup packet windows } Peter Torvals { diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template index 6c12e4f9b7..5e0bf17d4e 100644 --- a/doc/ethereal.pod.template +++ b/doc/ethereal.pod.template @@ -286,6 +286,17 @@ Collapses the protocol tree branches. Expands all branches of the protocol tree. +=item Display:Expand All + +Expands all branches of the protocol tree. + +=item Display:Show Packet In New Window + +Creates a new window containing a protocol tree view and a hex dump +window of the currently selected packet; this window will continue to +display that packet's protocol tree and data even if another packet is +selected. + =item Tools:Plugins Allows you to use and configure dynamically loadable modules (see diff --git a/file.c b/file.c index c7bb182c5f..d8321a3a07 100644 --- a/file.c +++ b/file.c @@ -1,7 +1,7 @@ /* file.c * File I/O routines * - * $Id: file.c,v 1.167 2000/02/21 08:18:00 guy Exp $ + * $Id: file.c,v 1.168 2000/02/29 06:24:15 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -77,6 +77,7 @@ #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" @@ -178,6 +179,10 @@ close_cap_file(capture_file *cf, void *w) { frame_data *fd, *fd_next; + /* Destroy all popup packet windows, as they refer to packets in the + capture file we're closing. */ + destroy_packet_wins(); + if (cf->fh) { file_close(cf->fh); cf->fh = NULL; diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 546225fd9a..2d8e214926 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for the GTK interface routines for Ethereal # -# $Id: Makefile.am,v 1.24 2000/02/12 08:31:45 guy Exp $ +# $Id: Makefile.am,v 1.25 2000/02/29 06:24:36 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs @@ -57,6 +57,8 @@ libui_a_SOURCES = \ main.h \ menu.c \ menu.h \ + packet_win.c \ + packet_win.h \ plugins_dlg.c \ prefs_dlg.c \ prefs_dlg.h \ diff --git a/gtk/Makefile.nmake b/gtk/Makefile.nmake index c331a04bd3..7848b23033 100644 --- a/gtk/Makefile.nmake +++ b/gtk/Makefile.nmake @@ -23,7 +23,8 @@ OBJECTS=capture_dlg.obj \ gui_prefs.obj \ main.obj \ menu.obj \ - plugins_dlg.obj \ + packet_win.obj \ + plugins_dlg.obj \ prefs_dlg.obj \ print_dlg.obj \ print_prefs.obj \ diff --git a/gtk/gtkglobals.h b/gtk/gtkglobals.h index 6643052338..59bb2f9c5b 100644 --- a/gtk/gtkglobals.h +++ b/gtk/gtkglobals.h @@ -1,7 +1,7 @@ /* gtkglobals.h * GTK-related Global defines, etc. * - * $Id: gtkglobals.h,v 1.5 1999/12/30 23:02:54 gram Exp $ + * $Id: gtkglobals.h,v 1.6 2000/02/29 06:24:36 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -36,10 +36,15 @@ extern GdkFont *m_r_font, *m_b_font; extern GtkStyle *item_style; -void set_scrollbar_placement(int); /* 1=right, 0=left */ +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(gboolean); -void set_ptree_line_style(gint style); -void set_ptree_expander_style(gint style); +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 diff --git a/gtk/gui_prefs.c b/gtk/gui_prefs.c index 089a065148..e3f6e32370 100644 --- a/gtk/gui_prefs.c +++ b/gtk/gui_prefs.c @@ -1,7 +1,7 @@ /* gui_prefs.c * Dialog box for GUI preferences * - * $Id: gui_prefs.c,v 1.3 1999/12/30 23:02:55 gram Exp $ + * $Id: gui_prefs.c,v 1.4 2000/02/29 06:24:37 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -241,7 +241,7 @@ scrollbar_menu_item_cb(GtkWidget *w, gpointer data) gboolean value = GPOINTER_TO_INT(data); temp_gui_scrollbar_on_right = value; - set_scrollbar_placement(value); + set_scrollbar_placement_all(value); } static void @@ -259,7 +259,7 @@ ptree_sel_browse_cb(GtkWidget *w, gpointer data) gboolean value = GPOINTER_TO_INT(data); temp_gui_ptree_sel_browse = value; - set_ptree_sel_browse(value); + set_ptree_sel_browse_all(value); } static void @@ -268,7 +268,7 @@ ptree_line_style_cb(GtkWidget *w, gpointer data) gint value = GPOINTER_TO_INT(data); temp_gui_ptree_line_style = value; - set_ptree_line_style(value); + set_ptree_line_style_all(value); } static void @@ -277,7 +277,7 @@ ptree_expander_style_cb(GtkWidget *w, gpointer data) gint value = GPOINTER_TO_INT(data); temp_gui_ptree_expander_style = value; - set_ptree_expander_style(value); + set_ptree_expander_style_all(value); } @@ -302,19 +302,19 @@ gui_prefs_save(GtkWidget *w) void gui_prefs_cancel(GtkWidget *w) { - /* Reset scrollbar placement value back to what the - * current preferences says it should be */ + /* 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(prefs.gui_scrollbar_on_right); + set_scrollbar_placement_all(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); + 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); } diff --git a/gtk/main.c b/gtk/main.c index 1238895329..391a85ecfa 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1,6 +1,6 @@ /* main.c * - * $Id: main.c,v 1.106 2000/02/20 14:52:27 deniel Exp $ + * $Id: main.c,v 1.107 2000/02/29 06:24:37 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -109,6 +109,7 @@ #include "proto_draw.h" #include "dfilter.h" #include "keys.h" +#include "packet_win.h" #include "gtkglobals.h" #include "plugins.h" @@ -138,6 +139,7 @@ static void follow_charset_toggle_cb(GtkWidget *w, gpointer parent_w); 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,19 +855,15 @@ static void 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); + finfo->start, finfo->length, cf.current_frame->encoding); } static void @@ -896,27 +894,55 @@ void resolve_name_cb(GtkWidget *widget, gpointer data) { } } +/* Set the scrollbar placement of a scrolled window based upon pos value: + 0 = left, 1 = right */ void -set_scrollbar_placement(int pos) /* 0=left, 1=right */ +set_scrollbar_placement_scrollw(GtkWidget *scrollw, 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); + 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) { @@ -933,41 +959,66 @@ set_plist_sel_browse(gboolean val) } } +/* Set the selection mode of a given packet tree window. */ void -set_ptree_sel_browse(gboolean val) +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(tree_view), GTK_SELECTION_SINGLE); + gtk_clist_set_selection_mode(GTK_CLIST(tv), GTK_SELECTION_SINGLE); } else { - gtk_clist_set_selection_mode(GTK_CLIST(tree_view), GTK_SELECTION_BROWSE); + gtk_clist_set_selection_mode(GTK_CLIST(tv), GTK_SELECTION_BROWSE); } } +/* Set the selection mode of all packet tree windows. */ void -set_ptree_line_style(gint style) +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(tree_view), style ); + gtk_ctree_set_line_style( GTK_CTREE(tv), style ); } +/* Set the line style of all packet tree window. */ void -set_ptree_expander_style(gint style) +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(tree_view), style ); + 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) @@ -1490,7 +1541,7 @@ static void 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, + *stat_hbox, *filter_bt, *filter_cm, *filter_te, *filter_reset; GList *filter_list = NULL; @@ -1526,10 +1577,10 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs) 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_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); @@ -1569,24 +1620,9 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs) 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); + /* 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", @@ -1599,43 +1635,13 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs) 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. */ + create_byte_view(bv_size, l_pane, &byte_view, &bv_vscroll_left, + &bv_vscroll_right); - 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); + set_scrollbar_placement_main_window(prefs->gui_scrollbar_on_right); /* Progress/filter/info box */ stat_hbox = gtk_hbox_new(FALSE, 1); diff --git a/gtk/menu.c b/gtk/menu.c index fc8b53acf2..2085b5ccb7 100644 --- a/gtk/menu.c +++ b/gtk/menu.c @@ -1,7 +1,7 @@ /* menu.c * Menu routines * - * $Id: menu.c,v 1.25 2000/02/20 14:52:28 deniel Exp $ + * $Id: menu.c,v 1.26 2000/02/29 06:24:39 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -51,6 +51,7 @@ #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,6 +121,7 @@ static GtkItemFactoryEntry menu_items[] = {"/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, "" }, #ifdef HAVE_PLUGINS {"/Tools/_Plugins...", NULL, GTK_MENU_FUNC(tools_plugins_cmd_cb), 0, NULL}, @@ -144,6 +146,7 @@ static GtkItemFactoryEntry packet_list_menu_items[] = {"/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[] = @@ -328,6 +331,7 @@ set_menus_for_selected_packet(gboolean have_selected_packet) 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); set_menu_sensitivity("/Resolve Name", diff --git a/gtk/packet_win.c b/gtk/packet_win.c new file mode 100644 index 0000000000..253b6d8268 --- /dev/null +++ b/gtk/packet_win.c @@ -0,0 +1,339 @@ +/* packet_win.c + * Routines for popping a window to display current packet + * + * Copyright 2000, Jeffrey C. Foster + * + * $Id: packet_win.c,v 1.1 2000/02/29 06:24:40 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#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 "ui_util.h" +#include "proto_draw.h" +#include "dfilter.h" +#include "keys.h" +#include "gtkglobals.h" +#include "plugins.h" + +/* Data structure holding information about a packet-detail window. */ +struct PacketWinData { + gint cap_len; + gint encoding; + guint8 *pd; /* Data for packet */ + proto_tree *protocol_tree; /* Protocol tree for packet */ + GtkWidget *main; + 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 PacketWinData *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 PacketWinData *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 PacketWinData *) g_malloc(sizeof(struct PacketWinData)); + + 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->main = main_w; + 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 PacketWinData *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 PacketWinData *DataPtr = (struct PacketWinData*)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 PacketWinData *DataPtr = (struct PacketWinData*)user_data; + + packet_hex_print(GTK_TEXT(DataPtr->byte_view), DataPtr->pd, + DataPtr->cap_len, -1, -1, DataPtr->encoding); +} + +/* Functions called from elsewhere to act on all popup packet windows. */ + +/* Destroy all popup packet windows. */ +void +destroy_packet_wins(void) +{ + struct PacketWinData *DataPtr; + + /* Destroying a packet window causes it to be removed from + the list of packet windows, so we can't do a "g_list_foreach()" + to go through the list of all packet windows and destroy them + as we find them; instead, as long as the list is non-empty, + we destroy the first window on the list. */ + while (detail_windows != NULL) { + DataPtr = (struct PacketWinData *)(detail_windows->data); + gtk_widget_destroy(DataPtr->main); + } +} + +/* 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 PacketWinData *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 PacketWinData *)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 PacketWinData *DataPtr = (struct PacketWinData *)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 PacketWinData *DataPtr = (struct PacketWinData *)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 PacketWinData *DataPtr = (struct PacketWinData *)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); +} diff --git a/gtk/packet_win.h b/gtk/packet_win.h new file mode 100644 index 0000000000..be2f4d3d84 --- /dev/null +++ b/gtk/packet_win.h @@ -0,0 +1,31 @@ +/* packet_win.h + * Declarations for popping a window to display current packet + * + * Copyright 2000, Jeffrey C. Foster + * + * $Id: packet_win.h,v 1.1 2000/02/29 06:24:40 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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); diff --git a/gtk/proto_draw.c b/gtk/proto_draw.c index 533aa3f567..1b2ef78c63 100644 --- a/gtk/proto_draw.c +++ b/gtk/proto_draw.c @@ -1,7 +1,7 @@ /* gtkpacket.c * Routines for GTK+ packet display * - * $Id: proto_draw.c,v 1.13 2000/01/25 03:45:45 gerald Exp $ + * $Id: proto_draw.c,v 1.14 2000/02/29 06:24:40 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -45,7 +45,9 @@ #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 @@ -55,6 +57,51 @@ extern GdkFont *m_r_font, *m_b_font; static void 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) { @@ -161,6 +208,33 @@ packet_hex_print(GtkText *bv, guint8 *pd, gint len, gint bstart, gint blen, } } +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) { int i; for(i=0; i < num_tree_types; i++) { diff --git a/gtk/proto_draw.h b/gtk/proto_draw.h index 2ffeef7329..dadcf9d81a 100644 --- a/gtk/proto_draw.h +++ b/gtk/proto_draw.h @@ -1,7 +1,7 @@ /* gtkpacket.h * Definitions for GTK+ packet display structures and routines * - * $Id: proto_draw.h,v 1.4 1999/11/22 06:24:56 gram Exp $ + * $Id: proto_draw.h,v 1.5 2000/02/29 06:24:41 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -27,10 +27,14 @@ #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); diff --git a/ui_util.h b/ui_util.h index 31d3731c8c..01c4957304 100644 --- a/ui_util.h +++ b/ui_util.h @@ -1,7 +1,7 @@ /* ui_util.h * Definitions for UI utility routines * - * $Id: ui_util.h,v 1.3 2000/01/03 06:59:10 guy Exp $ + * $Id: ui_util.h,v 1.4 2000/02/29 06:24:16 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -40,6 +40,9 @@ void set_main_window_name(gchar *); pop up the existing one rather than creating a new one. */ void reactivate_window(GtkWidget *); +/* Destroy all popup packet windows. */ +void destroy_packet_wins(void); + #ifdef __cplusplus } #endif /* __cplusplus */