variable: Introduce and use new function var_get_encoding().
[pspp] / src / data / sys-file-writer.c
index c1ff9a83a212fac17bf2767cadbc92ef1feb1581..0d93bd12f012e678cde6f1c00db793987124b67d 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -31,6 +31,7 @@
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
 #include <libpspp/str.h>
+#include <libpspp/i18n.h>
 #include <libpspp/version.h>
 
 #include <data/attributes.h>
@@ -95,8 +96,8 @@ static const struct casewriter_class sys_file_casewriter_class;
 
 static void write_header (struct sfm_writer *, const struct dictionary *);
 static void write_variable (struct sfm_writer *, const struct variable *);
-static void write_value_labels (struct sfm_writer *,
-                                struct variable *, int idx);
+static void write_value_labels (struct sfm_writer *, struct variable *,
+                                int idx);
 static void write_integer_info_record (struct sfm_writer *);
 static void write_float_info_record (struct sfm_writer *);
 
@@ -425,7 +426,7 @@ write_variable (struct sfm_writer *w, const struct variable *v)
   int width = var_get_width (v);
   int segment_cnt = sfm_width_to_segments (width);
   int seg0_width = sfm_segment_alloc_width (width, 0);
-  const struct missing_values *mv = var_get_missing_values (v);
+  struct missing_values mv;
   int i;
 
   /* Record type. */
@@ -440,7 +441,13 @@ write_variable (struct sfm_writer *w, const struct variable *v)
   /* Number of missing values.  If there is a range, then the
      range counts as 2 missing values and causes the number to be
      negated. */
-  write_int (w, mv_has_range (mv) ? -2 - mv_n_values (mv) : mv_n_values (mv));
+  mv_copy (&mv, var_get_missing_values (v));
+  if (mv_get_width (&mv) > 8)
+    mv_resize (&mv, 8);
+  if (mv_has_range (&mv))
+    write_int (w, -2 - mv_n_values (&mv));
+  else
+    write_int (w, mv_n_values (&mv));
 
   /* Print and write formats. */
   write_format (w, *var_get_print_format (v), seg0_width);
@@ -454,26 +461,24 @@ write_variable (struct sfm_writer *w, const struct variable *v)
   /* Value label. */
   if (var_has_label (v))
     {
-      const char *label = var_get_label (v);
-      size_t padded_len = ROUND_UP (MIN (strlen (label), 255), 4);
-      write_int (w, padded_len);
+      char *label = recode_string (var_get_encoding (v), UTF8, var_get_label (v), -1);
+      size_t label_len = MIN (strlen (label), 255);
+      size_t padded_len = ROUND_UP (label_len, 4);
+      write_int (w, label_len);
       write_string (w, label, padded_len);
+      free (label);
     }
 
   /* Write the missing values, if any, range first. */
-  if (mv_has_range (mv))
+  if (mv_has_range (&mv))
     {
       double x, y;
-      mv_get_range (mv, &x, &y);
+      mv_get_range (&mv, &x, &y);
       write_float (w, x);
       write_float (w, y);
     }
-  for (i = 0; i < mv_n_values (mv); i++)
-    {
-      union value value;
-      mv_get_value (mv, &value, i);
-      write_value (w, &value, seg0_width);
-    }
+  for (i = 0; i < mv_n_values (&mv); i++)
+    write_value (w, mv_get_value (&mv, i), mv_get_width (&mv));
 
   write_variable_continuation_records (w, seg0_width);
 
@@ -493,6 +498,8 @@ write_variable (struct sfm_writer *w, const struct variable *v)
 
       write_variable_continuation_records (w, seg_width);
     }
+
+  mv_destroy (&mv);
 }
 
 /* Writes the value labels for variable V having system file
@@ -520,13 +527,14 @@ write_value_labels (struct sfm_writer *w, struct variable *v, int idx)
   for (i = 0; i < n_labels; i++)
     {
       const struct val_lab *vl = labels[i];
-      const char *label = val_lab_get_label (vl);
+      char *label = recode_string (var_get_encoding (v), UTF8, val_lab_get_label (vl), -1);
       uint8_t len = MIN (strlen (label), 255);
 
       write_value (w, val_lab_get_value (vl), var_get_width (v));
       write_bytes (w, &len, 1);
       write_bytes (w, label, len);
       write_zeros (w, REM_RND_UP (len + 1, 8));
+      free (label);
     }
   free (labels);
 
@@ -770,11 +778,13 @@ write_longvar_table (struct sfm_writer *w, const struct dictionary *dict)
   for (i = 0; i < dict_get_var_cnt (dict); i++)
     {
       struct variable *v = dict_get_var (dict, i);
+      char *longname = recode_string (dict_get_encoding (dict), UTF8, var_get_name (v), -1);
 
       if (i)
         ds_put_char (&map, '\t');
       ds_put_format (&map, "%s=%s",
-                     var_get_short_name (v, 0), var_get_name (v));
+                     var_get_short_name (v, 0), longname);
+      free (longname);
     }
 
   write_int (w, 7);             /* Record type. */