2 * Routines for popping a window to display current packet
4 * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 * - Add close button to bottom.
28 * - improve the window Title and allow user to config it
29 * - Add print support ? ( could be a mess)
30 * - Add button to have main window jump to this packet ?
38 #ifdef HAVE_SYS_TYPES_H
39 #include <sys/types.h>
46 #include <epan/epan.h>
47 #include <epan/timestamp.h>
48 #include <epan/packet.h>
49 #include <epan/prefs.h>
50 #include <epan/column.h>
51 #include <epan/addr_resolv.h>
52 #include <epan/plugins.h>
53 #include <epan/epan_dissect.h>
54 #include <epan/strutil.h>
58 #include "../ui_util.h"
59 #include "../summary.h"
62 #include "gtk/packet_win.h"
63 #include "gtk/main_proto_draw.h"
65 #include "gtk/gtkglobals.h"
66 #include "gtk/gui_utils.h"
69 /* Data structure holding information about a packet-detail window. */
70 struct PacketWinData {
71 frame_data *frame; /* The frame being displayed */
72 union wtap_pseudo_header pseudo_header; /* Pseudo-header for packet */
73 guint8 *pd; /* Data for packet */
75 GtkWidget *tv_scrollw;
78 field_info *finfo_selected;
82 /* List of all the packet-detail windows popped up. */
83 static GList *detail_windows;
85 static void new_tree_view_selection_changed_cb(GtkTreeSelection *sel,
89 static void destroy_new_window(GtkObject *object, gpointer user_data);
92 button_press_handler(GtkWidget *widget, GdkEvent *event, gpointer data _U_)
94 if (widget == NULL || event == NULL) {
98 tree_view_select(widget, (GdkEventButton *) event);
100 /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
101 if (event->type == GDK_2BUTTON_PRESS) {
104 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
105 (gint) (((GdkEventButton *)event)->x),
106 (gint) (((GdkEventButton *)event)->y),
107 &path, NULL, NULL, NULL))
109 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path)) {
110 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
112 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path, FALSE);
114 gtk_tree_path_free(path);
121 void new_window_cb(GtkWidget *w _U_)
123 #define NewWinTitleLen 1000
124 char Title[NewWinTitleLen] = "";
126 gint tv_size = 95, bv_size = 75;
127 GtkWidget *main_w, *main_vbox, *pane,
128 *tree_view, *tv_scrollw,
130 struct PacketWinData *DataPtr;
133 if (!cfile.current_frame) {
134 /* nothing has been captured so far */
138 #ifdef NEW_PACKET_LIST
140 /* With the new packetlists "lazy columns" it's neccesary to reread the frame */
141 if (!cf_read_frame(&cfile, cfile.current_frame)) {
142 /* error reading the frame */
147 /* Allocate data structure to represent this window. */
148 DataPtr = (struct PacketWinData *) g_malloc(sizeof(struct PacketWinData));
150 DataPtr->frame = cfile.current_frame;
151 memcpy(&DataPtr->pseudo_header, &cfile.pseudo_header, sizeof DataPtr->pseudo_header);
152 DataPtr->pd = g_malloc(DataPtr->frame->cap_len);
153 memcpy(DataPtr->pd, cfile.pd, DataPtr->frame->cap_len);
154 DataPtr->edt = epan_dissect_new(TRUE, TRUE);
155 epan_dissect_run(DataPtr->edt, &DataPtr->pseudo_header, DataPtr->pd,
156 DataPtr->frame, &cfile.cinfo);
157 epan_dissect_fill_in_columns(DataPtr->edt, FALSE, TRUE);
160 * Build title of window by getting column data constructed when the
161 * frame was dissected.
163 for (i = 0; i < cfile.cinfo.num_cols; ++i) {
164 TextPtr = cfile.cinfo.col_data[i];
165 if ((strlen(Title) + strlen(TextPtr)) < NewWinTitleLen - 1) {
166 g_strlcat(Title, TextPtr, NewWinTitleLen);
167 g_strlcat(Title, " ", NewWinTitleLen);
171 main_w = window_new(GTK_WINDOW_TOPLEVEL, Title);
172 gtk_window_set_default_size(GTK_WINDOW(main_w), DEF_WIDTH, -1);
174 /* Container for paned windows */
175 main_vbox = gtk_vbox_new(FALSE, 1);
176 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
177 gtk_container_add(GTK_CONTAINER(main_w), main_vbox);
178 gtk_widget_show(main_vbox);
180 /* Panes for the tree and byte view */
181 pane = gtk_vpaned_new();
182 gtk_container_add(GTK_CONTAINER(main_vbox), pane);
183 gtk_widget_show(pane);
186 tv_scrollw = main_tree_view_new(&prefs, &tree_view);
187 gtk_paned_pack1(GTK_PANED(pane), tv_scrollw, TRUE, TRUE);
188 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
189 gtk_widget_show(tv_scrollw);
190 gtk_widget_show(tree_view);
193 bv_nb_ptr = byte_view_new();
194 gtk_paned_pack2(GTK_PANED(pane), bv_nb_ptr, FALSE, FALSE);
195 gtk_widget_set_size_request(bv_nb_ptr, -1, bv_size);
196 gtk_widget_show(bv_nb_ptr);
198 DataPtr->main = main_w;
199 DataPtr->tv_scrollw = tv_scrollw;
200 DataPtr->tree_view = tree_view;
201 DataPtr->bv_nb_ptr = bv_nb_ptr;
202 detail_windows = g_list_append(detail_windows, DataPtr);
204 /* load callback handlers */
205 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
206 "changed", G_CALLBACK(new_tree_view_selection_changed_cb), DataPtr);
207 g_signal_connect(tree_view, "button_press_event", G_CALLBACK(button_press_handler), NULL);
208 g_signal_connect(main_w, "destroy", G_CALLBACK(destroy_new_window), DataPtr);
210 /* draw the protocol tree & print hex data */
211 add_byte_views(DataPtr->edt, tree_view, DataPtr->bv_nb_ptr);
212 proto_tree_draw(DataPtr->edt->tree, tree_view);
214 DataPtr->finfo_selected = NULL;
215 gtk_widget_show(main_w);
219 destroy_new_window(GtkObject *object _U_, gpointer user_data)
221 struct PacketWinData *DataPtr = user_data;
223 detail_windows = g_list_remove(detail_windows, DataPtr);
224 epan_dissect_free(DataPtr->edt);
229 /* called when a tree row is (un)selected in the popup packet window */
231 new_tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data)
234 GtkWidget *byte_view;
240 struct PacketWinData *DataPtr = (struct PacketWinData*)user_data;
242 /* if something is selected */
243 if (gtk_tree_selection_get_selected(sel, &model, &iter))
245 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
248 set_notebook_page(DataPtr->bv_nb_ptr, finfo->ds_tvb);
249 byte_view = get_notebook_bv_ptr(DataPtr->bv_nb_ptr);
250 if (!byte_view) /* exit if no hex window to write in */
253 data = get_byte_view_data_and_length(byte_view, &len);
256 len = DataPtr->frame->cap_len;
259 DataPtr->finfo_selected = finfo;
260 packet_hex_print(byte_view, data, DataPtr->frame, finfo, len);
264 DataPtr->finfo_selected = NULL;
266 byte_view = get_notebook_bv_ptr(DataPtr->bv_nb_ptr);
267 if (!byte_view) /* exit if no hex window to write in */
270 data = get_byte_view_data_and_length(byte_view, &len);
271 g_assert(data != NULL);
272 packet_hex_reprint(byte_view);
276 /* Functions called from elsewhere to act on all popup packet windows. */
278 /* Destroy all popup packet windows. */
280 destroy_packet_wins(void)
282 struct PacketWinData *DataPtr;
284 /* Destroying a packet window causes it to be removed from
285 the list of packet windows, so we can't do a "g_list_foreach()"
286 to go through the list of all packet windows and destroy them
287 as we find them; instead, as long as the list is non-empty,
288 we destroy the first window on the list. */
289 while (detail_windows != NULL) {
290 DataPtr = (struct PacketWinData *)(detail_windows->data);
291 window_destroy(DataPtr->main);
296 redraw_packet_bytes_cb(gpointer data, gpointer user_data _U_)
298 struct PacketWinData *DataPtr = (struct PacketWinData *)data;
300 redraw_packet_bytes(DataPtr->bv_nb_ptr, DataPtr->frame, DataPtr->finfo_selected);
303 /* Redraw the packet bytes part of all the popup packet windows. */
305 redraw_packet_bytes_packet_wins(void)
307 g_list_foreach(detail_windows, redraw_packet_bytes_cb, NULL);