From 3f05bacd4fec23824489b51d964a7ce3565bb85b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 23 Oct 2016 13:59:26 +0200 Subject: Memorized all creators of line content at the line level and saved memory. --- ChangeLog | 22 ++ src/arch/immediate.c | 4 +- src/arch/target.c | 13 +- src/glibext/gbufferline.c | 508 +++++++++++++++++++++++++++++++----------- src/glibext/gbufferline.h | 8 +- src/glibext/gbuffersegment.c | 51 ----- src/glibext/gbuffersegment.h | 6 - src/glibext/gbufferview.c | 56 +++++ src/glibext/gbufferview.h | 3 + src/glibext/gcodebuffer.c | 13 +- src/gtkext/gtkbufferview.c | 41 ++-- src/gtkext/gtkviewpanel-int.h | 2 +- src/gtkext/gtkviewpanel.c | 10 +- src/gtkext/gtkviewpanel.h | 2 +- src/gui/menus/edition.c | 24 +- 15 files changed, 504 insertions(+), 259 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4be9aa4..11da097 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +16-10-23 Cyrille Bagard + + * src/arch/immediate.c: + * src/arch/target.c: + Update code. + + * src/glibext/gbufferline.c: + * src/glibext/gbufferline.h: + * src/glibext/gbuffersegment.c: + * src/glibext/gbuffersegment.h: + Memorize all creators of line content at the line level and save memory. + + * src/glibext/gbufferview.c: + * src/glibext/gbufferview.h: + * src/glibext/gcodebuffer.c: + * src/gtkext/gtkbufferview.c: + * src/gtkext/gtkviewpanel-int.h: + * src/gtkext/gtkviewpanel.c: + * src/gtkext/gtkviewpanel.h: + * src/gui/menus/edition.c: + Update code. + 16-10-22 Cyrille Bagard * src/glibext/gbuffersegment.c: diff --git a/src/arch/immediate.c b/src/arch/immediate.c index 4594e23..777ae14 100644 --- a/src/arch/immediate.c +++ b/src/arch/immediate.c @@ -892,12 +892,10 @@ static void g_imm_operand_print(const GImmOperand *operand, GBufferLine *line, A { char value[IMM_MAX_SIZE]; /* Chaîne à imprimer */ size_t len; /* Taille de l'élément inséré */ - GBufferSegment *segment; /* Nouveau segment mis en place*/ len = g_imm_operand_to_string(operand, syntax, value); - segment = g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_IMMEDIATE); - g_buffer_segment_set_creator(segment, G_OBJECT(operand)); + g_buffer_line_append_text(line, BLC_MAIN, value, len, RTT_IMMEDIATE, G_OBJECT(operand)); } diff --git a/src/arch/target.c b/src/arch/target.c index bf4da3a..0517062 100644 --- a/src/arch/target.c +++ b/src/arch/target.c @@ -212,7 +212,6 @@ GArchOperand *g_target_operand_new(MemoryDataSize size, virt_t addr) static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *line, AsmSyntax syntax) { const char *label; /* Etiquette liée à un symbole */ - GBufferSegment *segment; /* Nouveau segment mis en place*/ vmpa2t tmp; /* Coquille vide pour argument */ VMPA_BUFFER(value); /* Adresse brute à imprimer */ size_t len; /* Taille de l'élément inséré */ @@ -223,19 +222,16 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l g_buffer_line_insert_text(line, BLC_MAIN, "<", 1, RTT_LTGT); label = g_binary_symbol_get_label(operand->symbol); - segment = g_buffer_line_insert_text(line, BLC_MAIN, label, strlen(label), RTT_LABEL); - g_buffer_segment_set_creator(segment, G_OBJECT(operand)); + g_buffer_line_append_text(line, BLC_MAIN, label, strlen(label), RTT_LABEL, G_OBJECT(operand)); if (operand->diff > 0) { - segment = g_buffer_line_insert_text(line, BLC_MAIN, "+", 1, RTT_SIGNS); - g_buffer_segment_set_creator(segment, G_OBJECT(operand)); + g_buffer_line_append_text(line, BLC_MAIN, "+", 1, RTT_SIGNS, G_OBJECT(operand)); init_vmpa(&tmp, operand->diff, VMPA_NO_VIRTUAL); vmpa2_phys_to_string(&tmp, MDS_4_BITS, value, &len); - segment = g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_LABEL); - g_buffer_segment_set_creator(segment, G_OBJECT(operand)); + g_buffer_line_append_text(line, BLC_MAIN, value, len, RTT_LABEL, G_OBJECT(operand)); g_buffer_line_insert_text(line, BLC_MAIN, ">", 1, RTT_LTGT); @@ -247,8 +243,7 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l init_vmpa(&tmp, VMPA_NO_PHYSICAL, operand->addr); vmpa2_virt_to_string(&tmp, operand->size, value, &len); - segment = g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_LABEL); - g_buffer_segment_set_creator(segment, G_OBJECT(operand)); + g_buffer_line_append_text(line, BLC_MAIN, value, len, RTT_LABEL, G_OBJECT(operand)); } diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 0593748..a33817b 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -25,6 +25,7 @@ #include +#include #include #include /* Récupération du langage par défaut ; FIXME ? */ @@ -34,10 +35,6 @@ #include "../gtkext/support.h" -#include /* FIXME : à virer */ - - - /* ---------------------------- REGROUPEMENT PAR COLONNE ---------------------------- */ @@ -63,26 +60,32 @@ static void refresh_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 *); +static void add_segment_to_column(buffer_line_column *, GBufferSegment *) __attribute__ ((deprecated)); + +/* Ajoute un fragment de texte à une colonne de ligne. */ +static size_t append_text_to_line_column(buffer_line_column *, const char *, size_t, RenderingTagType); /* 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 *); +/* Indique l'indice du premier contenu de la colonne. */ +static bool get_column_first_content_index(const buffer_line_column *, size_t *); + +/* Indique l'indice du dernier contenu de la colonne. */ +static bool get_column_last_content_index(const buffer_line_column *, 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) -/* Donne le segment d'une colonne présent à une abscisse donnée. */ -static GBufferSegment *get_segment_at(const buffer_line_column *, gint *, GdkScrollDirection, gint *); +/* Indique l'indice du contenu de colonne à une abscisse donnée. */ +static bool get_column_content_index_at(const buffer_line_column *, gint *, GdkScrollDirection, gint *, size_t *); + +/* Donne le segment d'une colonne présent à un indice donné. */ +static GBufferSegment *get_column_content_from_index(const buffer_line_column *, size_t); /* Fournit le segment voisin d'un autre segment identifié. */ static GBufferSegment *find_near_segment(const buffer_line_column *, GBufferSegment *, GdkScrollDirection); -/* Fournit le segment créé par un objet particulier. */ -static GObject *find_first_segment_creator(const buffer_line_column *); - -/* Fournit le segment créé par un objet particulier. */ -static GBufferSegment *find_segment_from_creator(const buffer_line_column *, GObject *); - /* Imprime le contenu d'une colonne de ligne de texte. */ static void draw_segments_of_column(buffer_line_column *, cairo_t *, gint, gint, const segcnt_list *); @@ -94,6 +97,23 @@ static void export_segments_of_column(buffer_line_column *, buffer_export_contex /* ---------------------------- GESTION DE LINE COMPLETE ---------------------------- */ +/* Identification d'un contenu de colonne */ +typedef struct _col_coord_t +{ + BufferLineColumn column; /* Colonne concernée */ + size_t index; /* Indice d'insertion */ + +} col_coord_t; + +/* Mémorisation des origines de texte */ +typedef struct _content_origin +{ + col_coord_t coord; /* Localisation d'attachement */ + + GObject *creator; /* Origine de la création */ + +} content_origin; + /* Représentation de fragments de texte en ligne (instance) */ struct _GBufferLine { @@ -108,6 +128,9 @@ struct _GBufferLine BufferLineFlags flags; /* Drapeaux particuliers */ + content_origin *origins; /* Mémorisation des origines */ + size_t ocount; /* Nombre de ces mémorisations */ + union { struct @@ -152,6 +175,9 @@ static void g_buffer_line_finalize(GBufferLine *); /* Réagit au changement de contenu d'un segment encapsulé. */ static void on_line_segment_changed(GBufferSegment *, GBufferLine *); +/* Fournit les coordonnées correspondant à une abscisse donnée. */ +static bool g_buffer_line_get_coord_at(const GBufferLine *, const line_width_summary *, const bool *, gint *, gint *, GdkScrollDirection, bool, col_coord_t *); + /* ---------------------------------------------------------------------------------- */ @@ -266,6 +292,41 @@ static void add_segment_to_column(buffer_line_column *column, GBufferSegment *se /****************************************************************************** * * +* Paramètres : column = colonne de ligne à venir compléter. * +* text = texte à insérer dans l'existant. * +* length = taille du texte à traiter. * +* type = type de décorateur à utiliser. * +* * +* Description : Ajoute un fragment de texte à une colonne de ligne. * +* * +* Retour : Indice du point d'insertion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t append_text_to_line_column(buffer_line_column *column, const char *text, size_t length, RenderingTagType type) +{ + size_t result; /* Indice à retourner */ + GBufferSegment *content; /* Contenu à représenter */ + + result = column->count; + + content = g_buffer_segment_new(type, text, length); + + column->segments = (GBufferSegment **)realloc(column->segments, ++column->count * sizeof(GBufferSegment *)); + + column->segments[result] = content; + + column->max_width += g_buffer_segment_get_width(content); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : column = colonne de ligne à venir consulter. * * segment = fragment de texte à trouver dans la colonne. * * index = indice du segment retrouvé ou NULL. [OUT] * @@ -296,38 +357,88 @@ static bool column_has_segment(const buffer_line_column *column, const GBufferSe /****************************************************************************** * * +* Paramètres : column = colonne de ligne de texte à consulter. * +* index = indice du contenu enregistré à la position. [OUT] * +* * +* Description : Indique l'indice du premier contenu de la colonne. * +* * +* Retour : Validité de l'indice renseigné. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool get_column_first_content_index(const buffer_line_column *column, size_t *index) +{ + bool result; /* Bilan à retourner */ + + result = (column->count > 0); + + if (result) + *index = 0; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne de texte à consulter. * +* index = indice du contenu enregistré à la position. [OUT] * +* * +* Description : Indique l'indice du dernier contenu de la colonne. * +* * +* Retour : Validité de l'indice renseigné. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool get_column_last_content_index(const buffer_line_column *column, size_t *index) +{ + bool result; /* Bilan à retourner */ + + result = (column->count > 0); + + if (result) + *index = column->count - 1; + + return result; + +} + + +/****************************************************************************** +* * * 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] * +* index = indice du contenu enregistré à la position. [OUT] * * * -* Description : Donne le segment d'une colonne présent à une abscisse donnée.* +* Description : Indique l'indice du contenu de colonne à une abscisse donnée.* * * -* Retour : Segment trouvé ou NULL si hors borne. * +* Retour : Validité de l'indice renseigné. * * * * Remarques : - * * * ******************************************************************************/ -static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, GdkScrollDirection dir, gint *consumed) +static bool get_column_content_index_at(const buffer_line_column *column, gint *x, GdkScrollDirection dir, gint *consumed, size_t *index) { - GBufferSegment *result; /* Trouvaille à retourner */ + bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ gint width; /* Largeur à retirer */ bool included; /* Appartenance à une largeur ?*/ - result = NULL; + result = false; *consumed = 0; - printf(" == gs@ == count = %d width = %d\n", - column->count, get_column_width(column)); - - for (i = 0; i < column->count && result == NULL; i++) + for (i = 0; i < column->count && !result; i++) { width = g_buffer_segment_get_width(column->segments[i]); - printf(" -s- |%d| -> x=%d w=%d\n", i, *x, width); - /** * Soit une limite entre deux segments A et B : * @@ -341,11 +452,15 @@ static GBufferSegment *get_segment_at(const buffer_line_column *column, gint *x, else included = (width > *x); if (included) - result = column->segments[i]; + { + *index = i; + result = true; + } else if ((i + 1) == column->count) { - result = column->segments[i]; + *index = i; + result = true; *x = width; } @@ -357,7 +472,31 @@ 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. * +* index = indice du contenu à fournir. * +* * +* Description : Donne le segment d'une colonne présent à un indice donné. * +* * +* Retour : Segment trouvé ou NULL si hors borne. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferSegment *get_column_content_from_index(const buffer_line_column *column, size_t index) +{ + GBufferSegment *result; /* Trouvaille à retourner */ + + assert(index < column->count); + + result = column->segments[index]; return result; @@ -413,68 +552,6 @@ static GBufferSegment *find_near_segment(const buffer_line_column *column, GBuff /****************************************************************************** * * -* Paramètres : column = colonne de ligne de texte à consulter. * -* * -* Description : Fournit le segment créé par un objet particulier. * -* * -* Retour : Créateur trouvé à déréférencer par la suite ou NULL si échec.* -* * -* Remarques : - * -* * -******************************************************************************/ - -static GObject *find_first_segment_creator(const buffer_line_column *column) -{ - GObject *result; /* Trouvaille à retourner */ - size_t i; /* Boucle de parcours */ - - result = NULL; - - for (i = 0; i < column->count && result == NULL; i++) - result = g_buffer_segment_get_creator(column->segments[i]); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : column = colonne de ligne de texte à consulter. * -* creator = créateur à l'origine du segment recherché. * -* * -* Description : Fournit le segment créé par un objet particulier. * -* * -* Retour : Segment trouvé ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GBufferSegment *find_segment_from_creator(const buffer_line_column *column, GObject *creator) -{ - GBufferSegment *result; /* Trouvaille à retourner */ - size_t i; /* Boucle de parcours #1 */ - GBufferSegment *iter; /* Boucle de parcours #2 */ - - result = NULL; - - for (i = 0; i < column->count && result == NULL; i++) - { - iter = column->segments[i]; - - if (g_buffer_segment_get_creator(iter) == creator) - result = iter; - - } - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : column = colonne de ligne de texte à manipuler. * * cairo = contexte graphique à utiliser pour les pinceaux. * * x_init = abscisse du point d'impression de départ. * @@ -660,9 +737,14 @@ static void g_buffer_line_init(GBufferLine *line) static void g_buffer_line_dispose(GBufferLine *line) { + size_t i; /* Boucle de parcours */ + if (line->flags & BLF_WIDTH_MANAGER) g_object_unref(G_OBJECT(line->manager)); + for (i = 0; i < line->ocount; i++) + g_object_unref(G_OBJECT(line->origins[i].creator)); + G_OBJECT_CLASS(g_buffer_line_parent_class)->dispose(G_OBJECT(line)); } @@ -684,6 +766,10 @@ static void g_buffer_line_finalize(GBufferLine *line) { /* TODO : segments des colonnes... */ + + if (line->origins != NULL) + free(line->origins); + G_OBJECT_CLASS(g_buffer_line_parent_class)->finalize(G_OBJECT(line)); } @@ -925,10 +1011,17 @@ void g_buffer_line_fill_for_instr(GBufferLine *line, MemoryDataSize psize, Memor GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *line, BufferLineColumn column) { GObject *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ assert(column < BLC_COUNT); - result = find_first_segment_creator(&line->columns[column]); + result = NULL; + + for (i = 0; i < line->ocount && result == NULL; i++) + { + if (line->origins[i].coord.column == column) + result = line->origins[i].creator; + } if (result != NULL) g_object_ref(G_OBJECT(result)); @@ -954,12 +1047,24 @@ GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *line, Buffe GBufferSegment *g_buffer_line_find_segment_from_creator(const GBufferLine *line, GObject *creator) { GBufferSegment *result; /* Trouvaille à retourner */ - BufferLineColumn i; /* Boucle de parcours */ + size_t i; /* Boucle de parcours */ + const col_coord_t *coord; /* Emplacement du contenu visé */ result = NULL; - for (i = 0; i < BLC_COUNT && result == NULL; i++) - result = find_segment_from_creator(&line->columns[i], creator); + for (i = 0; i < line->ocount; i++) + { + if (line->origins[i].creator == creator) + { + coord = &line->origins[i].coord; + + result = get_column_content_from_index(&line->columns[coord->column], coord->index); + + break; + + } + + } if (result != NULL) g_object_ref(G_OBJECT(result)); @@ -1049,6 +1154,57 @@ GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn co /****************************************************************************** * * +* Paramètres : line = ligne à venir compléter. * +* column = colonne de la ligne visée par l'insertion. * +* text = texte à insérer dans l'existant. * +* length = taille du texte à traiter. * +* type = type de décorateur à utiliser. * +* creator = instance GLib quelconque à associer. * +* * +* Description : Ajoute du texte à formater dans une ligne donnée. * +* * +* Retour : Portion de texte mis en place, voire NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_line_append_text(GBufferLine *line, BufferLineColumn column, const char *text, size_t length, RenderingTagType type, GObject *creator) +{ + size_t index; /* Indice d'insertion */ + content_origin *origin; /* Définition d'une origine */ + + assert(length > 0); + + if (column == BLC_MAIN) + column = line->main_column; + + if (column == BLC_LAST_USED) + column = line->last_used; + else + line->last_used = column; + + index = append_text_to_line_column(&line->columns[column], text, length, type); + + if (creator != NULL) + { + line->origins = (content_origin *)realloc(line->origins, ++line->ocount * sizeof(content_origin)); + + origin = &line->origins[line->ocount - 1]; + + origin->coord.column = column; + origin->coord.index = index; + + origin->creator = creator; + g_object_ref(G_OBJECT(creator)); + + } + +} + + +/****************************************************************************** +* * * Paramètres : line = ligne à venir consulter. * * first = première colonne à parcourir. * * end = colonne de fin de parcours. * @@ -1444,46 +1600,38 @@ gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn i * offset = position à la colonne visée. [OUT] * * dir = direction d'un éventuel déplacement en cours. * * force = accepte les segments en bordure au pire. * +* coord = cordonnées à usage interne à renseigner. [OUT] * * * -* Description : Donne le segment présent à une abscisse donnée. * +* Description : Fournit les coordonnées correspondant à une abscisse donnée. * * * -* Retour : Segment trouvé ou NULL si hors borne. * +* Retour : true si des coordonnées valides ont été renseignées. * * * * Remarques : - * * * ******************************************************************************/ -GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_width_summary *summary, const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force) +static bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summary *summary, const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force, col_coord_t *coord) { - GBufferSegment *result; /* Trouvaille à retourner */ + bool result; /* Bilan à 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 limit; /* Limite d'appartenance */ gint consumed; /* Distance vers le segment */ gint old_base; /* Somme de toutes les largeurs*/ - result = NULL; + result = false; *base = 0; last = BLC_COUNT; - - //sum = 0; - - printf("---------------\n"); + last_base = 0; /* 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]), summary->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... */ @@ -1524,19 +1672,11 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const line } - printf(" -- get segment at -- found index %u (max=%u)\n", i, BLC_COUNT); - - - printf(" last seen = %u\n", last); - - - - + /* Si l'abscisse fournie tombe encore dans une colonne... */ if (i < BLC_COUNT) { - - printf(" -- width @ %u : %d\n", i, get_column_width(&line->columns[i])); + /* Il y a bien du contenu dans cette colonne */ if (get_column_width(&line->columns[i]) > 0) { @@ -1547,25 +1687,31 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const line */ if (*offset < 0) *offset = 0; - result = get_segment_at(&line->columns[i], offset, dir, &consumed); - *base += consumed; + result = get_column_content_index_at(&line->columns[i], offset, dir, &consumed, &coord->index); + + if (result) + { + coord->column = i; + + *base += consumed; + + } } /* La position fournie tombe dans une colonne vide ! */ + else { if (force || get_column_width(&line->columns[i]) == 0) { - result = NULL; + result = false; *offset = 0; old_base = *base; - for (i++; i < BLC_COUNT && result == NULL; i++) + for (i++; i < BLC_COUNT && !result; i++) { - printf(" -- update to col %u -- x = %d\n", i, *offset); - if ((i - 1) < line->merge_start) { width = g_buffer_line_compute_max_width(line, i - 1, summary); @@ -1574,13 +1720,14 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const line else *base += get_column_width(&line->columns[i - 1]); - result = get_first_segment(&line->columns[i]); + result = get_column_first_content_index(&line->columns[i], &coord->index); - } + if (result) + coord->column = i; - printf(" -- final x = %d (result=%p)\n", *offset, result); + } - if (result == NULL) + if (!result) { *base = old_base; goto use_right_border; @@ -1600,16 +1747,109 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const line if (last != BLC_COUNT) { - result = get_last_segment(&line->columns[last]); - *base = last_base; - *offset = get_column_width(&line->columns[last]); + result = get_column_last_content_index(&line->columns[last], &coord->index); + + if (result) + { + coord->column = last; + + *base = last_base; + *offset = get_column_width(&line->columns[last]); + + } + } else - result = NULL; + result = false; } else - result = NULL; + result = false; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : line = ligne à venir consulter. * +* summary = résumé des largeurs maximales. * +* display = règles d'affichage des colonnes modulables. * +* 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. * +* * +* Description : Donne le segment présent à une abscisse donnée. * +* * +* Retour : Segment trouvé ou NULL si hors borne. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_width_summary *summary, const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force) +{ + GBufferSegment *result; /* Trouvaille à retourner */ + col_coord_t coord; /* Emplacement du contenu visé */ + bool status; /* Bilan de la localisation */ + + status = g_buffer_line_get_coord_at(line, summary, display, base, offset, dir, force, &coord); + + if (status) + result = get_column_content_from_index(&line->columns[coord.column], coord.index); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : line = ligne à venir consulter. * +* summary = résumé des largeurs maximales. * +* display = règles d'affichage des colonnes modulables. * +* 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. * +* * +* Description : Donne le créateur présent à une abscisse donnée. * +* * +* Retour : Créateur trouvé ou NULL si hors borne. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObject *g_buffer_line_get_creator_at(const GBufferLine *line, const line_width_summary *summary, const bool *display, gint *base, gint *offset, GdkScrollDirection dir, bool force) +{ + GObject *result; /* Trouvaille à retourner */ + col_coord_t target; /* Emplacement du contenu visé */ + bool status; /* Bilan de la localisation */ + size_t i; /* Boucle de parcours */ + const col_coord_t *coord; /* Emplacement du contenu visé */ + + result = NULL; + + status = g_buffer_line_get_coord_at(line, summary, display, base, offset, dir, force, &target); + + if (status) + { + for (i = 0; i < line->ocount && result == NULL; i++) + { + coord = &line->origins[i].coord; + + if (coord->column == target.column && coord->index == target.index) + result = line->origins[i].creator; + + } + + if (result != NULL) + g_object_ref(G_OBJECT(result)); } diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index 6b213e3..9403d80 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -121,7 +121,10 @@ GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *, BufferLin GBufferSegment *g_buffer_line_find_segment_from_creator(const GBufferLine *, GObject *); /* Ajoute du texte à formater dans une ligne donnée. */ -GBufferSegment *g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType); +GBufferSegment *g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType) __attribute__ ((deprecated)); + +/* Ajoute du texte à formater dans une ligne donnée. */ +void g_buffer_line_append_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType, GObject *); /* Indique si du texte est présent dans une ligne de tampon. */ bool g_buffer_line_has_text(const GBufferLine *, BufferLineColumn, BufferLineColumn); @@ -184,6 +187,9 @@ gint g_buffer_line_compute_max_width(const GBufferLine *, BufferLineColumn, cons /* Donne le segment présent à une abscisse donnée. */ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const line_width_summary *, const bool *, gint *, gint *, GdkScrollDirection, bool); +/* Donne le créateur présent à une abscisse donnée. */ +GObject *g_buffer_line_get_creator_at(const GBufferLine *, const line_width_summary *, 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 line_width_summary *, const bool *, GdkScrollDirection, gint *); diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c index a2947ae..dfa8c41 100644 --- a/src/glibext/gbuffersegment.c +++ b/src/glibext/gbuffersegment.c @@ -141,8 +141,6 @@ struct _GBufferSegment seg_content *content; /* Contenu, partagé ou non */ - GObject *creator; /* Objet à l'origine du segment*/ - }; /* Fragment de caractères aux propriétés communes (classe) */ @@ -588,9 +586,6 @@ static void g_buffer_segment_dispose(GBufferSegment *segment) { release_shared_content(segment->content); - if (segment->creator != NULL) - g_object_unref(segment->creator); - G_OBJECT_CLASS(g_buffer_segment_parent_class)->dispose(G_OBJECT(segment)); } @@ -647,52 +642,6 @@ GBufferSegment *g_buffer_segment_new(RenderingTagType type, const char *text, si /****************************************************************************** * * -* Paramètres : segment = instance de segment à compléter. * -* obj = instance GLib quelconque à mémoriser. * -* * -* Description : Associe à un segment un objet GLib identifié comme créateur. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_buffer_segment_set_creator(GBufferSegment *segment, GObject *obj) -{ - if (segment->creator != NULL) - g_object_unref(segment->creator); - - segment->creator = obj; - g_object_ref(obj); - -} - - -/****************************************************************************** -* * -* Paramètres : segment = instance de segment à compléter. * -* * -* Description : Renvoie vers un éventuel objet lié en tant que créateur. * -* * -* Retour : Instance GLib quelconque ou NULL si aucune référencée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GObject *g_buffer_segment_get_creator(const GBufferSegment *segment) -{ - if (segment->creator != NULL) - g_object_ref(segment->creator); - - return segment->creator; - -} - - -/****************************************************************************** -* * * Paramètres : segment = fragment de texte à mettre à jour. * * pattern = paramètres d'impression du texte. * * text = chaîne de caractères à traiter. * diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h index 911df7b..01fb2ea 100644 --- a/src/glibext/gbuffersegment.h +++ b/src/glibext/gbuffersegment.h @@ -115,12 +115,6 @@ GType g_buffer_segment_get_type(void); /* Crée un nouveau fragment de texte avec des propriétés. */ GBufferSegment *g_buffer_segment_new(RenderingTagType, const char *, size_t); -/* Associe à un segment un objet GLib identifié comme créateur. */ -void g_buffer_segment_set_creator(GBufferSegment *, GObject *); - -/* Renvoie vers un éventuel objet lié en tant que créateur. */ -GObject *g_buffer_segment_get_creator(const GBufferSegment *); - /* Met à jour le contenu d'un fragment de texte. */ void g_buffer_segment_update_text(GBufferSegment *, const char *, size_t); diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c index cfa521e..2deeffe 100644 --- a/src/glibext/gbufferview.c +++ b/src/glibext/gbufferview.c @@ -1266,6 +1266,62 @@ GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, /****************************************************************************** * * +* Paramètres : view = visualisation à consulter. * +* x = abscisse comprise dans le segment recherché. [OUT] * +* y = ordonnée comprise dans la ligne recherchée. * +* idx = indice de la ligne trouvée ou NULL. [OUT] * +* display = règles d'affichage des colonnes modulables. * +* creator = instance à l'origine de la représentation. [OUT] * +* * +* Description : Fournit la ligne et son segment présents à une position. * +* * +* Retour : Ligne retrouvée ou NULL si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, GObject **creator) +{ + GBufferLine *result; /* Ligne trouvée à retourner */ + size_t index; /* Indice de la ligne trouvée */ + GBufferViewClass *class; /* Classe pour les vues */ + line_width_summary summary; /* Résumé concis des largeurs */ + + /* Recherche d'une ligne correspondante */ + + result = g_buffer_view_find_line_at(view, y, &index); + + if (idx != NULL) *idx = index; + + /* Recherche du segment visé éventuel */ + + if (result != NULL && creator != NULL) + { + class = G_BUFFER_VIEW_GET_CLASS(view); + + if (*x < class->left_text) + *creator = NULL; + + else + { + g_width_tracker_get_local_width_summary(view->tracker, index, &summary); + + *x -= class->left_text; + *creator = g_buffer_line_get_creator_at(result, &summary, display, + (gint []) { 0 }, x, GDK_SCROLL_LEFT, true); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : view = composant GTK à consulter. * * addr = adresse à présenter à l'écran. * * x = position horizontale au sein du composant. [OUT] * diff --git a/src/glibext/gbufferview.h b/src/glibext/gbufferview.h index 90c20bb..d5bfd3d 100644 --- a/src/glibext/gbufferview.h +++ b/src/glibext/gbufferview.h @@ -104,6 +104,9 @@ GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *); /* Fournit la ligne et son segment présents à une position. */ GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *, gint *, gint, size_t *, const bool *, GBufferSegment **); +/* Fournit la ligne et son segment présents à une position. */ +GBufferLine *g_buffer_view_find_line_and_creator_at(GBufferView *, gint *, gint, size_t *, const bool *, GObject **); + /* Indique la position d'affichage d'une adresse donnée. */ bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, gint *, gint *, bool); diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index c3c5a78..9961cbc 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -1077,7 +1077,6 @@ static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLin char *saveptr; /* Sauvegarde pour la sécurité */ char *token; /* Fragment à insérer */ size_t len; /* Taille dudit fragment */ - GBufferSegment *segment; /* Segment à marquer au fer */ GBufferLine *new; /* Nouvelle ligne créée */ size_t i; /* Boucle de parcours */ @@ -1099,17 +1098,13 @@ static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLin len = strlen(token); if (!result) - { - segment = g_buffer_line_insert_text(line, BLC_COMMENTS, token, len, RTT_COMMENT); - g_buffer_segment_set_creator(segment, creator); - } + g_buffer_line_append_text(line, BLC_COMMENTS, token, len, RTT_COMMENT, creator); else { new = g_code_buffer_prepare_new_line(buffer, range); - segment = g_buffer_line_insert_text(new, BLC_COMMENTS, token, len, RTT_COMMENT); - g_buffer_segment_set_creator(segment, creator); + g_buffer_line_append_text(new, BLC_COMMENTS, token, len, RTT_COMMENT, creator); extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *)); @@ -1201,7 +1196,6 @@ static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine * char *token; /* Fragment à insérer */ size_t len; /* Taille dudit fragment */ GBufferLine *new; /* Nouvelle ligne créée */ - GBufferSegment *segment; /* Segment à marquer au fer */ size_t i; /* Boucle de parcours */ assert(!g_buffer_line_has_comment(line)); @@ -1224,8 +1218,7 @@ static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine * new = g_code_buffer_prepare_new_line(buffer, range); g_buffer_line_start_merge_at(new, BLC_DISPLAY); - segment = g_buffer_line_insert_text(new, BLC_DISPLAY, token, len, RTT_COMMENT); - g_buffer_segment_set_creator(segment, creator); + g_buffer_line_append_text(new, BLC_DISPLAY, token, len, RTT_COMMENT, creator); extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *)); diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c index 2032547..2d1b51c 100644 --- a/src/gtkext/gtkbufferview.c +++ b/src/gtkext/gtkbufferview.c @@ -80,7 +80,7 @@ static const vmpa2t *gtk_buffer_view_get_caret_location(const GtkBufferView *); static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *, const vmpa2t *, gint *, gint *, ScrollPositionTweak); /* Fournit des éléments liés à la position courante dans la vue. */ -static bool gtk_buffer_view_get_position(const GtkBufferView *, GBufferLine **, GBufferSegment **); +static bool gtk_buffer_view_get_position(const GtkBufferView *, GBufferLine **, GObject **); /* Place en cache un rendu destiné à l'aperçu graphique rapide. */ static void gtk_buffer_view_cache_glance(GtkBufferView *, cairo_t *, const GtkAllocation *, double); @@ -557,11 +557,11 @@ static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event) static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard, GtkTooltip *tooltip) { + gboolean result; /* Bilan à retourner */ GtkBufferView *view; /* Autre version du composant */ gint real_x; /* Abscisse absolue réelle */ gint real_y; /* Ordonnée absolue réelle */ GBufferLine *line; /* Ligne en cours de survol */ - GBufferSegment *segment; /* Segment actif s'il existe */ GObject *creator; /* Créateur à l'orgine du seg. */ virt_t virt; /* Adresse virtuelle */ vmpa2t addr; /* Adresse de destination */ @@ -579,6 +579,8 @@ static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y, if (keyboard) return FALSE; + result = FALSE; + view = GTK_BUFFER_VIEW(widget); /* Récupération de la destination pointée */ @@ -587,14 +589,11 @@ static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y, real_y = y; gtk_view_panel_compute_real_coord(GTK_VIEW_PANEL(view), &real_x, &real_y); - line = g_buffer_view_find_line_and_segment_at(view->buffer_view, + line = g_buffer_view_find_line_and_creator_at(view->buffer_view, &real_x, real_y, NULL, - GTK_VIEW_PANEL(view)->display, &segment); - - if (line == NULL || segment == NULL) goto no_tooltip; + GTK_VIEW_PANEL(view)->display, &creator); - creator = g_buffer_segment_get_creator(segment); - if (creator == NULL) goto no_tooltip; + if (line == NULL || creator == NULL) goto no_tooltip; /** * On fait le pari de reposer uniquement sur des adresses virtuelles ! @@ -677,14 +676,20 @@ static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y, /* Impression finale */ + result = TRUE; + gtk_tooltip_set_markup(tooltip, markup); free(markup); - return TRUE; - no_tooltip: - return FALSE; + if (creator != NULL) + g_object_unref(creator); + + if (line != NULL) + g_object_unref(G_OBJECT(line)); + + return result; } @@ -862,7 +867,7 @@ static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *view, c * * * Paramètres : view = composant GTK à consulter. * * line = ligne de tampon où se trouve le curseur. [OUT] * -* segment = eventuel segment de ligne actif. [OUT] * +* creator = instance à l'origine de la représentation. [OUT] * * * * Description : Fournit des éléments liés à la position courante dans la vue.* * * @@ -872,20 +877,20 @@ static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *view, c * * ******************************************************************************/ -static bool gtk_buffer_view_get_position(const GtkBufferView *view, GBufferLine **line, GBufferSegment **segment) +static bool gtk_buffer_view_get_position(const GtkBufferView *view, GBufferLine **line, GObject **creator) { - GBufferSegment *seg; /* Segment à récupérer */ + GObject *obj; /* Elément à récupérer */ /* Si aucune position n'est définie... */ if (view->caret_addr == NULL) return false; - *line = g_buffer_view_find_line_and_segment_at(view->buffer_view, + *line = g_buffer_view_find_line_and_creator_at(view->buffer_view, (gint []){ view->caret.x }, view->caret.y, NULL, - GTK_VIEW_PANEL(view)->display, &seg); + GTK_VIEW_PANEL(view)->display, &obj); - if (segment != NULL) - *segment = seg; + if (creator != NULL) + *creator = obj; return (line != NULL); diff --git a/src/gtkext/gtkviewpanel-int.h b/src/gtkext/gtkviewpanel-int.h index f827b2c..5e24bec 100644 --- a/src/gtkext/gtkviewpanel-int.h +++ b/src/gtkext/gtkviewpanel-int.h @@ -58,7 +58,7 @@ typedef const vmpa2t * (* get_caret_location_fc) (const GtkViewPanel *); typedef bool (* get_addr_coordinates_fc) (const GtkViewPanel *, const vmpa2t *, gint *, gint *, ScrollPositionTweak); /* Fournit des éléments liés à la position courante dans la vue. */ -typedef bool (* get_view_position_fc) (const GtkViewPanel *, GBufferLine **, GBufferSegment **); +typedef bool (* get_view_position_fc) (const GtkViewPanel *, GBufferLine **, GObject **); /* Déplace le curseur à un emplacement défini. */ typedef bool (* move_caret_to_fc) (GtkViewPanel *, gint, gint); diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c index a39ea24..b7b58d9 100644 --- a/src/gtkext/gtkviewpanel.c +++ b/src/gtkext/gtkviewpanel.c @@ -1021,24 +1021,24 @@ void gtk_view_panel_request_move(GtkViewPanel *panel, const vmpa2t *addr) * * ******************************************************************************/ -bool gtk_view_panel_get_position(const GtkViewPanel *panel, GBufferLine **line, GBufferSegment **segment) +bool gtk_view_panel_get_position(const GtkViewPanel *panel, GBufferLine **line, GObject **creator) { bool result; /* Bilan de l'opération */ *line = NULL; - if (segment != NULL) *segment = NULL; + if (creator != NULL) *creator = NULL; if (GTK_VIEW_PANEL_GET_CLASS(panel)->get_position == NULL) return false; - result = GTK_VIEW_PANEL_GET_CLASS(panel)->get_position(panel, line, segment); + result = GTK_VIEW_PANEL_GET_CLASS(panel)->get_position(panel, line, creator); if (result) { g_object_ref(G_OBJECT(*line)); - if (segment != NULL && *segment != NULL) - g_object_ref(G_OBJECT(*segment)); + if (creator != NULL && *creator != NULL) + g_object_ref(G_OBJECT(*creator)); } diff --git a/src/gtkext/gtkviewpanel.h b/src/gtkext/gtkviewpanel.h index 0943dd1..9e198ac 100644 --- a/src/gtkext/gtkviewpanel.h +++ b/src/gtkext/gtkviewpanel.h @@ -95,7 +95,7 @@ void _gtk_view_panel_scroll_to_address(GtkViewPanel *, const vmpa2t *, ScrollPos void gtk_view_panel_request_move(GtkViewPanel *, const vmpa2t *); /* Fournit des éléments liés à la position courante dans la vue. */ -bool gtk_view_panel_get_position(const GtkViewPanel *, GBufferLine **, GBufferSegment **); +bool gtk_view_panel_get_position(const GtkViewPanel *, GBufferLine **, GObject **); /* 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/edition.c b/src/gui/menus/edition.c index 0a92e3e..f2742e6 100644 --- a/src/gui/menus/edition.c +++ b/src/gui/menus/edition.c @@ -246,7 +246,6 @@ void update_access_in_menu_edition(GObject *ref, GtkViewPanel *vpanel, const vmp bool state; /* Etat principal à considérer */ gboolean access; /* Accès à déterminer */ GBufferLine *line; /* Ligne de position courante */ - GBufferSegment *segment; /* Segment actif s'il existe */ GObject *creator; /* Créateur à l'orgine du seg. */ GtkWidget *item; /* Elément de menu à traiter */ @@ -256,15 +255,10 @@ void update_access_in_menu_edition(GObject *ref, GtkViewPanel *vpanel, const vmp { state = false; line = NULL; - segment = NULL; + creator = NULL; } else - state = gtk_view_panel_get_position(vpanel, &line, &segment); - - if (state) - creator = g_buffer_segment_get_creator(segment); - else - creator = NULL; + state = gtk_view_panel_get_position(vpanel, &line, &creator); /* Bascule des opérandes numériques */ @@ -300,8 +294,6 @@ void update_access_in_menu_edition(GObject *ref, GtkViewPanel *vpanel, const vmp /* Nettoyage et sortie finale */ if (creator != NULL) g_object_unref(G_OBJECT(creator)); - - if (segment != NULL) g_object_unref(G_OBJECT(segment)); if (line != NULL) g_object_unref(G_OBJECT(line)); } @@ -365,7 +357,6 @@ static void mcb_edition_switch_numeric_operand(GtkMenuItem *menuitem, GMenuBar * GEditorItem *editem; /* Autre version de la barre */ GtkViewPanel *vpanel; /* Afficheur effectif de code */ GBufferLine *line; /* Ligne de position courante */ - GBufferSegment *segment; /* Segment actif s'il existe */ GObject *creator; /* Créateur à l'orgine du seg. */ GDbSwitcher *switcher; /* Bascule à mettre en place */ const mrange_t *range; /* Emplacement de la ligne */ @@ -379,9 +370,8 @@ static void mcb_edition_switch_numeric_operand(GtkMenuItem *menuitem, GMenuBar * vpanel = g_editor_item_get_current_view(editem); - if (gtk_view_panel_get_position(vpanel, &line, &segment)) + if (gtk_view_panel_get_position(vpanel, &line, &creator)) { - creator = g_buffer_segment_get_creator(segment); assert(G_IS_IMM_OPERAND(creator)); range = g_buffer_line_get_range(line); @@ -399,8 +389,6 @@ static void mcb_edition_switch_numeric_operand(GtkMenuItem *menuitem, GMenuBar * g_object_unref(G_OBJECT(proc)); g_object_unref(creator); - - g_object_unref(G_OBJECT(segment)); g_object_unref(G_OBJECT(line)); } @@ -444,16 +432,14 @@ static void mcb_edition_follow_ref(GtkMenuItem *menuitem, GMenuBar *bar) { GtkViewPanel *vpanel; /* Afficheur effectif de code */ GBufferLine *line; /* Ligne de position courante */ - GBufferSegment *segment; /* Segment actif s'il existe */ GObject *creator; /* Créateur à l'orgine du seg. */ virt_t virt; /* Adresse virtuelle */ vmpa2t addr; /* Adresse de destination */ vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar)); - if (gtk_view_panel_get_position(vpanel, &line, &segment)) + if (gtk_view_panel_get_position(vpanel, &line, &creator)) { - creator = g_buffer_segment_get_creator(segment); assert(creator != NULL); /** @@ -479,8 +465,6 @@ static void mcb_edition_follow_ref(GtkMenuItem *menuitem, GMenuBar *bar) } g_object_unref(creator); - - g_object_unref(G_OBJECT(segment)); g_object_unref(G_OBJECT(line)); } -- cgit v0.11.2-87-g4458