diff options
Diffstat (limited to 'src/glibext/linecolumn.c')
-rw-r--r-- | src/glibext/linecolumn.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/src/glibext/linecolumn.c b/src/glibext/linecolumn.c new file mode 100644 index 0000000..22c1e44 --- /dev/null +++ b/src/glibext/linecolumn.c @@ -0,0 +1,480 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linecolumn.h - prototypes pour le regroupement des segments de texte par colonnes + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "linecolumn.h" + + +#include <assert.h> +#include <malloc.h> + + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à initialiser. * +* * +* Description : Initialise une colonne de ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void init_line_column(line_column *column) +{ + column->segments = NULL; + column->count = 0; + + column->max_width = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à mettre à jour. * +* * +* Description : Réinitialise une colonne de ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_line_column(line_column *column) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < column->count; i++) + release_line_segment(column->segments[i]); + + if (column->segments != NULL) + { + free(column->segments); + column->segments = NULL; + } + + column->count = 0; + + column->max_width = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à mettre à jour. * +* * +* Description : Recalcule la largeur d'une colonne de segments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void refresh_line_column_width(line_column *column) +{ + size_t i; /* Boucle de parcours */ + + column->max_width = 0; + + for (i = 0; i < column->count; i++) + column->max_width += get_line_segment_width(column->segments[i]); + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à consulter. * +* * +* Description : Fournit la quantité de pixels requise pour l'impression. * +* * +* Retour : Largeur requise par la colonne, en pixel. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint get_column_width(const line_column *column) +{ + return column->max_width; + +} + + +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +size_t append_text_to_line_column(line_column *column, const char *text, size_t length, RenderingTagType type) +{ + size_t result; /* Indice à retourner */ + line_segment *segment; /* Contenu à représenter */ + + result = column->count; + + segment = get_new_line_segment(type, text, length); + + column->segments = (line_segment **)realloc(column->segments, ++column->count * sizeof(line_segment *)); + + column->segments[result] = segment; + + column->max_width += get_line_segment_width(segment); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne à venir compléter. * +* index = indice du frament de texte à remplacer. * +* text = texte à insérer dans l'existant. * +* length = taille du texte à traiter. * +* * +* Description : Remplace un fragment de texte dans une colonne de ligne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void replace_text_in_line_column(line_column *column, size_t index, const char *text, size_t length) +{ + RenderingTagType type; /* Type de rendu à conserver */ + line_segment *segment; /* Contenu à représenter */ + + assert(index < column->count); + + /* Retrait */ + + segment = column->segments[index]; + + type = get_line_segment_type(segment); + + release_line_segment(segment); + + /* Ajout */ + + segment = get_new_line_segment(type, text, length); + + column->segments[index] = segment; + + refresh_line_column_width(column); + +} + + +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +bool get_line_column_first_content_index(const 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 : - * +* * +******************************************************************************/ + +bool get_line_column_last_content_index(const 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. * +* index = indice à consulter puis renseigner. [OUT] * +* dir = orientation des recherches. * +* * +* Description : Fournit le segment voisin d'un autre segment identifié. * +* * +* Retour : Validité de l'indice renseigné. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool find_near_segment(const line_column *column, size_t *index, GdkScrollDirection dir) +{ + bool result; /* Bilan à faire remonter */ + + result = false; + + switch (dir) + { + case GDK_SCROLL_LEFT: + if (*index > 0) + { + (*index)--; + result = true; + } + break; + + case GDK_SCROLL_RIGHT: + if ((*index + 1) < column->count) + { + (*index)++; + result = true; + } + break; + + default: + break; + + } + + 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 : Indique l'indice du contenu de colonne à une abscisse donnée.* +* * +* Retour : Validité de l'indice renseigné. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_line_column_content_index_at(const line_column *column, gint *x, GdkScrollDirection dir, gint *consumed, size_t *index) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + gint width; /* Largeur à retirer */ + bool included; /* Appartenance à une largeur ?*/ + + result = false; + *consumed = 0; + + for (i = 0; i < column->count && !result; i++) + { + width = get_line_segment_width(column->segments[i]); + + /** + * 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) + { + *index = i; + result = true; + } + + else if ((i + 1) == column->count) + { + *index = i; + result = true; + *x = width; + } + + else + { + *x -= width; + *consumed += width; + } + + } + + 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 : - * +* * +******************************************************************************/ + +line_segment *get_line_column_content_from_index(const line_column *column, size_t index) +{ + line_segment *result; /* Trouvaille à retourner */ + + assert(index < column->count); + + result = column->segments[index]; + + 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. * +* y = ordonnée du point d'impression. * +* list = liste de contenus à mettre en évidence. * +* * +* Description : Imprime le contenu d'une colonne de ligne de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void draw_line_column_segments(const line_column *column, cairo_t *cairo, gint x_init, gint y, const segcnt_list *list) +{ + gint x; /* Abscisse d'impression */ + size_t i; /* Boucle de parcours */ + + x = x_init; + + for (i = 0; i < column->count; i++) + draw_line_segment(column->segments[i], cairo, &x, y, list); + +} + + +/****************************************************************************** +* * +* Paramètres : column = colonne de ligne de texte à manipuler. * +* ctx = éléments à disposition pour l'exportation. * +* type = type d'exportation attendue. * +* span = fusion de colonnes au sein des cellules ? * +* * +* Description : Exporte la ligne de texte représentée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void export_line_column_segments(const line_column *column, buffer_export_context *ctx, BufferExportType type, int span) +{ + size_t i; /* Boucle de parcours */ + + switch (type) + { + case BET_HTML: + switch (span) + { + case 0: + break; + case 1: + dprintf(ctx->fd, "\t\t<TD>"); + break; + default: + if (span > 0) dprintf(ctx->fd, "\t\t<TD colspan=\"%d\">", span); + break; + } + break; + default: + break; + } + + for (i = 0; i < column->count; i++) + export_line_segment(column->segments[i], ctx, type); + + switch (type) + { + case BET_HTML: + if (span < 0 || span == 1) dprintf(ctx->fd, "</TD>\n"); + break; + default: + break; + } + +} |