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 current_doc : current edited document (doc_t * structure) 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(doc_t *current_doc) 00125 { 00126 gint return_value = FALSE; 00127 00128 if (current_doc != NULL) 00129 { 00130 if (current_doc->hex_doc != NULL) 00131 { 00132 return_value = hex_document_write(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 current_doc : current edited document (doc_t * 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(doc_t *current_doc, 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 (current_doc != NULL && 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(current_doc->hex_doc, fp); 00165 fclose(fp); 00166 00167 /* path_end stuff from ghex-window.c from ghex project !!! */ 00168 for(i = strlen(current_doc->hex_doc->file_name); 00169 (i >= 0) && (current_doc->hex_doc->file_name[i] != '/'); 00170 i--); 00171 if (current_doc->hex_doc->file_name[i] == '/') 00172 path_end = ¤t_doc->hex_doc->file_name[i+1]; 00173 else 00174 path_end = current_doc->hex_doc->file_name; 00175 00176 current_doc->hex_doc->path_end = g_filename_to_utf8(path_end, -1, NULL, NULL, NULL); 00177 } 00178 } 00179 00180 if (return_value != FALSE) 00181 { 00182 return HERAIA_NOERR; 00183 } 00184 else 00185 { 00186 return HERAIA_FILE_ERROR; 00187 } 00188 } 00189 00190 /** 00191 * Deals with the endianness of 'len' bytes located in 'result' 00192 * for BIG_ENDIAN we only swap bytes if we have two or more of them 00193 * if we have only one byte, we reverse its order 00194 * if endianness is MIDDLE_ENDIAN we swap only four or more bytes 00195 * Here we might have funny things with len corresponding to 24 or 56 bits 00196 * for example 00197 * @warning Assumption is made that the default order is LITTLE_ENDIAN (which may 00198 * not be true on some systems !) 00199 * @warning We do assume that 'result' really contains 'len' bytes of data previously 00200 * gmalloc'ed 00201 * @param len : len bytes to change endianness 00202 * @param endianness : H_DI_BIG_ENDIAN or H_DI_MIDDLE_ENDIAN we consider that there 00203 * is nothing to do with H_DI_LITTLE_ENDIAN 00204 * @param[in,out] result : contains the bytes to be swaped and at the end, contains 00205 * the result. 00206 */ 00207 static void change_endianness(guint len, guint endianness, guchar *result) 00208 { 00209 if (endianness == H_DI_BIG_ENDIAN) 00210 { 00211 if (len > 1) /* We swap bytes only if we have two or more */ 00212 { 00213 swap_bytes(result, 0, len-1); 00214 } 00215 else 00216 { 00217 reverse_byte_order(result); /* Only one byte and big endian requested */ 00218 } 00219 } 00220 else if (endianness == H_DI_MIDDLE_ENDIAN && len >= 4) 00221 { 00222 swap_bytes(result, 0, (len/2)-1); 00223 swap_bytes(result, (len/2), len-1); 00224 } 00225 } 00226 00227 00228 /** 00229 * Returns 'len' number of bytes located at 'pos' in the GtkHex 00230 * document and puts it in the result variable 00231 * 00232 * @warning We assume that a previous g_malloc has been done in order to 00233 * use the function. Here we need the "swap_bytes" function 00234 * defined in the decode.h header in order to take the endianness 00235 * into account 00236 * @param gh : A GtkHex document. 00237 * @param pos : position where we want to begin to copy bytes 00238 * @param len : number of bytes we want to copy 00239 * @param endianness : endianness we want to apply to the bytes we want to copy 00240 * @param[out] result : a previously g_malloc'ed gchar * string that will contain 00241 * copied bytes. 00242 * @return TRUE if everything went ok, FALSE otherwise 00243 */ 00244 gboolean ghex_memcpy(GtkHex *gh, guint pos, guint len, guint endianness, guchar *result) 00245 { 00246 guint i; 00247 00248 if (result == NULL || gh == NULL) 00249 { 00250 return FALSE; 00251 } 00252 else if ((pos < 0) || ((pos+len) > ghex_file_size(gh))) /* pos located in the file limits ! */ 00253 { 00254 return FALSE; 00255 } 00256 else 00257 { 00258 /* Extracts len bytes from the Ghex widget */ 00259 for (i=0; i<len ; i++) 00260 { 00261 result[i] = gtk_hex_get_byte(gh, pos+i); 00262 } 00263 00264 /* Deals with endianness to rearrange datas */ 00265 change_endianness(len, endianness, result); 00266 00267 return TRUE; 00268 } 00269 } 00270 00271 00272 00273 /** 00274 * Gets the data from the hexwidget, a wrapper to the ghex_memcpy 00275 * function. 00276 * @warning guchar *c MUST have been pre allocated BEFORE the call. 00277 * 00278 * @param data_window : data interpretor window structure 00279 * @param length : can be anything but MUST be strictly less than the size allocated 00280 * to *c 00281 * @param endianness : H_DI_BIG_ENDIAN, H_DI_MIDDLE_ENDIAN or H_DI_LITTLE_ENDIAN 00282 * @param c : a previously g_malloc'ed gchar * string that will contain 00283 * copied bytes. 00284 */ 00285 gboolean ghex_get_data(GtkWidget *hex_widget, guint length, guint endianness, guchar *c) 00286 { 00287 gboolean result = FALSE; 00288 GtkHex *gh = GTK_HEX(hex_widget); 00289 00290 if (gh != NULL) 00291 { 00292 result = ghex_memcpy(gh, gtk_hex_get_cursor(gh), length, endianness, c); 00293 } 00294 else 00295 { 00296 result = FALSE; 00297 } 00298 00299 return result; 00300 } 00301 00302 00303 /** 00304 * Returns the file size of an opened GtkHex document. 00305 * @param gh : an opened GtkHex document 00306 * @return resturns the file size of that document 00307 */ 00308 guint64 ghex_file_size(GtkHex *gh) 00309 { 00310 if (gh != NULL && gh->document != NULL) 00311 { 00312 return gh->document->file_size; 00313 } 00314 else 00315 { 00316 return 0; 00317 } 00318 } 00319 00320 /** 00321 * Retrieves the cursor's position from the current hexwidget 00322 * @param data_window : data interpretor window structure 00323 * @return returns the cursor's position 00324 */ 00325 guint64 ghex_get_cursor_position(GtkWidget *hex_widget) 00326 { 00327 GtkHex *gh = GTK_HEX(hex_widget); 00328 00329 if (gh != NULL) 00330 { 00331 return gtk_hex_get_cursor(gh); 00332 } 00333 else 00334 { 00335 return 0; 00336 } 00337 } 00338 00339 00340 /** 00341 * Inits a doc_t structure 00342 * @param doc : hex_document but encapsulated in Heraia_Document 00343 * structure 00344 * @param hexwidget : Widget to display an hexadecimal view of the file 00345 * @return returns a newly allocated doc_t structure 00346 */ 00347 doc_t *new_doc_t(Heraia_Document *hex_doc, GtkWidget *hex_widget) 00348 { 00349 doc_t *new_doc; 00350 00351 new_doc = (doc_t *) g_malloc0(sizeof(doc_t)); 00352 00353 new_doc->hex_doc = hex_doc; 00354 new_doc->hex_widget = hex_widget; 00355 00356 return new_doc; 00357 }