From 4724b73c5161140222cab3c61bb5b3d0c8dde360 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 25 Feb 2015 21:57:42 +0000
Subject: Provided tweaks about positions when looking for address coordinates.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@480 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                           | 26 ++++++++++++++++++
 plugins/pychrysa/gtkext/viewpanel.c |  2 +-
 src/glibext/gcodebuffer.c           | 53 ++++++++++++++++++++++++-------------
 src/glibext/gcodebuffer.h           |  2 +-
 src/gtkext/gtkbufferview.c          | 50 ++++++++++++++++++++++++++++------
 src/gtkext/gtkviewpanel-int.h       |  2 +-
 src/gtkext/gtkviewpanel.c           | 10 ++++---
 src/gtkext/gtkviewpanel.h           | 12 ++++++++-
 src/gui/menus/binary.c              |  2 +-
 src/gui/menus/edition.c             |  2 +-
 src/gui/panels/bookmarks.c          |  4 +--
 src/gui/panels/symbols.c            |  2 +-
 src/gui/tb/portions.c               |  2 +-
 src/project.c                       | 30 ++++++++++++++-------
 14 files changed, 150 insertions(+), 49 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8eb28e5..6c31b70 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+15-02-25  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pychrysa/gtkext/viewpanel.c:
+	Disable old code.
+
+	* src/glibext/gcodebuffer.c:
+	* src/glibext/gcodebuffer.h:
+	Allow to get coordinates of a line containing code, if possible,
+	for a given address.
+
+	* src/gtkext/gtkbufferview.c:
+	* src/gtkext/gtkviewpanel.c:
+	* src/gtkext/gtkviewpanel.h:
+	* src/gtkext/gtkviewpanel-int.h:
+	Provide tweaks about positions when looking for address coordinates.
+
+	* src/gui/menus/binary.c:
+	* src/gui/menus/edition.c:
+	* src/gui/panels/bookmarks.c:
+	* src/gui/panels/symbols.c:
+	* src/gui/tb/portions.c:
+	Update.
+
+	* src/project.c:
+	Wait a little bit before being abl able to use sizes to compute the position of the entry point.
+
 15-02-24  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/format/format.c:
diff --git a/plugins/pychrysa/gtkext/viewpanel.c b/plugins/pychrysa/gtkext/viewpanel.c
index d2770c4..f680487 100644
--- a/plugins/pychrysa/gtkext/viewpanel.c
+++ b/plugins/pychrysa/gtkext/viewpanel.c
@@ -116,7 +116,7 @@ static PyObject *py_view_panel_scroll_to_address(PyObject *self, PyObject *args)
     ret = PyArg_ParseTuple(args, "K", &addr);
     if (!ret) Py_RETURN_NONE;
 
-    gtk_view_panel_scroll_to_address(panel, addr);
+    //gtk_view_panel_scroll_to_address(panel, addr);
 
     Py_RETURN_NONE;
 
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index afad0f4..4b5378d 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -678,6 +678,9 @@ GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vm
         {
             if ((index + 1) == buffer->used) break;
 
+            /* FIXME : vérifier que l'adresse est toujours celle recherchée ! */
+            /* TODO : passer la recherche de code en option via argument ? */ 
+
             result = buffer->lines[++index];
 
         }
@@ -1756,6 +1759,7 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
 *                addr = adresse à présenter à l'écran.                        *
 *                x    = position horizontale au sein du composant. [OUT]      *
 *                y    = position verticale au sein du composant. [OUT]        *
+*                code = s'arrête si possible à une ligne avec code.           *
 *                                                                             *
 *  Description : Indique la position d'affichage d'une adresse donnée.        *
 *                                                                             *
@@ -1765,7 +1769,7 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *view, gint y, size_t *idx)
 *                                                                             *
 ******************************************************************************/
 
-bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, gint *x, gint *y)
+bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr, gint *x, gint *y, bool code)
 {
     bool result;                            /* Bilan à retourner           */
     gint lheight;                           /* Hauteur d'une ligne         */
@@ -1784,24 +1788,37 @@ bool g_buffer_view_get_address_coordinates(GBufferView *view, const vmpa2t *addr
     first = g_code_buffer_get_index_from_address(view->buffer, view->start, true);
     last = g_code_buffer_get_index_from_address(view->buffer, view->end, false);
 
-    if (view->buffer->used > 0)
-        for (i = first; i <= last; i++)
+    for (i = first; i <= last; i++)
+    {
+        /**
+         * Si l'adresse recherchée est plus petite que l'adresse de départ,
+         * on va effectuer un parcours complet pour rien.
+         *
+         * On considère cependant que le seul cas où celà peut arriver
+         * est lorsque que des découpages en blocs sont impliqués.
+         *
+         * Les découpages conduisent alors à la formation de petites zones,
+         * rapides à parcourir.
+         */
+
+        range = g_buffer_line_get_range(view->buffer->lines[i]);
+
+        result = mrange_contains_addr(range, addr);
+        if (result) break;
+
+        *y += lheight;
+
+    }
+
+    if (result && code)
+        for (; i <= last; i++)
         {
-            /**
-             * Si l'adresse recherchée est plus petite que l'adresse de départ,
-             * on va effectuer un parcours complet pour rien.
-             *
-             * On considère cependant que le seul cas où celà peut arriver
-             * est lorsque que des découpages en blocs sont impliqués.
-             *
-             * Les découpages conduisent alors à la formation de petites zones,
-             * rapides à parcourir.
-             */
-
-            range = g_buffer_line_get_range(view->buffer->lines[i]);
-
-            result = mrange_contains_addr(range, addr);
-            if (result) break;
+            if (g_buffer_line_get_flags(view->buffer->lines[i]) & BLF_HAS_CODE) break;
+
+            if (i == last) break;
+
+            range = g_buffer_line_get_range(view->buffer->lines[i + 1]);
+            if (!mrange_contains_addr(range, addr)) break;
 
             *y += lheight;
 
diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h
index ddd45db..5fd4e7b 100644
--- a/src/glibext/gcodebuffer.h
+++ b/src/glibext/gcodebuffer.h
@@ -150,7 +150,7 @@ void g_buffer_view_export(const GBufferView *, buffer_export_context *, BufferEx
 GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
 
 /* Indique la position d'affichage d'une adresse donnée. */
-bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, gint *, gint *);
+bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, gint *, gint *, bool);
 
 
 
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index f179845..30cf075 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -59,7 +59,7 @@ static void gtk_buffer_view_compute_requested_size(GtkBufferView *, gint *, gint
 static void gtk_buffer_view_compute_scroll_inc(GtkBufferView *, gint, GtkOrientation, gdouble *, gdouble *);
 
 /* Indique la position d'affichage d'une adresse donnée. */
-static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *, const vmpa2t *, gint *, gint *);
+static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *, const vmpa2t *, gint *, gint *, ScrollPositionTweak);
 
 /* Place en cache un rendu destiné à l'aperçu graphique rapide. */
 static void gtk_buffer_view_cache_glance(GtkBufferView *, cairo_t *, const GtkAllocation *, double);
@@ -474,7 +474,7 @@ static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event)
     printf("ctrl ? %d -- keyval = %d -->> %d\n", ctrl, event->keyval, result);
 
 
-    if (addr != NULL) gtk_view_panel_scroll_to_address(pview, addr);
+    if (addr != NULL) gtk_view_panel_scroll_to_address(pview, addr, SPT_RAW);
 
 
     printf("\n");
@@ -552,10 +552,11 @@ static void gtk_buffer_view_compute_scroll_inc(GtkBufferView *view, gint size, G
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : view = composant GTK à consulter.                            *
-*                addr = adresse à présenter à l'écran.                        *
-*                x    = position horizontale au sein du composant. [OUT]      *
-*                y    = position verticale au sein du composant. [OUT]        *
+*  Paramètres  : view  = composant GTK à consulter.                           *
+*                addr  = adresse à présenter à l'écran.                       *
+*                x     = position horizontale au sein du composant. [OUT]     *
+*                y     = position verticale au sein du composant. [OUT]       *
+*                tweak = adaptation finale à effectuer.                       *
 *                                                                             *
 *  Description : Indique la position d'affichage d'une adresse donnée.        *
 *                                                                             *
@@ -565,9 +566,42 @@ static void gtk_buffer_view_compute_scroll_inc(GtkBufferView *view, gint size, G
 *                                                                             *
 ******************************************************************************/
 
-static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *view, const vmpa2t *addr, gint *x, gint *y)
+static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *view, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak)
 {
-    return g_buffer_view_get_address_coordinates(view->buffer_view, addr, x, y);
+    bool result;                            /* Bilan à remonter            */
+    bool need_code;                         /* Recherche plus raffinée     */
+    int height;                             /* Hauteur allouée             */
+
+    need_code = (tweak == SPT_BOTTOM);
+
+    result = g_buffer_view_get_address_coordinates(view->buffer_view, addr, x, y, need_code);
+
+    if (result)
+    {
+        height = gtk_widget_get_allocated_height(GTK_WIDGET(view));
+
+        switch (tweak)
+        {
+            case SPT_RAW:
+                break;
+
+            case SPT_TOP:
+                break;
+
+            case SPT_CENTER:
+                *y -= (height / 2);
+                break;
+
+            case SPT_BOTTOM:
+                *y -= height;
+                *y += g_buffer_view_get_line_height(view->buffer_view);
+                break;
+
+        }
+
+    }
+
+    return result;
 
 }
 
diff --git a/src/gtkext/gtkviewpanel-int.h b/src/gtkext/gtkviewpanel-int.h
index f33499d..90bd141 100644
--- a/src/gtkext/gtkviewpanel-int.h
+++ b/src/gtkext/gtkviewpanel-int.h
@@ -49,7 +49,7 @@ typedef void (* define_address_fc) (GtkViewPanel *, vmpa_t);
 typedef void (* prepare_resize_fc) (GtkViewPanel *);
 
 /* Indique la position d'affichage d'une adresse donnée. */
-typedef bool (* get_addr_coordinates_fc) (const GtkViewPanel *, const vmpa2t *, gint *, gint *);
+typedef bool (* get_addr_coordinates_fc) (const GtkViewPanel *, const vmpa2t *, gint *, gint *, ScrollPositionTweak);
 
 /* Place en cache un rendu destiné à l'aperçu graphique rapide. */
 typedef void (* cache_glance_fc) (GtkViewPanel *, cairo_t *, const GtkAllocation *, double);
diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c
index 8e41fa1..40ae038 100644
--- a/src/gtkext/gtkviewpanel.c
+++ b/src/gtkext/gtkviewpanel.c
@@ -747,7 +747,7 @@ bool gtk_view_panel_contain_address(const GtkViewPanel *panel, vmpa_t addr)
     gint dummy_x;                           /* Abscisse pour l'appel       */
     gint dummy_y;                           /* Ordonnée pour l'appel       */
 
-    return GTK_VIEW_PANEL_GET_CLASS(panel)->get_coordinates(panel, addr, &dummy_x, &dummy_y);
+    return GTK_VIEW_PANEL_GET_CLASS(panel)->get_coordinates(panel, addr, &dummy_x, &dummy_y, SPT_RAW);
 
 }
 
@@ -756,6 +756,7 @@ bool gtk_view_panel_contain_address(const GtkViewPanel *panel, vmpa_t addr)
 *                                                                             *
 *  Paramètres  : panel = composant GTK à manipuler.                           *
 *                addr  = adresse à présenter à l'écran.                       *
+*                tweak = adaptation finale à effectuer.                       *
 *                                                                             *
 *  Description : S'assure qu'une adresse donnée est visible à l'écran.        *
 *                                                                             *
@@ -765,7 +766,7 @@ bool gtk_view_panel_contain_address(const GtkViewPanel *panel, vmpa_t addr)
 *                                                                             *
 ******************************************************************************/
 
-void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr)
+void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr, ScrollPositionTweak tweak)
 {
     gint x;                                 /* Abscisse à garantir         */
     gint y;                                 /* Ordonnée à garantir         */
@@ -781,7 +782,7 @@ void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr)
     */
 
 
-    if (GTK_VIEW_PANEL_GET_CLASS(panel)->get_coordinates(panel, addr, &x, &y))
+    if (GTK_VIEW_PANEL_GET_CLASS(panel)->get_coordinates(panel, addr, &x, &y, tweak))
     {
         viewport = gtk_widget_get_parent(GTK_WIDGET(panel));
 
@@ -807,12 +808,13 @@ void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr)
         page_size = gtk_adjustment_get_page_size(adj);
         value = gtk_adjustment_get_value(adj);
 
-        if (y < value)
+        if (y < value || tweak != SPT_RAW)
             gtk_adjustment_set_value(adj, y);
 
         else if ((y + step_inc) > (value + page_size))
             gtk_adjustment_set_value(adj, y + step_inc - page_size);
 
+
     }
 
 }
diff --git a/src/gtkext/gtkviewpanel.h b/src/gtkext/gtkviewpanel.h
index 95f2084..c733314 100644
--- a/src/gtkext/gtkviewpanel.h
+++ b/src/gtkext/gtkviewpanel.h
@@ -71,8 +71,18 @@ GLoadedBinary *gtk_view_panel_get_binary(const GtkViewPanel *);
 /* Indique si la vue contient une addrese donnée. */
 bool gtk_view_panel_contain_address(const GtkViewPanel *, vmpa_t);
 
+/* Adaptation d'une position sur une surface */
+typedef enum _ScrollPositionTweak
+{
+    SPT_RAW,                                /* Aucun ajustement            */
+    SPT_TOP,                                /* Le plus haut possible       */
+    SPT_CENTER,                             /* Au centre de la surface     */
+    SPT_BOTTOM                              /* Le plus bas possible        */
+
+} ScrollPositionTweak;
+
 /* S'assure qu'une adresse donnée est visible à l'écran. */
-void gtk_view_panel_scroll_to_address(GtkViewPanel *, const vmpa2t *);
+void gtk_view_panel_scroll_to_address(GtkViewPanel *, const vmpa2t *, ScrollPositionTweak);
 
 /* Place en cache un rendu destiné à l'aperçu graphique rapide. */
 void gtk_view_panel_cache_glance(GtkViewPanel *, cairo_t *, const GtkAllocation *, double);
diff --git a/src/gui/menus/binary.c b/src/gui/menus/binary.c
index c7c0347..50a9143 100644
--- a/src/gui/menus/binary.c
+++ b/src/gui/menus/binary.c
@@ -128,7 +128,7 @@ static void mcb_binary_entry_points(GtkMenuItem *menuitem, GMenuBar *bar)
         addr = get_address_from_gotox_dialog(dialog);
 
         vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
-        gtk_view_panel_scroll_to_address(vpanel, addr);
+        gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER);
 
         delete_vmpa(addr);
 
diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c
index eec3016..8893ce9 100644
--- a/src/gui/menus/edition.c
+++ b/src/gui/menus/edition.c
@@ -222,7 +222,7 @@ static void mcb_edition_goto(GtkMenuItem *menuitem, GMenuBar *bar)
         addr = get_address_from_goto_dialog(dialog);
 
         vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
-        gtk_view_panel_scroll_to_address(vpanel, addr);
+        gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER);
 
         delete_vmpa(addr);
 
diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c
index 052bf5a..e9ab0d1 100644
--- a/src/gui/panels/bookmarks.c
+++ b/src/gui/panels/bookmarks.c
@@ -647,7 +647,7 @@ static void on_bookmarks_selection_change(GtkTreeSelection *selection, GBookmark
         addr = g_db_bookmark_get_address(bookmark);
 
         vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel));
-        gtk_view_panel_scroll_to_address(vpanel, addr);
+        gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER);
 
         g_object_unref(G_OBJECT(bookmark));
 
@@ -1081,7 +1081,7 @@ static gboolean on_button_press_over_bookmarks(GtkWidget *widget, GdkEventButton
                 addr = g_db_bookmark_get_address(bookmark);
 
                 vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel));
-                gtk_view_panel_scroll_to_address(vpanel, addr);
+                gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER);
 
                 g_object_unref(G_OBJECT(bookmark));
 
diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c
index 7be9749..b523cd2 100644
--- a/src/gui/panels/symbols.c
+++ b/src/gui/panels/symbols.c
@@ -562,7 +562,7 @@ static void on_symbols_selection_change(GtkTreeSelection *selection, GSymbolsPan
         range = g_binary_symbol_get_range(symbol);
 
         vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel));
-        gtk_view_panel_scroll_to_address(vpanel, get_mrange_addr(range));
+        gtk_view_panel_scroll_to_address(vpanel, get_mrange_addr(range), SPT_CENTER);
 
         g_object_unref(G_OBJECT(symbol));
 
diff --git a/src/gui/tb/portions.c b/src/gui/tb/portions.c
index 7e9cb6c..39537eb 100644
--- a/src/gui/tb/portions.c
+++ b/src/gui/tb/portions.c
@@ -246,7 +246,7 @@ static void track_address_on_binary_strip(GtkBinaryStrip *strip, GEditorItem *it
     addr = gtk_binary_strip_get_location(strip);
 
     vpanel = g_editor_item_get_current_view(item);
-    gtk_view_panel_scroll_to_address(vpanel, addr);
+    gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER);
 
     focus_address_in_editor_items(g_editor_item_get_current_binary(item), addr, item);
 
diff --git a/src/project.c b/src/project.c
index f3a2702..c8d23f7 100644
--- a/src/project.c
+++ b/src/project.c
@@ -324,24 +324,36 @@ const char *g_study_project_get_filename(const GStudyProject *project)
 void g_study_project_add_loaded_binary(GLoadedBinary *binary, GStudyProject *project)
 {
     size_t index;                           /* Indice du nouveau binaire   */
-    GBinFormat *format;                     /* Format associé au binaire   */
-    GBinSymbol *symbol;                     /* Point d'entrée trouvé       */
-    const mrange_t *range;                  /* Emplacement de ce point     */
 
     index = g_study_project_attach_binary(project, binary);
 
-    g_panel_item_dock(G_PANEL_ITEM(project->binaries[index]->item));
+    gboolean scroll_for_the_first_time(GtkWidget *widget, GdkEvent *event, GLoadedBinary *binary)
+    {
+        GBinFormat *format;                 /* Format associé au binaire   */
+        GBinSymbol *symbol;                 /* Point d'entrée trouvé       */
+        const mrange_t *range;              /* Emplacement de ce point     */
 
-    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+        g_signal_handlers_disconnect_by_func(widget, G_CALLBACK(scroll_for_the_first_time), binary);
 
-    if (g_binary_format_find_symbol_by_label(format, "entry_point", &symbol))
-    {
-        range = g_binary_symbol_get_range(symbol);
+        format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
 
-        gtk_view_panel_scroll_to_address(project->binaries[index]->views[BVW_BLOCK], get_mrange_addr(range));
+        if (g_binary_format_find_symbol_by_label(format, "entry_point", &symbol))
+        {
+            range = g_binary_symbol_get_range(symbol);
+
+            gtk_view_panel_scroll_to_address(GTK_VIEW_PANEL(widget), get_mrange_addr(range), SPT_CENTER);
+
+        }
+
+        return FALSE;
 
     }
 
+    g_signal_connect(project->binaries[index]->views[BVW_BLOCK], "size-allocate",
+                     G_CALLBACK(scroll_for_the_first_time), binary);
+
+    g_panel_item_dock(G_PANEL_ITEM(project->binaries[index]->item));
+
 }
 
 
-- 
cgit v0.11.2-87-g4458