From f38d8af1713a2a46a8c2d4499081bd0d123af163 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 9 Apr 2015 20:29:54 +0000 Subject: Fixed all known bugs with the keyboard-based navigation in buffer views. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@507 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 7 ++ src/glibext/gbufferline.c | 257 ++++++++++++++++++++++++++-------------------- src/glibext/gcodebuffer.c | 38 ++++--- src/glibext/gcodebuffer.h | 2 +- 4 files changed, 178 insertions(+), 126 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b89b61..a65a813 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +15-04-09 Cyrille Bagard + + * src/glibext/gbufferline.c: + * src/glibext/gcodebuffer.c: + * src/glibext/gcodebuffer.h: + Fix all known bugs with the keyboard-based navigation in buffer views. + 15-04-06 Cyrille Bagard * src/analysis/block.c: diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 0422af5..e34f86f 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -62,6 +62,9 @@ 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 *); +/* Valide ou non la présence d'un segment dans une colonne. */ +static bool column_has_segment(const buffer_line_column *, const GBufferSegment *, size_t *); + #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) @@ -69,7 +72,7 @@ static void add_segment_to_column(buffer_line_column *, GBufferSegment *); 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 *); +static GBufferSegment *find_near_segment(const buffer_line_column *, GBufferSegment *, GdkScrollDirection); /* Met en surbrillance des segments similaires. */ static GSList *highlight_all_same_segments(const buffer_line_column *, GSList *, const GBufferSegment *); @@ -202,6 +205,36 @@ static void add_segment_to_column(buffer_line_column *column, GBufferSegment *se /****************************************************************************** * * +* Paramètres : column = colonne de ligne à venir consulter. * +* segment = fragment de texte à trouver dans la colonne. * +* index = indice du segment retrouvé ou NULL. [OUT] * +* * +* Description : Valide ou non la présence d'un segment dans une colonne. * +* * +* Retour : Statut de présence du segment indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool column_has_segment(const buffer_line_column *column, const GBufferSegment *segment, size_t *index) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < column->count; i++) + if (column->segments[i] == segment) + { + if (index != NULL) *index = i; + break; + } + + return (i < column->count); + +} + + +/****************************************************************************** +* * * Paramètres : column = colonne de ligne de texte à consulter. * * x = position de recherche à ajuster. [OUT] * * dir = direction d'un éventuel déplacement en cours. * @@ -264,7 +297,6 @@ static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, * 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é. * * * @@ -274,29 +306,25 @@ static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, * * ******************************************************************************/ -static GBufferSegment *find_near_segment(const buffer_line_column *column, GBufferSegment *target, GdkScrollDirection dir, bool *out) +static GBufferSegment *find_near_segment(const buffer_line_column *column, GBufferSegment *target, GdkScrollDirection dir) { 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; + column_has_segment(column, target, &i); if (i < column->count) switch (dir) { case GDK_SCROLL_LEFT: - *out = (i == 0); - if (!*out) + if (i > 0) result = column->segments[i - 1]; break; case GDK_SCROLL_RIGHT: - *out = ((i + 1) == column->count); - if (!*out) + if ((i + 1) < column->count) result = column->segments[i + 1]; break; @@ -743,6 +771,7 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint gint old; /* Valeur d'origine de position*/ BufferLineColumn last; /* Dernière colonne remplie */ gint last_x; /* Dernière abscisse associée */ + gint sum; /* Somme de toutes les largeurs*/ BufferLineColumn i; /* Boucle de parcours */ gint width; /* Largeur d'une colonne donnée*/ @@ -752,10 +781,11 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint last = BLC_COUNT; last_x = *x; /* Pour GCC */ - printf(" {{ ADDR }} 0x%08x\n", line->range.addr.physical); - + sum = 0; + printf("---------------\n"); + /* On cible déjà la colonne idéale */ for (i = 0; i < BLC_COUNT; i++) { @@ -769,7 +799,7 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint if (get_column_width(&line->columns[i]) > 0) { last = i; - last_x = *x; + last_x = sum; } if (i < line->merge_start) @@ -777,7 +807,11 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint width = max_widths[i]; if (*x <= width) break; - else *x -= (max_widths[i] + COL_MARGIN); + else + { + *x -= (max_widths[i] + COL_MARGIN); + sum += width + COL_MARGIN; + } } else @@ -785,7 +819,11 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint width = get_column_width(&line->columns[i]); if (*x <= width) break; - else *x -= width; + else + { + *x -= width; + sum += width; + } } @@ -799,59 +837,57 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint - if (force) + + + if (i < BLC_COUNT) { - if (i == BLC_COUNT) - { - /* Re-calcul des largeurs cumulées */ + printf(" -- width @ %u : %d\n", i, get_column_width(&line->columns[i])); - if (last == BLC_COUNT) i = BLC_COUNT; - else + if (get_column_width(&line->columns[i]) > 0) + result = get_segment_at(&line->columns[i], x, dir); + + /* La position fournie tombe dans une colonne vide ! */ + else + { + if (force || get_column_width(&line->columns[i]) == 0) { - *x = old; + result = NULL; + *x = sum; - for (i = 0; i < last; i++) + for (i++; i < BLC_COUNT && result == NULL; i++) { - if (i < line->merge_start) - *x -= (max_widths[i] + COL_MARGIN); - else - *x -= get_column_width(&line->columns[i]); - } + printf(" -- update to col %u -- x = %d\n", i, *x); - } + if ((i - 1) < line->merge_start) + *x += (max_widths[i - 1] + COL_MARGIN); + else + *x += get_column_width(&line->columns[i - 1]); + result = get_first_segment(&line->columns[i]); - printf(" -- get segment at -- last index %u (max=%u) -->> x = %d\n", i, BLC_COUNT, *x); + } + printf(" -- final x = %d (result=%p)\n", *x, result); + } } - /* Si on s'est arrêté sur un champ vide... */ - else if (i != last) + } + + else /* if (i == BLC_COUNT) */ + { + if (force && last != BLC_COUNT) { - i = last; - *x = last_x; + result = get_last_segment(&line->columns[last]); + *x = last_x + get_column_width(&line->columns[last]); } + else + result = NULL; } - - - - - if (i < BLC_COUNT) - 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, false)); - - - return result; } @@ -861,10 +897,10 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint * * * Paramètres : line = ligne à venir consulter. * * target = segment dont un voisin est à retourner. * -* max_widths = largeurs de colonne à respecter. XXXXXXXXXXXXXXX * +* max_widths = largeurs de colonne à respecter. * * display = règles d'affichage des colonnes modulables. * * dir = orientation des recherches. * -* offset = décalage pour amener à l'extrémité voisine. [OUT] * +* offset = décalage pour amener à l'extrémité nouvelle. [OUT] * * * * Description : Fournit le segment voisin d'un autre segment identifié. * * * @@ -877,93 +913,94 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint 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*/ + BufferLineColumn i; /* Boucle de parcours #1 */ + bool displayed; /* Confort de lecture */ + BufferLineColumn k; /* Boucle de parcours #2 */ result = NULL; - *offset = 0; - for (i = 0; i < BLC_COUNT && result == NULL; i++) - { - if (i < BLC_DISPLAY && !display[i]) continue; + /* Recherche dans la colonne de départ */ + + for (i = 0; i < BLC_COUNT; i++) + if (column_has_segment(&line->columns[i], target, NULL)) + break; - result = find_near_segment(&line->columns[i], target, dir, &out); + if (i == BLC_COUNT) return NULL; - printf(" [%d] near seg = %p (out ? %d)\n", i, result, out); + result = find_near_segment(&line->columns[i], target, dir); + if (result != NULL) return result; - if (result != NULL) break; + /* Recherche dans la direction des colonnes voisines */ - if (out) + if (result == NULL) + switch (dir) { - switch (dir) - { - case GDK_SCROLL_LEFT: + case GDK_SCROLL_LEFT: + + /* Si on a atteint la première colonne sans trouver... */ + if (i == 0) break; - gblfns_loop_left: + /* On s'assure que la colonne précédente est visible et peuplée */ + for (; i > BLC_FIRST && result == NULL; i--) + { + displayed = (i <= BLC_DISPLAY ? display[i - 1] : true); - /* 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 (displayed) + result = get_last_segment(&line->columns[i - 1]); - if (i > BLC_FIRST) result = get_last_segment(&line->columns[i - 1]); + } - printf(" [near] (%d) %p\n", i, result); + break; - 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; - } + case GDK_SCROLL_RIGHT: - if (result != NULL) - *offset += g_buffer_segment_get_width(result) - max_widths[i - 1] - COL_MARGIN; + /* Si on a atteint la dernière colonne sans trouver... */ + /*if (i == BLC_COUNT) break;*/ - break; + /* On s'assure que la colonne suivante est visible et peuplée */ + for (; (i + 1) < BLC_COUNT && result == NULL; i++) + { + displayed = ((i + 1) < BLC_DISPLAY ? display[i + 1] : true); - case GDK_SCROLL_RIGHT: + if (displayed) + result = get_first_segment(&line->columns[i + 1]); - gblfns_loop_right: + } - /* On s'assure que la colonne suivante est visible */ - for (; (i + 1) < BLC_DISPLAY; i++) - if (display[i + 1]) break; + break; - if ((i + 1) < BLC_COUNT) result = get_first_segment(&line->columns[i + 1]); + default: + break; + } - printf(" [near] (%d) %p\n", i, result); + /* Calcul de la position finale */ - 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 = 0; - 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); - } + for (k = 0; k < i; k++) + { + displayed = (k < BLC_DISPLAY ? display[k] : true); + if (displayed) + *offset += max_widths[k] + COL_MARGIN; - /* - if (result != NULL) - *offset += max_widths[i + 1] - g_buffer_segment_get_width(result) + COL_MARGIN; - */ + } - break; + switch (dir) + { + case GDK_SCROLL_LEFT: + *offset += get_column_width(&line->columns[i]); + break; - default: - break; + case GDK_SCROLL_RIGHT: + /**offset += 0;*/ + break; - } + default: + break; } diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index 1d42b35..4b4b2a6 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -1301,7 +1301,10 @@ GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, *segment = NULL; else + { + *x -= view->left_text; *segment = g_buffer_line_get_segment_at(result, view->max_widths, display, x, GDK_SCROLL_LEFT, true); + } } @@ -1345,8 +1348,8 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con - printf("\n[BASE] tronc = %d reste = %d dernier = %d largeur = %d\n", - x - remaining, remaining, g_buffer_segment_get_caret_position(segment, remaining), + printf("\n[BASE] orig = %d tronc = %d reste = %d dernier = %d largeur = %d\n", + x, x - remaining, remaining, g_buffer_segment_get_caret_position(segment, remaining), g_buffer_segment_get_width(segment)); printf(" '%s'\n", g_buffer_segment_get_text(segment, false)); @@ -1354,7 +1357,7 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con - caret->x = (x - remaining) + g_buffer_segment_get_caret_position(segment, remaining); + caret->x = /*view->left_text +*/ (x - remaining) + g_buffer_segment_get_caret_position(segment, remaining); caret->y = (index - view->first_index) * view->line_height; @@ -1383,7 +1386,7 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, con * * ******************************************************************************/ -const vmpa2t *g_buffer_view_compute_caret_old(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret) +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 */ GBufferSegment *segment; /* Segment visé par le pointeur*/ @@ -1395,16 +1398,16 @@ const vmpa2t *g_buffer_view_compute_caret_old(GBufferView *view, GBufferLine *li if (tmp_x < 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\n"); + if (segment == NULL) printf(" -- no segment OLD\n"); if (segment == NULL) return NULL; - printf("\n[BASE] tronc = %d reste = %d dernier = %d largeur = %d\n", + 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 = (x - tmp_x) + g_buffer_segment_get_caret_position(segment, tmp_x); + caret->x = view->left_text + tmp_x;//(x - tmp_x) + g_buffer_segment_get_caret_position(segment, tmp_x); first = g_code_buffer_get_index_from_address(view->buffer, view->start, true); caret->y = (index - first) * view->line_height; @@ -1475,6 +1478,10 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line printf(" ====== MOVE 1 ? %d\n", result); + if (result) + caret->x += (tmp_x - ref_x); + + /////////////////// if (!result) { @@ -1495,8 +1502,9 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line ref_x = 0; - tmp_x = offset; + tmp_x = view->left_text + offset; + caret->x = tmp_x; result = true; //result = g_buffer_segment_move_caret(segment, &tmp_x, ctrl, dir); @@ -1521,10 +1529,10 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line printf(" ====== NO NEW CARET!\n"); - + /* if (result) caret->x += (tmp_x - ref_x); - + */ return result; @@ -1640,7 +1648,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b if (index > first) { line = view->buffer->lines[index - 1]; - result = g_buffer_view_compute_caret_old(view, line, index - 1, caret->x, display, caret); + result = g_buffer_view_compute_caret_full(view, line, index - 1, caret->x, display, caret); } break; @@ -1650,7 +1658,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b if (index < last) { line = view->buffer->lines[index + 1]; - result = g_buffer_view_compute_caret_old(view, line, index + 1, caret->x, display, caret); + result = g_buffer_view_compute_caret_full(view, line, index + 1, caret->x, display, caret); } break; @@ -1665,7 +1673,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b if (!moved && index > first) { line = view->buffer->lines[index - 1]; - result = g_buffer_view_compute_caret_old(view, line, index - 1, INT_MAX, display, caret); + result = g_buffer_view_compute_caret_full(view, line, index - 1, INT_MAX, display, caret); } break; @@ -1680,7 +1688,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b if (!moved && index < last) { line = view->buffer->lines[index + 1]; - result = g_buffer_view_compute_caret_old(view, line, index + 1, left_pos, display, caret); + result = g_buffer_view_compute_caret_full(view, line, index + 1, left_pos, display, caret); } break; @@ -1698,7 +1706,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b /* if (result && !computed) - result = g_buffer_view_compute_caret_old(view, caret->x, caret->y, caret, display, NULL); + result = g_buffer_view_compute_caret_full(view, caret->x, caret->y, caret, display, NULL); */ return result; diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h index cb17821..0877ce8 100644 --- a/src/glibext/gcodebuffer.h +++ b/src/glibext/gcodebuffer.h @@ -135,7 +135,7 @@ GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *, gint *, gint, const vmpa2t *g_buffer_view_compute_caret(GBufferView *, gint, gint, const bool *, GdkRectangle *); /* Calcule la position idéale de curseur pour un point donné. */ -const vmpa2t *g_buffer_view_compute_caret_old(GBufferView *, GBufferLine *, size_t, gint, const bool *, GdkRectangle *) __attribute__ ((deprecated)); +const vmpa2t *g_buffer_view_compute_caret_full(GBufferView *, GBufferLine *, size_t, gint, const bool *, GdkRectangle *); /* Déplace le curseur au sein d'une vue de tampon. */ const vmpa2t *g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkScrollDirection, const bool *); -- cgit v0.11.2-87-g4458