From 729b96a6bd9342c45e6f65a113fd87c70da85b0a Mon Sep 17 00:00:00 2001
From: John Darrington <john@darrington.wattle.id.au>
Date: Tue, 7 Jul 2009 00:44:27 +0800
Subject: [PATCH] Convert to utf8 in data_out function.

Previously, the output value of data_out was of arbitrary encoding.
This change attempts to ensure that it is always utf8.
---
 src/data/data-out.c                     | 17 ++++++++----
 src/data/data-out.h                     |  4 +--
 src/data/variable.c                     |  3 +-
 src/language/data-io/list.q             |  8 +++---
 src/language/dictionary/split-file.c    |  2 +-
 src/language/expressions/operations.def |  2 +-
 src/language/stats/crosstabs.q          | 16 ++++++-----
 src/libpspp/i18n.c                      | 19 +++++++++----
 src/libpspp/i18n.h                      |  7 ++++-
 src/output/table.c                      |  6 ++--
 src/ui/gui/compute-dialog.c             |  8 +-----
 src/ui/gui/dialog-common.c              | 10 ++-----
 src/ui/gui/dict-display.c               | 14 ++--------
 src/ui/gui/helper.c                     |  4 +--
 src/ui/gui/helper.h                     |  3 +-
 src/ui/gui/missing-val-dialog.c         |  9 +++---
 src/ui/gui/missing-val-dialog.h         |  3 ++
 src/ui/gui/psppire-data-editor.c        |  8 +++---
 src/ui/gui/psppire-data-store.c         | 21 +++++---------
 src/ui/gui/psppire-dict.c               |  5 +---
 src/ui/gui/psppire-dictview.c           | 21 ++++----------
 src/ui/gui/psppire-var-sheet.c          |  2 ++
 src/ui/gui/psppire-var-store.c          |  2 +-
 src/ui/gui/text-data-import-dialog.c    |  2 +-
 src/ui/gui/val-labs-dialog.c            |  4 +--
 src/ui/gui/var-display.c                | 18 ++++++------
 src/ui/gui/var-type-dialog.c            |  4 +--
 src/ui/gui/variable-info-dialog.c       | 37 ++++++-------------------
 src/ui/syntax-gen.c                     |  2 +-
 29 files changed, 113 insertions(+), 148 deletions(-)

diff --git a/src/data/data-out.c b/src/data/data-out.c
index 7f15e5b24a..4c6ca3dd3c 100644
--- a/src/data/data-out.c
+++ b/src/data/data-out.c
@@ -37,6 +37,7 @@
 #include <libpspp/misc.h>
 #include <libpspp/str.h>
 #include <libpspp/pool.h>
+#include <libpspp/i18n.h>
 
 #include "minmax.h"
 
@@ -108,7 +109,7 @@ data_out_legacy (const union value *input, const char *encoding,
     legacy_recode (LEGACY_NATIVE, output, encoding, output, format->w);
 }
 
-/* Converts the INPUT value into printable form, according to format
+/* Converts the INPUT value into a UTF8 encoded string, according to format
    specification FORMAT. 
 
    VALUE must be the correct width for FORMAT, that is, its
@@ -119,21 +120,25 @@ data_out_legacy (const union value *input, const char *encoding,
    allocated on that pool.
 */
 char *
-data_out_pool (const union value *input, const struct fmt_spec *format,
+data_out_pool (const union value *input, const char *encoding, const struct fmt_spec *format,
 	  struct pool *pool)
 {
-  char *output = pool_malloc (pool, format->w + 1);
+  char *output = xmalloc (format->w + 1);
+  char *t ;
   assert (fmt_check_output (format));
 
   converters[format->type] (input, format, output);
   output[format->w] = '\0';
-  return output;
+
+  t =  recode_string_pool (UTF8, encoding, output, format->w, pool);
+  free (output);
+  return t;
 }
 
 char *
-data_out (const union value *input, const struct fmt_spec *format)
+data_out (const union value *input, const char *encoding, const struct fmt_spec *format)
 {
-  return data_out_pool (input, format, NULL);
+  return data_out_pool (input, encoding, format, NULL);
 }
 
 
diff --git a/src/data/data-out.h b/src/data/data-out.h
index 71cbbac3d5..735679b412 100644
--- a/src/data/data-out.h
+++ b/src/data/data-out.h
@@ -25,9 +25,9 @@
 struct fmt_spec;
 union value;
 
-char * data_out (const union value *, const struct fmt_spec *);
+char * data_out (const union value *, const char *encoding, const struct fmt_spec *);
 
-char * data_out_pool (const union value *, const struct fmt_spec *, struct pool *pool);
+char * data_out_pool (const union value *, const char *encoding, const struct fmt_spec *, struct pool *pool);
 
 void data_out_legacy (const union value *input, const char *encoding,
 		      const struct fmt_spec *format, char *output);
diff --git a/src/data/variable.c b/src/data/variable.c
index a60adcafcd..0b5ca26c97 100644
--- a/src/data/variable.c
+++ b/src/data/variable.c
@@ -590,9 +590,10 @@ var_append_value_name (const struct variable *v, const union value *value,
 		       struct string *str)
 {
   const char *name = var_lookup_value_label (v, value);
+  const struct dictionary *dict = var_get_vardict (v)->dict;
   if (name == NULL)
     {
-      char *s = data_out (value, &v->print);
+      char *s = data_out (value, dict_get_encoding (dict), &v->print);
       ds_put_cstr (str, s);
       free (s);
     }
diff --git a/src/language/data-io/list.q b/src/language/data-io/list.q
index b5a16f2654..c3f9b0881b 100644
--- a/src/language/data-io/list.q
+++ b/src/language/data-io/list.q
@@ -706,7 +706,7 @@ list_case (const struct ccase *c, casenumber case_idx,
             if (fmt_is_string (print->type)
                 || dict_contains_var (dict, v))
 	      {
-		char *s = data_out (case_data (c, v), print);
+		char *s = data_out (case_data (c, v), dict_get_encoding (dict), print);
 		ds_put_cstr (&line_buffer, s);
 		free (s);
 	      }
@@ -715,7 +715,7 @@ list_case (const struct ccase *c, casenumber case_idx,
 		char *s;
                 union value case_idx_value;
                 case_idx_value.f = case_idx;
-                s = data_out (&case_idx_value, print);
+                s = data_out (&case_idx_value, dict_get_encoding (dict), print);
 		ds_put_cstr (&line_buffer, s);
 		free (s);
               }
@@ -747,12 +747,12 @@ list_case (const struct ccase *c, casenumber case_idx,
 
             if (fmt_is_string (print->type)
                 || dict_contains_var (dict, v))
-	      s = data_out (case_data (c, v), print);
+	      s = data_out (case_data (c, v), dict_get_encoding (dict), print);
             else
               {
                 union value case_idx_value;
                 case_idx_value.f = case_idx;
-                s = data_out (&case_idx_value, print);
+                s = data_out (&case_idx_value, dict_get_encoding (dict), print);
               }
 
             fputs ("    <TD>", x->file);
diff --git a/src/language/dictionary/split-file.c b/src/language/dictionary/split-file.c
index 11fa097493..0024787fdd 100644
--- a/src/language/dictionary/split-file.c
+++ b/src/language/dictionary/split-file.c
@@ -94,7 +94,7 @@ output_split_file_values (const struct dataset *ds, const struct ccase *c)
 
       tab_text (t, 0, i + 1, TAB_LEFT | TAT_PRINTF, "%s", var_get_name (v));
 
-      s = data_out (case_data (c, v), print);
+      s = data_out (case_data (c, v), dict_get_encoding (dict), print);
 
       tab_text (t, 1, i + 1, TAT_PRINTF, "%.*s", print->w, s);
       free (s);
diff --git a/src/language/expressions/operations.def b/src/language/expressions/operations.def
index db71d27703..d78827a8da 100644
--- a/src/language/expressions/operations.def
+++ b/src/language/expressions/operations.def
@@ -587,7 +587,7 @@ absorb_miss string function STRING (x, no_format f)
   v.f = x;
 
   assert (!fmt_is_string (f->type));
-  s = data_out (&v, f);
+  s = data_out (&v, "no-such-encoding", f);
   dst = alloc_string (e, strlen (s));
   strcpy (dst.string, s);
   free (s);
diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q
index a83a86472f..3c689ebc49 100644
--- a/src/language/stats/crosstabs.q
+++ b/src/language/stats/crosstabs.q
@@ -177,6 +177,7 @@ get_var_range (const struct variable *v)
 
 struct crosstabs_proc
   {
+    const struct dictionary *dict;
     enum { INTEGER, GENERAL } mode;
     enum mv_class exclude;
     bool pivot;
@@ -204,6 +205,7 @@ static void
 init_proc (struct crosstabs_proc *proc, struct dataset *ds)
 {
   const struct variable *wv = dict_get_weight (dataset_dict (ds));
+  proc->dict = dataset_dict (ds);
   proc->bad_warn = true;
   proc->variables = NULL;
   proc->n_variables = 0;
@@ -1191,7 +1193,7 @@ create_crosstab_table (struct crosstabs_proc *proc, struct pivot_table *pt)
       /* Insert the formatted value of the variable, then trim
          leading spaces in what was just inserted. */
       ofs = ds_length (&title);
-      s = data_out (&pt->const_values[i], var_get_print_format (var));
+      s = data_out (&pt->const_values[i], dict_get_encoding (proc->dict), var_get_print_format (var));
       ds_put_cstr (&title, s);
       free (s);
       ds_remove (&title, ofs, ss_cspan (ds_substr (&title, ofs, SIZE_MAX),
@@ -1523,7 +1525,7 @@ table_value_missing (struct crosstabs_proc *proc,
     }
 
   s.string = tab_alloc (table, print->w);
-  ss = data_out (v, print);
+  ss = data_out (v, dict_get_encoding (proc->dict), print);
   strcpy (s.string, ss);
   free (ss);
   s.length = print->w;
@@ -1559,7 +1561,7 @@ display_dimensions (struct crosstabs_proc *proc, struct pivot_table *pt,
    additionally suffixed with a letter `M'. */
 static void
 format_cell_entry (struct tab_table *table, int c, int r, double value,
-                   char suffix, bool mark_missing)
+                   char suffix, bool mark_missing, const struct dictionary *dict)
 {
   const struct fmt_spec f = {FMT_F, 10, 1};
   union value v;
@@ -1569,7 +1571,7 @@ format_cell_entry (struct tab_table *table, int c, int r, double value,
   s.length = 10;
   s.string = tab_alloc (table, 16);
   v.f = value;
-  ss = data_out (&v, &f);
+  ss = data_out (&v, dict_get_encoding (dict), &f);
   strcpy (s.string, ss);
   free (ss);
   while (*s.string == ' ')
@@ -1657,7 +1659,7 @@ display_crosstabulation (struct crosstabs_proc *proc, struct pivot_table *pt,
                 default:
                   NOT_REACHED ();
                 }
-              format_cell_entry (table, c, i, v, suffix, mark_missing);
+              format_cell_entry (table, c, i, v, suffix, mark_missing, proc->dict);
             }
 
           mp++;
@@ -1708,7 +1710,7 @@ display_crosstabulation (struct crosstabs_proc *proc, struct pivot_table *pt,
               NOT_REACHED ();
             }
 
-          format_cell_entry (table, pt->n_cols, 0, v, suffix, mark_missing);
+          format_cell_entry (table, pt->n_cols, 0, v, suffix, mark_missing, proc->dict);
           tab_next_row (table);
         }
     }
@@ -1758,7 +1760,7 @@ display_crosstabulation (struct crosstabs_proc *proc, struct pivot_table *pt,
               NOT_REACHED ();
             }
 
-          format_cell_entry (table, c, i, v, suffix, mark_missing);
+          format_cell_entry (table, c, i, v, suffix, mark_missing, proc->dict);
         }
       last_row = i;
     }
diff --git a/src/libpspp/i18n.c b/src/libpspp/i18n.c
index 60189ff76e..d443619ac5 100644
--- a/src/libpspp/i18n.c
+++ b/src/libpspp/i18n.c
@@ -28,6 +28,7 @@
 #include "assertion.h"
 #include "hmapx.h"
 #include "hash-functions.h"
+#include "pool.h"
 
 #include "i18n.h"
 
@@ -85,13 +86,21 @@ create_iconv (const char* tocode, const char* fromcode)
   return converter->conv;
 }
 
+char *
+recode_string (const char *to, const char *from,
+	       const char *text, int length)
+{
+  return recode_string_pool (to, from, text, length, NULL);
+}
+
+
 /* Return a string based on TEXT converted according to HOW.
    If length is not -1, then it must be the number of bytes in TEXT.
    The returned string must be freed when no longer required.
 */
 char *
-recode_string (const char *to, const char *from,
-	       const char *text, int length)
+recode_string_pool (const char *to, const char *from,
+	       const char *text, int length, struct pool *pool)
 {
   char *outbuf = 0;
   size_t outbufferlength;
@@ -121,7 +130,7 @@ recode_string (const char *to, const char *from,
     if ( outbufferlength > length)
       break;
 
-  outbuf = xmalloc(outbufferlength);
+  outbuf = pool_malloc (pool, outbufferlength);
   op = outbuf;
 
   outbytes = outbufferlength;
@@ -158,7 +167,7 @@ recode_string (const char *to, const char *from,
 	  case E2BIG:
 	    free (outbuf);
 	    outbufferlength <<= 1;
-	    outbuf = xmalloc (outbufferlength);
+	    outbuf = pool_malloc (pool, outbufferlength);
 	    op = outbuf;
 	    outbytes = outbufferlength;
 	    inbytes = length;
@@ -176,7 +185,7 @@ recode_string (const char *to, const char *from,
   if (outbytes == 0 )
     {
       char *const oldaddr = outbuf;
-      outbuf = xrealloc (outbuf, outbufferlength + 1);
+      outbuf = pool_realloc (pool, outbuf, outbufferlength + 1);
 
       op += (outbuf - oldaddr) ;
     }
diff --git a/src/libpspp/i18n.h b/src/libpspp/i18n.h
index 2c30a70012..9c8f7c1401 100644
--- a/src/libpspp/i18n.h
+++ b/src/libpspp/i18n.h
@@ -24,7 +24,12 @@ void  i18n_init (void);
 
 #define UTF8 "UTF-8"
 
-char * recode_string (const char *to, const char *from,
+struct pool;
+
+char *recode_string_pool (const char *to, const char *from,
+			  const char *text, int length, struct pool *pool);
+
+char *recode_string (const char *to, const char *from,
 		      const char *text, int len);
 
 
diff --git a/src/output/table.c b/src/output/table.c
index a86f407d5f..97d1611732 100644
--- a/src/output/table.c
+++ b/src/output/table.c
@@ -537,7 +537,7 @@ tab_value (struct tab_table *table, int c, int r, unsigned char opt,
     }
 #endif
 
-  contents = data_out_pool (v, f, table->container);
+  contents = data_out_pool (v, "FIXME", f, table->container);
 
   table->cc[c + r * table->cf] = ss_cstr (contents);
   table->ct[c + r * table->cf] = opt;
@@ -578,7 +578,7 @@ tab_fixed (struct tab_table *table, int c, int r, unsigned char opt,
 #endif
 
   double_value.f = val;
-  s = data_out_pool (&double_value, &f, table->container);
+  s = data_out_pool (&double_value, "FIXME", &f, table->container);
 
   cp = s;
   while (isspace ((unsigned char) *cp) && cp < &s[w])
@@ -629,7 +629,7 @@ tab_double (struct tab_table *table, int c, int r, unsigned char opt,
 #endif
 
   double_value.f = val;
-  s = data_out_pool (&double_value, fmt, table->container);
+  s = data_out_pool (&double_value, "FIXME", fmt, table->container);
 
   cp = s;
   while (isspace ((unsigned char) *cp) && cp < s + fmt->w)
diff --git a/src/ui/gui/compute-dialog.c b/src/ui/gui/compute-dialog.c
index 183aa31b4d..e779fba6d7 100644
--- a/src/ui/gui/compute-dialog.c
+++ b/src/ui/gui/compute-dialog.c
@@ -604,7 +604,6 @@ insert_source_row_into_text_view (GtkTreeIter iter,
   gint *idx;
   struct variable *var;
   GtkTreeIter dict_iter;
-  gchar *name;
   GtkTextBuffer *buffer;
 
   g_return_if_fail (GTK_IS_TEXT_VIEW (dest));
@@ -632,15 +631,10 @@ insert_source_row_into_text_view (GtkTreeIter iter,
 
   gtk_tree_path_free (path);
 
-  name = recode_string (UTF8, psppire_dict_encoding (dict),
-			var_get_name (var),
-			-1);
-
   buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dest));
 
   erase_selection (buffer);
 
-  gtk_text_buffer_insert_at_cursor (buffer, name, -1);
+  gtk_text_buffer_insert_at_cursor (buffer, var_get_name (var), -1);
 
-  g_free (name);
 }
diff --git a/src/ui/gui/dialog-common.c b/src/ui/gui/dialog-common.c
index 8d03bed161..5d52204ce5 100644
--- a/src/ui/gui/dialog-common.c
+++ b/src/ui/gui/dialog-common.c
@@ -114,15 +114,9 @@ cell_var_name (GtkTreeViewColumn *tree_column,
 	       gpointer data)
 {
   PsppireDict *dict = data;
-  struct variable *var;
-  gchar *name;
-
-  var = get_selected_variable (tree_model, iter, dict);
+  const struct variable *var = get_selected_variable (tree_model, iter, dict);
 
-  name = recode_string (UTF8, psppire_dict_encoding (dict),
-			var_get_name (var), -1);
-  g_object_set (cell, "text", name, NULL);
-  g_free (name);
+  g_object_set (cell, "text", var_get_name (var), NULL);
 }
 
 
diff --git a/src/ui/gui/dict-display.c b/src/ui/gui/dict-display.c
index d6b1bcd58c..1665d7ff3f 100644
--- a/src/ui/gui/dict-display.c
+++ b/src/ui/gui/dict-display.c
@@ -67,7 +67,6 @@ insert_source_row_into_entry (GtkTreeIter iter,
   gint *idx;
   struct variable *var;
   GtkTreeIter dict_iter;
-  gchar *name;
 
   g_return_if_fail (GTK_IS_ENTRY(dest));
 
@@ -81,10 +80,7 @@ insert_source_row_into_entry (GtkTreeIter iter,
 
   gtk_tree_path_free (path);
 
-  name = recode_string (UTF8, psppire_dict_encoding (PSPPIRE_DICT (dict)),
-			var_get_name (var), -1);
-  gtk_entry_set_text (GTK_ENTRY (dest),  name);
-  g_free (name);
+  gtk_entry_set_text (GTK_ENTRY (dest),  var_get_name (var));
 }
 
 
@@ -123,14 +119,13 @@ is_currently_in_entry (GtkTreeModel *model, GtkTreeIter *iter,
 		       PsppireSelector *selector)
 {
   gboolean result;
-  gchar *name;
   GtkTreeIter dict_iter;
   GtkTreeModel *dict;
   struct variable *var;
   gint dict_index;
   gint *indeces;
   GtkTreePath *path;
-  const gchar *text =   gtk_entry_get_text (GTK_ENTRY (selector->dest));
+  const gchar *text =  gtk_entry_get_text (GTK_ENTRY (selector->dest));
 
   get_base_model (model, iter, &dict, &dict_iter);
 
@@ -144,10 +139,7 @@ is_currently_in_entry (GtkTreeModel *model, GtkTreeIter *iter,
 
   gtk_tree_path_free (path);
 
-  name = recode_string (UTF8, psppire_dict_encoding (PSPPIRE_DICT (dict)),
-			var_get_name (var), -1);
-  result = ( 0 == strcmp (text, name));
-  g_free (name);
+  result = ( 0 == strcmp (text, var_get_name (var) ));
 
   return result;
 }
diff --git a/src/ui/gui/helper.c b/src/ui/gui/helper.c
index bec6716689..31633de9ff 100644
--- a/src/ui/gui/helper.c
+++ b/src/ui/gui/helper.c
@@ -49,11 +49,11 @@
 /* Formats a value according to FORMAT
    The returned string must be freed when no longer required */
 gchar *
-value_to_text (union value v, struct fmt_spec format)
+value_to_text (union value v, const struct dictionary *dict, struct fmt_spec format)
 {
   gchar *s = 0;
 
-  s = data_out (&v, &format);
+  s = data_out (&v, dict_get_encoding (dict),  &format);
   g_strchug (s);
 
   return s;
diff --git a/src/ui/gui/helper.h b/src/ui/gui/helper.h
index a6287ddaf1..0cd1f5557e 100644
--- a/src/ui/gui/helper.h
+++ b/src/ui/gui/helper.h
@@ -30,10 +30,11 @@
 void paste_syntax_in_new_window (const gchar *syntax);
 
 struct fmt_spec;
+struct dictionary;
 
 /* Formats a value according to FORMAT
    The returned string must be freed when no longer required */
-gchar * value_to_text (union value v, struct fmt_spec format);
+gchar * value_to_text (union value v, const struct dictionary *dict, struct fmt_spec format);
 
 
 gboolean text_to_value (const gchar *text, union value *v,
diff --git a/src/ui/gui/missing-val-dialog.c b/src/ui/gui/missing-val-dialog.c
index 8efbaf975d..9230b8a6e5 100644
--- a/src/ui/gui/missing-val-dialog.c
+++ b/src/ui/gui/missing-val-dialog.c
@@ -309,8 +309,9 @@ missing_val_dialog_show (struct missing_val_dialog *dialog)
       gchar *high_text;
       mv_get_range (&dialog->mvl, &low.f, &high.f);
 
-      low_text = value_to_text (low, *write_spec);
-      high_text = value_to_text (high, *write_spec);
+
+      low_text = value_to_text (low, dialog->dict, *write_spec);
+      high_text = value_to_text (high, dialog->dict,  *write_spec);
 
       gtk_entry_set_text (GTK_ENTRY (dialog->low), low_text);
       gtk_entry_set_text (GTK_ENTRY (dialog->high), high_text);
@@ -320,7 +321,7 @@ missing_val_dialog_show (struct missing_val_dialog *dialog)
       if ( mv_has_value (&dialog->mvl))
 	{
 	  gchar *text;
-	  text = value_to_text (*mv_get_value (&dialog->mvl, 0), *write_spec);
+	  text = value_to_text (*mv_get_value (&dialog->mvl, 0), dialog->dict, *write_spec);
 	  gtk_entry_set_text (GTK_ENTRY (dialog->discrete), text);
 	  g_free (text);
 	}
@@ -341,7 +342,7 @@ missing_val_dialog_show (struct missing_val_dialog *dialog)
 	    {
 	      gchar *text ;
 
-	      text = value_to_text (*mv_get_value (&dialog->mvl, i),
+	      text = value_to_text (*mv_get_value (&dialog->mvl, i), dialog->dict,
                                     *write_spec);
 	      gtk_entry_set_text (GTK_ENTRY (dialog->mv[i]), text);
 	      g_free (text);
diff --git a/src/ui/gui/missing-val-dialog.h b/src/ui/gui/missing-val-dialog.h
index 7dc079d731..bbf36f26bf 100644
--- a/src/ui/gui/missing-val-dialog.h
+++ b/src/ui/gui/missing-val-dialog.h
@@ -32,6 +32,9 @@ struct missing_val_dialog
   /* The variable whose missing values are to be updated */
   struct variable *pv;
 
+  /* The dictionary to which that value belongs */
+  const struct dictionary *dict;
+
   /* local copy */
   struct missing_values mvl;
 
diff --git a/src/ui/gui/psppire-data-editor.c b/src/ui/gui/psppire-data-editor.c
index b48ad2338b..a2ca1d8851 100644
--- a/src/ui/gui/psppire-data-editor.c
+++ b/src/ui/gui/psppire-data-editor.c
@@ -1646,13 +1646,13 @@ enum {
 
 /* Perform data_out for case CC, variable V, appending to STRING */
 static void
-data_out_g_string (GString *string, const struct variable *v,
+data_out_g_string (GString *string, const struct dictionary *dict, const struct variable *v,
 		   const struct ccase *cc)
 {
   const struct fmt_spec *fs = var_get_print_format (v);
   const union value *val = case_data (cc, v);
 
-  char *s = data_out (val, fs);
+  char *s = data_out (val, dict_get_encoding (dict), fs);
 
   g_string_append_len (string, s, fs->w);
 
@@ -1686,7 +1686,7 @@ clip_to_text (void)
       for (c = 0 ; c < var_cnt ; ++c)
 	{
 	  const struct variable *v = dict_get_var (clip_dict, c);
-	  data_out_g_string (string, v, cc);
+	  data_out_g_string (string, clip_dict, v, cc);
 	  if ( c < val_cnt - 1 )
 	    g_string_append (string, "\t");
 	}
@@ -1731,7 +1731,7 @@ clip_to_html (void)
 	{
 	  const struct variable *v = dict_get_var (clip_dict, c);
 	  g_string_append (string, "<td>");
-	  data_out_g_string (string, v, cc);
+	  data_out_g_string (string, clip_dict, v, cc);
 	  g_string_append (string, "</td>\n");
 	}
 
diff --git a/src/ui/gui/psppire-data-store.c b/src/ui/gui/psppire-data-store.c
index 13ad0cc6cd..0779512433 100644
--- a/src/ui/gui/psppire-data-store.c
+++ b/src/ui/gui/psppire-data-store.c
@@ -583,12 +583,15 @@ psppire_data_store_get_string (PsppireDataStore *store, glong row, glong column)
   char *text;
   const struct fmt_spec *fp ;
   const struct variable *pv ;
+  const struct dictionary *dict;
   union value v;
   int width;
 
   g_return_val_if_fail (store->dict, NULL);
   g_return_val_if_fail (store->datasheet, NULL);
 
+  dict = store->dict->dict;
+
   if (column >= psppire_dict_get_var_cnt (store->dict))
     return NULL;
 
@@ -614,17 +617,13 @@ psppire_data_store_get_string (PsppireDataStore *store, glong row, glong column)
       if (label)
         {
           value_destroy (&v, width);
-	  return recode_string (UTF8, psppire_dict_encoding (store->dict),
-				label, -1);
+	  return g_strdup (label);
         }
     }
 
   fp = var_get_write_format (pv);
 
-  /* Converts binary value V into printable form in the exactly
-     FP->W character in buffer S according to format specification
-     FP.  No null terminator is appended to the buffer.  */
-  text = data_out (&v, fp);
+  text = data_out (&v, dict_get_encoding (dict), fp);
 
   g_strchomp (text);
 
@@ -755,15 +754,9 @@ static const gchar null_var_name[]=N_("var");
 static gchar *
 get_row_button_label (const PsppireSheetModel *model, gint unit)
 {
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
-  gchar *s = g_strdup_printf (_("%d"), unit + FIRST_CASE_NUMBER);
-
-  gchar *text =  recode_string (UTF8, psppire_dict_encoding (ds->dict),
-				s, -1);
+  // PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
 
-  g_free (s);
-
-  return text;
+  return g_strdup_printf (_("%d"), unit + FIRST_CASE_NUMBER);
 }
 
 
diff --git a/src/ui/gui/psppire-dict.c b/src/ui/gui/psppire-dict.c
index d6d278f596..c82395f2eb 100644
--- a/src/ui/gui/psppire-dict.c
+++ b/src/ui/gui/psppire-dict.c
@@ -760,11 +760,8 @@ tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
     {
     case DICT_TVM_COL_NAME:
       {
-	gchar *name = recode_string (UTF8, psppire_dict_encoding (dict),
-				     var_get_name (var), -1);
 	g_value_init (value, G_TYPE_STRING);
-	g_value_set_string (value, name);
-	g_free (name);
+	g_value_set_string (value, var_get_name (var));
       }
       break;
     case DICT_TVM_COL_VAR:
diff --git a/src/ui/gui/psppire-dictview.c b/src/ui/gui/psppire-dictview.c
index f63ea0ba6f..243d907826 100644
--- a/src/ui/gui/psppire-dictview.c
+++ b/src/ui/gui/psppire-dictview.c
@@ -340,19 +340,12 @@ var_description_cell_data_func (GtkTreeViewColumn *col,
 				     "<span stretch=\"condensed\">%s</span>",
 				     var_get_label (var));
 
-      char *utf8 = recode_string (UTF8, psppire_dict_encoding (dict),
-				  text, -1);
-
+      g_object_set (cell, "markup", text, NULL);
       g_free (text);
-      g_object_set (cell, "markup", utf8, NULL);
-      g_free (utf8);
     }
   else
     {
-      char *name = recode_string (UTF8, psppire_dict_encoding (dict),
-				  var_get_name (var), -1);
-      g_object_set (cell, "text", name, NULL);
-      g_free (name);
+      g_object_set (cell, "text", var_get_name (var), NULL);
     }
 }
 
@@ -439,7 +432,7 @@ set_tooltip_for_variable (GtkTreeView  *treeview,
     return FALSE;
 
   {
-    gchar *tip ;
+    const gchar *tip ;
     GtkTreeModel *m;
     PsppireDict *dict;
 
@@ -447,15 +440,11 @@ set_tooltip_for_variable (GtkTreeView  *treeview,
     dict = PSPPIRE_DICT (m);
 
     if ( PSPPIRE_DICT_VIEW (treeview)->prefer_labels )
-      tip = recode_string (UTF8, psppire_dict_encoding (dict),
-			   var_get_name (var), -1);
+      tip = var_get_name (var);
     else
-      tip = recode_string (UTF8, psppire_dict_encoding (dict),
-			   var_get_label (var), -1);
+      tip = var_get_label (var);
 
     gtk_tooltip_set_text (tooltip, tip);
-
-    g_free (tip);
   }
 
   return TRUE;
diff --git a/src/ui/gui/psppire-var-sheet.c b/src/ui/gui/psppire-var-sheet.c
index 3ebea2ea18..c0d0059bd7 100644
--- a/src/ui/gui/psppire-var-sheet.c
+++ b/src/ui/gui/psppire-var-sheet.c
@@ -384,6 +384,8 @@ var_sheet_change_active_cell (PsppireVarSheet *vs,
 	vs->missing_val_dialog->pv =
 	  psppire_var_store_get_var (var_store, row);
 
+	vs->missing_val_dialog->dict = var_store->dict->dict;
+
 	g_signal_connect_swapped (customEntry,
 				  "clicked",
 				  G_CALLBACK (missing_val_dialog_show),
diff --git a/src/ui/gui/psppire-var-store.c b/src/ui/gui/psppire-var-store.c
index 66da770643..991fdf467d 100644
--- a/src/ui/gui/psppire-var-store.c
+++ b/src/ui/gui/psppire-var-store.c
@@ -696,7 +696,7 @@ text_for_column (PsppireVarStore *vs,
 	    g_assert (vl);
 
 	    {
-	      gchar *const vstr = value_to_text (vl->value, *write_spec);
+	      gchar *const vstr = value_to_text (vl->value, dict->dict, *write_spec);
 
 	      return g_strdup_printf ( "{%s,\"%s\"}_", vstr, val_lab_get_label (vl));
 	    }
diff --git a/src/ui/gui/text-data-import-dialog.c b/src/ui/gui/text-data-import-dialog.c
index 8eebf97756..330d284741 100644
--- a/src/ui/gui/text-data-import-dialog.c
+++ b/src/ui/gui/text-data-import-dialog.c
@@ -1768,7 +1768,7 @@ parse_field (struct import_assistant *ia,
     }
   if (outputp != NULL)
     {
-      *outputp = data_out (&val, &out);
+      *outputp = data_out (&val, dict_get_encoding (ia->formats.dict),  &out);
     }
   value_destroy (&val, var_get_width (var));
 
diff --git a/src/ui/gui/val-labs-dialog.c b/src/ui/gui/val-labs-dialog.c
index 0b87d8bb64..04f9534d55 100644
--- a/src/ui/gui/val-labs-dialog.c
+++ b/src/ui/gui/val-labs-dialog.c
@@ -345,7 +345,7 @@ on_select_row (GtkTreeView *treeview, gpointer data)
   gchar *text;
 
   get_selected_tuple (dialog, &value, &label);
-  text = value_to_text (value, *var_get_write_format (dialog->pv));
+  text = value_to_text (value, NULL, *var_get_write_format (dialog->pv));
 
   g_signal_handler_block (GTK_ENTRY (dialog->value_entry),
 			 dialog->value_handler_id);
@@ -497,7 +497,7 @@ repopulate_dialog (struct val_labs_dialog *dialog)
       const struct val_lab *vl = labels[i];
 
       gchar *const vstr  =
-	value_to_text (vl->value,
+	value_to_text (vl->value, NULL,
 		      *var_get_write_format (dialog->pv));
 
       gchar *const text = g_strdup_printf ("%s = \"%s\"",
diff --git a/src/ui/gui/var-display.c b/src/ui/gui/var-display.c
index b615fe522b..fcec1e8f82 100644
--- a/src/ui/gui/var-display.c
+++ b/src/ui/gui/var-display.c
@@ -45,15 +45,14 @@ missing_values_to_string (const PsppireDict *dict, const struct variable *pv, GE
 	  gint i;
 	  for (i = 0 ; i < n; ++i )
 	    {
-	      mv[i] = value_to_text (*mv_get_value (miss, i), *fmt);
+	      mv[i] = value_to_text (*mv_get_value (miss, i), dict->dict, *fmt);
 	      if ( i > 0 )
 		g_string_append (gstr, ", ");
 	      g_string_append (gstr, mv[i]);
 	      g_free (mv[i]);
 	    }
-	  s = recode_string (UTF8, psppire_dict_encoding (dict),
-			     gstr->str, gstr->len);
-	  g_string_free (gstr, TRUE);
+	  s = gstr->str;
+	  g_string_free (gstr, FALSE);
 	}
       else
 	{
@@ -62,8 +61,8 @@ missing_values_to_string (const PsppireDict *dict, const struct variable *pv, GE
 	  union value low, high;
 	  mv_get_range (miss, &low.f, &high.f);
 
-	  l = value_to_text (low, *fmt);
-	  h = value_to_text (high, *fmt);
+	  l = value_to_text (low, dict->dict, *fmt);
+	  h = value_to_text (high, dict->dict,*fmt);
 
 	  g_string_printf (gstr, "%s - %s", l, h);
 	  g_free (l);
@@ -73,15 +72,14 @@ missing_values_to_string (const PsppireDict *dict, const struct variable *pv, GE
 	    {
 	      gchar *ss = 0;
 
-	      ss = value_to_text (*mv_get_value (miss, 0), *fmt);
+	      ss = value_to_text (*mv_get_value (miss, 0), dict->dict, *fmt);
 
 	      g_string_append (gstr, ", ");
 	      g_string_append (gstr, ss);
 	      free (ss);
 	    }
-	  s = recode_string (UTF8, psppire_dict_encoding (dict),
-			     gstr->str, gstr->len);
-	  g_string_free (gstr, TRUE);
+	  s = gstr->str;
+	  g_string_free (gstr, FALSE);
 	}
 
       return s;
diff --git a/src/ui/gui/var-type-dialog.c b/src/ui/gui/var-type-dialog.c
index c433bf3b25..05ba5d3c9e 100644
--- a/src/ui/gui/var-type-dialog.c
+++ b/src/ui/gui/var-type-dialog.c
@@ -262,12 +262,12 @@ preview_custom (GtkWidget *w, gpointer data)
       union value v;
       v.f = 1234.56;
 
-      sample_text = value_to_text (v, dialog->fmt_l);
+      sample_text = value_to_text (v, NULL, dialog->fmt_l);
       gtk_label_set_text (GTK_LABEL (dialog->label_psample), sample_text);
       g_free (sample_text);
 
       v.f = -v.f;
-      sample_text = value_to_text (v, dialog->fmt_l);
+      sample_text = value_to_text (v, NULL, dialog->fmt_l);
       gtk_label_set_text (GTK_LABEL (dialog->label_nsample), sample_text);
       g_free (sample_text);
     }
diff --git a/src/ui/gui/variable-info-dialog.c b/src/ui/gui/variable-info-dialog.c
index fa9d51011e..afa96615d5 100644
--- a/src/ui/gui/variable-info-dialog.c
+++ b/src/ui/gui/variable-info-dialog.c
@@ -40,26 +40,14 @@
 static const gchar none[] = N_("None");
 
 
-static gchar *
-name_to_string (const struct variable *var, PsppireDict *dict)
-{
-  const char *name = var_get_name (var);
-  g_assert (name);
-
-  return recode_string (UTF8, psppire_dict_encoding (dict),
-			name, -1);
-}
-
-
-static gchar *
-label_to_string (const struct variable *var, PsppireDict *dict)
+static const gchar *
+label_to_string (const struct variable *var)
 {
   const char *label = var_get_label (var);
 
-  if (! label) return g_strdup (none);
+  if (NULL == label) return g_strdup (none);
 
-  return recode_string (UTF8, psppire_dict_encoding (dict),
-			label, -1);
+  return label;
 }
 
 
@@ -82,16 +70,11 @@ populate_text (PsppireDictView *treeview, gpointer data)
 		NULL);
 
   gstring = g_string_sized_new (200);
-  text = name_to_string (var, dict);
-  g_string_assign (gstring, text);
-  g_free (text);
+  g_string_assign (gstring, var_get_name (var));
   g_string_append (gstring, "\n");
 
 
-  text = label_to_string (var, dict);
-  g_string_append_printf (gstring, _("Label: %s\n"), text);
-  g_free (text);
-
+  g_string_append_printf (gstring, _("Label: %s\n"), label_to_string (var));
   {
     const struct fmt_spec *fmt = var_get_print_format (var);
     char buffer[FMT_STRING_LEN_MAX + 1];
@@ -130,14 +113,10 @@ populate_text (PsppireDictView *treeview, gpointer data)
         {
           const struct val_lab *vl = labels[i];
 	  gchar *const vstr  =
-	    value_to_text (vl->value,  *var_get_print_format (var));
-
-	  text = recode_string (UTF8, psppire_dict_encoding (dict),
-				val_lab_get_label (vl), -1);
+	    value_to_text (vl->value,  dict->dict, *var_get_print_format (var));
 
-	  g_string_append_printf (gstring, _("%s %s\n"), vstr, text);
+	  g_string_append_printf (gstring, _("%s %s\n"), vstr, val_lab_get_label (vl));
 
-	  g_free (text);
 	  g_free (vstr);
 	}
       free (labels);
diff --git a/src/ui/syntax-gen.c b/src/ui/syntax-gen.c
index e853c56927..f063fa3965 100644
--- a/src/ui/syntax-gen.c
+++ b/src/ui/syntax-gen.c
@@ -150,7 +150,7 @@ syntax_gen_number (struct string *output,
       bool ok;
 
       v_in.f = number;
-      s = data_out (&v_in, format);
+      s = data_out (&v_in, "FIXME",  format);
       msg_disable ();
       ok = data_in (ss_cstr (s), LEGACY_NATIVE,
                     format->type, false, 0, 0, &v_out, 0);
-- 
2.30.2