Calculate the height and width of m_r_font globally, since various

routines need it.

When a user clicks on a hex digit or on the corresponding character
(the "text dump" portion) in the hex dump, find the field in the
proto_tree that the byte corresponds to, expand the GtkCTree so that
the field is viewable, select the field, and center it vertically.
LanAlyzer has this feature, and I've missed it in Ethereal.

svn path=/trunk/; revision=3096
This commit is contained in:
Gilbert Ramirez 2001-03-02 23:10:12 +00:00
parent 22e8d3d18f
commit 540f564993
8 changed files with 260 additions and 47 deletions

View File

@ -1,7 +1,7 @@
/* proto.c
* Routines for protocol tree
*
* $Id: proto.c,v 1.11 2001/03/01 20:24:05 gram Exp $
* $Id: proto.c,v 1.12 2001/03/02 23:10:11 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -2586,6 +2586,56 @@ proto_get_finfo_ptr_array(proto_tree *tree, int id)
return sinfo.result.ptr_array;
}
typedef struct {
guint offset;
field_info *finfo;
} offset_search_t;
static gboolean
check_for_offset(GNode *node, gpointer data)
{
field_info *fi = node->data;
offset_search_t *offsearch = data;
/* !fi == the top most container node which holds nothing */
if (fi && fi->visible) {
if (offsearch->offset >= fi->start &&
offsearch->offset <= (fi->start + fi->length)) {
offsearch->finfo = fi;
return FALSE; /* keep traversing */
}
}
return FALSE; /* keep traversing */
}
/* Search a proto_tree backwards (from leaves to root) looking for the field
* whose start/length occupies 'offset' */
/* XXX - I couldn't find an easy way to search backwards, so I search
* forwards, w/o stopping. Therefore, the last finfo I find will the be
* the one I want to return to the user. This algorithm is inefficient
* and could be re-done, but I'd have to handle all the children and
* siblings of each node myself. When I have more time I'll do that.
* (yeah right) */
field_info*
proto_find_field_from_offset(proto_tree *tree, guint offset)
{
offset_search_t offsearch;
offsearch.offset = offset;
offsearch.finfo = NULL;
g_node_traverse((GNode*)tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
check_for_offset, &offsearch);
return offsearch.finfo;
}
/* Dumps the contents of the registration database to stdout. An indepedent program can take

View File

@ -1,7 +1,7 @@
/* proto.h
* Definitions for protocol display
*
* $Id: proto.h,v 1.7 2001/02/13 18:34:49 guy Exp $
* $Id: proto.h,v 1.8 2001/03/02 23:10:11 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -557,4 +557,7 @@ hfinfo_bitwidth(header_field_info *hfinfo);
char*
proto_alloc_dfilter_string(field_info *finfo, guint8 *pd);
field_info*
proto_find_field_from_offset(proto_tree *tree, guint offset);
#endif /* proto.h */

View File

@ -1,7 +1,7 @@
/* gtkglobals.h
* GTK-related Global defines, etc.
*
* $Id: gtkglobals.h,v 1.11 2000/08/21 08:09:11 guy Exp $
* $Id: gtkglobals.h,v 1.12 2001/03/02 23:10:12 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -33,9 +33,9 @@
extern GtkWidget *top_level, *packet_list, *tree_view,
*byte_view, *info_bar;
extern GdkFont *m_r_font, *m_b_font;
extern guint m_font_height, m_font_width;
extern GtkStyle *item_style;
void set_scrollbar_placement_scrollw(GtkWidget *, int); /* 0=left, 1=right */
void set_scrollbar_placement_all(int); /* 1=right, 0=left */
void remember_scrolled_window(GtkWidget *);

View File

@ -1,7 +1,7 @@
/* gui_prefs.c
* Dialog box for GUI preferences
*
* $Id: gui_prefs.c,v 1.24 2000/11/21 23:54:09 guy Exp $
* $Id: gui_prefs.c,v 1.25 2001/03/02 23:10:12 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -455,8 +455,7 @@ gui_prefs_apply(GtkWidget *w)
set_ptree_font_all(new_r_font);
old_r_font = m_r_font;
old_b_font = m_b_font;
m_r_font = new_r_font;
m_b_font = new_b_font;
set_fonts(new_r_font, new_b_font);
g_free(bold_font_name);
}

View File

@ -1,6 +1,6 @@
/* help_dlg.c
*
* $Id: help_dlg.c,v 1.14 2001/02/01 22:28:58 guy Exp $
* $Id: help_dlg.c,v 1.15 2001/03/02 23:10:12 gram Exp $
*
* Laurent Deniel <deniel@worldnet.fr>
*
@ -345,7 +345,7 @@ static void set_help_text(GtkWidget *w, help_type_t type)
}
}
height = (2 + nb_lines) * (m_r_font->ascent + m_r_font->descent);
height = (2 + nb_lines) * m_font_height;
gtk_widget_set_usize(GTK_WIDGET(w), 20 + width, 20 + height);
break;
@ -394,7 +394,7 @@ static void set_help_text(GtkWidget *w, help_type_t type)
nb_lines ++;
}
height = (1 + nb_lines) * (m_r_font->ascent + m_r_font->descent);
height = (1 + nb_lines) * m_font_height;
gtk_widget_set_usize(GTK_WIDGET(w), 20 + width, 20 + height);
}

View File

@ -1,6 +1,6 @@
/* main.c
*
* $Id: main.c,v 1.181 2001/03/02 17:44:07 gram Exp $
* $Id: main.c,v 1.182 2001/03/02 23:10:12 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -139,6 +139,7 @@ GtkWidget *top_level, *packet_list, *tree_view, *byte_view,
*info_bar, *tv_scrollw, *pkt_scrollw;
static GtkWidget *bv_scrollw;
GdkFont *m_r_font, *m_b_font;
guint m_font_height, m_font_width;
guint main_ctx, file_ctx, help_ctx;
gchar comp_info_str[256];
gchar *ethereal_path = NULL;
@ -177,6 +178,19 @@ about_ethereal( GtkWidget *w, gpointer data ) {
comp_info_str);
}
void
set_fonts(GdkFont *regular, GdkFont *bold)
{
/* Yes, assert. The code that loads the font should check
* for NULL and provide its own error message. */
g_assert(m_r_font && m_b_font);
m_r_font = regular;
m_b_font = bold;
m_font_height = m_r_font->ascent + m_r_font->descent;
m_font_width = gdk_string_width(m_r_font, "0");
}
/* Match selected byte pattern */
void
@ -1162,6 +1176,9 @@ main(int argc, char *argv[])
prefs->gui_font_name = g_strdup("6x13");
}
/* Call this for the side-effects that set_fonts() produces */
set_fonts(m_r_font, m_b_font);
#ifdef HAVE_LIBPCAP
/* Is this a "child" ethereal, which is only supposed to pop up a
@ -1453,6 +1470,7 @@ boldify(const char *font_name)
return bold_font_name;
}
static void
create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
{
@ -1560,9 +1578,6 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
/* Byte view. */
create_byte_view(bv_size, l_pane, &byte_view, &bv_scrollw,
prefs->gui_scrollbar_on_right);
gtk_signal_connect(GTK_OBJECT(byte_view), "button_press_event",
GTK_SIGNAL_FUNC(popup_menu_handler),
gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_HEXDUMP_KEY));
/* Filter/info box */
stat_hbox = gtk_hbox_new(FALSE, 1);
@ -1615,3 +1630,5 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
gtk_widget_show(top_level);
}

View File

@ -1,7 +1,7 @@
/* main.h
* Global defines, etc.
*
* $Id: main.h,v 1.20 2000/09/08 10:59:17 guy Exp $
* $Id: main.h,v 1.21 2001/03/02 23:10:12 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -64,5 +64,6 @@ void unmark_all_frames_cb(GtkWidget *w, gpointer);
void update_marked_frames(void);
char *boldify(const char *);
void set_fonts(GdkFont *regular, GdkFont *bold);
#endif /* __MAIN_H__ */

View File

@ -1,7 +1,7 @@
/* proto_draw.c
* Routines for GTK+ packet display
*
* $Id: proto_draw.c,v 1.26 2001/02/01 20:36:01 gram Exp $
* $Id: proto_draw.c,v 1.27 2001/03/02 23:10:12 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -44,6 +44,8 @@
#include "main.h"
#include "packet.h"
#include "util.h"
#include "menu.h"
#include "keys.h"
#include "colors.h"
#include "prefs.h"
@ -72,6 +74,163 @@ redraw_hex_dump_all(void)
redraw_hex_dump_packet_wins();
}
static void
expand_tree(GtkCTree *ctree, GtkCTreeNode *node, gpointer user_data)
{
field_info *finfo;
gboolean *val;
finfo = gtk_ctree_node_get_row_data( ctree, node );
g_assert(finfo);
val = &tree_is_expanded[finfo->tree_type];
*val = TRUE;
}
static void
collapse_tree(GtkCTree *ctree, GtkCTreeNode *node, gpointer user_data)
{
field_info *finfo;
gboolean *val;
finfo = gtk_ctree_node_get_row_data( ctree, node );
g_assert(finfo);
val = &tree_is_expanded[finfo->tree_type];
*val = FALSE;
}
/* Which byte the offset is referring to. Associates
* whitespace with the preceding digits. */
static int
byte_num(int offset, int start_point)
{
return (offset - start_point) / 3;
}
/* If the user selected a certain byte in the byte view, try to find
* the item in the GUI proto_tree that corresponds to that byte, and
* select it. */
static gint
byte_view_select(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
GtkCTree *ctree = GTK_CTREE(tree_view);
GtkCTreeNode *node, *parent;
field_info *finfo;
GtkText *bv = GTK_TEXT(widget);
int row, column;
int byte;
/* The column of the first hex digit in the first half */
const int digits_start_1 = 6;
/* The column of the last hex digit in the first half. */
const int digits_end_1 = 28;
/* The column of the first hex digit in the second half */
const int digits_start_2 = 31;
/* The column of the last hex digit in the second half. */
const int digits_end_2 = 53;
/* The column of the first "text dump" character. */
const int text_start = 57;
/* The column of the last "text dump" character. */
const int text_end = 73;
/* Given the mouse (x,y) and the current GtkText (h,v)
* adjustments, and the size of the font, figure out
* which text column/row the user selected. This could be off
* if the bold version of the font is bigger than the
* regular version of the font. */
column = (bv->hadj->value + event->x) / m_font_width;
row = (bv->vadj->value + event->y) / m_font_height;
/* Given the column and row, determine which byte offset
* the user clicked on. */
if (column >= digits_start_1 && column <= digits_end_1) {
byte = byte_num(column, digits_start_1);
if (byte == -1) {
return FALSE;
}
}
else if (column >= digits_start_2 && column <= digits_end_2) {
byte = byte_num(column, digits_start_2);
if (byte == -1) {
return FALSE;
}
byte += 8;
}
else if (column >= text_start && column <= text_end) {
byte = column - text_start;
}
else {
/* The user didn't select a hex digit or
* text-dump character. */
return FALSE;
}
/* Add the number of bytes from the previous rows. */
byte += row * 16;
/* Find the finfo that corresponds to our byte. */
finfo = proto_find_field_from_offset(cfile.protocol_tree, byte);
if (!finfo) {
return FALSE;
}
node = gtk_ctree_find_by_row_data(ctree, NULL, finfo);
g_assert(node);
/* Expand and select our field's row */
gtk_ctree_expand(ctree, node);
gtk_ctree_select(ctree, node);
expand_tree(ctree, node, NULL);
/* ... and its parents */
parent = GTK_CTREE_ROW(node)->parent;
while (parent) {
gtk_ctree_expand(ctree, parent);
expand_tree(ctree, parent, NULL);
parent = GTK_CTREE_ROW(parent)->parent;
}
/* And position the window so the selection is visible.
* Position the selection in the middle of the viewable
* pane. */
gtk_ctree_node_moveto(ctree, node, 0, .5, 0);
return FALSE;
}
/* Calls functions for different mouse-button presses. */
static gint
byte_view_button_press_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
{
GdkEventButton *event_button = NULL;
if(widget == NULL || event == NULL || data == NULL) {
return FALSE;
}
if(event->type == GDK_BUTTON_PRESS) {
event_button = (GdkEventButton *) event;
switch(event_button->button) {
case 1:
return byte_view_select(widget, event_button, data);
case 3:
return popup_menu_handler(widget, event, data);
default:
return FALSE;
}
}
return FALSE;
}
void
create_byte_view(gint bv_size, GtkWidget *pane, GtkWidget **byte_view_p,
GtkWidget **bv_scrollw_p, int pos)
@ -82,9 +241,14 @@ create_byte_view(gint bv_size, GtkWidget *pane, GtkWidget **byte_view_p,
byte_scrollw = gtk_scrolled_window_new(NULL, NULL);
gtk_paned_pack2(GTK_PANED(pane), byte_scrollw, FALSE, FALSE);
gtk_widget_set_usize(byte_scrollw, -1, bv_size);
/* The horizontal scrollbar of the scroll-window doesn't seem
* to affect the GtkText widget at all, even when line wrapping
* is turned off in the GtkText widget and there is indeed more
* horizontal data. */
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(byte_scrollw),
GTK_POLICY_NEVER,
GTK_POLICY_ALWAYS);
/* Horizontal */GTK_POLICY_NEVER,
/* Vertical*/ GTK_POLICY_ALWAYS);
set_scrollbar_placement_scrollw(byte_scrollw, pos);
remember_scrolled_window(byte_scrollw);
gtk_widget_show(byte_scrollw);
@ -92,8 +256,13 @@ create_byte_view(gint bv_size, GtkWidget *pane, GtkWidget **byte_view_p,
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_text_set_line_wrap(GTK_TEXT(byte_view), FALSE);
gtk_container_add(GTK_CONTAINER(byte_scrollw), byte_view);
gtk_widget_show(byte_view);
gtk_signal_connect(GTK_OBJECT(byte_view), "button_press_event",
GTK_SIGNAL_FUNC(byte_view_button_press_cb),
gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_HEXDUMP_KEY));
*byte_view_p = byte_view;
*bv_scrollw_p = byte_scrollw;
@ -311,13 +480,12 @@ packet_hex_print(GtkText *bv, guint8 *pd, frame_data *fd, field_info *finfo)
/* scroll text into position */
gtk_text_thaw(bv); /* must thaw before adjusting scroll bars */
if ( bstart > 0 ) {
int lineheight, linenum;
int linenum;
float scrollval;
linenum = bstart / BYTE_VIEW_WIDTH;
/* This is the lineheight that the GtkText widget uses when drawing text. */
lineheight = m_b_font->ascent + m_b_font->descent;
scrollval = MIN(linenum * lineheight,bv->vadj->upper - bv->vadj->page_size);
scrollval = MIN(linenum * m_font_height,
bv->vadj->upper - bv->vadj->page_size);
gtk_adjustment_set_value(bv->vadj, scrollval);
}
@ -500,31 +668,6 @@ void collapse_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view) {
proto_tree_draw(protocol_tree, tree_view);
}
static void
expand_tree(GtkCTree *ctree, GList *node, gpointer user_data)
{
field_info *finfo;
gboolean *val;
finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
g_assert(finfo);
val = &tree_is_expanded[finfo->tree_type];
*val = TRUE;
}
static void
collapse_tree(GtkCTree *ctree, GList *node, gpointer user_data)
{
field_info *finfo;
gboolean *val;
finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
g_assert(finfo);
val = &tree_is_expanded[finfo->tree_type];
*val = FALSE;
}
struct proto_tree_draw_info {
GtkCTree *ctree;