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         doc_t *doc = main_window->current_doc;
00145         guint64 till_end = 0;
00146         GtkSpinButton *size_spin_button = NULL;
00147         GtkHex *gh = NULL;
00148 
00149         gh = GTK_HEX(doc->hex_widget);
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         doc_t *doc = main_window->current_doc;
00663         guint length = 0;
00664         gboolean result = FALSE;
00665         GtkWidget *entry = NULL;
00666         value_t *a_value = NULL;
00667         GList *values_list = NULL;
00668         GList *tment_c_list = NULL;
00669         guchar *final = NULL;
00670 
00671         length = main_window->current_data_type->size;
00672 
00673         if (doc->hex_widget != NULL)
00674                 {
00675                         bin_datas = (guchar *) g_malloc0(sizeof(guchar) * length);
00676                         result = ghex_get_data(data_window, length, H_DI_LITTLE_ENDIAN, bin_datas);
00677 
00678                         if (result == TRUE)
00679                                 {
00680                                         entry = heraia_get_widget(main_window->xmls->main, "hex_datas_entry");
00681                                         a_value = new_value_t(length, bin_datas);
00682                                         values_list = g_list_append(values_list, (gpointer) a_value);
00683 
00684                                         print_bin_to_hex(entry, values_list);
00685 
00686                                         /* Follows the others for the data_type beiing edited */
00687                                         tment_c_list = main_window->current_data_type->treatment_c_list;
00688                                         final = update_treatment_container_list_entries(tment_c_list, values_list);
00689                                                         
00690                                         /* data interpretor part */
00691                                         if (final != NULL)
00692                                                 {
00693                                                         gtk_entry_set_text(GTK_ENTRY(main_window->current_data_type->di_entry), (gchar *) final);
00694                                                 }
00695                                 }
00696 
00697                         g_free(bin_datas);
00698                 }       
00699 }
00700 
00701 
00702 /**
00703  *  Clears data_type window's widgets and sets to default
00704  *  values. Currently UNUSED
00705  */
00706 /*
00707 void clear_data_type_widgets(heraia_window_t *main_window)
00708 {
00709         GtkEntry *entry = NULL;
00710         GtkSpinButton *size_spin_button = NULL;
00711         gdouble min = 0.0;
00712         gdouble max = 0.0;
00713 
00714         entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
00715         gtk_entry_set_text(entry, "");
00716 
00717         size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
00718         gtk_spin_button_get_range(size_spin_button, &min, &max);
00719         gtk_spin_button_set_value(size_spin_button, min);
00720 
00721         refresh_hex_datas_entry(main_window);
00722 }
00723 */
00724 
00725 
00726 /**
00727  *  Fills the data_type window's widgets with values taken from the
00728  *  data_type_list structure
00729  */
00730 void fill_data_type_widgets(heraia_window_t *main_window, data_type_t *a_data_type)
00731 {
00732         GtkEntry *entry = NULL;
00733         GtkSpinButton *size_spin_button = NULL;
00734         gdouble min = 0.0;
00735         gdouble max = 0.0;
00736 
00737         /* name */
00738         entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
00739         gtk_entry_set_text(entry, a_data_type->name);
00740 
00741         /* size */
00742         size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
00743         gtk_spin_button_get_range(size_spin_button, &min, &max);
00744 
00745         if (a_data_type->size >= min && a_data_type->size <= max)
00746                 {
00747                         gtk_spin_button_set_value(size_spin_button, a_data_type->size);
00748                 }
00749         else
00750                 { 
00751                         if (a_data_type->size > max)
00752                                 { /* May be we're close the end of a file */
00753                                         gtk_spin_button_set_value(size_spin_button, max);
00754                                 }
00755                         else
00756                                 { /* Fallback case */
00757                                         gtk_spin_button_set_value(size_spin_button, max);
00758                                 }
00759                 }
00760 
00761         refresh_hex_datas_entry(main_window);
00762 }
00763 
00764 
00765 /**
00766  *  Says wether name "name" is already in use in "data_type_list" list
00767  *  and returns NULL if not or the list that contains the data_type_t 
00768  *  where name was found
00769  */
00770 GList *is_data_type_name_already_used(GList *data_type_list, gchar *name)
00771 { 
00772         gboolean result = FALSE;
00773         data_type_t *one_data_type = NULL;
00774 
00775         while (data_type_list != NULL && result == FALSE)
00776                 {
00777                         one_data_type = (data_type_t *) data_type_list->data;
00778                         
00779                         if (g_ascii_strcasecmp(name, one_data_type->name) == 0)
00780                                 {
00781                                         result = TRUE;
00782                                 }
00783                         else
00784                                 {
00785                                         data_type_list = data_type_list->next;
00786                                 }
00787                 }
00788 
00789         if (result == TRUE)
00790                 {
00791                         return data_type_list;
00792                 }
00793         else
00794                 {
00795                         return NULL;
00796                 }
00797 }
00798 
00799 
00800 /**
00801  *  Called when the data type window is killed or closed
00802  */
00803 static gboolean delete_data_type_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00804 {       
00805         heraia_window_t *main_window = (heraia_window_t *) data;
00806 
00807         close_data_type_window(main_window);
00808 
00809         return TRUE;
00810 }
00811 
00812 
00813 /**
00814  *  Called when the data type window is killed or closed
00815  */
00816 static void destroy_data_type_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00817 {
00818         heraia_window_t *main_window = (heraia_window_t *) data;
00819 
00820         close_data_type_window(main_window);
00821 }
00822 
00823 
00824 /**
00825  *  Retrieves informations from the data_type window widgets
00826  *  Currently UNUSED
00827  */
00828 /*
00829 static data_type_t *retrieve_data_type_information(heraia_window_t *main_window)
00830 {
00831         GtkEntry *entry = NULL;  
00832         gchar *name = NULL;      
00833         gint size = 0;           
00834         GtkSpinButton *size_spin_button = NULL;  
00835 
00836         entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
00837         name = gtk_entry_get_text(entry); 
00838 
00839         size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
00840         size = gtk_spin_button_get_value_as_int(size_spin_button);
00841 
00842         return new_data_type(name, size);
00843 }
00844 */
00845 
00846 
00847 /**
00848  *  Destroys a container Widget.
00849  *  If all is true it destroys everything even the treatment and such.
00850  *  If all is false it destroys only the widget part.
00851  */
00852 static void destroy_container_widget(treatment_container_t *tment_c, gboolean all)
00853 {
00854         if (tment_c != NULL)
00855                 {
00856                         destroy_a_single_widget(tment_c->plus); 
00857                         tment_c->plus = NULL;
00858 
00859                         destroy_a_single_widget(tment_c->moins); 
00860                         tment_c->moins = NULL;
00861                         
00862                         destroy_a_single_widget(tment_c->result); 
00863                         tment_c->result = NULL;
00864 
00865                         destroy_a_single_widget(tment_c->tment_list); 
00866                         tment_c->tment_list = NULL;
00867 
00868                         destroy_a_single_widget(tment_c->button_box); 
00869                         tment_c->button_box = NULL;
00870 
00871                         destroy_a_single_widget(tment_c->combo_box); 
00872                         tment_c->combo_box = NULL;
00873 
00874                         destroy_a_single_widget(tment_c->container_box); 
00875                         tment_c->container_box = NULL;
00876 
00877                         if (all == TRUE)
00878                                 {
00879 
00880                                         if (tment_c->treatment != NULL && tment_c->treatment->kill != NULL)
00881                                                 {
00882                                                         tment_c->treatment->kill(tment_c->treatment); /* erases itself */
00883                                                 }
00884                                         
00885                                         g_free(tment_c);
00886                                 }
00887                 }
00888 }
00889 
00890 /**
00891  *  Called when the data_type_window is closed
00892  */
00893 static void close_data_type_window(heraia_window_t *main_window)
00894 {
00895         data_type_t *a_data_type = NULL; /* data type currently in use */
00896         GList *list = NULL;
00897 
00898         /* Current data type beeing edited */
00899         a_data_type = main_window->current_data_type; 
00900 
00901         /* Current treatment container list for this data type */
00902         list = a_data_type->treatment_c_list;
00903         
00904         /* Destroys all widgets associated with the treatment container list */
00905         /* This does not destroys the list itself here */
00906         while (list != NULL)
00907                 {
00908                         destroy_container_widget((treatment_container_t *)list->data, FALSE);
00909                         list = g_list_next(list);
00910                 }
00911 
00912         /** Last box stuff : I do not know if this is really usefull !!                                   */
00913         /* Destroys the last widget (which should never contain any treatment)                            */
00914         /* list = g_list_last(a_data_type->treatment_c_list);                                             */
00915         /* if (list != NULL)                                                                              */
00916         /*      {                                                                                             */
00917         /*              destroy_container_widget((treatment_container_t *)list->data, TRUE);                      */
00918         /*              a_data_type->treatment_c_list  = g_list_delete_link(a_data_type->treatment_c_list, list); */
00919         /*      }                                                                                             */
00920         
00921         /* Hiding the window */
00922         gtk_widget_hide(heraia_get_widget(main_window->xmls->main, "data_type_window"));
00923 }
00924 
00925 /**
00926  *  The user clicks "Ok" button
00927  */
00928 static void dt_ok_button_clicked(GtkWidget *widget, gpointer data)
00929 {
00930   heraia_window_t *main_window = (heraia_window_t *) data;
00931   data_type_t *a_data_type = NULL;
00932   GList *data_type_list = NULL;
00933   
00934   a_data_type = main_window->current_data_type;
00935         
00936   if (g_ascii_strcasecmp(a_data_type->name, "") != 0)
00937           {
00938                   data_type_list = is_data_type_name_already_used(main_window->data_type_list, a_data_type->name);
00939 
00940                   if (data_type_list == NULL)
00941                           {
00942                                   /**
00943                                    *  The name does not exists, we want to add it to the treeview and to the
00944                                    *  list structure (the user clicked add(+) in the list window or edited the name)
00945                                    */
00946                                   log_message(main_window, G_LOG_LEVEL_DEBUG, "Adding %s data type name to treeview", a_data_type->name);
00947                                   add_data_type_name_to_treeview(main_window, a_data_type->name);
00948 
00949                                   /* data interpretor part */
00950                                   gtk_label_set_text(GTK_LABEL(a_data_type->di_label), a_data_type->name);
00951 
00952                                   main_window->data_type_list = g_list_prepend(main_window->data_type_list, a_data_type);
00953                           }
00954                   else
00955                           {
00956                                   /**
00957                                    *  The name is already in use, we assume that we are in editing mode
00958                                    *  and we simply replace the old data_type_t structure by the new one !
00959                                    */
00960                                   log_message(main_window, G_LOG_LEVEL_DEBUG, "Editing mode (%s exists)", a_data_type->name);
00961                                   
00962                                   /* We kill the old widget's that are unsefull (we replace them) */
00963                                   destroy_a_single_widget(main_window->current_data_type->di_label);
00964                                   destroy_a_single_widget(main_window->current_data_type->di_entry);
00965                                   destroy_a_single_widget(((data_type_t *)data_type_list->data)->di_label);
00966                                   destroy_a_single_widget(((data_type_t *)data_type_list->data)->di_entry);
00967 
00968                                   free_data_type((data_type_t *)data_type_list->data);
00969                                   create_ud_data_interpretor_widgets(main_window, a_data_type);
00970 
00971                                   /* data interpretor part */
00972                                   gtk_label_set_text(GTK_LABEL(a_data_type->di_label), a_data_type->name);
00973 
00974                                   data_type_list->data = a_data_type;
00975                           }
00976 
00977                   refresh_hex_datas_entry(main_window);
00978 
00979                   close_data_type_window(main_window);
00980           }
00981 }
00982 
00983 
00984 /**
00985  *  The user clicks "Cancel" button
00986  */
00987 static void dt_cancel_button_clicked(GtkWidget *widget, gpointer data)
00988 {
00989         heraia_window_t *main_window = (heraia_window_t *) data;
00990         data_type_t *a_data_type = NULL;
00991 
00992         a_data_type = main_window->current_data_type;
00993 
00994         /* the data interpretor part */
00995         destroy_a_single_widget(a_data_type->di_label);
00996         destroy_a_single_widget(a_data_type->di_entry);
00997    
00998         close_data_type_window(main_window);
00999 }
01000 
01001 
01002 /**
01003  *  When the user changes the size of the data that will
01004  *  be used to construct a new type
01005  */
01006 static void dt_size_spinbutton_value_changed(GtkWidget *widget, gpointer data)
01007 {
01008         heraia_window_t *main_window = (heraia_window_t *) data;
01009         GtkSpinButton *dt_size_spinbutton = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
01010         guint length = 0;
01011 
01012         if (main_window != NULL)
01013                 {
01014 
01015                 length = gtk_spin_button_get_value_as_int(dt_size_spinbutton);
01016                         
01017                 if (length >= DT_SPIN_MIN && length <= DT_SPIN_MAX)
01018                         {
01019                                 if (main_window->current_data_type != NULL)
01020                                         {
01021                                                 main_window->current_data_type->size = length;
01022                                         }       
01023                         }
01024 
01025                         refresh_hex_datas_entry(main_window);
01026                 }
01027 }
01028 
01029 
01030 /**
01031  *  When the user leaves the name entry 
01032  *  Gets the name entry if any and puts it in the current_data_type
01033  *  structure. 
01034  */
01035 static void dt_name_entry_leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
01036 {
01037         heraia_window_t *main_window = (heraia_window_t *) data;
01038         GtkEntry *entry = NULL;  
01039 
01040         if (main_window != NULL && main_window->current_data_type != NULL)
01041                 {
01042                         entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
01043                         
01044                         if (main_window->current_data_type->name != NULL)
01045                                 {
01046                                         g_free(main_window->current_data_type->name);
01047                                 }
01048 
01049                         main_window->current_data_type->name = g_strdup(gtk_entry_get_text(entry));
01050 
01051                 }
01052 }
01053 
01054 
01055 
01056 /**
01057  *  Connects data_type's window signals.
01058  */
01059 static void connect_data_type_signals(heraia_window_t *main_window)
01060 {
01061 
01062   if (main_window != NULL && main_window->xmls != NULL && main_window->xmls->main != NULL)
01063     {
01064       /* data type window killed or destroyed */
01065       g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "data_type_window")), "delete_event", 
01066                        G_CALLBACK(delete_data_type_window_event), main_window);
01067                   
01068       g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "data_type_window")), "destroy", 
01069                        G_CALLBACK(destroy_data_type_window), main_window);
01070       
01071       /* Ok button */
01072       g_signal_connect (G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_ok_button")), "clicked", 
01073                         G_CALLBACK(dt_ok_button_clicked), main_window);
01074       
01075       /* Cancel button */
01076       g_signal_connect (G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_cancel_button")), "clicked", 
01077                         G_CALLBACK(dt_cancel_button_clicked), main_window);
01078 
01079           /* When the size spinbutton changes its value */
01080           g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton")), "value-changed", 
01081                                            G_CALLBACK(dt_size_spinbutton_value_changed), main_window);
01082           
01083           /* When the user leaves the name entry */
01084           g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_name_entry")), "leave-notify-event", 
01085                                            G_CALLBACK(dt_name_entry_leave_notify_event), main_window);
01086 
01087     }
01088 }
01089 
01090 
01091 /**
01092  *  Inits the data type window with default values
01093  *  Should be called only once
01094  *  Here we may load a specific file where the user 
01095  *  data types are saved
01096  */
01097 void data_type_init_interface(heraia_window_t *main_window)
01098 {
01099   if (main_window != NULL)
01100     {
01101       connect_data_type_signals(main_window);
01102     }
01103 }

Generated on Tue Jun 30 23:18:17 2009 for Heraia by  doxygen 1.5.8