2012-06-16 20:59:12 +00:00
|
|
|
/* packet_panes.c
|
2012-06-16 21:30:24 +00:00
|
|
|
* Routines for GTK+ packet display (packet details and hex dump panes)
|
1999-03-23 03:14:46 +00:00
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
1999-03-23 03:14:46 +00:00
|
|
|
*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
1999-03-23 03:14:46 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2001-03-23 14:44:04 +00:00
|
|
|
* Jeff Foster, 2001/03/12, added support for displaying named
|
2010-10-12 17:39:44 +00:00
|
|
|
* data sources as tabbed hex windows
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1999-03-23 03:14:46 +00:00
|
|
|
* 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.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1999-03-23 03:14:46 +00:00
|
|
|
* 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.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1999-03-23 03:14:46 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-06-28 22:56:06 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
1999-03-23 03:14:46 +00:00
|
|
|
*/
|
|
|
|
|
2012-09-20 01:48:30 +00:00
|
|
|
#include "config.h"
|
1999-03-23 03:14:46 +00:00
|
|
|
|
|
|
|
#include <ctype.h>
|
2003-11-30 23:05:45 +00:00
|
|
|
|
2004-02-20 17:31:00 +00:00
|
|
|
#ifdef HAVE_FCNTL_H
|
|
|
|
#include <fcntl.h>
|
|
|
|
#endif
|
|
|
|
|
2003-11-30 23:05:45 +00:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2003-11-30 18:01:20 +00:00
|
|
|
#include <unistd.h>
|
2003-11-30 23:05:45 +00:00
|
|
|
#endif
|
1999-03-23 03:14:46 +00:00
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
2001-07-09 22:54:15 +00:00
|
|
|
#include <gdk/gdkkeysyms.h>
|
2011-06-20 00:48:05 +00:00
|
|
|
#if GTK_CHECK_VERSION(3,0,0)
|
|
|
|
# include <gdk/gdkkeysyms-compat.h>
|
|
|
|
#endif
|
1999-03-23 03:14:46 +00:00
|
|
|
|
2004-01-07 22:16:17 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2002-06-04 07:03:57 +00:00
|
|
|
#include <epan/epan_dissect.h>
|
|
|
|
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
2004-09-10 22:59:37 +00:00
|
|
|
#include <epan/charsets.h>
|
2004-09-27 22:55:15 +00:00
|
|
|
#include <epan/prefs.h>
|
2009-06-01 20:52:53 +00:00
|
|
|
#include <epan/filesystem.h>
|
1999-03-23 03:14:46 +00:00
|
|
|
|
2008-04-13 00:55:59 +00:00
|
|
|
#include "../isprint.h"
|
2012-01-18 19:38:34 +00:00
|
|
|
|
2012-01-16 01:07:52 +00:00
|
|
|
#include "ui/alert_box.h"
|
2012-01-18 19:38:34 +00:00
|
|
|
#include "ui/last_open_dir.h"
|
2012-01-16 01:07:52 +00:00
|
|
|
#include "ui/progress_dlg.h"
|
2012-01-18 19:38:34 +00:00
|
|
|
#include "ui/recent.h"
|
|
|
|
#include "ui/simple_dialog.h"
|
2012-01-16 01:07:52 +00:00
|
|
|
#include "ui/ui_util.h"
|
2012-01-18 19:38:34 +00:00
|
|
|
|
2008-05-22 15:46:27 +00:00
|
|
|
#include <wsutil/file_util.h>
|
2004-06-30 06:58:59 +00:00
|
|
|
|
2012-01-15 21:59:11 +00:00
|
|
|
#include "ui/gtk/keys.h"
|
|
|
|
#include "ui/gtk/color_utils.h"
|
|
|
|
#include "ui/gtk/packet_win.h"
|
|
|
|
#include "ui/gtk/file_dlg.h"
|
|
|
|
#include "ui/gtk/gui_utils.h"
|
|
|
|
#include "ui/gtk/gtkglobals.h"
|
|
|
|
#include "ui/gtk/font_utils.h"
|
|
|
|
#include "ui/gtk/webbrowser.h"
|
|
|
|
#include "ui/gtk/main.h"
|
|
|
|
#include "ui/gtk/menus.h"
|
2012-06-16 20:59:12 +00:00
|
|
|
#include "ui/gtk/packet_panes.h"
|
2012-06-10 22:07:54 +00:00
|
|
|
#include "ui/gtk/proto_tree_model.h"
|
2012-07-15 20:24:48 +00:00
|
|
|
#include "ui/gtk/bytes_view.h"
|
2008-04-12 20:11:12 +00:00
|
|
|
|
2011-01-30 23:24:23 +00:00
|
|
|
#ifdef _WIN32
|
2006-02-13 21:25:43 +00:00
|
|
|
#include <gdk/gdkwin32.h>
|
|
|
|
#include <windows.h>
|
2012-01-16 01:29:08 +00:00
|
|
|
#include "ui/win32/file_dlg_win32.h"
|
2006-02-13 21:25:43 +00:00
|
|
|
#endif
|
|
|
|
|
2008-04-13 12:41:22 +00:00
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
#define E_BYTE_VIEW_TREE_PTR "byte_view_tree_ptr"
|
|
|
|
#define E_BYTE_VIEW_TREE_VIEW_PTR "byte_view_tree_view_ptr"
|
|
|
|
#define E_BYTE_VIEW_TVBUFF_KEY "byte_view_tvbuff"
|
|
|
|
#define E_BYTE_VIEW_START_KEY "byte_view_start"
|
|
|
|
#define E_BYTE_VIEW_END_KEY "byte_view_end"
|
2010-04-20 07:47:33 +00:00
|
|
|
#define E_BYTE_VIEW_MASK_KEY "byte_view_mask"
|
2010-04-20 17:32:12 +00:00
|
|
|
#define E_BYTE_VIEW_MASKLE_KEY "byte_view_mask_le"
|
2007-09-17 12:12:02 +00:00
|
|
|
#define E_BYTE_VIEW_APP_START_KEY "byte_view_app_start"
|
|
|
|
#define E_BYTE_VIEW_APP_END_KEY "byte_view_app_end"
|
2013-06-20 23:28:35 +00:00
|
|
|
#define E_BYTE_VIEW_PROTO_START_KEY "byte_view_proto_start"
|
|
|
|
#define E_BYTE_VIEW_PROTO_END_KEY "byte_view_proto_end"
|
2002-02-18 01:08:44 +00:00
|
|
|
#define E_BYTE_VIEW_ENCODE_KEY "byte_view_encode"
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
/* Get the current text window for the notebook. */
|
|
|
|
GtkWidget *
|
|
|
|
get_notebook_bv_ptr(GtkWidget *nb_ptr)
|
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
int num;
|
|
|
|
GtkWidget *bv_page;
|
|
|
|
|
|
|
|
num = gtk_notebook_get_current_page(GTK_NOTEBOOK(nb_ptr));
|
|
|
|
bv_page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(nb_ptr), num);
|
|
|
|
if (bv_page)
|
2011-02-07 18:41:38 +00:00
|
|
|
return gtk_bin_get_child(GTK_BIN(bv_page));
|
2010-10-12 17:39:44 +00:00
|
|
|
else
|
|
|
|
return NULL;
|
2001-03-23 14:44:04 +00:00
|
|
|
}
|
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
/*
|
|
|
|
* Get the data and length for a byte view, given the byte view page.
|
|
|
|
* Return the pointer, or NULL on error, and set "*data_len" to the length.
|
|
|
|
*/
|
|
|
|
const guint8 *
|
|
|
|
get_byte_view_data_and_length(GtkWidget *byte_view, guint *data_len)
|
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
tvbuff_t *byte_view_tvb;
|
|
|
|
const guint8 *data_ptr;
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2013-03-21 02:29:09 +00:00
|
|
|
byte_view_tvb = (tvbuff_t *)g_object_get_data(G_OBJECT(byte_view), E_BYTE_VIEW_TVBUFF_KEY);
|
2010-10-12 17:39:44 +00:00
|
|
|
if (byte_view_tvb == NULL)
|
|
|
|
return NULL;
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2012-05-07 10:51:14 +00:00
|
|
|
if ((*data_len = tvb_length(byte_view_tvb))) {
|
|
|
|
data_ptr = tvb_get_ptr(byte_view_tvb, 0, -1);
|
|
|
|
return data_ptr;
|
|
|
|
} else
|
|
|
|
return "";
|
2001-03-23 14:44:04 +00:00
|
|
|
}
|
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
/*
|
|
|
|
* Set the current text window for the notebook to the window that
|
|
|
|
* refers to a particular tvbuff.
|
|
|
|
*/
|
2001-03-23 14:44:04 +00:00
|
|
|
void
|
2002-02-18 01:08:44 +00:00
|
|
|
set_notebook_page(GtkWidget *nb_ptr, tvbuff_t *tvb)
|
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
int num;
|
|
|
|
GtkWidget *bv_page, *bv;
|
|
|
|
tvbuff_t *bv_tvb;
|
|
|
|
|
|
|
|
for (num = 0;
|
|
|
|
(bv_page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(nb_ptr), num)) != NULL;
|
|
|
|
num++) {
|
2011-02-07 18:41:38 +00:00
|
|
|
bv = gtk_bin_get_child(GTK_BIN(bv_page));
|
2013-03-21 02:29:09 +00:00
|
|
|
bv_tvb = (tvbuff_t *)g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_TVBUFF_KEY);
|
2010-10-12 17:39:44 +00:00
|
|
|
if (bv_tvb == tvb) {
|
|
|
|
/* Found it. */
|
|
|
|
gtk_notebook_set_current_page(GTK_NOTEBOOK(nb_ptr), num);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-03-23 14:44:04 +00:00
|
|
|
}
|
|
|
|
|
2000-09-08 10:59:21 +00:00
|
|
|
/* Redraw a given byte view window. */
|
2000-09-08 09:50:08 +00:00
|
|
|
void
|
2009-11-05 10:16:49 +00:00
|
|
|
redraw_packet_bytes(GtkWidget *nb, frame_data *fd, field_info *finfo)
|
2000-09-08 09:50:08 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
GtkWidget *bv;
|
|
|
|
const guint8 *data;
|
|
|
|
guint len;
|
|
|
|
|
|
|
|
bv = get_notebook_bv_ptr(nb);
|
|
|
|
if (bv != NULL) {
|
|
|
|
data = get_byte_view_data_and_length(bv, &len);
|
|
|
|
if (data != NULL)
|
|
|
|
packet_hex_print(bv, data, fd, finfo, len);
|
|
|
|
}
|
2000-09-08 09:50:08 +00:00
|
|
|
}
|
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
/* Redraw all byte view windows. */
|
2000-09-08 09:50:08 +00:00
|
|
|
void
|
2009-11-05 10:16:49 +00:00
|
|
|
redraw_packet_bytes_all(void)
|
2000-09-08 09:50:08 +00:00
|
|
|
{
|
2004-05-18 00:05:12 +00:00
|
|
|
if (cfile.current_frame != NULL)
|
2010-01-29 19:09:01 +00:00
|
|
|
redraw_packet_bytes( byte_nb_ptr_gbl, cfile.current_frame, cfile.finfo_selected);
|
2010-01-07 02:24:06 +00:00
|
|
|
|
|
|
|
redraw_packet_bytes_packet_wins();
|
|
|
|
|
|
|
|
/* XXX - this is a hack, to workaround a bug in GTK2.x!
|
|
|
|
when changing the font size, even refilling of the corresponding
|
|
|
|
gtk_text_buffer doesn't seem to trigger an update.
|
|
|
|
The only workaround is to freshly select the frame, which will remove any
|
|
|
|
existing notebook tabs and "restart" the whole byte view again. */
|
|
|
|
if (cfile.current_frame != NULL) {
|
|
|
|
cfile.current_row = -1;
|
|
|
|
cf_goto_frame(&cfile, cfile.current_frame->num);
|
|
|
|
}
|
2000-09-08 09:50:08 +00:00
|
|
|
}
|
|
|
|
|
2013-07-15 01:46:47 +00:00
|
|
|
/* Expand trees (and any subtrees they may have) whose ett_ shows them as
|
|
|
|
* expanded.
|
|
|
|
* Callers should block calls to expand_tree() to avoid useless recursion.
|
|
|
|
*/
|
2013-07-11 23:01:13 +00:00
|
|
|
static void
|
2013-07-15 01:46:47 +00:00
|
|
|
check_expand_trees(GtkTreeView *tree_view, GtkTreeModel *model, GtkTreePath *path,
|
|
|
|
GtkTreeIter *iter, gboolean scroll_it, gboolean expand_parent)
|
2013-07-11 23:01:13 +00:00
|
|
|
{
|
|
|
|
/* code inspired by gtk_tree_model_foreach_helper */
|
|
|
|
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
do {
|
|
|
|
GtkTreeIter child;
|
|
|
|
|
|
|
|
if (gtk_tree_model_iter_children(model, &child, iter)) {
|
|
|
|
gtk_tree_model_get(model, iter, 1, &fi, -1);
|
|
|
|
|
|
|
|
if (tree_expanded(fi->tree_type)) {
|
2013-07-15 01:46:47 +00:00
|
|
|
if (expand_parent)
|
|
|
|
gtk_tree_view_expand_row(tree_view, path, FALSE);
|
2013-07-11 23:01:13 +00:00
|
|
|
|
2013-07-12 13:56:14 +00:00
|
|
|
if (scroll_it)
|
2013-07-11 23:01:13 +00:00
|
|
|
gtk_tree_view_scroll_to_cell(tree_view, path, NULL, TRUE, (prefs.gui_auto_scroll_percentage/100.0f), 0.0f);
|
|
|
|
|
|
|
|
/* try to expand children only when parent is expanded */
|
|
|
|
gtk_tree_path_down(path);
|
2013-07-15 01:46:47 +00:00
|
|
|
check_expand_trees(tree_view, model, path, &child, scroll_it, TRUE);
|
2013-07-11 23:01:13 +00:00
|
|
|
gtk_tree_path_up(path);
|
2013-07-19 17:51:05 +00:00
|
|
|
}
|
2013-07-11 23:01:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_tree_path_next(path);
|
|
|
|
} while (gtk_tree_model_iter_next(model, iter));
|
|
|
|
}
|
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
static void
|
|
|
|
expand_tree(GtkTreeView *tree_view, GtkTreeIter *iter,
|
2013-07-12 13:56:14 +00:00
|
|
|
GtkTreePath *path, gpointer user_data _U_)
|
2001-03-02 23:10:12 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
field_info *finfo;
|
2002-11-03 17:38:45 +00:00
|
|
|
GtkTreeModel *model;
|
|
|
|
|
|
|
|
model = gtk_tree_view_get_model(tree_view);
|
|
|
|
gtk_tree_model_get(model, iter, 1, &finfo, -1);
|
|
|
|
g_assert(finfo);
|
|
|
|
|
2012-06-16 21:39:16 +00:00
|
|
|
/* scroll the expanded item to reduce the need to do a manual scroll down
|
|
|
|
* and provide faster navigation of deeper trees */
|
2011-08-16 10:57:52 +00:00
|
|
|
|
2013-01-25 19:01:57 +00:00
|
|
|
if(prefs.gui_auto_scroll_on_expand)
|
2012-06-16 21:39:16 +00:00
|
|
|
gtk_tree_view_scroll_to_cell(tree_view, path, NULL, TRUE, (prefs.gui_auto_scroll_percentage/100.0f), 0.0f);
|
2011-08-16 10:57:52 +00:00
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
/*
|
|
|
|
* Nodes with "finfo->tree_type" of -1 have no ett_ value, and
|
|
|
|
* are thus presumably leaf nodes and cannot be expanded.
|
|
|
|
*/
|
2013-07-19 17:31:32 +00:00
|
|
|
if (finfo->tree_type != -1)
|
2013-07-11 23:01:13 +00:00
|
|
|
tree_expanded_set(finfo->tree_type, TRUE);
|
|
|
|
|
2013-07-19 17:31:32 +00:00
|
|
|
if (finfo->tree_type != -1 && path) {
|
2013-07-11 23:01:13 +00:00
|
|
|
/* Expand any subtrees that the user had left open */
|
2013-07-15 01:46:47 +00:00
|
|
|
g_signal_handlers_block_by_func(tree_view, expand_tree, NULL);
|
|
|
|
check_expand_trees(tree_view, model, path, iter, FALSE, FALSE);
|
|
|
|
g_signal_handlers_unblock_by_func(tree_view, expand_tree, NULL);
|
2013-07-11 23:01:13 +00:00
|
|
|
}
|
2001-03-02 23:10:12 +00:00
|
|
|
}
|
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
static void
|
|
|
|
collapse_tree(GtkTreeView *tree_view, GtkTreeIter *iter,
|
2010-10-12 17:39:44 +00:00
|
|
|
GtkTreePath *path _U_, gpointer user_data _U_)
|
2001-03-02 23:10:12 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
field_info *finfo;
|
2002-11-03 17:38:45 +00:00
|
|
|
GtkTreeModel *model;
|
|
|
|
|
|
|
|
model = gtk_tree_view_get_model(tree_view);
|
|
|
|
gtk_tree_model_get(model, iter, 1, &finfo, -1);
|
|
|
|
g_assert(finfo);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Nodes with "finfo->tree_type" of -1 have no ett_ value, and
|
|
|
|
* are thus presumably leaf nodes and cannot be collapsed.
|
|
|
|
*/
|
2013-07-07 16:33:49 +00:00
|
|
|
if (finfo->tree_type != -1)
|
2013-07-11 23:01:13 +00:00
|
|
|
tree_expanded_set(finfo->tree_type, FALSE);
|
2001-03-02 23:10:12 +00:00
|
|
|
}
|
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
struct field_lookup_info {
|
|
|
|
field_info *fi;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
};
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
lookup_finfo(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
|
2010-10-12 17:39:44 +00:00
|
|
|
gpointer data)
|
2002-11-03 17:38:45 +00:00
|
|
|
{
|
|
|
|
field_info *fi;
|
|
|
|
struct field_lookup_info *fli = (struct field_lookup_info *)data;
|
|
|
|
|
|
|
|
gtk_tree_model_get(model, iter, 1, &fi, -1);
|
|
|
|
if (fi == fli->fi) {
|
|
|
|
fli->iter = *iter;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-20 06:34:09 +00:00
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
GtkTreePath
|
|
|
|
*tree_find_by_field_info(GtkTreeView *tree_view, field_info *finfo)
|
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
GtkTreeModel *model;
|
|
|
|
struct field_lookup_info fli;
|
2004-03-20 06:34:09 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
g_assert(finfo != NULL);
|
2005-05-18 19:30:18 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
model = gtk_tree_view_get_model(tree_view);
|
|
|
|
fli.fi = finfo;
|
|
|
|
gtk_tree_model_foreach(model, lookup_finfo, &fli);
|
2004-03-20 06:34:09 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
return gtk_tree_model_get_path(model, &fli.iter);
|
2004-03-20 06:34:09 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 10:16:49 +00:00
|
|
|
/* 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:
|
|
|
|
*
|
2010-10-12 17:39:44 +00:00
|
|
|
* if we succeed, select it, and return TRUE;
|
|
|
|
* if we fail, return FALSE. */
|
2009-11-05 10:16:49 +00:00
|
|
|
gboolean
|
|
|
|
byte_view_select(GtkWidget *widget, GdkEventButton *event)
|
|
|
|
{
|
|
|
|
proto_tree *tree;
|
|
|
|
GtkTreeView *tree_view;
|
2010-03-22 18:09:33 +00:00
|
|
|
int byte = -1;
|
2009-11-05 10:16:49 +00:00
|
|
|
tvbuff_t *tvb;
|
|
|
|
|
2013-03-21 02:29:09 +00:00
|
|
|
tree = (proto_tree *)g_object_get_data(G_OBJECT(widget), E_BYTE_VIEW_TREE_PTR);
|
2009-11-05 10:16:49 +00:00
|
|
|
if (tree == NULL) {
|
|
|
|
/*
|
|
|
|
* Somebody clicked on the dummy byte view; do nothing.
|
|
|
|
*/
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
tree_view = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(widget),
|
|
|
|
E_BYTE_VIEW_TREE_VIEW_PTR));
|
|
|
|
|
2012-07-15 20:48:40 +00:00
|
|
|
byte = bytes_view_byte_from_xy(BYTES_VIEW(widget), (gint) event->x, (gint) event->y);
|
2009-11-05 10:16:49 +00:00
|
|
|
|
|
|
|
if (byte == -1) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
/* Get the data source tvbuff */
|
2013-03-21 02:29:09 +00:00
|
|
|
tvb = (tvbuff_t *)g_object_get_data(G_OBJECT(widget), E_BYTE_VIEW_TVBUFF_KEY);
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2006-11-14 22:35:22 +00:00
|
|
|
return highlight_field(tvb, byte, tree_view, tree);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This highlights the field in the proto tree that is at position byte */
|
|
|
|
gboolean
|
|
|
|
highlight_field(tvbuff_t *tvb, gint byte, GtkTreeView *tree_view,
|
2010-10-12 17:39:44 +00:00
|
|
|
proto_tree *tree)
|
2006-11-14 22:35:22 +00:00
|
|
|
{
|
2011-01-31 12:19:15 +00:00
|
|
|
GtkTreeModel *model = NULL;
|
|
|
|
GtkTreePath *first_path = NULL, *path = NULL;
|
2006-11-14 22:35:22 +00:00
|
|
|
GtkTreeIter parent;
|
2011-01-31 12:19:15 +00:00
|
|
|
field_info *finfo = NULL;
|
|
|
|
match_data mdata;
|
2006-11-14 22:35:22 +00:00
|
|
|
struct field_lookup_info fli;
|
|
|
|
|
2011-01-31 12:19:15 +00:00
|
|
|
if (cfile.search_in_progress && cfile.string && cfile.decode_data) {
|
|
|
|
/* The tree where the target string matched one of the labels was discarded in
|
|
|
|
match_protocol_tree() so we have to search again in the latest tree. (Uugh) */
|
|
|
|
if (cf_find_string_protocol_tree(&cfile, tree, &mdata)) {
|
|
|
|
finfo = mdata.finfo;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Find the finfo that corresponds to our byte. */
|
|
|
|
finfo = proto_find_field_from_offset(tree, byte, tvb);
|
|
|
|
}
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
if (!finfo) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
model = gtk_tree_view_get_model(tree_view);
|
|
|
|
fli.fi = finfo;
|
|
|
|
gtk_tree_model_foreach(model, lookup_finfo, &fli);
|
|
|
|
|
|
|
|
/* Expand our field's row */
|
|
|
|
first_path = gtk_tree_model_get_path(model, &fli.iter);
|
|
|
|
gtk_tree_view_expand_row(tree_view, first_path, FALSE);
|
|
|
|
expand_tree(tree_view, &fli.iter, NULL, NULL);
|
|
|
|
|
|
|
|
/* ... and its parents */
|
|
|
|
while (gtk_tree_model_iter_parent(model, &parent, &fli.iter)) {
|
|
|
|
path = gtk_tree_model_get_path(model, &parent);
|
|
|
|
gtk_tree_view_expand_row(tree_view, path, FALSE);
|
|
|
|
expand_tree(tree_view, &parent, NULL, NULL);
|
|
|
|
fli.iter = parent;
|
|
|
|
gtk_tree_path_free(path);
|
|
|
|
}
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
/* select our field's row */
|
|
|
|
gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
|
|
|
|
first_path);
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2012-06-16 21:39:16 +00:00
|
|
|
/* If the last search was a string or hex search within "Packet data", the entire field might
|
2011-01-19 18:21:21 +00:00
|
|
|
not be highlighted. If the user just clicked on one of the bytes comprising that field, the
|
|
|
|
above call didn't trigger a 'gtk_tree_view_get_selection' event. Call redraw_packet_bytes()
|
2011-07-11 18:18:35 +00:00
|
|
|
to make the highlighting of the entire field visible. */
|
2011-01-31 12:19:15 +00:00
|
|
|
if (!cfile.search_in_progress) {
|
|
|
|
if (cfile.hex || (cfile.string && cfile.packet_data)) {
|
2011-01-19 18:21:21 +00:00
|
|
|
redraw_packet_bytes(byte_nb_ptr_gbl, cfile.current_frame, cfile.finfo_selected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
/* And position the window so the selection is visible.
|
|
|
|
* Position the selection in the middle of the viewable
|
|
|
|
* pane. */
|
2009-04-21 16:57:52 +00:00
|
|
|
gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5f, 0.0f);
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
gtk_tree_path_free(first_path);
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
return TRUE;
|
2001-03-02 23:10:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Calls functions for different mouse-button presses. */
|
2010-07-30 12:41:56 +00:00
|
|
|
static gboolean
|
2001-03-02 23:10:12 +00:00
|
|
|
byte_view_button_press_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
|
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
GdkEventButton *event_button = NULL;
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
if(widget == NULL || event == NULL || data == NULL) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
if(event->type == GDK_BUTTON_PRESS) {
|
|
|
|
event_button = (GdkEventButton *) event;
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2004-01-27 19:46:52 +00:00
|
|
|
/* To qoute the "Gdk Event Structures" doc:
|
|
|
|
* "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
|
2010-10-12 17:39:44 +00:00
|
|
|
switch(event_button->button) {
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
return byte_view_select(widget, event_button);
|
|
|
|
case 3:
|
|
|
|
return popup_menu_handler(widget, event, data);
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
2001-03-02 23:10:12 +00:00
|
|
|
}
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
GtkWidget *
|
2004-01-19 00:42:12 +00:00
|
|
|
byte_view_new(void)
|
2000-02-29 06:24:41 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
GtkWidget *byte_nb;
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
byte_nb = gtk_notebook_new();
|
|
|
|
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(byte_nb), GTK_POS_BOTTOM);
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/* this will only have an effect, if no tabs are shown */
|
|
|
|
gtk_notebook_set_show_border(GTK_NOTEBOOK(byte_nb), FALSE);
|
2004-02-06 19:19:12 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/* set the tabs scrollable, if they don't fit into the pane */
|
|
|
|
gtk_notebook_set_scrollable(GTK_NOTEBOOK(byte_nb), TRUE);
|
2004-05-09 07:01:07 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/* enable a popup menu containing the tab labels, will be helpful if tabs don't fit into the pane */
|
|
|
|
gtk_notebook_popup_enable(GTK_NOTEBOOK(byte_nb));
|
2004-05-09 07:01:07 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/* Add a placeholder byte view so that there's at least something
|
|
|
|
displayed in the byte view notebook. */
|
|
|
|
add_byte_tab(byte_nb, "", NULL, NULL, NULL);
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
return byte_nb;
|
2002-02-18 01:08:44 +00:00
|
|
|
}
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
static void
|
2002-03-05 11:56:00 +00:00
|
|
|
byte_view_realize_cb(GtkWidget *bv, gpointer data _U_)
|
2002-02-18 01:08:44 +00:00
|
|
|
{
|
2002-11-03 17:38:45 +00:00
|
|
|
const guint8 *byte_data;
|
|
|
|
guint byte_len;
|
|
|
|
|
|
|
|
byte_data = get_byte_view_data_and_length(bv, &byte_len);
|
|
|
|
if (byte_data == NULL) {
|
|
|
|
/* This must be the dummy byte view if no packet is selected. */
|
|
|
|
return;
|
|
|
|
}
|
2006-11-05 00:54:17 +00:00
|
|
|
packet_hex_print(bv, byte_data, cfile.current_frame, NULL, byte_len);
|
2001-03-23 14:44:04 +00:00
|
|
|
}
|
|
|
|
|
2012-06-16 21:30:24 +00:00
|
|
|
GtkWidget *
|
2002-02-18 01:08:44 +00:00
|
|
|
add_byte_tab(GtkWidget *byte_nb, const char *name, tvbuff_t *tvb,
|
2002-11-03 17:38:45 +00:00
|
|
|
proto_tree *tree, GtkWidget *tree_view)
|
2001-03-23 14:44:04 +00:00
|
|
|
{
|
2012-07-15 20:24:48 +00:00
|
|
|
GtkWidget *byte_view, *byte_scrollw, *label;
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/* Byte view. Create a scrolled window for the text. */
|
|
|
|
byte_scrollw = scrolled_window_new(NULL, NULL);
|
|
|
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(byte_scrollw),
|
|
|
|
GTK_SHADOW_IN);
|
|
|
|
/* Add scrolled pane to tabbed window */
|
|
|
|
label = gtk_label_new(name);
|
|
|
|
gtk_notebook_append_page(GTK_NOTEBOOK(byte_nb), byte_scrollw, label);
|
2004-02-06 19:19:12 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
gtk_widget_show(byte_scrollw);
|
2000-02-29 06:24:41 +00:00
|
|
|
|
2012-07-15 20:24:48 +00:00
|
|
|
byte_view = bytes_view_new();
|
|
|
|
bytes_view_set_font(BYTES_VIEW(byte_view), user_font_get_regular());
|
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
g_object_set_data(G_OBJECT(byte_view), E_BYTE_VIEW_TVBUFF_KEY, tvb);
|
|
|
|
gtk_container_add(GTK_CONTAINER(byte_scrollw), byte_view);
|
|
|
|
|
|
|
|
g_signal_connect(byte_view, "show", G_CALLBACK(byte_view_realize_cb), NULL);
|
|
|
|
g_signal_connect(byte_view, "button_press_event", G_CALLBACK(byte_view_button_press_cb),
|
|
|
|
g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
|
|
|
|
|
|
|
|
g_object_set_data(G_OBJECT(byte_view), E_BYTE_VIEW_TREE_PTR, tree);
|
|
|
|
g_object_set_data(G_OBJECT(byte_view), E_BYTE_VIEW_TREE_VIEW_PTR, tree_view);
|
|
|
|
|
|
|
|
gtk_widget_show(byte_view); /* triggers byte_view_realize_cb which calls packet_hex_print */
|
|
|
|
|
|
|
|
/* no tabs if this is the first page */
|
|
|
|
if (!(gtk_notebook_page_num(GTK_NOTEBOOK(byte_nb), byte_scrollw)))
|
2002-02-18 01:08:44 +00:00
|
|
|
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(byte_nb), FALSE);
|
2010-10-12 17:39:44 +00:00
|
|
|
else
|
2002-02-18 01:08:44 +00:00
|
|
|
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(byte_nb), TRUE);
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/* set this page */
|
|
|
|
gtk_notebook_set_current_page(GTK_NOTEBOOK(byte_nb),
|
|
|
|
gtk_notebook_page_num(GTK_NOTEBOOK(byte_nb), byte_nb));
|
2004-04-23 19:43:06 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
return byte_view;
|
2001-03-23 14:44:04 +00:00
|
|
|
}
|
|
|
|
|
2001-11-20 10:37:16 +00:00
|
|
|
void
|
2002-06-04 07:03:57 +00:00
|
|
|
add_byte_views(epan_dissect_t *edt, GtkWidget *tree_view,
|
2002-11-03 17:38:45 +00:00
|
|
|
GtkWidget *byte_nb_ptr)
|
2001-11-20 10:10:45 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
GSList *src_le;
|
2012-10-20 19:54:56 +00:00
|
|
|
struct data_source *src;
|
2010-10-12 17:39:44 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get rid of all the old notebook tabs.
|
|
|
|
*/
|
|
|
|
while (gtk_notebook_get_nth_page(GTK_NOTEBOOK(byte_nb_ptr), 0) != NULL)
|
|
|
|
gtk_notebook_remove_page(GTK_NOTEBOOK(byte_nb_ptr), 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add to the specified byte view notebook tabs for hex dumps
|
|
|
|
* of all the data sources for the specified frame.
|
|
|
|
*/
|
|
|
|
for (src_le = edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
|
2013-03-21 02:29:09 +00:00
|
|
|
src = (struct data_source *)src_le->data;
|
2012-10-20 19:54:56 +00:00
|
|
|
add_byte_tab(byte_nb_ptr, get_data_source_name(src), get_data_source_tvb(src), edt->tree,
|
2010-10-12 17:39:44 +00:00
|
|
|
tree_view);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initially select the first byte view.
|
|
|
|
*/
|
|
|
|
gtk_notebook_set_current_page(GTK_NOTEBOOK(byte_nb_ptr), 0);
|
2000-02-29 06:24:41 +00:00
|
|
|
}
|
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
static void
|
|
|
|
copy_hex_all_info(GString* copy_buffer, const guint8* data_p, int data_len, gboolean append_text)
|
2007-01-28 02:49:50 +00:00
|
|
|
{
|
|
|
|
const int byte_line_length = 16; /* Print out data for 16 bytes on one line */
|
|
|
|
int i, j;
|
|
|
|
gboolean end_of_line = TRUE; /* Initial state is end of line */
|
|
|
|
int byte_line_part_length;
|
|
|
|
|
|
|
|
GString* hex_str;
|
|
|
|
GString* char_str;
|
|
|
|
|
|
|
|
/* Write hex data for a line, then ascii data, then concatenate and add to buffer */
|
|
|
|
hex_str = g_string_new("");
|
|
|
|
char_str= g_string_new("");
|
|
|
|
|
|
|
|
i = 0;
|
2010-04-13 17:56:59 +00:00
|
|
|
while (i<data_len) {
|
2007-01-28 02:49:50 +00:00
|
|
|
if(end_of_line) {
|
2008-05-06 05:50:31 +00:00
|
|
|
g_string_append_printf(hex_str,"%04x ",i); /* Offset - note that we _append_ here */
|
2007-01-28 02:49:50 +00:00
|
|
|
}
|
|
|
|
|
2008-05-06 05:50:31 +00:00
|
|
|
g_string_append_printf(hex_str," %02x",*data_p);
|
2007-01-28 02:49:50 +00:00
|
|
|
if(append_text) {
|
2008-05-06 05:50:31 +00:00
|
|
|
g_string_append_printf(char_str,"%c",isprint(*data_p) ? *data_p : '.');
|
2007-01-28 02:49:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
++data_p;
|
|
|
|
|
|
|
|
/* Look ahead to see if this is the end of the data */
|
|
|
|
byte_line_part_length = (++i) % byte_line_length;
|
|
|
|
if(i == data_len){
|
|
|
|
/* End of data - need to fill in spaces in hex string and then do "end of line".
|
2008-05-22 15:46:27 +00:00
|
|
|
*
|
2007-01-28 02:49:50 +00:00
|
|
|
*/
|
|
|
|
for(j = 0; append_text && (j < (byte_line_length - byte_line_part_length)); ++j) {
|
|
|
|
g_string_append(hex_str," "); /* Three spaces for each missing byte */
|
|
|
|
}
|
|
|
|
end_of_line = TRUE;
|
|
|
|
} else {
|
|
|
|
end_of_line = (byte_line_part_length == 0 ? TRUE : FALSE);
|
|
|
|
}
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2007-01-28 02:49:50 +00:00
|
|
|
|
|
|
|
if (end_of_line){
|
|
|
|
/* End of line */
|
|
|
|
g_string_append(copy_buffer, hex_str->str);
|
|
|
|
if(append_text) {
|
|
|
|
/* Two spaces between hex and text */
|
|
|
|
g_string_append_c(copy_buffer, ' ');
|
|
|
|
g_string_append_c(copy_buffer, ' ');
|
|
|
|
g_string_append(copy_buffer, char_str->str);
|
|
|
|
}
|
|
|
|
/* Setup ready for next line */
|
|
|
|
g_string_assign(char_str,"");
|
|
|
|
g_string_assign(hex_str, "\n");
|
|
|
|
}
|
2010-04-13 17:56:59 +00:00
|
|
|
}
|
2007-01-28 02:49:50 +00:00
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
g_string_free(hex_str, TRUE);
|
|
|
|
g_string_free(char_str, TRUE);
|
2007-01-28 02:49:50 +00:00
|
|
|
}
|
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
static int
|
|
|
|
copy_hex_bytes_text_only(GString* copy_buffer, const guint8* data_p, int data_len _U_)
|
2007-01-28 02:49:50 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
gchar to_append;
|
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
/* Copy printable characters, newlines, and (horizontal) tabs. */
|
2007-01-28 02:49:50 +00:00
|
|
|
if(isprint(*data_p)) {
|
|
|
|
to_append = *data_p;
|
|
|
|
} else if(*data_p==0x0a) {
|
2010-04-13 17:56:59 +00:00
|
|
|
to_append = '\n';
|
|
|
|
} else if(*data_p==0x09) {
|
|
|
|
to_append = '\t';
|
2007-01-28 02:49:50 +00:00
|
|
|
} else {
|
|
|
|
return 1; /* Just ignore non-printable bytes */
|
|
|
|
}
|
|
|
|
g_string_append_c(copy_buffer,to_append);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-05-22 15:46:27 +00:00
|
|
|
static
|
2007-01-28 02:49:50 +00:00
|
|
|
int copy_hex_bytes_hex(GString* copy_buffer, const guint8* data_p, int data_len _U_)
|
|
|
|
{
|
2008-05-06 05:50:31 +00:00
|
|
|
g_string_append_printf(copy_buffer, "%02x", *data_p);
|
2007-01-28 02:49:50 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2005-08-20 14:02:00 +00:00
|
|
|
void
|
2007-01-28 02:49:50 +00:00
|
|
|
copy_hex_cb(GtkWidget * w _U_, gpointer data _U_, copy_data_type data_type)
|
2004-09-02 16:58:43 +00:00
|
|
|
{
|
2010-04-13 17:56:59 +00:00
|
|
|
GtkWidget *bv;
|
2007-01-28 02:49:50 +00:00
|
|
|
|
2007-09-26 07:09:51 +00:00
|
|
|
guint len = 0;
|
2007-01-28 02:49:50 +00:00
|
|
|
int bytes_consumed = 0;
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
const guint8* data_p;
|
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
GString* copy_buffer = g_string_new(""); /* String to copy to clipboard */
|
2006-02-13 21:25:43 +00:00
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
bv = get_notebook_bv_ptr(byte_nb_ptr_gbl);
|
|
|
|
if (bv == NULL) {
|
2010-10-12 17:39:44 +00:00
|
|
|
/* shouldn't happen */
|
2013-02-21 01:00:44 +00:00
|
|
|
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not find the corresponding text window.");
|
2010-10-12 17:39:44 +00:00
|
|
|
return;
|
2010-04-13 17:56:59 +00:00
|
|
|
}
|
2006-02-13 21:25:43 +00:00
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
data_p = get_byte_view_data_and_length(bv, &len);
|
|
|
|
g_assert(data_p != NULL);
|
2006-11-18 01:47:49 +00:00
|
|
|
|
2007-01-28 02:49:50 +00:00
|
|
|
flags = data_type & CD_FLAGSMASK;
|
2013-03-21 02:29:09 +00:00
|
|
|
data_type = (copy_data_type)(data_type & CD_TYPEMASK);
|
2006-11-18 01:47:49 +00:00
|
|
|
|
2007-01-28 02:49:50 +00:00
|
|
|
if(flags & CD_FLAGS_SELECTEDONLY) {
|
|
|
|
int start, end;
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2010-01-25 20:58:24 +00:00
|
|
|
/* Get the start and end of the highlighted bytes. */
|
|
|
|
start = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY));
|
|
|
|
end = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY));
|
2007-01-28 02:49:50 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
if(start >= 0 && end > start && (end - start <= (int)len)) {
|
2007-01-28 02:49:50 +00:00
|
|
|
len = end - start;
|
|
|
|
data_p += start;
|
2006-05-11 05:08:00 +00:00
|
|
|
}
|
2007-01-28 02:49:50 +00:00
|
|
|
}
|
2006-02-13 21:25:43 +00:00
|
|
|
|
2007-01-28 02:49:50 +00:00
|
|
|
switch(data_type) {
|
|
|
|
case(CD_ALLINFO):
|
|
|
|
/* This is too different from other text formats - handle separately */
|
|
|
|
copy_hex_all_info(copy_buffer, data_p, len, TRUE);
|
|
|
|
break;
|
|
|
|
case(CD_HEXCOLUMNS):
|
|
|
|
/* This could be done incrementally, but it is easier to mingle with the code for CD_ALLINFO */
|
|
|
|
copy_hex_all_info(copy_buffer, data_p, len, FALSE);
|
|
|
|
break;
|
|
|
|
case(CD_BINARY):
|
|
|
|
/* Completely different logic to text copies - leave copy buffer alone */
|
|
|
|
copy_binary_to_clipboard(data_p,len);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Incrementally write to text buffer in various formats */
|
2010-10-12 17:39:44 +00:00
|
|
|
while (len > 0){
|
2007-01-28 02:49:50 +00:00
|
|
|
switch(data_type) {
|
|
|
|
case (CD_TEXTONLY):
|
|
|
|
bytes_consumed = copy_hex_bytes_text_only(copy_buffer, data_p, len);
|
|
|
|
break;
|
|
|
|
case (CD_HEX):
|
|
|
|
bytes_consumed = copy_hex_bytes_hex(copy_buffer, data_p, len);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert(bytes_consumed>0);
|
|
|
|
data_p += bytes_consumed;
|
|
|
|
len -= bytes_consumed;
|
|
|
|
}
|
|
|
|
break;
|
2006-05-11 05:08:00 +00:00
|
|
|
}
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2007-01-28 02:49:50 +00:00
|
|
|
if(copy_buffer->len > 0) {
|
|
|
|
copy_to_clipboard(copy_buffer);
|
2006-05-11 05:08:00 +00:00
|
|
|
}
|
2007-01-28 02:49:50 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
g_string_free(copy_buffer, TRUE);
|
2004-09-02 16:58:43 +00:00
|
|
|
}
|
|
|
|
|
2004-05-31 12:06:28 +00:00
|
|
|
/* save the current highlighted hex data */
|
2009-06-01 20:52:53 +00:00
|
|
|
static gboolean
|
2013-05-15 22:03:14 +00:00
|
|
|
savehex_save_clicked_cb(gchar *file, int start, int end, const guint8 *data_p)
|
2003-11-29 06:09:54 +00:00
|
|
|
{
|
2013-05-15 22:03:14 +00:00
|
|
|
int fd;
|
2010-10-12 17:39:44 +00:00
|
|
|
|
|
|
|
fd = ws_open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
|
|
|
|
if (fd == -1) {
|
|
|
|
open_failure_alert_box(file, errno, TRUE);
|
2013-05-15 22:03:14 +00:00
|
|
|
return FALSE;
|
2010-10-12 17:39:44 +00:00
|
|
|
}
|
|
|
|
if (ws_write(fd, data_p + start, end - start) < 0) {
|
|
|
|
write_failure_alert_box(file, errno);
|
|
|
|
ws_close(fd);
|
2013-05-15 22:03:14 +00:00
|
|
|
return FALSE;
|
2010-10-12 17:39:44 +00:00
|
|
|
}
|
|
|
|
if (ws_close(fd) < 0) {
|
|
|
|
write_failure_alert_box(file, errno);
|
2013-05-15 22:03:14 +00:00
|
|
|
return FALSE;
|
2010-10-12 17:39:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2003-11-29 06:09:54 +00:00
|
|
|
}
|
|
|
|
|
2004-05-31 12:06:28 +00:00
|
|
|
/* Launch the dialog box to put up the file selection box etc */
|
2011-01-30 23:24:23 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
void
|
|
|
|
savehex_cb(GtkWidget * w _U_, gpointer data _U_)
|
|
|
|
{
|
2013-10-11 17:20:50 +00:00
|
|
|
win32_export_raw_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile);
|
2011-01-30 23:24:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
2013-05-15 22:03:14 +00:00
|
|
|
static char *
|
|
|
|
gtk_export_raw_file(int start, int end)
|
|
|
|
{
|
|
|
|
GtkWidget *savehex_dlg;
|
|
|
|
gchar *label;
|
|
|
|
GtkWidget *dlg_lb;
|
|
|
|
char *pathname;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Build the dialog box we need.
|
|
|
|
*/
|
|
|
|
savehex_dlg = file_selection_new("Wireshark: Export Selected Packet Bytes", GTK_WINDOW(top_level), FILE_SELECTION_SAVE);
|
|
|
|
|
|
|
|
/* label */
|
|
|
|
label = g_strdup_printf("Will save %u %s of raw binary data to specified file.",
|
|
|
|
end - start, plurality(end - start, "byte", "bytes"));
|
|
|
|
dlg_lb = gtk_label_new(label);
|
|
|
|
g_free(label);
|
|
|
|
file_selection_set_extra_widget(savehex_dlg, dlg_lb);
|
|
|
|
gtk_widget_show(dlg_lb);
|
|
|
|
|
|
|
|
pathname = file_selection_run(savehex_dlg);
|
|
|
|
if (pathname == NULL) {
|
|
|
|
/* User cancelled or closed the dialog. */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We've crosed the Rubicon; get rid of the dialog box. */
|
|
|
|
window_destroy(savehex_dlg);
|
|
|
|
|
|
|
|
return pathname;
|
|
|
|
}
|
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
void
|
|
|
|
savehex_cb(GtkWidget * w _U_, gpointer data _U_)
|
2004-05-31 12:06:28 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
int start, end;
|
|
|
|
guint len;
|
|
|
|
const guint8 *data_p = NULL;
|
|
|
|
GtkWidget *bv;
|
2013-05-15 22:03:14 +00:00
|
|
|
char *pathname;
|
2004-05-31 12:06:28 +00:00
|
|
|
|
|
|
|
/* don't show up the dialog, if no data has to be saved */
|
2010-10-12 17:39:44 +00:00
|
|
|
bv = get_notebook_bv_ptr(byte_nb_ptr_gbl);
|
|
|
|
if (bv == NULL) {
|
|
|
|
/* shouldn't happen */
|
2013-02-21 01:00:44 +00:00
|
|
|
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not find the corresponding text window.");
|
2010-10-12 17:39:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
start = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY));
|
|
|
|
end = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY));
|
|
|
|
data_p = get_byte_view_data_and_length(bv, &len);
|
|
|
|
|
|
|
|
if (data_p == NULL || start == -1 || start > end) {
|
2013-02-21 01:00:44 +00:00
|
|
|
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No data selected to save.");
|
2010-10-12 17:39:44 +00:00
|
|
|
return;
|
|
|
|
}
|
2004-05-31 12:06:28 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/*
|
2013-05-15 22:03:14 +00:00
|
|
|
* Loop until the user either selects a file or gives up.
|
2010-10-12 17:39:44 +00:00
|
|
|
*/
|
2013-05-15 22:03:14 +00:00
|
|
|
for (;;) {
|
|
|
|
pathname = gtk_export_raw_file(start, end);
|
|
|
|
if (pathname == NULL) {
|
|
|
|
/* User gave up. */
|
|
|
|
break;
|
2009-06-01 20:52:53 +00:00
|
|
|
}
|
2013-05-15 22:03:14 +00:00
|
|
|
if (savehex_save_clicked_cb(pathname, start, end, data_p)) {
|
|
|
|
/* We succeeded. */
|
|
|
|
g_free(pathname);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Dump failed; let the user select another file or give up. */
|
|
|
|
g_free(pathname);
|
2009-06-01 20:52:53 +00:00
|
|
|
}
|
2004-05-31 12:06:28 +00:00
|
|
|
}
|
2011-01-30 23:24:23 +00:00
|
|
|
#endif
|
2004-05-31 12:06:28 +00:00
|
|
|
|
2010-04-20 07:47:33 +00:00
|
|
|
static void
|
|
|
|
packet_hex_update(GtkWidget *bv, const guint8 *pd, int len, int bstart,
|
2010-10-12 17:39:44 +00:00
|
|
|
int bend, guint32 bmask, int bmask_le,
|
2013-06-20 23:28:35 +00:00
|
|
|
int astart, int aend,
|
|
|
|
int pstart, int pend,
|
|
|
|
int encoding)
|
2010-04-20 07:47:33 +00:00
|
|
|
{
|
2013-07-11 23:01:13 +00:00
|
|
|
bytes_view_set_encoding(BYTES_VIEW(bv), encoding);
|
|
|
|
bytes_view_set_format(BYTES_VIEW(bv), recent.gui_bytes_view);
|
|
|
|
bytes_view_set_data(BYTES_VIEW(bv), pd, len);
|
2013-01-25 19:01:57 +00:00
|
|
|
|
2013-07-11 23:01:13 +00:00
|
|
|
bytes_view_set_highlight_style(BYTES_VIEW(bv), prefs.gui_hex_dump_highlight_style);
|
2013-01-25 19:01:57 +00:00
|
|
|
|
2013-07-11 23:01:13 +00:00
|
|
|
bytes_view_set_highlight(BYTES_VIEW(bv), bstart, bend, bmask, bmask_le);
|
|
|
|
bytes_view_set_highlight_extra(BYTES_VIEW(bv), BYTE_VIEW_HIGHLIGHT_APPENDIX, astart, aend);
|
|
|
|
bytes_view_set_highlight_extra(BYTES_VIEW(bv), BYTE_VIEW_HIGHLIGHT_PROTOCOL, pstart, pend);
|
2013-01-25 19:01:57 +00:00
|
|
|
|
2013-07-11 23:01:13 +00:00
|
|
|
if (bstart != -1 && bend != -1)
|
|
|
|
bytes_view_scroll_to_byte(BYTES_VIEW(bv), bstart);
|
|
|
|
bytes_view_refresh(BYTES_VIEW(bv));
|
1999-03-23 03:14:46 +00:00
|
|
|
}
|
|
|
|
|
2013-06-21 00:23:55 +00:00
|
|
|
static field_info *
|
|
|
|
get_top_finfo(proto_node *node, field_info *finfo)
|
|
|
|
{
|
|
|
|
proto_node *child;
|
|
|
|
field_info *top;
|
|
|
|
|
2013-07-01 15:20:02 +00:00
|
|
|
if (node == NULL)
|
|
|
|
return NULL;
|
2013-06-21 00:23:55 +00:00
|
|
|
if (PNODE_FINFO(node) == finfo) {
|
|
|
|
top = finfo;
|
|
|
|
|
|
|
|
while (node && node->parent) {
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
node = node->parent;
|
|
|
|
|
|
|
|
fi = PNODE_FINFO(node);
|
|
|
|
if (fi && fi->ds_tvb == finfo->ds_tvb)
|
|
|
|
top = fi;
|
|
|
|
}
|
|
|
|
|
|
|
|
return top;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (child = node->first_child; child; child = child->next) {
|
|
|
|
top = get_top_finfo(child, finfo);
|
|
|
|
if (top)
|
|
|
|
return top;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
void
|
2006-11-05 00:54:17 +00:00
|
|
|
packet_hex_print(GtkWidget *bv, const guint8 *pd, frame_data *fd,
|
2010-10-12 17:39:44 +00:00
|
|
|
field_info *finfo, guint len)
|
2002-02-18 01:08:44 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
/* do the initial printing and save the information needed */
|
|
|
|
/* to redraw the display if preferences change. */
|
|
|
|
|
|
|
|
int bstart = -1, bend = -1, blen = -1;
|
|
|
|
guint32 bmask = 0x00; int bmask_le = 0;
|
|
|
|
int astart = -1, aend = -1, alen = -1;
|
2013-06-20 23:28:35 +00:00
|
|
|
int pstart = -1, pend = -1, plen = -1;
|
2010-11-21 10:41:01 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
if (finfo != NULL) {
|
2013-06-21 00:23:55 +00:00
|
|
|
proto_tree *tree = (proto_tree *)g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_TREE_PTR);
|
|
|
|
field_info *top_finfo;
|
2011-01-19 18:21:21 +00:00
|
|
|
|
2011-01-31 12:19:15 +00:00
|
|
|
if (cfile.search_in_progress && (cfile.hex || (cfile.string && cfile.packet_data))) {
|
|
|
|
/* In the hex view, only highlight the target bytes or string. The entire
|
|
|
|
field can then be displayed by clicking on any of the bytes in the field. */
|
|
|
|
if (cfile.hex) {
|
2013-01-25 19:01:57 +00:00
|
|
|
char *p = cfile.sfilter;
|
|
|
|
|
|
|
|
blen = 0;
|
|
|
|
while (*p) {
|
|
|
|
if (g_ascii_isxdigit(*p++))
|
|
|
|
blen++;
|
|
|
|
}
|
|
|
|
blen = (blen + 1) / 2;
|
2011-01-31 12:19:15 +00:00
|
|
|
} else {
|
|
|
|
blen = (int)strlen(cfile.sfilter);
|
2011-01-19 18:21:21 +00:00
|
|
|
}
|
2011-01-31 12:19:15 +00:00
|
|
|
bstart = cfile.search_pos - (blen-1);
|
|
|
|
|
2011-07-11 18:18:35 +00:00
|
|
|
} else {
|
2011-01-19 18:21:21 +00:00
|
|
|
blen = finfo->length;
|
|
|
|
bstart = finfo->start;
|
|
|
|
}
|
|
|
|
|
2013-08-06 20:10:59 +00:00
|
|
|
/* bmask = finfo->hfinfo->bitmask << hfinfo_bitshift(finfo->hfinfo); */ /* (value & mask) >> shift */
|
2011-03-22 19:48:55 +00:00
|
|
|
if (finfo->hfinfo) bmask = finfo->hfinfo->bitmask;
|
2010-10-12 17:39:44 +00:00
|
|
|
astart = finfo->appendix_start;
|
|
|
|
alen = finfo->appendix_length;
|
|
|
|
|
2013-06-21 00:23:55 +00:00
|
|
|
top_finfo = get_top_finfo(tree, finfo);
|
|
|
|
/* it's possible to have top_finfo == finfo, no problem right now */
|
|
|
|
if (top_finfo) {
|
|
|
|
pstart = top_finfo->start;
|
|
|
|
plen = top_finfo->length;
|
2013-06-20 23:28:35 +00:00
|
|
|
}
|
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
if (FI_GET_FLAG(finfo, FI_LITTLE_ENDIAN))
|
|
|
|
bmask_le = 1;
|
|
|
|
else if (FI_GET_FLAG(finfo, FI_BIG_ENDIAN))
|
|
|
|
bmask_le = 0;
|
|
|
|
else { /* unknown endianess - disable mask
|
|
|
|
bmask_le = (G_BYTE_ORDER == G_LITTLE_ENDIAN);
|
|
|
|
*/
|
|
|
|
bmask = 0x00;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bmask == 0x00) {
|
|
|
|
int bito = FI_GET_BITS_OFFSET(finfo);
|
|
|
|
int bitc = FI_GET_BITS_SIZE(finfo);
|
|
|
|
int bitt = bito + bitc;
|
|
|
|
|
|
|
|
/* construct mask using bito & bitc */
|
|
|
|
/* XXX, mask has only 32 bit, later we can store bito&bitc, and use them (which should be faster) */
|
|
|
|
if (bitt > 0 && bitt < 32) {
|
|
|
|
|
2012-04-12 21:56:13 +00:00
|
|
|
bmask = ((1 << bitc) - 1) << ((8-bitt) & 7);
|
2010-10-12 17:39:44 +00:00
|
|
|
bmask_le = 0; /* ? */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-20 23:28:35 +00:00
|
|
|
if (pstart >= 0 && plen > 0 && (guint)pstart < len)
|
|
|
|
pend = pstart + plen;
|
|
|
|
|
|
|
|
if (bstart >= 0 && blen > 0 && (guint)bstart < len)
|
2010-10-12 17:39:44 +00:00
|
|
|
bend = bstart + blen;
|
2013-06-20 23:28:35 +00:00
|
|
|
|
|
|
|
if (astart >= 0 && alen > 0 && (guint)astart < len)
|
2010-10-12 17:39:44 +00:00
|
|
|
aend = astart + alen;
|
|
|
|
|
|
|
|
if (bend == -1 && aend != -1) {
|
|
|
|
bstart = astart;
|
|
|
|
bmask = 0x00;
|
|
|
|
bend = aend;
|
|
|
|
astart = aend = -1;
|
|
|
|
}
|
|
|
|
|
2010-11-21 10:41:01 +00:00
|
|
|
/* don't exceed the end of available data */
|
|
|
|
if (aend != -1 && (guint)aend > len) aend = len;
|
|
|
|
if (bend != -1 && (guint)bend > len) bend = len;
|
2013-06-20 23:28:35 +00:00
|
|
|
if (pend != -1 && (guint)pend > len) pend = len;
|
2010-11-21 10:41:01 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/* save the information needed to redraw the text */
|
|
|
|
/* should we save the fd & finfo pointers instead ?? */
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY, GINT_TO_POINTER(bstart));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY, GINT_TO_POINTER(bend));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY, GINT_TO_POINTER(bmask));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY, GINT_TO_POINTER(bmask_le));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY, GINT_TO_POINTER(astart));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY, GINT_TO_POINTER(aend));
|
2013-06-20 23:28:35 +00:00
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY, GINT_TO_POINTER(pstart));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY, GINT_TO_POINTER(pend));
|
2010-10-12 17:39:44 +00:00
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY,
|
|
|
|
GUINT_TO_POINTER((guint)fd->flags.encoding));
|
|
|
|
|
2011-04-26 08:51:25 +00:00
|
|
|
/* stig: it should be done only for bitview... */
|
|
|
|
if (recent.gui_bytes_view != BYTES_BITS)
|
|
|
|
bmask = 0x00;
|
2013-06-20 23:28:35 +00:00
|
|
|
packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, pstart, pend, fd->flags.encoding);
|
2011-04-26 08:51:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
packet_hex_editor_print(GtkWidget *bv, const guint8 *pd, frame_data *fd, int offset, int bitoffset, guint len)
|
|
|
|
{
|
|
|
|
/* do the initial printing and save the information needed */
|
|
|
|
/* to redraw the display if preferences change. */
|
|
|
|
|
|
|
|
int bstart = offset, bend = (bstart != -1) ? offset+1 : -1;
|
2012-02-07 11:15:22 +00:00
|
|
|
guint32 bmask=0; int bmask_le = 0;
|
2011-04-26 08:51:25 +00:00
|
|
|
int astart = -1, aend = -1;
|
2013-06-20 23:28:35 +00:00
|
|
|
int pstart = -1, pend = -1;
|
2011-04-26 08:51:25 +00:00
|
|
|
|
|
|
|
switch (recent.gui_bytes_view) {
|
|
|
|
case BYTES_HEX:
|
|
|
|
bmask = (bitoffset == 0) ? 0xf0 : (bitoffset == 4) ? 0x0f : 0xff;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BYTES_BITS:
|
|
|
|
bmask = (1 << (7-bitoffset));
|
|
|
|
break;
|
|
|
|
|
2012-06-16 21:39:16 +00:00
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
break;
|
2011-04-26 08:51:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* save the information needed to redraw the text */
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY, GINT_TO_POINTER(bstart));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY, GINT_TO_POINTER(bend));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY, GINT_TO_POINTER(bmask));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY, GINT_TO_POINTER(bmask_le));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY, GINT_TO_POINTER(astart));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY, GINT_TO_POINTER(aend));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY,
|
|
|
|
GUINT_TO_POINTER((guint)fd->flags.encoding));
|
2013-06-20 23:28:35 +00:00
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY, GINT_TO_POINTER(pstart));
|
|
|
|
g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY, GINT_TO_POINTER(pend));
|
2011-04-26 08:51:25 +00:00
|
|
|
|
2013-06-20 23:28:35 +00:00
|
|
|
packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, pstart, pend, fd->flags.encoding);
|
2001-03-23 14:44:04 +00:00
|
|
|
}
|
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
/*
|
|
|
|
* Redraw the text using the saved information; usually called if
|
|
|
|
* the preferences have changed.
|
|
|
|
*/
|
2001-03-23 14:44:04 +00:00
|
|
|
void
|
2006-11-05 00:54:17 +00:00
|
|
|
packet_hex_reprint(GtkWidget *bv)
|
2002-02-18 01:08:44 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
int start, end, mask, mask_le, encoding;
|
|
|
|
int astart, aend;
|
2013-06-20 23:28:35 +00:00
|
|
|
int pstart, pend;
|
2010-10-12 17:39:44 +00:00
|
|
|
const guint8 *data;
|
|
|
|
guint len = 0;
|
|
|
|
|
|
|
|
start = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY));
|
|
|
|
end = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY));
|
|
|
|
mask = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY));
|
|
|
|
mask_le = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY));
|
|
|
|
astart = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY));
|
|
|
|
aend = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY));
|
2013-06-20 23:28:35 +00:00
|
|
|
pstart = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY));
|
|
|
|
pend = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY));
|
2010-10-12 17:39:44 +00:00
|
|
|
data = get_byte_view_data_and_length(bv, &len);
|
|
|
|
g_assert(data != NULL);
|
|
|
|
encoding = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY));
|
|
|
|
|
2011-04-26 08:51:25 +00:00
|
|
|
/* stig: it should be done only for bitview... */
|
|
|
|
if (recent.gui_bytes_view != BYTES_BITS)
|
|
|
|
mask = 0x00;
|
2013-06-20 23:28:35 +00:00
|
|
|
packet_hex_update(bv, data, len, start, end, mask, mask_le, astart, aend, pstart, pend, encoding);
|
2001-03-23 14:44:04 +00:00
|
|
|
}
|
|
|
|
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
/* List of all protocol tree widgets, so we can globally set the selection
|
2002-01-11 06:43:18 +00:00
|
|
|
mode and font of all of them. */
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
static GList *ptree_widgets;
|
|
|
|
|
|
|
|
/* Add a protocol tree widget to the list of protocol tree widgets. */
|
|
|
|
static void forget_ptree_widget(GtkWidget *ptreew, gpointer data);
|
|
|
|
|
2000-09-08 09:50:08 +00:00
|
|
|
static void
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
remember_ptree_widget(GtkWidget *ptreew)
|
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
ptree_widgets = g_list_append(ptree_widgets, ptreew);
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
/* Catch the "destroy" event on the widget, so that we remove it from
|
|
|
|
the list when it's destroyed. */
|
|
|
|
g_signal_connect(ptreew, "destroy", G_CALLBACK(forget_ptree_widget), NULL);
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
}
|
|
|
|
|
2000-09-08 09:50:08 +00:00
|
|
|
/* Remove a protocol tree widget from the list of protocol tree widgets. */
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
static void
|
2002-03-05 11:56:00 +00:00
|
|
|
forget_ptree_widget(GtkWidget *ptreew, gpointer data _U_)
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
ptree_widgets = g_list_remove(ptree_widgets, ptreew);
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
}
|
|
|
|
|
2002-11-03 17:38:45 +00:00
|
|
|
static void
|
|
|
|
set_ptree_font_cb(gpointer data, gpointer user_data)
|
|
|
|
{
|
2011-08-17 15:29:15 +00:00
|
|
|
#if GTK_CHECK_VERSION(3,0,0)
|
|
|
|
gtk_widget_override_font((GtkWidget *)data,
|
|
|
|
(PangoFontDescription *)user_data);
|
|
|
|
#else
|
2010-10-12 17:39:44 +00:00
|
|
|
gtk_widget_modify_font((GtkWidget *)data,
|
|
|
|
(PangoFontDescription *)user_data);
|
2011-08-17 15:29:15 +00:00
|
|
|
#endif
|
2002-11-03 17:38:45 +00:00
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
void
|
2008-04-11 04:52:36 +00:00
|
|
|
set_ptree_font_all(PangoFontDescription *font)
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
{
|
2002-11-03 17:38:45 +00:00
|
|
|
g_list_foreach(ptree_widgets, set_ptree_font_cb, font);
|
Instead of each set of built-in preferences having "ok", "save",
"cancel", and "delete" methods, give them:
"fetch" - fetch from the notebook tab any values not already
stored in "prefs", and store them there, but doesn't apply them;
"apply" - apply the settings in "prefs";
"destroy" - clean up any windows created from the tab.
As we no longer have "cancel" methods, we don't have per-preference code
to revert preference values; instead, we have the common preference
dialog box code make a copy of all the current preferences, and, when
the "Cancel" button is clicked, free the current preferences and copy
the saved preferences to it, and apply the preferences.
Add an "Apply" button to the preference dialog box, which applies the
current preferences without closing the dialog box.
Treat a request to delete the preferences dialog box as equivalent to
clicking "Cancel".
Have a "remember_ptree_widget()" routine to remember all protocol tree
widgets, and use the list of those widgets when we set GUI preferences
for the protocol tree widgets, rather than setting the main protocol
tree widget and then using the list of packet windows. Move that code
out of "main.c" to "proto_draw.c", as it's not used by anything in
"main.c", but is used by stuff in "proto_draw.c".
Make the font one of the preferences we can set on the fly for protocol
tree widgets. Also make it something we can set on the fly for the
packet list widget.
svn path=/trunk/; revision=2316
2000-08-21 08:09:17 +00:00
|
|
|
}
|
|
|
|
|
2004-05-14 15:55:37 +00:00
|
|
|
|
2009-11-05 19:45:51 +00:00
|
|
|
/*
|
|
|
|
* Each expert_color_* level below should match the light gradient
|
|
|
|
* colors in image/expert_indicators.svg.
|
|
|
|
*/
|
2010-10-12 17:39:44 +00:00
|
|
|
static gboolean colors_ok = FALSE;
|
|
|
|
|
2012-12-23 04:37:58 +00:00
|
|
|
GdkColor expert_color_comment = { 0, 0xb7b7, 0xf7f7, 0x7474 }; /* Green */
|
2010-10-12 17:39:44 +00:00
|
|
|
GdkColor expert_color_chat = { 0, 0x8080, 0xb7b7, 0xf7f7 }; /* light blue */
|
|
|
|
GdkColor expert_color_note = { 0, 0xa0a0, 0xffff, 0xffff }; /* bright turquoise */
|
|
|
|
GdkColor expert_color_warn = { 0, 0xf7f7, 0xf2f2, 0x5353 }; /* yellow */
|
|
|
|
GdkColor expert_color_error = { 0, 0xffff, 0x5c5c, 0x5c5c }; /* pale red */
|
|
|
|
GdkColor expert_color_foreground = { 0, 0x0000, 0x0000, 0x0000 }; /* black */
|
|
|
|
GdkColor hidden_proto_item = { 0, 0x4444, 0x4444, 0x4444 }; /* gray */
|
2005-09-11 16:55:34 +00:00
|
|
|
|
2012-03-02 13:31:16 +00:00
|
|
|
gchar *expert_color_comment_str;
|
2009-08-26 17:26:26 +00:00
|
|
|
gchar *expert_color_chat_str;
|
|
|
|
gchar *expert_color_note_str;
|
|
|
|
gchar *expert_color_warn_str;
|
|
|
|
gchar *expert_color_error_str;
|
|
|
|
gchar *expert_color_foreground_str;
|
|
|
|
|
2006-02-13 21:25:43 +00:00
|
|
|
void proto_draw_colors_init(void)
|
2005-09-11 16:55:34 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
if(colors_ok) {
|
|
|
|
return;
|
|
|
|
}
|
2011-08-17 10:53:46 +00:00
|
|
|
#if 0
|
2012-06-16 21:39:16 +00:00
|
|
|
/* Allocating collor isn't necessary? */
|
2010-10-12 17:39:44 +00:00
|
|
|
get_color(&expert_color_chat);
|
|
|
|
get_color(&expert_color_note);
|
|
|
|
get_color(&expert_color_warn);
|
|
|
|
get_color(&expert_color_error);
|
|
|
|
get_color(&expert_color_foreground);
|
2011-08-17 10:53:46 +00:00
|
|
|
#endif
|
2012-03-02 13:31:16 +00:00
|
|
|
expert_color_comment_str = gdk_color_to_string(&expert_color_comment);
|
2010-10-12 17:39:44 +00:00
|
|
|
expert_color_chat_str = gdk_color_to_string(&expert_color_chat);
|
|
|
|
expert_color_note_str = gdk_color_to_string(&expert_color_note);
|
|
|
|
expert_color_warn_str = gdk_color_to_string(&expert_color_warn);
|
|
|
|
expert_color_error_str = gdk_color_to_string(&expert_color_error);
|
|
|
|
expert_color_foreground_str = gdk_color_to_string(&expert_color_foreground);
|
|
|
|
|
2011-08-17 10:53:46 +00:00
|
|
|
#if 0
|
2012-06-16 21:39:16 +00:00
|
|
|
get_color(&hidden_proto_item);
|
2011-08-17 10:53:46 +00:00
|
|
|
#endif
|
2010-10-12 17:39:44 +00:00
|
|
|
colors_ok = TRUE;
|
2005-09-11 16:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
static void
|
|
|
|
tree_cell_renderer(GtkTreeViewColumn *tree_column _U_, GtkCellRenderer *cell,
|
2010-10-12 17:39:44 +00:00
|
|
|
GtkTreeModel *tree_model, GtkTreeIter *iter,
|
|
|
|
gpointer data _U_)
|
2004-05-14 15:55:37 +00:00
|
|
|
{
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
gtk_tree_model_get(tree_model, iter, 1, &fi, -1);
|
|
|
|
|
2010-01-07 02:24:06 +00:00
|
|
|
if(!colors_ok) {
|
|
|
|
proto_draw_colors_init();
|
|
|
|
}
|
2005-09-11 16:55:34 +00:00
|
|
|
|
2010-01-07 02:24:06 +00:00
|
|
|
/* for the various possible attributes, see:
|
|
|
|
* http://developer.gnome.org/doc/API/2.0/gtk/GtkCellRendererText.html
|
|
|
|
*
|
|
|
|
* color definitions can be found at:
|
|
|
|
* http://cvs.gnome.org/viewcvs/gtk+/gdk-pixbuf/io-xpm.c?rev=1.42
|
|
|
|
* (a good color overview: http://www.computerhope.com/htmcolor.htm)
|
|
|
|
*
|
|
|
|
* some experiences:
|
|
|
|
* background-gdk: doesn't seem to work (probably the GdkColor must be allocated)
|
|
|
|
* weight/style: doesn't take any effect
|
|
|
|
*/
|
2005-08-21 15:23:48 +00:00
|
|
|
|
2004-05-14 15:55:37 +00:00
|
|
|
/* for each field, we have to reset the renderer attributes */
|
|
|
|
g_object_set (cell, "foreground-set", FALSE, NULL);
|
|
|
|
|
2008-03-14 06:15:06 +00:00
|
|
|
g_object_set (cell, "background-set", FALSE, NULL);
|
2005-08-21 15:23:48 +00:00
|
|
|
|
2004-05-14 15:55:37 +00:00
|
|
|
g_object_set (cell, "underline", PANGO_UNDERLINE_NONE, NULL);
|
|
|
|
g_object_set (cell, "underline-set", FALSE, NULL);
|
|
|
|
|
|
|
|
/*g_object_set (cell, "style", PANGO_STYLE_NORMAL, NULL);
|
|
|
|
g_object_set (cell, "style-set", FALSE, NULL);*/
|
|
|
|
|
|
|
|
/*g_object_set (cell, "weight", PANGO_WEIGHT_NORMAL, NULL);
|
|
|
|
g_object_set (cell, "weight-set", FALSE, NULL);*/
|
|
|
|
|
|
|
|
if(FI_GET_FLAG(fi, FI_GENERATED)) {
|
2010-01-07 02:24:06 +00:00
|
|
|
/* we use "[...]" to mark generated items, no need to change things here */
|
2005-09-11 16:55:34 +00:00
|
|
|
|
2004-05-14 15:55:37 +00:00
|
|
|
/* as some fonts don't support italic, don't use this */
|
|
|
|
/*g_object_set (cell, "style", PANGO_STYLE_ITALIC, NULL);
|
|
|
|
g_object_set (cell, "style-set", TRUE, NULL);
|
|
|
|
*/
|
|
|
|
/*g_object_set (cell, "weight", PANGO_WEIGHT_BOLD, NULL);
|
|
|
|
g_object_set (cell, "weight-set", TRUE, NULL);*/
|
2009-02-23 15:30:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(FI_GET_FLAG(fi, FI_HIDDEN)) {
|
2008-04-17 23:14:01 +00:00
|
|
|
g_object_set (cell, "foreground-gdk", &hidden_proto_item, NULL);
|
|
|
|
g_object_set (cell, "foreground-set", TRUE, NULL);
|
2004-05-14 15:55:37 +00:00
|
|
|
}
|
|
|
|
|
2009-10-01 14:41:34 +00:00
|
|
|
if (fi && fi->hfinfo) {
|
|
|
|
if(fi->hfinfo->type == FT_PROTOCOL) {
|
|
|
|
g_object_set (cell, "background", "gray90", NULL);
|
|
|
|
g_object_set (cell, "background-set", TRUE, NULL);
|
|
|
|
g_object_set (cell, "foreground", "black", NULL);
|
|
|
|
g_object_set (cell, "foreground-set", TRUE, NULL);
|
|
|
|
/*g_object_set (cell, "weight", PANGO_WEIGHT_BOLD, NULL);
|
2010-01-07 02:24:06 +00:00
|
|
|
g_object_set (cell, "weight-set", TRUE, NULL);*/
|
2009-10-01 14:41:34 +00:00
|
|
|
}
|
2010-10-12 17:39:44 +00:00
|
|
|
|
2009-10-01 14:41:34 +00:00
|
|
|
if((fi->hfinfo->type == FT_FRAMENUM) ||
|
|
|
|
(FI_GET_FLAG(fi, FI_URL) && IS_FT_STRING(fi->hfinfo->type))) {
|
|
|
|
render_as_url(cell);
|
|
|
|
}
|
2004-05-14 15:55:37 +00:00
|
|
|
}
|
2010-10-12 17:39:44 +00:00
|
|
|
|
2010-01-07 02:24:06 +00:00
|
|
|
if(FI_GET_FLAG(fi, PI_SEVERITY_MASK)) {
|
|
|
|
switch(FI_GET_FLAG(fi, PI_SEVERITY_MASK)) {
|
2012-03-02 13:31:16 +00:00
|
|
|
case(PI_COMMENT):
|
|
|
|
g_object_set (cell, "background-gdk", &expert_color_comment, NULL);
|
|
|
|
g_object_set (cell, "background-set", TRUE, NULL);
|
|
|
|
break;
|
2010-01-07 02:24:06 +00:00
|
|
|
case(PI_CHAT):
|
|
|
|
g_object_set (cell, "background-gdk", &expert_color_chat, NULL);
|
|
|
|
g_object_set (cell, "background-set", TRUE, NULL);
|
|
|
|
break;
|
|
|
|
case(PI_NOTE):
|
|
|
|
g_object_set (cell, "background-gdk", &expert_color_note, NULL);
|
|
|
|
g_object_set (cell, "background-set", TRUE, NULL);
|
|
|
|
break;
|
|
|
|
case(PI_WARN):
|
|
|
|
g_object_set (cell, "background-gdk", &expert_color_warn, NULL);
|
|
|
|
g_object_set (cell, "background-set", TRUE, NULL);
|
|
|
|
break;
|
|
|
|
case(PI_ERROR):
|
|
|
|
g_object_set (cell, "background-gdk", &expert_color_error, NULL);
|
|
|
|
g_object_set (cell, "background-set", TRUE, NULL);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
g_object_set (cell, "foreground", "black", NULL);
|
|
|
|
g_object_set (cell, "foreground-set", TRUE, NULL);
|
|
|
|
}
|
2004-05-14 15:55:37 +00:00
|
|
|
}
|
|
|
|
|
2004-01-19 00:42:12 +00:00
|
|
|
GtkWidget *
|
2013-01-22 18:27:18 +00:00
|
|
|
proto_tree_view_new(GtkWidget **tree_view_p)
|
2000-02-29 06:24:41 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
GtkWidget *tv_scrollw, *tree_view;
|
2012-06-10 22:07:54 +00:00
|
|
|
ProtoTreeModel *store;
|
2010-10-12 17:39:44 +00:00
|
|
|
GtkCellRenderer *renderer;
|
|
|
|
GtkTreeViewColumn *column;
|
|
|
|
gint col_offset;
|
|
|
|
|
|
|
|
/* Tree view */
|
|
|
|
tv_scrollw = scrolled_window_new(NULL, NULL);
|
|
|
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(tv_scrollw),
|
|
|
|
GTK_SHADOW_IN);
|
|
|
|
|
2012-06-10 22:07:54 +00:00
|
|
|
store = proto_tree_model_new(NULL, prefs.display_hidden_proto_items);
|
2010-10-12 17:39:44 +00:00
|
|
|
tree_view = tree_view_new(GTK_TREE_MODEL(store));
|
|
|
|
g_object_unref(G_OBJECT(store));
|
|
|
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
|
|
|
|
renderer = gtk_cell_renderer_text_new();
|
|
|
|
g_object_set (renderer, "ypad", 0, NULL);
|
|
|
|
col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree_view),
|
|
|
|
-1, "Name", renderer,
|
|
|
|
"text", 0, NULL);
|
|
|
|
column = gtk_tree_view_get_column(GTK_TREE_VIEW(tree_view),
|
|
|
|
col_offset - 1);
|
|
|
|
gtk_tree_view_column_set_cell_data_func(column, renderer, tree_cell_renderer,
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
|
|
|
|
GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
|
|
|
g_signal_connect(tree_view, "row-expanded", G_CALLBACK(expand_tree), NULL);
|
|
|
|
g_signal_connect(tree_view, "row-collapsed", G_CALLBACK(collapse_tree), NULL);
|
|
|
|
gtk_container_add( GTK_CONTAINER(tv_scrollw), tree_view );
|
2011-08-17 19:39:34 +00:00
|
|
|
#if GTK_CHECK_VERSION(3,0,0)
|
|
|
|
gtk_widget_override_font(tree_view, user_font_get_regular());
|
|
|
|
#else
|
2012-06-16 21:39:16 +00:00
|
|
|
gtk_widget_modify_font(tree_view, user_font_get_regular());
|
2011-08-17 19:39:34 +00:00
|
|
|
#endif
|
2010-10-12 17:39:44 +00:00
|
|
|
remember_ptree_widget(tree_view);
|
|
|
|
|
|
|
|
*tree_view_p = tree_view;
|
|
|
|
|
|
|
|
return tv_scrollw;
|
2000-02-29 06:24:41 +00:00
|
|
|
}
|
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
void
|
|
|
|
expand_all_tree(proto_tree *protocol_tree _U_, GtkWidget *tree_view)
|
2002-11-03 17:38:45 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
int i;
|
2013-07-07 16:33:49 +00:00
|
|
|
|
|
|
|
for(i=0; i < num_tree_types; i++)
|
|
|
|
tree_expanded_set(i, TRUE);
|
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_view));
|
1999-09-11 12:38:18 +00:00
|
|
|
}
|
|
|
|
|
2010-04-13 17:56:59 +00:00
|
|
|
void
|
|
|
|
collapse_all_tree(proto_tree *protocol_tree _U_, GtkWidget *tree_view)
|
2002-11-03 17:38:45 +00:00
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
int i;
|
2013-07-07 16:33:49 +00:00
|
|
|
|
|
|
|
for(i=0; i < num_tree_types; i++)
|
|
|
|
tree_expanded_set(i, FALSE);
|
|
|
|
|
2010-10-12 17:39:44 +00:00
|
|
|
gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree_view));
|
1999-09-11 12:38:18 +00:00
|
|
|
}
|
|
|
|
|
2005-08-20 14:02:00 +00:00
|
|
|
static void
|
2004-05-14 18:02:38 +00:00
|
|
|
tree_view_follow_link(field_info *fi)
|
2004-05-14 15:55:37 +00:00
|
|
|
{
|
2006-09-30 14:37:09 +00:00
|
|
|
gchar *url;
|
|
|
|
|
2004-05-15 00:41:27 +00:00
|
|
|
if(fi->hfinfo->type == FT_FRAMENUM) {
|
2007-01-18 11:02:26 +00:00
|
|
|
cf_goto_frame(&cfile, fi->value.value.uinteger);
|
2004-05-14 15:55:37 +00:00
|
|
|
}
|
2006-09-30 14:37:09 +00:00
|
|
|
if(FI_GET_FLAG(fi, FI_URL) && IS_FT_STRING(fi->hfinfo->type)) {
|
2011-03-29 20:05:33 +00:00
|
|
|
url = fvalue_to_string_repr(&fi->value, FTREPR_DISPLAY, NULL);
|
|
|
|
if(url){
|
|
|
|
browser_open_url(url);
|
|
|
|
g_free(url);
|
|
|
|
}
|
2006-09-30 14:37:09 +00:00
|
|
|
}
|
2004-05-14 15:55:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-27 19:46:52 +00:00
|
|
|
/* If the user selected a position in the tree view, try to find
|
|
|
|
* the item in the GUI proto_tree that corresponds to that byte, and
|
|
|
|
* select it. */
|
2004-01-27 20:36:48 +00:00
|
|
|
gboolean
|
2004-01-27 19:46:52 +00:00
|
|
|
tree_view_select(GtkWidget *widget, GdkEventButton *event)
|
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
GtkTreeSelection *sel;
|
|
|
|
GtkTreePath *path;
|
|
|
|
|
|
|
|
if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
|
|
|
|
(gint) (((GdkEventButton *)event)->x),
|
|
|
|
(gint) (((GdkEventButton *)event)->y),
|
|
|
|
&path, NULL, NULL, NULL))
|
|
|
|
{
|
|
|
|
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
|
|
|
|
|
|
|
|
/* if that's a doubleclick, try to follow the link */
|
|
|
|
if(event->type == GDK_2BUTTON_PRESS) {
|
|
|
|
GtkTreeModel *model;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
if(gtk_tree_selection_get_selected (sel, &model, &iter)) {
|
2013-03-21 23:59:55 +00:00
|
|
|
if (event->state & GDK_SHIFT_MASK) {
|
|
|
|
new_packet_window(NULL, TRUE, FALSE);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
gtk_tree_model_get(model, &iter, 1, &fi, -1);
|
|
|
|
tree_view_follow_link(fi);
|
|
|
|
}
|
2007-11-28 12:30:18 +00:00
|
|
|
}
|
2004-01-27 19:46:52 +00:00
|
|
|
}
|
2010-10-12 17:39:44 +00:00
|
|
|
else if (((GdkEventButton *)event)->button != 1) {
|
|
|
|
/* if button == 1 gtk_tree_selection_select_path is already (or will be) called by the widget */
|
|
|
|
gtk_tree_selection_select_path(sel, path);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-01-27 19:46:52 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-01-25 19:01:57 +00:00
|
|
|
void
|
2012-07-06 07:34:08 +00:00
|
|
|
proto_tree_draw_resolve(proto_tree *protocol_tree, GtkWidget *tree_view, const e_addr_resolve *resolv)
|
2012-06-30 10:43:50 +00:00
|
|
|
{
|
|
|
|
ProtoTreeModel *model;
|
2013-07-10 01:50:27 +00:00
|
|
|
GtkTreePath *path;
|
|
|
|
GtkTreeIter iter;
|
2012-06-30 10:43:50 +00:00
|
|
|
|
|
|
|
model = proto_tree_model_new(protocol_tree, prefs.display_hidden_proto_items);
|
2012-07-24 19:49:47 +00:00
|
|
|
if (resolv)
|
|
|
|
proto_tree_model_force_resolv(PROTO_TREE_MODEL(model), resolv);
|
2012-06-30 10:43:50 +00:00
|
|
|
gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(model));
|
|
|
|
|
2013-07-10 01:50:27 +00:00
|
|
|
g_signal_handlers_block_by_func(tree_view, expand_tree, NULL);
|
|
|
|
|
|
|
|
/* modified version of gtk_tree_model_foreach */
|
|
|
|
path = gtk_tree_path_new_first();
|
|
|
|
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path))
|
2013-07-15 01:46:47 +00:00
|
|
|
check_expand_trees(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(model),
|
|
|
|
path, &iter, prefs.gui_auto_scroll_on_expand, TRUE);
|
2013-07-10 01:50:27 +00:00
|
|
|
gtk_tree_path_free(path);
|
|
|
|
|
|
|
|
g_signal_handlers_unblock_by_func(tree_view, expand_tree, NULL);
|
|
|
|
|
2012-06-30 10:43:50 +00:00
|
|
|
g_object_unref(G_OBJECT(model));
|
|
|
|
}
|
|
|
|
|
2012-06-10 22:07:54 +00:00
|
|
|
/* fill the whole protocol tree with the string values */
|
|
|
|
void
|
|
|
|
proto_tree_draw(proto_tree *protocol_tree, GtkWidget *tree_view)
|
1999-03-23 03:14:46 +00:00
|
|
|
{
|
2012-07-24 19:49:47 +00:00
|
|
|
proto_tree_draw_resolve(protocol_tree, tree_view, NULL);
|
1999-03-23 03:14:46 +00:00
|
|
|
}
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
|
2009-11-05 10:16:49 +00:00
|
|
|
void
|
|
|
|
select_bytes_view (GtkWidget *w _U_, gpointer data _U_, gint view)
|
|
|
|
{
|
2010-10-12 17:39:44 +00:00
|
|
|
if (recent.gui_bytes_view != view) {
|
|
|
|
recent.gui_bytes_view = view;
|
|
|
|
redraw_packet_bytes_all();
|
|
|
|
}
|
2009-11-05 10:16:49 +00:00
|
|
|
}
|