Bug Summary

File:ctk/ctkpapersize.c
Warning:line 1143, column 3
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkpapersize.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-172619-43637-1 -x c ctkpapersize.c
1/* CTK - The GIMP Toolkit
2 * ctkpapersize.c: Paper Size
3 * Copyright (C) 2006, Red Hat, Inc.
4 * Copyright © 2006, 2007 Christian Persch
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "config.h"
21#include <string.h>
22#include <stdlib.h>
23#include <locale.h>
24#if defined(HAVE__NL_PAPER_HEIGHT1) && defined(HAVE__NL_PAPER_WIDTH1)
25#include <langinfo.h>
26#endif
27#include <math.h>
28
29#include "ctkpapersize.h"
30#include "ctkprintutils.h"
31#include "ctkprintoperation.h" /* for CtkPrintError */
32#include "ctkintl.h"
33
34/* _ctk_load_custom_papers() only on Unix so far */
35#ifdef G_OS_UNIX
36#include "ctkcustompaperunixdialog.h"
37#endif
38
39#include "paper_names_offsets.c"
40
41
42/**
43 * SECTION:ctkpapersize
44 * @Short_description: Support for named paper sizes
45 * @Title: CtkPaperSize
46 * @See_also:#CtkPageSetup
47 *
48 * CtkPaperSize handles paper sizes. It uses the standard called
49 * [PWG 5101.1-2002 PWG: Standard for Media Standardized Names](http://www.pwg.org/standards.html)
50 * to name the paper sizes (and to get the data for the page sizes).
51 * In addition to standard paper sizes, CtkPaperSize allows to
52 * construct custom paper sizes with arbitrary dimensions.
53 *
54 * The #CtkPaperSize object stores not only the dimensions (width
55 * and height) of a paper size and its name, it also provides
56 * default [print margins][print-margins].
57 *
58 * Printing support has been added in CTK+ 2.10.
59 */
60
61
62struct _CtkPaperSize
63{
64 const PaperInfo *info;
65
66 /* If these are not set we fall back to info */
67 gchar *name;
68 gchar *display_name;
69 gchar *ppd_name;
70
71 gdouble width, height; /* Stored in mm */
72 gboolean is_custom;
73 gboolean is_ipp;
74};
75
76G_DEFINE_BOXED_TYPE (CtkPaperSize, ctk_paper_size,static GType ctk_paper_size_get_type_once (void); GType ctk_paper_size_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_paper_size_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_paper_size_get_type_once (void
) { GType (* _g_register_boxed) (const gchar *, union { CtkPaperSize
* (*do_copy_type) (CtkPaperSize *); CtkPaperSize * (*do_const_copy_type
) (const CtkPaperSize *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkPaperSize
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkPaperSize"), ctk_paper_size_copy
, ctk_paper_size_free); { {{};} } return g_define_type_id; }
77 ctk_paper_size_copy,static GType ctk_paper_size_get_type_once (void); GType ctk_paper_size_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_paper_size_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_paper_size_get_type_once (void
) { GType (* _g_register_boxed) (const gchar *, union { CtkPaperSize
* (*do_copy_type) (CtkPaperSize *); CtkPaperSize * (*do_const_copy_type
) (const CtkPaperSize *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkPaperSize
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkPaperSize"), ctk_paper_size_copy
, ctk_paper_size_free); { {{};} } return g_define_type_id; }
78 ctk_paper_size_free)static GType ctk_paper_size_get_type_once (void); GType ctk_paper_size_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_paper_size_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_paper_size_get_type_once (void
) { GType (* _g_register_boxed) (const gchar *, union { CtkPaperSize
* (*do_copy_type) (CtkPaperSize *); CtkPaperSize * (*do_const_copy_type
) (const CtkPaperSize *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkPaperSize
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkPaperSize"), ctk_paper_size_copy
, ctk_paper_size_free); { {{};} } return g_define_type_id; }
79
80static const PaperInfo *
81lookup_paper_info (const gchar *name)
82{
83 int lower = 0;
84 int upper = G_N_ELEMENTS (standard_names_offsets)(sizeof (standard_names_offsets) / sizeof ((standard_names_offsets
)[0]))
- 1;
85
86 do
87 {
88 int mid;
89 int cmp;
90
91 mid = (lower + upper) / 2;
92 cmp = strcmp (name, paper_names + standard_names_offsets[mid].name);
93 if (cmp < 0)
94 upper = mid - 1;
95 else if (cmp > 0)
96 lower = mid + 1;
97 else
98 return &standard_names_offsets[mid];
99 }
100 while (lower <= upper);
101
102 return NULL((void*)0);
103}
104
105static gboolean
106parse_media_size (const gchar *size,
107 gdouble *width_mm,
108 gdouble *height_mm)
109{
110 const char *p;
111 char *e;
112 double short_dim, long_dim;
113
114 p = size;
115
116 short_dim = g_ascii_strtod (p, &e);
117
118 if (p == e || *e != 'x')
119 return FALSE(0);
120
121 p = e + 1; /* Skip x */
122
123 long_dim = g_ascii_strtod (p, &e);
124
125 if (p == e)
126 return FALSE(0);
127
128 p = e;
129
130 if (strcmp (p, "in") == 0)
131 {
132 short_dim = short_dim * MM_PER_INCH25.4;
133 long_dim = long_dim * MM_PER_INCH25.4;
134 }
135 else if (strcmp (p, "mm") != 0)
136 return FALSE(0);
137
138 if (width_mm)
139 *width_mm = short_dim;
140 if (height_mm)
141 *height_mm = long_dim;
142
143 return TRUE(!(0));
144}
145
146static gboolean
147parse_full_media_size_name (const gchar *full_name,
148 gchar **name,
149 gdouble *width_mm,
150 gdouble *height_mm)
151{
152 const char *p;
153 const char *end_of_name;
154
155 /* From the spec:
156 media-size-self-describing-name =
157 ( class-in "_" size-name "_" short-dim "x" long-dim "in" ) |
158 ( class-mm "_" size-name "_" short-dim "x" long-dim "mm" )
159 class-in = "custom" | "na" | "asme" | "roc" | "oe"
160 class-mm = "custom" | "iso" | "jis" | "jpn" | "prc" | "om"
161 size-name = ( lowalpha | digit ) *( lowalpha | digit | "-" )
162 short-dim = dim
163 long-dim = dim
164 dim = integer-part [fraction-part] | "0" fraction-part
165 integer-part = non-zero-digit *digit
166 fraction-part = "." *digit non-zero-digit
167 lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
168 "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
169 "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
170 non-zero-digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
171 digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
172 */
173
174 p = strchr (full_name, '_');
175 if (p == NULL((void*)0))
176 return FALSE(0);
177
178 p++; /* Skip _ */
179
180 p = strchr (p, '_');
181 if (p == NULL((void*)0))
182 return FALSE(0);
183
184 end_of_name = p;
185
186 p++; /* Skip _ */
187
188 if (!parse_media_size (p, width_mm, height_mm))
189 return FALSE(0);
190
191 if (name)
192 *name = g_strndup (full_name, end_of_name - full_name);
193
194 return TRUE(!(0));
195}
196
197static CtkPaperSize *
198ctk_paper_size_new_from_info (const PaperInfo *info)
199{
200 CtkPaperSize *size;
201
202 size = g_slice_new0 (CtkPaperSize)((CtkPaperSize*) g_slice_alloc0 (sizeof (CtkPaperSize)));
203 size->info = info;
204 size->width = info->width;
205 size->height = info->height;
206
207 return size;
208}
209
210/**
211 * ctk_paper_size_new:
212 * @name: (allow-none): a paper size name, or %NULL
213 *
214 * Creates a new #CtkPaperSize object by parsing a
215 * [PWG 5101.1-2002](ftp://ftp.pwg.org/pub/pwg/candidates/cs-pwgmsn10-20020226-5101.1.pdf)
216 * paper name.
217 *
218 * If @name is %NULL, the default paper size is returned,
219 * see ctk_paper_size_get_default().
220 *
221 * Returns: a new #CtkPaperSize, use ctk_paper_size_free()
222 * to free it
223 *
224 * Since: 2.10
225 */
226CtkPaperSize *
227ctk_paper_size_new (const gchar *name)
228{
229 CtkPaperSize *size;
230 char *short_name;
231 double width, height;
232 const PaperInfo *info;
233
234 if (name == NULL((void*)0))
235 name = ctk_paper_size_get_default ();
236
237 if (parse_full_media_size_name (name, &short_name, &width, &height))
238 {
239 info = lookup_paper_info (short_name);
240 if (info != NULL((void*)0) && info->width == width && info->height == height)
241 {
242 size = ctk_paper_size_new_from_info (info);
243 g_free (short_name);
244 }
245 else
246 {
247 size = g_slice_new0 (CtkPaperSize)((CtkPaperSize*) g_slice_alloc0 (sizeof (CtkPaperSize)));
248
249 size->width = width;
250 size->height = height;
251 size->name = short_name;
252 size->display_name = g_strdup (short_name)g_strdup_inline (short_name);
253 if (strncmp (short_name, "custom", 6) == 0)
254 size->is_custom = TRUE(!(0));
255 }
256 }
257 else
258 {
259 info = lookup_paper_info (name);
260 if (info != NULL((void*)0))
261 size = ctk_paper_size_new_from_info (info);
262 else
263 {
264 g_warning ("Unknown paper size %s", name);
265 size = g_slice_new0 (CtkPaperSize)((CtkPaperSize*) g_slice_alloc0 (sizeof (CtkPaperSize)));
266 size->name = g_strdup (name)g_strdup_inline (name);
267 size->display_name = g_strdup (name)g_strdup_inline (name);
268 /* Default to A4 size */
269 size->width = 210;
270 size->height = 297;
271 }
272 }
273
274 return size;
275}
276
277static gchar *
278improve_displayname (const gchar *name)
279{
280 gchar *p, *s;
281
282 p = strrchr (name, 'x');
283 if (p && p != name &&
284 g_ascii_isdigit (*(p - 1))((g_ascii_table[(guchar) (*(p - 1))] & G_ASCII_DIGIT) != 0
)
&&
285 g_ascii_isdigit (*(p + 1))((g_ascii_table[(guchar) (*(p + 1))] & G_ASCII_DIGIT) != 0
)
)
286 {
287 gchar *p1, *p2;
288 p1 = g_strndup (name, p - name);
289 p2 = g_strdup (p + 1)g_strdup_inline (p + 1);
290 s = g_strconcat (p1, "×", p2, NULL((void*)0));
291 g_free (p1);
292 g_free (p2);
293 }
294 else
295 s = g_strdup (name)g_strdup_inline (name);
296
297 return s;
298}
299
300/**
301 * ctk_paper_size_new_from_ppd:
302 * @ppd_name: a PPD paper name
303 * @ppd_display_name: the corresponding human-readable name
304 * @width: the paper width, in points
305 * @height: the paper height in points
306 *
307 * Creates a new #CtkPaperSize object by using
308 * PPD information.
309 *
310 * If @ppd_name is not a recognized PPD paper name,
311 * @ppd_display_name, @width and @height are used to
312 * construct a custom #CtkPaperSize object.
313 *
314 * Returns: a new #CtkPaperSize, use ctk_paper_size_free()
315 * to free it
316 *
317 * Since: 2.10
318 */
319CtkPaperSize *
320ctk_paper_size_new_from_ppd (const gchar *ppd_name,
321 const gchar *ppd_display_name,
322 gdouble width,
323 gdouble height)
324{
325 char *name;
326 const char *lookup_ppd_name;
327 char *freeme;
328 CtkPaperSize *size;
329 int i;
330 char *display_name;
331
332 lookup_ppd_name = ppd_name;
333
334 freeme = NULL((void*)0);
335 /* Strip out Traverse suffix in matching. */
336 if (g_str_has_suffix (ppd_name, ".Transverse")(__builtin_constant_p (".Transverse")? __extension__ ({ const
char * const __str = (ppd_name); const char * const __suffix
= (".Transverse"); gboolean __result = (0); if (__str == ((void
*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix)
(__str, __suffix); else { const size_t __str_len = strlen ((
(__str) + !(__str))); const size_t __suffix_len = strlen (((__suffix
) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (ppd_name, ".Transverse") )
)
337 {
338 lookup_ppd_name = freeme =
339 g_strndup (ppd_name, strlen (ppd_name) - strlen (".Transverse"));
340 }
341
342 for (i = 0; i < G_N_ELEMENTS (standard_names_offsets)(sizeof (standard_names_offsets) / sizeof ((standard_names_offsets
)[0]))
; i++)
343 {
344 if (standard_names_offsets[i].ppd_name != -1 &&
345 strcmp (paper_names + standard_names_offsets[i].ppd_name, lookup_ppd_name) == 0)
346 {
347 size = ctk_paper_size_new_from_info (&standard_names_offsets[i]);
348 goto out;
349 }
350 }
351
352 for (i = 0; i < G_N_ELEMENTS (extra_ppd_names_offsets)(sizeof (extra_ppd_names_offsets) / sizeof ((extra_ppd_names_offsets
)[0]))
; i++)
353 {
354 if (strcmp (paper_names + extra_ppd_names_offsets[i].ppd_name, lookup_ppd_name) == 0)
355 {
356 size = ctk_paper_size_new (paper_names + extra_ppd_names_offsets[i].standard_name);
357 goto out;
358 }
359 }
360
361 name = g_strconcat ("ppd_", ppd_name, NULL((void*)0));
362 display_name = improve_displayname (ppd_display_name);
363 size = ctk_paper_size_new_custom (name, display_name, width, height, CTK_UNIT_POINTS);
364 g_free (display_name);
365 g_free (name);
366
367 out:
368
369 if (size->info == NULL((void*)0) ||
370 size->info->ppd_name == -1 ||
371 strcmp (paper_names + size->info->ppd_name, ppd_name) != 0)
372 size->ppd_name = g_strdup (ppd_name)g_strdup_inline (ppd_name);
373
374 g_free (freeme);
375
376 return size;
377}
378
379/* Tolerance of paper size in points according to PostScript Language Reference */
380#define PAPER_SIZE_TOLERANCE5 5
381
382/**
383 * ctk_paper_size_new_from_ipp:
384 * @ipp_name: an IPP paper name
385 * @width: the paper width, in points
386 * @height: the paper height in points
387 *
388 * Creates a new #CtkPaperSize object by using
389 * IPP information.
390 *
391 * If @ipp_name is not a recognized paper name,
392 * @width and @height are used to
393 * construct a custom #CtkPaperSize object.
394 *
395 * Returns: a new #CtkPaperSize, use ctk_paper_size_free()
396 * to free it
397 *
398 * Since: 3.16
399 */
400CtkPaperSize *
401ctk_paper_size_new_from_ipp (const gchar *ipp_name,
402 gdouble width,
403 gdouble height)
404{
405 CtkPaperSize *size;
406 const gchar *name = NULL((void*)0);
407 gboolean found = FALSE(0);
408 gchar *display_name = NULL((void*)0);
409 gint i;
410
411 /* Find paper size according to its name */
412 for (i = 0; i < G_N_ELEMENTS (standard_names_offsets)(sizeof (standard_names_offsets) / sizeof ((standard_names_offsets
)[0]))
; i++)
413 {
414 if (standard_names_offsets[i].name != -1)
415 name = paper_names + standard_names_offsets[i].name;
416 if (name != NULL((void*)0) &&
417 /* Given paper size name is equal to a name
418 from the standard paper size names list. */
419 ((g_strcmp0 (ipp_name, name) == 0) ||
420 /* Given paper size name is prefixed by a name
421 from the standard paper size names list +
422 it consists of size in its name (e.g. iso_a4_210x297mm). */
423 (g_str_has_prefix (ipp_name, name)(__builtin_constant_p (name)? __extension__ ({ const char * const
__str = (ipp_name); const char * const __prefix = (name); gboolean
__result = (0); if (__str == ((void*)0) || __prefix == ((void
*)0)) __result = (g_str_has_prefix) (__str, __prefix); else {
const size_t __str_len = strlen (((__str) + !(__str))); const
size_t __prefix_len = strlen (((__prefix) + !(__prefix))); if
(__str_len >= __prefix_len) __result = memcmp (((__str) +
!(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0; }
__result; }) : (g_str_has_prefix) (ipp_name, name) )
&&
424 strlen (ipp_name) > strlen (name) + 2 &&
425 ipp_name[strlen (ipp_name)] == '_' &&
426 g_ascii_isdigit (ipp_name[strlen (ipp_name) + 1])((g_ascii_table[(guchar) (ipp_name[strlen (ipp_name) + 1])] &
G_ASCII_DIGIT) != 0)
&&
427 (g_str_has_suffix (ipp_name, "mm")(__builtin_constant_p ("mm")? __extension__ ({ const char * const
__str = (ipp_name); const char * const __suffix = ("mm"); gboolean
__result = (0); if (__str == ((void*)0) || __suffix == ((void
*)0)) __result = (g_str_has_suffix) (__str, __suffix); else {
const size_t __str_len = strlen (((__str) + !(__str))); const
size_t __suffix_len = strlen (((__suffix) + !(__suffix))); if
(__str_len >= __suffix_len) __result = memcmp (__str + __str_len
- __suffix_len, ((__suffix) + !(__suffix)), __suffix_len) ==
0; } __result; }) : (g_str_has_suffix) (ipp_name, "mm") )
||
428 g_str_has_suffix (ipp_name, "in")(__builtin_constant_p ("in")? __extension__ ({ const char * const
__str = (ipp_name); const char * const __suffix = ("in"); gboolean
__result = (0); if (__str == ((void*)0) || __suffix == ((void
*)0)) __result = (g_str_has_suffix) (__str, __suffix); else {
const size_t __str_len = strlen (((__str) + !(__str))); const
size_t __suffix_len = strlen (((__suffix) + !(__suffix))); if
(__str_len >= __suffix_len) __result = memcmp (__str + __str_len
- __suffix_len, ((__suffix) + !(__suffix)), __suffix_len) ==
0; } __result; }) : (g_str_has_suffix) (ipp_name, "in") )
))))
429 {
430 display_name = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,g_strdup_inline (g_dpgettext2 ("ctk30", "paper size", paper_names
+ standard_names_offsets[i].display_name))
431 "paper size",g_strdup_inline (g_dpgettext2 ("ctk30", "paper size", paper_names
+ standard_names_offsets[i].display_name))
432 paper_names + standard_names_offsets[i].display_name))g_strdup_inline (g_dpgettext2 ("ctk30", "paper size", paper_names
+ standard_names_offsets[i].display_name))
;
433 found = TRUE(!(0));
434 break;
435 }
436 }
437
438 /* Find paper size according to its size */
439 if (display_name == NULL((void*)0))
440 {
441 for (i = 0; i < G_N_ELEMENTS (standard_names_offsets)(sizeof (standard_names_offsets) / sizeof ((standard_names_offsets
)[0]))
; i++)
442 {
443 float x_dimension;
444 float y_dimension;
445
446 x_dimension = _ctk_print_convert_from_mm (standard_names_offsets[i].width, CTK_UNIT_POINTS);
447 y_dimension = _ctk_print_convert_from_mm (standard_names_offsets[i].height, CTK_UNIT_POINTS);
448
449 if (fabs (x_dimension - width) <= PAPER_SIZE_TOLERANCE5 &&
450 fabs (y_dimension - height) <= PAPER_SIZE_TOLERANCE5)
451 {
452 display_name = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,g_strdup_inline (g_dpgettext2 ("ctk30", "paper size", paper_names
+ standard_names_offsets[i].display_name))
453 "paper size",g_strdup_inline (g_dpgettext2 ("ctk30", "paper size", paper_names
+ standard_names_offsets[i].display_name))
454 paper_names + standard_names_offsets[i].display_name))g_strdup_inline (g_dpgettext2 ("ctk30", "paper size", paper_names
+ standard_names_offsets[i].display_name))
;
455 found = TRUE(!(0));
456 break;
457 }
458 }
459 }
460
461 /* Fallback to name of the paper size as given in "ipp_name" parameter */
462 if (display_name == NULL((void*)0))
463 display_name = g_strdup (ipp_name)g_strdup_inline (ipp_name);
464
465 size = ctk_paper_size_new_custom (ipp_name, display_name, width, height, CTK_UNIT_POINTS);
466 size->is_custom = !found;
467 size->is_ipp = found;
468
469 g_free (display_name);
470
471 return size;
472}
473
474/**
475 * ctk_paper_size_new_custom:
476 * @name: the paper name
477 * @display_name: the human-readable name
478 * @width: the paper width, in units of @unit
479 * @height: the paper height, in units of @unit
480 * @unit: the unit for @width and @height. not %CTK_UNIT_NONE.
481 *
482 * Creates a new #CtkPaperSize object with the
483 * given parameters.
484 *
485 * Returns: a new #CtkPaperSize object, use ctk_paper_size_free()
486 * to free it
487 *
488 * Since: 2.10
489 */
490CtkPaperSize *
491ctk_paper_size_new_custom (const gchar *name,
492 const gchar *display_name,
493 gdouble width,
494 gdouble height,
495 CtkUnit unit)
496{
497 CtkPaperSize *size;
498 g_return_val_if_fail (name != NULL, NULL)do { if ((name != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "name != NULL"); return (
((void*)0)); } } while (0)
;
499 g_return_val_if_fail (unit != CTK_UNIT_NONE, NULL)do { if ((unit != CTK_UNIT_NONE)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "unit != CTK_UNIT_NONE")
; return (((void*)0)); } } while (0)
;
500
501 size = g_slice_new0 (CtkPaperSize)((CtkPaperSize*) g_slice_alloc0 (sizeof (CtkPaperSize)));
502
503 size->name = g_strdup (name)g_strdup_inline (name);
504 size->display_name = g_strdup (display_name)g_strdup_inline (display_name);
505 size->is_custom = TRUE(!(0));
506
507 size->width = _ctk_print_convert_to_mm (width, unit);
508 size->height = _ctk_print_convert_to_mm (height, unit);
509
510 return size;
511}
512
513/**
514 * ctk_paper_size_copy:
515 * @other: a #CtkPaperSize
516 *
517 * Copies an existing #CtkPaperSize.
518 *
519 * Returns: a copy of @other
520 *
521 * Since: 2.10
522 */
523CtkPaperSize *
524ctk_paper_size_copy (CtkPaperSize *other)
525{
526 CtkPaperSize *size;
527
528 size = g_slice_new0 (CtkPaperSize)((CtkPaperSize*) g_slice_alloc0 (sizeof (CtkPaperSize)));
529
530 size->info = other->info;
531 if (other->name)
532 size->name = g_strdup (other->name)g_strdup_inline (other->name);
533 if (other->display_name)
534 size->display_name = g_strdup (other->display_name)g_strdup_inline (other->display_name);
535 if (other->ppd_name)
536 size->ppd_name = g_strdup (other->ppd_name)g_strdup_inline (other->ppd_name);
537
538 size->width = other->width;
539 size->height = other->height;
540 size->is_custom = other->is_custom;
541 size->is_ipp = other->is_ipp;
542
543 return size;
544}
545
546/**
547 * ctk_paper_size_free:
548 * @size: a #CtkPaperSize
549 *
550 * Free the given #CtkPaperSize object.
551 *
552 * Since: 2.10
553 */
554void
555ctk_paper_size_free (CtkPaperSize *size)
556{
557 g_free (size->name);
558 g_free (size->display_name);
559 g_free (size->ppd_name);
560
561 g_slice_free (CtkPaperSize, size)do { if (1) g_slice_free1 (sizeof (CtkPaperSize), (size)); else
(void) ((CtkPaperSize*) 0 == (size)); } while (0)
;
562}
563
564/**
565 * ctk_paper_size_is_equal:
566 * @size1: a #CtkPaperSize object
567 * @size2: another #CtkPaperSize object
568 *
569 * Compares two #CtkPaperSize objects.
570 *
571 * Returns: %TRUE, if @size1 and @size2
572 * represent the same paper size
573 *
574 * Since: 2.10
575 */
576gboolean
577ctk_paper_size_is_equal (CtkPaperSize *size1,
578 CtkPaperSize *size2)
579{
580 if (size1->info != NULL((void*)0) && size2->info != NULL((void*)0))
581 return size1->info == size2->info;
582
583 return strcmp (ctk_paper_size_get_name (size1),
584 ctk_paper_size_get_name (size2)) == 0;
585}
586
587/**
588 * ctk_paper_size_get_paper_sizes:
589 * @include_custom: whether to include custom paper sizes
590 * as defined in the page setup dialog
591 *
592 * Creates a list of known paper sizes.
593 *
594 * Returns: (element-type CtkPaperSize) (transfer full): a newly allocated list of newly
595 * allocated #CtkPaperSize objects
596 *
597 * Since: 2.12
598 */
599GList *
600ctk_paper_size_get_paper_sizes (gboolean include_custom)
601{
602 GList *list = NULL((void*)0);
603 guint i;
604/* _ctk_load_custom_papers() only on Unix so far */
605#ifdef G_OS_UNIX
606 if (include_custom)
607 {
608 GList *page_setups, *l;
609
610 page_setups = _ctk_load_custom_papers ();
611 for (l = page_setups; l != NULL((void*)0); l = l->next)
612 {
613 CtkPageSetup *setup = (CtkPageSetup *) l->data;
614 CtkPaperSize *size;
615
616 size = ctk_page_setup_get_paper_size (setup);
617 list = g_list_prepend (list, ctk_paper_size_copy (size));
618 }
619
620 g_list_free_full (page_setups, g_object_unref);
621 }
622#endif
623 for (i = 0; i < G_N_ELEMENTS (standard_names_offsets)(sizeof (standard_names_offsets) / sizeof ((standard_names_offsets
)[0]))
; ++i)
624 {
625 CtkPaperSize *size;
626
627 size = ctk_paper_size_new_from_info (&standard_names_offsets[i]);
628 list = g_list_prepend (list, size);
629 }
630
631 return g_list_reverse (list);
632}
633
634
635/**
636 * ctk_paper_size_get_name:
637 * @size: a #CtkPaperSize object
638 *
639 * Gets the name of the #CtkPaperSize.
640 *
641 * Returns: the name of @size
642 *
643 * Since: 2.10
644 */
645const gchar *
646ctk_paper_size_get_name (CtkPaperSize *size)
647{
648 if (size->name)
649 return size->name;
650 g_assert (size->info != NULL)do { if (size->info != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkpapersize.c", 650, ((const char*) (__func__)), "size->info != NULL"
); } while (0)
;
651 return paper_names + size->info->name;
652}
653
654/**
655 * ctk_paper_size_get_display_name:
656 * @size: a #CtkPaperSize object
657 *
658 * Gets the human-readable name of the #CtkPaperSize.
659 *
660 * Returns: the human-readable name of @size
661 *
662 * Since: 2.10
663 */
664const gchar *
665ctk_paper_size_get_display_name (CtkPaperSize *size)
666{
667 const gchar *display_name;
668
669 if (size->display_name)
670 return size->display_name;
671
672 g_assert (size->info != NULL)do { if (size->info != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkpapersize.c", 672, ((const char*) (__func__)), "size->info != NULL"
); } while (0)
;
673
674 display_name = paper_names + size->info->display_name;
675 return g_dpgettext2 (GETTEXT_PACKAGE"ctk30", "paper size", display_name);
676}
677
678/**
679 * ctk_paper_size_get_ppd_name:
680 * @size: a #CtkPaperSize object
681 *
682 * Gets the PPD name of the #CtkPaperSize, which
683 * may be %NULL.
684 *
685 * Returns: the PPD name of @size
686 *
687 * Since: 2.10
688 */
689const gchar *
690ctk_paper_size_get_ppd_name (CtkPaperSize *size)
691{
692 if (size->ppd_name)
693 return size->ppd_name;
694 if (size->info)
695 return paper_names + size->info->ppd_name;
696 return NULL((void*)0);
697}
698
699/**
700 * ctk_paper_size_get_width:
701 * @size: a #CtkPaperSize object
702 * @unit: the unit for the return value, not %CTK_UNIT_NONE
703 *
704 * Gets the paper width of the #CtkPaperSize, in
705 * units of @unit.
706 *
707 * Returns: the paper width
708 *
709 * Since: 2.10
710 */
711gdouble
712ctk_paper_size_get_width (CtkPaperSize *size,
713 CtkUnit unit)
714{
715 return _ctk_print_convert_from_mm (size->width, unit);
716}
717
718/**
719 * ctk_paper_size_get_height:
720 * @size: a #CtkPaperSize object
721 * @unit: the unit for the return value, not %CTK_UNIT_NONE
722 *
723 * Gets the paper height of the #CtkPaperSize, in
724 * units of @unit.
725 *
726 * Returns: the paper height
727 *
728 * Since: 2.10
729 */
730gdouble
731ctk_paper_size_get_height (CtkPaperSize *size,
732 CtkUnit unit)
733{
734 return _ctk_print_convert_from_mm (size->height, unit);
735}
736
737/**
738 * ctk_paper_size_is_custom:
739 * @size: a #CtkPaperSize object
740 *
741 * Returns %TRUE if @size is not a standard paper size.
742 *
743 * Returns: whether @size is a custom paper size.
744 **/
745gboolean
746ctk_paper_size_is_custom (CtkPaperSize *size)
747{
748 return size->is_custom;
749}
750
751/**
752 * ctk_paper_size_is_ipp:
753 * @size: a #CtkPaperSize object
754 *
755 * Returns %TRUE if @size is an IPP standard paper size.
756 *
757 * Returns: whether @size is not an IPP custom paper size.
758 **/
759gboolean
760ctk_paper_size_is_ipp (CtkPaperSize *size)
761{
762 return size->is_ipp;
763}
764
765/**
766 * ctk_paper_size_set_size:
767 * @size: a custom #CtkPaperSize object
768 * @width: the new width in units of @unit
769 * @height: the new height in units of @unit
770 * @unit: the unit for @width and @height
771 *
772 * Changes the dimensions of a @size to @width x @height.
773 *
774 * Since: 2.10
775 */
776void
777ctk_paper_size_set_size (CtkPaperSize *size,
778 gdouble width,
779 gdouble height,
780 CtkUnit unit)
781{
782 g_return_if_fail (size != NULL)do { if ((size != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "size != NULL"); return;
} } while (0)
;
783 g_return_if_fail (size->is_custom)do { if ((size->is_custom)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "size->is_custom"); return
; } } while (0)
;
784
785 size->width = _ctk_print_convert_to_mm (width, unit);
786 size->height = _ctk_print_convert_to_mm (height, unit);
787}
788
789#define NL_PAPER_GET(x)((union { char *string; unsigned int word; })nl_langinfo(x)).
word
\
790 ((union { char *string; unsigned int word; })nl_langinfo(x)).word
791
792/**
793 * ctk_paper_size_get_default:
794 *
795 * Returns the name of the default paper size, which
796 * depends on the current locale.
797 *
798 * Returns: the name of the default paper size. The string
799 * is owned by CTK+ and should not be modified.
800 *
801 * Since: 2.10
802 */
803const gchar *
804ctk_paper_size_get_default (void)
805{
806 char *locale, *freeme = NULL((void*)0);
807 const char *paper_size;
808
809#if defined(HAVE__NL_PAPER_HEIGHT1) && defined(HAVE__NL_PAPER_WIDTH1)
810 {
811 int width = NL_PAPER_GET (_NL_PAPER_WIDTH)((union { char *string; unsigned int word; })nl_langinfo(_NL_PAPER_WIDTH
)).word
;
812 int height = NL_PAPER_GET (_NL_PAPER_HEIGHT)((union { char *string; unsigned int word; })nl_langinfo(_NL_PAPER_HEIGHT
)).word
;
813
814 if (width == 210 && height == 297)
815 return CTK_PAPER_NAME_A4"iso_a4";
816
817 if (width == 216 && height == 279)
818 return CTK_PAPER_NAME_LETTER"na_letter";
819 }
820#endif
821
822#ifdef G_OS_WIN32
823 freeme = locale = g_win32_getlocale ();
824#elif defined(LC_PAPER7)
825 locale = setlocale(LC_PAPER7, NULL((void*)0));
826#else
827 locale = setlocale(LC_MESSAGES5, NULL((void*)0));
828#endif
829
830 if (!locale)
831 return CTK_PAPER_NAME_A4"iso_a4";
832
833 /* CLDR 1.8.1
834 * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/territory_language_information.html
835 */
836 if (g_regex_match_simple("[^_.@]{2,3}_(BZ|CA|CL|CO|CR|GT|MX|NI|PA|PH|PR|SV|US|VE)",
837 locale, G_REGEX_ANCHORED, G_REGEX_MATCH_ANCHORED))
838 paper_size = CTK_PAPER_NAME_LETTER"na_letter";
839 else
840 paper_size = CTK_PAPER_NAME_A4"iso_a4";
841
842 g_free (freeme);
843 return paper_size;
844}
845
846/* These get the default margins used for the paper size. Its
847 * larger than most printers margins, so that it will be within
848 * the imageble area on any printer.
849 *
850 * I’ve taken the actual values used from the OSX page setup dialog.
851 * I’m not sure exactly where they got these values for, but might
852 * correspond to this (from ghostscript docs):
853 *
854 * All DeskJets have 0.5 inches (1.27cm) of unprintable bottom margin,
855 * due to the mechanical arrangement used to grab the paper. Side margins
856 * are approximately 0.25 inches (0.64cm) for U.S. letter paper, and 0.15
857 * inches (0.38cm) for A4.
858 */
859
860/**
861 * ctk_paper_size_get_default_top_margin:
862 * @size: a #CtkPaperSize object
863 * @unit: the unit for the return value, not %CTK_UNIT_NONE
864 *
865 * Gets the default top margin for the #CtkPaperSize.
866 *
867 * Returns: the default top margin
868 *
869 * Since: 2.10
870 */
871gdouble
872ctk_paper_size_get_default_top_margin (CtkPaperSize *size G_GNUC_UNUSED__attribute__ ((__unused__)),
873 CtkUnit unit)
874{
875 gdouble margin;
876
877 margin = _ctk_print_convert_to_mm (0.25, CTK_UNIT_INCH);
878 return _ctk_print_convert_from_mm (margin, unit);
879}
880
881/**
882 * ctk_paper_size_get_default_bottom_margin:
883 * @size: a #CtkPaperSize object
884 * @unit: the unit for the return value, not %CTK_UNIT_NONE
885 *
886 * Gets the default bottom margin for the #CtkPaperSize.
887 *
888 * Returns: the default bottom margin
889 *
890 * Since: 2.10
891 */
892gdouble
893ctk_paper_size_get_default_bottom_margin (CtkPaperSize *size,
894 CtkUnit unit)
895{
896 gdouble margin;
897 const gchar *name;
898
899 margin = _ctk_print_convert_to_mm (0.25, CTK_UNIT_INCH);
900
901 name = ctk_paper_size_get_name (size);
902 if (strcmp (name, "na_letter") == 0 ||
903 strcmp (name, "na_legal") == 0 ||
904 strcmp (name, "iso_a4") == 0)
905 margin = _ctk_print_convert_to_mm (0.56, CTK_UNIT_INCH);
906
907 return _ctk_print_convert_from_mm (margin, unit);
908}
909
910/**
911 * ctk_paper_size_get_default_left_margin:
912 * @size: a #CtkPaperSize object
913 * @unit: the unit for the return value, not %CTK_UNIT_NONE
914 *
915 * Gets the default left margin for the #CtkPaperSize.
916 *
917 * Returns: the default left margin
918 *
919 * Since: 2.10
920 */
921gdouble
922ctk_paper_size_get_default_left_margin (CtkPaperSize *size G_GNUC_UNUSED__attribute__ ((__unused__)),
923 CtkUnit unit)
924{
925 gdouble margin;
926
927 margin = _ctk_print_convert_to_mm (0.25, CTK_UNIT_INCH);
928 return _ctk_print_convert_from_mm (margin, unit);
929}
930
931/**
932 * ctk_paper_size_get_default_right_margin:
933 * @size: a #CtkPaperSize object
934 * @unit: the unit for the return value, not %CTK_UNIT_NONE
935 *
936 * Gets the default right margin for the #CtkPaperSize.
937 *
938 * Returns: the default right margin
939 *
940 * Since: 2.10
941 */
942gdouble
943ctk_paper_size_get_default_right_margin (CtkPaperSize *size G_GNUC_UNUSED__attribute__ ((__unused__)),
944 CtkUnit unit)
945{
946 gdouble margin;
947
948 margin = _ctk_print_convert_to_mm (0.25, CTK_UNIT_INCH);
949 return _ctk_print_convert_from_mm (margin, unit);
950}
951
952/**
953 * ctk_paper_size_new_from_key_file:
954 * @key_file: the #GKeyFile to retrieve the papersize from
955 * @group_name: (nullable): the name of the group in the key file to read,
956 * or %NULL to read the first group
957 * @error: (allow-none): return location for an error, or %NULL
958 *
959 * Reads a paper size from the group @group_name in the key file
960 * @key_file.
961 *
962 * Returns: a new #CtkPaperSize object with the restored
963 * paper size, or %NULL if an error occurred
964 *
965 * Since: 2.12
966 */
967CtkPaperSize *
968ctk_paper_size_new_from_key_file (GKeyFile *key_file,
969 const gchar *group_name,
970 GError **error)
971{
972 CtkPaperSize *paper_size = NULL((void*)0);
973 gchar *name = NULL((void*)0);
974 gchar *ppd_name = NULL((void*)0);
975 gchar *display_name = NULL((void*)0);
976 gchar *freeme = NULL((void*)0);
977 gdouble width, height;
978 GError *err = NULL((void*)0);
979
980 g_return_val_if_fail (key_file != NULL, NULL)do { if ((key_file != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "key_file != NULL"); return
(((void*)0)); } } while (0)
;
981
982 if (!group_name)
983 group_name = freeme = g_key_file_get_start_group (key_file);
984 if (!group_name || !g_key_file_has_group (key_file, group_name))
985 {
986 g_set_error_literal (error,
987 CTK_PRINT_ERRORctk_print_error_quark (),
988 CTK_PRINT_ERROR_INVALID_FILE,
989 _("Not a valid page setup file")((char *) g_dgettext ("ctk30", "Not a valid page setup file")
)
);
990 goto out;
991 }
992
993#define GET_DOUBLE(kf, group, name, v) \
994 v = g_key_file_get_double (kf, group, name, &err); \
995 if (err != NULL((void*)0)) \
996 {\
997 g_propagate_error (error, err);\
998 goto out;\
999 }
1000
1001 GET_DOUBLE (key_file, group_name, "Width", width);
1002 GET_DOUBLE (key_file, group_name, "Height", height);
1003
1004#undef GET_DOUBLE
1005
1006 name = g_key_file_get_string (key_file, group_name,
1007 "Name", NULL((void*)0));
1008 ppd_name = g_key_file_get_string (key_file, group_name,
1009 "PPDName", NULL((void*)0));
1010 display_name = g_key_file_get_string (key_file, group_name,
1011 "DisplayName", NULL((void*)0));
1012 /* Fallback for old ~/.ctk-custom-paper entries */
1013 if (!display_name)
1014 display_name = g_strdup (name)g_strdup_inline (name);
1015
1016 if (ppd_name != NULL((void*)0))
1017 paper_size = ctk_paper_size_new_from_ppd (ppd_name,
1018 display_name,
1019 _ctk_print_convert_from_mm (width, CTK_UNIT_POINTS),
1020 _ctk_print_convert_from_mm (height, CTK_UNIT_POINTS));
1021 else if (name != NULL((void*)0))
1022 paper_size = ctk_paper_size_new_custom (name, display_name,
1023 width, height, CTK_UNIT_MM);
1024 else
1025 {
1026 g_set_error_literal (error,
1027 CTK_PRINT_ERRORctk_print_error_quark (),
1028 CTK_PRINT_ERROR_INVALID_FILE,
1029 _("Not a valid page setup file")((char *) g_dgettext ("ctk30", "Not a valid page setup file")
)
);
1030 goto out;
1031 }
1032
1033 g_assert (paper_size != NULL)do { if (paper_size != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkpapersize.c", 1033, ((const char*) (__func__)), "paper_size != NULL"
); } while (0)
;
1034
1035out:
1036 g_free (ppd_name);
1037 g_free (name);
1038 g_free (display_name);
1039 g_free (freeme);
1040
1041 return paper_size;
1042}
1043
1044/**
1045 * ctk_paper_size_to_key_file:
1046 * @size: a #CtkPaperSize
1047 * @key_file: the #GKeyFile to save the paper size to
1048 * @group_name: the group to add the settings to in @key_file
1049 *
1050 * This function adds the paper size from @size to @key_file.
1051 *
1052 * Since: 2.12
1053 */
1054void
1055ctk_paper_size_to_key_file (CtkPaperSize *size,
1056 GKeyFile *key_file,
1057 const gchar *group_name)
1058{
1059 const char *name, *ppd_name, *display_name;
1060
1061 g_return_if_fail (size != NULL)do { if ((size != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "size != NULL"); return;
} } while (0)
;
1062 g_return_if_fail (key_file != NULL)do { if ((key_file != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "key_file != NULL"); return
; } } while (0)
;
1063
1064 name = ctk_paper_size_get_name (size);
1065 display_name = ctk_paper_size_get_display_name (size);
1066 ppd_name = ctk_paper_size_get_ppd_name (size);
1067
1068 if (ppd_name != NULL((void*)0))
1069 g_key_file_set_string (key_file, group_name,
1070 "PPDName", ppd_name);
1071 else
1072 g_key_file_set_string (key_file, group_name,
1073 "Name", name);
1074
1075 if (display_name)
1076 g_key_file_set_string (key_file, group_name,
1077 "DisplayName", display_name);
1078
1079 g_key_file_set_double (key_file, group_name,
1080 "Width", ctk_paper_size_get_width (size, CTK_UNIT_MM));
1081 g_key_file_set_double (key_file, group_name,
1082 "Height", ctk_paper_size_get_height (size, CTK_UNIT_MM));
1083}
1084
1085/**
1086 * ctk_paper_size_to_gvariant:
1087 * @paper_size: a #CtkPaperSize
1088 *
1089 * Serialize a paper size to an a{sv} variant.
1090 *
1091 * Returns: (transfer none): a new, floating, #GVariant
1092 *
1093 * Since: 3.22
1094 */
1095GVariant *
1096ctk_paper_size_to_gvariant (CtkPaperSize *paper_size)
1097{
1098 const char *name;
1099 const char *ppd_name;
1100 const char *display_name;
1101 GVariantBuilder builder;
1102
1103 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT((const GVariantType *) "a{sv}"));
1104
1105 name = ctk_paper_size_get_name (paper_size);
1106 ppd_name = ctk_paper_size_get_ppd_name (paper_size);
1107 display_name = ctk_paper_size_get_display_name (paper_size);
1108
1109 if (ppd_name != NULL((void*)0))
1110 g_variant_builder_add (&builder, "{sv}", "PPDName", g_variant_new_string (ppd_name));
1111 else
1112 g_variant_builder_add (&builder, "{sv}", "Name", g_variant_new_string (name));
1113
1114 if (display_name != NULL((void*)0))
1115 g_variant_builder_add (&builder, "{sv}", "DisplayName", g_variant_new_string (display_name));
1116
1117 g_variant_builder_add (&builder, "{sv}", "Width", g_variant_new_double (ctk_paper_size_get_width (paper_size, CTK_UNIT_MM)));
1118 g_variant_builder_add (&builder, "{sv}", "Height", g_variant_new_double (ctk_paper_size_get_height (paper_size, CTK_UNIT_MM)));
1119
1120 return g_variant_builder_end (&builder);
1121}
1122
1123/**
1124 * ctk_paper_size_new_from_gvariant:
1125 * @variant: an a{sv} #GVariant
1126 *
1127 * Deserialize a paper size from an a{sv} variant in
1128 * the format produced by ctk_paper_size_to_gvariant().
1129 *
1130 * Returns: (transfer full): a new #CtkPaperSize object
1131 *
1132 * Since: 3.22
1133 */
1134CtkPaperSize *
1135ctk_paper_size_new_from_gvariant (GVariant *variant)
1136{
1137 CtkPaperSize *paper_size;
1138 const char *name;
1139 const char *ppd_name;
1140 const char *display_name;
1141 gdouble width, height;
1142
1143 g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL)do { if ((g_variant_is_of_type (variant, ((const GVariantType
*) "a{sv}")))) { } else { g_return_if_fail_warning ("Ctk", (
(const char*) (__func__)), "g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT)"
); return (((void*)0)); } } while (0)
;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
1144
1145 if (!g_variant_lookup (variant, "Width", "d", &width) ||
1146 !g_variant_lookup (variant, "Height", "d", &height))
1147 return NULL((void*)0);
1148
1149 if (!g_variant_lookup (variant, "Name", "&s", &name))
1150 name = NULL((void*)0);
1151
1152 if (!g_variant_lookup (variant, "PPDName", "&s", &ppd_name))
1153 ppd_name = NULL((void*)0);
1154
1155 if (!g_variant_lookup (variant, "DisplayName", "&s", &display_name))
1156 display_name = name;
1157
1158 if (ppd_name != NULL((void*)0))
1159 paper_size = ctk_paper_size_new_from_ppd (ppd_name,
1160 display_name,
1161 _ctk_print_convert_from_mm (width, CTK_UNIT_POINTS),
1162 _ctk_print_convert_from_mm (height, CTK_UNIT_POINTS));
1163 else if (name != NULL((void*)0))
1164 paper_size = ctk_paper_size_new_custom (name, display_name,
1165 width, height, CTK_UNIT_MM);
1166 else
1167 paper_size = NULL((void*)0);
1168
1169 return paper_size;
1170}