/* Finish up the user's Release command by choosing a location to store the project. This is a callback and the GDK lock is held when entering this function. */ void i7_story_save_compiler_output(I7Story *story, const gchar *dialog_title) { I7_STORY_USE_PRIVATE(story, priv); GFile *file = NULL; if(priv->copy_blorb_dest_file == NULL) { /* ask the user for a release file name if cBlorb didn't provide one */ /* Create a file chooser */ GtkFileFilter *filter = gtk_file_filter_new(); if(i7_story_get_story_format(story) == I7_STORY_FORMAT_GLULX) { gtk_file_filter_set_name(filter, _("Glulx games (.ulx,.gblorb)")); gtk_file_filter_add_pattern(filter, "*.ulx"); gtk_file_filter_add_pattern(filter, "*.gblorb"); } else { gtk_file_filter_set_name(filter, _("Z-code games (.z?,.zblorb)")); gtk_file_filter_add_pattern(filter, "*.z?"); gtk_file_filter_add_pattern(filter, "*.zblorb"); } GtkWidget *dialog = gtk_file_chooser_dialog_new(dialog_title, 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); char *curfilename = g_file_get_basename(priv->compiler_output_file); gchar *title = i7_document_get_display_name(I7_DOCUMENT(story)); char *extension = strrchr(curfilename, '.'); /* not allocated */ char *suggestname; if(title != NULL) { *(strrchr(title, '.')) = '\0'; suggestname = g_strconcat(title, extension, NULL); g_free(title); } else { suggestname = g_strconcat("Untitled", extension, NULL); } g_free(curfilename); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), suggestname); g_free(suggestname); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(dialog)); gtk_widget_destroy(dialog); } else { file = g_object_ref(priv->copy_blorb_dest_file); } if(file) { /* Move the finished file to the release location */ GError *err = NULL; if(!g_file_move(priv->compiler_output_file, file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &err)) { IO_ERROR_DIALOG(GTK_WINDOW(story), file, err, _("copying compiler output")); } g_object_unref(file); } }
/* Search the documentation pages for the string 'text', building the index if necessary */ void i7_search_window_search_documentation(I7SearchWindow *self) { GError *err; if(doc_index == NULL) { /* documentation index hasn't been built yet */ GFile *doc_file = i7_app_get_data_file_va(i7_app_get(), "Documentation", NULL); GFileEnumerator *docdir; if((docdir = g_file_enumerate_children(doc_file, "standard::*", G_FILE_QUERY_INFO_NONE, NULL, &err)) == NULL) { IO_ERROR_DIALOG(GTK_WINDOW(self), doc_file, err, _("opening documentation directory")); g_object_unref(doc_file); return; } start_spinner(self); GFileInfo *info; while((info = g_file_enumerator_next_file(docdir, NULL, &err)) != NULL) { const char *basename = g_file_info_get_name(info); const char *displayname = g_file_info_get_display_name(info); if(!g_str_has_suffix(basename, ".html") || (!g_str_has_prefix(basename, "doc") && !g_str_has_prefix(basename, "Rdoc"))) continue; char *label = g_strdup_printf(_("Please be patient, indexing %s..."), displayname); gtk_label_set_text(GTK_LABEL(self->search_text), label); g_free(label); while(gtk_events_pending()) gtk_main_iteration(); GFile *file = g_file_get_child(doc_file, basename); GSList *doctexts = html_to_ascii(file, g_str_has_prefix(basename, "R")); g_object_unref(file); if(doctexts != NULL) { GSList *iter; /* Append the entries to the documentation index and search them right now while we're at it */ for(iter = doctexts; iter != NULL; iter = g_slist_next(iter)) { doc_index = g_list_prepend(doc_index, iter->data); search_documentation(iter->data, self); } g_slist_free(doctexts); } } g_object_unref(doc_file); stop_spinner(self); update_label(self); } else { start_spinner(self); g_list_foreach(doc_index, (GFunc)search_documentation, self); stop_spinner(self); } return; }
/* Release->Open Materials Folder */ void action_open_materials_folder(GtkAction *action, I7Story *story) { GError *error = NULL; gchar *uri; GFile *materials_file = i7_story_get_materials_file(story); /* Prompt the user to create the folder if it doesn't exist */ if(!g_file_query_exists(materials_file, NULL)) { /* TRANSLATORS: Release->Open Materials Folder */ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(story), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, _("Could not find Materials folder")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), _("At the moment, this project has no Materials folder - a " "convenient place to put figures, sounds, manuals, hints or other " "matter to be packaged up with a release.\n\nWould you like to " "create one?")); gint response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if(response == GTK_RESPONSE_OK) { if(!g_file_make_directory_with_parents(materials_file, NULL, &error)) { /* shouldn't already exist, so don't ignore G_IO_ERROR_EXISTS */ IO_ERROR_DIALOG(GTK_WINDOW(story), materials_file, error, _("creating Materials folder")); goto finally; } file_set_custom_icon(materials_file, "application-x-inform-materials"); } else goto finally; } if(g_file_query_file_type(materials_file, G_FILE_QUERY_INFO_NONE, NULL) != G_FILE_TYPE_DIRECTORY) { /* Odd; the Materials folder is a file. We open the containing path so the user can see this and correct it if they like. */ GFile *parent = g_file_get_parent(materials_file); uri = g_file_get_uri(parent); g_object_unref(parent); } else { uri = g_file_get_uri(materials_file); } /* TRANSLATORS: this string is used in error messages and should fit in the pattern "We couldn't open a program to show ___" */ show_uri_externally(uri, GTK_WINDOW(story), _("the Materials folder")); g_free(uri); finally: g_object_unref(materials_file); }
/* Set everything up for using the NI compiler. Called from the main thread. */ static void prepare_ni_compiler(CompilerData *data) { I7_STORY_USE_PRIVATE(data->story, priv); GError *err = NULL; /* Clear the previous compile output */ gtk_text_buffer_set_text(priv->progress, "", -1); html_load_blank(WEBKIT_WEB_VIEW(data->story->panel[LEFT]->results_tabs[I7_RESULTS_TAB_REPORT])); html_load_blank(WEBKIT_WEB_VIEW(data->story->panel[RIGHT]->results_tabs[I7_RESULTS_TAB_REPORT])); /* Create the UUID file if needed */ GFile *uuid_file = g_file_get_child(data->input_file, "uuid.txt"); if(!g_file_query_exists(uuid_file, NULL)) { #ifdef E2FS_UUID /* code for e2fsprogs uuid */ uuid_t uuid; gchar uuid_string[37]; uuid_generate_time(uuid); uuid_unparse(uuid, uuid_string); #else /* code for OSSP UUID */ gchar *uuid_string = NULL; /* a new buffer is allocated if NULL */ uuid_t *uuid; if(!((uuid_create(&uuid) == UUID_RC_OK) && (uuid_make(uuid, UUID_MAKE_V1) == UUID_RC_OK) && (uuid_export(uuid, UUID_FMT_STR, (void **)&uuid_string, NULL) == UUID_RC_OK) && (uuid_destroy(uuid) == UUID_RC_OK))) { error_dialog(GTK_WINDOW(data->story), NULL, _("Error creating UUID.")); g_object_unref(uuid_file); return; } #endif /* UUID conditional */ if(!g_file_replace_contents(uuid_file, uuid_string, strlen(uuid_string), NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, &err)) { IO_ERROR_DIALOG(GTK_WINDOW(data->story), uuid_file, err, _("creating UUID file")); g_object_unref(uuid_file); return; } #ifndef E2FS_UUID /* Only OSSP UUID */ free(uuid_string); #endif /* !OSSP_UUID */ } g_object_unref(uuid_file); /* Display status message */ i7_document_display_status_message(I7_DOCUMENT(data->story), _("Compiling Inform 7 to Inform 6"), COMPILE_OPERATIONS); }
void on_extensions_view_drag_data_received(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *selectiondata, guint info, guint time) { GFile *file; GFileInfo *file_info; gchar *type_name = NULL; /* Check that we got data from source */ if(selectiondata == NULL || gtk_selection_data_get_length(selectiondata) < 0) goto fail; /* Check that we got the format we can use */ type_name = gdk_atom_name(gtk_selection_data_get_data_type(selectiondata)); if(strcmp(type_name, "text/uri-list") != 0) goto fail; /* Do stuff with the data */ char **extension_files = g_uri_list_extract_uris((char *)gtk_selection_data_get_data(selectiondata)); int foo; /* Get a list of URIs to the dropped files */ for(foo = 0; extension_files[foo] != NULL; foo++) { GError *err = NULL; file = g_file_new_for_uri(extension_files[foo]); file_info = g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, &err); if(!file_info) { IO_ERROR_DIALOG(NULL, file, err, _("accessing a URI")); goto fail2; } /* Check whether a directory was dropped. if so, install contents */ /* NOTE: not recursive (that would be kind of silly anyway) */ if(g_file_info_get_file_type(file_info) == G_FILE_TYPE_DIRECTORY) { GFileEnumerator *dir = g_file_enumerate_children(file, "standard::*", G_FILE_QUERY_INFO_NONE, NULL, &err); if(!dir) { IO_ERROR_DIALOG(NULL, file, err, _("opening a directory")); goto fail3; } GFileInfo *entry_info; while((entry_info = g_file_enumerator_next_file(dir, NULL, &err)) != NULL) { if(g_file_info_get_file_type(entry_info) != G_FILE_TYPE_DIRECTORY) { GFile *extension_file = g_file_get_child(file, g_file_info_get_name(entry_info)); i7_app_install_extension(i7_app_get(), extension_file); g_object_unref(extension_file); } g_object_unref(entry_info); } g_file_enumerator_close(dir, NULL, &err); g_object_unref(dir); if(err) { IO_ERROR_DIALOG(NULL, file, err, _("reading a directory")); goto fail3; } } else { /* just install it */ i7_app_install_extension(i7_app_get(), file); } g_object_unref(file_info); g_object_unref(file); } g_strfreev(extension_files); g_free(type_name); gtk_drag_finish(drag_context, TRUE, FALSE, time); return; fail3: g_object_unref(file_info); fail2: g_object_unref(file); g_strfreev(extension_files); fail: g_free(type_name); gtk_drag_finish(drag_context, FALSE, FALSE, time); }
/* 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); }