Commit 719cf0f1 authored by Michael Meeks's avatar Michael Meeks

Major OLE re-structuring, split to separate library.

parent 75daada2
1999-05-08 Michael Meeks <michael@imaginator.com>
* src/Makefile.am (gnumeric_LDADD): Added libole2 library.
* configure.in (XML_CFLAGS): Updated to add excel/libole2
* src/sheet.h: Commented sheet_cell_get vs. _fetch.
* src/expr.c (do_expr_tree_unref, value_string, value_release),
......
1999-05-08 Michael Meeks <michael@imaginator.com>
* src/Makefile.am (gnumeric_LDADD): Added libole2 library.
* configure.in (XML_CFLAGS): Updated to add excel/libole2
* src/sheet.h: Commented sheet_cell_get vs. _fetch.
* src/expr.c (do_expr_tree_unref, value_string, value_release),
......
1999-05-08 Michael Meeks <michael@imaginator.com>
* src/Makefile.am (gnumeric_LDADD): Added libole2 library.
* configure.in (XML_CFLAGS): Updated to add excel/libole2
* src/sheet.h: Commented sheet_cell_get vs. _fetch.
* src/expr.c (do_expr_tree_unref, value_string, value_release),
......
1999-05-08 Michael Meeks <michael@imaginator.com>
* src/Makefile.am (gnumeric_LDADD): Added libole2 library.
* configure.in (XML_CFLAGS): Updated to add excel/libole2
* src/sheet.h: Commented sheet_cell_get vs. _fetch.
* src/expr.c (do_expr_tree_unref, value_string, value_release),
......
......@@ -160,6 +160,7 @@ corba-test/Makefile
plugins/Makefile
plugins/sample/Makefile
plugins/excel/Makefile
plugins/excel/libole2/Makefile
plugins/python/Makefile
plugins/perl/Makefile
plugins/perl/ext/Makefile.PL
......
1999-05-08 Michael Meeks <michael@imaginator.com>
* ms-biff.c (ms_biff_query_copy): Updated to use new
global ms_ole_stream_copy.
* Makefile.am: Split out 'ole' program, added libole2
subdir. Added ms-biff.c.
* libole2/ Created, moved ole.c, ms-ole.[ch] there.
1999-05-08 Michael Meeks <michael@imaginator.com>
* ole.c (main): Large re-structure, split out into smaller
functions.
* ms-formula.c (ms_excel_parse_formula): Hack at ARRAY
functionality...
......
......@@ -3,37 +3,40 @@ INCLUDES = \
-DGNUMERIC_VERSION=\""$(VERSION)"\" \
-I$(includedir) \
-I$(top_srcdir)/src \
-Ilibole2 \
$(GNOME_INCLUDEDIR)
noinst_LIBRARIES = libexcel.a
libexcel_a_SOURCES = \
boot.c \
boot.h \
ms-excel-biff.h \
ms-biff.h \
biff-types.h \
escher-types.h \
ms-escher.c \
ms-escher.h \
ms-excel.c \
ms-excel.h \
ms-formula.c \
ms-formula.h \
ms-obj.c \
ms-obj.h \
ms-ole.c \
ms-ole.h
libexcel_a_SOURCES = \
boot.c \
boot.h \
ms-excel-biff.h \
ms-biff.c \
ms-biff.h \
biff-types.h \
escher-types.h \
ms-escher.c \
ms-escher.h \
ms-excel.c \
ms-excel.h \
ms-formula.c \
ms-formula.h \
ms-obj.c \
ms-obj.h
bin_PROGRAMS = \
bin_PROGRAMS = \
ole
ole_SOURCES = \
ole_SOURCES = \
ole.c
ole_LDADD = \
ms-ole.o \
$(GNOME_LIBDIR) \
$(GNOME_LIBS) \
ole_LDADD = \
ms-biff.o \
libole2/libole2.a \
$(GNOME_LIBDIR) \
$(GNOME_LIBS) \
$(INTLLIBS)
SUBDIRS = libole2
1999-05-08 Michael Meeks <michael@imaginator.com>
* ms-ole.c: Moved all biff code into ../ms-biff.c
Removed odd includes.
(pps_get_text): Changed types to guint8 from BYTE.
(ms_ole_stream_copy): Created, and made global.
INCLUDES = \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGNUMERIC_VERSION=\""$(VERSION)"\" \
-I$(includedir) \
-I$(top_srcdir)/src \
$(GNOME_INCLUDEDIR)
noinst_LIBRARIES = libole2.a
libole2_a_SOURCES = \
ms-ole.c \
ms-ole.h
......@@ -15,8 +15,6 @@
#include <ctype.h>
#include <glib.h>
#include "ms-ole.h"
#include "ms-biff.h"
#include "biff-types.h"
/* Implementational detail - not for global header */
......@@ -215,12 +213,12 @@ dump (guint8 *ptr, guint32 len)
/* FIXME: This needs proper unicode support ! current support is a guess */
/* NB. Different from biff_get_text, looks like a bug ! */
static char *
pps_get_text (BYTE *ptr, int length)
pps_get_text (guint8 *ptr, int length)
{
int lp, skip;
char *ans;
guint16 c;
BYTE *inb;
guint8 *inb;
if (!length)
return 0;
......@@ -334,7 +332,7 @@ dump_allocation (MS_OLE *f)
/* Create a nice linear array and return count of the number in the array */
static int
read_link_array(MS_OLE *f, BBPtr first, BBPtr **array)
read_link_array (MS_OLE *f, BBPtr first, BBPtr **array)
{
BBPtr ptr = first;
int lp, num=0;
......@@ -635,15 +633,6 @@ dump_stream (MS_OLE_STREAM *s)
printf ("block %d, offset %d\n", get_block(s), get_offset(s));
}
static void
dump_biff (BIFF_QUERY *bq)
{
printf ("Opcode 0x%x length %d malloced? %d\nData:\n", bq->opcode, bq->length, bq->data_malloced);
if (bq->length>0)
dump (bq->data, bq->length);
dump_stream (bq->pos);
}
static void
extend_file (MS_OLE *f, int blocks)
{
......@@ -1212,10 +1201,8 @@ ms_ole_stream_open (MS_OLE_DIRECTORY *d, char mode)
return s;
}
/* FIXME: This needs to be more cunning and have new write / read
functions that inser CONTINUE records etc. */
static MS_OLE_STREAM *
ms_ole_stream_duplicate (MS_OLE_STREAM *s)
MS_OLE_STREAM *
ms_ole_stream_copy (MS_OLE_STREAM *s)
{
MS_OLE_STREAM *ans = g_new (MS_OLE_STREAM, 1);
memcpy (ans, s, sizeof(MS_OLE_STREAM));
......@@ -1231,16 +1218,23 @@ ms_ole_stream_close (MS_OLE_STREAM *s)
}
}
/* You probably arn't too interested in the root directory anyway
but this is first */
MS_OLE_DIRECTORY *
ms_ole_directory_new (MS_OLE *f)
ms_ole_directory_get_root (MS_OLE *f)
{
MS_OLE_DIRECTORY *d = g_new0 (MS_OLE_DIRECTORY, 1);
d->file = f;
d->pps = PPS_ROOT_BLOCK;
d->primary_entry = PPS_ROOT_BLOCK;
d->name = PPS_NAME(f, d->pps);
return d;
}
/* You probably arn't too interested in the root directory anyway
but this is first */
MS_OLE_DIRECTORY *
ms_ole_directory_new (MS_OLE *f)
{
MS_OLE_DIRECTORY *d = ms_ole_directory_get_root (f);
ms_ole_directory_enter (d);
return d;
}
......@@ -1447,225 +1441,3 @@ ms_ole_directory_destroy (MS_OLE_DIRECTORY *d)
if (d)
g_free (d);
}
BIFF_QUERY *
ms_biff_query_new (MS_OLE_STREAM *ptr)
{
BIFF_QUERY *bq ;
if (!ptr)
return 0;
bq = g_new0 (BIFF_QUERY, 1);
bq->opcode = 0;
bq->length = 0;
bq->data_malloced = 0;
bq->pos = ptr;
bq->num_merges = 0;
#if OLE_DEBUG > 0
dump_biff(bq);
#endif
return bq;
}
BIFF_QUERY *
ms_biff_query_copy (const BIFF_QUERY *p)
{
BIFF_QUERY *bf = g_new (BIFF_QUERY, 1);
memcpy (bf, p, sizeof (BIFF_QUERY));
if (p->data_malloced)
{
bf->data = (guint8 *)g_malloc (p->length);
memcpy (bf->data, p->data, p->length);
}
bf->pos=ms_ole_stream_duplicate (p->pos);
return bf;
}
static int
ms_biff_merge_continues (BIFF_QUERY *bq, guint32 len)
{
GArray *contin;
guint8 tmp[4];
guint32 lp, total_len;
guint8 *d;
typedef struct {
guint8 *data;
guint32 length;
} chunk_t;
chunk_t chunk;
contin = g_array_new (0,1,sizeof(chunk_t));
/* First block: already got */
chunk.length = bq->length;
if (bq->data_malloced)
chunk.data = bq->data;
else {
chunk.data = g_new (guint8, bq->length);
memcpy (chunk.data, bq->data, bq->length);
}
total_len = chunk.length;
g_array_append_val (contin, chunk);
/* Subsequent continue blocks */
chunk.length = len;
do {
if (bq->pos->position >= bq->pos->size)
return 0;
chunk.data = g_new (guint8, chunk.length);
if (!bq->pos->read_copy (bq->pos, chunk.data, chunk.length))
return 0;
#if OLE_DEBUG > 8
printf ("Read raw : 0x%x -> 0x%x\n", chunk.data[0],
chunk.data[chunk.length-1]);
#endif
tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
bq->pos->read_copy (bq->pos, tmp, 4);
total_len += chunk.length;
g_array_append_val (contin, chunk);
chunk.length = BIFF_GETWORD (tmp+2);
bq->num_merges++;
} while ((BIFF_GETWORD(tmp) & 0xff) == BIFF_CONTINUE);
bq->pos->lseek (bq->pos, -4, MS_OLE_SEEK_CUR); /* back back off */
bq->data = g_malloc (total_len);
if (!bq->data)
return 0;
bq->length = total_len;
d = bq->data;
bq->data_malloced = 1;
for (lp=0;lp<contin->len;lp++) {
chunk = g_array_index (contin, chunk_t, lp);
#if OLE_DEBUG > 8
printf ("Copying block stats with 0x%x ends with 0x%x len 0x%x\n",
chunk.data[0], chunk.data[chunk.length-1], chunk.length);
g_assert ((d-bq->data)+chunk.length<=total_len);
#endif
memcpy (d, chunk.data, chunk.length);
d+=chunk.length;
g_free (chunk.data);
}
g_array_free (contin, 1);
#if OLE_DEBUG > 2
printf ("MERGE %d CONTINUES... len 0x%x\n", contin->len, len);
printf ("Biff read code 0x%x, length %d\n", bq->opcode, bq->length);
dump_biff (bq);
#endif
return 1;
}
void
ms_biff_query_unmerge (BIFF_QUERY *bq)
{
if (!bq || !bq->num_merges)
return;
bq->pos->lseek (bq->pos, -(4*(bq->num_merges+1)
+ bq->length), MS_OLE_SEEK_CUR);
ms_biff_query_next_merge (bq, FALSE);
}
/**
* Returns 0 if has hit end
**/
int
ms_biff_query_next (BIFF_QUERY *bq)
{
return ms_biff_query_next_merge (bq, TRUE);
}
/**
* Returns 0 if has hit end
**/
int
ms_biff_query_next_merge (BIFF_QUERY *bq, gboolean do_merge)
{
guint8 tmp[4];
int ans=1;
if (!bq || bq->pos->position >= bq->pos->size)
return 0;
if (bq->data_malloced) {
bq->num_merges = 0;
g_free (bq->data);
bq->data_malloced = 0;
}
bq->streamPos = bq->pos->position;
if (!bq->pos->read_copy (bq->pos, tmp, 4))
return 0;
bq->opcode = BIFF_GETWORD (tmp);
bq->length = BIFF_GETWORD (tmp+2);
bq->ms_op = (bq->opcode>>8);
bq->ls_op = (bq->opcode&0xff);
if (!(bq->data = bq->pos->read_ptr(bq->pos, bq->length))) {
bq->data = g_new0 (guint8, bq->length);
if (!bq->pos->read_copy(bq->pos, bq->data, bq->length)) {
ans = 0;
g_free(bq->data);
bq->length = 0;
} else
bq->data_malloced = 1;
}
if (ans && do_merge &&
bq->pos->read_copy (bq->pos, tmp, 4)) {
if ((BIFF_GETWORD(tmp) & 0xff) == BIFF_CONTINUE)
return ms_biff_merge_continues (bq, BIFF_GETWORD(tmp+2));
bq->pos->lseek (bq->pos, -4, MS_OLE_SEEK_CUR); /* back back off */
#if OLE_DEBUG > 4
printf ("Backed off\n");
#endif
}
#if OLE_DEBUG > 2
printf ("Biff read code 0x%x, length %d\n", bq->opcode, bq->length);
dump_biff (bq);
#endif
if (!bq->length) {
bq->data = 0;
return 1;
}
return (ans);
}
void
ms_biff_query_destroy (BIFF_QUERY *bq)
{
if (bq)
{
if (bq->data_malloced)
g_free (bq->data);
g_free (bq);
}
}
/* FIXME: Too nasty ! */
MS_OLE_STREAM *
ms_biff_query_data_to_stream (BIFF_QUERY *bq)
{
MS_OLE_STREAM *ans=ms_ole_stream_duplicate (bq->pos);
/* ans->advance(ans, -bq->length);
This will never work !
*/
/* Hack size down to biff length */
/* Can't be done non-destructively ! sod ! */
/* Should cut the length down a lot, hope we can know where
the end is somehow */
return ans;
}
#if G_BYTE_ORDER == G_BIG_ENDIAN
double biff_getdouble(guint8 *p)
{
double d;
int i;
guint8 *t = (guint8 *)&d;
int sd = sizeof (d);
for (i = 0; i < sd; i++)
t[i] = p[sd - 1 - i];
return d;
}
#endif
/**
* ms-biff.c: MS Excel Biff support...
*
* Author:
* Michael Meeks (michael@imaginator.com)
**/
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <malloc.h>
#include <assert.h>
#include <ctype.h>
#include <glib.h>
#include "ms-ole.h"
#include "ms-biff.h"
#include "biff-types.h"
#define BIFF_DEBUG 0
static void
dump_biff (BIFF_QUERY *bq)
{
printf ("Opcode 0x%x length %d malloced? %d\nData:\n", bq->opcode, bq->length, bq->data_malloced);
if (bq->length>0)
dump (bq->data, bq->length);
/* dump_stream (bq->pos); */
}
BIFF_QUERY *
ms_biff_query_new (MS_OLE_STREAM *ptr)
{
BIFF_QUERY *bq ;
if (!ptr)
return 0;
bq = g_new0 (BIFF_QUERY, 1);
bq->opcode = 0;
bq->length = 0;
bq->data_malloced = 0;
bq->pos = ptr;
bq->num_merges = 0;
#if BIFF_DEBUG > 0
dump_biff(bq);
#endif
return bq;
}
BIFF_QUERY *
ms_biff_query_copy (const BIFF_QUERY *p)
{
BIFF_QUERY *bf = g_new (BIFF_QUERY, 1);
memcpy (bf, p, sizeof (BIFF_QUERY));
if (p->data_malloced)
{
bf->data = (guint8 *)g_malloc (p->length);
memcpy (bf->data, p->data, p->length);
}
bf->pos=ms_ole_stream_copy (p->pos);
return bf;
}
static int
ms_biff_merge_continues (BIFF_QUERY *bq, guint32 len)
{
GArray *contin;
guint8 tmp[4];
guint32 lp, total_len;
guint8 *d;
typedef struct {
guint8 *data;
guint32 length;
} chunk_t;
chunk_t chunk;
contin = g_array_new (0,1,sizeof(chunk_t));
/* First block: already got */
chunk.length = bq->length;
if (bq->data_malloced)
chunk.data = bq->data;
else {
chunk.data = g_new (guint8, bq->length);
memcpy (chunk.data, bq->data, bq->length);
}
total_len = chunk.length;
g_array_append_val (contin, chunk);
/* Subsequent continue blocks */
chunk.length = len;
do {
if (bq->pos->position >= bq->pos->size)
return 0;
chunk.data = g_new (guint8, chunk.length);
if (!bq->pos->read_copy (bq->pos, chunk.data, chunk.length))
return 0;
#if BIFF_DEBUG > 8
printf ("Read raw : 0x%x -> 0x%x\n", chunk.data[0],
chunk.data[chunk.length-1]);
#endif
tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
bq->pos->read_copy (bq->pos, tmp, 4);
total_len += chunk.length;
g_array_append_val (contin, chunk);
chunk.length = BIFF_GETWORD (tmp+2);
bq->num_merges++;
} while ((BIFF_GETWORD(tmp) & 0xff) == BIFF_CONTINUE);
bq->pos->lseek (bq->pos, -4, MS_OLE_SEEK_CUR); /* back back off */
bq->data = g_malloc (total_len);
if (!bq->data)
return 0;
bq->length = total_len;
d = bq->data;
bq->data_malloced = 1;
for (lp=0;lp<contin->len;lp++) {
chunk = g_array_index (contin, chunk_t, lp);
#if BIFF_DEBUG > 8
printf ("Copying block stats with 0x%x ends with 0x%x len 0x%x\n",
chunk.data[0], chunk.data[chunk.length-1], chunk.length);
g_assert ((d-bq->data)+chunk.length<=total_len);
#endif
memcpy (d, chunk.data, chunk.length);
d+=chunk.length;
g_free (chunk.data);
}
g_array_free (contin, 1);
#if BIFF_DEBUG > 2
printf ("MERGE %d CONTINUES... len 0x%x\n", contin->len, len);
printf ("Biff read code 0x%x, length %d\n", bq->opcode, bq->length);
dump_biff (bq);
#endif
return 1;
}
void
ms_biff_query_unmerge (BIFF_QUERY *bq)
{
if (!bq || !bq->num_merges)
return;
bq->pos->lseek (bq->pos, -(4*(bq->num_merges+1)
+ bq->length), MS_OLE_SEEK_CUR);
ms_biff_query_next_merge (bq, FALSE);
}
/**
* Returns 0 if has hit end
**/
int
ms_biff_query_next (BIFF_QUERY *bq)
{
return ms_biff_query_next_merge (bq, TRUE);
}
/**
* Returns 0 if has hit end
**/
int
ms_biff_query_next_merge (BIFF_QUERY *bq, gboolean do_merge)
{
guint8 tmp[4];
int ans=1;
if (!bq || bq->pos->position >= bq->pos->size)
return 0;
if (bq->data_malloced) {
bq->num_merges = 0;
g_free (bq->data);
bq->data_malloced = 0;
}
bq->streamPos = bq->pos->position;
if (!bq->pos->read_copy (bq->pos, tmp, 4))
return 0;
bq->opcode = BIFF_GETWORD (tmp);
bq->length = BIFF_GETWORD (tmp+2);
bq->ms_op = (bq->opcode>>8);
bq->ls_op = (bq->opcode&0xff);
if (!(bq->data = bq->pos->read_ptr(bq->pos, bq->length))) {
bq->data = g_new0 (guint8, bq->length);
if (!bq->pos->read_copy(bq->pos, bq->data, bq->length)) {
ans = 0;
g_free(bq->data);
bq->length = 0;
} else
bq->data_malloced = 1;
}
if (ans && do_merge &&
bq->pos->read_copy (bq->pos, tmp, 4)) {
if ((BIFF_GETWORD(tmp) & 0xff) == BIFF_CONTINUE)
return ms_biff_merge_continues (bq, BIFF_GETWORD(tmp+2));
bq->pos->lseek (bq->pos, -4, MS_OLE_SEEK_CUR); /* back back off */
#if BIFF_DEBUG > 4
printf ("Backed off\n");
#endif
}
#if BIFF_DEBUG > 2
printf ("Biff read code 0x%x, length %d\n", bq->opcode, bq->length);
dump_biff (bq);
#endif
if (!bq->length) {
bq->data = 0;
return 1;
}
return (ans);
}
void
ms_biff_query_destroy (BIFF_QUERY *bq)
{
if (bq)
{
if (bq->data_malloced)
g_free (bq->data);
g_free (bq);
}
}
#if G_BYTE_ORDER == G_BIG_ENDIAN
double biff_getdouble(guint8 *p)
{
double d;
int i;
guint8 *t = (guint8 *)&d;
int sd = sizeof (d);
for (i = 0; i < sd; i++)
t[i] = p[sd - 1 - i];
return d;
}
#endif
......@@ -58,6 +58,4 @@ extern int ms_biff_query_next_merge (BIFF_QUERY *, gboolean do_merge);
/* Converts a merged query to the un-merged equivalent */
extern void ms_biff_query_unmerge (BIFF_QUERY *);
extern void ms_biff_query_destroy (BIFF_QUERY *);
/* Returns a stream which contains the data in the BIFF record. */
extern MS_OLE_STREAM *ms_biff_query_data_to_stream (BIFF_QUERY *);
#endif
/**
* ms-ole.h: MS Office OLE support for Gnumeric
*
* Author:
* Michael Meeks (michael@imaginator.com)
**/
#ifndef GNUMERIC_MS_OLE_H
#define GNUMERIC_MS_OLE_H
#include <glib.h>
typedef guint32 BBPtr ;
typedef guint32 SBPtr ;
typedef struct _MS_OLE_HEADER
{
/* sbd = Small Block Depot ( made up of BB's BTW ) */
BBPtr sbd_startblock ;
guint32 number_of_sbd_blocks ;
BBPtr *sbd_list ; /* [number_of_sbd_blocks] very often 1 */