It was silly of me to require that "forget_scrolled_window()" be called
[obnox/wireshark/wip.git] / gtk / packet_win.c
1 /* packet_win.c
2  * Routines for popping a window to display current packet
3  *
4  * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
5  *
6  * $Id: packet_win.c,v 1.11 2000/08/17 07:56:42 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  * 
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.
16  * 
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.
21  * 
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.
25  *
26  * To do:
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 ?
31  *
32  */
33
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <gtk/gtk.h>
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48
49 #include "main.h"
50 #include "timestamp.h"
51 #include "packet.h"
52 #include "capture.h"
53 #include "summary.h"
54 #include "file.h"
55 #include "menu.h"
56 #include "../menu.h"
57 #include "prefs_dlg.h"
58 #include "column.h"
59 #include "print.h"
60 #include "resolv.h"
61 #include "util.h"
62 #include "packet_win.h"
63 #include "simple_dialog.h"
64 #include "ui_util.h"
65 #include "proto_draw.h"
66 #include "dfilter.h"
67 #include "keys.h"
68 #include "gtkglobals.h"
69 #include "plugins.h"
70
71 /* Data structure holding information about a packet-detail window. */
72 struct PacketWinData {
73         gint        cap_len;
74         gint        encoding;
75         union wtap_pseudo_header pseudo_header; /* Pseudo-header for packet */
76         guint8     *pd;            /* Data for packet */
77         proto_tree *protocol_tree; /* Protocol tree for packet */
78         GtkWidget  *main;
79         GtkWidget  *tv_scrollw;
80         GtkWidget  *tree_view;
81         GtkWidget  *bv_scrollw;
82         GtkWidget  *byte_view;
83 };
84
85 /* List of all the packet-detail windows popped up. */
86 static GList *detail_windows;
87
88 static void new_tree_view_select_row_cb( GtkCTree *ctree, GList *node,
89         gint column, gpointer user_data);
90
91 static void new_tree_view_unselect_row_cb( GtkCTree *ctree, GList *node,
92         gint column, gpointer user_data);
93
94 static void create_new_window( char *Title, gint tv_size, gint bv_size);
95 static void destroy_new_window(GtkObject *object, gpointer user_data);
96
97 void new_window_cb(GtkWidget *w){
98
99         #define NewWinTitleLen 1000
100         
101         int row;
102         gint    tv_size = 95, bv_size = 75;
103         int i;
104         char Title[ NewWinTitleLen] = "";
105         char *TextPtr;
106
107                                         /* build title of window by getting */
108                                         /* data from the packet_list GtkCList */
109         /* Find what row this packet is in. */
110         row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
111             cfile.current_frame);
112         g_assert(row != -1);
113         for( i = 0; i < cfile.cinfo.num_cols; ++i){
114                                         
115                 if ( gtk_clist_get_text(GTK_CLIST( packet_list), 
116                                 row, i, &TextPtr)){
117                 
118                         if (( strlen( Title) + strlen( TextPtr))
119                                         < ( NewWinTitleLen - 1)){
120
121                                 strcat( Title, TextPtr);
122                                 strcat( Title, " ");
123                         }
124                 }               
125         }       
126         
127         create_new_window ( Title, tv_size, bv_size);
128 }
129
130
131 static void
132 create_new_window ( char *Title, gint tv_size, gint bv_size){
133
134   GtkWidget *main_w, *main_vbox, *pane,
135                       *tree_view, *byte_view, *tv_scrollw,
136                       *bv_scrollw;
137   struct PacketWinData *DataPtr;
138         
139   main_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
140
141   gtk_window_set_title(GTK_WINDOW(main_w), Title);
142   gtk_window_set_default_size(GTK_WINDOW(main_w), DEF_WIDTH, -1);
143
144   /* Container for paned windows  */
145   main_vbox = gtk_vbox_new(FALSE, 1);
146   gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
147   gtk_container_add(GTK_CONTAINER(main_w), main_vbox);
148   gtk_widget_show(main_vbox);
149
150   /* Panes for the tree and byte view */
151   pane = gtk_vpaned_new();
152   gtk_paned_gutter_size(GTK_PANED(pane), (GTK_PANED(pane))->handle_size);
153   gtk_container_add(GTK_CONTAINER(main_vbox), pane);
154   gtk_widget_show(pane);
155
156   /* Tree view */
157   create_tree_view(tv_size, &prefs, pane, &tv_scrollw, &tree_view,
158                         prefs.gui_scrollbar_on_right);
159   gtk_widget_show(tree_view);
160
161   /* Byte view */
162   create_byte_view(bv_size, pane, &byte_view, &bv_scrollw,
163                         prefs.gui_scrollbar_on_right);
164
165   /* Allocate data structure to represent this window. */
166   DataPtr = (struct PacketWinData *) g_malloc(sizeof(struct PacketWinData));
167
168   DataPtr->cap_len = cfile.current_frame->cap_len;
169   DataPtr->encoding = cfile.current_frame->flags.encoding;
170   memcpy(&DataPtr->pseudo_header, &cfile.pseudo_header, sizeof DataPtr->pseudo_header);
171   DataPtr->pd = g_malloc(DataPtr->cap_len);
172   memcpy(DataPtr->pd, cfile.pd, DataPtr->cap_len);
173   DataPtr->protocol_tree = proto_tree_create_root();
174   proto_tree_is_visible = TRUE;
175   dissect_packet(&DataPtr->pseudo_header, DataPtr->pd, cfile.current_frame,
176                 DataPtr->protocol_tree);
177   proto_tree_is_visible = FALSE;
178   DataPtr->main = main_w;
179   DataPtr->tv_scrollw = tv_scrollw;
180   DataPtr->tree_view = tree_view;
181   DataPtr->byte_view = byte_view;
182   DataPtr->bv_scrollw = bv_scrollw;
183   detail_windows = g_list_append(detail_windows, DataPtr);
184
185   /* load callback handlers */
186   gtk_signal_connect(GTK_OBJECT(tree_view), "tree-select-row",
187                 GTK_SIGNAL_FUNC(new_tree_view_select_row_cb), DataPtr);
188
189   gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
190                 GTK_SIGNAL_FUNC(new_tree_view_unselect_row_cb), DataPtr);
191
192   gtk_signal_connect(GTK_OBJECT(main_w), "destroy",
193                         GTK_SIGNAL_FUNC(destroy_new_window), DataPtr);
194
195   /* draw the protocol tree & print hex data */
196   proto_tree_draw(DataPtr->protocol_tree, tree_view);
197   packet_hex_print( GTK_TEXT(byte_view), DataPtr->pd,
198                 DataPtr->cap_len, -1, -1, DataPtr->encoding);
199                 
200   gtk_widget_show(main_w);
201 }
202
203 static void
204 destroy_new_window(GtkObject *object, gpointer user_data)
205 {
206   struct PacketWinData *DataPtr = user_data;
207
208   detail_windows = g_list_remove(detail_windows, DataPtr);
209   proto_tree_free(DataPtr->protocol_tree);
210   g_free(DataPtr->pd);
211   g_free(DataPtr);
212 }
213
214 static void
215 new_tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column,
216         gpointer user_data){
217         
218 /* called when a tree row is selected in the popup packet window */     
219
220         field_info      *finfo;
221
222         struct PacketWinData *DataPtr = (struct PacketWinData*)user_data;
223
224         g_assert(node);
225         finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
226         if (!finfo) return;
227
228         finfo_selected = finfo;
229
230         packet_hex_print(GTK_TEXT(DataPtr->byte_view), DataPtr->pd,
231                 DataPtr->cap_len, finfo->start, finfo->length,
232                 DataPtr->encoding);
233
234 }
235
236 static void
237 new_tree_view_unselect_row_cb(GtkCTree *ctree, GList *node, gint column,
238         gpointer user_data){
239
240 /* called when a tree row is unselected in the popup packet window */   
241         
242         
243         
244         struct PacketWinData *DataPtr = (struct PacketWinData*)user_data;
245
246         packet_hex_print(GTK_TEXT(DataPtr->byte_view), DataPtr->pd,
247                 DataPtr->cap_len, -1, -1, DataPtr->encoding);
248 }
249
250 /* Functions called from elsewhere to act on all popup packet windows. */
251
252 /* Destroy all popup packet windows. */
253 void
254 destroy_packet_wins(void)
255 {
256         struct PacketWinData *DataPtr;
257
258         /* Destroying a packet window causes it to be removed from
259            the list of packet windows, so we can't do a "g_list_foreach()"
260            to go through the list of all packet windows and destroy them
261            as we find them; instead, as long as the list is non-empty,
262            we destroy the first window on the list. */
263         while (detail_windows != NULL) {
264                 DataPtr = (struct PacketWinData *)(detail_windows->data);
265                 gtk_widget_destroy(DataPtr->main);
266         }
267 }
268
269 static void
270 set_ptree_sel_browse_cb(gpointer data, gpointer user_data)
271 {
272         struct PacketWinData *DataPtr = (struct PacketWinData *)data;
273
274         set_ptree_sel_browse(DataPtr->tree_view, *(gboolean *)user_data);
275 }
276
277 /* Set the selection mode of all the popup packet windows. */
278 void
279 set_ptree_sel_browse_packet_wins(gboolean val)
280 {
281         g_list_foreach(detail_windows, set_ptree_sel_browse_cb, &val);
282 }
283
284 static void
285 set_ptree_line_style_cb(gpointer data, gpointer user_data)
286 {
287         struct PacketWinData *DataPtr = (struct PacketWinData *)data;
288
289         set_ptree_line_style(DataPtr->tree_view, *(gint *)user_data);
290 }
291
292 /* Set the selection mode of all the popup packet windows. */
293 void
294 set_ptree_line_style_packet_wins(gint style)
295 {
296         g_list_foreach(detail_windows, set_ptree_line_style_cb, &style);
297 }
298
299 static void
300 set_ptree_expander_style_cb(gpointer data, gpointer user_data)
301 {
302         struct PacketWinData *DataPtr = (struct PacketWinData *)data;
303
304         set_ptree_expander_style(DataPtr->tree_view, *(gint *)user_data);
305 }
306
307 /* Set the selection mode of all the popup packet windows. */
308 void
309 set_ptree_expander_style_packet_wins(gint style)
310 {
311         g_list_foreach(detail_windows, set_ptree_expander_style_cb, &style);
312 }