ms-chart.c 58.2 KB
Newer Older
1
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 3 4 5 6 7
/**
 * ms-chart.c: MS Excel chart support for Gnumeric
 *
 * Author:
 *    Jody Goldberg (jgoldberg@home.com)
 *
8
 * (C) 1999-2001 Jody Goldberg
9 10
 **/

11
#include <config.h>
12
#include "boot.h"
Michael Meeks's avatar
Michael Meeks committed
13 14 15
#include "excel.h"
#include "ms-chart.h"
#include "ms-formula-read.h"
16 17
#include "ms-excel-read.h"
#include "ms-escher.h"
18 19 20 21 22 23 24

#include <parse-util.h>
#include <style-color.h>
#include <format.h>
#include <expr.h>
#include <gutils.h>

25
#include <gnumeric-graph.h>
Jody Goldberg's avatar
Jody Goldberg committed
26
#include <xml-io.h>
27 28
#include <gnome-xml/tree.h>
#include <stdio.h>
Michael Meeks's avatar
Michael Meeks committed
29

30
/* #define NO_DEBUG_EXCEL */
Michael Meeks's avatar
Michael Meeks committed
31

32 33 34 35 36 37 38 39 40
typedef enum {
	MS_VECTOR_PURPOSE_LABELS	= 0,
	MS_VECTOR_PURPOSE_VALUES	= 1,
	MS_VECTOR_PURPOSE_CATEGORIES	= 2,
	/* This is undocumented, but makes sense */
	MS_VECTOR_PURPOSE_BUBBLES	= 3,
	MS_VECTOR_PURPOSE_MAX		= 4
} MS_VECTOR_PURPOSE;

41 42 43 44 45
char const *const ms_vector_purpose_type_name [] =
{
    "labels", "values", "categories", "bubbles",
};

46 47 48
typedef struct _ExcelChartSeries
{
	struct {
49
		GnmGraphVectorType type;
50
		int count, remote_ID;
51 52
	} vector [MS_VECTOR_PURPOSE_MAX];

53
	int chart_group;
54 55 56
	xmlNodePtr  xml;
} ExcelChartSeries;

Michael Meeks's avatar
Michael Meeks committed
57 58
typedef struct
{
59 60 61
	MSContainer	 container;

	MSContainer	*parent;
62
	GArray		*stack;
63
	MsBiffVersion	 ver;
64 65
	guint32		 prev_opcode;
	ExcelWorkbook	*wb;
66 67
	GnmGraph	*graph;

Jody Goldberg's avatar
Jody Goldberg committed
68 69
	xmlDocPtr   	 xml_doc;
	xmlNsPtr	 xml_ns;
70

71 72 73
	ExcelChartSeries *currentSeries;
	GPtrArray	 *series;
} ExcelChartReadState;
Michael Meeks's avatar
Michael Meeks committed
74 75 76

typedef struct
{
77
	int dummy;
78
} GnumericChartState;
Michael Meeks's avatar
Michael Meeks committed
79

80 81
typedef struct biff_chart_handler ExcelChartHandler;
typedef gboolean (*ExcelChartReader)(ExcelChartHandler const *handle,
82
				     ExcelChartReadState *, BiffQuery *q);
83
typedef gboolean (*ExcelChartWriter)(ExcelChartHandler const *handle,
84
				     GnumericChartState *, BiffPut *os);
Michael Meeks's avatar
Michael Meeks committed
85 86 87
struct biff_chart_handler
{
	guint16 const opcode;
88
	int const	min_size; /* To be useful this needs to be versioned */
89 90 91
	char const *const name;
	ExcelChartReader const read_fn;
	ExcelChartWriter const write_fn;
Michael Meeks's avatar
Michael Meeks committed
92 93 94
};

#define BC(n)	biff_chart_ ## n
95 96
#define BC_R(n)	BC(read_ ## n)
#define BC_W(n)	BC(write_ ## n)
Michael Meeks's avatar
Michael Meeks committed
97

98 99 100 101 102 103 104 105 106 107
static ExcelChartSeries *
excel_chart_series_new (void)
{
	ExcelChartSeries *series;
	int i;

	series = g_new (ExcelChartSeries, 1);

	series->chart_group = -1;
	for (i = MS_VECTOR_PURPOSE_MAX; i-- > 0 ; ) {
108
		series->vector [i].remote_ID = -1;
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
		series->vector [i].type = GNM_VECTOR_AUTO; /* may be reset later */
	}

	/* labels are always strings */
	series->vector [MS_VECTOR_PURPOSE_LABELS].type = GNM_VECTOR_STRING;

	return series;
}

static void
excel_chart_series_delete (ExcelChartSeries *series)
{
	g_free (series);
}

124 125 126 127 128 129 130
static int
BC_R(top_state) (ExcelChartReadState *s)
{
	g_return_val_if_fail (s != NULL, 0);
	return g_array_index (s->stack, int, s->stack->len-1);
}

Michael Meeks's avatar
Michael Meeks committed
131
static StyleColor *
132
BC_R(color)(guint8 const *data, char *type)
Michael Meeks's avatar
Michael Meeks committed
133
{
134
	guint32 const rgb = MS_OLE_GET_GUINT32 (data);
Michael Meeks's avatar
Michael Meeks committed
135 136 137 138
	guint16 const r = (rgb >>  0) & 0xff;
	guint16 const g = (rgb >>  8) & 0xff;
	guint16 const b = (rgb >> 16) & 0xff;

139 140 141 142
#ifndef NO_DEBUG_EXCEL
	if (ms_excel_chart_debug > 0)
		printf("%s Color %02x%02x%02x\n", type, r, g, b);
#endif
Michael Meeks's avatar
Michael Meeks committed
143 144 145 146 147 148 149

	return style_color_new ((r<<8)|r, (g<<8)|g, (b<<8)|b);
}

/****************************************************************************/

static gboolean
150
BC_R(3dbarshape)(ExcelChartHandler const *handle,
151
		 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
152
{
153
	guint16 const type = MS_OLE_GET_GUINT16 (q->data);
154 155 156 157 158 159 160 161
	switch (type) {
	case 0 : puts ("box"); break;
	case 1 : puts ("cylinder"); break;
	case 256 : puts ("pyramid"); break;
	case 257 : puts ("cone"); break;
	default :
	    printf ("unknown 3dshape %d\n", type);
	};
Michael Meeks's avatar
Michael Meeks committed
162 163 164 165

	return FALSE;
}
static gboolean
166
BC_W(3dbarshape)(ExcelChartHandler const *handle,
167
		 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
168 169 170 171 172 173 174
{
	return FALSE;
}

/****************************************************************************/

static gboolean
175
BC_R(3d)(ExcelChartHandler const *handle,
176
	 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
177
{
178 179 180 181 182 183 184 185
	guint16 const rotation = MS_OLE_GET_GUINT16 (q->data);	/* 0-360 */
	guint16 const elevation = MS_OLE_GET_GUINT16 (q->data+2);	/* -90 - 90 */
	guint16 const distance = MS_OLE_GET_GUINT16 (q->data+4);	/* 0 - 100 */
	guint16 const height = MS_OLE_GET_GUINT16 (q->data+6);
	guint16 const depth = MS_OLE_GET_GUINT16 (q->data+8);
	guint16 const gap = MS_OLE_GET_GUINT16 (q->data+10);
	guint8 const flags = MS_OLE_GET_GUINT8 (q->data+12);
	guint8 const zero = MS_OLE_GET_GUINT8 (q->data+13);
186 187 188 189 190

	gboolean const use_perspective = (flags&0x01) ? TRUE :FALSE;
	gboolean const cluster = (flags&0x02) ? TRUE :FALSE;
	gboolean const auto_scale = (flags&0x04) ? TRUE :FALSE;
	gboolean const walls_2d = (flags&0x20) ? TRUE :FALSE;
Michael Meeks's avatar
Michael Meeks committed
191

192 193
	g_return_val_if_fail (zero == 0, FALSE); /* just warn for now */

194 195 196 197 198 199 200 201
	printf ("Rot = %hu\n", rotation);
	printf ("Elev = %hu\n", elevation);
	printf ("Dist = %hu\n", distance);
	printf ("Height = %hu\n", height);
	printf ("Depth = %hu\n", depth);
	printf ("Gap = %hu\n", gap);

	if (use_perspective)
202
		puts ("Use perspective");
203
	if (cluster)
204
		puts ("Cluster");
205
	if (auto_scale)
206
		puts ("Auto Scale");
207
	if (walls_2d)
208
		puts ("2D Walls");
Michael Meeks's avatar
Michael Meeks committed
209 210 211 212
	return FALSE;
}

static gboolean
213
BC_W(3d)(ExcelChartHandler const *handle,
214
	 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
215 216 217 218 219 220
{
	return FALSE;
}

/****************************************************************************/

221
static gboolean
222
BC_R(ai)(ExcelChartHandler const *handle,
223
	 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
224
{
225
	guint8 const purpose = MS_OLE_GET_GUINT8 (q->data);
226
	guint8 const ref_type = MS_OLE_GET_GUINT8 (q->data + 1);
227 228
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data + 2);
	guint16 const length = MS_OLE_GET_GUINT16 (q->data + 6);
229

230 231 232 233 234 235
	int popped_state = BC_R(top_state) (s);

	/* ignore these for now */
	if (popped_state == BIFF_CHART_text)
		return FALSE;

236 237 238
	/* Rest are 0 */
	if (flags&0x01) {
		guint16 const fmt_index = MS_OLE_GET_GUINT16 (q->data + 4);
239
		StyleFormat * fmt = biff_format_data_lookup (s->wb, fmt_index);
240
		puts ("Has Custom number format");
241 242 243 244 245
		if (fmt != NULL) {
			char * desc = style_format_as_XL (fmt, FALSE);
			printf ("Format = '%s';\n", desc);
			g_free (desc);
		}
246 247 248
	} else
		puts ("Uses number format from data source");

249 250
	g_return_val_if_fail (purpose < MS_VECTOR_PURPOSE_MAX, TRUE);
	switch (purpose) {
251
	case MS_VECTOR_PURPOSE_LABELS :	    puts ("Linking labels"); break;
252 253 254
	case MS_VECTOR_PURPOSE_VALUES :	    puts ("Linking values"); break;
	case MS_VECTOR_PURPOSE_CATEGORIES : puts ("Linking categories"); break;
	case MS_VECTOR_PURPOSE_BUBBLES :    puts ("Linking bubbles"); break;
Michael Meeks's avatar
Michael Meeks committed
255
	default :
256
		g_assert_not_reached ();
257
	};
258
	switch (ref_type) {
259 260
	case 0 : puts ("Use default categories"); break;
	case 1 : puts ("Text/Value entered directly"); break;
Jody Goldberg's avatar
Jody Goldberg committed
261
	case 2 : puts ("Linked to Container"); break;
262
	case 4 : puts ("'Error reported' what the heck is this ??"); break;
263
	default :
264
		 printf ("UKNOWN : reference type (%x)\n", ref_type);
Michael Meeks's avatar
Michael Meeks committed
265 266
	};

Jody Goldberg's avatar
Jody Goldberg committed
267
	/* (2) == linked to container */
268
	if (ref_type == 2) {
269
		ExprTree *expr = ms_container_parse_expr (s->parent,
Jody Goldberg's avatar
Jody Goldberg committed
270
							  q->data+8, length);
271
		if (expr) {
272 273 274
			Sheet *sheet = ms_container_sheet (s->parent);

			g_return_val_if_fail (sheet != NULL, FALSE);
275 276
			g_return_val_if_fail (s->currentSeries != NULL, TRUE);

277
#ifdef ENABLE_BONOBO
278
			s->currentSeries->vector [purpose].remote_ID =
279
				gnm_graph_add_vector (s->graph, expr,
280 281
					s->currentSeries->vector [purpose].type,
					sheet);
282 283 284 285
#endif

		}
	} else {
286
		g_return_val_if_fail (length == 0, TRUE);
287 288
	}

Michael Meeks's avatar
Michael Meeks committed
289 290 291 292
	return FALSE;
}

static gboolean
293
BC_W(ai)(ExcelChartHandler const *handle,
294
	 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
295 296 297 298 299 300 301
{
	return FALSE;
}

/****************************************************************************/

static gboolean
302
BC_R(alruns)(ExcelChartHandler const *handle,
303
	     ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
304
{
305
	gint16 length = MS_OLE_GET_GUINT16 (q->data);
306
	guint8 const *in = (q->data + 2);
307 308
	char *const ans = (char *) g_new (char, length + 2);
	char *out = ans;
Michael Meeks's avatar
Michael Meeks committed
309

310
	for (; --length >= 0 ; in+=4, ++out)
Michael Meeks's avatar
Michael Meeks committed
311
	{
312 313 314 315
		/*
		 * FIXME FIXME FIXME :
		 *        - don't toss font info
		 *        - Merge streams of the same font together.
Jody Goldberg's avatar
Jody Goldberg committed
316
		 *        - Combine with RTF support once merged
317
		 */
318
		guint32 const elem = MS_OLE_GET_GUINT32 (in);
319
		*out = (char)((elem >> 16) & 0xff);
Michael Meeks's avatar
Michael Meeks committed
320
	}
321 322 323
	*out = '\0';

	puts (ans);
Michael Meeks's avatar
Michael Meeks committed
324 325 326 327
	return FALSE;
}

static gboolean
328
BC_W(alruns)(ExcelChartHandler const *handle,
329
	     GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
330 331 332 333 334 335 336
{
	return FALSE;
}

/****************************************************************************/

static gboolean
337
BC_R(area)(ExcelChartHandler const *handle,
338
	   ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
339
{
340
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data);
341 342
	gboolean const stacked = (flags & 0x01) ? TRUE : FALSE;
	gboolean const as_percentage = (flags & 0x02) ? TRUE : FALSE;
Michael Meeks's avatar
Michael Meeks committed
343

Jody Goldberg's avatar
Jody Goldberg committed
344 345 346 347 348 349 350 351
	if (as_percentage)
		/* TODO : test theory that percentage implies stacked */
		printf ("Stacked Percentage. (%d should be TRUE)\n", stacked);
	else if (stacked)
		printf ("Stacked Percentage values\n");
	else
		printf ("Overlayed values\n");

352
	if (s->container.ver >= MS_BIFF_V8)
Michael Meeks's avatar
Michael Meeks committed
353
	{
354
		gboolean const has_shadow = (flags & 0x04) ? TRUE : FALSE;
Jody Goldberg's avatar
Jody Goldberg committed
355 356
		if (has_shadow)
			puts ("in 3D");
Michael Meeks's avatar
Michael Meeks committed
357 358 359 360 361
	}
	return FALSE;
}

static gboolean
362
BC_W(area)(ExcelChartHandler const *handle,
363
	   GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
364 365 366 367 368 369 370
{
	return FALSE;
}

/****************************************************************************/

static gboolean
371
BC_R(areaformat)(ExcelChartHandler const *handle,
372
		 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
373
{
374
#if 0
375 376
	StyleColor *fore = BC_R(color) (q->data, "Area Fore");
	StyleColor *back = BC_R(color) (q->data+4, "Area Back");
377
#endif
378 379
	guint16 const pattern = MS_OLE_GET_GUINT16 (q->data+8);
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data+10);
Jody Goldberg's avatar
Jody Goldberg committed
380
	gboolean const auto_format = (flags & 0x01) ? TRUE : FALSE;
Michael Meeks's avatar
Michael Meeks committed
381 382
	gboolean const swap_color_for_negative = flags & 0x02;

383 384 385 386 387 388 389 390 391 392
	printf ("pattern = %d;\n", pattern);
	if (auto_format)
		puts ("Use auto format;");
	if (swap_color_for_negative)
		puts ("Swap fore and back colours when displaying negatives;");

#if 0
	/* Ignore the colour indicies.  Use the colours themselves
	 * to avoid problems with guessing the strange index values
	 */
393
	if (s->container.ver >= MS_BIFF_V8)
Michael Meeks's avatar
Michael Meeks committed
394
	{
395 396
		guint16 const fore_index = MS_OLE_GET_GUINT16 (q->data+12);
		guint16 const back_index = MS_OLE_GET_GUINT16 (q->data+14);
Jody Goldberg's avatar
Jody Goldberg committed
397 398 399

		/* TODO : Ignore result for now,
		 * Which to use, fore and back, or these ? */
400 401
		ms_excel_palette_get (s->wb->palette, fore_index);
		ms_excel_palette_get (s->wb->palette, back_index);
Michael Meeks's avatar
Michael Meeks committed
402
	}
403
#endif
Michael Meeks's avatar
Michael Meeks committed
404 405 406 407
	return FALSE;
}

static gboolean
408
BC_W(areaformat)(ExcelChartHandler const *handle,
409
		 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
410 411 412 413 414 415 416
{
	return FALSE;
}

/****************************************************************************/

static gboolean
417
BC_R(attachedlabel)(ExcelChartHandler const *handle,
418
		    ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
419
{
420
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data);
421 422 423 424 425
	gboolean const show_value = (flags&0x01) ? TRUE : FALSE;
	gboolean const show_percent = (flags&0x02) ? TRUE : FALSE;
	gboolean const show_label_prercent = (flags&0x04) ? TRUE : FALSE;
	gboolean const smooth_line = (flags&0x08) ? TRUE : FALSE;
	gboolean const show_label = (flags&0x10) ? TRUE : FALSE;
426 427 428 429 430 431 432 433 434 435 436 437

	if (show_value)
		puts ("Show Value");
	if (show_percent)
		puts ("Show as Percentage");
	if (show_label_prercent)
		puts ("Show as Label Percentage");
	if (smooth_line)
		puts ("Smooth line");
	if (show_label)
		puts ("Show the label");

438
	if (s->container.ver >= MS_BIFF_V8)
439 440
	{
		gboolean const show_bubble_size = (flags&0x20) ? TRUE : FALSE;
441 442
		if (show_bubble_size)
			puts ("Show bubble size");
443
	}
Michael Meeks's avatar
Michael Meeks committed
444 445 446 447
	return FALSE;
}

static gboolean
448
BC_W(attachedlabel)(ExcelChartHandler const *handle,
449
		    GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
450 451 452 453 454 455 456
{
	return FALSE;
}

/****************************************************************************/

static gboolean
457
BC_R(axesused)(ExcelChartHandler const *handle,
458
	       ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
459
{
460
	guint16 const num_axis = MS_OLE_GET_GUINT16 (q->data);
461 462
	g_return_val_if_fail(1 <= num_axis && num_axis <= 2, TRUE);
	printf ("There are %hu axis.\n", num_axis);
Michael Meeks's avatar
Michael Meeks committed
463 464 465 466
	return FALSE;
}

static gboolean
467
BC_W(axesused)(ExcelChartHandler const *handle,
468
	       GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
469 470 471 472 473 474
{
	return FALSE;
}

/****************************************************************************/

475 476 477 478 479 480 481
typedef enum
{
	MS_AXIS_X	= 0,
	MS_AXIS_Y	= 1,
	MS_AXIS_SERIES	= 2,
	MS_AXIS_MAX	= 3
} MS_AXIS;
482
static char const *const ms_axis[] =
483 484 485 486
{
	"X-axis", "Y-axis", "series-axis"
};

Michael Meeks's avatar
Michael Meeks committed
487
static gboolean
488
BC_R(axis)(ExcelChartHandler const *handle,
489
	   ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
490
{
491
	guint16 const axis_type = MS_OLE_GET_GUINT16 (q->data);
492 493 494 495
	MS_AXIS atype;
	g_return_val_if_fail (axis_type < MS_AXIS_MAX, TRUE);
	atype = axis_type;
	printf ("This is a %s .\n", ms_axis[atype]);
Michael Meeks's avatar
Michael Meeks committed
496 497 498 499
	return FALSE;
}

static gboolean
500
BC_W(axis)(ExcelChartHandler const *handle,
501
	   GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
502 503 504 505 506 507 508
{
	return FALSE;
}

/****************************************************************************/

static gboolean
509
BC_R(axcext)(ExcelChartHandler const *handle,
510
	     ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
511 512 513 514
{
	return FALSE;
}
static gboolean
515
BC_W(axcext)(ExcelChartHandler const *handle,
516
	     GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
517 518 519 520 521 522 523
{
	return FALSE;
}

/****************************************************************************/

static gboolean
524
BC_R(axislineformat)(ExcelChartHandler const *handle,
525
		     ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
526
{
527
	guint16 const type = MS_OLE_GET_GUINT16 (q->data);
528 529 530 531 532 533 534 535

	printf ("Axisline is ");
	switch (type)
	{
	case 0 : puts ("the axis line."); break;
	case 1 : puts ("a major grid along the axis."); break;
	case 2 : puts ("a minor grid along the axis."); break;

536
	/* TODO TODO : floor vs wall */
537 538 539
	case 3 : puts ("a floor/wall along the axis."); break;
	default : printf ("an ERROR.  unkown type (%x).\n", type);
	};
Michael Meeks's avatar
Michael Meeks committed
540 541 542 543
	return FALSE;
}

static gboolean
544
BC_W(axislineformat)(ExcelChartHandler const *handle,
545
		     GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
546 547 548 549 550 551 552
{
	return FALSE;
}

/****************************************************************************/

static gboolean
553
BC_R(axisparent)(ExcelChartHandler const *handle,
554
		 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
555
{
556
	guint16 const index = MS_OLE_GET_GUINT16 (q->data);	/* 1 or 2 */
557
	/* Measured in 1/4000ths of the chart width */
558 559
	guint32 const x = MS_OLE_GET_GUINT32 (q->data+2);
	guint32 const y = MS_OLE_GET_GUINT32 (q->data+6);
560 561
	guint32 const width = MS_OLE_GET_GUINT32 (q->data+10);
	guint32 const height = MS_OLE_GET_GUINT32 (q->data+14);
562 563

	printf ("Axis # %hu @ %f,%f, X=%f, Y=%f\n",
564
		index, x/4000., y/4000., width/4000., height/4000.);
Michael Meeks's avatar
Michael Meeks committed
565 566 567 568
	return FALSE;
}

static gboolean
569
BC_W(axisparent)(ExcelChartHandler const *handle,
570
		 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
571 572 573 574 575 576 577
{
	return FALSE;
}

/****************************************************************************/

static gboolean
578
BC_R(bar)(ExcelChartHandler const *handle,
579
	  ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
580
{
Jody Goldberg's avatar
Jody Goldberg committed
581
	/* percent of bar width */
582 583
	guint16 const space_between_bar = MS_OLE_GET_GUINT16(q->data);
	guint16 const space_between_categories = MS_OLE_GET_GUINT16(q->data+2);
Jody Goldberg's avatar
Jody Goldberg committed
584

585
	guint16 const flags = MS_OLE_GET_GUINT16(q->data+4);
Jody Goldberg's avatar
Jody Goldberg committed
586 587 588 589 590 591 592 593 594 595 596 597 598 599

	gboolean const horizontal_bar = (flags&0x01) ? TRUE : FALSE;
	gboolean const stacked = (flags&0x02) ? TRUE : FALSE;
	gboolean const as_percentage = (flags&0x04) ? TRUE : FALSE;

	printf ( (horizontal_bar) ? "Horizontal " : "Vertical ");
	if (as_percentage)
		/* TODO : test theory that percentage implies stacked */
		printf ("Stacked Percentage. (%d should be TRUE)\n", stacked);
	else if (stacked)
		printf ("Stacked Percentage values\n");
	else
		printf ("Overlayed values\n");

600 601 602 603
	printf ("Space between bars = %d %% of width\n",
		space_between_bar);
	printf ("Space between categories = %d %% of width\n",
		space_between_categories);
604
	if (s->container.ver >= MS_BIFF_V8)
Jody Goldberg's avatar
Jody Goldberg committed
605 606 607 608 609
	{
		gboolean const has_shadow = (flags & 0x04) ? TRUE : FALSE;
		if (has_shadow)
			puts ("in 3D");
	}
Michael Meeks's avatar
Michael Meeks committed
610 611 612 613
	return FALSE;
}

static gboolean
614
BC_W(bar)(ExcelChartHandler const *handle,
615
	  GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
616 617 618 619 620 621 622
{
	return FALSE;
}

/****************************************************************************/

static gboolean
623
BC_R(begin)(ExcelChartHandler const *handle,
624
	    ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
625
{
626
	puts ("{");
627
	s->stack = g_array_append_val (s->stack, s->prev_opcode);
Michael Meeks's avatar
Michael Meeks committed
628 629 630 631
	return FALSE;
}

static gboolean
632
BC_W(begin)(ExcelChartHandler const *handle,
633
	    GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
634 635 636 637 638 639 640
{
	return FALSE;
}

/****************************************************************************/

static gboolean
641
BC_R(boppop)(ExcelChartHandler const *handle,
642
	     ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
643
{
Jody Goldberg's avatar
Jody Goldberg committed
644
#if 0
645 646 647
	guint8 const type = MS_OLE_GET_GUINT8 (q->data); /* 0-2 */
	gboolean const use_default_split = (MS_OLE_GET_GUINT8 (q->data+1) == 1);
	guint16 const split_type = MS_OLE_GET_GUINT8 (q->data+2); /* 0-3 */
Jody Goldberg's avatar
Jody Goldberg committed
648 649
#endif

650
	gboolean const is_3d = (MS_OLE_GET_GUINT16 (q->data+16) == 1);
Jody Goldberg's avatar
Jody Goldberg committed
651 652 653
	if (is_3d)
		puts("in 3D");

Michael Meeks's avatar
Michael Meeks committed
654 655 656
	return FALSE;
}
static gboolean
657
BC_W(boppop)(ExcelChartHandler const *handle,
658
	     GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
659 660 661 662 663 664 665
{
	return FALSE;
}

/****************************************************************************/

static gboolean
666
BC_R(boppopcustom)(ExcelChartHandler const *handle,
667
		   ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
668
{
Jody Goldberg's avatar
Jody Goldberg committed
669
#if 0
670
	gint16 const count = MS_OLE_GET_GUINT16 (q->data);
Jody Goldberg's avatar
Jody Goldberg committed
671 672
	/* TODO TODO : figure out the bitfield array */
#endif
Michael Meeks's avatar
Michael Meeks committed
673 674 675 676
	return FALSE;
}

static gboolean
677
BC_W(boppopcustom)(ExcelChartHandler const *handle,
678
		   GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
679 680 681 682
{
	return FALSE;
}

683
/***************************************************************************/
Michael Meeks's avatar
Michael Meeks committed
684 685

static gboolean
686
BC_R(catserrange)(ExcelChartHandler const *handle,
687
		  ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
688 689 690 691 692
{
	return FALSE;
}

static gboolean
693
BC_W(catserrange)(ExcelChartHandler const *handle,
694
		  GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
695 696 697 698 699 700 701
{
	return FALSE;
}

/****************************************************************************/

static gboolean
702
BC_R(chart)(ExcelChartHandler const *handle,
703
	    ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
704
{
705
	/* TODO TODO TODO : Why are all charts listed as starting at 0,0 ?? */
706
	/* Fixed point 2 bytes fraction 2 bytes integer */
707 708 709 710
	guint32 const x_pos_fixed = MS_OLE_GET_GUINT32 (q->data + 0);
	guint32 const y_pos_fixed = MS_OLE_GET_GUINT32 (q->data + 4);
	guint32 const x_size_fixed = MS_OLE_GET_GUINT32 (q->data + 8);
	guint32 const y_size_fixed = MS_OLE_GET_GUINT32 (q->data + 12);
711 712

	/* Measured in points (1/72 of an inch) */
713 714 715 716 717
	double const x_pos = x_pos_fixed / (65535. * 72.);
	double const y_pos = y_pos_fixed / (65535. * 72.);
	double const x_size = x_size_fixed / (65535. * 72.);
	double const y_size = y_size_fixed / (65535. * 72.);
	printf("Chart @ %g, %g is %g\" x %g\"\n", x_pos, y_pos, x_size, y_size);
718

Michael Meeks's avatar
Michael Meeks committed
719 720 721 722
	return FALSE;
}

static gboolean
723
BC_W(chart)(ExcelChartHandler const *handle,
724
	    GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
725 726 727 728 729 730 731
{
	return FALSE;
}

/****************************************************************************/

static gboolean
732
BC_R(chartformat)(ExcelChartHandler const *handle,
733
		  ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
734
{
735 736
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data+16);
	guint16 const z_order = MS_OLE_GET_GUINT16 (q->data+18);
737
	gboolean const vary_color = (flags&0x01) ? TRUE : FALSE;
738 739 740 741

	printf ("Z value = %uh\n", z_order);
	if (vary_color)
		printf ("Vary color of every data point\n");
Michael Meeks's avatar
Michael Meeks committed
742 743 744 745
	return FALSE;
}

static gboolean
746
BC_W(chartformat)(ExcelChartHandler const *handle,
747
		  GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
748 749 750 751 752 753 754
{
	return FALSE;
}

/****************************************************************************/

static gboolean
755
BC_R(chartformatlink)(ExcelChartHandler const *handle,
756
		      ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
757
{
Jody Goldberg's avatar
Jody Goldberg committed
758
	/* ignored */
Michael Meeks's avatar
Michael Meeks committed
759 760 761 762
	return FALSE;
}

static gboolean
763
BC_W(chartformatlink)(ExcelChartHandler const *handle,
764
		      GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
765
{
Jody Goldberg's avatar
Jody Goldberg committed
766
	/* ignored */
Michael Meeks's avatar
Michael Meeks committed
767 768 769 770 771 772
	return FALSE;
}

/****************************************************************************/

static gboolean
773
BC_R(chartline)(ExcelChartHandler const *handle,
774
		ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
775
{
776
	guint16 const type = MS_OLE_GET_GUINT16 (q->data);
777

778
	g_return_val_if_fail (type <= 2, FALSE);
779

780 781
	printf ("Use %s lines\n",
		(type == 0) ? "drop" : ((type == 1) ? "hi-lo" : "series"));
Michael Meeks's avatar
Michael Meeks committed
782 783 784 785
	return FALSE;
}

static gboolean
786
BC_W(chartline)(ExcelChartHandler const *handle,
787
		GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
788 789 790 791 792 793 794
{
	return FALSE;
}

/****************************************************************************/

static gboolean
795
BC_R(clrtclient)(ExcelChartHandler const *handle,
796
		 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
797
{
798 799
	puts ("Undocumented BIFF : clrtclient");
	dump_biff(q);
Michael Meeks's avatar
Michael Meeks committed
800 801 802
	return FALSE;
}
static gboolean
803
BC_W(clrtclient)(ExcelChartHandler const *handle,
804
		 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
805 806 807 808 809 810 811
{
	return FALSE;
}

/****************************************************************************/

static gboolean
812
BC_R(dat)(ExcelChartHandler const *handle,
813
	  ExcelChartReadState *s, BiffQuery *q)
814
{
815
#if 0
816
	gint16 const flags = MS_OLE_GET_GUINT16 (q->data);
817 818 819 820
	gboolean const horiz_border = (flags&0x01) ? TRUE : FALSE;
	gboolean const vert_border = (flags&0x02) ? TRUE : FALSE;
	gboolean const border = (flags&0x04) ? TRUE : FALSE;
	gboolean const series_keys = (flags&0x08) ? TRUE : FALSE;
821
#endif
Michael Meeks's avatar
Michael Meeks committed
822 823 824
	return FALSE;
}
static gboolean
825
BC_W(dat)(ExcelChartHandler const *handle,
826
	  GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
827 828 829 830 831 832 833
{
	return FALSE;
}

/****************************************************************************/

static gboolean
834
BC_R(dataformat)(ExcelChartHandler const *handle,
835
		 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
836
{
837 838
	guint16 const pt_num = MS_OLE_GET_GUINT16 (q->data);
	guint16 const series_index = MS_OLE_GET_GUINT16 (q->data+2);
839
#if 0
840 841
	guint16 const series_index_for_label = MS_OLE_GET_GUINT16 (q->data+4);
	guint16 const excel4_auto_color = MS_OLE_GET_GUINT16 (q->data+6) & 0x01;
842
#endif
843 844 845 846 847 848 849

	if (pt_num == 0xffff)
		printf ("All points");
	else
		printf ("Point-%hd", pt_num);

	printf (", series=%hd\n", series_index);
Michael Meeks's avatar
Michael Meeks committed
850 851 852 853
	return FALSE;
}

static gboolean
854
BC_W(dataformat)(ExcelChartHandler const *handle,
855
		 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
856 857 858 859 860 861 862
{
	return FALSE;
}

/****************************************************************************/

static gboolean
863
BC_R(defaulttext)(ExcelChartHandler const *handle,
864
		  ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
865
{
866
	guint16	const tmp = MS_OLE_GET_GUINT16 (q->data);
Michael Meeks's avatar
Michael Meeks committed
867 868 869
	printf ("applicability = %hd\n", tmp);

	/*
870 871 872 873
	 * 0 == 'show labels' label
	 * 1 == Value and percentage data label
	 * 2 == All text in chart
	 * 3 == Undocumented ??
Michael Meeks's avatar
Michael Meeks committed
874 875 876 877 878 879
	 */
	g_return_val_if_fail (tmp <= 3, TRUE);
	return FALSE;
}

static gboolean
880
BC_W(defaulttext)(ExcelChartHandler const *handle,
881
		  GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
882 883 884 885 886 887 888
{
	return FALSE;
}

/****************************************************************************/

static gboolean
889
BC_R(dropbar)(ExcelChartHandler const *handle,
890
	      ExcelChartReadState *s, BiffQuery *q)
891
{
892
	guint16 const width = MS_OLE_GET_GUINT16 (q->data);	/* 0-100 */
893
	g_return_val_if_fail (width <= 100, FALSE);
Michael Meeks's avatar
Michael Meeks committed
894 895 896 897
	return FALSE;
}

static gboolean
898
BC_W(dropbar)(ExcelChartHandler const *handle,
899
	      GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
900 901 902 903 904 905 906
{
	return FALSE;
}

/****************************************************************************/

static gboolean
907
BC_R(fbi)(ExcelChartHandler const *handle,
908
	  ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
909
{
910 911 912 913
	/*
	 * TODO TODO TODO : Work on appropriate scales.
	 * Is any of this useful other than the index ?
	 */
914 915 916 917 918
	guint16 const x_basis = MS_OLE_GET_GUINT16 (q->data);
	guint16 const y_basis = MS_OLE_GET_GUINT16 (q->data+2);
	guint16 const applied_height = MS_OLE_GET_GUINT16 (q->data+4);
	guint16 const scale_basis = MS_OLE_GET_GUINT16 (q->data+6);
	guint16 const index = MS_OLE_GET_GUINT16 (q->data+8);
919 920 921

	printf ("Font %hu (%hu x %hu) scale=%hu, height=%hu\n",
		index, x_basis, y_basis, scale_basis, applied_height);
Michael Meeks's avatar
Michael Meeks committed
922 923 924
	return FALSE;
}
static gboolean
925
BC_W(fbi)(ExcelChartHandler const *handle,
926
	  GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
927 928 929 930 931 932 933
{
	return FALSE;
}

/****************************************************************************/

static gboolean
934
BC_R(fontx)(ExcelChartHandler const *handle,
935
	    ExcelChartReadState *s, BiffQuery *q)
936
{
937
#if 0
938
	/* Child of TEXT, index into FONT table */
939
	guint16 const font = MS_OLE_GET_GUINT16 (q->data);
940
#endif
Michael Meeks's avatar
Michael Meeks committed
941 942 943 944
	return FALSE;
}

static gboolean
945
BC_W(fontx)(ExcelChartHandler const *handle,
946
	    GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
947 948 949 950 951 952 953
{
	return F