Update Spanish translation
[gnumeric.git] / src / print-info.c
blob8e322956a522d81fabdac60fd806ed47b539524e
2 /*
3 * print-info.c: Print information management. This keeps
4 * track of what the print parameters for a sheet are.
6 * Authors:
7 * Andreas J. Guelzow (aguelzow@taliesin.ca)
8 * Jody Goldberg (jody@gnome.org)
9 * Miguel de Icaza (miguel@gnu.org)
10 * Copyright (C) 2007-2009 Morten Welinder (terra@gnome.org)
12 #include <gnumeric-config.h>
13 #include <gnumeric.h>
14 #include <print-info.h>
16 #include <print.h>
17 #include <gutils.h>
18 #include <ranges.h>
19 #include <gnm-format.h>
20 #include <func.h>
21 #include <sheet.h>
22 #include <value.h>
23 #include <workbook.h>
24 #include <workbook-view.h>
25 #include <gnumeric-conf.h>
26 #include <parse-util.h>
27 #include <sheet-object.h>
28 #include <sheet-object-graph.h>
30 #include <goffice/goffice.h>
31 #include <gsf/gsf-doc-meta-data.h>
32 #include <gsf/gsf-meta-names.h>
34 #include <glib/gi18n-lib.h>
35 #include <string.h>
36 #include <locale.h>
37 #include <time.h>
39 #define PDF_SAVER_ID "Gnumeric_pdf:pdf_assistant"
41 #define MAX_SAVED_CUSTOM_HF_FORMATS 9
43 GList *gnm_print_hf_formats = NULL;
44 static gint hf_formats_base_num = 0;
46 GType
47 gnm_print_comment_placement_get_type (void)
49 static GType etype = 0;
50 if (etype == 0) {
51 static GEnumValue const values[] = {
52 { GNM_PRINT_COMMENTS_NONE,
53 "GNM_PRINT_COMMENTS_NONE",
54 "none"},
55 { GNM_PRINT_COMMENTS_IN_PLACE,
56 "GNM_PRINT_COMMENTS_IN_PLACE",
57 "in-place"},
58 { GNM_PRINT_COMMENTS_AT_END,
59 "GNM_PRINT_COMMENTS_AT_END",
60 "at-end"},
61 { 0, NULL, NULL }
63 etype = g_enum_register_static ("GnmPrintCommentPlacementType",
64 values);
66 return etype;
69 GType
70 gnm_print_errors_get_type (void)
72 static GType etype = 0;
73 if (etype == 0) {
74 static GEnumValue const values[] = {
75 { GNM_PRINT_ERRORS_AS_DISPLAYED,
76 "GNM_PRINT_ERRORS_AS_DISPLAYED", "as-displayed"},
77 { GNM_PRINT_ERRORS_AS_BLANK,
78 "GNM_PRINT_ERRORS_AS_BLANK", "as-blank"},
79 { GNM_PRINT_ERRORS_AS_DASHES,
80 "GNM_PRINT_ERRORS_AS_DASHES", "as-dashes"},
81 { GNM_PRINT_ERRORS_AS_NA,
82 "GNM_PRINT_ERRORS_AS_NA", "as-na"},
83 { 0, NULL, NULL }
85 etype = g_enum_register_static ("GnmPrintErrorsType",
86 values);
88 return etype;
92 GnmPrintHF *
93 gnm_print_hf_new (char const *left_side_format,
94 char const *middle_format,
95 char const *right_side_format)
97 GnmPrintHF *hf = g_new0 (GnmPrintHF, 1);
98 hf->left_format = g_strdup (left_side_format ?
99 left_side_format : "");
100 hf->middle_format = g_strdup (middle_format ?
101 middle_format : "");
102 hf->right_format = g_strdup (right_side_format ?
103 right_side_format : "");
104 return hf;
107 gboolean
108 gnm_print_hf_same (GnmPrintHF const *a, GnmPrintHF const *b)
110 if (a->left_format != b->left_format) {
111 if (a->left_format == NULL ||
112 b->left_format == NULL ||
113 strcmp (b->left_format, a->left_format))
114 return FALSE;
116 if (a->middle_format != b->middle_format) {
117 if (a->middle_format == NULL ||
118 b->middle_format == NULL ||
119 strcmp (b->middle_format, a->middle_format))
120 return FALSE;
122 if (a->right_format != b->right_format) {
123 if (a->right_format == NULL ||
124 b->right_format == NULL ||
125 strcmp (b->right_format, a->right_format))
126 return FALSE;
129 return TRUE;
132 GnmPrintHF *
133 gnm_print_hf_register (GnmPrintHF *hf)
135 GList *l;
136 GnmPrintHF *newi;
138 g_return_val_if_fail (hf != NULL, NULL);
140 for (l = gnm_print_hf_formats; l; l = l->next)
141 if (gnm_print_hf_same (hf, l->data))
142 return l->data;
144 newi = gnm_print_hf_copy (hf);
145 gnm_print_hf_formats = g_list_append (gnm_print_hf_formats, newi);
147 return newi;
151 GnmPrintHF *
152 gnm_print_hf_copy (GnmPrintHF const *source)
154 GnmPrintHF *res;
156 res = g_new0 (GnmPrintHF, 1);
157 res->left_format = g_strdup (source->left_format);
158 res->middle_format = g_strdup (source->middle_format);
159 res->right_format = g_strdup (source->right_format);
161 return res;
164 void
165 gnm_print_hf_free (GnmPrintHF *print_hf)
167 if (print_hf == NULL)
168 return;
170 g_free (print_hf->left_format);
171 g_free (print_hf->middle_format);
172 g_free (print_hf->right_format);
173 g_free (print_hf);
176 GType
177 gnm_print_hf_get_type (void)
179 static GType t = 0;
181 if (t == 0) {
182 t = g_boxed_type_register_static ("GnmPrintHF",
183 (GBoxedCopyFunc)gnm_print_hf_copy,
184 (GBoxedFreeFunc)gnm_print_hf_free);
186 return t;
189 void
190 gnm_print_info_free (GnmPrintInformation *pi)
192 g_return_if_fail (pi != NULL);
194 if (NULL != pi->page_breaks.v)
195 gnm_page_breaks_free (pi->page_breaks.v);
196 if (NULL != pi->page_breaks.h)
197 gnm_page_breaks_free (pi->page_breaks.h);
199 g_free (pi->repeat_top);
200 g_free (pi->repeat_left);
201 gnm_print_hf_free (pi->header);
202 gnm_print_hf_free (pi->footer);
204 g_free (pi->printtofile_uri);
205 if (pi->page_setup)
206 g_object_unref (pi->page_setup);
208 g_free (pi);
211 GType
212 gnm_print_information_get_type (void)
214 static GType t = 0;
216 if (t == 0) {
217 t = g_boxed_type_register_static ("GnmPrintInformation",
218 (GBoxedCopyFunc)gnm_print_info_dup,
219 (GBoxedFreeFunc)gnm_print_info_free);
221 return t;
224 static void
225 load_formats (void)
227 static struct {
228 char const *left_format;
229 char const *middle_format;
230 char const *right_format;
231 } const predefined_formats [] = {
232 { "", "", "" },
233 { "", N_("Page &[PAGE]"), "" },
234 { "", N_("Page &[PAGE] of &[PAGES]"), "" },
235 { "", N_("&[TAB]"), "" },
236 { N_("Page &[PAGE]"), N_("&[TAB]"), "" },
237 { N_("Page &[PAGE]"), N_("&[TAB]"), N_("&[DATE]") },
238 { "", N_("&[DATE]"), "" },
239 { N_("&[TAB]"), N_("Page &[PAGE] of &[PAGES]"), N_("&[DATE]") },
240 { NULL, NULL, NULL }
243 /* Fetch header/footer formats */
245 int i;
247 for (i = 0; predefined_formats [i].left_format; i++) {
248 GnmPrintHF *format;
250 format = gnm_print_hf_new (
251 predefined_formats [i].left_format[0]?
252 _(predefined_formats [i].left_format):"",
253 predefined_formats [i].middle_format[0]?
254 _(predefined_formats [i].middle_format):"",
255 predefined_formats [i].right_format[0]?
256 _(predefined_formats [i].right_format):"");
258 gnm_print_hf_formats = g_list_prepend (gnm_print_hf_formats, format);
259 hf_formats_base_num++;
263 /* Now append the custom formats */
265 GSList const *left;
266 GSList const *middle;
267 GSList const *right;
269 left = gnm_conf_get_printsetup_hf_left ();
270 middle = gnm_conf_get_printsetup_hf_middle ();
271 right = gnm_conf_get_printsetup_hf_right ();
273 while (left != NULL && middle != NULL && right != NULL)
275 GnmPrintHF *format;
277 format = gnm_print_hf_new
278 (left->data ? left->data : "",
279 middle->data ? middle->data : "",
280 right->data ? right->data : "");
282 gnm_print_hf_formats = g_list_prepend (gnm_print_hf_formats, format);
284 left = left->next;
285 middle = middle->next;
286 right = right->next;
290 gnm_print_hf_formats = g_list_reverse (gnm_print_hf_formats);
294 * gnm_print_info_load_defaults:
295 * @pi: #GnmPrintInformation
297 * Returns: (skip) (transfer none): @pi
299 * NOTE: This reads from a globally stored configuration. If a
300 * configuration is stored along with a sheet then that will
301 * override these global defaults.
303 GnmPrintInformation *
304 gnm_print_info_load_defaults (GnmPrintInformation *res)
306 GSList *list;
307 GtkPrintSettings *settings;
309 if (res->page_setup != NULL)
310 return res;
312 res->page_setup = gnm_conf_get_page_setup ();
314 res->scaling.type = gnm_conf_get_printsetup_scale_percentage ()
315 ? PRINT_SCALE_PERCENTAGE
316 : PRINT_SCALE_FIT_PAGES;
317 res->scaling.percentage.x = res->scaling.percentage.y
318 = gnm_conf_get_printsetup_scale_percentage_value ();
319 res->scaling.dim.cols = gnm_conf_get_printsetup_scale_width ();
320 res->scaling.dim.rows = gnm_conf_get_printsetup_scale_height ();
321 res->edge_to_below_header = gnm_conf_get_printsetup_margin_top ();
322 res->edge_to_above_footer = gnm_conf_get_printsetup_margin_bottom ();
323 res->desired_display.top = gnm_conf_get_printsetup_preferred_unit ();
324 res->desired_display.bottom = gnm_conf_get_printsetup_preferred_unit ();
325 res->desired_display.left = gnm_conf_get_printsetup_preferred_unit ();
326 res->desired_display.right = gnm_conf_get_printsetup_preferred_unit ();
327 res->desired_display.footer = gnm_conf_get_printsetup_preferred_unit ();
328 res->desired_display.header = gnm_conf_get_printsetup_preferred_unit ();
329 res->repeat_top = g_strdup (gnm_conf_get_printsetup_repeat_top ());
330 res->repeat_left = g_strdup (gnm_conf_get_printsetup_repeat_left ());
331 res->center_vertically = gnm_conf_get_printsetup_center_vertically ();
332 res->center_horizontally = gnm_conf_get_printsetup_center_horizontally ();
333 res->print_grid_lines = gnm_conf_get_printsetup_print_grid_lines ();
334 res->print_titles = gnm_conf_get_printsetup_print_titles ();
335 res->print_black_and_white = gnm_conf_get_printsetup_print_black_n_white ();
336 res->print_even_if_only_styles = gnm_conf_get_printsetup_print_even_if_only_styles ();
337 res->print_across_then_down = gnm_conf_get_printsetup_across_then_down ();
339 list = gnm_conf_get_printsetup_header ();
340 res->header = list ?
341 gnm_print_hf_new (g_slist_nth_data (list, 0),
342 g_slist_nth_data (list, 1),
343 g_slist_nth_data (list, 2)) :
344 gnm_print_hf_new ("", _("&[TAB]"), "");
346 list = gnm_conf_get_printsetup_footer ();
347 res->footer = list ?
348 gnm_print_hf_new (g_slist_nth_data (list, 0),
349 g_slist_nth_data (list, 1),
350 g_slist_nth_data (list, 2)) :
351 gnm_print_hf_new ("", _("Page &[PAGE]"), "");
353 settings = gnm_conf_get_print_settings ();
354 print_info_set_from_settings (res, settings);
355 g_object_unref (settings);
357 return res;
361 * gnm_print_information_new:
363 * Returns a newly allocated GnmPrintInformation buffer
366 GnmPrintInformation *
367 gnm_print_information_new (gboolean load_defaults)
369 GnmPrintInformation *res = g_new0 (GnmPrintInformation, 1);
371 res->print_as_draft = FALSE;
372 res->comment_placement = GNM_PRINT_COMMENTS_IN_PLACE;
373 res->error_display = GNM_PRINT_ERRORS_AS_DISPLAYED;
375 res->start_page = -1;
376 res->n_copies = 0;
377 res->do_not_print = FALSE;
379 res->page_setup = NULL;
380 res->page_breaks.v = NULL;
381 res->page_breaks.h = NULL;
383 res->printtofile_uri = NULL;
384 res->print_range = GNM_PRINT_ACTIVE_SHEET;
386 if (load_defaults)
387 return gnm_print_info_load_defaults (res);
388 else
389 return res;
393 * This can get out of hand, we should limit the number of stored
394 * formats.
396 static void
397 save_formats (void)
399 int base = hf_formats_base_num;
400 GList *l;
401 GSList *left = NULL;
402 GSList *middle = NULL;
403 GSList *right = NULL;
404 int start;
406 start = g_list_length (gnm_print_hf_formats) - MAX_SAVED_CUSTOM_HF_FORMATS;
407 if (start > base)
408 base = start;
410 for (l = gnm_print_hf_formats; l; l = l->next) {
411 GnmPrintHF *hf = l->data;
413 if (base-- > 0)
414 continue;
416 GO_SLIST_PREPEND (left, g_strdup(hf->left_format));
417 GO_SLIST_PREPEND (middle, g_strdup(hf->middle_format));
418 GO_SLIST_PREPEND (right, g_strdup(hf->right_format));
420 GO_SLIST_REVERSE(left);
421 gnm_conf_set_printsetup_hf_left (left);
422 g_slist_free_full (left, g_free);
424 GO_SLIST_REVERSE(middle);
425 gnm_conf_set_printsetup_hf_middle (middle);
426 g_slist_free_full (middle, g_free);
428 GO_SLIST_REVERSE(right);
429 gnm_conf_set_printsetup_hf_right (right);
430 g_slist_free_full (right, g_free);
433 static void
434 destroy_formats (void)
436 g_list_free_full (gnm_print_hf_formats, (GDestroyNotify)gnm_print_hf_free);
437 gnm_print_hf_formats = NULL;
440 static GSList *
441 make_triple (const GnmPrintHF *hf)
443 GSList *l = NULL;
445 GO_SLIST_PREPEND (l, hf->left_format ? hf->left_format : NULL);
446 GO_SLIST_PREPEND (l, hf->middle_format ? hf->middle_format : NULL);
447 GO_SLIST_PREPEND (l, hf->right_format ? hf->right_format : NULL);
449 return l;
452 void
453 gnm_print_info_save (GnmPrintInformation *pi)
455 GSList *l;
457 gnm_conf_set_printsetup_scale_percentage (pi->scaling.type == PRINT_SCALE_PERCENTAGE);
458 gnm_conf_set_printsetup_scale_percentage_value (pi->scaling.percentage.x);
459 gnm_conf_set_printsetup_scale_width (pi->scaling.dim.cols);
460 gnm_conf_set_printsetup_scale_height (pi->scaling.dim.rows);
462 gnm_conf_set_printsetup_margin_top (pi->edge_to_below_header);
463 gnm_conf_set_printsetup_margin_bottom (pi->edge_to_above_footer);
464 gnm_conf_set_printsetup_preferred_unit (pi->desired_display.top);
466 gnm_conf_set_printsetup_center_horizontally (pi->center_horizontally);
467 gnm_conf_set_printsetup_center_vertically (pi->center_vertically);
468 gnm_conf_set_printsetup_print_grid_lines (pi->print_grid_lines);
469 gnm_conf_set_printsetup_print_titles (pi->print_titles);
470 gnm_conf_set_printsetup_print_even_if_only_styles (pi->print_even_if_only_styles);
471 gnm_conf_set_printsetup_print_black_n_white (pi->print_black_and_white);
472 gnm_conf_set_printsetup_across_then_down (pi->print_across_then_down);
474 gnm_conf_set_printsetup_repeat_top (pi->repeat_top);
475 gnm_conf_set_printsetup_repeat_left (pi->repeat_left);
477 save_formats ();
479 l = make_triple (pi->header);
480 gnm_conf_set_printsetup_header (l);
481 g_slist_free (l);
483 l = make_triple (pi->footer);
484 gnm_conf_set_printsetup_footer (l);
485 g_slist_free (l);
487 gnm_conf_set_page_setup (pi->page_setup);
490 GtkUnit
491 unit_name_to_unit (char const *name)
493 if (!g_ascii_strcasecmp (name, "cm"))
494 return GTK_UNIT_MM;
495 if (!g_ascii_strcasecmp (name, "mm"))
496 return GTK_UNIT_MM;
497 if (!g_ascii_strcasecmp (name, "centimeter"))
498 return GTK_UNIT_MM;
499 if (!g_ascii_strcasecmp (name, "millimeter"))
500 return GTK_UNIT_MM;
501 if (!g_ascii_strcasecmp (name, "inch"))
502 return GTK_UNIT_INCH;
503 if (!g_ascii_strcasecmp (name, "in"))
504 return GTK_UNIT_INCH;
505 if (!g_ascii_strcasecmp (name, "inches"))
506 return GTK_UNIT_INCH;
508 return GTK_UNIT_POINTS;
511 char const *
512 unit_to_unit_name (GtkUnit unit)
514 switch (unit) {
515 case GTK_UNIT_MM:
516 return "mm";
517 case GTK_UNIT_INCH:
518 return "inch";
519 default:
520 return "points";
525 static void
526 render_cell (GString *target, GnmPrintHFRenderInfo *info, char const *args)
528 gboolean use_repeating = FALSE;
530 if (args && ((use_repeating = g_str_has_prefix (args, "rep|"))))
531 args += 4;
533 if (info->sheet) {
534 GnmRangeRef ref;
535 GnmValue const *val;
536 char const *tmp;
537 GnmParsePos ppos;
539 parse_pos_init (&ppos, info->sheet->workbook, (Sheet *)info->sheet, 0, 0);
540 tmp = rangeref_parse
541 (&ref, args, &ppos, sheet_get_conventions (info->sheet));
542 if (tmp == NULL || tmp == args) {
543 gnm_cellref_init (&ref.a, (Sheet *)(info->sheet), 0, 0, FALSE);
546 if (ref.a.row_relative)
547 ref.a.row += (use_repeating ?
548 info->top_repeating.row : info->page_area.start.row);
549 if (ref.a.col_relative)
550 ref.a.col += (use_repeating ?
551 info->top_repeating.col : info->page_area.start.col);
553 val = sheet_cell_get_value
554 (ref.a.sheet ? ref.a.sheet : (Sheet *)(info->sheet),
555 ref.a.col, ref.a.row);
556 if (val != NULL) {
557 char const *value;
558 value = value_peek_string (val);
559 g_string_append (target, value);
562 else {
563 if (use_repeating)
564 g_string_append (target, "[");
565 g_string_append (target, args);
566 if (use_repeating)
567 g_string_append (target, "]");
571 static void
572 render_tab (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
574 if (info->sheet)
575 g_string_append (target, info->sheet->name_unquoted);
576 else
577 g_string_append (target, _("Sheet"));
580 static void
581 render_page (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
583 g_string_append_printf (target, "%d", info->page);
586 static void
587 render_pages (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
589 g_string_append_printf (target, "%d", info->pages);
592 static void
593 render_timestamp_with_format (GString *target, char const *number_format, GnmPrintHFRenderInfo *info)
595 GOFormat *format;
597 /* TODO : Check this assumption. Is it a localized format? */
598 format = go_format_new_from_XL (number_format);
599 format_value_gstring (target, format, info->date_time,
600 -1, info->date_conv);
601 go_format_unref (format);
604 static void
605 render_date (GString *target, GnmPrintHFRenderInfo *info, char const *args)
607 char const *date_format;
609 if (args)
610 date_format = args;
611 else
612 date_format = "dd-mmm-yyyy";
614 render_timestamp_with_format (target, date_format, info);
617 static void
618 render_time (GString *target, GnmPrintHFRenderInfo *info, char const *args)
620 char const *time_format;
622 if (args)
623 time_format = args;
624 else
625 time_format = "hh:mm";
626 render_timestamp_with_format (target, time_format, info);
629 static void
630 render_file (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
632 if (info->sheet != NULL && info->sheet->workbook != NULL) {
633 char *name = go_basename_from_uri (
634 go_doc_get_uri (GO_DOC (info->sheet->workbook)));
635 g_string_append (target, name);
636 g_free (name);
637 } else
638 g_string_append (target, _("File Name"));
641 static void
642 render_path (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
644 if (info->sheet != NULL && info->sheet->workbook != NULL) {
645 char *path = go_dirname_from_uri (
646 go_doc_get_uri (GO_DOC (info->sheet->workbook)), TRUE);
647 g_string_append (target, path);
648 g_free (path);
649 } else
650 g_string_append (target, _("Path "));
653 static void
654 render_title (GString *target, GnmPrintHFRenderInfo *info, G_GNUC_UNUSED char const *args)
656 if (info->sheet != NULL && info->sheet->workbook != NULL) {
657 GsfDocProp *prop;
658 prop = gsf_doc_meta_data_lookup
659 (go_doc_get_meta_data (GO_DOC (info->sheet->workbook)), GSF_META_NAME_TITLE);
660 if (prop != NULL) {
661 GValue *prop_value = (GValue *) gsf_doc_prop_get_val (prop);
662 if (prop_value != NULL)
663 g_string_append (target, g_value_get_string (prop_value));
665 } else
666 g_string_append (target, _("Title"));
669 static struct {
670 char const *name;
671 void (*render)(GString *target, GnmPrintHFRenderInfo *info, char const *args);
672 char *name_trans;
673 } render_ops [] = {
674 { N_("TAB"), render_tab , NULL},
675 { N_("PAGE"), render_page , NULL},
676 { N_("PAGES"), render_pages , NULL},
677 { N_("DATE"), render_date , NULL},
678 { N_("TIME"), render_time , NULL},
679 { N_("FILE"), render_file , NULL},
680 { N_("PATH"), render_path , NULL},
681 { N_("CELL"), render_cell , NULL},
682 { N_("TITLE"), render_title , NULL},
683 { NULL , NULL, NULL},
686 * Renders an opcode. The opcodes can take an argument by adding trailing ':'
687 * to the opcode and then a number format code
689 static void
690 render_opcode (GString *target, char /* non-const */ *opcode,
691 GnmPrintHFRenderInfo *info,
692 G_GNUC_UNUSED GnmPrintHFRenderType render_type)
694 char *args;
695 char *opcode_trans;
696 int i;
698 args = g_utf8_strchr (opcode, -1, ':');
699 if (args) {
700 *args = 0;
701 args++;
703 opcode_trans = g_utf8_casefold (opcode, -1);
705 for (i = 0; render_ops [i].name; i++) {
706 if (render_ops [i].name_trans == NULL) {
707 render_ops [i].name_trans = g_utf8_casefold (_(render_ops [i].name), -1);
710 if ((g_ascii_strcasecmp (render_ops [i].name, opcode) == 0) ||
711 (g_utf8_collate (render_ops [i].name_trans, opcode_trans) == 0)) {
712 (*render_ops [i].render)(target, info, args);
715 g_free (opcode_trans);
718 #if 0
719 3.3.1.36 evenHeader (Even Page Header)
721 &P Current page number
722 &N Page count
723 &D Current date
724 &T Current time
725 &A Sheet name (BIFF5-BIFF8)
726 &F File name without path
727 &Z File path without file name (BIFF8X)
728 &G Picture (BIFF8X)
729 &B Bold on/off (BIFF2-BIFF4)
730 &I Italic on/off (BIFF2-BIFF4)
731 &U Underlining on/off
732 &E Double underlining on/off (BIFF5-BIFF8)
733 &S Strikeout on/off
734 &X Superscript on/off (BIFF5-BIFF8)
735 &Y Subscript on/off (BIFF5-BIFF8)
736 &"<fontname>" Set new font <fontname>
737 &"<fontname>,<fontstyle>" Set new font with specified style <fontstyle>. The style <fontstyle> is in most cases
738 one of "Regular", "Bold", "Italic", or "Bold Italic". But this setting is dependent on the
739 used font, it may differ (localised style names, or "Standard", "Oblique", ...). (BIFF5-
740 BIFF8)
741 &<fontheight> Set font height in points (<fontheight> is a decimal value). If this command is followed
742 by a plain number to be printed in the header, it will be separated from the font height
743 with a space character.
744 #endif
746 char *
747 gnm_print_hf_format_render (char const *format, GnmPrintHFRenderInfo *info, GnmPrintHFRenderType render_type)
749 GString *result;
750 char const *p;
752 if (!format)
753 return NULL;
755 result = g_string_new (NULL);
756 for (p = format; *p; p++) {
757 if (*p == '&' && p[1] == '[') {
758 char const *start;
760 p += 2;
761 start = p;
762 while (*p && (*p != ']'))
763 p++;
765 if (*p == ']') {
766 char *operation = g_strndup (start, p - start);
767 render_opcode (result, operation, info, render_type);
768 g_free (operation);
769 } else
770 break;
771 } else
772 g_string_append_c (result, *p);
775 return g_string_free (result, FALSE);
778 GnmPrintHFRenderInfo *
779 gnm_print_hf_render_info_new (void)
781 GnmPrintHFRenderInfo *hfi;
783 hfi = g_new0 (GnmPrintHFRenderInfo, 1);
784 hfi->date_conv = go_date_conv_from_str ("Lotus:1900");
785 hfi->date_time = value_new_float
786 (go_date_timet_to_serial_raw (time (NULL), hfi->date_conv));
787 /* It doesn't appear like the end is accessed. */
788 range_init (&hfi->page_area, 0, 0, G_MAXINT / 2, G_MAXINT / 2);
789 hfi->top_repeating.col = 0;
790 hfi->top_repeating.row = 0;
792 return hfi;
795 void
796 gnm_print_hf_render_info_destroy (GnmPrintHFRenderInfo *hfi)
798 g_return_if_fail (hfi != NULL);
800 value_release (hfi->date_time);
801 g_free (hfi);
804 static GnmPrintHFRenderInfo *
805 hf_render_info_copy (GnmPrintHFRenderInfo *hfi)
807 GnmPrintHFRenderInfo *res;
808 g_return_val_if_fail (hfi != NULL, NULL);
810 res = g_new (GnmPrintHFRenderInfo, 1);
811 res->sheet = hfi->sheet;
812 res->page = hfi->page;
813 res->pages = hfi->pages;
814 res->date_time = value_dup (hfi->date_time);
815 res->date_conv = hfi->date_conv;
816 res->page_area = hfi->page_area;
817 res->top_repeating = hfi->top_repeating;
818 return res;
821 GType
822 gnm_print_hf_render_info_get_type (void)
824 static GType t = 0;
826 if (t == 0) {
827 t = g_boxed_type_register_static ("GnmPrintHFRenderInfo",
828 (GBoxedCopyFunc)hf_render_info_copy,
829 (GBoxedFreeFunc)gnm_print_hf_render_info_destroy);
831 return t;
834 static void
835 pdf_write_workbook (G_GNUC_UNUSED GOFileSaver const *fs,
836 G_GNUC_UNUSED GOIOContext *context,
837 WorkbookView const *wbv, GsfOutput *output)
839 Workbook const *wb = wb_view_get_workbook (wbv);
840 GPtrArray *sheets = gnm_file_saver_get_sheets (fs, wbv, FALSE);
842 if (sheets) {
843 int i;
845 for (i = 0; i < workbook_sheet_count (wb); i++) {
846 Sheet *sheet = workbook_sheet_by_index (wb, i);
847 sheet->print_info->do_not_print = TRUE;
849 for (i = 0; i < (int)sheets->len; i++) {
850 Sheet *sheet = g_ptr_array_index (sheets, i);
851 sheet->print_info->do_not_print = FALSE;
855 if (sheets)
856 g_ptr_array_unref (sheets);
858 gnm_print_sheet (NULL, wb_view_cur_sheet (wbv), FALSE,
859 GNM_PRINT_ALL_SHEETS, output);
862 static void
863 pdf_export (GOFileSaver const *fs, GOIOContext *context,
864 GoView const *view, GsfOutput *output)
866 WorkbookView const *wbv = GNM_WORKBOOK_VIEW (view);
867 Workbook const *wb = wb_view_get_workbook (wbv);
868 GPtrArray *objects = g_object_get_data (G_OBJECT (wb), "pdf-objects");
870 if (objects && objects->len > 0) {
871 gpointer object_fit = g_object_get_data (G_OBJECT (wb), "pdf-object-fit");
872 if (object_fit != NULL && GPOINTER_TO_INT (object_fit) == 1
873 && GNM_IS_SO_GRAPH (g_ptr_array_index (objects, 0))) {
874 GError *err = NULL;
875 sheet_object_write_image (g_ptr_array_index (objects, 0), "pdf", 150., output, &err);
876 if (err != NULL) {
877 go_io_error_push (context, go_error_info_new_str (err->message));
878 g_error_free (err);
880 } else
881 gnm_print_so (NULL, objects, output);
882 } else
883 pdf_write_workbook (fs, context, wbv, output);
886 struct cb_set_pdf_option {
887 GOFileSaver *fs;
888 Workbook const *wb;
891 static gboolean
892 cb_set_pdf_option (const char *key, const char *value,
893 GError **err, gpointer user_)
895 struct cb_set_pdf_option *user = user_;
896 Workbook const *wb = user->wb;
898 if (strcmp (key, "object") == 0) {
899 GPtrArray *objects = g_object_get_data (G_OBJECT (wb), "pdf-objects");
900 GSList *sheets = workbook_sheets (wb);
901 gboolean object_seen = FALSE;
903 if (!objects) {
904 objects = g_ptr_array_new ();
905 g_object_set_data_full (G_OBJECT (wb),
906 "pdf-objects", objects,
907 (GDestroyNotify)g_ptr_array_unref);
910 for (; sheets != NULL; sheets = sheets->next) {
911 Sheet *sheet = sheets->data;
912 GSList *sobjects = sheet->sheet_objects;
913 for (; sobjects != NULL; sobjects = sobjects->next) {
914 SheetObject *so = sobjects->data;
915 gchar *name = NULL;
916 g_object_get (so, "name", &name, NULL);
917 if (strcmp (name, value) == 0) {
918 g_ptr_array_add (objects, so);
919 object_seen = TRUE;
923 if (!object_seen) {
924 *err = g_error_new (go_error_invalid (), 0,
925 _("There is no object with name "
926 "\'%s\'"), value);
927 return TRUE;
930 return FALSE;
933 if (strcmp (key, "paper") == 0) {
934 int i;
935 if (strcmp (value, "fit") == 0) {
936 g_object_set_data (G_OBJECT (wb),
937 "pdf-object-fit", GINT_TO_POINTER (1));
938 } else for (i = 0; i < workbook_sheet_count (wb); i++) {
939 Sheet *sheet = workbook_sheet_by_index (wb, i);
940 if (print_info_set_paper (sheet->print_info, value)) {
941 *err = g_error_new (go_error_invalid (), 0,
942 _("Unknown paper size"));
944 return TRUE;
947 return FALSE;
950 return gnm_file_saver_common_export_option (user->fs, wb,
951 key, value, err);
954 static gboolean
955 pdf_set_export_options (GOFileSaver *fs,
956 GODoc *doc,
957 const char *options,
958 GError **err,
959 G_GNUC_UNUSED gpointer user)
961 struct cb_set_pdf_option data;
962 data.fs = fs;
963 data.wb = WORKBOOK (doc);
964 return go_parse_key_value (options, err, cb_set_pdf_option, &data);
968 * print_init: (skip)
970 void
971 print_init (void)
973 /* Install a pdf saver. */
974 GOFileSaver *saver = go_file_saver_new (
975 PDF_SAVER_ID, "pdf",
976 _("PDF export"),
977 GO_FILE_FL_WRITE_ONLY, pdf_export);
978 g_object_set (G_OBJECT (saver), "sheet-selection", TRUE, NULL);
979 g_signal_connect (G_OBJECT (saver), "set-export-options",
980 G_CALLBACK (pdf_set_export_options),
981 NULL);
982 go_file_saver_register (saver);
983 g_object_unref (saver);
985 load_formats ();
989 * print_shutdown: (skip)
991 void
992 print_shutdown (void)
994 go_file_saver_unregister (go_file_saver_for_id (PDF_SAVER_ID));
996 save_formats ();
997 destroy_formats ();
1000 #define COPY(field) dst->field = src->field
1002 GnmPrintInformation *
1003 gnm_print_info_dup (GnmPrintInformation const *src)
1005 GnmPrintInformation *dst = gnm_print_information_new (TRUE);
1007 gnm_print_info_load_defaults ((GnmPrintInformation *)src);
1009 COPY(scaling);
1010 COPY(edge_to_below_header);
1011 COPY(edge_to_above_footer);
1012 COPY(desired_display);
1014 g_free (dst->repeat_top);
1015 dst->repeat_top = g_strdup (src->repeat_top);
1017 g_free (dst->repeat_left);
1018 dst->repeat_left = g_strdup (src->repeat_left);
1020 COPY(print_across_then_down);
1021 COPY(center_vertically);
1022 COPY(center_horizontally);
1023 COPY(print_grid_lines);
1024 COPY(print_titles);
1025 COPY(print_black_and_white);
1026 COPY(print_as_draft);
1027 COPY(print_even_if_only_styles);
1028 COPY(do_not_print);
1029 COPY(comment_placement);
1030 COPY(error_display);
1032 gnm_page_breaks_free (dst->page_breaks.h);
1033 dst->page_breaks.h = gnm_page_breaks_dup (src->page_breaks.h);
1035 gnm_page_breaks_free (dst->page_breaks.v);
1036 dst->page_breaks.v = gnm_page_breaks_dup (src->page_breaks.v);
1038 gnm_print_hf_free (dst->header);
1039 dst->header = gnm_print_hf_copy (src->header);
1041 gnm_print_hf_free (dst->footer);
1042 dst->footer = gnm_print_hf_copy (src->footer);
1044 COPY(start_page);
1045 COPY(n_copies);
1047 g_free (dst->printtofile_uri);
1048 dst->printtofile_uri = g_strdup (src->printtofile_uri);
1050 if (dst->page_setup)
1051 g_object_unref (dst->page_setup);
1052 dst->page_setup = gtk_page_setup_copy (src->page_setup);
1054 return dst;
1057 #undef COPY
1060 * print_info_get_margins:
1061 * @pi: #GnmPrintInformation
1062 * @top: (out) (optional): top margin.
1063 * @bottom: (out) (optional): bottom margin.
1064 * @left: (out) (optional): left margin.
1065 * @right: (out) (optional): right margin.
1066 * @edge_to_below_header: (out) (optional): margin.
1067 * @edge_to_above_footer: (out) (optional): margin.
1069 void
1070 print_info_get_margins (GnmPrintInformation *pi,
1071 double *top, double *bottom,
1072 double *left, double *right,
1073 double *edge_to_below_header,
1074 double *edge_to_above_footer)
1076 g_return_if_fail (pi != NULL);
1077 gnm_print_info_load_defaults (pi);
1078 g_return_if_fail (pi->page_setup != NULL);
1080 if (NULL != top)
1081 *top = gtk_page_setup_get_top_margin (pi->page_setup, GTK_UNIT_POINTS);
1082 if (NULL != bottom)
1083 *bottom = gtk_page_setup_get_bottom_margin (pi->page_setup, GTK_UNIT_POINTS);
1084 if (NULL != left)
1085 *left = gtk_page_setup_get_left_margin (pi->page_setup, GTK_UNIT_POINTS);
1086 if (NULL != right)
1087 *right = gtk_page_setup_get_right_margin (pi->page_setup, GTK_UNIT_POINTS);
1088 if (NULL != edge_to_below_header)
1089 *edge_to_below_header = pi->edge_to_below_header;
1090 if (NULL != edge_to_above_footer)
1091 *edge_to_above_footer = pi->edge_to_above_footer;
1094 void
1095 print_info_set_margin_header (GnmPrintInformation *pi, double header)
1097 g_return_if_fail (pi != NULL);
1098 gnm_print_info_load_defaults (pi);
1099 g_return_if_fail (pi->page_setup != NULL);
1101 gtk_page_setup_set_top_margin (pi->page_setup, header, GTK_UNIT_POINTS);
1104 void
1105 print_info_set_margin_footer (GnmPrintInformation *pi, double footer)
1107 g_return_if_fail (pi != NULL);
1108 gnm_print_info_load_defaults (pi);
1109 g_return_if_fail (pi->page_setup != NULL);
1111 gtk_page_setup_set_bottom_margin (pi->page_setup, footer, GTK_UNIT_POINTS);
1114 void
1115 print_info_set_margin_left (GnmPrintInformation *pi, double left)
1117 g_return_if_fail (pi != NULL);
1118 gnm_print_info_load_defaults (pi);
1119 g_return_if_fail (pi->page_setup != NULL);
1121 gtk_page_setup_set_left_margin (pi->page_setup, left, GTK_UNIT_POINTS);
1124 void
1125 print_info_set_margin_right (GnmPrintInformation *pi, double right)
1127 g_return_if_fail (pi != NULL);
1128 gnm_print_info_load_defaults (pi);
1129 g_return_if_fail (pi->page_setup != NULL);
1131 gtk_page_setup_set_right_margin (pi->page_setup, right, GTK_UNIT_POINTS);
1134 void
1135 print_info_set_edge_to_above_footer (GnmPrintInformation *pi, double e_f)
1137 g_return_if_fail (pi != NULL);
1138 gnm_print_info_load_defaults (pi);
1139 g_return_if_fail (pi->page_setup != NULL);
1141 pi->edge_to_above_footer = e_f;
1144 void
1145 print_info_set_edge_to_below_header (GnmPrintInformation *pi, double e_h)
1147 g_return_if_fail (pi != NULL);
1148 gnm_print_info_load_defaults (pi);
1149 g_return_if_fail (pi->page_setup != NULL);
1151 pi->edge_to_below_header = e_h;
1155 void
1156 print_info_set_margins (GnmPrintInformation *pi,
1157 double header, double footer, double left, double right)
1159 g_return_if_fail (pi != NULL);
1160 gnm_print_info_load_defaults (pi);
1161 g_return_if_fail (pi->page_setup != NULL);
1163 if (header >= 0)
1164 gtk_page_setup_set_top_margin (pi->page_setup,
1165 header, GTK_UNIT_POINTS);
1166 if (footer >= 0)
1167 gtk_page_setup_set_bottom_margin (pi->page_setup,
1168 footer, GTK_UNIT_POINTS);
1169 if (left >= 0)
1170 gtk_page_setup_set_left_margin (pi->page_setup,
1171 left, GTK_UNIT_POINTS);
1172 if (right >= 0)
1173 gtk_page_setup_set_right_margin (pi->page_setup,
1174 right, GTK_UNIT_POINTS);
1177 static gboolean
1178 known_bad_paper (const char *paper)
1180 if (strcmp (paper, "") == 0)
1181 return TRUE;
1182 return FALSE;
1186 static void
1187 paper_log_func (G_GNUC_UNUSED const gchar *log_domain,
1188 GLogLevelFlags log_level,
1189 G_GNUC_UNUSED const gchar *message,
1190 gpointer user_data)
1192 int *pwarn = user_data;
1194 if (log_level & G_LOG_LEVEL_WARNING)
1195 *pwarn = 1;
1198 gboolean
1199 page_setup_set_paper (GtkPageSetup *page_setup, char const *paper)
1201 GtkPaperSize* gtk_paper;
1202 int bad_paper = 0;
1204 g_return_val_if_fail (page_setup != NULL, TRUE);
1206 /* We are now using the standard paper names given by PWG 5101.1-2002 */
1207 /* We are trying to map some old gnome-print paper names. */
1210 "A4" -> GTK_PAPER_NAME_A4
1211 "USLetter" -> GTK_PAPER_NAME_LETTER
1212 "USLegal" -> GTK_PAPER_NAME_LEGAL
1213 "Executive" -> GTK_PAPER_NAME_EXECUTIVE
1214 "A3" -> GTK_PAPER_NAME_A3
1215 "A5" -> GTK_PAPER_NAME_A5
1216 "B5" -> GTK_PAPER_NAME_B5
1217 * */
1219 if (g_ascii_strcasecmp ("A4", paper) == 0)
1220 paper = GTK_PAPER_NAME_A4;
1221 else if (g_ascii_strcasecmp ("A3", paper) == 0)
1222 paper = GTK_PAPER_NAME_A3;
1223 else if (g_ascii_strcasecmp ("A5", paper) == 0)
1224 paper = GTK_PAPER_NAME_A5;
1225 else if (g_ascii_strcasecmp ("B5", paper) == 0)
1226 paper = GTK_PAPER_NAME_B5;
1227 else if (g_ascii_strcasecmp ("USLetter", paper) == 0 ||
1228 g_ascii_strcasecmp ("US-Letter", paper) == 0 ||
1229 g_ascii_strcasecmp ("Letter", paper) == 0)
1230 paper = GTK_PAPER_NAME_LETTER;
1231 else if (g_ascii_strcasecmp ("USLegal", paper) == 0)
1232 paper = GTK_PAPER_NAME_LEGAL;
1233 else if (g_ascii_strncasecmp ("Executive", paper, 9) == 0)
1234 paper = GTK_PAPER_NAME_EXECUTIVE;
1235 /* GTK behaves stupid on some string it should recognize:*/
1236 else if (g_str_has_prefix (paper, "iso_a3_"))
1237 paper = GTK_PAPER_NAME_A3;
1238 else if (g_str_has_prefix (paper, "iso_a4_"))
1239 paper = GTK_PAPER_NAME_A4;
1240 else if (g_str_has_prefix (paper, "iso_a5_"))
1241 paper = GTK_PAPER_NAME_A5;
1242 else if (g_str_has_prefix (paper, "iso_b5_"))
1243 paper = GTK_PAPER_NAME_B5;
1244 else if (g_str_has_prefix (paper, "na_letter_"))
1245 paper = GTK_PAPER_NAME_LETTER;
1246 else if (g_str_has_prefix (paper, "na_legal_"))
1247 paper = GTK_PAPER_NAME_LEGAL;
1248 else if (g_str_has_prefix (paper, "na_executive_"))
1249 paper = GTK_PAPER_NAME_EXECUTIVE;
1251 /* Hack: gtk_paper_size_new warns on bad paper, so shut it up. */
1252 /* http://bugzilla.gnome.org/show_bug.cgi?id=493880 */
1253 if (known_bad_paper (paper)) {
1254 gtk_paper = NULL;
1255 bad_paper = 1;
1256 } else {
1257 const char *domain = "Gtk";
1258 guint handler = g_log_set_handler (domain, G_LOG_LEVEL_WARNING,
1259 paper_log_func, &bad_paper);
1261 gtk_paper = gtk_paper_size_new (paper);
1262 g_log_remove_handler (domain, handler);
1263 if (!gtk_paper)
1264 bad_paper = 1;
1267 if (!bad_paper)
1268 gtk_page_setup_set_paper_size (page_setup, gtk_paper);
1269 if (gtk_paper)
1270 gtk_paper_size_free (gtk_paper);
1272 return bad_paper;
1275 gboolean
1276 print_info_set_paper (GnmPrintInformation *pi, char const *paper)
1278 g_return_val_if_fail (pi != NULL, TRUE);
1280 gnm_print_info_load_defaults (pi);
1281 return page_setup_set_paper (pi->page_setup, paper);
1284 char *
1285 page_setup_get_paper (GtkPageSetup *page_setup)
1287 GtkPaperSize* paper;
1288 char const *name;
1290 g_return_val_if_fail (page_setup != NULL, g_strdup (GTK_PAPER_NAME_A4));
1292 paper = gtk_page_setup_get_paper_size (page_setup);
1294 if (gtk_paper_size_is_custom (paper)) {
1295 double width = gtk_paper_size_get_width (paper, GTK_UNIT_MM);
1296 double height = gtk_paper_size_get_height (paper, GTK_UNIT_MM);
1297 return g_strdup_printf ("custom_Gnm-%.0fx%.0fmm_%.0fx%.0fmm",
1298 width, height, width, height);
1301 name = gtk_paper_size_get_name (gtk_page_setup_get_paper_size (page_setup));
1303 /* Working around gtk bug 426416 */
1304 if (strncmp (name, "custom", 6) == 0) {
1305 double width = gtk_paper_size_get_width (paper, GTK_UNIT_MM);
1306 double height = gtk_paper_size_get_height (paper, GTK_UNIT_MM);
1307 return g_strdup_printf ("custom_Gnm-%.0fx%.0fmm_%.0fx%.0fmm",
1308 width, height, width, height);
1310 return g_strdup (name);
1313 char *
1314 print_info_get_paper (GnmPrintInformation *pi)
1316 g_return_val_if_fail (pi != NULL, g_strdup (GTK_PAPER_NAME_A4));
1317 gnm_print_info_load_defaults (pi);
1319 return page_setup_get_paper (pi->page_setup);
1322 GtkPaperSize *
1323 print_info_get_paper_size (GnmPrintInformation *pi)
1325 g_return_val_if_fail (pi != NULL, NULL);
1326 gnm_print_info_load_defaults (pi);
1328 return gtk_page_setup_get_paper_size (pi->page_setup);
1332 * print_info_get_paper_display_name:
1333 * @pi: #GnmPrintInformation
1335 * Returns: (transfer none): the name of the selected paper type
1337 char const *
1338 print_info_get_paper_display_name (GnmPrintInformation *pi)
1340 GtkPaperSize* paper;
1342 g_return_val_if_fail (pi != NULL, "ERROR: No printinformation specified");
1343 gnm_print_info_load_defaults (pi);
1344 g_return_val_if_fail (pi->page_setup != NULL, "ERROR: No pagesetup loaded");
1346 paper = gtk_page_setup_get_paper_size (pi->page_setup);
1347 return gtk_paper_size_get_display_name (paper);
1350 double
1351 print_info_get_paper_width (GnmPrintInformation *pi, GtkUnit unit)
1353 g_return_val_if_fail (pi != NULL, 0.);
1354 gnm_print_info_load_defaults (pi);
1356 return gtk_page_setup_get_paper_width (pi->page_setup, unit);
1359 double
1360 print_info_get_paper_height (GnmPrintInformation *pi, GtkUnit unit)
1362 g_return_val_if_fail (pi != NULL, 0);
1363 gnm_print_info_load_defaults (pi);
1365 return gtk_page_setup_get_paper_height (pi->page_setup, unit);
1369 * gnm_print_info_get_page_setup:
1370 * @pi: #GnmPrintInformation
1372 * Returns: (transfer none): the page setup.
1374 GtkPageSetup *
1375 gnm_print_info_get_page_setup (GnmPrintInformation *pi)
1377 g_return_val_if_fail (pi != NULL, NULL);
1378 gnm_print_info_load_defaults (pi);
1380 return pi->page_setup;
1384 * gnm_print_info_set_page_setup:
1385 * @pi: #GnmPrintInformation
1386 * @page_setup: (transfer full): #GtkPageSetup
1388 * Absorb a ref to @page_setup.
1390 * WHY WHY WHY
1391 * 1) The life cycle in here is a tad odd, the load_defaults does nothing for the
1392 * case of an existing page_setup, and seems like it should be ignored for the
1393 * case of a new one.
1395 * 2) Why not copy the page_setup in here and make the arg const ?
1397 void
1398 gnm_print_info_set_page_setup (GnmPrintInformation *pi,
1399 GtkPageSetup *page_setup)
1401 g_return_if_fail (pi != NULL);
1403 gnm_print_info_load_defaults (pi);
1405 if (pi->page_setup) {
1406 double header, footer, left, right;
1407 print_info_get_margins (pi,
1408 &header, &footer, &left, &right, NULL, NULL);
1409 g_object_unref (pi->page_setup);
1410 pi->page_setup = page_setup;
1411 print_info_set_margins (pi, header, footer, left, right);
1412 } else
1413 pi->page_setup = page_setup;
1416 GtkPageOrientation
1417 print_info_get_paper_orientation (GnmPrintInformation *pi)
1419 GtkPageOrientation orientation;
1421 g_return_val_if_fail (pi != NULL, GTK_PAGE_ORIENTATION_PORTRAIT);
1422 gnm_print_info_load_defaults (pi);
1423 g_return_val_if_fail (pi->page_setup != NULL, GTK_PAGE_ORIENTATION_PORTRAIT);
1425 orientation = gtk_page_setup_get_orientation (pi->page_setup);
1426 return orientation;
1429 void
1430 print_info_set_paper_orientation (GnmPrintInformation *pi,
1431 GtkPageOrientation orientation)
1433 g_return_if_fail (pi != NULL);
1434 gnm_print_info_load_defaults (pi);
1436 gtk_page_setup_set_orientation (pi->page_setup, orientation);
1440 * print_info_set_breaks:
1441 * @pi: #GnmPrintInformation
1442 * @breaks: (transfer full): #GnmPageBreaks
1444 void
1445 print_info_set_breaks (GnmPrintInformation *pi,
1446 GnmPageBreaks *breaks)
1448 GnmPageBreaks **target;
1450 g_return_if_fail (pi != NULL);
1452 target = breaks->is_vert ? &pi->page_breaks.v : &pi->page_breaks.h;
1454 if (*target == breaks) /* just in case something silly happens */
1455 return;
1457 gnm_page_breaks_free (*target);
1458 *target = breaks;
1461 gboolean
1462 print_info_has_manual_breaks (GnmPrintInformation *pi)
1464 if (gnm_page_breaks_get_next_manual_break (pi->page_breaks.v, 0) > -1)
1465 return TRUE;
1466 return (gnm_page_breaks_get_next_manual_break (pi->page_breaks.h, 0) > -1);
1469 /********************************************************************
1470 * Simple data structure to store page breaks defined as a wrapper in case we
1471 * need something more extensive later. */
1474 * gnm_page_breaks_new:
1475 * @is_vert:
1477 * Allocate a collection of page breaks.
1479 GnmPageBreaks *
1480 gnm_page_breaks_new (gboolean is_vert)
1482 GnmPageBreaks *res = g_new (GnmPageBreaks, 1);
1484 res->is_vert = is_vert;
1485 res->details = g_array_new (FALSE, FALSE, sizeof (GnmPageBreak));
1487 return res;
1491 * gnm_page_breaks_dup:
1492 * @src: (transfer none) (nullable): #GnmPageBreak
1494 * Returns: (transfer full) (nullable): A duplicate #GnmPageBreak.
1496 GnmPageBreaks *
1497 gnm_page_breaks_dup (GnmPageBreaks const *src)
1499 if (src != NULL) {
1500 GnmPageBreaks *dst = gnm_page_breaks_new (src->is_vert);
1501 GArray *d_details = dst->details;
1502 GArray const *s_details = src->details;
1503 unsigned i;
1505 /* no need to validate through gnm_page_breaks_append_break, just dup */
1506 for (i = 0; i < s_details->len ; i++)
1507 g_array_append_val (d_details,
1508 g_array_index (s_details, GnmPageBreak, i));
1510 return dst;
1511 } else
1512 return NULL;
1516 * gnm_page_breaks_free:
1517 * @breaks: (transfer none) (nullable): #GnmPageBreak
1519 void
1520 gnm_page_breaks_free (GnmPageBreaks *breaks)
1522 if (breaks) {
1523 g_array_free (breaks->details, TRUE);
1524 g_free (breaks);
1528 GType
1529 gnm_page_breaks_get_type (void)
1531 static GType t = 0;
1533 if (t == 0) {
1534 t = g_boxed_type_register_static ("GnmPageBreaks",
1535 (GBoxedCopyFunc)gnm_page_breaks_dup,
1536 (GBoxedFreeFunc)gnm_page_breaks_free);
1538 return t;
1542 * gnm_page_breaks_dup_non_auto_breaks:
1543 * @src: (transfer none) (nullable): #GnmPageBreak
1545 * Returns: (transfer full) (nullable): A duplicate #GnmPageBreak, but
1546 * containing only non-auto page breaks.
1548 GnmPageBreaks *
1549 gnm_page_breaks_dup_non_auto_breaks (GnmPageBreaks const *src)
1551 if (src != NULL) {
1552 GnmPageBreaks *dst = gnm_page_breaks_new (src->is_vert);
1553 GArray *d_details = dst->details;
1554 GArray const *s_details = src->details;
1555 GnmPageBreak *pbreak;
1556 unsigned i;
1558 /* no need to validate through gnm_page_breaks_append_break, just dup */
1559 for (i = 0; i < s_details->len ; i++) {
1560 pbreak = &g_array_index (s_details, GnmPageBreak, i);
1561 if (pbreak->type != GNM_PAGE_BREAK_AUTO)
1562 g_array_append_val (d_details, *pbreak);
1564 return dst;
1565 } else
1566 return NULL;
1569 gboolean
1570 gnm_page_breaks_append_break (GnmPageBreaks *breaks,
1571 int pos,
1572 GnmPageBreakType type)
1574 GnmPageBreak const *prev;
1575 GnmPageBreak info;
1577 g_return_val_if_fail (breaks != NULL, FALSE);
1579 if (type == GNM_PAGE_BREAK_NONE)
1580 return TRUE;
1582 /* Do some simple validation */
1583 if (pos < 0)
1584 return FALSE;
1585 if (breaks->details->len > 0) {
1586 prev = &g_array_index (breaks->details, GnmPageBreak,
1587 breaks->details->len-1);
1588 if (prev->pos >= pos)
1589 return FALSE;
1592 info.pos = pos;
1593 info.type = type;
1594 g_array_append_val (breaks->details, info);
1596 return TRUE;
1599 GnmPageBreakType
1600 gnm_page_breaks_get_break (GnmPageBreaks *breaks,
1601 int pos)
1603 int i;
1605 if (breaks == NULL)
1606 return GNM_PAGE_BREAK_NONE;
1608 for (i = breaks->details->len - 1; i >= 0; i--) {
1609 GnmPageBreak *pbreak;
1610 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1611 if (pbreak->pos < pos)
1612 return GNM_PAGE_BREAK_NONE;
1613 if (pbreak->pos == pos)
1614 return (pbreak->type);
1616 return GNM_PAGE_BREAK_NONE;
1620 gnm_page_breaks_get_next_manual_break (GnmPageBreaks *breaks,
1621 int pos)
1623 guint i;
1625 if (breaks == NULL)
1626 return -1;
1628 for (i = 0; i < breaks->details->len; i++) {
1629 GnmPageBreak const *pbreak;
1630 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1631 if (pbreak->pos > pos
1632 && pbreak->type != GNM_PAGE_BREAK_AUTO)
1633 return pbreak->pos;
1635 return -1;
1639 gnm_page_breaks_get_next_break (GnmPageBreaks *breaks, int pos)
1641 guint i;
1643 if (breaks == NULL)
1644 return -1;
1646 for (i = 0; i < breaks->details->len; i++) {
1647 GnmPageBreak const *pbreak;
1648 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1649 if (pbreak->pos > pos)
1650 return pbreak->pos;
1652 return -1;
1655 gboolean
1656 gnm_page_breaks_set_break (GnmPageBreaks *breaks,
1657 int pos,
1658 GnmPageBreakType type)
1660 GnmPageBreak *pbreak;
1661 GnmPageBreak info;
1662 guint i;
1663 int before = -1;
1665 g_return_val_if_fail (breaks != NULL, FALSE);
1667 /* Do some simple validation */
1668 if (pos < 0)
1669 return FALSE;
1671 if (breaks->details->len == 0 && type != GNM_PAGE_BREAK_NONE)
1672 return gnm_page_breaks_append_break (breaks, pos, type);
1674 for (i = 0; i < breaks->details->len; i++) {
1675 pbreak = &g_array_index (breaks->details, GnmPageBreak, i);
1676 if (pbreak->pos == pos) {
1677 if (type == GNM_PAGE_BREAK_NONE) {
1678 g_array_remove_index (breaks->details, i);
1679 } else {
1680 pbreak->type = type;
1682 return TRUE;
1683 } else if (pbreak->pos < pos)
1684 before = (int) i;
1687 if (type == GNM_PAGE_BREAK_NONE)
1688 return TRUE;
1690 info.pos = pos;
1691 info.type = type;
1692 if ((before + 1) > (int) breaks->details->len)
1693 g_array_append_val (breaks->details, info);
1694 else
1695 g_array_insert_val (breaks->details, (before + 1), info);
1697 return TRUE;
1701 * gnm_page_break_type_from_str:
1702 * @str:
1705 GnmPageBreakType
1706 gnm_page_break_type_from_str (char const *str)
1708 if (0 == g_ascii_strcasecmp (str, "manual"))
1709 return GNM_PAGE_BREAK_MANUAL;
1710 if (0 == g_ascii_strcasecmp (str, "auto"))
1711 return GNM_PAGE_BREAK_AUTO;
1712 if (0 == g_ascii_strcasecmp (str, "data-slice"))
1713 return GNM_PAGE_BREAK_DATA_SLICE;
1714 if (0 == g_ascii_strcasecmp (str, "none"))
1715 return GNM_PAGE_BREAK_NONE;
1716 return GNM_PAGE_BREAK_NONE;
1721 * gnm_page_breaks_clean:
1722 * @breaks: (nullable): #GnmPageBreakType
1724 * Remove all auto page breaks
1726 void
1727 gnm_page_breaks_clean (GnmPageBreaks *breaks)
1729 guint i;
1731 if (breaks == NULL)
1732 return;
1734 for (i = 0; i < breaks->details->len; i++) {
1735 GnmPageBreak *pbreak = &g_array_index (breaks->details,
1736 GnmPageBreak, i);
1737 if (pbreak->type == GNM_PAGE_BREAK_AUTO) {
1738 g_array_remove_index (breaks->details, i);
1739 i--;
1744 void
1745 print_info_set_printtofile_uri (GnmPrintInformation *pi,
1746 gchar const *uri)
1748 g_free (pi->printtofile_uri);
1749 pi->printtofile_uri = g_strdup (uri);
1752 void
1753 print_info_set_printtofile_from_settings (GnmPrintInformation *pi,
1754 GtkPrintSettings* settings,
1755 gchar const *default_uri)
1757 char const *uri = gtk_print_settings_get
1758 (settings,
1759 GTK_PRINT_SETTINGS_OUTPUT_URI);
1760 if (strcmp (uri, default_uri) == 0)
1761 print_info_set_printtofile_uri (pi, NULL);
1762 else
1763 print_info_set_printtofile_uri (pi, uri);
1766 void
1767 print_info_set_from_settings (GnmPrintInformation *pi,
1768 GtkPrintSettings* settings)
1770 pi->print_range = gtk_print_settings_get_int_with_default
1771 (settings,
1772 GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY,
1773 GNM_PRINT_ACTIVE_SHEET);
1776 PrintRange
1777 print_info_get_printrange (GnmPrintInformation *pi)
1779 gnm_print_info_load_defaults (pi);
1780 return pi->print_range;
1783 void
1784 print_info_set_printrange (GnmPrintInformation *pi, PrintRange pr)
1786 if (pr >= GNM_PRINT_ACTIVE_SHEET
1787 && pr <= GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA)
1788 pi->print_range = pr;
1789 else
1790 pi->print_range = GNM_PRINT_ACTIVE_SHEET;
1794 * print_info_get_printtofile_uri:
1795 * @pi: @GnmPrintInformation
1797 * Returns: (transfer none): The uri used for print-to-file.
1799 char const *
1800 print_info_get_printtofile_uri (GnmPrintInformation *pi)
1802 gnm_print_info_load_defaults (pi);
1803 return pi->printtofile_uri;
1807 gboolean
1808 print_load_repeat_range (char const *str, GnmRange *r, Sheet const *sheet)
1810 GnmParsePos pp;
1811 GnmRangeRef res;
1813 if (str == NULL || *str == '\0')
1814 return FALSE;
1816 if (str != rangeref_parse (&res, str,
1817 parse_pos_init_sheet (&pp, sheet),
1818 gnm_conventions_default)) {
1819 Sheet *start_sheet = (Sheet *)sheet;
1820 Sheet *end_sheet = (Sheet *)sheet;
1821 gnm_rangeref_normalize_pp (&res, &pp,
1822 &start_sheet, &end_sheet,
1824 return TRUE;
1825 } else
1826 return FALSE;