result_window.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003   result_window.c
00004   result_window.c - A window that will collect all results of functions such as
00005                     find, find a data from type, ...
00006 
00007   (C) Copyright 2010 Olivier Delhomme
00008   e-mail : heraia@delhomme.org
00009   URL    : http://heraia.tuxfamily.org
00010 
00011   This program is free software; you can redistribute it and/or modify
00012   it under the terms of the GNU General Public License as published by
00013   the Free Software Foundation; either version 2, or  (at your option)
00014   any later version.
00015 
00016   This program is distributed in the hope that it will be useful,
00017   but WITHOUT ANY WARRANTY;  without even the implied warranty of
00018   MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00019   GNU General Public License for more details.
00020 
00021   You should have received a copy of the GNU General Public License
00022   along with this program; if not, write to the Free Software
00023   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00024 */
00025 /**
00026  * @file result_window.c
00027  *  Manage results coming from functions such as find, find a data from type,
00028  *  and so on.
00029  */
00030 #include <libheraia.h>
00031 
00032 static gboolean delete_result_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data);
00033 static void destroy_result_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data);
00034 static void result_window_close(GtkWidget *widget, gpointer data);
00035 static void result_window_connect_signal(heraia_struct_t *main_struct);
00036 
00037 static void tree_selection_changed(GtkTreeSelection *selection, gpointer data);
00038 static void rw_on_close_activate(GtkWidget *widget, gpointer data);
00039 
00040 static void determine_pos_and_buffer_size(guint64 *pos, guint *buffer_size, guint size, guint64 file_size);
00041 static void add_gtk_tree_view_to_result_notebook(heraia_struct_t *main_struct, GtkListStore *lstore, guchar *label_text, doc_t *doc);
00042 
00043 static void menu_result_toggle(GtkWidget *widget, gpointer data);
00044 
00045 
00046 /**
00047  * Show result window
00048  * @param widget : the widget that issued the signal (may be NULL as we do not
00049  *                 use it).
00050  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00051  */
00052 void result_window_show(GtkWidget *widget, gpointer data)
00053 {
00054     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00055     GtkWidget *window = NULL;      /**< result window itself */
00056 
00057     if (main_struct != NULL && main_struct->current_doc != NULL)
00058         {
00059             window = heraia_get_widget(main_struct->xmls->main, "result_window");
00060             move_and_show_dialog_box(window, main_struct->win_prop->result_window);
00061             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(heraia_get_widget(main_struct->xmls->main, "menu_result")), TRUE);
00062         }
00063 }
00064 
00065 
00066 /**
00067  * Inits all the things in the result window (signal and such)
00068  * @param main_struct : heraia's main structure
00069  */
00070 void result_window_init_interface(heraia_struct_t *main_struct)
00071 {
00072     if (main_struct != NULL && main_struct->xmls != NULL && main_struct->xmls->main != NULL)
00073         {
00074             result_window_connect_signal(main_struct);
00075         }
00076 }
00077 
00078 
00079 /**
00080  * Call back function for the result window destruction
00081  * @param widget : calling widget (may be NULL as we don't use this here)
00082  * @param event : event associated (may be NULL as we don't use this here)
00083  * @param data :  MUST be heraia_struct_t *main_struct main structure
00084  */
00085 static gboolean delete_result_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00086 {
00087     result_window_close(widget, data);
00088 
00089     return TRUE;
00090 }
00091 
00092 
00093 /**
00094  * Call back function for the result window destruction
00095  * @param widget : calling widget (may be NULL as we don't use this here)
00096  * @param event : event associated (may be NULL as we don't use this here)
00097  * @param data : user data - MUST be heraia_struct_t *main_struct main structure and not NULL
00098  */
00099 static void destroy_result_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00100 {
00101     result_window_close(widget, data);
00102 }
00103 
00104 
00105 /**
00106  * Close button has been clicked we want to hide the window
00107  * @param widget : calling widget
00108  * @param data : MUST be heraia_struct_t *main_struct main structure and not NULL
00109  */
00110 static void result_window_close(GtkWidget *widget, gpointer data)
00111 {
00112     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00113     GtkWidget *window = NULL;      /**< result window itself */
00114 
00115     if (main_struct != NULL)
00116         {
00117              window = heraia_get_widget(main_struct->xmls->main, "result_window");
00118              record_and_hide_dialog_box(window, main_struct->win_prop->result_window);
00119              gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(heraia_get_widget(main_struct->xmls->main, "menu_result")), FALSE);
00120         }
00121 }
00122 
00123 
00124 /**
00125  * Function called upon selection change. Changes the cursor position to the
00126  * right place (should also change to the right document).
00127  * @param selection : the selection that changed
00128  * @param data : user data MUST be main program's structure
00129  */
00130 static void tree_selection_changed(GtkTreeSelection *selection, gpointer data)
00131 {
00132     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00133     GtkTreeIter iter;
00134     GtkTreeModel *model = NULL;
00135     GtkWidget *result_notebook = NULL;
00136     guint64 a_pos = 0;
00137     gint index = 0;
00138     doc_t *the_doc = NULL;
00139 
00140     if (main_struct != NULL && main_struct->xmls != NULL && main_struct->xmls->main != NULL)
00141         {
00142             result_notebook = heraia_get_widget(main_struct->xmls->main, "result_notebook");
00143 
00144             if (gtk_tree_selection_get_selected(selection, &model, &iter))
00145                 {
00146                     gtk_tree_model_get(model, &iter, R_LS_POS, &a_pos, -1);
00147                     index = gtk_notebook_get_current_page(GTK_NOTEBOOK(result_notebook));
00148                     the_doc = g_ptr_array_index(main_struct->results, index);
00149                     log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("Search result index : %d "), index);
00150 
00151                     if (the_doc != NULL)
00152                         {
00153                             /* Change file's notebook tab in main window to display the_doc document if it is possible */
00154                             ghex_set_cursor_position(the_doc->hex_widget, a_pos - 1);
00155                         }
00156                 }
00157         }
00158 }
00159 
00160 
00161 /**
00162  * Calculates the position and the associated buffer size in order that the text
00163  * searched for will be centered in the results
00164  * @param pos : Must be the position of the searched text, is returned as the
00165  *              position where we will extract the text
00166  * @param buffer_size : is returned as the total buffer size (the extracted text
00167  *                      will be buffer_size + 1 in size)
00168  * @param size : size of the string searched for (in bytes)
00169  * @param file_size : size of the file (to verify that we are still in the
00170  *                    limits
00171  */
00172 static void determine_pos_and_buffer_size(guint64 *pos, guint *buffer_size, guint size, guint64 file_size)
00173 {
00174     guint64 a_pos = 0;
00175     guint a_buf_size = 0;
00176     gint gap = 0;
00177 
00178     a_pos = *pos;
00179     a_buf_size = *buffer_size;
00180 
00181     if ((a_pos + a_buf_size) > file_size)
00182         {
00183             gap = file_size - a_pos - size;
00184             if (gap < 0)
00185                 {
00186                     gap = 0;
00187                 }
00188             else if (gap > 4)
00189                     {
00190                         gap = 4;
00191                     }
00192             a_pos = a_pos - gap;
00193             a_buf_size = (2 * gap) + size;
00194         }
00195     else
00196         {
00197             if (a_pos >= 4)
00198                 {
00199                     a_pos = a_pos - 4;
00200                     a_buf_size = 8 + size; /* we want to have 4 bytes before and 4 bytes after the result to be displayed */
00201                 }
00202             else
00203                 {
00204                     a_buf_size = (2 * a_pos) + size;
00205                     a_pos = 0;
00206                 }
00207         }
00208 
00209     *pos = a_pos;
00210     *buffer_size = a_buf_size;
00211 }
00212 
00213 
00214 /**
00215  * Closes a result tab
00216  * @param widget : the widget that issued the signal
00217  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00218  */
00219 static void rw_on_close_activate(GtkWidget *widget, gpointer data)
00220 {
00221     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00222     GtkWidget *notebook = NULL;  /**< result_notebook from heraia.gtkbuilder     */
00223     gint tab_number = 0;         /**< index of the tab (and thus from the array) */
00224 
00225     tab_number = find_tab_number_from_widget(main_struct, "result_notebook", widget);
00226 
00227     /* Removing the index in the array */
00228     g_ptr_array_remove_index(main_struct->results, tab_number);
00229 
00230     /* And removing it in the notebook */
00231     notebook = heraia_get_widget(main_struct->xmls->main, "result_notebook");
00232     gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), tab_number);
00233 }
00234 
00235 
00236 /**
00237  * Add one tab to the result window's notebook with a gtk_tree_view in it
00238  * @param main_struct : main structure of heraia
00239  * @param lstore : the populated list store (for the tree view)
00240  * @param label_text : the text for the label of the tab
00241  * @param doc : the document from which the search was done
00242  */
00243 static void add_gtk_tree_view_to_result_notebook(heraia_struct_t *main_struct, GtkListStore *lstore, guchar *label_text, doc_t *doc)
00244 {
00245     GtkWidget *vbox = NULL;           /**< used for vbox creation                      */
00246     GtkWidget *scrolledw = NULL;      /**< the scrolled window                         */
00247     GtkWidget *notebook = NULL;       /**< result_notebook from heraia.gtkbuilder      */
00248     GtkWidget *tview = NULL;          /**< the tree view                               */
00249     GtkWidget *tab_label = NULL;      /**< tab's label                                 */
00250     GtkWidget *hbox = NULL;           /**< the hbox that will receive the close button */
00251     GtkCellRenderer *renderer = NULL; /**< a rennderer for the cells                   */
00252     GtkTreeViewColumn *column = NULL; /**< columns to be added to the treeview         */
00253     GtkTreeSelection *select = NULL;  /**< selection to the treeview                   */
00254     gint tab_num = -1;                /**< new tab's index                             */
00255     gchar *markup = NULL;             /**< markup text                                 */
00256     gchar *menu_markup = NULL;        /**< menu markup text (menu in the notebook)     */
00257     GtkWidget *menu_label = NULL;     /**<menu's label (notebook's menu)               */
00258     gchar *whole_filename = NULL;     /**< filename of the document from where the
00259                                            search took place                           */
00260 
00261     notebook = heraia_get_widget(main_struct->xmls->main, "result_notebook");
00262     vbox = gtk_vbox_new(FALSE, 2);
00263     scrolledw = gtk_scrolled_window_new(NULL, NULL);
00264     tview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(lstore));
00265     gtk_box_pack_start(GTK_BOX(vbox), scrolledw, TRUE, TRUE, 0);
00266     gtk_container_add(GTK_CONTAINER(scrolledw), tview);
00267 
00268     g_object_unref(lstore);
00269 
00270     /* Column Number (1....21321) the number of columns */
00271     renderer = gtk_cell_renderer_text_new();
00272     column = gtk_tree_view_column_new_with_attributes(Q_("Number"), renderer, "text", R_LS_N, NULL);
00273     gtk_tree_view_append_column(GTK_TREE_VIEW(tview), column);
00274 
00275     /* Column Position (23, 545, 879, 1324, ...) the positions of the text found */
00276     renderer = gtk_cell_renderer_text_new();
00277     column = gtk_tree_view_column_new_with_attributes(Q_("Position"), renderer, "text", R_LS_POS, NULL);
00278     gtk_tree_view_append_column(GTK_TREE_VIEW(tview), column);
00279 
00280     /* Column Hex : Hexadecimal text as found in the file */
00281     renderer = gtk_cell_renderer_text_new();
00282     column = gtk_tree_view_column_new_with_attributes(Q_("Hex"), renderer, "text", R_LS_HEX, NULL);
00283     gtk_tree_view_append_column(GTK_TREE_VIEW(tview), column);
00284 
00285     /* Column Ascii : Normal text found in the file (if printable) */
00286     renderer = gtk_cell_renderer_text_new();
00287     column = gtk_tree_view_column_new_with_attributes(Q_("Ascii"), renderer, "text", R_LS_ASCII, NULL);
00288     gtk_tree_view_append_column(GTK_TREE_VIEW(tview), column);
00289 
00290     /* Signal handling */
00291     select = gtk_tree_view_get_selection(GTK_TREE_VIEW(tview));
00292     gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
00293     g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(tree_selection_changed), main_struct);
00294 
00295 
00296     /* tab's label, menu label and tooltips */
00297     if (label_text != NULL)
00298         {
00299             tab_label = gtk_label_new(NULL);
00300             markup = g_markup_printf_escaped("%s", label_text);
00301             gtk_label_set_markup(GTK_LABEL(tab_label), markup);
00302 
00303             menu_label = gtk_label_new(NULL);
00304             menu_markup = g_markup_printf_escaped("%s", label_text);
00305             gtk_label_set_markup(GTK_LABEL(menu_label), menu_markup);
00306             gtk_label_set_justify(GTK_LABEL(menu_label), GTK_JUSTIFY_LEFT);
00307 
00308             whole_filename = doc_t_document_get_filename(doc);
00309             gtk_widget_set_tooltip_text(tab_label, g_filename_display_name(whole_filename));
00310 
00311             g_free(markup);
00312             g_free(menu_markup);
00313         }
00314 
00315     /* Creating the close button */
00316     hbox = create_tab_close_button(main_struct, tab_label, rw_on_close_activate);
00317 
00318     gtk_widget_show_all(vbox);
00319     tab_num = gtk_notebook_append_page_menu(GTK_NOTEBOOK(notebook), vbox, hbox, menu_label);
00320 
00321     gtk_widget_show_all(notebook);
00322 }
00323 
00324 
00325 /**
00326  * Add one tab for the results from the find all button
00327  * @param main_struct : main structure of heraia
00328  * @param all_pos : A GArray of all found positions
00329  * @param size : size of the string searched for (in bytes)
00330  */
00331 void rw_add_one_tab_from_find_all_bt(heraia_struct_t *main_struct, GArray *all_pos, guint size)
00332 {
00333     GtkListStore *lstore =  NULL;     /**< List store that will contain results                    */
00334     guint i = 0;
00335     guint64 pos = 0;                  /**< a calculated position to center the search string       */
00336     guint64 real_pos = 0;             /**< real position                                           */
00337     guint64 file_size = 0 ;           /**< size of the file  during the search (should not change) */
00338     doc_t *current_doc = NULL;        /**< Current document on which we want to do the search      */
00339     gint endianness = LITTLE_ENDIAN;  /**< endianness as selected in the data interpretor window   */
00340     guint buffer_size = 0;             /**< buffer size (bigger than size in order to display      */
00341                                       /**  some byte before and after the results)                 */
00342     guchar *ascii_buffer = NULL;      /**< the ascii buffer                                        */
00343     guchar *hex_buffer = NULL;        /**< the hex buffer                                          */
00344     GtkTreeIter iter;
00345     guchar *label_text = NULL;        /**< text label                                              */
00346 
00347 
00348     current_doc = main_struct->current_doc;
00349     g_ptr_array_add(main_struct->results, current_doc);
00350 
00351     endianness = LITTLE_ENDIAN; /** Endianness by default (we want the search to be flat) -> However this may
00352                                     be modified if someone asks for */
00353     file_size = ghex_file_size(GTK_HEX(current_doc->hex_widget));
00354 
00355     /* The columns :  R_LS_N (G_TYPE_UINT), R_LS_POS (G_TYPE_UINT64), R_LS_HEX (G_TYPE_STRING), R_LS_ASCII (G_TYPE_STRING) */
00356     lstore = gtk_list_store_new(R_LS_N_COLUMNS, G_TYPE_UINT, G_TYPE_UINT64, G_TYPE_STRING, G_TYPE_STRING);
00357 
00358     for (i = 0; i < all_pos->len; i++)
00359         {
00360             pos = g_array_index(all_pos, guint64, i);
00361             real_pos = pos;
00362 
00363             determine_pos_and_buffer_size(&pos, &buffer_size, size, file_size);
00364 
00365             ascii_buffer = ghex_get_data_to_ascii(current_doc->hex_widget, pos, buffer_size, endianness);
00366             hex_buffer = ghex_get_data_to_hex(current_doc->hex_widget, pos, buffer_size, endianness);
00367 
00368             if (ascii_buffer != NULL && hex_buffer != NULL)
00369                 {
00370                     gtk_list_store_append(lstore, &iter);
00371                     gtk_list_store_set(lstore, &iter, R_LS_N, i + 1, R_LS_POS, real_pos + 1, R_LS_HEX, hex_buffer, R_LS_ASCII, ascii_buffer, -1);
00372 
00373                     log_message(main_struct, G_LOG_LEVEL_DEBUG, "%lld : %d, %s - %s", pos, buffer_size, ascii_buffer, hex_buffer);
00374 
00375                     g_free(ascii_buffer);
00376                     g_free(hex_buffer);
00377                 }
00378         }
00379 
00380     /* Using last pos to retrieve the text for the label */
00381     label_text = ghex_get_data_to_ascii(current_doc->hex_widget, real_pos, size, endianness);
00382 
00383     add_gtk_tree_view_to_result_notebook(main_struct, lstore, label_text, current_doc);
00384 
00385     result_window_show(NULL, main_struct);
00386 }
00387 
00388 
00389 /**
00390  *  The Check menu item for the result window
00391  * @param widget : the widget that issued the signal (here the menu_result check
00392  *                 menu item
00393  * @param data : user data, MUST be main_struct main structure
00394  */
00395 static void menu_result_toggle(GtkWidget *widget, gpointer data)
00396 {
00397     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00398     GtkCheckMenuItem *cmi = GTK_CHECK_MENU_ITEM(widget);
00399     gboolean checked = gtk_check_menu_item_get_active(cmi);
00400 
00401     if (checked == TRUE)
00402         {
00403             result_window_show(widget, data);
00404         }
00405     else
00406         {
00407              result_window_close(widget, data);
00408         }
00409 }
00410 
00411 
00412 /**
00413  * Signal connections for the result window
00414  * @param main_struct : heraia's main structure
00415  */
00416 static void result_window_connect_signal(heraia_struct_t *main_struct)
00417 {
00418     /* Close button */
00419     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "rw_close_bt")), "clicked",
00420                      G_CALLBACK(result_window_close), main_struct);
00421 
00422     /* When result window is killed or destroyed */
00423     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "result_window")), "delete_event",
00424                      G_CALLBACK(delete_result_window_event), main_struct);
00425 
00426     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "result_window")), "destroy",
00427                      G_CALLBACK(destroy_result_window_event), main_struct);
00428 
00429     /* The toogle button in the main menu*/
00430     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "menu_result")), "toggled",
00431                      G_CALLBACK(menu_result_toggle), main_struct);
00432 }
00433 
00434 
00435 /**
00436  * Remove all tabs from the result window that correspond to the specified
00437  * document.
00438  * @param main_struct : heraia's main structure
00439  * @param doc : the document beeing close in main window's notebook
00440  */
00441 void rw_remove_all_tabs(heraia_struct_t *main_struct, doc_t *doc)
00442 {
00443     gint i = 0;
00444     gint len = 0;               /**< total len of result array                   */
00445     GtkWidget *notebook = NULL; /**< result_notebook from heraia.gtkbuilder      */
00446     doc_t *value = NULL;        /**< Value to compare with doc                   */
00447     GArray *array = NULL;       /**< array that stores the indexes where results
00448                                      value is equal to doc.                      */
00449 
00450     if (main_struct != NULL && main_struct->results != NULL)
00451         {
00452             notebook = heraia_get_widget(main_struct->xmls->main, "result_notebook");
00453 
00454             array = g_array_new(TRUE, TRUE, sizeof(gint));
00455 
00456             len = main_struct->results->len;
00457 
00458             /* looking for the results */
00459             i = 0;
00460             while (i < len)
00461                 {
00462                     value = g_ptr_array_index(main_struct->results, i);
00463 
00464                     if (value == doc)
00465                         {
00466                             log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("Removing index %d."), i);
00467                             g_ptr_array_remove_index(main_struct->results, i);
00468                             gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), i);
00469                             len = main_struct->results->len;
00470                         }
00471                     else
00472                         {
00473                             i = i + 1;
00474                         }
00475                 }
00476         }
00477 }
Generated on Sat Oct 30 18:31:55 2010 for Heraia by  doxygen 1.6.3