#include #include #include #include #include #include #include #include enum memory_view_columns { MEM_VIEW_COL_ADDRESS = 0, MEM_VIEW_COL_DATA, MEM_VIEW_COL_INTERPRETATION, MEM_VIEW_COLUMN_COUNT }; struct application_data { GtkWidget *borrowed_main_window; GtkTreeView *borrowed_tree_view; GtkHeaderBar *borrowed_header_bar; const char *error_memory_data; size_t file_size; }; static void tree_view_show_error_memory(GtkTreeView *tree_view, const char *memory, size_t len) { GtkListStore *store; GtkTreeIter _iter; GtkTreeIter *iter = &_iter; store = GTK_LIST_STORE(gtk_tree_view_get_model(tree_view)); if (store) { for (unsigned int i = 0; i < 0xFFFF; i+=4) { gtk_list_store_append(store, iter); gtk_list_store_set(store, iter, MEM_VIEW_COL_ADDRESS, i, MEM_VIEW_COL_INTERPRETATION, "Test", MEM_VIEW_COL_DATA, i % 12, -1); } } } void setup_tree_view(GtkTreeView *tree_view) { GtkListStore *list_store; GtkCellRenderer *string_renderer; GtkCellRenderer *hex_renderer; GtkTreeViewColumn *column; g_return_if_fail(GTK_IS_TREE_VIEW(tree_view)); list_store = gtk_list_store_new(MEM_VIEW_COLUMN_COUNT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING); gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(list_store)); string_renderer = gtk_cell_renderer_text_new(); hex_renderer = err_mem_view_address_cell_renderer_new(); column = gtk_tree_view_column_new_with_attributes("Address", hex_renderer, "hex-num", MEM_VIEW_COL_ADDRESS, NULL); gtk_tree_view_append_column(tree_view, column); column = gtk_tree_view_column_new_with_attributes("Data", hex_renderer, "hex-num", MEM_VIEW_COL_DATA, NULL); gtk_tree_view_append_column(tree_view, column); column = gtk_tree_view_column_new_with_attributes("Interpretation", string_renderer, "text", MEM_VIEW_COL_INTERPRETATION, NULL); gtk_tree_view_append_column(tree_view, column); } static int64_t get_file_size(int file) { off_t size; if (!file) return -1L; size = lseek(file, 0, SEEK_END); if (size == (off_t)-1) return -1; return (int64_t)size; } static const char *map_file_to_memory(const char *name, size_t *detected_size) { const char *ret = NULL; int file; int64_t file_size; file = open(name, O_RDONLY); if (file < 0) goto exit; file_size = get_file_size(file); if (file_size < 0) goto exit; if (detected_size) *detected_size = (size_t)file_size; ret = (const char *)mmap(NULL, (size_t)file_size, PROT_READ, MAP_SHARED, file, (off_t)0L); exit: return ret; } G_MODULE_EXPORT void open_button_clicked_cb(GtkButton *button, gpointer *user_data) { struct application_data *data = (struct application_data *)user_data; (void)button; GtkDialog *dialog; gint res; gchar *filename; dialog = GTK_DIALOG(gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(data->borrowed_main_window), GTK_FILE_CHOOSER_ACTION_OPEN, "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL)); res = gtk_dialog_run(dialog); if (res == GTK_RESPONSE_ACCEPT) { filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); data->error_memory_data = map_file_to_memory(filename, &data->file_size); if (!data->error_memory_data) { g_warning("File could not be loaded"); g_free(filename); goto ret_destroy_dialog; } gtk_header_bar_set_subtitle(data->borrowed_header_bar, filename); g_free(filename); } tree_view_show_error_memory(data->borrowed_tree_view, data->error_memory_data, data->file_size); ret_destroy_dialog: gtk_widget_destroy(GTK_WIDGET(dialog)); } static void app_activated(GApplication *app, gpointer user_data) { (void)user_data; GtkBuilder *builder; GtkWindow *main_window; static struct application_data data; builder = gtk_builder_new_from_resource("/gui/main"); main_window = GTK_WINDOW(gtk_builder_get_object(builder, "main-window")); data.borrowed_main_window = GTK_WIDGET(main_window); data.error_memory_data = NULL; data.borrowed_tree_view = GTK_TREE_VIEW(gtk_builder_get_object(builder, "error-mem-tree-view")); data.borrowed_header_bar = GTK_HEADER_BAR(gtk_builder_get_object(builder, "header-bar")); setup_tree_view(data.borrowed_tree_view); gtk_builder_connect_signals(builder, &data); g_object_unref(builder); gtk_application_add_window(GTK_APPLICATION(app), main_window); gtk_widget_show(GTK_WIDGET(main_window)); } static int start_gui(int argc, char **argv) { int ret = 0; GtkApplication *g_app; /* Create a new G application which will start a completely new process for each call to the program (NON_UNIQUE) instead * of creating an additional window in the same process */ g_app = gtk_application_new("de.shimatta.reflow.error-mem-viewer", G_APPLICATION_NON_UNIQUE); g_signal_connect(g_app, "activate", G_CALLBACK(app_activated), NULL); ret = g_application_run(G_APPLICATION(g_app), argc, argv); g_object_unref(g_app); return ret; } int main(int argc, char **argv) { return start_gui(argc, argv); }