Commit fc6287c2 authored by Michael Meeks's avatar Michael Meeks

Fix big leak. Embryonic array writing support, MISSARG support, Writes

Fix big leak.
Embryonic array writing support,
MISSARG support,
Writes inter-sheet references & 3D references,
Various BiffV8 updates,
far quieter.
parent 496e868a
1999-07-02 Michael Meeks <michael@edenproject.org>
* boot.c: Added 'main.h' to include debug symbol.
1999-07-02 Michael Meeks <michael@edenproject.org>
* ms-excel-read.c (ms_excel_read_workbook): Actually
insert the workbook_destroy at the end ( Huge leak ).
1999-07-01 Michael Meeks <michael@edenproject.org>
* ms-excel-write.c (ms_excel_write_get_externsheet_idx):
Stubbed.
(write_cell): More, verbose debug.
(write_index): shut it up.
(write_sheet): Fix a rather serious logic error that was
loosing us cells.
(write_sheet): Added error message for huge sheets... needs
more cunning indexing code.
* ms-formula-write.c (write_cellref_v[78]): Fixed
order of relative col/row bits. Implemented latter.
(write_ref): Implemented BiffV8 support.
(write_string): Added MISSARG support.
(write_area): Implemented BiffV8 support, and
3D area support.
* ms-formula-write.c (write_node): Split out
(write_ref): attempted to implement inter-sheet
references.
* ms-excel-write.c (ms_excel_write_get_sheet_idx):
Created.
1999-07-01 Morten Welinder <terra@diku.dk>
* boot.c: Clean out an incredible accumulation of #includes.
......
Michael
* Change all structure names ToCapitalisedLikeThisNames
* In ms-formula-write.c
* 3D areas & Intersheet references.
* Booleans
* IF
* Arrays
* Sort out silly things with massive sized sheets
* Deeper DBCELL records
* Truncated Index records
* Intelligent blank cell removal on insertion.
* New style support so we can do
* Colours
* Fonts etc.
* Remove silly name record in writing ( after debbugging is done )
* Rationalise Missing Argument stuff ... a new value ?
* Remove silly name record in writing ( after debugging is done )
* Fix inter-sheet dependencies ... well broken.
Jody
*
......
......@@ -11,6 +11,7 @@
#include "gnumeric.h"
#include "gnumeric-util.h"
#include "file.h"
#include "main.h"
#include "excel.h"
#include "boot.h"
......
......@@ -2895,11 +2895,12 @@ ms_excel_read_workbook (MS_OLE * file)
#endif
cell_deep_thaw_redraws ();
if (wb)
{
workbook_recalc (wb->gnum_wb);
return wb->gnum_wb;
if (wb) {
Workbook *ans = wb->gnum_wb;
ms_excel_workbook_destroy (wb);
workbook_recalc (ans);
return ans;
}
return 0;
}
......@@ -25,6 +25,7 @@
#include "sheet-object.h"
#include "style.h"
#include "main.h"
#include "utils.h"
#include "ms-ole.h"
#include "ms-biff.h"
......@@ -32,7 +33,7 @@
#include "ms-excel-write.h"
#include "ms-formula-write.h"
#define EXCEL_DEBUG 1
#define EXCEL_DEBUG 0
/**
* This function writes simple strings...
......@@ -375,6 +376,29 @@ write_bits (BIFF_PUT *bp, eBiff_version ver)
ms_biff_put_commit (bp);
}
int
ms_excel_write_get_sheet_idx (ExcelWorkbook *wb, Sheet *gnum_sheet)
{
guint lp;
for (lp=0;lp<wb->sheets->len;lp++) {
ExcelSheet *sheet = g_ptr_array_index (wb->sheets, lp);
g_return_val_if_fail (sheet, 0);
if (sheet->gnum_sheet == gnum_sheet)
return lp;
}
g_warning ("No associated sheet for %p\n", gnum_sheet);
return 0;
}
int
ms_excel_write_get_externsheet_idx (ExcelWorkbook *wb,
Sheet *sheeta,
Sheet *sheetb)
{
g_warning ("Get Externsheet not implemented yet\n");
return 0;
}
/**
* Returns stream position of start.
* See: S59D61.HTM
......@@ -802,6 +826,15 @@ write_cell (BIFF_PUT *bp, ExcelSheet *sheet, Cell *cell)
col = cell->col->pos;
row = cell->row->pos;
#if EXCEL_DEBUG > 2
{
EvalPosition tmp;
printf ("Cell at %s '%s' = '%s'\n", cell_name (col, row),
cell->parsed_node?expr_decode_tree (cell->parsed_node,
eval_pos_init (&tmp, sheet->gnum_sheet, col, row)):"none",
cell->value?value_get_as_string (cell->value):"empty");
}
#endif
if (cell->parsed_node) {
guint8 data[22];
guint8 lendat[2];
......@@ -821,10 +854,8 @@ write_cell (BIFF_PUT *bp, ExcelSheet *sheet, Cell *cell)
BIFF_SET_GUINT32 (data + 16, 0x0);
BIFF_SET_GUINT16 (data + 20, 0x0);
ms_biff_put_var_write (bp, data, 22);
ms_excel_write_formula (bp, sheet, cell->parsed_node,
col, row);
len = bp->length - 22;
len = ms_excel_write_formula (bp, sheet, cell->parsed_node,
col, row);
g_assert (len <= 0xffff);
ms_biff_put_var_seekto (bp, 20);
BIFF_SET_GUINT16 (lendat, len);
......@@ -1070,13 +1101,14 @@ write_index (MS_OLE_STREAM *s, ExcelSheet *sheet, ms_ole_pos_t pos)
for (lp=0;lp<sheet->dbcells->len;lp++) {
ms_ole_pos_t pos = g_array_index (sheet->dbcells, ms_ole_pos_t, lp);
BIFF_SET_GUINT32 (data, pos - sheet->wb->streamPos);
#if EXCEL_DEBUG > 1
printf ("writing index record 0x%4x - 0x%4x = 0x%4x\n",
pos, sheet->wb->streamPos, pos - sheet->wb->streamPos);
#endif
s->write (s, data, 4);
}
s->lseek (s, oldpos, MS_OLE_SEEK_SET);
}
/* See: S59DDB.HTM */
......@@ -1129,6 +1161,9 @@ write_sheet (BIFF_PUT *bp, ExcelSheet *sheet)
ms_ole_pos_t index_off;
sheet->streamPos = biff_bof_write (bp, sheet->wb->ver, eBiffTWorksheet);
if (sheet->maxy > 4096)
g_error ("Sheet seems impossibly big");
if (sheet->wb->ver >= eBiffV8) {
guint8 *data = ms_biff_put_len_next (bp, BIFF_INDEX,
......@@ -1169,11 +1204,12 @@ write_sheet (BIFF_PUT *bp, ExcelSheet *sheet)
Cell *cell = sheet_cell_get (sheet->gnum_sheet, x, y);
if (!cell)
run_size++;
else if (run_size) {
write_mulblank (bp, sheet, x, y, run_size);
else {
if (run_size)
write_mulblank (bp, sheet, x, y, run_size);
run_size = 0;
} else
write_cell (bp, sheet, cell);
}
}
if (run_size)
write_mulblank (bp, sheet, x, y, run_size);
......
......@@ -56,6 +56,10 @@ struct _ExcelWorkbook {
extern int ms_excel_write_ExcelWorkbook (MS_OLE *file, ExcelWorkbook *wb,
eBiff_version ver);
extern int ms_excel_write_get_sheet_idx (ExcelWorkbook *wb, Sheet *gnum_sheet);
extern int ms_excel_write_get_externsheet_idx (ExcelWorkbook *wb,
Sheet *gnum_sheeta,
Sheet *gnum_sheetb);
typedef enum { AS_PER_VER, SIXTEEN_BIT, EIGHT_BIT } PutType;
extern int
......
......@@ -4,8 +4,8 @@
* Author:
* Michael Meeks (michael@imaginator.com)
*/
#ifndef GNUMERIC_MS_FORMULA_H
#define GNUMERIC_MS_FORMULA_H
#ifndef GNUMERIC_MS_FORMULA_R_H
#define GNUMERIC_MS_FORMULA_R_H
#include <glib.h>
......
......@@ -119,7 +119,8 @@ push_guint32 (PolishData *pd, guint32 b)
}
static void
write_cellref_v7 (PolishData *pd, const CellRef *ref, guint8 *out_col, guint16 *out_row)
write_cellref_v7 (PolishData *pd, const CellRef *ref,
guint8 *out_col, guint16 *out_row)
{
guint row, col;
......@@ -133,19 +134,152 @@ write_cellref_v7 (PolishData *pd, const CellRef *ref, guint8 *out_col, guint16 *
row = ref->row;
if (ref->col_relative)
row|=0x8000;
row |= 0x4000;
if (ref->row_relative)
row|=0x4000;
row |= 0x8000;
BIFF_SET_GUINT16 (out_row, row);
BIFF_SET_GUINT8 (out_col, col);
}
static void
write_cellref_v8 (PolishData *pd, const CellRef *ref,
guint16 *out_col, guint16 *out_row)
{
guint row, col;
if (ref->col_relative)
col = ref->col + pd->col;
else
col = ref->col;
if (ref->row_relative)
row = ref->row + pd->row;
else
row = ref->row;
if (ref->col_relative)
col |= 0x4000;
if (ref->row_relative)
col |= 0x8000;
BIFF_SET_GUINT16 (out_row, row);
BIFF_SET_GUINT16 (out_col, col);
}
static void
write_string (PolishData *pd, gchar *txt)
{
push_guint8 (pd, FORMULA_PTG_STR);
biff_put_text (pd->bp, txt, eBiffV8, TRUE, SIXTEEN_BIT);
if (!txt || txt[0] == '\0')
push_guint8 (pd, FORMULA_PTG_MISSARG);
else {
push_guint8 (pd, FORMULA_PTG_STR);
biff_put_text (pd->bp, txt, eBiffV8, TRUE, SIXTEEN_BIT);
}
}
static void
write_area (PolishData *pd, const CellRef *a, const CellRef *b)
{
guint8 data[24];
if (!a->sheet || !b->sheet ||
(a->sheet == pd->sheet->gnum_sheet &&
a->sheet == b->sheet)) {
push_guint8 (pd, FORMULA_PTG_AREA);
if (pd->ver <= eBiffV7) {
write_cellref_v7 (pd, a,
data + 4, (guint16 *)(data + 0));
write_cellref_v7 (pd, b,
data + 5, (guint16 *)(data + 2));
ms_biff_put_var_write (pd->bp, data, 6);
} else {
write_cellref_v8 (pd, a,
(guint16 *)(data + 4), (guint16 *)(data + 0));
write_cellref_v8 (pd, b,
(guint16 *)(data + 6), (guint16 *)(data + 2));
ms_biff_put_var_write (pd->bp, data, 8);
}
} else {
guint16 first_idx, second_idx;
if (a->sheet)
first_idx = ms_excel_write_get_sheet_idx (pd->sheet->wb,
a->sheet);
else
first_idx = ms_excel_write_get_sheet_idx (pd->sheet->wb,
pd->sheet->gnum_sheet);
if (b->sheet)
second_idx = ms_excel_write_get_sheet_idx (pd->sheet->wb,
b->sheet);
else
second_idx = first_idx;
push_guint8 (pd, FORMULA_PTG_AREA_3D);
if (pd->ver <= eBiffV7) {
BIFF_SET_GUINT16 (data, 0); /* FIXME ? */
BIFF_SET_GUINT32 (data + 2, 0x0);
BIFF_SET_GUINT32 (data + 6, 0x0);
BIFF_SET_GUINT16 (data + 10, first_idx);
BIFF_SET_GUINT16 (data + 12, second_idx);
write_cellref_v7 (pd, a,
data + 18, (guint16 *)(data + 14));
write_cellref_v7 (pd, b,
data + 19, (guint16 *)(data + 16));
ms_biff_put_var_write (pd->bp, data, 20);
} else {
guint16 extn_idx = ms_excel_write_get_externsheet_idx (pd->sheet->wb,
a->sheet,
b->sheet);
BIFF_SET_GUINT16 (data, extn_idx);
write_cellref_v8 (pd, a,
(guint16 *)(data + 6), (guint16 *)(data + 2));
write_cellref_v8 (pd, b,
(guint16 *)(data + 8), (guint16 *)(data + 4));
ms_biff_put_var_write (pd->bp, data, 10);
}
}
}
static void
write_ref (PolishData *pd, const CellRef *ref)
{
guint8 data[24];
g_return_if_fail (pd);
g_return_if_fail (ref);
if (!ref->sheet ||
ref->sheet == pd->sheet->gnum_sheet) {
push_guint8 (pd, FORMULA_PTG_REF);
if (pd->ver <= eBiffV7) {
write_cellref_v7 (pd, ref, data + 2, (guint16 *)data);
ms_biff_put_var_write (pd->bp, data, 3);
} else { /* Duff docs */
write_cellref_v8 (pd, ref, (guint16 *)(data + 2), (guint16 *)data);
ms_biff_put_var_write (pd->bp, data, 4);
}
} else {
push_guint8 (pd, FORMULA_PTG_REF_3D);
if (pd->ver <= eBiffV7) {
guint16 extn_idx = ms_excel_write_get_sheet_idx (pd->sheet->wb,
ref->sheet);
BIFF_SET_GUINT16 (data, 0); /* FIXME ? */
BIFF_SET_GUINT32 (data + 2, 0x0);
BIFF_SET_GUINT32 (data + 6, 0x0);
BIFF_SET_GUINT16 (data + 10, extn_idx);
BIFF_SET_GUINT16 (data + 12, extn_idx);
write_cellref_v7 (pd, ref, data + 16,
(guint16 *)(data + 14));
ms_biff_put_var_write (pd->bp, data, 17);
} else {
guint16 extn_idx = ms_excel_write_get_externsheet_idx (pd->sheet->wb,
ref->sheet,
NULL);
BIFF_SET_GUINT16 (data, extn_idx);
write_cellref_v8 (pd, ref, (guint16 *)(data + 2),
(guint16 *)(data + 1));
ms_biff_put_var_write (pd->bp, data, 6);
}
}
}
/**
......@@ -277,11 +411,28 @@ write_node (PolishData *pd, ExprTree *tree)
break;
case VALUE_CELLRANGE:
{ /* FIXME: Could be 3D ! */
guint8 data[6];
push_guint8 (pd, FORMULA_PTG_AREA);
write_cellref_v7 (pd, &v->v.cell_range.cell_a, &data[4], (guint16 *)&data[0]);
write_cellref_v7 (pd, &v->v.cell_range.cell_b, &data[5], (guint16 *)&data[2]);
ms_biff_put_var_write (pd->bp, data, 6);
write_area (pd, &v->v.cell_range.cell_a,
&v->v.cell_range.cell_b);
break;
}
/* See S59E2B.HTM for some really duff docs */
case VALUE_ARRAY: /* Guestimation */
{
guint8 data[11];
if (v->v.array.x > 256 ||
v->v.array.y > 65536)
g_warning ("Array far too big");
BIFF_SET_GUINT8 (data + 0, FORMULA_PTG_ARRAY);
BIFF_SET_GUINT8 (data + 1, v->v.array.x - 1);
BIFF_SET_GUINT16 (data + 2, v->v.array.y - 1);
BIFF_SET_GUINT32 (data + 4, 0x0); /* ? */
BIFF_SET_GUINT16 (data + 8, 0x0); /* ? */
BIFF_SET_GUINT8 (data +10, 0x0); /* ? */
ms_biff_put_var_write (pd->bp, data, 11);
pd->arrays = g_list_append (pd->arrays, v);
break;
}
default:
......@@ -302,13 +453,8 @@ write_node (PolishData *pd, ExprTree *tree)
push_guint8 (pd, FORMULA_PTG_U_MINUS);
break;
case OPER_VAR:
{
guint8 data[3];
push_guint8 (pd, FORMULA_PTG_REF);
write_cellref_v7 (pd, &tree->u.ref, &data[2], (guint16 *)&data[0]);
ms_biff_put_var_write (pd->bp, data, 3);
write_ref (pd, &tree->u.ref);
break;
}
case OPER_ARRAY:
default:
{
......@@ -323,15 +469,51 @@ write_node (PolishData *pd, ExprTree *tree)
}
}
void
/* Writes the array and moves to next one */
/* See S59E2B.HTM for some really duff docs */
static void
write_arrays (PolishData *pd)
{
Value *array;
guint16 lpx, lpy;
guint8 data[8];
g_return_if_fail (pd);
g_return_if_fail (pd->arrays);
array = pd->arrays->data;
g_return_if_fail (array->type == VALUE_ARRAY);
for (lpy=0; lpy < array->v.array.y; lpy++) {
for (lpx=0; lpx < array->v.array.x; lpx++) {
const Value *v = array->v.array.vals[lpx][lpy];
if (VALUE_IS_NUMBER (v)) {
push_guint8 (pd, 1);
BIFF_SETDOUBLE (data, value_get_as_float (v));
ms_biff_put_var_write (pd->bp, data, 8);
} else { /* Can only be a string */
push_guint8 (pd, 2);
biff_put_text (pd->bp, value_get_as_string (v),
pd->ver, TRUE, AS_PER_VER);
}
}
}
pd->arrays = g_list_next (pd->arrays);
}
guint32
ms_excel_write_formula (BIFF_PUT *bp, ExcelSheet *sheet, ExprTree *expr,
int fn_col, int fn_row)
{
PolishData *pd;
ms_ole_pos_t start;
guint32 len;
g_return_if_fail (bp);
g_return_if_fail (expr);
g_return_if_fail (sheet);
g_return_val_if_fail (bp, 0);
g_return_val_if_fail (expr, 0);
g_return_val_if_fail (sheet, 0);
pd = g_new (PolishData, 1);
pd->col = fn_col;
......@@ -341,5 +523,12 @@ ms_excel_write_formula (BIFF_PUT *bp, ExcelSheet *sheet, ExprTree *expr,
pd->arrays = NULL;
pd->ver = sheet->wb->ver;
start = bp->length;
write_node (pd, expr);
len = bp->length - start;
while (pd->arrays)
write_arrays (pd);
return len;
}
......@@ -4,8 +4,8 @@
* Author:
* Michael Meeks (michael@imaginator.com)
*/
#ifndef GNUMERIC_MS_FORMULA_H
#define GNUMERIC_MS_FORMULA_H
#ifndef GNUMERIC_MS_FORMULA_W_H
#define GNUMERIC_MS_FORMULA_W_H
#include <glib.h>
......@@ -13,7 +13,7 @@
#include "ms-biff.h"
#include "formula-types.h"
void
guint32
ms_excel_write_formula (BIFF_PUT *bp, ExcelSheet *sheet, ExprTree *expr,
int fn_col, int fn_row);
......
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