1 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 : /*
3 : data_types.c
4 : Window allowing the user to create or edit a new data type
5 :
6 : (C) Copyright 2007 - 2007 Olivier Delhomme
7 : e-mail : heraia@delhomme.org
8 : URL : http://heraia.tuxfamily.org
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 2, or (at your option)
13 : any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program; if not, write to the Free Software
22 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 : */
24 :
25 : #include "heraia_types.h"
26 :
27 : static gboolean delete_data_type_window_event(GtkWidget *widget, GdkEvent *event, gpointer data);
28 : static void destroy_data_type_window(GtkWidget *widget, GdkEvent *event, gpointer data);
29 : static void dt_ok_button_clicked(GtkWidget *widget, gpointer data);
30 : static void dt_cancel_button_clicked(GtkWidget *widget, gpointer data);
31 : static void connect_data_type_signals(heraia_window_t *main_window);
32 : /* static data_type_t *retrieve_data_type_information(heraia_window_t *main_window); */
33 : static void set_spinbutton_max_range(heraia_window_t *main_window);
34 :
35 : static void close_data_type_window(heraia_window_t *main_window);
36 : static void destroy_container_widget(treatment_container_t *tment_c, gboolean all);
37 : static treatment_container_t *new_treatment_container(heraia_window_t *main_window);
38 : static void create_treatment_container_widget(heraia_window_t *main_window, treatment_container_t *tment_c);
39 : static guchar *print_bin_to_hex(GtkWidget *entry, GList *values_list);
40 :
41 : /* treatment container widget signals */
42 : static void add_treatment_container_widget(GtkWidget *widget, gpointer data);
43 : static void remove_treatment_container_widget(GtkWidget *widget, gpointer data);
44 : static void cb_changed_in_treatment_container_widget(GtkWidget *widget, gpointer data);
45 :
46 : /**
47 : * Returns a new data_type filled with name and size values
48 : */
49 : data_type_t *new_data_type(gchar *name, guint size)
50 0 : {
51 0 : data_type_t *a_data_type = NULL;
52 :
53 0 : a_data_type = (data_type_t *) g_malloc0(sizeof(data_type_t));
54 :
55 0 : if (name != NULL)
56 : {
57 0 : a_data_type->name = g_strdup(name);
58 : }
59 : else
60 : {
61 0 : a_data_type->name = NULL;
62 : }
63 :
64 0 : a_data_type->size = size;
65 :
66 : /* Data interpretor widgets */
67 0 : a_data_type->di_label = NULL;
68 0 : a_data_type->di_entry = NULL;
69 :
70 0 : return a_data_type;
71 : }
72 :
73 :
74 : /**
75 : * Frees the memory of a particular data_type
76 : */
77 : void free_data_type(data_type_t *a_data_type)
78 0 : {
79 0 : if (a_data_type != NULL)
80 : {
81 0 : if (a_data_type->name != NULL)
82 : {
83 0 : g_free(a_data_type->name);
84 : }
85 :
86 0 : g_free(a_data_type);
87 : }
88 0 : }
89 :
90 :
91 : /**
92 : * Copies the data_type_t structure in a new one,
93 : * that may be freely freed after use.
94 : * main_window needed to fill the combobox widget with available treatment list
95 : */
96 : data_type_t *copy_data_type_struct(heraia_window_t *main_window, data_type_t *a_data_type)
97 0 : {
98 0 : data_type_t *data_type = NULL;
99 0 : treatment_container_t *tment_c = NULL;
100 0 : GList *list = NULL;
101 0 : GList *list2 = NULL;
102 :
103 0 : if (a_data_type != NULL)
104 : {
105 0 : data_type = new_data_type(a_data_type->name, a_data_type->size);
106 0 : list = a_data_type->treatment_c_list;
107 :
108 0 : while (list != NULL)
109 : {
110 : /**
111 : * Here we do not copy the widgets as they will be created
112 : * on the fly. We copy the list and the treatments
113 : */
114 0 : tment_c = new_treatment_container(main_window);
115 0 : tment_c->treatment = copy_treatment(((treatment_container_t *)list->data)->treatment);
116 0 : list2 = g_list_append(list2, tment_c);
117 0 : list = g_list_next(list);
118 : }
119 :
120 0 : data_type->treatment_c_list = list2;
121 :
122 : /* data interpretor widget creation */
123 0 : create_ud_data_interpretor_widgets(main_window, data_type);
124 0 : gtk_label_set_text(GTK_LABEL(data_type->di_label), gtk_label_get_text(GTK_LABEL(a_data_type->di_label)));
125 : }
126 :
127 0 : return data_type;
128 : }
129 :
130 :
131 : /**
132 : * Sets the maximum range of the spinbutton on the Data type Window
133 : * (usefull when we're next to the file's end)
134 : * This is done to ensure that the spinbutton always represent an
135 : * exact and valid size
136 : */
137 : static void set_spinbutton_max_range(heraia_window_t *main_window)
138 0 : {
139 0 : data_window_t *data_window = main_window->current_DW;
140 0 : guint64 till_end = 0;
141 0 : GtkSpinButton *size_spin_button = NULL;
142 0 : GtkHex *gh = NULL;
143 :
144 0 : gh = GTK_HEX(data_window->current_hexwidget);
145 :
146 0 : if (gh != NULL)
147 : {
148 0 : size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
149 0 : till_end = ghex_file_size(gh) - gtk_hex_get_cursor(gh);
150 :
151 0 : if (till_end >= DT_SPIN_MIN && till_end <= DT_SPIN_MAX)
152 : {
153 0 : gtk_spin_button_set_range(size_spin_button, DT_SPIN_MIN, till_end);
154 : }
155 : else
156 : {
157 0 : gtk_spin_button_set_range(size_spin_button, DT_SPIN_MIN, DT_SPIN_MAX);
158 : }
159 : }
160 0 : }
161 :
162 :
163 : /**
164 : * Fills the treatment combobox with the available treatment list names
165 : * Set the active element on nothing (no active element)
166 : */
167 : static void fill_treatment_combobox(GtkWidget *tment_list, GList *available_list)
168 : {
169 0 : treatment_t *tment = NULL;
170 :
171 0 : while (available_list != NULL)
172 : {
173 0 : tment = (treatment_t *) available_list->data;
174 0 : if (tment->name != NULL)
175 : {
176 0 : gtk_combo_box_append_text(GTK_COMBO_BOX(tment_list), tment->name);
177 : }
178 :
179 0 : available_list = g_list_next(available_list);
180 : }
181 :
182 : /* No active element */
183 0 : gtk_combo_box_set_active(GTK_COMBO_BOX(tment_list), -1);
184 : }
185 :
186 : /**
187 : * Tries to set the named "name" active item of the combobox list.
188 : */
189 : static void set_active_text_item(GtkWidget *combo_box, gchar *name)
190 0 : {
191 : GtkTreeIter iter;
192 0 : GtkTreeModel *model = NULL;
193 0 : gchar *list_name = NULL;
194 0 : gboolean ok = TRUE;
195 0 : gboolean stop = FALSE;
196 :
197 0 : if (name != NULL)
198 : {
199 :
200 0 : model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box));
201 :
202 0 : ok = gtk_tree_model_get_iter_first(model, &iter);
203 :
204 0 : while (ok == TRUE && stop == FALSE)
205 : {
206 0 : gtk_tree_model_get(model, &iter, 0, &list_name, -1);
207 0 : if (g_ascii_strcasecmp(list_name, name) == 0)
208 : {
209 0 : stop = TRUE;
210 : }
211 : else
212 : {
213 0 : ok = gtk_tree_model_iter_next(model, &iter);
214 : }
215 : }
216 :
217 0 : if (stop == TRUE)
218 : {
219 0 : gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo_box), &iter);
220 : }
221 : }
222 0 : }
223 :
224 :
225 : /**
226 : * Create a new empty treatment container
227 : * Needs main_window structure to fill the combobox with available
228 : * treatments
229 : */
230 : static treatment_container_t *new_treatment_container(heraia_window_t *main_window)
231 0 : {
232 : treatment_container_t *tment_c;
233 :
234 0 : tment_c = (treatment_container_t *) g_malloc0(sizeof(treatment_container_t));
235 0 : tment_c->treatment = NULL;
236 :
237 : /* Widget initialization */
238 0 : tment_c->container_box = gtk_hbox_new(FALSE, DT_BOX_SPACING);
239 0 : tment_c->combo_box = gtk_vbox_new(FALSE, DT_BOX_SPACING);
240 0 : tment_c->button_box = gtk_hbox_new(FALSE, DT_BOX_SPACING);
241 0 : tment_c->tment_list = gtk_combo_box_new_text();
242 0 : fill_treatment_combobox(tment_c->tment_list, main_window->available_treatment_list);
243 :
244 0 : tment_c->result = gtk_entry_new();
245 0 : gtk_entry_set_editable(GTK_ENTRY(tment_c->result), FALSE);
246 0 : tment_c->moins = gtk_button_new_with_label(" - ");
247 0 : tment_c->plus = gtk_button_new_with_label(" + ");
248 :
249 :
250 0 : g_signal_connect(G_OBJECT(tment_c->plus), "clicked",
251 : G_CALLBACK(add_treatment_container_widget), main_window);
252 0 : g_signal_connect(G_OBJECT(tment_c->moins), "clicked",
253 : G_CALLBACK(remove_treatment_container_widget), main_window);
254 0 : g_signal_connect(G_OBJECT(tment_c->tment_list), "changed",
255 : G_CALLBACK(cb_changed_in_treatment_container_widget), main_window);
256 :
257 : /* Widget packing together */
258 0 : gtk_box_pack_start(GTK_BOX(tment_c->button_box), tment_c->moins, FALSE, FALSE, DT_BOX_PADDING);
259 0 : gtk_box_pack_start(GTK_BOX(tment_c->button_box), tment_c->plus, FALSE, FALSE, DT_BOX_PADDING);
260 0 : gtk_box_pack_start(GTK_BOX(tment_c->button_box), tment_c->result, FALSE, FALSE, DT_BOX_PADDING);
261 0 : gtk_box_pack_start(GTK_BOX(tment_c->combo_box), tment_c->tment_list, FALSE, FALSE, DT_BOX_PADDING);
262 0 : gtk_box_pack_end(GTK_BOX(tment_c->container_box), tment_c->button_box, FALSE, FALSE, DT_BOX_PADDING);
263 0 : gtk_box_pack_start(GTK_BOX(tment_c->container_box), tment_c->combo_box, FALSE, FALSE, DT_BOX_PADDING);
264 :
265 0 : return tment_c;
266 : }
267 :
268 :
269 : /**
270 : * Packs the container widget to the main window widgets via "dt_treatment_vbox".
271 : */
272 : static void create_treatment_container_widget(heraia_window_t *main_window, treatment_container_t *tment_c)
273 0 : {
274 0 : GtkWidget *vbox = NULL;
275 :
276 0 : vbox = heraia_get_widget(main_window->xmls->main, "dt_treatment_vbox");
277 :
278 0 : gtk_box_pack_start(GTK_BOX(vbox), tment_c->container_box, FALSE, FALSE, DT_BOX_PADDING);
279 :
280 0 : if (tment_c->treatment != NULL)
281 : {
282 : /* Here we call the method to init the treatment zone */
283 0 : tment_c->treatment->init(tment_c->treatment);
284 0 : set_active_text_item(tment_c->tment_list, tment_c->treatment->name);
285 : }
286 0 : }
287 :
288 :
289 : /**
290 : * Adds a treatment container widget when (+) button is clicked
291 : * TODO : determine which treatment it is (where the + button was clicked)
292 : * and insert the new one just after it (need to do the same in the list)
293 : */
294 : static void add_treatment_container_widget(GtkWidget *widget, gpointer data)
295 0 : {
296 0 : heraia_window_t *main_window = (heraia_window_t *) data;
297 0 : treatment_container_t *new_container = NULL;
298 0 : data_type_t *a_data_type = NULL;
299 :
300 0 : a_data_type = main_window->current_data_type;
301 :
302 : /* Creates a new treatment container */
303 0 : new_container = new_treatment_container(main_window);
304 :
305 : /* Create the last box that will contain one empty treatment container widget */
306 0 : create_treatment_container_widget(main_window, new_container);
307 :
308 0 : gtk_widget_show_all(new_container->container_box);
309 :
310 : /* Append the container to the list */
311 0 : a_data_type->treatment_c_list = g_list_append(a_data_type->treatment_c_list, (gpointer) new_container);
312 :
313 : /* Update the whole treatment container list + data interpretor window*/
314 0 : refresh_hex_datas_entry(main_window);
315 0 : }
316 :
317 : /**
318 : * Finds the container which contains the specified widget
319 : */
320 : static GList *find_treatment_container_from_widget(GList *container_list, GtkWidget *widget)
321 : {
322 0 : gboolean stop = FALSE;
323 0 : treatment_container_t *tment_c = NULL;
324 :
325 0 : while (container_list != NULL && stop == FALSE)
326 : {
327 0 : tment_c = (treatment_container_t *) container_list->data;
328 0 : if (tment_c->moins == widget || tment_c->tment_list == widget)
329 : {
330 0 : stop = TRUE;
331 : }
332 : else
333 : {
334 0 : container_list = g_list_next(container_list);
335 : }
336 : }
337 :
338 0 : return container_list;
339 : }
340 :
341 :
342 : /**
343 : * Removes a treatment container widget when (-) button is clicked
344 : */
345 : static void remove_treatment_container_widget(GtkWidget *widget, gpointer data)
346 0 : {
347 0 : heraia_window_t *main_window = (heraia_window_t *) data;
348 0 : data_type_t *a_data_type = NULL;
349 0 : treatment_container_t *tment_c = NULL;
350 0 : GList *list = NULL;
351 :
352 0 : a_data_type = main_window->current_data_type;
353 0 : list = find_treatment_container_from_widget(a_data_type->treatment_c_list, widget);
354 0 : if (list != NULL)
355 : {
356 0 : tment_c = (treatment_container_t *) list->data;
357 :
358 : /* Removes the container completely */
359 0 : destroy_container_widget(tment_c, TRUE);
360 :
361 : /* Removes the treatment container from the list */
362 0 : a_data_type->treatment_c_list = g_list_delete_link(a_data_type->treatment_c_list, list);
363 :
364 : /* Update the whole treatment container list + data interpretor window*/
365 0 : refresh_hex_datas_entry(main_window);
366 : }
367 0 : }
368 :
369 : /**
370 : * Updates the treatment_container list entries
371 : */
372 : static guchar *update_treatment_container_list_entries(GList *tment_c_list, GList *values_list)
373 : {
374 0 : treatment_container_t *tment_c = NULL;
375 0 : guchar *final = NULL;
376 :
377 0 : while (tment_c_list != NULL)
378 : {
379 0 : tment_c = (treatment_container_t *) tment_c_list->data;
380 :
381 0 : if (tment_c->treatment != NULL && tment_c->treatment->do_it != NULL)
382 : {
383 0 : values_list = tment_c->treatment->do_it(values_list);
384 0 : final = print_bin_to_hex(tment_c->result, values_list);
385 : }
386 :
387 0 : tment_c_list = g_list_next(tment_c_list);
388 : }
389 :
390 0 : return final;
391 : }
392 :
393 :
394 : /**
395 : * Called when a change is done in the treatment list combobox.
396 : * Affects the new treatment to the treatment_container.
397 : */
398 : static void cb_changed_in_treatment_container_widget(GtkWidget *widget, gpointer data)
399 0 : {
400 0 : heraia_window_t *main_window = (heraia_window_t *) data;
401 0 : data_type_t *a_data_type = NULL;
402 0 : treatment_container_t *tment_c = NULL;
403 0 : treatment_t *tment = NULL;
404 0 : gchar *tment_name = NULL;
405 0 : GList *list = NULL;
406 :
407 : /* Retreiving the treatment container concerned by the changed signal */
408 0 : a_data_type = main_window->current_data_type;
409 0 : list = find_treatment_container_from_widget(a_data_type->treatment_c_list, widget);
410 0 : if (list != NULL)
411 : {
412 0 : tment_c = (treatment_container_t *) list->data;
413 :
414 : /* Retrieving the treatment name selected */
415 0 : tment_name = gtk_combo_box_get_active_text(GTK_COMBO_BOX(tment_c->tment_list));
416 :
417 : /* Retrieves the treatment (with struct an such) from the treatment name */
418 0 : tment = find_treatment(main_window->available_treatment_list, tment_name);
419 :
420 0 : if (tment != NULL)
421 : {
422 : /* TODO : kill any previous treatment */
423 :
424 0 : tment_c->treatment = copy_treatment(tment);
425 :
426 : /* Update the whole treatment container list + data interpretor window*/
427 0 : refresh_hex_datas_entry(main_window);
428 : }
429 : }
430 0 : }
431 :
432 : /**
433 : * Creates new user defined widgets for the data interpretor window.
434 : */
435 : void create_ud_data_interpretor_widgets(heraia_window_t *main_window, data_type_t *a_data_type)
436 0 : {
437 0 : GtkWidget *vbox = NULL;
438 :
439 : /* Creates new widgets for the data interpretor window */
440 0 : a_data_type->di_label = gtk_label_new(NULL);
441 0 : gtk_misc_set_padding(GTK_MISC(a_data_type->di_label), 4, 4);
442 0 : gtk_misc_set_alignment(GTK_MISC(a_data_type->di_label), 0.5, 0.5);
443 :
444 0 : a_data_type->di_entry = gtk_entry_new();
445 :
446 0 : vbox = heraia_get_widget(main_window->xmls->main, "ud_type_vbox");
447 0 : gtk_box_pack_start(GTK_BOX(vbox), a_data_type->di_label, FALSE, FALSE, DT_BOX_PADDING);
448 :
449 0 : vbox = heraia_get_widget(main_window->xmls->main, "ud_value_vbox");
450 0 : gtk_box_pack_start(GTK_BOX(vbox), a_data_type->di_entry, FALSE, FALSE, DT_BOX_PADDING);
451 :
452 0 : gtk_widget_show(a_data_type->di_label);
453 0 : gtk_widget_show(a_data_type->di_entry);
454 0 : }
455 :
456 :
457 : /**
458 : * This constructs, fills and shows the data_type window
459 : * First I thought doing things with libglade here, but it seems
460 : * very hard. Same thing applies for GtkBuilder. I think I'll get
461 : * more flexibility with widgets created on the fly
462 : */
463 : void show_data_type_window(heraia_window_t *main_window, data_type_t *a_data_type)
464 0 : {
465 0 : treatment_container_t *new_container = NULL;
466 0 : GList *list = NULL;
467 :
468 : /* create all the treatment widgets */
469 0 : list = a_data_type->treatment_c_list;
470 :
471 0 : if (list == NULL) /* Creates only the first treatment_container */
472 : {
473 0 : log_message(main_window, G_LOG_LEVEL_DEBUG, "Creating a new treatment container");
474 :
475 : /* Creates a new empty treatment container */
476 0 : new_container = new_treatment_container(main_window);
477 :
478 : /* Create the last box that will contain one empty treatment container widget */
479 0 : create_treatment_container_widget(main_window, new_container);
480 :
481 : /* Append the container to the list */
482 0 : a_data_type->treatment_c_list = g_list_append(a_data_type->treatment_c_list, (gpointer) new_container);
483 : }
484 : else /* Create the widgets with all the treatments */
485 : {
486 0 : while (list != NULL)
487 : {
488 :
489 0 : new_container = (treatment_container_t *) list->data;
490 :
491 0 : log_message(main_window, G_LOG_LEVEL_DEBUG, "Creating a treatment container");
492 :
493 0 : create_treatment_container_widget(main_window, new_container);
494 0 : gtk_widget_show_all(new_container->container_box);
495 :
496 0 : list = g_list_next(list);
497 : }
498 : }
499 :
500 : /* fills widgets that are on top of the window (name, size and hexentry) */
501 0 : fill_data_type_widgets(main_window, a_data_type);
502 0 : set_spinbutton_max_range(main_window);
503 :
504 0 : gtk_widget_show_all(heraia_get_widget(main_window->xmls->main, "data_type_window"));
505 0 : }
506 :
507 :
508 : /**
509 : * Prints "length" "bin_datas" in an hexa form to the
510 : * entry widget named "widget_name"
511 : * TODO : add some specific representation options such
512 : * as space between characters
513 : */
514 : static guchar *print_bin_to_hex(GtkWidget *entry, GList *values_list)
515 0 : {
516 0 : guint i = 0;
517 0 : guchar *aux = NULL;
518 0 : guchar *hex = NULL;
519 0 : guchar *final = NULL;
520 0 : value_t *a_value = NULL;
521 :
522 0 : while (values_list != NULL)
523 : {
524 0 : a_value = (value_t *) values_list->data;
525 :
526 0 : aux = (guchar *) g_malloc0(sizeof(guchar) * 3);
527 0 : hex = (guchar *) g_malloc0(sizeof(guchar) * ((a_value->length * 2) + 1) );
528 :
529 0 : for(i = 0; i < a_value->length; i++)
530 : {
531 0 : sprintf((char *) aux, "%02x", a_value->bytes[i]);
532 0 : memcpy(hex+(i*2), aux, 2);
533 : }
534 :
535 0 : hex[i*2+1] = '\0';
536 0 : g_free(aux);
537 :
538 0 : if (final == NULL)
539 : {
540 0 : final = (guchar *) g_strdup((gchar *) hex);
541 : }
542 : else
543 : {
544 0 : aux = final;
545 0 : final = (guchar *) g_strconcat((gchar *) aux, " / ", (gchar *) hex);
546 0 : g_free(aux);
547 : }
548 :
549 0 : g_free(hex);
550 :
551 0 : values_list = g_list_next(values_list);
552 : }
553 :
554 0 : if (entry != NULL)
555 : {
556 0 : gtk_entry_set_text(GTK_ENTRY(entry), (gchar *) final);
557 : }
558 :
559 0 : return final;
560 : }
561 :
562 :
563 : /**
564 : * Refreshes one user defined data type when the cursor is moved
565 : * in the gtkhex structure.
566 : */
567 : static void refresh_one_ud_data_interpretor(data_type_t *a_data_type, value_t *a_value)
568 : {
569 0 : treatment_container_t *tment_c = NULL; /* one treatment container */
570 0 : GList *tment_c_list = NULL; /* treatment container list */
571 0 : guchar *final = NULL; /* final result */
572 0 : GList *values_list = NULL;
573 :
574 0 : values_list = g_list_append(values_list, (gpointer) a_value);
575 :
576 0 : if (a_data_type != NULL)
577 : {
578 0 : tment_c_list = a_data_type->treatment_c_list;
579 :
580 0 : while (tment_c_list != NULL)
581 : {
582 0 : tment_c = (treatment_container_t *) tment_c_list->data;
583 :
584 0 : if (tment_c->treatment != NULL && tment_c->treatment->do_it != NULL)
585 : {
586 0 : values_list = tment_c->treatment->do_it(values_list);
587 : }
588 :
589 0 : tment_c_list = g_list_next(tment_c_list);
590 : }
591 :
592 0 : final = print_bin_to_hex(a_data_type->di_entry, values_list);
593 0 : g_free(final);
594 : }
595 : }
596 :
597 :
598 : /**
599 : * Refreshes all the user data defined types (called when the cursor is moved)
600 : * Interpretation is done following the endianness 'endianness'
601 : */
602 : void refresh_all_ud_data_interpretor(heraia_window_t *main_window, guint endianness)
603 1 : {
604 1 : data_window_t *data_window = main_window->current_DW;
605 1 : value_t *a_value = NULL;
606 1 : guchar *bin_datas = NULL;
607 1 : GList *data_type_list = NULL;
608 1 : data_type_t *a_data_type = NULL;
609 1 : guint length = 0;
610 1 : gboolean result = FALSE;
611 1 : gchar *text = NULL;
612 :
613 1 : data_type_list = main_window->data_type_list;
614 :
615 2 : while (data_type_list != NULL)
616 : {
617 0 : a_data_type = (data_type_t *) data_type_list->data;
618 :
619 0 : if (a_data_type != NULL)
620 : {
621 0 : length = a_data_type->size;
622 0 : bin_datas = (guchar *) g_malloc0(sizeof(guchar) * length);
623 0 : result = ghex_get_data(data_window, length, endianness, bin_datas);
624 :
625 0 : if (result == TRUE)
626 : {
627 0 : a_value = new_value_t(length, bin_datas);
628 : refresh_one_ud_data_interpretor(a_data_type, a_value);
629 : }
630 : else
631 : {
632 0 : text = g_strdup_printf("Cannot copy %d bytes in order to interpret them !", length);
633 0 : gtk_entry_set_text(GTK_ENTRY(a_data_type->di_entry), text);
634 0 : g_free(text);
635 : }
636 0 : g_free(bin_datas);
637 : }
638 :
639 0 : data_type_list = g_list_next(data_type_list);
640 : }
641 :
642 1 : }
643 :
644 :
645 : /**
646 : * Refreshes the "hex_datas_entry" which displays
647 : * the hex datas extracted from the hexwidget at the
648 : * cursor position. Endianness is Little Endian for now,
649 : * we may, at a later time let the user choose its endianness
650 : * it also places the spin widget value in the current_data_type
651 : * structure.
652 : */
653 : void refresh_hex_datas_entry(heraia_window_t *main_window)
654 0 : {
655 0 : guchar *bin_datas = NULL;
656 0 : data_window_t *data_window = main_window->current_DW;
657 0 : guint length = 0;
658 0 : gboolean result = FALSE;
659 0 : GtkWidget *entry = NULL;
660 0 : value_t *a_value = NULL;
661 0 : GList *values_list = NULL;
662 0 : GList *tment_c_list = NULL;
663 0 : guchar *final = NULL;
664 :
665 0 : length = main_window->current_data_type->size;
666 :
667 0 : if (data_window->current_hexwidget != NULL)
668 : {
669 0 : bin_datas = (guchar *) g_malloc0(sizeof(guchar) * length);
670 0 : result = ghex_get_data(data_window, length, H_DI_LITTLE_ENDIAN, bin_datas);
671 :
672 0 : if (result == TRUE)
673 : {
674 0 : entry = heraia_get_widget(main_window->xmls->main, "hex_datas_entry");
675 0 : a_value = new_value_t(length, bin_datas);
676 0 : values_list = g_list_append(values_list, (gpointer) a_value);
677 :
678 0 : print_bin_to_hex(entry, values_list);
679 :
680 : /* Follows the others for the data_type beiing edited */
681 0 : tment_c_list = main_window->current_data_type->treatment_c_list;
682 0 : final = update_treatment_container_list_entries(tment_c_list, values_list);
683 :
684 : /* data interpretor part */
685 0 : if (final != NULL)
686 : {
687 0 : gtk_entry_set_text(GTK_ENTRY(main_window->current_data_type->di_entry), (gchar *) final);
688 : }
689 : }
690 :
691 0 : g_free(bin_datas);
692 : }
693 0 : }
694 :
695 :
696 : /**
697 : * Clears data_type window's widgets and sets to default
698 : * values. Currently UNUSED
699 : */
700 : /*
701 : void clear_data_type_widgets(heraia_window_t *main_window)
702 : {
703 : GtkEntry *entry = NULL;
704 : GtkSpinButton *size_spin_button = NULL;
705 : gdouble min = 0.0;
706 : gdouble max = 0.0;
707 :
708 : entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
709 : gtk_entry_set_text(entry, "");
710 :
711 : size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
712 : gtk_spin_button_get_range(size_spin_button, &min, &max);
713 : gtk_spin_button_set_value(size_spin_button, min);
714 :
715 : refresh_hex_datas_entry(main_window);
716 : }
717 : */
718 :
719 :
720 : /**
721 : * Fills the data_type window's widgets with values taken from the
722 : * data_type_list structure
723 : */
724 : void fill_data_type_widgets(heraia_window_t *main_window, data_type_t *a_data_type)
725 0 : {
726 0 : GtkEntry *entry = NULL;
727 0 : GtkSpinButton *size_spin_button = NULL;
728 0 : gdouble min = 0.0;
729 0 : gdouble max = 0.0;
730 :
731 : /* name */
732 0 : entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
733 0 : gtk_entry_set_text(entry, a_data_type->name);
734 :
735 : /* size */
736 0 : size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
737 0 : gtk_spin_button_get_range(size_spin_button, &min, &max);
738 :
739 0 : if (a_data_type->size >= min && a_data_type->size <= max)
740 : {
741 0 : gtk_spin_button_set_value(size_spin_button, a_data_type->size);
742 : }
743 : else
744 : {
745 0 : if (a_data_type->size > max)
746 : { /* May be we're close the end of a file */
747 0 : gtk_spin_button_set_value(size_spin_button, max);
748 : }
749 : else
750 : { /* Fallback case */
751 0 : gtk_spin_button_set_value(size_spin_button, max);
752 : }
753 : }
754 :
755 0 : refresh_hex_datas_entry(main_window);
756 0 : }
757 :
758 :
759 : /**
760 : * Says wether name "name" is already in use in "data_type_list" list
761 : * and returns NULL if not or the list that contains the data_type_t
762 : * where name was found
763 : */
764 : GList *is_data_type_name_already_used(GList *data_type_list, gchar *name)
765 0 : {
766 0 : gboolean result = FALSE;
767 0 : data_type_t *one_data_type = NULL;
768 :
769 0 : while (data_type_list != NULL && result == FALSE)
770 : {
771 0 : one_data_type = (data_type_t *) data_type_list->data;
772 :
773 0 : if (g_ascii_strcasecmp(name, one_data_type->name) == 0)
774 : {
775 0 : result = TRUE;
776 : }
777 : else
778 : {
779 0 : data_type_list = data_type_list->next;
780 : }
781 : }
782 :
783 0 : if (result == TRUE)
784 : {
785 0 : return data_type_list;
786 : }
787 : else
788 : {
789 0 : return NULL;
790 : }
791 : }
792 :
793 :
794 : /**
795 : * Called when the data type window is killed or closed
796 : */
797 : static gboolean delete_data_type_window_event(GtkWidget *widget, GdkEvent *event, gpointer data)
798 0 : {
799 0 : heraia_window_t *main_window = (heraia_window_t *) data;
800 :
801 0 : close_data_type_window(main_window);
802 :
803 0 : return TRUE;
804 : }
805 :
806 :
807 : /**
808 : * Called when the data type window is killed or closed
809 : */
810 : static void destroy_data_type_window(GtkWidget *widget, GdkEvent *event, gpointer data)
811 0 : {
812 0 : heraia_window_t *main_window = (heraia_window_t *) data;
813 :
814 0 : close_data_type_window(main_window);
815 0 : }
816 :
817 :
818 : /**
819 : * Retrieves informations from the data_type window widgets
820 : * Currently UNUSED
821 : */
822 : /*
823 : static data_type_t *retrieve_data_type_information(heraia_window_t *main_window)
824 : {
825 : GtkEntry *entry = NULL;
826 : gchar *name = NULL;
827 : gint size = 0;
828 : GtkSpinButton *size_spin_button = NULL;
829 :
830 : entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
831 : name = gtk_entry_get_text(entry);
832 :
833 : size_spin_button = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
834 : size = gtk_spin_button_get_value_as_int(size_spin_button);
835 :
836 : return new_data_type(name, size);
837 : }
838 : */
839 :
840 :
841 : /**
842 : * Destroys a container Widget.
843 : * If all is true it destroys everything even the treatment and such.
844 : * If all is false it destroys only the widget part.
845 : */
846 : static void destroy_container_widget(treatment_container_t *tment_c, gboolean all)
847 0 : {
848 0 : if (tment_c != NULL)
849 : {
850 0 : destroy_a_single_widget(tment_c->plus);
851 0 : tment_c->plus = NULL;
852 :
853 0 : destroy_a_single_widget(tment_c->moins);
854 0 : tment_c->moins = NULL;
855 :
856 0 : destroy_a_single_widget(tment_c->result);
857 0 : tment_c->result = NULL;
858 :
859 0 : destroy_a_single_widget(tment_c->tment_list);
860 0 : tment_c->tment_list = NULL;
861 :
862 0 : destroy_a_single_widget(tment_c->button_box);
863 0 : tment_c->button_box = NULL;
864 :
865 0 : destroy_a_single_widget(tment_c->combo_box);
866 0 : tment_c->combo_box = NULL;
867 :
868 0 : destroy_a_single_widget(tment_c->container_box);
869 0 : tment_c->container_box = NULL;
870 :
871 0 : if (all == TRUE)
872 : {
873 :
874 0 : if (tment_c->treatment != NULL && tment_c->treatment->kill != NULL)
875 : {
876 0 : tment_c->treatment->kill(tment_c->treatment); /* erases itself */
877 : }
878 :
879 0 : g_free(tment_c);
880 : }
881 : }
882 0 : }
883 :
884 : /**
885 : * Called when the data_type_window is closed
886 : */
887 : static void close_data_type_window(heraia_window_t *main_window)
888 0 : {
889 0 : data_type_t *a_data_type = NULL; /* data type currently in use */
890 0 : GList *list = NULL;
891 :
892 : /* Current data type beeing edited */
893 0 : a_data_type = main_window->current_data_type;
894 :
895 : /* Current treatment container list for this data type */
896 0 : list = a_data_type->treatment_c_list;
897 :
898 : /* Destroys all widgets associated with the treatment container list */
899 : /* This does not destroys the list itself here */
900 0 : while (list != NULL)
901 : {
902 0 : destroy_container_widget((treatment_container_t *)list->data, FALSE);
903 0 : list = g_list_next(list);
904 : }
905 :
906 : /** Last box stuff : I do not know if this is really usefull !! */
907 : /* Destroys the last widget (which should never contain any treatment) */
908 : /* list = g_list_last(a_data_type->treatment_c_list); */
909 : /* if (list != NULL) */
910 : /* { */
911 : /* destroy_container_widget((treatment_container_t *)list->data, TRUE); */
912 : /* a_data_type->treatment_c_list = g_list_delete_link(a_data_type->treatment_c_list, list); */
913 : /* } */
914 :
915 : /* Hiding the window */
916 0 : gtk_widget_hide(heraia_get_widget(main_window->xmls->main, "data_type_window"));
917 0 : }
918 :
919 : /**
920 : * The user clicks "Ok" button
921 : */
922 : static void dt_ok_button_clicked(GtkWidget *widget, gpointer data)
923 0 : {
924 0 : heraia_window_t *main_window = (heraia_window_t *) data;
925 0 : data_type_t *a_data_type = NULL;
926 0 : GList *data_type_list = NULL;
927 :
928 0 : a_data_type = main_window->current_data_type;
929 :
930 0 : if (g_ascii_strcasecmp(a_data_type->name, "") != 0)
931 : {
932 0 : data_type_list = is_data_type_name_already_used(main_window->data_type_list, a_data_type->name);
933 :
934 0 : if (data_type_list == NULL)
935 : {
936 : /**
937 : * The name does not exists, we want to add it to the treeview and to the
938 : * list structure (the user clicked add(+) in the list window or edited the name)
939 : */
940 0 : log_message(main_window, G_LOG_LEVEL_DEBUG, "Adding %s data type name to treeview", a_data_type->name);
941 0 : add_data_type_name_to_treeview(main_window, a_data_type->name);
942 :
943 : /* data interpretor part */
944 0 : gtk_label_set_text(GTK_LABEL(a_data_type->di_label), a_data_type->name);
945 :
946 0 : main_window->data_type_list = g_list_prepend(main_window->data_type_list, a_data_type);
947 : }
948 : else
949 : {
950 : /**
951 : * The name is already in use, we assume that we are in editing mode
952 : * and we simply replace the old data_type_t structure by the new one !
953 : */
954 0 : log_message(main_window, G_LOG_LEVEL_DEBUG, "Editing mode (%s exists)", a_data_type->name);
955 :
956 : /* We kill the old widget's that are unsefull (we replace them) */
957 0 : destroy_a_single_widget(main_window->current_data_type->di_label);
958 0 : destroy_a_single_widget(main_window->current_data_type->di_entry);
959 0 : destroy_a_single_widget(((data_type_t *)data_type_list->data)->di_label);
960 0 : destroy_a_single_widget(((data_type_t *)data_type_list->data)->di_entry);
961 :
962 0 : free_data_type((data_type_t *)data_type_list->data);
963 0 : create_ud_data_interpretor_widgets(main_window, a_data_type);
964 :
965 : /* data interpretor part */
966 0 : gtk_label_set_text(GTK_LABEL(a_data_type->di_label), a_data_type->name);
967 :
968 0 : data_type_list->data = a_data_type;
969 : }
970 :
971 0 : refresh_hex_datas_entry(main_window);
972 :
973 0 : close_data_type_window(main_window);
974 : }
975 0 : }
976 :
977 :
978 : /**
979 : * The user clicks "Cancel" button
980 : */
981 : static void dt_cancel_button_clicked(GtkWidget *widget, gpointer data)
982 0 : {
983 0 : heraia_window_t *main_window = (heraia_window_t *) data;
984 0 : data_type_t *a_data_type = NULL;
985 :
986 0 : a_data_type = main_window->current_data_type;
987 :
988 : /* the data interpretor part */
989 0 : destroy_a_single_widget(a_data_type->di_label);
990 0 : destroy_a_single_widget(a_data_type->di_entry);
991 :
992 0 : close_data_type_window(main_window);
993 0 : }
994 :
995 :
996 : /**
997 : * When the user changes the size of the data that will
998 : * be used to construct a new type
999 : */
1000 : static void dt_size_spinbutton_value_changed(GtkWidget *widget, gpointer data)
1001 0 : {
1002 0 : heraia_window_t *main_window = (heraia_window_t *) data;
1003 0 : GtkSpinButton *dt_size_spinbutton = GTK_SPIN_BUTTON(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton"));
1004 0 : guint length = 0;
1005 :
1006 0 : if (main_window != NULL)
1007 : {
1008 :
1009 0 : length = gtk_spin_button_get_value_as_int(dt_size_spinbutton);
1010 :
1011 0 : if (length >= DT_SPIN_MIN && length <= DT_SPIN_MAX)
1012 : {
1013 0 : if (main_window->current_data_type != NULL)
1014 : {
1015 0 : main_window->current_data_type->size = length;
1016 : }
1017 : }
1018 :
1019 0 : refresh_hex_datas_entry(main_window);
1020 : }
1021 0 : }
1022 :
1023 :
1024 : /**
1025 : * When the user leaves the name entry
1026 : * Gets the name entry if any and puts it in the current_data_type
1027 : * structure.
1028 : */
1029 : static void dt_name_entry_leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
1030 0 : {
1031 0 : heraia_window_t *main_window = (heraia_window_t *) data;
1032 0 : GtkEntry *entry = NULL;
1033 :
1034 0 : if (main_window != NULL && main_window->current_data_type != NULL)
1035 : {
1036 0 : entry = GTK_ENTRY(heraia_get_widget(main_window->xmls->main, "dt_name_entry"));
1037 :
1038 0 : if (main_window->current_data_type->name != NULL)
1039 : {
1040 0 : g_free(main_window->current_data_type->name);
1041 : }
1042 :
1043 0 : main_window->current_data_type->name = g_strdup(gtk_entry_get_text(entry));
1044 :
1045 : }
1046 0 : }
1047 :
1048 :
1049 :
1050 : /**
1051 : * Connects data_type's window signals.
1052 : */
1053 : static void connect_data_type_signals(heraia_window_t *main_window)
1054 1 : {
1055 :
1056 1 : if (main_window != NULL && main_window->xmls != NULL && main_window->xmls->main != NULL)
1057 : {
1058 : /* data type window killed or destroyed */
1059 1 : g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "data_type_window")), "delete_event",
1060 : G_CALLBACK(delete_data_type_window_event), main_window);
1061 :
1062 1 : g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "data_type_window")), "destroy",
1063 : G_CALLBACK(destroy_data_type_window), main_window);
1064 :
1065 : /* Ok button */
1066 1 : g_signal_connect (G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_ok_button")), "clicked",
1067 : G_CALLBACK(dt_ok_button_clicked), main_window);
1068 :
1069 : /* Cancel button */
1070 1 : g_signal_connect (G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_cancel_button")), "clicked",
1071 : G_CALLBACK(dt_cancel_button_clicked), main_window);
1072 :
1073 : /* When the size spinbutton changes its value */
1074 1 : g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_size_spinbutton")), "value-changed",
1075 : G_CALLBACK(dt_size_spinbutton_value_changed), main_window);
1076 :
1077 : /* When the user leaves the name entry */
1078 1 : g_signal_connect(G_OBJECT(heraia_get_widget(main_window->xmls->main, "dt_name_entry")), "leave-notify-event",
1079 : G_CALLBACK(dt_name_entry_leave_notify_event), main_window);
1080 :
1081 : }
1082 1 : }
1083 :
1084 :
1085 : /**
1086 : * Inits the data type window with default values
1087 : * Should be called only once
1088 : * Here we may load a specific file where the user
1089 : * data types are saved
1090 : */
1091 : void data_type_init_interface(heraia_window_t *main_window)
1092 1 : {
1093 1 : if (main_window != NULL)
1094 : {
1095 1 : connect_data_type_signals(main_window);
1096 : }
1097 1 : }
|