1 /* GTK - The GIMP Toolkit
2 * gtkpapersize.c: Paper Size
3 * Copyright (C) 2006, Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
25 #if defined(HAVE__NL_PAPER_HEIGHT) && defined(HAVE__NL_PAPER_WIDTH)
29 #include "gtkpapersize.h"
32 #define MM_PER_INCH 25.4
33 #define POINTS_PER_INCH 72
35 #include "paper_names_offsets.c"
39 const PaperInfo *info;
41 /* If these are not set we fall back to info */
46 double width, height; /* Stored in mm */
51 gtk_paper_size_get_type (void)
53 static GType our_type = 0;
56 our_type = g_boxed_type_register_static ("GtkPaperSize",
57 (GBoxedCopyFunc)gtk_paper_size_copy,
58 (GBoxedFreeFunc)gtk_paper_size_free);
63 lookup_paper_info (const char *name)
66 int upper = G_N_ELEMENTS (standard_names_offsets) - 1;
72 mid = (lower + upper) / 2;
73 cmp = strcmp (name, paper_names + standard_names_offsets[mid].name);
79 return &standard_names_offsets[mid];
81 while (lower <= upper);
87 to_mm (double len, GtkUnit unit)
94 return len * MM_PER_INCH;
97 g_warning ("Unsupported unit");
100 return len * (MM_PER_INCH / POINTS_PER_INCH);
106 from_mm (double len, GtkUnit unit)
113 return len / MM_PER_INCH;
116 g_warning ("Unsupported unit");
118 case GTK_UNIT_POINTS:
119 return len / (MM_PER_INCH / POINTS_PER_INCH);
125 parse_media_size (const char *size,
126 double *width_mm, double *height_mm)
130 double short_dim, long_dim;
134 short_dim = g_ascii_strtod (p, &e);
136 if (p == e || *e != 'x')
139 p = e + 1; /* Skip x */
141 long_dim = g_ascii_strtod (p, &e);
148 if (strcmp (p, "in") == 0)
150 short_dim = short_dim * MM_PER_INCH;
151 long_dim = long_dim * MM_PER_INCH;
153 else if (strcmp (p, "mm") != 0)
157 *width_mm = short_dim;
159 *height_mm = long_dim;
165 parse_full_media_size_name (const char *full_name,
167 double *width_mm, double *height_mm)
170 const char *end_of_name;
173 media-size-self-describing-name =
174 ( class-in "_" size-name "_" short-dim "x" long-dim "in" ) |
175 ( class-mm "_" size-name "_" short-dim "x" long-dim "mm" )
176 class-in = "custom" | "na" | "asme" | "roc" | "oe"
177 class-mm = "custom" | "iso" | "jis" | "jpn" | "prc" | "om"
178 size-name = ( lowalpha | digit ) *( lowalpha | digit | "-" )
181 dim = integer-part [fraction-part] | "0" fraction-part
182 integer-part = non-zero-digit *digit
183 fraction-part = "." *digit non-zero-digit
184 lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
185 "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
186 "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
187 non-zero-digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
188 digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
191 p = strchr (full_name, '_');
205 if (!parse_media_size (p, width_mm, height_mm))
209 *name = g_strndup (full_name, end_of_name - full_name);
214 static GtkPaperSize *
215 gtk_paper_size_new_from_info (const PaperInfo *info)
219 size = g_new0 (GtkPaperSize, 1);
221 size->width = info->width;
222 size->height = info->height;
228 gtk_paper_size_new (const char *name)
232 double width, height;
236 name = gtk_paper_size_get_default ();
238 if (parse_full_media_size_name (name, &short_name, &width, &height))
240 size = g_new0 (GtkPaperSize, 1);
243 size->height = height;
244 size->name = short_name;
245 size->display_name = g_strdup (short_name);
249 info = lookup_paper_info (name);
251 size = gtk_paper_size_new_from_info (info);
254 g_warning ("Unknown paper size %s\n", name);
255 size = g_new0 (GtkPaperSize, 1);
256 size->name = g_strdup (name);
257 size->display_name = g_strdup (name);
258 /* Default to A4 size */
268 gtk_paper_size_new_from_ppd (const char *ppd_name,
269 const char *ppd_display_name,
274 const char *lookup_ppd_name;
279 lookup_ppd_name = ppd_name;
282 /* Strip out Traverse suffix in matching. */
283 if (g_str_has_suffix (ppd_name, ".Transverse"))
285 lookup_ppd_name = freeme =
286 g_strndup (ppd_name, strlen (ppd_name) - strlen (".Transverse"));
289 for (i = 0; i < G_N_ELEMENTS(standard_names_offsets); i++)
291 if (standard_names_offsets[i].ppd_name != -1 &&
292 strcmp (paper_names + standard_names_offsets[i].ppd_name, lookup_ppd_name) == 0)
294 size = gtk_paper_size_new_from_info (&standard_names_offsets[i]);
299 for (i = 0; i < G_N_ELEMENTS(extra_ppd_names_offsets); i++)
301 if (strcmp (paper_names + extra_ppd_names_offsets[i].ppd_name, lookup_ppd_name) == 0)
303 size = gtk_paper_size_new (paper_names + extra_ppd_names_offsets[i].standard_name);
308 name = g_strdup_printf ("ppd_%s", ppd_name);
309 size = gtk_paper_size_new_custom (name, ppd_display_name, width, height, GTK_UNIT_POINTS);
314 if (size->info == NULL ||
315 size->info->ppd_name == -1 ||
316 strcmp (paper_names + size->info->ppd_name, ppd_name) != 0)
317 size->ppd_name = g_strdup (ppd_name);
326 gtk_paper_size_new_custom (const char *name,
327 const char *display_name,
333 g_return_val_if_fail (name != NULL, NULL);
334 g_return_val_if_fail (unit != GTK_UNIT_PIXEL, NULL);
336 size = g_new0 (GtkPaperSize, 1);
338 size->name = g_strdup (name);
339 size->display_name = g_strdup (display_name);
340 size->is_custom = TRUE;
342 size->width = to_mm (width, unit);
343 size->height = to_mm (height, unit);
349 gtk_paper_size_copy (GtkPaperSize *other)
353 size = g_new0 (GtkPaperSize, 1);
355 size->info = other->info;
357 size->name = g_strdup (other->name);
358 if (other->display_name)
359 size->display_name = g_strdup (other->display_name);
361 size->ppd_name = g_strdup (other->ppd_name);
363 size->width = other->width;
364 size->height = other->height;
365 size->is_custom = other->is_custom;
371 gtk_paper_size_free (GtkPaperSize *size)
374 g_free (size->display_name);
375 g_free (size->ppd_name);
380 gtk_paper_size_is_equal (GtkPaperSize *size1,
383 if (size1->info != NULL && size2->info != NULL)
384 return size1->info == size2->info;
386 return strcmp (gtk_paper_size_get_name (size1),
387 gtk_paper_size_get_name (size2)) == 0;
390 G_CONST_RETURN char *
391 gtk_paper_size_get_name (GtkPaperSize *size)
395 g_assert (size->info != NULL);
396 return paper_names + size->info->name;
399 G_CONST_RETURN char *
400 gtk_paper_size_get_display_name (GtkPaperSize *size)
402 if (size->display_name)
403 return size->display_name;
404 g_assert (size->info != NULL);
405 return gettext (paper_names + size->info->display_name);
408 G_CONST_RETURN char *
409 gtk_paper_size_get_ppd_name (GtkPaperSize *size)
412 return size->ppd_name;
414 return paper_names + size->info->ppd_name;
419 gtk_paper_size_get_width (GtkPaperSize *size, GtkUnit unit)
421 return from_mm (size->width, unit);
424 gtk_paper_size_get_height (GtkPaperSize *size, GtkUnit unit)
426 return from_mm (size->height, unit);
430 gtk_paper_size_is_custom (GtkPaperSize *size)
432 return size->is_custom;
435 /* Only for custom sizes: */
437 gtk_paper_size_set_size (GtkPaperSize *size, double width, double height, GtkUnit unit)
439 g_return_if_fail (size != NULL);
440 g_return_if_fail (size->is_custom);
442 size->width = to_mm (width, unit);
443 size->height = to_mm (height, unit);
446 #define NL_PAPER_GET(x) \
447 ((union { char *string; unsigned int word; })nl_langinfo(x)).word
449 G_CONST_RETURN char *
450 gtk_paper_size_get_default (void)
452 char *locale, *freeme = NULL;
453 const char *paper_size;
455 #if defined(HAVE__NL_PAPER_HEIGHT) && defined(HAVE__NL_PAPER_WIDTH)
457 int width = NL_PAPER_GET (_NL_PAPER_WIDTH);
458 int height = NL_PAPER_GET (_NL_PAPER_HEIGHT);
460 if (width == 210 && height == 297)
461 return GTK_PAPER_NAME_A4;
463 if (width == 216 && height == 279)
464 return GTK_PAPER_NAME_LETTER;
469 freeme = locale = g_win32_getlocale ();
470 #elif defined(LC_PAPER)
471 locale = setlocale(LC_PAPER, NULL);
473 locale = setlocale(LC_MESSAGES, NULL);
477 return GTK_PAPER_NAME_A4;
479 if (g_str_has_prefix (locale, "en_CA") ||
480 g_str_has_prefix (locale, "en_US") ||
481 g_str_has_prefix (locale, "es_PR") ||
482 g_str_has_prefix (locale, "es_US"))
483 paper_size = GTK_PAPER_NAME_LETTER;
485 paper_size = GTK_PAPER_NAME_A4;
491 /* These get the default margins used for the paper size. Its
492 * larger than most printers margins, so that it will be within
493 * the imageble area on any printer.
495 * I've taken the actual values used from the OSX page setup dialog.
496 * I'm not sure exactly where they got these values for, but might
497 * correspond to this (from ghostscript docs):
499 * All DeskJets have 0.5 inches (1.27cm) of unprintable bottom margin,
500 * due to the mechanical arrangement used to grab the paper. Side margins
501 * are approximately 0.25 inches (0.64cm) for U.S. letter paper, and 0.15
502 * inches (0.38cm) for A4.
506 gtk_paper_size_get_default_top_margin (GtkPaperSize *size, GtkUnit unit)
510 margin = to_mm (0.25, GTK_UNIT_INCH);
511 return from_mm (margin, unit);
515 gtk_paper_size_get_default_bottom_margin (GtkPaperSize *size, GtkUnit unit)
520 margin = to_mm (0.25, GTK_UNIT_INCH);
522 name = gtk_paper_size_get_name (size);
523 if (strcmp (name, "na_letter") == 0 ||
524 strcmp (name, "na_legal") == 0 ||
525 strcmp (name, "iso_a4") == 0)
526 margin = to_mm (0.56, GTK_UNIT_INCH);
528 return from_mm (margin, unit);
532 gtk_paper_size_get_default_left_margin (GtkPaperSize *size, GtkUnit unit)
536 margin = to_mm (0.25, GTK_UNIT_INCH);
537 return from_mm (margin, unit);
541 gtk_paper_size_get_default_right_margin (GtkPaperSize *size, GtkUnit unit)
545 margin = to_mm (0.25, GTK_UNIT_INCH);
546 return from_mm (margin, unit);
550 #define __GTK_PAPER_SIZE_C__
551 #include "gtkaliasdef.c"