Introspection fixes.
[gnumeric.git] / src / print-info.c
blob511a04947345566a1d6804e09aa5fb36afda6b15
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /*
4 * print-info.c: Print information management. This keeps
5 * track of what the print parameters for a sheet are.
7 * Authors:
8 * Andreas J. Guelzow (aguelzow@taliesin.ca)
9 * Jody Goldberg (jody@gnome.org)
10 * Miguel de Icaza (miguel@gnu.org)
11 * Copyright (C) 2007-2009 Morten Welinder (terra@gnome.org)
13 #include <gnumeric-config.h>
14 #include "gnumeric.h"
15 #include "print-info.h"
17 #include "print.h"
18 #include "gutils.h"
19 #include "ranges.h"
20 #include "gnm-format.h"
21 #include "func.h"
22 #include "sheet.h"
23 #include "value.h"
24 #include "workbook.h"
25 #include "workbook-view.h"
26 #include "gnumeric-conf.h"
27 #include "parse-util.h"
28 #include "sheet-object.h"
29 #include "sheet-object-graph.h"
31 #include <goffice/goffice.h>
32 #include <gsf/gsf-doc-meta-data.h>
33 #include <gsf/gsf-meta-names.h>
35 #include <glib/gi18n-lib.h>
36 #include <string.h>
37 #include <locale.h>
38 #include <time.h>
40 #define PDF_SAVER_ID "Gnumeric_pdf:pdf_assistant"
42 #define MAX_SAVED_CUSTOM_HF_FORMATS 9
44 GList *gnm_print_hf_formats = NULL;
45 static gint hf_formats_base_num = 0;
47 GType
48 gnm_print_comment_placement_get_type (void)
50 static GType etype = 0;
51 if (etype == 0) {
52 static GEnumValue const values[] = {
53 { GNM_PRINT_COMMENTS_NONE, "GNM_PRINT_COMMENTS_NONE", "none"},
54 { GNM_PRINT_COMMENTS_IN_PLACE, "GNM_PRINT_COMMENTS_IN_PLACE",
55 "in-place"},
56 { GNM_PRINT_COMMENTS_AT_END, "GNM_PRINT_COMMENTS_AT_END",
57 "at-end"},
58 { 0, NULL, NULL }
60 etype = g_enum_register_static ("GnmPrintCommentPlacementType",
61 values);
63 return etype;
66 GType
67 gnm_print_errors_get_type (void)
69 static GType etype = 0;
70 if (etype == 0) {
71 static GEnumValue const values[] = {
72 { GNM_PRINT_ERRORS_AS_DISPLAYED,
73 "GNM_PRINT_ERRORS_AS_DISPLAYED", "as-displayed"},
74 { GNM_PRINT_ERRORS_AS_BLANK,
75 "GNM_PRINT_ERRORS_AS_BLANK", "as-blank"},
76 { GNM_PRINT_ERRORS_AS_DASHES,
77 "GNM_PRINT_ERRORS_AS_DASHES", "as-dashes"},
78 { GNM_PRINT_ERRORS_AS_NA,
79 "GNM_PRINT_ERRORS_AS_NA", "as-na"},
80 { 0, NULL, NULL }
82 etype = g_enum_register_static ("GnmPrintErrorsType",
83 values);
85 return etype;
89 GnmPrintHF *
90 gnm_print_hf_new (char const *left_side_format,
91 char const *middle_format,
92 char const *right_side_format)
94 GnmPrintHF *hf = g_new0 (GnmPrintHF, 1);
95 hf->left_format = g_strdup (left_side_format ?
96 left_side_format : "");
97 hf->middle_format = g_strdup (middle_format ?
98 middle_format : "");
99 hf->right_format = g_strdup (right_side_format ?
100 right_side_format : "");
101 return hf;
104 gboolean
105 gnm_print_hf_same (GnmPrintHF const *a, GnmPrintHF const *b)
107 if (a->left_format != b->left_format) {
108 if (a->left_format == NULL ||
109 b->left_format == NULL ||
110 strcmp (b->left_format, a->left_format))
111 return FALSE;
113 if (a->middle_format != b->middle_format) {
114 if (a->middle_format == NULL ||
115 b->middle_format == NULL ||
116 strcmp (b->middle_format, a->middle_format))
117 return FALSE;
119 if (a->right_format != b->right_format) {
120 if (a->right_format == NULL ||
121 b->right_format == NULL ||
122 strcmp (b->right_format, a->right_format))
123 return FALSE;
126 return TRUE;
129 GnmPrintHF *
130 gnm_print_hf_register (GnmPrintHF *hf)
132 GList *l;
133 GnmPrintHF *newi;
135 g_return_val_if_fail (hf != NULL, NULL);
137 for (l = gnm_print_hf_formats; l; l = l->next)
138 if (gnm_print_hf_same (hf, l->data))
139 return l->data;
141 newi = gnm_print_hf_copy (hf);
142 gnm_print_hf_formats = g_list_append (gnm_print_hf_formats, newi);
144 return newi;
148 GnmPrintHF *
149 gnm_print_hf_copy (GnmPrintHF const *source)
151 GnmPrintHF *res;
153 res = g_new0 (GnmPrintHF, 1);
154 res->left_format = g_strdup (source->left_format);
155 res->middle_format = g_strdup (source->middle_format);
156 res->right_format = g_strdup (source->right_format);
158 return res;
161 void
162 gnm_print_hf_free (GnmPrintHF *print_hf)
164 if (print_hf == NULL)
165 return;
167 g_free (print_hf->left_format);
168 g_free (print_hf->middle_format);
169 g_free (print_hf->right_format);
170 g_free (print_hf);
173 GType
174 gnm_print_hf_get_type (void)
176 static GType t = 0;
178 if (t == 0) {
179 t = g_boxed_type_register_static ("GnmPrintHF",
180 (GBoxedCopyFunc)gnm_print_hf_copy,
181 (GBoxedFreeFunc)gnm_print_hf_free);
183 return t;
186 void
187 gnm_print_info_free (GnmPrintInformation *pi)
189 g_return_if_fail (pi != NULL);
191 if (NULL != pi->page_breaks.v)
192 gnm_page_breaks_free (pi->page_breaks.v);
193 if (NULL != pi->page_breaks.h)
194 gnm_page_breaks_free (pi->page_breaks.h);
196 g_free (pi->repeat_top);
197 g_free (pi->repeat_left);
198 gnm_print_hf_free (pi->header);
199 gnm_print_hf_free (pi->footer);
201 g_free (pi->printtofile_uri);
202 if (pi->page_setup)
203 g_object_unref (pi->page_setup);
205 g_free (pi);
208 GType
209 gnm_print_information_get_type (void)
211 static GType t = 0;
213 if (t == 0) {
214 t = g_boxed_type_register_static ("GnmPrintInformation",
215 (GBoxedCopyFunc)gnm_print_info_dup,
216 (GBoxedFreeFunc)gnm_print_info_free);
218 return t;
221 static void
222 load_formats (void)
224 static struct {
225 char const *left_format;
226 char const *middle_format;
227 char const *right_format;
228 } const predefined_formats [] = {
229 { "", "", "" },
230 { "", N_("Page &[PAGE]"), "" },
231 { "", N_("Page &[PAGE] of &[PAGES]"), "" },
232 { "", N_("&[TAB]"), "" },
233 { N_("Page &[PAGE]"), N_("&[TAB]"), "" },
234 { N_("Page &[PAGE]"), N_("&[TAB]"), N_("&[DATE]") },
235 { "", N_("&[DATE]"), "" },
236 { N_("&[TAB]"), N_("Page &[PAGE] of &[PAGES]"), N_("&[DATE]") },
237 { NULL, NULL, NULL }
240 /* Fetch header/footer formats */
242 int i;
244 for (i = 0; predefined_formats [i].left_format; i++) {
245 GnmPrintHF *format;
247 format = gnm_print_hf_new (
248 predefined_formats [i].left_format[0]?
249 _(predefined_formats [i].left_format):"",
250 predefined_formats [i].middle_format[0]?
251 _(predefined_formats [i].middle_format):"",
252 predefined_formats [i].right_format[0]?
253 _(predefined_formats [i].right_format):"");
255 gnm_print_hf_formats = g_list_prepend (gnm_print_hf_formats, format);
256 hf_formats_base_num++;
260 /* Now append the custom formats */
262 GSList const *left;
263 GSList const *middle;
264 GSList const *right;
266 left = gnm_conf_get_printsetup_hf_left ();
267 middle = gnm_conf_get_printsetup_hf_middle ();
268 right = gnm_conf_get_printsetup_hf_right ();
270 while (left != NULL && middle != NULL && right != NULL)
272 GnmPrintHF *format;
274 format = gnm_print_hf_new
275 (left->data ? left->data : "",
276 middle->data ? middle->data : "",
277 right->data ? right->data : "");
279 gnm_print_hf_formats = g_list_prepend (gnm_print_hf_formats, format);
281 left = left->next;
282 middle = middle->next;
283 right = right->next;
287 gnm_print_hf_formats = g_list_reverse (gnm_print_hf_formats);
291 * gnm_print_info_load_defaults:
294 * NOTE: This reads from a globally stored configuration. If a
295 * configuration is stored along with a sheet then that will
296 * override these global defaults.
299 GnmPrintInformation *
300 gnm_print_info_load_defaults (GnmPrintInformation *res)
302 GSList *list;
303 GtkPrintSettings *settings;
305 if (res->page_setup != NULL)
306 return res;
308 res->page_setup = gnm_conf_get_page_setup ();
310 res->scaling.type = gnm_conf_get_printsetup_scale_percentage ()
311 ? PRINT_SCALE_PERCENTAGE
312 : PRINT_SCALE_FIT_PAGES;
313 res->scaling.percentage.x = res->scaling.percentage.y
314 = gnm_conf_get_printsetup_scale_percentage_value ();
315 res->scaling.dim.cols = gnm_conf_get_printsetup_scale_width ();
316 res->scaling.dim.rows = gnm_conf_get_printsetup_scale_height ();
317 res->edge_to_below_header = gnm_conf_get_printsetup_margin_top ();
318 res->edge_to_above_footer = gnm_conf_get_printsetup_margin_bottom ();
319 res->desired_display.top = gnm_conf_get_printsetup_preferred_unit ();
320 res->desired_display.bottom = gnm_conf_get_printsetup_preferred_unit ();
321 res->desired_display.left = gnm_conf_get_printsetup_preferred_unit ();
322 res->desired_display.right = gnm_conf_get_printsetup_preferred_unit ();
323 res->desired_display.footer = gnm_conf_get_printsetup_preferred_unit ();
324 res->desired_display.header = gnm_conf_get_printsetup_preferred_unit ();
325 res->repeat_top = g_strdup (gnm_conf_get_printsetup_repeat_top ());
326 res->repeat_left = g_strdup (gnm_conf_get_printsetup_repeat_left ());
327 res->center_vertically = gnm_conf_get_printsetup_center_vertically ();
328 res->center_horizontally = gnm_conf_get_printsetup_center_horizontally ();
329 res->print_grid_lines = gnm_conf_get_printsetup_print_grid_lines ();
330 res->print_titles = gnm_conf_get_printsetup_print_titles ();
331 res->print_black_and_white = gnm_conf_get_printsetup_print_black_n_white ();
332 res->print_even_if_only_styles = gnm_conf_get_printsetup_print_even_if_only_styles ();
333 res->print_across_then_down = gnm_conf_get_printsetup_across_then_down ();
335 list = gnm_conf_get_printsetup_header ();
336 res->header = list ?
337 gnm_print_hf_new (g_slist_nth_data (list, 0),
338 g_slist_nth_data (list, 1),
339 g_slist_nth_data (list, 2)) :
340 gnm_print_hf_new ("", _("&[TAB]"), "");
342 list = gnm_conf_get_printsetup_footer ();
343 res->footer = list ?
344 gnm_print_hf_new (g_slist_nth_data (list, 0),
345 g_slist_nth_data (list, 1),
346 g_slist_nth_data (list, 2)) :
347 gnm_print_hf_new ("", _("Page &[PAGE]"), "");
349 settings = gnm_conf_get_print_settings ();
350 print_info_set_from_settings (res, settings);
351 g_object_unref (settings);
353 return res;
357 * gnm_print_information_new:
359 * Returns a newly allocated GnmPrintInformation buffer
362 GnmPrintInformation *
363 gnm_print_information_new (gboolean load_defaults)
365 GnmPrintInformation *res = g_new0 (GnmPrintInformation, 1);
367 res->print_as_draft = FALSE;
368 res->comment_placement = GNM_PRINT_COMMENTS_IN_PLACE;
369 res->error_display = GNM_PRINT_ERRORS_AS_DISPLAYED;
371 res->start_page = -1;
372 res->n_copies = 0;
373 res->do_not_print = FALSE;
375 res->page_setup = NULL;
376 res->page_breaks.v = NULL;
377 res->page_breaks.h = NULL;
379 res->printtofile_uri = NULL;
380 res->print_range = GNM_PRINT_ACTIVE_SHEET;
382 if (load_defaults)
383 return gnm_print_info_load_defaults (res);
384 else
385 return res;
389 * This can get out of hand, we should limit the number of stored
390 * formats.
392 static void
393 save_formats (void)
395 int base = hf_formats_base_num;
396 GList *l;
397 GSList *left = NULL;
398 GSList *middle = NULL;
399 GSList *right = NULL;
400 int start;
402 start = g_list_length (gnm_print_hf_formats) - MAX_SAVED_CUSTOM_HF_FORMATS;
403 if (start > base)
404 base = start;
406 for (l = gnm_print_hf_formats; l; l = l->next) {
407 GnmPrintHF *hf = l->data;
409 if (base-- > 0)
410 continue;
412 GO_SLIST_PREPEND (left, g_strdup(hf->left_format));
413 GO_SLIST_PREPEND (middle, g_strdup(hf->middle_format));
414 GO_SLIST_PREPEND (right, g_strdup(hf->right_format));
416 GO_SLIST_REVERSE(left);
417 gnm_conf_set_printsetup_hf_left (left);
418 g_slist_free_full (left, g_free);
420 GO_SLIST_REVERSE(middle);
421 gnm_conf_set_printsetup_hf_middle (middle);
422 g_slist_free_full (middle, g_free);
424 GO_SLIST_REVERSE(right);
425 gnm_conf_set_printsetup_hf_right (right);
426 g_slist_free_full (right, g_free);
429 static void
430 destroy_formats (void)
432 g_list_free_full (gnm_print_hf_formats, (GDestroyNotify)gnm_print_hf_free);
433 gnm_print_hf_formats = NULL;
436 static GSList *
437 make_triple (const GnmPrintHF *hf)
439 GSList *l = NULL;
441 GO_SLIST_PREPEND (l, hf->left_format ? hf->left_format : NULL);
442 GO_SLIST_PREPEND (l, hf->middle_format ? hf->middle_format : NULL);
443 GO_SLIST_PREPEND (l, hf->right_format ? hf->right_format : NULL);
445 return l;
448 void
449 gnm_print_info_save (GnmPrintInformation *pi)
451 GSList *l;
453 gnm_conf_set_printsetup_scale_percentage (pi->scaling.type == PRINT_SCALE_PERCENTAGE);
454 gnm_conf_set_printsetup_scale_percentage_value (pi->scaling.percentage.x);
455 gnm_conf_set_printsetup_scale_width (pi->scaling.dim.cols);
456 gnm_conf_set_printsetup_scale_height (pi->scaling.dim.rows);
458 gnm_conf_set_printsetup_margin_top (pi->edge_to_below_header);
459 gnm_conf_set_printsetup_margin_bottom (pi->edge_to_above_footer);
460 gnm_conf_set_printsetup_preferred_unit (pi->desired_display.top);
462 gnm_conf_set_printsetup_center_horizontally (pi->center_horizontally);
463 gnm_conf_set_printsetup_center_vertically (pi->center_vertically);
464 gnm_conf_set_printsetup_print_grid_lines (pi->print_grid_lines);
465 gnm_conf_set_printsetup_print_titles (pi->print_titles);
466 gnm_conf_set_printsetup_print_even_if_only_styles (pi->print_even_if_only_styles);
467 gnm_conf_set_printsetup_print_black_n_white (pi->print_black_and_white);
468 gnm_conf_set_printsetup_across_then_down (pi->print_across_then_down);
470 gnm_conf_set_printsetup_repeat_top (pi->repeat_top);
471 gnm_conf_set_printsetup_repeat_left (pi->repeat_left);
473 save_formats ();
475 l = make_triple (pi->header);
476 gnm_conf_set_printsetup_header (l);
477 g_slist_free (l);
479 l = make_triple (pi->footer);
480 gnm_conf_set_printsetup_footer (l);
481 g_slist_free (l);
483 gnm_conf_set_page_setup (pi->page_setup);
486 GtkUnit
487 unit_name_to_unit (char const *name)
489 if (!g_ascii_strcasecmp (name, "cm"))
490 return GTK_UNIT_MM;
491 if (!g_ascii_strcasecmp (name, "mm"))
492 return GTK_UNIT_MM;
493 if (!g_ascii_strcasecmp (name, "centimeter"))
494 return GTK_UNIT_MM;
495 if (!g_ascii_strcasecmp (name, "millimeter"))
496 return GTK_UNIT_MM;
497 if (!g_ascii_strcasecmp (name, "inch"))
498 return GTK_UNIT_INCH;
499 if (!g_ascii_strcasecmp (name, "in"))
500 return GTK_UNIT_INCH;
501 if (!g_ascii_strcasecmp (name, "inches"))
502 return GTK_UNIT_INCH;
504 return GTK_UNIT_POINTS;
507 char const *
508 unit_to_unit_name (GtkUnit unit)
510 switch (unit) {
511 case GTK_UNIT_MM:
512 return "mm";
513 case GTK_UNIT_INCH:
514 return "inch";
515 default:
516 return "points";
521 static void
522 render_cell (GString *target, GnmPrintHFRenderInfo *info, char const *args)
524 gboolean use_repeating = FALSE;
526 if (args && ((use_repeating = g_str_has_prefix (args, "rep|"))))
527 args += 4;
529 if (info->sheet) {
530 GnmRangeRef ref;
531 GnmValue const *val;
532 char const *tmp;
533 GnmParsePos ppos;
535 parse_pos_init (&ppos, info->sheet->workbook, (Sheet *)info->sheet, 0, 0);
536 tmp = rangeref_parse
537 (&ref, args, &ppos, sheet_get_conventions (info->sheet));
538 if (tmp == NULL || tmp == args) {
539 gnm_cellref_init (&ref.a, (Sheet *)(info->sheet), 0, 0, FALSE);
542 if (ref.a.row_relative)
543 ref.a.row += (use_repeating ?
544 info->top_repeating.row : info->page_area.start.row);
545 if (ref.a.col_relative)
546 ref.a.col += (use_repeating ?
547 info->top_repeating.col : info->page_area.start.col);
549 val = sheet_cell_get_value
550 (ref.a.sheet ? ref.a.sheet : (Sheet *)(info->sheet),
551 ref.a.col, ref.a.row);
552 if (val != NULL) {
553 char const *value;
554 value = value_peek_string (val);
555 g_string_append (target, value);
558 else {
559 if (use_repeating)
560 g_string_append (target, "[");
561 g_string_append (target, args);
562 if (use_repeating)
563 g_string_append (target, "]");
567 static void
568 render_tab (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
570 if (info->sheet)
571 g_string_append (target, info->sheet->name_unquoted);
572 else
573 g_string_append (target, _("Sheet"));
576 static void
577 render_page (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
579 g_string_append_printf (target, "%d", info->page);
582 static void
583 render_pages (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
585 g_string_append_printf (target, "%d", info->pages);
588 static void
589 render_timestamp_with_format (GString *target, char const *number_format, GnmPrintHFRenderInfo *info)
591 GOFormat *format;
593 /* TODO : Check this assumption. Is it a localized format? */
594 format = go_format_new_from_XL (number_format);
595 format_value_gstring (target, format, info->date_time,
596 -1, info->date_conv);
597 go_format_unref (format);
600 static void
601 render_date (GString *target, GnmPrintHFRenderInfo *info, char const *args)
603 char const *date_format;
605 if (args)
606 date_format = args;
607 else
608 date_format = "dd-mmm-yyyy";
610 render_timestamp_with_format (target, date_format, info);
613 static void
614 render_time (GString *target, GnmPrintHFRenderInfo *info, char const *args)
616 char const *time_format;
618 if (args)
619 time_format = args;
620 else
621 time_format = "hh:mm";
622 render_timestamp_with_format (target, time_format, info);
625 static void
626 render_file (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
628 if (info->sheet != NULL && info->sheet->workbook != NULL) {
629 char *name = go_basename_from_uri (
630 go_doc_get_uri (GO_DOC (info->sheet->workbook)));
631 g_string_append (target, name);
632 g_free (name);
633 } else
634 g_string_append (target, _("File Name"));
637 static void
638 render_path (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
640 if (info->sheet != NULL && info->sheet->workbook != NULL) {
641 char *path = go_dirname_from_uri (
642 go_doc_get_uri (GO_DOC (info->sheet->workbook)), TRUE);
643 g_string_append (target, path);
644 g_free (path);
645 } else
646 g_string_append (target, _("Path "));
649 static void
650 render_title (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
652 if (info->sheet != NULL && info->sheet->workbook != NULL) {
653 GsfDocProp *prop;
654 prop = gsf_doc_meta_data_lookup
655 (go_doc_get_meta_data (GO_DOC (info->sheet->workbook)), GSF_META_NAME_TITLE);
656 if (prop != NULL) {
657 GValue *prop_value = (GValue *) gsf_doc_prop_get_val (prop);
658 if (prop_value != NULL)
659 g_string_append (target, g_value_get_string (prop_value));
661 } else
662 g_string_append (target, _("Title"));
665 static struct {
666 char const *name;
667 void (*render)(GString *target, GnmPrintHFRenderInfo *info, char const *args);
668 char *name_trans;
669 } render_ops [] = {
670 { N_("TAB"), render_tab , NULL},
671 { N_("PAGE"), render_page , NULL},
672 { N_("PAGES"), render_pages , NULL},
673 { N_("DATE"), render_date , NULL},
674 { N_("TIME"), render_time , NULL},
675 { N_("FILE"), render_file , NULL},
676 { N_("PATH"), render_path , NULL},
677 { N_("CELL"), render_cell , NULL},
678 { N_("TITLE"), render_title , NULL},
679 { NULL , NULL, NULL},
682 * Renders an opcode. The opcodes can take an argument by adding trailing ':'
683 * to the opcode and then a number format code
685 static void
686 render_opcode (GString *target, char /* non-const */ *opcode,
687 GnmPrintHFRenderInfo *info,
688 G_GNUC_UNUSED GnmPrintHFRenderType render_type)
690 char *args;
691 char *opcode_trans;
692 int i;
694 args = g_utf8_strchr (opcode, -1, ':');
695 if (args) {
696 *args = 0;
697 args++;
699 opcode_trans = g_utf8_casefold (opcode, -1);
701 for (i = 0; render_ops [i].name; i++) {
702 if (render_ops [i].name_trans == NULL) {
703 render_ops [i].name_trans = g_utf8_casefold (_(render_ops [i].name), -1);
706 if ((g_ascii_strcasecmp (render_ops [i].name, opcode) == 0) ||
707 (g_utf8_collate (render_ops [i].name_trans, opcode_trans) == 0)) {
708 (*render_ops [i].render)(target, info, args);
711 g_free (opcode_trans);
714 #if 0
715 3.3.1.36 evenHeader (Even Page Header)
717 &P Current page number
718 &N Page count
719 &D Current date
720 &T Current time
721 &A Sheet name (BIFF5-BIFF8)
722 &F File name without path
723 &Z File path without file name (BIFF8X)
724 &G Picture (BIFF8X)
725 &B Bold on/off (BIFF2-BIFF4)
726 &I Italic on/off (BIFF2-BIFF4)
727 &U Underlining on/off
728 &E Double underlining on/off (BIFF5-BIFF8)
729 &S Strikeout on/off
730 &X Superscript on/off (BIFF5-BIFF8)
731 &Y Subscript on/off (BIFF5-BIFF8)
732 &"<fontname>" Set new font <fontname>
733 &"<fontname>,<fontstyle>" Set new font with specified style <fontstyle>. The style <fontstyle> is in most cases
734 one of "Regular", "Bold", "Italic", or "Bold Italic". But this setting is dependent on the
735 used font, it may differ (localised style names, or "Standard", "Oblique", ...). (BIFF5-
736 BIFF8)
737 &<fontheight> Set font height in points (<fontheight> is a decimal value). If this command is followed
738 by a plain number to be printed in the header, it will be separated from the font height
739 with a space character.
740 #endif
742 char *
743 gnm_print_hf_format_render (char const *format, GnmPrintHFRenderInfo *info, GnmPrintHFRenderType render_type)
745 GString *result;
746 char const *p;
748 if (!format)
749 return NULL;
751 result = g_string_new (NULL);
752 for (p = format; *p; p++) {
753 if (*p == '&' && p[1] == '[') {
754 char const *start;
756 p += 2;
757 start = p;
758 while (*p && (*p != ']'))
759 p++;
761 if (*p == ']') {
762 char *operation = g_strndup (start, p - start);
763 render_opcode (result, operation, info, render_type);
764 g_free (operation);
765 } else
766 break;
767 } else
768 g_string_append_c (result, *p);
771 return g_string_free (result, FALSE);
774 GnmPrintHFRenderInfo *
775 gnm_print_hf_render_info_new (void)
777 GnmPrintHFRenderInfo *hfi;
779 hfi = g_new0 (GnmPrintHFRenderInfo, 1);
780 hfi->date_conv = go_date_conv_from_str ("Lotus:1900");
781 hfi->date_time = value_new_float
782 (go_date_timet_to_serial_raw (time (NULL), hfi->date_conv));
783 /* It doesn't appear like the end is accessed. */
784 range_init (&hfi->page_area, 0, 0, G_MAXINT / 2, G_MAXINT / 2);
785 hfi->top_repeating.col = 0;
786 hfi->top_repeating.row = 0;
788 return hfi;
791 void
792 gnm_print_hf_render_info_destroy (GnmPrintHFRenderInfo *hfi)
794 g_return_if_fail (hfi != NULL);
796 value_release (hfi->date_time);
797 g_free (hfi);
800 static GnmPrintHFRenderInfo *
801 hf_render_info_copy (GnmPrintHFRenderInfo *hfi)
803 GnmPrintHFRenderInfo *res;
804 g_return_val_if_fail (hfi != NULL, NULL);
806 res = g_new (GnmPrintHFRenderInfo, 1);
807 res->sheet = hfi->sheet;
808 res->page = hfi->page;
809 res->pages = hfi->pages;
810 res->date_time = value_dup (hfi->date_time);
811 res->date_conv = hfi->date_conv;
812 res->page_area = hfi->page_area;
813 res->top_repeating = hfi->top_repeating;
814 return res;
817 GType
818 gnm_print_hf_render_info_get_type (void)
820 static GType t = 0;
822 if (t == 0) {
823 t = g_boxed_type_register_static ("GnmPrintHFRenderInfo",
824 (GBoxedCopyFunc)hf_render_info_copy,
825 (GBoxedFreeFunc)gnm_print_hf_render_info_destroy);
827 return t;
830 static void
831 pdf_write_workbook (G_GNUC_UNUSED GOFileSaver const *fs,
832 G_GNUC_UNUSED GOIOContext *context,
833 WorkbookView const *wbv, GsfOutput *output)
835 Workbook const *wb = wb_view_get_workbook (wbv);
836 GPtrArray *sheets = g_object_get_data (G_OBJECT (wb), "pdf-sheets");
838 if (sheets) {
839 int i;
841 for (i = 0; i < workbook_sheet_count (wb); i++) {
842 Sheet *sheet = workbook_sheet_by_index (wb, i);
843 sheet->print_info->do_not_print = TRUE;
845 for (i = 0; i < (int)sheets->len; i++) {
846 Sheet *sheet = g_ptr_array_index (sheets, i);
847 sheet->print_info->do_not_print = FALSE;
851 gnm_print_sheet (NULL, wb_view_cur_sheet (wbv), FALSE,
852 GNM_PRINT_ALL_SHEETS, output);
855 static void
856 pdf_export (GOFileSaver const *fs, GOIOContext *context,
857 GoView const *view, GsfOutput *output)
859 WorkbookView const *wbv = GNM_WORKBOOK_VIEW (view);
860 Workbook const *wb = wb_view_get_workbook (wbv);
861 GPtrArray *objects = g_object_get_data (G_OBJECT (wb), "pdf-objects");
863 if (objects && objects->len > 0) {
864 gpointer object_fit = g_object_get_data (G_OBJECT (wb), "pdf-object-fit");
865 if (object_fit != NULL && GPOINTER_TO_INT (object_fit) == 1
866 && GNM_IS_SO_GRAPH (g_ptr_array_index (objects, 0))) {
867 GError *err = NULL;
868 sheet_object_write_image (g_ptr_array_index (objects, 0), "pdf", 150., output, &err);
869 if (err != NULL) {
870 go_io_error_push (context, go_error_info_new_str (err->message));
871 g_error_free (err);
873 } else
874 gnm_print_so (NULL, objects, output);
875 } else
876 pdf_write_workbook (fs, context, wbv, output);
879 static gboolean
880 cb_set_pdf_option (const char *key, const char *value,
881 GError **err, gpointer user)
883 Workbook *wb = user;
885 if (strcmp (key, "sheet") == 0) {
886 Sheet *sheet = workbook_sheet_by_name (wb, value);
887 GPtrArray *sheets;
889 if (!sheet) {
890 *err = g_error_new (go_error_invalid (), 0,
891 _("There is no such sheet"));
892 return TRUE;
895 sheets = g_object_get_data (G_OBJECT (wb), "pdf-sheets");
896 if (!sheets) {
897 sheets = g_ptr_array_new ();
898 g_object_set_data_full (G_OBJECT (wb),
899 "pdf-sheets", sheets,
900 (GDestroyNotify)g_ptr_array_unref);
902 g_ptr_array_add (sheets, sheet);
904 return FALSE;
907 if (strcmp (key, "object") == 0) {
908 GPtrArray *objects = g_object_get_data (G_OBJECT (wb), "pdf-objects");
909 GSList *sheets = workbook_sheets (wb);
910 gboolean object_seen = FALSE;
912 if (!objects) {
913 objects = g_ptr_array_new ();
914 g_object_set_data_full (G_OBJECT (wb),
915 "pdf-objects", objects,
916 (GDestroyNotify)g_ptr_array_unref);
919 for (; sheets != NULL; sheets = sheets->next) {
920 Sheet *sheet = sheets->data;
921 GSList *sobjects = sheet->sheet_objects;
922 for (; sobjects != NULL; sobjects = sobjects->next) {
923 SheetObject *so = sobjects->data;
924 gchar *name = NULL;
925 g_object_get (so, "name", &name, NULL);
926 if (strcmp (name, value) == 0) {
927 g_ptr_array_add (objects, so);
928 object_seen = TRUE;
932 if (!object_seen) {
933 *err = g_error_new (go_error_invalid (), 0,
934 _("There is no object with name "
935 "\'%s\'"), value);
936 return TRUE;
939 return FALSE;
942 if (strcmp (key, "paper") == 0) {
943 int i;
944 if (strcmp (value, "fit") == 0) {
945 g_object_set_data (G_OBJECT (wb),
946 "pdf-object-fit", GINT_TO_POINTER (1));
947 } else for (i = 0; i < workbook_sheet_count (wb); i++) {
948 Sheet *sheet = workbook_sheet_by_index (wb, i);
949 if (print_info_set_paper (sheet->print_info, value)) {
950 *err = g_error_new (go_error_invalid (), 0,
951 _("Unknown paper size"));
953 return TRUE;
956 return FALSE;
959 if (err)
960 *err = g_error_new (go_error_invalid (), 0,
961 _("Invalid option for pdf exporter"));
963 return TRUE;
966 static gboolean
967 pdf_set_export_options (G_GNUC_UNUSED GOFileSaver *fs,
968 GODoc *doc,
969 const char *options,
970 GError **err,
971 G_GNUC_UNUSED gpointer user)
973 return go_parse_key_value (options, err, cb_set_pdf_option, doc);
977 * print_init: (skip)
979 void
980 print_init (void)
982 /* Install a pdf saver. */
983 GOFileSaver *saver = go_file_saver_new (
984 PDF_SAVER_ID, "pdf",
985 _("PDF export"),
986 GO_FILE_FL_WRITE_ONLY, pdf_export);
987 g_signal_connect (G_OBJECT (saver), "set-export-options",
988 G_CALLBACK (pdf_set_export_options),
989 NULL);
990 go_file_saver_register (saver);
991 g_object_unref (saver);
993 load_formats ();
997 * print_shutdown: (skip)
999 void
1000 print_shutdown (void)
1002 go_file_saver_unregister (go_file_saver_for_id (PDF_SAVER_ID));
1004 save_formats ();
1005 destroy_formats ();
1008 #define COPY(field) dst->field = src->field
1010 GnmPrintInformation *
1011 gnm_print_info_dup (GnmPrintInformation const *src)
1013 GnmPrintInformation *dst = gnm_print_information_new (TRUE);
1015 gnm_print_info_load_defaults ((GnmPrintInformation *)src);
1017 COPY(scaling);
1018 COPY(edge_to_below_header);
1019 COPY(edge_to_above_footer);
1020 COPY(desired_display);
1022 g_free (dst->repeat_top);
1023 dst->repeat_top = g_strdup (src->repeat_top);
1025 g_free (dst->repeat_left);
1026 dst->repeat_left = g_strdup (src->repeat_left);
1028 COPY(print_across_then_down);
1029 COPY(center_vertically);
1030 COPY(center_horizontally);
1031 COPY(print_grid_lines);
1032 COPY(print_titles);
1033 COPY(print_black_and_white);
1034 COPY(print_as_draft);
1035 COPY(print_even_if_only_styles);
1036 COPY(do_not_print);
1037 COPY(comment_placement);
1038 COPY(error_display);
1040 gnm_page_breaks_free (dst->page_breaks.h);
1041 dst->page_breaks.h = gnm_page_breaks_dup (src->page_breaks.h);
1043 gnm_page_breaks_free (dst->page_breaks.v);
1044 dst->page_breaks.v = gnm_page_breaks_dup (src->page_breaks.v);
1046 gnm_print_hf_free (dst->header);
1047 dst->header = gnm_print_hf_copy (src->header);
1049 gnm_print_hf_free (dst->footer);
1050 dst->footer = gnm_print_hf_copy (src->footer);
1052 COPY(start_page);
1053 COPY(n_copies);
1055 g_free (dst->printtofile_uri);
1056 dst->printtofile_uri = g_strdup (src->printtofile_uri);
1058 if (dst->page_setup)
1059 g_object_unref (dst->page_setup);
1060 dst->page_setup = gtk_page_setup_copy (src->page_setup);
1062 return dst;
1065 #undef COPY
1067 void
1068 print_info_get_margins (GnmPrintInformation *pi,
1069 double *top, double *bottom,
1070 double *left, double *right,
1071 double *edge_to_below_header,
1072 double *edge_to_above_footer)
1074 g_return_if_fail (pi != NULL);
1075 gnm_print_info_load_defaults (pi);
1076 g_return_if_fail (pi->page_setup != NULL);
1078 if (NULL != top)
1079 *top = gtk_page_setup_get_top_margin (pi->page_setup, GTK_UNIT_POINTS);
1080 if (NULL != bottom)
1081 *bottom = gtk_page_setup_get_bottom_margin (pi->page_setup, GTK_UNIT_POINTS);
1082 if (NULL != left)
1083 *left = gtk_page_setup_get_left_margin (pi->page_setup, GTK_UNIT_POINTS);
1084 if (NULL != right)
1085 *right = gtk_page_setup_get_right_margin (pi->page_setup, GTK_UNIT_POINTS);
1086 if (NULL != edge_to_below_header)
1087 *edge_to_below_header = pi->edge_to_below_header;
1088 if (NULL != edge_to_above_footer)
1089 *edge_to_above_footer = pi->edge_to_above_footer;
1092 void
1093 print_info_set_margin_header (GnmPrintInformation *pi, double header)
1095 g_return_if_fail (pi != NULL);
1096 gnm_print_info_load_defaults (pi);
1097 g_return_if_fail (pi->page_setup != NULL);
1099 gtk_page_setup_set_top_margin (pi->page_setup, header, GTK_UNIT_POINTS);
1102 void
1103 print_info_set_margin_footer (GnmPrintInformation *pi, double footer)
1105 g_return_if_fail (pi != NULL);
1106 gnm_print_info_load_defaults (pi);
1107 g_return_if_fail (pi->page_setup != NULL);
1109 gtk_page_setup_set_bottom_margin (pi->page_setup, footer, GTK_UNIT_POINTS);
1112 void
1113 print_info_set_margin_left (GnmPrintInformation *pi, double left)
1115 g_return_if_fail (pi != NULL);
1116 gnm_print_info_load_defaults (pi);
1117 g_return_if_fail (pi->page_setup != NULL);
1119 gtk_page_setup_set_left_margin (pi->page_setup, left, GTK_UNIT_POINTS);
1122 void
1123 print_info_set_margin_right (GnmPrintInformation *pi, double right)
1125 g_return_if_fail (pi != NULL);
1126 gnm_print_info_load_defaults (pi);
1127 g_return_if_fail (pi->page_setup != NULL);
1129 gtk_page_setup_set_right_margin (pi->page_setup, right, GTK_UNIT_POINTS);
1132 void
1133 print_info_set_edge_to_above_footer (GnmPrintInformation *pi, double e_f)
1135 g_return_if_fail (pi != NULL);
1136 gnm_print_info_load_defaults (pi);
1137 g_return_if_fail (pi->page_setup != NULL);
1139 pi->edge_to_above_footer = e_f;
1142 void
1143 print_info_set_edge_to_below_header (GnmPrintInformation *pi, double e_h)
1145 g_return_if_fail (pi != NULL);
1146 gnm_print_info_load_defaults (pi);
1147 g_return_if_fail (pi->page_setup != NULL);
1149 pi->edge_to_below_header = e_h;
1153 void
1154 print_info_set_margins (GnmPrintInformation *pi,
1155 double header, double footer, double left, double right)
1157 g_return_if_fail (pi != NULL);
1158 gnm_print_info_load_defaults (pi);
1159 g_return_if_fail (pi->page_setup != NULL);
1161 if (header >= 0)
1162 gtk_page_setup_set_top_margin (pi->page_setup,
1163 header, GTK_UNIT_POINTS);
1164 if (footer >= 0)
1165 gtk_page_setup_set_bottom_margin (pi->page_setup,
1166 footer, GTK_UNIT_POINTS);
1167 if (left >= 0)
1168 gtk_page_setup_set_left_margin (pi->page_setup,
1169 left, GTK_UNIT_POINTS);
1170 if (right >= 0)
1171 gtk_page_setup_set_right_margin (pi->page_setup,
1172 right, GTK_UNIT_POINTS);
1175 static gboolean
1176 known_bad_paper (const char *paper)
1178 if (strcmp (paper, "") == 0)
1179 return TRUE;
1180 return FALSE;
1184 static void
1185 paper_log_func (G_GNUC_UNUSED const gchar *log_domain,
1186 GLogLevelFlags log_level,
1187 G_GNUC_UNUSED const gchar *message,
1188 gpointer user_data)
1190 int *pwarn = user_data;
1192 if (log_level & G_LOG_LEVEL_WARNING)
1193 *pwarn = 1;
1196 gboolean
1197 page_setup_set_paper (GtkPageSetup *page_setup, char const *paper)
1199 GtkPaperSize* gtk_paper;
1200 int bad_paper = 0;
1202 g_return_val_if_fail (page_setup != NULL, TRUE);
1204 /* We are now using the standard paper names given by PWG 5101.1-2002 */
1205 /* We are trying to map some old gnome-print paper names. */
1208 "A4" -> GTK_PAPER_NAME_A4
1209 "USLetter" -> GTK_PAPER_NAME_LETTER
1210 "USLegal" -> GTK_PAPER_NAME_LEGAL
1211 "Executive" -> GTK_PAPER_NAME_EXECUTIVE
1212 "A3" -> GTK_PAPER_NAME_A3
1213 "A5" -> GTK_PAPER_NAME_A5
1214 "B5" -> GTK_PAPER_NAME_B5
1215 * */
1217 if (g_ascii_strcasecmp ("A4", paper) == 0)
1218 paper = GTK_PAPER_NAME_A4;
1219 else if (g_ascii_strcasecmp ("A3", paper) == 0)
1220 paper = GTK_PAPER_NAME_A3;
1221 else if (g_ascii_strcasecmp ("A5", paper) == 0)
1222 paper = GTK_PAPER_NAME_A5;
1223 else if (g_ascii_strcasecmp ("B5", paper) == 0)
1224 paper = GTK_PAPER_NAME_B5;
1225 else if (g_ascii_strcasecmp ("USLetter", paper) == 0 ||
1226 g_ascii_strcasecmp ("US-Letter", paper) == 0 ||
1227 g_ascii_strcasecmp ("Letter", paper) == 0)
1228 paper = GTK_PAPER_NAME_LETTER;
1229 else if (g_ascii_strcasecmp ("USLegal", paper) == 0)
1230 paper = GTK_PAPER_NAME_LEGAL;
1231 else if (g_ascii_strncasecmp ("Executive", paper, 9) == 0)
1232 paper = GTK_PAPER_NAME_EXECUTIVE;
1233 /* GTK behaves stupid on some string it should recognize:*/
1234 else if (g_str_has_prefix (paper, "iso_a3_"))
1235 paper = GTK_PAPER_NAME_A3;
1236 else if (g_str_has_prefix (paper, "iso_a4_"))
1237 paper = GTK_PAPER_NAME_A4;
1238 else if (g_str_has_prefix (paper, "iso_a5_"))
1239 paper = GTK_PAPER_NAME_A5;
1240 else if (g_str_has_prefix (paper, "iso_b5_"))
1241 paper = GTK_PAPER_NAME_B5;
1242 else if (g_str_has_prefix (paper, "na_letter_"))
1243 paper = GTK_PAPER_NAME_LETTER;
1244 else if (g_str_has_prefix (paper, "na_legal_"))
1245 paper = GTK_PAPER_NAME_LEGAL;
1246 else if (g_str_has_prefix (paper, "na_executive_"))
1247 paper = GTK_PAPER_NAME_EXECUTIVE;
1249 /* Hack: gtk_paper_size_new warns on bad paper, so shut it up. */
1250 /* http://bugzilla.gnome.org/show_bug.cgi?id=493880 */
1251 if (known_bad_paper (paper)) {
1252 gtk_paper = NULL;
1253 bad_paper = 1;
1254 } else {
1255 const char *domain = "Gtk";
1256 guint handler = g_log_set_handler (domain, G_LOG_LEVEL_WARNING,
1257 paper_log_func, &bad_paper);
1259 gtk_paper = gtk_paper_size_new (paper);
1260 g_log_remove_handler (domain, handler);
1261 if (!gtk_paper)
1262 bad_paper = 1;
1265 if (!bad_paper)
1266 gtk_page_setup_set_paper_size (page_setup, gtk_paper);
1267 if (gtk_paper)
1268 gtk_paper_size_free (gtk_paper);
1270 return bad_paper;
1273 gboolean
1274 print_info_set_paper (GnmPrintInformation *pi, char const *paper)
1276 g_return_val_if_fail (pi != NULL, TRUE);
1278 gnm_print_info_load_defaults (pi);
1279 return page_setup_set_paper (pi->page_setup, paper);
1282 char *
1283 page_setup_get_paper (GtkPageSetup *page_setup)
1285 GtkPaperSize* paper;
1286 char const *name;
1288 g_return_val_if_fail (page_setup != NULL, g_strdup (GTK_PAPER_NAME_A4));
1290 paper = gtk_page_setup_get_paper_size (page_setup);
1292 if (gtk_paper_size_is_custom (paper)) {
1293 double width = gtk_paper_size_get_width (paper, GTK_UNIT_MM);
1294 double height = gtk_paper_size_get_height (paper, GTK_UNIT_MM);
1295 return g_strdup_printf ("custom_Gnm-%.0fx%.0fmm_%.0fx%.0fmm",
1296 width, height, width, height);
1299 name = gtk_paper_size_get_name (gtk_page_setup_get_paper_size (page_setup));
1301 /* Working around gtk bug 426416 */
1302 if (strncmp (name, "custom", 6) == 0) {
1303 double width = gtk_paper_size_get_width (paper, GTK_UNIT_MM);
1304 double height = gtk_paper_size_get_height (paper, GTK_UNIT_MM);
1305 return g_strdup_printf ("custom_Gnm-%.0fx%.0fmm_%.0fx%.0fmm",
1306 width, height, width, height);
1308 return g_strdup (name);
1311 char *
1312 print_info_get_paper (GnmPrintInformation *pi)
1314 g_return_val_if_fail (pi != NULL, g_strdup (GTK_PAPER_NAME_A4));
1315 gnm_print_info_load_defaults (pi);
1317 return page_setup_get_paper (pi->page_setup);
1320 GtkPaperSize *
1321 print_info_get_paper_size (GnmPrintInformation *pi)
1323 g_return_val_if_fail (pi != NULL, NULL);
1324 gnm_print_info_load_defaults (pi);
1326 return gtk_page_setup_get_paper_size (pi->page_setup);
1330 char const*
1331 print_info_get_paper_display_name (GnmPrintInformation *pi)
1333 GtkPaperSize* paper;
1335 g_return_val_if_fail (pi != NULL, "ERROR: No printinformation specified");
1336 gnm_print_info_load_defaults (pi);
1337 g_return_val_if_fail (pi->page_setup != NULL, "ERROR: No pagesetup loaded");
1339 paper = gtk_page_setup_get_paper_size (pi->page_setup);
1340 return gtk_paper_size_get_display_name (paper);
1343 double
1344 print_info_get_paper_width (GnmPrintInformation *pi, GtkUnit unit)
1346 g_return_val_if_fail (pi != NULL, 0.);
1347 gnm_print_info_load_defaults (pi);
1349 return gtk_page_setup_get_paper_width (pi->page_setup, unit);
1352 double
1353 print_info_get_paper_height (GnmPrintInformation *pi, GtkUnit unit)
1355 g_return_val_if_fail (pi != NULL, 0);
1356 gnm_print_info_load_defaults (pi);
1358 return gtk_page_setup_get_paper_height (pi->page_setup, unit);
1362 * gnm_print_info_get_page_setup:
1363 * @pi: #GnmPrintInformation
1365 * Returns: (transfer none): the page setup.
1367 GtkPageSetup*
1368 gnm_print_info_get_page_setup (GnmPrintInformation *pi)
1370 g_return_val_if_fail (pi != NULL, NULL);
1371 gnm_print_info_load_defaults (pi);
1373 return pi->page_setup;
1377 * gnm_print_info_set_page_setup :
1378 * @pi: #GnmPrintInformation
1379 * @page_setup: #GtkPageSetup
1381 * Absorb a ref to @page_setup.
1383 * WHY WHY WHY
1384 * 1) The life cycle in here is a tad odd, the load_defaults does nothing for the
1385 * case of an existing page_setup, and seems like it should be ignored for the
1386 * case of a new one.
1388 * 2) Why not copy the page_setup in here and make the arg const ?
1390 void
1391 gnm_print_info_set_page_setup (GnmPrintInformation *pi, GtkPageSetup *page_setup)
1393 g_return_if_fail (pi != NULL);
1395 gnm_print_info_load_defaults (pi);
1397 if (pi->page_setup) {
1398 double header, footer, left, right;
1399 print_info_get_margins (pi,
1400 &header, &footer, &left, &right, NULL, NULL);
1401 g_object_unref (pi->page_setup);
1402 pi->page_setup = page_setup;
1403 print_info_set_margins (pi, header, footer, left, right);
1404 } else
1405 pi->page_setup = page_setup;
1408 GtkPageOrientation
1409 print_info_get_paper_orientation (GnmPrintInformation *pi)
1411 GtkPageOrientation orientation;
1413 g_return_val_if_fail (pi != NULL, GTK_PAGE_ORIENTATION_PORTRAIT);
1414 gnm_print_info_load_defaults (pi);
1415 g_return_val_if_fail (pi->page_setup != NULL, GTK_PAGE_ORIENTATION_PORTRAIT);
1417 orientation = gtk_page_setup_get_orientation (pi->page_setup);
1418 return orientation;
1421 void
1422 print_info_set_paper_orientation (GnmPrintInformation *pi,
1423 GtkPageOrientation orientation)
1425 g_return_if_fail (pi != NULL);
1426 gnm_print_info_load_defaults (pi);
1428 gtk_page_setup_set_orientation (pi->page_setup, orientation);
1432 * print_info_set_breaks :
1433 * @pi: #GnmPrintInformation
1434 * @breaks: #GnmPageBreaks
1436 * NOTE : Takes ownership of @breaks. DO NOT FREE after calling.
1438 void
1439 print_info_set_breaks (GnmPrintInformation *pi,
1440 GnmPageBreaks *breaks)
1442 GnmPageBreaks **target;
1444 g_return_if_fail (pi != NULL);
1446 target = breaks->is_vert ? &pi->page_breaks.v : &pi->page_breaks.h;
1448 if (*target == breaks) /* just in case something silly happens */
1449 return;
1451 gnm_page_breaks_free (*target);
1452 *target = breaks;
1455 gboolean
1456 print_info_has_manual_breaks (GnmPrintInformation *pi)
1458 if (gnm_page_breaks_get_next_manual_break (pi->page_breaks.v, 0) > -1)
1459 return TRUE;
1460 return (gnm_page_breaks_get_next_manual_break (pi->page_breaks.h, 0) > -1);
1463 /********************************************************************
1464 * Simple data structure to store page breaks defined as a wrapper in case we
1465 * need something more extensive later. */
1468 * gnm_page_breaks_new :
1469 * @is_vert:
1471 * Allocate a collection of page breaks.
1473 GnmPageBreaks *
1474 gnm_page_breaks_new (gboolean is_vert)
1476 GnmPageBreaks *res = g_new (GnmPageBreaks, 1);
1478 res->is_vert = is_vert;
1479 res->details = g_array_new (FALSE, FALSE, sizeof (GnmPageBreak));
1481 return res;
1484 GnmPageBreaks *
1485 gnm_page_breaks_dup (GnmPageBreaks const *src)
1487 if (src != NULL) {
1488 GnmPageBreaks *dst = gnm_page_breaks_new (src->is_vert);
1489 GArray *d_details = dst->details;
1490 GArray const *s_details = src->details;
1491 unsigned i;
1493 /* no need to validate through gnm_page_breaks_append_break, just dup */
1494 for (i = 0; i < s_details->len ; i++)
1495 g_array_append_val (d_details,
1496 g_array_index (s_details, GnmPageBreak, i));
1498 return dst;
1499 } else
1500 return NULL;
1503 void
1504 gnm_page_breaks_free (GnmPageBreaks *breaks)
1506 if (breaks) {
1507 g_array_free (breaks->details, TRUE);
1508 g_free (breaks);
1512 GType
1513 gnm_page_breaks_get_type (void)
1515 static GType t = 0;
1517 if (t == 0) {
1518 t = g_boxed_type_register_static ("GnmPageBreaks",
1519 (GBoxedCopyFunc)gnm_page_breaks_dup,
1520 (GBoxedFreeFunc)gnm_page_breaks_free);
1522 return t;
1525 GnmPageBreaks *
1526 gnm_page_breaks_dup_non_auto_breaks (GnmPageBreaks const *src)
1528 if (src != NULL) {
1529 GnmPageBreaks *dst = gnm_page_breaks_new (src->is_vert);
1530 GArray *d_details = dst->details;
1531 GArray const *s_details = src->details;
1532 GnmPageBreak *pbreak;
1533 unsigned i;
1535 /* no need to validate through gnm_page_breaks_append_break, just dup */
1536 for (i = 0; i < s_details->len ; i++) {
1537 pbreak = &g_array_index (s_details, GnmPageBreak, i);
1538 if (pbreak->type != GNM_PAGE_BREAK_AUTO)
1539 g_array_append_val (d_details, *pbreak);
1541 return dst;
1542 } else
1543 return NULL;
1546 gboolean
1547 gnm_page_breaks_append_break (GnmPageBreaks *breaks,
1548 int pos,
1549 GnmPageBreakType type)
1551 GnmPageBreak const *prev;
1552 GnmPageBreak info;
1554 g_return_val_if_fail (breaks != NULL, FALSE);
1556 if (type == GNM_PAGE_BREAK_NONE)
1557 return TRUE;
1559 /* Do some simple validation */
1560 if (pos < 0)
1561 return FALSE;
1562 if (breaks->details->len > 0) {
1563 prev = &g_array_index (breaks->details, GnmPageBreak,
1564 breaks->details->len-1);
1565 if (prev->pos >= pos)
1566 return FALSE;
1569 info.pos = pos;
1570 info.type = type;
1571 g_array_append_val (breaks->details, info);
1573 return TRUE;
1576 GnmPageBreakType
1577 gnm_page_breaks_get_break (GnmPageBreaks *breaks,
1578 int pos)
1580 int i;
1582 if (breaks == NULL)
1583 return GNM_PAGE_BREAK_NONE;
1585 for (i = breaks->details->len - 1; i >= 0; i--) {
1586 GnmPageBreak *pbreak;
1587 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1588 if (pbreak->pos < pos)
1589 return GNM_PAGE_BREAK_NONE;
1590 if (pbreak->pos == pos)
1591 return (pbreak->type);
1593 return GNM_PAGE_BREAK_NONE;
1597 gnm_page_breaks_get_next_manual_break (GnmPageBreaks *breaks,
1598 int pos)
1600 guint i;
1602 if (breaks == NULL)
1603 return -1;
1605 for (i = 0; i < breaks->details->len; i++) {
1606 GnmPageBreak const *pbreak;
1607 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1608 if (pbreak->pos > pos
1609 && pbreak->type != GNM_PAGE_BREAK_AUTO)
1610 return pbreak->pos;
1612 return -1;
1616 gnm_page_breaks_get_next_break (GnmPageBreaks *breaks,
1617 int pos)
1619 guint i;
1621 if (breaks == NULL)
1622 return -1;
1624 for (i = 0; i < breaks->details->len; i++) {
1625 GnmPageBreak const *pbreak;
1626 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1627 if (pbreak->pos > pos)
1628 return pbreak->pos;
1630 return -1;
1633 gboolean
1634 gnm_page_breaks_set_break (GnmPageBreaks *breaks,
1635 int pos,
1636 GnmPageBreakType type)
1638 GnmPageBreak *pbreak;
1639 GnmPageBreak info;
1640 guint i;
1641 int before = -1;
1643 g_return_val_if_fail (breaks != NULL, FALSE);
1645 /* Do some simple validation */
1646 if (pos < 0)
1647 return FALSE;
1649 if (breaks->details->len == 0 && type != GNM_PAGE_BREAK_NONE)
1650 return gnm_page_breaks_append_break (breaks, pos, type);
1652 for (i = 0; i < breaks->details->len; i++) {
1653 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1654 if (pbreak->pos == pos) {
1655 if (type == GNM_PAGE_BREAK_NONE) {
1656 g_array_remove_index (breaks->details, i);
1657 } else {
1658 pbreak->type = type;
1660 return TRUE;
1661 } else if (pbreak->pos < pos)
1662 before = (int) i;
1665 if (type == GNM_PAGE_BREAK_NONE)
1666 return TRUE;
1668 info.pos = pos;
1669 info.type = type;
1670 if ((before + 1) > (int) breaks->details->len)
1671 g_array_append_val (breaks->details, info);
1672 else
1673 g_array_insert_val (breaks->details, (before + 1), info);
1675 return TRUE;
1679 * gnm_page_break_type_from_str:
1680 * @str:
1683 GnmPageBreakType
1684 gnm_page_break_type_from_str (char const *str)
1686 if (0 == g_ascii_strcasecmp (str, "manual"))
1687 return GNM_PAGE_BREAK_MANUAL;
1688 if (0 == g_ascii_strcasecmp (str, "auto"))
1689 return GNM_PAGE_BREAK_AUTO;
1690 if (0 == g_ascii_strcasecmp (str, "data-slice"))
1691 return GNM_PAGE_BREAK_DATA_SLICE;
1692 if (0 == g_ascii_strcasecmp (str, "none"))
1693 return GNM_PAGE_BREAK_NONE;
1694 return GNM_PAGE_BREAK_NONE;
1699 * gnm_page_breaks_clean:
1701 * Remove all auto page breaks
1704 void
1705 gnm_page_breaks_clean (GnmPageBreaks *breaks)
1707 guint i;
1709 if (breaks == NULL)
1710 return;
1712 for (i = 0; i < breaks->details->len; i++) {
1713 GnmPageBreak *pbreak = &g_array_index (breaks->details,
1714 GnmPageBreak, i);
1715 if (pbreak->type == GNM_PAGE_BREAK_AUTO) {
1716 g_array_remove_index (breaks->details, i);
1717 i--;
1722 void
1723 print_info_set_printtofile_uri (GnmPrintInformation *pi,
1724 gchar const *uri)
1726 g_free (pi->printtofile_uri);
1727 pi->printtofile_uri = g_strdup (uri);
1730 void
1731 print_info_set_printtofile_from_settings (GnmPrintInformation *pi,
1732 GtkPrintSettings* settings,
1733 gchar const *default_uri)
1735 char const *uri = gtk_print_settings_get
1736 (settings,
1737 GTK_PRINT_SETTINGS_OUTPUT_URI);
1738 if (strcmp (uri, default_uri) == 0)
1739 print_info_set_printtofile_uri (pi, NULL);
1740 else
1741 print_info_set_printtofile_uri (pi, uri);
1744 void
1745 print_info_set_from_settings (GnmPrintInformation *pi,
1746 GtkPrintSettings* settings)
1748 pi->print_range = gtk_print_settings_get_int_with_default
1749 (settings,
1750 GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY,
1751 GNM_PRINT_ACTIVE_SHEET);
1754 PrintRange
1755 print_info_get_printrange (GnmPrintInformation *pi)
1757 gnm_print_info_load_defaults (pi);
1758 return pi->print_range;
1761 void
1762 print_info_set_printrange (GnmPrintInformation *pi, PrintRange pr)
1764 if (pr >= GNM_PRINT_ACTIVE_SHEET
1765 && pr <= GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA)
1766 pi->print_range = pr;
1767 else
1768 pi->print_range = GNM_PRINT_ACTIVE_SHEET;
1772 char const *
1773 print_info_get_printtofile_uri (GnmPrintInformation *pi)
1775 gnm_print_info_load_defaults (pi);
1776 return pi->printtofile_uri;
1780 gboolean
1781 print_load_repeat_range (char const *str, GnmRange *r, Sheet const *sheet)
1783 GnmParsePos pp;
1784 GnmRangeRef res;
1786 if (str == NULL || *str == '\0')
1787 return FALSE;
1789 if (str != rangeref_parse (&res, str,
1790 parse_pos_init_sheet (&pp, sheet),
1791 gnm_conventions_default)) {
1792 Sheet *start_sheet = (Sheet *)sheet;
1793 Sheet *end_sheet = (Sheet *)sheet;
1794 gnm_rangeref_normalize_pp (&res, &pp,
1795 &start_sheet, &end_sheet,
1797 return TRUE;
1798 } else
1799 return FALSE;