work on PRINT encoding
[pspp] / src / data / gnumeric-reader.c
index f166ee6aba86f1a00acefb409c466e253635a574..56ebc3062aed3090ccf26748b8d96a105bac85dc 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009, 2010, 2011 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
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-
-
 #include <config.h>
 
-#include <libpspp/message.h>
-#include <libpspp/misc.h>
+#include "libpspp/message.h"
+#include "libpspp/misc.h"
 
-#include "minmax.h"
+#include "gl/minmax.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 #define N_(msgid) (msgid)
 
+#include "spreadsheet-reader.h"
 
 #if !GNM_SUPPORT
 
 struct casereader *
-gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
+gnumeric_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict)
 {
-  msg (ME, _("Support for Gnumeric files was not compiled into this installation of PSPP"));
+  msg (ME, _("Support for %s files was not compiled into this installation of PSPP"), "Gnumeric");
 
   return NULL;
 }
 
 #else
 
-#include <data/casereader-provider.h>
-#include <errno.h>
-#include <libpspp/str.h>
-#include <libpspp/i18n.h>
-#include <data/dictionary.h>
-#include <data/variable.h>
-#include <xalloc.h>
+#include "data/gnumeric-reader.h"
 
+#include <assert.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <libxml/xmlreader.h>
 #include <zlib.h>
-#include <stdbool.h>
-
-#include <data/case.h>
-#include <data/value.h>
 
-#include "gnumeric-reader.h"
-#include <data/identifier.h>
-#include <assert.h>
+#include "data/case.h"
+#include "data/casereader-provider.h"
+#include "data/dictionary.h"
+#include "data/identifier.h"
+#include "data/value.h"
+#include "data/variable.h"
+#include "libpspp/i18n.h"
+#include "libpspp/str.h"
 
-/* Default width of string variables. */
-#define GNUMERIC_DEFAULT_WIDTH 8
+#include "gl/xalloc.h"
 
 static void gnm_file_casereader_destroy (struct casereader *, void *);
 
@@ -75,73 +70,6 @@ static const struct casereader_class gnm_file_casereader_class =
     NULL,
   };
 
-/* Convert a string, which is an integer encoded in base26
-   IE, A=0, B=1, ... Z=25 to the integer it represents.
-   ... except that in this scheme, digits with an exponent
-   greater than 1 are implicitly incremented by 1, so
-   AA  = 0 + 1*26, AB = 1 + 1*26,
-   ABC = 2 + 2*26 + 1*26^2 ....
-*/
-static int
-pseudo_base26 (const char *str)
-{
-  int i;
-  int multiplier = 1;
-  int result = 0;
-  int len = strlen (str);
-
-  for ( i = len - 1 ; i >= 0; --i)
-    {
-      int mantissa = (str[i] - 'A');
-
-      if ( mantissa < 0 || mantissa > 25 )
-       return -1;
-
-      if ( i != len - 1)
-       mantissa++;
-
-      result += mantissa * multiplier;
-
-      multiplier *= 26;
-    }
-
-  return result;
-}
-
-
-
-/* Convert a cell reference in the form "A1:B2", to
-   integers.  A1 means column zero, row zero.
-   B1 means column 1 row 0. AA1 means column 26, row 0.
-*/
-static bool
-convert_cell_ref (const char *ref,
-                 int *col0, int *row0,
-                 int *coli, int *rowi)
-{
-  char startcol[5];
-  char stopcol [5];
-
-  int startrow;
-  int stoprow;
-
-  int n = sscanf (ref, "%4[a-zA-Z]%d:%4[a-zA-Z]%d",
-             startcol, &startrow,
-             stopcol, &stoprow);
-  if ( n != 4)
-    return false;
-
-  str_uppercase (startcol);
-  *col0 = pseudo_base26 (startcol);
-  str_uppercase (stopcol);
-  *coli = pseudo_base26 (stopcol);
-  *row0 = startrow - 1;
-  *rowi = stoprow - 1 ;
-
-  return true;
-}
-
-
 enum reader_state
   {
     STATE_INIT = 0,        /* Initial state */
@@ -181,9 +109,6 @@ struct gnumeric_reader
 
 static void process_node (struct gnumeric_reader *r);
 
-#define _xml(X) (const xmlChar *)(X)
-
-#define _xmlchar_to_int(X) atoi((const char *)X)
 
 static void
 gnm_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
@@ -320,21 +245,17 @@ static void
 convert_xml_string_to_value (struct ccase *c, const struct variable *var,
                             const xmlChar *xv)
 {
-  int n_bytes = 0;
   union value *v = case_data_rw (c, var);
 
-  const char *text = (const char *) xv;
-
-  if ( text)
-    n_bytes = MIN (var_get_width (var), strlen (text));
-
-  if ( var_is_alpha (var))
-    {
-      memcpy (value_str_rw (v, var_get_width (var)), text, n_bytes);
-    }
+  if (xv == NULL)
+    value_set_missing (v, var_get_width (var));
+  else if ( var_is_alpha (var))
+    value_copy_str_rpad (v, var_get_width (var), xv, ' ');
   else
     {
+      const char *text = CHAR_CAST (const char *, xv);
       char *endptr;
+
       errno = 0;
       v->f = strtod (text, &endptr);
       if ( errno != 0 || endptr == text)
@@ -350,7 +271,7 @@ struct var_spec
 };
 
 struct casereader *
-gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
+gnumeric_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict)
 {
   unsigned long int vstart = 0;
   int ret;
@@ -365,7 +286,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
   if ( NULL == gz)
     {
-      msg (ME, _("Error opening \"%s\" for reading as a Gnumeric file: %s."),
+      msg (ME, _("Error opening `%s' for reading as a Gnumeric file: %s."),
            gri->file_name, strerror (errno));
 
       goto error;
@@ -385,7 +306,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
                               &r->start_col, &r->start_row,
                               &r->stop_col, &r->stop_row))
        {
-         msg (SE, _("Invalid cell range \"%s\""),
+         msg (SE, _("Invalid cell range `%s'"),
               gri->cell_range);
          goto error;
        }
@@ -463,7 +384,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
       if ( r->node_type == XML_READER_TYPE_TEXT )
        {
          xmlChar *value = xmlTextReaderValue (r->xtr);
-         const char *text  = (const char *) value;
+         const char *text  = CHAR_CAST (const char *, value);
 
          if ( r->row < r->start_row)
            {
@@ -478,7 +399,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
              if (-1 ==  var_spec [idx].width )
                var_spec [idx].width = (gri->asw == -1) ?
-                 ROUND_UP (strlen(text), GNUMERIC_DEFAULT_WIDTH) : gri->asw;
+                 ROUND_UP (strlen(text), SPREADSHEET_DEFAULT_WIDTH) : gri->asw;
            }
 
          free (value);
@@ -501,27 +422,21 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
 
   /* Create the dictionary and populate it */
-  *dict = r->dict = dict_create ();
-
-  dict_set_encoding (r->dict, (const char *) xmlTextReaderConstEncoding (r->xtr));
+  *dict = r->dict = dict_create (
+    CHAR_CAST (const char *, xmlTextReaderConstEncoding (r->xtr)));
 
   for (i = 0 ; i < n_var_specs ; ++i )
     {
-      char name[VAR_NAME_LEN + 1];
+      char *name;
 
       /* Probably no data exists for this variable, so allocate a
         default width */
       if ( var_spec[i].width == -1 )
-       var_spec[i].width = GNUMERIC_DEFAULT_WIDTH;
-
-      if  ( ! dict_make_unique_var_name (r->dict, var_spec[i].name,
-                                        &vstart, name))
-       {
-         msg (ME, _("Cannot create variable name from %s"), var_spec[i].name);
-         goto error;
-       }
+       var_spec[i].width = SPREADSHEET_DEFAULT_WIDTH;
 
+      name = dict_make_unique_var_name (r->dict, var_spec[i].name, &vstart);
       dict_create_var (r->dict, name, var_spec[i].width);
+      free (name);
     }
 
   /* Create the first case, and cache it */
@@ -529,7 +444,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
   if ( n_var_specs ==  0 )
     {
-      msg (MW, _("Selected sheet or range of spreadsheet \"%s\" is empty."),
+      msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
            gri->file_name);
       goto error;
     }