data_type.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003   data_types.c
00004   Window allowing the user to create or edit a new data type
00005   
00006   (C) Copyright 2007 - 2009 Olivier Delhomme
00007   e-mail : heraia@delhomme.org
00008   URL    : http://heraia.tuxfamily.org
00009  
00010   This program is free software; you can redistribute it and/or modify
00011   it under the terms of the GNU General Public License as published by
00012   the Free Software Foundation; either version 2, or  (at your option) 
00013   any later version.
00014  
00015   This program is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY;  without even the implied warranty of
00017   MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00018   GNU General Public License for more details.
00019  
00020   You should have received a copy of the GNU General Public License
00021   along with this program; if not, write to the Free Software
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
00023 */
00024 /**
00025  * @file data_type.c
00026  * This file must not be edited unless you know what you are
00027  * doing : the main maintainer wants to destroy it in a near
00028  * future !
00029  */
00030 #include <libheraia.h>
00031 
00032 static gboolean delete_data_type_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data);
00033 static void destroy_data_type_window(GtkWidget *widget, GdkEvent  *event, gpointer data);
00034 static void dt_ok_button_clicked(GtkWidget *widget, gpointer data);
00035 static void dt_cancel_button_clicked(GtkWidget *widget, gpointer data);
00036 static void connect_data_type_signals(heraia_window_t *main_window);
00037 /* static data_type_t *retrieve_data_type_information(heraia_window_t *main_window); */
00038 static void set_spinbutton_max_range(heraia_window_t *main_window);
00039 
00040 static void close_data_type_window(heraia_window_t *main_window);
00041 static void destroy_container_widget(treatment_container_t *tment_c, gboolean all);
00042 static treatment_container_t *new_treatment_container(heraia_window_t *main_window);
00043 static void create_treatment_container_widget(heraia_window_t *main_window, treatment_container_t *tment_c);
00044 static guchar *print_bin_to_hex(GtkWidget *entry, GList *values_list);
00045 
00046 /* treatment container widget signals */
00047 static void add_treatment_container_widget(GtkWidget *widget, gpointer data);
00048 static void remove_treatment_container_widget(GtkWidget *widget, gpointer data);
00049 static void cb_changed_in_treatment_container_widget(GtkWidget *widget, gpointer data);
00050 
00051 /**
00052  *  Returns a new data_type filled with name and size values
00053  */
00054 data_type_t *new_data_type(gchar *name, guint size)
00055 {
00056         data_type_t *a_data_type = NULL;
00057 
00058         a_data_type = (data_type_t *) g_malloc0(sizeof(data_type_t));
00059 
00060         if (name != NULL)
00061                 {
00062                         a_data_type->name = g_strdup(name);
00063                 }
00064         else
00065                 {
00066                         a_data_type->name = NULL;
00067                 }
00068 
00069         a_data_type->size = size;
00070 
00071         /* Data interpretor widgets */
00072         a_data_type->di_label = NULL;
00073         a_data_type->di_entry = NULL;
00074 
00075         return a_data_type;
00076 }
00077 
00078 
00079 /**
00080  *  Frees the memory of a particular data_type
00081  */
00082 void free_data_type(data_type_t *a_data_type)
00083 {
00084         if (a_data_type != NULL)
00085                 {
00086                         if (a_data_type->name != NULL)
00087                                 {
00088                                         g_free(a_data_type->name);
00089                                 }
00090                         
00091                         g_free(a_data_type);
00092                 }
00093 }
00094 
00095 
00096 /**
00097  *  Copies the data_type_t structure in a new one,
00098  *  that may be freely freed after use.
00099  *  main_window needed to fill the combobox widget with available treatment list
00100  */
00101 data_type_t *copy_data_type_struct(heraia_window_t *main_window, data_type_t *a_data_type)
00102 {
00103         data_type_t *data_type = NULL;
00104         treatment_container_t *tment_c = NULL;
00105         GList *list = NULL;
00106         GList *list2 = NULL;
00107 
00108         if (a_data_type != NULL)
00109                 {
00110                         data_type = new_data_type(a_data_type->name, a_data_type->size);
00111                         list = a_data_type->treatment_c_list;
00112 
00113                         while (list != NULL)
00114                                 {
00115                                         /**
00116                                          *  Here we do not copy the widgets as they will be created
00117                                          *  on the fly. We copy the list and the treatments
00118                                          */
00119                                         tment_c = new_treatment_container(main_window);
00120                                         tment_c->treatment = copy_treatment(((treatment_container_t *)list->data)->treatment);
00121                                         list2 = g_list_append(list2, tment_c);                             
00122                                         list = g_list_next(list);
00123                                 }
00124 
00125                         data_type->treatment_c_list = list2;
00126 
00127                         /* data interpretor widget creation */
00128                         create_ud_data_interpretor_widgets(main_window, data_type);
00129                         gtk_label_set_text(GTK_LABEL(data_type->di_label), gtk_label_get_text(GTK_LABEL(a_data_type->di_label)));
00130                 }
00131   
00132         return data_type;
00133 }
00134 
00135 
00136 /**
00137  *  Sets the maximum range of the spinbutton on the Data type Window 
00138  *  (usefull when we're next to the file's end) 
00139  *  This is done to ensure that the spinbutton always represent an
00140  *  exact and valid size 
00141  */
00142 static void set_spinbutton_max_range(heraia_window_t *main_window)
00143 {
00144         data_window_t *data_window = main_window->current_DW;
00145         guint64 till_end = 0;
00146         GtkSpinButton *size_spin_button = NULL;
00147         GtkHex *gh = NULL;
00148 
00149         gh = GTK_HEX(data_window->current_hexwidget);
00150 
00151         if (gh != NULL)
00152                 {
00153                         size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
00154                         till_end = ghex_file_size(gh) - gtk_hex_get_cursor(gh);
00155 
00156                         if (till_end >= DT_SPIN_MIN && till_end <= DT_SPIN_MAX)
00157                                 {
00158                                         gtk_spin_button_set_range(size_spin_button, DT_SPIN_MIN, till_end);
00159                                 }
00160                         else
00161                                 {
00162                                         gtk_spin_button_set_range(size_spin_button, DT_SPIN_MIN, DT_SPIN_MAX);
00163                                 }
00164                 }
00165 }
00166 
00167 
00168 /**
00169  *  Fills the treatment combobox with the available treatment list names 
00170  *  Set the active element on nothing (no active element)
00171  */
00172 static void fill_treatment_combobox(GtkWidget *tment_list, GList *available_list)
00173 {
00174         treatment_t *tment = NULL;
00175 
00176         while (available_list != NULL)
00177                 {
00178                         tment = (treatment_t *) available_list->data;
00179                         if (tment->name != NULL)
00180                                 {
00181                                         gtk_combo_box_append_text(GTK_COMBO_BOX(tment_list), tment->name);
00182                                 }
00183 
00184                         available_list = g_list_next(available_list);                   
00185                 }
00186 
00187         /* No active element */
00188         gtk_combo_box_set_active(GTK_COMBO_BOX(tment_list), -1);
00189 }
00190 
00191 /**
00192  *  Tries to set the named "name" active item of the combobox list.
00193  */
00194 static void set_active_text_item(GtkWidget *combo_box, gchar *name)
00195 {
00196         GtkTreeIter iter;
00197         GtkTreeModel *model = NULL;
00198         gchar *list_name = NULL;
00199         gboolean ok = TRUE;
00200         gboolean stop = FALSE;
00201 
00202         if (name != NULL)
00203                 {
00204 
00205                         model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box));
00206         
00207                         ok = gtk_tree_model_get_iter_first(model, &iter);
00208         
00209                         while (ok == TRUE && stop == FALSE)
00210                                 {
00211                                         gtk_tree_model_get(model, &iter, 0, &list_name, -1);
00212                                         if (g_ascii_strcasecmp(list_name, name) == 0)
00213                                                 {
00214                                                         stop = TRUE;
00215                                                 }
00216                                         else
00217                                                 {
00218                                                         ok = gtk_tree_model_iter_next(model, &iter);
00219                                                 }
00220                                 }
00221 
00222                         if (stop == TRUE)
00223                                 {
00224                                         gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo_box), &iter);
00225                                 }
00226                 }
00227 }
00228 
00229 
00230 /**
00231  *  Create a new empty treatment container
00232  *  Needs main_window structure to fill the combobox with available
00233  *  treatments
00234  */
00235 static treatment_container_t *new_treatment_container(heraia_window_t *main_window)
00236 {
00237         treatment_container_t *tment_c;
00238         
00239         tment_c = (treatment_container_t *) g_malloc0(sizeof(treatment_container_t));
00240         tment_c->treatment = NULL;
00241 
00242         /* Widget initialization */
00243         tment_c->container_box = gtk_hbox_new(FALSE, DT_BOX_SPACING);
00244         tment_c->combo_box = gtk_vbox_new(FALSE, DT_BOX_SPACING);
00245         tment_c->button_box = gtk_hbox_new(FALSE, DT_BOX_SPACING);
00246         tment_c->tment_list = gtk_combo_box_new_text();
00247         fill_treatment_combobox(tment_c->tment_list, main_window->available_treatment_list);
00248 
00249         tment_c->result = gtk_entry_new();
00250         gtk_entry_set_editable(GTK_ENTRY(tment_c->result), FALSE);
00251         tment_c->moins = gtk_button_new_with_label(" - ");
00252         tment_c->plus = gtk_button_new_with_label(" + ");
00253         
00254 
00255         g_signal_connect(G_OBJECT(tment_c->plus), "clicked", 
00256                                          G_CALLBACK(add_treatment_container_widget), main_window);
00257         g_signal_connect(G_OBJECT(tment_c->moins), "clicked", 
00258                                          G_CALLBACK(remove_treatment_container_widget), main_window);
00259         g_signal_connect(G_OBJECT(tment_c->tment_list), "changed",
00260                                          G_CALLBACK(cb_changed_in_treatment_container_widget), main_window);
00261 
00262         /* Widget packing together */
00263         gtk_box_pack_start(GTK_BOX(tment_c->button_box), tment_c->moins, FALSE, FALSE, DT_BOX_PADDING);
00264         gtk_box_pack_start(GTK_BOX(tment_c->button_box), tment_c->plus, FALSE, FALSE, DT_BOX_PADDING);
00265         gtk_box_pack_start(GTK_BOX(tment_c->button_box), tment_c->result, FALSE, FALSE, DT_BOX_PADDING);
00266         gtk_box_pack_start(GTK_BOX(tment_c->combo_box), tment_c->tment_list, FALSE, FALSE, DT_BOX_PADDING);
00267         gtk_box_pack_end(GTK_BOX(tment_c->container_box), tment_c->button_box, FALSE, FALSE, DT_BOX_PADDING);
00268         gtk_box_pack_start(GTK_BOX(tment_c->container_box), tment_c->combo_box, FALSE, FALSE, DT_BOX_PADDING);
00269 
00270         return tment_c;
00271 }
00272 
00273 
00274 /**
00275  *  Packs the container widget to the main window widgets via "dt_treatment_vbox".
00276  */
00277 static void create_treatment_container_widget(heraia_window_t *main_window, treatment_container_t *tment_c)
00278 {
00279         GtkWidget *vbox = NULL;
00280 
00281         vbox = heraia_get_widget(main_window->xmls->main, "dt_treatment_vbox");
00282 
00283         gtk_box_pack_start(GTK_BOX(vbox), tment_c->container_box, FALSE, FALSE, DT_BOX_PADDING);
00284 
00285         if (tment_c->treatment != NULL) 
00286                 {
00287                         /* Here we call the method to init the treatment zone */
00288                         tment_c->treatment->init(tment_c->treatment);
00289                         set_active_text_item(tment_c->tment_list, tment_c->treatment->name);
00290                 }
00291 }
00292 
00293 
00294 /**
00295  *  Adds a treatment container widget when (+) button is clicked
00296  *  TODO : determine which treatment it is (where the + button was clicked)
00297  *  and insert the new one just after it (need to do the same in the list)
00298  */
00299 static void add_treatment_container_widget(GtkWidget *widget, gpointer data)
00300 {
00301         heraia_window_t *main_window = (heraia_window_t *) data;
00302         treatment_container_t *new_container = NULL;
00303         data_type_t *a_data_type = NULL;
00304 
00305         a_data_type = main_window->current_data_type;
00306 
00307         /* Creates a new treatment container */
00308         new_container = new_treatment_container(main_window);
00309 
00310         /* Create the last box that will contain one empty treatment container widget */
00311         create_treatment_container_widget(main_window, new_container);
00312 
00313         gtk_widget_show_all(new_container->container_box);
00314 
00315         /* Append the container to the list */
00316         a_data_type->treatment_c_list = g_list_append(a_data_type->treatment_c_list, (gpointer) new_container);
00317 
00318         /* Update the whole treatment container list + data interpretor window*/
00319         refresh_hex_datas_entry(main_window);
00320 }
00321 
00322 /**
00323  *  Finds the container which contains the specified widget
00324  */
00325 static GList *find_treatment_container_from_widget(GList *container_list, GtkWidget *widget)
00326 {
00327         gboolean stop = FALSE;
00328         treatment_container_t *tment_c = NULL;
00329 
00330         while (container_list != NULL && stop == FALSE)
00331                 {
00332                         tment_c = (treatment_container_t *) container_list->data;
00333                         if (tment_c->moins == widget || tment_c->tment_list == widget)
00334                                 {
00335                                         stop = TRUE;
00336                                 }
00337                         else
00338                                 {
00339                                         container_list = g_list_next(container_list);
00340                                 }
00341                 }
00342 
00343         return container_list;
00344 }
00345 
00346 
00347 /**
00348  *  Removes a treatment container widget when (-) button is clicked
00349  */
00350 static void remove_treatment_container_widget(GtkWidget *widget, gpointer data)
00351 {
00352         heraia_window_t *main_window = (heraia_window_t *) data;
00353         data_type_t *a_data_type = NULL;
00354         treatment_container_t *tment_c = NULL;
00355         GList *list = NULL;
00356 
00357         a_data_type = main_window->current_data_type;
00358         list = find_treatment_container_from_widget(a_data_type->treatment_c_list, widget);
00359         if (list != NULL)
00360                 {
00361                         tment_c = (treatment_container_t *) list->data;
00362 
00363                         /* Removes the container completely */
00364                         destroy_container_widget(tment_c, TRUE);
00365 
00366                         /* Removes the treatment container from the list */
00367                         a_data_type->treatment_c_list = g_list_delete_link(a_data_type->treatment_c_list, list);
00368 
00369                         /* Update the whole treatment container list + data interpretor window*/
00370                         refresh_hex_datas_entry(main_window);
00371                 }
00372 }
00373 
00374 /**
00375  *  Updates the treatment_container list entries
00376  */
00377 static guchar *update_treatment_container_list_entries(GList *tment_c_list, GList *values_list)
00378 {
00379         treatment_container_t *tment_c = NULL;
00380         guchar *final = NULL;
00381 
00382         while (tment_c_list != NULL)
00383                 {
00384                         tment_c = (treatment_container_t *) tment_c_list->data;
00385                         
00386                         if (tment_c->treatment != NULL && tment_c->treatment->do_it != NULL)
00387                                 {
00388                                         values_list = tment_c->treatment->do_it(values_list);
00389                                         final = print_bin_to_hex(tment_c->result, values_list);
00390                                 }
00391 
00392                         tment_c_list = g_list_next(tment_c_list);
00393                 }
00394 
00395         return final;
00396 }
00397 
00398 
00399 /**
00400  *  Called when a change is done in the treatment list combobox.
00401  *  Affects the new treatment to the treatment_container.
00402  */
00403 static void cb_changed_in_treatment_container_widget(GtkWidget *widget, gpointer data)
00404 {
00405         heraia_window_t *main_window = (heraia_window_t *) data;
00406         data_type_t *a_data_type = NULL;
00407         treatment_container_t *tment_c = NULL;
00408         treatment_t *tment = NULL;
00409         gchar *tment_name = NULL;
00410         GList *list = NULL;
00411 
00412         /* Retreiving the treatment container concerned by the changed signal */
00413         a_data_type = main_window->current_data_type;
00414         list = find_treatment_container_from_widget(a_data_type->treatment_c_list, widget);
00415         if (list != NULL)
00416                 {
00417                         tment_c = (treatment_container_t *) list->data;
00418 
00419                         /* Retrieving the treatment name selected */
00420                         tment_name = gtk_combo_box_get_active_text(GTK_COMBO_BOX(tment_c->tment_list));
00421 
00422                         /* Retrieves the treatment (with struct an such) from the treatment name */
00423                         tment = find_treatment(main_window->available_treatment_list, tment_name);
00424         
00425                         if (tment != NULL)
00426                                 {
00427                                         /* TODO : kill any previous treatment */
00428 
00429                                         tment_c->treatment = copy_treatment(tment);
00430                 
00431                                         /* Update the whole treatment container list + data interpretor window*/
00432                                         refresh_hex_datas_entry(main_window);
00433                                 }
00434                 }
00435 }
00436 
00437 /**
00438  *  Creates new user defined widgets for the data interpretor window.
00439  */
00440 void create_ud_data_interpretor_widgets(heraia_window_t *main_window, data_type_t *a_data_type)
00441 {
00442         GtkWidget *vbox = NULL;
00443 
00444         /* Creates new widgets for the data interpretor window */
00445         a_data_type->di_label = gtk_label_new(NULL);
00446         gtk_misc_set_padding(GTK_MISC(a_data_type->di_label), 4, 4);
00447         gtk_misc_set_alignment(GTK_MISC(a_data_type->di_label), 0.5, 0.5);
00448 
00449         a_data_type->di_entry = gtk_entry_new();
00450 
00451         vbox = heraia_get_widget(main_window->xmls->main, "ud_type_vbox");
00452         gtk_box_pack_start(GTK_BOX(vbox), a_data_type->di_label, FALSE, FALSE, DT_BOX_PADDING);
00453         
00454         vbox = heraia_get_widget(main_window->xmls->main, "ud_value_vbox");
00455         gtk_box_pack_start(GTK_BOX(vbox), a_data_type->di_entry, FALSE, FALSE, DT_BOX_PADDING);
00456 
00457         gtk_widget_show(a_data_type->di_label);
00458         gtk_widget_show(a_data_type->di_entry);
00459 }
00460 
00461 
00462 /**
00463  *  This constructs, fills and shows the data_type window
00464  *  First I thought doing things with libglade here, but it seems
00465  *  very hard. Same thing applies for GtkBuilder. I think I'll get
00466  *  more flexibility with widgets created on the fly
00467  */
00468 void show_data_type_window(heraia_window_t *main_window, data_type_t *a_data_type)
00469 {
00470         treatment_container_t *new_container = NULL;
00471         GList *list = NULL;
00472 
00473         /* create all the treatment widgets */
00474         list = a_data_type->treatment_c_list;
00475         
00476         if (list == NULL) /* Creates only the first treatment_container */
00477                 {
00478                         log_message(main_window, G_LOG_LEVEL_DEBUG, "Creating a new treatment container");
00479 
00480                         /* Creates a new empty treatment container */
00481                         new_container = new_treatment_container(main_window);
00482 
00483                         /* Create the last box that will contain one empty treatment container widget */
00484                         create_treatment_container_widget(main_window, new_container); 
00485 
00486                         /* Append the container to the list */
00487                         a_data_type->treatment_c_list = g_list_append(a_data_type->treatment_c_list, (gpointer) new_container);
00488                 }
00489         else  /* Create the widgets with all the treatments */
00490                 {
00491                         while (list != NULL)
00492                                 {
00493                                         
00494                                         new_container = (treatment_container_t *) list->data;
00495 
00496                                         log_message(main_window, G_LOG_LEVEL_DEBUG, "Creating a treatment container");
00497 
00498                                         create_treatment_container_widget(main_window, new_container);
00499                                         gtk_widget_show_all(new_container->container_box);
00500 
00501                                         list = g_list_next(list);
00502                                 }
00503                 }
00504 
00505         /* fills widgets that are on top of the window (name, size and hexentry) */
00506         fill_data_type_widgets(main_window, a_data_type); 
00507         set_spinbutton_max_range(main_window);
00508 
00509         gtk_widget_show_all(heraia_get_widget(main_window->xmls->main, "data_type_window"));
00510 }
00511 
00512 
00513 /**
00514  *  Prints "length" "bin_datas" in an hexa form to the 
00515  *  entry widget named "widget_name"
00516  *  TODO : add some specific representation options such
00517  *         as space between characters
00518  */
00519 static guchar *print_bin_to_hex(GtkWidget *entry, GList *values_list)
00520 {
00521         guint i = 0;
00522         guchar *aux = NULL;
00523         guchar *hex = NULL;
00524         guchar *final = NULL;
00525         value_t *a_value = NULL;
00526 
00527         while (values_list != NULL)
00528                 {
00529                         a_value = (value_t *) values_list->data;
00530 
00531                         aux = (guchar *) g_malloc0(sizeof(guchar) * 3);
00532                         hex = (guchar *) g_malloc0(sizeof(guchar) * ((a_value->length * 2) + 1) );
00533 
00534                         for(i = 0; i < a_value->length; i++)  
00535                                 {
00536                                         sprintf((char *) aux, "%02x", a_value->bytes[i]); 
00537                                         memcpy(hex+(i*2), aux, 2);
00538                                 }
00539 
00540                         hex[i*2+1] = '\0';
00541                         g_free(aux);
00542 
00543                         if (final == NULL)
00544                                 {
00545                                         final = (guchar *) g_strdup((gchar *) hex);
00546                                 }
00547                         else
00548                                 {
00549                                         aux = final;
00550                                         final = (guchar *) g_strconcat((gchar *) aux, " / ", (gchar *) hex, NULL);
00551                                         g_free(aux);
00552                                 }
00553 
00554                         g_free(hex);
00555 
00556                         values_list = g_list_next(values_list);
00557                 }
00558         
00559         if (entry != NULL)
00560                 {
00561                         gtk_entry_set_text(GTK_ENTRY(entry), (gchar *) final);
00562                 }
00563 
00564         return final;
00565 }
00566 
00567 
00568 /**
00569  *  Refreshes one user defined data type when the cursor is moved
00570  *  in the gtkhex structure.
00571  */
00572 static void refresh_one_ud_data_interpretor(data_type_t *a_data_type, value_t *a_value)
00573 {
00574         treatment_container_t *tment_c = NULL; /* one treatment container  */
00575         GList *tment_c_list = NULL;            /* treatment container list */
00576         guchar *final = NULL;                  /* final result             */
00577         GList *values_list = NULL;
00578 
00579         values_list = g_list_append(values_list, (gpointer) a_value);
00580 
00581         if (a_data_type != NULL)
00582                 {
00583                         tment_c_list = a_data_type->treatment_c_list;
00584 
00585                         while (tment_c_list != NULL)
00586                                 {
00587                                         tment_c = (treatment_container_t *) tment_c_list->data;
00588                         
00589                                         if (tment_c->treatment != NULL && tment_c->treatment->do_it != NULL)
00590                                                 {
00591                                                         values_list = tment_c->treatment->do_it(values_list);   
00592                                                 }
00593 
00594                                         tment_c_list = g_list_next(tment_c_list);
00595                                 }
00596 
00597                         final = print_bin_to_hex(a_data_type->di_entry, values_list);
00598                         g_free(final);
00599                 }
00600 }
00601 
00602 
00603 /**
00604  *  Refreshes all the user data defined types (called when the cursor is moved)
00605  *  Interpretation is done following the endianness 'endianness'
00606  */
00607 void refresh_all_ud_data_interpretor(heraia_window_t *main_window, guint endianness)
00608 {
00609         data_window_t *data_window = main_window->current_DW;
00610         value_t *a_value = NULL;
00611         guchar *bin_datas = NULL;
00612         GList *data_type_list = NULL;
00613         data_type_t *a_data_type = NULL;
00614         guint length = 0;
00615         gboolean result = FALSE;
00616         gchar *text = NULL;
00617                         
00618         data_type_list = main_window->data_type_list;
00619 
00620         while (data_type_list != NULL)
00621                 {
00622                         a_data_type = (data_type_t *) data_type_list->data;
00623 
00624                         if (a_data_type != NULL)
00625                                 {
00626                                         length = a_data_type->size;
00627                                         bin_datas = (guchar *) g_malloc0(sizeof(guchar) * length);
00628                                         result = ghex_get_data(data_window, length, endianness, bin_datas);
00629 
00630                                         if (result == TRUE)
00631                                                 {
00632                                                         a_value = new_value_t(length, bin_datas);
00633                                                         refresh_one_ud_data_interpretor(a_data_type, a_value);
00634                                                 }
00635                                         else
00636                                                 {
00637                                                         text = g_strdup_printf("Cannot copy %d bytes in order to interpret them !", length);
00638                                                         gtk_entry_set_text(GTK_ENTRY(a_data_type->di_entry), text);
00639                                                         g_free(text);
00640                                                 }
00641                                         g_free(bin_datas);
00642                                 }
00643 
00644                         data_type_list = g_list_next(data_type_list);
00645                 }
00646                 
00647 }
00648 
00649 
00650 /**
00651  *  Refreshes the "hex_datas_entry" which displays
00652  *  the hex datas extracted from the hexwidget at the
00653  *  cursor position. Endianness is Little Endian for now,
00654  *  we may, at a later time let the user choose its endianness
00655  *  it also places the spin widget value in the current_data_type
00656  *  structure.
00657  */
00658 void refresh_hex_datas_entry(heraia_window_t *main_window)
00659 {
00660         guchar *bin_datas = NULL;
00661         data_window_t *data_window = main_window->current_DW;
00662         guint length = 0;
00663         gboolean result = FALSE;
00664         GtkWidget *entry = NULL;
00665         value_t *a_value = NULL;
00666         GList *values_list = NULL;
00667         GList *tment_c_list = NULL;
00668         guchar *final = NULL;
00669 
00670         length = main_window->current_data_type->size;
00671 
00672         if (data_window->current_hexwidget != NULL)
00673                 {
00674                         bin_datas = (guchar *) g_malloc0(sizeof(guchar) * length);
00675                         result = ghex_get_data(data_window, length, H_DI_LITTLE_ENDIAN, bin_datas);
00676 
00677                         if (result == TRUE)
00678                                 {
00679                                         entry = heraia_get_widget(main_window->xmls->main, "hex_datas_entry");
00680                                         a_value = new_value_t(length, bin_datas);
00681                                         values_list = g_list_append(values_list, (gpointer) a_value);
00682 
00683                                         print_bin_to_hex(entry, values_list);
00684 
00685                                         /* Follows the others for the data_type beiing edited */
00686                                         tment_c_list = main_window->current_data_type->treatment_c_list;
00687                                         final = update_treatment_container_list_entries(tment_c_list, values_list);
00688                                                         
00689                                         /* data interpretor part */
00690                                         if (final != NULL)
00691                                                 {
00692                                                         gtk_entry_set_text(GTK_ENTRY(main_window->current_data_type->di_entry), (gchar *) final);
00693                                                 }
00694                                 }
00695 
00696                         g_free(bin_datas);
00697                 }       
00698 }
00699 
00700 
00701 /**
00702  *  Clears data_type window's widgets and sets to default
00703  *  values. Currently UNUSED
00704  */
00705 /*
00706 void clear_data_type_widgets(heraia_window_t *main_window)
00707 {
00708         GtkEntry *entry = NULL;
00709         GtkSpinButton *size_spin_button = NULL;
00710         gdouble min = 0.0;
00711         gdouble max = 0.0;
00712 
00713         entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
00714         gtk_entry_set_text(entry, "");
00715 
00716         size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
00717         gtk_spin_button_get_range(size_spin_button, &min, &max);
00718         gtk_spin_button_set_value(size_spin_button, min);
00719 
00720         refresh_hex_datas_entry(main_window);
00721 }
00722 */
00723 
00724 
00725 /**
00726  *  Fills the data_type window's widgets with values taken from the
00727  *  data_type_list structure
00728  */
00729 void fill_data_type_widgets(heraia_window_t *main_window, data_type_t *a_data_type)
00730 {
00731         GtkEntry *entry = NULL;
00732         GtkSpinButton *size_spin_button = NULL;
00733         gdouble min = 0.0;
00734         gdouble max = 0.0;
00735 
00736         /* name */
00737         entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
00738         gtk_entry_set_text(entry, a_data_type->name);
00739 
00740         /* size */
00741         size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
00742         gtk_spin_button_get_range(size_spin_button, &min, &max);
00743 
00744         if (a_data_type->size >= min && a_data_type->size <= max)
00745                 {
00746                         gtk_spin_button_set_value(size_spin_button, a_data_type->size);
00747                 }
00748         else
00749                 { 
00750                         if (a_data_type->size > max)
00751                                 { /* May be we're close the end of a file */
00752                                         gtk_spin_button_set_value(size_spin_button, max);
00753                                 }
00754                         else
00755                                 { /* Fallback case */
00756                                         gtk_spin_button_set_value(size_spin_button, max);
00757                                 }
00758                 }
00759 
00760         refresh_hex_datas_entry(main_window);
00761 }
00762 
00763 
00764 /**
00765  *  Says wether name "name" is already in use in "data_type_list" list
00766  *  and returns NULL if not or the list that contains the data_type_t 
00767  *  where name was found
00768  */
00769 GList *is_data_type_name_already_used(GList *data_type_list, gchar *name)
00770 { 
00771         gboolean result = FALSE;
00772         data_type_t *one_data_type = NULL;
00773 
00774         while (data_type_list != NULL && result == FALSE)
00775                 {
00776                         one_data_type = (data_type_t *) data_type_list->data;
00777                         
00778                         if (g_ascii_strcasecmp(name, one_data_type->name) == 0)
00779                                 {
00780                                         result = TRUE;
00781                                 }
00782                         else
00783                                 {
00784                                         data_type_list = data_type_list->next;
00785                                 }
00786                 }
00787 
00788         if (result == TRUE)
00789                 {
00790                         return data_type_list;
00791                 }
00792         else
00793                 {
00794                         return NULL;
00795                 }
00796 }
00797 
00798 
00799 /**
00800  *  Called when the data type window is killed or closed
00801  */
00802 static gboolean delete_data_type_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00803 {       
00804         heraia_window_t *main_window = (heraia_window_t *) data;
00805 
00806         close_data_type_window(main_window);
00807 
00808         return TRUE;
00809 }
00810 
00811 
00812 /**
00813  *  Called when the data type window is killed or closed
00814  */
00815 static void destroy_data_type_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00816 {
00817         heraia_window_t *main_window = (heraia_window_t *) data;
00818 
00819         close_data_type_window(main_window);
00820 }
00821 
00822 
00823 /**
00824  *  Retrieves informations from the data_type window widgets
00825  *  Currently UNUSED
00826  */
00827 /*
00828 static data_type_t *retrieve_data_type_information(heraia_window_t *main_window)
00829 {
00830         GtkEntry *entry = NULL;  
00831         gchar *name = NULL;      
00832         gint size = 0;           
00833         GtkSpinButton *size_spin_button = NULL;  
00834 
00835         entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
00836         name = gtk_entry_get_text(entry); 
00837 
00838         size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
00839         size = gtk_spin_button_get_value_as_int(size_spin_button);
00840 
00841         return new_data_type(name, size);
00842 }
00843 */
00844 
00845 
00846 /**
00847  *  Destroys a container Widget.
00848  *  If all is true it destroys everything even the treatment and such.
00849  *  If all is false it destroys only the widget part.
00850  */
00851 static void destroy_container_widget(treatment_container_t *tment_c, gboolean all)
00852 {
00853         if (tment_c != NULL)
00854                 {
00855                         destroy_a_single_widget(tment_c->plus); 
00856                         tment_c->plus = NULL;
00857 
00858                         destroy_a_single_widget(tment_c->moins); 
00859                         tment_c->moins = NULL;
00860                         
00861                         destroy_a_single_widget(tment_c->result); 
00862                         tment_c->result = NULL;
00863 
00864                         destroy_a_single_widget(tment_c->tment_list); 
00865                         tment_c->tment_list = NULL;
00866 
00867                         destroy_a_single_widget(tment_c->button_box); 
00868                         tment_c->button_box = NULL;
00869 
00870                         destroy_a_single_widget(tment_c->combo_box); 
00871                         tment_c->combo_box = NULL;
00872 
00873                         destroy_a_single_widget(tment_c->container_box); 
00874                         tment_c->container_box = NULL;
00875 
00876                         if (all == TRUE)
00877                                 {
00878 
00879                                         if (tment_c->treatment != NULL && tment_c->treatment->kill != NULL)
00880                                                 {
00881                                                         tment_c->treatment->kill(tment_c->treatment); /* erases itself */
00882                                                 }
00883                                         
00884                                         g_free(tment_c);
00885                                 }
00886                 }
00887 }
00888 
00889 /**
00890  *  Called when the data_type_window is closed
00891  */
00892 static void close_data_type_window(heraia_window_t *main_window)
00893 {
00894         data_type_t *a_data_type = NULL; /* data type currently in use */
00895         GList *list = NULL;
00896 
00897         /* Current data type beeing edited */
00898         a_data_type = main_window->current_data_type; 
00899 
00900         /* Current treatment container list for this data type */
00901         list = a_data_type->treatment_c_list;
00902         
00903         /* Destroys all widgets associated with the treatment container list */
00904         /* This does not destroys the list itself here */
00905         while (list != NULL)
00906                 {
00907                         destroy_container_widget((treatment_container_t *)list->data, FALSE);
00908                         list = g_list_next(list);
00909                 }
00910 
00911         /** Last box stuff : I do not know if this is really usefull !!                                   */
00912         /* Destroys the last widget (which should never contain any treatment)                            */
00913         /* list = g_list_last(a_data_type->treatment_c_list);                                             */
00914         /* if (list != NULL)                                                                              */
00915         /*      {                                                                                             */
00916         /*              destroy_container_widget((treatment_container_t *)list->data, TRUE);                      */
00917         /*              a_data_type->treatment_c_list  = g_list_delete_link(a_data_type->treatment_c_list, list); */
00918         /*      }                                                                                             */
00919         
00920         /* Hiding the window */
00921         gtk_widget_hide(heraia_get_widget(main_window->xmls->main, "data_type_window"));
00922 }
00923 
00924 /**
00925  *  The user clicks "Ok" button
00926  */
00927 static void dt_ok_button_clicked(GtkWidget *widget, gpointer data)
00928 {
00929   heraia_window_t *main_window = (heraia_window_t *) data;
00930   data_type_t *a_data_type = NULL;
00931   GList *data_type_list = NULL;
00932   
00933   a_data_type = main_window->current_data_type;
00934         
00935   if (g_ascii_strcasecmp(a_data_type->name, "") != 0)
00936           {
00937                   data_type_list = is_data_type_name_already_used(main_window->data_type_list, a_data_type->name);
00938 
00939                   if (data_type_list == NULL)
00940                           {
00941                                   /**
00942                                    *  The name does not exists, we want to add it to the treeview and to the
00943                                    *  list structure (the user clicked add(+) in the list window or edited the name)
00944                                    */
00945                                   log_message(main_window, G_LOG_LEVEL_DEBUG, "Adding %s data type name to treeview", a_data_type->name);
00946                                   add_data_type_name_to_treeview(main_window, a_data_type->name);
00947 
00948                                   /* data interpretor part */
00949                                   gtk_label_set_text(GTK_LABEL(a_data_type->di_label), a_data_type->name);
00950 
00951                                   main_window->data_type_list = g_list_prepend(main_window->data_type_list, a_data_type);
00952                           }
00953                   else
00954                           {
00955                                   /**
00956                                    *  The name is already in use, we assume that we are in editing mode
00957                                    *  and we simply replace the old data_type_t structure by the new one !
00958                                    */
00959                                   log_message(main_window, G_LOG_LEVEL_DEBUG, "Editing mode (%s exists)", a_data_type->name);
00960                                   
00961                                   /* We kill the old widget's that are unsefull (we replace them) */
00962                                   destroy_a_single_widget(main_window->current_data_type->di_label);
00963                                   destroy_a_single_widget(main_window->current_data_type->di_entry);
00964                                   destroy_a_single_widget(((data_type_t *)data_type_list->data)->di_label);
00965                                   destroy_a_single_widget(((data_type_t *)data_type_list->data)->di_entry);
00966 
00967                                   free_data_type((data_type_t *)data_type_list->data);
00968                                   create_ud_data_interpretor_widgets(main_window, a_data_type);
00969 
00970                                   /* data interpretor part */
00971                                   gtk_label_set_text(GTK_LABEL(a_data_type->di_label), a_data_type->name);
00972 
00973                                   data_type_list->data = a_data_type;
00974                           }
00975 
00976                   refresh_hex_datas_entry(main_window);
00977 
00978                   close_data_type_window(main_window);
00979           }
00980 }
00981 
00982 
00983 /**
00984  *  The user clicks "Cancel" button
00985  */
00986 static void dt_cancel_button_clicked(GtkWidget *widget, gpointer data)
00987 {
00988         heraia_window_t *main_window = (heraia_window_t *) data;
00989         data_type_t *a_data_type = NULL;
00990 
00991         a_data_type = main_window->current_data_type;
00992 
00993         /* the data interpretor part */
00994         destroy_a_single_widget(a_data_type->di_label);
00995         destroy_a_single_widget(a_data_type->di_entry);
00996    
00997         close_data_type_window(main_window);
00998 }
00999 
01000 
01001 /**
01002  *  When the user changes the size of the data that will
01003  *  be used to construct a new type
01004  */
01005 static void dt_size_spinbutton_value_changed(GtkWidget *widget, gpointer data)
01006 {
01007         heraia_window_t *main_window = (heraia_window_t *) data;
01008         GtkSpinButton *dt_size_spinbutton = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
01009         guint length = 0;
01010 
01011         if (main_window != NULL)
01012                 {
01013 
01014                 length = gtk_spin_button_get_value_as_int(dt_size_spinbutton);
01015                         
01016                 if (length >= DT_SPIN_MIN && length <= DT_SPIN_MAX)
01017                         {
01018                                 if (main_window->current_data_type != NULL)
01019                                         {
01020                                                 main_window->current_data_type->size = length;
01021                                         }       
01022                         }
01023 
01024                         refresh_hex_datas_entry(main_window);
01025                 }
01026 }
01027 
01028 
01029 /**
01030  *  When the user leaves the name entry 
01031  *  Gets the name entry if any and puts it in the current_data_type
01032  *  structure. 
01033  */
01034 static void dt_name_entry_leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
01035 {
01036         heraia_window_t *main_window = (heraia_window_t *) data;
01037         GtkEntry *entry = NULL;  
01038 
01039         if (main_window != NULL && main_window->current_data_type != NULL)
01040                 {
01041                         entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
01042                         
01043                         if (main_window->current_data_type->name != NULL)
01044                                 {
01045                                         g_free(main_window->current_data_type->name);
01046                                 }
01047 
01048                         main_window->current_data_type->name = g_strdup(gtk_entry_get_text(entry));
01049 
01050                 }
01051 }
01052 
01053 
01054 
01055 /**
01056  *  Connects data_type's window signals.
01057  */
01058 static void connect_data_type_signals(heraia_window_t *main_window)
01059 {
01060 
01061   if (main_window != NULL && main_window->xmls != NULL && main_window->xmls->main != NULL)
01062     {
01063       /* data type window killed or destroyed */
01064       g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "data_type_window")), "delete_event", 
01065                        G_CALLBACK(delete_data_type_window_event), main_window);
01066                   
01067       g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "data_type_window")), "destroy", 
01068                        G_CALLBACK(destroy_data_type_window), main_window);
01069       
01070       /* Ok button */
01071       g_signal_connect (G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_ok_button")), "clicked", 
01072                         G_CALLBACK(dt_ok_button_clicked), main_window);
01073       
01074       /* Cancel button */
01075       g_signal_connect (G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_cancel_button")), "clicked", 
01076                         G_CALLBACK(dt_cancel_button_clicked), main_window);
01077 
01078           /* When the size spinbutton changes its value */
01079           g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton")), "value-changed", 
01080                                            G_CALLBACK(dt_size_spinbutton_value_changed), main_window);
01081           
01082           /* When the user leaves the name entry */
01083           g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_name_entry")), "leave-notify-event", 
01084                                            G_CALLBACK(dt_name_entry_leave_notify_event), main_window);
01085 
01086     }
01087 }
01088 
01089 
01090 /**
01091  *  Inits the data type window with default values
01092  *  Should be called only once
01093  *  Here we may load a specific file where the user 
01094  *  data types are saved
01095  */
01096 void data_type_init_interface(heraia_window_t *main_window)
01097 {
01098   if (main_window != NULL)
01099     {
01100       connect_data_type_signals(main_window);
01101     }
01102 }

Generated on Sat Mar 14 13:44:29 2009 for Heraia by  doxygen 1.5.6