[ghex/gtk4-port: 65/91] Move cpl calculation to the layout manager.




commit 9113f893559b740b9594af2a83d75f0adcc8e57c
Author: Logan Rathbone <poprocks gmail com>
Date:   Thu Jan 28 01:01:39 2021 -0500

    Move cpl calculation to the layout manager.
    
    The hex/ascii ratio in the widget needs optimization with longer byte
    groups, but I think this is a step in the right direction.

 src/gtkhex-layout-manager.c |  73 ++++++++++++++++++++++++------
 src/gtkhex-layout-manager.h |   9 ++++
 src/gtkhex.c                | 105 ++++++++++++++------------------------------
 src/gtkhex.h                |   9 +---
 4 files changed, 102 insertions(+), 94 deletions(-)
---
diff --git a/src/gtkhex-layout-manager.c b/src/gtkhex-layout-manager.c
index fcb18a1e..f48bb2b7 100644
--- a/src/gtkhex-layout-manager.c
+++ b/src/gtkhex-layout-manager.c
@@ -36,9 +36,10 @@ struct _GtkHexLayout {
        GtkWidget *ascii;
 
        guint char_width;
+       guint group_type;
 
-       int hex_width;
-       int ascii_width;
+       int cpl;
+       int hex_cpl;
 };
 
 G_DEFINE_TYPE (GtkHexLayout, gtk_hex_layout, GTK_TYPE_LAYOUT_MANAGER)
@@ -51,7 +52,6 @@ struct _GtkHexLayoutChild {
 
 enum {
   PROP_CHILD_COLUMN = 1,
-
   N_CHILD_PROPERTIES
 };
 
@@ -211,6 +211,27 @@ gtk_hex_layout_measure (GtkLayoutManager *layout_manager,
                *natural = natural_size;
 }
 
+/* Helper */
+static void
+get_cpl_from_ascii_width (GtkHexLayout *self, int width)
+{
+       int hex_cpl, ascii_cpl;
+
+       g_debug ("%s: GROUP_TYPE: %u", __func__, self->group_type);
+
+       /* Hex characters per line is a simple calculation: */
+
+       ascii_cpl = width / self->char_width;
+       while (ascii_cpl % self->group_type != 0)
+               --ascii_cpl;
+
+       hex_cpl = ascii_cpl * 2;
+       hex_cpl += ascii_cpl / self->group_type;
+
+       self->hex_cpl = hex_cpl;
+       self->cpl = ascii_cpl;
+}
+
 static void
 gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
                GtkWidget        *widget,
@@ -240,12 +261,12 @@ gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
                if (! gtk_widget_should_layout (child))
                        continue;
 
-               /* Get preferred size of the child widget
-                */
+               /* Get preferred size of the child widget */
+
                gtk_widget_get_preferred_size (child, &child_req, NULL);
 
-               /* Setup allocation depending on what column we're in.
-                */
+               /* Setup allocation depending on what column we're in. */
+
                child_info =
                        GTK_HEX_LAYOUT_CHILD(gtk_layout_manager_get_layout_child (layout_manager,
                                                child));
@@ -268,7 +289,8 @@ gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
                                scr_alloc.height = height;
                                break;
                        default:
-                               g_error ("%s: Programming error. The requested column is invalid.",
+                               g_error ("%s: Programming error. "
+                                               "The requested column is invalid.",
                                                __func__);
                                break;
                }
@@ -283,12 +305,12 @@ gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
                if (! gtk_widget_should_layout (child))
                        continue;
 
-               /* Get preferred size of the child widget
-                */
+               /* Get preferred size of the child widget */
+
                gtk_widget_get_preferred_size (child, &child_req, NULL);
 
-               /* Setup allocation depending on what column we're in.
-                */
+               /* Setup allocation depending on what column we're in. */
+
                child_info =
                        GTK_HEX_LAYOUT_CHILD(gtk_layout_manager_get_layout_child
                                        (layout_manager, child));
@@ -320,6 +342,9 @@ gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
                                                * HEX_RATIO;
                                }
                                tmp_alloc = asc_alloc;
+
+                               get_cpl_from_ascii_width (self, asc_alloc.width);
+
                                break;
 
                        case SCROLLBAR_COLUMN:
@@ -373,9 +398,9 @@ gtk_hex_layout_class_init (GtkHexLayoutClass *klass)
 static void
 gtk_hex_layout_init (GtkHexLayout *self)
 {
-       g_debug ("%s: TEST - SETTING A DEFAULT MINIMUM CHAR-WIDTH",
-                       __func__);
+       /* FIXME - dumb test initial default */
        self->char_width = 20;
+       self->group_type = GROUP_BYTE;
 }
 
 /* GtkHexLayout - Public Methods */
@@ -394,6 +419,26 @@ gtk_hex_layout_set_char_width (GtkHexLayout *layout, guint width)
        gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER(layout));
 }
 
+void
+gtk_hex_layout_set_group_type (GtkHexLayout *layout, guint group_type)
+{
+       layout->group_type = group_type;
+
+       gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER(layout));
+}
+
+int
+gtk_hex_layout_get_cpl (GtkHexLayout *layout)
+{
+       return layout->cpl;
+}
+
+int
+gtk_hex_layout_get_hex_cpl (GtkHexLayout *layout)
+{
+       return layout->hex_cpl;
+}
+
 /* GtkHexLayoutChild - Public Methods */
 
 void
diff --git a/src/gtkhex-layout-manager.h b/src/gtkhex-layout-manager.h
index 3decd4de..1855a193 100644
--- a/src/gtkhex-layout-manager.h
+++ b/src/gtkhex-layout-manager.h
@@ -29,6 +29,11 @@
 
 G_BEGIN_DECLS
 
+/* how to group bytes? */
+#define GROUP_BYTE 1
+#define GROUP_WORD 2
+#define GROUP_LONG 4
+
 #define GTK_TYPE_HEX_LAYOUT (gtk_hex_layout_get_type ())
 G_DECLARE_FINAL_TYPE (GtkHexLayout, gtk_hex_layout, GTK, HEX_LAYOUT,
                GtkLayoutManager)
@@ -50,6 +55,10 @@ void                         gtk_hex_layout_set_char_width (GtkHexLayout *layout,
                                                guint width);
 void                           gtk_hex_layout_child_set_column (GtkHexLayoutChild *child,
                                                GtkHexLayoutColumn column);
+int                                    gtk_hex_layout_get_cpl (GtkHexLayout *layout);
+int                            gtk_hex_layout_get_hex_cpl (GtkHexLayout *layout);
+void                           gtk_hex_layout_set_group_type (GtkHexLayout *layout,
+                                               guint group_type);
 
 G_END_DECLS
 
diff --git a/src/gtkhex.c b/src/gtkhex.c
index 639f6391..bc0d8eb1 100644
--- a/src/gtkhex.c
+++ b/src/gtkhex.c
@@ -40,7 +40,6 @@
 /* Don't move these from the source file as they are not part of the public
  * header.
  */
-#include "gtkhex-layout-manager.h"
 
 /* DEFINES */
 
@@ -51,6 +50,7 @@
 #define DEFAULT_CPL 32
 #define DEFAULT_LINES 10
 #define SCROLL_TIMEOUT 100
+#define STARTING_OFFSET 0
 
 #define is_displayable(c) (((c) >= 0x20) && ((c) < 0x7f))
 #define is_copyable(c) (is_displayable(c) || (c) == 0x0a || (c) == 0x0d)
@@ -186,7 +186,6 @@ struct _GtkHex
        int scroll_dir;
        guint scroll_timeout;
        gboolean show_offsets;
-       int starting_offset;
        gboolean insert;
        gboolean selecting;
 
@@ -199,7 +198,7 @@ struct _GtkHex
        int default_lines;
 };
 
-G_DEFINE_TYPE(GtkHex, gtk_hex, GTK_TYPE_WIDGET)
+G_DEFINE_TYPE (GtkHex, gtk_hex, GTK_TYPE_WIDGET)
 
 /* ----- */
 
@@ -574,7 +573,8 @@ get_char_width (GtkHex *gh)
        
        /* update layout manager */
        if (GTK_IS_HEX_LAYOUT(gh->layout_manager)) {
-               gtk_hex_layout_set_char_width (gh->layout_manager, width);
+               gtk_hex_layout_set_char_width (GTK_HEX_LAYOUT(gh->layout_manager),
+                               width);
        }
        return width;
 }
@@ -602,6 +602,8 @@ format_xblock(GtkHex *gh, gchar *out, guint start, guint end)
        int i, j, low, high;
        guchar c;
 
+       g_debug ("%s: GOT GROUP TYPE: %u", __func__, gh->group_type);
+
        for(i = start + 1, j = 0; i <= end; i++) {
                c = gtk_hex_get_byte(gh, i - 1);
                low = c & 0x0F;
@@ -610,7 +612,7 @@ format_xblock(GtkHex *gh, gchar *out, guint start, guint end)
                out[j++] = ((high < 10)?(high + '0'):(high - 10 + 'A'));
                out[j++] = ((low < 10)?(low + '0'):(low - 10 + 'A'));
                
-               if(i%gh->group_type == 0)
+               if (i % gh->group_type == 0)
                        out[j++] = ' ';
        }
        return j;
@@ -881,12 +883,12 @@ render_hex_highlights (GtkHex *gh,
                        gint cursor_line)
 {
        GtkHex_Highlight *curHighlight = &gh->selection;
-       gint xcpl = gh->cpl*2 + gh->cpl/gh->group_type;
-
        GtkHex_AutoHighlight *nextList = gh->auto_highlight;
        GtkStateFlags state;
        GtkStyleContext *context;
+       int hex_cpl;
 
+       hex_cpl = gtk_hex_layout_get_hex_cpl (GTK_HEX_LAYOUT(gh->layout_manager));
        context = gtk_widget_get_style_context (gh->xdisp);
        gtk_style_context_save (context);
 
@@ -919,7 +921,7 @@ render_hex_highlights (GtkHex *gh,
                                if (cursor_line == el)
                                        len = 2*(end%gh->cpl + 1) + (end%gh->cpl)/gh->group_type;
                                else
-                                       len = xcpl;
+                                       len = hex_cpl;
 
                                len = len - cursor_off;
 
@@ -947,7 +949,7 @@ render_hex_highlights (GtkHex *gh,
                                gtk_render_background (context, cr,
                                                 0,
                                                 cursor_line * gh->char_height,
-                                                xcpl * gh->char_width,
+                                                hex_cpl * gh->char_width,
                                                 gh->char_height);
                        }
                }
@@ -1115,12 +1117,16 @@ render_hex_lines (GtkHex *gh,
        GtkStateFlags state;
        GtkStyleContext *context;
        int cursor_line;
-       int xcpl = gh->cpl * 2 + gh->cpl / gh->group_type;
        int frm_len;
+       int hex_cpl;
 
        g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET(gh)));
        g_return_if_fail (gh->cpl > 0);
 
+       hex_cpl = gtk_hex_layout_get_hex_cpl (GTK_HEX_LAYOUT(gh->layout_manager));
+       g_debug ("%s: GROUP TYPE: %u", __func__, gh->group_type);
+       g_debug ("%s: HEX_CPL: %d", __func__, hex_cpl);
+
        context = gtk_widget_get_style_context (widget);
        state = gtk_widget_get_state_flags (widget);
        cursor_line = gh->cursor_pos / gh->cpl - gh->top_line;
@@ -1145,7 +1151,7 @@ render_hex_lines (GtkHex *gh,
        
        for (int i = min_lines; i <= max_lines; i++)
        {
-               int tmp = frm_len - ((i - min_lines) * xcpl);
+               int tmp = frm_len - ((i - min_lines) * hex_cpl);
 
                if (tmp <= 0)
                        break;
@@ -1155,8 +1161,8 @@ render_hex_lines (GtkHex *gh,
                /* Set pango layout to the line of hex to render. */
 
                pango_layout_set_text (gh->xlayout,
-                               gh->disp_buffer + (i - min_lines) * xcpl,
-                               MIN(xcpl, tmp));
+                               gh->disp_buffer + (i - min_lines) * hex_cpl,
+                               MIN(hex_cpl, tmp));
 
                gtk_render_layout (context, cr,
                                /* x: */ 0,
@@ -1252,7 +1258,7 @@ render_offsets (GtkHex *gh,
        context = gtk_widget_get_style_context (widget);
        state = gtk_widget_get_state_flags (widget);
 
-       gtk_widget_get_allocation(widget, &allocation);
+       gtk_widget_get_allocation (widget, &allocation);
 
        /* render background. */
        gtk_render_background (context, cr,
@@ -1268,7 +1274,7 @@ render_offsets (GtkHex *gh,
        for (int i = min_lines; i <= max_lines; i++) {
                /* generate offset string and place in temporary buffer */
                sprintf(offstr, "%08X",
-                               (gh->top_line + i) * gh->cpl + gh->starting_offset);
+                               (gh->top_line + i) * gh->cpl + STARTING_OFFSET);
 
                /* build pango layout for offset line; draw line with gtk. */
                pango_layout_set_text (gh->olayout, offstr, 8);
@@ -1289,51 +1295,13 @@ hex_draw (GtkDrawingArea *drawing_area,
                            gpointer user_data)
 {
        GtkHex *gh = GTK_HEX(user_data);
-       int xcpl = 0;
 
        g_return_if_fail (GTK_IS_HEX(gh));
 
-       /* Total number of characters that can be displayed per line on the hex
-        * widget (xcpl) is the simplest calculation:
-        */
-       xcpl = width / gh->char_width;
-
-       /* FIXME - This doesn't quite jibe with our new layout manager. Our
-        * calculations here are fine, but the layout manager has no knowledge
-        * of it, so sometimes characters get cut off if using larger group
-        * types.
-        */
-       /* Next, extrapolate the number of ASCII characters per line; this is
-        * dependent upon the 'grouping' (ie, hex: 2 characters followed by a
-        * space, a 'word' (2 hex characters together followed by a space, ie,
-        * 4 + space... this is best illustrated with an example.
-        *
-        * given 16 xcpl, 'word' grouping:
-        *
-        * 16 [xcpl] / (2 [fixed value; # characters in a hex pair] * 4
-        * [gh->group_type] + 1 [space]) == 1
-        *
-        * Meaning: 1 full word only can fit on a hex line, in this hypothetical,
-        * then multiply the result by the group type again to get the number of
-        * _characters_ (ascii) that this represents. (4 * 1 = 4 in this case)
-        * Whew!
-        */
-       gh->cpl = xcpl / (2 * gh->group_type + 1);
-       gh->cpl *= gh->group_type;
-
-       /* pixel width of hex drawing area */
-       gh->xdisp_width = xcpl * gh->char_width;
-
-       /* pixel width of ascii drawing area */
-       gh->adisp_width = gh->cpl * gh->char_width;
-
-       /* If gh->cpl is not greater than 0, something has gone wrong. */
-       g_return_if_fail (gh->cpl > 0);
-
        /* Now that we have gh->cpl defined, run this function to bump all
         * required values:
         */
-       recalc_displays(gh);
+       recalc_displays (gh);
 
        /* Finally, we can do what we wanted to do to begin with: draw our hex
         * lines!
@@ -1372,10 +1340,12 @@ offsets_draw (GtkDrawingArea *drawing_area,
  * lines we can display according to the current size of the widget
  */
 static void
-recalc_displays(GtkHex *gh)
+recalc_displays (GtkHex *gh)
 {
        GtkWidget *widget = GTK_WIDGET (gh);
-       int xcpl;
+       int hex_cpl;
+
+       hex_cpl = gtk_hex_layout_get_hex_cpl (GTK_HEX_LAYOUT(gh->layout_manager));
 
        /*
         * Only change the value of the adjustment to put the cursor on screen
@@ -1389,15 +1359,10 @@ recalc_displays(GtkHex *gh)
                        gh->lines++;
        }
 
-       /* FIXME - different than 'xcpl' in hex_draw. confusing.
-        */
-       /* set number of hex characters per line */
-       xcpl = gh->cpl * 2 + (gh->cpl - 1) / gh->group_type;
-
        if (gh->disp_buffer)
                g_free (gh->disp_buffer);
        
-       gh->disp_buffer = g_malloc ((xcpl + 1) * (gh->vis_lines + 1));
+       gh->disp_buffer = g_malloc ((hex_cpl + 1) * (gh->vis_lines + 1));
 }
 
 static void
@@ -2466,6 +2431,9 @@ gtk_hex_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
        gh->char_width = get_char_width(gh);
        gh->char_height = get_char_height(gh);
 
+       /* Get cpl from layout manager */
+       gh->cpl = gtk_hex_layout_get_cpl (GTK_HEX_LAYOUT(gh->layout_manager));
+
        /* get width and height, implicitly converted to floats so we can pass
         * to graphene_rect_init below. */
        width = gtk_widget_get_allocated_width (widget);
@@ -2725,9 +2693,7 @@ gtk_hex_init(GtkHex *gh)
        gh->scroll_timeout = -1;
 
        gh->document = NULL;
-       gh->starting_offset = 0;
 
-       gh->xdisp_width = gh->adisp_width = DEFAULT_DA_SIZE;
        gh->extra_width = 0;
        gh->active_view = VIEW_HEX;
        gh->group_type = GROUP_BYTE;
@@ -3284,6 +3250,9 @@ gtk_hex_set_group_type (GtkHex *gh, guint gt)
 
        hide_cursor(gh);
        gh->group_type = gt;
+
+       gtk_hex_layout_set_group_type (GTK_HEX_LAYOUT(gh->layout_manager), gt);
+
 #if 0
        gtk_widget_get_allocation(GTK_WIDGET(gh), &allocation);
        recalc_displays(gh, allocation.width, allocation.height);
@@ -3312,14 +3281,6 @@ gtk_hex_show_offsets(GtkHex *gh, gboolean show)
                hide_offsets_widget(gh);
 }
 
-void
-gtk_hex_set_starting_offset (GtkHex *gh, gint starting_offset)
-{
-       g_return_if_fail (gh != NULL);
-       g_return_if_fail(GTK_IS_HEX(gh));
-       gh->starting_offset = starting_offset;
-}
-
 void
 gtk_hex_set_insert_mode (GtkHex *gh, gboolean insert)
 {
diff --git a/src/gtkhex.h b/src/gtkhex.h
index 124bbd6d..6194c457 100644
--- a/src/gtkhex.h
+++ b/src/gtkhex.h
@@ -36,19 +36,13 @@
 #include <gdk/gdk.h>
 
 #include <hex-document.h>
+#include <gtkhex-layout-manager.h>
 
 G_BEGIN_DECLS
 
 #define GTK_TYPE_HEX (gtk_hex_get_type ())
 G_DECLARE_FINAL_TYPE(GtkHex, gtk_hex, GTK, HEX, GtkWidget)
 
-/* DEFINES */
-
-/* how to group bytes? */
-#define GROUP_BYTE 1
-#define GROUP_WORD 2
-#define GROUP_LONG 4
-
 /* OPAQUE DATATYPES */
 
 typedef struct _GtkHex_AutoHighlight GtkHex_AutoHighlight;
@@ -67,7 +61,6 @@ guchar gtk_hex_get_byte(GtkHex *, guint);
 void gtk_hex_set_group_type(GtkHex *, guint);
 guint gtk_hex_get_group_type (GtkHex *gh);
 
-void gtk_hex_set_starting_offset(GtkHex *, gint);
 void gtk_hex_show_offsets(GtkHex *, gboolean);
 void gtk_hex_set_font(GtkHex *, PangoFontMetrics *,
                const PangoFontDescription *);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]