00001 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */ 00002 /* 00003 ghex_heraia_interface.c 00004 heraia - an hexadecimal file editor and analyser based on ghex 00005 00006 (C) Copyright 2005 - 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 * @file ghex_heraia_interface.c 00025 * An interface to the ghex library -> this adds an abstract layer. 00026 */ 00027 #include <libheraia.h> 00028 00029 /** 00030 * @fn HERAIA_ERROR heraia_hex_document_new(heraia_window_t *main_window, char *filename) 00031 * Removes the old document if it exists and adds a new one 00032 * from the filename 'filename' 00033 * @param main_window : main structure 00034 * @param filename : a char * representing an existing file named "filename" 00035 * @return Always returns HERAIA_NOERR; @todo : do something to take errors into 00036 * account 00037 */ 00038 doc_t *heraia_hex_document_new(heraia_window_t *main_window, char *filename) 00039 { 00040 Heraia_Document *hex_doc = NULL; 00041 GtkWidget *hex_widget = NULL; 00042 doc_t *doc = NULL; 00043 00044 /* There is no more reasons that we destroy any documents here */ 00045 /* if (main_window->current_doc != NULL) 00046 { 00047 hex_document_remove_view(main_window->current_doc, main_window->current_DW->current_hexwidget); 00048 } 00049 00050 if (main_window->current_DW->current_hexwidget != NULL ) 00051 { 00052 gtk_widget_destroy(main_window->current_DW->current_hexwidget); 00053 } 00054 */ 00055 00056 /* Creating a new hex document */ 00057 hex_doc = hex_document_new_from_file(filename); 00058 00059 if (hex_doc != NULL) 00060 { 00061 /* creating a new view to this new document */ 00062 hex_widget = hex_document_add_view(hex_doc); 00063 00064 /* joining those two new structures in one */ 00065 doc = new_doc_t(hex_doc, hex_widget); 00066 00067 /* Adding this new doc to the list of docs (here a GPtrArray) */ 00068 g_ptr_array_add(main_window->documents, doc); 00069 00070 /* signal connection on cursor moves */ 00071 connect_cursor_moved_signal(main_window, hex_widget); 00072 00073 return doc; 00074 } 00075 else 00076 { 00077 return NULL; 00078 } 00079 } 00080 00081 00082 /** 00083 * Retrieves the filename of a document which ever it is ! 00084 * @param doc : an Heraia_Document 00085 * @return returns the filename of that document. 00086 */ 00087 gchar *heraia_hex_document_get_filename(Heraia_Document *hex_doc) 00088 { 00089 if (hex_doc != NULL) 00090 { 00091 return hex_doc->file_name; 00092 } 00093 else 00094 { 00095 return NULL; 00096 } 00097 } 00098 00099 /** 00100 * Retrieves from a doc_t * document it's filename, which ever it is 00101 * @param doc : an existing doc_t 00102 * @return returns the filename of that document. 00103 */ 00104 gchar *doc_t_document_get_filename(doc_t *doc) 00105 { 00106 if (doc != NULL) 00107 { 00108 return heraia_hex_document_get_filename(doc->hex_doc); 00109 } 00110 else 00111 { 00112 return NULL; 00113 } 00114 } 00115 00116 00117 00118 /** 00119 * @fn HERAIA_ERROR heraia_hex_document_save(heraia_window_t *main_window) 00120 * Saves an open and edited document 00121 * @param main_window : main structure, @todo may be we only need main_window->current_doc here 00122 * @return returns HERAIA_NOERR if everything went ok or HERAIA_FILE_ERROR in case of an error 00123 */ 00124 HERAIA_ERROR heraia_hex_document_save(heraia_window_t *main_window) 00125 { 00126 gint return_value = FALSE; 00127 00128 if (main_window->current_doc != NULL) 00129 { 00130 if (main_window->current_doc->hex_doc != NULL) 00131 { 00132 return_value = hex_document_write(main_window->current_doc->hex_doc); 00133 } 00134 } 00135 00136 if (return_value != FALSE) 00137 { 00138 return HERAIA_NOERR; 00139 } 00140 else 00141 { 00142 return HERAIA_FILE_ERROR; 00143 } 00144 } 00145 00146 /** 00147 * Saves an opened and edited document to a new file 00148 * @param main_window : main structure 00149 * @param filename : the new filename where to save the file 00150 * @return returns HERAIA_NOERR if everything went ok or HERAIA_FILE_ERROR in case of an error 00151 */ 00152 HERAIA_ERROR heraia_hex_document_save_as(heraia_window_t *main_window, gchar *filename) 00153 { 00154 gint return_value = FALSE; 00155 FILE *fp = NULL; 00156 gint i = 0; 00157 gchar *path_end = NULL; /**< to make libghex happy ! */ 00158 00159 if (main_window->current_doc != NULL && main_window->current_doc->hex_doc != NULL && filename != NULL) 00160 { 00161 fp = fopen(filename, "w"); 00162 if (fp != NULL) 00163 { 00164 return_value = hex_document_write_to_file(main_window->current_doc->hex_doc, fp); 00165 fclose(fp); 00166 00167 /* This may not be necessary any more as we have separated docs 00168 if (main_window->current_doc->file_name) 00169 { 00170 g_free(main_window->current_doc->file_name); 00171 } 00172 main_window->current_doc->file_name = filename; 00173 */ 00174 00175 /* This may disappear as it duplicates structures */ 00176 /* if (main_window->filename != NULL) 00177 { 00178 g_free(main_window->filename); 00179 } 00180 main_window->filename = g_strdup_printf("%s", main_window->current_doc->file_name); 00181 */ 00182 00183 /* path_end stuff from ghex-window.c from ghex project !!! */ 00184 for(i = strlen(main_window->current_doc->hex_doc->file_name); 00185 (i >= 0) && (main_window->current_doc->hex_doc->file_name[i] != '/'); 00186 i--); 00187 if (main_window->current_doc->hex_doc->file_name[i] == '/') 00188 path_end = &main_window->current_doc->hex_doc->file_name[i+1]; 00189 else 00190 path_end = main_window->current_doc->hex_doc->file_name; 00191 00192 main_window->current_doc->hex_doc->path_end = g_filename_to_utf8(path_end, -1, NULL, NULL, NULL); 00193 } 00194 } 00195 00196 if (return_value != FALSE) 00197 { 00198 return HERAIA_NOERR; 00199 } 00200 else 00201 { 00202 return HERAIA_FILE_ERROR; 00203 } 00204 } 00205 00206 /** 00207 * Deals with the endianness of 'len' bytes located in 'result' 00208 * for BIG_ENDIAN we only swap bytes if we have two or more of them 00209 * if we have only one byte, we reverse its order 00210 * if endianness is MIDDLE_ENDIAN we swap only four or more bytes 00211 * Here we might have funny things with len corresponding to 24 or 56 bits 00212 * for example 00213 * @warning Assumption is made that the default order is LITTLE_ENDIAN (which may 00214 * not be true on some systems !) 00215 * @warning We do assume that 'result' really contains 'len' bytes of data previously 00216 * gmalloc'ed 00217 * @param len : len bytes to change endianness 00218 * @param endianness : H_DI_BIG_ENDIAN or H_DI_MIDDLE_ENDIAN we consider that there 00219 * is nothing to do with H_DI_LITTLE_ENDIAN 00220 * @param[in,out] result : contains the bytes to be swaped and at the end, contains 00221 * the result. 00222 */ 00223 static void change_endianness(guint len, guint endianness, guchar *result) 00224 { 00225 if (endianness == H_DI_BIG_ENDIAN) 00226 { 00227 if (len > 1) /* We swap bytes only if we have two or more */ 00228 { 00229 swap_bytes(result, 0, len-1); 00230 } 00231 else 00232 { 00233 reverse_byte_order(result); /* Only one byte and big endian requested */ 00234 } 00235 } 00236 else if (endianness == H_DI_MIDDLE_ENDIAN && len >= 4) 00237 { 00238 swap_bytes(result, 0, (len/2)-1); 00239 swap_bytes(result, (len/2), len-1); 00240 } 00241 } 00242 00243 00244 /** 00245 * Returns 'len' number of bytes located at 'pos' in the GtkHex 00246 * document and puts it in the result variable 00247 * 00248 * @warning We assume that a previous g_malloc has been done in order to 00249 * use the function. Here we need the "swap_bytes" function 00250 * defined in the decode.h header in order to take the endianness 00251 * into account 00252 * @param gh : A GtkHex document. 00253 * @param pos : position where we want to begin to copy bytes 00254 * @param len : number of bytes we want to copy 00255 * @param endianness : endianness we want to apply to the bytes we want to copy 00256 * @param[out] result : a previously g_malloc'ed gchar * string that will contain 00257 * copied bytes. 00258 * @return TRUE if everything went ok, FALSE otherwise 00259 */ 00260 gboolean ghex_memcpy(GtkHex *gh, guint pos, guint len, guint endianness, guchar *result) 00261 { 00262 guint i; 00263 00264 if (result == NULL || gh == NULL) 00265 { 00266 return FALSE; 00267 } 00268 else if ((pos < 0) || ((pos+len) > ghex_file_size(gh))) /* pos located in the file limits ! */ 00269 { 00270 return FALSE; 00271 } 00272 else 00273 { 00274 /* Extracts len bytes from the Ghex widget */ 00275 for (i=0; i<len ; i++) 00276 { 00277 result[i] = gtk_hex_get_byte(gh, pos+i); 00278 } 00279 00280 /* Deals with endianness to rearrange datas */ 00281 change_endianness(len, endianness, result); 00282 00283 return TRUE; 00284 } 00285 } 00286 00287 00288 00289 /** 00290 * Gets the data from the hexwidget, a wrapper to the ghex_memcpy 00291 * function. 00292 * @warning guchar *c MUST have been pre allocated BEFORE the call. 00293 * 00294 * @param data_window : data interpretor window structure 00295 * @param length : can be anything but MUST be strictly less than the size allocated 00296 * to *c 00297 * @param endianness : H_DI_BIG_ENDIAN, H_DI_MIDDLE_ENDIAN or H_DI_LITTLE_ENDIAN 00298 * @param c : a previously g_malloc'ed gchar * string that will contain 00299 * copied bytes. 00300 */ 00301 gboolean ghex_get_data(GtkWidget *hex_widget, guint length, guint endianness, guchar *c) 00302 { 00303 gboolean result = FALSE; 00304 GtkHex *gh = GTK_HEX(hex_widget); 00305 00306 if (gh != NULL) 00307 { 00308 result = ghex_memcpy(gh, gtk_hex_get_cursor(gh), length, endianness, c); 00309 } 00310 else 00311 { 00312 result = FALSE; 00313 } 00314 00315 return result; 00316 } 00317 00318 00319 /** 00320 * Returns the file size of an opened GtkHex document. 00321 * @param gh : an opened GtkHex document 00322 * @return resturns the file size of that document 00323 */ 00324 guint64 ghex_file_size(GtkHex *gh) 00325 { 00326 if (gh != NULL && gh->document != NULL) 00327 { 00328 return gh->document->file_size; 00329 } 00330 else 00331 { 00332 return 0; 00333 } 00334 } 00335 00336 /** 00337 * Retrieves the cursor's position from the current hexwidget 00338 * @param data_window : data interpretor window structure 00339 * @return returns the cursor's position 00340 */ 00341 guint64 ghex_get_cursor_position(GtkWidget *hex_widget) 00342 { 00343 GtkHex *gh = GTK_HEX(hex_widget); 00344 00345 if (gh != NULL) 00346 { 00347 return gtk_hex_get_cursor(gh); 00348 } 00349 else 00350 { 00351 return 0; 00352 } 00353 } 00354 00355 00356 /** 00357 * Inits a doc_t structure 00358 * @param doc : hex_document but encapsulated in Heraia_Document 00359 * structure 00360 * @param hexwidget : Widget to display an hexadecimal view of the file 00361 * @return returns a newly allocated doc_t structure 00362 */ 00363 doc_t *new_doc_t(Heraia_Document *hex_doc, GtkWidget *hex_widget) 00364 { 00365 doc_t *new_doc; 00366 00367 new_doc = (doc_t *) g_malloc0(sizeof(doc_t)); 00368 00369 new_doc->hex_doc = hex_doc; 00370 new_doc->hex_widget = hex_widget; 00371 00372 return new_doc; 00373 }