Commit f0d6bd14 authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

fix bone headed indexing scheme. (xbase_close) : release the fmt.

2001-11-01  Jody Goldberg <jgoldberg@home.com>

	* xbase.c (record_get_field) : fix bone headed indexing scheme.
	(xbase_close) : release the fmt.
	(xbase_field_new) : renamed to make sense and supply a style for dates.

	* boot.c (xbase_field_as_value) : now that record_get_field is less
	  bizzare use a sane indexing scheme here to.  Support dates.
	  Use the field length so that strings don't magicly enclude the
	  entire record.
	(xbase_file_open) : use a nice sane indexing scheme here too.
parent 5f5030a6
2001-11-01 Jody Goldberg <jgoldberg@home.com>
* xbase.c (record_get_field) : fix bone headed indexing scheme.
(xbase_close) : release the fmt.
(xbase_field_new) : renamed to make sense and supply a style for dates.
* boot.c (xbase_field_as_value) : now that record_get_field is less
bizzare use a sane indexing scheme here to. Support dates.
Use the field length so that strings don't magicly enclude the
entire record.
(xbase_file_open) : use a nice sane indexing scheme here too.
2001-10-29 Jody Goldberg <jgoldberg@home.com> 2001-10-29 Jody Goldberg <jgoldberg@home.com>
* Release 0.74 * Release 0.74
......
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/** /**
* boot.c: XBase support for Gnumeric * boot.c: XBase support for Gnumeric
* *
...@@ -14,6 +15,10 @@ ...@@ -14,6 +15,10 @@
#include <plugin-util.h> #include <plugin-util.h>
#include <module-plugin-defs.h> #include <module-plugin-defs.h>
#include <sheet.h> #include <sheet.h>
#include <datetime.h>
#include <ranges.h>
#include <mstyle.h>
#include <sheet-style.h>
#include <libgnome/gnome-defs.h> #include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h> #include <libgnome/gnome-i18n.h>
...@@ -22,7 +27,7 @@ ...@@ -22,7 +27,7 @@
GNUMERIC_MODULE_PLUGIN_INFO_DECL; GNUMERIC_MODULE_PLUGIN_INFO_DECL;
void xbase_file_open (GnumFileOpener const *fo, IOContext *io_context, void xbase_file_open (GnumFileOpener const *fo, IOContext *io_context,
WorkbookView *wb_view, const char *filename); WorkbookView *wb_view, char const *filename);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN #if G_BYTE_ORDER == G_LITTLE_ENDIAN
...@@ -39,7 +44,7 @@ void xbase_file_open (GnumFileOpener const *fo, IOContext *io_context, ...@@ -39,7 +44,7 @@ void xbase_file_open (GnumFileOpener const *fo, IOContext *io_context,
#endif #endif
static double static double
xb_getdouble (const guint8 *p) xb_getdouble (guint8 const *p)
{ {
double d; double d;
int i; int i;
...@@ -68,11 +73,10 @@ xb_setdouble (guint8 *p, double d) ...@@ -68,11 +73,10 @@ xb_setdouble (guint8 *p, double d)
#endif #endif
static Value * static Value *
xbase_field_as_value (XBrecord *record, guint num) xbase_field_as_value (guint8 *content, XBfield *field)
{ {
gint8 *s = g_strdup (record_get_field (record, num)); guint8 *s = g_strndup (content, field->len);
Value *val; Value *val;
XBfield *field = record->file->format[num-1];
switch (field->type) { switch (field->type) {
case 'C': case 'C':
...@@ -101,10 +105,18 @@ xbase_field_as_value (XBrecord *record, guint num) ...@@ -101,10 +105,18 @@ xbase_field_as_value (XBrecord *record, guint num)
return value_new_string (str); return value_new_string (str);
} }
} }
case 'D': case 'D': {
val = value_new_string (s); /* double check that the date is stored according to spec */
int year, month, day;
if (sscanf (s, "%4d%2d%2d", &year, &month, &day)) {
GDate *date = g_date_new_dmy (day, month, year);
val = value_new_int (datetime_g_to_serial (date));
g_date_free (date);
} else
val = value_new_string (s);
g_free (s); g_free (s);
return val; return val;
}
case 'I': case 'I':
val = value_new_int (GINT32_FROM_LE (*(gint32 *)s)); val = value_new_int (GINT32_FROM_LE (*(gint32 *)s));
g_free (s); g_free (s);
...@@ -133,17 +145,18 @@ xbase_field_as_value (XBrecord *record, guint num) ...@@ -133,17 +145,18 @@ xbase_field_as_value (XBrecord *record, guint num)
void void
xbase_file_open (GnumFileOpener const *fo, IOContext *io_context, xbase_file_open (GnumFileOpener const *fo, IOContext *io_context,
WorkbookView *wb_view, const char *filename) WorkbookView *wb_view, char const *filename)
{ {
Workbook *wb = wb_view_workbook (wb_view); Workbook *wb;
XBfile *file; XBfile *file;
XBrecord *rec; XBrecord *record;
guint row, field; char *name;
char *name; Sheet *sheet = NULL;
Sheet *sheet = NULL; Cell *cell;
Cell *cell; Value *val;
Value *val; XBfield *field;
ErrorInfo *open_error; ErrorInfo *open_error;
guint row, i;
if ((file = xbase_open (filename, &open_error)) == NULL) { if ((file = xbase_open (filename, &open_error)) == NULL) {
gnumeric_io_error_info_set (io_context, error_info_new_str_with_details ( gnumeric_io_error_info_set (io_context, error_info_new_str_with_details (
...@@ -156,30 +169,38 @@ xbase_file_open (GnumFileOpener const *fo, IOContext *io_context, ...@@ -156,30 +169,38 @@ xbase_file_open (GnumFileOpener const *fo, IOContext *io_context,
*((gchar *) g_extension_pointer (name)) = '\0'; /* remove "dbf" */ *((gchar *) g_extension_pointer (name)) = '\0'; /* remove "dbf" */
rec = record_new (file); wb = wb_view_workbook (wb_view);
sheet = sheet_new (wb, g_basename (name)); sheet = sheet_new (wb, g_basename (name));
g_free (name); g_free (name);
workbook_sheet_attach (wb, sheet, NULL); workbook_sheet_attach (wb, sheet, NULL);
field = 0; i = 0;
while (field < file->fields) { for (i = 0 ; i < file->fields ; i++) {
cell = sheet_cell_fetch (sheet, field, 0); cell = sheet_cell_fetch (sheet, i, 0);
cell_set_text (cell, file->format[field++]->name); cell_set_text (cell, file->format [i]->name);
/* FIXME: apply StyleFont gnumeric-default_bold_font */ }
{
Range r;
MStyle *bold = mstyle_new ();
mstyle_set_font_bold (bold, TRUE);
sheet_style_apply_range (sheet,
range_init (&r, 0, 0, file->fields-1, 0), bold);
} }
record = record_new (file);
row = 1; row = 1;
do { do {
field = 0; for (i = 0; i < file->fields ; i++) {
while (field < file->fields) { field = record->file->format [i];
cell = sheet_cell_fetch (sheet, field, row); val = xbase_field_as_value (
val = xbase_field_as_value (rec, ++field); record_get_field (record, i), field);
cell_set_value (cell, val, NULL); cell = sheet_cell_fetch (sheet, i, row);
cell_set_value (cell, val, field->fmt);
} }
row++; row++;
} while (record_seek (rec, SEEK_CUR, 1)); } while (record_seek (record, SEEK_CUR, 1));
record_free (rec); record_free (record);
xbase_close (file); xbase_close (file);
sheet_flag_recompute_spans (sheet); sheet_flag_recompute_spans (sheet);
......
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
#include <config.h> #include <config.h>
#include "xbase.h" #include "xbase.h"
#include <format.h> #include <format.h>
#include <formats.h>
#include <gutils.h> #include <gutils.h>
#include <io-context.h> #include <io-context.h>
...@@ -9,13 +11,13 @@ ...@@ -9,13 +11,13 @@
#define XBASE_DEBUG 0 #define XBASE_DEBUG 0
static const char *field_types = "CNLDMF?BGPYTI"; static char const * const field_types = "CNLDMF?BGPYTI";
#if XBASE_DEBUG > 0 #if XBASE_DEBUG > 0
static const char *field_type_descriptions [] = { /* FIXME: fix array size from field_types*/ static char const * const field_type_descriptions [] = {
"Character", "Number", "Logical", "Date", "Memo", "Floating point", "Character", "Number", "Logical", "Date", "Memo", "Floating point",
"Character name variable", "Binary", "General", "Picture", "Currency", "Character name variable", "Binary", "General", "Picture", "Currency",
"DateTime", "Integer" "DateTime", "Integer"
}; };
#endif #endif
...@@ -81,11 +83,11 @@ record_free (XBrecord *record) ...@@ -81,11 +83,11 @@ record_free (XBrecord *record)
* Points to binary data for num'th field in record's data. * Points to binary data for num'th field in record's data.
*/ */
guint8 * guint8 *
record_get_field (const XBrecord *record, guint num) record_get_field (XBrecord const *record, guint num)
{ {
if (num > record->file->fields) if (num >= record->file->fields)
return NULL; return NULL;
return record->data + record->file->format[num-1]->pos; return record->data + record->file->format [num]->pos;
} }
static gboolean static gboolean
...@@ -96,7 +98,6 @@ xbase_read_header (XBfile *x) ...@@ -96,7 +98,6 @@ xbase_read_header (XBfile *x)
g_warning ("Header short"); g_warning ("Header short");
return TRUE; return TRUE;
} }
fprintf (stderr, "Version:\t");
switch (hdr[0]) { /* FIXME: assuming dBASE III+, not IV */ switch (hdr[0]) { /* FIXME: assuming dBASE III+, not IV */
case 0x02: case 0x02:
fprintf (stderr, "FoxBase\n"); fprintf (stderr, "FoxBase\n");
...@@ -160,18 +161,18 @@ xbase_read_header (XBfile *x) ...@@ -160,18 +161,18 @@ xbase_read_header (XBfile *x)
} }
static XBfield * static XBfield *
xbase_read_field (XBfile *file) xbase_field_new (XBfile *file)
{ {
XBfield *ans; XBfield *field;
guint8 buf[33]; guint8 buf[33];
char *p; char *p;
if (fread(buf, sizeof(buf[0]), 2, file->f) != 2) { /* 1 byte out ? */ if (fread (buf, sizeof (guint8), 2, file->f) != 2) { /* 1 byte out ? */
g_warning ("xbase_read_field: fread error"); g_warning ("xbase_field_new: fread error");
return NULL; return NULL;
} else if (buf[0] == 0x0D || buf[0] == 0) { /* field array terminator */ } else if (buf[0] == 0x0D || buf[0] == 0) { /* field array terminator */
if (buf[1] == 0) { /* FIXME: crude test, not in spec */ if (buf[1] == 0) { /* FIXME: crude test, not in spec */
if (fseek(file->f, 263, SEEK_CUR)) /* skip DBC */ if (fseek(file->f, 263, SEEK_CUR)) /* skip DBC */
g_warning ("xbase_read_field: fseek error"); g_warning ("xbase_field_new: fseek error");
} }
file->offset = ftell (file->f); file->offset = ftell (file->f);
return NULL; return NULL;
...@@ -184,31 +185,37 @@ xbase_read_field (XBfile *file) ...@@ -184,31 +185,37 @@ xbase_read_field (XBfile *file)
fprintf (stderr, "Field:\t'%s'\n", buf); fprintf (stderr, "Field:\t'%s'\n", buf);
#endif #endif
ans = g_new (XBfield, 1); field = g_new (XBfield, 1);
ans->len = buf[16]; field->len = buf[16];
strncpy(ans->name, buf, 10); strncpy(field->name, buf, 10);
ans->name[10] = '\0'; field->name[10] = '\0';
if ((p = strchr (field_types, ans->type = buf[11])) == NULL) if ((p = strchr (field_types, field->type = buf[11])) == NULL)
g_warning ("Unrecognised field type '%c'", ans->type); g_warning ("Unrecognised field type '%c'", field->type);
#if XBASE_DEBUG > 0 #if XBASE_DEBUG > 0
else else
fprintf (stderr, "Type:\t%c (%s)\n", ans->type, fprintf (stderr, "Type:\t%c (%s)\n", field->type,
field_type_descriptions [p-field_types]); field_type_descriptions [p-field_types]);
fprintf (stderr, "Data address:\t0x%.8X\n", gnumeric_get_le_uint32 (buf + 12)); fprintf (stderr, "Data address:\t0x%.8X\n", gnumeric_get_le_uint32 (buf + 12));
fprintf (stderr, "Length:\t%d\n", ans->len); fprintf (stderr, "Length:\t%d\n", field->len);
fprintf (stderr, "Decimal count:\t%d\n", buf[17]); fprintf (stderr, "Decimal count:\t%d\n", buf[17]);
#endif #endif
if (file->fields) { if (file->fields) {
XBfield *tmp = file->format[file->fields-1]; XBfield *tmp = file->format[file->fields-1];
ans->pos = tmp->pos + tmp->len; field->pos = tmp->pos + tmp->len;
} else } else
ans->pos = 0; field->pos = 0;
return ans; /* FIXME: use more of buf if needed ? */
if (field->type == 'D')
field->fmt = style_format_new_XL (cell_formats [FMT_DATE][0], FALSE);
else
field->fmt = NULL;
return field; /* FIXME: use more of buf if needed ? */
} }
XBfile * XBfile *
xbase_open (const char *filename, ErrorInfo **ret_error) xbase_open (char const *filename, ErrorInfo **ret_error)
{ {
FILE *f; FILE *f;
XBfile *ans; XBfile *ans;
...@@ -228,7 +235,7 @@ xbase_open (const char *filename, ErrorInfo **ret_error) ...@@ -228,7 +235,7 @@ xbase_open (const char *filename, ErrorInfo **ret_error)
* and handle errors */ * and handle errors */
ans->fields = 0; ans->fields = 0;
ans->format = NULL; ans->format = NULL;
while ((field = xbase_read_field (ans)) != NULL) { while ((field = xbase_field_new (ans)) != NULL) {
ans->format = g_renew (XBfield *, ans->format, ans->fields + 1); ans->format = g_renew (XBfield *, ans->format, ans->fields + 1);
/* FIXME: allocate number of field formats from file size? */ /* FIXME: allocate number of field formats from file size? */
ans->format[ans->fields++] = field; ans->format[ans->fields++] = field;
...@@ -241,10 +248,13 @@ xbase_close (XBfile *x) ...@@ -241,10 +248,13 @@ xbase_close (XBfile *x)
{ {
unsigned i; unsigned i;
fprintf (stderr, "Closing Xbase file\n");
fclose (x->f); fclose (x->f);
for (i = 0; i < x->fields; i++) for (i = 0; i < x->fields; i++) {
g_free (x->format[i]); XBfield *field = x->format[i];
if (field->fmt != NULL)
style_format_unref (field->fmt);
g_free (field);
}
g_free (x->format); g_free (x->format);
g_free (x); g_free (x);
} }
...@@ -10,6 +10,7 @@ typedef struct { /* field format */ ...@@ -10,6 +10,7 @@ typedef struct { /* field format */
guint8 type; /* type (single ASCII char) */ guint8 type; /* type (single ASCII char) */
guint8 len; /* byte length */ guint8 len; /* byte length */
guint pos; /* position in record */ guint pos; /* position in record */
StyleFormat *fmt;
} XBfield; } XBfield;
typedef struct { /* database instance */ typedef struct { /* database instance */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment