/* Chrysalide - Outil d'analyse de fichiers binaires
* items.c - manipulation de l'ensemble des composants graphiques actifs
*
* Copyright (C) 2017-2018 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* Chrysalide 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.
*
* Chrysalide 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 Chrysalide. If not, see .
*/
#include "items.h"
#include
#include
#include
#include "global.h"
#include "../../analysis/db/items/move.h"
/* Liste des éléments en place */
static GEditorItem **_item_list = NULL;
static size_t _item_count = 0;
/* Initialisations premières de façon unique */
static bool _first_content_change = true;
static bool _first_panel_change = true;
/* Lance une procédure de déplacement de la position courante. */
static void start_moving_to_cursor_in_loaded_panel(GLoadedPanel *, const GLineCursor *, gboolean, gpointer);
/* Suit les changements de position dans du code d'assembleur. */
static void track_cursor_on_view_panel(GLoadedPanel *, const GLineCursor *, gpointer);
/******************************************************************************
* *
* Paramètres : item = élément de l'interface graphique à intégrer. *
* *
* Description : Procède à l'enregistrement d'un élément reactif de l'éditeur.*
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void register_editor_item(GEditorItem *item)
{
_item_list = realloc(_item_list, ++_item_count * sizeof(GEditorItem *));
_item_list[_item_count - 1] = item;
g_object_ref(G_OBJECT(item));
}
/******************************************************************************
* *
* Paramètres : target = type de l'élément réactif à retrouver. *
* *
* Description : Retrouve un élément reactif de l'éditeur par son type. *
* *
* Retour : Elément retrouvé ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
GEditorItem *find_editor_item_by_type(GType target)
{
GEditorItem *result; /* Elément à retourner */
size_t i; /* Boucle de parcours */
GType type; /* Type d'un élément analysé */
result = NULL;
for (i = 0; i < _item_count && result == NULL; i++)
{
type = G_TYPE_FROM_INSTANCE(_item_list[i]);
if (type == target)
{
result = _item_list[i];
g_object_ref(G_OBJECT(result));
}
}
return result;
}
/******************************************************************************
* *
* Paramètres : item = élément de l'interface graphique à oublier. *
* *
* Description : Retire un des éléments reactifs de l'éditeur. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void unregister_editor_item(GEditorItem *item)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < _item_count; i++)
if (_item_list[i] == item)
break;
assert(i < _item_count);
g_object_unref(G_OBJECT(item));
memmove(&_item_list[i], &_item_list[i + 1], (_item_count - i - 1) * sizeof(GEditorItem *));
_item_list = realloc(_item_list, --_item_count * sizeof(GEditorItem *));
}
/******************************************************************************
* *
* Paramètres : content = nouvelle instance de contenu analysé. *
* *
* Description : Lance une actualisation du fait d'un changement de contenu. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void change_editor_items_current_content(GLoadedContent *content)
{
GLoadedContent *old; /* Ancien contenu */
size_t i; /* Boucle de parcours */
old = get_current_content();
if (content != old || _first_content_change)
{
_first_content_change = false;
if (content != NULL)
g_object_ref(G_OBJECT(content));
set_current_content(content);
for (i = 0; i < _item_count; i++)
g_editor_item_change_content(_item_list[i], old, content);
}
if (old != NULL)
g_object_unref(G_OBJECT(old));
}
/******************************************************************************
* *
* Paramètres : panel = composant d'affichage parcouru. *
* cursor = emplacement à cibler pour un déplacement. *
* save = le changement est-il majeur ? *
* unused = adresse non utilisée ici. *
* *
* Description : Lance une procédure de déplacement de la position courante. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void start_moving_to_cursor_in_loaded_panel(GLoadedPanel *panel, const GLineCursor *cursor, gboolean save, gpointer unused)
{
GLineCursor *src; /* Position courante de curseur*/
GDbMove *move; /* Déplacement à organiser */
GLoadedBinary *binary; /* Binaire en cours d'étude */
src = g_loaded_panel_get_cursor(panel);
if (save && src != NULL)
{
move = g_db_move_new(src, cursor);
binary = G_LOADED_BINARY(g_loaded_panel_get_content(panel));
g_loaded_binary_add_to_collection(binary, G_DB_ITEM(move));
g_object_unref(G_OBJECT(binary));
}
else
g_loaded_panel_scroll_to_cursor(panel, cursor, SPT_CENTER, true);
if (src != NULL)
g_object_unref(G_OBJECT(src));
}
/******************************************************************************
* *
* Paramètres : panel = composant d'affichage parcouru. *
* cursor = nouvel emplacement du curseur courant. *
* unused = adresse non utilisée ici. *
* *
* Description : Suit les changements de position dans du code d'assembleur. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void track_cursor_on_view_panel(GLoadedPanel *panel, const GLineCursor *cursor, gpointer unused)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < _item_count; i++)
g_editor_item_track_cursor(_item_list[i], panel, cursor);
}
/******************************************************************************
* *
* Paramètres : panel = nouveau panneau d'affichage actif. *
* *
* Description : Lance une actualisation du fait d'un changement de vue. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void change_editor_items_current_view(GLoadedPanel *panel)
{
GLoadedPanel *old; /* Ancien affichage */
size_t i; /* Boucle de parcours */
/* Suivi des affichages */
old = get_current_view();
if (panel != old || _first_panel_change)
{
_first_panel_change = false;
if (panel != NULL)
g_object_ref(G_OBJECT(panel));
set_current_view(panel);
for (i = 0; i < _item_count; i++)
g_editor_item_change_view(_item_list[i], old, panel);
/* Suivi du curseur */
if (old != NULL)
{
g_signal_handlers_disconnect_by_func(old,
G_CALLBACK(start_moving_to_cursor_in_loaded_panel),
NULL);
g_signal_handlers_disconnect_by_func(old,
G_CALLBACK(track_cursor_on_view_panel),
NULL);
}
if (panel != NULL)
{
g_signal_connect(panel, "move-request",
G_CALLBACK(start_moving_to_cursor_in_loaded_panel),
NULL);
g_signal_connect(panel, "cursor-moved",
G_CALLBACK(track_cursor_on_view_panel),
NULL);
}
}
if (old != NULL)
g_object_unref(G_OBJECT(old));
}
/******************************************************************************
* *
* Paramètres : panel = nouveau panneau d'affichage actif. *
* *
* Description : Lance une actualisation du fait d'un changement de contenu. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void update_editor_items_current_view(GLoadedPanel *panel)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < _item_count; i++)
g_editor_item_update_view(_item_list[i], panel);
}
/******************************************************************************
* *
* Paramètres : content = contenu contenant le curseur à représenter. *
* cursor = nouvel emplacement du curseur courant. *
* source = composant à l'origine du changement. *
* *
* Description : Concentre l'attention de l'ensemble sur une adresse donnée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void focus_cursor_in_editor_items(GLoadedContent *content, const GLineCursor *cursor, GEditorItem *source)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < _item_count; i++)
{
if (_item_list[i] != source)
g_editor_item_focus_cursor(_item_list[i], content, cursor);
}
}
/******************************************************************************
* *
* Paramètres : project = projet concerné par l'évolution. *
* *
* Description : Lance une actualisation relative à l'étendue du projet. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void update_project_area(GStudyProject *project)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < _item_count; i++)
g_editor_item_update_project_area(_item_list[i], project);
}