/* Search the project file for the string 'text' */ void i7_search_window_search_project(I7SearchWindow *self) { I7_SEARCH_WINDOW_USE_PRIVATE(self, priv); GtkTreeIter result; GtkTextIter search_from, match_start, match_end; GtkTextBuffer *buffer = GTK_TEXT_BUFFER(i7_document_get_buffer(priv->document)); gtk_text_buffer_get_start_iter(buffer, &search_from); start_spinner(self); while(find_no_wrap(&search_from, priv->text, TRUE, GTK_SOURCE_SEARCH_TEXT_ONLY | (priv->ignore_case? GTK_SOURCE_SEARCH_CASE_INSENSITIVE : 0), priv->algorithm, &match_start, &match_end)) { while(gtk_events_pending()) gtk_main_iteration(); search_from = match_end; /* Get the line number (counted from 0) */ guint lineno = gtk_text_iter_get_line(&match_start) + 1; gchar *context = extract_context(buffer, &match_start, &match_end); /* Make a sort string */ gchar *sort = g_strdup_printf("%04i", lineno); /* Put the full path to the project in */ GFile *file = i7_document_get_file(priv->document); gtk_list_store_append(priv->results, &result); gtk_list_store_set(priv->results, &result, I7_RESULT_CONTEXT_COLUMN, context, I7_RESULT_SORT_STRING_COLUMN, sort, I7_RESULT_FILE_COLUMN, file, I7_RESULT_RESULT_TYPE_COLUMN, I7_RESULT_TYPE_PROJECT, I7_RESULT_LINE_NUMBER_COLUMN, lineno, -1); g_free(context); g_free(sort); g_object_unref(file); } stop_spinner(self); }
/* Start the compiling process. Called from the main thread. */ void i7_story_compile(I7Story *story, gboolean release, gboolean refresh) { I7_STORY_USE_PRIVATE(story, priv); i7_document_save(I7_DOCUMENT(story)); i7_story_stop_running_game(story); if(priv->copy_blorb_dest_file) { g_object_unref(priv->copy_blorb_dest_file); priv->copy_blorb_dest_file = NULL; } if(priv->compiler_output_file) { g_object_unref(priv->compiler_output_file); priv->compiler_output_file = NULL; } gtk_action_group_set_sensitive(priv->compile_action_group, FALSE); /* Set up the compiler */ CompilerData *data = g_slice_new0(CompilerData); data->story = story; data->create_blorb = release && i7_story_get_create_blorb(story); data->use_debug_flags = !release; data->refresh_only = refresh; gchar *filename; if(data->create_blorb) { if(i7_story_get_story_format(story) == I7_STORY_FORMAT_GLULX) filename = g_strdup("output.gblorb"); else filename = g_strdup("output.zblorb"); } else { filename = g_strconcat("output.", i7_story_get_extension(story), NULL); } data->input_file = i7_document_get_file(I7_DOCUMENT(story)); data->builddir_file = g_file_get_child(data->input_file, "Build"); data->output_file = g_file_get_child(data->builddir_file, filename); g_free(filename); prepare_ni_compiler(data); start_ni_compiler(data); }
/* Finish up the user's Export iFiction Record command. This is a callback and the GDK lock is held when entering this function. */ void i7_story_save_ifiction(I7Story *story) { /* Work out where the file should be */ GFile *project_file = i7_document_get_file(I7_DOCUMENT(story)); if(project_file == NULL) { g_warning("Tried to save iFiction record of story without associated file"); return; /* This shouldn't happen because the file is saved before compilation */ } GFile *ifiction_file = g_file_get_child(project_file, "Metadata.iFiction"); /* Prompt user to save iFiction file if it exists */ if(g_file_query_exists(ifiction_file, NULL)) { /* Make a file filter */ GtkFileFilter *filter = gtk_file_filter_new(); gtk_file_filter_set_name(filter, _("iFiction records (.iFiction)")); gtk_file_filter_add_pattern(filter, "*.iFiction"); /* Make up a default file name */ gchar *name = i7_document_get_display_name(I7_DOCUMENT(story)); /* project_file is not NULL so neither is name */ *(strrchr(name, '.')) = '\0'; gchar *filename = g_strconcat(name, ".iFiction", NULL); g_free(name); /* Create a file chooser */ GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Save iFiction record"), GTK_WINDOW(story), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); g_free(filename); GFile *parent_file = g_file_get_parent(project_file); /* Ignore error */ gtk_file_chooser_set_current_folder_file(GTK_FILE_CHOOSER(dialog), parent_file, NULL); g_object_unref(parent_file); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); /* Copy the finished file to the chosen location */ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { GFile *dest_file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(dialog)); GError *error = NULL; if(!g_file_copy(ifiction_file, dest_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error)) { IO_ERROR_DIALOG(GTK_WINDOW(story), dest_file, error, _("copying iFiction record")); } g_object_unref(dest_file); } gtk_widget_destroy(dialog); } else error_dialog(GTK_WINDOW(story), NULL, _("The compiler failed to create an iFiction record; check the " "results page to see why.")); g_object_unref(ifiction_file); g_object_unref(project_file); }
/* Display any errors from the NI compiler and continue on. This function is called from a child process watch, so the GDK lock is not held and must be acquired for any GUI calls. */ static void finish_ni_compiler(GPid pid, gint status, CompilerData *data) { I7_STORY_USE_PRIVATE(data->story, priv); I7App *theapp = i7_app_get(); GSettings *prefs = i7_app_get_prefs(theapp); /* Clear the progress indicator */ gdk_threads_enter(); i7_document_remove_status_message(I7_DOCUMENT(data->story), COMPILE_OPERATIONS); i7_document_clear_progress(I7_DOCUMENT(data->story)); gdk_threads_leave(); /* Get the ni.exe exit code */ int exit_code = WIFEXITED(status)? WEXITSTATUS(status) : -1; /* Display the appropriate HTML error or success page */ GFile *problems_file = NULL; if(exit_code <= 1) { /* In the case of success or a "normal" failure, or a negative error code should one occur, display the compiler's generated Problems.html*/ problems_file = g_file_get_child(data->builddir_file, "Problems.html"); } else { gchar *file = g_strdup_printf("Error%i.html", exit_code); problems_file = i7_app_check_data_file_va(theapp, "Resources", "en", file, NULL); g_free(file); if(!problems_file) problems_file = i7_app_get_data_file_va(theapp, "Resources", "en", "Error0.html", NULL); } g_clear_object(&data->results_file); data->results_file = problems_file; /* assumes reference */ if(g_settings_get_boolean(prefs, PREFS_SHOW_DEBUG_LOG)) { /* Update */ gdk_threads_enter(); while(gtk_events_pending()) gtk_main_iteration(); gdk_threads_leave(); /* Refresh the debug log */ gchar *text; GFile *debug_file = g_file_get_child(data->builddir_file, "Debug log.txt"); /* Ignore errors, just don't show it if it's not there */ if(g_file_load_contents(debug_file, NULL, &text, NULL, NULL, NULL)) { gdk_threads_enter(); gtk_text_buffer_set_text(priv->debug_log, text, -1); gdk_threads_leave(); g_free(text); } g_object_unref(debug_file); /* Refresh the I6 code */ GFile *i6_file = g_file_get_child(data->builddir_file, "auto.inf"); if(g_file_load_contents(i6_file, NULL, &text, NULL, NULL, NULL)) { gdk_threads_enter(); gtk_text_buffer_set_text(GTK_TEXT_BUFFER(priv->i6_source), text, -1); gdk_threads_leave(); g_free(text); } g_object_unref(i6_file); } /* Stop here and show the Results/Report tab if there was an error */ if(exit_code != 0) { finish_compiling(FALSE, data); return; } /* Reload the Index in the background */ i7_story_reload_index_tabs(data->story, FALSE); /* Read in the Blorb manifest */ GFile *file = i7_document_get_file(I7_DOCUMENT(data->story)); GFile *manifest_file = g_file_get_child(file, "manifest.plist"); g_object_unref(file); PlistObject *manifest = plist_read_file(manifest_file, NULL, NULL); g_object_unref(manifest_file); /* If that failed, then silently keep the old manifest */ if(manifest) { plist_object_free(priv->manifest); priv->manifest = manifest; } /* Decide what to do next */ if(data->refresh_only) { I7Story *story = data->story; finish_compiling(TRUE, data); /* Hold the GDK lock for the callback */ gdk_threads_enter(); (priv->compile_finished_callback)(story, priv->compile_finished_callback_data); gdk_threads_leave(); return; } prepare_i6_compiler(data); start_i6_compiler(data); }