From 7bd707cb43ed8830add9d9eec3a670c9a0ce4d68 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 11 Apr 2015 20:01:03 +0000
Subject: Fixed the remaining bugs in all kinds of navigation in buffer views.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@509 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                  |   8 ++
 src/glibext/gbufferline.c  | 204 ++++++++++++++++++++++++++++++++++++++++++---
 src/glibext/gbufferline.h  |   2 +-
 src/glibext/gcodebuffer.c  |  85 +++++--------------
 src/gtkext/gtkbufferview.c |   3 +-
 5 files changed, 227 insertions(+), 75 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f971576..55e8dde 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+15-04-11  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/glibext/gbufferline.c:
+	* src/glibext/gbufferline.h:
+	* src/glibext/gcodebuffer.c:
+	* src/gtkext/gtkbufferview.c:
+	Fix the remaining bugs in all kinds of navigation in buffer views.
+
 15-04-10  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/core/params.c:
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index e34f86f..d763e9d 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -69,7 +69,7 @@ static bool column_has_segment(const buffer_line_column *, const GBufferSegment
 #define get_last_segment(col) ((col)->count > 0 ? (col)->segments[(col)->count - 1] : NULL)
 
 /* Donne le segment d'une colonne présent à une abscisse donnée. */
-static GBufferSegment *get_segment_at(const buffer_line_column *, gint *, GdkScrollDirection);
+static GBufferSegment *get_segment_at(const buffer_line_column *, gint *, GdkScrollDirection, gint *);
 
 /* Fournit le segment voisin d'un autre segment identifié. */
 static GBufferSegment *find_near_segment(const buffer_line_column *, GBufferSegment *, GdkScrollDirection);
@@ -235,9 +235,10 @@ static bool column_has_segment(const buffer_line_column *column, const GBufferSe
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : column = colonne de ligne de texte à consulter.              *
-*                x      = position de recherche à ajuster. [OUT]              *
-*                dir    = direction d'un éventuel déplacement en cours.       *
+*  Paramètres  : column   = colonne de ligne de texte à consulter.            *
+*                x        = position de recherche, puis position locale. [OUT]*
+*                dir      = direction d'un éventuel déplacement en cours.     *
+*                consumed = distance pour arriver à la base du segment. [OUT] *
 *                                                                             *
 *  Description : Donne le segment d'une colonne présent à une abscisse donnée.*
 *                                                                             *
@@ -247,7 +248,7 @@ static bool column_has_segment(const buffer_line_column *column, const GBufferSe
 *                                                                             *
 ******************************************************************************/
 
-static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, GdkScrollDirection dir)
+static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, GdkScrollDirection dir, gint *consumed)
 {
     GBufferSegment *result;                 /* Trouvaille à retourner      */
     size_t i;                               /* Boucle de parcours          */
@@ -255,6 +256,7 @@ static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x,
     bool included;                          /* Appartenance à une largeur ?*/
 
     result = NULL;
+    *consumed = 0;
 
     printf(" == gs@ ==   count = %d   width = %d\n",
            column->count, get_column_width(column));
@@ -277,11 +279,20 @@ static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x,
         if (dir == GDK_SCROLL_LEFT) included = (width >= *x);
         else included = (width > *x);
 
-        if (included || (i + 1) == column->count)
+        if (included)
             result = column->segments[i];
 
+        else if ((i + 1) == column->count)
+        {
+            result = column->segments[i];
+            *x = width;
+        }
+
         else
+        {
             *x -= width;
+            *consumed += width;
+        }
 
     }
 
@@ -753,7 +764,8 @@ void g_buffer_line_add_segment(GBufferLine *line, BufferLineColumn index, GBuffe
 *  Paramètres  : line       = ligne à venir consulter.                        *
 *                max_widths = largeurs de colonne à respecter.                *
 *                display    = règles d'affichage des colonnes modulables.     *
-*                x          = position à la colonne visée. [OUT]              *
+*                base       = position jusqu'au segment trouvé. [OUT]         *
+*                offset     = position à la colonne visée. [OUT]              *
 *                dir        = direction d'un éventuel déplacement en cours.   *
 *                force      = accepte les segments en bordure au pire.        *
 *                                                                             *
@@ -765,7 +777,164 @@ void g_buffer_line_add_segment(GBufferLine *line, BufferLineColumn index, GBuffe
 *                                                                             *
 ******************************************************************************/
 
-GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint max_widths[BLC_COUNT], const bool *display, gint *x, GdkScrollDirection dir, bool force)
+GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint max_widths[BLC_COUNT], const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force)
+{
+    GBufferSegment *result;                 /* Trouvaille à retourner      */
+    BufferLineColumn last;                  /* Dernière colonne remplie    */
+    gint last_base;                         /* Dernière abscisse associée  */
+    BufferLineColumn i;                     /* Boucle de parcours          */
+    gint width;                             /* Largeur d'une colonne donnée*/
+
+    gint limit;
+
+    gint consumed;                          /* Distance vers le segment    */
+    gint old_base;                          /* Somme de toutes les largeurs*/
+
+    result = NULL;
+
+    *base = 0;
+
+    last = BLC_COUNT;
+
+    //sum = 0;
+
+    printf("---------------\n");
+
+    /* On cible déjà la colonne idéale */
+
+    for (i = 0; i < BLC_COUNT; i++)
+    {
+        printf(" @ (%d) x=%d  width=%d  max=%d  display ? %d\n",
+               i, *offset, get_column_width(&line->columns[i]), max_widths[i], i < BLC_DISPLAY ? display[i] : true);
+
+
+        if (i < BLC_DISPLAY && !display[i]) continue;
+
+        /* Mémorisation de la dernière colonne contenant quelque chose... */
+        if (get_column_width(&line->columns[i]) > 0)
+        {
+            last = i;
+            last_base = *base;
+        }
+
+        if (i < line->merge_start)
+        {
+            width = max_widths[i];
+
+            if ((i + 1) < BLC_COUNT) limit = width + COL_MARGIN / 2;
+            else limit = width;
+
+            if (*offset <= limit) break;
+            else
+            {
+                *offset -= width + COL_MARGIN;
+                *base += width + COL_MARGIN;
+            }
+
+        }
+        else
+        {
+            width = get_column_width(&line->columns[i]);
+
+            if (*offset <= width) break;
+            else
+            {
+                *offset -= width;
+                *base += width;
+            }
+
+        }
+
+
+    }
+
+    printf(" -- get segment at -- found index %u (max=%u)\n", i, BLC_COUNT);
+
+
+    printf("                      last seen = %u\n", last);
+
+
+
+
+
+    if (i < BLC_COUNT)
+    {
+
+        printf(" -- width @ %u : %d\n", i, get_column_width(&line->columns[i]));
+
+        if (get_column_width(&line->columns[i]) > 0)
+        {
+            /**
+             * Si la position était au milieu d'une marge, la sélection a pu pousser
+             * jusqu'à la colonne suivante, plus proche.
+             * Relativment à la base de cette dernière, la position est donc devenue négative.
+             */
+            if (*offset < 0) *offset = 0;
+
+            result = get_segment_at(&line->columns[i], offset, dir, &consumed);
+            *base += consumed;
+        }
+
+        /* La position fournie tombe dans une colonne vide ! */
+        else
+        {
+            if (force || get_column_width(&line->columns[i]) == 0)
+            {
+                result = NULL;
+                *offset = 0;
+
+                old_base = *base;
+
+                for (i++; i < BLC_COUNT && result == NULL; i++)
+                {
+                    printf(" -- update to col %u  -- x = %d\n", i, *offset);
+
+                    if ((i - 1) < line->merge_start)
+                        *base += (max_widths[i - 1] + COL_MARGIN);
+                    else
+                        *base += get_column_width(&line->columns[i - 1]);
+
+                    result = get_first_segment(&line->columns[i]);
+
+                }
+
+                printf(" -- final x = %d (result=%p)\n", *offset, result);
+
+                if (result == NULL)
+                {
+                    *base = old_base;
+                    goto use_right_border;
+                }
+
+            }
+
+        }
+
+    }
+
+    else /* if (i == BLC_COUNT) */
+    {
+        if (force && last != BLC_COUNT)
+        {
+ use_right_border:
+
+            result = get_last_segment(&line->columns[last]);
+            *base = last_base;
+            *offset = get_column_width(&line->columns[last]);
+
+        }
+        else
+            result = NULL;
+
+    }
+
+    return result;
+
+}
+
+
+#if 0
+GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint max_widths[BLC_COUNT], const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force)
 {
     GBufferSegment *result;                 /* Trouvaille à retourner      */
     gint old;                               /* Valeur d'origine de position*/
@@ -774,6 +943,7 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
     gint sum;                               /* Somme de toutes les largeurs*/
     BufferLineColumn i;                     /* Boucle de parcours          */
     gint width;                             /* Largeur d'une colonne donnée*/
+    gint consumed;                          /* Distance vers le segment    */
 
     result = NULL;
 
@@ -805,12 +975,13 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
         if (i < line->merge_start)
         {
             width = max_widths[i];
+            if ((i + 1) < BLC_COUNT) width += COL_MARGIN;
 
             if (*x <= width) break;
             else
             {
-                *x -= (max_widths[i] + COL_MARGIN);
-                sum += width + COL_MARGIN;
+                *x -= width;
+                sum += width;
             }
 
         }
@@ -845,7 +1016,10 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
         printf(" -- width @ %u : %d\n", i, get_column_width(&line->columns[i]));
 
         if (get_column_width(&line->columns[i]) > 0)
-            result = get_segment_at(&line->columns[i], x, dir);
+        {
+            result = get_segment_at(&line->columns[i], x, dir, &consumed);
+            *x += sum + consumed;
+        }
 
         /* La position fournie tombe dans une colonne vide ! */
         else
@@ -870,6 +1044,9 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
 
                 printf(" -- final x = %d (result=%p)\n", *x, result);
 
+                if (result == NULL)
+                    goto use_right_border;
+
             }
 
         }
@@ -880,8 +1057,11 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
     {
         if (force && last != BLC_COUNT)
         {
+ use_right_border:
+
             result = get_last_segment(&line->columns[last]);
             *x = last_x + get_column_width(&line->columns[last]);
+
         }
         else
             result = NULL;
@@ -891,6 +1071,8 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
     return result;
 
 }
+#endif
+
 
 
 /******************************************************************************
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 3a00ce0..e8916ac 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -113,7 +113,7 @@ void g_buffer_line_fill_for_instr(GBufferLine *, MemoryDataSize, MemoryDataSize,
 void g_buffer_line_add_segment(GBufferLine *, BufferLineColumn, GBufferSegment *) __attribute__ ((deprecated));
 
 /* Donne le segment présent à une abscisse donnée. */
-GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BLC_COUNT], const bool *, gint *, GdkScrollDirection, bool);
+GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BLC_COUNT], const bool *, gint *, gint *, GdkScrollDirection, bool);
 
 /* Fournit le segment voisin d'un autre segment identifié. */
 GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *, GBufferSegment *, const gint [BLC_COUNT], const bool *, GdkScrollDirection, gint *);
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 4b4b2a6..f7c7cd6 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -1303,7 +1303,8 @@ GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x,
         else
         {
             *x -= view->left_text;
-            *segment = g_buffer_line_get_segment_at(result, view->max_widths, display, x, GDK_SCROLL_LEFT, true);
+            *segment = g_buffer_line_get_segment_at(result, view->max_widths, display,
+                                                    (gint []) { 0 }, x, GDK_SCROLL_LEFT, true);
         }
 
     }
@@ -1388,26 +1389,20 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con
 
 const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret)
 {
-    gint tmp_x;                             /* Copie de travail modifiable */
+    gint offset;                            /* Point de travail modifiable */
+    gint base;                              /* Position absolue de segment */
     GBufferSegment *segment;                /* Segment visé par le pointeur*/
     size_t first;                           /* Première ligne intégrée     */
 
-    tmp_x = x;
+    offset = x;
 
-    tmp_x -= view->left_text;
-    if (tmp_x < 0) return NULL;
+    offset -= view->left_text;
+    if (offset < 0) return NULL;
 
-    segment = g_buffer_line_get_segment_at(line, view->max_widths, display, &tmp_x, GDK_SCROLL_LEFT, true);
-    if (segment == NULL) printf(" -- no segment OLD\n");
+    segment = g_buffer_line_get_segment_at(line, view->max_widths, display, &base, &offset, GDK_SCROLL_LEFT, true);
     if (segment == NULL) return NULL;
 
-    printf("\n[BASE OLD]  tronc = %d   reste = %d   dernier = %d   largeur = %d\n",
-           x - tmp_x, tmp_x, g_buffer_segment_get_caret_position(segment, tmp_x),
-           g_buffer_segment_get_width(segment));
-
-    printf("        '%s'\n", g_buffer_segment_get_text(segment, false));
-
-    caret->x = view->left_text + tmp_x;//(x - tmp_x) + g_buffer_segment_get_caret_position(segment, tmp_x);
+    caret->x = view->left_text + base + offset;
 
     first = g_code_buffer_get_index_from_address(view->buffer, view->start, true);
     caret->y = (index - first) * view->line_height;
@@ -1438,25 +1433,21 @@ const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *view, GBufferLine *l
 
 static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, const bool *display)
 {
-    bool result;
-
-    gint tmp_x;                             /* Copie de travail modifiable */
+    bool result;                            /* Bilan à retourner           */
+    gint offset;                            /* Point de travail modifiable */
+    gint base;                              /* Position absolue de segment */
     GBufferSegment *segment;                /* Segment visé par le pointeur*/
     size_t first;                           /* Première ligne intégrée     */
 
     gint ref_x;
 
 
-    gint offset;
-
+    offset = caret->x;
 
+    offset -= view->left_text;
+    if (offset < 0) return false;
 
-    tmp_x = caret->x;
-
-    tmp_x -= view->left_text;
-    if (tmp_x < 0) return false;
-
-    segment = g_buffer_line_get_segment_at(line, view->max_widths, display, &tmp_x, dir, false);
+    segment = g_buffer_line_get_segment_at(line, view->max_widths, display, &base, &offset, dir, false);
 
     if (segment == NULL) printf(" ===== NO SEG...\n");
 
@@ -1467,25 +1458,22 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
 
 
 
-    ref_x = tmp_x;
+    ref_x = offset;
 
 
 
     //if (dir == GDK_SCROLL_LEFT || dir == GDK_SCROLL_RIGHT)
-        result = g_buffer_segment_move_caret(segment, &tmp_x, ctrl, dir);
+        result = g_buffer_segment_move_caret(segment, &offset, ctrl, dir);
     //else
         //result = true;
 
     printf(" ====== MOVE 1 ? %d\n", result);
 
-    if (result)
-        caret->x += (tmp_x - ref_x);
-
     ///////////////////
 
     if (!result)
     {
-
+        base = 0;
 
         segment = g_buffer_line_find_near_segment(line, segment, view->max_widths, display, dir, &offset);
 
@@ -1494,20 +1482,9 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
 
         if (segment != NULL)
         {
-            //tmp_x = /*ref_x + */g_buffer_segment_get_width(segment);
-
-
-            //ref_x = tmp_x;
-            ref_x = tmp_x = 0;
-
-
-            ref_x = 0;
-            tmp_x = view->left_text + offset;
-
-            caret->x = tmp_x;
 
             result = true;
-            //result = g_buffer_segment_move_caret(segment, &tmp_x, ctrl, dir);
+            //result = g_buffer_segment_move_caret(segment, &offset, ctrl, dir);
 
             /*
             if (result)
@@ -1524,33 +1501,17 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
 
 
     if (result)
-        printf(" ====== NEW CARET: %d -> %d\n", caret->x, caret->x + (tmp_x - ref_x));
+        printf(" ====== NEW CARET: %d -> %d\n", caret->x, view->left_text + base + offset);
     else
         printf(" ====== NO NEW CARET!\n");
 
 
-    /*
-    if (result)
-        caret->x += (tmp_x - ref_x);
-    */
 
+    if (result)
+        caret->x = view->left_text + base + offset;
 
     return result;
 
-
-    //bool g_buffer_segment_move_caret(const GBufferSegment *segment, gint *x, bool ctrl, GdkScrollDirection dir)
-
-
-
-    /* TODO : utiliser les arguments booléens */
-
-    caret->x += (dir == GDK_SCROLL_RIGHT ? 10 : -10);
-
-    return true;
-
-
-    return false;
-
 }
 
 
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index ef4f985..ef5aac6 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -260,7 +260,8 @@ static gboolean gtk_buffer_view_button_press(GtkWidget *widget, GdkEventButton *
     else
     {
         //addr = g_buffer_view_compute_caret_old(view->buffer_view, line, index, real_x, pview->display, &new);
-        addr = g_buffer_view_compute_caret(view->buffer_view, real_x, real_y, pview->display, &new);
+        //addr = g_buffer_view_compute_caret(view->buffer_view, real_x, real_y, pview->display, &new);
+        addr = g_buffer_view_compute_caret_full(view->buffer_view, line, index, real_x, pview->display, &new);
         gtk_buffer_view_relocate_caret(view, &new, addr);
     }
 
-- 
cgit v0.11.2-87-g4458