dialog-printer-setup.c 88.3 KB
Newer Older
1
/*
2 3
 * dialog-printer-setup.c: Printer setup dialog box
 *
4
 * Authors:
5
 *  Wayne Schuller (k_wayne@linuxpower.org)
6
 *  Miguel de Icaza (miguel@gnu.org)
7
 *  Andreas J. Guelzow (aguelzow@pyrshep.ca)
jpekka's avatar
jpekka committed
8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
21
 */
22
#include <gnumeric-config.h>
23
#include <glib/gi18n-lib.h>
24
#include <gnumeric.h>
25 26
#include <dialogs/dialogs.h>
#include <dialogs/help.h>
27 28

#include <gui-util.h>
29
#include <commands.h>
30 31 32 33
#include <print-info.h>
#include <print.h>
#include <ranges.h>
#include <sheet.h>
34
#include <sheet-object-graph.h>
35
#include <workbook.h>
36
#include <wbc-gtk.h>
37
#include <style.h>
38
#include <gnumeric-conf.h>
39

40
#include <gdk/gdkkeysyms.h>
41
#include <goffice/goffice.h>
42
#include <string.h>
43 44 45 46

#define PREVIEW_MARGIN_X 20
#define PREVIEW_MARGIN_Y 20

47
#define MARGIN_COLOR_DEFAULT 0xa9a9a9ff /* dark gray */
48
#define MARGIN_COLOR_ACTIVE GO_COLOR_RED
49

50
/* FIXME: do not hardcode pixel counts.  */
51
#define HF_PREVIEW_X 350
52
#define HF_PREVIEW_Y 75
53 54
#define HF_PREVIEW_SHADOW 2
#define HF_PREVIEW_PADDING 5
55
#define HF_PREVIEW_MARGIN 10
56

57 58
#define PRINTER_SETUP_KEY "printer-setup-dialog"

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
59
#define PAPER_PAGE 0
60 61
#define SCALE_PAGE 1
#define HF_PAGE 2
62

63 64
#define HF_TAG_NAME "field_tag"

65
typedef struct {
66
	/* The Canvas object */
67 68 69
	GtkWidget        *canvas;

	/* Objects in the Preview Canvas */
70
	GocItem  *group;
71

72
	/* Values for the scaling of the nice preview */
73
	int width, height;
74 75
	int offset_x, offset_y;	/* For centering the small page preview */
	double scale;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
76 77
} MarginPreviewInfo;

78 79
typedef struct {
	/* The available width and height for the nice preview page */
80
	guint height, width;
81
} MarginPreviewPageAvailableSize;
82

83 84 85 86 87
typedef struct {
	/* The Canvas object for the header/footer sample preview */
	GtkWidget        *canvas;

	/* Objects in the Preview Canvas */
88 89 90
	GocItem		*left;
	GocItem		*middle;
	GocItem		*right;
91 92 93

} HFPreviewInfo;

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
94 95

typedef struct _PrinterSetupState PrinterSetupState;
96 97 98
typedef struct {
	double     value;
	GtkSpinButton *spin;
99
	GocItem *line;
100
	double bound_x1, bound_y1, bound_x2, bound_y2;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
101
	MarginPreviewInfo *pi;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
102
	PrinterSetupState *state;
103 104
} UnitInfo;

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
105
struct _PrinterSetupState {
106
	WBCGtk  *wbcg;
107
	Sheet            *sheet;
108
	GtkBuilder       *gui;
Morten Welinder's avatar
Morten Welinder committed
109
	GnmPrintInformation *pi;
110
	GtkWidget        *dialog;
111
	GtkWidget        *sheet_selector;
112

113 114 115
	GtkWidget        *scale_percent_radio;
	GtkWidget        *scale_fit_to_radio;
	GtkWidget        *scale_no_radio;
116

117 118 119 120 121
	GtkWidget        *portrait_radio;
	GtkWidget        *landscape_radio;
	GtkWidget        *rev_portrait_radio;
	GtkWidget        *rev_landscape_radio;

122
	GtkWidget        *unit_selector;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
123 124
	GtkTreeModel     *unit_model;
	GtkUnit		  display_unit;
125

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
126 127 128 129
	struct {
		UnitInfo top, bottom, left, right;
		UnitInfo header, footer;
	} margins;
130

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
131
	MarginPreviewInfo preview;
132

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
133 134
	double height, width;

135
	GtkWidget * check_center_v;
Morten Welinder's avatar
Morten Welinder committed
136
	GtkWidget * check_center_h;
137

138 139
	GtkWidget *icon_rd;
	GtkWidget *icon_dr;
140 141 142
	GnmExprEntry *area_entry;
	GnmExprEntry *top_entry;
	GnmExprEntry *left_entry;
143

144
	/* The header and footer data. */
Morten Welinder's avatar
Morten Welinder committed
145 146
	GnmPrintHF *header;
	GnmPrintHF *footer;
Morten Welinder's avatar
Morten Welinder committed
147

148 149 150
	/* The header and footer customize dialogs. */
	GtkWidget *customize_header;
	GtkWidget *customize_footer;
151

152
	/* The header and footer preview widgets. */
153 154
	HFPreviewInfo *pi_header;
	HFPreviewInfo *pi_footer;
155 156

	/* Error Display */
157
	struct {
158 159 160 161 162
		GtkListStore    *store;
		GtkWidget	*combo;
	} error_display;

	/* Comment Display */
163
	struct {
164 165 166
		GtkListStore    *store;
		GtkWidget	*combo;
	} comment_display;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
167
};
168

169
typedef struct _HFCustomizeState HFCustomizeState;
170 171 172 173

typedef struct _HFDTFormatState HFDTFormatState;
struct _HFDTFormatState {
	GtkWidget        *dialog;
174
	GtkBuilder       *gui;
175 176 177 178 179
	HFCustomizeState *hf_state;
	char             *format_string;
	GtkWidget        *format_sel;
};

180 181
struct _HFCustomizeState {
	GtkWidget        *dialog;
182
	GtkBuilder       *gui;
183
	PrinterSetupState *printer_setup_state;
Morten Welinder's avatar
Morten Welinder committed
184
	GnmPrintHF          **hf;
185
	gboolean         is_header;
186 187 188 189 190 191 192 193
	GtkTextBuffer    *left_buffer;
	GtkTextBuffer    *middle_buffer;
	GtkTextBuffer    *right_buffer;
	GList            *marks;
};

typedef enum {
	HF_FIELD_UNKNOWN,
Morten Welinder's avatar
Morten Welinder committed
194
	HF_FIELD_FILE,
195 196 197 198 199
	HF_FIELD_PATH,
	HF_FIELD_DATE,
	HF_FIELD_TIME,
	HF_FIELD_PAGE,
	HF_FIELD_PAGES,
200 201
	HF_FIELD_SHEET,
	HF_FIELD_CELL
202 203 204 205 206 207 208
} HFFieldType;

typedef struct _HFMarkInfo HFMarkInfo;
struct _HFMarkInfo {
	GtkTextMark *mark;
	HFFieldType type;
	char *options;
209 210
};

211
static void dialog_gtk_printer_setup_cb (PrinterSetupState *state);
212
static void fetch_settings (PrinterSetupState *state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
213
static void do_update_page (PrinterSetupState *state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
214
static void do_fetch_margins (PrinterSetupState *state);
215
static void do_hf_customize (gboolean header, PrinterSetupState *state);
216 217
static char *do_hf_dt_format_customize (gboolean date, HFCustomizeState *hf_state);

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

static double
get_conversion_factor (GtkUnit unit)
{
	switch (unit) {
	case GTK_UNIT_MM:
		return (72./25.4);
	case GTK_UNIT_INCH:
		return 72.;
	case GTK_UNIT_PIXEL:
	case GTK_UNIT_POINTS:
	default:
		return 1.0;
	}
}
233

234
static void
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
235
margin_preview_page_destroy (PrinterSetupState *state)
236
{
237
	if (state->preview.group) {
238
		g_object_unref (state->preview.group);
239
		state->preview.group = NULL;
240 241 242
	}
}

243
static void
244
move_line (GocItem *item,
245 246 247
	   double x1, double y1,
	   double x2, double y2)
{
248 249 250 251 252 253 254
	if (item != NULL)
		goc_item_set (item,
			     "x0", floor (x1) + .5,
			     "y0", floor (y1) + .5,
			     "x1", floor (x2) + .5,
			     "y1", floor (y2) + .5,
			     NULL);
255 256
}

257 258
static GocItem *
make_line (GocGroup *g, double x1, double y1, double x2, double y2)
259 260
{

261 262
	GocItem *item;
	GOStyle *style;
263

264 265 266 267 268 269
	item = goc_item_new (
		g, goc_line_get_type (),
		"x0", floor (x1) + .5,
		"y0", floor (y1) + .5,
		"x1", floor (x2) + .5,
		"y1", floor (y2) + .5,
270
		NULL);
271 272 273
	style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
	style->line.width = 1.;
	style->line.color = MARGIN_COLOR_DEFAULT;
274 275 276 277 278

	return item;
}

static void
279
draw_margin_top (UnitInfo *uinfo)
280
{
281
	double x1, x2, y1;
282 283

	x1 = uinfo->bound_x1;
284
	x2 = uinfo->bound_x2;
285
	y1 = uinfo->bound_y1;
286 287 288 289 290 291 292 293 294 295 296

	y1 += uinfo->pi->scale * uinfo->value;
	move_line (uinfo->line, x1, y1, x2, y1);
}

static void
draw_margin_bottom (UnitInfo *uinfo)
{
	double x1, x2, y2;

	x1 = uinfo->bound_x1;
297 298 299
	x2 = uinfo->bound_x2;
	y2 = uinfo->bound_y2;

300 301 302
	y2 -= uinfo->pi->scale * uinfo->value;
	move_line (uinfo->line, x1, y2, x2, y2);
}
303

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
static void
draw_margin_left (UnitInfo *uinfo)
{
	double x1, y1, y2;

	x1 = uinfo->bound_x1;
	y1 = uinfo->bound_y1;
	y2 = uinfo->bound_y2;

	x1 += uinfo->pi->scale * uinfo->value;
	move_line (uinfo->line, x1, y1, x1, y2);
}

static void
draw_margin_right (UnitInfo *uinfo)
{
	double y1, x2, y2;

	y1 = uinfo->bound_y1;
	x2 = uinfo->bound_x2;
	y2 = uinfo->bound_y2;

	x2 -= uinfo->pi->scale * uinfo->value;
	move_line (uinfo->line, x2, y1, x2, y2);
328 329 330
}

static void
331 332 333 334 335 336 337 338 339 340 341 342
draw_margin_header (UnitInfo *uinfo)
{
	double x1, y1, x2;
	double outside = uinfo->pi->scale *
		uinfo->state->margins.top.value;
	double inside = uinfo->pi->scale * uinfo->value;

	x1 = uinfo->bound_x1;
	y1 = uinfo->bound_y1;
	x2 = uinfo->bound_x2;

	if (inside < 1.0)
Morten Welinder's avatar
Morten Welinder committed
343
		inside = 1.0;
344
	y1 += outside + inside ;
Morten Welinder's avatar
Morten Welinder committed
345

346 347 348 349 350 351 352 353 354 355
	move_line (uinfo->line, x1, y1, x2, y1);
}

static void
draw_margin_footer (UnitInfo *uinfo)
{
	double x1, x2, y2;
	double outside = uinfo->pi->scale *
		uinfo->state->margins.bottom.value;
	double inside = uinfo->pi->scale * uinfo->value;
Morten Welinder's avatar
Morten Welinder committed
356

357 358 359 360 361
	x1 = uinfo->bound_x1;
	x2 = uinfo->bound_x2;
	y2 = uinfo->bound_y2;

	if (inside < 1.0)
Morten Welinder's avatar
Morten Welinder committed
362
		inside = 1.0;
363 364 365 366 367 368
	y2 -= outside + inside ;
	move_line (uinfo->line, x1, y2, x2, y2);
}

static void
create_margin (UnitInfo *uinfo,
369 370 371
	       double x1, double y1,
	       double x2, double y2)
{
372
	GocGroup *g = GOC_GROUP (uinfo->state->preview.group);
373 374 375 376 377 378

	uinfo->line = make_line (g, x1 + 8, y1, x1 + 8, y2);
	uinfo->bound_x1 = x1;
	uinfo->bound_y1 = y1;
	uinfo->bound_x2 = x2;
	uinfo->bound_y2 = y2;
379 380 381
}

static void
382
draw_margins (PrinterSetupState *state, double x1, double y1, double x2, double y2)
383 384
{
	/* Margins */
385 386 387 388 389 390 391 392 393 394 395 396 397 398
	create_margin (&state->margins.left, x1, y1, x2, y2);
	create_margin (&state->margins.right, x1, y1, x2, y2);
	create_margin (&state->margins.top, x1, y1, x2, y2);
	create_margin (&state->margins.bottom, x1, y1, x2, y2);

	/* Headers & footers */
	create_margin (&state->margins.header, x1, y1, x2, y2);
	create_margin (&state->margins.footer, x1, y1, x2, y2);

	/* Margins */
	draw_margin_left (&state->margins.left);
	draw_margin_right (&state->margins.right);
	draw_margin_top (&state->margins.top);
	draw_margin_bottom (&state->margins.bottom);
399 400

	/* Headers & footers */
401 402
	draw_margin_header (&state->margins.header);
	draw_margin_footer (&state->margins.footer);
403 404
}

405
static void
406 407
margin_preview_page_available_size (PrinterSetupState *state,
				    MarginPreviewPageAvailableSize *available_size)
408
{
Morten Welinder's avatar
Morten Welinder committed
409 410
	GList *children, *l;
	GtkWidget *grid;
411
	unsigned *widths, *heights;
412
	GtkRequisition requisition;
413 414
	unsigned top, left, width, height, i;
	unsigned nrows, ncols, first_col, first_row;
415 416 417 418 419

	/* Reset available size to zero*/
	available_size->width = 0;
	available_size->height = 0;

420 421 422 423 424 425 426 427 428 429
	grid = go_gtk_builder_get_widget (state->gui, "paper-selector-grid");
	gtk_container_child_get (GTK_CONTAINER (grid),
	                         go_gtk_builder_get_widget (state->gui, "container-paper-sample"),
				 "top-attach", &first_row,
				 "left-attach", &first_col,
				 "width", &ncols,
				 "height", &nrows,
				 NULL);
	widths = g_new0 (guint, ncols);
	heights = g_new0 (guint, nrows);
430

431
	/* Iterate through all child widgets in the grid */
Morten Welinder's avatar
Morten Welinder committed
432 433 434
	children = gtk_container_get_children (GTK_CONTAINER (grid));
	for (l = children; l; l = l->next) {
		GtkWidget *child_widget = l->data;
435 436

		/* Determine which cells the align widget spans across */
437 438 439 440 441 442
		gtk_container_child_get (GTK_CONTAINER (grid), GTK_WIDGET (child_widget),
					 "top-attach", &top,
					 "left-attach", &left,
					 "width", &width,
					 "height", &height,
					 NULL);
443 444

		/* Determine the requisition size for the widget */
445
		gtk_widget_get_preferred_size (GTK_WIDGET(child_widget), &requisition, NULL);
446 447

		/* Find largest widget in each table column */
448
		/* Exclude widgets that expand across more than one grid cells
449 450 451 452
		 * or are not in a relevant column */
		if (left >= first_col && width == 1 && left < first_col + ncols) {
			if ((guint) requisition.width > widths[left - first_col]) {
				widths[left - first_col] = (guint) requisition.width;
453 454 455 456
			}
		}

		/* Find largest widget in each table row */
457 458 459 460 461
		/* Exclude widgets that expand across more than one grid cells
		 * or are not in a relevant column */
		if (top >= first_row && height == 1 && top < first_row + nrows) {
			if ((guint) requisition.height > heights[top - first_row]) {
				heights[top - first_row] = (guint) requisition.height;
462 463 464
			}
		}
	}
Morten Welinder's avatar
Morten Welinder committed
465
	g_list_free (children);
466 467 468

	/* Calculate width of container widget using maximum */
	/* widget widths from above */
469
	for (i = 0; i <  ncols; i++){
470 471 472 473 474
		available_size->width = available_size->width + widths[i];
	}

	/* Calculate height of container widget using maximum */
	/* widget heights from above */
475
	for (i = 0; i < nrows; i++){
476 477 478 479 480 481 482 483
		available_size->height = available_size->height + heights[i];
	}

	g_free(widths);
	g_free(heights);

	/* Account for the spacing between table cells */
	available_size->width = available_size->width +
484
		gtk_grid_get_column_spacing (GTK_GRID (grid)) * (ncols - 1);
485
	available_size->height = available_size->height +
486
		gtk_grid_get_row_spacing (GTK_GRID (grid)) * (nrows - 1);
487
}
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
488

489
static void
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
490
margin_preview_page_create (PrinterSetupState *state)
491 492 493
{
	double x1, y1, x2, y2;
	double width, height;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
494
	MarginPreviewInfo *pi = &state->preview;
495
	GOStyle *style;
496 497
	MarginPreviewPageAvailableSize margin_available_size;

498
	margin_preview_page_available_size (state, &margin_available_size);
499
	gtk_widget_set_size_request (state->preview.canvas, margin_available_size.width, margin_available_size.height);
500

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
501 502
	width = state->width;
	height = state->height;
503 504 505
	x1 = (margin_available_size.width - PREVIEW_MARGIN_X) / width;
	x2 = (margin_available_size.height - PREVIEW_MARGIN_Y) / height;
	pi->scale = MIN (x1, x2);
506

507 508
	pi->offset_x = (margin_available_size.width - (width  * pi->scale)) / 2;
	pi->offset_y = (margin_available_size.height - (height * pi->scale)) / 2;
509 510
	x1 = pi->offset_x;
	y1 = pi->offset_y;
511 512 513
	x2 = pi->offset_x + width * pi->scale;
	y2 = pi->offset_y + height * pi->scale;

514 515 516
	pi->group = goc_item_new (
		goc_canvas_get_root (GOC_CANVAS (pi->canvas)),
		goc_group_get_type (),
517 518 519
		"x", 0.0,
		"y", 0.0,
		NULL);
520

521 522 523 524 525 526 527 528
	style = go_styled_object_get_style (
	        GO_STYLED_OBJECT (goc_item_new (GOC_GROUP (pi->group),
			GOC_TYPE_RECTANGLE,
			"x",		 (double) x1+2,
			"y",		 (double) y1+2,
			"width",	 (double) x2-x1,
			"height",	 (double) y2-y1,
			NULL)));
529 530
	style->fill.pattern.back = GO_COLOR_BLACK;
	style->line.color = GO_COLOR_BLACK;
531
	style->line.width = 1.;
532 533 534 535 536 537 538 539 540

	style = go_styled_object_get_style (
		GO_STYLED_OBJECT (goc_item_new (GOC_GROUP (pi->group),
			GOC_TYPE_RECTANGLE,
			"x",		 (double) x1,
			"y",		 (double) y1,
			"width",	 (double) x2-x1,
			"height",	 (double) y2-y1,
			NULL)));
541 542
	style->fill.pattern.back = GO_COLOR_WHITE;
	style->line.color = GO_COLOR_BLACK;
543
	style->line.width = 1.;
544

545 546
	goc_item_invalidate (pi->group);

547
	draw_margins (state, x1, y1, x2, y2);
548 549
}

550 551 552
static void
canvas_update (PrinterSetupState *state)
{
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
553 554
	margin_preview_page_destroy (state);
	margin_preview_page_create (state);
555 556
}

557

558
static gboolean
559
cb_spin_activated (UnitInfo *target)
560
{
561 562 563
	GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (target->line));
	style->fill.pattern.back = MARGIN_COLOR_ACTIVE,
	goc_item_invalidate (target->line);
564
	return FALSE;
565 566
}

567
static gboolean
568
cb_spin_deactivated (UnitInfo *target)
569
{
570 571 572 573
	GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (target->line));
	style->fill.pattern.back = MARGIN_COLOR_DEFAULT,
	goc_item_invalidate (target->line);
	return FALSE;
574
	return FALSE;
575 576
}

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
static void
configure_bounds_header (PrinterSetupState *state)
{
	double max = state->height - state->margins.top.value
		- state->margins.footer.value - state->margins.bottom.value;
	gtk_spin_button_set_range (state->margins.header.spin, 0., max);
}

static void
configure_bounds_footer (PrinterSetupState *state)
{
	double max = state->height - state->margins.header.value
		- state->margins.top.value - state->margins.bottom.value;
	gtk_spin_button_set_range (state->margins.footer.spin, 0., max);
}

static void
configure_bounds_bottom (PrinterSetupState *state)
{
	double max = state->height - state->margins.header.value
		- state->margins.footer.value - state->margins.top.value;
	gtk_spin_button_set_range (state->margins.bottom.spin, 0., max);
}

static void
configure_bounds_top (PrinterSetupState *state)
{
	double max = state->height - state->margins.header.value
		- state->margins.footer.value - state->margins.bottom.value;
	gtk_spin_button_set_range (state->margins.top.spin, 0., max);
}

static void
configure_bounds_left (PrinterSetupState *state)
{
	double max = state->width - state->margins.right.value;
	gtk_spin_button_set_range (state->margins.left.spin, 0., max);
}

static void
configure_bounds_right (PrinterSetupState *state)
{
	double max = state->width - state->margins.left.value;
	gtk_spin_button_set_range (state->margins.right.spin, 0., max);
}

static void
value_changed_header_cb (gpointer user_data)
{
	UnitInfo *target = user_data;

	target->value = gtk_spin_button_get_value (target->spin);

	configure_bounds_top (target->state);
	configure_bounds_bottom (target->state);
	configure_bounds_footer (target->state);
633 634

	draw_margin_header (target);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
635 636 637 638 639 640 641 642 643 644 645 646
}

static void
value_changed_footer_cb (gpointer user_data)
{
	UnitInfo *target = user_data;

	target->value = gtk_spin_button_get_value (target->spin);

	configure_bounds_top (target->state);
	configure_bounds_bottom (target->state);
	configure_bounds_header (target->state);
647 648

	draw_margin_footer (target);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
649 650 651 652 653 654 655 656 657 658 659 660
}

static void
value_changed_top_cb (gpointer user_data)
{
	UnitInfo *target = user_data;

	target->value = gtk_spin_button_get_value (target->spin);

	configure_bounds_header (target->state);
	configure_bounds_bottom (target->state);
	configure_bounds_footer (target->state);
661 662 663

	draw_margin_top (target);
	draw_margin_header (&target->state->margins.header);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
664 665 666 667 668 669 670 671 672 673 674 675 676
}


static void
value_changed_bottom_cb (gpointer user_data)
{
	UnitInfo *target = user_data;

	target->value = gtk_spin_button_get_value (target->spin);

	configure_bounds_header (target->state);
	configure_bounds_top (target->state);
	configure_bounds_footer (target->state);
677 678

	draw_margin_bottom (target);
679
	draw_margin_footer (&target->state->margins.footer);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
680 681 682 683 684 685 686 687 688 689
}

static void
value_changed_left_cb (gpointer user_data)
{
	UnitInfo *target = user_data;

	target->value = gtk_spin_button_get_value (target->spin);

	configure_bounds_right (target->state);
690 691

	draw_margin_left (target);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
692 693 694 695 696 697 698 699 700 701
}

static void
value_changed_right_cb (gpointer user_data)
{
	UnitInfo *target = user_data;

	target->value = gtk_spin_button_get_value (target->spin);

	configure_bounds_left (target->state);
702 703

	draw_margin_right (target);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
704 705 706 707
}

static void
margin_spin_configure (UnitInfo *target, PrinterSetupState *state,
708 709
		       const char *spin_name,
		       void (*value_changed_cb) (gpointer user_data))
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
710 711 712
{
	target->value = 0.;
	target->pi = &state->preview;
Morten Welinder's avatar
Morten Welinder committed
713
	target->spin = GTK_SPIN_BUTTON (go_gtk_builder_get_widget (state->gui, spin_name));
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
714 715 716 717 718
	target->state = state;
	gtk_spin_button_set_update_policy (target->spin, GTK_UPDATE_IF_VALID);
	g_signal_connect_swapped (G_OBJECT (target->spin),
		"value_changed",
		G_CALLBACK (value_changed_cb), target);
719 720 721 722 723 724
	g_signal_connect_swapped (G_OBJECT (target->spin),
                "focus_in_event",
                G_CALLBACK (cb_spin_activated), target);
	g_signal_connect_swapped (G_OBJECT (target->spin),
		"focus_out_event",
		G_CALLBACK (cb_spin_deactivated), target);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
725 726
}

727
static void
728
cb_unit_selector_changed (G_GNUC_UNUSED GtkComboBox *widget,
729
			  PrinterSetupState *state)
730
{
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
731 732
	GtkTreeIter iter;
	GtkUnit unit;
Morten Welinder's avatar
Morten Welinder committed
733

734 735
	g_return_if_fail (state != NULL);

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
736 737 738
	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (state->unit_selector), &iter)) {
		gtk_tree_model_get (state->unit_model, &iter, 1, &unit, -1);

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
739
		do_fetch_margins (state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
740 741
		state->display_unit = unit;
		do_update_page (state);
742
	}
743 744
}

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
745 746
static gint
unit_sort_func (GtkTreeModel *model,
747
		GtkTreeIter *a, GtkTreeIter *b,
748
		G_GNUC_UNUSED gpointer user_data)
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
749 750 751 752 753 754 755
{
	char *str_a;
	char *str_b;
	gint result;

	gtk_tree_model_get (model, a, 0, &str_a, -1);
	gtk_tree_model_get (model, b, 0, &str_b, -1);
Morten Welinder's avatar
Morten Welinder committed
756

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
757 758 759 760 761 762 763
	result = g_utf8_collate (str_a, str_b);

	g_free (str_a);
	g_free (str_b);
	return result;
}

764

765
/*
766 767 768 769
 * Header and footer are stored with Excel semantics, but displayed with
 * more natural semantics. In Excel, both top margin and header are measured
 * from top of sheet. The Gnumeric user interface presents header as the
 * band between top margin and the print area. Bottom margin and footer are
770
 * handled likewise. See illustration at top of src/print.c
771
 */
772
static void
773
do_setup_margin (PrinterSetupState *state)
774
{
775
	GtkWidget *grid, *container;
776 777
	MarginPreviewPageAvailableSize margin_available_size;

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
778 779 780 781 782
	{
		GtkListStore *list_store;
		GtkTreeIter iter;
		GtkTreeIter current;
		GtkCellRenderer *text_renderer;
Morten Welinder's avatar
Morten Welinder committed
783

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
784
		list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
785

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
		gtk_list_store_append (list_store, &iter);
		gtk_list_store_set (list_store, &iter, 0, (_("points")), 1, GTK_UNIT_POINTS, -1);
		if (GTK_UNIT_POINTS == state->display_unit)
			current = iter;
		gtk_list_store_append (list_store, &iter);
		gtk_list_store_set (list_store, &iter, 0, (_("inches")), 1, GTK_UNIT_INCH, -1);
		if (GTK_UNIT_INCH == state->display_unit)
			current = iter;
		gtk_list_store_append (list_store, &iter);
		gtk_list_store_set (list_store, &iter, 0, (_("mm")), 1, GTK_UNIT_MM, -1);
		if (GTK_UNIT_MM == state->display_unit)
			current = iter;

		gtk_tree_sortable_set_default_sort_func
			(GTK_TREE_SORTABLE (list_store),
			 unit_sort_func, NULL, NULL);
		gtk_tree_sortable_set_sort_column_id
			(GTK_TREE_SORTABLE (list_store),
			 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
			 GTK_SORT_ASCENDING);

		state->unit_selector = gtk_combo_box_new_with_model (GTK_TREE_MODEL (list_store));
		state->unit_model    = GTK_TREE_MODEL (list_store);
		text_renderer = gtk_cell_renderer_text_new ();
Morten Welinder's avatar
Morten Welinder committed
810
		gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(state->unit_selector),
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
811 812
					    text_renderer, TRUE);
		gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(state->unit_selector),
Morten Welinder's avatar
Morten Welinder committed
813 814
					       text_renderer, "text", 0);

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
815 816
		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (state->unit_selector), &current);
	}
817 818 819
	grid = go_gtk_builder_get_widget (state->gui, "paper-selector-grid");
	gtk_widget_set_hexpand (state->unit_selector, TRUE);
	gtk_grid_attach (GTK_GRID (grid), state->unit_selector, 3, 8, 1, 1);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
820

Morten Welinder's avatar
Morten Welinder committed
821 822
	g_signal_connect (G_OBJECT (state->unit_selector), "changed",
			  G_CALLBACK (cb_unit_selector_changed), state);
823
	gtk_widget_show (state->unit_selector);
824

825 826 827 828 829 830 831 832
	margin_preview_page_available_size (state, &margin_available_size);

	g_return_if_fail (state && state->pi);

	state->preview.canvas = GTK_WIDGET (g_object_new (GOC_TYPE_CANVAS, NULL));
	gtk_widget_set_size_request (state->preview.canvas, margin_available_size.width, margin_available_size.height);
	gtk_widget_show (state->preview.canvas);

833 834 835 836 837 838 839 840 841 842 843 844
	margin_spin_configure  (&state->margins.header, state, "spin-header",
				value_changed_header_cb);
	margin_spin_configure  (&state->margins.footer, state, "spin-footer",
				value_changed_footer_cb);
	margin_spin_configure  (&state->margins.top, state, "spin-top",
				value_changed_top_cb);
	margin_spin_configure  (&state->margins.bottom, state, "spin-bottom",
				value_changed_bottom_cb);
	margin_spin_configure  (&state->margins.left, state, "spin-left",
				value_changed_left_cb);
	margin_spin_configure  (&state->margins.right, state, "spin-right",
				value_changed_right_cb);
845

Morten Welinder's avatar
Morten Welinder committed
846
	state->check_center_h = go_gtk_builder_get_widget (state->gui,
847
						      "check_center_h");
Morten Welinder's avatar
Morten Welinder committed
848
	state->check_center_v = go_gtk_builder_get_widget (state->gui,
849 850 851 852 853 854 855 856
						      "check_center_v");
	gtk_toggle_button_set_active (
				      GTK_TOGGLE_BUTTON (state->check_center_v),
				      state->pi->center_vertically == 1);
	gtk_toggle_button_set_active (
				      GTK_TOGGLE_BUTTON (state->check_center_h),
				      state->pi->center_horizontally == 1);

857 858 859
	container = go_gtk_builder_get_widget (state->gui,
					       "container-paper-sample");
	gtk_container_add (GTK_CONTAINER (container), state->preview.canvas);
860

861 862
}

863 864
/* Display the header or footer preview in the print setup dialog.
 * Use the canvas widget in the HFPreviewInfo struct.
865
 *
866 867
 */
static void
868
display_hf_preview (PrinterSetupState *state, gboolean header)
869
{
870
	gchar *text = NULL;
Morten Welinder's avatar
Morten Welinder committed
871 872
	GnmPrintHF *sample = NULL;
	GnmPrintHFRenderInfo *hfi;
873
	HFPreviewInfo *pi;
874

Morten Welinder's avatar
Morten Welinder committed
875
	g_return_if_fail (state != NULL);
876

Morten Welinder's avatar
Morten Welinder committed
877
	hfi = gnm_print_hf_render_info_new ();
878 879

	hfi->page = 1;
880 881
	hfi->pages = 99;
	hfi->sheet = state->sheet;
882 883

	if (header) {
884
		pi = state->pi_header;
885 886
		sample = state->header;
	} else {
887
		pi = state->pi_footer;
888 889 890
		sample = state->footer;
	}

Morten Welinder's avatar
Morten Welinder committed
891
	text = gnm_print_hf_format_render (sample->left_format, hfi, HF_RENDER_PRINT);
892
	goc_item_set (pi->left, "text", text ? text : "", NULL);
Morten Welinder's avatar
Morten Welinder committed
893
	g_free (text);
894

Morten Welinder's avatar
Morten Welinder committed
895
	text = gnm_print_hf_format_render (sample->middle_format, hfi, HF_RENDER_PRINT);
896
	goc_item_set (pi->middle, "text", text ? text : "", NULL);
Morten Welinder's avatar
Morten Welinder committed
897
	g_free (text);
898

Morten Welinder's avatar
Morten Welinder committed
899
	text  = gnm_print_hf_format_render (sample->right_format, hfi, HF_RENDER_PRINT);
900
	goc_item_set (pi->right, "text", text ? text : "", NULL);
Morten Welinder's avatar
Morten Welinder committed
901
	g_free (text);
902

Morten Welinder's avatar
Morten Welinder committed
903
	gnm_print_hf_render_info_destroy (hfi);
904 905
}

906
static void
907
do_header_customize (PrinterSetupState *state)
908
{
909
	do_hf_customize (TRUE, state);
910 911 912
}

static void
913
do_footer_customize (PrinterSetupState *state)
914
{
915
	do_hf_customize (FALSE, state);
916 917
}

918
static void
919
header_changed (GtkComboBox *menu, PrinterSetupState *state)
920
{
Morten Welinder's avatar
Morten Welinder committed
921
	GList *selection = g_list_nth (gnm_print_hf_formats,
922
		gtk_combo_box_get_active (menu));
Morten Welinder's avatar
Morten Welinder committed
923
	GnmPrintHF *format = (selection)? selection->data: NULL;
924 925

	if (format == NULL) {
926
		do_header_customize (state);
927
	} else {
Morten Welinder's avatar
Morten Welinder committed
928 929
		gnm_print_hf_free (state->header);
		state->header = gnm_print_hf_copy (format);
930
	}
Morten Welinder's avatar
Morten Welinder committed
931

932
		display_hf_preview (state, TRUE);
933 934 935
}

static void
936
footer_changed (GtkComboBox *menu, PrinterSetupState *state)
937
{
Morten Welinder's avatar
Morten Welinder committed
938
	GList *selection = g_list_nth (gnm_print_hf_formats,
939
		gtk_combo_box_get_active (menu));
Morten Welinder's avatar
Morten Welinder committed
940
	GnmPrintHF *format = (selection)? selection->data: NULL;
941 942

	if (format == NULL) {
943
		do_footer_customize (state);
944
	} else {
Morten Welinder's avatar
Morten Welinder committed
945 946
		gnm_print_hf_free (state->footer);
		state->footer = gnm_print_hf_copy (format);
947 948
	}

949
	display_hf_preview (state, FALSE);
950 951
}

952 953 954 955 956 957 958
static char *
create_hf_name (char const *left, char const *middle, char const *right)
{
		char *this, *res;

		res = g_strdup_printf ("%s%s%s%s%s",
				       left," \xe2\x90\xa3 ", middle, " \xe2\x90\xa3 ", right);
Morten Welinder's avatar
Morten Welinder committed
959

960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
		this = res;
		while (*this) {
			if (*this == '\n') {
				char *newstring;
				*this = 0;
				newstring =  g_strconcat (res, "\xe2\x90\xa4", this + 1, NULL);
				this = newstring + (this - res);
				g_free (res);
				res = newstring;
			} else
				this = g_utf8_find_next_char (this, NULL);
		}

		return res;
}

static void
Morten Welinder's avatar
Morten Welinder committed
977
append_hf_item (GtkListStore *store, GnmPrintHF *format, GnmPrintHFRenderInfo *hfi)
978 979 980 981 982
{
	GtkTreeIter iter;
	char *left, *middle, *right;
	char *res;

Morten Welinder's avatar
Morten Welinder committed
983 984 985
	left   = gnm_print_hf_format_render (format->left_format, hfi, HF_RENDER_PRINT);
	middle = gnm_print_hf_format_render (format->middle_format, hfi, HF_RENDER_PRINT);
	right  = gnm_print_hf_format_render (format->right_format, hfi, HF_RENDER_PRINT);
986 987 988 989 990 991 992 993 994 995 996 997 998 999

	res = create_hf_name (left, middle, right);

	gtk_list_store_append (store, &iter);
	gtk_list_store_set (store, &iter,
			    0, res,
			    -1);

	g_free (res);
	g_free (left);
	g_free (middle);
	g_free (right);

}
1000

1001
/*
1002 1003 1004 1005
 * Fills one of the GtkCombos for headers or footers with the list
 * of existing header/footer formats
 */
static void
1006
fill_hf (PrinterSetupState *state, GtkComboBox *om, GCallback callback, gboolean header)
1007 1008
{
	GList *l;
Morten Welinder's avatar
Morten Welinder committed
1009
	GnmPrintHFRenderInfo *hfi;
1010
	GtkListStore *store;
Morten Welinder's avatar
Morten Welinder committed
1011
	GnmPrintHF *select = header ? state->header : state->footer;
1012
	int i, idx = -1;
1013

Morten Welinder's avatar
Morten Welinder committed
1014
	hfi = gnm_print_hf_render_info_new ();
1015
	hfi->page = 1;
1016
	hfi->pages = 99;
1017

1018 1019
	store = gtk_list_store_new (1, G_TYPE_STRING);
	gtk_combo_box_set_model (om, GTK_TREE_MODEL (store));
1020
	g_object_unref (store);
1021

Morten Welinder's avatar
Morten Welinder committed
1022 1023
	for (i = 0, l = gnm_print_hf_formats; l; l = l->next, i++) {
		GnmPrintHF *format = l->data;
1024

Morten Welinder's avatar
Morten Welinder committed
1025
		if (gnm_print_hf_same (format, select))
1026
			idx = i;
1027

1028
		append_hf_item (store, format, hfi);
1029
	}
1030

1031 1032
	if (idx < 0)
		g_critical ("Current format is not registered!");
Morten Welinder's avatar
Morten Welinder committed
1033

1034 1035
	gtk_combo_box_set_active (om, idx);
	g_signal_connect (G_OBJECT (om), "changed", callback, state);
Morten Welinder's avatar
Morten Welinder committed
1036

Morten Welinder's avatar
Morten Welinder committed
1037
	gnm_print_hf_render_info_destroy (hfi);
1038 1039
}

1040 1041 1042
static void
do_setup_hf_menus (PrinterSetupState *state)
{
1043 1044
	GtkComboBox *header;
	GtkComboBox *footer;
1045

Morten Welinder's avatar
Morten Welinder committed
1046
	g_return_if_fail (state != NULL);
1047

Morten Welinder's avatar
Morten Welinder committed
1048 1049
	header = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "option-menu-header"));
	footer = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "option-menu-footer"));
1050

1051
	if (state->header)
Morten Welinder's avatar
Morten Welinder committed
1052
		gnm_print_hf_register (state->header);
1053
	if (state->footer)
Morten Welinder's avatar
Morten Welinder committed
1054
		gnm_print_hf_register (state->footer);
1055

1056
	if (state->header)
1057
		fill_hf (state, header, G_CALLBACK (header_changed), TRUE);
1058
	if (state->footer)
1059
		fill_hf (state, footer, G_CALLBACK (footer_changed), FALSE);
1060 1061
}

1062 1063
/*************  Header Footer Customization *********** Start *************/

1064
static void
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
hf_delete_tag_cb (HFCustomizeState *hf_state)
{
	GtkWidget* focus;

	focus = gtk_window_get_focus (GTK_WINDOW (hf_state->dialog));

	if (GTK_IS_TEXT_VIEW (focus)) {
		GtkTextBuffer *textbuffer;
		GtkTextTag    *tag;
		GtkTextIter   start;
		GtkTextIter   end;

		textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focus));
		tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (textbuffer),
						 HF_TAG_NAME);
		gtk_text_buffer_get_selection_bounds (textbuffer, &start, &end);
Morten Welinder's avatar
Morten Welinder committed
1081

1082 1083 1084 1085
		if (gtk_text_iter_has_tag (&start, tag) && !gtk_text_iter_begins_tag (&start, tag))
			gtk_text_iter_backward_to_tag_toggle (&start, tag);
		if (gtk_text_iter_has_tag (&end, tag) && !gtk_text_iter_toggles_tag (&end, tag))
			gtk_text_iter_forward_to_tag_toggle (&end, tag);
Morten Welinder's avatar
Morten Welinder committed
1086 1087


1088 1089 1090 1091
		gtk_text_buffer_delete (textbuffer, &start, &end);
	}
}

1092

1093
static void
Morten Welinder's avatar
Morten Welinder committed
1094 1095
hf_insert_hf_stock_tag (HFCustomizeState *hf_state, GtkTextBuffer *buffer,
			HFFieldType type, const char *options)
1096
{
1097
	GtkTextIter iter;
1098
	gchar const *icon_name;
1099 1100 1101
	GdkPixbuf* pix;
	GtkTextMark *new_mark;
	HFMarkInfo *mark_info;
Morten Welinder's avatar
Morten Welinder committed
1102

1103 1104
	switch (type) {
	case HF_FIELD_FILE:
1105
		icon_name = GTK_STOCK_FILE;
1106 1107
		break;
	case HF_FIELD_PATH:
1108
		icon_name = "folder";
1109
		break;
1110
	case HF_FIELD_PAGE:
1111
		icon_name = "gnumeric-pagesetup-hf-page";
1112 1113
		break;
	case HF_FIELD_PAGES:
1114
		icon_name = "gnumeric-pagesetup-hf-pages";
1115 1116
		break;
	case HF_FIELD_DATE:
1117
		icon_name = "gnumeric-pagesetup-hf-date";
1118 1119
		break;
	case HF_FIELD_TIME:
1120
		icon_name = "gnumeric-pagesetup-hf-time";
1121 1122
		break;
	case HF_FIELD_SHEET:
1123
		icon_name = "gnumeric-pagesetup-hf-sheet";
1124
		break;
1125
	case HF_FIELD_CELL:
1126
		icon_name = "gnumeric-pagesetup-hf-cell";
1127
		break;
1128 1129 1130
	default:
		return;
	}
Morten Welinder's avatar
Morten Welinder committed
1131

1132 1133
	hf_delete_tag_cb (hf_state);

Morten Welinder's avatar
Morten Welinder committed
1134
	if (gtk_text_buffer_insert_interactive_at_cursor
1135
	    (buffer, "", -1, TRUE)) {
1136
		GtkWidget *w = GTK_WIDGET (wbcg_toplevel (hf_state->printer_setup_state->wbcg));
1137

Morten Welinder's avatar
Morten Welinder committed
1138
		gtk_text_buffer_get_iter_at_mark
1139
			(buffer, &iter, gtk_text_buffer_get_insert (buffer));
Morten Welinder's avatar
Morten Welinder committed
1140

1141
		pix = go_gtk_widget_render_icon_pixbuf (w, icon_name, GTK_ICON_SIZE_BUTTON);
1142
		gtk_text_buffer_insert_pixbuf (buffer, &iter, pix);
Morten Welinder's avatar
Morten Welinder committed
1143
		g_object_unref (pix);
1144 1145 1146 1147 1148 1149 1150 1151
		gtk_text_iter_backward_char (&iter);
		new_mark = gtk_text_buffer_create_mark (buffer, NULL,
							&iter, FALSE);
		g_object_ref (new_mark);

		mark_info = g_new0 (HFMarkInfo, 1);
		mark_info->mark = new_mark;
		mark_info->type = type;
1152
		mark_info->options = g_strdup (options);
1153 1154 1155 1156 1157
		hf_state->marks = g_list_append (hf_state->marks, mark_info);
	}
}

static void
Morten Welinder's avatar
Morten Welinder committed
1158 1159
hf_insert_hf_tag (HFCustomizeState *hf_state, HFFieldType type,
		  const char *options)
1160 1161
{
	GtkWidget* focus;
1162 1163 1164 1165

	focus = gtk_window_get_focus (GTK_WINDOW (hf_state->dialog));

	if (GTK_IS_TEXT_VIEW (focus)) {
Morten Welinder's avatar
Morten Welinder committed
1166
		GtkTextBuffer *buffer =
1167
			gtk_text_view_get_buffer (GTK_TEXT_VIEW (focus));
1168
		hf_insert_hf_stock_tag (hf_state, buffer, type, options);
1169 1170 1171 1172
	}
}


1173

1174
static void
1175
hf_insert_date_cb (GtkWidget *widget, HFCustomizeState *hf_state)
1176
{
Morten Welinder's avatar
Morten Welinder committed
1177

1178
	hf_insert_hf_tag (hf_state, HF_FIELD_DATE,
1179
			  g_object_get_data (G_OBJECT (widget), "options"));
1180 1181
}

1182
static void
1183
hf_insert_custom_date_cb (G_GNUC_UNUSED GtkWidget *widget,
1184
			  HFCustomizeState *hf_state)
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
{
	char *format;

	format = do_hf_dt_format_customize (TRUE, hf_state);
	if (format != NULL) {
		hf_insert_hf_tag (hf_state, HF_FIELD_DATE, format);
		g_free (format);
	}
}

1195
static void
1196
hf_insert_time_cb (GtkWidget *widget, HFCustomizeState *hf_state)
1197
{
1198
	hf_insert_hf_tag (hf_state, HF_FIELD_TIME,
1199
			  g_object_get_data (G_OBJECT (widget), "options"));
1200 1201
}

1202
static void
1203
hf_insert_custom_time_cb (G_GNUC_UNUSED GtkWidget *widget,
1204
			  HFCustomizeState *hf_state)
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214
{
	char *format;

	format = do_hf_dt_format_customize (FALSE, hf_state);
	if (format != NULL) {
		hf_insert_hf_tag (hf_state, HF_FIELD_TIME, format);
		g_free (format);
	}
}

1215 1216 1217
static void
hf_insert_cell_cb (GtkWidget *widget, HFCustomizeState *hf_state)
{
Morten Welinder's avatar
Morten Welinder committed
1218
	const char *options;
1219 1220
	options = g_object_get_data (G_OBJECT (widget), "options");
	if (options == NULL)
Morten Welinder's avatar
Morten Welinder committed
1221
		options = "A1";
1222 1223 1224
	hf_insert_hf_tag (hf_state, HF_FIELD_CELL, options);
}

1225 1226 1227
static void
hf_insert_page_cb (HFCustomizeState *hf_state)
{
1228
	hf_insert_hf_tag (hf_state, HF_FIELD_PAGE, NULL);
1229 1230 1231 1232 1233
}

static void
hf_insert_pages_cb (HFCustomizeState *hf_state)
{
1234
	hf_insert_hf_tag (hf_state, HF_FIELD_PAGES, NULL);
1235 1236 1237 1238 1239
}

static void
hf_insert_sheet_cb (HFCustomizeState *hf_state)
{
1240
	hf_insert_