- fix a segmentation violation with big "match selected" filters.
[obnox/wireshark/wip.git] / gtk / proto_draw.c
1 /* gtkpacket.c
2  * Routines for GTK+ packet display
3  *
4  * $Id: proto_draw.c,v 1.3 1999/09/12 20:23:43 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <ctype.h>
35 #include <stdarg.h>
36
37 #include <gtk/gtk.h>
38
39 #ifdef NEED_SNPRINTF_H
40 # include "snprintf.h"
41 #endif
42
43 #include <stdio.h>
44 #include "main.h"
45 #include "packet.h"
46
47 #include "proto_draw.h"
48
49 #define BYTE_VIEW_WIDTH    16
50 #define BYTE_VIEW_SEP      8
51
52 extern GtkWidget    *byte_view;
53 extern GdkFont      *m_r_font, *m_b_font;
54
55 static void
56 proto_tree_draw_node(GNode *node, gpointer data);
57
58 void
59 packet_hex_print(GtkText *bv, guint8 *pd, gint len, gint bstart, gint blen) {
60   gint     i = 0, j, k, cur;
61   gchar    line[128], hexchars[] = "0123456789abcdef";
62   GdkFont *cur_font, *new_font;
63   
64   while (i < len) {
65     /* Print the line number */
66     sprintf(line, "%04x  ", i);
67     gtk_text_insert(bv, m_r_font, NULL, NULL, line, -1);
68     /* Do we start in bold? */
69     cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
70     j   = i;
71     k   = i + BYTE_VIEW_WIDTH;
72     cur = 0;
73     /* Print the hex bit */
74     while (i < k) {
75       if (i < len) {
76         line[cur++] = hexchars[(pd[i] & 0xf0) >> 4];
77         line[cur++] = hexchars[pd[i] & 0x0f];
78       } else {
79         line[cur++] = ' '; line[cur++] = ' ';
80       }
81       line[cur++] = ' ';
82       i++;
83       /* insert a space every BYTE_VIEW_SEP bytes */
84       if( ( i % BYTE_VIEW_SEP ) == 0 ) line[cur++] = ' ';
85       /* Did we cross a bold/plain boundary? */
86       new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
87       if (cur_font != new_font) {
88         gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
89         cur_font = new_font;
90         cur = 0;
91       }
92     }
93     line[cur++] = ' ';
94     gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
95     cur = 0;
96     i = j;
97     /* Print the ASCII bit */
98     cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
99     while (i < k) {
100       if (i < len) {
101         line[cur++] = (isgraph(pd[i])) ? pd[i] : '.';
102       } else {
103         line[cur++] = ' ';
104       }
105       i++;
106       /* insert a space every BYTE_VIEW_SEP bytes */
107       if( ( i % BYTE_VIEW_SEP ) == 0 ) line[cur++] = ' ';
108       /* Did we cross a bold/plain boundary? */
109       new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
110       if (cur_font != new_font) {
111         gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
112         cur_font = new_font;
113         cur = 0;
114       }
115     }
116     line[cur++] = '\n';
117     line[cur]   = '\0';
118     gtk_text_insert(bv, cur_font, NULL, NULL, line, -1);
119   }
120 }
121
122 void expand_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view) {
123   int i;
124   for(i=0; i < NUM_TREE_TYPES; i++) {
125     tree_is_expanded[i] = TRUE;
126   }
127   gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
128   proto_tree_draw(protocol_tree, tree_view);
129 }
130
131 void collapse_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view) {
132   int i;
133   for(i=0; i < NUM_TREE_TYPES; i++) {
134     tree_is_expanded[i] = FALSE;
135   }
136   gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
137   proto_tree_draw(protocol_tree, tree_view);
138 }
139
140 static void
141 expand_tree(GtkWidget *w, gpointer data) {
142   gboolean *val = (gint *) data;
143   *val = TRUE;
144 }
145
146 static void
147 collapse_tree(GtkWidget *w, gpointer data) {
148   gboolean *val = (gint *) data;
149   *val = FALSE;
150 }
151
152 static void
153 set_item_style(GtkWidget *widget, gpointer dummy)
154 {
155   gtk_widget_set_style(widget, item_style);
156 }
157
158 void
159 proto_tree_draw(proto_tree *protocol_tree, GtkWidget *tree_view)
160 {
161         g_node_children_foreach((GNode*) protocol_tree, G_TRAVERSE_ALL,
162                 proto_tree_draw_node, tree_view);
163 }
164
165 static void
166 proto_tree_draw_node(GNode *node, gpointer data)
167 {
168         GtkWidget       *tree_view = (GtkWidget*) data;
169         field_info      *fi = (field_info*) (node->data);
170         GtkWidget       *ti, *subtree;
171         gchar           label_str[ITEM_LABEL_LENGTH];
172         gchar           *label_ptr;
173
174         if (!fi->visible)
175                 return;
176
177         /* was a free format label produced? */
178         if (fi->representation) {
179                 label_ptr = fi->representation;
180         }
181         else { /* no, make a generic label */
182                 label_ptr = label_str;
183                 proto_item_fill_label(fi, label_str);
184         }
185                 
186         ti = gtk_tree_item_new_with_label(label_ptr);
187         gtk_container_foreach(GTK_CONTAINER(ti), set_item_style, NULL);
188         gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_START_KEY, (gpointer) fi->start);
189         gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_LEN_KEY, (gpointer) fi->length);
190         gtk_tree_append(GTK_TREE(tree_view), ti);
191         gtk_widget_show(ti);
192
193         if (g_node_n_children(node) > 0) {
194                 subtree = gtk_tree_new();
195                 gtk_tree_item_set_subtree(GTK_TREE_ITEM(ti), GTK_WIDGET(subtree));
196                 if (tree_is_expanded[fi->tree_type])
197                         gtk_tree_item_expand(GTK_TREE_ITEM(ti));
198                 gtk_signal_connect(GTK_OBJECT(ti), "expand", (GtkSignalFunc) expand_tree,
199                         (gpointer) &tree_is_expanded[fi->tree_type]);
200                 gtk_signal_connect(GTK_OBJECT(ti), "collapse", (GtkSignalFunc) collapse_tree,
201                         (gpointer) &tree_is_expanded[fi->tree_type]);
202
203                 g_node_children_foreach(node, G_TRAVERSE_ALL,
204                         proto_tree_draw_node, subtree);
205         }
206 }