Started using thread-private data. Multisession still doesn't work, but regular opera...
[rodin/chimara.git] / libchimara / fileref.c
index 08ae5843d2318156619ee1ffdf92d17342ae2370..97c6e487bb62a02c79b4af9c8665a50f220b9edd 100644 (file)
@@ -7,7 +7,7 @@
 #include "magic.h"
 #include "chimara-glk-private.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /**
  * glk_fileref_iterate:
@@ -24,7 +24,8 @@ frefid_t
 glk_fileref_iterate(frefid_t fref, glui32 *rockptr)
 {
        VALID_FILEREF_OR_NULL(fref, return NULL);
-       
+
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
        GList *retnode;
        
        if(fref == NULL)
@@ -62,6 +63,8 @@ fileref_new(gchar *filename, glui32 rock, glui32 usage, glui32 orig_filemode)
 {
        g_return_val_if_fail(filename != NULL, NULL);
 
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       
        frefid_t f = g_new0(struct glk_fileref_struct, 1);
        f->magic = MAGIC_FILEREF;
        f->rock = rock;
@@ -137,30 +140,31 @@ glk_fileref_create_temp(glui32 usage, glui32 rock)
  * <note><title>Chimara</title>
  * <para>
  * Chimara uses a <link 
- * linkend="gtk-GtkFileChooserDialog">GtkFileChooserDialog</link>.
+ * linkend="gtk-GtkFileChooserDialog">GtkFileChooserDialog</link>. The default
+ * starting location for the dialog may be set with glkunix_set_base_file().
  * </para></note>
  *
  * @fmode must be one of these values:
  * <variablelist>
  * <varlistentry>
- *   <term>#filemode_Read</term>
+ *   <term>%filemode_Read</term>
  *   <listitem><para>The file must already exist; and the player will be asked
  *   to select from existing files which match the usage.</para></listitem>
  * </varlistentry>
  * <varlistentry>
- *   <term>#filemode_Write</term>
+ *   <term>%filemode_Write</term>
  *   <listitem><para>The file should not exist; if the player selects an
  *   existing file, he will be warned that it will be replaced.
  *   </para></listitem>
  * </varlistentry>
  * <varlistentry>
- *   <term>#filemode_ReadWrite</term>
+ *   <term>%filemode_ReadWrite</term>
  *   <listitem><para>The file may or may not exist; if it already exists, the
  *   player will be warned that it will be modified.</para></listitem>
  * </varlistentry>
  * <varlistentry>
- *   <term>#filemode_WriteAppend</term>
- *   <listitem><para>Same behavior as #filemode_ReadWrite.</para></listitem>
+ *   <term>%filemode_WriteAppend</term>
+ *   <listitem><para>Same behavior as %filemode_ReadWrite.</para></listitem>
  * </varlistentry>
  * </variablelist>
  *
@@ -184,6 +188,8 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
        for each usage */
        GtkWidget *chooser;
 
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       
        gdk_threads_enter();
 
        switch(fmode)
@@ -224,6 +230,9 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
                        return NULL;
        }
        
+       if(glk_data->current_dir)
+               gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), glk_data->current_dir);
+       
        if(gtk_dialog_run( GTK_DIALOG(chooser) ) != GTK_RESPONSE_ACCEPT)
        {
                gtk_widget_destroy(chooser);
@@ -254,7 +263,8 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
  * </para></note>
  * <note><title>Chimara</title>
  * <para>
- * In Chimara, the file is created in the current working directory.
+ * In Chimara, the file is created in the directory last set by 
+ * glkunix_set_base_file(), and otherwise in the current working directory.
  * </para></note>
  *
  * Since filenames are highly platform-specific, you should use
@@ -284,6 +294,12 @@ glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock)
 {
        g_return_val_if_fail(name != NULL && strlen(name) > 0, NULL);
 
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       
+       /* Do any string-munging here to remove illegal Latin-1 characters from 
+       filename. On ext3, the only illegal characters are '/' and '\0'. */
+       g_strdelimit(name, "/", '_');
+       
        /* Find out what encoding filenames are in */
        const gchar **charsets; /* Do not free */
        g_get_filename_charsets(&charsets);
@@ -297,14 +313,16 @@ glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock)
                WARNING_S("Error during latin1->filename conversion", error->message);
                return NULL;
        }
-
-       /* Do any string-munging here to remove illegal characters from filename.
-       On ext3, the only illegal characters are '/' and '\0'. TODO: Should this
-       function be allowed to reference files in other directories, or should we
-       disallow '/'? */
-
-       frefid_t f = fileref_new(osname, rock, usage, filemode_ReadWrite);
+       
+       gchar *path;
+       if(glk_data->current_dir)
+               path = g_build_filename(glk_data->current_dir, osname, NULL);
+       else
+               path = g_strdup(osname);
        g_free(osname);
+       
+       frefid_t f = fileref_new(path, rock, usage, filemode_ReadWrite);
+       g_free(path);
        return f;
 }
 
@@ -318,7 +336,7 @@ glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock)
  * original fileref is not modified.)
  *
  * The use of this function can be tricky. If you change the type of the fileref
- * (#fileusage_Data, #fileusage_SavedGame, etc), the new reference may or may
+ * (%fileusage_Data, %fileusage_SavedGame, etc), the new reference may or may
  * not point to the same actual disk file.
  *
  * <note><para>
@@ -330,8 +348,8 @@ glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock)
  * unpredictable. It is safest to change the type of a fileref only if it refers
  * to a nonexistent file.
  *
- * If you change the mode of a fileref (#fileusage_TextMode,
- * #fileusage_BinaryMode), but leave the rest of the type unchanged, the new
+ * If you change the mode of a fileref (%fileusage_TextMode,
+ * %fileusage_BinaryMode), but leave the rest of the type unchanged, the new
  * fileref will definitely point to the same disk file as the old one.
  * 
  * Obviously, if you write to a file in text mode and then read from it in
@@ -362,6 +380,8 @@ void
 glk_fileref_destroy(frefid_t fref)
 {
        VALID_FILEREF(fref, return);
+
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
        
        glk_data->fileref_list = g_list_delete_link(glk_data->fileref_list, fref->fileref_list);
        if(fref->filename)