Introspection: add col/row manipulations
[gnumeric.git] / src / print-info.c
blob578f4affbbbe7ec835bfff2c9d627d502c584bac
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);
976 void
977 print_init (void)
979 /* Install a pdf saver. */
980 GOFileSaver *saver = go_file_saver_new (
981 PDF_SAVER_ID, "pdf",
982 _("PDF export"),
983 GO_FILE_FL_WRITE_ONLY, pdf_export);
984 g_signal_connect (G_OBJECT (saver), "set-export-options",
985 G_CALLBACK (pdf_set_export_options),
986 NULL);
987 go_file_saver_register (saver);
988 g_object_unref (saver);
990 load_formats ();
993 void
994 print_shutdown (void)
996 go_file_saver_unregister (go_file_saver_for_id (PDF_SAVER_ID));
998 save_formats ();
999 destroy_formats ();
1002 #define COPY(field) dst->field = src->field
1004 GnmPrintInformation *
1005 gnm_print_info_dup (GnmPrintInformation const *src)
1007 GnmPrintInformation *dst = gnm_print_information_new (TRUE);
1009 gnm_print_info_load_defaults ((GnmPrintInformation *)src);
1011 COPY(scaling);
1012 COPY(edge_to_below_header);
1013 COPY(edge_to_above_footer);
1014 COPY(desired_display);
1016 g_free (dst->repeat_top);
1017 dst->repeat_top = g_strdup (src->repeat_top);
1019 g_free (dst->repeat_left);
1020 dst->repeat_left = g_strdup (src->repeat_left);
1022 COPY(print_across_then_down);
1023 COPY(center_vertically);
1024 COPY(center_horizontally);
1025 COPY(print_grid_lines);
1026 COPY(print_titles);
1027 COPY(print_black_and_white);
1028 COPY(print_as_draft);
1029 COPY(print_even_if_only_styles);
1030 COPY(do_not_print);
1031 COPY(comment_placement);
1032 COPY(error_display);
1034 gnm_page_breaks_free (dst->page_breaks.h);
1035 dst->page_breaks.h = gnm_page_breaks_dup (src->page_breaks.h);
1037 gnm_page_breaks_free (dst->page_breaks.v);
1038 dst->page_breaks.v = gnm_page_breaks_dup (src->page_breaks.v);
1040 gnm_print_hf_free (dst->header);
1041 dst->header = gnm_print_hf_copy (src->header);
1043 gnm_print_hf_free (dst->footer);
1044 dst->footer = gnm_print_hf_copy (src->footer);
1046 COPY(start_page);
1047 COPY(n_copies);
1049 g_free (dst->printtofile_uri);
1050 dst->printtofile_uri = g_strdup (src->printtofile_uri);
1052 if (dst->page_setup)
1053 g_object_unref (dst->page_setup);
1054 dst->page_setup = gtk_page_setup_copy (src->page_setup);
1056 return dst;
1059 #undef COPY
1061 void
1062 print_info_get_margins (GnmPrintInformation *pi,
1063 double *top, double *bottom,
1064 double *left, double *right,
1065 double *edge_to_below_header,
1066 double *edge_to_above_footer)
1068 g_return_if_fail (pi != NULL);
1069 gnm_print_info_load_defaults (pi);
1070 g_return_if_fail (pi->page_setup != NULL);
1072 if (NULL != top)
1073 *top = gtk_page_setup_get_top_margin (pi->page_setup, GTK_UNIT_POINTS);
1074 if (NULL != bottom)
1075 *bottom = gtk_page_setup_get_bottom_margin (pi->page_setup, GTK_UNIT_POINTS);
1076 if (NULL != left)
1077 *left = gtk_page_setup_get_left_margin (pi->page_setup, GTK_UNIT_POINTS);
1078 if (NULL != right)
1079 *right = gtk_page_setup_get_right_margin (pi->page_setup, GTK_UNIT_POINTS);
1080 if (NULL != edge_to_below_header)
1081 *edge_to_below_header = pi->edge_to_below_header;
1082 if (NULL != edge_to_above_footer)
1083 *edge_to_above_footer = pi->edge_to_above_footer;
1086 void
1087 print_info_set_margin_header (GnmPrintInformation *pi, double header)
1089 g_return_if_fail (pi != NULL);
1090 gnm_print_info_load_defaults (pi);
1091 g_return_if_fail (pi->page_setup != NULL);
1093 gtk_page_setup_set_top_margin (pi->page_setup, header, GTK_UNIT_POINTS);
1096 void
1097 print_info_set_margin_footer (GnmPrintInformation *pi, double footer)
1099 g_return_if_fail (pi != NULL);
1100 gnm_print_info_load_defaults (pi);
1101 g_return_if_fail (pi->page_setup != NULL);
1103 gtk_page_setup_set_bottom_margin (pi->page_setup, footer, GTK_UNIT_POINTS);
1106 void
1107 print_info_set_margin_left (GnmPrintInformation *pi, double left)
1109 g_return_if_fail (pi != NULL);
1110 gnm_print_info_load_defaults (pi);
1111 g_return_if_fail (pi->page_setup != NULL);
1113 gtk_page_setup_set_left_margin (pi->page_setup, left, GTK_UNIT_POINTS);
1116 void
1117 print_info_set_margin_right (GnmPrintInformation *pi, double right)
1119 g_return_if_fail (pi != NULL);
1120 gnm_print_info_load_defaults (pi);
1121 g_return_if_fail (pi->page_setup != NULL);
1123 gtk_page_setup_set_right_margin (pi->page_setup, right, GTK_UNIT_POINTS);
1126 void
1127 print_info_set_edge_to_above_footer (GnmPrintInformation *pi, double e_f)
1129 g_return_if_fail (pi != NULL);
1130 gnm_print_info_load_defaults (pi);
1131 g_return_if_fail (pi->page_setup != NULL);
1133 pi->edge_to_above_footer = e_f;
1136 void
1137 print_info_set_edge_to_below_header (GnmPrintInformation *pi, double e_h)
1139 g_return_if_fail (pi != NULL);
1140 gnm_print_info_load_defaults (pi);
1141 g_return_if_fail (pi->page_setup != NULL);
1143 pi->edge_to_below_header = e_h;
1147 void
1148 print_info_set_margins (GnmPrintInformation *pi,
1149 double header, double footer, double left, double right)
1151 g_return_if_fail (pi != NULL);
1152 gnm_print_info_load_defaults (pi);
1153 g_return_if_fail (pi->page_setup != NULL);
1155 if (header >= 0)
1156 gtk_page_setup_set_top_margin (pi->page_setup,
1157 header, GTK_UNIT_POINTS);
1158 if (footer >= 0)
1159 gtk_page_setup_set_bottom_margin (pi->page_setup,
1160 footer, GTK_UNIT_POINTS);
1161 if (left >= 0)
1162 gtk_page_setup_set_left_margin (pi->page_setup,
1163 left, GTK_UNIT_POINTS);
1164 if (right >= 0)
1165 gtk_page_setup_set_right_margin (pi->page_setup,
1166 right, GTK_UNIT_POINTS);
1169 static gboolean
1170 known_bad_paper (const char *paper)
1172 if (strcmp (paper, "") == 0)
1173 return TRUE;
1174 return FALSE;
1178 static void
1179 paper_log_func (G_GNUC_UNUSED const gchar *log_domain,
1180 GLogLevelFlags log_level,
1181 G_GNUC_UNUSED const gchar *message,
1182 gpointer user_data)
1184 int *pwarn = user_data;
1186 if (log_level & G_LOG_LEVEL_WARNING)
1187 *pwarn = 1;
1190 gboolean
1191 page_setup_set_paper (GtkPageSetup *page_setup, char const *paper)
1193 GtkPaperSize* gtk_paper;
1194 int bad_paper = 0;
1196 g_return_val_if_fail (page_setup != NULL, TRUE);
1198 /* We are now using the standard paper names given by PWG 5101.1-2002 */
1199 /* We are trying to map some old gnome-print paper names. */
1202 "A4" -> GTK_PAPER_NAME_A4
1203 "USLetter" -> GTK_PAPER_NAME_LETTER
1204 "USLegal" -> GTK_PAPER_NAME_LEGAL
1205 "Executive" -> GTK_PAPER_NAME_EXECUTIVE
1206 "A3" -> GTK_PAPER_NAME_A3
1207 "A5" -> GTK_PAPER_NAME_A5
1208 "B5" -> GTK_PAPER_NAME_B5
1209 * */
1211 if (g_ascii_strcasecmp ("A4", paper) == 0)
1212 paper = GTK_PAPER_NAME_A4;
1213 else if (g_ascii_strcasecmp ("A3", paper) == 0)
1214 paper = GTK_PAPER_NAME_A3;
1215 else if (g_ascii_strcasecmp ("A5", paper) == 0)
1216 paper = GTK_PAPER_NAME_A5;
1217 else if (g_ascii_strcasecmp ("B5", paper) == 0)
1218 paper = GTK_PAPER_NAME_B5;
1219 else if (g_ascii_strcasecmp ("USLetter", paper) == 0 ||
1220 g_ascii_strcasecmp ("US-Letter", paper) == 0 ||
1221 g_ascii_strcasecmp ("Letter", paper) == 0)
1222 paper = GTK_PAPER_NAME_LETTER;
1223 else if (g_ascii_strcasecmp ("USLegal", paper) == 0)
1224 paper = GTK_PAPER_NAME_LEGAL;
1225 else if (g_ascii_strncasecmp ("Executive", paper, 9) == 0)
1226 paper = GTK_PAPER_NAME_EXECUTIVE;
1227 /* GTK behaves stupid on some string it should recognize:*/
1228 else if (g_str_has_prefix (paper, "iso_a3_"))
1229 paper = GTK_PAPER_NAME_A3;
1230 else if (g_str_has_prefix (paper, "iso_a4_"))
1231 paper = GTK_PAPER_NAME_A4;
1232 else if (g_str_has_prefix (paper, "iso_a5_"))
1233 paper = GTK_PAPER_NAME_A5;
1234 else if (g_str_has_prefix (paper, "iso_b5_"))
1235 paper = GTK_PAPER_NAME_B5;
1236 else if (g_str_has_prefix (paper, "na_letter_"))
1237 paper = GTK_PAPER_NAME_LETTER;
1238 else if (g_str_has_prefix (paper, "na_legal_"))
1239 paper = GTK_PAPER_NAME_LEGAL;
1240 else if (g_str_has_prefix (paper, "na_executive_"))
1241 paper = GTK_PAPER_NAME_EXECUTIVE;
1243 /* Hack: gtk_paper_size_new warns on bad paper, so shut it up. */
1244 /* http://bugzilla.gnome.org/show_bug.cgi?id=493880 */
1245 if (known_bad_paper (paper)) {
1246 gtk_paper = NULL;
1247 bad_paper = 1;
1248 } else {
1249 const char *domain = "Gtk";
1250 guint handler = g_log_set_handler (domain, G_LOG_LEVEL_WARNING,
1251 paper_log_func, &bad_paper);
1253 gtk_paper = gtk_paper_size_new (paper);
1254 g_log_remove_handler (domain, handler);
1255 if (!gtk_paper)
1256 bad_paper = 1;
1259 if (!bad_paper)
1260 gtk_page_setup_set_paper_size (page_setup, gtk_paper);
1261 if (gtk_paper)
1262 gtk_paper_size_free (gtk_paper);
1264 return bad_paper;
1267 gboolean
1268 print_info_set_paper (GnmPrintInformation *pi, char const *paper)
1270 g_return_val_if_fail (pi != NULL, TRUE);
1272 gnm_print_info_load_defaults (pi);
1273 return page_setup_set_paper (pi->page_setup, paper);
1276 char *
1277 page_setup_get_paper (GtkPageSetup *page_setup)
1279 GtkPaperSize* paper;
1280 char const *name;
1282 g_return_val_if_fail (page_setup != NULL, g_strdup (GTK_PAPER_NAME_A4));
1284 paper = gtk_page_setup_get_paper_size (page_setup);
1286 if (gtk_paper_size_is_custom (paper)) {
1287 double width = gtk_paper_size_get_width (paper, GTK_UNIT_MM);
1288 double height = gtk_paper_size_get_height (paper, GTK_UNIT_MM);
1289 return g_strdup_printf ("custom_Gnm-%.0fx%.0fmm_%.0fx%.0fmm",
1290 width, height, width, height);
1293 name = gtk_paper_size_get_name (gtk_page_setup_get_paper_size (page_setup));
1295 /* Working around gtk bug 426416 */
1296 if (strncmp (name, "custom", 6) == 0) {
1297 double width = gtk_paper_size_get_width (paper, GTK_UNIT_MM);
1298 double height = gtk_paper_size_get_height (paper, GTK_UNIT_MM);
1299 return g_strdup_printf ("custom_Gnm-%.0fx%.0fmm_%.0fx%.0fmm",
1300 width, height, width, height);
1302 return g_strdup (name);
1305 char *
1306 print_info_get_paper (GnmPrintInformation *pi)
1308 g_return_val_if_fail (pi != NULL, g_strdup (GTK_PAPER_NAME_A4));
1309 gnm_print_info_load_defaults (pi);
1311 return page_setup_get_paper (pi->page_setup);
1314 GtkPaperSize *
1315 print_info_get_paper_size (GnmPrintInformation *pi)
1317 g_return_val_if_fail (pi != NULL, NULL);
1318 gnm_print_info_load_defaults (pi);
1320 return gtk_page_setup_get_paper_size (pi->page_setup);
1324 char const*
1325 print_info_get_paper_display_name (GnmPrintInformation *pi)
1327 GtkPaperSize* paper;
1329 g_return_val_if_fail (pi != NULL, "ERROR: No printinformation specified");
1330 gnm_print_info_load_defaults (pi);
1331 g_return_val_if_fail (pi->page_setup != NULL, "ERROR: No pagesetup loaded");
1333 paper = gtk_page_setup_get_paper_size (pi->page_setup);
1334 return gtk_paper_size_get_display_name (paper);
1337 double
1338 print_info_get_paper_width (GnmPrintInformation *pi, GtkUnit unit)
1340 g_return_val_if_fail (pi != NULL, 0.);
1341 gnm_print_info_load_defaults (pi);
1343 return gtk_page_setup_get_paper_width (pi->page_setup, unit);
1346 double
1347 print_info_get_paper_height (GnmPrintInformation *pi, GtkUnit unit)
1349 g_return_val_if_fail (pi != NULL, 0);
1350 gnm_print_info_load_defaults (pi);
1352 return gtk_page_setup_get_paper_height (pi->page_setup, unit);
1356 * gnm_print_info_get_page_setup:
1357 * @pi: #GnmPrintInformation
1359 * Returns: (transfer none): the page setup.
1361 GtkPageSetup*
1362 gnm_print_info_get_page_setup (GnmPrintInformation *pi)
1364 g_return_val_if_fail (pi != NULL, NULL);
1365 gnm_print_info_load_defaults (pi);
1367 return pi->page_setup;
1371 * gnm_print_info_set_page_setup :
1372 * @pi: #GnmPrintInformation
1373 * @page_setup: #GtkPageSetup
1375 * Absorb a ref to @page_setup.
1377 * WHY WHY WHY
1378 * 1) The life cycle in here is a tad odd, the load_defaults does nothing for the
1379 * case of an existing page_setup, and seems like it should be ignored for the
1380 * case of a new one.
1382 * 2) Why not copy the page_setup in here and make the arg const ?
1384 void
1385 gnm_print_info_set_page_setup (GnmPrintInformation *pi, GtkPageSetup *page_setup)
1387 g_return_if_fail (pi != NULL);
1389 gnm_print_info_load_defaults (pi);
1391 if (pi->page_setup) {
1392 double header, footer, left, right;
1393 print_info_get_margins (pi,
1394 &header, &footer, &left, &right, NULL, NULL);
1395 g_object_unref (pi->page_setup);
1396 pi->page_setup = page_setup;
1397 print_info_set_margins (pi, header, footer, left, right);
1398 } else
1399 pi->page_setup = page_setup;
1402 GtkPageOrientation
1403 print_info_get_paper_orientation (GnmPrintInformation *pi)
1405 GtkPageOrientation orientation;
1407 g_return_val_if_fail (pi != NULL, GTK_PAGE_ORIENTATION_PORTRAIT);
1408 gnm_print_info_load_defaults (pi);
1409 g_return_val_if_fail (pi->page_setup != NULL, GTK_PAGE_ORIENTATION_PORTRAIT);
1411 orientation = gtk_page_setup_get_orientation (pi->page_setup);
1412 return orientation;
1415 void
1416 print_info_set_paper_orientation (GnmPrintInformation *pi,
1417 GtkPageOrientation orientation)
1419 g_return_if_fail (pi != NULL);
1420 gnm_print_info_load_defaults (pi);
1422 gtk_page_setup_set_orientation (pi->page_setup, orientation);
1426 * print_info_set_breaks :
1427 * @pi: #GnmPrintInformation
1428 * @breaks: #GnmPageBreaks
1430 * NOTE : Takes ownership of @breaks. DO NOT FREE after calling.
1432 void
1433 print_info_set_breaks (GnmPrintInformation *pi,
1434 GnmPageBreaks *breaks)
1436 GnmPageBreaks **target;
1438 g_return_if_fail (pi != NULL);
1440 target = breaks->is_vert ? &pi->page_breaks.v : &pi->page_breaks.h;
1442 if (*target == breaks) /* just in case something silly happens */
1443 return;
1445 gnm_page_breaks_free (*target);
1446 *target = breaks;
1449 gboolean
1450 print_info_has_manual_breaks (GnmPrintInformation *pi)
1452 if (gnm_page_breaks_get_next_manual_break (pi->page_breaks.v, 0) > -1)
1453 return TRUE;
1454 return (gnm_page_breaks_get_next_manual_break (pi->page_breaks.h, 0) > -1);
1457 /********************************************************************
1458 * Simple data structure to store page breaks defined as a wrapper in case we
1459 * need something more extensive later. */
1462 * gnm_page_breaks_new :
1463 * @is_vert:
1465 * Allocate a collection of page breaks.
1467 GnmPageBreaks *
1468 gnm_page_breaks_new (gboolean is_vert)
1470 GnmPageBreaks *res = g_new (GnmPageBreaks, 1);
1472 res->is_vert = is_vert;
1473 res->details = g_array_new (FALSE, FALSE, sizeof (GnmPageBreak));
1475 return res;
1478 GnmPageBreaks *
1479 gnm_page_breaks_dup (GnmPageBreaks const *src)
1481 if (src != NULL) {
1482 GnmPageBreaks *dst = gnm_page_breaks_new (src->is_vert);
1483 GArray *d_details = dst->details;
1484 GArray const *s_details = src->details;
1485 unsigned i;
1487 /* no need to validate through gnm_page_breaks_append_break, just dup */
1488 for (i = 0; i < s_details->len ; i++)
1489 g_array_append_val (d_details,
1490 g_array_index (s_details, GnmPageBreak, i));
1492 return dst;
1493 } else
1494 return NULL;
1497 void
1498 gnm_page_breaks_free (GnmPageBreaks *breaks)
1500 if (breaks) {
1501 g_array_free (breaks->details, TRUE);
1502 g_free (breaks);
1506 GType
1507 gnm_page_breaks_get_type (void)
1509 static GType t = 0;
1511 if (t == 0) {
1512 t = g_boxed_type_register_static ("GnmPageBreaks",
1513 (GBoxedCopyFunc)gnm_page_breaks_dup,
1514 (GBoxedFreeFunc)gnm_page_breaks_free);
1516 return t;
1519 GnmPageBreaks *
1520 gnm_page_breaks_dup_non_auto_breaks (GnmPageBreaks const *src)
1522 if (src != NULL) {
1523 GnmPageBreaks *dst = gnm_page_breaks_new (src->is_vert);
1524 GArray *d_details = dst->details;
1525 GArray const *s_details = src->details;
1526 GnmPageBreak *pbreak;
1527 unsigned i;
1529 /* no need to validate through gnm_page_breaks_append_break, just dup */
1530 for (i = 0; i < s_details->len ; i++) {
1531 pbreak = &g_array_index (s_details, GnmPageBreak, i);
1532 if (pbreak->type != GNM_PAGE_BREAK_AUTO)
1533 g_array_append_val (d_details, *pbreak);
1535 return dst;
1536 } else
1537 return NULL;
1540 gboolean
1541 gnm_page_breaks_append_break (GnmPageBreaks *breaks,
1542 int pos,
1543 GnmPageBreakType type)
1545 GnmPageBreak const *prev;
1546 GnmPageBreak info;
1548 g_return_val_if_fail (breaks != NULL, FALSE);
1550 if (type == GNM_PAGE_BREAK_NONE)
1551 return TRUE;
1553 /* Do some simple validation */
1554 if (pos < 0)
1555 return FALSE;
1556 if (breaks->details->len > 0) {
1557 prev = &g_array_index (breaks->details, GnmPageBreak,
1558 breaks->details->len-1);
1559 if (prev->pos >= pos)
1560 return FALSE;
1563 info.pos = pos;
1564 info.type = type;
1565 g_array_append_val (breaks->details, info);
1567 return TRUE;
1570 GnmPageBreakType
1571 gnm_page_breaks_get_break (GnmPageBreaks *breaks,
1572 int pos)
1574 int i;
1576 if (breaks == NULL)
1577 return GNM_PAGE_BREAK_NONE;
1579 for (i = breaks->details->len - 1; i >= 0; i--) {
1580 GnmPageBreak *pbreak;
1581 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1582 if (pbreak->pos < pos)
1583 return GNM_PAGE_BREAK_NONE;
1584 if (pbreak->pos == pos)
1585 return (pbreak->type);
1587 return GNM_PAGE_BREAK_NONE;
1591 gnm_page_breaks_get_next_manual_break (GnmPageBreaks *breaks,
1592 int pos)
1594 guint i;
1596 if (breaks == NULL)
1597 return -1;
1599 for (i = 0; i < breaks->details->len; i++) {
1600 GnmPageBreak const *pbreak;
1601 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1602 if (pbreak->pos > pos
1603 && pbreak->type != GNM_PAGE_BREAK_AUTO)
1604 return pbreak->pos;
1606 return -1;
1610 gnm_page_breaks_get_next_break (GnmPageBreaks *breaks,
1611 int pos)
1613 guint i;
1615 if (breaks == NULL)
1616 return -1;
1618 for (i = 0; i < breaks->details->len; i++) {
1619 GnmPageBreak const *pbreak;
1620 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1621 if (pbreak->pos > pos)
1622 return pbreak->pos;
1624 return -1;
1627 gboolean
1628 gnm_page_breaks_set_break (GnmPageBreaks *breaks,
1629 int pos,
1630 GnmPageBreakType type)
1632 GnmPageBreak *pbreak;
1633 GnmPageBreak info;
1634 guint i;
1635 int before = -1;
1637 g_return_val_if_fail (breaks != NULL, FALSE);
1639 /* Do some simple validation */
1640 if (pos < 0)
1641 return FALSE;
1643 if (breaks->details->len == 0 && type != GNM_PAGE_BREAK_NONE)
1644 return gnm_page_breaks_append_break (breaks, pos, type);
1646 for (i = 0; i < breaks->details->len; i++) {
1647 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1648 if (pbreak->pos == pos) {
1649 if (type == GNM_PAGE_BREAK_NONE) {
1650 g_array_remove_index (breaks->details, i);
1651 } else {
1652 pbreak->type = type;
1654 return TRUE;
1655 } else if (pbreak->pos < pos)
1656 before = (int) i;
1659 if (type == GNM_PAGE_BREAK_NONE)
1660 return TRUE;
1662 info.pos = pos;
1663 info.type = type;
1664 if ((before + 1) > (int) breaks->details->len)
1665 g_array_append_val (breaks->details, info);
1666 else
1667 g_array_insert_val (breaks->details, (before + 1), info);
1669 return TRUE;
1673 * gnm_page_break_type_from_str:
1674 * @str:
1677 GnmPageBreakType
1678 gnm_page_break_type_from_str (char const *str)
1680 if (0 == g_ascii_strcasecmp (str, "manual"))
1681 return GNM_PAGE_BREAK_MANUAL;
1682 if (0 == g_ascii_strcasecmp (str, "auto"))
1683 return GNM_PAGE_BREAK_AUTO;
1684 if (0 == g_ascii_strcasecmp (str, "data-slice"))
1685 return GNM_PAGE_BREAK_DATA_SLICE;
1686 if (0 == g_ascii_strcasecmp (str, "none"))
1687 return GNM_PAGE_BREAK_NONE;
1688 return GNM_PAGE_BREAK_NONE;
1693 * gnm_page_breaks_clean:
1695 * Remove all auto page breaks
1698 void
1699 gnm_page_breaks_clean (GnmPageBreaks *breaks)
1701 guint i;
1703 if (breaks == NULL)
1704 return;
1706 for (i = 0; i < breaks->details->len; i++) {
1707 GnmPageBreak *pbreak = &g_array_index (breaks->details,
1708 GnmPageBreak, i);
1709 if (pbreak->type == GNM_PAGE_BREAK_AUTO) {
1710 g_array_remove_index (breaks->details, i);
1711 i--;
1716 void
1717 print_info_set_printtofile_uri (GnmPrintInformation *pi,
1718 gchar const *uri)
1720 g_free (pi->printtofile_uri);
1721 pi->printtofile_uri = g_strdup (uri);
1724 void
1725 print_info_set_printtofile_from_settings (GnmPrintInformation *pi,
1726 GtkPrintSettings* settings,
1727 gchar const *default_uri)
1729 char const *uri = gtk_print_settings_get
1730 (settings,
1731 GTK_PRINT_SETTINGS_OUTPUT_URI);
1732 if (strcmp (uri, default_uri) == 0)
1733 print_info_set_printtofile_uri (pi, NULL);
1734 else
1735 print_info_set_printtofile_uri (pi, uri);
1738 void
1739 print_info_set_from_settings (GnmPrintInformation *pi,
1740 GtkPrintSettings* settings)
1742 pi->print_range = gtk_print_settings_get_int_with_default
1743 (settings,
1744 GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY,
1745 GNM_PRINT_ACTIVE_SHEET);
1748 PrintRange
1749 print_info_get_printrange (GnmPrintInformation *pi)
1751 gnm_print_info_load_defaults (pi);
1752 return pi->print_range;
1755 void
1756 print_info_set_printrange (GnmPrintInformation *pi, PrintRange pr)
1758 if (pr >= GNM_PRINT_ACTIVE_SHEET
1759 && pr <= GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA)
1760 pi->print_range = pr;
1761 else
1762 pi->print_range = GNM_PRINT_ACTIVE_SHEET;
1766 char const *
1767 print_info_get_printtofile_uri (GnmPrintInformation *pi)
1769 gnm_print_info_load_defaults (pi);
1770 return pi->printtofile_uri;
1774 gboolean
1775 print_load_repeat_range (char const *str, GnmRange *r, Sheet const *sheet)
1777 GnmParsePos pp;
1778 GnmRangeRef res;
1780 if (str == NULL || *str == '\0')
1781 return FALSE;
1783 if (str != rangeref_parse (&res, str,
1784 parse_pos_init_sheet (&pp, sheet),
1785 gnm_conventions_default)) {
1786 Sheet *start_sheet = (Sheet *)sheet;
1787 Sheet *end_sheet = (Sheet *)sheet;
1788 gnm_rangeref_normalize_pp (&res, &pp,
1789 &start_sheet, &end_sheet,
1791 return TRUE;
1792 } else
1793 return FALSE;