aboutsummaryrefslogtreecommitdiffstats
path: root/gtk/main_proto_draw.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2010-04-20 07:47:33 +0000
committerAnders Broman <anders.broman@ericsson.com>2010-04-20 07:47:33 +0000
commit132c2a43ea8fdf7fe72fda247595ff92eb04f6bc (patch)
treee033d2ceaf0766592a5dc629f34675f3e371a1c6 /gtk/main_proto_draw.c
parent1c73f4eecee7d16a9f9ed65459e09b7b00f0bfaf (diff)
downloadwireshark-132c2a43ea8fdf7fe72fda247595ff92eb04f6bc.tar.gz
wireshark-132c2a43ea8fdf7fe72fda247595ff92eb04f6bc.tar.bz2
wireshark-132c2a43ea8fdf7fe72fda247595ff92eb04f6bc.zip
From Jakub Zawadzki:
Improve bitview display https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4413 svn path=/trunk/; revision=32522
Diffstat (limited to 'gtk/main_proto_draw.c')
-rw-r--r--gtk/main_proto_draw.c312
1 files changed, 205 insertions, 107 deletions
diff --git a/gtk/main_proto_draw.c b/gtk/main_proto_draw.c
index 45b5014086..dcae76215c 100644
--- a/gtk/main_proto_draw.c
+++ b/gtk/main_proto_draw.c
@@ -85,6 +85,7 @@
#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"
+#define E_BYTE_VIEW_MASK_KEY "byte_view_mask"
#define E_BYTE_VIEW_APP_START_KEY "byte_view_app_start"
#define E_BYTE_VIEW_APP_END_KEY "byte_view_app_end"
#define E_BYTE_VIEW_ENCODE_KEY "byte_view_encode"
@@ -1091,7 +1092,131 @@ savehex_cb(GtkWidget * w _U_, gpointer data _U_)
window_destroy(savehex_dlg);
}
+static GtkTextMark *
+packet_hex_apply_reverse_tag(GtkTextBuffer *buf, int start, int end, guint32 mask, int use_digits, int create_mark)
+{
+ GtkTextIter i_start, i_stop, iter;
+
+ GtkTextTag *revstyle_tag;
+ const char *revstyle;
+
+ int per_line = 0;
+ int per_one = 0;
+ int bits_per_one = 0;
+ int hex_offset, ascii_offset;
+
+ int start_line, start_line_pos;
+ int stop_line, stop_line_pos;
+
+ if (start == -1 || end == -1)
+ return NULL;
+
+ /* Display with inverse video ? */
+ if (prefs.gui_hex_dump_highlight_style)
+ revstyle = "reverse";
+ else
+ revstyle = "bold";
+
+ revstyle_tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buf), revstyle);
+
+ switch (recent.gui_bytes_view) {
+ case BYTES_HEX:
+ per_line = BYTES_PER_LINE;
+ per_one = 2+1; /* "ff " */
+ bits_per_one = 4;
+ break;
+ case BYTES_BITS:
+ per_line = BITS_PER_LINE;
+ per_one = 8+1; /* "10101010 " */
+ bits_per_one = 1;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ start_line = start / per_line;
+ start_line_pos = start % per_line;
+
+ stop_line = end / per_line;
+ stop_line_pos = end % per_line;
+
+#define hex_fix(pos) hex_offset + (pos * per_one) + (pos / BYTE_VIEW_SEP) - (pos == per_line)
+#define ascii_fix(pos) ascii_offset + pos + (pos / BYTE_VIEW_SEP) - (pos == per_line)
+
+ hex_offset = use_digits + 2;
+ ascii_offset = hex_fix(per_line) + 2;
+ gtk_text_buffer_get_iter_at_line_index(buf, &iter, start_line, hex_fix(start_line_pos));
+
+ /* stig: it should be done only for bitview... */
+ if (mask == 0x00 || recent.gui_bytes_view != BYTES_BITS) {
+ while (start_line <= stop_line) {
+ int end_line = (start_line == stop_line) ? stop_line_pos : per_line;
+
+ if (start_line_pos == end_line) break;
+
+ /* bits/hex */
+ gtk_text_buffer_get_iter_at_line_index(buf, &i_start, start_line, hex_fix(start_line_pos));
+ gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, start_line, hex_fix(end_line)-1);
+ gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop);
+
+ /* ascii */
+ gtk_text_buffer_get_iter_at_line_index(buf, &i_start, start_line, ascii_fix(start_line_pos));
+ gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, start_line, ascii_fix(end_line));
+ gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop);
+
+ start_line_pos = 0;
+ start_line++;
+ }
+
+ } else {
+ /* XXX, merge & optimize? */
+
+ /* XXX, Spaces are not highlighted - good thing or bad? */
+ while (start_line <= stop_line) {
+ int end_line = (start_line == stop_line) ? stop_line_pos : per_line;
+ int line_pos = start_line_pos;
+
+ while (line_pos < end_line) {
+ int lop = 8 / bits_per_one;
+ int mask_per_one = (1 << bits_per_one) - 1;
+ int ascii_on = 0;
+
+ while (lop--) {
+ if ((mask & mask_per_one)) {
+ /* bits/hex */
+ gtk_text_buffer_get_iter_at_line_index(buf, &i_start, start_line, hex_fix(line_pos)+lop);
+ gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, start_line, hex_fix(line_pos)+lop+1);
+ gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop);
+
+ ascii_on = 1;
+ }
+ mask >>= bits_per_one;
+ }
+
+ /* at least one bit of ascii was one -> turn ascii on */
+ if (ascii_on) {
+ /* ascii */
+ gtk_text_buffer_get_iter_at_line_index(buf, &i_start, start_line, ascii_fix(line_pos));
+ gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, start_line, ascii_fix(line_pos)+1);
+ gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop);
+ }
+
+ if (!mask)
+ goto end;
+
+ line_pos++;
+ }
+
+ start_line_pos = 0;
+ start_line++;
+ }
+ }
+end:
+ return (create_mark) ? gtk_text_buffer_create_mark(buf, NULL, &iter, TRUE) : NULL;
+#undef hex_fix
+#undef ascii_fix
+}
/* Update the progress bar this many times when reading a file. */
#define N_PROGBAR_UPDATES 100
@@ -1112,8 +1237,7 @@ savehex_cb(GtkWidget * w _U_, gpointer data _U_)
* the hex dump column.
*/
static void
-packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
- int bend, int astart, int aend, int encoding)
+packet_hex_print_common(GtkTextBuffer *buf, GtkWidget *bv, const guint8 *pd, int len, int encoding)
{
int i = 0, j, k = 0, b, cur;
guchar line[MAX_LINES_LEN + 1];
@@ -1124,12 +1248,7 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
guchar c = '\0';
unsigned int use_digits;
- gboolean reverse, newreverse;
- GtkTextView *bv_text_view = GTK_TEXT_VIEW(bv);
- GtkTextBuffer *buf;
GtkTextIter iter;
- const char *revstyle;
- GtkTextMark *mark = NULL;
progdlg_t *progbar = NULL;
float progbar_val;
@@ -1139,26 +1258,6 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
int progbar_nextstep;
int progbar_quantum;
- buf = gtk_text_view_get_buffer(bv_text_view);
- g_object_ref(buf);
-#if 0
- gtk_text_view_set_buffer( bv_text_view, NULL); /* XXX: Apparently not a good idea; If a progress_bar
- * is displayed below in delayed_create_progress_dlg()
- * there will then be a crash internally in the gtk library.
- * (It appears that gtk_text_view_set_buffer
- * queues a callback to be run when this
- * thread is next idle. Unfortunately the call to
- * gtk_main_iteration() in delayed_create_progress_dlg()
- * causes the internal callback to be run which then
- * crashes (because the textview has no buffer ?))
- */
-#endif
- gtk_text_view_set_buffer( bv_text_view,
- gtk_text_buffer_new(NULL));/* attach a dummy buffer in place of the real buffer.
- * (XXX: Presumably this is done so there's no attempt
- * to display the real buffer until it has been
- * completely generated).
- */
gtk_text_buffer_set_text(buf, "", 0);
gtk_text_buffer_get_start_iter(buf, &iter);
@@ -1252,14 +1351,6 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
line[cur++] = ' ';
line[cur++] = ' ';
- /* Display with inverse video ? */
- if (prefs.gui_hex_dump_highlight_style)
- revstyle = "reverse";
- else
- revstyle = "bold";
-
- /* Do we start in reverse? */
- reverse = (i >= bstart && i < bend) || (i >= astart && i < aend);
j = i;
switch (recent.gui_bytes_view) {
case BYTES_HEX:
@@ -1271,11 +1362,6 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
default:
g_assert_not_reached();
}
- if (reverse) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- "plain", NULL);
- cur = 0;
- }
/* Print the hex bit */
while (i < k) {
if (i < len) {
@@ -1307,13 +1393,6 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
}
}
i++;
- newreverse = (i >= bstart && i < bend) || (i >= astart && i < aend);
- /* Have we gone from reverse to plain? */
- if (reverse && (reverse != newreverse)) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- revstyle, NULL);
- cur = 0;
- }
/* Inter byte space if not at end of line */
if (i < k) {
line[cur++] = ' ';
@@ -1322,22 +1401,6 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
line[cur++] = ' ';
}
}
- /* Have we gone from plain to reversed? */
- if (!reverse && (reverse != newreverse)) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- "plain", NULL);
- /* If [astart..aend) and [bstart..bend) are disjoint, select first one as a marker */
- if (!mark)
- mark = gtk_text_buffer_create_mark(buf, NULL, &iter, TRUE);
- cur = 0;
- }
- reverse = newreverse;
- }
- if (reverse) {
- /* Print remaining part of line */
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- revstyle, NULL);
- cur = 0;
}
/* Print some space at the end of the line */
@@ -1345,13 +1408,6 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
/* Print the ASCII bit */
i = j;
- /* Do we start in reverse? */
- reverse = (i >= bstart && i < bend) || (i >= astart && i < aend);
- if (reverse) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- "plain",NULL);
- cur = 0;
- }
while (i < k) {
if (i < len) {
@@ -1369,38 +1425,16 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
line[cur++] = ' ';
}
i++;
- newreverse = (i >= bstart && i < bend) || (i >= astart && i < aend);
- /* Have we gone from reverse to plain? */
- if (reverse && (reverse != newreverse)) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- revstyle, NULL);
-
- cur = 0;
- }
if (i < k) {
/* insert a space every BYTE_VIEW_SEP bytes */
if( ( i % BYTE_VIEW_SEP ) == 0 ) {
line[cur++] = ' ';
}
}
- /* Have we gone from plain to reversed? */
- if (!reverse && (reverse != newreverse)) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- "plain", NULL);
- cur = 0;
- }
- reverse = newreverse;
- }
- /* Print remaining part of line */
- if (reverse) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- revstyle, NULL);
- cur = 0;
}
line[cur++] = '\n';
if (cur >= (MAX_LINES_LEN - MAX_LINE_LEN)) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- "plain", NULL);
+ gtk_text_buffer_insert(buf, &iter, line, cur);
cur = 0;
}
}
@@ -1410,18 +1444,66 @@ packet_hex_print_common(GtkWidget *bv, const guint8 *pd, int len, int bstart,
if (progbar != NULL)
destroy_progress_dlg(progbar);
- /* scroll text into position */
if (cur) {
- gtk_text_buffer_insert_with_tags_by_name(buf, &iter, line, cur,
- "plain", NULL);
+ gtk_text_buffer_insert(buf, &iter, line, cur);
}
- gtk_text_view_set_buffer( bv_text_view, buf);
+}
- if (mark) {
- gtk_text_view_scroll_to_mark(bv_text_view, mark, 0.0, TRUE, 1.0, 0.0);
- gtk_text_buffer_delete_mark(buf, mark);
- }
- g_object_unref(buf);
+static void
+packet_hex_update(GtkWidget *bv, const guint8 *pd, int len, int bstart,
+ int bend, guint32 bmask, int astart, int aend, int encoding)
+{
+ GtkTextView *bv_text_view = GTK_TEXT_VIEW(bv);
+ GtkTextBuffer *buf = gtk_text_view_get_buffer(bv_text_view);
+ GtkTextMark *mark;
+ int ndigits;
+
+ GtkTextIter start, end;
+
+ g_object_ref(buf);
+
+#if 0
+ /* XXX: Apparently not a good idea; If a progress_bar
+ * is displayed below in delayed_create_progress_dlg()
+ * there will then be a crash internally in the gtk library.
+ * (It appears that gtk_text_view_set_buffer
+ * queues a callback to be run when this
+ * thread is next idle. Unfortunately the call to
+ * gtk_main_iteration() in delayed_create_progress_dlg()
+ * causes the internal callback to be run which then
+ * crashes (because the textview has no buffer ?))
+ */
+ gtk_text_view_set_buffer(bv_text_view, NULL);
+#endif
+
+ /* attach a dummy buffer in place of the real buffer.
+ * (XXX: Presumably this is done so there's no attempt
+ * to display the real buffer until it has been
+ * completely generated).
+ */
+ gtk_text_view_set_buffer(bv_text_view, gtk_text_buffer_new(NULL));
+
+ packet_hex_print_common(buf, bv, pd, len, encoding);
+
+ /* mark everything with "plain" tag */
+ gtk_text_buffer_get_start_iter(buf, &start);
+ gtk_text_buffer_get_end_iter(buf, &end);
+ gtk_text_buffer_apply_tag_by_name(buf, "plain", &start, &end);
+
+ ndigits = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_NDIGITS_KEY));
+
+ /* mark reverse tags */
+ mark = packet_hex_apply_reverse_tag(buf, bstart, bend, bmask, ndigits, 1);
+ packet_hex_apply_reverse_tag(buf, astart, aend, 0x00, ndigits, 0);
+
+ gtk_text_view_set_buffer(bv_text_view, buf);
+
+ /* scroll text into position */
+ if (mark) {
+ gtk_text_view_scroll_to_mark(bv_text_view, mark, 0.0, TRUE, 1.0, 0.0);
+ gtk_text_buffer_delete_mark(buf, mark);
+ }
+ g_object_unref(buf);
}
void
@@ -1432,31 +1514,46 @@ packet_hex_print(GtkWidget *bv, const guint8 *pd, frame_data *fd,
/* to redraw the display if preferences change. */
int bstart = -1, bend = -1, blen = -1;
+ guint32 bmask = 0x00;
int astart = -1, aend = -1, alen = -1;
if (finfo != NULL) {
bstart = finfo->start;
blen = finfo->length;
+ /* bmask = finfo->hfinfo->bitmask << finfo->hfinfo->bitshift; */ /* (value & mask) >> shift */
+ bmask = finfo->hfinfo->bitmask;
astart = finfo->appendix_start;
alen = finfo->appendix_length;
+
+ /* XXX, for now there's no support for masks && len > 1 cause of endianess problems */
+ if (blen > 1)
+ bmask = 0x00;
}
- if (bstart >= 0 && blen >= 0) {
+ if (bstart >= 0 && blen > 0) {
bend = bstart + blen;
}
- if (astart >= 0 && alen >= 0) {
+ if (astart >= 0 && alen > 0) {
aend = astart + alen;
}
+ if (bend == -1 && aend != -1) {
+ bstart = astart;
+ bmask = 0x00;
+ bend = aend;
+ astart = aend = -1;
+ }
+
/* 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_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));
- packet_hex_print_common(bv, pd, len, bstart, bend, astart, aend, fd->flags.encoding);
+ packet_hex_update(bv, pd, len, bstart, bend, bmask, astart, aend, fd->flags.encoding);
}
/*
@@ -1466,20 +1563,21 @@ packet_hex_print(GtkWidget *bv, const guint8 *pd, frame_data *fd,
void
packet_hex_reprint(GtkWidget *bv)
{
- int start, end, encoding;
+ int start, end, mask, encoding;
int astart, aend;
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));
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));
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));
- packet_hex_print_common(bv, data, len, start, end, astart, aend, encoding);
+ packet_hex_update(bv, data, len, start, end, mask, astart, aend, encoding);
}
/* List of all protocol tree widgets, so we can globally set the selection