summaryrefslogtreecommitdiff
path: root/src/glibext/gbufferline.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-11-01 20:31:29 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-11-01 20:31:29 (GMT)
commit67c0fe6eddda7ac5ff591ec972425095209d75ff (patch)
treed2f923845545c9b7f94968e9b9ded7539f3dbb7b /src/glibext/gbufferline.c
parent085fef16a819cb321fd38e7e0926d3cca863777a (diff)
Moved the caret with mouse and keyboard.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@417 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/glibext/gbufferline.c')
-rw-r--r--src/glibext/gbufferline.c324
1 files changed, 284 insertions, 40 deletions
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index cb5c267..6970dac 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -56,13 +56,19 @@ typedef struct _buffer_line_column
static void reset_column(buffer_line_column *);
/* Fournit la quantité de pixels requise pour l'impression. */
-static gint get_column_width(buffer_line_column *);
+static gint get_column_width(const buffer_line_column *);
/* Ajoute un fragment de texte à une colonne de ligne. */
static void add_segment_to_column(buffer_line_column *, GBufferSegment *);
+#define get_first_segment(col) ((col)->count > 0 ? (col)->segments[0] : NULL)
+#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 *, bool);
+static GBufferSegment *get_segment_at(const buffer_line_column *, gint *, GdkScrollDirection);
+
+/* Fournit le segment voisin d'un autre segment identifié. */
+static GBufferSegment *find_near_segment(const buffer_line_column *, GBufferSegment *, GdkScrollDirection, bool *);
/* Met en surbrillance des segments similaires. */
GSList *highlight_all_same_segments(const buffer_line_column *, GSList *, const GBufferSegment *);
@@ -129,7 +135,7 @@ static void g_buffer_line_init(GBufferLine *);
static void reset_column(buffer_line_column *column)
{
- column->max_width = -1;
+ column->max_width = 0;
}
@@ -146,19 +152,8 @@ static void reset_column(buffer_line_column *column)
* *
******************************************************************************/
-static gint get_column_width(buffer_line_column *column)
+static gint get_column_width(const buffer_line_column *column)
{
- size_t i; /* Boucle de parcours */
-
- if (column->max_width == -1)
- {
- column->max_width = 0;
-
- for (i = 0; i < column->count; i++)
- column->max_width += g_buffer_segment_get_width(column->segments[i]);
-
- }
-
return column->max_width;
}
@@ -189,6 +184,8 @@ static void add_segment_to_column(buffer_line_column *column, GBufferSegment *se
column->segments[column->count - 1] = segment;
+ column->max_width += g_buffer_segment_get_width(segment);
+
}
@@ -196,7 +193,7 @@ static void add_segment_to_column(buffer_line_column *column, GBufferSegment *se
* *
* Paramètres : column = colonne de ligne de texte à consulter. *
* x = position de recherche à ajuster. [OUT] *
-* force = accepte les segments en bordure au pire. *
+* dir = direction d'un éventuel déplacement en cours. *
* *
* Description : Donne le segment d'une colonne présent à une abscisse donnée.*
* *
@@ -206,19 +203,37 @@ static void add_segment_to_column(buffer_line_column *column, GBufferSegment *se
* *
******************************************************************************/
-static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, bool force)
+static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, GdkScrollDirection dir)
{
GBufferSegment *result; /* Trouvaille à retourner */
size_t i; /* Boucle de parcours */
gint width; /* Largeur à retirer */
+ bool included; /* Appartenance à une largeur ?*/
result = NULL;
+ printf(" == gs@ == count = %d width = %d\n",
+ column->count, get_column_width(column));
+
for (i = 0; i < column->count && result == NULL; i++)
{
width = g_buffer_segment_get_width(column->segments[i]);
- if (width > *x || ((i + 1) == column->count && force))
+ printf(" -s- |%d| -> x=%d w=%d\n", i, *x, width);
+
+ /**
+ * Soit une limite entre deux segments A et B :
+ *
+ * - dans le cas d'un déplacement vers la gauche, on part de cette limite
+ * pour progresser à l'intérieur de A. Donc la limite fait partie de A.
+ *
+ * - dans le cas d'un déplacement vers la droite, on part de cette limite
+ * pour progresser à l'intérieur de B. Donc la limite ne fait pas partie de A.
+ */
+ if (dir == GDK_SCROLL_LEFT) included = (width >= *x);
+ else included = (width > *x);
+
+ if (included || (i + 1) == column->count)
result = column->segments[i];
else
@@ -226,6 +241,59 @@ static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x,
}
+ printf(" == gs@ == > segment = %p\n", result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : column = colonne de ligne de texte à consulter. *
+* target = segment dont un voisin est à retourner. *
+* dir = orientation des recherches. *
+* out = renvoie vers une bordure extérieur au besoin. [OUT] *
+* *
+* Description : Fournit le segment voisin d'un autre segment identifié. *
+* *
+* Retour : Segment trouvé ou NULL si hors borne ou inconnu. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GBufferSegment *find_near_segment(const buffer_line_column *column, GBufferSegment *target, GdkScrollDirection dir, bool *out)
+{
+ GBufferSegment *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+ *out = false;
+
+ for (i = 0; i < column->count; i++)
+ if (column->segments[i] == target) break;
+
+ if (i < column->count)
+ switch (dir)
+ {
+ case GDK_SCROLL_LEFT:
+ *out = (i == 0);
+ if (!*out)
+ result = column->segments[i - 1];
+ break;
+
+ case GDK_SCROLL_RIGHT:
+ *out = ((i + 1) == column->count);
+ if (!*out)
+ result = column->segments[i + 1];
+ break;
+
+ default:
+ break;
+
+ }
+
return result;
}
@@ -518,7 +586,9 @@ 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] *
+* dir = direction d'un éventuel déplacement en cours. *
* force = accepte les segments en bordure au pire. *
* *
* Description : Donne le segment présent à une abscisse donnée. *
@@ -529,30 +599,120 @@ 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], gint *x, bool force)
+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 *result; /* Trouvaille à retourner */
+ gint old; /* Valeur d'origine de position*/
+ BufferLineColumn last; /* Dernière colonne remplie */
+ gint last_x; /* Dernière abscisse associée */
BufferLineColumn i; /* Boucle de parcours */
+ gint width; /* Largeur d'une colonne donnée*/
result = NULL;
+ old = *x;
+ last = BLC_COUNT;
+ last_x = *x; /* Pour GCC */
+
+ printf(" {{ ADDR }} 0x%08x\n", line->range.addr.physical);
+
+
+
+
for (i = 0; i < BLC_COUNT; i++)
{
- /* FIXME : addr/code */
+ printf(" @ (%d) x=%d width=%d max=%d display ? %d\n",
+ i, *x, 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_x = *x;
+ }
+
+ if (i < line->merge_start)
+ {
+ width = max_widths[i];
+
+ if (*x <= width) break;
+ else *x -= (max_widths[i] + COL_MARGIN);
+
+ }
+ else
+ {
+ width = get_column_width(&line->columns[i]);
+
+ if (*x <= width) break;
+ else *x -= width;
+
+ }
- if (*x < max_widths[i]) break;
- else *x -= (max_widths[i] + COL_MARGIN);
}
- if (i == BLC_COUNT && force)
+ printf(" -- get segment at -- found index %u (max=%u)\n", i, BLC_COUNT);
+
+
+ printf(" last seen = %u\n", last);
+
+
+
+ if (force)
{
- i = BLC_COUNT - 1;
- *x += (max_widths[i] + COL_MARGIN);
+ if (i == BLC_COUNT)
+ {
+
+ /* Re-calcul des largeurs cumulées */
+
+ if (last == BLC_COUNT) i = BLC_COUNT;
+ else
+ {
+ *x = old;
+
+ for (i = 0; i < last; i++)
+ {
+ if (i < line->merge_start)
+ *x -= (max_widths[i] + COL_MARGIN);
+ else
+ *x -= get_column_width(&line->columns[i]);
+ }
+
+ }
+
+
+ printf(" -- get segment at -- last index %u (max=%u) -->> x = %d\n", i, BLC_COUNT, *x);
+
+
+
+ }
+
+ /* Si on s'est arrêté sur un champ vide... */
+ else if (i != last)
+ {
+ i = last;
+ *x = last_x;
+ }
+
}
+
+
+
+
if (i < BLC_COUNT)
- result = get_segment_at(&line->columns[i], x, force);
+ result = get_segment_at(&line->columns[i], x, dir);
+
+
+ if (result == NULL)
+ printf(" -- get segment at -- found nothing...\n");
+ else
+ printf(" -- get segment at -- found %p '%s'...\n", result, g_buffer_segment_get_text(result));
+
+
return result;
@@ -561,33 +721,117 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
/******************************************************************************
* *
-* Paramètres : line = ligne à venir consulter. *
-* caret = position du curseur à faire évoluer. *
-* ctrl = indique la demande d'un parcours rapide. *
-* dir = direction du parcours. *
-* phys = indique si les positions doivent être affichées. *
-* virt = indique si les adresses doivent être affichées. *
-* code = indique si le code binaire doit être affiché. *
+* Paramètres : line = ligne à venir consulter. *
+* target = segment dont un voisin est à retourner. *
+* max_widths = largeurs de colonne à respecter. XXXXXXXXXXXXXXX *
+* display = règles d'affichage des colonnes modulables. *
+* dir = orientation des recherches. *
+* offset = décalage pour amener à l'extrémité voisine. [OUT] *
* *
-* Description : Déplace le curseur au sein d'une vue de tampon. *
+* Description : Fournit le segment voisin d'un autre segment identifié. *
* *
-* Retour : true si un déplacement a été effectué, false sinon. *
+* Retour : Segment trouvé dans la ligne ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_buffer_line_move_caret(const GBufferLine *line, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, bool phys, bool virt, bool code)
+GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBufferSegment *target, const gint max_widths[BLC_COUNT], const bool *display, GdkScrollDirection dir, gint *offset)
{
+ GBufferSegment *result; /* Trouvaille à retourner */
+ BufferLineColumn i; /* Boucle de parcours */
+ bool out; /* Présence de cible en bordure*/
- /* TODO : utiliser les arguments booléens */
+ result = NULL;
+ *offset = 0;
+
+ for (i = 0; i < BLC_COUNT && result == NULL; i++)
+ {
+ if (i < BLC_DISPLAY && !display[i]) continue;
+
+ result = find_near_segment(&line->columns[i], target, dir, &out);
+
+ printf(" [%d] near seg = %p (out ? %d)\n", i, result, out);
+
+ if (result != NULL) break;
+
+ if (out)
+ {
+ switch (dir)
+ {
+ case GDK_SCROLL_LEFT:
+
+ gblfns_loop_left:
+
+ /* On s'assure que la colonne précédente est visible */
+ if (i <= BLC_DISPLAY)
+ for (; i > BLC_FIRST; i--)
+ if (display[i - 1]) break;
+
+ if (i > BLC_FIRST) result = get_last_segment(&line->columns[i - 1]);
+
+ printf(" [near] (%d) %p\n", i, result);
+
+ if (result == NULL && i > BLC_FIRST)
+ {
+ printf(" [loop] %u -> %u\n", i, i - 1);
+ i--;
+ *offset -= (max_widths[i] + COL_MARGIN);
+ goto gblfns_loop_left;
+ }
+
+ if (result != NULL)
+ *offset += g_buffer_segment_get_width(result) - max_widths[i - 1] - COL_MARGIN;
+
+ break;
- caret->x += (dir == GDK_SCROLL_RIGHT ? 10 : -10);
+ case GDK_SCROLL_RIGHT:
- return true;
+ gblfns_loop_right:
+ /* On s'assure que la colonne suivante est visible */
+ for (; (i + 1) < BLC_DISPLAY; i++)
+ if (display[i + 1]) break;
- return false;
+ if ((i + 1) < BLC_COUNT) result = get_first_segment(&line->columns[i + 1]);
+
+
+ printf(" [near] (%d) %p\n", i, result);
+
+ if (result == NULL && (i + 1) < BLC_COUNT)
+ {
+ printf(" [loop] %u -> %u\n", i, i + 1);
+ *offset += (max_widths[i] + COL_MARGIN);
+ printf(" -- add %d ~> %d\n", max_widths[i], *offset);
+ i++;
+ goto gblfns_loop_right;
+ }
+
+ if (result != NULL)
+ {
+ *offset -= g_buffer_segment_get_width(target);
+ *offset += max_widths[i] + COL_MARGIN;
+ printf(" -- add %d ~> %d\n", max_widths[i], *offset);
+ }
+
+
+ /*
+ if (result != NULL)
+ *offset += max_widths[i + 1] - g_buffer_segment_get_width(result) + COL_MARGIN;
+ */
+
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+ }
+
+ return result;
}