Commit 08f616b9 authored by Michael Meeks's avatar Michael Meeks
Browse files

Fixups to OLE magic numbers,

Added more function translation,
Write side now writes strings & numbers :)
parent 3083f162
1999-05-17 Michael Meeks <michael@imaginator.com>
* ms-formula-read.c (formula_func_data): Function data from
Luke Plant.
* ms-biff.h: Add biff_setdouble prototype.
* ms-excel-read.c: Updated commenting.
* ms-biff.c (ms_bug_get_padding): Quietened.
Implemented 'tell' throught
(ms_biff_put_var_commit): Fixed seeking over end.
......
......@@ -10,6 +10,8 @@
(ms_ole_create): Fix killer stupid bug ! setting whole map to
END_OF_CHAIN instead of UNUSED_BLOCK ! idiot !
Correctly terminated the root directory chain.
Added magic numbers.
(ms_ole_directory_create): Added magic numbers.
* ms-ole.h (struct _MS_OLE_STREAM): Add tell method, and fix
broken comments.
......
......@@ -333,6 +333,30 @@ check (MS_OLE *f)
}
/* Pass a pointer to the raw memory at start of PPS */
static void
init_pps (guint8 *mem, char *name)
{
int lp;
/* Blank stuff I don't understand */
for (lp=0;lp<PPS_BLOCK_SIZE;lp++)
SET_GUINT8(mem+lp, 0);
lp = 0;
while (name[lp] && lp < (PPS_BLOCK_SIZE/2)-1)
{
SET_GUINT8(mem + lp*2, name[lp]);
SET_GUINT8(mem + lp*2 + 1, 0);
lp++;
}
SET_GUINT16(mem + 0x40, lp);
/* Magic numbers */
SET_GUINT32 (mem + 0x50, 0x00020900);
SET_GUINT32 (mem + 0x5c, 0x46000000);
}
/* Create a nice linear array and return count of the number in the array */
static GArray *
read_link_array (MS_OLE *f, BBPtr first)
......@@ -429,7 +453,7 @@ ms_ole_create (const char *name)
int file;
MS_OLE *f;
int init_blocks = 5, lp;
guint8 *ptr;
guint8 *ptr, *mem;
guint32 root_startblock = 0;
guint32 sbd_startblock = 0, zero = 0;
char title[] ="Root Entry";
......@@ -479,10 +503,19 @@ ms_ole_create (const char *name)
/* The header block */
for (lp=0;lp<BB_BLOCK_SIZE/4;lp++)
SET_GUINT32(f->mem + lp*4, END_OF_CHAIN);
SET_GUINT32(f->mem + lp*4, (lp<(0x52/4))?0:END_OF_CHAIN);
SET_GUINT32(f->mem, 0xe011cfd0); /* Magic number */
SET_GUINT32(f->mem + 4, 0xe11ab1a1);
/* More magic numbers */
SET_GUINT32(f->mem + 0x18, 0x0003003b);
SET_GUINT32(f->mem + 0x1c, 0x0009fffe);
SET_GUINT32(f->mem + 0x20, 0x6);
SET_GUINT32(f->mem + 0x38, 0x00001000);
SET_GUINT32(f->mem + 0x40, 0x1);
SET_GUINT32(f->mem + 0x44, 0xfffffffe);
SET_NUM_BBD_BLOCKS(f, 1);
SET_BBD_LIST(f, 0, 1);
......@@ -503,15 +536,9 @@ ms_ole_create (const char *name)
read_root_list (f);
/* The first PPS block : 0 */
lp = 0;
ptr = f->mem + BB_BLOCK_SIZE;
while (title[lp])
*ptr++ = title[lp++];
for (;lp<PPS_BLOCK_SIZE;lp++) /* Blank stuff I don't understand */
*ptr++ = 0;
init_pps (f->mem + BB_BLOCK_SIZE, title);
PPS_SET_NAME_LEN(f, PPS_ROOT_BLOCK, lp);
......@@ -1561,6 +1588,7 @@ ms_ole_directory_create (MS_OLE_DIRECTORY *d, char *name, PPS_TYPE type)
/* Memory Debug */
#if OLE_DEBUG > 0
{
int idx = (((p)*PPS_BLOCK_SIZE)/BB_BLOCK_SIZE);
guint32 ptr = ms_array_index ((f)->header.root_list, BBPtr, idx);
......@@ -1572,19 +1600,10 @@ ms_ole_directory_create (MS_OLE_DIRECTORY *d, char *name, PPS_TYPE type)
SET_GUINT8(mem, 0);
mem+= PPS_BLOCK_SIZE-1;
SET_GUINT8(mem, 0);
#endif
/* Blank stuff I don't understand */
for (lp=0;lp<PPS_BLOCK_SIZE;lp++)
SET_GUINT8(PPS_PTR(f, p)+lp, 0);
init_pps (PPS_PTR(f,p), name);
lp = 0;
while (name[lp] && lp < (PPS_BLOCK_SIZE/2)-1)
{
SET_GUINT8(PPS_PTR(f, p) + lp*2, name[lp]);
SET_GUINT8(PPS_PTR(f, p) + lp*2 + 1, 0);
lp++;
}
PPS_SET_NAME_LEN(f, p, lp);
PPS_SET_STARTBLOCK(f, p, END_OF_CHAIN);
/* Chain into the directory */
......
......@@ -85,7 +85,9 @@ ms_bug_get_padding (guint16 opcode)
ans=0;
break;
default:
#if BIFF_DEBUG > 0
printf ("Unknown padding to fix bug on record 0x%x\n", opcode);
#endif
break;
}
#if BIFF_DEBUG > 0
......
......@@ -29,7 +29,8 @@ typedef guint64 DLONG;
(*((guint8 *)(p)+2)=((n)>>16)&0xff), \
(*((guint8 *)(p)+3)=((n)>>24)&0xff))
double biff_getdouble(guint8 *p);
extern double biff_getdouble(guint8 *p);
extern void biff_setdouble (guint8 *p, double d);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
# define BIFF_GETDOUBLE(p) (*((double*)(p)))
......
......@@ -14,10 +14,10 @@
#define EX_GETXF(p) (BIFF_GETWORD(p->data + 4))
#define EX_GETSTRLEN(p) (BIFF_GETWORD(p->data + 6))
#define EX_SETROW(p,d) (BIFF_SET_GUINT16(p->data + 0, d))
#define EX_SETCOL(p,d) (BIFF_SET_GUINT16(p->data + 2, d))
#define EX_SETXF(p,d) (BIFF_SET_GUINT16(p->data + 4, d))
#define EX_SETSTRLEN(p,d) (BIFF_SET_GUINT16(p->data + 6, d))
#define EX_SETROW(p,d) (BIFF_SET_GUINT16(p + 0, d))
#define EX_SETCOL(p,d) (BIFF_SET_GUINT16(p + 2, d))
#define EX_SETXF(p,d) (BIFF_SET_GUINT16(p + 4, d))
#define EX_SETSTRLEN(p,d) (BIFF_SET_GUINT16(p + 6, d))
/* Version info types as found in various Biff records */
typedef enum _eBiff_filetype { eBiffTWorkbook=0, eBiffTVBModule=1, eBiffTWorksheet=2,
......
......@@ -1538,7 +1538,7 @@ ms_excel_read_cell (BIFF_QUERY * q, MS_EXCEL_SHEET * sheet)
}
break;
}
case BIFF_RSTRING:
case BIFF_RSTRING: /* See: S59DDC.HTM */
{
char *txt ;
/*
......@@ -1554,7 +1554,8 @@ ms_excel_read_cell (BIFF_QUERY * q, MS_EXCEL_SHEET * sheet)
case BIFF_DBCELL: /* S59D6D.HTM */
/* Can be ignored on read side */
break ;
case BIFF_NUMBER: {
case BIFF_NUMBER: /* S59DAC.HTM */
{
Value *v = value_new_float (BIFF_GETDOUBLE (q->data + 6));
#if EXCEL_DEBUG > 0
printf ("Read number %g\n", BIFF_GETDOUBLE (q->data + 6));
......@@ -1594,9 +1595,10 @@ ms_excel_read_cell (BIFF_QUERY * q, MS_EXCEL_SHEET * sheet)
case BIFF_RK: /* See: S59DDA.HTM */
{
Value *v = biff_get_rk(q->data+6);
/* printf ("RK number : 0x%x, length 0x%x\n", q->opcode, q->length);
dump (q->data, q->length);*/
#if EXCEL_DEBUG > 2
printf ("RK number : 0x%x, length 0x%x\n", q->opcode, q->length);
dump (q->data, q->length);
#endif
ms_excel_sheet_insert_val (sheet, EX_GETXF (q), EX_GETCOL (q),
EX_GETROW (q), v);
break;
......
......@@ -31,6 +31,8 @@
#include "excel.h"
#include "ms-excel-write.h"
#define EXCEL_DEBUG 0
typedef struct _SHEET SHEET;
typedef struct _WORKBOOK WORKBOOK;
......@@ -53,7 +55,7 @@ struct _WORKBOOK {
* it returns the length of the string.
**/
static void
biff_put_text (BIFF_PUT *bp, char *txt, eBiff_version ver)
biff_put_text (BIFF_PUT *bp, char *txt, eBiff_version ver, gboolean write_len)
{
#define BLK_LEN 16
......@@ -66,14 +68,22 @@ biff_put_text (BIFF_PUT *bp, char *txt, eBiff_version ver)
len = strlen (txt);
if (ver >= eBiffV8) { /* Write header & word length*/
data[0] = 0;
BIFF_SET_GUINT16(data+1, len);
ms_biff_put_var_write (bp, data, 3);
ans = len + 3;
if (write_len) {
BIFF_SET_GUINT16(data+1, len);
ms_biff_put_var_write (bp, data, 3);
ans = len + 3;
} else {
ms_biff_put_var_write (bp, data, 1);
ans = len;
}
} else { /* Byte length */
g_return_if_fail (len<256);
BIFF_SET_GUINT8(data, len);
ms_biff_put_var_write (bp, data, 1);
ans = len + 1;
if (write_len) {
g_return_if_fail (len<256);
BIFF_SET_GUINT8(data, len);
ms_biff_put_var_write (bp, data, 1);
ans = len + 1;
} else
ans = len;
}
/* An attempt at efficiency */
......@@ -189,7 +199,7 @@ biff_boundsheet_write_first (BIFF_PUT *bp, eBiff_filetype type,
BIFF_SET_GUINT8 (data+5, 0); /* Visible */
ms_biff_put_var_write (bp, data, 6);
biff_put_text (bp, name, ver);
biff_put_text (bp, name, ver, TRUE);
ms_biff_put_var_commit (bp);
return pos;
......@@ -214,11 +224,84 @@ biff_boundsheet_write_last (MS_OLE_STREAM *s, guint32 pos,
s->lseek (s, oldpos, MS_OLE_SEEK_SET);
}
static void
write_value (BIFF_PUT *bp, Value *v, eBiff_version ver, guint32 col, guint32 row, guint16 xf)
{
switch (v->type) {
case VALUE_INTEGER:
{
int_t vint = v->v.v_int;
guint head = 3;
guint8 *data;
if (vint%100==0)
vint/=100;
else
head = 2;
#if EXCEL_DEBUG > 0
printf ("writing %d %d %d\n", vint, v->v.v_int, head);
#endif
if (vint & ~0x3fff) /* Chain to floating point then. */
printf ("FIXME: Serious loss of precision saving number\n");
data = ms_biff_put_len_next (bp, BIFF_RK, 10);
EX_SETROW(data, row);
EX_SETCOL(data, col);
EX_SETXF (data, xf);
BIFF_SET_GUINT32 (data + 6, (vint<<2) + head);
ms_biff_put_len_commit (bp);
break;
}
case VALUE_FLOAT:
{
if (ver >= eBiffV8) { /* See: S59DAC.HTM */
guint8 *data =ms_biff_put_len_next (bp, BIFF_NUMBER, 14);
EX_SETROW(data, row);
EX_SETCOL(data, col);
EX_SETXF (data, xf);
BIFF_SETDOUBLE (data + 6, v->v.v_float);
ms_biff_put_len_commit (bp);
} else { /* Nasty RK thing S59DDA.HTM */
guint8 data[16];
ms_biff_put_var_next (bp, BIFF_RK);
BIFF_SETDOUBLE (data+6-4, v->v.v_float);
EX_SETROW(data, row);
EX_SETCOL(data, col);
EX_SETXF (data, xf);
data[6] &= 0xfc;
ms_biff_put_var_write (bp, data, 10); /* Yes loose it. */
ms_biff_put_var_commit (bp);
}
break;
}
case VALUE_STRING:
{
char data[16];
g_return_if_fail (v->v.str->str);
if (ver == eBiffV8); /* Use SST stuff in fulness of time */
/* See: S59DDC.HTM */
ms_biff_put_var_next (bp, BIFF_RSTRING);
EX_SETXF (data, xf);
EX_SETCOL(data, col);
EX_SETROW(data, row);
EX_SETSTRLEN (data, strlen(v->v.str->str));
ms_biff_put_var_write (bp, data, 8);
biff_put_text (bp, v->v.str->str, ver, FALSE);
ms_biff_put_var_commit (bp);
break;
}
default:
printf ("Unhandled value type %d\n", v->type);
break;
}
}
typedef struct {
SHEET *sheet;
BIFF_PUT *bp;
} CellArgs;
static void
write_cell (gpointer key, Cell *cell, CellArgs *a)
{
......@@ -227,16 +310,15 @@ write_cell (gpointer key, Cell *cell, CellArgs *a)
g_return_if_fail (a);
g_return_if_fail (cell);
if (cell->value && VALUE_IS_NUMBER (cell->value)) {
guint8 *data;
data = ms_biff_put_len_next (bp, BIFF_NUMBER, 14);
EX_SETROW(bp, cell->row->pos);
EX_SETCOL(bp, cell->col->pos);
EX_SETXF (bp, 0);
BIFF_SETDOUBLE (bp->data + 6,
value_get_as_float (cell->value));
ms_biff_put_len_commit (bp);
}
if (cell->parsed_node)
#if EXCEL_DEBUG > 0
printf ("FIXME: Skipping function\n");
#else
;
#endif
else if (cell->value)
write_value (bp, cell->value, a->sheet->wb->ver,
cell->col->pos, cell->row->pos, 0);
}
static void
......
......@@ -86,7 +86,7 @@ FORMULA_FUNC_DATA formula_func_data[] =
{ "COS", 1 },
{ "TAN", 1 },
{ "ATAN", 1 },
{ "0x13", 8 },
{ "ATAN2", 2 },
{ "SQRT", 1 },
{ "EXP", 1 },
{ "LN", 1 },
......@@ -410,7 +410,7 @@ FORMULA_FUNC_DATA formula_func_data[] =
{ "0x154", 8 },
{ "0x155", 8 },
{ "RADIANS", 1 },
{ "0x157", 8 },
{ "DEGREES", 1 },
{ "0x158", 8 },
{ "0x159", 8 },
{ "0x15a", 8 },
......
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