1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
5 * Copyright (C) 2002-2006 Jody Goldberg (jody@gnome.org)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2.1 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
22 #include <gsf-config.h>
23 #include <gsf/gsf-utils.h>
24 #include <gsf/gsf-input.h>
25 #include <gsf/gsf-doc-meta-data.h>
26 #include <gsf/gsf-docprop-vector.h>
27 #include <gsf/gsf-impl-utils.h>
29 #include <gsf/gsf-infile.h>
30 #include <gsf/gsf-infile-msole.h>
31 #include <gsf/gsf-infile-msvba.h>
32 #include <gsf/gsf-infile-stdio.h>
33 #include <gsf/gsf-infile-zip.h>
35 #include <gsf/gsf-input.h>
36 #include <gsf/gsf-input-gzip.h>
37 #include <gsf/gsf-input-http.h>
38 #include <gsf/gsf-input-memory.h>
39 #include <gsf/gsf-input-proxy.h>
40 #include <gsf/gsf-input-stdio.h>
41 #include <gsf/gsf-input-textline.h>
43 #include <gsf/gsf-output.h>
44 #include <gsf/gsf-output-bzip.h>
45 #include <gsf/gsf-output-csv.h>
46 #include <gsf/gsf-output-gzip.h>
47 #include <gsf/gsf-output-iconv.h>
48 #include <gsf/gsf-output-iochannel.h>
49 #include <gsf/gsf-output-memory.h>
50 #include <gsf/gsf-output-stdio.h>
52 #include <gsf/gsf-outfile.h>
53 #include <gsf/gsf-outfile-msole.h>
54 #include <gsf/gsf-outfile-stdio.h>
55 #include <gsf/gsf-outfile-zip.h>
57 #include <gsf/gsf-libxml.h>
58 #include <gsf/gsf-blob.h>
59 #include <gsf/gsf-structured-blob.h>
60 #include <gsf/gsf-shared-memory.h>
61 #include <gsf/gsf-clip-data.h>
62 #include <gsf/gsf-open-pkg-utils.h>
64 #include <gobject/gvaluecollector.h>
65 #include <glib/gi18n-lib.h>
72 * Glib gets this wrong, really. ARM's floating point format is a weird
75 #define G_ARMFLOAT_ENDIAN 56781234
76 #if defined(__arm__) && !defined(__ARM_EABI__) && (G_BYTE_ORDER == G_LITTLE_ENDIAN)
77 #define G_FLOAT_BYTE_ORDER G_ARMFLOAT_ENDIAN
79 #define G_FLOAT_BYTE_ORDER G_BYTE_ORDER
83 gsf_debug_flag (const char *flag)
86 key.key = (char *)flag;
89 return g_parse_debug_string (g_getenv ("GSF_DEBUG"), &key, 1) != 0;
93 #ifndef HAVE_G_BASE64_ENCODE
94 static void base64_init (void);
97 #ifdef _GSF_GTYPE_THREADING_FIXED
98 typedef GTypeModule GsfDummyTypeModule;
99 typedef GTypeModuleClass GsfDummyTypeModuleClass;
101 gsf_dummy_type_module_load (GTypeModule *module)
103 gsf_init_dynamic (module);
107 gsf_dummy_type_module_class_init (GTypeModuleClass *gtm_class)
109 gtm_class->load = gsf_dummy_type_module_load;
111 static GSF_CLASS (GsfDummyTypeModule, gsf_dummy_type_module,
112 gsf_dummy_type_module_class_init, NULL,
115 static GTypeModule *static_type_module = NULL;
120 static HMODULE gsf_dll_hmodule;
122 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
124 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, G_GNUC_UNUSED LPVOID lpvReserved)
126 if (fdwReason == DLL_PROCESS_ATTACH) gsf_dll_hmodule = hinstDLL;
134 * Initializes the GSF library
139 static gboolean libgsf_initialized = FALSE;
140 if (libgsf_initialized)
146 char *pkg_dir = g_win32_get_package_installation_directory_of_module (gsf_dll_hmodule);
147 gchar *locale_dir = g_build_filename (pkg_dir, "lib/locale", NULL);
148 bindtextdomain (GETTEXT_PACKAGE, locale_dir);
153 bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
155 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
159 #ifndef HAVE_G_BASE64_ENCODE
163 #ifdef _GSF_GTYPE_THREADING_FIXED
164 if (NULL == static_type_module) {
165 static_type_module = g_object_new (gsf_dummy_type_module_get_type(), NULL);
166 g_assert (static_type_module != NULL);
167 g_type_module_use (static_type_module);
168 g_type_module_set_name (static_type_module, "libgsf-builtin");
171 gsf_init_dynamic (NULL);
175 /* Little-endian representation of M_PI. */
176 static guint8 pibytes[8] = {
177 0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40
182 * http://bugzilla.gnome.org/show_bug.cgi?id=350973
184 double pi = gsf_le_get_double (pibytes);
185 if (!(pi > 3.14 && pi < 3.15))
186 g_error ("Compilation trouble with endianess.");
193 * De-intializes the GSF library
194 * Currently does nothing.
201 #ifdef _GSF_GTYPE_THREADING_FIXED
202 #define REGISTER(prefix) \
204 prefix ## _register_type (module); \
205 types = g_slist_prepend (types, \
206 g_type_class_ref (prefix ## _get_type())); \
209 /* Assign the value to avoid compiler warnings */
210 #define REGISTER(prefix) t = prefix ## _get_type()
215 * @module : #GTypeModule.
217 * Initializes the GSF library and associates it with a type module @mod.
220 gsf_init_dynamic (GTypeModule *module)
222 #ifndef _GSF_GTYPE_THREADING_FIXED
224 if (NULL != module) {
225 g_warning ("glib's support of dynamic types is not thread safe.\n"
226 "Support for gsf_init_dynamic has been disabled until that is fixed");
229 REGISTER (gsf_input);
230 REGISTER (gsf_input_gzip);
231 REGISTER (gsf_input_http);
232 REGISTER (gsf_input_memory);
233 REGISTER (gsf_input_proxy);
234 REGISTER (gsf_input_stdio);
235 REGISTER (gsf_input_textline);
237 REGISTER (gsf_infile);
238 REGISTER (gsf_infile_msole);
239 REGISTER (gsf_infile_msvba);
240 REGISTER (gsf_infile_stdio);
241 REGISTER (gsf_infile_zip);
243 REGISTER (gsf_output);
244 REGISTER (gsf_output_bzip);
245 REGISTER (gsf_output_csv_quoting_mode);
246 REGISTER (gsf_output_csv);
247 REGISTER (gsf_output_gzip);
248 REGISTER (gsf_output_iconv);
249 REGISTER (gsf_output_iochannel);
250 REGISTER (gsf_output_memory);
251 REGISTER (gsf_output_stdio);
253 REGISTER (gsf_outfile);
254 REGISTER (gsf_outfile_msole);
255 REGISTER (gsf_outfile_stdio);
256 REGISTER (gsf_outfile_zip);
257 REGISTER (gsf_outfile_open_pkg);
259 REGISTER (gsf_shared_memory);
260 REGISTER (gsf_structured_blob);
261 REGISTER (gsf_xml_out);
263 REGISTER (gsf_clip_data);
264 REGISTER (gsf_doc_meta_data);
265 REGISTER (gsf_docprop_vector);
271 * De-intializes the GSF library from a type module.
272 * Currently does nothing.
275 gsf_shutdown_dynamic (G_GNUC_UNUSED GTypeModule *module)
280 gsf_mem_dump_full (guint8 const *ptr, size_t len, gsf_off_t offset)
282 static const char hexdigit[16] = "0123456789abcdef";
285 char hexpart[3 * 16 + 1], *phex = hexpart;
288 for (j = 0; j < 16; j++) {
290 *phex++ = hexdigit[*ptr >> 4];
291 *phex++ = hexdigit[*ptr & 0xf];
292 pic[j] = (*ptr >= '!' && *ptr < 127 ? *ptr : '.');
305 g_print ("%8lx | %s| %s\n", (long)offset, hexpart, pic);
312 * @ptr: memory area to be dumped.
313 * @len: how many bytes will be dumped.
315 * Dump @len bytes from the memory location given by @ptr.
318 gsf_mem_dump (guint8 const *ptr, size_t len)
320 gsf_mem_dump_full (ptr, len, 0);
325 * @input: a #GsfInput
326 * @dump_as_hex: If %TRUE, dump in hexidecmal format
328 * Dumps @input's contents to STDOUT, optionally in hex format.
331 gsf_input_dump (GsfInput *input, gboolean dump_as_hex)
333 gsf_off_t offset = 0;
337 /* read in small blocks to excercise things */
338 size = gsf_input_size (GSF_INPUT (input));
343 data = gsf_input_read (GSF_INPUT (input), count, NULL);
344 g_return_if_fail (data != NULL);
346 gsf_mem_dump_full (data, count, offset);
348 fwrite (data, 1, count, stdout);
358 * @p: pointer to storage
360 * Interpret binary data as a guint64 (8 byte unsigned integer type) in little
363 * Returns: interpreted data
366 gsf_le_get_guint64 (void const *p)
368 #if G_BYTE_ORDER == G_BIG_ENDIAN
369 if (sizeof (guint64) == 8) {
372 guint8 *t = (guint8 *)&li;
373 guint8 *p2 = (guint8 *)p;
374 int sd = sizeof (li);
376 for (i = 0; i < sd; i++)
377 t[i] = p2[sd - 1 - i];
381 g_error ("Big endian machine, but weird size of guint64");
383 #elif G_BYTE_ORDER == G_LITTLE_ENDIAN
384 if (sizeof (guint64) == 8) {
386 * On i86, we could access directly, but Alphas require
390 memcpy (&data, p, sizeof (data));
393 g_error ("Little endian machine, but weird size of guint64");
396 #error "Byte order not recognised -- out of luck"
402 * @p: pointer to storage
404 * Interpret binary data as a float in little endian order.
407 * Returns: interpreted data
410 gsf_le_get_float (void const *p)
412 #if G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
413 if (sizeof (float) == 4) {
416 guint8 *t = (guint8 *)&f;
417 guint8 *p2 = (guint8 *)p;
420 for (i = 0; i < sd; i++)
421 t[i] = p2[sd - 1 - i];
425 g_error ("Big endian machine, but weird size of floats");
427 #elif (G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN) || (G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN)
428 if (sizeof (float) == 4) {
430 * On i86, we could access directly, but Alphas require
434 memcpy (&data, p, sizeof (data));
437 g_error ("Little endian machine, but weird size of floats");
440 #error "Floating-point byte order not recognised -- out of luck"
446 * @p: pointer to storage
447 * @f: float to be stored
449 * Store a value of type float in memory in little endian order.
452 gsf_le_set_float (void *p, float f)
454 #if G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
455 if (sizeof (float) == 4) {
457 guint8 *t = (guint8 *)&f;
458 guint8 *p2 = (guint8 *)p;
461 for (i = 0; i < sd; i++)
462 p2[sd - 1 - i] = t[i];
464 g_error ("Big endian machine, but weird size of floats");
466 #elif (G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN) || (G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN)
467 if (sizeof (float) == 4) {
469 * On i86, we could access directly, but Alphas require
472 memcpy (p, &f, sizeof (f));
474 g_error ("Little endian machine, but weird size of floats");
477 #error "Floating-point byte order not recognised -- out of luck"
482 * gsf_le_get_double :
483 * @p: pointer to storage
485 * Interpret binary data as a double in little endian order.
487 * Returns: interpreted data
490 gsf_le_get_double (void const *p)
492 #if G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN
494 memcpy ((char *)&data + 4, p, 4);
495 memcpy ((char *)&data, (char const *)p + 4, 4);
497 #elif G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
498 if (sizeof (double) == 8) {
501 guint8 *t = (guint8 *)&d;
502 guint8 *p2 = (guint8 *)p;
505 for (i = 0; i < sd; i++)
506 t[i] = p2[sd - 1 - i];
510 g_error ("Big endian machine, but weird size of doubles");
512 #elif G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN
513 if (sizeof (double) == 8) {
515 * On i86, we could access directly, but Alphas require
519 memcpy (&data, p, sizeof (data));
522 g_error ("Little endian machine, but weird size of doubles");
525 #error "Floating-point byte order not recognised -- out of luck"
530 * gsf_le_set_double :
531 * @p: pointer to storage
532 * @d: double to be stored
534 * Store a value of type double in memory in little endian order
537 gsf_le_set_double (void *p, double d)
539 #if G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN
540 memcpy (p, (char const *)&d + 4, 4);
541 memcpy ((char *)p + 4, &d, 4);
542 #elif G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
543 if (sizeof (double) == 8) {
545 guint8 *t = (guint8 *)&d;
546 guint8 *p2 = (guint8 *)p;
549 for (i = 0; i < sd; i++)
550 p2[sd - 1 - i] = t[i];
552 g_error ("Big endian machine, but weird size of doubles");
554 #elif G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN
555 if (sizeof (double) == 8) {
557 * On i86, we could access directly, but Alphas require
560 memcpy (p, &d, sizeof (d));
562 g_error ("Little endian machine, but weird size of doubles");
565 #error "Floating-point byte order not recognised -- out of luck"
570 * gsf_extension_pointer:
571 * @path: A filename or file path.
573 * Extracts the extension from the end of a filename (the part after the final
574 * '.' in the filename).
576 * Returns: A pointer to the extension part of the filename, or a
577 * pointer to the end of the string if the filename does not
581 gsf_extension_pointer (char const *path)
585 g_return_val_if_fail (path != NULL, NULL);
587 end = path + strlen (path);
588 for (s = end; s > path; ) {
590 if (G_IS_DIR_SEPARATOR (*s))
601 * @handle : handle to be closed.
603 * A utility wrapper to safely close an iconv handle.
606 gsf_iconv_close (GIConv handle)
608 if (handle != NULL && handle != ((GIConv)-1))
609 g_iconv_close (handle);
613 * gsf_filename_to_utf8:
614 * @filename: file name suitable for open(2).
615 * @quoted: if %TRUE, the resulting utf8 file name will be quoted
616 * (unless it is invalid).
618 * A utility wrapper to make sure filenames are valid utf8.
619 * Caller must g_free the result.
621 * Returns: @filename using utf-8 encoding for display
624 gsf_filename_to_utf8 (char const *filename, gboolean quoted)
626 char *dname = g_filename_display_name (filename);
630 result = g_strconcat ("\"", dname, "\"", NULL);
638 #ifndef HAVE_G_BASE64_ENCODE
639 /***************************************************************************/
640 /* some code taken from evolution/camel/camel-mime-utils.c */
643 * Copyright (C) 2000 Ximian Inc.
645 * Authors: Michael Zucchi <notzed@ximian.com>
646 * Jeffrey Stedfast <fejj@ximian.com>
648 * This program is free software; you can redistribute it and/or
649 * modify it under the terms of version 2 of the GNU Lesser General Public
650 * License as published by the Free Software Foundation.
652 * This program is distributed in the hope that it will be useful,
653 * but WITHOUT ANY WARRANTY; without even the implied warranty of
654 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
655 * General Public License for more details.
657 * You should have received a copy of the GNU General Public
658 * License along with this program; if not, write to the
659 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
660 * Boston, MA 02110-1301 USA
663 /* dont touch this file without my permission - Michael */
664 static guint8 camel_mime_base64_rank[256];
665 static char const *base64_alphabet =
666 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
670 /* Line length for base64 encoding. Must be a multiple of 4. */
671 enum { BASE64_LINE_LEN = 76 };
678 memset(camel_mime_base64_rank, 0xff, sizeof(camel_mime_base64_rank));
680 camel_mime_base64_rank[(unsigned int)base64_alphabet[i]] = i;
682 camel_mime_base64_rank['='] = 0;
687 * gsf_base64_encode_close :
688 * @in : Data to be encoded
689 * @inlen : Length of data to be encoded
690 * @break_lines : Whether to use line breaks
691 * @out : Encoded data.
692 * @state: holds the number of bits that are stored in @save
693 * @save: leftover bits that have not yet been decoded
695 * This funcion should be called to when finished encoding everything, to
696 * flush off the last little bit.
698 * Returns: a count of the number of bytes in the final block.
701 gsf_base64_encode_close (guint8 const *in, size_t inlen,
702 gboolean break_lines, guint8 *out, int *state, unsigned int *save)
704 guint8 *outptr = out;
705 #ifdef HAVE_G_BASE64_ENCODE
707 outptr += gsf_base64_encode_step (in, inlen, break_lines,
708 outptr, state, save);
709 outptr += g_base64_encode_close (break_lines, outptr, state, save);
714 outptr += gsf_base64_encode_step(in, inlen, break_lines, outptr, state, save);
716 c1 = ((guint8 *)save)[1];
717 c2 = ((guint8 *)save)[2];
719 d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
720 (int)((char *)save)[0],
721 (int)((char *)save)[1],
722 (int)((char *)save)[2]));
724 switch (((char *)save)[0]) {
726 outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
727 g_assert(outptr[2] != 0);
732 outptr[0] = base64_alphabet[ c1 >> 2 ];
733 outptr[1] = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )];
739 if (break_lines && *state > 0)
750 * gsf_base64_encode_step :
752 * @len : max length of data to decode
753 * @break_lines : Whether to use line breaks
754 * @out : output stream
755 * @state : holds the number of bits that are stored in @save
756 * @save : leftover bits that have not yet been decoded
758 * Performs an 'encode step', only encodes blocks of 3 characters from @in into
759 * the output @out at a time, saves left-over state in @state and @save
760 * (initialise to 0 on first invocation).
762 * Returns: the number of bytes encoded
765 gsf_base64_encode_step (guint8 const *in, size_t len,
766 gboolean break_lines, guint8 *out, int *state, unsigned int *save)
768 #ifdef HAVE_G_BASE64_ENCODE
769 return g_base64_encode_step (in, len, break_lines, out, state, save);
771 register guint8 const *inptr;
772 register guint8 *outptr;
780 d(printf("we have %d chars, and %d saved chars\n", len, ((char *)save)[0]));
782 if (len + ((char *)save)[0] > 2) {
783 guint8 const *inend = in+len-2;
784 register int c1, c2, c3;
785 register int already;
789 switch (((char *)save)[0]) {
790 case 1: c1 = ((guint8 *)save)[1]; goto skip1;
791 case 2: c1 = ((guint8 *)save)[1];
792 c2 = ((guint8 *)save)[2]; goto skip2;
795 /* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */
796 while (inptr < inend) {
802 *outptr++ = base64_alphabet[ c1 >> 2 ];
803 *outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ];
804 *outptr++ = base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ];
805 *outptr++ = base64_alphabet[ c3 & 0x3f ];
806 /* this is a bit ugly ... */
807 if (break_lines && (++already) * 4 >= BASE64_LINE_LEN) {
813 ((char *)save)[0] = 0;
814 len = 2-(inptr-inend);
818 d(printf("state = %d, len = %d\n",
819 (int)((char *)save)[0],
823 register char *saveout;
825 /* points to the slot for the next char to save */
826 saveout = & (((char *)save)[1]) + ((char *)save)[0];
828 /* len can only be 0 1 or 2 */
830 case 2: *saveout++ = *inptr++;
831 case 1: *saveout++ = *inptr++;
833 ((char *)save)[0]+=len;
836 d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
837 (int)((char *)save)[0],
838 (int)((char *)save)[1],
839 (int)((char *)save)[2]));
847 * gsf_base64_decode_step:
849 * @len: max length of data to decode
850 * @out: output stream
851 * @state: holds the number of bits that are stored in @save
852 * @save: leftover bits that have not yet been decoded
854 * Decodes a chunk of base64 encoded data
856 * Returns: the number of bytes converted
859 gsf_base64_decode_step (guint8 const *in, size_t len, guint8 *out,
860 int *state, guint *save)
862 #ifdef HAVE_G_BASE64_ENCODE
863 return g_base64_decode_step (in, len, out, state, save);
865 register guint8 const *inptr;
866 register guint8 *outptr, c;
867 register unsigned int v;
874 /* convert 4 base64 bytes to 3 normal bytes */
878 while (inptr<inend) {
879 c = camel_mime_base64_rank[*inptr++];
895 /* quick scan back for '=' on the end somewhere */
896 /* fortunately we can drop 1 output char for each trailing = (upto 2) */
898 while (inptr>in && i) {
900 if (camel_mime_base64_rank[*inptr] != 0xff) {
901 if (*inptr == '=' && outptr>out)
907 /* if i!= 0 then there is a truncation error! */
913 * gsf_base64_encode_simple :
914 * @data : data stream
915 * @len : max length of data to encode
917 * Encodes data from @data back into @data using base64 encoding.
919 * Returns: the number of bytes encoded
922 gsf_base64_encode_simple (guint8 const *data, size_t len)
927 gboolean break_lines = TRUE; /* This differs from g_base64_encode */
928 size_t outlen = len * 4 / 3 + 5;
931 outlen += outlen / 72 + 1;
932 out = g_new (guint8, outlen);
933 outlen = gsf_base64_encode_close (data, len, break_lines,
940 * gsf_base64_decode_simple :
941 * @data : data stream
942 * @len : max length of data to decode
944 * Decodes a chunk of base64 encoded data from @data back into @data.
946 * Returns: the number of bytes converted
949 gsf_base64_decode_simple (guint8 *data, size_t len)
953 return gsf_base64_decode_step (data, len, data, &state, &save);
957 /* Largely a copy of g_object_new_valist. */
959 * gsf_property_settings_collect_valist:
960 * @object_type: the GType for which the properties are being set.
961 * @p_n_params: a pointer to the number of properties collected. (Used for
962 * both input and output.)
963 * @p_params: a pointer to the GParameter array that holds the properties.
964 * (Used for both input and output. This may point to a %NULL pointer if
965 * there are no properties collected yet.)
966 * @first_property_name: the name of the first property being set, or NULL.
967 * @var_args: a va_list holding the remainder of the property names and
968 * values, terminated by a %NULL.
970 * This function builds a GParameter array suitable for g_object_newv.
973 gsf_property_settings_collect_valist (GType object_type,
974 GParameter **p_params,
976 const gchar *first_property_name,
980 GParameter *params = *p_params;
982 size_t n_params = *p_n_params;
983 size_t n_alloced_params = n_params; /* We might have more. */
985 g_return_if_fail (G_TYPE_IS_OBJECT (object_type));
987 class = g_type_class_ref (object_type);
989 name = first_property_name;
993 GParamSpec *pspec = g_object_class_find_property (class, name);
996 g_warning ("%s: object class `%s' has no property named `%s'",
998 g_type_name (object_type),
1003 if (n_params >= n_alloced_params)
1005 n_alloced_params += 16;
1006 params = g_renew (GParameter, params, n_alloced_params);
1008 params[n_params].name = name;
1009 params[n_params].value.g_type = 0;
1010 g_value_init (¶ms[n_params].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1011 G_VALUE_COLLECT (¶ms[n_params].value, var_args, 0, &error);
1014 g_warning ("%s: %s", G_STRFUNC, error);
1016 g_value_unset (¶ms[n_params].value);
1020 name = va_arg (var_args, gchar*);
1023 g_type_class_unref (class);
1026 *p_n_params = n_params;
1029 /* This is a vararg version of gsf_property_settings_collect_valist. */
1031 gsf_property_settings_collect (GType object_type,
1032 GParameter **p_params,
1034 const gchar *first_property_name,
1038 va_start (var_args, first_property_name);
1039 gsf_property_settings_collect_valist (object_type, p_params, p_n_params, first_property_name, var_args);
1044 gsf_property_settings_free (GParameter *params,
1048 g_value_unset (¶ms[n_params].value);
1059 * Returns: the #GQuark used to identify libgsf errors in #GError structures.
1060 * Specific error codes come from the #GsfError enumeration.
1063 gsf_error_quark (void)
1065 static GQuark quark;
1068 quark = g_quark_from_static_string ("gsf-error-quark");