gui: Make File|Recent Files remember the correct encoding.
authorBen Pfaff <blp@cs.stanford.edu>
Thu, 12 May 2011 05:36:45 +0000 (22:36 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 13 May 2011 04:07:14 +0000 (21:07 -0700)
It's no good to have File|Open... able to open a file in any encoding
if later pulling up the same file with File|Recent Files screws that
up, so this commit fixes the problem by noting the charset in the
file's mime-type.

src/ui/gui/psppire-data-window.c
src/ui/gui/psppire-syntax-window.c
src/ui/gui/psppire-window.c
src/ui/gui/psppire-window.h

index 604bd566a5ff2f1bcd7c8707082cc56567f81083..10e3fed57b9a5cad701c99db38a1a5973def399f 100644 (file)
@@ -23,6 +23,7 @@
 #include "data/session.h"
 #include "language/lexer/lexer.h"
 #include "libpspp/message.h"
 #include "data/session.h"
 #include "language/lexer/lexer.h"
 #include "libpspp/message.h"
+#include "libpspp/str.h"
 #include "ui/gui/aggregate-dialog.h"
 #include "ui/gui/binomial-dialog.h"
 #include "ui/gui/chi-square-dialog.h"
 #include "ui/gui/aggregate-dialog.h"
 #include "ui/gui/binomial-dialog.h"
 #include "ui/gui/chi-square-dialog.h"
@@ -64,6 +65,7 @@
 #include "ui/syntax-gen.h"
 
 #include "gl/c-strcase.h"
 #include "ui/syntax-gen.h"
 
 #include "gl/c-strcase.h"
+#include "gl/c-strcasestr.h"
 #include "gl/xvasprintf.h"
 
 #include <gettext.h>
 #include "gl/xvasprintf.h"
 
 #include <gettext.h>
@@ -359,8 +361,9 @@ name_has_suffix (const gchar *name)
 static gboolean
 load_file (PsppireWindow *de, const gchar *file_name)
 {
 static gboolean
 load_file (PsppireWindow *de, const gchar *file_name)
 {
-  gchar *utf8_file_name;
   struct string filename;
   struct string filename;
+  gchar *utf8_file_name;
+  const char *mime_type;
   gchar *syntax;
   bool ok;
 
   gchar *syntax;
   bool ok;
 
@@ -378,10 +381,14 @@ load_file (PsppireWindow *de, const gchar *file_name)
   ok = execute_syntax (PSPPIRE_DATA_WINDOW (de),
                        lex_reader_for_string (syntax));
   g_free (syntax);
   ok = execute_syntax (PSPPIRE_DATA_WINDOW (de),
                        lex_reader_for_string (syntax));
   g_free (syntax);
-  return ok;
-}
 
 
+  mime_type = (name_has_por_suffix (file_name)
+               ? "application/x-spss-por"
+               : "application/x-spss-sav");
+  add_most_recent (ds_cstr (&filename), mime_type);
 
 
+  return ok;
+}
 
 /* Save DE to file */
 static void
 
 /* Save DE to file */
 static void
@@ -756,21 +763,63 @@ on_recent_data_select (GtkMenuShell *menushell,
   g_free (file);
 }
 
   g_free (file);
 }
 
+static char *
+charset_from_mime_type (const char *mime_type)
+{
+  const char *charset;
+  struct string s;
+  const char *p;
+
+  if (mime_type == NULL)
+    return NULL;
+
+  charset = c_strcasestr (mime_type, "charset=");
+  if (charset == NULL)
+    return NULL;
+
+  ds_init_empty (&s);
+  p = charset + 8;
+  if (*p == '"')
+    {
+      /* Parse a "quoted-string" as defined by RFC 822. */
+      for (p++; *p != '\0' && *p != '"'; p++)
+        {
+          if (*p != '\\')
+            ds_put_byte (&s, *p);
+          else if (*++p != '\0')
+            ds_put_byte (&s, *p);
+        }
+    }
+  else
+    {
+      /* Parse a "token" as defined by RFC 2045. */
+      while (*p > 32 && *p < 127 && strchr ("()<>@,;:\\\"/[]?=", *p) == NULL)
+        ds_put_byte (&s, *p++);
+    }
+  if (!ds_is_empty (&s))
+    return ds_steal_cstr (&s);
+
+  ds_destroy (&s);
+  return NULL;
+}
+
 static void
 on_recent_files_select (GtkMenuShell *menushell,   gpointer user_data)
 {
 static void
 on_recent_files_select (GtkMenuShell *menushell,   gpointer user_data)
 {
+  GtkRecentInfo *item;
+  char *encoding;
+  GtkWidget *se;
   gchar *file;
 
   gchar *file;
 
-  GtkWidget *se ;
+  /* Get the file name and its encoding. */
+  item = gtk_recent_chooser_get_current_item (GTK_RECENT_CHOOSER (menushell));
+  file = g_filename_from_uri (gtk_recent_info_get_uri (item), NULL, NULL);
+  encoding = charset_from_mime_type (gtk_recent_info_get_mime_type (item));
+  gtk_recent_info_unref (item);
 
 
-  gchar *uri =
-    gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
-
-  file = g_filename_from_uri (uri, NULL, NULL);
-
-  g_free (uri);
+  se = psppire_syntax_window_new (encoding);
 
 
-  se = psppire_syntax_window_new (NULL);
+  free (encoding);
 
   if ( psppire_window_load (PSPPIRE_WINDOW (se), file) ) 
     gtk_widget_show (se);
 
   if ( psppire_window_load (PSPPIRE_WINDOW (se), file) ) 
     gtk_widget_show (se);
index 7459a41d562046583001ae250c4396d0aec90f66..b117825f752f8e7e074ac2f179651733533cd2c9 100644 (file)
@@ -867,6 +867,7 @@ syntax_load (PsppireWindow *window, const gchar *filename)
   GtkTextIter iter;
   PsppireSyntaxWindow *sw = PSPPIRE_SYNTAX_WINDOW (window);
   gchar *encoding;
   GtkTextIter iter;
   PsppireSyntaxWindow *sw = PSPPIRE_SYNTAX_WINDOW (window);
   gchar *encoding;
+  char *mime_type;
 
   /* FIXME: What if it's a very big file ? */
   if ( ! g_file_get_contents (filename, &text_locale, &len_locale, &err) )
 
   /* FIXME: What if it's a very big file ? */
   if ( ! g_file_get_contents (filename, &text_locale, &len_locale, &err) )
@@ -897,6 +898,10 @@ syntax_load (PsppireWindow *window, const gchar *filename)
 
   free (text_utf8);
 
 
   free (text_utf8);
 
+  mime_type = xasprintf ("text/x-spss-syntax; charset=%s", sw->encoding);
+  add_most_recent (filename, mime_type);
+  free (mime_type);
+
   return TRUE;
 }
 
   return TRUE;
 }
 
index 81fcb8c0591f2ffa9cb6e2121707121d94a611e8..edaa372670755020b0cfc9594e8cb0c6d5fde3db 100644 (file)
@@ -692,8 +692,6 @@ psppire_window_save_as (PsppireWindow *w)
     }
 }
 
     }
 }
 
-
-static void add_most_recent (const char *file_name);
 static void delete_recent (const char *file_name);
 
 gboolean
 static void delete_recent (const char *file_name);
 
 gboolean
@@ -713,7 +711,6 @@ psppire_window_load (PsppireWindow *w, const gchar *file)
   if ( ok )
     {
       psppire_window_set_filename (w, file);
   if ( ok )
     {
       psppire_window_set_filename (w, file);
-      add_most_recent (file);
       w->dirty = FALSE;
     }
   else
       w->dirty = FALSE;
     }
   else
@@ -832,16 +829,31 @@ psppire_window_open (PsppireWindow *de)
 }
 
 
 }
 
 
-/* Puts FILE_NAME into the recent list.
-   If it's already in the list, it moves it to the top
-*/
-static void
-add_most_recent (const char *file_name)
+/* Puts FILE_NAME (encoded in the glib file name encoding) into the recent list
+   with associated MIME_TYPE.  If it's already in the list, it moves it to the
+   top. */
+void
+add_most_recent (const char *file_name, const char *mime_type)
 {
   gchar *uri = g_filename_to_uri  (file_name, NULL, NULL);
 
   if ( uri )
 {
   gchar *uri = g_filename_to_uri  (file_name, NULL, NULL);
 
   if ( uri )
-    gtk_recent_manager_add_item (gtk_recent_manager_get_default (), uri);
+    {
+      GtkRecentData recent_data;
+
+      recent_data.display_name = NULL;
+      recent_data.description = NULL;
+      recent_data.mime_type = CONST_CAST (gchar *, mime_type);
+      recent_data.app_name = CONST_CAST (gchar *, g_get_application_name ());
+      recent_data.app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
+      recent_data.groups = NULL;
+      recent_data.is_private = FALSE;
+
+      gtk_recent_manager_add_full (gtk_recent_manager_get_default (),
+                                   uri, &recent_data);
+
+      g_free (recent_data.app_exec);
+    }
 
   g_free (uri);
 }
 
   g_free (uri);
 }
index 0aa913c1f99edffcc23e51b59dbab1016dc574b9..b80f79d699af04d14a647be6d817830ff9a5b65b 100644 (file)
@@ -114,6 +114,7 @@ gboolean psppire_window_load (PsppireWindow *w, const gchar *file);
 void psppire_window_open (PsppireWindow *de);
 GtkWidget *psppire_window_file_chooser_dialog (PsppireWindow *toplevel);
 
 void psppire_window_open (PsppireWindow *de);
 GtkWidget *psppire_window_file_chooser_dialog (PsppireWindow *toplevel);
 
+void add_most_recent (const char *file_name, const char *mime_type);
 
 G_END_DECLS
 
 
 G_END_DECLS