diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
commit | 5c1676dfe6d2f3c837a5e074117b45613fd29a72 (patch) | |
tree | cbffb45144febf451e54061db2b21395faf94bfe /libgimpconfig | |
parent | Initial commit. (diff) | |
download | gimp-5c1676dfe6d2f3c837a5e074117b45613fd29a72.tar.xz gimp-5c1676dfe6d2f3c837a5e074117b45613fd29a72.zip |
Adding upstream version 2.10.34.upstream/2.10.34upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
26 files changed, 9072 insertions, 0 deletions
diff --git a/libgimpconfig/Makefile.am b/libgimpconfig/Makefile.am new file mode 100644 index 0000000..40d30ca --- /dev/null +++ b/libgimpconfig/Makefile.am @@ -0,0 +1,163 @@ +## Process this file with automake to produce Makefile.in + +libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la +libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la +libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la + +if PLATFORM_WIN32 +no_undefined = -no-undefined +endif + +if OS_WIN32 +gimpconfig_def = gimpconfig.def +libgimpconfig_export_symbols = -export-symbols $(srcdir)/gimpconfig.def + +install-libtool-import-lib: + $(INSTALL) .libs/libgimpconfig-$(GIMP_API_VERSION).dll.a $(DESTDIR)$(libdir) + $(INSTALL) $(srcdir)/gimpconfig.def $(DESTDIR)$(libdir) + +uninstall-libtool-import-lib: + -rm $(DESTDIR)$(libdir)/libgimpconfig-$(GIMP_API_VERSION).dll.a + -rm $(DESTDIR)$(libdir)/gimpconfig.def +else +install-libtool-import-lib: +uninstall-libtool-import-lib: +endif + +if MS_LIB_AVAILABLE +noinst_DATA = gimpconfig-$(GIMP_API_VERSION).lib + +install-ms-lib: + $(INSTALL) gimpconfig-$(GIMP_API_VERSION).lib $(DESTDIR)$(libdir) + +uninstall-ms-lib: + -rm $(DESTDIR)$(libdir)/gimpconfig-$(GIMP_API_VERSION).lib + +gimpconfig-@GIMP_API_VERSION@.lib: gimpconfig.def + lib -name:libgimpconfig-$(GIMP_API_VERSION)-@LT_CURRENT_MINUS_AGE@.dll -def:gimpconfig.def -out:$@ + +else +install-ms-lib: +uninstall-ms-lib: +endif + +libgimpconfigincludedir = $(includedir)/gimp-$(GIMP_API_VERSION)/libgimpconfig + +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"LibGimpConfig\" \ + -DGIMP_CONFIG_COMPILATION \ + -I$(top_srcdir) \ + $(GIO_UNIX_CFLAGS) \ + $(GIO_WINDOWS_CFLAGS) \ + $(GEGL_CFLAGS) \ + $(CAIRO_CFLAGS) \ + $(GDK_PIXBUF_CFLAGS) \ + -I$(includedir) + +EXTRA_DIST = \ + gimpconfig.def + +lib_LTLIBRARIES = libgimpconfig-@GIMP_API_VERSION@.la + +libgimpconfig_sources = \ + gimpconfig.h \ + gimpconfigenums.h \ + gimpconfigtypes.h \ + \ + gimpconfig-iface.c \ + gimpconfig-iface.h \ + gimpconfig-deserialize.c \ + gimpconfig-deserialize.h \ + gimpconfig-error.c \ + gimpconfig-error.h \ + gimpconfig-params.h \ + gimpconfig-path.c \ + gimpconfig-path.h \ + gimpconfig-serialize.c \ + gimpconfig-serialize.h \ + gimpconfig-utils.c \ + gimpconfig-utils.h \ + gimpconfigwriter.c \ + gimpconfigwriter.h \ + gimpscanner.c \ + gimpscanner.h \ + gimpcolorconfig.c \ + gimpcolorconfig.h + +libgimpconfig_built_sources = \ + gimpconfigenums.c + +libgimpconfig_@GIMP_API_VERSION@_la_SOURCES = \ + $(libgimpconfig_sources) \ + $(libgimpconfig_built_sources) + + +libgimpconfiginclude_HEADERS = \ + gimpconfig.h \ + gimpconfigenums.h \ + gimpconfigtypes.h \ + gimpconfig-iface.h \ + gimpconfig-deserialize.h \ + gimpconfig-error.h \ + gimpconfig-params.h \ + gimpconfig-path.h \ + gimpconfig-serialize.h \ + gimpconfig-utils.h \ + gimpconfigwriter.h \ + gimpscanner.h \ + gimpcolorconfig.h + + +libgimpconfig_@GIMP_API_VERSION@_la_LDFLAGS = \ + -version-info $(LT_VERSION_INFO) \ + $(no_undefined) \ + $(libgimpconfig_export_symbols) + +EXTRA_libgimpconfig_@GIMP_API_VERSION@_la_DEPENDENCIES = $(gimpconfig_def) + +libgimpconfig_@GIMP_API_VERSION@_la_LIBADD = \ + $(libgimpbase) \ + $(libgimpcolor) \ + $(libgimpmath) \ + $(GIO_UNIX_LIBS) \ + $(GIO_WINDOWS_LIBS) \ + $(GEGL_LIBS) \ + $(CAIRO_LIBS) \ + $(GDK_PIXBUF_LIBS) + + +install-data-local: install-ms-lib install-libtool-import-lib + +uninstall-local: uninstall-ms-lib uninstall-libtool-import-lib + + +# +# rules to generate built sources +# + +gen_sources = xgen-cec +CLEANFILES = $(gen_sources) + +xgen-cec: $(srcdir)/gimpconfigenums.h $(GIMP_MKENUMS) Makefile.am + $(AM_V_GEN) $(GIMP_MKENUMS) \ + --fhead "#include \"config.h\"\n#include <gio/gio.h>\n#include \"libgimpbase/gimpbase.h\"\n#include \"gimpconfigenums.h\"\n#include \"libgimp/libgimp-intl.h\"" \ + --fprod "\n/* enumerations from \"@basename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static const G@Type@Value values[] =\n {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n" \ + --dhead " static const Gimp@Type@Desc descs[] =\n {" \ + --dprod " { @VALUENAME@, @valuedesc@, @valuehelp@ },@if ('@valueabbrev@' ne 'NULL')@\n /* Translators: this is an abbreviated version of @valueudesc@.\n Keep it short. */\n { @VALUENAME@, @valueabbrev@, NULL },@endif@" \ + --dtail " { 0, NULL, NULL }\n };\n\n static GType type = 0;\n\n if (G_UNLIKELY (! type))\n {\n type = g_@type@_register_static (\"@EnumName@\", values);\n gimp_type_set_translation_domain (type, GETTEXT_PACKAGE \"-libgimp\");\n gimp_type_set_translation_context (type, \"@enumnick@\");\n gimp_@type@_set_value_descriptions (type, descs);\n }\n\n return type;\n}\n" \ + $< > $@ + +# copy the generated enum file back to the source directory only if it's +# changed; otherwise, only update its timestamp, so that the recipe isn't +# executed again on the next build, however, allow this to (harmlessly) fail, +# to support building from a read-only source tree. +$(srcdir)/gimpconfigenums.c: xgen-cec + $(AM_V_GEN) if ! cmp -s $< $@; then \ + cp $< $@; \ + else \ + touch $@ 2> /dev/null \ + || true; \ + fi diff --git a/libgimpconfig/Makefile.in b/libgimpconfig/Makefile.in new file mode 100644 index 0000000..4afaa42 --- /dev/null +++ b/libgimpconfig/Makefile.in @@ -0,0 +1,1179 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = libgimpconfig +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4macros/alsa.m4 \ + $(top_srcdir)/m4macros/ax_compare_version.m4 \ + $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ + $(top_srcdir)/m4macros/detectcflags.m4 \ + $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(libgimpconfiginclude_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(libgimpconfigincludedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgimpconfig_@GIMP_API_VERSION@_la_DEPENDENCIES = $(libgimpbase) \ + $(libgimpcolor) $(libgimpmath) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__objects_1 = gimpconfig-iface.lo gimpconfig-deserialize.lo \ + gimpconfig-error.lo gimpconfig-path.lo gimpconfig-serialize.lo \ + gimpconfig-utils.lo gimpconfigwriter.lo gimpscanner.lo \ + gimpcolorconfig.lo +am__objects_2 = gimpconfigenums.lo +am_libgimpconfig_@GIMP_API_VERSION@_la_OBJECTS = $(am__objects_1) \ + $(am__objects_2) +libgimpconfig_@GIMP_API_VERSION@_la_OBJECTS = \ + $(am_libgimpconfig_@GIMP_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgimpconfig_@GIMP_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libgimpconfig_@GIMP_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/gimpcolorconfig.Plo \ + ./$(DEPDIR)/gimpconfig-deserialize.Plo \ + ./$(DEPDIR)/gimpconfig-error.Plo \ + ./$(DEPDIR)/gimpconfig-iface.Plo \ + ./$(DEPDIR)/gimpconfig-path.Plo \ + ./$(DEPDIR)/gimpconfig-serialize.Plo \ + ./$(DEPDIR)/gimpconfig-utils.Plo \ + ./$(DEPDIR)/gimpconfigenums.Plo \ + ./$(DEPDIR)/gimpconfigwriter.Plo ./$(DEPDIR)/gimpscanner.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgimpconfig_@GIMP_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(libgimpconfig_@GIMP_API_VERSION@_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(noinst_DATA) +HEADERS = $(libgimpconfiginclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +AA_LIBS = @AA_LIBS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPSTREAM_UTIL = @APPSTREAM_UTIL@ +AR = @AR@ +AS = @AS@ +ATK_CFLAGS = @ATK_CFLAGS@ +ATK_LIBS = @ATK_LIBS@ +ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BABL_CFLAGS = @BABL_CFLAGS@ +BABL_LIBS = @BABL_LIBS@ +BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ +BUG_REPORT_URL = @BUG_REPORT_URL@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +BZIP2_LIBS = @BZIP2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@ +CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@ +CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@ +CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CC_VERSION = @CC_VERSION@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DESKTOP_DATADIR = @DESKTOP_DATADIR@ +DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@ +DLLTOOL = @DLLTOOL@ +DOC_SHOOTER = @DOC_SHOOTER@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_AA = @FILE_AA@ +FILE_EXR = @FILE_EXR@ +FILE_HEIF = @FILE_HEIF@ +FILE_JP2_LOAD = @FILE_JP2_LOAD@ +FILE_JPEGXL = @FILE_JPEGXL@ +FILE_MNG = @FILE_MNG@ +FILE_PDF_SAVE = @FILE_PDF_SAVE@ +FILE_PS = @FILE_PS@ +FILE_WMF = @FILE_WMF@ +FILE_XMC = @FILE_XMC@ +FILE_XPM = @FILE_XPM@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@ +FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDBUS_CODEGEN = @GDBUS_CODEGEN@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@ +GEGL = @GEGL@ +GEGL_CFLAGS = @GEGL_CFLAGS@ +GEGL_LIBS = @GEGL_LIBS@ +GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@ +GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GEXIV2_CFLAGS = @GEXIV2_CFLAGS@ +GEXIV2_LIBS = @GEXIV2_LIBS@ +GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@ +GIMP_API_VERSION = @GIMP_API_VERSION@ +GIMP_APP_VERSION = @GIMP_APP_VERSION@ +GIMP_BINARY_AGE = @GIMP_BINARY_AGE@ +GIMP_COMMAND = @GIMP_COMMAND@ +GIMP_DATA_VERSION = @GIMP_DATA_VERSION@ +GIMP_FULL_NAME = @GIMP_FULL_NAME@ +GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@ +GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@ +GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@ +GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@ +GIMP_MKENUMS = @GIMP_MKENUMS@ +GIMP_MODULES = @GIMP_MODULES@ +GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@ +GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@ +GIMP_PLUGINS = @GIMP_PLUGINS@ +GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@ +GIMP_REAL_VERSION = @GIMP_REAL_VERSION@ +GIMP_RELEASE = @GIMP_RELEASE@ +GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@ +GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@ +GIMP_UNSTABLE = @GIMP_UNSTABLE@ +GIMP_USER_VERSION = @GIMP_USER_VERSION@ +GIMP_VERSION = @GIMP_VERSION@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@ +GIO_UNIX_LIBS = @GIO_UNIX_LIBS@ +GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@ +GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@ +GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@ +GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GS_LIBS = @GS_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@ +GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ +GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ +GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ +HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ +HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_FINITE = @HAVE_FINITE@ +HAVE_ISFINITE = @HAVE_ISFINITE@ +HAVE_VFORK = @HAVE_VFORK@ +HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@ +ISO_CODES_LOCATION = @ISO_CODES_LOCATION@ +JPEG_LIBS = @JPEG_LIBS@ +JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@ +JSON_GLIB_LIBS = @JSON_GLIB_LIBS@ +JXL_CFLAGS = @JXL_CFLAGS@ +JXL_LIBS = @JXL_LIBS@ +JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@ +JXL_THREADS_LIBS = @JXL_THREADS_LIBS@ +LCMS_CFLAGS = @LCMS_CFLAGS@ +LCMS_LIBS = @LCMS_LIBS@ +LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@ +LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@ +LIBHEIF_LIBS = @LIBHEIF_LIBS@ +LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@ +LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@ +LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@ +LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@ +LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@ +LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +LZMA_CFLAGS = @LZMA_CFLAGS@ +LZMA_LIBS = @LZMA_LIBS@ +MAIL = @MAIL@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@ +MIME_INFO_LIBS = @MIME_INFO_LIBS@ +MIME_TYPES = @MIME_TYPES@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@ +MNG_CFLAGS = @MNG_CFLAGS@ +MNG_LIBS = @MNG_LIBS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@ +MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@ +NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@ +NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENEXR_CFLAGS = @OPENEXR_CFLAGS@ +OPENEXR_LIBS = @OPENEXR_LIBS@ +OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@ +OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@ +OPENJPEG_LIBS = @OPENJPEG_LIBS@ +OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ +PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ +PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@ +PATHSEP = @PATHSEP@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@ +PERL_VERSION = @PERL_VERSION@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +POFILES = @POFILES@ +POPPLER_CFLAGS = @POPPLER_CFLAGS@ +POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@ +POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@ +POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@ +POPPLER_LIBS = @POPPLER_LIBS@ +POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PYBIN_PATH = @PYBIN_PATH@ +PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ +PYCAIRO_LIBS = @PYCAIRO_LIBS@ +PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@ +PYGTK_CFLAGS = @PYGTK_CFLAGS@ +PYGTK_CODEGEN = @PYGTK_CODEGEN@ +PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ +PYGTK_LIBS = @PYGTK_LIBS@ +PYLINK_LIBS = @PYLINK_LIBS@ +PYTHON = @PYTHON@ +PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ +RT_LIBS = @RT_LIBS@ +SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ +SED = @SED@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ +SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ +STRIP = @STRIP@ +SVG_CFLAGS = @SVG_CFLAGS@ +SVG_LIBS = @SVG_LIBS@ +SYMPREFIX = @SYMPREFIX@ +TIFF_LIBS = @TIFF_LIBS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@ +WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@ +WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@ +WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@ +WEBPMUX_LIBS = @WEBPMUX_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ +WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@ +WEB_PAGE = @WEB_PAGE@ +WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@ +WINDRES = @WINDRES@ +WMF_CFLAGS = @WMF_CFLAGS@ +WMF_CONFIG = @WMF_CONFIG@ +WMF_LIBS = @WMF_LIBS@ +WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@ +XDG_EMAIL = @XDG_EMAIL@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@ +XMC_CFLAGS = @XMC_CFLAGS@ +XMC_LIBS = @XMC_LIBS@ +XMKMF = @XMKMF@ +XMLLINT = @XMLLINT@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ +XSLTPROC = @XSLTPROC@ +XVFB_RUN = @XVFB_RUN@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gimpdatadir = @gimpdatadir@ +gimpdir = @gimpdir@ +gimplocaledir = @gimplocaledir@ +gimpplugindir = @gimpplugindir@ +gimpsysconfdir = @gimpsysconfdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +manpage_gimpdir = @manpage_gimpdir@ +mkdir_p = @mkdir_p@ +ms_librarian = @ms_librarian@ +mypaint_brushes_dir = @mypaint_brushes_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la +libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la +libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la +@PLATFORM_WIN32_TRUE@no_undefined = -no-undefined +@OS_WIN32_TRUE@gimpconfig_def = gimpconfig.def +@OS_WIN32_TRUE@libgimpconfig_export_symbols = -export-symbols $(srcdir)/gimpconfig.def +@MS_LIB_AVAILABLE_TRUE@noinst_DATA = gimpconfig-$(GIMP_API_VERSION).lib +libgimpconfigincludedir = $(includedir)/gimp-$(GIMP_API_VERSION)/libgimpconfig +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"LibGimpConfig\" \ + -DGIMP_CONFIG_COMPILATION \ + -I$(top_srcdir) \ + $(GIO_UNIX_CFLAGS) \ + $(GIO_WINDOWS_CFLAGS) \ + $(GEGL_CFLAGS) \ + $(CAIRO_CFLAGS) \ + $(GDK_PIXBUF_CFLAGS) \ + -I$(includedir) + +EXTRA_DIST = \ + gimpconfig.def + +lib_LTLIBRARIES = libgimpconfig-@GIMP_API_VERSION@.la +libgimpconfig_sources = \ + gimpconfig.h \ + gimpconfigenums.h \ + gimpconfigtypes.h \ + \ + gimpconfig-iface.c \ + gimpconfig-iface.h \ + gimpconfig-deserialize.c \ + gimpconfig-deserialize.h \ + gimpconfig-error.c \ + gimpconfig-error.h \ + gimpconfig-params.h \ + gimpconfig-path.c \ + gimpconfig-path.h \ + gimpconfig-serialize.c \ + gimpconfig-serialize.h \ + gimpconfig-utils.c \ + gimpconfig-utils.h \ + gimpconfigwriter.c \ + gimpconfigwriter.h \ + gimpscanner.c \ + gimpscanner.h \ + gimpcolorconfig.c \ + gimpcolorconfig.h + +libgimpconfig_built_sources = \ + gimpconfigenums.c + +libgimpconfig_@GIMP_API_VERSION@_la_SOURCES = \ + $(libgimpconfig_sources) \ + $(libgimpconfig_built_sources) + +libgimpconfiginclude_HEADERS = \ + gimpconfig.h \ + gimpconfigenums.h \ + gimpconfigtypes.h \ + gimpconfig-iface.h \ + gimpconfig-deserialize.h \ + gimpconfig-error.h \ + gimpconfig-params.h \ + gimpconfig-path.h \ + gimpconfig-serialize.h \ + gimpconfig-utils.h \ + gimpconfigwriter.h \ + gimpscanner.h \ + gimpcolorconfig.h + +libgimpconfig_@GIMP_API_VERSION@_la_LDFLAGS = \ + -version-info $(LT_VERSION_INFO) \ + $(no_undefined) \ + $(libgimpconfig_export_symbols) + +EXTRA_libgimpconfig_@GIMP_API_VERSION@_la_DEPENDENCIES = $(gimpconfig_def) +libgimpconfig_@GIMP_API_VERSION@_la_LIBADD = \ + $(libgimpbase) \ + $(libgimpcolor) \ + $(libgimpmath) \ + $(GIO_UNIX_LIBS) \ + $(GIO_WINDOWS_LIBS) \ + $(GEGL_LIBS) \ + $(CAIRO_LIBS) \ + $(GDK_PIXBUF_LIBS) + + +# +# rules to generate built sources +# +gen_sources = xgen-cec +CLEANFILES = $(gen_sources) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libgimpconfig/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libgimpconfig/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgimpconfig-@GIMP_API_VERSION@.la: $(libgimpconfig_@GIMP_API_VERSION@_la_OBJECTS) $(libgimpconfig_@GIMP_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgimpconfig_@GIMP_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgimpconfig_@GIMP_API_VERSION@_la_LINK) -rpath $(libdir) $(libgimpconfig_@GIMP_API_VERSION@_la_OBJECTS) $(libgimpconfig_@GIMP_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcolorconfig.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpconfig-deserialize.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpconfig-error.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpconfig-iface.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpconfig-path.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpconfig-serialize.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpconfig-utils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpconfigenums.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpconfigwriter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpscanner.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-libgimpconfigincludeHEADERS: $(libgimpconfiginclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libgimpconfiginclude_HEADERS)'; test -n "$(libgimpconfigincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgimpconfigincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgimpconfigincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgimpconfigincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgimpconfigincludedir)" || exit $$?; \ + done + +uninstall-libgimpconfigincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libgimpconfiginclude_HEADERS)'; test -n "$(libgimpconfigincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgimpconfigincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libgimpconfigincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/gimpcolorconfig.Plo + -rm -f ./$(DEPDIR)/gimpconfig-deserialize.Plo + -rm -f ./$(DEPDIR)/gimpconfig-error.Plo + -rm -f ./$(DEPDIR)/gimpconfig-iface.Plo + -rm -f ./$(DEPDIR)/gimpconfig-path.Plo + -rm -f ./$(DEPDIR)/gimpconfig-serialize.Plo + -rm -f ./$(DEPDIR)/gimpconfig-utils.Plo + -rm -f ./$(DEPDIR)/gimpconfigenums.Plo + -rm -f ./$(DEPDIR)/gimpconfigwriter.Plo + -rm -f ./$(DEPDIR)/gimpscanner.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local \ + install-libgimpconfigincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/gimpcolorconfig.Plo + -rm -f ./$(DEPDIR)/gimpconfig-deserialize.Plo + -rm -f ./$(DEPDIR)/gimpconfig-error.Plo + -rm -f ./$(DEPDIR)/gimpconfig-iface.Plo + -rm -f ./$(DEPDIR)/gimpconfig-path.Plo + -rm -f ./$(DEPDIR)/gimpconfig-serialize.Plo + -rm -f ./$(DEPDIR)/gimpconfig-utils.Plo + -rm -f ./$(DEPDIR)/gimpconfigenums.Plo + -rm -f ./$(DEPDIR)/gimpconfigwriter.Plo + -rm -f ./$(DEPDIR)/gimpscanner.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES \ + uninstall-libgimpconfigincludeHEADERS uninstall-local + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-data-local install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-libgimpconfigincludeHEADERS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \ + uninstall-libgimpconfigincludeHEADERS uninstall-local + +.PRECIOUS: Makefile + + +@OS_WIN32_TRUE@install-libtool-import-lib: +@OS_WIN32_TRUE@ $(INSTALL) .libs/libgimpconfig-$(GIMP_API_VERSION).dll.a $(DESTDIR)$(libdir) +@OS_WIN32_TRUE@ $(INSTALL) $(srcdir)/gimpconfig.def $(DESTDIR)$(libdir) + +@OS_WIN32_TRUE@uninstall-libtool-import-lib: +@OS_WIN32_TRUE@ -rm $(DESTDIR)$(libdir)/libgimpconfig-$(GIMP_API_VERSION).dll.a +@OS_WIN32_TRUE@ -rm $(DESTDIR)$(libdir)/gimpconfig.def +@OS_WIN32_FALSE@install-libtool-import-lib: +@OS_WIN32_FALSE@uninstall-libtool-import-lib: + +@MS_LIB_AVAILABLE_TRUE@install-ms-lib: +@MS_LIB_AVAILABLE_TRUE@ $(INSTALL) gimpconfig-$(GIMP_API_VERSION).lib $(DESTDIR)$(libdir) + +@MS_LIB_AVAILABLE_TRUE@uninstall-ms-lib: +@MS_LIB_AVAILABLE_TRUE@ -rm $(DESTDIR)$(libdir)/gimpconfig-$(GIMP_API_VERSION).lib + +@MS_LIB_AVAILABLE_TRUE@gimpconfig-@GIMP_API_VERSION@.lib: gimpconfig.def +@MS_LIB_AVAILABLE_TRUE@ lib -name:libgimpconfig-$(GIMP_API_VERSION)-@LT_CURRENT_MINUS_AGE@.dll -def:gimpconfig.def -out:$@ + +@MS_LIB_AVAILABLE_FALSE@install-ms-lib: +@MS_LIB_AVAILABLE_FALSE@uninstall-ms-lib: + +install-data-local: install-ms-lib install-libtool-import-lib + +uninstall-local: uninstall-ms-lib uninstall-libtool-import-lib + +xgen-cec: $(srcdir)/gimpconfigenums.h $(GIMP_MKENUMS) Makefile.am + $(AM_V_GEN) $(GIMP_MKENUMS) \ + --fhead "#include \"config.h\"\n#include <gio/gio.h>\n#include \"libgimpbase/gimpbase.h\"\n#include \"gimpconfigenums.h\"\n#include \"libgimp/libgimp-intl.h\"" \ + --fprod "\n/* enumerations from \"@basename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static const G@Type@Value values[] =\n {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n" \ + --dhead " static const Gimp@Type@Desc descs[] =\n {" \ + --dprod " { @VALUENAME@, @valuedesc@, @valuehelp@ },@if ('@valueabbrev@' ne 'NULL')@\n /* Translators: this is an abbreviated version of @valueudesc@.\n Keep it short. */\n { @VALUENAME@, @valueabbrev@, NULL },@endif@" \ + --dtail " { 0, NULL, NULL }\n };\n\n static GType type = 0;\n\n if (G_UNLIKELY (! type))\n {\n type = g_@type@_register_static (\"@EnumName@\", values);\n gimp_type_set_translation_domain (type, GETTEXT_PACKAGE \"-libgimp\");\n gimp_type_set_translation_context (type, \"@enumnick@\");\n gimp_@type@_set_value_descriptions (type, descs);\n }\n\n return type;\n}\n" \ + $< > $@ + +# copy the generated enum file back to the source directory only if it's +# changed; otherwise, only update its timestamp, so that the recipe isn't +# executed again on the next build, however, allow this to (harmlessly) fail, +# to support building from a read-only source tree. +$(srcdir)/gimpconfigenums.c: xgen-cec + $(AM_V_GEN) if ! cmp -s $< $@; then \ + cp $< $@; \ + else \ + touch $@ 2> /dev/null \ + || true; \ + fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libgimpconfig/gimpcolorconfig.c b/libgimpconfig/gimpcolorconfig.c new file mode 100644 index 0000000..ccb8476 --- /dev/null +++ b/libgimpconfig/gimpcolorconfig.c @@ -0,0 +1,1087 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * GimpColorConfig class + * Copyright (C) 2004 Stefan Döhla <stefan@doehla.de> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <cairo.h> +#include <gegl.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include "libgimpbase/gimpbase.h" +#include "libgimpcolor/gimpcolor.h" + +#include "gimpconfigtypes.h" + +#include "gimpcolorconfig.h" +#include "gimpconfig-error.h" +#include "gimpconfig-iface.h" +#include "gimpconfig-params.h" +#include "gimpconfig-path.h" + +#include "libgimp/libgimp-intl.h" + + +/** + * SECTION: gimpcolorconfig + * @title: GimpColorConfig + * @short_description: Color management settings. + * + * Color management settings. + **/ + + +#define COLOR_MANAGEMENT_MODE_BLURB \ + _("How images are displayed on screen.") + +#define DISPLAY_PROFILE_BLURB \ + _("The color profile of your (primary) monitor.") + +#define DISPLAY_PROFILE_FROM_GDK_BLURB \ + _("When enabled, GIMP will try to use the display color profile from " \ + "the windowing system. The configured monitor profile is then only " \ + "used as a fallback.") + +#define RGB_PROFILE_BLURB \ + _("The preferred RGB working space color profile. It will be offered " \ + "next to the built-in RGB profile when a color profile can be chosen.") + +#define GRAY_PROFILE_BLURB \ + _("The preferred grayscale working space color profile. It will be offered " \ + "next to the built-in grayscale profile when a color profile can be chosen.") + +#define CMYK_PROFILE_BLURB \ + _("The CMYK color profile used to convert between RGB and CMYK.") + +#define SIMULATION_PROFILE_BLURB \ + _("The color profile to use for soft-proofing from your image's " \ + "color space to some other color space, including " \ + "soft-proofing to a printer or other output device profile. ") + +#define DISPLAY_RENDERING_INTENT_BLURB \ + _("How colors are converted from your image's color space to your " \ + "display device. Relative colorimetric is usually the best choice. " \ + "Unless you use a LUT monitor profile (most monitor profiles are " \ + "matrix), choosing perceptual intent really gives you relative " \ + "colorimetric." ) + +#define DISPLAY_USE_BPC_BLURB \ + _("Do use black point compensation (unless you know you have a reason " \ + "not to).") + +#define DISPLAY_OPTIMIZE_BLURB \ + _("When disabled, image display might be of better quality " \ + "at the cost of speed.") + +#define SIMULATION_RENDERING_INTENT_BLURB \ + _("How colors are converted from your image's color space to the " \ + "output simulation device (usually your monitor). " \ + "Try them all and choose what looks the best. ") + +#define SIMULATION_USE_BPC_BLURB \ + _("Try with and without black point compensation "\ + "and choose what looks best. ") + +#define SIMULATION_OPTIMIZE_BLURB \ + _("When disabled, soft-proofing might be of better quality " \ + "at the cost of speed.") + +#define SIMULATION_GAMUT_CHECK_BLURB \ + _("When enabled, the soft-proofing will mark colors " \ + "which can not be represented in the target color space.") + +#define OUT_OF_GAMUT_COLOR_BLURB \ + _("The color to use for marking colors which are out of gamut.") + +#define SHOW_RGB_U8_BLURB \ + _("When enabled, set the color scales to display 0...255 instead " \ + "of percentages") + +#define SHOW_HSV_BLURB \ + _("When enabled, set the color scales to display HSV blend mode instead " \ + "of LCh") + +enum +{ + PROP_0, + PROP_MODE, + PROP_RGB_PROFILE, + PROP_GRAY_PROFILE, + PROP_CMYK_PROFILE, + PROP_DISPLAY_PROFILE, + PROP_DISPLAY_PROFILE_FROM_GDK, + PROP_SIMULATION_PROFILE, + PROP_DISPLAY_RENDERING_INTENT, + PROP_DISPLAY_USE_BPC, + PROP_DISPLAY_OPTIMIZE, + PROP_SIMULATION_RENDERING_INTENT, + PROP_SIMULATION_USE_BPC, + PROP_SIMULATION_OPTIMIZE, + PROP_SIMULATION_GAMUT_CHECK, + PROP_OUT_OF_GAMUT_COLOR, + PROP_SHOW_RGB_U8, + PROP_SHOW_HSV, + PROP_DISPLAY_MODULE +}; + + +typedef struct _GimpColorConfigPrivate GimpColorConfigPrivate; + +struct _GimpColorConfigPrivate +{ + gboolean display_optimize; + gboolean simulation_optimize; + + gboolean show_rgb_u8; + gboolean show_hsv; +}; + +#define GET_PRIVATE(obj) \ + ((GimpColorConfigPrivate *) gimp_color_config_get_instance_private ((GimpColorConfig *) (obj))) + + +static void gimp_color_config_finalize (GObject *object); +static void gimp_color_config_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_color_config_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void gimp_color_config_set_rgb_profile (GimpColorConfig *config, + const gchar *filename, + GError **error); +static void gimp_color_config_set_gray_profile (GimpColorConfig *config, + const gchar *filename, + GError **error); +static void gimp_color_config_set_cmyk_profile (GimpColorConfig *config, + const gchar *filename, + GError **error); +static void gimp_color_config_set_display_profile (GimpColorConfig *config, + const gchar *filename, + GError **error); +static void gimp_color_config_set_simulation_profile (GimpColorConfig *config, + const gchar *filename, + GError **error); + + +G_DEFINE_TYPE_WITH_CODE (GimpColorConfig, gimp_color_config, G_TYPE_OBJECT, + G_ADD_PRIVATE (GimpColorConfig) + G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG, NULL) + gimp_type_set_translation_domain (g_define_type_id, + GETTEXT_PACKAGE "-libgimp")) + +#define parent_class gimp_color_config_parent_class + + +static void +gimp_color_config_class_init (GimpColorConfigClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpRGB color; + + gimp_rgba_set (&color, 1.0, 0.0, 1.0, 1.0); /* magenta */ + + object_class->finalize = gimp_color_config_finalize; + object_class->set_property = gimp_color_config_set_property; + object_class->get_property = gimp_color_config_get_property; + + GIMP_CONFIG_PROP_ENUM (object_class, PROP_MODE, + "mode", + _("Mode of operation"), + COLOR_MANAGEMENT_MODE_BLURB, + GIMP_TYPE_COLOR_MANAGEMENT_MODE, + GIMP_COLOR_MANAGEMENT_DISPLAY, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_PATH (object_class, PROP_RGB_PROFILE, + "rgb-profile", + _("Preferred RGB profile"), + RGB_PROFILE_BLURB, + GIMP_CONFIG_PATH_FILE, NULL, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_PATH (object_class, PROP_GRAY_PROFILE, + "gray-profile", + _("Preferred grayscale profile"), + GRAY_PROFILE_BLURB, + GIMP_CONFIG_PATH_FILE, NULL, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_PATH (object_class, PROP_CMYK_PROFILE, + "cmyk-profile", + _("CMYK profile"), + CMYK_PROFILE_BLURB, + GIMP_CONFIG_PATH_FILE, NULL, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_PATH (object_class, PROP_DISPLAY_PROFILE, + "display-profile", + _("Monitor profile"), + DISPLAY_PROFILE_BLURB, + GIMP_CONFIG_PATH_FILE, NULL, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DISPLAY_PROFILE_FROM_GDK, + "display-profile-from-gdk", + _("Use the system monitor profile"), + DISPLAY_PROFILE_FROM_GDK_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_PATH (object_class, PROP_SIMULATION_PROFILE, + /* FIXME: 3.0: change to simulation-profile */ + "printer-profile", + _("Simulation profile for soft-proofing"), + SIMULATION_PROFILE_BLURB, + GIMP_CONFIG_PATH_FILE, NULL, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_ENUM (object_class, PROP_DISPLAY_RENDERING_INTENT, + "display-rendering-intent", + _("Display rendering intent"), + DISPLAY_RENDERING_INTENT_BLURB, + GIMP_TYPE_COLOR_RENDERING_INTENT, + GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DISPLAY_USE_BPC, + "display-use-black-point-compensation", + _("Use black point compensation for the display"), + DISPLAY_USE_BPC_BLURB, + TRUE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DISPLAY_OPTIMIZE, + "display-optimize", + _("Optimize display color transformations"), + DISPLAY_OPTIMIZE_BLURB, + TRUE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_ENUM (object_class, PROP_SIMULATION_RENDERING_INTENT, + "simulation-rendering-intent", + _("Soft-proofing rendering intent"), + SIMULATION_RENDERING_INTENT_BLURB, + GIMP_TYPE_COLOR_RENDERING_INTENT, + GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SIMULATION_USE_BPC, + "simulation-use-black-point-compensation", + _("Use black point compensation for soft-proofing"), + SIMULATION_USE_BPC_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SIMULATION_OPTIMIZE, + "simulation-optimize", + _("Optimize soft-proofing color transformations"), + SIMULATION_OPTIMIZE_BLURB, + TRUE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SIMULATION_GAMUT_CHECK, + "simulation-gamut-check", + _("Mark out of gamut colors"), + SIMULATION_GAMUT_CHECK_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_RGB (object_class, PROP_OUT_OF_GAMUT_COLOR, + "out-of-gamut-color", + _("Out of gamut warning color"), + OUT_OF_GAMUT_COLOR_BLURB, + FALSE, &color, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_RGB_U8, + "show-rgb-u8", + "Show RGB 0..255", + _("Show RGB 0..255 scales"), + FALSE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_HSV, + "show-hsv", + "Show HSV", + _("Show HSV instead of LCH"), + FALSE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_STRING (object_class, PROP_DISPLAY_MODULE, + "display-module", + "Display module", + "This property is deprecated and its value ignored", + "CdisplayLcms", + GIMP_PARAM_STATIC_STRINGS); +} + +static void +gimp_color_config_init (GimpColorConfig *config) +{ +} + +static void +gimp_color_config_finalize (GObject *object) +{ + GimpColorConfig *color_config = GIMP_COLOR_CONFIG (object); + + if (color_config->rgb_profile) + g_free (color_config->rgb_profile); + + if (color_config->gray_profile) + g_free (color_config->gray_profile); + + if (color_config->cmyk_profile) + g_free (color_config->cmyk_profile); + + if (color_config->display_profile) + g_free (color_config->display_profile); + + if (color_config->printer_profile) + g_free (color_config->printer_profile); + + if (color_config->display_module) + g_free (color_config->display_module); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_color_config_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpColorConfig *color_config = GIMP_COLOR_CONFIG (object); + GimpColorConfigPrivate *priv = GET_PRIVATE (object); + GError *error = NULL; + + switch (property_id) + { + case PROP_MODE: + color_config->mode = g_value_get_enum (value); + break; + case PROP_RGB_PROFILE: + gimp_color_config_set_rgb_profile (color_config, + g_value_get_string (value), + &error); + break; + case PROP_GRAY_PROFILE: + gimp_color_config_set_gray_profile (color_config, + g_value_get_string (value), + &error); + break; + case PROP_CMYK_PROFILE: + gimp_color_config_set_cmyk_profile (color_config, + g_value_get_string (value), + &error); + break; + case PROP_DISPLAY_PROFILE: + gimp_color_config_set_display_profile (color_config, + g_value_get_string (value), + &error); + break; + case PROP_DISPLAY_PROFILE_FROM_GDK: + color_config->display_profile_from_gdk = g_value_get_boolean (value); + break; + case PROP_SIMULATION_PROFILE: + gimp_color_config_set_simulation_profile (color_config, + g_value_get_string (value), + &error); + break; + case PROP_DISPLAY_RENDERING_INTENT: + color_config->display_intent = g_value_get_enum (value); + break; + case PROP_DISPLAY_USE_BPC: + color_config->display_use_black_point_compensation = g_value_get_boolean (value); + break; + case PROP_DISPLAY_OPTIMIZE: + priv->display_optimize = g_value_get_boolean (value); + break; + case PROP_SIMULATION_RENDERING_INTENT: + color_config->simulation_intent = g_value_get_enum (value); + break; + case PROP_SIMULATION_USE_BPC: + color_config->simulation_use_black_point_compensation = g_value_get_boolean (value); + break; + case PROP_SIMULATION_OPTIMIZE: + priv->simulation_optimize = g_value_get_boolean (value); + break; + case PROP_SIMULATION_GAMUT_CHECK: + color_config->simulation_gamut_check = g_value_get_boolean (value); + break; + case PROP_OUT_OF_GAMUT_COLOR: + color_config->out_of_gamut_color = *(GimpRGB *) g_value_get_boxed (value); + break; + case PROP_SHOW_RGB_U8: + priv->show_rgb_u8 = g_value_get_boolean (value); + break; + case PROP_SHOW_HSV: + priv->show_hsv = g_value_get_boolean (value); + break; + case PROP_DISPLAY_MODULE: + g_free (color_config->display_module); + color_config->display_module = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } + + if (error) + { + g_message ("%s", error->message); + g_clear_error (&error); + } +} + +static void +gimp_color_config_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpColorConfig *color_config = GIMP_COLOR_CONFIG (object); + GimpColorConfigPrivate *priv = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_MODE: + g_value_set_enum (value, color_config->mode); + break; + case PROP_RGB_PROFILE: + g_value_set_string (value, color_config->rgb_profile); + break; + case PROP_GRAY_PROFILE: + g_value_set_string (value, color_config->gray_profile); + break; + case PROP_CMYK_PROFILE: + g_value_set_string (value, color_config->cmyk_profile); + break; + case PROP_DISPLAY_PROFILE: + g_value_set_string (value, color_config->display_profile); + break; + case PROP_DISPLAY_PROFILE_FROM_GDK: + g_value_set_boolean (value, color_config->display_profile_from_gdk); + break; + case PROP_SIMULATION_PROFILE: + g_value_set_string (value, color_config->printer_profile); + break; + case PROP_DISPLAY_RENDERING_INTENT: + g_value_set_enum (value, color_config->display_intent); + break; + case PROP_DISPLAY_USE_BPC: + g_value_set_boolean (value, color_config->display_use_black_point_compensation); + break; + case PROP_DISPLAY_OPTIMIZE: + g_value_set_boolean (value, priv->display_optimize); + break; + case PROP_SIMULATION_RENDERING_INTENT: + g_value_set_enum (value, color_config->simulation_intent); + break; + case PROP_SIMULATION_USE_BPC: + g_value_set_boolean (value, color_config->simulation_use_black_point_compensation); + break; + case PROP_SIMULATION_OPTIMIZE: + g_value_set_boolean (value, priv->simulation_optimize); + break; + case PROP_SIMULATION_GAMUT_CHECK: + g_value_set_boolean (value, color_config->simulation_gamut_check); + break; + case PROP_OUT_OF_GAMUT_COLOR: + g_value_set_boxed (value, &color_config->out_of_gamut_color); + break; + case PROP_SHOW_RGB_U8: + g_value_set_boolean (value, priv->show_rgb_u8); + break; + case PROP_SHOW_HSV: + g_value_set_boolean (value, priv->show_hsv); + break; + case PROP_DISPLAY_MODULE: + g_value_set_string (value, color_config->display_module); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +/* public functions */ + +/** + * gimp_color_config_get_mode: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +GimpColorManagementMode +gimp_color_config_get_mode (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), + GIMP_COLOR_MANAGEMENT_OFF); + + return config->mode; +} + +/** + * gimp_color_config_get_display_intent: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +GimpColorRenderingIntent +gimp_color_config_get_display_intent (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), + GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL); + + return config->display_intent; +} + +/** + * gimp_color_config_get_display_bpc: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +gboolean +gimp_color_config_get_display_bpc (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), FALSE); + + return config->display_use_black_point_compensation; +} + +/** + * gimp_color_config_get_display_optimize: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +gboolean +gimp_color_config_get_display_optimize (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), FALSE); + + return GET_PRIVATE (config)->display_optimize; +} + +/** + * gimp_color_config_get_display_profile_from_gdk: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +gboolean +gimp_color_config_get_display_profile_from_gdk (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), FALSE); + + return config->display_profile_from_gdk; +} + +/** + * gimp_color_config_get_simulation_intent: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +GimpColorRenderingIntent +gimp_color_config_get_simulation_intent (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), + GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL); + + return config->simulation_intent; +} + +/** + * gimp_color_config_get_simulation_bpc: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +gboolean +gimp_color_config_get_simulation_bpc (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), FALSE); + + return config->simulation_use_black_point_compensation; +} + +/** + * gimp_color_config_get_simulation_optimize: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +gboolean +gimp_color_config_get_simulation_optimize (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), FALSE); + + return GET_PRIVATE (config)->simulation_optimize; +} + +/** + * gimp_color_config_get_simulation_gamut_check: + * @config: a #GimpColorConfig + * + * Since: 2.10 + **/ +gboolean +gimp_color_config_get_simulation_gamut_check (GimpColorConfig *config) +{ + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), FALSE); + + return config->simulation_gamut_check; +} + +/** + * gimp_color_config_get_rgb_color_profile: + * @config: a #GimpColorConfig + * @error: return location for a #GError + * + * Since: 2.10 + **/ +GimpColorProfile * +gimp_color_config_get_rgb_color_profile (GimpColorConfig *config, + GError **error) +{ + GimpColorProfile *profile = NULL; + + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (config->rgb_profile) + { + GFile *file = gimp_file_new_for_config_path (config->rgb_profile, + error); + + if (file) + { + profile = gimp_color_profile_new_from_file (file, error); + + if (profile && ! gimp_color_profile_is_rgb (profile)) + { + g_object_unref (profile); + profile = NULL; + + g_set_error (error, GIMP_CONFIG_ERROR, 0, + _("Color profile '%s' is not for RGB color space."), + gimp_file_get_utf8_name (file)); + } + + g_object_unref (file); + } + } + + return profile; +} + +/** + * gimp_color_config_get_gray_color_profile: + * @config: a #GimpColorConfig + * @error: return location for a #GError + * + * Since: 2.10 + **/ +GimpColorProfile * +gimp_color_config_get_gray_color_profile (GimpColorConfig *config, + GError **error) +{ + GimpColorProfile *profile = NULL; + + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (config->gray_profile) + { + GFile *file = gimp_file_new_for_config_path (config->gray_profile, + error); + + if (file) + { + profile = gimp_color_profile_new_from_file (file, error); + + if (profile && ! gimp_color_profile_is_gray (profile)) + { + g_object_unref (profile); + profile = NULL; + + g_set_error (error, GIMP_CONFIG_ERROR, 0, + _("Color profile '%s' is not for GRAY color space."), + gimp_file_get_utf8_name (file)); + } + + g_object_unref (file); + } + } + + return profile; +} + +/** + * gimp_color_config_get_cmyk_color_profile: + * @config: a #GimpColorConfig + * @error: return location for a #GError + * + * Since: 2.10 + **/ +GimpColorProfile * +gimp_color_config_get_cmyk_color_profile (GimpColorConfig *config, + GError **error) +{ + GimpColorProfile *profile = NULL; + + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (config->cmyk_profile) + { + GFile *file = gimp_file_new_for_config_path (config->cmyk_profile, + error); + + if (file) + { + profile = gimp_color_profile_new_from_file (file, error); + + if (profile && ! gimp_color_profile_is_cmyk (profile)) + { + g_object_unref (profile); + profile = NULL; + + g_set_error (error, GIMP_CONFIG_ERROR, 0, + _("Color profile '%s' is not for CMYK color space."), + gimp_file_get_utf8_name (file)); + } + + g_object_unref (file); + } + } + + return profile; +} + +/** + * gimp_color_config_get_display_color_profile: + * @config: a #GimpColorConfig + * @error: return location for a #GError + * + * Since: 2.10 + **/ +GimpColorProfile * +gimp_color_config_get_display_color_profile (GimpColorConfig *config, + GError **error) +{ + GimpColorProfile *profile = NULL; + + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (config->display_profile) + { + GFile *file = gimp_file_new_for_config_path (config->display_profile, + error); + + if (file) + { + profile = gimp_color_profile_new_from_file (file, error); + + g_object_unref (file); + } + } + + return profile; +} + +/** + * gimp_color_config_get_simulation_color_profile: + * @config: a #GimpColorConfig + * @error: return location for a #GError + * + * Since: 2.10 + **/ +GimpColorProfile * +gimp_color_config_get_simulation_color_profile (GimpColorConfig *config, + GError **error) +{ + GimpColorProfile *profile = NULL; + + g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (config->printer_profile) + { + GFile *file = gimp_file_new_for_config_path (config->printer_profile, + error); + + if (file) + { + profile = gimp_color_profile_new_from_file (file, error); + + g_object_unref (file); + } + } + + return profile; +} + + +/* private functions */ + +static void +gimp_color_config_set_rgb_profile (GimpColorConfig *config, + const gchar *filename, + GError **error) +{ + gboolean success = TRUE; + + if (filename) + { + GFile *file = gimp_file_new_for_config_path (filename, error); + + if (file) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_file (file, error); + + if (profile) + { + if (! gimp_color_profile_is_rgb (profile)) + { + g_set_error (error, GIMP_CONFIG_ERROR, 0, + _("Color profile '%s' is not for RGB " + "color space."), + gimp_file_get_utf8_name (file)); + success = FALSE; + } + + g_object_unref (profile); + } + else + { + success = FALSE; + } + + g_object_unref (file); + } + else + { + success = FALSE; + } + } + + if (success) + { + g_free (config->rgb_profile); + config->rgb_profile = g_strdup (filename); + } +} + +static void +gimp_color_config_set_gray_profile (GimpColorConfig *config, + const gchar *filename, + GError **error) +{ + gboolean success = TRUE; + + if (filename) + { + GFile *file = gimp_file_new_for_config_path (filename, error); + + if (file) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_file (file, error); + + if (profile) + { + if (! gimp_color_profile_is_gray (profile)) + { + g_set_error (error, GIMP_CONFIG_ERROR, 0, + _("Color profile '%s' is not for GRAY " + "color space."), + gimp_file_get_utf8_name (file)); + success = FALSE; + } + + g_object_unref (profile); + } + else + { + success = FALSE; + } + + g_object_unref (file); + } + else + { + success = FALSE; + } + } + + if (success) + { + g_free (config->gray_profile); + config->gray_profile = g_strdup (filename); + } +} + +static void +gimp_color_config_set_cmyk_profile (GimpColorConfig *config, + const gchar *filename, + GError **error) +{ + gboolean success = TRUE; + + if (filename) + { + GFile *file = gimp_file_new_for_config_path (filename, error); + + if (file) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_file (file, error); + + if (profile) + { + if (! gimp_color_profile_is_cmyk (profile)) + { + g_set_error (error, GIMP_CONFIG_ERROR, 0, + _("Color profile '%s' is not for CMYK " + "color space."), + gimp_file_get_utf8_name (file)); + success = FALSE; + } + + g_object_unref (profile); + } + else + { + success = FALSE; + } + + g_object_unref (file); + } + else + { + success = FALSE; + } + } + + if (success) + { + g_free (config->cmyk_profile); + config->cmyk_profile = g_strdup (filename); + } +} + +static void +gimp_color_config_set_display_profile (GimpColorConfig *config, + const gchar *filename, + GError **error) +{ + gboolean success = TRUE; + + if (filename) + { + GFile *file = gimp_file_new_for_config_path (filename, error); + + if (file) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_file (file, error); + + if (profile) + { + g_object_unref (profile); + } + else + { + success = FALSE; + } + + g_object_unref (file); + } + else + { + success = FALSE; + } + } + + if (success) + { + g_free (config->display_profile); + config->display_profile = g_strdup (filename); + } +} + +static void +gimp_color_config_set_simulation_profile (GimpColorConfig *config, + const gchar *filename, + GError **error) +{ + gboolean success = TRUE; + + if (filename) + { + GFile *file = gimp_file_new_for_config_path (filename, error); + + if (file) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_file (file, error); + + if (profile) + { + g_object_unref (profile); + } + else + { + success = FALSE; + } + + g_object_unref (file); + } + else + { + success = FALSE; + } + } + + if (success) + { + g_free (config->printer_profile); + config->printer_profile = g_strdup (filename); + } +} diff --git a/libgimpconfig/gimpcolorconfig.h b/libgimpconfig/gimpcolorconfig.h new file mode 100644 index 0000000..b4fdf28 --- /dev/null +++ b/libgimpconfig/gimpcolorconfig.h @@ -0,0 +1,110 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * GimpColorConfig class + * Copyright (C) 2004 Stefan Döhla <stefan@doehla.de> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_COLOR_CONFIG_H__ +#define __GIMP_COLOR_CONFIG_H__ + + +#define GIMP_TYPE_COLOR_CONFIG (gimp_color_config_get_type ()) +#define GIMP_COLOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_COLOR_CONFIG, GimpColorConfig)) +#define GIMP_COLOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_COLOR_CONFIG, GimpColorConfigClass)) +#define GIMP_IS_COLOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_COLOR_CONFIG)) +#define GIMP_IS_COLOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_COLOR_CONFIG)) + + +typedef struct _GimpColorConfigClass GimpColorConfigClass; + +struct _GimpColorConfig +{ + GObject parent_instance; + + /*< public >*/ + GimpColorManagementMode mode; + gchar *rgb_profile; + gchar *cmyk_profile; + gchar *display_profile; + gboolean display_profile_from_gdk; + gchar *printer_profile; + GimpColorRenderingIntent display_intent; + GimpColorRenderingIntent simulation_intent; + + gchar *display_module; + + gboolean simulation_gamut_check; + GimpRGB out_of_gamut_color; + + gboolean display_use_black_point_compensation; + gboolean simulation_use_black_point_compensation; + + gchar *gray_profile; + + /*< private >*/ + /* Padding for future expansion */ +#if (GLIB_SIZEOF_VOID_P == 8) + void (* _gimp_reserved3) (void); +#endif + void (* _gimp_reserved4) (void); + void (* _gimp_reserved5) (void); + void (* _gimp_reserved6) (void); + void (* _gimp_reserved7) (void); + void (* _gimp_reserved8) (void); +}; + +struct _GimpColorConfigClass +{ + GObjectClass parent_class; +}; + + +GType gimp_color_config_get_type (void) G_GNUC_CONST; + +GimpColorManagementMode + gimp_color_config_get_mode (GimpColorConfig *config); + +GimpColorRenderingIntent + gimp_color_config_get_display_intent (GimpColorConfig *config); +gboolean gimp_color_config_get_display_bpc (GimpColorConfig *config); +gboolean gimp_color_config_get_display_optimize (GimpColorConfig *config); +gboolean gimp_color_config_get_display_profile_from_gdk (GimpColorConfig *config); + +GimpColorRenderingIntent + gimp_color_config_get_simulation_intent (GimpColorConfig *config); +gboolean gimp_color_config_get_simulation_bpc (GimpColorConfig *config); +gboolean gimp_color_config_get_simulation_optimize (GimpColorConfig *config); +gboolean gimp_color_config_get_simulation_gamut_check (GimpColorConfig *config); + +GimpColorProfile * gimp_color_config_get_rgb_color_profile (GimpColorConfig *config, + GError **error); +GimpColorProfile * gimp_color_config_get_gray_color_profile (GimpColorConfig *config, + GError **error); +GimpColorProfile * gimp_color_config_get_cmyk_color_profile (GimpColorConfig *config, + GError **error); +GimpColorProfile * gimp_color_config_get_display_color_profile (GimpColorConfig *config, + GError **error); +GimpColorProfile * gimp_color_config_get_simulation_color_profile (GimpColorConfig *config, + GError **error); + + +#endif /* GIMP_COLOR_CONFIG_H__ */ diff --git a/libgimpconfig/gimpconfig-deserialize.c b/libgimpconfig/gimpconfig-deserialize.c new file mode 100644 index 0000000..55cbf50 --- /dev/null +++ b/libgimpconfig/gimpconfig-deserialize.c @@ -0,0 +1,1019 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Object properties deserialization routines + * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <cairo.h> +#include <gegl.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include "libgimpbase/gimpbase.h" +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" + +#include "gimpconfigtypes.h" + +#include "gimpconfigwriter.h" +#include "gimpconfig-iface.h" +#include "gimpconfig-deserialize.h" +#include "gimpconfig-params.h" +#include "gimpconfig-path.h" +#include "gimpscanner.h" + +#include "libgimp/libgimp-intl.h" + + +/** + * SECTION: gimpconfig-deserialize + * @title: GimpConfig-deserialize + * @short_description: Deserializing code for libgimpconfig. + * + * Deserializing code for libgimpconfig. + **/ + + +/* + * All functions return G_TOKEN_RIGHT_PAREN on success, + * the GTokenType they would have expected but didn't get + * or G_TOKEN_NONE if they got the expected token but + * couldn't parse it. + */ + +static GTokenType gimp_config_deserialize_value (GValue *value, + GimpConfig *config, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_fundamental (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_enum (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_memsize (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_path (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_rgb (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_matrix2 (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_object (GValue *value, + GimpConfig *config, + GParamSpec *prop_spec, + GScanner *scanner, + gint nest_level); +static GTokenType gimp_config_deserialize_value_array (GValue *value, + GimpConfig *config, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_unit (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_file_value (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_deserialize_any (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner); +static GTokenType gimp_config_skip_unknown_property (GScanner *scanner); + +static inline gboolean scanner_string_utf8_valid (GScanner *scanner, + const gchar *token_name); + +static inline gboolean +scanner_string_utf8_valid (GScanner *scanner, + const gchar *token_name) +{ + if (g_utf8_validate (scanner->value.v_string, -1, NULL)) + return TRUE; + + g_scanner_error (scanner, + _("value for token %s is not a valid UTF-8 string"), + token_name); + + return FALSE; +} + +/** + * gimp_config_deserialize_properties: + * @config: a #GimpConfig. + * @scanner: a #GScanner. + * @nest_level: the nest level + * + * This function uses the @scanner to configure the properties of @config. + * + * Return value: %TRUE on success, %FALSE otherwise. + * + * Since: 2.4 + **/ +gboolean +gimp_config_deserialize_properties (GimpConfig *config, + GScanner *scanner, + gint nest_level) +{ + GObjectClass *klass; + GParamSpec **property_specs; + guint n_property_specs; + guint i; + guint scope_id; + guint old_scope_id; + GTokenType token; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + + klass = G_OBJECT_GET_CLASS (config); + property_specs = g_object_class_list_properties (klass, &n_property_specs); + + if (! property_specs) + return TRUE; + + scope_id = g_type_qname (G_TYPE_FROM_INSTANCE (config)); + old_scope_id = g_scanner_set_scope (scanner, scope_id); + + for (i = 0; i < n_property_specs; i++) + { + GParamSpec *prop_spec = property_specs[i]; + + if (prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE) + { + g_scanner_scope_add_symbol (scanner, scope_id, + prop_spec->name, prop_spec); + } + } + + g_free (property_specs); + + g_object_freeze_notify (G_OBJECT (config)); + + token = G_TOKEN_LEFT_PAREN; + + while (TRUE) + { + GTokenType next = g_scanner_peek_next_token (scanner); + + if (next == G_TOKEN_EOF) + break; + + if (G_UNLIKELY (next != token && + ! (token == G_TOKEN_SYMBOL && + next == G_TOKEN_IDENTIFIER))) + { + break; + } + + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case G_TOKEN_LEFT_PAREN: + token = G_TOKEN_SYMBOL; + break; + + case G_TOKEN_IDENTIFIER: + token = gimp_config_skip_unknown_property (scanner); + break; + + case G_TOKEN_SYMBOL: + token = gimp_config_deserialize_property (config, + scanner, nest_level); + break; + + case G_TOKEN_RIGHT_PAREN: + token = G_TOKEN_LEFT_PAREN; + break; + + default: /* do nothing */ + break; + } + } + + g_scanner_set_scope (scanner, old_scope_id); + + g_object_thaw_notify (G_OBJECT (config)); + + if (token == G_TOKEN_NONE) + return FALSE; + + return gimp_config_deserialize_return (scanner, token, nest_level); +} + +/** + * gimp_config_deserialize_property: + * @config: a #GimpConfig. + * @scanner: a #GScanner. + * @nest_level: the nest level + * + * This function deserializes a single property of @config. You + * shouldn't need to call this function directly. If possible, use + * gimp_config_deserialize_properties() instead. + * + * Return value: %G_TOKEN_RIGHT_PAREN on success, otherwise the + * expected #GTokenType or %G_TOKEN_NONE if the expected token was + * found but couldn't be parsed. + * + * Since: 2.4 + **/ +GTokenType +gimp_config_deserialize_property (GimpConfig *config, + GScanner *scanner, + gint nest_level) +{ + GimpConfigInterface *config_iface = NULL; + GimpConfigInterface *parent_iface = NULL; + GParamSpec *prop_spec; + GTokenType token = G_TOKEN_RIGHT_PAREN; + GValue value = G_VALUE_INIT; + guint old_scope_id; + + old_scope_id = g_scanner_set_scope (scanner, 0); + + prop_spec = G_PARAM_SPEC (scanner->value.v_symbol); + + g_value_init (&value, prop_spec->value_type); + + if (G_TYPE_IS_OBJECT (prop_spec->owner_type)) + { + GTypeClass *owner_class = g_type_class_peek (prop_spec->owner_type); + + config_iface = g_type_interface_peek (owner_class, GIMP_TYPE_CONFIG); + + /* We must call deserialize_property() *only* if the *exact* class + * which implements it is param_spec->owner_type's class. + * + * Therefore, we ask param_spec->owner_type's immediate parent class + * for it's GimpConfigInterface and check if we get a different + * pointer. + * + * (if the pointers are the same, param_spec->owner_type's + * GimpConfigInterface is inherited from one of it's parent classes + * and thus not able to handle param_spec->owner_type's properties). + */ + if (config_iface) + { + GTypeClass *owner_parent_class; + + owner_parent_class = g_type_class_peek_parent (owner_class); + + parent_iface = g_type_interface_peek (owner_parent_class, + GIMP_TYPE_CONFIG); + } + } + + if (config_iface && + config_iface != parent_iface && /* see comment above */ + config_iface->deserialize_property && + config_iface->deserialize_property (config, + prop_spec->param_id, + &value, + prop_spec, + scanner, + &token)) + { + /* nop */ + } + else + { + if (G_VALUE_HOLDS_OBJECT (&value) && + G_VALUE_TYPE (&value) != G_TYPE_FILE) + { + token = gimp_config_deserialize_object (&value, + config, prop_spec, + scanner, nest_level); + } + else + { + token = gimp_config_deserialize_value (&value, + config, prop_spec, scanner); + } + } + + if (token == G_TOKEN_RIGHT_PAREN && + g_scanner_peek_next_token (scanner) == token) + { + if (! (G_VALUE_HOLDS_OBJECT (&value) && + (prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE))) + g_object_set_property (G_OBJECT (config), prop_spec->name, &value); + } +#ifdef CONFIG_DEBUG + else + { + g_warning ("%s: couldn't deserialize property %s::%s of type %s", + G_STRFUNC, + g_type_name (G_TYPE_FROM_INSTANCE (config)), + prop_spec->name, + g_type_name (prop_spec->value_type)); + } +#endif + + g_value_unset (&value); + + g_scanner_set_scope (scanner, old_scope_id); + + return token; +} + +static GTokenType +gimp_config_deserialize_value (GValue *value, + GimpConfig *config, + GParamSpec *prop_spec, + GScanner *scanner) +{ + if (G_TYPE_FUNDAMENTAL (prop_spec->value_type) == G_TYPE_ENUM) + { + return gimp_config_deserialize_enum (value, prop_spec, scanner); + } + else if (G_TYPE_IS_FUNDAMENTAL (prop_spec->value_type)) + { + return gimp_config_deserialize_fundamental (value, prop_spec, scanner); + } + else if (prop_spec->value_type == GIMP_TYPE_MEMSIZE) + { + return gimp_config_deserialize_memsize (value, prop_spec, scanner); + } + else if (prop_spec->value_type == GIMP_TYPE_CONFIG_PATH) + { + return gimp_config_deserialize_path (value, prop_spec, scanner); + } + else if (prop_spec->value_type == GIMP_TYPE_RGB) + { + return gimp_config_deserialize_rgb (value, prop_spec, scanner); + } + else if (prop_spec->value_type == GIMP_TYPE_MATRIX2) + { + return gimp_config_deserialize_matrix2 (value, prop_spec, scanner); + } + else if (prop_spec->value_type == GIMP_TYPE_VALUE_ARRAY) + { + return gimp_config_deserialize_value_array (value, + config, prop_spec, scanner); + } + else if (prop_spec->value_type == GIMP_TYPE_UNIT) + { + return gimp_config_deserialize_unit (value, prop_spec, scanner); + } + else if (prop_spec->value_type == G_TYPE_FILE) + { + return gimp_config_deserialize_file_value (value, prop_spec, scanner); + } + + /* This fallback will only work for value_types that + * can be transformed from a string value. + */ + return gimp_config_deserialize_any (value, prop_spec, scanner); +} + +static GTokenType +gimp_config_deserialize_fundamental (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + GTokenType token; + GTokenType next_token; + GType value_type; + gboolean negate = FALSE; + + value_type = G_TYPE_FUNDAMENTAL (prop_spec->value_type); + + switch (value_type) + { + case G_TYPE_STRING: + token = G_TOKEN_STRING; + break; + + case G_TYPE_BOOLEAN: + token = G_TOKEN_IDENTIFIER; + break; + + case G_TYPE_INT: + case G_TYPE_LONG: + case G_TYPE_INT64: + if (g_scanner_peek_next_token (scanner) == '-') + { + negate = TRUE; + g_scanner_get_next_token (scanner); + } + /* fallthrough */ + case G_TYPE_UINT: + case G_TYPE_ULONG: + case G_TYPE_UINT64: + token = G_TOKEN_INT; + break; + + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + if (g_scanner_peek_next_token (scanner) == '-') + { + negate = TRUE; + g_scanner_get_next_token (scanner); + } + token = G_TOKEN_FLOAT; + break; + + default: + g_assert_not_reached (); + break; + } + + next_token = g_scanner_peek_next_token (scanner); + + /* we parse integers into floats too, because g_ascii_dtostr() + * serialized whole number without decimal point + */ + if (next_token != token && + ! (token == G_TOKEN_FLOAT && next_token == G_TOKEN_INT)) + { + return token; + } + + g_scanner_get_next_token (scanner); + + switch (value_type) + { + case G_TYPE_STRING: + if (scanner_string_utf8_valid (scanner, prop_spec->name)) + g_value_set_string (value, scanner->value.v_string); + else + return G_TOKEN_NONE; + break; + + case G_TYPE_BOOLEAN: + if (! g_ascii_strcasecmp (scanner->value.v_identifier, "yes") || + ! g_ascii_strcasecmp (scanner->value.v_identifier, "true")) + g_value_set_boolean (value, TRUE); + else if (! g_ascii_strcasecmp (scanner->value.v_identifier, "no") || + ! g_ascii_strcasecmp (scanner->value.v_identifier, "false")) + g_value_set_boolean (value, FALSE); + else + { + g_scanner_error + (scanner, + /* please don't translate 'yes' and 'no' */ + _("expected 'yes' or 'no' for boolean token %s, got '%s'"), + prop_spec->name, scanner->value.v_identifier); + return G_TOKEN_NONE; + } + break; + + case G_TYPE_INT: + g_value_set_int (value, (negate ? + - (gint) scanner->value.v_int64 : + (gint) scanner->value.v_int64)); + break; + case G_TYPE_UINT: + g_value_set_uint (value, scanner->value.v_int64); + break; + + case G_TYPE_LONG: + g_value_set_long (value, (negate ? + - (glong) scanner->value.v_int64 : + (glong) scanner->value.v_int64)); + break; + case G_TYPE_ULONG: + g_value_set_ulong (value, scanner->value.v_int64); + break; + + case G_TYPE_INT64: + g_value_set_int64 (value, (negate ? + - (gint64) scanner->value.v_int64 : + (gint64) scanner->value.v_int64)); + break; + case G_TYPE_UINT64: + g_value_set_uint64 (value, scanner->value.v_int64); + break; + + case G_TYPE_FLOAT: + if (next_token == G_TOKEN_FLOAT) + g_value_set_float (value, negate ? + - scanner->value.v_float : + scanner->value.v_float); + else + g_value_set_float (value, negate ? + - (gfloat) scanner->value.v_int : + (gfloat) scanner->value.v_int); + break; + + case G_TYPE_DOUBLE: + if (next_token == G_TOKEN_FLOAT) + g_value_set_double (value, negate ? + - scanner->value.v_float: + scanner->value.v_float); + else + g_value_set_double (value, negate ? + - (gdouble) scanner->value.v_int: + (gdouble) scanner->value.v_int); + break; + + default: + g_assert_not_reached (); + break; + } + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_deserialize_enum (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + GEnumClass *enum_class; + GEnumValue *enum_value; + + enum_class = g_type_class_peek (G_VALUE_TYPE (value)); + + switch (g_scanner_peek_next_token (scanner)) + { + case G_TOKEN_IDENTIFIER: + g_scanner_get_next_token (scanner); + + enum_value = g_enum_get_value_by_nick (enum_class, + scanner->value.v_identifier); + if (! enum_value) + enum_value = g_enum_get_value_by_name (enum_class, + scanner->value.v_identifier); + if (! enum_value) + { + /* if the value was not found, check if we have a compat + * enum to find the ideitifier + */ + GQuark quark = g_quark_from_static_string ("gimp-compat-enum"); + GType compat_type = (GType) g_type_get_qdata (G_VALUE_TYPE (value), + quark); + + if (compat_type) + { + GEnumClass *compat_class = g_type_class_ref (compat_type); + + enum_value = g_enum_get_value_by_nick (compat_class, + scanner->value.v_identifier); + if (! enum_value) + enum_value = g_enum_get_value_by_name (compat_class, + scanner->value.v_identifier); + + /* finally, if we found a compat value, make sure the + * same value exists in the original enum + */ + if (enum_value) + enum_value = g_enum_get_value (enum_class, enum_value->value); + + g_type_class_unref (compat_class); + } + } + + if (! enum_value) + { + g_scanner_error (scanner, + _("invalid value '%s' for token %s"), + scanner->value.v_identifier, prop_spec->name); + return G_TOKEN_NONE; + } + break; + + case G_TOKEN_INT: + g_scanner_get_next_token (scanner); + + enum_value = g_enum_get_value (enum_class, + (gint) scanner->value.v_int64); + + if (! enum_value) + { + g_scanner_error (scanner, + _("invalid value '%ld' for token %s"), + (glong) scanner->value.v_int64, prop_spec->name); + return G_TOKEN_NONE; + } + break; + + default: + return G_TOKEN_IDENTIFIER; + } + + g_value_set_enum (value, enum_value->value); + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_deserialize_memsize (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + gchar *orig_cset_first = scanner->config->cset_identifier_first; + gchar *orig_cset_nth = scanner->config->cset_identifier_nth; + guint64 memsize; + + scanner->config->cset_identifier_first = G_CSET_DIGITS; + scanner->config->cset_identifier_nth = G_CSET_DIGITS "gGmMkKbB"; + + if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER) + return G_TOKEN_IDENTIFIER; + + g_scanner_get_next_token (scanner); + + scanner->config->cset_identifier_first = orig_cset_first; + scanner->config->cset_identifier_nth = orig_cset_nth; + + if (! gimp_memsize_deserialize (scanner->value.v_identifier, &memsize)) + return G_TOKEN_NONE; + + g_value_set_uint64 (value, memsize); + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_deserialize_path (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + GError *error = NULL; + + if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING) + return G_TOKEN_STRING; + + g_scanner_get_next_token (scanner); + + if (!scanner_string_utf8_valid (scanner, prop_spec->name)) + return G_TOKEN_NONE; + + if (scanner->value.v_string) + { + /* Check if the string can be expanded + * and converted to the filesystem encoding. + */ + gchar *expand = gimp_config_path_expand (scanner->value.v_string, + TRUE, &error); + + if (!expand) + { + g_scanner_error (scanner, + _("while parsing token '%s': %s"), + prop_spec->name, error->message); + g_error_free (error); + + return G_TOKEN_NONE; + } + + g_free (expand); + + g_value_set_static_string (value, scanner->value.v_string); + } + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_deserialize_rgb (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + GimpRGB rgb; + + if (! gimp_scanner_parse_color (scanner, &rgb)) + return G_TOKEN_NONE; + + g_value_set_boxed (value, &rgb); + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_deserialize_matrix2 (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + GimpMatrix2 matrix; + + if (! gimp_scanner_parse_matrix2 (scanner, &matrix)) + return G_TOKEN_NONE; + + g_value_set_boxed (value, &matrix); + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_deserialize_object (GValue *value, + GimpConfig *config, + GParamSpec *prop_spec, + GScanner *scanner, + gint nest_level) +{ + GimpConfigInterface *config_iface; + GimpConfig *prop_object; + + g_object_get_property (G_OBJECT (config), prop_spec->name, value); + + prop_object = g_value_get_object (value); + + if (! prop_object) + { + /* if the object property is not GIMP_CONFIG_PARAM_AGGREGATE, read + * the type of the object and create it + */ + if (! (prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE)) + { + gchar *type_name; + GType type; + + if (! gimp_scanner_parse_string (scanner, &type_name)) + return G_TOKEN_STRING; + + if (! (type_name && *type_name)) + { + g_scanner_error (scanner, "Type name is empty"); + g_free (type_name); + return G_TOKEN_NONE; + } + + type = g_type_from_name (type_name); + g_free (type_name); + + if (! g_type_is_a (type, prop_spec->value_type)) + return G_TOKEN_STRING; + + prop_object = g_object_new (type, NULL); + + g_value_take_object (value, prop_object); + } + else + { + return G_TOKEN_RIGHT_PAREN; + } + } + + config_iface = GIMP_CONFIG_GET_INTERFACE (prop_object); + + if (! config_iface) + return gimp_config_deserialize_any (value, prop_spec, scanner); + + if (! config_iface->deserialize (prop_object, scanner, nest_level + 1, NULL)) + return G_TOKEN_NONE; + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_deserialize_value_array (GValue *value, + GimpConfig *config, + GParamSpec *prop_spec, + GScanner *scanner) +{ + GimpParamSpecValueArray *array_spec; + GimpValueArray *array; + GValue array_value = G_VALUE_INIT; + gint n_values; + GTokenType token; + gint i; + + array_spec = GIMP_PARAM_SPEC_VALUE_ARRAY (prop_spec); + + if (! gimp_scanner_parse_int (scanner, &n_values)) + return G_TOKEN_INT; + + array = gimp_value_array_new (n_values); + + for (i = 0; i < n_values; i++) + { + g_value_init (&array_value, array_spec->element_spec->value_type); + + token = gimp_config_deserialize_value (&array_value, + config, + array_spec->element_spec, + scanner); + + if (token == G_TOKEN_RIGHT_PAREN) + gimp_value_array_append (array, &array_value); + + g_value_unset (&array_value); + + if (token != G_TOKEN_RIGHT_PAREN) + return token; + } + + g_value_take_boxed (value, array); + + return G_TOKEN_RIGHT_PAREN; +} + +/* This function is entirely sick, so is our method of serializing + * units, which we write out as (unit foo bar) instead of + * (unit "foo bar"). The assumption that caused this shit was that a + * unit's "identifier" is really an identifier in the C-ish sense, + * when in fact it's just a random user entered string. + * + * Here, we try to parse at least the default units shipped with gimp, + * and we add code to parse (unit "foo bar") in order to be compatible + * with future correct unit serializing. + */ +static GTokenType +gimp_config_deserialize_unit (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + gchar *old_cset_skip_characters; + gchar *old_cset_identifier_first; + gchar *old_cset_identifier_nth; + GString *buffer; + GValue src = G_VALUE_INIT; + GTokenType token; + + /* parse the next token *before* reconfiguring the scanner, so it + * skips whitespace first + */ + token = g_scanner_peek_next_token (scanner); + + if (token == G_TOKEN_STRING) + return gimp_config_deserialize_any (value, prop_spec, scanner); + + old_cset_skip_characters = scanner->config->cset_skip_characters; + old_cset_identifier_first = scanner->config->cset_identifier_first; + old_cset_identifier_nth = scanner->config->cset_identifier_nth; + + scanner->config->cset_skip_characters = ""; + scanner->config->cset_identifier_first = ( G_CSET_a_2_z G_CSET_A_2_Z "." ); + scanner->config->cset_identifier_nth = ( G_CSET_a_2_z G_CSET_A_2_Z + G_CSET_DIGITS "-_." ); + + buffer = g_string_new (""); + + while (g_scanner_peek_next_token (scanner) != G_TOKEN_RIGHT_PAREN) + { + token = g_scanner_peek_next_token (scanner); + + if (token == G_TOKEN_IDENTIFIER) + { + g_scanner_get_next_token (scanner); + g_string_append (buffer, scanner->value.v_identifier); + } + else if (token == G_TOKEN_CHAR) + { + g_scanner_get_next_token (scanner); + g_string_append_c (buffer, scanner->value.v_char); + } + else if (token == ' ') + { + g_scanner_get_next_token (scanner); + g_string_append_c (buffer, token); + } + else + { + token = G_TOKEN_IDENTIFIER; + goto cleanup; + } + } + + g_value_init (&src, G_TYPE_STRING); + g_value_set_static_string (&src, buffer->str); + g_value_transform (&src, value); + g_value_unset (&src); + + token = G_TOKEN_RIGHT_PAREN; + + cleanup: + + g_string_free (buffer, TRUE); + + scanner->config->cset_skip_characters = old_cset_skip_characters; + scanner->config->cset_identifier_first = old_cset_identifier_first; + scanner->config->cset_identifier_nth = old_cset_identifier_nth; + + return token; +} + +static GTokenType +gimp_config_deserialize_file_value (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + GTokenType token; + + token = g_scanner_peek_next_token (scanner); + + if (token != G_TOKEN_IDENTIFIER && + token != G_TOKEN_STRING) + { + return G_TOKEN_STRING; + } + + g_scanner_get_next_token (scanner); + + if (token == G_TOKEN_IDENTIFIER) + { + /* this is supposed to parse a literal "NULL" only, but so what... */ + g_value_set_object (value, NULL); + } + else + { + gchar *path = gimp_config_path_expand (scanner->value.v_string, TRUE, + NULL); + + if (path) + { + GFile *file = g_file_new_for_path (path); + + g_value_take_object (value, file); + g_free (path); + } + else + { + g_value_set_object (value, NULL); + } + } + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_deserialize_any (GValue *value, + GParamSpec *prop_spec, + GScanner *scanner) +{ + GValue src = G_VALUE_INIT; + GTokenType token; + + if (!g_value_type_transformable (G_TYPE_STRING, prop_spec->value_type)) + { + g_warning ("%s: %s can not be transformed from a string", + G_STRFUNC, g_type_name (prop_spec->value_type)); + return G_TOKEN_NONE; + } + + token = g_scanner_peek_next_token (scanner); + + if (token != G_TOKEN_IDENTIFIER && + token != G_TOKEN_STRING) + { + return G_TOKEN_IDENTIFIER; + } + + g_scanner_get_next_token (scanner); + + g_value_init (&src, G_TYPE_STRING); + + if (token == G_TOKEN_IDENTIFIER) + g_value_set_static_string (&src, scanner->value.v_identifier); + else + g_value_set_static_string (&src, scanner->value.v_string); + + g_value_transform (&src, value); + g_value_unset (&src); + + return G_TOKEN_RIGHT_PAREN; +} + +static GTokenType +gimp_config_skip_unknown_property (GScanner *scanner) +{ + gint open_paren = 0; + + while (TRUE) + { + GTokenType token = g_scanner_peek_next_token (scanner); + + switch (token) + { + case G_TOKEN_LEFT_PAREN: + open_paren++; + g_scanner_get_next_token (scanner); + break; + + case G_TOKEN_RIGHT_PAREN: + if (open_paren == 0) + return token; + + open_paren--; + g_scanner_get_next_token (scanner); + break; + + case G_TOKEN_EOF: + return token; + + default: + g_scanner_get_next_token (scanner); + break; + } + } +} diff --git a/libgimpconfig/gimpconfig-deserialize.h b/libgimpconfig/gimpconfig-deserialize.h new file mode 100644 index 0000000..271a20d --- /dev/null +++ b/libgimpconfig/gimpconfig-deserialize.h @@ -0,0 +1,44 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * Object properties deserialization routines + * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_CONFIG_DESERIALIZE_H__ +#define __GIMP_CONFIG_DESERIALIZE_H__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + + +gboolean gimp_config_deserialize_properties (GimpConfig *config, + GScanner *scanner, + gint nest_level); +GTokenType gimp_config_deserialize_property (GimpConfig *config, + GScanner *scanner, + gint nest_level); + + +G_END_DECLS + +#endif /* __GIMP_CONFIG_DESERIALIZE_H__ */ diff --git a/libgimpconfig/gimpconfig-error.c b/libgimpconfig/gimpconfig-error.c new file mode 100644 index 0000000..ed57cb0 --- /dev/null +++ b/libgimpconfig/gimpconfig-error.c @@ -0,0 +1,51 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Config file serialization and deserialization interface + * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <glib.h> + +#include "gimpconfig-error.h" + + +/** + * SECTION: gimpconfig-error + * @title: GimpConfig-error + * @short_description: Error utils for libgimpconfig. + * + * Error utils for libgimpconfig. + **/ + + +/** + * gimp_config_error_quark: + * + * This function is never called directly. Use GIMP_CONFIG_ERROR() instead. + * + * Return value: the #GQuark that defines the GimpConfig error domain. + * + * Since: 2.4 + **/ +GQuark +gimp_config_error_quark (void) +{ + return g_quark_from_static_string ("gimp-config-error-quark"); +} diff --git a/libgimpconfig/gimpconfig-error.h b/libgimpconfig/gimpconfig-error.h new file mode 100644 index 0000000..a20884e --- /dev/null +++ b/libgimpconfig/gimpconfig-error.h @@ -0,0 +1,59 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Copyright (C) 2003 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_CONFIG_ERROR_H__ +#define __GIMP_CONFIG_ERROR_H__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + + +/** + * GimpConfigError: + * @GIMP_CONFIG_ERROR_OPEN: open failed + * @GIMP_CONFIG_ERROR_OPEN_ENOENT: file does not exist + * @GIMP_CONFIG_ERROR_WRITE: write failed + * @GIMP_CONFIG_ERROR_PARSE: parser error + * @GIMP_CONFIG_ERROR_VERSION: parser failed due to version mismatch + * + * The possible values of a #GError thrown by libgimpconfig. + **/ +typedef enum +{ + GIMP_CONFIG_ERROR_OPEN, + GIMP_CONFIG_ERROR_OPEN_ENOENT, + GIMP_CONFIG_ERROR_WRITE, + GIMP_CONFIG_ERROR_PARSE, + GIMP_CONFIG_ERROR_VERSION +} GimpConfigError; + +#define GIMP_CONFIG_ERROR (gimp_config_error_quark ()) + +GQuark gimp_config_error_quark (void) G_GNUC_CONST; + + +G_END_DECLS + +#endif /* __GIMP_CONFIG_ERROR_H__ */ diff --git a/libgimpconfig/gimpconfig-iface.c b/libgimpconfig/gimpconfig-iface.c new file mode 100644 index 0000000..6604aca --- /dev/null +++ b/libgimpconfig/gimpconfig-iface.c @@ -0,0 +1,859 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Config file serialization and deserialization interface + * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> + +#include <gio/gio.h> + +#include "libgimpbase/gimpbase.h" + +#include "gimpconfigtypes.h" + +#include "gimpconfigwriter.h" +#include "gimpconfig-iface.h" +#include "gimpconfig-deserialize.h" +#include "gimpconfig-serialize.h" +#include "gimpconfig-params.h" +#include "gimpconfig-utils.h" +#include "gimpscanner.h" + +#include "libgimp/libgimp-intl.h" + + +/** + * SECTION: gimpconfig-iface + * @title: GimpConfig-iface + * @short_description: High-level API for libgimpconfig. + * + * High-level API for libgimpconfig. + **/ + + +/* + * The GimpConfig serialization and deserialization interface. + */ + + +/* local function prototypes */ + +static void gimp_config_iface_default_init (GimpConfigInterface *iface); +static void gimp_config_iface_base_init (GimpConfigInterface *iface); + +static gboolean gimp_config_iface_serialize (GimpConfig *config, + GimpConfigWriter *writer, + gpointer data); +static gboolean gimp_config_iface_deserialize (GimpConfig *config, + GScanner *scanner, + gint nest_level, + gpointer data); +static GimpConfig * gimp_config_iface_duplicate (GimpConfig *config); +static gboolean gimp_config_iface_equal (GimpConfig *a, + GimpConfig *b); +static void gimp_config_iface_reset (GimpConfig *config); +static gboolean gimp_config_iface_copy (GimpConfig *src, + GimpConfig *dest, + GParamFlags flags); + + +/* private functions */ + + +GType +gimp_config_get_type (void) +{ + static GType config_iface_type = 0; + + if (! config_iface_type) + { + const GTypeInfo config_iface_info = + { + sizeof (GimpConfigInterface), + (GBaseInitFunc) gimp_config_iface_base_init, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gimp_config_iface_default_init, + (GClassFinalizeFunc) NULL, + }; + + config_iface_type = g_type_register_static (G_TYPE_INTERFACE, + "GimpConfigInterface", + &config_iface_info, + 0); + + g_type_interface_add_prerequisite (config_iface_type, G_TYPE_OBJECT); + } + + return config_iface_type; +} + +GType +gimp_config_interface_get_type (void) +{ + return gimp_config_get_type (); +} + +static void +gimp_config_iface_default_init (GimpConfigInterface *iface) +{ + iface->serialize = gimp_config_iface_serialize; + iface->deserialize = gimp_config_iface_deserialize; + iface->duplicate = gimp_config_iface_duplicate; + iface->equal = gimp_config_iface_equal; + iface->reset = gimp_config_iface_reset; + iface->copy = gimp_config_iface_copy; +} + +static void +gimp_config_iface_base_init (GimpConfigInterface *iface) +{ + /* always set these to NULL since we don't want to inherit them + * from parent classes + */ + iface->serialize_property = NULL; + iface->deserialize_property = NULL; +} + +static gboolean +gimp_config_iface_serialize (GimpConfig *config, + GimpConfigWriter *writer, + gpointer data) +{ + return gimp_config_serialize_properties (config, writer); +} + +static gboolean +gimp_config_iface_deserialize (GimpConfig *config, + GScanner *scanner, + gint nest_level, + gpointer data) +{ + return gimp_config_deserialize_properties (config, scanner, nest_level); +} + +static GimpConfig * +gimp_config_iface_duplicate (GimpConfig *config) +{ + GObject *object = G_OBJECT (config); + GObjectClass *klass = G_OBJECT_GET_CLASS (object); + GParamSpec **property_specs; + guint n_property_specs; + gint n_construct_properties = 0; + const gchar **construct_names = NULL; + GValue *construct_values = NULL; + guint i; + GObject *dup; + + property_specs = g_object_class_list_properties (klass, &n_property_specs); + + construct_names = g_new0 (const gchar *, n_property_specs); + construct_values = g_new0 (GValue, n_property_specs); + + for (i = 0; i < n_property_specs; i++) + { + GParamSpec *prop_spec = property_specs[i]; + + if ((prop_spec->flags & G_PARAM_READABLE) && + (prop_spec->flags & G_PARAM_WRITABLE) && + (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY)) + { + construct_names[n_construct_properties] = prop_spec->name; + + g_value_init (&construct_values[n_construct_properties], + prop_spec->value_type); + g_object_get_property (object, prop_spec->name, + &construct_values[n_construct_properties]); + + n_construct_properties++; + } + } + + g_free (property_specs); + + dup = g_object_new_with_properties (G_TYPE_FROM_INSTANCE (object), + n_construct_properties, + (const gchar **) construct_names, + (const GValue *) construct_values); + + for (i = 0; i < n_construct_properties; i++) + g_value_unset (&construct_values[i]); + + g_free (construct_names); + g_free (construct_values); + + gimp_config_copy (config, GIMP_CONFIG (dup), 0); + + return GIMP_CONFIG (dup); +} + +static gboolean +gimp_config_iface_equal (GimpConfig *a, + GimpConfig *b) +{ + GObjectClass *klass; + GParamSpec **property_specs; + guint n_property_specs; + guint i; + gboolean equal = TRUE; + + klass = G_OBJECT_GET_CLASS (a); + + property_specs = g_object_class_list_properties (klass, &n_property_specs); + + for (i = 0; equal && i < n_property_specs; i++) + { + GParamSpec *prop_spec; + GValue a_value = G_VALUE_INIT; + GValue b_value = G_VALUE_INIT; + + prop_spec = property_specs[i]; + + if (! (prop_spec->flags & G_PARAM_READABLE)) + continue; + + g_value_init (&a_value, prop_spec->value_type); + g_value_init (&b_value, prop_spec->value_type); + g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value); + g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value); + + if (g_param_values_cmp (prop_spec, &a_value, &b_value)) + { + if ((prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE) && + G_IS_PARAM_SPEC_OBJECT (prop_spec) && + g_type_interface_peek (g_type_class_peek (prop_spec->value_type), + GIMP_TYPE_CONFIG)) + { + if (! gimp_config_is_equal_to (g_value_get_object (&a_value), + g_value_get_object (&b_value))) + { + equal = FALSE; + } + } + else + { + equal = FALSE; + } + } + + g_value_unset (&a_value); + g_value_unset (&b_value); + } + + g_free (property_specs); + + return equal; +} + +static void +gimp_config_iface_reset (GimpConfig *config) +{ + gimp_config_reset_properties (G_OBJECT (config)); +} + +static gboolean +gimp_config_iface_copy (GimpConfig *src, + GimpConfig *dest, + GParamFlags flags) +{ + return gimp_config_sync (G_OBJECT (src), G_OBJECT (dest), flags); +} + + +/* public functions */ + + +/** + * gimp_config_serialize_to_file: + * @config: a #GObject that implements the #GimpConfigInterface. + * @filename: the name of the file to write the configuration to. + * @header: optional file header (must be ASCII only) + * @footer: optional file footer (must be ASCII only) + * @data: user data passed to the serialize implementation. + * @error: return location for a possible error + * + * Serializes the object properties of @config to the file specified + * by @filename. If a file with that name already exists, it is + * overwritten. Basically this function opens @filename for you and + * calls the serialize function of the @config's #GimpConfigInterface. + * + * Return value: %TRUE if serialization succeeded, %FALSE otherwise. + * + * Since: 2.4 + **/ +gboolean +gimp_config_serialize_to_file (GimpConfig *config, + const gchar *filename, + const gchar *header, + const gchar *footer, + gpointer data, + GError **error) +{ + GimpConfigWriter *writer; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + g_return_val_if_fail (filename != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + writer = gimp_config_writer_new_file (filename, TRUE, header, error); + if (!writer) + return FALSE; + + GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data); + + return gimp_config_writer_finish (writer, footer, error); +} + +/** + * gimp_config_serialize_to_gfile: + * @config: a #GObject that implements the #GimpConfigInterface. + * @file: the #GFile to write the configuration to. + * @header: optional file header (must be ASCII only) + * @footer: optional file footer (must be ASCII only) + * @data: user data passed to the serialize implementation. + * @error: return location for a possible error + * + * Serializes the object properties of @config to the file specified + * by @file. If a file with that name already exists, it is + * overwritten. Basically this function opens @file for you and calls + * the serialize function of the @config's #GimpConfigInterface. + * + * Return value: %TRUE if serialization succeeded, %FALSE otherwise. + * + * Since: 2.10 + **/ +gboolean +gimp_config_serialize_to_gfile (GimpConfig *config, + GFile *file, + const gchar *header, + const gchar *footer, + gpointer data, + GError **error) +{ + GimpConfigWriter *writer; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + writer = gimp_config_writer_new_gfile (file, TRUE, header, error); + if (!writer) + return FALSE; + + GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data); + + return gimp_config_writer_finish (writer, footer, error); +} + +/** + * gimp_config_serialize_to_stream: + * @config: a #GObject that implements the #GimpConfigInterface. + * @output: the #GOutputStream to write the configuration to. + * @header: optional file header (must be ASCII only) + * @footer: optional file footer (must be ASCII only) + * @data: user data passed to the serialize implementation. + * @error: return location for a possible error + * + * Serializes the object properties of @config to the stream specified + * by @output. + * + * Return value: %TRUE if serialization succeeded, %FALSE otherwise. + * + * Since: 2.10 + **/ +gboolean +gimp_config_serialize_to_stream (GimpConfig *config, + GOutputStream *output, + const gchar *header, + const gchar *footer, + gpointer data, + GError **error) +{ + GimpConfigWriter *writer; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + writer = gimp_config_writer_new_stream (output, header, error); + if (!writer) + return FALSE; + + GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data); + + return gimp_config_writer_finish (writer, footer, error); +} + +/** + * gimp_config_serialize_to_fd: + * @config: a #GObject that implements the #GimpConfigInterface. + * @fd: a file descriptor, opened for writing + * @data: user data passed to the serialize implementation. + * + * Serializes the object properties of @config to the given file + * descriptor. + * + * Return value: %TRUE if serialization succeeded, %FALSE otherwise. + * + * Since: 2.4 + **/ +gboolean +gimp_config_serialize_to_fd (GimpConfig *config, + gint fd, + gpointer data) +{ + GimpConfigWriter *writer; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + g_return_val_if_fail (fd > 0, FALSE); + + writer = gimp_config_writer_new_fd (fd); + if (!writer) + return FALSE; + + GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data); + + return gimp_config_writer_finish (writer, NULL, NULL); +} + +/** + * gimp_config_serialize_to_string: + * @config: a #GObject that implements the #GimpConfigInterface. + * @data: user data passed to the serialize implementation. + * + * Serializes the object properties of @config to a string. + * + * Return value: a newly allocated NUL-terminated string. + * + * Since: 2.4 + **/ +gchar * +gimp_config_serialize_to_string (GimpConfig *config, + gpointer data) +{ + GimpConfigWriter *writer; + GString *str; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL); + + str = g_string_new (NULL); + writer = gimp_config_writer_new_string (str); + + GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data); + + gimp_config_writer_finish (writer, NULL, NULL); + + return g_string_free (str, FALSE); +} + +/** + * gimp_config_deserialize_file: + * @config: a #GObject that implements the #GimpConfigInterface. + * @filename: the name of the file to read configuration from. + * @data: user data passed to the deserialize implementation. + * @error: return location for a possible error + * + * Opens the file specified by @filename, reads configuration data + * from it and configures @config accordingly. Basically this function + * creates a properly configured #GScanner for you and calls the + * deserialize function of the @config's #GimpConfigInterface. + * + * Return value: %TRUE if deserialization succeeded, %FALSE otherwise. + * + * Since: 2.4 + **/ +gboolean +gimp_config_deserialize_file (GimpConfig *config, + const gchar *filename, + gpointer data, + GError **error) +{ + GScanner *scanner; + gboolean success; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + g_return_val_if_fail (filename != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + scanner = gimp_scanner_new_file (filename, error); + if (! scanner) + return FALSE; + + g_object_freeze_notify (G_OBJECT (config)); + + success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config, + scanner, 0, data); + + g_object_thaw_notify (G_OBJECT (config)); + + gimp_scanner_destroy (scanner); + + if (! success) + g_assert (error == NULL || *error != NULL); + + return success; +} + +/** + * gimp_config_deserialize_gfile: + * @config: a #GObject that implements the #GimpConfigInterface. + * @file: the #GFile to read configuration from. + * @data: user data passed to the deserialize implementation. + * @error: return location for a possible error + * + * Opens the file specified by @file, reads configuration data from it + * and configures @config accordingly. Basically this function creates + * a properly configured #GScanner for you and calls the deserialize + * function of the @config's #GimpConfigInterface. + * + * Return value: %TRUE if deserialization succeeded, %FALSE otherwise. + * + * Since: 2.10 + **/ +gboolean +gimp_config_deserialize_gfile (GimpConfig *config, + GFile *file, + gpointer data, + GError **error) +{ + GScanner *scanner; + gboolean success; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + scanner = gimp_scanner_new_gfile (file, error); + if (! scanner) + return FALSE; + + g_object_freeze_notify (G_OBJECT (config)); + + success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config, + scanner, 0, data); + + g_object_thaw_notify (G_OBJECT (config)); + + gimp_scanner_destroy (scanner); + + if (! success) + g_assert (error == NULL || *error != NULL); + + return success; +} + +/** + * gimp_config_deserialize_stream: + * @config: a #GObject that implements the #GimpConfigInterface. + * @input: the #GInputStream to read configuration from. + * @data: user data passed to the deserialize implementation. + * @error: return location for a possible error + * + * Reads configuration data from @input and configures @config + * accordingly. Basically this function creates a properly configured + * #GScanner for you and calls the deserialize function of the + * @config's #GimpConfigInterface. + * + * Return value: %TRUE if deserialization succeeded, %FALSE otherwise. + * + * Since: 2.10 + **/ +gboolean +gimp_config_deserialize_stream (GimpConfig *config, + GInputStream *input, + gpointer data, + GError **error) +{ + GScanner *scanner; + gboolean success; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + g_return_val_if_fail (G_IS_INPUT_STREAM (input), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + scanner = gimp_scanner_new_stream (input, error); + if (! scanner) + return FALSE; + + g_object_freeze_notify (G_OBJECT (config)); + + success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config, + scanner, 0, data); + + g_object_thaw_notify (G_OBJECT (config)); + + gimp_scanner_destroy (scanner); + + if (! success) + g_assert (error == NULL || *error != NULL); + + return success; +} + +/** + * gimp_config_deserialize_string: + * @config: a #GObject that implements the #GimpConfigInterface. + * @text: string to deserialize (in UTF-8 encoding) + * @text_len: length of @text in bytes or -1 + * @data: client data + * @error: return location for a possible error + * + * Configures @config from @text. Basically this function creates a + * properly configured #GScanner for you and calls the deserialize + * function of the @config's #GimpConfigInterface. + * + * Returns: %TRUE if deserialization succeeded, %FALSE otherwise. + * + * Since: 2.4 + **/ +gboolean +gimp_config_deserialize_string (GimpConfig *config, + const gchar *text, + gint text_len, + gpointer data, + GError **error) +{ + GScanner *scanner; + gboolean success; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + g_return_val_if_fail (text != NULL || text_len == 0, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + scanner = gimp_scanner_new_string (text, text_len, error); + + g_object_freeze_notify (G_OBJECT (config)); + + success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config, + scanner, 0, data); + + g_object_thaw_notify (G_OBJECT (config)); + + gimp_scanner_destroy (scanner); + + if (! success) + g_assert (error == NULL || *error != NULL); + + return success; +} + +/** + * gimp_config_deserialize_return: + * @scanner: a #GScanner + * @expected_token: the expected token + * @nest_level: the nest level + * + * Returns: + * + * Since: 2.4 + **/ +gboolean +gimp_config_deserialize_return (GScanner *scanner, + GTokenType expected_token, + gint nest_level) +{ + GTokenType next_token; + + g_return_val_if_fail (scanner != NULL, FALSE); + + next_token = g_scanner_peek_next_token (scanner); + + if (expected_token != G_TOKEN_LEFT_PAREN) + { + g_scanner_get_next_token (scanner); + g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL, + _("fatal parse error"), TRUE); + return FALSE; + } + else + { + if (nest_level > 0 && next_token == G_TOKEN_RIGHT_PAREN) + { + return TRUE; + } + else if (next_token != G_TOKEN_EOF) + { + g_scanner_get_next_token (scanner); + g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL, + _("fatal parse error"), TRUE); + return FALSE; + } + } + + return TRUE; +} + + +/** + * gimp_config_serialize: + * @config: a #GObject that implements the #GimpConfigInterface. + * @writer: the #GimpConfigWriter to use. + * @data: client data + * + * Serialize the #GimpConfig object. + * + * Returns: %TRUE if serialization succeeded, %FALSE otherwise. + * + * Since: 2.8 + **/ +gboolean +gimp_config_serialize (GimpConfig *config, + GimpConfigWriter *writer, + gpointer data) +{ + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + + return GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, + writer, + data); +} + +/** + * gimp_config_deserialize: + * @config: a #GObject that implements the #GimpConfigInterface. + * @scanner: the #GScanner to use. + * @nest_level: the nest level. + * @data: client data. + * + * Deserialize the #GimpConfig object. + * + * Returns: %TRUE if deserialization succeeded, %FALSE otherwise. + * + * Since: 2.8 + **/ +gboolean +gimp_config_deserialize (GimpConfig *config, + GScanner *scanner, + gint nest_level, + gpointer data) +{ + g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE); + + return GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config, + scanner, + nest_level, + data); +} + +/** + * gimp_config_duplicate: + * @config: a #GObject that implements the #GimpConfigInterface. + * + * Creates a copy of the passed object by copying all object + * properties. The default implementation of the #GimpConfigInterface + * only works for objects that are completely defined by their + * properties. + * + * Return value: the duplicated #GimpConfig object + * + * Since: 2.4 + **/ +gpointer +gimp_config_duplicate (GimpConfig *config) +{ + g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL); + + return GIMP_CONFIG_GET_INTERFACE (config)->duplicate (config); +} + +/** + * gimp_config_is_equal_to: + * @a: a #GObject that implements the #GimpConfigInterface. + * @b: another #GObject of the same type as @a. + * + * Compares the two objects. The default implementation of the + * #GimpConfigInterface compares the object properties and thus only + * works for objects that are completely defined by their + * properties. + * + * Return value: %TRUE if the two objects are equal. + * + * Since: 2.4 + **/ +gboolean +gimp_config_is_equal_to (GimpConfig *a, + GimpConfig *b) +{ + g_return_val_if_fail (GIMP_IS_CONFIG (a), FALSE); + g_return_val_if_fail (GIMP_IS_CONFIG (b), FALSE); + g_return_val_if_fail (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b), + FALSE); + + return GIMP_CONFIG_GET_INTERFACE (a)->equal (a, b); +} + +/** + * gimp_config_reset: + * @config: a #GObject that implements the #GimpConfigInterface. + * + * Resets the object to its default state. The default implementation of the + * #GimpConfigInterface only works for objects that are completely defined by + * their properties. + * + * Since: 2.4 + **/ +void +gimp_config_reset (GimpConfig *config) +{ + g_return_if_fail (GIMP_IS_CONFIG (config)); + + g_object_freeze_notify (G_OBJECT (config)); + + GIMP_CONFIG_GET_INTERFACE (config)->reset (config); + + g_object_thaw_notify (G_OBJECT (config)); +} + +/** + * gimp_config_copy: + * @src: a #GObject that implements the #GimpConfigInterface. + * @dest: another #GObject of the same type as @a. + * @flags: a mask of GParamFlags + * + * Compares all read- and write-able properties from @src and @dest + * that have all @flags set. Differing values are then copied from + * @src to @dest. If @flags is 0, all differing read/write properties. + * + * Properties marked as "construct-only" are not touched. + * + * Return value: %TRUE if @dest was modified, %FALSE otherwise + * + * Since: 2.6 + **/ +gboolean +gimp_config_copy (GimpConfig *src, + GimpConfig *dest, + GParamFlags flags) +{ + gboolean changed; + + g_return_val_if_fail (GIMP_IS_CONFIG (src), FALSE); + g_return_val_if_fail (GIMP_IS_CONFIG (dest), FALSE); + g_return_val_if_fail (G_TYPE_FROM_INSTANCE (src) == G_TYPE_FROM_INSTANCE (dest), + FALSE); + + g_object_freeze_notify (G_OBJECT (dest)); + + changed = GIMP_CONFIG_GET_INTERFACE (src)->copy (src, dest, flags); + + g_object_thaw_notify (G_OBJECT (dest)); + + return changed; +} diff --git a/libgimpconfig/gimpconfig-iface.h b/libgimpconfig/gimpconfig-iface.h new file mode 100644 index 0000000..eae41b5 --- /dev/null +++ b/libgimpconfig/gimpconfig-iface.h @@ -0,0 +1,141 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Config file serialization and deserialization interface + * Copyright (C) 2001-2003 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_CONFIG_IFACE_H__ +#define __GIMP_CONFIG_IFACE_H__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + + +#define GIMP_TYPE_CONFIG (gimp_config_get_type ()) +#define GIMP_IS_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CONFIG)) +#define GIMP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CONFIG, GimpConfig)) +#define GIMP_CONFIG_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GIMP_TYPE_CONFIG, GimpConfigInterface)) + + +typedef struct _GimpConfigInterface GimpConfigInterface; + +struct _GimpConfigInterface +{ + GTypeInterface base_iface; + + gboolean (* serialize) (GimpConfig *config, + GimpConfigWriter *writer, + gpointer data); + gboolean (* deserialize) (GimpConfig *config, + GScanner *scanner, + gint nest_level, + gpointer data); + gboolean (* serialize_property) (GimpConfig *config, + guint property_id, + const GValue *value, + GParamSpec *pspec, + GimpConfigWriter *writer); + gboolean (* deserialize_property) (GimpConfig *config, + guint property_id, + GValue *value, + GParamSpec *pspec, + GScanner *scanner, + GTokenType *expected); + GimpConfig * (* duplicate) (GimpConfig *config); + gboolean (* equal) (GimpConfig *a, + GimpConfig *b); + void (* reset) (GimpConfig *config); + gboolean (* copy) (GimpConfig *src, + GimpConfig *dest, + GParamFlags flags); +}; + + +GType gimp_config_get_type (void) G_GNUC_CONST; + +GIMP_DEPRECATED_FOR (gimp_config_get_type) +GType gimp_config_interface_get_type (void) G_GNUC_CONST; + +gboolean gimp_config_serialize_to_file (GimpConfig *config, + const gchar *filename, + const gchar *header, + const gchar *footer, + gpointer data, + GError **error); +gboolean gimp_config_serialize_to_gfile (GimpConfig *config, + GFile *file, + const gchar *header, + const gchar *footer, + gpointer data, + GError **error); +gboolean gimp_config_serialize_to_stream (GimpConfig *config, + GOutputStream *output, + const gchar *header, + const gchar *footer, + gpointer data, + GError **error); +gboolean gimp_config_serialize_to_fd (GimpConfig *config, + gint fd, + gpointer data); +gchar * gimp_config_serialize_to_string (GimpConfig *config, + gpointer data); +gboolean gimp_config_deserialize_file (GimpConfig *config, + const gchar *filename, + gpointer data, + GError **error); +gboolean gimp_config_deserialize_gfile (GimpConfig *config, + GFile *file, + gpointer data, + GError **error); +gboolean gimp_config_deserialize_stream (GimpConfig *config, + GInputStream *input, + gpointer data, + GError **error); +gboolean gimp_config_deserialize_string (GimpConfig *config, + const gchar *text, + gint text_len, + gpointer data, + GError **error); +gboolean gimp_config_deserialize_return (GScanner *scanner, + GTokenType expected_token, + gint nest_level); + +gboolean gimp_config_serialize (GimpConfig *config, + GimpConfigWriter *writer, + gpointer data); +gboolean gimp_config_deserialize (GimpConfig *config, + GScanner *scanner, + gint nest_level, + gpointer data); +gpointer gimp_config_duplicate (GimpConfig *config); +gboolean gimp_config_is_equal_to (GimpConfig *a, + GimpConfig *b); +void gimp_config_reset (GimpConfig *config); +gboolean gimp_config_copy (GimpConfig *src, + GimpConfig *dest, + GParamFlags flags); + + +G_END_DECLS + +#endif /* __GIMP_CONFIG_IFACE_H__ */ diff --git a/libgimpconfig/gimpconfig-params.h b/libgimpconfig/gimpconfig-params.h new file mode 100644 index 0000000..e63631a --- /dev/null +++ b/libgimpconfig/gimpconfig-params.h @@ -0,0 +1,240 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * ParamSpecs for config objects + * Copyright (C) 2001 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_CONFIG_PARAMS_H__ +#define __GIMP_CONFIG_PARAMS_H__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + + +/** + * SECTION: gimpconfig-params + * @title: GimpConfig-params + * @short_description: Macros and defines to install config properties. + * + * Macros and defines to install config properties. + **/ + + +/* + * GIMP_CONFIG_PARAM_SERIALIZE - A property that can and should be + * serialized and deserialized. + * GIMP_CONFIG_PARAM_AGGREGATE - The object property is to be treated as + * part of the parent object. + * GIMP_CONFIG_PARAM_RESTART - Changes to this property take effect only + * after a restart. + * GIMP_CONFIG_PARAM_CONFIRM - Changes to this property should be + * confirmed by the user before being applied. + * GIMP_CONFIG_PARAM_DEFAULTS - Don't serialize this property if it has the + * default value. + * GIMP_CONFIG_PARAM_IGNORE - This property exists for obscure reasons + * or is needed for backward compatibility. + * Ignore the value read and don't serialize it. + */ + +#define GIMP_CONFIG_PARAM_SERIALIZE (1 << (0 + G_PARAM_USER_SHIFT)) +#define GIMP_CONFIG_PARAM_AGGREGATE (1 << (1 + G_PARAM_USER_SHIFT)) +#define GIMP_CONFIG_PARAM_RESTART (1 << (2 + G_PARAM_USER_SHIFT)) +#define GIMP_CONFIG_PARAM_CONFIRM (1 << (3 + G_PARAM_USER_SHIFT)) +#define GIMP_CONFIG_PARAM_DEFAULTS (1 << (4 + G_PARAM_USER_SHIFT)) +#define GIMP_CONFIG_PARAM_IGNORE (1 << (5 + G_PARAM_USER_SHIFT)) + +#define GIMP_CONFIG_PARAM_FLAGS (G_PARAM_READWRITE | \ + G_PARAM_CONSTRUCT | \ + GIMP_CONFIG_PARAM_SERIALIZE) + + + +/* some convenience macros to install object properties */ + +#define GIMP_CONFIG_PROP_BOOLEAN(class, id, name, nick, blurb, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_boolean (name, nick, blurb,\ + default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_INT(class, id, name, nick, blurb, min, max, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_int (name, nick, blurb,\ + min, max, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_UINT(class, id, name, nick, blurb, min, max, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_uint (name, nick, blurb,\ + min, max, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_INT64(class, id, name, nick, blurb, min, max, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_int64 (name, nick, blurb,\ + min, max, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_UINT64(class, id, name, nick, blurb, min, max, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_uint64 (name, nick, blurb,\ + min, max, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_UNIT(class, id, name, nick, blurb, pixels, percent, default, flags) \ + g_object_class_install_property (class, id,\ + gimp_param_spec_unit (name, nick, blurb,\ + pixels, percent, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_MEMSIZE(class, id, name, nick, blurb, min, max, default, flags) \ + g_object_class_install_property (class, id,\ + gimp_param_spec_memsize (name, nick, blurb,\ + min, max, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_DOUBLE(class, id, name, nick, blurb, min, max, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_double (name, nick, blurb,\ + min, max, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_RESOLUTION(class, id, name, nick, blurb, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_double (name, nick, blurb,\ + GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION, \ + default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_ENUM(class, id, name, nick, blurb, enum_type, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_enum (name, nick, blurb,\ + enum_type, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_STRING(class, id, name, nick, blurb, default, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_string (name, nick, blurb,\ + default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_PATH(class, id, name, nick, blurb, path_type, default, flags) \ + g_object_class_install_property (class, id,\ + gimp_param_spec_config_path (name, nick, blurb,\ + path_type, default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_RGB(class, id, name, nick, blurb, has_alpha, default, flags) \ + g_object_class_install_property (class, id,\ + gimp_param_spec_rgb (name, nick, blurb,\ + has_alpha, default, \ + flags | GIMP_CONFIG_PARAM_FLAGS)) + +#define GIMP_CONFIG_PROP_MATRIX2(class, id, name, nick, blurb, default, flags) \ + g_object_class_install_property (class, id,\ + gimp_param_spec_matrix2 (name, nick, blurb,\ + default,\ + flags | GIMP_CONFIG_PARAM_FLAGS)) + + +/* object, boxed and pointer properties are _not_ G_PARAM_CONSTRUCT */ + +#define GIMP_CONFIG_PROP_OBJECT(class, id, name, nick, blurb, object_type, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_object (name, nick, blurb,\ + object_type,\ + flags |\ + G_PARAM_READWRITE |\ + GIMP_CONFIG_PARAM_SERIALIZE)) + +#define GIMP_CONFIG_PROP_BOXED(class, id, name, nick, blurb, boxed_type, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_boxed (name, nick, blurb,\ + boxed_type,\ + flags |\ + G_PARAM_READWRITE |\ + GIMP_CONFIG_PARAM_SERIALIZE)) + +#define GIMP_CONFIG_PROP_POINTER(class, id, name, nick, blurb, flags) \ + g_object_class_install_property (class, id,\ + g_param_spec_pointer (name, nick, blurb,\ + flags |\ + G_PARAM_READWRITE |\ + GIMP_CONFIG_PARAM_SERIALIZE)) + + +/* deprecated macros, they all lack the "nick" parameter */ + +#ifndef GIMP_DISABLE_DEPRECATED + +#define GIMP_CONFIG_INSTALL_PROP_BOOLEAN(class, id, name, blurb, default, flags) \ + GIMP_CONFIG_PROP_BOOLEAN(class, id, name, NULL, blurb, default, flags); + +#define GIMP_CONFIG_INSTALL_PROP_INT(class, id, name, blurb, min, max, default, flags) \ + GIMP_CONFIG_PROP_INT(class, id, name, NULL, blurb, min, max, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_UINT(class, id, name, blurb, min, max, default, flags) \ + GIMP_CONFIG_PROP_UINT(class, id, name, NULL, blurb, min, max, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_UNIT(class, id, name, blurb, pixels, percent, default, flags) \ + GIMP_CONFIG_PROP_UNIT(class, id, name, NULL, blurb, pixels, percent, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_MEMSIZE(class, id, name, blurb, min, max, default, flags) \ + GIMP_CONFIG_PROP_MEMSIZE(class, id, name, NULL, blurb, min, max, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_DOUBLE(class, id, name, blurb, min, max, default, flags) \ + GIMP_CONFIG_PROP_DOUBLE(class, id, name, NULL, blurb, min, max, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_RESOLUTION(class, id, name, blurb, default, flags) \ + GIMP_CONFIG_PROP_RESOLUTION(class, id, name, NULL, blurb, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_ENUM(class, id, name, blurb, enum_type, default, flags) \ + GIMP_CONFIG_PROP_ENUM(class, id, name, NULL, blurb, enum_type, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_STRING(class, id, name, blurb, default, flags) \ + GIMP_CONFIG_PROP_STRING(class, id, name, NULL, blurb, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_PATH(class, id, name, blurb, path_type, default, flags) \ + GIMP_CONFIG_PROP_PATH(class, id, name, NULL, blurb, path_type, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_RGB(class, id, name, blurb, has_alpha, default, flags) \ + GIMP_CONFIG_PROP_RGB(class, id, name, NULL, blurb, has_alpha, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_MATRIX2(class, id, name, blurb, default, flags) \ + GIMP_CONFIG_PROP_MATRIX2(class, id, name, NULL, blurb, default, flags) + +#define GIMP_CONFIG_INSTALL_PROP_OBJECT(class, id, name, blurb, object_type, flags) \ + GIMP_CONFIG_PROP_OBJECT(class, id, name, NULL, blurb, object_type, flags) + +#define GIMP_CONFIG_INSTALL_PROP_BOXED(class, id, name, blurb, boxed_type, flags) \ + GIMP_CONFIG_PROP_BOXED(class, id, name, NULL, blurb, boxed_type, flags) + +#define GIMP_CONFIG_INSTALL_PROP_POINTER(class, id, name, blurb, flags) \ + GIMP_CONFIG_PROP_POINTER(class, id, name, NULL, blurb, flags) + +#endif /* GIMP_DISABLE_DEPRECATED */ + + +G_END_DECLS + +#endif /* __GIMP_CONFIG_PARAMS_H__ */ diff --git a/libgimpconfig/gimpconfig-path.c b/libgimpconfig/gimpconfig-path.c new file mode 100644 index 0000000..8d87e4a --- /dev/null +++ b/libgimpconfig/gimpconfig-path.c @@ -0,0 +1,720 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * gimpconfig-path.c + * Copyright (C) 2001 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <stdio.h> +#include <string.h> + +#include <gio/gio.h> + +#include "libgimpbase/gimpbase.h" + +#include "gimpconfig-error.h" +#include "gimpconfig-path.h" + +#include "libgimp/libgimp-intl.h" + + +/** + * SECTION: gimpconfig-path + * @title: GimpConfig-path + * @short_description: File path utilities for libgimpconfig. + * + * File path utilities for libgimpconfig. + **/ + + +/** + * gimp_config_path_get_type: + * + * Reveals the object type + * + * Returns: the #GType for a GimpConfigPath string property + * + * Since: 2.4 + **/ +GType +gimp_config_path_get_type (void) +{ + static GType path_type = 0; + + if (! path_type) + { + const GTypeInfo type_info = { 0, }; + + path_type = g_type_register_static (G_TYPE_STRING, "GimpConfigPath", + &type_info, 0); + } + + return path_type; +} + + +/* + * GIMP_TYPE_PARAM_CONFIG_PATH + */ + +#define GIMP_PARAM_SPEC_CONFIG_PATH(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_CONFIG_PATH, GimpParamSpecConfigPath)) + +typedef struct _GimpParamSpecConfigPath GimpParamSpecConfigPath; + +struct _GimpParamSpecConfigPath +{ + GParamSpecString parent_instance; + + GimpConfigPathType type; +}; + +static void gimp_param_config_path_class_init (GParamSpecClass *class); + +/** + * gimp_param_config_path_get_type: + * + * Reveals the object type + * + * Returns: the #GType for a directory path object + * + * Since: 2.4 + **/ +GType +gimp_param_config_path_get_type (void) +{ + static GType spec_type = 0; + + if (! spec_type) + { + const GTypeInfo type_info = + { + sizeof (GParamSpecClass), + NULL, NULL, + (GClassInitFunc) gimp_param_config_path_class_init, + NULL, NULL, + sizeof (GimpParamSpecConfigPath), + 0, NULL, NULL + }; + + spec_type = g_type_register_static (G_TYPE_PARAM_STRING, + "GimpParamConfigPath", + &type_info, 0); + } + + return spec_type; +} + +static void +gimp_param_config_path_class_init (GParamSpecClass *class) +{ + class->value_type = GIMP_TYPE_CONFIG_PATH; +} + +/** + * gimp_param_spec_config_path: + * @name: Canonical name of the param + * @nick: Nickname of the param + * @blurb: Brief description of param. + * @type: a #GimpConfigPathType value. + * @default_value: Value to use if none is assigned. + * @flags: a combination of #GParamFlags + * + * Creates a param spec to hold a filename, dir name, + * or list of file or dir names. + * See g_param_spec_internal() for more information. + * + * Returns: a newly allocated #GParamSpec instance + * + * Since: 2.4 + **/ +GParamSpec * +gimp_param_spec_config_path (const gchar *name, + const gchar *nick, + const gchar *blurb, + GimpConfigPathType type, + const gchar *default_value, + GParamFlags flags) +{ + GParamSpecString *pspec; + + pspec = g_param_spec_internal (GIMP_TYPE_PARAM_CONFIG_PATH, + name, nick, blurb, flags); + + pspec->default_value = g_strdup (default_value); + + GIMP_PARAM_SPEC_CONFIG_PATH (pspec)->type = type; + + return G_PARAM_SPEC (pspec); +} + +/** + * gimp_param_spec_config_path_type: + * @pspec: A #GParamSpec for a path param + * + * Tells whether the path param encodes a filename, + * dir name, or list of file or dir names. + * + * Returns: a #GimpConfigPathType value + * + * Since: 2.4 + **/ +GimpConfigPathType +gimp_param_spec_config_path_type (GParamSpec *pspec) +{ + g_return_val_if_fail (GIMP_IS_PARAM_SPEC_CONFIG_PATH (pspec), 0); + + return GIMP_PARAM_SPEC_CONFIG_PATH (pspec)->type; +} + + +/* + * GimpConfig path utilities + */ + +static gchar * gimp_config_path_expand_only (const gchar *path, + GError **error) G_GNUC_MALLOC; +static inline gchar * gimp_config_path_extract_token (const gchar **str); +static gchar * gimp_config_path_unexpand_only (const gchar *path) G_GNUC_MALLOC; + + +/** + * gimp_config_build_data_path: + * @name: directory name (in UTF-8 encoding) + * + * Creates a search path as it is used in the gimprc file. The path + * returned by gimp_config_build_data_path() includes a directory + * below the user's gimp directory and one in the system-wide data + * directory. + * + * Note that you cannot use this path directly with gimp_path_parse(). + * As it is in the gimprc notation, you first need to expand and + * recode it using gimp_config_path_expand(). + * + * Returns: a newly allocated string + * + * Since: 2.4 + **/ +gchar * +gimp_config_build_data_path (const gchar *name) +{ + return g_strconcat ("${gimp_dir}", G_DIR_SEPARATOR_S, name, + G_SEARCHPATH_SEPARATOR_S, + "${gimp_data_dir}", G_DIR_SEPARATOR_S, name, + NULL); +} + +/** + * gimp_config_build_plug_in_path: + * @name: directory name (in UTF-8 encoding) + * + * Creates a search path as it is used in the gimprc file. The path + * returned by gimp_config_build_plug_in_path() includes a directory + * below the user's gimp directory and one in the system-wide plug-in + * directory. + * + * Note that you cannot use this path directly with gimp_path_parse(). + * As it is in the gimprc notation, you first need to expand and + * recode it using gimp_config_path_expand(). + * + * Returns: a newly allocated string + * + * Since: 2.4 + **/ +gchar * +gimp_config_build_plug_in_path (const gchar *name) +{ + return g_strconcat ("${gimp_dir}", G_DIR_SEPARATOR_S, name, + G_SEARCHPATH_SEPARATOR_S, + "${gimp_plug_in_dir}", G_DIR_SEPARATOR_S, name, + NULL); +} + +/** + * gimp_config_build_writable_path: + * @name: directory name (in UTF-8 encoding) + * + * Creates a search path as it is used in the gimprc file. The path + * returned by gimp_config_build_writable_path() is just the writable + * parts of the search path constructed by gimp_config_build_data_path(). + * + * Note that you cannot use this path directly with gimp_path_parse(). + * As it is in the gimprc notation, you first need to expand and + * recode it using gimp_config_path_expand(). + * + * Returns: a newly allocated string + * + * Since: 2.4 + **/ +gchar * +gimp_config_build_writable_path (const gchar *name) +{ + return g_strconcat ("${gimp_dir}", G_DIR_SEPARATOR_S, name, NULL); +} + + +/** + * gimp_config_path_expand: + * @path: a NUL-terminated string in UTF-8 encoding + * @recode: whether to convert to the filesystem's encoding + * @error: return location for errors + * + * Paths as stored in gimprc and other config files have to be treated + * special. The string may contain special identifiers such as for + * example ${gimp_dir} that have to be substituted before use. Also + * the user's filesystem may be in a different encoding than UTF-8 + * (which is what is used for the gimprc). This function does the + * variable substitution for you and can also attempt to convert to + * the filesystem encoding. + * + * To reverse the expansion, use gimp_config_path_unexpand(). + * + * Return value: a newly allocated NUL-terminated string + * + * Since: 2.4 + **/ +gchar * +gimp_config_path_expand (const gchar *path, + gboolean recode, + GError **error) +{ + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (recode) + { + gchar *retval; + gchar *expanded = gimp_config_path_expand_only (path, error); + + if (! expanded) + return NULL; + + retval = g_filename_from_utf8 (expanded, -1, NULL, NULL, error); + + g_free (expanded); + + return retval; + } + + return gimp_config_path_expand_only (path, error); +} + +/** + * gimp_config_path_expand_to_files: + * @path: a NUL-terminated string in UTF-8 encoding + * @error: return location for errors + * + * Paths as stored in the gimprc have to be treated special. The + * string may contain special identifiers such as for example + * ${gimp_dir} that have to be substituted before use. Also the user's + * filesystem may be in a different encoding than UTF-8 (which is what + * is used for the gimprc). + * + * This function runs @path through gimp_config_path_expand() and + * gimp_path_parse(), then turns the filenames returned by + * gimp_path_parse() into GFile using g_file_new_for_path(). + * + * Return value: a #GList of newly allocated #GFile objects. + * + * Since: 2.10 + **/ +GList * +gimp_config_path_expand_to_files (const gchar *path, + GError **error) +{ + GList *files; + GList *list; + gchar *expanded; + + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + expanded = gimp_config_path_expand (path, TRUE, error); + + if (! expanded) + return NULL; + + files = gimp_path_parse (expanded, 256, FALSE, NULL); + + g_free (expanded); + + for (list = files; list; list = g_list_next (list)) + { + gchar *dir = list->data; + + list->data = g_file_new_for_path (dir); + g_free (dir); + } + + return files; +} + +/** + * gimp_config_path_unexpand: + * @path: a NUL-terminated string + * @recode: whether @path is in filesystem encoding or UTF-8 + * @error: return location for errors + * + * The inverse operation of gimp_config_path_expand() + * + * This function takes a @path and tries to substitute the first + * elements by well-known special identifiers such as for example + * ${gimp_dir}. The unexpanded path can then be stored in gimprc and + * other config files. + * + * If @recode is %TRUE then @path is in local filesystem encoding, + * if @recode is %FALSE then @path is assumed to be UTF-8. + * + * Return value: a newly allocated NUL-terminated UTF-8 string + * + * Since: 2.10 + **/ +gchar * +gimp_config_path_unexpand (const gchar *path, + gboolean recode, + GError **error) +{ + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (recode) + { + gchar *retval; + gchar *utf8 = g_filename_to_utf8 (path, -1, NULL, NULL, error); + + if (! utf8) + return NULL; + + retval = gimp_config_path_unexpand_only (utf8); + + g_free (utf8); + + return retval; + } + + return gimp_config_path_unexpand_only (path); +} + +/** + * gimp_file_new_for_config_path: + * @path: a NUL-terminated string in UTF-8 encoding + * @error: return location for errors + * + * Expands @path using gimp_config_path_expand() and returns a #GFile + * for the expanded path. + * + * To reverse the expansion, use gimp_file_get_config_path(). + * + * Return value: a newly allocated #GFile, or %NULL if the expansion failed. + * + * Since: 2.10 + **/ +GFile * +gimp_file_new_for_config_path (const gchar *path, + GError **error) +{ + GFile *file = NULL; + gchar *expanded; + + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + expanded = gimp_config_path_expand (path, TRUE, error); + + if (expanded) + { + file = g_file_new_for_path (expanded); + g_free (expanded); + } + + return file; +} + +/** + * gimp_file_get_config_path: + * @file: a #GFile + * @error: return location for errors + * + * Unexpands @file's path using gimp_config_path_unexpand() and + * returns the unexpanded path. + * + * The inverse operation of gimp_file_new_for_config_path(). + * + * Return value: a newly allocated NUL-terminated UTF-8 string, or %NULL if + * unexpanding failed. + * + * Since: 2.10 + **/ +gchar * +gimp_file_get_config_path (GFile *file, + GError **error) +{ + gchar *unexpanded = NULL; + gchar *path; + + g_return_val_if_fail (G_IS_FILE (file), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + path = g_file_get_path (file); + + if (path) + { + unexpanded = gimp_config_path_unexpand (path, TRUE, error); + g_free (path); + } + else + { + g_set_error_literal (error, 0, 0, + _("File has no path representation")); + } + + return unexpanded; +} + + +/* private functions */ + +#define SUBSTS_ALLOC 4 + +static gchar * +gimp_config_path_expand_only (const gchar *path, + GError **error) +{ + const gchar *home; + const gchar *p; + const gchar *s; + gchar *n; + gchar *token; + gchar *filename = NULL; + gchar *expanded = NULL; + gchar **substs = NULL; + guint n_substs = 0; + gint length = 0; + gint i; + + home = g_get_home_dir (); + if (home) + home = gimp_filename_to_utf8 (home); + + p = path; + + while (*p) + { + if (*p == '~' && home) + { + length += strlen (home); + p += 1; + } + else if ((token = gimp_config_path_extract_token (&p)) != NULL) + { + for (i = 0; i < n_substs; i++) + if (strcmp (substs[2*i], token) == 0) + break; + + if (i < n_substs) + { + s = substs[2*i+1]; + } + else + { + s = NULL; + + if (strcmp (token, "gimp_dir") == 0) + s = gimp_directory (); + else if (strcmp (token, "gimp_data_dir") == 0) + s = gimp_data_directory (); + else if (strcmp (token, "gimp_plug_in_dir") == 0 || + strcmp (token, "gimp_plugin_dir") == 0) + s = gimp_plug_in_directory (); + else if (strcmp (token, "gimp_sysconf_dir") == 0) + s = gimp_sysconf_directory (); + else if (strcmp (token, "gimp_installation_dir") == 0) + s = gimp_installation_directory (); + else if (strcmp (token, "gimp_cache_dir") == 0) + s = gimp_cache_directory (); + else if (strcmp (token, "gimp_temp_dir") == 0) + s = gimp_temp_directory (); + + if (!s) + s = g_getenv (token); + +#ifdef G_OS_WIN32 + /* The default user gimprc on Windows references + * ${TEMP}, but not all Windows installations have that + * environment variable, even if it should be kinda + * standard. So special-case it. + */ + if (!s && strcmp (token, "TEMP") == 0) + s = g_get_tmp_dir (); +#endif /* G_OS_WIN32 */ + } + + if (!s) + { + g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE, + _("Cannot expand ${%s}"), token); + g_free (token); + goto cleanup; + } + + if (n_substs % SUBSTS_ALLOC == 0) + substs = g_renew (gchar *, substs, 2 * (n_substs + SUBSTS_ALLOC)); + + substs[2*n_substs] = token; + substs[2*n_substs + 1] = (gchar *) gimp_filename_to_utf8 (s); + + length += strlen (substs[2*n_substs + 1]); + + n_substs++; + } + else + { + length += g_utf8_skip[(const guchar) *p]; + p = g_utf8_next_char (p); + } + } + + if (n_substs == 0) + return g_strdup (path); + + expanded = g_new (gchar, length + 1); + + p = path; + n = expanded; + + while (*p) + { + if (*p == '~' && home) + { + *n = '\0'; + strcat (n, home); + n += strlen (home); + p += 1; + } + else if ((token = gimp_config_path_extract_token (&p)) != NULL) + { + for (i = 0; i < n_substs; i++) + { + if (strcmp (substs[2*i], token) == 0) + { + s = substs[2*i+1]; + + *n = '\0'; + strcat (n, s); + n += strlen (s); + + break; + } + } + + g_free (token); + } + else + { + *n++ = *p++; + } + } + + *n = '\0'; + + cleanup: + for (i = 0; i < n_substs; i++) + g_free (substs[2*i]); + + g_free (substs); + g_free (filename); + + return expanded; +} + +static inline gchar * +gimp_config_path_extract_token (const gchar **str) +{ + const gchar *p; + gchar *token; + + if (strncmp (*str, "${", 2)) + return NULL; + + p = *str + 2; + + while (*p && (*p != '}')) + p = g_utf8_next_char (p); + + if (! *p) + return NULL; + + token = g_strndup (*str + 2, g_utf8_pointer_to_offset (*str + 2, p)); + + *str = p + 1; /* after the closing bracket */ + + return token; +} + +static gchar * +gimp_config_path_unexpand_only (const gchar *path) +{ + const struct + { + const gchar *id; + const gchar *prefix; + } + identifiers[] = + { + { "${gimp_plug_in_dir}", gimp_plug_in_directory () }, + { "${gimp_data_dir}", gimp_data_directory () }, + { "${gimp_sysconf_dir}", gimp_sysconf_directory () }, + { "${gimp_installation_dir}", gimp_installation_directory () }, + { "${gimp_cache_dir}", gimp_cache_directory () }, + { "${gimp_temp_dir}", gimp_temp_directory () }, + { "${gimp_dir}", gimp_directory () } + }; + + GList *files; + GList *list; + gchar *unexpanded; + + files = gimp_path_parse (path, 256, FALSE, NULL); + + for (list = files; list; list = g_list_next (list)) + { + gchar *dir = list->data; + gint i; + + for (i = 0; i < G_N_ELEMENTS (identifiers); i++) + { + if (g_str_has_prefix (dir, identifiers[i].prefix)) + { + gchar *tmp = g_strconcat (identifiers[i].id, + dir + strlen (identifiers[i].prefix), + NULL); + + g_free (dir); + list->data = tmp; + + break; + } + } + } + + unexpanded = gimp_path_to_str (files); + + gimp_path_free (files); + + return unexpanded; +} diff --git a/libgimpconfig/gimpconfig-path.h b/libgimpconfig/gimpconfig-path.h new file mode 100644 index 0000000..1b157f9 --- /dev/null +++ b/libgimpconfig/gimpconfig-path.h @@ -0,0 +1,108 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpconfig-path.h + * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_CONFIG_PATH_H__ +#define __GIMP_CONFIG_PATH_H__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + + +/* + * GIMP_TYPE_CONFIG_PATH + */ + +#define GIMP_TYPE_CONFIG_PATH (gimp_config_path_get_type ()) +#define GIMP_VALUE_HOLDS_CONFIG_PATH(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_CONFIG_PATH)) + +GType gimp_config_path_get_type (void) G_GNUC_CONST; + + + +/* + * GIMP_TYPE_PARAM_CONFIG_PATH + */ + +/** + * GimpConfigPathType: + * @GIMP_CONFIG_PATH_FILE: A single file + * @GIMP_CONFIG_PATH_FILE_LIST: A list of files + * @GIMP_CONFIG_PATH_DIR: A single folder + * @GIMP_CONFIG_PATH_DIR_LIST: A list of folders + * + * Types of config paths. + **/ +typedef enum +{ + GIMP_CONFIG_PATH_FILE, + GIMP_CONFIG_PATH_FILE_LIST, + GIMP_CONFIG_PATH_DIR, + GIMP_CONFIG_PATH_DIR_LIST +} GimpConfigPathType; + + +#define GIMP_TYPE_PARAM_CONFIG_PATH (gimp_param_config_path_get_type ()) +#define GIMP_IS_PARAM_SPEC_CONFIG_PATH(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_CONFIG_PATH)) + +GType gimp_param_config_path_get_type (void) G_GNUC_CONST; + +GParamSpec * gimp_param_spec_config_path (const gchar *name, + const gchar *nick, + const gchar *blurb, + GimpConfigPathType type, + const gchar *default_value, + GParamFlags flags); + +GimpConfigPathType gimp_param_spec_config_path_type (GParamSpec *pspec); + + +/* + * GimpConfigPath utilities + */ + +gchar * gimp_config_path_expand (const gchar *path, + gboolean recode, + GError **error) G_GNUC_MALLOC; +GList * gimp_config_path_expand_to_files (const gchar *path, + GError **error) G_GNUC_MALLOC; + +gchar * gimp_config_path_unexpand (const gchar *path, + gboolean recode, + GError **error) G_GNUC_MALLOC; + +GFile * gimp_file_new_for_config_path (const gchar *path, + GError **error) G_GNUC_MALLOC; +gchar * gimp_file_get_config_path (GFile *file, + GError **error) G_GNUC_MALLOC; + +gchar * gimp_config_build_data_path (const gchar *name) G_GNUC_MALLOC; +gchar * gimp_config_build_writable_path (const gchar *name) G_GNUC_MALLOC; +gchar * gimp_config_build_plug_in_path (const gchar *name) G_GNUC_MALLOC; + + +G_END_DECLS + +#endif /* __GIMP_CONFIG_PATH_H__ */ diff --git a/libgimpconfig/gimpconfig-serialize.c b/libgimpconfig/gimpconfig-serialize.c new file mode 100644 index 0000000..0df5bbc --- /dev/null +++ b/libgimpconfig/gimpconfig-serialize.c @@ -0,0 +1,576 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Object properties serialization routines + * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <cairo.h> +#include <gegl.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include "libgimpbase/gimpbase.h" +#include "libgimpmath/gimpmath.h" +#include "libgimpcolor/gimpcolor.h" + +#include "gimpconfigtypes.h" + +#include "gimpconfigwriter.h" +#include "gimpconfig-iface.h" +#include "gimpconfig-params.h" +#include "gimpconfig-path.h" +#include "gimpconfig-serialize.h" +#include "gimpconfig-utils.h" + + +/** + * SECTION: gimpconfig-serialize + * @title: GimpConfig-serialize + * @short_description: Serializing for libgimpconfig. + * + * Serializing interface for libgimpconfig. + **/ + + +static gboolean gimp_config_serialize_rgb (const GValue *value, + GString *str, + gboolean has_alpha); + + +/** + * gimp_config_serialize_properties: + * @config: a #GimpConfig. + * @writer: a #GimpConfigWriter. + * + * This function writes all object properties to the @writer. + * + * Returns: %TRUE if serialization succeeded, %FALSE otherwise + * + * Since: 2.4 + **/ +gboolean +gimp_config_serialize_properties (GimpConfig *config, + GimpConfigWriter *writer) +{ + GObjectClass *klass; + GParamSpec **property_specs; + guint n_property_specs; + guint i; + + g_return_val_if_fail (G_IS_OBJECT (config), FALSE); + + klass = G_OBJECT_GET_CLASS (config); + + property_specs = g_object_class_list_properties (klass, &n_property_specs); + + if (! property_specs) + return TRUE; + + for (i = 0; i < n_property_specs; i++) + { + GParamSpec *prop_spec = property_specs[i]; + + if (! (prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE)) + continue; + + if (! gimp_config_serialize_property (config, prop_spec, writer)) + return FALSE; + } + + g_free (property_specs); + + return TRUE; +} + +/** + * gimp_config_serialize_changed_properties: + * @config: a #GimpConfig. + * @writer: a #GimpConfigWriter. + * + * This function writes all object properties that have been changed from + * their default values to the @writer. + * + * Returns: %TRUE if serialization succeeded, %FALSE otherwise + * + * Since: 2.4 + **/ +gboolean +gimp_config_serialize_changed_properties (GimpConfig *config, + GimpConfigWriter *writer) +{ + GObjectClass *klass; + GParamSpec **property_specs; + guint n_property_specs; + guint i; + GValue value = G_VALUE_INIT; + + g_return_val_if_fail (G_IS_OBJECT (config), FALSE); + + klass = G_OBJECT_GET_CLASS (config); + + property_specs = g_object_class_list_properties (klass, &n_property_specs); + + if (! property_specs) + return TRUE; + + for (i = 0; i < n_property_specs; i++) + { + GParamSpec *prop_spec = property_specs[i]; + + if (! (prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE)) + continue; + + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (config), prop_spec->name, &value); + + if (! g_param_value_defaults (prop_spec, &value)) + { + if (! gimp_config_serialize_property (config, prop_spec, writer)) + return FALSE; + } + + g_value_unset (&value); + } + + g_free (property_specs); + + return TRUE; +} + +/** + * gimp_config_serialize_property: + * @config: a #GimpConfig. + * @param_spec: a #GParamSpec. + * @writer: a #GimpConfigWriter. + * + * This function serializes a single object property to the @writer. + * + * Returns: %TRUE if serialization succeeded, %FALSE otherwise + * + * Since: 2.4 + **/ +gboolean +gimp_config_serialize_property (GimpConfig *config, + GParamSpec *param_spec, + GimpConfigWriter *writer) +{ + GimpConfigInterface *config_iface = NULL; + GimpConfigInterface *parent_iface = NULL; + GValue value = G_VALUE_INIT; + gboolean success = FALSE; + + if (! (param_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE)) + return FALSE; + + if (param_spec->flags & GIMP_CONFIG_PARAM_IGNORE) + return TRUE; + + g_value_init (&value, param_spec->value_type); + g_object_get_property (G_OBJECT (config), param_spec->name, &value); + + if (param_spec->flags & GIMP_CONFIG_PARAM_DEFAULTS && + g_param_value_defaults (param_spec, &value)) + { + g_value_unset (&value); + return TRUE; + } + + if (G_TYPE_IS_OBJECT (param_spec->owner_type)) + { + GTypeClass *owner_class = g_type_class_peek (param_spec->owner_type); + + config_iface = g_type_interface_peek (owner_class, GIMP_TYPE_CONFIG); + + /* We must call serialize_property() *only* if the *exact* class + * which implements it is param_spec->owner_type's class. + * + * Therefore, we ask param_spec->owner_type's immediate parent class + * for it's GimpConfigInterface and check if we get a different + * pointer. + * + * (if the pointers are the same, param_spec->owner_type's + * GimpConfigInterface is inherited from one of it's parent classes + * and thus not able to handle param_spec->owner_type's properties). + */ + if (config_iface) + { + GTypeClass *owner_parent_class; + + owner_parent_class = g_type_class_peek_parent (owner_class); + + parent_iface = g_type_interface_peek (owner_parent_class, + GIMP_TYPE_CONFIG); + } + } + + if (config_iface && + config_iface != parent_iface && /* see comment above */ + config_iface->serialize_property && + config_iface->serialize_property (config, + param_spec->param_id, + (const GValue *) &value, + param_spec, + writer)) + { + success = TRUE; + } + + /* If there is no serialize_property() method *or* if it returned + * FALSE, continue with the default implementation + */ + + if (! success) + { + if (G_VALUE_HOLDS_OBJECT (&value) && + G_VALUE_TYPE (&value) != G_TYPE_FILE) + { + GimpConfigInterface *config_iface = NULL; + GimpConfig *prop_object; + + prop_object = g_value_get_object (&value); + + if (prop_object) + config_iface = GIMP_CONFIG_GET_INTERFACE (prop_object); + else + success = TRUE; + + if (config_iface) + { + gimp_config_writer_open (writer, param_spec->name); + + /* if the object property is not GIMP_CONFIG_PARAM_AGGREGATE, + * deserializing will need to know the exact type + * in order to create the object + */ + if (! (param_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE)) + { + GType object_type = G_TYPE_FROM_INSTANCE (prop_object); + + gimp_config_writer_string (writer, g_type_name (object_type)); + } + + success = config_iface->serialize (prop_object, writer, NULL); + + if (success) + gimp_config_writer_close (writer); + else + gimp_config_writer_revert (writer); + } + } + else + { + GString *str = g_string_new (NULL); + + if (GIMP_VALUE_HOLDS_RGB (&value)) + { + gboolean has_alpha = gimp_param_spec_rgb_has_alpha (param_spec); + + success = gimp_config_serialize_rgb (&value, str, has_alpha); + } + else + { + success = gimp_config_serialize_value (&value, str, TRUE); + } + + if (success) + { + gimp_config_writer_open (writer, param_spec->name); + gimp_config_writer_print (writer, str->str, str->len); + gimp_config_writer_close (writer); + } + + g_string_free (str, TRUE); + } + + if (! success) + { + /* don't warn for empty string properties */ + if (G_VALUE_HOLDS_STRING (&value)) + { + success = TRUE; + } + else + { + g_warning ("couldn't serialize property %s::%s of type %s", + g_type_name (G_TYPE_FROM_INSTANCE (config)), + param_spec->name, + g_type_name (param_spec->value_type)); + } + } + } + + g_value_unset (&value); + + return success; +} + +/** + * gimp_config_serialize_property_by_name: + * @config: a #GimpConfig. + * @prop_name: the property's name. + * @writer: a #GimpConfigWriter. + * + * This function serializes a single object property to the @writer. + * + * Returns: %TRUE if serialization succeeded, %FALSE otherwise + * + * Since: 2.6 + **/ +gboolean +gimp_config_serialize_property_by_name (GimpConfig *config, + const gchar *prop_name, + GimpConfigWriter *writer) +{ + GParamSpec *pspec; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), + prop_name); + + if (! pspec) + return FALSE; + + return gimp_config_serialize_property (config, pspec, writer); +} + +/** + * gimp_config_serialize_value: + * @value: a #GValue. + * @str: a #GString. + * @escaped: whether to escape string values. + * + * This utility function appends a string representation of #GValue to @str. + * + * Return value: %TRUE if serialization succeeded, %FALSE otherwise. + * + * Since: 2.4 + **/ +gboolean +gimp_config_serialize_value (const GValue *value, + GString *str, + gboolean escaped) +{ + if (G_VALUE_HOLDS_BOOLEAN (value)) + { + gboolean bool; + + bool = g_value_get_boolean (value); + g_string_append (str, bool ? "yes" : "no"); + return TRUE; + } + + if (G_VALUE_HOLDS_ENUM (value)) + { + GEnumClass *enum_class = g_type_class_peek (G_VALUE_TYPE (value)); + GEnumValue *enum_value = g_enum_get_value (enum_class, + g_value_get_enum (value)); + + if (enum_value && enum_value->value_nick) + { + g_string_append (str, enum_value->value_nick); + return TRUE; + } + else + { + g_warning ("Couldn't get nick for enum_value of %s", + G_ENUM_CLASS_TYPE_NAME (enum_class)); + return FALSE; + } + } + + if (G_VALUE_HOLDS_STRING (value)) + { + const gchar *cstr = g_value_get_string (value); + + if (!cstr) + return FALSE; + + if (escaped) + gimp_config_string_append_escaped (str, cstr); + else + g_string_append (str, cstr); + + return TRUE; + } + + if (G_VALUE_HOLDS_DOUBLE (value) || G_VALUE_HOLDS_FLOAT (value)) + { + gdouble v_double; + gchar buf[G_ASCII_DTOSTR_BUF_SIZE]; + + if (G_VALUE_HOLDS_DOUBLE (value)) + v_double = g_value_get_double (value); + else + v_double = (gdouble) g_value_get_float (value); + + g_ascii_dtostr (buf, sizeof (buf), v_double); + g_string_append (str, buf); + return TRUE; + } + + if (GIMP_VALUE_HOLDS_RGB (value)) + { + return gimp_config_serialize_rgb (value, str, TRUE); + } + + if (GIMP_VALUE_HOLDS_MATRIX2 (value)) + { + GimpMatrix2 *trafo; + + trafo = g_value_get_boxed (value); + + if (trafo) + { + gchar buf[4][G_ASCII_DTOSTR_BUF_SIZE]; + gint i, j, k; + + for (i = 0, k = 0; i < 2; i++) + for (j = 0; j < 2; j++, k++) + g_ascii_dtostr (buf[k], G_ASCII_DTOSTR_BUF_SIZE, + trafo->coeff[i][j]); + + g_string_append_printf (str, "(matrix %s %s %s %s)", + buf[0], buf[1], buf[2], buf[3]); + } + else + { + g_string_append (str, "(matrix 1.0 1.0 1.0 1.0)"); + } + + return TRUE; + } + + if (G_VALUE_TYPE (value) == GIMP_TYPE_VALUE_ARRAY) + { + GimpValueArray *array; + + array = g_value_get_boxed (value); + + if (array) + { + gint length = gimp_value_array_length (array); + gint i; + + g_string_append_printf (str, "%d", length); + + for (i = 0; i < length; i++) + { + g_string_append (str, " "); + + if (! gimp_config_serialize_value (gimp_value_array_index (array, + i), + str, TRUE)) + return FALSE; + } + } + else + { + g_string_append (str, "0"); + } + + return TRUE; + } + + if (G_VALUE_TYPE (value) == G_TYPE_FILE) + { + GFile *file = g_value_get_object (value); + + if (file) + { + gchar *path = g_file_get_path (file); + gchar *unexpand = NULL; + + if (path) + { + unexpand = gimp_config_path_unexpand (path, TRUE, NULL); + g_free (path); + } + + if (unexpand) + { + if (escaped) + gimp_config_string_append_escaped (str, unexpand); + else + g_string_append (str, unexpand); + + g_free (unexpand); + } + else + { + g_string_append (str, "NULL"); + } + } + else + { + g_string_append (str, "NULL"); + } + + return TRUE; + } + + if (g_value_type_transformable (G_VALUE_TYPE (value), G_TYPE_STRING)) + { + GValue tmp_value = G_VALUE_INIT; + + g_value_init (&tmp_value, G_TYPE_STRING); + g_value_transform (value, &tmp_value); + + g_string_append (str, g_value_get_string (&tmp_value)); + + g_value_unset (&tmp_value); + return TRUE; + } + + return FALSE; +} + +static gboolean +gimp_config_serialize_rgb (const GValue *value, + GString *str, + gboolean has_alpha) +{ + GimpRGB *rgb; + + rgb = g_value_get_boxed (value); + + if (rgb) + { + gchar buf[4][G_ASCII_DTOSTR_BUF_SIZE]; + + g_ascii_dtostr (buf[0], G_ASCII_DTOSTR_BUF_SIZE, rgb->r); + g_ascii_dtostr (buf[1], G_ASCII_DTOSTR_BUF_SIZE, rgb->g); + g_ascii_dtostr (buf[2], G_ASCII_DTOSTR_BUF_SIZE, rgb->b); + + if (has_alpha) + { + g_ascii_dtostr (buf[3], G_ASCII_DTOSTR_BUF_SIZE, rgb->a); + + g_string_append_printf (str, "(color-rgba %s %s %s %s)", + buf[0], buf[1], buf[2], buf[3]); + } + else + { + g_string_append_printf (str, "(color-rgb %s %s %s)", + buf[0], buf[1], buf[2]); + } + + return TRUE; + } + + return FALSE; +} diff --git a/libgimpconfig/gimpconfig-serialize.h b/libgimpconfig/gimpconfig-serialize.h new file mode 100644 index 0000000..c25ab3b --- /dev/null +++ b/libgimpconfig/gimpconfig-serialize.h @@ -0,0 +1,52 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * Object properties serialization routines + * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_CONFIG_SERIALIZE_H__ +#define __GIMP_CONFIG_SERIALIZE_H__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + + +gboolean gimp_config_serialize_properties (GimpConfig *config, + GimpConfigWriter *writer); +gboolean gimp_config_serialize_changed_properties (GimpConfig *config, + GimpConfigWriter *writer); + +gboolean gimp_config_serialize_property (GimpConfig *config, + GParamSpec *param_spec, + GimpConfigWriter *writer); +gboolean gimp_config_serialize_property_by_name (GimpConfig *config, + const gchar *prop_name, + GimpConfigWriter *writer); +gboolean gimp_config_serialize_value (const GValue *value, + GString *str, + gboolean escaped); + + +G_END_DECLS + +#endif /* __GIMP_CONFIG_SERIALIZE_H__ */ diff --git a/libgimpconfig/gimpconfig-utils.c b/libgimpconfig/gimpconfig-utils.c new file mode 100644 index 0000000..7cef219 --- /dev/null +++ b/libgimpconfig/gimpconfig-utils.c @@ -0,0 +1,482 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Utility functions for GimpConfig. + * Copyright (C) 2001-2003 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gio/gio.h> + +#include "libgimpbase/gimpbase.h" + +#include "gimpconfigtypes.h" + +#include "gimpconfigwriter.h" +#include "gimpconfig-iface.h" +#include "gimpconfig-params.h" +#include "gimpconfig-utils.h" + + +/** + * SECTION: gimpconfig-utils + * @title: GimpConfig-utils + * @short_description: Miscellaneous utility functions for libgimpconfig. + * + * Miscellaneous utility functions for libgimpconfig. + **/ + + +static gboolean +gimp_config_diff_property (GObject *a, + GObject *b, + GParamSpec *prop_spec) +{ + GValue a_value = G_VALUE_INIT; + GValue b_value = G_VALUE_INIT; + gboolean retval = FALSE; + + g_value_init (&a_value, prop_spec->value_type); + g_value_init (&b_value, prop_spec->value_type); + + g_object_get_property (a, prop_spec->name, &a_value); + g_object_get_property (b, prop_spec->name, &b_value); + + if (g_param_values_cmp (prop_spec, &a_value, &b_value)) + { + if ((prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE) && + G_IS_PARAM_SPEC_OBJECT (prop_spec) && + g_type_interface_peek (g_type_class_peek (prop_spec->value_type), + GIMP_TYPE_CONFIG)) + { + if (! gimp_config_is_equal_to (g_value_get_object (&a_value), + g_value_get_object (&b_value))) + { + retval = TRUE; + } + } + else + { + retval = TRUE; + } + } + + g_value_unset (&a_value); + g_value_unset (&b_value); + + return retval; +} + +static GList * +gimp_config_diff_same (GObject *a, + GObject *b, + GParamFlags flags) +{ + GParamSpec **param_specs; + guint n_param_specs; + gint i; + GList *list = NULL; + + param_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), + &n_param_specs); + + for (i = 0; i < n_param_specs; i++) + { + GParamSpec *prop_spec = param_specs[i]; + + if (! flags || ((prop_spec->flags & flags) == flags)) + { + if (gimp_config_diff_property (a, b, prop_spec)) + list = g_list_prepend (list, prop_spec); + } + } + + g_free (param_specs); + + return list; +} + +static GList * +gimp_config_diff_other (GObject *a, + GObject *b, + GParamFlags flags) +{ + GParamSpec **param_specs; + guint n_param_specs; + gint i; + GList *list = NULL; + + param_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), + &n_param_specs); + + for (i = 0; i < n_param_specs; i++) + { + GParamSpec *a_spec = param_specs[i]; + GParamSpec *b_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (b), + a_spec->name); + + if (b_spec && + (a_spec->value_type == b_spec->value_type) && + (! flags || (a_spec->flags & b_spec->flags & flags) == flags)) + { + if (gimp_config_diff_property (a, b, b_spec)) + list = g_list_prepend (list, b_spec); + } + } + + g_free (param_specs); + + return list; +} + + +/** + * gimp_config_diff: + * @a: a #GObject + * @b: another #GObject object + * @flags: a mask of GParamFlags + * + * Compares all properties of @a and @b that have all @flags set. If + * @flags is 0, all properties are compared. + * + * If the two objects are not of the same type, only properties that + * exist in both object classes and are of the same value_type are + * compared. + * + * Return value: a GList of differing GParamSpecs. + * + * Since: 2.4 + **/ +GList * +gimp_config_diff (GObject *a, + GObject *b, + GParamFlags flags) +{ + GList *diff; + + g_return_val_if_fail (G_IS_OBJECT (a), NULL); + g_return_val_if_fail (G_IS_OBJECT (b), NULL); + + if (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b)) + diff = gimp_config_diff_same (a, b, flags); + else + diff = gimp_config_diff_other (a, b, flags); + + return g_list_reverse (diff); +} + +/** + * gimp_config_sync: + * @src: a #GObject + * @dest: another #GObject + * @flags: a mask of GParamFlags + * + * Compares all read- and write-able properties from @src and @dest + * that have all @flags set. Differing values are then copied from + * @src to @dest. If @flags is 0, all differing read/write properties. + * + * Properties marked as "construct-only" are not touched. + * + * If the two objects are not of the same type, only properties that + * exist in both object classes and are of the same value_type are + * synchronized + * + * Return value: %TRUE if @dest was modified, %FALSE otherwise + * + * Since: 2.4 + **/ +gboolean +gimp_config_sync (GObject *src, + GObject *dest, + GParamFlags flags) +{ + GList *diff; + GList *list; + + g_return_val_if_fail (G_IS_OBJECT (src), FALSE); + g_return_val_if_fail (G_IS_OBJECT (dest), FALSE); + + /* we use the internal versions here for a number of reasons: + * - it saves a g_list_reverse() + * - it avoids duplicated parameter checks + */ + if (G_TYPE_FROM_INSTANCE (src) == G_TYPE_FROM_INSTANCE (dest)) + diff = gimp_config_diff_same (src, dest, (flags | G_PARAM_READWRITE)); + else + diff = gimp_config_diff_other (src, dest, flags); + + if (!diff) + return FALSE; + + g_object_freeze_notify (G_OBJECT (dest)); + + for (list = diff; list; list = list->next) + { + GParamSpec *prop_spec = list->data; + + if (! (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY)) + { + GValue value = G_VALUE_INIT; + + g_value_init (&value, prop_spec->value_type); + + g_object_get_property (src, prop_spec->name, &value); + g_object_set_property (dest, prop_spec->name, &value); + + g_value_unset (&value); + } + } + + g_object_thaw_notify (G_OBJECT (dest)); + + g_list_free (diff); + + return TRUE; +} + +/** + * gimp_config_reset_properties: + * @object: a #GObject + * + * Resets all writable properties of @object to the default values as + * defined in their #GParamSpec. Properties marked as "construct-only" + * are not touched. + * + * If you want to reset a #GimpConfig object, please use gimp_config_reset(). + * + * Since: 2.4 + **/ +void +gimp_config_reset_properties (GObject *object) +{ + GObjectClass *klass; + GParamSpec **property_specs; + guint n_property_specs; + guint i; + + g_return_if_fail (G_IS_OBJECT (object)); + + klass = G_OBJECT_GET_CLASS (object); + + property_specs = g_object_class_list_properties (klass, &n_property_specs); + if (!property_specs) + return; + + g_object_freeze_notify (object); + + for (i = 0; i < n_property_specs; i++) + { + GParamSpec *prop_spec; + GValue value = G_VALUE_INIT; + + prop_spec = property_specs[i]; + + if ((prop_spec->flags & G_PARAM_WRITABLE) && + ! (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY)) + { + if (G_IS_PARAM_SPEC_OBJECT (prop_spec)) + { + if ((prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE) && + (prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE) && + g_type_interface_peek (g_type_class_peek (prop_spec->value_type), + GIMP_TYPE_CONFIG)) + { + g_value_init (&value, prop_spec->value_type); + + g_object_get_property (object, prop_spec->name, &value); + + gimp_config_reset (g_value_get_object (&value)); + + g_value_unset (&value); + } + } + else + { + GValue default_value = G_VALUE_INIT; + + g_value_init (&default_value, prop_spec->value_type); + g_value_init (&value, prop_spec->value_type); + + g_param_value_set_default (prop_spec, &default_value); + g_object_get_property (object, prop_spec->name, &value); + + if (g_param_values_cmp (prop_spec, &default_value, &value)) + { + g_object_set_property (object, prop_spec->name, + &default_value); + } + + g_value_unset (&value); + g_value_unset (&default_value); + } + } + } + + g_object_thaw_notify (object); + + g_free (property_specs); +} + + +/** + * gimp_config_reset_property: + * @object: a #GObject + * @property_name: name of the property to reset + * + * Resets the property named @property_name to its default value. The + * property must be writable and must not be marked as "construct-only". + * + * Since: 2.4 + **/ +void +gimp_config_reset_property (GObject *object, + const gchar *property_name) +{ + GObjectClass *klass; + GParamSpec *prop_spec; + + g_return_if_fail (G_IS_OBJECT (object)); + g_return_if_fail (property_name != NULL); + + klass = G_OBJECT_GET_CLASS (object); + + prop_spec = g_object_class_find_property (klass, property_name); + + if (!prop_spec) + return; + + if ((prop_spec->flags & G_PARAM_WRITABLE) && + ! (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY)) + { + GValue value = G_VALUE_INIT; + + if (G_IS_PARAM_SPEC_OBJECT (prop_spec)) + { + if ((prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE) && + (prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE) && + g_type_interface_peek (g_type_class_peek (prop_spec->value_type), + GIMP_TYPE_CONFIG)) + { + g_value_init (&value, prop_spec->value_type); + + g_object_get_property (object, prop_spec->name, &value); + + gimp_config_reset (g_value_get_object (&value)); + + g_value_unset (&value); + } + } + else + { + g_value_init (&value, prop_spec->value_type); + g_param_value_set_default (prop_spec, &value); + + g_object_set_property (object, prop_spec->name, &value); + + g_value_unset (&value); + } + } +} + + +/* + * GimpConfig string utilities + */ + +/** + * gimp_config_string_append_escaped: + * @string: pointer to a #GString + * @val: a string to append or %NULL + * + * Escapes and quotes @val and appends it to @string. The escape + * algorithm is different from the one used by g_strescape() since it + * leaves non-ASCII characters intact and thus preserves UTF-8 + * strings. Only control characters and quotes are being escaped. + * + * Since: 2.4 + **/ +void +gimp_config_string_append_escaped (GString *string, + const gchar *val) +{ + g_return_if_fail (string != NULL); + + if (val) + { + const guchar *p; + gchar buf[4] = { '\\', 0, 0, 0 }; + gint len; + + g_string_append_c (string, '\"'); + + for (p = (const guchar *) val, len = 0; *p; p++) + { + if (*p < ' ' || *p == '\\' || *p == '\"') + { + g_string_append_len (string, val, len); + + len = 2; + switch (*p) + { + case '\b': + buf[1] = 'b'; + break; + case '\f': + buf[1] = 'f'; + break; + case '\n': + buf[1] = 'n'; + break; + case '\r': + buf[1] = 'r'; + break; + case '\t': + buf[1] = 't'; + break; + case '\\': + case '"': + buf[1] = *p; + break; + + default: + len = 4; + buf[1] = '0' + (((*p) >> 6) & 07); + buf[2] = '0' + (((*p) >> 3) & 07); + buf[3] = '0' + ((*p) & 07); + break; + } + + g_string_append_len (string, buf, len); + + val = (const gchar *) p + 1; + len = 0; + } + else + { + len++; + } + } + + g_string_append_len (string, val, len); + g_string_append_c (string, '\"'); + } + else + { + g_string_append_len (string, "\"\"", 2); + } +} diff --git a/libgimpconfig/gimpconfig-utils.h b/libgimpconfig/gimpconfig-utils.h new file mode 100644 index 0000000..6975b64 --- /dev/null +++ b/libgimpconfig/gimpconfig-utils.h @@ -0,0 +1,52 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Utility functions for GimpConfig. + * Copyright (C) 2001-2003 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_CONFIG_UTILS_H__ +#define __GIMP_CONFIG_UTILS_H__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + + +GList * gimp_config_diff (GObject *a, + GObject *b, + GParamFlags flags); + +gboolean gimp_config_sync (GObject *src, + GObject *dest, + GParamFlags flags); + +void gimp_config_reset_properties (GObject *object); +void gimp_config_reset_property (GObject *object, + const gchar *property_name); + +void gimp_config_string_append_escaped (GString *string, + const gchar *val); + + +G_END_DECLS + +#endif /* __GIMP_CONFIG_UTILS_H__ */ diff --git a/libgimpconfig/gimpconfig.def b/libgimpconfig/gimpconfig.def new file mode 100644 index 0000000..582edab --- /dev/null +++ b/libgimpconfig/gimpconfig.def @@ -0,0 +1,94 @@ +EXPORTS + gimp_color_config_get_cmyk_color_profile + gimp_color_config_get_display_bpc + gimp_color_config_get_display_color_profile + gimp_color_config_get_display_intent + gimp_color_config_get_display_optimize + gimp_color_config_get_display_profile_from_gdk + gimp_color_config_get_gray_color_profile + gimp_color_config_get_mode + gimp_color_config_get_rgb_color_profile + gimp_color_config_get_simulation_bpc + gimp_color_config_get_simulation_color_profile + gimp_color_config_get_simulation_gamut_check + gimp_color_config_get_simulation_intent + gimp_color_config_get_simulation_optimize + gimp_color_config_get_type + gimp_color_management_mode_get_type + gimp_color_rendering_intent_get_type + gimp_config_build_data_path + gimp_config_build_plug_in_path + gimp_config_build_writable_path + gimp_config_copy + gimp_config_deserialize + gimp_config_deserialize_file + gimp_config_deserialize_gfile + gimp_config_deserialize_properties + gimp_config_deserialize_property + gimp_config_deserialize_return + gimp_config_deserialize_stream + gimp_config_deserialize_string + gimp_config_diff + gimp_config_duplicate + gimp_config_error_quark + gimp_config_get_type + gimp_config_interface_get_type + gimp_config_is_equal_to + gimp_config_path_expand + gimp_config_path_expand_to_files + gimp_config_path_get_type + gimp_config_path_unexpand + gimp_config_reset + gimp_config_reset_properties + gimp_config_reset_property + gimp_config_serialize + gimp_config_serialize_changed_properties + gimp_config_serialize_properties + gimp_config_serialize_property + gimp_config_serialize_property_by_name + gimp_config_serialize_to_fd + gimp_config_serialize_to_file + gimp_config_serialize_to_gfile + gimp_config_serialize_to_stream + gimp_config_serialize_to_string + gimp_config_serialize_value + gimp_config_string_append_escaped + gimp_config_sync + gimp_config_writer_close + gimp_config_writer_comment + gimp_config_writer_comment_mode + gimp_config_writer_data + gimp_config_writer_finish + gimp_config_writer_identifier + gimp_config_writer_linefeed + gimp_config_writer_new_fd + gimp_config_writer_new_file + gimp_config_writer_new_gfile + gimp_config_writer_new_stream + gimp_config_writer_new_string + gimp_config_writer_open + gimp_config_writer_print + gimp_config_writer_printf + gimp_config_writer_revert + gimp_config_writer_string + gimp_file_get_config_path + gimp_file_new_for_config_path + gimp_param_config_path_get_type + gimp_param_spec_config_path + gimp_param_spec_config_path_type + gimp_scanner_destroy + gimp_scanner_new_file + gimp_scanner_new_gfile + gimp_scanner_new_stream + gimp_scanner_new_string + gimp_scanner_parse_boolean + gimp_scanner_parse_color + gimp_scanner_parse_data + gimp_scanner_parse_float + gimp_scanner_parse_identifier + gimp_scanner_parse_int + gimp_scanner_parse_int64 + gimp_scanner_parse_matrix2 + gimp_scanner_parse_string + gimp_scanner_parse_string_no_validate + gimp_scanner_parse_token diff --git a/libgimpconfig/gimpconfig.h b/libgimpconfig/gimpconfig.h new file mode 100644 index 0000000..1b2bb8e --- /dev/null +++ b/libgimpconfig/gimpconfig.h @@ -0,0 +1,40 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#ifndef __GIMP_CONFIG_H__ +#define __GIMP_CONFIG_H__ + +#define __GIMP_CONFIG_H_INSIDE__ + +#include <libgimpconfig/gimpconfigtypes.h> + +#include <libgimpconfig/gimpconfigwriter.h> +#include <libgimpconfig/gimpconfig-iface.h> +#include <libgimpconfig/gimpconfig-error.h> +#include <libgimpconfig/gimpconfig-serialize.h> +#include <libgimpconfig/gimpconfig-deserialize.h> +#include <libgimpconfig/gimpconfig-utils.h> +#include <libgimpconfig/gimpconfig-params.h> +#include <libgimpconfig/gimpconfig-path.h> +#include <libgimpconfig/gimpscanner.h> + +#include <libgimpconfig/gimpcolorconfig.h> + +#undef __GIMP_CONFIG_H_INSIDE__ + +#endif /* __GIMP_CONFIG_H__ */ diff --git a/libgimpconfig/gimpconfigenums.c b/libgimpconfig/gimpconfigenums.c new file mode 100644 index 0000000..294d7c0 --- /dev/null +++ b/libgimpconfig/gimpconfigenums.c @@ -0,0 +1,79 @@ + +/* Generated data (by gimp-mkenums) */ + +#include "config.h" +#include <gio/gio.h> +#include "libgimpbase/gimpbase.h" +#include "gimpconfigenums.h" +#include "libgimp/libgimp-intl.h" + +/* enumerations from "gimpconfigenums.h" */ +GType +gimp_color_management_mode_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_COLOR_MANAGEMENT_OFF, "GIMP_COLOR_MANAGEMENT_OFF", "off" }, + { GIMP_COLOR_MANAGEMENT_DISPLAY, "GIMP_COLOR_MANAGEMENT_DISPLAY", "display" }, + { GIMP_COLOR_MANAGEMENT_SOFTPROOF, "GIMP_COLOR_MANAGEMENT_SOFTPROOF", "softproof" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_COLOR_MANAGEMENT_OFF, NC_("color-management-mode", "No color management"), NULL }, + { GIMP_COLOR_MANAGEMENT_DISPLAY, NC_("color-management-mode", "Color-managed display"), NULL }, + { GIMP_COLOR_MANAGEMENT_SOFTPROOF, NC_("color-management-mode", "Soft-proofing"), NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (G_UNLIKELY (! type)) + { + type = g_enum_register_static ("GimpColorManagementMode", values); + gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp"); + gimp_type_set_translation_context (type, "color-management-mode"); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} + +GType +gimp_color_rendering_intent_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, "GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL", "perceptual" }, + { GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, "GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC", "relative-colorimetric" }, + { GIMP_COLOR_RENDERING_INTENT_SATURATION, "GIMP_COLOR_RENDERING_INTENT_SATURATION", "saturation" }, + { GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC, "GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC", "absolute-colorimetric" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, NC_("color-rendering-intent", "Perceptual"), NULL }, + { GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, NC_("color-rendering-intent", "Relative colorimetric"), NULL }, + { GIMP_COLOR_RENDERING_INTENT_SATURATION, NC_("color-rendering-intent", "Saturation"), NULL }, + { GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC, NC_("color-rendering-intent", "Absolute colorimetric"), NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (G_UNLIKELY (! type)) + { + type = g_enum_register_static ("GimpColorRenderingIntent", values); + gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp"); + gimp_type_set_translation_context (type, "color-rendering-intent"); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} + + +/* Generated data ends here */ + diff --git a/libgimpconfig/gimpconfigenums.h b/libgimpconfig/gimpconfigenums.h new file mode 100644 index 0000000..ec5c759 --- /dev/null +++ b/libgimpconfig/gimpconfigenums.h @@ -0,0 +1,68 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpconfigenums.h + * Copyright (C) 2004 Stefan Döhla <stefan@doehla.de> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#ifndef __GIMP_CONFIG_ENUMS_H__ +#define __GIMP_CONFIG_ENUMS_H__ + + +#define GIMP_TYPE_COLOR_MANAGEMENT_MODE (gimp_color_management_mode_get_type ()) + +GType gimp_color_management_mode_get_type (void) G_GNUC_CONST; + +/** + * GimpColorManagementMode: + * @GIMP_COLOR_MANAGEMENT_OFF: Color management is off + * @GIMP_COLOR_MANAGEMENT_DISPLAY: Color managed display + * @GIMP_COLOR_MANAGEMENT_SOFTPROOF: Soft-proofing + * + * Modes of color management. + **/ +typedef enum +{ + GIMP_COLOR_MANAGEMENT_OFF, /*< desc="No color management" >*/ + GIMP_COLOR_MANAGEMENT_DISPLAY, /*< desc="Color-managed display" >*/ + GIMP_COLOR_MANAGEMENT_SOFTPROOF /*< desc="Soft-proofing" >*/ +} GimpColorManagementMode; + + +#define GIMP_TYPE_COLOR_RENDERING_INTENT (gimp_color_rendering_intent_get_type ()) + +GType gimp_color_rendering_intent_get_type (void) G_GNUC_CONST; + +/** + * GimpColorRenderingIntent: + * @GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL: Preceptual + * @GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC: Relative colorimetric + * @GIMP_COLOR_RENDERING_INTENT_SATURATION: Saturation + * @GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC: Absolute colorimetric + * + * Intents for color management. + **/ +typedef enum +{ + GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, /*< desc="Perceptual" >*/ + GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, /*< desc="Relative colorimetric" >*/ + GIMP_COLOR_RENDERING_INTENT_SATURATION, /*< desc="Saturation" >*/ + GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC /*< desc="Absolute colorimetric" >*/ +} GimpColorRenderingIntent; + + +#endif /* __GIMP_CONFIG_ENUMS_H__ */ diff --git a/libgimpconfig/gimpconfigtypes.h b/libgimpconfig/gimpconfigtypes.h new file mode 100644 index 0000000..df2fc93 --- /dev/null +++ b/libgimpconfig/gimpconfigtypes.h @@ -0,0 +1,38 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * Config file serialization and deserialization interface + * Copyright (C) 2001-2003 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#ifndef __GIMP_CONFIG_TYPES_H__ +#define __GIMP_CONFIG_TYPES_H__ + + +#include <libgimpbase/gimpbasetypes.h> + + +typedef struct _GimpConfig GimpConfig; /* dummy typedef */ +typedef struct _GimpConfigWriter GimpConfigWriter; +typedef gchar * GimpConfigPath; /* to satisfy docs */ + +typedef struct _GimpColorConfig GimpColorConfig; + +#include <libgimpconfig/gimpconfigenums.h> + + +#endif /* __GIMP_CONFIG_TYPES_H__ */ diff --git a/libgimpconfig/gimpconfigwriter.c b/libgimpconfig/gimpconfigwriter.c new file mode 100644 index 0000000..bac83f3 --- /dev/null +++ b/libgimpconfig/gimpconfigwriter.c @@ -0,0 +1,799 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * GimpConfigWriter + * Copyright (C) 2003 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> + +#include <gio/gio.h> + +#ifdef G_OS_WIN32 +#include <gio/gwin32outputstream.h> +#else +#include <gio/gunixoutputstream.h> +#endif + +#include "libgimpbase/gimpbase.h" + +#include "gimpconfigtypes.h" + +#include "gimpconfigwriter.h" +#include "gimpconfig-iface.h" +#include "gimpconfig-error.h" +#include "gimpconfig-serialize.h" +#include "gimpconfig-utils.h" + +#include "libgimp/libgimp-intl.h" + + +/** + * SECTION: gimpconfigwriter + * @title: GimpConfigWriter + * @short_description: Functions for writing config info to a file for + * libgimpconfig. + * + * Functions for writing config info to a file for libgimpconfig. + **/ + + +struct _GimpConfigWriter +{ + GOutputStream *output; + GFile *file; + GError *error; + GString *buffer; + gboolean comment; + gint depth; + gint marker; +}; + + +static inline void gimp_config_writer_flush (GimpConfigWriter *writer); +static inline void gimp_config_writer_newline (GimpConfigWriter *writer); +static gboolean gimp_config_writer_close_output (GimpConfigWriter *writer, + GError **error); + +static inline void +gimp_config_writer_flush (GimpConfigWriter *writer) +{ + GError *error = NULL; + + if (! writer->output) + return; + + if (! g_output_stream_write_all (writer->output, + writer->buffer->str, + writer->buffer->len, + NULL, NULL, &error)) + { + g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE, + _("Error writing to '%s': %s"), + writer->file ? + gimp_file_get_utf8_name (writer->file) : "output stream", + error->message); + g_clear_error (&error); + } + + g_string_truncate (writer->buffer, 0); +} + +static inline void +gimp_config_writer_newline (GimpConfigWriter *writer) +{ + gint i; + + g_string_append_c (writer->buffer, '\n'); + + if (writer->comment) + g_string_append_len (writer->buffer, "# ", 2); + + for (i = 0; i < writer->depth; i++) + g_string_append_len (writer->buffer, " ", 4); +} + +/** + * gimp_config_writer_new_file: + * @filename: a filename + * @atomic: if %TRUE the file is written atomically + * @header: text to include as comment at the top of the file + * @error: return location for errors + * + * Creates a new #GimpConfigWriter and sets it up to write to + * @filename. If @atomic is %TRUE, a temporary file is used to avoid + * possible race conditions. The temporary file is then moved to + * @filename when the writer is closed. + * + * Return value: a new #GimpConfigWriter or %NULL in case of an error + * + * Since: 2.4 + **/ +GimpConfigWriter * +gimp_config_writer_new_file (const gchar *filename, + gboolean atomic, + const gchar *header, + GError **error) +{ + GimpConfigWriter *writer; + GFile *file; + + g_return_val_if_fail (filename != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + file = g_file_new_for_path (filename); + + writer = gimp_config_writer_new_gfile (file, atomic, header, error); + + g_object_unref (file); + + return writer; +} + +/** + * gimp_config_writer_new_gfile: + * @file: a #GFile + * @atomic: if %TRUE the file is written atomically + * @header: text to include as comment at the top of the file + * @error: return location for errors + * + * Creates a new #GimpConfigWriter and sets it up to write to + * @file. If @atomic is %TRUE, a temporary file is used to avoid + * possible race conditions. The temporary file is then moved to @file + * when the writer is closed. + * + * Return value: a new #GimpConfigWriter or %NULL in case of an error + * + * Since: 2.10 + **/ +GimpConfigWriter * +gimp_config_writer_new_gfile (GFile *file, + gboolean atomic, + const gchar *header, + GError **error) +{ + GimpConfigWriter *writer; + GOutputStream *output; + GFile *dir; + + g_return_val_if_fail (G_IS_FILE (file), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + dir = g_file_get_parent (file); + if (dir && ! g_file_query_exists (dir, NULL)) + { + if (! g_file_make_directory_with_parents (dir, NULL, error)) + g_prefix_error (error, + _("Could not create directory '%s' for '%s': "), + gimp_file_get_utf8_name (dir), + gimp_file_get_utf8_name (file)); + } + g_object_unref (dir); + + if (error && *error) + return NULL; + + if (atomic) + { + output = G_OUTPUT_STREAM (g_file_replace (file, + NULL, FALSE, G_FILE_CREATE_NONE, + NULL, error)); + if (! output) + g_prefix_error (error, + _("Could not create temporary file for '%s': "), + gimp_file_get_utf8_name (file)); + } + else + { + output = G_OUTPUT_STREAM (g_file_replace (file, + NULL, FALSE, + G_FILE_CREATE_REPLACE_DESTINATION, + NULL, error)); + } + + if (! output) + return NULL; + + writer = g_slice_new0 (GimpConfigWriter); + + writer->output = output; + writer->file = g_object_ref (file); + writer->buffer = g_string_new (NULL); + + if (header) + { + gimp_config_writer_comment (writer, header); + gimp_config_writer_linefeed (writer); + } + + return writer; +} + +/** + * gimp_config_writer_new_stream: + * @output: a #GOutputStream + * @header: text to include as comment at the top of the file + * @error: return location for errors + * + * Creates a new #GimpConfigWriter and sets it up to write to + * @output. + * + * Return value: a new #GimpConfigWriter or %NULL in case of an error + * + * Since: 2.10 + **/ +GimpConfigWriter * +gimp_config_writer_new_stream (GOutputStream *output, + const gchar *header, + GError **error) +{ + GimpConfigWriter *writer; + + g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + writer = g_slice_new0 (GimpConfigWriter); + + writer->output = g_object_ref (output); + writer->buffer = g_string_new (NULL); + + if (header) + { + gimp_config_writer_comment (writer, header); + gimp_config_writer_linefeed (writer); + } + + return writer; +} + +/** + * gimp_config_writer_new_fd: + * @fd: + * + * Return value: a new #GimpConfigWriter or %NULL in case of an error + * + * Since: 2.4 + **/ +GimpConfigWriter * +gimp_config_writer_new_fd (gint fd) +{ + GimpConfigWriter *writer; + + g_return_val_if_fail (fd > 0, NULL); + + writer = g_slice_new0 (GimpConfigWriter); + +#ifdef G_OS_WIN32 + writer->output = g_win32_output_stream_new ((gpointer) fd, FALSE); +#else + writer->output = g_unix_output_stream_new (fd, FALSE); +#endif + + writer->buffer = g_string_new (NULL); + + return writer; +} + +/** + * gimp_config_writer_new_string: + * @string: + * + * Return value: a new #GimpConfigWriter or %NULL in case of an error + * + * Since: 2.4 + **/ +GimpConfigWriter * +gimp_config_writer_new_string (GString *string) +{ + GimpConfigWriter *writer; + + g_return_val_if_fail (string != NULL, NULL); + + writer = g_slice_new0 (GimpConfigWriter); + + writer->buffer = string; + + return writer; +} + +/** + * gimp_config_writer_comment_mode: + * @writer: a #GimpConfigWriter + * @enable: %TRUE to enable comment mode, %FALSE to disable it + * + * This function toggles whether the @writer should create commented + * or uncommented output. This feature is used to generate the + * system-wide installed gimprc that documents the default settings. + * + * Since comments have to start at the beginning of a line, this + * function will insert a newline if necessary. + * + * Since: 2.4 + **/ +void +gimp_config_writer_comment_mode (GimpConfigWriter *writer, + gboolean enable) +{ + g_return_if_fail (writer != NULL); + + if (writer->error) + return; + + enable = (enable ? TRUE : FALSE); + + if (writer->comment == enable) + return; + + writer->comment = enable; + + if (enable) + { + if (writer->buffer->len == 0) + g_string_append_len (writer->buffer, "# ", 2); + else + gimp_config_writer_newline (writer); + } +} + + +/** + * gimp_config_writer_open: + * @writer: a #GimpConfigWriter + * @name: name of the element to open + * + * This function writes the opening parenthesis followed by @name. + * It also increases the indentation level and sets a mark that + * can be used by gimp_config_writer_revert(). + * + * Since: 2.4 + **/ +void +gimp_config_writer_open (GimpConfigWriter *writer, + const gchar *name) +{ + g_return_if_fail (writer != NULL); + g_return_if_fail (name != NULL); + + if (writer->error) + return; + + /* store the current buffer length so we can revert to this state */ + writer->marker = writer->buffer->len; + + if (writer->depth > 0) + gimp_config_writer_newline (writer); + + writer->depth++; + + g_string_append_printf (writer->buffer, "(%s", name); +} + +/** + * gimp_config_writer_print: + * @writer: a #GimpConfigWriter + * @string: a string to write + * @len: number of bytes from @string or -1 if @string is NUL-terminated. + * + * Appends a space followed by @string to the @writer. Note that string + * must not contain any special characters that might need to be escaped. + * + * Since: 2.4 + **/ +void +gimp_config_writer_print (GimpConfigWriter *writer, + const gchar *string, + gint len) +{ + g_return_if_fail (writer != NULL); + g_return_if_fail (len == 0 || string != NULL); + + if (writer->error) + return; + + if (len < 0) + len = strlen (string); + + if (len) + { + g_string_append_c (writer->buffer, ' '); + g_string_append_len (writer->buffer, string, len); + } +} + +/** + * gimp_config_writer_printf: + * @writer: a #GimpConfigWriter + * @format: a format string as described for g_strdup_printf(). + * @...: list of arguments according to @format + * + * A printf-like function for #GimpConfigWriter. + * + * Since: 2.4 + **/ +void +gimp_config_writer_printf (GimpConfigWriter *writer, + const gchar *format, + ...) +{ + gchar *buffer; + va_list args; + + g_return_if_fail (writer != NULL); + g_return_if_fail (format != NULL); + + if (writer->error) + return; + + va_start (args, format); + buffer = g_strdup_vprintf (format, args); + va_end (args); + + g_string_append_c (writer->buffer, ' '); + g_string_append (writer->buffer, buffer); + + g_free (buffer); +} + +/** + * gimp_config_writer_string: + * @writer: a #GimpConfigWriter + * @string: a NUL-terminated string + * + * Writes a string value to @writer. The @string is quoted and special + * characters are escaped. + * + * Since: 2.4 + **/ +void +gimp_config_writer_string (GimpConfigWriter *writer, + const gchar *string) +{ + g_return_if_fail (writer != NULL); + + if (writer->error) + return; + + g_string_append_c (writer->buffer, ' '); + gimp_config_string_append_escaped (writer->buffer, string); +} + +/** + * gimp_config_writer_identifier: + * @writer: a #GimpConfigWriter + * @identifier: a NUL-terminated string + * + * Writes an identifier to @writer. The @string is *not* quoted and special + * characters are *not* escaped. + * + * Since: 2.4 + **/ +void +gimp_config_writer_identifier (GimpConfigWriter *writer, + const gchar *identifier) +{ + g_return_if_fail (writer != NULL); + g_return_if_fail (identifier != NULL); + + if (writer->error) + return; + + g_string_append_printf (writer->buffer, " %s", identifier); +} + + +/** + * gimp_config_writer_data: + * @writer: a #GimpConfigWriter + * @length: + * @data: + * + * Since: 2.4 + **/ +void +gimp_config_writer_data (GimpConfigWriter *writer, + gint length, + const guint8 *data) +{ + gint i; + + g_return_if_fail (writer != NULL); + g_return_if_fail (length >= 0); + g_return_if_fail (data != NULL || length == 0); + + if (writer->error) + return; + + g_string_append (writer->buffer, " \""); + + for (i = 0; i < length; i++) + { + if (g_ascii_isalpha (data[i])) + g_string_append_c (writer->buffer, data[i]); + else + g_string_append_printf (writer->buffer, "\\%o", data[i]); + } + + g_string_append (writer->buffer, "\""); +} + +/** + * gimp_config_writer_revert: + * @writer: a #GimpConfigWriter + * + * Reverts all changes to @writer that were done since the last call + * to gimp_config_writer_open(). This can only work if you didn't call + * gimp_config_writer_close() yet. + * + * Since: 2.4 + **/ +void +gimp_config_writer_revert (GimpConfigWriter *writer) +{ + g_return_if_fail (writer != NULL); + + if (writer->error) + return; + + g_return_if_fail (writer->depth > 0); + g_return_if_fail (writer->marker != -1); + + g_string_truncate (writer->buffer, writer->marker); + + writer->depth--; + writer->marker = -1; +} + +/** + * gimp_config_writer_close: + * @writer: a #GimpConfigWriter + * + * Closes an element opened with gimp_config_writer_open(). + * + * Since: 2.4 + **/ +void +gimp_config_writer_close (GimpConfigWriter *writer) +{ + g_return_if_fail (writer != NULL); + + if (writer->error) + return; + + g_return_if_fail (writer->depth > 0); + + g_string_append_c (writer->buffer, ')'); + + if (--writer->depth == 0) + { + g_string_append_c (writer->buffer, '\n'); + + gimp_config_writer_flush (writer); + } +} + +/** + * gimp_config_writer_finish: + * @writer: a #GimpConfigWriter + * @footer: text to include as comment at the bottom of the file + * @error: return location for possible errors + * + * This function finishes the work of @writer and frees it afterwards. + * It closes all open elements, appends an optional comment and + * releases all resources allocated by @writer. You must not access + * the @writer afterwards. + * + * Return value: %TRUE if everything could be successfully written, + * %FALSE otherwise + * + * Since: 2.4 + **/ +gboolean +gimp_config_writer_finish (GimpConfigWriter *writer, + const gchar *footer, + GError **error) +{ + gboolean success = TRUE; + + g_return_val_if_fail (writer != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (writer->depth < 0) + { + g_warning ("gimp_config_writer_finish: depth < 0 !!"); + } + else + { + while (writer->depth) + gimp_config_writer_close (writer); + } + + if (footer) + { + gimp_config_writer_linefeed (writer); + gimp_config_writer_comment (writer, footer); + } + + if (writer->output) + { + success = gimp_config_writer_close_output (writer, error); + + if (writer->file) + g_object_unref (writer->file); + + g_string_free (writer->buffer, TRUE); + } + + if (writer->error) + { + if (error && *error == NULL) + g_propagate_error (error, writer->error); + else + g_clear_error (&writer->error); + + success = FALSE; + } + + g_slice_free (GimpConfigWriter, writer); + + return success; +} + +void +gimp_config_writer_linefeed (GimpConfigWriter *writer) +{ + g_return_if_fail (writer != NULL); + + if (writer->error) + return; + + if (writer->output && writer->buffer->len == 0 && !writer->comment) + { + GError *error = NULL; + + if (! g_output_stream_write_all (writer->output, "\n", 1, + NULL, NULL, &error)) + { + g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE, + _("Error writing to '%s': %s"), + writer->file ? + gimp_file_get_utf8_name (writer->file) : "output stream", + error->message); + g_clear_error (&error); + } + } + else + { + gimp_config_writer_newline (writer); + } +} + +/** + * gimp_config_writer_comment: + * @writer: a #GimpConfigWriter + * @comment: the comment to write (ASCII only) + * + * Appends the @comment to @str and inserts linebreaks and hash-marks to + * format it as a comment. Note that this function does not handle non-ASCII + * characters. + * + * Since: 2.4 + **/ +void +gimp_config_writer_comment (GimpConfigWriter *writer, + const gchar *comment) +{ + const gchar *s; + gboolean comment_mode; + gint i, len, space; + +#define LINE_LENGTH 75 + + g_return_if_fail (writer != NULL); + + if (writer->error) + return; + + g_return_if_fail (writer->depth == 0); + + if (!comment) + return; + + comment_mode = writer->comment; + gimp_config_writer_comment_mode (writer, TRUE); + + len = strlen (comment); + + while (len > 0) + { + for (s = comment, i = 0, space = 0; + *s != '\n' && (i <= LINE_LENGTH || space == 0) && i < len; + s++, i++) + { + if (g_ascii_isspace (*s)) + space = i; + } + + if (i > LINE_LENGTH && space && *s != '\n') + i = space; + + g_string_append_len (writer->buffer, comment, i); + + i++; + + comment += i; + len -= i; + + if (len > 0) + gimp_config_writer_newline (writer); + } + + gimp_config_writer_comment_mode (writer, comment_mode); + gimp_config_writer_newline (writer); + + if (writer->depth == 0) + gimp_config_writer_flush (writer); + +#undef LINE_LENGTH +} + +static gboolean +gimp_config_writer_close_output (GimpConfigWriter *writer, + GError **error) +{ + g_return_val_if_fail (writer->output != NULL, FALSE); + + if (writer->error) + { + GCancellable *cancellable = g_cancellable_new (); + + /* Cancel the overwrite initiated by g_file_replace(). */ + g_cancellable_cancel (cancellable); + g_output_stream_close (writer->output, cancellable, NULL); + g_object_unref (cancellable); + + g_object_unref (writer->output); + writer->output = NULL; + + return FALSE; + } + + if (writer->file) + { + GError *my_error = NULL; + + if (! g_output_stream_close (writer->output, NULL, &my_error)) + { + g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE, + _("Error writing '%s': %s"), + gimp_file_get_utf8_name (writer->file), + my_error->message); + g_clear_error (&my_error); + + g_object_unref (writer->output); + writer->output = NULL; + + return FALSE; + } + } + + g_object_unref (writer->output); + writer->output = NULL; + + return TRUE; +} diff --git a/libgimpconfig/gimpconfigwriter.h b/libgimpconfig/gimpconfigwriter.h new file mode 100644 index 0000000..91a1a10 --- /dev/null +++ b/libgimpconfig/gimpconfigwriter.h @@ -0,0 +1,74 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * GimpConfigWriter + * Copyright (C) 2003 Sven Neumann <sven@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_CONFIG_WRITER_H__ +#define __GIMP_CONFIG_WRITER_H__ + + +GimpConfigWriter * gimp_config_writer_new_file (const gchar *filename, + gboolean atomic, + const gchar *header, + GError **error); +GimpConfigWriter * gimp_config_writer_new_gfile (GFile *file, + gboolean atomic, + const gchar *header, + GError **error); +GimpConfigWriter * gimp_config_writer_new_stream (GOutputStream *output, + const gchar *header, + GError **error); +GimpConfigWriter * gimp_config_writer_new_fd (gint fd); +GimpConfigWriter * gimp_config_writer_new_string (GString *string); + +void gimp_config_writer_open (GimpConfigWriter *writer, + const gchar *name); +void gimp_config_writer_comment_mode (GimpConfigWriter *writer, + gboolean enable); + +void gimp_config_writer_print (GimpConfigWriter *writer, + const gchar *string, + gint len); +void gimp_config_writer_printf (GimpConfigWriter *writer, + const gchar *format, + ...) G_GNUC_PRINTF (2, 3); +void gimp_config_writer_identifier (GimpConfigWriter *writer, + const gchar *identifier); +void gimp_config_writer_string (GimpConfigWriter *writer, + const gchar *string); +void gimp_config_writer_data (GimpConfigWriter *writer, + gint length, + const guint8 *data); +void gimp_config_writer_comment (GimpConfigWriter *writer, + const gchar *comment); +void gimp_config_writer_linefeed (GimpConfigWriter *writer); + + +void gimp_config_writer_revert (GimpConfigWriter *writer); +void gimp_config_writer_close (GimpConfigWriter *writer); +gboolean gimp_config_writer_finish (GimpConfigWriter *writer, + const gchar *footer, + GError **error); + + +#endif /* __GIMP_CONFIG_WRITER_H__ */ diff --git a/libgimpconfig/gimpscanner.c b/libgimpconfig/gimpscanner.c new file mode 100644 index 0000000..8f65d08 --- /dev/null +++ b/libgimpconfig/gimpscanner.c @@ -0,0 +1,871 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpscanner.c + * Copyright (C) 2002 Sven Neumann <sven@gimp.org> + * Michael Natterer <mitch@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> +#include <errno.h> + +#include <cairo.h> +#include <gegl.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include "libgimpbase/gimpbase.h" +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" + +#include "gimpconfig-error.h" +#include "gimpscanner.h" + +#include "libgimp/libgimp-intl.h" + + +/** + * SECTION: gimpscanner + * @title: GimpScanner + * @short_description: A wrapper around #GScanner with some convenience API. + * + * A wrapper around #GScanner with some convenience API. + **/ + + +typedef struct +{ + gchar *name; + GMappedFile *mapped; + gchar *text; + GError **error; +} GimpScannerData; + + +/* local function prototypes */ + +static GScanner * gimp_scanner_new (const gchar *name, + GMappedFile *mapped, + gchar *text, + GError **error); +static void gimp_scanner_message (GScanner *scanner, + gchar *message, + gboolean is_error); + + +/* public functions */ + +/** + * gimp_scanner_new_file: + * @filename: + * @error: + * + * Return value: + * + * Since: 2.4 + **/ +GScanner * +gimp_scanner_new_file (const gchar *filename, + GError **error) +{ + GScanner *scanner; + GFile *file; + + g_return_val_if_fail (filename != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + file = g_file_new_for_path (filename); + scanner = gimp_scanner_new_gfile (file, error); + g_object_unref (file); + + return scanner; +} + +/** + * gimp_scanner_new_gfile: + * @file: a #GFile + * @error: return location for #GError, or %NULL + * + * Return value: The new #GScanner. + * + * Since: 2.10 + **/ +GScanner * +gimp_scanner_new_gfile (GFile *file, + GError **error) +{ + GScanner *scanner; + gchar *path; + + g_return_val_if_fail (G_IS_FILE (file), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + path = g_file_get_path (file); + + if (path) + { + GMappedFile *mapped; + + mapped = g_mapped_file_new (path, FALSE, error); + g_free (path); + + if (! mapped) + { + if (error) + { + (*error)->domain = GIMP_CONFIG_ERROR; + (*error)->code = ((*error)->code == G_FILE_ERROR_NOENT ? + GIMP_CONFIG_ERROR_OPEN_ENOENT : + GIMP_CONFIG_ERROR_OPEN); + } + + return NULL; + } + + /* gimp_scanner_new() takes a "name" for the scanner, not a filename */ + scanner = gimp_scanner_new (gimp_file_get_utf8_name (file), + mapped, NULL, error); + + g_scanner_input_text (scanner, + g_mapped_file_get_contents (mapped), + g_mapped_file_get_length (mapped)); + } + else + { + GInputStream *input; + + input = G_INPUT_STREAM (g_file_read (file, NULL, error)); + + if (! input) + { + if (error) + { + (*error)->domain = GIMP_CONFIG_ERROR; + (*error)->code = ((*error)->code == G_IO_ERROR_NOT_FOUND ? + GIMP_CONFIG_ERROR_OPEN_ENOENT : + GIMP_CONFIG_ERROR_OPEN); + } + + return NULL; + } + + g_object_set_data (G_OBJECT (input), "gimp-data", file); + + scanner = gimp_scanner_new_stream (input, error); + + g_object_unref (input); + } + + return scanner; +} + +/** + * gimp_scanner_new_stream: + * @input: a #GInputStream + * @error: return location for #GError, or %NULL + * + * Return value: The new #GScanner. + * + * Since: 2.10 + **/ +GScanner * +gimp_scanner_new_stream (GInputStream *input, + GError **error) +{ + GScanner *scanner; + GFile *file; + const gchar *path; + GString *string; + gchar buffer[4096]; + gsize bytes_read; + + g_return_val_if_fail (G_IS_INPUT_STREAM (input), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + file = g_object_get_data (G_OBJECT (input), "gimp-file"); + if (file) + path = gimp_file_get_utf8_name (file); + else + path = "stream"; + + string = g_string_new (NULL); + + do + { + GError *my_error = NULL; + gboolean success; + + success = g_input_stream_read_all (input, buffer, sizeof (buffer), + &bytes_read, NULL, &my_error); + + if (bytes_read > 0) + g_string_append_len (string, buffer, bytes_read); + + if (! success) + { + if (string->len > 0) + { + g_printerr ("%s: read error in '%s', trying to scan " + "partial content: %s", + G_STRFUNC, path, my_error->message); + g_clear_error (&my_error); + break; + } + + g_string_free (string, TRUE); + + g_propagate_error (error, my_error); + + return NULL; + } + } + while (bytes_read == sizeof (buffer)); + + /* gimp_scanner_new() takes a "name" for the scanner, not a filename */ + scanner = gimp_scanner_new (path, NULL, string->str, error); + + bytes_read = string->len; + + g_scanner_input_text (scanner, g_string_free (string, FALSE), bytes_read); + + return scanner; +} + +/** + * gimp_scanner_new_string: + * @text: + * @text_len: + * @error: + * + * Return value: + * + * Since: 2.4 + **/ +GScanner * +gimp_scanner_new_string (const gchar *text, + gint text_len, + GError **error) +{ + GScanner *scanner; + + g_return_val_if_fail (text != NULL || text_len <= 0, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (text_len < 0) + text_len = text ? strlen (text) : 0; + + scanner = gimp_scanner_new (NULL, NULL, NULL, error); + + g_scanner_input_text (scanner, text, text_len); + + return scanner; +} + +static GScanner * +gimp_scanner_new (const gchar *name, + GMappedFile *mapped, + gchar *text, + GError **error) +{ + GScanner *scanner; + GimpScannerData *data; + + scanner = g_scanner_new (NULL); + + data = g_slice_new0 (GimpScannerData); + + data->name = g_strdup (name); + data->mapped = mapped; + data->text = text; + data->error = error; + + scanner->user_data = data; + scanner->msg_handler = gimp_scanner_message; + + scanner->config->cset_identifier_first = ( G_CSET_a_2_z G_CSET_A_2_Z ); + scanner->config->cset_identifier_nth = ( G_CSET_a_2_z G_CSET_A_2_Z + G_CSET_DIGITS "-_" ); + scanner->config->scan_identifier_1char = TRUE; + + scanner->config->store_int64 = TRUE; + + return scanner; +} + +/** + * gimp_scanner_destroy: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * + * Since: 2.4 + **/ +void +gimp_scanner_destroy (GScanner *scanner) +{ + GimpScannerData *data; + + g_return_if_fail (scanner != NULL); + + data = scanner->user_data; + + if (data->mapped) + g_mapped_file_unref (data->mapped); + + if (data->text) + g_free (data->text); + + g_free (data->name); + g_slice_free (GimpScannerData, data); + + g_scanner_destroy (scanner); +} + +/** + * gimp_scanner_parse_token: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @token: the #GTokenType expected as next token. + * + * Return value: %TRUE if the next token is @token, %FALSE otherwise. + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_token (GScanner *scanner, + GTokenType token) +{ + if (g_scanner_peek_next_token (scanner) != token) + return FALSE; + + g_scanner_get_next_token (scanner); + + return TRUE; +} + +/** + * gimp_scanner_parse_identifier: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @identifier: the expected identifier. + * + * Return value: %TRUE if the next token is an identifier and if its + * value matches @identifier. + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_identifier (GScanner *scanner, + const gchar *identifier) +{ + if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER) + return FALSE; + + g_scanner_get_next_token (scanner); + + if (strcmp (scanner->value.v_identifier, identifier)) + return FALSE; + + return TRUE; +} + +/** + * gimp_scanner_parse_string: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @dest: Return location for the parsed string + * + * Return value: %TRUE on success + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_string (GScanner *scanner, + gchar **dest) +{ + if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING) + return FALSE; + + g_scanner_get_next_token (scanner); + + if (*scanner->value.v_string) + { + if (! g_utf8_validate (scanner->value.v_string, -1, NULL)) + { + g_scanner_warn (scanner, _("invalid UTF-8 string")); + return FALSE; + } + + *dest = g_strdup (scanner->value.v_string); + } + else + { + *dest = NULL; + } + + return TRUE; +} + +/** + * gimp_scanner_parse_string_no_validate: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @dest: Return location for the parsed string + * + * Return value: %TRUE on success + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_string_no_validate (GScanner *scanner, + gchar **dest) +{ + if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING) + return FALSE; + + g_scanner_get_next_token (scanner); + + if (*scanner->value.v_string) + *dest = g_strdup (scanner->value.v_string); + else + *dest = NULL; + + return TRUE; +} + +/** + * gimp_scanner_parse_data: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @length: Length of the data to parse + * @dest: Return location for the parsed data + * + * Return value: %TRUE on success + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_data (GScanner *scanner, + gint length, + guint8 **dest) +{ + if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING) + return FALSE; + + g_scanner_get_next_token (scanner); + + if (scanner->value.v_string) + *dest = g_memdup (scanner->value.v_string, length); + else + *dest = NULL; + + return TRUE; +} + +/** + * gimp_scanner_parse_int: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @dest: Return location for the parsed integer + * + * Return value: %TRUE on success + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_int (GScanner *scanner, + gint *dest) +{ + gboolean negate = FALSE; + + if (g_scanner_peek_next_token (scanner) == '-') + { + negate = TRUE; + g_scanner_get_next_token (scanner); + } + + if (g_scanner_peek_next_token (scanner) != G_TOKEN_INT) + return FALSE; + + g_scanner_get_next_token (scanner); + + if (negate) + *dest = -scanner->value.v_int64; + else + *dest = scanner->value.v_int64; + + return TRUE; +} + +/** + * gimp_scanner_parse_int64: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @dest: Return location for the parsed integer + * + * Return value: %TRUE on success + * + * Since: 2.8 + **/ +gboolean +gimp_scanner_parse_int64 (GScanner *scanner, + gint64 *dest) +{ + gboolean negate = FALSE; + + if (g_scanner_peek_next_token (scanner) == '-') + { + negate = TRUE; + g_scanner_get_next_token (scanner); + } + + if (g_scanner_peek_next_token (scanner) != G_TOKEN_INT) + return FALSE; + + g_scanner_get_next_token (scanner); + + if (negate) + *dest = -scanner->value.v_int64; + else + *dest = scanner->value.v_int64; + + return TRUE; +} + +/** + * gimp_scanner_parse_float: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @dest: Return location for the parsed float + * + * Return value: %TRUE on success + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_float (GScanner *scanner, + gdouble *dest) +{ + gboolean negate = FALSE; + + if (g_scanner_peek_next_token (scanner) == '-') + { + negate = TRUE; + g_scanner_get_next_token (scanner); + } + + if (g_scanner_peek_next_token (scanner) == G_TOKEN_FLOAT) + { + g_scanner_get_next_token (scanner); + + if (negate) + *dest = -scanner->value.v_float; + else + *dest = scanner->value.v_float; + + return TRUE; + } + else if (g_scanner_peek_next_token (scanner) == G_TOKEN_INT) + { + g_scanner_get_next_token (scanner); + + if (negate) + *dest = -scanner->value.v_int; + else + *dest = scanner->value.v_int; + + return TRUE; + } + + return FALSE; +} + +/** + * gimp_scanner_parse_boolean: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @dest: Return location for the parsed boolean + * + * Return value: %TRUE on success + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_boolean (GScanner *scanner, + gboolean *dest) +{ + if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER) + return FALSE; + + g_scanner_get_next_token (scanner); + + if (! g_ascii_strcasecmp (scanner->value.v_identifier, "yes") || + ! g_ascii_strcasecmp (scanner->value.v_identifier, "true")) + { + *dest = TRUE; + } + else if (! g_ascii_strcasecmp (scanner->value.v_identifier, "no") || + ! g_ascii_strcasecmp (scanner->value.v_identifier, "false")) + { + *dest = FALSE; + } + else + { + g_scanner_error + (scanner, + /* please don't translate 'yes' and 'no' */ + _("expected 'yes' or 'no' for boolean token, got '%s'"), + scanner->value.v_identifier); + + return FALSE; + } + + return TRUE; +} + +enum +{ + COLOR_RGB = 1, + COLOR_RGBA, + COLOR_HSV, + COLOR_HSVA +}; + +/** + * gimp_scanner_parse_color: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @dest: Pointer to a color to store the result + * + * Return value: %TRUE on success + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_color (GScanner *scanner, + GimpRGB *dest) +{ + guint scope_id; + guint old_scope_id; + GTokenType token; + GimpRGB color = { 0.0, 0.0, 0.0, 1.0 }; + + scope_id = g_quark_from_static_string ("gimp_scanner_parse_color"); + old_scope_id = g_scanner_set_scope (scanner, scope_id); + + if (! g_scanner_scope_lookup_symbol (scanner, scope_id, "color-rgb")) + { + g_scanner_scope_add_symbol (scanner, scope_id, + "color-rgb", GINT_TO_POINTER (COLOR_RGB)); + g_scanner_scope_add_symbol (scanner, scope_id, + "color-rgba", GINT_TO_POINTER (COLOR_RGBA)); + g_scanner_scope_add_symbol (scanner, scope_id, + "color-hsv", GINT_TO_POINTER (COLOR_HSV)); + g_scanner_scope_add_symbol (scanner, scope_id, + "color-hsva", GINT_TO_POINTER (COLOR_HSVA)); + } + + token = G_TOKEN_LEFT_PAREN; + + while (g_scanner_peek_next_token (scanner) == token) + { + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case G_TOKEN_LEFT_PAREN: + token = G_TOKEN_SYMBOL; + break; + + case G_TOKEN_SYMBOL: + { + gdouble col[4] = { 0.0, 0.0, 0.0, 1.0 }; + gint n_channels = 4; + gboolean is_hsv = FALSE; + gint i; + + switch (GPOINTER_TO_INT (scanner->value.v_symbol)) + { + case COLOR_RGB: + n_channels = 3; + /* fallthrough */ + case COLOR_RGBA: + break; + + case COLOR_HSV: + n_channels = 3; + /* fallthrough */ + case COLOR_HSVA: + is_hsv = TRUE; + break; + } + + token = G_TOKEN_FLOAT; + + for (i = 0; i < n_channels; i++) + { + if (! gimp_scanner_parse_float (scanner, &col[i])) + goto finish; + } + + if (is_hsv) + { + GimpHSV hsv; + + gimp_hsva_set (&hsv, col[0], col[1], col[2], col[3]); + gimp_hsv_to_rgb (&hsv, &color); + } + else + { + gimp_rgba_set (&color, col[0], col[1], col[2], col[3]); + } + + token = G_TOKEN_RIGHT_PAREN; + } + break; + + case G_TOKEN_RIGHT_PAREN: + token = G_TOKEN_NONE; /* indicates success */ + goto finish; + + default: /* do nothing */ + break; + } + } + + finish: + + if (token != G_TOKEN_NONE) + { + g_scanner_get_next_token (scanner); + g_scanner_unexp_token (scanner, token, NULL, NULL, NULL, + _("fatal parse error"), TRUE); + } + else + { + *dest = color; + } + + g_scanner_set_scope (scanner, old_scope_id); + + return (token == G_TOKEN_NONE); +} + +/** + * gimp_scanner_parse_matrix2: + * @scanner: A #GScanner created by gimp_scanner_new_file() or + * gimp_scanner_new_string() + * @dest: Pointer to a matrix to store the result + * + * Return value: %TRUE on success + * + * Since: 2.4 + **/ +gboolean +gimp_scanner_parse_matrix2 (GScanner *scanner, + GimpMatrix2 *dest) +{ + guint scope_id; + guint old_scope_id; + GTokenType token; + GimpMatrix2 matrix; + + scope_id = g_quark_from_static_string ("gimp_scanner_parse_matrix"); + old_scope_id = g_scanner_set_scope (scanner, scope_id); + + if (! g_scanner_scope_lookup_symbol (scanner, scope_id, "matrix")) + g_scanner_scope_add_symbol (scanner, scope_id, + "matrix", GINT_TO_POINTER (0)); + + token = G_TOKEN_LEFT_PAREN; + + while (g_scanner_peek_next_token (scanner) == token) + { + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case G_TOKEN_LEFT_PAREN: + token = G_TOKEN_SYMBOL; + break; + + case G_TOKEN_SYMBOL: + { + token = G_TOKEN_FLOAT; + + if (! gimp_scanner_parse_float (scanner, &matrix.coeff[0][0])) + goto finish; + if (! gimp_scanner_parse_float (scanner, &matrix.coeff[0][1])) + goto finish; + if (! gimp_scanner_parse_float (scanner, &matrix.coeff[1][0])) + goto finish; + if (! gimp_scanner_parse_float (scanner, &matrix.coeff[1][1])) + goto finish; + + token = G_TOKEN_RIGHT_PAREN; + } + break; + + case G_TOKEN_RIGHT_PAREN: + token = G_TOKEN_NONE; /* indicates success */ + goto finish; + + default: /* do nothing */ + break; + } + } + + finish: + + if (token != G_TOKEN_NONE) + { + g_scanner_get_next_token (scanner); + g_scanner_unexp_token (scanner, token, NULL, NULL, NULL, + _("fatal parse error"), TRUE); + } + else + { + *dest = matrix; + } + + g_scanner_set_scope (scanner, old_scope_id); + + return (token == G_TOKEN_NONE); +} + + +/* private functions */ + +static void +gimp_scanner_message (GScanner *scanner, + gchar *message, + gboolean is_error) +{ + GimpScannerData *data = scanner->user_data; + + /* we don't expect warnings */ + g_return_if_fail (is_error); + + if (data->name) + g_set_error (data->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE, + _("Error while parsing '%s' in line %d: %s"), + data->name, scanner->line, message); + else + /* should never happen, thus not marked for translation */ + g_set_error (data->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE, + "Error parsing internal buffer: %s", message); +} diff --git a/libgimpconfig/gimpscanner.h b/libgimpconfig/gimpscanner.h new file mode 100644 index 0000000..36ce8d9 --- /dev/null +++ b/libgimpconfig/gimpscanner.h @@ -0,0 +1,67 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpscanner.h + * Copyright (C) 2002 Sven Neumann <sven@gimp.org> + * Michael Natterer <mitch@gimp.org> + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION) +#error "Only <libgimpconfig/gimpconfig.h> can be included directly." +#endif + +#ifndef __GIMP_SCANNER_H__ +#define __GIMP_SCANNER_H__ + + +GScanner * gimp_scanner_new_file (const gchar *filename, + GError **error); +GScanner * gimp_scanner_new_gfile (GFile *file, + GError **error); +GScanner * gimp_scanner_new_stream (GInputStream *input, + GError **error); +GScanner * gimp_scanner_new_string (const gchar *text, + gint text_len, + GError **error); +void gimp_scanner_destroy (GScanner *scanner); + +gboolean gimp_scanner_parse_token (GScanner *scanner, + GTokenType token); +gboolean gimp_scanner_parse_identifier (GScanner *scanner, + const gchar *identifier); +gboolean gimp_scanner_parse_string (GScanner *scanner, + gchar **dest); +gboolean gimp_scanner_parse_string_no_validate (GScanner *scanner, + gchar **dest); +gboolean gimp_scanner_parse_data (GScanner *scanner, + gint length, + guint8 **dest); +gboolean gimp_scanner_parse_int (GScanner *scanner, + gint *dest); +gboolean gimp_scanner_parse_int64 (GScanner *scanner, + gint64 *dest); +gboolean gimp_scanner_parse_float (GScanner *scanner, + gdouble *dest); +gboolean gimp_scanner_parse_boolean (GScanner *scanner, + gboolean *dest); +gboolean gimp_scanner_parse_color (GScanner *scanner, + GimpRGB *dest); +gboolean gimp_scanner_parse_matrix2 (GScanner *scanner, + GimpMatrix2 *dest); + + +#endif /* __GIMP_SCANNER_H__ */ |