ms-chart.c 64.3 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
/**
 * ms-chart.c: MS Excel chart support for Gnumeric
 *
 * Author:
Jody Goldberg's avatar
Jody Goldberg committed
6
 *    Jody Goldberg (jody@gnome.org)
7
 *
8
 * (C) 1999-2001 Jody Goldberg
9 10
 **/

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

#include <parse-util.h>
#include <style-color.h>
#include <format.h>
#include <expr.h>
24
#include <value.h>
25 26
#include <gutils.h>

27
#ifdef WITH_BONOBO
28
#include <gnumeric-graph.h>
29
#endif
Jody Goldberg's avatar
Jody Goldberg committed
30
#include <xml-io.h>
31
#include <gal/util/e-xml-utils.h>
Jody Goldberg's avatar
Jody Goldberg committed
32
#include <libxml/tree.h>
33
#include <stdio.h>
34
#include <math.h>
Michael Meeks's avatar
Michael Meeks committed
35

36
/* #define NO_DEBUG_EXCEL */
37 38 39 40 41
#ifndef NO_DEBUG_EXCEL
#define d(level, code)	do { if (ms_excel_chart_debug > level) { code } } while (0)
#else
#define d(level, code)
#endif
Michael Meeks's avatar
Michael Meeks committed
42

43 44 45 46 47 48 49 50 51
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;

52 53 54 55 56
char const *const ms_vector_purpose_type_name [] =
{
    "labels", "values", "categories", "bubbles",
};

57 58 59
typedef struct _ExcelChartSeries
{
	struct {
60
#ifdef WITH_BONOBO
61
		GnmGraphVectorType type;
62
#endif
63
		int count, remote_ID;
64 65
	} vector [MS_VECTOR_PURPOSE_MAX];

66
	int chart_group;
67
	xmlNode	*xml;
68 69
} ExcelChartSeries;

Michael Meeks's avatar
Michael Meeks committed
70 71
typedef struct
{
72 73 74
	MSContainer	 container;

	MSContainer	*parent;
75
	GArray		*stack;
76
	MsBiffVersion	 ver;
77
	guint32		 prev_opcode;
78 79
	GnmGraph	*graph;

80
	struct {
81 82 83 84 85
		xmlDoc	*doc;
		xmlNs	*ns;
		xmlNode *plots;
		xmlNode *currentChartGroup;
		xmlNode *dataFormat;
86
	} xml;
87

88
	int plot_counter;
89 90 91
	ExcelChartSeries *currentSeries;
	GPtrArray	 *series;
} ExcelChartReadState;
Michael Meeks's avatar
Michael Meeks committed
92 93 94

typedef struct
{
95
	int dummy;
96
} GnumericChartState;
Michael Meeks's avatar
Michael Meeks committed
97

98 99
typedef struct biff_chart_handler ExcelChartHandler;
typedef gboolean (*ExcelChartReader)(ExcelChartHandler const *handle,
100
				     ExcelChartReadState *, BiffQuery *q);
101
typedef gboolean (*ExcelChartWriter)(ExcelChartHandler const *handle,
102
				     GnumericChartState *, BiffPut *os);
Michael Meeks's avatar
Michael Meeks committed
103 104 105
struct biff_chart_handler
{
	guint16 const opcode;
106
	int const	min_size; /* To be useful this needs to be versioned */
107 108 109
	char const *const name;
	ExcelChartReader const read_fn;
	ExcelChartWriter const write_fn;
Michael Meeks's avatar
Michael Meeks committed
110 111 112
};

#define BC(n)	biff_chart_ ## n
113 114
#define BC_R(n)	BC(read_ ## n)
#define BC_W(n)	BC(write_ ## n)
Michael Meeks's avatar
Michael Meeks committed
115

116 117 118 119 120 121 122 123 124
static ExcelChartSeries *
excel_chart_series_new (void)
{
	ExcelChartSeries *series;
	int i;

	series = g_new (ExcelChartSeries, 1);

	series->chart_group = -1;
125
	series->xml = NULL;
126
	for (i = MS_VECTOR_PURPOSE_MAX; i-- > 0 ; ) {
127
		series->vector [i].remote_ID = -1;
128
#ifdef WITH_BONOBO
129
		series->vector [i].type = GNM_VECTOR_AUTO; /* may be reset later */
130
#endif
131 132 133
	}

	/* labels are always strings */
134
#ifdef WITH_BONOBO
135
	series->vector [MS_VECTOR_PURPOSE_LABELS].type = GNM_VECTOR_STRING;
136
#endif
137 138 139 140 141 142 143 144 145 146

	return series;
}

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

147 148 149

static void
excel_chart_series_write_xml (ExcelChartSeries *series,
150
			      ExcelChartReadState *s, xmlNode *data)
151 152 153
{
	unsigned i;

154
	g_return_if_fail (series->xml != NULL);
155

156
	xmlAddChild (data, series->xml);
157 158
	for (i = 0 ; i < MS_VECTOR_PURPOSE_MAX; i++ )
		if (series->vector [i].remote_ID >= 0) {
159
#ifdef WITH_BONOBO
160
			xmlNode *v = gnm_graph_series_add_dimension (series->xml,
161
				ms_vector_purpose_type_name [i]);
162
			if (v != NULL)
Jody Goldberg's avatar
Jody Goldberg committed
163
				e_xml_set_integer_prop_by_name (v, (xmlChar *)"ID",
164
					series->vector [i].remote_ID);
165
#endif
166 167 168
		}
}

169 170 171 172 173 174 175
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);
}

176
static void
Jody Goldberg's avatar
Jody Goldberg committed
177
BC_R(color) (guint8 const *data, xmlChar *type, xmlNode *node, gboolean transparent)
Michael Meeks's avatar
Michael Meeks committed
178
{
Jody Goldberg's avatar
Jody Goldberg committed
179
	static xmlChar buf[20];
180
	guint32 const rgb = MS_OLE_GET_GUINT32 (data);
Michael Meeks's avatar
Michael Meeks committed
181 182 183 184
	guint16 const r = (rgb >>  0) & 0xff;
	guint16 const g = (rgb >>  8) & 0xff;
	guint16 const b = (rgb >> 16) & 0xff;

Jody Goldberg's avatar
Jody Goldberg committed
185
	sprintf ((char *)buf, "%02x:%02x:%02x", r, g, b);
186 187 188
	xmlSetProp (node, type, buf);

	d (0, printf("%s %02x:%02x:%02x;\n", type, r, g, b););
Michael Meeks's avatar
Michael Meeks committed
189 190
}

191
static xmlNode *
Jody Goldberg's avatar
Jody Goldberg committed
192
BC_R(store_chartgroup_type)(ExcelChartReadState *s, xmlChar const *t)
193
{
194
	xmlNode *fmt;
195 196 197

	g_return_val_if_fail (s->xml.currentChartGroup != NULL, NULL);

Jody Goldberg's avatar
Jody Goldberg committed
198
	fmt = e_xml_get_child_by_name (s->xml.currentChartGroup, (xmlChar *)"Type");
199 200 201

	g_return_val_if_fail (fmt == NULL, NULL);

Jody Goldberg's avatar
Jody Goldberg committed
202 203
	fmt = xmlNewChild (s->xml.currentChartGroup, s->xml.ns, (xmlChar *)"Type", NULL);
	xmlSetProp (fmt, (xmlChar *)"name", t);
204
	return fmt;
205 206
}

Michael Meeks's avatar
Michael Meeks committed
207 208 209
/****************************************************************************/

static gboolean
210
BC_R(3dbarshape)(ExcelChartHandler const *handle,
211
		 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
212
{
213
	d (0, {
214 215 216 217 218 219 220 221 222
		guint16 const type = MS_OLE_GET_GUINT16 (q->data);
		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);
		};
223
	});
Michael Meeks's avatar
Michael Meeks committed
224 225 226 227

	return FALSE;
}
static gboolean
228
BC_W(3dbarshape)(ExcelChartHandler const *handle,
229
		 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
230 231 232 233 234 235 236
{
	return FALSE;
}

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

static gboolean
237
BC_R(3d)(ExcelChartHandler const *handle,
238
	 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
239
{
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
	d (0, {
		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);

		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;

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

		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)
			puts ("Use perspective");
		if (cluster)
			puts ("Cluster");
		if (auto_scale)
			puts ("Auto Scale");
		if (walls_2d)
			puts ("2D Walls");
	});

Michael Meeks's avatar
Michael Meeks committed
274 275 276 277
	return FALSE;
}

static gboolean
278
BC_W(3d)(ExcelChartHandler const *handle,
279
	 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
280 281 282 283 284 285
{
	return FALSE;
}

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

286
static gboolean
287
BC_R(ai)(ExcelChartHandler const *handle,
288
	 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
289
{
290
	guint8 const purpose = MS_OLE_GET_GUINT8 (q->data);
291
	guint8 const ref_type = MS_OLE_GET_GUINT8 (q->data + 1);
292 293
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data + 2);
	guint16 const length = MS_OLE_GET_GUINT16 (q->data + 6);
294

295 296 297 298 299 300
	int popped_state = BC_R(top_state) (s);

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

301 302
	/* Rest are 0 */
	if (flags&0x01) {
Jody Goldberg's avatar
Jody Goldberg committed
303
		StyleFormat *fmt = ms_container_get_fmt (&s->container,
304
			MS_OLE_GET_GUINT16 (q->data + 4));
305
		d (2, puts ("Has Custom number format"););
306 307
		if (fmt != NULL) {
			char * desc = style_format_as_XL (fmt, FALSE);
308
			d (2, printf ("Format = '%s';\n", desc););
309
			g_free (desc);
Morten Welinder's avatar
Morten Welinder committed
310 311

			style_format_unref (fmt);
312
		}
313 314 315
	} else {
		d (2, puts ("Uses number format from data source"););
	}
316

317
	g_return_val_if_fail (purpose < MS_VECTOR_PURPOSE_MAX, TRUE);
318
	d (0, {
319
	switch (purpose) {
320
	case MS_VECTOR_PURPOSE_LABELS :	    puts ("Linking labels"); break;
321 322 323
	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
324
	default :
325
		g_assert_not_reached ();
326
	};
327
	switch (ref_type) {
328 329
	case 0 : puts ("Use default categories"); break;
	case 1 : puts ("Text/Value entered directly"); break;
Jody Goldberg's avatar
Jody Goldberg committed
330
	case 2 : puts ("Linked to Container"); break;
331
	case 4 : puts ("'Error reported' what the heck is this ??"); break;
332
	default :
333
		 printf ("UKNOWN : reference type (%x)\n", ref_type);
Michael Meeks's avatar
Michael Meeks committed
334
	};
335
	});
Michael Meeks's avatar
Michael Meeks committed
336

Jody Goldberg's avatar
Jody Goldberg committed
337
	/* (2) == linked to container */
338
	if (ref_type == 2) {
339 340
		GnmExpr const *expr = ms_container_parse_expr (s->parent,
			q->data+8, length);
341
		if (expr) {
342 343 344
			Sheet *sheet = ms_container_sheet (s->parent);

			g_return_val_if_fail (sheet != NULL, FALSE);
345 346
			g_return_val_if_fail (s->currentSeries != NULL, TRUE);

347
#ifdef WITH_BONOBO
348
			s->currentSeries->vector [purpose].remote_ID =
349
				gnm_graph_add_vector (s->graph, expr,
350 351
					s->currentSeries->vector [purpose].type,
					sheet);
352 353 354 355
#endif

		}
	} else {
356
		g_return_val_if_fail (length == 0, TRUE);
357 358
	}

Michael Meeks's avatar
Michael Meeks committed
359 360 361 362
	return FALSE;
}

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

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

static gboolean
372
BC_R(alruns)(ExcelChartHandler const *handle,
373
	     ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
374
{
375
	gint16 length = MS_OLE_GET_GUINT16 (q->data);
376
	guint8 const *in = (q->data + 2);
377 378
	char *const ans = (char *) g_new (char, length + 2);
	char *out = ans;
Michael Meeks's avatar
Michael Meeks committed
379

380
	for (; --length >= 0 ; in+=4, ++out) {
381 382 383 384
		/*
		 * FIXME FIXME FIXME :
		 *        - don't toss font info
		 *        - Merge streams of the same font together.
Jody Goldberg's avatar
Jody Goldberg committed
385
		 *        - Combine with RTF support once merged
386
		 */
387
		guint32 const elem = MS_OLE_GET_GUINT32 (in);
388
		*out = (char)((elem >> 16) & 0xff);
Michael Meeks's avatar
Michael Meeks committed
389
	}
390 391
	*out = '\0';

392
	/*puts (ans);*/
Michael Meeks's avatar
Michael Meeks committed
393 394 395 396
	return FALSE;
}

static gboolean
397
BC_W(alruns)(ExcelChartHandler const *handle,
398
	     GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
399 400 401 402 403 404 405
{
	return FALSE;
}

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

static gboolean
406
BC_R(area)(ExcelChartHandler const *handle,
407
	   ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
408
{
409
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data);
410 411
	gboolean const stacked = (flags & 0x01) ? TRUE : FALSE;
	gboolean const as_percentage = (flags & 0x02) ? TRUE : FALSE;
Michael Meeks's avatar
Michael Meeks committed
412

413
	d (0, {
Jody Goldberg's avatar
Jody Goldberg committed
414 415 416 417 418 419 420
	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");
421
	});
Jody Goldberg's avatar
Jody Goldberg committed
422

423
	if (s->container.ver >= MS_BIFF_V8)
Michael Meeks's avatar
Michael Meeks committed
424
	{
425
		d (0, {
426
		gboolean const has_shadow = (flags & 0x04) ? TRUE : FALSE;
Jody Goldberg's avatar
Jody Goldberg committed
427 428
		if (has_shadow)
			puts ("in 3D");
429
		});
Michael Meeks's avatar
Michael Meeks committed
430 431 432 433 434
	}
	return FALSE;
}

static gboolean
435
BC_W(area)(ExcelChartHandler const *handle,
436
	   GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
437 438 439 440 441 442 443
{
	return FALSE;
}

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

static gboolean
444
BC_R(areaformat)(ExcelChartHandler const *handle,
445
		 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
446
{
447
	xmlNode *area = NULL;
448
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data+10);
Jody Goldberg's avatar
Jody Goldberg committed
449
	gboolean const auto_format = (flags & 0x01) ? TRUE : FALSE;
450 451 452

	d (0, {
	guint16 const pattern = MS_OLE_GET_GUINT16 (q->data+8);
Michael Meeks's avatar
Michael Meeks committed
453 454
	gboolean const swap_color_for_negative = flags & 0x02;

455 456 457 458 459
	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;");
460 461 462 463
	});

	/* These apply to frames also */
	if (s->xml.dataFormat != NULL) {
Jody Goldberg's avatar
Jody Goldberg committed
464
		area = e_xml_get_child_by_name (s->xml.dataFormat, (xmlChar *)"Area");
465 466
		if (area == NULL)
			area = xmlNewChild (s->xml.dataFormat, s->xml.ns,
Jody Goldberg's avatar
Jody Goldberg committed
467
					    (xmlChar *)"Area", NULL);
468 469
	}
	if (area != NULL && !auto_format) {
Jody Goldberg's avatar
Jody Goldberg committed
470 471
		BC_R(color) (q->data, (xmlChar *)"ForegroundColour", area, FALSE);
		BC_R(color) (q->data+4, (xmlChar *)"BackgroundColour", area, FALSE);
472
	}
473 474 475 476
#if 0
	/* Ignore the colour indicies.  Use the colours themselves
	 * to avoid problems with guessing the strange index values
	 */
477
	if (s->container.ver >= MS_BIFF_V8)
Michael Meeks's avatar
Michael Meeks committed
478
	{
479 480
		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
481 482 483

		/* TODO : Ignore result for now,
		 * Which to use, fore and back, or these ? */
484 485
		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
486
	}
487
#endif
Michael Meeks's avatar
Michael Meeks committed
488 489 490 491
	return FALSE;
}

static gboolean
492
BC_W(areaformat)(ExcelChartHandler const *handle,
493
		 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
494 495 496 497 498 499 500
{
	return FALSE;
}

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

static gboolean
501
BC_R(attachedlabel)(ExcelChartHandler const *handle,
502
		    ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
503
{
504
	d (3,{
505
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data);
506 507 508 509 510
	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;
511 512 513 514 515 516 517 518 519 520 521 522

	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");

523
	if (s->container.ver >= MS_BIFF_V8)
524 525
	{
		gboolean const show_bubble_size = (flags&0x20) ? TRUE : FALSE;
526 527
		if (show_bubble_size)
			puts ("Show bubble size");
528
	}
529
	});
Michael Meeks's avatar
Michael Meeks committed
530 531 532 533
	return FALSE;
}

static gboolean
534
BC_W(attachedlabel)(ExcelChartHandler const *handle,
535
		    GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
536 537 538 539 540 541 542
{
	return FALSE;
}

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

static gboolean
543
BC_R(axesused)(ExcelChartHandler const *handle,
544
	       ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
545
{
546
	guint16 const num_axis = MS_OLE_GET_GUINT16 (q->data);
547
	g_return_val_if_fail(1 <= num_axis && num_axis <= 2, TRUE);
548
	d (0, printf ("There are %hu axis.\n", num_axis););
Michael Meeks's avatar
Michael Meeks committed
549 550 551 552
	return FALSE;
}

static gboolean
553
BC_W(axesused)(ExcelChartHandler const *handle,
554
	       GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
555 556 557 558 559 560
{
	return FALSE;
}

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

561 562 563 564 565 566 567
typedef enum
{
	MS_AXIS_X	= 0,
	MS_AXIS_Y	= 1,
	MS_AXIS_SERIES	= 2,
	MS_AXIS_MAX	= 3
} MS_AXIS;
568
static char const *const ms_axis[] =
569 570 571 572
{
	"X-axis", "Y-axis", "series-axis"
};

Michael Meeks's avatar
Michael Meeks committed
573
static gboolean
574
BC_R(axis)(ExcelChartHandler const *handle,
575
	   ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
576
{
577
	guint16 const axis_type = MS_OLE_GET_GUINT16 (q->data);
578 579 580
	MS_AXIS atype;
	g_return_val_if_fail (axis_type < MS_AXIS_MAX, TRUE);
	atype = axis_type;
581
	d (0, printf ("This is a %s .\n", ms_axis[atype]););
Michael Meeks's avatar
Michael Meeks committed
582 583 584 585
	return FALSE;
}

static gboolean
586
BC_W(axis)(ExcelChartHandler const *handle,
587
	   GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
588 589 590 591 592 593 594
{
	return FALSE;
}

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

static gboolean
595
BC_R(axcext)(ExcelChartHandler const *handle,
596
	     ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
597 598 599 600
{
	return FALSE;
}
static gboolean
601
BC_W(axcext)(ExcelChartHandler const *handle,
602
	     GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
603 604 605 606 607 608 609
{
	return FALSE;
}

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

static gboolean
610
BC_R(axislineformat)(ExcelChartHandler const *handle,
611
		     ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
612
{
613
	d (0, {
614
	guint16 const type = MS_OLE_GET_GUINT16 (q->data);
615 616 617 618 619 620 621 622

	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;

623
	/* TODO TODO : floor vs wall */
624 625 626
	case 3 : puts ("a floor/wall along the axis."); break;
	default : printf ("an ERROR.  unkown type (%x).\n", type);
	};
627
	});
Michael Meeks's avatar
Michael Meeks committed
628 629 630 631
	return FALSE;
}

static gboolean
632
BC_W(axislineformat)(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(axisparent)(ExcelChartHandler const *handle,
642
		 ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
643
{
644
	d (0, {
645
	guint16 const index = MS_OLE_GET_GUINT16 (q->data);	/* 1 or 2 */
646
	/* Measured in 1/4000ths of the chart width */
647 648
	guint32 const x = MS_OLE_GET_GUINT32 (q->data+2);
	guint32 const y = MS_OLE_GET_GUINT32 (q->data+6);
649 650
	guint32 const width = MS_OLE_GET_GUINT32 (q->data+10);
	guint32 const height = MS_OLE_GET_GUINT32 (q->data+14);
651 652

	printf ("Axis # %hu @ %f,%f, X=%f, Y=%f\n",
653
		index, x/4000., y/4000., width/4000., height/4000.);
654
	});
Michael Meeks's avatar
Michael Meeks committed
655 656 657 658
	return FALSE;
}

static gboolean
659
BC_W(axisparent)(ExcelChartHandler const *handle,
660
		 GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
661 662 663 664 665 666 667
{
	return FALSE;
}

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

static gboolean
668
BC_R(bar)(ExcelChartHandler const *handle,
669
	  ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
670
{
671
	guint16 const flags = MS_OLE_GET_GUINT16 (q->data+4);
Jody Goldberg's avatar
Jody Goldberg committed
672

Jody Goldberg's avatar
Jody Goldberg committed
673
	xmlNode *tmp, *fmt = BC_R(store_chartgroup_type)(s, (xmlChar *)"Bar");
Jody Goldberg's avatar
Jody Goldberg committed
674

675
	g_return_val_if_fail (fmt != NULL, TRUE);
Jody Goldberg's avatar
Jody Goldberg committed
676

677
	/* Always set this it makes things clearer */
Jody Goldberg's avatar
Jody Goldberg committed
678 679
	xmlNewChild (fmt, fmt->ns, (xmlChar *)"horizontal",
		(xmlChar *)((flags & 0x01) ? "true" : "false"));
680 681

	if (flags & 0x04)
Jody Goldberg's avatar
Jody Goldberg committed
682
		xmlNewChild (fmt, fmt->ns, (xmlChar *)"as_percentage", NULL);
683
	else if (flags & 0x02)
Jody Goldberg's avatar
Jody Goldberg committed
684
		xmlNewChild (fmt, fmt->ns, (xmlChar *)"stacked", NULL);
685 686

	if (s->container.ver >= MS_BIFF_V8 && (flags & 0x08))
Jody Goldberg's avatar
Jody Goldberg committed
687
		xmlNewChild (fmt, fmt->ns, (xmlChar *)"in_3d", NULL);
688

Jody Goldberg's avatar
Jody Goldberg committed
689
	tmp = xmlNewChild (fmt, fmt->ns, (xmlChar *)"percentage_space_between_items", NULL);
690
	xml_node_set_int (tmp, NULL, MS_OLE_GET_GUINT16 (q->data));
Jody Goldberg's avatar
Jody Goldberg committed
691
	tmp = xmlNewChild (fmt, fmt->ns, (xmlChar *)"percentage_space_between_groups", NULL);
Jody Goldberg's avatar
typo.  
Jody Goldberg committed
692
	xml_node_set_int (tmp, NULL, MS_OLE_GET_GUINT16 (q->data+2));
Jody Goldberg's avatar
Jody Goldberg committed
693

Michael Meeks's avatar
Michael Meeks committed
694 695 696 697
	return FALSE;
}

static gboolean
698
BC_W(bar)(ExcelChartHandler const *handle,
699
	  GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
700 701 702 703 704 705 706
{
	return FALSE;
}

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

static gboolean
707
BC_R(begin)(ExcelChartHandler const *handle,
708
	    ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
709
{
710
	d(0, puts ("{"););
711
	s->stack = g_array_append_val (s->stack, s->prev_opcode);
Michael Meeks's avatar
Michael Meeks committed
712 713 714 715
	return FALSE;
}

static gboolean
716
BC_W(begin)(ExcelChartHandler const *handle,
717
	    GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
718 719 720 721 722 723 724
{
	return FALSE;
}

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

static gboolean
725
BC_R(boppop)(ExcelChartHandler const *handle,
726
	     ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
727
{
Jody Goldberg's avatar
Jody Goldberg committed
728
#if 0
729 730 731
	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
732 733
#endif

734
	gboolean const is_3d = (MS_OLE_GET_GUINT16 (q->data+16) == 1);
Jody Goldberg's avatar
Jody Goldberg committed
735 736 737
	if (is_3d)
		puts("in 3D");

Michael Meeks's avatar
Michael Meeks committed
738 739 740
	return FALSE;
}
static gboolean
741
BC_W(boppop)(ExcelChartHandler const *handle,
742
	     GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
743 744 745 746 747 748 749
{
	return FALSE;
}

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

static gboolean
750
BC_R(boppopcustom)(ExcelChartHandler const *handle,
751
		   ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
752
{
Jody Goldberg's avatar
Jody Goldberg committed
753
#if 0
754
	gint16 const count = MS_OLE_GET_GUINT16 (q->data);
Jody Goldberg's avatar
Jody Goldberg committed
755 756
	/* TODO TODO : figure out the bitfield array */
#endif
Michael Meeks's avatar
Michael Meeks committed
757 758 759 760
	return FALSE;
}

static gboolean
761
BC_W(boppopcustom)(ExcelChartHandler const *handle,
762
		   GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
763 764 765 766
{
	return FALSE;
}

767
/***************************************************************************/
Michael Meeks's avatar
Michael Meeks committed
768 769

static gboolean
770
BC_R(catserrange)(ExcelChartHandler const *handle,
771
		  ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
772 773 774 775 776
{
	return FALSE;
}

static gboolean
777
BC_W(catserrange)(ExcelChartHandler const *handle,
778
		  GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
779 780 781 782 783 784 785
{
	return FALSE;
}

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

static gboolean
786
BC_R(chart)(ExcelChartHandler const *handle,
787
	    ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
788
{
789
	d (0, {
790
	/* Fixed point 2 bytes fraction 2 bytes integer */
791 792 793 794
	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);
795 796

	/* Measured in points (1/72 of an inch) */
797 798 799 800 801
	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);
802
	});
803

Michael Meeks's avatar
Michael Meeks committed
804 805 806 807
	return FALSE;
}

static gboolean
808
BC_W(chart)(ExcelChartHandler const *handle,
809
	    GnumericChartState *s, BiffPut *os)
Michael Meeks's avatar
Michael Meeks committed
810 811 812 813 814 815 816
{
	return FALSE;
}

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

static gboolean
817
BC_R(chartformat)(ExcelChartHandler const *handle,
818
		  ExcelChartReadState *s, BiffQuery *q)
Michael Meeks's avatar
Michael Meeks committed
819
{