/* OpenIDA - Outil d'analyse de fichiers binaires * node.c - éléments de graphiques chez dot * * Copyright (C) 2009-2012 Cyrille Bagard * * This file is part of OpenIDA. * * 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 . */ #include "node.h" #include #include #include #include "../../common/extstr.h" /* -------------------------- GESTION DES NOEUDS A L'UNITE -------------------------- */ /* Intermédiaire entre le noeud dot et la bribe de code (instance) */ struct _GGraphNode { GObject parent; /* A laisser en premier */ GtkWidget *view; /* Morceau de code représenté */ char *name; /* Adresse sous forme humaine */ GtkAllocation alloc; /* Emplacement du bloc rattaché*/ }; /* Intermédiaire entre le noeud dot et la bribe de code (classe) */ struct _GGraphNodeClass { GObjectClass parent; /* A laisser en premier */ double dpi_x; /* Résolution en abscisse */ double dpi_y; /* Résolution en ordonnée */ }; /* Initialise la classe des intermédiaires avec les noeuds dot. */ static void g_graph_node_class_init(GGraphNodeClass *); /* Initialise la classe des intermédiaires avec les noeuds dot. */ static void g_graph_node_init(GGraphNode *); /* ---------------------------------------------------------------------------------- */ /* GESTION DES NOEUDS A L'UNITE */ /* ---------------------------------------------------------------------------------- */ /* Indique le type définit par la GLib pour le noeud. */ G_DEFINE_TYPE(GGraphNode, g_graph_node, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des intermédiaires avec les noeuds dot. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_graph_node_class_init(GGraphNodeClass *klass) { GdkScreen *screen; /* Ecran par défaut */ gint width; /* Largeur d'écran en pixels */ gint height; /* Hauteur d'écran en pixels */ gint width_mm; /* Largeur d'écran en mm. */ gint height_mm; /* Hauteur d'écran en mm. */ screen = gdk_screen_get_default(); width = gdk_screen_get_width(screen); height = gdk_screen_get_height(screen); width_mm = gdk_screen_get_width_mm(screen); height_mm = gdk_screen_get_height_mm(screen); /** * Il y a 2.54 centimètres, soit 25.4 millimètres, dans un pouce. * On a donc : * * dpi = N pixels / (M millimètres / (25.4 millimètres / 1 pouce)) * = N pixels / (M pouces / 25.4) * = N * 25.4 pixels / M pouces * */ if (width_mm > 0 && height_mm > 0) { klass->dpi_x = (width * 25.4) / (double)width_mm; klass->dpi_y = (height * 25.4) / (double)height_mm; } else { klass->dpi_x = 96; klass->dpi_y = 96; } klass->dpi_x = 72; klass->dpi_y = 72; } /****************************************************************************** * * * Paramètres : node = instance à initialiser. * * * * Description : Initialise la classe des intermédiaires avec les noeuds dot. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_graph_node_init(GGraphNode *node) { } /****************************************************************************** * * * Paramètres : view = morceau d'affichage à représenter. * * * * Description : Constitue un intermédiaire entre un noeud dot et du code. * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ GGraphNode *g_graph_node_new(GtkWidget *view) { GGraphNode *result; /* Structure à retourner */ size_t len; /* Taille du nom */ result = g_object_new(G_TYPE_GRAPH_NODE, NULL); result->view = view; len = 3 + sizeof(GtkWidget *) * 2 + 1; result->name = (char *)calloc(len, sizeof(char)); snprintf(result->name, len, "_%p", result->view); return result; } /****************************************************************************** * * * Paramètres : node = intermédiaire à consulter. * * cmds = description pour dot à compléter. * * * * Description : Déclare l'intermédiaire en tant que noeud pour dot. * * * * Retour : Description dûment complétée. * * * * Remarques : - * * * ******************************************************************************/ char *g_graph_node_register_for_dot(const GGraphNode *node, char *cmds) { GtkRequisition requisition; /* Taille à l'écran requise */ char buffer[128]; gtk_widget_size_request(node->view, &requisition); snprintf(buffer, 128, " subgraph cluster%s {\n", node->name); cmds = stradd(cmds, buffer); cmds = stradd(cmds, " style=invisible;\n"); cmds = stradd(cmds, " "); cmds = stradd(cmds, node->name); cmds = stradd(cmds, " [shape=box, fixedsize "); snprintf(buffer, 128, ", width=\"%g\"", requisition.width / G_GRAPH_NODE_GET_CLASS(node)->dpi_x); cmds = stradd(cmds, buffer); snprintf(buffer, 128, ", height=\"%g\"", requisition.height / G_GRAPH_NODE_GET_CLASS(node)->dpi_y); cmds = stradd(cmds, buffer); cmds = stradd(cmds, "];\n"); cmds = stradd(cmds, " }\n"); return cmds; } /****************************************************************************** * * * Paramètres : node = intermédiaire à consulter. * * view = support de destination. * * x = abscisse du point d'intégration. * * y = ordonnée du point d'intégration. * * * * Description : Place le morceau de code de l'intermédiaire à l'écran. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_graph_node_place(GGraphNode *node, GtkGraphView *view, gint x, gint y) { GtkRequisition requisition; /* Taille à l'écran actuelle */ gtk_widget_size_request(node->view, &requisition); x -= requisition.width / 2; y -= requisition.height / 2; node->alloc.x = x; node->alloc.y = y; node->alloc.width = requisition.width; node->alloc.height = requisition.height; gtk_graph_view_put(view, node->view, &node->alloc); } /****************************************************************************** * * * Paramètres : node = intermédiaire à consulter. * * x = abscisse du point à relier. * * y = ordonnée du point à relier. * * points = liste de points à mettre à jour. [OUT] * * count = taille de cette même liste. [OUT] * * * * Description : Etablit une jonction ferme avec un noeud. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_graph_node_connect(const GGraphNode *node, gint x, gint y, GdkPoint **points, size_t *count) { const GtkAllocation *alloc; /* Emplacement du bloc rattaché*/ alloc = &node->alloc; *points = (GdkPoint *)realloc(*points, ++(*count) * sizeof(GdkPoint)); /* Si le point est sur la gauche... */ if (alloc->y <= y && y < (alloc->y + alloc->height) && x < alloc->x) { (*points)[*count - 1].x = alloc->x; (*points)[*count - 1].y = y; } /* Si le point est sur la droite... */ else if (alloc->y <= y && y < (alloc->y + alloc->height) && x > (alloc->x + alloc->width)) { (*points)[*count - 1].x = alloc->x + alloc->width; (*points)[*count - 1].y = y; } /* Si le point est au dessus... */ else if (alloc->x <= x && x < (alloc->x + alloc->width) && y < alloc->y) { (*points)[*count - 1].x = x; (*points)[*count - 1].y = alloc->y; } /* Si le point est en dessous... */ else if (alloc->x <= x && x < (alloc->x + alloc->width) && y > (alloc->y + alloc->height)) { (*points)[*count - 1].x = x; (*points)[*count - 1].y = alloc->y + alloc->height; } else (*count)--; } /* ---------------------------------------------------------------------------------- */ /* MANIPULATION D'ENSEMBLES DE NOEUDS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : nodes = liste de noeuds à parcourir. * * count = taille de la liste. * * target = nom du noeud recherché. * * * * Description : Recherche un noeud donné dans une série de noeuds. * * * * Retour : Noeud trouvé ou NULL si aucun. * * * * Remarques : - * * * ******************************************************************************/ GGraphNode *find_graph_node_by_name(GGraphNode **nodes, size_t count, const char *target) { GGraphNode *result; /* Trouvaille à remonter */ size_t i; /* Boucle de parcours */ result = NULL; for (i = 0; i < count && result == NULL; i++) if (strcmp(nodes[i]->name, target) == 0) result = nodes[i]; return result; }