Witness: enum witness_notifyResponse_type
[wireshark-wip.git] / ui / gtk / bytes_view.c
blobdfbbcbc316e6336895c8fac3faa2adf516c4c00f
1 /* bytes_view.c
3 * $Id$
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA.
25 /* Code based on:
26 * xtext, the text widget used by X-Chat. Peter Zelezny <zed@xchat.org>.
27 * GtkTextView. Copyright (C) 2000 Red Hat, Inc.
28 * GtkHex. Jaka Mocnik <jaka@gnu.org>.
29 * pango-layout.c: High-level layout driver. Copyright (C) 2000, 2001, 2006 Red Hat Software
32 #include "config.h"
34 #include <gtk/gtk.h>
35 #include "ui/gtk/old-gtk-compat.h"
37 #include <string.h>
39 #include "../isprint.h"
41 #include <epan/charsets.h>
42 #include <epan/packet.h>
43 #include <epan/prefs.h>
45 #include "packet_panes.h"
47 #define MARGIN 2
48 #define REFRESH_TIMEOUT 10
50 static GtkWidgetClass *parent_class = NULL;
52 struct _BytesView
54 GtkWidget widget;
56 PangoContext *context;
58 PangoFontDescription *font;
59 int font_ascent;
60 int font_descent;
61 int fontsize;
63 GtkAdjustment *vadj;
64 GtkAdjustment *hadj;
65 #if GTK_CHECK_VERSION(3, 0, 0)
66 guint hscroll_policy : 1;
67 guint vscroll_policy : 1;
68 #endif
69 gint adj_tag;
70 int max_width;
72 gboolean bold_highlight;
73 int state;
75 /* data */
76 packet_char_enc encoding; /* ASCII or EBCDIC */
77 bytes_view_type format; /* bytes in hex or bytes as bits */
78 guint8 *pd; /* packet data */
79 int len; /* length of packet data in bytes */
80 /* data-highlight (field, appendix, protocol) */
81 int start[3];
82 int end[3];
84 int per_line; /* number of bytes shown per line */
85 int use_digits; /* number of hex digits of byte offset */
88 #include "bytes_view.h"
90 typedef struct _BytesViewClass
92 GtkWidgetClass parent_class;
94 void (*set_scroll_adjustments)(BytesView *, GtkAdjustment *, GtkAdjustment *);
96 } BytesViewClass;
98 static void bytes_view_set_scroll_adjustments(BytesView *, GtkAdjustment *, GtkAdjustment *);
99 static void bytes_view_adjustment_set(BytesView *);
101 static void
102 bytes_view_init(BytesView *bv)
104 #ifdef WANT_PACKET_EDITOR
105 gtk_widget_set_can_focus(GTK_WIDGET(bv), TRUE);
106 #endif
107 bv->context = NULL;
109 bv->encoding = PACKET_CHAR_ENC_CHAR_ASCII;
110 bv->format = BYTES_HEX;
112 bv->per_line = 16;
113 bv->use_digits = 4;
115 bv->max_width = 0;
118 static void
119 bytes_view_destroy(BytesView *bv)
121 if (bv->pd) {
122 g_free(bv->pd);
123 bv->pd = NULL;
125 if (bv->adj_tag) {
126 g_source_remove(bv->adj_tag);
127 bv->adj_tag = 0;
129 if (bv->vadj) {
130 g_object_unref(G_OBJECT(bv->vadj));
131 bv->vadj = NULL;
133 if (bv->hadj) {
134 g_object_unref(G_OBJECT(bv->hadj));
135 bv->hadj = NULL;
137 if (bv->font) {
138 pango_font_description_free(bv->font);
139 bv->font = NULL;
141 if (bv->context) {
142 g_object_unref(bv->context);
143 bv->context = NULL;
147 #if GTK_CHECK_VERSION(3, 0, 0)
148 static void
149 bytes_view_destroy_widget(GtkWidget *widget)
151 bytes_view_destroy(BYTES_VIEW(widget));
153 GTK_WIDGET_CLASS(parent_class)->destroy(widget);
156 #else
158 static void
159 bytes_view_destroy_object(GtkObject *object)
161 bytes_view_destroy(BYTES_VIEW(object));
163 if (GTK_OBJECT_CLASS(parent_class)->destroy)
164 (*GTK_OBJECT_CLASS(parent_class)->destroy)(object);
167 #endif
169 static void
170 bytes_view_ensure_layout(BytesView *bv)
172 if (bv->context == NULL) {
173 bv->context = gtk_widget_get_pango_context(GTK_WIDGET(bv));
174 g_object_ref(bv->context);
177 PangoLanguage *lang;
178 PangoFontMetrics *metrics;
180 /* vte and xchat does it this way */
181 lang = pango_context_get_language(bv->context);
182 metrics = pango_context_get_metrics(bv->context, bv->font, lang);
183 bv->font_ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
184 bv->font_descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
185 pango_font_metrics_unref(metrics);
187 bv->fontsize = bv->font_ascent + bv->font_descent;
189 g_assert(bv->context);
190 bytes_view_adjustment_set(bv);
194 static void
195 bytes_view_realize(GtkWidget *widget)
197 BytesView *bv;
198 GdkWindowAttr attributes;
199 GtkAllocation allocation;
200 GdkWindow *win;
202 #if GTK_CHECK_VERSION(3, 0, 0)
203 GtkStyleContext *context;
204 #endif
206 _gtk_widget_set_realized_true(widget);
207 bv = BYTES_VIEW(widget);
209 gtk_widget_get_allocation(widget, &allocation);
211 attributes.window_type = GDK_WINDOW_CHILD;
212 attributes.x = allocation.x;
213 attributes.y = allocation.y;
214 attributes.width = allocation.width;
215 attributes.height = allocation.height;
216 attributes.wclass = GDK_INPUT_OUTPUT;
217 attributes.visual = gtk_widget_get_visual(widget);
218 attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK;
220 #if !GTK_CHECK_VERSION(3, 0, 0)
221 attributes.colormap = gtk_widget_get_colormap(widget);
223 win = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
224 #else
225 win = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
226 #endif
228 gtk_widget_set_window(widget, win);
230 #if GTK_CHECK_VERSION(3, 8, 0)
231 gtk_widget_register_window(widget, win);
232 #else
233 gdk_window_set_user_data(win, widget);
234 #endif
236 #if !GTK_CHECK_VERSION(3, 0, 0) /* XXX, check */
237 gdk_window_set_back_pixmap(win, NULL, FALSE);
238 #endif
240 #if GTK_CHECK_VERSION(3, 0, 0)
241 context = gtk_widget_get_style_context(widget);
242 gtk_style_context_add_class(context, GTK_STYLE_CLASS_VIEW);
243 /* gtk_style_context_add_class(context, GTK_STYLE_CLASS_ENTRY); */
245 #elif GTK_CHECK_VERSION(2, 20, 0)
246 gtk_widget_style_attach(widget);
247 #else
248 widget->style = gtk_style_attach(widget->style, win);
249 #endif
250 bytes_view_ensure_layout(bv);
253 static void
254 bytes_view_unrealize(GtkWidget *widget)
256 BytesView *bv = BYTES_VIEW(widget);
258 if (bv->context) {
259 g_object_unref(bv->context);
260 bv->context = NULL;
262 /* if there are still events in the queue, this'll avoid segfault */
263 #if !GTK_CHECK_VERSION(3, 8, 0)
264 gdk_window_set_user_data(gtk_widget_get_window(widget), NULL);
265 #endif
267 if (parent_class->unrealize)
268 (*GTK_WIDGET_CLASS(parent_class)->unrealize)(widget);
271 static GtkAdjustment *
272 bytes_view_ensure_vadj(BytesView *bv)
274 if (bv->vadj == NULL) {
275 bytes_view_set_scroll_adjustments(bv, bv->hadj, bv->vadj);
276 g_assert(bv->vadj != NULL);
278 return bv->vadj;
281 static GtkAdjustment *
282 bytes_view_ensure_hadj(BytesView *bv)
284 if (bv->hadj == NULL) {
285 bytes_view_set_scroll_adjustments(bv, bv->hadj, bv->vadj);
286 g_assert(bv->hadj != NULL);
288 return bv->hadj;
291 static gboolean
292 bytes_view_scroll(GtkWidget *widget, GdkEventScroll *event)
294 BytesView *bv = BYTES_VIEW(widget);
296 gdouble new_value;
298 if (event->direction == GDK_SCROLL_UP) { /* mouse wheel pageUp */
299 bytes_view_ensure_vadj(bv);
301 new_value = gtk_adjustment_get_value(bv->vadj) - (gtk_adjustment_get_page_increment(bv->vadj) / 10);
302 if (new_value < gtk_adjustment_get_lower(bv->vadj))
303 new_value = gtk_adjustment_get_lower(bv->vadj);
304 gtk_adjustment_set_value(bv->vadj, new_value);
306 } else if (event->direction == GDK_SCROLL_DOWN) { /* mouse wheel pageDn */
307 bytes_view_ensure_vadj(bv);
309 new_value = gtk_adjustment_get_value(bv->vadj) + (gtk_adjustment_get_page_increment(bv->vadj) / 10);
310 if (new_value > (gtk_adjustment_get_upper(bv->vadj) - gtk_adjustment_get_page_size(bv->vadj)))
311 new_value = gtk_adjustment_get_upper(bv->vadj) - gtk_adjustment_get_page_size(bv->vadj);
312 gtk_adjustment_set_value(bv->vadj, new_value);
314 return FALSE;
317 static void
318 bytes_view_allocate(GtkWidget *widget, GtkAllocation *allocation)
320 gtk_widget_set_allocation(widget, allocation);
322 if (gtk_widget_get_realized(widget)) {
323 BytesView *bv = BYTES_VIEW(widget);
325 gdk_window_move_resize(gtk_widget_get_window(widget), allocation->x, allocation->y, allocation->width, allocation->height);
326 bytes_view_adjustment_set(bv);
330 #if GTK_CHECK_VERSION(3, 0, 0)
331 static void
332 bytes_view_get_preferred_width(GtkWidget *widget _U_, gint *minimum, gint *natural)
334 *minimum = *natural = 200;
337 static void
338 bytes_view_get_preferred_height(GtkWidget *widget _U_, gint *minimum, gint *natural)
340 *minimum = *natural = 90;
343 #else
345 static void
346 bytes_view_size_request(GtkWidget *widget _U_, GtkRequisition *requisition)
348 requisition->width = 200;
349 requisition->height = 90;
351 #endif
353 static GSList *
354 _pango_runs_build(BytesView *bv, const char *str, int len)
356 GSList *runs = NULL;
358 PangoAttrList *attrs;
359 PangoAttrIterator *iter;
361 GList *run_list;
362 GList *tmp_list;
364 attrs = pango_attr_list_new();
365 pango_attr_list_insert_before(attrs, pango_attr_font_desc_new(bv->font));
367 iter = pango_attr_list_get_iterator(attrs);
369 run_list = pango_itemize(bv->context, str, 0, len, attrs, iter);
371 for (tmp_list = run_list; tmp_list; tmp_list = tmp_list->next) {
372 PangoLayoutRun *run = g_slice_new(PangoLayoutRun);
373 PangoItem *run_item = (PangoItem *)tmp_list->data;
375 run->item = run_item;
377 /* XXX pango_layout_get_item_properties(run_item, &state->properties); */
379 run->glyphs = pango_glyph_string_new();
380 pango_shape(str + run_item->offset, run_item->length, &run_item->analysis, run->glyphs);
382 runs = g_slist_prepend(runs, run);
385 g_list_free(run_list);
387 pango_attr_iterator_destroy(iter);
388 pango_attr_list_unref(attrs);
390 return g_slist_reverse(runs);
393 static int
394 _pango_glyph_string_to_pixels(PangoGlyphString *glyphs, PangoFont *font _U_)
396 #if PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 14
397 return pango_glyph_string_get_width(glyphs) / PANGO_SCALE;
398 #else
399 PangoRectangle logical_rect;
401 pango_glyph_string_extents(glyphs, font, NULL, &logical_rect);
402 /* pango_extents_to_pixels(&logical_rect, NULL); */
404 return (logical_rect.width / PANGO_SCALE);
405 #endif
408 static int
409 xtext_draw_layout_line(cairo_t *cr, gint x, gint y, GSList *runs)
411 while (runs) {
412 PangoLayoutRun *run = (PangoLayoutRun *)runs->data;
414 cairo_move_to(cr, x, y);
415 pango_cairo_show_glyph_string(cr, run->item->analysis.font, run->glyphs);
417 x += _pango_glyph_string_to_pixels(run->glyphs, run->item->analysis.font);
418 runs = runs->next;
420 return x;
423 static int
424 _pango_runs_width(GSList *runs)
426 int width = 0;
428 while (runs) {
429 PangoLayoutRun *run = (PangoLayoutRun *)runs->data;
431 width += _pango_glyph_string_to_pixels(run->glyphs, run->item->analysis.font);
432 runs = runs->next;
434 return width;
437 static void
438 _pango_runs_free(GSList *runs)
440 GSList *list = runs;
442 while (list) {
443 PangoLayoutRun *run = (PangoLayoutRun *)list->data;
445 pango_item_free(run->item);
446 pango_glyph_string_free(run->glyphs);
447 g_slice_free(PangoLayoutRun, run);
449 list = list->next;
451 g_slist_free(runs);
454 typedef int bytes_view_line_cb(BytesView *, void *data, int x, int arg1, const char *str, int len);
456 static int
457 bytes_view_flush_render(BytesView *bv, void *data, int x, int y, const char *str, int len)
459 cairo_t *cr = (cairo_t *)data;
460 GSList *line_runs;
461 int str_width;
463 #if GTK_CHECK_VERSION(3, 0, 0)
464 GtkStyleContext *context;
465 GdkRGBA bg_color, fg_color;
466 #endif
468 if (len < 1)
469 return 0;
471 line_runs = _pango_runs_build(bv, str, len);
473 /* XXX, cliping */
475 #if GTK_CHECK_VERSION(3, 0, 0)
476 context = gtk_widget_get_style_context(GTK_WIDGET(bv));
477 #endif
479 if (bv->state == GTK_STATE_SELECTED || bv->state == GTK_STATE_INSENSITIVE) {
480 str_width = _pango_runs_width(line_runs);
482 /* background */
483 #if GTK_CHECK_VERSION(3, 0, 0)
484 gtk_style_context_get_background_color(context, (GtkStateFlags)( (bv->state == GTK_STATE_SELECTED ? GTK_STATE_FLAG_FOCUSED : 0) | GTK_STATE_FLAG_SELECTED), &bg_color);
485 gdk_cairo_set_source_rgba(cr, &bg_color);
486 #else
487 gdk_cairo_set_source_color(cr, &gtk_widget_get_style(GTK_WIDGET(bv))->base[bv->state]);
488 #endif
489 cairo_rectangle(cr, x, y - bv->font_ascent, str_width, bv->fontsize);
490 cairo_fill(cr);
493 /* text */
494 #if GTK_CHECK_VERSION(3, 0, 0)
495 gtk_style_context_get_color(context, (GtkStateFlags)(GTK_STATE_FLAG_FOCUSED | (bv->state == GTK_STATE_SELECTED ? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_NORMAL)), &fg_color);
496 gdk_cairo_set_source_rgba(cr, &fg_color);
497 #else
498 gdk_cairo_set_source_color(cr, &gtk_widget_get_style(GTK_WIDGET(bv))->text[bv->state]);
499 #endif
500 str_width = xtext_draw_layout_line(cr, x, y, line_runs)-x;
502 _pango_runs_free(line_runs);
504 return str_width;
507 static int
508 _pango_runs_find_index(GSList *runs, int x_pos, const char *str)
510 int start_pos = 0;
512 while (runs) {
513 PangoLayoutRun *run = (PangoLayoutRun *)runs->data;
514 int width;
516 width = _pango_glyph_string_to_pixels(run->glyphs, run->item->analysis.font);
518 if (x_pos >= start_pos && x_pos < start_pos + width) {
519 gboolean char_trailing;
520 int pos;
522 pango_glyph_string_x_to_index(run->glyphs,
523 (char *) str + run->item->offset, run->item->length,
524 &run->item->analysis,
525 (x_pos - start_pos) * PANGO_SCALE,
526 &pos, &char_trailing);
528 return run->item->offset + pos;
531 start_pos += width;
532 runs = runs->next;
534 return -1;
537 static int
538 bytes_view_flush_pos(BytesView *bv, void *data, int x, int search_x, const char *str, int len)
540 int *pos_x = (int *)data;
541 GSList *line_runs;
542 int line_width;
544 if (len < 1)
545 return 0;
547 line_runs = _pango_runs_build(bv, str, len);
549 line_width = _pango_runs_width(line_runs);
551 if (x <= search_x && x + line_width > search_x) {
552 int off_x = search_x - x;
553 int pos_run;
555 if ((pos_run = _pango_runs_find_index(line_runs, off_x, str)) != -1)
556 *pos_x = (-*pos_x) + pos_run;
558 return -1; /* terminate */
559 } else
560 *pos_x -= len;
562 _pango_runs_free(line_runs);
564 return line_width;
567 static void
568 bytes_view_render_state(BytesView *bv, int state)
570 g_assert(state == GTK_STATE_NORMAL || state == GTK_STATE_SELECTED || state == GTK_STATE_INSENSITIVE);
572 if (bv->bold_highlight) {
573 pango_font_description_set_weight(bv->font,
574 (state == GTK_STATE_SELECTED) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
575 bv->state = GTK_STATE_NORMAL;
576 } else
577 bv->state = state;
580 #define BYTE_VIEW_SEP 8 /* insert a space every BYTE_VIEW_SEP bytes */
582 static void
583 _bytes_view_line_common(BytesView *bv, void *data, const int org_off, int xx, int arg1, bytes_view_line_cb flush)
585 static const guchar hexchars[16] = {
586 '0', '1', '2', '3', '4', '5', '6', '7',
587 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
589 const guint8 *pd = bv->pd;
590 const int len = bv->len;
592 int state;
594 char str[128];
595 int cur = 0;
597 int off;
598 guchar c;
599 int byten;
600 int j;
602 int scroll_x;
603 int dx;
605 g_assert(org_off >= 0);
607 scroll_x = (int) gtk_adjustment_get_value(bytes_view_ensure_hadj(bv));
609 state = GTK_STATE_NORMAL;
610 bytes_view_render_state(bv, GTK_STATE_NORMAL);
612 /* Print the line number */
613 j = bv->use_digits;
614 do {
615 j--;
616 c = (org_off >> (j*4)) & 0xF;
617 str[cur++] = hexchars[c];
618 } while (j != 0);
619 str[cur++] = ' ';
620 str[cur++] = ' ';
622 /* Print the hex bit */
623 for (byten = 0, off = org_off; byten < bv->per_line; byten++) {
624 gboolean byte_highlighted =
625 (off >= bv->start[0] && off < bv->end[0]) ||
626 (off >= bv->start[1] && off < bv->end[1]);
627 gboolean proto_byte_highlighted =
628 (off >= bv->start[2] && off < bv->end[2]);
630 int state_cur = (off < len && byte_highlighted) ?
631 GTK_STATE_SELECTED :
632 (off < len && proto_byte_highlighted) ?
633 GTK_STATE_INSENSITIVE :
634 GTK_STATE_NORMAL;
636 if (state_cur != state) {
637 /* ok, we want to put space, we prefer to put it in STATE_NORMAL or STATE_INSENSITIVE */
638 int space_now = (state_cur != GTK_STATE_NORMAL && state_cur != GTK_STATE_INSENSITIVE)
639 || state == GTK_STATE_NORMAL;
641 if (space_now && byten) {
642 str[cur++] = ' ';
643 /* insert a space every BYTE_VIEW_SEP bytes */
644 if ((off % BYTE_VIEW_SEP) == 0)
645 str[cur++] = ' ';
648 if ((dx = flush(bv, data, xx - scroll_x, arg1, str, cur)) < 0)
649 return;
650 xx += dx;
651 cur = 0;
652 bytes_view_render_state(bv, state_cur);
653 state = state_cur;
655 if (!space_now && byten) {
656 str[cur++] = ' ';
657 /* insert a space every BYTE_VIEW_SEP bytes */
658 if ((off % BYTE_VIEW_SEP) == 0)
659 str[cur++] = ' ';
662 } else if (byten) {
663 str[cur++] = ' ';
664 /* insert a space every BYTE_VIEW_SEP bytes */
665 if ((off % BYTE_VIEW_SEP) == 0)
666 str[cur++] = ' ';
669 if (off < len) {
670 switch (bv->format) {
671 case BYTES_HEX:
672 str[cur++] = hexchars[(pd[off] & 0xf0) >> 4];
673 str[cur++] = hexchars[pd[off] & 0x0f];
674 break;
675 case BYTES_BITS:
676 /* XXX, bitmask */
677 for (j = 7; j >= 0; j--)
678 str[cur++] = (pd[off] & (1 << j)) ? '1' : '0';
679 break;
681 } else {
682 switch (bv->format) {
683 case BYTES_HEX:
684 str[cur++] = ' ';
685 str[cur++] = ' ';
686 break;
687 case BYTES_BITS:
688 for (j = 7; j >= 0; j--)
689 str[cur++] = ' ';
690 break;
693 off++;
696 if (state != GTK_STATE_NORMAL) {
697 if ((dx = flush(bv, data, xx - scroll_x, arg1, str, cur)) < 0)
698 return;
699 xx += dx;
700 cur = 0;
701 bytes_view_render_state(bv, GTK_STATE_NORMAL);
702 state = GTK_STATE_NORMAL;
705 /* Print some space at the end of the line */
706 str[cur++] = ' '; str[cur++] = ' '; str[cur++] = ' ';
708 /* Print the ASCII bit */
709 for (byten = 0, off = org_off; byten < bv->per_line; byten++) {
710 gboolean byte_highlighted =
711 (off >= bv->start[0] && off < bv->end[0]) ||
712 (off >= bv->start[1] && off < bv->end[1]);
713 gboolean proto_byte_highlighted =
714 (off >= bv->start[2] && off < bv->end[2]);
716 int state_cur = (off < len && byte_highlighted) ?
717 GTK_STATE_SELECTED :
718 (off < len && proto_byte_highlighted) ?
719 GTK_STATE_INSENSITIVE :
720 GTK_STATE_NORMAL;
722 if (state_cur != state) {
723 int space_now = (state_cur != GTK_STATE_NORMAL && state_cur != GTK_STATE_INSENSITIVE)
724 || state == GTK_STATE_NORMAL;
726 if (space_now && byten) {
727 /* insert a space every BYTE_VIEW_SEP bytes */
728 if ((off % BYTE_VIEW_SEP) == 0)
729 str[cur++] = ' ';
732 if ((dx = flush(bv, data, xx - scroll_x, arg1, str, cur)) < 0)
733 return;
734 xx += dx;
735 cur = 0;
736 bytes_view_render_state(bv, state_cur);
737 state = state_cur;
739 if (!space_now && byten) {
740 /* insert a space every BYTE_VIEW_SEP bytes */
741 if ((off % BYTE_VIEW_SEP) == 0)
742 str[cur++] = ' ';
745 } else if (byten) {
746 /* insert a space every BYTE_VIEW_SEP bytes */
747 if ((off % BYTE_VIEW_SEP) == 0)
748 str[cur++] = ' ';
751 if (off < len) {
752 c = (bv->encoding == PACKET_CHAR_ENC_CHAR_EBCDIC) ?
753 EBCDIC_to_ASCII1(pd[off]) :
754 pd[off];
756 str[cur++] = isprint(c) ? c : '.';
757 } else
758 str[cur++] = ' ';
760 off++;
763 if (cur) {
764 if ((dx = flush(bv, data, xx - scroll_x, arg1, str, cur)) < 0)
765 return;
766 xx += dx;
767 /* cur = 0; */
770 if (state != GTK_STATE_NORMAL) {
771 bytes_view_render_state(bv, GTK_STATE_NORMAL);
772 /* state = GTK_STATE_NORMAL; */
775 if (bv->max_width < xx)
776 bv->max_width = xx;
779 static void
780 _bytes_view_render_line(BytesView *bv, cairo_t *cr, const int org_off, int yy)
782 _bytes_view_line_common(bv, cr, org_off, MARGIN, yy, bytes_view_flush_render);
785 static int
786 _bytes_view_find_pos(BytesView *bv, const int org_off, int search_x)
788 int pos_x = 0;
790 _bytes_view_line_common(bv, &pos_x, org_off, MARGIN, search_x, bytes_view_flush_pos);
792 return pos_x;
795 static void
796 bytes_view_render(BytesView *bv, cairo_t *cr, GdkRectangle *area)
798 const int old_max_width = bv->max_width;
800 int width, height;
801 int y;
802 int off;
804 guint line, lines_max;
805 guint lines_max_full;
807 #if GTK_CHECK_VERSION(3, 0, 0)
808 GtkStyleContext *context;
809 GdkRGBA bg_color;
810 #endif
812 if (!gtk_widget_get_realized(GTK_WIDGET(bv)))
813 return;
815 bytes_view_ensure_layout(bv);
817 #if GTK_CHECK_VERSION(3, 0, 0)
818 width = gtk_widget_get_allocated_width(GTK_WIDGET(bv));
819 height = gtk_widget_get_allocated_height(GTK_WIDGET(bv));
820 #elif GTK_CHECK_VERSION(2,24,0)
821 width = gdk_window_get_width(gtk_widget_get_window(GTK_WIDGET(bv)));
822 height = gdk_window_get_height(gtk_widget_get_window(GTK_WIDGET(bv)));
823 #else
824 gdk_drawable_get_size(gtk_widget_get_window(GTK_WIDGET(bv)), &width, &height);
825 #endif
827 if (width < 32 + MARGIN || height < bv->fontsize)
828 return;
830 if (area) {
831 line = area->y / bv->fontsize;
832 lines_max = 1 + (area->y + area->height) / bv->fontsize;
833 } else {
834 line = 0;
835 lines_max = (guint) -1;
837 /* g_print("from %d to %d\n", line, lines_max); */
839 y = (bv->fontsize * line);
841 /* clear */
842 #if GTK_CHECK_VERSION(3, 0, 0)
843 context = gtk_widget_get_style_context(GTK_WIDGET(bv));
844 gtk_style_context_get_background_color(context, (GtkStateFlags)(GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_NORMAL), &bg_color);
845 gdk_cairo_set_source_rgba(cr, &bg_color);
846 #else
847 gdk_cairo_set_source_color(cr, &gtk_widget_get_style(GTK_WIDGET(bv))->base[GTK_STATE_NORMAL]);
848 #endif
849 if (area)
850 cairo_rectangle(cr, area->x, area->y, area->x + area->width, area->y + area->height);
851 else
852 cairo_rectangle(cr, 0, 0, width, height);
853 cairo_fill(cr);
855 if (bv->pd) {
856 guint real_line = line + (guint) gtk_adjustment_get_value(bytes_view_ensure_vadj(bv));
858 lines_max_full = (height / bv->fontsize) + 1;
859 if (lines_max_full < lines_max)
860 lines_max = lines_max_full;
862 off = real_line * bv->per_line;
864 while (off < bv->len) {
865 _bytes_view_render_line(bv, cr, off, y + bv->font_ascent);
866 line++;
867 if (line >= lines_max)
868 break;
870 off += bv->per_line;
871 y += bv->fontsize;
875 if (old_max_width != bv->max_width)
876 bytes_view_adjustment_set(bv);
879 static void
880 bytes_view_render_full(BytesView *bv)
882 cairo_t *cr;
884 if (bv->adj_tag) {
885 g_source_remove(bv->adj_tag);
886 bv->adj_tag = 0;
889 cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(bv)));
890 bytes_view_render(bv, cr, NULL);
891 cairo_destroy(cr);
894 #if GTK_CHECK_VERSION(3, 0, 0)
895 static gboolean
896 bytes_view_draw(GtkWidget *widget, cairo_t *cr)
898 GdkRectangle area;
900 gdk_cairo_get_clip_rectangle(cr, &area);
902 bytes_view_render(BYTES_VIEW(widget), cr, &area);
903 return FALSE;
906 #else
908 static gboolean
909 bytes_view_expose(GtkWidget *widget, GdkEventExpose *event)
911 BytesView *bv = BYTES_VIEW(widget);
912 cairo_t *cr;
914 cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(bv)));
916 gdk_cairo_region(cr, event->region);
917 cairo_clip(cr);
919 bytes_view_render(bv, cr, &event->area);
921 cairo_destroy(cr);
922 return FALSE;
925 #endif
927 #if !GTK_CHECK_VERSION(2, 14, 0)
928 static void
929 _gtk_adjustment_configure(GtkAdjustment *adj,
930 gdouble value,
931 gdouble lower,
932 gdouble upper,
933 gdouble step_increment,
934 gdouble page_increment,
935 gdouble page_size)
937 adj->value = value;
938 adj->lower = lower;
939 adj->upper = upper;
940 adj->step_increment = step_increment;
941 adj->page_increment = page_increment;
942 adj->page_size = page_size;
944 gtk_adjustment_changed(adj);
947 #elif GTK_CHECK_VERSION(3, 0, 0)
949 #define _gtk_adjustment_configure(adj, val, low, up, step, page, size) \
950 gtk_adjustment_configure(adj, val, low, MAX((up), (size)), step, page, size)
952 #else
954 #define _gtk_adjustment_configure(adj, val, low, up, step, page, size) \
955 gtk_adjustment_configure(adj, val, low, up, step, page, size)
957 #endif
960 static void
961 bytes_view_adjustment_set(BytesView *bv)
963 GtkAllocation allocation;
964 double lower, upper, page_size, step_increment, page_increment, value;
966 if (bv->vadj == NULL || bv->hadj == NULL)
967 return;
969 if (bv->context == NULL) {
970 bytes_view_ensure_layout(bv);
971 /* bytes_view_ensure_layout will call bytes_view_adjustment_set() again */
972 return;
975 gtk_widget_get_allocation(GTK_WIDGET(bv), &allocation);
977 if (bv->vadj) {
978 lower = 0;
979 upper = (int) (bv->len / bv->per_line);
980 if ((bv->len % bv->per_line))
981 upper++;
983 page_size = (allocation.height - bv->font_descent) / bv->fontsize;
984 page_increment = page_size;
985 step_increment = 1;
987 value = gtk_adjustment_get_value(bv->vadj);
989 if (value > upper - page_size)
990 value = upper - page_size;
992 if (value < 0)
993 value = 0;
995 _gtk_adjustment_configure(bv->vadj, value, lower, upper, step_increment, page_increment, page_size);
998 if (bv->hadj) {
999 lower = 0;
1000 upper = bv->max_width;
1002 page_size = allocation.width;
1003 page_increment = page_size;
1004 step_increment = page_size / 10.0;
1006 value = gtk_adjustment_get_value(bv->hadj);
1008 if (value > upper - page_size)
1009 value = upper - page_size;
1011 if (value < 0)
1012 value = 0;
1014 _gtk_adjustment_configure(bv->hadj, value, lower, upper, step_increment, page_increment, page_size);
1018 static gint
1019 bytes_view_adjustment_timeout(BytesView *bv)
1021 bv->adj_tag = 0;
1022 bytes_view_render_full(bv);
1023 return 0;
1026 static void
1027 bytes_view_adjustment_changed(GtkAdjustment *adj, BytesView *bv)
1029 /* delay rendering when scrolling (10ms) */
1030 if (adj && ((adj == bv->vadj) || (adj == bv->hadj))) {
1031 if (!bv->adj_tag)
1032 bv->adj_tag = g_timeout_add(REFRESH_TIMEOUT, (GSourceFunc) bytes_view_adjustment_timeout, bv);
1036 static void
1037 bytes_view_set_scroll_adjustments(BytesView *bv, GtkAdjustment *hadj, GtkAdjustment *vadj)
1039 gboolean need_adjust = FALSE;
1041 g_return_if_fail(!hadj || GTK_IS_ADJUSTMENT(hadj));
1042 g_return_if_fail(!vadj || GTK_IS_ADJUSTMENT(vadj));
1044 if (!vadj)
1045 vadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1047 if (!hadj)
1048 hadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1050 if (bv->vadj && (bv->vadj != vadj)) {
1051 g_signal_handlers_disconnect_by_func(bv->vadj, bytes_view_adjustment_changed, bv);
1052 g_object_unref(bv->vadj);
1054 if (bv->vadj != vadj) {
1055 bv->vadj = vadj;
1056 g_object_ref_sink(bv->vadj);
1058 g_signal_connect(bv->vadj, "value-changed", G_CALLBACK(bytes_view_adjustment_changed), bv);
1059 need_adjust = TRUE;
1060 #if GTK_CHECK_VERSION(3, 0, 0)
1061 g_object_notify(G_OBJECT(bv), "vadjustment");
1062 #endif
1065 if (bv->hadj && (bv->hadj != hadj)) {
1066 g_signal_handlers_disconnect_by_func(bv->hadj, bytes_view_adjustment_changed, bv);
1067 g_object_unref(bv->hadj);
1069 if (bv->hadj != hadj) {
1070 bv->hadj = hadj;
1071 g_object_ref_sink(bv->hadj);
1073 g_signal_connect(bv->hadj, "value-changed", G_CALLBACK(bytes_view_adjustment_changed), bv);
1074 need_adjust = TRUE;
1075 #if GTK_CHECK_VERSION(3, 0, 0)
1076 g_object_notify(G_OBJECT(bv), "hadjustment");
1077 #endif
1080 if (need_adjust)
1081 bytes_view_adjustment_set(bv);
1084 #if GTK_CHECK_VERSION(3, 0, 0)
1085 enum {
1086 PROP_0,
1087 PROP_HADJUSTMENT,
1088 PROP_VADJUSTMENT,
1089 PROP_HSCROLL_POLICY,
1090 PROP_VSCROLL_POLICY
1093 static void
1094 bytes_view_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
1096 BytesView *bv = BYTES_VIEW(object);
1098 switch (prop_id) {
1099 case PROP_HADJUSTMENT:
1100 bytes_view_set_scroll_adjustments(bv, (GtkAdjustment *)g_value_get_object(value), bv->vadj);
1101 break;
1103 case PROP_VADJUSTMENT:
1104 bytes_view_set_scroll_adjustments(bv, bv->hadj, (GtkAdjustment *)g_value_get_object(value));
1105 break;
1107 case PROP_HSCROLL_POLICY:
1108 bv->hscroll_policy = g_value_get_enum(value);
1109 gtk_widget_queue_resize(GTK_WIDGET(bv));
1110 break;
1112 case PROP_VSCROLL_POLICY:
1113 bv->vscroll_policy = g_value_get_enum(value);
1114 gtk_widget_queue_resize(GTK_WIDGET(bv));
1115 break;
1117 default:
1118 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1119 break;
1123 static void
1124 bytes_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
1126 BytesView *bv = BYTES_VIEW(object);
1128 switch (prop_id) {
1129 case PROP_HADJUSTMENT:
1130 g_value_set_object(value, bv->hadj);
1131 break;
1133 case PROP_VADJUSTMENT:
1134 g_value_set_object(value, bv->vadj);
1135 break;
1137 case PROP_HSCROLL_POLICY:
1138 g_value_set_enum(value, bv->hscroll_policy);
1139 break;
1141 case PROP_VSCROLL_POLICY:
1142 g_value_set_enum(value, bv->vscroll_policy);
1143 break;
1145 default:
1146 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1147 break;
1151 #else
1153 /* bv_VOID__OBJECT_OBJECT() generated by:
1154 * $ echo 'VOID:OBJECT,OBJECT' | glib-genmarshal --prefix=bv --body
1155 * (glib-genmarshal version 2.32.4)
1156 * I *really hope* it's portable over platforms and can be put generated.
1159 static void
1160 bv_VOID__OBJECT_OBJECT(GClosure *closure, GValue *return_value _U_, guint n_params, const GValue *param_values, gpointer hint _U_, gpointer marshal_data)
1162 typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT)(gpointer, gpointer, gpointer, gpointer);
1164 register GMarshalFunc_VOID__OBJECT_OBJECT callback;
1165 register GCClosure *cc = (GCClosure*) closure;
1166 register gpointer data1, data2;
1168 g_return_if_fail(n_params == 3);
1170 if (G_CCLOSURE_SWAP_DATA(closure)) {
1171 data1 = closure->data;
1172 data2 = g_value_peek_pointer(param_values + 0);
1173 } else {
1174 data1 = g_value_peek_pointer(param_values + 0);
1175 data2 = closure->data;
1177 callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
1179 callback(data1, g_value_get_object(param_values + 1), g_value_get_object(param_values + 2), data2);
1182 #endif
1184 static void
1185 bytes_view_class_init(BytesViewClass *klass)
1187 #if !GTK_CHECK_VERSION(3, 0, 0)
1188 GtkObjectClass *object_class;
1189 #endif
1190 GtkWidgetClass *widget_class;
1192 parent_class = (GtkWidgetClass *) g_type_class_peek_parent(klass);
1194 #if !GTK_CHECK_VERSION(3, 0, 0)
1195 object_class = (GtkObjectClass *) klass;
1196 #endif
1197 widget_class = (GtkWidgetClass *) klass;
1199 #if GTK_CHECK_VERSION(3, 0, 0)
1200 widget_class->destroy = bytes_view_destroy_widget;
1201 #else
1202 object_class->destroy = bytes_view_destroy_object;
1203 #endif
1204 widget_class->realize = bytes_view_realize;
1205 widget_class->unrealize = bytes_view_unrealize;
1206 #if GTK_CHECK_VERSION(3, 0, 0)
1207 widget_class->get_preferred_width = bytes_view_get_preferred_width;
1208 widget_class->get_preferred_height = bytes_view_get_preferred_height;
1209 #else
1210 widget_class->size_request = bytes_view_size_request;
1211 #endif
1212 widget_class->size_allocate = bytes_view_allocate;
1214 #if GTK_CHECK_VERSION(3, 0, 0)
1215 widget_class->draw = bytes_view_draw;
1216 #else
1217 widget_class->expose_event = bytes_view_expose;
1218 #endif
1220 widget_class->scroll_event = bytes_view_scroll;
1222 #if GTK_CHECK_VERSION(3, 0, 0)
1224 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1226 gobject_class->set_property = bytes_view_set_property;
1227 gobject_class->get_property = bytes_view_get_property;
1229 /* XXX, move some code from widget->destroy to gobject->finalize? */
1230 /* gobject_class->finalize = bytes_view_finalize; */
1232 g_object_class_override_property(gobject_class, PROP_HADJUSTMENT, "hadjustment");
1233 g_object_class_override_property(gobject_class, PROP_VADJUSTMENT, "vadjustment");
1234 g_object_class_override_property(gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy");
1235 g_object_class_override_property(gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy");
1237 #else
1238 klass->set_scroll_adjustments = bytes_view_set_scroll_adjustments;
1240 widget_class->set_scroll_adjustments_signal =
1241 g_signal_new(g_intern_static_string("set-scroll-adjustments"),
1242 G_OBJECT_CLASS_TYPE(object_class),
1243 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1244 G_STRUCT_OFFSET(BytesViewClass, set_scroll_adjustments),
1245 NULL, NULL,
1246 bv_VOID__OBJECT_OBJECT,
1247 G_TYPE_NONE, 2,
1248 GTK_TYPE_ADJUSTMENT,
1249 GTK_TYPE_ADJUSTMENT);
1250 #endif
1253 GType
1254 bytes_view_get_type(void)
1256 static GType bytes_view_gtype = 0;
1258 if (!bytes_view_gtype) {
1259 static const GTypeInfo bytes_view_info = {
1260 sizeof (BytesViewClass),
1261 NULL, /* base_init */
1262 NULL, /* base_finalize */
1263 (GClassInitFunc) bytes_view_class_init,
1264 NULL, /* class finalize */
1265 NULL, /* class_data */
1266 sizeof(BytesView),
1267 0, /* n_preallocs */
1268 (GInstanceInitFunc) bytes_view_init,
1269 NULL /* value_table */
1272 #if GTK_CHECK_VERSION(3, 0, 0)
1273 static const GInterfaceInfo scrollable_info = {
1274 NULL,
1275 NULL,
1276 NULL
1278 #endif
1280 bytes_view_gtype = g_type_register_static(GTK_TYPE_WIDGET,
1281 "BytesView",
1282 &bytes_view_info,
1283 (GTypeFlags)0);
1285 #if GTK_CHECK_VERSION(3, 0, 0)
1286 g_type_add_interface_static(bytes_view_gtype,
1287 GTK_TYPE_SCROLLABLE,
1288 &scrollable_info);
1289 #endif
1291 return bytes_view_gtype;
1295 bytes_view_byte_from_xy(BytesView *bv, int x, int y)
1297 /* hex_pos_byte array generated with hex_view_get_byte(0, 0, 0...70) */
1298 static const int hex_pos_byte[70] = {
1299 -1, -1,
1300 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3,
1301 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7,
1303 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11,
1304 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15,
1305 -1, -1,
1306 0, 1, 2, 3, 4, 5, 6, 7,
1308 8, 9, 10, 11, 12, 13, 14, 15
1311 /* bits_pos_byte array generated with bit_view_get_byte(0, 0, 0...84) */
1312 static const int bits_pos_byte[84] = {
1313 -1, -1,
1314 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1315 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1316 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1317 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1318 -1, -1,
1319 0, 1, 2, 3, 4, 5, 6, 7
1322 int char_x, off_x = 1;
1323 int char_y, off_y;
1325 if (x < MARGIN)
1326 return -1;
1328 bytes_view_ensure_layout(bv);
1330 char_y = (int) gtk_adjustment_get_value(bytes_view_ensure_vadj(bv)) + (y / bv->fontsize);
1331 off_y = char_y * bv->per_line;
1333 char_x = _bytes_view_find_pos(bv, off_y, x);
1334 if (/* char_x < 0 || */ char_x < bv->use_digits)
1335 return -1;
1336 char_x -= bv->use_digits;
1338 switch (bv->format) {
1339 case BYTES_BITS:
1340 g_return_val_if_fail(char_x >= 0 && char_x < (int) G_N_ELEMENTS(bits_pos_byte), -1);
1341 off_x = bits_pos_byte[char_x];
1342 break;
1344 case BYTES_HEX:
1345 g_return_val_if_fail(char_x >= 0 && char_x < (int) G_N_ELEMENTS(hex_pos_byte), -1);
1346 off_x = hex_pos_byte[char_x];
1347 break;
1350 if (off_x == -1)
1351 return -1;
1353 return off_y + off_x;
1356 void
1357 bytes_view_scroll_to_byte(BytesView *bv, int byte)
1359 int line;
1361 g_return_if_fail(byte >= 0 && byte < bv->len);
1363 line = byte / bv->per_line;
1365 bytes_view_ensure_vadj(bv);
1367 if (line > gtk_adjustment_get_upper(bv->vadj) - gtk_adjustment_get_page_size(bv->vadj)) {
1368 line = (int)(gtk_adjustment_get_upper(bv->vadj) - gtk_adjustment_get_page_size(bv->vadj));
1370 if (line < 0)
1371 line = 0;
1374 /* after bytes_view_scroll_to_byte() we always do bytes_view_refresh() so we can block it */
1375 g_signal_handlers_block_by_func(bv->vadj, bytes_view_adjustment_changed, bv);
1376 gtk_adjustment_set_value(bv->vadj, line);
1377 g_signal_handlers_unblock_by_func(bv->vadj, bytes_view_adjustment_changed, bv);
1379 /* XXX, scroll hadj? */
1382 void
1383 bytes_view_set_font(BytesView *bv, PangoFontDescription *font)
1385 if (bv->font)
1386 pango_font_description_free(bv->font);
1388 #if GTK_CHECK_VERSION(3, 0, 0)
1389 gtk_widget_override_font(GTK_WIDGET(bv), font);
1390 #else
1391 gtk_widget_modify_font(GTK_WIDGET(bv), font);
1392 #endif
1393 bv->font = pango_font_description_copy(font);
1394 bv->max_width = 0;
1396 if (bv->context) {
1397 g_object_unref(bv->context);
1398 bv->context = NULL;
1399 bytes_view_ensure_layout(bv);
1403 void
1404 bytes_view_set_data(BytesView *bv, const guint8 *data, int len)
1406 g_free(bv->pd);
1407 bv->pd = (guint8 *)g_memdup(data, len);
1408 bv->len = len;
1411 * How many of the leading digits of the offset will we supply?
1412 * We always supply at least 4 digits, but if the maximum offset
1413 * won't fit in 4 digits, we use as many digits as will be needed.
1415 if (((len - 1) & 0xF0000000) != 0)
1416 bv->use_digits = 8; /* need all 8 digits */
1417 else if (((len - 1) & 0x0F000000) != 0)
1418 bv->use_digits = 7; /* need 7 digits */
1419 else if (((len - 1) & 0x00F00000) != 0)
1420 bv->use_digits = 6; /* need 6 digits */
1421 else if (((len - 1) & 0x000F0000) != 0)
1422 bv->use_digits = 5; /* need 5 digits */
1423 else
1424 bv->use_digits = 4; /* we'll supply 4 digits */
1426 bytes_view_ensure_vadj(bv);
1428 bytes_view_adjustment_set(bv);
1431 void
1432 bytes_view_set_encoding(BytesView *bv, int enc)
1434 g_assert(enc == PACKET_CHAR_ENC_CHAR_ASCII || enc == PACKET_CHAR_ENC_CHAR_EBCDIC);
1436 bv->encoding = (packet_char_enc)enc;
1439 void
1440 bytes_view_set_format(BytesView *bv, int format)
1442 g_assert(format == BYTES_HEX || format == BYTES_BITS);
1444 bv->format = (bytes_view_type)format;
1446 switch (format) {
1447 case BYTES_BITS:
1448 bv->per_line = 8;
1449 break;
1451 case BYTES_HEX:
1452 bv->per_line = 16;
1453 break;
1457 void
1458 bytes_view_set_highlight_style(BytesView *bv, gboolean inverse)
1460 bv->bold_highlight = !inverse;
1463 void
1464 bytes_view_set_highlight(BytesView *bv, int start, int end, guint32 mask _U_, int maskle _U_)
1466 bv->start[0] = start;
1467 bv->end[0] = end;
1470 void
1471 bytes_view_set_highlight_extra(BytesView *bv, int id, int start, int end)
1473 bv->start[id] = start;
1474 bv->end[id] = end;
1477 void
1478 bytes_view_refresh(BytesView *bv)
1480 /* bytes_view_render_full(bv); */
1481 gtk_widget_queue_draw(GTK_WIDGET(bv));
1484 GtkWidget *
1485 bytes_view_new(void)
1487 GtkWidget *widget;
1489 widget = (GtkWidget *) g_object_new(BYTES_VIEW_TYPE, NULL);
1491 g_assert(widget != NULL);
1493 return widget;