Project import generated by Copybara. GitOrigin-RevId: 3f33ab8e637a446002e7de8fc64cb862d3ddf759
diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..13fd0fb --- /dev/null +++ b/.clang-format
@@ -0,0 +1,11 @@ +# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting +BasedOnStyle: GNU +AlwaysBreakAfterDefinitionReturnType: All +BreakBeforeBinaryOperators: None +BinPackParameters: false +SpaceAfterCStyleCast: true +# Our column limit is actually 80, but setting that results in clang-format +# making a lot of dubious hanging-indent choices; disable it and assume the +# developer will line wrap appropriately. clang-format will still check +# existing hanging indents. +ColumnLimit: 0
diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..abf24af --- /dev/null +++ b/.dir-locals.el
@@ -0,0 +1 @@ +((c-mode . ((indent-tabs-mode . nil)))))
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3ff37de --- /dev/null +++ b/.gitattributes
@@ -0,0 +1 @@ +README.win32 text eol=crlf
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6b1ad6a --- /dev/null +++ b/.gitignore
@@ -0,0 +1,30 @@ +# for all subdirectories +TAGS +tags +.libs +.deps +*.o +*.lo +*.la +*.pc +.*.swp +.sw? +*.rc +*.gcno +*.gcda +*.gcov +*.sourcefiles +*.stp +*.exe +*.def +*.test +*.log +*.trs + +INSTALL +/glib-lcov.info +/glib-lcov/ + +# Meson +/meson-build/ +/subprojects/*/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..fb0454e --- /dev/null +++ b/.gitlab-ci.yml
@@ -0,0 +1,481 @@ +stages: + - style-check + - build + - coverage + - analysis + - deploy + +cache: + paths: + - _ccache/ + +variables: + FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/glib/fedora:v9" + DEBIAN_IMAGE: "registry.gitlab.gnome.org/gnome/glib/debian-stable:v6" + ANDROID_IMAGE: "registry.gitlab.gnome.org/gnome/glib/android-ndk:v3" + MINGW_IMAGE: "registry.gitlab.gnome.org/gnome/glib/mingw:v2" + MESON_TEST_TIMEOUT_MULTIPLIER: 2 + G_MESSAGES_DEBUG: all + MESON_COMMON_OPTIONS_NO_WARNING: "--buildtype debug --wrap-mode=nodownload" + MESON_COMMON_OPTIONS: "${MESON_COMMON_OPTIONS_NO_WARNING} --fatal-meson-warnings" + +.only-default: + only: + - branches + except: + - tags + +.build: + extends: .only-default + before_script: + - bash .gitlab-ci/show-execution-environment.sh + - cp -r $HOME/subprojects/* subprojects/ + +style-check-diff: + extends: .only-default + image: $DEBIAN_IMAGE + stage: style-check + allow_failure: true + script: + - .gitlab-ci/run-style-check-diff.sh + +check-todos: + extends: .only-default + image: $DEBIAN_IMAGE + stage: style-check + allow_failure: true + script: + - .gitlab-ci/run-check-todos.sh + +fedora-x86_64: + extends: .build + image: $FEDORA_IMAGE + stage: build + variables: + CFLAGS: "-coverage -ftest-coverage -fprofile-arcs" + script: + # FIXME: Cannot use MESON_COMMON_OPTIONS here because meson warns about gtkdoc + # feature introduced in 0.52 but we only depends on 0.49. So we cannot build + # with --fatal-meson-warnings. + - meson ${MESON_COMMON_OPTIONS_NO_WARNING} + --werror + --default-library=both + --prefix=$HOME/glib-installed + --libdir=lib + -Dsystemtap=true + -Ddtrace=true + -Dfam=true + -Dinstalled_tests=true + -Dgtk_doc=true + _build + - ninja -C _build + - mkdir -p _coverage + - lcov --config-file .gitlab-ci/lcovrc --directory _build --capture --initial --output-file "_coverage/${CI_JOB_NAME}-baseline.lcov" + - .gitlab-ci/run-tests.sh + - lcov --config-file .gitlab-ci/lcovrc --directory _build --capture --output-file "_coverage/${CI_JOB_NAME}.lcov" + artifacts: + reports: + junit: "_build/${CI_JOB_NAME}-report.xml" + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/config.h" + - "_build/glib/glibconfig.h" + - "_build/meson-logs" + - "_build/docs/reference/glib/glib-undeclared.txt" + - "_build/docs/reference/glib/glib-undocumented.txt" + - "_build/docs/reference/glib/glib-unused.txt" + - "_build/docs/reference/gobject/gobject-undeclared.txt" + - "_build/docs/reference/gobject/gobject-undocumented.txt" + - "_build/docs/reference/gobject/gobject-unused.txt" + - "_build/docs/reference/gio/gio-undeclared.txt" + - "_build/docs/reference/gio/gio-undocumented.txt" + - "_build/docs/reference/gio/gio-unused.txt" + - "_build/${CI_JOB_NAME}-report.xml" + - "_coverage" + +debian-stable-x86_64: + extends: .build + image: $DEBIAN_IMAGE + stage: build + script: + - meson ${MESON_COMMON_OPTIONS} + --werror + --default-library=both + --prefix=$HOME/glib-installed + --libdir=lib + -Dsystemtap=true + -Ddtrace=true + -Dfam=true + -Dinstalled_tests=true + _build + - ninja -C _build + - .gitlab-ci/run-tests.sh + artifacts: + reports: + junit: "_build/${CI_JOB_NAME}-report.xml" + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/config.h" + - "_build/glib/glibconfig.h" + - "_build/meson-logs" + - "_build/${CI_JOB_NAME}-report.xml" + +installed-tests: + extends: .build + image: $FEDORA_IMAGE + stage: build + script: + # dtrace is disabled because it breaks the static-link.py test + - meson ${MESON_COMMON_OPTIONS} + --werror + --prefix=/usr --libdir=/usr/lib64 + -Dfam=true + -Dinstalled_tests=true + -Ddefault_library=both + -Ddtrace=false + _build + - ninja -C _build + - sudo ninja -C _build install + - sudo chown -R `id -un`:`id -gn` _build/ + # FIXME Install newer xdg-desktop-portal with + # GMemoryMonitor support, see: + # https://github.com/flatpak/xdg-desktop-portal/pull/365 + - git clone --single-branch https://github.com/flatpak/xdg-desktop-portal.git + - cd xdg-desktop-portal + - git reset --hard 1.6.0 + - ./autogen.sh --prefix=/usr --libdir=/usr/lib64 --disable-libportal --disable-dependency-tracking + - make + - sudo make install + - cd .. + # FIXME install newer gobject-introspection + # with GMemoryMonitor support, see: + # https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/193 + - git clone --single-branch https://gitlab.gnome.org/GNOME/gobject-introspection.git + - cd gobject-introspection + - /usr/bin/meson _build --prefix=/usr --libdir=/usr/lib64 + - ninja -C _build + - sudo ninja -C _build install + - cd .. + # Work-around https://gitlab.gnome.org/GNOME/gnome-desktop-testing/merge_requests/2 + - mkdir -p _build/installed-tests-report/logs/ + - GLIB_TEST_COMPILATION=1 gnome-desktop-testing-runner + --report-directory=_build/installed-tests-report/failed/ + --log-directory=_build/installed-tests-report/logs/ + --parallel=0 + glib + artifacts: + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/config.h" + - "_build/glib/glibconfig.h" + - "_build/meson-logs" + - "_build/installed-tests-report/" + +G_DISABLE_ASSERT: + extends: .build + image: $FEDORA_IMAGE + stage: build + script: + - meson ${MESON_COMMON_OPTIONS} + --werror + -Dsystemtap=true + -Ddtrace=true + -Dfam=true + -Dinstalled_tests=true + -Dglib_assert=false + _build + - ninja -C _build + - bash -x ./.gitlab-ci/run-tests.sh + artifacts: + reports: + junit: "_build/${CI_JOB_NAME}-report.xml" + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/config.h" + - "_build/glib/glibconfig.h" + - "_build/meson-logs" + - "_build/${CI_JOB_NAME}-report.xml" + +valgrind: + extends: .build + image: $FEDORA_IMAGE + stage: analysis + variables: + MESON_TEST_TIMEOUT_MULTIPLIER: 10 + script: + - meson ${MESON_COMMON_OPTIONS} + --werror + -Dsystemtap=true + -Ddtrace=true + -Dfam=true + -Dinstalled_tests=true + _build + - ninja -C _build + - bash -x ./.gitlab-ci/run-tests.sh + --log-file _build/meson-logs/testlog-valgrind.json + --wrap "valgrind --tool=memcheck --error-exitcode=1 --track-origins=yes --leak-check=full --leak-resolution=high --num-callers=50 --show-leak-kinds=definite,possible --show-error-list=yes --suppressions=${CI_PROJECT_DIR}/glib.supp" + --no-suite no-valgrind + --no-suite slow + # FIXME: Remove this when we have zero valgrind leaks. + # https://gitlab.gnome.org/GNOME/glib/issues/333 + allow_failure: true + artifacts: + reports: + junit: "_build/${CI_JOB_NAME}-report.xml" + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/config.h" + - "_build/glib/glibconfig.h" + - "_build/meson-logs" + +.cross-template: &cross-template + extends: .build + stage: build + artifacts: + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/meson-logs" + +cross-android_api21_arm64: + <<: *cross-template + image: $ANDROID_IMAGE + script: + # FIXME: add --werror + # We use -Diconv=auto to test that we successfully detect that iconv is not + # provided by android api 21, and detect the external iconv instead. + - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_android_arm64_21.txt -Diconv=auto -Dinternal_pcre=true _build + - ninja -C _build + +cross-android_api28_arm64: + <<: *cross-template + image: $ANDROID_IMAGE + script: + # FIXME: add --werror + - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_android_arm64_28.txt -Dinternal_pcre=true _build + - ninja -C _build + +cross-mingw64: + <<: *cross-template + image: $MINGW_IMAGE + script: + # FIXME: Add --werror + - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_mingw64.txt _build + - ninja -C _build + +msys2-mingw32: + extends: .only-default + stage: build + tags: + - win32-ps + variables: + MSYSTEM: "MINGW32" + CHERE_INVOKING: "yes" + script: + - C:\msys64\usr\bin\pacman --noconfirm -Syyuu --ask 20 + - C:\msys64\usr\bin\bash .gitlab-ci/show-execution-environment.sh + - C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh" + artifacts: + reports: + junit: "_build/${env:CI_JOB_NAME}-report.xml" + name: "glib-${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}" + when: always + paths: + - _build/meson-logs + - "_build/${env:CI_JOB_NAME}-report.xml" + - _coverage/ + +vs2017-x64: + extends: .only-default + stage: build + tags: + - win32-ps + script: + - .gitlab-ci/test-msvc.bat + artifacts: + reports: + junit: "_build/${env:CI_JOB_NAME}-report.xml" + name: "glib-${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}" + when: always + paths: + - _build/meson-logs + - "_build/${env:CI_JOB_NAME}-report.xml" + +freebsd-11-x86_64: + stage: build + only: + - branches@GNOME/glib + tags: + # To run a FreeBSD builder, install gitlab-runner package and start both + # gitlab-runner and dbus service because we need /var/lib/dbus/machine-id. + # To compile GLib, you still have to install the following packages: + # desktop-file-utils gettext libiconv meson pkgconf python3 shared-mime-info + - freebsd-11 + variables: + # CPPFLAGS is required because libintl doesn't use pkg-config. + CPPFLAGS: -I/usr/local/include + # FIXME: Workaround meson inability to set LD_LIBRARY_PATH. + # https://github.com/mesonbuild/meson/issues/1383 + # https://github.com/mesonbuild/meson/issues/1635 + # https://github.com/mesonbuild/meson/issues/2881 + LDFLAGS: -L/usr/local/lib -Wl,--disable-new-dtags + # FreeBSD doesn't have C.UTF-8 locale. + LANG: en_US.UTF-8 + before_script: + - bash .gitlab-ci/show-execution-environment.sh + script: + # We cannot use -Wl,--no-undefined because GLib uses 'environ' variable. + # FreeBSD iconv doesn't handle transliteration, so we use (external) GNU libiconv here. + # FreeBSD supports xattr, but its API is different from Linux xattr. + # FIXME: extattr(2) support: https://gitlab.gnome.org/GNOME/glib/issues/1404 + - meson ${MESON_COMMON_OPTIONS} -Db_lundef=false -Diconv=external -Dxattr=false _build + - ninja -C _build + - bash -x ./.gitlab-ci/run-tests.sh + artifacts: + reports: + junit: "_build/${CI_JOB_NAME}-report.xml" + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/config.h" + - "_build/glib/glibconfig.h" + - "_build/meson-logs" + - "_build/${CI_JOB_NAME}-report.xml" + +freebsd-12-x86_64: + stage: build + only: + - branches@GNOME/glib + tags: + - freebsd-12 + variables: + CPPFLAGS: -I/usr/local/include + LDFLAGS: -L/usr/local/lib -Wl,--disable-new-dtags + LANG: en_US.UTF-8 + before_script: + - bash .gitlab-ci/show-execution-environment.sh + script: + - meson ${MESON_COMMON_OPTIONS} -Db_lundef=false -Diconv=external -Dxattr=false _build + - ninja -C _build + - bash -x ./.gitlab-ci/run-tests.sh + except: + - tags + artifacts: + reports: + junit: "_build/${CI_JOB_NAME}-report.xml" + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/config.h" + - "_build/glib/glibconfig.h" + - "_build/meson-logs" + - "_build/${CI_JOB_NAME}-report.xml" + +macos: + extends: .only-default + stage: build + only: + - branches@GNOME/glib + tags: + - macos + before_script: + - bash .gitlab-ci/show-execution-environment.sh + - pip3 install --user meson==0.49.2 + - pip3 install --user ninja + - export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH + script: + # FIXME: Add --werror + # FIXME: Use --wrap-mode=default so we download dependencies each time, + # until the macOS runner is a VM where we can use a pre-made image which + # already contains the dependencies. See: + # - https://gitlab.gnome.org/GNOME/glib/merge_requests/388 + # - https://gitlab.gnome.org/Infrastructure/Infrastructure/issues/225 + - meson ${MESON_COMMON_OPTIONS} + --wrap-mode=default + _build + - ninja -C _build + # FIXME: Multiple unit tests currently fails + - .gitlab-ci/run-tests.sh || true + artifacts: + reports: + junit: "_build/${CI_JOB_NAME}-report.xml" + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/config.h" + - "_build/glib/glibconfig.h" + - "_build/meson-logs" + - "_build/${CI_JOB_NAME}-report.xml" + +coverage: + extends: .only-default + image: $FEDORA_IMAGE + stage: coverage + artifacts: + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + paths: + - _coverage/ + before_script: + - bash .gitlab-ci/show-execution-environment.sh + script: + - bash -x ./.gitlab-ci/coverage-docker.sh + coverage: '/^\s+lines\.+:\s+([\d.]+\%)\s+/' + +scan-build: + extends: .build + image: $FEDORA_IMAGE + stage: analysis + script: + - meson ${MESON_COMMON_OPTIONS} + --werror + --default-library=both + --prefix=$HOME/glib-installed + --libdir=lib + -Dsystemtap=true + -Ddtrace=true + -Dfam=true + -Dinstalled_tests=true + _scan_build + - ninja -C _scan_build scan-build + artifacts: + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_scan_build/meson-logs/scanbuild" + +pages: + stage: deploy + only: + - master + script: + - mv _coverage/ public/ + artifacts: + paths: + - public + +dist-job: + image: $FEDORA_IMAGE + stage: build + only: + - tags + script: + # FIXME: Cannot use --fatal-meson-warnings here because meson warns about gtkdoc + # feature introduced in 0.52 but we only depends on 0.49. + - meson ${MESON_COMMON_OPTIONS_NO_WARNING} --buildtype release -Dgtk_doc=true -Dman=true _build + - cd _build + - ninja dist + - ninja glib-doc gobject-doc gio-doc + - tar -c -J -f "glib-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/glib html + - tar -c -J -f "gobject-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/gobject html + - tar -c -J -f "gio-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/gio html + artifacts: + paths: + - "${CI_PROJECT_DIR}/_build/glib-docs-$CI_COMMIT_TAG.tar.xz" + - "${CI_PROJECT_DIR}/_build/gobject-docs-$CI_COMMIT_TAG.tar.xz" + - "${CI_PROJECT_DIR}/_build/gio-docs-$CI_COMMIT_TAG.tar.xz" + - "${CI_PROJECT_DIR}/_build/meson-dist/glib-*.tar.xz"
diff --git a/.gitlab-ci/README.md b/.gitlab-ci/README.md new file mode 100644 index 0000000..f56cbbd --- /dev/null +++ b/.gitlab-ci/README.md
@@ -0,0 +1,23 @@ +# CI support stuff + +## Docker image + +GitLab CI jobs run in a Docker image, defined here. To update that image +(perhaps to install some more packages): + +1. Edit `.gitlab-ci/Dockerfile` with the changes you want +1. Run `.gitlab-ci/run-docker.sh build --base=debian-stable --base-version=1` to + build the new image (bump the version from the latest listed for that `base` + on https://gitlab.gnome.org/GNOME/glib/container_registry) +1. Run `.gitlab-ci/run-docker.sh push --base=debian-stable --base-version=1` to + upload the new image to the GNOME GitLab Docker registry + * If this is the first time you're doing this, you'll need to log into the + registry + * If you use 2-factor authentication on your GNOME GitLab account, you'll + need to [create a personal access token][pat] and use that rather than + your normal password — the token should have `read_registry` and + `write_registry` permissions +1. Edit `.gitlab-ci.yml` (in the root of this repository) to use your new + image + +[pat]: https://gitlab.gnome.org/profile/personal_access_tokens
diff --git a/.gitlab-ci/android-download-ndk.sh b/.gitlab-ci/android-download-ndk.sh new file mode 100755 index 0000000..7739e39 --- /dev/null +++ b/.gitlab-ci/android-download-ndk.sh
@@ -0,0 +1,31 @@ +#!/bin/bash + +# +# Copyright 2018 Collabora ltd. +# +# 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 2.1 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 +# Lesser 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 <http://www.gnu.org/licenses/>. +# +# Author: Xavier Claessens <xavier.claessens@collabora.com> +# + +set -e + +# Download Android NDK +ANDROID_NDK_VERSION="r17b" +ANDROID_NDK_SHA512="062fac12f747730f5563995089a8b4abab683fbbc621aa8582fdf35fe327daee5d69ed2437af257c10ec4ef54ecd3805a8f134a1400eb8f34ee76f55c8dc9ae9" +wget --quiet "https://dl.google.com/android/repository/android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip" +echo "${ANDROID_NDK_SHA512} android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip" | sha512sum -c +unzip "android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip" +rm "android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip" +mv "android-ndk-${ANDROID_NDK_VERSION}" "${ANDROID_NDK_PATH}"
diff --git a/.gitlab-ci/android-ndk.Dockerfile b/.gitlab-ci/android-ndk.Dockerfile new file mode 100644 index 0000000..56b186c --- /dev/null +++ b/.gitlab-ci/android-ndk.Dockerfile
@@ -0,0 +1,78 @@ +FROM fedora:28 + +RUN dnf -y install \ + autoconf \ + automake \ + bindfs \ + clang \ + clang-analyzer \ + desktop-file-utils \ + elfutils-libelf-devel \ + findutils \ + fuse \ + gamin-devel \ + gcc \ + gcc-c++ \ + gettext \ + git \ + glibc-devel \ + glibc-headers \ + glibc-langpack-de \ + glibc-langpack-el \ + glibc-langpack-el \ + glibc-langpack-en \ + glibc-langpack-es \ + glibc-langpack-es \ + glibc-langpack-fa \ + glibc-langpack-fr \ + glibc-langpack-hr \ + glibc-langpack-ja \ + glibc-langpack-lt \ + glibc-langpack-pl \ + glibc-langpack-ru \ + glibc-langpack-tr \ + gtk-doc \ + itstool \ + lcov \ + libattr-devel \ + libffi-devel \ + libmount-devel \ + libselinux-devel \ + libtool \ + libxslt \ + make \ + ncurses-compat-libs \ + ninja-build \ + pcre-devel \ + python3 \ + python3-pip \ + python3-wheel \ + systemtap-sdt-devel \ + unzip \ + wget \ + xz \ + zlib-devel \ + && dnf clean all + +WORKDIR /opt +ENV ANDROID_NDK_PATH /opt/android-ndk +COPY android-download-ndk.sh . +RUN ./android-download-ndk.sh +COPY android-setup-env.sh . +RUN ./android-setup-env.sh arm64 21 +RUN ./android-setup-env.sh arm64 28 +RUN rm -rf $ANDROID_NDK_PATH + +RUN pip3 install meson==0.49.2 + +ARG HOST_USER_ID=5555 +ENV HOST_USER_ID ${HOST_USER_ID} +RUN useradd -u $HOST_USER_ID -ms /bin/bash user + +USER user +WORKDIR /home/user + +COPY cache-subprojects.sh . +RUN ./cache-subprojects.sh + +ENV LANG C.UTF-8
diff --git a/.gitlab-ci/android-setup-env.sh b/.gitlab-ci/android-setup-env.sh new file mode 100755 index 0000000..42620cc --- /dev/null +++ b/.gitlab-ci/android-setup-env.sh
@@ -0,0 +1,102 @@ +#!/bin/bash + +# +# Copyright 2018 Collabora ltd. +# +# 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 2.1 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 +# Lesser 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 <http://www.gnu.org/licenses/>. +# +# Author: Xavier Claessens <xavier.claessens@collabora.com> +# + +set -e + +arch=$1 +api=$2 +toolchain_path=$(pwd)/android-toolchain-$arch-$api +prefix_path=$(pwd)/android-$arch-$api + +# Create standalone toolchains +"${ANDROID_NDK_PATH}/build/tools/make_standalone_toolchain.py" --arch "${arch}" --api "${api}" --install-dir "${toolchain_path}" + +target_host=aarch64-linux-android +export AR=$target_host-ar +export AS=$target_host-clang +export CC=$target_host-clang +export CXX=$target_host-clang++ +export LD=$target_host-ld +export STRIP=$target_host-strip +export PATH=$PATH:$toolchain_path/bin + +# Cross build libiconv when using API level <= 28. +# Newer Android has it in its libc already. +if [ "$api" -lt "28" ]; then + wget --quiet http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz + echo "1233fe3ca09341b53354fd4bfe342a7589181145a1232c9919583a8c9979636855839049f3406f253a9d9829908816bb71fd6d34dd544ba290d6f04251376b1a libiconv-1.15.tar.gz" | sha512sum -c + tar xzf libiconv-1.15.tar.gz + pushd libiconv-1.15 + ./configure --host="${target_host}" --prefix="${prefix_path}" --libdir="${prefix_path}/lib64" + make + make install + popd + rm libiconv-1.15.tar.gz + rm -r libiconv-1.15 +fi + +# Cross build libffi +wget --quiet https://github.com/libffi/libffi/releases/download/v3.3-rc0/libffi-3.3-rc0.tar.gz +echo "e6e695d32cd6eb7d65983f32986fccdfc786a593d2ea18af30ce741f58cfa1eb264b1a8d09df5084cb916001aea15187b005c2149a0620a44397a4453b6137d4 libffi-3.3-rc0.tar.gz" | sha512sum -c +tar xzf libffi-3.3-rc0.tar.gz +pushd libffi-3.3-rc0 +./configure --host="${target_host}" --prefix="${prefix_path}" --libdir="${prefix_path}/lib64" +make +make install +popd +rm libffi-3.3-rc0.tar.gz +rm -r libffi-3.3-rc0 + +# Create a pkg-config wrapper that won't pick fedora libraries +mkdir -p "${prefix_path}/bin" +export PKG_CONFIG=$prefix_path/bin/pkg-config +cat > "${PKG_CONFIG}" <<- EOM +#!/bin/sh +SYSROOT=${prefix_path} +export PKG_CONFIG_DIR= +export PKG_CONFIG_LIBDIR=\${SYSROOT}/lib64/pkgconfig +export PKG_CONFIG_SYSROOT_DIR=\${SYSROOT} +exec pkg-config "\$@" +EOM +chmod +x "${PKG_CONFIG}" + +# Create a cross file that can be passed to meson +cat > "cross_file_android_${arch}_${api}.txt" <<- EOM +[host_machine] +system = 'android' +cpu_family = 'aarch64' +cpu = 'aarch64' +endian = 'little' + +[properties] +c_args = ['-I${prefix_path}/include'] +c_link_args = ['-L${prefix_path}/lib64', + '-fuse-ld=gold'] +growing_stack = true + +[binaries] +c = '${toolchain_path}/bin/${CC}' +cpp = '${toolchain_path}/bin/${CXX}' +ar = '${toolchain_path}/bin/${AR}' +ld = '${toolchain_path}/bin/${LD}' +strip = '${toolchain_path}/bin/${STRIP}' +pkgconfig = '${PKG_CONFIG}' +EOM
diff --git a/.gitlab-ci/cache-subprojects.sh b/.gitlab-ci/cache-subprojects.sh new file mode 100755 index 0000000..421631e --- /dev/null +++ b/.gitlab-ci/cache-subprojects.sh
@@ -0,0 +1,9 @@ +#!/bin/bash + +set -e + +git clone https://gitlab.gnome.org/GNOME/glib.git +meson subprojects download --sourcedir glib +rm glib/subprojects/*.wrap +mv glib/subprojects/ . +rm -rf glib
diff --git a/.gitlab-ci/check-todos.py b/.gitlab-ci/check-todos.py new file mode 100755 index 0000000..83b3eee --- /dev/null +++ b/.gitlab-ci/check-todos.py
@@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# +# Copyright © 2019 Endless Mobile, Inc. +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Original author: Philip Withnall + +""" +Checks that a merge request doesn’t add any instances of the string ‘todo’ +(in uppercase), or similar keywords. It may remove instances of that keyword, +or move them around, according to the logic of `git log -S`. +""" + +import argparse +import re +import subprocess +import sys + + +# We have to specify these keywords obscurely to avoid the script matching +# itself. The keyword ‘fixme’ (in upper case) is explicitly allowed because +# that’s conventionally used as a way of marking a workaround which needs to +# be merged for now, but is to be grepped for and reverted or reworked later. +BANNED_KEYWORDS = [ + 'TO' + 'DO', + 'X' + 'XX', + 'W' + 'IP', +] + + +def main(): + parser = argparse.ArgumentParser( + description='Check a range of commits to ensure they don’t contain ' + 'banned keywords.') + parser.add_argument('commits', + help='SHA to diff from, or range of commits to diff') + args = parser.parse_args() + + banned_words_seen = set() + seen_in_log = False + seen_in_diff = False + + # Check the log messages for banned words. + log_process = subprocess.run( + ['git', 'log', '--no-color', args.commits + '..HEAD'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', + check=True) + log_lines = log_process.stdout.strip().split('\n') + + for line in log_lines: + for keyword in BANNED_KEYWORDS: + if re.search('(^|\W+){}(\W+|$)'.format(keyword), line): + banned_words_seen.add(keyword) + seen_in_log = True + + # Check the diff for banned words. + diff_process = subprocess.run( + ['git', 'diff', '-U0', '--no-color', args.commits], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', + check=True) + diff_lines = diff_process.stdout.strip().split('\n') + + for line in diff_lines: + if not line.startswith('+ '): + continue + + for keyword in BANNED_KEYWORDS: + if re.search('(^|\W+){}(\W+|$)'.format(keyword), line): + banned_words_seen.add(keyword) + seen_in_diff = True + + if banned_words_seen: + if seen_in_log and seen_in_diff: + where = 'commit message and diff' + elif seen_in_log: + where = 'commit message' + elif seen_in_diff: + where = 'commit diff' + + print('Saw banned keywords in a {}: {}. ' + 'This indicates the branch is a work in progress and should not ' + 'be merged in its current ' + 'form.'.format(where, ', '.join(banned_words_seen))) + sys.exit(1) + + +if __name__ == '__main__': + main()
diff --git a/.gitlab-ci/coverage-docker.sh b/.gitlab-ci/coverage-docker.sh new file mode 100755 index 0000000..bf79561 --- /dev/null +++ b/.gitlab-ci/coverage-docker.sh
@@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# Fixup Windows paths +python3 ./.gitlab-ci/fixup-cov-paths.py _coverage/*.lcov + +for path in _coverage/*.lcov; do + # Remove coverage from generated code in the build directory + lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*/_build/*' -o "$(pwd)/${path}" + # Remove any coverage from system files + lcov --config-file .gitlab-ci/lcovrc -e "${path}" "$(pwd)/*" -o "$(pwd)/${path}" +done + +genhtml \ + --ignore-errors=source \ + --config-file .gitlab-ci/lcovrc \ + _coverage/*.lcov \ + -o _coverage/coverage + +cd _coverage +rm -f ./*.lcov + +cat >index.html <<EOL +<html> +<body> +<ul> +<li><a href="coverage/index.html">Coverage</a></li> +</ul> +</body> +</html> +EOL
diff --git a/.gitlab-ci/cross_file_ios_example.txt b/.gitlab-ci/cross_file_ios_example.txt new file mode 100644 index 0000000..0afeef0 --- /dev/null +++ b/.gitlab-ci/cross_file_ios_example.txt
@@ -0,0 +1,25 @@ +[host_machine] +system = 'darwin' +cpu_family = 'aarch64' +cpu = 'arm64' +endian = 'little' + +[properties] +c_args = ['-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk', '-miphoneos-version-min=11.0'] +cpp_args = ['-stdlib=libc++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk', '-miphoneos-version-min=11.0'] +objc_args = ['-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk', '-miphoneos-version-min=11.0'] +objcpp_args = ['-stdlib=libc++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk', '-miphoneos-version-min=11.0'] +c_link_args = ['-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk', '-Wl,-iphoneos_version_min,11.0'] +cpp_link_args = ['-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk', '-Wl,-iphoneos_version_min,11.0'] +objc_link_args = ['-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk', '-Wl,-iphoneos_version_min,11.0'] +objcpp_link_args = ['-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk', '-Wl,-iphoneos_version_min,11.0'] +growing_stack = true + + +[binaries] +c = ['clang'] +cpp = ['clang++'] +objc = ['clang'] +objcpp = ['clang++'] +ar = ['ar'] +strip = ['strip']
diff --git a/.gitlab-ci/cross_file_mingw64.txt b/.gitlab-ci/cross_file_mingw64.txt new file mode 100644 index 0000000..7c9176b --- /dev/null +++ b/.gitlab-ci/cross_file_mingw64.txt
@@ -0,0 +1,19 @@ +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[properties] +c_args = [] +c_link_args = [] + +[binaries] +c = 'x86_64-w64-mingw32-gcc' +cpp = 'x86_64-w64-mingw32-g++' +ar = 'x86_64-w64-mingw32-ar' +ld = 'x86_64-w64-mingw32-ld' +objcopy = 'x86_64-w64-mingw32-objcopy' +strip = 'x86_64-w64-mingw32-strip' +pkgconfig = 'x86_64-w64-mingw32-pkg-config' +windres = 'x86_64-w64-mingw32-windres'
diff --git a/.gitlab-ci/debian-stable.Dockerfile b/.gitlab-ci/debian-stable.Dockerfile new file mode 100644 index 0000000..54d2d8c --- /dev/null +++ b/.gitlab-ci/debian-stable.Dockerfile
@@ -0,0 +1,78 @@ +FROM debian:buster + +RUN apt-get update -qq && apt-get install --no-install-recommends -qq -y \ + bindfs \ + clang \ + clang-tools-7 \ + clang-format-7 \ + dbus \ + desktop-file-utils \ + elfutils \ + findutils \ + fuse \ + gcc \ + g++ \ + gettext \ + git \ + libc6-dev \ + gtk-doc-tools \ + itstool \ + lcov \ + libattr1-dev \ + libdbus-1-dev \ + libelf-dev \ + libffi-dev \ + libgamin-dev \ + libmount-dev \ + libpcre2-dev \ + libselinux1-dev \ + libxml2-utils \ + libxslt1-dev \ + libz3-dev \ + locales \ + ninja-build \ + python3 \ + python3-pip \ + python3-setuptools \ + python3-wheel \ + shared-mime-info \ + systemtap-sdt-dev \ + unzip \ + wget \ + xsltproc \ + xz-utils \ + zlib1g-dev \ + && rm -rf /usr/share/doc/* /usr/share/man/* + +# Locale for our build +RUN locale-gen C.UTF-8 && /usr/sbin/update-locale LANG=C.UTF-8 + +# Locales for our tests +RUN locale-gen de_DE.UTF-8 \ + && locale-gen el_GR.UTF-8 \ + && locale-gen en_US.UTF-8 \ + && locale-gen es_ES.UTF-8 \ + && locale-gen fa_IR.UTF-8 \ + && locale-gen fr_FR.UTF-8 \ + && locale-gen hr_HR.UTF-8 \ + && locale-gen ja_JP.UTF-8 \ + && locale-gen lt_LT.UTF-8 \ + && locale-gen pl_PL.UTF-8 \ + && locale-gen ru_RU.UTF-8 \ + && locale-gen tr_TR.UTF-8 + +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +RUN pip3 install meson==0.49.2 + +ARG HOST_USER_ID=5555 +ENV HOST_USER_ID ${HOST_USER_ID} +RUN useradd -u $HOST_USER_ID -ms /bin/bash user + +USER user +WORKDIR /home/user + +COPY cache-subprojects.sh . +RUN ./cache-subprojects.sh + +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8
diff --git a/.gitlab-ci/fedora.Dockerfile b/.gitlab-ci/fedora.Dockerfile new file mode 100644 index 0000000..39553e2 --- /dev/null +++ b/.gitlab-ci/fedora.Dockerfile
@@ -0,0 +1,92 @@ +FROM fedora:31 + +RUN dnf -y update \ + && dnf -y install \ + bindfs \ + clang \ + clang-analyzer \ + dbus-daemon \ + dbus-devel \ + desktop-file-utils \ + elfutils-libelf-devel \ + findutils \ + fuse \ + gamin-devel \ + gcc \ + gcc-c++ \ + gettext \ + git \ + glibc-devel \ + glibc-headers \ + glibc-langpack-de \ + glibc-langpack-el \ + glibc-langpack-el \ + glibc-langpack-en \ + glibc-langpack-es \ + glibc-langpack-es \ + glibc-langpack-fa \ + glibc-langpack-fr \ + glibc-langpack-hr \ + glibc-langpack-ja \ + glibc-langpack-lt \ + glibc-langpack-pl \ + glibc-langpack-ru \ + glibc-langpack-tr \ + "gnome-desktop-testing >= 2018.1" \ + gtk-doc \ + itstool \ + lcov \ + libattr-devel \ + libffi-devel \ + libmount-devel \ + libselinux-devel \ + libxslt \ + ncurses-compat-libs \ + ninja-build \ + pcre-devel \ + "python3-dbusmock >= 0.18.3-2" \ + python3-pip \ + python3-pygments \ + python3-wheel \ + shared-mime-info \ + systemtap-sdt-devel \ + unzip \ + valgrind \ + wget \ + xdg-desktop-portal \ + xz \ + zlib-devel \ + && dnf -y install \ + meson \ + flex \ + bison \ + python3-devel \ + autoconf \ + automake \ + gettext-devel \ + libtool \ + diffutils \ + fontconfig-devel \ + json-glib-devel \ + geoclue2-devel \ + pipewire-devel \ + fuse-devel \ + make \ + && dnf clean all + +RUN pip3 install meson==0.52.1 + +# Enable sudo for wheel users +RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers + +ARG HOST_USER_ID=5555 +ENV HOST_USER_ID ${HOST_USER_ID} +RUN useradd -u $HOST_USER_ID -G wheel -ms /bin/bash user + +USER user +WORKDIR /home/user + +COPY cache-subprojects.sh . +RUN ./cache-subprojects.sh + +ENV LANG C.UTF-8
diff --git a/.gitlab-ci/fixup-cov-paths.py b/.gitlab-ci/fixup-cov-paths.py new file mode 100644 index 0000000..d614b60 --- /dev/null +++ b/.gitlab-ci/fixup-cov-paths.py
@@ -0,0 +1,29 @@ +import sys +import os +import io + + +def main(argv): + # Fix paths in lcov files generated on a Windows host so they match our + # current source layout. + paths = argv[1:] + + for path in paths: + print("cov-fixup:", path) + text = io.open(path, "r", encoding="utf-8").read() + text = text.replace("\\\\", "/") + glib_dir = "/glib/" + end = text.index(glib_dir) + start = text[:end].rindex(":") + 1 + old_root = text[start:end] + assert os.path.basename(os.getcwd()) == "glib" + new_root = os.path.dirname(os.getcwd()) + if old_root != new_root: + print("replacing %r with %r" % (old_root, new_root)) + text = text.replace(old_root, new_root) + with io.open(path, "w", encoding="utf-8") as h: + h.write(text) + + +if __name__ == "__main__": + sys.exit(main(sys.argv))
diff --git a/.gitlab-ci/lcovrc b/.gitlab-ci/lcovrc new file mode 100644 index 0000000..3901f81 --- /dev/null +++ b/.gitlab-ci/lcovrc
@@ -0,0 +1,13 @@ +# lcov and genhtml configuration +# See http://ltp.sourceforge.net/coverage/lcov/lcovrc.5.php + +# Always enable branch coverage +lcov_branch_coverage = 1 + +# Exclude precondition assertions, as we can never reasonably get full branch +# coverage of them, as they should never normally fail. +# See https://github.com/linux-test-project/lcov/issues/44 +lcov_excl_br_line = LCOV_EXCL_BR_LINE|g_return_if_fail|g_return_val_if_fail|g_assert|g_assert_ + +# Similarly for unreachable assertions. +lcov_excl_line = LCOV_EXCL_LINE|g_return_if_reached|g_return_val_if_reached|g_assert_not_reached \ No newline at end of file
diff --git a/.gitlab-ci/meson-junit-report.py b/.gitlab-ci/meson-junit-report.py new file mode 100755 index 0000000..90939ff --- /dev/null +++ b/.gitlab-ci/meson-junit-report.py
@@ -0,0 +1,115 @@ +#!/usr/bin/env python3 + +# Turns a Meson testlog.json file into a JUnit XML report +# +# Copyright 2019 GNOME Foundation +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Original author: Emmanuele Bassi + +import argparse +import datetime +import json +import os +import sys +import xml.etree.ElementTree as ET + +aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUnit report') +aparser.add_argument('--project-name', metavar='NAME', + help='The project name', + default='unknown') +aparser.add_argument('--job-id', metavar='ID', + help='The job ID for the report', + default='Unknown') +aparser.add_argument('--branch', metavar='NAME', + help='Branch of the project being tested', + default='master') +aparser.add_argument('--output', metavar='FILE', + help='The output file, stdout by default', + type=argparse.FileType('w', encoding='UTF-8'), + default=sys.stdout) +aparser.add_argument('infile', metavar='FILE', + help='The input testlog.json, stdin by default', + type=argparse.FileType('r', encoding='UTF-8'), + default=sys.stdin) + +args = aparser.parse_args() + +outfile = args.output + +testsuites = ET.Element('testsuites') +testsuites.set('id', '{}/{}'.format(args.job_id, args.branch)) +testsuites.set('package', args.project_name) +testsuites.set('timestamp', datetime.datetime.utcnow().isoformat()) + +suites = {} +for line in args.infile: + data = json.loads(line) + (full_suite, unit_name) = data['name'].split(' / ') + try: + (project_name, suite_name) = full_suite.split(':') + except ValueError: + project_name = full_suite + suite_name = full_suite + + duration = data['duration'] + return_code = data['returncode'] + log = data['stdout'] + log_stderr = data.get('stderr', '') + + unit = { + 'suite': suite_name, + 'name': unit_name, + 'duration': duration, + 'returncode': return_code, + 'stdout': log, + 'stderr': log_stderr, + } + + units = suites.setdefault(suite_name, []) + units.append(unit) + +for name, units in suites.items(): + print('Processing suite {} (units: {})'.format(name, len(units))) + + def if_failed(unit): + if unit['returncode'] != 0: + return True + return False + + def if_succeded(unit): + if unit['returncode'] == 0: + return True + return False + + successes = list(filter(if_succeded, units)) + failures = list(filter(if_failed, units)) + print(' - {}: {} pass, {} fail'.format(name, len(successes), len(failures))) + + testsuite = ET.SubElement(testsuites, 'testsuite') + testsuite.set('name', '{}/{}'.format(args.project_name, name)) + testsuite.set('tests', str(len(units))) + testsuite.set('errors', str(len(failures))) + testsuite.set('failures', str(len(failures))) + + for unit in successes: + testcase = ET.SubElement(testsuite, 'testcase') + testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite'])) + testcase.set('name', unit['name']) + testcase.set('time', str(unit['duration'])) + + for unit in failures: + testcase = ET.SubElement(testsuite, 'testcase') + testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite'])) + testcase.set('name', unit['name']) + testcase.set('time', str(unit['duration'])) + + failure = ET.SubElement(testcase, 'failure') + failure.set('classname', '{}/{}'.format(args.project_name, unit['suite'])) + failure.set('name', unit['name']) + failure.set('type', 'error') + failure.text = unit['stdout'] + '\n' + unit['stderr'] + +output = ET.tostring(testsuites, encoding='unicode') +outfile.write(output)
diff --git a/.gitlab-ci/mingw.Dockerfile b/.gitlab-ci/mingw.Dockerfile new file mode 100644 index 0000000..d89de8c --- /dev/null +++ b/.gitlab-ci/mingw.Dockerfile
@@ -0,0 +1,73 @@ +FROM fedora:29 + +RUN dnf -y install \ + bindfs \ + clang \ + clang-analyzer \ + desktop-file-utils \ + elfutils-libelf-devel \ + findutils \ + fuse \ + gamin-devel \ + gcc \ + gcc-c++ \ + gettext \ + git \ + glibc-devel \ + glibc-headers \ + glibc-langpack-de \ + glibc-langpack-el \ + glibc-langpack-el \ + glibc-langpack-en \ + glibc-langpack-es \ + glibc-langpack-es \ + glibc-langpack-fa \ + glibc-langpack-fr \ + glibc-langpack-hr \ + glibc-langpack-ja \ + glibc-langpack-lt \ + glibc-langpack-pl \ + glibc-langpack-ru \ + glibc-langpack-tr \ + gtk-doc \ + itstool \ + lcov \ + libattr-devel \ + libffi-devel \ + libmount-devel \ + libselinux-devel \ + libxslt \ + mingw64-gcc \ + mingw64-gcc-c++ \ + mingw64-gettext \ + mingw64-libffi \ + mingw64-zlib \ + ncurses-compat-libs \ + ninja-build \ + pcre-devel \ + python3 \ + python3-pip \ + python3-wheel \ + systemtap-sdt-devel \ + unzip \ + wget \ + xz \ + zlib-devel \ + && dnf clean all + +WORKDIR /opt +COPY cross_file_mingw64.txt /opt + +RUN pip3 install meson==0.49.2 + +ARG HOST_USER_ID=5555 +ENV HOST_USER_ID ${HOST_USER_ID} +RUN useradd -u $HOST_USER_ID -ms /bin/bash user + +USER user +WORKDIR /home/user + +COPY cache-subprojects.sh . +RUN ./cache-subprojects.sh + +ENV LANG C.UTF-8
diff --git a/.gitlab-ci/run-check-todos.sh b/.gitlab-ci/run-check-todos.sh new file mode 100755 index 0000000..8af1027 --- /dev/null +++ b/.gitlab-ci/run-check-todos.sh
@@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +# We need to add a new remote for the upstream target branch, since this script +# could be running in a personal fork of the repository which has out of date +# branches. +git remote add upstream https://gitlab.gnome.org/GNOME/glib.git +git fetch upstream + +# Work out the newest common ancestor between the detached HEAD that this CI job +# has checked out, and the upstream target branch (which will typically be +# `upstream/master` or `upstream/glib-2-62`). +# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if we’re running in +# a merge request pipeline; fall back to `${CI_DEFAULT_BRANCH}` otherwise. +newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "upstream/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent HEAD) | head -1) +./.gitlab-ci/check-todos.py "${newest_common_ancestor_sha}"
diff --git a/.gitlab-ci/run-docker.sh b/.gitlab-ci/run-docker.sh new file mode 100755 index 0000000..9b6fce4 --- /dev/null +++ b/.gitlab-ci/run-docker.sh
@@ -0,0 +1,132 @@ +#!/bin/bash + +read_arg() { + # $1 = arg name + # $2 = arg value + # $3 = arg parameter + local rematch='^[^=]*=(.*)$' + if [[ $2 =~ $rematch ]]; then + read -r "$1" <<< "${BASH_REMATCH[1]}" + else + read -r "$1" <<< "$3" + # There is no way to shift our callers args, so + # return 1 to indicate they should do it instead. + return 1 + fi +} + +SUDO_CMD="sudo" +if docker -v |& grep -q podman; then + # Using podman + SUDO_CMD="" + # Docker is actually implemented by podman, and its OCI output + # is incompatible with some of the dockerd instances on GitLab + # CI runners. + export BUILDAH_FORMAT=docker +fi + +set -e + +base="" +base_version="" +build=0 +run=0 +push=0 +list=0 +print_help=0 +no_login=0 + +while (($# > 0)); do + case "${1%%=*}" in + build) build=1;; + run) run=1;; + push) push=1;; + list) list=1;; + help) print_help=1;; + --base|-b) read_arg base "$@" || shift;; + --base-version) read_arg base_version "$@" || shift;; + --no-login) no_login=1;; + *) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;; + esac + shift +done + +if [ $print_help == 1 ]; then + echo "$0 - Build and run Docker images" + echo "" + echo "Usage: $0 <command> [options] [basename]" + echo "" + echo "Available commands" + echo "" + echo " build --base=<BASENAME> - Build Docker image <BASENAME>.Dockerfile" + echo " run --base=<BASENAME> - Run Docker image <BASENAME>" + echo " push --base=<BASENAME> - Push Docker image <BASENAME> to the registry" + echo " list - List available images" + echo " help - This help message" + echo "" + exit 0 +fi + +cd "$(dirname "$0")" + +if [ $list == 1 ]; then + echo "Available Docker images:" + for f in *.Dockerfile; do + filename=$( basename -- "$f" ) + basename="${filename%.*}" + + echo -e " \e[1;39m$basename\e[0m" + done + exit 0 +fi + +# All commands after this require --base to be set +if [ -z "${base}" ]; then + echo "Usage: $0 <command>" + exit 1 +fi + +if [ ! -f "$base.Dockerfile" ]; then + echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found" + exit 1 +fi + +if [ -z "${base_version}" ]; then + base_version="latest" +else + base_version="v$base_version" +fi + +TAG="registry.gitlab.gnome.org/gnome/glib/${base}:${base_version}" + +if [ $build == 1 ]; then + echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}" + $SUDO_CMD docker build \ + --build-arg HOST_USER_ID="$UID" \ + --tag "${TAG}" \ + --file "${base}.Dockerfile" . + exit $? +fi + +if [ $push == 1 ]; then + echo -e "\e[1;32mPUSHING\e[0m: ${base} as ${TAG}" + + if [ $no_login == 0 ]; then + $SUDO_CMD docker login registry.gitlab.gnome.org + fi + + $SUDO_CMD docker push $TAG + exit $? +fi + +if [ $run == 1 ]; then + echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}" + $SUDO_CMD docker run \ + --rm \ + --volume "$(pwd)/..:/home/user/app" \ + --workdir "/home/user/app" \ + --tty \ + --interactive "${TAG}" \ + bash + exit $? +fi
diff --git a/.gitlab-ci/run-style-check-diff.sh b/.gitlab-ci/run-style-check-diff.sh new file mode 100755 index 0000000..1f7b8c1 --- /dev/null +++ b/.gitlab-ci/run-style-check-diff.sh
@@ -0,0 +1,40 @@ +#!/bin/bash + +set -e + +# Wrap everything in a subshell so we can propagate the exit status. +( + +# We need to add a new remote for the upstream target branch, since this script +# could be running in a personal fork of the repository which has out of date +# branches. +git remote add upstream https://gitlab.gnome.org/GNOME/glib.git +git fetch upstream + +# Work out the newest common ancestor between the detached HEAD that this CI job +# has checked out, and the upstream target branch (which will typically be +# `upstream/master` or `upstream/glib-2-62`). +# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if we’re running in +# a merge request pipeline; fall back to `${CI_DEFAULT_BRANCH}` otherwise. +newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "upstream/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent HEAD) | head -1) +git diff -U0 --no-color "${newest_common_ancestor_sha}" | ./clang-format-diff.py -binary "clang-format-7" -p1 + +) +exit_status=$? + +# The style check is not infallible. The clang-format configuration cannot +# perfectly describe GLib’s coding style: in particular, it cannot align +# function arguments. The documented coding style for GLib takes priority over +# clang-format suggestions. Hopefully we can eventually improve clang-format to +# be configurable enough for our coding style. That’s why this CI check is OK +# to fail: the idea is that people can look through the output and ignore it if +# it’s wrong. (That situation can also happen if someone touches pre-existing +# badly formatted code and it doesn’t make sense to tidy up the wider coding +# style with the changes they’re making.) +echo "" +echo "Note that clang-format output is advisory and cannot always match the GLib coding style, documented at" +echo " https://gitlab.gnome.org/GNOME/gtk/blob/master/docs/CODING-STYLE" +echo "Warnings from this tool can be ignored in favour of the documented coding style," +echo "or in favour of matching the style of existing surrounding code." + +exit ${exit_status}
diff --git a/.gitlab-ci/run-tests.sh b/.gitlab-ci/run-tests.sh new file mode 100755 index 0000000..b545a6f --- /dev/null +++ b/.gitlab-ci/run-tests.sh
@@ -0,0 +1,29 @@ +#!/bin/bash + +set +e + +case "$1" in + --log-file) + log_file="$2" + shift + shift + ;; + *) + log_file="_build/meson-logs/testlog.json" +esac + +meson test \ + -C _build \ + --timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \ + --no-suite flaky \ + "$@" + +exit_code=$? + +python3 .gitlab-ci/meson-junit-report.py \ + --project-name=glib \ + --job-id "${CI_JOB_NAME}" \ + --output "_build/${CI_JOB_NAME}-report.xml" \ + "${log_file}" + +exit $exit_code
diff --git a/.gitlab-ci/show-execution-environment.sh b/.gitlab-ci/show-execution-environment.sh new file mode 100755 index 0000000..0c22651 --- /dev/null +++ b/.gitlab-ci/show-execution-environment.sh
@@ -0,0 +1,11 @@ +#!/bin/bash + +set -eux -o pipefail + +id || : +capsh --print || : +env -0 | sort -z | perl -pe 's/\0/\n/g' || : +setpriv --dump || : +ulimit -a || : +cat /proc/self/status || : +cat /proc/self/mountinfo || :
diff --git a/.gitlab-ci/test-msvc.bat b/.gitlab-ci/test-msvc.bat new file mode 100644 index 0000000..6cc6d80 --- /dev/null +++ b/.gitlab-ci/test-msvc.bat
@@ -0,0 +1,24 @@ +@echo on +:: vcvarsall.bat sets various env vars like PATH, INCLUDE, LIB, LIBPATH for the +:: specified build architecture +call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64 +@echo on + +:: FIXME: make warnings fatal +pip3 install --upgrade --user meson==0.49.2 || goto :error +meson _build || goto :error +ninja -C _build || goto :error + +:: FIXME: dont ignore test errors +meson test -C _build --timeout-multiplier %MESON_TEST_TIMEOUT_MULTIPLIER% --no-suite flaky + +:: FIXME: can we get code coverage support? + + +python "%CD%\.gitlab-ci\meson-junit-report.py" --project-name glib ^ +--job-id "%CI_JOB_NAME%" --output "%CD%/_build/%CI_JOB_NAME%-report.xml" ^ +"%CD%/_build/meson-logs/testlog.json" + +goto :EOF +:error +exit /b 1
diff --git a/.gitlab-ci/test-msys2.sh b/.gitlab-ci/test-msys2.sh new file mode 100755 index 0000000..9845b1a --- /dev/null +++ b/.gitlab-ci/test-msys2.sh
@@ -0,0 +1,75 @@ +#!/bin/bash + +set -e + +export PATH="/c/msys64/$MSYSTEM/bin:$PATH" +if [[ "$MSYSTEM" == "MINGW32" ]]; then + export MSYS2_ARCH="i686" +else + export MSYS2_ARCH="x86_64" +fi + +pacman --noconfirm -Suy + +pacman --noconfirm -S --needed \ + base-devel \ + mingw-w64-$MSYS2_ARCH-ccache \ + mingw-w64-$MSYS2_ARCH-gettext \ + mingw-w64-$MSYS2_ARCH-libffi \ + mingw-w64-$MSYS2_ARCH-meson \ + mingw-w64-$MSYS2_ARCH-pcre \ + mingw-w64-$MSYS2_ARCH-python3 \ + mingw-w64-$MSYS2_ARCH-python3-pip \ + mingw-w64-$MSYS2_ARCH-toolchain \ + mingw-w64-$MSYS2_ARCH-zlib \ + mingw-w64-$MSYS2_ARCH-libelf + +curl -O -J -L "https://github.com/linux-test-project/lcov/releases/download/v1.14/lcov-1.14.tar.gz" +echo "14995699187440e0ae4da57fe3a64adc0a3c5cf14feab971f8db38fb7d8f071a lcov-1.14.tar.gz" | sha256sum -c +tar -xzf lcov-1.14.tar.gz +# FIXME: not currently using lcov, see below +#LCOV="$(pwd)/lcov-1.14/bin/lcov" + +mkdir -p _coverage +mkdir -p _ccache +CCACHE_BASEDIR="$(pwd)" +CCACHE_DIR="${CCACHE_BASEDIR}/_ccache" +export CCACHE_BASEDIR CCACHE_DIR + +pip3 install --upgrade --user meson==0.49.2 + +PATH="$(cygpath "$USERPROFILE")/.local/bin:$HOME/.local/bin:$PATH" +CFLAGS="-coverage -ftest-coverage -fprofile-arcs" +DIR="$(pwd)" +export PATH CFLAGS + +meson --werror --buildtype debug _build +cd _build +ninja + +# FIXME: lcov doesn't support gcc9 yet: +# https://github.com/linux-test-project/lcov/issues/58 +#"${LCOV}" \ +# --quiet \ +# --config-file "${DIR}"/.gitlab-ci/lcovrc \ +# --directory "${DIR}/_build" \ +# --capture \ +# --initial \ +# --output-file "${DIR}/_coverage/${CI_JOB_NAME}-baseline.lcov" + +# FIXME: fix the test suite +meson test --timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" --no-suite flaky || true + +python3 "${DIR}"/.gitlab-ci/meson-junit-report.py \ + --project-name glib \ + --job-id "${CI_JOB_NAME}" \ + --output "${DIR}/_build/${CI_JOB_NAME}-report.xml" \ + "${DIR}/_build/meson-logs/testlog.json" + +# FIXME: see above +#"${LCOV}" \ +# --quiet \ +# --config-file "${DIR}"/.gitlab-ci/lcovrc \ +# --directory "${DIR}/_build" \ +# --capture \ +# --output-file "${DIR}/_coverage/${CI_JOB_NAME}.lcov"
diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..16884db --- /dev/null +++ b/AUTHORS
@@ -0,0 +1,40 @@ +Below are just a few of the people who have contributed +to GLib. Please don't mail these people about problems you +have with GLib; see the README.md file for information about +filing bugs and submitting changes. + +GLib-2.0 Team +------------- +Hans Breuer <hans@breuer.org> +Matthias Clasen <mclasen@redhat.com> +Tor Lillqvist <tml@iki.fi> +Tim Janik <timj@gtk.org> +Havoc Pennington <hp@redhat.com> +Ron Steinke <rsteinke@w-link.net> +Owen Taylor <otaylor@redhat.com> +Sebastian Wilhelmi <seppi@seppi.de> + +GLib-1.2 Team +------------- +Shawn T. Amundson <amundson@gimp.org> +Jeff Garzik <jgarzik@pobox.com> +Raja R Harinath <harinath@cs.umn.edu> +Tim Janik <timj@gtk.org> +Elliot Lee <sopwith@redhat.com> +Tor Lillqvist <tml@iki.fi> +Paolo Molaro <lupus@debian.org> +Havoc Pennington <hp@pobox.com> +Manish Singh <yosh@gimp.org> +Owen Taylor <otaylor@gtk.org> +Sebastian Wilhelmi <wilhelmi@ira.uka.de> + +The random number generator "Mersenne Twister", which is used by GLib, +was developed and originally coded by: +Makoto Matsumoto <matumoto@math.keio.ac.jp> +Takuji Nishimura <nisimura@math.keio.ac.jp> + +Original Authors +---------------- +Peter Mattis <petm@xcf.berkeley.edu> +Spencer Kimball <spencer@xcf.berkeley.edu> +Josh MacDonald <jmacd@xcf.berkeley.edu>
diff --git a/Android.mk b/Android.mk new file mode 100755 index 0000000..6571161 --- /dev/null +++ b/Android.mk
@@ -0,0 +1 @@ +include $(all-subdir-makefiles)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..52f17b1 --- /dev/null +++ b/CONTRIBUTING.md
@@ -0,0 +1,274 @@ +# Contribution guidelines + +Thank you for considering contributing to the GLib project! + +These guidelines are meant for new contributors, regardless of their level +of proficiency; following them allows the core developers of the GLib project to +more effectively evaluate your contribution, and provide prompt feedback to +you. Additionally, by following these guidelines you clearly communicate +that you respect the time and effort that the people developing GLib put into +managing the project. + +GLib is a complex free software utility library, and it would not exist without +contributions from the free and open source software community. There are +many things that we value: + + - bug reporting and fixing + - documentation and examples + - tests + - testing and support for other platforms + - new features + +Please, do not use the issue tracker for support questions. If you have +questions on how to use GLib effectively, you can use: + + - the `#gtk` IRC channel on irc.gnome.org + - the [`glib` tag on GNOME's Discourse](https://discourse.gnome.org/tags/glib) + +You can also look at the [`glib` tag on Stack +Overflow](https://stackoverflow.com/questions/tagged/glib). + +The issue tracker is meant to be used for actionable issues only. + +## How to report bugs + +### Security issues + +You should not open a new issue for security related questions. + +When in doubt, send an email to the [security](mailto:security@gnome.org) +mailing list. + +### Bug reports + +If you’re reporting a bug make sure to list: + + 0. which version of GLib are you using? + 0. which operating system are you using? + 0. the necessary steps to reproduce the issue + 0. the expected outcome + 0. a description of the behavior + 0. a small, self-contained example exhibiting the behavior + +If the issue includes a crash, you should also include: + + 0. the eventual warnings printed on the terminal + 0. a backtrace, obtained with tools such as GDB or LLDB + +If the issue includes a memory leak, you should also include: + + 0. a log of definite leaks from a tool such as [valgrind’s + memcheck](http://valgrind.org/docs/manual/mc-manual.html) + +For small issues, such as: + + - spelling/grammar fixes in the documentation, + - typo correction, + - comment clean ups, + - changes to metadata files (CI, `.gitignore`), + - build system changes, or + - source tree clean ups and reorganizations; + +or for self-contained bug fixes where you have implemented and tested a solution +already, you should directly open a merge request instead of filing a new issue. + +### Features and enhancements + +Feature discussion can be open ended and require high bandwidth channels; if +you are proposing a new feature on the issue tracker, make sure to make +an actionable proposal, and list: + + 0. what you’re trying to achieve and the problem it solves + 0. three (or more) existing pieces of software which would benefit from the + new feature + 0. how the feature is implementable on platforms other than Linux + +New APIs, in particular, should follow the ‘rule of three’, where there should +be three (or more) pieces of software which are ready to use the new APIs. This +allows us to check that the new APIs are usable in real-life code, and fit well +with related APIs. This reduces the chances of awkward or unusable APIs becoming +stable in GLib and having to be supported forever. + +A common way to introduce new APIs or data types to GLib is to prototype them in +another code base for a while, to gain real-life experience with them before +they are imported into GLib and marked as stable. + +Each feature should also come fully documented, and with tests which approach +full branch coverage of the new code. GLib’s CI system generates code coverage +reports which are viewable for each merge request. + +If proposing a large feature or change, it’s better to discuss it (on the +`#gtk` IRC channel or on [Discourse](https://discourse.gnome.org) before +putting time into writing an actionable issue — and certainly before putting +time into writing a merge request. + +## Your first contribution + +### Prerequisites + +If you want to contribute to the GLib project, you will need to have the +development tools appropriate for your operating system, including: + + - Python 3.x + - Meson + - Ninja + - Gettext (19.7 or newer) + - a [C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements) + +Up-to-date instructions about developing GNOME applications and libraries +can be found on [the GNOME Developer Center](https://developer.gnome.org). + +The [GLib project uses GitLab](https://gitlab.gnome.org/GNOME/glib/) for code +hosting and for tracking issues. More information about using GitLab can be +found [on the GNOME wiki](https://wiki.gnome.org/GitLab). + +### Getting started + +You should start by forking the GLib repository from the GitLab web UI, and +cloning from your fork: + +```sh +$ git clone https://gitlab.gnome.org/yourusername/glib.git +$ cd glib +``` + +**Note**: if you plan to push changes to back to the main repository and +have a GNOME account, you can skip the fork, and use the following instead: + +```sh +$ git clone git@gitlab.gnome.org:GNOME/glib.git +$ cd glib +``` + +To compile the Git version of GLib on your system, you will need to +configure your build using Meson: + +```sh +$ meson _builddir . +$ cd _builddir +$ ninja +``` + +Typically, you should work on your own branch: + +```sh +$ git checkout -b your-branch +``` + +Once you’ve finished working on the bug fix or feature, push the branch +to the Git repository and open a new merge request, to let the GLib +core developers review your contribution. + +### Code reviews + +Each contribution is reviewed by the core developers of the GLib project. + +The [CODEOWNERS](./docs/CODEOWNERS) document contains the list of core +contributors to GLib and the areas for which they are responsible; you +should ensure to receive their review and signoff on your changes. + +It is our intention that every commit to GLib is reviewed by at least one other +person, including commits from core developers. We all make mistakes and can +always learn from each other, and code review allows that. It also reduces +[bus factor](https://en.wikipedia.org/wiki/Bus_factor) by spreading knowledge +of each commit between at least two people. + +With each code review, we intend to: + + 0. Identify if this is a desirable change or new feature. Ideally for larger + features this will have been discussed (in an issue, on IRC, or on Discourse) + already, so that effort isn’t wasted on putting together merge requests + which will be rejected. + 0. Check the design of any new API. + 0. Provide realistic estimates of how long a review might take, if it can’t + happen immediately. + 0. Ensure that all significant contributions of new code, or bug fixes, are + adequately tested, either through requiring tests to be submitted at the + same time, or as a follow-up. + 0. Ensure that all new APIs are documented and have [introspection + annotations](https://wiki.gnome.org/Projects/GObjectIntrospection/Annotations). + 0. Check that the contribution is split into logically separate commits, each + with a good commit message. + 0. Encourage further high quality contributions. + 0. Ensure code style and quality is upheld. + +If a code review is stalled (due to not receiving comments for two or more +weeks; or due to a technical disagreement), please ping another GLib core +developer on the merge request, or on IRC, to ask for a second opinion. + +### Commit messages + +The expected format for git commit messages is as follows: + +```plain +Short explanation of the commit + +Longer explanation explaining exactly what’s changed, whether any +external or private interfaces changed, what bugs were fixed (with bug +tracker reference if applicable) and so forth. Be concise but not too +brief. + +Closes #1234 +``` + + - Always add a brief description of the commit to the _first_ line of + the commit and terminate by two newlines (it will work without the + second newline, but that is not nice for the interfaces). + + - First line (the brief description) must only be one sentence and + should start with a capital letter unless it starts with a lowercase + symbol or identifier. Don’t use a trailing period either. Don’t exceed + 72 characters. + + - The main description (the body) is normal prose and should use normal + punctuation and capital letters where appropriate. Consider the commit + message as an email sent to the developers (or yourself, six months + down the line) detailing **why** you changed something. There’s no need + to specify the **how**: the changes can be inlined. + + - When committing code on behalf of others use the `--author` option, e.g. + `git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`. + + - If your commit is addressing an issue, use the + [GitLab syntax](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html) + to automatically close the issue when merging the commit with the upstream + repository: + +```plain +Closes #1234 +Fixes #1234 +Closes: https://gitlab.gnome.org/GNOME/glib/issues/1234 +``` + + - If you have a merge request with multiple commits and none of them + completely fixes an issue, you should add a reference to the issue in + the commit message, e.g. `Bug: #1234`, and use the automatic issue + closing syntax in the description of the merge request. + +### Merge access to the GLib repository + +GLib is part of the GNOME infrastructure. At the current time, any +person with write access to the GNOME repository can merge merge requests to +GLib. This is a good thing, in that it allows maintainership to be delegated +and shared as needed. However, GLib is a fairly large and complicated package +that many other things depend on, and which has platform specific behavior — so +to avoid unnecessary breakage, and to take advantage of the knowledge about GLib +that has been built up over the years, we’d like to ask people contributing to +GLib to follow a few rules: + +0. Never push to the `master` branch, or any stable branches, directly; you + should always go through a merge request, to ensure that the code is + tested on the CI infrastructure at the very least. A merge request is + also the proper place to get a comprehensive code review from the core + developers of GLib. + +0. Always get a code review, even for seemingly trivial changes. + +0. Pay attention to the CI results. Merge requests cannot be merged until the + CI passes. If they consistently fail, either something is wrong with the + change, or the CI tests need fixing — in either case, please bring this to + the attention of a core developer rather than overriding the CI. + +If you have been contributing to GLib for a while and you don’t have commit +access to the repository, you may ask to obtain it following the [GNOME account +process](https://wiki.gnome.org/AccountsTeam/NewAccounts).
diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/COPYING
@@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 2.1 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 + Lesser 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it!
diff --git a/HACKING b/HACKING new file mode 100644 index 0000000..3306350 --- /dev/null +++ b/HACKING
@@ -0,0 +1,17 @@ +If you want to hack on the GLib project, you'll need to have the +following packages installed: + + - Meson 0.48.0 + - GNU gettext 0.10.40 + - pkg-config 0.16 + - gtk-doc + - libffi 3.0.0 + +To compile a Git version of glib on your system, you will need to take +several steps to setup the tree for compilation. You can do all these +steps at once by running: + + checkout/glib# meson _build + +For information about submitting patches see the CONTRIBUTING.md file. For +information about major design decisions, see the README.rationale file.
diff --git a/INSTALL.in b/INSTALL.in new file mode 100644 index 0000000..12774c3 --- /dev/null +++ b/INSTALL.in
@@ -0,0 +1,125 @@ +Simple install procedure +======================== + + % tar xf glib-@GLIB_VERSION@.tar.gz # unpack the sources + % cd glib-@GLIB_VERSION@ # change to the toplevel directory + % meson _build # configure the build + % ninja -C _build # build GLib + + [ Become root if necessary ] + % ninja -C _build install # install GLib + +Requirements +============ + +GLib requires a C90-compliant (but not necessarily C99-compliant) C +compiler and libc. On UNIX-like systems, it also assumes compliance +with at least the original 1990 version of POSIX. + +GLib-2.0 requires pkg-config, which is tool for tracking the +compilation flags needed for libraries. (For each library, a small .pc +text file is installed in a standard location that contains the +compilation flags needed for that library along with version number +information.) Information about pkg-config can be found at: + + http://www.freedesktop.org/software/pkgconfig/ + +Meson (http://mesonbuild.com/) is also required. + +In order to implement conversions between character sets, +GLib requires an implementation of the standard iconv() routine. +Most modern systems will have a suitable implementation, however +many older systems lack an iconv() implementation. On such systems, +you must install the libiconv library. This can be found at: + + http://www.gnu.org/software/libiconv/ + +If your system has an iconv implementation but you want to use +libiconv instead, you can pass the --with-libiconv option to +configure. This forces libiconv to be used. + +Note that if you have libiconv installed in your default include +search path (for instance, in /usr/local/), but don't enable +it, you will get an error while compiling GLib because the +iconv.h that libiconv installs hides the system iconv. + +If you are using the native iconv implementation on Solaris +instead of libiconv, you'll need to make sure that you have +the converters between locale encodings and UTF-8 installed. +At a minimum you'll need the SUNWuiu8 package. You probably +should also install the SUNWciu8, SUNWhiu8, SUNWjiu8, and +SUNWkiu8 packages. + +The native iconv on Compaq Tru64 doesn't contain support for +UTF-8, so you'll need to use GNU libiconv instead. (When +using GNU libiconv for GLib, you'll need to use GNU libiconv +for GNU gettext as well.) This probably applies to related +operating systems as well. + +Finally, for message catalog handling, GLib requires an implementation +of gettext(). If your system doesn't provide this functionality, +you should use the libintl library from the GNU gettext package, +available from: + + http://www.gnu.org/software/gettext/ + +Support for extended attributes and SELinux in GIO requires +libattr and libselinux. + +Some of the mimetype-related functionality in GIO requires the +update-mime-database and update-desktop-database utilities, which +are part of shared-mime-info and desktop-file-utils, respectively. + +GObject uses libffi to implement generic marshalling functionality. + +The Nitty-Gritty +================ + +Complete information about installing GLib can be found +in the file: + + docs/reference/glib/html/glib-building.html + +Or online at: + + https://developer.gnome.org/glib/stable/glib-building.html + + +Installation directories +======================== + +The location of the installed files is determined by the --prefix +and --exec-prefix options given to configure. There are also more +detailed flags to control individual directories. However, the +use of these flags is not tested. + +One particular detail to note, is that the architecture-dependent +include file glibconfig.h is installed in: + + $exec_prefix/lib/glib/include/ + +if you have a version in $prefix/include, this is out of date +and should be deleted. + +.pc files for the various libraries are installed in +$exec_prefix/lib/pkgconfig to provide information when compiling +other packages that depend on GLib. If you set PKG_CONFIG_PATH +so that it points to this directory, then you can get the +correct include flags and library flags for compiling a GLib +application with: + + pkg-config --cflags glib-2.0 + pkg-config --libs glib-2.0 + + +Cross-compiling GLib +==================== + +Information about cross-compilation of GLib can be found +in the file: + + docs/reference/glib/html/glib-cross-compiling.html + +Or online at: + + https://developer.gnome.org/glib/stable/glib-cross-compiling.html
diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..fe32008 --- /dev/null +++ b/NEWS
@@ -0,0 +1,12294 @@ +Overview of changes in GLib 2.64.0 +================================== + +* Use `posix_spawn()` to speed up launching test D-Bus instances (!1388) + +* Bugs fixed: + - #1783 Document using glib-mkenums with meson + - #2049 Crash in g_array_copy + - !1384 Some minor clang warning fixes + - !1386 docs: Document generated headers caveats for genmarshal + - !1387 ci: Correctly propagate exit status in run-style-check-diff.sh + - !1388 gtestdbus: Use posix_spawn() to spawn dbus-daemon + - !1389 Update GError docs to use G_DEFINE_QUARK + +* Translation updates: + - Czech + - Danish + + +Overview of changes in GLib 2.63.6 +================================== + +* Fix potential relative read when calling g_printerr(), which could lead to a + denial of service from a setuid-root process being used to block access to the + TTY for another user (#1919) + +* Fix SOCKS proxy resolver sometimes not being used when resolving addresses + via Happy Eyeballs (CVE-2020-6750) (#1989) + +* Several other Happy Eyeballs fixes for address resolution (#1871, #1872, #1902) + +* Various race fixes in `GDBusConnection` and its unit tests (#1515) + +* Fix a race condition with D-Bus name ownership (#1517) + +* Drop `gio-launch-desktop` helper application in favour of calling `sh` directly (#1633) + +* Fix win32 exception handling with C# exceptions (#2025) + +* Fix thread safety of `GUnixMountMonitor` (#2030) + +* Additional fixes to new thread pool attribute behaviour from GLib 2.63.4 to + check if sched_setattr() is allowed by system policies before depending on it (#2039, !1356) + +* Fix memory leaks and corruption when freeing `GSource`s while freeing a `GMainContext` (!1353) + +* Drop inappropriate installation of object manager example documentation (!1359) + +* Bugs fixed: + - #938 gdbus call -a doesn't support message bus connections + - #1515 gio/gdbus-threading test sometimes fails in CI + - #1517 g_bus_own_name does not always call name_lost_handler when _REPLACE and _ALLOW_REPLACEMENT are set + - #1633 should not install gio-launch-desktop into PATH + - #1919 read from relative path in g_printerr() in 2.58.3 + - #1995 Tracker issue for Happy Eyeballs regressions + - #2002 g_io_channel_read_line does not honour the line_term symbols set + - #2025 W32 exception handling misbehaves when C# exceptions are thrown when running inside the Visual Studio debugger + - #2030 Random nautilus test suite failures involving GUnixMountMonitor + - #2039 sched_setattr() still can cause EPERM through natural causes + - #2043 Low memory monitor test failed in CI + - #2044 GApplication docs suggest invalid GVariant type + - !1185 gtimezone: Tidy up UTC timezone creation + - !1281 ci: Update Docker packages + - !1283 gmodule: change _g_module_close to only take a handle. + - !1298 tests: Speed up the GIO actions test + - !1299 gapplication: Fix a minor typo in the documentation + - !1339 gsocketclient: Refactor g_socket_client_connect_async() + - !1353 GMainContext - Fix memory leaks and memory corruption when freeing sources while freeing a context + - !1354 GThreadPool - Add test for !1340 + - !1355 glist: Add docs examples of how to combine with g_steal_pointer() + - !1356 GThread - Check if sched_setattr is allowed by the system policies before depending on it + - !1359 docs: Don’t install object manager example separately + - !1363 Make tests pass if we are euid != 0 with capabilities + - !1366 Fix oss-fuzz coverage link + - !1372 gobject: Fix strict aliasing warnings with g_set_object() + - !1376 gitlab-ci: 64-bit ARM is aarch64, not arm64 + - !1381 ghash: Document the iteration order over a hash table is not defined + - !1382 tests: Bump the refcount timeout in gdbus-threading + - !1383 ci: Enable parallelisation when running installed tests + +* Translation updates: + - Basque + - English (United Kingdom) + - French + - Galician + - German + - Greek, Modern (1453-) + - Hungarian + - Indonesian + - Japanese + - Korean + - Lithuanian + - Polish + - Portuguese (Brazil) + - Spanish + - Swedish + - Turkish + + +Overview of changes in GLib 2.63.5 +================================== + +* Fix behaviour of `g_file_move()` fallback code to not follow symlinks (#986) + +* Rename `--glib-min-version` argument of `gdbus-codegen` to `--glib-min-required` + (this is not an API break as `--glib-min-version` was added earlier in the + 2.63 cycle) (#1993) + +* Add gtk-doc checks to CI and fix a number of documentation issues + (thanks to Xavier Claessens) (!978) + +* Add `G_SIZEOF_MEMBER()` macro (!1333) + +* Add a debug message if `g_setenv()` or `g_unsetenv()` are used after any + threads have been spawned — this will be upgraded to a warning in future (!1337, #715) + +* Skip memory monitor tests if xdg-desktop-portal or dbusmock are not available (!1296, !1338) + +* Change the `libmount` configure option from a boolean to a Meson `feature` (!1344) + +* Do not return `target-uri` from `g_file_peek_path()` when called on trash/recent files (!1346) + +* Drop new TLS certificate API for PKCS #11 backed certificates, as the implementation + is not ready yet (this is not an API break as the API was added earlier in the + 2.63 cycle) (!1347) + +* Bugs fixed: + - #986 g_file_move: remove G_FILE_COPY_NOFOLLOW_SYMLINKS section + - #1551 CI: Add checks for `TODO` in MRs + - #1925 Large number of routes installed into kernel cause high cpu usage + - #1993 Rename gdbus-codegen --glib-min-version argument to --glib-min-required and add --glib-max-allowed + - #2012 spawn_thread_queue not initialised in GThreadPool + - #2020 g_network_monitor_base_add_network() improperly unrefs GInetAddressMask + - !978 Various fixes to make gtkdoc-check pass on glib + - !1018 docs: tag enclose 'all' and 'help' values + - !1170 Avoid C++20 deprecated assignment to volatile + - !1296 tests: Skip GMemoryMonitor tests if the dbusmock template is not available + - !1307 Remove global declaration of GMemoryMonitor + - !1322 gmain: Mark G_SOURCE_FUNC as available in 2.58 + - !1333 Add and use G_SIZEOF_MEMBER() macro + - !1337 genviron: Message if g_setenv()/g_unsetenv() are used after threads spawned + - !1338 tests: Skip GMemoryMonitor tests if xdg-desktop-portal is not available + - !1344 meson: libmount autodectection + - !1345 gio-tool-info: Print unix mount information where available + - !1346 gfile: Do not return target-uri from g_file_peek_path() + - !1347 Revert "gtlscertificate: Add support for PKCS #11 backed certificates" + - !1348 ghash: Clarify that g_hash_table_add() always consumes the key + - !1349 doc: Clarify that _locker_new() does not actually allocate memory + - !1351 glib.supp: update g-threaded-resolver-getaddrinfo-config + +* Translation updates: + - Japanese + - Lithuanian + - Malay + - Portuguese (Brazil) + - Swedish + + +Overview of changes in GLib 2.63.4 +================================== + +* Fix various race conditions on signal emission in GDBus (#604, #978, #1232) + +* Change thread pools so that thread attributes (in particular, priority) are + inherited from the thread which created the `GThreadPool` initially, rather + than from the thread which is pushing a new job into the pool (#1834, #2007) + +* Expand support for running Windows apps with + `g_app_info_launch_default_for_uri()` using rundll32 on Windows (#1932) + +* Support multiple directories in `GSETTINGS_SCHEMA_DIR` environment variable (#1998) + +* Support full Julian day range in `TZ` environment variable (#1999) + +* Apply recursion depth limits to variants in D-Bus messages (!1201) + +* Support adding call flags and timeouts to method calls generated by + `gdbus-codegen` through the new `--glib-min-version` option (!1286) + +* Fully deprecate TLS rehandshakes; they are now ignored due to TLS protocol + changes (!1305) + +* Bugs fixed: + - #198 g_fopen and friends: should also state how to close a stream + - #604 GDBus name watching dispatch is buggy/excessively-complicated + - #833 g_object_set: document the need to cast varargs + - #978 SIGSEGV in on_name_lost_or_acquired + - #1232 Insufficient thread safety around GDBusObjectManagerClient + - #1416 Re-add macOS CI + - #1834 Unwanted priority/etc inheritance with GThreadPool and GThread and the POSIX implementation + - #1932 Windows: Gio.AppInfo.launch_default_for_uri seems not to work for local files/folders + - #1983 glib:gio / dbus-appinfo test fails: GLib-GIO:ERROR:../../../../Projects/glib/gio/tests/dbus-appinfo.c:326:on_flatpak_open: 'g_file_equal (files[0], f)' should be TRUE + - #1997 Base64 encoding with "break_lines" claims to wrap at 72 characters but seems to wrap at 76 + - #1998 support multiple directories in GSETTINGS_SCHEMA_DIR + - #1999 GTimeZone fails to accept full Julian day range when parsing the direct $TZ string format + - #2007 Thread scheduler attributes fail under valgrind + - !388 ci: Avoid downloading subprojects for each job + - !1111 gio: test that launch_uris() exports files with the document portal when launching a flatpak + - !1201 gdbusmessage: Limit recursion of variants in D-Bus messages + - !1279 tests: Fix an error message set by foo_set_property() + - !1286 gdbus-codegen: Add a GDBusCallFlags arg to method calls + - !1291 gio-tool-list: Add an option to print display names + - !1294 GMemoryMonitor docs fixes + - !1295 gio: Fix socket test + - !1301 GThread - Inherit parent thread priority by default for new Win32 threads + - !1303 gvariant-core: Don't pass NULL second argument to memcpy + - !1305 Fully deprecate TLS rehandshakes + - !1308 gsocketclient: run timeout source on the task's main context + - !1309 Fix crash in gutils when application is prevented access to passwd file + - !1317 gfdonotificationbackend: remove notifications when bus name vanishes + - !1320 subprojects: Temporarily avoid using wrapdb while it’s down + - !1324 ci: Add some documentation to the style check CI test + - !1325 Check for SYS_sched_getattr before using it unconditionally + - !1330 W32: Correctly set st_ino when doing private stat() + - !1334 gthread: Ensure GThreadSchedulerSettings is always defined + +* Translation updates: + - Catalan + - Galician + - Hungarian + - Indonesian + - Polish + - Portuguese (Brazil) + - Spanish + + +Overview of changes in GLib 2.63.3 +================================== + +* Add a `--glib-min-version` argument to `gdbus-codegen` which controls breaks in the API of generated code (#1726) + +* Add `g_clear_list()` API to clear `GList`s to `NULL` (#1943) + +* Add a `GMemoryMonitor` API to be notified of memory pressure situations using the low-memory-monitor project (!1005) + +* Add support for dispose functions for `GSource` implementations (!1175) + +* Tighten up validation of GObject signal and property names, allowing performance improvements (!1224) + +* Fix installation path of GIO modules on MSVC to be the bindir (!1254) + +* Bugs fixed: + - #650 g_signal_lookup gives too many warnings + - #1011 GListStore, easily find if the item is already inserted + - #1130 gdbus-codegen: Add an option to strictly generate markdown in source comments + - #1687 glocalvfs.c uses non-thread-safe getpwnam() + - #1726 Warn when method/signal uses type 'h' but lacks GDBus.C.UnixFD annotation + - #1935 Assert in _kqsub_free seems to be too strict + - #1943 Consider g_clear_list() + - #1947 Documentation clarification for g_uuid_string_random() + - #1953 Documentation for g_type_init() and others missing from online gtk-doc documentation + - #1961 A typo in the comment of `g_settings_schema_get_path`: threfore -> therefore + - !1005 gio: Add GMemoryMonitor to monitor for low-memory + - !1172 gptrarray: Add an example to the g_ptr_array_steal() docs + - !1175 Implement a dispose function for GSource + - !1223 Add additional valgrind suppressions + - !1224 Signal name handling improvements + - !1230 ci: Run installed-tests on Fedora + - !1235 Add sudo to Fedora docker image + - !1239 tests: Run "timeout tests" sequentially + - !1248 ci: Update all Debian CI runners to use v5 of the Dockerfile + - !1249 gio-tool-mount: Allow mounting by the given UUID + - !1252 ci: Fix running all jobs on merge requests + - !1253 gthread: Fix "zero as null pointer" warning + - !1254 giomodule: gio modules are no longer installed in bindir on MSVC + - !1255 ci: Build Docker images rather than OCI images if using podman + - !1256 gdate: Add autoptr support + - !1258 Minor CI fixups + - !1261 gtk-doc: Ensure we have recent enough version + - !1262 tests: Add tests for the gdbus-codegen executable + - !1265 build: don't check for protected visibility + - !1267 Revert "doc: Workaround gtkdoc-scan bug leading to undocumented symbols" + - !1268 ci: Work-around successful installed tests having no logs + - !1269 gvariant: Add guard to g_variant_get() + - !1271 tests: Enable GDBus debug for a number of unreliable tests + - !1274 trash portal: Don't follow symlinks + - !1275 Small doc correction + - !1277 Various gtk-doc improvements + - !1278 Update installed tests CI + - !1280 clang-format-diff: Output diff for multiple files, not just one + - !1282 Revert "Revert "docs: remove GDBusObjectManager example"" + - !1284 Update POTFILES.in 191212 + - !1287 atomic/tests: test g_atomic_pointer_compare_and_exchange() with const pointers + - !1289 gtype: Define auto-cleanup functions for Module class + +* Translation updates: + - Spanish + + +Overview of changes in GLib 2.63.2 +================================== + +* Use `lldb` rather than `gdb` on macOS for debugging (#1004) + +* Switch the atomic builtins from `__sync_fetch_*()` to the slightly more modern + `__atomic_*()` (#1750) + +* Fix calculation of `gsize` width on various platforms (including OpenBSD) (#1777) + +* Fix undefined behaviour causing brokenness in `g_utf8_find_prev_char()` when + compiling with GCC ≥ 8 (#1917) + +* Revert UNIX mode changes in `G_FILE_ATTRIBUTE_ID_UNIX_MODE` which broke OSTree (#1934) + +* Slightly improve performance for signal emissions when no handlers are connected (!1083) + +* Add `g_task_return_value()` and `g_task_propagate_value()` APIs to allow + `GTask` to be used from language bindings more easily (!1216) + +* Fix a file monitoring crash on kqueue-based systems (BSD) (!1221) + +* Bugs fixed: + - #1004 [PATCH] Make gbacktrace use lldb on Mac OS X + - #1552 CI: Add code style checks + - #1750 Switch from __sync_fetch_*() to __atomic_*() in glib/gatomic.h + - #1777 gsize: improper typedef on (at least) OpenBSD + - #1895 Regression: glib does not compile on centos 6: "objcopy: unrecognized option '--add-symbol'" + - #1917 Test utf8-pointer fails with static build, LTO, optimisations, and new GCC + - #1930 glib/tests/bookmarkfile.c:385:test_modify: assertion failed: (stamp == now) + - #1934 ostree tests broken since bfdc5fc4fc84ef8518d2d1a328c8482cf5a38e98: File '/tmp/test-tmp-libostree_test-basic-user.sh.test-QB4SA0/diff-test2' is not empty + - #1938 GDateTime doesn't support leap seconds + - #1940 atomics test fails on FreeBSD CI since !1123 + - !1039 Improve documentation for footgun function g_tls_client_connection_copy_session_state() + - !1083 Use the GObject hole on 64bit arches for some flags to improve performance + - !1202 CI updates after !1177 + - !1208 gutils: Slightly improve docs formatting for g_get_os_info() + - !1209 Make ld executable configurable + - !1210 gdbus-server-auth test: Include gcredentialsprivate.h + - !1213 gsocket: Improve diagnostics on bind() failure + - !1214 gvariant, gbytes: Avoid memcmp (NULL, ., 0) or memcmp (., NULL, 0) + - !1216 Make GTask more binding-friendly + - !1218 gdb: Fix GHashTable pretty printer off-by-one error + - !1220 gparam: fix memory leak in g_param_value_defaults() + - !1221 Add NOTE_REVOKE to the list of the monitoring events + - !1225 gtlsconnection: clarify handshake() documentation + - !1227 Deprecate old GTlsConnection functionality even harder! + - !1231 Fix build on old libc that does not define _SC_HOST_NAME_MAX + - !1238 gstrfuncs: use gsize type internally for strv functions + - !1242 gfileinfo: Clarify the documentation for G_FILE_ATTRIBUTE_UNIX_MODE + - !1243 docs: Fix "occurred" typos in API documentation + +* Translation updates: + - Spanish + + +Overview of changes in GLib 2.63.1 +================================== + +* Several usability improvements to command line `gio` tool (!1153) + +* Add `g_array_steal()`, `g_ptr_array_steal()` and `g_byte_array_steal()` APIs (#285) + +* Add `g_get_os_info()` API (!1063, !1160) + +* Add `g_warning_once()` API (!1028) + +* Always resolve `localhost` to loopback address in `GResolver` (!616) + +* Add `GMainContextPusher` API (!983) + +* Limit recursion in `g_variant_parse()` (!1173) + +* Fix crash in `g_spawn()` with high FD numbers due to use of `select()` rather + than `poll()` (#954) + +* Allow passing empty `GValue`s to `g_param_value_set_default()` (!1186) + +* Escape header guards generated by `gdbus-codegen` better (#1379) + +* Bugs fixed: + - #285 [PATCH] add array steal and memdup functions + - #954 The g_spawn_sync() function uses select() which has limitations + - #1318 rare failure in gdbus-peer test: invalid uninstantiatable type '(null)' in cast to 'GDBusServer' + - #1379 gdbus-codegen generates invalid header guards when build directory contains a + character + - #1622 NULL pointer derefs on g_vasprintf() failure + - #1813 g_option_context_add_main_entries() is missing array annotation for entries parameter + - #1831 No reply on private socket due to auth problem + - #1836 gobject.c uses undefined annotation “(not optional)” + - #1858 docs/reference/gobject/tut_gobject.xml: object properties example uses deprecated API + - #1877 g_cancellable_source_new annotated with 'skip' + - #1896 Use after free when calling g_dbus_connection_flush_sync() in a dedicated thread + - #1897 glib 2.62.0 fails test 'test_writev_no_vectors' wih gcc7 + - #1903 use-after-free in mimeapps test causes intermittent segfault during testing + - #1906 test_os_info fails on FreeBSD + - #1916 objcopy not used from cross-compilation file in GIO tests + - #1923 Recent Versions of GLib Break Dolphin File-Manager's Thumbnailing when Using 'gtk2' Style + - !616 Always resolve localhost to loopback address + - !983 gmain: Add GMainContextPusher convenience API + - !1014 tests: Add a test for g_assert_finalize_object() + - !1028 gmessages: Add g_warning_once() + - !1035 Switching from C gnu89 to C gnu99 standard + - !1063 gutils: Add g_get_os_info() + - !1082 gdatetime: Document RFC 3339 extensions when parsing ISO 8601 + - !1105 syscall flood on every time*() function call + - !1120 Update documentation with FreeBSD build instructions + - !1135 gmain: use atomic operation instead of GMutex to access g_main_context_default() + - !1146 Solaris build fixes + - !1147 gmodule: fix typo in doc comment + - !1148 gio/gfileinfo: fix parameter references + - !1149 gio/gfile: fix parameter reference for value_p + - !1150 gio/gfile: fix parameter references to @contents + - !1151 gio/gfile: fix typo in doc comment + - !1152 gwinhttpvfs: Handle g_get_prgname() returning NULL + - !1153 Several gio-tool bash completion fixes and improvements + - !1155 Strict-aliasing fixes to new atomic built-ins + - !1157 Fix various compiler warnings on Android + - !1160 Add Windows support to g_get_os_info() + - !1161 hash: Remove an assertion from the hot path + - !1163 gcharset: Expand the documentation for g_get_locale_variants() + - !1165 Use uname as a fallback to get OS info + - !1167 Fix some minor leaks in testfilemonitor + - !1168 Fix gdatetime tests on toolbox + - !1171 Revert "gdbus-codegen: emit GUnixFDLists if an arg has type 'h'" + - !1173 gvariant: Limit recursion in g_variant_parse() + - !1177 ci: Add libdbus development files to CI Docker images + - !1179 Improve GPtrArray doc-comments + - !1180 array: Avoid use of memcpy(dest, NULL, 0) + - !1181 gmain: Clarify thread safety of some common GSource functions + - !1182 gio: Fix typo in URL + - !1186 Allow using an empty GValue with g_param_value_set_default() + - !1189 gparamspecs: Fix type class leaks on error handling paths + - !1197 Fix GDBus test failures on non-Linux (in particular FreeBSD) + - !1200 Minor fixes from a scan-build run + +* Translation updates: + - Catalan + - Chinese (Taiwan) + - Spanish + + +Overview of changes in GLib 2.63.0 +================================== + +* Add g_fsync() API (#35) + +* Fix regression in g_file_copy() when passing + `G_FILE_COPY_TARGET_DEFAULT_PERMS` flag; the destination permissions would be + private rather than following the process’ umask (!1142) + +* Several `GDateTime` parsing fixes (!1127) + +* Always build the tests if installed-tests are enabled, so that the tests can + actually be installed (!1141) + +* Rework atomic function implementations to use memory barrier in the correct + place (when compiler intrinsics aren’t providing the atomics), and fix + signedness issues (#1449, #1565) + +* Use the OS’ `fdwalk()` function (if safe) to speed up `g_spawn_*()` on BSD (#1638) + +* Remove the macOS `dyld` `GModule` implementation in favour of `dl` instead (!1093) + +* Bump Python requirement to ≥ 3.5, which we implicitly relied on anyway through + our Meson dependency (!1132) + +* Bugs fixed: + - #35 add g_fsync to API + - #174 g_file_copy always preserves permissions, even if G_FILE_COPY_ALL_METADATA flag is not set + - #259 docs: fix a misunderstanding in g_type_add_interface_* + - #767 g_signal_lookup fails if class is not referenced + - #1052 g_io_write_chars calls abort when given a null byte as input + - #1449 glib fallback atomic int/ptr get/set have memory barrier in wrong place + - #1565 Signedness of atomic operations + - #1638 g_spawn_*() is extremely slow under certain circumstances + - #1809 Provide API for working with PKCS11 backed certificates + - #1843 TSAN false positive with g_atomic_pointer_get/g_atomic_pointer_set under Clang + - #1865 g_variant_get_data_as_bytes fails after serializing a variant + - #1875 Segfault and Overflow in __gio_xdg_cache_mime_type_subclass() with Wps-Office installed + - #1887 glib 2.62.0 breaks loading dylibs as modules + - #1888 2.62: docs build on Windows broken + - #1897 glib 2.62.0 fails test 'test_writev_no_vectors' wih gcc7 + - !1020 docs: Remove priv pointers from the tutorial example + - !1062 gtype: mark the inline functions in G_DECLARE_*_TYPE() as UNUSED + - !1080 tests: Fix skipping mkdir-with-parents-permission test + - !1088 Various small scan-build fixes + - !1090 giochannel: Clarify type of GSource callback in documentation + - !1093 gmodule: remove macOS dyld implementation + - !1095 Define G_IOV_MAX to 512 on macOS/iOS + - !1099 gmem: clarify that g_malloc always uses the system allocator + - !1109 doc: fix typo in gio/gsettings.c + - !1110 gio: Add missing "gio remove" option to bash completion script + - !1112 Add version macros for GLib 2.64 + - !1115 gdatetime: Fix error handling in g_date_time_new_ordinal() + - !1116 gmarkup: Add a limit on the number of attributes in an element + - !1119 Annotate the return value of various utility functions + - !1124 docs: Fix typo in GConverter{Input,Output}Stream section titles + - !1125 gdatetime: Fix error handling in g_date_time_new_week() + - !1126 fileinfo: Mention that usec mtimes are set + - !1129 gdate: Fix tautological comparison warnings on Android + - !1130 Improve GLIB_DEPRECATED_MACRO_FOR output + - !1131 gio/gfileinfo: fix param reference in doc comment + - !1132 build: Bump Python requirement to ≥ 3.5 + - !1137 gregistrysettings: bump key name length to 2048 + - !1138 Always build tests if we enabled installed-tests + - !1139 g_file_info_get_modification_date_time: Calculate in integer domain + +* Translation updates: + - Danish + - Italian + - Panjabi + - Serbian + - Turkish + + +Overview of changes in GLib 2.62.0 +================================== + +* Fix new `GFileInfo` APIs to work when `G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC` + was not queried (!1087) + +* Bugs fixed: + - #487 Add valgrind test runs to CI + - !1084 garray: Fix reference to GLIB_SIZEOF_INT + - !1086 glib.supp: make gobject_init() calloc also of the possible kind + - !1087 fileinfo: ignore USEC if not available + +* Translation updates: + - Friulian + - Portuguese (Brazil) + + +Overview of changes in GLib 2.61.3 +================================== + +* Support setting thread name on BSD systems (#1761) + +* Install previously-uninstalled headers for public `GNativeSocketAddress` + object (#1854) + +* Very initial support for Windows apps (UWP) (!1057) + +* Add various new valgrind suppressions to `glib.supp` (#1879, !1075) + +* Bugs fixed: + - #83 Optimisation for g_nearest_pow() in garray.c + - #512 GSignal: accumulator function not called to accumulate G_SIGNAL_RUN_CLEANUP object handler return values + - #873 allow NULL arguments to parse_strv + - #905 Patches from static analysis run on 2.40 + - #1057 goption: add sanity check to input parameters + - #1309 GSettings object stops emitting "changed" signal on g_settings_reset after call to g_settings_delay + - #1620 GDBus criticals from GVfs with GLib master + - #1761 Setting thread-name on BSD systems + - #1803 GDK_SCALE=X is not respected when using "gio open" + - #1819 Invalid characters in Open Location dialog crashes GIMP + - #1852 Regression: g_mkdir_with_parents() returns 0 on failure + - #1854 glib/gio: GNativeSocketAddress headers not installed. + - #1860 g_clear_handle_id does not trigger GLIB_VERSION_MAX_ALLOWED warning + - #1863 Potential invalid writes on g_utf8_strreverse + - #1867 A couple of en_GBisms + - #1870 GSettingsBackend watches not thread-safe + - #1879 Incomplete valgrind suppressions - 16 KiB leak reported by valgrind from loading libglib-2.0.so + - #1880 glib/gbacktrace.c: If dup2 happened to return -1, don't call dup2 with same value + - #1881 GIO_USE_VOLUME_MONITOR and GIO_USE_FILE_MONITOR do not work as documented + - !1002 Remove mentions of mailing lists from the documentation + - !1011 gapplication: Fix a leaking GRemoteActionGroup member + - !1015 Post-release version bump + - !1016 gnetworkmonitornm fixups + - !1017 Improve ISO 8601 parsing by GDateTime + - !1023 g_object_get_property: Improve documentation for use of G_VALUE_INIT + - !1026 gutf8: Assert that written memory stays in bounds + - !1027 gfileutils: Fix error propagation for other than ENOENT + - !1031 meson: build gnulib if printf isn't good enough + - !1032 meson: small printf check cleanups + - !1033 win32: don't assume the format specifier for the stdlib printf/scanf like functions + - !1034 glib/tests/fileutils: Add a reproducer for #1852 + - !1036 cond test: Don't make assumptions about struct sigaction member order + - !1037 Meson: Override glib-compile-resources/schemas + - !1044 Relax use of g_test_bug() to not require g_test_bug_base() to be called first + - !1049 minor typos in the documentation + - !1050 tests: Fix a pragma warning on FreeBSD + - !1054 gerror: Add a docs paragraph about not displaying errors verbatim in UI + - !1057 Some (probably) easy uwp patches + - !1059 Update win32 readme, add myself to codeowners + - !1066 libffi.wrap: Meson port has moved to FDO gitlab + - !1068 gsubprocesslauncher.c: fix documentation + - !1071 meson: Move libdl_dep to the top level + - !1074 Adjust README formatting + - !1075 glib.supp: add suppression for g_type_class_ref() + +* Translation updates: + - Basque + - Catalan + - Czech + - English (United Kingdom) + - French + - Galician + - German + - Hungarian + - Indonesian + - Korean + - Lithuanian + - Polish + - Romanian + - Spanish + - Swedish + + +Overview of changes in GLib 2.61.2 +================================== + +* Add various new array functions (#236, #269, #373) + - `g_array_copy()` + - `g_ptr_array_copy()` + - `g_ptr_array_extend()` + - `g_ptr_array_extend_and_steal()` + - `g_array_binary_search()` + +* Add `g_assert_finalize_object()` helper function for writing tests (#488) + +* Rework how D-Bus connections are closed/unreffed when `g_test_dbus_down()` is + called. Tests which leak a `GDBusConnection` may now time out and abort, + rather than silently leaking. (#787) + +* Add a deprecation macro for GLib macros, and use it; third-party uses of + long-deprecated GLib macros may now start causing warnings. (#1060) + +* Deprecate `GTime` and `GTimeVal`, and various functions which use them. + Use `GDateTime` and `guint64` UNIX timestamps instead. (#1438) + +* Stop using `G_DISABLE_DEPRECATED` to allow disabling deprecation warnings; + third-party code should now be using + `GLIB_VERSION_{MIN_REQUIRED, MAX_ALLOWED}` to control symbol usage (!871) + +* Improve support for running `ninja test` when GLib is built statically (#1648) + +* Improve `GNetworkMonitor` detection of offline states (#1788) + +* Fix build failure on macOS related to missing `_g_content_type_get_mime_dirs` + function (#1791) + +* Add various installed utilities’ paths to `gio-2.0.pc` (#1796) + +* Fix keyfile `GSettings` backend and portal (especially relevant to any version + of GLib included in a flatpak runtime) (#1822, !985) + +* More IPv6 ‘Happy Eyeballs’ fixes in `GNetworkAddress` (!865) + +* Fix CVE-2019-12450, wide permissions of files when copying using GIO (!876) + +* Bump the Meson dependency from 0.48.0 to 0.49.2; we won’t depend on anything + higher than this for a while, as Debian 10 ships 0.49 (!924) + +* Various test fixes for Windows (!930, !931) + +* Initial support for Universal Windows Platform (UWP): certification, and use + of packaged libraries (!951) + +* Add experimental clang-cl support on Windows, allowing `g_autoptr()` support + on Windows (!979) + +* Bugs fixed: + - #77 G_STDIO_NO_WRAP_ON_UNIX wraps + - #236 Add a function to copy an array + - #269 Additional convenience functions for g_ptr_array + - #373 GArray could use a binary search function + - #436 running tests leaves lots of coredumps + - #453 find-enclosing-mount docs confusing + - #488 Add g_object_assert_last_unref() helper macro to detect object leaks in tests + - #590 A reader lock can be obtained even if a writer is already waiting for a lock + - #638 g_atexit is defined when not declared + - #737 Initialize GValue in g_object_get_property() + - #787 gtestdbus: Properly close server connections + - #804 gdbusproxy prefixes unstripped error + - #870 Fix and enhance GDatetime for Windows + - #872 ucs4 functions have wrong return transfer + - #887 gdusmessage.c mishandles bounds of GDBusMessageType and related enums + - #894 gvalue: Avoid expensive checks where possible + - #940 Docs for g_socket_listener_set_backlog are not very helpful + - #943 G_DEFINE_TYPE_WITH_PRIVATE docs not helpful + - #1018 Allow guid key in dbus addresses + - #1060 Add deprecation macro for macros + - #1169 Tools can display gibberish messages from translations + - #1270 g_get_charset always returns 8-bit codepage on Windows, crippling UTF-8 output + - #1438 Deprecate GTimeVal- and GTime-based APIs + - #1635 g_socket_join_multicast_group iface parameter fails on win32/64 + - #1648 2.58.2: Assorted asserts fail in Arch Linux when built statically + - #1729 g_content_type_guess segfaults when passed an empty data buffer on Mac OS + - #1788 GNetworkMonitor claims I am offline + - #1790 documentation on g_file_info_get_attribute_as_string + - #1791 _g_content_type_get_mime_dirs missing from libgio-2.0.0.dylib on MacOS + - #1792 glib-genmarshal generated valist marshal does not respect static scope for some types + - #1793 glib-genmarshal generates wrong code for va marshaler for VARIANT type + - #1794 API Proposal: g_timer_is_active + - #1796 Add gio-querymodules variable to pkg-config file + - #1797 glib/tests/win32 test failing on 64-bit Visual Studio builds + - #1798 /contenttype/tree reliably fails on FreeBSD since !863 + - #1807 g_dbus_server_new_sync() documentation references nonexistent function + - #1808 Stopping a GDBusServer should clean up Unix socket paths (if not abstract) and nonce-tcp nonce files + - #1811 Introspection info for g_unichar_compose's 3rd arg should be OUT + - #1822 keyfile gsettings backend not loading + - #1823 Documentation for disabling selinux is incorrect + - #1825 GKeyFileSettingsBackend created without filename construct property and unchecked assertion + - #1828 Small typo in gio manpage + - #1837 Specify for each (optional) parameter, whether it is OUT or INOUT + - #1838 Reword documentation for G_DECLARE_FINAL_TYPE + - #1847 Setting GLIB_VERSION_{MIN_REQUIRED, MAX_ALLOWED} to before 2.56 triggers warnings + - !533 docs: Document pitfall of deprecation pragmas + - !563 ci: Add scan-build job in a new ‘analysis’ pipeline stage + - !678 glib-compile-schemas: Improve translatable strings + - !817 gdate: Officially mark GTime as deprecated + - !851 gsettings: Document that lists are returned in no defined order + - !853 gobject: Fix apostrophe usage in a few small bits of documentation + - !859 gobject: Add a g_assert_finalize_object() macro + - !863 gunicollate/cygwin: Don't use __STDC_ISO_10646__ for wchar_t related checks + - !865 gnetworkaddress: fix "happy eyeballs" logic + - !867 Post-release version bump + - !871 Drop G_DISABLE_DEPRECATED + - !873 Use atomic reference counting for GSource + - !874 Clamp number of vectors to IOV_MAX / UIO_MAXIOV for GOutputStream writev()... + - !875 CI/msys2: disable coverage reporting, lcov doesn't support gcc9 yet + - !876 CVE-2019-12450: gfile: Limit access to files when copying + - !877 gio: specify proper c_marshaller and va_marshallers + - !883 tests: Fix small race in GSubprocess tests + - !884 garcbox.c: Fix typo atomit => atomic + - !885 goption: Clarify G_OPTION_ARG_FILENAME documentation + - !889 Include <sys/filio.h> for FIONREAD + - !901 gmain: Clarify that g_source_destroy() doesn’t drop a reference + - !904 Add glib-genmarshal tests and fix some valist marshaller bugs + - !906 property action: Add state hints + - !908 Improve testfilemonitor test repeatability and debuggability + - !909 D-Bus auth mechanism improvements + - !914 ci: Run scan-build in a different build directory + - !915 docs: fix typo on arrays examples in gvariant-text + - !917 docs: Fix name of IRC channel in CONTRIBUTING.md + - !919 glib/tests/refcount.c: Fix tests on non-GCC-isque compilers + - !920 gmacros: Only use deprecated attributes on enumerators with GCC ≥ 6.5 + - !923 Check if compiler symbols are defined before using them + - !924 Bump the required version of Meson + - !930 glib/tests/convert.c: Skip tests that aren't meaningful for Windows + - !931 glib/tests/fileutils.c: Fix stdio Wrapper Test on Windows + - !934 build: Increase the slow test timeout to 180s + - !935 Ignore */__pycache__/* directories + - !937 Fix module tests on Visual Studio builds + - !939 gstdio: minor cleanups + - !941 list model: Expand items-changed docs + - !944 gutils: Don't limit the length of the host name to 99 + - !945 Avoid overrunning stack at the end of the varargs. + - !947 gobject/tests/signals.c: Fix tests on Windows + - !948 GObject: Fix mkenums.py and genmarshal.py tests on Windows + - !950 ci: Enable CI on FreeBSD 12 + - !951 Preliminary patches for Universal Windows Platform support + - !952 gio: Make minor docs improvements + - !953 g_utf8_normalize: Doc comment return missing nullable annotation + - !954 Fix the ISO 15924 code for Manichaean + - !955 gmacros: Use _Static_assert when C11 is available + - !958 gthread: fix minor errno problem in GCond + - !961 gmain: Fix g_main_context_prepare priority annotation + - !962 gmacros: Use _Static_assert only for non-expr static assert + - !964 gmacros.h: Use static_assert on MSVC if possible + - !968 Fix typo in request handle + - !970 gdatetime: Unset LC_ALL for the test as well + - !971 docs.c: Forward link from g_auto* → G_DEFINE_AUTO* + - !973 doc: fix typo in gio/gresource.c + - !979 Experimental clang-cl support + - !980 gmacros.h: Add better support for clang-cl + - !981 gio: fix typo in g_settings_reset documentation + - !982 Various doc fixes + - !985 Keyfile portal fixes + - !987 gio/tests: Remove code and comments referring to libtool + - !991 fix atomic detection on older gcc versions + - !992 docs: Add example to g_test_summary() documentation + - !994 gio: Fix minor docs mistakes + - !996 Small array test fixes + - !997 gdbusaddress: Add missing transfer annotation + - !1007 Resubmission of !832 “Try to create the complete path right away and fall back” + - !1009 gapplication: remove inactivity_timeout source on finalize + +* Translation updates: + - Hungarian + - Indonesian + - Portuguese (Brazil) + - Spanish + + +Overview of changes in GLib 2.61.1 +================================== + +* `g_unichar_isxdigit()` and `g_unichar_xdigit_value()` now handle full-width + characters (U+FF21–U+FF26 and U+FF41–U+FF46) (#58) + +* Deprecate `gtester` utility and its test reporting format and enable TAP + output by default instead — the `--tap` option to tests is now a no-op + (#1441, #1619) + +* Add `g_test_summary()` to allow test authors to programmatically summarise + what each unit test in a test suite does (#1450) + +* Upgrade to Unicode Character Database v12.1 (#1713, !822) + +* More IPv6 Happy Eyeballs fixes to `GNetworkAddress` and `GSocketClient` + (#1747, #1771, #1774) + +* Fix valgrind and gdb support for the new `GHashTable` changes (#1749, #1780) + +* Fix GTask wait times growing faster than the number of task threads (#1683) + +* Change `GApplication` to ignore `-psn_*` arguments on the macOS command line, + as they are irrelevant (#1784) + +* Add `g_autoqueue()` helper macros, similar to `g_autolist()` (!474) + +* Add pre-allocated link helpers for `GList` and `GQueue`: + - `g_list_insert_before_link()` + - `g_queue_insert_before_link()` + - `g_queue_insert_after_link()` + +* Improve network availability detection with NetworkManager to treat lower + levels of connectivity as having reduced availability (!781) + +* Add `g_clear_signal_handler()` to allow disconnecting from a `GObject` signal + and clearing the signal handler ID to zero in a single call (!819) + +* Add `g_autoptr()` support for `GRWLock` (!825) + +* Define `G_OS_UNIX`, not `G_OS_WIN32`, when GLib is built agains Cygwin (!862) + +* Bugs fixed: + - #29 GScanner: should explicitly document modifiable fields (value, next_value, ...) + - #58 g_unichar_isxdigit() and g_unichar_xdigit_value() should deal with full-width a-fA-F + - #106 Boxed types should be documented better + - #135 g_unichar_totitle(0) returns 0x00001F88 instead of 0 + - #429 g_format_size() is broken on Windows + - #1441 Deprecate gtester + - #1450 Add API for tests to describe what they're checking + - #1619 GTest should have a way to default to TAP + - #1683 GTask: task_wait_time is increased constantly when the number of running thread is greather than 10 + - #1713 Upgrade to Unicode Character Database v12 + - #1739 meson build failure libdl + - #1747 Critical in g_socket_client_async_connect_complete + - #1749 New GHashTable implementation confuses valgrind + - #1753 Remove memory leaks from gio/test/resolver.c + - #1755 Please revert #535 gmacros: Try to use the standard __func__ first in G_STRFUNC + - #1759 test_month_names: assertion failed + - #1760 Document for g_resolver_lookup_records why it returns a list of list of gchar*. + - #1763 tests: -p runs tests in the reverse of the specified order + - #1768 g_strlcat(): Possible buffer overflow in implementation + - #1771 GNetworkAddressAddressEnumerator unsafely modifies cache in GNetworkAddress + - #1774 Leaks in gsocketclient.c connection code + - #1776 glib/date test fails + - #1780 GDB pretty-printer for GHashTable no longer works + - #1782 Error in documentation for cross-compile. + - #1784 MacOS adds a -psn_X_XXXXXX parameter to the command line + - !474 Add g_autoqueue + - !476 Add pre-allocated link helpers for GList and GQueue + - !556 gtestutils: Make --tap compatible with -p and --GTestSkipCount + - !732 gsocket: Clarify in docs that `flags` arguments can be platform specific + - !766 W32: swap special g_get_prgname() for platform_get_argv0() + - !774 Only build tests if certain conditions are met. + - !780 Add copyright and licensing terms to test report generator + - !781 gnetworkmonitornm: Fix network available detection + - !782 build: Fix check for RTLD_NEXT + - !785 Remove monitor test + - !787 build: Remove */.gitignore files + - !791 glib/gconstructor.h: Include stdlib.h for MSVC builds + - !792 general: Remove a few unhelpful references to ‘master’ + - !795 gdesktopappinfo: Add support for MATE and Xfce4 terminals + - !802 gio: tests, don't check for libdl on OpenBSD + - !806 Get to 100% coverage on GQueue tests + - !808 Update the Docker images used for CI + - !809 Modified version of !784 — Adding tests cases for a better coverage of glib/tests/strfuncs.c + - !813 gappinfo: Add precondition checks to GAppLaunchContext env methods + - !814 gschema.dtd: Add target attribute to alias + - !819 Clear signal handler + - !820 ci: Keep JUnit report script working on Debian stable + - !821 Various minor cleanups to autoptrs + - !822 glib: Update Unicode Character Database to version 12.1.0 + - !825 Add autoptr support for GRWLock + - !831 build: (Long time after) post-release version bump + - !835 Fix typo in German translation + - !836 Document the best practices for binding GInitiallyUnowned + - !862 build: define G_OS_UNIX, not G_OS_WIN32 under cygwin + +* Translation updates: + - Basque + - Catalan + - German + - Indonesian + - Spanish + + +Overview of changes in GLib 2.61.0 +================================== + +* Changes to `iconv` configure options, including the default iconv + implementation on macOS — distributors may need to check their configure + scripts (#1557) + +* Build fixes when building GLib with `G_DISABLE_ASSERT` defined (#1708) + +* Fix documentation for `gdbus-tool wait` to use correct units (#1737) + +* Improvements to symlink handling on Windows (!269) + +* Add exception handling for crashes on Windows (!582) + +* Set `G_WITH_CYGWIN` again when GLib is built on Cygwin (this was a regression + from the autotools build) (!736) + +* Use `GCocoaNotificationBackend` by default on macOS, rather than + `GGtkNotificationBackend` (!745) + +* Use Windows symbol visibility when GLib is built on Cygwin, as PE binaries + are subject to W32 visibility mechanics — this affects the definition of + `_GLIB_EXTERN` (!752) + +* Add coloured output support to `gdbus introspect` (!761) + +* Bugs fixed: + - #682 docs: advise not to use non-literal strings as qdata keys + - #1177 gparted crashes due to g_quark_from_static_string used in global initialization + - #1258 the buffer written to by g_input_stream_read is not marked as an out parameter + - #1557 By default glib tries to use libc instead of native iconv on OSX + - #1566 Meld Windows shows error on startup "There was a problem starting c:\Program" + - #1614 GIO tests fail on FreeBSD CI with: Unexpected error from C library during 'pthread_mutex_lock': Invalid argument + - #1708 Building GLib with G_DISABLE_ASSERT fails + - #1709 GResource generation test incompatible with stable LLVM on Linux + - #1710 Crash in g_cancellable_cancel + - #1712 gdbus-proxy test is flaky + - #1724 unconditional check in fuzzing/meson.build + - #1725 gosxappinfo.h is not installed on macOS + - #1727 Cannot use trash folder with an NFS mount using automount / autofs + - #1728 GSocket does not support ENOTSOCK + - #1732 Win32: lookup_by_name_async segfaults for not available domains + - #1737 gdbus-tool wait command timeout argument incorrect unit reference + - !67 glib: update internal gnulib from upstream + - !269 Win32 symlink code refactoring + - !493 tests: Check that cancelling g_file_replace don't overwrite existing file + - !582 Basic W32 exception handling for glib + - !680 Fix warnings glib + - !690 Fix thread safety issues + - !694 gvariant-parser: Fix pattern coalesce of M and * + - !706 Fix data races in task test and gmenumodel test + - !709 Bump release version for 2.62 series + - !710 socket: Fix annotation for flags in g_socket_receive_message + - !712 gwin32: Fix comment for g_win32_veh_handler + - !716 Various minor documentation fixes + - !717 Improve formatting of GCC attribute documentation + - !718 GSocketClient - Free last error if a connection attempt fails and on retry the... + - !719 Handle an UNKNOWN NetworkManager connectivity as NONE + - !721 codegen: Fix use of uninitialised variable + - !723 Provide examples for GNUC attribute macros + - !724 meson: do a build-time check for strlcpy before attempting runtime check + - !728 gsocket: Remove (type) annotation from flags arguments + - !730 Improve gdbus-address parsing tests + - !735 docs: Use the right g_autoptr function when using an auxiliary function + - !736 Set G_WITH_CYGWIN again + - !737 gresolver: Don’t use gai_strerror() on Windows, as it isn’t threadsafe + - !741 Fix use-after-free triggered by gnome-session-binary + - !745 gcocoanotificationbackend: give more priority than the gtk one + - !749 gio: Add missing autocleanup definition for GSettingsSchema{Key,Source} + - !750 Check for RTLD_NEXT + - !752 Use W32 visibility for Cygwin + - !754 Check for /proc/self/cmdline + - !757 Fix gnulib build on older Visual Studio builds + - !760 Properly ensure the cocoa notification backend type + - !761 RFC: gdbus-tool: Add --color option for introspect + - !762 gutils: Add (nullable) annotation to g_get_prgname() + - !765 gslice: Use a convenience macro + - !769 ci: Generate a cover report for the test suite + - !772 tests: Check that option-argv0 test succeeds on Linux + - !776 tests: Only run --external-data test on GNU ld/objcopy + - !779 Fix 2.62 documentation symbols + +* Translation updates: + - Dutch + + +Overview of changes in GLib 2.60.0 +================================== + +* Further fixes to the Happy Eyeballs (RFC 8305) implementation (#1653, #1679, #1693) + +* Add support for the XDG trash portal (#1676, !276) + +* Bugs fixed: + - #1653 gsocketclient-slow test is flaky + - #1658 keyfile settings backend: Consider tightening permissions + - #1668 Fill in CODE-OWNERS file + - #1675 glib-compile-resources: c_name generation issue + - #1676 Trash portal tries to open files as read-only but D-Bus API documents against that + - #1679 socket-service test is flaky + - #1693 Happy Eyeballs failure in gsocketclient-slow test + - #1697 gthreadresolver: do_lookup_records does res_ninit with an uninitialized state + - #1698 g_base64_encode(NULL, 0) causes critical warnings + - !276 Support the trash portal + - !639 gvariant-parser: Fix error handling when type coalescing fails + - !666 Socket fixes to W32 test suite + - !674 Update gvdb submodule + - !676 Initialize a variable + - !677 gerror: Add a missing precondition assertion in documentation + - !686 gio: Also support modules built with MSVC + - !688 gsocketclient: Fix critical on cancellation + - !689 glib-compile-resources: Fix a minor leak + - !691 gtask: Separate GTask fields memory locations to avoid data races + - !692 glib.supp: Add more variations of existing suppressions + - !696 Move closures refcount test to gobject/tests/ + - !698 gthreadedresolver: Remove unused thread pool + - !699 tests: Fix closure-refcount to preserve old semantics + - !702 Rename gobjectenumtypes.[ch] to glib-enumtypes.[ch] + - !703 Clean up gmarshal.[ch] + +* Translation updates: + - Catalan + - Czech + - French + - Friulian + - German + - Italian + - Korean + - Romanian + - Serbian + + +Overview of changes in GLib 2.59.3 +================================== + +* Fix support for g_get_user_special_dir() on macOS, including support for the Downloads directory (#1048) + +* Ensure that cancelling a GTask cannot cause its callback to be called synchronously (in the same call chain as the original *_async() call) (#1608) + +* Further fixes to the Happy Eyeballs (RFC 8305) implementation (#1644, #1680) + +* Various fixes for installation of installed tests (thanks to Iain Lane) (!649, !651) + +* Various fixes for tests when run on Windows (thanks to LRN) (!665, !667) + +* Bugs fixed: + - #535 gmacros: Try to use the standard __func__ first in G_STRFUNC + - #875 gio-gvfs on Windows: Don't mishandle other non-native URIs in gwinhttpvfs.c + - #1048 "Desktop" shortcut appears twice in file chooser sidebar on OSX + - #1608 Cancellation might not be asynchronous under certain circumstances + - #1644 network-address test failure in CI: IPv6 Broken (g-io-error-quark, 24) + - #1680 Regression: g_socket_client_connect_to_host_async() sometimes gets "Connection refused" when connecting to localhost + - #1686 gdbus-peer test is sometimes timing out + - !613 Use win32 io channel on windows for the protocol test + - !634 Win32: gio/gsocket.c: Set WSAEWOULDBLOCK on G_POLLABLE_RETURN_WOULD_BLOCK + - !638 gvariant-parser: Fix parsing of G_MININT* values in GVariant text format + - !640 tests: Tag socket-service test as ‘flaky’ + - !641 Minor typo fixes to GSpawn documentation + - !645 gsocketlistener: Fix multiple returns of GTask when accepting sockets + - !647 gsocketclient: Ensure task is always returned on cancel + - !648 gio/tests/task: Run the worker indefinitely until it's cancelled + - !649 gio tests: Install test1.overlay file when building installed tests + - !650 gstring: fully document semantics of @len for g_string_insert_len + - !651 tests: Install the slow-connect-preload.so library and use it + - !667 GSubprocess fixes for W32 test suite + - !668 tests: Mark gdbus-peer test as flaky + - !669 GWin32VolumeMonitor: Sort the volumes correctly + - !670 gpollableoutputstream: Fix the description of the interface + - !672 Fix some tests when running as root + +* Translation updates: + - Catalan + - Danish + - French + - Indonesian + - Kazakh + - Portuguese (Brazil) + - Slovenian + - Turkish + + +Overview of changes in GLib 2.59.2 +================================== + +* Fix check on GDBusMessage size when reading it. (#1642) + +* Add async GIO API: g_file_query_default_handler_async(), g_app_info_launch_uris_async() (#1249, #1347) + +* Fix some bugs in the Happy Eyeballs implementation. (#1646, #1649) + +* Install a new generated header with enum types for Unicode enums. (!481) + +* Support the XDG trash portal. (!276) + +* Bugs fixed: + - #1224 TSAN patches + - #1249 xdg-open/gnome-open doesn't work if service isn't started + - #1347 g_app_info_launch_default_for_uri_async is not really async + - #1376 gmarkup: Optimize g_markup_escape_text() + - #1642 minor mismatch between error and code in g_dbus_message_bytes_needed + - #1646 Criticals in g_socket_client_enumerator_callback() + - #1649 Critical in g_socket_client_connected_callback + - #1673 G_MININT constants broken in g-i + - !276 Support the trash portal + - !481 Define enum types for Unicode enums + - !585 gio: do not pass O_PATH file descriptors to portal APIs + - !593 Don't fail trash test if ~/.local doesn't exist or mount points can't be determined (master) + - !609 Make `g_app_info_launch_uris_async()` really asynchronous + - !619 gvariant: Fix a mistake in docs + - !622 Fixing warnings + - !626 gdbus: Avoid printing null strings + - !627 gsocketclient: Fix criticals + - !629 Various memory leak cleanups to GSettings tests (subset) + - !630 docs: Ignore more version macros + +* Translation updates: + - Galician + - Hungarian + - Lithuanian + - Polish + - Spanish + + +Overview of changes in GLib 2.59.1 +================================== + +* Autotools support is gone. (!580) + +* g_format_size() now uses a no-break space to separate digits and units; + translations will need to be updated accordingly. (#1625) + +* New g_queue_clear_full() API. (#1464) + +* Fix argument quoting on win32 when spawning subprocesses. (!419) + +* Allow polling more than 64 handles on win32 using g_poll(). (#1071) + +* Tag various tests as ‘flaky’. These are no longer run routinely on our + upstream CI machines, and downstream packagers may want to not run them (or + not treat those test failures as package build failures) on their test + machines either. They are in the `flaky` test suite. (!579) + +* Add overlay support to g_resources_get_info(). (#1445) + +* Support defaults and locks in the keyfile GSettings backend. This will be + used for flatpaks. (!450) + +* Accept unquoted strings in the keyfile GSettings backend to simplify things + for sysadmins. (!603) + +* Update our contribution guidelines (`CONTRIBUTING.md`). (!590) + +* Add writev() and writev_all() APIs to GOutputStream and GPollableOutputStream, + and provide implementations of them for many subclasses. (#1431) + +* Bugs fixed: + - #424 Add 'proxy' debugging support + - #1055 Provide alignment macros + - #1071 Eliminate MAXIMUM_WAIT_OBJECTS limitation in g_poll() on Windows + - #1445 g_resources_get_info doesn't respect resource overlays + - #1464 Add g_queue_clear_full() API + - #1500 GListStore needs double checking on some warnings + - #1623 xdg-open: file with colon results in “The specified location is not supported” + - #1625 Unbreakable space needed when showing size of folder/file + - #1636 GTask getters don’t return TRUE/FALSE after bitfield changes + - #1637 EXCEPTION_ACCESS_VIOLATION in g_clear_pointer + - #1639 GListStore implementation of g_list_model_get_item() returns wrong results on integer overflow + - #1655 gvariant-parser warnings + - #1663 G_MININT32 triggers compiler warning C4146 with Visual C++ + - #1666 `G_DEFINE_DYNAMIC_TYPE_EXTENDED` causes warnings with -Wcast-function-type + - !319 giomodule: Print the type of each default GIO module + - !333 Add writev() API to GOutputStream and GPollableOutputStream + - !419 gspawn, win32: qouted args - escape end backslash + - !450 Settings portal + - !512 gtype: Clarify type of GInterfaceInitFunc + - !516 gthread: Add g_private_set_alloc0() convenience API + - !535 win32 gpoll: overcome the 64 handles limit + - !545 goption: Fix an annotation on g_option_context_parse_strv() + - !560 docs: Fix dconf GSETTINGS_BACKEND name in gio overview + - !564 gtype: Document type for iface_default_init() function + - !568 Add separate definitions of g_assert_[non]null() for C++ + - !571 docs: Add note on how to check a gboolean condition + - !575 gio: Update bad cert error in accept-certificate and GTlsError docs + - !579 Temporarily disable flaky tests + - !580 Drop autotools support + - !583 gmacros: MSVC supports the noreturn function attribute + - !587 Remove unused .pc.in files + - !588 MSVC: Move dirent implementation to glib/dirent/ + - !590 Update contribution documentation + - !591 gfileinfo: Fix annotation for g_file_info_set_attribute_stringv + - !592 Remove leftover build/ directory + - !595 gtestutils: pass open file descriptors to subprocess + - !597 tests: Tag gsocketclient-slow test as ‘flaky’ + - !598 gdbus-proxy test fails with GLib-GIO:ERROR:glib/gio/tests/gdbus-proxy.c:832:fail_test: code should not be reached + - !599 gdtlsconnection: do not return on a void method + - !601 gio: Support "help" in extension point env vars + - !602 Update POTFILES.in + - !603 keyfile settings: Accept unquoted strings + - !608 build: Add -Wno-pedantic flag to compiler arguments + - !611 gnetworkaddress: fix use-after-free for network address + - !612 gdir: shutup a warning when building with msvc + - !615 Fix a couple of wrong compiler warnings + +* Translation updates: + - Spanish + - Swedish + + +Overview of changes in GLib 2.59.0 +================================== + +* This will be the last development release with autotools support. As our + Meson support has been around since 2.56.x, and was used to release tarballs + in 2.58.x, the next development release (2.59.1) will drop autotools as used + to build GLib. The macros installed for other packages to use will remain. + +* Add `G_TEST_OPTION_ISOLATE_DIRS` to redirect `XDG_*_HOME` to a temporary + directory for each unit test. (#538) + +* Support `Property.EmitsChangedSignal` annotations in `gdbus-codegen`. (#542) + +* Add `g_assert_cmpvariant()` API for unit tests. (#1191) + +* Hide bind mounts from GIO mount listings. (#1271) + +* Automatically realign data passed to `g_variant_new_from_bytes()` or + `g_variant_new_from_data()` if it is not correctly aligned. This prevents + misaligned accesses on architectures which don’t support them. Callers should + still aim to correctly align data to get higher performance. (#1342) + +* Support `ld -b binary` (on platforms which support it; i.e. Linux) to provide + large pre-compiled `GResource` resources with a fast compilation time. (#1489) + +* Unconditionally install GLib m4 macros, so that projects which depend on GLib + and which still build using autotools can continue to build even once GLib has + ported entirely to Meson. (#1520) + +* Various fixes to the Meson build. + +* Drop Python 2 support and require Python 3.4+. See discussion on + https://mail.gnome.org/archives/desktop-devel-list/2018-July/msg00004.html. + (!196) + +* `GHashTable` performance and memory improvements for common cases. See + https://hpjansson.org/blag/2018/07/24/a-hash-table-re-hash/. (!208) + +* Add flags that allow a `GApplication` to signal and replace a currently + running other instance of the same `GApplication`. This will be used for app + upgrades with flatpak. (!250) + +* Autostart xdg-desktop-portal when using the network monitor and proxy monitor + portal backends. (!317) + +* Add a g_task_set_name() API to allow `GTask`s to be described; useful for + debugging. (!384) + +* Enable FreeBSD CI on every commit for upstream GLib. (!387) + +* Various GVariant, GMarkup and GDBus fuzzing fixes, including buffer overflow + fixes. (!411) + +* Various fixes to eliminate thread races, found by thread sanitizer (tsan). + +* Deprecate TLS/DTLS rehandshaking, as it has been removed from the protocol in + TLS 1.3. (!478) + +* Support reading arguments from a file with `glib-mkenums`, which is useful + for long argument lists due to having deeply nested build directories, on + systems with a low limit on the command line length. (!489) + +* Make `g_environ_*()` case-insensitive on Windows, as the environment itself + is case-insensitive on Windows. (!500) + +* Add Application Layer Protocol Negotiation (ALPN) support to `GTlsConnection` + and `GDtlsConnection`, so that higher layer protocols can be negotiated when + setting up a TLS connection, without additional round trips and latency. This + is needed for eventual HTTP/2 support. (!520) + +* Add support for TPM keys in PEM files when loading TLS certificates. (!522) + +* Add a `GRecMutexLocker` auto-pointer wrapper for `GRecMutex`. (!528) + +* Bugs fixed: + - #107 The "g_key_file_get_comment" interface returns comment with unexpected new line symbol at the end + - #179 g_object_unref assert in debug code + - #277 'destroy_data' in g_cclosure_new is registered as finalize notifier instread invalidate. + - #538 Add helpers to redirect XDG_*_HOME to a temp dir for unit tests + - #542 gdbus-codegen does not honor "Property.EmitsChangedSignal" annotations + - #656 check for -Werror=format-security broken + - #734 Provide a way to instantiate a GDBusProxy-derived class from a GDBusConnection and a object path without blocking + - #827 gmain: Clarify that g_source_set_callback() is safe on attached sources + - #1055 Provide alignment macros + - #1119 GVolumeMonitor: Results don't reflect current state but state when application was launched + - #1191 add g_assert_equal_variants + - #1261 Add option to leave <default> in gschema empty + - #1271 fstab binds appear as mounts (x-gvfs-hide is being ignored) + - #1310 gdbusproxy: make g-name-owner property useful with unique names + - #1313 Meson: Rework the config.h generation + - #1342 Automatically realign data passed to g_variant_new_from_bytes() or g_variant_new_from_data() + - #1343 g_date_set_parse: Parses "September" in Polish incorrectly + - #1362 Incorrect documentation about GSettings child add/remove notifications + - #1452 GFileInfo: unable to retrieve correct modification time of links and mounted volumes on Windows + - #1471 Incorporate oss-fuzz fuzz targets into GLib + - #1489 Use `ld -b binary` to speed up GResource generation for linking + - #1498 distcheck fails in distclean + - #1506 error: redefinition of typedef 'GKqueueFileMonitor' + - #1509 test_timeval_to_iso8601_overflow: 'out' should be NULL + - #1513 GIcon regression? + - #1514 gio/appinfo test sometimes fails in CI + - #1518 /network-monitor/create-in-thread fails in (LXC) containers on glib-2-56 + - #1520 Change conditions for installing m4 macros + - #1522 Trash not working on NTFS folder accessed from symlink + - #1523 GIO NetworkMonitor doesn't reflect the current network state + - #1525 GTask allows (buggy) application code to cause callback to be called twice, without warning + - #1527 Meson doesn't install data for installed-tests + - #1528 Meson tests are hard to debug in an autobuilder environment + - #1530 tests/mainloop-test appears to be flaky + - #1535 meson: installed-test metadata not run in TAP mode + - #1536 meson: spurious dependencies on convenience libraries in .pc files + - #1537 meson: absolute paths to ${builddir} included in gtk-doc HTML + - #1538 meson: G_HAVE_GROWING_STACK defined differently + - #1539 meson: Some files are unnecessarily installed executable + - #1541 meson: timeloop-closure test not installed + - #1542 meson: /usr/lib/glib2.0/installed-tests/glib/gdbus-peer: error while loading shared libraries: libgdbus-example-objectmanager.so: cannot open shared object file: No such file or directory + - #1544 meson: gtester-report #! not replaced with ${PYTHON} + - #1546 Cross-compilation fails in 2.58 + - #1556 build: Too long file path issue with meson on Windows + - #1562 GDate test suite fails with latest glibc + - #1570 ghash.c:694:27: left shift of 1 by 31 places cannot be represented in type 'int' + - #1572 Flags validation fails + - #1575 g_date_time_format() should have format attribute + - #1576 Fails to build with Meson on Debian armel (armv5te EABI softfloat little-endian) + - #1580 glib-compile-resources using strings breaks building e.g. GTK+ on MS Visual C, which limits strings to 65535 chars + - #1581 Memory used for reference counted data might be misaligned. + - #1588 Moving a bookmark item to the same URI causes a crash + - #1589 g_log_writer_is_journald memoizes a single result, even though it accepts a parameter + - #1590 tests: g-file-info-filesystem-readonly fails if run more than once with fuse & bindfs installed + - #1594 Return value of g_dbus_connection_get_unique_name not annotated as nullable + - #1600 g_timeout_source_new_seconds overflows when given interval > (G_MAXUINT / 1000) + - #1601 appinfo test fix is defective + - #1605 g_date_time_format fails when used with non ASCII format string on POSIX locale + - #1615 gdbus-codegen not generating nullable annotation + - !196 [RFC] build: Drop Python 2 support and require Python 3.4+ + - !200 Add a new GTlsError to indicate protocol downgrade attacks + - !208 GHashTable improvements + - !219 glocalfilemonitor: Fallback to poll file monitor for NFS + - !238 W32 GFileInfo improvements + - !250 Application replace + - !264 glib-compile-resources: encode data as string + - !268 build: simplify alloca checks. See #1313 + - !272 dtrace: Add missing const attributes to types in glib_probes.d + - !273 gtlsbackend: add support for setting the default TLS database + - !277 Use "command -v" instead of "which" + - !282 meson: Add macOS libtool versioning for ABI compatibility + - !286 gspawn: Fix build on systems without O_CLOEXEC + - !287 glib-compile-resources: Fix generated code compiling with C++ compilers + - !289 tests: Add more tests to finish branch coverage of GHashTable + - !290 build: fix installation dir of glib-gettextize + - !292 Remove all ChangeLog files + - !293 Document new volume class `loop` + - !294 portal network monitor: Always emit changed signal on changed + - !295 meson: fix typo + - !296 Add G_GNUC_FALLTHROUGH for __attribute__(fallthrough)) + - !297 build: Drop AC_C_CONST from configure.ac + - !302 Document that GTimeVal is subject to the year 2038 problem on 32-bit systems + - !303 liststore: Simplify code + - !304 Add more GListStore/GListModel tests + - !309 codegen: Change pointer casting to remove type-punning warnings + - !312 Enable GIO tests on Windows + - !316 gdbus: Improve error when well-known name is unowned + - !317 Autostart xdg-desktop-portal if needed + - !322 gnetworkmonitornm: Set a GError properly on an error handling path + - !332 gmarkup: Make the documentation even more explicit about untrusted input + - !334 gio: automake: Add libgmodule dependency + - !338 gcharset: fix leaking g_get_language_names_with_category + - !339 Add g_desktop_app_info_get_string_list(); fix g_key_file_free() + - !340 tests: Mark two more tests as slow + - !345 Fix build failure on systems without POSIX spawn + - !347 Use Meson 0.48.0 for CI + - !348 Documentation tweaks for g_array_free + - !353 Meson: Do not run tests/refcount with --tap + - !354 Fix spelling mistakes detected by Debian's Lintian tool + - !358 Autotools: Move libmount from Libs.private to Requires.private + - !360 CI: Test static build on installed glib + - !363 Tests: Mark printf wrappers with G_GNUC_PRINTF + - !364 ci: Enable FreeBSD CI + - !366 gunixmounts: Mark mounts as system internal instead of filtering out + - !372 gmacros: Fix G_[UN]LIKELY to not mask -Wparentheses + - !374 gthreadpool: Include prgname in thread name + - !375 m4macros: Allow information from pkg-config to be overridden + - !376 gthread: Clarify priority handling in GRWLock + - !379 Ignore g_return_*if_fail() branches in lcov coverage report + - !381 Add UTF-8 communication tests for GSubprocess + - !384 gtask: Add a g_task_set_name() method + - !387 ci: Enable FreeBSD CI in the official repository + - !396 m4: Fix AM_PATH_GLIB_2_0 macro + - !400 grefcount: add missing gatomic.h + - !403 build-sys: Pass CFLAGS to $(DTRACE) + - !405 ci/msys2: fix path to the lcov config file + - !406 meson: Mark 1bit-emufutex test as slow + - !407 meson: Increase test timeouts + - !410 gfileutils: Add examples to g_path_get_dirname() documentation + - !411 Various GVariant, GMarkup and GDBus fuzzing fixes + - !412 Enable compile time check of g_date_time_format() format + - !413 Add support for g_auto(s)list to G_DECLARE'd types + - !414 gio, tests: ensure objectmanager sources are generated + - !415 gseekable: fix 'attmepting' typo + - !416 gdbus-peer: Make sure to not include objectmanager-gen.c source + - !417 Fix ^*ay handling in g_variant_iter_loop() + - !418 Meson: Cleanup a FIXME now that we have dict addition + - !420 gdbus-codegen: add autocleanup for FooObject + - !422 GMarkup buffer overflow fixes for error handling, round 2 + - !423 gutils: Check whether getauxval function exists + - !424 ci: Fix Docker image version + - !425 gdate: Reinitialize using_twodigit_years and locale_era_adjust. + - !435 gdatetime: Fix formatting of time zones offsets in range -01:00 to +00:00 + - !436 valgrind: Add glib_init()-related suppressions + - !440 Fix minor memory leaks in tests + - !443 tests: Avoid multithreaded use of g_test_rand_int_range + - !444 gvarianttypeinfo: Consistently use atomics to access ref_count + - !446 gmain: Fix data races in GUnixSignalWatchSource and GChildWatchSource + - !451 closures test: Avoid timeout on ARM64 CPUs + - !452 Atomic reference count in GVariant, ContainerInfo and GDBus introspection + - !453 tests: Fix some data races in tests + - !454 gdbusproxy: make g-name-owner property useful with unique names + - !458 glib-compile-resources: Fix size allocation for compressed streams + - !460 gatomicrefcount: Make g_atomic_ref_count_init non-atomic + - !461 Meson: Fix build error in gdbus-example-objectmanager + - !462 meson: add aarch64 memory barrier handling + - !463 gio, tests: fix leak of dbus connection. + - !467 Update documentation of g_tls_connection_handshake() again + - !469 docs: add index of new symbols for gio > 2.52 + - !470 docs: Clarify return/error behaviour of D-Bus signal subscriptions + - !472 gdbusmessage: Gracefully handle message signatures with invalid types + - !477 gthread: Remove unsynchronized access to g_once_init_list from assertion + - !478 Deprecate TLS rehandshaking + - !480 docs: add a missing semicolon + - !482 Check for 'z' library before fallbacking to subproject + - !483 meson: Turn selinux into a meson feature and make it auto by default + - !484 Meson: Add 'nls' option to disable translation + - !485 gdbus-codegen: Tag interfaces and properties so annotated with G_PARAM_DEPRECATED + - !486 Check for zlib header + - !489 glib-mkenums: Support reading @rspfiles for arguments + - !490 gspawn: Fix g_spawn deadlock in a multi-threaded program on Linux + - !491 Meson: Add missing include_directories when using glib as subproject + - !492 g_value_get_variant: return value is transfer-none not transfer-full + - !494 Resolve "Follow-up from "gunixmounts: Stop considering cifs/nfs as system file systems"" + - !500 genviron: make g_environ_* case-insensitive on Windows + - !504 tests: Unset LANGUAGE when running gdatetime tests + - !505 Support isolating directories for unit tests + - !508 ci: Install additional locales used during tests + - !510 Add new Linux Testing project version number to configure script + - !511 gvariant: Fix error handling for parsing Unicode escapes + - !514 fix gdbus-codegen --interface-info-{header,body} + - !515 binding: Clarify the use of g_object_unref() to remove a binding + - !517 Meson: Fix deprecation warning with upcoming 0.49.0 release + - !518 Meson: Fix declare_dependency() calls + - !520 GTlsConnection: add ALPN support + - !521 tests: Rename macro to avoid conflict with encoding prefix + - !522 gtlscertificate: Add support for TPM keys in PEM files + - !524 gdatetime: Fix typo in the comment + - !528 Add GRecMutexLocker + - !530 tests: Minor improvements to mkenums.py and taptestrunner.py used by it + - !534 gtlscertificate: Fix bug in PEM private key parser + - !536 Various minor docs fixes + - !541 gtimezone: Fallback to /etc/timezone on Gentoo + - !546 spawn: add shebang line to script + - !547 Do not check for NULL when calling free() + - !549 Improve documentation of g_assert_error() + - !551 Revert "tests: Fix GOptionContext leak in GSubprocess tests" + - !554 Only subscribe to owner-changed signals on message bus connections + - !555 Suppress -Wint-in-bool-context warning with G_DEFINE_INTERFACE and g++ + +* Translation updates: + - Brazilian Portuguese + - Czech + - Danish + - Greek + - Hungarian + - Lithuanian + - Norwegian bokmål + - Polish + - Slovak + - Slovenian + - Spanish + - Swedish + - Turkish + + +Overview of changes in GLib 2.58.0 +================================== + +* Tarball built with `ninja dist`, so if you want to build this release with + autotools (which is supported), you will need to re-run autogen.sh. This + release, and all micro releases in the 2.58.x series, support being built + with Meson or autotools. See: + https://mail.gnome.org/archives/gtk-devel-list/2018-June/msg00012.html + +* Fix cancellation of g_subprocess_communicate_async() calls. See !266. + +* Drop support for the __int64 type, which further breaks compilation on old + MSVC versions (before VS2013). See #1313. + +* Expose GSettings schema directory in gio-2.0.pc as `schemasdir`. See !274. + +* Support v3 of the xdg-desktop-portal network monitor API. See !265, !279. + +* Fix G_MODULE_SUFFIX on macOS when GLib is built with Meson — it should be `so` + rather than `dylib`. Projects that use Meson and the `g_module_build_path()` + API such as glib-networking should pass `name_suffix:` to `shared_module()` to + ensure that plugins continue to be called libfoo.so on macOS. See !280. + +Bugs fixed: + !280 meson: Always set G_MODULE_SUFFIX to `so` on macOS + !266 subprocess: Fix communicate_cancelled signature + !279 Revert "Add a gnet utility" (see !265) + !265 Network monitor again + !274 gio: Provide schemas directory information in pkg-config file + !239 gvariant: Fix more bounds checking in GVariant text format parser + !195 garray: add overflow checks before expanding array + #1497 g_strdup_printf warns on invalid format specifier with G_GUINT64_FORMAT on Win32 + !270 autotools: remove support for the __int64 type. See #1313 + !267 ci: Add an autotools job + +* Translation updates: + Czech + Galician + Indonesian + Italian + Kazakh + Korean + Turkish + + +Overview of changes in GLib 2.57.3 +================================== + +* G_GNUC_MALLOC’s definition has been tightened up to match an updated + definition from GCC. Many uses of G_GNUC_MALLOC which were previously + appropriate may cause miscompilation with newer GCC versions. Check your uses + of it against the updated documentation. See #1465. + +* Many minor documentation fixes. + +* Fix for gint64 and int64_t compatibility on macOS and BSD. See #972. + +* Fix free space metadata on some file systems (notably FAT). See #328. + +* Support installed-tests with our Meson build system. See #1444. + +* Forbid @filename@/@basename@ in glib-mkenums templates, which is a change to + its long-standing behaviour (which was long-standing nonsensical). See !241. + +* Various stat() fixes on Windows. See #1452, #1476. + +* MinGW-w64 ABI warning: In case you build 64 bit glib without LFS support by + passing --disable-largefile (not the default) and use GStatBuf, you need to + rebuild your application as the size of GStatBuf has changed for this case. + See #1476. + +* Improve TAP compatibility of g_test_incomplete(). See #1474. + +* Change fallback preferences when loading icons. See !72. + +Bugs fixed: + !263 build: Clean files left behind after gio/tests/gresource.c test + !262 gmem: Only evaluate pointer argument to g_clear_pointer() once + #1465 Many uses of G_GNUC_MALLOC are incorrect + #1448 g_error does not abort() as documented + #1494 g_clear_pointer may not use the correct calling convention with its callback + #972 Mismatch between gint64 and int64_t on 64-bit macOS/BSD + !251 gtestdbus: Fix watcher crash on FreeBSD + #1492 gcc-8: -Wcast-function-type: new warnings for g_list_copy_deep() + !252 tests: fix gnotification tests broken due to the recent icon name fallback changes + #328 filesystem::{free,size,used} not set for full FAT fs + !248 network monitor portal: update properties initially + #1373 Incorrect transfer annotation for g_binding_unbind. + #1444 the meson build doesn't support installed tests + #1027 Fix trashing on overlayfs + #1454 gvdb does not treat corrupt files as empty as promised; dconf suffers + !243 tests: Explicitly set TZ=UTC for g_time_val_from_iso8601() testing + #1488 ‘O_CLOEXEC’ undeclared (first use in this function) + !241 glib-mkenums: forbid @filename@/@basename@ in fhead and ftail + !240 gtimer: Ensure arithmetic is correctly signed for ISO 8601 parsing + #1452 GFileInfo: unable to retrieve correct modification time of links and mounted volumes on Windows + !234 DOC: Documentation fix in GTask description + #1363 Meson: Review cross compilation properties + !225 gtimer: Add overflow checks to g_time_val_from_iso8601() + !230 gbookmarkfile: Fix some more minor leaks when metadata elements are repeated + !229 Fix up g_bytes_compare() documentation + #1476 g_stat - possbile memory corruption causing SEGFAULT + !199 Update TLS documentation + #1474 g_test_incomplete() makes test_case_run() return FALSE + #1475 glib/tests/atomic.c test_types() trips -Werror=bad-function-cast on Debian armel + #1472 Test for BROKEN_IP_MREQ_SOURCE_STRUCT is broken on Windows / Mingw + !220 date test: Use g_test_skip(), not g_test_incomplete() + #1467 malloc difference causes refstring test to fail on FreeBSD + !230 gbookmarkfile: Fix some more minor leaks when metadata elements are repeated + #1466 Not Able to Build glib 2.57.2 in Mingw-w64 x64 bits + #1433 test_posix_parse: assertion failed (g_time_zone_get_abbreviation (tz, 0) == "UTC"): ("LMT" == "UTC") + #1446 Follow-up from "Document difference between g_assert() and g_assert_*() wrt G_DISABLE_ASSERT" + !206 grefstring: Avoid an unnecessary NUL assignment + #1458 g_volume_get_mount returns NULL value after g_volume_mount_finish is called with no error + !72 gio: icons should fallback to non-preferred style appropriately. + +* Translation updates: + Brazilian + Chinese (Taiwan) + French + German + Lithuanian + Polish + Romanian + Turkish + + +Overview of changes in GLib 2.57.2 +================================== + +* Require pcre 8.31 +* Require meson 0.47.0 + +* Bugs fixed: + 742456 Add g_steal_pointer() convenience function to mark ownership... + 795569 MinGW CI: fix tests + 796341 gmem.h: Use typeof() in g_steal_pointer() macro + #1013 Support for per-session overrides + #1360 glib-mkenums breaks if option specified but no nick + #1175 Add names and tags to various GSources and GTasks constructed in GLib + #903 g_main_context_wait() not deprecated in API, but emits a g_critical()... + #786 Fix memory leaks in libgio tests + #927 gio/gresource.c:do_lookup check for terminating "/" + #976 Document difference between g_assert() and g_assert_*()... + #1447 glib 2.57.1: test_month_names: assertion failed... + #1407 Update to Unicode Character Database 11 + #1455 glib python tools have full python path in shebang, limits to 128 characters + #1459 Missing g_return_val_if_fail in g_async_queue_timeout_pop + +* Translation updates: + Friulian + German + Romanian + Spanish + + +Overview of changes in GLib 2.57.1 +================================== + +* New api: + - g_hash_table_steal_extended + - G_GNUC_NO_INLINE + +* Bug fixes: + 668132 Use libmount and expose mount options on GUnixMountEntry type + 736741 Update private copy of valgrind.h + 748620 g_regex_* utf-8 validity requirements are not stated clearly + 784995 meson: some Windows improvements + 788771 NODELETE missing when built with meson + 788773 meson does not install correct pc files + 789968 Add g_autoptr() support for GTypeClass + 794325 Various fixes to compile on OSX + 795152 gdesktopappinfo: Mark GDesktopAppInfo constructors as nullable. + 795165 Add g_date_time_get_timezone() and g_time_zone_get_identifier() + 795180 Investigate performance impacts of recent compiler features on hot functions + 795302 Add g_hash_table_steal_extended() API + 795376 Add g_ptr_array_steal() + 795544 Add binary/textfile/zero size detection + 795569 MinGW CI: fix tests + 795636 gitlab-ci: generate test coverage reports + 795735 Fix comparison for GVariant property values + 795802 gdbus-codegen doesn't accept --output-directory with --output for --body and --header + 795849 gwin32: Fix detection of MinGW32 vs MinGW-w64 + 795876 meson: Fix checks for posix_memalign and stpcpy + 795960 g_format_size_for_display() is deprecated since 2.30 + 796085 Meson: Many apps breaks on non-glibc because of missing libintl + 796138 Fix typo in g_file_info_set_attribute docs + 796139 Add g_autoptr() support for GParamSpec + 796164 Fix atomic ops check in meson.build + 796186 Typo: "instead off" in gsignal.c + 796213 Meson: Fail to build on macosx + 796220 meson: do not run atomic test with msvc + 796264 Add android CI + 796325 meson: Add exception for atomic ops test for Android + 796328 gengiotypefuncs.py: Read and parse files in binary mode + +* Translation updates: + Czech + Indonesian + + +Overview of changes in GLib 2.57.0 +================================== + +* Bug fixes: + 739424 Rewrite kqueue GFileMonitor backend to drop threading + 751826 Use g_get_language_names() for other locale categories + 788773 meson does not install correct pc files + 793400 g_application_id_is_valid() not strict enough + 793578 gdatetime tests depend on Japanese translation of month names + 793645 test_month_names: Updated translations needed for el_GR, hr_HR, ru_RU + 793729 gitlab-ci: Add Windows MinGW support + 793994 GUnixVolumeMonitor doesn’t show user mounts when run as root + 794170 gdbus: hexdecode() and hexencode() do not return/use decoded/encoded s... + 794194 gobject_gdb.py: 'address' is a property of gdb.Value not a function + 794207 leak: g_socket_listener_add_inet_port increases ref-count on socket-li... + 794284 Support whitespace stripping for JSON resources + 794285 glib-compile-resources should not noisily g_printerr() when xmllint is... + 794473 Remove duplicated option in gio.xml + 794506 glib-mkenums: Enters infinite loop if using typedef enum SomeIdentifier + 794528 Fix segfault caused by use-after-free in GPollFileMonitor + 794555 glib meson build fails on MinGW due to misdetected functions + 794557 gtkdoc-scangobj fails on gio in meson builds + 794606 glib-2.56.0 fails to compile when res_nquery is not available + 794635 gmacros: Don't define bogus __has_* macros + 794636 G_HAVE_GNUC_VISIBILITY is defined in meson MinGW builds + 794686 Date (except weekday) displayed in English + 794732 Fix various compiler warnings + +* Translation updates + Hungarian + Slowak + Slovenian + Spanish + + +Overview of changes in GLib 2.56.0 +================================== + +* Bugs fixed: + 672777 Error in gdummyfile.c + 732184 GObject: warn on use of deprecated properties + 733338 Don't segfault in GNetworkMonitor when IPv6 support is unavailable + 742124 g_data_input_stream_read_upto()'s documentation should say that the... + 749206 GDateTime: month names in the genitive case + 768507 simplify qguark functions + 791457 Slow transfer rate when writing to smb/cifs + 793272 fix GCC 8.0's -Wcast-function-type warnings + 793300 g_hash_table_add() return value change in 2.40 not mentioned in docs + 793399 Fix some cases of -Wduplicated-branches + 793555 -Wimplicit-function-declaration when using g_abort() + 793565 GLib does not compile on macOS 10.13 due to .m file naming + 793597 gdbus-tool: Make --dest optional for emit again + 793635 Enable CI for GLib + 793880 gnetworkmonitor: Minor fixes based on code review + 793578 gdatetime tests depend on Japanese translation of month names + 794180 test_month_names fails unless installed + +* Translation updates: + Brazilian Portuguese + British English + Catalan + Czech + Danish + Dutch + Finnish + French + Friulian + Galician + German + Hungarian + Indonesian + Italian + Kazakh + Korean + Lithuanian + Polish + Scottish Gaelic + Serbian + Serbian Latin + Spanish + Swedish + Turkish + + +Overview of changes in GLib 2.55.2 +================================== + +* GFile now has API to get the path without copying + +* A network monitor implementation for Windows has been added + +* Bugs fixed: + 520116 g_utf8_strlcpy() + 584284 g_data_input_stream_read_until_async behaves confusingly different f... + 605700 request for g_key_file_get_locale() + 658713 ngettext (plural forms) needed for "Message has %d file descriptors ... + 685442 windows GNetworkMonitor implementation + 723003 gsettings list-recursively reports some keys multiple times + 749583 GSequence performance improvements + 757284 Move G_DIR_SEPARATOR* and G_SEARCHPATH_SEPARATOR* into glibconfig.h + 760324 [PATCH] gkeyfile.c: find_file_in_data_dirs fails to return the path ... + 761102 Increase performance for main loop + 767976 GFile: Add g_file_peek_path() + 770335 gdbus-codegen: generated getter for 'ao' property is actually (trans... + 772989 Totem allows invalid urls that might cause segfault that's irrecover... + 790698 convert: test failure on NetBSD + 791015 gdbus-codegen: Split generation of header and source + 791622 Disable strict-aliasing in GLib + 792050 GResolver is not thread-safe + 792217 Deprecate GTlsClientConnection:use-ssl3 + 792338 meson, autotools: figure out if mem barrier is needed for arm64 host... + 792351 gbookmarkfile: check length before dereferencing groups + 792364 gdbus-threading test method-calls-in-thread: assertion failed (elaps... + 792370 GNetworkMonitor: Rename "network-changed" signal argument + 792410 GDateTime new_from_iso8601 test broken in 2.55 on i386 + 792432 flush stdout after logging (debug) messages + 792455 Improve docs of GSequence + 792499 deadlock on startup with TCP session bus + 792516 gconvert: More consistent handling of embedded NUL bytes + 792777 g_notification_set_urgent() unconditionally sets G_NOTIFICATION_PRIO... + 792780 gbytes should reference toplevel bytes when slicing with g_bytes_new... + 792856 off64_t isn't a part of C standard + 792862 gpollableoutputstream: document side effects of WOULD_BLOCK on D/TLS + 792903 Clarification between g_try_.. functions and their counterparts + 793006 High CPU load for GUnixMountsMonitor consumers + 793026 possible mem leak in g_mutex_impl_new + 793074 g_message() does not get -Wformat warnings when compiling with G_LOG... + +* Translation updates: + Hungarian + Indonesian + Polish + + +Overview of changes in GLib 2.55.1 +================================== + +* Build: + - The --enable-rebuilds configure option has been removed + - The --with-charsetalias-dir configure option has been added + +* GList and GSList now have autoptr support + +* The gsettings list-schemas command has gained a --print-paths option + +* Bugs fixed: + 346816 Refactor LIBDIR in libcharset Makefile + 508976 Does g_slist_sort preserve the order of equal elements? + 562334 2.18.2 break libglade on Solaris + 662802 systemtap multiarch issue + 684282 Add support static link of GIO modules + 692034 Install an invalidation notifier for GClosure in g_source_set_closure() + 694723 Get rid of REBUILD stuff in configure.ac + 697715 floating point precision problem in check test gst/gstvalue + 701156 testgobject assumes that the priv data follows the instance data + 720380 Segfault when using GDBusMenuModel on a peer-to-peer connection + 724383 glib: document restrictions on various foreach() functions + 724412 GLib mappedfile.c test uses g_get_user_runtime_dir instead of a tempo... + 724794 Fix "on on" typo in tap-driver.sh comment + 732003 gnode: Eliminate implicit signed-to-unsigned integer conversion + 734479 G_VALUE_HOLDS etc. cause -Wcast-qual warnings for a const GValue * + 737677 gmain: Make GSourceCallback thread-safe + 741167 gdbus-codegen fix for boxed out parameters + 748534 gtest: if a subprocess assertion fails, print its stdout and stderr + 749527 add weak pointer helpers similar to g_set_object + 749652 compilation errors with gcc 4.8 + 754634 Update the list of Linux filesystem magic numbers used in get_fs_type + 756011 Fix up annotations for GBookmarkFile + 761102 Increase performance for main loop + 773980 GIR scanner doesn't interpret array type properly + 776147 gio/glocalfilemonitor.c doesn't handle case G_FILE_MONITOR_EVENT_MOVE... + 776195 -z nodelete configure check does not work on Solaris + 777075 Potential leak of memory pointed to by 'list' + 779413 Translated X-Geoclue-Reason string not used in a dialog window + 780309 gio/tests/appinfo build fails: gdesktopappinfo.c skipped on OS X + 780893 Reword licensing header for gdbus-codegen + 782057 Unit tests fail in run-assert-msg-test.sh + 784995 meson: some Windows improvements + 786796 gtk-doc build fails with meson + 788806 Impossible to build static glib via meson + 788936 Show mime type icons on OS X + 790416 g_date_time_format returns empty string on %r with German locale + 790588 Generated file missing from .gitignore + 790697 g_object_ref API should propagate parameter type + 790785 glib-tap: Add missing mkdir for .test generation rule + 790829 glib-genmarshal --body must not generate alias implementations + 790830 Mismatch between number of interface methods in text and example code + 790837 Meson: missing many configure options + 790839 GApplication command line: lacks parameter_string, summary and descri... + 790877 fix non-portable check in G_GNUC_CHECK_VERSION + 790894 Do not connect to the session bus when trying GProxyResolverPortal io... + 790896 docs/reference/README has broken link to http://www.gtk.org/rdp/ + 790914 gdesktopappinfo: Downgrade a warning to a debug message + 790934 gtester doesn't handle skipped tests + 790948 GSourceFuncs documentation is confusing: when will dispatch be called? + 791036 Guard for g_output_stream_vprintf makes no sense + 791128 C runtime complains about bad arguments on each g_log() call + 791221 po/README.translators has no useful information in 2017 + 791235 Fix gschema.dtd regarding flags. + 791267 Make gschema.dtd usable. + 791296 gtester-report: fix range usage when running as python3 app + 791318 GBytes: Improve documentation + 791325 Gio handling of thumbnail:: attribute namespace causes inconsistent b... + 791334 gbinding.c:898: The target object of type GNetworkAddress has no prop... + 791337 Crash opening URIs with g_desktop_app_info_launch_uris_with_spawn() + 791342 Add autoptr support for lists + 791460 meson: fixes for OSX + 791532 Implicit declaration of function ‘memcmp’ in gtestutils.h + 791622 Disable strict-aliasing in GLib + 791720 Criticals in gio/xdp-dbus.h leading to crash under flatpak + 791744 gmenumodel test sometimes fails: assertion failed (items_changed_coun... + 791745 not immediately clear whether g_test_slow() is in effect by default + 791906 GSocketListenerClass.event has wrong signature + 792064 gsettings list-schemas --print-paths + 792098 Binding: bind_property’s @notify func is nullable + 792099 gdbus-test-codegen: Cast to void* to printf "%p" + 792129 meson: skip optional linux/unix deps that default to true when buildi... + 792322 GLib-GIO:ERROR:gschema-compile.c:51:test_schema: child process (/gsch... + 792324 gkeyfile: Document need for KEEP_TRANSLATIONS with get_locale_string() + +* Translation updates + Hebrew + Indonesian + + +Overview of changes in GLib 2.55.0 +================================== + +* New API: + - g_clear_handle_id, to simplify removing sources from the default mainloop + - g_file_load_bytes, to make it more convenient to load files into GBytes + +* Bugs fixed: + 330458 Sample code for the GLib Key-value parser + 483341 g_error and friends create warnings when not used in MSVC + 569375 g[u]intptr undocumented + 573251 documentation for g_seekable_truncate() needs some love + 629347 Missing annotations in GFile (was: Perf throws an exception in cur... + 630983 [PATCH] Type accuracy for result of strlen() in string utilities. + 632953 Clarify documentation of GValueTransform. + 636210 Document that pre-unmount is not guaranteed and backend-dependant + 656502 type information for GSettings::backend missing from .gir + 661442 Nautilus crashes when refreshing home folder after modifying ~/.co... + 668035 gtester-report broken with python 2.7.2 and glib 2.30.1 + 670139 gbytes.c:try_steal_and_unref nit + 677233 (transfer full) annotation not correct for g_closure_new_simple re... + 679347 glocalfile seems to leak 'fstype' + 679467 Mention translation in g_warning() documentation + 689323 Variable scoping in gunixmounts.c + 691436 glib-mkenums output arch dependent + 695681 gsettings bash completion put error messages + 705331 AM_PATH_GLIB_2_0 macro fails with -Wstrict-prototypes -Werror + 706667 Fix permission denied error when installing from an nfs directory + 711809 gdbus-proxy: Fix erroneous timeout during following tests + 722256 gslist: Simplified node removal and got rid of some code duplication + 723655 Socket source is left in the poll after the socket is closed + 723743 g_child_watch_add() doesn't check for non-pids + 725014 g_settings_schema_source_ref should check for NULL pointer + 727346 docs: Escape some backslashes for markdown + 730296 gsignal: Fix a potential NULL pointer dereference + 731625 Improve test for darwin printf format-strings + 731705 gio/tests/desktop-app-info assumes /bin/true + 737278 Clarify relationship of g_application_quit() to hold count + 738176 Skip GSpawnChildSetupFunc closures in introspection + 740223 source_object for GAsyncResult should be nullable + 740791 gio: cannot specify the source when joining a multicast group (IGM... + 740826 glib doesn't know fuse filesystems + 742548 configure.ac: stay out of autoconf's namespace + 742997 Don't skip invalid enum values in schemas + 745723 -Wunused-but-set-variable work-around no longer sufficient + 749371 Use a GHashTable as a set when possible + 751738 Unused-variable warnings in glib/tests/autoptr.c + 752239 Missing dependency for python files in build file + 752240 Add DTLS support to GIO + 753459 GDateTime: Add conversion functions from/to ISO 8601 strings + 753521 g_subprocess_launcher_set_environ misses argument annotations + 754026 gfileutils: add some sanity checks + 756009 'const gchar* const *' gets incorrectly defaulted to utf8 + 756103 Skip g_base64_decode_step() in introspection + 756128 Fix up annotations in gconvert + 756430 g_rw_lock_reader_lock() can return without locking, or error + 756470 Fix up annotations in gdataset.c + 756588 Fix up annotations on data/qdata API of GObject + 760022 Memory leak in gvariant-parser.c + 760109 [PATCH] Invalid GDate can't be g_boxed_copy()'d + 760716 Fix documentation regarding <glib/gprintf.h> + 765063 Update annotations for gio + 765552 Please set serial in .m4 files to prevent autoreconf failure on up... + 767215 GCC version number is interpreted as start of a list in docs for g... + 767239 Tautological comparisons in convert tests + 769674 some GIO tests' arbitrary timeouts are too short + 769846 gmessages: Add timestamp to g_log_writer_format_fields() + 770459 Tutorial article is slightly wrong + 773355 Incorrect documentation about stopping a signal emission from a hook + 774083 spelling mistakes in glib: charater + 776562 Add Intel C Compiler support for G_GNUC_BEGIN/END_IGNORE_DEPRECATI... + 777308 GModule win32: disable error dialog popup + 777310 gio/gasynchelper.c: fix cast from pointer to smaller int type on w... + 777956 gmessages: Update advice for G_LOG_DOMAIN + 779182 xdg-open fails with gio open for some uris + 779501 Type of GIConv given wrongly on web + 780202 introspection: Don't expose GValueArray.free + 780296 xdg-open/gnome-open doesn't work if service isn't started + 781598 gstdio.h should #include what it needs to work + 781867 various gvfsd-* wants to look in /boot/efi, causes unnecessary/ina... + 783210 build: Switch to sassc for generating style + 783270 Improve Visual Studio support for Meson builds + 783825 Suggest that asynchronous operations should invoke the callback in... + 786737 No g_variant_get() example for dicts + 786785 Commit #fe2a9887a8 breaks gdbus-codegen, cannot find its module so... + 787271 Make GListModel usable from G-I bindings + 787485 g_tls_backend_supports_dtls () returns true when the backend doesn't + 787551 Factor out some duplicated code in GParamSpec validation + 787581 tests: Add tests for g_slist_copy() and g_slist_copy_deep() + 787671 meson: Fix permissions of installed scripts + 787731 g_file_query_filesystem_info() wrongly reports "filesystem::readon... + 788138 glib-compile-resources: Fix leak of a GHashTable + 788180 G_FILE_ATTRIBUTE_ID_FILE is useless on W32 + 788270 gmodule - failed to load symbol on Android 64bit + 788368 Race condition in GDbusObjectManagerClient + 788384 gtypes: Fix signedness of __builtin_bswap() usage + 788385 gtestutils: Explicitly cast args to g_assertion_message_cmpnum() + 788401 PATCH: MacOS build cannot detect content type from content - xdgmi... + 788467 Fatal errors and warnings should be reported as TAP + 788488 GFile-based API for g_build_filename() + 788489 gmain: add g_clear_source API + 788561 Document how to integrate GTest into your project + 788594 gdbus-tool doesn’t handle non-message-bus connections correctly + 788705 Allow building GLib on older Linux platforms + 788766 fixed a doc-typo in socket_get_remote_address + 788772 meson installs gdb scripts incorrectly + 788863 Add more filename type annotations for strings which can contain f... + 788880 gunixmounts: Update list of virtual file systems to ignore + 788927 Expose better API for detecting ‘system’ mounts + 788936 Show mime type icons on OS X + 788948 Document Autotools best practices for genmarshal/mkenums + 788975 Meson + Visual Studio: Can't find zlib.h with subprojects/zlib + 788978 Document XML has a syntax error + 788989 Use subdir-objects with Autotools + 788990 Include licensing information in output from glib-mkenums, glib-ge... + 789087 gint and guint misrepresented as functions + 789170 GFormatSizeFlags should have a value for bits + 789245 g_settings_bind() not conforming to lifecycle specification + 789444 Fix handling of length in g_utf8_make_valid + 789637 glib-mkenums: Fails when --ouput file does not exist + 789681 meson: Libmount support not built + 789723 [PATCH] gdbus-codegen: Call abspath() earlier + 789755 g_get_host_name: ensure return value is always UTF8 encoded + 789820 GPollFileMonitor is not cleaning up correctly + 790015 docs: Various linking and syntax fixes + 790030 GResource/GVariant fails to load from non-pointer aligned memory + 790093 gio-tool: fix inverted logic in monitor tool + 790126 gengiotypefuncs.py is missing from tarballs + 790147 build: Drop data-to-c.pl in favour of data-to-c.py + 790157 gmessages: Give examples of G_DEBUG with gdb in the documentation + 790272 file: add g_file_load_bytes() + 790275 avoid temporary string allocations in g_resources_enumerate_children + 790310 speedup path canonicalization in GResourceFile + +* Translation updates: + Catalan (Valencian) + Czech + German + Nepali + Norwegian bokmål + Slovak + Slovenian + Spanish + + +Overview of changes in GLib 2.54.0 +================================== + +* Bugs fixed: + 780861 Crash in GnomeWallClock + 786983 Please make the output of gio-querymodules deterministic + 787109 Valgrind false positive in ioctl() in btrfs file copy + 787123 glib: Slighty update GIOChannel documentation + 787146 GMainLoop: match of parameter pair of LOCK_CONTEXT/UNLOCK_CONTEXT + +* Translation updates: + Basque + Catalan + Romanian + Swedish + + +Overview of changes in GLib 2.53.7 +================================== + +* Bugs fixed: + 736710 remove unnecessary executions of libtool from configure + 785260 gio/tests/appmonitor fails if local dir not writeable + 786456 g_subprocess_wait[_check]_async() breaks when cancelled... + 786555 g_array_free() is not thread safe w.r.t. g_array_unref() + 786580 gdesktopappinfo.c: Add Tilix as a fallback terminal + 786807 g_uuid_string_random undefined when built with meson + +* Translation updates: + Brazilian Portuguese + Catalan + Czech + Danish + Finnish + French + Friulian + German + Italian + Kazakh + Korean + Latvian + Nepali + Polish + Spanish + Turkish + + +Overview of changes in GLib 2.53.6 +================================== + +* Bugs fixed: + 766358 glib doesn't respect XDG_* envvars on W32, ever + 783270 Improve Visual Studio support for Meson builds + 785955 pthread_setname_np misdetected with meson + 786060 Sequences documentation does not make it clear... + 786360 gobject: add autoptr support for GClosure + 786452 crash on Linux without stderr stream + 786460 gio-tool: Unify buffer sizes + 786462 Use g_output_stream_write_all instead of while + 786463 gio-tool-save: Prevent overwriting error + +* Translation updates: + Catalan + Galician + Hungarian + Indonesian + Lithuanian + Nepali + Serbian + + +Overview of changes in GLib 2.53.5 +================================== + +* Bugs fixed: + 695573 Untranslatable strings in glib-compile-schemas + 725950 GApplication: call dbus_unregister only once, and before destruction + 731703 giomodule test misbuilds its test modules as libraries + 769135 External control for g_test_add/g_test_run + 779332 Rewrite mkenums in Python + 779607 Race between mounts-changed signal and g_unix_mounts_get() function + 784000 Improve strerror_r() detection + 784815 Map G_NOTIFICATION_PRIORITY_HIGH to NOTIFY_URGENCY_NORMAL + 784965 Use the glib preset for i18n in Meson + 784995 meson: some Windows improvements + 785113 glib-mkenums Python port fixes + 785130 G_LOG_DOMAIN shouldn't be left undefined for applications + 785438 Spurious -Wmaybe-uninitialized in gdatetime.c + 785468 glib/gpoll: Unnecessary if conditional included in the poll_rest() function + 785520 Replace advice to use removed gdk_spawn functions + 785577 clobbers errno while setting GError + +* Translation updates: + Slovenian + Spanish + + +Overview of changes in GLib 2.53.4 +================================== + +* Unicode support has been updated to Unicode 10.0.0 + +* glib-genmarshal and glib-mkenums have been rewritten in python. + Every effort has been made to keep compatibility. Please report + problems related to these tools + +* GLib can now be built with meson. autotools are still supported + +* Bugs fixed: + 722047 drop makefile.msc? + 733821 g_strerror() uses strerror(3) instead of strerror_r(3) + 773842 g_utf8_find_next_char() won't signal the end of a NUL-terminated string + 779332 Rewrite mkenums in Python + 780095 g_utf8_get_char_validated() stopping at nul byte even for length specified... + 780634 Remove remaining old codepage ABI comapt code + 783841 test_GDateTime_new_from_timeval_overflow fails on 32 bit systems + 784000 Improve strerror_r() detection + 784020 GKeyFile – Add array length annotations to to_data(), get_keys() and get_g... + 784037 gio: Mention the ALL_METADATA flag in g_file_copy() + 784433 gdbus-codegen with variant type parameters result in nested variant + 784456 Update to Unicode 10.0.0 + 784528 Rewrite glib-genmarshal in Python + 784579 Calling g_dir_open on Missing Directory When Executable File Path Contains... + 784581 docs: Fix cut'n'paste error in g_resources_get_info() doc + 784739 Minor typo in configure error message + 784792 Just fixing a little typo in comments + +* Translation updates: + Hebrew + + +Overview of changes in GLib 2.53.3 +================================== + +* Bugs fixed: + 658446 Add translation comment for wrong password notice string + 661926 Improve the default logging setup in GLib + 674885 type initialisation deadlock in GObject + 775593 GIO cannot write symlinks on FreeBSD and NetBSD + 776169 Various gio-tool fixes + 776333 Fix annotation on g_file_copy_async() + 776504 Upgrade license from LGPLv2+ to LGPLv2.1+ + 777307 race condition between gdbus signal callback and g_bus_unwatch_name... + 778422 gsubprocesslauncher: Clarify the behavior of set_environ() + 781301 Stack pointer corrupted by incorrect call of NtNotifyChangeMultipleKeys + 782336 Add additional documentation of the GResource XML format + 782996 build: Use AM_TESTS_ENVIRONMENT rather than TESTS_ENVIRONMENT + 783061 GApplication: Remove some unused members + 783130 Make dbus activation sandbox-aware + 783193 Adapt to OpenURI api change + 783201 gdbus-codegen: Apply --output-directory to generated docs as well + 783340 win32: port monotonic times to use QPC + 783350 length parameter can be NULL g_data_input_stream_read_line + 783392 incorrect (out) annotation for g_dbus_interface_info_generate_xml + 783593 GGtkNotificationBackend should use /org/freedesktop/DBus to call Ge... + +* Translation updates: + Esperanto + German + Indonesian + Kazakh + Spanish + + +Overview of changes in GLib 2.53.2 +================================== + +* A few new number parsing functions have been added: + - g_ascii_string_to_signed + - g_ascii_string_to_unsigned + These have better error handling than the existing ones. + +* glib-mkenums now supports /*< private >*/ and /*< public >*/ + +* GSettings now consider XDG_DATA_HOME in addition to XDG_DATA_DIRS. + +* Bugs fixed: + 674885 type initialisation deadlock in GObject + 698064 Add g_ptr_array_contains() + 732000 gdatetime: Remove an unnecessary NULL pointer check + 734946 Implement GContentType on OSX + 741335 Possible differences in use of XDG_DATA_DIRS versus XDG base directory specification + 748263 Use-after-free in g_dbus_connection_call_internal() + 776876 gmodule – Various Android bug-fixes + 777030 build error where minor() and major() cant be resolved in gio/gdbusmessage.c + 780300 gio/gosxappinfo.c uses deprecated LSFindApplicationForInfo + 780309 gio/tests/appinfo build fails: gdesktopappinfo.c skipped on OS X + 781755 Avoid compiler warnings in generated marshallers code + 781826 portal support: Read /.flatpak-info + 781830 Fix some typos and errors in GVariant documentation + 781847 Use-after-free under send_message_with_reply_cleanup():gdbusconnection.c:1792 + 781867 various gvfsd-* wants to look in /boot/efi, causes unnecessary/inappropriate auto... + 782068 doc: Trivial typo fixes + 782075 gtimer: Handle gmtime() failure in g_time_val_to_iso8601() + 782089 gdatetime: Fix overflow checks when constructing from timestamps + 782162 Support public/private trigraph in glib-mkenums + 782237 make check error + 782311 inode/directory is treated as a subclass of application/octet-stream + 782628 libmount build dependency check not requiring the right version? + +* Translation updates: + Hungarian + Indonesian + Spanish + + +Overview of changes in GLib 2.53.1 +================================== + +* The gdbus tool gained a wait command + +* g_unix_signal_source_new support SIGWINCH now + +* There are now g_enum_to_string and g_flags_to_string functions + +* A new function to instantiate objects: g_objet_new_with_properties + +* GParameter and related APIs have been deprecated + +* Bug fixes + 447907 enum/flags from string + type transform + tests + 668962 GUnixMountPoint/GUnixMountEntry not usable through gobject-introspection + 669355 gdbus-codegen output contains stray semicolons at file scope (forbidden in C99) + 674885 type initialisation deadlock in GObject + 698064 Add g_ptr_array_contains() + 709865 Add boxing to GParameter + 725894 build: Include gettext libraries for static compilation on Mac OS X + 734946 Implement GContentType on OSX + 741229 gio: Handle NULL cached properties in NetworkManager monitor + 745971 gdbus-tool: Add a command to wait for a well-known name on the bus + 755046 gfileutils: Add precondition checks to g_file_test() + 761102 Increase performance for main loop + 761889 GDateTime: %p does not always print AM/PM string + 766660 Please clarify the extent to which GInitable, GAsyncInitable must be idempotent + 769534 g_unix_signal_source_new does not support SIGWINCH + 772221 Take advantage of Unicode + 775879 g_log_default_handler should not check G_MESSAGES_DEBUG + 776169 various gio-tool fixes + 777961 Documentation for g_app_info_equals() could be clearer + 778049 race in gsource detected by TSan + 778207 gio-querymodules: fix memory leak + 778287 G_MODULE_EXPORT and -fvisibility=hidden + 779409 Fix false positive g_warning() in remove_filter() + 780066 g_base64_encode_close() in glib/gbase64.c produces invalid base64 encoding + 780095 g_utf8_get_char_validated() stopping at nul byte even for length specified buffers + 780306 Unused function in gunicollate.c for CARBON + 780310 g_tls_database_verify_chain doesn't set the GError for failures other than cancell... + 780384 gio/tests/contenttype fails on OS X: "public.directory" != "public.folder" + 780441 Make the portal implementation of g_app_info_launch() synchronous + 780634 Remove remaining old codepage ABI comapt code + 780908 gobject: remove duplicate GType sanity check + 780924 Memory leak in gdbusmethodinvocation.c + 781125 gio-tool: Fix errors format string + 781234 the buffer written to by g_input_stream_read is not marked as an out parameter + 781298 gfileutils.c:330:3: error: ISO C90 forbids mixed declarations and code + +* Translation updates + Catalan + Friulian + German + Hebrew + Indonesian + Polish + Russian + + +Overview of changes in GLib 2.52.0 +================================== + +* Bug fixes: + 779799 gdatetime test fails with tzdata 2017a + 780032 Add missing attributes to two functions + 780144 gio/fam: Remove leftover debug print + +* Translation updates: + French + Friulian + Latvian + + +Overview of changes in GLib 2.51.5 +================================== + +* OS X implementations of GContentType and GAppInfo + have been added + +* Bugs fixed: + 673047 gunicollate is broken on OS X (patch included!) + 734946 Implement GContentType on OSX + 747146 Implement GNotification on OSX + 769983 glib-mkenums generates non-reproducible Makefile snippets + 777203 gnulib license information is not correct in glib2.0 + 778515 Crash in the gio kqueue backend + 779456 Make g_utf8_make_valid optionally take a length + +* Translation updates: + Danish + Friulian + German + Hungarian + Korean + Lithuanian + + +Overview of changes in GLib 2.51.4 +================================== + +* Memory leak fixes +* Fix the released tarball + + +Overview of changes in GLib 2.51.3 +================================== + +* Bugs fixed: + 771997 gchecksum: Add SHA-384 support + 778422 gsubprocesslauncher: Clarify the behavior of set_environ() + 778581 gdbus-codegen: Fix -Wconversion warning + 778801 gdbus-codegen: Add --outdir flag + 778991 Plug a mem leak in gdbusauth + 779183 g_io_extension_point_get_extensions should check for NULL pointer + +* Translation updates: + Basque + Chinese (Taiwan) + Danish + Indonesian + Italian + Serbian + + +Overview of changes in GLib 2.51.2 +================================== + +* Minimal support for UUIDs has been added + +* A new file attribute, G_FILE_ATTRIBUTE_RECENT_MODIFIED has been added + to improve sorting of recent files + +* Bugs fixed: + 639078 UUID support feature request + 777135 gkeyfile: Be more specific about error codes in documentation + 777307 race condition between gdbus signal callback and g_bus_unwatch_name... + 777481 goutputstream: docs: fix typos + 777493 g_mkdtemp() not introspectable + 777507 Recent view sorting incorrectly + 777592 Add minor examples to GDBus and GVariant documentation + 778002 race in gdbusprivate.c detected by the ThreadSanitizer + 778096 race in gdbusconnection reported by TSan + +* Translation updates: + Norwegian bokmål + Polish + Simplified Chinese + Slovak + Spanish + Swedish + + +Overview of changes in GLib 2.51.1 +================================== + +* glib-compile-resources grew a --generate-phony-targets flag + +* GLib now installs a valgrind suppressions file for GLib and GIO + +* Bugs fixed: + 666114 should have infrastructure to run its tests under valgrind + 729730 GDBusMessage: Fix segfault if DEBUG_SERIALIZER is enabled + 730932 statically assert that reasonable assumptions about enums are true + 735731 gobject: Document behaviour of GType checking macros on NULL + 736810 gdbus: Fix leak in g_dbus_message_print() + 762283 GSocket – Fix race conditions on Win32 if multiple threads are waiting on cond... + 767609 Test suite problems + 767952 g_dbus_method_invocation_return_*, g_dbus_method_invocation_take_error: They d... + 769672 Assert threads for testcase 642026 are sucessfully created + 769745 gtask: Add guards for public functions + 770175 Add command line argument to mkenums and genmarshal to write output to a file + 770646 glib: Namespace global tapset variables by soname + 772160 Add g_unix_mount_for() support + 772989 Totem allows invalid urls that might cause segfault that's irrecoverable + 773823 gio: Bump copy buffer size to 256k by default + 774086 fix g_main_context_check declaration + 774368 Dependency file output of resource scanner breaks Ninja + 774421 Two minor patches + 774520 GSocket allocates and processes control messages even if not requested + 775309 Crash in gdbusauth + 775468 Improve log write supports color method on windows + 775510 testing with -fsanitize=undefined reports various undefined behaviour + 775517 Password input is echoed in the terminal + 775621 gmessages: Fix compilation on Android + 775765 FDO notification withdrawal backend sends wrong ID to the server + 775913 subprocesslauncher: potential infinite loop in verify_disposition() + 776198 Stray semicolon after g_variant_print() function in gvariant.c + 776586 License headers cleanup + 777077 Use of memory after it is freed + +* Translation updates: + Brazilian Portuguese + Czech + Galician + German + Hebrew + Kazakh + Lithuanian + Spanish + Swedish + + +Overview of changes in GLib 2.51.0 +================================== + +* glib-genmarshal and glib-mkenums have gained --output options + for better build system integration + +* New API: g_utf8_make_valid + +* Bugs fixed: + 591603 Make _g_utf8_make_valid public + 610969 Nice to have g_utf8_make_valid as public + 767882 Bit shift overflow (-Wshift-overflow) warning in gparam.h + 769135 External control for g_test_add/g_test_run + 769630 gfile: G_FILE_MONITOR_WATCH_MOVES was actually introduced in 2.46 + 772160 Add g_unix_mount_for() support + 772221 Take advantage of Unicode + 773303 GApplication leaks option_strings + +* Translation updates: + French + Galician + German + Hungarian + Lithuanian + Norwegian bokmål + Occitan + Polish + Slovak + Turkish + + +Overview of changes in GLib 2.50.1 +================================== + +* Update Unicode support to Unicode 9.0.0 + +* Bugs fixed: + 662946 gunixmounts monitoring doesn't work correctly with libmount + 771591 Update to Unicode 9.0.0 + 772054 glib/gspawn-win32-helper.c: unexpected behavior re CommandLineToArgvW() + 772255 gresolver: Mark GResolver as an abstract class + 772269 Add --version options to glib-compile-resources and glib-compile-schemas + 772297 completion: Complete gsettings describe + 772511 g_log_default_handler crashes windows apps with "Unspecified fatal err... + +* Translation updates: + Brazilian Portuguese + Catalan + Croatian + Czech + Danish + Hungarian + Italian + Latvian + Polish + Swedish + + +Overview of changes in GLib 2.50.0 +================================== + +* Bugs fixed: + 771438 Turn on libmount by default on linux + Fix the annotation for g_log_variant + +* Translation updates: + British English + French + + +Overview of changes in GLib 2.49.7 +================================== + +* Add g_log_variant, binding-friendly api for structured logging + +Bugs fixed: + 646926 arg_data invalid after g_option_context_parse() fails + +* Translation updates: + Danish + Finnish + Galician + German + Hebrew + Kazakh + Korean + Latvian + Lithuanian + Polish + Portuguese + Serbian + Slovak + Spanish + Swedish + Thai + + +Overview of changes in GLib 2.49.6 +================================== + +* The gsettings commandline tool now has a describe command + +Bugs fixed: + 745754 Add gcc-style dependency output to glib-compile-resources + 769076 Fix warning: attempt to override closure->va_marshal with new marshal + 770372 gdbus-codegen: Strip @since parameters before comparison + +Translation updates: + Brazilian Portuguese + Czech + German + Hungarian + Polish + Portuguese + Spanish + + +Overview of changes in GLib 2.49.5 +================================== + +* Structured logging: + - drop libsystemd dependency + - document that g_test_expect_message does not work with structured logs + +* Use libmount for unix mount support + +* Add an async variant of g_app_info_launch_default_for_uri + +Bugs fixed: + 522053 GUnixMountMonitor needs to use /proc/self/mountinfo on recent Linux + 682794 Add usage guidance to logging documentation + 744456 Structured logging API + 766370 Add a macro for initializing g_auto(GVariantBuilder) + 767240 Regex failures with pcre 8.38 + 768198 Can't build glib with systemtap enabled + 768453 Gdbus test: compilation fails due to -Werror=format-y2k errors + 768752 Add async variant of g_app_info_launch_default_for_uri + 769027 Docs misleadingly imply G_CHECKSUM_SHA512 is available since 2.16 + 769029 gmessage: compiler complains about -Wformat-nonliteral + 769042 'O_CLOEXEC' undeclared (first use in this function) + 769087 gmessages: support NULL log domain + 769089 Fix gsettings uint64 testcase + 769104 Build failure when using _GLIB_CHECKED_ADD_U32 with the Intel compiler + 769139 g_log_writer_journald uses non-standard 'htole64' function + 769238 memory increases every time I umount and mount my secondary hard disk. + 769245 is_valid_heap_iter define misses NULL pointer check + 769507 gmessages: Don’t require is_journald() call before writer_journald() + 769785 gmessages: Expand documentation further for structured logging + 769995 gdbus-codegen: Allow '@since: UNRELEASED' in documentation comments + +Translation updates: + Catalan + Hebrew + Lithuanian + Slovak + Spanish + + +Overview of changes in GLib 2.49.4 +================================== + +* Change the just-introduced structured logging API. The arguments + of g_log_structured() had to be reordered to enable an implementation + within the limits of what the standards guarantee about var args. + +Bugs fixed: + 744456 Structured logging API + 768936 gio doc build fails because of missing gio.xml in the tarballs + 768963 improper va_list use in g_log_structured() + 768968 gio/tests/socket-listener hangs since e4ee307 + +Translation updates: + Spanish + + +Overview of changes in GLib 2.49.3 +================================== + +* GLib has a structured logging API, g_log_structured, with support + for writing to the systemd journal. It also supports colored output + in terminals + +* Some new GBytes API has been added: + - g_key_file_load_from_bytes + - g_compute_hmac_for_bytes + +* Stack-allocated GVariantBuilder and GVariantDict objects can now be + initialized with G_VARIANT_BUILDER_INIT and G_VARIANT_DICT_INIT + +* gio: + - Add a way to register handlers for custom uri schemes + - Add a G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE attribute to + have these heuristics in a single place + - Include a gio tool that makes the functionality of the + various gvfs commandline tools available in a single place + - Add portal support to g_app_info_launch_default_for_uri + - Add portal support to GNetworkMonitor + - Add portal support to GProxyResolver + - Add portal support to g_application_send_notification + +Bugs fixed: + 547200 g_utf8_find_next_char() issues + 662802 systemtap multiarch issue + 723506 fork/exec from non-main thread when autolaunching could be avoided... + 725902 build: simplify dtrace configuration + 728207 gsocketservice: Documentation does not mention that is already act... + 729914 instead of DEBUG_CODE and IF_DEBUG, provide a common macro to supp... + 744456 Structured logging API + 744678 Unable to delete relocatable schemas + 746685 clarify that g_variant_get_data() can be used instead of g_variant... + 747134 glib-compile-resources --generate should detect common C++ file ex... + 750257 GSettings changed signal should clearly state the order required + 753231 Memory is potentially used after free + 754012 missing filename in "Error loading css: Failed to import: Error op... + 760115 gtestutils: add missing dash in seed argument's --help documentation + 760423 gio-querymodules prints error messages as question marks on some l... + 761102 Increase performance for main loop + 765338 GLib.compute_hmac_for_data throws every time + 766370 Add a macro for initializing g_auto(GVariantBuilder) + 766899 Superflous HTML/XML comments in GDBusProxyTypeFunc documentation s... + 766933 GSocketAddress leaks in gnetworkmonitornetlink.c:read_netlink_mess... + 767765 Add names and tags to various GSources and GTasks constructed in GLib + 767880 gkeyfile: add g_key_file_load_from_bytes() API + 767887 vfs: add g_vfs_register_uri_scheme() + 767949 [patch] Typos in glib docs + 768029 infinite loop in parse_name_internal() + 768119 Fix fallout from get_supported_schemes() changes + 768357 Build the gio tool on Windows/MSVC + 768498 portal support for glib + 768504 keyfile: g_key_file_get_double behavior doesn't follow documentation + 768549 Test failure: test_ip_sync_dgram + 768551 Test failure: test_socket_address_to_string + 768560 gio/tests/gsettings: fix GSettings reference leaks in some tests + 768780 O_PATH is a non-standard flag which may be unavailable on non-Lin... + 768806 gdbus tool must swallow -- argument + +Translation updates: + Chinese (Taiwan) + French + Hebrew + Indonesian + Lithuanian + Portuguese + Spanish + + +Overview of changes in GLib 2.49.2 +================================== + + * GMainContext and GTask have gained more systemtap probes + +Bugs fixed: + 673101 resource compiler dependency generation not working for gen... + 700756 GFile.new_for_path arguments misses (type filename) annotation + 730187 glocalfileoutputstream: Fix an FD leak in an error path + 755439 Memory leak in gdbusproxy.c + 759813 Add more SystemTap/DTrace probes for main context and GTask + 761810 gio: Support using GDBusObjectManagerServer at path ‘/’ + 767172 docs: Move GIO_USE_VFS to "okay for production" section + 767218 Remove a UTF-8 ellipsis from gsignal.h + 767245 Add filename type annotations + 767824 Some UTC timezones incorrectly recognized on Windows 7 + +Translation updates: + Occitan + + +Overview of changes in GLib 2.49.1 +================================== + + * GDesktopAppInfo now allows bus activation with dashes. This is + not technically allowed per the Desktop Entry specification, but + it happens in the wild. Rather than forcing people to go through + another traumatic desktop file rename, accept it and translate - to _. + + * The support for giving names to threads has been improved. Thread names + are now supported on Solaris as well, and the Linux support no longer + uses prctl() but the pthread api. + + * GIO resources can now be overridden at runtime, using the G_RESOURCE_OVERLAYS + environment variable. + + * gdbus-codegen can now generate autocleanup definitions for the types + it generates. Use the --c-generate-autocleanup option to control this + +Bugs fixed: + 665446 Use g_abort() instead of abort() + 731988 glocalfile: Avoid a potential NULL pointer dereference + 742898 g_value_type_transformable() description differs from the code + 747107 GVariant varargs documentation: g_variant_get() example + 747478 g_system_thread_set_name() is not implemented for gthread-win32 + 748474 g_get_language_names() is not thread-safe + 748530 gthread: W32 implementation of g_get_num_processors() has lame fallback + 748806 GVariant: Better introduction to the concepts and its uses + 749583 GSequence performance improvements + 749606 tests: always remove app.desktop + 755898 [PATCH] settings: add get/set uint64 + 758174 Fix documentation typos + 758738 Usage of GType properties causes crashes due to gulong/gpointer mismatch + 760186 namespace clash with gdb pretty-printing code + 762994 Race condition in GIO/AppFileChooser crashes Firefox/Gtk3 + 763379 codegen: Add support for g_autoptr to gdbus-codegen–generated objects + 763821 build: Also dist Systemtap files always for gobject/ + 764092 gstrfuncs: Document the behaviour of g_strjoinv() + 764163 g_task_had_error doesn't remember the error after g_task_propagate_* + 764415 Very High CPU usage in g_poll() Windows implementation + 764574 build: Fix all statfs() tests failing + 764575 tests: Fix compilation errors due to Y2K format problems + 764685 GApplication documentation about handling command-line options is confusing + 764754 '-' in application id: unbreak bus activation and notifications + 765173 documentation of g_main_context_push_thread_default() regarding GIO... + 765668 GResources: add support for resource overlays + 765710 gdbus-tool: only print note about expected argument types if that... + 765712 tests: Fix compilation + 765861 task: avoid context lock when setting source name + 765900 Add g_drive_is_removable() support + 765924 Improve external drives detection + 765959 socket: set fd field to -1 after closing socket + 765990 Visual Studio: Define inline only when necessary + 765991 Compilation of gresource.c is broken due to S_ISDIR + 766092 Incorrect locale handling in g_date_time_format_locale() + 766211 Fix the upper bound in g_unichar_iswide_bsearch + 766407 Some build-related defects in glib testsuite + 766570 build: Fix a misnamed variable in glib-tap.mk + +Translation updates: + Basque + Catalan + Chinese + Occitan + Portuguese + Turkish + Vietnamese + + +Overview of changes in GLib 2.48.0 +================================== + + * a minor build fix in the name of determinism + + * a few coverity fixes + +Bugs fixed: + 763617 giotypefuncs.c: Sort _get_type functions in the 'C' locale + +Translations updated: + Danish + Italian + +Overview of changes in GLib 2.47.92 +=================================== + + * gdbus-codegen now supports g_autoptr() + + * g_get_user_runtime_dir() now reliably returns an existing directory + + * g_array_remove_range() can now remove 0 items from the end of an array + + * Many fixes for Windows + * build fixes + * file monitoring + * gsettings backend + * streams + * random numbers + * wide character support + + * documentation improvements + + * other small bugfixes + +Bugs fixed: + 724847 Segmentation fault on "gsettings list-recursively" + 743933 gapplication: add --app-id command line option + 756706 [PATCH] gio/gtestdbus.c: don't use non-standard %m printf modifier + 757506 gsettings: schema_list should use the passed schema's source + 760694 W32: Apps linked with -mwindows make cursor busy sometimes + 762202 g_win32_error_message improvements + 762637 build: Unconditionally dist tapset files + 762748 Undefined behavior + 762937 Mention that g_clear_error can be used with an "empty" GError + 763339 array: Support clearing an empty array with g_array_remove_range() + 763344 g_get_user_runtime_dir(): ensure directory exists + 763379 codegen: Add support for g_autoptr to gdbus-codegen–generated objects + +Translations updated: + Brazilian Portuguese + Czech + Finnish + French + Galician s + German + Greek + Hebrew + Hungarian + Italian + Kazakh + Korean + Latvian + Lithuanian + Occitan + Polish + Russian + Serbian + Slovak + Slovenian + Spanish + Swedish + +Overview of changes in GLib 2.47.6 +================================== + +* Windows usupport: + - Fixes and improvements to the GSettings registry backend + - Handle readability and writability of registry keys + - Use Unicode registry APIs + +* Bugs fixed: +760852 744772 761126 747927 761337 744570 761504 761550 761843 + 744570 GString is missing (transfer none) annotations on many of its methods + 744772 systemtap and gdb scripts install in wrong place + 747927 Documentation: various small improvements + 760852 gdbusobjectmanagerserver: Clarify recommended ObjectManager paths + 761126 winiconv: update to upstream version + 761337 Fix some annotations + 761504 W32 registry GSettings backend does not use Unicode + 761550 Cannot build with default flags under Fedora rawhide (-Werror=format-... + 761843 gmacros.h is testing attributes with __has_feature (when compiling wi... + +* Translation updates: + Brazilian Portuguese + Bulagarian + Chinese (Taiwan) + Hungarian + Polish + Slovak + Slovenian + Spanish + Swedish + + +Overview of changes in GLib 2.47.5 +================================== + +* the system copy of PCRE is now used by default to implement GRegex. + Configure with --with-pcre=internal if a system PCRE version + is unavailable or undesired. + +* interfaces for DTLS support have been added. A new version of + glib-networking will also be required. + +* GDBusMethodInvocation now drops replies if the sender set the + NO_REPLY_EXPECTED flag + +* several GApplication fixes, including fixes for commandline arguments + in interpreted languages on Windows + +Bugs fixed: + 624186 Deprecate glib-gettext macros + 734095 gtk-demo.py of PyGObject fails to run on Windows (and likely other binding scripts using g_application_run()) + 735754 Implement close on TLS GOutputStream + 748064 gnulib vfprintf returns desired (not actual) number of bytes, ignores errors + 752240 Add DTLS support to GIO + 755421 GDBus ignores NO_REPLY_EXPECTED flag in messages, leading to warnings on system bus + 756875 Include ntdef.h for NTSTATUS + 759554 g_application_run() calls g_main_context_default() repeatidly + 760199 gsettings: Install gettext ITS rules + 760215 G_LIKELY/_UNLIKELY macros need more parentheses + 760683 regex test: Check the expected PCRE exceptions at runtime + +Translations updated: + Brazilian Portuguese + Czech + German + Lithuanian + Swedish + +Overview of changes in GLib 2.47.4 +================================== + +* The GApplication documentation has been improved in several areas. + +* Bugs fixed: + 749092 gdb pretty-printers fail on Python 3 with a TypeError... + 757374 macros: clean up "inline" mess + 758641 Memory leak in g_dbus_proxy_new_for_bus_sync() + 759134 Add missing checks for gnulib vasnprintf() + 759408 Do not use uninitialized var + 756475 Stop supporting non-POSIX getpwuid_r, getgrgid_r + 757372 GApplication: destroy the impl on shutdown + 728099 macros: add G_GNUC_CHECK_VERSION() for compiler checks + 757299 glib-compile-resources: do not leak c_name + 758553 Fix gettext use + 758823 file monitors: reorder some code to avoid segfault + 756214 gsettings: Don't translate "" + 710243 Add GParamSpec object ref management annotations + 735696 xdgmime: Finer handling for cases where mmap() is not available + 752983 gapplication: Acquire the main context before running + +* Translation updates: + Swedish + + +Overview of changes in GLib 2.47.3 +================================== + +The inline cleanup in the last release accidentally removed three +symbols from libglib-2.0.so. It is unlikely that this will have caused +any problems because these symbols were only backup symbols for +definitions exported as inlines in the header files, but ABI is ABI. + +This release corrects only this problem. + +Overview of changes in GLib 2.47.2 +================================== + +* We have formalised the assumption that all compilers that are + interested in support 'static inline' and simplified the macros around + this considerably. Please watch for and report unintentional fallout. + +* New API: hardware-assisted helpers for overflow-checked integer math. + +* other fixes + +Bugs fixed: + 696324 gtester-report doesn't work with Python 3.x + 719966 glib: Add missing (nullable) and (optional) annotations + 752837 gobject and glib-compile-resources rely on .CRT$XCU section, no longer works with Win 10 UCRT (VS 2015) + 755364 make gtkdoc-check happy again + 756134 Segmentation fault on calling g_simple_action_group_add_action with bad action constructor call + 756179 gwin32.c: Replace VerifyVersionInfoW() with RtlGetVersion() due to API deprecation + 756988 GSequence should document each function's complexity + 757294 Move G_POLLFD_FORMAT to glibconfig.h + 757374 macros: clean up "inline" mess + 757451 doc: fix g_task_attach_source() example + 757628 gio tests fail to build when cross compiling 2.46.1 + 757693 Invalid free in g_local_file_trash() + 757742 Fix up annotations in ghash.c + 758181 GTask: fix wrong example code + +Translations updated: + Greek + Hebrew + Hungarian + Norwegian bokmål + Portuguese + Scottish Gaelic + Simplified Chinese + Spanish + +Overview of changes in GLib 2.47.1 +================================== + +* The Unicode support has been updated to version 8.0 of the Unicode standard + +* GDesktopAppInfo no longer sets the DISPLAY environment variable when + launching apps. This is now done in the GAppLaunchContext implementations + when appropriate + +* Bug fixes: + 664740 Key-value file parser, space after integer + 687223 cleverer GThreadPool management + 692085 stderr and stdout are not always file descriptors 1 and 2 + 697907 Add interface for socket-like things (GSocket, DTLS, etc) + 735754 Implement close on TLS GOutputStream + 737116 Add functions to print GSocketConnectables and addresses as strings + 743011 Minor additions to GError documentation + 749161 undefined reference to `__imp__stat32i64' + 749314 Cannot restore a just-trashed file + 751924 Add recvmmsg()-like API on GSocket + 752240 Add DTLS support to GIO + 752837 gobject and glib-compile-resources rely on .CRT$XCU section, no longer... + 753310 Remove `#pragma GCC system_header` from gmessages.h + 753935 Update example namespace and class names in GObject tutorial + 754855 Object instantiation documentation refers to example that no longer ex... + 754983 Wayland: g_desktop_app_info_launch_uris_with_spawn() forces DISPLAY va... + 754994 g_date_time_get_second () sometimes returns an off-by-one result + 755083 Clarify in G_ADD_PRIVATE that it is safe to call _get_instance_private... + 755351 Example still contains g_autoptr(gchar) + 755355 Move GStrv to glib.h so it can be used with g_auto() + 755374 g_variant_get_child(): flatten-first logic on '&' + 755496 glib 2.46 fails GStreamer test suite + 755609 glib 2.46.0 breaks Sun Java JVM 1.8.0.60 + 755766 gvalue: The g_auto cleanup function assert if value is G_VALUE_INIT + 755795 2.46 considers empty files as octet-stream rather than text (leads to... + 755961 Fix up annotations in gbytes.c + 756053 MSVC doesn't understand the symbol 'msghdr' + 756054 MSVC linker error due to 'g_socket_send_message_with_timeout()' + 756077 testutils: remove internal ABI comment + 756099 g_main_context_query(): Annotate @n_fds as (in) parameter + 756139 musl: ctors called in the wrong order + 756179 gwin32.c: Replace VerifyVersionInfoW() with RtlGetVersion() due to AP... + 756251 The documentation of G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START is confusing + 756255 GOutputStream swallowing errors in splice with G_OUTPUT_STREAM_SPLICE... + 756316 GSequence should provide fast api to check if empty + 756382 snprintf used on Windows with VS2015 doesn't support %n + 756477 gio/gthreadedresolver.c has outdated copy of bionic headers (for android) + 756550 gtypes.h: Make G_MININTn literals negative + 756875 Include ntdef.h for NTSTATUS + 756952 giomodule: return a copy of module name + +* Translation updates: + Basque + Czech + Serbian + Serbian Latin + Vietnamese + + +Overview of changes in GLib 2.46.0 +================================== + +* Disable runtime-deprecation warnings + +* Fix marshalling of flags on bigendian 64bit architectures + +* Translation updates + Brazilian Portuguese + Danish + German + Latvian + Russian + Turkish + + +Overview of changes in GLib 2.45.8 +================================== + +* utf8 validation and utf8-to-ucs4 conversion are faster + +* Small speedups to property change notification + +* Various other small optimizations for GQuark, GData + +* Bugs fixed: + 696426 GParamSpecTypeInfo do not need to be static + 735429 Cleanup MSVC Project Files Generation + 738504 Optimize UTF-8 decoding by unrolling branches and expressions + 742903 Add missing (transfer) annotation to GString + 748633 g_set_object order of operations + 754431 Fix build of glib/gstrfuncs.c on Windows + 754560 gioerror: Add more mappings for WinSock error codes + 754582 Glib cannot compile + 754601 Make g_strerror work with non-glibc POSIX systems + 754636 tests/unicode-encoding test fails for glib 2.45.7 on x86-64 + 754788 more g_strerror stuff + 754831 autocleanups: Add GString type + 754924 Improve test coverage of g_utf8_validate() by added known-... + 754986 Avoid unnecessary signal emission during draw + +* Translation updates: + Italian + Kazakh + Korean + Lithuanian + Slovenian + Swedish + + +Overview of changes in GLib 2.45.7 +================================== + +* Add G_FILE_ATTRIBUTE_STANDARD_IS_VOLATILE for use by non-POSIX-like + backends (e.g. cloud storage). + +* GFileMonitor: Make the inotify backend work with atomic renames again + +* GSettings: change notification is again working unconditionally + +* GListStore has a sort function now + +* Test infrastructure: + - Tests are now required to have unique names + - TAP support has been improved + - A macro for asserting that two memory regions have identical content + has been added + +* Bugs fixed: + 708525 A "g_file_query_info" on the file path "/sys/kernel/debug/hid"... + 742849 inotify: send paired events to both sides + 744060 Update GObject tutorial documentation to use G_DECLARE_FINAL_T... + 747364 Fix GError leak in g_file_query_writable_namespaces() + 749492 Support file creation time on FreeBSD and NetBSD + 752769 (g_socket_receive_message | g_socket_send_message) performance + 753745 glib-genmarshal still needed for cross-compilation + 754152 Add g_list_store_sort + 754211 Memory leak in g_file_enumerator_iterate () + 754264 GLib 2.44 certificate chain construction fails if the PEM incl... + 754283 gtestutils: add g_assert_cmpmem() + 754284 gtestutils: print the TAP test plan first, not last + 754286 misc gtestutils fixes + 754307 size of array '_GStaticAssertCompileTimeAssertion_3387' is neg... + + +* Translation updates: + Chinese (Taiwan) + French + Galician + Greek + Hebrew + Hungarian + Indonesian + Polish + Portuguese + + +Overview of changes in GLib 2.45.6 +================================== + +* Fix a test failure and a build failure + +Overview of changes in GLib 2.45.5 +================================== + +* GNetworkMonitor now provides information about metered networks + +* g_mem_set_vtable has been deprecated; it has not been working for + quite a while. The recommendation is to use valgrind, or replace + malloc itself. + +* Bugs fixed: + 656325 Make GDBusInterfaceVTable binding friendly + 741779 Documentation tweaks addressing real-world API misuses + 741822 Fails to build with VS 2015 + 742386 gdbusconnection: Don't g_printerr() when exiting + 743018 gobject: Add more cross-links between documentation pages + 750282 Add g_network_monitor_get_network_metered() to get if the connection... + 751358 GFileMonitor doesn't react to "mv some-file watched-file" + 751592 Stop using GMemVtable + 751598 Stop 'handle-local-options' propagation when callback reports an err... + 751610 g_str_hash produces collisions with strings of length 2 + 751751 Wrong docs of g_async_queue_remove + 752210 gdbus command crashes with SIGSEGV + 752656 gdbusconnection: Fix signal subscription documentation + 752767 Fix typo in g_hash_table_replace() documentation + 753278 gdbus: Don't use g_assert_no_error() GDBusObjectManagerServer + 753285 g_menu_item_set_icon fails if called with NULL icon + +* Translation updates: + Catalan + Czech + French + Indonesian + Lithuanian + Norwegian bokmål + Slovak + Spanish + Thai + Turkish + + +Overview of changes in GLib 2.45.4 +================================== + +* Bugs fixed: + 727829 win32: glibconfig.h.win32 updates + 741901 Clang cannot know that g_error don't return + 746339 GSocket kills process when fd is not a socket + 747676 gio/tests/socket fails: test_fd_roundtrip + 748610 Some tests fail with non-English locales + 749911 g_inet_address_to_string broken on XP/2003 + 749912 g_inet_address_new_from_string broken on XP/2003 + 750625 Should dismiss Software Updates Available notification after... + 750807 G_BREAKPOINT doesn't work as intended on Darwin + 751160 gtask does unnecessary work + 751672 -Wduplicate-decl-specifier in glib/tests/keyfile.c + 751731 GFile/DirectoryMonitor emit move events with other_file=NULL + 751737 gio/tests/appmonitor test fails in 2.45.3 + 751798 Wrong enum type used in some test-cases + 752089 make gsocketservice::active a property + 752293 small cleanup: use list_free_full + +* Translation updates: + Greek + Hebrew + Portuguese + + +Overview of changes in GLib 2.45.3 +================================== + +* Improve performance of g_signal_handler_disconnect for signals + with many handlers + +* GDBus has gained a new call flag to allow interactive authorization + +* GSettings: + - New API: g_settings_schema_list_keys + - Deprecated: g_settings_list_keys + +* OS X: + - Implement GNotification + - Bump the OS X requirement to 10.9 + +* Windows: + - Add registry reading API + - Reimplement GAppInfo using registry information + +* Bugs fixed: + 666831 Support URI opening on W32 + 728489 property action with inverted boolean state + 730168 Incorrect annotation on g_action_group_get_action_state_type return... + 733325 Several regex tests fail with pcre3 8.35 + 734888 GLib has no helper functions to work with W32 Registry + 737009 signal handler lookup doesn't scale + 738185 Misleading language about "file name encoding" in the docs on g_env... + 738504 Optimize UTF-8 decoding by unrolling branches and expressions + 739122 glib not handling -1 return ("no limit") from sysconf (_SC_THREAD_S... + 739424 gnome-shell crashes when files are added, deleted, or modified in $... + 739616 DBus; Add new call flag to allow interactive authorization + 740308 Add g_settings_schema_list_keys() method + 740516 RFE: please provide an introspectible version of g_log_set_handler + 741788 Document GSettings build system integration + 745013 GBinding not thread safe + 747146 Implement GNotification on OSX + 747941 try XDG_RUNTIME_DIR/bus before falling back to X11 autolaunch (dbus... + 748727 Filechooser dialog shows no icons for directories on W32 + 749693 GActionGroupExporter: flush queue on requests + 750203 GNetworkMonitorNetlink hangs in user namespace + 750322 gapplication: Make sure --help output is translated + 750344 GTlsInteractionClass is missing from doc + 750369 Various GBinding cleanups + 750386 Race condition in g_io_condition_get_type + 750399 Typo "equilalent" in glib documentation's glib-Error-Reporting.html... + 750573 GTlsDatabaseClass is not documented + 750918 genmarshal: silence register storage class warnings + 751122 gsocket: avoid unnecessary g_socket_cond_wait() in _send_messages() + 479730 The "g_key_file_set_comment" interface prepends '#' character to... + +* Translation updates: + Hungarian + Spanish + + +Overview of changes in GLib 2.45.2 +================================== + +* Improve error reporting in glib-compile-schemas. + +* Add introspection annotations to GListStore. + +* Bugs fixed: + 696749 win32 : failed to compile because of careless mistake in the code + 723394 const parameter to GtkPopover gtk_popover_set_pointing_to + 724113 gdbus-connection-loss test can fail on slow machines + 725981 tap-driver.sh: internal error getting exit status + 733325 Several regex tests fail with pcre3 8.35 + 744895 Unknown or unsupported transport 'this-should-not-be-used-and-will... + 747882 gtype: Bump allowed number of children + 748534 gtest: if a subprocess assertion fails, print its stdout and stderr + 748612 de_DE locale used in option-context test is not supported by FreeBSD + 748614 Double unref in g_socket_listener_add_inet_port + 748834 glocalfilemonitor: Emit notification on rate limit change + 749079 gdbus-peer test: TCP tests can fail with ECONNRESET due to a race... + 749080 gdatetime test: fails if close to rollover between seconds + 749180 gnetworkaddress: add return type annotation to parse methods + 749352 g_binding_unbind() fails when source is also the target + 749353 GBinding does not connect to the detailed notify signal + +* Translation updates: + Catalan + French + Slovak + Thai + + +Overview of changes in GLib 2.45.1 +================================== + +* The GSettings schema compiler, glib-compile-schemas has been changed + to reject schema xml that has duplicate <summary> or <description> + elements. Such elements typically occur when translations are merged + into the schema, with xml:lang attributes. This is not the correct + way to translate schemas. Instead keep the translations in the .mo + file and set the gettext-domain attribute on the <schemalist> element. + +* The file monitoring infrastructure has been rewritten, and all backends + have seen major improvements. + + The inotify backend is reporting events with less delay (no event will + be delayed more than 10ms) and wakeups due to file monitoring have been + significantly reduced. A CHANGES_DONE event will also be sent when new + files appear. + + The poll implementation is now using the thread default main context. + + The fam implmentation is now running in the worker thread. + + The fen implementation has been removed, since it was unmaintained. + +* The GSettings schema compiler, glib-compile-schemas, is more strict + about rejecting schemas with xml:lang style merged translations. + Schema translations should be done by specifying the gettext domain + in the xml, and keeping the translations in gettext. To avoid breaking + already-installed schemas, this change is only taking effect when + you use the --strict option. + +* The hardcoded 10-thread limit of GTask's thread pool has been removed, + since it was prone to causing deadlocks. The thread pool is now allowed + to grow dynamically and will shrink back over time. + +* GSimpleAsyncResult has been deprecated in favor of GTask. + +* The algorithm used by GAppInfo to find default handlers for mime types + has been tweaked to prefer apps that handle the specific subtype over + default handlers for a generic supertype. + +* Bug fixes: + 627285 inotify file monitor hardwired delay + 631597 Segmentation fault in append_escaped_text + 661767 merge/improve various bits of run-in-thread functionality + 687223 cleverer GThreadPool management + 711547 win32: silence some build warnings + 719966 glib: Add missing (nullable) and (optional) annotations + 726447 Possibly an error in text string + 728663 W32: wrong stat struct is used when built with MinGW-w64 + 728669 W32: GLocalFile can't measure size of files larger than 2^32... + 730188 gsocket: Document FD ownership with g_socket_new_from_fd() + 733325 Several regex tests fail with pcre3 8.35 + 738207 Add a way to set SO_SENDBUF and SO_RECVBUF on listener (and... + 739850 GClosure: add valgrind hints + 741791 gmain: Save errno when handling unix signals + 744282 gvfs-open for application/x-virt-viewer changed behaviour bet... + 745255 Add support for copying sessions between GTlsClientConnections + 745745 gdbus: fix out-of-bound array access + 745821 Don't use __alloc_size__ attribute with clang + 746749 GLib-GIO:ERROR:inotify-kernel.c:327:ik_source_dispatch: ass... + 746753 Glib-compile-resources --generate-header not using ".h" as ... + 747209 glib-compile-schemas ought to reject repeated <summary> and... + 747349 Conversion of gdbus to use GTask causes deadlocks + 747363 gatomic: Add missing new line in API doc comment + 747472 Don't ignore already-installed schemas with multiple <summa... + 747541 gdbus segfaults with invalid --dest + 747772 Having hardcoded utf8 strings in the source code does not p... + 748019 gsocketconnection: Fix copy-pasto in documentation + 748177 not all test schemas are distributed, "make distcheck" fails + +* Translation updates: + Basque + Czech + Danish + Finnish + German + Hebrew + Icelandic + Norwegian bokmål + Russian + Turkish + + +Overview of changes in GLib 2.43.92 +=================================== + +GLib is now considered frozen. We do not expect any major changes +before the release of 2.44.0. + + * GUnixMountMonitor now properly supports multiple main contexts + + * many documentation improvements and cleanups. We are now + approaching a point where the documentation is 100% complete and the + xml will build without warnings. This will probably be enabled by + default in the next cycle. + + * new support for HTTP proxies in GIO + + * new GTask:completed property + + * use "private" futexes in order to further improve the performance of + the contended case of GMutex and g_bit_lock() + +Bugs fixed: + 614684 Make various parts of GObject const-correct + 730352 Use inet_pton(), if_nametoindex() and if_indextoname() for newer versions of Windows + 733876 Proxy protocol 'http' is not supported. + 741442 threads: use FUTEX_WAIT_PRIVATE and FUTEX_WAKE_PRIVATE if possible + 742599 Clean up GUnixMountMonitor + 743636 gtask: Add a GTask:completed property + 743661 g_win32_check_windows_version() is missing from doc + 744722 docs: Expand introduction to mention using async calls over sync ones + 745589 [Patch] gio: add some missing autocleanup + 745634 [GNotifications] Use themed icon as icon-name + +Translations updated: + Bosnian + Bulgarian + Catalan + Czech + French + German + Greek + Hungarian + Italian + Kazakh + Korean + Latvian + Lithuanian + POTFILESin + Polish + Russian + Serbian + Slovak + Slovenian + Spanish + Swedish + Vietnamese + pa for Gnome + +Overview of changes in GLib 2.43.91 +=================================== + +We have now added 'g_autofree' as a libgsystem-style autocleanup macro +that calls g_free() on the content of a local variable when it leaves +scope (working only on GCC and clang). + +GApplication now has an "is-busy" property, allowing one to query the +effective busy state. + +There have been various other bugfixes and cleanups. + +Bugs fixed: + 661554 GIO's use of GError is wrong + 744263 Fix format specifier for __LINE__ in G_OBJECT_WARN_INVALID_PSPEC + 744565 gapplication: add bind_busy_property() + 744747 Add g_autofree + 744756 Can't find out if gapplication is marked as busy + 744830 autocleanups: Add GArray and GPtrArray + 744876 Unclean exit from from g_application_run + 745239 g_property_action_new missing type annotation + +Translations updated: + Chinese (Taiwan) + French + Galician + Lithuanian + Slovak + +Overview of changes in GLib 2.43.90 +=================================== + +* new GSimpleIOStream class to construct a GIOStream from an arbitrary + GInputStream and GOutputStream + +* GApplication: new API for marking 'busy' state according to the value + of a boolean property on another object + +* GOptionGroup: add binding support (boxed type, annotation fixes, etc.) + +Bugs fixed: + 739724 Test functions should have async scope + 741024 glist: Mention that g_list_length() is bad for checking list emptiness + 741630 Add GSimpleIOStream class + 743349 goption: Add boxed type for GOptionGroup + 743990 GDBus connection closing is broken + 744565 gapplication: add bind_busy_property() + +Translations updated: + Greek + Italian + Norwegian bokmål + Russian + Slovenian + Swedish + +Overview of changes in GLib 2.43.4 +================================== + +* GType now has type declaration macros G_DECLARE_DERIVABLE_TYPE, + G_DECLARE_FINAL_TYPE and G_DECLARE_INTERFACE, which significantly reduce + the boilerplate needed for GObject types and interfaces. + +* g_autoptr and g_auto are macros for declaring variables with automatic + cleanup. They only work with gcc and clang. + +* GListModel is a new interface that represents a dynamic list of GObjects. + +* GListStore is a GSequence-based implementation of GListModel. + +* Support thread names on OS X + +* g_simple_action_set_state_hint: New function to set the state hint + of GSimpleActions + +* g_win32_check_windows_version: New function to check Windows version + +* g_settings_schema_list_children and g_settings_schema_key_get_name + are new functions to complete the GSettingsSchema API. + +* Bugs fixed: + 389585 G_DEFINE_TYPE hack for header files + 729351 Add GListModel + 736914 Docs: various fixes and improvements + 741807 Add thread name support on OS X and iOS + 741895 gwin32: Add Simple API to check whether we are on at least a v... + 742456 object: Add g_steal_pointer() convenience function to mark own... + 743508 polkitd fails to start: patch for gio/gcredentialsprivate.h + 743517 GSettings API is missing some introspection functions + 743521 GSimpleAction: add g_simple_action_set_state_hint + 743596 G_DECLARE_DERIVABLE_TYPE() should allow additional typedef for... + 743640 add __attribute__((cleanup)) support + 743827 Fix build of GListModel (on Visual Studio) + 743927 GListStore: add sorted insert function + 743936 glib: handle unsigned modifier for long long in internal printf + 744012 Add GMutexLocker + 744190 Fix build on Compilers That Do Not Use inline for Plain C Code + + +Overview of changes in GLib 2.43.3 +================================== + +* add g_set_object() convenience function + +* GNetworkMonitor: check if NM is not running and don't crash + +* fix some races with g_mkdir_with_parents + +* fix some warnings in MSVC + +* avoid use of G_STRLOC in G_OBJECT_WARN_INVALID_PSPEC in order to save + on static strings + +* fix some content type vs. mime issues + +* documentation improvements + +* Bugs fixed: + 719455 g_file_make_directory_with_parents() can erroneously throw G_IO_ERROR_EXISTS + 732439 GSocket: avoid unnecessary g_socket_wait_condition() for blocking sockets + 734946 Implement GContentType on OSX + 741589 gobject: Add g_set_object() convenience function to set GObject pointers + 741653 gnetworkmonitornm: Check if network-manager is running + 741654 [patch] gobject: don't use G_STRLOC in G_OBJECT_WARN_INVALID_PSPEC() macro + 741707 Gsocket blocks trying to send data + 741788 Document GSettings build system integration + 742548 configure.ac: stay out of autoconf's namespace + 742851 avoid MSVC warnings in G_STMT_END + 742972 ggettext: Include an example of setlocale() and friends in the i18n docs + 743014 gtestutils: Add an example of using test fixtures + +* Translations updated: + Basque + Brazilian Portuguese + Spanish + +Overview of changes in GLib 2.43.2 +================================== + +* New function: g_strv_contains + +* New function: g_network_address_new_loopback + +* New function: g_socket_send_messages + +* A new GNetworkMonitor implementation using NetworkManager provides + more detailed connectivity information + +* Bugs fixed: + 11059 Linux poll issue + 664562 captive wifi portal support for GNetworkMonitor + 685880 Add g_strv_contains() + 712570 Hang in g_threaded_socket_service_func + 719646 GSocket: add g_socket_send_messages() to send multiple messages... + 728928 Provide separate error code for "Connection reset by peer" + 732317 Support GSocketConnectable for loopback addresses + 740814 "make check" should ensure that every symbol is documented + 740848 Backend subscription fails when connecting to a signal with a d... + 741016 gio: add G_IO_ERROR_NOT_CONNECTED + 741226 keyfile: Add "in group" to GError message consistently + +* Translation updates: + Gujarati + Hebrew + Hungarian + Kannada + Turkish + Vietnamese + + +Overview of changes in GLib 2.43.1 +================================== + +* GQueue now accepts NULL as a sibling in g_queue_insert_before() and + g_queue_insert_after() + +* Bugs fixed: + 11059 Linux poll issue + 726037 Add G_PARAM_READWRITE value to the GParamFlags enumeration + 727988 GMemoryOutputStream hangs when writing more than 1GiB + 729739 tlscertificate: add support for loading certificate chains + 733791 GSettings: delay backend subscription + 736286 Clarify g_file_replace behavior with etags + 736620 GQueue: accept NULL sibling for insert_before() and insert_after() + 737150 GLib-GIO-WARNING **: Failed to parse translated string 'visible-name... + 737160 unhelpful error message + 738259 GDBusInterfaceVTable: clarify memory handling for the method() virt... + 738551 'interface' variable conflicts with Windows defines + 738633 Need to disable SSLv3 in glib-networking + 740157 <app> --help doesn't work even when options were added + 740309 Fix docs in g_strfreev + 740413 Fix the GSettings Registry Backend + +* Translation updates: + Norwegian bokmål + + +Overview of changes in GLib 2.43.0 +================================== + +* GObject gained a debug option to provide instance counts. To use it, + set GOBJECT_DEBUG=instance-count and call g_type_get_instance_count(). + +* GOption now has a strict POSIX mode in which it stops parsing arguments + as soon as a non-option argument is encountered. + +* Bugs fixed: + 354457 Feature Proposal: Per-Type Statistics for Instantiable GTypes + 695082 g_hash_table_remove_all is not save against a call to g_hash_table_remove + 723160 GOption: add strict posix mode + 728256 gcredentials: add NetBSD support + 729739 tlscertificate: add support for loading certificate chains + 733338 Don't segfault in GNetworkMonitor when IPv6 support is unavailable + 736273 gdesktopappinfo: Use symbolic names in the code + 736284 Keep only one list of signal emissions + 736806 gtask: Fix reference count loop causing leaks + 736914 Docs: various fixes and improvements + 737143 Include <stdint.h> in glib/valgrind.h + 737259 gcancellable: Clarify that GSources hold references to GCancellables + 737338 gmain: Unref child sources when finalising a GSource + 737446 tests: Fix some minor leaks in the unit tests + 737451 Provide api to read_all_async + 737741 g_datalist_id_get_data assertion fails for non-existant keys + 737869 GApplication command line handling breaks --help + 738170 g_byte_array_new_take() doesn't initialize array->alloc + 738197 g_cond_timed_wait() doesn't time out on Mac OS X + 738374 gfile: g_file_equal (x, x) is TRUE + 738675 GSubprocessLauncher is missing some data on the docs + +* Translation updates: + Bengali (India) + Bulgarian + Gujarati + Italian + Telugu + + +Overview of changes in GLib 2.42.0 +=================================== + +All changes in this release are trivial in nature. + + - introspection warning fixes + + - g_application_add_main_option now uses an enum instead of an 'int' + for the type of a parameter + + - added a G_OPTION_FLAG_NONE so that people don't need to use 0 + + - gresource: Use GError in more places + + - gresource commandline tool: improve extraction from multiple sections + + - GSource now takes the context lock (if any) in g_source_set_name() + + - new documentation to clarify the use of some APIs related to + GVariant, GSource, GApplication + + - other minor updates to docs + +* Bugs fixed + 736683 Thread safety issues with g_main_context_find_source_by_id + 736975 [patch] please document that GVariant serialization needs an + out-of-band length field + +* Translation updates + Danish + Hindi + Marathi + Punjabi + Serbian + Simplified Chinese + +Overview of changes in GLib 2.41.5 +================================== + +* Bug fixes: + 735819 single native credential struct used for two purposes + 735915 glib-building.html uses --enable-gcov instead of --enable-coverage + 736350 GDesktopAppInfo: avoid polling on missing desktop dirs + 736351 Don't use issetugid() on Android + Fix the default application logic in GDesktopAppInfo + 736458 Only use rand_s() when targetting Visual Studio >= 2005 + +* Translation updates + Galician + Hungarian + Indonesian + Kannada + Latvian + Polish + Russian + Slovenian + Tamil + + +Overview of changes in GLib 2.41.4 +================================== + +* GApplication now has binding-friendly API to handle + commandline options: g_application_add_main_option + +* G_GNUC_BEGIN_IGNORE_DEPRECATIONS works with clang + +* Bugs fixed: + 583330 poll list of mounted file systems (no mtab support) + 727455 Command line option parsing from bindings + 734126 add G_GNUC_BEGIN_IGNORE_DEPRECATIONS macro for clang + 735179 gsocketclient: Handle cancellation between CONNECTING... + 735297 Docs claim that GThread struct is deprecated + +* Translation updates: + Assamese + Catalan + Catalan (Valencian) + Czech + French + German + Greek + Hebrew + Korean + Oriya + Traditional Chinese + + +Overview of changes in GLib 2.41.3 +================================== + +* g_clear_pointer and g_clear_object no longer use atomics + +* Bugs fixed: + 711547 win32: silence some build warnings + 725511 Compiled resource files should have the same /-separators everywhere + 725513 Some tests fail to build on W32 + 725514 W32: gfileutils does not preserve errno correctly + 725515 test-printf fails on W32 + 728730 gsocket: Set SO_NOSIGPIPE on sockets on Darwin + 729703 Leaks a GError in g_file_move + 730932 statically assert that reasonable assumptions about enums are true + 732085 gtype: Fast-path for g_type_is_a + 732754 GDBusMessage: optimise (de)serialisation of fixed arrays + 733345 ginetaddress: Add a precondition to g_inet_address_new_from_string() + 733576 Patches from static analysis run on 2.40 + 733715 glib's configure.ac makes accidentally use of nested function + 733934 win32: improve the package installation dir lookup + 733960 W32: spawning a console process creates a new window when stdout... + 733969 Remove atomic aspects of g_clear_pointer/object + 733982 Do not crash when checking whether an instance type is of a given... + 734035 gedit hangs up when there's no GSettings key in the registry + +* Translation updates: + Basque + Brazilian Portuguese + Lithuanian + Slovenian + Spanish + + +Overview of changes in GLib 2.41.2 +================================== + +* The Unicode support has been updated to version 7.0 + of the Unicode standard + +* GNotification now supports priorities for notifications + +* GCredentials has gained NetBSD support + +* GMutex now uses a faster, native implementation on Linux + +* Bugs fixed: + 699132 Pluggable event loop backends + 720708 g_assert_warning(): number of arguments doesn't match for... + 722092 Add GtkApplication resources support + 724986 Change gio/data-to-c.pl to /usr/bin/env perl. + 727974 Fix up failure-to-see-expected-message logging + 728256 gcredentials: add NetBSD support + 728401 GDateTime: Add guards to g_date_time_new() + 729825 Formatting of g_alloca documentation + 729914 instead of DEBUG_CODE and IF_DEBUG, provide a common macro... + 730293 clang++-3.4: error: 'register' storage class specifier is ... + 731339 giochannel: avoid setting uninitialised length + 731424 #ifdef spaghetti for load_user_special_dirs() implementations + 731623 GNotification: add support for a priority setting + 731929 update tables to unicode 7.0.0 + 731950 gvalue: New g_value_from_instance + 731986 GLib: implement GMutex natively on Linux + 732184 GObject: warn on use of deprecated properties + 732357 Docs: various fixes and improvements + 732429 GActionEntry: improve documentation + 732465 Fix build on x64 Visual C++ builds + 732704 Docs: various fixes and improvements + 732739 ginetsocketaddress: Explicitly initialise flags for getaddr... + 732754 GDBusMessage: optimise (de)serialisation of fixed arrays + 732984 g_object_ref(NULL) in g_dbus_object_manager_client_finalize + 733084 Typos in g_bytes_hash() and g_time_zone_find_interval() docs + 733146 spawn helper does not use correctly the parameters + +* Translation updates: + Lithuanian + + +Overview of changes in GLib 2.41.1 +================================== + +* Bug fixes: + 697229 Custom Interface implementations will be broken with glib 2.37/38 + 698614 GObject: prevent installing properties after init + 729269 gvariant: Fix confusion between type and format strings in the docs + 730198 broken valgrind.h leads to crashes in g_type_free_instance on mingw64 + 730807 GMutex performance regression + 730963 gconvert: mention that the g_convert len should be in bytes + 730984 Faster instance type check for fundamentals + 731050 <structname> tags appear in documentation + 731200 unconditional 'notify' during g_object_set() is problematic + 731335 gtype: guard uses of new fundamental type check + 731341 gparam: change value of G_PARAM_EXPLICIT_NOTIFY + 731366 run-assert-msg-test.sh gdb leaves assert-msg-test zombie + 731425 giomodule protects function-call with different token than function... + 731513 clang: build failure: implicit declaration of function '__atomic_load_4' + 731584 gbookmarkfile: Cleaner error handling code to pacify static analysis + 731657 Prevent an invalid @CARBON_LIBS@ from appearing in the .pc files + 731979 docs: Correct param to interface's default_init() + 731996 Return folder as icon for directories + 732002 gwakeup: Clarify buffer sizing in g_wakeup_signal() + 732005 Remove unused assignments + 732019 gtestdbus: Don’t close stdout for dbus-daemon + 732068 gsignal: Add an example to the g_signal_connect_swapped() documentation + 732081 gsocket: Document that g_socket_create_source() holds a socket ref + 732107 gsocketlistener: Reconsider closing sockets on listener finalisation + + +Overview of changes in GLib 2.41.0 +=================================== + +* Many bugfixes found by static analysis, including potential fd leaks + and NULL pointer dereferences. + +* Increased use of (nullable) attribute on out values and return types + now that it is supported (mostly from porting Vala metadata). + +* use XDG_CURRENT_DESKTOP for OnlyShowIn/NotShowIn handling of desktop + files, deprecating g_desktop_app_info_set_desktop_env() + +* add support for g_desktop_app_info_get_implementations() to find + desktop files that have an Implements= line for a given interface + +* GHmac has gained SHA-512 support + +* support the new mimeapps specification (most notably, moving the + assoications/defaults configuration to ~/.config/mimeapps.list). + +* libgobject is now linked -Wl,-z,nodelete when possible to avoid errors + when gobject is used from a module for a program that does not itself + use gobject and that module is unloaded/reloaded + +* ... and many other bug fixes. + + 623552 glib warns if backtrace.py is not present + 667468 glib-2.30.2: ipv6 tests fail when no ipv6 support is available + 668152 -framework Carbon linker flag not passed to pkg-config .pc files + 707298 libgobject should be linked with -Wl,-z,nodelete + 712391 Add g_desktop_app_info_get_implementors() + 722723 Infinite recursion when calling g_io_stream_close_async() from libsoup + 724741 hmac: Fix support for SHA-512 in GHmac + 726040 networkaddress: fix parsing of uri with @ after authority + 726318 gio: Document that GSocket is not thread safe + 726611 socketclient: Leak on cancellation + 726872 gio: Add names to idles and timeouts + 727119 wrong IN6_IS_ADDR_MC_LINKLOCAL usage break android build + 727123 GNotification: Some small documentation fixes + 727320 docs: Remove escaping '\' from literals + 727551 Check use_count of GApplication in g_application_release() + 727559 g_file_copy: Don't set GError when we intend to ignore errors + 727692 gio/gtlscertificate.c -- broken PEM-file processing (affects local CA root stores, for starters) + 727890 soup_content_sniffer_real_sniff segfault + 727900 gio: Add newer dbus UnknownXxxx and PropertyReadOnly errors + 727928 gapplication-tool fixes + 727939 INTLLIBS are always appended in configure checks + 727964 g_io_extension_point_get_extension_by_name: Warn, but don't crash, for NULL inputs + 728040 Implement new mimeapps spec + 728066 Deal with startup notify id being NULL + 728280 platform_get_argv0: fix sysctl(3) use on OpenBSD + 728285 docs: Use markdown links in .h files, too + 728350 gaction: Minor clarifications in the GAction documentation + 728380 docs: Remove <!-- --> comment before plural s + 728565 gfile: More explicitly document the context for GFileProgressCallback + 728983 Docs: various fixes and improvements + 729167 gobject: Document that classes/objects/interfaces are zero-filled + 729563 GOption: A short option's value is included in G_OPTION_REMAINING + 729813 AppInfo: use XDG_CURRENT_DESKTOP for OnlyShowIn + 729875 gio: cleanup gdbusmessage.c file + 730045 Avoid overeager warning about deprecated properties + 730189 gtestutils: Fix a very unlikely FD leak in test fork handling + 730190 gsocket: Add missing preconditions to g_socket_send_message() + 730277 gthread: Fix use of a local variable after it went out of scope + 730278 gsubprocess: Add a missing va_end() call + 730295 gdbus-tool: Remove dead variables + 730493 Port annotations from Vala metadata + +Translations updated: + Basque + Brazilian Portuguese + Catalan + Czech + Danish + Greek + Hebrew + Hungarian + Punjabi + Serbian + Slovenian + Spanish + Ukrainian + +Overview of changes from GLib 2.39.91 to GLib 2.39.92 +===================================================== + +This is a release candidate for 2.40.0. + +There are no major changes in this release, but a few serious bugs have +been fixed. + +* Bugs fixed: + 710367 Crash in g_settings_backend_dispatch_signal() + 723899 G_DEFINE_TYPE() causes compiler warnings with clang due to foo_get_instance_private + 724859 Let the test_wait_until() test also run on non-*nix + 724916 gio unmount code makes XFCE's Thunar crash + 725651 GSubprocessLauncher: Does not copy the calling process environment. + 725656 Unskip GVariantDict + 725891 gio tests: add codegen to BUILT_SOURCES + 726046 Recent commit created symbolic icons issues + +* Translations: + Chinese + French + Korean + Latvian + Norwegian bokmål + Portuguese + Russian + Traditional Chinese + +Overview of changes from GLib 2.39.90 to GLib 2.39.91 +===================================================== + +This release introduces a hard dependency on present and functioning +clock_gettime() and CLOCK_MONOTONIC. It also introduces a dependency on +pthread_condattr_setclock() unless your system happens to have +pthread_cond_timedwait_relative_np() (as do Mac OS and Android). This +release is known to be broken with at least GNU/Hurd, pending addition +of working pthread_condattr_setclock(CLOCK_MONOTONIC) there. + +New API: g_str_to_ascii() + +* Fixed bugs: + 670144 unconditional use of CLOCK_MONOTONIC is broken + 673607 invalid assumption in g_cond_wait_until() / g_get_monotonic_time() API + 710142 Add more impressive transliteration to GLib + 722360 make check fails + 722604 (partial) Various tests are failing with 2.39.3 + 723316 g_hash_table_iter_remove() should be explicit whether or not it is safe while iterating the table + 724609 Fix build of GIO on Windows + 724687 gmain: make monotonic time really monotonic, everywhere + 724706 gsource: document priority of child sources + 724707 some GSocket source improvements + 724839 GMainContext: some source ID cleanups + 724858 Dist gtranslit-data.h + 724994 Missing icons for bookmarks in file chooser + 725023 Can no longer find apps by executable/desktop file name + +* Translations: + Lithuanian + Polish + Thai + +Overview of changes from GLib 2.39.4 to GLib 2.39.90 +==================================================== + +* Fixed bugs: + 625408 make GVariant dictionaries more useful + 660809 document that if you fail a precondition check, documented guarantees do not apply + 661576 fix handling of constructors that destroy half-constructed objects + 679957 g_inet_address_new_from_string is not able to handle dots and numbers IPv4 addresses + 712837 gvariant: Document the need to cast varargs when constructing GVariants + 721458 g_simple_async_result_is_valid has a NULL check for the wrong source_tag + 721977 improve split handling of command line arguments + 722033 win32: fixup lib.exe invocation + 723422 Fix g_socket_get_available() with TCP on Windows + 723616 gio/tests: fix race when generating code + 724001 gsubprocess: Fix a broken link in the documentation + 724124 glib/tests/collate.c fails if no en_US locale + 724126 intermittent GApplication test failure: /gapplication/local-actions: lines of output permuted + 724233 gsocketservice: Note g_socket_listener_close() for closing open sockets + 724239 soup_session_queue_message - Connection terminated unexpectedly + 724278 gsocketconnection: Document closing connections with g_io_stream_close() + 724330 configure.ac: tweak inotify check + 724385 gtestutils: make the new assert messages more detailed + 724401 gsubprocess: Mutex leak + 724417 glib master build broken on OpenBSD + 724434 Build failure in gio/gresolver.c + +* Updated translations: + Brazilian Portuguese + Galician + Indonesian + Italian + Kannada + Norwegian bokmål + Spanish + Thai + +Overview of changes from GLib 2.39.3 to GLib 2.39.4 +=================================================== + +* Fixed Bugs: + 139699 Correction for g_main_context_unref() + 583036 g_strchomp and g_strchug are not declared const + 683388 improve documentation for application developers + 685204 ./configure fails to add the '-g' flag to CFLAGS + 688406 GStaticMutex broke ABI on at least ARM EABI during 2.31.x + 693299 cannot compile on Solaris: error in gbitlock.c + 707111 Clarify type transformability and compatibility + 711547 win32: silence some build warnings + 719344 Fix the various test programs (or GLib itself) on Windows + 722025 cleanup/clarify command line argument encoding on Windows + 722323 remove unused include 'gslist.h' in 'gbookmarkfile.c' + 722326 gstringchunk: Use g_slist_free_full() where possible + 722357 gio: fix small memory leak on local xattr + 722436 Adjust doc to Makefile.decl renaming + 722503 GSimpleAction: add default activate handler + 722526 glib/deprecated/gthread.h error on FreeBSD + 722591 [documentation] broken link to GtkAction from GAction.html + 722973 Broken example in GApplication reference + 723048 'network-access' test can fail to guess interface index + 723360 gmain: Note that g_source_destroy() can be called multiple times + +* Updated Translations: + Assamese + Tamil + Traditional Chinese + + +Overview of changes from GLib 2.39.2 to GLib 2.39.3 +=================================================== + +No major changes this release -- mostly lots of small fixes and +improvements in test coverage. + + * fix a crasher in code from gdbus-codegen + + * improvements to gobject gdb helper script + + * portability: + + - fix a deadlock issue with kqueue on FreeBSD + + - work around a quirk in the sunstudio compiler + + - rename a variable to avoid clashing with a macro definition of + 'environ' on some platforms (like mingw) + + - use POSIX-specified <poll.h> over <sys/poll.h> + + - many improvements to Visual Studio projects and and some build + fixes for Windows + + * tests + - a very large number of improvements in test coverage + + - don't report skipped tests as failures + + - return 77 if we skip all tests in an executable + + - improve gtest documentation and fix some minor issues + + - fix g_test_trap_reached_timeout() return value + + - remove some dead code uncovered during test coverage expansion + + - Use tap mode for installed tests too, when using tap + + * fix races in unix signal handling + + * make our GVariant-based commandline tools (glib-compile-schemas, + gdbus, gapplication) print out GVariant parse errors in context + + * GApplication now has a --gapplication-service command line switch to + turn any GApplication into a service + + * improve compatibility of GApplication and GOptionContext + + * fix gsettings.m4 wrt. builddir != srcdir with non-recursive make + + * use a directory monitor in GKeyfileSettingsBackend + + * improve robustness of some GIcon classes + +Bugs fixed + 141251 poll(2) is in <poll.h>, not <sys/poll.h> per SUS standard + 613732 [PATCH] gobject.py: Don't install frame filters when GDB does not support them + 708212 g_variant_parser_error_get_quark() has unexpected name. + 710965 GApplication: add --gapplication-service switch + 711090 periodic failure of spawn-multithreaded async testcase + 712171 gsettings.m4: @GSETTINGS_RULES@: Support srcdir != builddir with nonrecursive make + 712630 Revert "gsettings m4: check for .xml in src/builddir" + 715028 GVariant: add way to print context of parse errors + 719344 Fix the various test programs (or GLib itself) on Windows + 720263 gtestutils: skipping a test should count as success, not failure + 720539 gdbus-codegen: Fix crasher in goa-using apps + 720635 Make gdb pretty-printers compatible with Python3 + 720891 g_settings_get_child does not inherit the backend + 721034 glib 2.38.2 cannot be compiled with SunStudio Compiler under Solaris + 721059 g_subprocess_launcher_set_environ vs "environ" + 721074 kqueue: deadlock + 721087 Missing -lselinux in pkg-config --libs --static gio-2.0 + 721324 Error message is printed to stdout + 721624 Regression in GTest framework reorders existing test cases + 721625 backwards NEWS entry about g_source_remove change + 721796 insufficient escaping in g_dbus_annotation_info_generate_xml() + 721947 Improve GApplication ⇔ GOptionContext compatibility + +Translations updated: + Brazilian Portuguese + Galician + Greek + Hebrew + +Overview of changes from GLib 2.39.1 to GLib 2.39.2 +=================================================== + +* Portability + + - Remove alleged support for OS/2 + + - Remove alleged support for BeOS + + - Remove alleged support for last-millennium Unixes + + - Require C90 compliance + + - Require POSIX.1 (1990) compliance on Unix + + - Require GNU make + +* Bugs fixed: + 113075 support "nonnull" attribute + 159528 g_ptr_array_remove_range() + 307947 The check for growing stack pointer in configure can fail + 607016 docs should mention property notification order + 671557 Fun with integers and g_key_file_load_from_data() + 676761 don't use g_critical for a runtime error + 690525 g_file_replace_contents_async doesn't copy its @conten... + 691608 Support compilation with clang 3.2 + 697585 g_variant_builder_add's doc example is leaking + 697828 g_hash_table_add() should return a boolean + 702862 gdbus-codegen : look for deps in default install path + 703522 Reference leak in GvariantBuilder documentation + 705902 g_get_current_dir() should check PWD env var and retur... + 708274 Added GObject Introspection annotations to genums.c + 710519 Portability schmortability + 710741 some mainloop instrumentation + 710983 Test failures on powerpc + 711047 Enable the build of the various test programs on Windo... + 711051 Add basic test for the GNotification gtk backend + 711088 gbacktrace: Don't close stderr when running gdb + 711103 gmessages: Add g_info macro for G_LOG_LEVEL_INFO + 711178 appinfo test problems + 711546 utf8: report allocation error + 711640 gdesktopappinfo: Rank Keywords matches higher than Gen... + 711751 Fix memory leaks in libglib tests + 711753 gthread-posix: Don't use gslice allocated GRecMutex + 711796 glib-tap.mk: fix to actually use the TAP driver + 711800 fix g_test_set_nonfatal_assertions() + 711801 giomodule: Allow overriding source directory gio modul... + 711805 gdbus-connection: Fix race condition in test + 711806 gtestdbus: Don't destroy GSource twice + 711807 gtestdbus: Properly close server connections + 711871 Broken and misleading configure check for growing stack + 712136 'O_CLOEXEC' undeclared (first use in this function) + 712148 Add system bus support to GTestDBus + 712171 gsettings.m4: @GSETTINGS_RULES@: Support srcdir != bui... + 712314 AIX port: splice(); major()/minor(); libtool library order + 712315 GSettings: More docs for deprecated _list_schemas() + 712393 gobject: Box GMappedFile + 712547 GSocketClient "event" not useful for determining resol... + 715164 Clang static analysis fixes + 719395 GPtrArray add g_ptr_array_insert + 719402 Crashes when startup + 719472 leak in generated proxy-side property-setter + 719687 fix or remove g_trap_object_ref + 719809 Signal connection ids are always > 0 if successful + 719837 gdbus-connection: Work around race in connection tests + 719884 Fix documentation typos in GTask and GCancellable examples + 719979 g_settings_get: check validity of format string + 720080 Truncating a GMemoryOutputStream to a larger size cause... + 720210 gdataset: Remove unused define + 720236 Allow clean simple use of g_test_trap_subprocess() + +* Translations updates: + Italian + Lithuanian + Simplified Chinese + Spanish + + +Overview of changes from GLib 2.39.0 to GLib 2.39.1 +==================================================== + + * GSettings fixes/improvements + + - GSettingsSchema API is now more powerful and consistent + + - new GSettingsSchemaKey API allows accessing metadata for keys: + type, default value, range and the long-awaited support for summary + and description + + - GSettingsSchemaSource gains support for listing schemas within a + source. Deprecate the global API that did this for the default + source. + + - 'gsettings list-schemas' now works properly with --schemadir + + - deprecate a bunch of now-redundant functionality on GSettings + + - add API to GSettings for getting the default value of a key (as set + by the sysadmin) + + - add API to GSettings for determining if the user has assigned a + particular value to a key (ie: we are not just reading the default) + + - ignore qualified tags and attributes appearing in schema files + + * Applications/Actions + + - make GSimpleAction a bit more strict with respect to state changes + that would violate the interface (ie: by changing the state type + after construction) + + - throw an error when attempting to 'Describe' a non-existent action + via D-Bus instead of returning a bogus description + + - throw an error when attempting to invoke unsupported methods on an + Application (eg: 'Open' on an app that doesn't HANDLES_OPEN) + instead of emitting a g_critical() in context of the app (which is + not itself at fault for the errant call) + + * Appinfo + + - substantially rework GDesktopAppInfo to reduce the amount of disk + accesses that are performed in common situations + + - add a new class: GAppInfoMonitor for discovering when applications + are installed/removed + + - add a new g_desktop_app_info_search() API for searching for + installed applications by name, keywords, etc. + + * GMarkup: add new G_MARKUP_IGNORE_QUALIFIED flag for skipping over + "qualified" tags and attributes (those with a colon in the name, such + as 'my:tag') + + * GDBus + + - ignore qualified tags, as above + + - GTestDBus: unset all D-Bus addresses (such as STARTER) to ensure + that test programs don't pick them up + + - add new session_bus_run() convenience in the tests and use it + + * GRand: use real random data as a seed on win32 and use the + timestamp/pid/uid fallback only on UNIX machines where we can't open + '/dev/urandom'. This may cause issues with older mingw32 releases + due to a missing prototype for the rand_s() API. + + * Many win32 (and particularly MSVC) portability fixes. Many + additional tests are now runnable when building with MSVC. + + * Due to early testing of the (soon to land) GCleanup framework, a very + large number of memory errors have been found and fixed (mostly in + the testcases, but some in glib itself). + + * GIO: + + - some more seeking cleanups: particularly on GLocalFileInputStream + + - don't leave a .trashinfo file around if trashing a file fails + + - Add a request_certificate virtual method to GTlsInteraction + +Translations updated: + Assamese + Galician + Greek + Spanish + Tamil + +Bugs fixed: + 635641 schema compiler should ignore unknown attributes + 637257 g_tls_client_connection_gnutls_retrieve_function needs to be able to block + 637956 GKeyfileSettingsBackend should ignore file deletions + 645453 keys from base schema missing from extended schema + 665634 g_dbus_node_info_new_for_xml() errors on unknown attributes in XML files + 668232 Unable to get description and summary for a key + 668233 Unable to determine if a key is set to the default / what the default value is + 680838 Need g_settings_schema_source_get_schemas() + 683017 API for accessing GSettings Schema metadata + 687185 org.gtk.Actions.Describe doesn't return an error for non-existing action names + 687202 If trashing fails, the ".trashinfo" file is not removed + 695558 The --schemadir option has no effect + 696424 GSimpleAction.state property is not right + 697348 GTestDBus should unset DBUS_STARTER_ADDRESS, DBUS_STARTER_BUS_TYPE + 710133 Emit backward compatible code with gdbus-codegen + 710691 glib-networking: locking during implicit handshake + 710738 GRand has lame fallback for Windows + 710859 Typo in gio docs + 710885 Two fixes for GApplication + 710962 error: 'F_DUPFD_CLOEXEC' undeclared (first use in this function) + 710964 Add g_hash_table_get_key_array() + 710991 test: g_debug messages shouldn't affect g_assert_expected_messages + 711016 g_settings_list_keys () segfaults for empty schemas + 711048 glocalfileinputstream.c allows skip past end of file + 711049 Fix build of GLib-GIO 2.39.x on Windows/MSVC + 711064 Adding child source to blocked source can cause a segfault + 711070 Copying a symlink over another one segfaults + 711099 gapplication test failure + 711520 GDesktopAppInfo: allow more than one level of legacy folder prefixes + 711556 Add GAppInfoMonitor + 711557 Add g_desktop_app_info_search() + 711600 trivial portability fix + 711632 The desktop-app-info test fails during make check + 711754 gmain: Fix use of uninitialized memory in sigaction structure + 711755 private: Use threading primitives correctly in private test + 711756 gthreadpool: Don't pass bad data to GThreadPool sorter + 711768 Fix memory leaks in libgmodule tests + 711775 utils: Don't free memory owned by glib in test + 711782 boxed: Fix double free in boxed unit tests + 711803 gsubprocess: Fix a number of leaks and a segfault + 711808 gtestdbus: Fix leak of GMainLoop + +Overview of changes from GLib 2.38.0 to GLib 2.39.0 +==================================================== + + * prep for the 2.40 series (version macros, docs index, etc.) + + * GNotification + + - new API for sending persistent notifications via the desktop shell + + - notifications persist when the application has quit and clicking on + them can restart the application with an action (via + DBusActivatable) + + * GSubprocess + + - new API for launching subprocesses + + - nice GIO integration like async functions, cancellability, etc. + + - a convenient communicate() API inspired by the same API in Python + + - related: the gspawn API now has a CLOEXEC flag for the created + pipes for stdin/stdout/stderr + + * New gapplication(1) commandline tool + + - intended to be used with DBusActivatable apps + + - can be used for launching apps, opening files, invoking application + actions and listing apps and actions + + - bash tab completion is supported + + * GDesktopAppInfo changes: + + - g_file_get_path() can implicitly cause a FUSE mount so don't call + it until we know we need it (for an app that doesn't support URIs) + + - don't crash when trying to load from a keyfile with + DBusActivatable=true + + - remove some dead code, refactor the search path handling a bit and + do a large-scale whitespace cleanup (prep work for the pending + desktop file index) + + * File monitors + + - fix broken handling of mount point monitoring + + - remove some strange use of GObject::constructor() from the base + class and inotify backend + + - fix GFileMonitor to work in the non-default main context even when + the main context is not running (or is blocked) + + - add internal private API for easily creating a file monitor in the + GLib worker thread + + * GSettings + + - g_settings_list_children: only list viable schemas. This fixes a + longstanding issue where 'gsettings list-recursively' will crash + when there are invalid schemas installed + + - don't accept invalid paths on g_settings_new_with_path, etc. + + * GIO + + - GFile now has a thumbnail::is-valid attribute to check if the + thumbnail in thumbnail::path needs to be regenerated + + - GDBusProxy now has a flag to control autostarting of services at + construction time + + - for GSeekable, properly introduce the concept of "resizable" vs. + "fixed-sized" streams in the docs, explaining the expected + semantics of the interface in each case + + - fix some cases in GMemoryOutputStream that were violating the above + expectations (which may cause a slight API incompatibility) + + - clean up GCredentials code and add support for Hurd and Solaris + + - improve splicing by using different codepaths for the case where we + have real _read_async() and _write_async() implementations on the + stream vs. the case where they are internally emulated (via + dispatching the sync variant of the call in a thread) + + * GKeyFile + + - fix a leak in g_key_file_get_(u)int64 when we fail to parse the + value as an integer + + - add long-requested API g_key_file_save_to_file() + + * Portability improvements + + - avoid using O_DIRECTORY on platforms that don't have it + + - be careful about systems that define SOCK_CLOEXEC but don't + actually support it (like Hurd) + + - only use SA_RESTART if it exists + + * Other small API changes/additions + + - a pair of functions to support matching strings for the type of + search functionality that you'd expect to have with things like + GtkSearchBar. This will also be used by the desktop file index. + + - g_str_is_ascii() with obvious purpose + + - g_test_expect_message() no longer appears to allow you to catch + G_LOG_ERROR messages + + * GMainContext/GSource + + - fix handling of overflowing the 'next source id' counter + + - g_source_remove() will now throw a critical in the case that you + try to remove a non-existent source. We expect that there is some + code in the wild that will fall afoul of this new critical but + considering that we now reuse source IDs, this code is already + broken and should probably be fixed. + + - simplify handling of the 'current dispatching source' to not + require use of a linked list + + * GObject + + - the long-broken (and leaky) pattern of destroying a just-allocated + object from inside of a custom GObject::constructor is now + officially completely illegal and will abort the program + + * Unicode: update to 6.3.0 + + * Bug fixes + + - g_file_copy() now falls back to pathname queryinfo. This should + clear up the bugs with copying from some GVfs backends (afp, + gphoto, archive, at least). + + - fix an out-of-bounds read in the xdgmime code + + - fix a typo in the /org/freedesktop/DBus path on the object manager + client + + - skip emitting path_namespace='/' in match rules in order to + workaround a bug in the D-Bus daemon and fix our own implementation + (which shared exactly the same bug) + + - fix crashes on precondition violations for GParamSpec constructors + + - many other small fixups (see bug list) + + * Many documentation improvements + +Bugs fixed: + 309224 g_key_file_save_to_file missing + 583321 QNX: no SA_RESTART + 661576 fix handling of constructors that destroy half-constructed objects + 672102 GSubprocess class + 684842 Seeks on GMemoryOutputStream don't have opaque semantics + 688492 Add a notification API + 691581 g_output_stream_real_splice_async doesn't use overriden read/write_async functions + 702516 gfileutils: Make -Werror=format-nonliteral happy + 704218 New gapplication(1) tool + 704593 g_setenv: on some systems (BSD, OSX…), setting a variable to NULL crashes the system + 704882 GLocalDirectoryMonitorClass mount_notify field is useless + 704887 file monitoring improvements + 705029 Support for Solaris credentials + 705688 g_settings_list_children: only list viable schemas + 706254 Afp backend cannot copy files + 707887 Attempting to create GObject Property with underscore prefix segfaults + 708042 gapplication: don't rely on cmdline being finalized immediately + 708265 add support for GNU/Hurd in GLib D-Bus Library + 708266 fix error code checks when SOCK_CLOEXEC is defined but not supported + 708529 xdgmime: valgrind warns about invalid reads + 708677 incorrect object path 'deskop' used in gio/gdbusobjectmanagerclient.c + 708714 Typo in docs of GLIB_VERSION_2_40 macro. + 708753 gdesktopappinfo: Call g_file_get_path() on demand + 708793 glib build fails with clang < 3.1: error: expected ';' after top level declarator + 708828 GDBusProxy: add the ability to call methods on non autostarted proxies + 708860 glib-2.38.0 doesn't build on Solaris 10 + 708972 gnetworking.h in tarball screws up out-of-source builds + 709113 [PATCH] Main loop dispatch path has needless linked list + 709227 Update to unicode 6.3.0 + 709301 goutputstream: Add clear warning about short writes to _write_bytes() and async version + 709326 GDesktopAppInfo crashes creating a DBusActivatable app without a filename + 709440 Fix overloading of "source" and "target" terminology in GBinding + 709615 Cannot use g_test_expect_message with g_error + 709753 Add helpers for string matches when using GtkSearchBar-like widget + 709898 Expose thumbnail validity in GFile attributes + 709966 Remove outdated documentation + 709994 Minor fix for HACKERS doc to direct hackers to proper help file + 709995 Obsolete makefile rules + 710002 G_MAXUINT may be assigned as duplicate source id + 710313 Memory leak in g_key_file_get_(u)int64 with invalid integer values + 710345 [Patches] Fix some redundant-decls + 710496 g_locale_to/from_utf8() doc updated. + 710625 g_file_error_from_errno: Remove unneeded breaks + 710666 Frame clock related bug fixes + 710724 gmain: Warn when g_source_remove() fails + 710726 Work around D-Bus bug with path_namespace='/' match rules + +Translations: + Assamese + Brazilian Portuguese + Indonesian + Russian + Tamil + Traditional Chinese + +What's new in Glib 2.38 +======================== + + * Application support + + - GIO now provides an implementation of Desktop Actions from the + desktop entry specification + + - GApplication now implements the org.freedesktop.Application + interface as per the desktop entry specification, allowing for + standards-based D-Bus launching of GLib-based applications + + - GDesktopAppInfo now supports DBusActivatable as per the desktop + entry specification, allowing GLib-based applications to use D-Bus + to launch other applications + + - GApplication now has a "busy" flag that can be set on an application + to allow the shell to show that it is busy + + * GObject + + - the private offset for a given class type is now always constant. + This was done by reorganising the memory layout of instances so that + the private data comes before the "official" pointer for the object + (ie: at a negative offset). Valgrind macros were added to mitigate + any problems that this may have caused. + + - a new G_DEFINE_TYPE_WITH_PRIVATE has been added along with a + generated function *_get_instance_private() that can now serve as an + equally-performing alternative to ->priv pointers in instances + (allowing memory savings) + + - new G_PRIVATE_FIELD, G_PRIVATE_FIELD_P and G_PRIVATE_OFFSET macros + provide a convenient method of converting between named variables in + private structures and their (now constant) offsets + + - installing properties on a GObjectClass must now be done from + class_init. It is no longer valid to install them after class_init + has returned. + + - it is now possible to manually break a GObject property binding + without destroying one of the objects involved + + * Icons + + - the requirements for implementing the GIcon interface have changed + in order to make it possible to consume all implementations of GIcon + with a finite number of cases + + - a new GBytesIcon type was added for an icon represented by an + in-memory binary blob in a known image format (ideally png). + + - new APIs g_icon_serialize() and g_icon_deserialize() replace the old + to/from_string APIs and will always work, irrespective of which + types have been initialised in the calling process, allowing for a + serialised GdkPixbuf to be deserialised in a process that doesn't + have GdkPixbuf + + - support for icons has been added to GMenuModel using the new APIs + + * Actions and menus + + - GPropertyAction provides a convenient way of creating a stateful + property corresponding to a property on a GObject, such as the + "visible-child-name" property of a GtkStack + + - new API g_menu_remove_all() + + - we now have established rules about what is a "valid" action name + and an API to check them + + - a new API for converting detailed action names to and from the + split-out name and parameter value (as GVariant) + + - for backwards compatibility, invalid action names can still be used + with most functions, but this is not recommended + + * Other GIO + + - GDBus now supports services that wish to handle some of all + properties on an interface asynchronously, without requiring the + service to reimplement the entire org.freedesktop.DBus.Properties + interface + + - GFile now has a new _measure_disk_usage() (and async) API for + recursively determining the amount of disk space used by a + particular directory (akin to 'du'). + + - asynchronous version of g_file_trash() and g_file_make_directory() + have been added + + * Other new API + + - GRegex has a new function to query the maximum lookbehind length to + allow for regexp matching on streams + + - GVariant has two new APIs for constructing strings that allow + avoiding copies in some cases: g_variant_new_take_string() and + g_variant_new_printf() + + * Testing + + - we can now generate TAP output + + - new support functions for simplifying the process of dealing with + data files for srcdir != builddir and installed test cases + + - g_test_trap_subprocess() provides a portable alternative to + g_test_trap_fork() + + * Other + + - GLib now builds on Android against the bionic C library + +Overview of changes from GLib 2.37.93 to 2.38.0 +================================================ + +* fix the documentation for GSourceFuncs + +* fix compilation on OS X/ppc64 + +Bugs fixed: 708445, 647145 + +Translations updated: + Danish + French + Portuguese + Punjabi + +Overview of changes from GLib 2.37.92 to 2.37.93 +================================================ + +* a couple of bugfixes in the new g_file_measure_disk_usage() API + +* updated Traditional Chinese translation + +Overview of changes from GLib 2.37.7 to 2.37.92 +=============================================== + +* new API g_file_measure_disk_usage() similar to du(1) + +* minor fixes + +* Translation updates: + Assamese + Belarusian + Brazilian Portuguese + Catalan + Czech + Galician + German + Hungarian + Indonesian + Italian + Korean + Korean + Latvian + Lithuanian + Polish + Serbian + Slovenian + Spanish + +Overview of changes from GLib 2.37.6 to 2.37.7 +============================================== + +* GDateTime now supports %:z formatting variations + for timezones. This is a GNU date extension. + +* Bugs fixed: + 685387 Segfault with GObject.signal_handler_is_connected()... + 686786 g_socket_get_available_bytes() returns wrong value ... + 705027 GSocket GSource not threadsafe on Windows + 706469 Fix G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE documentation + 706706 Fix Gir annotations on g_loadable_icon_load_finish + 706888 gtype: fix a no-op assertion + 706958 configure.ac: fix atomic opts detection + 707092 "File Utilities" page for GLib documentation doesn'... + 707151 gdatetime: Extend the '%z' timezone format + +* Translation updates: + Catalan + Hungarian + Japanese + Polish + Slovak + Tamil + + +Overview of changes from GLib 2.37.5 to 2.37.6 +============================================== + +* Tests using the g_test facilities can now generate TAP output + +* Bugs fixed: + 680926 generic type fallback logic is broken for -symbolic + 684327 setting null icon to icon list + 689245 GSocket unable to reuse (address,port) on Mac OS X + 692125 Support TAP as GTest output format + 693335 build: fix dtrace-related warnings + 696633 gdbus-codegen trips over unicode chars when using python 3.x + 696970 Compiling 2.36.0 for win64 fails + 697185 GSocket – Allow specifying the multicast interface from... + 700268 Add support for using the clang analyzer + 701318 Add G_SPAWN_DEFAULT to GSpawnFlags + 701529 glib/tests/gdatetime: use UTC time in test_GDateTime_diff() + 701800 a new approach to reporting critical errors + 702674 g_date_time_new_utc crash + 704165 GLib.IOChannel read_unichar() fails + 705075 Simplify g_get_tmp_dir() + 705152 Race in glib/task.test + 705398 gtype: Fix typo in g_type_class_add_private() error message + 705570 Check ref_count in g_object_notify_by_pspec + 705600 Deprecate GSimpleActionGroup functions? + +* Updated translations: + Assamese + Brazilian Portuguese + Czech + Dutch + Galician + Gujarati + Hebrew + Italian + Lithuanian + Marathi + Norwegian bokmål + Russian + Slovenian + Spanish + Thai + Traditional Chinese + + +Overview of changes from GLib 2.37.4 to 2.37.5 +============================================== + +* Implement the Desktop Action specification: In the case that the + application is a GApplication and DBusActivatable, actions from the + desktop file are translated into GActions that have been added to + the application with g_action_map_add_action(). + +* GPropertyAction is a new type of GAction that represents the value + of a property on an object, and allows to change the value when + activated. + +* GNetworkMonitorNetlink can now handle default routes via a device. + +* The gsettings tool now reports failure to write a key (e.g. because + the key was locked down) + +* Miscellaneous new api: + - g_variant_new_printf + - g_action_print_detailed_name + - g_regex_get_max_lookbehind + +* Bugs fixed: + 664444 Support additional application actions in .desktop files + 684123 glib build only tries -D_GNU_SOURCE if glibc is detected + 689794 support incremental matching + 699259 add org.freedesktop.Application support to GIO + 700460 rewrite tests to not rely on precise timing of timeouts + 701511 updates to various GSource types + 701609 gnetworkmonitornetlink: handle default route via device + 703270 add GPropertyAction + 704157 GAction: add function for printing detailed names + 704250 Doc: various fixes + 704267 regression gsourceclosure: segfault in gedit file chooser + 704322 glib-unix: fix handling of multiple signal source for the... + 704424 No error when failing to override a locked key + 704447 Fix build/use of g_child_watch_closure_callback on Windows + 704523 g_thread_create_full() can dereference NULL pointer + 704543 Add implementations for G_GNUC_*_IGNORE_DEPRECATIONS for ... + 704567 gdbusnameowning: Don't spew an error if we're releasing a... + 704585 libc printf can give mixed-case strings for NaN and Inf + 704587 FTBFS: statfs_result is undeclared for statvfs() + 704699 gmain: Reset signal handlers to default when source is + 704704 AI_NUMERICSERV cannot be used with ai_socktype = 0 + 704873 inotify: don't assume mainloop is running + 704999 glib/convert.test crashing due to lack of iconv cache + 704931 GMenuModel: add annotations to virtual functions + +* Translation updates: + Assamese + Czech + German + Gujarati + Spanish + Tamil + + +Overview of changes from GLib 2.37.3 to 2.37.4 +============================================== + +* Bugs fixed: + 701283 g_source_add_child_source() segfault + 702147 inconsistency of G_STRFUNC + 703191 new private macros interact poorly with versioning macros + 703254 Doc: various fixes + 703407 g_spawn_async() keeps child_pid_report_pipe open in child process + 703437 GDBusConnection: be more careful with async GetAll + 703478 Missing G_BEGIN/END_DECLS in gsettingsschema.h + +* Translation updates: + Catalan + +Overview of changes from GLib 2.37.2 to 2.37.3 +============================================== + +* add a new API for instance private data: G_DEFINE_TYPE_WITH_PRIVATE + +* fix timestamps in tarball to prevent automake from being required to + build the unmodified source + +* add new D-Bus API for async property handling + +* add back fsync() on ext4 for g_file_set_contents() after it was + discovered that despite statements in the ext4 documentation + suggesting that this is safe, it is not safe. + +* Translations: + Italian + Norwegian bokmål + +* Bugs fixed: + 698375 - D-Bus async properties + 700350 - timestamp issue + 701560 - fsync issue (fixed again) + 700035 - new API for instance private data + +Overview of changes from GLib 2.37.1 to 2.37.2 +============================================== + +* The GLib test utilities have grown some file-related APIs + to support tests that can be used installed and uninstalled. + +* Installing properties after class initialization is deprecated, + and will trigger a warning. + +* GApplication: + - Support org.freedesktop.Application, including D-Bus activation + from desktop files + - Set prgname to appid for services + +* Bugs fixed: + 549783 gtester lacks framework for tests with data files + 692848 Fix property example in gobject tutorial + 698018 Add an explicit g_binding_release() + 698614 GObject: prevent installing properties after init + 699259 add org.freedesktop.Application support to GIO + 699959 g_file_copy(): Ensure we create private files by default + 700123 Test failure: g_inet_socket_address_get_scope_id + 700725 GIcon: NULLify the `type' out param in the sync methods too + 701401 gtest: add function for testing for WINE + 701456 Error in gnome/glib/gio/tests/file.c + 701474 Error building glibmm due to extra comma in glib/gtestutils.h + 701560 various improvements for g_file_set_contents() + 701680 GFileEnumerator: Add some documentation about ordering + 701878 Check wakeup() before iteration(TRUE) doesn't block + +* Translations: + Assamese + Czech + Galician + Gujarati + Kannada + Marathi + Odia + Polish + Slovenian + Spanish + Telugu + + +Overview of changes from GLib 2.37.0 to 2.37.1 +============================================== + + * add support for installed tests: + https://live.gnome.org/GnomeGoals/InstalledTests + + * add a new g_test_trap_subprocess() that works on Windows as a + replacement for the (now deprecated) g_test_trap_fork() + + * support for explicitly cancelling a gobject property binding + + * performance improvements for signal argument handling + + * stop using `quotes' in very many log messages generated by GLib, for + favour of 'this style'. This may cause testcases in other packages + to fail if they were matching on the previous text. + + * improve manpages: add missing arguments and flags + +Translations: + Aragonese + Assamese + Gujarati + Hindi + Kannada + Norwegian bokmål + Odia + Slovenian + Spanish + Tamil + Telugu + +Bugs fixed: + 679683 replace g_test_trap_fork() + 694380 Improve signal argument collection performance + 695233 Strings require plural forms + 697849 spelling fixes in cross.xml and running.xml + 698877 GProxyAddressEnumerator calls g_network_address_parse_uri without port + 698981 [PATCH] test /gdbus/connection/large_message could hang forever + 699079 Prototype support for installed tests + 699485 [PATCH] tests/mappedfile: Also handle ENOMEM + 699493 SOCKS5 proxy code crashes if it cannot authenticate + 699500 gbitlock: fix this to not unconditionally use futex emulation + 699779 [PATCH] G_GNUC_FORMAT: documentation error + 700263 m4macros/glib-gettext.m4: Don't use AC_HEADER_STDC + 700714 [PATCH] gtestutils: Ensure test subprocesses don't dump core + 700746 Use 'dumb quotes' rather than `really dumb quotes' + +Overview of changes fron GLib 2.36.0 to 2.37.0 +============================================== + +* The syntax for detailed action names has been documented, + and a parser API for them is now provided + +* GApplication has gained a busy state. This feature is intended for + clients that want to signal a desktop shell their busy state, for + instance because a long-running operation is pending. + +* GLib can now be built with the bionic C library + +* GIcon can now be serialized to a GVariant + +* Bugs fixed: + 548353 Finish implementing GFile interface (mostly asynchron... + 645881 Full port of glib-2.28.1 onto Android-ARM + 665445 Glib mistakes nl_langinfo() from plibc for the real t... + 672018 Need API to set global application state (busy, count... + 687659 drop support for adding interfaces after class_init + 688820 GIcon is a bad interface + 688954 extend 'detailed action' syntax, provide parser + 689223 Fix compilation on Android with the bionic C library + 695156 Add support for arg0namespace matching in signal_subs... + 696108 gdbus-codegen: avoid warnings in generated code + 696629 fix sed(1) usage + 696652 GTask won't free its error member variable on finalize + 696857 GThreadedResolver: set an error if no records could b... + 696973 Compiling 2.36.0 for win64 fails in gdbusmessage.c + 697131 No --version + 697160 [PATCH] gmacros: Mark G_UNAVAILABLE() functions as de... + 697229 Custom Interface implementations will be broken with ... + 697250 Documentation glitch of G_DEFINE_TYPE_EXTENDED causes... + 697365 Fix usage of hasmntopt in gunixmounts.c + 697367 Remove warning on gio/gunixmounts.c + 697386 Except const argument with atomic is not lock free + 697595 g_main_context_unref unlocks a mutex twice + 697601 reduce GMenuModel D-Bus traffic + 697626 Allow posix threads to be used on w32 + 697652 Help options generated even when help disabled + 697771 fix a typo of "fo" to "of" in building.xml + 697887 GVariant: fix transfer annotation + 697942 abicheck.sh fails on mips + 698056 rewrite g_object_new() + 698081 Pidgin hangs in g_spawn_command_line_sync + 698455 GVariant: add new g_variant_new_take_string() API + 698457 g_variant_get_data_as_bytes() always returns toplevel... + 698478 gactionmap: don't require GActionGroup + 698595 the valgrind/priv-before-instance bug + 698655 desktop-app-info test relies on true being in /usr/bin/ + 698686 GUnixSocketAddress: fix construct parameter issue + 698716 Use of g_mem_set_vtable() breaks after gobject automa... + 698999 bytesicon: fix a memory leak + 699001 bytesicon: don't use g_object_unref() on GBytes + 699361 gio: fix small leak + +* Translation updates: + Assamese + Gujarati + Hungarian + Italian + Kannada + Norwegian bokmål + Polish + Spanish + Tamil + + +Overview of changes fron GLib 2.35.9 to 2.36.0 +============================================== + +This release contains only small bugfixes and translations updates. + + - g_file_copy(): fix bug where attributes were not applied properly to + the destination file + + - fix some 'available since' annotations + + - fix gdbus-codegen to produce more pedantically-correct code + +* Bugs fixed: + 696108 gdbus-codegen: avoid warnings in generated code + 696014 g_file_copy(): Ensure G_FILE_COPY_OVERWRITE preserves permissions + +* Translations updated: + Basque + Czech + Gujarati + Hindi + Hungarian + Japanese + Malayalam + Marathi + Odia + Punjabi + Russian + Tadjik + Tamil + Telugu + +Overview of changes from GLib 2.35.8 to 2.35.9 +============================================== + +This release drops the old codepage ABI from gutils.c. This is a +source-compatible change and only breaks ABI with respect to truly +ancient binaries (and those binaries are already broken for other +reasons). This change only affects Windows. + +* Bugs fixed: + 682896 glib doesn't build on mingw32 + 693204 split up g_get_{hostname,username,realname,home_dir} etc. + 694181 Handle GNetworkAddress better in g_network_monitor_base_... + 694253 occasional /gdbus/unref-pending test failure + 694350 Add type names to gsignal warnings + 694757 Use separate GLIB_WARN_CFLAGS that can be overridden ext... + 568405 Which is the correct replacement for g_strncasecmp, if... + 630284 g_hash_table_get_keys docs + 659428 docs: Small clean-up of howto subsection headers + 675333 Cannot forget association in Open With dialog: program... + 694669 consider unicode corrigendum #9 + 694843 g_base64_decode_step () produces invalid data + 695147 Don't use PATH_MAX as it's not guaranteed to be defined + 695191 Commit f641699 broke /appinfo/mime/api test case + 695339 Swapped msgid plural forms for translation + 695376 GDBusMethodInvocation leak and potential crash + 695425 Untranslatable message in gsettings-tool + 695887 Improvements to GObject API documentation + 695925 GUINT32/64_SWAP_LE_BE macros do not enclose val argume... + 696015 PATCH Add doc warning to g_base64_decode() + +* Translation updates: + Assamese + Belarusian + Brazilian Portuguese + Catalan + Catalan (Valencian) + Danish + French + Galician + German + Greek + Gujarati + Italian + Korean + Latvian + Lithuanian + Polish + Portuguese + Punjabi + Serbian + Simplified Chinese + Slovak + Slovenian + Spanish + Thai + Traditional Chinese + Uyghur + Vietnamese + + +Overview of changes from GLib 2.35.7 to 2.35.8 +============================================== + +This release contains one major change that may cause problems: type +modules are now never unloaded. This is implemented by (effectively) +leaking the last reference on dynamic types. Some testcases that check +for unloading of types have been observed to be broken by this change, +but we know of no actual cases of "real code" breaking. Please report +any problems. + +Other changes: + * A couple of build fixes for Solaris + * Fix signal emission for GDBusObjectManagerClient + * annotations fixes + * new API: g_dbus_address_escape_value() + * GSocketClient: add proxy-resolver property + * GSimpleProxyResolver: new simple GProxyResolver class + * documentation fixes + * gnetworkaddress: preserve IPv6 scope ID in IP literals + +Bugs fixed: + 691105 Allow GSocketClient to override GProxyResolver for per client proxy settings. + 692827 configure test fails for arpa_nameser.h + 692829 new Btrfs support causes build failure on Solaris + 693285 GDBusObjectManagerClient: won't emit object-added|removed if name-owner arrives later + 693502 Cross-compiling documentation: typo (np -> no) + 693673 add g_dbus_address_escape_value() + 693694 gio: Fix annotations on g_[async_]initable_new() and friends + +Translations: + Dutch + Galician + Polish + Serbian + +Overview of changes from GLib 2.35.6 to 2.35.7 +============================================== + +This is a quick follow-up release with a few bug fixes. + +* Fix the build on systems with strict linkers by adding -pthread back + to the LDFLAGS for a testcase. + +* Re-enable native atomic operations on some buggy versions of clang + that ship as part of the MacOS X SDK. + +* Make G_IO_FLAG_IS_WRITEABLE an enum again (the #define broke bindings) + +* a small docs fix + +* Bugs fixed: + 657045 + 636683 + 682818 + 693105 + +* Translations: + Italian + +Overview of changes from GLib 2.35.4 to 2.35.6 +============================================== + +* GUnixFdSource is a new way to add file descriptors + to the mainloop + +* g_source_set_ready_time lets you mark a source to become + ready at a specified monotonic time + +* The internal visibility handling of GLib has been reworked + +* GFileMonitor will now automatically use fam instead of inotify + if $HOME is on NFS + +* The file monitor implementation can now be overridden with + the GIO_USE_FILE_MONITOR environment variable + +* Bugs fixed: + 570572 2 make check errors on + 592211 No monitoring over NFS mounts + 625552 wrong behaviour of GVolume GVolumeMonitor related func... + 657729 modernise GMainLoop + 658020 GSource for a single GPollFD + 678223 g_mutex_free + 682560 leak fixes + 682819 EINTR-harden all the things + 684404 When using g_network_address_address_enumerator_next()... + 686853 new GSource fd API + 688169 G_DISABLE_DEPRECATED doesn't cover deprecated/gthread.... + 688681 build: Make .symbols file canonical on all platforms + 690118 Crash when closing last tab of a window using Ctrl-w + 691624 glib/gtester.c: missing include + 691812 gioinputstream - give task as callback_data not task_data + 691866 fails out of source build directory - gnetwork.h not f... + 692029 Add new API checking utility + 692034 Install an invalidation notifier for GClosure in g_sou... + 692058 Broken makefile for gio tests + 692079 build failure in gmarkup.c when using gcc 4.8 and buil... + 692201 inotify: fix a memleak + 692202 gfile: don't report completion twice on g_file_load_co... + 692229 Incorrect string formatters in a translation string + 692332 GNetworkMonitorNetlink: make the netlink socket cloexec + 692360 possibly non-threadsafe code in g_content_type_guess()? + 692404 tester: Use FD_CLOEXEC when creating pipes + 692408 nautilus SIGSEGV in g_file_info_get_size() + 692544 [PATCH] gfile: Ensure we create internal pipe with FD_C... + 692583 atomic get doesn't accept a const argument on architect... + 692618 Use g_timeout_add_seconds + 692815 Using g_hash_table_insert() when using a hash table as ... + 692865 Invalid docbook generated by gdbus-codegen + 692928 Document G_MENU_{ATTRIBUTE,LINK}_* + +* Translation updates: + Hebrew + Kannada + Lithuanian + Norwegian bokmål + Polish + Serbian + Slovenian + Spanish + Uyghur + + +Overview of changes from GLib 2.35.3 to 2.35.4 +============================================== + +* New features: + - New API: g_get_num_processors + - New API: g_application_command_line_get_stdin + - New GFileMonitor flag: G_FILE_MONITOR_WATCH_HARD_LINKS + - Parse more timezone offset formats + - Better timezone support on Windows + - Make GParamSpec constructors introspectable + +* Removed or deprecated features: + - Disallow adding interfaces after class_init + +* Bug fixes: + 532815 gio + inotify support for hardlinks + 614930 add g_get_num_processors (), return the max concurrent... + 626497 Btrfs clone/reflink ioctl support in g_local_file_copy + 633117 glib fails stests if /etc/localtime is not properly set + 661767 merge/improve various bits of run-in-thread functionality + 668210 Add g_application_command_line_get_stdin() + 675856 Use GDbus via gobject-introspection instead dbus-python + 684103 make glib work with python3 + 684723 run-assert-msg-test.sh fails + 686058 OpenBSD: disable ipv6_v4mapped test + 686128 GTimeZone should be able to parse POSIX format for... + 687223 cleverer GThreadPool management + 687659 drop support for adding interfaces after class_init + 687920 GCredentials should have an accessor for the process ID + 688681 build: Make .symbols file canonical on all platforms + 688829 Variable overflow in utils.c test on 32-bit machine + 689324 Variable scoping in gunixmounts.c + 689810 Include guard optimization + 690043 Broken link for gsettings tutorial: gnome-utils in... + 690084 gmarkup: Make GMarkupParseContext a boxed type + 690388 Check if CMSG_FIRSTHDR() returns NULL when there is... + 690538 gschema DTD is invalid + 690543 Add test coverage for testing in-tree DBus services... + 690670 local_command_line not introspectable/annotated + 690902 G_END_DECLS needs to be at the end of gutils.h + 690970 Unhelpful deprecation message for g_value_array_get_nth + 691001 building docs is broken on master branch + 691011 Automake-1.13 errors on obsolete AM_PROG_CC_STDC + 691077 gio-querymodules crashes with SIGSEGV + 691110 g_cond_wait() docs incomplete + 691489 Crash in Oscars 2013 page + 691558 Only check for .hidden files if standard::is-hidden... + 691608 Support compilation with clang 3.2 + +* Translation updates: + Assamese + Bulgarian + Estonian + Galician + Greek + Hebrew + Norwegian bokmål + Polish + Slovak + Slovenian + Spanish + Tamil + + +Overview of changes from GLib 2.35.2 to 2.35.3 +============================================== + +* This release contains an incompatible change to the g_get_home_dir() + function. Previously, this function would effectively ignore the HOME + environment variable and always return the value from /etc/password. + As of this version, the HOME variable is used if it is set and the + value from /etc/passwd is only used as a fallback. + +* We now install a public "gnetworking.h" header that can be used to + include the relevant OS-dependent networking headers. This does not + really abstract away unix-vs-windows however; error codes, in + particular, are incompatible. + +* Bugs fixed in this release: + 142568 Allow $HOME to override passwd entry if the user really wants + 587806 The file selector should honor .hidden files + 602715 [GChecksum] Please add support for SHA512 + 623187 provide some support for arbitrary setsockopt()s? + 629301 .goutputstream files left behind when cancelling I/O + 652650 Optimize GDBusMessage serialization + 664627 /gapplication/basic test intermittently fails: cmdline re-or... + 675516 Win32: Don't start a DBus server when built as static library + 679683 replace g_test_trap_fork() + 684145 Current Git sources fails to cross-compile for Windows in Li... + 686895 file-info: catch thumbnail files in large directory as well + 687092 IPv6 <-> IPv4 mismatch when subscribing to multicast (send) + 688180 GObject: Minor error in description of floating reference + 688319 gthread: add missing AVAILABLE_IN_2_32 annotations + 688377 configure: add missing square bracket in AS_IF for memmove + 688419 gtask: source_object arguments and return values not annota... + 688497 AppInfo: Add sufficient api to port gnome-session from Egg... + 688681 build: Make .symbols file canonical on all platforms + 688704 Add boxed GType for GThread + 688886 Improve the i18n documentation + 688931 GMemoryOutputStream: Add new _resizable() constructor usab... + 689037 need helper for creating a GFile from a remote commandline... + 689377 Fix a compiler warning in GDBus + 689538 Source object tag set too late in gsocketlistener + 689800 Treat lost+found directory as a hidden file + 689847 Add fast repeated typename -> GType resolver + 689982 Make GChecksum more fully introspectable + 690069 g_unix_open_pipe: Add missing F_SETFD + 690083 gfileenumerator: Add a g_file_enumerator_get_child method + 690163 Add a pre-configured gio/gnetworking.h for Visual C++ builds + 690346 Remove an unneeded escaping in NAMESER_COMPAT_INCLUDE + 690348 Fix g_type_add_class_private() name in g_warning + +* Translation updates: + Assamese + Galician + Hebrew + Hindi + Kannada + Odia + Polish + Spanish + + +Overview of changes from GLib 2.35.1 to 2.35.2 +============================================== + +Note that the incompatible change to the ->constructed() vfunc that was +made in the last unstable release (2.35.1) has been reverted due to +causing regressions in applications. + +A new incompatible change has been introduced in this version: it is no +longer permitted to add interfaces to a class after the first +instantiation (or more strictly: after g_type_class_ref()). Bug #687659 +is tracking this. + +Two private symbols (g_menu_{attribute,link}_hash_iter_get_type) which +were accidentally exported have also been properly hidden. This may +cause some tools to issue warnings about ABI mismatch. + +The remaining changes should be relatively harmless: + + * GIO now has kqueue support for GFileMonitor (BSDs, Mac OS) + + * New g_variant_new_from_bytes() API + + * UNIX signal sources now allow watching SIGUSR1 and SIGUSR2 + + * Many pedantic cleanups to adhere to a higher level of -W use + + * GTask changes to avoid a deadlock + + * many cleanups/fixes for Windows + + * Boxing for GPollFD, GIOChannel, GBytes, GByteArray + + * Fix URL-encoding of trashed files + + * Many other docs and annotations fixes + +Translations: + + Galician + Gujarati + Lithuanian + Serbian + Slovak + Slovenian + +Bugs closed: + + 649302 Add support for GNU/FreeBSD + 668842 [GSocket] Add caching for the sender address in g_socket_receive_from() + 672924 Add annotations for g_filename_from_uri() + 673229 glib: Use Returns:, not @returns + 677062 (partial) GVariant: Make g_variant_new_from_bytes() public, add more GBytes API + 686185 g_date_time_format Transcoding Fails on OSX + 686191 g_mutex_get_impl() should use g_atomic_pointer_get() + 686797 Box GPollFD to make it introspectable + 686810 [regression] Infinite wait in g_task_run_in_thread_sync() + 686822 possible dlopen()/dlclose() issue with automatic g_type_init() + 686839 mkinstalldirs: Move to glib-mkinstalldirs + 686895 file-info: catch thumbnail files in large directory as well + 686898 g_unix_signal_source_new: Allow SIGUSR1 and SIGUSR2 + 686920 gdbus: Allow GDBusObjectManagerClient to work on peer connections + 686921 Remove some of the repetition from gio/tests/Makefile.am + 687075 g_spawn_sync diagnostic incorrectly complains about SIGCHLD + 687089 g_dbus_connection_export_menu_model(): fix a crash + 687098 Repeated g_timeout_add* use can lead to guint overflow + 687385 Add some stricter CFLAGS, fix up the code + 687441 ABI break in master: g_menu_attribute_hash_iter_get_type, g_menu_link_hash_iter_get_type removed + 687516 typo in string: KB should be kB + 687540 In Trash folder, Nautilus misinterprets "\n" in filename as a line break + 687541 GSignalQuery param_types field needs array annotation + 687600 gfileutils.c performs invalid cast of (varargs) open to non-vararg type + 687698 plural forms needed + 687700 ending spaces + 687742 Add support for internal linkage to glib-compile-resources + 687801 tests/buffered-input-stream: Fix size of parameter passed + 688109 win32 warning/error fixes + 688255 'make check' regressed in 138f4c1 because GMarkup error messages changed + 688338 [PATCH] gobject/gtype.c: Fix spelling of »exceed« + 688370 GDBusError documentation improvement for client-side + 688378 g_socket_join_multicast_group not working + 688518 gio-kqueue: use O_EVTONLY on MacOS + + + +Overview of changes from GLib 2.34.0 to 2.35.1 +============================================== + +These two changes in particular may be slightly incompatible. Please +give feedback if they cause trouble: + + * Signal handlers connected with g_signal_connect_object() are now + automatically disconnected on target object destruction + + * The ->constructed vfunc is now called after all properties are set + +The remaining changes should not cause problems. + + * g_type_init() is no longer necessary and has been deprecated + + * GTask (the new GAsyncResult implementation) has landed + + * GLib version macros updated + + * Update to Unicode 6.2 + + * Thread safety fixes for GFileMonitor in non-default main contexts + + * GTimeZone support for old-format zoneinfo database (as on Mac OS) + + * g_settings_bind() now works with non-canonical property names + + * Fix crashes related to NULL connection passed to + GBusNameVanishedCallback and document this situation + +* Bugs fixed: + 118536 Make g_signal_connect_object'ed handlers disconnect when the data object is destroyed + 661767 merge/improve various bits of run-in-thread functionality + 682950 GFileMonitor crashing on high event count when running in different thread + 683642 Missing g_content_type_get_symbolic_icon + 684882 Gsettings should spaw a warning when binding against a low_underscored_property + 684909 codegen: Explicitly close output + 684912 Update to Unicode 6.2 + 685037 g_strcmp0: Returns shall include values less and greater than zero + 685069 Leak in glib-compile-resources + 685208 missing g_return_if_fail + 685608 [Patch] Port gio tests from pygobject to pygi + 685697 Documentation typo in g_dbus_interface_skeleton_has_connection() + 685733 Call ->constructed() after all properties are set + 685787 gtestdbus: correct documentation typos + 685995 Crash in g_menu_exporter_name_vanished + 686091 Invalid reads in g_bytes_unref_to_data + 686119 dtrace, gobject_probes.d, the last three probes - semicolon missing + 686161 Deprecate g_type_init() + 686231 GBusNameVanishedCallback: document NULL connection + 686458 slightly increase poll duration in test_timed_wait + +* Translations updated + Catalan (Valencian) + Czech + Danish + Italian + Lithuanian + Norwegian bokmål + Slovenian + +Overview of changes from GLib 2.33.14 to 2.34.0 +=============================================== + +* Bug fixes: + 654239 g_type_init()'s docs have no statement about how to... + 674620 Update GSettings migration guide for intltool updates + 676034 Fix doc annotation for g_ptr_array_ref() + 684278 Fix GIO build on Windows + +* Translation updates: + Brazilian Portuguese + British English + Bulgarian + Catalan + Galician + German + Hebrew + Hindi + Hungarian + Kannada + Latvian + Marathi + Spanish + Telugu + + +Overview of changes from GLib 2.33.12 to 2.33.14 +================================================ + + * CVE-2012-3524: don't run dbus-launch from setuid binaries + + * g_content_type_get_generic_icon_name(): + new API for getting the icon name for a mime type + + * Introspection fixes: + - GDBusConnection nullability fixes + - give a box type to GTimeZone + + * Drop GVFS_INOTIFY_DIAG + + * Add a new "Writing GLib Applications" section to the reference + documentation with general info on security, threads, etc. + + * gwin32mount.c: Fix syntax error + + * gresource tests: srcdir != builddir fixes + + * tests/gvariant: Fix test on big endian architectures + + * Fix regression in g_shell_parse_argv() + +Bugs fixed: + 562907 g_shell_parse_argv() mishandles # (hash) + 683167 g_time_zone_new not introspectable + 683384 /gvariant/checksum-basic failure on big endian machines + 683641 Typo in gwin32mount.c + 683744 have a way to get the generic icon name for a mime type + +Translation updates: + Assamese + Belarusian + British English + Czech + Danish + French + Galician + German + Greek + Hebrew + Indonesian + Indonesian + Korean + Lithuanian + Marathi + Marathi + Polish + Portuguese + Punjabi + Russian + Serbian + Slovenian + Traditional Chinese + +Overview of changes from GLib 2.33.10 to 2.33.12 +================================================ + +* Add a G_DEFINE_QUARK macro + +* Add symbolic icon support to drive, volume, and mount, file + and content types + +* Add API to allow thread-safe access to the same qdata item + +* Bugs fixed: + 562907 g_shell_parse_argv() mishandles # (hash) + 627240 add G_DEFINE_QUARK + 672329 memory leaks in gutils.c and glib tests + 673012 Stable byte-level specification for normal form + 674805 gdbusproxy async test is broken + 679835 gvariant format string parsing (and assertions)... + 682075 gdbus: Fix double free and use after free of ob... + 682101 Provide a way to get a symbolic icon for a device + 682222 test_method_calls_on_proxy: assertion failed (e... + 682284 mount-op: use gint64 instead of guint64 for tim... + 682386 "make check" fails due to sys/resource.h not be... + 682560 leak fixes + 682586 gsettings-tool: make list-recursively really re... + 682819 EINTR-harden all the things + 682833 Handle EINTR for open() + 682849 drop the global lock for g_object_weak_ref + 682965 gdbus-tool: Check return value of strrchr() + 683088 gdbus-codegen: fix error when wrong interface n... + Fix the build with gtk-doc-stub + Don't crash if set_app_info is called before ad... + +* Translation updates + Assamese + Galician + Greek + Indonesian + Japanese + Latvian + Lithuanian + Norwegian bokmål + Polish + Portuguese + Punjabi + Russian + Spanish + Traditional Chinese + Vietnamese + + +Overview of changes from GLib 2.33.8 to 2.33.10 +=============================================== + +* New GTest API for testcases where log output is expected: + g_test_expect_message() + +* GMenuItem now has 'get' accessors and a construct-from-GMenuModel API + +* GVariant now has a function to check a format-string for type + compatibility + +* win32: We now use overlapped IO to support multiple asynchronous + operations (ie: reading and writing) at the same time. + +* GMappedFile: Add g_mapped_file_get_bytes() + +* The problems with g_file_make_directory_with_parents() should be + resolved. + +* The long-standing issues with placeholder generation of manpages are + now resolved. + +* gtlscertificate: Add GBytes based certificate and private-key props + +* build: Switch back to using AS_IF for conditionals + +* test coverage improvements, documentation improvements, leak fixes + +* Bugs fixed + 326931 Better docs for G_GNUC_* + 550433 g_test_init doesn't recognize --help + 600751 GCompletion should better document if and how items memory is managed + 628193 Miscellaneous string fixes + 637460 man glib-genmarshal is hard to use + 674483 broken configure results when cross-compiling with gcc >= 4.5 + 677065 GMappedFile: Add g_mapped_file_get_bytes() + 679288 win32: use overlapped events for streams + 679556 it's hard to use gtest when g_warning() is expected + 680823 g_file_make_directory_with_parents: Fix error propagation + 681319 gtlscertificate: Add certificate-bytes and private-key-bytes props + 681336 man pages not built if --enable-gtk-doc not specified + 681413 build: Switch back to using AS_IF for conditionals + 681501 gmem: array only partially filled with memcpy + 681854 Documentation fix for Howto compile a program with glib + 682025 Documentation correction + 682067 Fix problems with CLEANFILES and automake-1.11.1 + +* Translations updated: + Lithuanian + Spanish + Galician + Telugu + Serbian + Assamese + Marathi + Indonesian + Traditional Chinese + +Overview of changes from GLib 2.33.6 to 2.33.8 +============================================== + +* GIO now has a g_file_delete_async function + +* The defaults for GThreadPools max_unused_threads + and max_idle_time values have been changed to + 2 and 15*1000, respectively. + +* Bugs fixed: + 661767 merge/improve various bits of run-in-thread functionality + 680074 undefined symbol "get_C_locale" + 680121 g_cancellable_source_new: don't use a file descriptor + 680148 gthread: check for definition of PR_SET_NAME + 680310 Sorting of access points by strengh not working + 680704 g_utf8_strup() crash + 68076a0 GFile: Add g_file_delete_async() + 680787 Add .dir-locals.el to tell Emacs users not to use tabs... + 680823 g_file_make_directory_with_parents: Fix error propagation + 680994 STATIC_ASSERT in GDBusError docs don't have much utility + 681116 gtlscertificate: Add g_tls_certificate_equal() function + 681118 gtlsdatabase: Don't complain if no callbacks for async... + 669331 try to get gio tests working a little better on win32 + 674314 Make gtk-doc not a hard dependency of GLib + 674800 gclosure: generic marshaller leaks return value + 675524 gsocket: FIONREAD undeclared (needs sys/filio.h) + 679509 use after free in g_dbus_action_group_describe_all_done() + 679996 gobject docs minor cleanup + 680459 Extra newline char in local implementation of g_applic... + 680505 object_path memory leak in gdbusobjectproxy.c + 680831 Deprecate and remove g_slice_[sg]et_config.* + 680912 gchecksum: Add g_compute_checksum_for_bytes() + 681151 checksum: Use functions instead of macros when buildin... + 681158 gtlscertificate: Don't confuse certificate and public ... + +* Translation updates: + Galician + German + Gujarati + Hebrew + Norwegian bokmål + Serbian + Slovenian + + +Overview of changes from GLib 2.33.4 to 2.33.6 +============================================== + +* GAsyncInitable: partially revert the init_finish changes, + some applications were found to rely on behaviour that + was broken by these changes + +* Bugs fixed: + 679617 win32: fix g_get_environ() + 679968 Add some annotations to GBytes, GVariantType... + 680111 GIOScheduler assumes GCancellable "cancelled... + +* Translation updates: + Spanish + +Overview of changes from GLib 2.33.3 to 2.33.4 +============================================== + +* GMainContext: the source list has been reorganzied to + avoid O(n) behaviour + +* GRegex: Update included PCRE to 8.31 and expose new + functionality in 8.x versions of PCRE + +* GMountOperation gained a ::show-unmount-progress signal + which provides information about slow unmount operations + +* Bugs fixed: + 616892 gio: Add a boxed type for GFileAttributeMatcher + 619329 g_source_attach() O(n) in number of sources + 639771 g_dir_read_name() can also return NULL on error + 661767 merge/improve various bits of run-in-thread fun... + 667375 GAsyncInitable subclassing (and async subclassi... + 671545 Constify collect and lcopy strings in GTypeValu... + 674452 SEGFAULT in gio contenttype test + 674898 Deal with GLIB_VERSION_MIN_REQUIRED/MAX_ALLOWED... + 675504 Fix up GObject interface documentation + 677064 GString: Tweak documentation, add g_string_free... + 677578 error in PCRE error code conversion + 677579 update GRegexError for newer PCRE error codes + 678066 gdbus codegen does not work with python3 + 678273 unicode othercasing is wrong in gregex + 678576 GIOScheduler performance enhancements + 678758 GTlsInteraction unlocks an unlocked mutex + 678808 GTestDBus issues + 678881 Test failures in /socket/timed_wait in some cas... + 678941 /contenttype/guess test case failure + 678944 gio returns the wrong default applications for ... + 678949 wrong definition of ulong_bool for 64 bit big e... + 678959 /mainloop/timeouts race condition: assertion fa... + 679193 update included pcre to 8.31 + 679258 The 'Since' tag for G_SOURCE_CONTINUE and G_SOU... + 679473 Don't generate invalid property names + 679691 Add g_spawn_check_exit_status() + 679671 GDBusNodeInfo: the XML string must contain exac... + 676111 mount-operation: add show-unmount-progress signal + 679691 win32: fix build g_spawn_check_exit_status() wi... + 679813 Documentation bug on http://developer.gnome.org... + +* Translation updates: + Assamese + Belarusian + Bulgarian + Galician + Greek + Norwegian bokmål + Polish + Spanish + Traditional Chinese + Vietnamese + + +Overview of changes from GLib 2.33.2 to 2.33.3 +============================================== + +This release contains mostly bugfixes, cleanups and performance +improvements (including many fixes contributed by Colin on the advice of +Coverity). There are a few notable externally-visible changes: + +* Thumbnails are now in XDG_CACHE_HOME + +* new GDBus API: per-thread g_dbus_connection_get_last_serial() + +* GUnixOutputStream now has a can_poll() implementation + +* New deep copy APIs for G(S)List: g_(s)list_copy_deep + +* Bugs fixed: + 518309 Incorrect data*dir path in glib-gettextize output + 566994 Safer passing of -framework flag + 672889 GLib.utf8_validate does segfault + 673253 Not strict enough autconf test for libelf + 675024 adds g_list_copy_deep() and g_slist_copy_deep + 675168 prepare for thumbnails to move to XDG_CACHE_HOME + 675966 gresolver: More robust parsing of DNS responses + 676594 [Patch] fix g_reload_user_special_dirs_cache + 676825 Implement g_dbus_connection_get_last_serial () + 677235 Clarify the comment at the top of gmarshal.list + 677527 OS X: gthread/spawn-async selftest failure + 677718 GDBusProxy: treat org.freedesktop.systemd1.Masked error as non-fatal + 677770 GUnixOutputStream does not implement can_poll + 677782 Install bash completion files in /usr/share + 677817 g_key_file_to_data adds extra blank lines in some cases + 677952 Missing annotation for GDBusConnection signal "closed" + 678052 g_wakeup_acknowledge is called too often. + 678273 unicode othercasing is wrong in gregex + 678333 gdbus-codegen code causes warnings under -Wfloat-equal + +* Translations updated: + Arabic + Assamese + Galecian + Greek + Spanish + Telugu + +Overview of changes from GLib 2.33.1 to 2.33.2 +============================================== + +* GLIB_VERSION_MIN_REQUIRED now defaults to the current stable version + +* GIO input and output stream classes have grown GBytes-based methods + +* GApplication now has hooks to register D-Bus objects before the bus + name is taken + +* Bugs fixed: + 605976 add g_type_ensure(), to ensure that a type has... + 660851 Breakage of code due to changes in the GThread... + 666386 Empathy doesn't open Redirect URI with particu... + 671139 need (transfer async) for io stream buffers + 672329 memory leaks in gutils.c and glib tests + 672548 g_utf8_validate: @str shouldn't end up annotat... + 674111 Provide an accessor for MimeType desktop entry... + 674483 broken configure results when cross-compiling ... + 674634 Add g_clear_pointer() + 674777 What's the (transfer) of g_variant_lookup()? + 675309 gkeyfile: Fix annotations for g_key_file_load_... + 675446 gfile: Plug memory leak in g_file_make_directo... + 675509 add extra dbus hooks + 675832 Incomplete gsettings bash auto-completion + 676208 The tmpl parameter to g_file_new_tmp can be NULL + 676265 GNetworkMonitor leaks a lot of memory + 676277 Document that g_app_info_create_from_commandli... + 676397 g_environ_* should work with NULL envp + 676398 g_spawn_* should take PATH from the passed env... + 676478 Broken gzip decoding + 676594 [Patch] fix g_reload_user_special_dirs_cache + 676816 Add more GLIB_AVAILABLE_IN_* + 676937 Document notify signal deduplication with free... + +* Translation updates: + Czech + French + German + Greek + Japanese + Russian + Slovenian + Spanish + + +Overview of changes from GLib 2.32.1 to 2.33.1 +============================================== + +* GApplication + - can now have a NULL application ID + - add accessors for determining dbus connection and object path + +* g_clear_object: fix warnings when using it on C++ (due to lack of + ability to implicitly cast void*) +* add g_clear_pointer as a generic form of g_clear_object + +* GDBus: + - add our own implementation of the message bus for use on Windows only + - fix up a few bugs that use of this bus uncovered in GDBus + - escape nonce files in dbus addressess (think 'c:\') + - support initial underscores in dbus codegen namespace (for private) + - add GTestDBus for bringing up a session bus for testing purposes + - gdbus-codegen: Avoid warnings in generated code + - GDBusAuthObserver: Add a way to control what authentication mechanisms to use + - + +* Fix misdetection of GNUstep as Cocoa (for the MacOS GSettings backend) + +* make sure configure fails if AC_CHECK_ALIGNOF cannot detect the alignment + +* GAppInfo + - overwrite the DISPLAY only if it is set in the launch context + - add accessor for StartupWMClass + +* glib/tests/date: force US locale running the GDateTime tests + +* Resources: + - fix broken use of GVDB on big endian machines + - set a 'display name' so that pretty file names appear in Gtk CSS + warning messages + +* GMainContext: + - block child sources when blocking the parent + - introduce more testcases for child sources + +* GResolver: add support for MX, TXT, NS and SOA records + +* GSocketControlMessage: Don't warn about unknown messages + +* GIO: + - implement GSeekable for the data and buffered stream classes + - implement GPollable for many more classes as well + - fix GConverterInputStream infinite loop when fill_buffer returns an error + - fileinfo: document the correct type for trash::orig-path + +* test coverage improvements and general fixes + +* new 2.34 stuff: version macros, docs index section, etc. + +* Build: + - add --disable-modular-tests build option + - don't require host binaries if tests are not enabled for cross-builds + +* Translations updated + Brazilian Portuguese + Bulgarian + Czech + French + Galician + German + Hebrew + Hindi + Italian + Norwegian bokmål + Polish + Russian + Russian + Serbian + Simplified Chinese + Slovenian + Spanish + Telugu + +Overview of changes from GLib 2.32.0 to 2.32.1 +============================================== + +* Bugs fixed: + 670254 glib-2.30.2: Fails /GDateTime/new_from_unix test + 672541 glib-compile-resources prepends --sourcedir to absolute paths + 673139 URL to mailing lists in README incorrect + 673174 g_input_stream_read[_finish]: document returning 0 on EOF + 673191 glib/gchecksum.c warning: dereferencing type-punned pointer... + 673216 [W32] gtestutils does not use path separators consistently + 673439 Properly deprecate g_value_{set,get}_char + 673612 Fails to decode dictionaries wrapped in two layers of array + 673803 gclosure: Support return values of GVariants + 669285 glib/tests/markup-parse fails under non-english locale + 673911 gio-2.0.pc lists full path to executables, breaking cross com.. + 673762 gnextstepsettingsbackend.c:343: error: parse error before 'in' + +* Updated translations: + Belarusian + British English + Bulgarian + Catalan + Czech + French + German + Hebrew + Hindi + Hungarian + Italian + Japanese + Kannada + Latvian + Lithuanian + Marathi + Norwegian bokmål + Odia + Polish + Serbian + Slovenian + Spanish + Swedish + Telugu + + +Overview of changes from GLib 2.31.22 to 2.32.0 +=============================================== + +* Bugs fixed: + 671988 Quickly registering / unregistering objects on bus... + 672095 glib needs stable sort function + 672406 glib/tests/include.c fails to build on FreeBSD + +* Updated translations: + Telugu + + +Overview of changes from GLib 2.31.20 to 2.31.22 +================================================ + +* Bugs fixed: + 531901 Use __builtin_bswap* for GUINT*_SWAP_LE_BE if building... + 653167 Out of tree build is broken on windows + 668973 Test /gvariant/parser fails on Solaris 10 + 669797 gvfs now lists its fuse mounts + 670846 deadlock: GStreamer-WARNING **: wrong STREAM_LOCK count 0 + 671664 gio-querymodules: unlink instead of writing empty cache + 671676 Glib can't be cross-compiled any more after merge of... + 671918 gnome-shell is inaccessible unless started while an AT... + 671942 GSocketMsgFlags: annotate as a flags + 671997 Unix signal handling assumes that volatile 1-byte writes... + 672013 GSimpleAsyncResult: support reliable cancellation + 672026 default log output should include pid and/or prgname + 672095 glib needs stable sort function + 672201 G_SPAWN_SEARCH_PATH should continue on ENODEV and ETIMEDOUT + 672239 request NO_REPLY from g_dbus_connection_call() with no as... + 672249 gdbusproxy leaks asyncresult in an error case instead of... + +* Translation updates: + Assamese + British English + Catalan + Catalan (Valencian) + Danish + Esperanto + Finnish + French + German + Hungarian + Korean + Lithuanian + Norwegian bokmål + Polish + Portuguese + Russian + Traditional Chinese + + +Overview of changes from GLib 2.31.18 to 2.31.20 +================================================ + +* Update to Unicode 6.1 + +* Update PCRE to 8.30 + +* Deprecations are now versioned, and new API is + marked with the version it was introduced. + Use these with GLIB_VERSION_{MIN,MAX}_REQUIRED + +* The performance of signal emissions has been + improved for simple cases + +* Bugs fixed: + 529806 Cannot build in 64-bit Mac OS X due to libiconv + 580873 Documentation of register type functions incomplete + 592666 Document how to unset an attribute + 597785 g_type_class_add_private code snippet is a bad example + 621368 glib-2.24.1: FAIL: run-assert-msg-test.sh when updating... + 622149 --disable-regex breaks glib2 build + 639873 GBinding: Crash when binding two properties on the same... + 640202 For GLIB v. 2.23.6 and above: impossibility to build mu... + 668295 Need a way to classify GVolume instances + 669670 gasyncqueue: don't use deprecated g_cond_timed_wait() + 670542 Add version information for deprecations + 670557 gvaluetransform: Fix an infinite loop with GFlagsValue... + 670721 global variable for signal ID should be hidden + 670751 IceWM build fails due to the G_DEPRECATED_FOR macro + 670909 g_dbus_connection_call leaks when it receives an error... + 670922 Include path to gdbus-codegen in the pkgconfig file + 670969 GSequence lookup may fail if there was no sort prior to... + 671025 Constants and identifiers starting with a number are no... + 671270 make distclean failures + 671281 glib-compile-resources.xml is missing from the dist tar... + +* Translation updates: + Basque + Belarusian + Brazilian Portuguese + Bulgarian + Galician + Hebrew + Lithuanian + Persian + Punjabi + Serbian + Simplified Chinese + Slovenian + Telugu + Traditional Chinese + Uyghur + Vietnamese + + +Overview of changes from GLib 2.31.16 to 2.31.18 +================================================ + +* GDBusProxy has now a flag, G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, + which can be set to make GDBus automatically reload + changed properties even if the propertychanged signal + does not contain the new values. + +* GApplication puts non-unique applications on the bus + +* GApplication now has g_application_quit() + +* g_async_queue_timed_pop has been deprecated in favor of + the new g_async_queue_timeout_pop, which uses relative + delays in microseconds instead of a GTimeVal. + +* a huge number of API documentation fixes + +* Bugs fixed: + 647986 put non-unique apps on D-Bus + 658484 vpn connection vs NetworkSecretDialog + 664237 GDateTime falls back to UTC if TZ is set + 669329 gthread-win32: update for g_get_monotonic_time() changes + 669330 glocalfile: fix error code when opening a directory on win32 + 669372 glib/tests memory leaks. + 669412 mem leak in g_environ_unsetenv + 669538 Fix compilation of glib-compile-resources.c on Windows + 669544 gdbus-codegen example introspection XML is not complete + 669595 glib-mkenums: fix handling of forward enum declarations + 669670 gasyncqueue: don't use deprecated g_cond_timed_wait() + 669671 gobject: use #pragmas to avoid deprecated function warnings + 669689 Retrieve cwd and environ in local GApplicationCommandLine + 669810 socket/win32: flush pending read before signaling HUP + 669865 g_regex_fetch() + 670085 memory leak in g_output_stream_write_async + 670138 gbytes.h is missing the G_BEGIN/END_DECL guards + 670485 Simplify session API (shared bug with gtk+) + +* Updated translations: + Belarusian + Danish + Galician + Serbian + Telugu + Hebrew + + +Overview of changes from GLib 2.31.14 to 2.31.16 +================================================ + +* GResource: + - The resource compiler can now convert pngs into + pixel data that can be used without parsing at runtime + (requires gdk-pixbuf-pixdata to be present) + +* Bugs fixed: + 669123 resource compiler: failing to-pixdata should... + 669173 resource: fix xml preprocess entity handling + 669224 Cross-compilation broken by data-to-c + 669253 gsettings set buggy on array values + 669334 fix memory leak in bookmark file parser + +* Translation updates: + Norwegian bokmål + Spanish + + +Overview of changes from GLib 2.31.12 to 2.31.14 +================================================ + +* GResource: + - GLib now includes a commandline utility, gresource, + to explore resources in ELF files + - The resource compiler can now optionally strip + ignorable whitespace from XML resources + - The resource compiler can now generate build dependencies + - The resource compiler will now autoselect output formats + +* GApplication: + - The menu markup parser API has been dropped, the + menu XML support lives in GTK+ now + +* GValueArray has been deprecated + +* Bugs fixed: + 626258 N-ary Trees - 'nodes' can be inserted before and after... + 634232 Core Dump / Aborted using g_key_file_to_data + 639099 schema compiler chokes on valid schema + 667228 Deprecate GValueArray + 667243 Add an element clear function to GArray + 667929 glib-compile-resources: xml resources doesn't need to... + 668250 g_date_time_format() produces a non-UTF8 string + 668468 'IP_ADD_SOURCE_MEMBERSHIP' undeclared + 668532 resources: add dependency generator to the resource compiler + 668539 resources: compiler should autoselect output format... + 668561 gresource-tool not internationalized + 668572 glib_cv_g_atomic_lock_free config.cache setting not honored... + 668650 GRealArray->clear_func should be initialized + 668756 GKeyFile: allow loading from empty strings + 668857 fix couple of typos in comments + 669024 goption: implement platform_get_argv0() for OpenBSD + +* Updated translations: + Galician + Norwegian bokmål + Spanish + Traditional Chinese + +Overview of changes from GLib 2.31.10 to 2.31.12 +================================================ + +* GApplication: + - Drop support for exporting menus - this functionality + will be provided in GtkApplication + - Add a way to create actions that change settings + +* Bugs fixed: + 629503 Add async versions of g_unix_connection_{receive,send}_credentials + 656301 glib-compile-schemas should not create an empty file + 668071 mingw-gcc build fails on gio/gsocket.[c|h] + 668118 the big appmenu switcheroo + 668158 base64 encode and line termination + 668163 GDBusConnection: note that exit-on-close is sometimes TRUE + 668269 gsignal: add g_signal_handlers_disconnect_by_data + 668279 create GAction from GSettings + +* Translation updates: + Norwegian bokmål + + +Overview of changes from GLib 2.31.8 to 2.31.10 +=============================================== + +* GResource: + - A new facility to allow linking data files into binaries + and make them available as resources + - Resources are compiled using glib-compile-resources + - GIO supports resource:/// uris to access resources + +* Bugs fixed: + 619126 Missing dependency libs + 658315 g_key_file_get_keys() should set length to 0... + 660371 is it ever valid to have 0 as a GError domain? + 666700 Add some missing (allow-none) annotations + 667375 GAsyncInitable subclassing (and async subclassing... + 667447 Missing many introspection annotations + 667790 Protect call to pthread_condattr_setclock with define + 667938 wrong gtypes generated for empty flags enums + +* Translation updates: + Hebrew + Spanish + + +Overview of changes from GLib 2.31.6 to 2.31.8 +============================================== + +* GObject: + - The type checks for overriding properties have been loosened. + In particular, it is now possible to add the CONSTRUCT flag + to an overridden property + - GWeakRef is a new API for weak references; unlike g_object_weak_ref + and g_object_add_weak_pointer, it is thread-safe. + +* GHashTable has grown new convenience api for use as a set: + g_hash_table_add, g_hash_table_contains + +* GSocketConnection has gained API for managing connection status + +* GSettings: a native OS X backend has been added, under the + name 'nexstep' + +* Bugs fixed + 455640 Something fishy with GRegex and unicode + 548954 weak references are not threadsafe + 625751 Add G_FILE_ATTRIBUTE_FILESYSTEM_USED + 658871 gbacktrace: g_get_prgname () isn't called for a NULL argu... + 664069 gvariant: Never break out of g_variant_iter_loop + 664830 g_strescape doesn't natively handle \v (vertical tab) + 665211 GDBusConnection singleton access can race with disposal + 665805 Add GSocketClient::action, for tracking socket client status + 666116 some tests provoke undefined behaviour, which is undesira... + 666422 Unreachable code in gio gnetworkmonitornetlink.c + 666551 Crash in g_thread_xp_SleepConditionVariableSRW + 666595 menu parser disallows id='' on submenu and section + 666615 loosen property override flag restrictions + 666616 gobject: fix property override type checks + 666803 g_utf8_validate() fails to validate strings with known size + 666804 g_ateaxit deprecation warning in devhelp points in wrong ... + 666951 g_mkdtemp: Since version incorrect in docs + 666978 Fails to compile glib applications with ISO C90 compiler + 667098 ginetaddressmask leaks its address property + 667225 GSocket: add missing type checks to public methods + 667226 GSocket: fix an error return value + 667279 Sometimes crashes when launching commandline-crea... + 667285 Wrong keyname listed in documentation for g_deskt... + 667331 Use g_queue_free_full() convenience function + 667420 GHashTable GDB pretty printing is broken + +* Updated translations + Belarusian + Bulgarian + Hebrew + Norwegian bokmål + Norwegian Nynorsk + Spanish + Vietnamese + + +Overview of changes from GLib 2.31.4 to 2.31.6 +============================================== + +* GApplication no longer has APIs for setting menus. Those have been + moved to GtkApplication. + +* the GActionGroup import/export functionality has been decoupled from + GApplication by the introduction of a new interface for the purpose of + handling platform data: GRemoteActionGroup. This allows Gtk to + properly deal with platform data (and gdk threads) on window actions. + +* lots of documentation improvements + +* bug fixes and a huge number of memory leak fixes + +* the test suite now passes on ARM and some of the GDBus testcase hangs + we've been seeing have been resolved (although others could remain) + +* g_bytes_get_data() API changed: now includes 'size' out parameter + +* new g_queue_free_full() API similar to g_[s]list_free_full() + +* desktop files: use standard "Keywords" now, not "X-GNOME-Keywords" + +* gsettings commandline tool now has --schemadir option for schemas not + installed in the usual place (ie: as part of plugins) + +* Bugs fixed: + 643736 GApplication doesn't emit dbus signals on action updates + 657433 g_queue_free_full() missing + 664699 glib: documentation fixes + 665737 acquire/release gdk threads lock on incoming dbus + 665879 GBytes: add a size argument to g_bytes_get_data + 666113 various leaks in GLib, GIO are visible in the regression tests + 666115 various tests leak memory, obscuring real leaks in the library + 666145 Doc could be more explicite that g_thread_init calls can be droped + 666173 Configure warning - linux/netlink.h usability... no + 666296 Race condition in g_thread_xp_get_srwlock + 666415 Settings tools should allow specifying a schema directory + +* Translations updated: + French + Spanish + +Overview of changes from GLib 2.31.2 to 2.31.4 +============================================== + +* EXPERIMENTAL: Menu support has been added to GApplication. Menus + are exported on the bus, alongside the actions that are already there. + There have also been many related improvements to action group + functionality. + + These new APIs are subject to changes in the coming releases. In + particular, it seems somewhat likely that the APIs for registering + menubars may change in order to accommodate windows with different + types of menubars. + +* GDBusConnection previously directly dispatched destroy notifies when + unregistering objects if the current main context was the same context + the object was exported on. It now unconditionally dispatches these + through an idle on the context. + +* Clean up Requires in pc files. Linking against GIO no + longer drags in gmodule. This may require dependency + fixes here and there. + +* Introduce GBytes, a data type for immutable, fixed-size + byte sequences. This makes the pre-existing GBuffer + API available outside GLib + +* GDBusInterfaceSkeleton can now be exported on multiple + connections + +* Bugs fixed: + 600161 Do not use static GTypeInfo and GInterfaceInfo + 640077 GFileMonitor: Always send CHANGES_DONE_HINT after a move... + 641720 Misleading definition for local_command_line() in GApplic... + 648516 Little comment error and 2 useless lines of code + 651997 Dummy backend for gapplication + 652560 Test for g_ascii_strtod is failing + 662208 failure to initialize a GInitable should be considered... + 662718 GDBusInterfaceSkeleton should be able to export on multi... + 663291 GBytes: Immutable, refcounted sequence of bytes + 664406 Need context for a proper translation + 664455 Build fixes for GLib GIT master (2.31.x) + 664558 GDBusWorker.frozen has a value > 1 in a gboolean + 664559 sys/wait.h not available on windows + 664617 gdbus segfault error 4 in libgio-2.0.so.0.3102.0 + 664635 GMemory{Out,In}putStream _async functions break sub-class... + 664809 Add command line option to gtester to allow skipping tests + 665067 cryptic assertion failure if nonsensical flag combinations... + 665184 Check ref. count before reffing/unreffing + 665298 Add 'Requires.private: libpcre' to glib-2.0.pc + 665391 update documentation around mainloops + 665607 ./configure is there for fiddling with cross-compile enviro... + 665634 g_dbus_node_info_new_for_xml() errors on unknown attributes... + 665685 Add a #define for the max length of a Unicode decomposition + 665733 GDBusConnection holds lock while calling destroynotify + +* Translation updates: + Norwegian bokmål + Spanish + + +Overview of changes from GLib 2.31.0 to 2.31.2 +============================================== + +* Monotonic time is now properly supported on Windows + +* glib-mkenums: fix @ENUMPREFIX@ with /*< underscore_name=... >*/ + +* EXPERIMENTAL: introduce new GSettingsSchema and GSettingsSchemaSource + APIs for the convenience of plugin system authors and those who wish + to introspect the contents of schemas. This API may change. + +* Improve the performance of GObject property notifies. + +* GDBus: + - fix a race when unowning a name immediately after owning it + - thread safety improvements on GDBusConnection + - fixes for exit-on-close functionality + +* Deprecations: + - add G_SIGNAL_DEPRECATED + - don't use G_DISABLE_DEPRECATED masking for functions anymore + +* docs + - tmpl/ is finally dead for glib + +* GIO: + - GInetAddressMask: new type for internet address range matching + - various GIO file and stream fixes + - improvements to attribute and fileinfo handling + +Overview of changes from GLib 2.29/2.30 to 2.31.0 +================================================= + +This release contains a huge number of changes (500 commits worth). The +list below attempts to summarise, but not every change is listed. + +* Major changes to threading and synchronisation + - threading is now always enabled in GLib + - support for custom thread implementations (including our own internal + support for errorcheck mutexes) has been removed + - a whole lot of dead code (to deal with the non-threaded case) has + been ripped out. This includes the racy path of GMainContext that + caused deadlocks with respect to child process exits in + single-threaded programs (such as gtester). + - libgthread is now an empty shell and g_thread_init() is no longer + required (and has been deprecated) + - GMutex and GCond can now be statically allocated without explicit + initialisation. Dynamic allocation for these types is deprecated. + - new types GRecMutex and GRWLock can also be statically allocated + without explicit initialisation. + - GPrivate can now be statically allocated and has an improved API. + Dynamic allocation of GPrivate is deprecated. + - GStaticMutex, GStaticRecMutex, GStaticRwLock, GStaticPrivate are + deprecated. + - GCond now uses monotonic time internally and a new API takes + monotonic time for timed waits, deprecating the wallclock API + - removal of the insane macro indirection used in the previous + implementation of threading and synchronisation APIs + - use SRWLock and CONDITION_VARIABLE APIs when available on Windows + (Vista and later) and emulate them on XP + - leaks of G(Static)Private-allocated data on some cases of thread exit + have been fixed + - simplified new thread creation API with the old API deprecated. The + concept of joinability has disappeared (all threads are joinable) as + have priority levels, 'bound'ness (ie: kernel vs. userspace threads) + and ability to manipulate the stack size. + - GThread is now a refcounted type + - other implementation details changed + +* Move headers for some deprecated functionality to a separate + deprecated/ directory. + +* New support for attribute-based deprecations to issue compiler + warnings instead of breaking the build and/or giving warnings about + implicit declarations (and possibly miscompiling). + +* GCache has been deprecated (after its last use was removed from our + platform over a year ago). + +* It is no longer possible to include individual headers (like + "ghash.h") -- you must #include <glib.h>. + +* The misguided experiment of allowing the program to stumble along with + missing GSettings schemas is now over -- the abort is back. + +* Clarify that fork() is not valid while using GMainContext. This is + because the internal resources of the GMainContext end up being shared + by both processes. We had an assert here but it was breaking existing + (valid) use cases as well, so it has been removed for now. + +* GApplication + - add ::shutdown signal as logical dual to ::startup + - don't use a GMainLoop: iterate the GMainContext directly (improves + quit logic) + +* Several portability fixes for Windows, OpenBSD, Solaris + +* Add new GValue API to specifically deal in signed chars (in case the + platform defines 'char' as unsigned) + +* some new API to mitigate the problems associated with calling setenv() + in a multi-threaded program + +* Use CLOCK_MONOTONIC unconditionally if the libc has support at compile + time (ie: stop checking for kernel support at runtime). + +* pkg-config files: + - drop -uninstalled variants + - remove gobject dependency on gthread + +* New macro G_ATOMIC_LOCK_FREE is defined if the atomic operations are + implemented without use of a mutex. Cleaned up atomic-related + compilation issues with mingw compilers on win32 systems. + +* SOCKS proxy and resolver improvements + +* Fix the spelling of G_IO_FLAG_IS_WRITABLE (was WRITEABLE) and + introduce a macro for backwards compatibility. + +* GDBus: + - many code generation updates and improvements + - some race condition fixes, including testcase hangs + +* GVariant: + - new g_variant_new_from_fixed_array() API + - substantial docs improvements/clarifications + +* GKeyFile is now refcounted and boxed + +* mount monitoring is now based on /proc/mounts (where available) + instead of mtab + +* new macros G_SOURCE_CONTINUE and G_SOURCE_REMOVE for returning from + GSourceFunc (so you don't have to remember what TRUE and FALSE mean) + +* use xlocale functions where available to avoid too much heavy lifting + in functions like g_ascii_strtod() + +* GMappedFile can now be created from an fd + +* error message strings grammar/i18n fixes + +* many docs updates + +* Partial list of bugs closed: + 70598 Unify GStaticMutex and GMutex. + 320888 optimization for g_main_context_wakeup + 398418 GChildWatch race condition? + 527214 g_timer_elapsed() returns random values + 580505 add a way to set/get name for a thread + 583511 race condition means g_main_loop_quit() does not work + 590808 GKeyFile should have a refcount and a boxed type in GObject + 592715 Document that g_str_hash() and g_int_hash() are not NULL safe + 631413 Add macros for GSourceFunc return values + 632049 not immediately clear what g_variant_get_fixed_array expects + 640212 "Error stating file" is not a friendly message + 640293 Use xlocale functions to implement g_ascii_strtod() + 640975 Check that error exists before trying to set it + 643934 GApplication lacking a logical dual for the ::startup signal + 651268 assertion failed in GDBus worker thread + 653987 g_key_file_get_integer cannot interpret trailing spaces + 654412 Documentation for g_variant_get_child_value unclear + 654563 info capplet: Failed to calculate disk space + 655366 missing GSettings schemas lead to obscure crashes + 656621 g_spawn_*() calls executables in current directory + 656679 [gi] Add two annotations to gio + 657992 Add glib__private__() API to share between glib,gio + 658188 _set_as_last_used_for_type generates a broken mimeapps.list + 658206 gsocks5proxy.c has invalid gettext use + 658207 glib-compile-schemas says "can not" + 658558 simpleaction: Fix documentation of :enabled + 658683 clean up charset/language threading issues + 658692 add introspection annotations to g_time_val_from_iso8601() + 658715 Duplicite strings + 658769 Invalid reuse of GError in GThreadedResolver + 658806 sign error in string hash implementation + 658976 gdbus-codegen's C namespace option needs to support Ugly_Case + 659070 gdbus-codegen generated code segfaults when property changes + 659082 gdbus-codegen: Single letter namespaces get dropped from names + 659212 GMappedFile should fail on non-regular files + 659324 _SPLICE_CLOSE_TARGET doesn't mark the output stream as closed + 659423 Use adaptive mutexes when available + 659427 Move deprecated code to a separate directory + 659646 gdbus-codegen produce code that warnings at build + 659690 Possible build warning in code generated by gdbus-codegen + 659699 property name collision when generating code for "Connection" + 659754 Add API to GMappedFile that allows to pass FD + 659838 incorrect types in introspection for g_object_bind_property + 659866 pthread_rwlock_t requires defined __USE_UNIX98 + 659870 gvalue: Fix signedness of g_value_get_char() + 659889 glib-2.29.92/gio-2.0.pc.in has a wrong line. + 659916 GObject size of 64K is not actively enforced + 659920 Missing setter for read/write property 'closed' of GIOStream + 659923 Add g_variant_new_fixed_array() function + 660013 Remove old g_atomic configure cruft + 660096 glib/rwlock tests failure (tests asserted) + 660130 Possible loss of user data when updating mimeapps.list + 660147 tracker causes g_critical in "gsettings list-recursively" + 660413 Make G_ASSERT_STATIC work with clang + 660498 Generated test code fails when the codegen changes + 660511 Use /proc/mounts for monitoring mounts, not /etc/mtab + 660536 Expose options for /etc/fstab entries + 660635 Deprecate g_thread_foreach + 660637 Pending dbus method calls not canceled on connection loss + 660739 kill off g_{mutex,cond}_{new,free}() + 660740 make GThread more standard + 660741 g_cond_timedwait is a disaster + 660743 macro wrappers for g_once_init_enter/leave + 660744 finish killing g_thread_init() + 660745 GPrivate leaks on Windows + 660791 [gio] Improve doc for g_file_make_directory_with_parents() + 660843 asyncqueue-test is broken + 660849 Remove cruft from g_strerror and g_strsignal + 660886 GDBusProxy: don't drop/complain about unknown props/signals + 660887 g_slice_set_config() is broken + 660994 Add g_main_context_ref_thread_default() + 661255 gio: enable test_peer regression test for OpenBSD + 661257 giomodules.c uses ":" instead of G_SEARCHPATH_SEPARATOR_S + 661318 tests use pthread without appropriate compiler/linker flags + 661421 Applications fail to initialize on GNU Hurd - commit + 661438 Implement G_GNUC_DEPRECATED/G_GNUC_DEPRECATED_FOR on Visual C++ + 661711 Sorting keys for GDrive, GVolume and GMount instances + 661763 desktop-app-info: Add support for X-GNOME-Keywords + 661896 /gdbus/connection/life-cycle is racy + 661914 Gstreamer/Totem locks up + 662100 regression: g_dbus_connection_close() triggers exit-on-close logic + +* Translations updates: + Belarusian + Brazilian Portuguese + British English + Bulgarian + Catalan + Catalan (Valencian) + Czech + Danish + Esperanto + French + Gujarati + Hebrew + Hungarian + Italian + Japanese + Lithuanian + Norwegian bokmål + Oriya + Polish + Russian + Serbian + Simplified Chinese + Slovak + Slovenian + Spanish + Tamil + Vietnamese + +Overview of changes from GLib 2.29.18 to 2.29.90 +================================================ + +* API/ABI changes: + - unix signal watches now match the API of all of the other sources + - revert the addition of g_date_time_source_new () from last release + +* networking and other fixes for Solaris + - we no longer support symbolic port names (ie: from /etc/services) + - check if -lsocket is needed + - fix g_socket_details_from_fd() + - avoid getmntinfo + - fix some harmless warnings + +* GDateTime improvements: + - generally improved standards compliance (with C99) + - support C99-specified format strings: %g, %G, %V, %c, %C, %w + - consult the locale for the preferred 12-hour time format (%r) + - drop support for non-standard %N and broken %W + - better support for formatting non-POSIX (eg: Arabic) numerals + - locale-related test case fixups, and fix some leaks + +* GTlsInteraction: add interaction method invocation guarantees + +* gdbus-codegen: post-process all interfaces when parsing >1 file + +* make GMainLoop, GMainContext and GSource boxed types + +* fix a race condition in the first use of g_get_monotonic_time() + +* lots gtk-doc cleanups + +* better intltool compatibility when generating pot file + +* avoid GCC-specific compiler options when not using GCC + +* Translation updates: + Belarusian + Brazilian Portuguese + Canadian English + Galician + Indonesian + Korean + Lithuanian + Norwegian bokmål + Portuguese + Spanish + Swedish + +Overview of changes from GLib 2.29.16 to 2.29.18 +================================================ + +* GDateTime is now respecting LC_TIME when formatting + +* GTimeZoneMonitor has been removed again + +* A new API for wallclock functionality has been added: + g_date_time_source_new(). This API is still experimental + and may be changed or removed before 2.30. + +* Bugs fixed: + 628904 Add credential support for FreeBSD and fix a socket issue + 650763 gdbus-codegen is broken with python 2.7 + 655129 GDateTime could provide api for implementing wall clocks + 656341 gtlsconsoleinteraction.c uses getpass() which isn't avail... + 656387 GCancellable can be used concurrently + 656443 Make GTlsInteraction ask_password cancellable + 656675 void functions should not return in glib 2.29.16 + 656772 g_variant_compare for uint64 incorrect + 656914 Load GIO_EXTRA_MODULES first, and ignore duplicates + 657083 The header langinfo.h is not available on all systems + 657084 gfileutils: fix docs/annotations for temp file methods + 657138 Some files missing in POTFILES.in + 657206 GInputStream leaked in g_file_icon_load_async() + 657243 g_cancellable_set_error_if_cancelled() documentation + 657274 Use detected PYTHON variable as shebang for gdbus-codegen + 657336 Speling fixes for glib found with codespell + 657452 plural forms needed + 657454 Translation comment needed + 657540 Print out file:// URL to coverage HTML report after building + 657593 g_test_trap_fork calls close(-1) + 646082 Addresses from GSocket should be normalized before returning + 657517 fix gio/tests/gdbus-peer on bsd + +* Translation updates: + Brazilian Portuguese + Galician + Norwegian bokmål + Punjabi + Russian + Serbian + Spanish + Swedish + Traditional Chinese + Uighur + + +Overview of changes from GLib 2.29.14 to 2.29.16 +================================================ + +* GTlsDatabase: an abstract class that provides support + or certificate and key lookup. An implementation will + be provided in glib-networking + +* GHmac: Support or HMAC digests + +* Misc new API: + - g_ptr_array_add_full: creates a GPtrArray with + a preallocated size and a destroy function + - g_desktop_app_info_get_show_in: checks if a GDesktopAppInfo + should be shown in a given desktop environment + - g_mkdtemp, g_mkdtemp_full, g_dir_make_tmp: create + temporary directories + +* Unify thread wakeup implementations of GMainContext + and GCancellable, and use eventfd for it when available + +* Show mounts in $XDG_USER_DIR in addition to /media and $HOME + +* Bugs fixed: + 636572 GTlsCertificateDB + 644601 Some tests need a running dbus session + 652284 deal with small key lengths + 652827 glib-2.29.8 no longer builds with mingw.org's toolchain + 653063 PEM parser fails parsing private key when put first + 654078 Fail to static linking with Glib library + 654450 New functions: g_ptr_array_new_full() + 654793 Add G_VALUE_INIT + 655044 GDesktopAppInfo: Add g_desktop_app_info_get_show_in() + 655148 gdbusconnection is broken when compiling with mingw + 655241 glocalfile.c no longer compiles with MinGW GCC + 655598 g_cancellable_get_fd: silently return -1 for NULL cancellable + 655664 gdbus should not abort if no dbus session is available + 655769 Use ZLIB_CFLAGS when compiling gio + 656031 Improve GVariant annotations + 656048 glib-codegen requires Python >= 2.5 + 656151 configure test logic inverted, doesn't match comments + 656152 GCC only syntax used, yet other compilers allowed by configure. + 656162 allow use of lcov 1.9 for coverage + 656282 GDBusProxy: uninitialized local variables can be freed + 656283 Failing tls connection cause assertion + 118563 Add g_mkdtemp in the spirit of g_mkstemp + 636405 Add g_return_if_fail() to g_settings_bind_with_mapping() + 656039 race condition between GDBusProxy signals and public API + 656492 g_io_channel_new_file failure (open(2) behavior wrt POSIX) + +* Translation updates: + Bulgarian + Esperanto + French + Galician + German + Hebrew + Indonesian + Italian + Norwegian bokmål + Russian + Spanish + Swedish + + +Overview of changes from GLib 2.29.12 to 2.29.14 +================================================ + +* Unicode improvements + - add g_unicode_script_{to,from}_iso15924 + - add G_UNICODE_SPACING_MARK define + - more normalisation improvements + - stop using deprecated g_unicode_canonical_decomposition() + +* GParamSpec: + - mark the 'name' field as 'const' and add a comment to the header to + help avoid future problems caused by bad hacks + +* Merge some (modified) patches from Debian: + - 03_blacklist-directories.patch + - add some blacklisted mount directories + - 60_wait-longer-for-threads-to-die.patch + - sleep longer in a test case, if needed to avoid failing + +* Units policy change: prefer use of SI units + - deprecate g_format_size_for_display, add g_format_size(_full) + +* GSettings: don't call g_error() when the schema is missing + +* GVariant support for arrays of object paths: + - new g_variant_{new,get,dup}_objv API + - support for g_variant_{new,get} '^ao' and '^a&o' similar to '^as' + +* GDBus: + - use new improved array-of-objects support and pass 'ao' as char** + instead of GVariant* + - improve handling of 'h' type (Unix file descriptor index) + +* GIO: + - fix compilation without USE_STATFS and USE_STATVFS + +* Documentation fixes + +* Bugs fixed: + 622921 Migrate from dbus-glib to glib's GDBus + 648271 Add g_unicode_script_to_iso15924() + 654948 Stop using deprecated g_unicode_canonical_decomposition() + 654988 g_atomic_int_add should document behaviour change + 655025 #define G_UNICODE_SPACING_MARK G_UNICODE_COMBINING_MARK + 655076 normalization misses some Full_Composition_Exclusion=True. + +* Translations updated: + Spanish + +Overview of changes from GLib 2.29.10 to 2.29.12 +================================================ + +* Add new API to do Unicode (de-)composition in atomic steps, + for use in Harfbuzz. + +* Bugs fixed: + 615895 (indirectly) support non-NULL-terminated regexes in GRegex + 617949 glib trunk fails to compile on Solaris w/ Studio 12... + 620423 Document the possibility to unset attributes + 627974 Floating reference headaches + 644687 Not finding cross-links in current doc set + 649246 g_output_stream_splice() cannot be used on 32-bit machines... + 653841 a helper script to build glib from git master on win32 + 653935 g_slist_free_full/g_list_free_full iterates twice in the list + 654017 tests: fix glib_translations_work() in gsettings unit test + 654085 Don't needlessly use "echo -e" when creating .def files + 654195 Add g_unichar_compose() and g_unichar_decompose() + 654232 GCancellable eventfd problems + 654394 suspicious use of floating references in GDBusInterfaceSkeleton + 654536 GSettings: lift key name length restriction to 64 + 654627 GParamSpec: intern property names + 654651 Better g_unicode_canonical_decomposition() + 654917 Make g_cclosure_marshal_generic the default signal handler + +* Translation updates: + Belarusian + Finnish + Korean + Latvian + Lithuanian + Norwegian bokmål + Turkish + + +Overview of changes from GLib 2.29.8 to 2.29.10 +=============================================== + +* New features: + - g_desktop_app_info_get_nodisplay: a function that is required + to port gnome-menus to GDesktopAppInfo + - g_hash_Table_iter_replace: new function to replace a value + while iterating over a hash table + - g_utf8_substring: convenience API to extract substrings from + UTF-8 strings + - g_action_group_add_entries: convenience API for creating lots + of actions quickly + - Use eventfd instead of pipes for waking up main contexts and + for cancellation when available + - GMatchInfo is now a refcounted boxed type + +* API changes in GAction: + - the 'set_state' entry in the GActionInterface vtable has been + renamed to 'change_state + - g_action_set_state has been renamed to g_action_change_state + - the 'state' property has been changed to read-only + - GSimpleAction can no longer be subclassed + +* Bug fixes + 647796 g_variant_new_variant is not marked as constructor + 652072 gmain: make use of signalfd() + 652168 Crosscompiling Fails if build<=2.24 and host >2.24 + 652750 make dist fails + 652758 GDataInputStream: Clarify g_data_input_stream_read_line docs... + 652822 Add a g_hash_table_iter_replace + 652897 tiny docs clarification for g_utf8_to_ucs4_fast + 653140 gmain: use Linux eventfd() for main context wake up + 653429 drop AM_MAINTAINER_MODE or enable it by default + 653484 GAsyncCallbacks should default to allow-none + Add missing fundamental types to the generic marshaller + +* Translation updates + Belarusian + Galician + Russian + +Overview of changes from GLib 2.29.6 to 2.29.8 +============================================== + +* Bug fixes + 646608 export_symbols variable for gio dynamic library is wrong + 646635 Fix introspection of GLib + 647930 Documentation: GDataInputStream _read_upto() version + 651745 Switch to _ prefixing rather than G_GNUC_INTERNAL + 651920 Improve qsort_r detection + 651959 gbitlock: "asm goto" is not available in gcc < 4.5 + 651998 gdbus-codegen: Use relative Python imports + 652000 Fix for gatomic.c on Windows/MSVC + 652002 Proposal to clean up gvaluetransform.c for MSVC + 652025 g_dbus_connection_register_object: error is not set... + 652081 Typos in a GBinding warning message + 652197 Improper handling of double values in GDBusMessage + Fix a deadlock in gobject finalization + +* Translation updates: + Czech + Galician + German + Hebrew + Norwegian bokmål + Spanish + Uighur + + +Overview of changes from GLib 2.29.4 to 2.29.6 +============================================== + +* Atomic operations have been rewritten from scratch to make use + of gcc builtins where possible. As a side-effect of this, calls + to g_atomic_ API with explicit casts may now be problematic; if + that happens to you, try first to remove the casts. Another + side-effect of the rewrite is that g_atomic_int_exchange_and_add + has been deprecated in favor of g_atomic_int_add. + +* A full set of atomic operations on pointers has been added, + including bit locks in pointer-size locations. + +* Access to quarks is now lockless + +* GObject data scalability has been greatly improved + +* g_data_time_format now supports alternative digits and padding + +* Introspection improvements: + - Add a boxed type for GVariantBuilder + - Annotation fixes in GDBus, GVariant, g_base64_ + +* Bugs fixed: + 502560 g_rand_double_range returns 'inf' + 612729 g_mkdir_with_parents can fail if the directory already exists + 617491 g_once() implementation is inefficient + 619418 Add a performance test for UTF-8 decoding functions + 619435 Make g_utf8_to_ucs4_fast() yet faster + 626549 G_STATIC_ASSERT_EXPR + 631231 bitlock: Fix detection and usage of futexes with Bionic + 632294 g_queue_remove() should return a boolean + 640518 GMainLoop has quadratic complexity when all pollfd's... + 642026 Race condition in g_static_private_free + 646635 Fix introspection of GLib + 648678 g_date_time_format(): support %O flags for localized numbers + 649480 Use MSG_CMSG_CLOEXEC in recvmsg in gio/gsocket.c + 649506 GTestFunc et al lacking Since tag + 649657 Don't return gboolean for functions that throw + 649775 glib-gio-gdbuscodegen-Makefile.patch + 649915 gsettings accepts unquoted strings longer than two characters + 649973 gthread: build unix tests only on unix + 649988 gdbus-codegen: Drop dependency on argparse + 650078 forkbomb building glib/tests/protocol + 650211 Optimization in key file parsing + 650236 Application over DBus implements action state incorrectly + 650345 g_key_file_has_key_full: New function to fix g_key_file_has_key... + 650458 reduce overhead in g_object_set/get_data + 650459 hash table consistency while calling destroy notify funcs + 650688 enforce rules about hash table modification + 650823 expand the set of atomic ops + 650874 codegen chokes on docs + 650882 use stdout instead of stderr for informational messages + 650884 fix compilation with gcc2 + 650885 implement glib credentials on OpenBSD (hackish) + 650935 G_GNUC_MAY_ALIAS and atomic ops + 651009 minor documentation fix + 651034 Regarding g_cond_wait after g_thread_pool_push in gthreadedresolver + 651133 race condition in GDBusConnection's emit_signal_instance_in_idle_cb + 651141 hashtable infinite loop + 651219 fix path to true(1) on OpenBSD + 651223 Fix some compile warnings on OpenBSD + 651327 Minor fixes for the gsocket API + 651467 Add pointer sized bitlocks + 651650 gdbus: Avoid busy wait loop + 651725 gmain: Cleanups and a new test case + 651745 Switch to _ prefixing rather than G_GNUC_INTERNAL + +* Updated translations: + Catalan (Valencian) + Esperanto + Hebrew + Hungarian + Russian + Spanish + + +Overview of changes from GLib 2.29.2 to 2.29.4 +============================================== + +* GDBus: + - Includes several new types to support modeling D-Bus + objects and interfaces more fully, and also introduces + an 'object manager' pattern: + GDBusInterface, GDBusObject, GDBusObjectManager + These interfaces have client-side implementations: + GDBusProxy, GDBusObjectProxy, GDBusObjectManagerClient + And server-side implementations: + GDBusInterfaceSkeleton, GDBusObjectSkeleton, GDBusObjectManagerServer + - The new gdbus-codegen utility uses these new classes + to generate C code and documentation from D-Bus interface + descriptions in XML + +* GTest: + - There is now a g_test_fail() function to mark + tests as failed + +* GDesktopAppInfo + - Now has a binding-friendly filename property + - Other new API to more fully expose desktop file contents: + g_desktop_app_info_get_categories(), + g_desktop_app_info_get_generic_name() + +* GHashTable: + - Several optimizations to reduce space consumption of + large hash tables, in particular tables that are used + to store sets. + +* Unix-specific APIs: + GLib now installs a separate header, glib-unix.h, that is + meant to collect Unix-specific APIs. For now, it contains + g_unix_open_pipe(), g_unix_set_fd_non_blocking() for dealing + with pipes and fds, as well as APIs to create mainloop + sources which can trigger callbacks on certain Unix + signals (SIGTERM, SIGHUP, SIGINT). + +* Bugs fixed: + 631379 GDBus nonce-tcp test failing + 632631 GLib-CRITICAL **: g_variant_new_string: assertion `g_utf8_validate (string, -1, NULL)' failed + 635694 gdbus aborting due to unauthorized socket in DBUS_SESSION_BUS_ADDRESS + 637561 Crash when using G_DBUS_SERVER_FLAGS_RUN_IN_THREAD + 642935 g_date_time_format() prints wrong value for %z and timezone -0800 + 643134 g_dbus_message_copy + 644941 glib-unix: New Unix-specific API + 646013 g_hash_table_remove_all_nodes optimization + 646309 glib cannot be cross-compilled for mingw32 + 646435 GTimeZone doesn't seem to be thread-safe + 646957 GIO chained calls don't work with a thread default context + 647594 README link to mailing list is broken + 647602 Cannot connect to remote message bus via TCP + 647746 The GSocketService documentation is incomplete. + 647826 API: gtester: Add g_test_fail() + 647903 GDesktopAppInfo: Add g_desktop_app_info_get_categories() + 648416 g_app_info_create_from_commandline ignores SUPPORTS_STARTUP_NOTIFICATION + 648423 Support G_DEBUG=trap-warnings + 648425 GDesktopAppInfo: Add "filename" property for bindings + 648966 Update g_unichar_iswide and g_unichar_iswide_cjk + +* Updated translations + Norwegian bokmål + Spanish + Turkish + Uighur + + +Overview of Changes from GLib 2.28.0 to 2.29.2 +============================================== + +* GApplication + - The documentation has been enhanced and clarified + - An opt-out for uniqueness has been added: G_APPLICATION_NON_UNIQUE + - GApplication now syncs settings before g_application_run() returns + +* GDBus + - Interface lookups are now happening in constant time + - Signature checking and handling of various unexpected + situations has been improved + +* GVariant + - The format accepted by the GVariant parser has beend documented + - GVariant accepts G_VARIANT_TYPE_VARDICT for a{sv} + +* GDateTime: + - The return value of g_datetime_compare() has been fixed to + match strcmp() semantics + - In order to handle problems with changing timezones, a GTimeZoneMonitor + has been added to GIO, and g_time_zone_refresh_local() can be + called to update the cached information about the local timezone + +* GOption now uses /proc/self/cmdline to set the program name instead + and only falls back to "<unknown>" if that is unavailable + +* GSettings: + - The schema compiler now warns about references to non-existing schemas + +* Commandline utilities are now fully translated + +* Signals can now indicate that collecting their arguments must + always happen, even in the absence of connected signal handlers, + using the G_SIGNAL_MUST_COLLECT flag. + +* Bugs fixed: + 635099 Memory leak in gdbus introspection when parsing xml + 640489 $ and ^ do not match lines if G_REGEX_MULTILINE|G_R... + 642042 Overriding GDBus org.freedesktop.DBus.Properties im... + 642052 g_timeout_add(_seconds) cannot handle large intervals + 642490 notify_desktop_launch() "g_variant_new_bytestring:... + 613269 g_type_get_qdata() doesn't work as I expected on subtypes + 624943 G_VALUE_NOCOPY_CONTENTS is undocumented + 637738 object_interface_check_properties never actually executes + 638185 GIOCondition should be annotated as "flags" + 639478 GDBusServer's g_dbus_server_new_sync() function should just... + 641755 Add g_settings_get/set_uint() helpers + 641768 dconf gsettings backend silently drops writes if it can't... + 642797 g_app_info_get_default_for_type() broken for subtypes + 642825 Unnecessary assertion failure in g_option_context_parse() + 642944 NULL key lookup using g_hash_table_lookup_extended() + 643074 Incorrect documentation for g_socket_receive() and g_socket... + 643197 g_application_id_is_valid docs imply no valid ids + 643468 GApplication docs: Warn that handling "command-line" means... + 643478 GApplication::local_command_line vfunc documentation seems wrong + 643624 Can g_variant_unref() on an already free'd variant + 643649 g_application_run() should say that argc/argv can be NULL + 643780 shouldn't need to create an action group to use actions... + 643795 g_timeout_add_seconds fires with intervals 1 second longer... + 644309 Program name is not set when using GtkApplication + 644428 Crash in failure section of g_markup_collect_attributes() + 644465 undefined reference to `_usleep' + 644552 g_timeout_add_seconds(1, ...) may have a latency of up to 2... + 644607 Correct internal definition of C_() + 645789 annotations for g_file_*_contents + 646039 g_settings_list_children() returns child that cannot be opened + 646310 Accept range with only min or max + 646420 g_dbus_method_invocation_get_parameters() docs should say... + 646843 occasional abort on autologin + 646985 add G_APPLICATION_NON_UNIQUE flag + 647579 gsettings: Implement reset-recursively + 647600 gsettings description has typo + +* Translation updates + Afrikaans + Bulgarian + Bengali India + British English + Bulgarian + Catalan + Czech + Danish + French + Galician + German + Greek + Gujarati + Hebrew + Hungarian + Italian + Japanese + Korean + Lithuanian + Polish + Portuguese + Romanian + Serbian + Simplified Chinese + Spanish + Swedish + Traditional Chinese + Uighur + Vietnamese + + +Overview of Changes from GLib 2.27.93 to 2.28.0 +=============================================== + +* Bugs fixed: +641363 GInitable documentation isn't clear about that finalize... +641395 Add more data about the origin application to the "Lau... +641411 gdesktopappinfo signals lost if it's the session bus... +641477 glib-mkenums uses unportable #! line +641572 Add @EXEEXT@ to pkgconfig binary name +641688 glib installs GSettings.html and gsettings.html + +* Translation updates: + Galician + Italian + Korean + Punjabi + + +Overview of Changes from GLib 2.27.92 to 2.27.93 +================================================ + +* Bugs fixed: + 637013 gio/gdbusmessage.c fails to compile on Solaris + 640192 Error creating a Gio.Settings object through py... + 640261 Minimum version for external pcre needs to be.. + 640262 GActionGroup contains redundant TYPE macros + 640436 Make load_user_special_dirs() resistant to non... + 640695 g_key_file_load_from_file() mishandles a CR-LF... + 640724 can't compile gio due to format string issues + 640725 can't compile tests due to format string issue + 640807 improve GVariant behaviour with invalid pointers + 640823 wrong documentation for g_source_add_child_source + +* Translation updates: + Bulgarian + Galician + Hebrew + Norwegian bokmål + Spanish + Traditional Chinese + + +Overview of Changes from GLib 2.27.91 to 2.27.92 +================================================ + +* Update to Unicode 6.0 + +* Update PCRE to 8.12 + +* Bugs fixed: + 637696 g_unix_connection_send_fd() doesn't work + 638872 null settings backend bug + 640042 GtkApplication's warning about not connecting... + +* Translation updates: + Arabic + Basque + Estonian + Greek + +Overview of Changes from GLib 2.27.90 to 2.27.91 +================================================ + +* Bugs fixed: + 638838 gdesktopappinfo: Don't crash if we don't have a desktop filename + 638894 Splitting on \s* gives no result + 639064 Update gschema.dtd + 639084 Copy/paste error in GSettings::writable-changed signal + 639177 SIGSEGV for GApplications with G_APPLICATION_IS_SERVICE + +* Translation updates: + Estonian + Galician + Indonesian + + +Overview of Changes from GLib 2.27.5 to 2.27.90 +=============================================== + +* Test reports created by gtester-report can now + include revision information + +* The g_desktop_app_info_launch_* family of functions + now emit a DBus signal when an application is launched. + Additionally, there is a new variant + g_desktop_app_info_launch_uris_as_manager(), which + gives more control over the launched process. + +* The memory and null GSettings backends are now available + as public API + +* g_get_locale_variants() is a new function that returns a + list of variants of a locale identifier + +* Bugs fixed: + 587898 I/O timeouts for GSocket + 606960 gio: Add extension point for informing parties... + 631980 Handle an optional <revision> node in the report... + 634569 Document that g_variant_builder_add_value consumes... + 635998 Make _g_compute_locale_variants public + 636806 Add g_{memory,null}_settings_backend_get_default + 637262 Need a binary DER version of ::accepted-cas + 637544 Skip fsync() on btrfs + 637720 void functions should not return a value. + 637738 object_interface_check_properties never actually... + 637759 GIOChannel: fix a crash in g_io_channel_read_chars() + 637852 Updates to glib.vsprops file for MSVC 2008 builds... + 637858 Updates to test/testglib.c... + 638349 parameter name of g_variant_new_* may conflict... + +* Translation updates: + Hebrew + Norwegian bokmål + Simplified Chinese + Spanish + Swedish + Uyghur + Vietnamese + + +Overview of Changes from GLib 2.27.4 to 2.27.5 +============================================== + +* Network support: + - Add g_tls_certificate_verify() to verify a certificate + - Add GTlsConnection:use-system-certdb + - Other TLS api additions + +* GIO: + - Add g_io_stream_splice_async()/_finish() to splice two iostreams + - Add g_emblemed_icon_clear_emblems() and make GEmblemedIcon derivable + - Remove GPeriodic; it did not receive the necessary review and + integration work to declare it stable + +* GSequence: + - New methods g_sequence_lookup() and g_sequence_lookup_iter() + +* Bugs fixed: + 617254 Missing g_sequence_lookup + 632544 g_dbus_connection_send_message can not send a locked message... + 633350 g_hostname_to_ascii() ignores non-ascii dots + 634583 Better error reporting for g_variant_parse() + 635007 gsetting enum rule don't work for out-of-srcdir builds + 635626 GDBus message idle can execute while flushes are pending + 636100 Can't read GSettings:backend property + 636305 Typo on g_queue_remove_all() function description + 636311 appinfo: tweak application positioning for content-types + 636351 g_simple_async_result_is_valid lacks a version tag + 636387 gdb autoload files shadow the "dir" builtin + 636673 g_simple_async_report_error_in_idle should allow object... + 637147 Add a "delay-apply" property to GSettings + 637171 emblemedicon: add g_emblemed_icon_clear_emblems() + 637237 gapplication: plug a memory leak + +* Translation updates: + Estonian + Galician + Hebrew + Norwegian bokmål + Simplified Chinese + Spanish + Traditional Chinese + Vietnamese + + +Overview of Changes from GLib 2.27.3 to 2.27.4 +============================================== + +* GIO + - Mounts are treated as hidden if they have a path element + that starts with a dot + - GAppInfo gained API to differentiate between recommended + and fallback mime handlers + - g_cancellable_create_source: creates a GSource that triggers + when the GCancellable is canceled + - GPollableInput/OutputStream: Interfaces for pollable streams + - TLS support has landed, with an extension point that is + implemented in glib-networking + +* GLib + - Mainloop sources can now have 'child sources' + - g_get_runtime_dir: New function to return the XDG_RUNTIME_DIR + +* Bugs fixed: + 530786 GFileMonitor "changed" signal underdocumented + 588189 TLS support for GSocket* + 630357 g_object_new_valist uses uninitialized memory + 630559 typo in public string in gsocks: 'The SOCKSv5 require... + 632445 Documentation refers to removed GNOME 2.0 porting guide + 634239 Child GSources + 634241 Add pollable input/output streams + 634504 allow passing a NULL emblem to g_emblemed_icon_new() + 634613 unsufficient g_get_user_runtime_dir() documentation + 635640 schema should inherit gettext-domain from schemalist + 635768 Protect g_file_monitor_set_rate_limit() against negative... + 635882 Fix the wrong-category schema test + 635187 Wrong type of GVariant received in an action... + +* Updated translations: + Galician + Italian + Norwegian bokmål + Uyghur + + +Overview of Changes from GLib 2.27.2 to 2.27.3 +============================================== + +* The GTimeSpec type that was introduced in the 2.27.2 has been + dropped again in favour of APIs that return microseconds as + 64-bit integer. + Affected functions: + g_source_get_time + g_periodic_unblock + g_get_monotonic_time + g_get_real_time + The similar GTimeVal struct is still around, but its use is + discouraged. + +* GTimer is now using monotonic time unconditionally + +* There are some new functions to facilitate error reporting + in async GIO APIs: + g_simple_async_result_take_error + g_simple_async_result_new_take_error + g_simple_async_report_take_gerror_in_idle + +* There is new convenience API to us GVariant dictionaries: + g_variant_lookup + +* It is now possible to delay sending match rules to the + D-Bus daemon in GDBus: + G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE + +* Support has been added for XDG_RUNTIME_DIR: + g_get_user_runtime_dir + +* Various fixes for Win64/MSVC builds have been committed + +* Bugs fixed: + 620263 Add g_clear_object, g_clear_pointer, g_clear_boxed + 633075 update Project Files and sources for MSVC 2008/C89 + 633381 gsettings Makefile rules should handle empty list... + 633685 Use g_simple_async_result_{new_,}take_error + 633686 Add g_simple_async_report_take_gerror_in_idle + +* Translation updates: + Belarusian + Galician + Hebrew + Punjabi + Spanish + + +Overview of Changes from GLib 2.27.1 to 2.27.2 +============================================== + +* GApplication + - Export actions over DBus and support activating them from remote instances + - Support environment passing + +* GSettings + - The gsettings utility has a list-recursively command + - The gsettings utility has commandline completion for enum values + +* GLib is now linked against librt and uses monotonic time for + timeouts and GPeriod sources. GSource has a new g_source_get_time() + which returns monotonic time, and g_source_get_current_time() has + been deprecated + +* Bugs fixed: + 158725 free linked list with data + 626320 GVariant: Avoid locking in g_variant_get_child_value() if possible + 629247 add gsimpleasyncresult methods to take over a GError + 629274 GNetworkService does not do fallback when there is no SRV record + 631264 gsettings-tool choice/range support + 631482 g_date_time_from_instant: 1000000000000000000 + 632169 docs for manual use of gsettings-data-convert + 632571 Add equivalent to gconftool-2's -R option + 633115 GSettings m4 doesn't fail the build for broken schemas + 633206 Default g_application_local_command_line() doesn't set exit_status... + 633339 support more complex gapplication setups + 633356 Make timeout G_MAXINT mean "no timeout" + +* Translation updates: + Catalan (Valencian) + Indonesian + Japanese + + +Overview of Changes from GLib 2.27.0 to 2.27.1 +============================================== + +* GDateTime now has full week number support. + New API: g_date_time_get_week_numbering_year + +* The GSettings schema compiler will now skip over + broken .xml schema files instead of aborting altogether + +* GSettings now works properly on bigendian systems + +* GSettings has more complete support for ranges + New API: + g_settings_get_range + g_settings_range_check + The gsettings commandline tool supports ranges too. + +* GApplication has been rewritten; see the API docs for details + and examples. The action support is not complete yet. + +* The GLib mainloop has gained 'dispatch to context' functionality, + which can replace manually created idles in many cases. + New API: + g_main_context_invoke + g_main_context_invoke_full + +* The gio-desktop-app-info-lookup extension point has been + removed from GIO. GIO now uses x-scheme-handler mimetypes when + looking for default applications. + +* On win32, make g_get_user_data_dir() return the CSIDL_LOCAL_APPDATA + folder on Windows, and not CSIDL_PERSONAL. This matches what Qt does, + and has been widely requested. Also make g_get_user_config_dir() return + this and not the (roaming) CSIDL_APPDATA folder. + +* A periodic event clock has been added in GIO: GPeriodic. Note that this + API is still experimental and expected to undergo changes before it + will be incorporated into a stable GLib release. Use at your own risk. + +Bug fixes: + 613822 gobject signal connect/disconnect not thread safe + 618737 "dispatch to context" functionality + 620710 g_get_user_data_dir() uses CSIDL_PERSONAL and not CSIDL_APPDATA + 623400 acquire context before dispatching + 627126 gsettings schema files don't get installed on FreeBSD + 627171 g_socket_new_from_fd() doesn't set the right protocol + 628876 Wrong error description + 628937 gracefully handle broken schemas + 629274 GNetworkService doesn't fallback when there is no SRV record + 629289 g_error() used wrong, produces core dump + 629687 leaks class refcount in gsocketcontrolmessage + 629849 GLib-CRITICAL **: g_source_get_context: assertion `!SOURCE_... + 629945 GDBus deadlock in g_bus_get_sync() + 630000 g_date_time_difference + 630077 GDateTime week number support + 630185 Allow NULL strings in g_quark_try_string() + 630797 docs mention non-existent g_object_dispose() + 630968 gschema-compile problems on power g5 + 631263 GSettings needs range/choice APIs + 631264 gsettings-tool choice/range support + 631379 GDBus nonce-tcp test failing + 631410 Port gapplookupgconf.c to using x-scheme-handler/ + 632884 Possible deadlock in g_object_remove_toggle_ref() + +Transation updates: + Basque + Brazilian Portuguese + British English + Bulgarian + Czech + Dutch + Estonian + French + Galician + German + Greek + Hebrew + Hungarian + Japanese + Lithuanian + Polish + Portuguese + Romanian + Simplified Chinese + Slovenian + Spanish + + +Overview of Changes from GLib 2.25.15 to GLib 2.27.0 +==================================================== + +Build: + - massive restructuring to reduce #include abuse + - tweaks to silence some harmless compiler warnings + - rename gschema-compile.c to glib-compile-schemas.c + - Windows fixes + - fix building with zlib < 1.2.4 on win32 + +GDateTime: + - better msgctxt for translating month and weekday names + - API is changed quite a lot, implementation is improved + - GTimeZone is now exposed + +GObject: + - make ordering for overridden interface properties consistent + - ->priv structures are limited to 64k but this was not documented, + and exceeding this limit produced bad results. Add docs and enforce + the limit properly. + - add g_object_class_install_properties() to install multiple + properties in one go + - improve debugging output for GValue containing G_TYPE_STRV + +GIO: + - fix priority sorting of GIO extensions + - add GCredentials support on FreeBSD + - fix support for IPv6 addresses in URI parsing functions + - GSocketClient fixes for when g_socket_connect succeeds immediately + - clarify string encoding for GFile constructors in docs + - new functions g_data_input_stream_read_upto{,async,finish} + - tweak confusing documentation for g_output_stream_write() + +GDBus: + - GDBusMessage can now be locked and copied (like in libdbus) + - GDBusConnection filter function API has changed again + - GDBusServer: ::new-connection now declares if the connection was claimed + - add a partial workaround for GObject bug 627724. + - very many memory leaks fixed + +GVariant: + - check for size == 0 in g_variant_get_bytestring to avoid a crash + when attempting to get_bytestring() from an empty array + - improve gobject-introspection annotations + +GSettings: + - add GSettings Windows registry backend + - some internal tweaks to the backend API + - remove g_settings_list_items + - add g_settings_list_children and _list_keys to replace it + - add schema compiler restrictions for dealing with lists + - don't automatically emit value changed signals on writability + changes + +Other: + - constify the 'parser' vtable param to g_markup_parse_context_push() + - plug many memory leaks in test cases + +Bugs closed: + 50076 Time API to go with date API + 584284 g_data_input_stream_read_until_async different from sync version + 624546 Modification of GDBusMessage in filter function + 626919 Let g_object_class_install_property() return the installed GParamSpec* + 628029 GDateTime missing get_week_of_year method + 628253 Interface properties not listed in a consistent order + 628331 Plug lots of mem leaks in gio test suite + 628345 Plug a mem leak + 628436 Plug a mem leak + 628505 Fix building with zlib < 1.2.4 on win32 + 628839 [PATCH] datetime: Rename shadowing variables + 628904 [PATCH] Add credential support for FreeBSD and fix a socket issue + 628952 incorrect glib_major_version and other variables on cygwin. + 629192 g_strdup_value_contents(): dump GStrv more usefully + 629251 g_socket_client_async_connect_complete: assertion failed + 629259 Failed to connect to "::1" + 629328 g_markup_parse_context_push doesn't respect const structs + 629429 month "May" short and full form same with "GDateTime" msgctxt + 629689 GDBusConnection leaks its GCredentials + 629698 Segfault in g_variant_get_bytestring() + +Updated translations: + Arabic + Armenian + Basque + British English + Czech + Finnish + Galician + German + Hungarian + Indonesian + Japanese + Lithuanian + Norwegian bokmål + Polish + Portuguese + Punjabi + Simplified Chinese + Slovenian + Spanish + Swedish + Swedish + Traditional Chinese + +Overview of Changes from GLib 2.25.14 to GLib 2.25.15 +===================================================== + + * GIO + - Memory leak fixes + - The GZip(De}Compressor can now process header information + - Support for network proxies has been added, with the GProxy + interface and the gio-proxy-resolver extension point. GIO + includes SOCKSv4 and SOCKSv5 implementations, and libproxy + is also going to provide an implementation of this extension + point. + - There are GAction and GActionGroup interfaces now, which will + be used in GApplication in the near future. + + * GObject + - There are now convenience macros for defining boxed and + pointer types + + * GDBus + - Memory leak fixes + - GDBusProxy for well-known names can now auto-restart + the service if the name owner disapperas + - Filter functions are now allowed to modify messages + + * GLib + - GDateTime is a replacement for GDate that supports time + and timezone information. + + * Bugs fixed: + 50076 Time API to go with date API + 449565 Add G_DEFINE_BOXED_TYPE() + 617691 Add GZIP header processing to GZlibCompressor/GZlibDecompressor + 622184 add g_memory_output_stream_steal_data + 624546 Modification of GDBusMessage in filter function + 627088 Build failure in gdbus-peer.c on FreeBSD + 627181 save a memdup + 627182 Plug a mem leak in the gdbus-connection test + 627187 Plug some gdbus mem leaks + 627188 gdbus-non-socket test occasionally fails + 627252 G_OPTION_FLAG_NO_ARG is only for callback options + 627392 gdbus commit 8a3a4596 breaks win32 compile + 627407 FTBFS on !linux UNIX platforms + 627604 String error: 'that' twice in a row + 627969 ABR in g_file_open_tmp + 628084 gdbus-peer fails with assertion + 628193 Miscellaneous string fixes + 628296 abort() in gsocketconnection.c + 628309 Plug a mem leak in GConverterOutputStream + 628317 GEmblemedIcon:equal implementation is buggy + 628323 Fix invalid reads + 628327 Plug a mem leak + 628328 Plug a mem leak + 628329 Don't leak the FD list + 628324 Invalid reads in gdbus-export test + + * Updated translations: + British English + Danish + Galician + Hebrew + Punjabi + Serbian + Spanish + Traditional Chinese + + +Overview of Changes from GLib 2.25.13 to GLib 2.25.14 +===================================================== + +* GDBus + - Make the closure variants of GDBus apis work + - Make error unregistration work + - Use async IO in the IO thread (626748) + +* GIO + - Make g_simple_async_result_is_valid work without source (626208) + - GSocketClient: add a timeout property + - Fix memory leaks in GSocketClient + - Handle async vs. sync correctly in GSocketConnection stream (616458) + - Declare stream base classes as abstract + - Clarify semantics of g_output_stream_write() (627071) + +* Other + - Improve test coverage for GDBus, GRegex, GAsyncResult + - Drop dead code in pcre, xdgmime + - Fix a race condition in gtester (578295) + - Avoid an extra allocation in GAsyncQueue (626704) + - Add test case for non-socket GIOStream (626841) + - More explicit GVariant docs (622770) + - Imroved docs for GAsyncInitable and GSimpleAsyncResult (602417) + +* Translation updates: + - Galician + - Norwegian bokmål + - Punjabi + - Simplified Chinese + - Swedish + + +Overview of Changes from GLib 2.25.12 to GLib 2.25.13 +===================================================== + ++-------------------------------------------------------------------+ +| WARNING: There have been no breaks in API or ABI. Weird, eh? | ++-------------------------------------------------------------------+ + +The primary purpose of this release is to fix a serious problem with +glib 2.25.12: glibconfig.h (as generated on a Fedora amd64 system) was +being distributed in the tarball. It was being used to build some parts +of glib on other systems (eg: 32bit ones). This was causing some very +serious problems. + +There have been many other improvements, however: + + Build and testing: + - vastly improved test coverage + - old tests moved to the gtester framework + - gtester Makefile modified so that the tests only run once + - cleanup of how we handle includes while building glib + + GVariant: + - add a g_return_if_fail (utf8) to g_variant_new_string() + + GDBus: + - perform extra sanity checks when serialising messages + - add API to query and set the byteorder of a GDBusMessage + - improve debug output, add some extra options + - if exiting due to the bus disconnecting us, print an error message + explaining why + - sort property names correctly + - don't bother sending RemoveMatch when we will close the connection + anyway + - use effective uid/gid for credential passing + + GSettings: + - add G_SETTINGS_BIND_INVERT_BOOLEAN for inverting boolean bindings + without mapping functions + - mark all strings in the schema compiler for translation + + Binding: + - improve closure support for bindings + - copy GSettings INVERT_BOOLEAN flag + + Other: + - fix another complicated GCancellable deadlock possibility + +Bugs closed: + 599590 glib build doesn't look for correct pkg-config + 619026 avoid warning in gutils.h when using gcc with -Wconversion + 624739 Please fix POTFILES.in + 625472 Valgrind claims uninitialized bytes used + 625500 g_date_set_time_val documentation doesn't mention local time + 625628 GDBusProxy: wrong property name sorting + 625753 Incorrect flags used in g_dbus_connection_call_sync() + 625827 Expand documentation about error quark naming + 625988 builddir != srcdir issues + 626107 glibconfig.h is being disted + +Updated translations: + French + Galician + Hebrew + Norwegian bokmål + Spanish + + +Overview of Changes from GLib 2.25.11 to GLib 2.25.12 +===================================================== + ++-------------------------------------------------------------------+ +| WARNING: There have been many API changes in GDBus -- sending | +| messages, subscribing to signals, closing connections and | +| registering subtrees are affected. The ABI for GSettingsBackend | +| has also been changed. For both reasons, a new dconf release is | +| required (and will be along soon). | ++-------------------------------------------------------------------+ + +Build: + - cleanup automake setup + - rename configure.in to configure.ac + - various docs fixups + - move glibconfig.h to glib/ + - disable dtrace support on Mac OS (which has incompatible 'dtrace') + +GSettings: + - add support for vendor override files (to change the default values + in a schema) + - change GSettingsBackend vtable + - add g_settings_reset() + - support binding to G_TYPE_STRV properties + +GDBus: + - many bug fixes, including a serialisation fix + - stop handling incoming connections as soon as stop() is called + - proper support for file descriptor passing + - new flags parameter for sending messages + - new flags parameter for subscribing to signals + - always reset the message serial when sending a message unless + G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL is given + - constness fixes for introspection structures + - clean ups to subtree registration API + +Other: + - fix divide by zero bug in g_malloc_n functions + - GIO: don't blindly assume that SOCK_CLOEXEC is supported + - make GObject property notify freezes threadsafe + - GIO: clean up credentials passing + - GApplication: make default-quit not apply if register=FALSE + - GIO: add annotations for gobject-introspection + +Bugs closed: + 166020 use GAtomic for refcounting + 617483 Credentials passing + 622005 [GApplication] no way to modify the "default-quit" property + 623293 vendor override files + 623810 Message serialization bug + 623815 Don't check sender for GDBusProxy objects where name is not set + 624473 GDBusSubtreeIntrospectFunc return type + 624483 GDBusSubtreeEnumerateFunc clarification + 624484 GDBusSubtreeDispatchFunc clarification + 624754 gdbusaddress.c missing sys/wait.h + 624968 div by zero in g_malloc_n family + 624991 GSettings mapping for G_TYPE_STRV + 625383 Add missing GI annotations + +Updated Translations: + Armenian + Galician + German + Hebrew + Kazakh + Romanian + Simplified Chinese + Spanish + +Overview of Changes from GLib 2.25.10 to GLib 2.25.11 +===================================================== + ++-------------------------------------------------------------------+ +| WARNING: There have been minor API changes in GDBus and GVariant. | +| These API changes will not affect many users, but they do require | +| a new version of GTK+ to be installed. | ++-------------------------------------------------------------------+ + +Build: + - add a --disable-Bsymbolic configure flag to disable linking with + -Bsymbolic-functions + - this release sees the complete removal of the old 'g*alias' hacks + - honour the NOCONFIGURE environment variable from autogen.sh + - use proper feature test macros for isnan + - use pkg-config to check for zlib + - add ACLOCAL_AMFLAGS to Makefile.am + +GDBus: + - hide Class and instance structures for all GDBus types except + GDBusProxy. This breaks API by preventing subclassing, but probably + nobody was doing that. + - add new GDBusConnection call to support flushing all pending + outgoing messages + - change the register_object API to add a reference to the + GDBusInterfaceInfo object so the caller need not keep it alive + themselves + - don't rewrite the serial number when sending messages that already + have a serial number + - better error checking for DBUS_SESSION_BUS_ADDRESS environment + variable + - switch to g_parse_debug_string for G_DBUS_DEBUG and add a lot of new + flags + - add support for temporarily freezing a freshly created + GDBusConnection. Do this until after the ::new-connection signal + has finished running on GDBus services. + - never require non-closed connections (the user is incapable of doing + this due to the obvious race) + - remove weird/misleading redundant check on NameOwnerChanged signal + - emit GDBusProxy::g-properties-changed on NameOwnerChanged + +GVariant: + - the 'g_variant_{new,get}_byte_array' APIs have been removed + - g_variant_{new,get,dup}_bytestring has been added, with different + arguments and different behaviour + - g_variant_{new,get,dup}_bytestring_array has been added, doing + essentially the same thing as the 'strv' functions, but with byte + strings instead of utf8 strings + - G_VARIANT_TYPE_BYTESTRING ('ay'), BYTESTRING_ARRAY ('aay') and + STRING_ARRAY ('as') constants have been added + - the undocumented behaviour that g_variant_get_strv() deserialised + arrays of object paths or signature strings has been dropped + - additional varargs support for converting bytestrings or bytestring + arrays with ^ay ^aay ^&ay and ^a&ay + - improved gobject-introspection annotation + - fix a problem with GBuffer calling g_slice_free for the wrong type + - fix leaks in the type inferencing code of the parser + +GSettings: + - improved documentation + - updated schema XML DTD, now xincluded into the docs + - added support for schemas that extend other schemas (using the + 'extends=' attribute). Values of keys in the base schema can be + overridden using <override>. + - added theoretical support for lists (using the 'list-of=' attribute) + - lots of new tests + - add support for flags (implemented similarly to enums) + - add support for generating .enums.xml files to gsettings.m4: + gsettings_ENUM_NAMESPACE = org.example.myapp + gsettings_ENUM_FILES = ../path/to/*.h + will generate org.example.myapp.enums.xml with mappings for all + enums and flags in the specified .h files. + - warn with g_message() if the 'memory' backend is used by default + (ie: because no other GSettings backends are installed) + - fix get_property() for GSettings::schema + - command line tool: fix a bug that prevented non-basic values from + being set due to a premature free + - command line tool: bash completion support + - chain up in _finalize + - add a new g_settings_get_mapped API to read settings that require + post-processing + - retry with the translated or schema default value if the + GSettingsBindGetMapping function fails + - schema compiler: never fail due to empty schema directories (but + warn) + - peek rather than ref/unref the GEnumClass in the mapping function + - schema compiler: compile *.enums.xml before *.gschemas.xml to ensure + that we have all the enums that the schemas may reference + - schema compiler: improve accuracy of line numbers in error reports + - fix crashes in the keyfile backend caused by invalid group names in + the keyfile + +Other: + - always intern GBinding prop names + - base64: remove asserts preventing conversion of empty strings + - document NULL special-cases for GValueArray + - GNode docs improvements + - improve detection of 'system internal' mounts + - fix leaks in the inotify GFileMonitor implementation + - annotate all custom GIO GSources to improve debugging (e.g. using + SystemTap) + +Tests: + - Turn on glibc malloc checking features for make check + - improvements for GSettings tests, plus new tests + - improved tests for GKeyfile + - new tests for GDir, GSList, GSList, GAppLaunchContext, + CharsetConverter, GIcon, ... + - move some tests to GTester (tree tests, uri tests) + - generally, really an awful lot of new tests + - don't try to allocate 2gigs of memory anymore for the array test + + 552363 g_value_array_{insert,prepend,append}'s special cases for NULL + 561248 Improve return value description from g_node_prev/next_sibling() + 570036 Add ACLOCAL_AMFLAGS to Makefile.am + 576833 g_sprintf add a reference to g_strdup_printf + 576854 g_strconcat() documentation should provide a hint about bad l10n + 582227 reference: add other URI functions to 'URI Functions' section + 599223 should provide g_spawn_* variants that take a GAppLaunchContext + 610784 array test failing + 613057 Leak in inotify GFileMonitor implementation + 620536 Annotate all custom GIO GSource using g_source_set_name + 620913 More control with G_DBUS_DEBUG + 622124 implement flags + 622127 GSettings extended key validation + 622128 retry with default value for failed mapping + 622294 More annotations for GVariant + 622565 glib-compile-schemas fails when no schemas + 622600 Fix missing prototype warning + 622813 gsettings mapping & enum buglet + 623142 Ensure ::new-connection runs before processing D-Bus messages + 623143 Never require non-closed connections + 623319 use g_parse_debug_string for dbus debug flags + 623401 process enums first + 623402 schema compiler reports wrong line numbers + 623407 g_keyfile_settings_backend_new crashes with the key "/" + 623473 zlib should be checked with pkg-config + 623537 GDBusProxy has weird checking on NameOwnerChanged + 623538 GDBusProxy::g-properties-changed emission for corner cases + 623692 directory with file at multiple MLS levels may display empty + 623720 gschema.dtd does not contain enum definitions + 623770 quoting of expand_macro in gdesktopappinfo.c + 623772 gdesktopappinfo.c, function child_setup + 623780 g_unix_is_mount_path_system_internal + 623954 g_settings_finalize + 623955 Dubious return values + +Updated translations: + Galician + Hebrew + Norwegian bokmål + Spanish + +Overview of Changes from GLib 2.25.9 to GLib 2.25.10 +==================================================== + ++----------------------------------------------------------------+ +| WARNING: There have been API changes in GDBus. Users of these | +| APIs will need to be adapted. In particular, a new release of | +| dconf is required to go along with this one. There has also | +| been a change in the GSettings backend API used for keyfiles. | ++----------------------------------------------------------------+ + +* GDBus: + - add direction parameter to filter functions (API change) + - allow calling other interfaces with a GDBusProxy + - padding added to class struct fields (ABI change) + - fixes for closures-based functions + +* GVariant: + - new is_floating() call + - add g_value_take_variant() call (required for marshallers) + +* GSettings: + - support for binding GParamSpecEnum properties + - ifelse-style condition support for GLIB_GSETTINGS m4 macro + - remove gsettings-schema-convert tool (now in GConf) + - allow introspection of all installed schemas + - allow introspection of the keys in a schema + - rewrite keyfile backend (API change) + +* GNIO: + - don't implicitly close GSocket until it is destroyed + - windows fixups + +* Other: + - allow GChecksum to take (NULL, 0) for data/length + - GRelation and GCompletion are now deprecated + - introduce G_PARAM_DEPRECATED and G_ENABLE_DIAGNOSTIC + - add working directory to GApplication platform data + - lots of documentation cleanups + - PCRE updated to 8.02 + +* Build: + - the IA__g_* style symbol aliasing has been disabled and replaced with + the -Bsymbolic-functions linker flag on platforms that support it. + Please be on the watch for portability issues and report them to us. + - many test cases have been moved to the GTester framework + - lcov support has been added for tests + - many windows fixes + +* Bugs fixed: + 501057 lcov coverage suite and GLib integration + 551271 deprecate GRelation + 601686 Implement diagnostic mode + 603309 GSocketOutputStream broken on Windows (?) + 616718 GLIB_GSETTINGS macro can't be used conditionally + 616855 GSocketConnection: don't close the socket if it's still reffed + 618866 g_ptr_array_remove_index_fast memory leak + 619878 keyfile backend calls keys_changed with invalid argument + 619879 keyfile backend doesn't make use of expected_type + 621092 Add with_closures() variants for bindings + 621172 Cross compiling fails + 621838 Actually add cwd to platform data + 621945 Filter outgoing messages in GDBusConnection + 621947 add g_value_take_variant + 622038 GSettings: "It is a programmer error" documentation is unclear + 622154 [patch] update documentation for g_application_new + 622281 binding: Add SYNC_CREATE to the flags + 622480 Improve documentation for g_strcmp0() + 622554 g_error called if schema not installed + 622601 Return interned strings from g_settings_list_keys + +* Translation updates: + - Galician + +Overview of Changes from GLib 2.25.8 to GLib 2.25.9 +=================================================== + ++----------------------------------------------------------------+ +| WARNING: There have been API changes in GDBus, GSettings and | +| GApplication. Users of these APIs will need to be adapted. In | +| particular, a new release of GTK+ is required to go along with | +| this one. | ++----------------------------------------------------------------+ + +* GDBus + - Use Gio's default async implementation + - Fix proxy construction for objects with no properties + - Fix error handling in synchronous initialization + - Do not dispatch calls to unregistered objects + - Add _with_closures alternative functions + - Allow constructing GDBusProxy with well-known names + - Remove GType parameters from GDBusProxy constructors + - Nuke g_bus_watch_proxy API + - Add --xml to gdbus-tool to print raw introspected XML + +* GSettings + - schema file format change: store (default, options) in gvdb + - Add g_settings_sync() + - Add support for enums and ranges + - 'context' support has been replaced by direct use of + GSettingsBackend + +* GApplication + - Switch to using variants for timestamps + - Use GInitable + +* GObject + - Introduce g_object_notify_by_pspec + - Add GBinding + - The GVariant gtype G_TYPE_VARIANT was changed from boxed + to fundamental. We believe there were no existing users + of the boxed type, so this should not cause any applications + to break. + +* Test framework + - Add package and version to the test report XML + - Use optparse to parse gtester-report commandline + - Add subunit support to gtester-report + - Prevent division by zero if no tests + +* Bugs fixed: + 621782 Crash using gbinding + 619945 GConverterOutputStream triggers assertion and corrupts data + 621319 more leaked GVariants in GSettings + 621168 GKeyFile memory leak on Windows platform + 621002 Switch to using variants for timestamps, split out signals + 620953 tiny docs addition + 618904 Lies in gunixmounts documentation + 621702 Correctly initialize GError + 611778 minor cleanup of gtester-report + 621213 GDBusProxy and well-known names + 621034 Rewrite apps test to ensure children are killed + 620954 gapplication gvariant simplifications + 611869 add subunit out feature to gtester-report + 621119 GDBusProxy and objects with no properties + 620990 Use Gio's default async implementation again + 620952 g_application_register_with_data is an ugly API + 621252 GSettings leaks context + 618715 fork() in GSettings test cases is problematic 618715 + 621905 Assume a ref when doing async work + 621266 GSettings "context" clarification + +* Translation updates: + Chinese + + +Overview of Changes from GLib 2.25.7 to GLib 2.25.8 +=================================================== + +* Initial support for dtrace and systemtap profiling: + - mainloop sources can be named + - probes for memory allocation with g_malloc and gslice + - gquark name tracking + - type creation + - object life-cyle (creation, finalization, ref, unref) + - signal creation and emission + +* GVariant + - has been fixed to work with the FreeBSD malloc + - added introspection annotations + - new function: g_variant_builder_add_parsed + +* GSettings: + - g_settings_set/get_strv functions have lost their length parameter + - g_settings_set_strv accepts NULL + - added introspection annotiations + +* GPermission: an abstract interface for representing permissions, + with a minimal implementation named GSimplePermission + +* GApplication: a basic application support class, with a D-Bus based + implementation + +* Bugs fixed: + 619585 glib-compile-schemas asserts on FreeBSD + 620384 Annotate GVariant and GSettings _strv() functions + 606044 Add support for dtrace/systemtap static markers + 620350 add g_variant_builder_add_parsed() API + 620349 utf8ify GVariant printer + 620767 Typo in GSettings documentation: "INTLTOOL_NOMERGE_RULE" + 620312 Fix g_settings_[gs]et_strv() API + 620519 GPermission + 620582 GPermission needs a simple implementation + 620496 GSettings schema compiler should reject invalid paths + 620173 missing single header inclusion guards + 620265 g_assertion_message_error should take const GError * + +* Translation updates: + Esperanto + Galician + Hebrew + Indonesian + Norwegian bokmål + Slovenian + Spanish + + +Overview of Changes from GLib 2.25.6 to GLib 2.25.7 +=================================================== + +* NOTE: API/ABI breaks since 2.25.6 release: + - g_dbus_connection_sync{,_sync} takes a new 'reply_type' argument + - GSettingsBackendClass 'list' virtual function changed + + GSettings backends and things using GDBus may need to be rebuilt. + +* GDBus: many build-related fixes + +* GDBus (service): return a DBus error when receiving a method call for + an unknown interface. + +* GSettings: fix 'make install' bug in gsettings.m4 for generated schema + files + +* GSettings: avoid non-portable use of LC_MESSAGES + +* better approach to handling man pages + + +* Bugs fixed: + 619527 please improve docs on g_file_make_symlink + 619391 send-with-reply should have expected result signature + 618616 Use stack-allocated GVariantBuilders + 617004 Build with "--disable-nls" fails under MinGW/Win32 + 619142 Build fixes (GDBus) + +* Updated translations: + Estonian + Galician + Norwegian bokmål + +Overview of Changes from GLib 2.25.5 to GLib 2.25.6 +=================================================== + +* GDBus: introspection improvements +* GDBus: build fixes + +* GSettings: GSettingsBackend ABI changed **** NOTE **** +* GSettings: --uninstall option for schema compiler +* GSettings: new m4 macro with more power +* GSettings: thread support + +* rework of file notification on Solaris +* fixes for gold linker + +* Bugs fixed: + 619038 increase gsettings.m4 power + 619031 method-calls-in-thread test failing + 618839 Typo at translation message + 616864 GSETTINGS_CHECK_RULE doesn't work with multiple files + 618730 gunixcredentialsmessage.c doesn't compile on GNU/kfreebsd + 616314 Make GSettings (partially) threadsafe + +* Updated Translations: + Indonesian + Galician + Spanish + +Overview of Changes from GLib 2.25.4 to GLib 2.25.5 +=================================================== + +* GDBus: Fix serialization of empty arrays + +* GDBus: Plug various memory leaks + +* GSettings: Fix problems with GSETTINGS_CHECK_RULE + +* Bugs fixed: + 616731 GSETTINGS_CHECK_RULE doesn't work in non-srcdir builds + 616864 GSETTINGS_CHECK_RULE doesn't work with multiple files + 618615 mem leaks in parse_value_from_blob + 618622 Plug some mem leaks in gdbus + 618650 Plug a mem leak in gdbusauth + 618663 Plug mem leaks in gdbus tests & examples + +* Updated translations: + Spanish + + +Overview of Changes from GLib 2.25.3 to GLib 2.25.4 +=================================================== + +* GDBus D-Bus support has been merged. This provides an API + to replace dbus-glib + +* GVariant no requires strings to be UTF-8. You can use byte + arrays for non-UTF-8 strings. + +* GSettings allows to bind string properties to byte arrays + +* The schema compiler supports range restrictions + +* Bugs fixed: + 618051 socket-server|client.c fail to compile under AIX... + 616102 GSettings ignores <choice> and <range> + 616720 Chunked quark allocation + 616877 Several issues with g_socket_receive_message + 616892 gio: Add a boxed type for GFileAttributeMatcher + 616967 Add g_regex_get_compile_flags() and g_regex_get_match_flags() + 617767 g_settings_[gs]et_strv() 'length' argument has missing docs... + 617914 gtester-report: cope with binaries with no test cases + 617937 output_stream_close vs output_stream_close_async semantics + 615494 Connction timeouts produce partially invalid error messages + 617823 glib-compile-schemas problems with an out of source build + 617947 glib-mkenums: add @valuenum@ support + +* Translation updates: + Galicaian + Norwegian bokmål + Shavian + Spanish + + +Overview of Changes from GLib 2.25.2 to GLib 2.25.3 +=================================================== + +* New macro: G_GNUC_DEPRECATED_FOR, a variant of G_GNUC_DEPRECATED + that lets you add replacement information (requires gcc 4.5) + +* Rename AM_GSETTINGS autoconf macro to GLIB_GSETTINGS + +* Rename gschema-compile utility to glib-compile-schemas + +* Add support for timeouts in GSocket + +* Bugs fixed: + 589989 Compilation error on Solaris 9 + 616648 Change AM_GSETTINGS macro to GLIB_GSETTINGS + 587898 I/O timeouts for GSocket + 614541 Add G_TYPE_ERROR boxed type for GError + + +Overview of Changes from GLib 2.25.0 to GLib 2.25.2 +=================================================== + +* Include a 'gsettings' utility, for commandline access to GSettings + +* Install a AM_GSETTINGS autoconf macro similar to AM_GCONF + +* GSettings can bind the writability of a key explicitly + +* There is now a predefined boxed type for GError + +* Bugs fixed: + 615379 g_new macros crash if sizeof(struct_type) == 0 + 616312 Add m4 rule equivalent to GCONF_SCHEMAS_INSTALL + 616295 mapping bug for uint64 + 616216 glib compile from remote directory fails + 615960 Fix size passed to connect() for abstract sockets + 616432 Crash in gschema-compile + 616331 gsettings-schema-convert uses imaginary types + 616309 gsettings-schema-convert should output gettext-domain + 616384 Add mention of GConfBridge in conversion docs + 616311 gschema-compile outputs in current directory + 616276 simplify gschema-compile test setup + 616156 keys with unnecessary empty options arrays + 616405 gsettings missing g_return_if_fail's + 616245 Use G_DEFINE_INTERFACE macro + 614541 Add G_TYPE_ERROR boxed type for GError + +* Updated translations: + Catalan (Valencian) + Galician + Kannada + Spanish + + +Overview of Changes from GLib 2.24.0 to GLib 2.25.0 +=================================================== + +* The GSettings framework has been merged. This provides the API to + replace GConf. DConf will provide a backend implementation for it. + GConf will also provide a backend implementation to ease the + transition. We provide utilities to assist with schema conversion + and data migration, as well as a porting guide. + +* Translation updates: + Bengali + Catalan + Danish + Gujarati + Marathi + Thai + Traditional Chinese + + +Overview of Changes from GLib 2.23.6 to GLib 2.24.0 +=================================================== + +* Bug fixes: + 613601 buglet in dup_close_on_exec_fd + 584284 g_data_input_stream_read_until_async behaves confusingly + 613748 Write errors in middle of copy cause hang + 613923 splice_stream_with_progress: wrong error handling + 613667 Typo in GObject documentation + 613618 gvariant format string docs unclear + +* Translation updates: + Basque + Ukrainian + Vietnamese + + +Overview of Changes from GLib 2.23.5 to GLib 2.23.6 +=================================================== + +* Class private data: + - support for private data associated with a GTypeClass + +* GVariant merge is now complete: + - loading functions and parser merged + +* Windows improvements: + - socket fixes + - various build improvements + - removal of GCC/C99isms in favour of portable code + - drop unmaintained Visual Studio 8 support + +* Minor API addition: + - g_desktop_app_info_get_filename() + +* Bugs fixed: + 521707 Class private data + 612502 build fails on glib/tests/gvariant.c + 612832 [GDesktopAppInfo] New function g_desktop_app_info_get_filename + 612702 [PATCH] Fix GSocket-related crash on Windows + 612736 Improve the documentation about single include + 610858 gvariant test fails sometimes + 612327 uninitialized variable + +* New translations: + Afrikaans + LowGerman + +* Updated translations: + Czech + Finnish + Galician + Greek + Punjabi + Romanian + Serbian + + +Overview of Changes from GLib 2.23.4 to GLib 2.23.5 +=================================================== + +* New API addition: g_malloc_n() and friends used to implement an + overflow-safe family of g_new() macros. + +* GVariant: + - GVariantBuilder and GVariantIter are now merged. + - The variable arguments API is now merged. + - The parser will be in a future release. + +* GIO: + - Remove GUtf8InputStream (which never appeared in a stable release) + for now since it doesn't satisfy the needs of its main intended use + case. We hope to reimplement this feature in a better form in a + future release. + +* Bugs fixed: + 609531 missing licence headers + 612107 Missing G_FILE_ATTRIBUTE_TRASH_ORIG_PATH + 611897 g_io_modules_scan_all_in_directory leaks + 608196 Overflow-safe g_new family + 611696 gio uses GetAddrInfo which requires special handing on windows 2k + 605667 Don't use G_PARAM_SPEC_VALUE_TYPE when we know the pspec is valid + 610860 test_g_file_open_readwrite fails if $HOME is unwritable + 552912 glib-2.18 /live-g-file/test_copy_move failed when run as root + 609813 Renaming a file discards file notes + +* Updated translations: + Basque + Brazilian Portuguese + British English + Bulgarian + Catalan + Danish + Estonian + French + German + Hungarian + Italian + Lithuanian + Norwegian bokmål + Portuguese + Russian + Slovenian + Spanish + Swedish + Traditional Chinese + + +Overview of Changes from GLib 2.23.3 to GLib 2.23.4 +=================================================== + +* GVariant: The core of GVariant has been merged now, with some + API still to follow. + +* GIO: + - There is a new interface GFileDescriptorBased for file descriptor + based IO. GLocalFile{Input,Output}Stream implement it + - Use splice(2) to transfer data between file descriptors without + extraneous copies + - Add a way to request move events from file monitors + +* Bugs fixed: + 609143 *result_uncertain is never assigned in g_content_type_guess + 604086 Use splice(2) when doing local file copies + 547890 No move events for GFileMonitorEvent? + 568760 nautilus freezes due to a bug in garray.c:322 + 609962 Add info about the use of G_DEFINE_INTERFACE + 609564 g_base64_encode_close docs should mention outbuf size... + 610484 g_variant_equal bug + 610131 libasyncns does not compile on Solaris 8 + 609530 missing single header include guards + +* Updated translations: + Czech + Estonian + Galician + German + Korean + Polish + Slovenian + Spanish + Traditional Chinese + + +Overview of Changes from GLib 2.23.2 to GLib 2.23.3 +=================================================== + +* GLib now has a facility for locks that consume only one bit of + storage inside an integer: g_bit_lock() + +* GVariant: The serializer has been merged, with more API to follow + +* Bugs fixed + 548967 1 bit mutex lock + 604967 2.22.3 libasyncns build fails on HP-UX 11.11 + 608602 G_VALUE_COLLECT_INIT variables shadow those in G_VALUE_COLLECT + 608743 Crash in g_hostname_to_ascii visiting certain website in epiphany + 599197 array ref and unref functions crash on NULL array. + 608159 mem leak in g_io_modules_scan_all_in_directory + +* Translation updates + Brazilian Portuguese + Czech + French + Norwegian bokmål + Slovenian + Spanish + Thai + + +Overview of Changes from GLib 2.23.1 to GLib 2.23.2 +=================================================== + +* We are now using gcc builtins for atomic operations when available + +* g_assert() grew the ability to store assertions in core dumps + +* GIO supports lazy loading of GIO modules, and there is a new + gio-querymodule utility that goes along with this. + Packagers will need to adapt to this. + +* Threading changes: + - The requirements for g_thread_init() have been relaxed slightly, + it can be called multiple times, and does not have to be the first + call. + - GObject now links to GThread and threads are enabled automatically + when g_type_init() is called. + - Thread-safety issues with boxed types in GObject have been fixed. + +* GObject: + - Another bunch of performance work has landed + +* GVariant: + - GVariantType has been merged, with the rest of the GVariant + API to follow. + +* Bugs fixed: + 568760 nautilus freezes due to a bug in garray.c:322 + 602417 Document lifecycles of GSimpleAsyncResult and friends + 604824 crash in Epiphany: Selecting my Slashdot bo... + 448888 don't init g_slice for always-malloc + 531902 Use GCC atomic buildins for g_atomic* + 554887 boxed type registration is not thread safe + 586150 unresolved symbols when building glib 2.21.2 on OS X Tiger + 589176 row gvalue transform array exponentially + 594872 Support storing assertion messages into core dump + 602240 Upgrade libasyncns to 0.8 + 603590 Speed up G_VALUE_COLLECT + 604457 gutf8inputstream.c: increasing unknown size pointer + 605686 GCharsetConverter doesn't flush + 605733 g_memory_output_stream_new violates GObject standards + 605883 g_object_new() processes varargs even when there are none + 605977 invalid utf-8 conversion in g_local_file_get_parse_name(... + 606775 Enable threads by default in gobject + +* Translation updates: + Asturian + Basque + Bengali + Bulgarian + Estonian + Norwegian bokmål + Spanish + Thai + Ukrainian + + +Overview of Changes from GLib 2.23.0 to GLib 2.23.1 +=================================================== + +* GObject performance work has landed: + - Construction of simple objects is much faster + - Interface lookup is lock-free and constant-time now + - Reduced locking overhead when dealing with types + +* GType now has a G_DEFINE_INTERFACE convenience macro + +* GIO gained GUtf8InputStream, an input stream that + performs utf-8 validation + +* GLib now has byte-swap macros for gsize and gssize + +* Bugs fixed: +557151 Determining the newly_constructed boolean in gobject.c... +557100 Performance improvements for GObjectClasses that don't... +501166 Warning message says IA__g_type_init instead of g_type_init +585375 Performance and Contention problems with g_type_class_ref... +587892 Race in GType when instantiating the same class for the... +603270 Input Stream validating utf8 +603476 gioenums.h:62: error: comma at end of enumerator list +603540 g_time_val_from_iso8601 uses uninitialised variable +603982 Stack overflow when reading file async with filter +604645 G_DEFINE_INTERFACE_* documentation is not generated +604875 Use of sa_len conflicts with system header +320482 provide G_DEFINE_TYPE like macros for interfaces + +* Updated translations: + Estonian + Hebrew + Norwegian bokmål + Vietnamese + Welsh + + +Overview of Changes from GLib 2.22.x to GLib 2.23.0 +=================================================== + +* GIO: + - GConverter: a generic interface for stateful conversions of data, + suitable for charset conversion, compression, decompression, regexp + replacement. Concrete implementations are GCharsetConverter, + GZlibCompressor and GZlibDecompressor. GConverterInputStream, + GConverterOutputStream are stream implementations that convert data + while loading or saving it. + - GMounts can now have a 'default location': a path that reflects + the main entry point for the user (e.g. the home directory). + - As a consequence of the compression support, GIO depends on zlib now. + +* GObject: + - G_IMPLEMENT_INTERFACE_DYNAMIC: a convenience macro for adding + interfaces to dynamic types. + +* GModule: + - The -pthread flag has been added to all gmodule .pc files, because + it is not generally permissible to load modules that are linked + against libpthread if the program has not been compiled with threading + support. + +* Bugs fixed: + 601637 GUnixFDMessage should contain a GUnixFDList + 585566 GSocketListener API issues + 572252 Bug in g_file_test() function. + 600550 g_app_info_create_from_commandline doesn't treat arguments properly + 541236 not detecting exact content type + 350200 [PATCH] GTypeModule derived class unref does not unload plugin + 589631 Please enclose literal values with double quotes + 577711 cross compile check for g++ broken + 600620 Support X-GNOME-FullName in GAppInfo + 598899 GWin32DirectoryMonitor is broken + 593809 Nautilus does not restore the position of the icons on the desktop... + 563627 g_get_prgname() threadsafety + 600141 Add -pthread to gmodule pkg-config + 593856 file and directory monitors don't work when glib is compiled... + 324930 Nautilus should disallow copying of symlink to FAT drive early + 587300 Deadlock when calling g_cancellable_disconnect in a... + 595138 GFile not robust with invalid input + 591216 Warning building resolver.o + 590016 Does not compile under MinGW32 + Wine + 591214 Warnings building gcancellable.o + 561998 Have specific entry points (paths) for mounts... + 508157 Add G_IMPLEMENT_INTERFACE_DYNAMIC + 535159 g_file_has_parent + +* Updated translations: + Brazilian Portuguese + Catalan + Estonian + Galician + Norwegian bokmål + Shavian + Slovenian + Spanish + Swedish + + +Overview of Changes from GLib 2.22.1 to GLib 2.22.2 +=================================================== + +* GIO: + - Support case-sensitive globs in the shared mime database, + including support for the newer cache format that allows these. + Case-sensitive globs have been introduced in shared-mime-info + version 0.70 + +* GObject: + - Speed up creation of simple objects + +* Bugs fixed: + 597194 Typo in _G_TYPE_CVH macro + +* Updated translations: + Russian + + +Overview of Changes from GLib 2.22.0 to GLib 2.22.1 +=================================================== + +* Bugs fixed: + 596064 Test file marked for translation + 595972 possibly invalid search in mime_info_cache_dir_add_... + 596561 C99 style of declaration of variable in gmessages.c + 596314 g_utf16_to_utf8 returns an invalid UTF8 string + 596748 g_async_result_get_source_object returns a new ref + 593809 Nautilus does not restore the position of the icons... + 593775 uses inotify_init1 unconditionally + +* Updated translations: + Bengali + Hebrew + + +Overview of Changes from GLib 2.21.6 to GLib 2.22.0 +=================================================== + +* Add gdb python macros to make gobject debugging more pleasant + +* Bugs fixed: + 579050 Allow making selected critical and warning messages non-fatal + 594759 g_socket_send_message fails due to invalid sendmsg params + 593941 GNetworkAddress skipping addresses when enumerating + 594597 Fix build with srcdir != builddir + 595619 Include gdb pretty printers + +* Changes that might affect bindings: + - The error parameter of g_simple_async_result_set_from_error has been + made const. + +* Updated translations: + Assamese + Bengali India + British English + Bulgarian + Catalan + Czech + Danish + Finnish + Galician + Greek + Gujarati + Hindi + Japanese + Kannada + Malayalam + Marathi + Norwegian bokmål + Oriya + Polish + Punjabi + Romanian + Serbian + Simplified Chinese + Slovenian + Spanish + Tamil + Telugu + Thai + Traditional Chinese + Ukrainian + Vietnamese + + +Overview of Changes from GLib 2.21.5 to GLib 2.21.6 +=================================================== + +* Minor API additions: + g_mkstemp_full is a variant of g_mkstemp that allows to specify flags + and permissions + +* Bugs fixed: + 593232 g_rand_new: read no more than requested from /dev/urandom + 591995 use saved errno + 589491 g_time_val_from_iso8601 doesn't handle some cases + 593406 Permissions set to 777 after copying via Nautilus + 594034 Add g_mkstemp_full() + +* Updated translations: + Assamese + Basque + Brazilian Portuguese + Czech + Estonian + French + German + Hungarian + Italian + Kannada + Malayalam + Marathi + Norwegian bokmål + Oriya + Portuguese + Swedish + Tamil + Turkish + + +Overview of Changes from GLib 2.21.4 to GLib 2.21.5 +=================================================== + +* A performance problem with trashing of many files has been fixed + +* GResolver now invalidates the libc resolv.conf cache as needed + +* Minor api additions: + - g_cancellable_make_pollfd returns a boolean now. And there is a + new function g_cancellable_release_fd that can be used to released + the resources used by a GCancellable. + +* Bugs fixed: + 589988 Compilation error on Solaris 9 (missing stdint.h) + 588901 gtcpconnection.c won't compile + 584246 GResolver needs to call res_init() when network state changes + 591714 Figure out failure handling for g_cancellable_make_pollfd() + 591532 redundent '/' returned from g_file_resolve_relative_path + 591378 Use MSG_NOSIGNAL in GSocket if it's available + 589649 API documentation migration for Base64 Encoding + 591840 configure fails with autoconf 2.64 + +* Updated translations: + Basque + Brazilian Portuguese + Bulgarian + Danish + Estonian + Finnish + Galician + Gujarati + Hndi + Irish + Japanese + Korean + Norwegian bokmål + Polish + Portuguese + Punjabi + Spanish + Swedish + Telugu + Traditional Chinese + Thai + + +Overview of Changes from GLib 2.21.3 to GLib 2.21.4 +=================================================== + +* GTree is now refcounted + +* Bugs fixed: + 587938 Undocumented limitation for g_str_equal + 587773 refcounts for GTree + +* Updated translations: + French + Hebrew + Norwegian bokmål + Spanish + Swedish + Traditional Chinese + Ukrainian + + +Overview of Changes from GLib 2.21.2 to GLib 2.21.3 +=================================================== + +* GMappedFile is refcounted now + +* Mainloop: It is now possible to set per-thread default contexts, + with g_main_context_push_thread_default. + +* glib-mkenums supports a @basename@ substitution, in addition + to @filename@. + +* GIO: + - Vfs implementations can support storing of per-file metadata. + - GCancellable can now be subclassed. + - Unmount and eject methods now optionally allow interaction, via + variants that take a GMountOperation object. + +* Bugs fixed: + 556706 Inconsistent help arguments -h, -? + 579449 FileChoosers no longer work if an idle handler is active + 579933 mainloop FD_CLOEXEC has a race condition + 579984 alternate GMainContext support + 585937 gio/gsocket.c (glib 2.21.2) does not compile (Windows/mingw) + 586675 Runtime library location + 586797 Add GCancellables to GSocket ops + 586868 g_filename_complete_get_completions doesn't always return... + 587415 g_resolver_lookup_by_name_finish returns a freed list + 587434 regression tests fail, at least on x86_64 + 586928 Avoid g++ warning in g_error() + +* Updated translations: + Estonian + Hebrew + + +Overview of Changes from GLib 2.21.1 to GLib 2.21.2 +=================================================== + +* GIO: + - g_socket_speaks_ipv4 is a new function to check if a socket can + speak IPv4. + - g_socket_listener_add_address gained a new effective_address out + parameter. + - GIO now returns special icons for XDG user directories, by the + name folder-music, folder-documents, etc. + - GIO gained support for starting/stopping of drives, which can be used + in connection with external hard disk enclosures, disk arrays, iSCSI + devices, etc. See g_file_start/stop_mountable. + +* GLib: + - g_reload_user_special_dirs_cache is a new function to force GLib to + reload the XDG user directory mapping from disk. + +* Bug fixes: + 584574 glib compile failure on Mac OS X with gunixresolver.c and... + 585566 GSocketListener API issues + 584255 Incorrect freeing of thread pool in GThreadedSocketService + 585088 g_string_chunk_insert_len stops at nul bytes + 585360 Monitor fontconfig configuration files using gio causes m... + 580103 Terminal starts on Display :0.0 when started on :0.1 in D... + 580301 network: a few issues on old darwin + 583398 SRV weight sorting is incorrect + 584176 build fixes on FreeBSD + 585189 g_cancellable_reset() must be called in same thread as g_... + 585280 compilation dies on gio/gsocket.c, needs sys/uio.h to con... + 585281 gio/gunixfdmessage.c needs sys/types.h for platforms that... + 585478 don't leak the inotify fd + 585575 g_socket_listener_add_inet_port() doesn't do the right thing + 585599 g_socket_listener_add_socket() consumes the socket + 585676 GEmblem doesn't reference its 'icon' if that is set as a ... + 585717 "bytes" nautilus translation to french is not shown in th... + 541276 XDG directories should have their own icons + 585726 Grammatical error in GList documentation + 585520 Wrong warning option in documentation + 585673 GNOME Goal: Remove deprecated glib symbols + 585591 Starting/stopping drives + +* Updated translations: + Bengali India + Norwegian bokmål + + +Overview of Changes from GLib 2.21.0 to GLib 2.21.1 +=================================================== + +* GIO: + - Support for network IO has been added, including a low-level + socket API and a high-level API for network connections and + services. + - Support for read-write access with GIOStream and its subclasses. + - GMount gained a pre-unmount signal. + +* Bug fixes: + 576104Implement GMount::pre-unmount + 578769 implement GWinHttpFileInputStream::close_fn + 582856 gsocket.c doesn't compile on Solaris + 569375 g[u]intptr undocumented + 573246 [FIX] g_desktop_app_info_dup() can access NULL pointer + 575013 g_cancellable_push_current() does not allow NULL + 577884 live-g-file.c:461: error: format ‘%d’ expects type ... + 578499 g_output_stream_splice and stream closing with gnio strea... + 579558 Application employing gvfs crashes with only libgvfscommo... + 583001 SIGPIPE (grr!) + 583061 Please add convenience function to connect to machines by... + 583198 typo in error message + 583206 use g_set_error_literal where appropriate + 583229 void function g_async_initable_init_async returns value + 583324 locking problem in g_main_context_iterate() + 583408 void function g_socket_control_message_serialize returns ... + 578786 wrong and confusing error message + 583205 g_inet_address_to_bytes has no length outparam + 583196 mem leak in keyfile test + 583663 GSocketType enum ends with a comma + 569024 Make g_error_new_valist public + 569376 missing G_G[U]INTPTR_FORMAT + 580347 off-by-1 bug in GWinHttpFile + +* Updated translations: + Oriya + Spanish + Valencian-Catalan + + +Overview of Changes from GLib 2.20.x to GLib 2.21.0 +=================================================== + +* GIO: + - New helper functions g_cancellable_connect/disconnect to avoid + race conditions when connecting to the "cancelled" signal on + GCancellable. + - New types and methods for dealing with IPv4 and IPv6 addresses (and + UNIX domain socket addresses under UNIX). This does not include code + for actual socket I/O. + - GResolver provides asynchronous and cancellable APIs for resolving + hostnames, reverse lookup of IP addresses and resolving SRV records. + +* Glib now provides hash and comparison functions for int64 and double + types, suitable for use with GHashTable. + +* GArray, GPtrArray and GByteArray can be ref counted now, and have + boxed types. + +* Bugs fixed: + 572844 Helper for GCancellable::cancelled connect/disconnect + 578363 goption docs should be improved + 548466 async/cancellable DNS resolver + 579830 param spec strings should use P_() + 579862 requesting xattr::foo ends up calling getxattr(..., user... + 580453 Hash and equal functions for gint64 and gdouble + 580450 Reference counting and boxed types for arrays + 580194 gresolver doesn't build on Solaris + 580301 network: a few issues on old darwin + 580299 network: include sys/types.h before sys/socket.h to insur... + 572508 gmarkup speedup + 580546 g_strtoull() referenced in documentation... + 580656 g_key_file_set_string_list erroneously asserts list != NULL + 579272 leaks in g_simple_async_result_set_op_res_gpointer + + +* Updated translations: + Catalan (ca) + Pashto (ps) + Spanish (es) + + +Overview of Changes from GLib 2.20.0 to GLib 2.20.1 +=================================================== + +* Bug fixes: + 575555 Use fsync() when replacing files to avoid data loss on + 575708 runaway inotify madness + 575270 GVolumeMonitor::mount-pre-unmount not being emitted + 577128 glib make check Failed to execute child process... + 573673 Always show "backup" directories + 578369 g_time_val_from_iso8601() parses timezones incorrectly + 578002 Fix a small typo in GFile docs + 578017 G_DEFINE_TYPE_EXTENDED docs + +* Updated translations: + Arabic + Assamese + Basque + Bularian + Brazilian Portuguese + British English + Catalan + Danish + French + Galician + German + Greek + Hungarian + Italian + Japanese + Kannada + Lithuanian + Malayalam + Norwegian bokmål + Oriya + Polish + Punjabi + Russian + Simplified Chinese + Slovenian + Spanish + Swedish + Tamil + + +Overview of Changes from GLib 2.19.9 to GLib 2.20.0 +=================================================== + +* Base64 support: Avoid integer overflows. CVE-2008-4316 + +* Bugs fixed: + 574019 GChecksum: document and guarantee hex characters in lower case + 573454 Unable copy/move files to directories symlinked to gvfs share + 561172 gnome-open fails on local URIs with anchors + 573970 crash in gunixvolumemonitor:update_mounts when unmounting + 573843 g_get_current_dir returns non-absolute path + +* Updated translations: + Assamese (as) + Bengali (bn_IN) + Czech (cs) + Hindi (hi) + Italian (it) + Japanese (ja) + Lithuanian (lt) + Malayalam (ml) + Marathi (mr) + Oriya (or) + Polish (pl) + Romanian (ro) + Telugu (te) + + +Overview of Changes from GLib 2.19.8 to GLib 2.19.9 +=================================================== + +* GMarkup: + - Considerable speedup + +* GIO + - Add G_FILE_CREATE_REPLACE_DESTINATION flag to allow replacing + the destination of a copying operation as if it did not exit before. + - Be more careful when classifying files as desktop files + - Support desktop file key X-GIO-NoFuse which disables the use + of fuse pathnames for %u and %U arguments + +* Bugs fixed: + 572672 glib/gthread.c: argument is different type + 572464 Doc for g_file_get_contents + 572151 “it's” and “its” confused in docs and comments + 570501 g_win32_get_system_data_dirs uses invalid conversion... + 167569 g_string_append_printf crashes on win32 when used... + 572508 gmarkup speedup + 560564 Replacing a symlink with its linked file truncates... + 549298 impossible to copy files with p (pipe) flag + 543183 Clarify docs for g_file_has_prefix + 540461 g_memory_output_stream_get_data_size() doesn't behave... + 573462 GEmblemedIcon leak + 573421 Clarify message format in GMountOperation + 573658 Deadlock in giomodule.c + 556706 Inconsistent help arguments -h, -? + 573527 Wrong shell to run config.status in Makefile.in.in + 573128 A couple of typos in GObject documentation + +* Updated translations: + Catalan (ca) + British English (en_GB) + Spanish (es) + Basque (eu) + Finnish (fi) + French (fr) + Gujarati (gu) + Hebrew (he) + Hungarian (hu) + Korean (ko) + Maithili (mai) + Norwegian bokmål (nb) + Dutch (nl) + Portugese (pt) + Swedish (sv) + Thai (th) + Traditional Chinese (zh_HK) + Traditional Chinese (zh_TW) + + +Overview of Changes from GLib 2.19.7 to GLib 2.19.8 +=================================================== + +* GIO: Fix missing exports of new API + +* Fix strict aliasing warnings and violations to make Glib work + with gcc 4.4 + + +Overview of Changes from GLib 2.19.6 to GLib 2.19.7 +=================================================== + +* GIO + - GFile gained an attribute for the actual file size in bytes + - GMountOperation gained an "aborted' signal that allows to abort + a mount operation from the backend side + +* Bugs fixed: + 523742 Use noinst for non-installable libraries + 566747 URIs opened with firefox %u load as local files + 541225 Can't compile gio on AIX duplicate case value in gioerror.c + 571598 GAsyncResult with NULL gobject + 505042 add file attribute for actually used file size in bytes + +* Updates translations: + Basque (eu) + Gujarati (gu) + Italian (it) + Japanese (ja) + Norwegian bokmål (nb) + Dutch (nl) + Portugese (pt) + Thai (th) + Vietnamese (vi) + + +Overview of Changes from GLib 2.19.5 to GLib 2.19.6 +=================================================== + +* New format macro to print goffset data: G_OFFSET_FORMAT + +* GIO: + - Add a GFilter{Input,Output}Stream::close-base-stream properties which + determine whether the base stream will be closed when the filter stream + is finalized. + - g_data_input_stream_read_line and ..._read_until have asynchronous + variants now. + +* Bugs fixed: + 568294 A wrong reference in the description of g_bookmark_file_... + 563141 RFE: define G_OFFSET_FORMAT + 569105 g_time_val_to_iso8601() assumes time_t==long + 568394 dropping the last reference to a stream filter closes... + 568741 g_buffered_input_stream_fill_async doesn't work + 568723 g_buffered_input_stream_fill_async doesn't take count == -1 + 568575 _async functions for GDataInputStream + +* Updated translations: + Bulgarian (bg) + Finnish (fi) + Hungarian (hu) + Oriya (or) + Swedish (sv) + Traditional Chinese (zh_HK) + Traditional Chinese (zy_TW) + + +Overview of Changes from GLib 2.19.4 to GLib 2.19.5 +=================================================== + +* Update included PCRE to 7.8 + +* g_base64_decode_inplace: New function to do base64 decoding in place + +* Bugs fixed: + 567138 get_package_directory_from_module() does not free ... + 566569 gregex docs clarification + 566573 g_match_info_fetch_pos docs + 564728 Add function to decode base64 encoded data in place + 567838 G_STRUCT_OFFSETOF fails to compile under icc 9.1 + 567977 textdomain() macro should not return NULL ... + 512779 --disable-regex breaks compilation + 566770 error code 0 for Too many open files is useless + 565484 g_content_type_guess passes non-UTF8 text to XDG ... + +* Updated translations: + Catalan (ca) + Spanish (es) + Italian (it) + Swedish (sv) + + +Overview of Changes from GLib 2.19.3 to GLib 2.19.4 +=================================================== + +* GIO: + - Use O_NOATIME when sniffing mimetypes + - Add a convenience method to check if a GSimpleAsyncResult + is valid + +* Bugs fixed: + 560676 function access for g_threads_supported + 565905 There is no g_context_group_set_translation_domain + 564210 SUN Studio 12 has supported visibility attribute + 565136 GObject's "notify" signal parameters are wrong in gtk-doc + 565831 error in interface creation sample + 566348 g_file_open_tmp uses the wrong g_mkstemp on win32 + 566064 Add NOATIME flag to query_info_flags + 566170 g_async_result_verify_source_object + +* Updated translations: + Spanish (es) + Norwegian bokmål (nb) + Brazilian Portugese (pt_BR) + Simplified Chinese (zh_CN) + + +Overview of Changes from GLib 2.19.1 to GLib 2.19.3 +=================================================== + +* Bugs fixed: + 508021 Add support for the CRIS and CRISv32 architectures + 526320 should not list mounts that the user doesn't have permission to use + 558458 Cannot build gio tests on Solaris using SUN cc + 555465 GUnix{Input,Output}Stream lacks fd/close_fd_at_close property + 558298 Hide ecryptfs mounts + 515777 incorrect date&time on copy + 562452 Ensure we return G_IO_ERROR_CANCELLED if cancelling + g_simple_async_result_run_in_thread + 473150 g_type_module_use inconsistently increases the use + counter in case of error + 563150 G_GU?INT*_MODIFIER/FORMAT docs + 563156 Document printing and scanning gunichar values + +* Updated translations: + Hebrew (he) + Italian (it) + + +Overview of Changes from GLib 2.19.0 to GLib 2.19.1 +=================================================== + +* GIO: + - g_icon_to_string, g_icon_new_for_string: GIcon serialization support + - G_FILE_ATTRIBUTE_PREVIEW_ICON: new file attribute for preview images + - g_app_info_get_commandline: new function to get the full commandline + - g_mount_shadow, g_mount_unshadow, g_mount_is_shadowed: New functions + to 'shadow' mounts (i.e. hide them from the UI when they already + have a different representation, like a bookmark) + +* Bugs fixed: + 556186 gpoll.h breaks gmain.h inclusion + 557087 mem leak in g_content_types_get_registered + 556921 gpoll.h breaks hal compilation + 557210 g_compute_checksum_for_* asserts with less than 2 bytes + 558381 Add support for compile time assertions + 558185 'parent' variable in g_local_file_get_child_for_display_name() + hits g_object_unref(NULL) assertion + 558513 g_warn_if_fail FIXME in gtestutils + 558672 NULL key lookup using g_hash_table_lookup_extended() + 555740 gicon serialization + 557182 preview functionality + 528320 Incorrect icons displayed for files with custom mimetype icons + 556910 Memory leak: sub + 557592 Missing include in gwinhttpfile.c + 556415 Crash on Windows 2000 in g_winhttp_vfs_init() + 555935 Clarify the mechanism of overwriting properties + 552776 ac_cv_func_posix_getgrgid_r not mentioned + 559448 GObject Reference Manual (typo) + 561212 GFileReadMoreCallback API doc refers to non-existant function + 560569 gkeyfile doesn't use the set list_separator in some cases + 560568 gkeyfile docs buglet + 559413 g_option_group_set_error_hook docs buglet + 562378 callback return value not respected for callback option + with no arg + 559110 Do not include libintl.h after glibintl.h + 557603 carbon check output misplaced + 562544 g_key_file_get_string and g_key_file_get_value + documentation does not explain the difference + 547264 Missing "no flags" flag + 562638 GDebugKey key member should be const + 562639 g_parse_debug_flags() parsing "help" + 562549 g_byte_array_free should tell how free data + 559452 GObject Reference Manual (typo) + 559462 GObject Reference Manual (typo) + 559517 GObject Reference Manual (typo) + 562538 GObject interface tutorial shouldn't finalise with + "Please forget everything" + 561352 Leak of icon description + 561375 Leaks mountpoint description + 561807 inotify_sub.c: dup_dirname() fails to remove trailing '/' + 562393 g_buffered_input_stream_read_byte broken if data available + 541715 win32 : patch for warnings and signature problems in recent code + 547481 g_data_input_stream_read_line behaves not as stated in the docs + 548163 Nautilus displays wrong error message for too long file names + 559633 gtk_image_new_from_gicon does not always work for .desktop files + 555486 – No way to recover command line from GAppInfo + +* Translation updates: + Spanish (es) + Ukrainian (uk) + + +Overview of Changes from GLib 2.18.1 to GLib 2.19.0 +=================================================== + +* Rewrite GHashTable to use open addressing with quadratic probing instead + of chaining. This has the potential to reduce memory fragmentation + significantly, while being slightly faster due to better locality and + no need to call alloc/free functions for nodes. Benchmarks suggest it + also uses less memory overall. + +* Make g_poll available as public api + +* New macros g_assert_error and g_assert_no_error to assert + that a GError is set or unset + +* g_cancellable_make_pollfd: New method to make a GPollFD for a cancellable + +* g_app_info_can_delete, g_app_info_delete, g_app_info_reset_type_associations: + New functions to clean up app infos and content types + +* When launching applications, always pass fuse file:// uris when possible, + and let gio convert such uris back to gio uris. + +* Bugs fixed: + 505361 gunixinputstream.c assumes poll() available + 509446 portable blocking gio cancellation + 553820 gpoll.c: undeclared identifier + 553724 python interpretter path not patched in correctly + 553857 gbacktrace.h requires signal.h + 553447 g_assert_no_error() + 554092 glib doesn't return G_FILE_ERROR_NOENT et al on OS X + 528670 Always pass file:/// uri's in GAppLaunchContext + 555224 Improve g_format_size_for_display doc + 555309 giochannel breaks on error + 554790 g_convert() misbehaves with winiconv versions + 555314 mem leak in gmarkup + 555313 GFileAttribute boxed type get_type function should... + 552861 glib-2.0.m4 calls system(3) without storing its result + 554557 Patch to fix gcc warnings about missing format specifiers + 552107 Small libtool fixes + 551355 Make glib build with libtool 2.2 + 555311 format not a string literal and no format arguments + 556101 static mutex yields warnings with g++ + 556186 gpoll.h breaks gmain.h inclusion + 526456 Open addressing in GHashTable + 553426 cancellable clarifications + 545350 GAppInfo deletion + 545351 Reset associations for content type + 552168 volume's mount not mounted after g_volume_mount_finish + 554970 segfault when update-desktop-database is not available... + 554745 GFileAttributeInfoList should be boxed + 555121 Improved build-time handling of gio module-dir + 555711 Wrong fallback order of mimetype icons + 555331 Deprecate adoption of mounts + 556335 make check fails in abicheck.sh + 556334 Warning when building without selinux support + 556422 g_file_enumerator_next_file: unclear... + +* Updated translations: + Arabic (ar) + Danish (da) + Polish (pl) + Brazilian Portugese (pt_BR) + Romanian (ro) + Russian (ru) + + +Overview of Changes from GLib 2.18.0 to GLib 2.18.1 +=================================================== + +* Bugs fixed: + 550433 g_test_init doesn't recognize --help + 523463 Core dump in gmain.c:2482:IA__g_main_context_check + 551228 G_STRFUNC on recent Sun compiler should be expanded... + 551410 gtestutils.c: using printf without prototype + 551731 g_date_set_time[_t] docs should mention what timezone + 548321 <string.h> is not included in gi18n-lib.h + 551149 xdgmime mem leak + 550647 synchronous pipe I/O when reading mount reply + 551887 Docs for g_desktop_app_info_new_from_filename aren't... + 551681 g_content_type_guess() too naive with filenames + 552352 g_app_info_launch doesn't work if "Path" key... + 551408 gmodule.def generated to builddir... + 552359 g_file_info_get_icon should return GThemedIcon, and... + +* Updated translations: + Arabic (ar) + Bengali India (bn_IN) + British English (en_GB) + Hindi (hi) + Croatian (hr) + Korean (ko) + Oriya (or) + Turkish (tr) + Telugu (te) + + +Overview of Changes from GLib 2.17.7 to GLib 2.18.0 +=================================================== + +* Win32: + - rework the g_poll() implementation to match poll() semantics more closely + +* Bugs fixed: + 324234 Using g_io_add_watch_full() to wait for connect() to return... + 548278 Async GETs connections are always terminated unexpectedly... + 500246 Bug fixes for giowin32 + 523939 Example program for GValue + 550096 GBookmarkFile parser is not forward compatible + 550040 Move GString, rand and printf tests to the unit test framework + 550104 trivial documentation fix for g_get_home_dir + 548988 g_file_replace fails on Windows when the target file exists + 550059 Wrong docs for g_emblemed_icon_add_emblem + 548800 Missing a g_object_get_type function + 550056 Missing documentation for g_emblemed_icon_get_emblems + +* Updated translations: + Bulgarian (bg) + Czech (cs) + German (de) + Estonian (et) + Basque (eu) + French (fr) + Hebrew (he) + Hungarian (hu) + Italian (it) + Japanese (ja) + Lithuanian (lt) + Maithili (mai) + Dutch (nl) + Swedish (sv) + Thai (th) + Ukrainian (uk) + Vietnamese (vi) + + +Overview of Changes from GLib 2.17.6 to GLib 2.17.7 +=================================================== + +* More fixes for 64-bit Windows + +* GIO + - Add a vfs implementation for HTTP and HTTPS URIs on Windows + +* Bugs fixed: + 546329 API docs for g_utf8_normalize() are incorrect + 546876 Modify GMarkup parser to accept  ..  + 547200 g_utf8_find_next_char() issues + 547637 unconditional #include of sys/statfs.h in configure + 547337 G_DISABLE_DEPRECATED breaks tests build + 547832 gtk+-2.12.11 fails to build - AC_PROG_MMAP too strict + 502498 Test framework assertion failures should follow gcc + 546371 Improve docs re g_file_monitor + 546483 GThemedIcon:use-default-fallbacks is not readable without... + 546132 GFileIcon is bindings-unfriendly + 542156 zfs mount in home directory shown on nautilus desktop + 535124 umask 002 not being applied for new directories... + 547080 g_file_copy leaks expected errors + 546582 Callbacks from GFileMonitor present a GFile... + 547262 Missing link in the docs + +* Updated translations: + Arabic (ar) + Catalan (ca) + Spanish (es) + Basque (eu) + Finnish (fi) + Galician (gl) + Hebrew (he) + Marathi (mr) + Norwegian bokmål (nb) + Portugese (pt) + Brazilian Portugese (pt_BR) + Swedish (sv) + Thai (th) + + +Overview of Changes from GLib 2.17.4 to GLib 2.17.6 +=================================================== + +* Fix problems on 64-bit Windows + +* g_markup_context_get_user_data: New function to access + the user_data outside of callbacks + +* GIO + - g_mount_guess_content_type_sync: synchronous version of + g_mount_guess_content_type + - GEmblem: A GIcon implementation that adds emblem-related + metadata to icons + - GEmblemedIcon: A GIcon implementation that can add emblems + to icons + +* Bugs fixed: + 544088 option_test_LDADD is left in tests/Makefile.am + 544465 gmarkup makes it hard to use pre-rolled parsers + 545485 Implicit declaration of utime() + 545798 "Since: 2.18" mark is missing in g_set_error_literal... + 544140 fam-helper 64-bit issue + 529694 SELinux context setting support + 545157 wrong/no list of "open with" applications for .cc... + 545203 gfile.c: argument is different type + 545457 gdmsetup crashed with SIGSEGV in g_unix_mount_guess... + 544177 Fix trivial cut and paste error in documentation + 545395 Language tweak for g_value_set_string* docs + 541036 Gnumeric crashes when trying to open Desktop... + 546079 leak in xdgmime + 545395 Language tweak for g_value_set_string* docs + 546017 Don't copy attributes when copying a symlink + +* Updated translations: + Arabic (ar) + Estonian (et) + Galician (gl) + Italian (it) + Japanese (ja) + Korean (ko) + Norwegian bokmål (nb) + Pashto (ps) + Portugese (pt) + + +Overview of Changes from GLib 2.17.3 to GLib 2.17.4 +=================================================== + +* GIO: + - New API to handle content types: g_mount_guess_content_type, + g_content_type_guess_for_tree. + - Export the eject-button signal on the volume monitor class + - New API to enable out-of-process volume monitors: + g_volume_get_activation_root + +* GObject: + - New API to handle signals without slots in the class structure: + g_signal_new_class_handler, g_signal_override_class_handler + +* Internationalization: + - Add an NC_ macro that is a no-op equivalent of C_ + +* GMarkup: + - Add two new functions g_markup_parse_context_push, + g_markup_parse_context_pop to support "subparsers" + +* Bugs fixed: + 541208 Functions to easily install and use signals without... + 541507 Ambiguous description of assigned characters in the... + 543040 async reading on dummy file will crash on GIO_USE_VFS=local + 543560 enable gio-FEN back-end warnings on Solaris will crash... + 528317 GRegex does not allow recursion limit + 337518 GMarkup: Subparser support + 541794 drive-eject-button signal + 541793 activation root for volumes + 467707 test_iconv_state() in tests/convert-test.c fails on AIX 5.3 + 428048 2 of 51 tests fail on Solaris + 542332 small fix for error message in GMarkup + 482413 get_contents_stdio -- overflow and memory corruption + 406120 g_ascii_strtod + 334234 "printf" format error + 536996 Missing noop i18n macro equivalent to C_ + 540616 mem leak in filechooser button + 539229 gobject-query calls itself query + 521589 [RFC] gobject documentation should mention Vala + 543168 Description of G_SLICE=debug-blocks discourages its use + 543220 Case collision on gio-extension-points.html + 530759 update the gobject tutorial to the XXI century + 535223 gbookmark file inefficiency ... + 543504 crash in Epiphany Web Browser: Opening local file + +* Updated translation: + German (de) + Estonian (et) + Pashto (ps) + Albanian (sq) + Thai (th) + Traditional Chinese (zh_HK) + Traditional Chinese (zh_TW) + + +Overview of Changes from GLib 2.17.1 to GLib 2.17.3 +=================================================== + +* PCRE + - fix for CVE-2008-2371 + +* Bugs fixed: + 538119 glib's mainloop leaks a pipe to sub-processes + 537635 Corrections and improvements to g_time_val_{to,from}_iso8601 + 539067 The document g_io_channel_win32_new_fd() says... + 535949 annotate g_strip_context and g_dpgettext with G_GNUC_FORMAT + 539123 annotate g_d[n]gettext with G_GNUC_FORMAT + 539074 Cannot get exit status with g_spawn_command_line_sync + 316221 G_LOCK warns about breaking strict-aliasing rules + 539770 migrate gstrfunc unit tests to gtest + 539626 Update docstrings for g_object_freeze_notify and g_object_thaw_notify + 538044 unconditional use of LC_MESSAGES + 540545 Monotonic time and timer offset + 535947 want g_set_error_literal + 539999 glibconfig.h: add GLIB_USING_SYSTEM_PRINTF + 536252 GFileEnumerator should allow access to the containing GFile + 538362 Get Win32 icons back in the file chooser + 540802 g_list_prepend doesn't concat lists + 540423 unrecoverable error after g_seekable_truncate + 538836 make check failure on PPC and ALPHA: pltcheck.sh on g_atomic_pointer_get + 539090 g_content_type_from_mime_type() should unalias + 540331 g_file_append_to () documentation: can return NULL + 534639 add g_desktop_app_info_new_from_keyfile + 536733 gio build failure on Irix + 536160 Add g_file_monitor() + 538127 FileChooser broken on win32 + 531476 /live-g-file/test_traverse_structure test fails on Mac HFS+ + 538564 gio should have gio-types.h + 540047 glib-genmarshal.c: '#include <io.h>' is too before + +Updated translations: + Korean (ko) + Occitan (oc) + + +Overview of Changes from GLib 2.17.0 to GLib 2.17.1 +=================================================== + +* New function: g_utime(), a gstdio wrapper for utime() + +* New functions: g_dgettext() and g_dngettext(), wrappers + for corresponding gettext functions with added functionaliy + +* Support the latest version of the shared-mime spec, including + icons for mime types + +* New function: g_themed_icon_prepend_name() + +* Bugs fixed: + 535418 Please document which glib version defines goffset + 528715 Misprint in the description of the interface g_type_class_add_private + 528714 Misprint in the description of the interface g_param_spec_flags + 537260 Doc bug in G_TYPE_INSTANCE_GET_CLASS() + 530527 Misprint in the description of the interface + g_cclosure_marshal_VOID__FLAGS + 530526 Misprint in the description of the fields 'class_init' and + 'class_finalize' of the structure GTypeInfo + 528719 Improvement to the documentation of the "g_object_connect" interface + 528172 gtk_signal_handlers_unblock_* functions return value + amount of matched signals, not amount of actually unblocked + 528717 Misprint in the description of the parameter 'type_id' for + the interface g_type_register_fundamental + 528716 Misprint in the description of the parameter 'iface_data' for + the callback types GInterfaceInitFunc and GInterfaceFinalizeFunc + 537555 GObject instantiation not thread safe + 537546 'desktop' shortcut in file chooser looks like a generic folder + 537392 Additional colon in xattr name + 536641 Filesystem querying in gio does not list AFS and autofs file systems + 528600 g_dummy_file_get_parent("scheme://example.com/") + 503071 Application direction changes to right to left even if theres no + translation + 502511 g_assert_cmphex prints invalid message + 338162 Use po/LINGUAS + 314453 Nautilus crashes in Solaris when browsing the attached file + 529321 make check fails in glib/pcre + 455215 g_get_user_special_dir: no reference about G_USER_DIRECTORY_DOWNLOAD + fallback to $HOME/Desktop if xdg-user-dirs is not in use + 498732 g_key_file_to_data cannot fail + 511367 add g_file_make_directory_with_parents + 531900 Use __builtin_offsetof for G_STRUCT_OFFSET if building with + gcc 4.0 or newer + 536158 also bump GHashTable version when a node is removed via + g_hash_table_iter_remove()/g_hash_table_iter_steal() + 531403 g_utf8_collate broken on Mac + 535628 test/patterntest.c still includes gpattern.h directly + 535625 alias.h:2648: error: 'utime' undeclared here (not in a function) + +* Translation updates: + Arabic (ar) + German (de) + Italian (it) + Norwegian bokmål (nb) + Thai (th) + + +Overview of Changes from GLib 2.16.x to GLib 2.17.0 +=================================================== + +* Update to Unicode 5.1 + +* Update included libcharset to the one shipped with libiconv 0.12 + +* Update included PCRE to 7.7 + +* Enforce that only toplevel headers are directly included. + This is turned on by default for GObject and GIO. To turn + it on for GLib, define G_DISABLE_SINGLE_INCLUDES. + +* Fix library version of GIO. GLib 2.16 shipped with libgio-2.0.so.0.0.0 + +* On Solaris, use FEN for file monitoring in GIO + +* Use the GIO_EXTRA_MODULES environment variable to find + additional GIO modules + +* G_GNUC_ALLOC_SIZE: New macro that wraps the gcc alloc_size + function attribute + +* g_checksum_reset: New function to reset the state of a GChecksum + +* g_unix_mount_monitor_set_rate_limit: New function to limit the + rate at which events are reported + +* g_file_query_file_type: New utility function to query the type of + a file + +* g_memory_output_stream_get_data_size: New function to obtain the + size of the written data. + +* Bugs fixed: + 522292 Gives warnings in glib/gutils.h with GCC in C99 mode + 523298 win_iconv can't convert from UTF-8 to GB18030 (or vice versa) + 518160 replace two g_strdup_printf calls in GBookmarkFile + 523877 gbookmarkfile: avoid using g_string_append_printf() and + other optimizations + 525192 100% CPU if run main loop with no IO sources + 315437 extern inline -> static inline + 524314 g_convert() on Win32 implicitly converts full width + alphanumerics into half width + 525732 Error in documentation for g_list_first + 525674 A typo in gmarkup.c + 448943 g_timeout_add_seconds() problems + 525972 UCS-4 not in the new win_iconv implementation + 526619 make test-report crash + 491554 Update to Unicode 5.1.0 + 519137 g_slice_dup macro needs cast for 64-bit platform + 528752 Win32 build and SSL not working + 530457 G_USER_DIRECTORY_DOWNLOAD folder improperly mapped + 528667 Typos in testing module documentation + 459905 Bug in wcwidth data + 534085 g_unichar_iswide_cjk() has a totally wrong table + 501651 Update glib/libcharset + 519026 G_STMT_START/G_STMT_END test a non-existent preprocessor symbol + 534319 GLib's .pc files could use Libs.private + 534137 Typo in g_spawn_async_with_pipes doc + 517419 gio win32 directory monitor + 526796 Wrong order of arguments in g_file_copy's fallback + 530196 _g_local_file_has_trash_dir() doesn't handle st_dev == 0 + 532965 Should not return filesystem::free for certain file systems + 525553 fix typo and nitpicking in GArray documentation + 526572 Missing * in declaration of parent_class in Object + Destruction section of GObject Reference Manual + 528648 Extra >s in Object Construction section + 535021 g_param_spec_internal documentation should + describe purpose of nick and blurb + 521513 Firefox crash when using file picker + 528433 gdesktopappinfo snafu ... + 533369 API g_file_info_get_attribute_string () unables to get "... + 521045 glib f_fstypename miscellany + 521672 compile error + 521946 control rate limit on GUnixMountMonitor + 522335 Fails to build: glib/gtester.c:276: error: 'ARG_MAX' unde... + 523015 Implement sliding window based upload operation + 523019 Use new GCC 4 feature + 523338 list nfs4 as a nfs mount type + 524350 Make glib build without NLS again + 524579 g_file_copy reports wrong total on progress callback for ... + 524742 A typo in gtestutils.c. + 524950 Minor documentation typos. + 525866 the user directory should not be considered as a mount to... + 526320 should not list mounts that the user doesn't have permiss... + 527132 nautilus crash when making ftp connection + 532852 CRITICAL **: totem_pl_parser_parse_with_base: assertion `... + 534759 Build failure in gio + 534764 Typo in error produced by g_file_make_directory + 521851 Redudant tests in gunixmounts.c + 524344 glib/gthread.h still use G_GNUC_PRETTY_FUNCTION + 525060 glib fails to build with -DG_DISABLE_ASSERT in CPPFLAGS o... + 534177 Invalid description of the interface g_cclosure_marshal_S... + 520715 Add GFile method g_file_query_file_type + 523039 nautilus can't access to trash/computer/network if gvfs i... + +* Updated translations: + Arabic (ar) + Bulgarian (bg) + Catalan (ca) + Czech (cs) + Greek (el) + Candian English (en_CA) + British English (en_GB) + Spanish (es) + Estonian (et) + Basque (eu) + Galician (gl) + Hebrew (he) + Hungarian (hu) + Japanese (ja) + Lithuanian (lt) + Norwegian bokmål (nb) + Dutch (nl) + Occitan (oc) + Portugese (pt) + Russian (ru) + Slovak (sk) + Albanian (sq) + Swedish (sv) + Turkish (tr) + Vietnamese (vi) + + +Overview of Changes from GLib 2.16.0 to GLib 2.16.1 +=================================================== + +* Fix a crash in g_themed_icon_new + +* Update the included PCRE to 7.6 + + +Overview of Changes from GLib 2.15.6 to GLib 2.16.0 +=================================================== + +* Fix the definition of G_INLINE_FUNC to work with gcc 4.3.0 + +* GIO: + - Add missing GMountMountFlags argument to g_unix_volume_mount + - Fix the adopt_orphan_mount vfunc to take a volume monitor + reference + - Add properties to GThemedIcon for bindings sake + +* Bugs fixed: + 520484 gvfsd-trash crashed with SIGSEGV in g_path_is_absolute() + 510855 g_checksum_update(): Take -1 for length. + 517676 g_themed_icon_new*() do more than call g_object_new(). + 518816 should handle rmdir returning EEXIST correctly + 519352 g_[s]list_delete_link() docs + 519489 Fixes for sparse warnings in gio + 520169 add monitor argument to vfunc for GVolumeMonitor + 520700 Add type check in g_file_query_exists + 521145 FILE_READ_ONLY_VOLUME not present on Mingw32 + 518720 No MIME type for empty files + 521013 in documentation, goffset doesn't say "Since 2.x" + 521028 Missleading error messages from g_io_channel_set_encoding() + 517484 GMainLoop could set the thread "Alertable" for APCs to be... + +* Updated translations: + Assamese (as) + Bengali India (bn_IN) + Czech (cs) + German (de) + Spanish (es) + Estonian (et) + Finnish (fi) + French (fr) + Gujarati (gu) + Italian (it) + Lithuanian (lt) + Malayalam (ml) + Marathi (mr) + Norwegian bokmål (nb) + Romanian (ro) + Russian (ru) + Slovak (sk) + Ukrainian (uk) + + +Overview of Changes from GLib 2.15.5 to GLib 2.15.6 +=================================================== + +* GIO: + - New file attributes: trash::item-count, filesystem::use-preview + - Rename g_file_contains_file to g_file_has_prefix + - g_file_query_filesystem_info grew async variants + - g_themed_icon_append_name: new convenience function + - g_content_type_get_icon is implemented now + - Only show mounts in /media and ~ + - g_file_contains_file has been renamed to g_file_has_prefix + +* Win32: + - g_win32_get_package_installation_directory_of_module: new function + which supersedes g_win32_get_package_installation_directory + - Use alertable wait functions so that I/O completion routines or + user-mode Asynchronous Procedure Calls can be run + - Fix race conditions in g_spawn implementation on win32 + +* Other: + - g_uri_get_scheme has been renamed go g_uri_parse_scheme + +* Updated translations: + Arabic (ar) + Belarusian Latin (be@latin) + Catalan (ca) + British English (en_GB) + Finnish (fi) + Galician (gl) + Hebrew (he) + Italian (it) + Kannada (kn) + Norwegian bokmål (nb) + Dutch (nl) + Brazilian Portugese (pt_BR) + Vietnamese (vi) + + +Overview of Changes from GLib 2.15.4 to GLib 2.15.5 +=================================================== + +* Update the included PCRE to 7.6 + +* GIO: + - g_volume_should_automount: new function to determine if a volume + should be mounted automatically + - g_file_query_default_handler: new convenience function to get + the default handler for a file + - g_app_info_launch_default_for_uri new convenience function to + launch the default handler for a URI + - Use mimeapps.list and defaults.list as discussed on xdg list + recently + - g_app_info_get_default_for_uri_scheme has a real implementation + now (gvfs provides a GConf-based implementation) + - There is the beginning of a test suite + - standard::description: new file attribute + - GMountMountFlags flags argument added to mount calls + +* GObject: + - class initialization is now threadsafe + +* Updated translations: + Arabic (ar) + Catalan (ca) + Spanish (es) + Basque (eu) + Italian (it) + Japanese (ja) + Kannada (kn) + Korean (ko) + Macedonian (mk) + Occitan (oc) + Portugese (pt) + Brazilian Portugese (pt_BR) + Swedish (sv) + Thai (th) + + +Overview of Changes from GLib 2.15.3 to GLib 2.15.4 +=================================================== + +* G_GNUC_PRETTY_FUNCTION has been deprecated + +* GIO: + - g_file_copy has an async variant now + - Drives and volumes now have API to get identifiers + like Hal UDIs or UUIDs. + - There is now a registration API to let modules register + extensions they provide, such as volume monitor implementations + +* Bugs fixed: + 511807 g_time_val_to_iso8601() uses MT-unsafe gmtime() function + 316260 [patch] Doc patches for gnode (2.8.1) + 385132 solaris gettext support fix + 484261 ./configure check for system PCRE unicode support fails w... + 510292 GOption main help not shown + 511580 Implement g_file_copy_async + 511654 Compile errors due to C99 constructs + 487909 g_utf8_strreverse and combining marks + 512381 unused variable 'is_main_group' + +* Updated translations: + Arabic (ar) + Belarusian (be) + Czech (cz) + Spanish (es) + French (fr) + Galician (gl) + Portugese (pt) + Russian (ru) + Swedish (sv) + Thai (th) + + +Overview of Changes from GLib 2.15.2 to GLib 2.15.3 +=================================================== + +* GChecksum: + - g_checksum_update can accept nul-terminated strings + - The MD5 implementation works correctly on buffers + that are longer than 64 bytes + +* GIO: + - Don't include a copy of the inotify headers, rely on system headers + - g_file_find_enclosing_mount has an async variant now + - Reduntant seek API on file streams has been removed + +* Bugs fixed: + 508602 gmemory{in|out}putstream.c: unknown pointer size + 508771 There is no g_file_test/exists() for GFile + 508773 g_uri_escape_string() documentation unclear. + 509465 AM_PATH_GLIB_2_0 doesn't support gio + 509626 async functions: Document allowed NULL callback? + 509990 GSeekable documentation unclear + 510448 No inotify support on ARM or SH5 + 510855 g_checksum_update(): Take -1 for length. + +* Updated translations: + Basque (eu) + Marathi (mr) + Swedish (sv) + Ukrainian (uk) + + +Overview of Changes from GLib 2.15.1 to GLib 2.15.2 +=================================================== + +* GIO: + - Mount operation API change: unhandled methods get reported via + the reply, rather than by the signal emission return value + - File monitor API change: Add a GError argument to g_file_monitor_file + - g_unix_mount_guess_should_display(): new function + +* Bugs fixed: + 508224 [PATCH] FAM backend crashes due to double free + 508074 GAsyncResult documentation suggests g_freeing it. + 508108 GFile documentation slightly unclear. + 508309 rpc_pipefs mount points should be hidden + 508378 GFileInfo documentation implies that it changes attribute... + 508719 g_file_get_relative_path fails if parent is root + 508773 g_uri_escape_string() documentation unclear. + +* Updated translations: + Arabic (ar) + Spanish (es) + Hebrew (he) + Italian (it) + Korean (ko) + Turkish (tr) + + +Overview of Changes from GLib 2.15.0 to GLib 2.15.1 +=================================================== + + * Portability fixes: + - Assertion functions are marked as noreturn again + - Handling of inline functions has been fixed to work with gcc 4.3 + - C99 comments have been removed from headers + - The nonportable sed -i option is no longer used + + * GIO: + - Clarified the semantics of g_app_info_get_all() + - API for memory input and output streams has been changed a bit + - GDirectoryMonitor has been removed; GFileMonitor can monitor + files and directories now + + * Bugs fixed: + 504829 Invalid environment passed to g_spawn_async in g_desktop_... + 505258 crash in Users and Groups: Adding a user + 505815 g_content_types_get_registered should not g_free keys + 491218 g_timer_new() doesn't initialize timer->end + 315437 extern inline -> static inline + 476856 Inconsistency between standard and implementation of the ... + 480122 g_module_open fails to open modules with ".la" extension + 495589 gspawn.c failing to set FD_CLOEXEC + 500273 doesn't build with --disable-visibility + 504142 Do not show empty groups in --help output + 504879 giofam incorrectly linked + 505042 add file attribute for actually used file size in bytes + 505058 xattr namespace docs + 505674 Misprint in the definition of the macro G_CCLOSURE_SWAP_DATA + 505730 Fails to build on OSX 10.4: _NSGetEnviron not declared + 505887 older darwin lacks lchown + 506374 gmemoryinputstream api + 506461 Conversion of g_assert_not_reached() and friends into fun... + 503051 Small bug in glib interface + 506395 Updates to GIO documentation + 507628 Missing .pc entry for gio linking against glib + 505195 [patch] typo in g_try_new0 docs + 507822 g{file,directory}monitor changes signal problem + 506377 gmemoryoutputstream write implementation + 507835 bug in gunixinputstream + + * Updated translations: + Arabic (ar) + Belarusian Latin (be@latin) + Spanish (es) + Basque (eu) + Irish (ga) + Hebrew (he) + Occitan (oc) + Vietnamese (vi) + + +Overview of Changes from GLib 2.14.x to GLib 2.15.0 +=================================================== + +Major new features: + + * GIO: a VFS API, designed to replace GnomeVFS. The GIO implementation + in GLib has support for local filesystems. The new, separate gvfs + module contains various backend implementations (cifs, ftp, sftp, + http, ...) + + * GChecksum: provides various hash algorithms, such as MD5, SHA-1 + and SHA-256 + + * GTest: a test framework + +Smaller additions: + + * GHash: + - GHash has iterators, as an alternative to g_hash_table_foreach + + * GMarkup: + - g_markup_parse_context_get_element_stack: New function to + get the stack of open elements + - G_MARKUP_PREFIX_ERROR_POSITION: New flag to improve error + reporting + - g_markup_collect_attributes: Convenience function for handling + attributes + +* GKeyFile: + - Functions that take a GError now return a boolean to indicate + success, instead of void + - Various performance improvements + +* GAsyncQueue: + - g_async_queue_new_full: new function that allows to specify + a free function for leftover elements + +* GError: + - g_prefix_error and g_propagate_prefixed_error: New functions + to ease error propagation + +* Internationalization: + - C_: A new 2-argument variant of the Q_() macro + - Use native character set conversion API on Windows + +* GLib builds with automake 1.10 + +* Bugs fixed: + 455725 specific combination of g_utf8_strlen and g_pattern_match... + 467537 g_convert_with_iconv() not resetting iconv() state correc... + 497033 Commandline option parser should warn about missing optio... + 504527 gchecksum: Conditional jump or move depends on uninitiali... + 445362 Non-numeric local labels in gatomic.c are causing linker ... + 482313 gregex: no way to tell why compilation failed + 317775 main loops continues to run after g_main_loop_quit() has ... + 418778 Insufficient pkg-config version requirement + 436293 g_option_context_new() doc should mention that the string... + 466557 glib-mkenums shifts ARGV[0] to undefined + 468882 GKeyFile doesn't accept "True" as a true boolean value + 469551 application --help messages are garbaged on none UTF-8 lo... + 479724 Memory leak upon calling "g_main_loop_run" in the seconda... + 490061 outptrs uninitialized after g_parse_long_long + 490637 gobject documentation patch + 495294 glib-genmarshal prints warnings but returns 0 + 496046 option to prefix location of errors for GMarkup + 498113 tests/regex-test fails on 64bit environment + 500506 Fails to build on OSX 10.4 + 500638 gkeyfile speedup ... + 500875 Make check fails as there is no "test" target for "build"... + 502511 g_assert_cmphex prints invalid message + 502927 g_array_index triggers cast aligment warning + 503029 g_time_val_from_iso8601 parse non-ISO8601 dates + 503222 Need context to translate + 503420 gkeyfile leaks a hash table + 503470 Fix build when builddir != srcdir + 504227 Inverse variant for g_test_trap_assert_stdout, g_test_tra... + 71704 file include order + 491957 Misprint in the specification of the interface "g_main_co... + 491959 Misprint in description of the structure "GThreadPool" + 491965 Mistype in the specification of the function "g_hook_list... + 491966 Misprint in the specification of the interface "g_main_co... + 491968 The documentation does not mention the restriction for th... + 491970 The documentation for the interface "g_date_clamp" is inc... + 491974 The documentation of the interface "g_main_context_iterat... + 491975 The documentation for the interfaces "g_io_channel_read_u... + 491979 Misprint in the description of the interfaces g_key_file_... + 491982 Misprint in the description of the interface "g_key_file_... + 501107 EXTRA_DIST automake warnings + 501997 g_utf8_normalize() returns NULL on invalid string + 502590 C_/g_dpgettext efficiency + 464259 g_set_application_name() docs should say "Since 2.2" + 496518 gbase64.c API doc clarification + 498728 g_key_file_get_*_list should set length to 0 when returni... + 500361 Improve docs for g_array_free() and g_ptr_array_free() + 501853 g_checksum_get_digest docs + 503862 Allow NULL strings in g_parse_debug_string() + 142676 Q_ + 367550 Add g_async_queue_new_full() with GDestroyNotify function + 375651 Minor enhancements to GKeyFile API + 443648 MD5 digest support + 449937 Upgrade auto* sources to be clean under automake1.9 + 452887 gmarkup context "get element" function is useless when ca... + 491549 [PATCH] Eliminate libiconv dependency on Windows + 500507 GHashTableIter API + +* Translation updates + Belarusian Latin (be@latin) + Czech (cs) + German (de) + Spanish (es) + Esperanto (et) + French (fr) + Korean (ko) + Marathi (mr) + Norwegian bokmål (nb) + Brazilian Portugese (pt_BR) + Slovenian (sl) + Swedish (sv) + + +Overview of Changes from GLib 2.14.2 to GLib 2.14.3 +=================================================== + +* Update PCRE to 7.4 + +* Bugs fixed: + 487491 Fix some warnings from sparse + 488068 Small (one-time) memory leak in glib_gettext initialization + 493688 TYPE macro "_get_type ()" is documented wrong + +* Updated translations: + Arabic (ar) + Belarusian Latin (be@latin) + Estonian (et) + Irish (ga) + Slovenian (sl) + + +Overview of Changes from GLib 2.14.1 to GLib 2.14.2 +=================================================== + +* Bugs fixed: + 476849 Invocation of the interface "g_hook_free" fails in certai... + 359165 marshallers can throw warnings with -Wunused + 477957 more discussion on g_value_set_object vs. g_value_take_ob... + 478459 G_DEFINE_DYNAMIC_TYPE_EXTENDED doesn't work with G_IMPLEM... + 483337 inline is disabled for MSVC when compiling C code + 478349 Broken link to gettext website + 469231 g_spawn optimization for setting all open fds to CLOEXEC + +* Updated translations: +Arabic (ar) +Galician (gl) +Hebrew (he) +Korean (ko) + + +Overview of Changes from GLib 2.14.0 to GLib 2.14.1 +=================================================== + +* Bugs fixed: + 476840 Invocation of the interface "g_utf8_strreverse" crashes f... + 444765 Fix FIXME in gregex.c when new pcre is out + 464145 g_markup_escape_text Produces Invalid XML + 465625 g_type_default_interface_ref() does not ensure working g_... + 466768 Clearify that comments can be put anywhere in a Key-file. + 474229 The GError documentation should give convention for the G... + 474899 G_BREAKPOINT() docs inaccurate + 475854 Overuse of -lpcre when using system pcre + 473879 Incorrect includes in gregex.c + 468694 Typoes in documentation + 469051 g_snprintf () talks about characters where it probably me... + 457601 Missing arch specific atomic implementation + 475923 Missing pcre flags when static-linking against glib + 475619 glibthread-2.0.la does not list -lpthread + +* Updated translations: + Bulgarian (bg) + Catalan (ca) + Danish (da) + German (de) + Canadian English (en_CA) + British English (en_GB) + Spanish (es) + Estonian (et) + Finnish (fi) + French (fr) + Gujarati (gu) + Hungarian (hu) + Italian (it) + Georgian (ka) + Kannada (kn) + Lithuanian (lt) + Makedonian (mk) + Norwegian (nb) + Dutch (nl) + Polish (pl) + Portugese (pt) + Brazilian Portugese (pt_BR) + Romanian (ro) + Russian (ru) + Albanian (sq) + Serbian (sr, sr@Latn) + Swedish (sv) + Tamil (ta) + Thai (th) + Ukrainian (uk) + Vietnamese (vi) + + +Overview of Changes from GLib 2.13.7 to GLib 2.14.0 +=================================================== + +* Last-minute API additions: + - Make g_unichar_combining_class public + - Add goffset type, add G_MAXSSIZE and G_MINSSIZE + +* Update PCRE to 7.2 + +* Bugs fixed: + 453998 Make _g_unichar_combining_class() public + 462549 gregex.c: variable is declared at middle of block + 417068 g_file_test doc inconsistency + +* Updated translations: + Assamese (as) + Basque (eu) + Kannada (kn) + Malayalam (ml) + Dutch (nl) + Polish (pl) + Brazilian Portugese (pt_BR) + Turkish (tr) + + +Overview of Changes from GLib 2.13.6 to GLib 2.13.7 +=================================================== + +* The memory corruption warning from the slice allocator that + occurred when threads were initialized after the slice allocator + has been removed, as the slice allocator now works fine + in this scenario. + +* New functions g_once_init_enter() and g_once_init_leave() make + it easier to write threadsafe one-time initialization functions + +* Bugs fixed: + 454473 Simple XML Subset Parser terminates on invalid XML + 445813 g_module_open error, add file name + 453796 errno gets clobbered by g_filename_display_name + 341988 don't use "-c" with msgfmt in Makefile.in.in + 447048 Please produce slightly more output during long tests + 454785 GModule documentation lists same block of code twice. + 454786 GModule documentation lists same paragraph twice. + 383155 small docs quirks in gobject/closure API documentation + 65041 _get_type() functions aren't thread safe + +* Updated translations + Assamese (as) + Spanish (es) + Gujarati (gu) + Japanese (ja) + Korean (ko) + Macedonian (mk) + + +Overview of Changes from GLib 2.13.5 to GLib 2.13.6 +=================================================== + +* Reintroduce a GType typedef whose removal in 2.13.5 + caused trouble for C++ bindings + +* Bugs fixed: + 450216 docs not explicit enough about g_free() + 451459 g_type_register_static_simple calls g_type_register_static + +* Updated translations + Norwegian bokmål (nb) + Sinhala (si) + + +Overview of Changes from GLib 2.13.4 to GLib 2.13.5 +=================================================== + +* xdg-user-dirs support: + - the Desktop directory is guaranteed to be defined + - user-dirs.dirs is no longer reloaded on changes + +* Slice allocator: + - new api to duplicate slices + +* Regular expression support: + - GRegex is a boxed type now + +* Bugs fixed: + 44793 make check failing in trunk + 354522 Small problem with PLT hiding 6 symbols + 363986 glib 2.12.4 does not compile with SGI IDO cc + 443869 g_type_class_add_private doesn't warn when adding 0-sized... + 446859 Legitimately return 0 for g_quark_from_string(NULL) + 447534 Small typo in g_timeout_add_seconds() doc + 447583 GStaticRWLock + 447935 g_get_current_dir SIGSEGV on long path + 448260 CLAMP has surprising result if low > high + 57693 g_string_vprintf() + 442029 add g_slice_dup() + 445065 Add GRegex boxed type + 448819 Add full version of g_timeout_add_seconds() + +* Updated translations: + Swedish (sv) + Oriya (or) + Hebrew (he) + Spanish (es) + Estonian (et) + + +Overview of Changes from GLib 2.13.3 to GLib 2.13.4 +=================================================== + +* Bugs fixed: + 444121 g_get_user_special_dir deadlocks + 444161 invalid UTF8 in key name shows up as valgrind error in g_... + 444130 g_option_context_get_help() is broken when there's a desc... + + +Overview of Changes from GLib 2.13.2 to GLib 2.13.3 +=================================================== + +* GKeyFile: + - Added defines for easier handling of desktop files + +* Unicode support: + - Update g_unichar_iswide_cjk for Unicode 5.0 + +* Regular expression support: + - GRegex structs can now be ref-counted + - Some new functions for dealing with incremental + replacement have been added + - The GRegexEvalCallback signature has been changed + +* g_get_user_special_dir() has been added to support + xdg-user-dirs + +* Bugs fixed: + 419376 Functions using named subpatterns behave inconsistently w... + 434358 g_regex_fetch_named() and g_regex_fetch_named_pos() are b... + 423708 typo in the README.win32 file see patch below + 339225 Add new defines for easier handling of .desktop files + 442265 API additions/changes for GRegex + 432651 Add a glib-ish xdg_user_dir_lookup + +* Updated translations: + Estonian (et) + Norwegian bokmål (nb) + + +Overview of Changes from GLib 2.13.1 to GLib 2.13.2 +=================================================== + +* Unicode support: + - Add g_unichar_ismark() + +* GOption: + - Allow to use callbacks for remaining args + +* Updated translations: + Belarusian Latin (be@latin) + British English (en_GB) + Galician (gl) + Norwegian bokmål (nb) + Oriya (or) + Spanish (es) + Thai (th) + + +Overview of Changes from GLib 2.13.0 to GLib 2.13.1 +=================================================== + +* GRegex: + - Portability fixes + - Split into immutable GRegex and GMatchInfo + - Add g_regex_get_max_backref() and g_regex_get_capture_count() + to obtain information about the compiled regex + +* GKeyFile: + - Fix roundtrip problems + - Add g_key_file_load_from_dirs() + +* Unicode support: + - Fix corner cases in case conversion routines + +* GOption: + - Add a function to get the formatted help string + +* GHash: + - Add new functions g_hash_table_get_keys() and + g_hash_table_get_values() to retrieve the keys and + values in list form + +* Updated transations: + Simplified Chinese (zh_CN) + Arabic (ar) + + +Overview of Changes from GLib 2.12 to GLib 2.13.0 +================================================= + +* Add GSequence, a list that is implemented using + a balanced binary tree. + +* Add GRegex, an implementation of Perl regular expressions, + based on PCRE. + +* Use Posix monotonic clocks instead of gettimeofday() + for GTimer when available. + +* Support static initialization of GQeues with G_QUEUE_INIT, + g_queue_init() and g_queue_clear(). + +* Add g_string_chunk_clear() for clearing a + GStringChunk. + +* Add g_unichar_get_script() to obtain Unicode + script information. + +* Add g_unichar_iszerowidth() to obtain information + about zero-width characters. + +* Add G_GNUC_MAY_ALIAS which wraps the gcc may_alias + type attribute. + +* G_GNUC_INTERNAL has a working definition for the + Sun Studio compiler. This requires the macro to + be positioned before the function declaration. + +* The slice allocator can produce detailed debugging + information with G_SLICE=debug-blocks. + +* Modules support G_DEBUG flags resident-modules and + bind-now-modules. + +* Add G_DEFINE_DYNAMIC_TYPE() to make it easier + to define types in modules. + +* Bug fixes: too many to list them in detail here. + +* New and updated translations (be,bg,bn,ca,cs,de, + en_CA,en_GB,et,fa,fr,he,hu,it,ja,ku,lt,mg,mk,ml, + nb,ne,nn,pt,pt_BR,ro,sr,sr@Latn,sv,ta,uk,vi,zh_CN, + zh_HK,zh_TW) + + +Overview of Changes from GLib 2.12.1 to GLib 2.12.2 +=================================================== + +* Unicode updates: + - Normalization is following Unicode TR #29 + - g_unichar_isxdigit() only accept characters + for which g_unichar_xdigit_value() returns a value + - g_unichar_toupper and g_unichar_tolower leave + unconvertable characters in place instead of + replacing them by NUL + +* Bugs fixed + 348491 g_utf8_strup() and g_utf8_strdown() returns + string with NUL bytes + 349825 GKeyFile always inserts a newline before a group + 347842 g_unichar_isxdigit() is too general about what + it considers a digit + 348694 g_utf8_normalize() hasn't been updated to PR #29 + 348785 Hint about G_DEBUG in Message Logging docs + 349792 Wrong english string (UI) + 349952 gparamspecs.c uses gcc feature + +* Translation updates (ca,cs,de,dz,es,eu,fi,gu,ko, + nl,pl,tr,uk,zh_HK,zh_TW) + + +Overview of Changes from GLib 2.12.0 to GLib 2.12.1 +=================================================== + +* Update to final Unicode Character Database 5.0.0 + +* Bugs fixed: + 346660 issues with base64 api documentation / g_base64_decode_cl... + 348136 Coverity reports allocation of wrong size CID #2839 + 336281 Update to UCD 5.0 + 346197 g_date_strftime %F option doesnt work for win32 + 348011 Small optimization to real_toupper() + 246494 prototype mismatch in glib/gconvert.c + +* New and updated translations (bg,bn_IN,ca,dz,eu,fi, + fr,he,it,ja,mk,or,pt) + + +Overview of Changes from GLib 2.11.4 to GLib 2.12 +================================================= + +* Bugs fixed: + 344905 leap-year bug in g_time_val_from_iso8601 w/o HAVE_TIMEGM + +* Updated translations (cy,nb,nl) + + +Overview of Changes from GLib 2.11.3 to GLib 2.11.4 +=================================================== + +* GBookmarkFile: + - g_bookmark_file_remove_item returns a boolean + +* g_mkstemp accepts the XXXXXX in the middle of + the template + +* Bugs fixed: + 344868 g_key_file_to_data should separate groups + +* Updated translations (de,es,fr,gu,hi,ko,th) + + +Overview of Changes from GLib 2.11.2 to GLib 2.11.3 +=================================================== + +* GBookmarkFile: + - g_bookmark_file_move_item: Return TRUE in case of + an empty target + +* Bugs fixed: + 343919 gunicollate.c: strxfrm bug on VC8 + +* Updated translations (fi) + +Overview of Changes from GLib 2.11.1 to GLib 2.11.2 +=================================================== + +* Add g_ascii_stroll to parse signed 64bit integers + +* GMarkup: add a flag to treat CDATA as text + +* GHashTable: add functions to remove all entries + +* GMainLoop: add functions to find the currently + running source, and determine if it is destroyed + +* Bug fixes: + 342563 g_atomic_thread_init() needs to be called before + other _g_*_thread_init() functions + 343548 Potential use after free in callers of g_string_free() + 168538 Wish: Clearing contents of GHashTables + 321886 GTK+ cannot be reliably used in multi-threaded + applications + 341826 goption.c: 'strtoll' is C99's function + 343899 g_ascii_formatd dosn't work as expected for all + format strings + 317793 Make GEnumValue strings const + 337129 Compile warnings in G_IMPLEMENT_INTERFACE + 303622 What is G_TYPE_CHAR? + +* Updated translations (bg,dz,eu,gl,ja,ko,nl,th,vi) + + +Overview of Changes from GLib 2.11.0 to GLib 2.11.1 +=================================================== + +* GOption + - Support 64-bit integers + - Allow optional text before and after the options + in help output + +* Bug fixes: + 340538 gbase64-test writes OOB + 340816 GKeyFile set_string_list invalid memory reads + 339105 g_key_file_parse_value_as_double + 340434 convert-test.c fails (function test_one_half) + 311043 Memory leaks (and potential infinite loops) + when using G_ERRORCHECK_MUTEXES + 335198 Error checking mutexes are fubar + 341237 Add a G_OPTION_ARG_INT64 + 341192 g_io_channel_set_flags not implemented on win32 + 336120 Allow adding description before/after GOption + --help output body + 341191 misplaced check in g_relation_delete + 340530 mismatched calloc / g_free in win32 threads + +* Updated translation (es) + +Overview of Changes from GLib 2.10.x to GLib 2.11.0 +=================================================== + +* GBookmarkFile: a parser for files containing bookmarks + stored using the Desktop Bookmark specification. + +* Base64 encoding support + +* Unicode 5.0 support + +* GOption supports floating point numbers + +* GKeyFile supports floating point numbers + +* Bug fixes: + 155884 gatomic.c should be based on new SDK + 157877 update-desktop-database doesn't handle duplicate entries + 164719 keyfile parser doesn't support floats + 327662 Import BookmarkFile from libegg + 329548 Add G_OPTION_ARG_DOUBLE + 329789 option-test.c type confusion + 332841 Segmentation Fault when %llu is passed to vasnprintf and + HAVE_SNPRINTF is not defined + 333879 gthread/gthread-win32.c: IsDebuggerPresent needs '#define + _WIN32_WINDOWS 0x0401' + 333916 g_timer_elapsed docs should mention that microseconds + may be NULL + 334440 dlerror() portability issue causes crash on (old) a.out + NetBSD platform + 334646 goption + error out params + 334799 g_remove() must check return value of remove() + 334943 make check FAIL: threadpool-test + 335215 Some breakages with GThreadPool + 336085 g_option_context_new parameter lacks better explanation + 336677 Documentation for g_object_ref_sink() is incorrect + 337027 gbookmarkfile.c: sys/time.h include error + 337553 Wrong escaping of URIs + 338572 Dereferencing NULL value in g_key_file_get_group_comment + 338845 g_completion_complete_utf8 crashes when NULL is passed to it + 339337 g_bookmark_file_set_description + 339338 gbookmarkfile.c, function expand_exec_line + 339340 gbookmarkfile.c, function bookmark_app_info_dump + +* Translation updates (bg,en_GB,et,gl,gu,he,hi,ka,nb,nl,nn, + or,pt_BR,ro,tr,vi,zh_CN) + + +Overview of Changes from GLib 2.10.0 to GLib 2.10.1 +=================================================== + +* Bugs fixed: + 314794 Broken pthread detection on Darwin [Gregor Riepl] + 322476 Missing check for .dylib [Vladimir Panov] + 333651 Inconsistent _g_charset_get_aliases prototype [Julio + M. Merino Vidal] + 333761 GInitiallyUnowned breaks application code [Sven Herzberg] + +* Win32 changes: + - Fix g_listenv() implementation. + - Allow up to 100 GPrivate structs + +* Translation updates (fr,hu,lt,pl,sv) + + +Overview of Changes from GLib 2.9.6 to GLib 2.10.0 +================================================== + +* Bugs fixed: + 328997 64bit pointer trunction in glib slab-allocator + [Pascal Hofstee] + 331110 g_cond_broadcast(inform_cond) without holding + inform_mutex [Chris Wilson, Sebastian Wilhelmi] + 332093 Fix some leaks in the tests [Kjartan Maraas] + 332435 g_utf8_strlen returns wrong value if a maximum + number of bytes to check is specified + [Matthias Clasen] + 331367 gslice requires more POSIX-like semantics for + GPrivate destructors [Tor Lillqvist] + +* Documentation improvements [Matthias, Kang Jeong-Hee, + Tor Lillqvist, Stefan Kost] + +* Translation updates (el,eu,ka,uk) + +Overview of Changes from GLib 2.9.5 to GLib 2.9.6 +================================================= + +* Bugs fixed: + 329124 distclean removes README [Kjartan Maraas, Tim Janik] + 317679 GRelation field type not documented [Behdad Esfahbod] + 329123 Typo in GTime docs [Kjartan Maraas] + +* Documentation improvements [Sven Herzberg, David + Schleef, Kjartan Maraas, Behdad Esfahbod] + +* Translation updates (cs,cy,it,ko,pt,sq,sr,sr@Latn,ru + +Overview of Changes from GLib 2.9.4 to GLib 2.9.5 +================================================= + +* Memory management: + Runtime debugging support: The slice allocator + can be turned off by setting G_SLICE=always-malloc + in the environment. Zeroing of freed memory can + now be turned on at runtime by setting + G_DEBUG=gc-friendly in the environment. [Tim Janik] + +* Bugs fixed: + 328253 HP-UX/IA-64 uses ".so" as default shared library + extension [Albert Chin] + 143380 unicode-encoding test fails converting to UTF-16 + with libiconv [Marc Moorcroft] + 328254 Build breakage (GSlice) [Jens Ganseuer] + 328705 C99ism in glib/gmem.c [Kazuki Iwamoto] + +* Translation updates (da,et,zh_CN) + +Overview of Changes from GLib 2.9.3 to GLib 2.9.4 +================================================= + +* Type system: + Fix a problem with g_object_compat_control() which + can lead to segfaults in GTK+ applications on 64bit + platforms. + +* Thread suppport: + Unused threads now fall back to the global pool after + 500 milliseconds, where they wait for another + max-idle-time milliseconds. [Sebastian Wilhelmi] + +* Fix a memory allocation problem in GKeyFile. [Morten + Welinder] + + +Overview of Changes from GLib 2.9.2 to GLib 2.9.3 +================================================= + +* GTree: + - Replace the simple recursive implementation by + a nonrecursive, threaded one [Maurizio Monge] + +* Change g_filename_display_name and + g_filename_display_basename to use the Unicode + replacement character U+FFFD instead of a question + mark, and don't append "(invalid encoding)" [Matthias] + +* Documentation improvements [Sven Herzberg, Federico + Mena Quintero, Stefan Kost] + +* Bugs fixed: + 323937 gslice.c in glib 2.9.1 doesn't build on Mac OS X + [Bogdan Nicula] + 326558 Some test failures on IRIX 6.5 [Daichi Kawahata] + 169285 "threaded" tree implementation for GTree + [Maurizio Monge] + 326747 g_filename_display_basename adds (invalid encoding) + [Alberto Ruiz] + +Other contributors: Christian Kellner, Murray Cumming + +New and updated translations (bg,ca,de,es,et,gu,ja,nl,th,vi) + + +Overview of Changes from GLib 2.9.1 to GLib 2.9.2 +================================================= + +* Memory management: + - Add tests for cache colorization [Tim Janik] + - Minimize space consumption if small amounts of differently + sized slices are allocated, at a small performance cost. [Tim] + +* Thread support: + - Add g_atomic_pointer_set() and g_atomic_int_set() [Tim Janik, + Sebastian Wilhelmi] + - Add g_thread_pool_set_sort_function() to allow sorting the + tasks of a threadpool. [Martyn Russell] + - Add g_thread_pool_set_idle_time() to allow unused threads + to exit after a certain time. [Martyn] + +* Type system: + - introduce a new type GInitiallyUnowned, which has an initial + floating reference. [Tim] + - Add support for GType parameters. [Matthias] + +* Main loop: + - Add g_main_context_is_owner() to determine if the current + thread is the owner of the context. [Michael Meeks] + +* Provide g_access(), g_chdir(), g_unlink(), g_rmdir() as + wrapper functions instead of macros. [Manish Singh] + +* Documentation improvements [Tim, Matthias, Federico Mena Quintero, + Stefan Kasal, Dan Williams] + +* New and updated translations (en_CA,fi,fr,gl,ml,nb,no,zh_HK,zh_TW) + +* Bugs fixed: + 324179 g_allocator_new() returns pointer to const dummy which Gtk+ 2.8 + tries to modify [J. Ali Harlow] + 324332 g_option_context_parse() returns false without setting error + [Tim-Philipp Müller] + 324950 GLIB 2.9.1 testcase errors [Dan Yefimov] + 325015 gslice.c: process.h is needed on Windows [Kazuki Iwamoto] + 321978 G_DATALIST_GET_FLAGS() macro is not casting datalist to + gpointer [Andrew Paprocki] + 316221 G_LOCK warns about breaking strict-aliasing [Michal Benes, + Stanislav Brabec] + 325273 Error in documentation for glib_check_version () [Declan Naughton] + 325310 g_spawn_sync hangs when catching both stdout and + stderr [Tor Lillqvist] + 325249 gcc warning when using g_rmdir from <glib/gstdio.h> [Jani Monoses] + 325864 glib/gthreadpool.c:"#define debug(...)" is C99 [Kazuki Iwamoto] + 325874 Should say somewhere that source IDs are > 0 [Dan Williams] + 325438 a typo (compatability) [Stefan Kasal] + 323937 gslice.c in glib 2.9.1 doesn't build on Mac OS X [Bogdan Nicula] + + +Overview of Changes from GLib 2.9.0 to GLib 2.9.1 +================================================= + +* Memory management + - The slice allocator is implemented [Tim Janik] + - g_slice_free_chain() has been renamed to + g_slice_free_chain_with_offset() [Tim, Behdad Esfahbod] + - Mem chunks are deprecated [Matthias Clasen] + +* Data structures + - Hash tables are refcounted, and have a boxed type [Tim] + +* Thread support + - Support for Solaris threads has been removed + [Sebastian Wilhelmi, Andrew Paprocki] + - g_async_queue_sort(), g_async_queue_push_sorted() have + been added to allow GAsyncQueue to be used as a priority + queue, together with the corresponding _unlocked + variants [Martyn Russell] + +* GObject: + - The concept of a floating initial reference has been + moved from GtkObject to GObject [Tim] + +* Win32 changes: + - Make g_rename() replace existing files [Tor Lillqvist] + +* Misc new API: + - G_GUINT64_CONSTANT macro to define guint64 + constants [Andrew Paprocki] + - G_GNUC_WARN_UNUSED_RESULT macro to instruct the + compiler to emit a warning if the value returned + by a function is ignored. [Arjan van de Ven, Alex Larsson] + - GList and GSList now have sort functions which take an + extra user data argument [Martyn Russell] + - g_param_spec_ref_sink() has been added for consistency [Tim] + +* $LOGNAME is respected when determining user data. [Laszlo Peter] + +* Other changes and bug fixes [Tim, Matthias, Behdad, + Christian Persch, Benedikt Meurer, Andrew Paprocki, + Kazuki Iwamoto, Alexis S. L. Carvalho, Stanislav Brabec, + Andreas Schwab, Kalle Vahlman] + +* Documentation + - Deprecation warnings carry version information [Matthias] + - The slice allocator has been documented [Matthias, Tim] + - Other improvements [Morten Welinder] + +Overview of Changes from GLib 2.8.x to GLib 2.9.0 +================================================= +* Unicode support: + - The Unicode tables have been updated to Unicode 4.1, + adding several new values to the GUnicodeBreakType + enumeration. This breaks Pango <= 1.10 + [Behdad Esfahbod] + - The various Unicode character predicate functions + (g_unichar_isalpha, g_unichar_isdigit,...) have + been optimized + [Behdad] + - g_utf8_pointer_to_offset, g_utf8_offset_to_pointer: + These functions handle negative offsets now, and + going backwards in g_utf8_offset_to_pointer uses + "stutter stepping". + [Larry Ewing, Matthias Clasen] + +* Memory management: + - Mem chunks are no longer used internally in GLib and + GObject. GMemChunk will be deprecated in GLib 2.10 + - All APIs based on GAllocator (g_list_push/pop_allocator, + and similar push/pop_allocator functions for other + data structures) have been deprecated, since they + never worked as intended. + - The g_slice_* functions have been added as a + new API for fast allocation of small memory blocks. + The implementation in GLib 2.9.0 is just a simple + wrapper around malloc. GLib 2.10 will have an + efficient and scalable implementation. + [Tim Janik, Matthias] + +* Pattern matching: + - g_pattern_match has been optimized to avoid + unnecessary recursion. + [Tim, Matthias] + +* g_intern_string, g_intern_static_string: + - New functions to intern strings. These are now used + by GObject to avoid duplicating static strings + [Matthias] + +* g_thread_foreach: + - New function to iterate over all GThreads + [Tim, Matthias] + +* g_date_set_time_t, g_date_set_time_val: + - New functions to set a GDate from a time_t or + GTimeVal value. g_date_set_time has been deprecated + in favor of these. + [Roger Leigh] + +* g_snprintf and g_vsnprintf: + - These functions are no longer declared in gprintf.h, + since they are in glib.h + [Matthias] + +Overview of Changes from GLib 2.8.0 to GLib 2.8.1 +================================================= +* Optimize single-character insertions in GString [Ross Burton] +* Fix build problems on OS X +* Fix build problems on Win32 [Tor Lillqvist, Hans Breuer] +* Other bug fixes [Matthew F. Barnes, Stepan Kasal] +* Documentation improvements [Tristan van Berkom, Behnam + Esfahbod, Gustavo Carneiro, Stepan Kasal, Matthias] +* New and updated translations (ca,cy,ko,ro,uk) + +Overview of Changes from GLib 2.7.7 to GLib 2.8.0 +================================================= +* Make g_value_transform() handle enum values + correctly on ppc64. [Michael Lorenz] + (Third-party code accessing enumeration values + in GValues should also be changed to access + v_long, not v_int, in order to work on bigendian + 64bit machines.) +* Make g_flags_get_first_value() handle a value + of 0 meaningfully. [Tim-Philipp Müller] + +Overview of Changes from GLib 2.7.6 to GLib 2.7.7 +================================================= +* Make atomic operations on s390 work [Matthias] +* Fix C++ guards in gstdio.h [Tor Lillqvist] + +Overview of Changes from GLib 2.7.5 to GLib 2.7.6 +================================================= +* Add native implementations of atomic operations + on s390 [Matthias] +* Make atomic reference counting of closures + work on s390 [Matthias] +* Avoid an infinite loop in g_convert_with_iconv(). + [Sebastian Bacher] +* Documentation improvements [Ross Burton] + +Overview of Changes from GLib 2.7.4 to GLib 2.7.5 +================================================= +* Thread-related changes + - Fix build issues on HP-UX [Paul Cornett] + - Threadsafe access to flags stored in datasets [Tim Janik] + - Fix several issues with atomic refcounting for + closures, objects and paramspecs [Tim] + - Improve tests for atomic refcounting changes [Tim] +* Fix handling of stateful encodings in g_convert_* [Matthias] +* Fix translation of GOption help output [Dan Winship] +* Catch format errors in translations. This may cause + "make check" to fail when using older versions + of gettext [Matthias] +* Win32 bug fixes [Tor Lillqvist] +* Documentation improvements [Ross Burton, Jochen Baier, + Matthias, Tim] +* New and updated translations (de,fi,gu,pl,pt,tr,zh_TW) + +Overview of Changes from GLib 2.7.3 to GLib 2.7.4 +================================================= +* Fix g_atomic_pointer_compare_and_exchange + on Sparc64 [Gert Doering] +* Fix a hang in g_thread_pool_free. [Hong Jen Yee] +* Win32 bug fixes [Tor Lillquist] +* Other bug fixes [Benoit Dejean, Manish Singh] +* Documentation improvements [Bryan Silverthorn, + Callum McKenzie] +* New and updated translations (de,lt,sq,zh_CN) + +Overview of Changes from GLib 2.7.2 to GLib 2.7.3 +================================================= +* GOption + - Allow callbacks with optional arguments [Pawel Sliwowski] + - Allow to turn off the automatic long option name + disambiguation [Adam McLaurin] + - Only allow printable ASCII as short option names [Matthias] +* Win32 + - Build fixes [Tor Lillqvist] + - Rewrite iochannel socket implementation [Tor] +* GObject + - Threadsafety improvements; in particular, refcounting + of objects is done atomically now. [Wim Taymans, Tim Janik] +* Bug fixes [Morten Welinder, Matthias, Wim Taymans] +* Documentation improvements [Richard Laager, Matthias] +* New and improved translations (bf,cs,hu,nb,nl,no) + +Overview of Changes from GLib 2.7.1 to GLib 2.7.2 +================================================= +* Win32 build fixes [Hans Breuer] +* Bug fixes [Mikael Magnusson] +* Documentation improvements [Matthias Clasen] +* New and updated translations (en_CA,es,et,ja,sr,sr@Latn,zh_TW) + +Overview of Changes from GLib 2.7.0 to GLib 2.7.1 +================================================= +* GOption + - Allow callback arguments without parameters [Dan Winship] +* GMappedFile: an mmap wrapper [David Schleef, Behdad Esfahbod] +* Misc new functions: + - g_get_host_name [Tor Lillqvist] + - g_mkdir_with_parents [Tor] + - g_build_pathv, g_build_filenamev [Todd A. Fisher, + Matthias Clasen] +* Bug fixes [Roger Leigh, Masatake YAMATO, Kjartan Maraas, + Manish Singh, Tor, Murray Cumming, Kian Duffy, Morten Welinder] +* Documentation improvements [Hong Gang XU, Dan Winship, Matthias] +* New and updated translations (bg,cs,da,en_CA,es,et,nb,nl,no, + sk,th,zh_TW) + +Overview of Changes from GLib 2.6.x to GLib 2.7.0 +================================================= +* GKeyFile + - Add unit tests [Matthias Clasen, Suren A. Chilingaryan] + - Accept \r\n as line end [Bastian Nocera] + - Don't interpret leading zeros as octal numbers. [Matthias] + - Make key and group removal work [David Hoover, Matthias Hasselmann] +* GOption + - Improve formatting of --help output [Matthias, Noah Levitt] + - Accept -? [Matthias] + - Warn about duplicate main groups [Jeff Franks] + - Treat '-' as non-option argument [Tim Musson, Thomas Leonard] + - Report missing arguments as errors [Björn Lindqvist] + - Add a boxed type for GDate [Tim-Philipp Müller] +* GTree + - g_tree_remove() and g_tree_steal() return status information [Matthew F. Barnes] +* Stdio wrappers + - Work regardless of large file support [Manish Singh] + - Add g_access(), g_chmod(), g_creat(), g_chdir [Tor Lillqvist] +* GObject + - Implement "toggle references" to help language bindings [Owen Taylor] + - Allow to mark names, nicks and blurbs of pspecs as static [Ben Maurer, Matthias] + - Make pspec lookup a bit faster [Morten Welinder] +* Add g_listenv() to list all set environment variables [Hans Petter Jansson] +* Add g_file_set_contents() to atomically write a file. [Søren Sandmann, + Sven Neumann, Manish, Alexis S. L. Carvalho] +* Add g_try_malloc(), g_try_new(), g_try_new0() and g_try_renew() [Stefan Kost] +* Add g_utf8_collate_key_for_filename() to sort filenames taking + extensions and numeric suffixes into account. [Ole Laursen, Alex Larsson] +* Add G_GNUC_NULL_TERMINATED to mark varargs function with + NULL-terminated argument lists. [Marc Meissner] +* Win32 changes + - Improved debugability [Ulf Lamping, Hans Breuer] + - Make filename handling more robust [Tor, Billy Skaggs] + - Improve g_get_system_data_dirs() [Tor] + - Use more precise timers [Tor] + - Build fixes [Kazuki Iwamoto, Hans, Tor, Robert Ögren] +* Other bug fixes [Roger Leigh, Owen, Matthias, Morten, Kjartan Maraas, + Pawel Sakowski, Tor, Simon Budig, Ed Avis, Manish, Nicolas Laurent, + Bastien, Fabrício Barros Cabral, Michael Banck, Daniel Atallah, + J. Ali Harlow, Tim Janik, Hazael Maldonado Torres, Sven, Jon-Kare Hellan, + Dave Benson, Tommi Komulainen, Benjamin Otte, Brian Cameron, Changwoo Ryu, + Christian Biere, Noah, Benoît Carpentier] +* Documentation improvements [Vincent Untz, Matthias, Tim-Philipp Müller, + Morten, Matthew, Federico Mena Quintero, Sebastian Bacher, Oliver Sessink, + Stefan, Jared Lash, Tor, Owen, Daniel Vaillard, Mathieu Lacage] +* New and updated translations (ca,cs,da,el,en_CA,en_GB,es,et,eu,fa,fr,gl, + hu,id,it,lt,mn,ne,nl,pl,pt,pt_BR,ro,rw,sk,sq,sr,sr@Latn,tl,uk,xh,zh_CN) + +Overview of Changes from GLib 2.6.0 to GLib 2.6.1 +================================================= +* GOption + - Make gtk_init(NULL, NULL) work again [Marcin Krzyzanowski] + - Improve handling of -- [Matthias Clasen] + - Don't show G_OPTION_REMAINING in --help output [Matthew F. Barnes] +* g_find_program_in_path() doesn't return directories [Tommi Komulainen] +* Add gmodule-export-2.0.pc [Matthias] +* Win32 changes + - Improve hangling of UNC paths [Tor Lillqvist] + - g_getenv(), g_setenv(), g_unsetenv(), g_find_program_in_path() + take and return UTF-8 now [Tor] + - Make g_file_test() work more reliably, and use PATHEXT + when check for executables [Tor] + - Build and cross-compilation fixes [J. Ali Harlow] +* Other bug fixes [Jens Hatlak, Morten Welinder, + Tor, Kalpesh Shah, Adrian Bunk] +* Documentation improvements [Marcin Krzyzanowski, Tor, Crispin + Flowerday, Mariano Suárez-Alvarez, Christian Biere, Danny Milo, + Vincent Untz, Bastien Nocera] +* New and updated translations (cy,de,nl,ru,sq,sv) + +Overview of Changes from GLib 2.4.x to GLib 2.6.0 +================================================= + +* Major new APIs + - GOption, a commandline option parser + - GKeyFile, a parser/editor for the .ini like files + - Functions to support the XDG basedir specification + - Wrappers for common POSIX pathname functions to handle filename + encodings consistently. On Windows, these use UTF-8. + +* Miscellaneous new functions + - g_filename_display_name() converts filenames in displayable UTF-8 strings + - g_uri_list_extract_uris() splits uri lists + - g_date_get_iso8601_week_of_year() gets ISO 8601 week numbers + - g_log_set_default_handler() installs an alternate default log handler + - g_get_language_names() obtains a list of applicable locale names + - g_strv_length() calculates the length of NULL-terminated string arrays + - g_win32_get_windows_version() determines the Windows version + - G_GNUC_INTERNAL marks functions as non-exported + - glib_check_version() checks the GLib version at runtime + - g_debug() completes the family of logging functions + +* Performance improvements + - Optimize g_utf8_validate() + - Optimize g_markup_parse_context_parse() + - Reduce signal connection complexity from O(n) to O(1) + - Get rid of many PLT entries for internally used exported symbols + - Reduce code size by removing literal strings from g_return_if_fail() + +* Other changes + - On Windows, GLib functions that take file name arguments now require + those to be in UTF-8. Functions that return file names return UTF-8. + - Use higher precision for mathematical constants + - Don't convert to/from UTF-8 in g_filename_to_uri/g_filename_from_uri + - Support ll as printf format modifier for long long on all platforms + - Clean up the ABI and enforce the list of exported symbols + - Add a .pc file for using gmodule in libraries + - Require ngettext + +Overview of Changes from GLib 2.5.7 to GLib 2.6.0 +================================================= +* GOption: Don't list help options if group-specific + options have been requested [Glynn Foster] +* Make g_get_language_names() track locale changes [Christian Persch] +* Win32 bug fixes [Tor Lillqvist] +* Bug fixes [Philippe Blain, Owen Taylor, Sebastian Wilhelmi] +* New and updated translations (da,es,ja,lt,zh_CN) +Bugs fixed: 159530,100697,160271,160645,157255 + +Overview of Changes from GLib 2.5.6 to GLib 2.5.7 +================================================= +* Optimize g_utf8_validate() [Owen Taylor, Matthias Clasen] +* Optimize g_markup_parse_context_parse() [Havoc Pennington, + Morten Welinder] +* Reduce signal connection complexity from O(n) to O(1) + [Sven Neumann] +* Add a .pc file for using gmodule in libraries [Owen] +* Add G_GNUC_MALLOC to mark functions returning newly + allocated memory [Matthias] +* Win32 bug fixes [Hans Breuer, Tor Lillqvist, Robert Ögren, + Bruce Hochstetler] +* Bug fixes [Kazuki IWAMOTO, Matthias, Manish Singh, Morten, + Frederic Crozat, Tor] +* Documentation improvements [Matthias, Tor, Owen] +* New and updated translations (cs,da,de,en_CA,en_GB,es,nb,nl,sq,zh_CN) + +Overview of Changes from GLib 2.5.5 to GLib 2.5.6 +================================================= +* GOption + - Add G_OPTION_FLAG_REVERSE to allow options + which unset a boolean variable [Tor Lillqvist] +* GChildWatch + - Use sigaction instead of signal [Jonas Jonnson, + Archana Shah] + - Make the very first SIGCHLD work [Gustavo Carneiro] +* Bug fixes [Morten Welinder, Tor, David MacLachlan, + Manish Singh, J. Ali Harlow] +* Documentation improvements [Matthias Clasen, Tor] +* Updated translations (da,ja,tr,zh_CN) + +Overview of Changes from GLib 2.5.4 to GLib 2.5.5 +================================================= +* GKeyFile + - Cleanups, add more error checking [Ray Strode] + - Fall back to the untranslated string when getting + locale strings [Mark McLoughlin] +* GOption + - Document GOption [Matthias Clasen] + - Better support for rest arguments [Owen Taylor, Matthias] + - Handle conflicts between groups [Matthias] +* Add g_lstat() to the stdio wrappers [Tor Lillqvist] +* Add g_filename_display_name() to convert filenames + in displayable UTF-8 strings [Alex Larsson, Matthias] +* Win32 bug fixes [Kazuki IWAMOTO, Hans Breuer, Tor] +* Bug fixes [Christophe Fergeau, Morten Welinder, + Owen, Kjartan Maraas, Mark] +* Documentation improvements [Matthias, Tor] + +Overview of Changes from GLib 2.5.3 to GLib 2.5.4 +================================================= +Add GKeyFile, a parser/editor for the .ini like files used in various + freedesktop.org specifications. [Ray Strode] +Make the handling of filename encodings consistent across all + GLib functions, introduce wrappers for common POSIX + functions which accept the same filename encoding. [Tor Lillqvist, + Owen Taylor] +GOption + - Rename g_context_option_error_quark() to a more language-binding + friendly name [Murray Cumming] + - Accept backslashes in filenames on Win32 [Tor Lillqvist] +* Strip the internal aliasing prefix IA__ from function names in + assertions [Matthias Clasen] +* Add a function to split uri lists. [Matthias] +* Win32 bug fixes + - Don't open console windows [Tor] +* Other bug fixes [Philippe Blain, Robert Ögren, Hidetaka Iwai, Matthias, + Morten Welinder, Mats-Ola Persson, Tor, Nickolay V. Shmyrev, Kjartan Maraas, + Anders Carlsson, Tim-Philipp Müller, Lucas Rocha, Andrea Campi, Manish + Singh, Thomas Fitzsimmons, Kazuki IWAMOTO] +* Documentation improvements [Matthias, Linus Walleij, Nickolay, Philippe, + Adam Hooper, Gustavo Carneiro] +* New and updated translations (cs,en_CA,en_GB,ja,nb,nl,or,sr,sr@Latn,sq) + +Overview of Changes from GLib 2.5.2 to GLib 2.5.3 +================================================= +* GOption + - set the program name from argv[0] [Masatake YAMATO] + - make contexts work without a main group [Anders Carlsson] +* Performance + - Get rid of many PLT entries for internally used exported symbols, + and clean up the ABI at the same time and make make check check the + list of exported symbols. [Matthias Clasen] +* Add API to get ISO 8601 week numbers [Niklas Lundell] +* Add API to install an alternate default log handler [Darin Adler] +* Add API to obtain a list of applicable locale names [Hidetoshi Tajima] +* Reduce code size bloat by removing literal strings from + the g_return_if_fail() macros [Owen Taylor] +* Add g_strv_length [Tim-Philipp Müller] +* Win32 changes + - Add API to determine the Windows version [Tor Lillqvist] +* Other bug fixes [Stepan Kasal, Anders, Tor, Kazuki Iwamoto, + Manish Singh] +* Documentation improvements [Morten Welinder, Matthias] +* New and updated translations (es,nn,ro) + +Overview of Changes from GLib 2.5.1 to GLib 2.5.2 +================================================= +* Add G_GNUC_INTERNAL macro [Arjan van de Ven] +* Add GOption, a commandline option parser [Anders Carlsson] +* Add glib_check_version [Michael Natterer] +* Add XDG basedir API [Ray Strode] +* Require ngettext [Danilo Segan] +* Bug fixes [Manish Singh, Ray Strode, Vincent Noel, + Jon-Kare Hellan, Jody Goldberg] +* Win32 bug fixes [Tor Lillqvist, Hans Breuer, Peter Zelezny] +* Documentation improvements [Matthias Clasen, Vincent Untz, Christian Persch] +* New and updated translations (bs,eu,fi,gu,ne,pa) + +Overview of Changes from GLib 2.5.0 to GLib 2.5.1 +================================================= + +* Bug fixes [Oliver Guntermann, Sven Neumann, James + Henstridge, Hiroyuki Ikezoe, Matthias Clasen, Robert + Ögren, Tommi Komulainen] +* Documentation improvements [Soeren Sandmann, + Christophe Fergeau, Danek Duvall] +* New and updated translations (eu,hi) + +Overview of Changes from GLib 2.4.1 to GLib 2.5.0 +================================================= + +* New functions g_debug [Sven Herzberg] +* Use higher precision for mathematical constants [Morten + Welinder] +* Don't convert to/from UTF-8 in g_filename_{to,from}_uri + [Federico Mena Quintero] +* Win32 + - Handle empty digit string in printf() functions + correctly [Tor Lillqvist] + - Support ll as format modifier for long long [Tor] + - Be more careful about HOME [Tor, Ivan Wong] + - Bug fixes [John Ehresman] +* Miscellaneous bug and portability fixes [Danilo Segan, + Owen Taylor, Nikolai Weibull, Benoît Carpentier, Morten + Welinder, Manish Singh, Sven Neumann, Julio M. Merino Vidal, + Kaz Sasayama, Murray Cumming, Federico, Mariano Suarez-Alvarez] +* Documentation updates [Matthias Clasen, Crispin Flowerday, + Tommi Komulainen, Federico Mena Quintero, Ed Griffiths] +* New and updated translations (ja,ne,no,wa) + +Overview of Changes from GLib 2.4.0 to GLib 2.4.1 +================================================= + +* Win32 bug fixes [Tor Lillqvist, Roger Leigh, John Ehresman] +* Miscellaneous bug and portability fixes [Owen Taylor, + Matthias Clasen, Jonas Jonsson, Christian Krause, + Nickolay V. Shmyrev, Christophe Saout, Philippe Blain, + Piotr Klaban] +* Documentation updates [Matthias] +* New and updated translations (ca,cs,cy,el,en_CA,en_GB,es,eu,fi, + fr,gu,he,id,nl,pt,pl,ru,sr,sr@ije,sr@Latn,sv,uk) + +Overview of Changes from GLib 2.3.6 to GLib 2.4.0 +================================================= + +* Handle invalid-UTF-8 in g_log() properly [Matthias Clasen] +* Win32 bug fixes [Tor Lillqvist, Bruce Hochstetler] +* Miscellaneous bug and portability fixes [Olivier Biot, David L. Cooper II, + Kjartan Maraas, Frédéric L. W. Meunier, Christof Petig, Manish Singh, + Sebastian Wilhelmi] +* Documentation updates [Owen] +* Updated translations (hr,ro) + +Overview of Changes from GLib 2.3.5 to GLib 2.3.6 +================================================= + +* GAtomic bug fixes [Sebastian Wilhelmi, Mark McLoughlin] +* GMain threading fixes and improvements [Sebastian] +* Win32 [Tor Lillqvist] + - restore some symbols extraneously exported from gobject to maintain ABI compatibility + - Misc build improvements and fixes [Tor, Cedric Gustin, Hans Breuer] +* Documentation updates [Sebastian, Takeshi AIHANA, Matthias, Sven Herzberg] +* New and updated translations (be,es,fi,ga,pa,sr@ije,zh_CN) + +Overview of Changes from GLib 2.3.3 to GLib 2.3.5 +================================================= + +* Make glib-mkenums parse initializers with macros. [Matthias Clasen, muppet] +* Respect locale era in g_date_set_parse(). [Theppitak Karoonboonyanan] +* Add atomic operations and use it for the async queue and + gonce implementation. [Sebastian Wilhelmi] +* Documentation improvements [Sebastian, Matthias, Sven Herzberg] +* Add g_main_depth() for finding the recursion depth of the main + loop [Owen Taylor, Tim Janik, Stefan Westerfeld] +* Add g_spawn_close_pid(), needed on win32 [J. Ali] +* Win32 fixes. [Hans Breuer, J. Ali Harlow] +* Misc bugfixes [Sebastian, Matthias, Balazs Scheidler, Owen] +* Updated translations (cy,et,ga,sq) + +Overview of Changes from GLib 2.3.2 to GLib 2.3.3 +================================================= + +* Add a native AIX gmodule implementation. [Laurent Vivier] +* Add g_node_copy_deep(). [James M. Cape, Matthias Clasen] +* Extend GQueue API to match the GList API. [Soeren Sandmann] +* Add g_hash_table_find(). [Tim Janik] +* Add a G_MODULE_BIND_LOCAL flag. [David Schleef] +* Inline g_string_append_c() when possible. [Owen Taylor, Tim] +* Wrap waitpid() as a GSource. [Jonathan R. Blandford] +* Add g_completion_complete_utf8(). [Theppitak Karoonboonyanan, + Matthias] +* Add g_strsplit_set(). [Soeren] +* Documentation improvements. [Vincent Untz, Sebastian Wilhelmi, + Soeren, Matthias] +* Win32 build fixes. [Tor Lillqvist] +* Misc bugfixes [Manish Singh, Noah Levitt, Simon Josefsson, + Morten Welinder, Damien Carbery, Julio M. Merino Vidal, Sebastian, + Matthias] +* Updated translations (nn,cs,it,ko,sq,ms,az,hr,uk,sr,sr@Latn,sq,ta) + +Overview of Changes from GLib 2.3.1 to GLib 2.3.2 +================================================= + +* Add G_MAXSIZE. [Manish Singh] +* Add g_rand_new_with_seed_array(), g_rand_set_seed_array(), + implementing the init-by-array functionality of the + original mersenne twister. Add g_rand_copy(). Improve seeding. + [George Lebl] +* Add a lowercase_name option to glib-mkenums. [Murray Cumming] +* Add g_ptr_array_foreach(). [Matthias Clasen] +* Add g_timer_continue(). [Tim-Philipp Müller] +* Fix a threadsafety issue in mem chunks. [Matthias, Balazs Scheidler] +* Fix g_filename_{to,from}_utf8() on Win32 and improve + g_file_test() there too [Hans Breuer] +* Add a boxed type for NULL-terminated string arrays. [Matthias] +* Add G_DEFINE_TYPE() plus variants to ease the constuction + of GObject boilerplate code. [Tim Janik] +* Support & in password GECOS field [Matthias, Soeren Boll Overgaard] +* Documentation improvements [Matthias, Manish] +* Win32 build fixes [Hans] +* Misc bug fixes [Damien Carbery, Matthias, Manish, Olivier Poncet, + Zack Rusin] +* Updated translations (ar,de,fa,ga,mn,nn,no,sq) + +Overview of Changes from GLib 2.3.0 to GLib-2.3.1 +================================================= + +* Add glib/gi18n.h and glib/gi18n-lib.h for common + gettext support, including a Q_() macro for translation + with context [Matthias Clasen] +* Add a more flexible G_FILENAME_ENCODING variable + as a replacement for G_BROKEN_FILENAMES [Matthias] +* Fix the return value g_main_context_iterate() for + newly ready sources [Padraig O'Briain] +* Handle Hangul composition for normalization [Noah Levitt] +* Add G_{MIN,MAX,MAXU}INT{8,16,32}. [Mark Jones, Matthias] +* Add G_GSIZE_FORMAT/G_SSIZE_FORMAT [Manish Singh] +* Add G_STRFUNC as a portable wrapper for __func__ [Tim Janik] +* Documentation improvements [Matthias] +* GObject [Tim Janik] + - Support '-' in g_signal_connect()/disconnect() names + like 'swapped-signal'. + - Add g_type_class_peek_static() and use to optimize + g_object_new() for static types [Tim] + - Allow setting construct-only properties from within + init() implementations + - Enforce readability/writeability in g_object_set/get() +* Fix bug with g_ascii_strtod and multi-byte separator. + [Behdad Esfahbod, Roozbeh Pournader] +* Misc bug fixes [Matthias, John Ehresman, Andrew Lanoix, + Tor Lillqvist, Mark McLoughlin, Tim-Philipp Müller, Manish, + Morten Welinder] +* Updated translations (ca,cs,da,es,fr,ja,nn,no,pt,ru) + +Overview of Changes from GLib 2.2.x to GLib-2.3.0 +================================================= + +* Replace Trio printf by gnulib vasnprintf [Matthias Clasen] +* Update Unicode data to Unicode 4.0 [Noah Levitt] +* Support XML-safe formatted output with + g_markup_[v]printf_escaped [Owen Taylor] +* Add g_file_read_link to read symbolic links [Matthias] +* Add g_unichar_get_mirror_char to obtain the + mirrored variant of a character [Noah] +* Support for one-time initialization functions. + [Sebastian Wilhelmi] +* Miscellaneous API additions: g_vasprintf + g_string_chunk_insert_len, g_setenv, g_unsetenv [Matthias] +* Docs improvements [Matthias] +* Add support instance-private data on classed types + [Mark McLoughlin, Tim Janik, Owen] +* Optimize signal emissions [Soeren Sandmann, Tim] +* Support a "default vtable" per interface [Tim] +* Add support for properties on interfaces [Owen, Tim] +* Miscellaneous API additions: g_value_take_string(), + g_value_take_param(), g_value_take_object(), + g_value_take_boxed(). [Matthias] +* Win32 build fixes [Tor Lillqvist] + +Overview of Changes from GLib 2.1.5 to GLib-2.2.0 +================================================= + +* Fix a problem with g_thread_init() on 64-bit problems + [Alceste Scalas, Sebastian Wilhelmi] +* Add assembly implementations of byteswap macros + for ia64 and x86_64. [Manish Singh] +* IOChannel fixes for Win32 [Tor Lillqvist, Thorsten Maerz] +* Updated translations (bg,ca,es,da,fi,lv,ru,sk) + +Overview of Changes from GLib 2.1.4 to GLib-2.1.5 +================================================= + +* Win32 bug fixes [Tor Lillqvist] +* Various post-rewrite fixes for glib-gettext.m4 [Owen Taylor, + Jody Goldberg, Kjartan Maraas, Johannes Stezenbach] +* Ensure we have a GUINT64_FORMAT by pulling in Trio + if necessary [Manish Singh] +* Further Trio build fixes [Matthias Clasen, Owen] +* Hack around gcc, libtool issues with -pthread [Owen] +* Docs improvements [Matthias] +* Bug and portability fixes +* Updated and new translations (bg,de,fi,fr,sq,fr) + +Other contributors: Kai Poitschke, Morten Welinder + +Overview of Changes from GLib 2.1.3 to GLib-2.1.4 +================================================= + +* autoconf changes to make it possible to cross compile + GLib. [Owen Taylor, Dan Kegel, Amy Lin, Dimi Shahbaz, + Johannes Stezenbach] +* Use libintl when it has bind_textdomain_codeset() and + GLib doesn't. [Owen] +* Improve generation of pseudo-random integers [Morten Welinder, + Sebastian Wilhelmi] +* Avoid literal UTF-8 in favor of octal escapes [Owen, Tomas Ogren] +* Cleanup include order [Sven Neumann] +* autoconf cleanups and bug fixes [Daniel, Matthias Clasen, Owen] +* Doc fixes and additions [Matthias] + +Other contributors: James M. Cape, Frederic Crozat, Martin Gansser, + Phuc LeHong, Manish Singh, Joshua Weage, Morten Welinder + +Overview of Changes from GLib 2.0.x to GLib-2.1.x +================================================= + +* Add copy of the Trio library to build and use for printf() when + system printf isn't good enough. Add g_printf()/etc. [Matthias Clasen] +* Add g_str_has_suffix()/g_str_has_prefix() [Alex Larsson] +* Add g_markup_parse_context_get_element() [Matthias] +* Add g_utf8_strreverse [Matthias] +* Add g_ascii_strtoull() [Tim Janik] +* Support scanning of 64-bit values with GScanner [Tim] +* Add g_set/get_application_name() [Havoc Pennington] +* Add G_LIKELY()/G_UNLIKELY() macros for hinting branch probabilities. + Use for g_return_if_fail(). [Matthias Clasen] +* Add G_GNUC_DEPRECATED macro [Tom Tromey] +* Improve the seeding algorithm of GRandom to avoid problems + with certain pathological seeds. Support G_RANDOM_VERSION=2.0 + environment variable. [Sebastian Wilhelmi] +* Improve thread configure checks, use -pthread where applicable + [Sebastian] +* Improve handlng of thread priorities [Sebastian] +* Fix up parameter names that might shadow functions from + system headers [Soeren Sandmann] +* Clean up usage of deprecated functions [Manish Singh] +* Docs fixes and improvements. In particular, include "Since" information. + [Matthias, Soeren, Martin Schulze, Daryll Strauss, Bill Janssen, + Owen Taylor, Morten Welinder]. + +Overview of Changes in GLib 2.0.7 +================================= + +* Fix C++ warnings in gtype.h [Dom Lachowicz] +* Fix g_type_fundamental_next() [Tim Janik] +* Fix various missing includes of config.h [Morten Welinder] +* Handle main loop initialization before g_thread_init [Sebastian Wilhelmi] +* Various 64-bit fixes [Manish Singh] +* Fix GPoll on Win32 [Tor Lillqvist, Herman Bloggs] +* Fix bug with buffering on UTF-8 IOChannels [Daniel Elstner] +* Misc bug and build fixes [Soren Andersen, Gustavo Carneiro, Tor, + Tim, Havoc Pennington, Matthias Clasen, Sebastian Rittau, + Masahiro Sakai, Arvind Samptur, HideToshi Tajima, Owen Taylor] +* Updated and new translations (be,cs,de,*fa,it,lv,pt_BR,tr) + +Overview of Changes in GLib 2.0.6 +================================= + +* Fix problem with interface prerequisites [Jon Trowbridge, Dave Camp] +* Clean up debug spew from GObject [Anders Carlsson] +* Compiler warning fixes [David L. Cooper II] +* Fix some problems with g_build_path() [Guillaume Chazarain, Owen Taylor] +* Fixes for --disable-debug [Sebastian Wilhelmi] +* Threading fixes [Sebastian Wilhelmi, Miroslaw Dobrzanski-Neumann, + Rajkumar Sivasamy, Laurent Vivier] +* Documentation fixes [Jacob Berkman, Manuel Clos, Jared Dukat, + Sebastian Rittau, Linus Welleij] +* Misc bug fixes [Anders Carlsson, Sam Couter, Morten Welinder, Owen] +* Updated translations (bg,ko,vi) + +Overview of Changes in GLib 2.0.5 +================================= + +* Fix problem with interface prerequisites [Jon Trowbridge, Dave Camp] +* Clean up debug spew from GObject [Anders Carlsson] +* Compiler warning fixes [David L. Cooper II] +* Fix some problems with g_build_path() [Guillaume Chazarain, Owen Taylor] +* Fixes for --disable-debug [Sebastian Wilhelmi] +* Threading fixes [Sebastian Wilhelmi, Miroslaw Dobrzanski-Neumann, + Rajkumar Sivasamy, Laurent Vivier] +* Documentation fixes [Jacob Berkman, Manuel Clos, Jared Dukat, + Sebastian Rittau, Linus Welleij] +* Misc bug fixes [Anders Carlsson, Sam Couter, Morten Welinder, Owen] +* Updated translations (bg,ko,vi) + +Overview of Changes in GLib 2.0.4 +================================= + +* Fix some 64-bit problems. (George Lebl, David L. Cooper II) +* Add note about Tru64 iconv to INSTALL. (Manuel Op de Coul) +* Fix problem with timouts > MAXINT. (Tim Janik, Owen Taylor) +* Updated translations (ca,es,fr,ja,gl,ms,nl,pl,pt,ru) + +Overview of Changes in GLib 2.0.3 +================================= + +* Handle sorting 0-length arrays (Ron Arts) +* Threading fixes (Sebastian Wilhelmi) +* Portability fixes (Miroslaw Dobrzanski-Neumann, Jacob Berkman, Gareth Pierce, + Sebastian, Qingjiang Yuan) +* Various fixes for glib-2.0.m4. (Jim Gettys, others.) +* Locate right glib-genmarshal when cross-compiling. (Mitch Natterer) +* Win32 fixes (Tor Lillqvist) +* Try to fix g_get_charset() related segfaults. (Owen) +* Fixes for gettext detection. (Dan Winship, HideToshi Tajima, Boyd Lynn Gerber, + Andrew P. Lentvorski, Jr.) +* Fix g_scanner_unexp_token() (Tim Janik, Sven Neumann) +* g_markup fixes. (Matthias Clasen.) +* Bug fixes and cleanups (Daniel Elstner, Matthias, Laszlo Peter, Morten Welinder, + Wayne Schuller) + +Overview of Changes in GLib 2.0.1 +================================= + +* Portability fixes for Sun's Forte compiler [Erwann Chenede] +* Performance improvements for GObject parameter lookup, + g_filename_to/from_utf8() [Alex Larsson] +* Actually check interface prerequisites [Matthias Clasen, + Miroslaw Dobrzanski-Neumann] +* Fix problem with glib-mkenums taking huge amounts of stack. [Owen Taylor] +* Fix g_signal_handlers_disconnect_by_func() for C++ [Damien Sandras] +* Fixes for g_log() and threading. + [Sebastian Wilhelmi, Miroslaw Dobrzanski-Neumann, Tim Janik] +* Make g_print(), g_printerr(), g_warning(), etc, convert from + UTF-8 to the encoding of the locale [Sebastian Wilhelmi, Tim] +* Fixes for GIOChannel on windows. [Tor Lillqvist] +* Fix gsize/gint mismatches in giochannel.c [Miroslaw Dobrzanski-Neumann] +* Fix file descriptor leak in g_file_get_contents() [Matthias] +* Workaround iconv() problems on older Solaris [Lauri Alanko] +* Fix warnings with gcc-3.1 about asm const [Cody Russel] +* Minor bug fixes. + +Other contributors: Hans Breuer, LEE Sau Dan, Sven Neumann, Salmaso Raffaele, + Akira Tagoh, Morten Welinder + + +Overview of Changes in GLib 2.0.0 +================================= + +* Thread portability fixes [Sebastian Wilhelmi] +* Documentation updates [Owen Taylor] +* Make g_strerror(), g_strsignal() properly return UTF-8, + call bind_text_domain_codeset() so that error strings + are in UTF-8 as well. [Owen, Tor Lillqvist] + +Overview of Changes in GLib 2.0.0 rc1: +====================================== + +* Win32 fixes [Tor Lillqvist] +* Portability fixes [Finlay Dobbie, Miroslaw Dobrzanski-Neumann] +* Fix up g_date_strftime [Daniel Elstner] +* Add some structure padding [Tim Janik] +* Make g_get_homedir() prefer the users home directory to $HOME + +Other contributors: Matthias Clasen, Paolo Maggi, Christian Rose + +Overview of Changes in GLib 1.3.15: +=================================== + +* Speed up marshalers by using private access to GValue + [Anders Carlsson, Tim Janik] +* Reduce GValue to 2 elements [Tim] +* Add G_DEBUG environment variable, G_DEBUG=fatal_warnings [Matthias Clasen] +* Fixes for AIX compilation [Miroslaw Dobrzanski-Neumann] +* Add padding to various structures [Owen Taylor, Tim] +* Win32 fixes [Tor Lillqvist] + +Other contributors: James Henstridge, Ryan Lovett, Morten Welinder, + Daniel Elstner + +Overview of Changes in GLib 1.3.14: +=================================== + +* Register value transformations for gint64, guint64 [Andy Wingo] +* Build with large-file support [Sven Neumann, Owen Taylor] +* Fix handling of hostnames in URI's [Darin Adler] +* Main loop bug fixes [Havoc Pennington, Owen] +* Doc fixes and improvements [Manish Singh, Tim Janik] +* Support ' as attribute delimiters in GMarkup [Matthias Clasen] +* Win32 fixes [Hans Breuer, Tor Lillqvist] +* Threading bug and build fixes [Sebastian Wilhelmi, Miroslaw Dobrzanski-Neumann] +* Miscellaneous bug fixes + +Other contributors: Matthias Clasen, James Henstridge, Mitch Natterer, + Morten Welinder. + +Overview of Changes in GLib 1.3.13: +=================================== + +* Fix g_filename_to/from_uri for Win32 [Tor Lillqvist, Darin Adler] +* Miscellaneous win32 fixes [Tor, Hans Breuer] +* Fix thread options for gcc on AIX [Jerome Zago, Sebastian Wilhelmi] +* Documentation improvements [Ron Steinke, Matthias, Sebastian] +* Cache iconv converters as used by g_convert() [Jeffrey Stedfast] +* Bug fixes [Sven Neumann, Owen Taylor, Matthias Clasen, Jeffrey, + Laszlo Peter, Havoc Pennington, Tim Janik] + +Overview of Changes in GLib 1.3.12: +=================================== + +* Implement closure chaining, fixing up API (Tim Janik) +* Closure chaining test case (James Henstridge) +* Make GType long not int where both are equal width (Tim) +* Win32 fixes and improvements (Hans Breuer, Tor Lillqvist) +* Fixes for NetBSD. (Dan Winship) +* Use snprintf() for g_printf_string_upper_bound() where possible. (Matthias Clasen) +* Save space for GBSearchArray (Tim Janik) +* Documentation improvements. (Matthias, Sven Neumann, Havoc Pennington) + +Other contributors: Darin Adler, Chris Blizzard, Anders Carlson, Daniel Elstner, Michael Meeks, + Mark McLoughlin, Dave Neary, Manish Singh, Owen Taylor, HideToshi Tajima, + Sebastian Wilhelmi. + + +Overview of Changes in GLib 1.3.11: +=================================== + +* Win32 fixes [Hans Breuer, Tor Lillqvist] +* Documentation improvements [Matthias Clasen] +* Portable directory handling API [Hans] +* Threading fixes [Sebastian Wilhelmi, Havoc Pennington] +* Fix excess relocations in Unicode tables [Andrew Taylor] +* Fix gpattern for UTF-8 [Matthias Clasen] +* Support overriding class closures [Tim Janik] +* Support for derivation from G_TYPE_POINTER [Owen Taylor] +* Hide pointers to type information inside GType to reduce locking + [Alex Larsson, Tim] +* Adds check for direct inclusion of gobject/*.h [Owen] +* GObject API cleanups [Tim] + +Other contributors: Darin Adler, Jacob Berkman, Daniel Egger, Eric Lemings, + Michael Meeks, Mark McLoughlin, Arkadiusz Miskiewicz, Dan Winship + + +Overview of Changes in GLib 1.3.10: +=================================== + +* Many Win32 fixes and improvements [Tor Lillqvist] +* Documentation improvements [Matthias Clasen] +* g_string_printfa() renamed to g_string_append_printf() +* Use libcharset from libiconv to implement charset detection + more portably. [Owen Taylor, Hidetoshi Tajima] +* Add 64 bit type support to GObject [Joshua Pritikin, Mathieu Lacage, Owen] +* Make support for 64 bit integers a requirement [Joshua] +* GPattern improvements [Tim Janik, Matthias] +* Locale independent g_ascii_strtod / g_ascii_dtostr [Alex Larsson] +* Many bug fixes and minor tweaks. + +Other Contributors: Darin Adler, Jakub Jelinek, James Antill, Andrew Taylor, + Ben Gertzfield, Elliot Lee, Manish Singh, Abel Cheung, Laszlo Peter, + Sven Neumann, George Lebl, Raja Harinath, Sebastian Wilhelmi, + Jacob Berkman + + +Overview of Changes in GLib 1.3.9: +================================== + +* Fixes for comparison of threads [Sebastian Wilhelmi] +* Use vasprintf() when possible for g_strdup_printf [Matthias Clasen] +* Win32 fixes [Tor Lillqvist, Hans Breuer] +* Add a len argument to g_ascii_strup/strdown +* Bug, portability fixes, cleanups. + +Other Contributors: Darin Adler, Katsuhiro Okuno, Joshua N. Pritikin + + +Overview of Changes in GLib 1.3.8: +================================== + +* Documentation updates [Owen] +* Made GType interfaces overridable in derived types +* Many win32 fixes [Tor Lillqvist] +* Miscellaneous cleanups and fixes + +Other contributors: + Darin Adler, Matthias Clasen, Ron Steinke, Hans Breuer, Alex Larsson + + +Overview of Changes in GLib 1.3.7: +================================== + +* Integrate GClosure support into the main loop [Owen Taylor] +* More GSignal convenience functions (macros) [Sven Neumann, Tim Janik] +* Introduced weak references for GObject [James Henstridge, Sven, Tim] +* Minor hash table optimizations +* Main loop and threading improvements [Sebastian Wilhelmi] +* Added g_ascii_* functions to be used for locale insensitive UTF-8 + compliant code instead of old string functions [Darin Adler, Alex Larsson] +* Add functions for Unicode case-conversion, normalization, and + collation [Owen]* GString improvements [Owen] +* Reworked the GIOChannel code [Hidetoshi Tajima, Ron Steinke] +* Removed glib-config-2.0 in favour of pkgconfig [Sebastian] +* Make code 64bit clean [Mark Murnane] +* More G_CONST_RETURN fixes +* Many improvements to the win32 code [Tor Lillqvist, Hans Breuer] +* Miscellaneous bug and API fixes + +Other contributors: + Michael Natterer, Christopher James Lahey, Padraig O'Briain, + Matthias Clasen, Josh Pritikin, Steve Baker, Cesar Rincon, Garry R. Osgood, + Michael Meeks, Laszlo Peter, Martin Baulig, Kjartan Maraas, Andrew Lanoix, + Peter Williams + + +Overview of Changes in GLib 1.3.6: +================================== + +* Threads have a "return value" from g_thread_join +* Removed ability to adjust thread stack size +* Prefix warnings with progname/PID by default, change toggle for this to + be an env variable G_MESSAGES_PREFIXED not a compile-time option +* GMarkup speedups +* GDate const, convenience fixups +* Include test cases that headers are compilable by C++ compiler +* Add ability to spawn processes with argv[0] != executable path. +* g_strstr_len, g_strrstr, g_strrstr_len +* Add length argument to g_utf8_strchr and g_utf8_strrchr. +* Misc bug fixes + + +Overview of Changes in GLib 1.3.5: +================================== + +* Added an installed glib-mkenums Perl program for parsing enumeration + declarations from header files. +* Mark some additional deprecated functions. +* Bug and Portability fixes + + +Overview of Changes in GLib 1.3.4: +================================== + +* Efficiency improvements for GThreadPool +* A few bug fixes +* Build fixes +* Documentation improvements + + +Overview of Changes in GLib 1.3.3: +================================== + +GLib: + +* More user_data support in various functions. +* Main loop API revamps to support per-thread main loops. +* Unicode handling improvements. +* Implemented debugging traps. +* G_CONST_RETURN specification all over the place. +* Various new small utility functions. +* Random number generator precision improvements. +* New configure option --disable-mem-pools. +* Many Win32 improvements. +* Added g_try_malloc() friends varinats. +* Many documentation improvements. +* Many threading improvements, support for dynamic allocation + of static mutexes. +* GHookLIst API cleanups. +* Improved format support of GDate parser. +* String function speed improvements with new g_stpcpy(). +* Hashtable API additions. +* New GPatternSpec for shell-style pattern matching (from GtkPatternSpec). +* Optimizations, cleanups, bug fixes. + +GObject: + +* Added many convenience functions. +* GClosure and GParamSpec use float/sink ref-counting scheme now. +* Reworked property change notification. +* Binary searchable array cleanups, so it's widely usable now. +* Added static content keeping for some GValue types. +* Support for statically scoped signal parameters. +* Extinguished property trailer args in set/get interface. +* Added support for abstract types. +* G_CONST_RETURN specification all over the place. +* Split parameter exchange functionality into value transforms + and parameter conversions. +* Added signal emission hooks and signal accumulators. +* Added interface prerequisites to support is_a (interface, object) + relations. +* Implemented GValueArray. +* New types, boxed: G_TYPE_VALUE, G_TYPE_CLOSURE, G_TYPE_GSTRING + GParamSpecs: G_TYPE_PARAM_PARAM, G_TYPE_PARAM_POINTER, G_TYPE_PARAM_CLOSURE, + G_TYPE_VALUE_ARRAY, G_TYPE_PARAM_UNICHAR, G_TYPE_PARAM_VALUE_ARRAY. +* Varrags value collection improvements. +* Implemented debugging traps. +* Made things thread-safe. +* Many documentation improvements. +* Many cleanups, optimizations and bug fixes. + + +Overview of Changes in GLib 1.3.2: +================================== + +GLib: + +* Win32 build improvements [Tor] +* Improvements to error reporting + (g_critical(), g_return_if_reached()) [Darin] +* Add g_strlcpy/g_strlcat [David Wheeler] +* New IO channel implementation for Win32 [Tor] +* Make g_array_free, g_string_free return pointer to memory requested + not to be freed. [Darin] +* Added GError based error reporting for thread functions. [Sebastian] +* Moved reference docs into GLib distribution. [Owen] +* Added g_convert() for doing convenient character set conversions based + on iconv. (GLib now requires libiconv or a native iconv.) [Havoc/Owen] +* Various Unicode handling additions (g_ucs4_to_utf8, g_utf8_validate(), + g_{locale,filename}_{to,from}_utf8) [Robert/Havoc/Owen] +* Portability fixes for threading. [Sebastian] +* Added convenient functions for launching new processes (g_spawn_*), + and shell quoting/unquoting functions. [Havoc] +* Split glib.h into many headers. [Sebastian] +* Added a simple callback-based parser for XML-like files (GMarkup). [Havoc] +* Fixed confusions between comparison functions that return <0, 0, >0 + and equaility functions that return FALSE,TRUE. [Sebastian] +* Added safe/portable temporary file manipulation functions. [Tor] +* autoconf improvements. [Raja] +* Many documentation improvements. +* Bug fixes. + +GObject: + +* Added boxed and pointer types. [Tim/Jonathan] +* Added callback abstraction (GClosure) [Tim] +* Added signal system (GSignal) [Tim] +* Make GTypePlugin an interface [Tim] +* Added GTypeModule - a simple GTypePlugin instantiation [Owen] +* Bug fixes. + + +What's new in GLib 1.3.1: +========================= + +* New GObject library added including object system based on + the GTK+ object system. +* Functions for getting the properties of Unicode characters, + computing the canonical decomposition and ordering combining + characters aand manipulating UTF-8 string manipulation based + on libunicode. +* GString now properly handles embedded nuls. +* Multiple fixes from the 1.2.x branch. +* Upgrade to libtool 1.3.3 +* Full thread support (thread creation and destruction). +* BeOS port, BeOS dynamic modules. +* Many improvements to the Windows ports. +* Improvements to the OS/2 port, OS/2 module support. +* Double ended queue implementation. +* GLib macros for printf() formatting, e.g. G_GULONG_FORMAT = "lu" +* New configure option --enable-msg-prefix to prefix messages, warnings + et ceteri with the program name and the process id. +* New thread-safe random number generator Mersenne Twister. +* g_strcompress() added, g_strescape() had a slight API change, and + more tightly defined semantics. +* the g_string(x) macro has been removed, #x may be used instead. + +
diff --git a/NEWS.pre-1-3 b/NEWS.pre-1-3 new file mode 100644 index 0000000..1aa4f4e --- /dev/null +++ b/NEWS.pre-1-3
@@ -0,0 +1,211 @@ +Overview of Changes in GLib 1.2.1: + +* g_realloc() fix for SunOS (please report further problems). +* Continued the never ending fix vendetta regarding getpwuid(), + this time AIX has been the culprit. +* Upgrade to libtool 1.2f +* Miscellaneous other buglets fixed. + +What's new in GLib 1.2.0 (since GLib 1.0.x): + +* GLib is distributed seperatedly from Gtk+ +* Win32 Portability +* Threading support +* GModule mechanism (implemented in an extra library) which wraps dynamic + object code loading facilities in a portable manner +* GIOChannel structure to encapsulate the IPC mechanism +* GQuarks and datasets +* GRelations for n-way mapping of certain data +* An n-way tree implementation +* GDate functionality for calendar date manipulations +* GAllocator type and associated functions +* Added generic callback maintenance functions (ghook) +* Generic functions for TAB completions +* Endian defines (G_*_ENDIAN) +* g_log() mechanism for logging of messages at different log levels +* Generic main-loop mechanism +* New glib-config helper script +* Many more API extensions + +Overview of Changes in GLib 1.1.16: + +* Allocate smaller pools of memory for glists, gslists, gnodes +* Bug Fixes + +Overview of Changes in GLib 1.1.15: + +* HPUX 11 thread system detection should now work +* Release the main loop lock around calls to prepare() and + check() so it is not held over user code +* A few Win32 fixups + +Overview of Changes in GLib 1.1.14: + +* Check for dlsym() in system libraries and -dl +* FreeBSD portability fixes +* Random bug fixes and autoconf/automake changes + +Overview of Changes in GLib 1.1.13: + +* Removed alloca() based function and macro variants again. +* Improved thread related configure tests. +* GSource destruction fixups. +* Fixed up idle function removal based on user_data pointer. +* Advanced Win32 portability. +* Enforced GSource's check(), prepare() and dispatch() constrains, + loop recursions may only happen from dispatch(), and check() as well + as prepare() are called while the main_loop lock is being held. +* GLib development now requires GNU autoconf 2.13, GNU automake 1.4 + and GNU libtool 1.2d. +* Lots of random portability and bug fixes. + +Overview of Changes in GLib 1.1.12: + +* Added alloca functions/macros: g_strdup_a, g_strconcat3_a, g_alloca, + g_new_a, g_new0_a +* New tests structure. Type 'make check' on your system to run them. +* Avoid unnecessary extra hook referencing in g_hook_list_marshal + +Overview of Changes in GLib 1.1.11: + +* provide defaults for POLL sysdefs +* g_main_is_running: new function to check whether a main loop has been quitted +* a few other enhancement/fixes + +Overview of Changes in GLib 1.1.9: + +* Check for pthread_attr_init in all cases, Digital Unix 4 requires this +* For G_LOCK_DECLARE_*, if !G_THREADS_ENABLED, eat trailing semicolon better +* Changed g_main_poll_(add|remove) to g_main_(add|remove)_poll + +Overview of Changes in GLib 1.1.8: + +* Added threading support + - The ability to specify a set of functions to be used for + locking at runtime. + - Default implementations of locking functions for pthreads, + Solaris threads, and (experimentally) NSPR. + - All static variables should now properly locked. + - Enhancements to the generic main-loop mechanism to be thread-safe. + (It is used for the main-loop in GTK+ as of GTK+-1.1.8) +* Portability fixes. + +Overview of Changes in GLib 1.1.7: + +* Removed multiple define from glibconfig.h + +Overview of Changes in GLib 1.1.6: + +* New GDate functionality for calendar date manipulations (g_date_*) +* New GAllocator type and associated functions +* New functions g_slist_copy and g_list_copy to duplicate a list with all + its data pointers. +* New function g_array_insert_vals and new macro g_array_insert_val to + insert elements at an arbitrary index +* GAllocators used for glist, gslist, gnode node allocations +* Incremental freezing in ghash +* New function g_hook_list_marshal_check to eventually destroy hooks after + they got marshalled +* Revised GIOChannel to provide generic virtual-function based interface +* Added generic main-loop abstraction +* Removed GListAllocator type and its g_*_allocator_*() function variants +* Bug fixes + +Overview of Changes in GLib 1.1.5: + +* Win32 portability +* GIOChannel structure to encapsulate the IPC mechanism +* Reimplemented endian stuff, using inline asm for x86 +* New functions: + - g_strescape: escapes backslashes + - g_path_is_absolute and g_path_skip_root + - g_getenv: expands environment variables that contain references + to other environment variables + - g_scanner_sync_file_offset: rewind the filedescriptor to the current + buffer position and blow the file read ahead buffer + - g_array_remove_index: remove an entry, preserving the order + - g_array_remove_index_fast: remove an entry, order might be distorted + - g_ptr_array_remove: remove an entry, preserving the order + - g_ptr_array_remove_fast: remove an entry, order might be distorted + - g_byte_array_remove_index: wrapper for g_array_remove_index + - g_byte_array_remove_index_fast: wrapper for g_array_remove_index_fast + - g_strncasecmp: modeled closely after g_strcasecmp + - g_list_sort, g_slist_sort: to merge sort GLists and GSLists +* New macros: + - G_DIR_SEPARATOR, G_DIR_SEPARATOR_S: platform-dependant file name + syntax elements + - G_SEARCHPATH_SEPARATOR, G_SEARCHPATH_SEPARATOR_S: platform-dependant + search path syntax conventions + - G_STRUCT_OFFSET, G_STRUCT_MEMBER_P, G_STRUCT_MEMBER: for handling + structure fields through their offsets +* Removed G_ENUM, G_FLAGS, G_NV, and G_SV macros +* Bug fixes + +Overview of Changes in GLib 1.1.4: + +* Added generic callback maintenance functions (ghook) +* New endian defines (G_*_ENDIAN) +* New string join/split/free routines +* Fixes + +Overview of Changes in GLib 1.1.3: + +* New GModule mechanism (implemented in an extra library) which wraps dynamic + object code loading facilities in a portable manner. +* glib-config features extra "glib" (old behaviour remains) and "gmodule" + (add libgmodule.so to the --libs output) arguments now. this can also + be specified as fourth argument to the AM_PATH_GLIB() macro. +* Overhaul of the `inline' autoconfiguration stuff, so inlining should be + sufficiently supported on all systems that allow inlining now. +* New g_log() mechanism for logging of messages at different log levels, + associated with certain log domains (define -DG_LOG_DOMAIN for your library). +* New inline functions for bit masks tests. +* GNode macros (and functions) now return the newly allocated node. +* New macro G_VA_COPY() to work around va_list copying oddities on some + platforms. the non-static g_vsprintf() function vanished in favour of + a publically exported g_strdup_vprintf(). + People that used the former g_vsprintf() would definitely want to read the + associated ChangeLog entries (grep for printf). +* New utility functions: + g_strndup(), g_on_error_query(), g_on_error_stack_trace(), g_strdup_printf(), + g_strdup_vprintf(), g_printf_string_upper_bound(), g_spaced_primes_closest(), + g_strnfill(), g_memdup(). +* Overhaul of the array implementations, this contains some source incompatible + changes. Again, the ChangeLog is much more informative (grep for garray.c). +* The internals of the g_dataset mechanism are now exported through the + new g_datalist_* API (this is also the underlying implementation for the + keyed data of GtkObjects). +* New function g_atexit(), use of the ATEXIT() macro is discouraged. +* Better configure checks for ansi compliance. +* Libtool update to version 1.2b. +* Lotsa bug fixes and cleanups as always ;) + +Overview of Changes in GLib 1.1.2: + +* Fixed packaging mistake which occured in 1.1.1 +* fix 64-bitness in g_prints in glibtest + +What is new in GLib 1.1.1: + +* An n-way tree implementation is provided now, based on the GNode structure. +* Bugfix for pointer arrays. + +What is new in GLib 1.1.0: + +* GLib is distributed seperatedly from Gtk+ now and uses a sophisticated + shared library versioning scheme to deal with interface and binary + incompatibilities. +* There is a glib-config helper script installed now. +* Fixups all over the place. +* gboolean is now a gint, not a gchar anymore. +* API extensions for GList and GSList. +* New g_str*() functions for simple string handling. +* GScanner extensions for scope, warning and error handling. +* Minor performance improvements for GMemChunks. +* Implementations of GQuarks and datasets (similar to GtkObjects data + mechansim, but works for generic memory locations). +* More convenience macros for GNU C function arguments. +* Const correction all over the place, including a new pointer type + gconstpointer. +* Generic functions for TAB completions. +* GRelations for n-way mapping of certain data.
diff --git a/README b/README new file mode 100644 index 0000000..96dc92f --- /dev/null +++ b/README
@@ -0,0 +1 @@ +See README.md
diff --git a/README.md b/README.md new file mode 100644 index 0000000..4bc4113 --- /dev/null +++ b/README.md
@@ -0,0 +1,333 @@ +# GLib + +GLib is the low-level core library that forms the basis for projects such +as GTK and GNOME. It provides data structure handling for C, portability +wrappers, and interfaces for such runtime functionality as an event loop, +threads, dynamic loading, and an object system. + +The official download locations are: + <https://download.gnome.org/sources/glib> + +The official web site is: + <https://www.gtk.org/> + +## Installation + +See the file '[INSTALL.in](INSTALL.in)' + +## How to report bugs + +Bugs should be reported to the GNOME issue tracking system. +(<https://gitlab.gnome.org/GNOME/glib/issues/new>). You will need +to create an account for yourself. + +In the bug report please include: + +* Information about your system. For instance: + * What operating system and version + * For Linux, what version of the C library + * And anything else you think is relevant. +* How to reproduce the bug. + * If you can reproduce it with one of the test programs that are built + in the tests/ subdirectory, that will be most convenient. Otherwise, + please include a short test program that exhibits the behavior. + As a last resort, you can also provide a pointer to a larger piece + of software that can be downloaded. +* If the bug was a crash, the exact text that was printed out + when the crash occurred. +* Further information such as stack traces may be useful, but + is not necessary. + +## Patches + +Patches should also be submitted as merge requests to gitlab.gnome.org. If the +patch fixes an existing issue, please refer to the issue in your commit message +with the following notation (for issue 123): +Closes: #123 + +Otherwise, create a new merge request that introduces the change, filing a +separate issue is not required. + +## Notes + +### Notes about GLib 2.48 + +* The system copy of PCRE is now used by default to implement GRegex. + Configure with --with-pcre=internal if a system PCRE version + is unavailable or undesired. + +### Notes about GLib 2.46 + +* GTask no longer imposes a fixed limit on the number of tasks that + can be run_in_thread() simultaneously, since doing this inevitably + results in deadlocks in some use cases. Instead, it now has a base + number of threads that can be used "for free", but will gradually + add more threads to the pool if too much time passes without any + tasks completing. + + The exact behavior may continue to change in the future, and it's + possible that some future version of GLib may not do any + rate-limiting at all. As a result, you should no longer assume that + GTask will rate-limit tasks itself (or, by extension, that calls to + certain async gio methods will automatically be rate-limited for + you). If you have a very large number of tasks to run, and don't + want them to all run at once, you should rate-limit them yourself. + +### Notes about GLib 2.40 + +* g_test_run() no longer runs tests in exactly the order they are + registered; instead, it groups them according to test suites (ie, + path components) like the documentation always claimed it did. In + some cases, this can result in a sub-optimal ordering of tests, + relative to the old behavior. The fix is to change the test paths to + properly group together the tests that should run together. (eg, if + you want to run test_foo_simple(), test_bar_simple(), and + test_foo_using_bar() in that order, they should have test paths like + "/simple/foo", "/simple/bar", "/complex/foo-using-bar", not + "/foo/simple", "/bar/simple", "/foo/using-bar" (which would result + in test_foo_using_bar() running before test_bar_simple()). + + (The behavior actually changed in GLib 2.36, but it was not + documented at the time, since we didn't realize it mattered.) + +### Notes about GLib 2.36 + +* It is no longer necessary to call g_type_init(). If you are + loading GLib as a dynamic module, you should be careful to avoid + unloading it, then subsequently loading it again. This never + really worked before, but it is now explicitly undefined behavior. + Note that if g_type_init() was the only explicit use of a GObject + API and you are using linker flags such as --no-add-needed, then + you may have to artificially use some GObject call to keep the + linker from optimizing away -lgobject. We recommend to use + g_type_ensure (G_TYPE_OBJECT) for this purpose. + +* This release contains an incompatible change to the g_get_home_dir() + function. Previously, this function would effectively ignore the HOME + environment variable and always return the value from /etc/password. + As of this version, the HOME variable is used if it is set and the + value from /etc/passwd is only used as a fallback. + +* The 'flowinfo' and 'scope_id' fields of GInetSocketAddress + (introduced in GLib 2.32) have been fixed to be in host byte order + rather than network byte order. This is an incompatible change, but + the previous behavior was clearly broken, so it seems unlikely that + anyone was using it. + +### Notes about GLib 2.34 + +* GIO now looks for thumbnails in XDG_CACHE_HOME, following a + recent alignment of the thumbnail spec with the basedir spec. + +* The default values for GThreadPools max_unused_threads and + max_idle_time settings have been changed to 2 and 15*1000, + respectively. + +### Notes about GLib 2.32 + +* It is no longer necessary to use g_thread_init() or to link against + libgthread. libglib is now always thread-enabled. Custom thread + system implementations are no longer supported (including errorcheck + mutexes). + +* The thread and synchronisation APIs have been updated. + GMutex and GCond can be statically allocated without explicit + initialisation, as can new types GRWLock and GRecMutex. The + GStatic_______ variants of these types have been deprecated. GPrivate + can also be statically allocated and has a nicer API (deprecating + GStaticPrivate). Finally, g_thread_create() has been replaced with a + substantially simplified g_thread_new(). + +* The g_once_init_enter()/_leave() functions have been replaced with + macros that allow for a pointer to any gsize-sized object, not just a + gsize*. The assertions to ensure that a pointer to a correctly-sized + object is being used will not work with generic pointers (ie: (void*) + and (gpointer) casts) which would have worked with the old version. + +* It is now mandatory to include glib.h instead of individual headers. + +* The -uninstalled variants of the pkg-config files have been dropped. + +* For a long time, gobject-2.0.pc mistakenly declared a public + dependency on gthread-2.0.pc (when the dependency should have been + private). This means that programs got away with calling + g_thread_init() without explicitly listing gthread-2.0.pc among their + dependencies. + + gthread has now been removed as a gobject dependency, which will cause + such programs to break. + + The fix for this problem is either to declare an explicit dependency + on gthread-2.0.pc (if you care about compatibility with older GLib + versions) or to stop calling g_thread_init(). + +* g_debug() output is no longer enabled by default. It can be enabled + on a per-domain basis with the G_MESSAGES_DEBUG environment variable + like + G_MESSAGES_DEBUG=domain1,domain2 + or + G_MESSAGES_DEBUG=all + +### Notes about GLib 2.30 + +* GObject includes a generic marshaller, g_cclosure_marshal_generic. + To use it, simply specify NULL as the marshaller in g_signal_new(). + The generic marshaller is implemented with libffi, and consequently + GObject depends on libffi now. + +### Notes about GLib 2.28 + +* The GApplication API has changed compared to the version that was + included in the 2.25 development snapshots. Existing users will need + adjustments. + +### Notes about GLib 2.26 + +* Nothing noteworthy. + +### Notes about GLib 2.24 + +* It is now allowed to call g_thread_init(NULL) multiple times, and + to call glib functions before g_thread_init(NULL) is called + (although the later is mainly a change in docs as this worked before + too). See the GThread reference documentation for the details. + +* GObject now links to GThread and threads are enabled automatically + when g_type_init() is called. + +* GObject no longer allows to call g_object_set() on construct-only properties + while an object is being initialized. If this behavior is needed, setting a + custom constructor that just chains up will re-enable this functionality. + +* GMappedFile on an empty file now returns NULL for the contents instead of + returning an empty string. The documentation specifically states that code + may not rely on nul-termination here so any breakage caused by this change + is a bug in application code. + +### Notes about GLib 2.22 + +* Repeated calls to g_simple_async_result_set_op_res_gpointer used + to leak the data. This has been fixed to always call the provided + destroy notify. + +### Notes about GLib 2.20 + +* The functions for launching applications (e.g. g_app_info_launch() + + friends) now passes a FUSE file:// URI if possible (requires gvfs + with the FUSE daemon to be running and operational). With gvfs 2.26, + FUSE file:// URIs will be mapped back to gio URIs in the GFile + constructors. The intent of this change is to better integrate + POSIX-only applications, see bug #528670 for the rationale. The + only user-visible change is when an application needs to examine an + URI passed to it (e.g. as a positional parameter). Instead of + looking at the given URI, the application will now need to look at + the result of g_file_get_uri() after having constructed a GFile + object with the given URI. + +### Notes about GLib 2.18 + +* The recommended way of using GLib has always been to only include the + toplevel headers glib.h, glib-object.h and gio.h. GLib enforces this by + generating an error when individual headers are directly included. + To help with the transition, the enforcement is not turned on by + default for GLib headers (it is turned on for GObject and GIO). + To turn it on, define the preprocessor symbol G_DISABLE_SINGLE_INCLUDES. + +### Notes about GLib 2.16 + +* GLib now includes GIO, which adds optional dependencies against libattr + and libselinux for extended attribute and SELinux support. Use + --disable-xattr and --disable-selinux to build without these. + +### Notes about GLib 2.10 + +* The functions g_snprintf() and g_vsnprintf() have been removed from + the gprintf.h header, since they are already declared in glib.h. This + doesn't break documented use of gprintf.h, but people have been known + to include gprintf.h without including glib.h. + +* The Unicode support has been updated to Unicode 4.1. This adds several + new members to the GUnicodeBreakType enumeration. + +* The support for Solaris threads has been retired. Solaris has provided + POSIX threads for long enough now to have them available on every + Solaris platform. + +* 'make check' has been changed to validate translations by calling + msgfmt with the -c option. As a result, it may fail on systems with + older gettext implementations (GNU gettext < 0.14.1, or Solaris gettext). + 'make check' will also fail on systems where the C compiler does not + support ELF visibility attributes. + +* The GMemChunk API has been deprecated in favour of a new 'slice + allocator'. See the g_slice documentation for more details. + +* A new type, GInitiallyUnowned, has been introduced, which is + intended to serve as a common implementation of the 'floating reference' + concept that is e.g. used by GtkObject. Note that changing the + inheritance hierarchy of a type can cause problems for language + bindings and other code which needs to work closely with the type + system. Therefore, switching to GInitiallyUnowned should be done + carefully. g_object_compat_control() has been added to GLib 2.8.5 + to help with the transition. + +### Notes about GLib 2.6.0 + +* GLib 2.6 introduces the concept of 'GLib filename encoding', which is the + on-disk encoding on Unix, but UTF-8 on Windows. All GLib functions + returning or accepting pathnames have been changed to expect + filenames in this encoding, and the common POSIX functions dealing + with pathnames have been wrapped. These wrappers are declared in the + header <glib/gstdio.h> which must be included explicitly; it is not + included through <glib.h>. + + On current (NT-based) Windows versions, where the on-disk file names + are Unicode, these wrappers use the wide-character API in the C + library. Thus applications can handle file names containing any + Unicode characters through GLib's own API and its POSIX wrappers, + not just file names restricted to characters in the system codepage. + + To keep binary compatibility with applications compiled against + older versions of GLib, the Windows DLL still provides entry points + with the old semantics using the old names, and applications + compiled against GLib 2.6 will actually use new names for the + functions. This is transparent to the programmer. + + When compiling against GLib 2.6, applications intended to be + portable to Windows must take the UTF-8 file name encoding into + consideration, and use the gstdio wrappers to access files whose + names have been constructed from strings returned from GLib. + +* Likewise, g_get_user_name() and g_get_real_name() have been changed + to return UTF-8 on Windows, while keeping the old semantics for + applications compiled against older versions of GLib. + +* The GLib uses an '_' prefix to indicate private symbols that + must not be used by applications. On some platforms, symbols beginning + with prefixes such as _g will be exported from the library, on others not. + In no case can applications use these private symbols. In addition to that, + GLib+ 2.6 makes several symbols private which were not in any installed + header files and were never intended to be exported. + +* To reduce code size and improve efficiency, GLib, when compiled + with the GNU toolchain, has separate internal and external entry + points for exported functions. The internal names, which begin with + IA__, may be seen when debugging a GLib program. + +* On Windows, GLib no longer opens a console window when printing + warning messages if stdout or stderr are invalid, as they are in + "Windows subsystem" (GUI) applications. Simply redirect stdout or + stderr if you need to see them. + +* The child watch functionality tends to reveal a bug in many + thread implementations (in particular the older LinuxThreads + implementation on Linux) where it's not possible to call waitpid() + for a child created in a different thread. For this reason, for + maximum portability, you should structure your code to fork all + child processes that you want to wait for from the main thread. + +* A problem was recently discovered with g_signal_connect_object(); + it doesn't actually disconnect the signal handler once the object being + connected to dies, just disables it. See the API docs for the function + for further details and the correct workaround that will continue to + work with future versions of GLib.
diff --git a/README.rationale b/README.rationale new file mode 100644 index 0000000..85a3dfd --- /dev/null +++ b/README.rationale
@@ -0,0 +1,10 @@ +This file documents various major decisions which affect GLib development, +giving a brief rationale of each decision, plus a link to further discussion. + + + * Compiler attributes: https://bugzilla.gnome.org/show_bug.cgi?id=113075#c46 + + GLib uses GIR annotations instead of compiler attributes. They are tidier, + already supported by GLib and GNOME tools, and accomplish the same task as + compiler attributes. GLib does not provide macros for attributes like + nonnull because it would not use them.
diff --git a/README.win32 b/README.win32 new file mode 100644 index 0000000..2a31029 --- /dev/null +++ b/README.win32
@@ -0,0 +1 @@ +See README.win32.md
diff --git a/README.win32.md b/README.win32.md new file mode 100644 index 0000000..2925d3d --- /dev/null +++ b/README.win32.md
@@ -0,0 +1,182 @@ +Chun-wei Fan `<fanc999@yahoo.com.tw>` +Philip Withnall `<withnall@endlessm.com>` +Nirbheek Chauhan `<nirbheek@centricular.com>` + +This document was last updated in 2019. You're reading this in the future, and +lots of information might be misleading or outdated in your age. You have been +warned. + +# General + +For prebuilt binaries (DLLs and EXEs) and developer packages (headers, +import libraries) of GLib, Pango, GTK+ etc for Windows, go to +https://www.gtk.org/download/windows.php . They are for "native" +Windows meaning they use the Win32 API and Microsoft C runtime library +only. No POSIX (Unix) emulation layer like Cygwin is involved. + +To build GLib on Win32, you can use either GCC ("MinGW") or the Microsoft +Visual Studio toolchain. For the latter, Visual Studio 2015 and later are +recommended. For older Visual Studio versions, see below. + +You can also cross-compile GLib for Windows from Linux using the +cross-compiling mingw packages for your distro. + +Note that to just *use* GLib on Windows, there is no need to build it +yourself. + +On Windows setting up a correct build environment is very similar to typing +`meson; ninja` like on Linux. + +The following preprocessor macros are to be used for conditional +compilation related to Win32 in GLib-using code: + +- `G_OS_WIN32` is defined when compiling for native Win32, without + any POSIX emulation, other than to the extent provided by the + bundled Microsoft C library. + +- `G_WITH_CYGWIN` is defined if compiling for the Cygwin + environment. Note that `G_OS_WIN32` is *not* defined in that case, as + Cygwin is supposed to behave like Unix. `G_OS_UNIX` *is* defined by a GLib + for Cygwin. + +- `G_PLATFORM_WIN32` is defined when either `G_OS_WIN32` or `G_WITH_CYGWIN` + is defined. + +These macros are defined in `glibconfig.h`, and are thus available in +all source files that include `<glib.h>`. + +Additionally, there are the compiler-specific macros: +- `__GNUC__` is defined when using GCC or Clang +- `__clang__` is defined when using Clang or Clang-CL +- `_MSC_VER` is defined when using MSVC or Clang-CL + +`G_OS_WIN32` implies using the Microsoft C runtime, which used to be +`msvcrt.dll` and is now the [Universal CRT](https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=vs-2015) +when building with Visual Studio. When using the MinGW-GCC toolchain, the CRT +in use depends on the settings used while the toolchain was built. We highly +recommend [using the Universal CRT when building with +MinGW](https://mingwpy.github.io/ucrt.html) too. + +GLib is not actively tested with the static versions of the UCRT, but if you +need to use those, patches are welcome. + +# Building software that use GLib or GTK+ + +Building software that just *uses* GLib or GTK+ also require to have +the right compiler set up the right way. If you intend to use MinGW-GCC, +follow the relevant instructions below in that case, too. + +You should link to GLib using the `-mms-bitfields` GCC flag. This flag means +that the struct layout rules are identical to those used by MSVC. This is +essential if the same DLLs are to be usable both from gcc- and MSVC-compiled +code. + +## Cross-CRT issues + +You should take care that the DLLs that your code links to are using the same +C runtime library. Not doing so can and likely will lead to panics and crashes +**unless** you're very careful while passing objects allocated by a library +linked with one CRT to a library linked to another CRT, or (more commonly) not +doing that at all. + +If you *do* pass CRT objects across CRT boundaries, do not file any issues +about whatever happens next. + +To give an example, opening a `FILE` handle created by one CRT cannot be +understood by any other CRT, and will lead to an access violation. You also +cannot allocate memory in one CRT and free it using another. + +There are [many other cases where you must not allow objects to cross CRT boundaries](https://docs.microsoft.com/en-us/cpp/c-runtime-library/potential-errors-passing-crt-objects-across-dll-boundaries?view=vs-2019), +but in theory if you're **very very** careful, you can make things work. Again, +please do not come to us for help if you choose to do this. + +# Building GLib + +You can build GLib with MinGW-GCC, MSVC, or (experimentally) with Clang-CL. + +For all compilers, you will need the following: + +- Install Python 3.6.x or newer, either 32-bit or 64-bit. We recommend enabling + the option to add it to your `PATH`. +- [Install Meson](https://mesonbuild.com/Getting-meson.html) +- Install the [Ninja build tool](https://github.com/ninja-build/ninja/releases), which can also be + installed with `pip3`. You can skip this step if you want to generate Visual + Studio project files. +- [git for Windows](https://gitforwindows.org/) is required, since Meson makes + use of git to download dependencies using subprojects. + +## Building with MinGW-GCC + +Open your MSYS or [MSYS2](https://www.msys2.org/) shell where you have the +MinGW-GCC toolchain installed, and build GLib [like any other Meson +project](https://mesonbuild.com/Quick-guide.html#compiling-a-meson-project). + +## Building with Visual Studio 2015 or newer + +Meson is now the only supported method of building GLib using Visual Studio. + +To do a build using Meson, do the following: + +- Open a Visual Studio (or SDK) command prompt that matches the Visual Studio + version and build platform (Win32/x86, x64, etc.) that will be used in all + the following steps. + +- Create an empty directory/folder for the build inside your GLib sources + directory, say, `_builddir`, and `cd` into it. + +- Set up the build using Meson: + +```cmd +> meson .. --buildtype=<release|debug|debugoptimized> --prefix=<path> [--backend=vs] +``` + + Please see [the Meson docs](https://mesonbuild.com/Builtin-options.html#core-options) + for an explanation for `--buildtype`. + + The path passed for `--prefix` need not to be on the same drive as where the + build is carried out, but it is recommended to use forward slashes for this + path. The `--backend=vs` option can be used if the Visual Studio project + generator is preferred over using Ninja. + +- Build, test and install the build: + Run `ninja` to build, `meson test` to test and `meson install` to install the + build. If you used `--backend=vs`, instead of running `ninja`, you need to + use `msbuild` or you can open the generated solution in Visual Studio. + +## Building with old versions of Visual Studio + +The steps are the same as above, with the following notes about issues that you might face. + +### C4819 build errors + +If you are building GLib-based libraries or applications, or GLib itself +and you see a `C4819` error (or warning, before `C4819` is treated as an error +in `msvc_recommended_pragmas.h`), please be advised that this error/warning should +not be disregarded, as this likely means portions of the build are not being +done correctly, as this is an issue of Visual Studio running on CJK (East Asian) +locales. This is an issue that also affects builds of other projects, such as +QT, Firefox, LibreOffice/OpenOffice, Pango and GTK, along with many other projects. + +To overcome this problem, please set your system's locale setting for non-Unicode to +English (United States), reboot, and restart the build, and the code should build +normally. + +### Visual Studio 2008 hacks + +- You need to run the following lines from your build directory, to embed the + manifests that are generated during the build, assuming the built binaries + are installed to `$(PREFIX)`, after a successful build/installation: + +```cmd +> for /r %f in (*.dll.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f $(PREFIX)\bin\%~nf;2 +> for /r %f in (*.exe.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f $(PREFIX)\bin\%~nf;1 +``` + + +- If building for amd64/x86_64/x64, sometimes the compilation of sources may seem to hang, which + is caused by an optimization issue in the 2008 x64 compiler. You need to use Task Manager to + remove all running instances of `cl.exe`, which will cause the build process to terminate. Update + the build flags of the sources that hang on compilation by changing its `"/O2"` flag to `"/O1"` + in `build.ninja`, and retry the build, where things should continue to build normally. At the + time of writing, this is needed for compiling `glib/gtestutils.c`, `gio/gsettings.c`, + `gio/gsettingsschema.c` and `gio/tests/gsubprocess-testprog.c`
diff --git a/check-abis.sh b/check-abis.sh new file mode 100755 index 0000000..a18103b --- /dev/null +++ b/check-abis.sh
@@ -0,0 +1,23 @@ +#!/bin/sh -e + +list_leaked_symbols () { + nm -D "$1" | grep ' T ' | cut -f 3 -d ' ' | egrep -v "$2" +} + +check_symbols () { + if [ "`list_leaked_symbols "$1" "$2" | wc -l`" -ne 0 ]; then + echo File "$1" possibly leaking symbols: + list_leaked_symbols "$1" "$2" + exit 1 + fi +} + +allowed="^_init$|^_fini$|^_ftext$|^g_" +allowed_in_libglib="${allowed}|^glib__private__$|^glib_gettext$|^glib_pgettext$|^glib_check_version$" +allowed_in_libgthread='^_init$|^_fini$|^_ftext$|^g_thread_init$|^g_thread_init_with_errorcheck_mutexes$' + +check_symbols glib/.libs/libglib-2.0.so "$allowed_in_libglib" +check_symbols gthread/.libs/libgthread-2.0.so "$allowed_in_libgthread" +for file in gmodule/.libs/libgmodule-2.0.so gobject/.libs/libgobject-2.0.so gio/.libs/libgio-2.0.so; do + check_symbols "$file" "$allowed" +done
diff --git a/clang-format-diff.py b/clang-format-diff.py new file mode 100755 index 0000000..3fb776c --- /dev/null +++ b/clang-format-diff.py
@@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +# +# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== # +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ===---------------------------------------------------------------------=== # + +""" +This script reads input from a unified diff and reformats all the changed +lines. This is useful to reformat all the lines touched by a specific patch. +Example usage for git/svn users: + + git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i + svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i + +""" +from __future__ import absolute_import, division, print_function + +import argparse +import difflib +import re +import subprocess +import sys + +if sys.version_info.major >= 3: + from io import StringIO +else: + from io import BytesIO as StringIO + + +def main(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('-i', action='store_true', default=False, + help='apply edits to files instead of displaying a ' + 'diff') + parser.add_argument('-p', metavar='NUM', default=0, + help='strip the smallest prefix containing P slashes') + parser.add_argument('-regex', metavar='PATTERN', default=None, + help='custom pattern selecting file paths to reformat ' + '(case sensitive, overrides -iregex)') + parser.add_argument('-iregex', metavar='PATTERN', + default=r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc' + r'|js|ts|proto|protodevel|java|cs)', + help='custom pattern selecting file paths to reformat ' + '(case insensitive, overridden by -regex)') + parser.add_argument('-sort-includes', action='store_true', default=False, + help='let clang-format sort include blocks') + parser.add_argument('-v', '--verbose', action='store_true', + help='be more verbose, ineffective without -i') + parser.add_argument('-style', + help='formatting style to apply (LLVM, Google, ' + 'Chromium, Mozilla, WebKit)') + parser.add_argument('-binary', default='clang-format', + help='location of binary to use for clang-format') + args = parser.parse_args() + + # Extract changed lines for each file. + filename = None + lines_by_file = {} + for line in sys.stdin: + match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line) + if match: + filename = match.group(2) + if filename is None: + continue + + if args.regex is not None: + if not re.match('^%s$' % args.regex, filename): + continue + else: + if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE): + continue + + match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line) + if match: + start_line = int(match.group(1)) + line_count = 1 + if match.group(3): + line_count = int(match.group(3)) + if line_count == 0: + continue + end_line = start_line + line_count - 1 + lines_by_file.setdefault(filename, []).extend( + ['-lines', str(start_line) + ':' + str(end_line)]) + + # Reformat files containing changes in place. + # We need to count amount of bytes generated in the output of + # clang-format-diff. If clang-format-diff doesn't generate any bytes it + # means there is nothing to format. + format_line_counter = 0 + for filename, lines in lines_by_file.items(): + if args.i and args.verbose: + print('Formatting {}'.format(filename)) + command = [args.binary, filename] + if args.i: + command.append('-i') + if args.sort_includes: + command.append('-sort-includes') + command.extend(lines) + if args.style: + command.extend(['-style', args.style]) + p = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=None, + stdin=subprocess.PIPE, + universal_newlines=True) + stdout, _ = p.communicate() + if p.returncode != 0: + sys.exit(p.returncode) + + if not args.i: + with open(filename) as f: + code = f.readlines() + formatted_code = StringIO(stdout).readlines() + diff = difflib.unified_diff(code, formatted_code, + filename, filename, + '(before formatting)', + '(after formatting)') + diff_string = ''.join(diff) + if diff_string: + format_line_counter += sys.stdout.write(diff_string) + + if format_line_counter > 0: + sys.exit(1) + + +if __name__ == '__main__': + main()
diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS new file mode 100644 index 0000000..e1d6efe --- /dev/null +++ b/docs/CODEOWNERS
@@ -0,0 +1,83 @@ +# These are the people responsible for subsystems in GLib; if you're opening +# a merge request for files listed here, please add the following people to +# the list of reviewers + +# The syntax of this file is defined by GitLab: +# https://docs.gitlab.com/ee/user/project/code_owners.html +# Which, in turn, is similar to the .gitignore and .gitattributes files: +# +# - comments start with `#` +# - the first column contains paths and globs +# - the second column contains GitLab user names or email addresses, +# separated by spaces +# +# The last matching glob (rather than the union of *all* matching globs) gives +# the owners of a piece of code. +# +# If you want to be responsible for code reviews in specific sections of +# the GLib code base, add yourself here. + +# Overall maintainers +* @pwithnall @ebassi + +# Build system +meson.build @xclaesse @nirbheek @pwithnall +meson_options.txt @xclaesse @nirbheek @pwithnall +subprojects/ @xclaesse @nirbheek @pwithnall + +# CI integration +.gitlab-ci* @pwithnall @xclaesse @creiter + +# macOS support +*osx* @jralls @pwithnall @sdroege +*.m @jralls @pwithnall @sdroege + +# Windows support +*win32* @lrn @creiter @fanc999 @pwithnall @sdroege @nirbheek + +# Windows support (MSVC-specific) +*msvc* @fanc999 @creiter @pwithnall @sdroege @nirbheek + +# Windows support (UWP-specific) +*uwp* @nirbheek + +# Android support +*android* @xclaesse @pwithnall @sdroege + +# BSD support +*bsd* @jmatthew @ajacoutot @lantw @pwithnall +*kqueue* @jmatthew @ajacoutot @lantw @pwithnall + +# flatpak portals +gio/*portal* @matthiasc @alexl @pwithnall + +# Networking +gio/g*{tcp,udp,tls,socket,resolver,proxy,network,inet,datagram}* @mcatanzaro @pgriffis @pwithnall @sdroege + +# D-Bus +gio/g*bus* @smcv @pwithnall + +# I/O +gio/g*{file,vfs,mount,drive,volume}* @oholy @alexl @pwithnall @sdroege +gio/g*stream* @alexl @pwithnall @sdroege +gio/gio-tool* @oholy @alexl @pwithnall + +# Generic bits of GLib +glib/ @ebassi @pwithnall @sdroege + +# GObject type system +gobject/ @ebassi @pwithnall @sdroege + +# GVariant +glib/gvariant* @pwithnall @sdroege + +# grefcount, GRcBox and GRefString +glib/gref{count,string}.[ch] @ebassi @pwithnall @sdroege +glib/grc*.[ch] @ebassi @pwithnall @sdroege +glib/garc*.[ch] @ebassi @pwithnall @sdroege + +# Logging +glib/gmessages.[ch] @pwithnall @sdroege + +# Google clusterfuzz support +fuzzing/ @pwithnall \ No newline at end of file
diff --git a/docs/debugging.txt b/docs/debugging.txt new file mode 100644 index 0000000..2cc600a --- /dev/null +++ b/docs/debugging.txt
@@ -0,0 +1,38 @@ + +Traps (G_BREAKPOINT) and traces for the debugging +================================================= + +Some code portions contain trap variables that can be set during +debugging time if G_ENABLE_DEBUG has been defined upon compilation +(use the --buildtype=debug option to configure for this, macros.txt +covers more details). +Such traps lead to immediate code halts to examine the current +program state and backtrace. +Currently, the following trap variables exist: + +static volatile gulong g_trap_free_size; +static volatile gulong g_trap_realloc_size; +static volatile gulong g_trap_malloc_size; + If set to a size > 0, g_free(), g_realloc() and g_malloc() + respectively, will be intercepted if the size matches the + size of the corresponding memory block to free/reallocate/allocate. + This will only work with g_mem_set_vtable (glib_mem_profiler_table) + upon startup though, because memory profiling is required to match + on the memory block sizes. +static volatile GObject *g_trap_object_ref; + If set to a valid object pointer, ref/unref will be intercepted + with G_BREAKPOINT (); +static volatile gpointer *g_trap_instance_signals; +static volatile gpointer *g_trace_instance_signals; + If set to a valid instance pointer, debugging messages + will be spewed about emissions of signals on this instance. + For g_trap_instance_signals matches, the emissions will + also be intercepted with G_BREAKPOINT (); + +Environment variables for debugging +=================================== +When G_ENABLE_DEBUG was defined upon compilation, the GObject library +supports an environment variable GOBJECT_DEBUG that can be set to a +combination of the flags passed in to g_type_init() (currently +"objects" and "signals") to trigger debugging messages about +object bookkeeping and signal emissions during runtime. \ No newline at end of file
diff --git a/docs/macros.txt b/docs/macros.txt new file mode 100644 index 0000000..aa326a4 --- /dev/null +++ b/docs/macros.txt
@@ -0,0 +1,54 @@ +GLib's configure options and corresponding macros +================================================= + +--buildtype={plain,release,minsize,custom} + none +--buildtype={debug,debugoptimized} [debugoptimized is the default] + -DG_ENABLE_DEBUG -g +-Dglib_asserts=false + -DG_DISABLE_ASSERT +-Dglib_checks=false + -DG_DISABLE_CHECKS + +Besides these, there are some local feature specific options, but my main +focus here is to concentrate on macros that affect overall GLib behaviour +and/or third party code. + + +Notes on GLib's internal and global macros +========================================== + +G_DISABLE_ASSERT + The g_assert() and g_assert_not_reached() become non-functional + with this define. The motivation is to speed up end-user apps by + avoiding expensive checks. + This macro can affect third-party code. Defining it when building GLib + will only disable the assertion macros for GLib itself, but third-party code + that passes -DG_DISABLE_ASSERT to the compiler upon its own build + will end up with the non-functional variants after including glib.h + as well. + NOTE: Code inside the assertion macros should not have side effects + that affect the operation of the program. +G_DISABLE_CHECKS + This macro is similar to G_DISABLE_ASSERT, it affects third-party + code as mentioned above and the NOTE about G_DISABLE_ASSERT applies + too. The macros that become non-functional here are + g_return_if_fail(), g_return_val_if_fail(), g_return_if_reached() and + g_return_val_if_reached(). + Additionally the glib_mem_profiler_table and g_mem_profile() from + gmem.h become non-functional if this macro is supplied. + This macro also switches off certain checks in the GSignal code. +G_ENABLE_DEBUG + Quite a bit of additional debugging code is compiled into GLib for this + macro, and since it is a globally visible define, third-party code may + be affected by it similar to G_DISABLE_ASSERT. + The additional code executed/compiled for this macro currently involve: + - extra validity checks for GDate + - memory profiling traps in gmem.c (consult debugging.txt for details) + - BREAKPOINT abortion for fatal log levels in gmessage.c instead of + plain abort() to allow debuggers trapping and overriding them + - added verbosity of gscanner.c to catch deprecated code paths + - added verbosity of gutils.c to catch deprecated code paths + - object ref/unref traps (consult debugging.txt) and object bookkeeping + in gobject.c + - extra validity checks in gsignal.c \ No newline at end of file
diff --git a/docs/reference/.gitignore b/docs/reference/.gitignore new file mode 100644 index 0000000..f9e370e --- /dev/null +++ b/docs/reference/.gitignore
@@ -0,0 +1,16 @@ +*-decl-list.txt +*-decl.txt +*-unused.txt +*-undocumented.txt +*-undeclared.txt +*.args +*.hierarchy +*.interfaces +*.prerequisites +*.signals +*.stamp +html +xml +*.bak +version.xml +*.1
diff --git a/docs/reference/AUTHORS b/docs/reference/AUTHORS new file mode 100644 index 0000000..64f46b7 --- /dev/null +++ b/docs/reference/AUTHORS
@@ -0,0 +1,7 @@ +Damon Chaplin <damon@karuna.freeserve.co.uk> and others. + +See: + + http://www.gtk.org/rdp/status.html + +for a complete list.
diff --git a/docs/reference/COPYING b/docs/reference/COPYING new file mode 100644 index 0000000..df952d3 --- /dev/null +++ b/docs/reference/COPYING
@@ -0,0 +1,30 @@ +This work may be reproduced and distributed in whole or in part, in +any medium, physical or electronic, so as long as this copyright +notice remains intact and unchanged on all copies. Commercial +redistribution is permitted and encouraged, but you may not +redistribute, in whole or in part, under terms more restrictive than +those under which you received it. If you redistribute a modified or +translated version of this work, you must also make the source code to +the modified or translated version available in electronic form +without charge. However, mere aggregation as part of a larger work +shall not count as a modification for this purpose. + +All code examples in this work are placed into the public domain, +and may be used, modified and redistributed without restriction. + +BECAUSE THIS WORK IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE WORK, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE WORK "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. SHOULD THE WORK PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY REPAIR OR CORRECTION. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE WORK AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +WORK, EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES.
diff --git a/docs/reference/NEWS b/docs/reference/NEWS new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/reference/NEWS
diff --git a/docs/reference/gio/.gitignore b/docs/reference/gio/.gitignore new file mode 100644 index 0000000..e9e522e --- /dev/null +++ b/docs/reference/gio/.gitignore
@@ -0,0 +1,3 @@ +*.1 +gio-overrides.txt +tmpl
diff --git a/docs/reference/gio/concat-files-helper.py b/docs/reference/gio/concat-files-helper.py new file mode 100644 index 0000000..94d64c3 --- /dev/null +++ b/docs/reference/gio/concat-files-helper.py
@@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Copyright (C) 2018 Collabora Inc. +# +# 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 2.1 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 +# Lesser 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 <http://www.gnu.org/licenses/>. +# +# Author: Xavier Claessens <xavier.claessens@collabora.com> + +import sys + +if len(sys.argv) < 3: + print('Usage: {} <output file> <input file 1> ...'.format(os.path.basename(sys.argv[0]))) + sys.exit(1) + +with open(sys.argv[1], 'w') as outfile: + for fname in sys.argv[2:]: + with open(fname) as infile: + for line in infile: + outfile.write(line)
diff --git a/docs/reference/gio/gapplication.xml b/docs/reference/gio/gapplication.xml new file mode 100644 index 0000000..13e3f23 --- /dev/null +++ b/docs/reference/gio/gapplication.xml
@@ -0,0 +1,352 @@ +<refentry id="gapplication-tool" lang="en"> + <refentryinfo> + <title>gapplication</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Ryan</firstname> + <surname>Lortie</surname> + </author> + </authorgroup> + </refentryinfo> + + <refmeta> + <refentrytitle>gapplication</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>gapplication</refname> + <refpurpose>D-Bus application launcher</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <cmdsynopsis> + <command>gapplication</command> + <arg choice="plain">help</arg> + <arg choice="opt"><replaceable>COMMAND</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gapplication</command> + <arg choice="plain">version</arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gapplication</command> + <arg choice="plain">list-apps</arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gapplication</command> + <arg choice="plain">launch</arg> + <arg choice="plain"><replaceable>APPID</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gapplication</command> + <arg choice="plain">launch</arg> + <arg choice="plain"><replaceable>APPID</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>FILE</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gapplication</command> + <arg choice="plain">list-actions</arg> + <arg choice="plain"><replaceable>APPID</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gapplication</command> + <arg choice="plain">action</arg> + <arg choice="plain"><replaceable>APPID</replaceable></arg> + <arg choice="plain"><replaceable>ACTION</replaceable></arg> + <arg choice="opt"><replaceable>PARAMETER</replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>gapplication</command> is a commandline implementation of the client-side of the + <interfacename>org.freedesktop.Application</interfacename> interface as specified by the freedesktop.org + Desktop Entry Specification. + </para> + + <para> + <command>gapplication</command> can be used to start applications that have + <varname>DBusActivatable</varname> set to <literal>true</literal> in their <filename>.desktop</filename> + files and can be used to send messages to already-running instances of other applications. + </para> + + <para> + It is possible for applications to refer to <command>gapplication</command> in the <varname>Exec</varname> + line of their <filename class='extension'>.desktop</filename> file to maintain backwards compatibility + with implementations that do not directly support <varname>DBusActivatable</varname>. + </para> + + <para> + <command>gapplication</command> ships as part of <application>GLib</application>. + </para> + </refsect1> + + <refsect1> + <title>Commands</title> + + <refsect2> + <title>Global commands</title> + + <variablelist> + <varlistentry> + <term> + <command>help</command> + <arg choice="opt"><replaceable>COMMAND</replaceable></arg> + </term> + <listitem> + <para> + Displays a short synopsis of the available commands or provides detailed help on a specific + command. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>version</command> + </term> + <listitem> + <para> + Prints the GLib version whence <command>gapplication</command> came. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>list-apps</command> + </term> + <listitem> + <para> + Prints a list of all application IDs that are known to support D-Bus activation. This list is + generated by scanning <filename class='extension'>.desktop</filename> files as per the current + <envar>XDG_DATA_DIRS</envar>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>launch</command> + <arg choice="plain"><replaceable>APPID</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>FILE</replaceable></arg> + </term> + <listitem> + <para> + Launches an application. + </para> + <para> + The first parameter is the application ID in the familiar "reverse DNS" style (eg: + '<literal>org.gnome.app</literal>') without the <filename class='extension'>.desktop</filename> + suffix. + </para> + <para> + Optionally, if additional parameters are given, they are treated as the names of files to open and + may be filenames or URIs. If no files are given then the application is simply activated. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>list-actions</command> + <arg choice="plain"><replaceable>APPID</replaceable></arg> + </term> + <listitem> + <para> + List the actions declared in the application's <filename class='extension'>.desktop</filename> + file. The parameter is the application ID, as above. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>action</command> + <arg choice="plain"><replaceable>APPID</replaceable></arg> + <arg choice="plain"><replaceable>ACTION</replaceable></arg> + <arg choice="opt"><replaceable>PARAMETER</replaceable></arg> + </term> + <listitem> + <para> + Invokes the named action (in the same way as would occur when activating an action specified in + the <filename class='extension'>.desktop</filename> file). + </para> + <para> + The application ID (as above) is the first parameter. The action name follows. + </para> + <para> + Optionally, following the action name can be one parameter, in GVariant format, given as a single + argument. Make sure to use sufficient quoting. + </para> + </listitem> + </varlistentry> + + </variablelist> + </refsect2> + </refsect1> + + <refsect1> + <title>Examples</title> + + <refsect2> + <title>From the commandline</title> + + <para> + Launching an application: + </para> + + <programlisting> + gapplication launch org.example.fooview + </programlisting> + + <para> + Opening a file with an application: + </para> + + <programlisting> + gapplication launch org.example.fooview ~/file.foo + </programlisting> + + <para> + Opening many files with an application: + </para> + + <programlisting> + gapplication launch org.example.fooview ~/foos/*.foo + </programlisting> + + <para> + Invoking an action on an application: + </para> + + <programlisting> + gapplication action org.example.fooview create + </programlisting> + + <para> + Invoking an action on an application, with an action: + </para> + + <programlisting> + gapplication action org.example.fooview show-item '"item_id_828739"' + </programlisting> + </refsect2> + + <refsect2> + <title> + From the <varname>Exec</varname> lines of a <filename class='extension'>.desktop</filename> file + </title> + + <para> + The commandline interface of <command>gapplication</command> was designed so that it could be used + directly from the <varname>Exec</varname> line of a <filename class='extension'>.desktop</filename> + file. + </para> + + <para> + You might want to do this to allow for backwards compatibility with implementations of the specification + that do not understand how to do D-Bus activation, without having to install a separate utility program. + </para> + + <para> + Consider the following example: + </para> + + <programlisting> + [Desktop Entry] + Version=1.1 + Type=Application + Name=Foo Viewer + DBusActivatable=true + MimeType=image/x-foo; + Exec=gapplication launch org.example.fooview %F + Actions=gallery;create; + + [Desktop Action gallery] + Name=Browse Gallery + Exec=gapplication action org.example.fooview gallery + + [Desktop Action create] + Name=Create a new Foo! + Exec=gapplication action org.example.fooview create + </programlisting> + </refsect2> + + <refsect2> + <title>From a script</title> + + <para> + If installing an application that supports D-Bus activation you may still want to put a file in + <filename class='directory'>/usr/bin</filename> so that your program can be started from a terminal. + </para> + + <para> + It is possible for this file to be a shell script. The script can handle arguments such as --help and + --version directly. It can also parse other command line arguments and convert them to uses of + <command>gapplication</command> to activate the application, open files, or invoke actions. + </para> + + <para> + Here is a simplified example, as may be installed in <filename>/usr/bin/fooview</filename>: + </para> + + <programlisting> + #!/bin/sh + + case "$1" in + --help) + echo "see 'man fooview' for more information" + ;; + + --version) + echo "fooview 1.2" + ;; + + --gallery) + gapplication action org.example.fooview gallery + ;; + + --create) + gapplication action org.example.fooview create + ;; + + -*) + echo "unrecognised commandline argument" + exit 1 + ;; + + *) + gapplication launch org.example.fooview "$@" + ;; + esac + </programlisting> + </refsect2> + </refsect1> + + <refsect1> + <title>See also</title> + <para> + <ulink url='http://standards.freedesktop.org/desktop-entry-spec/latest/'>Desktop Entry Specification</ulink>, + <citerefentry> + <refentrytitle>gdbus</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>xdg-open</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>desktop-file-validate</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry> + </para> + </refsect1> + +</refentry>
diff --git a/docs/reference/gio/gdbus-codegen.xml b/docs/reference/gio/gdbus-codegen.xml new file mode 100644 index 0000000..25210c3 --- /dev/null +++ b/docs/reference/gio/gdbus-codegen.xml
@@ -0,0 +1,1165 @@ +<refentry id="gdbus-codegen" lang="en"> + +<refentryinfo> + <title>gdbus</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>David</firstname> + <surname>Zeuthen</surname> + <email>zeuthen@gmail.com</email> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> + <refentrytitle>gdbus-codegen</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> + <refname>gdbus-codegen</refname> + <refpurpose>D-Bus code and documentation generator</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>gdbus-codegen</command> + <arg><option>-h</option>, <option>--help</option></arg> + <arg><option>--interface-prefix</option> <replaceable>org.project.Prefix</replaceable></arg> + <arg><option>--generate-c-code</option> <replaceable>OUTFILES</replaceable></arg> + <arg><option>--c-namespace</option> <replaceable>YourProject</replaceable></arg> + <arg><option>--c-generate-object-manager</option></arg> + <arg><option>--c-generate-autocleanup</option> none|objects|all</arg> + <arg><option>--output-directory</option> <replaceable>OUTDIR</replaceable></arg> + <arg><option>--generate-docbook</option> <replaceable>OUTFILES</replaceable></arg> + <arg><option>--pragma-once</option></arg> + <arg><option>--xml-files</option> <replaceable>FILE</replaceable></arg> + <arg><option>--header</option></arg> + <arg><option>--body</option></arg> + <arg><option>--interface-info-header</option></arg> + <arg><option>--interface-info-body</option></arg> + <arg><option>--symbol-decorator</option> <replaceable>DECORATOR</replaceable></arg> + <arg><option>--symbol-decorator-header</option> <replaceable>HEADER</replaceable></arg> + <arg><option>--symbol-decorator-define</option> <replaceable>DEFINE</replaceable></arg> + <arg><option>--output</option> <replaceable>OUTFILE</replaceable></arg> + <group choice="plain" rep="repeat"> + <arg> + <option>--annotate</option> + <replaceable>ELEMENT</replaceable> + <replaceable>KEY</replaceable> + <replaceable>VALUE</replaceable> + </arg> + </group> + <arg><option>--glib-min-required</option> <replaceable>VERSION</replaceable></arg> + <arg><option>--glib-max-allowed</option> <replaceable>VERSION</replaceable></arg> + <arg choice="plain">FILE</arg> + <arg> + <arg choice="plain" rep="repeat">FILE</arg> + </arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1> + <title>Description</title> + <para> + <command>gdbus-codegen</command> is used to generate code and/or + documentation for one or more D-Bus interfaces. + </para> + <para> + <command>gdbus-codegen</command> reads + <ulink + url="http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format">D-Bus + Introspection XML</ulink> from files passed as additional + arguments on the command line and generates output files. + It currently supports generating C source code (via + <option>--body</option>) or header (via <option>--header</option>) + and Docbook XML (via <option>--generate-docbook</option>). Alternatively, + more restricted C source code and headers can be generated, which just + contain the interface information (as <type>GDBusInterfaceInfo</type> + structures) using <option>--interface-info-body</option> and + <option>--interface-info-header</option>. + </para> +</refsect1> + +<refsect1> + <title>Generating C code</title> + <para> + When generating C code, a + #GInterface<!-- -->-derived type is generated for each D-Bus + interface. Additionally, for every generated type, + <type>FooBar</type>, two concrete instantiable types, + <type>FooBarProxy</type> and <type>FooBarSkeleton</type>, implementing + said interface are also generated. The former is derived from + #GDBusProxy and intended for use on the client side + while the latter is derived from the + #GDBusInterfaceSkeleton type making it easy to export on a + #GDBusConnection either directly or via a + #GDBusObjectManagerServer instance. + </para> + <para> + For C code generation either <option>--body</option> that + generates source code, <option>--header</option> that + generates headers, <option>--interface-info-body</option> that generates + interface information source code, or + <option>--interface-info-header</option> that generates interface information + headers, can be used. These options must be used along with + <option>--output</option>, which is used to specify the file to output to. + </para> + <para> + Both files can be generated at the same time by using + <option>--generate-c-code</option>, but this option is deprecated. + In this case <option>--output</option> cannot be used due to the + generation of multiple files. Instead pass + <option>--output-directory</option> to specify the directory to put + the output files in. By default the current directory will be used. + </para> + <para> + The name of each generated C type is derived from the D-Bus + interface name stripped with the prefix given with + <option>--interface-prefix</option> and with the dots removed and + initial characters capitalized. For example, for the D-Bus + interface <literal>com.acme.Coyote</literal> the name used is + <literal>ComAcmeCoyote</literal>. For the D-Bus interface + <literal>org.project.Bar.Frobnicator</literal> with + <option>--interface-prefix</option> + <literal>org.project.</literal>, the name used is + <literal>BarFrobnicator</literal>. + </para> + <para> + For methods, signals and properties, if not specified, the name + defaults to the name of the method, signal or property. + </para> + <para> + Two forms of the name are used - the CamelCase form and the + lower-case form. The CamelCase form is used for the #GType and + struct name, while lower-case form is used in function names. The + lower-case form is calculated by converting from CamelCase to + lower-case and inserting underscores at word boundaries (using + certain heuristics). + </para> + <para> + If the value given by the <literal>org.gtk.GDBus.C.Name</literal> + annotation or the <option>--c-namespace</option> option contains + an underscore (sometimes called <emphasis>Ugly_Case</emphasis>), + then the camel-case name is derived by removing all underscores, + and the lower-case name is derived by lower-casing the + string. This is useful in some situations where abbreviations are + used. For example, if the annotation is used on the interface + <literal>net.MyCorp.MyApp.iSCSITarget</literal> with the value + <literal>iSCSI_Target</literal> the CamelCase form is + <literal>iSCSITarget</literal> while the lower-case form is + <literal>iscsi_target</literal>. If the annotation is used on the + method <literal>EjectTheiPod</literal> with the value + <literal>Eject_The_iPod</literal>, the lower-case form is + <literal>eject_the_ipod</literal>. + </para> +</refsect1> + +<refsect1> + <title>Generating Docbook documentation</title> + <para> + Each generated Docbook XML file (see the + <option>--generate-docbook</option> option for details) is a <ulink + url="http://www.docbook.org/tdg/en/html/refentry.html"><literal>RefEntry</literal></ulink> + article describing the D-Bus interface. + </para> +</refsect1> + +<refsect1> + <title>Options</title> + <para> + The following options are supported: + </para> + <variablelist> + + <varlistentry> + <term><option>-h</option>, <option>--help</option></term> + <listitem> + <para> + Show help and exit. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--xml-files</option> <replaceable>FILE</replaceable></term> + <listitem> + <para> + This option is deprecated; use positional arguments instead. + The D-Bus introspection XML file. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--interface-prefix</option> <replaceable>org.project.Prefix.</replaceable></term> + <listitem> + <para> + A prefix to strip from all D-Bus interface names when + calculating the typename for the C binding and the Docbook + <ulink + url="http://www.docbook.org/tdg/en/html/primary.html">sortas + attribute</ulink>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--generate-docbook</option> <replaceable>OUTFILES</replaceable></term> + <listitem> + <para> + Generate Docbook Documentation for each D-Bus interface and + put it in <filename>OUTFILES-NAME.xml</filename> where + <literal>NAME</literal> is a place-holder for the interface + name, e.g. <literal>net.Corp.FooBar</literal> and so on. + </para> + <para> + Pass <option>--output-directory</option> to specify the directory + to put the output files in. By default the current directory + will be used. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--generate-c-code</option> <replaceable>OUTFILES</replaceable></term> + <listitem> + <para> + Generate C code for all D-Bus interfaces and put it in + <filename>OUTFILES.c</filename> and + <filename>OUTFILES.h</filename> including any sub-directories. If you want the files to + be output in a different location use <option>--output-directory</option> as <filename>OUTFILES.h</filename> + including sub-directories will be referenced from <filename>OUTFILES.c</filename>. + </para> + <para> + The full paths would then be <literal>$(OUTDIR)/$(dirname $OUTFILES)/$(basename $OUTFILES).{c,h}</literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--c-namespace</option> <replaceable>YourProject</replaceable></term> + <listitem> + <para> + The namespace to use for generated C code. This is expected + to be in <ulink + url="http://en.wikipedia.org/wiki/CamelCase">CamelCase</ulink> + or <emphasis>Ugly_Case</emphasis> (see above). + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--pragma-once</option></term> + <listitem> + <para> + If this option is passed, the + <ulink url="https://en.wikipedia.org/wiki/Pragma_once">#pragma once</ulink> + preprocessor directive is used instead of include guards. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--c-generate-object-manager</option></term> + <listitem> + <para> + If this option is passed, suitable #GDBusObject, + #GDBusObjectProxy, #GDBusObjectSkeleton and + #GDBusObjectManagerClient subclasses are generated. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--c-generate-autocleanup</option> none|objects|all</term> + <listitem> + <para> + This option influences what types autocleanup functions are + generated for. 'none' means to not generate any autocleanup functions. + 'objects' means to generate them for object types, and 'all' means to + generate them for object types and interfaces. The default is 'objects' + due to a corner case in backwards compatibility with a few projects, + but you should likely switch your project to use 'all'. + This option was added in GLib 2.50. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--output-directory</option> <replaceable>OUTDIR</replaceable></term> + <listitem> + <para> + Directory to output generated source to. Equivalent to changing directory before generation. + </para> + <para> + This option cannot be used with <option>--body</option>, + <option>--header</option>, <option>--interface-info-body</option> or + <option>--interface-info-header</option>; and + <option>--output</option> must be used. + </para> + + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--header</option></term> + <listitem> + <para> + If this option is passed, it will generate the header code and write it to the disk by + using the path and file name provided by <option>--output</option>. + </para> + <para> + Using <option>--generate-c-code</option>, <option>--generate-docbook</option> or + <option>--output-directory</option> are not allowed to be used along with + <option>--header</option> and <option>--body</option> options, because these options + are used to generate only one file. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--body</option></term> + <listitem> + <para> + If this option is passed, it will generate the source code and write it to the disk by + using the path and file name provided by <option>--output</option>. + </para> + <para> + Using <option>--generate-c-code</option>, <option>--generate-docbook</option> or + <option>--output-directory</option> are not allowed to be used along with + <option>--header</option> and <option>--body</option> options, because these options + are used to generate only one file. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--interface-info-header</option></term> + <listitem> + <para> + If this option is passed, it will generate the header code for the + <type>GDBusInterfaceInfo</type> structures only and will write it to + the disk by using the path and file name provided by + <option>--output</option>. + </para> + <para> + Using <option>--generate-c-code</option>, <option>--generate-docbook</option> or + <option>--output-directory</option> are not allowed to be used along with + the <option>--interface-info-header</option> and + <option>--interface-info-body</option> options, because these options + are used to generate only one file. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--interface-info-body</option></term> + <listitem> + <para> + If this option is passed, it will generate the source code for the + <type>GDBusInterfaceInfo</type> structures only and will write it to + the disk by using the path and file name provided by + <option>--output</option>. + </para> + <para> + Using <option>--generate-c-code</option>, <option>--generate-docbook</option> or + <option>--output-directory</option> are not allowed to be used along with + the <option>--interface-info-header</option> and + <option>--interface-info-body</option> options, because these options + are used to generate only one file. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--symbol-decorator</option> <replaceable>DECORATOR</replaceable></term> + <listitem> + <para> + If a <literal>DECORATOR</literal> is passed in with this option, all the + generated function prototypes in the generated header will be marked with + <literal>DECORATOR</literal>. This can be used, for instance, to export + symbols from code generated with <command>gdbus-codegen</command>. + This option is added in GLib-2.66 + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--symbol-decorator-header</option> <replaceable>HEADER</replaceable></term> + <listitem> + <para> + If a <literal>HEADER</literal> is passed in with this option, the + generated header will put a <literal>#include HEADER</literal> before the rest of the + items, except for the inclusion guards or <literal>#pragma once</literal> + (if <option>--pragma-once</option> is used). This is used if using another header file is + needed for the decorator passed in via <option>--symbol-decorator</option> to be defined. + This option is added in GLib-2.66. + </para> + <para> + This option can only be used if <option>--symbol-decorator</option> is used. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--symbol-decorator-define</option> <replaceable>DEFINE</replaceable></term> + <listitem> + <para> + If a <literal>DEFINE</literal> is passed in with this option, the + generated source will add a <literal>#define DEFINE</literal> before the rest of the + items. This is used if a particular macro is needed to ensure the decorator + passed in via <option>--symbol-decorator</option> uses the correct definition when the + generated source is being compiled. This option is added in GLib-2.66. + </para> + <para> + This option can only be used if <option>--symbol-decorator</option> is used. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--output</option> <replaceable>OUTFILE</replaceable></term> + <listitem> + <para> + The full path where the header (<option>--header</option>, + <option>--interface-info-header</option>) or the source code + (<option>--body</option>, <option>--interface-info-body</option>) will + be written, using the path and filename provided by + <option>--output</option>. The full path could be something like + <literal>$($OUTFILE).{c,h}</literal>. + </para> + <para> + Using <option>--generate-c-code</option>, <option>--generate-docbook</option> or + <option>--output-directory</option> is not allowed along with + <option>--output</option>, because the latter is used to generate only one file. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--annotate</option> <replaceable>ELEMENT</replaceable> <replaceable>KEY</replaceable> <replaceable>VALUE</replaceable></term> + <listitem> + <para> + Used to inject D-Bus annotations into the given XML + files. It can be used with interfaces, methods, signals, + properties and arguments in the following way: + </para> +<informalexample><programlisting><![CDATA[ +gdbus-codegen --c-namespace MyApp \ + --generate-c-code myapp-generated \ + --annotate "org.project.InterfaceName" \ + org.gtk.GDBus.C.Name MyFrobnicator \ + --annotate "org.project.InterfaceName:Property" \ + bar bat \ + --annotate "org.project.InterfaceName.Method()" \ + org.freedesktop.DBus.Deprecated true \ + --annotate "org.project.InterfaceName.Method()[arg_name]" \ + snake hiss \ + --annotate "org.project.InterfaceName::Signal" \ + cat meow \ + --annotate "org.project.InterfaceName::Signal[arg_name]" \ + dog wuff \ + myapp-dbus-interfaces.xml +]]></programlisting></informalexample> + <para> + Any UTF-8 string can be used for <replaceable>KEY</replaceable> and <replaceable>VALUE</replaceable>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--glib-min-required</option> <replaceable>VERSION</replaceable></term> + <listitem> + <para> + Specifies the minimum version of GLib which the code generated by + <command>gdbus-codegen</command> can depend on. This may be used to + make backwards-incompatible changes in the output or behaviour of + <command>gdbus-codegen</command> in future, which users may opt in to + by increasing the value they pass for <option>--glib-min-required</option>. + If this option is not passed, the output from <command>gdbus-codegen</command> + is guaranteed to be compatible with all versions of GLib from 2.30 + upwards, as that is when <command>gdbus-codegen</command> was first + released. + </para> + <para> + Note that some version parameters introduce incompatible changes: all callers + of the generated code might need to be updated, and if the generated code is part of + a library's API or ABI, then increasing the version parameter can result in an API + or ABI break. + </para> + <para> + The version number must be of the form + <literal><replaceable>MAJOR</replaceable>.<replaceable>MINOR</replaceable>.<replaceable>MICRO</replaceable></literal>, + where all parts are integers. <replaceable>MINOR</replaceable> and + <replaceable>MICRO</replaceable> are optional. The version number may not be smaller + than <literal>2.30</literal>. + </para> + <para> + If the version number is <literal>2.64</literal> or greater, the generated code will + have the following features: (1) If a method has <literal>h</literal> (file + descriptor) parameter(s), a <type>GUnixFDList</type> parameter will exist in the + generated code for it (whereas previously the annotation + <literal>org.gtk.GDBus.C.UnixFD</literal> was required), and (2) Method call functions will + have two additional arguments to allow the user to specify <type>GDBusCallFlags</type> + and a timeout value, as is possible when using <function>g_dbus_proxy_call()</function>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--glib-max-allowed</option> <replaceable>VERSION</replaceable></term> + <listitem> + <para> + Specifies the maximum version of GLib which the code generated by + <command>gdbus-codegen</command> can depend on. This may be used to + ensure that code generated by <command>gdbus-codegen</command> is + compilable with specific older versions of GLib that your software has + to support. + </para> + <para> + The version number must be of the form + <literal><replaceable>MAJOR</replaceable>.<replaceable>MINOR</replaceable>.<replaceable>MICRO</replaceable></literal>, + where all parts are integers. <replaceable>MINOR</replaceable> and + <replaceable>MICRO</replaceable> are optional. The version number must + be greater than or equal to that passed to <option>--glib-min-required</option>. + It defaults to the version of GLib which provides this <command>gdbus-codegen</command>. + </para> + </listitem> + </varlistentry> + + </variablelist> +</refsect1> + +<refsect1> + <title>Supported D-Bus Annotations</title> + <para> + The following D-Bus annotations are supported by + <command>gdbus-codegen</command>: + </para> + + <variablelist> + + <varlistentry> + <term><literal>org.freedesktop.DBus.Deprecated</literal></term> + <listitem> + <para> + Can be used on any <literal><interface></literal>, + <literal><method></literal>, + <literal><signal></literal> and + <literal><property></literal> element to specify that + the element is deprecated if its value is + <literal>true</literal>. Note that this annotation is + defined in the <ulink + url="http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format">D-Bus + specification</ulink> and can only assume the values + <literal>true</literal> and <literal>false</literal>. In + particular, you cannot specify the version that the element + was deprecated in nor any helpful deprecation message. Such + information should be added to the element documentation + instead. + </para> + <para> + When generating C code, this annotation is used to add + #G_GNUC_DEPRECATED to generated functions for the element. + </para> + <para> + When generating Docbook XML, a deprecation warning will + appear along the documentation for the element. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>org.gtk.GDBus.Since</literal></term> + <listitem> + <para> + Can be used on any <literal><interface></literal>, + <literal><method></literal>, + <literal><signal></literal> and + <literal><property></literal> element to specify the + version (any free-form string but compared using a + version-aware sort function) the element appeared in. + </para> + <para> + When generating C code, this field is used to ensure + function pointer order for preserving ABI/API, see <xref + linkend="gdbus-code-stability"/>. + </para> + <para> + When generating Docbook XML, the value of this tag appears + in the documentation. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>org.gtk.GDBus.DocString</literal></term> + <listitem> + <para> + A string with Docbook content for documentation. This annotation can + be used on <literal><interface></literal>, + <literal><method></literal>, + <literal><signal></literal>, + <literal><property></literal> and + <literal><arg></literal> elements. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>org.gtk.GDBus.DocString.Short</literal></term> + <listitem> + <para> + A string with Docbook content for short/brief + documentation. This annotation can only be used on + <literal><interface></literal> elements. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>org.gtk.GDBus.C.Name</literal></term> + <listitem> + <para> + Can be used on any <literal><interface></literal>, + <literal><method></literal>, + <literal><signal></literal> and + <literal><property></literal> element to specify the + name to use when generating C code. The value is expected to + be in <ulink + url="http://en.wikipedia.org/wiki/CamelCase">CamelCase</ulink> + or <emphasis>Ugly_Case</emphasis> (see above). + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>org.gtk.GDBus.C.ForceGVariant</literal></term> + <listitem> + <para> + If set to a non-empty string, a #GVariant instance will + be used instead of the natural C type. This annotation can + be used on any <literal><arg></literal> and + <literal><property></literal> element. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>org.gtk.GDBus.C.UnixFD</literal></term> + <listitem> + <para> + If set to a non-empty string, the generated code will + include parameters to exchange file descriptors using the + #GUnixFDList type. This annotation can be used on + <literal><method></literal> elements. + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + As an easier alternative to using the + <literal>org.gtk.GDBus.DocString</literal> annotation, note that + parser used by <command>gdbus-codegen</command> parses XML + comments in a way similar to <ulink + url="http://www.gtk.org/gtk-doc/">gtk-doc</ulink>: +<informalexample><programlisting><![CDATA[ +<!-- + net.Corp.Bar: + @short_description: A short description + + A <emphasis>longer</emphasis> description. + + This is a new paragraph. +--> +<interface name="net.corp.Bar"> + <!-- + FooMethod: + @greeting: The docs for greeting parameter. + @response: The docs for response parameter. + + The docs for the actual method. + --> + <method name="FooMethod"> + <arg name="greeting" direction="in" type="s"/> + <arg name="response" direction="out" type="s"/> + </method> + + <!-- + BarSignal: + @blah: The docs for blah parameter. + @boo: The docs for boo parameter. + @since: 2.30 + + The docs for the actual signal. + --> + <signal name="BarSignal"> + <arg name="blah" type="s"/> + <arg name="boo" type="s"/> + </signal> + + <!-- BazProperty: The docs for the property. --> + <property name="BazProperty" type="s" access="read"/> +</interface> +]]></programlisting></informalexample> + </para> + <para> + Note that <literal><![CDATA[@since]]></literal> can be used in any inline + documentation bit (e.g. for interfaces, methods, signals and + properties) to set the <literal>org.gtk.GDBus.Since</literal> + annotation. For the <literal>org.gtk.GDBus.DocString</literal> + annotation (and inline comments), note that substrings of the form + <literal><![CDATA[#net.Corp.Bar]]></literal>, + <literal><![CDATA[net.Corp.Bar.FooMethod()]]></literal>, + <literal><![CDATA[#net.Corp.Bar::BarSignal]]></literal> and + <literal><![CDATA[#net.Corp.InlineDocs:BazProperty]]></literal> are all + expanded to links to the respective interface, method, signal and + property. + Additionally, substrings starting with <literal>@</literal> and <literal>%</literal> characters are rendered as + <ulink url="http://www.docbook.org/tdg/en/html/parameter.html">parameter</ulink> and + <ulink url="http://www.docbook.org/tdg/en/html/constant.html">constant</ulink> respectively. + </para> + <para> + If both XML comments and + <literal>org.gtk.GDBus.DocString</literal> or + <literal>org.gtk.GDBus.DocString.Short</literal> annotations are + present, the latter wins. + </para> +</refsect1> + +<refsect1> + <title>Example</title> + <para> + Consider the following D-Bus Introspection XML. + </para> + <informalexample><programlisting><![CDATA[ +<node> + <interface name="net.Corp.MyApp.Frobber"> + <method name="HelloWorld"> + <arg name="greeting" direction="in" type="s"/> + <arg name="response" direction="out" type="s"/> + </method> + + <signal name="Notification"> + <arg name="icon_blob" type="ay"/> + <arg name="height" type="i"/> + <arg name="messages" type="as"/> + </signal> + + <property name="Verbose" type="b" access="readwrite"/> + </interface> +</node> +]]></programlisting> + </informalexample> + <para> + If <command>gdbus-codegen</command> is used on this file like this: + </para> +<informalexample><programlisting><![CDATA[ +gdbus-codegen --generate-c-code myapp-generated \ + --c-namespace MyApp \ + --interface-prefix net.corp.MyApp. \ + net.Corp.MyApp.Frobber.xml +]]></programlisting></informalexample> + <para> + two files called + <filename>myapp-generated.[ch]</filename> are + generated. The files provide an abstract + #GTypeInterface<!-- -->-derived type called + <type>MyAppFrobber</type> as well as two instantiable types with + the same name but suffixed with <type>Proxy</type> and + <type>Skeleton</type>. The generated file, roughly, contains the + following facilities: + </para> +<informalexample><programlisting><![CDATA[ +/* GType macros for the three generated types */ +#define MY_APP_TYPE_FROBBER (my_app_frobber_get_type ()) +#define MY_APP_TYPE_FROBBER_SKELETON (my_app_frobber_skeleton_get_type ()) +#define MY_APP_TYPE_FROBBER_PROXY (my_app_frobber_proxy_get_type ()) + +typedef struct _MyAppFrobber MyAppFrobber; /* Dummy typedef */ + +typedef struct +{ + GTypeInterface parent_iface; + + /* Signal handler for the ::notification signal */ + void (*notification) (MyAppFrobber *proxy, + GVariant *icon_blob, + gint height, + const gchar* const *messages); + + /* Signal handler for the ::handle-hello-world signal */ + gboolean (*handle_hello_world) (MyAppFrobber *proxy, + GDBusMethodInvocation *invocation, + const gchar *greeting); +} MyAppFrobberIface; + +/* Asynchronously calls HelloWorld() */ +void +my_app_frobber_call_hello_world (MyAppFrobber *proxy, + const gchar *greeting, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean +my_app_frobber_call_hello_world_finish (MyAppFrobber *proxy, + gchar **out_response, + GAsyncResult *res, + GError **error); + +/* Synchronously calls HelloWorld(). Blocks calling thread. */ +gboolean +my_app_frobber_call_hello_world_sync (MyAppFrobber *proxy, + const gchar *greeting, + gchar **out_response, + GCancellable *cancellable, + GError **error); + +/* Completes handling the HelloWorld() method call */ +void +my_app_frobber_complete_hello_world (MyAppFrobber *object, + GDBusMethodInvocation *invocation, + const gchar *response); + +/* Emits the ::notification signal / Notification() D-Bus signal */ +void +my_app_frobber_emit_notification (MyAppFrobber *object, + GVariant *icon_blob, + gint height, + const gchar* const *messages); + +/* Gets the :verbose GObject property / Verbose D-Bus property. + * Does no blocking I/O. + */ +gboolean my_app_frobber_get_verbose (MyAppFrobber *object); + +/* Sets the :verbose GObject property / Verbose D-Bus property. + * Does no blocking I/O. + */ +void my_app_frobber_set_verbose (MyAppFrobber *object, + gboolean value); + +/* Gets the interface info */ +GDBusInterfaceInfo *my_app_frobber_interface_info (void); + +/* Creates a new skeleton object, ready to be exported */ +MyAppFrobber *my_app_frobber_skeleton_new (void); + +/* Client-side proxy constructors. + * + * Additionally, _new_for_bus(), _new_for_bus_finish() and + * _new_for_bus_sync() proxy constructors are also generated. + */ +void +my_app_frobber_proxy_new (GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +MyAppFrobber * +my_app_frobber_proxy_new_finish (GAsyncResult *res, + GError **error); +MyAppFrobber * +my_app_frobber_proxy_new_sync (GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); +]]></programlisting></informalexample> + <para> + Thus, for every D-Bus method, there will be three C functions for + calling the method, one #GObject signal for handling an incoming + call and one C function for completing an incoming call. For every + D-Bus signal, there's one #GObject signal and one C function for + emitting it. For every D-Bus property, two C functions are + generated (one setter, one getter) and one #GObject property. The + following table summarizes the generated facilities and where they + are applicable: + </para> + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry></entry> + <entry>Client</entry> + <entry>Server</entry> + </row> + </thead> + <tbody> + <row> + <entry>Types</entry> + <entry>Use <type>MyAppFrobberProxy</type></entry> + <entry>Any type implementing the <type>MyAppFrobber</type> interface</entry> + </row> + <row> + <entry>Methods</entry> + <entry>Use <function>m_a_f_hello_world()</function> to call.</entry> + <entry>Receive via the <function>handle_hello_world()</function> signal handler. Complete the call with <function>m_a_f_complete_hello_world()</function></entry> + </row> + <row> + <entry>Signals</entry> + <entry>Connect to the <function>::notification</function> GObject signal.</entry> + <entry>Use <function>m_a_f_emit_notification()</function> to emit signal.</entry> + </row> + <row> + <entry>Properties (Reading)</entry> + <entry>Use <function>m_a_f_get_verbose()</function> or <parameter>:verbose</parameter>.</entry> + <entry>Implement #GObject<!-- -->'s <function>get_property()</function> vfunc.</entry> + </row> + <row> + <entry>Properties (writing)</entry> + <entry>Use <function>m_a_f_set_verbose()</function> or <parameter>:verbose</parameter>.</entry> + <entry>Implement #GObject<!-- -->'s <function>set_property()</function> vfunc.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + + <refsect2> + <title>Client-side usage</title> + <para> + You can use the generated proxy type with the generated + constructors: + </para> + <informalexample><programlisting><![CDATA[ + MyAppFrobber *proxy; + GError *error; + + error = NULL; + proxy = my_app_frobber_proxy_new_for_bus_sync ( + G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "net.Corp.MyApp", /* bus name */ + "/net/Corp/MyApp/SomeFrobber", /* object */ + NULL, /* GCancellable* */ + &error); + /* do stuff with proxy */ + g_object_unref (proxy); +]]></programlisting></informalexample> + <para> + Instead of using the generic #GDBusProxy facilities, one can use + the generated methods such as + <function>my_app_frobber_call_hello_world()</function> to invoke + the <function>net.Corp.MyApp.Frobber.HelloWorld()</function> + D-Bus method, connect to the + <function>::notification</function> GObject signal to receive + the <function>net.Corp.MyApp.Frobber::Notification</function> + D-Bus signal and get/set the + <parameter>net.Corp.MyApp.Frobber:Verbose</parameter> D-Bus + Property using either the GObject property + <parameter>:verbose</parameter> or the + <function>my_app_get_verbose()</function> and + <function>my_app_set_verbose()</function> methods. Use the + standard #GObject::notify signal to listen to property changes. + </para> + <para> + Note that all property access is via #GDBusProxy<!-- -->'s + property cache so no I/O is ever done when reading properties. + Also note that setting a property will cause the + <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.DBus.Properties.Set</ulink> method to be + called on the remote object. This call, however, is asynchronous + so setting a property won't block. Further, the change is + delayed and no error checking is possible. + </para> + </refsect2> + + <refsect2> + <title>Server-side usage</title> + <para> + The generated <type>MyAppFrobber</type> interface is designed so + it is easy to implement it in a #GObject + subclass. For example, to handle + <function>HelloWorld()</function> method invocations, set the + vfunc for <function>handle_hello_hello_world()</function> in the + <type>MyAppFrobberIface</type> structure. Similarly, to handle + the <parameter>net.Corp.MyApp.Frobber:Verbose</parameter> + property override the <parameter>:verbose</parameter> #GObject + property from the subclass. To emit a signal, use + e.g. <function>my_app_emit_signal()</function> or + g_signal_emit_by_name(). + </para> + <para> + Instead of subclassing, it is often easier to use the generated + <type>MyAppFrobberSkeleton</type> subclass. To handle incoming + method calls, use <function>g_signal_connect()</function> with + the <function>::handle-*</function> signals and instead of + overriding #GObject<!-- -->'s + <function>get_property()</function> and + <function>set_property()</function> vfuncs, use + g_object_get() and + g_object_set() or the generated property + getters and setters (the generated class has an internal + property bag implementation). + </para> + <informalexample><programlisting><![CDATA[ +static gboolean +on_handle_hello_world (MyAppFrobber *interface, + GDBusMethodInvocation *invocation, + const gchar *greeting, + gpointer user_data) +{ + if (g_strcmp0 (greeting, "Boo") != 0) + { + gchar *response; + response = g_strdup_printf ("Word! You said `%s'.", greeting); + my_app_complete_hello_world (interface, invocation, response); + g_free (response); + } + else + { + g_dbus_method_invocation_return_error (invocation, + MY_APP_ERROR, + MY_APP_ERROR_NO_WHINING, + "Hey, %s, there will be no whining!", + g_dbus_method_invocation_get_sender (invocation)); + } + return TRUE; +} + + [...] + + interface = my_app_frobber_skeleton_new (); + my_app_frobber_set_verbose (interface, TRUE); + + g_signal_connect (interface, + "handle-hello-world", + G_CALLBACK (on_handle_hello_world), + some_user_data); + + [...] + + error = NULL; + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (interface), + connection, + "/path/of/dbus_object", + &error)) + { + /* handle error */ + } +]]></programlisting></informalexample> + <para> + To facilitate atomic changesets (multiple properties changing at + the same time), #GObject::notify signals are queued up when + received. The queue is drained in an idle handler (which is called from the + <link linkend="g-main-context-push-thread-default">thread-default main loop</link> + of the thread where the skeleton object was + constructed) and will cause emissions of the <ulink + url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.DBus.Properties::PropertiesChanged</ulink> + signal with all the properties that have changed. Use + g_dbus_interface_skeleton_flush() or + g_dbus_object_skeleton_flush() to empty the queue + immediately. Use g_object_freeze_notify() and + g_object_thaw_notify() for atomic changesets if on a different + thread. + </para> + </refsect2> +</refsect1> + +<refsect1> + <title>C Type Mapping</title> + <para> + Scalar types + (type-strings + <link linkend="G-VARIANT-TYPE-BOOLEAN:CAPS">'b'</link>, + <link linkend="G-VARIANT-TYPE-BYTE:CAPS">'y'</link>, + <link linkend="G-VARIANT-TYPE-INT16:CAPS">'n'</link>, + <link linkend="G-VARIANT-TYPE-UINT16:CAPS">'q'</link>, + <link linkend="G-VARIANT-TYPE-INT32:CAPS">'i'</link>, + <link linkend="G-VARIANT-TYPE-UINT32:CAPS">'u'</link>, + <link linkend="G-VARIANT-TYPE-INT64:CAPS">'x'</link>, + <link linkend="G-VARIANT-TYPE-UINT64:CAPS">'t'</link> and + <link linkend="G-VARIANT-TYPE-DOUBLE:CAPS">'d'</link>) + ), + strings (type-strings + <link linkend="G-VARIANT-TYPE-STRING:CAPS">'s'</link>, + <link linkend="G-VARIANT-TYPE-BYTESTRING:CAPS">'ay'</link>, + <link linkend="G-VARIANT-TYPE-OBJECT-PATH:CAPS">'o'</link> and + <link linkend="G-VARIANT-TYPE-SIGNATURE:CAPS">'g'</link>) and + arrays of string (type-strings + <link linkend="G-VARIANT-TYPE-STRING-ARRAY:CAPS">'as'</link>, + <link linkend="G-VARIANT-TYPE-OBJECT-PATH-ARRAY:CAPS">'ao'</link> and + <link linkend="G-VARIANT-TYPE-BYTESTRING-ARRAY:CAPS">'aay'</link>) + are mapped to the natural types, + e.g. #gboolean, #gdouble, #gint, <link linkend="gchararray">gchar*</link>, + <link linkend="GStrv">gchar**</link> and + so on. Everything else is mapped to the #GVariant + type. + </para> + <para> + This automatic mapping can be turned off by using the annotation + <literal>org.gtk.GDBus.C.ForceGVariant</literal> - if used then a + #GVariant is always exchanged instead of the + corresponding native C type. This annotation may be convenient to + use when using + bytestrings (type-string <link linkend="G-VARIANT-TYPE-BYTESTRING:CAPS">'ay'</link>) + for data that could have embedded NUL bytes. + </para> +</refsect1> + +<refsect1 id="gdbus-code-stability"> + <title>Stability Guarantees</title> + <para> + The generated C functions are guaranteed to not change their ABI + that is, if a method, signal or property does not change its + signature in the introspection XML, the generated C functions will + not change its C ABI either. The ABI of the generated instance and + class structures will be preserved as well. + </para> + <para> + The ABI of the generated #GType<!-- -->s will be preserved only if + the <literal>org.gtk.GDBus.Since</literal> annotation is used + judiciously — this is because the VTable for the #GInterface + relies on functions pointers for signal handlers. Specifically, if + a D-Bus method, property or signal or is added to a D-Bus + interface, then ABI of the generated #GInterface type is preserved + if, and only if, each added method, property signal is annotated + with they <literal>org.gtk.GDBus.Since</literal> annotation using + a greater version number than previous versions. + </para> + <para> + The generated C code currently happens to be annotated with <ulink + url="http://www.gtk.org/gtk-doc/">gtk-doc</ulink> / <ulink + url="https://wiki.gnome.org/Projects/GObjectIntrospection">GObject + Introspection</ulink> comments / annotations. The layout and + contents might change in the future so no guarantees about + e.g. <literal>SECTION</literal> usage etc. is given. + </para> + <para> + While the generated Docbook for D-Bus interfaces isn't expected to + change, no guarantees are given at this point. + </para> + <para> + It is important to note that the generated code should not be + checked into revision control systems, nor it should be included + in distributed source archives. + </para> +</refsect1> + +<refsect1> + <title>Bugs</title> + <para> + Please send bug reports to either the distribution bug tracker + or the upstream bug tracker at + <ulink url="https://gitlab.gnome.org/GNOME/glib/issues/new">https://gitlab.gnome.org/GNOME/glib/issues/new</ulink>. + </para> +</refsect1> + +<refsect1> + <title>See also</title> + <para> + <citerefentry> + <refentrytitle>gdbus</refentrytitle><manvolnum>1</manvolnum> + </citerefentry> + </para> +</refsect1> + +</refentry>
diff --git a/docs/reference/gio/gdbus-object-manager-example/.gitignore b/docs/reference/gio/gdbus-object-manager-example/.gitignore new file mode 100644 index 0000000..cc8a11d --- /dev/null +++ b/docs/reference/gio/gdbus-object-manager-example/.gitignore
@@ -0,0 +1 @@ +gdbus-object-manager-example-overrides.txt
diff --git a/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-docs.xml b/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-docs.xml new file mode 100644 index 0000000..7b0d1ca --- /dev/null +++ b/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-docs.xml
@@ -0,0 +1,17 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'"> +]> +<book lang="en" xmlns:xi="http://www.w3.org/2003/XInclude"> + <part> + <title>foo</title> + <chapter> + <title>bar</title> + <xi:include href="xml/ExampleAnimal.xml"/> + <xi:include href="xml/ExampleCat.xml"/> + <xi:include href="xml/ExampleObject.xml"/> + <xi:include href="xml/ExampleObjectManagerClient.xml"/> + </chapter> + </part> +</book>
diff --git a/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-sections.txt b/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-sections.txt new file mode 100644 index 0000000..1e3b8b8 --- /dev/null +++ b/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-sections.txt
@@ -0,0 +1,161 @@ +<SECTION> +<FILE>ExampleAnimal</FILE> +<TITLE>ExampleAnimal</TITLE> +ExampleAnimal +ExampleAnimalIface +example_animal_interface_info +example_animal_override_properties +example_animal_call_poke +example_animal_call_poke_finish +example_animal_call_poke_sync +example_animal_complete_poke +example_animal_emit_jumped +example_animal_get_mood +example_animal_get_foo +example_animal_get_bar +example_animal_dup_mood +example_animal_dup_foo +example_animal_dup_bar +example_animal_set_mood +example_animal_set_foo +example_animal_set_bar +ExampleAnimalProxy +ExampleAnimalProxyClass +example_animal_proxy_new +example_animal_proxy_new_finish +example_animal_proxy_new_sync +example_animal_proxy_new_for_bus +example_animal_proxy_new_for_bus_finish +example_animal_proxy_new_for_bus_sync +ExampleAnimalSkeleton +ExampleAnimalSkeletonClass +example_animal_skeleton_new +<SUBSECTION Standard> +example_animal_get_type +example_animal_proxy_get_type +example_animal_skeleton_get_type +ExampleAnimalSkeletonPrivate +ExampleAnimalProxyPrivate +EXAMPLE_TYPE_ANIMAL +EXAMPLE_TYPE_ANIMAL_PROXY +EXAMPLE_TYPE_ANIMAL_SKELETON +EXAMPLE_ANIMAL +EXAMPLE_ANIMAL_GET_IFACE +EXAMPLE_ANIMAL_PROXY +EXAMPLE_ANIMAL_PROXY_CLASS +EXAMPLE_ANIMAL_PROXY_GET_CLASS +EXAMPLE_ANIMAL_SKELETON +EXAMPLE_ANIMAL_SKELETON_CLASS +EXAMPLE_ANIMAL_SKELETON_GET_CLASS +EXAMPLE_IS_ANIMAL +EXAMPLE_IS_ANIMAL_PROXY +EXAMPLE_IS_ANIMAL_PROXY_CLASS +EXAMPLE_IS_ANIMAL_SKELETON +EXAMPLE_IS_ANIMAL_SKELETON_CLASS +</SECTION> + +<SECTION> +<FILE>ExampleCat</FILE> +<TITLE>ExampleCat</TITLE> +ExampleCat +ExampleCatIface +example_cat_interface_info +example_cat_override_properties +ExampleCatProxy +ExampleCatProxyClass +example_cat_proxy_new +example_cat_proxy_new_finish +example_cat_proxy_new_sync +example_cat_proxy_new_for_bus +example_cat_proxy_new_for_bus_finish +example_cat_proxy_new_for_bus_sync +ExampleCatSkeleton +ExampleCatSkeletonClass +example_cat_skeleton_new +<SUBSECTION Standard> +example_cat_get_type +example_cat_proxy_get_type +example_cat_skeleton_get_type +ExampleCatProxyPrivate +ExampleCatSkeletonPrivate +EXAMPLE_TYPE_CAT +EXAMPLE_TYPE_CAT_PROXY +EXAMPLE_TYPE_CAT_SKELETON +EXAMPLE_CAT +EXAMPLE_CAT_GET_IFACE +EXAMPLE_CAT_PROXY +EXAMPLE_CAT_PROXY_CLASS +EXAMPLE_CAT_PROXY_GET_CLASS +EXAMPLE_CAT_SKELETON +EXAMPLE_CAT_SKELETON_CLASS +EXAMPLE_CAT_SKELETON_GET_CLASS +EXAMPLE_IS_CAT +EXAMPLE_IS_CAT_PROXY +EXAMPLE_IS_CAT_PROXY_CLASS +EXAMPLE_IS_CAT_SKELETON +EXAMPLE_IS_CAT_SKELETON_CLASS +</SECTION> + +<SECTION> +<FILE>ExampleObject</FILE> +<TITLE>ExampleObject</TITLE> +ExampleObject +ExampleObjectIface +example_object_get_animal +example_object_get_cat +example_object_peek_animal +example_object_peek_cat +ExampleObjectProxy +ExampleObjectProxyClass +example_object_proxy_new +ExampleObjectSkeleton +ExampleObjectSkeletonClass +example_object_skeleton_new +example_object_skeleton_set_animal +example_object_skeleton_set_cat +<SUBSECTION Standard> +example_object_get_type +example_object_proxy_get_type +example_object_skeleton_get_type +ExampleObjectProxyPrivate +ExampleObjectSkeletonPrivate +EXAMPLE_IS_OBJECT +EXAMPLE_IS_OBJECT_PROXY +EXAMPLE_IS_OBJECT_PROXY_CLASS +EXAMPLE_IS_OBJECT_SKELETON +EXAMPLE_IS_OBJECT_SKELETON_CLASS +EXAMPLE_OBJECT +EXAMPLE_OBJECT_GET_IFACE +EXAMPLE_OBJECT_PROXY +EXAMPLE_OBJECT_PROXY_CLASS +EXAMPLE_OBJECT_PROXY_GET_CLASS +EXAMPLE_OBJECT_SKELETON +EXAMPLE_OBJECT_SKELETON_CLASS +EXAMPLE_OBJECT_SKELETON_GET_CLASS +EXAMPLE_TYPE_OBJECT +EXAMPLE_TYPE_OBJECT_PROXY +EXAMPLE_TYPE_OBJECT_SKELETON +</SECTION> + +<SECTION> +<FILE>ExampleObjectManagerClient</FILE> +<TITLE>ExampleObjectManagerClient</TITLE> +ExampleObjectManagerClient +ExampleObjectManagerClientClass +example_object_manager_client_get_proxy_type +example_object_manager_client_new +example_object_manager_client_new_finish +example_object_manager_client_new_sync +example_object_manager_client_new_for_bus +example_object_manager_client_new_for_bus_finish +example_object_manager_client_new_for_bus_sync +<SUBSECTION Standard> +example_object_manager_client_get_type +EXAMPLE_IS_OBJECT_MANAGER_CLIENT +EXAMPLE_IS_OBJECT_MANAGER_CLIENT_CLASS +EXAMPLE_OBJECT_MANAGER_CLIENT +EXAMPLE_OBJECT_MANAGER_CLIENT_CLASS +EXAMPLE_OBJECT_MANAGER_CLIENT_GET_CLASS +EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT +ExampleObjectManagerClientPrivate +</SECTION>
diff --git a/docs/reference/gio/gdbus-object-manager-example/meson.build b/docs/reference/gio/gdbus-object-manager-example/meson.build new file mode 100644 index 0000000..13cae5b --- /dev/null +++ b/docs/reference/gio/gdbus-object-manager-example/meson.build
@@ -0,0 +1,11 @@ +gdbus_object_manager_example_doc = gnome.gtkdoc('gdbus-object-manager-example', + main_xml : 'gdbus-object-manager-example-docs.xml', + namespace : 'example', + dependencies : [libgdbus_example_objectmanager_dep], + src_dir : 'gio/tests/gdbus-object-manager-example', + scan_args : gtkdoc_common_scan_args + [ + '--rebuild-types', + ], + install : false, +) +
diff --git a/docs/reference/gio/gdbus.xml b/docs/reference/gio/gdbus.xml new file mode 100644 index 0000000..0e6c14d --- /dev/null +++ b/docs/reference/gio/gdbus.xml
@@ -0,0 +1,416 @@ +<refentry id="gdbus" lang="en"> + +<refentryinfo> + <title>gdbus</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>David</firstname> + <surname>Zeuthen</surname> + <email>zeuthen@gmail.com</email> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> + <refentrytitle>gdbus</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> + <refname>gdbus</refname> + <refpurpose>Tool for working with D-Bus objects</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>gdbus</command> + <arg choice="plain">introspect</arg> + <group> + <arg choice="plain">--system</arg> + <arg choice="plain">--session</arg> + <arg choice="plain">--address <replaceable>address</replaceable></arg> + </group> + <arg choice="plain">--dest <replaceable>bus_name</replaceable></arg> + <arg choice="plain">--object-path <replaceable>/path/to/object</replaceable></arg> + <group> + <arg choice="plain">--xml</arg> + </group> + <group> + <arg choice="plain">--recurse</arg> + </group> + <group> + <arg choice="plain">--only-properties</arg> + </group> + </cmdsynopsis> + <cmdsynopsis> + <command>gdbus</command> + <arg choice="plain">monitor</arg> + <group> + <arg choice="plain">--system</arg> + <arg choice="plain">--session</arg> + <arg choice="plain">--address <replaceable>address</replaceable></arg> + </group> + <arg choice="plain">--dest <replaceable>bus_name</replaceable></arg> + <group> + <arg choice="plain">--object-path <replaceable>/path/to/object</replaceable></arg> + </group> + </cmdsynopsis> + <cmdsynopsis> + <command>gdbus</command> + <arg choice="plain">call</arg> + <group> + <arg choice="plain">--system</arg> + <arg choice="plain">--session</arg> + <arg choice="plain">--address <replaceable>address</replaceable></arg> + </group> + <arg choice="plain">--dest <replaceable>bus_name</replaceable></arg> + <arg choice="plain">--object-path <replaceable>/path/to/object</replaceable></arg> + <arg choice="plain">--method <replaceable>org.project.InterfaceName.MethodName</replaceable></arg> + <group> + <arg choice="plain">--timeout <replaceable>seconds</replaceable></arg> + </group> + <arg choice="plain">ARG1</arg> + <arg choice="plain" rep="repeat">ARG2</arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gdbus</command> + <arg choice="plain">emit</arg> + <group> + <arg choice="plain">--system</arg> + <arg choice="plain">--session</arg> + <arg choice="plain">--address <replaceable>address</replaceable></arg> + </group> + <arg choice="plain">--object-path <replaceable>/path/to/object</replaceable></arg> + <arg choice="plain">--signal <replaceable>org.project.InterfaceName.SignalName</replaceable></arg> + <group> + <arg choice="plain">--dest <replaceable>unique_bus_name</replaceable></arg> + </group> + <arg choice="plain">ARG1</arg> + <arg choice="plain" rep="repeat">ARG2</arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gdbus</command> + <arg choice="plain">wait</arg> + <group> + <arg choice="plain">--system</arg> + <arg choice="plain">--session</arg> + <arg choice="plain">--address <replaceable>address</replaceable></arg> + </group> + <arg choice="plain">--activate <replaceable>bus_name</replaceable></arg> + <group> + <arg choice="plain">--timeout <replaceable>seconds</replaceable></arg> + </group> + <arg choice="plain"><replaceable>bus_name</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gdbus</command> + <arg choice="plain">help</arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1> + <title>Description</title> + <para> + <command>gdbus</command> is a simple tool for working with D-Bus objects. + </para> +</refsect1> +<refsect1> + <title>Commands</title> + <variablelist> + <varlistentry> + <term><option>introspect</option></term> + <listitem><para> + Prints out interfaces and property values for a remote object. + For this to work, the owner of the object needs to implement the + <literal>org.freedesktop.DBus.Introspectable</literal> interface. + If the <option>--xml</option> option is used, the returned + introspection XML is printed, otherwise a parsed pretty + representation is printed. + The <option>--recurse</option> option can be used to + introspect children (and their children and so on) and the + <option>--only-properties</option> option can be used to + only print the interfaces with properties. + </para></listitem> + </varlistentry> + <varlistentry> + <term><option>monitor</option></term> + <listitem><para> + Monitors one or all objects owned by the owner of + <replaceable>bus_name</replaceable>. + </para></listitem> + </varlistentry> + <varlistentry> + <term><option>call</option></term> + <listitem><para> + Invokes a method on a remote object. Each argument to pass to the + method must be specified as a serialized + <link linkend="GVariant"><type>GVariant</type></link> except that strings do + not need explicit quotes. The return values are printed out as + serialized <link linkend="GVariant"><type>GVariant</type></link> + values. + </para></listitem> + </varlistentry> + <varlistentry> + <term><option>emit</option></term> + <listitem><para> + Emits a signal. Each argument to include in the signal must be specified as a serialized + <link linkend="GVariant"><type>GVariant</type></link> except that strings do + not need explicit quotes. + </para></listitem> + </varlistentry> + <varlistentry> + <term><option>wait</option></term> + <listitem><para> + Waits until <replaceable>bus_name</replaceable> is owned by some + process on the bus. If the <option>--activate</option> is specified, + that bus name will be auto-started first. It may be the same as the + bus name being waited for, or different. + </para></listitem> + </varlistentry> + <varlistentry> + <term><option>help</option></term> + <listitem><para> + Prints help and exit. + </para></listitem> + </varlistentry> + </variablelist> +</refsect1> + +<refsect1> + <title>Bash Completion</title> + <para> + <command>gdbus</command> ships with a bash completion script to + complete commands, destinations, bus names, object paths and + interface/method names. + </para> +</refsect1> + +<refsect1> + <title>Examples</title> + This shows how to introspect an object - note that the value of each + property is displayed: +<programlisting> +$ gdbus introspect --system \ + --dest org.freedesktop.NetworkManager \ + --object-path /org/freedesktop/NetworkManager/Devices/0 +node /org/freedesktop/NetworkManager/Devices/0 { + interface org.freedesktop.DBus.Introspectable { + methods: + Introspect(out s data); + }; + interface org.freedesktop.DBus.Properties { + methods: + Get(in s interface, + in s propname, + out v value); + Set(in s interface, + in s propname, + in v value); + GetAll(in s interface, + out a{sv} props); + }; + interface org.freedesktop.NetworkManager.Device.Wired { + signals: + PropertiesChanged(a{sv} arg_0); + properties: + readonly b Carrier = false; + readonly u Speed = 0; + readonly s HwAddress = '00:1D:72:88:BE:97'; + }; + interface org.freedesktop.NetworkManager.Device { + methods: + Disconnect(); + signals: + StateChanged(u arg_0, + u arg_1, + u arg_2); + properties: + readonly u DeviceType = 1; + readonly b Managed = true; + readwrite o Ip6Config = '/'; + readwrite o Dhcp4Config = '/'; + readwrite o Ip4Config = '/'; + readonly u State = 2; + readwrite u Ip4Address = 0; + readonly u Capabilities = 3; + readonly s Driver = 'e1000e'; + readwrite s Interface = 'eth0'; + readonly s Udi = '/sys/devices/pci0000:00/0000:00:19.0/net/eth0'; + }; +}; +</programlisting> +<para> + The <option>--recurse</option> and <option>--only-properties</option> options can be useful when wanting to inspect all objects owned by a particular process: +</para> +<programlisting> +$ gdbus introspect --system --dest org.freedesktop.UPower --object-path / --recurse --only-properties +node / { + node /org { + node /org/freedesktop { + node /org/freedesktop/UPower { + interface org.freedesktop.UPower { + properties: + readonly b IsDocked = true; + readonly b LidForceSleep = false; + readonly b LidIsPresent = false; + readonly b LidIsClosed = false; + readonly b OnLowBattery = false; + readonly b OnBattery = false; + readonly b CanHibernate = true; + readonly b CanSuspend = true; + readonly s DaemonVersion = '0.9.10'; + }; + node /org/freedesktop/UPower/Policy { + }; + node /org/freedesktop/UPower/Wakeups { + interface org.freedesktop.UPower.Wakeups { + properties: + readonly b HasCapability = true; + }; + }; + }; + }; + }; +}; +</programlisting> +<para> + In a similar fashion, the <option>introspect</option> command can be + used to learn details about the <literal>Notify</literal> method: +</para> +<programlisting> +[...] + interface org.freedesktop.Notifications { + methods: + GetServerInformation(out s return_name, + out s return_vendor, + out s return_version, + out s return_spec_version); + GetCapabilities(out as return_caps); + CloseNotification(in u id); + Notify(in s app_name, + in u id, + in s icon, + in s summary, + in s body, + in as actions, + in a{sv} hints, + in i timeout, + out u return_id); + }; +[...] +</programlisting> +<para> + With this information, it's easy to use the <option>call</option> + command to display a notification +</para> +<programlisting> +$ gdbus call --session \ + --dest org.freedesktop.Notifications \ + --object-path /org/freedesktop/Notifications \ + --method org.freedesktop.Notifications.Notify \ + my_app_name \ + 42 \ + gtk-dialog-info \ + "The Summary" \ + "Here's the body of the notification" \ + [] \ + {} \ + 5000 +(uint32 12,) +</programlisting> +<para> + Monitoring all objects on a service: +</para> +<programlisting> +$ gdbus monitor --system --dest org.freedesktop.ConsoleKit +Monitoring signals from all objects owned by org.freedesktop.ConsoleKit +The name org.freedesktop.ConsoleKit is owned by :1.15 +/org/freedesktop/ConsoleKit/Session2: org.freedesktop.ConsoleKit.Session.ActiveChanged (false,) +/org/freedesktop/ConsoleKit/Seat1: org.freedesktop.ConsoleKit.Seat.ActiveSessionChanged ('',) +/org/freedesktop/ConsoleKit/Session2: org.freedesktop.ConsoleKit.Session.ActiveChanged (true,) +/org/freedesktop/ConsoleKit/Seat1: org.freedesktop.ConsoleKit.Seat.ActiveSessionChanged ('/org/freedesktop/ConsoleKit/Session2',) +</programlisting> +<para> + Monitoring a single object on a service: +</para> +<programlisting> +$ gdbus monitor --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager/AccessPoint/4141 +Monitoring signals on object /org/freedesktop/NetworkManager/AccessPoint/4141 owned by org.freedesktop.NetworkManager +The name org.freedesktop.NetworkManager is owned by :1.5 +/org/freedesktop/NetworkManager/AccessPoint/4141: org.freedesktop.NetworkManager.AccessPoint.PropertiesChanged ({'Strength': <byte 0x5c>},) +/org/freedesktop/NetworkManager/AccessPoint/4141: org.freedesktop.NetworkManager.AccessPoint.PropertiesChanged ({'Strength': <byte 0x64>},) +/org/freedesktop/NetworkManager/AccessPoint/4141: org.freedesktop.NetworkManager.AccessPoint.PropertiesChanged ({'Strength': <byte 0x5e>},) +/org/freedesktop/NetworkManager/AccessPoint/4141: org.freedesktop.NetworkManager.AccessPoint.PropertiesChanged ({'Strength': <byte 0x64>},) +</programlisting> + +<para> + Emitting a signal: +</para> +<programlisting> +$ gdbus emit --session --object-path /foo --signal org.bar.Foo "['foo', 'bar', 'baz']" +</programlisting> + +<para> + Emitting a signal to a specific process: +</para> +<programlisting> +$ gdbus emit --session --object-path /bar --signal org.bar.Bar someString --dest :1.42 +</programlisting> + +<para> + Waiting for a well-known name to be owned on the bus; this will + <emphasis>not</emphasis> auto-start the service: +</para> +<programlisting> +$ gdbus wait --session org.bar.SomeName +</programlisting> + +<para> + Auto-starting then waiting for a well-known name to be owned on the bus: +</para> +<programlisting> +$ gdbus wait --session --activate org.bar.SomeName +</programlisting> + +<para> + Auto-starting a different service, then waiting for a well-known name to be + owned on the bus. This is useful in situations where + <replaceable>SomeName</replaceable> is not directly activatable: +</para> +<programlisting> +$ gdbus wait --session --activate org.bar.PrerequisiteName org.bar.SomeName +</programlisting> + +<para> + Waiting for a well-known name and giving up after 30 seconds. By default, + the timeout is disabled; or set <option>--timeout</option> to 0 to disable it: +</para> +<programlisting> +$ gdbus wait --session --timeout 30 org.bar.SomeName +</programlisting> + +</refsect1> + +<refsect1> + <title>Bugs</title> + <para> + Please send bug reports to either the distribution bug tracker + or the upstream bug tracker at + <ulink url="https://gitlab.gnome.org/GNOME/glib/issues/new"/>. + </para> +</refsect1> + +<refsect1> + <title>See Also</title> + <para> + <citerefentry> + <refentrytitle>dbus-send</refentrytitle><manvolnum>1</manvolnum> + </citerefentry> + </para> +</refsect1> + +</refentry> +
diff --git a/docs/reference/gio/gio-docs-unix.xml b/docs/reference/gio/gio-docs-unix.xml new file mode 100644 index 0000000..b78edda --- /dev/null +++ b/docs/reference/gio/gio-docs-unix.xml
@@ -0,0 +1,3 @@ +<chapter id='unix-support'> +<!--FIXME: fill this with unix APIs that cannot build on Windows --> +</chapter>
diff --git a/docs/reference/gio/gio-docs-win32.xml b/docs/reference/gio/gio-docs-win32.xml new file mode 100644 index 0000000..f34a6e6 --- /dev/null +++ b/docs/reference/gio/gio-docs-win32.xml
@@ -0,0 +1,6 @@ +<chapter id='win32-support'> + <title>Win32 support</title> + <xi:include href="xml/gwin32registrykey.xml"/> + <xi:include href="xml/gwin32inputstream.xml"/> + <xi:include href="xml/gwin32outputstream.xml"/> +</chapter>
diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml new file mode 100644 index 0000000..565c20c --- /dev/null +++ b/docs/reference/gio/gio-docs.xml
@@ -0,0 +1,391 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.5//EN' + 'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd' [ +<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'"> +<!ENTITY version SYSTEM "version.xml"> +]> +<book lang="en" id="gio" xmlns:xi="http://www.w3.org/2003/XInclude"> +<title>GIO Reference Manual</title> + <bookinfo> + <title>GIO Reference Manual</title> + <releaseinfo> + for GIO &version; + The latest version of this documentation can be found on-line at + <ulink role="online-location" url="https://developer.gnome.org/gio/unstable/">https://developer.gnome.org/gio/unstable/</ulink>. + </releaseinfo> + </bookinfo> + + <xi:include href="xml/overview.xml"/> + + <part> + <title>API Reference</title> + <chapter id="file_ops"> + <title>File Operations</title> + <xi:include href="xml/gfile.xml"/> + <xi:include href="xml/gfileattribute.xml"/> + <xi:include href="xml/gfileinfo.xml"/> + <xi:include href="xml/gfileenumerator.xml"/> + <xi:include href="xml/gioerror.xml"/> + <xi:include href="xml/gmountoperation.xml"/> + </chapter> + <chapter id="file_mon"> + <title>File System Monitoring</title> + <xi:include href="xml/gfilemonitor.xml"/> + </chapter> + <chapter id="utils"> + <title>File-related Utilities</title> + <xi:include href="xml/gfilenamecompleter.xml"/> + </chapter> + <chapter id="async"> + <title>Asynchronous I/O</title> + <xi:include href="xml/gcancellable.xml"/> + <xi:include href="xml/gasyncresult.xml"/> + <xi:include href="xml/gtask.xml"/> + <xi:include href="xml/gioscheduler.xml"/> + <xi:include href="xml/gsimpleasyncresult.xml"/> + </chapter> + <chapter id="conversion"> + <title>Data conversion</title> + <xi:include href="xml/gconverter.xml"/> + <xi:include href="xml/gcharsetconverter.xml"/> + <xi:include href="xml/gzcompressor.xml"/> + <xi:include href="xml/gzdecompressor.xml"/> + </chapter> + <chapter id="streaming"> + <title>Streaming I/O</title> + <xi:include href="xml/gseekable.xml"/> + <xi:include href="xml/ginputstream.xml"/> + <xi:include href="xml/goutputstream.xml"/> + <xi:include href="xml/giostream.xml"/> + <xi:include href="xml/gsimpleiostream.xml"/> + <xi:include href="xml/gfileinputstream.xml"/> + <xi:include href="xml/gfileoutputstream.xml"/> + <xi:include href="xml/gfileiostream.xml"/> + <xi:include href="xml/gfiledescriptorbased.xml"/> + <xi:include href="xml/gfilterinputstream.xml"/> + <xi:include href="xml/gfilteroutputstream.xml"/> + <xi:include href="xml/gmemoryinputstream.xml"/> + <xi:include href="xml/gmemoryoutputstream.xml"/> + <xi:include href="xml/gbufferedinputstream.xml"/> + <xi:include href="xml/gbufferedoutputstream.xml"/> + <xi:include href="xml/gdatainputstream.xml"/> + <xi:include href="xml/gdataoutputstream.xml"/> + <xi:include href="xml/gunixinputstream.xml"/> + <xi:include href="xml/gunixoutputstream.xml"/> + <xi:include href="xml/gconverterinputstream.xml"/> + <xi:include href="xml/gconverteroutputstream.xml"/> + <xi:include href="xml/gpollableinputstream.xml"/> + <xi:include href="xml/gpollableoutputstream.xml"/> + <xi:include href="xml/gpollableutils.xml"/> + </chapter> + <chapter id="types"> + <title>File types and applications</title> + <xi:include href="xml/gcontenttype.xml"/> + <xi:include href="xml/gappinfo.xml"/> + <xi:include href="xml/gappinfomonitor.xml"/> + <xi:include href="xml/gdesktopappinfo.xml"/> + </chapter> + <chapter id="volume_mon"> + <title>Volumes and Drives</title> + <xi:include href="xml/gvolumemonitor.xml"/> + <xi:include href="xml/gvolume.xml"/> + <xi:include href="xml/gmount.xml"/> + <xi:include href="xml/gdrive.xml"/> + <xi:include href="xml/gunixmounts.xml"/> + </chapter> + <chapter id="icons"> + <title>Icons</title> + <xi:include href="xml/gicon.xml"/> + <xi:include href="xml/gfileicon.xml"/> + <xi:include href="xml/gbytesicon.xml"/> + <xi:include href="xml/gloadableicon.xml"/> + <xi:include href="xml/gthemedicon.xml"/> + <xi:include href="xml/gemblemedicon.xml"/> + <xi:include href="xml/gemblem.xml"/> + </chapter> + <chapter id="failable_initialization"> + <title>Failable Initialization</title> + <xi:include href="xml/ginitable.xml"/> + <xi:include href="xml/gasyncinitable.xml"/> + </chapter> + <chapter id="subprocesses"> + <title>Subprocesses</title> + <xi:include href="xml/gsubprocess.xml"/> + <xi:include href="xml/gsubprocesslauncher.xml"/> + </chapter> + <chapter id="networking"> + <title>Low-level network support</title> + <xi:include href="xml/gsocket.xml"/> + <xi:include href="xml/gdatagrambased.xml"/> + <xi:include href="xml/ginetaddress.xml"/> + <xi:include href="xml/ginetaddressmask.xml"/> + <xi:include href="xml/gsocketaddress.xml"/> + <xi:include href="xml/ginetsocketaddress.xml"/> + <xi:include href="xml/gunixsocketaddress.xml"/> + <xi:include href="xml/gnativesocketaddress.xml"/> + <xi:include href="xml/gsocketcontrolmessage.xml"/> + <xi:include href="xml/gunixfdlist.xml"/> + <xi:include href="xml/gunixfdmessage.xml"/> + <xi:include href="xml/gcredentials.xml"/> + <xi:include href="xml/gunixcredentialsmessage.xml"/> + <xi:include href="xml/gproxy.xml"/> + <xi:include href="xml/gproxyaddress.xml"/> + <xi:include href="xml/gnetworking.xml"/> + </chapter> + <chapter id="highlevel-socket"> + <title>High-level network functionality</title> + <xi:include href="xml/gsocketclient.xml"/> + <xi:include href="xml/gsocketconnection.xml"/> + <xi:include href="xml/gunixconnection.xml"/> + <xi:include href="xml/gtcpconnection.xml"/> + <xi:include href="xml/gtcpwrapperconnection.xml"/> + <xi:include href="xml/gsocketlistener.xml"/> + <xi:include href="xml/gsocketservice.xml"/> + <xi:include href="xml/gthreadedsocketservice.xml"/> + <xi:include href="xml/gnetworkmonitor.xml"/> + </chapter> + <chapter id="tls"> + <title>TLS (SSL) support</title> + <xi:include href="xml/gtls.xml"/> + <xi:include href="xml/gtlscertificate.xml"/> + <xi:include href="xml/gtlsconnection.xml"/> + <xi:include href="xml/gtlsclientconnection.xml"/> + <xi:include href="xml/gtlsserverconnection.xml"/> + <xi:include href="xml/gdtlsconnection.xml"/> + <xi:include href="xml/gdtlsclientconnection.xml"/> + <xi:include href="xml/gdtlsserverconnection.xml"/> + <xi:include href="xml/gtlsbackend.xml"/> + <xi:include href="xml/gtlsdatabase.xml"/> + <xi:include href="xml/gtlsfiledatabase.xml"/> + <xi:include href="xml/gtlsinteraction.xml"/> + <xi:include href="xml/gtlspassword.xml"/> + </chapter> + <chapter id="resolver"> + <title>DNS resolution</title> + <xi:include href="xml/gresolver.xml"/> + <xi:include href="xml/gproxyresolver.xml"/> + <xi:include href="xml/gsimpleproxyresolver.xml"/> + <xi:include href="xml/gsocketconnectable.xml"/> + <xi:include href="xml/gsocketaddressenumerator.xml"/> + <xi:include href="xml/gproxyaddressenumerator.xml"/> + <xi:include href="xml/gnetworkaddress.xml"/> + <xi:include href="xml/gnetworkservice.xml"/> + <xi:include href="xml/gsrvtarget.xml"/> + </chapter> + <chapter id="gdbus-lowlevel"> + <title>Low-level D-Bus Support</title> + <xi:include href="xml/gdbusutils.xml"/> + <xi:include href="xml/gdbusaddress.xml"/> + <xi:include href="xml/gdbusintrospection.xml"/> + <xi:include href="xml/gdbuserror.xml"/> + <xi:include href="xml/gdbusmessage.xml"/> + <xi:include href="xml/gdbusconnection.xml"/> + <xi:include href="xml/gdbusmethodinvocation.xml"/> + <xi:include href="xml/gdbusserver.xml"/> + <xi:include href="xml/gdbusauthobserver.xml"/> + </chapter> + <chapter id="gdbus-convenience"> + <title>High-level D-Bus Support</title> + <xi:include href="xml/gdbusnameowning.xml"/> + <xi:include href="xml/gdbusnamewatching.xml"/> + <xi:include href="xml/gdbusinterface.xml"/> + <xi:include href="xml/gdbusinterfaceskeleton.xml"/> + <xi:include href="xml/gdbusproxy.xml"/> + <xi:include href="xml/gdbusobject.xml"/> + <xi:include href="xml/gdbusobjectskeleton.xml"/> + <xi:include href="xml/gdbusobjectproxy.xml"/> + <xi:include href="xml/gdbusobjectmanager.xml"/> + <xi:include href="xml/gdbusobjectmanagerserver.xml"/> + <xi:include href="xml/gdbusobjectmanagerclient.xml"/> + </chapter> + <chapter id="settings"> + <title>Settings</title> + <xi:include href="xml/gsettings.xml"/> + <xi:include href="xml/gsettingsbackend.xml"/> + <xi:include href="xml/gsettingsschema.xml"/> + </chapter> + <chapter id="resources"> + <title>Resources</title> + <xi:include href="xml/gresource.xml"/> + </chapter> + <chapter id='permissions'> + <title>Permissions</title> + <xi:include href="xml/gpermission.xml"/> + <xi:include href="xml/gsimplepermission.xml"/> + </chapter> + <chapter id='data-models'> + <title>Data Models</title> + <xi:include href="xml/glistmodel.xml"/> + <xi:include href="xml/gliststore.xml"/> + </chapter> + + <chapter id="application"> + <title>Application support</title> + <xi:include href="xml/gapplication.xml"/> + <xi:include href="xml/gapplicationcommandline.xml"/> + <xi:include href="xml/gactiongroup.xml"/> + <xi:include href="xml/gactionmap.xml"/> + <xi:include href="xml/gsimpleactiongroup.xml"/> + <xi:include href="xml/gaction.xml"/> + <xi:include href="xml/gsimpleaction.xml"/> + <xi:include href="xml/gpropertyaction.xml"/> + <xi:include href="xml/gremoteactiongroup.xml"/> + <xi:include href="xml/gactiongroupexporter.xml"/> + <xi:include href="xml/gdbusactiongroup.xml"/> + <xi:include href="xml/gmemorymonitor.xml"/> + <xi:include href="xml/gmenumodel.xml"/> + <xi:include href="xml/gmenu.xml"/> + <xi:include href="xml/gmenuexporter.xml"/> + <xi:include href="xml/gdbusmenumodel.xml"/> + <xi:include href="xml/gnotification.xml"/> + </chapter> + <chapter id="extending"> + <title>Extending GIO</title> + <xi:include href="xml/gvfs.xml"/> + <xi:include href="xml/giomodule.xml"/> + <xi:include href="xml/extensionpoints.xml"/> + </chapter> + <chapter id="tools"> + <title>GIO Tools</title> + <xi:include href="gio-querymodules.xml"/> + <xi:include href="gsettings.xml"/> + <xi:include href="glib-compile-schemas.xml"/> + <xi:include href="glib-compile-resources.xml"/> + <xi:include href="gdbus.xml"/> + <xi:include href="xml/gdbus-codegen.xml"/> + <xi:include href="gresource.xml"/> + <xi:include href="gapplication.xml"/> + <xi:include href="gio.xml"/> + </chapter> + <chapter id="testing"> + <title>GIO Testing</title> + <xi:include href="xml/gtestdbus.xml"/> + </chapter> + <xi:include href="gio-docs-platform.xml"/> + </part> + + <part id="migrating"> + <title>Migrating to GIO</title> + <xi:include href="xml/migrating-posix.xml"/> + <xi:include href="xml/migrating-gnome-vfs.xml"/> + <xi:include href="xml/migrating-gconf.xml"/> + <xi:include href="xml/migrating-gdbus.xml"/> + </part> + + <chapter id="gio-hierarchy"> + <title>Object Hierarchy</title> + <xi:include href="xml/tree_index.sgml"/> + </chapter> + + <index id="api-index-full"> + <title id="index-all">Index</title> + <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-deprecated" role="deprecated"> + <title>Index of deprecated symbols</title> + <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-18" role="2.18"> + <title>Index of new symbols in 2.18</title> + <xi:include href="xml/api-index-2.18.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-20" role="2.20"> + <title>Index of new symbols in 2.20</title> + <xi:include href="xml/api-index-2.20.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-22" role="2.22"> + <title>Index of new symbols in 2.22</title> + <xi:include href="xml/api-index-2.22.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-24" role="2.24"> + <title>Index of new symbols in 2.24</title> + <xi:include href="xml/api-index-2.24.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-26" role="2.26"> + <title>Index of new symbols in 2.26</title> + <xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-28" role="2.28"> + <title>Index of new symbols in 2.28</title> + <xi:include href="xml/api-index-2.28.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-30" role="2.30"> + <title>Index of new symbols in 2.30</title> + <xi:include href="xml/api-index-2.30.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-32" role="2.32"> + <title>Index of new symbols in 2.32</title> + <xi:include href="xml/api-index-2.32.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-34" role="2.34"> + <title>Index of new symbols in 2.34</title> + <xi:include href="xml/api-index-2.34.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-36" role="2.36"> + <title>Index of new symbols in 2.36</title> + <xi:include href="xml/api-index-2.36.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-38" role="2.38"> + <title>Index of new symbols in 2.38</title> + <xi:include href="xml/api-index-2.38.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-40" role="2.40"> + <title>Index of new symbols in 2.40</title> + <xi:include href="xml/api-index-2.40.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-42" role="2.42"> + <title>Index of new symbols in 2.42</title> + <xi:include href="xml/api-index-2.42.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-44" role="2.44"> + <title>Index of new symbols in 2.44</title> + <xi:include href="xml/api-index-2.44.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-46" role="2.46"> + <title>Index of new symbols in 2.46</title> + <xi:include href="xml/api-index-2.46.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-48" role="2.48"> + <title>Index of new symbols in 2.48</title> + <xi:include href="xml/api-index-2.48.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-50" role="2.50"> + <title>Index of new symbols in 2.50</title> + <xi:include href="xml/api-index-2.50.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-52" role="2.52"> + <title>Index of new symbols in 2.52</title> + <xi:include href="xml/api-index-2.52.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-54" role="2.54"> + <title>Index of new symbols in 2.54</title> + <xi:include href="xml/api-index-2.54.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-56" role="2.56"> + <title>Index of new symbols in 2.56</title> + <xi:include href="xml/api-index-2.56.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-58" role="2.58"> + <title>Index of new symbols in 2.58</title> + <xi:include href="xml/api-index-2.58.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-60" role="2.60"> + <title>Index of new symbols in 2.60</title> + <xi:include href="xml/api-index-2.60.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-62" role="2.62"> + <title>Index of new symbols in 2.62</title> + <xi:include href="xml/api-index-2.62.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-64" role="2.64"> + <title>Index of new symbols in 2.64</title> + <xi:include href="xml/api-index-2.64.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-66" role="2.66"> + <title>Index of new symbols in 2.66</title> + <xi:include href="xml/api-index-2.66.xml"><xi:fallback /></xi:include> + </index> + + <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> + +</book>
diff --git a/docs/reference/gio/gio-querymodules.xml b/docs/reference/gio/gio-querymodules.xml new file mode 100644 index 0000000..c9c5eec --- /dev/null +++ b/docs/reference/gio/gio-querymodules.xml
@@ -0,0 +1,45 @@ +<refentry id="gio-querymodules" lang="en"> + +<refentryinfo> + <title>glib-compile-schemas</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Alexander</firstname> + <surname>Larsson</surname> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> + <refentrytitle>gio-querymodules</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> + <refname>gio-querymodules</refname> + <refpurpose>GIO module cache creation</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>gio-querymodules</command> + <arg choice="req" rep="repeat">DIRECTORY</arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>gio-querymodules</command> creates a +<filename>giomodule.cache</filename> file in the listed directories. +This file lists the implemented extension points for each module +that has been found. It is used by GIO at runtime to avoid opening +all modules just to find out which extension points they are implementing. +</para> +<para> +GIO modules are usually installed in the <filename>gio/modules</filename> +subdirectory of libdir. +</para> +</refsect1> +</refentry>
diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt new file mode 100644 index 0000000..cd62b8a --- /dev/null +++ b/docs/reference/gio/gio-sections-common.txt
@@ -0,0 +1,4683 @@ +<SECTION> +<FILE>ginitable</FILE> +<TITLE>GInitable</TITLE> +GInitable +GInitableIface +g_initable_init +g_initable_new +g_initable_new_valist +g_initable_newv +<SUBSECTION Standard> +G_INITABLE +G_INITABLE_GET_IFACE +G_IS_INITABLE +G_TYPE_INITABLE +G_TYPE_IS_INITABLE +<SUBSECTION Private> +g_initable_get_type +</SECTION> + +<SECTION> +<FILE>gasyncinitable</FILE> +<TITLE>GAsyncInitable</TITLE> +GAsyncInitable +GAsyncInitableIface +g_async_initable_init_async +g_async_initable_init_finish +g_async_initable_new_async +g_async_initable_new_finish +g_async_initable_new_valist_async +g_async_initable_newv_async +<SUBSECTION Standard> +G_ASYNC_INITABLE +G_ASYNC_INITABLE_GET_IFACE +G_IS_ASYNC_INITABLE +G_TYPE_ASYNC_INITABLE +G_TYPE_IS_ASYNC_INITABLE +<SUBSECTION Private> +g_async_initable_get_type +</SECTION> + +<SECTION> +<FILE>gvfs</FILE> +<TITLE>GVfs</TITLE> +GVfs +GVfsFileLookupFunc +G_VFS_EXTENSION_POINT_NAME +g_vfs_get_file_for_path +g_vfs_get_file_for_uri +g_vfs_parse_name +g_vfs_get_default +g_vfs_get_local +g_vfs_is_active +g_vfs_get_supported_uri_schemes +g_vfs_register_uri_scheme +g_vfs_unregister_uri_scheme +<SUBSECTION Standard> +GVfsClass +G_VFS +G_IS_VFS +G_TYPE_VFS +G_VFS_CLASS +G_IS_VFS_CLASS +G_VFS_GET_CLASS +<SUBSECTION Private> +g_vfs_get_type +</SECTION> + +<SECTION> +<FILE>gfile</FILE> +<TITLE>GFile</TITLE> +GFile +GFileIface +GFileQueryInfoFlags +GFileCreateFlags +GFileCopyFlags +GFileMonitorFlags +GFileMeasureFlags +GFilesystemPreviewType +GFileProgressCallback +GFileReadMoreCallback +GFileMeasureProgressCallback +g_file_new_for_path +g_file_new_for_uri +g_file_new_for_commandline_arg +g_file_new_for_commandline_arg_and_cwd +g_file_new_tmp +g_file_parse_name +g_file_new_build_filename +g_file_dup +g_file_hash +g_file_equal +g_file_get_basename +g_file_get_path +g_file_peek_path +g_file_get_uri +g_file_get_parse_name +g_file_get_parent +g_file_has_parent +g_file_get_child +g_file_get_child_for_display_name +g_file_has_prefix +g_file_get_relative_path +g_file_resolve_relative_path +g_file_is_native +g_file_has_uri_scheme +g_file_get_uri_scheme +g_file_read +g_file_read_async +g_file_read_finish +g_file_append_to +g_file_create +g_file_replace +g_file_append_to_async +g_file_append_to_finish +g_file_create_async +g_file_create_finish +g_file_replace_async +g_file_replace_finish +g_file_query_info +g_file_query_info_async +g_file_query_info_finish +g_file_query_exists +g_file_query_file_type +g_file_query_filesystem_info +g_file_query_filesystem_info_async +g_file_query_filesystem_info_finish +g_file_query_default_handler +g_file_query_default_handler_async +g_file_query_default_handler_finish +g_file_measure_disk_usage +g_file_measure_disk_usage_async +g_file_measure_disk_usage_finish +g_file_find_enclosing_mount +g_file_find_enclosing_mount_async +g_file_find_enclosing_mount_finish +g_file_enumerate_children +g_file_enumerate_children_async +g_file_enumerate_children_finish +g_file_set_display_name +g_file_set_display_name_async +g_file_set_display_name_finish +g_file_delete +g_file_delete_async +g_file_delete_finish +g_file_trash +g_file_trash_async +g_file_trash_finish +g_file_copy +g_file_copy_async +g_file_copy_finish +g_file_move +g_file_make_directory +g_file_make_directory_async +g_file_make_directory_finish +g_file_make_directory_with_parents +g_file_make_symbolic_link +g_file_query_settable_attributes +g_file_query_writable_namespaces +g_file_set_attribute +g_file_set_attributes_from_info +g_file_set_attributes_async +g_file_set_attributes_finish +g_file_set_attribute_string +g_file_set_attribute_byte_string +g_file_set_attribute_uint32 +g_file_set_attribute_int32 +g_file_set_attribute_uint64 +g_file_set_attribute_int64 +g_file_mount_mountable +g_file_mount_mountable_finish +g_file_unmount_mountable +g_file_unmount_mountable_finish +g_file_unmount_mountable_with_operation +g_file_unmount_mountable_with_operation_finish +g_file_eject_mountable +g_file_eject_mountable_finish +g_file_eject_mountable_with_operation +g_file_eject_mountable_with_operation_finish +g_file_start_mountable +g_file_start_mountable_finish +g_file_stop_mountable +g_file_stop_mountable_finish +g_file_poll_mountable +g_file_poll_mountable_finish +g_file_mount_enclosing_volume +g_file_mount_enclosing_volume_finish +g_file_monitor_directory +g_file_monitor_file +g_file_monitor +g_file_load_bytes +g_file_load_bytes_async +g_file_load_bytes_finish +g_file_load_contents +g_file_load_contents_async +g_file_load_contents_finish +g_file_load_partial_contents_async +g_file_load_partial_contents_finish +g_file_replace_contents +g_file_replace_contents_async +g_file_replace_contents_bytes_async +g_file_replace_contents_finish +g_file_copy_attributes +g_file_create_readwrite +g_file_create_readwrite_async +g_file_create_readwrite_finish +g_file_open_readwrite +g_file_open_readwrite_async +g_file_open_readwrite_finish +g_file_replace_readwrite +g_file_replace_readwrite_async +g_file_replace_readwrite_finish +g_file_supports_thread_contexts +<SUBSECTION Standard> +G_FILE +G_IS_FILE +G_TYPE_FILE +G_FILE_GET_IFACE +G_TYPE_FILESYSTEM_PREVIEW_TYPE +G_TYPE_FILE_COPY_FLAGS +G_TYPE_FILE_CREATE_FLAGS +G_TYPE_FILE_MEASURE_FLAGS +G_TYPE_FILE_MONITOR_EVENT +G_TYPE_FILE_MONITOR_FLAGS +G_TYPE_FILE_QUERY_INFO_FLAGS +<SUBSECTION Private> +g_file_get_type +g_file_copy_flags_get_type +g_file_create_flags_get_type +g_file_measure_flags_get_type +g_file_monitor_event_get_type +g_file_monitor_flags_get_type +g_file_query_info_flags_get_type +g_filesystem_preview_type_get_type +</SECTION> + +<SECTION> +<FILE>gfileenumerator</FILE> +<TITLE>GFileEnumerator</TITLE> +GFileEnumerator +g_file_enumerator_iterate +g_file_enumerator_next_file +g_file_enumerator_close +g_file_enumerator_next_files_async +g_file_enumerator_next_files_finish +g_file_enumerator_close_async +g_file_enumerator_close_finish +g_file_enumerator_is_closed +g_file_enumerator_has_pending +g_file_enumerator_set_pending +g_file_enumerator_get_container +g_file_enumerator_get_child +<SUBSECTION Standard> +GFileEnumeratorClass +G_FILE_ENUMERATOR +G_IS_FILE_ENUMERATOR +G_TYPE_FILE_ENUMERATOR +G_FILE_ENUMERATOR_CLASS +G_IS_FILE_ENUMERATOR_CLASS +G_FILE_ENUMERATOR_GET_CLASS +<SUBSECTION Private> +g_file_enumerator_get_type +GFileEnumeratorPrivate +</SECTION> + +<SECTION> +<FILE>gfileinfo</FILE> +<TITLE>GFileInfo</TITLE> +GFileAttributeMatcher +GFileType +GFileInfo +G_FILE_ATTRIBUTE_STANDARD_TYPE +G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN +G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP +G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK +G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL +G_FILE_ATTRIBUTE_STANDARD_IS_VOLATILE +G_FILE_ATTRIBUTE_STANDARD_NAME +G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME +G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME +G_FILE_ATTRIBUTE_STANDARD_COPY_NAME +G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION +G_FILE_ATTRIBUTE_STANDARD_ICON +G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON +G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE +G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE +G_FILE_ATTRIBUTE_STANDARD_SIZE +G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE +G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET +G_FILE_ATTRIBUTE_STANDARD_TARGET_URI +G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER +G_FILE_ATTRIBUTE_ETAG_VALUE +G_FILE_ATTRIBUTE_ID_FILE +G_FILE_ATTRIBUTE_ID_FILESYSTEM +G_FILE_ATTRIBUTE_ACCESS_CAN_READ +G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE +G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE +G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE +G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH +G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME +G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT +G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT +G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT +G_FILE_ATTRIBUTE_MOUNTABLE_UNIX_DEVICE +G_FILE_ATTRIBUTE_MOUNTABLE_UNIX_DEVICE_FILE +G_FILE_ATTRIBUTE_MOUNTABLE_HAL_UDI +G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START +G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED +G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP +G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE +G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL +G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC +G_FILE_ATTRIBUTE_TIME_MODIFIED +G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC +G_FILE_ATTRIBUTE_TIME_ACCESS +G_FILE_ATTRIBUTE_TIME_ACCESS_USEC +G_FILE_ATTRIBUTE_TIME_CHANGED +G_FILE_ATTRIBUTE_TIME_CHANGED_USEC +G_FILE_ATTRIBUTE_TIME_CREATED +G_FILE_ATTRIBUTE_TIME_CREATED_USEC +G_FILE_ATTRIBUTE_UNIX_DEVICE +G_FILE_ATTRIBUTE_UNIX_INODE +G_FILE_ATTRIBUTE_UNIX_MODE +G_FILE_ATTRIBUTE_UNIX_NLINK +G_FILE_ATTRIBUTE_UNIX_UID +G_FILE_ATTRIBUTE_UNIX_GID +G_FILE_ATTRIBUTE_UNIX_RDEV +G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE +G_FILE_ATTRIBUTE_UNIX_BLOCKS +G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT +G_FILE_ATTRIBUTE_DOS_IS_ARCHIVE +G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT +G_FILE_ATTRIBUTE_DOS_IS_SYSTEM +G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG +G_FILE_ATTRIBUTE_OWNER_USER +G_FILE_ATTRIBUTE_OWNER_USER_REAL +G_FILE_ATTRIBUTE_OWNER_GROUP +G_FILE_ATTRIBUTE_THUMBNAIL_PATH +G_FILE_ATTRIBUTE_THUMBNAILING_FAILED +G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID +G_FILE_ATTRIBUTE_PREVIEW_ICON +G_FILE_ATTRIBUTE_FILESYSTEM_SIZE +G_FILE_ATTRIBUTE_FILESYSTEM_FREE +G_FILE_ATTRIBUTE_FILESYSTEM_USED +G_FILE_ATTRIBUTE_FILESYSTEM_TYPE +G_FILE_ATTRIBUTE_FILESYSTEM_READONLY +G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW +G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE +G_FILE_ATTRIBUTE_GVFS_BACKEND +G_FILE_ATTRIBUTE_SELINUX_CONTEXT +G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT +G_FILE_ATTRIBUTE_TRASH_ORIG_PATH +G_FILE_ATTRIBUTE_TRASH_DELETION_DATE +G_FILE_ATTRIBUTE_RECENT_MODIFIED +g_file_info_new +g_file_info_dup +g_file_info_copy_into +g_file_info_has_attribute +g_file_info_has_namespace +g_file_info_list_attributes +g_file_info_get_attribute_type +g_file_info_remove_attribute +g_file_info_get_attribute_as_string +g_file_info_get_attribute_data +g_file_info_get_attribute_status +g_file_info_get_attribute_string +g_file_info_get_attribute_stringv +g_file_info_get_attribute_byte_string +g_file_info_get_attribute_boolean +g_file_info_get_attribute_uint32 +g_file_info_get_attribute_int32 +g_file_info_get_attribute_uint64 +g_file_info_get_attribute_int64 +g_file_info_get_attribute_object +g_file_info_set_attribute +g_file_info_set_attribute_status +g_file_info_set_attribute_string +g_file_info_set_attribute_stringv +g_file_info_set_attribute_byte_string +g_file_info_set_attribute_boolean +g_file_info_set_attribute_uint32 +g_file_info_set_attribute_int32 +g_file_info_set_attribute_uint64 +g_file_info_set_attribute_int64 +g_file_info_set_attribute_object +g_file_info_clear_status +g_file_info_get_file_type +g_file_info_get_is_hidden +g_file_info_get_is_backup +g_file_info_get_is_symlink +g_file_info_get_name +g_file_info_get_display_name +g_file_info_get_edit_name +g_file_info_get_icon +g_file_info_get_symbolic_icon +g_file_info_get_content_type +g_file_info_get_size +g_file_info_get_modification_time +g_file_info_get_modification_date_time +g_file_info_get_symlink_target +g_file_info_get_etag +g_file_info_get_sort_order +g_file_info_get_deletion_date +g_file_info_set_attribute_mask +g_file_info_unset_attribute_mask +g_file_info_set_file_type +g_file_info_set_is_hidden +g_file_info_set_is_symlink +g_file_info_set_name +g_file_info_set_display_name +g_file_info_set_edit_name +g_file_info_set_icon +g_file_info_set_symbolic_icon +g_file_info_set_content_type +g_file_info_set_size +g_file_info_set_modification_time +g_file_info_set_modification_date_time +g_file_info_set_symlink_target +g_file_info_set_sort_order +g_file_attribute_matcher_new +g_file_attribute_matcher_ref +g_file_attribute_matcher_subtract +g_file_attribute_matcher_unref +g_file_attribute_matcher_matches +g_file_attribute_matcher_matches_only +g_file_attribute_matcher_enumerate_namespace +g_file_attribute_matcher_enumerate_next +g_file_attribute_matcher_to_string +<SUBSECTION Standard> +GFileInfoClass +G_FILE_INFO +G_IS_FILE_INFO +G_TYPE_FILE_INFO +G_FILE_INFO_CLASS +G_IS_FILE_INFO_CLASS +G_FILE_INFO_GET_CLASS +g_file_attribute_matcher_get_type +G_TYPE_FILE_TYPE +<SUBSECTION Private> +g_file_info_get_type +g_file_type_get_type +</SECTION> + +<SECTION> +<FILE>gfileattribute</FILE> +<TITLE>GFileAttribute</TITLE> +GFileAttributeType +GFileAttributeInfoFlags +GFileAttributeStatus +GFileAttributeInfo +GFileAttributeInfoList +g_file_attribute_info_list_new +g_file_attribute_info_list_ref +g_file_attribute_info_list_unref +g_file_attribute_info_list_dup +g_file_attribute_info_list_lookup +g_file_attribute_info_list_add +<SUBSECTION Standard> +G_TYPE_FILE_ATTRIBUTE_INFO_FLAGS +G_TYPE_FILE_ATTRIBUTE_INFO_LIST +G_TYPE_FILE_ATTRIBUTE_MATCHER +G_TYPE_FILE_ATTRIBUTE_STATUS +G_TYPE_FILE_ATTRIBUTE_TYPE +<SUBSECTION Private> +g_file_attribute_info_list_get_type +g_file_attribute_info_flags_get_type +g_file_attribute_status_get_type +g_file_attribute_type_get_type +</SECTION> + +<SECTION> +<FILE>gfilemonitor</FILE> +<TITLE>GFileMonitor</TITLE> +GFileMonitorEvent +GFileMonitor +g_file_monitor_cancel +g_file_monitor_is_cancelled +g_file_monitor_set_rate_limit +g_file_monitor_emit_event +<SUBSECTION Standard> +GFileMonitorClass +G_FILE_MONITOR +G_IS_FILE_MONITOR +G_TYPE_FILE_MONITOR +G_FILE_MONITOR_CLASS +G_IS_FILE_MONITOR_CLASS +G_FILE_MONITOR_GET_CLASS +<SUBSECTION Private> +g_file_monitor_get_type +GFileMonitorPrivate +</SECTION> + +<SECTION> +<FILE>gicon</FILE> +<TITLE>GIcon</TITLE> +GIcon +GIconIface +g_icon_hash +g_icon_equal +g_icon_to_string +g_icon_new_for_string +g_icon_serialize +g_icon_deserialize +<SUBSECTION Standard> +G_ICON +G_IS_ICON +G_TYPE_ICON +G_ICON_GET_IFACE +<SUBSECTION Private> +g_icon_get_type +</SECTION> + +<SECTION> +<FILE>gthemedicon</FILE> +<TITLE>GThemedIcon</TITLE> +GThemedIcon +g_themed_icon_new +g_themed_icon_new_from_names +g_themed_icon_new_with_default_fallbacks +g_themed_icon_prepend_name +g_themed_icon_append_name +g_themed_icon_get_names +<SUBSECTION Standard> +GThemedIconClass +G_THEMED_ICON +G_IS_THEMED_ICON +G_TYPE_THEMED_ICON +G_THEMED_ICON_CLASS +G_IS_THEMED_ICON_CLASS +G_THEMED_ICON_GET_CLASS +<SUBSECTION Private> +g_themed_icon_get_type +</SECTION> + +<SECTION> +<FILE>gloadableicon</FILE> +<TITLE>GLoadableIcon</TITLE> +GLoadableIcon +GLoadableIconIface +g_loadable_icon_load +g_loadable_icon_load_async +g_loadable_icon_load_finish +<SUBSECTION Standard> +G_LOADABLE_ICON +G_IS_LOADABLE_ICON +G_TYPE_LOADABLE_ICON +G_LOADABLE_ICON_GET_IFACE +<SUBSECTION Private> +g_loadable_icon_get_type +</SECTION> + +<SECTION> +<FILE>gfileicon</FILE> +<TITLE>GFileIcon</TITLE> +GFileIcon +g_file_icon_new +g_file_icon_get_file +<SUBSECTION Standard> +GFileIconClass +G_FILE_ICON +G_IS_FILE_ICON +G_TYPE_FILE_ICON +G_FILE_ICON_CLASS +G_IS_FILE_ICON_CLASS +G_FILE_ICON_GET_CLASS +<SUBSECTION Private> +g_file_icon_get_type +</SECTION> + +<SECTION> +<FILE>gbytesicon</FILE> +<TITLE>GBytesIcon</TITLE> +GBytesIcon +g_bytes_icon_new +g_bytes_icon_get_bytes +<SUBSECTION Standard> +G_BYTES_ICON +G_IS_BYTES_ICON +G_TYPE_BYTES_ICON +<SUBSECTION Private> +g_bytes_icon_get_type +</SECTION> + +<SECTION> +<FILE>gemblemedicon</FILE> +<TITLE>GEmblemedIcon</TITLE> +GEmblemedIcon +g_emblemed_icon_new +g_emblemed_icon_get_icon +g_emblemed_icon_get_emblems +g_emblemed_icon_add_emblem +g_emblemed_icon_clear_emblems +<SUBSECTION Standard> +GEmblemedIconClass +G_EMBLEMED_ICON +G_EMBLEMED_ICON_CLASS +G_EMBLEMED_ICON_GET_CLASS +G_IS_EMBLEMED_ICON +G_IS_EMBLEMED_ICON_CLASS +G_TYPE_EMBLEMED_ICON + +<SUBSECTION Private> +GEmblemedIconPrivate +g_emblemed_icon_get_type +</SECTION> + +<SECTION> +<FILE>gemblem</FILE> +<TITLE>GEmblem</TITLE> +GEmblem +GEmblemOrigin +g_emblem_new +g_emblem_new_with_origin +g_emblem_get_icon +g_emblem_get_origin +<SUBSECTION Private> +GEmblemClass +g_emblem_get_type +G_EMBLEM +G_EMBLEM_CLASS +G_EMBLEM_GET_CLASS +G_IS_EMBLEM +G_IS_EMBLEM_CLASS +G_TYPE_EMBLEM +G_TYPE_EMBLEM_ORIGIN +g_emblem_origin_get_type +</SECTION> + +<SECTION> +<FILE>ginputstream</FILE> +<TITLE>GInputStream</TITLE> +GInputStream +g_input_stream_read +g_input_stream_read_all +g_input_stream_read_all_async +g_input_stream_read_all_finish +g_input_stream_skip +g_input_stream_close +g_input_stream_read_async +g_input_stream_read_finish +g_input_stream_skip_async +g_input_stream_skip_finish +g_input_stream_close_async +g_input_stream_close_finish +g_input_stream_is_closed +g_input_stream_has_pending +g_input_stream_set_pending +g_input_stream_clear_pending +g_input_stream_read_bytes +g_input_stream_read_bytes_async +g_input_stream_read_bytes_finish +<SUBSECTION Standard> +GInputStreamClass +G_INPUT_STREAM +G_IS_INPUT_STREAM +G_TYPE_INPUT_STREAM +G_INPUT_STREAM_CLASS +G_IS_INPUT_STREAM_CLASS +G_INPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_input_stream_get_type +GInputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gfileinputstream</FILE> +<TITLE>GFileInputStream</TITLE> +GFileInputStream +g_file_input_stream_query_info +g_file_input_stream_query_info_async +g_file_input_stream_query_info_finish +<SUBSECTION Standard> +GFileInputStreamClass +G_FILE_INPUT_STREAM +G_IS_FILE_INPUT_STREAM +G_TYPE_FILE_INPUT_STREAM +G_FILE_INPUT_STREAM_CLASS +G_IS_FILE_INPUT_STREAM_CLASS +G_FILE_INPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_file_input_stream_get_type +GFileInputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gfilterinputstream</FILE> +<TITLE>GFilterInputStream</TITLE> +GFilterInputStream +g_filter_input_stream_get_base_stream +g_filter_input_stream_get_close_base_stream +g_filter_input_stream_set_close_base_stream +<SUBSECTION Standard> +GFilterInputStreamClass +G_FILTER_INPUT_STREAM +G_IS_FILTER_INPUT_STREAM +G_TYPE_FILTER_INPUT_STREAM +G_FILTER_INPUT_STREAM_CLASS +G_IS_FILTER_INPUT_STREAM_CLASS +G_FILTER_INPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_filter_input_stream_get_type +</SECTION> + +<SECTION> +<FILE>gunixinputstream</FILE> +<TITLE>GUnixInputStream</TITLE> +GUnixInputStream +g_unix_input_stream_new +g_unix_input_stream_set_close_fd +g_unix_input_stream_get_close_fd +g_unix_input_stream_get_fd +<SUBSECTION Standard> +GUnixInputStreamClass +G_UNIX_INPUT_STREAM +G_IS_UNIX_INPUT_STREAM +G_TYPE_UNIX_INPUT_STREAM +G_UNIX_INPUT_STREAM_CLASS +G_IS_UNIX_INPUT_STREAM_CLASS +G_UNIX_INPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_unix_input_stream_get_type +GUnixInputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gmemoryinputstream</FILE> +<TITLE>GMemoryInputStream</TITLE> +GMemoryInputStream +g_memory_input_stream_new +g_memory_input_stream_new_from_data +g_memory_input_stream_new_from_bytes +g_memory_input_stream_add_data +g_memory_input_stream_add_bytes +<SUBSECTION Standard> +GMemoryInputStreamClass +G_MEMORY_INPUT_STREAM +G_IS_MEMORY_INPUT_STREAM +G_TYPE_MEMORY_INPUT_STREAM +G_MEMORY_INPUT_STREAM_CLASS +G_IS_MEMORY_INPUT_STREAM_CLASS +G_MEMORY_INPUT_STREAM_GET_CLASS +<SUBSECTION Private> +GMemoryInputStreamPrivate +g_memory_input_stream_get_type +</SECTION> + +<SECTION> +<FILE>gdatainputstream</FILE> +<TITLE>GDataInputStream</TITLE> +GDataInputStream +GDataStreamByteOrder +GDataStreamNewlineType +g_data_input_stream_new +g_data_input_stream_set_byte_order +g_data_input_stream_get_byte_order +g_data_input_stream_set_newline_type +g_data_input_stream_get_newline_type +g_data_input_stream_read_byte +g_data_input_stream_read_int16 +g_data_input_stream_read_uint16 +g_data_input_stream_read_int32 +g_data_input_stream_read_uint32 +g_data_input_stream_read_int64 +g_data_input_stream_read_uint64 +g_data_input_stream_read_line +g_data_input_stream_read_line_utf8 +g_data_input_stream_read_line_async +g_data_input_stream_read_line_finish +g_data_input_stream_read_line_finish_utf8 +g_data_input_stream_read_upto +g_data_input_stream_read_upto_async +g_data_input_stream_read_upto_finish +g_data_input_stream_read_until +g_data_input_stream_read_until_async +g_data_input_stream_read_until_finish +<SUBSECTION Standard> +GDataInputStreamClass +G_DATA_INPUT_STREAM +G_IS_DATA_INPUT_STREAM +G_TYPE_DATA_INPUT_STREAM +G_DATA_INPUT_STREAM_CLASS +G_IS_DATA_INPUT_STREAM_CLASS +G_DATA_INPUT_STREAM_GET_CLASS +G_TYPE_DATA_STREAM_BYTE_ORDER +G_TYPE_DATA_STREAM_NEWLINE_TYPE +<SUBSECTION Private> +g_data_input_stream_get_type +GDataInputStreamPrivate +g_data_stream_byte_order_get_type +g_data_stream_newline_type_get_type +</SECTION> + +<SECTION> +<FILE>gbufferedinputstream</FILE> +<TITLE>GBufferedInputStream</TITLE> +GBufferedInputStream +g_buffered_input_stream_new +g_buffered_input_stream_new_sized +g_buffered_input_stream_get_buffer_size +g_buffered_input_stream_set_buffer_size +g_buffered_input_stream_get_available +g_buffered_input_stream_peek_buffer +g_buffered_input_stream_peek +g_buffered_input_stream_fill +g_buffered_input_stream_fill_async +g_buffered_input_stream_fill_finish +g_buffered_input_stream_read_byte +<SUBSECTION Standard> +GBufferedInputStreamClass +G_BUFFERED_INPUT_STREAM +G_IS_BUFFERED_INPUT_STREAM +G_TYPE_BUFFERED_INPUT_STREAM +G_BUFFERED_INPUT_STREAM_CLASS +G_IS_BUFFERED_INPUT_STREAM_CLASS +G_BUFFERED_INPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_buffered_input_stream_get_type +GBufferedInputStreamPrivate +</SECTION> + +<SECTION> +<FILE>goutputstream</FILE> +<TITLE>GOutputStream</TITLE> +GOutputStreamSpliceFlags +GOutputStream +g_output_stream_write +g_output_stream_write_all +g_output_stream_write_all_async +g_output_stream_write_all_finish +g_output_stream_writev +g_output_stream_writev_all +g_output_stream_writev_async +g_output_stream_writev_finish +g_output_stream_writev_all_async +g_output_stream_writev_all_finish +g_output_stream_splice +g_output_stream_flush +g_output_stream_close +g_output_stream_write_async +g_output_stream_write_finish +g_output_stream_splice_async +g_output_stream_splice_finish +g_output_stream_flush_async +g_output_stream_flush_finish +g_output_stream_close_async +g_output_stream_close_finish +g_output_stream_is_closing +g_output_stream_is_closed +g_output_stream_has_pending +g_output_stream_set_pending +g_output_stream_clear_pending +g_output_stream_write_bytes +g_output_stream_write_bytes_async +g_output_stream_write_bytes_finish +g_output_stream_printf +g_output_stream_vprintf +<SUBSECTION Standard> +GOutputStreamClass +G_OUTPUT_STREAM +G_IS_OUTPUT_STREAM +G_TYPE_OUTPUT_STREAM +G_OUTPUT_STREAM_CLASS +G_IS_OUTPUT_STREAM_CLASS +G_OUTPUT_STREAM_GET_CLASS +G_TYPE_OUTPUT_STREAM_SPLICE_FLAGS +<SUBSECTION Private> +g_output_stream_get_type +GOutputStreamPrivate +g_output_stream_splice_flags_get_type +</SECTION> + +<SECTION> +<FILE>gfileoutputstream</FILE> +<TITLE>GFileOutputStream</TITLE> +GFileOutputStream +g_file_output_stream_query_info +g_file_output_stream_query_info_async +g_file_output_stream_query_info_finish +g_file_output_stream_get_etag +<SUBSECTION Standard> +GFileOutputStreamClass +G_FILE_OUTPUT_STREAM +G_IS_FILE_OUTPUT_STREAM +G_TYPE_FILE_OUTPUT_STREAM +G_FILE_OUTPUT_STREAM_CLASS +G_IS_FILE_OUTPUT_STREAM_CLASS +G_FILE_OUTPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_file_output_stream_get_type +GFileOutputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gfilteroutputstream</FILE> +<TITLE>GFilterOutputStream</TITLE> +GFilterOutputStream +g_filter_output_stream_get_base_stream +g_filter_output_stream_get_close_base_stream +g_filter_output_stream_set_close_base_stream +<SUBSECTION Standard> +GFilterOutputStreamClass +G_FILTER_OUTPUT_STREAM +G_IS_FILTER_OUTPUT_STREAM +G_TYPE_FILTER_OUTPUT_STREAM +G_FILTER_OUTPUT_STREAM_CLASS +G_IS_FILTER_OUTPUT_STREAM_CLASS +G_FILTER_OUTPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_filter_output_stream_get_type +</SECTION> + +<SECTION> +<FILE>gbufferedoutputstream</FILE> +<TITLE>GBufferedOutputStream</TITLE> +GBufferedOutputStream +g_buffered_output_stream_new +g_buffered_output_stream_new_sized +g_buffered_output_stream_get_buffer_size +g_buffered_output_stream_set_buffer_size +g_buffered_output_stream_get_auto_grow +g_buffered_output_stream_set_auto_grow +<SUBSECTION Standard> +GBufferedOutputStreamClass +G_BUFFERED_OUTPUT_STREAM +G_IS_BUFFERED_OUTPUT_STREAM +G_TYPE_BUFFERED_OUTPUT_STREAM +G_BUFFERED_OUTPUT_STREAM_CLASS +G_IS_BUFFERED_OUTPUT_STREAM_CLASS +G_BUFFERED_OUTPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_buffered_output_stream_get_type +GBufferedOutputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gmemoryoutputstream</FILE> +<TITLE>GMemoryOutputStream</TITLE> +GReallocFunc +GMemoryOutputStream +g_memory_output_stream_new +g_memory_output_stream_new_resizable +g_memory_output_stream_get_data +g_memory_output_stream_get_size +g_memory_output_stream_get_data_size +g_memory_output_stream_steal_data +g_memory_output_stream_steal_as_bytes +<SUBSECTION Standard> +GMemoryOutputStreamClass +G_MEMORY_OUTPUT_STREAM +G_IS_MEMORY_OUTPUT_STREAM +G_TYPE_MEMORY_OUTPUT_STREAM +G_MEMORY_OUTPUT_STREAM_CLASS +G_IS_MEMORY_OUTPUT_STREAM_CLASS +G_MEMORY_OUTPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_memory_output_stream_get_type +GMemoryOutputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gdataoutputstream</FILE> +<TITLE>GDataOutputStream</TITLE> +GDataOutputStream +g_data_output_stream_new +g_data_output_stream_set_byte_order +g_data_output_stream_get_byte_order +g_data_output_stream_put_byte +g_data_output_stream_put_int16 +g_data_output_stream_put_uint16 +g_data_output_stream_put_int32 +g_data_output_stream_put_uint32 +g_data_output_stream_put_int64 +g_data_output_stream_put_uint64 +g_data_output_stream_put_string +<SUBSECTION Standard> +GDataOutputStreamClass +G_DATA_OUTPUT_STREAM +G_IS_DATA_OUTPUT_STREAM +G_TYPE_DATA_OUTPUT_STREAM +G_DATA_OUTPUT_STREAM_CLASS +G_IS_DATA_OUTPUT_STREAM_CLASS +G_DATA_OUTPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_data_output_stream_get_type +GDataOutputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gunixoutputstream</FILE> +<TITLE>GUnixOutputStream</TITLE> +GUnixOutputStream +g_unix_output_stream_new +g_unix_output_stream_set_close_fd +g_unix_output_stream_get_close_fd +g_unix_output_stream_get_fd +<SUBSECTION Standard> +GUnixOutputStreamClass +G_UNIX_OUTPUT_STREAM +G_IS_UNIX_OUTPUT_STREAM +G_TYPE_UNIX_OUTPUT_STREAM +G_UNIX_OUTPUT_STREAM_CLASS +G_IS_UNIX_OUTPUT_STREAM_CLASS +G_UNIX_OUTPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_unix_output_stream_get_type +GUnixOutputStreamPrivate +</SECTION> + +<SECTION> +<FILE>giostream</FILE> +<TITLE>GIOStream</TITLE> +GIOStreamSpliceFlags +GIOStream +g_io_stream_get_input_stream +g_io_stream_get_output_stream +g_io_stream_splice_async +g_io_stream_splice_finish +g_io_stream_close +g_io_stream_close_async +g_io_stream_close_finish +g_io_stream_is_closed +g_io_stream_has_pending +g_io_stream_set_pending +g_io_stream_clear_pending +<SUBSECTION Standard> +GIOStreamClass +G_IO_STREAM +G_IO_STREAM_CLASS +G_IO_STREAM_GET_CLASS +G_IS_IO_STREAM +G_IS_IO_STREAM_CLASS +G_TYPE_IO_STREAM +G_TYPE_IO_STREAM_SPLICE_FLAGS +<SUBSECTION Private> +GIOStreamPrivate +GIOStreamAdapter +g_io_stream_get_type +g_io_stream_splice_flags_get_type +</SECTION> + +<SECTION> +<FILE>gsimpleiostream</FILE> +<TITLE>GSimpleIOStream</TITLE> +GSimpleIOStream +g_simple_io_stream_new +<SUBSECTION Standard> +GIOStreamClass +G_TYPE_SIMPLE_IO_STREAM +G_IS_SIMPLE_IO_STREAM +G_SIMPLE_IO_STREAM +<SUBSECTION Private> +g_simple_io_stream_get_type +</SECTION> + +<SECTION> +<FILE>gfileiostream</FILE> +<TITLE>GFileIOStream</TITLE> +GFileIOStream +g_file_io_stream_get_etag +g_file_io_stream_query_info +g_file_io_stream_query_info_async +g_file_io_stream_query_info_finish +<SUBSECTION Standard> +GFileIOStreamClass +G_FILE_IO_STREAM +G_FILE_IO_STREAM_CLASS +G_FILE_IO_STREAM_GET_CLASS +G_IS_FILE_IO_STREAM +G_IS_FILE_IO_STREAM_CLASS +G_TYPE_FILE_IO_STREAM +<SUBSECTION Private> +GFileIOStreamPrivate +g_file_io_stream_get_type +</SECTION> + +<SECTION> +<FILE>gseekable</FILE> +<TITLE>GSeekable</TITLE> +GSeekable +GSeekableIface +g_seekable_tell +g_seekable_can_seek +g_seekable_seek +g_seekable_can_truncate +g_seekable_truncate +<SUBSECTION Standard> +G_SEEKABLE +G_IS_SEEKABLE +G_TYPE_SEEKABLE +G_SEEKABLE_GET_IFACE +<SUBSECTION Private> +g_seekable_get_type +</SECTION> + +<SECTION> +<FILE>gvolumemonitor</FILE> +<TITLE>GVolumeMonitor</TITLE> +GVolumeMonitor +G_VOLUME_MONITOR_EXTENSION_POINT_NAME +g_volume_monitor_get +g_volume_monitor_get_connected_drives +g_volume_monitor_get_volumes +g_volume_monitor_get_mounts +g_volume_monitor_adopt_orphan_mount +g_volume_monitor_get_mount_for_uuid +g_volume_monitor_get_volume_for_uuid +<SUBSECTION Standard> +GVolumeMonitorClass +G_VOLUME_MONITOR +G_IS_VOLUME_MONITOR +G_TYPE_VOLUME_MONITOR +G_VOLUME_MONITOR_CLASS +G_IS_VOLUME_MONITOR_CLASS +G_VOLUME_MONITOR_GET_CLASS +<SUBSECTION Private> +g_volume_monitor_get_type +</SECTION> + +<SECTION> +<FILE>gmount</FILE> +<TITLE>GMount</TITLE> +GMount +GMountIface +g_mount_get_name +g_mount_get_uuid +g_mount_get_icon +g_mount_get_symbolic_icon +g_mount_get_drive +g_mount_get_root +g_mount_get_volume +g_mount_get_default_location +g_mount_can_unmount +GMountMountFlags +GMountUnmountFlags +g_mount_unmount +g_mount_unmount_finish +g_mount_unmount_with_operation +g_mount_unmount_with_operation_finish +g_mount_remount +g_mount_remount_finish +g_mount_can_eject +g_mount_eject +g_mount_eject_finish +g_mount_eject_with_operation +g_mount_eject_with_operation_finish +g_mount_guess_content_type +g_mount_guess_content_type_finish +g_mount_guess_content_type_sync +g_mount_is_shadowed +g_mount_shadow +g_mount_unshadow +g_mount_get_sort_key +<SUBSECTION Standard> +G_IS_MOUNT +G_MOUNT +G_MOUNT_GET_IFACE +G_TYPE_MOUNT +G_TYPE_MOUNT_MOUNT_FLAGS +G_TYPE_MOUNT_UNMOUNT_FLAGS +<SUBSECTION Private> +g_mount_get_type +g_mount_mount_flags_get_type +g_mount_unmount_flags_get_type +</SECTION> + +<SECTION> +<FILE>gvolume</FILE> +<TITLE>GVolume</TITLE> +GVolume +GVolumeIface +g_volume_get_name +g_volume_get_uuid +g_volume_get_icon +g_volume_get_symbolic_icon +g_volume_get_drive +g_volume_get_mount +g_volume_can_mount +g_volume_should_automount +g_volume_get_activation_root +g_volume_mount +g_volume_mount_finish +g_volume_can_eject +g_volume_eject +g_volume_eject_finish +g_volume_eject_with_operation +g_volume_eject_with_operation_finish +G_VOLUME_IDENTIFIER_KIND_HAL_UDI +G_VOLUME_IDENTIFIER_KIND_LABEL +G_VOLUME_IDENTIFIER_KIND_NFS_MOUNT +G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE +G_VOLUME_IDENTIFIER_KIND_UUID +G_VOLUME_IDENTIFIER_KIND_CLASS +g_volume_enumerate_identifiers +g_volume_get_identifier +g_volume_get_sort_key +<SUBSECTION Standard> +G_VOLUME +G_IS_VOLUME +G_TYPE_VOLUME +G_VOLUME_GET_IFACE +<SUBSECTION Private> +g_volume_get_type +</SECTION> + +<SECTION> +<FILE>gdrive</FILE> +<TITLE>GDrive</TITLE> +GDrive +GDriveIface +GDriveStartFlags +GDriveStartStopType +g_drive_get_name +g_drive_get_icon +g_drive_get_symbolic_icon +g_drive_has_volumes +g_drive_get_volumes +g_drive_can_eject +g_drive_get_start_stop_type +g_drive_can_start +g_drive_can_start_degraded +g_drive_can_stop +g_drive_can_poll_for_media +g_drive_poll_for_media +g_drive_poll_for_media_finish +g_drive_has_media +g_drive_is_media_check_automatic +g_drive_is_removable +g_drive_is_media_removable +g_drive_eject +g_drive_eject_finish +g_drive_eject_with_operation +g_drive_eject_with_operation_finish +g_drive_start +g_drive_start_finish +g_drive_stop +g_drive_stop_finish +g_drive_enumerate_identifiers +g_drive_get_identifier +g_drive_get_sort_key +G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE +<SUBSECTION Standard> +G_DRIVE +G_IS_DRIVE +G_TYPE_DRIVE +G_DRIVE_GET_IFACE +G_TYPE_DRIVE_START_FLAGS +G_TYPE_DRIVE_START_STOP_TYPE +<SUBSECTION Private> +g_drive_get_type +g_drive_start_flags_get_type +g_drive_start_stop_type_get_type +</SECTION> + +<SECTION> +<FILE>gcancellable</FILE> +<TITLE>GCancellable</TITLE> +GCancellable +g_cancellable_new +g_cancellable_is_cancelled +g_cancellable_set_error_if_cancelled +g_cancellable_get_fd +g_cancellable_make_pollfd +g_cancellable_release_fd +g_cancellable_source_new +GCancellableSourceFunc +g_cancellable_get_current +g_cancellable_pop_current +g_cancellable_push_current +g_cancellable_reset +g_cancellable_connect +g_cancellable_disconnect +g_cancellable_cancel +<SUBSECTION Standard> +GCancellableClass +G_CANCELLABLE +G_IS_CANCELLABLE +G_TYPE_CANCELLABLE +G_CANCELLABLE_CLASS +G_IS_CANCELLABLE_CLASS +G_CANCELLABLE_GET_CLASS +<SUBSECTION Private> +GCancellablePrivate +g_cancellable_get_type +</SECTION> + +<SECTION> +<FILE>gasyncresult</FILE> +<TITLE>GAsyncResult</TITLE> +GAsyncResult +GAsyncResultIface +GAsyncReadyCallback +g_async_result_get_user_data +g_async_result_get_source_object +g_async_result_is_tagged +g_async_result_legacy_propagate_error +<SUBSECTION Standard> +G_ASYNC_RESULT +G_IS_ASYNC_RESULT +G_TYPE_ASYNC_RESULT +G_ASYNC_RESULT_GET_IFACE +<SUBSECTION Private> +g_async_result_get_type +</SECTION> + +<SECTION> +<FILE>gsimpleasyncresult</FILE> +<TITLE>GSimpleAsyncResult</TITLE> +GSimpleAsyncResult +GSimpleAsyncThreadFunc +g_simple_async_result_new +g_simple_async_result_new_error +g_simple_async_result_new_from_error +g_simple_async_result_new_take_error +g_simple_async_result_set_check_cancellable +g_simple_async_result_set_op_res_gpointer +g_simple_async_result_get_op_res_gpointer +g_simple_async_result_set_op_res_gssize +g_simple_async_result_get_op_res_gssize +g_simple_async_result_set_op_res_gboolean +g_simple_async_result_get_op_res_gboolean +g_simple_async_result_get_source_tag +g_simple_async_result_is_valid +g_simple_async_result_set_handle_cancellation +g_simple_async_result_complete +g_simple_async_result_complete_in_idle +g_simple_async_result_run_in_thread +g_simple_async_result_set_from_error +g_simple_async_result_take_error +g_simple_async_result_propagate_error +g_simple_async_result_set_error +g_simple_async_result_set_error_va +g_simple_async_report_error_in_idle +g_simple_async_report_gerror_in_idle +g_simple_async_report_take_gerror_in_idle +<SUBSECTION Standard> +GSimpleAsyncResultClass +G_SIMPLE_ASYNC_RESULT +G_IS_SIMPLE_ASYNC_RESULT +G_TYPE_SIMPLE_ASYNC_RESULT +G_SIMPLE_ASYNC_RESULT_CLASS +G_IS_SIMPLE_ASYNC_RESULT_CLASS +G_SIMPLE_ASYNC_RESULT_GET_CLASS +<SUBSECTION Private> +g_simple_async_result_get_type +</SECTION> + +<SECTION> +<FILE>gioscheduler</FILE> +<TITLE>GIOScheduler</TITLE> +GIOSchedulerJob +GIOSchedulerJobFunc +g_io_scheduler_push_job +g_io_scheduler_cancel_all_jobs +g_io_scheduler_job_send_to_mainloop +g_io_scheduler_job_send_to_mainloop_async +</SECTION> + +<SECTION> +<FILE>gioerror</FILE> +<TITLE>GIOError</TITLE> +G_IO_ERROR +GIOErrorEnum +g_io_error_from_errno +g_io_error_from_win32_error +<SUBSECTION Standard> +G_TYPE_IO_ERROR_ENUM +<SUBSECTION Private> +g_io_error_quark +g_io_error_enum_get_type +</SECTION> + +<SECTION> +<FILE>gcontenttype</FILE> +<TITLE>GContentType</TITLE> +g_content_type_equals +g_content_type_is_a +g_content_type_is_mime_type +g_content_type_is_unknown +g_content_type_get_description +g_content_type_get_mime_type +g_content_type_get_icon +g_content_type_get_symbolic_icon +g_content_type_get_generic_icon_name +g_content_type_can_be_executable +g_content_type_from_mime_type +g_content_type_guess +g_content_type_guess_for_tree +g_content_types_get_registered +</SECTION> + +<SECTION> +<FILE>gappinfo</FILE> +<TITLE>GAppInfo</TITLE> +GAppInfoCreateFlags +GAppInfo +GAppInfoIface +GAppLaunchContext +g_app_info_create_from_commandline +g_app_info_dup +g_app_info_equal +g_app_info_get_id +g_app_info_get_name +g_app_info_get_display_name +g_app_info_get_description +g_app_info_get_executable +g_app_info_get_commandline +g_app_info_get_icon +g_app_info_launch +g_app_info_supports_files +g_app_info_supports_uris +g_app_info_launch_uris +g_app_info_launch_uris_async +g_app_info_launch_uris_finish +g_app_info_should_show +g_app_info_can_delete +g_app_info_delete +g_app_info_reset_type_associations +g_app_info_set_as_default_for_type +g_app_info_set_as_default_for_extension +g_app_info_set_as_last_used_for_type +g_app_info_add_supports_type +g_app_info_can_remove_supports_type +g_app_info_remove_supports_type +g_app_info_get_supported_types +g_app_info_get_all +g_app_info_get_all_for_type +g_app_info_get_default_for_type +g_app_info_get_default_for_uri_scheme +g_app_info_get_fallback_for_type +g_app_info_get_recommended_for_type +g_app_info_launch_default_for_uri +g_app_info_launch_default_for_uri_async +g_app_info_launch_default_for_uri_finish +g_app_launch_context_setenv +g_app_launch_context_unsetenv +g_app_launch_context_get_environment +g_app_launch_context_get_display +g_app_launch_context_get_startup_notify_id +g_app_launch_context_launch_failed +g_app_launch_context_new +<SUBSECTION Standard> +GAppLaunchContextClass +G_APP_INFO +G_IS_APP_INFO +G_TYPE_APP_INFO +G_APP_INFO_GET_IFACE +G_APP_LAUNCH_CONTEXT +G_APP_LAUNCH_CONTEXT_CLASS +G_APP_LAUNCH_CONTEXT_GET_CLASS +G_IS_APP_LAUNCH_CONTEXT +G_IS_APP_LAUNCH_CONTEXT_CLASS +G_TYPE_APP_LAUNCH_CONTEXT +G_TYPE_APP_INFO_CREATE_FLAGS +<SUBSECTION Private> +g_app_info_get_type +g_app_info_create_flags_get_type +g_app_launch_context_get_type +GAppLaunchContextPrivate +</SECTION> + +<SECTION> +<FILE>gappinfomonitor</FILE> +<TITLE>GAppInfoMonitor</TITLE> +g_app_info_monitor_get +<SUBSECTION Standard> +GAppInfoMonitor +G_APP_INFO_MONITOR +G_IS_APP_INFO_MONITOR +G_TYPE_APP_INFO_MONITOR +<SUBSECTION Private> +g_app_info_monitor_get_type +</SECTION> + +<SECTION> +<FILE>gmountoperation</FILE> +<TITLE>GMountOperation</TITLE> +GAskPasswordFlags +GPasswordSave +GMountOperation +GMountOperationResult +g_mount_operation_new +g_mount_operation_get_username +g_mount_operation_set_username +g_mount_operation_get_password +g_mount_operation_set_password +g_mount_operation_get_anonymous +g_mount_operation_set_anonymous +g_mount_operation_get_domain +g_mount_operation_set_domain +g_mount_operation_get_password_save +g_mount_operation_set_password_save +g_mount_operation_get_choice +g_mount_operation_set_choice +g_mount_operation_get_is_tcrypt_hidden_volume +g_mount_operation_set_is_tcrypt_hidden_volume +g_mount_operation_get_is_tcrypt_system_volume +g_mount_operation_set_is_tcrypt_system_volume +g_mount_operation_get_pim +g_mount_operation_set_pim +g_mount_operation_reply +<SUBSECTION Standard> +GMountOperationClass +G_MOUNT_OPERATION +G_IS_MOUNT_OPERATION +G_TYPE_MOUNT_OPERATION +G_MOUNT_OPERATION_CLASS +G_IS_MOUNT_OPERATION_CLASS +G_MOUNT_OPERATION_GET_CLASS +G_TYPE_ASK_PASSWORD_FLAGS +G_TYPE_MOUNT_OPERATION_RESULT +G_TYPE_PASSWORD_SAVE +<SUBSECTION Private> +g_mount_operation_get_type +g_ask_password_flags_get_type +GMountOperationPrivate +g_mount_operation_result_get_type +g_password_save_get_type +</SECTION> + +<SECTION> +<FILE>gfilenamecompleter</FILE> +<TITLE>GFilenameCompleter</TITLE> +GFilenameCompleter +g_filename_completer_new +g_filename_completer_get_completion_suffix +g_filename_completer_get_completions +g_filename_completer_set_dirs_only +<SUBSECTION Standard> +GFilenameCompleterClass +G_FILENAME_COMPLETER +G_IS_FILENAME_COMPLETER +G_TYPE_FILENAME_COMPLETER +G_FILENAME_COMPLETER_CLASS +G_IS_FILENAME_COMPLETER_CLASS +G_FILENAME_COMPLETER_GET_CLASS +<SUBSECTION Private> +g_filename_completer_get_type +</SECTION> + +<SECTION> +<FILE>gunixmounts</FILE> +<TITLE>Unix Mounts</TITLE> +GUnixMountPoint +GUnixMountEntry +GUnixMountMonitor +g_unix_mount_free +g_unix_mount_compare +g_unix_mount_copy +g_unix_mount_get_mount_path +g_unix_mount_get_device_path +g_unix_mount_get_root_path +g_unix_mount_get_fs_type +g_unix_mount_get_options +g_unix_mount_is_readonly +g_unix_mount_is_system_internal +g_unix_mount_guess_icon +g_unix_mount_guess_symbolic_icon +g_unix_mount_guess_name +g_unix_mount_guess_can_eject +g_unix_mount_guess_should_display +g_unix_mount_point_free +g_unix_mount_point_compare +g_unix_mount_point_copy +g_unix_mount_point_get_mount_path +g_unix_mount_point_get_device_path +g_unix_mount_point_get_fs_type +g_unix_mount_point_get_options +g_unix_mount_point_is_readonly +g_unix_mount_point_is_user_mountable +g_unix_mount_point_is_loopback +g_unix_mount_point_guess_icon +g_unix_mount_point_guess_symbolic_icon +g_unix_mount_point_guess_name +g_unix_mount_point_guess_can_eject +g_unix_mount_points_get +g_unix_mounts_get +g_unix_mount_at +g_unix_mount_for +g_unix_mounts_changed_since +g_unix_mount_points_changed_since +g_unix_mount_monitor_get +g_unix_mount_monitor_new +g_unix_mount_monitor_set_rate_limit +g_unix_is_mount_path_system_internal +g_unix_is_system_fs_type +g_unix_is_system_device_path +<SUBSECTION Standard> +GUnixMountMonitorClass +G_UNIX_MOUNT_MONITOR +G_IS_UNIX_MOUNT_MONITOR +G_TYPE_UNIX_MOUNT_MONITOR +G_UNIX_MOUNT_MONITOR_CLASS +G_IS_UNIX_MOUNT_MONITOR_CLASS +G_TYPE_UNIX_MOUNT_ENTRY +G_TYPE_UNIX_MOUNT_POINT +<SUBSECTION Private> +g_unix_mount_monitor_get_type +g_unix_mount_entry_get_type +g_unix_mount_point_get_type +</SECTION> + +<SECTION> +<FILE>gdesktopappinfo</FILE> +<TITLE>Desktop file based GAppInfo</TITLE> +GDesktopAppInfo +g_desktop_app_info_new_from_filename +g_desktop_app_info_new_from_keyfile +g_desktop_app_info_new +g_desktop_app_info_get_filename +g_desktop_app_info_get_is_hidden +g_desktop_app_info_get_nodisplay +g_desktop_app_info_get_show_in +g_desktop_app_info_get_generic_name +g_desktop_app_info_get_categories +g_desktop_app_info_get_keywords +g_desktop_app_info_get_startup_wm_class +g_desktop_app_info_set_desktop_env +g_desktop_app_info_get_string +g_desktop_app_info_get_locale_string +g_desktop_app_info_get_boolean +g_desktop_app_info_get_string_list +g_desktop_app_info_has_key +GDesktopAppLaunchCallback +g_desktop_app_info_launch_uris_as_manager +g_desktop_app_info_launch_uris_as_manager_with_fds +<SUBSECTION> +g_desktop_app_info_list_actions +g_desktop_app_info_get_action_name +g_desktop_app_info_launch_action +<SUBSECTION> +g_desktop_app_info_search +g_desktop_app_info_get_implementations +<SUBSECTION> +GDesktopAppInfoLookup +GDesktopAppInfoLookupIface +G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME +<SUBSECTION Standard> +GDesktopAppInfoClass +G_TYPE_DESKTOP_APP_INFO +G_DESKTOP_APP_INFO +G_DESKTOP_APP_INFO_CLASS +G_IS_DESKTOP_APP_INFO +G_IS_DESKTOP_APP_INFO_CLASS +G_DESKTOP_APP_INFO_GET_CLASS +G_DESKTOP_APP_INFO_LOOKUP +G_DESKTOP_APP_INFO_LOOKUP_GET_IFACE +G_IS_DESKTOP_APP_INFO_LOOKUP +G_TYPE_DESKTOP_APP_INFO_LOOKUP +<SUBSECTION Private> +g_desktop_app_info_get_type +g_desktop_app_info_lookup_get_default_for_uri_scheme +g_desktop_app_info_lookup_get_type +</SECTION> + +<SECTION> +<FILE>giomodule</FILE> +<TITLE>GIOModule</TITLE> +GIOModule +GIOModuleScope +GIOModuleScopeFlags +g_io_module_new +g_io_module_scope_block +g_io_module_scope_free +g_io_module_scope_new +g_io_modules_load_all_in_directory +g_io_modules_load_all_in_directory_with_scope +g_io_modules_scan_all_in_directory +g_io_modules_scan_all_in_directory_with_scope +g_io_module_load +g_io_module_unload +g_io_module_query +<SUBSECTION Standard> +GIOModuleClass +G_IO_MODULE +G_IO_IS_MODULE +G_IO_TYPE_MODULE +G_IO_MODULE_CLASS +G_IO_IS_MODULE_CLASS +G_IO_MODULE_GET_CLASS +G_TYPE_IO_MODULE_SCOPE_FLAGS +<SUBSECTION Private> +g_io_module_get_type +g_io_module_scope_flags_get_type +</SECTION> + +<SECTION> +<FILE>extensionpoints</FILE> +<TITLE>Extension Points</TITLE> +GIOExtension +GIOExtensionPoint +g_io_extension_get_name +g_io_extension_get_priority +g_io_extension_get_type +g_io_extension_point_get_extension_by_name +g_io_extension_point_get_extensions +g_io_extension_point_get_required_type +g_io_extension_point_implement +g_io_extension_point_lookup +g_io_extension_point_register +g_io_extension_point_set_required_type +g_io_extension_ref_class +</SECTION> + +<SECTION> +<FILE>gunixfdlist</FILE> +<TITLE>GUnixFDList</TITLE> +GUnixFDList +g_unix_fd_list_new_from_array +g_unix_fd_list_new +g_unix_fd_list_get_length +g_unix_fd_list_get +g_unix_fd_list_peek_fds +g_unix_fd_list_steal_fds +g_unix_fd_list_append +<SUBSECTION Standard> +GUnixFDListClass +G_UNIX_FD_LIST +G_UNIX_FD_LIST_CLASS +G_IS_UNIX_FD_LIST +G_IS_UNIX_FD_LIST_CLASS +G_UNIX_FD_LIST_GET_CLASS +G_TYPE_UNIX_FD_LIST +<SUBSECTION Private> +GUnixFDListPrivate +g_unix_fd_list_get_type +</SECTION> + +<SECTION> +<FILE>ginetaddress</FILE> +<TITLE>GInetAddress</TITLE> +GInetAddress +g_inet_address_new_from_string +g_inet_address_new_from_bytes +g_inet_address_new_any +g_inet_address_new_loopback +g_inet_address_equal +g_inet_address_to_bytes +g_inet_address_get_native_size +g_inet_address_to_string +g_inet_address_get_family +g_inet_address_get_is_any +g_inet_address_get_is_loopback +g_inet_address_get_is_link_local +g_inet_address_get_is_site_local +g_inet_address_get_is_multicast +g_inet_address_get_is_mc_link_local +g_inet_address_get_is_mc_node_local +g_inet_address_get_is_mc_site_local +g_inet_address_get_is_mc_org_local +g_inet_address_get_is_mc_global +<SUBSECTION Standard> +GInetAddressClass +GInetAddressPrivate +G_INET_ADDRESS +G_INET_ADDRESS_CLASS +G_INET_ADDRESS_GET_CLASS +G_IS_INET_ADDRESS +G_IS_INET_ADDRESS_CLASS +G_TYPE_INET_ADDRESS +<SUBSECTION Private> +g_inet_address_get_type +</SECTION> + +<SECTION> +<FILE>ginetaddressmask</FILE> +<TITLE>GInetAddressMask</TITLE> +GInetAddressMask +g_inet_address_mask_new +g_inet_address_mask_new_from_string +g_inet_address_mask_to_string +g_inet_address_mask_get_family +g_inet_address_mask_get_address +g_inet_address_mask_get_length +g_inet_address_mask_matches +g_inet_address_mask_equal +<SUBSECTION Standard> +GInetAddressMaskClass +GInetAddressMaskPrivate +G_INET_ADDRESS_MASK +G_INET_ADDRESS_MASK_CLASS +G_INET_ADDRESS_MASK_GET_CLASS +G_IS_INET_ADDRESS_MASK +G_IS_INET_ADDRESS_MASK_CLASS +G_TYPE_INET_ADDRESS_MASK +<SUBSECTION Private> +g_inet_address_mask_get_type +</SECTION> + +<SECTION> +<FILE>gsocketaddress</FILE> +<TITLE>GSocketAddress</TITLE> +GSocketAddress +GSocketFamily +g_socket_address_new_from_native +g_socket_address_get_family +g_socket_address_to_native +g_socket_address_get_native_size +<SUBSECTION Standard> +GSocketAddressClass +G_IS_SOCKET_ADDRESS +G_IS_SOCKET_ADDRESS_CLASS +G_SOCKET_ADDRESS +G_SOCKET_ADDRESS_CLASS +G_SOCKET_ADDRESS_GET_CLASS +G_TYPE_SOCKET_ADDRESS +G_TYPE_SOCKET_FAMILY +<SUBSECTION Private> +g_socket_address_get_type +g_socket_family_get_type +</SECTION> + +<SECTION> +<FILE>ginetsocketaddress</FILE> +<TITLE>GInetSocketAddress</TITLE> +GInetSocketAddress +g_inet_socket_address_new +g_inet_socket_address_new_from_string +g_inet_socket_address_get_address +g_inet_socket_address_get_port +g_inet_socket_address_get_flowinfo +g_inet_socket_address_get_scope_id +<SUBSECTION Standard> +GInetSocketAddressClass +GInetSocketAddressPrivate +G_INET_SOCKET_ADDRESS +G_INET_SOCKET_ADDRESS_CLASS +G_INET_SOCKET_ADDRESS_GET_CLASS +G_IS_INET_SOCKET_ADDRESS +G_IS_INET_SOCKET_ADDRESS_CLASS +G_TYPE_INET_SOCKET_ADDRESS +<SUBSECTION Private> +g_inet_socket_address_get_type +</SECTION> + +<SECTION> +<FILE>gunixsocketaddress</FILE> +<TITLE>GUnixSocketAddress</TITLE> +GUnixSocketAddress +GUnixSocketAddressType +g_unix_socket_address_new +g_unix_socket_address_new_abstract +g_unix_socket_address_new_with_type +g_unix_socket_address_get_is_abstract +g_unix_socket_address_get_address_type +g_unix_socket_address_get_path +g_unix_socket_address_get_path_len +g_unix_socket_address_abstract_names_supported +<SUBSECTION Standard> +GUnixSocketAddressClass +GUnixSocketAddressPrivate +G_IS_UNIX_SOCKET_ADDRESS +G_IS_UNIX_SOCKET_ADDRESS_CLASS +G_TYPE_UNIX_SOCKET_ADDRESS +G_UNIX_SOCKET_ADDRESS +G_UNIX_SOCKET_ADDRESS_CLASS +G_UNIX_SOCKET_ADDRESS_GET_CLASS +G_TYPE_UNIX_SOCKET_ADDRESS_TYPE +<SUBSECTION Private> +g_unix_socket_address_get_type +g_unix_socket_address_type_get_type +</SECTION> + +<SECTION> +<FILE>gnativesocketaddress</FILE> +<TITLE>GNativeSocketAddress</TITLE> +GNativeSocketAddress +g_native_socket_address_new +<SUBSECTION Standard> +GNativeSocketAddressClass +GNativeSocketAddressPrivate +G_IS_NATIVE_SOCKET_ADDRESS +G_IS_NATIVE_SOCKET_ADDRESS_CLASS +G_TYPE_NATIVE_SOCKET_ADDRESS +G_NATIVE_SOCKET_ADDRESS +G_NATIVE_SOCKET_ADDRESS_CLASS +G_NATIVE_SOCKET_ADDRESS_GET_CLASS +G_TYPE_NATIVE_SOCKET_ADDRESS_TYPE +<SUBSECTION Private> +g_native_socket_address_get_type +</SECTION> + +<SECTION> +<FILE>gresolver</FILE> +<TITLE>GResolver</TITLE> +GResolver +g_resolver_get_default +g_resolver_set_default +g_resolver_lookup_by_name +g_resolver_lookup_by_name_async +g_resolver_lookup_by_name_finish +GResolverNameLookupFlags +g_resolver_lookup_by_name_with_flags +g_resolver_lookup_by_name_with_flags_async +g_resolver_lookup_by_name_with_flags_finish +g_resolver_free_addresses +g_resolver_lookup_by_address +g_resolver_lookup_by_address_async +g_resolver_lookup_by_address_finish +g_resolver_lookup_service +g_resolver_lookup_service_async +g_resolver_lookup_service_finish +g_resolver_free_targets +<SUBSECTION> +GResolverRecordType +g_resolver_lookup_records +g_resolver_lookup_records_async +g_resolver_lookup_records_finish + +<SUBSECTION> +G_RESOLVER_ERROR +GResolverError + +<SUBSECTION Standard> +GResolverClass +G_IS_RESOLVER +G_IS_RESOLVER_CLASS +G_RESOLVER +G_RESOLVER_CLASS +G_RESOLVER_GET_CLASS +G_TYPE_RESOLVER +G_TYPE_RESOLVER_ERROR +G_TYPE_RESOLVER_RECORD_TYPE +G_TYPE_RESOLVER_NAME_LOOKUP_FLAGS + +<SUBSECTION Private> +GResolverPrivate +g_resolver_get_type +g_resolver_error_quark +g_resolver_record_type_get_type +g_resolver_error_get_type +g_resolver_name_lookup_flags_get_type +</SECTION> + +<SECTION> +<FILE>gsrvtarget</FILE> +<TITLE>GSrvTarget</TITLE> +GSrvTarget +g_srv_target_new +g_srv_target_copy +g_srv_target_free +g_srv_target_get_hostname +g_srv_target_get_port +g_srv_target_get_priority +g_srv_target_get_weight +g_srv_target_list_sort +<SUBSECTION Standard> +G_TYPE_SRV_TARGET +<SUBSECTION Private> +g_srv_target_get_type +</SECTION> + +<SECTION> +<FILE>gsocketconnectable</FILE> +<TITLE>GSocketConnectable</TITLE> +GSocketConnectable +GSocketConnectableIface +g_socket_connectable_enumerate +g_socket_connectable_proxy_enumerate +g_socket_connectable_to_string +<SUBSECTION Standard> +G_IS_SOCKET_CONNECTABLE +G_SOCKET_CONNECTABLE +G_SOCKET_CONNECTABLE_GET_IFACE +G_TYPE_SOCKET_CONNECTABLE +<SUBSECTION Private> +g_socket_connectable_get_type +</SECTION> + +<SECTION> +<FILE>gsocketaddressenumerator</FILE> +<TITLE>GSocketAddressEnumerator</TITLE> +GSocketAddressEnumerator +GSocketAddressEnumeratorClass +g_socket_address_enumerator_next +g_socket_address_enumerator_next_async +g_socket_address_enumerator_next_finish +<SUBSECTION Standard> +G_IS_SOCKET_ADDRESS_ENUMERATOR +G_IS_SOCKET_ADDRESS_ENUMERATOR_CLASS +G_SOCKET_ADDRESS_ENUMERATOR +G_SOCKET_ADDRESS_ENUMERATOR_CLASS +G_SOCKET_ADDRESS_ENUMERATOR_GET_CLASS +G_TYPE_SOCKET_ADDRESS_ENUMERATOR +<SUBSECTION Private> +g_socket_address_enumerator_get_type +</SECTION> + +<SECTION> +<FILE>gproxyaddressenumerator</FILE> +<TITLE>GProxyAddressEnumerator</TITLE> +GProxyAddressEnumerator +GProxyAddressEnumeratorClass +<SUBSECTION Standard> +G_IS_PROXY_ADDRESS_ENUMERATOR +G_IS_PROXY_ADDRESS_ENUMERATOR_CLASS +G_PROXY_ADDRESS_ENUMERATOR +G_PROXY_ADDRESS_ENUMERATOR_CLASS +G_PROXY_ADDRESS_ENUMERATOR_GET_CLASS +G_TYPE_PROXY_ADDRESS_ENUMERATOR +<SUBSECTION Private> +GProxyAddressEnumeratorPrivate +g_proxy_address_enumerator_get_type +</SECTION> + +<SECTION> +<FILE>gnetworkaddress</FILE> +<TITLE>GNetworkAddress</TITLE> +GNetworkAddress +g_network_address_new +g_network_address_new_loopback +g_network_address_parse +g_network_address_parse_uri +g_network_address_get_hostname +g_network_address_get_port +g_network_address_get_scheme +<SUBSECTION Standard> +GNetworkAddressClass +GNetworkAddressPrivate +G_IS_NETWORK_ADDRESS +G_IS_NETWORK_ADDRESS_CLASS +G_NETWORK_ADDRESS +G_NETWORK_ADDRESS_CLASS +G_NETWORK_ADDRESS_GET_CLASS +G_TYPE_NETWORK_ADDRESS +<SUBSECTION Private> +g_network_address_get_type +</SECTION> + +<SECTION> +<FILE>gnetworkservice</FILE> +<TITLE>GNetworkService</TITLE> +GNetworkService +g_network_service_new +g_network_service_get_service +g_network_service_get_protocol +g_network_service_get_domain +g_network_service_get_scheme +g_network_service_set_scheme +<SUBSECTION Standard> +GNetworkServiceClass +GNetworkServicePrivate +G_IS_NETWORK_SERVICE +G_IS_NETWORK_SERVICE_CLASS +G_NETWORK_SERVICE +G_NETWORK_SERVICE_CLASS +G_NETWORK_SERVICE_GET_CLASS +G_TYPE_NETWORK_SERVICE +<SUBSECTION Private> +g_network_service_get_type +</SECTION> + +<SECTION> +<FILE>gdatagrambased</FILE> +<TITLE>GDatagramBased</TITLE> +GDatagramBased +GDatagramBasedInterface +GDatagramBasedSourceFunc +g_datagram_based_receive_messages +g_datagram_based_send_messages +g_datagram_based_create_source +g_datagram_based_condition_check +g_datagram_based_condition_wait +<SUBSECTION Standard> +G_DATAGRAM_BASED +G_DATAGRAM_BASED_GET_IFACE +G_IS_DATAGRAM_BASED +G_TYPE_DATAGRAM_BASED +G_TYPE_IS_DATAGRAM_BASED +<SUBSECTION Private> +g_datagram_based_get_type +</SECTION> + +<SECTION> +<FILE>gsocket</FILE> +<TITLE>GSocket</TITLE> +GSocket +GSocketSourceFunc +GSocketType +GSocketProtocol +GSocketMsgFlags +GInputVector +GInputMessage +GOutputVector +GOutputMessage +g_socket_new +g_socket_new_from_fd +g_socket_bind +g_socket_listen +g_socket_accept +g_socket_connect +g_socket_check_connect_result +g_socket_receive +g_socket_receive_from +g_socket_receive_message +g_socket_receive_messages +g_socket_receive_with_blocking +g_socket_send +g_socket_send_to +g_socket_send_message +g_socket_send_message_with_timeout +g_socket_send_messages +g_socket_send_with_blocking +g_socket_close +g_socket_is_closed +g_socket_shutdown +g_socket_is_connected +g_socket_create_source +g_socket_condition_check +g_socket_condition_wait +g_socket_condition_timed_wait +g_socket_get_available_bytes +g_socket_set_listen_backlog +g_socket_get_listen_backlog +g_socket_get_blocking +g_socket_set_blocking +g_socket_get_keepalive +g_socket_set_keepalive +g_socket_get_timeout +g_socket_set_timeout +g_socket_set_ttl +g_socket_get_ttl +g_socket_get_broadcast +g_socket_set_broadcast +g_socket_get_option +g_socket_set_option +g_socket_get_family +g_socket_get_fd +g_socket_get_local_address +g_socket_get_protocol +g_socket_get_remote_address +g_socket_get_socket_type +g_socket_speaks_ipv4 +g_socket_get_credentials +<SUBSECTION> +g_socket_join_multicast_group +g_socket_leave_multicast_group +g_socket_join_multicast_group_ssm +g_socket_leave_multicast_group_ssm +g_socket_get_multicast_loopback +g_socket_set_multicast_loopback +g_socket_get_multicast_ttl +g_socket_set_multicast_ttl +<SUBSECTION Standard> +GSocketClass +G_IS_SOCKET +G_IS_SOCKET_CLASS +G_SOCKET +G_SOCKET_CLASS +G_TYPE_SOCKET +G_SOCKET_GET_CLASS +G_TYPE_SOCKET_MSG_FLAGS +G_TYPE_SOCKET_PROTOCOL +G_TYPE_SOCKET_TYPE +<SUBSECTION Private> +g_socket_get_type +GSocketPrivate +g_socket_msg_flags_get_type +g_socket_protocol_get_type +g_socket_type_get_type +</SECTION> + +<SECTION> +<FILE>gsocketclient</FILE> +<TITLE>GSocketClient</TITLE> +GSocketClient +GSocketClientEvent +g_socket_client_new +g_socket_client_connect +g_socket_client_connect_async +g_socket_client_connect_finish +g_socket_client_connect_to_host +g_socket_client_connect_to_host_async +g_socket_client_connect_to_host_finish +g_socket_client_connect_to_service +g_socket_client_connect_to_service_async +g_socket_client_connect_to_service_finish +g_socket_client_connect_to_uri +g_socket_client_connect_to_uri_async +g_socket_client_connect_to_uri_finish +g_socket_client_set_family +g_socket_client_set_local_address +g_socket_client_set_protocol +g_socket_client_set_socket_type +g_socket_client_set_timeout +g_socket_client_set_enable_proxy +g_socket_client_set_proxy_resolver +g_socket_client_set_tls +g_socket_client_set_tls_validation_flags +g_socket_client_get_family +g_socket_client_get_local_address +g_socket_client_get_protocol +g_socket_client_get_socket_type +g_socket_client_get_timeout +g_socket_client_get_enable_proxy +g_socket_client_get_proxy_resolver +g_socket_client_get_tls +g_socket_client_get_tls_validation_flags +g_socket_client_add_application_proxy +<SUBSECTION Standard> +GSocketClientClass +G_IS_SOCKET_CLIENT +G_IS_SOCKET_CLIENT_CLASS +G_SOCKET_CLIENT +G_SOCKET_CLIENT_CLASS +G_SOCKET_CLIENT_GET_CLASS +G_TYPE_SOCKET_CLIENT +G_TYPE_SOCKET_CLIENT_EVENT +<SUBSECTION Private> +GSocketClientPrivate +g_socket_client_get_type +g_socket_client_event_get_type +</SECTION> + +<SECTION> +<FILE>gsocketconnection</FILE> +<TITLE>GSocketConnection</TITLE> +GSocketConnection +g_socket_connection_connect +g_socket_connection_connect_async +g_socket_connection_connect_finish +<SUBSECTION> +g_socket_connection_is_connected +g_socket_connection_get_local_address +g_socket_connection_get_remote_address +g_socket_connection_get_socket +<SUBSECTION> +g_socket_connection_factory_create_connection +g_socket_connection_factory_lookup_type +g_socket_connection_factory_register_type +<SUBSECTION Standard> +GSocketConnectionClass +G_IS_SOCKET_CONNECTION +G_IS_SOCKET_CONNECTION_CLASS +G_SOCKET_CONNECTION +G_SOCKET_CONNECTION_CLASS +G_SOCKET_CONNECTION_GET_CLASS +G_TYPE_SOCKET_CONNECTION +<SUBSECTION Private> +GSocketConnectionPrivate +g_socket_connection_get_type +</SECTION> + +<SECTION> +<FILE>gunixconnection</FILE> +<TITLE>GUnixConnection</TITLE> +GUnixConnection +g_unix_connection_receive_fd +g_unix_connection_send_fd +g_unix_connection_receive_credentials +g_unix_connection_receive_credentials_async +g_unix_connection_receive_credentials_finish +g_unix_connection_send_credentials +g_unix_connection_send_credentials_async +g_unix_connection_send_credentials_finish +<SUBSECTION Standard> +GUnixConnectionClass +G_IS_UNIX_CONNECTION +G_IS_UNIX_CONNECTION_CLASS +G_TYPE_UNIX_CONNECTION +G_UNIX_CONNECTION +G_UNIX_CONNECTION_CLASS +G_UNIX_CONNECTION_GET_CLASS +<SUBSECTION Private> +GUnixConnectionPrivate +g_unix_connection_get_type +</SECTION> + +<SECTION> +<FILE>gtcpconnection</FILE> +<TITLE>GTcpConnection</TITLE> +GTcpConnection +g_tcp_connection_set_graceful_disconnect +g_tcp_connection_get_graceful_disconnect +<SUBSECTION Standard> +GTcpConnectionClass +G_IS_TCP_CONNECTION +G_IS_TCP_CONNECTION_CLASS +G_TYPE_TCP_CONNECTION +G_TCP_CONNECTION +G_TCP_CONNECTION_CLASS +G_TCP_CONNECTION_GET_CLASS +<SUBSECTION Private> +GTcpConnectionPrivate +g_tcp_connection_get_type +</SECTION> + +<SECTION> +<FILE>gtcpwrapperconnection</FILE> +<TITLE>GTcpWrapperConnection</TITLE> +GTcpWrapperConnection +g_tcp_wrapper_connection_new +g_tcp_wrapper_connection_get_base_io_stream +<SUBSECTION Standard> +GTcpWrapperConnectionClass +G_IS_TCP_WRAPPER_CONNECTION +G_IS_TCP_WRAPPER_CONNECTION_CLASS +G_TYPE_TCP_WRAPPER_CONNECTION +G_TCP_WRAPPER_CONNECTION +G_TCP_WRAPPER_CONNECTION_CLASS +G_TCP_WRAPPER_CONNECTION_GET_CLASS +<SUBSECTION Private> +GTcpWrapperConnectionPrivate +g_tcp_wrapper_connection_get_type +</SECTION> + +<SECTION> +<FILE>gsocketcontrolmessage</FILE> +<TITLE>GSocketControlMessage</TITLE> +GSocketControlMessage +g_socket_control_message_deserialize +g_socket_control_message_get_level +g_socket_control_message_get_msg_type +g_socket_control_message_get_size +g_socket_control_message_serialize +<SUBSECTION Standard> +GSocketControlMessageClass +G_IS_SOCKET_CONTROL_MESSAGE +G_IS_SOCKET_CONTROL_MESSAGE_CLASS +G_SOCKET_CONTROL_MESSAGE +G_SOCKET_CONTROL_MESSAGE_CLASS +G_SOCKET_CONTROL_MESSAGE_GET_CLASS +G_TYPE_SOCKET_CONTROL_MESSAGE +<SUBSECTION Private> +GSocketControlMessagePrivate +g_socket_control_message_get_type +</SECTION> + +<SECTION> +<FILE>gsocketlistener</FILE> +<TITLE>GSocketListener</TITLE> +GSocketListener +GSocketListenerEvent +g_socket_listener_new +g_socket_listener_add_socket +g_socket_listener_add_address +g_socket_listener_add_inet_port +g_socket_listener_add_any_inet_port +g_socket_listener_accept +g_socket_listener_accept_async +g_socket_listener_accept_finish +g_socket_listener_accept_socket +g_socket_listener_accept_socket_async +g_socket_listener_accept_socket_finish +g_socket_listener_close +g_socket_listener_set_backlog +<SUBSECTION Standard> +GSocketListenerClass +G_IS_SOCKET_LISTENER +G_IS_SOCKET_LISTENER_CLASS +G_SOCKET_LISTENER +G_SOCKET_LISTENER_CLASS +G_SOCKET_LISTENER_GET_CLASS +G_TYPE_SOCKET_LISTENER +G_TYPE_SOCKET_LISTENER_EVENT +<SUBSECTION Private> +GSocketListenerPrivate +g_socket_listener_get_type +g_socket_listener_event_get_type +</SECTION> + +<SECTION> +<FILE>gsocketservice</FILE> +<TITLE>GSocketService</TITLE> +GSocketService +g_socket_service_new +g_socket_service_start +g_socket_service_stop +g_socket_service_is_active +<SUBSECTION Standard> +GSocketServiceClass +G_IS_SOCKET_SERVICE +G_IS_SOCKET_SERVICE_CLASS +G_SOCKET_SERVICE +G_SOCKET_SERVICE_CLASS +G_SOCKET_SERVICE_GET_CLASS +G_TYPE_SOCKET_SERVICE +<SUBSECTION Private> +GSocketServicePrivate +g_socket_service_get_type +</SECTION> + +<SECTION> +<FILE>gthreadedsocketservice</FILE> +<TITLE>GThreadedSocketService</TITLE> +GThreadedSocketService +g_threaded_socket_service_new +<SUBSECTION Standard> +GThreadedSocketServiceClass +G_IS_THREADED_SOCKET_SERVICE +G_IS_THREADED_SOCKET_SERVICE_CLASS +G_THREADED_SOCKET_SERVICE +G_THREADED_SOCKET_SERVICE_CLASS +G_THREADED_SOCKET_SERVICE_GET_CLASS +G_TYPE_THREADED_SOCKET_SERVICE +<SUBSECTION Private> +GThreadedSocketServicePrivate +g_threaded_socket_service_get_type +</SECTION> + +<SECTION> +<FILE>gunixfdmessage</FILE> +<TITLE>GUnixFDMessage</TITLE> +GUnixFDMessage +g_unix_fd_message_new_with_fd_list +g_unix_fd_message_new +g_unix_fd_message_get_fd_list +g_unix_fd_message_append_fd +g_unix_fd_message_steal_fds +<SUBSECTION Standard> +GUnixFDMessageClass +G_IS_UNIX_FD_MESSAGE +G_IS_UNIX_FD_MESSAGE_CLASS +G_TYPE_UNIX_FD_MESSAGE +G_UNIX_FD_MESSAGE +G_UNIX_FD_MESSAGE_CLASS +G_UNIX_FD_MESSAGE_GET_CLASS +<SUBSECTION Private> +GUnixFDMessagePrivate +g_unix_fd_message_get_type +</SECTION> + +<SECTION> +<FILE>gconverter</FILE> +<TITLE>GConverter</TITLE> +GConverter +GConverterIface +GConverterResult +GConverterFlags +g_converter_convert +g_converter_reset +<SUBSECTION Standard> +G_TYPE_CONVERTER +G_CONVERTER +G_IS_CONVERTER +G_CONVERTER_GET_IFACE +G_TYPE_CONVERTER_FLAGS +G_TYPE_CONVERTER_RESULT +<SUBSECTION Private> +g_converter_get_type +g_converter_flags_get_type +g_converter_result_get_type +</SECTION> + +<SECTION> +<FILE>gcharsetconverter</FILE> +<TITLE>GCharsetConverter</TITLE> +GCharsetConverter +g_charset_converter_new +g_charset_converter_set_use_fallback +g_charset_converter_get_use_fallback +g_charset_converter_get_num_fallbacks +<SUBSECTION Standard> +GCharsetConverterClass +G_TYPE_CHARSET_CONVERTER +G_CHARSET_CONVERTER +G_IS_CHARSET_CONVERTER +G_CHARSET_CONVERTER_CLASS +G_IS_CHARSET_CONVERTER_CLASS +G_CHARSET_CONVERTER_GET_CLASS +<SUBSECTION Private> +g_charset_converter_get_type +</SECTION> + +<SECTION> +<FILE>gconverterinputstream</FILE> +<TITLE>GConverterInputStream</TITLE> +GConverterInputStream +g_converter_input_stream_new +g_converter_input_stream_get_converter +<SUBSECTION Standard> +GConverterInputStreamClass +G_TYPE_CONVERTER_INPUT_STREAM +G_CONVERTER_INPUT_STREAM +G_IS_CONVERTER_INPUT_STREAM +G_CONVERTER_INPUT_STREAM_CLASS +G_IS_CONVERTER_INPUT_STREAM_CLASS +G_CONVERTER_INPUT_STREAM_GET_CLASS +<SUBSECTION Private> +GConverterInputStreamPrivate +g_converter_input_stream_get_type +</SECTION> + +<SECTION> +<FILE>gconverteroutputstream</FILE> +<TITLE>GConverterOutputStream</TITLE> +GConverterOutputStream +g_converter_output_stream_new +g_converter_output_stream_get_converter +<SUBSECTION Standard> +GConverterOutputStreamClass +G_TYPE_CONVERTER_OUTPUT_STREAM +G_CONVERTER_OUTPUT_STREAM +G_IS_CONVERTER_OUTPUT_STREAM +G_CONVERTER_OUTPUT_STREAM_CLASS +G_IS_CONVERTER_OUTPUT_STREAM_CLASS +G_CONVERTER_OUTPUT_STREAM_GET_CLASS +<SUBSECTION Private> +GConverterOutputStreamPrivate +g_converter_output_stream_get_type +</SECTION> + +<SECTION> +<FILE>gzcompressor</FILE> +<TITLE>GZlibCompressor</TITLE> +GZlibCompressor +GZlibCompressorFormat +g_zlib_compressor_new +g_zlib_compressor_get_file_info +g_zlib_compressor_set_file_info +<SUBSECTION Standard> +GZlibCompressorClass +G_TYPE_ZLIB_COMPRESSOR +G_ZLIB_COMPRESSOR +G_IS_ZLIB_COMPRESSOR +G_ZLIB_COMPRESSOR_CLASS +G_IS_ZLIB_COMPRESSOR_CLASS +G_ZLIB_COMPRESSOR_GET_CLASS +G_TYPE_ZLIB_COMPRESSOR_FORMAT +<SUBSECTION Private> +g_zlib_compressor_get_type +g_zlib_compressor_format_get_type +</SECTION> + +<SECTION> +<FILE>gzdecompressor</FILE> +<TITLE>GZlibDecompressor</TITLE> +GZlibDecompressor +g_zlib_decompressor_new +g_zlib_decompressor_get_file_info +<SUBSECTION Standard> +GZlibDecompressorClass +G_TYPE_ZLIB_DECOMPRESSOR +G_ZLIB_DECOMPRESSOR +G_IS_ZLIB_DECOMPRESSOR +G_ZLIB_DECOMPRESSOR_CLASS +G_IS_ZLIB_DECOMPRESSOR_CLASS +G_ZLIB_DECOMPRESSOR_GET_CLASS +<SUBSECTION Private> +g_zlib_decompressor_get_type +</SECTION> + +<SECTION> +<FILE>gfiledescriptorbased</FILE> +<TITLE>GFileDescriptorBased</TITLE> +GFileDescriptorBased +GFileDescriptorBasedIface +g_file_descriptor_based_get_fd +<SUBSECTION Private> +g_file_descriptor_based_get_type +G_FILE_DESCRIPTOR_BASED +G_FILE_DESCRIPTOR_BASED_GET_IFACE +G_IS_FILE_DESCRIPTOR_BASED +G_TYPE_FILE_DESCRIPTOR_BASED +</SECTION> + +<SECTION> +<FILE>gsettingsbackend</FILE> +<TITLE>GSettingsBackend</TITLE> +GSettingsBackend +GSettingsBackendClass +G_SETTINGS_BACKEND_EXTENSION_POINT_NAME +g_settings_backend_get_default +g_settings_backend_changed +g_settings_backend_path_changed +g_settings_backend_keys_changed +g_settings_backend_path_writable_changed +g_settings_backend_writable_changed +g_settings_backend_changed_tree +g_settings_backend_flatten_tree +g_keyfile_settings_backend_new +g_memory_settings_backend_new +g_null_settings_backend_new + +<SUBSECTION Standard> +G_IS_SETTINGS_BACKEND +G_IS_SETTINGS_BACKEND_CLASS +G_SETTINGS_BACKEND +G_SETTINGS_BACKEND_CLASS +G_SETTINGS_BACKEND_GET_CLASS +G_TYPE_SETTINGS_BACKEND + +<SUBSECTION Private> +g_settings_backend_get_type +GSettingsBackendPrivate +</SECTION> + +<SECTION> +<FILE>gsettingsschema</FILE> +<TITLE>GSettingsSchema, GSettingsSchemaSource</TITLE> +GSettingsSchemaSource +g_settings_schema_source_get_default +g_settings_schema_source_ref +g_settings_schema_source_unref + +<SUBSECTION> +g_settings_schema_source_new_from_directory + +<SUBSECTION> +g_settings_schema_source_list_schemas +g_settings_schema_source_lookup + +<SUBSECTION> +GSettingsSchema +g_settings_schema_ref +g_settings_schema_unref + +<SUBSECTION> +g_settings_schema_get_id +g_settings_schema_get_path + +<SUBSECTION> +GSettingsSchemaKey +g_settings_schema_has_key +g_settings_schema_get_key +g_settings_schema_key_ref +g_settings_schema_key_unref +g_settings_schema_list_children +g_settings_schema_list_keys + +<SUBSECTION> +g_settings_schema_key_get_value_type +g_settings_schema_key_get_default_value +g_settings_schema_key_get_range +g_settings_schema_key_range_check + +<SUBSECTION> +g_settings_schema_key_get_name +g_settings_schema_key_get_summary +g_settings_schema_key_get_description + +<SUBSECTION Standard> +G_TYPE_SETTINGS_SCHEMA_KEY +G_TYPE_SETTINGS_SCHEMA +G_TYPE_SETTINGS_SCHEMA_SOURCE + +<SUBSECTION Private> +g_settings_schema_get_type +g_settings_schema_key_get_type +g_settings_schema_source_get_type +</SECTION> + +<SECTION> +<FILE>gsettings</FILE> +<TITLE>GSettings</TITLE> +GSettings +g_settings_new +g_settings_new_with_path +g_settings_new_with_backend +g_settings_new_with_backend_and_path +g_settings_new_full +g_settings_sync +g_settings_get_value +g_settings_set_value +g_settings_is_writable +g_settings_delay +g_settings_apply +g_settings_revert +g_settings_get_has_unapplied +g_settings_get_child +g_settings_reset +g_settings_get_user_value +g_settings_get_default_value + +<SUBSECTION Introspection> +g_settings_list_schemas +g_settings_list_relocatable_schemas +g_settings_list_keys +g_settings_list_children +g_settings_get_range +g_settings_range_check + +<SUBSECTION Convenience> +g_settings_get +g_settings_set +g_settings_get_boolean +g_settings_set_boolean +g_settings_get_int +g_settings_set_int +g_settings_get_int64 +g_settings_set_int64 +g_settings_get_uint +g_settings_set_uint +g_settings_get_uint64 +g_settings_set_uint64 +g_settings_get_double +g_settings_set_double +g_settings_get_string +g_settings_set_string +g_settings_get_strv +g_settings_set_strv +g_settings_get_enum +g_settings_set_enum +g_settings_get_flags +g_settings_set_flags + +<SUBSECTION MappedGet> +GSettingsGetMapping +g_settings_get_mapped + +<SUBSECTION Binding> +GSettingsBindFlags +g_settings_bind +g_settings_bind_with_mapping +g_settings_bind_writable +g_settings_unbind +GSettingsBindSetMapping +GSettingsBindGetMapping + +<SUBSECTION> +g_settings_create_action + +<SUBSECTION Standard> +GSettingsClass +G_IS_SETTINGS +G_IS_SETTINGS_CLASS +G_SETTINGS +G_SETTINGS_CLASS +G_SETTINGS_GET_CLASS +G_TYPE_SETTINGS +G_TYPE_SETTINGS_BIND_FLAGS + +<SUBSECTION Private> +GSettingsPrivate +g_settings_get_type +g_settings_bind_flags_get_type +</SECTION> + +<SECTION> +<FILE>gunixcredentialsmessage</FILE> +<TITLE>GUnixCredentialsMessage</TITLE> +GUnixCredentialsMessage +GUnixCredentialsMessageClass +g_unix_credentials_message_new +g_unix_credentials_message_new_with_credentials +g_unix_credentials_message_get_credentials +g_unix_credentials_message_is_supported +<SUBSECTION Standard> +G_IS_UNIX_CREDENTIALS_MESSAGE +G_IS_UNIX_CREDENTIALS_MESSAGE_CLASS +G_TYPE_UNIX_CREDENTIALS_MESSAGE +G_UNIX_CREDENTIALS_MESSAGE +G_UNIX_CREDENTIALS_MESSAGE_CLASS +G_UNIX_CREDENTIALS_MESSAGE_GET_CLASS +<SUBSECTION Private> +GUnixCredentialsMessagePrivate +g_unix_credentials_message_get_type +</SECTION> + +<SECTION> +<FILE>gcredentials</FILE> +<TITLE>GCredentials</TITLE> +GCredentials +GCredentialsType +g_credentials_new +g_credentials_to_string +g_credentials_get_native +g_credentials_set_native +g_credentials_is_same_user +g_credentials_get_unix_user +g_credentials_set_unix_user +g_credentials_get_unix_pid +<SUBSECTION Standard> +G_CREDENTIALS +G_IS_CREDENTIALS +G_TYPE_CREDENTIALS +G_CREDENTIALS_CLASS +G_IS_CREDENTIALS_CLASS +G_CREDENTIALS_GET_CLASS +G_TYPE_CREDENTIALS_TYPE +<SUBSECTION Private> +g_credentials_get_type +g_credentials_type_get_type +G_CREDENTIALS_NATIVE_SIZE +G_CREDENTIALS_NATIVE_TYPE +G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED +G_CREDENTIALS_SPOOFING_SUPPORTED +G_CREDENTIALS_SUPPORTED +G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED +G_CREDENTIALS_USE_FREEBSD_CMSGCRED +G_CREDENTIALS_USE_LINUX_UCRED +G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED +G_CREDENTIALS_USE_SOLARIS_UCRED +</SECTION> + +<SECTION> +<FILE>gdbusaddress</FILE> +g_dbus_is_address +g_dbus_is_supported_address +g_dbus_address_get_stream +g_dbus_address_get_stream_finish +g_dbus_address_get_stream_sync +g_dbus_address_get_for_bus_sync +g_dbus_address_escape_value +</SECTION> + +<SECTION> +<FILE>gdbusutils</FILE> +g_dbus_generate_guid +g_dbus_is_guid +g_dbus_is_name +g_dbus_is_unique_name +g_dbus_is_member_name +g_dbus_is_interface_name +g_dbus_gvalue_to_gvariant +g_dbus_gvariant_to_gvalue +</SECTION> + +<SECTION> +<FILE>gdbusauthobserver</FILE> +<TITLE>GDBusAuthObserver</TITLE> +GDBusAuthObserver +g_dbus_auth_observer_new +g_dbus_auth_observer_authorize_authenticated_peer +g_dbus_auth_observer_allow_mechanism +<SUBSECTION Standard> +G_DBUS_AUTH_OBSERVER +G_IS_DBUS_AUTH_OBSERVER +G_TYPE_DBUS_AUTH_OBSERVER +<SUBSECTION Private> +g_dbus_auth_observer_get_type +</SECTION> + +<SECTION> +<FILE>gdbusserver</FILE> +<TITLE>GDBusServer</TITLE> +GDBusServer +GDBusServerFlags +g_dbus_server_new_sync +g_dbus_server_start +g_dbus_server_stop +g_dbus_server_is_active +g_dbus_server_get_guid +g_dbus_server_get_flags +g_dbus_server_get_client_address +<SUBSECTION Standard> +G_DBUS_SERVER +G_IS_DBUS_SERVER +G_TYPE_DBUS_SERVER +G_TYPE_DBUS_SERVER_FLAGS +<SUBSECTION Private> +g_dbus_server_get_type +g_dbus_server_flags_get_type +</SECTION> + +<SECTION> +<FILE>gdbusmessage</FILE> +<TITLE>GDBusMessage</TITLE> +GDBusMessage +GDBusMessageType +GDBusMessageFlags +GDBusMessageHeaderField +GDBusMessageByteOrder +g_dbus_message_new +g_dbus_message_new_signal +g_dbus_message_new_method_call +g_dbus_message_new_method_reply +g_dbus_message_new_method_error +g_dbus_message_new_method_error_valist +g_dbus_message_new_method_error_literal +g_dbus_message_print +g_dbus_message_get_locked +g_dbus_message_lock +g_dbus_message_copy +g_dbus_message_get_byte_order +g_dbus_message_set_byte_order +g_dbus_message_get_message_type +g_dbus_message_set_message_type +g_dbus_message_get_serial +g_dbus_message_set_serial +g_dbus_message_get_flags +g_dbus_message_set_flags +g_dbus_message_get_body +g_dbus_message_set_body +g_dbus_message_get_unix_fd_list +g_dbus_message_set_unix_fd_list +g_dbus_message_get_num_unix_fds +g_dbus_message_set_num_unix_fds +g_dbus_message_get_header_fields +g_dbus_message_get_header +g_dbus_message_set_header +g_dbus_message_get_destination +g_dbus_message_set_destination +g_dbus_message_get_error_name +g_dbus_message_set_error_name +g_dbus_message_get_interface +g_dbus_message_set_interface +g_dbus_message_get_member +g_dbus_message_set_member +g_dbus_message_get_path +g_dbus_message_set_path +g_dbus_message_get_reply_serial +g_dbus_message_set_reply_serial +g_dbus_message_get_sender +g_dbus_message_set_sender +g_dbus_message_get_signature +g_dbus_message_set_signature +g_dbus_message_get_arg0 +g_dbus_message_to_blob +g_dbus_message_bytes_needed +g_dbus_message_new_from_blob +g_dbus_message_to_gerror +<SUBSECTION Standard> +G_DBUS_MESSAGE +G_IS_DBUS_MESSAGE +G_TYPE_DBUS_MESSAGE +G_TYPE_DBUS_MESSAGE_BYTE_ORDER +G_TYPE_DBUS_MESSAGE_FLAGS +G_TYPE_DBUS_MESSAGE_HEADER_FIELD +G_TYPE_DBUS_MESSAGE_TYPE +<SUBSECTION Private> +g_dbus_message_get_type +g_dbus_message_byte_order_get_type +g_dbus_message_flags_get_type +g_dbus_message_header_field_get_type +g_dbus_message_type_get_type +</SECTION> + +<SECTION> +<FILE>gdbusconnection</FILE> +<TITLE>GDBusConnection</TITLE> +GBusType +g_bus_get +g_bus_get_finish +g_bus_get_sync +GDBusConnection +GDBusConnectionFlags +g_dbus_connection_new +g_dbus_connection_new_finish +g_dbus_connection_new_sync +g_dbus_connection_new_for_address +g_dbus_connection_new_for_address_finish +g_dbus_connection_new_for_address_sync +g_dbus_connection_start_message_processing +g_dbus_connection_close +g_dbus_connection_close_finish +g_dbus_connection_close_sync +g_dbus_connection_is_closed +g_dbus_connection_flush +g_dbus_connection_flush_finish +g_dbus_connection_flush_sync +g_dbus_connection_get_exit_on_close +g_dbus_connection_set_exit_on_close +g_dbus_connection_get_stream +g_dbus_connection_get_flags +g_dbus_connection_get_guid +g_dbus_connection_get_unique_name +GDBusCapabilityFlags +g_dbus_connection_get_capabilities +g_dbus_connection_get_peer_credentials +g_dbus_connection_get_last_serial +GDBusCallFlags +g_dbus_connection_call +g_dbus_connection_call_finish +g_dbus_connection_call_sync +g_dbus_connection_call_with_unix_fd_list +g_dbus_connection_call_with_unix_fd_list_finish +g_dbus_connection_call_with_unix_fd_list_sync +g_dbus_connection_emit_signal +GDBusSignalFlags +GDBusSignalCallback +g_dbus_connection_signal_subscribe +g_dbus_connection_signal_unsubscribe +GDBusSendMessageFlags +g_dbus_connection_send_message +g_dbus_connection_send_message_with_reply +g_dbus_connection_send_message_with_reply_finish +g_dbus_connection_send_message_with_reply_sync +GDBusMessageFilterFunction +g_dbus_connection_add_filter +g_dbus_connection_remove_filter +GDBusInterfaceVTable +GDBusInterfaceMethodCallFunc +GDBusInterfaceGetPropertyFunc +GDBusInterfaceSetPropertyFunc +g_dbus_connection_register_object +g_dbus_connection_unregister_object +g_dbus_connection_register_object_with_closures +GDBusSubtreeVTable +GDBusSubtreeEnumerateFunc +GDBusSubtreeIntrospectFunc +GDBusSubtreeDispatchFunc +GDBusSubtreeFlags +g_dbus_connection_register_subtree +g_dbus_connection_unregister_subtree +<SUBSECTION Standard> +G_DBUS_CONNECTION +G_IS_DBUS_CONNECTION +G_TYPE_DBUS_CONNECTION +G_TYPE_BUS_TYPE +G_TYPE_DBUS_CALL_FLAGS +G_TYPE_DBUS_CAPABILITY_FLAGS +G_TYPE_DBUS_CONNECTION_FLAGS +G_TYPE_DBUS_SEND_MESSAGE_FLAGS +G_TYPE_DBUS_SIGNAL_FLAGS +G_TYPE_DBUS_SUBTREE_FLAGS +<SUBSECTION Private> +g_dbus_connection_get_type +g_bus_type_get_type +g_dbus_call_flags_get_type +g_dbus_capability_flags_get_type +g_dbus_connection_flags_get_type +g_dbus_send_message_flags_get_type +g_dbus_signal_flags_get_type +g_dbus_subtree_flags_get_type +</SECTION> + +<SECTION> +<FILE>gdbusmethodinvocation</FILE> +<TITLE>GDBusMethodInvocation</TITLE> +GDBusMethodInvocation +g_dbus_method_invocation_get_sender +g_dbus_method_invocation_get_object_path +g_dbus_method_invocation_get_interface_name +g_dbus_method_invocation_get_method_name +g_dbus_method_invocation_get_method_info +g_dbus_method_invocation_get_property_info +g_dbus_method_invocation_get_connection +g_dbus_method_invocation_get_message +g_dbus_method_invocation_get_parameters +g_dbus_method_invocation_get_user_data +g_dbus_method_invocation_return_value +g_dbus_method_invocation_return_error +g_dbus_method_invocation_return_error_valist +g_dbus_method_invocation_return_error_literal +g_dbus_method_invocation_return_gerror +g_dbus_method_invocation_return_dbus_error +g_dbus_method_invocation_take_error +g_dbus_method_invocation_return_value_with_unix_fd_list +<SUBSECTION Standard> +G_DBUS_METHOD_INVOCATION +G_IS_DBUS_METHOD_INVOCATION +G_TYPE_DBUS_METHOD_INVOCATION +<SUBSECTION Private> +g_dbus_method_invocation_get_type +</SECTION> + +<SECTION> +<FILE>gdbusnameowning</FILE> +GBusAcquiredCallback +GBusNameAcquiredCallback +GBusNameLostCallback +GBusNameOwnerFlags +g_bus_own_name +g_bus_own_name_on_connection +g_bus_unown_name +g_bus_own_name_with_closures +g_bus_own_name_on_connection_with_closures + +<SUBSECTION Standard> +G_TYPE_BUS_NAME_OWNER_FLAGS +<SUBSECTION Private> +g_bus_name_owner_flags_get_type +</SECTION> + +<SECTION> +<FILE>gdbusnamewatching</FILE> +GBusNameAppearedCallback +GBusNameVanishedCallback +GBusNameWatcherFlags +g_bus_watch_name +g_bus_watch_name_on_connection +g_bus_unwatch_name +g_bus_watch_name_with_closures +g_bus_watch_name_on_connection_with_closures + +<SUBSECTION Standard> +G_TYPE_BUS_NAME_WATCHER_FLAGS +<SUBSECTION Private> +g_bus_name_watcher_flags_get_type +</SECTION> + +<SECTION> +<FILE>gdbuserror</FILE> +GDBusError +G_DBUS_ERROR +g_dbus_error_is_remote_error +g_dbus_error_get_remote_error +g_dbus_error_strip_remote_error +GDBusErrorEntry +g_dbus_error_register_error_domain +g_dbus_error_register_error +g_dbus_error_unregister_error +g_dbus_error_new_for_dbus_error +g_dbus_error_set_dbus_error +g_dbus_error_set_dbus_error_valist +g_dbus_error_encode_gerror +<SUBSECTION Standard> +G_TYPE_DBUS_ERROR +g_dbus_error_quark +g_dbus_error_get_type +</SECTION> + +<SECTION> +<FILE>gdbusproxy</FILE> +<TITLE>GDBusProxy</TITLE> +GDBusProxyFlags +GDBusProxy +GDBusProxyClass +g_dbus_proxy_new +g_dbus_proxy_new_finish +g_dbus_proxy_new_sync +g_dbus_proxy_new_for_bus +g_dbus_proxy_new_for_bus_finish +g_dbus_proxy_new_for_bus_sync +g_dbus_proxy_get_flags +g_dbus_proxy_get_connection +g_dbus_proxy_get_name +g_dbus_proxy_get_name_owner +g_dbus_proxy_get_object_path +g_dbus_proxy_get_interface_name +g_dbus_proxy_get_default_timeout +g_dbus_proxy_set_default_timeout +g_dbus_proxy_get_cached_property +g_dbus_proxy_set_cached_property +g_dbus_proxy_get_cached_property_names +g_dbus_proxy_set_interface_info +g_dbus_proxy_get_interface_info +g_dbus_proxy_call +g_dbus_proxy_call_finish +g_dbus_proxy_call_sync +g_dbus_proxy_call_with_unix_fd_list +g_dbus_proxy_call_with_unix_fd_list_finish +g_dbus_proxy_call_with_unix_fd_list_sync +<SUBSECTION Standard> +G_DBUS_PROXY +G_IS_DBUS_PROXY +G_TYPE_DBUS_PROXY +G_DBUS_PROXY_CLASS +G_IS_DBUS_PROXY_CLASS +G_DBUS_PROXY_GET_CLASS +G_TYPE_DBUS_PROXY_FLAGS +<SUBSECTION Private> +GDBusProxyPrivate +g_dbus_proxy_get_type +g_dbus_proxy_flags_get_type +</SECTION> + +<SECTION> +<FILE>gdbusintrospection</FILE> +GDBusAnnotationInfo +GDBusArgInfo +GDBusMethodInfo +GDBusSignalInfo +GDBusPropertyInfoFlags +GDBusPropertyInfo +GDBusInterfaceInfo +GDBusNodeInfo +g_dbus_annotation_info_lookup +g_dbus_interface_info_lookup_method +g_dbus_interface_info_lookup_signal +g_dbus_interface_info_lookup_property +g_dbus_interface_info_cache_build +g_dbus_interface_info_cache_release +g_dbus_interface_info_generate_xml +g_dbus_node_info_new_for_xml +g_dbus_node_info_lookup_interface +g_dbus_node_info_generate_xml +G_TYPE_DBUS_NODE_INFO +G_TYPE_DBUS_INTERFACE_INFO +G_TYPE_DBUS_METHOD_INFO +G_TYPE_DBUS_SIGNAL_INFO +G_TYPE_DBUS_PROPERTY_INFO +G_TYPE_DBUS_ARG_INFO +G_TYPE_DBUS_ANNOTATION_INFO +g_dbus_node_info_ref +g_dbus_interface_info_ref +g_dbus_method_info_ref +g_dbus_signal_info_ref +g_dbus_property_info_ref +g_dbus_arg_info_ref +g_dbus_annotation_info_ref +g_dbus_node_info_unref +g_dbus_interface_info_unref +g_dbus_method_info_unref +g_dbus_signal_info_unref +g_dbus_property_info_unref +g_dbus_arg_info_unref +g_dbus_annotation_info_unref +<SUBSECTION Standard> +G_TYPE_DBUS_PROPERTY_INFO_FLAGS +<SUBSECTION Private> +g_dbus_annotation_info_get_type +g_dbus_arg_info_get_type +g_dbus_interface_info_get_type +g_dbus_method_info_get_type +g_dbus_node_info_get_type +g_dbus_property_info_get_type +g_dbus_signal_info_get_type +g_dbus_property_info_flags_get_type +</SECTION> + +<SECTION> +<FILE>gpermission</FILE> +GPermission +g_permission_get_allowed +g_permission_get_can_acquire +g_permission_get_can_release +<SUBSECTION> +g_permission_acquire +g_permission_acquire_async +g_permission_acquire_finish +g_permission_release +g_permission_release_async +g_permission_release_finish +<SUBSECTION> +g_permission_impl_update +<SUBSECTION Standard> +G_PERMISSION +G_PERMISSION_CLASS +G_PERMISSION_GET_CLASS +G_IS_PERMISSION +G_IS_PERMISSION_CLASS +GPermissionClass +G_TYPE_PERMISSION +<SUBSECTION Private> +g_permission_get_type +GPermissionPrivate +</SECTION> + +<SECTION> +<FILE>gsimplepermission</FILE> +GSimplePermission +g_simple_permission_new + +<SUBSECTION Standard> +G_SIMPLE_PERMISSION +G_IS_SIMPLE_PERMISSION +G_TYPE_SIMPLE_PERMISSION + +<SUBSECTION Private> +g_simple_permission_get_type +</SECTION> + +<SECTION> +<FILE>gapplication</FILE> +GApplication +GApplicationClass +<SUBSECTION> +GApplicationFlags +g_application_id_is_valid +g_application_new +<SUBSECTION> +g_application_get_application_id +g_application_set_application_id +<SUBSECTION> +g_application_get_inactivity_timeout +g_application_set_inactivity_timeout +<SUBSECTION> +g_application_get_flags +g_application_set_flags +<SUBSECTION> +g_application_get_resource_base_path +g_application_set_resource_base_path +<SUBSECTION> +g_application_get_dbus_connection +g_application_get_dbus_object_path +<SUBSECTION> +g_application_set_action_group +<SUBSECTION> +g_application_get_is_registered +g_application_get_is_remote +g_application_register +<SUBSECTION> +g_application_hold +g_application_release +g_application_quit +<SUBSECTION> +g_application_activate +g_application_open +<SUBSECTION> +g_application_send_notification +g_application_withdraw_notification +<SUBSECTION> +g_application_run +g_application_add_main_option_entries +g_application_add_main_option +g_application_add_option_group +g_application_set_option_context_parameter_string +g_application_set_option_context_summary +g_application_set_option_context_description +<SUBSECTION> +g_application_set_default +g_application_get_default +<SUBSECTION> +g_application_mark_busy +g_application_unmark_busy +g_application_get_is_busy +g_application_bind_busy_property +g_application_unbind_busy_property +<SUBSECTION Standard> +G_TYPE_APPLICATION +G_APPLICATION +G_APPLICATION_CLASS +G_IS_APPLICATION +G_IS_APPLICATION_CLASS +G_APPLICATION_GET_CLASS +G_TYPE_APPLICATION_FLAGS +<SUBSECTION Private> +GApplicationPrivate +g_application_get_type +g_application_flags_get_type +</SECTION> + +<SECTION> +<FILE>gapplicationcommandline</FILE> +GApplicationCommandLine +GApplicationCommandLineClass +<SUBSECTION> +g_application_command_line_get_arguments +g_application_command_line_get_cwd +g_application_command_line_get_environ +g_application_command_line_get_options_dict +g_application_command_line_get_stdin +g_application_command_line_create_file_for_arg +g_application_command_line_getenv +g_application_command_line_get_is_remote +g_application_command_line_get_platform_data +<SUBSECTION> +g_application_command_line_set_exit_status +g_application_command_line_get_exit_status +<SUBSECTION> +g_application_command_line_print +g_application_command_line_printerr +<SUBSECTION Standard> +G_TYPE_APPLICATION_COMMAND_LINE +G_APPLICATION_COMMAND_LINE +G_APPLICATION_COMMAND_LINE_CLASS +G_IS_APPLICATION_COMMAND_LINE +G_IS_APPLICATION_COMMAND_LINE_CLASS +G_APPLICATION_COMMAND_LINE_GET_CLASS +<SUBSECTION Private> +GApplicationCommandLinePrivate +g_application_command_line_get_type +</SECTION> + + +<SECTION> +<FILE>gactiongroup</FILE> +<TITLE>GActionGroup</TITLE> +GActionGroup +GActionGroupInterface + +<SUBSECTION> +g_action_group_list_actions +g_action_group_query_action + +<SUBSECTION> +g_action_group_has_action +g_action_group_get_action_enabled +g_action_group_get_action_parameter_type +g_action_group_get_action_state_type +g_action_group_get_action_state_hint +g_action_group_get_action_state + +<SUBSECTION> +g_action_group_change_action_state +g_action_group_activate_action + +<SUBSECTION> +g_action_group_action_added +g_action_group_action_removed +g_action_group_action_enabled_changed +g_action_group_action_state_changed + +<SUBSECTION Standard> +g_action_group_get_type +G_TYPE_ACTION_GROUP +G_IS_ACTION_GROUP +G_ACTION_GROUP_GET_IFACE +G_ACTION_GROUP +</SECTION> + +<SECTION> +<FILE>gactiongroupexporter</FILE> +g_dbus_connection_export_action_group +g_dbus_connection_unexport_action_group +</SECTION> + +<SECTION> +<FILE>gdbusactiongroup</FILE> +GDBusActionGroup +g_dbus_action_group_get + +<SUBSECTION Standard> +G_TYPE_DBUS_ACTION_GROUP +G_DBUS_ACTION_GROUP +G_DBUS_ACTION_GROUP_CLASS +G_IS_DBUS_ACTION_GROUP +G_IS_DBUS_ACTION_GROUP_CLASS +G_DBUS_ACTION_GROUP_GET_CLASS + +<SUBSECTION Private> +g_dbus_action_group_get_type +</SECTION> + +<SECTION> +<FILE>gremoteactiongroup</FILE> +GRemoteActionGroup +GRemoteActionGroupInterface + +<SUBSECTION> +g_remote_action_group_activate_action_full +g_remote_action_group_change_action_state_full + +<SUBSECTION Standard> +G_TYPE_REMOTE_ACTION_GROUP +G_REMOTE_ACTION_GROUP +G_IS_REMOTE_ACTION_GROUP +G_REMOTE_ACTION_GROUP_GET_IFACE +g_remote_action_group_get_type +</SECTION> + +<SECTION> +<FILE>gaction</FILE> +<TITLE>GAction</TITLE> +GAction +GActionInterface + +<SUBSECTION> +g_action_name_is_valid +g_action_get_name +g_action_get_parameter_type +g_action_get_state_type +g_action_get_state_hint + +<SUBSECTION> +g_action_get_enabled +g_action_get_state + +<SUBSECTION> +g_action_change_state +g_action_activate + +<SUBSECTION> +g_action_parse_detailed_name +g_action_print_detailed_name + +<SUBSECTION Standard> +g_action_get_type +G_TYPE_ACTION +G_IS_ACTION +G_ACTION_GET_IFACE +G_ACTION +</SECTION> + +<SECTION> +<FILE>gsimpleaction</FILE> +<TITLE>GSimpleAction</TITLE> +GSimpleAction + +<SUBSECTION> +g_simple_action_new +g_simple_action_new_stateful + +<SUBSECTION> +g_simple_action_set_enabled +g_simple_action_set_state +g_simple_action_set_state_hint + +<SUBSECTION Standard> +g_simple_action_get_type +G_TYPE_SIMPLE_ACTION +G_IS_SIMPLE_ACTION +G_SIMPLE_ACTION +</SECTION> + +<SECTION> +<FILE>gpropertyaction</FILE> +<TITLE>GPropertyAction</TITLE> +GPropertyAction + +<SUBSECTION> +g_property_action_new + +<SUBSECTION Standard> +g_property_action_get_type +G_TYPE_PROPERTY_ACTION +G_IS_PROPERTY_ACTION +G_PROPERTY_ACTION +</SECTION> + +<SECTION> +<FILE>gsimpleactiongroup</FILE> +<TITLE>GSimpleActionGroup</TITLE> +GSimpleActionGroup + +<SUBSECTION> +g_simple_action_group_new + +<SUBSECTION> +g_simple_action_group_lookup +g_simple_action_group_insert +g_simple_action_group_remove + +<SUBSECTION> +g_simple_action_group_add_entries + +<SUBSECTION Standard> +GSimpleActionGroupClass +GSimpleActionGroupPrivate +g_simple_action_group_get_type +G_TYPE_SIMPLE_ACTION_GROUP +G_IS_SIMPLE_ACTION_GROUP +G_SIMPLE_ACTION_GROUP_CLASS +G_SIMPLE_ACTION_GROUP_GET_CLASS +G_IS_SIMPLE_ACTION_GROUP_CLASS +G_SIMPLE_ACTION_GROUP +</SECTION> + +<SECTION> +<FILE>gactionmap</FILE> +<TITLE>GActionMap</TITLE> +GActionMap +GActionMapInterface +g_action_map_lookup_action +GActionEntry +g_action_map_add_action_entries +g_action_map_add_action +g_action_map_remove_action + +<SUBSECTION Standard> +G_TYPE_ACTION_MAP +G_ACTION_MAP +G_IS_ACTION_MAP +G_ACTION_MAP_GET_IFACE + +<SUBSECTION Private> +g_action_map_get_type +</SECTION> + +<SECTION> +<FILE>gproxyresolver</FILE> +<TITLE>GProxyResolver</TITLE> +GProxyResolver +GProxyResolverInterface +G_PROXY_RESOLVER_EXTENSION_POINT_NAME +g_proxy_resolver_get_default +g_proxy_resolver_is_supported +g_proxy_resolver_lookup +g_proxy_resolver_lookup_async +g_proxy_resolver_lookup_finish +<SUBSECTION Standard> +G_PROXY_RESOLVER +G_IS_PROXY_RESOLVER +G_TYPE_PROXY_RESOLVER +G_PROXY_RESOLVER_GET_IFACE +<SUBSECTION Private> +g_proxy_resolver_get_type +</SECTION> + +<SECTION> +<FILE>gproxyaddress</FILE> +<TITLE>GProxyAddress</TITLE> +GProxyAddress +GProxyAddressClass +g_proxy_address_get_destination_protocol +g_proxy_address_get_destination_hostname +g_proxy_address_get_destination_port +g_proxy_address_get_password +g_proxy_address_get_protocol +g_proxy_address_get_username +g_proxy_address_get_uri +g_proxy_address_new +<SUBSECTION Standard> +G_PROXY_ADDRESS +G_PROXY_ADDRESS_CLASS +G_PROXY_ADDRESS_GET_CLASS +G_IS_PROXY_ADDRESS +G_IS_PROXY_ADDRESS_CLASS +G_TYPE_PROXY_ADDRESS +<SUBSECTION Private> +GProxyAddressPrivate +g_proxy_address_get_type +</SECTION> + +<SECTION> +<FILE>gproxy</FILE> +<TITLE>GProxy</TITLE> +GProxy +GProxyInterface +G_PROXY_EXTENSION_POINT_NAME +g_proxy_connect +g_proxy_connect_async +g_proxy_connect_finish +g_proxy_get_default_for_protocol +g_proxy_supports_hostname +<SUBSECTION Standard> +G_PROXY +G_PROXY_GET_IFACE +G_IS_PROXY +G_TYPE_PROXY +<SUBSECTION Private> +g_proxy_get_type +</SECTION> + +<SECTION> +<FILE>gpollableinputstream</FILE> +<TITLE>GPollableInputStream</TITLE> +GPollableInputStream +GPollableInputStreamInterface +<SUBSECTION> +g_pollable_input_stream_can_poll +g_pollable_input_stream_is_readable +g_pollable_input_stream_create_source +g_pollable_input_stream_read_nonblocking +<SUBSECTION Standard> +G_POLLABLE_INPUT_STREAM +G_POLLABLE_INPUT_STREAM_GET_INTERFACE +G_IS_POLLABLE_INPUT_STREAM +G_TYPE_POLLABLE_INPUT_STREAM +<SUBSECTION Private> +g_pollable_input_stream_get_type +</SECTION> + +<SECTION> +<FILE>gpollableoutputstream</FILE> +<TITLE>GPollableOutputStream</TITLE> +GPollableOutputStream +GPollableOutputStreamInterface +<SUBSECTION> +g_pollable_output_stream_can_poll +g_pollable_output_stream_is_writable +g_pollable_output_stream_create_source +g_pollable_output_stream_write_nonblocking +g_pollable_output_stream_writev_nonblocking +<SUBSECTION Standard> +G_POLLABLE_OUTPUT_STREAM +G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE +G_IS_POLLABLE_OUTPUT_STREAM +G_TYPE_POLLABLE_OUTPUT_STREAM +<SUBSECTION Private> +g_pollable_output_stream_get_type +</SECTION> + +<SECTION> +<FILE>gpollableutils</FILE> +GPollableReturn +GPollableSourceFunc +g_pollable_source_new +g_pollable_source_new_full +<SUBSECTION> +g_pollable_stream_read +g_pollable_stream_write +g_pollable_stream_write_all +<SUBSECTION Standard> +G_TYPE_POLLABLE_RETURN +<SUBSECTION Private> +g_pollable_return_get_type +</SECTION> + +<SECTION> +<FILE>gtls</FILE> +G_TLS_ERROR +GTlsError +<SUBSECTION> +GTlsAuthenticationMode +GTlsCertificateFlags +<SUBSECTION Standard> +G_TYPE_TLS_AUTHENTICATION_MODE +G_TYPE_TLS_CERTIFICATE_FLAGS +G_TYPE_TLS_ERROR +g_tls_authentication_mode_get_type +g_tls_certificate_flags_get_type +g_tls_error_get_type +</SECTION> + +<SECTION> +<FILE>gtlsbackend</FILE> +<TITLE>GTlsBackend</TITLE> +G_TLS_BACKEND_EXTENSION_POINT_NAME +GTlsBackend +GTlsBackendInterface +g_tls_backend_get_default +g_tls_backend_supports_tls +g_tls_backend_supports_dtls +g_tls_backend_get_default_database +g_tls_backend_set_default_database +g_tls_backend_get_certificate_type +g_tls_backend_get_client_connection_type +g_tls_backend_get_server_connection_type +g_tls_backend_get_dtls_client_connection_type +g_tls_backend_get_dtls_server_connection_type +g_tls_backend_get_file_database_type +<SUBSECTION Standard> +G_IS_TLS_BACKEND +G_TLS_BACKEND +G_TLS_BACKEND_GET_INTERFACE +G_TYPE_TLS_BACKEND +g_tls_error_quark +<SUBSECTION Private> +g_tls_backend_get_type +</SECTION> + +<SECTION> +<FILE>gtlscertificate</FILE> +<TITLE>GTlsCertificate</TITLE> +GTlsCertificate +g_tls_certificate_new_from_pem +g_tls_certificate_new_from_file +g_tls_certificate_new_from_files +g_tls_certificate_list_new_from_file +g_tls_certificate_get_issuer +g_tls_certificate_verify +g_tls_certificate_is_same +<SUBSECTION Standard> +GTlsCertificateClass +GTlsCertificatePrivate +G_IS_TLS_CERTIFICATE +G_IS_TLS_CERTIFICATE_CLASS +G_TLS_CERTIFICATE +G_TLS_CERTIFICATE_CLASS +G_TLS_CERTIFICATE_GET_CLASS +G_TYPE_TLS_CERTIFICATE +<SUBSECTION Private> +g_tls_certificate_get_type +</SECTION> + +<SECTION> +<FILE>gtlsconnection</FILE> +<TITLE>GTlsConnection</TITLE> +GTlsConnection +g_tls_connection_set_certificate +g_tls_connection_get_certificate +g_tls_connection_get_peer_certificate +g_tls_connection_get_peer_certificate_errors +g_tls_connection_set_require_close_notify +g_tls_connection_get_require_close_notify +GTlsRehandshakeMode +g_tls_connection_set_rehandshake_mode +g_tls_connection_get_rehandshake_mode +g_tls_connection_set_advertised_protocols +g_tls_connection_get_negotiated_protocol +g_tls_connection_set_use_system_certdb +g_tls_connection_get_use_system_certdb +g_tls_connection_get_database +g_tls_connection_set_database +g_tls_connection_get_interaction +g_tls_connection_set_interaction +<SUBSECTION> +g_tls_connection_handshake +g_tls_connection_handshake_async +g_tls_connection_handshake_finish +<SUBSECTION> +g_tls_connection_emit_accept_certificate +<SUBSECTION Standard> +GTlsConnectionClass +GTlsConnectionPrivate +G_IS_TLS_CONNECTION +G_IS_TLS_CONNECTION_CLASS +G_TLS_CONNECTION +G_TLS_CONNECTION_CLASS +G_TLS_CONNECTION_GET_CLASS +G_TYPE_TLS_CONNECTION +G_TYPE_TLS_REHANDSHAKE_MODE +<SUBSECTION Private> +g_tls_connection_get_type +g_tls_rehandshake_mode_get_type +</SECTION> + +<SECTION> +<FILE>gtlsclientconnection</FILE> +<TITLE>GTlsClientConnection</TITLE> +GTlsClientConnection +GTlsClientConnectionInterface +g_tls_client_connection_new +g_tls_client_connection_set_server_identity +g_tls_client_connection_get_server_identity +g_tls_client_connection_set_validation_flags +g_tls_client_connection_get_validation_flags +g_tls_client_connection_set_use_ssl3 +g_tls_client_connection_get_use_ssl3 +g_tls_client_connection_get_accepted_cas +g_tls_client_connection_copy_session_state +<SUBSECTION Standard> +G_IS_TLS_CLIENT_CONNECTION +G_TLS_CLIENT_CONNECTION +G_TLS_CLIENT_CONNECTION_GET_INTERFACE +G_TYPE_TLS_CLIENT_CONNECTION +<SUBSECTION Private> +g_tls_client_connection_get_type +</SECTION> + +<SECTION> +<FILE>gtlsdatabase</FILE> +<TITLE>GTlsDatabase</TITLE> +GTlsDatabase +GTlsDatabaseClass +GTlsDatabaseVerifyFlags +G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER +G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT +g_tls_database_verify_chain +g_tls_database_verify_chain_async +g_tls_database_verify_chain_finish +GTlsDatabaseLookupFlags +g_tls_database_lookup_certificate_issuer +g_tls_database_lookup_certificate_issuer_async +g_tls_database_lookup_certificate_issuer_finish +g_tls_database_lookup_certificates_issued_by +g_tls_database_lookup_certificates_issued_by_async +g_tls_database_lookup_certificates_issued_by_finish +g_tls_database_create_certificate_handle +g_tls_database_lookup_certificate_for_handle +g_tls_database_lookup_certificate_for_handle_async +g_tls_database_lookup_certificate_for_handle_finish +<SUBSECTION Standard> +G_IS_TLS_DATABASE +G_IS_TLS_DATABASE_CLASS +G_TLS_DATABASE +G_TLS_DATABASE_CLASS +G_TLS_DATABASE_GET_CLASS +G_TYPE_TLS_DATABASE +G_TYPE_TLS_DATABASE_LOOKUP_FLAGS +G_TYPE_TLS_DATABASE_VERIFY_FLAGS +<SUBSECTION Private> +g_tls_database_lookup_flags_get_type +g_tls_database_verify_flags_get_type +g_tls_database_get_type +GTlsDatabasePrivate +</SECTION> + +<SECTION> +<FILE>gtlsfiledatabase</FILE> +<TITLE>GTlsFileDatabase</TITLE> +GTlsFileDatabase +GTlsFileDatabaseInterface +g_tls_file_database_new +<SUBSECTION Standard> +G_TLS_FILE_DATABASE +G_TLS_FILE_DATABASE_GET_INTERFACE +G_TYPE_TLS_FILE_DATABASE +G_IS_TLS_FILE_DATABASE +<SUBSECTION Private> +g_tls_file_database_get_type +</SECTION> + +<SECTION> +<FILE>gtlsserverconnection</FILE> +<TITLE>GTlsServerConnection</TITLE> +GTlsServerConnection +GTlsServerConnectionInterface +g_tls_server_connection_new +<SUBSECTION Standard> +G_IS_TLS_SERVER_CONNECTION +G_TLS_SERVER_CONNECTION +G_TLS_SERVER_CONNECTION_GET_INTERFACE +G_TYPE_TLS_SERVER_CONNECTION +<SUBSECTION Private> +g_tls_server_connection_get_type +</SECTION> + +<SECTION> +<FILE>gtlspassword</FILE> +<TITLE>GTlsPassword</TITLE> +GTlsPassword +GTlsPasswordClass +GTlsPasswordFlags +g_tls_password_new +g_tls_password_get_value +g_tls_password_set_value +g_tls_password_set_value_full +g_tls_password_get_description +g_tls_password_set_description +g_tls_password_get_flags +g_tls_password_set_flags +g_tls_password_get_warning +g_tls_password_set_warning +<SUBSECTION Standard> +g_tls_password_flags_get_type +g_tls_password_get_type +G_IS_TLS_PASSWORD +G_TLS_PASSWORD +G_TYPE_TLS_PASSWORD +G_TYPE_TLS_PASSWORD_FLAGS +G_TLS_PASSWORD_CLASS +G_TLS_PASSWORD_GET_CLASS +G_IS_TLS_PASSWORD_CLASS +<SUBSECTION Private> +GTlsPasswordPrivate +</SECTION> + +<SECTION> +<FILE>gtlsinteraction</FILE> +<TITLE>GTlsInteraction</TITLE> +GTlsInteraction +GTlsInteractionResult +GTlsCertificateRequestFlags +GTlsInteractionClass +g_tls_interaction_invoke_ask_password +g_tls_interaction_invoke_request_certificate +g_tls_interaction_ask_password +g_tls_interaction_ask_password_async +g_tls_interaction_ask_password_finish +g_tls_interaction_request_certificate +g_tls_interaction_request_certificate_async +g_tls_interaction_request_certificate_finish +<SUBSECTION Standard> +G_IS_TLS_INTERACTION +G_IS_TLS_INTERACTION_CLASS +G_TYPE_TLS_INTERACTION +G_TLS_INTERACTION +G_TLS_INTERACTION_CLASS +G_TLS_INTERACTION_GET_CLASS +G_TYPE_TLS_INTERACTION_RESULT +G_TYPE_TLS_CERTIFICATE_REQUEST_FLAGS +<SUBSECTION Private> +GTlsInteractionPrivate +g_tls_interaction_get_type +g_tls_interaction_result_get_type +g_tls_certificate_request_flags_get_type +</SECTION> + +<SECTION> +<FILE>gdtlsconnection</FILE> +<TITLE>GDtlsConnection</TITLE> +GDtlsConnection +g_dtls_connection_set_certificate +g_dtls_connection_get_certificate +g_dtls_connection_get_peer_certificate +g_dtls_connection_get_peer_certificate_errors +g_dtls_connection_set_require_close_notify +g_dtls_connection_get_require_close_notify +g_dtls_connection_set_rehandshake_mode +g_dtls_connection_get_rehandshake_mode +g_dtls_connection_set_advertised_protocols +g_dtls_connection_get_negotiated_protocol +g_dtls_connection_get_database +g_dtls_connection_set_database +g_dtls_connection_get_interaction +g_dtls_connection_set_interaction +<SUBSECTION> +g_dtls_connection_handshake +g_dtls_connection_handshake_async +g_dtls_connection_handshake_finish +<SUBSECTION> +g_dtls_connection_shutdown +g_dtls_connection_shutdown_async +g_dtls_connection_shutdown_finish +g_dtls_connection_close +g_dtls_connection_close_async +g_dtls_connection_close_finish +<SUBSECTION> +g_dtls_connection_emit_accept_certificate +<SUBSECTION Standard> +GDtlsConnectionClass +GDtlsConnectionPrivate +G_IS_DTLS_CONNECTION +G_IS_DTLS_CONNECTION_CLASS +G_DTLS_CONNECTION +G_DTLS_CONNECTION_CLASS +G_DTLS_CONNECTION_GET_CLASS +G_TYPE_DTLS_CONNECTION +G_DTLS_CONNECTION_GET_INTERFACE +<SUBSECTION Private> +g_dtls_connection_get_type +</SECTION> + +<SECTION> +<FILE>gdtlsclientconnection</FILE> +<TITLE>GDtlsClientConnection</TITLE> +GDtlsClientConnection +GDtlsClientConnectionInterface +g_dtls_client_connection_new +g_dtls_client_connection_set_server_identity +g_dtls_client_connection_get_server_identity +g_dtls_client_connection_set_validation_flags +g_dtls_client_connection_get_validation_flags +g_dtls_client_connection_get_accepted_cas +<SUBSECTION Standard> +G_IS_DTLS_CLIENT_CONNECTION +G_DTLS_CLIENT_CONNECTION +G_DTLS_CLIENT_CONNECTION_GET_INTERFACE +G_TYPE_DTLS_CLIENT_CONNECTION +<SUBSECTION Private> +g_dtls_client_connection_get_type +</SECTION> + +<SECTION> +<FILE>gdtlsserverconnection</FILE> +<TITLE>GDtlsServerConnection</TITLE> +GDtlsServerConnection +GDtlsServerConnectionInterface +g_dtls_server_connection_new +<SUBSECTION Standard> +G_IS_DTLS_SERVER_CONNECTION +G_DTLS_SERVER_CONNECTION +G_DTLS_SERVER_CONNECTION_GET_INTERFACE +G_TYPE_DTLS_SERVER_CONNECTION +<SUBSECTION Private> +g_dtls_server_connection_get_type +</SECTION> + +<SECTION> +<FILE>gdbusinterface</FILE> +<TITLE>GDBusInterface</TITLE> +GDBusInterface +GDBusInterfaceIface +g_dbus_interface_get_info +g_dbus_interface_get_object +g_dbus_interface_dup_object +g_dbus_interface_set_object +<SUBSECTION Standard> +G_DBUS_INTERFACE +G_IS_DBUS_INTERFACE +G_TYPE_DBUS_INTERFACE +g_dbus_interface_get_type +G_DBUS_INTERFACE_GET_IFACE +</SECTION> + + +<SECTION> +<FILE>gdbusinterfaceskeleton</FILE> +<TITLE>GDBusInterfaceSkeleton</TITLE> +GDBusInterfaceSkeleton +GDBusInterfaceSkeletonClass +g_dbus_interface_skeleton_flush +g_dbus_interface_skeleton_get_info +g_dbus_interface_skeleton_get_vtable +g_dbus_interface_skeleton_get_properties +g_dbus_interface_skeleton_export +g_dbus_interface_skeleton_unexport +g_dbus_interface_skeleton_unexport_from_connection +g_dbus_interface_skeleton_get_connection +g_dbus_interface_skeleton_get_connections +g_dbus_interface_skeleton_has_connection +g_dbus_interface_skeleton_get_object_path +GDBusInterfaceSkeletonFlags +g_dbus_interface_skeleton_get_flags +g_dbus_interface_skeleton_set_flags +<SUBSECTION Standard> +G_DBUS_INTERFACE_SKELETON +G_IS_DBUS_INTERFACE_SKELETON +G_TYPE_DBUS_INTERFACE_SKELETON +g_dbus_interface_skeleton_get_type +G_DBUS_INTERFACE_SKELETON_CLASS +G_IS_DBUS_INTERFACE_SKELETON_CLASS +G_DBUS_INTERFACE_SKELETON_GET_CLASS +<SUBSECTION Private> +GDBusInterfaceSkeletonPrivate +G_TYPE_DBUS_INTERFACE_SKELETON_FLAGS +g_dbus_interface_skeleton_flags_get_type +</SECTION> + +<SECTION> +<FILE>gdbusobject</FILE> +<TITLE>GDBusObject</TITLE> +GDBusObject +GDBusObjectIface +g_dbus_object_get_object_path +g_dbus_object_get_interfaces +g_dbus_object_get_interface +<SUBSECTION Standard> +G_DBUS_OBJECT +G_IS_DBUS_OBJECT +G_TYPE_DBUS_OBJECT +g_dbus_object_get_type +G_DBUS_OBJECT_GET_IFACE +</SECTION> + +<SECTION> +<FILE>gdbusobjectproxy</FILE> +<TITLE>GDBusObjectProxy</TITLE> +GDBusObjectProxy +GDBusObjectProxyClass +g_dbus_object_proxy_new +g_dbus_object_proxy_get_connection +<SUBSECTION Standard> +G_DBUS_OBJECT_PROXY +G_IS_DBUS_OBJECT_PROXY +G_TYPE_DBUS_OBJECT_PROXY +g_dbus_object_proxy_get_type +G_DBUS_OBJECT_PROXY_CLASS +G_IS_DBUS_OBJECT_PROXY_CLASS +G_DBUS_OBJECT_PROXY_GET_CLASS +<SUBSECTION Private> +GDBusObjectProxyPrivate +</SECTION> + +<SECTION> +<FILE>gdbusobjectskeleton</FILE> +<TITLE>GDBusObjectSkeleton</TITLE> +GDBusObjectSkeleton +GDBusObjectSkeletonClass +g_dbus_object_skeleton_new +g_dbus_object_skeleton_flush +g_dbus_object_skeleton_add_interface +g_dbus_object_skeleton_remove_interface +g_dbus_object_skeleton_remove_interface_by_name +g_dbus_object_skeleton_set_object_path +<SUBSECTION Standard> +G_DBUS_OBJECT_SKELETON +G_IS_DBUS_OBJECT_SKELETON +G_TYPE_DBUS_OBJECT_SKELETON +g_dbus_object_skeleton_get_type +G_DBUS_OBJECT_SKELETON_CLASS +G_IS_DBUS_OBJECT_SKELETON_CLASS +G_DBUS_OBJECT_SKELETON_GET_CLASS +<SUBSECTION Private> +GDBusObjectSkeletonPrivate +</SECTION> + +<SECTION> +<FILE>gdbusobjectmanager</FILE> +<TITLE>GDBusObjectManager</TITLE> +GDBusObjectManager +GDBusObjectManagerIface +g_dbus_object_manager_get_object_path +g_dbus_object_manager_get_objects +g_dbus_object_manager_get_object +g_dbus_object_manager_get_interface +<SUBSECTION Standard> +G_DBUS_OBJECT_MANAGER +G_IS_DBUS_OBJECT_MANAGER +G_TYPE_DBUS_OBJECT_MANAGER +g_dbus_object_manager_get_type +G_DBUS_OBJECT_MANAGER_GET_IFACE +</SECTION> + +<SECTION> +<FILE>gdbusobjectmanagerclient</FILE> +<TITLE>GDBusObjectManagerClient</TITLE> +GDBusObjectManagerClient +GDBusObjectManagerClientClass +GDBusObjectManagerClientFlags +GDBusProxyTypeFunc +g_dbus_object_manager_client_new +g_dbus_object_manager_client_new_finish +g_dbus_object_manager_client_new_sync +g_dbus_object_manager_client_new_for_bus +g_dbus_object_manager_client_new_for_bus_finish +g_dbus_object_manager_client_new_for_bus_sync +g_dbus_object_manager_client_get_connection +g_dbus_object_manager_client_get_flags +g_dbus_object_manager_client_get_name +g_dbus_object_manager_client_get_name_owner +<SUBSECTION Standard> +G_DBUS_OBJECT_MANAGER_CLIENT +G_IS_DBUS_OBJECT_MANAGER_CLIENT +G_TYPE_DBUS_OBJECT_MANAGER_CLIENT +g_dbus_object_manager_client_get_type +G_DBUS_OBJECT_MANAGER_CLIENT_CLASS +G_IS_DBUS_OBJECT_MANAGER_CLIENT_CLASS +G_DBUS_OBJECT_MANAGER_CLIENT_GET_CLASS +<SUBSECTION Private> +GDBusObjectManagerClientPrivate +G_TYPE_DBUS_OBJECT_MANAGER_CLIENT_FLAGS +g_dbus_object_manager_client_flags_get_type +</SECTION> + +<SECTION> +<FILE>gdbusobjectmanagerserver</FILE> +<TITLE>GDBusObjectManagerServer</TITLE> +GDBusObjectManagerServer +GDBusObjectManagerServerClass +g_dbus_object_manager_server_new +g_dbus_object_manager_server_get_connection +g_dbus_object_manager_server_set_connection +g_dbus_object_manager_server_export +g_dbus_object_manager_server_export_uniquely +g_dbus_object_manager_server_is_exported +g_dbus_object_manager_server_unexport +<SUBSECTION Standard> +G_DBUS_OBJECT_MANAGER_SERVER +G_IS_DBUS_OBJECT_MANAGER_SERVER +G_TYPE_DBUS_OBJECT_MANAGER_SERVER +g_dbus_object_manager_server_get_type +G_DBUS_OBJECT_MANAGER_SERVER_CLASS +G_IS_DBUS_OBJECT_MANAGER_SERVER_CLASS +G_DBUS_OBJECT_MANAGER_SERVER_GET_CLASS +<SUBSECTION Private> +GDBusObjectManagerServerPrivate +</SECTION> + +<SECTION> +<FILE>gmemorymonitor</FILE> +<TITLE>GMemoryMonitor</TITLE> +GMemoryMonitor +GMemoryMonitorInterface +GMemoryMonitorWarningLevel +G_MEMORY_MONITOR_EXTENSION_POINT_NAME +g_memory_monitor_dup_default +<SUBSECTION Standard> +g_memory_monitor_get_type +G_TYPE_MEMORY_MONITOR +G_MEMORY_MONITOR +G_IS_MEMORY_MONITOR +G_MEMORY_MONITOR_GET_INTERFACE +G_TYPE_MEMORY_MONITOR_WARNING_LEVEL +g_memory_monitor_warning_level_get_type +</SECTION> + +<SECTION> +<FILE>gnetworkmonitor</FILE> +<TITLE>GNetworkMonitor</TITLE> +GNetworkMonitor +GNetworkMonitorInterface +G_NETWORK_MONITOR_EXTENSION_POINT_NAME +g_network_monitor_get_default +g_network_monitor_get_network_available +g_network_monitor_get_network_metered +g_network_monitor_can_reach +g_network_monitor_can_reach_async +g_network_monitor_can_reach_finish +GNetworkConnectivity +g_network_monitor_get_connectivity +<SUBSECTION Standard> +g_network_monitor_get_type +G_TYPE_NETWORK_CONNECTIVITY +G_TYPE_NETWORK_MONITOR +G_NETWORK_MONITOR +G_IS_NETWORK_MONITOR +G_NETWORK_MONITOR_GET_INTERFACE +g_network_connectivity_get_type +</SECTION> + +<SECTION> +<FILE>gmenuexporter</FILE> +g_dbus_connection_export_menu_model +g_dbus_connection_unexport_menu_model +</SECTION> + +<SECTION> +<FILE>gdbusmenumodel</FILE> +GDBusMenuModel +g_dbus_menu_model_get + +<SUBSECTION Standard> +G_TYPE_DBUS_MENU_MODEL +G_DBUS_MENU_MODEL +G_IS_DBUS_MENU_MODEL + +<SUBSECTION Private> +g_dbus_menu_model_get_type +</SECTION> + +<SECTION> +<FILE>gmenu</FILE> +GMenu +g_menu_new +g_menu_freeze + +<SUBSECTION> +g_menu_insert +g_menu_prepend +g_menu_append + +<SUBSECTION> +g_menu_insert_item +g_menu_append_item +g_menu_prepend_item + +<SUBSECTION> +g_menu_insert_section +g_menu_prepend_section +g_menu_append_section + +<SUBSECTION> +g_menu_append_submenu +g_menu_insert_submenu +g_menu_prepend_submenu + +<SUBSECTION> +g_menu_remove +g_menu_remove_all + +<SUBSECTION> +GMenuItem +g_menu_item_new +g_menu_item_new_section +g_menu_item_new_submenu +g_menu_item_new_from_model + +<SUBSECTION> +g_menu_item_set_label +g_menu_item_set_icon +g_menu_item_set_action_and_target_value +g_menu_item_set_action_and_target +g_menu_item_set_detailed_action +g_menu_item_set_section +g_menu_item_set_submenu + +<SUBSECTION> +g_menu_item_get_attribute_value +g_menu_item_get_attribute +g_menu_item_get_link +g_menu_item_set_attribute_value +g_menu_item_set_attribute +g_menu_item_set_link + +<SUBSECTION Private> +g_menu_item_get_type +g_menu_get_type + +<SUBSECTION Standard> +G_TYPE_MENU +G_MENU +G_IS_MENU + +G_TYPE_MENU_ITEM +G_MENU_ITEM +G_IS_MENU_ITEM +</SECTION> + +<SECTION> +<FILE>gmenumodel</FILE> +GMenuModel +g_menu_model_is_mutable +g_menu_model_get_n_items + +<SUBSECTION> +G_MENU_ATTRIBUTE_ACTION +G_MENU_ATTRIBUTE_ACTION_NAMESPACE +G_MENU_ATTRIBUTE_TARGET +G_MENU_ATTRIBUTE_LABEL +G_MENU_ATTRIBUTE_ICON +G_MENU_LINK_SECTION +G_MENU_LINK_SUBMENU + +<SUBSECTION> +g_menu_model_get_item_attribute_value +g_menu_model_get_item_attribute +g_menu_model_get_item_link +g_menu_model_iterate_item_attributes +g_menu_model_iterate_item_links + +<SUBSECTION> +g_menu_model_items_changed + +<SUBSECTION> +GMenuAttributeIter +g_menu_attribute_iter_get_next +g_menu_attribute_iter_get_name +g_menu_attribute_iter_get_value +g_menu_attribute_iter_next + +<SUBSECTION> +GMenuLinkIter +g_menu_link_iter_get_name +g_menu_link_iter_get_next +g_menu_link_iter_get_value +g_menu_link_iter_next + +<SUBSECTION Private> +g_menu_attribute_iter_get_type +g_menu_link_iter_get_type +g_menu_model_get_type +g_menu_model_get_label_quark +g_menu_model_get_action_quark +g_menu_model_get_section_quark +g_menu_model_get_submenu_quark +g_menu_model_get_target_quark + +<SUBSECTION Standard> +GMenuModelClass +GMenuModelPrivate +G_TYPE_MENU_MODEL +G_MENU_MODEL +G_IS_MENU_MODEL +G_MENU_MODEL_CLASS +G_IS_MENU_MODEL_CLASS +G_MENU_MODEL_GET_CLASS + +GMenuAttributeIterClass +GMenuAttributeIterPrivate +G_TYPE_MENU_LINK_ITER +G_MENU_LINK_ITER +G_IS_MENU_LINK_ITER +G_MENU_LINK_ITER_CLASS +G_IS_MENU_LINK_ITER_CLASS +G_MENU_LINK_ITER_GET_CLASS + +GMenuLinkIterClass +GMenuLinkIterPrivate +G_TYPE_MENU_ATTRIBUTE_ITER +G_MENU_ATTRIBUTE_ITER +G_IS_MENU_ATTRIBUTE_ITER +G_MENU_ATTRIBUTE_ITER_CLASS +G_IS_MENU_ATTRIBUTE_ITER_CLASS +G_MENU_ATTRIBUTE_ITER_GET_CLASS +</SECTION> + +<SECTION> +<FILE>gresource</FILE> +<TITLE>GResource</TITLE> +GResource +GResourceFlags +GResourceLookupFlags +g_resource_load +g_resource_new_from_data +g_resource_ref +g_resource_unref +g_resource_lookup_data +g_resource_open_stream +g_resource_enumerate_children +g_resource_get_info + +<SUBSECTION Static> +GStaticResource +g_static_resource_init +g_static_resource_fini +g_static_resource_get_resource + +<SUBSECTION Global> +g_resources_register +g_resources_unregister +g_resources_lookup_data +g_resources_open_stream +g_resources_enumerate_children +g_resources_get_info + +<SUBSECTION> +G_RESOURCE_ERROR +GResourceError + +<SUBSECTION Standard> +G_TYPE_RESOURCE +G_TYPE_RESOURCE_ERROR +G_TYPE_RESOURCE_FILE +G_TYPE_RESOURCE_FLAGS +G_TYPE_RESOURCE_LOOKUP_FLAGS + +<SUBSECTION Private> +g_resource_get_type +g_resource_error_get_type +g_resource_flags_get_type +g_resource_lookup_flags_get_type +g_resource_error_quark +</SECTION> + +<SECTION> +<FILE>gtestdbus</FILE> +<TITLE>GTestDBus</TITLE> +GTestDBus +GTestDBusFlags +g_test_dbus_new +g_test_dbus_get_flags +g_test_dbus_get_bus_address +g_test_dbus_add_service_dir +g_test_dbus_up +g_test_dbus_stop +g_test_dbus_down +g_test_dbus_unset +<SUBSECTION Private> +g_test_dbus_get_type +g_test_dbus_flags_get_type +<SUBSECTION Standard> +G_TEST_DBUS +G_IS_TEST_DBUS +G_TYPE_TEST_DBUS +G_TYPE_TEST_DBUS_FLAGS +</SECTION> + +<SECTION> +<FILE>gtask</FILE> +<TITLE>GTask</TITLE> +GTask +g_task_new +g_task_set_task_data +g_task_set_priority +g_task_set_check_cancellable +g_task_set_return_on_cancel +g_task_set_source_tag +g_task_set_name +<SUBSECTION> +g_task_report_error +g_task_report_new_error +<SUBSECTION> +g_task_get_task_data +g_task_get_priority +g_task_get_cancellable +g_task_get_check_cancellable +g_task_get_return_on_cancel +g_task_get_context +g_task_get_source_object +g_task_get_source_tag +g_task_get_name +<SUBSECTION> +g_task_return_boolean +g_task_return_int +g_task_return_pointer +g_task_return_value +g_task_return_error +g_task_return_new_error +g_task_return_error_if_cancelled +<SUBSECTION> +g_task_propagate_boolean +g_task_propagate_int +g_task_propagate_pointer +g_task_propagate_value +g_task_had_error +g_task_get_completed +<SUBSECTION> +g_task_run_in_thread +g_task_run_in_thread_sync +GTaskThreadFunc +g_task_attach_source +<SUBSECTION> +g_task_is_valid +<SUBSECTION Standard> +GTaskClass +GTaskPrivate +G_TYPE_TASK +G_TASK +G_IS_TASK +G_TASK_CLASS +G_IS_TASK_CLASS +G_TASK_GET_CLASS +g_task_get_type +</SECTION> + +<SECTION> +<FILE>gnetworking</FILE> +<TITLE>gnetworking.h</TITLE> +g_networking_init +<SUBSECTION Private> +CMSG_LEN +CMSG_SPACE +GLIB_ALIGN_TO_SIZEOF +T_SRV +ws2funcs +</SECTION> + +<SECTION> +<FILE>gsimpleproxyresolver</FILE> +<TITLE>GSimpleProxyResolver</TITLE> +GSimpleProxyResolver +g_simple_proxy_resolver_new +g_simple_proxy_resolver_set_default_proxy +g_simple_proxy_resolver_set_ignore_hosts +g_simple_proxy_resolver_set_uri_proxy +<SUBSECTION Standard> +GSimpleProxyResolverClass +GSimpleProxyResolverPrivate +G_TYPE_SIMPLE_PROXY_RESOLVER +G_SIMPLE_PROXY_RESOLVER +G_IS_SIMPLE_PROXY_RESOLVER +G_SIMPLE_PROXY_RESOLVER_CLASS +G_IS_SIMPLE_PROXY_RESOLVER_CLASS +G_SIMPLE_PROXY_RESOLVER_GET_CLASS +g_simple_proxy_resolver_get_type +</SECTION> + +<SECTION> +<FILE>gsubprocess</FILE> +<TITLE>GSubprocess</TITLE> +GSubprocess +GSubprocessFlags +g_subprocess_new +g_subprocess_newv +g_subprocess_get_identifier +<SUBSECTION IO> +g_subprocess_get_stdin_pipe +g_subprocess_get_stdout_pipe +g_subprocess_get_stderr_pipe +<SUBSECTION Waiting> +g_subprocess_wait +g_subprocess_wait_async +g_subprocess_wait_finish +g_subprocess_wait_check +g_subprocess_wait_check_async +g_subprocess_wait_check_finish +<SUBSECTION Status> +g_subprocess_get_successful +g_subprocess_get_if_exited +g_subprocess_get_exit_status +g_subprocess_get_if_signaled +g_subprocess_get_term_sig +g_subprocess_get_status +<SUBSECTION Control> +g_subprocess_send_signal +g_subprocess_force_exit +<SUBSECTION communicate> +g_subprocess_communicate +g_subprocess_communicate_async +g_subprocess_communicate_finish +g_subprocess_communicate_utf8 +g_subprocess_communicate_utf8_async +g_subprocess_communicate_utf8_finish +<SUBSECTION Standard> +G_IS_SUBPROCESS +G_TYPE_SUBPROCESS +G_SUBPROCESS +G_TYPE_SUBPROCESS_FLAGS +g_subprocess_get_type +g_subprocess_flags_get_type +</SECTION> + +<SECTION> +<FILE>gsubprocesslauncher</FILE> +<TITLE>GSubprocessLauncher</TITLE> +GSubprocessLauncher +g_subprocess_launcher_new +g_subprocess_launcher_spawn +g_subprocess_launcher_spawnv +g_subprocess_launcher_set_environ +g_subprocess_launcher_setenv +g_subprocess_launcher_unsetenv +g_subprocess_launcher_getenv +g_subprocess_launcher_set_cwd +g_subprocess_launcher_set_flags +g_subprocess_launcher_set_stdin_file_path +g_subprocess_launcher_take_stdin_fd +g_subprocess_launcher_set_stdout_file_path +g_subprocess_launcher_take_stdout_fd +g_subprocess_launcher_set_stderr_file_path +g_subprocess_launcher_take_stderr_fd +g_subprocess_launcher_take_fd +g_subprocess_launcher_set_child_setup +<SUBSECTION Standard> +G_IS_SUBPROCESS_LAUNCHER +G_SUBPROCESS_LAUNCHER +G_TYPE_SUBPROCESS_LAUNCHER +g_subprocess_launcher_get_type +</SECTION> + +<SECTION> +<FILE>gnotification</FILE> +<TITLE>GNotification</TITLE> +GNotification +g_notification_new +<SUBSECTION> +g_notification_set_title +g_notification_set_body +g_notification_set_icon +GNotificationPriority +g_notification_set_priority +g_notification_set_urgent +<SUBSECTION> +g_notification_set_default_action +g_notification_set_default_action_and_target +g_notification_set_default_action_and_target_value +<SUBSECTION> +g_notification_add_button +g_notification_add_button_with_target +g_notification_add_button_with_target_value +<SUBSECTION Standard> +G_IS_NOTIFICATION +G_NOTIFICATION +G_TYPE_NOTIFICATION +G_TYPE_NOTIFICATION_BACKEND +g_notification_get_type +G_TYPE_NOTIFICATION_PRIORITY +g_notification_priority_get_type +</SECTION> + +<SECTION> +<FILE>glistmodel</FILE> +<TITLE>GListModel</TITLE> +GListModel +GListModelInterface +<SUBSECTION> +g_list_model_get_item_type +g_list_model_get_n_items +g_list_model_get_item +g_list_model_get_object +g_list_model_items_changed +<SUBSECTION Standard> +G_TYPE_LIST_MODEL +G_LIST_MODEL +G_IS_LIST_MODEL +G_LIST_MODEL_GET_IFACE +<SUBSECTION Private> +g_list_model_get_type +</SECTION> + +<SECTION> +<FILE>gliststore</FILE> +<TITLE>GListStore</TITLE> +GListStore +<SUBSECTION> +g_list_store_new +g_list_store_insert +g_list_store_insert_sorted +g_list_store_append +g_list_store_remove +g_list_store_remove_all +g_list_store_splice +g_list_store_sort +g_list_store_find +g_list_store_find_with_equal_func +<SUBSECTION Standard> +G_TYPE_LIST_STORE +<SUBSECTION Private> +g_list_store_get_type +</SECTION>
diff --git a/docs/reference/gio/gio-sections-win32.txt b/docs/reference/gio/gio-sections-win32.txt new file mode 100644 index 0000000..52d137e --- /dev/null +++ b/docs/reference/gio/gio-sections-win32.txt
@@ -0,0 +1,112 @@ +<SECTION> +<FILE>gwin32inputstream</FILE> +<TITLE>GWin32InputStream</TITLE> +GWin32InputStream +g_win32_input_stream_new +g_win32_input_stream_set_close_handle +g_win32_input_stream_get_close_handle +g_win32_input_stream_get_handle +<SUBSECTION Standard> +GWin32InputStreamClass +G_WIN32_INPUT_STREAM +G_IS_WIN32_INPUT_STREAM +G_TYPE_WIN32_INPUT_STREAM +G_WIN32_INPUT_STREAM_CLASS +G_IS_WIN32_INPUT_STREAM_CLASS +G_WIN32_INPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_win32_input_stream_get_type +GWin32InputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gwin32outputstream</FILE> +<TITLE>GWin32OutputStream</TITLE> +GWin32OutputStream +g_win32_output_stream_new +g_win32_output_stream_set_close_handle +g_win32_output_stream_get_close_handle +g_win32_output_stream_get_handle +<SUBSECTION Standard> +GWin32OutputStreamClass +G_WIN32_OUTPUT_STREAM +G_IS_WIN32_OUTPUT_STREAM +G_TYPE_WIN32_OUTPUT_STREAM +G_WIN32_OUTPUT_STREAM_CLASS +G_IS_WIN32_OUTPUT_STREAM_CLASS +G_WIN32_OUTPUT_STREAM_GET_CLASS +<SUBSECTION Private> +g_win32_output_stream_get_type +GWin32OutputStreamPrivate +</SECTION> + +<SECTION> +<FILE>gwin32registrykey</FILE> + +<SUBSECTION> +GWin32RegistrySubkeyIter +g_win32_registry_subkey_iter_copy +g_win32_registry_subkey_iter_free +g_win32_registry_subkey_iter_assign + +<SUBSECTION> +GWin32RegistryValueIter +g_win32_registry_value_iter_copy +g_win32_registry_value_iter_free +g_win32_registry_value_iter_assign + +<SUBSECTION> +GWin32RegistryKey +g_win32_registry_key_new +g_win32_registry_key_new_w +g_win32_registry_key_get_child +g_win32_registry_key_get_child_w + +<SUBSECTION> +g_win32_registry_subkey_iter_init +g_win32_registry_subkey_iter_clear +g_win32_registry_subkey_iter_n_subkeys +g_win32_registry_subkey_iter_next +g_win32_registry_subkey_iter_get_name +g_win32_registry_subkey_iter_get_name_w + +<SUBSECTION> +g_win32_registry_value_iter_init +g_win32_registry_value_iter_clear +g_win32_registry_value_iter_n_values +g_win32_registry_value_iter_next +GWin32RegistryValueType +g_win32_registry_value_iter_get_value_type +g_win32_registry_value_iter_get_name +g_win32_registry_value_iter_get_name_w +g_win32_registry_value_iter_get_data +g_win32_registry_value_iter_get_data_w + +<SUBSECTION> +g_win32_registry_key_get_value +g_win32_registry_key_get_value_w +g_win32_registry_key_get_path +g_win32_registry_key_get_path_w +GWin32RegistryKeyWatchCallbackFunc +GWin32RegistryKeyWatcherFlags +g_win32_registry_key_watch +g_win32_registry_key_has_changed +g_win32_registry_key_erase_change_indicator + +<SUBSECTION Standard> +GWin32RegistryKeyClass + +<SUBSECTION Private> +GWin32RegistryKeyPrivate +g_win32_registry_key_get_type +g_win32_registry_subkey_iter_get_type +g_win32_registry_value_iter_get_type +G_TYPE_WIN32_REGISTRY_KEY +G_WIN32_REGISTRY_KEY +G_WIN32_REGISTRY_KEY_CLASS +G_IS_WIN32_REGISTRY_KEY +G_IS_WIN32_REGISTRY_KEY_CLASS +G_WIN32_REGISTRY_KEY_GET_CLASS +G_TYPE_WIN32_REGISTRY_SUBKEY_ITER +G_TYPE_WIN32_REGISTRY_VALUE_ITER +</SECTION>
diff --git a/docs/reference/gio/gio.xml b/docs/reference/gio/gio.xml new file mode 100644 index 0000000..641b222 --- /dev/null +++ b/docs/reference/gio/gio.xml
@@ -0,0 +1,775 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> +<refentry id="gio"> + <refentryinfo> + <title>gio</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Matthias</firstname> + <surname>Clasen</surname> + <email>mclasen@redhat.com</email> + </author> + </authorgroup> + </refentryinfo> + + <refmeta> + <refentrytitle>gio</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>gio</refname> + <refpurpose>GIO commandline tool</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">help</arg> + <arg choice="opt"><replaceable>COMMAND</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">version</arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">cat</arg> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">copy</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>SOURCE</replaceable></arg> + <arg choice="plain"><replaceable>DESTINATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">info</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">list</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">mime</arg> + <arg choice="plain"><replaceable>MIMETYPE</replaceable></arg> + <arg choice="opt"><replaceable>HANDLER</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">mkdir</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">monitor</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">mount</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">move</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>SOURCE</replaceable></arg> + <arg choice="plain"><replaceable>DESTINATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">open</arg> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">rename</arg> + <arg choice="plain"><replaceable>LOCATION</replaceable></arg> + <arg choice="plain"><replaceable>NAME</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">remove</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">save</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain"><replaceable>DESTINATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">set</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain"><replaceable>LOCATION</replaceable></arg> + <arg choice="plain"><replaceable>ATTRIBUTE</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>VALUE</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">trash</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gio</command> + <arg choice="plain">tree</arg> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + <para><command>gio</command> is a utility that makes many of the GIO + features available from the commandline. In doing so, it provides + commands that are similar to traditional utilities, but let you + use GIO locations instead of local files: for example you can use + something like <filename>smb://server/resource/file.txt</filename> + as a location.</para> + <para>Plain filenames which contain a colon will be interpreted as URIs + with an unknown protocol. To avoid this, prefix them with a path such as + <filename>./</filename>, or with the <literal>file:</literal> protocol.</para> + </refsect1> + + <refsect1> + <title>Commands</title> + + <variablelist> + <varlistentry> + <term> + <command>help</command> + <arg choice="opt"><replaceable>COMMAND</replaceable></arg> + </term> + <listitem> + <para>Displays a short synopsis of the available commands or provides + detailed help on a specific command.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>version</command> + </term> + <listitem> + <para>Prints the GLib version to which <command>gio</command> + belongs.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>cat</command> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Concatenates the given files and prints them to the standard + output.</para> + <para>The <command>cat</command> command works just like the traditional <command>cat</command> utility.</para> + <para>Note: just pipe through <command>cat</command> if you need its formatting options + like <option>-n</option>, <option>-T</option> or other.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>copy</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>SOURCE</replaceable></arg> + <arg choice="plain"><replaceable>DESTINATION</replaceable></arg> + </term> + <listitem> + <para>Copies one or more files from <replaceable>SOURCE</replaceable> + to <replaceable>DESTINATION</replaceable>. If more than one source + is specified, the destination must be a directory.</para> + <para>The <command>copy</command> command is similar to the traditional <command>cp</command> utility.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-T</option>, <option>--no-target-directory</option></term> + <listitem><para>Don’t copy into <replaceable>DESTINATION</replaceable> even if it is a directory.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-p</option>, <option>--progress</option></term> + <listitem><para>Show progress.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-i</option>, <option>--interactive</option></term> + <listitem><para>Prompt for confirmation before overwriting files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>--preserve</option></term> + <listitem><para>Preserve all attributes of copied files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-b</option>, <option>--backup</option></term> + <listitem><para>Create backups of existing destination files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-P</option>, <option>--no-dereference</option></term> + <listitem><para>Never follow symbolic links.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>--default-permissions</option></term> + <listitem><para>Use the default permissions of the current process for the destination file, rather than copying the permissions of the source file.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + <varlistentry> + <term> + <command>info</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Shows information about the given locations.</para> + <para>The <command>info</command> command is similar to the traditional <command>ls</command> utility.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-w</option>, <option>--query-writable</option></term> + <listitem><para>List writable attributes.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-f</option>, <option>--filesystem</option></term> + <listitem><para>Show information about the filesystem that the given + locations reside on.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-a</option> <option>--attributes=<replaceable>ATTRIBUTES</replaceable></option></term> + <listitem><para>The attributes to get.</para> + <para>Attributes can be specified with their GIO name, e.g. + <literal>standard::icon</literal>, or just by namespace, e.g. <literal>unix</literal>, or by <literal>*</literal>, + which matches all attributes. Several attributes or groups + of attributes can be specified, separated by comma.</para> + <para>By default, all attributes are listed.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-n</option>, <option>--nofollow-symlinks</option></term> + <listitem><para>Don’t follow symbolic links.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>list</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Lists the contents of the given locations. If no location is + given, the contents of the current directory are shown.</para> + <para>The <command>list</command> command is similar to the traditional <command>ls</command> utility.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-a</option> <option>--attributes=<replaceable>ATTRIBUTES</replaceable></option></term> + <listitem><para>The attributes to get.</para> + <para>Attributes can be specified with their GIO name, e.g. + <literal>standard::icon</literal>, or just by namespace, e.g. <literal>unix</literal>, or by <literal>*</literal>, + which matches all attributes. Several attributes or groups + of attributes can be specified, separated by comma.</para> + <para>By default, all attributes are listed.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-h</option>, <option>--hidden</option></term> + <listitem><para>Show hidden files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-l</option>, <option>--long</option></term> + <listitem><para>Use a long listing format.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-n</option>, <option>--nofollow-symlinks</option></term> + <listitem><para>Don’t follow symbolic links.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-d</option>, <option>--print-display-names</option></term> + <listitem><para>Print display names.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-u</option>, <option>--print-uris</option></term> + <listitem><para>Print full URIs.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>mime</command> + <arg choice="plain"><replaceable>MIMETYPE</replaceable></arg> + <arg choice="opt"><replaceable>HANDLER</replaceable></arg> + </term> + <listitem> + <para>If no handler is given, the <command>mime</command> command lists the + registered and recommended applications for the mimetype. + If a handler is given, it is set as the default handler for + the mimetype.</para> + <para>Handlers must be specified by their desktop file name, + including the extension. Example: <literal>org.gnome.gedit.desktop</literal>.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>mkdir</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Creates directories.</para> + <para>The <command>mkdir</command> command is similar to the traditional <command>mkdir</command> utility.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-p</option>, <option>--parent</option></term> + <listitem><para>Create parent directories when necessary.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>monitor</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Monitors files or directories for changes, such as creation + deletion, content and attribute changes, and mount and unmount + operations affecting the monitored locations.</para> + <para>The <command>monitor</command> command uses the GIO file monitoring APIs to do + its job. GIO has different implementations for different platforms. + The most common implementation on Linux uses inotify.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-d</option>, <option>--dir=<replaceable>LOCATION</replaceable></option></term> + <listitem><para>Monitor the given location as a directory. Normally, + the file type is used to determine whether to monitor a file or directory.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-f</option>, <option>--file=<replaceable>LOCATION</replaceable></option></term> + <listitem><para>Monitor the given location as a file. Normally, + the file type is used to determine whether to monitor a file or directory.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-D</option>, <option>--direct=<replaceable>LOCATION</replaceable></option></term> + <listitem><para>Monitor the file directly. This allows changes made via hardlinks to be captured.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-s</option>, <option>--silent=<replaceable>LOCATION</replaceable></option></term> + <listitem><para>Monitor the file directly, but don’t report changes.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-n</option>, <option>--no-moves</option></term> + <listitem><para>Report moves and renames as simple deleted/created events.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-m</option>, <option>--mounts</option></term> + <listitem><para>Watch for mount events.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>mount</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Provides commandline access to various aspects of GIO’s mounting + functionality.</para> + <para>Mounting refers to the traditional concept of arranging multiple + file systems and devices in a single tree, rooted at <filename>/</filename>. Classical + mounting happens in the kernel and is controlled by the mount utility. + GIO expands this concept by introducing mount daemons that can make + file systems available to GIO applications without kernel + involvement.</para> + <para>GIO mounts can require authentication, and the <command>mount</command> command + may ask for user IDs, passwords, and so on, when required.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-m</option>, <option>--mountable</option></term> + <listitem><para>Mount as mountable.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-d</option>, <option>--device=<replaceable>ID</replaceable></option></term> + <listitem><para>Mount volume with device file, or other identifier.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-u</option>, <option>--unmount</option></term> + <listitem><para>Unmount the location.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-e</option>, <option>--eject</option></term> + <listitem><para>Eject the location.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-t</option>, <option>--stop=<replaceable>DEVICE</replaceable></option></term> + <listitem><para>Stop drive with device file.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-s</option>, <option>--unmount-scheme=<replaceable>SCHEME</replaceable></option></term> + <listitem><para>Unmount all mounts with the given scheme.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-f</option>, <option>--force</option></term> + <listitem><para>Ignore outstanding file operations when unmounting or ejecting.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-a</option>, <option>--anonymous</option></term> + <listitem><para>Use an anonymous user when authenticating.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-l</option>, <option>--list</option></term> + <listitem><para>List all GIO mounts.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-o</option>, <option>--monitor</option></term> + <listitem><para>Monitor mount-related events.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>-i</option>, <option>--detail</option></term> + <listitem><para>Show extra information.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>--tcrypt-pim</option></term> + <listitem><para>The numeric PIM when unlocking a VeraCrypt volume.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>--tcrypt-hidden</option></term> + <listitem><para>Mount a TCRYPT hidden volume.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>--tcrypt-system</option></term> + <listitem><para>Mount a TCRYPT system volume.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>move</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>SOURCE</replaceable></arg> + <arg choice="plain"><replaceable>DESTINATION</replaceable></arg> + </term> + <listitem> + <para>Moves one or more files from <replaceable>SOURCE</replaceable> + to <replaceable>DESTINATION</replaceable>. If more than one source + is specified, the destination must be a directory.</para> + <para>The <command>move</command> command is similar to the traditional <command>mv</command> utility.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-T</option>, <option>--no-target-directory</option></term> + <listitem><para>Don’t copy into <replaceable>DESTINATION</replaceable> even if it is a directory.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-p</option>, <option>--progress</option></term> + <listitem><para>Show progress.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-i</option>, <option>--interactive</option></term> + <listitem><para>Prompt for confirmation before overwriting files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-b</option>, <option>--backup</option></term> + <listitem><para>Create backups of existing destination files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-C</option>, <option>--no-copy-fallback</option></term> + <listitem><para>Don’t use copy and delete fallback.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>open</command> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Opens files with the default application that is registered + to handle files of this type.</para> + <para>GIO obtains this information from the shared-mime-info + database, with per-user overrides stored in + <filename><envar>$XDG_DATA_HOME</envar>/applications/mimeapps.list</filename>.</para> + <para>The <command>mime</command> command can be used to change the default handler for + a mimetype.</para> + <para>Environment variables will not be set on the application, as it + may be an existing process which is activated to handle the new file.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>rename</command> + <arg choice="plain"><replaceable>LOCATION</replaceable></arg> + <arg choice="plain"><replaceable>NAME</replaceable></arg> + </term> + <listitem> + <para>Renames a file.</para> + <para>The <command>rename</command> command is similar to the traditional <command>rename</command> utility.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>remove</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Deletes each given file.</para> + <para>This command removes files irreversibly. If you want a reversible + way to remove files, see the <command>trash</command> command.</para> + <para>Note that not all URI schemes that are supported by GIO may + allow deletion of files.</para> + <para>The <command>remove</command> command is similar to the traditional <command>rm</command> utility.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-f</option>, <option>--force</option></term> + <listitem><para>Ignore non-existent and non-deletable files.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>save</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain"><replaceable>DESTINATION</replaceable></arg> + </term> + <listitem> + <para>Reads from standard input and saves the data to the given + location.</para> + <para>This is similar to just redirecting output to a file using + traditional shell syntax, but the <command>save</command> command allows saving to + location that GIO can write to.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-b</option>, <option>--backup</option></term> + <listitem><para>Back up existing destination files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-c</option>, <option>--create</option></term> + <listitem><para>Only create the destination if it doesn’t exist yet.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-a</option>, <option>--append</option></term> + <listitem><para>Append to the end of the file.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-p</option>, <option>--private</option></term> + <listitem><para>When creating, restrict access to the current user.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-u</option>, <option>--unlink</option></term> + <listitem><para>When replacing, replace as if the destination did not exist.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-v</option>, <option>--print-etag</option></term> + <listitem><para>Print the new ETag in the end.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-e</option>, <option>--etag=<replaceable>ETAG</replaceable></option></term> + <listitem><para>The ETag of the file that is overwritten.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>set</command> + <arg choice="plain"><replaceable>LOCATION</replaceable></arg> + <arg choice="plain"><replaceable>ATTRIBUTE</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>VALUE</replaceable></arg> + </term> + <listitem> + <para>Sets a file attribute on a file.</para> + <para>File attributes can be specified with their GIO name, e.g + <literal>standard::icon</literal>. Note that not all GIO file attributes are writable. + Use the <option>--query-writable</option> option of the <command>info</command> command to list + writable file attributes.</para> + <para>If the <replaceable>TYPE</replaceable> is unset, + <replaceable>VALUE</replaceable> does not have to be specified. + If the <replaceable>TYPE</replaceable> is <literal>stringv</literal>, multiple values can be given.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-t</option>, <option>--type=<replaceable>TYPE</replaceable></option></term> + <listitem><para>Specifies the type of the attribute. Supported + types are <literal>string</literal>, <literal>stringv</literal>, + <literal>bytestring</literal>, <literal>boolean</literal>, + <literal>uint32</literal>, <literal>int32</literal>, + <literal>uint64</literal>, <literal>int64</literal> and <literal>unset</literal>.</para> + <para>If the type is not specified, <literal>string</literal> is assumed.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>-n</option>, <option>--nofollow-symlinks</option></term> + <listitem><para>Don’t follow symbolic links.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>trash</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Sends files or directories to the ‘Trashcan’. This can be a + different folder depending on where the file is located, and not + all file systems support this concept. In the common case that the + file lives inside a user’s home directory, the trash folder is + <filename><envar>$XDG_DATA_HOME</envar>/Trash</filename>.</para> + <para>Note that moving files to the trash does not free up space on + the file system until the ‘Trashcan’ is emptied. If you are interested + in deleting a file irreversibly, see the <command>remove</command> command.</para> + <para>Inspecting and emptying the ‘Trashcan’ is normally supported by + graphical file managers such as Nautilus, but you can also see the + trash with the command: <command>gio list trash://</command>.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-f</option>, <option>--force</option></term> + <listitem><para>Ignore non-existent and non-deletable files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>--empty</option></term> + <listitem><para>Empty the trash.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <command>tree</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>LOCATION</replaceable></arg> + </term> + <listitem> + <para>Lists the contents of the given locations recursively, in a + tree-like format. If no location is given, it defaults to the current + directory.</para> + <para>The <command>tree</command> command is similar to the traditional <command>tree</command> utility.</para> + <refsect3> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>-h</option>, <option>--hidden</option></term> + <listitem><para>Show hidden files.</para></listitem> + </varlistentry> + <varlistentry> + <term><option>-l</option>, <option>--follow-symlinks</option></term> + <listitem><para>Follow symbolic links.</para></listitem> + </varlistentry> + </variablelist> + </refsect3> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Exit status</title> + <para>On success 0 is returned, a non-zero failure code otherwise.</para> + </refsect1> + + <refsect1> + <title>See Also</title> + <para> + <citerefentry> + <refentrytitle>cat</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>cp</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>ls</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>mkdir</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>mv</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>rm</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>tree</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>. + </para> + </refsect1> +</refentry>
diff --git a/docs/reference/gio/glib-compile-resources.xml b/docs/reference/gio/glib-compile-resources.xml new file mode 100644 index 0000000..5421f3d --- /dev/null +++ b/docs/reference/gio/glib-compile-resources.xml
@@ -0,0 +1,241 @@ +<refentry id="glib-compile-resources" lang="en"> + +<refentryinfo> + <title>glib-compile-schemas</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Alexander</firstname> + <surname>Larsson</surname> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> + <refentrytitle>glib-compile-resources</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> + <refname>glib-compile-resources</refname> + <refpurpose>GLib resource compiler</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>glib-compile-resources</command> + <arg choice="opt" rep="repeat">OPTION</arg> + <arg choice="req">FILE</arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>glib-compile-resources</command> reads the resource description from +<replaceable>FILE</replaceable> and the files that it references +and creates a binary resource bundle that is suitable for use with the +<link linkend="GResource"><type>GResource</type></link> API. +The resulting bundle is then written out as-is, or as C source for linking into +an application. +</para> +<para> +The XML resource files normally have the filename extension <filename>.gresource.xml</filename>. +For a detailed description of the XML file format, see the +<link linkend="GResource"><type>GResource</type></link> documentation. +</para> +</refsect1> + +<refsect1><title>Options</title> +<variablelist> + +<varlistentry> +<term><option>-h</option>, <option>--help</option></term> +<listitem><para> +Print help and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--version</option></term> +<listitem><para> +Print program version and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--target=<replaceable>TARGET</replaceable></option></term> +<listitem><para> +Store the compiled resources in the file <replaceable>TARGET</replaceable>. +If not specified a filename based on the <replaceable>FILE</replaceable> +basename is used. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--sourcedir=<replaceable>DIRECTORY</replaceable></option></term> +<listitem><para> +The files referenced in <replaceable>FILE</replaceable> are loaded from +this directory. If not specified, the current directory is used. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--generate</option></term> +<listitem><para> +Write the output file in the format selected for by its filename extension: +<variablelist> +<varlistentry> +<term><literal>.c</literal></term> +<listitem><para>C source</para></listitem> +</varlistentry> +<varlistentry> +<term><literal>.h</literal></term> +<listitem><para>C header</para></listitem> +</varlistentry> +<varlistentry> +<term><literal>.gresource</literal></term> +<listitem><para>resource bundle</para></listitem> +</varlistentry> +</variablelist> +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--generate-source</option></term> +<listitem><para> +Instead of a writing the resource bundle in binary form create a C source file +that contains the resource bundle. This can then be compiled into an +application for easy access. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--generate-header</option></term> +<listitem><para> +Generate a header file for use with C code generated by +<option>--generate-source</option>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--generate-dependencies</option></term> +<listitem><para> +Prints the list of files that the resource bundle references to standard output. +This can be used to track dependencies in the build system. For example, the +following make rule would mark <replaceable>test.gresource</replaceable> as +depending on all the files that <replaceable>test.gresource.xml</replaceable> +includes, so that is is automatically rebuilt if any of them change: +<programlisting> +test.gresource: test.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies test.gresource.xml) +</programlisting> +Note that this may or may not be portable to non-GNU <command>make</command>. +</para> +<para> +Also see <option>--dependency-file</option>. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><option>--c-name</option></term> +<listitem><para> +Specify the prefix used for the C identifiers in the code generated by +<option>--generate-source</option> and <option>--generate-header</option>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--manual-register</option></term> +<listitem><para> +By default code generated by <option>--generate-source</option> uses automatic +initialization of the resource. This works on most systems by using the +compiler support for constructors. However, some (uncommon) compilers may not +support this, you can then specify <option>--manual-register</option>, +which will generate custom register and unregister functions that your code +can manually call at initialization and uninitialization time. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--internal</option></term> +<listitem><para> +By default code generated by <option>--generate-source</option> declares all +initialization functions as <type>extern</type>. So they are exported +unless this is prevented by a link script or other means. Since libraries +usually want to use the functions only internally it can be more useful to +declare them as +<link linkend="G-GNUC-INTERNAL:CAPS"><literal>G_GNUC_INTERNAL</literal></link> +which is what <option>--internal</option> does. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--external-data</option></term> +<listitem><para> +By default code generated by <option>--generate-source</option> embeds the +resource data as a string literal. When <option>--external-data</option> +is given, the data is only declared in the generated C file, and the data +has to be linked externally. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--dependency-file=<replaceable>FILE</replaceable></option></term> +<listitem><para> +Write dependencies in the same style as gcc -M -MF to the given file. +If <option>FILE</option> is -, the dependencies are written to the standard +output. Unlike <option>--generate-dependencies</option>, this option can be +combined with other <option>--generate</option> options to generate dependencies +as a side-effect of generating sources. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--generate-phony-targets</option></term> +<listitem><para> +When creating a dependency file with <option>--dependency-file</option> +include phony targets in the same style as gcc -MP. This would typically +be used with <literal>make</literal>. +</para></listitem> +</varlistentry> + +</variablelist> +</refsect1> + +<refsect1><title>Environment</title> +<variablelist> + +<varlistentry> +<term><envar>XMLLINT</envar></term> +<listitem><para> +The full path to the <command>xmllint</command> executable. This is used to +preprocess resources with the <literal>xml-stripblanks</literal> preprocessing +option. If this environment variable is not set, <command>xmllint</command> is +searched for in the <envar>PATH</envar>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><envar>GDK_PIXBUF_PIXDATA</envar></term> +<listitem><para> +The full path to the <command>gdk-pixbuf-pixdata</command> executable. This is +used to preprocess resources with the <literal>to-pixdata</literal> preprocessing +option. If this environment variable is not set, <command>gdk-pixbuf-pixdata</command> +is searched for in the <envar>PATH</envar>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><envar>JSON_GLIB_FORMAT</envar></term> +<listitem><para> +The full path to the <command>json-glib-format</command> executable. This is used +to preprocess resources with the <literal>json-stripblanks</literal> preprocessing +option. If this environment variable is not set, <command>json-glib-format</command> +is searched for in the <envar>PATH</envar>. +</para></listitem> +</varlistentry> + +</variablelist> +</refsect1> +</refentry>
diff --git a/docs/reference/gio/glib-compile-schemas.xml b/docs/reference/gio/glib-compile-schemas.xml new file mode 100644 index 0000000..0796bd7 --- /dev/null +++ b/docs/reference/gio/glib-compile-schemas.xml
@@ -0,0 +1,118 @@ +<refentry id="glib-compile-schemas" lang="en"> + +<refentryinfo> + <title>glib-compile-schemas</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Ryan</firstname> + <surname>Lortie</surname> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> + <refentrytitle>glib-compile-schemas</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> + <refname>glib-compile-schemas</refname> + <refpurpose>GSettings schema compiler</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>glib-compile-schemas</command> + <arg choice="opt" rep="repeat">OPTION</arg> + <arg choice="req">DIRECTORY</arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>glib-compile-schemas</command> compiles all the GSettings XML +schema files in <replaceable>DIRECTORY</replaceable> into a binary file +with the name <filename>gschemas.compiled</filename> that can be used +by <link linkend="GSettings"><type>GSettings</type></link>. The XML schema +files must have the filename extension <filename>.gschema.xml</filename>. +For a detailed description of the XML file format, see the +<link linkend="GSettings"><type>GSettings</type></link> documentation. +</para> +<para> +At runtime, GSettings looks for schemas in the +<filename>glib-2.0/schemas</filename> subdirectories of all directories +specified in the <envar>XDG_DATA_DIRS</envar> environment variable. The +usual location to install schema files is +<filename>/usr/share/glib-2.0/schemas</filename>. +</para> +<para> +In addition to schema files, glib-compile-schemas reads 'vendor override' +files, which are key files that can override default values for keys in +the schemas. The group names in the key files are the schema id, and the +values are written in serialized GVariant form. +Vendor override files must have the filename extension +<filename>.gschema.override</filename>. +</para> +<para> +By convention, vendor override files begin with <filename>nn_</filename> +where <filename>nn</filename> is a number from 00 to 99. Higher +numbered files have higher priority (eg: if the same override is made in +a file numbered 10 and then again in a file numbered 20, the override +from 20 will take precedence). +</para> +</refsect1> + +<refsect1><title>Options</title> +<variablelist> + +<varlistentry> +<term><option>-h</option>, <option>--help</option></term> +<listitem><para> +Print help and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--version</option></term> +<listitem><para> +Print program version and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--targetdir=<replaceable>TARGET</replaceable></option></term> +<listitem><para> +Store <filename>gschemas.compiled</filename> in the <replaceable>TARGET</replaceable> directory instead of <replaceable>DIRECTORY</replaceable>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--strict</option></term> +<listitem><para> +Abort on any errors in schemas. Without this option, faulty schema files are +simply omitted from the resulting compiled schema. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--dry-run</option></term> +<listitem><para> +Don't write <filename>gschemas.compiled</filename>. This option can be used +to check <filename>.gschema.xml</filename> sources for errors. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--allow-any-name</option></term> +<listitem><para> +Do not enforce restrictions on key names. Note that this option is purely +to facility the transition from GConf, and will be removed at some time +in the future. +</para></listitem> +</varlistentry> + +</variablelist> +</refsect1> +</refentry>
diff --git a/docs/reference/gio/gresource.xml b/docs/reference/gio/gresource.xml new file mode 100644 index 0000000..4ada0eb --- /dev/null +++ b/docs/reference/gio/gresource.xml
@@ -0,0 +1,127 @@ +<refentry id="gresource-tool" lang="en"> + +<refentryinfo> + <title>gresource</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Matthias</firstname> + <surname>Clasen</surname> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> + <refentrytitle>gresource</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> + <refname>gresource</refname> + <refpurpose>GResource tool</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>gresource</command> + <arg choice="opt">--section <replaceable>SECTION</replaceable></arg> + <arg choice="plain">list</arg> + <arg choice="plain"><replaceable>FILE</replaceable></arg> + <arg choice="opt"><replaceable>PATH</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gresource</command> + <arg choice="opt">--section <replaceable>SECTION</replaceable></arg> + <arg choice="plain">details</arg> + <arg choice="plain"><replaceable>FILE</replaceable></arg> + <arg choice="opt"><replaceable>PATH</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gresource</command> + <arg choice="opt">--section <replaceable>SECTION</replaceable></arg> + <arg choice="plain">extract</arg> + <arg choice="plain"><replaceable>FILE</replaceable></arg> + <arg choice="plain"><replaceable>PATH</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gresource</command> + <arg choice="plain">sections</arg> + <arg choice="plain"><replaceable>FILE</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gresource</command> + <arg choice="plain">help</arg> + <arg choice="opt"><replaceable>COMMAND</replaceable></arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>gresource</command> offers a simple commandline +interface to <link linkend="GResource"><type>GResource</type></link>. +It lets you list and extract resources that have been compiled +into a resource file or included in an elf file (a binary or a +shared library). +</para> +<para> +The file to operate on is specified by the <replaceable>FILE</replaceable> +argument. +</para> +<para> +If an elf file includes multiple sections with resources, it is +possible to select which one to operate on with the +<arg choice="plain">--section</arg> option. Use the +<arg choice="plain">sections</arg> command to find available sections. +</para> +</refsect1> + +<refsect1><title>Commands</title> +<variablelist> + +<varlistentry> +<term><option>list</option></term> +<listitem><para> +Lists resources. If <replaceable>SECTION</replaceable> is given, only +list resources in this section. If <replaceable>PATH</replaceable> is +given, only list matching resources. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>details</option></term> +<listitem><para> +Lists resources with details. If <replaceable>SECTION</replaceable> +is given, only list resources in this section. If +<replaceable>PATH</replaceable> is given, only list matching resources. +Details include the section, size and compression of each resource. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>extract</option></term> +<listitem><para> +Extracts the resource named by <replaceable>PATH</replaceable> to stdout. +Note that resources may contain binary data. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>sections</option></term> +<listitem><para> +Lists sections containing resources. This is only interesting if +<replaceable>FILE</replaceable> is an elf file. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>help</option></term> +<listitem><para> +Prints help and exits. +</para></listitem> +</varlistentry> + +</variablelist> + +</refsect1> +</refentry>
diff --git a/docs/reference/gio/gsettings.xml b/docs/reference/gio/gsettings.xml new file mode 100644 index 0000000..d7dc65d --- /dev/null +++ b/docs/reference/gio/gsettings.xml
@@ -0,0 +1,248 @@ +<refentry id="gsettings-tool" lang="en"> + +<refentryinfo> + <title>gsettings</title> + <productname>GIO</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Ryan</firstname> + <surname>Lortie</surname> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> + <refentrytitle>gsettings</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> + <refname>gsettings</refname> + <refpurpose>GSettings configuration tool</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">get</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + <arg choice="plain"><replaceable>KEY</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">monitor</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + <arg choice="opt"><replaceable>KEY</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">writable</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + <arg choice="plain"><replaceable>KEY</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">range</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + <arg choice="plain"><replaceable>KEY</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">describe</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + <arg choice="plain"><replaceable>KEY</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">set</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + <arg choice="plain"><replaceable>KEY</replaceable></arg> + <arg choice="plain"><replaceable>VALUE</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">reset</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + <arg choice="plain"><replaceable>KEY</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">reset-recursively</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">list-schemas</arg> + <arg choice="opt">--print-paths</arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">list-relocatable-schemas</arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">list-keys</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">list-children</arg> + <arg choice="plain"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">list-recursively</arg> + <arg choice="opt"><replaceable>SCHEMA</replaceable><arg choice="opt">:<replaceable>PATH</replaceable></arg></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>gsettings</command> + <arg choice="plain">help</arg> + <arg choice="opt"><replaceable>COMMAND</replaceable></arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>gsettings</command> offers a simple commandline +interface to <link linkend="GSettings"><type>GSettings</type></link>. +It lets you get, set or monitor an individual key for changes. +</para> +<para> +The <replaceable>SCHEMA</replaceable> and <replaceable>KEY</replaceable> +arguments are required for most commands to specify the schema id and the +name of the key to operate on. The schema id may optionally have a +:<replaceable>PATH</replaceable> suffix. Specifying the path is only needed +if the schema does not have a fixed path. +</para> +<para> +When setting a key, you also need specify a <replaceable>VALUE</replaceable> +The format for the value is that of a serialized +<link linkend="GVariant"><type>GVariant</type></link>, +so e.g. a string +must include explicit quotes: "'foo'". This format is also used when printing +out values. +</para> +<para> +Note that gsettings needs a D-Bus session bus connection to write changes to +the dconf database. +</para> +</refsect1> + +<refsect1><title>Commands</title> +<variablelist> + +<varlistentry> +<term><option>get</option></term> +<listitem><para> +Gets the value of <replaceable>KEY</replaceable>. +The value is printed out as a serialised +<link linkend="GVariant"><type>GVariant</type></link>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>monitor</option></term> +<listitem><para> +Monitors <replaceable>KEY</replaceable> for changes and prints the changed +values. If no <replaceable>KEY</replaceable> is specified, all keys in the +schema are monitored. Monitoring will continue until the process is terminated. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>writable</option></term> +<listitem><para> +Finds out whether <replaceable>KEY</replaceable> is writable. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>range</option></term> +<listitem><para> +Queries the range of valid values for <replaceable>KEY</replaceable>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>describe</option></term> +<listitem><para> +Queries the description of valid values for <replaceable>KEY</replaceable>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>set</option></term> +<listitem><para> +Sets the value of <replaceable>KEY</replaceable> to +<replaceable>VALUE</replaceable>. The value is specified as a serialised +<link linkend="GVariant"><type>GVariant</type></link>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>reset</option></term> +<listitem><para> +Resets <replaceable>KEY</replaceable> to its default value. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>reset-recursively</option></term> +<listitem><para> +Reset all keys under the given <replaceable>SCHEMA</replaceable>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>list-schemas</option></term> +<listitem><para> +Lists the installed, non-relocatable schemas. +See <option>list-relocatable-schemas</option> if you are interested in +relocatable schemas. If <optional><option>--print-paths</option></optional> +is given, the path where each schema is mapped is also printed. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>list-relocatable-schemas</option></term> +<listitem><para> +Lists the installed, relocatable schemas. +See <option>list-schemas</option> if you are interested in +non-relocatable schemas. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>list-keys</option></term> +<listitem><para> +Lists the keys in <replaceable>SCHEMA</replaceable>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>list-children</option></term> +<listitem><para> +Lists the children of <replaceable>SCHEMA</replaceable>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>list-recursively</option></term> +<listitem><para> +Lists keys and values, recursively. If no <replaceable>SCHEMA</replaceable> +is given, list keys in all schemas. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>help</option></term> +<listitem><para> +Prints help and exits. +</para></listitem> +</varlistentry> + +</variablelist> + +</refsect1> +</refentry>
diff --git a/docs/reference/gio/gvfs-overview.odg b/docs/reference/gio/gvfs-overview.odg new file mode 100644 index 0000000..ca2bb8d --- /dev/null +++ b/docs/reference/gio/gvfs-overview.odg Binary files differ
diff --git a/docs/reference/gio/gvfs-overview.png b/docs/reference/gio/gvfs-overview.png new file mode 100644 index 0000000..628684d --- /dev/null +++ b/docs/reference/gio/gvfs-overview.png Binary files differ
diff --git a/docs/reference/gio/menu-example.png b/docs/reference/gio/menu-example.png new file mode 100644 index 0000000..91aeccf --- /dev/null +++ b/docs/reference/gio/menu-example.png Binary files differ
diff --git a/docs/reference/gio/menu-model.png b/docs/reference/gio/menu-model.png new file mode 100644 index 0000000..a4d9f11 --- /dev/null +++ b/docs/reference/gio/menu-model.png Binary files differ
diff --git a/docs/reference/gio/meson.build b/docs/reference/gio/meson.build new file mode 100644 index 0000000..a4e67ca --- /dev/null +++ b/docs/reference/gio/meson.build
@@ -0,0 +1,239 @@ +if get_option('gtk_doc') + if installed_tests_enabled + subdir('gdbus-object-manager-example') + endif + subdir('xml') + + ignore_headers = [ + 'fam', + 'fen', + 'gdbus-2.0', + 'gvdb', + 'inotify', + 'kqueue', + 'libasyncns', + 'tests', + 'win32', + 'xdgmime', + 'gappinfoprivate.h', + 'gapplicationimpl.h', + 'gasynchelper.h', + 'gcontenttypeprivate.h', + 'gcontextspecificgroup.h', + 'gcredentialsprivate.h', + 'gdbus-daemon-generated.h', + 'gdbusactiongroup-private.h', + 'gdbusauth.h', + 'gdbusauthmechanismanon.h', + 'gdbusauthmechanismexternal.h', + 'gdbusauthmechanism.h', + 'gdbusauthmechanismsha1.h', + 'gdbusdaemon.h', + 'gdbusprivate.h', + 'gdelayedsettingsbackend.h', + 'gdocumentportal.h', + 'gdummyfile.h', + 'gdummyproxyresolver.h', + 'gdummytlsbackend.h', + 'gfileattribute-priv.h', + 'gfileinfo-priv.h', + 'ghttpproxy.h', + 'giomodule-priv.h', + 'gioprivate.h', + 'giowin32-priv.h', + 'gio_probes.h', + 'gio_trace.h', + 'gio-tool.h', + 'glocaldirectorymonitor.h', + 'glocalfileenumerator.h', + 'glocalfile.h', + 'glocalfileinfo.h', + 'glocalfileinputstream.h', + 'glocalfileiostream.h', + 'glocalfilemonitor.h', + 'glocalfileoutputstream.h', + 'glocalvfs.h', + 'gmemorymonitordbus.h', + 'gmemorymonitorportal.h', + 'gmountprivate.h', + 'gnativevolumemonitor.h', + 'gnetworkingprivate.h', + 'gnetworkmonitorbase.h', + 'gnetworkmonitornetlink.h', + 'gnetworkmonitornm.h', + 'gnetworkmonitorportal.h', + 'gnotificationbackend.h', + 'gnotification-private.h', + 'gopenuriportal.h', + 'gpollfilemonitor.h', + 'gportalsupport.h', + 'gproxyresolverportal.h', + 'gregistrysettingsbackend.h', + 'gresourcefile.h', + 'gsettingsbackendinternal.h', + 'gsettings-mapping.h', + 'gsettingsschema-internal.h', + 'gsocketinputstream.h', + 'gsocketoutputstream.h', + 'gsocks4aproxy.h', + 'gsocks4proxy.h', + 'gsocks5proxy.h', + 'gsubprocesslauncher-private.h', + 'gthreadedresolver.h', + 'gtrashportal.h', + 'gunionvolumemonitor.h', + 'gunixmount.h', + 'gunixresolver.h', + 'gunixvolume.h', + 'gunixvolumemonitor.h', + 'gwin32networkmonitor.h', + 'gwin32appinfo.h', + 'gwin32mount.h', + 'gwin32resolver.h', + 'gwin32volumemonitor.h', + 'thumbnail-verify.h', + 'xdp-dbus.h', + ] + + sections_files = files('gio-sections-common.txt') + + if host_system == 'windows' + ignore_headers += [ + 'gfiledescriptorbased.h', + 'gunixconnection.h', + 'gunixcredentialsmessage.h', + 'gunixmounts.h', + 'gunixfdlist.h', + 'gunixfdmessage.h', + 'gunixinputstream.h', + 'gunixoutputstream.h', + 'gunixsocketaddress.h', + 'gdesktopappinfo.h', + 'gosxappinfo.h', + ] + sections_files += files('gio-sections-win32.txt') + platform_file = files('gio-docs-win32.xml') + else + if glib_have_cocoa + ignore_headers += ['gdesktopappinfo.h'] + else + ignore_headers += ['gosxappinfo.h'] + endif + + ignore_headers += [ + 'gwin32inputstream.h', + 'gwin32outputstream.h', + 'gwin32registrykey.h', + ] + platform_file = files('gio-docs-unix.xml') + endif + + ignore_sources = [ + 'kqueue', + 'tests', + 'gdbus-daemon-generated.c', + 'xdp-dbus.c', + ] + + docpath = join_paths(glib_datadir, 'gtk-doc', 'html') + version_conf = configuration_data() + version_conf.set('VERSION', meson.project_version()) + configure_file( + input: 'version.xml.in', + output: 'version.xml', + configuration: version_conf + ) + + # FIXME: configure_file() does not support more than one file in input + # argument. If input argument is omitted then meson checks that all items in + # the command array are strings. But if we have an input then extra files + # can be passed in command array. + # See https://github.com/mesonbuild/meson/issues/5893 + concat_files_helper = find_program('concat-files-helper.py') + configure_file( + output : 'gio-sections.txt', + input : sections_files[0], + command : [concat_files_helper, '@OUTPUT@'] + sections_files, + ) + + configure_file( + output : 'gio-docs-platform.xml', + input : platform_file, + copy : true, + ) + + content_files = [ + 'overview.xml', + 'migrating-posix.xml', + 'migrating-gnome-vfs.xml', + 'migrating-gconf.xml', + 'migrating-gdbus.xml', + 'gio-querymodules.xml', + 'glib-compile-schemas.xml', + 'glib-compile-resources.xml', + 'gapplication.xml', + 'gsettings.xml', + 'gresource.xml', + 'gdbus.xml', + 'gdbus-codegen.xml', + ] + + if installed_tests_enabled + content_files += [ + gdbus_example_objectmanager_xml, + gdbus_example_objectmanager_sources, + gdbus_object_manager_example_doc + ] + endif + + gnome.gtkdoc('gio', + main_xml : 'gio-docs.xml', + namespace : 'g', + mode : 'none', + dependencies : [libgio_dep, libgobject_dep, libglib_dep], + src_dir : 'gio', + scan_args : gtkdoc_common_scan_args + [ + '--rebuild-types', + '--ignore-headers=' + ' '.join(ignore_headers), + ], + mkdb_args : [ + '--ignore-files=' + ' '.join(ignore_sources), + ], + content_files : content_files, + expand_content_files : [ + 'overview.xml', + 'migrating-posix.xml', + 'migrating-gnome-vfs.xml', + 'migrating-gconf.xml', + 'migrating-gdbus.xml', + 'gdbus-codegen.xml', + ], + html_assets : [ + 'gvfs-overview.png', + 'menu-example.png', + 'menu-model.png', + ], + fixxref_args: [ + '--html-dir=' + docpath, + '--extra-dir=' + join_paths('gio', '..', 'glib', 'html'), + '--extra-dir=' + join_paths('gio', '..', 'gobject', 'html'), + ], + install: true, + check: true, + ) +endif + + +if get_option('man') + manpages = ['gapplication', 'gio-querymodules', 'glib-compile-schemas', + 'glib-compile-resources', 'gsettings', 'gresource', 'gdbus', + 'gio', 'gdbus-codegen'] + foreach page : manpages + custom_target(page + '-man', + input: page + '.xml', + output: page + '.1', + command: xsltproc_command, + install: true, + install_dir: man1_dir) + endforeach +endif
diff --git a/docs/reference/gio/migrating-gconf.xml b/docs/reference/gio/migrating-gconf.xml new file mode 100644 index 0000000..d9fd064 --- /dev/null +++ b/docs/reference/gio/migrating-gconf.xml
@@ -0,0 +1,515 @@ + <chapter> + <title>Migrating from GConf to GSettings</title> + + <section> + <title>Before you start</title> + + <para> + Converting individual applications and their settings from GConf to + GSettings can be done at will. But desktop-wide settings like font or + theme settings often have consumers in multiple modules. Therefore, + some consideration has to go into making sure that all users of a setting + are converted to GSettings at the same time or that the program + responsible for configuring that setting continues to update the value in + both places. + </para> + <para> + It is always a good idea to have a look at how others have handled + similar problems before. + </para> + </section> + + <section> + <title>Conceptual differences</title> + + <para> + Conceptually, GConf and GSettings are fairly similar. Both + have a concept of pluggable backends. Both keep information + about keys and their types in schemas. Both have a concept of + mandatory values, which lets you implement lock-down. + </para> + <para> + There are some differences in the approach to schemas. GConf + installs the schemas into the database and has API to handle + schema information (gconf_client_get_default_from_schema(), + gconf_value_get_schema(), etc). GSettings on the other hand + assumes that an application knows its own schemas, and does + not provide API to handle schema information at runtime. + GSettings is also more strict about requiring a schema whenever + you want to read or write a key. To deal with more free-form + information that would appear in schema-less entries in GConf, + GSettings allows for schemas to be 'relocatable'. + </para> + <para> + One difference in the way applications interact with their + settings is that with GConf you interact with a tree of + settings (ie the keys you pass to functions when reading + or writing values are actually paths with the actual name + of the key as the last element. With GSettings, you create + a GSettings object which has an implicit prefix that determines + where the settings get stored in the global tree of settings, + but the keys you pass when reading or writing values are just + the key names, not the full path. + </para> + </section> + + <section> + <title>GConfClient (and GConfBridge) API conversion</title> + + <para> + Most people use GConf via the high-level #GConfClient API. + The corresponding API is the #GSettings object. While not + every GConfClient function has a direct GSettings equivalent, + many do: + <table id="gconf-client-vs-gsettings"> + <tgroup cols="2"> + <thead> + <row><entry>GConfClient</entry><entry>GSettings</entry></row> + </thead> + <tbody> + <row><entry>gconf_client_get_default()</entry><entry>no direct equivalent, + instead you call g_settings_new() for the schemas you use</entry></row> + <row><entry>gconf_client_set()</entry><entry>g_settings_set()</entry></row> + <row><entry>gconf_client_get()</entry><entry>g_settings_get()</entry></row> + <row><entry>gconf_client_get_bool()</entry><entry>g_settings_get_boolean()</entry></row> + <row><entry>gconf_client_set_bool()</entry><entry>g_settings_set_boolean()</entry></row> + <row><entry>gconf_client_get_int()</entry><entry>g_settings_get_int()</entry></row> + <row><entry>gconf_client_set_int()</entry><entry>g_settings_set_int()</entry></row> + <row><entry>gconf_client_get_float()</entry><entry>g_settings_get_double()</entry></row> + <row><entry>gconf_client_set_float()</entry><entry>g_settings_set_double()</entry></row> + <row><entry>gconf_client_get_string()</entry><entry>g_settings_get_string()</entry></row> + <row><entry>gconf_client_set_string()</entry><entry>g_settings_set_string()</entry></row> + <row><entry>gconf_client_get_list()</entry><entry>for string lists, see g_settings_get_strv(), else see g_settings_get_value() and #GVariant API</entry></row> + <row><entry>gconf_client_set_list()</entry><entry>for string lists, see g_settings_set_strv(), else see g_settings_set_value() and #GVariant API</entry></row> + <row><entry>gconf_entry_get_is_writable()</entry><entry>g_settings_is_writable()</entry></row> + <row><entry>gconf_client_notify_add()</entry><entry>not required, the #GSettings::changed signal is emitted automatically</entry></row> + <row><entry>gconf_client_add_dir()</entry><entry>not required, each GSettings instance automatically watches all keys in its path</entry></row> + <row><entry>#GConfChangeSet</entry><entry>g_settings_delay(), g_settings_apply()</entry></row> + <row><entry>gconf_client_get_default_from_schema()</entry><entry>no equivalent, applications are expected to know their schema</entry></row> + <row><entry>gconf_client_all_entries()</entry><entry>no equivalent, applications are expected to know their schema, and GSettings does not allow schema-less entries</entry></row> + <row><entry>gconf_client_get_without_default()</entry><entry>no equivalent</entry></row> + <row><entry>gconf_bridge_bind_property()</entry><entry>g_settings_bind()</entry></row> + <row><entry>gconf_bridge_bind_property_full()</entry><entry>g_settings_bind_with_mapping()</entry></row> + </tbody> + </tgroup> + </table> + </para> + <para> + GConfBridge was a third-party library that used GConf to bind an object property + to a particular configuration key. GSettings offers this service itself. + </para> + <para> + There is a pattern that is sometimes used for GConf, where a setting can have + explicit 'value A', explicit 'value B' or 'use the system default'. With GConf, + 'use the system default' is sometimes implemented by unsetting the user value. + </para> + <para> + This is not possible in GSettings, since it does not have API to determine if a value + is the default and does not let you unset values. The recommended way (and much + clearer) way in which this can be implemented in GSettings is to have a separate + 'use-system-default' boolean setting. + </para> + </section> + + <section> + <title>Change notification</title> + + <para> + GConf requires you to call gconf_client_add_dir() and + gconf_client_notify_add() to get change notification. With + GSettings, this is not necessary; signals get emitted automatically + for every change. + </para> + <para> + The #GSettings::changed signal is emitted for each changed key. + There is also a #GSettings::change-event signal that you can handle + if you need to see groups of keys that get changed at the same time. + </para> + <para> + GSettings also notifies you about changes in writability of keys, + with the #GSettings::writable-changed signal (and the + #GSettings::writable-change-event signal). + </para> + </section> + + <section><title>Change sets</title> + <para> + GConf has a concept of a set of changes which can be applied or reverted + at once: #GConfChangeSet (GConf doesn't actually apply changes atomically, + which is one of its shortcomings). + </para> + <para> + Instead of a separate object to represent a change set, GSettings has a + 'delayed-apply' mode, which can be turned on for a GSettings object by + calling g_settings_delay(). In this mode, changes done to the GSettings + object are not applied - they are still visible when calling g_settings_get() + <emphasis>on the same object</emphasis>, but not to other GSettings instances + or even other processes. + </para> + <para> + To apply the pending changes all at once (GSettings <emphasis>does</emphasis> + atomicity here), call g_settings_apply(). To revert the pending changes, + call g_settings_revert() or just drop the reference to the #GSettings object. + </para> + </section> + + <section> + <title>Schema conversion</title> + + <para> + If you are porting your application from GConf, most likely you already + have a GConf schema. GConf comes with a commandline tool + gsettings-schema-convert that can help with the task of converting + a GConf schema into an equivalent GSettings schema. The tool is not + perfect and may need assistance in some cases. + </para> + <example><title>An example for using gsettings-schema-convert</title> + <para>Running <userinput>gsettings-schema-convert --gconf --xml --schema-id "org.gnome.font-rendering" --output org.gnome.font-rendering.gschema.xml destop_gnome_font_rendering.schemas</userinput> on the following <filename>desktop_gnome_font_rendering.schemas</filename> file: + <programlisting> +<![CDATA[ +<?xml version="1.0"?> +<gconfschemafile> + <schemalist> + <schema> + <key>/schemas/desktop/gnome/font_rendering/dpi</key> + <applyto>/desktop/gnome/font_rendering/dpi</applyto> + <owner>gnome</owner> + <type>int</type> + <default>96</default> + <locale name="C"> + <short>DPI</short> + <long>The resolution used for converting font sizes to pixel sizes, in dots per inch.</long> + </locale> + </schema> + </schemalist> +</gconfschemafile> +]]> +</programlisting> +produces a <filename>org.gnome.font-rendering.gschema.xml</filename> file with the following content: +<programlisting> +<![CDATA[ +<schemalist> + <schema id="org.gnome.font-rendering" path="/desktop/gnome/font_rendering/"> + <key name="dpi" type="i"> + <default>96</default> + <summary>DPI</summary> + <description>The resolution used for converting font sizes to pixel sizes, in dots per inch.</description> + </key> + </schema> +</schemalist> +]]> +</programlisting> +</para> + </example> + + <para> + GSettings schemas are identified at runtime by their id (as specified + in the XML source file). It is recommended to use a dotted name as schema + id, similar in style to a D-Bus bus name, e.g. "org.gnome.SessionManager". + In cases where the settings are general and not specific to one application, + the id should not use StudlyCaps, e.g. "org.gnome.font-rendering". + The filename used for the XML schema source is immaterial, but + schema compiler expects the files to have the extension + <filename>.gschema.xml</filename>. It is recommended to simply + use the schema id as the filename, followed by this extension, + e.g. <filename>org.gnome.SessionManager.gschema.xml</filename>. + </para> + + <para> + The XML source file for your GSettings schema needs to get installed + into <filename>$datadir/glib-2.0/schemas</filename>, and needs to be + compiled into a binary form. At runtime, GSettings looks for compiled + schemas in the <filename>glib-2.0/schemas</filename> subdirectories + of all <envar>XDG_DATA_DIRS</envar> directories, so if you install + your schema in a different location, you need to set the + <envar>XDG_DATA_DIRS</envar> environment variable appropriately. + </para> + <para> + Schemas are compiled into binary form by the + <link linkend="glib-compile-schemas">glib-compile-schemas</link> utility. + GIO provides a <literal>glib_compile_schemas</literal> + variable for the schema compiler. + </para> + <para> + You can ignore all of this by using the provided m4 macros. To + do this, add to your <filename>configure.ac</filename>: +<programlisting> +GLIB_GSETTINGS +</programlisting> + The corresponding <filename>Makefile.am</filename> fragment looks like + this: +<programlisting> +# gsettings_SCHEMAS is a list of all the schemas you want to install +gsettings_SCHEMAS = my.app.gschema.xml + +# include the appropriate makefile rules for schema handling +@GSETTINGS_RULES@ +</programlisting> + </para> + + <para> + This is not sufficient on its own. You need to mention what the source + of the <filename>my.app.gschema.xml</filename> file is. If the schema + file is distributed directly with your project's tarball then a mention + in <varname>EXTRA_DIST</varname> is appropriate. If the schema file is + generated from another source then you will need the appropriate rule + for that, plus probably an item in <varname>EXTRA_DIST</varname> for the + source files used by that rule. + </para> + + <para> + One possible pitfall in doing schema conversion is that the default + values in GSettings schemas are parsed by the #GVariant parser. + This means that strings need to include quotes in the XML. Also note + that the types are now specified as #GVariant type strings. + <programlisting> +<![CDATA[ +<type>string</type> +<default>rgb</default> +]]> + </programlisting> + becomes + <programlisting> +<![CDATA[ +<key name="rgba-order" type="s"> + <default>'rgb'</default> <!-- note quotes --> +</key> +]]> + </programlisting> + </para> + <para> + Another possible complication is that GConf specifies full paths + for each key, while a GSettings schema has a 'path' attribute that + contains the prefix for all the keys in the schema, and individual + keys just have a simple name. So + <programlisting> +<![CDATA[ +<key>/schemas/desktop/gnome/font_rendering/antialiasing</key> +]]> + </programlisting> + becomes + <programlisting> +<![CDATA[ +<schema id="org.gnome.font" path="/desktop/gnome/font_rendering/"> + <key name="antialiasing" type="s"> +]]> + </programlisting> + </para> + <para> + Default values can be localized in both GConf and GSettings schemas, + but GSettings uses gettext for the localization. You can specify + the gettext domain to use in the <tag class="attribute">gettext-domain</tag> + attribute. Therefore, when converting localized defaults in GConf, + <programlisting> +<![CDATA[ +<key>/schemas/apps/my_app/font_size</key> + <locale name="C"> + <default>18</default> + </locale> + <locale name="be"> + <default>24</default> + </locale> +</key> +]]> + </programlisting> + becomes + <programlisting> +<![CDATA[ +<schema id="..." gettext-domain="your-domain"> + ... +<key name="font-size" type="i"> + <default l10n="messages" context="font_size">18</default> +</key> +]]> + </programlisting> + </para> + <para> + GSettings uses gettext for translation of default values. + The string that is translated is exactly the string that appears + inside of the <tag class='starttag'>default</tag> element. This + includes the quotation marks that appear around strings. + Default values must be marked with the <varname>l10n</varname> + attribute in the <tag class='starttag'>default</tag> tag, which + should be set as equal to <literal>'messages'</literal> or + <literal>'time'</literal> depending on the desired category. An + optional translation context can also be specified with the + <varname>context</varname> attribute, as in the example. This + is usually recommended, since the string "<literal>18</literal>" + is not particularly easy to translate without context. The + translated version of the default value should be stored in the + specified <varname>gettext-domain</varname>. Care must be taken + during translation to ensure that all translated values remain + syntactically valid; mistakes here will cause runtime errors. + </para> + <para> + GSettings schemas have optional <tag class="starttag">summary</tag> and + <tag class="starttag">description</tag> elements for each key which + correspond to the <tag class="starttag">short</tag> and + <tag class="starttag">long</tag> elements in the GConf schema and + will be used in similar ways by a future gsettings-editor, so you + should use the same conventions for them: The summary is just a short + label with no punctuation, the description can be one or more complete + sentences. If multiple paragraphs are desired for the description, the + paragraphs should be separated by a completely empty line. + </para> + <para> + Translations for these strings will also be handled + via gettext, so you should arrange for these strings to be + extracted into your gettext catalog. One way to do that is to use + intltool. Since intltool 0.50.1, schema files are + supported, so all you have to do is to add your .gschema.xml + files to <filename>POTFILES.in</filename> with a line like + <programlisting> + [type: gettext/gsettings]data/org.foo.MyApp.gschema.xml + </programlisting> + </para> + <para> + GSettings is a bit more restrictive about key names than GConf. Key + names in GSettings can be at most 32 characters long, and must only + consist of lowercase characters, numbers and dashes, with no + consecutive dashes. The first character must not be a number or dash, + and the last character cannot be '-'. + </para> + <para> + If you are using the GConf backend for GSettings during the + transition, you may want to keep your key names the same they + were in GConf, so that existing settings in the users GConf + database are preserved. You can achieve this by using the + <option>--allow-any-name</option> with the + <link linkend="glib-compile-schemas">glib-compile-schemas</link> schema + compiler. Note that this option is only meant + to ease the process of porting your application, allowing parts + of your application to continue to access GConf and parts to use + GSettings. By the time you have finished porting your application + you must ensure that all key names are valid. + </para> + </section> + + <section><title>Data conversion</title> + <para> + GConf comes with a GSettings backend that can be used to + facility the transition to the GSettings API until you are + ready to make the jump to a different backend (most likely + dconf). To use it, you need to set the <envar>GSETTINGS_BACKEND</envar> + to 'gconf', e.g. by using +<programlisting> + g_setenv ("GSETTINGS_BACKEND", "gconf", TRUE); +</programlisting> + early on in your program. Note that this backend is meant purely + as a transition tool, and should not be used in production. + </para> + <para> + GConf also comes with a utility called + <command>gsettings-data-convert</command>, which is designed to help + with the task of migrating user settings from GConf into another + GSettings backend. It can be run manually, but it is designed to be + executed automatically, every time a user logs in. It keeps track of + the data migrations that it has already done, and it is harmless to + run it more than once. + </para> + <para> + To make use of this utility, you must install a keyfile in the + directory <filename>/usr/share/GConf/gsettings</filename> which + lists the GSettings keys and GConf paths to map to each other, for + each schema that you want to migrate user data for. + </para> + <para> + Here is an example: + <programlisting> +<![CDATA[ +[org.gnome.fonts] +antialiasing = /desktop/gnome/font_rendering/antialiasing +dpi = /desktop/gnome/font_rendering/dpi +hinting = /desktop/gnome/font_rendering/hinting +rgba-order = /desktop/gnome/font_rendering/rgba_order + +[apps.myapp:/path/to/myapps/] +some-odd-key1 = /apps/myapp/some_ODD-key1 +]]> + </programlisting> + The last key demonstrates that it may be necessary to modify the key + name to comply with stricter GSettings key name rules. Of course, + that means your application must use the new key names when looking + up settings in GSettings. + </para> + <para> + The last group in the example also shows how to handle the case + of 'relocatable' schemas, which don't have a fixed path. You can + specify the path to use in the group name, separated by a colon. + </para> + <para> + There are some limitations: <command>gsettings-data-convert</command> + does not do any transformation of the values. And it does not handle + complex GConf types other than lists of strings or integers. + </para> + <para> + Don't forget to require GConf 2.31.1 or newer in your configure + script if you are making use of the GConf backend or the conversion + utility. + </para> + + <para> + If, as an application developer, you are interested in manually + ensuring that <command>gsettings-data-convert</command> has been + invoked (for example, to deal with the case where the user is + logged in during a distribution upgrade or for non-XDG desktop + environments which do not run the command as an autostart) you + may invoke it manually during your program initialisation. This + is not recommended for all application authors -- it is your + choice if this use case concerns you enough. + </para> + <para> + Internally, <command>gsettings-data-convert</command> uses a + keyfile to track which settings have been migrated. The + following code fragment will check that keyfile to see if your + data conversion script has been run yet and, if not, will + attempt to invoke the tool to run it. You should adapt it to + your application as you see fit. + </para> + <para> + <programlisting> +<![CDATA[ +static void +ensure_migrated (const gchar *name) +{ + gboolean needed = TRUE; + GKeyFile *kf; + gchar **list; + gsize i, n; + + kf = g_key_file_new (); + + g_key_file_load_from_data_dirs (kf, "gsettings-data-convert", + NULL, G_KEY_FILE_NONE, NULL); + list = g_key_file_get_string_list (kf, "State", "converted", &n, NULL); + + if (list) + { + for (i = 0; i < n; i++) + if (strcmp (list[i], name) == 0) + { + needed = FALSE; + break; + } + + g_strfreev (list); + } + + g_key_file_free (kf); + + if (needed) + g_spawn_command_line_sync ("gsettings-data-convert", + NULL, NULL, NULL, NULL); +} + +]]> + </programlisting> + </para> + <para> + Although there is the possibility that the + <command>gsettings-data-convert</command> script will end up + running multiple times concurrently with this approach, it is + believed that this is safe. + </para> + </section> + </chapter>
diff --git a/docs/reference/gio/migrating-gdbus.xml b/docs/reference/gio/migrating-gdbus.xml new file mode 100644 index 0000000..5e2d464 --- /dev/null +++ b/docs/reference/gio/migrating-gdbus.xml
@@ -0,0 +1,309 @@ +<?xml version="1.0"?> +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'"> +<!ENTITY version SYSTEM "version.xml"> +]> +<chapter> + <title>Migrating to GDBus</title> + + <section> + <title>Conceptual differences</title> + + <para> + The central concepts of D-Bus are modelled in a very similar way + in dbus-glib and GDBus. Both have objects representing connections, + proxies and method invocations. But there are some important + differences: + <itemizedlist> + <listitem><para> + dbus-glib uses the <ulink + url="http://www.freedesktop.org/wiki/Software/dbus#ReferenceImplementation.28dbus-daemonandlibdbus.29">libdbus + reference implementation</ulink>, GDBus doesn't. Instead, it + relies on GIO streams as transport layer, and has its own + implementation for the D-Bus connection setup and + authentication. Apart from using streams as transport, + avoiding libdbus also lets GDBus avoid some thorny + multithreading issues. + </para></listitem> + <listitem><para> + dbus-glib uses the GObject type system for method arguments and + return values, including a homegrown container specialization + mechanism. GDBus relies on the #GVariant type system which is + explicitly designed to match D-Bus types. + </para></listitem> + <listitem><para> + dbus-glib models only D-Bus interfaces and does not provide + any types for objects. GDBus models both D-Bus interfaces + (via the #GDBusInterface, #GDBusProxy and + #GDBusInterfaceSkeleton types) and objects (via the + #GDBusObject, #GDBusObjectSkeleton and #GDBusObjectProxy types). + </para></listitem> + <listitem><para> + GDBus includes native support for the <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.DBus.Properties</ulink> (via the #GDBusProxy type) and <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">org.freedesktop.DBus.ObjectManager</ulink> D-Bus interfaces, dbus-glib doesn't. + </para></listitem> + <listitem><para> + The typical way to export an object in dbus-glib involves + generating glue code from XML introspection data using + <command>dbus-binding-tool</command>. GDBus provides a + similar tool called <command><link + linkend="gdbus-codegen">gdbus-codegen</link></command> that + can also generate Docbook D-Bus interface documentation. + </para></listitem> + <listitem><para> + dbus-glib doesn't provide any convenience API for owning and + watching bus names, GDBus provides the g_bus_own_name() and + g_bus_watch_name() family of convenience functions. + </para></listitem> + <listitem><para> + GDBus provides API to parse, generate and work with <link + linkend="gio-D-Bus-Introspection-Data">Introspection + XML</link>, dbus-glib doesn't. + </para></listitem> + <listitem><para> + GTestDBus provides API to create isolated unit tests <link + linkend="gio-D-Bus-Test-Scaffolding">GDBus Test Scaffolding</link>. + </para></listitem> + </itemizedlist> + </para> + </section> + + <section> + <title>API comparison</title> + + <table id="dbus-glib-vs-gdbus"> + <title>dbus-glib APIs and their GDBus counterparts</title> + <tgroup cols="2"> + <thead> + <row><entry>dbus-glib</entry><entry>GDBus</entry></row> + </thead> + <tbody> + <row><entry>#DBusGConnection</entry><entry>#GDBusConnection</entry></row> + <row><entry>#DBusGProxy</entry><entry>#GDBusProxy, #GDBusInterface - also see #GDBusObjectProxy</entry></row> + <row><entry>#DBusGObject</entry><entry>#GDBusInterfaceSkeleton, #GDBusInterface - also see #GDBusObjectSkeleton</entry></row> + <row><entry>#DBusGMethodInvocation</entry><entry>#GDBusMethodInvocation</entry></row> + <row><entry>dbus_g_bus_get()</entry><entry>g_bus_get_sync(), also see + g_bus_get()</entry></row> + <row><entry>dbus_g_proxy_new_for_name()</entry><entry>g_dbus_proxy_new_sync() and + g_dbus_proxy_new_for_bus_sync(), also see g_dbus_proxy_new()</entry></row> + <row><entry>dbus_g_proxy_add_signal()</entry><entry>not needed, use the generic #GDBusProxy::g-signal</entry></row> + <row><entry>dbus_g_proxy_connect_signal()</entry><entry>use g_signal_connect() with #GDBusProxy::g-signal</entry></row> + <row><entry>dbus_g_connection_register_g_object()</entry><entry>g_dbus_connection_register_object() - also see g_dbus_object_manager_server_export()</entry></row> + <row><entry>dbus_g_connection_unregister_g_object()</entry><entry>g_dbus_connection_unregister_object() - also see g_dbus_object_manager_server_unexport()</entry></row> + <row><entry>dbus_g_object_type_install_info()</entry><entry>introspection data is installed while registering + an object, see g_dbus_connection_register_object()</entry></row> + <row><entry>dbus_g_proxy_begin_call()</entry><entry>g_dbus_proxy_call()</entry></row> + <row><entry>dbus_g_proxy_end_call()</entry><entry>g_dbus_proxy_call_finish()</entry></row> + <row><entry>dbus_g_proxy_call()</entry><entry>g_dbus_proxy_call_sync()</entry></row> + <row><entry>dbus_g_error_domain_register()</entry><entry>g_dbus_error_register_error_domain()</entry></row> + <row><entry>dbus_g_error_has_name()</entry><entry>no direct equivalent, see g_dbus_error_get_remote_error()</entry></row> + <row><entry>dbus_g_method_return()</entry><entry>g_dbus_method_invocation_return_value()</entry></row> + <row><entry>dbus_g_method_return_error()</entry><entry>g_dbus_method_invocation_return_error() and variants</entry></row> + <row><entry>dbus_g_method_get_sender()</entry><entry>g_dbus_method_invocation_get_sender()</entry></row> + </tbody> + </tgroup> + </table> + </section> + + <section> + <title>Owning bus names</title> + <para> + Using dbus-glib, you typically call RequestName manually + to own a name, like in the following excerpt: + <informalexample><programlisting><![CDATA[ + error = NULL; + res = dbus_g_proxy_call (system_bus_proxy, + "RequestName", + &error, + G_TYPE_STRING, NAME_TO_CLAIM, + G_TYPE_UINT, DBUS_NAME_FLAG_ALLOW_REPLACEMENT, + G_TYPE_INVALID, + G_TYPE_UINT, &result, + G_TYPE_INVALID); + if (!res) + { + if (error != NULL) + { + g_warning ("Failed to acquire %s: %s", + NAME_TO_CLAIM, error->message); + g_error_free (error); + } + else + { + g_warning ("Failed to acquire %s", NAME_TO_CLAIM); + } + goto out; + } + + if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) + { + if (error != NULL) + { + g_warning ("Failed to acquire %s: %s", + NAME_TO_CLAIM, error->message); + g_error_free (error); + } + else + { + g_warning ("Failed to acquire %s", NAME_TO_CLAIM); + } + exit (1); + } + + dbus_g_proxy_add_signal (system_bus_proxy, "NameLost", + G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (system_bus_proxy, "NameLost", + G_CALLBACK (on_name_lost), NULL, NULL); + + /* further setup ... */ +]]> + </programlisting></informalexample> + </para> + <para> + While you can do things this way with GDBus too, using + g_dbus_proxy_call_sync(), it is much nicer to use the high-level API + for this: + <informalexample><programlisting><![CDATA[ +static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + /* further setup ... */ +} + +/* ... */ + + owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM, + NAME_TO_CLAIM, + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, + on_bus_acquired, + on_name_acquired, + on_name_lost, + NULL, + NULL); + + g_main_loop_run (loop); + + g_bus_unown_name (owner_id); +]]> + </programlisting></informalexample> + Note that g_bus_own_name() works asynchronously and requires + you to enter your mainloop to await the on_name_aquired() + callback. Also note that in order to avoid race conditions (e.g. + when your service is activated by a method call), you have to export + your manager object <emphasis>before</emphasis> acquiring the + name. The on_bus_acquired() callback is the right place to do + such preparations. + </para> + </section> + + <section> + <title>Creating proxies for well-known names</title> + <para> + dbus-glib lets you create proxy objects for well-known names, like the + following example: + <informalexample><programlisting><![CDATA[ + proxy = dbus_g_proxy_new_for_name (system_bus_connection, + "org.freedesktop.Accounts", + "/org/freedesktop/Accounts", + "org.freedesktop.Accounts"); + ]]> + </programlisting></informalexample> + For a #DBusGProxy constructed like this, method calls will be sent to + the current owner of the name, and that owner can change over time. + </para> + <para> + The same can be achieved with #GDBusProxy: + <informalexample><programlisting><![CDATA[ + error = NULL; + proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, /* GDBusInterfaceInfo */ + "org.freedesktop.Accounts", + "/org/freedesktop/Accounts", + "org.freedesktop.Accounts", + NULL, /* GCancellable */ + &error); + ]]> + </programlisting></informalexample> + For an added layer of safety, you can specify what D-Bus + interface the proxy is expected to conform to by using the + #GDBusInterfaceInfo type. Additionally, #GDBusProxy loads, + caches and tracks changes to the D-Bus properties on the remote + object. It also sets up match rules so D-Bus signals from the + remote object are delivered locally. + </para> + <para> + The #GDBusProxy type normally isn't used directly - instead + proxies subclassing #GDBusProxy generated by <command><link + linkend="gdbus-codegen">gdbus-codegen</link></command> is used, see <xref linkend="gdbus-example-gdbus-codegen"/> + </para> + </section> + + <section> + <title>Generating code and docs</title> + + <section id="gdbus-example-gdbus-codegen"> + <title>Using gdbus-codegen</title> + + <para> + dbus-glib comes with <command>dbus-binding-tool</command>, which + can produce somewhat nice client- and server-side wrappers for a D-Bus interface. + With GDBus, <command><link + linkend="gdbus-codegen">gdbus-codegen</link></command> is used and like + its counterpart, it also takes D-Bus Introspection XML as input: + </para> + <example id="gdbus-example-codegen-input"><title>Example D-Bus Introspection XML</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../gdbus-example-objectmanager.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + <para> + If this XML is processed like this +<informalexample><programlisting><![CDATA[ +gdbus-codegen --interface-prefix org.gtk.GDBus.Example.ObjectManager. \ + --generate-c-code generated-code \ + --c-namespace Example \ + --c-generate-object-manager \ + --generate-docbook generated-docs \ + gdbus-example-objectmanager.xml +]]></programlisting></informalexample> + then two files <filename>generated-code.h</filename> and + <filename>generated-code.c</filename> are + generated. Additionally, two XML files + <filename>generated-docs-org.gtk.GDBus.Example.ObjectManager.Animal</filename> and + <filename>generated-docs-org.gtk.GDBus.Example.ObjectManager.Cat</filename> + with Docbook XML are generated. For an example of what the docs look + like see <link + linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal">the Animal D-Bus interface documentation</link>. + and + <link + linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat">the Cat D-Bus interface documentation</link>. + </para> + <para> + While the contents of <filename>generated-code.h</filename> and + <filename>generated-code.c</filename> are best described by the + <command><link + linkend="gdbus-codegen">gdbus-codegen</link></command> manual + page, brief examples of how this generated code can be used can be found in + <xref linkend="gdbus-example-codegen-server"/> + and <xref + linkend="gdbus-example-codegen-client"/>. Additionally, since + the generated code has 100% gtk-doc coverage, see + #ExampleAnimal, #ExampleCat, #ExampleObject and + #ExampleObjectManagerClient pages for documentation. + </para> + + <example id="gdbus-example-codegen-server"><title>Server-side application using generated code</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../gdbus-example-objectmanager-server.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + + <example id="gdbus-example-codegen-client"><title>Client-side application using generated code</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../gdbus-example-objectmanager-client.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + + </section> + + <xi:include href="../../../../gio/tests/gdbus-object-manager-example/objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Animal.xml"/> + <xi:include href="../../../../gio/tests/gdbus-object-manager-example/objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Cat.xml"/> + <xi:include href="../gdbus-object-manager-example/xml/ExampleAnimal.xml"/> + <xi:include href="../gdbus-object-manager-example/xml/ExampleCat.xml"/> + <xi:include href="../gdbus-object-manager-example/xml/ExampleObject.xml"/> + <xi:include href="../gdbus-object-manager-example/xml/ExampleObjectManagerClient.xml"/> + + </section> + +</chapter>
diff --git a/docs/reference/gio/migrating-gnome-vfs.xml b/docs/reference/gio/migrating-gnome-vfs.xml new file mode 100644 index 0000000..27194aa --- /dev/null +++ b/docs/reference/gio/migrating-gnome-vfs.xml
@@ -0,0 +1,133 @@ + <chapter> + <title>Migrating from GnomeVFS to GIO</title> + + <table id="gnome-vfs-vs-gio"> + <title>Comparison of GnomeVFS and GIO concepts</title> + <tgroup cols="2"> + <thead> + <row><entry>GnomeVFS</entry><entry>GIO</entry></row> + </thead> + <tbody> + <row><entry>GnomeVFSURI</entry><entry>GFile</entry></row> + <row><entry>GnomeVFSFileInfo</entry><entry>GFileInfo</entry></row> + <row><entry>GnomeVFSResult</entry><entry>GError, with G_IO_ERROR values</entry></row> + <row><entry>GnomeVFSHandle & GnomeVFSAsyncHandle</entry><entry>GInputStream or GOutputStream</entry></row> + <row><entry>GnomeVFSDirectoryHandle</entry><entry>GFileEnumerator</entry></row> + <row><entry>mime type</entry><entry>content type</entry></row> + <row><entry>GnomeVFSMonitor</entry><entry>GFileMonitor</entry></row> + <row><entry>GnomeVFSVolumeMonitor</entry><entry>GVolumeMonitor</entry></row> + <row><entry>GnomeVFSVolume</entry><entry>GMount</entry></row> + <row><entry>GnomeVFSDrive</entry><entry>GVolume</entry></row> + <row><entry>-</entry><entry>GDrive</entry></row> + <row><entry>GnomeVFSContext</entry><entry>GCancellable</entry></row> + <row><entry>gnome_vfs_async_cancel</entry><entry>g_cancellable_cancel</entry></row> + </tbody> + </tgroup> + </table> + + <section> + <title>Trash handling</title> + + <para> + The handling of trashed files has been changed in GIO, compared + to gnome-vfs. gnome-vfs has a home-grown trash implementation that + predates the freedesktop.org <ulink url="http://www.freedesktop.org/wiki/Specifications/trash-spec">Desktop Trash Can</ulink> specification + that is implemented in GIO. The location for storing trashed files + has changed from <filename>$HOME/.Trash</filename> to + <filename>$HOME/.local/share/Trash</filename> (or more correctly + <filename>$XDG_DATA_HOME/Trash</filename>), which means that + there is a need for migrating files that have been trashed by + gnome-vfs to the new location. + </para> + <para> + In gnome-vfs, the <filename>trash://</filename> scheme offering a + merged view of all trash directories was implemented in nautilus, + and trash-handling applications had to find and monitor all trash + directories themselves. With GIO, the <filename>trash://</filename> + implementation has been moved to gvfs and applications can simply + monitor that location: + </para> +<informalexample><programlisting> +static void +file_changed (GFileMonitor *file_monitor, + GFile *child, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + switch (event_type) + { + case G_FILE_MONITOR_EVENT_DELETED: + g_print ("'%s' removed from trash\n", g_file_get_basename (child)); + break; + case G_FILE_MONITOR_EVENT_CREATED: + g_print ("'%s' added to trash\n", g_file_get_basename (child)); + break; + default: ; + } +} + +static void +start_monitoring_trash (void) +{ + GFile *file; + GFileMonitor *monitor; + + file = g_file_new_for_uri ("trash://"); + monitor = g_file_monitor_directory (file, 0, NULL, NULL); + g_object_unref (file); + + g_signal_connect (monitor, "changed", G_CALLBACK (file_changed), NULL); + + /* ... */ + +} +</programlisting></informalexample> + <para> + GIO exposes some useful metadata about trashed files. There are + trash::orig-path and trash::deletion-date attributes. The + standard::icon attribute of the <filename>trash://</filename> + itself provides a suitable icon for displaying the trash can on + the desktop. If you are using this icon, make sure to monitor + this attribute for changes, since the icon may be updated to + reflect that state of the trash can. + </para> + <para> + Moving a file to the trash is much simpler with GIO. Instead of + using gnome_vfs_find_directory() with %GNOME_VFS_DIRECTORY_KIND_TRASH + to find out where to move the trashed file, just use the g_file_trash() + function. + </para> + </section> + + <section> + <title>Operations on multiple files</title> + + <para> + gnome-vfs has the dreaded gnome_vfs_xfer_uri_list() function which + has tons of options and offers the equivalent of cp, mv, ln, mkdir + and rm at the same time. + </para> + <para> + GIO offers a much simpler I/O scheduler functionality instead, that + lets you schedule a function to be called in a separate thread, or + if threads are not available, as an idle in the mainloop. + See g_io_scheduler_push_job(). + </para> + + </section> + + <section> + <title>Mime monitoring</title> + + <para> + gnome-vfs offered a way to monitor the association between mime types + and default handlers for changes, with the #GnomeVFSMIMEMonitor object. + GIO does not offer a replacement for this functionality at this time, + since we have not found a compelling use case where + #GnomeVFSMIMEMonitor was used. If you think you have such a use + case, please report it at + <ulink url="https://gitlab.gnome.org/GNOME/glib/issues/new">https://gitlab.gnome.org/GNOME/glib/issues/new</ulink>. + </para> + </section> + </chapter>
diff --git a/docs/reference/gio/migrating-posix.xml b/docs/reference/gio/migrating-posix.xml new file mode 100644 index 0000000..e7dc9f4 --- /dev/null +++ b/docs/reference/gio/migrating-posix.xml
@@ -0,0 +1,27 @@ +<part id="migrating"> + <title>Migrating to GIO</title> + + <chapter> + <title>Migrating from POSIX to GIO</title> + + <table id="posix-vs-gio"> + <title>Comparison of POSIX and GIO concepts</title> + <tgroup cols="2"> + <thead> + <row><entry>POSIX</entry><entry>GIO</entry></row> + </thead> + <tbody> + <row><entry>char *path</entry><entry>GFile *file</entry></row> + <row><entry>struct stat *buf</entry><entry>GFileInfo *info</entry></row> + <row><entry>struct statvfs *buf</entry><entry>GFileInfo *info</entry></row> + <row><entry morerows="1">int fd</entry><entry>GInputStream *in</entry></row> + <row><entry>GOutputStream *out</entry></row> + <row><entry>DIR *</entry><entry>GFileEnumerator *enum</entry></row> + <row><entry>fstab entry</entry><entry>GUnixMountPoint *mount_point</entry></row> + <row><entry>mtab entry</entry><entry>GUnixMountEntry *mount_entry</entry></row> + </tbody> + </tgroup> + </table> + + </chapter> +</part>
diff --git a/docs/reference/gio/overview.xml b/docs/reference/gio/overview.xml new file mode 100644 index 0000000..7817ab6 --- /dev/null +++ b/docs/reference/gio/overview.xml
@@ -0,0 +1,755 @@ +<part> + <title>GIO Overview</title> + + <chapter> + <title>Introduction</title> + + <para> + GIO is striving to provide a modern, easy-to-use VFS API that sits + at the right level in the library stack, as well as other generally + useful APIs for desktop applications (such as networking and + D-Bus support). The goal is to overcome the shortcomings of GnomeVFS + and provide an API that is so good that developers prefer it over raw + POSIX calls. Among other things that means using GObject. It also means + not cloning the POSIX API, but providing higher-level, document-centric + interfaces. + </para> + + <para> + The abstract file system model of GIO consists of a number of + interfaces and base classes for I/O and files: + <variablelist> + <varlistentry> + <term>GFile</term> + <listitem><para>reference to a file</para></listitem> + </varlistentry> + <varlistentry> + <term>GFileInfo</term> + <listitem><para>information about a file or filesystem</para></listitem> + </varlistentry> + <varlistentry> + <term>GFileEnumerator</term> + <listitem><para>list files in directories</para></listitem> + </varlistentry> + <varlistentry> + <term>GDrive</term> + <listitem><para>represents a drive</para></listitem> + </varlistentry> + <varlistentry> + <term>GVolume</term> + <listitem><para>represents a file system in an abstract way</para></listitem> + </varlistentry> + <varlistentry> + <term>GMount</term> + <listitem><para>represents a mounted file system</para></listitem> + </varlistentry> + </variablelist> + Then there is a number of stream classes, similar to the input and + output stream hierarchies that can be found in frameworks like Java: + <variablelist> + <varlistentry> + <term>GInputStream</term> + <listitem><para>read data</para></listitem> + </varlistentry> + <varlistentry> + <term>GOutputStream</term> + <listitem><para>write data</para></listitem> + </varlistentry> + <varlistentry> + <term>GIOStream</term> + <listitem><para>read and write data</para></listitem> + </varlistentry> + <varlistentry> + <term>GSeekable</term> + <listitem><para>interface optionally implemented by streams to support seeking</para></listitem> + </varlistentry> + </variablelist> + There are interfaces related to applications and the types + of files they handle: + <variablelist> + <varlistentry> + <term>GAppInfo</term> + <listitem><para>information about an installed application</para></listitem> + </varlistentry> + <varlistentry> + <term>GIcon</term> + <listitem><para>abstract type for file and application icons</para></listitem> + </varlistentry> + </variablelist> + There is a framework for storing and retrieving application settings: + <variablelist> + <varlistentry> + <term>GSettings</term> + <listitem><para>stores and retrieves application settings</para></listitem> + </varlistentry> + </variablelist> + There is support for network programming, including connectivity monitoring, + name resolution, lowlevel socket APIs and highlevel client and server + helper classes: + <variablelist> + <varlistentry> + <term>GSocket</term> + <listitem><para>lowlevel platform independent socket object</para></listitem> + </varlistentry> + <varlistentry> + <term>GResolver</term> + <listitem><para>asynchronous and cancellable DNS resolver</para></listitem> + </varlistentry> + <varlistentry> + <term>GSocketClient</term> + <listitem><para>high-level network client helper</para></listitem> + </varlistentry> + <varlistentry> + <term>GSocketService</term> + <listitem><para>high-level network server helper</para></listitem> + </varlistentry> + <varlistentry> + <term>GSocketConnection</term> + <listitem><para>network connection stream</para></listitem> + </varlistentry> + <varlistentry> + <term>GNetworkMonitor</term> + <listitem><para>network connectivity monitoring</para></listitem> + </varlistentry> + </variablelist> + There is support for connecting to <ulink url="http://www.freedesktop.org/wiki/Software/dbus">D-Bus</ulink>, + sending and receiving messages, owning and watching bus names, + and making objects available on the bus: + <variablelist> + <varlistentry> + <term>GDBusConnection</term> + <listitem><para>a D-Bus connection</para></listitem> + </varlistentry> + + <varlistentry> + <term>GDBusMethodInvocation</term> + <listitem><para>for handling remote calls</para></listitem> + </varlistentry> + + <varlistentry> + <term>GDBusServer</term> + <listitem><para>helper for accepting connections</para></listitem> + </varlistentry> + + <varlistentry> + <term>GDBusProxy</term> + <listitem><para>proxy to access D-Bus interfaces on a remote object</para></listitem> + </varlistentry> + + </variablelist> + Beyond these, GIO provides facilities for file monitoring, + asynchronous I/O and filename completion. In addition to the + interfaces, GIO provides implementations for the local case. + Implementations for various network file systems are provided + by the GVFS package as loadable modules. + </para> + + <para> + Other design choices which consciously break with the GnomeVFS + design are to move backends out-of-process, which minimizes the + dependency bloat and makes the whole system more robust. The backends + are not included in GIO, but in the separate GVFS package. The GVFS + package also contains the GVFS daemon, which spawn further mount + daemons for each individual connection. + </para> + + <figure id="gvfs-overview"> + <title>GIO in the GTK+ library stack</title> + <graphic fileref="gvfs-overview.png" format="PNG"></graphic> + </figure> + + <para> + The GIO model of I/O is stateful: if an application establishes e.g. + a SFTP connection to a server, it becomes available to all applications + in the session; the user does not have to enter his password over + and over again. + </para> + <para> + One of the big advantages of putting the VFS in the GLib layer + is that GTK+ can directly use it, e.g. in the filechooser. + </para> + </chapter> + + <chapter> + <title>Writing GIO applications</title> + + <para> + The information in the GLib <ulink url="http://developer.gnome.org/glib/stable/glib-programming.html">documentation</ulink> about writing GLib + applications is generally applicable when writing GIO applications. + </para> + + <simplesect><title>Threads</title> + + <para> + GDBus has its own private worker thread, so applications using + GDBus have at least 3 threads. GIO makes heavy use of the concept + of a <link linkend="g-main-context-push-thread-default">thread-default + main context</link> to execute callbacks of asynchronous + methods in the same context in which the operation was started. + </para> + + </simplesect> + + <simplesect id="async-programming"><title>Asynchronous Programming</title> + + <para> + Many GIO functions come in two versions: synchronous and asynchronous, + denoted by an <code>_async</code> suffix. It is important to use these + appropriately: synchronous calls should not be used from + within a main loop which is shared with other code, such as one in the + application’s main thread. Synchronous calls block until they complete, + and I/O operations can take noticeable amounts of time (even on ‘fast’ + SSDs). Blocking a main loop iteration while waiting for I/O means that + other sources in the main loop will not be dispatched, such as input and + redraw handlers for the application’s UI. This can cause the application + to ‘freeze’ until I/O completes. + </para> + + <para> + A few self-contained groups of functions, such as code generated by + <link linkend="gdbus-codegen"><application>gdbus-codegen</application></link>, + use a different convention: functions are asynchronous default, and it is + the <emphasis>synchronous</emphasis> version which has a + <code>_sync</code> + suffix. Aside from naming differences, they should be treated the same + way as functions following the normal convention above. + </para> + + <para> + The asynchronous (<code>_async</code>) versions of functions return + control to the caller immediately, after scheduling the I/O in the kernel + and adding a callback for it to the main loop. This callback will be + invoked when the operation has completed. From the callback, the paired + <code>_finish</code> function should be called to retrieve the return + value of the I/O operation, and any errors which occurred. For more + information on using and implementing asynchronous functions, see + <link linkend="GAsyncResult.description"><type>GAsyncResult</type></link> + and <link linkend="GTask.description"><type>GTask</type></link>. + </para> + + <para> + By starting multiple asynchronous operations in succession, they will be + executed in parallel (up to an arbitrary limit imposed by GIO’s internal + worker thread pool). + </para> + + <para> + The synchronous versions of functions can be used early in application + startup when there is no main loop to block, for example to load initial + configuration files. They can also be used for I/O on files which are + guaranteed to be small and on the local disk. Note that the user’s home + directory is not guaranteed to be on the local disk. + </para> + </simplesect> + + <simplesect><title>Security</title> + +<para> +When your program needs to carry out some privileged operation (say, +create a new user account), there are various ways in which you can go +about this: +<itemizedlist> +<listitem><para> +Implement a daemon that offers the privileged operation. A convenient +way to do this is as a D-Bus system-bus service. The daemon will probably +need ways to check the identity and authorization of the caller before +executing the operation. <ulink url="http://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html">polkit</ulink> is a framework that allows this. +</para></listitem> +<listitem><para> +Use a small helper that is executed with elevated privileges via +pkexec. <ulink url="http://www.freedesktop.org/software/polkit/docs/latest/pkexec.1.html">pkexec</ulink> is a small program launcher that is part of polkit. +</para></listitem> +<listitem><para> +Use a small helper that is executed with elevated privileges by +being suid root. +</para></listitem> +</itemizedlist> +None of these approaches is the clear winner, they all have their +advantages and disadvantages. +</para> + +<para> +When writing code that runs with elevated privileges, it is important +to follow some basic rules of secure programming. David Wheeler has an +excellent book on this topic, +<ulink url="http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/index.html">Secure Programming for Linux and Unix HOWTO</ulink>. +</para> + +<para> +When using GIO in code that runs with elevated privileges, you have to +be careful. GIO has extension points whose implementations get loaded +from modules (executable code in shared objects), which could allow +an attacker to sneak his own code into your application by tricking it +into loading the code as a module. However, GIO will never load modules +from your home directory except when explicitly asked to do so via an +environment variable. +</para> + +<para> +In most cases, your helper program should be so small that you don't +need GIO, whose APIs are largely designed to support full-blown desktop +applications. If you can't resist the convenience of these APIs, here +are some steps you should take: +<itemizedlist> +<listitem><para> +Clear the environment, e.g. using the <function>clearenv()</function> +function. +David Wheeler has a good <ulink url="http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/environment-variables.html">explanation</ulink> for why it is +important to sanitize the environment. +See <xref linkend="running-gio-apps"/> +for a list of all environment variables affecting GIO. In particular, +<envar>PATH</envar> (used to locate binaries), <envar>GIO_EXTRA_MODULES</envar> (used to locate loadable modules) and <envar>DBUS_{SYSTEM,SESSION}_BUS_ADDRESS</envar> (used to locate the D-Bus system and session bus) are important. +</para></listitem> +<listitem><para> +Don't use GVfs, by setting <envar>GIO_USE_VFS=local</envar> in the environment. +The reason to avoid GVfs in security-sensitive programs is that it uses +many libraries which have not necessarily been audited for security problems. +Gvfs is also heavily distributed and relies on a session bus to be present. +</para></listitem> +</itemizedlist> +</para> + + </simplesect> + + </chapter> + + <chapter> + <title>Compiling GIO applications</title> + + <para> + GIO comes with a <filename>gio-2.0.pc</filename> file that you + should use together with <literal>pkg-config</literal> to obtain + the necessary information about header files and libraries. See + the <literal>pkg-config</literal> man page or the GLib documentation + for more information on how to use <literal>pkg-config</literal> + to compile your application. + </para> + + <para> + If you are using GIO on UNIX-like systems, you may want to use + UNIX-specific GIO interfaces such as #GUnixInputStream, + #GUnixOutputStream, #GUnixMount or #GDesktopAppInfo. + To do so, use the <filename>gio-unix-2.0.pc</filename> file + instead of <filename>gio-2.0.pc</filename> + </para> + </chapter> + + <chapter id="running-gio-apps"> + <title>Running GIO applications</title> + + <para> + GIO inspects a few environment variables in addition to the + ones used by GLib. + </para> + + <formalpara> + <title><envar>XDG_DATA_HOME</envar>, <envar>XDG_DATA_DIRS</envar></title> + + <para> + GIO uses these environment variables to locate MIME information. + For more information, see the <ulink url="http://freedesktop.org/Standards/shared-mime-info-spec">Shared MIME-info Database</ulink> + and the <ulink url="http://freedesktop.org/Standards/basedir-spec">Base Directory Specification</ulink>. + </para> + </formalpara> + + <formalpara> + <title><envar>GVFS_DISABLE_FUSE</envar></title> + + <para> + This variable can be set to keep #Gvfs from starting the fuse backend, + which may be unwanted or unnecessary in certain situations. + </para> + </formalpara> + + <formalpara> + <title><envar>GIO_USE_VFS</envar></title> + + <para> + This environment variable can be set to the name of a #GVfs + implementation to override the default for debugging purposes. + The #GVfs implementation for local files that is included in GIO + has the name "local", the implementation in the gvfs module has + the name "gvfs". Most commonly, system software will set this to "local" + to avoid having `GFile` APIs perform unnecessary DBus calls. + </para><para> + The special value <literal>help</literal> can be used to print a list of + available implementations to standard output. + </para> + </formalpara> + + <para> + The following environment variables are only useful for debugging + GIO itself or modules that it loads. They should not be set in a + production environment. + </para> + + <formalpara> + <title><envar>GIO_USE_FILE_MONITOR</envar></title> + + <para> + This variable can be set to the name of a #GFileMonitor + implementation to override the default for debugging purposes. + The #GFileMonitor implementation for local files that is included + in GIO on Linux has the name "inotify", others that are built + are built as modules (depending on the platform) are called + "fam" and "fen". + </para><para> + The special value <literal>help</literal> can be used to print a list of + available implementations to standard output. + </para> + </formalpara> + + <formalpara> + <title><envar>GIO_USE_VOLUME_MONITOR</envar></title> + + <para> + This variable can be set to the name of a #GVolumeMonitor + implementation to override the default for debugging purposes. + The #GVolumeMonitor implementation for local files that is included + in GIO has the name "unix", the udisks2-based implementation in the + gvfs module has the name "udisks2". + </para><para> + The special value <literal>help</literal> can be used to print a list of + available implementations to standard output. + </para> + </formalpara> + + <formalpara> + <title><envar>GIO_USE_TLS</envar></title> + + <para> + This variable can be set to the name of a #GTlsBackend + implementation to override the default for debugging purposes. + GIO does not include a #GTlsBackend implementation, the gnutls-based + implementation in the glib-networking module has the name "gnutls". + </para><para> + The special value <literal>help</literal> can be used to print a list of + available implementations to standard output. + </para> + </formalpara> + + <formalpara> + <title><envar>GIO_MODULE_DIR</envar></title> + + <para> + When this environment variable is set to a path, GIO will load + modules from this alternate directory instead of the directory + built into GIO. This is useful when running tests, for example. + </para> + </formalpara> + + <formalpara> + <title><envar>GIO_EXTRA_MODULES</envar></title> + + <para> + When this environment variable is set to a path, or a set of + paths separated by a colon, GIO will attempt to load + additional modules from within the path. + </para> + </formalpara> + + <formalpara> + <title><envar>GSETTINGS_BACKEND</envar></title> + + <para> + This variable can be set to the name of a #GSettingsBackend + implementation to override the default for debugging purposes. + The memory-based implementation that is included in GIO has + the name "memory", the one in dconf has the name "dconf". + </para><para> + The special value <literal>help</literal> can be used to print a list of + available implementations to standard output. + </para> + </formalpara> + + <formalpara> + <title><envar>GSETTINGS_SCHEMA_DIR</envar></title> + + <para> + This variable can be set to the names of directories to consider when looking for compiled schemas for #GSettings, + in addition to the <filename>glib-2.0/schemas</filename> + subdirectories of the XDG system data dirs. To specify multiple directories, use <constant>G_SEARCHPATH_SEPARATOR_S</constant> as a separator. + </para> + </formalpara> + + <formalpara> + <title><envar>DBUS_SYSTEM_BUS_ADDRESS</envar></title> + + <para> + This variable is consulted to find the address of the D-Bus system + bus. For the format of D-Bus addresses, see the D-Bus + <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#addresses">specification</ulink>. + </para> + <para> + Setting this variable overrides platform-specific ways of determining + the system bus address. + </para> + </formalpara> + + <formalpara> + <title><envar>DBUS_SESSION_BUS_ADDRESS</envar></title> + + <para> + This variable is consulted to find the address of the D-Bus session bus. + </para> + <para> + Setting this variable overrides platform-specific ways of determining + the session bus address. + </para> + </formalpara> + + <formalpara> + <title><envar>DBUS_STARTER_BUS_TYPE</envar></title> + + <para> + This variable is consulted to find out the 'starter' bus for an + application that has been started via D-Bus activation. The possible + values are 'system' or 'session'. + </para> + </formalpara> + + <formalpara> + <title><envar>G_DBUS_DEBUG</envar></title> + + <para> + This variable can be set to a list of debug options, which + cause GLib to print out different types of debugging + information when using the D-Bus routines. + <variablelist> + <varlistentry> + <term>transport</term> + <listitem><para>Show IO activity (e.g. reads and writes)</para></listitem> + </varlistentry> + <varlistentry> + <term>message</term> + <listitem><para>Show all sent and received D-Bus messages</para></listitem> + </varlistentry> + <varlistentry> + <term>payload</term> + <listitem><para>Show payload for all sent and received D-Bus messages (implies message)</para></listitem> + </varlistentry> + <varlistentry> + <term>call</term> + <listitem><para>Trace g_dbus_connection_call() and g_dbus_connection_call_sync() API usage</para></listitem> + </varlistentry> + <varlistentry> + <term>signal</term> + <listitem><para>Show when a D-Bus signal is received</para></listitem> + </varlistentry> + <varlistentry> + <term>incoming</term> + <listitem><para>Show when an incoming D-Bus method call is received</para></listitem> + </varlistentry> + <varlistentry> + <term>return</term> + <listitem><para>Show when a reply is returned via the #GDBusMethodInvocation API</para></listitem> + </varlistentry> + <varlistentry> + <term>emission</term> + <listitem><para>Trace g_dbus_connection_emit_signal() API usage</para></listitem> + </varlistentry> + <varlistentry> + <term>authentication</term> + <listitem><para>Show information about connection authentication</para></listitem> + </varlistentry> + <varlistentry> + <term>address</term> + <listitem><para>Show information about D-Bus address lookups and autolaunching</para></listitem> + </varlistentry> + </variablelist> + The special value <literal>all</literal> can be used to turn + on all debug options. The special value + <literal>help</literal> can be used to print a list of + supported options to standard output. + </para> + </formalpara> + + <formalpara> + <title><envar>G_DBUS_COOKIE_SHA1_KEYRING_DIR</envar></title> + + <para> + Can be used to override the directory used to store the + keyring used in the <literal>DBUS_COOKIE_SHA1</literal> + authentication mechanism. Normally the directory used is + <filename>.dbus-keyrings</filename> in the user's home + directory. + </para> + </formalpara> + + <formalpara> + <title><envar>G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION</envar></title> + + <para> + If set, the permissions of the directory used to store the + keyring used in the <literal>DBUS_COOKIE_SHA1</literal> + authentication mechanism won't be checked. Normally the + directory must be readable only by the user. + </para> + </formalpara> + </chapter> + + <chapter id="extending-gio"> + <title>Extending GIO</title> + + <para> + A lot of the functionality that is accessible through GIO + is implemented in loadable modules, and modules provide a convenient + way to extend GIO. In addition to the #GIOModule API which supports + writing such modules, GIO has a mechanism to define extension points, + and register implementations thereof, see #GIOExtensionPoint. + </para> + <para> + The following extension points are currently defined by GIO: + </para> + + <formalpara> + <title>G_VFS_EXTENSION_POINT_NAME</title> + + <para> + Allows to override the functionality of the #GVfs class. + Implementations of this extension point must be derived from #GVfs. + GIO uses the implementation with the highest priority that is active, + see g_vfs_is_active(). + </para> + <para> + GIO implements this extension point for local files, gvfs contains + an implementation that supports all the backends in gvfs. + </para> + </formalpara> + + <formalpara> + <title>G_VOLUME_MONITOR_EXTENSION_POINT_NAME</title> + + <para> + Allows to add more volume monitors. + Implementations of this extension point must be derived from + #GVolumeMonitor. GIO uses all registered extensions. + </para> + <para> + gvfs contains an implementation that works together with the #GVfs + implementation in gvfs. + </para> + </formalpara> + + <formalpara> + <title>G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME</title> + + <para> + Allows to override the 'native' volume monitor. + Implementations of this extension point must be derived from + #GNativeVolumeMonitor. GIO uses the implementation with + the highest priority that is supported, as determined by the + is_supported() vfunc in #GVolumeMonitorClass. + </para> + <para> + GIO implements this extension point for local mounts, + gvfs contains a udisks2-based implementation. + </para> + </formalpara> + + <formalpara> + <title>G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME</title> + + <para> + Allows to override the file monitor implementation for + local files. Implementations of this extension point must + be derived from #GLocalFileMonitor. GIO uses the implementation + with the highest priority that is supported, as determined by the + is_supported() vfunc in #GLocalFileMonitorClass. + </para> + <para> + GIO uses this extension point internally, to switch between + its fam-based and inotify-based file monitoring implementations. + </para> + </formalpara> + + <formalpara> + <title>G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME</title> + + <para> + Allows to override the directory monitor implementation for + local files. Implementations of this extension point must be + derived from #GLocalDirectoryMonitor. GIO uses the implementation + with the highest priority that is supported, as determined by the + is_supported() vfunc in #GLocalDirectoryMonitorClass. + </para> + <para> + GIO uses this extension point internally, to switch between + its fam-based and inotify-based directory monitoring implementations. + </para> + </formalpara> + + <formalpara> + <title>G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME</title> + + <para> + Unix-only. Allows to provide a way to associate default handlers + with URI schemes. Implementations of this extension point must + implement the #GDesktopAppInfoLookup interface. GIO uses the + implementation with the highest priority. + </para> + <para> + This extension point has been discontinued in GLib 2.28. It is + still available to keep API and ABI stability, but GIO is no + longer using it for default handlers. Instead, the mime handler + mechanism is used, together with x-scheme-handler pseudo-mimetypes. + </para> + </formalpara> + + <formalpara> + <title>G_SETTINGS_BACKEND_EXTENSION_POINT_NAME</title> + + <para> + Allows to provide an alternative storage for #GSettings. + Implementations of this extension point must derive from the + #GSettingsBackend type. GIO contains a keyfile-based + implementation of this extension point, another one is provided + by dconf. + </para> + </formalpara> + + <formalpara> + <title>G_PROXY_EXTENSION_POINT_NAME</title> + + <para> + Allows to provide implementations for network proxying. + Implementations of this extension point must provide the + #GProxy interface, and must be named after the network + protocol they are proxying. + </para> + <para> + glib-networking contains an implementation of this extension + point based on libproxy. + </para> + </formalpara> + <formalpara> + <title>G_TLS_BACKEND_EXTENSION_POINT_NAME</title> + + <para> + Allows to provide implementations for TLS support. + Implementations of this extension point must implement + the #GTlsBackend interface. + </para> + <para> + glib-networking contains an implementation of this extension + point. + </para> + </formalpara> + + <formalpara> + <title>G_NETWORK_MONITOR_EXTENSION_POINT_NAME</title> + + <para> + Allows to provide implementations for network connectivity + monitoring. + Implementations of this extension point must implement + the #GNetworkMonitorInterface interface. + </para> + <para> + GIO contains an implementation of this extension point + that is using the netlink interface of the Linux kernel. + </para> + </formalpara> + </chapter> +</part> +
diff --git a/docs/reference/gio/version.xml.in b/docs/reference/gio/version.xml.in new file mode 100644 index 0000000..d78bda9 --- /dev/null +++ b/docs/reference/gio/version.xml.in
@@ -0,0 +1 @@ +@VERSION@
diff --git a/docs/reference/gio/xml/gtkdocentities.ent.in b/docs/reference/gio/xml/gtkdocentities.ent.in new file mode 100644 index 0000000..f12c9ff --- /dev/null +++ b/docs/reference/gio/xml/gtkdocentities.ent.in
@@ -0,0 +1,8 @@ +<!ENTITY package "@PACKAGE@"> +<!ENTITY package_bugreport "@PACKAGE_BUGREPORT@"> +<!ENTITY package_name "@PACKAGE_NAME@"> +<!ENTITY package_string "@PACKAGE_STRING@"> +<!ENTITY package_tarname "@PACKAGE_TARNAME@"> +<!ENTITY package_url "@PACKAGE_URL@"> +<!ENTITY package_version "@PACKAGE_VERSION@"> +<!ENTITY package_api_version "@PACKAGE_API_VERSION@">
diff --git a/docs/reference/gio/xml/meson.build b/docs/reference/gio/xml/meson.build new file mode 100644 index 0000000..6aeb745 --- /dev/null +++ b/docs/reference/gio/xml/meson.build
@@ -0,0 +1,14 @@ +ent_conf = configuration_data() +ent_conf.set('PACKAGE', 'glib') +ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/glib/issues/new') +ent_conf.set('PACKAGE_NAME', 'glib') +ent_conf.set('PACKAGE_STRING', 'glib') +ent_conf.set('PACKAGE_TARNAME', 'glib') +ent_conf.set('PACKAGE_URL', 'FIXME') +ent_conf.set('PACKAGE_VERSION', glib_version) +ent_conf.set('PACKAGE_API_VERSION', glib_api_version) +configure_file( + input: 'gtkdocentities.ent.in', + output: 'gtkdocentities.ent', + configuration: ent_conf +)
diff --git a/docs/reference/glib/Sorted_binary_tree_breadth-first_traversal.svg b/docs/reference/glib/Sorted_binary_tree_breadth-first_traversal.svg new file mode 100644 index 0000000..697d7db --- /dev/null +++ b/docs/reference/glib/Sorted_binary_tree_breadth-first_traversal.svg
@@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="266px" height="212px" viewBox="0 0 266 212" enable-background="new 0 0 266 212" xml:space="preserve"> +<g> + <g> + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="27.23" y1="23.192" x2="29.23" y2="23.192"/> + + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="3.9562,3.9562" x1="33.187" y1="23.192" x2="236.932" y2="23.192"/> + <polyline fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" points="238.91,23.192 240.91,23.192 + 238.97,23.677 "/> + + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="3.9907,3.9907" x1="235.099" y1="24.646" x2="27.971" y2="76.427"/> + <polyline fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" points="26.035,76.912 24.095,77.396 + 26.095,77.396 "/> + + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="4.0154,4.0154" x1="30.11" y1="77.396" x2="236.902" y2="77.396"/> + <polyline fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" points="238.91,77.396 240.91,77.396 + 238.97,77.881 "/> + + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="3.9907,3.9907" x1="235.099" y1="78.85" x2="27.971" y2="130.631"/> + <polyline fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" points="26.035,131.114 24.095,131.6 + 26.095,131.6 "/> + + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="4.0154,4.0154" x1="30.11" y1="131.6" x2="236.902" y2="131.6"/> + <polyline fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" points="238.91,131.6 240.91,131.6 + 238.97,132.085 "/> + + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="3.9907,3.9907" x1="235.099" y1="133.053" x2="27.971" y2="184.835"/> + <polyline fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" points="26.035,185.318 24.095,185.804 + 26.095,185.804 "/> + + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="4.0086,4.0086" x1="30.104" y1="185.804" x2="228.53" y2="185.804"/> + + <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="230.534" y1="185.804" x2="232.534" y2="185.804"/> + <g> + <rect x="24.095" y="19.892" width="6.602" height="6.602"/> + </g> + <g> + <path d="M238.569,185.804c-2.84,1.054-6.363,2.852-8.548,4.756l1.721-4.756l-1.721-4.755 + C232.206,182.953,235.729,184.751,238.569,185.804z"/> + </g> + </g> +</g> +<g id="graph0"> + <title>sorted_binary_tree</title> + <g id="node1"> + <title>C</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="60.23" cy="185.804" rx="18.067" ry="18.067"/> + <text transform="matrix(1 0 0 1 55.5435 190.8223)" font-family="'Times-Roman'" font-size="14.0528">C</text> + </g> + <g id="node2"> + <title>E</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="132.502" cy="185.804" rx="18.067" ry="18.067"/> + <text transform="matrix(1 0 0 1 128.21 190.8223)" font-family="'Times-Roman'" font-size="14.0528">E</text> + </g> + <g id="node3"> + <title>H</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="204.773" cy="185.804" rx="17.064" ry="18.067"/> + <text transform="matrix(1 0 0 1 199.6992 190.8223)" font-family="'Times-Roman'" font-size="14.0528">H</text> + </g> + <g id="node4"> + <title>A</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="24.094" cy="131.6" rx="17.064" ry="18.068"/> + <text transform="matrix(1 0 0 1 19.02 136.6191)" font-family="'Times-Roman'" font-size="14.0528">A</text> + </g> + <g id="node5"> + <title>D</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="96.366" cy="131.6" rx="17.064" ry="18.068"/> + <text transform="matrix(1 0 0 1 91.292 136.6191)" font-family="'Times-Roman'" font-size="14.0528">D</text> + </g> + <g id="edge6"> + <title>D->C</title> + <path fill="none" stroke="#000000" d="M86.328,147.66c-3.011,4.016-7.026,9.034-10.038,14.053"/> + <polygon stroke="#000000" points="78.298,164.725 70.268,170.747 73.279,160.709 "/> + </g> + <g id="edge8"> + <title>D->E</title> + <path fill="none" stroke="#000000" d="M106.404,147.66c3.011,4.016,7.026,9.034,10.038,14.053"/> + <polygon stroke="#000000" points="119.453,160.709 122.464,170.747 114.434,164.725 "/> + </g> + <g id="node6"> + <title>I</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="240.909" cy="131.6" rx="18.068" ry="18.068"/> + <text transform="matrix(1 0 0 1 238.5693 136.6191)" font-family="'Times-Roman'" font-size="14.0528">I</text> + </g> + <g id="edge12"> + <title>I->H</title> + <path fill="none" stroke="#000000" d="M230.871,146.656c-3.011,5.02-6.021,10.038-10.037,15.057"/> + <polygon stroke="#000000" points="223.846,163.721 214.812,169.743 217.822,159.705 "/> + </g> + <g id="node7"> + <title>B</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="60.23" cy="77.396" rx="18.068" ry="18.068"/> + <text transform="matrix(1 0 0 1 55.5435 82.415)" font-family="'Times-Roman'" font-size="14.0528">B</text> + </g> + <g id="edge3"> + <title>B->A</title> + <path fill="none" stroke="#000000" d="M50.192,92.453c-3.011,5.019-6.022,10.038-10.038,15.057"/> + <polygon stroke="#000000" points="43.166,109.518 34.132,115.539 37.144,105.502 "/> + </g> + <g id="edge5"> + <title>B->D</title> + <path fill="none" stroke="#000000" d="M70.268,92.453c3.011,5.019,6.022,10.038,10.038,15.057"/> + <polygon stroke="#000000" points="83.317,105.502 86.328,115.539 77.294,109.518 "/> + </g> + <g id="node8"> + <title>G</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="204.773" cy="77.396" rx="17.064" ry="18.068"/> + <text transform="matrix(1 0 0 1 199.6992 82.415)" font-family="'Times-Roman'" font-size="14.0528">G</text> + </g> + <g id="edge11"> + <title>G->I</title> + <path fill="none" stroke="#000000" d="M214.812,93.457c3.011,4.015,7.026,9.034,10.038,14.053"/> + <polygon stroke="#000000" points="227.86,106.506 230.871,116.543 222.842,110.521 "/> + </g> + <g id="node9"> + <title>F</title> + <ellipse fill="#FFFFFF" stroke="#000000" cx="132.502" cy="23.192" rx="18.068" ry="18.068"/> + <text transform="matrix(1 0 0 1 128.5942 28.2109)" font-family="'Times-Roman'" font-size="14.0528">F</text> + </g> + <g id="edge2"> + <title>F->B</title> + <path fill="none" stroke="#000000" d="M117.445,34.234c-11.042,8.03-23.087,17.064-34.128,26.098"/> + <polygon stroke="#000000" points="85.325,63.343 75.287,66.354 81.31,57.321 "/> + </g> + <g id="edge10"> + <title>F->G</title> + <path fill="none" stroke="#000000" d="M147.559,34.234c11.041,8.03,23.087,17.064,34.129,26.098"/> + <polygon stroke="#000000" points="183.694,57.321 189.717,66.354 179.68,63.343 "/> + </g> +</g> +</svg>
diff --git a/docs/reference/glib/Sorted_binary_tree_inorder.svg b/docs/reference/glib/Sorted_binary_tree_inorder.svg new file mode 100644 index 0000000..3927430 --- /dev/null +++ b/docs/reference/glib/Sorted_binary_tree_inorder.svg
@@ -0,0 +1,753 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="266" + height="226.79848" + id="svg3953" + version="1.1" + inkscape:version="0.48.4 r9939" + sodipodi:docname="Sorted_binary_tree_inorder.svg" + inkscape:export-filename="/home/mclasen/Sources/glib/docs/reference/glib/Sorted_binary_tree_inorder.png" + inkscape:export-xdpi="60.543114" + inkscape:export-ydpi="60.543114"> + <defs + id="defs3955"> + <marker + inkscape:stockid="SquareL" + orient="auto" + refY="0" + refX="0" + id="SquareL" + style="overflow:visible"> + <path + id="path4940" + d="M -5,-5 -5,5 5,5 5,-5 -5,-5 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="scale(0.8,0.8)" + inkscape:connector-curvature="0" /> + </marker> + <marker + style="overflow:visible" + id="DistanceStart" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="DistanceStart"> + <g + id="g2300"> + <path + style="fill:none;stroke:#ffffff;stroke-width:1.14999998;stroke-linecap:square" + d="M 0,0 2,0" + id="path2306" + inkscape:connector-curvature="0" /> + <path + style="fill:#000000;fill-rule:evenodd;stroke:none" + d="M 0,0 13,4 9,0 13,-4 0,0 z" + id="path2302" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square" + d="M 0,-4 0,40" + id="path2304" + inkscape:connector-curvature="0" /> + </g> + </marker> + <marker + inkscape:stockid="DotL" + orient="auto" + refY="0" + refX="0" + id="DotL" + style="overflow:visible"> + <path + id="path4931" + d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none" + transform="matrix(0.8,0,0,0.8,5.92,0.8)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow2Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow2Lend" + style="overflow:visible"> + <path + id="path4890" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + id="path4869" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="matrix(0.8,0,0,0.8,10,0)" + inkscape:connector-curvature="0" /> + </marker> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective3961" /> + <inkscape:perspective + id="perspective3971" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:path-effect + effect="spiro" + id="path-effect2940" + is_visible="true" /> + <inkscape:path-effect + effect="skeletal" + id="path-effect2942" + is_visible="true" + pattern="m 187.18135,13.365063 1,0" + copytype="single_stretched" + prop_scale="1" + scale_y_rel="false" + spacing="0" + normal_offset="0" + tang_offset="0" + prop_units="false" + vertical_pattern="false" + fuse_tolerance="0" /> + <inkscape:perspective + id="perspective4212" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-5" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-76" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-2" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-22" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-8" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4852" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective5886" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-4" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-1" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-3" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-11" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-74" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-79" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-9" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-6" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4" + inkscape:cx="-5.5963911" + inkscape:cy="76.419161" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1366" + inkscape:window-height="702" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata3958"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-275.57143,-78.931534)"> + <g + transform="matrix(0.9925764,0,0,0.9925764,278.52645,98.594058)" + id="graph0" + class="graph" + style="font-size:14px;font-family:Times-Roman"> + <title + id="title5">sorted_binary_tree</title> + <g + id="node1" + class="node"> + <title + id="title8">C</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="185" + sodipodi:cx="60" + d="m 78,185 c 0,9.94113 -8.058875,18 -18,18 -9.941125,0 -18,-8.05887 -18,-18 0,-9.94113 8.058875,-18 18,-18 9.941125,0 18,8.05887 18,18 z" + cx="60" + cy="185" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse10" /> + <text + style="text-anchor:middle" + x="60" + y="190" + id="text12">C</text> + </g> + <g + id="node2" + class="node"> + <title + id="title15">E</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="185" + sodipodi:cx="132" + d="m 150,185 c 0,9.94113 -8.05887,18 -18,18 -9.94113,0 -18,-8.05887 -18,-18 0,-9.94113 8.05887,-18 18,-18 9.94113,0 18,8.05887 18,18 z" + cx="132" + cy="185" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse17" /> + <text + style="text-anchor:middle" + x="132" + y="190" + id="text19">E</text> + </g> + <g + id="node3" + class="node"> + <title + id="title22">H</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="185" + sodipodi:cx="204" + d="m 221,185 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94113 7.61116,-18 17,-18 9.38884,0 17,8.05887 17,18 z" + cx="204" + cy="185" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse24" /> + <text + style="text-anchor:middle" + x="204" + y="190" + id="text26">H</text> + </g> + <g + id="node4" + class="node"> + <title + id="title29">A</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="131" + sodipodi:cx="24" + d="m 41,131 c 0,9.94113 -7.611159,18 -17,18 -9.388841,0 -17,-8.05887 -17,-18 0,-9.94113 7.611159,-18 17,-18 9.388841,0 17,8.05887 17,18 z" + cx="24" + cy="131" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse31" /> + <text + style="text-anchor:middle" + x="24" + y="136" + id="text33">A</text> + </g> + <g + id="node5" + class="node"> + <title + id="title36">D</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="131" + sodipodi:cx="96" + d="m 113,131 c 0,9.94113 -7.61116,18 -17,18 -9.388841,0 -17,-8.05887 -17,-18 0,-9.94113 7.611159,-18 17,-18 9.38884,0 17,8.05887 17,18 z" + cx="96" + cy="131" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse38" /> + <text + style="text-anchor:middle" + x="96" + y="136" + id="text40">D</text> + </g> + <g + id="edge6" + class="edge"> + <title + id="title43">D->C</title> + <path + style="fill:none;stroke:#000000" + d="m 86,147 c -3,4 -7,9 -10,14" + id="path45" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="78,164 70,170 73,160 78,164 " + id="polygon47" /> + </g> + <g + id="edge8" + class="edge"> + <title + id="title50">D->E</title> + <path + style="fill:none;stroke:#000000" + d="m 106,147 c 3,4 7,9 10,14" + id="path52" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="119,160 122,170 114,164 119,160 " + id="polygon54" /> + </g> + <g + id="node6" + class="node"> + <title + id="title57">I</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="131" + sodipodi:cx="240" + d="m 258,131 c 0,9.94113 -8.05887,18 -18,18 -9.94113,0 -18,-8.05887 -18,-18 0,-9.94113 8.05887,-18 18,-18 9.94113,0 18,8.05887 18,18 z" + cx="240" + cy="131" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse59" /> + <text + style="text-anchor:middle" + x="240" + y="136" + id="text61">I</text> + </g> + <g + id="edge12" + class="edge"> + <title + id="title64">I->H</title> + <path + style="fill:none;stroke:#000000" + d="m 230,146 c -3,5 -6,10 -10,15" + id="path66" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="223,163 214,169 217,159 223,163 " + id="polygon68" /> + </g> + <g + id="node7" + class="node"> + <title + id="title71">B</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="77" + sodipodi:cx="60" + d="m 78,77 c 0,9.941125 -8.058875,18 -18,18 -9.941125,0 -18,-8.058875 -18,-18 0,-9.941125 8.058875,-18 18,-18 9.941125,0 18,8.058875 18,18 z" + cx="60" + cy="77" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse73" /> + <text + style="text-anchor:middle" + x="60" + y="82" + id="text75">B</text> + </g> + <g + id="edge3" + class="edge"> + <title + id="title78">B->A</title> + <path + style="fill:none;stroke:#000000" + d="m 50,92 c -3,5 -6,10 -10,15" + id="path80" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="43,109 34,115 37,105 43,109 " + id="polygon82" /> + </g> + <g + id="edge5" + class="edge"> + <title + id="title85">B->D</title> + <path + style="fill:none;stroke:#000000" + d="m 70,92 c 3,5 6,10 10,15" + id="path87" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="83,105 86,115 77,109 83,105 " + id="polygon89" /> + </g> + <g + id="node8" + class="node"> + <title + id="title92">G</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="77" + sodipodi:cx="204" + d="m 221,77 c 0,9.941125 -7.61116,18 -17,18 -9.38884,0 -17,-8.058875 -17,-18 0,-9.941125 7.61116,-18 17,-18 9.38884,0 17,8.058875 17,18 z" + cx="204" + cy="77" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse94" /> + <text + style="text-anchor:middle" + x="204" + y="82" + id="text96">G</text> + </g> + <g + id="edge11" + class="edge"> + <title + id="title99">G->I</title> + <path + style="fill:none;stroke:#000000" + d="m 214,93 c 3,4 7,9 10,14" + id="path101" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="227,106 230,116 222,110 227,106 " + id="polygon103" /> + </g> + <g + id="node9" + class="node"> + <title + id="title106">F</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="23" + sodipodi:cx="132" + d="m 150,23 c 0,9.941125 -8.05887,18 -18,18 -9.94113,0 -18,-8.058875 -18,-18 0,-9.941125 8.05887,-18 18,-18 9.94113,0 18,8.058875 18,18 z" + cx="132" + cy="23" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse108" /> + <text + style="text-anchor:middle" + x="132" + y="28" + id="text110">F</text> + </g> + <g + id="edge2" + class="edge"> + <title + id="title113">F->B</title> + <path + style="fill:none;stroke:#000000" + d="M 117,34 C 106,42 94,51 83,60" + id="path115" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="85,63 75,66 81,57 85,63 " + id="polygon117" /> + </g> + <g + id="edge10" + class="edge"> + <title + id="title120">F->G</title> + <path + style="fill:none;stroke:#000000" + d="m 147,34 c 11,8 23,17 34,26" + id="path122" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="183,57 189,66 179,63 183,57 " + id="polygon124" /> + </g> + </g> + <path + style="fill:none;stroke:#000000;stroke-width:0.82904756;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3.31619022, 3.31619022;stroke-dashoffset:0;marker-start:url(#SquareL);marker-end:url(#Arrow2Lend)" + d="m 407.86585,83.916245 c -8.09235,12.934463 -16.24193,25.833125 -24.4484,38.695485 -4.10893,6.44009 -8.28,12.93078 -13.72464,18.28932 -5.44312,5.35704 -12.35084,9.56414 -19.94187,10.40186 -3.3055,0.36478 -6.64352,0.0886 -9.9615,-0.13591 -1e-5,0 -3e-5,0 -4e-5,0 -3.30753,-0.22377 -6.65223,-0.39935 -9.91915,0.16371 -3.67892,0.63407 -7.19225,2.2113 -10.11083,4.53904 -10e-6,1e-5 -2e-5,2e-5 -3e-5,2e-5 -2.91857,2.32774 -5.23772,5.40225 -6.67417,8.84797 -1.43645,3.44574 -1.98788,7.25719 -1.58695,10.96875 0.40093,3.71157 1.75359,7.31733 3.89275,10.37682 -1.57329,7.77579 -6.47676,14.83297 -13.21535,19.01981 -4.08578,2.53859 -8.72148,4.0255 -13.0897,6.03963 -2e-5,0 -3e-5,1e-5 -4e-5,2e-5 -4.36719,2.01365 -8.65699,4.73894 -11.05709,8.90627 -10e-6,1e-5 -10e-6,2e-5 -2e-5,3e-5 -1.54971,2.69079 -2.21037,5.86275 -2.00701,8.96123 0.20338,3.09874 1.25331,6.121 2.89275,8.75838 3.2781,5.27351 8.79594,8.88365 14.67878,10.8706 10e-6,0 2e-5,1e-5 4e-5,1e-5 5.05172,1.70623 10.53116,2.32159 15.76564,1.30607 1e-5,-1e-5 2e-5,-1e-5 3e-5,-1e-5 5.23327,-1.0153 10.20383,-3.73183 13.53666,-7.89237 2.8325,-3.53596 4.39168,-7.94004 5.28933,-12.38079 0,-1e-5 10e-6,-3e-5 10e-6,-4e-5 0.89772,-4.44111 1.18109,-8.97997 1.75051,-13.47498 0.87253,-6.88777 2.42162,-13.6897 4.61772,-20.27603 2.52197,-0.49612 5.17081,-0.33611 7.61472,0.45997 2.44389,0.79608 4.67875,2.2269 6.42464,4.11322 2e-5,1e-5 3e-5,3e-5 5e-5,5e-5 3.21102,3.46934 4.63062,8.27318 5.04051,12.98264 0.41,4.71077 -0.0852,9.44723 -0.1789,14.17488 -0.10721,5.4079 0.30156,10.912 -1.06029,16.14671 -1.55704,5.98502 -5.48588,11.32637 -10.73556,14.59527 -3.77605,-0.86428 -7.77873,-0.72238 -11.48409,0.40712 -3.70537,1.1295 -7.10659,3.24452 -9.75844,6.0682 -4.15358,4.42272 -6.37982,10.5847 -6.11019,16.64605 0,2e-5 0,3e-5 0,4e-5 0.23758,5.34073 2.36859,10.56193 5.83809,14.62917 10e-6,10e-6 2e-5,2e-5 3e-5,3e-5 3.46975,4.06752 8.24802,6.97932 13.4221,8.32573 4.51162,1.17403 9.34056,1.17129 13.82052,-0.11828 4.47975,-1.2895 8.59635,-3.87695 11.61522,-7.42904 3.02242,-3.55627 4.91711,-8.06019 5.34575,-12.70759 10e-6,-3e-5 10e-6,-5e-5 10e-6,-8e-5 0.42864,-4.64742 -0.61029,-9.42195 -2.93128,-13.47106 -1.10365,-2.89524 -1.08961,-6.20429 0.0386,-9.09005 0,-10e-6 1e-5,-3e-5 1e-5,-4e-5 1.1282,-2.88577 3.36222,-5.32694 6.1369,-6.70594 3.47162,-1.72538 7.76143,-1.72538 11.23305,0 3.47935,0.88812 6.65089,2.94914 8.87568,5.76782 2.22478,2.81869 3.49269,6.38223 3.5483,9.97271 0.0448,2.88989 -0.66677,5.7303 -1.2997,8.55039 -0.63291,2.82001 -1.19432,5.71596 -0.84587,8.58504 0,2e-5 0,3e-5 0,4e-5 0.43816,3.60767 2.33339,6.96423 4.97344,9.46172 2.64067,2.49807 5.99201,4.1741 9.49814,5.13355 10e-6,0 2e-5,1e-5 4e-5,1e-5 8.13425,2.22592 17.27288,0.51296 24.04882,-4.50774 2.95407,-2.80833 5.12951,-6.42944 6.22172,-10.35631 1.09222,-3.92687 1.09889,-8.15119 0.0191,-12.0815 -1.22234,-4.44914 -3.84239,-8.50594 -7.39496,-11.45011 -3.55256,-2.94417 -8.02526,-4.76546 -12.62397,-5.1405 -2e-5,0 -3e-5,0 -4e-5,0 -2.56836,0.72381 -5.27682,0.94784 -7.9292,0.65587 -10e-6,0 -2e-5,0 -4e-5,0 -3.77599,-0.41566 -7.46992,-1.91446 -10.28756,-4.46235 -10e-6,-1e-5 -2e-5,-1e-5 -2e-5,-2e-5 -2.8168,-2.54715 -4.70691,-6.17422 -4.91006,-9.96645 -0.14723,-2.74836 0.56276,-5.4692 1.41517,-8.08617 0.85243,-2.61706 1.85748,-5.20104 2.33283,-7.91207 0.92354,-5.26723 -0.28222,-10.88387 -3.28625,-15.30794 -3.00404,-4.42407 -7.77987,-7.61656 -13.01633,-8.70101 -3.38923,0.38773 -6.89239,-0.26847 -9.91151,-1.8566 -2e-5,-1e-5 -4e-5,-2e-5 -7e-5,-3e-5 -3.23617,-1.70233 -5.90142,-4.47336 -7.47657,-7.7733 -1.57515,-3.29994 -2.05353,-7.11482 -1.34194,-10.70152 0,-2e-5 1e-5,-5e-5 1e-5,-7e-5 0.98555,-6.30654 2.75458,-12.49035 5.25348,-18.36396 1e-5,-2e-5 2e-5,-5e-5 3e-5,-7e-5 2.90825,-6.83578 6.89834,-13.35821 12.56261,-18.16464 5.66117,-4.8038 13.16594,-7.75245 20.54108,-6.89651 4.32392,0.50183 8.42733,2.25397 12.75051,2.76214 4.7583,0.55932 9.69143,-0.45462 13.8434,-2.84533 2e-5,-2e-5 4e-5,-3e-5 6e-5,-4e-5 9.24006,1.13358 17.98407,5.97778 23.8453,13.21033 5.15234,6.35781 7.99577,14.2147 11.30601,21.69872 1.92466,4.3514 4.05797,8.66096 7.03333,12.37393 10e-6,2e-5 3e-5,4e-5 5e-5,6e-5 2.97478,3.71223 6.87266,6.82357 11.43539,8.16948 2e-5,1e-5 5e-5,1e-5 7e-5,2e-5 4.08278,1.20432 8.59203,0.91743 12.48927,-0.79459 2.77058,2.06261 4.93246,4.93513 6.1476,8.16838 10e-6,2e-5 2e-5,4e-5 2e-5,6e-5 1.21514,3.23328 1.48028,6.81866 0.75396,10.19551 -0.64549,3.00105 -2.03848,5.78453 -2.94997,8.71576 -0.45574,1.4656 -0.79214,2.97858 -0.84237,4.51258 -0.0502,1.5339 0.19468,3.09454 0.85538,4.47976 1.12213,2.35266 3.31808,4.00019 4.78859,6.15235 10e-6,2e-5 3e-5,4e-5 4e-5,6e-5 1.28491,1.88055 1.99273,4.15109 2.00406,6.42866 0,2e-5 0,5e-5 0,7e-5 0.0113,2.27755 -0.67387,4.55499 -1.94,6.44821 -1.26613,1.89323 -3.10926,3.39632 -5.21849,4.25572 -2.10924,0.8594 -4.47799,1.07243 -6.70672,0.60317 -6.72013,2.08 -13.07673,5.33027 -18.69744,9.56041 -3.43389,2.58434 -6.63757,5.58482 -8.83155,9.28034 -2.19309,3.69404 -3.30672,8.16333 -2.4015,12.36288 0.73825,3.42496 2.77646,6.49085 5.39143,8.82264 2.61545,2.33222 5.78751,3.97275 9.08008,5.17224 2e-5,1e-5 5e-5,2e-5 7e-5,3e-5 7.59964,2.76856 16.01971,3.25052 23.88562,1.3672 2e-5,-10e-6 4e-5,-3e-5 6e-5,-4e-5 5.55583,-4.2436 9.26683,-10.83973 10.0094,-17.79128 0.48273,-4.51901 -0.25456,-9.16391 -2.11291,-13.31132 -1.12772,-3.87126 -0.64207,-8.19191 1.31693,-11.71621 1.95901,-3.5243 5.37216,-6.21769 9.25535,-7.3036 3.03411,-0.84847 6.23896,-0.7413 9.38918,-0.78414 3.15001,-0.0428 6.40369,-0.26967 9.21028,-1.70056 1.87052,-0.95365 3.46254,-2.41445 4.68173,-4.12379 1.21923,-1.70942 2.07411,-3.66326 2.63108,-5.68772 0,-2e-5 10e-6,-4e-5 2e-5,-7e-5 1.11392,-4.04896 1.04531,-8.32057 0.84497,-12.51519 0,-2e-5 0,-5e-5 0,-7e-5 -0.20277,-4.24553 -0.53208,-8.48502 -0.98732,-12.71094 -1.04658,-3.18409 -3.10978,-6.02749 -5.8122,-8.01008 -2.70242,-1.9826 -6.03405,-3.09704 -9.38546,-3.13947 -1.77072,-0.0224 -3.53043,0.24491 -5.29437,0.40133 -1.76389,0.15642 -3.56824,0.19871 -5.27791,-0.26261 -1.52465,-0.4114 -2.93141,-1.21815 -4.11285,-2.26602 -2e-5,-2e-5 -3e-5,-3e-5 -5e-5,-5e-5 -1.1815,-1.04794 -2.14182,-2.33315 -2.88667,-3.72574 -1.48968,-2.78513 -2.11051,-5.95234 -2.4471,-9.09286 0,-2e-5 -10e-6,-5e-5 -10e-6,-7e-5 -0.7501,-6.99887 -0.1865,-14.13231 -1.52514,-21.0428 -0.72945,-3.76565 -2.0464,-7.46897 -4.28746,-10.58183 -2.2404,-3.11195 -5.46685,-5.60479 -9.18911,-6.5259 -3.02141,-0.74768 -6.20154,-0.44617 -9.27072,0.0716 -3.06933,0.51775 -6.11978,1.24879 -9.23079,1.35113 -2e-5,0 -5e-5,0 -7e-5,0 -3.90344,0.1284 -7.81108,-0.74979 -11.38322,-2.32877 -3.5723,-1.57904 -6.81761,-3.84706 -9.69109,-6.49241 -5.74696,-5.29072 -9.96674,-12.00296 -13.94631,-18.72474 -2.39922,-4.05246 -4.71299,-8.17874 -6.40846,-12.57238 -1.69522,-4.39298 -2.67881,-9.02583 -3.50306,-13.661852 l -1.9823,-11.149545" + id="path2938" + inkscape:path-effect="#path-effect2940;#path-effect2942" + inkscape:original-d="m 407.86585,83.916245 c 0,0 -14.11559,27.469705 -24.4484,38.695485 -9.34236,10.14972 -20.62893,24.18364 -33.66651,28.69118 -10.61846,3.67116 -11.93657,-7.91708 -19.88069,0.0278 -8.03966,8.04037 -7.9913,25.39502 -14.47923,34.7326 0,0 -7.13271,14.26573 -13.21535,19.01981 -8.72576,6.81989 -26.98503,4.24108 -24.14685,14.94595 2.83816,10.70488 4.57641,21.84782 15.56452,28.59021 9.79125,6.00799 28.36077,4.86263 29.30237,-6.5863 0.94161,-11.44892 3.2096,-17.00295 7.03985,-25.85581 3.83025,-8.85286 -1.10893,-26.61597 4.61772,-20.27603 0,0 11.6923,-3.64141 14.03941,4.57324 1.70869,5.98028 2.66345,21.33932 4.86161,27.15752 2.19816,5.81821 -0.52766,12.44562 -1.06029,16.14671 -1.09286,7.59409 -3.21008,13.10136 -10.73556,14.59527 0,0 -15.16484,1.49219 -21.24253,6.47532 -6.22299,5.10225 -7.51576,8.72253 -6.11019,16.64609 1.81705,10.24319 9.04679,20.97753 19.26022,22.95493 11.49367,2.22528 19.58074,2.59049 25.43574,-7.54732 4.1679,-7.21663 -1.97686,-19.09584 2.41448,-26.17873 0,0 0.33183,-12.5434 6.17549,-15.79603 3.2717,-1.82105 9.2379,-3.16852 11.23305,0 0,0 11.52539,9.6056 12.42398,15.74053 0.95363,6.51078 -5.98915,11.79446 -2.14557,17.13547 3.84359,5.34102 7.61186,11.46161 14.47158,14.59527 8.85083,4.04326 19.94604,4.31564 24.04886,-4.50773 0,0 8.1669,-13.23439 6.24082,-22.43781 -2.16604,-10.34997 -9.48077,-17.46228 -20.01897,-16.59061 0,0 -5.42758,1.53646 -7.9292,0.65587 -6.58909,-2.31941 -16.02955,-7.49314 -15.19768,-14.42882 0.83187,-6.93568 9.55833,8.44447 3.748,-15.99824 -1.55478,-6.54061 -9.59437,-24.45283 -16.30258,-24.00895 0,0 -6.96155,-0.35298 -9.91151,-1.8566 -7.36557,-3.75427 -10.83778,-10.45812 -8.81857,-18.47492 0,0 1.87298,-13.03292 5.25348,-18.36396 7.93496,-12.51342 19.58924,-22.07695 33.10372,-25.06122 4.24644,-0.93771 6.93062,3.3283 12.75051,2.76214 5.10303,-0.49642 9.84185,-6.05074 13.84346,-2.84537 0,0 16.88165,-1.28992 23.8453,13.21033 3.31247,6.89749 4.71066,17.81941 11.30601,21.69872 6.59535,3.87931 11.60217,19.87279 18.46884,20.54349 3.94867,0.38568 10.25015,-4.06981 12.48927,-0.79459 0,0 6.35327,10.96916 6.90158,18.36395 0.48511,6.54257 -6.59488,12.262 -2.93696,17.7081 3.65793,5.44611 4.68796,1.4131 4.78863,6.15241 0.15241,7.17408 -4.7607,16.6994 -11.86115,17.73583 0,0 -12.53135,5.17234 -18.69744,9.56041 -6.62245,4.71284 -15.87104,14.96813 -11.23305,21.64322 0,0 7.82042,10.07549 14.47158,13.99491 7.43886,4.38361 19.41887,8.75645 23.88562,1.3672 0,0 8.90884,-10.20704 10.00946,-17.79132 0.87615,-6.0375 -5.07693,-7.979 -2.11291,-13.31132 0,0 4.26218,-15.44258 10.57228,-19.01981 5.94288,-3.36906 15.32144,3.50888 18.59946,-2.4847 0,0 7.61918,-13.6222 8.1578,-22.32684 0.40659,-6.57079 4.32078,-8.81675 -0.98732,-12.71094 0,0 -9.00115,-10.11082 -15.19766,-11.14955 -3.63896,-0.61001 -8.14088,2.91403 -10.57228,0.13872 0,0 -8.10433,-8.53592 -9.44667,-15.08467 -1.56983,-7.65869 4.02354,-15.53542 -1.52515,-21.04287 -5.54869,-5.50744 -5.14034,-14.65591 -13.47657,-17.10773 -6.04893,-1.77908 -13.54572,5.32072 -18.50151,1.42268 -4.95579,-3.89803 -26.23756,-15.56939 -35.02069,-27.54592 -5.52823,-7.53822 -8.27517,-17.03053 -9.91152,-26.234232 l -1.9823,-11.149545" + sodipodi:nodetypes="cssssszszzsszsssssssssszssssszsssssassszssszssssssssssssssszszssc" + inkscape:connector-curvature="0" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,454.12853,95.367832)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-9" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,525.04284,40.275046)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-2" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,418.24759,148.76546)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-95" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,454.97612,201.88055)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-3" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,490.00948,149.33052)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-27" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,526.17295,202.4456)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-31" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,596.80473,93.955197)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-8" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,634.0983,148.2004)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-5" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,597.36978,202.44561)" /> + </g> +</svg>
diff --git a/docs/reference/glib/Sorted_binary_tree_postorder.svg b/docs/reference/glib/Sorted_binary_tree_postorder.svg new file mode 100644 index 0000000..1160e42 --- /dev/null +++ b/docs/reference/glib/Sorted_binary_tree_postorder.svg
@@ -0,0 +1,750 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="265.90625" + height="226.94397" + id="svg3953" + version="1.1" + inkscape:version="0.48.4 r9939" + sodipodi:docname="Sorted_binary_tree_postorder.svg"> + <defs + id="defs3955"> + <marker + inkscape:stockid="SquareL" + orient="auto" + refY="0" + refX="0" + id="SquareL" + style="overflow:visible"> + <path + id="path4940" + d="M -5,-5 -5,5 5,5 5,-5 -5,-5 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="scale(0.8,0.8)" + inkscape:connector-curvature="0" /> + </marker> + <marker + style="overflow:visible" + id="DistanceStart" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="DistanceStart"> + <g + id="g2300"> + <path + style="fill:none;stroke:#ffffff;stroke-width:1.14999998;stroke-linecap:square" + d="M 0,0 2,0" + id="path2306" + inkscape:connector-curvature="0" /> + <path + style="fill:#000000;fill-rule:evenodd;stroke:none" + d="M 0,0 13,4 9,0 13,-4 0,0 z" + id="path2302" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square" + d="M 0,-4 0,40" + id="path2304" + inkscape:connector-curvature="0" /> + </g> + </marker> + <marker + inkscape:stockid="DotL" + orient="auto" + refY="0" + refX="0" + id="DotL" + style="overflow:visible"> + <path + id="path4931" + d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none" + transform="matrix(0.8,0,0,0.8,5.92,0.8)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow2Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow2Lend" + style="overflow:visible"> + <path + id="path4890" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + id="path4869" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="matrix(0.8,0,0,0.8,10,0)" + inkscape:connector-curvature="0" /> + </marker> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective3961" /> + <inkscape:perspective + id="perspective3971" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:path-effect + effect="spiro" + id="path-effect2940" + is_visible="true" /> + <inkscape:path-effect + effect="skeletal" + id="path-effect2942" + is_visible="true" + pattern="m 187.18135,13.365063 1,0" + copytype="single_stretched" + prop_scale="1" + scale_y_rel="false" + spacing="0" + normal_offset="0" + tang_offset="0" + prop_units="false" + vertical_pattern="false" + fuse_tolerance="0" /> + <inkscape:perspective + id="perspective4212" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-5" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-76" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-2" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-22" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-8" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4852" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective5886" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-4" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-1" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-3" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-11" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-74" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-79" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-9" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-6" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4" + inkscape:cx="-131.03835" + inkscape:cy="76.407899" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1366" + inkscape:window-height="702" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata3958"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-275.65625,-78.774784)"> + <g + transform="matrix(0.9925764,0,0,0.9925764,278.52645,98.594058)" + id="graph0" + class="graph" + style="font-size:14px;font-family:Times-Roman"> + <title + id="title5">sorted_binary_tree</title> + <g + id="node1" + class="node"> + <title + id="title8">C</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="185" + sodipodi:cx="60" + d="m 78,185 c 0,9.94113 -8.058875,18 -18,18 -9.941125,0 -18,-8.05887 -18,-18 0,-9.94113 8.058875,-18 18,-18 9.941125,0 18,8.05887 18,18 z" + cx="60" + cy="185" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse10" /> + <text + style="text-anchor:middle" + x="60" + y="190" + id="text12">C</text> + </g> + <g + id="node2" + class="node"> + <title + id="title15">E</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="185" + sodipodi:cx="132" + d="m 150,185 c 0,9.94113 -8.05887,18 -18,18 -9.94113,0 -18,-8.05887 -18,-18 0,-9.94113 8.05887,-18 18,-18 9.94113,0 18,8.05887 18,18 z" + cx="132" + cy="185" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse17" /> + <text + style="text-anchor:middle" + x="132" + y="190" + id="text19">E</text> + </g> + <g + id="node3" + class="node"> + <title + id="title22">H</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="185" + sodipodi:cx="204" + d="m 221,185 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94113 7.61116,-18 17,-18 9.38884,0 17,8.05887 17,18 z" + cx="204" + cy="185" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse24" /> + <text + style="text-anchor:middle" + x="204" + y="190" + id="text26">H</text> + </g> + <g + id="node4" + class="node"> + <title + id="title29">A</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="131" + sodipodi:cx="24" + d="m 41,131 c 0,9.94113 -7.611159,18 -17,18 -9.388841,0 -17,-8.05887 -17,-18 0,-9.94113 7.611159,-18 17,-18 9.388841,0 17,8.05887 17,18 z" + cx="24" + cy="131" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse31" /> + <text + style="text-anchor:middle" + x="24" + y="136" + id="text33">A</text> + </g> + <g + id="node5" + class="node"> + <title + id="title36">D</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="131" + sodipodi:cx="96" + d="m 113,131 c 0,9.94113 -7.61116,18 -17,18 -9.388841,0 -17,-8.05887 -17,-18 0,-9.94113 7.611159,-18 17,-18 9.38884,0 17,8.05887 17,18 z" + cx="96" + cy="131" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse38" /> + <text + style="text-anchor:middle" + x="96" + y="136" + id="text40">D</text> + </g> + <g + id="edge6" + class="edge"> + <title + id="title43">D->C</title> + <path + style="fill:none;stroke:#000000" + d="m 86,147 c -3,4 -7,9 -10,14" + id="path45" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="78,164 70,170 73,160 78,164 " + id="polygon47" /> + </g> + <g + id="edge8" + class="edge"> + <title + id="title50">D->E</title> + <path + style="fill:none;stroke:#000000" + d="m 106,147 c 3,4 7,9 10,14" + id="path52" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="119,160 122,170 114,164 119,160 " + id="polygon54" /> + </g> + <g + id="node6" + class="node"> + <title + id="title57">I</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="131" + sodipodi:cx="240" + d="m 258,131 c 0,9.94113 -8.05887,18 -18,18 -9.94113,0 -18,-8.05887 -18,-18 0,-9.94113 8.05887,-18 18,-18 9.94113,0 18,8.05887 18,18 z" + cx="240" + cy="131" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse59" /> + <text + style="text-anchor:middle" + x="240" + y="136" + id="text61">I</text> + </g> + <g + id="edge12" + class="edge"> + <title + id="title64">I->H</title> + <path + style="fill:none;stroke:#000000" + d="m 230,146 c -3,5 -6,10 -10,15" + id="path66" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="223,163 214,169 217,159 223,163 " + id="polygon68" /> + </g> + <g + id="node7" + class="node"> + <title + id="title71">B</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="77" + sodipodi:cx="60" + d="m 78,77 c 0,9.941125 -8.058875,18 -18,18 -9.941125,0 -18,-8.058875 -18,-18 0,-9.941125 8.058875,-18 18,-18 9.941125,0 18,8.058875 18,18 z" + cx="60" + cy="77" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse73" /> + <text + style="text-anchor:middle" + x="60" + y="82" + id="text75">B</text> + </g> + <g + id="edge3" + class="edge"> + <title + id="title78">B->A</title> + <path + style="fill:none;stroke:#000000" + d="m 50,92 c -3,5 -6,10 -10,15" + id="path80" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="43,109 34,115 37,105 43,109 " + id="polygon82" /> + </g> + <g + id="edge5" + class="edge"> + <title + id="title85">B->D</title> + <path + style="fill:none;stroke:#000000" + d="m 70,92 c 3,5 6,10 10,15" + id="path87" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="83,105 86,115 77,109 83,105 " + id="polygon89" /> + </g> + <g + id="node8" + class="node"> + <title + id="title92">G</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="77" + sodipodi:cx="204" + d="m 221,77 c 0,9.941125 -7.61116,18 -17,18 -9.38884,0 -17,-8.058875 -17,-18 0,-9.941125 7.61116,-18 17,-18 9.38884,0 17,8.058875 17,18 z" + cx="204" + cy="77" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse94" /> + <text + style="text-anchor:middle" + x="204" + y="82" + id="text96">G</text> + </g> + <g + id="edge11" + class="edge"> + <title + id="title99">G->I</title> + <path + style="fill:none;stroke:#000000" + d="m 214,93 c 3,4 7,9 10,14" + id="path101" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="227,106 230,116 222,110 227,106 " + id="polygon103" /> + </g> + <g + id="node9" + class="node"> + <title + id="title106">F</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="23" + sodipodi:cx="132" + d="m 150,23 c 0,9.941125 -8.05887,18 -18,18 -9.94113,0 -18,-8.058875 -18,-18 0,-9.941125 8.05887,-18 18,-18 9.94113,0 18,8.058875 18,18 z" + cx="132" + cy="23" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse108" /> + <text + style="text-anchor:middle" + x="132" + y="28" + id="text110">F</text> + </g> + <g + id="edge2" + class="edge"> + <title + id="title113">F->B</title> + <path + style="fill:none;stroke:#000000" + d="M 117,34 C 106,42 94,51 83,60" + id="path115" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="85,63 75,66 81,57 85,63 " + id="polygon117" /> + </g> + <g + id="edge10" + class="edge"> + <title + id="title120">F->G</title> + <path + style="fill:none;stroke:#000000" + d="m 147,34 c 11,8 23,17 34,26" + id="path122" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="183,57 189,66 179,63 183,57 " + id="polygon124" /> + </g> + </g> + <path + style="fill:none;stroke:#000000;stroke-width:0.82904756;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3.31619022, 3.31619022;stroke-dashoffset:0;marker-start:url(#SquareL);marker-end:url(#Arrow2Lend)" + d="m 407.86585,83.916245 c -8.09235,12.934463 -16.24193,25.833125 -24.4484,38.695485 -4.10893,6.44009 -8.28,12.93078 -13.72464,18.28932 -5.44312,5.35704 -12.35084,9.56414 -19.94187,10.40186 -3.3055,0.36478 -6.64352,0.0886 -9.9615,-0.13591 -1e-5,0 -3e-5,0 -4e-5,0 -3.30753,-0.22377 -6.65223,-0.39935 -9.91915,0.16371 -3.67892,0.63407 -7.19225,2.2113 -10.11083,4.53904 -10e-6,1e-5 -2e-5,2e-5 -3e-5,2e-5 -2.91857,2.32774 -5.23772,5.40225 -6.67417,8.84797 -1.43645,3.44574 -1.98788,7.25719 -1.58695,10.96875 0.40093,3.71157 1.75359,7.31733 3.89275,10.37682 -1.57329,7.77579 -6.47676,14.83297 -13.21535,19.01981 -4.08578,2.53859 -8.72148,4.0255 -13.0897,6.03963 -2e-5,0 -3e-5,1e-5 -4e-5,2e-5 -4.36719,2.01365 -8.65699,4.73894 -11.05709,8.90627 -10e-6,1e-5 -10e-6,2e-5 -2e-5,3e-5 -1.54971,2.69079 -2.21037,5.86275 -2.00701,8.96123 0.20338,3.09874 1.25331,6.121 2.89275,8.75838 3.2781,5.27351 8.79594,8.88365 14.67878,10.8706 10e-6,0 2e-5,1e-5 4e-5,1e-5 5.05172,1.70623 10.53116,2.32159 15.76564,1.30607 1e-5,-1e-5 2e-5,-1e-5 3e-5,-1e-5 5.23327,-1.0153 10.20383,-3.73183 13.53666,-7.89237 2.8325,-3.53596 4.39168,-7.94004 5.28933,-12.38079 0,-1e-5 10e-6,-3e-5 10e-6,-4e-5 0.89772,-4.44111 1.18109,-8.97997 1.75051,-13.47498 0.87253,-6.88777 2.42162,-13.6897 4.61772,-20.27603 2.52197,-0.49612 5.17081,-0.33611 7.61472,0.45997 2.44389,0.79608 4.67875,2.2269 6.42464,4.11322 2e-5,1e-5 3e-5,3e-5 5e-5,5e-5 3.21102,3.46934 4.63062,8.27318 5.04051,12.98264 0.41,4.71077 -0.0852,9.44723 -0.1789,14.17488 -0.10721,5.4079 0.30156,10.912 -1.06029,16.14671 -1.55704,5.98502 -5.48588,11.32637 -10.73556,14.59527 -3.77605,-0.86428 -7.77873,-0.72238 -11.48409,0.40712 -3.70537,1.1295 -7.10659,3.24452 -9.75844,6.0682 -4.15358,4.42272 -6.37982,10.5847 -6.11019,16.64605 0,2e-5 0,3e-5 0,4e-5 0.23758,5.34073 2.36859,10.56193 5.83809,14.62917 10e-6,10e-6 2e-5,2e-5 3e-5,3e-5 3.46975,4.06752 8.24802,6.97932 13.4221,8.32573 4.51162,1.17403 9.34056,1.17129 13.82052,-0.11828 4.47975,-1.2895 8.59635,-3.87695 11.61522,-7.42904 3.02242,-3.55627 4.91711,-8.06019 5.34575,-12.70759 10e-6,-3e-5 10e-6,-5e-5 10e-6,-8e-5 0.42864,-4.64742 -0.61029,-9.42195 -2.93128,-13.47106 -1.10365,-2.89524 -1.08961,-6.20429 0.0386,-9.09005 0,-10e-6 1e-5,-3e-5 1e-5,-4e-5 1.1282,-2.88577 3.36222,-5.32694 6.1369,-6.70594 3.47162,-1.72538 7.76143,-1.72538 11.23305,0 3.47935,0.88812 6.65089,2.94914 8.87568,5.76782 2.22478,2.81869 3.49269,6.38223 3.5483,9.97271 0.0448,2.88989 -0.66677,5.7303 -1.2997,8.55039 -0.63291,2.82001 -1.19432,5.71596 -0.84587,8.58504 0,2e-5 0,3e-5 0,4e-5 0.43816,3.60767 2.33339,6.96423 4.97344,9.46172 2.64067,2.49807 5.99201,4.1741 9.49814,5.13355 10e-6,0 2e-5,1e-5 4e-5,1e-5 8.13425,2.22592 17.27288,0.51296 24.04882,-4.50774 2.95407,-2.80833 5.12951,-6.42944 6.22172,-10.35631 1.09222,-3.92687 1.09889,-8.15119 0.0191,-12.0815 -1.22234,-4.44914 -3.84239,-8.50594 -7.39496,-11.45011 -3.55256,-2.94417 -8.02526,-4.76546 -12.62397,-5.1405 -2e-5,0 -3e-5,0 -4e-5,0 -2.56836,0.72381 -5.27682,0.94784 -7.9292,0.65587 -10e-6,0 -2e-5,0 -4e-5,0 -3.77599,-0.41566 -7.46992,-1.91446 -10.28756,-4.46235 -10e-6,-1e-5 -2e-5,-1e-5 -2e-5,-2e-5 -2.8168,-2.54715 -4.70691,-6.17422 -4.91006,-9.96645 -0.14723,-2.74836 0.56276,-5.4692 1.41517,-8.08617 0.85243,-2.61706 1.85748,-5.20104 2.33283,-7.91207 0.92354,-5.26723 -0.28222,-10.88387 -3.28625,-15.30794 -3.00404,-4.42407 -7.77987,-7.61656 -13.01633,-8.70101 -3.38923,0.38773 -6.89239,-0.26847 -9.91151,-1.8566 -2e-5,-1e-5 -4e-5,-2e-5 -7e-5,-3e-5 -3.23617,-1.70233 -5.90142,-4.47336 -7.47657,-7.7733 -1.57515,-3.29994 -2.05353,-7.11482 -1.34194,-10.70152 0,-2e-5 1e-5,-5e-5 1e-5,-7e-5 0.98555,-6.30654 2.75458,-12.49035 5.25348,-18.36396 1e-5,-2e-5 2e-5,-5e-5 3e-5,-7e-5 2.90825,-6.83578 6.89834,-13.35821 12.56261,-18.16464 5.66117,-4.8038 13.16594,-7.75245 20.54108,-6.89651 4.32392,0.50183 8.42733,2.25397 12.75051,2.76214 4.7583,0.55932 9.69143,-0.45462 13.8434,-2.84533 2e-5,-2e-5 4e-5,-3e-5 6e-5,-4e-5 9.24006,1.13358 17.98407,5.97778 23.8453,13.21033 5.15234,6.35781 7.99577,14.2147 11.30601,21.69872 1.92466,4.3514 4.05797,8.66096 7.03333,12.37393 10e-6,2e-5 3e-5,4e-5 5e-5,6e-5 2.97478,3.71223 6.87266,6.82357 11.43539,8.16948 2e-5,1e-5 5e-5,1e-5 7e-5,2e-5 4.08278,1.20432 8.59203,0.91743 12.48927,-0.79459 2.77058,2.06261 4.93246,4.93513 6.1476,8.16838 10e-6,2e-5 2e-5,4e-5 2e-5,6e-5 1.21514,3.23328 1.48028,6.81866 0.75396,10.19551 -0.64549,3.00105 -2.03848,5.78453 -2.94997,8.71576 -0.45574,1.4656 -0.79214,2.97858 -0.84237,4.51258 -0.0502,1.5339 0.19468,3.09454 0.85538,4.47976 1.12213,2.35266 3.31808,4.00019 4.78859,6.15235 10e-6,2e-5 3e-5,4e-5 4e-5,6e-5 1.28491,1.88055 1.99273,4.15109 2.00406,6.42866 0,2e-5 0,5e-5 0,7e-5 0.0113,2.27755 -0.67387,4.55499 -1.94,6.44821 -1.26613,1.89323 -3.10926,3.39632 -5.21849,4.25572 -2.10924,0.8594 -4.47799,1.07243 -6.70672,0.60317 -6.72013,2.08 -13.07673,5.33027 -18.69744,9.56041 -3.43389,2.58434 -6.63757,5.58482 -8.83155,9.28034 -2.19309,3.69404 -3.30672,8.16333 -2.4015,12.36288 0.73825,3.42496 2.77646,6.49085 5.39143,8.82264 2.61545,2.33222 5.78751,3.97275 9.08008,5.17224 2e-5,1e-5 5e-5,2e-5 7e-5,3e-5 7.59964,2.76856 16.01971,3.25052 23.88562,1.3672 2e-5,-10e-6 4e-5,-3e-5 6e-5,-4e-5 5.55583,-4.2436 9.26683,-10.83973 10.0094,-17.79128 0.48273,-4.51901 -0.25456,-9.16391 -2.11291,-13.31132 -1.12772,-3.87126 -0.64207,-8.19191 1.31693,-11.71621 1.95901,-3.5243 5.37216,-6.21769 9.25535,-7.3036 3.03411,-0.84847 6.23896,-0.7413 9.38918,-0.78414 3.15001,-0.0428 6.40369,-0.26967 9.21028,-1.70056 1.87052,-0.95365 3.46254,-2.41445 4.68173,-4.12379 1.21923,-1.70942 2.07411,-3.66326 2.63108,-5.68772 0,-2e-5 10e-6,-4e-5 2e-5,-7e-5 1.11392,-4.04896 1.04531,-8.32057 0.84497,-12.51519 0,-2e-5 0,-5e-5 0,-7e-5 -0.20277,-4.24553 -0.53208,-8.48502 -0.98732,-12.71094 -1.04658,-3.18409 -3.10978,-6.02749 -5.8122,-8.01008 -2.70242,-1.9826 -6.03405,-3.09704 -9.38546,-3.13947 -1.77072,-0.0224 -3.53043,0.24491 -5.29437,0.40133 -1.76389,0.15642 -3.56824,0.19871 -5.27791,-0.26261 -1.52465,-0.4114 -2.93141,-1.21815 -4.11285,-2.26602 -2e-5,-2e-5 -3e-5,-3e-5 -5e-5,-5e-5 -1.1815,-1.04794 -2.14182,-2.33315 -2.88667,-3.72574 -1.48968,-2.78513 -2.11051,-5.95234 -2.4471,-9.09286 0,-2e-5 -10e-6,-5e-5 -10e-6,-7e-5 -0.7501,-6.99887 -0.1865,-14.13231 -1.52514,-21.0428 -0.72945,-3.76565 -2.0464,-7.46897 -4.28746,-10.58183 -2.2404,-3.11195 -5.46685,-5.60479 -9.18911,-6.5259 -3.02141,-0.74768 -6.20154,-0.44617 -9.27072,0.0716 -3.06933,0.51775 -6.11978,1.24879 -9.23079,1.35113 -2e-5,0 -5e-5,0 -7e-5,0 -3.90344,0.1284 -7.81108,-0.74979 -11.38322,-2.32877 -3.5723,-1.57904 -6.81761,-3.84706 -9.69109,-6.49241 -5.74696,-5.29072 -9.96674,-12.00296 -13.94631,-18.72474 -2.39922,-4.05246 -4.71299,-8.17874 -6.40846,-12.57238 -1.69522,-4.39298 -2.67881,-9.02583 -3.50306,-13.661852 l -1.9823,-11.149545" + id="path2938" + inkscape:path-effect="#path-effect2940;#path-effect2942" + inkscape:original-d="m 407.86585,83.916245 c 0,0 -14.11559,27.469705 -24.4484,38.695485 -9.34236,10.14972 -20.62893,24.18364 -33.66651,28.69118 -10.61846,3.67116 -11.93657,-7.91708 -19.88069,0.0278 -8.03966,8.04037 -7.9913,25.39502 -14.47923,34.7326 0,0 -7.13271,14.26573 -13.21535,19.01981 -8.72576,6.81989 -26.98503,4.24108 -24.14685,14.94595 2.83816,10.70488 4.57641,21.84782 15.56452,28.59021 9.79125,6.00799 28.36077,4.86263 29.30237,-6.5863 0.94161,-11.44892 3.2096,-17.00295 7.03985,-25.85581 3.83025,-8.85286 -1.10893,-26.61597 4.61772,-20.27603 0,0 11.6923,-3.64141 14.03941,4.57324 1.70869,5.98028 2.66345,21.33932 4.86161,27.15752 2.19816,5.81821 -0.52766,12.44562 -1.06029,16.14671 -1.09286,7.59409 -3.21008,13.10136 -10.73556,14.59527 0,0 -15.16484,1.49219 -21.24253,6.47532 -6.22299,5.10225 -7.51576,8.72253 -6.11019,16.64609 1.81705,10.24319 9.04679,20.97753 19.26022,22.95493 11.49367,2.22528 19.58074,2.59049 25.43574,-7.54732 4.1679,-7.21663 -1.97686,-19.09584 2.41448,-26.17873 0,0 0.33183,-12.5434 6.17549,-15.79603 3.2717,-1.82105 9.2379,-3.16852 11.23305,0 0,0 11.52539,9.6056 12.42398,15.74053 0.95363,6.51078 -5.98915,11.79446 -2.14557,17.13547 3.84359,5.34102 7.61186,11.46161 14.47158,14.59527 8.85083,4.04326 19.94604,4.31564 24.04886,-4.50773 0,0 8.1669,-13.23439 6.24082,-22.43781 -2.16604,-10.34997 -9.48077,-17.46228 -20.01897,-16.59061 0,0 -5.42758,1.53646 -7.9292,0.65587 -6.58909,-2.31941 -16.02955,-7.49314 -15.19768,-14.42882 0.83187,-6.93568 9.55833,8.44447 3.748,-15.99824 -1.55478,-6.54061 -9.59437,-24.45283 -16.30258,-24.00895 0,0 -6.96155,-0.35298 -9.91151,-1.8566 -7.36557,-3.75427 -10.83778,-10.45812 -8.81857,-18.47492 0,0 1.87298,-13.03292 5.25348,-18.36396 7.93496,-12.51342 19.58924,-22.07695 33.10372,-25.06122 4.24644,-0.93771 6.93062,3.3283 12.75051,2.76214 5.10303,-0.49642 9.84185,-6.05074 13.84346,-2.84537 0,0 16.88165,-1.28992 23.8453,13.21033 3.31247,6.89749 4.71066,17.81941 11.30601,21.69872 6.59535,3.87931 11.60217,19.87279 18.46884,20.54349 3.94867,0.38568 10.25015,-4.06981 12.48927,-0.79459 0,0 6.35327,10.96916 6.90158,18.36395 0.48511,6.54257 -6.59488,12.262 -2.93696,17.7081 3.65793,5.44611 4.68796,1.4131 4.78863,6.15241 0.15241,7.17408 -4.7607,16.6994 -11.86115,17.73583 0,0 -12.53135,5.17234 -18.69744,9.56041 -6.62245,4.71284 -15.87104,14.96813 -11.23305,21.64322 0,0 7.82042,10.07549 14.47158,13.99491 7.43886,4.38361 19.41887,8.75645 23.88562,1.3672 0,0 8.90884,-10.20704 10.00946,-17.79132 0.87615,-6.0375 -5.07693,-7.979 -2.11291,-13.31132 0,0 4.26218,-15.44258 10.57228,-19.01981 5.94288,-3.36906 15.32144,3.50888 18.59946,-2.4847 0,0 7.61918,-13.6222 8.1578,-22.32684 0.40659,-6.57079 4.32078,-8.81675 -0.98732,-12.71094 0,0 -9.00115,-10.11082 -15.19766,-11.14955 -3.63896,-0.61001 -8.14088,2.91403 -10.57228,0.13872 0,0 -8.10433,-8.53592 -9.44667,-15.08467 -1.56983,-7.65869 4.02354,-15.53542 -1.52515,-21.04287 -5.54869,-5.50744 -5.14034,-14.65591 -13.47657,-17.10773 -6.04893,-1.77908 -13.54572,5.32072 -18.50151,1.42268 -4.95579,-3.89803 -26.23756,-15.56939 -35.02069,-27.54592 -5.52823,-7.53822 -8.27517,-17.03053 -9.91152,-26.234232 l -1.9823,-11.149545" + sodipodi:nodetypes="cssssszszzsszsssssssssszssssszsssssassszssszssssssssssssssszszssc" + inkscape:connector-curvature="0" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,471.08015,79.546314)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-9" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,543.12457,23.323419)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-2" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,434.63417,132.94394)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-95" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,471.36269,185.49397)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-3" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,505.831,131.81383)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-27" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,542.55952,186.62408)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-31" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,614.32141,78.133679)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-8" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,649.91982,131.24877)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-5" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,613.1913,185.49398)" /> + </g> +</svg>
diff --git a/docs/reference/glib/Sorted_binary_tree_preorder.svg b/docs/reference/glib/Sorted_binary_tree_preorder.svg new file mode 100644 index 0000000..ae3d22c --- /dev/null +++ b/docs/reference/glib/Sorted_binary_tree_preorder.svg
@@ -0,0 +1,750 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="265.90625" + height="226.94397" + id="svg3953" + version="1.1" + inkscape:version="0.48.4 r9939" + sodipodi:docname="Sorted_binary_tree_preorder.svg"> + <defs + id="defs3955"> + <marker + inkscape:stockid="SquareL" + orient="auto" + refY="0" + refX="0" + id="SquareL" + style="overflow:visible"> + <path + id="path4940" + d="M -5,-5 -5,5 5,5 5,-5 -5,-5 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="scale(0.8,0.8)" + inkscape:connector-curvature="0" /> + </marker> + <marker + style="overflow:visible" + id="DistanceStart" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="DistanceStart"> + <g + id="g2300"> + <path + style="fill:none;stroke:#ffffff;stroke-width:1.14999998;stroke-linecap:square" + d="M 0,0 2,0" + id="path2306" + inkscape:connector-curvature="0" /> + <path + style="fill:#000000;fill-rule:evenodd;stroke:none" + d="M 0,0 13,4 9,0 13,-4 0,0 z" + id="path2302" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square" + d="M 0,-4 0,40" + id="path2304" + inkscape:connector-curvature="0" /> + </g> + </marker> + <marker + inkscape:stockid="DotL" + orient="auto" + refY="0" + refX="0" + id="DotL" + style="overflow:visible"> + <path + id="path4931" + d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none" + transform="matrix(0.8,0,0,0.8,5.92,0.8)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow2Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow2Lend" + style="overflow:visible"> + <path + id="path4890" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + id="path4869" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="matrix(0.8,0,0,0.8,10,0)" + inkscape:connector-curvature="0" /> + </marker> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective3961" /> + <inkscape:perspective + id="perspective3971" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:path-effect + effect="spiro" + id="path-effect2940" + is_visible="true" /> + <inkscape:path-effect + effect="skeletal" + id="path-effect2942" + is_visible="true" + pattern="m 187.18135,13.365063 1,0" + copytype="single_stretched" + prop_scale="1" + scale_y_rel="false" + spacing="0" + normal_offset="0" + tang_offset="0" + prop_units="false" + vertical_pattern="false" + fuse_tolerance="0" /> + <inkscape:perspective + id="perspective4212" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-5" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-76" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-2" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-22" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4744-8" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4852" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective5886" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-4" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-1" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-3" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-11" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-74" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-79" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-9" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective6303-6" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.98775168" + inkscape:cx="303.24736" + inkscape:cy="-18.949243" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1366" + inkscape:window-height="702" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata3958"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-275.65625,-78.774784)"> + <g + transform="matrix(0.9925764,0,0,0.9925764,278.52645,98.594058)" + id="graph0" + class="graph" + style="font-size:14px;font-family:Times-Roman"> + <title + id="title5">sorted_binary_tree</title> + <g + id="node1" + class="node"> + <title + id="title8">C</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="185" + sodipodi:cx="60" + d="m 78,185 c 0,9.94113 -8.058875,18 -18,18 -9.941125,0 -18,-8.05887 -18,-18 0,-9.94113 8.058875,-18 18,-18 9.941125,0 18,8.05887 18,18 z" + cx="60" + cy="185" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse10" /> + <text + style="text-anchor:middle" + x="60" + y="190" + id="text12">C</text> + </g> + <g + id="node2" + class="node"> + <title + id="title15">E</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="185" + sodipodi:cx="132" + d="m 150,185 c 0,9.94113 -8.05887,18 -18,18 -9.94113,0 -18,-8.05887 -18,-18 0,-9.94113 8.05887,-18 18,-18 9.94113,0 18,8.05887 18,18 z" + cx="132" + cy="185" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse17" /> + <text + style="text-anchor:middle" + x="132" + y="190" + id="text19">E</text> + </g> + <g + id="node3" + class="node"> + <title + id="title22">H</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="185" + sodipodi:cx="204" + d="m 221,185 c 0,9.94113 -7.61116,18 -17,18 -9.38884,0 -17,-8.05887 -17,-18 0,-9.94113 7.61116,-18 17,-18 9.38884,0 17,8.05887 17,18 z" + cx="204" + cy="185" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse24" /> + <text + style="text-anchor:middle" + x="204" + y="190" + id="text26">H</text> + </g> + <g + id="node4" + class="node"> + <title + id="title29">A</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="131" + sodipodi:cx="24" + d="m 41,131 c 0,9.94113 -7.611159,18 -17,18 -9.388841,0 -17,-8.05887 -17,-18 0,-9.94113 7.611159,-18 17,-18 9.388841,0 17,8.05887 17,18 z" + cx="24" + cy="131" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse31" /> + <text + style="text-anchor:middle" + x="24" + y="136" + id="text33">A</text> + </g> + <g + id="node5" + class="node"> + <title + id="title36">D</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="131" + sodipodi:cx="96" + d="m 113,131 c 0,9.94113 -7.61116,18 -17,18 -9.388841,0 -17,-8.05887 -17,-18 0,-9.94113 7.611159,-18 17,-18 9.38884,0 17,8.05887 17,18 z" + cx="96" + cy="131" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse38" /> + <text + style="text-anchor:middle" + x="96" + y="136" + id="text40">D</text> + </g> + <g + id="edge6" + class="edge"> + <title + id="title43">D->C</title> + <path + style="fill:none;stroke:#000000" + d="m 86,147 c -3,4 -7,9 -10,14" + id="path45" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="78,164 70,170 73,160 78,164 " + id="polygon47" /> + </g> + <g + id="edge8" + class="edge"> + <title + id="title50">D->E</title> + <path + style="fill:none;stroke:#000000" + d="m 106,147 c 3,4 7,9 10,14" + id="path52" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="119,160 122,170 114,164 119,160 " + id="polygon54" /> + </g> + <g + id="node6" + class="node"> + <title + id="title57">I</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="131" + sodipodi:cx="240" + d="m 258,131 c 0,9.94113 -8.05887,18 -18,18 -9.94113,0 -18,-8.05887 -18,-18 0,-9.94113 8.05887,-18 18,-18 9.94113,0 18,8.05887 18,18 z" + cx="240" + cy="131" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse59" /> + <text + style="text-anchor:middle" + x="240" + y="136" + id="text61">I</text> + </g> + <g + id="edge12" + class="edge"> + <title + id="title64">I->H</title> + <path + style="fill:none;stroke:#000000" + d="m 230,146 c -3,5 -6,10 -10,15" + id="path66" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="223,163 214,169 217,159 223,163 " + id="polygon68" /> + </g> + <g + id="node7" + class="node"> + <title + id="title71">B</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="77" + sodipodi:cx="60" + d="m 78,77 c 0,9.941125 -8.058875,18 -18,18 -9.941125,0 -18,-8.058875 -18,-18 0,-9.941125 8.058875,-18 18,-18 9.941125,0 18,8.058875 18,18 z" + cx="60" + cy="77" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse73" /> + <text + style="text-anchor:middle" + x="60" + y="82" + id="text75">B</text> + </g> + <g + id="edge3" + class="edge"> + <title + id="title78">B->A</title> + <path + style="fill:none;stroke:#000000" + d="m 50,92 c -3,5 -6,10 -10,15" + id="path80" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="43,109 34,115 37,105 43,109 " + id="polygon82" /> + </g> + <g + id="edge5" + class="edge"> + <title + id="title85">B->D</title> + <path + style="fill:none;stroke:#000000" + d="m 70,92 c 3,5 6,10 10,15" + id="path87" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="83,105 86,115 77,109 83,105 " + id="polygon89" /> + </g> + <g + id="node8" + class="node"> + <title + id="title92">G</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="17" + sodipodi:cy="77" + sodipodi:cx="204" + d="m 221,77 c 0,9.941125 -7.61116,18 -17,18 -9.38884,0 -17,-8.058875 -17,-18 0,-9.941125 7.61116,-18 17,-18 9.38884,0 17,8.058875 17,18 z" + cx="204" + cy="77" + rx="17" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse94" /> + <text + style="text-anchor:middle" + x="204" + y="82" + id="text96">G</text> + </g> + <g + id="edge11" + class="edge"> + <title + id="title99">G->I</title> + <path + style="fill:none;stroke:#000000" + d="m 214,93 c 3,4 7,9 10,14" + id="path101" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="227,106 230,116 222,110 227,106 " + id="polygon103" /> + </g> + <g + id="node9" + class="node"> + <title + id="title106">F</title> + <ellipse + sodipodi:ry="18" + sodipodi:rx="18" + sodipodi:cy="23" + sodipodi:cx="132" + d="m 150,23 c 0,9.941125 -8.05887,18 -18,18 -9.94113,0 -18,-8.058875 -18,-18 0,-9.941125 8.05887,-18 18,-18 9.94113,0 18,8.058875 18,18 z" + cx="132" + cy="23" + rx="18" + ry="18" + style="fill:#ffffff;stroke:#000000" + id="ellipse108" /> + <text + style="text-anchor:middle" + x="132" + y="28" + id="text110">F</text> + </g> + <g + id="edge2" + class="edge"> + <title + id="title113">F->B</title> + <path + style="fill:none;stroke:#000000" + d="M 117,34 C 106,42 94,51 83,60" + id="path115" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="85,63 75,66 81,57 85,63 " + id="polygon117" /> + </g> + <g + id="edge10" + class="edge"> + <title + id="title120">F->G</title> + <path + style="fill:none;stroke:#000000" + d="m 147,34 c 11,8 23,17 34,26" + id="path122" + inkscape:connector-curvature="0" /> + <polygon + style="fill:#000000;stroke:#000000" + points="183,57 189,66 179,63 183,57 " + id="polygon124" /> + </g> + </g> + <path + style="fill:none;stroke:#000000;stroke-width:0.82904756;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3.31619022, 3.31619022;stroke-dashoffset:0;marker-start:url(#SquareL);marker-end:url(#Arrow2Lend)" + d="m 407.86585,83.916245 c -8.09235,12.934463 -16.24193,25.833125 -24.4484,38.695485 -4.10893,6.44009 -8.28,12.93078 -13.72464,18.28932 -5.44312,5.35704 -12.35084,9.56414 -19.94187,10.40186 -3.3055,0.36478 -6.64352,0.0886 -9.9615,-0.13591 -1e-5,0 -3e-5,0 -4e-5,0 -3.30753,-0.22377 -6.65223,-0.39935 -9.91915,0.16371 -3.67892,0.63407 -7.19225,2.2113 -10.11083,4.53904 -10e-6,1e-5 -2e-5,2e-5 -3e-5,2e-5 -2.91857,2.32774 -5.23772,5.40225 -6.67417,8.84797 -1.43645,3.44574 -1.98788,7.25719 -1.58695,10.96875 0.40093,3.71157 1.75359,7.31733 3.89275,10.37682 -1.57329,7.77579 -6.47676,14.83297 -13.21535,19.01981 -4.08578,2.53859 -8.72148,4.0255 -13.0897,6.03963 -2e-5,0 -3e-5,1e-5 -4e-5,2e-5 -4.36719,2.01365 -8.65699,4.73894 -11.05709,8.90627 -10e-6,1e-5 -10e-6,2e-5 -2e-5,3e-5 -1.54971,2.69079 -2.21037,5.86275 -2.00701,8.96123 0.20338,3.09874 1.25331,6.121 2.89275,8.75838 3.2781,5.27351 8.79594,8.88365 14.67878,10.8706 10e-6,0 2e-5,1e-5 4e-5,1e-5 5.05172,1.70623 10.53116,2.32159 15.76564,1.30607 1e-5,-1e-5 2e-5,-1e-5 3e-5,-1e-5 5.23327,-1.0153 10.20383,-3.73183 13.53666,-7.89237 2.8325,-3.53596 4.39168,-7.94004 5.28933,-12.38079 0,-1e-5 10e-6,-3e-5 10e-6,-4e-5 0.89772,-4.44111 1.18109,-8.97997 1.75051,-13.47498 0.87253,-6.88777 2.42162,-13.6897 4.61772,-20.27603 2.52197,-0.49612 5.17081,-0.33611 7.61472,0.45997 2.44389,0.79608 4.67875,2.2269 6.42464,4.11322 2e-5,1e-5 3e-5,3e-5 5e-5,5e-5 3.21102,3.46934 4.63062,8.27318 5.04051,12.98264 0.41,4.71077 -0.0852,9.44723 -0.1789,14.17488 -0.10721,5.4079 0.30156,10.912 -1.06029,16.14671 -1.55704,5.98502 -5.48588,11.32637 -10.73556,14.59527 -3.77605,-0.86428 -7.77873,-0.72238 -11.48409,0.40712 -3.70537,1.1295 -7.10659,3.24452 -9.75844,6.0682 -4.15358,4.42272 -6.37982,10.5847 -6.11019,16.64605 0,2e-5 0,3e-5 0,4e-5 0.23758,5.34073 2.36859,10.56193 5.83809,14.62917 10e-6,10e-6 2e-5,2e-5 3e-5,3e-5 3.46975,4.06752 8.24802,6.97932 13.4221,8.32573 4.51162,1.17403 9.34056,1.17129 13.82052,-0.11828 4.47975,-1.2895 8.59635,-3.87695 11.61522,-7.42904 3.02242,-3.55627 4.91711,-8.06019 5.34575,-12.70759 10e-6,-3e-5 10e-6,-5e-5 10e-6,-8e-5 0.42864,-4.64742 -0.61029,-9.42195 -2.93128,-13.47106 -1.10365,-2.89524 -1.08961,-6.20429 0.0386,-9.09005 0,-10e-6 1e-5,-3e-5 1e-5,-4e-5 1.1282,-2.88577 3.36222,-5.32694 6.1369,-6.70594 3.47162,-1.72538 7.76143,-1.72538 11.23305,0 3.47935,0.88812 6.65089,2.94914 8.87568,5.76782 2.22478,2.81869 3.49269,6.38223 3.5483,9.97271 0.0448,2.88989 -0.66677,5.7303 -1.2997,8.55039 -0.63291,2.82001 -1.19432,5.71596 -0.84587,8.58504 0,2e-5 0,3e-5 0,4e-5 0.43816,3.60767 2.33339,6.96423 4.97344,9.46172 2.64067,2.49807 5.99201,4.1741 9.49814,5.13355 10e-6,0 2e-5,1e-5 4e-5,1e-5 8.13425,2.22592 17.27288,0.51296 24.04882,-4.50774 2.95407,-2.80833 5.12951,-6.42944 6.22172,-10.35631 1.09222,-3.92687 1.09889,-8.15119 0.0191,-12.0815 -1.22234,-4.44914 -3.84239,-8.50594 -7.39496,-11.45011 -3.55256,-2.94417 -8.02526,-4.76546 -12.62397,-5.1405 -2e-5,0 -3e-5,0 -4e-5,0 -2.56836,0.72381 -5.27682,0.94784 -7.9292,0.65587 -10e-6,0 -2e-5,0 -4e-5,0 -3.77599,-0.41566 -7.46992,-1.91446 -10.28756,-4.46235 -10e-6,-1e-5 -2e-5,-1e-5 -2e-5,-2e-5 -2.8168,-2.54715 -4.70691,-6.17422 -4.91006,-9.96645 -0.14723,-2.74836 0.56276,-5.4692 1.41517,-8.08617 0.85243,-2.61706 1.85748,-5.20104 2.33283,-7.91207 0.92354,-5.26723 -0.28222,-10.88387 -3.28625,-15.30794 -3.00404,-4.42407 -7.77987,-7.61656 -13.01633,-8.70101 -3.38923,0.38773 -6.89239,-0.26847 -9.91151,-1.8566 -2e-5,-1e-5 -4e-5,-2e-5 -7e-5,-3e-5 -3.23617,-1.70233 -5.90142,-4.47336 -7.47657,-7.7733 -1.57515,-3.29994 -2.05353,-7.11482 -1.34194,-10.70152 0,-2e-5 1e-5,-5e-5 1e-5,-7e-5 0.98555,-6.30654 2.75458,-12.49035 5.25348,-18.36396 1e-5,-2e-5 2e-5,-5e-5 3e-5,-7e-5 2.90825,-6.83578 6.89834,-13.35821 12.56261,-18.16464 5.66117,-4.8038 13.16594,-7.75245 20.54108,-6.89651 4.32392,0.50183 8.42733,2.25397 12.75051,2.76214 4.7583,0.55932 9.69143,-0.45462 13.8434,-2.84533 2e-5,-2e-5 4e-5,-3e-5 6e-5,-4e-5 9.24006,1.13358 17.98407,5.97778 23.8453,13.21033 5.15234,6.35781 7.99577,14.2147 11.30601,21.69872 1.92466,4.3514 4.05797,8.66096 7.03333,12.37393 10e-6,2e-5 3e-5,4e-5 5e-5,6e-5 2.97478,3.71223 6.87266,6.82357 11.43539,8.16948 2e-5,1e-5 5e-5,1e-5 7e-5,2e-5 4.08278,1.20432 8.59203,0.91743 12.48927,-0.79459 2.77058,2.06261 4.93246,4.93513 6.1476,8.16838 10e-6,2e-5 2e-5,4e-5 2e-5,6e-5 1.21514,3.23328 1.48028,6.81866 0.75396,10.19551 -0.64549,3.00105 -2.03848,5.78453 -2.94997,8.71576 -0.45574,1.4656 -0.79214,2.97858 -0.84237,4.51258 -0.0502,1.5339 0.19468,3.09454 0.85538,4.47976 1.12213,2.35266 3.31808,4.00019 4.78859,6.15235 10e-6,2e-5 3e-5,4e-5 4e-5,6e-5 1.28491,1.88055 1.99273,4.15109 2.00406,6.42866 0,2e-5 0,5e-5 0,7e-5 0.0113,2.27755 -0.67387,4.55499 -1.94,6.44821 -1.26613,1.89323 -3.10926,3.39632 -5.21849,4.25572 -2.10924,0.8594 -4.47799,1.07243 -6.70672,0.60317 -6.72013,2.08 -13.07673,5.33027 -18.69744,9.56041 -3.43389,2.58434 -6.63757,5.58482 -8.83155,9.28034 -2.19309,3.69404 -3.30672,8.16333 -2.4015,12.36288 0.73825,3.42496 2.77646,6.49085 5.39143,8.82264 2.61545,2.33222 5.78751,3.97275 9.08008,5.17224 2e-5,1e-5 5e-5,2e-5 7e-5,3e-5 7.59964,2.76856 16.01971,3.25052 23.88562,1.3672 2e-5,-10e-6 4e-5,-3e-5 6e-5,-4e-5 5.55583,-4.2436 9.26683,-10.83973 10.0094,-17.79128 0.48273,-4.51901 -0.25456,-9.16391 -2.11291,-13.31132 -1.12772,-3.87126 -0.64207,-8.19191 1.31693,-11.71621 1.95901,-3.5243 5.37216,-6.21769 9.25535,-7.3036 3.03411,-0.84847 6.23896,-0.7413 9.38918,-0.78414 3.15001,-0.0428 6.40369,-0.26967 9.21028,-1.70056 1.87052,-0.95365 3.46254,-2.41445 4.68173,-4.12379 1.21923,-1.70942 2.07411,-3.66326 2.63108,-5.68772 0,-2e-5 10e-6,-4e-5 2e-5,-7e-5 1.11392,-4.04896 1.04531,-8.32057 0.84497,-12.51519 0,-2e-5 0,-5e-5 0,-7e-5 -0.20277,-4.24553 -0.53208,-8.48502 -0.98732,-12.71094 -1.04658,-3.18409 -3.10978,-6.02749 -5.8122,-8.01008 -2.70242,-1.9826 -6.03405,-3.09704 -9.38546,-3.13947 -1.77072,-0.0224 -3.53043,0.24491 -5.29437,0.40133 -1.76389,0.15642 -3.56824,0.19871 -5.27791,-0.26261 -1.52465,-0.4114 -2.93141,-1.21815 -4.11285,-2.26602 -2e-5,-2e-5 -3e-5,-3e-5 -5e-5,-5e-5 -1.1815,-1.04794 -2.14182,-2.33315 -2.88667,-3.72574 -1.48968,-2.78513 -2.11051,-5.95234 -2.4471,-9.09286 0,-2e-5 -10e-6,-5e-5 -10e-6,-7e-5 -0.7501,-6.99887 -0.1865,-14.13231 -1.52514,-21.0428 -0.72945,-3.76565 -2.0464,-7.46897 -4.28746,-10.58183 -2.2404,-3.11195 -5.46685,-5.60479 -9.18911,-6.5259 -3.02141,-0.74768 -6.20154,-0.44617 -9.27072,0.0716 -3.06933,0.51775 -6.11978,1.24879 -9.23079,1.35113 -2e-5,0 -5e-5,0 -7e-5,0 -3.90344,0.1284 -7.81108,-0.74979 -11.38322,-2.32877 -3.5723,-1.57904 -6.81761,-3.84706 -9.69109,-6.49241 -5.74696,-5.29072 -9.96674,-12.00296 -13.94631,-18.72474 -2.39922,-4.05246 -4.71299,-8.17874 -6.40846,-12.57238 -1.69522,-4.39298 -2.67881,-9.02583 -3.50306,-13.661852 l -1.9823,-11.149545" + id="path2938" + inkscape:path-effect="#path-effect2940;#path-effect2942" + inkscape:original-d="m 407.86585,83.916245 c 0,0 -14.11559,27.469705 -24.4484,38.695485 -9.34236,10.14972 -20.62893,24.18364 -33.66651,28.69118 -10.61846,3.67116 -11.93657,-7.91708 -19.88069,0.0278 -8.03966,8.04037 -7.9913,25.39502 -14.47923,34.7326 0,0 -7.13271,14.26573 -13.21535,19.01981 -8.72576,6.81989 -26.98503,4.24108 -24.14685,14.94595 2.83816,10.70488 4.57641,21.84782 15.56452,28.59021 9.79125,6.00799 28.36077,4.86263 29.30237,-6.5863 0.94161,-11.44892 3.2096,-17.00295 7.03985,-25.85581 3.83025,-8.85286 -1.10893,-26.61597 4.61772,-20.27603 0,0 11.6923,-3.64141 14.03941,4.57324 1.70869,5.98028 2.66345,21.33932 4.86161,27.15752 2.19816,5.81821 -0.52766,12.44562 -1.06029,16.14671 -1.09286,7.59409 -3.21008,13.10136 -10.73556,14.59527 0,0 -15.16484,1.49219 -21.24253,6.47532 -6.22299,5.10225 -7.51576,8.72253 -6.11019,16.64609 1.81705,10.24319 9.04679,20.97753 19.26022,22.95493 11.49367,2.22528 19.58074,2.59049 25.43574,-7.54732 4.1679,-7.21663 -1.97686,-19.09584 2.41448,-26.17873 0,0 0.33183,-12.5434 6.17549,-15.79603 3.2717,-1.82105 9.2379,-3.16852 11.23305,0 0,0 11.52539,9.6056 12.42398,15.74053 0.95363,6.51078 -5.98915,11.79446 -2.14557,17.13547 3.84359,5.34102 7.61186,11.46161 14.47158,14.59527 8.85083,4.04326 19.94604,4.31564 24.04886,-4.50773 0,0 8.1669,-13.23439 6.24082,-22.43781 -2.16604,-10.34997 -9.48077,-17.46228 -20.01897,-16.59061 0,0 -5.42758,1.53646 -7.9292,0.65587 -6.58909,-2.31941 -16.02955,-7.49314 -15.19768,-14.42882 0.83187,-6.93568 9.55833,8.44447 3.748,-15.99824 -1.55478,-6.54061 -9.59437,-24.45283 -16.30258,-24.00895 0,0 -6.96155,-0.35298 -9.91151,-1.8566 -7.36557,-3.75427 -10.83778,-10.45812 -8.81857,-18.47492 0,0 1.87298,-13.03292 5.25348,-18.36396 7.93496,-12.51342 19.58924,-22.07695 33.10372,-25.06122 4.24644,-0.93771 6.93062,3.3283 12.75051,2.76214 5.10303,-0.49642 9.84185,-6.05074 13.84346,-2.84537 0,0 16.88165,-1.28992 23.8453,13.21033 3.31247,6.89749 4.71066,17.81941 11.30601,21.69872 6.59535,3.87931 11.60217,19.87279 18.46884,20.54349 3.94867,0.38568 10.25015,-4.06981 12.48927,-0.79459 0,0 6.35327,10.96916 6.90158,18.36395 0.48511,6.54257 -6.59488,12.262 -2.93696,17.7081 3.65793,5.44611 4.68796,1.4131 4.78863,6.15241 0.15241,7.17408 -4.7607,16.6994 -11.86115,17.73583 0,0 -12.53135,5.17234 -18.69744,9.56041 -6.62245,4.71284 -15.87104,14.96813 -11.23305,21.64322 0,0 7.82042,10.07549 14.47158,13.99491 7.43886,4.38361 19.41887,8.75645 23.88562,1.3672 0,0 8.90884,-10.20704 10.00946,-17.79132 0.87615,-6.0375 -5.07693,-7.979 -2.11291,-13.31132 0,0 4.26218,-15.44258 10.57228,-19.01981 5.94288,-3.36906 15.32144,3.50888 18.59946,-2.4847 0,0 7.61918,-13.6222 8.1578,-22.32684 0.40659,-6.57079 4.32078,-8.81675 -0.98732,-12.71094 0,0 -9.00115,-10.11082 -15.19766,-11.14955 -3.63896,-0.61001 -8.14088,2.91403 -10.57228,0.13872 0,0 -8.10433,-8.53592 -9.44667,-15.08467 -1.56983,-7.65869 4.02354,-15.53542 -1.52515,-21.04287 -5.54869,-5.50744 -5.14034,-14.65591 -13.47657,-17.10773 -6.04893,-1.77908 -13.54572,5.32072 -18.50151,1.42268 -4.95579,-3.89803 -26.23756,-15.56939 -35.02069,-27.54592 -5.52823,-7.53822 -8.27517,-17.03053 -9.91152,-26.234232 l -1.9823,-11.149545" + sodipodi:nodetypes="cssssszszzsszsssssssssszssssszsssssassszssszssssssssssssssszszssc" + inkscape:connector-curvature="0" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,436.04679,77.286097)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-9" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,509.22132,21.628256)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-2" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,402.42607,130.68372)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-95" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,435.76428,185.49397)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-3" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,473.62291,131.24878)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-27" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,508.09122,184.36387)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-31" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,580.41815,77.003571)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-8" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,616.01657,130.11867)" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.04799998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="path5876-5" + sodipodi:cx="-146.78572" + sodipodi:cy="122.70478" + sodipodi:rx="5.3571429" + sodipodi:ry="5.3571429" + d="m -141.42858,122.70478 c 0,2.95867 -2.39847,5.35714 -5.35714,5.35714 -2.95867,0 -5.35714,-2.39847 -5.35714,-5.35714 0,-2.95867 2.39847,-5.35714 5.35714,-5.35714 2.95867,0 5.35714,2.39847 5.35714,5.35714 z" + transform="matrix(0.79107591,0,0,0.79107591,580.41815,185.49398)" /> + </g> +</svg>
diff --git a/docs/reference/glib/building.xml b/docs/reference/glib/building.xml new file mode 100644 index 0000000..720a6ff --- /dev/null +++ b/docs/reference/glib/building.xml
@@ -0,0 +1,401 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<refentry id="glib-building"> + <refmeta> + <refentrytitle>Compiling the GLib package</refentrytitle> + <manvolnum>3</manvolnum> + <refmiscinfo>GLib Library</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>Compiling the GLib Package</refname> + <refpurpose>How to compile GLib itself</refpurpose> + </refnamediv> + + <refsect1 id="building"> + <title>Building the Library on UNIX</title> + <para> + On UNIX, GLib uses the standard <application>Meson</application> build + system. The normal sequence for compiling and installing the GLib library + is thus: + + <literallayout> + <userinput>meson _build</userinput> + <userinput>ninja -C _build</userinput> + <userinput>ninja -C _build install</userinput> + </literallayout> + + On FreeBSD: + <literallayout> + <userinput>env CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib -Wl,--disable-new-dtags" meson -Dxattr=false -Dinstalled_tests=true -Diconv=external -Db_lundef=false _build</userinput> + <userinput>ninja -C _build</userinput> + </literallayout> + </para> + + <para> + The standard options provided by <application>Meson</application> may be + passed to the <command>meson</command> command. Please see the + <application>Meson</application> documentation or run + <command>meson configure --help</command> for information about + the standard options. + </para> + <para> + GLib is compiled with + <ulink url="https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fstrict-aliasing">strict aliasing</ulink> + disabled. It is strongly recommended that this is not re-enabled by + overriding the compiler flags, as GLib has not been tested with strict + aliasing and cannot be guaranteed to work. + </para> + <para> + The GTK+ documentation contains + <ulink url="https://developer.gnome.org/gtk3/stable/gtk-building.html">further details</ulink> + about the build process and ways to influence it. + </para> + </refsect1> + <refsect1 id="dependencies"> + <title>Dependencies</title> + <para> + Before you can compile the GLib library, you need to have + various other tools and libraries installed on your system. + If you are building from a release archive, you will need + <ulink url="https://wiki.gnome.org/Projects/GLib/CompilerRequirements">a compliant C toolchain</ulink>, + <application>Meson</application>, and <application>pkg-config</application>; + the requirements are the same when building from a Git repository clone + of GLib. + </para> + <itemizedlist> + <listitem> + <para> + <ulink url="https://www.freedesktop.org/wiki/Software/pkg-config/">pkg-config</ulink> + is a tool for tracking the compilation flags needed for + libraries that are used by the GLib library. (For each + library, a small <literal>.pc</literal> text file is + installed in a standard location that contains the compilation + flags needed for that library along with version number + information). + </para> + </listitem> + </itemizedlist> + <para> + A UNIX build of GLib requires that the system implements at + least the original 1990 version of POSIX. Beyond this, it + depends on a number of other libraries. + </para> + <itemizedlist> + <listitem> + <para> + The <ulink url="http://www.gnu.org/software/libiconv/">GNU + libiconv library</ulink> is needed to build GLib if your + system doesn't have the <function>iconv()</function> + function for doing conversion between character + encodings. Most modern systems should have + <function>iconv()</function>, however many older systems lack + an <function>iconv()</function> implementation. On such systems, + you must install the libiconv library. This can be found at: + <ulink url="http://www.gnu.org/software/libiconv">http://www.gnu.org/software/libiconv</ulink>. + </para> + <para> + If your system has an <function>iconv()</function> implementation but + you want to use libiconv instead, you can pass the + <option>-Diconv=gnu</option> option to <command>meson</command>. This + forces libiconv to be used. + </para> + <para> + Note that if you have libiconv installed in your default include + search path (for instance, in <filename>/usr/local/</filename>), but + don't enable it, you will get an error while compiling GLib because + the <filename>iconv.h</filename> that libiconv installs hides the + system iconv. + </para> + <para> + If you are using the native iconv implementation on Solaris + instead of libiconv, you'll need to make sure that you have + the converters between locale encodings and UTF-8 installed. + At a minimum you'll need the SUNWuiu8 package. You probably + should also install the SUNWciu8, SUNWhiu8, SUNWjiu8, and + SUNWkiu8 packages. + </para> + <para> + The native iconv on Compaq Tru64 doesn't contain support for + UTF-8, so you'll need to use GNU libiconv instead. (When + using GNU libiconv for GLib, you'll need to use GNU libiconv + for GNU gettext as well.) This probably applies to related + operating systems as well. + </para> + </listitem> + <listitem> + <para> + Python 3.5 or newer is required. Your system Python must + conform to <ulink + url="https://www.python.org/dev/peps/pep-0394/">PEP 394 + </ulink> + For FreeBSD, this means that the + <literal>lang/python3</literal> port must be installed. + </para> + </listitem> + <listitem> + <para> + The libintl library from the <ulink + url="http://www.gnu.org/software/gettext">GNU gettext + package</ulink> is needed if your system doesn't have the + <function>gettext()</function> functionality for handling + message translation databases. + </para> + </listitem> + <listitem> + <para> + A thread implementation is needed. The thread support in GLib + can be based upon POSIX threads or win32 threads. + </para> + </listitem> + <listitem> + <para> + GRegex uses the <ulink url="http://www.pcre.org/">PCRE library</ulink> + for regular expression matching. The default is to use the system + version of PCRE, to reduce the chances of security fixes going out + of sync. GLib additionally provides an internal copy of PCRE in case + the system version is too old, or does not support UTF-8; the internal + copy is patched to use GLib for memory management and to share the + same Unicode tables. + </para> + </listitem> + <listitem> + <para> + The optional extended attribute support in GIO requires the + <function>getxattr()</function> family of functions that may be + provided by the C library or by the standalone libattr library. To + build GLib without extended attribute support, use the + <option>-Dxattr=false</option> option. + </para> + </listitem> + <listitem> + <para> + The optional SELinux support in GIO requires libselinux. + To build GLib without SELinux support, use the + <option>-Dselinux=disabled</option> option. + </para> + </listitem> + <listitem> + <para> + The optional support for DTrace requires the + <filename>sys/sdt.h</filename> header, which is provided + by SystemTap on Linux. To build GLib without DTrace, use + the <option>-Ddtrace=false</option> option. + </para> + </listitem> + <listitem> + <para> + The optional support for + <ulink url="http://sourceware.org/systemtap/">SystemTap</ulink> + can be disabled with the <option>-Dsystemtap=false</option> + option. Additionally, you can control the location + where GLib installs the SystemTap probes, using the + <option>-Dtapset_install_dir=DIR</option> option. + </para> + </listitem> + </itemizedlist> + + </refsect1> + <refsect1 id="extra-configuration-options"> + <title>Extra Configuration Options</title> + + <para> + In addition to the normal options, these additional ones are supported + when configuring the GLib library: + </para> + + <formalpara> + <title><option>--buildtype</option></title> + + <para> + This is a standard <application>Meson</application> option which + specifies how much debugging and optimization to enable. If the build + type starts with <literal>debug</literal>, + <literal>G_ENABLE_DEBUG</literal> will be defined and GLib will be built + with additional debug code enabled. + </para> + </formalpara> + + <formalpara> + <title><option>-Dforce_posix_threads=true</option></title> + + <para> + Normally, <application>Meson</application> should be able to work out + the correct thread implementation to use. This option forces POSIX + threads to be used even if the platform provides another threading API + (for example, on Windows). + </para> + </formalpara> + + <formalpara> + <title><option>-Dinternal_pcre=true</option></title> + + <para> + Normally, GLib will be configured to use the system-supplied PCRE + library if it is suitable, falling back to an internal version + otherwise. If this option is specified, the internal version will always + be used. + </para> + <para> + Using the internal PCRE is the preferred solution if: + <itemizedlist> + <listitem> + <para> + your system has strict resource constraints; the system-supplied + PCRE has a separated copy of the tables used for Unicode + handling, whereas the internal copy shares the Unicode tables + used by GLib. + </para> + </listitem> + <listitem> + <para> + your system has PCRE built without some needed features, + such as UTF-8 and Unicode support. + </para> + </listitem> + <listitem> + <para> + you are planning to use both GRegex and PCRE API at the same + time, either directly or indirectly through a dependency; PCRE + uses some global variables for memory management and + other features, and if both GLib and PCRE try to access them + at the same time, this could lead to undefined behavior. + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + <formalpara> + <title><option>-Dbsymbolic_functions=false</option> and + <option>-Dbsymbolic_functions=true</option></title> + + <para> + By default, GLib uses the <option>-Bsymbolic-functions</option> + linker flag to avoid intra-library PLT jumps. A side-effect + of this is that it is no longer possible to override + internal uses of GLib functions with + <envar>LD_PRELOAD</envar>. Therefore, it may make + sense to turn this feature off in some situations. + The <option>-Dbsymbolic_functions=false</option> option allows + to do that. + </para> + </formalpara> + + <formalpara> + <title><option>-Dgtk_doc=false</option> and + <option>-Dgtk_doc=true</option></title> + + <para> + By default, GLib will detect whether the + <application>gtk-doc</application> package is installed. + If it is, then it will use it to extract and build the + documentation for the GLib library. These options + can be used to explicitly control whether + <application>gtk-doc</application> should be + used or not. If it is not used, the distributed, + pre-generated HTML files will be installed instead of + building them on your machine. + </para> + </formalpara> + + <formalpara> + <title><option>-Dman=false</option> and + <option>-Dman=true</option></title> + + <para> + By default, GLib will detect whether <application>xsltproc</application> + and the necessary DocBook stylesheets are installed. + If they are, then it will use them to rebuild the included + man pages from the XML sources. These options can be used + to explicitly control whether man pages should be rebuilt + used or not. The distribution includes pre-generated man + pages. + </para> + </formalpara> + + <formalpara> + <title><option>-Dxattr=false</option> and + <option>-Dxattr=true</option></title> + + <para> + By default, GLib will detect whether the + <function>getxattr()</function> + family of functions is available. If it is, then extended + attribute support will be included in GIO. These options can + be used to explicitly control whether extended attribute + support should be included or not. <function>getxattr()</function> + and friends can be provided by glibc or by the standalone + libattr library. + </para> + </formalpara> + + <formalpara> + <title><option>-Dselinux=auto</option>, + <option>-Dselinux=enabled</option> or + <option>-Dselinux=disabled</option></title> + + <para> + By default, GLib will detect if libselinux is available and + include SELinux support in GIO if it is. These options can be + used to explicitly control whether SELinux support should + be included. + </para> + </formalpara> + + <formalpara> + <title><option>-Ddtrace=false</option> and + <option>-Ddtrace=true</option></title> + + <para> + By default, GLib will detect if DTrace support is available, and use it. + These options can be used to explicitly control whether DTrace support + is compiled into GLib. + </para> + </formalpara> + + <formalpara> + <title><option>-Dsystemtap=false</option> and + <option>-Dsystemtap=true</option></title> + + <para> + This option requires DTrace support. If it is available, then + GLib will also check for the presence of SystemTap. + </para> + </formalpara> + + <formalpara> + <title><option>-Db_coverage=true</option> and + <option>-Db_coverage=false</option></title> + + <para> + Enable the generation of coverage reports for the GLib tests. + This requires the lcov frontend to gcov from the + <ulink url="http://ltp.sourceforge.net">Linux Test Project</ulink>. + To generate a coverage report, use + <command>ninja coverage-html</command>. The report is placed in the + <filename>meson-logs</filename> directory. + </para> + </formalpara> + + <formalpara> + <title><option>-Druntime_libdir=RELPATH</option></title> + + <para> + Allows specifying a relative path to where to install the runtime + libraries (meaning library files used for running, not developing, + GLib applications). This can be used in operating system setups where + programs using GLib needs to run before e.g. <filename>/usr</filename> + is mounted. + For example, if <varname>LIBDIR</varname> is <filename>/usr/lib</filename> and + <filename>../../lib</filename> is passed to + <option>-Druntime_libdir</option> then the + runtime libraries are installed into <filename>/lib</filename> rather + than <filename>/usr/lib</filename>. + </para> + </formalpara> + </refsect1> + +</refentry>
diff --git a/docs/reference/glib/changes.xml b/docs/reference/glib/changes.xml new file mode 100644 index 0000000..9b4aa74 --- /dev/null +++ b/docs/reference/glib/changes.xml
@@ -0,0 +1,174 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<refentry id="glib-changes" revision="17 Jan 2002"> +<refmeta> +<refentrytitle>Changes to GLib</refentrytitle> +<manvolnum>3</manvolnum> +<refmiscinfo>Changes to GLib</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>Changes to GLib</refname> +<refpurpose> +Incompatible changes made between successive versions of GLib +</refpurpose> +</refnamediv> + + +<refsect1> +<title>Incompatible changes from 2.0 to 2.2</title> + +<itemizedlist> + +<listitem> +<para> +GLib changed the seeding algorithm for the pseudo-random number +generator Mersenne Twister, as used by <structname>GRand</structname> +and <structname>GRandom</structname>. This was necessary, because some +seeds would yield very bad pseudo-random streams. Also the +pseudo-random integers generated by +<function>g_rand*_int_range()</function> will have a +slightly better equal distribution with the new version of GLib. +</para> + +<para> +Further information can be found at the website of the Mersenne +Twister random number generator at <ulink +url="http://www.math.keio.ac.jp/~matumoto/emt.html">http://www.math.keio.ac.jp/~matumoto/emt.html</ulink>. +</para> + +<para> +The original seeding and generation algorithms, as found in GLib +2.0.x, can be used instead of the new ones by setting the environment +variable <envar>G_RANDOM_VERSION</envar> to the value of '2.0'. Use +the GLib-2.0 algorithms only if you have sequences of numbers generated +with Glib-2.0 that you need to reproduce exactly. +</para> + +</listitem> + +</itemizedlist> + +</refsect1> + +<refsect1> +<title>Incompatible changes from 1.2 to 2.0</title> + +<itemizedlist> + +<listitem> +<para> +The event loop functionality <structname>GMain</structname> has extensively +been revised to support multiple separate main loops in separate threads. +All sources (timeouts, idle functions, etc.) are associated with a +<structname>GMainContext</structname>. +</para> + +<para> +Compatibility functions exist so that most application code dealing with +the main loop will continue to work. However, code that creates new custom +types of sources will require modification. +</para> + +<para> +The main changes here are: + + <itemizedlist> + + <listitem> + <para> + Sources are now exposed as <type>GSource *</type>, rather than simply as + numeric ids. + </para> + </listitem> + + <listitem> + <para> + New types of sources are created by structure "derivation" from + <structname>GSource</structname>, so the <literal>source_data</literal> + parameter to the <structname>GSource</structname> virtual functions has been + replaced with a <type>GSource *</type>. + </para> + </listitem> + + <listitem> + <para> + Sources are first created, then later added to a specific + <structname>GMainContext</structname>. + </para> + </listitem> + + <listitem> + <para> + Dispatching has been modified so both the callback and data are passed + in to the <function>dispatch()</function> virtual function. + </para> + </listitem> + + </itemizedlist> + To go along with this change, the vtable for + <structname>GIOChannel</structname> has changed and + <function>add_watch()</function> has been replaced by + <function>create_watch()</function>. +</para> +</listitem> + +<listitem> +<para> +<function>g_list_foreach()</function> and +<function>g_slist_foreach()</function> have been changed so they +are now safe against removal of the current item, not the next item. +</para> + +<para> +It's not recommended to mutate the list in the callback to these +functions in any case. +</para> +</listitem> + +<listitem> +<para> +<structname>GDate</structname> now works in UTF-8, not in the current locale. +If you want to use it with the encoding of the locale, you need to convert +strings using <function>g_locale_to_utf8()</function> first. +</para> +</listitem> + +<listitem> +<para> +<function>g_strsplit()</function> has been fixed to: + + <itemizedlist> + <listitem> + <para> + include trailing empty tokens, rather than stripping them + </para> + </listitem> + <listitem> + <para> + split into a maximum of <literal>max_tokens</literal> tokens, rather + than <literal>max_tokens + 1</literal> + </para> + </listitem> + </itemizedlist> + + Code depending on either of these bugs will need to be fixed. +</para> +</listitem> + +<listitem> +<para> +Deprecated functions that got removed: +<function>g_set_error_handler()</function>, +<function>g_set_warning_handler()</function>, +<function>g_set_message_handler()</function>, use +<function>g_log_set_handler()</function> instead. +</para> +</listitem> +</itemizedlist> + +</refsect1> + +</refentry>
diff --git a/docs/reference/glib/compiling.xml b/docs/reference/glib/compiling.xml new file mode 100644 index 0000000..02971a6 --- /dev/null +++ b/docs/reference/glib/compiling.xml
@@ -0,0 +1,125 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<refentry id="glib-compiling" revision="17 Jan 2002"> +<refmeta> +<refentrytitle>Compiling GLib Applications</refentrytitle> +<manvolnum>3</manvolnum> +<refmiscinfo>GLib Library</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>Compiling GLib Applications</refname> +<refpurpose> +How to compile your GLib application +</refpurpose> +</refnamediv> + +<refsect1> +<title>Compiling GLib Applications on UNIX</title> + +<para> +To compile a GLib application, you need to tell the compiler where to +find the GLib header files and libraries. This is done with the +<application>pkg-config</application> utility. +</para> +<para> +The following interactive shell session demonstrates how +<application>pkg-config</application> is used (the actual output on +your system may be different): +<programlisting> +$ pkg-config --cflags glib-2.0 + -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include +$ pkg-config --libs glib-2.0 + -L/usr/lib -lm -lglib-2.0 +</programlisting> +</para> +<para> +See the <ulink url="http://www.freedesktop.org/wiki/Software/pkg-config">pkg-config website</ulink> +for more information about <application>pkg-config</application>. +</para> +<para> +If your application uses or <structname>GObject</structname> +features, it must be compiled and linked with the options returned +by the following <application>pkg-config</application> invocation: +<programlisting> +$ pkg-config --cflags --libs gobject-2.0 +</programlisting> +</para> +<para> +If your application uses modules, it must be compiled and linked +with the options returned by one of the following +<application>pkg-config</application> invocations: +<programlisting> +$ pkg-config --cflags --libs gmodule-no-export-2.0 +$ pkg-config --cflags --libs gmodule-2.0 +</programlisting> +The difference between the two is that gmodule-2.0 adds +<option>--export-dynamic</option> to the linker flags, +which is often not needed. +</para> +<para> +The simplest way to compile a program is to use the "backticks" +feature of the shell. If you enclose a command in backticks +(<emphasis>not single quotes</emphasis>), then its output will +be substituted into the command line before execution. So to +compile a GLib Hello, World, you would type the following: +<programlisting> +$ cc hello.c `pkg-config --cflags --libs glib-2.0` -o hello +</programlisting> +</para> +<note><para> +Note that the name of the file must come before the other options +(such as <emphasis>pkg-config</emphasis>), or else you may get an +error from the linker. +</para></note> + +<para> +Deprecated GLib functions are annotated to make the compiler +emit warnings when they are used (e.g. with gcc, you need to use +the -Wdeprecated-declarations option). If these warnings are +problematic, they can be turned off by defining the preprocessor +symbol %GLIB_DISABLE_DEPRECATION_WARNINGS by using the commandline +option <literal>-DGLIB_DISABLE_DEPRECATION_WARNINGS</literal> +</para> + +<para> +GLib deprecation annotations are versioned; by defining the +macros %GLIB_VERSION_MIN_REQUIRED and %GLIB_VERSION_MAX_ALLOWED, +you can specify the range of GLib versions whose API you want +to use. APIs that were deprecated before or introduced after +this range will trigger compiler warnings. +</para> + +<para> +Since GLib 2.62, the older deprecation mechanism of hiding deprecated interfaces +entirely from the compiler by using the preprocessor symbol +<literal>G_DISABLE_DEPRECATED</literal> has been removed. All deprecations +are now handled using the above mechanism. +</para> + +<para> +The recommended way of using GLib has always been to only include the +toplevel headers <filename>glib.h</filename>, +<filename>glib-object.h</filename>, <filename>gio.h</filename>. +Starting with 2.32, GLib enforces this by generating an error +when individual headers are directly included. +</para> + +<para> +Still, there are some exceptions; these headers have to be included +separately: +<filename>gmodule.h</filename>, +<filename>glib-unix.h</filename>, +<filename>glib/gi18n-lib.h</filename> or +<filename>glib/gi18n.h</filename> (see +the <link linkend="glib-I18N">Internationalization section</link>), +<filename>glib/gprintf.h</filename> and +<filename>glib/gstdio.h</filename> +(we don't want to pull in all of stdio). +</para> + +</refsect1> + +</refentry>
diff --git a/docs/reference/glib/cross.xml b/docs/reference/glib/cross.xml new file mode 100644 index 0000000..c90b30b --- /dev/null +++ b/docs/reference/glib/cross.xml
@@ -0,0 +1,147 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<refentry id="glib-cross-compiling" revision="7 Aug 2018"> +<refmeta> +<refentrytitle>Cross-compiling the GLib package</refentrytitle> +<manvolnum>3</manvolnum> +<refmiscinfo>GLib Library</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>Cross-compiling the GLib Package</refname> +<refpurpose> +How to cross-compile GLib +</refpurpose> +</refnamediv> + + <refsect1 id="cross"> + <title>Building the Library for a different architecture</title> + <para> + Cross-compilation is the process of compiling a program or + library on a different architecture or operating system then + it will be run upon. GLib is slightly more difficult to + cross-compile than many packages because much of GLib is + about hiding differences between different systems. + </para> + <para> + These notes cover things specific to cross-compiling GLib; + for general information about cross-compilation, see the + <ulink url="http://mesonbuild.com/Cross-compilation.html">meson</ulink> + info pages. + </para> + <para> + GLib tries to detect as much information as possible about + the target system by compiling and linking programs without + actually running anything; however, some information GLib + needs is not available this way. This information needs + to be provided to meson via a ‘cross file’. + </para> + <para> + As an example of using a cross file, to cross compile for + the ‘MingW32’ Win64 runtime environment on a Linux system, + create a file <filename>cross_file.txt</filename> with the following + contents: + </para> + <programlisting> +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[properties] +c_args = [] +c_link_args = [] + +[binaries] +c = 'x86_64-w64-mingw32-gcc' +cpp = 'x86_64-w64-mingw32-g++' +ar = 'x86_64-w64-mingw32-ar' +ld = 'x86_64-w64-mingw32-ld' +objcopy = 'x86_64-w64-mingw32-objcopy' +strip = 'x86_64-w64-mingw32-strip' +pkgconfig = 'x86_64-w64-mingw32-pkg-config' +windres = 'x86_64-w64-mingw32-windres' + </programlisting> + <para> + Then execute the following commands: + </para> + <programlisting> +meson --cross-file cross_file.txt builddir + </programlisting> + <para> + The complete list of cross properties follows. Most + of these won't need to be set in most cases. + </para> + </refsect1> + <refsect1 id="cross-properties"> + <title>Cross properties</title> + <formalpara> + <title>have_[function]</title> + + <para> + When meson checks if a function is supported, the test can be + overridden by setting the + <literal>have_<replaceable>function</replaceable></literal> property + to <constant>true</constant> or <constant>false</constant>. + For example <programlisting>Checking for function "fsync" : YES</programlisting> + can be overridden by setting <programlisting>have_fsync = false</programlisting> + </para> + </formalpara> + <formalpara> + <title>growing_stack=[true/false]</title> + + <para> + Whether the stack grows up or down. Most places will want + <constant>false</constant>. + A few architectures, such as PA-RISC need <constant>true</constant>. + </para> + </formalpara> + <formalpara> + <title>have_strlcpy=[true/false]</title> + + <para> + Whether you have <function>strlcpy()</function> that matches + OpenBSD. Defaults to <constant>false</constant>, which is safe, + since GLib uses a built-in version in that case. + </para> + </formalpara> + <formalpara> + <title>va_val_copy=[true/false]</title> + + <para> + Whether <type>va_list</type> can be copied as a pointer. If set + to <constant>false</constant>, then <function>memcopy()</function> + will be used. Only matters if you don't have + <function>va_copy()</function> or <function>__va_copy()</function>. + (So, doesn't matter for GCC.) + Defaults to <constant>true</constant> which is slightly more common + than <constant>false</constant>. + </para> + </formalpara> + <formalpara> + <title>have_c99_vsnprintf=[true/false]</title> + + <para> + Whether you have a <function>vsnprintf()</function> with C99 + semantics. (C99 semantics means returning the number of bytes + that would have been written had the output buffer had enough + space.) Defaults to <constant>false</constant>. + </para> + </formalpara> + <formalpara> + <title>have_c99_snprintf=[true/false]</title> + + <para> + Whether you have a <function>snprintf()</function> with C99 + semantics. (C99 semantics means returning the number of bytes + that would have been written had the output buffer had enough + space.) Defaults to <constant>false</constant>. + </para> + </formalpara> + + </refsect1> + +</refentry>
diff --git a/docs/reference/glib/file-name-encodings.png b/docs/reference/glib/file-name-encodings.png new file mode 100644 index 0000000..7adbcea --- /dev/null +++ b/docs/reference/glib/file-name-encodings.png Binary files differ
diff --git a/docs/reference/glib/file-name-encodings.sxd b/docs/reference/glib/file-name-encodings.sxd new file mode 100644 index 0000000..46750dc --- /dev/null +++ b/docs/reference/glib/file-name-encodings.sxd Binary files differ
diff --git a/docs/reference/glib/glib-docs.xml b/docs/reference/glib/glib-docs.xml new file mode 100644 index 0000000..3ed1256 --- /dev/null +++ b/docs/reference/glib/glib-docs.xml
@@ -0,0 +1,290 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.5//EN' + 'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd' [ +<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'"> +<!ENTITY version SYSTEM "version.xml"> +]> +<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude"> + <bookinfo> + <title>GLib Reference Manual</title> + <releaseinfo> + for GLib &version; + The latest version of this documentation can be found on-line at + <ulink role="online-location" url="https://developer.gnome.org/glib/unstable/">https://developer.gnome.org/glib/unstable/</ulink>. + </releaseinfo> + </bookinfo> + + <chapter id="glib"> + <title>GLib Overview</title> + <para> + GLib is a general-purpose utility library, which provides many useful + data types, macros, type conversions, string utilities, file utilities, + a mainloop abstraction, and so on. It works on many UNIX-like platforms, + as well as Windows and OS X. GLib is released under the GNU Lesser + General Public License (GNU LGPL). + </para> + + <xi:include href="building.xml" /> + <xi:include href="cross.xml" /> + <xi:include href="programming.xml" /> + <xi:include href="xml/compiling.xml" /> + <xi:include href="running.xml" /> + <xi:include href="changes.xml" /> + <xi:include href="resources.xml" /> + + </chapter> + + <chapter id="glib-fundamentals"> + <title>GLib Fundamentals</title> + <xi:include href="xml/version.xml" /> + <xi:include href="xml/types.xml" /> + <xi:include href="xml/macros.xml" /> + <xi:include href="xml/type_conversion.xml" /> + <xi:include href="xml/byte_order.xml" /> + <xi:include href="xml/checkedmath.xml" /> + <xi:include href="xml/numerical.xml" /> + <xi:include href="xml/macros_misc.xml" /> + <xi:include href="xml/atomic_operations.xml" /> + </chapter> + + <chapter id="glib-core"> + <title>GLib Core Application Support</title> + <xi:include href="xml/main.xml" /> + <xi:include href="xml/threads.xml" /> + <xi:include href="xml/thread_pools.xml" /> + <xi:include href="xml/async_queues.xml" /> + <xi:include href="xml/modules.xml" /> + <xi:include href="xml/memory.xml" /> + <xi:include href="xml/memory_slices.xml" /> + <xi:include href="xml/iochannels.xml" /> + <xi:include href="xml/error_reporting.xml" /> + <xi:include href="xml/warnings.xml" /> + <xi:include href="xml/messages.xml" /> + </chapter> + + <chapter id="glib-utilities"> + <title>GLib Utilities</title> + <xi:include href="xml/string_utils.xml" /> + <xi:include href="xml/conversions.xml" /> + <xi:include href="xml/unicode.xml" /> + <xi:include href="xml/base64.xml" /> + <xi:include href="xml/checksum.xml" /> + <xi:include href="xml/hmac.xml" /> + <xi:include href="xml/i18n.xml" /> + <xi:include href="xml/date.xml" /> + <xi:include href="xml/timezone.xml" /> + <xi:include href="xml/date-time.xml" /> + <xi:include href="xml/random_numbers.xml" /> + <xi:include href="xml/hooks.xml" /> + <xi:include href="xml/misc_utils.xml" /> + <xi:include href="xml/scanner.xml" /> + <xi:include href="xml/timers.xml" /> + <xi:include href="xml/spawn.xml" /> + <xi:include href="xml/fileutils.xml" /> + <xi:include href="xml/gurifuncs.xml" /> + <xi:include href="xml/ghostutils.xml" /> + <xi:include href="xml/shell.xml" /> + <xi:include href="xml/option.xml" /> + <xi:include href="xml/patterns.xml" /> + <xi:include href="xml/gregex.xml" /> + <xi:include href="regex-syntax.xml" /> + <xi:include href="xml/markup.xml" /> + <xi:include href="xml/keyfile.xml" /> + <xi:include href="xml/bookmarkfile.xml" /> + <xi:include href="xml/testing.xml" /> + <xi:include href="xml/gunix.xml" /> + <xi:include href="xml/windows.xml" /> + <xi:include href="xml/uuid.xml" /> + </chapter> + + <chapter id="glib-data-types"> + <title>GLib Data Types</title> + <xi:include href="xml/linked_lists_double.xml" /> + <xi:include href="xml/linked_lists_single.xml" /> + <xi:include href="xml/queue.xml" /> + <xi:include href="xml/sequence.xml" /> + <xi:include href="xml/trash_stack.xml" /> + <xi:include href="xml/hash_tables.xml" /> + <xi:include href="xml/strings.xml" /> + <xi:include href="xml/string_chunks.xml" /> + <xi:include href="xml/arrays.xml" /> + <xi:include href="xml/arrays_pointer.xml" /> + <xi:include href="xml/arrays_byte.xml" /> + <xi:include href="xml/trees-binary.xml" /> + <xi:include href="xml/trees-nary.xml" /> + <xi:include href="xml/quarks.xml" /> + <xi:include href="xml/datalist.xml" /> + <xi:include href="xml/datasets.xml" /> + <xi:include href="xml/gvarianttype.xml"/> + <xi:include href="xml/gvariant.xml"/> + <xi:include href="gvariant-varargs.xml"/> + <xi:include href="gvariant-text.xml"/> + <xi:include href="xml/refcount.xml"/> + <xi:include href="xml/rcbox.xml"/> + <xi:include href="xml/arcbox.xml"/> + <xi:include href="xml/refstring.xml"/> + </chapter> + + <chapter id="deprecated"> + <title>Deprecated APIs</title> + <xi:include href="xml/threads-deprecated.xml"/> + <xi:include href="xml/caches.xml" /> + <xi:include href="xml/relations.xml" /> + <xi:include href="xml/completion.xml" /> + </chapter> + + <chapter id="tools"> + <title>GLib Tools</title> + <xi:include href="glib-gettextize.xml" /> + </chapter> + + <chapter id="deprecated-tools"> + <title>Deprecated Tools</title> + <xi:include href="gtester.xml" /> + <xi:include href="gtester-report.xml" /> + </chapter> + + <index id="api-index-full"> + <title>Index</title> + <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-deprecated" role="deprecated"> + <title>Index of deprecated symbols</title> + <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-2" role="2.2"> + <title>Index of new symbols in 2.2</title> + <xi:include href="xml/api-index-2.2.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-4" role="2.4"> + <title>Index of new symbols in 2.4</title> + <xi:include href="xml/api-index-2.4.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-6" role="2.6"> + <title>Index of new symbols in 2.6</title> + <xi:include href="xml/api-index-2.6.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-8" role="2.8"> + <title>Index of new symbols in 2.8</title> + <xi:include href="xml/api-index-2.8.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-10" role="2.10"> + <title>Index of new symbols in 2.10</title> + <xi:include href="xml/api-index-2.10.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-12" role="2.12"> + <title>Index of new symbols in 2.12</title> + <xi:include href="xml/api-index-2.12.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-14" role="2.14"> + <title>Index of new symbols in 2.14</title> + <xi:include href="xml/api-index-2.14.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-16" role="2.16"> + <title>Index of new symbols in 2.16</title> + <xi:include href="xml/api-index-2.16.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-18" role="2.18"> + <title>Index of new symbols in 2.18</title> + <xi:include href="xml/api-index-2.18.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-20" role="2.20"> + <title>Index of new symbols in 2.20</title> + <xi:include href="xml/api-index-2.20.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-22" role="2.22"> + <title>Index of new symbols in 2.22</title> + <xi:include href="xml/api-index-2.22.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-24" role="2.24"> + <title>Index of new symbols in 2.24</title> + <xi:include href="xml/api-index-2.24.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-26" role="2.26"> + <title>Index of new symbols in 2.26</title> + <xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-28" role="2.28"> + <title>Index of new symbols in 2.28</title> + <xi:include href="xml/api-index-2.28.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-30" role="2.30"> + <title>Index of new symbols in 2.30</title> + <xi:include href="xml/api-index-2.30.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-32" role="2.32"> + <title>Index of new symbols in 2.32</title> + <xi:include href="xml/api-index-2.32.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-34" role="2.34"> + <title>Index of new symbols in 2.34</title> + <xi:include href="xml/api-index-2.34.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-36" role="2.36"> + <title>Index of new symbols in 2.36</title> + <xi:include href="xml/api-index-2.36.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-38" role="2.38"> + <title>Index of new symbols in 2.38</title> + <xi:include href="xml/api-index-2.38.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-40" role="2.40"> + <title>Index of new symbols in 2.40</title> + <xi:include href="xml/api-index-2.40.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-42" role="2.42"> + <title>Index of new symbols in 2.42</title> + <xi:include href="xml/api-index-2.42.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-44" role="2.44"> + <title>Index of new symbols in 2.44</title> + <xi:include href="xml/api-index-2.44.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-46" role="2.46"> + <title>Index of new symbols in 2.46</title> + <xi:include href="xml/api-index-2.46.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-48" role="2.48"> + <title>Index of new symbols in 2.48</title> + <xi:include href="xml/api-index-2.48.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-50" role="2.50"> + <title>Index of new symbols in 2.50</title> + <xi:include href="xml/api-index-2.50.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-52" role="2.52"> + <title>Index of new symbols in 2.52</title> + <xi:include href="xml/api-index-2.52.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-54" role="2.54"> + <title>Index of new symbols in 2.54</title> + <xi:include href="xml/api-index-2.54.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-56" role="2.56"> + <title>Index of new symbols in 2.56</title> + <xi:include href="xml/api-index-2.56.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-58" role="2.58"> + <title>Index of new symbols in 2.58</title> + <xi:include href="xml/api-index-2.58.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-60" role="2.60"> + <title>Index of new symbols in 2.60</title> + <xi:include href="xml/api-index-2.60.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-62" role="2.62"> + <title>Index of new symbols in 2.62</title> + <xi:include href="xml/api-index-2.62.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-64" role="2.64"> + <title>Index of new symbols in 2.64</title> + <xi:include href="xml/api-index-2.64.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-66" role="2.66"> + <title>Index of new symbols in 2.66</title> + <xi:include href="xml/api-index-2.66.xml"><xi:fallback /></xi:include> + </index> + + <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> + +</book>
diff --git a/docs/reference/glib/glib-gettextize.xml b/docs/reference/glib/glib-gettextize.xml new file mode 100644 index 0000000..f016b28 --- /dev/null +++ b/docs/reference/glib/glib-gettextize.xml
@@ -0,0 +1,88 @@ +<refentry id="glib-gettextize" lang="en"> + +<refentryinfo> +<title>glib-gettextize</title> +<productname>GLib</productname> +<authorgroup> +<author> +<contrib>Developer</contrib> +<firstname>Owen</firstname> +<surname>Taylor</surname> +</author> +</authorgroup> +</refentryinfo> + +<refmeta> +<refentrytitle>glib-gettextize</refentrytitle> +<manvolnum>1</manvolnum> +<refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>glib-gettextize</refname> +<refpurpose>gettext internationalization utility</refpurpose> +</refnamediv> + +<refsynopsisdiv> +<cmdsynopsis> +<command>glib-gettextize</command> +<arg choice="opt" rep="repeat">OPTION</arg> +<arg choice="opt">DIRECTORY</arg> +</cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>glib-gettextize</command> helps to prepare a source package for being +internationalized through <application>gettext</application>. +It is a variant of the <command>gettextize</command> that ships with +<application>gettext</application>. +</para> + +<para><command>glib-gettextize</command> differs +from <command>gettextize</command> in that it doesn't create an +<filename>intl/</filename> subdirectory and doesn't modify +<filename>po/ChangeLog</filename> (note that newer versions of +<command>gettextize</command> behave like this when called with the +<option>--no-changelog</option> option). +</para> +</refsect1> + +<refsect1><title>Options</title> +<variablelist> + +<varlistentry> +<term><option>--help</option></term> +<listitem><para> +print help and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--version</option></term> +<listitem><para> +print version information and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-c</option>, <option>--copy</option></term> +<listitem><para> +copy files instead of making symlinks +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-f</option>, <option>--force</option></term> +<listitem><para> +force writing of new files even if old ones exist +</para></listitem> +</varlistentry> +</variablelist> +</refsect1> + +<refsect1><title>See also</title> +<para> +<citerefentry><refentrytitle>gettextize</refentrytitle><manvolnum>1</manvolnum></citerefentry> +</para> +</refsect1> +</refentry>
diff --git a/docs/reference/glib/glib-overrides.txt b/docs/reference/glib/glib-overrides.txt new file mode 100644 index 0000000..991fcf2 --- /dev/null +++ b/docs/reference/glib/glib-overrides.txt
@@ -0,0 +1,294 @@ +# This file makes most of the thread related macros look like +# functions, which they really were, if possible easy. + +<MACRO> +<NAME>GLIB_DISABLE_DEPRECATION_WARNINGS</NAME> +#ifdef GLIB_DISABLE_DEPRECATION_WARNINGS +</MACRO> + +<MACRO> +<NAME>G_ATOMIC_LOCK_FREE</NAME> +#define G_ATOMIC_LOCK_FREE +</MACRO> + +# default thread implementation + +<MACRO> +<NAME>G_THREADS_IMPL_POSIX</NAME> +#define G_THREADS_IMPL_POSIX +</MACRO> + +<MACRO> +<NAME>G_THREADS_IMPL_WIN32</NAME> +#define G_THREADS_IMPL_NONE +</MACRO> + +# threads supported? + +<FUNCTION> +<NAME>g_thread_supported</NAME> +<RETURNS>gboolean</RETURNS> +</FUNCTION> + +# GMutex + +<FUNCTION> +<NAME>g_mutex_new</NAME> +<RETURNS>GMutex *</RETURNS> +</FUNCTION> + +<FUNCTION> +<NAME>g_mutex_lock</NAME> +<RETURNS>void</RETURNS> +GMutex *mutex +</FUNCTION> + +<FUNCTION> +<NAME>g_mutex_trylock</NAME> +<RETURNS>gboolean</RETURNS> +GMutex *mutex +</FUNCTION> + +<FUNCTION> +<NAME>g_mutex_unlock</NAME> +<RETURNS>void</RETURNS> +GMutex *mutex +</FUNCTION> + +<FUNCTION> +<NAME>g_mutex_free</NAME> +<RETURNS>void</RETURNS> +GMutex *mutex +</FUNCTION> + +# GStaticMutex + +<STRUCT> +<NAME>GStaticMutex</NAME> +</STRUCT> + +<MACRO> +<NAME>G_STATIC_MUTEX_INIT</NAME> +#define G_STATIC_MUTEX_INIT +</MACRO> + +<FUNCTION> +<NAME>g_static_mutex_lock</NAME> +<RETURNS>void</RETURNS> +GStaticMutex* mutex +</FUNCTION> + +<FUNCTION> +<NAME>g_static_mutex_trylock</NAME> +<RETURNS>gboolean</RETURNS> +GStaticMutex* mutex +</FUNCTION> + +<FUNCTION> +<NAME>g_static_mutex_unlock</NAME> +<RETURNS>void</RETURNS> +GStaticMutex* mutex +</FUNCTION> + +<FUNCTION> +<NAME>g_static_mutex_get_mutex</NAME> +<RETURNS>GMutex *</RETURNS> +GStaticMutex* mutex +</FUNCTION> + +# GThread + +<FUNCTION> +<NAME>g_thread_yield</NAME> +<RETURNS>void</RETURNS> +</FUNCTION> + +<FUNCTION> +<NAME>g_thread_create</NAME> +<RETURNS>GThread *</RETURNS> +GThreadFunc func +gpointer data, +gboolean joinable, +GError **error +</FUNCTION> + +# G_LOCK_* macros + +<MACRO> +<NAME>G_LOCK_DEFINE</NAME> +#define G_LOCK_DEFINE(name) +</MACRO> + +<MACRO> +<NAME>G_LOCK_DEFINE_STATIC</NAME> +#define G_LOCK_DEFINE_STATIC(name) +</MACRO> + +<MACRO> +<NAME>G_LOCK_EXTERN</NAME> +#define G_LOCK_EXTERN(name) +</MACRO> + +<MACRO> +<NAME>G_LOCK</NAME> +#define G_LOCK(name) +</MACRO> + +<MACRO> +<NAME>G_UNLOCK</NAME> +#define G_UNLOCK(name) +</MACRO> + +<MACRO> +<NAME>G_TRYLOCK</NAME> +#define G_TRYLOCK(name) +</MACRO> + +# GCond + +<FUNCTION> +<NAME>g_cond_new</NAME> +<RETURNS>GCond*</RETURNS> +</FUNCTION> + +<FUNCTION> +<NAME>g_cond_signal</NAME> +<RETURNS>void</RETURNS> +GCond *cond +</FUNCTION> + +<FUNCTION> +<NAME>g_cond_broadcast</NAME> +<RETURNS>void</RETURNS> +GCond *cond +</FUNCTION> + +<FUNCTION> +<NAME>g_cond_wait</NAME> +<RETURNS>void</RETURNS> +GCond *cond, GMutex *mutex +</FUNCTION> + +<FUNCTION> +<NAME>g_cond_timed_wait</NAME> +<RETURNS>gboolean</RETURNS> +GCond *cond, GMutex *mutex, GTimeVal *abs_time +</FUNCTION> + +<FUNCTION> +<NAME>g_cond_free</NAME> +<RETURNS>void</RETURNS> +GCond *cond +</FUNCTION> + +# GPrivate +<MACRO> +<NAME>G_PRIVATE_INIT</NAME> +#define G_PRIVATE_INIT(notify) +</MACRO> + +# GStaticPrivate + +<MACRO> +<NAME>G_STATIC_PRIVATE_INIT</NAME> +#define G_STATIC_PRIVATE_INIT +</MACRO> + +# Definitions for different operating systems + +<MACRO> +<NAME>G_OS_UNIX</NAME> +#define G_OS_UNIX +</MACRO> + +<MACRO> +<NAME>G_OS_WIN32</NAME> +#define G_OS_WIN32 +</MACRO> + +# g_ascii_isxxx + +<FUNCTION> +<NAME>g_ascii_isalnum</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_isalpha</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_iscntrl</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_isdigit</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_isgraph</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_islower</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_isprint</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_ispunct</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_isspace</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_isupper</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +<FUNCTION> +<NAME>g_ascii_isxdigit</NAME> +<RETURNS>gboolean</RETURNS> +gchar c +</FUNCTION> + +# g_atomic + +<FUNCTION> +<NAME>g_atomic_int_inc</NAME> +<RETURNS>void</RETURNS> +gint *atomic +</FUNCTION> + +<FUNCTION> +<NAME>g_atomic_int_dec_and_test</NAME> +<RETURNS>gboolean</RETURNS> +gint *atomic +</FUNCTION> + +<MACRO> +<NAME>G_VA_COPY</NAME> +#define G_VA_COPY(ap1,ap2) +</MACRO>
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt new file mode 100644 index 0000000..eed38b7 --- /dev/null +++ b/docs/reference/glib/glib-sections.txt
@@ -0,0 +1,3825 @@ +<INCLUDE>glib.h</INCLUDE> + +<SECTION> +<TITLE>Basic Types</TITLE> +<FILE>types</FILE> +gboolean +gpointer +gconstpointer +gchar +guchar + +<SUBSECTION> +gint +G_MININT +G_MAXINT +guint +G_MAXUINT +gshort +G_MINSHORT +G_MAXSHORT +gushort +G_MAXUSHORT +glong +G_MINLONG +G_MAXLONG +gulong +G_MAXULONG + +<SUBSECTION> +gint8 +G_MININT8 +G_MAXINT8 +guint8 +G_MAXUINT8 +gint16 +G_MININT16 +G_MAXINT16 +G_GINT16_MODIFIER +G_GINT16_FORMAT +guint16 +G_MAXUINT16 +G_GUINT16_FORMAT +gint32 +G_MININT32 +G_MAXINT32 +G_GINT32_MODIFIER +G_GINT32_FORMAT +guint32 +G_MAXUINT32 +G_GUINT32_FORMAT +gint64 +G_MININT64 +G_MAXINT64 +G_GINT64_MODIFIER +G_GINT64_FORMAT +G_GINT64_CONSTANT +guint64 +G_MAXUINT64 +G_GUINT64_FORMAT +G_GUINT64_CONSTANT + +<SUBSECTION> +gfloat +G_MINFLOAT +G_MAXFLOAT +gdouble +G_MINDOUBLE +G_MAXDOUBLE + +<SUBSECTION> +gsize +G_MAXSIZE +G_GSIZE_MODIFIER +G_GSIZE_FORMAT +gssize +G_MINSSIZE +G_MAXSSIZE +G_GSSIZE_MODIFIER +G_GSSIZE_FORMAT +goffset +G_MINOFFSET +G_MAXOFFSET +G_GOFFSET_MODIFIER +G_GOFFSET_FORMAT +G_GOFFSET_CONSTANT + +<SUBSECTION> +gintptr +G_GINTPTR_MODIFIER +G_GINTPTR_FORMAT +guintptr +G_GUINTPTR_FORMAT + +<SUBSECTION Private> +GLIB_SIZEOF_SSIZE_T +GLIB_SIZEOF_VOID_P +GLIB_SIZEOF_LONG +GLIB_SIZEOF_SIZE_T +G_HAVE_GINT64 +</SECTION> + +<SECTION> +<TITLE>Version Information</TITLE> +<FILE>version</FILE> +glib_major_version +glib_minor_version +glib_micro_version +glib_binary_age +glib_interface_age +glib_check_version + +<SUBSECTION> +GLIB_MAJOR_VERSION +GLIB_MINOR_VERSION +GLIB_MICRO_VERSION +GLIB_CHECK_VERSION + +<SUBSECTION> +GLIB_VERSION_2_26 +GLIB_VERSION_2_28 +GLIB_VERSION_2_30 +GLIB_VERSION_2_32 +GLIB_VERSION_2_34 +GLIB_VERSION_2_36 +GLIB_VERSION_2_38 +GLIB_VERSION_2_40 +GLIB_VERSION_2_42 +GLIB_VERSION_2_44 +GLIB_VERSION_2_46 +GLIB_VERSION_2_48 +GLIB_VERSION_2_50 +GLIB_VERSION_2_52 +GLIB_VERSION_2_54 +GLIB_VERSION_2_56 +GLIB_VERSION_2_58 +GLIB_VERSION_2_60 +GLIB_VERSION_2_62 +GLIB_VERSION_2_64 +GLIB_VERSION_2_66 +GLIB_VERSION_MIN_REQUIRED +GLIB_VERSION_MAX_ALLOWED +GLIB_DISABLE_DEPRECATION_WARNINGS + +<SUBSECTION Private> +G_ENCODE_VERSION +GLIB_AVAILABLE_ENUMERATOR_IN_2_26 +GLIB_AVAILABLE_ENUMERATOR_IN_2_28 +GLIB_AVAILABLE_ENUMERATOR_IN_2_30 +GLIB_AVAILABLE_ENUMERATOR_IN_2_32 +GLIB_AVAILABLE_ENUMERATOR_IN_2_34 +GLIB_AVAILABLE_ENUMERATOR_IN_2_36 +GLIB_AVAILABLE_ENUMERATOR_IN_2_38 +GLIB_AVAILABLE_ENUMERATOR_IN_2_40 +GLIB_AVAILABLE_ENUMERATOR_IN_2_42 +GLIB_AVAILABLE_ENUMERATOR_IN_2_44 +GLIB_AVAILABLE_ENUMERATOR_IN_2_46 +GLIB_AVAILABLE_ENUMERATOR_IN_2_48 +GLIB_AVAILABLE_ENUMERATOR_IN_2_50 +GLIB_AVAILABLE_ENUMERATOR_IN_2_52 +GLIB_AVAILABLE_ENUMERATOR_IN_2_54 +GLIB_AVAILABLE_ENUMERATOR_IN_2_56 +GLIB_AVAILABLE_ENUMERATOR_IN_2_58 +GLIB_AVAILABLE_ENUMERATOR_IN_2_60 +GLIB_AVAILABLE_ENUMERATOR_IN_2_62 +GLIB_AVAILABLE_ENUMERATOR_IN_2_64 +GLIB_AVAILABLE_ENUMERATOR_IN_2_66 +GLIB_AVAILABLE_IN_ALL +GLIB_AVAILABLE_IN_2_26 +GLIB_AVAILABLE_IN_2_28 +GLIB_AVAILABLE_IN_2_30 +GLIB_AVAILABLE_IN_2_32 +GLIB_AVAILABLE_IN_2_34 +GLIB_AVAILABLE_IN_2_36 +GLIB_AVAILABLE_IN_2_38 +GLIB_AVAILABLE_IN_2_40 +GLIB_AVAILABLE_IN_2_42 +GLIB_AVAILABLE_IN_2_44 +GLIB_AVAILABLE_IN_2_46 +GLIB_AVAILABLE_IN_2_48 +GLIB_AVAILABLE_IN_2_50 +GLIB_AVAILABLE_IN_2_52 +GLIB_AVAILABLE_IN_2_54 +GLIB_AVAILABLE_IN_2_56 +GLIB_AVAILABLE_IN_2_58 +GLIB_AVAILABLE_IN_2_60 +GLIB_AVAILABLE_IN_2_62 +GLIB_AVAILABLE_IN_2_64 +GLIB_AVAILABLE_IN_2_66 +GLIB_AVAILABLE_MACRO_IN_2_26 +GLIB_AVAILABLE_MACRO_IN_2_28 +GLIB_AVAILABLE_MACRO_IN_2_30 +GLIB_AVAILABLE_MACRO_IN_2_32 +GLIB_AVAILABLE_MACRO_IN_2_34 +GLIB_AVAILABLE_MACRO_IN_2_36 +GLIB_AVAILABLE_MACRO_IN_2_38 +GLIB_AVAILABLE_MACRO_IN_2_40 +GLIB_AVAILABLE_MACRO_IN_2_42 +GLIB_AVAILABLE_MACRO_IN_2_44 +GLIB_AVAILABLE_MACRO_IN_2_46 +GLIB_AVAILABLE_MACRO_IN_2_48 +GLIB_AVAILABLE_MACRO_IN_2_50 +GLIB_AVAILABLE_MACRO_IN_2_52 +GLIB_AVAILABLE_MACRO_IN_2_54 +GLIB_AVAILABLE_MACRO_IN_2_56 +GLIB_AVAILABLE_MACRO_IN_2_58 +GLIB_AVAILABLE_MACRO_IN_2_60 +GLIB_AVAILABLE_MACRO_IN_2_62 +GLIB_AVAILABLE_MACRO_IN_2_64 +GLIB_AVAILABLE_MACRO_IN_2_66 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_44 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_60 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_62 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_64 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_66 +GLIB_AVAILABLE_TYPE_IN_2_26 +GLIB_AVAILABLE_TYPE_IN_2_28 +GLIB_AVAILABLE_TYPE_IN_2_30 +GLIB_AVAILABLE_TYPE_IN_2_32 +GLIB_AVAILABLE_TYPE_IN_2_34 +GLIB_AVAILABLE_TYPE_IN_2_36 +GLIB_AVAILABLE_TYPE_IN_2_38 +GLIB_AVAILABLE_TYPE_IN_2_40 +GLIB_AVAILABLE_TYPE_IN_2_42 +GLIB_AVAILABLE_TYPE_IN_2_44 +GLIB_AVAILABLE_TYPE_IN_2_46 +GLIB_AVAILABLE_TYPE_IN_2_48 +GLIB_AVAILABLE_TYPE_IN_2_50 +GLIB_AVAILABLE_TYPE_IN_2_52 +GLIB_AVAILABLE_TYPE_IN_2_54 +GLIB_AVAILABLE_TYPE_IN_2_56 +GLIB_AVAILABLE_TYPE_IN_2_58 +GLIB_AVAILABLE_TYPE_IN_2_60 +GLIB_AVAILABLE_TYPE_IN_2_62 +GLIB_AVAILABLE_TYPE_IN_2_64 +GLIB_AVAILABLE_TYPE_IN_2_66 +GLIB_DEPRECATED_ENUMERATOR +GLIB_DEPRECATED_ENUMERATOR_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_26 +GLIB_DEPRECATED_ENUMERATOR_IN_2_26_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_28 +GLIB_DEPRECATED_ENUMERATOR_IN_2_28_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_30 +GLIB_DEPRECATED_ENUMERATOR_IN_2_30_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_32 +GLIB_DEPRECATED_ENUMERATOR_IN_2_32_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_34 +GLIB_DEPRECATED_ENUMERATOR_IN_2_34_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_36 +GLIB_DEPRECATED_ENUMERATOR_IN_2_36_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_38 +GLIB_DEPRECATED_ENUMERATOR_IN_2_38_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_40 +GLIB_DEPRECATED_ENUMERATOR_IN_2_40_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_42 +GLIB_DEPRECATED_ENUMERATOR_IN_2_42_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_44 +GLIB_DEPRECATED_ENUMERATOR_IN_2_44_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_46 +GLIB_DEPRECATED_ENUMERATOR_IN_2_46_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_48 +GLIB_DEPRECATED_ENUMERATOR_IN_2_48_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_50 +GLIB_DEPRECATED_ENUMERATOR_IN_2_50_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_52 +GLIB_DEPRECATED_ENUMERATOR_IN_2_52_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_54 +GLIB_DEPRECATED_ENUMERATOR_IN_2_54_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_56 +GLIB_DEPRECATED_ENUMERATOR_IN_2_56_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_58 +GLIB_DEPRECATED_ENUMERATOR_IN_2_58_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_60 +GLIB_DEPRECATED_ENUMERATOR_IN_2_60_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_62 +GLIB_DEPRECATED_ENUMERATOR_IN_2_62_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_64 +GLIB_DEPRECATED_ENUMERATOR_IN_2_64_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_66 +GLIB_DEPRECATED_ENUMERATOR_IN_2_66_FOR +GLIB_DEPRECATED_IN_2_26 +GLIB_DEPRECATED_IN_2_26_FOR +GLIB_DEPRECATED_IN_2_28 +GLIB_DEPRECATED_IN_2_28_FOR +GLIB_DEPRECATED_IN_2_30 +GLIB_DEPRECATED_IN_2_30_FOR +GLIB_DEPRECATED_IN_2_32 +GLIB_DEPRECATED_IN_2_32_FOR +GLIB_DEPRECATED_IN_2_34 +GLIB_DEPRECATED_IN_2_34_FOR +GLIB_DEPRECATED_IN_2_36 +GLIB_DEPRECATED_IN_2_36_FOR +GLIB_DEPRECATED_IN_2_38 +GLIB_DEPRECATED_IN_2_38_FOR +GLIB_DEPRECATED_IN_2_40 +GLIB_DEPRECATED_IN_2_40_FOR +GLIB_DEPRECATED_IN_2_42 +GLIB_DEPRECATED_IN_2_42_FOR +GLIB_DEPRECATED_IN_2_44 +GLIB_DEPRECATED_IN_2_44_FOR +GLIB_DEPRECATED_IN_2_46 +GLIB_DEPRECATED_IN_2_46_FOR +GLIB_DEPRECATED_IN_2_48 +GLIB_DEPRECATED_IN_2_48_FOR +GLIB_DEPRECATED_IN_2_50 +GLIB_DEPRECATED_IN_2_50_FOR +GLIB_DEPRECATED_IN_2_52 +GLIB_DEPRECATED_IN_2_52_FOR +GLIB_DEPRECATED_IN_2_54 +GLIB_DEPRECATED_IN_2_54_FOR +GLIB_DEPRECATED_IN_2_56 +GLIB_DEPRECATED_IN_2_56_FOR +GLIB_DEPRECATED_IN_2_58 +GLIB_DEPRECATED_IN_2_58_FOR +GLIB_DEPRECATED_IN_2_60 +GLIB_DEPRECATED_IN_2_60_FOR +GLIB_DEPRECATED_IN_2_62 +GLIB_DEPRECATED_IN_2_62_FOR +GLIB_DEPRECATED_IN_2_64 +GLIB_DEPRECATED_IN_2_64_FOR +GLIB_DEPRECATED_IN_2_66 +GLIB_DEPRECATED_IN_2_66_FOR +GLIB_DEPRECATED_MACRO +GLIB_DEPRECATED_MACRO_FOR +GLIB_DEPRECATED_MACRO_IN_2_26 +GLIB_DEPRECATED_MACRO_IN_2_26_FOR +GLIB_DEPRECATED_MACRO_IN_2_28 +GLIB_DEPRECATED_MACRO_IN_2_28_FOR +GLIB_DEPRECATED_MACRO_IN_2_30 +GLIB_DEPRECATED_MACRO_IN_2_30_FOR +GLIB_DEPRECATED_MACRO_IN_2_32 +GLIB_DEPRECATED_MACRO_IN_2_32_FOR +GLIB_DEPRECATED_MACRO_IN_2_34 +GLIB_DEPRECATED_MACRO_IN_2_34_FOR +GLIB_DEPRECATED_MACRO_IN_2_36 +GLIB_DEPRECATED_MACRO_IN_2_36_FOR +GLIB_DEPRECATED_MACRO_IN_2_38 +GLIB_DEPRECATED_MACRO_IN_2_38_FOR +GLIB_DEPRECATED_MACRO_IN_2_40 +GLIB_DEPRECATED_MACRO_IN_2_40_FOR +GLIB_DEPRECATED_MACRO_IN_2_42 +GLIB_DEPRECATED_MACRO_IN_2_42_FOR +GLIB_DEPRECATED_MACRO_IN_2_44 +GLIB_DEPRECATED_MACRO_IN_2_44_FOR +GLIB_DEPRECATED_MACRO_IN_2_46 +GLIB_DEPRECATED_MACRO_IN_2_46_FOR +GLIB_DEPRECATED_MACRO_IN_2_48 +GLIB_DEPRECATED_MACRO_IN_2_48_FOR +GLIB_DEPRECATED_MACRO_IN_2_50 +GLIB_DEPRECATED_MACRO_IN_2_50_FOR +GLIB_DEPRECATED_MACRO_IN_2_52 +GLIB_DEPRECATED_MACRO_IN_2_52_FOR +GLIB_DEPRECATED_MACRO_IN_2_54 +GLIB_DEPRECATED_MACRO_IN_2_54_FOR +GLIB_DEPRECATED_MACRO_IN_2_56 +GLIB_DEPRECATED_MACRO_IN_2_56_FOR +GLIB_DEPRECATED_MACRO_IN_2_58 +GLIB_DEPRECATED_MACRO_IN_2_58_FOR +GLIB_DEPRECATED_MACRO_IN_2_60 +GLIB_DEPRECATED_MACRO_IN_2_60_FOR +GLIB_DEPRECATED_MACRO_IN_2_62 +GLIB_DEPRECATED_MACRO_IN_2_62_FOR +GLIB_DEPRECATED_MACRO_IN_2_64 +GLIB_DEPRECATED_MACRO_IN_2_64_FOR +GLIB_DEPRECATED_MACRO_IN_2_66 +GLIB_DEPRECATED_MACRO_IN_2_66_FOR +GLIB_DEPRECATED_TYPE +GLIB_DEPRECATED_TYPE_FOR +GLIB_DEPRECATED_TYPE_IN_2_26 +GLIB_DEPRECATED_TYPE_IN_2_26_FOR +GLIB_DEPRECATED_TYPE_IN_2_28 +GLIB_DEPRECATED_TYPE_IN_2_28_FOR +GLIB_DEPRECATED_TYPE_IN_2_30 +GLIB_DEPRECATED_TYPE_IN_2_30_FOR +GLIB_DEPRECATED_TYPE_IN_2_32 +GLIB_DEPRECATED_TYPE_IN_2_32_FOR +GLIB_DEPRECATED_TYPE_IN_2_34 +GLIB_DEPRECATED_TYPE_IN_2_34_FOR +GLIB_DEPRECATED_TYPE_IN_2_36 +GLIB_DEPRECATED_TYPE_IN_2_36_FOR +GLIB_DEPRECATED_TYPE_IN_2_38 +GLIB_DEPRECATED_TYPE_IN_2_38_FOR +GLIB_DEPRECATED_TYPE_IN_2_40 +GLIB_DEPRECATED_TYPE_IN_2_40_FOR +GLIB_DEPRECATED_TYPE_IN_2_42 +GLIB_DEPRECATED_TYPE_IN_2_42_FOR +GLIB_DEPRECATED_TYPE_IN_2_44 +GLIB_DEPRECATED_TYPE_IN_2_44_FOR +GLIB_DEPRECATED_TYPE_IN_2_46 +GLIB_DEPRECATED_TYPE_IN_2_46_FOR +GLIB_DEPRECATED_TYPE_IN_2_48 +GLIB_DEPRECATED_TYPE_IN_2_48_FOR +GLIB_DEPRECATED_TYPE_IN_2_50 +GLIB_DEPRECATED_TYPE_IN_2_50_FOR +GLIB_DEPRECATED_TYPE_IN_2_52 +GLIB_DEPRECATED_TYPE_IN_2_52_FOR +GLIB_DEPRECATED_TYPE_IN_2_54 +GLIB_DEPRECATED_TYPE_IN_2_54_FOR +GLIB_DEPRECATED_TYPE_IN_2_56 +GLIB_DEPRECATED_TYPE_IN_2_56_FOR +GLIB_DEPRECATED_TYPE_IN_2_58 +GLIB_DEPRECATED_TYPE_IN_2_58_FOR +GLIB_DEPRECATED_TYPE_IN_2_60 +GLIB_DEPRECATED_TYPE_IN_2_60_FOR +GLIB_DEPRECATED_TYPE_IN_2_62 +GLIB_DEPRECATED_TYPE_IN_2_62_FOR +GLIB_DEPRECATED_TYPE_IN_2_64 +GLIB_DEPRECATED_TYPE_IN_2_64_FOR +GLIB_DEPRECATED_TYPE_IN_2_66 +GLIB_DEPRECATED_TYPE_IN_2_66_FOR +GLIB_VERSION_CUR_STABLE +GLIB_VERSION_PREV_STABLE +</SECTION> + +<SECTION> +<TITLE>Standard Macros</TITLE> +<FILE>macros</FILE> +<SUBSECTION> +G_OS_WIN32 +G_OS_UNIX + +<SUBSECTION> +G_DIR_SEPARATOR +G_DIR_SEPARATOR_S +G_IS_DIR_SEPARATOR +G_SEARCHPATH_SEPARATOR +G_SEARCHPATH_SEPARATOR_S + +<SUBSECTION> +TRUE +FALSE + +<SUBSECTION> +NULL + +<SUBSECTION> +MIN +MAX + +<SUBSECTION> +ABS +CLAMP +G_APPROX_VALUE + +<SUBSECTION> +G_SIZEOF_MEMBER +G_STRUCT_MEMBER +G_STRUCT_MEMBER_P +G_STRUCT_OFFSET + +<SUBSECTION> +G_MEM_ALIGN + +<SUBSECTION> +G_ALIGNOF + +<SUBSECTION> +G_CONST_RETURN + +<SUBSECTION> +G_N_ELEMENTS +</SECTION> + +<SECTION> +<TITLE>Type Conversion Macros</TITLE> +<FILE>type_conversion</FILE> +GINT_TO_POINTER +GPOINTER_TO_INT + +<SUBSECTION> +GUINT_TO_POINTER +GPOINTER_TO_UINT +GSIZE_TO_POINTER +GPOINTER_TO_SIZE +</SECTION> + +<SECTION> +<TITLE>Byte Order Macros</TITLE> +<FILE>byte_order</FILE> +G_BYTE_ORDER +G_LITTLE_ENDIAN +G_BIG_ENDIAN +G_PDP_ENDIAN + +<SUBSECTION> +g_htonl +g_htons +g_ntohl +g_ntohs + +<SUBSECTION> +GINT_FROM_BE +GINT_FROM_LE +GINT_TO_BE +GINT_TO_LE + +<SUBSECTION> +GUINT_FROM_BE +GUINT_FROM_LE +GUINT_TO_BE +GUINT_TO_LE + +<SUBSECTION> +GLONG_FROM_BE +GLONG_FROM_LE +GLONG_TO_BE +GLONG_TO_LE + +<SUBSECTION> +GULONG_FROM_BE +GULONG_FROM_LE +GULONG_TO_BE +GULONG_TO_LE + +<SUBSECTION> +GSIZE_FROM_BE +GSIZE_FROM_LE +GSIZE_TO_BE +GSIZE_TO_LE + +<SUBSECTION> +GSSIZE_FROM_BE +GSSIZE_FROM_LE +GSSIZE_TO_BE +GSSIZE_TO_LE + +<SUBSECTION> +GINT16_FROM_BE +GINT16_FROM_LE +GINT16_TO_BE +GINT16_TO_LE + +<SUBSECTION> +GUINT16_FROM_BE +GUINT16_FROM_LE +GUINT16_TO_BE +GUINT16_TO_LE + +<SUBSECTION> +GINT32_FROM_BE +GINT32_FROM_LE +GINT32_TO_BE +GINT32_TO_LE + +<SUBSECTION> +GUINT32_FROM_BE +GUINT32_FROM_LE +GUINT32_TO_BE +GUINT32_TO_LE + +<SUBSECTION> +GINT64_FROM_BE +GINT64_FROM_LE +GINT64_TO_BE +GINT64_TO_LE + +<SUBSECTION> +GUINT64_FROM_BE +GUINT64_FROM_LE +GUINT64_TO_BE +GUINT64_TO_LE + +<SUBSECTION> +GUINT16_SWAP_BE_PDP +GUINT16_SWAP_LE_BE +GUINT16_SWAP_LE_PDP + +<SUBSECTION> +GUINT32_SWAP_BE_PDP +GUINT32_SWAP_LE_BE +GUINT32_SWAP_LE_PDP + +<SUBSECTION> +GUINT64_SWAP_LE_BE + +<SUBSECTION Private> +GUINT16_SWAP_LE_BE_CONSTANT +GUINT32_SWAP_LE_BE_CONSTANT +GUINT64_SWAP_LE_BE_CONSTANT +GUINT16_SWAP_LE_BE_IA32 +GUINT32_SWAP_LE_BE_IA32 +GUINT64_SWAP_LE_BE_IA32 +GUINT16_SWAP_LE_BE_IA64 +GUINT32_SWAP_LE_BE_IA64 +GUINT64_SWAP_LE_BE_IA64 +GUINT32_SWAP_LE_BE_X86_64 +GUINT64_SWAP_LE_BE_X86_64 + +</SECTION> + +<SECTION> +<TITLE>Bounds-checked integer arithmetic</TITLE> +<FILE>checkedmath</FILE> +g_uint_checked_add +g_uint_checked_mul +g_uint64_checked_add +g_uint64_checked_mul +g_size_checked_add +g_size_checked_mul +</SECTION> + +<SECTION> +<TITLE>Numerical Definitions</TITLE> +<FILE>numerical</FILE> +G_IEEE754_FLOAT_BIAS +G_IEEE754_DOUBLE_BIAS +GFloatIEEE754 +GDoubleIEEE754 + +<SUBSECTION> +G_E +G_LN2 +G_LN10 +G_PI +G_PI_2 +G_PI_4 +G_SQRT2 +G_LOG_2_BASE_10 +</SECTION> + +<SECTION> +<TITLE>Miscellaneous Macros</TITLE> +<FILE>macros_misc</FILE> +G_INLINE_FUNC + +<SUBSECTION> +g_auto +g_autoptr +g_autofree +g_autolist +g_autoslist +g_autoqueue +G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC +G_DEFINE_AUTO_CLEANUP_FREE_FUNC + +<SUBSECTION> +G_STMT_START +G_STMT_END + +<SUBSECTION> +G_BEGIN_DECLS +G_END_DECLS + +<SUBSECTION> +G_VA_COPY + +<SUBSECTION> +G_STRINGIFY +G_PASTE +G_STATIC_ASSERT +G_STATIC_ASSERT_EXPR + +<SUBSECTION> +G_GNUC_CHECK_VERSION +G_GNUC_EXTENSION +G_GNUC_CONST +G_GNUC_PURE +G_GNUC_MALLOC +G_GNUC_ALLOC_SIZE +G_GNUC_ALLOC_SIZE2 +G_GNUC_DEPRECATED +G_GNUC_DEPRECATED_FOR +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +G_GNUC_END_IGNORE_DEPRECATIONS +G_GNUC_NORETURN +G_GNUC_FALLTHROUGH +G_GNUC_UNUSED +G_GNUC_PRINTF +G_GNUC_SCANF +G_GNUC_STRFTIME +G_GNUC_FORMAT +G_GNUC_NULL_TERMINATED +G_GNUC_WARN_UNUSED_RESULT +G_GNUC_FUNCTION +G_GNUC_PRETTY_FUNCTION +G_GNUC_NO_INLINE +G_GNUC_NO_INSTRUMENT +G_HAVE_GNUC_VISIBILITY +G_GNUC_INTERNAL +G_GNUC_MAY_ALIAS + +<SUBSECTION> +G_DEPRECATED +G_DEPRECATED_FOR +G_UNAVAILABLE + +<SUBSECTION> +G_LIKELY +G_UNLIKELY + +<SUBSECTION> +G_STRLOC +G_STRFUNC + +<SUBSECTION Private> +GLIB_VAR +G_STRINGIFY_ARG +G_PASTE_ARGS +G_HAVE_INLINE +G_CAN_INLINE +inline +G_HAVE___INLINE +G_HAVE___INLINE__ +G_INLINE_DEFINE_NEEDED +G_HAVE_GNUC_VARARGS +G_HAVE_ISO_VARARGS +G_HAVE_GROWING_STACK +G_VA_COPY_AS_ARRAY +GLIB_DEPRECATED +GLIB_DEPRECATED_FOR +GLIB_UNAVAILABLE +GLIB_UNAVAILABLE_ENUMERATOR +GLIB_UNAVAILABLE_MACRO +GLIB_UNAVAILABLE_STATIC_INLINE +GLIB_UNAVAILABLE_TYPE +G_ANALYZER_ANALYZING +G_ANALYZER_NORETURN +g_autoptr_cleanup_generic_gfree +g_has_typeof +g_macro__has_attribute +g_macro__has_builtin +g_macro__has_feature +</SECTION> + +<SECTION> +<TITLE>Error Reporting</TITLE> +<FILE>error_reporting</FILE> +GError +g_error_new +g_error_new_literal +g_error_new_valist +g_error_free +g_error_copy +g_error_matches +g_set_error +g_set_error_literal +g_propagate_error +g_clear_error +g_prefix_error +g_propagate_prefixed_error +</SECTION> + +<SECTION> +<TITLE>The Main Event Loop</TITLE> +<FILE>main</FILE> +GMainLoop +g_main_loop_new +g_main_loop_ref +g_main_loop_unref +g_main_loop_run +g_main_loop_quit +g_main_loop_is_running +g_main_loop_get_context +g_main_new +g_main_destroy +g_main_run +g_main_quit +g_main_is_running + +<SUBSECTION> +G_PRIORITY_HIGH +G_PRIORITY_DEFAULT +G_PRIORITY_HIGH_IDLE +G_PRIORITY_DEFAULT_IDLE +G_PRIORITY_LOW + +<SUBSECTION> +G_SOURCE_CONTINUE +G_SOURCE_REMOVE + +<SUBSECTION> +GMainContext +g_main_context_new +g_main_context_ref +g_main_context_unref +g_main_context_default +g_main_context_iteration +g_main_iteration +g_main_context_pending +g_main_pending +g_main_context_find_source_by_id +g_main_context_find_source_by_user_data +g_main_context_find_source_by_funcs_user_data +g_main_context_wakeup +g_main_context_acquire +g_main_context_release +g_main_context_is_owner +g_main_context_wait +g_main_context_prepare +g_main_context_query +g_main_context_check +g_main_context_dispatch +g_main_context_set_poll_func +g_main_context_get_poll_func +GPollFunc +g_main_context_add_poll +g_main_context_remove_poll +g_main_depth +g_main_current_source +g_main_set_poll_func +g_main_context_invoke +g_main_context_invoke_full + +<SUBSECTION> +GMainContextPusher +g_main_context_pusher_new +g_main_context_pusher_free + +<SUBSECTION> +g_main_context_get_thread_default +g_main_context_ref_thread_default +g_main_context_push_thread_default +g_main_context_pop_thread_default + +<SUBSECTION> +g_timeout_source_new +g_timeout_source_new_seconds +g_timeout_add +g_timeout_add_full +g_timeout_add_seconds +g_timeout_add_seconds_full + +<SUBSECTION> +g_idle_source_new +g_idle_add +g_idle_add_full +g_idle_remove_by_data + +<SUBSECTION> +GPid +G_PID_FORMAT +GChildWatchFunc +g_child_watch_source_new +g_child_watch_add +g_child_watch_add_full + +<SUBSECTION> +GPollFD +g_poll +G_POLLFD_FORMAT + +<SUBSECTION> +GSource +GSourceDummyMarshal +GSourceFuncs +GSourceDisposeFunc +GSourceCallbackFuncs +g_source_new +g_source_ref +g_source_unref +g_source_set_funcs +g_source_set_dispose_function +g_source_attach +g_source_destroy +g_source_is_destroyed +g_source_set_priority +g_source_get_priority +g_source_set_can_recurse +g_source_get_can_recurse +g_source_get_id +g_source_get_name +g_source_set_name +g_source_set_name_by_id +g_source_get_context +g_source_set_callback +GSourceFunc +G_SOURCE_FUNC +g_source_set_callback_indirect +g_source_set_ready_time +g_source_get_ready_time +g_source_add_unix_fd +g_source_remove_unix_fd +g_source_modify_unix_fd +g_source_query_unix_fd +g_source_add_poll +g_source_remove_poll +g_source_add_child_source +g_source_remove_child_source +g_source_get_time +g_source_get_current_time +g_source_remove +g_source_remove_by_funcs_user_data +g_source_remove_by_user_data +GClearHandleFunc +g_clear_handle_id + +<SUBSECTION Private> +GLIB_HAVE_ALLOCA_H +alloca +GLIB_USING_SYSTEM_PRINTF +GLIB_SYSDEF_POLLERR +GLIB_SYSDEF_POLLHUP +GLIB_SYSDEF_POLLIN +GLIB_SYSDEF_POLLNVAL +GLIB_SYSDEF_POLLOUT +GLIB_SYSDEF_POLLPRI +GLIB_SYSDEF_AF_INET +GLIB_SYSDEF_AF_INET6 +GLIB_SYSDEF_AF_UNIX +GLIB_SYSDEF_MSG_DONTROUTE +GLIB_SYSDEF_MSG_OOB +GLIB_SYSDEF_MSG_PEEK +G_WIN32_MSG_HANDLE +g_idle_funcs +g_timeout_funcs +g_child_watch_funcs +g_unix_signal_funcs +g_unix_fd_source_funcs +GSourcePrivate +</SECTION> + + +<SECTION> +<TITLE>Threads</TITLE> +<FILE>threads</FILE> +<SUBSECTION> +G_THREAD_ERROR +GThreadError + +<SUBSECTION> +GThread +GThreadFunc +g_thread_new +g_thread_try_new +g_thread_ref +g_thread_unref +g_thread_join +g_thread_yield +g_thread_exit +g_thread_self + +<SUBSECTION> +GMutex +g_mutex_init +g_mutex_clear +g_mutex_lock +g_mutex_trylock +g_mutex_unlock + +<SUBSECTION> +GMutexLocker +g_mutex_locker_new +g_mutex_locker_free + +<SUBSECTION> +G_LOCK_DEFINE +G_LOCK_DEFINE_STATIC +G_LOCK_EXTERN +G_LOCK +G_TRYLOCK +G_UNLOCK + +<SUBSECTION> +GRecMutex +g_rec_mutex_init +g_rec_mutex_clear +g_rec_mutex_lock +g_rec_mutex_trylock +g_rec_mutex_unlock + +<SUBSECTION> +GRecMutexLocker +g_rec_mutex_locker_new +g_rec_mutex_locker_free + +<SUBSECTION> +GRWLockWriterLocker +g_rw_lock_writer_locker_new +g_rw_lock_writer_locker_free + +<SUBSECTION> +GRWLockReaderLocker +g_rw_lock_reader_locker_new +g_rw_lock_reader_locker_free + +<SUBSECTION> +GRWLock +g_rw_lock_init +g_rw_lock_clear +g_rw_lock_writer_lock +g_rw_lock_writer_trylock +g_rw_lock_writer_unlock +g_rw_lock_reader_lock +g_rw_lock_reader_trylock +g_rw_lock_reader_unlock + +<SUBSECTION> +GCond +g_cond_init +g_cond_clear +g_cond_wait +g_cond_timed_wait +g_cond_wait_until +g_cond_signal +g_cond_broadcast + +<SUBSECTION> +GPrivate +G_PRIVATE_INIT +g_private_get +g_private_set +g_private_replace + +<SUBSECTION> +GOnce +GOnceStatus +G_ONCE_INIT +g_once +g_once_init_enter +g_once_init_leave + +<SUBSECTION> +g_bit_lock +g_bit_trylock +g_bit_unlock +g_pointer_bit_lock +g_pointer_bit_trylock +g_pointer_bit_unlock + +<SUBSECTION> +g_get_num_processors + +<SUBSECTION Private> +G_LOCK_NAME +atexit +g_thread_error_quark +g_once_impl +</SECTION> + +<SECTION> +<TITLE>Deprecated Thread APIs</TITLE> +<FILE>threads-deprecated</FILE> + +<SUBSECTION> +G_THREADS_IMPL_POSIX +G_THREADS_IMPL_WIN32 + +<SUBSECTION> +g_thread_init +g_thread_supported +g_thread_get_initialized + +<SUBSECTION> +g_thread_create +g_thread_create_full +GThreadPriority +g_thread_set_priority +g_thread_foreach + +<SUBSECTION> +g_mutex_new +g_mutex_free +g_cond_new +g_cond_free +g_private_new + +<SUBSECTION> +GStaticMutex +G_STATIC_MUTEX_INIT +g_static_mutex_init +g_static_mutex_lock +g_static_mutex_trylock +g_static_mutex_unlock +g_static_mutex_get_mutex +g_static_mutex_free + +<SUBSECTION> +GStaticRecMutex +G_STATIC_REC_MUTEX_INIT +g_static_rec_mutex_init +g_static_rec_mutex_lock +g_static_rec_mutex_trylock +g_static_rec_mutex_unlock +g_static_rec_mutex_lock_full +g_static_rec_mutex_unlock_full +g_static_rec_mutex_free + +<SUBSECTION> +GStaticRWLock +G_STATIC_RW_LOCK_INIT +g_static_rw_lock_init +g_static_rw_lock_reader_lock +g_static_rw_lock_reader_trylock +g_static_rw_lock_reader_unlock +g_static_rw_lock_writer_lock +g_static_rw_lock_writer_trylock +g_static_rw_lock_writer_unlock +g_static_rw_lock_free + +<SUBSECTION> +GStaticPrivate +G_STATIC_PRIVATE_INIT +g_static_private_init +g_static_private_get +g_static_private_set +g_static_private_free + +<SUBSECTION Private> +GThreadFunctions +g_thread_init_with_errorcheck_mutexes +G_THREADS_ENABLED +g_static_mutex_get_mutex_impl +g_thread_use_default_impl +g_threads_got_initialized +g_thread_functions_for_glib_use +g_thread_gettime +g_once_init_enter_impl +</SECTION> + +<SECTION> +<TITLE>Thread Pools</TITLE> +<FILE>thread_pools</FILE> +GThreadPool +g_thread_pool_new +g_thread_pool_push +g_thread_pool_set_max_threads +g_thread_pool_get_max_threads +g_thread_pool_get_num_threads +g_thread_pool_unprocessed +g_thread_pool_free +g_thread_pool_set_max_unused_threads +g_thread_pool_get_max_unused_threads +g_thread_pool_get_num_unused_threads +g_thread_pool_stop_unused_threads +g_thread_pool_set_sort_function +g_thread_pool_set_max_idle_time +g_thread_pool_get_max_idle_time +g_thread_pool_move_to_front +</SECTION> + +<SECTION> +<TITLE>Asynchronous Queues</TITLE> +<FILE>async_queues</FILE> +GAsyncQueue +g_async_queue_new +g_async_queue_new_full +g_async_queue_ref +g_async_queue_unref +g_async_queue_push +g_async_queue_push_sorted +g_async_queue_push_front +g_async_queue_remove +g_async_queue_pop +g_async_queue_try_pop +g_async_queue_timeout_pop +g_async_queue_length +g_async_queue_sort + +<SUBSECTION> +g_async_queue_lock +g_async_queue_unlock +g_async_queue_ref_unlocked +g_async_queue_unref_and_unlock +g_async_queue_push_unlocked +g_async_queue_push_sorted_unlocked +g_async_queue_push_front_unlocked +g_async_queue_remove_unlocked +g_async_queue_pop_unlocked +g_async_queue_try_pop_unlocked +g_async_queue_timeout_pop_unlocked +g_async_queue_length_unlocked +g_async_queue_sort_unlocked + +<SUBSECTION> +g_async_queue_timed_pop +g_async_queue_timed_pop_unlocked +</SECTION> + +<SECTION> +<TITLE>Atomic Operations</TITLE> +<FILE>atomic_operations</FILE> +G_ATOMIC_LOCK_FREE + +<SUBSECTION> +g_atomic_int_get +g_atomic_int_set +g_atomic_int_inc +g_atomic_int_dec_and_test +g_atomic_int_compare_and_exchange +g_atomic_int_add +g_atomic_int_and +g_atomic_int_or +g_atomic_int_xor + +<SUBSECTION> +g_atomic_pointer_get +g_atomic_pointer_set +g_atomic_pointer_compare_and_exchange +g_atomic_pointer_add +g_atomic_pointer_and +g_atomic_pointer_or +g_atomic_pointer_xor + +<SUBSECTION> +g_atomic_int_exchange_and_add +</SECTION> + +<SECTION> +<TITLE>IO Channels</TITLE> +<FILE>iochannels</FILE> +GIOChannel + +<SUBSECTION> +g_io_channel_unix_new +g_io_channel_unix_get_fd +g_io_channel_win32_new_fd +g_io_channel_win32_new_socket +g_io_channel_win32_new_messages + +<SUBSECTION> +g_io_channel_init + +<SUBSECTION> +g_io_channel_new_file +g_io_channel_read_chars +g_io_channel_read_unichar +g_io_channel_read_line +g_io_channel_read_line_string +g_io_channel_read_to_end +g_io_channel_write_chars +g_io_channel_write_unichar +g_io_channel_flush +g_io_channel_seek_position +GSeekType +g_io_channel_shutdown + +<SUBSECTION> +GIOStatus +GIOChannelError +G_IO_CHANNEL_ERROR +g_io_channel_error_from_errno + +<SUBSECTION> +g_io_channel_ref +g_io_channel_unref + +<SUBSECTION> +g_io_create_watch +g_io_add_watch +g_io_add_watch_full +GIOCondition +GIOFunc + +<SUBSECTION> +GIOFuncs + +<SUBSECTION> +g_io_channel_get_buffer_size +g_io_channel_set_buffer_size +g_io_channel_get_buffer_condition +g_io_channel_get_flags +g_io_channel_set_flags +GIOFlags +g_io_channel_get_line_term +g_io_channel_set_line_term +g_io_channel_get_buffered +g_io_channel_set_buffered +g_io_channel_get_encoding +g_io_channel_set_encoding +g_io_channel_get_close_on_unref +g_io_channel_set_close_on_unref + +<SUBSECTION> +g_io_channel_read +GIOError +g_io_channel_write +g_io_channel_seek +g_io_channel_close + +<SUBSECTION Private> +g_io_channel_win32_poll +g_io_channel_win32_make_pollfd +g_io_channel_win32_get_fd +g_io_channel_win32_new_stream_socket +g_io_channel_win32_set_debug +g_io_channel_error_quark +g_io_watch_funcs +G_IO_FLAG_IS_WRITEABLE +</SECTION> + +<SECTION> +<TITLE>Memory Allocation</TITLE> +<FILE>memory</FILE> +g_new +g_new0 +g_renew +g_try_new +g_try_new0 +g_try_renew + +<SUBSECTION> +g_malloc +g_malloc0 +g_realloc +g_try_malloc +g_try_malloc0 +g_try_realloc +g_malloc_n +g_malloc0_n +g_realloc_n +g_try_malloc_n +g_try_malloc0_n +g_try_realloc_n + +<SUBSECTION> +g_free +g_clear_pointer +g_steal_pointer +g_mem_gc_friendly + +<SUBSECTION> +g_alloca +g_newa + +<SUBSECTION> +g_memmove +g_memdup + +<SUBSECTION> +GMemVTable +g_mem_set_vtable +g_mem_is_system_malloc + +<SUBSECTION> +glib_mem_profiler_table +g_mem_profile +</SECTION> + +<SECTION> +<TITLE>Warnings and Assertions</TITLE> +<FILE>warnings</FILE> +g_print +g_set_print_handler +GPrintFunc + +<SUBSECTION> +g_printerr +g_set_printerr_handler + +<SUBSECTION> +g_return_if_fail +g_return_val_if_fail +g_return_if_reached +g_return_val_if_reached +g_warn_if_fail +g_warn_if_reached + +<SUBSECTION> +g_on_error_query +g_on_error_stack_trace + +<SUBSECTION> +G_BREAKPOINT + +<SUBSECTION Private> +g_return_if_fail_warning +g_assert_warning +g_warn_message +</SECTION> + +<SECTION> +<TITLE>Glob-style pattern matching</TITLE> +<FILE>patterns</FILE> +GPatternSpec +g_pattern_spec_new +g_pattern_spec_free +g_pattern_spec_equal +g_pattern_match +g_pattern_match_string +g_pattern_match_simple +</SECTION> + +<SECTION> +<TITLE>Perl-compatible regular expressions</TITLE> +<FILE>gregex</FILE> +GRegexError +G_REGEX_ERROR +GRegexCompileFlags +GRegexMatchFlags +GRegex +GRegexEvalCallback +g_regex_new +g_regex_ref +g_regex_unref +g_regex_get_pattern +g_regex_get_max_backref +g_regex_get_capture_count +g_regex_get_has_cr_or_lf +g_regex_get_max_lookbehind +g_regex_get_string_number +g_regex_get_compile_flags +g_regex_get_match_flags +g_regex_escape_string +g_regex_escape_nul +g_regex_match_simple +g_regex_match +g_regex_match_full +g_regex_match_all +g_regex_match_all_full +g_regex_split_simple +g_regex_split +g_regex_split_full +g_regex_replace +g_regex_replace_literal +g_regex_replace_eval +g_regex_check_replacement +GMatchInfo +g_match_info_get_regex +g_match_info_get_string +g_match_info_ref +g_match_info_unref +g_match_info_free +g_match_info_matches +g_match_info_next +g_match_info_get_match_count +g_match_info_is_partial_match +g_match_info_expand_references +g_match_info_fetch +g_match_info_fetch_pos +g_match_info_fetch_named +g_match_info_fetch_named_pos +g_match_info_fetch_all +<SUBSECTION Private> +g_regex_error_quark +</SECTION> + +<SECTION> +<TITLE>Message Logging</TITLE> +<FILE>messages</FILE> +G_LOG_DOMAIN +G_LOG_FATAL_MASK +G_LOG_LEVEL_USER_SHIFT +GLogFunc +GLogLevelFlags + +<SUBSECTION> +g_log +g_logv +g_message +g_warning +g_warning_once +g_critical +g_error +g_info +g_debug + +<SUBSECTION> +g_log_set_handler +g_log_set_handler_full +g_log_remove_handler +g_log_set_always_fatal +g_log_set_fatal_mask +g_log_default_handler +g_log_set_default_handler + +<SUBSECTION> +g_log_structured +g_log_variant +GLogField +g_log_structured_array +G_DEBUG_HERE + +<SUBSECTION> +GLogWriterOutput +GLogWriterFunc +g_log_set_writer_func +g_log_writer_supports_color +g_log_writer_is_journald +g_log_writer_format_fields +g_log_writer_journald +g_log_writer_standard_streams +g_log_writer_default + +<SUBSECTION Private> +g_log_structured_standard +</SECTION> + +<SECTION> +<TITLE>Timers</TITLE> +<FILE>timers</FILE> +GTimer +g_timer_new +g_timer_start +g_timer_stop +g_timer_continue +g_timer_elapsed +g_timer_reset +g_timer_destroy +g_timer_is_active +</SECTION> + +<SECTION> +<TITLE>Spawning Processes</TITLE> +<FILE>spawn</FILE> +GSpawnError +G_SPAWN_ERROR +GSpawnFlags +GSpawnChildSetupFunc +g_spawn_async_with_fds +g_spawn_async_with_pipes +g_spawn_async +g_spawn_sync +G_SPAWN_EXIT_ERROR +g_spawn_check_exit_status +g_spawn_command_line_async +g_spawn_command_line_sync +g_spawn_close_pid +<SUBSECTION Private> +g_spawn_error_quark +g_spawn_exit_error_quark +</SECTION> + +<SECTION> +<TITLE>Simple XML Subset Parser</TITLE> +<FILE>markup</FILE> +GMarkupError +G_MARKUP_ERROR +GMarkupParseFlags +GMarkupParseContext +GMarkupParser +g_markup_escape_text +g_markup_printf_escaped +g_markup_vprintf_escaped +g_markup_parse_context_new +g_markup_parse_context_parse +g_markup_parse_context_end_parse +g_markup_parse_context_free +g_markup_parse_context_get_position +g_markup_parse_context_get_element +g_markup_parse_context_get_element_stack +g_markup_parse_context_get_user_data +g_markup_parse_context_push +g_markup_parse_context_pop +g_markup_parse_context_ref +g_markup_parse_context_unref +<SUBSECTION> +GMarkupCollectType +g_markup_collect_attributes +<SUBSECTION Private> +g_markup_error_quark +</SECTION> + + +<SECTION> +<TITLE>Shell-related Utilities</TITLE> +<FILE>shell</FILE> +GShellError +G_SHELL_ERROR +g_shell_parse_argv +g_shell_quote +g_shell_unquote +<SUBSECTION Private> +g_shell_error_quark +</SECTION> + + +<SECTION> +<TITLE>Commandline option parser</TITLE> +<FILE>option</FILE> +GOptionError +G_OPTION_ERROR +GOptionArgFunc +GOptionContext +g_option_context_new +g_option_context_set_summary +g_option_context_get_summary +g_option_context_set_description +g_option_context_get_description +GTranslateFunc +g_option_context_set_translate_func +g_option_context_set_translation_domain +g_option_context_free +g_option_context_parse +g_option_context_parse_strv +g_option_context_set_help_enabled +g_option_context_get_help_enabled +g_option_context_set_ignore_unknown_options +g_option_context_get_ignore_unknown_options +g_option_context_get_help +g_option_context_get_strict_posix +g_option_context_set_strict_posix +GOptionArg +GOptionFlags +G_OPTION_REMAINING +GOptionEntry +g_option_context_add_main_entries +GOptionGroup +g_option_context_add_group +g_option_context_set_main_group +g_option_context_get_main_group +g_option_group_new +g_option_group_ref +g_option_group_unref +g_option_group_free +g_option_group_add_entries +GOptionParseFunc +g_option_group_set_parse_hooks +GOptionErrorFunc +g_option_group_set_error_hook +g_option_group_set_translate_func +g_option_group_set_translation_domain +<SUBSECTION Private> +g_option_error_quark +</SECTION> + + +<SECTION> +<TITLE>File Utilities</TITLE> +<FILE>fileutils</FILE> +<INCLUDE>glib.h,glib/gstdio.h,fcntl.h,sys/types.h,sys/stat.h</INCLUDE> +GFileError +G_FILE_ERROR +GFileTest +g_file_error_from_errno +g_file_get_contents +g_file_set_contents +g_file_test +g_mkstemp +g_mkstemp_full +g_file_open_tmp +g_file_read_link +g_mkdir_with_parents +g_mkdtemp +g_mkdtemp_full +g_dir_make_tmp + +<SUBSECTION> +GDir +g_dir_open +g_dir_read_name +g_dir_rewind +g_dir_close + +<SUBSECTION> +GMappedFile +g_mapped_file_new +g_mapped_file_new_from_fd +g_mapped_file_ref +g_mapped_file_unref +g_mapped_file_free +g_mapped_file_get_length +g_mapped_file_get_contents +g_mapped_file_get_bytes + +<SUBSECTION> +g_open +g_rename +g_mkdir +GStatBuf +g_stat +g_lstat +g_unlink +g_remove +g_rmdir +g_fopen +g_freopen +g_fsync +g_chmod +g_access +g_creat +g_chdir +g_utime +g_close + +<SUBSECTION Private> +g_file_error_quark +utimbuf +</SECTION> + + +<SECTION> +<TITLE>String Utility Functions</TITLE> +<FILE>string_utils</FILE> +<INCLUDE>glib.h,glib/gprintf.h</INCLUDE> +g_strdup +g_strndup +g_strdupv +g_strnfill +g_stpcpy +g_strstr_len +g_strrstr +g_strrstr_len +g_str_has_prefix +g_str_has_suffix +g_strcmp0 +g_str_to_ascii +g_str_tokenize_and_fold +g_str_match_string + +<SUBSECTION> +g_strlcpy +g_strlcat + +<SUBSECTION> +g_strdup_printf +g_strdup_vprintf +g_printf +g_vprintf +g_fprintf +g_vfprintf +g_sprintf +g_vsprintf +g_snprintf +g_vsnprintf +g_vasprintf +g_printf_string_upper_bound + +<SUBSECTION> +g_str_is_ascii +g_ascii_isalnum +g_ascii_isalpha +g_ascii_iscntrl +g_ascii_isdigit +g_ascii_isgraph +g_ascii_islower +g_ascii_isprint +g_ascii_ispunct +g_ascii_isspace +g_ascii_isupper +g_ascii_isxdigit + +<SUBSECTION> +g_ascii_digit_value +g_ascii_xdigit_value + +<SUBSECTION> +g_ascii_strcasecmp +g_ascii_strncasecmp + +<SUBSECTION> +g_ascii_strup +g_ascii_strdown + +<SUBSECTION> +g_ascii_tolower +g_ascii_toupper + +<SUBSECTION> +g_string_ascii_up +g_string_ascii_down + +<SUBSECTION> +g_strup +g_strdown + +<SUBSECTION> +g_strcasecmp +g_strncasecmp + +<SUBSECTION> +g_strreverse + +<SUBSECTION> +g_ascii_strtoll +g_ascii_strtoull +G_ASCII_DTOSTR_BUF_SIZE +g_ascii_strtod +g_ascii_dtostr +g_ascii_formatd +g_strtod + +<SUBSECTION> +GNumberParserError +G_NUMBER_PARSER_ERROR +g_ascii_string_to_signed +g_ascii_string_to_unsigned + +<SUBSECTION Private> +g_number_parser_error_quark + +<SUBSECTION> +g_strchug +g_strchomp +g_strstrip + +<SUBSECTION> +g_strdelimit +G_STR_DELIMITERS +g_strescape +g_strcompress +g_strcanon +g_strsplit +g_strsplit_set +g_strfreev +g_strconcat +g_strjoin +g_strjoinv + +<SUBSECTION> +GStrv +g_strv_length +g_strv_contains +g_strv_equal + +<SUBSECTION> +g_strerror +g_strsignal + +<SUBSECTION Private> +GAsciiType +g_ascii_table +</SECTION> + +<SECTION> +<TITLE>Date and Time Functions</TITLE> +<FILE>date</FILE> +G_USEC_PER_SEC +GTimeVal +g_get_current_time +g_usleep +g_time_val_add +g_time_val_from_iso8601 +g_time_val_to_iso8601 + +<SUBSECTION> +g_get_monotonic_time +g_get_real_time + +<SUBSECTION> +GDate +GTime +GDateDMY +GDateDay +GDateMonth +GDateYear +GDateWeekday + +<SUBSECTION> +G_DATE_BAD_DAY +G_DATE_BAD_JULIAN +G_DATE_BAD_YEAR + +<SUBSECTION> +g_date_new +g_date_new_dmy +g_date_new_julian +g_date_clear +g_date_free +g_date_copy + +<SUBSECTION> +g_date_set_day +g_date_set_month +g_date_set_year +g_date_set_dmy +g_date_set_julian +g_date_set_time +g_date_set_time_t +g_date_set_time_val +g_date_set_parse + +<SUBSECTION> +g_date_add_days +g_date_subtract_days +g_date_add_months +g_date_subtract_months +g_date_add_years +g_date_subtract_years +g_date_days_between +g_date_compare +g_date_clamp +g_date_order + +<SUBSECTION> +g_date_get_day +g_date_get_month +g_date_get_year +g_date_get_julian +g_date_get_weekday +g_date_get_day_of_year + +<SUBSECTION> +g_date_get_days_in_month +g_date_is_first_of_month +g_date_is_last_of_month +g_date_is_leap_year +g_date_get_monday_week_of_year +g_date_get_monday_weeks_in_year +g_date_get_sunday_week_of_year +g_date_get_sunday_weeks_in_year +g_date_get_iso8601_week_of_year + +<SUBSECTION> +g_date_strftime +g_date_to_struct_tm + +<SUBSECTION> +g_date_valid +g_date_valid_day +g_date_valid_month +g_date_valid_year +g_date_valid_dmy +g_date_valid_julian +g_date_valid_weekday + +<SUBSECTION Private> +g_date_weekday +g_date_month +g_date_year +g_date_day +g_date_julian +g_date_day_of_year +g_date_monday_week_of_year +g_date_sunday_week_of_year +g_date_days_in_month +g_date_monday_weeks_in_year +g_date_sunday_weeks_in_year +</SECTION> + +<SECTION> +<FILE>timezone</FILE> +<SUBSECTION> +GTimeZone +g_time_zone_unref +g_time_zone_ref +<SUBSECTION> +g_time_zone_new +g_time_zone_new_local +g_time_zone_new_utc +g_time_zone_new_offset +<SUBSECTION> +GTimeType +g_time_zone_find_interval +g_time_zone_adjust_time +<SUBSECTION> +g_time_zone_get_identifier +g_time_zone_get_abbreviation +g_time_zone_get_offset +g_time_zone_is_dst +</SECTION> + +<SECTION> +<FILE>date-time</FILE> +GTimeSpan +G_TIME_SPAN_DAY +G_TIME_SPAN_HOUR +G_TIME_SPAN_MINUTE +G_TIME_SPAN_SECOND +G_TIME_SPAN_MILLISECOND + +<SUBSECTION> +GDateTime +g_date_time_unref +g_date_time_ref + +<SUBSECTION> +g_date_time_new_now +g_date_time_new_now_local +g_date_time_new_now_utc + +<SUBSECTION> +g_date_time_new_from_unix_local +g_date_time_new_from_unix_utc + +<SUBSECTION> +g_date_time_new_from_timeval_local +g_date_time_new_from_timeval_utc +g_date_time_new_from_iso8601 + +<SUBSECTION> +g_date_time_new +g_date_time_new_local +g_date_time_new_utc + +<SUBSECTION> +g_date_time_add + +<SUBSECTION> +g_date_time_add_years +g_date_time_add_months +g_date_time_add_weeks +g_date_time_add_days + +<SUBSECTION> +g_date_time_add_hours +g_date_time_add_minutes +g_date_time_add_seconds + +<SUBSECTION> +g_date_time_add_full + +<SUBSECTION> +g_date_time_compare +g_date_time_difference +g_date_time_hash +g_date_time_equal + +<SUBSECTION> +g_date_time_get_ymd + +<SUBSECTION> +g_date_time_get_year +g_date_time_get_month +g_date_time_get_day_of_month + +<SUBSECTION> +g_date_time_get_week_numbering_year +g_date_time_get_week_of_year +g_date_time_get_day_of_week + +<SUBSECTION> +g_date_time_get_day_of_year + +<SUBSECTION> +g_date_time_get_hour +g_date_time_get_minute +g_date_time_get_second +g_date_time_get_microsecond +g_date_time_get_seconds + +<SUBSECTION> +g_date_time_to_unix +g_date_time_to_timeval + +<SUBSECTION> +g_date_time_get_utc_offset +g_date_time_get_timezone +g_date_time_get_timezone_abbreviation +g_date_time_is_daylight_savings + +<SUBSECTION> +g_date_time_to_timezone +g_date_time_to_local +g_date_time_to_utc + +<SUBSECTION> +g_date_time_format +g_date_time_format_iso8601 +</SECTION> + +<SECTION> +<TITLE>Hook Functions</TITLE> +<FILE>hooks</FILE> +GHookList +GHookFinalizeFunc +GHook +GHookFunc +GHookCheckFunc + +<SUBSECTION> +g_hook_list_init +g_hook_list_invoke +g_hook_list_invoke_check +g_hook_list_marshal +GHookMarshaller +g_hook_list_marshal_check +GHookCheckMarshaller +g_hook_list_clear + +<SUBSECTION> +g_hook_alloc +g_hook_append +g_hook_prepend +g_hook_insert_before +g_hook_insert_sorted +GHookCompareFunc +g_hook_compare_ids + +<SUBSECTION> +g_hook_get +g_hook_find +GHookFindFunc +g_hook_find_data +g_hook_find_func +g_hook_find_func_data + +<SUBSECTION> +g_hook_first_valid +g_hook_next_valid + +GHookFlagMask +G_HOOK_FLAGS +G_HOOK_FLAG_USER_SHIFT + +<SUBSECTION> +G_HOOK +G_HOOK_IS_VALID +G_HOOK_ACTIVE +G_HOOK_IN_CALL +G_HOOK_IS_UNLINKED + +<SUBSECTION> +g_hook_ref +g_hook_unref + +g_hook_free +g_hook_destroy +g_hook_destroy_link +</SECTION> + +<SECTION> +<TITLE>Miscellaneous Utility Functions</TITLE> +<FILE>misc_utils</FILE> +g_get_application_name +g_set_application_name +g_get_prgname +g_set_prgname +g_get_environ +g_environ_getenv +g_environ_setenv +g_environ_unsetenv +g_getenv +g_setenv +g_unsetenv +g_listenv +g_get_user_name +g_get_real_name +g_get_user_cache_dir +g_get_user_data_dir +g_get_user_config_dir +g_get_user_runtime_dir +GUserDirectory +g_get_user_special_dir +g_get_system_data_dirs +g_get_system_config_dirs +g_reload_user_special_dirs_cache +g_get_os_info + +<SUBSECTION> +G_OS_INFO_KEY_NAME +G_OS_INFO_KEY_PRETTY_NAME +G_OS_INFO_KEY_VERSION +G_OS_INFO_KEY_VERSION_CODENAME +G_OS_INFO_KEY_VERSION_ID +G_OS_INFO_KEY_ID +G_OS_INFO_KEY_HOME_URL +G_OS_INFO_KEY_DOCUMENTATION_URL +G_OS_INFO_KEY_SUPPORT_URL +G_OS_INFO_KEY_BUG_REPORT_URL +G_OS_INFO_KEY_PRIVACY_POLICY_URL + +<SUBSECTION> +g_get_host_name +g_get_home_dir +g_get_tmp_dir +g_get_current_dir +g_basename +g_dirname +g_canonicalize_filename +g_path_is_absolute +g_path_skip_root +g_path_get_basename +g_path_get_dirname +g_build_filename +g_build_filenamev +g_build_filename_valist +g_build_path +g_build_pathv + +<SUBSECTION> +g_format_size +GFormatSizeFlags +g_format_size_full +g_format_size_for_display + +<SUBSECTION> +g_find_program_in_path + +<SUBSECTION> +g_bit_nth_lsf +g_bit_nth_msf +g_bit_storage + +<SUBSECTION> +g_spaced_primes_closest + +<SUBSECTION> +g_atexit +g_abort + +<SUBSECTION> +g_parse_debug_string +GDebugKey + +<SUBSECTION> +GVoidFunc +GFreeFunc + +<SUBSECTION> +g_qsort_with_data + +<SUBSECTION> +g_nullify_pointer + +<SUBSECTION Private> +G_NATIVE_ATEXIT +g_ATEXIT +g_win32_get_system_data_dirs_for_module +ATEXIT +g_bit_nth_lsf_impl +g_bit_nth_msf_impl +g_bit_storage_impl + +</SECTION> + +<SECTION> +<TITLE>Lexical Scanner</TITLE> +<FILE>scanner</FILE> +GScanner +GScannerConfig +g_scanner_new +g_scanner_destroy + +<SUBSECTION> +g_scanner_input_file +g_scanner_sync_file_offset +g_scanner_input_text +g_scanner_peek_next_token +g_scanner_get_next_token +g_scanner_eof + +<SUBSECTION> +g_scanner_cur_line +g_scanner_cur_position +g_scanner_cur_token +g_scanner_cur_value + +<SUBSECTION> +g_scanner_set_scope +g_scanner_scope_add_symbol +g_scanner_scope_foreach_symbol +g_scanner_scope_lookup_symbol +g_scanner_scope_remove_symbol +g_scanner_add_symbol +g_scanner_remove_symbol +g_scanner_foreach_symbol + +<SUBSECTION> +g_scanner_freeze_symbol_table +g_scanner_thaw_symbol_table +g_scanner_lookup_symbol + +<SUBSECTION> +g_scanner_warn +g_scanner_error +g_scanner_unexp_token +GScannerMsgFunc + +<SUBSECTION> +G_CSET_a_2_z +G_CSET_A_2_Z +G_CSET_DIGITS +G_CSET_LATINC +G_CSET_LATINS +GTokenType +GTokenValue +GErrorType + +</SECTION> + +<SECTION> +<TITLE>Key-value file parser</TITLE> +<FILE>keyfile</FILE> +GKeyFile +G_KEY_FILE_ERROR +GKeyFileError +GKeyFileFlags + +<SUBSECTION> +g_key_file_new +g_key_file_free +g_key_file_ref +g_key_file_unref +g_key_file_set_list_separator +g_key_file_load_from_file +g_key_file_load_from_data +g_key_file_load_from_bytes +g_key_file_load_from_data_dirs +g_key_file_load_from_dirs +g_key_file_to_data +g_key_file_save_to_file +g_key_file_get_start_group +g_key_file_get_groups +g_key_file_get_keys +g_key_file_has_group +g_key_file_has_key + +<SUBSECTION> +g_key_file_get_value +g_key_file_get_string +g_key_file_get_locale_string +g_key_file_get_locale_for_key +g_key_file_get_boolean +g_key_file_get_integer +g_key_file_get_int64 +g_key_file_get_uint64 +g_key_file_get_double +g_key_file_get_string_list +g_key_file_get_locale_string_list +g_key_file_get_boolean_list +g_key_file_get_integer_list +g_key_file_get_double_list +g_key_file_get_comment + +<SUBSECTION> +g_key_file_set_value +g_key_file_set_string +g_key_file_set_locale_string +g_key_file_set_boolean +g_key_file_set_integer +g_key_file_set_int64 +g_key_file_set_uint64 +g_key_file_set_double +g_key_file_set_string_list +g_key_file_set_locale_string_list +g_key_file_set_boolean_list +g_key_file_set_integer_list +g_key_file_set_double_list +g_key_file_set_comment +g_key_file_remove_group +g_key_file_remove_key +g_key_file_remove_comment + +<SUBSECTION> +G_KEY_FILE_DESKTOP_GROUP +G_KEY_FILE_DESKTOP_KEY_TYPE +G_KEY_FILE_DESKTOP_KEY_VERSION +G_KEY_FILE_DESKTOP_KEY_NAME +G_KEY_FILE_DESKTOP_KEY_GENERIC_NAME +G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY +G_KEY_FILE_DESKTOP_KEY_COMMENT +G_KEY_FILE_DESKTOP_KEY_ICON +G_KEY_FILE_DESKTOP_KEY_HIDDEN +G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN +G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN +G_KEY_FILE_DESKTOP_KEY_TRY_EXEC +G_KEY_FILE_DESKTOP_KEY_EXEC +G_KEY_FILE_DESKTOP_KEY_PATH +G_KEY_FILE_DESKTOP_KEY_TERMINAL +G_KEY_FILE_DESKTOP_KEY_MIME_TYPE +G_KEY_FILE_DESKTOP_KEY_CATEGORIES +G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY +G_KEY_FILE_DESKTOP_KEY_STARTUP_WM_CLASS +G_KEY_FILE_DESKTOP_KEY_URL +G_KEY_FILE_DESKTOP_KEY_ACTIONS +G_KEY_FILE_DESKTOP_KEY_DBUS_ACTIVATABLE +G_KEY_FILE_DESKTOP_TYPE_APPLICATION +G_KEY_FILE_DESKTOP_TYPE_LINK +G_KEY_FILE_DESKTOP_TYPE_DIRECTORY + +<SUBSECTION Private> +g_key_file_error_quark +g_key_file_get_type +</SECTION> + +<SECTION> +<TITLE>Bookmark file parser</TITLE> +<FILE>bookmarkfile</FILE> +GBookmarkFile +G_BOOKMARK_FILE_ERROR +GBookmarkFileError +g_bookmark_file_new +g_bookmark_file_free +g_bookmark_file_load_from_file +g_bookmark_file_load_from_data +g_bookmark_file_load_from_data_dirs +g_bookmark_file_to_data +g_bookmark_file_to_file +g_bookmark_file_has_item +g_bookmark_file_has_group +g_bookmark_file_has_application +g_bookmark_file_get_size +g_bookmark_file_get_uris G_GNUC_MALLOC + +<SUBSECTION> +g_bookmark_file_get_title +g_bookmark_file_get_description +g_bookmark_file_get_mime_type +g_bookmark_file_get_is_private +g_bookmark_file_get_icon +g_bookmark_file_get_added +g_bookmark_file_get_added_date_time +g_bookmark_file_get_modified +g_bookmark_file_get_modified_date_time +g_bookmark_file_get_visited +g_bookmark_file_get_visited_date_time +g_bookmark_file_get_groups +g_bookmark_file_get_applications +g_bookmark_file_get_app_info +g_bookmark_file_get_application_info + +<SUBSECTION> +g_bookmark_file_set_title +g_bookmark_file_set_description +g_bookmark_file_set_mime_type +g_bookmark_file_set_is_private +g_bookmark_file_set_icon +g_bookmark_file_set_added +g_bookmark_file_set_added_date_time +g_bookmark_file_set_groups +g_bookmark_file_set_modified +g_bookmark_file_set_modified_date_time +g_bookmark_file_set_visited +g_bookmark_file_set_visited_date_time +g_bookmark_file_set_app_info +g_bookmark_file_set_application_info +g_bookmark_file_add_group +g_bookmark_file_add_application +g_bookmark_file_remove_group +g_bookmark_file_remove_application +g_bookmark_file_remove_item +g_bookmark_file_move_item + +<SUBSECTION Private> +g_bookmark_file_error_quark +</SECTION> + +<SECTION> +<TITLE>Dynamic Loading of Modules</TITLE> +<FILE>modules</FILE> +<INCLUDE>gmodule.h</INCLUDE> +GModule +g_module_supported +g_module_build_path +g_module_open +GModuleFlags +g_module_symbol +g_module_name +g_module_make_resident +g_module_close +g_module_error +<SUBSECTION> +GModuleCheckInit +GModuleUnload +G_MODULE_SUFFIX +G_MODULE_EXPORT +G_MODULE_IMPORT +</SECTION> + +<SECTION> +<TITLE>Automatic String Completion</TITLE> +<FILE>completion</FILE> +GCompletion +g_completion_new +GCompletionFunc +g_completion_add_items +g_completion_remove_items +g_completion_clear_items +g_completion_complete +g_completion_complete_utf8 +g_completion_set_compare +GCompletionStrncmpFunc +g_completion_free +</SECTION> + +<SECTION> +<TITLE>Windows Compatibility Functions</TITLE> +<FILE>windows</FILE> +MAXPATHLEN +GWin32OSType + +g_win32_check_windows_version +g_win32_get_command_line +g_win32_error_message +g_win32_getlocale +g_win32_get_package_installation_directory +g_win32_get_package_installation_directory_of_module +g_win32_get_package_installation_subdirectory +g_win32_get_windows_version +g_win32_locale_filename_from_utf8 +G_WIN32_DLLMAIN_FOR_DLL_NAME +G_WIN32_HAVE_WIDECHAR_API +G_WIN32_IS_NT_BASED + +<SUBSECTION Private> +g_win32_ftruncate + +</SECTION> + +<SECTION> +<TITLE>UNIX-specific utilities and integration</TITLE> +<FILE>gunix</FILE> +G_UNIX_ERROR +g_unix_open_pipe +g_unix_set_fd_nonblocking + +<SUBSECTION> +g_unix_signal_add +g_unix_signal_add_full +g_unix_signal_source_new + +<SUBSECTION> +GUnixFDSourceFunc +g_unix_fd_add +g_unix_fd_add_full +g_unix_fd_source_new + +<SUBSECTION> +g_unix_get_passwd_entry + +<SUBSECTION Private> +g_unix_error_quark +</SECTION> + +# Data Structures + +<SECTION> +<TITLE>Memory Slices</TITLE> +<FILE>memory_slices</FILE> +g_slice_alloc +g_slice_alloc0 +g_slice_copy +g_slice_free1 +g_slice_free_chain_with_offset + +<SUBSECTION> +g_slice_new +g_slice_new0 +g_slice_dup +g_slice_free +g_slice_free_chain + +<SUBSECTION Private> +GSliceConfig +g_slice_set_config +g_slice_get_config +g_slice_get_config_state +g_slice_debug_tree_statistics +</SECTION> + +<SECTION> +<TITLE>Doubly-Linked Lists</TITLE> +<FILE>linked_lists_double</FILE> +GList + +<SUBSECTION> +g_list_append +g_list_prepend +g_list_insert +g_list_insert_before +g_list_insert_before_link +g_list_insert_sorted +g_list_remove +g_list_remove_link +g_list_delete_link +g_list_remove_all +g_list_free +g_list_free_full +g_clear_list + +<SUBSECTION> +g_list_alloc +g_list_free_1 +g_list_free1 + +<SUBSECTION> +g_list_length +g_list_copy +g_list_copy_deep +g_list_reverse +g_list_sort +GCompareFunc +g_list_insert_sorted_with_data +g_list_sort_with_data +GCompareDataFunc +g_list_concat +g_list_foreach +GFunc + +<SUBSECTION> +g_list_first +g_list_last +g_list_previous +g_list_next +g_list_nth +g_list_nth_data +g_list_nth_prev + +<SUBSECTION> +g_list_find +g_list_find_custom +g_list_position +g_list_index +</SECTION> + +<SECTION> +<TITLE>Singly-Linked Lists</TITLE> +<FILE>linked_lists_single</FILE> +GSList + +<SUBSECTION> +g_slist_alloc +g_slist_append +g_slist_prepend +g_slist_insert +g_slist_insert_before +g_slist_insert_sorted +g_slist_remove +g_slist_remove_link +g_slist_delete_link +g_slist_remove_all +g_slist_free +g_slist_free_full +g_slist_free_1 +g_slist_free1 +g_clear_slist + +<SUBSECTION> +g_slist_length +g_slist_copy +g_slist_copy_deep +g_slist_reverse +g_slist_insert_sorted_with_data +g_slist_sort +g_slist_sort_with_data +g_slist_concat +g_slist_foreach + +<SUBSECTION> +g_slist_last +g_slist_next +g_slist_nth +g_slist_nth_data + +<SUBSECTION> +g_slist_find +g_slist_find_custom +g_slist_position +g_slist_index +</SECTION> + +<SECTION> +<TITLE>Double-ended Queues</TITLE> +<FILE>queue</FILE> + +GQueue +g_queue_new +g_queue_free +g_queue_free_full +G_QUEUE_INIT +g_queue_init +g_queue_clear +g_queue_clear_full +g_queue_is_empty +g_queue_get_length +g_queue_reverse +g_queue_copy +g_queue_foreach +g_queue_find +g_queue_find_custom +g_queue_sort +g_queue_push_head +g_queue_push_tail +g_queue_push_nth +g_queue_pop_head +g_queue_pop_tail +g_queue_pop_nth +g_queue_peek_head +g_queue_peek_tail +g_queue_peek_nth +g_queue_index +g_queue_remove +g_queue_remove_all +g_queue_insert_before +g_queue_insert_before_link +g_queue_insert_after +g_queue_insert_after_link +g_queue_insert_sorted +g_queue_push_head_link +g_queue_push_tail_link +g_queue_push_nth_link +g_queue_pop_head_link +g_queue_pop_tail_link +g_queue_pop_nth_link +g_queue_peek_head_link +g_queue_peek_tail_link +g_queue_peek_nth_link +g_queue_link_index +g_queue_unlink +g_queue_delete_link +</SECTION> + +<SECTION> +<TITLE>Sequences</TITLE> +<FILE>sequence</FILE> + +GSequence +GSequenceIter +GSequenceIterCompareFunc + +<SUBSECTION> +g_sequence_new +g_sequence_free +g_sequence_get_length +g_sequence_is_empty +g_sequence_foreach +g_sequence_foreach_range +g_sequence_sort +g_sequence_sort_iter + +<SUBSECTION> +g_sequence_get_begin_iter +g_sequence_get_end_iter +g_sequence_get_iter_at_pos +g_sequence_append +g_sequence_prepend +g_sequence_insert_before +g_sequence_move +g_sequence_swap +g_sequence_insert_sorted +g_sequence_insert_sorted_iter +g_sequence_sort_changed +g_sequence_sort_changed_iter +g_sequence_remove +g_sequence_remove_range +g_sequence_move_range +g_sequence_search +g_sequence_search_iter +g_sequence_lookup +g_sequence_lookup_iter + +<SUBSECTION> +g_sequence_get +g_sequence_set + +<SUBSECTION> +g_sequence_iter_is_begin +g_sequence_iter_is_end +g_sequence_iter_next +g_sequence_iter_prev +g_sequence_iter_get_position +g_sequence_iter_move +g_sequence_iter_get_sequence + +<SUBSECTION> +g_sequence_iter_compare +g_sequence_range_get_midpoint +</SECTION> + +<SECTION> +<TITLE>Trash Stacks</TITLE> +<FILE>trash_stack</FILE> +GTrashStack + +g_trash_stack_push +g_trash_stack_pop +g_trash_stack_peek +g_trash_stack_height +</SECTION> + +<SECTION> +<TITLE>Hash Tables</TITLE> +<FILE>hash_tables</FILE> +GHashTable +g_hash_table_new +g_hash_table_new_full +GHashFunc +GEqualFunc +g_hash_table_insert +g_hash_table_replace +g_hash_table_add +g_hash_table_contains +g_hash_table_size +g_hash_table_lookup +g_hash_table_lookup_extended +g_hash_table_foreach +g_hash_table_find +GHFunc +g_hash_table_remove +g_hash_table_steal +g_hash_table_steal_extended +g_hash_table_foreach_remove +g_hash_table_foreach_steal +g_hash_table_remove_all +g_hash_table_steal_all +g_hash_table_get_keys +g_hash_table_get_values +g_hash_table_get_keys_as_array +GHRFunc +g_hash_table_freeze +g_hash_table_thaw +g_hash_table_destroy +g_hash_table_ref +g_hash_table_unref +GHashTableIter +g_hash_table_iter_init +g_hash_table_iter_next +g_hash_table_iter_get_hash_table +g_hash_table_iter_replace +g_hash_table_iter_remove +g_hash_table_iter_steal + +<SUBSECTION> +g_direct_equal +g_direct_hash +g_int_equal +g_int_hash +g_int64_equal +g_int64_hash +g_double_equal +g_double_hash +g_str_equal +g_str_hash + +</SECTION> + +<SECTION> +<TITLE>Strings</TITLE> +<FILE>strings</FILE> +GString +g_string_new +g_string_new_len +g_string_sized_new +g_string_assign +g_string_sprintf +g_string_sprintfa +g_string_vprintf +g_string_append_vprintf +g_string_printf +g_string_append_printf +g_string_append +g_string_append_c +g_string_append_unichar +g_string_append_len +g_string_append_uri_escaped +g_string_prepend +g_string_prepend_c +g_string_prepend_unichar +g_string_prepend_len +g_string_insert +g_string_insert_c +g_string_insert_unichar +g_string_insert_len +g_string_overwrite +g_string_overwrite_len +g_string_erase +g_string_truncate +g_string_set_size +g_string_free +g_string_free_to_bytes + +<SUBSECTION> +g_string_up +g_string_down + +<SUBSECTION> +g_string_hash +g_string_equal + +<SUBSECTION Private> +g_string_append_c_inline +g_autoptr_cleanup_gstring_free +</SECTION> + +<SECTION> +<TITLE>String Chunks</TITLE> +<FILE>string_chunks</FILE> +GStringChunk +g_string_chunk_new +g_string_chunk_insert +g_string_chunk_insert_const +g_string_chunk_insert_len +g_string_chunk_clear +g_string_chunk_free + +</SECTION> + +<SECTION> +<TITLE>Arrays</TITLE> +<FILE>arrays</FILE> +GArray +g_array_new +g_array_steal +g_array_sized_new +g_array_copy +g_array_ref +g_array_unref +g_array_get_element_size +g_array_append_val +g_array_append_vals +g_array_prepend_val +g_array_prepend_vals +g_array_insert_val +g_array_insert_vals +g_array_remove_index +g_array_remove_index_fast +g_array_remove_range +g_array_sort +g_array_sort_with_data +g_array_binary_search +g_array_index +g_array_set_size +g_array_set_clear_func +g_array_free +</SECTION> + +<SECTION> +<TITLE>Pointer Arrays</TITLE> +<FILE>arrays_pointer</FILE> +GPtrArray +g_ptr_array_new +g_ptr_array_steal +g_ptr_array_sized_new +g_ptr_array_new_with_free_func +g_ptr_array_copy +g_ptr_array_new_full +g_ptr_array_set_free_func +g_ptr_array_ref +g_ptr_array_unref +g_ptr_array_add +g_ptr_array_extend +g_ptr_array_extend_and_steal +g_ptr_array_insert +g_ptr_array_remove +g_ptr_array_remove_index +g_ptr_array_remove_fast +g_ptr_array_remove_index_fast +g_ptr_array_remove_range +g_ptr_array_steal_index +g_ptr_array_steal_index_fast +g_ptr_array_sort +g_ptr_array_sort_with_data +g_ptr_array_set_size +g_ptr_array_index +g_ptr_array_free +g_ptr_array_foreach +g_ptr_array_find +g_ptr_array_find_with_equal_func + +</SECTION> + +<SECTION> +<TITLE>Byte Arrays</TITLE> +<FILE>arrays_byte</FILE> +<SUBSECTION> +GByteArray +g_byte_array_new +g_byte_array_steal +g_byte_array_new_take +g_byte_array_sized_new +g_byte_array_ref +g_byte_array_unref +g_byte_array_append +g_byte_array_prepend +g_byte_array_remove_index +g_byte_array_remove_index_fast +g_byte_array_remove_range +g_byte_array_sort +g_byte_array_sort_with_data +g_byte_array_set_size +g_byte_array_free +g_byte_array_free_to_bytes + +<SUBSECTION> +GBytes +g_bytes_new +g_bytes_new_take +g_bytes_new_static +g_bytes_new_with_free_func +g_bytes_new_from_bytes +g_bytes_get_data +g_bytes_get_size +g_bytes_hash +g_bytes_equal +g_bytes_compare +g_bytes_ref +g_bytes_unref +g_bytes_unref_to_data +g_bytes_unref_to_array + +<SUBSECTION Private> +g_bytes_get_type +</SECTION> + +<SECTION> +<TITLE>Balanced Binary Trees</TITLE> +<FILE>trees-binary</FILE> +GTree +g_tree_new +g_tree_ref +g_tree_unref +g_tree_new_with_data +g_tree_new_full +g_tree_insert +g_tree_replace +g_tree_nnodes +g_tree_height +g_tree_lookup +g_tree_lookup_extended +g_tree_foreach +g_tree_traverse +GTraverseFunc +g_tree_search +g_tree_remove +g_tree_steal +g_tree_destroy +</SECTION> + +<SECTION> +<TITLE>N-ary Trees</TITLE> +<FILE>trees-nary</FILE> +GNode +g_node_new +g_node_copy +GCopyFunc +g_node_copy_deep + +<SUBSECTION> +g_node_insert +g_node_insert_before +g_node_insert_after +g_node_append +g_node_prepend + +<SUBSECTION> +g_node_insert_data +g_node_insert_data_after +g_node_insert_data_before +g_node_append_data +g_node_prepend_data + +<SUBSECTION> +g_node_reverse_children +g_node_traverse +GTraverseType +GTraverseFlags +GNodeTraverseFunc +g_node_children_foreach +GNodeForeachFunc + +<SUBSECTION> +g_node_get_root +g_node_find +g_node_find_child +g_node_child_index +g_node_child_position +g_node_first_child +g_node_last_child +g_node_nth_child +g_node_first_sibling +g_node_next_sibling +g_node_prev_sibling +g_node_last_sibling + +<SUBSECTION> +G_NODE_IS_LEAF +G_NODE_IS_ROOT +g_node_depth +g_node_n_nodes +g_node_n_children +g_node_is_ancestor +g_node_max_height + +<SUBSECTION> +g_node_unlink +g_node_destroy +</SECTION> + + +<SECTION> +<TITLE>Quarks</TITLE> +<FILE>quarks</FILE> +GQuark +G_DEFINE_QUARK +g_quark_from_string +g_quark_from_static_string +g_quark_to_string +g_quark_try_string +g_intern_string +g_intern_static_string +</SECTION> + +<SECTION> +<TITLE>Keyed Data Lists</TITLE> +<FILE>datalist</FILE> +GData +g_datalist_init + +<SUBSECTION> +g_datalist_id_set_data +g_datalist_id_set_data_full +g_datalist_id_get_data +g_datalist_id_remove_data +g_datalist_id_remove_no_notify +GDuplicateFunc +g_datalist_id_dup_data +g_datalist_id_replace_data + +<SUBSECTION> +g_datalist_set_data +g_datalist_set_data_full +g_datalist_get_data +g_datalist_remove_data +g_datalist_remove_no_notify + +<SUBSECTION> +g_datalist_foreach +g_datalist_clear +g_datalist_set_flags +g_datalist_unset_flags +g_datalist_get_flags +G_DATALIST_FLAGS_MASK +</SECTION> + + +<SECTION> +<TITLE>Datasets</TITLE> +<FILE>datasets</FILE> +g_dataset_id_set_data +g_dataset_id_set_data_full +GDestroyNotify +g_dataset_id_get_data +g_dataset_id_remove_data +g_dataset_id_remove_no_notify + +<SUBSECTION> +g_dataset_set_data +g_dataset_set_data_full +g_dataset_get_data +g_dataset_remove_data +g_dataset_remove_no_notify + +<SUBSECTION> +g_dataset_foreach +GDataForeachFunc +g_dataset_destroy + +</SECTION> + +<SECTION> +<TITLE>Relations and Tuples</TITLE> +<FILE>relations</FILE> +GRelation +g_relation_new +g_relation_index +g_relation_insert +g_relation_exists +g_relation_count +g_relation_select +g_relation_delete +g_relation_destroy + +<SUBSECTION> +g_relation_print + +<SUBSECTION> +GTuples +g_tuples_destroy +g_tuples_index +</SECTION> + +<SECTION> +<TITLE>Caches</TITLE> +<FILE>caches</FILE> +GCache +g_cache_new +g_cache_insert +g_cache_remove +g_cache_destroy + +<SUBSECTION> +g_cache_key_foreach +g_cache_value_foreach + +<SUBSECTION> +GCacheDestroyFunc +GCacheDupFunc +GCacheNewFunc +</SECTION> + +<SECTION> +<TITLE>Random Numbers</TITLE> +<FILE>random_numbers</FILE> +GRand +g_rand_new_with_seed +g_rand_new_with_seed_array +g_rand_new +g_rand_copy +g_rand_free +g_rand_set_seed +g_rand_set_seed_array +g_rand_boolean +g_rand_int +g_rand_int_range +g_rand_double +g_rand_double_range +g_random_set_seed +g_random_boolean +g_random_int +g_random_int_range +g_random_double +g_random_double_range +</SECTION> + +<SECTION> +<TITLE>Character Set Conversion</TITLE> +<FILE>conversions</FILE> +g_convert +g_convert_with_fallback +GIConv +g_convert_with_iconv +G_CONVERT_ERROR +g_iconv_open +g_iconv +g_iconv_close +g_locale_to_utf8 +g_filename_to_utf8 +g_filename_from_utf8 +g_get_filename_charsets +g_filename_display_name +g_filename_display_basename +g_locale_from_utf8 +GConvertError + +<SUBSECTION> +g_get_charset +g_get_codeset +g_get_console_charset + +<SUBSECTION Private> +g_convert_error_quark +</SECTION> + +<SECTION> +<TITLE>Unicode Manipulation</TITLE> +<FILE>unicode</FILE> +gunichar +gunichar2 + +<SUBSECTION> +g_unichar_validate +g_unichar_isalnum +g_unichar_isalpha +g_unichar_iscntrl +g_unichar_isdefined +g_unichar_isdigit +g_unichar_isgraph +g_unichar_islower +g_unichar_ismark +g_unichar_isprint +g_unichar_ispunct +g_unichar_isspace +g_unichar_istitle +g_unichar_isupper +g_unichar_isxdigit +g_unichar_iswide +g_unichar_iswide_cjk +g_unichar_iszerowidth +g_unichar_toupper +g_unichar_tolower +g_unichar_totitle +g_unichar_digit_value +g_unichar_xdigit_value +g_unichar_compose +g_unichar_decompose +g_unichar_fully_decompose +G_UNICHAR_MAX_DECOMPOSITION_LENGTH +GUnicodeType +G_UNICODE_COMBINING_MARK +g_unichar_type +GUnicodeBreakType +g_unichar_break_type +g_unichar_combining_class +g_unicode_canonical_ordering +g_unicode_canonical_decomposition +g_unichar_get_mirror_char +GUnicodeScript +g_unichar_get_script +g_unicode_script_from_iso15924 +g_unicode_script_to_iso15924 + +<SUBSECTION> +g_utf8_next_char +g_utf8_get_char +g_utf8_get_char_validated +g_utf8_offset_to_pointer +g_utf8_pointer_to_offset +g_utf8_prev_char +g_utf8_find_next_char +g_utf8_find_prev_char +g_utf8_strlen +g_utf8_strncpy +g_utf8_strchr +g_utf8_strrchr +g_utf8_strreverse +g_utf8_substring +g_utf8_validate +g_utf8_validate_len +g_utf8_make_valid + +<SUBSECTION> +g_utf8_strup +g_utf8_strdown +g_utf8_casefold +g_utf8_normalize +GNormalizeMode +g_utf8_collate +g_utf8_collate_key +g_utf8_collate_key_for_filename + +<SUBSECTION> +g_utf8_to_utf16 +g_utf8_to_ucs4 +g_utf8_to_ucs4_fast +g_utf16_to_ucs4 +g_utf16_to_utf8 +g_ucs4_to_utf16 +g_ucs4_to_utf8 +g_unichar_to_utf8 + +<SUBSECTION Private> +g_utf8_skip +</SECTION> + +<SECTION> +<TITLE>I18N</TITLE> +<FILE>i18n</FILE> +<INCLUDE>glib.h,glib/gi18n.h</INCLUDE> +_ +Q_ +C_ +N_ +NC_ +g_dgettext +g_dcgettext +g_dngettext +g_dpgettext +g_dpgettext2 +g_strip_context +<SUBSECTION> +g_get_language_names +g_get_locale_variants +</SECTION> + +<SECTION> +<TITLE>Base64 Encoding</TITLE> +<FILE>base64</FILE> +g_base64_encode_step +g_base64_encode_close +g_base64_encode +g_base64_decode_step +g_base64_decode +g_base64_decode_inplace +</SECTION> + +<SECTION> +<TITLE>URI Functions</TITLE> +<FILE>gurifuncs</FILE> +G_URI_RESERVED_CHARS_ALLOWED_IN_PATH +G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT +G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO +G_URI_RESERVED_CHARS_GENERIC_DELIMITERS +G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS +g_uri_parse_scheme +g_uri_escape_string +g_uri_unescape_string +g_uri_unescape_segment +g_uri_list_extract_uris +g_filename_from_uri +g_filename_to_uri +</SECTION> + +<SECTION> +<TITLE>Data Checksums</TITLE> +<FILE>checksum</FILE> +GChecksumType +g_checksum_type_get_length +GChecksum +g_checksum_new +g_checksum_copy +g_checksum_free +g_checksum_reset +g_checksum_update +g_checksum_get_string +g_checksum_get_digest +<SUBSECTION> +g_compute_checksum_for_data +g_compute_checksum_for_string +g_compute_checksum_for_bytes +</SECTION> + +<SECTION> +<TITLE>Data HMACs</TITLE> +<FILE>hmac</FILE> +GHmac +g_hmac_new +g_hmac_copy +g_hmac_ref +g_hmac_unref +g_hmac_update +g_hmac_get_string +g_hmac_get_digest +<SUBSECTION> +g_compute_hmac_for_data +g_compute_hmac_for_string +g_compute_hmac_for_bytes +</SECTION> + +<SECTION> +<TITLE>Testing</TITLE> +<FILE>testing</FILE> +G_TEST_OPTION_ISOLATE_DIRS +g_test_minimized_result +g_test_maximized_result +g_test_init +g_test_initialized +g_test_quick +g_test_slow +g_test_thorough +g_test_perf +g_test_verbose +g_test_undefined +g_test_quiet +g_test_subprocess +g_test_run +GTestFunc +g_test_add_func +GTestDataFunc +g_test_add_data_func +g_test_add_data_func_full +g_test_add + +GTestFileType +g_test_build_filename +g_test_get_filename +g_test_get_dir + +g_test_fail +g_test_skip +g_test_incomplete +g_test_failed +g_test_message +g_test_bug_base +g_test_bug +g_test_summary +GTestLogFatalFunc +g_test_log_set_fatal_handler + +g_test_timer_start +g_test_timer_elapsed +g_test_timer_last + +g_test_queue_free +g_test_queue_destroy +g_test_queue_unref + +g_test_expect_message +g_test_assert_expected_messages + +GTestTrapFlags +GTestSubprocessFlags +g_test_trap_subprocess +g_test_trap_has_passed +g_test_trap_reached_timeout +g_test_trap_assert_passed +g_test_trap_assert_failed +g_test_trap_assert_stdout +g_test_trap_assert_stdout_unmatched +g_test_trap_assert_stderr +g_test_trap_assert_stderr_unmatched +g_test_trap_fork + +g_test_rand_bit +g_test_rand_int +g_test_rand_int_range +g_test_rand_double +g_test_rand_double_range + +g_assert +g_assert_not_reached + +g_assert_cmpstr +g_assert_cmpint +g_assert_cmpuint +g_assert_cmphex +g_assert_cmpfloat +g_assert_cmpfloat_with_epsilon +g_assert_cmpmem +g_assert_cmpvariant +g_assert_no_error +g_assert_error +g_assert_true +g_assert_false +g_assert_null +g_assert_nonnull +g_assert_no_errno +g_test_set_nonfatal_assertions + +GTestCase +GTestSuite +GTestFixtureFunc +g_test_create_case +g_test_create_suite +g_test_get_root +g_test_suite_add +g_test_suite_add_suite +g_test_run_suite + +<SUBSECTION Private> +g_test_trap_assertions +g_assertion_message +g_assertion_message_expr +g_assertion_message_cmpstr +g_assertion_message_cmpnum +g_assertion_message_error +g_test_assert_expected_messages_internal + +g_test_config_vars + +g_test_add_vtable +GTestConfig +GTestLogType +GTestLogMsg +GTestLogBuffer +GTestResult + +g_test_log_type_name +g_test_log_buffer_new +g_test_log_buffer_free +g_test_log_buffer_push +g_test_log_buffer_pop +g_test_log_msg_free +</SECTION> + +<SECTION> +<TITLE>GVariantType</TITLE> +<FILE>gvarianttype</FILE> +GVariantType +G_VARIANT_TYPE_BOOLEAN +G_VARIANT_TYPE_BYTE +G_VARIANT_TYPE_INT16 +G_VARIANT_TYPE_UINT16 +G_VARIANT_TYPE_INT32 +G_VARIANT_TYPE_UINT32 +G_VARIANT_TYPE_INT64 +G_VARIANT_TYPE_UINT64 +G_VARIANT_TYPE_HANDLE +G_VARIANT_TYPE_DOUBLE +G_VARIANT_TYPE_STRING +G_VARIANT_TYPE_OBJECT_PATH +G_VARIANT_TYPE_SIGNATURE +G_VARIANT_TYPE_VARIANT +G_VARIANT_TYPE_ANY +G_VARIANT_TYPE_BASIC +G_VARIANT_TYPE_MAYBE +G_VARIANT_TYPE_ARRAY +G_VARIANT_TYPE_TUPLE +G_VARIANT_TYPE_UNIT +G_VARIANT_TYPE_DICT_ENTRY +G_VARIANT_TYPE_DICTIONARY +G_VARIANT_TYPE_STRING_ARRAY +G_VARIANT_TYPE_OBJECT_PATH_ARRAY +G_VARIANT_TYPE_BYTESTRING +G_VARIANT_TYPE_BYTESTRING_ARRAY +G_VARIANT_TYPE_VARDICT + +<SUBSECTION> +G_VARIANT_TYPE +g_variant_type_free +g_variant_type_copy +g_variant_type_new + +<SUBSECTION> +g_variant_type_string_is_valid +g_variant_type_string_scan +g_variant_type_get_string_length +g_variant_type_peek_string +g_variant_type_dup_string + +<SUBSECTION> +g_variant_type_is_definite +g_variant_type_is_container +g_variant_type_is_basic +g_variant_type_is_maybe +g_variant_type_is_array +g_variant_type_is_tuple +g_variant_type_is_dict_entry +g_variant_type_is_variant + +<SUBSECTION> +g_variant_type_hash +g_variant_type_equal +g_variant_type_is_subtype_of + +<SUBSECTION> +g_variant_type_new_maybe +g_variant_type_new_array +g_variant_type_new_tuple +g_variant_type_new_dict_entry + +<SUBSECTION> +g_variant_type_element +g_variant_type_n_items +g_variant_type_first +g_variant_type_next +g_variant_type_key +g_variant_type_value +</SECTION> + +<SECTION> +<TITLE>GVariant</TITLE> +<FILE>gvariant</FILE> +GVariant +g_variant_unref +g_variant_ref +g_variant_ref_sink +g_variant_is_floating +g_variant_take_ref +g_variant_get_type +g_variant_get_type_string +g_variant_is_of_type +g_variant_is_container +g_variant_compare + +<SUBSECTION> +g_variant_classify +GVariantClass + +<SUBSECTION> +g_variant_check_format_string +g_variant_get +g_variant_get_va +g_variant_new +g_variant_new_va + +<SUBSECTION> +g_variant_new_boolean +g_variant_new_byte +g_variant_new_int16 +g_variant_new_uint16 +g_variant_new_int32 +g_variant_new_uint32 +g_variant_new_int64 +g_variant_new_uint64 +g_variant_new_handle +g_variant_new_double +g_variant_new_string +g_variant_new_take_string +g_variant_new_printf +g_variant_new_object_path +g_variant_is_object_path +g_variant_new_signature +g_variant_is_signature +g_variant_new_variant +g_variant_new_strv +g_variant_new_objv +g_variant_new_bytestring +g_variant_new_bytestring_array + +<SUBSECTION> +g_variant_get_boolean +g_variant_get_byte +g_variant_get_int16 +g_variant_get_uint16 +g_variant_get_int32 +g_variant_get_uint32 +g_variant_get_int64 +g_variant_get_uint64 +g_variant_get_handle +g_variant_get_double +g_variant_get_string +g_variant_dup_string +g_variant_get_variant +g_variant_get_strv +g_variant_dup_strv +g_variant_get_objv +g_variant_dup_objv +g_variant_get_bytestring +g_variant_dup_bytestring +g_variant_get_bytestring_array +g_variant_dup_bytestring_array + +<SUBSECTION> +g_variant_new_maybe +g_variant_new_array +g_variant_new_tuple +g_variant_new_dict_entry +g_variant_new_fixed_array + +<SUBSECTION> +g_variant_get_maybe +g_variant_n_children +g_variant_get_child_value +g_variant_get_child +g_variant_lookup_value +g_variant_lookup +g_variant_get_fixed_array + +<SUBSECTION> +g_variant_get_size +g_variant_get_data +g_variant_get_data_as_bytes +g_variant_store +g_variant_new_from_data +g_variant_new_from_bytes +g_variant_byteswap +g_variant_get_normal_form +g_variant_is_normal_form + +<SUBSECTION> +g_variant_hash +g_variant_equal + +<SUBSECTION> +g_variant_print +g_variant_print_string + +<SUBSECTION> +GVariantIter +g_variant_iter_copy +g_variant_iter_free +g_variant_iter_init +g_variant_iter_n_children +g_variant_iter_new +g_variant_iter_next_value +g_variant_iter_next +g_variant_iter_loop + +<SUBSECTION> +G_VARIANT_BUILDER_INIT +GVariantBuilder +g_variant_builder_unref +g_variant_builder_ref +g_variant_builder_new +g_variant_builder_init +g_variant_builder_clear +g_variant_builder_add_value +g_variant_builder_add +g_variant_builder_add_parsed +g_variant_builder_end +g_variant_builder_open +g_variant_builder_close + +<SUBSECTION> +G_VARIANT_DICT_INIT +GVariantDict +g_variant_dict_unref +g_variant_dict_ref +g_variant_dict_new +g_variant_dict_init +g_variant_dict_clear +g_variant_dict_contains +g_variant_dict_lookup +g_variant_dict_lookup_value +g_variant_dict_insert +g_variant_dict_insert_value +g_variant_dict_remove +g_variant_dict_end + +<SUBSECTION> +GVariantParseError +G_VARIANT_PARSE_ERROR +g_variant_parse +g_variant_new_parsed_va +g_variant_new_parsed +g_variant_parse_error_print_context + +<SUBSECTION Private> +g_variant_parse_error_quark +g_variant_parser_get_error_quark +g_variant_type_checked_ +g_variant_type_string_get_depth_ +</SECTION> + + +<SECTION> +<FILE>ghostutils</FILE> +<TITLE>Hostname Utilities</TITLE> +g_hostname_to_ascii +g_hostname_to_unicode +<SUBSECTION> +g_hostname_is_non_ascii +g_hostname_is_ascii_encoded +<SUBSECTION> +g_hostname_is_ip_address +</SECTION> + +<SECTION> +<FILE>uuid</FILE> +<TITLE>GUuid</TITLE> +g_uuid_string_is_valid +g_uuid_string_random +</SECTION> + +<SECTION> +<FILE>refcount</FILE> +grefcount +g_ref_count_init +g_ref_count_inc +g_ref_count_dec +g_ref_count_compare +<SUBSECTION> +gatomicrefcount +g_atomic_ref_count_init +g_atomic_ref_count_inc +g_atomic_ref_count_dec +g_atomic_ref_count_compare +</SECTION> + +<SECTION> +<FILE>rcbox</FILE> +g_rc_box_alloc +g_rc_box_alloc0 +g_rc_box_new +g_rc_box_new0 +g_rc_box_dup +g_rc_box_acquire +g_rc_box_release +g_rc_box_release_full +g_rc_box_get_size +</SECTION> + +<SECTION> +<FILE>arcbox</FILE> +g_atomic_rc_box_alloc +g_atomic_rc_box_alloc0 +g_atomic_rc_box_new +g_atomic_rc_box_new0 +g_atomic_rc_box_dup +g_atomic_rc_box_acquire +g_atomic_rc_box_release +g_atomic_rc_box_release_full +g_atomic_rc_box_get_size +</SECTION> + +<SECTION> +<FILE>refstring</FILE> +GRefString +g_ref_string_new +g_ref_string_new_intern +g_ref_string_new_len +g_ref_string_acquire +g_ref_string_release +g_ref_string_length +</SECTION>
diff --git a/docs/reference/glib/gtester-report.xml b/docs/reference/glib/gtester-report.xml new file mode 100644 index 0000000..eee9337 --- /dev/null +++ b/docs/reference/glib/gtester-report.xml
@@ -0,0 +1,78 @@ +<refentry id="gtester-report"> + +<refentryinfo> +<title>gtester-report</title> +<productname>GLib</productname> +<authorgroup> +<author> +<contrib>Developer</contrib> +<firstname>Tim</firstname> +<surname>Janik</surname> +</author> +</authorgroup> +</refentryinfo> + +<refmeta> +<refentrytitle>gtester-report</refentrytitle> +<manvolnum>1</manvolnum> +<refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>gtester-report</refname> +<refpurpose>test report formatting utility</refpurpose> +</refnamediv> + +<refsynopsisdiv> +<cmdsynopsis> +<command>gtester-report</command> +<arg choice="opt" rep="repeat">option</arg> +<arg>gtester-log</arg> +</cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>gtester-report</command> is a script which converts +the XML output generated by gtester into HTML. +</para> +<para>Since GLib 2.62, <command>gtester-report</command> is deprecated. Use +TAP for reporting test results instead, and feed it to the test harness provided +by your build system.</para> +</refsect1> + +<refsect1><title>Options</title> +<variablelist> + +<varlistentry> +<term><option>-h</option>, <option>--help</option></term> +<listitem><para> +print help and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-v</option>, <option>--version</option></term> +<listitem><para> +print version information and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-s</option>, <option>--subunit</option></term> +<listitem><para> +Output subunit. Needs python-subunit. +</para></listitem> +</varlistentry> + +</variablelist> +</refsect1> + +<refsect1><title>See also</title> +<para> +<citerefentry> +<refentrytitle>gtester</refentrytitle> +<manvolnum>1</manvolnum> +</citerefentry> +</para> +</refsect1> +</refentry>
diff --git a/docs/reference/glib/gtester.xml b/docs/reference/glib/gtester.xml new file mode 100644 index 0000000..5626d4d --- /dev/null +++ b/docs/reference/glib/gtester.xml
@@ -0,0 +1,192 @@ +<refentry id="gtester"> + +<refentryinfo> +<title>gtester</title> +<productname>GLib</productname> +<authorgroup> +<author> +<contrib>Developer</contrib> +<firstname>Tim</firstname> +<surname>Janik</surname> +</author> +<author> +<contrib>Developer</contrib> +<firstname>Sven</firstname> +<surname>Herzberg</surname> +</author> +</authorgroup> +</refentryinfo> + +<refmeta> +<refentrytitle>gtester</refentrytitle> +<manvolnum>1</manvolnum> +<refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>gtester</refname> +<refpurpose>test running utility</refpurpose> +</refnamediv> + +<refsynopsisdiv> +<cmdsynopsis> +<command>gtester</command> +<arg choice="opt" rep="repeat">OPTION</arg> +<arg>testprogram</arg> +</cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>gtester</command> is a utility to run unit tests that have +been written using the GLib test framework. +</para> +<para>Since GLib 2.62, <command>gtester-report</command> is deprecated. Use +TAP for reporting test results instead, and feed it to the test harness provided +by your build system.</para> +<para> +When called with the <option>-o</option> option, <command>gtester</command> +writes an XML report of the test results, which can be converted +into HTML using the <command>gtester-report</command> utility. +</para> +</refsect1> + +<refsect1><title>Options</title> +<variablelist> + +<varlistentry> +<term><option>-h</option>, <option>--help</option></term> +<listitem><para> +print help and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-v</option>, <option>--version</option></term> +<listitem><para> +print version information and exit +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--g-fatal-warnings</option></term> +<listitem><para> +make warnings fatal +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-k</option>, <option>--keep-going</option></term> +<listitem><para> +continue running after tests failed +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-l</option></term> +<listitem><para> +list paths of available test cases +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-m=<replaceable>MODE</replaceable></option></term> +<listitem><para> + run test cases in <replaceable>MODE</replaceable>, which can be one of: + + <variablelist> + <varlistentry> + <term><option>perf</option></term> + <listitem><para> + run performance tests + </para></listitem> + </varlistentry> + + <varlistentry> + <term><option>slow</option>, <option>thorough</option></term> + <listitem><para> + run slow tests, or repeat non-deterministic tests more often + </para></listitem> + </varlistentry> + + <varlistentry> + <term><option>quick</option></term> + <listitem><para> + do not run slow or performance tests, or do extra repeats + of non-deterministic tests (default) + </para></listitem> + </varlistentry> + + <varlistentry> + <term><option>undefined</option></term> + <listitem><para> + run test cases that deliberately provoke checks or assertion + failures, if implemented (default) + </para></listitem> + </varlistentry> + + <varlistentry> + <term><option>no-undefined</option></term> + <listitem><para> + do not run test cases that deliberately provoke checks or + assertion failures + </para></listitem> + </varlistentry> + </variablelist> + +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-p=<replaceable>TESTPATH</replaceable></option></term> +<listitem><para> +only run test cases matching <replaceable>TESTPATH</replaceable> +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-s=<replaceable>TESTPATH</replaceable></option></term> +<listitem><para> +skip test cases matching <replaceable>TESTPATH</replaceable> +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--seed=<replaceable>SEEDSTRING</replaceable></option></term> +<listitem><para> +run all test cases with random number seed <replaceable>SEEDSTRING</replaceable> +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-o=<replaceable>LOGFILE</replaceable></option></term> +<listitem><para> +write the test log to <replaceable>LOGFILE</replaceable> +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-q</option>, <option>--quiet</option></term> +<listitem><para> +suppress per test binary output +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--verbose</option></term> +<listitem><para> +report success per testcase +</para></listitem> +</varlistentry> + +</variablelist> +</refsect1> + +<refsect1><title>See also</title> +<para> +<citerefentry> +<refentrytitle>gtester-report</refentrytitle> +<manvolnum>1</manvolnum> +</citerefentry> +</para> +</refsect1> +</refentry>
diff --git a/docs/reference/glib/gvariant-text.xml b/docs/reference/glib/gvariant-text.xml new file mode 100644 index 0000000..55d476e --- /dev/null +++ b/docs/reference/glib/gvariant-text.xml
@@ -0,0 +1,622 @@ +<?xml version='1.0' encoding='utf-8'?> + +<refentry id='gvariant-text'> + <refmeta> + <refentrytitle>GVariant Text Format</refentrytitle> + </refmeta> + <refnamediv> + <refname>GVariant Text Format</refname> + <refpurpose>textual representation of GVariants</refpurpose> + </refnamediv> + + <refsect1> + <title>GVariant Text Format</title> + + <para> + This page attempts to document the GVariant text format as produced by + <link linkend='g-variant-print'><function>g_variant_print()</function></link> and parsed by the + <link linkend='g-variant-parse'><function>g_variant_parse()</function></link> family of functions. In most + cases the style closely resembles the formatting of literals in Python but there are some additions and + exceptions. + </para> + + <para> + The functions that deal with GVariant text format absolutely always deal in utf-8. Conceptually, GVariant + text format is a string of Unicode characters -- not bytes. Non-ASCII but otherwise printable Unicode + characters are not treated any differently from normal ASCII characters. + </para> + + <para> + The parser makes two passes. The purpose of the first pass is to determine the type of the value being + parsed. The second pass does the actual parsing. Based on the fact that all elements in an array have to + have the same type, GVariant is able to make some deductions that would not otherwise be possible. As an + example: + + <informalexample><programlisting>[[1, 2, 3], [4, 5, 6]]</programlisting></informalexample> + + is parsed as an array of arrays of integers (type '<literal>aai</literal>'), but + + <informalexample><programlisting>[[1, 2, 3], [4, 5, 6.0]]</programlisting></informalexample> + + is parsed as an array of arrays of doubles (type '<literal>aad</literal>'). + </para> + + <para> + As another example, GVariant is able to determine that + + <informalexample><programlisting>["hello", nothing]</programlisting></informalexample> + + is an array of maybe strings (type '<literal>ams</literal>'). + </para> + + <para> + What the parser accepts as valid input is dependent on context. The API permits for out-of-band type + information to be supplied to the parser (which will change its behaviour). This can be seen in the + GSettings and GDBus command line utilities where the type information is available from the schema or the + remote introspection information. The additional information can cause parses to succeed when they would not + otherwise have been able to (by resolving ambiguous type information) or can cause them to fail (due to + conflicting type information). Unless stated otherwise, the examples given in this section assume that no + out-of-band type data has been given to the parser. + </para> + </refsect1> + + <refsect1> + <title>Syntax Summary</title> + + <para> + The following table describes the rough meaning of symbols that may appear inside GVariant text format. + Each symbol is described in detail in its own section, including usage examples. + </para> + + <informaltable> + <tgroup cols='2'> + <colspec colname='col_0'/> + <colspec colname='col_1'/> + <tbody> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'>Symbol</emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'>Meaning</emphasis> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>true</literal></emphasis>, + <emphasis role='strong'><literal>false</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-booleans'>Booleans</link>. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>""</literal></emphasis>, + <emphasis role='strong'><literal>''</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + String literal. See <link linkend='gvariant-text-strings'>Strings</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + numbers + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + See <link linkend='gvariant-text-numbers'>Numbers</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>()</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-tuples'>Tuples</link>. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>[]</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-arrays'>Arrays</link>. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>{}</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-dictionaries'>Dictionaries and Dictionary Entries</link>. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal><></literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-variants'>Variants</link>. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>just</literal></emphasis>, + <emphasis role='strong'><literal>nothing</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-maybe-types'>Maybe Types</link>. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>@</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-type-annotations'>Type Annotations</link>. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + type keywords + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <literal>boolean</literal>, + <literal>byte</literal>, + <literal>int16</literal>, + <literal>uint16</literal>, + <literal>int32</literal>, + <literal>uint32</literal>, + <literal>handle</literal>, + <literal>int64</literal>, + <literal>uint64</literal>, + <literal>double</literal>, + <literal>string</literal>, + <literal>objectpath</literal>, + <literal>signature</literal> + </para> + <para> + See <link linkend='gvariant-text-type-annotations'>Type Annotations</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>b""</literal></emphasis>, + <emphasis role='strong'><literal>b''</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-bytestrings'>Bytestrings</link>. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>%</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gvariant-text-positional'>Positional Parameters</link>. + </para> + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + + <refsect2 id='gvariant-text-booleans'> + <title>Booleans</title> + <para> + The strings <literal>true</literal> and <literal>false</literal> are parsed as booleans. This is the only + way to specify a boolean value. + </para> + </refsect2> + + <refsect2 id='gvariant-text-strings'> + <title>Strings</title> + <para> + Strings literals must be quoted using <literal>""</literal> or <literal>''</literal>. The two are + completely equivalent (except for the fact that each one is unable to contain itself unescaped). + </para> + <para> + Strings are Unicode strings with no particular encoding. For example, to specify the character + <literal>é</literal>, you just write <literal>'é'</literal>. You could also give the Unicode codepoint of + that character (U+E9) as the escape sequence <literal>'\u00e9'</literal>. Since the strings are pure + Unicode, you should not attempt to encode the utf-8 byte sequence corresponding to the string using escapes; + it won't work and you'll end up with the individual characters corresponding to each byte. + </para> + <para> + Unicode escapes of the form <literal>\uxxxx</literal> and <literal>\Uxxxxxxxx</literal> are supported, in + hexadecimal. The usual control sequence escapes <literal>\a</literal>, <literal>\b</literal>, + <literal>\f</literal>, <literal>\n</literal>, <literal>\r</literal>, <literal>\t</literal> and + <literal>\v</literal> are supported. Additionally, a <literal>\</literal> before a newline character causes + the newline to be ignored. Finally, any other character following <literal>\</literal> is copied literally + (for example, <literal>\"</literal> or <literal>\\</literal>) but for forwards compatibility with future + additions you should only use this feature when necessary for escaping backslashes or quotes. + </para> + <para> + The usual octal and hexadecimal escapes <literal>\0nnn</literal> and <literal>\xnn</literal> are not + supported here. Those escapes are used to encode byte values and GVariant strings are Unicode. + </para> + <para> + Single-character strings are not interpreted as bytes. Bytes must be specified by their numerical value. + </para> + </refsect2> + + <refsect2 id='gvariant-text-numbers'> + <title>Numbers</title> + <para> + Numbers are given by default as decimal values. Octal and hex values can be given in the usual way (by + prefixing with <literal>0</literal> or <literal>0x</literal>). Note that GVariant considers bytes to be + unsigned integers and will print them as a two digit hexadecimal number by default. + </para> + <para> + Floating point numbers can also be given in the usual ways, including scientific and hexadecimal notations. + </para> + <para> + For lack of additional information, integers will be parsed as int32 values by default. If the number has a + point or an 'e' in it, then it will be parsed as a double precision floating point number by default. If + type information is available (either explicitly or inferred) then that type will be used instead. + </para> + <para> + Some examples: + </para> + <para> + <literal>5</literal> parses as the int32 value five. + </para> + <para> + <literal>37.5</literal> parses as a floating point value. + </para> + <para> + <literal>3.75e1</literal> parses the same as the value above. + </para> + <para> + <literal>uint64 7</literal> parses seven as a uint64. + See <link linkend='gvariant-text-type-annotations'>Type Annotations</link>. + </para> + </refsect2> + + <refsect2 id='gvariant-text-tuples'> + <title>Tuples</title> + <para> + Tuples are formed using the same syntax as Python. Here are some examples: + </para> + <para> + <literal>()</literal> parses as the empty tuple. + </para> + <para> + <literal>(5,)</literal> is a tuple containing a single value. + </para> + <para> + <literal>("hello", 42)</literal> is a pair. Note that values of different types are permitted. + </para> + </refsect2> + + <refsect2 id='gvariant-text-arrays'> + <title>Arrays</title> + <para> + Arrays are formed using the same syntax as Python uses for lists (which is arguably the term that GVariant + should have used). Note that, unlike Python lists, GVariant arrays are statically typed. This has two + implications. + </para> + <para> + First, all items in the array must have the same type. Second, the type of the array must be known, even in + the case that it is empty. This means that (unless there is some other way to infer it) type information + will need to be given explicitly for empty arrays. + </para> + <para> + The parser is able to infer some types based on the fact that all items in an array must have the same type. + See the examples below: + </para> + <para> + <literal>[1]</literal> parses (without additional type information) as a one-item array of signed integers. + </para> + <para> + <literal>[1, 2, 3]</literal> parses (similarly) as a three-item array. + </para> + <para> + <literal>[1, 2, 3.0]</literal> parses as an array of doubles. This is the most simple case of the type + inferencing in action. + </para> + <para> + <literal>[(1, 2), (3, 4.0)]</literal> causes the 2 to also be parsed as a double (but the 1 and 3 are still + integers). + </para> + <para> + <literal>["", nothing]</literal> parses as an array of maybe strings. The presence of + "<literal>nothing</literal>" clearly implies that the array elements are nullable. + </para> + <para> + <literal>[[], [""]]</literal> will parse properly because the type of the first (empty) array can be + inferred to be equal to the type of the second array (both are arrays of strings). + </para> + <para> + <literal>[b'hello', []]</literal> looks odd but will parse properly. + See <link linkend='gvariant-text-bytestrings'>Bytestrings</link> + </para> + <para> + And some examples of errors: + </para> + <para> + <literal>["hello", 42]</literal> fails to parse due to conflicting types. + </para> + <para> + <literal>[]</literal> will fail to parse without additional type information. + </para> + </refsect2> + + <refsect2 id='gvariant-text-dictionaries'> + <title>Dictionaries and Dictionary Entries</title> + <para> + Dictionaries and dictionary entries are both specified using the <literal>{}</literal> characters. + </para> + <para> + The dictionary syntax is more commonly used. This is what the printer elects to use in the normal case of + dictionary entries appearing in an array (aka "a dictionary"). The separate syntax for dictionary entries + is typically only used for when the entries appear on their own, outside of an array (which is valid but + unusual). Of course, you are free to use the dictionary entry syntax within arrays but there is no good + reason to do so (and the printer itself will never do so). Note that, as with arrays, the type of empty + dictionaries must be established (either explicitly or through inference). + </para> + <para> + The dictionary syntax is the same as Python's syntax for dictionaries. Some examples: + </para> + <para> + <literal>@a{sv} {}</literal> parses as the empty dictionary of everyone's favourite type. + </para> + <para> + <literal>@a{sv} []</literal> is the same as above (owing to the fact that dictionaries are really arrays). + </para> + <para> + <literal>{1: "one", 2: "two", 3: "three"}</literal> parses as a dictionary mapping integers to strings. + </para> + <para> + The dictionary entry syntax looks just like a pair (2-tuple) that uses braces instead of parens. The + presence of a comma immediately following the key differentiates it from the dictionary syntax (which + features a colon after the first key). Some examples: + </para> + <para> + <literal>{1, "one"}</literal> is a free-standing dictionary entry that can be parsed on its own or as part + of another container value. + </para> + <para> + <literal>[{1, "one"}, {2, "two"}, {3, "three"}]</literal> is exactly equivalent to the dictionary example + given above. + </para> + </refsect2> + + <refsect2 id='gvariant-text-variants'> + <title>Variants</title> + <para> + Variants are denoted using angle brackets (aka "XML brackets"), <literal><></literal>. They may not + be omitted. + </para> + <para> + Using <literal><></literal> effectively disrupts the type inferencing that occurs between array + elements. This can have positive and negative effects. + </para> + <para> + <literal>[<"hello">, <42>]</literal> will parse whereas <literal>["hello", 42]</literal> would + not. + </para> + <para> + <literal>[<['']>, <[]>]</literal> will fail to parse even though <literal>[[''], []]</literal> + parses successfully. You would need to specify <literal>[<['']>, <@as []>]</literal>. + </para> + <para> + <literal>{"title": <"frobit">, "enabled": <true>, "width": <800>}</literal> is an example of + perhaps the most pervasive use of both dictionaries and variants. + </para> + </refsect2> + + <refsect2 id='gvariant-text-maybe-types'> + <title>Maybe Types</title> + <para> + The syntax for specifying maybe types is inspired by Haskell. + </para> + <para> + The null case is specified using the keyword <literal>nothing</literal> and the non-null case is explicitly + specified using the keyword <literal>just</literal>. GVariant allows <literal>just</literal> to be omitted + in every case that it is able to unambiguously determine the intention of the writer. There are two cases + where it must be specified: + </para> + <itemizedlist> + <listitem> + <para>when using nested maybes, in order to specify the <literal>just nothing</literal> case</para> + </listitem> + <listitem> + <para> + to establish the nullability of the type of a value without explicitly specifying its full type + </para> + </listitem> + </itemizedlist> + <para> + Some examples: + </para> + <para> + <literal>just 'hello'</literal> parses as a non-null nullable string. + </para> + <para> + <literal>@ms 'hello'</literal> is the same (demonstrating how <literal>just</literal> can be dropped if the type is already + known). + </para> + <para> + <literal>nothing</literal> will not parse wtihout extra type information. + </para> + <para> + <literal>@ms nothing</literal> parses as a null nullable string. + </para> + <para> + <literal>[just 3, nothing]</literal> is an array of nullable integers + </para> + <para> + <literal>[3, nothing]</literal> is the same as the above (demonstrating another place were + <literal>just</literal> can be dropped). + </para> + <para> + <literal>[3, just nothing]</literal> parses as an array of maybe maybe integers (type + <literal>'ammi'</literal>). + </para> + </refsect2> + + <refsect2 id='gvariant-text-type-annotations'> + <title>Type Annotations</title> + <para> + Type annotations allow additional type information to be given to the parser. Depending on the context, + this type information can change the output of the parser, cause an error when parsing would otherwise have + succeeded or resolve an error when parsing would have otherwise failed. + </para> + <para> + Type annotations come in two forms: type codes and type keywords. + </para> + <para> + Type keywords can be seen as more verbose (and more legible) versions of a common subset of the type codes. + The type keywords <literal>boolean</literal>, <literal>byte</literal>, <literal>int16</literal>, + <literal>uint16</literal>, <literal>int32</literal>, <literal>uint32</literal>, <literal>handle</literal>, + <literal>int64</literal>, <literal>uint64</literal>, <literal>double</literal>, <literal>string</literal>, + <literal>objectpath</literal> and literal <literal>signature</literal> are each exactly equivalent to their + corresponding type code. + </para> + <para> + Type codes are an <literal>@</literal> ("at" sign) followed by a definite GVariant type string. Some + examples: + </para> + <para> + <literal>uint32 5</literal> causes the number to be parsed unsigned instead of signed (the default). + </para> + <para> + <literal>@u 5</literal> is the same + </para> + <para> + <literal>objectpath "/org/gnome/xyz"</literal> creates an object path instead of a normal string + </para> + <para> + <literal>@au []</literal> specifies the type of the empty array (which would not parse otherwise) + </para> + <para> + <literal>@ms ""</literal> indicates that a string value is meant to have a maybe type + </para> + </refsect2> + + <refsect2 id='gvariant-text-bytestrings'> + <title>Bytestrings</title> + <para> + The bytestring syntax is a piece of syntactic sugar meant to complement the bytestring APIs in GVariant. It + constructs arrays of non-nul bytes (type '<literal>ay</literal>') with a nul terminator at the end. These are + normal C strings with no particular encoding enforced, so the bytes may not be valid UTF-8. + Bytestrings are a special case of byte arrays; byte arrays (also type '<literal>ay</literal>'), in the general + case, can contain nul at any position, and need not end with nul. + </para> + <para> + Bytestrings are specified with either <literal>b""</literal> or <literal>b''</literal>. As with strings, + there is no fundamental difference between the two different types of quotes. + </para> + <para> + Bytestrings support the full range of escapes that you would expect (ie: those supported by + <link linkend='g-strcompress'><function>g_strcompress()</function></link>. This includes the normal control + sequence escapes (as mentioned in the section on strings) as well as octal and hexadecimal escapes of the + forms <literal>\0nnn</literal> and <literal>\xnn</literal>. + </para> + <para> + <literal>b'abc'</literal> is equivalent to <literal>[byte 0x61, 0x62, 0x63, 0]</literal>. + </para> + <para> + When formatting arrays of bytes, the printer will choose to display the array as a bytestring if it contains + a nul character at the end and no other nul bytes within. Otherwise, it is formatted as a normal array. + </para> + </refsect2> + + <refsect2 id='gvariant-text-positional'> + <title>Positional Parameters</title> + <para> + Positional parameters are not a part of the normal GVariant text format, but they are mentioned here because + they can be used with <link linkend='g-variant-new-parsed'><function>g_variant_new_parsed()</function></link>. + </para> + <para> + A positional parameter is indicated with a <literal>%</literal> followed by any valid + <link linkend='gvariant-format-strings'>GVariant Format String</link>. Variable arguments are collected as + specified by the format string and the resulting value is inserted at the current position. + </para> + <para> + This feature is best explained by example: + </para> + <informalexample><programlisting><![CDATA[char *t = "xyz"; +gboolean en = false; +GVariant *value; + +value = g_variant_new_parsed ("{'title': <%s>, 'enabled': <%b>}", t, en);]]></programlisting></informalexample> + <para> + This constructs a dictionary mapping strings to variants (type '<literal>a{sv}</literal>') with two items in + it. The key names are parsed from the string and the values for those keys are taken as variable arguments + parameters. + </para> + <para> + The arguments are always collected in the order that they appear in the string to be parsed. Format strings + that collect multiple arguments are permitted, so you may require more varargs parameters than the number of + <literal>%</literal> signs that appear. You can also give format strings that collect no arguments, but + there's no good reason to do so. + </para> + </refsect2> + </refsect1> +</refentry>
diff --git a/docs/reference/glib/gvariant-varargs.xml b/docs/reference/glib/gvariant-varargs.xml new file mode 100644 index 0000000..8529a28 --- /dev/null +++ b/docs/reference/glib/gvariant-varargs.xml
@@ -0,0 +1,1172 @@ +<?xml version='1.0' encoding='utf-8'?> + +<refentry id='gvariant-format-strings'> + <refmeta> + <refentrytitle>GVariant Format Strings</refentrytitle> + </refmeta> + <refnamediv> + <refname>GVariant Format Strings</refname> + <refpurpose>varargs conversion of GVariants</refpurpose> + </refnamediv> + + <refsect1> + <title>Variable Argument Conversions</title> + + <para> + This page attempts to document how to perform variable argument + conversions with GVariant. + </para> + <para> + Conversions occur according to format strings. A format string is a two-way mapping between a single + <link linkend='GVariant'>GVariant</link> value and one or more C values. + </para> + <para> + A conversion from C values into a <link linkend='GVariant'>GVariant</link> value is made using the + <link linkend='g-variant-new'><function>g_variant_new()</function></link> function. A conversion from a + <link linkend='GVariant'>GVariant</link> into C values is made using the + <link linkend='g-variant-get'><function>g_variant_get()</function></link> function. + </para> + </refsect1> + + <refsect1> + <title>Syntax</title> + + <para> + This section exhaustively describes all possibilities for GVariant format strings. There are no valid forms of + format strings other than those described here. Please note that the format string syntax is likely to expand in the + future. + </para> + <para> + Valid format strings have one of the following forms: + </para> + <itemizedlist> + <listitem> + <para>any type string</para> + </listitem> + <listitem> + <para> + a type string prefixed with a '<literal>@</literal>' + </para> + </listitem> + <listitem> + <para> + '<literal>&s</literal>' '<literal>&o</literal>', '<literal>&g</literal>', '<literal>^as</literal>', + '<literal>^a&s</literal>', '<literal>^ao</literal>', '<literal>^a&o</literal>','<literal>^ay</literal>', + '<literal>^&ay</literal>', '<literal>^aay</literal>' or '<literal>^a&ay</literal>'. + </para> + </listitem> + <listitem> + <para> + any format string, prefixed with an '<literal>m</literal>' + </para> + </listitem> + <listitem> + <para> + a sequence of zero or more format strings, concatenated and enclosed in parentheses + </para> + </listitem> + <listitem> + <para> + an opening brace, followed by two format strings, followed by a closing brace (subject to the constraint that the + first format string correspond to a type valid for use as the key type of a dictionary) + </para> + </listitem> + </itemizedlist> + </refsect1> + <refsect1> + <title>Symbols</title> + + <para> + The following table describes the rough meaning of symbols that may appear inside a GVariant format string. Each + symbol is described in detail in its own section, including usage examples. + </para> + + <informaltable> + <tgroup cols='2'> + <colspec colname='col_0'/> + <colspec colname='col_1'/> + <tbody> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'>Symbol</emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'>Meaning</emphasis> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>b</literal>, <literal>y</literal>, <literal>n</literal>, <literal>q</literal>, <literal>i</literal>, + <literal>u</literal>, <literal>x</literal>, <literal>t</literal>, <literal>h</literal>, <literal>d</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used for building or deconstructing boolean, byte and numeric types. See + <link linkend='gvariant-format-strings-numeric-types'>Numeric Types</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>s</literal>, <literal>o</literal>, <literal>g</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used for building or deconstructing string types. See + <link linkend='gvariant-format-strings-strings'>Strings</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>v</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used for building or deconstructing variant types. See + <link linkend='gvariant-format-strings-variants'>Variants</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>a</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used for building or deconstructing arrays. See + <link linkend='gvariant-format-strings-arrays'>Arrays</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>m</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used for building or deconstructing maybe types. See + <link linkend='gvariant-format-strings-maybe-types'>Maybe Types</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>()</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used for building or deconstructing tuples. See + <link linkend='gvariant-format-strings-tuples'>Tuples</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>{}</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used for building or deconstructing dictionary entries. See + <link linkend='gvariant-format-strings-dictionaries'>Dictionaries</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>@</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used as a prefix for a GVariant type string (not a prefix for a format string, so <literal>@as</literal> is + a valid format string but <literal>@^as</literal> is not). Denotes that a pointer to a + <link linkend='GVariant'>GVariant</link> should be used in place of the normal C type or types. For + <link linkend='g-variant-new'><function>g_variant_new()</function></link> this means that you must pass a + non-<link linkend='NULL:CAPS'><literal>NULL</literal></link> <code>(<link linkend='GVariant'>GVariant</link> + *)</code>; if it is a floating reference, ownership will be taken, as + if by using <link linkend="g-variant-ref-sink"><function>g_variant_ref_sink()</function></link>. + For <link linkend='g-variant-get'><function>g_variant_get()</function></link> this means that you + must pass a pointer to a <code>(<link linkend='GVariant'>GVariant</link> *)</code> for the value to be returned + by reference or <link linkend='NULL:CAPS'><literal>NULL</literal></link> to ignore the value. See + <link linkend='gvariant-format-strings-gvariant'><code>GVariant *</code></link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>*</literal>, <literal>?</literal>, <literal>r</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Exactly equivalent to <literal>@*</literal>, <literal>@?</literal> and <literal>@r</literal>. Provided only for + completeness so that all GVariant type strings can be used also as format strings. See <link + linkend='gvariant-format-strings-gvariant'><code>GVariant *</code></link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>&</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used as a prefix for a GVariant type string (not a prefix for a format string, so <literal>&s</literal> is + a valid format string but <literal>&@s</literal> is not). + Denotes that a C pointer to serialised data + should be used in place of the normal C type. See + <link linkend='gvariant-format-strings-pointers'>Pointers</link> below. + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'><literal>^</literal></emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + Used as a prefix on some specific types of format strings. See + <link linkend='gvariant-format-strings-convenience'>Convenience Conversions</link> below. + </para> + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + + + <refsect2 id='gvariant-format-strings-numeric-types'> + <title>Numeric Types</title> + <para> + <emphasis role='strong'> + Characters: <literal>b</literal>, <literal>y</literal>, <literal>n</literal>, <literal>q</literal>, + <literal>i</literal>, <literal>u</literal>, <literal>x</literal>, <literal>t</literal>, <literal>h</literal>, + <literal>d</literal> + </emphasis> + </para> + + <para> + Variable argument conversions from numeric types work in the most obvious way possible. Upon encountering one of + these characters, <link linkend='g-variant-new'><function>g_variant_new()</function></link> takes the equivalent C + type as an argument. <link linkend='g-variant-get'><function>g_variant_get()</function></link> takes a pointer to + the equivalent C type (or <link linkend='NULL:CAPS'><literal>NULL</literal></link> to ignore the value). + </para> + + <para> + The equivalent C types are as follows: + </para> + + <informaltable> + <tgroup cols='2'> + <colspec colname='col_0'/><colspec colname='col_1'/> + <tbody> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'>Character</emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'>Equivalent C type</emphasis> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>b</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gboolean'><type>gboolean</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>y</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='guchar'><type>guchar</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>n</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gint16'><type>gint16</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>q</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='guint16'><type>guint16</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>i</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gint32'><type>gint32</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>u</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='guint32'><type>guint32</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>x</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gint64'><type>gint64</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>t</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='guint64'><type>guint64</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>h</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gint32'><type>gint32</type></link> + </para> + </entry> + </row> + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>d</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <link linkend='gdouble'><type>gdouble</type></link> + </para> + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + + <anchor id='gvariant-varargs'/> + <para> + Note that in C, small integer types in variable argument lists are promoted up to <link + linkend='gint'><type>int</type></link> or <link linkend='guint'><type>unsigned int</type></link> as appropriate, and + read back accordingly. <link linkend='gint'><type>int</type></link> is 32 bits on every platform on which GLib is + currently supported. This means that you can use C expressions of type <link linkend='gint'><type>int</type></link> + with <link linkend='g-variant-new'><function>g_variant_new()</function></link> and format characters + '<literal>b</literal>', '<literal>y</literal>', '<literal>n</literal>', '<literal>q</literal>', + '<literal>i</literal>', '<literal>u</literal>' and '<literal>h</literal>'. Specifically, you can use integer + literals with these characters. + </para> + + <para> + When using the '<literal>x</literal>' and '<literal>t</literal>' characters, you must ensure that the value that you + provide is 64 bit. This means that you should use a cast or make use of the + <link linkend='G-GINT64-CONSTANT:CAPS'><literal>G_GINT64_CONSTANT</literal></link> or + <link linkend='G-GUINT64-CONSTANT:CAPS'><literal>G_GUINT64_CONSTANT</literal></link> macros. + </para> + + <para> + No type promotion occurs when using <link linkend='g-variant-get'><function>g_variant_get()</function></link> since + it operates with pointers. The pointers must always point to a memory region of exactly the correct size. + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariant *value1, *value2, *value3, *value4; + +value1 = g_variant_new ("y", 200); +value2 = g_variant_new ("b", TRUE); +value3 = g_variant_new ("d", 37.5): +value4 = g_variant_new ("x", G_GINT64_CONSTANT (998877665544332211)); + +{ + gdouble floating; + gboolean truth; + gint64 bignum; + + + g_variant_get (value1, "y", NULL); /* ignore the value. */ + g_variant_get (value2, "b", &truth); + g_variant_get (value3, "d", &floating); + g_variant_get (value4, "x", &bignum); +}]]></programlisting></informalexample> + </refsect3> + </refsect2> + + <refsect2 id='gvariant-format-strings-strings'> + <title>Strings</title> + <para> + <emphasis role='strong'> + Characters: <literal>s</literal>, <literal>o</literal>, <literal>g</literal> + </emphasis> + </para> + + <para> + String conversions occur to and from standard nul-terminated C strings. Upon encountering an + '<literal>s</literal>', '<literal>o</literal>' or '<literal>g</literal>' in a format string, + <link linkend='g-variant-new'><function>g_variant_new()</function></link> takes a <code>(const + <link linkend='gchar'>gchar</link> *)</code> and makes a copy of it. + <link linkend='NULL:CAPS'><literal>NULL</literal></link> is not a valid string; use + <link linkend='gvariant-format-strings-maybe-types'>maybe types</link> to encode that. If the '<literal>o</literal>' or + '<literal>g</literal>' characters are used, care must be taken to ensure that the passed string is a valid DBus + object path or DBus type signature, respectively. + </para> + <para> + Upon encounting '<literal>s</literal>', '<literal>o</literal>' or '<literal>g</literal>', <link + linkend='g-variant-get'><function>g_variant_get()</function></link> takes a pointer to a + <code>(<link linkend='gchar'>gchar</link> *)</code> (ie: <code>(<link linkend='gchar'>gchar</link> **)</code>) and + sets it to a newly-allocated copy of the string. It is appropriate to free this copy using + <link linkend='g-free'><function>g_free()</function></link>. + <link linkend='NULL:CAPS'><literal>NULL</literal></link> may also be passed to indicate that the value of the + string should be ignored (in which case no copy is made). + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariant *value1, *value2, *value3; + +value1 = g_variant_new ("s", "hello world!"); +value2 = g_variant_new ("o", "/must/be/a/valid/path"); +value3 = g_variant_new ("g", "iias"); + +#if 0 + g_variant_new ("s", NULL); /* not valid: NULL is not a string. */ +#endif + +{ + gchar *result; + + g_variant_get (value1, "s", &result); + g_print ("It was '%s'\n", result); + g_free (result); +}]]></programlisting></informalexample> + </refsect3> + </refsect2> + + <refsect2 id='gvariant-format-strings-variants'> + <title>Variants</title> + <para> + <emphasis role='strong'> + Characters: <literal>v</literal> + </emphasis> + </para> + + <para> + Upon encountering a '<literal>v</literal>', + <link linkend='g-variant-new'><function>g_variant_new()</function></link> takes a <code>(<link + linkend='GVariant'>GVariant</link> *)</code>. The value of the + <link linkend='GVariant'><type>GVariant</type></link> is used as the contents of the variant value. + </para> + <para> + Upon encountering a '<literal>v</literal>', <link + linkend='g-variant-get'><function>g_variant_get()</function></link> takes a pointer to a + <code>(<link linkend='GVariant'>GVariant</link> *)</code> (ie: <code>(<link linkend='GVariant'>GVariant</link> **) + </code>). It is set to a new reference to a <link linkend='GVariant'><type>GVariant</type></link> instance + containing the contents of the variant value. It is appropriate to free this reference using + <link linkend='g-variant-unref'><function>g_variant_unref()</function></link>. + <link linkend='NULL:CAPS'><literal>NULL</literal></link> may also be passed to indicate that the value should be + ignored (in which case no new reference is created). + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariant *x, *y; + +/* the following two lines are equivalent: */ +x = g_variant_new ("v", y); +x = g_variant_new_variant (y); + +/* as are these: */ +g_variant_get (x, "v", &y); +y = g_variant_get_variant (x);]]></programlisting></informalexample> + </refsect3> + </refsect2> + + + <refsect2 id='gvariant-format-strings-arrays'> + <title>Arrays</title> + <para> + <emphasis role='strong'> + Characters: <literal>a</literal> + </emphasis> + </para> + + <para> + Upon encountering an '<literal>a</literal>' character followed by a type string, + <link linkend='g-variant-new'><function>g_variant_new()</function></link> will take a + <code>(<link linkend='GVariantBuilder'>GVariantBuilder</link> *)</code> that has been created as an array builder + for an array of the type given in the type string. The builder will have + <link linkend='g-variant-builder-end'><function>g_variant_builder_end()</function></link> called on it and the + result will be used as the value. As a special exception, if the given type string is a definite type, then + <link linkend='NULL:CAPS'><literal>NULL</literal></link> may be given to mean an empty array of that type. + </para> + + <para> + Upon encountering an '<literal>a</literal>' character followed by a type string, + <link linkend='g-variant-get'><function>g_variant_get()</function></link> will take a pointer to a + <code>(<link linkend='GVariantIter'>GVariantIter</link> *)</code> (ie: + <code>(<link linkend='GVariantIter'>GVariantIter</link> **)</code>). + A new heap-allocated iterator is created and returned, initialised for iterating over the elements of the array. + This iterator should be freed when you are done with it, using + <link linkend='g-variant-iter-free'><function>g_variant_iter_free()</function></link>. + <link linkend='NULL:CAPS'><literal>NULL</literal></link> may also be given to indicate that the value of the array + should be ignored. + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariantBuilder *builder; +GVariant *value; + +builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); +g_variant_builder_add (builder, "s", "when"); +g_variant_builder_add (builder, "s", "in"); +g_variant_builder_add (builder, "s", "the"); +g_variant_builder_add (builder, "s", "course"); +value = g_variant_new ("as", builder); +g_variant_builder_unref (builder); + +{ + GVariantIter *iter; + gchar *str; + + g_variant_get (value, "as", &iter); + while (g_variant_iter_loop (iter, "s", &str)) + g_print ("%s\n", str); + g_variant_iter_free (iter); +} + +g_variant_unref (value);]]></programlisting></informalexample> + </refsect3> + </refsect2> + + <refsect2 id='gvariant-format-strings-maybe-types'> + <title>Maybe Types</title> + <para> + <emphasis role='strong'> + Characters: <literal>m</literal> + </emphasis> + </para> + <para> + Maybe types are handled in two separate ways depending on the format string that follows the + '<literal>m</literal>'. The method that is used currently depends entirely on the character immediately following the + '<literal>m</literal>'. + </para> + + <para> + The first way is used with format strings starting with '<literal>a</literal>', '<literal>s</literal>', + '<literal>o</literal>', '<literal>g</literal>', '<literal>v</literal>', '<literal>@</literal>', + '<literal>*</literal>', '<literal>?</literal>', '<literal>r</literal>', '<literal>&</literal>', or + '<literal>^</literal>'. In all of these cases, for non-maybe types, + <link linkend='g-variant-new'><function>g_variant_new()</function></link> takes a pointer to a + non-<link linkend='NULL:CAPS'><literal>NULL</literal></link> value and + <link linkend='g-variant-get'><function>g_variant_get()</function></link> returns (by reference) a + non-<link linkend='NULL:CAPS'><literal>NULL</literal></link> pointer. When any of these format strings are + prefixed with an '<literal>m</literal>', the type of arguments that are collected does not change in any way, but + <link linkend='NULL:CAPS'><literal>NULL</literal></link> becomes a permissible value, to indicate the Nothing case. + </para> + <para> + Note that the "special exception" introduced in the array section for constructing empty arrays is ignored + here. Using a <literal>NULL</literal> pointer with the format string '<literal>mas</literal>' constructs + the Nothing value -- not an empty array. + </para> + <para> + The second way is used with all other format strings. For + <link linkend='g-variant-new'><function>g_variant_new()</function></link> an additional + <link linkend='gboolean'><type>gboolean</type></link> argument is collected and for + <link linkend='g-variant-get'><function>g_variant_get()</function></link> an additional + <code>(<link linkend='gboolean'>gboolean</link> *)</code>. Following this argument, the arguments that are normally + collected for the equivalent non-maybe type will be collected. + </para> + <para> + If <link linkend='FALSE:CAPS'><literal>FALSE</literal></link> is given to + <link linkend='g-variant-new'><function>g_variant_new()</function></link> then the Nothing value is constructed and + the collected arguments are ignored. Otherwise (if <link linkend='TRUE:CAPS'><literal>TRUE</literal></link> was + given), the arguments are used in the normal way to create the Just value. + </para> + <para> + If <link linkend='NULL:CAPS'><literal>NULL</literal></link> is given to + <link linkend='g-variant-get'><function>g_variant_get()</function></link> then the value is ignored. If a + non-<link linkend='NULL:CAPS'><literal>NULL</literal></link> pointer is given then it is used to return by reference + whether the value was Just. In the case that the value was Just, the + <link linkend='gboolean'><type>gboolean</type></link> will be set to + <link linkend='TRUE:CAPS'><literal>TRUE</literal></link> and the value will be stored in the arguments in the usual + way. In the case that the value was Nothing, the <link linkend='gboolean'><type>gboolean</type></link> will be set to + <link linkend='FALSE:CAPS'><literal>FALSE</literal></link> and the arguments will be collected in the normal way + but have their values set to binary zero. + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariant *value1, *value2, *value3, *value4, *value5, *value6; +value1 = g_variant_new ("ms", "Hello world"); +value2 = g_variant_new ("ms", NULL); +value3 = g_variant_new ("(m(ii)s)", TRUE, 123, 456, "Done"); +value4 = g_variant_new ("(m(ii)s)", FALSE, -1, -1, "Done"); /* both '-1' are ignored. */ +value5 = g_variant_new ("(m@(ii)s)", NULL, "Done"); + +{ + GVariant *contents; + const gchar *cstr; + gboolean just; + gint32 x, y; + gchar *str; + + g_variant_get (value1, "ms", &str); + if (str != NULL) + g_print ("str: %s\n", str); + else + g_print ("it was null\n"); + g_free (str); + + + g_variant_get (value2, "m&s", &cstr); + if (cstr != NULL) + g_print ("str: %s\n", cstr); + else + g_print ("it was null\n"); + /* don't free 'cstr' */ + + + /* NULL passed for the gboolean *, but two 'gint32 *' still collected */ + g_variant_get (value3, "(m(ii)s)", NULL, NULL, NULL, &str); + g_print ("string is %s\n", str); + g_free (str); + + /* note: &s used, so g_free() not needed */ + g_variant_get (value4, "(m(ii)&s)", &just, &x, &y, &cstr); + if (just) + g_print ("it was (%d, %d)\n", x, y); + else + g_print ("it was null\n"); + g_print ("string is %s\n", cstr); + /* don't free 'cstr' */ + + + g_variant_get (value5, "(m*s)", &contents, NULL); /* ignore the string. */ + if (contents != NULL) + { + g_variant_get (contents, "(ii)", &x, &y); + g_print ("it was (%d, %d)\n", x, y); + g_variant_unref (contents); + } + else + g_print ("it was null\n"); +}]]></programlisting></informalexample> + </refsect3> + </refsect2> + + <refsect2 id='gvariant-format-strings-tuples'> + <title>Tuples</title> + <para> + <emphasis role='strong'> + Characters: <code>()</code> + </emphasis> + </para> + + <para> + Tuples are handled by handling each item in the tuple, in sequence. Each item is handled in the usual way. + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariant *value1, *value2; + +value1 = g_variant_new ("(s(ii))", "Hello", 55, 77); +value2 = g_variant_new ("()"); + +{ + gchar *string; + gint x, y; + + g_variant_get (value1, "(s(ii))", &string, &x, &y); + g_print ("%s, %d, %d\n", string, x, y); + g_free (string); + + g_variant_get (value2, "()"); /* do nothing... */ +}]]></programlisting></informalexample> + </refsect3> + </refsect2> + + <refsect2 id='gvariant-format-strings-gvariant'> + <title>GVariant *</title> + <para> + <emphasis role='strong'> + Characters: <literal>@</literal>, <literal>*</literal>, <literal>?</literal>, <literal>r</literal> + </emphasis> + + </para> + <para> + Upon encountering a '<literal>@</literal>' in front of a type string, + <link linkend='g-variant-new'><function>g_variant_new()</function></link> takes a + non-<link linkend='NULL:CAPS'><literal>NULL</literal></link> pointer to a + <link linkend='GVariant'><type>GVariant</type></link> and uses its value directly instead of collecting arguments to + create the value. The provided <link linkend='GVariant'><type>GVariant</type></link> must have a type that matches the + type string following the '<literal>@</literal>'. '<literal>*</literal>' is + the same as '<literal>@*</literal>' (ie: take a <link linkend='GVariant'><type>GVariant</type></link> of any type). + '<literal>?</literal>' is the same as '<literal>@?</literal>' (ie: take a + <link linkend='GVariant'><type>GVariant</type></link> of any basic type). '<literal>r</literal>' is the same as + '<literal>@r</literal>' (ie: take a <link linkend='GVariant'><type>GVariant</type></link> of any tuple type). + </para> + <para> + Upon encountering a '<literal>@</literal>' in front of a type string, + <link linkend='g-variant-get'><function>g_variant_get()</function></link> + takes a pointer to a <code>(<link linkend='GVariant'>GVariant</link> *)</code> (ie: a + <code>(<link linkend='GVariant'>GVariant</link> **)</code>) and sets it to a new reference to a + <link linkend='GVariant'><type>GVariant</type></link> containing the value (instead of deconstructing the value into + C types in the usual way). <link linkend='NULL:CAPS'><literal>NULL</literal></link> can be given to ignore the + value. '<literal>*</literal>', '<literal>?</literal>' and '<literal>r</literal>' are handled in a way analogous to + what is stated above. + </para> + <para> + You can always use '<literal>*</literal>' as an alternative to '<literal>?</literal>', '<literal>r</literal>' or any + use of '<literal>@</literal>'. Using the other characters where possible is recommended, however, due to the + improvements in type safety and code self-documentation. + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariant *value1, *value2; + +value1 = g_variant_new ("(i@ii)", 44, g_variant_new_int32 (55), 66); + +/* note: consumes floating reference count on 'value1' */ +value2 = g_variant_new ("(@(iii)*)", value1, g_variant_new_string ("foo")); + +{ + const gchar *string; + GVariant *tmp; + gsize length; + gint x, y, z; + + g_variant_get (value2, "((iii)*)", &x, &y, &z, &tmp); + string = g_variant_get_string (tmp, &length); + g_print ("it is %d %d %d %s (length=%d)\n", x, y, z, string, (int) length); + g_variant_unref (tmp); + + /* quick way to skip all the values in a tuple */ + g_variant_get (value2, "(rs)", NULL, &string); /* or "(@(iii)s)" */ + g_print ("i only got the string: %s\n", string); + g_free (string); +}]]></programlisting></informalexample> + </refsect3> + </refsect2> + + <refsect2 id='gvariant-format-strings-dictionaries'> + <title>Dictionaries</title> + <para> + <emphasis role='strong'> + Characters: <code>{}</code> + </emphasis> + </para> + + <para> + Dictionary entries are handled by handling first the key, then the value. Each is handled in the usual way. + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariantBuilder *b; +GVariant *dict; + +b = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); +g_variant_builder_add (b, "{sv}", "name", g_variant_new_string ("foo")); +g_variant_builder_add (b, "{sv}", "timeout", g_variant_new_int32 (10)); +dict = g_variant_builder_end (b);]]></programlisting></informalexample> + </refsect3> + + <para> + To extract data from nested dictionaries you can go through a vardict. + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[GVariant *data; +gint value = 1; +gint max = 3; + +/* type (oa{sa{sv}) */ +data = g_variant_new_parsed ("(%o, {'brightness': {'value': <%i>, 'max': <%i>}})", + "/object/path", value, max); +{ + GVariant *params; + GVariant *p_brightness; + gchar *obj + gint p_max; + + g_variant_get (data, "(o@a{?*})", &obj, ¶ms); + g_print ("object_path: %s\n", obj); + + p_brightness = g_variant_lookup_value (params, "brightness", G_VARIANT_TYPE_VARDICT); + g_variant_lookup (p_brightness, "max", "i", &p_max); + g_print ("max: %d\n", p_max); +}]]></programlisting></informalexample> + </refsect3> + + </refsect2> + + <refsect2 id='gvariant-format-strings-pointers'> + <title>Pointers</title> + <para> + <emphasis role='strong'> + Characters: <code>&</code> + </emphasis> + </para> + + <para> + The '<code>&</code>' character is used to indicate that serialised data should be directly exchanged via a + pointer. + </para> + <para> + Currently, the only use for this character is when it is applied to a string (ie: '<literal>&s</literal>', + '<literal>&o</literal>' or '<code>&g</code>'). For + <link linkend='g-variant-new'><function>g_variant_new()</function></link> this has absolutely no effect. The string + is collected and duplicated normally. For <link linkend='g-variant-get'><function>g_variant_get()</function></link> + it means that instead of creating a newly allocated copy of the string, a pointer to the serialised data is + returned. This pointer should not be freed. Validity checks are performed to ensure that the string data will + always be properly nul-terminated. + </para> + + <refsect3> + <title>Examples</title> + <informalexample><programlisting> +<![CDATA[{ + const gchar *str; + GVariant *value; + + value = g_variant_new ("&s", "hello world"); + g_variant_get (value, "&s", &str); + g_print ("string is: %s\n", str); + /* no need to free str */ +}]]></programlisting></informalexample> + </refsect3> + </refsect2> + + <refsect2 id='gvariant-format-strings-convenience'> + <title>Convenience Conversions</title> + <para> + <emphasis role='strong'> + Characters: <literal>^</literal> + </emphasis> + </para> + + <para> + The '<literal>^</literal>' character currently supports conversion to and from bytestrings or to and from arrays + of strings or bytestrings. It does not support byte arrays. It has a number of forms. + </para> + + <para> + In all forms, when used with <link linkend='g-variant-new'><function>g_variant_new()</function></link> one + pointer value is collected from the variable arguments and passed to a function (as given in the table below). + The result of that function is used as the value for this position. When used with + <link linkend='g-variant-get'><function>g_variant_get()</function></link> one pointer value is produced by using + the function (given in the table) and returned by reference. + </para> + + <informaltable> + <tgroup cols='2'> + <colspec colname='col_0'/> + <colspec colname='col_1'/> + <colspec colname='col_2'/> + <tbody> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'>Conversion</emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + Used with <link linkend='g-variant-new'><function>g_variant_new()</function></link> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + Used with <link linkend='g-variant-get'><function>g_variant_get()</function></link> + </emphasis> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>^as</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1' morerows='1'> + <para> + equivalent to <link linkend='g-variant-new-strv'><function>g_variant_new_strv()</function></link> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + equivalent to <link linkend='g-variant-dup-strv'><function>g_variant_dup_strv()</function></link> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>^a&s</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + equivalent to <link linkend='g-variant-get-strv'><function>g_variant_get_strv()</function></link> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>^ao</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1' morerows='1'> + <para> + equivalent to <link linkend='g-variant-new-objv'><function>g_variant_new_objv()</function></link> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + equivalent to <link linkend='g-variant-dup-objv'><function>g_variant_dup_objv()</function></link> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>^a&o</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + equivalent to <link linkend='g-variant-get-objv'><function>g_variant_get_objv()</function></link> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>^ay</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1' morerows='1'> + <para> + equivalent to <link linkend='g-variant-new-bytestring'><function>g_variant_new_bytestring()</function></link> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + equivalent to <link linkend='g-variant-dup-bytestring'><function>g_variant_dup_bytestring()</function></link> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>^&ay</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + equivalent to <link linkend='g-variant-get-bytestring'><function>g_variant_get_bytestring()</function></link> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>^aay</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1' morerows='1'> + <para> + equivalent to <link linkend='g-variant-new-bytestring-array'><function>g_variant_new_bytestring_array()</function></link> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + equivalent to <link linkend='g-variant-dup-bytestring-array'><function>g_variant_dup_bytestring_array()</function></link> + </para> + </entry> + </row> + + <row rowsep='1'> + <entry colsep='1' rowsep='1'> + <para> + <emphasis role='strong'> + <literal>^a&ay</literal> + </emphasis> + </para> + </entry> + <entry colsep='1' rowsep='1'> + <para> + equivalent to <link linkend='g-variant-get-bytestring-array'><function>g_variant_get_bytestring_array()</function></link> + </para> + </entry> + </row> + + </tbody> + </tgroup> + </informaltable> + </refsect2> + </refsect1> +</refentry>
diff --git a/docs/reference/glib/mainloop-states.eps b/docs/reference/glib/mainloop-states.eps new file mode 100644 index 0000000..b3d159b --- /dev/null +++ b/docs/reference/glib/mainloop-states.eps
@@ -0,0 +1,306 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: mainloop-stages.eps +%%Creator: fig2dev Version 3.2 Patchlevel 3c +%%CreationDate: Wed Nov 29 12:23:52 2000 +%%For: otaylor@fresnel.labs.redhat.com (Owen Taylor) +%%BoundingBox: 0 0 503 291 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 291 moveto 0 0 lineto 503 0 lineto 503 291 lineto closepath clip newpath +-106.0 402.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +%%Page: 1 1 +10 setmiterlimit + 0.06000 0.06000 sc +% +% Fig objects follow +% +/Times-Roman ff 270.00 scf sf +9300 6225 m +gs 1 -1 sc (Initial[n+1]) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman ff 270.00 scf sf +9300 6540 m +gs 1 -1 sc (\(Recursion\)) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +15.000 slw + [60] 0 sd +n 1905 6000 m 1800 6000 1800 6420 105 arcto 4 {pop} repeat + 1800 6525 3120 6525 105 arcto 4 {pop} repeat + 3225 6525 3225 6105 105 arcto 4 {pop} repeat + 3225 6000 1905 6000 105 arcto 4 {pop} repeat + cp gs col0 s gr [] 0 sd +% Polyline + [60] 0 sd +gs clippath +3865 5498 m 3806 5431 l 3688 5535 l 3808 5490 l 3747 5602 l cp +3184 5976 m 3243 6043 l 3361 5939 l 3242 5985 l 3302 5872 l cp +eoclip +n 3225 6000 m + 3825 5475 l gs col0 s gr gr + [] 0 sd +% arrowhead +n 3302 5872 m 3242 5985 l 3361 5939 l 3302 5872 l cp gs 0.00 setgray ef gr col0 s +% arrowhead +n 3747 5602 m 3808 5490 l 3688 5535 l 3747 5602 l cp gs 0.00 setgray ef gr col0 s +% Polyline +n 4980 5775 m 4875 5775 4875 6270 105 arcto 4 {pop} repeat + 4875 6375 6870 6375 105 arcto 4 {pop} repeat + 6975 6375 6975 5880 105 arcto 4 {pop} repeat + 6975 5775 4980 5775 105 arcto 4 {pop} repeat + cp gs col0 s gr +% Polyline + [60] 0 sd +gs clippath +8457 5969 m 8515 5900 l 8394 5799 l 8458 5911 l 8337 5868 l cp +8042 5505 m 7984 5574 l 8105 5675 l 8042 5564 l 8162 5606 l cp +eoclip +n 8025 5550 m + 8475 5925 l gs col0 s gr gr + [] 0 sd +% arrowhead +n 8162 5606 m 8042 5564 l 8105 5675 l 8162 5606 l cp gs 0.00 setgray ef gr col0 s +% arrowhead +n 8337 5868 m 8458 5911 l 8394 5799 l 8337 5868 l cp gs 0.00 setgray ef gr col0 s +% Polyline + [60] 0 sd +n 8580 5850 m 8475 5850 8475 6570 105 arcto 4 {pop} repeat + 8475 6675 10020 6675 105 arcto 4 {pop} repeat + 10125 6675 10125 5955 105 arcto 4 {pop} repeat + 10125 5850 8580 5850 105 arcto 4 {pop} repeat + cp gs col0 s gr [] 0 sd +% Polyline +n 7155 3825 m 7050 3825 7050 4320 105 arcto 4 {pop} repeat + 7050 4425 9045 4425 105 arcto 4 {pop} repeat + 9150 4425 9150 3930 105 arcto 4 {pop} repeat + 9150 3825 7155 3825 105 arcto 4 {pop} repeat + cp gs col0 s gr +% Polyline +n 5055 2100 m 4950 2100 4950 2595 105 arcto 4 {pop} repeat + 4950 2700 6945 2700 105 arcto 4 {pop} repeat + 7050 2700 7050 2205 105 arcto 4 {pop} repeat + 7050 2100 5055 2100 105 arcto 4 {pop} repeat + cp gs col0 s gr +% Polyline +n 2730 3900 m 2625 3900 2625 4395 105 arcto 4 {pop} repeat + 2625 4500 4620 4500 105 arcto 4 {pop} repeat + 4725 4500 4725 4005 105 arcto 4 {pop} repeat + 4725 3900 2730 3900 105 arcto 4 {pop} repeat + cp gs col0 s gr +% Polyline + [60] 0 sd +n 8580 1875 m 8475 1875 8475 2295 105 arcto 4 {pop} repeat + 8475 2400 9645 2400 105 arcto 4 {pop} repeat + 9750 2400 9750 1980 105 arcto 4 {pop} repeat + 9750 1875 8580 1875 105 arcto 4 {pop} repeat + cp gs col0 s gr [] 0 sd +% Polyline + [60] 0 sd +gs clippath +8518 2419 m 8451 2358 l 8345 2474 l 8460 2416 l 8412 2534 l cp +8003 2848 m 8070 2909 l 8176 2793 l 8062 2852 l 8109 2733 l cp +eoclip +n 8047 2868 m + 8475 2400 l gs col0 s gr gr + [] 0 sd +% arrowhead +n 8109 2733 m 8062 2852 l 8176 2793 l 8109 2733 l cp gs 0.00 setgray ef gr col0 s +% arrowhead +n 8412 2534 m 8460 2416 l 8345 2474 l 8412 2534 l cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +gs clippath +3340 4475 m 3252 4494 l 3286 4648 l 3305 4522 l 3374 4629 l cp +eoclip +n 4875 6075 m 4874 6075 l 4872 6074 l 4868 6073 l 4861 6072 l 4852 6070 l + 4839 6067 l 4824 6064 l 4805 6059 l 4783 6054 l 4759 6048 l + 4731 6041 l 4701 6033 l 4669 6025 l 4635 6015 l 4600 6004 l + 4563 5993 l 4526 5981 l 4487 5967 l 4448 5953 l 4408 5937 l + 4367 5920 l 4326 5901 l 4284 5881 l 4241 5859 l 4198 5835 l + 4154 5809 l 4109 5781 l 4063 5749 l 4016 5715 l 3968 5678 l + 3920 5638 l 3872 5595 l 3825 5550 l 3780 5503 l 3737 5455 l + 3697 5407 l 3660 5359 l 3626 5312 l 3594 5266 l 3566 5221 l + 3540 5177 l 3516 5134 l 3494 5091 l 3474 5049 l 3455 5008 l + 3438 4967 l 3422 4927 l 3408 4888 l 3394 4849 l 3382 4812 l + 3371 4775 l 3360 4740 l 3350 4706 l 3342 4674 l 3334 4644 l + 3327 4616 l 3321 4592 l 3316 4570 l 3311 4551 l 3308 4536 l + 3305 4523 l 3303 4514 l + 3300 4500 l gs col0 s gr gr + +% arrowhead +0 slj +n 3374 4629 m 3305 4522 l 3286 4648 l 3374 4629 l cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +gs clippath +6943 6114 m 6978 6197 l 7123 6135 l 6995 6141 l 7087 6052 l cp +eoclip +n 8475 4500 m 8475 4501 l 8475 4503 l 8475 4508 l 8475 4515 l 8474 4525 l + 8474 4538 l 8473 4553 l 8472 4573 l 8470 4594 l 8468 4619 l + 8465 4646 l 8462 4675 l 8457 4706 l 8452 4739 l 8445 4773 l + 8437 4808 l 8427 4845 l 8416 4882 l 8403 4921 l 8388 4961 l + 8370 5002 l 8350 5045 l 8326 5090 l 8299 5137 l 8268 5186 l + 8232 5237 l 8192 5290 l 8148 5345 l 8100 5400 l 8057 5445 l + 8013 5490 l 7968 5533 l 7923 5573 l 7878 5612 l 7833 5649 l + 7789 5684 l 7745 5717 l 7701 5749 l 7658 5779 l 7615 5807 l + 7573 5834 l 7531 5861 l 7489 5886 l 7447 5910 l 7407 5933 l + 7366 5955 l 7327 5977 l 7288 5997 l 7250 6017 l 7214 6035 l + 7180 6052 l 7147 6068 l 7117 6083 l 7090 6096 l 7065 6108 l + 7043 6118 l 7025 6127 l 7010 6134 l 6998 6140 l 6989 6144 l + + 6975 6150 l gs col0 s gr gr + +% arrowhead +0 slj +n 7087 6052 m 6995 6141 l 7123 6135 l 7087 6052 l cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +gs clippath +8433 3848 m 8521 3831 l 8493 3676 l 8471 3803 l 8404 3693 l cp +eoclip +n 7050 2400 m 7051 2400 l 7054 2401 l 7058 2401 l 7066 2403 l 7076 2404 l + 7090 2407 l 7107 2410 l 7127 2414 l 7150 2418 l 7177 2424 l + 7206 2430 l 7238 2437 l 7271 2445 l 7306 2454 l 7343 2463 l + 7381 2474 l 7419 2486 l 7458 2499 l 7498 2513 l 7538 2528 l + 7579 2545 l 7621 2564 l 7663 2585 l 7706 2608 l 7750 2634 l + 7795 2662 l 7841 2694 l 7887 2728 l 7933 2766 l 7980 2807 l + 8025 2850 l 8068 2895 l 8109 2942 l 8147 2988 l 8181 3034 l + 8213 3080 l 8241 3125 l 8267 3169 l 8290 3212 l 8311 3254 l + 8330 3296 l 8347 3337 l 8362 3377 l 8376 3417 l 8389 3456 l + 8401 3494 l 8412 3532 l 8421 3569 l 8430 3604 l 8438 3637 l + 8445 3669 l 8451 3698 l 8457 3725 l 8461 3748 l 8465 3768 l + 8468 3785 l 8471 3799 l 8472 3809 l + 8475 3825 l gs col0 s gr gr + +% arrowhead +0 slj +n 8404 3693 m 8471 3803 l 8493 3676 l 8404 3693 l cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +gs clippath +4970 2442 m 4959 2353 l 4803 2372 l 4928 2403 l 4814 2461 l cp +eoclip +n 3375 3900 m 3375 3899 l 3376 3897 l 3377 3892 l 3378 3886 l 3380 3876 l + 3383 3863 l 3386 3848 l 3391 3828 l 3396 3806 l 3402 3781 l + 3409 3753 l 3417 3722 l 3425 3689 l 3435 3655 l 3446 3619 l + 3457 3581 l 3469 3543 l 3483 3504 l 3497 3464 l 3513 3423 l + 3530 3383 l 3549 3341 l 3569 3299 l 3591 3257 l 3615 3214 l + 3641 3170 l 3669 3125 l 3701 3080 l 3735 3034 l 3772 2988 l + 3812 2941 l 3855 2895 l 3900 2850 l 3950 2804 l 4001 2762 l + 4052 2723 l 4102 2687 l 4152 2655 l 4201 2625 l 4248 2599 l + 4295 2576 l 4340 2555 l 4385 2536 l 4429 2519 l 4472 2504 l + 4515 2490 l 4557 2477 l 4598 2466 l 4638 2456 l 4677 2447 l + 4715 2439 l 4751 2432 l 4784 2426 l 4815 2420 l 4843 2415 l + 4868 2411 l 4890 2408 l 4908 2406 l 4922 2404 l 4933 2402 l + + 4950 2400 l gs col0 s gr gr + +% arrowhead +0 slj +n 4814 2461 m 4928 2403 l 4803 2372 l 4814 2461 l cp gs 0.00 setgray ef gr col0 s +/Times-Roman ff 360.00 scf sf +5925 6225 m +gs 1 -1 sc (Initial[n]) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman ff 360.00 scf sf +8100 4275 m +gs 1 -1 sc (Dispatching) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman ff 360.00 scf sf +3675 4350 m +gs 1 -1 sc (Prepared) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman ff 360.00 scf sf +5925 2550 m +gs 1 -1 sc (Polling) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman ff 270.00 scf sf +4050 3300 m +gs 1 -1 sc (query\(\)) col0 sh gr +/Times-Roman ff 270.00 scf sf +7800 3225 m +gs 1 -1 sc (check\(\)) dup sw pop neg 0 rm col0 sh gr +/Times-Roman ff 270.00 scf sf +2475 6375 m +gs 1 -1 sc (Working) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman ff 270.00 scf sf +3900 5400 m +gs 1 -1 sc (prepare\(\)) col0 sh gr +/Times-Roman ff 270.00 scf sf +8025 5325 m +gs 1 -1 sc (dispatch\(\)) dup sw pop neg 0 rm col0 sh gr +/Times-Roman ff 270.00 scf sf +9150 2250 m +gs 1 -1 sc (Working) dup sw pop 2 div neg 0 rm col0 sh gr +$F2psEnd +rs
diff --git a/docs/reference/glib/mainloop-states.fig b/docs/reference/glib/mainloop-states.fig new file mode 100644 index 0000000..6acbedb --- /dev/null +++ b/docs/reference/glib/mainloop-states.fig
@@ -0,0 +1,65 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 8625 6000 9975 6600 +4 1 0 50 0 0 18 0.0000 4 240 1290 9300 6225 Initial[n+1]\001 +4 1 0 50 0 0 18 0.0000 4 255 1335 9300 6540 (Recursion)\001 +-6 +2 4 1 2 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3225 6525 3225 6000 1800 6000 1800 6525 3225 6525 +2 1 1 2 0 7 50 0 -1 4.000 0 0 -1 1 1 2 + 1 1 2.00 90.00 120.00 + 1 1 2.00 90.00 120.00 + 3225 6000 3825 5475 +2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 + 6975 6375 6975 5775 4875 5775 4875 6375 6975 6375 +2 1 1 2 0 7 50 0 -1 4.000 0 0 -1 1 1 2 + 1 1 2.00 90.00 120.00 + 1 1 2.00 90.00 120.00 + 8025 5550 8475 5925 +2 4 1 2 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 10125 6675 10125 5850 8475 5850 8475 6675 10125 6675 +2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 + 9150 4425 9150 3825 7050 3825 7050 4425 9150 4425 +2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 + 7050 2700 7050 2100 4950 2100 4950 2700 7050 2700 +2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 + 4725 4500 4725 3900 2625 3900 2625 4500 4725 4500 +2 4 1 2 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 9750 2400 9750 1875 8475 1875 8475 2400 9750 2400 +2 1 1 2 0 7 50 0 -1 4.000 0 0 -1 1 1 2 + 1 1 2.00 90.00 120.00 + 1 1 2.00 90.00 120.00 + 8047 2868 8475 2400 +3 2 0 2 0 7 50 0 -1 0.000 0 1 0 3 + 1 1 2.00 90.00 120.00 + 4875 6075 3825 5550 3300 4500 + 0.000 -1.000 0.000 +3 2 0 2 0 7 50 0 -1 0.000 0 1 0 3 + 1 1 2.00 90.00 120.00 + 8475 4500 8100 5400 6975 6150 + 0.000 -1.000 0.000 +3 2 0 2 0 7 50 0 -1 0.000 0 1 0 3 + 1 1 2.00 90.00 120.00 + 7050 2400 8025 2850 8475 3825 + 0.000 -1.000 0.000 +3 2 0 2 0 7 50 0 -1 0.000 0 1 0 3 + 1 1 2.00 90.00 120.00 + 3375 3900 3900 2850 4950 2400 + 0.000 -1.000 0.000 +4 1 0 50 0 0 24 0.0000 4 315 1290 5925 6225 Initial[n]\001 +4 1 0 50 0 0 24 0.0000 4 330 1770 8100 4275 Dispatching\001 +4 1 0 50 0 0 24 0.0000 4 330 1320 3675 4350 Prepared\001 +4 1 0 50 0 0 24 0.0000 4 330 1050 5925 2550 Polling\001 +4 0 0 50 0 0 18 0.0000 4 255 825 4050 3300 query()\001 +4 2 0 50 0 0 18 0.0000 4 255 855 7800 3225 check()\001 +4 1 0 50 0 0 18 0.0000 4 255 990 2475 6375 Working\001 +4 0 0 50 0 0 18 0.0000 4 255 1050 3900 5400 prepare()\001 +4 2 0 50 0 0 18 0.0000 4 255 1140 8025 5325 dispatch()\001 +4 1 0 50 0 0 18 0.0000 4 255 990 9150 2250 Working\001
diff --git a/docs/reference/glib/mainloop-states.gif b/docs/reference/glib/mainloop-states.gif new file mode 100644 index 0000000..0ba1a89 --- /dev/null +++ b/docs/reference/glib/mainloop-states.gif Binary files differ
diff --git a/docs/reference/glib/mainloop-states.png b/docs/reference/glib/mainloop-states.png new file mode 100644 index 0000000..4e9fc9d --- /dev/null +++ b/docs/reference/glib/mainloop-states.png Binary files differ
diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build new file mode 100644 index 0000000..62d95f7 --- /dev/null +++ b/docs/reference/glib/meson.build
@@ -0,0 +1,105 @@ +if get_option('gtk_doc') + subdir('xml') + + ignore_headers = [ + 'gallocator.h', + 'gdatasetprivate.h', + 'glibintl.h', + 'gbsearcharray.h', + 'glib-private.h', + 'gmoduleconf.h', + 'grcboxprivate.h', + 'gstdioprivate.h', + 'gthreadprivate.h', + 'gunibreak.h', + 'gunicomp.h', + 'gunidecomp.h', + 'gunichartables.h', + 'glib_probes.h', + 'glib_trace.h', + 'libcharset.h', + 'gdebug.h', + 'gprintfint.h', + 'gmirroringtable.h', + 'gscripttable.h', + 'glib-mirroring-tab', + 'gnulib', + 'pcre', + 'update-pcre', + 'gbytesprivate.h', + 'gvariant-internal.h', + 'gvariant-serialiser.h', + 'gvariant-core.h', + 'gvarianttypeinfo.h', + 'gwakeup.h', + 'gtranslit-data.h', + 'glib-init.h', + 'gconstructor.h', + 'valgrind.h', + 'gutilsprivate.h', + 'gvalgrind.h', + 'dirent.h', + ] + + docpath = join_paths(glib_datadir, 'gtk-doc', 'html') + version_conf = configuration_data() + version_conf.set('GLIB_VERSION', meson.project_version()) + configure_file( + input: 'version.xml.in', + output: 'version.xml', + configuration: version_conf + ) + + gnome.gtkdoc('glib', + main_xml : 'glib-docs.xml', + namespace : 'g', + mode : 'none', + src_dir : [ 'glib', 'gmodule' ], + dependencies : libglib_dep, + scan_args : gtkdoc_common_scan_args + [ + '--ignore-headers=' + ' '.join(ignore_headers), + ], + content_files : [ + 'cross.xml', + 'running.xml', + 'building.xml', + 'changes.xml', + 'compiling.xml', + 'programming.xml', + 'resources.xml', + 'regex-syntax.xml', + 'glib-gettextize.xml', + 'gtester.xml', + 'gtester-report.xml', + 'gvariant-varargs.xml', + 'gvariant-text.xml', + ], + expand_content_files : [ + 'compiling.xml', + ], + html_assets : [ + 'file-name-encodings.png', + 'mainloop-states.gif', + 'Sorted_binary_tree_breadth-first_traversal.svg', + 'Sorted_binary_tree_inorder.svg', + 'Sorted_binary_tree_postorder.svg', + 'Sorted_binary_tree_preorder.svg', + ], + fixxref_args: [ + '--html-dir=' + docpath, + ], + install: true, + check: true) +endif + +if get_option('man') + manpages = ['glib-gettextize', 'gtester', 'gtester-report'] + foreach page : manpages + custom_target(page + '-man', + input: page + '.xml', + output: page + '.1', + command: xsltproc_command, + install: true, + install_dir: man1_dir) + endforeach +endif
diff --git a/docs/reference/glib/programming.xml b/docs/reference/glib/programming.xml new file mode 100644 index 0000000..52df907 --- /dev/null +++ b/docs/reference/glib/programming.xml
@@ -0,0 +1,67 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<refentry id="glib-programming"> +<refmeta> +<refentrytitle>Writing GLib Applications</refentrytitle> +<manvolnum>3</manvolnum> +<refmiscinfo>GLib Library</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>Writing GLib Applications</refname> +<refpurpose> +General considerations when programming with GLib +</refpurpose> +</refnamediv> + +<refsect1> +<title>Writing GLib Applications</title> + +<refsect2> +<title>Threads</title> + +<para> +The general policy of GLib is that all functions are invisibly threadsafe +with the exception of data structure manipulation functions, where, if +you have two threads manipulating the <emphasis>same</emphasis> data +structure, they must use a lock to synchronize their operation. +</para> + +<para> +GLib creates a worker thread for its own purposes so GLib applications +will always have at least 2 threads. +</para> + +<para> +See the sections on <link linkend="glib-Threads">threads</link> and +<link linkend="glib-Thread-Pools">threadpools</link> for GLib APIs that +support multithreaded applications. +</para> + +</refsect2> + +<refsect2> +<title>Security</title> + +<para> +When writing code that runs with elevated privileges, it is important +to follow some basic rules of secure programming. David Wheeler has an +excellent book on this topic, +<ulink url="http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/index.html">Secure Programming for Linux and Unix HOWTO</ulink>. +</para> + +<para> +When it comes to GLib and its associated libraries, GLib and +GObject are generally fine to use in code that runs with elevated +privileges; they don't load modules (executable code in shared objects) +or run other programs 'behind your back'. GIO has to be used +carefully in privileged programs, see the <ulink url="http://developer.gnome.org/gio/stable/ch02.html">GIO documentation</ulink> for details. +</para> + +</refsect2> + +</refsect1> + +</refentry>
diff --git a/docs/reference/glib/regex-syntax.xml b/docs/reference/glib/regex-syntax.xml new file mode 100644 index 0000000..5dd9291 --- /dev/null +++ b/docs/reference/glib/regex-syntax.xml
@@ -0,0 +1,2531 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<refentry id="glib-regex-syntax" revision="11 Jul 2006"> + <refmeta> + <refentrytitle>Regular expression syntax</refentrytitle> + </refmeta> + + +<!-- +Based on the man page for pcrepattern. + +Remember to sync this document with the file docs/pcrepattern.3 in the +pcre package when upgrading to a newer version of pcre. + +In sync with PCRE 7.0 +--> + +<refnamediv> +<refname>Regular expression syntax</refname> +<refpurpose> +syntax and semantics of regular expressions supported by GRegex +</refpurpose> +</refnamediv> + +<refsect1> +<title>GRegex regular expression details</title> +<para> +A regular expression is a pattern that is matched against a +string from left to right. Most characters stand for themselves in a +pattern, and match the corresponding characters in the string. As a +trivial example, the pattern +</para> + +<programlisting> +The quick brown fox +</programlisting> + +<para> +matches a portion of a string that is identical to itself. When +caseless matching is specified (the <varname>G_REGEX_CASELESS</varname> flag), letters are +matched independently of case. +</para> + +<para> +The power of regular expressions comes from the ability to include +alternatives and repetitions in the pattern. These are encoded in the +pattern by the use of metacharacters, which do not stand for themselves +but instead are interpreted in some special way. +</para> + +<para> +There are two different sets of metacharacters: those that are recognized +anywhere in the pattern except within square brackets, and those +that are recognized in square brackets. Outside square brackets, the +metacharacters are as follows: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Metacharacters outside square brackets</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Character</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>\</entry> + <entry>general escape character with several uses</entry> + </row> + <row> + <entry>^</entry> + <entry>assert start of string (or line, in multiline mode)</entry> + </row> + <row> + <entry>$</entry> + <entry>assert end of string (or line, in multiline mode)</entry> + </row> + <row> + <entry>.</entry> + <entry>match any character except newline (by default)</entry> + </row> + <row> + <entry>[</entry> + <entry>start character class definition</entry> + </row> + <row> + <entry>|</entry> + <entry>start of alternative branch</entry> + </row> + <row> + <entry>(</entry> + <entry>start subpattern</entry> + </row> + <row> + <entry>)</entry> + <entry>end subpattern</entry> + </row> + <row> + <entry>?</entry> + <entry>extends the meaning of (, or 0/1 quantifier, or quantifier minimizer</entry> + </row> + <row> + <entry>*</entry> + <entry>0 or more quantifier</entry> + </row> + <row> + <entry>+</entry> + <entry>1 or more quantifier, also "possessive quantifier"</entry> + </row> + <row> + <entry>{</entry> + <entry>start min/max quantifier</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +Part of a pattern that is in square brackets is called a "character +class". In a character class the only metacharacters are: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Metacharacters inside square brackets</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Character</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>\</entry> + <entry>general escape character</entry> + </row> + <row> + <entry>^</entry> + <entry>negate the class, but only if the first character</entry> + </row> + <row> + <entry>-</entry> + <entry>indicates character range</entry> + </row> + <row> + <entry>[</entry> + <entry>POSIX character class (only if followed by POSIX syntax)</entry> + </row> + <row> + <entry>]</entry> + <entry>terminates the character class</entry> + </row> +</tbody> +</tgroup> +</table> +</refsect1> + +<refsect1> +<title>Backslash</title> +<para> +The backslash character has several uses. Firstly, if it is followed by +a non-alphanumeric character, it takes away any special meaning that +character may have. This use of backslash as an escape character +applies both inside and outside character classes. +</para> + +<para> +For example, if you want to match a * character, you write \* in the +pattern. This escaping action applies whether or not the following +character would otherwise be interpreted as a metacharacter, so it is +always safe to precede a non-alphanumeric with backslash to specify +that it stands for itself. In particular, if you want to match a +backslash, you write \\. +</para> + +<para> +If a pattern is compiled with the <varname>G_REGEX_EXTENDED</varname> +option, whitespace in the pattern (other than in a character class) and +characters between a # outside a character class and the next newline +are ignored. +An escaping backslash can be used to include a whitespace or # character +as part of the pattern. +</para> + +<para> +Note that the C compiler interprets backslash in strings itself, therefore +you need to duplicate all \ characters when you put a regular expression +in a C string, like "\\d{3}". +</para> + +<para> +If you want to remove the special meaning from a sequence of characters, +you can do so by putting them between \Q and \E. +The \Q...\E sequence is recognized both inside and outside character +classes. +</para> + +<refsect2> +<title>Non-printing characters</title> +<para> +A second use of backslash provides a way of encoding non-printing +characters in patterns in a visible manner. There is no restriction on the +appearance of non-printing characters, apart from the binary zero that +terminates a pattern, but when a pattern is being prepared by text +editing, it is usually easier to use one of the following escape +sequences than the binary character it represents: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Non-printing characters</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Escape</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>\a</entry> + <entry>alarm, that is, the BEL character (hex 07)</entry> + </row> + <row> + <entry>\cx</entry> + <entry>"control-x", where x is any character</entry> + </row> + <row> + <entry>\e</entry> + <entry>escape (hex 1B)</entry> + </row> + <row> + <entry>\f</entry> + <entry>formfeed (hex 0C)</entry> + </row> + <row> + <entry>\n</entry> + <entry>newline (hex 0A)</entry> + </row> + <row> + <entry>\r</entry> + <entry>carriage return (hex 0D)</entry> + </row> + <row> + <entry>\t</entry> + <entry>tab (hex 09)</entry> + </row> + <row> + <entry>\ddd</entry> + <entry>character with octal code ddd, or backreference</entry> + </row> + <row> + <entry>\xhh</entry> + <entry>character with hex code hh</entry> + </row> + <row> + <entry>\x{hhh..}</entry> + <entry>character with hex code hhh..</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +The precise effect of \cx is as follows: if x is a lower case letter, +it is converted to upper case. Then bit 6 of the character (hex 40) is +inverted. Thus \cz becomes hex 1A, but \c{ becomes hex 3B, while \c; +becomes hex 7B. +</para> + +<para> +After \x, from zero to two hexadecimal digits are read (letters can be +in upper or lower case). Any number of hexadecimal digits may appear +between \x{ and }, but the value of the character code +must be less than 2**31 (that is, the maximum hexadecimal value is +7FFFFFFF). If characters other than hexadecimal digits appear between +\x{ and }, or if there is no terminating }, this form of escape is not +recognized. Instead, the initial \x will be interpreted as a basic hexadecimal +escape, with no following digits, giving a character whose +value is zero. +</para> + +<para> +Characters whose value is less than 256 can be defined by either of the +two syntaxes for \x. There is no difference +in the way they are handled. For example, \xdc is exactly the same as +\x{dc}. +</para> + +<para> +After \0 up to two further octal digits are read. If there are fewer +than two digits, just those that are present are used. +Thus the sequence \0\x\07 specifies two binary zeros followed by a BEL +character (code value 7). Make sure you supply two digits after the +initial zero if the pattern character that follows is itself an octal +digit. +</para> + +<para> +The handling of a backslash followed by a digit other than 0 is complicated. +Outside a character class, GRegex reads it and any following digits as a +decimal number. If the number is less than 10, or if there +have been at least that many previous capturing left parentheses in the +expression, the entire sequence is taken as a back reference. A +description of how this works is given later, following the discussion +of parenthesized subpatterns. +</para> + +<para> +Inside a character class, or if the decimal number is greater than 9 +and there have not been that many capturing subpatterns, GRegex re-reads +up to three octal digits following the backslash, and uses them to generate +a data character. Any subsequent digits stand for themselves. For example: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Non-printing characters</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Escape</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>\040</entry> + <entry>is another way of writing a space</entry> + </row> + <row> + <entry>\40</entry> + <entry>is the same, provided there are fewer than 40 previous capturing subpatterns</entry> + </row> + <row> + <entry>\7</entry> + <entry>is always a back reference</entry> + </row> + <row> + <entry>\11</entry> + <entry>might be a back reference, or another way of writing a tab</entry> + </row> + <row> + <entry>\011</entry> + <entry>is always a tab</entry> + </row> + <row> + <entry>\0113</entry> + <entry>is a tab followed by the character "3"</entry> + </row> + <row> + <entry>\113</entry> + <entry>might be a back reference, otherwise the character with octal code 113</entry> + </row> + <row> + <entry>\377</entry> + <entry>might be a back reference, otherwise the byte consisting entirely of 1 bits</entry> + </row> + <row> + <entry>\81</entry> + <entry>is either a back reference, or a binary zero followed by the two characters "8" and "1"</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +Note that octal values of 100 or greater must not be introduced by a +leading zero, because no more than three octal digits are ever read. +</para> + +<para> +All the sequences that define a single character can be used both inside +and outside character classes. In addition, inside a character class, the +sequence \b is interpreted as the backspace character (hex 08), and the +sequences \R and \X are interpreted as the characters "R" and "X", respectively. +Outside a character class, these sequences have different meanings (see below). +</para> +</refsect2> + +<refsect2> +<title>Absolute and relative back references</title> +<para> +The sequence \g followed by a positive or negative number, optionally enclosed +in braces, is an absolute or relative back reference. Back references are +discussed later, following the discussion of parenthesized subpatterns. +</para> +</refsect2> + +<refsect2> +<title>Generic character types</title> + +<para> +Another use of backslash is for specifying generic character types. +The following are always recognized: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Generic characters</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Escape</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>\d</entry> + <entry>any decimal digit</entry> + </row> + <row> + <entry>\D</entry> + <entry>any character that is not a decimal digit</entry> + </row> + <row> + <entry>\s</entry> + <entry>any whitespace character</entry> + </row> + <row> + <entry>\S</entry> + <entry>any character that is not a whitespace character</entry> + </row> + <row> + <entry>\w</entry> + <entry>any "word" character</entry> + </row> + <row> + <entry>\W</entry> + <entry>any "non-word" character</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +Each pair of escape sequences partitions the complete set of characters +into two disjoint sets. Any given character matches one, and only one, +of each pair. +</para> + +<para> +These character type sequences can appear both inside and outside character +classes. They each match one character of the appropriate type. +If the current matching point is at the end of the passed string, all +of them fail, since there is no character to match. +</para> + +<para> +For compatibility with Perl, \s does not match the VT character (code +11). This makes it different from the POSIX "space" class. The \s +characters are HT (9), LF (10), FF (12), CR (13), and space (32). +</para> + +<para> +A "word" character is an underscore or any character less than 256 that +is a letter or digit.</para> + +<para> +Characters with values greater than 128 never match \d, +\s, or \w, and always match \D, \S, and \W. +</para> +</refsect2> + +<refsect2> +<title>Newline sequences</title> +<para>Outside a character class, the escape sequence \R matches any Unicode +newline sequence. +This particular group matches either the two-character sequence CR followed by +LF, or one of the single characters LF (linefeed, U+000A), VT (vertical tab, +U+000B), FF (formfeed, U+000C), CR (carriage return, U+000D), NEL (next +line, U+0085), LS (line separator, U+2028), or PS (paragraph separator, U+2029). +The two-character sequence is treated as a single unit that +cannot be split. Inside a character class, \R matches the letter "R".</para> +</refsect2> + +<refsect2> +<title>Unicode character properties</title> +<para> +To support generic character types there are three additional escape +sequences, they are: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Generic character types</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Escape</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>\p{xx}</entry> + <entry>a character with the xx property</entry> + </row> + <row> + <entry>\P{xx}</entry> + <entry>a character without the xx property</entry> + </row> + <row> + <entry>\X</entry> + <entry>an extended Unicode sequence</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +The property names represented by xx above are limited to the Unicode +script names, the general category properties, and "Any", which matches +any character (including newline). Other properties such as "InMusicalSymbols" +are not currently supported. Note that \P{Any} does not match any characters, +so always causes a match failure. +</para> + +<para> +Sets of Unicode characters are defined as belonging to certain scripts. A +character from one of these sets can be matched using a script name. For +example, \p{Greek} or \P{Han}. +</para> + +<para> +Those that are not part of an identified script are lumped together as +"Common". The current list of scripts can be found in the documentation for +the #GUnicodeScript enumeration. Script names for use with \p{} can be +found by replacing all spaces with underscores, e.g. for Linear B use +\p{Linear_B}. +</para> + +<para> +Each character has exactly one general category property, specified by a +two-letter abbreviation. For compatibility with Perl, negation can be specified +by including a circumflex between the opening brace and the property name. For +example, \p{^Lu} is the same as \P{Lu}. +</para> + +<para> +If only one letter is specified with \p or \P, it includes all the general +category properties that start with that letter. In this case, in the absence +of negation, the curly brackets in the escape sequence are optional; these two +examples have the same effect: +</para> + +<programlisting> +\p{L} +\pL +</programlisting> + +<para> +In addition to the two-letter category codes listed in the +documentation for the #GUnicodeType enumeration, the following +general category property codes are supported: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Property codes</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Code</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>C</entry> + <entry>Other</entry> + </row> + <row> + <entry>L</entry> + <entry>Letter</entry> + </row> + <row> + <entry>M</entry> + <entry>Mark</entry> + </row> + <row> + <entry>N</entry> + <entry>Number</entry> + </row> + <row> + <entry>P</entry> + <entry>Punctuation</entry> + </row> + <row> + <entry>S</entry> + <entry>Symbol</entry> + </row> + <row> + <entry>Z</entry> + <entry>Separator</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +The special property L& is also supported: it matches a character that has +the Lu, Ll, or Lt property, in other words, a letter that is not classified as +a modifier or "other". +</para> + +<para> +The long synonyms for these properties that Perl supports (such as \ep{Letter}) +are not supported by GRegex, nor is it permitted to prefix any of these +properties with "Is". +</para> + +<para> +No character that is in the Unicode table has the Cn (unassigned) property. +Instead, this property is assumed for any code point that is not in the +Unicode table. +</para> + +<para> +Specifying caseless matching does not affect these escape sequences. +For example, \p{Lu} always matches only upper case letters. +</para> + +<para> +The \X escape matches any number of Unicode characters that form an +extended Unicode sequence. \X is equivalent to +</para> + +<programlisting> +(?>\PM\pM*) +</programlisting> + +<para> +That is, it matches a character without the "mark" property, followed +by zero or more characters with the "mark" property, and treats the +sequence as an atomic group (see below). Characters with the "mark" +property are typically accents that affect the preceding character. +</para> + +<para> +Matching characters by Unicode property is not fast, because GRegex has +to search a structure that contains data for over fifteen thousand +characters. That is why the traditional escape sequences such as \d and +\w do not use Unicode properties. +</para> +</refsect2> + +<refsect2> +<title>Simple assertions</title> +<para> +The final use of backslash is for certain simple assertions. An +assertion specifies a condition that has to be met at a particular point in +a match, without consuming any characters from the string. The +use of subpatterns for more complicated assertions is described below. +The backslashed assertions are: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Simple assertions</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Escape</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>\b</entry> + <entry>matches at a word boundary</entry> + </row> + <row> + <entry>\B</entry> + <entry>matches when not at a word boundary</entry> + </row> + <row> + <entry>\A</entry> + <entry>matches at the start of the string</entry> + </row> + <row> + <entry>\Z</entry> + <entry>matches at the end of the string or before a newline at the end of the string</entry> + </row> + <row> + <entry>\z</entry> + <entry>matches only at the end of the string</entry> + </row> + <row> + <entry>\G</entry> + <entry>matches at first matching position in the string</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +These assertions may not appear in character classes (but note that \b +has a different meaning, namely the backspace character, inside a +character class). +</para> + +<para> +A word boundary is a position in the string where the current +character and the previous character do not both match \w or \W (i.e. +one matches \w and the other matches \W), or the start or end of the +string if the first or last character matches \w, respectively. +</para> + +<para> +The \A, \Z, and \z assertions differ from the traditional circumflex +and dollar (described in the next section) in that they only ever match +at the very start and end of the string, whatever options are +set. Thus, they are independent of multiline mode. These three assertions +are not affected by the <varname>G_REGEX_MATCH_NOTBOL</varname> or <varname>G_REGEX_MATCH_NOTEOL</varname> options, +which affect only the behaviour of the circumflex and dollar metacharacters. +However, if the start_position argument of a matching function is non-zero, +indicating that matching is to start at a point other than the beginning of +the string, \A can never match. The difference between \Z and \z is +that \Z matches before a newline at the end of the string as well at the +very end, whereas \z matches only at the end. +</para> + +<para> +The \G assertion is true only when the current matching position is at +the start point of the match, as specified by the start_position argument +to the matching functions. It differs from \A when the value of startoffset is +non-zero. +</para> + +<para> +Note, however, that the interpretation of \G, as the start of the +current match, is subtly different from Perl’s, which defines it as the +end of the previous match. In Perl, these can be different when the +previously matched string was empty. +</para> + +<para> +If all the alternatives of a pattern begin with \G, the expression is +anchored to the starting match position, and the "anchored" flag is set +in the compiled regular expression. +</para> +</refsect2> +</refsect1> + +<refsect1> +<title>Circumflex and dollar</title> +<para> +Outside a character class, in the default matching mode, the circumflex +character is an assertion that is true only if the current matching +point is at the start of the string. If the start_position argument to +the matching functions is non-zero, circumflex can never match if the +<varname>G_REGEX_MULTILINE</varname> option is unset. Inside a character class, circumflex +has an entirely different meaning (see below). +</para> + +<para> +Circumflex need not be the first character of the pattern if a number +of alternatives are involved, but it should be the first thing in each +alternative in which it appears if the pattern is ever to match that +branch. If all possible alternatives start with a circumflex, that is, +if the pattern is constrained to match only at the start of the string, +it is said to be an "anchored" pattern. (There are also other +constructs that can cause a pattern to be anchored.) +</para> + +<para> +A dollar character is an assertion that is true only if the current +matching point is at the end of the string, or immediately +before a newline at the end of the string (by default). Dollar need not +be the last character of the pattern if a number of alternatives are +involved, but it should be the last item in any branch in which it +appears. Dollar has no special meaning in a character class. +</para> + +<para> +The meaning of dollar can be changed so that it matches only at the +very end of the string, by setting the <varname>G_REGEX_DOLLAR_ENDONLY</varname> option at +compile time. This does not affect the \Z assertion. +</para> + +<para> +The meanings of the circumflex and dollar characters are changed if the +<varname>G_REGEX_MULTILINE</varname> option is set. When this is the case, +a circumflex matches immediately after internal newlines as well as at the +start of the string. It does not match after a newline that ends the string. +A dollar matches before any newlines in the string, as well as at the very +end, when <varname>G_REGEX_MULTILINE</varname> is set. When newline is +specified as the two-character sequence CRLF, isolated CR and LF characters +do not indicate newlines. +</para> + +<para> +For example, the pattern /^abc$/ matches the string "def\nabc" (where +\n represents a newline) in multiline mode, but not otherwise. Consequently, +patterns that are anchored in single line mode because all branches start with +^ are not anchored in multiline mode, and a match for circumflex is possible +when the <varname>start_position</varname> argument of a matching function +is non-zero. The <varname>G_REGEX_DOLLAR_ENDONLY</varname> option is ignored +if <varname>G_REGEX_MULTILINE</varname> is set. +</para> + +<para> +Note that the sequences \A, \Z, and \z can be used to match the start and +end of the string in both modes, and if all branches of a pattern start with +\A it is always anchored, whether or not <varname>G_REGEX_MULTILINE</varname> +is set. +</para> +</refsect1> + +<refsect1> +<title>Full stop (period, dot)</title> +<para> +Outside a character class, a dot in the pattern matches any one character +in the string, including a non-printing character, but not (by +default) newline. In UTF-8 a character might be more than one byte long. +</para> + +<para> +When a line ending is defined as a single character, dot never matches that +character; when the two-character sequence CRLF is used, dot does not match CR +if it is immediately followed by LF, but otherwise it matches all characters +(including isolated CRs and LFs). When any Unicode line endings are being +recognized, dot does not match CR or LF or any of the other line ending +characters. +</para> + +<para> +If the <varname>G_REGEX_DOTALL</varname> flag is set, dots match newlines +as well. The handling of dot is entirely independent of the handling of circumflex +and dollar, the only relationship being that they both involve newline +characters. Dot has no special meaning in a character class. +</para> + +<para> +The behaviour of dot with regard to newlines can be changed. If the +<varname>G_REGEX_DOTALL</varname> option is set, a dot matches any one +character, without exception. If newline is defined as the two-character +sequence CRLF, it takes two dots to match it. +</para> + +<para> +The handling of dot is entirely independent of the handling of circumflex and +dollar, the only relationship being that they both involve newlines. Dot has no +special meaning in a character class. +</para> +</refsect1> + +<refsect1> +<title>Matching a single byte</title> +<para> +Outside a character class, the escape sequence \C matches any one byte, +both in and out of UTF-8 mode. Unlike a dot, it always matches any line +ending characters. +The feature is provided in Perl in order to match individual bytes in +UTF-8 mode. Because it breaks up UTF-8 characters into individual +bytes, what remains in the string may be a malformed UTF-8 string. For +this reason, the \C escape sequence is best avoided. +</para> + +<para> +GRegex does not allow \C to appear in lookbehind assertions (described +below), because in UTF-8 mode this would make it impossible to calculate +the length of the lookbehind. +</para> +</refsect1> + +<refsect1> +<title>Square brackets and character classes</title> +<para> +An opening square bracket introduces a character class, terminated by a +closing square bracket. A closing square bracket on its own is not special. If a closing square bracket is required as a member of the class, +it should be the first data character in the class (after an initial +circumflex, if present) or escaped with a backslash. +</para> + +<para> +A character class matches a single character in the string. A matched character +must be in the set of characters defined by the class, unless the first +character in the class definition is a circumflex, in which case the +string character must not be in the set defined by the class. If a +circumflex is actually required as a member of the class, ensure it is +not the first character, or escape it with a backslash. +</para> + +<para> +For example, the character class [aeiou] matches any lower case vowel, +while [^aeiou] matches any character that is not a lower case vowel. +Note that a circumflex is just a convenient notation for specifying the +characters that are in the class by enumerating those that are not. A +class that starts with a circumflex is not an assertion: it still consumes +a character from the string, and therefore it fails if the current pointer +is at the end of the string. +</para> + +<para> +In UTF-8 mode, characters with values greater than 255 can be included +in a class as a literal string of bytes, or by using the \x{ escaping +mechanism. +</para> + +<para> +When caseless matching is set, any letters in a class represent both +their upper case and lower case versions, so for example, a caseless +[aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not +match "A", whereas a caseful version would. +</para> + +<para> +Characters that might indicate line breaks are never treated +in any special way when matching character classes, whatever line-ending +sequence is in use, and whatever setting of the <varname>G_REGEX_DOTALL</varname> +and <varname>G_REGEX_MULTILINE</varname> options is used. A class such as [^a] +always matches one of these characters. +</para> + +<para> +The minus (hyphen) character can be used to specify a range of characters in +a character class. For example, [d-m] matches any letter +between d and m, inclusive. If a minus character is required in a +class, it must be escaped with a backslash or appear in a position +where it cannot be interpreted as indicating a range, typically as the +first or last character in the class. +</para> + +<para> +It is not possible to have the literal character "]" as the end character +of a range. A pattern such as [W-]46] is interpreted as a class of +two characters ("W" and "-") followed by a literal string "46]", so it +would match "W46]" or "-46]". However, if the "]" is escaped with a +backslash it is interpreted as the end of range, so [W-\]46] is interpreted +as a class containing a range followed by two other characters. +The octal or hexadecimal representation of "]" can also be used to end +a range. +</para> + +<para> +Ranges operate in the collating sequence of character values. They can +also be used for characters specified numerically, for example +[\000-\037]. In UTF-8 mode, ranges can include characters whose values +are greater than 255, for example [\x{100}-\x{2ff}]. +</para> + +<para> +The character types \d, \D, \p, \P, \s, \S, \w, and \W may also appear +in a character class, and add the characters that they match to the +class. For example, [\dABCDEF] matches any hexadecimal digit. A +circumflex can conveniently be used with the upper case character types to +specify a more restricted set of characters than the matching lower +case type. For example, the class [^\W_] matches any letter or digit, +but not underscore. +</para> + +<para> +The only metacharacters that are recognized in character classes are +backslash, hyphen (only where it can be interpreted as specifying a +range), circumflex (only at the start), opening square bracket (only +when it can be interpreted as introducing a POSIX class name - see the +next section), and the terminating closing square bracket. However, +escaping other non-alphanumeric characters does no harm. +</para> +</refsect1> + +<refsect1> +<title>Posix character classes</title> +<para> +GRegex supports the POSIX notation for character classes. This uses names +enclosed by [: and :] within the enclosing square brackets. For example, +</para> + +<programlisting> +[01[:alpha:]%] +</programlisting> + +<para> +matches "0", "1", any alphabetic character, or "%". The supported class +names are +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Posix classes</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Name</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>alnum</entry> + <entry>letters and digits</entry> + </row> + <row> + <entry>alpha</entry> + <entry>letters</entry> + </row> + <row> + <entry>ascii</entry> + <entry>character codes 0 - 127</entry> + </row> + <row> + <entry>blank</entry> + <entry>space or tab only</entry> + </row> + <row> + <entry>cntrl</entry> + <entry>control characters</entry> + </row> + <row> + <entry>digit</entry> + <entry>decimal digits (same as \d)</entry> + </row> + <row> + <entry>graph</entry> + <entry>printing characters, excluding space</entry> + </row> + <row> + <entry>lower</entry> + <entry>lower case letters</entry> + </row> + <row> + <entry>print</entry> + <entry>printing characters, including space</entry> + </row> + <row> + <entry>punct</entry> + <entry>printing characters, excluding letters and digits</entry> + </row> + <row> + <entry>space</entry> + <entry>white space (not quite the same as \s)</entry> + </row> + <row> + <entry>upper</entry> + <entry>upper case letters</entry> + </row> + <row> + <entry>word</entry> + <entry>"word" characters (same as \w)</entry> + </row> + <row> + <entry>xdigit</entry> + <entry>hexadecimal digits</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +The "space" characters are HT (9), LF (10), VT (11), FF (12), CR (13), +and space (32). Notice that this list includes the VT character (code +11). This makes "space" different to \s, which does not include VT (for +Perl compatibility). +</para> + +<para> +The name "word" is a Perl extension, and "blank" is a GNU extension. +Another Perl extension is negation, which is indicated by a ^ character +after the colon. For example, +</para> + +<programlisting> +[12[:^digit:]] +</programlisting> + +<para> +matches "1", "2", or any non-digit. GRegex also recognize the +POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but +these are not supported, and an error is given if they are encountered. +</para> + +<para> +In UTF-8 mode, characters with values greater than 128 do not match any +of the POSIX character classes. +</para> +</refsect1> + +<refsect1> +<title>Vertical bar</title> +<para> +Vertical bar characters are used to separate alternative patterns. For +example, the pattern +</para> + +<programlisting> + gilbert|sullivan +</programlisting> + +<para> +matches either "gilbert" or "sullivan". Any number of alternatives may +appear, and an empty alternative is permitted (matching the empty +string). The matching process tries each alternative in turn, from +left to right, and the first one that succeeds is used. If the alternatives are within a subpattern (defined below), "succeeds" means matching the rest of the main pattern as well as the alternative in the subpattern. +</para> +</refsect1> + +<refsect1> +<title>Internal option setting</title> +<para> +The settings of the <varname>G_REGEX_CASELESS</varname>, <varname>G_REGEX_MULTILINE</varname>, <varname>G_REGEX_MULTILINE</varname>, +and <varname>G_REGEX_EXTENDED</varname> options can be changed from within the pattern by a +sequence of Perl-style option letters enclosed between "(?" and ")". The +option letters are +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Option settings</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Option</entry> + <entry>Flag</entry> + </row> +</thead> +<tbody> + <row> + <entry>i</entry> + <entry><varname>G_REGEX_CASELESS</varname></entry> + </row> + <row> + <entry>m</entry> + <entry><varname>G_REGEX_MULTILINE</varname></entry> + </row> + <row> + <entry>s</entry> + <entry><varname>G_REGEX_DOTALL</varname></entry> + </row> + <row> + <entry>x</entry> + <entry><varname>G_REGEX_EXTENDED</varname></entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +For example, (?im) sets caseless, multiline matching. It is also +possible to unset these options by preceding the letter with a hyphen, and a +combined setting and unsetting such as (?im-sx), which sets <varname>G_REGEX_CASELESS</varname> +and <varname>G_REGEX_MULTILINE</varname> while unsetting <varname>G_REGEX_DOTALL</varname> and <varname>G_REGEX_EXTENDED</varname>, +is also permitted. If a letter appears both before and after the +hyphen, the option is unset. +</para> + +<para> +When an option change occurs at top level (that is, not inside subpattern +parentheses), the change applies to the remainder of the pattern +that follows. +</para> + +<para> +An option change within a subpattern (see below for a description of subpatterns) +affects only that part of the current pattern that follows it, so +</para> + +<programlisting> +(a(?i)b)c +</programlisting> + +<para> +matches abc and aBc and no other strings (assuming <varname>G_REGEX_CASELESS</varname> is not +used). By this means, options can be made to have different settings +in different parts of the pattern. Any changes made in one alternative +do carry on into subsequent branches within the same subpattern. For +example, +</para> + +<programlisting> +(a(?i)b|c) +</programlisting> + +<para> +matches "ab", "aB", "c", and "C", even though when matching "C" the +first branch is abandoned before the option setting. This is because +the effects of option settings happen at compile time. There would be +some very weird behaviour otherwise. +</para> + +<para> +The options <varname>G_REGEX_UNGREEDY</varname> and +<varname>G_REGEX_EXTRA</varname> and <varname>G_REGEX_DUPNAMES</varname> +can be changed in the same way as the Perl-compatible options by using +the characters U, X and J respectively. +</para> +</refsect1> + +<refsect1> +<title>Subpatterns</title> +<para> +Subpatterns are delimited by parentheses (round brackets), which can be +nested. Turning part of a pattern into a subpattern does two things: +</para> + +<itemizedlist> +<listitem><para> +It localizes a set of alternatives. For example, the pattern +cat(aract|erpillar|) matches one of the words "cat", "cataract", or +"caterpillar". Without the parentheses, it would match "cataract", +"erpillar" or an empty string. +</para></listitem> +<listitem><para> +It sets up the subpattern as a capturing subpattern. This means +that, when the whole pattern matches, that portion of the +string that matched the subpattern can be obtained using <function>g_match_info_fetch()</function>. +Opening parentheses are counted from left to right (starting from 1, as +subpattern 0 is the whole matched string) to obtain numbers for the +capturing subpatterns. +</para></listitem> +</itemizedlist> + +<para> +For example, if the string "the red king" is matched against the pattern +</para> + +<programlisting> +the ((red|white) (king|queen)) +</programlisting> + +<para> +the captured substrings are "red king", "red", and "king", and are numbered 1, 2, and 3, respectively. +</para> + +<para> +The fact that plain parentheses fulfil two functions is not always +helpful. There are often times when a grouping subpattern is required +without a capturing requirement. If an opening parenthesis is followed +by a question mark and a colon, the subpattern does not do any capturing, +and is not counted when computing the number of any subsequent +capturing subpatterns. For example, if the string "the white queen" is +matched against the pattern +</para> + +<programlisting> +the ((?:red|white) (king|queen)) +</programlisting> + +<para> +the captured substrings are "white queen" and "queen", and are numbered +1 and 2. The maximum number of capturing subpatterns is 65535. +</para> + +<para> +As a convenient shorthand, if any option settings are required at the +start of a non-capturing subpattern, the option letters may appear +between the "?" and the ":". Thus the two patterns +</para> + +<programlisting> +(?i:saturday|sunday) +(?:(?i)saturday|sunday) +</programlisting> + +<para> +match exactly the same set of strings. Because alternative branches are +tried from left to right, and options are not reset until the end of +the subpattern is reached, an option setting in one branch does affect +subsequent branches, so the above patterns match "SUNDAY" as well as +"Saturday". +</para> +</refsect1> + +<refsect1> +<title>Named subpatterns</title> +<para> +Identifying capturing parentheses by number is simple, but it can be +very hard to keep track of the numbers in complicated regular expressions. +Furthermore, if an expression is modified, the numbers may +change. To help with this difficulty, GRegex supports the naming of +subpatterns. A subpattern can be named in one of three ways: (?<name>...) or +(?'name'...) as in Perl, or (?P<name>...) as in Python. +References to capturing parentheses from other +parts of the pattern, such as backreferences, recursion, and conditions, +can be made by name as well as by number. +</para> + +<para> +Names consist of up to 32 alphanumeric characters and underscores. Named +capturing parentheses are still allocated numbers as well as names, exactly as +if the names were not present. +By default, a name must be unique within a pattern, but it is possible to relax +this constraint by setting the <varname>G_REGEX_DUPNAMES</varname> option at +compile time. This can be useful for patterns where only one instance of the +named parentheses can match. Suppose you want to match the name of a weekday, +either as a 3-letter abbreviation or as the full name, and in both cases you +want to extract the abbreviation. This pattern (ignoring the line breaks) does +the job: +</para> + +<programlisting> +(?<DN>Mon|Fri|Sun)(?:day)?| +(?<DN>Tue)(?:sday)?| +(?<DN>Wed)(?:nesday)?| +(?<DN>Thu)(?:rsday)?| +(?<DN>Sat)(?:urday)? +</programlisting> + +<para> +There are five capturing substrings, but only one is ever set after a match. +The function for extracting the data by name returns the substring +for the first (and in this example, the only) subpattern of that name that +matched. This saves searching to find which numbered subpattern it was. If you +make a reference to a non-unique named subpattern from elsewhere in the +pattern, the one that corresponds to the lowest number is used. +</para> +</refsect1> + +<refsect1> +<title>Repetition</title> +<para> +Repetition is specified by quantifiers, which can follow any of the +following items: +</para> + +<itemizedlist> +<listitem><para>a literal data character</para></listitem> +<listitem><para>the dot metacharacter</para></listitem> +<listitem><para>the \C escape sequence</para></listitem> +<listitem><para>the \X escape sequence (in UTF-8 mode)</para></listitem> +<listitem><para>the \R escape sequence</para></listitem> +<listitem><para>an escape such as \d that matches a single character</para></listitem> +<listitem><para>a character class</para></listitem> +<listitem><para>a back reference (see next section)</para></listitem> +<listitem><para>a parenthesized subpattern (unless it is an assertion)</para></listitem> +</itemizedlist> + +<para> +The general repetition quantifier specifies a minimum and maximum number +of permitted matches, by giving the two numbers in curly brackets +(braces), separated by a comma. The numbers must be less than 65536, +and the first must be less than or equal to the second. For example: +</para> + +<programlisting> +z{2,4} +</programlisting> + +<para> +matches "zz", "zzz", or "zzzz". A closing brace on its own is not a +special character. If the second number is omitted, but the comma is +present, there is no upper limit; if the second number and the comma +are both omitted, the quantifier specifies an exact number of required +matches. Thus +</para> + +<programlisting> +[aeiou]{3,} +</programlisting> + +<para> +matches at least 3 successive vowels, but may match many more, while +</para> + +<programlisting> +\d{8} +</programlisting> + +<para> +matches exactly 8 digits. An opening curly bracket that appears in a +position where a quantifier is not allowed, or one that does not match +the syntax of a quantifier, is taken as a literal character. For example, +{,6} is not a quantifier, but a literal string of four characters. +</para> + +<para> +In UTF-8 mode, quantifiers apply to UTF-8 characters rather than to +individual bytes. Thus, for example, \x{100}{2} matches two UTF-8 +characters, each of which is represented by a two-byte sequence. Similarly, +\X{3} matches three Unicode extended sequences, each of which may be +several bytes long (and they may be of different lengths). +</para> + +<para> +The quantifier {0} is permitted, causing the expression to behave as if +the previous item and the quantifier were not present. +</para> + +<para> +For convenience, the three most common quantifiers have single-character +abbreviations: +</para> + +<table frame="all" colsep="1" rowsep="1"> +<title>Abbreviations for quantifiers</title> +<tgroup cols="2"> +<colspec colnum="1" align="center"/> +<thead> + <row> + <entry>Abbreviation</entry> + <entry>Meaning</entry> + </row> +</thead> +<tbody> + <row> + <entry>*</entry> + <entry>is equivalent to {0,}</entry> + </row> + <row> + <entry>+</entry> + <entry>is equivalent to {1,}</entry> + </row> + <row> + <entry>?</entry> + <entry>is equivalent to {0,1}</entry> + </row> +</tbody> +</tgroup> +</table> + +<para> +It is possible to construct infinite loops by following a subpattern +that can match no characters with a quantifier that has no upper limit, +for example: +</para> + +<programlisting> +(a?)* +</programlisting> + +<para> +Because there are cases where this can be useful, such patterns are +accepted, but if any repetition of the subpattern does in fact match +no characters, the loop is forcibly broken. +</para> + +<para> +By default, the quantifiers are "greedy", that is, they match as much +as possible (up to the maximum number of permitted times), without +causing the rest of the pattern to fail. The classic example of where +this gives problems is in trying to match comments in C programs. These +appear between /* and */ and within the comment, individual * and / +characters may appear. An attempt to match C comments by applying the +pattern +</para> + +<programlisting> +/\*.*\*/ +</programlisting> + +<para> +to the string +</para> + +<programlisting> +/* first comment */ not comment /* second comment */ +</programlisting> + +<para> +fails, because it matches the entire string owing to the greediness of +the .* item. +</para> + +<para> +However, if a quantifier is followed by a question mark, it ceases to +be greedy, and instead matches the minimum number of times possible, so +the pattern +</para> + +<programlisting> +/\*.*?\*/ +</programlisting> + +<para> +does the right thing with the C comments. The meaning of the various +quantifiers is not otherwise changed, just the preferred number of +matches. Do not confuse this use of question mark with its use as a +quantifier in its own right. Because it has two uses, it can sometimes +appear doubled, as in +</para> + +<programlisting> +\d??\d +</programlisting> + +<para> +which matches one digit by preference, but can match two if that is the +only way the rest of the pattern matches. +</para> + +<para> +If the <varname>G_REGEX_UNGREEDY</varname> flag is set, the quantifiers are not greedy +by default, but individual ones can be made greedy by following them with +a question mark. In other words, it inverts the default behaviour. +</para> + +<para> +When a parenthesized subpattern is quantified with a minimum repeat +count that is greater than 1 or with a limited maximum, more memory is +required for the compiled pattern, in proportion to the size of the +minimum or maximum. +</para> + +<para> +If a pattern starts with .* or .{0,} and the <varname>G_REGEX_DOTALL</varname> flag +is set, thus allowing the dot to match newlines, the +pattern is implicitly anchored, because whatever follows will be tried +against every character position in the string, so there is no +point in retrying the overall match at any position after the first. +GRegex normally treats such a pattern as though it were preceded by \A. +</para> + +<para> +In cases where it is known that the string contains no newlines, it +is worth setting <varname>G_REGEX_DOTALL</varname> in order to obtain this optimization, +or alternatively using ^ to indicate anchoring explicitly. +</para> + +<para> +However, there is one situation where the optimization cannot be used. +When .* is inside capturing parentheses that are the subject of a +backreference elsewhere in the pattern, a match at the start may fail +where a later one succeeds. Consider, for example: +</para> + +<programlisting> +(.*)abc\1 +</programlisting> + +<para> +If the string is "xyz123abc123" the match point is the fourth character. +For this reason, such a pattern is not implicitly anchored. +</para> + +<para> +When a capturing subpattern is repeated, the value captured is the +substring that matched the final iteration. For example, after +</para> + +<programlisting> +(tweedle[dume]{3}\s*)+ +</programlisting> + +<para> +has matched "tweedledum tweedledee" the value of the captured substring +is "tweedledee". However, if there are nested capturing subpatterns, +the corresponding captured values may have been set in previous iterations. +For example, after +</para> + +<programlisting> +/(a|(b))+/ +</programlisting> + +<para> +matches "aba" the value of the second captured substring is "b". +</para> +</refsect1> + +<refsect1> +<title>Atomic grouping and possessive quantifiers</title> +<para> +With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy") +repetition, failure of what follows normally causes the repeated +item to be re-evaluated to see if a different number +of repeats allows the rest of the pattern to match. Sometimes it +is useful to prevent this, either to change the nature of the +match, or to cause it fail earlier than it otherwise might, when the +author of the pattern knows there is no point in carrying on. +</para> + +<para> +Consider, for example, the pattern \d+foo when applied to the string +</para> + +<programlisting> +123456bar +</programlisting> + +<para> +After matching all 6 digits and then failing to match "foo", the normal +action of the matcher is to try again with only 5 digits matching the +\d+ item, and then with 4, and so on, before ultimately failing. +"Atomic grouping" (a term taken from Jeffrey Friedl’s book) provides +the means for specifying that once a subpattern has matched, it is not +to be re-evaluated in this way. +</para> + +<para> +If we use atomic grouping for the previous example, the matcher +give up immediately on failing to match "foo" the first time. The notation +is a kind of special parenthesis, starting with (?> as in this +example: +</para> + +<programlisting> +(?>\d+)foo +</programlisting> + +<para> +This kind of parenthesis "locks up" the part of the pattern it contains +once it has matched, and a failure further into the pattern is +prevented from backtracking into it. Backtracking past it to previous +items, however, works as normal. +</para> + +<para> +An alternative description is that a subpattern of this type matches +the string of characters that an identical standalone pattern would +match, if anchored at the current point in the string. +</para> + +<para> +Atomic grouping subpatterns are not capturing subpatterns. Simple cases +such as the above example can be thought of as a maximizing repeat that +must swallow everything it can. So, while both \d+ and \d+? are prepared +to adjust the number of digits they match in order to make the +rest of the pattern match, (?>\d+) can only match an entire sequence of +digits. +</para> + +<para> +Atomic groups in general can of course contain arbitrarily complicated +subpatterns, and can be nested. However, when the subpattern for an +atomic group is just a single repeated item, as in the example above, a +simpler notation, called a "possessive quantifier" can be used. This +consists of an additional + character following a quantifier. Using +this notation, the previous example can be rewritten as +</para> + +<programlisting> +\d++foo +</programlisting> + +<para> +Possessive quantifiers are always greedy; the setting of the +<varname>G_REGEX_UNGREEDY</varname> option is ignored. They are a convenient notation for the +simpler forms of atomic group. However, there is no difference in the +meaning of a possessive quantifier and the equivalent +atomic group, though there may be a performance difference; +possessive quantifiers should be slightly faster. +</para> + +<para> +The possessive quantifier syntax is an extension to the Perl syntax. +It was invented by Jeffrey Friedl in the first edition of his book and +then implemented by Mike McCloskey in Sun's Java package. +It ultimately found its way into Perl at release 5.10. +</para> + +<para> +GRegex has an optimization that automatically "possessifies" certain simple +pattern constructs. For example, the sequence A+B is treated as A++B because +there is no point in backtracking into a sequence of A's when B must follow. +</para> + +<para> +When a pattern contains an unlimited repeat inside a subpattern that +can itself be repeated an unlimited number of times, the use of an +atomic group is the only way to avoid some failing matches taking a +very long time indeed. The pattern +</para> + +<programlisting> +(\D+|<\d+>)*[!?] +</programlisting> + +<para> +matches an unlimited number of substrings that either consist of non- +digits, or digits enclosed in <>, followed by either ! or ?. When it +matches, it runs quickly. However, if it is applied to +</para> + +<programlisting> +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +</programlisting> + +<para> +it takes a long time before reporting failure. This is because the +string can be divided between the internal \D+ repeat and the external +* repeat in a large number of ways, and all have to be tried. (The +example uses [!?] rather than a single character at the end, because +GRegex has an optimization that allows for fast failure +when a single character is used. It remember the last single character +that is required for a match, and fail early if it is not present +in the string.) If the pattern is changed so that it uses an atomic +group, like this: +</para> + +<programlisting> +((?>\D+)|<\d+>)*[!?] +</programlisting> + +<para> +sequences of non-digits cannot be broken, and failure happens quickly. +</para> +</refsect1> + +<refsect1> +<title>Back references</title> +<para> +Outside a character class, a backslash followed by a digit greater than +0 (and possibly further digits) is a back reference to a capturing subpattern +earlier (that is, to its left) in the pattern, provided there have been that +many previous capturing left parentheses. +</para> + +<para> +However, if the decimal number following the backslash is less than 10, +it is always taken as a back reference, and causes an error only if +there are not that many capturing left parentheses in the entire pattern. +In other words, the parentheses that are referenced need not be +to the left of the reference for numbers less than 10. A "forward back +reference" of this type can make sense when a repetition is involved and +the subpattern to the right has participated in an earlier iteration. +</para> + +<para> +It is not possible to have a numerical "forward back reference" to subpattern +whose number is 10 or more using this syntax because a sequence such as \e50 is +interpreted as a character defined in octal. See the subsection entitled +"Non-printing characters" above for further details of the handling of digits +following a backslash. There is no such problem when named parentheses are used. +A back reference to any subpattern is possible using named parentheses (see below). +</para> + +<para> +Another way of avoiding the ambiguity inherent in the use of digits following a +backslash is to use the \g escape sequence (introduced in Perl 5.10.) +This escape must be followed by a positive or a negative number, +optionally enclosed in braces. +</para> + +<para> +A positive number specifies an absolute reference without the ambiguity that is +present in the older syntax. It is also useful when literal digits follow the +reference. A negative number is a relative reference. Consider "(abc(def)ghi)\g{-1}", +the sequence \g{-1} is a reference to the most recently started capturing +subpattern before \g, that is, is it equivalent to \2. Similarly, \g{-2} +would be equivalent to \1. The use of relative references can be helpful in +long patterns, and also in patterns that are created by joining together +fragments that contain references within themselves. +</para> + +<para> +A back reference matches whatever actually matched the capturing subpattern +in the current string, rather than anything matching +the subpattern itself (see "Subpatterns as subroutines" below for a way +of doing that). So the pattern +</para> + +<programlisting> +(sens|respons)e and \1ibility +</programlisting> + +<para> +matches "sense and sensibility" and "response and responsibility", but +not "sense and responsibility". If caseful matching is in force at the +time of the back reference, the case of letters is relevant. For example, +</para> + +<programlisting> +((?i)rah)\s+\1 +</programlisting> + +<para> +matches "rah rah" and "RAH RAH", but not "RAH rah", even though the +original capturing subpattern is matched caselessly. +</para> + +<para> +Back references to named subpatterns use the Perl syntax \k<name> or \k'name' +or the Python syntax (?P=name). We could rewrite the above example in either of +the following ways: +</para> + +<programlisting> +(?<p1>(?i)rah)\s+\k<p1> +(?P<p1>(?i)rah)\s+(?P=p1) +</programlisting> + +<para> +A subpattern that is referenced by name may appear in the pattern before or +after the reference. +</para> + +<para> +There may be more than one back reference to the same subpattern. If a +subpattern has not actually been used in a particular match, any back +references to it always fail. For example, the pattern +</para> + +<programlisting> +(a|(bc))\2 +</programlisting> + +<para> +always fails if it starts to match "a" rather than "bc". Because there +may be many capturing parentheses in a pattern, all digits following +the backslash are taken as part of a potential back reference number. +If the pattern continues with a digit character, some delimiter must be +used to terminate the back reference. If the <varname>G_REGEX_EXTENDED</varname> flag is +set, this can be whitespace. Otherwise an empty comment (see "Comments" below) can be used. +</para> + +<para> +A back reference that occurs inside the parentheses to which it refers +fails when the subpattern is first used, so, for example, (a\1) never +matches. However, such references can be useful inside repeated subpatterns. +For example, the pattern +</para> + +<programlisting> +(a|b\1)+ +</programlisting> + +<para> +matches any number of "a"s and also "aba", "ababbaa" etc. At each iteration +of the subpattern, the back reference matches the character +string corresponding to the previous iteration. In order for this to +work, the pattern must be such that the first iteration does not need +to match the back reference. This can be done using alternation, as in +the example above, or by a quantifier with a minimum of zero. +</para> +</refsect1> + +<refsect1> +<title>Assertions</title> +<para> +An assertion is a test on the characters following or preceding the +current matching point that does not actually consume any characters. +The simple assertions coded as \b, \B, \A, \G, \Z, \z, ^ and $ are +described above. +</para> + +<para> +More complicated assertions are coded as subpatterns. There are two +kinds: those that look ahead of the current position in the +string, and those that look behind it. An assertion subpattern is +matched in the normal way, except that it does not cause the current +matching position to be changed. +</para> + +<para> +Assertion subpatterns are not capturing subpatterns, and may not be +repeated, because it makes no sense to assert the same thing several +times. If any kind of assertion contains capturing subpatterns within +it, these are counted for the purposes of numbering the capturing +subpatterns in the whole pattern. However, substring capturing is carried +out only for positive assertions, because it does not make sense for +negative assertions. +</para> + +<refsect2> +<title>Lookahead assertions</title> +<para> +Lookahead assertions start with (?= for positive assertions and (?! for +negative assertions. For example, +</para> + +<programlisting> +\w+(?=;) +</programlisting> + +<para> +matches a word followed by a semicolon, but does not include the semicolon +in the match, and +</para> + +<programlisting> +foo(?!bar) +</programlisting> + +<para> +matches any occurrence of "foo" that is not followed by "bar". Note +that the apparently similar pattern +</para> + +<programlisting> +(?!foo)bar +</programlisting> + +<para> +does not find an occurrence of "bar" that is preceded by something +other than "foo"; it finds any occurrence of "bar" whatsoever, because +the assertion (?!foo) is always true when the next three characters are +"bar". A lookbehind assertion is needed to achieve the other effect. +</para> + +<para> +If you want to force a matching failure at some point in a pattern, the +most convenient way to do it is with (?!) because an empty string +always matches, so an assertion that requires there not to be an empty +string must always fail. +</para> +</refsect2> + +<refsect2> +<title>Lookbehind assertions</title> +<para> +Lookbehind assertions start with (?<= for positive assertions and (?<! +for negative assertions. For example, +</para> + +<programlisting> +(?<!foo)bar +</programlisting> + +<para> +does find an occurrence of "bar" that is not preceded by "foo". The +contents of a lookbehind assertion are restricted such that all the +strings it matches must have a fixed length. However, if there are +several top-level alternatives, they do not all have to have the same +fixed length. Thus +</para> + +<programlisting> +(?<=bullock|donkey) +</programlisting> + +<para> +is permitted, but +</para> + +<programlisting> +(?<!dogs?|cats?) +</programlisting> + +<para> +causes an error at compile time. Branches that match different length +strings are permitted only at the top level of a lookbehind assertion. +An assertion such as +</para> + +<programlisting> +(?<=ab(c|de)) +</programlisting> + +<para> +is not permitted, because its single top-level branch can match two +different lengths, but it is acceptable if rewritten to use two top- +level branches: +</para> + +<programlisting> +(?<=abc|abde) +</programlisting> + +<para> +The implementation of lookbehind assertions is, for each alternative, +to temporarily move the current position back by the fixed length and +then try to match. If there are insufficient characters before the +current position, the assertion fails. +</para> + +<para> +GRegex does not allow the \C escape (which matches a single byte in UTF-8 +mode) to appear in lookbehind assertions, because it makes it impossible +to calculate the length of the lookbehind. The \X and \R escapes, which can +match different numbers of bytes, are also not permitted. +</para> + +<para> +Possessive quantifiers can be used in conjunction with lookbehind assertions to +specify efficient matching at the end of the subject string. Consider a simple +pattern such as +</para> + +<programlisting> +abcd$ +</programlisting> + +<para> +when applied to a long string that does not match. Because matching +proceeds from left to right, GRegex will look for each "a" in the string +and then see if what follows matches the rest of the pattern. If the +pattern is specified as +</para> + +<programlisting> +^.*abcd$ +</programlisting> + +<para> +the initial .* matches the entire string at first, but when this fails +(because there is no following "a"), it backtracks to match all but the +last character, then all but the last two characters, and so on. Once +again the search for "a" covers the entire string, from right to left, +so we are no better off. However, if the pattern is written as +</para> + +<programlisting> +^.*+(?<=abcd) +</programlisting> + +<para> +there can be no backtracking for the .*+ item; it can match only the +entire string. The subsequent lookbehind assertion does a single test +on the last four characters. If it fails, the match fails immediately. +For long strings, this approach makes a significant difference to the +processing time. +</para> +</refsect2> + +<refsect2> +<title>Using multiple assertions</title> +<para> +Several assertions (of any sort) may occur in succession. For example, +</para> + +<programlisting> +(?<=\d{3})(?<!999)foo +</programlisting> + +<para> +matches "foo" preceded by three digits that are not "999". Notice that +each of the assertions is applied independently at the same point in +the string. First there is a check that the previous three +characters are all digits, and then there is a check that the same +three characters are not "999". This pattern does not match "foo" preceded +by six characters, the first of which are digits and the last +three of which are not "999". For example, it doesn’t match "123abcfoo". +A pattern to do that is +</para> + +<programlisting> +(?<=\d{3}...)(?<!999)foo +</programlisting> + +<para> +This time the first assertion looks at the preceding six characters, +checking that the first three are digits, and then the second assertion +checks that the preceding three characters are not "999". +</para> + +<para> +Assertions can be nested in any combination. For example, +</para> + +<programlisting> +(?<=(?<!foo)bar)baz +</programlisting> + +<para> +matches an occurrence of "baz" that is preceded by "bar" which in turn +is not preceded by "foo", while +</para> + +<programlisting> +(?<=\d{3}(?!999)...)foo +</programlisting> + +<para> +is another pattern that matches "foo" preceded by three digits and any +three characters that are not "999". +</para> +</refsect2> +</refsect1> + +<refsect1> +<title>Conditional subpatterns</title> +<para> +It is possible to cause the matching process to obey a subpattern +conditionally or to choose between two alternative subpatterns, depending +on the result of an assertion, or whether a previous capturing subpattern +matched or not. The two possible forms of conditional subpattern are +</para> + +<programlisting> +(?(condition)yes-pattern) +(?(condition)yes-pattern|no-pattern) +</programlisting> + +<para> +If the condition is satisfied, the yes-pattern is used; otherwise the +no-pattern (if present) is used. If there are more than two alternatives +in the subpattern, a compile-time error occurs. +</para> + +<para> +There are four kinds of condition: references to subpatterns, references to +recursion, a pseudo-condition called DEFINE, and assertions. +</para> + +<refsect2> +<title>Checking for a used subpattern by number</title> +<para> +If the text between the parentheses consists of a sequence of digits, the +condition is true if the capturing subpattern of that number has previously +matched. +</para> + +<para> +Consider the following pattern, which contains non-significant white space +to make it more readable (assume the <varname>G_REGEX_EXTENDED</varname>) +and to divide it into three parts for ease of discussion: +</para> + +<programlisting> +( \( )? [^()]+ (?(1) \) ) +</programlisting> + +<para> +The first part matches an optional opening parenthesis, and if that +character is present, sets it as the first captured substring. The second +part matches one or more characters that are not parentheses. The +third part is a conditional subpattern that tests whether the first set +of parentheses matched or not. If they did, that is, if string started +with an opening parenthesis, the condition is true, and so the yes-pattern +is executed and a closing parenthesis is required. Otherwise, +since no-pattern is not present, the subpattern matches nothing. In +other words, this pattern matches a sequence of non-parentheses, +optionally enclosed in parentheses. +</para> +</refsect2> + +<refsect2> +<title>Checking for a used subpattern by name</title> +<para> +Perl uses the syntax (?(<name>)...) or (?('name')...) to test for a used +subpattern by name, the Python syntax (?(name)...) is also recognized. However, +there is a possible ambiguity with this syntax, because subpattern names may +consist entirely of digits. GRegex looks first for a named subpattern; if it +cannot find one and the name consists entirely of digits, GRegex looks for a +subpattern of that number, which must be greater than zero. Using subpattern +names that consist entirely of digits is not recommended. +</para> + +<para> +Rewriting the above example to use a named subpattern gives this: +</para> + +<programlisting> +(?<OPEN> \( )? [^()]+ (?(<OPEN>) \) ) +</programlisting> +</refsect2> + +<refsect2> +<title>Checking for pattern recursion</title> +<para> +If the condition is the string (R), and there is no subpattern with the name R, +the condition is true if a recursive call to the whole pattern or any +subpattern has been made. If digits or a name preceded by ampersand follow the +letter R, for example: +</para> + +<programlisting> +(?(R3)...) +(?(R&name)...) +</programlisting> + +<para> +the condition is true if the most recent recursion is into the subpattern whose +number or name is given. This condition does not check the entire recursion +stack. +</para> + +<para> +At "top level", all these recursion test conditions are false. Recursive +patterns are described below. +</para> +</refsect2> + +<refsect2> +<title>Defining subpatterns for use by reference only</title> +<para> +If the condition is the string (DEFINE), and there is no subpattern with the +name DEFINE, the condition is always false. In this case, there may be only one +alternative in the subpattern. It is always skipped if control reaches this +point in the pattern; the idea of DEFINE is that it can be used to define +"subroutines" that can be referenced from elsewhere. (The use of "subroutines" +is described below.) For example, a pattern to match an IPv4 address could be +written like this (ignore whitespace and line breaks): +</para> + +<programlisting> +(?(DEFINE) (?<byte> 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d) ) +\b (?&byte) (\.(?&byte)){3} \b +</programlisting> + +<para> +The first part of the pattern is a DEFINE group inside which another group +named "byte" is defined. This matches an individual component of an IPv4 +address (a number less than 256). When matching takes place, this part of the +pattern is skipped because DEFINE acts like a false condition. +</para> + +<para> +The rest of the pattern uses references to the named group to match the four +dot-separated components of an IPv4 address, insisting on a word boundary at +each end. +</para> +</refsect2> + +<refsect2> +<title>Assertion conditions</title> +<para> +If the condition is not in any of the above formats, it must be an +assertion. This may be a positive or negative lookahead or lookbehind +assertion. Consider this pattern, again containing non-significant +white space, and with the two alternatives on the second line: +</para> + +<programlisting> +(?(?=[^a-z]*[a-z]) +\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) +</programlisting> + +<para> +The condition is a positive lookahead assertion that matches an +optional sequence of non-letters followed by a letter. In other words, +it tests for the presence of at least one letter in the string. If a +letter is found, the string is matched against the first alternative; +otherwise it is matched against the second. This pattern matches +strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are +letters and dd are digits. +</para> +</refsect2> +</refsect1> + +<refsect1> +<title>Comments</title> +<para> +The sequence (?# marks the start of a comment that continues up to the +next closing parenthesis. Nested parentheses are not permitted. The +characters that make up a comment play no part in the pattern matching +at all. +</para> + +<para> +If the <varname>G_REGEX_EXTENDED</varname> option is set, an unescaped # +character outside a character class introduces a comment that continues to +immediately after the next newline in the pattern. +</para> +</refsect1> + +<refsect1> +<title>Recursive patterns</title> +<para> +Consider the problem of matching a string in parentheses, allowing for +unlimited nested parentheses. Without the use of recursion, the best +that can be done is to use a pattern that matches up to some fixed +depth of nesting. It is not possible to handle an arbitrary nesting +depth. +</para> + +<para> +For some time, Perl has provided a facility that allows regular expressions to +recurse (amongst other things). It does this by interpolating Perl code in the +expression at run time, and the code can refer to the expression itself. A Perl +pattern using code interpolation to solve the parentheses problem can be +created like this: +</para> + +<programlisting> +$re = qr{\( (?: (?>[^()]+) | (?p{$re}) )* \)}x; +</programlisting> + +<para> +The (?p{...}) item interpolates Perl code at run time, and in this case refers +recursively to the pattern in which it appears. +</para> + +<para> +Obviously, GRegex cannot support the interpolation of Perl code. Instead, it +supports special syntax for recursion of the entire pattern, and also for +individual subpattern recursion. This kind of recursion was introduced into +Perl at release 5.10. +</para> + +<para> +A special item that consists of (? followed by a number greater than zero and a +closing parenthesis is a recursive call of the subpattern of the given number, +provided that it occurs inside that subpattern. (If not, it is a "subroutine" +call, which is described in the next section.) The special item (?R) or (?0) is +a recursive call of the entire regular expression. +</para> + +<para> +In GRegex (like Python, but unlike Perl), a recursive subpattern call is always +treated as an atomic group. That is, once it has matched some of the subject +string, it is never re-entered, even if it contains untried alternatives and +there is a subsequent matching failure. +</para> + +<para> +This pattern solves the nested parentheses problem (assume the +<varname>G_REGEX_EXTENDED</varname> option is set so that white space is +ignored): +</para> + +<programlisting> +\( ( (?>[^()]+) | (?R) )* \) +</programlisting> + +<para> +First it matches an opening parenthesis. Then it matches any number of +substrings which can either be a sequence of non-parentheses, or a +recursive match of the pattern itself (that is, a correctly parenthesized +substring). Finally there is a closing parenthesis. +</para> + +<para> +If this were part of a larger pattern, you would not want to recurse +the entire pattern, so instead you could use this: +</para> + +<programlisting> +( \( ( (?>[^()]+) | (?1) )* \) ) +</programlisting> + +<para> +We have put the pattern into parentheses, and caused the recursion to +refer to them instead of the whole pattern. In a larger pattern, keeping +track of parenthesis numbers can be tricky. It may be more convenient to +use named parentheses instead. +The Perl syntax for this is (?&name); GRegex also supports the(?P>name) +syntax. We could rewrite the above example as follows: +</para> + +<programlisting> +(?<pn> \( ( (?>[^()]+) | (?&pn) )* \) ) +</programlisting> + +<para> +If there is more than one subpattern with the same name, the earliest one is +used. This particular example pattern contains nested unlimited repeats, and so +the use of atomic grouping for matching strings of non-parentheses is important +when applying the pattern to strings that do not match. +For example, when this pattern is applied to +</para> + +<programlisting> +(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() +</programlisting> + +<para> +it yields "no match" quickly. However, if atomic grouping is not used, +the match runs for a very long time indeed because there are so many +different ways the + and * repeats can carve up the string, and all +have to be tested before failure can be reported. +</para> + +<para> +At the end of a match, the values set for any capturing subpatterns are +those from the outermost level of the recursion at which the subpattern +value is set. + +<!-- Callouts are not supported by GRegex +If you want to obtain intermediate values, a callout +function can be used (see below and the pcrecallout documentation). --> + +If the pattern above is matched against +</para> + +<programlisting> +(ab(cd)ef) +</programlisting> + +<para> +the value for the capturing parentheses is "ef", which is the last +value taken on at the top level. If additional parentheses are added, +giving +</para> + +<programlisting> +\( ( ( (?>[^()]+) | (?R) )* ) \) + ^ ^ + ^ ^ +</programlisting> + +<para> +the string they capture is "ab(cd)ef", the contents of the top level +parentheses. +</para> + +<para> +Do not confuse the (?R) item with the condition (R), which tests for +recursion. Consider this pattern, which matches text in angle brackets, +allowing for arbitrary nesting. Only digits are allowed in nested +brackets (that is, when recursing), whereas any characters are permitted +at the outer level. +</para> + +<programlisting> +< (?: (?(R) \d++ | [^<>]*+) | (?R)) * > +</programlisting> + +<para> +In this pattern, (?(R) is the start of a conditional subpattern, with +two different alternatives for the recursive and non-recursive cases. +The (?R) item is the actual recursive call. +</para> +</refsect1> + +<refsect1> +<title>Subpatterns as subroutines</title> +<para> +If the syntax for a recursive subpattern reference (either by number or +by name) is used outside the parentheses to which it refers, it operates +like a subroutine in a programming language. The "called" subpattern may +be defined before or after the reference. An earlier example pointed out +that the pattern +</para> + +<programlisting> +(sens|respons)e and \1ibility +</programlisting> + +<para> +matches "sense and sensibility" and "response and responsibility", but +not "sense and responsibility". If instead the pattern +</para> + +<programlisting> +(sens|respons)e and (?1)ibility +</programlisting> + +<para> +is used, it does match "sense and responsibility" as well as the other +two strings. Another example is given in the discussion of DEFINE above. +</para> + +<para> +Like recursive subpatterns, a "subroutine" call is always treated as an atomic +group. That is, once it has matched some of the string, it is never +re-entered, even if it contains untried alternatives and there is a subsequent +matching failure. +</para> + +<para> +When a subpattern is used as a subroutine, processing options such as +case-independence are fixed when the subpattern is defined. They cannot be +changed for different calls. For example, consider this pattern: +</para> + +<programlisting> +(abc)(?i:(?1)) +</programlisting> + +<para> +It matches "abcabc". It does not match "abcABC" because the change of +processing option does not affect the called subpattern. +</para> +</refsect1> + +<!-- Callouts are not supported by GRegex +<refsect1> +<title>Callouts</title> +<para> +Perl has a feature whereby using the sequence (?{...}) causes arbitrary +Perl code to be obeyed in the middle of matching a regular expression. +This makes it possible, amongst other things, to extract different substrings that match the same pair of parentheses when there is a repetition. +</para> + +<para> +PCRE provides a similar feature, but of course it cannot obey arbitrary +Perl code. The feature is called "callout". The caller of PCRE provides +an external function by putting its entry point in the global variable +pcre_callout. By default, this variable contains NULL, which disables +all calling out. +</para> + +<para> +Within a regular expression, (?C) indicates the points at which the +external function is to be called. If you want to identify different +callout points, you can put a number less than 256 after the letter C. +The default value is zero. For example, this pattern has two callout +points: +</para> + +<programlisting> +(?C1)abc(?C2)def +</programlisting> + +<para> +If the PCRE_AUTO_CALLOUT flag is passed to pcre_compile(), callouts are +automatically installed before each item in the pattern. They are all +numbered 255. +</para> + +<para> +During matching, when PCRE reaches a callout point (and pcre_callout is +set), the external function is called. It is provided with the number +of the callout, the position in the pattern, and, optionally, one item +of data originally supplied by the caller of pcre_exec(). The callout +function may cause matching to proceed, to backtrack, or to fail altogether. A complete description of the interface to the callout function +is given in the pcrecallout documentation. +</para> +</refsect1> +--> + +<refsect1> +<title>Copyright</title> +<para> +This document was copied and adapted from the PCRE documentation, +specifically from the man page for pcrepattern. +The original copyright note is: +</para> + +<programlisting> +Copyright (c) 1997-2006 University of Cambridge. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the name of Google + Inc. nor the names of their contributors may be used to endorse or + promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +</programlisting> +</refsect1> + +</refentry>
diff --git a/docs/reference/glib/resources.xml b/docs/reference/glib/resources.xml new file mode 100644 index 0000000..c5cfa78 --- /dev/null +++ b/docs/reference/glib/resources.xml
@@ -0,0 +1,77 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<refentry id="glib-resources" revision="17 Jan 2002"> +<refmeta> +<refentrytitle>Mailing lists and bug reports</refentrytitle> +<manvolnum>3</manvolnum> +<refmiscinfo>Mailing lists and bug reports</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>Mailing lists and bug reports</refname> +<refpurpose> +Getting help with GLib +</refpurpose> +</refnamediv> + +<refsect1> +<title>Filing a bug report or feature request</title> + +<para> +If you encounter a bug, misfeature, or missing feature in GLib, please +file a bug report on the issue tracker at +<ulink url="https://gitlab.gnome.org/GNOME/glib/issues/new">https://gitlab.gnome.org/GNOME/glib/issues/new</ulink>. +We'd also appreciate reports of incomplete or misleading information in +the GLib documentation; file those with the ‘Documentation’ label. +</para> + +<para> +Don't hesitate to file a bug report, even if you think we may know +about it already, or aren't sure of the details. Just give us as much +information as you have, and if it's already fixed or has already been +discussed, we'll add a note to that effect in the report. +</para> + +<para> +The issue tracker should definitely be used for feature requests, it's +not only for bugs. We track all GLib development in GitLab, so it's +the way to be sure the GLib developers won't forget about an issue. +</para> + +</refsect1> + +<refsect1> +<title>Code Contributions</title> + +<para> +If you develop a bugfix or enhancement for GLib, please open a merge request +for that in GitLab as well. All branches must be offered under the terms of +the GNU LGPL license, so be sure you are authorized to give us the branch +under those terms. +</para> + +<para> +If you want to discuss your branch before or after developing it, open a +topic on <ulink url="https://discourse.gnome.org/tags/glib">Discourse</ulink>. +But be sure to create the GitLab merge request as well; if the branch is only +on the list and not in GitLab, it's likely to slip through the cracks. +</para> + +</refsect1> + +<refsect1> +<title>Discussions and user questions</title> + +<para> +The <ulink url="https://gitlab.gnome.org/GNOME/glib/issues">GLib issue tracker</ulink> +is meant for discussions with actionable topics. If you want to ask a question +about using GLib, or discuss new features, you should use +<ulink url="https://discourse.gnome.org/tags/glib">the glib tag on Discourse</ulink>. +</para> + +</refsect1> + + +</refentry>
diff --git a/docs/reference/glib/running.xml b/docs/reference/glib/running.xml new file mode 100644 index 0000000..aaafddf --- /dev/null +++ b/docs/reference/glib/running.xml
@@ -0,0 +1,411 @@ +<?xml version="1.0"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<refentry id="glib-running"> +<refmeta> +<refentrytitle>Running GLib Applications</refentrytitle> +<manvolnum>3</manvolnum> +<refmiscinfo>GLib Library</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>Running GLib Applications</refname> +<refpurpose> +How to run and debug your GLib application +</refpurpose> +</refnamediv> + +<refsect1> +<title>Running and debugging GLib Applications</title> + +<refsect2> +<title>Environment variables</title> + +<para> + The runtime behaviour of GLib applications can be influenced by a + number of environment variables. +</para> + +<formalpara> + <title>Standard variables</title> + + <para> + GLib reads standard environment variables like <envar>LANG</envar>, + <envar>PATH</envar>, <envar>HOME</envar>, <envar>TMPDIR</envar>, + <envar>TZ</envar> and <envar>LOGNAME</envar>. + </para> +</formalpara> + +<formalpara> + <title>XDG directories</title> + + <para> + GLib consults the environment variables <envar>XDG_DATA_HOME</envar>, + <envar>XDG_DATA_DIRS</envar>, <envar>XDG_CONFIG_HOME</envar>, + <envar>XDG_CONFIG_DIRS</envar>, <envar>XDG_CACHE_HOME</envar> and + <envar>XDG_RUNTIME_DIR</envar> for the various XDG directories. + For more information, see the <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG basedir spec</ulink>. + </para> +</formalpara> + +<formalpara id="G_FILENAME_ENCODING"> + <title><envar>G_FILENAME_ENCODING</envar></title> + + <para> + This environment variable can be set to a comma-separated list of character + set names. GLib assumes that filenames are encoded in the first character + set from that list rather than in UTF-8. The special token "@locale" can be + used to specify the character set for the current locale. + </para> +</formalpara> + +<formalpara id="G_BROKEN_FILENAMES"> + <title><envar>G_BROKEN_FILENAMES</envar></title> + + <para> + If this environment variable is set, GLib assumes that filenames are in + the locale encoding rather than in UTF-8. G_FILENAME_ENCODING takes + priority over G_BROKEN_FILENAMES. + </para> +</formalpara> + +<formalpara id="G_MESSAGES_PREFIXED"> + <title><envar>G_MESSAGES_PREFIXED</envar></title> + + <para> + A list of log levels for which messages should be prefixed by the + program name and PID of the application. The default is to prefix + everything except <literal>G_LOG_LEVEL_MESSAGE</literal> and + <literal>G_LOG_LEVEL_INFO</literal>. + The possible values are + <literal>error</literal>, + <literal>warning</literal>, + <literal>critical</literal>, + <literal>message</literal>, + <literal>info</literal> and + <literal>debug</literal>. + You can also use the special values + <literal>all</literal> and + <literal>help</literal>. + </para> + <para> + This environment variable only affects the default log handler, + g_log_default_handler(). + </para> +</formalpara> + +<formalpara id="G_MESSAGES_DEBUG"> + <title><envar>G_MESSAGES_DEBUG</envar></title> + + <para> + A space-separated list of log domains for which informational + and debug messages should be printed. By default, these + messages are not printed. + </para> + <para> + You can also use the special value <literal>all</literal>. + </para> + <para> + This environment variable only affects the default log handler, + g_log_default_handler(). + </para> +</formalpara> + +<formalpara id="G-DEBUG:CAPS"> + <title><envar>G_DEBUG</envar></title> + + <para> + This environment variable can be set to a list of debug options, + which cause GLib to print out different types of debugging information. + <variablelist> + <varlistentry> + <term>fatal-warnings</term> + <listitem><para>Causes GLib to abort the program at the first call + to g_warning() or g_critical(). Use of this flag is not + recommended except when debugging.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>fatal-criticals</term> + <listitem><para>Causes GLib to abort the program at the first call + to g_critical(). This flag can be useful during debugging and + testing.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>gc-friendly</term> + <listitem><para>Newly allocated memory that isn't directly initialized, + as well as memory being freed will be reset to 0. The point here is + to allow memory checkers and similar programs that use Boehm GC alike + algorithms to produce more accurate results.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>resident-modules</term> + <listitem><para>All modules loaded by GModule will be made resident. + This can be useful for tracking memory leaks in modules which are + later unloaded; but it can also hide bugs where code is accessed + after the module would have normally been unloaded.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>bind-now-modules</term> + <listitem><para>All modules loaded by GModule will bind their symbols + at load time, even when the code uses %G_MODULE_BIND_LAZY.</para> + </listitem> + </varlistentry> + </variablelist> + The special value <literal>all</literal> can be used to turn on all debug options. + The special value <literal>help</literal> can be used to print all available options. + </para> +</formalpara> + +<formalpara id="G_SLICE"> + <title><envar>G_SLICE</envar></title> + + <para> + This environment variable allows reconfiguration of the GSlice + memory allocator. + <variablelist> + <varlistentry> + <term>always-malloc</term> + <listitem><para>This will cause all slices allocated through + g_slice_alloc() and released by g_slice_free1() to be actually + allocated via direct calls to g_malloc() and g_free(). + This is most useful for memory checkers and similar programs that + use Boehm GC alike algorithms to produce more accurate results. + It can also be in conjunction with debugging features of the system's + malloc() implementation such as glibc's MALLOC_CHECK_=2 to debug + erroneous slice allocation code, although + <literal>debug-blocks</literal> is usually a better suited debugging + tool.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>debug-blocks</term> + <listitem><para>Using this option (present since GLib 2.13) engages + extra code which performs sanity checks on the released memory + slices. Invalid slice addresses or slice sizes will be reported and + lead to a program halt. This option is for debugging scenarios. + In particular, client packages sporting their own test suite should + <emphasis>always enable this option when running tests</emphasis>. + Global slice validation is ensured by storing size and address + information for each allocated chunk, and maintaining a global + hash table of that data. That way, multi-thread scalability is + given up, and memory consumption is increased. However, the + resulting code usually performs acceptably well, possibly better + than with comparable memory checking carried out using external + tools.</para> + <para>An example of a memory corruption scenario that cannot be + reproduced with <literal>G_SLICE=always-malloc</literal>, but will + be caught by <literal>G_SLICE=debug-blocks</literal> is as follows: + <programlisting> + void *slist = g_slist_alloc (); /* void* gives up type-safety */ + g_list_free (slist); /* corruption: sizeof (GSList) != sizeof (GList) */ + </programlisting></para> + </listitem> + </varlistentry> + </variablelist> + The special value <literal>all</literal> can be used to turn on all options. + The special value <literal>help</literal> can be used to print all available options. + </para> +</formalpara> + +<formalpara id="G_RANDOM_VERSION"> + <title><envar>G_RANDOM_VERSION</envar></title> + + <para> + If this environment variable is set to '2.0', the outdated + pseudo-random number seeding and generation algorithms from + GLib 2.0 are used instead of the newer, better ones. You should + only set this variable if you have sequences of numbers that were + generated with Glib 2.0 that you need to reproduce exactly. + </para> +</formalpara> + +<formalpara id="LIBCHARSET_ALIAS_DIR"> + <title><envar>LIBCHARSET_ALIAS_DIR</envar></title> + + <para> + Allows to specify a nonstandard location for the + <filename>charset.aliases</filename> file that is used by the + character set conversion routines. The default location is the + <replaceable>libdir</replaceable> specified at compilation time. + </para> +</formalpara> + +<formalpara id="TZDIR"> + <title><envar>TZDIR</envar></title> + + <para> + Allows to specify a nonstandard location for the timezone data files + that are used by the #GDateTime API. The default location is under + <filename>/usr/share/zoneinfo</filename>. For more information, + also look at the <command>tzset</command> manual page. + </para> +</formalpara> + +<formalpara id="G_ENABLE_DIAGNOSTIC"> + <title><envar>G_ENABLE_DIAGNOSTIC</envar></title> + + <para> + If set to a non-zero value, this environment variable enables + diagnostic messages, like deprecation messages for GObject properties + and signals. + </para> +</formalpara> + +<formalpara id="G_DEBUGGER"> + <title><envar>G_DEBUGGER</envar></title> + + <para> + When running on Windows, if set to a non-empty string, GLib will + try to interpret the contents of this environment variable as + a command line to a debugger, and run it if the process crashes. + The debugger command line should contain <literal>%p</literal> and <literal>%e</literal> substitution + tokens, which GLib will replace with the process ID of the crashing + process and a handle to an event that the debugger should signal + to let GLib know that the debugger successfully attached to the + process. If <literal>%e</literal> is absent, or if the debugger is not able to + signal events, GLib will resume execution after 60 seconds. + If <literal>%p</literal> is absent, the debugger won't know which process to attach to, + and GLib will also resume execution after 60 seconds. + </para> + <para> + Additionally, even if <envar>G_DEBUGGER</envar> is not set, GLib would still + try to print basic exception information (code and address) into + stderr. + </para> + <para> + By default the debugger gets a new console allocated for it. + Set the <envar>G_DEBUGGER_OLD_CONSOLE</envar> environment variable to any + non-empty string to make the debugger inherit the console of + the crashing process. Normally this is only used by the GLib + testsuite. + </para> + <para> + The exception handler is written with the aim of making it as + simple as possible, to minimize the risk of it invoking + buggy functions or running buggy code, which would result + in exceptions being raised recursively. Because of that + it lacks most of the amenities that one would expect of GLib. + Namely, it does not support Unicode, so it is highly advisable + to only use ASCII characters in <envar>G_DEBUGGER</envar>. + </para> + <para> + See also <link linkend="G_VEH_CATCH"><envar>G_VEH_CATCH</envar></link>. + </para> +</formalpara> + +<formalpara id="G_VEH_CATCH"> + <title><envar>G_VEH_CATCH</envar></title> + + <para> + Catching some exceptions can break the program, since Windows + will sometimes use exceptions for execution flow control and + other purposes other than signalling a crash. + </para> + <para> + The <envar>G_VEH_CATCH</envar> environment variable augments + <ulink url="https://docs.microsoft.com/en-us/windows/desktop/debug/vectored-exception-handling">Vectored Exception Handling</ulink> + on Windows (see <link linkend="G_DEBUGGER"><envar>G_DEBUGGER</envar></link>), allowing GLib to catch more + exceptions. Set this variable to a comma-separated list of + hexadecimal exception codes that should additionally be caught. + </para> + <para> + By default GLib will only catch Access Violation, Stack Overflow and + Illegal Instruction <ulink url="https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_exception_record">exceptions</ulink>. + </para> +</formalpara> + +</refsect2> + +<refsect2 id="setlocale"> +<title>Locale</title> + +<para> +A number of interfaces in GLib depend on the current locale in which +an application is running. Therefore, most GLib-using applications should +call <function>setlocale (LC_ALL, "")</function> to set up the current +locale. +</para> + +<para> +On Windows, in a C program there are several locale concepts +that not necessarily are synchronized. On one hand, there is the +system default ANSI code-page, which determines what encoding is used +for file names handled by the C library's functions and the Win32 +API. (We are talking about the "narrow" functions here that take +character pointers, not the "wide" ones.) +</para> + +<para> +On the other hand, there is the C library's current locale. The +character set (code-page) used by that is not necessarily the same as +the system default ANSI code-page. Strings in this character set are +returned by functions like <function>strftime()</function>. +</para> + +</refsect2> + +<para> +GLib ships with a set of Python macros for the GDB debugger. These includes pretty +printers for lists, hashtables and GObject types. It also has a backtrace filter +that makes backtraces with signal emissions easier to read. +</para> + +<para> +To use this you need a version of GDB that supports Python scripting; anything +from 7.0 should be fine. You then need to install GLib in the same prefix as +GDB so that the Python GDB autoloaded files get installed in the right place +for GDB to pick up. +</para> + +<para> +General pretty printing should just happen without having to do anything special. +To get the signal emission filtered backtrace you must use the "new-backtrace" command +instead of the standard one. +</para> + +<para> +There is also a new command called gforeach that can be used to apply a command +on each item in a list. E.g. you can do +<programlisting> +gforeach i in some_list_variable: print *(GtkWidget *)l +</programlisting> +Which would print the contents of each widget in a list of widgets. +</para> + +<refsect2> +<title>SystemTap</title> + +<para> +<ulink url="http://sourceware.org/systemtap/">SystemTap</ulink> is a dynamic whole-system +analysis toolkit. GLib ships with a file <filename>libglib-2.0.so.*.stp</filename> which defines a +set of probe points, which you can hook into with custom SystemTap scripts. +See the files <filename>libglib-2.0.so.*.stp</filename>, <filename>libgobject-2.0.so.*.stp</filename> +and <filename>libgio-2.0.so.*.stp</filename> which +are in your shared SystemTap scripts directory. +</para> + +</refsect2> + +<refsect2> +<title>Memory statistics</title> + +<para> +g_mem_profile() will output a summary g_malloc() memory usage, if memory +profiling has been enabled by calling +<literal>g_mem_set_vtable (glib_mem_profiler_table)</literal> upon startup. +</para> + +<para> +If GLib has been configured with <option>--enable-debug=yes</option>, +then g_slice_debug_tree_statistics() can be called in a debugger to +output details about the memory usage of the slice allocator. +</para> + +</refsect2> +</refsect1> +</refentry>
diff --git a/docs/reference/glib/version.xml.in b/docs/reference/glib/version.xml.in new file mode 100644 index 0000000..af9b9c4 --- /dev/null +++ b/docs/reference/glib/version.xml.in
@@ -0,0 +1 @@ +@GLIB_VERSION@
diff --git a/docs/reference/glib/xml/gtkdocentities.ent.in b/docs/reference/glib/xml/gtkdocentities.ent.in new file mode 100644 index 0000000..f12c9ff --- /dev/null +++ b/docs/reference/glib/xml/gtkdocentities.ent.in
@@ -0,0 +1,8 @@ +<!ENTITY package "@PACKAGE@"> +<!ENTITY package_bugreport "@PACKAGE_BUGREPORT@"> +<!ENTITY package_name "@PACKAGE_NAME@"> +<!ENTITY package_string "@PACKAGE_STRING@"> +<!ENTITY package_tarname "@PACKAGE_TARNAME@"> +<!ENTITY package_url "@PACKAGE_URL@"> +<!ENTITY package_version "@PACKAGE_VERSION@"> +<!ENTITY package_api_version "@PACKAGE_API_VERSION@">
diff --git a/docs/reference/glib/xml/meson.build b/docs/reference/glib/xml/meson.build new file mode 100644 index 0000000..6aeb745 --- /dev/null +++ b/docs/reference/glib/xml/meson.build
@@ -0,0 +1,14 @@ +ent_conf = configuration_data() +ent_conf.set('PACKAGE', 'glib') +ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/glib/issues/new') +ent_conf.set('PACKAGE_NAME', 'glib') +ent_conf.set('PACKAGE_STRING', 'glib') +ent_conf.set('PACKAGE_TARNAME', 'glib') +ent_conf.set('PACKAGE_URL', 'FIXME') +ent_conf.set('PACKAGE_VERSION', glib_version) +ent_conf.set('PACKAGE_API_VERSION', glib_api_version) +configure_file( + input: 'gtkdocentities.ent.in', + output: 'gtkdocentities.ent', + configuration: ent_conf +)
diff --git a/docs/reference/gobject/glib-genmarshal.xml b/docs/reference/gobject/glib-genmarshal.xml new file mode 100644 index 0000000..2b3e86f --- /dev/null +++ b/docs/reference/gobject/glib-genmarshal.xml
@@ -0,0 +1,579 @@ +<refentry id="glib-genmarshal" lang="en"> + +<refentryinfo> + <title>glib-genmarshal</title> + <productname>GObject</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Emmanuele</firstname> + <surname>Bassi</surname> + </author> + <author> + <contrib>Original developer</contrib> + <firstname>Tim</firstname> + <surname>Janik</surname> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> +<refentrytitle>glib-genmarshal</refentrytitle> +<manvolnum>1</manvolnum> +<refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>glib-genmarshal</refname> +<refpurpose>C code marshaller generation utility for GLib closures</refpurpose> +</refnamediv> + +<refsynopsisdiv> +<cmdsynopsis> +<command>glib-genmarshal</command> +<arg choice="opt" rep="repeat">OPTION</arg> +<arg choice="opt" rep="repeat">FILE</arg> +</cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>glib-genmarshal</command> is a small utility that generates C code +marshallers for callback functions of the GClosure mechanism in the GObject +sublibrary of GLib. The marshaller functions have a standard signature, +they get passed in the invoking closure, an array of value structures holding +the callback function parameters and a value structure for the return value +of the callback. The marshaller is then responsible to call the respective C +code function of the closure with all the parameters on the stack and to +collect its return value. +</para> + +<para><command>glib-genmarshal</command> takes a list of marshallers to generate as +input. The marshaller list is either read from files passed as additional arguments +on the command line; or from standard input, by using <literal>-</literal> as the +input file. +</para> + +<refsect2><title>Marshaller list format</title> +<para> +The marshaller lists are processed line by line, a line can contain a +comment in the form of +<informalexample><programlisting> +# this is a comment +</programlisting></informalexample> +or a marshaller specification of the form +<programlisting> +<replaceable>RTYPE</replaceable>:<replaceable>PTYPE</replaceable> +<replaceable>RTYPE</replaceable>:<replaceable>PTYPE</replaceable>,<replaceable>PTYPE</replaceable> +<replaceable>RTYPE</replaceable>:<replaceable>PTYPE</replaceable>,<replaceable>PTYPE</replaceable>,<replaceable>PTYPE</replaceable> +</programlisting> +</para> +<para> +The <replaceable>RTYPE</replaceable> part specifies the callback's return +type and the <replaceable>PTYPE</replaceable>s right to the colon specify +the callback's parameter list, except for the first and the last arguments +which are always pointers. +</para> +</refsect2> +<refsect2><title>Parameter types</title> +<para> +Currently, the following types are supported: +<variablelist> +<varlistentry> +<term><replaceable>VOID</replaceable></term> +<listitem><para> +indicates no return type, or no extra parameters. +If <replaceable>VOID</replaceable> is used as the parameter list, no +additional parameters may be present. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>BOOLEAN</replaceable></term> +<listitem><para> +for boolean types (gboolean) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>CHAR</replaceable></term> +<listitem><para> +for signed char types (gchar) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>UCHAR</replaceable></term> +<listitem><para> +for unsigned char types (guchar) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>INT</replaceable></term> +<listitem><para> +for signed integer types (gint) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>UINT</replaceable></term> +<listitem><para> +for unsigned integer types (guint) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>LONG</replaceable></term> +<listitem><para> +for signed long integer types (glong) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>ULONG</replaceable></term> +<listitem><para> +for unsigned long integer types (gulong) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>INT64</replaceable></term> +<listitem><para> +for signed 64bit integer types (gint64) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>UINT64</replaceable></term> +<listitem><para> +for unsigned 64bit integer types (guint64) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>ENUM</replaceable></term> +<listitem><para> +for enumeration types (gint) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>FLAGS</replaceable></term> +<listitem><para> +for flag enumeration types (guint) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>FLOAT</replaceable></term> +<listitem><para> +for single-precision float types (gfloat) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>DOUBLE</replaceable></term> +<listitem><para> +for double-precision float types (gdouble) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>STRING</replaceable></term> +<listitem><para> +for string types (gchar*) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>BOXED</replaceable></term> +<listitem><para> +for boxed (anonymous but reference counted) types (GBoxed*) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>PARAM</replaceable></term> +<listitem><para> +for GParamSpec or derived types (GParamSpec*) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>POINTER</replaceable></term> +<listitem><para> +for anonymous pointer types (gpointer) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>OBJECT</replaceable></term> +<listitem><para> +for GObject or derived types (GObject*) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>VARIANT</replaceable></term> +<listitem><para> +for GVariant types (GVariant*) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>NONE</replaceable></term> +<listitem><para> +deprecated alias for <replaceable>VOID</replaceable> +</para></listitem> +</varlistentry> + +<varlistentry> +<term><replaceable>BOOL</replaceable></term> +<listitem><para> +deprecated alias for <replaceable>BOOLEAN</replaceable> +</para></listitem> +</varlistentry> +</variablelist> +</para> +</refsect2> +</refsect1> + +<refsect1><title>Options</title> +<variablelist> + +<varlistentry> +<term><option>--header</option></term> +<listitem><para> +Generate header file contents of the marshallers. This option is mutually +exclusive with the <option>--body</option> option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--body</option></term> +<listitem><para> +Generate C code file contents of the marshallers. This option is mutually +exclusive with the <option>--header</option> option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--prefix=<replaceable>PREFIX</replaceable></option></term> +<listitem><para> +Specify marshaller prefix. The default prefix is <literal>`g_cclosure_user_marshal'</literal>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--skip-source</option></term> +<listitem><para> +Skip source location remarks in generated comments. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--stdinc</option></term> +<listitem><para> +Use the standard marshallers of the GObject library, and include +<filename>glib-object.h</filename> in generated header files. This +option is mutually exclusive with the <option>--nostdinc</option> +option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--nostdinc</option></term> +<listitem><para> +Do not use the standard marshallers of the GObject library, and skip +<filename>glib-object.h</filename> include directive in generated header files. +This option is mutually exclusive with the <option>--stdinc</option> option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--internal</option></term> +<listitem><para> +Mark generated functions as internal, using <literal>G_GNUC_INTERNAL</literal>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--valist-marshallers</option></term> +<listitem><para> +Generate valist marshallers, for use with <function>g_signal_set_va_marshaller()</function>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-v</option>, <option>--version</option></term> +<listitem><para> +Print version information. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--g-fatal-warnings</option></term> +<listitem><para> +Make warnings fatal, that is, exit immediately once a warning occurs. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-h</option>, <option>--help</option></term> +<listitem><para> +Print brief help and exit. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-v</option>, <option>--version</option></term> +<listitem><para> +Print version and exit. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--output=FILE</option></term> +<listitem><para> +Write output to <replaceable>FILE</replaceable> instead of the standard output. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--prototypes</option></term> +<listitem><para> +Generate function prototypes before the function definition in the C source +file, in order to avoid a <literal>missing-prototypes</literal> compiler +warning. This option is only useful when using the <option>--body</option> +option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--pragma-once</option></term> +<listitem><para> +Use the <literal>once</literal> pragma instead of an old style header guard +when generating the C header file. This option is only useful when using the +<option>--header</option> option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--include-header=<replaceable>HEADER</replaceable></option></term> +<listitem><para> +Adds a <literal>#include</literal> directive for the given file in the C +source file. This option is only useful when using the <option>--body</option> +option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-D <replaceable>SYMBOL[=VALUE]</replaceable></option></term> +<listitem><para> +Adds a <literal>#define</literal> C pre-processor directive for +<replaceable>SYMBOL</replaceable> and its given <replaceable>VALUE</replaceable>, +or "1" if the value is unset. You can use this option multiple times; if you do, +all the symbols will be defined in the same order given on the command line, before +the symbols undefined using the <option>-U</option> option. This option is only +useful when using the <option>--body</option> option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-U <replaceable>SYMBOL</replaceable></option></term> +<listitem><para> +Adds a <literal>#undef</literal> C pre-processor directive to undefine the +given <replaceable>SYMBOL</replaceable>. You can use this option multiple times; +if you do, all the symbols will be undefined in the same order given on the +command line, after the symbols defined using the <option>-D</option> option. +This option is only useful when using the <option>--body</option> option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--quiet</option></term> +<listitem><para> +Minimizes the output of <command>glib-genmarshal</command>, by printing only +warnings and errors. This option is mutually exclusive with the +<option>--verbose</option> option. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--verbose</option></term> +<listitem><para> +Increases the verbosity of <command>glib-genmarshal</command>, by printing +debugging information. This option is mutually exclusive with the +<option>--quiet</option> option. +</para></listitem> +</varlistentry> + +</variablelist> +</refsect1> + +<refsect1><title>Using <command>glib-genmarshal</command> with Meson</title> +<para> +Meson supports generating closure marshallers using <command>glib-genmarshal</command> +out of the box in its "gnome" module. +</para> + +<para> +In your <filename>meson.build</filename> file you will typically call the +<literal>gnome.genmarshal()</literal> method with the source list of marshallers +to generate: +</para> +<informalexample><programlisting> +gnome = import('gnome') +marshal_files = gnome.genmarshal('marshal', + sources: 'marshal.list', + internal: true, +) +</programlisting></informalexample> +<para> +The <literal>marshal_files</literal> variable will contain an array of two elements +in the following order: +</para> +<itemizedlist> + <listitem><para>a build target for the source file</para></listitem> + <listitem><para>a build target for the header file</para></listitem> +</itemizedlist> +<para> +You should use the returned objects to provide a dependency on every other +build target that references the source or header file; for instance, if you +are using the source to build a library: +</para> +<informalexample><programlisting> +mainlib = library('project', + sources: project_sources + marshal_files, + ... +) +</programlisting></informalexample> +<para> +Additionally, if you are including the generated header file inside a build +target that depends on the library you just built, you must ensure that the +internal dependency includes the generated header as a required source file: +</para> +<informalexample><programlisting> +mainlib_dep = declare_dependency(sources: marshal_files[1], link_with: mainlib) +</programlisting></informalexample> +<para> +You should not include the generated source file as well, otherwise it will +be built separately for every target that depends on it, causing build +failures. To know more about why all this is required, please refer to the +<ulink url="https://mesonbuild.com/FAQ.html#how-do-i-tell-meson-that-my-sources-use-generated-headers"> +corresponding Meson FAQ entry</ulink>. +</para> +<para> +For more information on how to use the method, see the +<ulink url="https://mesonbuild.com/Gnome-module.html#gnomegenmarshal">Meson +documentation for <literal>gnome.genmarshal()</literal></ulink>. +</para> +</refsect1> + +<refsect1><title>Using <command>glib-genmarshal</command> with Autotools</title> +<para> +In order to use <command>glib-genmarshal</command> in your project when using +Autotools as the build system, you will first need to modify your +<filename>configure.ac</filename> file to ensure you find the appropriate +command using <command>pkg-config</command>, similarly as to how you discover +the compiler and linker flags for GLib. +</para> +<informalexample><programlisting> +PKG_PROG_PKG_CONFIG([0.28]) + +PKG_CHECK_VAR([GLIB_GENMARSHAL], [glib-2.0], [glib_genmarshal]) +</programlisting></informalexample> +<para> +In your <filename>Makefile.am</filename> file you will typically need very +simple rules to generate the C files needed for the build. +</para> +<informalexample><programlisting> +marshal.h: marshal.list + $(AM_V_GEN)$(GLIB_GENMARSHAL) \ + --header \ + --output=$@ \ + $< + +marshal.c: marshal.list marshal.h + $(AM_V_GEN)$(GLIB_GENMARSHAL) \ + --include-header=marshal.h \ + --body \ + --output=$@ \ + $< + +BUILT_SOURCES += marshal.h marshal.c +CLEANFILES += marshal.h marshal.c +EXTRA_DIST += marshal.list +</programlisting></informalexample> +<para> +In the example above, the first rule generates the header file and depends on +a <filename>marshal.list</filename> file in order to regenerate the result in +case the marshallers list is updated. The second rule generates the source file +for the same <filename>marshal.list</filename>, and includes the file generated +by the header rule. +</para> +</refsect1> + +<refsect1><title>Example</title> +<para> +To generate marshallers for the following callback functions: +</para> +<informalexample><programlisting> +void foo (gpointer data1, + gpointer data2); +void bar (gpointer data1, + gint param1, + gpointer data2); +gfloat baz (gpointer data1, + gboolean param1, + guchar param2, + gpointer data2); +</programlisting></informalexample> +<para> +The <filename>marshaller.list</filename> file has to look like this: +</para> +<programlisting> +VOID:VOID +VOID:INT +FLOAT:BOOLEAN,UCHAR +</programlisting> +<para> +and you call glib-genmarshal like this: +</para> +<programlisting> +glib-genmarshal --header marshaller.list > marshaller.h +glib-genmarshal --body marshaller.list > marshaller.c +</programlisting> +<para> +The generated marshallers have the arguments encoded in their function name. +For this particular list, they are +</para> +<programlisting> +g_cclosure_user_marshal_VOID__VOID(...), +g_cclosure_user_marshal_VOID__INT(...), +g_cclosure_user_marshal_FLOAT__BOOLEAN_UCHAR(...). +</programlisting> +<para> +They can be used directly for GClosures or be passed in as the +GSignalCMarshaller c_marshaller; argument upon creation of signals: +</para> +<informalexample><programlisting> +GClosure *cc_foo, *cc_bar, *cc_baz; + +cc_foo = g_cclosure_new (NULL, foo, NULL); +g_closure_set_marshal (cc_foo, g_cclosure_user_marshal_VOID__VOID); +cc_bar = g_cclosure_new (NULL, bar, NULL); +g_closure_set_marshal (cc_bar, g_cclosure_user_marshal_VOID__INT); +cc_baz = g_cclosure_new (NULL, baz, NULL); +g_closure_set_marshal (cc_baz, g_cclosure_user_marshal_FLOAT__BOOLEAN_UCHAR); +</programlisting></informalexample> +</refsect1> +<refsect1><title>See also</title> +<para> +<citerefentry> +<refentrytitle>glib-mkenums</refentrytitle> +<manvolnum>1</manvolnum> +</citerefentry> +</para> +</refsect1> +</refentry>
diff --git a/docs/reference/gobject/glib-mkenums.xml b/docs/reference/gobject/glib-mkenums.xml new file mode 100644 index 0000000..2200328 --- /dev/null +++ b/docs/reference/gobject/glib-mkenums.xml
@@ -0,0 +1,653 @@ +<refentry id="glib-mkenums" lang="en"> + +<refentryinfo> + <title>gdbus</title> + <productname>GObject</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Owen</firstname> + <surname>Taylor</surname> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> +<refentrytitle>glib-mkenums</refentrytitle> +<manvolnum>1</manvolnum> +<refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>glib-mkenums</refname> +<refpurpose>C language enum description generation utility</refpurpose> +</refnamediv> + +<refsynopsisdiv> +<cmdsynopsis> +<command>glib-mkenums</command> +<arg choice="opt" rep="repeat">OPTION</arg> +<arg choice="opt" rep="repeat">FILE</arg> +</cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para><command>glib-mkenums</command> is a small utility that parses C code to +extract enum definitions and produces enum descriptions based on text templates +specified by the user. Typically, you can use this tool to generate enumeration +types for the GType type system, for GObject properties and signal marshalling; +additionally, you can use it to generate enumeration values of GSettings schemas. +</para> + +<para><command>glib-mkenums</command> takes a list of valid C code files as +input. The options specified control the text that generated, substituting various +keywords enclosed in <literal>@</literal> characters in the templates. +</para> + +<refsect2><title>Production text substitutions</title> +<para> +Certain keywords enclosed in <literal>@</literal> characters will be substituted in the +emitted text. For the substitution examples of the keywords below, +the following example enum definition is assumed: +</para> +<informalexample><programlisting> +typedef enum +{ + PREFIX_THE_XVALUE = 1 << 3, + PREFIX_ANOTHER_VALUE = 1 << 4 +} PrefixTheXEnum; +</programlisting></informalexample> +<variablelist> +<varlistentry> +<term><literal>@EnumName@</literal>></term> +<listitem><para> +The name of the enum currently being processed, enum names are assumed to be +properly namespaced and to use mixed capitalization to separate +words (e.g. <literal>PrefixTheXEnum</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@enum_name@</literal></term> +<listitem><para> +The enum name with words lowercase and word-separated by underscores +(e.g. <literal>prefix_the_xenum</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@ENUMNAME@</literal></term> +<listitem><para> +The enum name with words uppercase and word-separated by underscores +(e.g. <literal>PREFIX_THE_XENUM</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@ENUMSHORT@</literal></term> +<listitem><para> +The enum name with words uppercase and word-separated by underscores, +prefix stripped (e.g. <literal>THE_XENUM</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@ENUMPREFIX@</literal></term> +<listitem><para> +The prefix of the enum name (e.g. <literal>PREFIX</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@VALUENAME@</literal></term> +<listitem><para> +The enum value name currently being processed with words uppercase and +word-separated by underscores, +this is the assumed literal notation of enum values in the C sources +(e.g. <literal>PREFIX_THE_XVALUE</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@valuenick@</literal></term> +<listitem><para> +A nick name for the enum value currently being processed, this is usually +generated by stripping common prefix words of all the enum values of the +current enum, the words are lowercase and underscores are substituted by a +minus (e.g. <literal>the-xvalue</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@valuenum@</literal></term> +<listitem><para> +The integer value for the enum value currently being processed. If the +evaluation fails then <command>glib-mkenums</command> will exit with an +error status, but this only happens if <literal>@valuenum@</literal> +appears in your value production template. (Since: 2.26) +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@type@</literal></term> +<listitem><para> +This is substituted either by "enum" or "flags", depending on whether the +enum value definitions contained bit-shift operators or not (e.g. <literal>flags</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@Type@</literal></term> +<listitem><para> +The same as <literal>@type@</literal> with the first letter capitalized (e.g. <literal>Flags</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@TYPE@</literal></term> +<listitem><para> +The same as <literal>@type@</literal> with all letters uppercased (e.g. <literal>FLAGS</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@filename@</literal></term> +<listitem><para> +The full path of the input file currently being processed (e.g. <literal>/build/environment/project/src/foo.h</literal>). +</para></listitem> +</varlistentry> + +<varlistentry> +<term><literal>@basename@</literal></term> +<listitem><para> +The base name of the input file currently being processed (e.g. <literal>foo.h</literal>). +Typically you want to use <literal>@basename@</literal> in place of <literal>@filename@</literal> +in your templates, to improve the reproducibility of the build. (Since: 2.22) +</para></listitem> +</varlistentry> +</variablelist> +</refsect2> +<refsect2><title>Trigraph extensions</title> +<para> +Some C comments are treated specially in the parsed enum definitions, +such comments start out with the trigraph sequence <literal>/*<</literal> +and end with the trigraph sequence <literal>>*/</literal>. +</para> + +<para>The following options can be specified per enum definition:</para> +<variablelist> +<varlistentry> +<term><literal>skip</literal></term> +<listitem><para> +Indicates this enum definition should be skipped. +</para></listitem> +</varlistentry> +<varlistentry> +<term><literal>flags</literal></term> +<listitem><para> +Indicates this enum should be treated as a flags definition. +</para></listitem> +</varlistentry> +<varlistentry> +<term><literal>underscore_name</literal></term> +<listitem><para> +Specifies the word separation used in the <function>*_get_type()</function> +function. For instance, <literal>/*< underscore_name=gnome_vfs_uri_hide_options >*/</literal>. +</para></listitem> +</varlistentry> +<varlistentry> +<term><literal>since</literal></term> +<listitem><para> +Specifies the version tag that will be used to substitute the <literal>@enumsince@</literal> +keyword in the template, useful when documenting methods generated from the enums +(e.g. <literal>Since: @enumsince@</literal>). (Since: 2.66) +</para></listitem> +</varlistentry> +</variablelist> + +<para>The following options can be specified per value definition:</para> +<variablelist> +<varlistentry> +<term><literal>skip</literal></term> +<listitem><para> +Indicates the value should be skipped. +</para></listitem> +</varlistentry> +<varlistentry> +<term><literal>nick</literal></term> +<listitem><para> +Specifies the otherwise auto-generated nickname. +</para></listitem> +</varlistentry> +</variablelist> + +<para>Examples:</para> +<informalexample><programlisting> +typedef enum /*< skip >*/ +{ + PREFIX_FOO +} PrefixThisEnumWillBeSkipped; +typedef enum /*< flags,prefix=PREFIX,since=1.0 >*/ +{ + PREFIX_THE_ZEROTH_VALUE, /*< skip >*/ + PREFIX_THE_FIRST_VALUE, + PREFIX_THE_SECOND_VALUE, + PREFIX_THE_THIRD_VALUE, /*< nick=the-last-value >*/ +} PrefixTheFlagsEnum; +</programlisting></informalexample> +</refsect2> +</refsect1> + +<refsect1><title>Options</title> +<variablelist> + +<varlistentry> +<term><option>--fhead</option> <replaceable>TEXT</replaceable></term> +<listitem><para> +Emits <replaceable>TEXT</replaceable> prior to processing input files. +</para> +<para> +You can specify this option multiple times, and the <replaceable>TEXT</replaceable> +will be concatenated. +</para> +<para> +When used along with a template file, <replaceable>TEXT</replaceable> +will be prepended to the template's <literal>file-header</literal> section. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--fprod</option> <replaceable>TEXT</replaceable></term> +<listitem><para> +Emits <replaceable>TEXT</replaceable> every time a new input file +is being processed. +</para> +<para> +You can specify this option multiple times, and the <replaceable>TEXT</replaceable> +will be concatenated. +</para> +<para> +When used along with a template file, <replaceable>TEXT</replaceable> +will be appended to the template's <literal>file-production</literal> section. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--ftail</option> <replaceable>TEXT</replaceable></term> +<listitem><para> +Emits <replaceable>TEXT</replaceable> after all input files have been +processed. +</para> +<para> +You can specify this option multiple times, and the <replaceable>TEXT</replaceable> +will be concatenated. +</para> +<para> +When used along with a template file, <replaceable>TEXT</replaceable> +will be appended to the template's <literal>file-tail</literal> section. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--eprod</option> <replaceable>TEXT</replaceable></term> +<listitem><para> +Emits <replaceable>TEXT</replaceable> every time an enum is encountered +in the input files. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--vhead</option> <replaceable>TEXT</replaceable></term> +<listitem><para> +Emits <replaceable>TEXT</replaceable> before iterating over the set of +values of an enum. +</para> +<para> +You can specify this option multiple times, and the <replaceable>TEXT</replaceable> +will be concatenated. +</para> +<para> +When used along with a template file, <replaceable>TEXT</replaceable> +will be prepended to the template's <literal>value-header</literal> section. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--vprod</option> <replaceable>TEXT</replaceable></term> +<listitem><para> +Emits <replaceable>TEXT</replaceable> for every value of an enum. +</para> +<para> +You can specify this option multiple times, and the <replaceable>TEXT</replaceable> +will be concatenated. +</para> +<para> +When used along with a template file, <replaceable>TEXT</replaceable> +will be appended to the template's <literal>value-production</literal> section. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--vtail</option> <replaceable>TEXT</replaceable></term> +<listitem><para> +Emits <replaceable>TEXT</replaceable> after iterating over all values +of an enum. +</para> +<para> +You can specify this option multiple times, and the <replaceable>TEXT</replaceable> +will be concatenated. +</para> +<para> +When used along with a template file, <replaceable>TEXT</replaceable> +will be appended to the template's <literal>value-tail</literal> section. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--comments</option> <replaceable>TEXT</replaceable></term> +<listitem><para> +Template for auto-generated comments, the default (for C code generations) is +<literal>"/* @comment@ */"</literal>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--template</option> <replaceable>FILE</replaceable></term> +<listitem><para> +Read templates from the given file. The templates are enclosed in +specially-formatted C comments: +</para> +<informalexample><programlisting> +/*** BEGIN section ***/ +/*** END section ***/ +</programlisting></informalexample> +<para> +<replaceable>section</replaceable> may be <literal>file-header</literal>, +<literal>file-production</literal>, <literal>file-tail</literal>, +<literal>enumeration-production</literal>, <literal>value-header</literal>, +<literal>value-production</literal>, <literal>value-tail</literal> or +<literal>comment</literal>. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--identifier-prefix</option> <replaceable>PREFIX</replaceable></term> +<listitem><para> +Indicates what portion of the enum name should be interpreted as the +prefix (eg, the "<literal>Gtk</literal>" in +"<literal>GtkDirectionType</literal>"). Normally this will be figured +out automatically, but you may need to override the default if your +namespace is capitalized oddly. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--symbol-prefix</option> <replaceable>PREFIX</replaceable></term> +<listitem><para> +Indicates what prefix should be used to correspond to the identifier +prefix in related C function names (eg, the "<literal>gtk</literal>" +in "<literal>gtk_direction_type_get_type</literal>". Equivalently, +this is the lowercase version of the prefix component of the enum +value names (eg, the "<literal>GTK</literal>" in +"<literal>GTK_DIR_UP</literal>". The default value is the identifier +prefix, converted to lowercase. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--help</option></term> +<listitem><para> +Print brief help and exit. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--version</option></term> +<listitem><para> +Print version and exit. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>--output=FILE</option></term> +<listitem><para> +Write output to FILE instead of stdout. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>@RSPFILE</option></term> +<listitem><para> +When passed as the sole argument, read and parse the actual arguments from +<literal>RSPFILE</literal>. Useful on systems with a low command-line length +limit. For example, Windows has a limit of 8191 characters. +</para></listitem> +</varlistentry> + +</variablelist> +</refsect1> + +<refsect1><title>Using templates</title> +<para> +Instead of passing the various sections of the generated file to the command +line of <command>glib-mkenums</command>, it's strongly recommended to use a +template file, especially for generating C sources. +</para> + +<para> +A C header template file will typically look like this: +</para> +<informalexample><programlisting> +/*** BEGIN file-header ***/ +#pragma once + +/* Include the main project header */ +#include "project.h" + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS +/*** END file-tail ***/ +</programlisting></informalexample> + +<para> +A C source template file will typically look like this: +</para> +<informalexample><programlisting> +/*** BEGIN file-header ***/ +#include "config.h" +#include "enum-types.h" + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static volatile gsize g_@type@_type_id__volatile; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + + GType g_@type@_type_id = + g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + + g_once_init_leave (&g_@type@_type_id__volatile, g_@type@_type_id); + } + return g_@type@_type_id__volatile; +} + +/*** END value-tail ***/ +</programlisting></informalexample> + +<para> +Template files are easier to modify and update, and can be used +to generate various types of outputs using the same command line +or tools during the build. +</para> +</refsect1> + +<refsect1><title>Using glib-mkenums with Meson</title> +<para> +Meson supports generating enumeration types using <command>glib-mkenums</command> +out of the box in its "gnome" module. +</para> + +<para> +In your <filename>meson.build</filename> file you will typically call the +<literal>gnome.mkenums_simple()</literal> method to generate idiomatic enumeration +types from a list of headers to inspect: +</para> +<informalexample><programlisting> +project_headers = [ + 'project-foo.h', + 'project-bar.h', + 'project-baz.h', +] + +gnome = import('gnome') +enum_files = gnome.mkenums_simple('enum-types', + sources: project_headers, +) +</programlisting></informalexample> + +<para> +The <literal>enum_files</literal> variable will contain an array of two elements +in the following order: +</para> +<itemizedlist> + <listitem><para>a build target for the source file</para></listitem> + <listitem><para>a build target for the header file</para></listitem> +</itemizedlist> +<para> +You should use the returned objects to provide a dependency on every other +build target that references the source or header file; for instance, if you +are using the source to build a library: +</para> +<informalexample><programlisting> +mainlib = library('project', + sources: project_sources + enum_files, + ... +) +</programlisting></informalexample> +<para> +Additionally, if you are including the generated header file inside a build +target that depends on the library you just built, you must ensure that the +internal dependency includes the generated header as a required source file: +</para> +<informalexample><programlisting> +mainlib_dep = declare_dependency(sources: enum_files[1], link_with: mainlib) +</programlisting></informalexample> +<para> +You should not include the generated source file as well, otherwise it will +be built separately for every target that depends on it, causing build +failures. To know more about why all this is required, please refer to the +<ulink url="https://mesonbuild.com/FAQ.html#how-do-i-tell-meson-that-my-sources-use-generated-headers"> +corresponding Meson FAQ entry</ulink>. +</para> + +<para> +If you are generating C header and source files that require special +templates, you can use <literal>gnome.mkenums()</literal> to provide those +headers, for instance: +</para> +<informalexample><programlisting> +enum_files = gnome.mkenums('enum-types', + sources: project_headers, + h_template: 'enum-types.h.in', + c_template: 'enum-types.c.in', + install_header: true, +) +</programlisting></informalexample> +<para> +For more information, see the <ulink url="https://mesonbuild.com/Gnome-module.html#gnomegenmarshal">Meson +documentation for <literal>gnome.mkenums()</literal></ulink>. +</para> +</refsect1> + +<refsect1><title>Using glib-mkenums with Autotools</title> +<para> +In order to use <command>glib-mkenums</command> in your project when using +Autotools as the build system, you will first need to modify your +<filename>configure.ac</filename> file to ensure you find the appropriate +command using <command>pkg-config</command>, similarly as to how you discover +the compiler and linker flags for GLib. +</para> +<informalexample><programlisting> +PKG_PROG_PKG_CONFIG([0.28]) + +PKG_CHECK_VAR([GLIB_MKENUMS], [glib-2.0], [glib_mkenums]) +</programlisting></informalexample> +<para> +In your <filename>Makefile.am</filename> file you will typically use rules +like these: +</para> +<informalexample><programlisting> +# A list of headers to inspect +project_headers = \ + project-foo.h \ + project-bar.h \ + project-baz.h + +enum-types.h: $(project_headers) enum-types.h.in + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template=enum-types.h.in \ + --output=$@ \ + $(project_headers) + +enum-types.c: $(project_headers) enum-types.c.in enum-types.h + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template=enum-types.c.in \ + --output=$@ \ + $(project_headers) + +# Build the enum types files before every other target +BUILT_SOURCES += enum-types.h enum-types.c +CLEANFILES += enum-types.h enum-types.c +EXTRA_DIST += enum-types.h.in enum-types.c.in +</programlisting></informalexample> +<para> +In the example above, we have a variable called <literal>project_headers</literal> +where we reference all header files we want to inspect for generating enumeration +GTypes. In the <filename>enum-types.h</filename> rule we use <command>glib-mkenums</command> +with a template called <filename>enum-types.h.in</filename> in order to generate the +header file; similarly, in the <filename>enum-types.c</filename> rule we use a +template called <filename>enum-types.c.in</filename>. +</para> +</refsect1> + +<refsect1><title>See also</title> +<para> +<citerefentry> +<refentrytitle>glib-genmarshal</refentrytitle> +<manvolnum>1</manvolnum> +</citerefentry> +</para> +</refsect1> +</refentry>
diff --git a/docs/reference/gobject/gobject-docs.xml b/docs/reference/gobject/gobject-docs.xml new file mode 100644 index 0000000..74cfcd9 --- /dev/null +++ b/docs/reference/gobject/gobject-docs.xml
@@ -0,0 +1,210 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.5//EN' + 'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd' [ + +<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'"> +<!ENTITY version SYSTEM "version.xml"> +]> +<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude"> + <bookinfo> + <title>GObject Reference Manual</title> + <releaseinfo> + for GObject &version; + The latest version of this documentation can be found on-line at + <ulink role="online-location" url="https://developer.gnome.org/gobject/unstable/">https://developer.gnome.org/gobject/unstable/</ulink>. + </releaseinfo> + </bookinfo> + + <preface> + <title>Introduction</title> + <para> + Most modern programming languages come with their own native object + systems and additional fundamental algorithmic language constructs. + Just as GLib serves as an implementation of such fundamental + types and algorithms (linked lists, hash tables and so forth), the + GLib Object System provides the required implementations of a + flexible, extensible, and intentionally easy to map (into other + languages) object-oriented framework for C. + The substantial elements that are provided can be summarized as: + <itemizedlist> + <listitem><para> + A generic type system to register arbitrary single-inherited + flat and deep derived types as well as interfaces for + structured types. + It takes care of creation, initialization and memory management + of the assorted object and class structures, maintains + parent/child relationships and deals with dynamic implementations + of such types. That is, their type specific implementations are + relocatable/unloadable during runtime. + </para></listitem> + <listitem><para> + A collection of fundamental type implementations, such as integers, + doubles, enums and structured types, to name a few. + </para></listitem> + <listitem><para> + A sample fundamental type implementation to base object hierarchies + upon - the GObject fundamental type. + </para></listitem> + <listitem><para> + A signal system that allows very flexible user customization of + virtual/overridable object methods and can serve as a powerful + notification mechanism. + </para></listitem> + <listitem><para> + An extensible parameter/value system, supporting all the provided + fundamental types that can be used to generically handle object + properties or otherwise parameterized types. + </para></listitem> + </itemizedlist> + </para> + </preface> + + <part label="I"> + <title>Concepts</title> + + <xi:include href="tut_intro.xml" /> + <xi:include href="tut_gtype.xml" /> + <xi:include href="tut_gobject.xml" /> + <xi:include href="tut_gsignal.xml" /> + </part> + <reference label="II"> + <title>API Reference</title> + + <xi:include href="xml/gtype.xml" /> + <xi:include href="xml/gtypeplugin.xml" /> + <xi:include href="xml/gtypemodule.xml" /> + <xi:include href="xml/objects.xml" /> + <xi:include href="xml/enumerations_flags.xml" /> + <xi:include href="xml/gboxed.xml" /> + <xi:include href="xml/generic_values.xml" /> + <xi:include href="xml/param_value_types.xml" /> + <xi:include href="xml/gparamspec.xml" /> + <xi:include href="xml/value_collection.xml" /> + <xi:include href="xml/signals.xml" /> + <xi:include href="xml/gclosure.xml" /> + <xi:include href="xml/value_arrays.xml" /> + <xi:include href="xml/gbinding.xml" /> + </reference> + <reference label="III"> + <title>Tools Reference</title> + + <xi:include href="glib-mkenums.xml" /> + <xi:include href="glib-genmarshal.xml" /> + <xi:include href="gobject-query.xml" /> + </reference> + + <xi:include href="tut_howto.xml" /> + <xi:include href="tut_tools.xml" /> + + <index id="api-index-full"> + <title>Index</title> + <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-deprecated" role="deprecated"> + <title>Index of deprecated symbols</title> + <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-2" role="2.2"> + <title>Index of new symbols in 2.2</title> + <xi:include href="xml/api-index-2.2.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-4" role="2.4"> + <title>Index of new symbols in 2.4</title> + <xi:include href="xml/api-index-2.4.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-6" role="2.6"> + <title>Index of new symbols in 2.6</title> + <xi:include href="xml/api-index-2.6.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-8" role="2.8"> + <title>Index of new symbols in 2.8</title> + <xi:include href="xml/api-index-2.8.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-10" role="2.10"> + <title>Index of new symbols in 2.10</title> + <xi:include href="xml/api-index-2.10.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-12" role="2.12"> + <title>Index of new symbols in 2.12</title> + <xi:include href="xml/api-index-2.12.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-14" role="2.14"> + <title>Index of new symbols in 2.14</title> + <xi:include href="xml/api-index-2.14.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-18" role="2.18"> + <title>Index of new symbols in 2.18</title> + <xi:include href="xml/api-index-2.18.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-22" role="2.22"> + <title>Index of new symbols in 2.22</title> + <xi:include href="xml/api-index-2.22.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-24" role="2.24"> + <title>Index of new symbols in 2.24</title> + <xi:include href="xml/api-index-2.24.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-26" role="2.26"> + <title>Index of new symbols in 2.26</title> + <xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-28" role="2.28"> + <title>Index of new symbols in 2.28</title> + <xi:include href="xml/api-index-2.28.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-30" role="2.30"> + <title>Index of new symbols in 2.30</title> + <xi:include href="xml/api-index-2.30.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-32" role="2.32"> + <title>Index of new symbols in 2.32</title> + <xi:include href="xml/api-index-2.32.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-34" role="2.34"> + <title>Index of new symbols in 2.34</title> + <xi:include href="xml/api-index-2.34.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-36" role="2.36"> + <title>Index of new symbols in 2.36</title> + <xi:include href="xml/api-index-2.36.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-38" role="2.38"> + <title>Index of new symbols in 2.38</title> + <xi:include href="xml/api-index-2.38.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-40" role="2.40"> + <title>Index of new symbols in 2.40</title> + <xi:include href="xml/api-index-2.40.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-42" role="2.42"> + <title>Index of new symbols in 2.42</title> + <xi:include href="xml/api-index-2.42.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-44" role="2.44"> + <title>Index of new symbols in 2.44</title> + <xi:include href="xml/api-index-2.44.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-46" role="2.46"> + <title>Index of new symbols in 2.46</title> + <xi:include href="xml/api-index-2.46.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-54" role="2.54"> + <title>Index of new symbols in 2.54</title> + <xi:include href="xml/api-index-2.54.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-56" role="2.56"> + <title>Index of new symbols in 2.56</title> + <xi:include href="xml/api-index-2.56.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-62" role="2.62"> + <title>Index of new symbols in 2.62</title> + <xi:include href="xml/api-index-2.62.xml"><xi:fallback /></xi:include> + </index> + <index id="api-index-2-66" role="2.66"> + <title>Index of new symbols in 2.66</title> + <xi:include href="xml/api-index-2.66.xml"><xi:fallback /></xi:include> + </index> + + <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> + +</book>
diff --git a/docs/reference/gobject/gobject-overrides.txt b/docs/reference/gobject/gobject-overrides.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/reference/gobject/gobject-overrides.txt
diff --git a/docs/reference/gobject/gobject-query.xml b/docs/reference/gobject/gobject-query.xml new file mode 100644 index 0000000..437d714 --- /dev/null +++ b/docs/reference/gobject/gobject-query.xml
@@ -0,0 +1,123 @@ +<refentry id="gobject-query" lang="en"> + +<refentryinfo> + <title>gobject-query</title> + <productname>GObject</productname> + <authorgroup> + <author> + <contrib>Developer</contrib> + <firstname>Tim</firstname> + <surname>Janik</surname> + </author> + </authorgroup> +</refentryinfo> + +<refmeta> +<refentrytitle>gobject-query</refentrytitle> +<manvolnum>1</manvolnum> +<refmiscinfo class="manual">User Commands</refmiscinfo> +</refmeta> + +<refnamediv> +<refname>gobject-query</refname> +<refpurpose>display a tree of types</refpurpose> +</refnamediv> + +<refsynopsisdiv> +<cmdsynopsis> +<command>gobject-query</command> +<arg choice="plain">froots</arg> +<arg choice="opt" rep="repeat">OPTION</arg> +</cmdsynopsis> +<cmdsynopsis> +<command>gobject-query</command> +<arg choice="plain">tree</arg> +<arg choice="opt" rep="repeat">OPTION</arg> +</cmdsynopsis> +</refsynopsisdiv> + +<refsect1><title>Description</title> +<para> +<command>gobject-query</command> is a small utility that draws a tree of +types. +</para> + +<para> +<command>gobject-query</command> takes a mandatory argument that specifies +whether it should iterate over the fundamental types or print a type tree. +</para> +</refsect1> + +<refsect1><title>Commands</title> +<variablelist> +<varlistentry> +<term><option>froots</option></term> +<listitem><para> +iterate over fundamental roots +</para></listitem> +</varlistentry> +<varlistentry> +<term><option>tree</option></term> +<listitem><para> +print type tree +</para></listitem> +</varlistentry> +</variablelist> +</refsect1> + +<refsect1><title>Options</title> +<variablelist> + +<varlistentry> +<term><option>-r</option> <replaceable>TYPE</replaceable></term> +<listitem><para> +specify the root type +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-n</option></term> +<listitem><para> +don't descend type tree +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-b</option> <replaceable>STRING</replaceable></term> +<listitem><para> +specify indent string +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-i</option> <replaceable>STRING</replaceable></term> +<listitem><para> +specify incremental indent string +</para></listitem> +</varlistentry> + + +<varlistentry> +<term><option>-s</option> <replaceable>NUMBER</replaceable></term> +<listitem><para> +specify line spacing +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-h</option>, <option>--help</option></term> +<listitem><para> +Print brief help and exit. +</para></listitem> +</varlistentry> + +<varlistentry> +<term><option>-v</option>, <option>--version</option></term> +<listitem><para> +Print version and exit. +</para></listitem> +</varlistentry> + +</variablelist> +</refsect1> +</refentry>
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt new file mode 100644 index 0000000..e5ffe5b --- /dev/null +++ b/docs/reference/gobject/gobject-sections.txt
@@ -0,0 +1,994 @@ +<INCLUDE>glib-object.h</INCLUDE> + +<SECTION> +<FILE>gtype</FILE> +<TITLE>Type Information</TITLE> +GType +G_TYPE_FUNDAMENTAL +G_TYPE_FUNDAMENTAL_MAX +G_TYPE_MAKE_FUNDAMENTAL +G_TYPE_IS_ABSTRACT +G_TYPE_IS_DERIVED +G_TYPE_IS_FUNDAMENTAL +G_TYPE_IS_VALUE_TYPE +G_TYPE_HAS_VALUE_TABLE +G_TYPE_IS_CLASSED +G_TYPE_IS_INSTANTIATABLE +G_TYPE_IS_DERIVABLE +G_TYPE_IS_DEEP_DERIVABLE +G_TYPE_IS_INTERFACE +GTypeInterface +GTypeInstance +GTypeClass +GTypeInfo +GTypeFundamentalInfo +GInterfaceInfo +GTypeValueTable +G_TYPE_FROM_INSTANCE +G_TYPE_FROM_CLASS +G_TYPE_FROM_INTERFACE +G_TYPE_INSTANCE_GET_CLASS +G_TYPE_INSTANCE_GET_INTERFACE +G_TYPE_INSTANCE_GET_PRIVATE +G_TYPE_CLASS_GET_PRIVATE +G_TYPE_CHECK_INSTANCE +G_TYPE_CHECK_INSTANCE_CAST +G_TYPE_CHECK_INSTANCE_TYPE +G_TYPE_CHECK_INSTANCE_FUNDAMENTAL_TYPE +G_TYPE_CHECK_CLASS_CAST +G_TYPE_CHECK_CLASS_TYPE +G_TYPE_CHECK_VALUE +G_TYPE_CHECK_VALUE_TYPE +G_TYPE_FLAG_RESERVED_ID_BIT +g_type_init +GTypeDebugFlags +g_type_init_with_debug_flags +g_type_name +g_type_qname +g_type_from_name +g_type_parent +g_type_depth +g_type_next_base +g_type_is_a +g_type_class_ref +g_type_class_peek +g_type_class_peek_static +g_type_class_unref +g_type_class_peek_parent +g_type_class_add_private +g_type_add_class_private +g_type_interface_peek +g_type_interface_peek_parent +g_type_default_interface_ref +g_type_default_interface_peek +g_type_default_interface_unref +g_type_children +g_type_interfaces +g_type_interface_prerequisites +g_type_set_qdata +g_type_get_qdata +g_type_query +GTypeQuery +GBaseInitFunc +GBaseFinalizeFunc +GClassInitFunc +GClassFinalizeFunc +GInstanceInitFunc +GInterfaceInitFunc +GInterfaceFinalizeFunc +GTypeClassCacheFunc +GTypeFlags +GTypeFundamentalFlags +g_type_register_static +g_type_register_static_simple +g_type_register_dynamic +g_type_register_fundamental +g_type_add_interface_static +g_type_add_interface_dynamic +g_type_interface_add_prerequisite +g_type_get_plugin +g_type_interface_get_plugin +g_type_fundamental_next +g_type_fundamental +g_type_create_instance +g_type_free_instance +g_type_add_class_cache_func +g_type_remove_class_cache_func +g_type_class_unref_uncached +g_type_add_interface_check +g_type_remove_interface_check +GTypeInterfaceCheckFunc +g_type_value_table_peek +g_type_ensure +g_type_get_type_registration_serial +g_type_get_instance_count + +G_DECLARE_FINAL_TYPE +G_DECLARE_DERIVABLE_TYPE +G_DECLARE_INTERFACE +G_DEFINE_TYPE +G_DEFINE_TYPE_WITH_PRIVATE +G_DEFINE_TYPE_WITH_CODE +G_DEFINE_ABSTRACT_TYPE +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE +G_DEFINE_ABSTRACT_TYPE_WITH_CODE +G_ADD_PRIVATE +G_PRIVATE_OFFSET +G_PRIVATE_FIELD +G_PRIVATE_FIELD_P +G_DEFINE_INTERFACE +G_DEFINE_INTERFACE_WITH_CODE +G_IMPLEMENT_INTERFACE +G_DEFINE_TYPE_EXTENDED +G_DEFINE_BOXED_TYPE +G_DEFINE_BOXED_TYPE_WITH_CODE +G_DEFINE_POINTER_TYPE +G_DEFINE_POINTER_TYPE_WITH_CODE + +<SUBSECTION Private> +G_TYPE_FUNDAMENTAL_SHIFT +g_type_check_instance +g_type_check_instance_cast +g_type_check_instance_is_a +g_type_check_instance_is_fundamentally_a +g_type_check_class_cast +g_type_check_class_is_a +g_type_check_is_value_type +g_type_check_value +g_type_check_value_holds +g_type_class_adjust_private_offset +g_type_add_instance_private +g_type_instance_get_private +g_type_class_get_instance_private_offset +g_type_class_get_private +g_type_test_flags +g_type_name_from_instance +g_type_name_from_class + +<SUBSECTION> +G_TYPE_INVALID +G_TYPE_NONE +G_TYPE_INTERFACE +G_TYPE_CHAR +G_TYPE_UCHAR +G_TYPE_BOOLEAN +G_TYPE_INT +G_TYPE_UINT +G_TYPE_LONG +G_TYPE_ULONG +G_TYPE_INT64 +G_TYPE_UINT64 +G_TYPE_ENUM +G_TYPE_FLAGS +G_TYPE_FLOAT +G_TYPE_DOUBLE +G_TYPE_STRING +G_TYPE_POINTER +G_TYPE_BOXED +G_TYPE_PARAM +G_TYPE_OBJECT +G_TYPE_GTYPE +G_TYPE_VARIANT +G_TYPE_CHECKSUM + +<SUBSECTION> +G_TYPE_RESERVED_GLIB_FIRST +G_TYPE_RESERVED_GLIB_LAST +G_TYPE_RESERVED_BSE_FIRST +G_TYPE_RESERVED_BSE_LAST +G_TYPE_RESERVED_USER_FIRST + +<SUBSECTION Private> +GOBJECT_VAR +</SECTION> + +<SECTION> +<FILE>gtypeplugin</FILE> +<TITLE>GTypePlugin</TITLE> +GTypePlugin +GTypePluginClass +GTypePluginUse +GTypePluginUnuse +GTypePluginCompleteTypeInfo +GTypePluginCompleteInterfaceInfo +g_type_plugin_use +g_type_plugin_unuse +g_type_plugin_complete_type_info +g_type_plugin_complete_interface_info +<SUBSECTION Standard> +G_TYPE_PLUGIN +G_IS_TYPE_PLUGIN +G_TYPE_TYPE_PLUGIN +g_type_plugin_get_type +G_TYPE_PLUGIN_CLASS +G_IS_TYPE_PLUGIN_CLASS +G_TYPE_PLUGIN_GET_CLASS +</SECTION> + +<SECTION> +<FILE>gtypemodule</FILE> +<TITLE>GTypeModule</TITLE> +GTypeModule +GTypeModuleClass +g_type_module_use +g_type_module_unuse +g_type_module_set_name +g_type_module_register_type +g_type_module_add_interface +g_type_module_register_enum +g_type_module_register_flags + +G_DEFINE_DYNAMIC_TYPE +G_DEFINE_DYNAMIC_TYPE_EXTENDED +G_IMPLEMENT_INTERFACE_DYNAMIC +G_ADD_PRIVATE_DYNAMIC + +<SUBSECTION Standard> +G_TYPE_MODULE +G_IS_TYPE_MODULE +G_TYPE_TYPE_MODULE +g_type_module_get_type +G_TYPE_MODULE_CLASS +G_IS_TYPE_MODULE_CLASS +G_TYPE_MODULE_GET_CLASS +</SECTION> + +<SECTION> +<TITLE>The Base Object Type</TITLE> +<FILE>objects</FILE> +GObject +GObjectClass +GObjectConstructParam +GObjectGetPropertyFunc +GObjectSetPropertyFunc +GObjectFinalizeFunc +G_TYPE_IS_OBJECT +G_OBJECT +G_IS_OBJECT +G_OBJECT_CLASS +G_IS_OBJECT_CLASS +G_OBJECT_GET_CLASS +G_OBJECT_TYPE +G_OBJECT_TYPE_NAME +G_OBJECT_CLASS_TYPE +G_OBJECT_CLASS_NAME +g_object_class_install_property +g_object_class_install_properties +g_object_class_find_property +g_object_class_list_properties +g_object_class_override_property +g_object_interface_install_property +g_object_interface_find_property +g_object_interface_list_properties +g_object_new +g_object_new_with_properties +g_object_newv +GParameter +g_object_ref +g_object_unref +g_object_ref_sink +g_set_object +g_clear_object +GInitiallyUnowned +GInitiallyUnownedClass +G_TYPE_INITIALLY_UNOWNED +g_object_is_floating +g_object_force_floating +GWeakNotify +g_object_weak_ref +g_object_weak_unref +g_object_add_weak_pointer +g_object_remove_weak_pointer +g_set_weak_pointer +g_clear_weak_pointer +GToggleNotify +g_object_add_toggle_ref +g_object_remove_toggle_ref +g_object_connect +g_object_disconnect +g_object_set +g_object_setv +g_object_get +g_object_getv +g_object_notify +g_object_notify_by_pspec +g_object_freeze_notify +g_object_thaw_notify +g_object_get_data +g_object_set_data +g_object_set_data_full +g_object_steal_data +g_object_dup_data +g_object_replace_data +g_object_get_qdata +g_object_set_qdata +g_object_set_qdata_full +g_object_steal_qdata +g_object_dup_qdata +g_object_replace_qdata +g_object_set_property +g_object_get_property +g_object_new_valist +g_object_set_valist +g_object_get_valist +g_object_watch_closure +g_object_run_dispose +G_OBJECT_WARN_INVALID_PROPERTY_ID + +<SUBSECTION Weak references> +GWeakRef +g_weak_ref_init +g_weak_ref_clear +g_weak_ref_get +g_weak_ref_set + +<SUBSECTION Testing> +g_assert_finalize_object + +<SUBSECTION Standard> +G_INITIALLY_UNOWNED +G_INITIALLY_UNOWNED_CLASS +G_INITIALLY_UNOWNED_GET_CLASS +G_IS_INITIALLY_UNOWNED +G_IS_INITIALLY_UNOWNED_CLASS + +<SUBSECTION Private> +G_OBJECT_WARN_INVALID_PSPEC +g_initially_unowned_get_type +g_object_compat_control +g_object_get_type +</SECTION> + +<SECTION> +<TITLE>Enumeration and Flag Types</TITLE> +<FILE>enumerations_flags</FILE> +GEnumClass +GFlagsClass +G_ENUM_CLASS_TYPE +G_ENUM_CLASS_TYPE_NAME +G_TYPE_IS_ENUM +G_ENUM_CLASS +G_IS_ENUM_CLASS +G_TYPE_IS_FLAGS +G_FLAGS_CLASS +G_IS_FLAGS_CLASS +G_FLAGS_CLASS_TYPE +G_FLAGS_CLASS_TYPE_NAME +GEnumValue +GFlagsValue +g_enum_get_value +g_enum_get_value_by_name +g_enum_get_value_by_nick +g_enum_to_string +g_flags_get_first_value +g_flags_get_value_by_name +g_flags_get_value_by_nick +g_flags_to_string +g_enum_register_static +g_flags_register_static +g_enum_complete_type_info +g_flags_complete_type_info +</SECTION> + +<SECTION> +<FILE>gboxed</FILE> +<TITLE>Boxed Types</TITLE> +GBoxedCopyFunc +GBoxedFreeFunc +g_boxed_copy +g_boxed_free +g_boxed_type_register_static +g_pointer_type_register_static + +<SUBSECTION> +G_TYPE_HASH_TABLE +G_TYPE_DATE +G_TYPE_GSTRING +G_TYPE_STRV +G_TYPE_REGEX +G_TYPE_MATCH_INFO +G_TYPE_ARRAY +G_TYPE_BYTE_ARRAY +G_TYPE_PTR_ARRAY +G_TYPE_BYTES +G_TYPE_VARIANT_TYPE +G_TYPE_ERROR +G_TYPE_DATE_TIME +G_TYPE_TIME_ZONE +G_TYPE_IO_CHANNEL +G_TYPE_IO_CONDITION +G_TYPE_VARIANT_BUILDER +G_TYPE_VARIANT_DICT +G_TYPE_KEY_FILE +G_TYPE_MAIN_CONTEXT +G_TYPE_MAIN_LOOP +G_TYPE_MAPPED_FILE +G_TYPE_MARKUP_PARSE_CONTEXT +G_TYPE_SOURCE +G_TYPE_POLLFD +G_TYPE_THREAD +G_TYPE_OPTION_GROUP + +<SUBSECTION Standard> +G_TYPE_IS_BOXED + +<SUBSECTION Private> +g_gstring_get_type +g_strv_get_type +g_date_get_type +g_hash_table_get_type +g_regex_get_type +g_match_info_get_type +g_array_get_type +g_byte_array_get_type +g_ptr_array_get_type +g_error_get_type +g_date_time_get_type +g_time_zone_get_type +g_variant_get_gtype +g_variant_type_get_gtype +g_variant_builder_get_type +g_variant_dict_get_type +g_gtype_get_type +g_main_context_get_type +g_main_loop_get_type +g_source_get_type +g_pollfd_get_type +g_bytes_get_type +g_key_file_get_type +g_checksum_get_type +g_mapped_file_get_type +g_markup_parse_context_get_type +g_thread_get_type +g_option_group_get_type +</SECTION> + +<SECTION> +<TITLE>Generic values</TITLE> +<FILE>generic_values</FILE> +G_VALUE_INIT +G_VALUE_HOLDS +G_VALUE_TYPE +G_VALUE_TYPE_NAME +G_TYPE_IS_VALUE +G_TYPE_IS_VALUE_ABSTRACT +G_IS_VALUE +GValue +G_TYPE_VALUE +G_TYPE_VALUE_ARRAY +g_value_init +g_value_copy +g_value_reset +g_value_unset +g_value_init_from_instance +g_value_set_instance +g_value_fits_pointer +g_value_peek_pointer +g_value_type_compatible +g_value_type_transformable +g_value_transform +GValueTransform +g_value_register_transform_func +g_strdup_value_contents + +<SUBSECTION Private> +G_VALUE_NOCOPY_CONTENTS +g_value_get_type +g_value_array_get_type +</SECTION> + +<SECTION> +<TITLE>Value arrays</TITLE> +<FILE>value_arrays</FILE> +GValueArray +g_value_array_get_nth +g_value_array_new +g_value_array_copy +g_value_array_free +g_value_array_append +g_value_array_prepend +g_value_array_insert +g_value_array_remove +g_value_array_sort +g_value_array_sort_with_data +</SECTION> + +<SECTION> +<TITLE>GParamSpec</TITLE> +<FILE>gparamspec</FILE> +G_TYPE_IS_PARAM +G_PARAM_SPEC +G_IS_PARAM_SPEC +G_PARAM_SPEC_CLASS +G_IS_PARAM_SPEC_CLASS +G_PARAM_SPEC_GET_CLASS +G_PARAM_SPEC_TYPE +G_PARAM_SPEC_TYPE_NAME +G_PARAM_SPEC_VALUE_TYPE +GParamSpec +GParamSpecClass +GParamFlags +G_PARAM_STATIC_STRINGS +G_PARAM_MASK +G_PARAM_USER_SHIFT +g_param_spec_ref +g_param_spec_unref +g_param_spec_sink +g_param_spec_ref_sink +g_param_spec_get_default_value +g_param_value_set_default +g_param_value_defaults +g_param_value_validate +g_param_value_convert +g_param_values_cmp +g_param_spec_is_valid_name +g_param_spec_get_name +g_param_spec_get_name_quark +g_param_spec_get_nick +g_param_spec_get_blurb +g_param_spec_get_qdata +g_param_spec_set_qdata +g_param_spec_set_qdata_full +g_param_spec_steal_qdata +g_param_spec_get_redirect_target +g_param_spec_internal +GParamSpecTypeInfo +g_param_type_register_static +GParamSpecPool +g_param_spec_pool_new +g_param_spec_pool_insert +g_param_spec_pool_remove +g_param_spec_pool_lookup +g_param_spec_pool_list +g_param_spec_pool_list_owned +</SECTION> + +<SECTION> +<TITLE>Standard Parameter and Value Types</TITLE> +<FILE>param_value_types</FILE> + +<SUBSECTION gboolean> +G_IS_PARAM_SPEC_BOOLEAN +G_PARAM_SPEC_BOOLEAN +G_VALUE_HOLDS_BOOLEAN +G_TYPE_PARAM_BOOLEAN +GParamSpecBoolean +g_param_spec_boolean +g_value_set_boolean +g_value_get_boolean + +<SUBSECTION gchar> +G_IS_PARAM_SPEC_CHAR +G_PARAM_SPEC_CHAR +G_VALUE_HOLDS_CHAR +G_TYPE_PARAM_CHAR +GParamSpecChar +g_param_spec_char +g_value_set_char +g_value_get_char +g_value_get_schar +g_value_set_schar + +<SUBSECTION guchar> +G_IS_PARAM_SPEC_UCHAR +G_PARAM_SPEC_UCHAR +G_VALUE_HOLDS_UCHAR +G_TYPE_PARAM_UCHAR +GParamSpecUChar +g_param_spec_uchar +g_value_set_uchar +g_value_get_uchar + +<SUBSECTION gint> +G_IS_PARAM_SPEC_INT +G_PARAM_SPEC_INT +G_VALUE_HOLDS_INT +G_TYPE_PARAM_INT +GParamSpecInt +g_param_spec_int +g_value_set_int +g_value_get_int + +<SUBSECTION guint> +G_IS_PARAM_SPEC_UINT +G_PARAM_SPEC_UINT +G_VALUE_HOLDS_UINT +G_TYPE_PARAM_UINT +GParamSpecUInt +g_param_spec_uint +g_value_set_uint +g_value_get_uint + +<SUBSECTION glong> +G_IS_PARAM_SPEC_LONG +G_PARAM_SPEC_LONG +G_VALUE_HOLDS_LONG +G_TYPE_PARAM_LONG +GParamSpecLong +g_param_spec_long +g_value_set_long +g_value_get_long + +<SUBSECTION gulong> +G_IS_PARAM_SPEC_ULONG +G_PARAM_SPEC_ULONG +G_VALUE_HOLDS_ULONG +G_TYPE_PARAM_ULONG +GParamSpecULong +g_param_spec_ulong +g_value_set_ulong +g_value_get_ulong + +<SUBSECTION gint64> +G_IS_PARAM_SPEC_INT64 +G_PARAM_SPEC_INT64 +G_VALUE_HOLDS_INT64 +G_TYPE_PARAM_INT64 +GParamSpecInt64 +g_param_spec_int64 +g_value_set_int64 +g_value_get_int64 + +<SUBSECTION guint64> +G_IS_PARAM_SPEC_UINT64 +G_PARAM_SPEC_UINT64 +G_VALUE_HOLDS_UINT64 +G_TYPE_PARAM_UINT64 +GParamSpecUInt64 +g_param_spec_uint64 +g_value_set_uint64 +g_value_get_uint64 + +<SUBSECTION gfloat> +G_IS_PARAM_SPEC_FLOAT +G_PARAM_SPEC_FLOAT +G_VALUE_HOLDS_FLOAT +G_TYPE_PARAM_FLOAT +GParamSpecFloat +g_param_spec_float +g_value_set_float +g_value_get_float + +<SUBSECTION gdouble> +G_IS_PARAM_SPEC_DOUBLE +G_PARAM_SPEC_DOUBLE +G_VALUE_HOLDS_DOUBLE +G_TYPE_PARAM_DOUBLE +GParamSpecDouble +g_param_spec_double +g_value_set_double +g_value_get_double + +<SUBSECTION GEnum> +G_IS_PARAM_SPEC_ENUM +G_PARAM_SPEC_ENUM +G_VALUE_HOLDS_ENUM +G_TYPE_PARAM_ENUM +GParamSpecEnum +g_param_spec_enum +g_value_set_enum +g_value_get_enum + +<SUBSECTION GFLags> +G_IS_PARAM_SPEC_FLAGS +G_PARAM_SPEC_FLAGS +G_VALUE_HOLDS_FLAGS +G_TYPE_PARAM_FLAGS +GParamSpecFlags +g_param_spec_flags +g_value_set_flags +g_value_get_flags + +<SUBSECTION gchararray> +G_IS_PARAM_SPEC_STRING +G_PARAM_SPEC_STRING +G_VALUE_HOLDS_STRING +G_TYPE_PARAM_STRING +G_VALUE_IS_INTERNED_STRING +G_VALUE_INTERNED_STRING +GParamSpecString +gchararray +g_param_spec_string +g_value_set_string +g_value_set_static_string +g_value_take_string +g_value_set_string_take_ownership +g_value_get_string +g_value_dup_string +g_value_set_interned_string + +<SUBSECTION GParamSpec> +G_IS_PARAM_SPEC_PARAM +G_PARAM_SPEC_PARAM +G_VALUE_HOLDS_PARAM +G_TYPE_PARAM_PARAM +GParamSpecParam +g_param_spec_param +g_value_set_param +g_value_take_param +g_value_set_param_take_ownership +g_value_get_param +g_value_dup_param + +<SUBSECTION GBoxed> +G_IS_PARAM_SPEC_BOXED +G_PARAM_SPEC_BOXED +G_VALUE_HOLDS_BOXED +G_TYPE_PARAM_BOXED +GParamSpecBoxed +g_param_spec_boxed +g_value_set_boxed +g_value_set_static_boxed +g_value_take_boxed +g_value_set_boxed_take_ownership +g_value_get_boxed +g_value_dup_boxed + +<SUBSECTION gpointer> +G_IS_PARAM_SPEC_POINTER +G_PARAM_SPEC_POINTER +G_VALUE_HOLDS_POINTER +G_TYPE_PARAM_POINTER +GParamSpecPointer +g_param_spec_pointer +g_value_set_pointer +g_value_get_pointer + +<SUBSECTION GObject> +G_IS_PARAM_SPEC_OBJECT +G_PARAM_SPEC_OBJECT +G_VALUE_HOLDS_OBJECT +G_TYPE_PARAM_OBJECT +GParamSpecObject +g_param_spec_object +g_value_set_object +g_value_take_object +g_value_set_object_take_ownership +g_value_get_object +g_value_dup_object + +<SUBSECTION gunichar> +G_IS_PARAM_SPEC_UNICHAR +G_PARAM_SPEC_UNICHAR +G_TYPE_PARAM_UNICHAR +GParamSpecUnichar +g_param_spec_unichar + +<SUBSECTION GValueArray> +G_IS_PARAM_SPEC_VALUE_ARRAY +G_PARAM_SPEC_VALUE_ARRAY +G_TYPE_PARAM_VALUE_ARRAY +GParamSpecValueArray +g_param_spec_value_array + +<SUBSECTION Override> +G_IS_PARAM_SPEC_OVERRIDE +G_PARAM_SPEC_OVERRIDE +G_TYPE_PARAM_OVERRIDE +GParamSpecOverride +g_param_spec_override + +<SUBSECTION GType> +G_IS_PARAM_SPEC_GTYPE +G_PARAM_SPEC_GTYPE +G_VALUE_HOLDS_GTYPE +G_TYPE_PARAM_GTYPE +GParamSpecGType +g_param_spec_gtype +g_value_get_gtype +g_value_set_gtype + +<SUBSECTION GVariant> +G_IS_PARAM_SPEC_VARIANT +G_PARAM_SPEC_VARIANT +G_VALUE_HOLDS_VARIANT +G_TYPE_PARAM_VARIANT +GParamSpecVariant +g_param_spec_variant +g_value_get_variant +g_value_dup_variant +g_value_set_variant +g_value_take_variant + +<SUBSECTION Private> +g_value_set_instance +g_param_spec_types +</SECTION> + +<SECTION> +<TITLE>Varargs Value Collection</TITLE> +<FILE>value_collection</FILE> +<INCLUDE>glib-object.h,gobject/gvaluecollector.h</INCLUDE> +GTypeCValue +G_VALUE_COLLECT_INIT +G_VALUE_COLLECT +G_VALUE_COLLECT_SKIP +G_VALUE_LCOPY +G_VALUE_COLLECT_FORMAT_MAX_LENGTH +</SECTION> + +<SECTION> +<TITLE>Signals</TITLE> +<FILE>signals</FILE> +GSignalInvocationHint +GSignalAccumulator +GSignalCMarshaller +GSignalCVaMarshaller +GSignalEmissionHook +GSignalFlags +GSignalMatchType +GSignalQuery +G_SIGNAL_TYPE_STATIC_SCOPE +G_SIGNAL_MATCH_MASK +G_SIGNAL_FLAGS_MASK +g_signal_new +g_signal_newv +g_signal_new_valist +g_signal_set_va_marshaller +g_signal_query +g_signal_lookup +g_signal_name +g_signal_list_ids +g_signal_emit +g_signal_emit_by_name +g_signal_emitv +g_signal_emit_valist +g_signal_connect +g_signal_connect_after +g_signal_connect_swapped +g_signal_connect_object +GConnectFlags +g_signal_connect_data +g_signal_connect_closure +g_signal_connect_closure_by_id +g_signal_handler_block +g_signal_handler_unblock +g_signal_handler_disconnect +g_signal_handler_find +g_signal_handlers_block_matched +g_signal_handlers_unblock_matched +g_signal_handlers_disconnect_matched +g_signal_handler_is_connected +g_signal_handlers_block_by_func +g_signal_handlers_unblock_by_func +g_signal_handlers_disconnect_by_func +g_signal_handlers_disconnect_by_data +g_signal_has_handler_pending +g_signal_stop_emission +g_signal_stop_emission_by_name +g_signal_override_class_closure +g_signal_chain_from_overridden +g_signal_new_class_handler +g_signal_override_class_handler +g_signal_chain_from_overridden_handler +g_signal_add_emission_hook +g_signal_remove_emission_hook +g_signal_is_valid_name +g_signal_parse_name +g_signal_get_invocation_hint +g_signal_type_cclosure_new +g_signal_accumulator_first_wins +g_signal_accumulator_true_handled +g_clear_signal_handler +<SUBSECTION Private> +g_signal_handlers_destroy +</SECTION> + +<SECTION> +<FILE>gclosure</FILE> +<TITLE>Closures</TITLE> +G_CLOSURE_NEEDS_MARSHAL +G_CLOSURE_N_NOTIFIERS +G_CCLOSURE_SWAP_DATA +G_CALLBACK +GCallback +GClosure +G_TYPE_CLOSURE +GCClosure +GClosureMarshal +GVaClosureMarshal +GClosureNotify +g_cclosure_new +g_cclosure_new_swap +g_cclosure_new_object +g_cclosure_new_object_swap +g_cclosure_marshal_generic +g_closure_new_object +g_closure_ref +g_closure_sink +g_closure_unref +g_closure_invoke +g_closure_invalidate +g_closure_add_finalize_notifier +g_closure_add_invalidate_notifier +g_closure_remove_finalize_notifier +g_closure_remove_invalidate_notifier +g_closure_new_simple +g_closure_set_marshal +g_closure_add_marshal_guards +g_closure_set_meta_marshal +g_source_set_closure +g_source_set_dummy_callback + +<SUBSECTION> +g_cclosure_marshal_VOID__VOID +g_cclosure_marshal_VOID__BOOLEAN +g_cclosure_marshal_VOID__CHAR +g_cclosure_marshal_VOID__UCHAR +g_cclosure_marshal_VOID__INT +g_cclosure_marshal_VOID__UINT +g_cclosure_marshal_VOID__LONG +g_cclosure_marshal_VOID__ULONG +g_cclosure_marshal_VOID__ENUM +g_cclosure_marshal_VOID__FLAGS +g_cclosure_marshal_VOID__FLOAT +g_cclosure_marshal_VOID__DOUBLE +g_cclosure_marshal_VOID__STRING +g_cclosure_marshal_VOID__PARAM +g_cclosure_marshal_VOID__BOXED +g_cclosure_marshal_VOID__POINTER +g_cclosure_marshal_VOID__OBJECT +g_cclosure_marshal_VOID__VARIANT +g_cclosure_marshal_STRING__OBJECT_POINTER +g_cclosure_marshal_VOID__UINT_POINTER +g_cclosure_marshal_BOOLEAN__FLAGS +g_cclosure_marshal_BOOL__FLAGS +g_cclosure_marshal_BOOLEAN__BOXED_BOXED +g_cclosure_marshal_BOOL__BOXED_BOXED + +<SUBSECTION> +g_cclosure_marshal_generic_va +g_cclosure_marshal_VOID__VOIDv +g_cclosure_marshal_VOID__BOOLEANv +g_cclosure_marshal_VOID__CHARv +g_cclosure_marshal_VOID__UCHARv +g_cclosure_marshal_VOID__INTv +g_cclosure_marshal_VOID__UINTv +g_cclosure_marshal_VOID__LONGv +g_cclosure_marshal_VOID__ULONGv +g_cclosure_marshal_VOID__ENUMv +g_cclosure_marshal_VOID__FLAGSv +g_cclosure_marshal_VOID__FLOATv +g_cclosure_marshal_VOID__DOUBLEv +g_cclosure_marshal_VOID__STRINGv +g_cclosure_marshal_VOID__PARAMv +g_cclosure_marshal_VOID__BOXEDv +g_cclosure_marshal_VOID__POINTERv +g_cclosure_marshal_VOID__OBJECTv +g_cclosure_marshal_VOID__VARIANTv +g_cclosure_marshal_STRING__OBJECT_POINTERv +g_cclosure_marshal_VOID__UINT_POINTERv +g_cclosure_marshal_BOOLEAN__FLAGSv +g_cclosure_marshal_BOOLEAN__BOXED_BOXEDv + +<SUBSECTION Private> +GClosureNotifyData +g_closure_get_type +g_io_channel_get_type +g_io_condition_get_type +</SECTION> + +<SECTION> +<FILE>gbinding</FILE> +GBinding +GBindingFlags +g_binding_get_source +g_binding_get_source_property +g_binding_get_target +g_binding_get_target_property +g_binding_get_flags +g_binding_unbind +<SUBSECTION> +g_object_bind_property +GBindingTransformFunc +g_object_bind_property_full +g_object_bind_property_with_closures +<SUBSECTION Standard> +G_TYPE_BINDING +G_TYPE_BINDING_FLAGS +G_BINDING +G_IS_BINDING +<SUBSECTION Private> +g_binding_flags_get_type +g_binding_get_type +</SECTION>
diff --git a/docs/reference/gobject/images/glue.png b/docs/reference/gobject/images/glue.png new file mode 100644 index 0000000..f5f3aab --- /dev/null +++ b/docs/reference/gobject/images/glue.png Binary files differ
diff --git a/docs/reference/gobject/meson.build b/docs/reference/gobject/meson.build new file mode 100644 index 0000000..a9a6543 --- /dev/null +++ b/docs/reference/gobject/meson.build
@@ -0,0 +1,68 @@ +if get_option('gtk_doc') + subdir('xml') + + ignore_headers = [ + 'tests', + 'gatomicarray.h', + 'gobject_probes.h', + 'gobject_trace.h', + 'gtype-private.h', + 'glib-enumtypes.h', + ] + + docpath = join_paths(glib_datadir, 'gtk-doc', 'html') + version_conf = configuration_data() + version_conf.set('GLIB_VERSION', meson.project_version()) + configure_file( + input: 'version.xml.in', + output: 'version.xml', + configuration: version_conf + ) + + gtkdocincl = include_directories('.') + + gnome.gtkdoc('gobject', + main_xml : 'gobject-docs.xml', + namespace : 'g', + mode : 'none', + dependencies : [libgobject_dep, libglib_dep], + include_directories : [gtkdocincl], + src_dir : 'gobject', + scan_args : gtkdoc_common_scan_args + [ + '--rebuild-types', + '--ignore-headers=' + ' '.join(ignore_headers), + ], + content_files : [ + 'glib-mkenums.xml', + 'glib-genmarshal.xml', + 'gobject-query.xml', + 'tut_gobject.xml', + 'tut_gsignal.xml', + 'tut_gtype.xml', + 'tut_howto.xml', + 'tut_intro.xml', + 'tut_tools.xml' + ], + html_assets : [ + 'images/glue.png' + ], + fixxref_args: [ + '--html-dir=' + docpath, + '--extra-dir=' + join_paths('gobject', '..', 'glib', 'html'), + ], + install: true, + check: true, + ) +endif + +if get_option('man') + manpages = ['glib-mkenums', 'glib-genmarshal', 'gobject-query'] + foreach page : manpages + custom_target(page + '-man', + input: page + '.xml', + output: page + '.1', + command: xsltproc_command, + install: true, + install_dir: man1_dir) + endforeach +endif
diff --git a/docs/reference/gobject/tut_gobject.xml b/docs/reference/gobject/tut_gobject.xml new file mode 100644 index 0000000..fc7d6fe --- /dev/null +++ b/docs/reference/gobject/tut_gobject.xml
@@ -0,0 +1,728 @@ +<?xml version='1.0' encoding="UTF-8"?> +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<chapter id="chapter-gobject"> + <title>The GObject base class</title> + + <para> + The previous chapter discussed the details of GLib's Dynamic Type System. + The GObject library also contains an implementation for a base fundamental + type named <link linkend="GObject"><type>GObject</type></link>. + </para> + + <para> + <link linkend="GObject"><type>GObject</type></link> is a fundamental classed instantiable type. It implements: + <itemizedlist> + <listitem><para>Memory management with reference counting</para></listitem> + <listitem><para>Construction/Destruction of instances</para></listitem> + <listitem><para>Generic per-object properties with set/get function pairs</para></listitem> + <listitem><para>Easy use of signals</para></listitem> + </itemizedlist> + All the GNOME libraries which use the GLib type system (like GTK+ and GStreamer) + inherit from <link linkend="GObject"><type>GObject</type></link> which is why it is important to understand + the details of how it works. + </para> + + <sect1 id="gobject-instantiation"> + <title>Object instantiation</title> + + <para> + The <function><link linkend="g-object-new">g_object_new</link></function> + family of functions can be used to instantiate any GType which inherits + from the GObject base type. All these functions make sure the class and + instance structures have been correctly initialized by GLib's type system + and then invoke at one point or another the constructor class method + which is used to: + <itemizedlist> + <listitem><para> + Allocate and clear memory through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>, + </para></listitem> + <listitem><para> + Initialize the object's instance with the construction properties. + </para></listitem> + </itemizedlist> + Although one can expect all class and instance members (except the fields + pointing to the parents) to be set to zero, some consider it good practice + to explicitly set them. + </para> + + <para> + Once all construction operations have been completed and constructor + properties set, the constructed class method is called. + </para> + + <para> + Objects which inherit from GObject are allowed to override this + constructed class method. + The example below shows how <type>ViewerFile</type> overrides the parent's construction process: +<informalexample><programlisting> +#define VIEWER_TYPE_FILE viewer_file_get_type () +G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) + +struct _ViewerFile +{ + GObject parent_instance; + + /* instance members */ + gchar *filename; + guint zoom_level; +}; + +/* will create viewer_file_get_type and set viewer_file_parent_class */ +G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT) + +static void +viewer_file_constructed (GObject *obj) +{ + /* update the object state depending on constructor properties */ + + /* Always chain up to the parent constructed function to complete object + * initialisation. */ + G_OBJECT_CLASS (viewer_file_parent_class)->constructed (obj); +} + +static void +viewer_file_finalize (GObject *obj) +{ + ViewerFile *self = VIEWER_FILE (obj); + + g_free (self->filename); + + /* Always chain up to the parent finalize function to complete object + * destruction. */ + G_OBJECT_CLASS (viewer_file_parent_class)->finalize (obj); +} + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = viewer_file_constructed; + object_class->finalize = viewer_file_finalize; +} + +static void +viewer_file_init (ViewerFile *self) +{ + /* initialize the object */ +} + +</programlisting></informalexample> + If the user instantiates an object <type>ViewerFile</type> with: +<informalexample><programlisting> +ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL); +</programlisting></informalexample> + If this is the first instantiation of such an object, the + <function>viewer_file_class_init</function> function will be invoked + after any <function>viewer_file_base_class_init</function> function. + This will make sure the class structure of this new object is + correctly initialized. Here, <function>viewer_file_class_init</function> + is expected to override the object's class methods and setup the + class' own methods. In the example above, the <literal>constructed</literal> + method is the only overridden method: it is set to + <function>viewer_file_constructed</function>. + </para> + + <para> + Once <function><link linkend="g-object-new">g_object_new</link></function> has obtained a reference to an initialized + class structure, it invokes its constructor method to create an instance of the new + object, if the constructor has been overridden in <function>viewer_file_class_init</function>. + Overridden constructors must chain up to their parent’s constructor. In + order to find the parent class and chain up to the parent class + constructor, we can use the <literal>viewer_file_parent_class</literal> + pointer that has been set up for us by the + <link linkend="G-DEFINE-TYPE:CAPS"><literal>G_DEFINE_TYPE</literal></link> + macro. + </para> + + <para> + Finally, at one point or another, <function>g_object_constructor</function> is invoked + by the last constructor in the chain. This function allocates the object's instance buffer + through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> + which means that the <function>instance_init</function> function is invoked at this point if one + was registered. After <function>instance_init</function> returns, the object is fully initialized and should be + ready to have its methods called by the user. When + <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> + returns, <function>g_object_constructor</function> sets the construction properties + (i.e. the properties which were given to <function><link linkend="g-object-new">g_object_new</link></function>) and returns + to the user's constructor. + </para> + + <para> + The process described above might seem a bit complicated, but it can be + summarized easily by the table below which lists the functions invoked + by <function><link linkend="g-object-new">g_object_new</link></function> + and their order of invocation: + </para> + + <para> + <table id="gobject-construction-table"> + <title><function><link linkend="g-object-new">g_object_new</link></function></title> + <tgroup cols="3"> + <colspec colwidth="*" colnum="1" align="left"/> + <colspec colwidth="*" colnum="2" align="left"/> + <colspec colwidth="8*" colnum="3" align="left"/> + + <thead> + <row> + <entry>Invocation time</entry> + <entry>Function invoked</entry> + <entry>Function's parameters</entry> + <entry>Remark</entry> + </row> + </thead> + <tbody> + <row> + <entry morerows="3">First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry> + <entry>target type's <function>base_init</function> function</entry> + <entry>On the inheritance tree of classes from fundamental type to target type. + <function>base_init</function> is invoked once for each class structure.</entry> + <entry>Never used in practice. Unlikely you will need it.</entry> + </row> + <row> + <!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> + <entry>target type's <function>class_init</function> function</entry> + <entry>On target type's class structure</entry> + <entry> + Here, you should make sure to initialize or override class methods (that is, + assign to each class' method its function pointer) and create the signals and + the properties associated to your object. + </entry> + </row> + <row> + <!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> + <entry>interface's <function>base_init</function> function</entry> + <entry>On interface's vtable</entry> + <entry></entry> + </row> + <row> + <!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> + <entry>interface's <function>interface_init</function> function</entry> + <entry>On interface's vtable</entry> + <entry></entry> + </row> + <row> + <entry morerows="2">Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry> + <entry>target type's class <function>constructor</function> method: <function>GObjectClass->constructor</function></entry> + <entry>On object's instance</entry> + <entry> + If you need to handle construct properties in a custom way, or implement a singleton class, override the constructor + method and make sure to chain up to the object's + parent class before doing your own initialization. + In doubt, do not override the constructor method. + </entry> + </row> + <row> + <!--entry>Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> + <entry>type's <function>instance_init</function> function</entry> + <entry>On the inheritance tree of classes from fundamental type to target type. + the <function>instance_init</function> provided for each type is invoked once for each instance + structure.</entry> + <entry> + Provide an <function>instance_init</function> function to initialize your object before its construction + properties are set. This is the preferred way to initialize a GObject instance. + This function is equivalent to C++ constructors. + </entry> + </row> + <row> + <!--entry>Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> + <entry>target type's class <function>constructed</function> method: <function>GObjectClass->constructed</function></entry> + <entry>On object's instance</entry> + <entry> + If you need to perform object initialization steps after all construct properties have been set. + This is the final step in the object initialization process, and is only called if the <function>constructor</function> + method returned a new object instance (rather than, for example, an existing singleton). + </entry> + </row> + </tbody> + </tgroup> + </table> + </para> + + <para> + Readers should feel concerned about one little twist in the order in + which functions are invoked: while, technically, the class' constructor + method is called <emphasis>before</emphasis> the GType's <function>instance_init</function> + function (since <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> which calls <function>instance_init</function> is called by + <function>g_object_constructor</function> which is the top-level class + constructor method and to which users are expected to chain to), the + user's code which runs in a user-provided constructor will always + run <emphasis>after</emphasis> GType's <function>instance_init</function> function since the + user-provided constructor <emphasis>must</emphasis> (you've been warned) + chain up <emphasis>before</emphasis> doing anything useful. + </para> + </sect1> + + <sect1 id="gobject-memory"> + <title>Object memory management</title> + + <para> + The memory-management API for GObjects is a bit complicated but the idea behind it + is pretty simple: the goal is to provide a flexible model based on reference counting + which can be integrated in applications which use or require different memory management + models (such as garbage collection). The methods which are used to + manipulate this reference count are described below. + </para> + + <sect2 id="gobject-memory-refcount"> + <title>Reference count</title> + + <para> + The functions <function><link linkend="g-object-ref">g_object_ref</link></function>/<function><link linkend="g-object-unref">g_object_unref</link></function> respectively + increase and decrease the reference count. These functions are + thread-safe. + <function><link linkend="g-clear-object">g_clear_object</link></function> + is a convenience wrapper around <function>g_object_unref</function> + which also clears the pointer passed to it. + </para> + <para> + The reference count is initialized to one by + <function><link linkend="g-object-new">g_object_new</link></function> which means that the caller + is currently the sole owner of the newly-created reference. + When the reference count reaches zero, that is, + when <function><link linkend="g-object-unref">g_object_unref</link></function> is called by the last client holding + a reference to the object, the <emphasis>dispose</emphasis> and the + <emphasis>finalize</emphasis> class methods are invoked. + </para> + <para> + Finally, after <emphasis>finalize</emphasis> is invoked, + <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> is called to free the object instance. + Depending on the memory allocation policy decided when the type was registered (through + one of the <function>g_type_register_*</function> functions), the object's instance + memory will be freed or returned to the object pool for this type. + Once the object has been freed, if it was the last instance of the type, the type's class + will be destroyed as described in <xref linkend="gtype-instantiable-classed"/> and + <xref linkend="gtype-non-instantiable-classed"/>. + </para> + + <para> + The table below summarizes the destruction process of a GObject: + <table id="gobject-destruction-table"> + <title><function><link linkend="g-object-unref">g_object_unref</link></function></title> + <tgroup cols="3"> + <colspec colwidth="*" colnum="1" align="left"/> + <colspec colwidth="*" colnum="2" align="left"/> + <colspec colwidth="8*" colnum="3" align="left"/> + + <thead> + <row> + <entry>Invocation time</entry> + <entry>Function invoked</entry> + <entry>Function's parameters</entry> + <entry>Remark</entry> + </row> + </thead> + <tbody> + <row> + <entry morerows="1">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for an instance + of target type + </entry> + <entry>target type's dispose class function</entry> + <entry>GObject instance</entry> + <entry> + When dispose ends, the object should not hold any reference to any other + member object. The object is also expected to be able to answer client + method invocations (with possibly an error code but no memory violation) + until finalize is executed. dispose can be executed more than once. + dispose should chain up to its parent implementation just before returning + to the caller. + </entry> + </row> + <row> + <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for an instance + of target type + </entry--> + <entry>target type's finalize class function</entry> + <entry>GObject instance</entry> + <entry> + Finalize is expected to complete the destruction process initiated by + dispose. It should complete the object's destruction. finalize will be + executed only once. + finalize should chain up to its parent implementation just before returning + to the caller. + The reason why the destruction process is split is two different phases is + explained in <xref linkend="gobject-memory-cycles"/>. + </entry> + </row> + <row> + <entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last + instance of target type + </entry> + <entry>interface's <function>interface_finalize</function> function</entry> + <entry>On interface's vtable</entry> + <entry>Never used in practice. Unlikely you will need it.</entry> + </row> + <row> + <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function>for the last + instance of target type + </entry--> + <entry>interface's <function>base_finalize</function> function</entry> + <entry>On interface's vtable</entry> + <entry>Never used in practice. Unlikely you will need it.</entry> + </row> + <row> + <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last + instance of target type + </entry--> + <entry>target type's <function>class_finalize</function> function</entry> + <entry>On target type's class structure</entry> + <entry>Never used in practice. Unlikely you will need it.</entry> + </row> + <row> + <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last + instance of target type + </entry--> + <entry>type's <function>base_finalize</function> function</entry> + <entry>On the inheritance tree of classes from fundamental type to target type. + <function>base_init</function> is invoked once for each class structure.</entry> + <entry>Never used in practice. Unlikely you will need it.</entry> + </row> + </tbody> + </tgroup> + </table> + </para> + + </sect2> + + <sect2 id="gobject-memory-weakref"> + <title>Weak References</title> + + <para> + Weak references are used to monitor object finalization: + <function><link linkend="g-object-weak-ref">g_object_weak_ref</link></function> adds a monitoring callback which does + not hold a reference to the object but which is invoked when the object runs + its dispose method. As such, each weak ref can be invoked more than once upon + object finalization (since dispose can run more than once during object + finalization). + </para> + + <para> + <function><link linkend="g-object-weak-unref">g_object_weak_unref</link></function> can be used to remove a monitoring + callback from the object. + </para> + + <para> + Weak references are also used to implement <function><link linkend="g-object-add-weak-pointer">g_object_add_weak_pointer</link></function> + and <function><link linkend="g-object-remove-weak-pointer">g_object_remove_weak_pointer</link></function>. These functions add a weak reference + to the object they are applied to which makes sure to nullify the pointer given by the user + when object is finalized. + </para> + + <para> + Similarly, <link linkend="GWeakRef"><type>GWeakRef</type></link> can be + used to implement weak references if thread safety is required. + </para> + </sect2> + + <sect2 id="gobject-memory-cycles"> + <title>Reference counts and cycles</title> + + <para> + GObject's memory management model was designed to be easily integrated in existing code + using garbage collection. This is why the destruction process is split in two phases: + the first phase, executed in the dispose handler is supposed to release all references + to other member objects. The second phase, executed by the finalize handler is supposed + to complete the object's destruction process. Object methods should be able to run + without program error in-between the two phases. + </para> + + <para> + This two-step destruction process is very useful to break reference counting cycles. + While the detection of the cycles is up to the external code, once the cycles have been + detected, the external code can invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> which + will indeed break any existing cycles since it will run the dispose handler associated + to the object and thus release all references to other objects. + </para> + + <para> + This explains one of the rules about the dispose handler stated earlier: + the dispose handler can be invoked multiple times. Let's say we + have a reference count cycle: object A references B which itself references object A. + Let's say we have detected the cycle and we want to destroy the two objects. One way to + do this would be to invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> on one of the + objects. + </para> + + <para> + If object A releases all its references to all objects, this means it releases its + reference to object B. If object B was not owned by anyone else, this is its last + reference count which means this last unref runs B's dispose handler which, in turn, + releases B's reference on object A. If this is A's last reference count, this last + unref runs A's dispose handler which is running for the second time before + A's finalize handler is invoked ! + </para> + + <para> + The above example, which might seem a bit contrived, can really happen if + GObjects are being handled by language bindings — hence the rules for + object destruction should be closely followed. + </para> + </sect2> + </sect1> + + <sect1 id="gobject-properties"> + <title>Object properties</title> + + <para> + One of GObject's nice features is its generic get/set mechanism for object + properties. When an object + is instantiated, the object's <function>class_init</function> handler should be used to register + the object's properties with <function><link linkend="g-object-class-install-properties">g_object_class_install_properties</link></function>. + </para> + + <para> + The best way to understand how object properties work is by looking at a real example + of how it is used: +<informalexample><programlisting> +/************************************************/ +/* Implementation */ +/************************************************/ + +typedef enum +{ + PROP_FILENAME = 1, + PROP_ZOOM_LEVEL, + N_PROPERTIES +} ViewerFileProperty; + +static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; + +static void +viewer_file_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ViewerFile *self = VIEWER_FILE (object); + + switch ((ViewerFileProperty) property_id) + { + case PROP_FILENAME: + g_free (self->filename); + self->filename = g_value_dup_string (value); + g_print ("filename: %s\n", self->filename); + break; + + case PROP_ZOOM_LEVEL: + self->zoom_level = g_value_get_uint (value); + g_print ("zoom level: %u\n", self->zoom_level); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +viewer_file_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ViewerFile *self = VIEWER_FILE (object); + + switch ((ViewerFileProperty) property_id) + { + case PROP_FILENAME: + g_value_set_string (value, self->filename); + break; + + case PROP_ZOOM_LEVEL: + g_value_set_uint (value, self->zoom_level); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = viewer_file_set_property; + object_class->get_property = viewer_file_get_property; + + obj_properties[PROP_FILENAME] = + g_param_spec_string ("filename", + "Filename", + "Name of the file to load and display from.", + NULL /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + + obj_properties[PROP_ZOOM_LEVEL] = + g_param_spec_uint ("zoom-level", + "Zoom level", + "Zoom level to view the file at.", + 0 /* minimum value */, + 10 /* maximum value */, + 2 /* default value */, + G_PARAM_READWRITE); + + g_object_class_install_properties (object_class, + N_PROPERTIES, + obj_properties); +} + +/************************************************/ +/* Use */ +/************************************************/ + +ViewerFile *file; +GValue val = G_VALUE_INIT; + +file = g_object_new (VIEWER_TYPE_FILE, NULL); + +g_value_init (&val, G_TYPE_UINT); +g_value_set_char (&val, 11); + +g_object_set_property (G_OBJECT (file), "zoom-level", &val); + +g_value_unset (&val); +</programlisting></informalexample> + The client code above looks simple but a lot of things happen under the hood: + </para> + + <para> + <function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property + with this name was registered in <emphasis>file</emphasis>'s <function>class_init</function> handler. If so it walks the class hierarchy, + from bottom-most most-derived type, to top-most fundamental type to find the class + which registered that property. It then tries to convert the user-provided + <link linkend="GValue"><type>GValue</type></link> + into a <type>GValue</type> whose type is that of the associated property. + </para> + + <para> + If the user provides a <type>signed char</type> <type>GValue</type>, as is shown + here, and if the object's property was registered as an <type>unsigned int</type>, + <function><link linkend="g-value-transform">g_value_transform</link></function> will try to transform the input signed char into + an unsigned int. Of course, the success of the transformation depends on the availability + of the required transform function. In practice, there will almost always be a transformation + <footnote> + <para>Its behaviour might not be what you expect but it is up to you to actually avoid + relying on these transformations. + </para> + </footnote> + which matches and conversion will be carried out if needed. + </para> + + <para> + After transformation, the <link linkend="GValue"><type>GValue</type></link> is validated by + <function><link linkend="g-param-value-validate">g_param_value_validate</link></function> which makes sure the user's + data stored in the <link linkend="GValue"><type>GValue</type></link> matches the characteristics specified by + the property's <link linkend="GParamSpec"><type>GParamSpec</type></link>. + Here, the <link linkend="GParamSpec"><type>GParamSpec</type></link> we + provided in <function>class_init</function> has a validation function which makes sure that the GValue + contains a value which respects the minimum and maximum bounds of the + <link linkend="GParamSpec"><type>GParamSpec</type></link>. In the example above, the client's GValue does not + respect these constraints (it is set to 11, while the maximum is 10). As such, the + <function><link linkend="g-object-set-property">g_object_set_property</link></function> function will return with an error. + </para> + + <para> + If the user's GValue had been set to a valid value, <function><link linkend="g-object-set-property">g_object_set_property</link></function> + would have proceeded with calling the object's + <function>set_property</function> class method. Here, since our + implementation of <type>ViewerFile</type> did override this method, execution would jump to + <function>viewer_file_set_property</function> after having retrieved from the + <link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis> + <footnote> + <para> + It should be noted that the param_id used here need only to uniquely identify each + <link linkend="GParamSpec"><type>GParamSpec</type></link> within the <type>ViewerFileClass</type> such that the switch + used in the set and get methods actually works. Of course, this locally-unique + integer is purely an optimization: it would have been possible to use a set of + <emphasis>if (strcmp (a, b) == 0) {} else if (strcmp (a, b) == 0) {}</emphasis> statements. + </para> + </footnote> + which had been stored by + <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>. + </para> + + <para> + Once the property has been set by the object's + <function>set_property</function> class method, execution + returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which makes sure that + the "notify" signal is emitted on the object's instance with the changed property as + parameter unless notifications were frozen by <function><link linkend="g-object-freeze-notify">g_object_freeze_notify</link></function>. + </para> + + <para> + <function><link linkend="g-object-thaw-notify">g_object_thaw_notify</link></function> can be used to re-enable notification of + property modifications through the + <link linkend="GObject-notify"><type>“notify”</type></link> signal. It is important to remember that + even if properties are changed while property change notification is frozen, the "notify" + signal will be emitted once for each of these changed properties as soon as the property + change notification is thawed: no property change is lost for the "notify" + signal, although multiple notifications for a single property are + compressed. Signals can only be delayed by the notification freezing + mechanism. + </para> + + <para> + It sounds like a tedious task to set up GValues every time when one wants to modify a property. + In practice one will rarely do this. The functions <function><link linkend="g-object-set-property">g_object_set_property</link></function> + and <function><link linkend="g-object-get-property">g_object_get_property</link></function> + are meant to be used by language bindings. For application there is an easier way and + that is described next. + </para> + + <sect2 id="gobject-multi-properties"> + <title>Accessing multiple properties at once</title> + + <para> + It is interesting to note that the <function><link linkend="g-object-set">g_object_set</link></function> and + <function><link linkend="g-object-set-valist">g_object_set_valist</link></function> (variadic version) functions can be used to set + multiple properties at once. The client code shown above can then be re-written as: +<informalexample><programlisting> +ViewerFile *file; +file = /* */; +g_object_set (G_OBJECT (file), + "zoom-level", 6, + "filename", "~/some-file.txt", + NULL); +</programlisting></informalexample> + This saves us from managing the GValues that we were needing to handle when using + <function><link linkend="g-object-set-property">g_object_set_property</link></function>. + The code above will trigger one notify signal emission for each property modified. + </para> + + <para> + Equivalent <function>_get</function> versions are also available: + <function><link linkend="g-object-get">g_object_get</link></function> + and <function><link linkend="g-object-get-valist">g_object_get_valist</link></function> (variadic version) can be used to get numerous + properties at once. + </para> + + <para> + These high level functions have one drawback — they don't provide a return value. + One should pay attention to the argument types and ranges when using them. + A known source of errors is to pass a different type from what the + property expects; for instance, passing an integer when the property + expects a floating point value and thus shifting all subsequent parameters + by some number of bytes. Also forgetting the terminating + <literal>NULL</literal> will lead to undefined behaviour. + </para> + + <para> + This explains how <function><link linkend="g-object-new">g_object_new</link></function>, + <function><link linkend="g-object-newv">g_object_newv</link></function> and <function><link linkend="g-object-new-valist">g_object_new_valist</link></function> + work: they parse the user-provided variable number of parameters and invoke + <function><link linkend="g-object-set">g_object_set</link></function> on the parameters only after the object has been successfully constructed. + The "notify" signal will be emitted for each property set. + </para> + + </sect2> + +<!-- @todo tell here about how to pass use handle properties in derived classes --> + + </sect1> + +</chapter>
diff --git a/docs/reference/gobject/tut_gsignal.xml b/docs/reference/gobject/tut_gsignal.xml new file mode 100644 index 0000000..4ed4211 --- /dev/null +++ b/docs/reference/gobject/tut_gsignal.xml
@@ -0,0 +1,495 @@ +<?xml version='1.0' encoding="UTF-8"?> +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<chapter id="chapter-signal"> + <title>The GObject messaging system</title> + + <sect1 id="closure"> + <title>Closures</title> + + <para> + Closures are central to the concept of asynchronous signal delivery + which is widely used throughout GTK+ and GNOME applications. A closure is an + abstraction, a generic representation of a callback. It is a small structure + which contains three objects: + <itemizedlist> + <listitem><para>a function pointer (the callback itself) whose prototype looks like: +<informalexample><programlisting> +return_type function_callback (… , gpointer user_data); +</programlisting></informalexample> + </para></listitem> + <listitem><para> + the <parameter>user_data</parameter> pointer which is passed to the callback upon invocation of the closure + </para></listitem> + <listitem><para> + a function pointer which represents the destructor of the closure: whenever the + closure's refcount reaches zero, this function will be called before the closure + structure is freed. + </para></listitem> + </itemizedlist> + </para> + + <para> + The <link linkend="GClosure"><type>GClosure</type></link> structure represents the common functionality of all + closure implementations: there exists a different closure implementation for + each separate runtime which wants to use the GObject type system. + <footnote><para> + In practice, closures sit at the boundary of language runtimes: if you are + writing Python code and one of your Python callbacks receives a signal from + a GTK+ widget, the C code in GTK+ needs to execute your Python + code. The closure invoked by the GTK+ object invokes the Python callback: + it behaves as a normal C object for GTK+ and as a normal Python object for + Python code. + </para></footnote> + The GObject library provides a simple <link linkend="GCClosure"><type>GCClosure</type></link> type which + is a specific implementation of closures to be used with C/C++ callbacks. + </para> + <para> + A <link linkend="GClosure"><type>GClosure</type></link> provides simple services: + <itemizedlist> + <listitem><para> + Invocation (<function><link linkend="g-closure-invoke">g_closure_invoke</link></function>): this is what closures + were created for: they hide the details of callback invocation from the + callback invoker.</para> + </listitem> + <listitem><para> + Notification: the closure notifies listeners of certain events such as + closure invocation, closure invalidation and closure finalization. Listeners + can be registered with <function><link linkend="g-closure-add-finalize-notifier">g_closure_add_finalize_notifier</link></function> + (finalization notification), <function><link linkend="g-closure-add-invalidate-notifier">g_closure_add_invalidate_notifier</link></function> + (invalidation notification) and + <function><link linkend="g-closure-add-marshal-guards">g_closure_add_marshal_guards</link></function> (invocation notification). + There exist symmetric deregistration functions for finalization and invalidation + events (<function><link linkend="g-closure-remove-finalize-notifier">g_closure_remove_finalize_notifier</link></function> and + <function><link linkend="g-closure-remove-invalidate-notifier">g_closure_remove_invalidate_notifier</link></function>) but not for the invocation + process. + <footnote><para> + Closures are reference counted and notify listeners of their destruction in a two-stage + process: the invalidation notifiers are invoked before the finalization notifiers. + </para></footnote></para> + </listitem> + </itemizedlist> + </para> + + <sect2> + <title>C Closures</title> + + <para> + If you are using C or C++ + to connect a callback to a given event, you will either use simple <link linkend="GCClosure"><type>GCClosure</type></link>s + which have a pretty minimal API or the even simpler <function><link linkend="g-signal-connect">g_signal_connect</link></function> + functions (which will be presented a bit later). + </para> + + <para> + <function><link linkend="g-cclosure-new">g_cclosure_new</link></function> will create a new closure which can invoke the + user-provided callback_func with the user-provided + <parameter>user_data</parameter> as its last parameter. When the closure + is finalized (second stage of the destruction process), it will invoke + the <parameter>destroy_data</parameter> function if the user has + supplied one. + </para> + + <para> + <function><link linkend="g-cclosure-new-swap">g_cclosure_new_swap</link></function> will create a new closure which can invoke the + user-provided <parameter>callback_func</parameter> with the + user-provided <parameter>user_data</parameter> as its first parameter + (instead of being the + last parameter as with <function><link linkend="g-cclosure-new">g_cclosure_new</link></function>). When the closure + is finalized (second stage of the destruction process), it will invoke + the <parameter>destroy_data</parameter> function if the user has + supplied one. + </para> + </sect2> + + <sect2> + <title>Non-C closures (for the fearless)</title> + + <para> + As was explained above, closures hide the details of callback invocation. In C, + callback invocation is just like function invocation: it is a matter of creating + the correct stack frame for the called function and executing a <emphasis>call</emphasis> + assembly instruction. + </para> + + <para> + C closure marshallers transform the array of GValues which represent + the parameters to the target function into a C-style function parameter list, invoke + the user-supplied C function with this new parameter list, get the return value of the + function, transform it into a GValue and return this GValue to the marshaller caller. + </para> + + <para> + A generic C closure marshaller is available as + <link linkend="g-cclosure-marshal-generic"><function>g_cclosure_marshal_generic</function></link> + which implements marshalling for all function types using libffi. Custom + marshallers for different types are not needed apart from performance + critical code where the libffi-based marshaller may be too slow. + </para> + + <para> + An example of a custom marshaller is given below, illustrating how + <type>GValue</type>s can be converted to a C function call. The + marshaller is for a C function which takes an integer as its first + parameter and returns void. +<informalexample><programlisting> +g_cclosure_marshal_VOID__INT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__INT) (gpointer data1, + gint arg_1, + gpointer data2); + register GMarshalFunc_VOID__INT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 2); + + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + + callback = (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_int (param_values + 1), + data2); +} +</programlisting></informalexample> + </para> + + <para> + There exist other kinds of marshallers, for example there is a generic + Python marshaller which is used by all Python closures (a Python closure + is used to invoke a callback written in Python). This Python marshaller + transforms the input GValue list representing the function parameters + into a Python tuple which is the equivalent structure in Python. + </para> + + </sect2> + </sect1> + + <sect1 id="signal"> + <title>Signals</title> + + <para> + GObject's signals have nothing to do with standard UNIX signals: they connect + arbitrary application-specific events with any number of listeners. + For example, in GTK+, every user event (keystroke or mouse move) is received + from the windowing system and generates a GTK+ event in the form of a signal emission + on the widget object instance. + </para> + + <para> + Each signal is registered in the type system together with the type on which + it can be emitted: users of the type are said to <emphasis>connect</emphasis> + to the signal on a given type instance when they register a closure to be + invoked upon the signal emission. Users can also emit the signal by themselves + or stop the emission of the signal from within one of the closures connected + to the signal. + </para> + + <para> + When a signal is emitted on a given type instance, all the closures + connected to this signal on this type instance will be invoked. All the closures + connected to such a signal represent callbacks whose signature looks like: +<informalexample><programlisting> +return_type function_callback (gpointer instance, …, gpointer user_data); +</programlisting></informalexample> + </para> + + <sect2 id="signal-registration"> + <title>Signal registration</title> + + <para> + To register a new signal on an existing type, we can use any of <function><link linkend="g-signal-newv">g_signal_newv</link></function>, + <function><link linkend="g-signal-new-valist">g_signal_new_valist</link></function> or <function><link linkend="g-signal-new">g_signal_new</link></function> functions: +<informalexample><programlisting> +guint g_signal_newv (const gchar *signal_name, + GType itype, + GSignalFlags signal_flags, + GClosure *class_closure, + GSignalAccumulator accumulator, + gpointer accu_data, + GSignalCMarshaller c_marshaller, + GType return_type, + guint n_params, + GType *param_types); +</programlisting></informalexample> + The number of parameters to these functions is a bit intimidating but they are relatively + simple: + <itemizedlist> + <listitem><para> + <parameter>signal_name</parameter>: is a string which can be used to uniquely identify a given signal. + </para></listitem> + <listitem><para> + <parameter>itype</parameter>: is the instance type on which this signal can be emitted. + </para></listitem> + <listitem><para> + <parameter>signal_flags</parameter>: partly defines the order in which closures which were connected to the + signal are invoked. + </para></listitem> + <listitem><para> + <parameter>class_closure</parameter>: this is the default closure for the signal: if it is not NULL upon + the signal emission, it will be invoked upon this emission of the signal. The + moment where this closure is invoked compared to other closures connected to that + signal depends partly on the signal_flags. + </para></listitem> + <listitem><para> + <parameter>accumulator</parameter>: this is a function pointer which is invoked after each closure + has been invoked. If it returns FALSE, signal emission is stopped. If it returns + TRUE, signal emission proceeds normally. It is also used to compute the return + value of the signal based on the return value of all the invoked closures. + For example, an accumulator could ignore + <literal>NULL</literal> returns from closures; or it + could build a list of the values returned by the + closures. + </para></listitem> + <listitem><para> + <parameter>accu_data</parameter>: this pointer will be passed down to each invocation of the + accumulator during emission. + </para></listitem> + <listitem><para> + <parameter>c_marshaller</parameter>: this is the default C marshaller for any closure which is connected to + this signal. + </para></listitem> + <listitem><para> + <parameter>return_type</parameter>: this is the type of the return value of the signal. + </para></listitem> + <listitem><para> + <parameter>n_params</parameter>: this is the number of parameters this signal takes. + </para></listitem> + <listitem><para> + <parameter>param_types</parameter>: this is an array of GTypes which indicate the type of each parameter + of the signal. The length of this array is indicated by n_params. + </para></listitem> + </itemizedlist> + </para> + + <para> + As you can see from the above definition, a signal is basically a description + of the closures which can be connected to this signal and a description of the + order in which the closures connected to this signal will be invoked. + </para> + + </sect2> + + <sect2 id="signal-connection"> + <title>Signal connection</title> + + <para> + If you want to connect to a signal with a closure, you have three possibilities: + <itemizedlist> + <listitem><para> + You can register a class closure at signal registration: this is a + system-wide operation. i.e.: the class closure will be invoked during each emission + of a given signal on <emphasis>any</emphasis> of the instances of the type which supports that signal. + </para></listitem> + <listitem><para> + You can use <function><link linkend="g-signal-override-class-closure">g_signal_override_class_closure</link></function> which + overrides the class closure of a given type. It is possible to call this function + only on a derived type of the type on which the signal was registered. + This function is of use only to language bindings. + </para></listitem> + <listitem><para> + You can register a closure with the <function><link linkend="g-signal-connect">g_signal_connect</link></function> + family of functions. This is an instance-specific operation: the closure + will be invoked only during emission of a given signal on a given instance. + </para></listitem> + </itemizedlist> + It is also possible to connect a different kind of callback on a given signal: + emission hooks are invoked whenever a given signal is emitted whatever the instance on + which it is emitted. Emission hooks are used for example to get all mouse_clicked + emissions in an application to be able to emit the small mouse click sound. + Emission hooks are connected with <function><link linkend="g-signal-add-emission-hook">g_signal_add_emission_hook</link></function> + and removed with <function><link linkend="g-signal-remove-emission-hook">g_signal_remove_emission_hook</link></function>. + </para> + + </sect2> + + <sect2 id="signal-emission"> + <title>Signal emission</title> + + <para> + Signal emission is done through the use of the <function><link linkend="g-signal-emit">g_signal_emit</link></function> family + of functions. +<informalexample><programlisting> +void g_signal_emitv (const GValue *instance_and_params, + guint signal_id, + GQuark detail, + GValue *return_value); +</programlisting></informalexample> + <itemizedlist> + <listitem><para> + The <parameter>instance_and_params</parameter> array of GValues contains the list of input + parameters to the signal. The first element of the array is the + instance pointer on which to invoke the signal. The following elements of + the array contain the list of parameters to the signal. + </para></listitem> + <listitem><para> + <parameter>signal_id</parameter> identifies the signal to invoke. + </para></listitem> + <listitem><para> + <parameter>detail</parameter> identifies the specific detail of the signal to invoke. A detail is a kind of + magic token/argument which is passed around during signal emission and which is used + by closures connected to the signal to filter out unwanted signal emissions. In most + cases, you can safely set this value to zero. See <xref linkend="signal-detail"/> for + more details about this parameter. + </para></listitem> + <listitem><para> + <parameter>return_value</parameter> holds the return value of the last closure invoked during emission if + no accumulator was specified. If an accumulator was specified during signal creation, + this accumulator is used to calculate the return value as a function of the return + values of all the closures invoked during emission. + If no closure is invoked during + emission, the <parameter>return_value</parameter> is nonetheless initialized to zero/null. + </para></listitem> + </itemizedlist> + </para> + + <para> + Signal emission can be decomposed in 5 steps: + <orderedlist> + <listitem><para> + <literal>RUN_FIRST</literal>: if the + <link linkend="G-SIGNAL-RUN-FIRST:CAPS"><literal>G_SIGNAL_RUN_FIRST</literal></link> flag was used + during signal registration and if there exists a class closure for this signal, + the class closure is invoked. + </para></listitem> + <listitem><para> + <literal>EMISSION_HOOK</literal>: if any emission hook was added to + the signal, they are invoked from first to last added. Accumulate return values. + </para></listitem> + <listitem><para> + <literal>HANDLER_RUN_FIRST</literal>: if any closure were connected + with the <function><link linkend="g-signal-connect">g_signal_connect</link></function> family of + functions, and if they are not blocked (with the <function><link linkend="g-signal-handler-block">g_signal_handler_block</link></function> + family of functions) they are run here, from first to last connected. + </para></listitem> + <listitem><para> + <literal>RUN_LAST</literal>: if the <literal>G_SIGNAL_RUN_LAST</literal> + flag was set during registration and if a class closure + was set, it is invoked here. + </para></listitem> + <listitem><para> + <literal>HANDLER_RUN_LAST</literal>: if any closure were connected + with the <function>g_signal_connect_after</function> family of + functions, if they were not invoked during <literal>HANDLER_RUN_FIRST</literal> and if they + are not blocked, they are run here, from first to last connected. + </para></listitem> + <listitem><para> + <literal>RUN_CLEANUP</literal>: if the <literal>G_SIGNAL_RUN_CLEANUP</literal> flag + was set during registration and if a class closure was set, + it is invoked here. Signal emission is completed here. + </para></listitem> + </orderedlist> + </para> + + <para> + If, at any point during emission (except in <literal>RUN_CLEANUP</literal> or + <literal>EMISSION_HOOK</literal> state), one of the closures stops the signal emission with + <function><link linkend="g-signal-stop-emission">g_signal_stop_emission</link></function>, + emission jumps to <literal>RUN_CLEANUP</literal> state. + </para> + + <para> + If, at any point during emission, one of the closures or emission hook + emits the same signal on the same instance, emission is restarted from + the <literal>RUN_FIRST</literal> state. + </para> + + <para> + The accumulator function is invoked in all states, after invocation + of each closure (except in <literal>RUN_EMISSION_HOOK</literal> and + <literal>RUN_CLEANUP</literal>). It accumulates + the closure return value into the signal return value and returns TRUE or + FALSE. If, at any point, it does not return TRUE, emission jumps + to <literal>RUN_CLEANUP</literal> state. + </para> + + <para> + If no accumulator function was provided, the value returned by the last handler + run will be returned by <function><link linkend="g-signal-emit">g_signal_emit</link></function>. + </para> + + </sect2> + + + <sect2 id="signal-detail"> + <title>The <emphasis>detail</emphasis> argument</title> + + <para>All the functions related to signal emission or signal connection have a parameter + named the <emphasis>detail</emphasis>. Sometimes, this parameter is hidden by the API + but it is always there, in one form or another. + </para> + + <para> + Of the three main connection functions, + only one has an explicit detail parameter as a <link linkend="GQuark"><type>GQuark</type></link>: + <link linkend="g-signal-connect-closure-by-id"><function>g_signal_connect_closure_by_id</function></link>. + <footnote> + <para>A GQuark is an integer which uniquely represents a string. It is possible to transform + back and forth between the integer and string representations with the functions + <function><link linkend="g-quark-from-string">g_quark_from_string</link></function> and <function><link linkend="g-quark-to-string">g_quark_to_string</link></function>. + </para> + </footnote> + </para> + <para> + The two other functions, + <link linkend="g-signal-connect-closure"><function>g_signal_connect_closure</function></link> and + <link linkend="g-signal-connect-data"><function>g_signal_connect_data</function></link> + hide the detail parameter in the signal name identification. + Their <parameter>detailed_signal</parameter> parameter is a + string which identifies the name of the signal to connect to. + The format of this string should match + <emphasis>signal_name::detail_name</emphasis>. For example, + connecting to the signal named + <emphasis>notify::cursor_position</emphasis> will actually + connect to the signal named <emphasis>notify</emphasis> with the + <emphasis>cursor_position</emphasis> detail. + Internally, the detail string is transformed to a GQuark if it is present. + </para> + + <para> + Of the four main signal emission functions, one hides it in its + signal name parameter: + <link linkend="g-signal-connect"><function>g_signal_connect</function></link>. + The other three have an explicit detail parameter as a + <link linkend="GQuark"><type>GQuark</type></link> again: + <link linkend="g-signal-emit"><function>g_signal_emit</function></link>, + <link linkend="g-signal-emitv"><function>g_signal_emitv</function></link> and + <link linkend="g-signal-emit-valist"><function>g_signal_emit_valist</function></link>. + </para> + + <para> + If a detail is provided by the user to the emission function, it is used during emission to match + against the closures which also provide a detail. + If a closure's detail does not match the detail provided by the user, it + will not be invoked (even though it is connected to a signal which is + being emitted). + </para> + + <para> + This completely optional filtering mechanism is mainly used as an optimization for signals + which are often emitted for many different reasons: the clients can filter out which events they are + interested in before the closure's marshalling code runs. For example, this is used extensively + by the <link linkend="GObject-notify"><structfield>notify</structfield></link> signal of GObject: whenever a property is modified on a GObject, + instead of just emitting the <emphasis>notify</emphasis> signal, GObject associates as a detail to this + signal emission the name of the property modified. This allows clients who wish to be notified of changes + to only one property to filter most events before receiving them. + </para> + + <para> + As a simple rule, users can and should set the detail parameter to zero: this will disable completely + this optional filtering for that signal. + </para> + + </sect2> + + </sect1> +</chapter> +
diff --git a/docs/reference/gobject/tut_gtype.xml b/docs/reference/gobject/tut_gtype.xml new file mode 100644 index 0000000..a1c6005 --- /dev/null +++ b/docs/reference/gobject/tut_gtype.xml
@@ -0,0 +1,1003 @@ +<?xml version='1.0' encoding="UTF-8"?> +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> + <chapter id="chapter-gtype"> + <title>The GLib Dynamic Type System</title> + + <para> + A type, as manipulated by the GLib type system, is much more generic than what + is usually understood as an Object type. It is best explained by looking at the + structure and the functions used to register new types in the type system. + <informalexample><programlisting> +typedef struct _GTypeInfo GTypeInfo; +struct _GTypeInfo +{ + /* interface types, classed types, instantiated types */ + guint16 class_size; + + GBaseInitFunc base_init; + GBaseFinalizeFunc base_finalize; + + /* classed types, instantiated types */ + GClassInitFunc class_init; + GClassFinalizeFunc class_finalize; + gconstpointer class_data; + + /* instantiated types */ + guint16 instance_size; + guint16 n_preallocs; + GInstanceInitFunc instance_init; + + /* value handling */ + const GTypeValueTable *value_table; +}; +GType g_type_register_static (GType parent_type, + const gchar *type_name, + const GTypeInfo *info, + GTypeFlags flags); +GType g_type_register_fundamental (GType type_id, + const gchar *type_name, + const GTypeInfo *info, + const GTypeFundamentalInfo *finfo, + GTypeFlags flags); + </programlisting></informalexample> + </para> + + <para> + <function><link linkend="g-type-register-static">g_type_register_static</link></function>, + <function><link linkend="g-type-register-dynamic">g_type_register_dynamic</link></function> and + <function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function> + are the C functions, defined in + <filename>gtype.h</filename> and implemented in <filename>gtype.c</filename> + which you should use to register a new <link linkend="GType"><type>GType</type></link> in the program's type system. + It is not likely you will ever need to use + <function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function> + but in case you want to, the last chapter explains how to create + new fundamental types. + </para> + + <para> + Fundamental types are top-level types which do not derive from any other type + while other non-fundamental types derive from other types. + Upon initialization, the type system not only initializes its + internal data structures but it also registers a number of core + types: some of these are fundamental types. Others are types derived from these + fundamental types. + </para> + + <para> + Fundamental and non-fundamental types are defined by: + <itemizedlist> + <listitem><para> + class size: the class_size field in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>. + </para></listitem> + <listitem><para> + class initialization functions (C++ constructor): the <function>base_init</function> and + <function>class_init</function> fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>. + </para></listitem> + <listitem><para> + class destruction functions (C++ destructor): the base_finalize and + class_finalize fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>. + </para></listitem> + <listitem><para> + instance size (C++ parameter to new): the instance_size field in + <link linkend="GTypeInfo"><type>GTypeInfo</type></link>. + </para></listitem> + <listitem><para> + instantiation policy (C++ type of new operator): the n_preallocs + field in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>. + </para></listitem> + <listitem><para> + copy functions (C++ copy operators): the value_table field in + <link linkend="GTypeInfo"><type>GTypeInfo</type></link>. + </para></listitem> + <listitem><para> + type characteristic flags: <link linkend="GTypeFlags"><type>GTypeFlags</type></link>. + </para></listitem> + </itemizedlist> + Fundamental types are also defined by a set of <link linkend="GTypeFundamentalFlags"><type>GTypeFundamentalFlags</type></link> + which are stored in a <link linkend="GTypeFundamentalInfo"><type>GTypeFundamentalInfo</type></link>. + Non-fundamental types are furthermore defined by the type of their parent which is + passed as the parent_type parameter to <function><link linkend="g-type-register-static">g_type_register_static</link></function> + and <function><link linkend="g-type-register-dynamic">g_type_register_dynamic</link></function>. + </para> + + <sect1 id="gtype-copy"> + <title>Copy functions</title> + + <para> + The major common point between <emphasis>all</emphasis> GLib types (fundamental and + non-fundamental, classed and non-classed, instantiable and non-instantiable) is that + they can all be manipulated through a single API to copy/assign them. + </para> + + <para> + The <link linkend="GValue"><type>GValue</type></link> structure is used as an abstract container for all of these + types. Its simplistic API (defined in <filename>gobject/gvalue.h</filename>) can be + used to invoke the value_table functions registered + during type registration: for example <function><link linkend="g-value-copy">g_value_copy</link></function> copies the + content of a <link linkend="GValue"><type>GValue</type></link> to another <link linkend="GValue"><type>GValue</type></link>. This is similar + to a C++ assignment which invokes the C++ copy operator to modify the default + bit-by-bit copy semantics of C++/C structures/classes. + </para> + + <para> + The following code shows how you can copy around a 64 bit integer, as well as a <link linkend="GObject"><type>GObject</type></link> + instance pointer: +<informalexample><programlisting> +static void test_int (void) +{ + GValue a_value = G_VALUE_INIT; + GValue b_value = G_VALUE_INIT; + guint64 a, b; + + a = 0xdeadbeef; + + g_value_init (&a_value, G_TYPE_UINT64); + g_value_set_uint64 (&a_value, a); + + g_value_init (&b_value, G_TYPE_UINT64); + g_value_copy (&a_value, &b_value); + + b = g_value_get_uint64 (&b_value); + + if (a == b) { + g_print ("Yay !! 10 lines of code to copy around a uint64.\n"); + } else { + g_print ("Are you sure this is not a Z80 ?\n"); + } +} + +static void test_object (void) +{ + GObject *obj; + GValue obj_vala = G_VALUE_INIT; + GValue obj_valb = G_VALUE_INIT; + obj = g_object_new (VIEWER_TYPE_FILE, NULL); + + g_value_init (&obj_vala, VIEWER_TYPE_FILE); + g_value_set_object (&obj_vala, obj); + + g_value_init (&obj_valb, G_TYPE_OBJECT); + + /* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference. + * This function thus calls g_object_ref. + * It is interesting to note that the assignment works here because + * VIEWER_TYPE_FILE is a G_TYPE_OBJECT. + */ + g_value_copy (&obj_vala, &obj_valb); + + g_object_unref (G_OBJECT (obj)); + g_object_unref (G_OBJECT (obj)); +} +</programlisting></informalexample> + The important point about the above code is that the exact semantics of the copy calls + is undefined since they depend on the implementation of the copy function. Certain + copy functions might decide to allocate a new chunk of memory and then to copy the + data from the source to the destination. Others might want to simply increment + the reference count of the instance and copy the reference to the new GValue. + </para> + + <para> + The value table used to specify these assignment functions is + documented in + <link linkend="GTypeValueTable"><type>GTypeValueTable</type></link>. + </para> + <para> + Interestingly, it is also very unlikely + you will ever need to specify a value_table during type registration + because these value_tables are inherited from the parent types for + non-fundamental types. + </para> + </sect1> + + <sect1 id="gtype-conventions"> + <title>Conventions</title> + + + <para> + There are a number of conventions users are expected to follow when creating new types + which are to be exported in a header file: + <itemizedlist> + <listitem><para> + Type names (including object names) must be at least three + characters long and start with ‘a–z’, ‘A–Z’ or ‘_’. + </para></listitem> + <listitem><para> + Use the <function>object_method</function> pattern for function names: to invoke + the method named <function>save</function> on an instance of object type <type>file</type>, call + <function>file_save</function>. + </para></listitem> + <listitem><para>Use prefixing to avoid namespace conflicts with other projects. + If your library (or application) is named <emphasis>Viewer</emphasis>, + prefix all your function names with <emphasis>viewer_</emphasis>. + For example: <function>viewer_object_method</function>. + </para></listitem> + <listitem><para>Create a macro named <function>PREFIX_TYPE_OBJECT</function> which always + returns the GType for the associated object type. For an object of type + <emphasis>File</emphasis> in the <emphasis>Viewer</emphasis> namespace, + use: <function>VIEWER_TYPE_FILE</function>. + This macro is implemented using a function named + <function>prefix_object_get_type</function>; for example, <function>viewer_file_get_type</function>. + </para></listitem> + <listitem> + <para> + Use <link linkend="G-DECLARE-FINAL-TYPE:CAPS"><function>G_DECLARE_FINAL_TYPE</function></link> + or <link linkend="G-DECLARE-DERIVABLE-TYPE:CAPS"><function>G_DECLARE_DERIVABLE_TYPE</function></link> + to define various other conventional macros for your object: + </para> + <itemizedlist> + <listitem><para><function>PREFIX_OBJECT (obj)</function>, which + returns a pointer of type <type>PrefixObject</type>. This macro is used to enforce + static type safety by doing explicit casts wherever needed. It also enforces + dynamic type safety by doing runtime checks. It is possible to disable the dynamic + type checks in production builds (see <link linkend="glib-building">building GLib</link>). + For example, we would create + <function>VIEWER_FILE (obj)</function> to keep the previous example. + </para></listitem> + <listitem><para><function>PREFIX_OBJECT_CLASS (klass)</function>, which + is strictly equivalent to the previous casting macro: it does static casting with + dynamic type checking of class structures. It is expected to return a pointer + to a class structure of type <type>PrefixObjectClass</type>. An example is: + <function>VIEWER_FILE_CLASS</function>. + </para></listitem> + <listitem><para><function>PREFIX_IS_OBJECT (obj)</function>, which + returns a <type>gboolean</type> which indicates whether the input + object instance pointer is non-<type>NULL</type> and of type <type>OBJECT</type>. + For example, <function>VIEWER_IS_FILE</function>. + </para></listitem> + <listitem><para><function>PREFIX_IS_OBJECT_CLASS (klass)</function>, which returns a boolean + if the input class pointer is a pointer to a class of type OBJECT. + For example, <function>VIEWER_IS_FILE_CLASS</function>. + </para></listitem> + <listitem><para><function>PREFIX_OBJECT_GET_CLASS (obj)</function>, + which returns the class pointer associated to an instance of a given type. This macro + is used for static and dynamic type safety purposes (just like the previous casting + macros). + For example, <function>VIEWER_FILE_GET_CLASS</function>. + </para></listitem> + </itemizedlist> + </listitem> + </itemizedlist> + The implementation of these macros is pretty straightforward: a number of simple-to-use + macros are provided in <filename>gtype.h</filename>. For the example we used above, we would + write the following trivial code to declare the macros: +<informalexample><programlisting> +#define VIEWER_TYPE_FILE viewer_file_get_type () +G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) +</programlisting></informalexample> + </para> + + <para> + Unless your code has special requirements, you can use the + <function><link linkend="G-DEFINE-TYPE:CAPS">G_DEFINE_TYPE</link></function> + macro to define a class: +<informalexample><programlisting> +G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT) +</programlisting></informalexample> + </para> + + <para> + Otherwise, the <function>viewer_file_get_type</function> function must be + implemented manually: +<informalexample><programlisting> +GType viewer_file_get_type (void) +{ + static GType type = 0; + if (type == 0) { + const GTypeInfo info = { + /* You fill this structure. */ + }; + type = g_type_register_static (G_TYPE_OBJECT, + "ViewerFile", + &info, 0); + } + return type; +} +</programlisting></informalexample> + </para> + + </sect1> + + <sect1 id="gtype-non-instantiable"> + <title>Non-instantiable non-classed fundamental types</title> + + <para> + A lot of types are not instantiable by the type system and do not have + a class. Most of these types are fundamental trivial types such as <emphasis>gchar</emphasis>, + and are already registered by GLib. + </para> + + <para> + In the rare case of needing to register such a type in the type + system, fill a + <link linkend="GTypeInfo"><type>GTypeInfo</type></link> structure with zeros since these types are also most of the time + fundamental: + <informalexample><programlisting> + GTypeInfo info = { + 0, /* class_size */ + NULL, /* base_init */ + NULL, /* base_destroy */ + NULL, /* class_init */ + NULL, /* class_destroy */ + NULL, /* class_data */ + 0, /* instance_size */ + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL, /* value_table */ + }; + static const GTypeValueTable value_table = { + value_init_long0, /* value_init */ + NULL, /* value_free */ + value_copy_long0, /* value_copy */ + NULL, /* value_peek_pointer */ + "i", /* collect_format */ + value_collect_int, /* collect_value */ + "p", /* lcopy_format */ + value_lcopy_char, /* lcopy_value */ + }; + info.value_table = &value_table; + type = g_type_register_fundamental (G_TYPE_CHAR, "gchar", &info, &finfo, 0); + </programlisting></informalexample> + </para> + + + <para> + Having non-instantiable types might seem a bit useless: what good is a type + if you cannot instantiate an instance of that type ? Most of these types + are used in conjunction with <link linkend="GValue"><type>GValue</type></link>s: a GValue is initialized + with an integer or a string and it is passed around by using the registered + type's value_table. <link linkend="GValue"><type>GValue</type></link>s (and by extension these trivial fundamental + types) are most useful when used in conjunction with object properties and signals. + </para> + + </sect1> + + <sect1 id="gtype-instantiable-classed"> + <title>Instantiable classed types: objects</title> + + <para> + This section covers the theory behind objects. See + <xref linkend="howto-gobject"/> for the recommended way to define a + GObject. + </para> + + <para> + Types which are registered with a class and are declared instantiable are + what most closely resembles an <emphasis>object</emphasis>. + Although <link linkend="GObject"><type>GObject</type></link>s (detailed in <xref linkend="chapter-gobject"/>) + are the most well known type of instantiable + classed types, other kinds of similar objects used as the base of an inheritance + hierarchy have been externally developed and they are all built on the fundamental + features described below. + </para> + + <para> + For example, the code below shows how you could register + such a fundamental object type in the type system (using none of the + GObject convenience API): +<informalexample><programlisting> +typedef struct { + GObject parent; + + /* instance members */ + gchar *filename; +} ViewerFile; + +typedef struct { + GObjectClass parent; + + /* class members */ + /* the first is public, pure and virtual */ + void (*open) (ViewerFile *self, + GError **error); + + /* the second is public and virtual */ + void (*close) (ViewerFile *self, + GError **error); +} ViewerFileClass; + +#define VIEWER_TYPE_FILE (viewer_file_get_type ()) + +GType +viewer_file_get_type (void) +{ + static GType type = 0; + if (type == 0) { + const GTypeInfo info = { + sizeof (ViewerFileClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) viewer_file_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (ViewerFile), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL /* instance_init */ + }; + type = g_type_register_static (G_TYPE_OBJECT, + "ViewerFile", + &info, 0); + } + return type; +} +</programlisting></informalexample> + Upon the first call to <function>viewer_file_get_type</function>, the type named + <emphasis>ViewerFile</emphasis> will be registered in the type system as inheriting + from the type <emphasis>G_TYPE_OBJECT</emphasis>. + </para> + + <para> + Every object must define two structures: its class structure and its + instance structure. All class structures must contain as first member + a <link linkend="GTypeClass"><type>GTypeClass</type></link> structure. All instance structures must contain as first + member a <link linkend="GTypeInstance"><type>GTypeInstance</type></link> structure. The declaration of these C types, + coming from <filename>gtype.h</filename> is shown below: +<informalexample><programlisting> +struct _GTypeClass +{ + GType g_type; +}; +struct _GTypeInstance +{ + GTypeClass *g_class; +}; +</programlisting></informalexample> + These constraints allow the type system to make sure that every object instance + (identified by a pointer to the object's instance structure) contains in its + first bytes a pointer to the object's class structure. + </para> + <para> + This relationship is best explained by an example: let's take object B which + inherits from object A: +<informalexample><programlisting> +/* A definitions */ +typedef struct { + GTypeInstance parent; + int field_a; + int field_b; +} A; +typedef struct { + GTypeClass parent_class; + void (*method_a) (void); + void (*method_b) (void); +} AClass; + +/* B definitions. */ +typedef struct { + A parent; + int field_c; + int field_d; +} B; +typedef struct { + AClass parent_class; + void (*method_c) (void); + void (*method_d) (void); +} BClass; +</programlisting></informalexample> + The C standard mandates that the first field of a C structure is stored starting + in the first byte of the buffer used to hold the structure's fields in memory. + This means that the first field of an instance of an object B is A's first field + which in turn is <type>GTypeInstance</type>'s first field which in + turn is <structfield>g_class</structfield>, a pointer + to B's class structure. + </para> + + <para> + Thanks to these simple conditions, it is possible to detect the type of every + object instance by doing: +<informalexample><programlisting> +B *b; +b->parent.parent.g_class->g_type +</programlisting></informalexample> + or, more quickly: +<informalexample><programlisting> +B *b; +((GTypeInstance *) b)->g_class->g_type +</programlisting></informalexample> + </para> + + <sect2 id="gtype-instantiable-classed-init-done"> + <title>Initialization and Destruction</title> + + <para> + instantiation of these types can be done with + <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>, + which will look up the type information + structure associated with the type requested. Then, the instance size and instantiation + policy (if the <structfield>n_preallocs</structfield> field is set + to a non-zero value, the type system allocates + the object's instance structures in chunks rather than mallocing for every instance) + declared by the user are used to get a buffer to hold the object's instance + structure. + </para> + + <para> + If this is the first instance of the object ever created, the type system must create a class structure. + It allocates a buffer to hold the object's class structure and initializes it. The first part of the + class structure (ie: the embedded parent class structure) is initialized by copying the contents from + the class structure of the parent class. The rest of class structure is initialized to zero. If there + is no parent, the entire class structure is initialized to zero. The type system then invokes the + <function>base_class_initialization</function> functions + (<link linkend="GBaseInitFunc"><type>GBaseInitFunc</type></link>) from topmost + fundamental object to bottom-most most derived object. The object's <function>class_init</function> + (<link linkend="GClassInitFunc"><type>GClassInitFunc</type></link>) function is invoked afterwards to complete + initialization of the class structure. + Finally, the object's interfaces are initialized (we will discuss interface initialization + in more detail later). + </para> + + <para> + Once the type system has a pointer to an initialized class structure, it sets the object's + instance class pointer to the object's class structure and invokes the object's + <function>instance_init</function> + (<link linkend="GInstanceInitFunc"><type>GInstanceInitFunc</type></link>) + functions, from top-most fundamental + type to bottom-most most-derived type. + </para> + + <para> + Object instance destruction through <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> is very simple: + the instance structure is returned to the instance pool if there is one and if this was the + last living instance of the object, the class is destroyed. + </para> + + + <para> + Class destruction (the concept of destruction is sometimes partly + referred to as finalization in GType) is the symmetric process of + the initialization: interfaces are destroyed first. + Then, the most derived + class_finalize (<link linkend="GClassFinalizeFunc"><type>GClassFinalizeFunc</type></link>) function is invoked. Finally, the + base_class_finalize (<link linkend="GBaseFinalizeFunc"><type>GBaseFinalizeFunc</type></link>) functions are + invoked from bottom-most most-derived type to top-most fundamental type and + the class structure is freed. + </para> + + <para> + The base initialization/finalization process is + very similar to the C++ constructor/destructor paradigm. The practical details are different + though and it is important not to get confused by superficial similarities. + GTypes have no instance destruction mechanism. It is + the user's responsibility to implement correct destruction semantics on top + of the existing GType code. (This is what GObject does: see + <xref linkend="chapter-gobject"/>.) + Furthermore, C++ code equivalent to the <function>base_init</function> + and <function>class_init</function> callbacks of GType is usually not needed because C++ cannot really create object + types at runtime. + </para> + + <para> + The instantiation/finalization process can be summarized as follows: + <table id="gtype-init-fini-table"> + <title>GType Instantiation/Finalization</title> + <tgroup cols="3"> + <colspec colwidth="*" colnum="1" align="left"/> + <colspec colwidth="*" colnum="2" align="left"/> + <colspec colwidth="8*" colnum="3" align="left"/> + + <thead> + <row> + <entry>Invocation time</entry> + <entry>Function invoked</entry> + <entry>Function's parameters</entry> + </row> + </thead> + <tbody> + <row> + <entry morerows="2">First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry> + <entry>type's <function>base_init</function> function</entry> + <entry>On the inheritance tree of classes from fundamental type to target type. + <function>base_init</function> is invoked once for each class structure.</entry> + </row> + <row> + <!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry--> + <entry>target type's <function>class_init</function> function</entry> + <entry>On target type's class structure</entry> + </row> + <row> + <!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry--> + <entry>interface initialization, see + <xref linkend="gtype-non-instantiable-classed-init"/></entry> + <entry></entry> + </row> + <row> + <entry>Each call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry> + <entry>target type's <function>instance_init</function> function</entry> + <entry>On object's instance</entry> + </row> + <row> + <entry morerows="2">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry> + <entry>interface destruction, see + <xref linkend="gtype-non-instantiable-classed-dest"/></entry> + <entry></entry> + </row> + <row> + <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry--> + <entry>target type's <function>class_finalize</function> function</entry> + <entry>On target type's class structure</entry> + </row> + <row> + <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry--> + <entry>type's <function>base_finalize</function> function</entry> + <entry>On the inheritance tree of classes from fundamental type to target type. + <function>base_finalize</function> is invoked once for each class structure.</entry> + </row> + </tbody> + </tgroup> + </table> + </para> + + </sect2> + + </sect1> + + <sect1 id="gtype-non-instantiable-classed"> + <title>Non-instantiable classed types: interfaces</title> + + <para> + This section covers the theory behind interfaces. See + <xref linkend="howto-interface"/> for the recommended way to define an + interface. + </para> + + <para> + GType's interfaces are very similar to Java's interfaces. They allow + to describe a common API that several classes will adhere to. + Imagine the play, pause and stop buttons on hi-fi equipment — those can + be seen as a playback interface. Once you know what they do, you can + control your CD player, MP3 player or anything that uses these symbols. + To declare an interface you have to register a non-instantiable + classed type which derives from + <link linkend="GTypeInterface"><type>GTypeInterface</type></link>. The following piece of code declares such an interface. +<informalexample><programlisting> +#define VIEWER_TYPE_EDITABLE viewer_editable_get_type () +G_DECLARE_INTERFACE (ViewerEditable, viewer_editable, VIEWER, EDITABLE, GObject) + +struct _ViewerEditableInterface { + GTypeInterface parent; + + void (*save) (ViewerEditable *self, + GError **error); +}; + +void viewer_editable_save (ViewerEditable *self, + GError **error); +</programlisting></informalexample> + The interface function, <function>viewer_editable_save</function> is implemented + in a pretty simple way: +<informalexample><programlisting> +void +viewer_editable_save (ViewerEditable *self, + GError **error) +{ + ViewerEditableinterface *iface; + + g_return_if_fail (VIEWER_IS_EDITABLE (self)); + g_return_if_fail (error == NULL || *error == NULL); + + iface = VIEWER_EDITABLE_GET_IFACE (self); + g_return_if_fail (iface->save != NULL); + iface->save (self); +} +</programlisting></informalexample> + <function>viewer_editable_get_type</function> registers a type named <emphasis>ViewerEditable</emphasis> + which inherits from <type>G_TYPE_INTERFACE</type>. All interfaces must + be children of <type>G_TYPE_INTERFACE</type> in the inheritance tree. + </para> + + <para> + An interface is defined by only one structure which must contain as first member + a <link linkend="GTypeInterface"><type>GTypeInterface</type></link> structure. The interface structure is expected to + contain the function pointers of the interface methods. It is good style to + define helper functions for each of the interface methods which simply call + the interface's method directly: <function>viewer_editable_save</function> + is one of these. + </para> + + <para> + If you have no special requirements you can use the + <link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link> macro + to implement an interface: +<informalexample><programlisting> +static void +viewer_file_save (ViewerEditable *self) +{ + g_print ("File implementation of editable interface save method.\n"); +} + +static void +viewer_file_editable_interface_init (ViewerEditableInterface *iface) +{ + iface->save = viewer_file_save; +} + +G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, VIEWER_TYPE_FILE, + G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE, + viewer_file_editable_interface_init)) +</programlisting></informalexample> + </para> + + <para> + If your code does have special requirements, you must write a custom + <function>get_type</function> function to register your GType which + inherits from some <link linkend="GObject"><type>GObject</type></link> + and which implements the interface <type>ViewerEditable</type>. For + example, this code registers a new <type>ViewerFile</type> class which + implements <type>ViewerEditable</type>: +<informalexample><programlisting> +static void +viewer_file_save (ViewerEditable *editable) +{ + g_print ("File implementation of editable interface save method.\n"); +} + +static void +viewer_file_editable_interface_init (gpointer g_iface, + gpointer iface_data) +{ + ViewerEditableInterface *iface = g_iface; + + iface->save = viewer_file_save; +} + +GType +viewer_file_get_type (void) +{ + static GType type = 0; + if (type == 0) { + const GTypeInfo info = { + sizeof (ViewerFileClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (ViewerFile), + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + const GInterfaceInfo editable_info = { + (GInterfaceInitFunc) viewer_file_editable_interface_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + type = g_type_register_static (VIEWER_TYPE_FILE, + "ViewerFile", + &info, 0); + g_type_add_interface_static (type, + VIEWER_TYPE_EDITABLE, + &editable_info); + } + return type; +} +</programlisting></informalexample> + </para> + + <para> + <function><link linkend="g-type-add-interface-static">g_type_add_interface_static</link></function> records in the type system that + a given type implements also <type>FooInterface</type> + (<function>foo_interface_get_type</function> returns the type of + <type>FooInterface</type>). + The <link linkend="GInterfaceInfo"><type>GInterfaceInfo</type></link> structure holds + information about the implementation of the interface: +<informalexample><programlisting> +struct _GInterfaceInfo +{ + GInterfaceInitFunc interface_init; + GInterfaceFinalizeFunc interface_finalize; + gpointer interface_data; +}; +</programlisting></informalexample> + </para> + + <sect2 id="gtype-non-instantiable-classed-init"> + <title>Interface Initialization</title> + + <para> + When an instantiable classed type which implements an interface + (either directly or by inheriting an implementation from a superclass) + is created for the first time, its class structure is initialized + following the process described in <xref linkend="gtype-instantiable-classed"/>. + After that, the interface implementations associated with + the type are initialized. + </para> + + <para> + First a memory buffer is allocated to hold the interface structure. The parent's + interface structure is then copied over to the new interface structure (the parent + interface is already initialized at that point). If there is no parent interface, + the interface structure is initialized with zeros. The + <structfield>g_type</structfield> and the + <structfield>g_instance_type</structfield> fields are then + initialized: <structfield>g_type</structfield> is set to the type of + the most-derived interface and + <structfield>g_instance_type</structfield> is set to the type of the + most derived type which implements this interface. + </para> + + <para> + The interface's <function>base_init</function> function is called, + and then the interface's <function>default_init</function> is invoked. + Finally if the type has registered an implementation of the interface, + the implementation's <function>interface_init</function> + function is invoked. If there are multiple implementations of an + interface the <function>base_init</function> and + <function>interface_init</function> functions will be invoked once + for each implementation initialized. + </para> + + <para> + It is thus recommended to use a <function>default_init</function> function to + initialize an interface. This function is called only once for the interface no + matter how many implementations there are. The + <function>default_init</function> function is declared by + <link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link> + which can be used to define the interface: +<informalexample><programlisting> +G_DEFINE_INTERFACE (ViewerEditable, viewer_editable, G_TYPE_OBJECT) + +static void +viewer_editable_default_init (ViewerEditableInterface *iface) +{ + /* add properties and signals here, will only be called once */ +} +</programlisting></informalexample> + </para> + + <para> + Or you can do that yourself in a GType function for your interface: +<informalexample><programlisting> +GType +viewer_editable_get_type (void) +{ + static volatile gsize type_id = 0; + if (g_once_init_enter (&type_id)) { + const GTypeInfo info = { + sizeof (ViewerEditableInterface), + NULL, /* base_init */ + NULL, /* base_finalize */ + viewer_editable_default_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, /* instance_size */ + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + GType type = g_type_register_static (G_TYPE_INTERFACE, + "ViewerEditable", + &info, 0); + g_once_init_leave (&type_id, type); + } + return type_id; +} + +static void +viewer_editable_default_init (ViewerEditableInterface *iface) +{ + /* add properties and signals here, will only called once */ +} +</programlisting></informalexample> + </para> + + <para> + In summary, interface initialization uses the following functions: + </para> + + <para> + <table id="ginterface-init-table"> + <title>Interface Initialization</title> + <tgroup cols="3"> + <colspec colwidth="*" colnum="1" align="left"/> + <colspec colwidth="*" colnum="2" align="left"/> + <colspec colwidth="8*" colnum="3" align="left"/> + + <thead> + <row> + <entry>Invocation time</entry> + <entry>Function Invoked</entry> + <entry>Function's parameters</entry> + <entry>Remark</entry> + </row> + </thead> + <tbody> + <row> + <entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> + for <emphasis>any</emphasis> type implementing interface + </entry> + <entry>interface's <function>base_init</function> function</entry> + <entry>On interface's vtable</entry> + <entry>Rarely necessary to use this. Called once per instantiated classed type implementing the interface.</entry> + </row> + <row> + <entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> + for <emphasis>each</emphasis> type implementing interface + </entry> + <entry>interface's <function>default_init</function> function</entry> + <entry>On interface's vtable</entry> + <entry>Register interface's signals, properties, etc. here. Will be called once.</entry> + </row> + <row> + <entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> + for <emphasis>any</emphasis> type implementing interface + </entry> + <entry>implementation's <function>interface_init</function> function</entry> + <entry>On interface's vtable</entry> + <entry> + Initialize interface implementation. Called for each class that that + implements the interface. Initialize the interface method pointers + in the interface structure to the implementing class's implementation. + </entry> + </row> + </tbody> + </tgroup> + </table> + </para> + + </sect2> + + <sect2 id="gtype-non-instantiable-classed-dest"> + <title>Interface Destruction</title> + + <para> + When the last instance of an instantiable type which registered + an interface implementation is destroyed, the interface's + implementations associated to the type are destroyed. + </para> + + <para> + To destroy an interface implementation, GType first calls the + implementation's <function>interface_finalize</function> function + and then the interface's most-derived + <function>base_finalize</function> function. + </para> + + <para> + Again, it is important to understand, as in + <xref linkend="gtype-non-instantiable-classed-init"/>, + that both <function>interface_finalize</function> and <function>base_finalize</function> + are invoked exactly once for the destruction of each implementation of an interface. Thus, + if you were to use one of these functions, you would need to use a static integer variable + which would hold the number of instances of implementations of an interface such that + the interface's class is destroyed only once (when the integer variable reaches zero). + </para> + + <para> + The above process can be summarized as follows: + <table id="ginterface-fini-table"> + <title>Interface Finalization</title> + <tgroup cols="3"> + <colspec colwidth="*" colnum="1" align="left"/> + <colspec colwidth="*" colnum="2" align="left"/> + <colspec colwidth="8*" colnum="3" align="left"/> + + <thead> + <row> + <entry>Invocation time</entry> + <entry>Function Invoked</entry> + <entry>Function's parameters</entry> + </row> + </thead> + <tbody> + <row> + <entry morerows="1">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for type + implementing interface + </entry> + <entry>interface's <function>interface_finalize</function> function</entry> + <entry>On interface's vtable</entry> + </row> + <row> + <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function>for type + implementing interface + </entry--> + <entry>interface's <function>base_finalize</function> function</entry> + <entry>On interface's vtable</entry> + </row> + </tbody> + </tgroup> + </table> + </para> + </sect2> + </sect1> + </chapter>
diff --git a/docs/reference/gobject/tut_howto.xml b/docs/reference/gobject/tut_howto.xml new file mode 100644 index 0000000..bfb8d95 --- /dev/null +++ b/docs/reference/gobject/tut_howto.xml
@@ -0,0 +1,1535 @@ +<?xml version='1.0' encoding="UTF-8"?> +<!DOCTYPE part PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<part label="IV"> + <title>Tutorial</title> + <partintro> + <para> + This chapter tries to answer the real-life questions of users and presents + the most common use cases in order from most likely to least + likely. + </para> + </partintro> + +<chapter id="howto-gobject"> + <title>How to define and implement a new GObject</title> + + <para> + This chapter focuses on the implementation of a subtype of GObject, for + example to create a custom class hierarchy, or to subclass a GTK+ widget. + </para> + + <para> + Throughout the chapter, a running example of a file viewer program is used, + which has a <type>ViewerFile</type> class to represent a single file being + viewed, and various derived classes for different types of files with + special functionality, such as audio files. The example application also + supports editing files (for example, to tweak a photo being viewed), using + a <type>ViewerEditable</type> interface. + </para> + + <sect1 id="howto-gobject-header"> + <title>Boilerplate header code</title> + + <para> + The first step before writing the code for your GObject is to write the + type's header which contains the needed type, function and macro + definitions. Each of these elements is nothing but a convention which + is followed by almost all users of GObject, and has been refined over + multiple years of experience developing GObject-based code. If you are + writing a library, it is particularly important for you to adhere closely + to these conventions; users of your library will assume that you have. + Even if not writing a library, it will help other people who want to work + on your project. + </para> + + <para> + Pick a name convention for your headers and source code and stick to it: + <itemizedlist> + <listitem><para>use a dash to separate the prefix from the typename: + <filename>viewer-file.h</filename> and <filename>viewer-file.c</filename> + (this is the convention used by Nautilus and most GNOME libraries).</para></listitem> + <listitem><para>use an underscore to separate the prefix from the + typename: <filename>viewer_file.h</filename> and + <filename>viewer_file.c</filename>.</para></listitem> + <listitem><para>Do not separate the prefix from the typename: + <filename>viewerfile.h</filename> and <filename>viewerfile.c</filename>. + (this is the convention used by GTK+)</para></listitem> + </itemizedlist> + Some people like the first two solutions better: it makes reading file + names easier for those with poor eyesight. + </para> + + <para> + The basic conventions for any header which exposes a GType are described + in <xref linkend="gtype-conventions"/>. + </para> + + <para> + If you want to declare a type named ‘file’ in namespace ‘viewer’, name the + type instance <function>ViewerFile</function> and its class + <function>ViewerFileClass</function> (names are case sensitive). The + recommended method of declaring a type differs based on whether the type + is final or derivable. + </para> + + <para> + Final types cannot be subclassed further, and should be the default choice + for new types — changing a final type to be derivable is always a change + that will be compatible with existing uses of the code, but the converse + will often cause problems. Final types are declared using + <link linkend="G-DECLARE-FINAL-TYPE:CAPS"><function>G_DECLARE_FINAL_TYPE</function></link>, + and require a structure to hold the instance data to be declared in the + source code (not the header file). + +<informalexample><programlisting> +/* + * Copyright/Licensing information. + */ + +/* inclusion guard */ +#ifndef __VIEWER_FILE_H__ +#define __VIEWER_FILE_H__ + +#include <glib-object.h> +/* + * Potentially, include other headers on which this header depends. + */ + +G_BEGIN_DECLS + +/* + * Type declaration. + */ +#define VIEWER_TYPE_FILE viewer_file_get_type () +G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) + +/* + * Method definitions. + */ +ViewerFile *viewer_file_new (void); + +G_END_DECLS + +#endif /* __VIEWER_FILE_H__ */ +</programlisting></informalexample> + </para> + + <para> + Derivable types <emphasis>can</emphasis> be subclassed further, and their class and + instance structures form part of the public API which must not be changed + if API stability is cared about. They are declared using + <link linkend="G-DECLARE-DERIVABLE-TYPE:CAPS"><function>G_DECLARE_DERIVABLE_TYPE</function></link>: +<informalexample><programlisting> +/* + * Copyright/Licensing information. + */ + +/* inclusion guard */ +#ifndef __VIEWER_FILE_H__ +#define __VIEWER_FILE_H__ + +#include <glib-object.h> +/* + * Potentially, include other headers on which this header depends. + */ + +G_BEGIN_DECLS + +/* + * Type declaration. + */ +#define VIEWER_TYPE_FILE viewer_file_get_type () +G_DECLARE_DERIVABLE_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) + +struct _ViewerFileClass +{ + GObjectClass parent_class; + + /* Class virtual function fields. */ + void (* open) (ViewerFile *file, + GError **error); + + /* Padding to allow adding up to 12 new virtual functions without + * breaking ABI. */ + gpointer padding[12]; +}; + +/* + * Method definitions. + */ +ViewerFile *viewer_file_new (void); + +G_END_DECLS + +#endif /* __VIEWER_FILE_H__ */ +</programlisting></informalexample> + </para> + + <para> + The convention for header includes is to add the minimum number of + <function>#include</function> directives to the top of your headers needed + to compile that header. This + allows client code to simply <function>#include "viewer-file.h"</function>, + without needing to know the prerequisites for + <filename>viewer-file.h</filename>. + </para> + </sect1> + + <sect1 id="howto-gobject-code"> + <title>Boilerplate code</title> + + <para> + In your code, the first step is to <function>#include</function> the + needed headers: +<informalexample><programlisting> +/* + * Copyright information + */ + +#include "viewer-file.h" + +/* Private structure definition. */ +typedef struct { + gchar *filename; + /* stuff */ +} ViewerFilePrivate; + +/* + * forward definitions + */ +</programlisting></informalexample> + </para> + + <para> + If the class is being declared as final using + <function>G_DECLARE_FINAL_TYPE</function>, its instance structure should + be defined in the C file: +<informalexample><programlisting> +struct _ViewerFile +{ + GObject parent_instance; + + /* Other members, including private data. */ +}; +</programlisting></informalexample> + </para> + + <para> + Call the <function>G_DEFINE_TYPE</function> macro (or + <function>G_DEFINE_TYPE_WITH_PRIVATE</function> if your class needs + private data — final types do <emphasis>not</emphasis> need private data) + using the name + of the type, the prefix of the functions and the parent GType to + reduce the amount of boilerplate needed. This macro will: + + <itemizedlist> + <listitem><simpara>implement the <function>viewer_file_get_type</function> + function</simpara></listitem> + <listitem><simpara>define a parent class pointer accessible from + the whole .c file</simpara></listitem> + <listitem><simpara>add private instance data to the type (if using + <function>G_DEFINE_TYPE_WITH_PRIVATE</function>)</simpara></listitem> + </itemizedlist> + </para> + + <para> + If the class has been declared as final using + <function>G_DECLARE_FINAL_TYPE</function> (see + <xref linkend="howto-gobject-header"/>), private data should be placed in + the instance structure, <type>ViewerFile</type>, and + <function>G_DEFINE_TYPE</function> should be used instead of + <function>G_DEFINE_TYPE_WITH_PRIVATE</function>. The instance structure + for a final class is not exposed publicly, and is not embedded in the + instance structures of any derived classes (because the class is final); + so its size can vary without causing incompatibilities for code which uses + the class. Conversely, private data for derivable classes + <emphasis>must</emphasis> be included in a private structure, and + <function>G_DEFINE_TYPE_WITH_PRIVATE</function> must be used. + +<informalexample><programlisting> +G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT) +</programlisting></informalexample> +or +<informalexample><programlisting> +G_DEFINE_TYPE_WITH_PRIVATE (ViewerFile, viewer_file, G_TYPE_OBJECT) +</programlisting></informalexample> + </para> + + <para> + It is also possible to use the + <function>G_DEFINE_TYPE_WITH_CODE</function> macro to control the + <function>get_type</function> function implementation — for instance, to + add a call to the <function>G_IMPLEMENT_INTERFACE</function> macro to + implement an interface. + </para> + </sect1> + + <sect1 id="howto-gobject-construction"> + <title>Object construction</title> + + <para> + People often get confused when trying to construct their GObjects because of the + sheer number of different ways to hook into the objects's construction process: it is + difficult to figure which is the <emphasis>correct</emphasis>, recommended way. + </para> + + <para> + <xref linkend="gobject-construction-table"/> shows what user-provided functions + are invoked during object instantiation and in which order they are invoked. + A user looking for the equivalent of the simple C++ constructor function should use + the <function>instance_init</function> method. It will be invoked after + all the parents’ <function>instance_init</function> + functions have been invoked. It cannot take arbitrary construction parameters + (as in C++) but if your object needs arbitrary parameters to complete initialization, + you can use construction properties. + </para> + + <para> + Construction properties will be set only after all + <function>instance_init</function> functions have run. + No object reference will be returned to the client of <function><link linkend="g-object-new">g_object_new</link></function> + until all the construction properties have been set. + </para> + + <para> + It is important to note that object construction cannot <emphasis>ever</emphasis> + fail. If you require a fallible GObject construction, you can use the + <link linkend="GInitable"><type>GInitable</type></link> and + <link linkend="GAsyncInitable"><type>GAsyncInitable</type></link> + interfaces provided by the GIO library. + </para> + + <para> + You should write the following code first: +<informalexample><programlisting> +G_DEFINE_TYPE_WITH_PRIVATE (ViewerFile, viewer_file, G_TYPE_OBJECT) + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ +} + +static void +viewer_file_init (ViewerFile *self) +{ + ViewerFilePrivate *priv = viewer_file_get_instance_private (self); + + /* initialize all public and private members to reasonable default values. + * They are all automatically initialized to 0 to begin with. */ +} +</programlisting></informalexample> + </para> + + <para> + If you need special construction properties (with + <link linkend="G-PARAM-CONSTRUCT-ONLY:CAPS"><function>G_PARAM_CONSTRUCT_ONLY</function></link> + set), install the properties in + the <function>class_init()</function> function, override the <function>set_property()</function> + and <function>get_property()</function> methods of the GObject class, + and implement them as described by <xref linkend="gobject-properties"/>. + </para> + + <para> + Property IDs must start from 1, as 0 is reserved for internal use by + GObject. +<informalexample><programlisting> +enum +{ + PROP_FILENAME = 1, + PROP_ZOOM_LEVEL, + N_PROPERTIES +}; + +static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = viewer_file_set_property; + object_class->get_property = viewer_file_get_property; + + obj_properties[PROP_FILENAME] = + g_param_spec_string ("filename", + "Filename", + "Name of the file to load and display from.", + NULL /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + + obj_properties[PROP_ZOOM_LEVEL] = + g_param_spec_uint ("zoom-level", + "Zoom level", + "Zoom level to view the file at.", + 0 /* minimum value */, + 10 /* maximum value */, + 2 /* default value */, + G_PARAM_READWRITE); + + g_object_class_install_properties (object_class, + N_PROPERTIES, + obj_properties); +} +</programlisting></informalexample> + If you need this, make sure you can build and run code similar to the + code shown above. Also, make sure your construct properties can be set + without side effects during construction. + </para> + + <para> + Some people sometimes need to complete the initialization of an instance + of a type only after the properties passed to the constructors have been + set. This is possible through the use of the <function>constructor()</function> + class method as described in <xref linkend="gobject-instantiation"/> or, + more simply, using the <function>constructed()</function> class method. + Note that the <function>constructed()</function> + virtual function will only be invoked after the properties marked as + <function>G_PARAM_CONSTRUCT_ONLY</function> or + <function>G_PARAM_CONSTRUCT</function> have been consumed, but + before the regular properties passed to <function>g_object_new()</function> + have been set. + </para> + </sect1> + + <sect1 id="howto-gobject-destruction"> + <title>Object destruction</title> + + <para> + Again, it is often difficult to figure out which mechanism to use to + hook into the object's destruction process: when the last + <function><link linkend="g-object-unref">g_object_unref</link></function> + function call is made, a lot of things happen as described in + <xref linkend="gobject-destruction-table"/>. + </para> + + <para> + The destruction process of your object is in two phases: dispose and + finalize. This split is necessary to handle + potential cycles due to the nature of the reference counting mechanism + used by GObject, as well as dealing with temporary revival of + instances in case of signal emission during the destruction sequence. + See <xref linkend="gobject-memory-cycles"/> for more information. +<informalexample><programlisting> +struct _ViewerFilePrivate +{ + gchar *filename; + guint zoom_level; + + GInputStream *input_stream; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ViewerFile, viewer_file, G_TYPE_OBJECT) + +static void +viewer_file_dispose (GObject *gobject) +{ + ViewerFilePrivate *priv = viewer_file_get_instance_private (VIEWER_FILE (gobject)); + + /* In dispose(), you are supposed to free all types referenced from this + * object which might themselves hold a reference to self. Generally, + * the most simple solution is to unref all members on which you own a + * reference. + */ + + /* dispose() might be called multiple times, so we must guard against + * calling g_object_unref() on an invalid GObject by setting the member + * NULL; g_clear_object() does this for us. + */ + g_clear_object (&priv->input_stream); + + /* Always chain up to the parent class; there is no need to check if + * the parent class implements the dispose() virtual function: it is + * always guaranteed to do so + */ + G_OBJECT_CLASS (viewer_file_parent_class)->dispose (gobject); +} + +static void +viewer_file_finalize (GObject *gobject) +{ + ViewerFilePrivate *priv = viewer_file_get_instance_private (VIEWER_FILE (gobject)); + + g_free (priv->filename); + + /* Always chain up to the parent class; as with dispose(), finalize() + * is guaranteed to exist on the parent's class virtual function table + */ + G_OBJECT_CLASS (viewer_file_parent_class)->finalize (gobject); +} + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = viewer_file_dispose; + object_class->finalize = viewer_file_finalize; +} + +static void +viewer_file_init (ViewerFile *self); +{ + ViewerFilePrivate *priv = viewer_file_get_instance_private (self); + + priv->input_stream = g_object_new (VIEWER_TYPE_INPUT_STREAM, NULL); + priv->filename = /* would be set as a property */; +} +</programlisting></informalexample> + </para> + + <para> + It is possible that object methods might be invoked after dispose is + run and before finalize runs. GObject does not consider this to be a + program error: you must gracefully detect this and neither crash nor + warn the user, by having a disposed instance revert to an inert state. + </para> + </sect1> + + <sect1 id="howto-gobject-methods"> + <title>Object methods</title> + + <para> + Just as with C++, there are many different ways to define object + methods and extend them: the following list and sections draw on + C++ vocabulary. (Readers are expected to know basic C++ concepts. + Those who have not had to write C++ code recently can refer to e.g. + <ulink url="http://www.cplusplus.com/doc/tutorial/"/> to refresh + their memories.) + <itemizedlist> + <listitem><para> + non-virtual public methods, + </para></listitem> + <listitem><para> + virtual public methods and + </para></listitem> + <listitem><para> + virtual private methods + </para></listitem> + </itemizedlist> + </para> + + <sect2 id="non-virtual-public-methods"> + <title>Non-virtual public methods</title> + + <para> + These are the simplest, providing a simple method which + acts on the object. Provide a function + prototype in the header and an implementation of that prototype + in the source file. +<informalexample><programlisting> +/* declaration in the header. */ +void viewer_file_open (ViewerFile *self, + GError **error); + +/* implementation in the source file */ +void +viewer_file_open (ViewerFile *self, + GError **error) +{ + g_return_if_fail (VIEWER_IS_FILE (self)); + g_return_if_fail (error == NULL || *error == NULL); + + /* do stuff here. */ +} +</programlisting></informalexample> + </para> + </sect2> + + <sect2 id="virtual-public-methods"> + <title>Virtual public methods</title> + + <para> + This is the preferred way to create GObjects with overridable methods: + <itemizedlist> + <listitem><para> + Define the common method and its virtual function in the + class structure in the public header + </para></listitem> + <listitem><para> + Define the common method in the header file and implement it in the + source file + </para></listitem> + <listitem><para> + Implement a base version of the virtual function in the source + file and initialize the virtual function pointer to this + implementation in the object’s <function>class_init</function> + function; or leave it as <constant>NULL</constant> for a ‘pure + virtual’ method which must be overridden by derived classes + </para></listitem> + <listitem><para> + Re-implement the virtual function in each derived class which needs + to override it + </para></listitem> + </itemizedlist> + </para> + <para> + Note that virtual functions can only be defined if the class is + derivable, declared using + <link linkend="G-DECLARE-DERIVABLE-TYPE:CAPS"><function>G_DECLARE_DERIVABLE_TYPE</function></link> + so the class structure can be defined. +<informalexample><programlisting> +/* declaration in viewer-file.h. */ +#define VIEWER_TYPE_FILE viewer_file_get_type () +G_DECLARE_DERIVABLE_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) + +struct _ViewerFileClass +{ + GObjectClass parent_class; + + /* stuff */ + void (*open) (ViewerFile *self, + GError **error); + + /* Padding to allow adding up to 12 new virtual functions without + * breaking ABI. */ + gpointer padding[12]; +}; + +void viewer_file_open (ViewerFile *self, + GError **error); + +/* implementation in viewer-file.c */ +void +viewer_file_open (ViewerFile *self, + GError **error) +{ + ViewerFileClass *klass; + + g_return_if_fail (VIEWER_IS_FILE (self)); + g_return_if_fail (error == NULL || *error == NULL); + + klass = VIEWER_FILE_GET_CLASS (self); + g_return_if_fail (klass->open != NULL); + + klass->open (self, error); +} +</programlisting></informalexample> + The code above simply redirects the <function>open</function> call + to the relevant virtual function. + </para> + + <para> + It is possible to provide a default + implementation for this class method in the object's + <function>class_init</function> function: initialize the + <function>klass->open</function> field to a pointer to the + actual implementation. + By default, class methods that are not inherited are initialized to + <function>NULL</function>, and thus are to be considered "pure virtual". +<informalexample><programlisting> +static void +viewer_file_real_close (ViewerFile *self, + GError **error) +{ + /* Default implementation for the virtual method. */ +} + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ + /* this is not necessary, except for demonstration purposes. + * + * pure virtual method: mandates implementation in children. + */ + klass->open = NULL; + + /* merely virtual method. */ + klass->close = viewer_file_real_close; +} + +void +viewer_file_open (ViewerFile *self, + GError **error) +{ + ViewerFileClass *klass; + + g_return_if_fail (VIEWER_IS_FILE (self)); + g_return_if_fail (error == NULL || *error == NULL); + + klass = VIEWER_FILE_GET_CLASS (self); + + /* if the method is purely virtual, then it is a good idea to + * check that it has been overridden before calling it, and, + * depending on the intent of the class, either ignore it silently + * or warn the user. + */ + g_return_if_fail (klass->open != NULL); + klass->open (self, error); +} + +void +viewer_file_close (ViewerFile *self, + GError **error) +{ + ViewerFileClass *klass; + + g_return_if_fail (VIEWER_IS_FILE (self)); + g_return_if_fail (error == NULL || *error == NULL); + + klass = VIEWER_FILE_GET_CLASS (self); + if (klass->close != NULL) + klass->close (self, error); +} +</programlisting></informalexample> + </para> + </sect2> + + <sect2 id="virtual-private-methods"> + <title>Virtual private Methods</title> + + <para> + These are very similar to <link linkend="virtual-public-methods">virtual + public methods</link>. They just don't + have a public function to call directly. The header + file contains only a declaration of the virtual function: +<informalexample><programlisting> +/* declaration in viewer-file.h. */ +struct _ViewerFileClass +{ + GObjectClass parent; + + /* Public virtual method as before. */ + void (*open) (ViewerFile *self, + GError **error); + + /* Private helper function to work out whether the file can be loaded via + * memory mapped I/O, or whether it has to be read as a stream. */ + gboolean (*can_memory_map) (ViewerFile *self); + + /* Padding to allow adding up to 12 new virtual functions without + * breaking ABI. */ + gpointer padding[12]; +}; + +void viewer_file_open (ViewerFile *self, GError **error); +</programlisting></informalexample> + These virtual functions are often used to delegate part of the job + to child classes: +<informalexample><programlisting> +/* this accessor function is static: it is not exported outside of this file. */ +static gboolean +viewer_file_can_memory_map (ViewerFile *self) +{ + return VIEWER_FILE_GET_CLASS (self)->can_memory_map (self); +} + +void +viewer_file_open (ViewerFile *self, + GError **error) +{ + g_return_if_fail (VIEWER_IS_FILE (self)); + g_return_if_fail (error == NULL || *error == NULL); + + /* + * Try to load the file using memory mapped I/O, if the implementation of the + * class determines that is possible using its private virtual method. + */ + if (viewer_file_can_memory_map (self)) + { + /* Load the file using memory mapped I/O. */ + } + else + { + /* Fall back to trying to load the file using streaming I/O… */ + } +} +</programlisting></informalexample> + </para> + + <para> + Again, it is possible to provide a default implementation for this + private virtual function: +<informalexample><programlisting> +static gboolean +viewer_file_real_can_memory_map (ViewerFile *self) +{ + /* As an example, always return false. Or, potentially return true if the + * file is local. */ + return FALSE; +} + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ + /* non-pure virtual method; does not have to be implemented in children. */ + klass->can_memory_map = viewer_file_real_can_memory_map; +} +</programlisting></informalexample> + </para> + + <para> + Derived classes can then override the method with code such as: +<informalexample><programlisting> +static void +viewer_audio_file_class_init (ViewerAudioFileClass *klass) +{ + ViewerFileClass *file_class = VIEWER_FILE_CLASS (klass); + + /* implement pure virtual function. */ + file_class->can_memory_map = viewer_audio_file_can_memory_map; +} +</programlisting></informalexample> + </para> + </sect2> + </sect1> + + <sect1 id="howto-gobject-chainup"> + <title>Chaining up</title> + + <para>Chaining up is often loosely defined by the following set of + conditions: + <itemizedlist> + <listitem><para>Parent class A defines a public virtual method named <function>foo</function> and + provides a default implementation.</para></listitem> + <listitem><para>Child class B re-implements method <function>foo</function>.</para></listitem> + <listitem><para>B’s implementation of <function>foo</function> calls (‘chains up to’) its parent class A’s implementation of <function>foo</function>.</para></listitem> + </itemizedlist> + There are various uses of this idiom: + <itemizedlist> + <listitem><para>You need to extend the behaviour of a class without modifying its code. You create + a subclass to inherit its implementation, re-implement a public virtual method to modify the behaviour + and chain up to ensure that the previous behaviour is not really modified, just extended. + </para></listitem> + <listitem><para>You need to implement the + <ulink url="http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern">Chain + Of Responsibility pattern</ulink>: each object of the inheritance + tree chains up to its parent (typically, at the beginning or the end of the method) to ensure that + each handler is run in turn.</para></listitem> + </itemizedlist> + </para> + + <para> + To explicitly chain up to the implementation of the virtual method in the parent class, + you first need a handle to the original parent class structure. This pointer can then be used to + access the original virtual function pointer and invoke it directly. + <footnote> + <para> + The <emphasis>original</emphasis> adjective used in this sentence is not innocuous. To fully + understand its meaning, recall how class structures are initialized: for each object type, + the class structure associated with this object is created by first copying the class structure of its + parent type (a simple <function>memcpy</function>) and then by invoking the <function>class_init</function> callback on + the resulting class structure. Since the <function>class_init</function> callback is responsible for overwriting the class structure + with the user re-implementations of the class methods, the modified copy of the parent class + structure stored in the derived instance cannot be used. A copy of the class structure of an instance of the parent + class is needed. + </para> + </footnote> + </para> + + <para> + Use the <function>parent_class</function> pointer created and initialized + by the + <link linkend="G-DEFINE-TYPE:CAPS"><function>G_DEFINE_TYPE</function></link> + family of macros, for instance: +<informalexample><programlisting> +static void +b_method_to_call (B *obj, gint some_param) +{ + /* do stuff before chain up */ + + /* call the method_to_call() virtual function on the + * parent of BClass, AClass. + * + * remember the explicit cast to AClass* + */ + A_CLASS (b_parent_class)->method_to_call (obj, some_param); + + /* do stuff after chain up */ +} +</programlisting></informalexample> + </para> + + </sect1> + +</chapter> +<!-- End Howto GObject --> + +<chapter id="howto-interface"> + <title>How to define and implement interfaces</title> + + <sect1 id="howto-interface-define"> + <title>Defining interfaces</title> + + <para> + The theory behind how GObject interfaces work is given in + <xref linkend="gtype-non-instantiable-classed"/>; this section covers how to + define and implement an interface. + </para> + + <para> + The first step is to get the header right. This interface + defines three methods: +<informalexample><programlisting> +/* + * Copyright/Licensing information. + */ + +#ifndef __VIEWER_EDITABLE_H__ +#define __VIEWER_EDITABLE_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define VIEWER_TYPE_EDITABLE viewer_editable_get_type () +G_DECLARE_INTERFACE (ViewerEditable, viewer_editable, VIEWER, EDITABLE, GObject) + +struct _ViewerEditableInterface +{ + GTypeInterface parent_iface; + + void (*save) (ViewerEditable *self, + GError **error); + void (*undo) (ViewerEditable *self, + guint n_steps); + void (*redo) (ViewerEditable *self, + guint n_steps); +}; + +void viewer_editable_save (ViewerEditable *self, + GError **error); +void viewer_editable_undo (ViewerEditable *self, + guint n_steps); +void viewer_editable_redo (ViewerEditable *self, + guint n_steps); + +G_END_DECLS + +#endif /* __VIEWER_EDITABLE_H__ */ +</programlisting></informalexample> + This code is the same as the code for a normal <link linkend="GType"><type>GType</type></link> + which derives from a <link linkend="GObject"><type>GObject</type></link> except for a few details: + <itemizedlist> + <listitem><para> + The <function>_GET_CLASS</function> function is called + <function>_GET_IFACE</function> (and is defined by + <link linkend="G-DECLARE-INTERFACE:CAPS"><function>G_DECLARE_INTERFACE</function></link>). + </para></listitem> + <listitem><para> + The instance type, <type>ViewerEditable</type>, is not fully defined: it is + used merely as an abstract type which represents an instance of + whatever object which implements the interface. + </para></listitem> + <listitem><para> + The parent of the <type>ViewerEditableInterface</type> is + <type>GTypeInterface</type>, not <type>GObjectClass</type>. + </para></listitem> + </itemizedlist> + </para> + + <para> + The implementation of the <type>ViewerEditable</type> type itself is trivial: + <itemizedlist> + <listitem><para><function><link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link></function> + creates a <function>viewer_editable_get_type</function> function which registers the + type in the type system. The third argument is used to define a + <link linkend="howto-interface-prerequisite">prerequisite interface</link> + (which we'll talk about more later). Just pass <code>0</code> for this + argument when an interface has no prerequisite. + </para></listitem> + <listitem><para><function>viewer_editable_default_init</function> is expected + to register the interface's signals if there are any (we will see a bit + later how to use them).</para></listitem> + <listitem><para>The interface methods <function>viewer_editable_save</function>, + <function>viewer_editable_undo</function> and <function>viewer_editable_redo</function> dereference the interface + structure to access its associated interface function and call it. + </para></listitem> + </itemizedlist> +<informalexample><programlisting> +G_DEFINE_INTERFACE (ViewerEditable, viewer_editable, G_TYPE_OBJECT) + +static void +viewer_editable_default_init (ViewerEditableInterface *iface) +{ + /* add properties and signals to the interface here */ +} + +void +viewer_editable_save (ViewerEditable *self, + GError **error) +{ + ViewerEditableInterface *iface; + + g_return_if_fail (VIEWER_IS_EDITABLE (self)); + g_return_if_fail (error == NULL || *error == NULL); + + iface = VIEWER_EDITABLE_GET_IFACE (self); + g_return_if_fail (iface->save != NULL); + iface->save (self, error); +} + +void +viewer_editable_undo (ViewerEditable *self, + guint n_steps) +{ + ViewerEditableInterface *iface; + + g_return_if_fail (VIEWER_IS_EDITABLE (self)); + + iface = VIEWER_EDITABLE_GET_IFACE (self); + g_return_if_fail (iface->undo != NULL); + iface->undo (self, n_steps); +} + +void +viewer_editable_redo (ViewerEditable *self, + guint n_steps) +{ + ViewerEditableInterface *iface; + + g_return_if_fail (VIEWER_IS_EDITABLE (self)); + + iface = VIEWER_EDITABLE_GET_IFACE (self); + g_return_if_fail (iface->redo != NULL); + iface->redo (self, n_steps); +} +</programlisting></informalexample> + </para> + </sect1> + + <sect1 id="howto-interface-implement"> + <title>Implementing interfaces</title> + + <para> + Once the interface is defined, implementing it is rather trivial. + </para> + + <para> + The first step is to define a normal final GObject class exactly as in + <xref linkend="howto-gobject-header"/>. + </para> + + <para> + The second step is to implement <type>ViewerFile</type> by defining + it using + <function><link linkend="G-DEFINE-TYPE-WITH-CODE:CAPS">G_DEFINE_TYPE_WITH_CODE</link></function> + and + <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function> + instead of + <function><link linkend="G-DEFINE-TYPE:CAPS">G_DEFINE_TYPE</link></function>: +<informalexample><programlisting> +static void viewer_file_editable_interface_init (ViewerEditableInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE, + viewer_file_editable_interface_init)) +</programlisting></informalexample> + This definition is very much like all the similar functions seen + previously. The only interface-specific code present here is the use of + <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>. + </para> + + <note><para>Classes can implement multiple interfaces by using multiple calls to + <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function> + inside the call to + <function><link linkend="G-DEFINE-TYPE-WITH-CODE:CAPS">G_DEFINE_TYPE_WITH_CODE</link></function> + </para></note> + + <para> + <function>viewer_file_editable_interface_init</function>, the interface + initialization function: inside it every virtual method of the interface + must be assigned to its implementation: +<informalexample><programlisting> +static void +viewer_file_editable_save (ViewerFile *self, + GError **error) +{ + g_print ("File implementation of editable interface save method: %s.\n", + self->filename); +} + +static void +viewer_file_editable_undo (ViewerFile *self, + guint n_steps) +{ + g_print ("File implementation of editable interface undo method: %s.\n", + self->filename); +} + +static void +viewer_file_editable_redo (ViewerFile *self, + guint n_steps) +{ + g_print ("File implementation of editable interface redo method: %s.\n", + self->filename); +} + +static void +viewer_file_editable_interface_init (ViewerEditableInterface *iface) +{ + iface->save = viewer_file_editable_save; + iface->undo = viewer_file_editable_undo; + iface->redo = viewer_file_editable_redo; +} + +static void +viewer_file_init (ViewerFile *self) +{ + /* Instance variable initialisation code. */ +} +</programlisting></informalexample> + </para> + <para> + If the object is not of final type, e.g. was declared using + <function><link linkend="G-DECLARE-DERIVABLE-TYPE:CAPS">G_DECLARE_DERIVABLE_TYPE</link></function> + then + <function><link linkend="G-ADD-PRIVATE:CAPS">G_ADD_PRIVATE</link></function> + macro should be added. The private structure should be declared exactly + as for a normal derivable object, see <xref linkend="howto-gobject-code"/>. +<informalexample><programlisting> +G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, G_TYPE_OBJECT, + G_ADD_PRIVATE (ViewerFile) + G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE, + viewer_file_editable_interface_init)) +</programlisting></informalexample> + </para> + </sect1> + + <sect1 id="howto-interface-prerequisite"> + <title>Interface definition prerequisites</title> + + <para> + To specify that an interface requires the presence of other interfaces + when implemented, GObject introduces the concept of + <emphasis>prerequisites</emphasis>: it is possible to associate + a list of prerequisite types to an interface. For example, if + object A wishes to implement interface I1, and if interface I1 has a + prerequisite on interface I2, A has to implement both I1 and I2. + </para> + + <para> + The mechanism described above is, in practice, very similar to + Java's interface I1 extends interface I2. The example below shows + the GObject equivalent: +<informalexample><programlisting> +/* Make the ViewerEditableLossy interface require ViewerEditable interface. */ +G_DEFINE_INTERFACE (ViewerEditableLossy, viewer_editable_lossy, VIEWER_TYPE_EDITABLE) +</programlisting></informalexample> + In the <function><link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link></function> + call above, the third parameter defines the prerequisite type. This + is the GType of either an interface or a class. In this case + the <type>ViewerEditable</type> interface is a prerequisite of + <type>ViewerEditableLossy</type>. The code + below shows how an implementation can implement both interfaces and + register their implementations: +<informalexample><programlisting> +static void +viewer_file_editable_lossy_compress (ViewerEditableLossy *editable) +{ + ViewerFile *self = VIEWER_FILE (editable); + + g_print ("File implementation of lossy editable interface compress method: %s.\n", + self->filename); +} + +static void +viewer_file_editable_lossy_interface_init (ViewerEditableLossyInterface *iface) +{ + iface->compress = viewer_file_editable_lossy_compress; +} + +static void +viewer_file_editable_save (ViewerEditable *editable, + GError **error) +{ + ViewerFile *self = VIEWER_FILE (editable); + + g_print ("File implementation of editable interface save method: %s.\n", + self->filename); +} + +static void +viewer_file_editable_undo (ViewerEditable *editable, + guint n_steps) +{ + ViewerFile *self = VIEWER_FILE (editable); + + g_print ("File implementation of editable interface undo method: %s.\n", + self->filename); +} + +static void +viewer_file_editable_redo (ViewerEditable *editable, + guint n_steps) +{ + ViewerFile *self = VIEWER_FILE (editable); + + g_print ("File implementation of editable interface redo method: %s.\n", + self->filename); +} + +static void +viewer_file_editable_interface_init (ViewerEditableInterface *iface) +{ + iface->save = viewer_file_editable_save; + iface->undo = viewer_file_editable_undo; + iface->redo = viewer_file_editable_redo; +} + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ + /* Nothing here. */ +} + +static void +viewer_file_init (ViewerFile *self) +{ + /* Instance variable initialisation code. */ +} + +G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE, + viewer_file_editable_interface_init) + G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE_LOSSY, + viewer_file_editable_lossy_interface_init)) +</programlisting></informalexample> + It is very important to notice that the order in which interface + implementations are added to the main object is not random: + <function><link linkend="g-type-add-interface-static">g_type_add_interface_static</link></function>, + which is called by + <function><link linkend="G-DEFINE-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>, + must be invoked first on the interfaces which have no prerequisites and then on + the others. + </para> + </sect1> + + <sect1 id="howto-interface-properties"> + <title>Interface properties</title> + + <para> + GObject interfaces can also have + properties. Declaration of the interface properties is similar to + declaring the properties of ordinary GObject types as explained in + <xref linkend="gobject-properties"/>, except that + <function><link linkend="g-object-interface-install-property">g_object_interface_install_property</link></function> + is used to declare the properties instead of + <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>. + </para> + + <para> + To include a property named 'autosave-frequency' of type <type>gdouble</type> in the + <type>ViewerEditable</type> interface example code above, we only need to + add one call in <function>viewer_editable_default_init</function> as shown + below: +<informalexample><programlisting> +static void +viewer_editable_default_init (ViewerEditableInterface *iface) +{ + g_object_interface_install_property (iface, + g_param_spec_double ("autosave-frequency", + "Autosave frequency", + "Frequency (in per-seconds) to autosave backups of the editable content at. " + "Or zero to disable autosaves.", + 0.0, /* minimum */ + G_MAXDOUBLE, /* maximum */ + 0.0, /* default */ + G_PARAM_READWRITE)); +} +</programlisting></informalexample> + </para> + + <para> + One point worth noting is that the declared property wasn't assigned an + integer ID. The reason being that integer IDs of properties are used + only inside the <function>get_property</function> and + <function>set_property</function> virtual methods. Since interfaces + declare but do not <emphasis>implement</emphasis> properties, there is no + need to assign integer IDs to them. + </para> + + <para> + An implementation declares and defines its properties in the usual + way as explained in <xref linkend="gobject-properties"/>, except for one + small change: it can declare the properties of the interface it + implements using <function><link linkend="g-object-class-override-property">g_object_class_override_property</link></function> + instead of <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>. + The following code snippet shows the modifications needed in the + <type>ViewerFile</type> declaration and implementation above: +<informalexample><programlisting> +struct _ViewerFile +{ + GObject parent_instance; + + gdouble autosave_frequency; +}; + +enum +{ + PROP_AUTOSAVE_FREQUENCY = 1, + N_PROPERTIES +}; + +static void +viewer_file_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ViewerFile *file = VIEWER_FILE (object); + + switch (prop_id) + { + case PROP_AUTOSAVE_FREQUENCY: + file->autosave_frequency = g_value_get_double (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +viewer_file_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ViewerFile *file = VIEWER_FILE (object); + + switch (prop_id) + { + case PROP_AUTOSAVE_FREQUENCY: + g_value_set_double (value, file->autosave_frequency); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +viewer_file_class_init (ViewerFileClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = viewer_file_set_property; + object_class->get_property = viewer_file_get_property; + + g_object_class_override_property (object_class, PROP_AUTOSAVE_FREQUENCY, "autosave-frequency"); +} +</programlisting></informalexample> + </para> + + </sect1> + + <sect1 id="howto-interface-override"> + <title>Overriding interface methods</title> + + <para> + If a base class already implements an interface and a derived + class needs to implement the same interface but needs to override certain + methods, you must reimplement the interface and set only the interface + methods which need overriding. + </para> + + <para> + In this example, <type>ViewerAudioFile</type> is derived from + <type>ViewerFile</type>. Both implement the <type>ViewerEditable</type> + interface. <type>ViewerAudioFile</type> only implements one method of the + <type>ViewerEditable</type> interface and uses the base class implementation of + the other. +<informalexample><programlisting> +static void +viewer_audio_file_editable_save (ViewerEditable *editable, + GError **error) +{ + ViewerAudioFile *self = VIEWER_AUDIO_FILE (editable); + + g_print ("Audio file implementation of editable interface save method.\n"); +} + +static void +viewer_audio_file_editable_interface_init (ViewerEditableInterface *iface) +{ + /* Override the implementation of save(). */ + iface->save = viewer_audio_file_editable_save; + + /* + * Leave iface->undo and ->redo alone, they are already set to the + * base class implementation. + */ +} + +G_DEFINE_TYPE_WITH_CODE (ViewerAudioFile, viewer_audio_file, VIEWER_TYPE_FILE, + G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE, + viewer_audio_file_editable_interface_init)) + +static void +viewer_audio_file_class_init (ViewerAudioFileClass *klass) +{ + /* Nothing here. */ +} + +static void +viewer_audio_file_init (ViewerAudioFile *self) +{ + /* Nothing here. */ +} +</programlisting></informalexample> + </para> + + <para> + To access the base class interface implementation use + <function><link linkend="g-type-interface-peek-parent">g_type_interface_peek_parent</link></function> + from within an interface's <function>default_init</function> function. + </para> + + <para> + To call the base class implementation of an interface + method from a derived class where than interface method has been + overridden, stash away the pointer returned from + <function><link linkend="g-type-interface-peek-parent">g_type_interface_peek_parent</link></function> + in a global variable. + </para> + + <para> + In this example <type>ViewerAudioFile</type> overrides the + <function>save</function> interface method. In its overridden method + it calls the base class implementation of the same interface method. +<informalexample><programlisting> +static ViewerEditableInterface *viewer_editable_parent_interface = NULL; + +static void +viewer_audio_file_editable_save (ViewerEditable *editable, + GError **error) +{ + ViewerAudioFile *self = VIEWER_AUDIO_FILE (editable); + + g_print ("Audio file implementation of editable interface save method.\n"); + + /* Now call the base implementation */ + viewer_editable_parent_interface->save (editable, error); +} + +static void +viewer_audio_file_editable_interface_init (ViewerEditableInterface *iface) +{ + viewer_editable_parent_interface = g_type_interface_peek_parent (iface); + + iface->save = viewer_audio_file_editable_save; +} + +G_DEFINE_TYPE_WITH_CODE (ViewerAudioFile, viewer_audio_file, VIEWER_TYPE_FILE, + G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE, + viewer_audio_file_editable_interface_init)) + +static void +viewer_audio_file_class_init (ViewerAudioFileClass *klass) +{ + /* Nothing here. */ +} + +static void +viewer_audio_file_init (ViewerAudioFile *self) +{ + /* Nothing here. */ +} +</programlisting></informalexample> + </para> + + </sect1> + +</chapter> +<!-- End Howto Interfaces --> + +<chapter id="howto-signals"> + <title>How to create and use signals</title> + + <para> + The signal system in GType is pretty complex and + flexible: it is possible for its users to connect at runtime any + number of callbacks (implemented in any language for which a binding + exists) + <footnote> + <para>A Python callback can be connected to any signal on any + C-based GObject, and vice versa, assuming that the Python object + inherits from GObject.</para> + </footnote> + to any signal and to stop the emission of any signal at any + state of the signal emission process. This flexibility makes it + possible to use GSignal for much more than just emitting signals to + multiple clients. + </para> + + <sect1 id="howto-simple-signals"> + <title>Simple use of signals</title> + + <para> + The most basic use of signals is to implement event + notification. For example, given a <type>ViewerFile</type> object with + a <function>write</function> method, a signal could be emitted whenever + the file is changed using that method. + The code below shows how the user can connect a callback to the + "changed" signal. +<informalexample><programlisting> +file = g_object_new (VIEWER_FILE_TYPE, NULL); + +g_signal_connect (file, "changed", (GCallback) changed_event, NULL); + +viewer_file_write (file, buffer, strlen (buffer)); +</programlisting></informalexample> + </para> + + <para> + The <type>ViewerFile</type> signal is registered in the + <function>class_init</function> function: +<informalexample><programlisting> +file_signals[CHANGED] = + g_signal_newv ("changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + NULL /* closure */, + NULL /* accumulator */, + NULL /* accumulator data */, + NULL /* C marshaller */, + G_TYPE_NONE /* return_type */, + 0 /* n_params */, + NULL /* param_types */); +</programlisting></informalexample> + and the signal is emitted in <function>viewer_file_write</function>: +<informalexample><programlisting> +void +viewer_file_write (ViewerFile *self, + const guint8 *buffer, + gsize size) +{ + g_return_if_fail (VIEWER_IS_FILE (self)); + g_return_if_fail (buffer != NULL || size == 0); + + /* First write data. */ + + /* Then, notify user of data written. */ + g_signal_emit (self, file_signals[CHANGED], 0 /* details */); +} +</programlisting></informalexample> + As shown above, the details parameter can safely be set to zero if no + detail needs to be conveyed. For a discussion of what it can be used for, + see <xref linkend="signal-detail"/> + </para> + + <para> + The C signal marshaller should always be <literal>NULL</literal>, in which + case the best marshaller for the given closure type will be chosen by + GLib. This may be an internal marshaller specific to the closure type, or + <function>g_cclosure_marshal_generic</function>, which implements generic + conversion of arrays of parameters to C callback invocations. GLib used to + require the user to write or generate a type-specific marshaller and pass + that, but that has been deprecated in favour of automatic selection of + marshallers. + </para> + + <para> + Note that <function>g_cclosure_marshal_generic</function> is slower than + non-generic marshallers, so should be avoided for performance critical + code. However, performance critical code should rarely be using signals + anyway, as emitting a signal blocks on emitting it to all listeners, which + has potentially unbounded cost. + </para> + </sect1> +</chapter> +</part>
diff --git a/docs/reference/gobject/tut_intro.xml b/docs/reference/gobject/tut_intro.xml new file mode 100644 index 0000000..7614bf0 --- /dev/null +++ b/docs/reference/gobject/tut_intro.xml
@@ -0,0 +1,185 @@ +<?xml version='1.0' encoding="UTF-8"?> +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<chapter id="chapter-intro"> + <title>Background</title> + + <para> + GObject, and its lower-level type system, GType, are used by GTK+ and most GNOME libraries to + provide: + <itemizedlist> + <listitem><para>object-oriented C-based APIs and</para></listitem> + <listitem><para>automatic transparent API bindings to other compiled + or interpreted languages.</para></listitem> + </itemizedlist> + </para> + + <para> + A lot of programmers are used to working with compiled-only or dynamically interpreted-only + languages and do not understand the challenges associated with cross-language interoperability. + This introduction tries to provide an insight into these challenges and briefly describes + the solution chosen by GLib. + </para> + + <para> + The following chapters go into greater detail into how GType and GObject work and + how you can use them as a C programmer. It is useful to keep in mind that + allowing access to C objects from other interpreted languages was one of the major design + goals: this can often explain the sometimes rather convoluted APIs and features present + in this library. + </para> + + <sect1> + <title>Data types and programming</title> + + <para> + One could say + that a programming language is merely a way to create data types and manipulate them. Most languages + provide a number of language-native types and a few primitives to create more complex types based + on these primitive types. + </para> + + <para> + In C, the language provides types such as <emphasis>char</emphasis>, <emphasis>long</emphasis>, + <emphasis>pointer</emphasis>. During compilation of C code, the compiler maps these + language types to the compiler's target architecture machine types. If you are using a C interpreter + (assuming one exists), the interpreter (the program which interprets + the source code and executes it) maps the language types to the machine types of the target machine at + runtime, during the program execution (or just before execution if it uses a Just In Time compiler engine). + </para> + + <para> + Perl and Python are interpreted languages which do not really provide type definitions similar + to those used by C. Perl and Python programmers manipulate variables and the type of the variables + is decided only upon the first assignment or upon the first use which forces a type on the variable. + The interpreter also often provides a lot of automatic conversions from one type to the other. For example, + in Perl, a variable which holds an integer can be automatically converted to a string given the + required context: +<informalexample><programlisting> +my $tmp = 10; +print "this is an integer converted to a string:" . $tmp . "\n"; +</programlisting></informalexample> + Of course, it is also often possible to explicitly specify conversions when the default conversions provided + by the language are not intuitive. + </para> + + </sect1> + + <sect1> + <title>Exporting a C API</title> + + <para> + C APIs are defined by a set of functions and global variables which are usually exported from a + binary. C functions have an arbitrary number of arguments and one return value. Each function is thus + uniquely identified by the function name and the set of C types which describe the function arguments + and return value. The global variables exported by the API are similarly identified by their name and + their type. + </para> + + <para> + A C API is thus merely defined by a set of names to which a set of types are associated. If you know the + function calling convention and the mapping of the C types to the machine types used by the platform you + are on, you can resolve the name of each function to find where the code associated to this function + is located in memory, and then construct a valid argument list for the function. Finally, all you have to + do is trigger a call to the target C function with the argument list. + </para> + + <para> + For the sake of discussion, here is a sample C function and the associated 32 bit x86 + assembly code generated by GCC on a Linux computer: +<informalexample><programlisting> +static void +function_foo (int foo) +{ +} + +int +main (int argc, + char *argv[]) +{ + function_foo (10); + + return 0; +} + +push $0xa +call 0x80482f4 <function_foo> +</programlisting></informalexample> + The assembly code shown above is pretty straightforward: the first instruction pushes + the hexadecimal value 0xa (decimal value 10) as a 32-bit integer on the stack and calls + <function>function_foo</function>. As you can see, C function calls are implemented by + GCC as native function calls (this is probably the fastest implementation possible). + </para> + + <para> + Now, let's say we want to call the C function <function>function_foo</function> from + a Python program. To do this, the Python interpreter needs to: + <itemizedlist> + <listitem><para>Find where the function is located. This probably means finding the binary generated by the C compiler + which exports this function.</para></listitem> + <listitem><para>Load the code of the function in executable memory.</para></listitem> + <listitem><para>Convert the Python parameters to C-compatible parameters before calling + the function.</para></listitem> + <listitem><para>Call the function with the right calling convention.</para></listitem> + <listitem><para>Convert the return values of the C function to Python-compatible + variables to return them to the Python code.</para></listitem> + </itemizedlist> + </para> + + <para> + The process described above is pretty complex and there are a lot of ways to make it entirely automatic + and transparent to C and Python programmers: + <itemizedlist> + <listitem><para>The first solution is to write by hand a lot of glue code, once for each function exported or imported, + which does the Python-to-C parameter conversion and the C-to-Python return value conversion. This glue code is then + linked with the interpreter which allows Python programs to call Python functions which delegate work to + C functions.</para></listitem> + <listitem><para>Another, nicer solution is to automatically generate the glue code, once for each function exported or + imported, with a special compiler which + reads the original function signature.</para></listitem> + <listitem><para>The solution used by GLib is to use the GType library which holds at runtime a description of + all the objects manipulated by the programmer. This so-called <emphasis>dynamic type</emphasis> + <footnote> + <para> + There are numerous different implementations of dynamic type systems: all C++ + compilers have one, Java and .NET have one too. A dynamic type system allows you + to get information about every instantiated object at runtime. It can be implemented + by a process-specific database: every new object created registers the characteristics + of its associated type in the type system. It can also be implemented by introspection + interfaces. The common point between all these different type systems and implementations + is that they all allow you to query for object metadata at runtime. + </para> + </footnote> + library is then used by special generic glue code to automatically convert function parameters and + function calling conventions between different runtime domains.</para></listitem> + </itemizedlist> + The greatest advantage of the solution implemented by GType is that the glue code sitting at the runtime domain + boundaries is written once: the figure below states this more clearly. + <figure> + <mediaobject> + <imageobject> <!-- this is for HTML output --> + <imagedata fileref="glue.png" format="PNG" align="center"/> + </imageobject> + <imageobject> <!-- this is for PDF output --> + <imagedata fileref="glue.jpg" format="JPG" align="center"/> + </imageobject> + </mediaobject> + </figure> + + Currently, there exist at least Python and Perl generic glue code which makes it possible to use + C objects written with GType directly in Python or Perl, with a minimum amount of work: there + is no need to generate huge amounts of glue code either automatically or by hand. + </para> + + <para> + Although that goal was arguably laudable, its pursuit has had a major influence on + the whole GType/GObject library. C programmers are likely to be puzzled at the complexity + of the features exposed in the following chapters if they forget that the GType/GObject library + was not only designed to offer OO-like features to C programmers but also transparent + cross-language interoperability. + </para> + + </sect1> + +</chapter>
diff --git a/docs/reference/gobject/tut_tools.xml b/docs/reference/gobject/tut_tools.xml new file mode 100644 index 0000000..f1076e8 --- /dev/null +++ b/docs/reference/gobject/tut_tools.xml
@@ -0,0 +1,125 @@ +<?xml version='1.0' encoding="UTF-8"?> +<!DOCTYPE part PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> +<part label="V"> + <title>Related Tools</title> + + <partintro> + <para> + Several useful developer tools have been build around GObject + technology. The next sections briefly introduce them and link to + the respective project pages. + </para> + + <para> + For example, writing GObjects is often seen as a tedious task. It + requires a lot of typing and just doing a copy/paste requires a + great deal of care. A lot of projects and scripts have been + written to generate GObject skeleton form boilerplate code, or + even translating higher-level language into plain C. + </para> + </partintro> + + <chapter id="tools-vala"> + <title>Vala</title> + <para> + From the <ulink url="https://wiki.gnome.org/Projects/Vala">Vala + homepage</ulink> itself: <quote>Vala is a new programming language + that aims to bring modern programming language features to GNOME + developers without imposing any additional runtime requirements + and without using a different ABI compared to applications and + libraries written in C.</quote> + </para> + + <para> + The syntax of Vala is similar to C#. The available compiler + translates Vala into GObject C code. It can also compile + non-GObject C, using plain C API. + </para> + </chapter> + + <chapter id="tools-gob"> + <title>GObject builder</title> + + <para> + In order to help a GObject class developer, one obvious idea is + to use some sort of templates for the skeletons and then run + them through a special tool to generate the real C files. <ulink + url="http://www.5z.com/jirka/gob.html">GOB</ulink> (or GOB2) is + such a tool. It is a preprocessor which can be used to build + GObjects with inline C code so that there is no need to edit the + generated C code. The syntax is inspired by Java and Yacc or + Lex. The implementation is intentionally kept simple: the inline C + code provided by the user is not parsed. + </para> + </chapter> + + <chapter id="tools-ginspector"> + <title>Graphical inspection of GObjects</title> + + <para> + Yet another tool that you may find helpful when working with + GObjects is <ulink + url="http://sourceforge.net/projects/g-inspector">G-Inspector</ulink>. It + is able to display GLib/GTK+ objects and their properties. + </para> + </chapter> + + <chapter id="tools-refdb"> + <title>Debugging reference count problems</title> + + <para> + The reference counting scheme used by GObject does solve quite + a few memory management problems but also introduces new sources of bugs. + In large applications, finding the exact spot where the reference count + of an Object is not properly handled can be very difficult. + </para> + <para> + A useful tool in debugging reference counting problems is to + set breakpoints in gdb on g_object_ref() and g_object_unref(). + Once you know the address of the object you are interested in, + you can make the breakpoints conditional: + <programlisting> +break g_object_ref if _object == 0xcafebabe +break g_object_unref if _object == 0xcafebabe + </programlisting> + </para> + </chapter> + + <chapter id="tools-gtkdoc"> + <title>Writing API docs</title> + + <para>The API documentation for most of the GLib, GObject, GTK+ and GNOME + libraries is built with a combination of complex tools. Typically, the part of + the documentation which describes the behavior of each function is extracted + from the specially-formatted source code comments by a tool named gtk-doc which + generates DocBook XML and merges this DocBook XML with a set of template XML + DocBook files. These XML DocBook files are finally processed with xsltproc + (a small program part of the libxslt library) to generate the final HTML + output. Other tools can be used to generate PDF output from the source XML. + The following code excerpt shows what these comments look like. + <informalexample><programlisting> +/** + * gtk_widget_freeze_child_notify: + * @widget: a #GtkWidget + * + * Stops emission of "child-notify" signals on @widget. The signals are + * queued until gtk_widget_thaw_child_notify() is called on @widget. + * + * This is the analogue of g_object_freeze_notify() for child properties. + **/ +void +gtk_widget_freeze_child_notify (GtkWidget *widget) +{ +... + </programlisting></informalexample> + </para> + <para> + Thorough + <ulink url="https://developer.gnome.org/gtk-doc-manual/stable/">documentation</ulink> + on how to set up and use gtk-doc in your project is provided on the + <ulink url="https://developer.gnome.org/">GNOME developer website</ulink>. + </para> + </chapter> +</part>
diff --git a/docs/reference/gobject/version.xml.in b/docs/reference/gobject/version.xml.in new file mode 100644 index 0000000..af9b9c4 --- /dev/null +++ b/docs/reference/gobject/version.xml.in
@@ -0,0 +1 @@ +@GLIB_VERSION@
diff --git a/docs/reference/gobject/xml/gtkdocentities.ent.in b/docs/reference/gobject/xml/gtkdocentities.ent.in new file mode 100644 index 0000000..f12c9ff --- /dev/null +++ b/docs/reference/gobject/xml/gtkdocentities.ent.in
@@ -0,0 +1,8 @@ +<!ENTITY package "@PACKAGE@"> +<!ENTITY package_bugreport "@PACKAGE_BUGREPORT@"> +<!ENTITY package_name "@PACKAGE_NAME@"> +<!ENTITY package_string "@PACKAGE_STRING@"> +<!ENTITY package_tarname "@PACKAGE_TARNAME@"> +<!ENTITY package_url "@PACKAGE_URL@"> +<!ENTITY package_version "@PACKAGE_VERSION@"> +<!ENTITY package_api_version "@PACKAGE_API_VERSION@">
diff --git a/docs/reference/gobject/xml/meson.build b/docs/reference/gobject/xml/meson.build new file mode 100644 index 0000000..6aeb745 --- /dev/null +++ b/docs/reference/gobject/xml/meson.build
@@ -0,0 +1,14 @@ +ent_conf = configuration_data() +ent_conf.set('PACKAGE', 'glib') +ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/glib/issues/new') +ent_conf.set('PACKAGE_NAME', 'glib') +ent_conf.set('PACKAGE_STRING', 'glib') +ent_conf.set('PACKAGE_TARNAME', 'glib') +ent_conf.set('PACKAGE_URL', 'FIXME') +ent_conf.set('PACKAGE_VERSION', glib_version) +ent_conf.set('PACKAGE_API_VERSION', glib_api_version) +configure_file( + input: 'gtkdocentities.ent.in', + output: 'gtkdocentities.ent', + configuration: ent_conf +)
diff --git a/docs/reference/meson.build b/docs/reference/meson.build new file mode 100644 index 0000000..a676af1 --- /dev/null +++ b/docs/reference/meson.build
@@ -0,0 +1,62 @@ +# The list of minor versions in the 2.x.x series which have had +# GLIB_AVAILABLE_IN_* macros. This should include the current unreleased stable +# version. +# +# FIXME: It would be good to be able to generate this list: +# https://github.com/mesonbuild/meson/issues/5026 +stable_2_series_versions = [ + '26', '28', '30', '32', '34', '36', '38', + '40', '42', '44', '46', '48', '50', '52', '54', '56', '58', + '60', '62', '64', '66', +] + +ignore_decorators = [ + 'GLIB_VAR', + 'G_GNUC_INTERNAL', + 'G_GNUC_WARN_UNUSED_RESULT', + 'GLIB_AVAILABLE_IN_ALL', +] + +foreach version : stable_2_series_versions + ignore_decorators += [ + # Note that gtkdoc is going to use those in regex, and the longest match + # must come first. That's why '_FOR()' variant comes first. + # gtkdoc special-case '()' and replace it by a regex matching a symbol name. + 'GLIB_AVAILABLE_IN_2_' + version, + 'GLIB_DEPRECATED_IN_2_' + version + '_FOR()', + 'GLIB_DEPRECATED_IN_2_' + version, + + 'GLIB_AVAILABLE_STATIC_INLINE_IN_2_' + version, + + 'GLIB_AVAILABLE_ENUMERATOR_IN_2_' + version, + 'GLIB_DEPRECATED_ENUMERATOR_IN_2_' + version + '_FOR()', + 'GLIB_DEPRECATED_ENUMERATOR_IN_2_' + version, + + 'GLIB_AVAILABLE_MACRO_IN_2_' + version, + 'GLIB_DEPRECATED_MACRO_IN_2_' + version + '_FOR()', + 'GLIB_DEPRECATED_MACRO_IN_2_' + version, + + 'GLIB_AVAILABLE_TYPE_IN_2_' + version, + 'GLIB_DEPRECATED_TYPE_IN_2_' + version + '_FOR()', + 'GLIB_DEPRECATED_TYPE_IN_2_' + version, + ] +endforeach + +gtkdoc_common_scan_args = [ + '--ignore-decorators=' + '|'.join(ignore_decorators), +] + +if get_option('gtk_doc') + if not meson.version().version_compare('>=0.52.0') + error('Building documentation requires Meson >= 0.52.0.') + endif + # Check we have the minimum gtk-doc version required. Older versions won't + # generate correct documentation. + dependency('gtk-doc', version : '>=1.32.1', + fallback : ['gtk-doc', 'dummy_dep'], + default_options : ['tests=false']) +endif + +subdir('gio') +subdir('glib') +subdir('gobject')
diff --git a/fuzzing/README.md b/fuzzing/README.md new file mode 100644 index 0000000..16f5a05 --- /dev/null +++ b/fuzzing/README.md
@@ -0,0 +1,51 @@ +Fuzz targets used by [oss-fuzz](https://github.com/google/oss-fuzz/). + +Useful links: [Dashboard](https://oss-fuzz.com/) _(requires access)_, [Build logs](https://oss-fuzz-build-logs.storage.googleapis.com/index.html), [Coverage](https://oss-fuzz.com/coverage-report/job/libfuzzer_asan_glib/latest) + +## How to add new targets + +Add **fuzz_target_name.c** and edit `meson.build` accordingly. + +New targets are picked up by oss-fuzz automatically within a day. Targets must not be renamed once added. + +Add (optional) **fuzz_target_name.dict** containing keywords and magic bytes. + +Add (optional) **fuzz_target_name.corpus** with file names on separate lines. Wildcards `?`, `*` and `**` are supported. Examples below. + +```bash +glib/* # all files in directory glib +glib/** # all files in directory glib and sub-directories +**.xbel # all files ending with .xbel in the repository +``` + +Recommended reading: [Fuzz Target](https://llvm.org/docs/LibFuzzer.html#fuzz-target), [Dictionaries](https://llvm.org/docs/LibFuzzer.html#dictionaries), [Corpus](https://llvm.org/docs/LibFuzzer.html#corpus) + +## How to reproduce oss-fuzz bugs locally + +Build with at least the following flags, choosing a sanitizer as needed. A somewhat recent version of [clang](http://clang.llvm.org/) is recommended. + +```bash +$ CC=clang CXX=clang++ meson DIR -Db_sanitize=<address|undefined> -Db_lundef=false +``` + +Afterwards run the affected target against the provided test case. + +```bash +$ DIR/fuzzing/fuzz_target_name FILE +``` + +#### FAQs + +###### What about Memory Sanitizer (MSAN)? + +Correct MSAN instrumentation is [difficult to achieve](https://clang.llvm.org/docs/MemorySanitizer.html#handling-external-code) locally, so false positives are very likely to mask the actual bug. + +If need be, [you can still reproduce](https://github.com/google/oss-fuzz/blob/master/docs/reproducing.md#building-using-docker) those bugs with the oss-fuzz provided docker images. + +###### There are no file/function names in the stack trace. + +`llvm-symbolizer` must be in `PATH`. + +###### UndefinedBehavior Sanitizer (UBSAN) doesn't provide a stack trace. + +Set environment variable `UBSAN_OPTIONS` to `print_stacktrace=1` prior to running the target.
diff --git a/fuzzing/driver.c b/fuzzing/driver.c new file mode 100644 index 0000000..99e965b --- /dev/null +++ b/fuzzing/driver.c
@@ -0,0 +1,32 @@ +/* Simpler gnu89 version of StandaloneFuzzTargetMain.c from LLVM */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +extern int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size); + +int +main (int argc, char **argv) +{ + FILE *f; + size_t n_read, len; + unsigned char *buf; + + if (argc < 2) + return 1; + + f = fopen (argv[1], "r"); + assert (f); + fseek (f, 0, SEEK_END); + len = ftell (f); + fseek (f, 0, SEEK_SET); + buf = (unsigned char*) malloc (len); + n_read = fread (buf, 1, len, f); + assert (n_read == len); + LLVMFuzzerTestOneInput (buf, len); + + free (buf); + printf ("Done!\n"); + return 0; +}
diff --git a/fuzzing/fuzz.h b/fuzzing/fuzz.h new file mode 100644 index 0000000..4a87998 --- /dev/null +++ b/fuzzing/fuzz.h
@@ -0,0 +1,22 @@ +#include "gio/gio.h" +#include "glib/glib.h" + +int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size); + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +static GLogWriterOutput +empty_logging_func (GLogLevelFlags log_level, const GLogField *fields, + gsize n_fields, gpointer user_data) +{ + return G_LOG_WRITER_HANDLED; +} +#endif + +/* Disables logging for oss-fuzz. Must be used with each target. */ +static void +fuzz_set_logging_func (void) +{ +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + g_log_set_writer_func (empty_logging_func, NULL, NULL); +#endif +}
diff --git a/fuzzing/fuzz_bookmark.c b/fuzzing/fuzz_bookmark.c new file mode 100644 index 0000000..4f257fd --- /dev/null +++ b/fuzzing/fuzz_bookmark.c
@@ -0,0 +1,15 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + GBookmarkFile *bookmark = NULL; + + fuzz_set_logging_func (); + + bookmark = g_bookmark_file_new (); + g_bookmark_file_load_from_data (bookmark, (const gchar*) data, size, NULL); + + g_bookmark_file_free (bookmark); + return 0; +}
diff --git a/fuzzing/fuzz_bookmark.corpus b/fuzzing/fuzz_bookmark.corpus new file mode 100644 index 0000000..5c78bc9 --- /dev/null +++ b/fuzzing/fuzz_bookmark.corpus
@@ -0,0 +1 @@ +glib/tests/**.xbel
diff --git a/fuzzing/fuzz_dbus_message.c b/fuzzing/fuzz_dbus_message.c new file mode 100644 index 0000000..bccb2ba --- /dev/null +++ b/fuzzing/fuzz_dbus_message.c
@@ -0,0 +1,28 @@ +#include "fuzz.h" + +const static GDBusCapabilityFlags flags = G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING; + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + gssize bytes; + GDBusMessage *msg = NULL; + guchar *blob = NULL; + gsize msg_size; + + fuzz_set_logging_func (); + + bytes = g_dbus_message_bytes_needed ((guchar*) data, size, NULL); + if (bytes <= 0) + return 0; + + msg = g_dbus_message_new_from_blob ((guchar*) data, size, flags, NULL); + if (msg == NULL) + return 0; + + blob = g_dbus_message_to_blob (msg, &msg_size, flags, NULL); + + g_free (blob); + g_object_unref (msg); + return 0; +}
diff --git a/fuzzing/fuzz_key.c b/fuzzing/fuzz_key.c new file mode 100644 index 0000000..8d0edc5 --- /dev/null +++ b/fuzzing/fuzz_key.c
@@ -0,0 +1,16 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + GKeyFile *key = NULL; + + fuzz_set_logging_func (); + + key = g_key_file_new (); + g_key_file_load_from_data (key, (const gchar*) data, size, G_KEY_FILE_NONE, + NULL); + + g_key_file_free (key); + return 0; +}
diff --git a/fuzzing/fuzz_key.corpus b/fuzzing/fuzz_key.corpus new file mode 100644 index 0000000..5a1cb41 --- /dev/null +++ b/fuzzing/fuzz_key.corpus
@@ -0,0 +1,2 @@ +glib/tests/**.ini +gio/tests/**.desktop
diff --git a/fuzzing/fuzz_variant_binary.c b/fuzzing/fuzz_variant_binary.c new file mode 100644 index 0000000..995718c --- /dev/null +++ b/fuzzing/fuzz_variant_binary.c
@@ -0,0 +1,21 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + GVariant *variant = NULL, *normal_variant = NULL; + + fuzz_set_logging_func (); + + variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size, FALSE, + NULL, NULL); + if (variant == NULL) + return 0; + + normal_variant = g_variant_take_ref (g_variant_get_normal_form (variant)); + g_variant_get_data (variant); + + g_variant_unref (normal_variant); + g_variant_unref (variant); + return 0; +}
diff --git a/fuzzing/fuzz_variant_text.c b/fuzzing/fuzz_variant_text.c new file mode 100644 index 0000000..a797909 --- /dev/null +++ b/fuzzing/fuzz_variant_text.c
@@ -0,0 +1,21 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + const gchar *gdata = (const gchar*) data; + GVariant *variant = NULL; + gchar *text = NULL; + + fuzz_set_logging_func (); + + variant = g_variant_parse (NULL, gdata, gdata + size, NULL, NULL); + if (variant == NULL) + return 0; + + text = g_variant_print (variant, TRUE); + + g_free (text); + g_variant_unref (variant); + return 0; +}
diff --git a/fuzzing/fuzz_variant_text.dict b/fuzzing/fuzz_variant_text.dict new file mode 100644 index 0000000..a0e5284 --- /dev/null +++ b/fuzzing/fuzz_variant_text.dict
@@ -0,0 +1,32 @@ +"'" +"\"" +"(" +")" +"<" +">" +"[" +"]" +"{" +"}" +"*" +"?" +"@" +"b'" +"b\"" +"boolean" +"byte" +"double" +"false" +"handle" +"int16" +"int32" +"int64" +"just" +"nothing" +"objectpath" +"signature" +"string" +"true" +"uint16" +"uint32" +"uint64"
diff --git a/fuzzing/meson.build b/fuzzing/meson.build new file mode 100644 index 0000000..7fdd8c9 --- /dev/null +++ b/fuzzing/meson.build
@@ -0,0 +1,28 @@ +fuzz_targets = [ + 'fuzz_bookmark', + 'fuzz_dbus_message', + 'fuzz_key', + 'fuzz_variant_binary', + 'fuzz_variant_text', +] + +deps = [libgmodule_dep, libgio_dep, libglib_dep, libgobject_dep] + +extra_sources = [] +extra_c_args = cc.get_supported_arguments('-Werror=unused-function') + +# Links in a static library provided by oss-fuzz, else a standalone driver. +# https://github.com/google/oss-fuzz/blob/master/docs/new_project_guide.md#buildsh-script-environment +fuzzing_engine = cxx.find_library('FuzzingEngine', required : get_option('oss_fuzz')) +if fuzzing_engine.found() + deps += fuzzing_engine +else + extra_sources += 'driver.c' +endif + +foreach target_name : fuzz_targets + exe = executable(target_name, [extra_sources, target_name + '.c'], + c_args : extra_c_args, + dependencies : deps, + ) +endforeach
diff --git a/gio/completion/.gitignore b/gio/completion/.gitignore new file mode 100644 index 0000000..6930af9 --- /dev/null +++ b/gio/completion/.gitignore
@@ -0,0 +1 @@ +!gio
diff --git a/gio/completion/gapplication b/gio/completion/gapplication new file mode 100644 index 0000000..565025b --- /dev/null +++ b/gio/completion/gapplication
@@ -0,0 +1,55 @@ + +# Check for bash +[ -z "$BASH_VERSION" ] && return + +#################################################################################################### + +__app() { + case "${COMP_CWORD}" in + 1) + COMPREPLY=($(compgen -W "help version list-apps launch action list-actions" -- "${COMP_WORDS[1]}")) + return 0 + ;; + + 2) + case "${COMP_WORDS[1]}" in + launch|action|list-actions) + COMPREPLY=($(compgen -W "`gapplication list-apps`" -- "${COMP_WORDS[2]}")) + return 0 + ;; + + *) + COMPREPLY=() + return 0 + ;; + esac + ;; + esac + + # Otherwise, what we will do is based on the command in ${COMP_WORDS[1]} + case "${COMP_WORDS[1]}" in + action) + # Word 3 is the action name. This is the only one we can help with. + if [ "${COMP_CWORD}" == 3 ]; then + COMPREPLY=($(compgen -W "`gapplication list-actions "${COMP_WORDS[2]}"`" -- "${COMP_WORDS[3]}")) + return 0 + else + COMPREPLY=() + return 0 + fi + ;; + launch) + # Filenames... + COMPREPLY=($(compgen -A file "${COMP_WORDS[COMP_CWORD]}")) + return 0 + ;; + *) + # Nothing else should be out this far... + COMPREPLY=() + return 0 + esac +} + +#################################################################################################### + +complete -F __app gapplication
diff --git a/gio/completion/gdbus b/gio/completion/gdbus new file mode 100644 index 0000000..79f4cb4 --- /dev/null +++ b/gio/completion/gdbus
@@ -0,0 +1,33 @@ + +# Check for bash +[ -z "$BASH_VERSION" ] && return + +#################################################################################################### + + +__gdbus() { + local IFS=$'\n' + local cur=`_get_cword :` + + local suggestions=$(gdbus complete "${COMP_LINE}" ${COMP_POINT}) + COMPREPLY=($(compgen -W "$suggestions" -- "$cur")) + + # Remove colon-word prefix from COMPREPLY items + case "$cur" in + *:*) + case "$COMP_WORDBREAKS" in + *:*) + local colon_word=${cur%${cur##*:}} + local i=${#COMPREPLY[*]} + while [ $((--i)) -ge 0 ]; do + COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} + done + ;; + esac + ;; + esac +} + +#################################################################################################### + +complete -o nospace -F __gdbus gdbus
diff --git a/gio/completion/gio b/gio/completion/gio new file mode 100644 index 0000000..75473d2 --- /dev/null +++ b/gio/completion/gio
@@ -0,0 +1,119 @@ +# +# Copyright (C) 2018 Red Hat, Inc. +# +# 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 2.1 of the +# licence, or (at your option) any later version. +# +# This 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 Lesser 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 <http://www.gnu.org/licenses/>. +# + +# Check for bash +[ -z "$BASH_VERSION" ] && return + +#################################################################################################### + +# Check whether the suggestions have common prefix (i.e. suggestions won't be +# shown and prefix will be completed first) +__has_common_prefix() { + for (( i = 1; i < ${#COMPREPLY[@]}; i++ )); do + if [[ "${COMPREPLY[i-1]:${#cur}:1}" != "${COMPREPLY[i]:${#cur}:1}" ]]; then + return 1 # False + fi + done + + return 0 # True +} + +# Complete file location +__gio_location() { + # Prevent breaking on colons, we have to work with uris + local cur + _get_comp_words_by_ref -n : cur + + # Resolve dirname for dir listing + local dir="" + if [[ $cur =~ "/"$ ]]; then + dir="$cur" + elif [[ $cur =~ "/" ]]; then + # Subtract basename because dirname cmd doesn't work well with schemes + dir=${cur%$(basename "$cur")} + fi + + # List volumes and mounts + local mounts=( ) + while IFS=$'\n' read mount; do + # Do not care about local mounts + [[ "$mount" =~ ^"file:" ]] && continue + + # Use only matching mounts + [[ "$mount" =~ ^"$cur" && "$mount" != "$cur" ]] && mounts+=("$mount") + done < <(gio mount -li | sed -n -r 's/^ *(default_location|activation_root)=(.*)$/\2/p' | sort -u) + + # Workaround to unescape dir name (e.g. "\ " -> " ") + declare -a tmp="( ${dir} )" + unescaped_dir="${tmp[0]}" + + # List files + local files=() + local names=() + while IFS=$'\t' read name size type; do + # Escape name properly + local escaped_name="$(printf "%q" "$name")" + + # Append slash for directories and space for files + if [[ "$type" == "(directory)" ]]; then + escaped_name="$escaped_name/" + else + escaped_name="$escaped_name " + fi + + path="$dir$escaped_name" + + # Use only matching paths + if [[ "$path" =~ ^"$cur" ]]; then + files+=("$path") + names+=("$escaped_name") + fi + done < <(gio list -hl "$unescaped_dir" 2> /dev/null) + + COMPREPLY=("${files[@]}" "${mounts[@]}") + + # Workaround to show suggestions as basenames only + if ! __has_common_prefix; then + COMPREPLY=("${mounts[@]} ${names[@]}") + + # Workaround to prevent overwriting suggestions, it adds empty + # suggestion, otherwise names with colons will be corrupted + COMPREPLY+=(" ") + + return 0 + fi + + # Workaround to complete names with colons, it removes colon prefix from + # COMPREPLY + __ltrim_colon_completions "$cur" +} + +__gio() { + # Complete subcommands + if (( ${COMP_CWORD} == 1 )); then + COMPREPLY=($(compgen -W "help version cat copy info list mime mkdir monitor mount move open rename remove save set trash tree" -- "${COMP_WORDS[1]}")) + compopt +o nospace + return 0 + fi + + # Complete file locations + __gio_location +} + +#################################################################################################### + +complete -o nospace -F __gio gio
diff --git a/gio/completion/gresource b/gio/completion/gresource new file mode 100644 index 0000000..ef1145d --- /dev/null +++ b/gio/completion/gresource
@@ -0,0 +1,58 @@ + +# Check for bash +[ -z "$BASH_VERSION" ] && return + +#################################################################################################### + +__gresource() { + local choices coffset section + + if [ ${COMP_CWORD} -gt 2 ]; then + if [ ${COMP_WORDS[1]} = --section ]; then + section=${COMP_WORDS[2]} + coffset=2 + else + coffset=0 + fi + else + coffset=0 + fi + + case "$((${COMP_CWORD}-$coffset))" in + 1) + choices=$'--section \nhelp \nsections \nlist \ndetails \nextract ' + ;; + + 2) + case "${COMP_WORDS[$(($coffset+1))]}" in + --section) + return 0 + ;; + + help) + choices=$'sections\nlist\ndetails\nextract' + ;; + + sections|list|details|extract) + COMPREPLY=($(compgen -f -- ${COMP_WORDS[${COMP_CWORD}]})) + return 0 + ;; + esac + ;; + + 3) + case "${COMP_WORDS[$(($coffset+1))]}" in + list|details|extract) + choices="$(gresource list ${COMP_WORDS[$(($coffset+2))]} 2> /dev/null | sed -e 's.$. .')" + ;; + esac + ;; + esac + + local IFS=$'\n' + COMPREPLY=($(compgen -W "${choices}" -- "${COMP_WORDS[${COMP_CWORD}]}")) +} + +#################################################################################################### + +complete -o nospace -F __gresource gresource
diff --git a/gio/completion/gsettings b/gio/completion/gsettings new file mode 100644 index 0000000..d509758 --- /dev/null +++ b/gio/completion/gsettings
@@ -0,0 +1,88 @@ + +# Check for bash +[ -z "$BASH_VERSION" ] && return + +#################################################################################################### + +__gsettings() { + local choices coffset schemadir + + if [ ${COMP_CWORD} -gt 2 ]; then + if [ ${COMP_WORDS[1]} = --schemadir ]; then + # this complexity is needed to perform correct tilde expansion + schemadir=$(eval "echo --schemadir ${COMP_WORDS[2]}") + coffset=2 + else + coffset=0 + fi + else + coffset=0 + fi + + case "$((${COMP_CWORD}-$coffset))" in + 1) + choices=$'--schemadir\n--version\nhelp \nlist-schemas\nlist-relocatable-schemas\nlist-keys \nlist-children \nlist-recursively \nget \nrange \nset \nreset \nreset-recursively \nwritable \nmonitor \ndescribe ' + ;; + + 2) + case "${COMP_WORDS[$(($coffset+1))]}" in + --schemadir) + COMPREPLY=($(compgen -o dirnames -- ${COMP_WORDS[${COMP_CWORD}]})) + return 0 + ;; + + help) + choices=$'list-schemas\nlist-relocatable-schemas\nlist-keys\nlist-children\nlist-recursively\nget\nrange\nset\nreset\nreset-recursively\nwritable\nmonitor' + ;; + list-keys|list-children|list-recursively|reset-recursively) + choices="$(gsettings $schemadir list-schemas 2> /dev/null)"$'\n'"$(gsettings $schemadir list-relocatable-schemas 2> /dev/null | sed -e 's.$.:/.')" + ;; + list-schemas) + COMPREPLY=($(compgen -W "--print-paths" -- ${COMP_WORDS[${COMP_CWORD}]})) + return 0 + ;; + + get|range|set|reset|writable|monitor|describe) + choices="$(gsettings $schemadir list-schemas 2> /dev/null | sed -e 's.$. .')"$'\n'"$(gsettings $schemadir list-relocatable-schemas 2> /dev/null | sed -e 's.$.:/.')" + ;; + esac + ;; + + 3) + case "${COMP_WORDS[$(($coffset+1))]}" in + set) + choices="$(gsettings $schemadir list-keys ${COMP_WORDS[$(($coffset+2))]} 2> /dev/null | sed -e 's.$. .')" + ;; + + get|range|reset|writable|monitor|describe) + choices="$(gsettings $schemadir list-keys ${COMP_WORDS[$(($coffset+2))]} 2> /dev/null)" + ;; + esac + ;; + + 4) + case "${COMP_WORDS[$(($coffset+2))]}" in + set) + range=($(gsettings $schemadir range ${COMP_WORDS[$(($coffset+2))]} ${COMP_WORDS[$(($coffset+3))]} 2> /dev/null)) + case "${range[0]}" in + enum) + unset range[0] + ;; + *) + unset range + ;; + esac + local IFS=$'\n' + choices="${range[*]}" + ;; + esac + ;; + esac + + local IFS=$'\n' + COMPREPLY=($(compgen -W "${choices}" -- "${COMP_WORDS[${COMP_CWORD}]}")) +} + +#################################################################################################### + +complete -o nospace -F __gsettings gsettings
diff --git a/gio/data-to-c.py b/gio/data-to-c.py new file mode 100755 index 0000000..f226220 --- /dev/null +++ b/gio/data-to-c.py
@@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 4: + print('Usage: {0} <filename> <variable> <output>') + +with open(sys.argv[1], 'rb') as f: + in_data = f.read().decode('utf-8', 'backslashreplace') +b = [r'\x{:02x}'.format(ord(c)) for c in in_data] + +out_data = "const char {0}[] = \"".format(sys.argv[2]) +out_data += "".join(b) + "\";" + +with open(sys.argv[3], 'w') as f: + f.write(out_data)
diff --git a/gio/dbus-daemon.xml b/gio/dbus-daemon.xml new file mode 100644 index 0000000..515dd34 --- /dev/null +++ b/gio/dbus-daemon.xml
@@ -0,0 +1,76 @@ +<node> + <interface name="org.freedesktop.DBus"> + <method name="Hello"> + <arg direction="out" type="s" name="assigned_name"/> + </method> + <method name="RequestName"> + <arg direction="in" type="s" name="name"/> + <arg direction="in" type="u" name="flags"/> + <arg direction="out" type="u" name="value"/> + </method> + <method name="ReleaseName"> + <arg direction="in" type="s" name="name"/> + <arg direction="out" type="u" name="value"/> + </method> + <method name="StartServiceByName"> + <arg direction="in" type="s" name="name"/> + <arg direction="in" type="u" name="flags"/> + <arg direction="out" type="u" name="value"/> + </method> + <method name="NameHasOwner"> + <arg direction="in" type="s" name="name"/> + <arg direction="out" type="b" name="has_owner"/> + </method> + <method name="ListNames"> + <arg direction="out" type="as" name="names"/> + </method> + <method name="ListActivatableNames"> + <arg direction="out" type="as" name="activatable_names"/> + </method> + <method name="AddMatch"> + <arg direction="in" type="s" name="rule"/> + </method> + <method name="RemoveMatch"> + <arg direction="in" type="s" name="rule"/> + </method> + <method name="GetNameOwner"> + <arg direction="in" type="s" name="name"/> + <arg direction="out" type="s" name="unique_name"/> + </method> + <method name="ListQueuedOwners"> + <arg direction="in" type="s" name="name"/> + <arg direction="out" type="as" name="queued_owners"/> + </method> + <method name="GetConnectionUnixUser"> + <arg direction="in" type="s" name="name"/> + <arg direction="out" type="u" name="uid"/> + </method> + <method name="GetConnectionUnixProcessID"> + <arg direction="in" type="s" name="name"/> + <arg direction="out" type="u" name="pid"/> + </method> + <method name="GetConnectionSELinuxSecurityContext"> + <arg direction="in" type="s" name="name"/> + <arg direction="out" type="ay" name="security_context"/> + </method> + <method name="UpdateActivationEnvironment"> + <arg direction="in" type="a{ss}" name="environment"/> + </method> + <method name="ReloadConfig"> + </method> + <method name="GetId"> + <arg direction="out" type="s" name="unique_id"/> + </method> + <signal name="NameOwnerChanged"> + <arg type="s" name="name"/> + <arg type="s" name="old_owner"/> + <arg type="s" name="new_owner"/> + </signal> + <signal name="NameLost"> + <arg type="s" name="name"/> + </signal> + <signal name="NameAcquired"> + <arg type="s" name="name"/> + </signal> + </interface> +</node>
diff --git a/gio/fam/gfamfilemonitor.c b/gio/fam/gfamfilemonitor.c new file mode 100644 index 0000000..d9518a6 --- /dev/null +++ b/gio/fam/gfamfilemonitor.c
@@ -0,0 +1,235 @@ +/* + * Copyright © 2015 Canonical Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" + +#include <gio/glocalfilemonitor.h> +#include <gio/giomodule.h> +#include "glib-private.h" +#include <glib-unix.h> +#include <fam.h> + +static GMutex fam_lock; +static gboolean fam_initialised; +static FAMConnection fam_connection; +static GSource *fam_source; + +#define G_TYPE_FAM_FILE_MONITOR (g_fam_file_monitor_get_type ()) +#define G_FAM_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_FAM_FILE_MONITOR, GFamFileMonitor)) + +typedef GLocalFileMonitorClass GFamFileMonitorClass; + +typedef struct +{ + GLocalFileMonitor parent_instance; + + FAMRequest request; +} GFamFileMonitor; + +static GType g_fam_file_monitor_get_type (void); +G_DEFINE_DYNAMIC_TYPE (GFamFileMonitor, g_fam_file_monitor, G_TYPE_LOCAL_FILE_MONITOR) + +static gboolean +g_fam_file_monitor_callback (gint fd, + GIOCondition condition, + gpointer user_data) +{ + gint64 now = g_source_get_time (fam_source); + + g_mutex_lock (&fam_lock); + + while (FAMPending (&fam_connection)) + { + const gchar *child; + FAMEvent ev; + + if (FAMNextEvent (&fam_connection, &ev) != 1) + { + /* The daemon died. We're in a really bad situation now + * because we potentially have a bunch of request structures + * outstanding which no longer make any sense to anyone. + * + * The best thing that we can do is do nothing. Notification + * won't work anymore for this process. + */ + g_mutex_unlock (&fam_lock); + + g_warning ("Lost connection to FAM (file monitoring) service. Expect no further file monitor events."); + + return FALSE; + } + + /* We expect ev.filename to be a relative path for children in a + * monitored directory, and an absolute path for a monitored file + * or the directory itself. + */ + if (ev.filename[0] != '/') + child = ev.filename; + else + child = NULL; + + switch (ev.code) + { + case FAMAcknowledge: + g_source_unref (ev.userdata); + break; + + case FAMChanged: + g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CHANGED, child, NULL, NULL, now); + break; + + case FAMDeleted: + g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_DELETED, child, NULL, NULL, now); + break; + + case FAMCreated: + g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CREATED, child, NULL, NULL, now); + break; + + default: + /* unknown type */ + break; + } + } + + g_mutex_unlock (&fam_lock); + + return TRUE; +} + +static gboolean +g_fam_file_monitor_is_supported (void) +{ + g_mutex_lock (&fam_lock); + + if (!fam_initialised) + { + fam_initialised = FAMOpen2 (&fam_connection, "GLib GIO") == 0; + + if (fam_initialised) + { +#ifdef HAVE_FAM_NO_EXISTS + /* This is a gamin extension that avoids sending all the + * Exists event for dir monitors + */ + FAMNoExists (&fam_connection); +#endif + + fam_source = g_unix_fd_source_new (FAMCONNECTION_GETFD (&fam_connection), G_IO_IN); + g_source_set_callback (fam_source, (GSourceFunc) g_fam_file_monitor_callback, NULL, NULL); + g_source_attach (fam_source, GLIB_PRIVATE_CALL(g_get_worker_context) ()); + } + } + + g_mutex_unlock (&fam_lock); + + return fam_initialised; +} + +static gboolean +g_fam_file_monitor_cancel (GFileMonitor *monitor) +{ + GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (monitor); + + g_mutex_lock (&fam_lock); + + g_assert (fam_initialised); + + FAMCancelMonitor (&fam_connection, &gffm->request); + + g_mutex_unlock (&fam_lock); + + return TRUE; +} + +static void +g_fam_file_monitor_start (GLocalFileMonitor *local_monitor, + const gchar *dirname, + const gchar *basename, + const gchar *filename, + GFileMonitorSource *source) +{ + GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (local_monitor); + + g_mutex_lock (&fam_lock); + + g_assert (fam_initialised); + + g_source_ref ((GSource *) source); + + if (dirname) + FAMMonitorDirectory (&fam_connection, dirname, &gffm->request, source); + else + FAMMonitorFile (&fam_connection, filename, &gffm->request, source); + + g_mutex_unlock (&fam_lock); +} + +static void +g_fam_file_monitor_init (GFamFileMonitor* monitor) +{ +} + +static void +g_fam_file_monitor_class_init (GFamFileMonitorClass *class) +{ + GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (class); + + class->is_supported = g_fam_file_monitor_is_supported; + class->start = g_fam_file_monitor_start; + file_monitor_class->cancel = g_fam_file_monitor_cancel; +} + +static void +g_fam_file_monitor_class_finalize (GFamFileMonitorClass *class) +{ +} + +void +g_io_module_load (GIOModule *module) +{ + g_type_module_use (G_TYPE_MODULE (module)); + + g_fam_file_monitor_register_type (G_TYPE_MODULE (module)); + + g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, + G_TYPE_FAM_FILE_MONITOR, "fam", 10); + + g_io_extension_point_implement (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME, + G_TYPE_FAM_FILE_MONITOR, "fam", 10); +} + +void +g_io_module_unload (GIOModule *module) +{ + g_assert_not_reached (); +} + +char ** +g_io_module_query (void) +{ + char *eps[] = { + G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, + G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME, + NULL + }; + + return g_strdupv (eps); +}
diff --git a/gio/fam/gfamfilemonitor.map b/gio/fam/gfamfilemonitor.map new file mode 100644 index 0000000..43ed5a7 --- /dev/null +++ b/gio/fam/gfamfilemonitor.map
@@ -0,0 +1,8 @@ +{ +global: + g_io_module_load; + g_io_module_unload; + g_io_module_query; +local: + *; +};
diff --git a/gio/fam/meson.build b/gio/fam/meson.build new file mode 100644 index 0000000..8019fe5 --- /dev/null +++ b/gio/fam/meson.build
@@ -0,0 +1,36 @@ +if not get_option('fam') + subdir_done() +endif + +fam_dep = cc.find_library('fam') +fam_c_args = gio_c_args +if cc.has_function('FAMNoExists', dependencies : fam_dep) + fam_c_args += '-DHAVE_FAM_NO_EXISTS=1' +endif + +deps = [ + fam_dep, + libglib_dep, + libgobject_dep, + libgio_dep, +] + +symbol_map = join_paths(meson.current_source_dir(), 'gfamfilemonitor.map') +fam_ldflags = cc.get_supported_link_arguments([ + '-Wl,--version-script,' + symbol_map, + '-Wl,-no-undefined', +]) + +module = shared_module('giofam', 'gfamfilemonitor.c', + include_directories : [gmoduleinc], + dependencies : deps, + c_args : fam_c_args, + link_args : fam_ldflags, + link_depends : symbol_map, + install_dir : glib_giomodulesdir, + install : true, +) + +if not meson.is_cross_build() + meson.add_install_script('../gio-querymodules-wrapper.py', gio_querymodules.full_path(), glib_giomodulesdir) +endif
diff --git a/gio/gaction.c b/gio/gaction.c new file mode 100644 index 0000000..c3748a9 --- /dev/null +++ b/gio/gaction.c
@@ -0,0 +1,587 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" +#include "gaction.h" +#include "glibintl.h" + +#include <string.h> + +G_DEFINE_INTERFACE (GAction, g_action, G_TYPE_OBJECT) + +/** + * SECTION:gaction + * @title: GAction + * @short_description: An action interface + * @include: gio/gio.h + * + * #GAction represents a single named action. + * + * The main interface to an action is that it can be activated with + * g_action_activate(). This results in the 'activate' signal being + * emitted. An activation has a #GVariant parameter (which may be + * %NULL). The correct type for the parameter is determined by a static + * parameter type (which is given at construction time). + * + * An action may optionally have a state, in which case the state may be + * set with g_action_change_state(). This call takes a #GVariant. The + * correct type for the state is determined by a static state type + * (which is given at construction time). + * + * The state may have a hint associated with it, specifying its valid + * range. + * + * #GAction is merely the interface to the concept of an action, as + * described above. Various implementations of actions exist, including + * #GSimpleAction. + * + * In all cases, the implementing class is responsible for storing the + * name of the action, the parameter type, the enabled state, the + * optional state type and the state and emitting the appropriate + * signals when these change. The implementor is responsible for filtering + * calls to g_action_activate() and g_action_change_state() for type + * safety and for the state being enabled. + * + * Probably the only useful thing to do with a #GAction is to put it + * inside of a #GSimpleActionGroup. + **/ + +/** + * GAction: + * + * #GAction is an opaque data structure and can only be accessed + * using the following functions. + **/ + +/** + * GActionInterface: + * @get_name: the virtual function pointer for g_action_get_name() + * @get_parameter_type: the virtual function pointer for g_action_get_parameter_type() + * @get_state_type: the virtual function pointer for g_action_get_state_type() + * @get_state_hint: the virtual function pointer for g_action_get_state_hint() + * @get_enabled: the virtual function pointer for g_action_get_enabled() + * @get_state: the virtual function pointer for g_action_get_state() + * @change_state: the virtual function pointer for g_action_change_state() + * @activate: the virtual function pointer for g_action_activate(). Note that #GAction does not have an + * 'activate' signal but that implementations of it may have one. + * + * The virtual function table for #GAction. + * + * Since: 2.28 + */ + +void +g_action_default_init (GActionInterface *iface) +{ + /** + * GAction:name: + * + * The name of the action. This is mostly meaningful for identifying + * the action once it has been added to a #GActionGroup. It is immutable. + * + * Since: 2.28 + **/ + g_object_interface_install_property (iface, + g_param_spec_string ("name", + P_("Action Name"), + P_("The name used to invoke the action"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GAction:parameter-type: + * + * The type of the parameter that must be given when activating the + * action. This is immutable, and may be %NULL if no parameter is needed when + * activating the action. + * + * Since: 2.28 + **/ + g_object_interface_install_property (iface, + g_param_spec_boxed ("parameter-type", + P_("Parameter Type"), + P_("The type of GVariant passed to activate()"), + G_TYPE_VARIANT_TYPE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GAction:enabled: + * + * If @action is currently enabled. + * + * If the action is disabled then calls to g_action_activate() and + * g_action_change_state() have no effect. + * + * Since: 2.28 + **/ + g_object_interface_install_property (iface, + g_param_spec_boolean ("enabled", + P_("Enabled"), + P_("If the action can be activated"), + TRUE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GAction:state-type: + * + * The #GVariantType of the state that the action has, or %NULL if the + * action is stateless. This is immutable. + * + * Since: 2.28 + **/ + g_object_interface_install_property (iface, + g_param_spec_boxed ("state-type", + P_("State Type"), + P_("The type of the state kept by the action"), + G_TYPE_VARIANT_TYPE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GAction:state: + * + * The state of the action, or %NULL if the action is stateless. + * + * Since: 2.28 + **/ + g_object_interface_install_property (iface, + g_param_spec_variant ("state", + P_("State"), + P_("The state the action is in"), + G_VARIANT_TYPE_ANY, + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +/** + * g_action_change_state: + * @action: a #GAction + * @value: the new state + * + * Request for the state of @action to be changed to @value. + * + * The action must be stateful and @value must be of the correct type. + * See g_action_get_state_type(). + * + * This call merely requests a change. The action may refuse to change + * its state or may change its state to something other than @value. + * See g_action_get_state_hint(). + * + * If the @value GVariant is floating, it is consumed. + * + * Since: 2.30 + **/ +void +g_action_change_state (GAction *action, + GVariant *value) +{ + const GVariantType *state_type; + + g_return_if_fail (G_IS_ACTION (action)); + g_return_if_fail (value != NULL); + state_type = g_action_get_state_type (action); + g_return_if_fail (state_type != NULL); + g_return_if_fail (g_variant_is_of_type (value, state_type)); + + g_variant_ref_sink (value); + + G_ACTION_GET_IFACE (action) + ->change_state (action, value); + + g_variant_unref (value); +} + +/** + * g_action_get_state: + * @action: a #GAction + * + * Queries the current state of @action. + * + * If the action is not stateful then %NULL will be returned. If the + * action is stateful then the type of the return value is the type + * given by g_action_get_state_type(). + * + * The return value (if non-%NULL) should be freed with + * g_variant_unref() when it is no longer required. + * + * Returns: (transfer full): the current state of the action + * + * Since: 2.28 + **/ +GVariant * +g_action_get_state (GAction *action) +{ + g_return_val_if_fail (G_IS_ACTION (action), NULL); + + return G_ACTION_GET_IFACE (action) + ->get_state (action); +} + +/** + * g_action_get_name: + * @action: a #GAction + * + * Queries the name of @action. + * + * Returns: the name of the action + * + * Since: 2.28 + **/ +const gchar * +g_action_get_name (GAction *action) +{ + g_return_val_if_fail (G_IS_ACTION (action), NULL); + + return G_ACTION_GET_IFACE (action) + ->get_name (action); +} + +/** + * g_action_get_parameter_type: + * @action: a #GAction + * + * Queries the type of the parameter that must be given when activating + * @action. + * + * When activating the action using g_action_activate(), the #GVariant + * given to that function must be of the type returned by this function. + * + * In the case that this function returns %NULL, you must not give any + * #GVariant, but %NULL instead. + * + * Returns: (nullable): the parameter type + * + * Since: 2.28 + **/ +const GVariantType * +g_action_get_parameter_type (GAction *action) +{ + g_return_val_if_fail (G_IS_ACTION (action), NULL); + + return G_ACTION_GET_IFACE (action) + ->get_parameter_type (action); +} + +/** + * g_action_get_state_type: + * @action: a #GAction + * + * Queries the type of the state of @action. + * + * If the action is stateful (e.g. created with + * g_simple_action_new_stateful()) then this function returns the + * #GVariantType of the state. This is the type of the initial value + * given as the state. All calls to g_action_change_state() must give a + * #GVariant of this type and g_action_get_state() will return a + * #GVariant of the same type. + * + * If the action is not stateful (e.g. created with g_simple_action_new()) + * then this function will return %NULL. In that case, g_action_get_state() + * will return %NULL and you must not call g_action_change_state(). + * + * Returns: (nullable): the state type, if the action is stateful + * + * Since: 2.28 + **/ +const GVariantType * +g_action_get_state_type (GAction *action) +{ + g_return_val_if_fail (G_IS_ACTION (action), NULL); + + return G_ACTION_GET_IFACE (action) + ->get_state_type (action); +} + +/** + * g_action_get_state_hint: + * @action: a #GAction + * + * Requests a hint about the valid range of values for the state of + * @action. + * + * If %NULL is returned it either means that the action is not stateful + * or that there is no hint about the valid range of values for the + * state of the action. + * + * If a #GVariant array is returned then each item in the array is a + * possible value for the state. If a #GVariant pair (ie: two-tuple) is + * returned then the tuple specifies the inclusive lower and upper bound + * of valid values for the state. + * + * In any case, the information is merely a hint. It may be possible to + * have a state value outside of the hinted range and setting a value + * within the range may fail. + * + * The return value (if non-%NULL) should be freed with + * g_variant_unref() when it is no longer required. + * + * Returns: (nullable) (transfer full): the state range hint + * + * Since: 2.28 + **/ +GVariant * +g_action_get_state_hint (GAction *action) +{ + g_return_val_if_fail (G_IS_ACTION (action), NULL); + + return G_ACTION_GET_IFACE (action) + ->get_state_hint (action); +} + +/** + * g_action_get_enabled: + * @action: a #GAction + * + * Checks if @action is currently enabled. + * + * An action must be enabled in order to be activated or in order to + * have its state changed from outside callers. + * + * Returns: whether the action is enabled + * + * Since: 2.28 + **/ +gboolean +g_action_get_enabled (GAction *action) +{ + g_return_val_if_fail (G_IS_ACTION (action), FALSE); + + return G_ACTION_GET_IFACE (action) + ->get_enabled (action); +} + +/** + * g_action_activate: + * @action: a #GAction + * @parameter: (nullable): the parameter to the activation + * + * Activates the action. + * + * @parameter must be the correct type of parameter for the action (ie: + * the parameter type given at construction time). If the parameter + * type was %NULL then @parameter must also be %NULL. + * + * If the @parameter GVariant is floating, it is consumed. + * + * Since: 2.28 + **/ +void +g_action_activate (GAction *action, + GVariant *parameter) +{ + g_return_if_fail (G_IS_ACTION (action)); + + if (parameter != NULL) + g_variant_ref_sink (parameter); + + G_ACTION_GET_IFACE (action) + ->activate (action, parameter); + + if (parameter != NULL) + g_variant_unref (parameter); +} + +/** + * g_action_name_is_valid: + * @action_name: a potential action name + * + * Checks if @action_name is valid. + * + * @action_name is valid if it consists only of alphanumeric characters, + * plus '-' and '.'. The empty string is not a valid action name. + * + * It is an error to call this function with a non-utf8 @action_name. + * @action_name must not be %NULL. + * + * Returns: %TRUE if @action_name is valid + * + * Since: 2.38 + **/ +gboolean +g_action_name_is_valid (const gchar *action_name) +{ + gchar c; + gint i; + + g_return_val_if_fail (action_name != NULL, FALSE); + + for (i = 0; (c = action_name[i]); i++) + if (!g_ascii_isalnum (c) && c != '.' && c != '-') + return FALSE; + + return i > 0; +} + +/** + * g_action_parse_detailed_name: + * @detailed_name: a detailed action name + * @action_name: (out): the action name + * @target_value: (out): the target value, or %NULL for no target + * @error: a pointer to a %NULL #GError, or %NULL + * + * Parses a detailed action name into its separate name and target + * components. + * + * Detailed action names can have three formats. + * + * The first format is used to represent an action name with no target + * value and consists of just an action name containing no whitespace + * nor the characters ':', '(' or ')'. For example: "app.action". + * + * The second format is used to represent an action with a target value + * that is a non-empty string consisting only of alphanumerics, plus '-' + * and '.'. In that case, the action name and target value are + * separated by a double colon ("::"). For example: + * "app.action::target". + * + * The third format is used to represent an action with any type of + * target value, including strings. The target value follows the action + * name, surrounded in parens. For example: "app.action(42)". The + * target value is parsed using g_variant_parse(). If a tuple-typed + * value is desired, it must be specified in the same way, resulting in + * two sets of parens, for example: "app.action((1,2,3))". A string + * target can be specified this way as well: "app.action('target')". + * For strings, this third format must be used if * target value is + * empty or contains characters other than alphanumerics, '-' and '.'. + * + * Returns: %TRUE if successful, else %FALSE with @error set + * + * Since: 2.38 + **/ +gboolean +g_action_parse_detailed_name (const gchar *detailed_name, + gchar **action_name, + GVariant **target_value, + GError **error) +{ + const gchar *target; + gsize target_len; + gsize base_len; + + /* For historical (compatibility) reasons, this function accepts some + * cases of invalid action names as long as they don't interfere with + * the separation of the action from the target value. + * + * We decide which format we have based on which we see first between + * '::' '(' and '\0'. + */ + + if (*detailed_name == '\0' || *detailed_name == ' ') + goto bad_fmt; + + base_len = strcspn (detailed_name, ": ()"); + target = detailed_name + base_len; + target_len = strlen (target); + + switch (target[0]) + { + case ' ': + case ')': + goto bad_fmt; + + case ':': + if (target[1] != ':') + goto bad_fmt; + + *target_value = g_variant_ref_sink (g_variant_new_string (target + 2)); + break; + + case '(': + { + if (target[target_len - 1] != ')') + goto bad_fmt; + + *target_value = g_variant_parse (NULL, target + 1, target + target_len - 1, NULL, error); + if (*target_value == NULL) + goto bad_fmt; + } + break; + + case '\0': + *target_value = NULL; + break; + } + + *action_name = g_strndup (detailed_name, base_len); + + return TRUE; + +bad_fmt: + if (error) + { + if (*error == NULL) + g_set_error (error, G_VARIANT_PARSE_ERROR, G_VARIANT_PARSE_ERROR_FAILED, + "Detailed action name '%s' has invalid format", detailed_name); + else + g_prefix_error (error, "Detailed action name '%s' has invalid format: ", detailed_name); + } + + return FALSE; +} + +/** + * g_action_print_detailed_name: + * @action_name: a valid action name + * @target_value: (nullable): a #GVariant target value, or %NULL + * + * Formats a detailed action name from @action_name and @target_value. + * + * It is an error to call this function with an invalid action name. + * + * This function is the opposite of g_action_parse_detailed_name(). + * It will produce a string that can be parsed back to the @action_name + * and @target_value by that function. + * + * See that function for the types of strings that will be printed by + * this function. + * + * Returns: a detailed format string + * + * Since: 2.38 + **/ +gchar * +g_action_print_detailed_name (const gchar *action_name, + GVariant *target_value) +{ + g_return_val_if_fail (g_action_name_is_valid (action_name), NULL); + + if (target_value == NULL) + return g_strdup (action_name); + + if (g_variant_is_of_type (target_value, G_VARIANT_TYPE_STRING)) + { + const gchar *str = g_variant_get_string (target_value, NULL); + + if (g_action_name_is_valid (str)) + return g_strconcat (action_name, "::", str, NULL); + } + + { + GString *result = g_string_new (action_name); + g_string_append_c (result, '('); + g_variant_print_string (target_value, result, TRUE); + g_string_append_c (result, ')'); + + return g_string_free (result, FALSE); + } +}
diff --git a/gio/gaction.h b/gio/gaction.h new file mode 100644 index 0000000..f9f4b38 --- /dev/null +++ b/gio/gaction.h
@@ -0,0 +1,98 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_ACTION_H__ +#define __G_ACTION_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_ACTION (g_action_get_type ()) +#define G_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_ACTION, GAction)) +#define G_IS_ACTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_ACTION)) +#define G_ACTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \ + G_TYPE_ACTION, GActionInterface)) + +typedef struct _GActionInterface GActionInterface; + +struct _GActionInterface +{ + GTypeInterface g_iface; + + /* virtual functions */ + const gchar * (* get_name) (GAction *action); + const GVariantType * (* get_parameter_type) (GAction *action); + const GVariantType * (* get_state_type) (GAction *action); + GVariant * (* get_state_hint) (GAction *action); + + gboolean (* get_enabled) (GAction *action); + GVariant * (* get_state) (GAction *action); + + void (* change_state) (GAction *action, + GVariant *value); + void (* activate) (GAction *action, + GVariant *parameter); +}; + +GLIB_AVAILABLE_IN_2_30 +GType g_action_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +const gchar * g_action_get_name (GAction *action); +GLIB_AVAILABLE_IN_ALL +const GVariantType * g_action_get_parameter_type (GAction *action); +GLIB_AVAILABLE_IN_ALL +const GVariantType * g_action_get_state_type (GAction *action); +GLIB_AVAILABLE_IN_ALL +GVariant * g_action_get_state_hint (GAction *action); + +GLIB_AVAILABLE_IN_ALL +gboolean g_action_get_enabled (GAction *action); +GLIB_AVAILABLE_IN_ALL +GVariant * g_action_get_state (GAction *action); + +GLIB_AVAILABLE_IN_ALL +void g_action_change_state (GAction *action, + GVariant *value); +GLIB_AVAILABLE_IN_ALL +void g_action_activate (GAction *action, + GVariant *parameter); + +GLIB_AVAILABLE_IN_2_28 +gboolean g_action_name_is_valid (const gchar *action_name); + +GLIB_AVAILABLE_IN_2_38 +gboolean g_action_parse_detailed_name (const gchar *detailed_name, + gchar **action_name, + GVariant **target_value, + GError **error); + +GLIB_AVAILABLE_IN_2_38 +gchar * g_action_print_detailed_name (const gchar *action_name, + GVariant *target_value); + +G_END_DECLS + +#endif /* __G_ACTION_H__ */
diff --git a/gio/gactiongroup.c b/gio/gactiongroup.c new file mode 100644 index 0000000..24da353 --- /dev/null +++ b/gio/gactiongroup.c
@@ -0,0 +1,763 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" +#include "gactiongroup.h" +#include "gaction.h" +#include "glibintl.h" +#include "gmarshal-internal.h" + +/** + * SECTION:gactiongroup + * @title: GActionGroup + * @short_description: A group of actions + * @include: gio/gio.h + * @see_also: #GAction + * + * #GActionGroup represents a group of actions. Actions can be used to + * expose functionality in a structured way, either from one part of a + * program to another, or to the outside world. Action groups are often + * used together with a #GMenuModel that provides additional + * representation data for displaying the actions to the user, e.g. in + * a menu. + * + * The main way to interact with the actions in a GActionGroup is to + * activate them with g_action_group_activate_action(). Activating an + * action may require a #GVariant parameter. The required type of the + * parameter can be inquired with g_action_group_get_action_parameter_type(). + * Actions may be disabled, see g_action_group_get_action_enabled(). + * Activating a disabled action has no effect. + * + * Actions may optionally have a state in the form of a #GVariant. The + * current state of an action can be inquired with + * g_action_group_get_action_state(). Activating a stateful action may + * change its state, but it is also possible to set the state by calling + * g_action_group_change_action_state(). + * + * As typical example, consider a text editing application which has an + * option to change the current font to 'bold'. A good way to represent + * this would be a stateful action, with a boolean state. Activating the + * action would toggle the state. + * + * Each action in the group has a unique name (which is a string). All + * method calls, except g_action_group_list_actions() take the name of + * an action as an argument. + * + * The #GActionGroup API is meant to be the 'public' API to the action + * group. The calls here are exactly the interaction that 'external + * forces' (eg: UI, incoming D-Bus messages, etc.) are supposed to have + * with actions. 'Internal' APIs (ie: ones meant only to be accessed by + * the action group implementation) are found on subclasses. This is + * why you will find - for example - g_action_group_get_action_enabled() + * but not an equivalent set() call. + * + * Signals are emitted on the action group in response to state changes + * on individual actions. + * + * Implementations of #GActionGroup should provide implementations for + * the virtual functions g_action_group_list_actions() and + * g_action_group_query_action(). The other virtual functions should + * not be implemented - their "wrappers" are actually implemented with + * calls to g_action_group_query_action(). + */ + +/** + * GActionGroup: + * + * #GActionGroup is an opaque data structure and can only be accessed + * using the following functions. + **/ + +/** + * GActionGroupInterface: + * @has_action: the virtual function pointer for g_action_group_has_action() + * @list_actions: the virtual function pointer for g_action_group_list_actions() + * @get_action_parameter_type: the virtual function pointer for g_action_group_get_action_parameter_type() + * @get_action_state_type: the virtual function pointer for g_action_group_get_action_state_type() + * @get_action_state_hint: the virtual function pointer for g_action_group_get_action_state_hint() + * @get_action_enabled: the virtual function pointer for g_action_group_get_action_enabled() + * @get_action_state: the virtual function pointer for g_action_group_get_action_state() + * @change_action_state: the virtual function pointer for g_action_group_change_action_state() + * @query_action: the virtual function pointer for g_action_group_query_action() + * @activate_action: the virtual function pointer for g_action_group_activate_action() + * @change_action_state: the virtual function pointer for g_action_group_change_action_state() + * @action_added: the class closure for the #GActionGroup::action-added signal + * @action_removed: the class closure for the #GActionGroup::action-removed signal + * @action_enabled_changed: the class closure for the #GActionGroup::action-enabled-changed signal + * @action_state_changed: the class closure for the #GActionGroup::action-enabled-changed signal + * + * The virtual function table for #GActionGroup. + * + * Since: 2.28 + **/ + +G_DEFINE_INTERFACE (GActionGroup, g_action_group, G_TYPE_OBJECT) + +enum +{ + SIGNAL_ACTION_ADDED, + SIGNAL_ACTION_REMOVED, + SIGNAL_ACTION_ENABLED_CHANGED, + SIGNAL_ACTION_STATE_CHANGED, + NR_SIGNALS +}; + +static guint g_action_group_signals[NR_SIGNALS]; + +static gboolean +g_action_group_real_has_action (GActionGroup *action_group, + const gchar *action_name) +{ + return g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, NULL); +} + +static gboolean +g_action_group_real_get_action_enabled (GActionGroup *action_group, + const gchar *action_name) +{ + gboolean enabled = FALSE; + + g_action_group_query_action (action_group, action_name, &enabled, NULL, NULL, NULL, NULL); + + return enabled; +} + +static const GVariantType * +g_action_group_real_get_action_parameter_type (GActionGroup *action_group, + const gchar *action_name) +{ + const GVariantType *type = NULL; + + g_action_group_query_action (action_group, action_name, NULL, &type, NULL, NULL, NULL); + + return type; +} + +static const GVariantType * +g_action_group_real_get_action_state_type (GActionGroup *action_group, + const gchar *action_name) +{ + const GVariantType *type = NULL; + + g_action_group_query_action (action_group, action_name, NULL, NULL, &type, NULL, NULL); + + return type; +} + +static GVariant * +g_action_group_real_get_action_state_hint (GActionGroup *action_group, + const gchar *action_name) +{ + GVariant *hint = NULL; + + g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, &hint, NULL); + + return hint; +} + +static GVariant * +g_action_group_real_get_action_state (GActionGroup *action_group, + const gchar *action_name) +{ + GVariant *state = NULL; + + g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, &state); + + return state; +} + +static gboolean +g_action_group_real_query_action (GActionGroup *action_group, + const gchar *action_name, + gboolean *enabled, + const GVariantType **parameter_type, + const GVariantType **state_type, + GVariant **state_hint, + GVariant **state) +{ + GActionGroupInterface *iface = G_ACTION_GROUP_GET_IFACE (action_group); + + /* we expect implementations to override this method, but we also + * allow for implementations that existed before this method was + * introduced to override the individual accessors instead. + * + * detect the case that neither has happened and report it. + */ + if G_UNLIKELY (iface->has_action == g_action_group_real_has_action || + iface->get_action_enabled == g_action_group_real_get_action_enabled || + iface->get_action_parameter_type == g_action_group_real_get_action_parameter_type || + iface->get_action_state_type == g_action_group_real_get_action_state_type || + iface->get_action_state_hint == g_action_group_real_get_action_state_hint || + iface->get_action_state == g_action_group_real_get_action_state) + { + g_critical ("Class '%s' implements GActionGroup interface without overriding " + "query_action() method -- bailing out to avoid infinite recursion.", + G_OBJECT_TYPE_NAME (action_group)); + return FALSE; + } + + if (!(* iface->has_action) (action_group, action_name)) + return FALSE; + + if (enabled != NULL) + *enabled = (* iface->get_action_enabled) (action_group, action_name); + + if (parameter_type != NULL) + *parameter_type = (* iface->get_action_parameter_type) (action_group, action_name); + + if (state_type != NULL) + *state_type = (* iface->get_action_state_type) (action_group, action_name); + + if (state_hint != NULL) + *state_hint = (* iface->get_action_state_hint) (action_group, action_name); + + if (state != NULL) + *state = (* iface->get_action_state) (action_group, action_name); + + return TRUE; +} + +static void +g_action_group_default_init (GActionGroupInterface *iface) +{ + iface->has_action = g_action_group_real_has_action; + iface->get_action_enabled = g_action_group_real_get_action_enabled; + iface->get_action_parameter_type = g_action_group_real_get_action_parameter_type; + iface->get_action_state_type = g_action_group_real_get_action_state_type; + iface->get_action_state_hint = g_action_group_real_get_action_state_hint; + iface->get_action_state = g_action_group_real_get_action_state; + iface->query_action = g_action_group_real_query_action; + + /** + * GActionGroup::action-added: + * @action_group: the #GActionGroup that changed + * @action_name: the name of the action in @action_group + * + * Signals that a new action was just added to the group. + * This signal is emitted after the action has been added + * and is now visible. + * + * Since: 2.28 + **/ + g_action_group_signals[SIGNAL_ACTION_ADDED] = + g_signal_new (I_("action-added"), + G_TYPE_ACTION_GROUP, + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (GActionGroupInterface, action_added), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + /** + * GActionGroup::action-removed: + * @action_group: the #GActionGroup that changed + * @action_name: the name of the action in @action_group + * + * Signals that an action is just about to be removed from the group. + * This signal is emitted before the action is removed, so the action + * is still visible and can be queried from the signal handler. + * + * Since: 2.28 + **/ + g_action_group_signals[SIGNAL_ACTION_REMOVED] = + g_signal_new (I_("action-removed"), + G_TYPE_ACTION_GROUP, + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (GActionGroupInterface, action_removed), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + + /** + * GActionGroup::action-enabled-changed: + * @action_group: the #GActionGroup that changed + * @action_name: the name of the action in @action_group + * @enabled: whether the action is enabled or not + * + * Signals that the enabled status of the named action has changed. + * + * Since: 2.28 + **/ + g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED] = + g_signal_new (I_("action-enabled-changed"), + G_TYPE_ACTION_GROUP, + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (GActionGroupInterface, + action_enabled_changed), + NULL, NULL, + _g_cclosure_marshal_VOID__STRING_BOOLEAN, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_BOOLEAN); + g_signal_set_va_marshaller (g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED], + G_TYPE_FROM_INTERFACE (iface), + _g_cclosure_marshal_VOID__STRING_BOOLEANv); + + /** + * GActionGroup::action-state-changed: + * @action_group: the #GActionGroup that changed + * @action_name: the name of the action in @action_group + * @value: the new value of the state + * + * Signals that the state of the named action has changed. + * + * Since: 2.28 + **/ + g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED] = + g_signal_new (I_("action-state-changed"), + G_TYPE_ACTION_GROUP, + G_SIGNAL_RUN_LAST | + G_SIGNAL_DETAILED | + G_SIGNAL_MUST_COLLECT, + G_STRUCT_OFFSET (GActionGroupInterface, + action_state_changed), + NULL, NULL, + _g_cclosure_marshal_VOID__STRING_VARIANT, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_VARIANT); + g_signal_set_va_marshaller (g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED], + G_TYPE_FROM_INTERFACE (iface), + _g_cclosure_marshal_VOID__STRING_VARIANTv); +} + +/** + * g_action_group_list_actions: + * @action_group: a #GActionGroup + * + * Lists the actions contained within @action_group. + * + * The caller is responsible for freeing the list with g_strfreev() when + * it is no longer required. + * + * Returns: (transfer full): a %NULL-terminated array of the names of the + * actions in the group + * + * Since: 2.28 + **/ +gchar ** +g_action_group_list_actions (GActionGroup *action_group) +{ + g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL); + + return G_ACTION_GROUP_GET_IFACE (action_group) + ->list_actions (action_group); +} + +/** + * g_action_group_has_action: + * @action_group: a #GActionGroup + * @action_name: the name of the action to check for + * + * Checks if the named action exists within @action_group. + * + * Returns: whether the named action exists + * + * Since: 2.28 + **/ +gboolean +g_action_group_has_action (GActionGroup *action_group, + const gchar *action_name) +{ + g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE); + + return G_ACTION_GROUP_GET_IFACE (action_group) + ->has_action (action_group, action_name); +} + +/** + * g_action_group_get_action_parameter_type: + * @action_group: a #GActionGroup + * @action_name: the name of the action to query + * + * Queries the type of the parameter that must be given when activating + * the named action within @action_group. + * + * When activating the action using g_action_group_activate_action(), + * the #GVariant given to that function must be of the type returned + * by this function. + * + * In the case that this function returns %NULL, you must not give any + * #GVariant, but %NULL instead. + * + * The parameter type of a particular action will never change but it is + * possible for an action to be removed and for a new action to be added + * with the same name but a different parameter type. + * + * Returns: (nullable): the parameter type + * + * Since: 2.28 + **/ +const GVariantType * +g_action_group_get_action_parameter_type (GActionGroup *action_group, + const gchar *action_name) +{ + g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL); + + return G_ACTION_GROUP_GET_IFACE (action_group) + ->get_action_parameter_type (action_group, action_name); +} + +/** + * g_action_group_get_action_state_type: + * @action_group: a #GActionGroup + * @action_name: the name of the action to query + * + * Queries the type of the state of the named action within + * @action_group. + * + * If the action is stateful then this function returns the + * #GVariantType of the state. All calls to + * g_action_group_change_action_state() must give a #GVariant of this + * type and g_action_group_get_action_state() will return a #GVariant + * of the same type. + * + * If the action is not stateful then this function will return %NULL. + * In that case, g_action_group_get_action_state() will return %NULL + * and you must not call g_action_group_change_action_state(). + * + * The state type of a particular action will never change but it is + * possible for an action to be removed and for a new action to be added + * with the same name but a different state type. + * + * Returns: (nullable): the state type, if the action is stateful + * + * Since: 2.28 + **/ +const GVariantType * +g_action_group_get_action_state_type (GActionGroup *action_group, + const gchar *action_name) +{ + g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL); + + return G_ACTION_GROUP_GET_IFACE (action_group) + ->get_action_state_type (action_group, action_name); +} + +/** + * g_action_group_get_action_state_hint: + * @action_group: a #GActionGroup + * @action_name: the name of the action to query + * + * Requests a hint about the valid range of values for the state of the + * named action within @action_group. + * + * If %NULL is returned it either means that the action is not stateful + * or that there is no hint about the valid range of values for the + * state of the action. + * + * If a #GVariant array is returned then each item in the array is a + * possible value for the state. If a #GVariant pair (ie: two-tuple) is + * returned then the tuple specifies the inclusive lower and upper bound + * of valid values for the state. + * + * In any case, the information is merely a hint. It may be possible to + * have a state value outside of the hinted range and setting a value + * within the range may fail. + * + * The return value (if non-%NULL) should be freed with + * g_variant_unref() when it is no longer required. + * + * Returns: (nullable) (transfer full): the state range hint + * + * Since: 2.28 + **/ +GVariant * +g_action_group_get_action_state_hint (GActionGroup *action_group, + const gchar *action_name) +{ + g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL); + + return G_ACTION_GROUP_GET_IFACE (action_group) + ->get_action_state_hint (action_group, action_name); +} + +/** + * g_action_group_get_action_enabled: + * @action_group: a #GActionGroup + * @action_name: the name of the action to query + * + * Checks if the named action within @action_group is currently enabled. + * + * An action must be enabled in order to be activated or in order to + * have its state changed from outside callers. + * + * Returns: whether or not the action is currently enabled + * + * Since: 2.28 + **/ +gboolean +g_action_group_get_action_enabled (GActionGroup *action_group, + const gchar *action_name) +{ + g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE); + + return G_ACTION_GROUP_GET_IFACE (action_group) + ->get_action_enabled (action_group, action_name); +} + +/** + * g_action_group_get_action_state: + * @action_group: a #GActionGroup + * @action_name: the name of the action to query + * + * Queries the current state of the named action within @action_group. + * + * If the action is not stateful then %NULL will be returned. If the + * action is stateful then the type of the return value is the type + * given by g_action_group_get_action_state_type(). + * + * The return value (if non-%NULL) should be freed with + * g_variant_unref() when it is no longer required. + * + * Returns: (nullable) (transfer full): the current state of the action + * + * Since: 2.28 + **/ +GVariant * +g_action_group_get_action_state (GActionGroup *action_group, + const gchar *action_name) +{ + g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL); + + return G_ACTION_GROUP_GET_IFACE (action_group) + ->get_action_state (action_group, action_name); +} + +/** + * g_action_group_change_action_state: + * @action_group: a #GActionGroup + * @action_name: the name of the action to request the change on + * @value: the new state + * + * Request for the state of the named action within @action_group to be + * changed to @value. + * + * The action must be stateful and @value must be of the correct type. + * See g_action_group_get_action_state_type(). + * + * This call merely requests a change. The action may refuse to change + * its state or may change its state to something other than @value. + * See g_action_group_get_action_state_hint(). + * + * If the @value GVariant is floating, it is consumed. + * + * Since: 2.28 + **/ +void +g_action_group_change_action_state (GActionGroup *action_group, + const gchar *action_name, + GVariant *value) +{ + g_return_if_fail (G_IS_ACTION_GROUP (action_group)); + g_return_if_fail (action_name != NULL); + g_return_if_fail (value != NULL); + + G_ACTION_GROUP_GET_IFACE (action_group) + ->change_action_state (action_group, action_name, value); +} + +/** + * g_action_group_activate_action: + * @action_group: a #GActionGroup + * @action_name: the name of the action to activate + * @parameter: (nullable): parameters to the activation + * + * Activate the named action within @action_group. + * + * If the action is expecting a parameter, then the correct type of + * parameter must be given as @parameter. If the action is expecting no + * parameters then @parameter must be %NULL. See + * g_action_group_get_action_parameter_type(). + * + * Since: 2.28 + **/ +void +g_action_group_activate_action (GActionGroup *action_group, + const gchar *action_name, + GVariant *parameter) +{ + g_return_if_fail (G_IS_ACTION_GROUP (action_group)); + g_return_if_fail (action_name != NULL); + + G_ACTION_GROUP_GET_IFACE (action_group) + ->activate_action (action_group, action_name, parameter); +} + +/** + * g_action_group_action_added: + * @action_group: a #GActionGroup + * @action_name: the name of an action in the group + * + * Emits the #GActionGroup::action-added signal on @action_group. + * + * This function should only be called by #GActionGroup implementations. + * + * Since: 2.28 + **/ +void +g_action_group_action_added (GActionGroup *action_group, + const gchar *action_name) +{ + g_return_if_fail (G_IS_ACTION_GROUP (action_group)); + g_return_if_fail (action_name != NULL); + + g_signal_emit (action_group, + g_action_group_signals[SIGNAL_ACTION_ADDED], + g_quark_try_string (action_name), + action_name); +} + +/** + * g_action_group_action_removed: + * @action_group: a #GActionGroup + * @action_name: the name of an action in the group + * + * Emits the #GActionGroup::action-removed signal on @action_group. + * + * This function should only be called by #GActionGroup implementations. + * + * Since: 2.28 + **/ +void +g_action_group_action_removed (GActionGroup *action_group, + const gchar *action_name) +{ + g_return_if_fail (G_IS_ACTION_GROUP (action_group)); + g_return_if_fail (action_name != NULL); + + g_signal_emit (action_group, + g_action_group_signals[SIGNAL_ACTION_REMOVED], + g_quark_try_string (action_name), + action_name); +} + +/** + * g_action_group_action_enabled_changed: + * @action_group: a #GActionGroup + * @action_name: the name of an action in the group + * @enabled: whether or not the action is now enabled + * + * Emits the #GActionGroup::action-enabled-changed signal on @action_group. + * + * This function should only be called by #GActionGroup implementations. + * + * Since: 2.28 + **/ +void +g_action_group_action_enabled_changed (GActionGroup *action_group, + const gchar *action_name, + gboolean enabled) +{ + g_return_if_fail (G_IS_ACTION_GROUP (action_group)); + g_return_if_fail (action_name != NULL); + + enabled = !!enabled; + + g_signal_emit (action_group, + g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED], + g_quark_try_string (action_name), + action_name, + enabled); +} + +/** + * g_action_group_action_state_changed: + * @action_group: a #GActionGroup + * @action_name: the name of an action in the group + * @state: the new state of the named action + * + * Emits the #GActionGroup::action-state-changed signal on @action_group. + * + * This function should only be called by #GActionGroup implementations. + * + * Since: 2.28 + **/ +void +g_action_group_action_state_changed (GActionGroup *action_group, + const gchar *action_name, + GVariant *state) +{ + g_return_if_fail (G_IS_ACTION_GROUP (action_group)); + g_return_if_fail (action_name != NULL); + + g_signal_emit (action_group, + g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED], + g_quark_try_string (action_name), + action_name, + state); +} + +/** + * g_action_group_query_action: + * @action_group: a #GActionGroup + * @action_name: the name of an action in the group + * @enabled: (out): if the action is presently enabled + * @parameter_type: (out) (optional): the parameter type, or %NULL if none needed + * @state_type: (out) (optional): the state type, or %NULL if stateless + * @state_hint: (out) (optional): the state hint, or %NULL if none + * @state: (out) (optional): the current state, or %NULL if stateless + * + * Queries all aspects of the named action within an @action_group. + * + * This function acquires the information available from + * g_action_group_has_action(), g_action_group_get_action_enabled(), + * g_action_group_get_action_parameter_type(), + * g_action_group_get_action_state_type(), + * g_action_group_get_action_state_hint() and + * g_action_group_get_action_state() with a single function call. + * + * This provides two main benefits. + * + * The first is the improvement in efficiency that comes with not having + * to perform repeated lookups of the action in order to discover + * different things about it. The second is that implementing + * #GActionGroup can now be done by only overriding this one virtual + * function. + * + * The interface provides a default implementation of this function that + * calls the individual functions, as required, to fetch the + * information. The interface also provides default implementations of + * those functions that call this function. All implementations, + * therefore, must override either this function or all of the others. + * + * If the action exists, %TRUE is returned and any of the requested + * fields (as indicated by having a non-%NULL reference passed in) are + * filled. If the action doesn't exist, %FALSE is returned and the + * fields may or may not have been modified. + * + * Returns: %TRUE if the action exists, else %FALSE + * + * Since: 2.32 + **/ +gboolean +g_action_group_query_action (GActionGroup *action_group, + const gchar *action_name, + gboolean *enabled, + const GVariantType **parameter_type, + const GVariantType **state_type, + GVariant **state_hint, + GVariant **state) +{ + return G_ACTION_GROUP_GET_IFACE (action_group) + ->query_action (action_group, action_name, enabled, parameter_type, state_type, state_hint, state); +}
diff --git a/gio/gactiongroup.h b/gio/gactiongroup.h new file mode 100644 index 0000000..bba8a23 --- /dev/null +++ b/gio/gactiongroup.h
@@ -0,0 +1,161 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_ACTION_GROUP_H__ +#define __G_ACTION_GROUP_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + + +#define G_TYPE_ACTION_GROUP (g_action_group_get_type ()) +#define G_ACTION_GROUP(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_ACTION_GROUP, GActionGroup)) +#define G_IS_ACTION_GROUP(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + G_TYPE_ACTION_GROUP)) +#define G_ACTION_GROUP_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \ + G_TYPE_ACTION_GROUP, GActionGroupInterface)) + +typedef struct _GActionGroupInterface GActionGroupInterface; + +struct _GActionGroupInterface +{ + GTypeInterface g_iface; + + /* virtual functions */ + gboolean (* has_action) (GActionGroup *action_group, + const gchar *action_name); + + gchar ** (* list_actions) (GActionGroup *action_group); + + gboolean (* get_action_enabled) (GActionGroup *action_group, + const gchar *action_name); + + const GVariantType * (* get_action_parameter_type) (GActionGroup *action_group, + const gchar *action_name); + + const GVariantType * (* get_action_state_type) (GActionGroup *action_group, + const gchar *action_name); + + GVariant * (* get_action_state_hint) (GActionGroup *action_group, + const gchar *action_name); + + GVariant * (* get_action_state) (GActionGroup *action_group, + const gchar *action_name); + + void (* change_action_state) (GActionGroup *action_group, + const gchar *action_name, + GVariant *value); + + void (* activate_action) (GActionGroup *action_group, + const gchar *action_name, + GVariant *parameter); + + /* signals */ + void (* action_added) (GActionGroup *action_group, + const gchar *action_name); + void (* action_removed) (GActionGroup *action_group, + const gchar *action_name); + void (* action_enabled_changed) (GActionGroup *action_group, + const gchar *action_name, + gboolean enabled); + void (* action_state_changed) (GActionGroup *action_group, + const gchar *action_name, + GVariant *state); + + /* more virtual functions */ + gboolean (* query_action) (GActionGroup *action_group, + const gchar *action_name, + gboolean *enabled, + const GVariantType **parameter_type, + const GVariantType **state_type, + GVariant **state_hint, + GVariant **state); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_action_group_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +gboolean g_action_group_has_action (GActionGroup *action_group, + const gchar *action_name); +GLIB_AVAILABLE_IN_ALL +gchar ** g_action_group_list_actions (GActionGroup *action_group); + +GLIB_AVAILABLE_IN_ALL +const GVariantType * g_action_group_get_action_parameter_type (GActionGroup *action_group, + const gchar *action_name); +GLIB_AVAILABLE_IN_ALL +const GVariantType * g_action_group_get_action_state_type (GActionGroup *action_group, + const gchar *action_name); +GLIB_AVAILABLE_IN_ALL +GVariant * g_action_group_get_action_state_hint (GActionGroup *action_group, + const gchar *action_name); + +GLIB_AVAILABLE_IN_ALL +gboolean g_action_group_get_action_enabled (GActionGroup *action_group, + const gchar *action_name); + +GLIB_AVAILABLE_IN_ALL +GVariant * g_action_group_get_action_state (GActionGroup *action_group, + const gchar *action_name); +GLIB_AVAILABLE_IN_ALL +void g_action_group_change_action_state (GActionGroup *action_group, + const gchar *action_name, + GVariant *value); + +GLIB_AVAILABLE_IN_ALL +void g_action_group_activate_action (GActionGroup *action_group, + const gchar *action_name, + GVariant *parameter); + +/* signals */ +GLIB_AVAILABLE_IN_ALL +void g_action_group_action_added (GActionGroup *action_group, + const gchar *action_name); +GLIB_AVAILABLE_IN_ALL +void g_action_group_action_removed (GActionGroup *action_group, + const gchar *action_name); +GLIB_AVAILABLE_IN_ALL +void g_action_group_action_enabled_changed (GActionGroup *action_group, + const gchar *action_name, + gboolean enabled); + +GLIB_AVAILABLE_IN_ALL +void g_action_group_action_state_changed (GActionGroup *action_group, + const gchar *action_name, + GVariant *state); + +GLIB_AVAILABLE_IN_2_32 +gboolean g_action_group_query_action (GActionGroup *action_group, + const gchar *action_name, + gboolean *enabled, + const GVariantType **parameter_type, + const GVariantType **state_type, + GVariant **state_hint, + GVariant **state); + +G_END_DECLS + +#endif /* __G_ACTION_GROUP_H__ */
diff --git a/gio/gactiongroupexporter.c b/gio/gactiongroupexporter.c new file mode 100644 index 0000000..17111ff --- /dev/null +++ b/gio/gactiongroupexporter.c
@@ -0,0 +1,608 @@ +/* + * Copyright © 2010 Codethink Limited + * Copyright © 2011 Canonical Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" + +#include "gactiongroupexporter.h" + +#include "gdbusmethodinvocation.h" +#include "gremoteactiongroup.h" +#include "gdbusintrospection.h" +#include "gdbusconnection.h" +#include "gactiongroup.h" +#include "gdbuserror.h" + +/** + * SECTION:gactiongroupexporter + * @title: GActionGroup exporter + * @include: gio/gio.h + * @short_description: Export GActionGroups on D-Bus + * @see_also: #GActionGroup, #GDBusActionGroup + * + * These functions support exporting a #GActionGroup on D-Bus. + * The D-Bus interface that is used is a private implementation + * detail. + * + * To access an exported #GActionGroup remotely, use + * g_dbus_action_group_get() to obtain a #GDBusActionGroup. + */ + +static GVariant * +g_action_group_describe_action (GActionGroup *action_group, + const gchar *name) +{ + const GVariantType *type; + GVariantBuilder builder; + gboolean enabled; + GVariant *state; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("(bgav)")); + + enabled = g_action_group_get_action_enabled (action_group, name); + g_variant_builder_add (&builder, "b", enabled); + + if ((type = g_action_group_get_action_parameter_type (action_group, name))) + { + gchar *str = g_variant_type_dup_string (type); + g_variant_builder_add (&builder, "g", str); + g_free (str); + } + else + g_variant_builder_add (&builder, "g", ""); + + g_variant_builder_open (&builder, G_VARIANT_TYPE ("av")); + if ((state = g_action_group_get_action_state (action_group, name))) + { + g_variant_builder_add (&builder, "v", state); + g_variant_unref (state); + } + g_variant_builder_close (&builder); + + return g_variant_builder_end (&builder); +} + +/* Using XML saves us dozens of relocations vs. using the introspection + * structure types. We only need to burn cycles and memory if we + * actually use the exporter -- not in every single app using GIO. + * + * It's also a lot easier to read. :) + * + * For documentation of this interface, see + * https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI + */ +const char org_gtk_Actions_xml[] = + "<node>" + " <interface name='org.gtk.Actions'>" + " <method name='List'>" + " <arg type='as' name='list' direction='out'/>" + " </method>" + " <method name='Describe'>" + " <arg type='s' name='action_name' direction='in'/>" + " <arg type='(bgav)' name='description' direction='out'/>" + " </method>" + " <method name='DescribeAll'>" + " <arg type='a{s(bgav)}' name='descriptions' direction='out'/>" + " </method>" + " <method name='Activate'>" + " <arg type='s' name='action_name' direction='in'/>" + " <arg type='av' name='parameter' direction='in'/>" + " <arg type='a{sv}' name='platform_data' direction='in'/>" + " </method>" + " <method name='SetState'>" + " <arg type='s' name='action_name' direction='in'/>" + " <arg type='v' name='value' direction='in'/>" + " <arg type='a{sv}' name='platform_data' direction='in'/>" + " </method>" + " <signal name='Changed'>" + " <arg type='as' name='removals'/>" + " <arg type='a{sb}' name='enable_changes'/>" + " <arg type='a{sv}' name='state_changes'/>" + " <arg type='a{s(bgav)}' name='additions'/>" + " </signal>" + " </interface>" + "</node>"; + +static GDBusInterfaceInfo *org_gtk_Actions; + +typedef struct +{ + GActionGroup *action_group; + GDBusConnection *connection; + GMainContext *context; + gchar *object_path; + GHashTable *pending_changes; + GSource *pending_source; +} GActionGroupExporter; + +#define ACTION_ADDED_EVENT (1u<<0) +#define ACTION_REMOVED_EVENT (1u<<1) +#define ACTION_STATE_CHANGED_EVENT (1u<<2) +#define ACTION_ENABLED_CHANGED_EVENT (1u<<3) + +static gboolean +g_action_group_exporter_dispatch_events (gpointer user_data) +{ + GActionGroupExporter *exporter = user_data; + GVariantBuilder removes; + GVariantBuilder enabled_changes; + GVariantBuilder state_changes; + GVariantBuilder adds; + GHashTableIter iter; + gpointer value; + gpointer key; + + g_variant_builder_init (&removes, G_VARIANT_TYPE_STRING_ARRAY); + g_variant_builder_init (&enabled_changes, G_VARIANT_TYPE ("a{sb}")); + g_variant_builder_init (&state_changes, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_init (&adds, G_VARIANT_TYPE ("a{s(bgav)}")); + + g_hash_table_iter_init (&iter, exporter->pending_changes); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + guint events = GPOINTER_TO_INT (value); + const gchar *name = key; + + /* Adds and removes are incompatible with enabled or state + * changes, but we must report at least one event. + */ + g_assert (((events & (ACTION_ENABLED_CHANGED_EVENT | ACTION_STATE_CHANGED_EVENT)) == 0) != + ((events & (ACTION_REMOVED_EVENT | ACTION_ADDED_EVENT)) == 0)); + + if (events & ACTION_REMOVED_EVENT) + g_variant_builder_add (&removes, "s", name); + + if (events & ACTION_ENABLED_CHANGED_EVENT) + { + gboolean enabled; + + enabled = g_action_group_get_action_enabled (exporter->action_group, name); + g_variant_builder_add (&enabled_changes, "{sb}", name, enabled); + } + + if (events & ACTION_STATE_CHANGED_EVENT) + { + GVariant *state; + + state = g_action_group_get_action_state (exporter->action_group, name); + g_variant_builder_add (&state_changes, "{sv}", name, state); + g_variant_unref (state); + } + + if (events & ACTION_ADDED_EVENT) + { + GVariant *description; + + description = g_action_group_describe_action (exporter->action_group, name); + g_variant_builder_add (&adds, "{s@(bgav)}", name, description); + } + } + + g_hash_table_remove_all (exporter->pending_changes); + + g_dbus_connection_emit_signal (exporter->connection, NULL, exporter->object_path, + "org.gtk.Actions", "Changed", + g_variant_new ("(asa{sb}a{sv}a{s(bgav)})", + &removes, &enabled_changes, + &state_changes, &adds), + NULL); + + exporter->pending_source = NULL; + + return FALSE; +} + +static void +g_action_group_exporter_flush_queue (GActionGroupExporter *exporter) +{ + if (exporter->pending_source) + { + g_source_destroy (exporter->pending_source); + g_action_group_exporter_dispatch_events (exporter); + g_assert (exporter->pending_source == NULL); + } +} + +static guint +g_action_group_exporter_get_events (GActionGroupExporter *exporter, + const gchar *name) +{ + return (gsize) g_hash_table_lookup (exporter->pending_changes, name); +} + +static void +g_action_group_exporter_set_events (GActionGroupExporter *exporter, + const gchar *name, + guint events) +{ + gboolean have_events; + gboolean is_queued; + + if (events != 0) + g_hash_table_insert (exporter->pending_changes, g_strdup (name), GINT_TO_POINTER (events)); + else + g_hash_table_remove (exporter->pending_changes, name); + + have_events = g_hash_table_size (exporter->pending_changes) > 0; + is_queued = exporter->pending_source != NULL; + + if (have_events && !is_queued) + { + GSource *source; + + source = g_idle_source_new (); + exporter->pending_source = source; + g_source_set_callback (source, g_action_group_exporter_dispatch_events, exporter, NULL); + g_source_set_name (source, "[gio] g_action_group_exporter_dispatch_events"); + g_source_attach (source, exporter->context); + g_source_unref (source); + } + + if (!have_events && is_queued) + { + g_source_destroy (exporter->pending_source); + exporter->pending_source = NULL; + } +} + +static void +g_action_group_exporter_action_added (GActionGroup *action_group, + const gchar *action_name, + gpointer user_data) +{ + GActionGroupExporter *exporter = user_data; + guint event_mask; + + event_mask = g_action_group_exporter_get_events (exporter, action_name); + + /* The action is new, so we should not have any pending + * enabled-changed or state-changed signals for it. + */ + g_assert (~event_mask & (ACTION_STATE_CHANGED_EVENT | + ACTION_ENABLED_CHANGED_EVENT)); + + event_mask |= ACTION_ADDED_EVENT; + + g_action_group_exporter_set_events (exporter, action_name, event_mask); +} + +static void +g_action_group_exporter_action_removed (GActionGroup *action_group, + const gchar *action_name, + gpointer user_data) +{ + GActionGroupExporter *exporter = user_data; + guint event_mask; + + event_mask = g_action_group_exporter_get_events (exporter, action_name); + + /* If the add event for this is still queued then just cancel it since + * it's gone now. + * + * If the event was freshly added, there should not have been any + * enabled or state changed events. + */ + if (event_mask & ACTION_ADDED_EVENT) + { + g_assert (~event_mask & ~(ACTION_STATE_CHANGED_EVENT | ACTION_ENABLED_CHANGED_EVENT)); + event_mask &= ~ACTION_ADDED_EVENT; + } + + /* Otherwise, queue a remove event. Drop any state or enabled changes + * that were queued before the remove. */ + else + { + event_mask |= ACTION_REMOVED_EVENT; + event_mask &= ~(ACTION_STATE_CHANGED_EVENT | ACTION_ENABLED_CHANGED_EVENT); + } + + g_action_group_exporter_set_events (exporter, action_name, event_mask); +} + +static void +g_action_group_exporter_action_state_changed (GActionGroup *action_group, + const gchar *action_name, + GVariant *value, + gpointer user_data) +{ + GActionGroupExporter *exporter = user_data; + guint event_mask; + + event_mask = g_action_group_exporter_get_events (exporter, action_name); + + /* If it was removed, it must have been added back. Otherwise, why + * are we hearing about changes? + */ + g_assert (~event_mask & ACTION_REMOVED_EVENT || + event_mask & ACTION_ADDED_EVENT); + + /* If it is freshly added, don't also bother with the state change + * signal since the updated state will be sent as part of the pending + * add message. + */ + if (~event_mask & ACTION_ADDED_EVENT) + event_mask |= ACTION_STATE_CHANGED_EVENT; + + g_action_group_exporter_set_events (exporter, action_name, event_mask); +} + +static void +g_action_group_exporter_action_enabled_changed (GActionGroup *action_group, + const gchar *action_name, + gboolean enabled, + gpointer user_data) +{ + GActionGroupExporter *exporter = user_data; + guint event_mask; + + event_mask = g_action_group_exporter_get_events (exporter, action_name); + + /* Reasoning as above. */ + g_assert (~event_mask & ACTION_REMOVED_EVENT || + event_mask & ACTION_ADDED_EVENT); + + if (~event_mask & ACTION_ADDED_EVENT) + event_mask |= ACTION_ENABLED_CHANGED_EVENT; + + g_action_group_exporter_set_events (exporter, action_name, event_mask); +} + +static void +org_gtk_Actions_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GActionGroupExporter *exporter = user_data; + GVariant *result = NULL; + + g_action_group_exporter_flush_queue (exporter); + + if (g_str_equal (method_name, "List")) + { + gchar **list; + + list = g_action_group_list_actions (exporter->action_group); + result = g_variant_new ("(^as)", list); + g_strfreev (list); + } + + else if (g_str_equal (method_name, "Describe")) + { + const gchar *name; + GVariant *desc; + + g_variant_get (parameters, "(&s)", &name); + + if (!g_action_group_has_action (exporter->action_group, name)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "The named action ('%s') does not exist.", name); + return; + } + + desc = g_action_group_describe_action (exporter->action_group, name); + result = g_variant_new ("(@(bgav))", desc); + } + + else if (g_str_equal (method_name, "DescribeAll")) + { + GVariantBuilder builder; + gchar **list; + gint i; + + list = g_action_group_list_actions (exporter->action_group); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{s(bgav)}")); + for (i = 0; list[i]; i++) + { + const gchar *name = list[i]; + GVariant *description; + + description = g_action_group_describe_action (exporter->action_group, name); + g_variant_builder_add (&builder, "{s@(bgav)}", name, description); + } + result = g_variant_new ("(a{s(bgav)})", &builder); + g_strfreev (list); + } + + else if (g_str_equal (method_name, "Activate")) + { + GVariant *parameter = NULL; + GVariant *platform_data; + GVariantIter *iter; + const gchar *name; + + g_variant_get (parameters, "(&sav@a{sv})", &name, &iter, &platform_data); + g_variant_iter_next (iter, "v", ¶meter); + g_variant_iter_free (iter); + + if (G_IS_REMOTE_ACTION_GROUP (exporter->action_group)) + g_remote_action_group_activate_action_full (G_REMOTE_ACTION_GROUP (exporter->action_group), + name, parameter, platform_data); + else + g_action_group_activate_action (exporter->action_group, name, parameter); + + if (parameter) + g_variant_unref (parameter); + + g_variant_unref (platform_data); + } + + else if (g_str_equal (method_name, "SetState")) + { + GVariant *platform_data; + const gchar *name; + GVariant *state; + + g_variant_get (parameters, "(&sv@a{sv})", &name, &state, &platform_data); + + if (G_IS_REMOTE_ACTION_GROUP (exporter->action_group)) + g_remote_action_group_change_action_state_full (G_REMOTE_ACTION_GROUP (exporter->action_group), + name, state, platform_data); + else + g_action_group_change_action_state (exporter->action_group, name, state); + + g_variant_unref (platform_data); + g_variant_unref (state); + } + + else + g_assert_not_reached (); + + g_dbus_method_invocation_return_value (invocation, result); +} + +static void +g_action_group_exporter_free (gpointer user_data) +{ + GActionGroupExporter *exporter = user_data; + + g_signal_handlers_disconnect_by_func (exporter->action_group, + g_action_group_exporter_action_added, exporter); + g_signal_handlers_disconnect_by_func (exporter->action_group, + g_action_group_exporter_action_enabled_changed, exporter); + g_signal_handlers_disconnect_by_func (exporter->action_group, + g_action_group_exporter_action_state_changed, exporter); + g_signal_handlers_disconnect_by_func (exporter->action_group, + g_action_group_exporter_action_removed, exporter); + + g_hash_table_unref (exporter->pending_changes); + if (exporter->pending_source) + g_source_destroy (exporter->pending_source); + + g_main_context_unref (exporter->context); + g_object_unref (exporter->connection); + g_object_unref (exporter->action_group); + g_free (exporter->object_path); + + g_slice_free (GActionGroupExporter, exporter); +} + +/** + * g_dbus_connection_export_action_group: + * @connection: a #GDBusConnection + * @object_path: a D-Bus object path + * @action_group: a #GActionGroup + * @error: a pointer to a %NULL #GError, or %NULL + * + * Exports @action_group on @connection at @object_path. + * + * The implemented D-Bus API should be considered private. It is + * subject to change in the future. + * + * A given object path can only have one action group exported on it. + * If this constraint is violated, the export will fail and 0 will be + * returned (with @error set accordingly). + * + * You can unexport the action group using + * g_dbus_connection_unexport_action_group() with the return value of + * this function. + * + * The thread default main context is taken at the time of this call. + * All incoming action activations and state change requests are + * reported from this context. Any changes on the action group that + * cause it to emit signals must also come from this same context. + * Since incoming action activations and state change requests are + * rather likely to cause changes on the action group, this effectively + * limits a given action group to being exported from only one main + * context. + * + * Returns: the ID of the export (never zero), or 0 in case of failure + * + * Since: 2.32 + **/ +guint +g_dbus_connection_export_action_group (GDBusConnection *connection, + const gchar *object_path, + GActionGroup *action_group, + GError **error) +{ + const GDBusInterfaceVTable vtable = { + org_gtk_Actions_method_call + }; + GActionGroupExporter *exporter; + guint id; + + if G_UNLIKELY (org_gtk_Actions == NULL) + { + GError *error = NULL; + GDBusNodeInfo *info; + + info = g_dbus_node_info_new_for_xml (org_gtk_Actions_xml, &error); + if G_UNLIKELY (info == NULL) + g_error ("%s", error->message); + org_gtk_Actions = g_dbus_node_info_lookup_interface (info, "org.gtk.Actions"); + g_assert (org_gtk_Actions != NULL); + g_dbus_interface_info_ref (org_gtk_Actions); + g_dbus_node_info_unref (info); + } + + exporter = g_slice_new (GActionGroupExporter); + id = g_dbus_connection_register_object (connection, object_path, org_gtk_Actions, &vtable, + exporter, g_action_group_exporter_free, error); + + if (id == 0) + { + g_slice_free (GActionGroupExporter, exporter); + return 0; + } + + exporter->context = g_main_context_ref_thread_default (); + exporter->pending_changes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + exporter->pending_source = NULL; + exporter->action_group = g_object_ref (action_group); + exporter->connection = g_object_ref (connection); + exporter->object_path = g_strdup (object_path); + + g_signal_connect (action_group, "action-added", + G_CALLBACK (g_action_group_exporter_action_added), exporter); + g_signal_connect (action_group, "action-removed", + G_CALLBACK (g_action_group_exporter_action_removed), exporter); + g_signal_connect (action_group, "action-state-changed", + G_CALLBACK (g_action_group_exporter_action_state_changed), exporter); + g_signal_connect (action_group, "action-enabled-changed", + G_CALLBACK (g_action_group_exporter_action_enabled_changed), exporter); + + return id; +} + +/** + * g_dbus_connection_unexport_action_group: + * @connection: a #GDBusConnection + * @export_id: the ID from g_dbus_connection_export_action_group() + * + * Reverses the effect of a previous call to + * g_dbus_connection_export_action_group(). + * + * It is an error to call this function with an ID that wasn't returned + * from g_dbus_connection_export_action_group() or to call it with the + * same ID more than once. + * + * Since: 2.32 + **/ +void +g_dbus_connection_unexport_action_group (GDBusConnection *connection, + guint export_id) +{ + g_dbus_connection_unregister_object (connection, export_id); +}
diff --git a/gio/gactiongroupexporter.h b/gio/gactiongroupexporter.h new file mode 100644 index 0000000..ba28c89 --- /dev/null +++ b/gio/gactiongroupexporter.h
@@ -0,0 +1,45 @@ +/* + * Copyright © 2010 Codethink Limited + * Copyright © 2011 Canonical Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + + +#ifndef __G_ACTION_GROUP_EXPORTER_H__ +#define __G_ACTION_GROUP_EXPORTER_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +GLIB_AVAILABLE_IN_2_32 +guint g_dbus_connection_export_action_group (GDBusConnection *connection, + const gchar *object_path, + GActionGroup *action_group, + GError **error); + +GLIB_AVAILABLE_IN_2_32 +void g_dbus_connection_unexport_action_group (GDBusConnection *connection, + guint export_id); + +G_END_DECLS + +#endif /* __G_ACTION_GROUP_EXPORTER_H__ */
diff --git a/gio/gactionmap.c b/gio/gactionmap.c new file mode 100644 index 0000000..bfcda8d --- /dev/null +++ b/gio/gactionmap.c
@@ -0,0 +1,285 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" + +#include "gsimpleaction.h" +#include "gactionmap.h" +#include "gaction.h" + +/** + * SECTION:gactionmap + * @title: GActionMap + * @include: gio/gio.h + * @short_description: Interface for action containers + * + * The GActionMap interface is implemented by #GActionGroup + * implementations that operate by containing a number of + * named #GAction instances, such as #GSimpleActionGroup. + * + * One useful application of this interface is to map the + * names of actions from various action groups to unique, + * prefixed names (e.g. by prepending "app." or "win."). + * This is the motivation for the 'Map' part of the interface + * name. + * + * Since: 2.32 + **/ + +/** + * GActionMap: + * + * #GActionMap is an opaque data structure and can only be accessed + * using the following functions. + **/ + +/** + * GActionMapInterface: + * @lookup_action: the virtual function pointer for g_action_map_lookup_action() + * @add_action: the virtual function pointer for g_action_map_add_action() + * @remove_action: the virtual function pointer for g_action_map_remove_action() + * + * The virtual function table for #GActionMap. + * + * Since: 2.32 + **/ + +G_DEFINE_INTERFACE (GActionMap, g_action_map, G_TYPE_OBJECT) + +static void +g_action_map_default_init (GActionMapInterface *iface) +{ +} + +/** + * g_action_map_lookup_action: + * @action_map: a #GActionMap + * @action_name: the name of an action + * + * Looks up the action with the name @action_name in @action_map. + * + * If no such action exists, returns %NULL. + * + * Returns: (transfer none): a #GAction, or %NULL + * + * Since: 2.32 + */ +GAction * +g_action_map_lookup_action (GActionMap *action_map, + const gchar *action_name) +{ + return G_ACTION_MAP_GET_IFACE (action_map) + ->lookup_action (action_map, action_name); +} + +/** + * g_action_map_add_action: + * @action_map: a #GActionMap + * @action: a #GAction + * + * Adds an action to the @action_map. + * + * If the action map already contains an action with the same name + * as @action then the old action is dropped from the action map. + * + * The action map takes its own reference on @action. + * + * Since: 2.32 + */ +void +g_action_map_add_action (GActionMap *action_map, + GAction *action) +{ + G_ACTION_MAP_GET_IFACE (action_map)->add_action (action_map, action); +} + +/** + * g_action_map_remove_action: + * @action_map: a #GActionMap + * @action_name: the name of the action + * + * Removes the named action from the action map. + * + * If no action of this name is in the map then nothing happens. + * + * Since: 2.32 + */ +void +g_action_map_remove_action (GActionMap *action_map, + const gchar *action_name) +{ + G_ACTION_MAP_GET_IFACE (action_map)->remove_action (action_map, action_name); +} + +/** + * GActionEntry: + * @name: the name of the action + * @activate: the callback to connect to the "activate" signal of the + * action. Since GLib 2.40, this can be %NULL for stateful + * actions, in which case the default handler is used. For + * boolean-stated actions with no parameter, this is a + * toggle. For other state types (and parameter type equal + * to the state type) this will be a function that + * just calls @change_state (which you should provide). + * @parameter_type: the type of the parameter that must be passed to the + * activate function for this action, given as a single + * GVariant type string (or %NULL for no parameter) + * @state: the initial state for this action, given in + * [GVariant text format][gvariant-text]. The state is parsed + * with no extra type information, so type tags must be added to + * the string if they are necessary. Stateless actions should + * give %NULL here. + * @change_state: the callback to connect to the "change-state" signal + * of the action. All stateful actions should provide a + * handler here; stateless actions should not. + * + * This struct defines a single action. It is for use with + * g_action_map_add_action_entries(). + * + * The order of the items in the structure are intended to reflect + * frequency of use. It is permissible to use an incomplete initialiser + * in order to leave some of the later values as %NULL. All values + * after @name are optional. Additional optional fields may be added in + * the future. + * + * See g_action_map_add_action_entries() for an example. + **/ + +/** + * g_action_map_add_action_entries: + * @action_map: a #GActionMap + * @entries: (array length=n_entries) (element-type GActionEntry): a pointer to + * the first item in an array of #GActionEntry structs + * @n_entries: the length of @entries, or -1 if @entries is %NULL-terminated + * @user_data: the user data for signal connections + * + * A convenience function for creating multiple #GSimpleAction instances + * and adding them to a #GActionMap. + * + * Each action is constructed as per one #GActionEntry. + * + * |[<!-- language="C" --> + * static void + * activate_quit (GSimpleAction *simple, + * GVariant *parameter, + * gpointer user_data) + * { + * exit (0); + * } + * + * static void + * activate_print_string (GSimpleAction *simple, + * GVariant *parameter, + * gpointer user_data) + * { + * g_print ("%s\n", g_variant_get_string (parameter, NULL)); + * } + * + * static GActionGroup * + * create_action_group (void) + * { + * const GActionEntry entries[] = { + * { "quit", activate_quit }, + * { "print-string", activate_print_string, "s" } + * }; + * GSimpleActionGroup *group; + * + * group = g_simple_action_group_new (); + * g_action_map_add_action_entries (G_ACTION_MAP (group), entries, G_N_ELEMENTS (entries), NULL); + * + * return G_ACTION_GROUP (group); + * } + * ]| + * + * Since: 2.32 + */ +void +g_action_map_add_action_entries (GActionMap *action_map, + const GActionEntry *entries, + gint n_entries, + gpointer user_data) +{ + gint i; + + g_return_if_fail (G_IS_ACTION_MAP (action_map)); + g_return_if_fail (entries != NULL || n_entries == 0); + + for (i = 0; n_entries == -1 ? entries[i].name != NULL : i < n_entries; i++) + { + const GActionEntry *entry = &entries[i]; + const GVariantType *parameter_type; + GSimpleAction *action; + + if (entry->parameter_type) + { + if (!g_variant_type_string_is_valid (entry->parameter_type)) + { + g_critical ("g_action_map_add_entries: the type " + "string '%s' given as the parameter type for " + "action '%s' is not a valid GVariant type " + "string. This action will not be added.", + entry->parameter_type, entry->name); + return; + } + + parameter_type = G_VARIANT_TYPE (entry->parameter_type); + } + else + parameter_type = NULL; + + if (entry->state) + { + GError *error = NULL; + GVariant *state; + + state = g_variant_parse (NULL, entry->state, NULL, NULL, &error); + if (state == NULL) + { + g_critical ("g_action_map_add_entries: GVariant could " + "not parse the state value given for action '%s' " + "('%s'): %s. This action will not be added.", + entry->name, entry->state, error->message); + g_error_free (error); + continue; + } + + action = g_simple_action_new_stateful (entry->name, + parameter_type, + state); + + g_variant_unref (state); + } + else + { + action = g_simple_action_new (entry->name, + parameter_type); + } + + if (entry->activate != NULL) + g_signal_connect (action, "activate", + G_CALLBACK (entry->activate), user_data); + + if (entry->change_state != NULL) + g_signal_connect (action, "change-state", + G_CALLBACK (entry->change_state), user_data); + + g_action_map_add_action (action_map, G_ACTION (action)); + g_object_unref (action); + } +}
diff --git a/gio/gactionmap.h b/gio/gactionmap.h new file mode 100644 index 0000000..2a22a27 --- /dev/null +++ b/gio/gactionmap.h
@@ -0,0 +1,95 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_ACTION_MAP_H__ +#define __G_ACTION_MAP_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + + +#define G_TYPE_ACTION_MAP (g_action_map_get_type ()) +#define G_ACTION_MAP(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_ACTION_MAP, GActionMap)) +#define G_IS_ACTION_MAP(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + G_TYPE_ACTION_MAP)) +#define G_ACTION_MAP_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \ + G_TYPE_ACTION_MAP, GActionMapInterface)) + +typedef struct _GActionMapInterface GActionMapInterface; +typedef struct _GActionEntry GActionEntry; + +struct _GActionMapInterface +{ + GTypeInterface g_iface; + + GAction * (* lookup_action) (GActionMap *action_map, + const gchar *action_name); + void (* add_action) (GActionMap *action_map, + GAction *action); + void (* remove_action) (GActionMap *action_map, + const gchar *action_name); +}; + +struct _GActionEntry +{ + const gchar *name; + + void (* activate) (GSimpleAction *action, + GVariant *parameter, + gpointer user_data); + + const gchar *parameter_type; + + const gchar *state; + + void (* change_state) (GSimpleAction *action, + GVariant *value, + gpointer user_data); + + /*< private >*/ + gsize padding[3]; +}; + +GLIB_AVAILABLE_IN_2_32 +GType g_action_map_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_2_32 +GAction * g_action_map_lookup_action (GActionMap *action_map, + const gchar *action_name); +GLIB_AVAILABLE_IN_2_32 +void g_action_map_add_action (GActionMap *action_map, + GAction *action); +GLIB_AVAILABLE_IN_2_32 +void g_action_map_remove_action (GActionMap *action_map, + const gchar *action_name); +GLIB_AVAILABLE_IN_2_32 +void g_action_map_add_action_entries (GActionMap *action_map, + const GActionEntry *entries, + gint n_entries, + gpointer user_data); + +G_END_DECLS + +#endif /* __G_ACTION_MAP_H__ */
diff --git a/gio/gappinfo.c b/gio/gappinfo.c new file mode 100644 index 0000000..6b00925 --- /dev/null +++ b/gio/gappinfo.c
@@ -0,0 +1,1470 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" + +#include "gappinfo.h" +#include "gappinfoprivate.h" +#include "gcontextspecificgroup.h" +#include "gtask.h" +#include "gcancellable.h" + +#include "glibintl.h" +#include "gmarshal-internal.h" +#include <gioerror.h> +#include <gfile.h> + +#ifdef G_OS_UNIX +#include "gdbusconnection.h" +#include "gdbusmessage.h" +#include "gportalsupport.h" +#include "gunixfdlist.h" +#include "gopenuriportal.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#endif + +/** + * SECTION:gappinfo + * @short_description: Application information and launch contexts + * @include: gio/gio.h + * @see_also: #GAppInfoMonitor + * + * #GAppInfo and #GAppLaunchContext are used for describing and launching + * applications installed on the system. + * + * As of GLib 2.20, URIs will always be converted to POSIX paths + * (using g_file_get_path()) when using g_app_info_launch() even if + * the application requested an URI and not a POSIX path. For example + * for a desktop-file based application with Exec key `totem + * %U` and a single URI, `sftp://foo/file.avi`, then + * `/home/user/.gvfs/sftp on foo/file.avi` will be passed. This will + * only work if a set of suitable GIO extensions (such as gvfs 2.26 + * compiled with FUSE support), is available and operational; if this + * is not the case, the URI will be passed unmodified to the application. + * Some URIs, such as `mailto:`, of course cannot be mapped to a POSIX + * path (in gvfs there's no FUSE mount for it); such URIs will be + * passed unmodified to the application. + * + * Specifically for gvfs 2.26 and later, the POSIX URI will be mapped + * back to the GIO URI in the #GFile constructors (since gvfs + * implements the #GVfs extension point). As such, if the application + * needs to examine the URI, it needs to use g_file_get_uri() or + * similar on #GFile. In other words, an application cannot assume + * that the URI passed to e.g. g_file_new_for_commandline_arg() is + * equal to the result of g_file_get_uri(). The following snippet + * illustrates this: + * + * |[ + * GFile *f; + * char *uri; + * + * file = g_file_new_for_commandline_arg (uri_from_commandline); + * + * uri = g_file_get_uri (file); + * strcmp (uri, uri_from_commandline) == 0; + * g_free (uri); + * + * if (g_file_has_uri_scheme (file, "cdda")) + * { + * // do something special with uri + * } + * g_object_unref (file); + * ]| + * + * This code will work when both `cdda://sr0/Track 1.wav` and + * `/home/user/.gvfs/cdda on sr0/Track 1.wav` is passed to the + * application. It should be noted that it's generally not safe + * for applications to rely on the format of a particular URIs. + * Different launcher applications (e.g. file managers) may have + * different ideas of what a given URI means. + */ + +struct _GAppLaunchContextPrivate { + char **envp; +}; + +typedef GAppInfoIface GAppInfoInterface; +G_DEFINE_INTERFACE (GAppInfo, g_app_info, G_TYPE_OBJECT) + +static void +g_app_info_default_init (GAppInfoInterface *iface) +{ +} + + +/** + * g_app_info_dup: + * @appinfo: a #GAppInfo. + * + * Creates a duplicate of a #GAppInfo. + * + * Returns: (transfer full): a duplicate of @appinfo. + **/ +GAppInfo * +g_app_info_dup (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->dup) (appinfo); +} + +/** + * g_app_info_equal: + * @appinfo1: the first #GAppInfo. + * @appinfo2: the second #GAppInfo. + * + * Checks if two #GAppInfos are equal. + * + * Note that the check <emphasis>may not</emphasis> compare each individual + * field, and only does an identity check. In case detecting changes in the + * contents is needed, program code must additionally compare relevant fields. + * + * Returns: %TRUE if @appinfo1 is equal to @appinfo2. %FALSE otherwise. + **/ +gboolean +g_app_info_equal (GAppInfo *appinfo1, + GAppInfo *appinfo2) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo1), FALSE); + g_return_val_if_fail (G_IS_APP_INFO (appinfo2), FALSE); + + if (G_TYPE_FROM_INSTANCE (appinfo1) != G_TYPE_FROM_INSTANCE (appinfo2)) + return FALSE; + + iface = G_APP_INFO_GET_IFACE (appinfo1); + + return (* iface->equal) (appinfo1, appinfo2); +} + +/** + * g_app_info_get_id: + * @appinfo: a #GAppInfo. + * + * Gets the ID of an application. An id is a string that + * identifies the application. The exact format of the id is + * platform dependent. For instance, on Unix this is the + * desktop file id from the xdg menu specification. + * + * Note that the returned ID may be %NULL, depending on how + * the @appinfo has been constructed. + * + * Returns: a string containing the application's ID. + **/ +const char * +g_app_info_get_id (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->get_id) (appinfo); +} + +/** + * g_app_info_get_name: + * @appinfo: a #GAppInfo. + * + * Gets the installed name of the application. + * + * Returns: the name of the application for @appinfo. + **/ +const char * +g_app_info_get_name (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->get_name) (appinfo); +} + +/** + * g_app_info_get_display_name: + * @appinfo: a #GAppInfo. + * + * Gets the display name of the application. The display name is often more + * descriptive to the user than the name itself. + * + * Returns: the display name of the application for @appinfo, or the name if + * no display name is available. + * + * Since: 2.24 + **/ +const char * +g_app_info_get_display_name (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->get_display_name == NULL) + return (* iface->get_name) (appinfo); + + return (* iface->get_display_name) (appinfo); +} + +/** + * g_app_info_get_description: + * @appinfo: a #GAppInfo. + * + * Gets a human-readable description of an installed application. + * + * Returns: a string containing a description of the + * application @appinfo, or %NULL if none. + **/ +const char * +g_app_info_get_description (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->get_description) (appinfo); +} + +/** + * g_app_info_get_executable: + * @appinfo: a #GAppInfo + * + * Gets the executable's name for the installed application. + * + * Returns: (type filename): a string containing the @appinfo's application + * binaries name + **/ +const char * +g_app_info_get_executable (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->get_executable) (appinfo); +} + + +/** + * g_app_info_get_commandline: + * @appinfo: a #GAppInfo + * + * Gets the commandline with which the application will be + * started. + * + * Returns: (type filename): a string containing the @appinfo's commandline, + * or %NULL if this information is not available + * + * Since: 2.20 + **/ +const char * +g_app_info_get_commandline (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->get_commandline) + return (* iface->get_commandline) (appinfo); + + return NULL; +} + +/** + * g_app_info_set_as_default_for_type: + * @appinfo: a #GAppInfo. + * @content_type: the content type. + * @error: a #GError. + * + * Sets the application as the default handler for a given type. + * + * Returns: %TRUE on success, %FALSE on error. + **/ +gboolean +g_app_info_set_as_default_for_type (GAppInfo *appinfo, + const char *content_type, + GError **error) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + g_return_val_if_fail (content_type != NULL, FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->set_as_default_for_type) (appinfo, content_type, error); +} + +/** + * g_app_info_set_as_last_used_for_type: + * @appinfo: a #GAppInfo. + * @content_type: the content type. + * @error: a #GError. + * + * Sets the application as the last used application for a given type. + * This will make the application appear as first in the list returned + * by g_app_info_get_recommended_for_type(), regardless of the default + * application for that content type. + * + * Returns: %TRUE on success, %FALSE on error. + **/ +gboolean +g_app_info_set_as_last_used_for_type (GAppInfo *appinfo, + const char *content_type, + GError **error) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + g_return_val_if_fail (content_type != NULL, FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->set_as_last_used_for_type) (appinfo, content_type, error); +} + +/** + * g_app_info_set_as_default_for_extension: + * @appinfo: a #GAppInfo. + * @extension: (type filename): a string containing the file extension + * (without the dot). + * @error: a #GError. + * + * Sets the application as the default handler for the given file extension. + * + * Returns: %TRUE on success, %FALSE on error. + **/ +gboolean +g_app_info_set_as_default_for_extension (GAppInfo *appinfo, + const char *extension, + GError **error) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + g_return_val_if_fail (extension != NULL, FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->set_as_default_for_extension) + return (* iface->set_as_default_for_extension) (appinfo, extension, error); + + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "g_app_info_set_as_default_for_extension not supported yet"); + return FALSE; +} + + +/** + * g_app_info_add_supports_type: + * @appinfo: a #GAppInfo. + * @content_type: a string. + * @error: a #GError. + * + * Adds a content type to the application information to indicate the + * application is capable of opening files with the given content type. + * + * Returns: %TRUE on success, %FALSE on error. + **/ +gboolean +g_app_info_add_supports_type (GAppInfo *appinfo, + const char *content_type, + GError **error) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + g_return_val_if_fail (content_type != NULL, FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->add_supports_type) + return (* iface->add_supports_type) (appinfo, content_type, error); + + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "g_app_info_add_supports_type not supported yet"); + + return FALSE; +} + + +/** + * g_app_info_can_remove_supports_type: + * @appinfo: a #GAppInfo. + * + * Checks if a supported content type can be removed from an application. + * + * Returns: %TRUE if it is possible to remove supported + * content types from a given @appinfo, %FALSE if not. + **/ +gboolean +g_app_info_can_remove_supports_type (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->can_remove_supports_type) + return (* iface->can_remove_supports_type) (appinfo); + + return FALSE; +} + + +/** + * g_app_info_remove_supports_type: + * @appinfo: a #GAppInfo. + * @content_type: a string. + * @error: a #GError. + * + * Removes a supported type from an application, if possible. + * + * Returns: %TRUE on success, %FALSE on error. + **/ +gboolean +g_app_info_remove_supports_type (GAppInfo *appinfo, + const char *content_type, + GError **error) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + g_return_val_if_fail (content_type != NULL, FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->remove_supports_type) + return (* iface->remove_supports_type) (appinfo, content_type, error); + + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "g_app_info_remove_supports_type not supported yet"); + + return FALSE; +} + +/** + * g_app_info_get_supported_types: + * @appinfo: a #GAppInfo that can handle files + * + * Retrieves the list of content types that @app_info claims to support. + * If this information is not provided by the environment, this function + * will return %NULL. + * This function does not take in consideration associations added with + * g_app_info_add_supports_type(), but only those exported directly by + * the application. + * + * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): + * a list of content types. + * + * Since: 2.34 + */ +const char ** +g_app_info_get_supported_types (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->get_supported_types) + return iface->get_supported_types (appinfo); + else + return NULL; +} + + +/** + * g_app_info_get_icon: + * @appinfo: a #GAppInfo. + * + * Gets the icon for the application. + * + * Returns: (transfer none): the default #GIcon for @appinfo or %NULL + * if there is no default icon. + **/ +GIcon * +g_app_info_get_icon (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->get_icon) (appinfo); +} + + +/** + * g_app_info_launch: + * @appinfo: a #GAppInfo + * @files: (nullable) (element-type GFile): a #GList of #GFile objects + * @context: (nullable): a #GAppLaunchContext or %NULL + * @error: a #GError + * + * Launches the application. Passes @files to the launched application + * as arguments, using the optional @context to get information + * about the details of the launcher (like what screen it is on). + * On error, @error will be set accordingly. + * + * To launch the application without arguments pass a %NULL @files list. + * + * Note that even if the launch is successful the application launched + * can fail to start if it runs into problems during startup. There is + * no way to detect this. + * + * Some URIs can be changed when passed through a GFile (for instance + * unsupported URIs with strange formats like mailto:), so if you have + * a textual URI you want to pass in as argument, consider using + * g_app_info_launch_uris() instead. + * + * The launched application inherits the environment of the launching + * process, but it can be modified with g_app_launch_context_setenv() + * and g_app_launch_context_unsetenv(). + * + * On UNIX, this function sets the `GIO_LAUNCHED_DESKTOP_FILE` + * environment variable with the path of the launched desktop file and + * `GIO_LAUNCHED_DESKTOP_FILE_PID` to the process id of the launched + * process. This can be used to ignore `GIO_LAUNCHED_DESKTOP_FILE`, + * should it be inherited by further processes. The `DISPLAY` and + * `DESKTOP_STARTUP_ID` environment variables are also set, based + * on information provided in @context. + * + * Returns: %TRUE on successful launch, %FALSE otherwise. + **/ +gboolean +g_app_info_launch (GAppInfo *appinfo, + GList *files, + GAppLaunchContext *launch_context, + GError **error) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->launch) (appinfo, files, launch_context, error); +} + + +/** + * g_app_info_supports_uris: + * @appinfo: a #GAppInfo. + * + * Checks if the application supports reading files and directories from URIs. + * + * Returns: %TRUE if the @appinfo supports URIs. + **/ +gboolean +g_app_info_supports_uris (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->supports_uris) (appinfo); +} + + +/** + * g_app_info_supports_files: + * @appinfo: a #GAppInfo. + * + * Checks if the application accepts files as arguments. + * + * Returns: %TRUE if the @appinfo supports files. + **/ +gboolean +g_app_info_supports_files (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->supports_files) (appinfo); +} + + +/** + * g_app_info_launch_uris: + * @appinfo: a #GAppInfo + * @uris: (nullable) (element-type utf8): a #GList containing URIs to launch. + * @context: (nullable): a #GAppLaunchContext or %NULL + * @error: a #GError + * + * Launches the application. This passes the @uris to the launched application + * as arguments, using the optional @context to get information + * about the details of the launcher (like what screen it is on). + * On error, @error will be set accordingly. + * + * To launch the application without arguments pass a %NULL @uris list. + * + * Note that even if the launch is successful the application launched + * can fail to start if it runs into problems during startup. There is + * no way to detect this. + * + * Returns: %TRUE on successful launch, %FALSE otherwise. + **/ +gboolean +g_app_info_launch_uris (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *launch_context, + GError **error) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->launch_uris) (appinfo, uris, launch_context, error); +} + +/** + * g_app_info_launch_uris_async: + * @appinfo: a #GAppInfo + * @uris: (nullable) (element-type utf8): a #GList containing URIs to launch. + * @context: (nullable): a #GAppLaunchContext or %NULL + * @cancellable: (nullable): a #GCancellable + * @callback: (nullable): a #GAsyncReadyCallback to call when the request is done + * @user_data: (nullable): data to pass to @callback + * + * Async version of g_app_info_launch_uris(). + * + * The @callback is invoked immediately after the application launch, but it + * waits for activation in case of D-Bus–activated applications and also provides + * extended error information for sandboxed applications, see notes for + * g_app_info_launch_default_for_uri_async(). + * + * Since: 2.60 + **/ +void +g_app_info_launch_uris_async (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *context, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GAppInfoIface *iface; + + g_return_if_fail (G_IS_APP_INFO (appinfo)); + g_return_if_fail (context == NULL || G_IS_APP_LAUNCH_CONTEXT (context)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + iface = G_APP_INFO_GET_IFACE (appinfo); + if (iface->launch_uris_async == NULL) + { + GTask *task; + + task = g_task_new (appinfo, cancellable, callback, user_data); + g_task_set_source_tag (task, g_app_info_launch_uris_async); + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Operation not supported for the current backend."); + g_object_unref (task); + + return; + } + + (* iface->launch_uris_async) (appinfo, uris, context, cancellable, callback, user_data); +} + +/** + * g_app_info_launch_uris_finish: + * @appinfo: a #GAppInfo + * @result: a #GAsyncResult + * @error: (nullable): a #GError + * + * Finishes a g_app_info_launch_uris_async() operation. + * + * Returns: %TRUE on successful launch, %FALSE otherwise. + * + * Since: 2.60 + */ +gboolean +g_app_info_launch_uris_finish (GAppInfo *appinfo, + GAsyncResult *result, + GError **error) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + if (iface->launch_uris_finish == NULL) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Operation not supported for the current backend."); + return FALSE; + } + + return (* iface->launch_uris_finish) (appinfo, result, error); +} + +/** + * g_app_info_should_show: + * @appinfo: a #GAppInfo. + * + * Checks if the application info should be shown in menus that + * list available applications. + * + * Returns: %TRUE if the @appinfo should be shown, %FALSE otherwise. + **/ +gboolean +g_app_info_should_show (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + return (* iface->should_show) (appinfo); +} + +/** + * g_app_info_launch_default_for_uri: + * @uri: the uri to show + * @context: (nullable): an optional #GAppLaunchContext + * @error: (nullable): return location for an error, or %NULL + * + * Utility function that launches the default application + * registered to handle the specified uri. Synchronous I/O + * is done on the uri to detect the type of the file if + * required. + * + * The D-Bus–activated applications don't have to be started if your application + * terminates too soon after this function. To prevent this, use + * g_app_info_launch_default_for_uri_async() instead. + * + * Returns: %TRUE on success, %FALSE on error. + **/ +gboolean +g_app_info_launch_default_for_uri (const char *uri, + GAppLaunchContext *launch_context, + GError **error) +{ + char *uri_scheme; + GAppInfo *app_info = NULL; + gboolean res = FALSE; + + /* g_file_query_default_handler() calls + * g_app_info_get_default_for_uri_scheme() too, but we have to do it + * here anyway in case GFile can't parse @uri correctly. + */ + uri_scheme = g_uri_parse_scheme (uri); + if (uri_scheme && uri_scheme[0] != '\0') + app_info = g_app_info_get_default_for_uri_scheme (uri_scheme); + g_free (uri_scheme); + + if (!app_info) + { + GFile *file; + + file = g_file_new_for_uri (uri); + app_info = g_file_query_default_handler (file, NULL, error); + g_object_unref (file); + } + + if (app_info) + { + GList l; + + l.data = (char *)uri; + l.next = l.prev = NULL; + res = g_app_info_launch_uris (app_info, &l, launch_context, error); + g_object_unref (app_info); + } + +#ifdef G_OS_UNIX + if (!res && glib_should_use_portal ()) + { + const char *parent_window = NULL; + + /* Reset any error previously set by launch_default_for_uri */ + g_clear_error (error); + + if (launch_context && launch_context->priv->envp) + parent_window = g_environ_getenv (launch_context->priv->envp, "PARENT_WINDOW_ID"); + + return g_openuri_portal_open_uri (uri, parent_window, error); + } +#endif + + return res; +} + +typedef struct +{ + gchar *uri; + GAppLaunchContext *context; +} LaunchDefaultForUriData; + +static void +launch_default_for_uri_data_free (LaunchDefaultForUriData *data) +{ + g_free (data->uri); + g_clear_object (&data->context); + g_free (data); +} + +#ifdef G_OS_UNIX +static void +launch_default_for_uri_portal_open_uri_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = G_TASK (user_data); + GError *error = NULL; + + if (g_openuri_portal_open_uri_finish (result, &error)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, g_steal_pointer (&error)); + g_object_unref (task); +} +#endif + +static void +launch_default_for_uri_portal_open_uri (GTask *task, GError *error) +{ +#ifdef G_OS_UNIX + LaunchDefaultForUriData *data = g_task_get_task_data (task); + GCancellable *cancellable = g_task_get_cancellable (task); + + if (glib_should_use_portal ()) + { + const char *parent_window = NULL; + + /* Reset any error previously set by launch_default_for_uri */ + g_error_free (error); + + if (data->context && data->context->priv->envp) + parent_window = g_environ_getenv (data->context->priv->envp, + "PARENT_WINDOW_ID"); + + g_openuri_portal_open_uri_async (data->uri, + parent_window, + cancellable, + launch_default_for_uri_portal_open_uri_cb, + g_steal_pointer (&task)); + return; + } +#endif + + g_task_return_error (task, g_steal_pointer (&error)); + g_object_unref (task); +} + +static void +launch_default_for_uri_launch_uris_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GAppInfo *app_info = G_APP_INFO (object); + GTask *task = G_TASK (user_data); + GError *error = NULL; + + if (g_app_info_launch_uris_finish (app_info, result, &error)) + { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + } + else + launch_default_for_uri_portal_open_uri (g_steal_pointer (&task), g_steal_pointer (&error)); +} + +static void +launch_default_for_uri_launch_uris (GTask *task, + GAppInfo *app_info) +{ + GCancellable *cancellable = g_task_get_cancellable (task); + GList l; + LaunchDefaultForUriData *data = g_task_get_task_data (task); + + l.data = (char *)data->uri; + l.next = l.prev = NULL; + g_app_info_launch_uris_async (app_info, + &l, + data->context, + cancellable, + launch_default_for_uri_launch_uris_cb, + g_steal_pointer (&task)); + g_object_unref (app_info); +} + +static void +launch_default_for_uri_default_handler_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GFile *file = G_FILE (object); + GTask *task = G_TASK (user_data); + GAppInfo *app_info = NULL; + GError *error = NULL; + + app_info = g_file_query_default_handler_finish (file, result, &error); + if (app_info) + launch_default_for_uri_launch_uris (g_steal_pointer (&task), g_steal_pointer (&app_info)); + else + launch_default_for_uri_portal_open_uri (g_steal_pointer (&task), g_steal_pointer (&error)); +} + +/** + * g_app_info_launch_default_for_uri_async: + * @uri: the uri to show + * @context: (nullable): an optional #GAppLaunchContext + * @cancellable: (nullable): a #GCancellable + * @callback: (nullable): a #GAsyncReadyCallback to call when the request is done + * @user_data: (nullable): data to pass to @callback + * + * Async version of g_app_info_launch_default_for_uri(). + * + * This version is useful if you are interested in receiving + * error information in the case where the application is + * sandboxed and the portal may present an application chooser + * dialog to the user. + * + * This is also useful if you want to be sure that the D-Bus–activated + * applications are really started before termination and if you are interested + * in receiving error information from their activation. + * + * Since: 2.50 + */ +void +g_app_info_launch_default_for_uri_async (const char *uri, + GAppLaunchContext *context, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + char *uri_scheme; + GAppInfo *app_info = NULL; + LaunchDefaultForUriData *data; + + g_return_if_fail (uri != NULL); + + task = g_task_new (NULL, cancellable, callback, user_data); + g_task_set_source_tag (task, g_app_info_launch_default_for_uri_async); + + data = g_new (LaunchDefaultForUriData, 1); + data->uri = g_strdup (uri); + data->context = (context != NULL) ? g_object_ref (context) : NULL; + g_task_set_task_data (task, g_steal_pointer (&data), (GDestroyNotify) launch_default_for_uri_data_free); + + /* g_file_query_default_handler_async() calls + * g_app_info_get_default_for_uri_scheme() too, but we have to do it + * here anyway in case GFile can't parse @uri correctly. + */ + uri_scheme = g_uri_parse_scheme (uri); + if (uri_scheme && uri_scheme[0] != '\0') + /* FIXME: The following still uses blocking calls. */ + app_info = g_app_info_get_default_for_uri_scheme (uri_scheme); + g_free (uri_scheme); + + if (!app_info) + { + GFile *file; + + file = g_file_new_for_uri (uri); + g_file_query_default_handler_async (file, + G_PRIORITY_DEFAULT, + cancellable, + launch_default_for_uri_default_handler_cb, + g_steal_pointer (&task)); + g_object_unref (file); + } + else + launch_default_for_uri_launch_uris (g_steal_pointer (&task), g_steal_pointer (&app_info)); +} + +/** + * g_app_info_launch_default_for_uri_finish: + * @result: a #GAsyncResult + * @error: (nullable): return location for an error, or %NULL + * + * Finishes an asynchronous launch-default-for-uri operation. + * + * Returns: %TRUE if the launch was successful, %FALSE if @error is set + * + * Since: 2.50 + */ +gboolean +g_app_info_launch_default_for_uri_finish (GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} + +/** + * g_app_info_can_delete: + * @appinfo: a #GAppInfo + * + * Obtains the information whether the #GAppInfo can be deleted. + * See g_app_info_delete(). + * + * Returns: %TRUE if @appinfo can be deleted + * + * Since: 2.20 + */ +gboolean +g_app_info_can_delete (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->can_delete) + return (* iface->can_delete) (appinfo); + + return FALSE; +} + + +/** + * g_app_info_delete: + * @appinfo: a #GAppInfo + * + * Tries to delete a #GAppInfo. + * + * On some platforms, there may be a difference between user-defined + * #GAppInfos which can be deleted, and system-wide ones which cannot. + * See g_app_info_can_delete(). + * + * Virtual: do_delete + * Returns: %TRUE if @appinfo has been deleted + * + * Since: 2.20 + */ +gboolean +g_app_info_delete (GAppInfo *appinfo) +{ + GAppInfoIface *iface; + + g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); + + iface = G_APP_INFO_GET_IFACE (appinfo); + + if (iface->do_delete) + return (* iface->do_delete) (appinfo); + + return FALSE; +} + + +enum { + LAUNCH_FAILED, + LAUNCHED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE_WITH_PRIVATE (GAppLaunchContext, g_app_launch_context, G_TYPE_OBJECT) + +/** + * g_app_launch_context_new: + * + * Creates a new application launch context. This is not normally used, + * instead you instantiate a subclass of this, such as #GdkAppLaunchContext. + * + * Returns: a #GAppLaunchContext. + **/ +GAppLaunchContext * +g_app_launch_context_new (void) +{ + return g_object_new (G_TYPE_APP_LAUNCH_CONTEXT, NULL); +} + +static void +g_app_launch_context_finalize (GObject *object) +{ + GAppLaunchContext *context = G_APP_LAUNCH_CONTEXT (object); + + g_strfreev (context->priv->envp); + + G_OBJECT_CLASS (g_app_launch_context_parent_class)->finalize (object); +} + +static void +g_app_launch_context_class_init (GAppLaunchContextClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = g_app_launch_context_finalize; + + /** + * GAppLaunchContext::launch-failed: + * @context: the object emitting the signal + * @startup_notify_id: the startup notification id for the failed launch + * + * The ::launch-failed signal is emitted when a #GAppInfo launch + * fails. The startup notification id is provided, so that the launcher + * can cancel the startup notification. + * + * Since: 2.36 + */ + signals[LAUNCH_FAILED] = g_signal_new (I_("launch-failed"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GAppLaunchContextClass, launch_failed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_STRING); + + /** + * GAppLaunchContext::launched: + * @context: the object emitting the signal + * @info: the #GAppInfo that was just launched + * @platform_data: additional platform-specific data for this launch + * + * The ::launched signal is emitted when a #GAppInfo is successfully + * launched. The @platform_data is an GVariant dictionary mapping + * strings to variants (ie a{sv}), which contains additional, + * platform-specific data about this launch. On UNIX, at least the + * "pid" and "startup-notification-id" keys will be present. + * + * Since: 2.36 + */ + signals[LAUNCHED] = g_signal_new (I_("launched"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GAppLaunchContextClass, launched), + NULL, NULL, + _g_cclosure_marshal_VOID__OBJECT_VARIANT, + G_TYPE_NONE, 2, + G_TYPE_APP_INFO, G_TYPE_VARIANT); + g_signal_set_va_marshaller (signals[LAUNCHED], + G_TYPE_FROM_CLASS (klass), + _g_cclosure_marshal_VOID__OBJECT_VARIANTv); +} + +static void +g_app_launch_context_init (GAppLaunchContext *context) +{ + context->priv = g_app_launch_context_get_instance_private (context); +} + +/** + * g_app_launch_context_setenv: + * @context: a #GAppLaunchContext + * @variable: (type filename): the environment variable to set + * @value: (type filename): the value for to set the variable to. + * + * Arranges for @variable to be set to @value in the child's + * environment when @context is used to launch an application. + * + * Since: 2.32 + */ +void +g_app_launch_context_setenv (GAppLaunchContext *context, + const char *variable, + const char *value) +{ + g_return_if_fail (G_IS_APP_LAUNCH_CONTEXT (context)); + g_return_if_fail (variable != NULL); + g_return_if_fail (value != NULL); + + if (!context->priv->envp) + context->priv->envp = g_get_environ (); + + context->priv->envp = + g_environ_setenv (context->priv->envp, variable, value, TRUE); +} + +/** + * g_app_launch_context_unsetenv: + * @context: a #GAppLaunchContext + * @variable: (type filename): the environment variable to remove + * + * Arranges for @variable to be unset in the child's environment + * when @context is used to launch an application. + * + * Since: 2.32 + */ +void +g_app_launch_context_unsetenv (GAppLaunchContext *context, + const char *variable) +{ + g_return_if_fail (G_IS_APP_LAUNCH_CONTEXT (context)); + g_return_if_fail (variable != NULL); + + if (!context->priv->envp) + context->priv->envp = g_get_environ (); + + context->priv->envp = + g_environ_unsetenv (context->priv->envp, variable); +} + +/** + * g_app_launch_context_get_environment: + * @context: a #GAppLaunchContext + * + * Gets the complete environment variable list to be passed to + * the child process when @context is used to launch an application. + * This is a %NULL-terminated array of strings, where each string has + * the form `KEY=VALUE`. + * + * Returns: (array zero-terminated=1) (element-type filename) (transfer full): + * the child's environment + * + * Since: 2.32 + */ +char ** +g_app_launch_context_get_environment (GAppLaunchContext *context) +{ + g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL); + + if (!context->priv->envp) + context->priv->envp = g_get_environ (); + + return g_strdupv (context->priv->envp); +} + +/** + * g_app_launch_context_get_display: + * @context: a #GAppLaunchContext + * @info: a #GAppInfo + * @files: (element-type GFile): a #GList of #GFile objects + * + * Gets the display string for the @context. This is used to ensure new + * applications are started on the same display as the launching + * application, by setting the `DISPLAY` environment variable. + * + * Returns: a display string for the display. + */ +char * +g_app_launch_context_get_display (GAppLaunchContext *context, + GAppInfo *info, + GList *files) +{ + GAppLaunchContextClass *class; + + g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL); + g_return_val_if_fail (G_IS_APP_INFO (info), NULL); + + class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context); + + if (class->get_display == NULL) + return NULL; + + return class->get_display (context, info, files); +} + +/** + * g_app_launch_context_get_startup_notify_id: + * @context: a #GAppLaunchContext + * @info: a #GAppInfo + * @files: (element-type GFile): a #GList of of #GFile objects + * + * Initiates startup notification for the application and returns the + * `DESKTOP_STARTUP_ID` for the launched operation, if supported. + * + * Startup notification IDs are defined in the + * [FreeDesktop.Org Startup Notifications standard](http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt). + * + * Returns: a startup notification ID for the application, or %NULL if + * not supported. + **/ +char * +g_app_launch_context_get_startup_notify_id (GAppLaunchContext *context, + GAppInfo *info, + GList *files) +{ + GAppLaunchContextClass *class; + + g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL); + g_return_val_if_fail (G_IS_APP_INFO (info), NULL); + + class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context); + + if (class->get_startup_notify_id == NULL) + return NULL; + + return class->get_startup_notify_id (context, info, files); +} + + +/** + * g_app_launch_context_launch_failed: + * @context: a #GAppLaunchContext. + * @startup_notify_id: the startup notification id that was returned by g_app_launch_context_get_startup_notify_id(). + * + * Called when an application has failed to launch, so that it can cancel + * the application startup notification started in g_app_launch_context_get_startup_notify_id(). + * + **/ +void +g_app_launch_context_launch_failed (GAppLaunchContext *context, + const char *startup_notify_id) +{ + g_return_if_fail (G_IS_APP_LAUNCH_CONTEXT (context)); + g_return_if_fail (startup_notify_id != NULL); + + g_signal_emit (context, signals[LAUNCH_FAILED], 0, startup_notify_id); +} + + +/** + * SECTION:gappinfomonitor + * @short_description: Monitor application information for changes + * + * #GAppInfoMonitor is a very simple object used for monitoring the app + * info database for changes (ie: newly installed or removed + * applications). + * + * Call g_app_info_monitor_get() to get a #GAppInfoMonitor and connect + * to the "changed" signal. + * + * In the usual case, applications should try to make note of the change + * (doing things like invalidating caches) but not act on it. In + * particular, applications should avoid making calls to #GAppInfo APIs + * in response to the change signal, deferring these until the time that + * the data is actually required. The exception to this case is when + * application information is actually being displayed on the screen + * (eg: during a search or when the list of all applications is shown). + * The reason for this is that changes to the list of installed + * applications often come in groups (like during system updates) and + * rescanning the list on every change is pointless and expensive. + * + * Since: 2.40 + **/ + +/** + * GAppInfoMonitor: + * + * The only thing you can do with this is to get it via + * g_app_info_monitor_get() and connect to the "changed" signal. + * + * Since: 2.40 + **/ + +typedef struct _GAppInfoMonitorClass GAppInfoMonitorClass; + +struct _GAppInfoMonitor +{ + GObject parent_instance; + GMainContext *context; +}; + +struct _GAppInfoMonitorClass +{ + GObjectClass parent_class; +}; + +static GContextSpecificGroup g_app_info_monitor_group; +static guint g_app_info_monitor_changed_signal; + +G_DEFINE_TYPE (GAppInfoMonitor, g_app_info_monitor, G_TYPE_OBJECT) + +static void +g_app_info_monitor_finalize (GObject *object) +{ + GAppInfoMonitor *monitor = G_APP_INFO_MONITOR (object); + + g_context_specific_group_remove (&g_app_info_monitor_group, monitor->context, monitor, NULL); + + G_OBJECT_CLASS (g_app_info_monitor_parent_class)->finalize (object); +} + +static void +g_app_info_monitor_init (GAppInfoMonitor *monitor) +{ +} + +static void +g_app_info_monitor_class_init (GAppInfoMonitorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + /** + * GAppInfoMonitor::changed: + * + * Signal emitted when the app info database for changes (ie: newly installed + * or removed applications). + **/ + g_app_info_monitor_changed_signal = g_signal_new (I_("changed"), G_TYPE_APP_INFO_MONITOR, G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + object_class->finalize = g_app_info_monitor_finalize; +} + +/** + * g_app_info_monitor_get: + * + * Gets the #GAppInfoMonitor for the current thread-default main + * context. + * + * The #GAppInfoMonitor will emit a "changed" signal in the + * thread-default main context whenever the list of installed + * applications (as reported by g_app_info_get_all()) may have changed. + * + * You must only call g_object_unref() on the return value from under + * the same main context as you created it. + * + * Returns: (transfer full): a reference to a #GAppInfoMonitor + * + * Since: 2.40 + **/ +GAppInfoMonitor * +g_app_info_monitor_get (void) +{ + return g_context_specific_group_get (&g_app_info_monitor_group, + G_TYPE_APP_INFO_MONITOR, + G_STRUCT_OFFSET (GAppInfoMonitor, context), + NULL); +} + +void +g_app_info_monitor_fire (void) +{ + g_context_specific_group_emit (&g_app_info_monitor_group, g_app_info_monitor_changed_signal); +}
diff --git a/gio/gappinfo.h b/gio/gappinfo.h new file mode 100644 index 0000000..d26d048 --- /dev/null +++ b/gio/gappinfo.h
@@ -0,0 +1,347 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_APP_INFO_H__ +#define __G_APP_INFO_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_APP_INFO (g_app_info_get_type ()) +#define G_APP_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_APP_INFO, GAppInfo)) +#define G_IS_APP_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_APP_INFO)) +#define G_APP_INFO_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_APP_INFO, GAppInfoIface)) + +#define G_TYPE_APP_LAUNCH_CONTEXT (g_app_launch_context_get_type ()) +#define G_APP_LAUNCH_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_APP_LAUNCH_CONTEXT, GAppLaunchContext)) +#define G_APP_LAUNCH_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_APP_LAUNCH_CONTEXT, GAppLaunchContextClass)) +#define G_IS_APP_LAUNCH_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_APP_LAUNCH_CONTEXT)) +#define G_IS_APP_LAUNCH_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_APP_LAUNCH_CONTEXT)) +#define G_APP_LAUNCH_CONTEXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_APP_LAUNCH_CONTEXT, GAppLaunchContextClass)) + +typedef struct _GAppLaunchContextClass GAppLaunchContextClass; +typedef struct _GAppLaunchContextPrivate GAppLaunchContextPrivate; + +/** + * GAppInfo: + * + * Information about an installed application and methods to launch + * it (with file arguments). + */ + +/** + * GAppInfoIface: + * @g_iface: The parent interface. + * @dup: Copies a #GAppInfo. + * @equal: Checks two #GAppInfos for equality. + * @get_id: Gets a string identifier for a #GAppInfo. + * @get_name: Gets the name of the application for a #GAppInfo. + * @get_description: Gets a short description for the application described by the #GAppInfo. + * @get_executable: Gets the executable name for the #GAppInfo. + * @get_icon: Gets the #GIcon for the #GAppInfo. + * @launch: Launches an application specified by the #GAppInfo. + * @supports_uris: Indicates whether the application specified supports launching URIs. + * @supports_files: Indicates whether the application specified accepts filename arguments. + * @launch_uris: Launches an application with a list of URIs. + * @should_show: Returns whether an application should be shown (e.g. when getting a list of installed applications). + * [FreeDesktop.Org Startup Notification Specification](http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt). + * @set_as_default_for_type: Sets an application as default for a given content type. + * @set_as_default_for_extension: Sets an application as default for a given file extension. + * @add_supports_type: Adds to the #GAppInfo information about supported file types. + * @can_remove_supports_type: Checks for support for removing supported file types from a #GAppInfo. + * @remove_supports_type: Removes a supported application type from a #GAppInfo. + * @can_delete: Checks if a #GAppInfo can be deleted. Since 2.20 + * @do_delete: Deletes a #GAppInfo. Since 2.20 + * @get_commandline: Gets the commandline for the #GAppInfo. Since 2.20 + * @get_display_name: Gets the display name for the #GAppInfo. Since 2.24 + * @set_as_last_used_for_type: Sets the application as the last used. See g_app_info_set_as_last_used_for_type(). + * @get_supported_types: Retrieves the list of content types that @app_info claims to support. + * @launch_uris_async: Asynchronously launches an application with a list of URIs. (Since: 2.60) + * @launch_uris_finish: Finishes an operation started with @launch_uris_async. (Since: 2.60) + + * Application Information interface, for operating system portability. + */ +typedef struct _GAppInfoIface GAppInfoIface; + +struct _GAppInfoIface +{ + GTypeInterface g_iface; + + /* Virtual Table */ + + GAppInfo * (* dup) (GAppInfo *appinfo); + gboolean (* equal) (GAppInfo *appinfo1, + GAppInfo *appinfo2); + const char * (* get_id) (GAppInfo *appinfo); + const char * (* get_name) (GAppInfo *appinfo); + const char * (* get_description) (GAppInfo *appinfo); + const char * (* get_executable) (GAppInfo *appinfo); + GIcon * (* get_icon) (GAppInfo *appinfo); + gboolean (* launch) (GAppInfo *appinfo, + GList *files, + GAppLaunchContext *context, + GError **error); + gboolean (* supports_uris) (GAppInfo *appinfo); + gboolean (* supports_files) (GAppInfo *appinfo); + gboolean (* launch_uris) (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *context, + GError **error); + gboolean (* should_show) (GAppInfo *appinfo); + + /* For changing associations */ + gboolean (* set_as_default_for_type) (GAppInfo *appinfo, + const char *content_type, + GError **error); + gboolean (* set_as_default_for_extension) (GAppInfo *appinfo, + const char *extension, + GError **error); + gboolean (* add_supports_type) (GAppInfo *appinfo, + const char *content_type, + GError **error); + gboolean (* can_remove_supports_type) (GAppInfo *appinfo); + gboolean (* remove_supports_type) (GAppInfo *appinfo, + const char *content_type, + GError **error); + gboolean (* can_delete) (GAppInfo *appinfo); + gboolean (* do_delete) (GAppInfo *appinfo); + const char * (* get_commandline) (GAppInfo *appinfo); + const char * (* get_display_name) (GAppInfo *appinfo); + gboolean (* set_as_last_used_for_type) (GAppInfo *appinfo, + const char *content_type, + GError **error); + const char ** (* get_supported_types) (GAppInfo *appinfo); + void (* launch_uris_async) (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *context, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* launch_uris_finish) (GAppInfo *appinfo, + GAsyncResult *result, + GError **error); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_app_info_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_ALL +GAppInfo * g_app_info_create_from_commandline (const char *commandline, + const char *application_name, + GAppInfoCreateFlags flags, + GError **error); +GLIB_AVAILABLE_IN_ALL +GAppInfo * g_app_info_dup (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_equal (GAppInfo *appinfo1, + GAppInfo *appinfo2); +GLIB_AVAILABLE_IN_ALL +const char *g_app_info_get_id (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +const char *g_app_info_get_name (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +const char *g_app_info_get_display_name (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +const char *g_app_info_get_description (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +const char *g_app_info_get_executable (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +const char *g_app_info_get_commandline (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +GIcon * g_app_info_get_icon (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_launch (GAppInfo *appinfo, + GList *files, + GAppLaunchContext *context, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_supports_uris (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_supports_files (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_launch_uris (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *context, + GError **error); +GLIB_AVAILABLE_IN_2_60 +void g_app_info_launch_uris_async (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *context, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GLIB_AVAILABLE_IN_2_60 +gboolean g_app_info_launch_uris_finish (GAppInfo *appinfo, + GAsyncResult *result, + GError **error); + +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_should_show (GAppInfo *appinfo); + +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_set_as_default_for_type (GAppInfo *appinfo, + const char *content_type, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_set_as_default_for_extension (GAppInfo *appinfo, + const char *extension, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_add_supports_type (GAppInfo *appinfo, + const char *content_type, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_can_remove_supports_type (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_remove_supports_type (GAppInfo *appinfo, + const char *content_type, + GError **error); +GLIB_AVAILABLE_IN_2_34 +const char **g_app_info_get_supported_types (GAppInfo *appinfo); + +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_can_delete (GAppInfo *appinfo); +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_delete (GAppInfo *appinfo); + +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_set_as_last_used_for_type (GAppInfo *appinfo, + const char *content_type, + GError **error); + +GLIB_AVAILABLE_IN_ALL +GList * g_app_info_get_all (void); +GLIB_AVAILABLE_IN_ALL +GList * g_app_info_get_all_for_type (const char *content_type); +GLIB_AVAILABLE_IN_ALL +GList * g_app_info_get_recommended_for_type (const gchar *content_type); +GLIB_AVAILABLE_IN_ALL +GList * g_app_info_get_fallback_for_type (const gchar *content_type); + +GLIB_AVAILABLE_IN_ALL +void g_app_info_reset_type_associations (const char *content_type); +GLIB_AVAILABLE_IN_ALL +GAppInfo *g_app_info_get_default_for_type (const char *content_type, + gboolean must_support_uris); +GLIB_AVAILABLE_IN_ALL +GAppInfo *g_app_info_get_default_for_uri_scheme (const char *uri_scheme); + +GLIB_AVAILABLE_IN_ALL +gboolean g_app_info_launch_default_for_uri (const char *uri, + GAppLaunchContext *context, + GError **error); + +GLIB_AVAILABLE_IN_2_50 +void g_app_info_launch_default_for_uri_async (const char *uri, + GAppLaunchContext *context, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GLIB_AVAILABLE_IN_2_50 +gboolean g_app_info_launch_default_for_uri_finish (GAsyncResult *result, + GError **error); + + +/** + * GAppLaunchContext: + * + * Integrating the launch with the launching application. This is used to + * handle for instance startup notification and launching the new application + * on the same screen as the launching window. + */ +struct _GAppLaunchContext +{ + GObject parent_instance; + + /*< private >*/ + GAppLaunchContextPrivate *priv; +}; + +struct _GAppLaunchContextClass +{ + GObjectClass parent_class; + + char * (* get_display) (GAppLaunchContext *context, + GAppInfo *info, + GList *files); + char * (* get_startup_notify_id) (GAppLaunchContext *context, + GAppInfo *info, + GList *files); + void (* launch_failed) (GAppLaunchContext *context, + const char *startup_notify_id); + void (* launched) (GAppLaunchContext *context, + GAppInfo *info, + GVariant *platform_data); + + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_app_launch_context_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_ALL +GAppLaunchContext *g_app_launch_context_new (void); + +GLIB_AVAILABLE_IN_2_32 +void g_app_launch_context_setenv (GAppLaunchContext *context, + const char *variable, + const char *value); +GLIB_AVAILABLE_IN_2_32 +void g_app_launch_context_unsetenv (GAppLaunchContext *context, + const char *variable); +GLIB_AVAILABLE_IN_2_32 +char ** g_app_launch_context_get_environment (GAppLaunchContext *context); + +GLIB_AVAILABLE_IN_ALL +char * g_app_launch_context_get_display (GAppLaunchContext *context, + GAppInfo *info, + GList *files); +GLIB_AVAILABLE_IN_ALL +char * g_app_launch_context_get_startup_notify_id (GAppLaunchContext *context, + GAppInfo *info, + GList *files); +GLIB_AVAILABLE_IN_ALL +void g_app_launch_context_launch_failed (GAppLaunchContext *context, + const char * startup_notify_id); + +#define G_TYPE_APP_INFO_MONITOR (g_app_info_monitor_get_type ()) +#define G_APP_INFO_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_APP_INFO_MONITOR, GAppInfoMonitor)) +#define G_IS_APP_INFO_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + G_TYPE_APP_INFO_MONITOR)) + +typedef struct _GAppInfoMonitor GAppInfoMonitor; + +GLIB_AVAILABLE_IN_2_40 +GType g_app_info_monitor_get_type (void); + +GLIB_AVAILABLE_IN_2_40 +GAppInfoMonitor * g_app_info_monitor_get (void); + +G_END_DECLS + +#endif /* __G_APP_INFO_H__ */
diff --git a/gio/gappinfoprivate.h b/gio/gappinfoprivate.h new file mode 100644 index 0000000..f8b0f48 --- /dev/null +++ b/gio/gappinfoprivate.h
@@ -0,0 +1,26 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2013 Canonical Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_APP_INFO_PRIVATE_H__ +#define __G_APP_INFO_PRIVATE_H__ + +void g_app_info_monitor_fire (void); + +#endif /* __G_APP_INFO_PRIVATE_H__ */
diff --git a/gio/gapplication-tool.c b/gio/gapplication-tool.c new file mode 100644 index 0000000..68a7424 --- /dev/null +++ b/gio/gapplication-tool.c
@@ -0,0 +1,469 @@ +/* + * Copyright © 2013 Canonical Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" + +#include <gio/gdesktopappinfo.h> + +#include <glib/gi18n.h> +#include <gio/gio.h> + +#include <string.h> +#include <locale.h> + +struct help_topic +{ + const gchar *command; + const gchar *summary; + const gchar *description; + const gchar *synopsis; +}; + +struct help_substvar +{ + const gchar *var; + const gchar *description; +}; + +static const struct help_topic topics[] = { + { "help", N_("Print help"), + N_("Print help"), + N_("[COMMAND]") + }, + { "version", N_("Print version"), + N_("Print version information and exit") + }, + { "list-apps", N_("List applications"), + N_("List the installed D-Bus activatable applications (by .desktop files)") + }, + { "launch", N_("Launch an application"), + N_("Launch the application (with optional files to open)"), + N_("APPID [FILE…]") + }, + { "action", N_("Activate an action"), + N_("Invoke an action on the application"), + N_("APPID ACTION [PARAMETER]") + }, + { "list-actions", N_("List available actions"), + N_("List static actions for an application (from .desktop file)"), + N_("APPID") + } +}; + +static const struct help_substvar substvars[] = { + { N_("COMMAND"), N_("The command to print detailed help for") }, + { N_("APPID"), N_("Application identifier in D-Bus format (eg: org.example.viewer)") }, + { N_("FILE"), N_("Optional relative or absolute filenames, or URIs to open") }, + { N_("ACTION"), N_("The action name to invoke") }, + { N_("PARAMETER"), N_("Optional parameter to the action invocation, in GVariant format") } +}; + +static int +app_help (gboolean requested, + const gchar *command) +{ + const struct help_topic *topic = NULL; + GString *string; + + string = g_string_new (NULL); + + if (command) + { + gint i; + + for (i = 0; i < G_N_ELEMENTS (topics); i++) + if (g_str_equal (topics[i].command, command)) + topic = &topics[i]; + + if (!topic) + { + g_string_printf (string, _("Unknown command %s\n\n"), command); + requested = FALSE; + } + } + + g_string_append (string, _("Usage:\n")); + + if (topic) + { + gint maxwidth; + gint i; + + g_string_append_printf (string, "\n %s %s %s\n\n", "gapplication", + topic->command, topic->synopsis ? _(topic->synopsis) : ""); + g_string_append_printf (string, "%s\n\n", _(topic->description)); + + if (topic->synopsis) + { + g_string_append (string, _("Arguments:\n")); + + maxwidth = 0; + for (i = 0; i < G_N_ELEMENTS (substvars); i++) + if (strstr (topic->synopsis, substvars[i].var)) + maxwidth = MAX(maxwidth, strlen (_(substvars[i].var))); + + for (i = 0; i < G_N_ELEMENTS (substvars); i++) + if (strstr (topic->synopsis, substvars[i].var)) + g_string_append_printf (string, " %-*.*s %s\n", maxwidth, maxwidth, + _(substvars[i].var), _(substvars[i].description)); + g_string_append (string, "\n"); + } + } + else + { + gint maxwidth; + gint i; + + g_string_append_printf (string, "\n %s %s %s\n\n", "gapplication", _("COMMAND"), _("[ARGS…]")); + g_string_append_printf (string, _("Commands:\n")); + + maxwidth = 0; + for (i = 0; i < G_N_ELEMENTS (topics); i++) + maxwidth = MAX(maxwidth, strlen (topics[i].command)); + + for (i = 0; i < G_N_ELEMENTS (topics); i++) + g_string_append_printf (string, " %-*.*s %s\n", maxwidth, maxwidth, + topics[i].command, _(topics[i].summary)); + + g_string_append (string, "\n"); + /* Translators: do not translate 'help', but please translate 'COMMAND'. */ + g_string_append_printf (string, _("Use “%s help COMMAND” to get detailed help.\n\n"), "gapplication"); + } + + if (requested) + g_print ("%s", string->str); + else + g_printerr ("%s\n", string->str); + + g_string_free (string, TRUE); + + return requested ? 0 : 1; +} + +static gboolean +app_check_name (gchar **args, + const gchar *command) +{ + if (args[0] == NULL) + { + g_printerr (_("%s command requires an application id to directly follow\n\n"), command); + return FALSE; + } + + if (!g_dbus_is_name (args[0])) + { + g_printerr (_("invalid application id: “%s”\n"), args[0]); + return FALSE; + } + + return TRUE; +} + +static int +app_no_args (const gchar *command) +{ + /* Translators: %s is replaced with a command name like 'list-actions' */ + g_printerr (_("“%s” takes no arguments\n\n"), command); + return app_help (FALSE, command); +} + +static int +app_version (gchar **args) +{ + if (g_strv_length (args)) + return app_no_args ("version"); + + g_print (PACKAGE_VERSION "\n"); + return 0; +} + +static int +app_list (gchar **args) +{ + GList *apps; + + if (g_strv_length (args)) + return app_no_args ("list"); + + apps = g_app_info_get_all (); + + while (apps) + { + GDesktopAppInfo *info = apps->data; + + if (G_IS_DESKTOP_APP_INFO (info)) + if (g_desktop_app_info_get_boolean (info, "DBusActivatable")) + { + const gchar *filename; + + filename = g_app_info_get_id (G_APP_INFO (info)); + if (g_str_has_suffix (filename, ".desktop")) + { + gchar *id; + + id = g_strndup (filename, strlen (filename) - 8); + g_print ("%s\n", id); + g_free (id); + } + } + + apps = g_list_delete_link (apps, apps); + g_object_unref (info); + } + + return 0; +} + +static gchar * +app_path_for_id (const gchar *app_id) +{ + gchar *path; + gint i; + + path = g_strconcat ("/", app_id, NULL); + for (i = 0; path[i]; i++) + { + if (path[i] == '.') + path[i] = '/'; + if (path[i] == '-') + path[i] = '_'; + } + + return path; +} + +static int +app_call (const gchar *app_id, + const gchar *method_name, + GVariant *parameters) +{ + GDBusConnection *session; + GError *error = NULL; + gchar *object_path; + GVariant *result; + + + session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + if (!session) + { + g_variant_unref (g_variant_ref_sink (parameters)); + g_printerr (_("unable to connect to D-Bus: %s\n"), error->message); + g_error_free (error); + return 1; + } + + object_path = app_path_for_id (app_id); + + result = g_dbus_connection_call_sync (session, app_id, object_path, "org.freedesktop.Application", + method_name, parameters, G_VARIANT_TYPE_UNIT, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + + g_free (object_path); + + if (result) + { + g_variant_unref (result); + return 0; + } + else + { + g_printerr (_("error sending %s message to application: %s\n"), method_name, error->message); + g_error_free (error); + return 1; + } +} + +static GVariant * +app_get_platform_data (void) +{ + GVariantBuilder builder; + const gchar *startup_id; + + g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + + if ((startup_id = g_getenv ("DESKTOP_STARTUP_ID"))) + g_variant_builder_add (&builder, "{sv}", "desktop-startup-id", g_variant_new_string (startup_id)); + + return g_variant_builder_end (&builder); +} + +static int +app_action (gchar **args) +{ + GVariantBuilder params; + const gchar *name; + + if (!app_check_name (args, "action")) + return 1; + + if (args[1] == NULL) + { + g_printerr (_("action name must be given after application id\n")); + return 1; + } + + name = args[1]; + + if (!g_action_name_is_valid (name)) + { + g_printerr (_("invalid action name: “%s”\n" + "action names must consist of only alphanumerics, “-” and “.”\n"), name); + return 1; + } + + g_variant_builder_init (¶ms, G_VARIANT_TYPE ("av")); + + if (args[2]) + { + GError *error = NULL; + GVariant *parameter; + + parameter = g_variant_parse (NULL, args[2], NULL, NULL, &error); + + if (!parameter) + { + gchar *context; + + context = g_variant_parse_error_print_context (error, args[2]); + g_printerr (_("error parsing action parameter: %s\n"), context); + g_variant_builder_clear (¶ms); + g_error_free (error); + g_free (context); + return 1; + } + + g_variant_builder_add (¶ms, "v", parameter); + g_variant_unref (parameter); + + if (args[3]) + { + g_printerr (_("actions accept a maximum of one parameter\n")); + g_variant_builder_clear (¶ms); + return 1; + } + } + + return app_call (args[0], "ActivateAction", g_variant_new ("(sav@a{sv})", name, ¶ms, app_get_platform_data ())); +} + +static int +app_activate (const gchar *app_id) +{ + return app_call (app_id, "Activate", g_variant_new ("(@a{sv})", app_get_platform_data ())); +} + +static int +app_launch (gchar **args) +{ + GVariantBuilder files; + gint i; + + if (!app_check_name (args, "launch")) + return 1; + + if (args[1] == NULL) + return app_activate (args[0]); + + g_variant_builder_init (&files, G_VARIANT_TYPE_STRING_ARRAY); + + for (i = 1; args[i]; i++) + { + GFile *file; + + /* "This operation never fails" */ + file = g_file_new_for_commandline_arg (args[i]); + g_variant_builder_add_value (&files, g_variant_new_take_string (g_file_get_uri (file))); + g_object_unref (file); + } + + return app_call (args[0], "Open", g_variant_new ("(as@a{sv})", &files, app_get_platform_data ())); +} + +static int +app_list_actions (gchar **args) +{ + const gchar * const *actions; + GDesktopAppInfo *app_info; + gchar *filename; + gint i; + + if (!app_check_name (args, "list-actions")) + return 1; + + if (args[1]) + { + g_printerr (_("list-actions command takes only the application id")); + app_help (FALSE, "list-actions"); + } + + filename = g_strconcat (args[0], ".desktop", NULL); + app_info = g_desktop_app_info_new (filename); + g_free (filename); + + if (app_info == NULL) + { + g_printerr (_("unable to find desktop file for application %s\n"), args[0]); + return 1; + } + + actions = g_desktop_app_info_list_actions (app_info); + + for (i = 0; actions[i]; i++) + g_print ("%s\n", actions[i]); + + g_object_unref (app_info); + + return 0; +} + +int +main (int argc, char **argv) +{ + setlocale (LC_ALL, ""); + textdomain (GETTEXT_PACKAGE); + bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR); +#ifdef HAVE_BIND_TEXTDOMAIN_CODESET + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + if (argc < 2) + return app_help (TRUE, NULL); + + if (g_str_equal (argv[1], "help")) + return app_help (TRUE, argv[2]); + + if (g_str_equal (argv[1], "version")) + return app_version (argv + 2); + + if (g_str_equal (argv[1], "list-apps")) + return app_list (argv + 2); + + if (g_str_equal (argv[1], "launch")) + return app_launch (argv + 2); + + if (g_str_equal (argv[1], "action")) + return app_action (argv + 2); + + if (g_str_equal (argv[1], "list-actions")) + return app_list_actions (argv + 2); + + g_printerr (_("unrecognised command: %s\n\n"), argv[1]); + + return app_help (FALSE, NULL); +}
diff --git a/gio/gapplication.c b/gio/gapplication.c new file mode 100644 index 0000000..b78fd9a --- /dev/null +++ b/gio/gapplication.c
@@ -0,0 +1,3116 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +/* Prologue {{{1 */ +#include "config.h" + +#include "gapplication.h" + +#include "gapplicationcommandline.h" +#include "gsimpleactiongroup.h" +#include "gremoteactiongroup.h" +#include "gapplicationimpl.h" +#include "gactiongroup.h" +#include "gactionmap.h" +#include "gsettings.h" +#include "gnotification-private.h" +#include "gnotificationbackend.h" +#include "gdbusutils.h" + +#include "gioenumtypes.h" +#include "gioenums.h" +#include "gfile.h" + +#include "glibintl.h" +#include "gmarshal-internal.h" + +#include <string.h> + +/** + * SECTION:gapplication + * @title: GApplication + * @short_description: Core application class + * @include: gio/gio.h + * + * A #GApplication is the foundation of an application. It wraps some + * low-level platform-specific services and is intended to act as the + * foundation for higher-level application classes such as + * #GtkApplication or #MxApplication. In general, you should not use + * this class outside of a higher level framework. + * + * GApplication provides convenient life cycle management by maintaining + * a "use count" for the primary application instance. The use count can + * be changed using g_application_hold() and g_application_release(). If + * it drops to zero, the application exits. Higher-level classes such as + * #GtkApplication employ the use count to ensure that the application + * stays alive as long as it has any opened windows. + * + * Another feature that GApplication (optionally) provides is process + * uniqueness. Applications can make use of this functionality by + * providing a unique application ID. If given, only one application + * with this ID can be running at a time per session. The session + * concept is platform-dependent, but corresponds roughly to a graphical + * desktop login. When your application is launched again, its + * arguments are passed through platform communication to the already + * running program. The already running instance of the program is + * called the "primary instance"; for non-unique applications this is + * always the current instance. On Linux, the D-Bus session bus + * is used for communication. + * + * The use of #GApplication differs from some other commonly-used + * uniqueness libraries (such as libunique) in important ways. The + * application is not expected to manually register itself and check + * if it is the primary instance. Instead, the main() function of a + * #GApplication should do very little more than instantiating the + * application instance, possibly connecting signal handlers, then + * calling g_application_run(). All checks for uniqueness are done + * internally. If the application is the primary instance then the + * startup signal is emitted and the mainloop runs. If the application + * is not the primary instance then a signal is sent to the primary + * instance and g_application_run() promptly returns. See the code + * examples below. + * + * If used, the expected form of an application identifier is the same as + * that of of a + * [D-Bus well-known bus name](https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-bus). + * Examples include: `com.example.MyApp`, `org.example.internal_apps.Calculator`, + * `org._7_zip.Archiver`. + * For details on valid application identifiers, see g_application_id_is_valid(). + * + * On Linux, the application identifier is claimed as a well-known bus name + * on the user's session bus. This means that the uniqueness of your + * application is scoped to the current session. It also means that your + * application may provide additional services (through registration of other + * object paths) at that bus name. The registration of these object paths + * should be done with the shared GDBus session bus. Note that due to the + * internal architecture of GDBus, method calls can be dispatched at any time + * (even if a main loop is not running). For this reason, you must ensure that + * any object paths that you wish to register are registered before #GApplication + * attempts to acquire the bus name of your application (which happens in + * g_application_register()). Unfortunately, this means that you cannot use + * g_application_get_is_remote() to decide if you want to register object paths. + * + * GApplication also implements the #GActionGroup and #GActionMap + * interfaces and lets you easily export actions by adding them with + * g_action_map_add_action(). When invoking an action by calling + * g_action_group_activate_action() on the application, it is always + * invoked in the primary instance. The actions are also exported on + * the session bus, and GIO provides the #GDBusActionGroup wrapper to + * conveniently access them remotely. GIO provides a #GDBusMenuModel wrapper + * for remote access to exported #GMenuModels. + * + * There is a number of different entry points into a GApplication: + * + * - via 'Activate' (i.e. just starting the application) + * + * - via 'Open' (i.e. opening some files) + * + * - by handling a command-line + * + * - via activating an action + * + * The #GApplication::startup signal lets you handle the application + * initialization for all of these in a single place. + * + * Regardless of which of these entry points is used to start the + * application, GApplication passes some ‘platform data’ from the + * launching instance to the primary instance, in the form of a + * #GVariant dictionary mapping strings to variants. To use platform + * data, override the @before_emit or @after_emit virtual functions + * in your #GApplication subclass. When dealing with + * #GApplicationCommandLine objects, the platform data is + * directly available via g_application_command_line_get_cwd(), + * g_application_command_line_get_environ() and + * g_application_command_line_get_platform_data(). + * + * As the name indicates, the platform data may vary depending on the + * operating system, but it always includes the current directory (key + * "cwd"), and optionally the environment (ie the set of environment + * variables and their values) of the calling process (key "environ"). + * The environment is only added to the platform data if the + * %G_APPLICATION_SEND_ENVIRONMENT flag is set. #GApplication subclasses + * can add their own platform data by overriding the @add_platform_data + * virtual function. For instance, #GtkApplication adds startup notification + * data in this way. + * + * To parse commandline arguments you may handle the + * #GApplication::command-line signal or override the local_command_line() + * vfunc, to parse them in either the primary instance or the local instance, + * respectively. + * + * For an example of opening files with a GApplication, see + * [gapplication-example-open.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-open.c). + * + * For an example of using actions with GApplication, see + * [gapplication-example-actions.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-actions.c). + * + * For an example of using extra D-Bus hooks with GApplication, see + * [gapplication-example-dbushooks.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-dbushooks.c). + */ + +/** + * GApplication: + * + * #GApplication is an opaque data structure and can only be accessed + * using the following functions. + * Since: 2.28 + */ + +/** + * GApplicationClass: + * @startup: invoked on the primary instance immediately after registration + * @shutdown: invoked only on the registered primary instance immediately + * after the main loop terminates + * @activate: invoked on the primary instance when an activation occurs + * @open: invoked on the primary instance when there are files to open + * @command_line: invoked on the primary instance when a command-line is + * not handled locally + * @local_command_line: invoked (locally). The virtual function has the chance + * to inspect (and possibly replace) command line arguments. See + * g_application_run() for more information. Also see the + * #GApplication::handle-local-options signal, which is a simpler + * alternative to handling some commandline options locally + * @before_emit: invoked on the primary instance before 'activate', 'open', + * 'command-line' or any action invocation, gets the 'platform data' from + * the calling instance + * @after_emit: invoked on the primary instance after 'activate', 'open', + * 'command-line' or any action invocation, gets the 'platform data' from + * the calling instance + * @add_platform_data: invoked (locally) to add 'platform data' to be sent to + * the primary instance when activating, opening or invoking actions + * @quit_mainloop: Used to be invoked on the primary instance when the use + * count of the application drops to zero (and after any inactivity + * timeout, if requested). Not used anymore since 2.32 + * @run_mainloop: Used to be invoked on the primary instance from + * g_application_run() if the use-count is non-zero. Since 2.32, + * GApplication is iterating the main context directly and is not + * using @run_mainloop anymore + * @dbus_register: invoked locally during registration, if the application is + * using its D-Bus backend. You can use this to export extra objects on the + * bus, that need to exist before the application tries to own the bus name. + * The function is passed the #GDBusConnection to to session bus, and the + * object path that #GApplication will use to export is D-Bus API. + * If this function returns %TRUE, registration will proceed; otherwise + * registration will abort. Since: 2.34 + * @dbus_unregister: invoked locally during unregistration, if the application + * is using its D-Bus backend. Use this to undo anything done by + * the @dbus_register vfunc. Since: 2.34 + * @handle_local_options: invoked locally after the parsing of the commandline + * options has occurred. Since: 2.40 + * @name_lost: invoked when another instance is taking over the name. Since: 2.60 + * + * Virtual function table for #GApplication. + * + * Since: 2.28 + */ + +struct _GApplicationPrivate +{ + GApplicationFlags flags; + gchar *id; + gchar *resource_path; + + GActionGroup *actions; + + guint inactivity_timeout_id; + guint inactivity_timeout; + guint use_count; + guint busy_count; + + guint is_registered : 1; + guint is_remote : 1; + guint did_startup : 1; + guint did_shutdown : 1; + guint must_quit_now : 1; + + GRemoteActionGroup *remote_actions; + GApplicationImpl *impl; + + GNotificationBackend *notifications; + + /* GOptionContext support */ + GOptionGroup *main_options; + GSList *option_groups; + GHashTable *packed_options; + gboolean options_parsed; + gchar *parameter_string; + gchar *summary; + gchar *description; + + /* Allocated option strings, from g_application_add_main_option() */ + GSList *option_strings; +}; + +enum +{ + PROP_NONE, + PROP_APPLICATION_ID, + PROP_FLAGS, + PROP_RESOURCE_BASE_PATH, + PROP_IS_REGISTERED, + PROP_IS_REMOTE, + PROP_INACTIVITY_TIMEOUT, + PROP_ACTION_GROUP, + PROP_IS_BUSY +}; + +enum +{ + SIGNAL_STARTUP, + SIGNAL_SHUTDOWN, + SIGNAL_ACTIVATE, + SIGNAL_OPEN, + SIGNAL_ACTION, + SIGNAL_COMMAND_LINE, + SIGNAL_HANDLE_LOCAL_OPTIONS, + SIGNAL_NAME_LOST, + NR_SIGNALS +}; + +static guint g_application_signals[NR_SIGNALS]; + +static void g_application_action_group_iface_init (GActionGroupInterface *); +static void g_application_action_map_iface_init (GActionMapInterface *); +G_DEFINE_TYPE_WITH_CODE (GApplication, g_application, G_TYPE_OBJECT, + G_ADD_PRIVATE (GApplication) + G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, g_application_action_group_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_MAP, g_application_action_map_iface_init)) + +/* GApplicationExportedActions {{{1 */ + +/* We create a subclass of GSimpleActionGroup that implements + * GRemoteActionGroup and deals with the platform data using + * GApplication's before/after_emit vfuncs. This is the action group we + * will be exporting. + * + * We could implement GRemoteActionGroup on GApplication directly, but + * this would be potentially extremely confusing to have exposed as part + * of the public API of GApplication. We certainly don't want anyone in + * the same process to be calling these APIs... + */ +typedef GSimpleActionGroupClass GApplicationExportedActionsClass; +typedef struct +{ + GSimpleActionGroup parent_instance; + GApplication *application; +} GApplicationExportedActions; + +static GType g_application_exported_actions_get_type (void); +static void g_application_exported_actions_iface_init (GRemoteActionGroupInterface *iface); +G_DEFINE_TYPE_WITH_CODE (GApplicationExportedActions, g_application_exported_actions, G_TYPE_SIMPLE_ACTION_GROUP, + G_IMPLEMENT_INTERFACE (G_TYPE_REMOTE_ACTION_GROUP, g_application_exported_actions_iface_init)) + +static void +g_application_exported_actions_activate_action_full (GRemoteActionGroup *remote, + const gchar *action_name, + GVariant *parameter, + GVariant *platform_data) +{ + GApplicationExportedActions *exported = (GApplicationExportedActions *) remote; + + G_APPLICATION_GET_CLASS (exported->application) + ->before_emit (exported->application, platform_data); + + g_action_group_activate_action (G_ACTION_GROUP (exported), action_name, parameter); + + G_APPLICATION_GET_CLASS (exported->application) + ->after_emit (exported->application, platform_data); +} + +static void +g_application_exported_actions_change_action_state_full (GRemoteActionGroup *remote, + const gchar *action_name, + GVariant *value, + GVariant *platform_data) +{ + GApplicationExportedActions *exported = (GApplicationExportedActions *) remote; + + G_APPLICATION_GET_CLASS (exported->application) + ->before_emit (exported->application, platform_data); + + g_action_group_change_action_state (G_ACTION_GROUP (exported), action_name, value); + + G_APPLICATION_GET_CLASS (exported->application) + ->after_emit (exported->application, platform_data); +} + +static void +g_application_exported_actions_init (GApplicationExportedActions *actions) +{ +} + +static void +g_application_exported_actions_iface_init (GRemoteActionGroupInterface *iface) +{ + iface->activate_action_full = g_application_exported_actions_activate_action_full; + iface->change_action_state_full = g_application_exported_actions_change_action_state_full; +} + +static void +g_application_exported_actions_class_init (GApplicationExportedActionsClass *class) +{ +} + +static GActionGroup * +g_application_exported_actions_new (GApplication *application) +{ + GApplicationExportedActions *actions; + + actions = g_object_new (g_application_exported_actions_get_type (), NULL); + actions->application = application; + + return G_ACTION_GROUP (actions); +} + +/* Command line option handling {{{1 */ + +static void +free_option_entry (gpointer data) +{ + GOptionEntry *entry = data; + + switch (entry->arg) + { + case G_OPTION_ARG_STRING: + case G_OPTION_ARG_FILENAME: + g_free (*(gchar **) entry->arg_data); + break; + + case G_OPTION_ARG_STRING_ARRAY: + case G_OPTION_ARG_FILENAME_ARRAY: + g_strfreev (*(gchar ***) entry->arg_data); + break; + + default: + /* most things require no free... */ + break; + } + + /* ...except for the space that we allocated for it ourselves */ + g_free (entry->arg_data); + + g_slice_free (GOptionEntry, entry); +} + +static void +g_application_pack_option_entries (GApplication *application, + GVariantDict *dict) +{ + GHashTableIter iter; + gpointer item; + + g_hash_table_iter_init (&iter, application->priv->packed_options); + while (g_hash_table_iter_next (&iter, NULL, &item)) + { + GOptionEntry *entry = item; + GVariant *value = NULL; + + switch (entry->arg) + { + case G_OPTION_ARG_NONE: + if (*(gboolean *) entry->arg_data != 2) + value = g_variant_new_boolean (*(gboolean *) entry->arg_data); + break; + + case G_OPTION_ARG_STRING: + if (*(gchar **) entry->arg_data) + value = g_variant_new_string (*(gchar **) entry->arg_data); + break; + + case G_OPTION_ARG_INT: + if (*(gint32 *) entry->arg_data) + value = g_variant_new_int32 (*(gint32 *) entry->arg_data); + break; + + case G_OPTION_ARG_FILENAME: + if (*(gchar **) entry->arg_data) + value = g_variant_new_bytestring (*(gchar **) entry->arg_data); + break; + + case G_OPTION_ARG_STRING_ARRAY: + if (*(gchar ***) entry->arg_data) + value = g_variant_new_strv (*(const gchar ***) entry->arg_data, -1); + break; + + case G_OPTION_ARG_FILENAME_ARRAY: + if (*(gchar ***) entry->arg_data) + value = g_variant_new_bytestring_array (*(const gchar ***) entry->arg_data, -1); + break; + + case G_OPTION_ARG_DOUBLE: + if (*(gdouble *) entry->arg_data) + value = g_variant_new_double (*(gdouble *) entry->arg_data); + break; + + case G_OPTION_ARG_INT64: + if (*(gint64 *) entry->arg_data) + value = g_variant_new_int64 (*(gint64 *) entry->arg_data); + break; + + default: + g_assert_not_reached (); + } + + if (value) + g_variant_dict_insert_value (dict, entry->long_name, value); + } +} + +static GVariantDict * +g_application_parse_command_line (GApplication *application, + gchar ***arguments, + GError **error) +{ + gboolean become_service = FALSE; + gchar *app_id = NULL; + gboolean replace = FALSE; + GVariantDict *dict = NULL; + GOptionContext *context; + GOptionGroup *gapplication_group; + + /* Due to the memory management of GOptionGroup we can only parse + * options once. That's because once you add a group to the + * GOptionContext there is no way to get it back again. This is fine: + * local_command_line() should never get invoked more than once + * anyway. Add a sanity check just to be sure. + */ + g_return_val_if_fail (!application->priv->options_parsed, NULL); + + context = g_option_context_new (application->priv->parameter_string); + g_option_context_set_summary (context, application->priv->summary); + g_option_context_set_description (context, application->priv->description); + + gapplication_group = g_option_group_new ("gapplication", + _("GApplication options"), _("Show GApplication options"), + NULL, NULL); + g_option_group_set_translation_domain (gapplication_group, GETTEXT_PACKAGE); + g_option_context_add_group (context, gapplication_group); + + /* If the application has not registered local options and it has + * G_APPLICATION_HANDLES_COMMAND_LINE then we have to assume that + * their primary instance commandline handler may want to deal with + * the arguments. We must therefore ignore them. + * + * We must also ignore --help in this case since some applications + * will try to handle this from the remote side. See #737869. + */ + if (application->priv->main_options == NULL && (application->priv->flags & G_APPLICATION_HANDLES_COMMAND_LINE)) + { + g_option_context_set_ignore_unknown_options (context, TRUE); + g_option_context_set_help_enabled (context, FALSE); + } + + /* Add the main option group, if it exists */ + if (application->priv->main_options) + { + /* This consumes the main_options */ + g_option_context_set_main_group (context, application->priv->main_options); + application->priv->main_options = NULL; + } + + /* Add any other option groups if they exist. Adding them to the + * context will consume them, so we free the list as we go... + */ + while (application->priv->option_groups) + { + g_option_context_add_group (context, application->priv->option_groups->data); + application->priv->option_groups = g_slist_delete_link (application->priv->option_groups, + application->priv->option_groups); + } + + /* In the case that we are not explicitly marked as a service or a + * launcher then we want to add the "--gapplication-service" option to + * allow the process to be made into a service. + */ + if ((application->priv->flags & (G_APPLICATION_IS_SERVICE | G_APPLICATION_IS_LAUNCHER)) == 0) + { + GOptionEntry entries[] = { + { "gapplication-service", '\0', 0, G_OPTION_ARG_NONE, &become_service, + N_("Enter GApplication service mode (use from D-Bus service files)") }, + { NULL } + }; + + g_option_group_add_entries (gapplication_group, entries); + } + + /* Allow overriding the ID if the application allows it */ + if (application->priv->flags & G_APPLICATION_CAN_OVERRIDE_APP_ID) + { + GOptionEntry entries[] = { + { "gapplication-app-id", '\0', 0, G_OPTION_ARG_STRING, &app_id, + N_("Override the application’s ID") }, + { NULL } + }; + + g_option_group_add_entries (gapplication_group, entries); + } + + /* Allow replacing if the application allows it */ + if (application->priv->flags & G_APPLICATION_ALLOW_REPLACEMENT) + { + GOptionEntry entries[] = { + { "gapplication-replace", '\0', 0, G_OPTION_ARG_NONE, &replace, + N_("Replace the running instance") }, + { NULL } + }; + + g_option_group_add_entries (gapplication_group, entries); + } + + /* Now we parse... */ + if (!g_option_context_parse_strv (context, arguments, error)) + goto out; + + /* Check for --gapplication-service */ + if (become_service) + application->priv->flags |= G_APPLICATION_IS_SERVICE; + + /* Check for --gapplication-app-id */ + if (app_id) + g_application_set_application_id (application, app_id); + + /* Check for --gapplication-replace */ + if (replace) + application->priv->flags |= G_APPLICATION_REPLACE; + + dict = g_variant_dict_new (NULL); + if (application->priv->packed_options) + { + g_application_pack_option_entries (application, dict); + g_hash_table_unref (application->priv->packed_options); + application->priv->packed_options = NULL; + } + +out: + /* Make sure we don't run again */ + application->priv->options_parsed = TRUE; + + g_option_context_free (context); + g_free (app_id); + + return dict; +} + +static void +add_packed_option (GApplication *application, + GOptionEntry *entry) +{ + switch (entry->arg) + { + case G_OPTION_ARG_NONE: + entry->arg_data = g_new (gboolean, 1); + *(gboolean *) entry->arg_data = 2; + break; + + case G_OPTION_ARG_INT: + entry->arg_data = g_new0 (gint, 1); + break; + + case G_OPTION_ARG_STRING: + case G_OPTION_ARG_FILENAME: + case G_OPTION_ARG_STRING_ARRAY: + case G_OPTION_ARG_FILENAME_ARRAY: + entry->arg_data = g_new0 (gpointer, 1); + break; + + case G_OPTION_ARG_INT64: + entry->arg_data = g_new0 (gint64, 1); + break; + + case G_OPTION_ARG_DOUBLE: + entry->arg_data = g_new0 (gdouble, 1); + break; + + default: + g_return_if_reached (); + } + + if (!application->priv->packed_options) + application->priv->packed_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_option_entry); + + g_hash_table_insert (application->priv->packed_options, + g_strdup (entry->long_name), + g_slice_dup (GOptionEntry, entry)); +} + +/** + * g_application_add_main_option_entries: + * @application: a #GApplication + * @entries: (array zero-terminated=1) (element-type GOptionEntry) a + * %NULL-terminated list of #GOptionEntrys + * + * Adds main option entries to be handled by @application. + * + * This function is comparable to g_option_context_add_main_entries(). + * + * After the commandline arguments are parsed, the + * #GApplication::handle-local-options signal will be emitted. At this + * point, the application can inspect the values pointed to by @arg_data + * in the given #GOptionEntrys. + * + * Unlike #GOptionContext, #GApplication supports giving a %NULL + * @arg_data for a non-callback #GOptionEntry. This results in the + * argument in question being packed into a #GVariantDict which is also + * passed to #GApplication::handle-local-options, where it can be + * inspected and modified. If %G_APPLICATION_HANDLES_COMMAND_LINE is + * set, then the resulting dictionary is sent to the primary instance, + * where g_application_command_line_get_options_dict() will return it. + * This "packing" is done according to the type of the argument -- + * booleans for normal flags, strings for strings, bytestrings for + * filenames, etc. The packing only occurs if the flag is given (ie: we + * do not pack a "false" #GVariant in the case that a flag is missing). + * + * In general, it is recommended that all commandline arguments are + * parsed locally. The options dictionary should then be used to + * transmit the result of the parsing to the primary instance, where + * g_variant_dict_lookup() can be used. For local options, it is + * possible to either use @arg_data in the usual way, or to consult (and + * potentially remove) the option from the options dictionary. + * + * This function is new in GLib 2.40. Before then, the only real choice + * was to send all of the commandline arguments (options and all) to the + * primary instance for handling. #GApplication ignored them completely + * on the local side. Calling this function "opts in" to the new + * behaviour, and in particular, means that unrecognised options will be + * treated as errors. Unrecognised options have never been ignored when + * %G_APPLICATION_HANDLES_COMMAND_LINE is unset. + * + * If #GApplication::handle-local-options needs to see the list of + * filenames, then the use of %G_OPTION_REMAINING is recommended. If + * @arg_data is %NULL then %G_OPTION_REMAINING can be used as a key into + * the options dictionary. If you do use %G_OPTION_REMAINING then you + * need to handle these arguments for yourself because once they are + * consumed, they will no longer be visible to the default handling + * (which treats them as filenames to be opened). + * + * It is important to use the proper GVariant format when retrieving + * the options with g_variant_dict_lookup(): + * - for %G_OPTION_ARG_NONE, use `b` + * - for %G_OPTION_ARG_STRING, use `&s` + * - for %G_OPTION_ARG_INT, use `i` + * - for %G_OPTION_ARG_INT64, use `x` + * - for %G_OPTION_ARG_DOUBLE, use `d` + * - for %G_OPTION_ARG_FILENAME, use `^&ay` + * - for %G_OPTION_ARG_STRING_ARRAY, use `^a&s` + * - for %G_OPTION_ARG_FILENAME_ARRAY, use `^a&ay` + * + * Since: 2.40 + */ +void +g_application_add_main_option_entries (GApplication *application, + const GOptionEntry *entries) +{ + gint i; + + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (entries != NULL); + + if (!application->priv->main_options) + { + application->priv->main_options = g_option_group_new (NULL, NULL, NULL, NULL, NULL); + g_option_group_set_translation_domain (application->priv->main_options, NULL); + } + + for (i = 0; entries[i].long_name; i++) + { + GOptionEntry my_entries[2] = { { NULL }, { NULL } }; + my_entries[0] = entries[i]; + + if (!my_entries[0].arg_data) + add_packed_option (application, &my_entries[0]); + + g_option_group_add_entries (application->priv->main_options, my_entries); + } +} + +/** + * g_application_add_main_option: + * @application: the #GApplication + * @long_name: the long name of an option used to specify it in a commandline + * @short_name: the short name of an option + * @flags: flags from #GOptionFlags + * @arg: the type of the option, as a #GOptionArg + * @description: the description for the option in `--help` output + * @arg_description: (nullable): the placeholder to use for the extra argument + * parsed by the option in `--help` output + * + * Add an option to be handled by @application. + * + * Calling this function is the equivalent of calling + * g_application_add_main_option_entries() with a single #GOptionEntry + * that has its arg_data member set to %NULL. + * + * The parsed arguments will be packed into a #GVariantDict which + * is passed to #GApplication::handle-local-options. If + * %G_APPLICATION_HANDLES_COMMAND_LINE is set, then it will also + * be sent to the primary instance. See + * g_application_add_main_option_entries() for more details. + * + * See #GOptionEntry for more documentation of the arguments. + * + * Since: 2.42 + **/ +void +g_application_add_main_option (GApplication *application, + const char *long_name, + char short_name, + GOptionFlags flags, + GOptionArg arg, + const char *description, + const char *arg_description) +{ + gchar *dup_string; + GOptionEntry my_entry[2] = { + { NULL, short_name, flags, arg, NULL, NULL, NULL }, + { NULL } + }; + + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (long_name != NULL); + g_return_if_fail (description != NULL); + + my_entry[0].long_name = dup_string = g_strdup (long_name); + application->priv->option_strings = g_slist_prepend (application->priv->option_strings, dup_string); + + my_entry[0].description = dup_string = g_strdup (description); + application->priv->option_strings = g_slist_prepend (application->priv->option_strings, dup_string); + + my_entry[0].arg_description = dup_string = g_strdup (arg_description); + application->priv->option_strings = g_slist_prepend (application->priv->option_strings, dup_string); + + g_application_add_main_option_entries (application, my_entry); +} + +/** + * g_application_add_option_group: + * @application: the #GApplication + * @group: (transfer full): a #GOptionGroup + * + * Adds a #GOptionGroup to the commandline handling of @application. + * + * This function is comparable to g_option_context_add_group(). + * + * Unlike g_application_add_main_option_entries(), this function does + * not deal with %NULL @arg_data and never transmits options to the + * primary instance. + * + * The reason for that is because, by the time the options arrive at the + * primary instance, it is typically too late to do anything with them. + * Taking the GTK option group as an example: GTK will already have been + * initialised by the time the #GApplication::command-line handler runs. + * In the case that this is not the first-running instance of the + * application, the existing instance may already have been running for + * a very long time. + * + * This means that the options from #GOptionGroup are only really usable + * in the case that the instance of the application being run is the + * first instance. Passing options like `--display=` or `--gdk-debug=` + * on future runs will have no effect on the existing primary instance. + * + * Calling this function will cause the options in the supplied option + * group to be parsed, but it does not cause you to be "opted in" to the + * new functionality whereby unrecognised options are rejected even if + * %G_APPLICATION_HANDLES_COMMAND_LINE was given. + * + * Since: 2.40 + **/ +void +g_application_add_option_group (GApplication *application, + GOptionGroup *group) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (group != NULL); + + application->priv->option_groups = g_slist_prepend (application->priv->option_groups, group); +} + +/** + * g_application_set_option_context_parameter_string: + * @application: the #GApplication + * @parameter_string: (nullable): a string which is displayed + * in the first line of `--help` output, after the usage summary `programname [OPTION...]`. + * + * Sets the parameter string to be used by the commandline handling of @application. + * + * This function registers the argument to be passed to g_option_context_new() + * when the internal #GOptionContext of @application is created. + * + * See g_option_context_new() for more information about @parameter_string. + * + * Since: 2.56 + */ +void +g_application_set_option_context_parameter_string (GApplication *application, + const gchar *parameter_string) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + + g_free (application->priv->parameter_string); + application->priv->parameter_string = g_strdup (parameter_string); +} + +/** + * g_application_set_option_context_summary: + * @application: the #GApplication + * @summary: (nullable): a string to be shown in `--help` output + * before the list of options, or %NULL + * + * Adds a summary to the @application option context. + * + * See g_option_context_set_summary() for more information. + * + * Since: 2.56 + */ +void +g_application_set_option_context_summary (GApplication *application, + const gchar *summary) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + + g_free (application->priv->summary); + application->priv->summary = g_strdup (summary); +} + +/** + * g_application_set_option_context_description: + * @application: the #GApplication + * @description: (nullable): a string to be shown in `--help` output + * after the list of options, or %NULL + * + * Adds a description to the @application option context. + * + * See g_option_context_set_description() for more information. + * + * Since: 2.56 + */ +void +g_application_set_option_context_description (GApplication *application, + const gchar *description) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + + g_free (application->priv->description); + application->priv->description = g_strdup (description); + +} + + +/* vfunc defaults {{{1 */ +static void +g_application_real_before_emit (GApplication *application, + GVariant *platform_data) +{ +} + +static void +g_application_real_after_emit (GApplication *application, + GVariant *platform_data) +{ +} + +static void +g_application_real_startup (GApplication *application) +{ + application->priv->did_startup = TRUE; +} + +static void +g_application_real_shutdown (GApplication *application) +{ + application->priv->did_shutdown = TRUE; +} + +static void +g_application_real_activate (GApplication *application) +{ + if (!g_signal_has_handler_pending (application, + g_application_signals[SIGNAL_ACTIVATE], + 0, TRUE) && + G_APPLICATION_GET_CLASS (application)->activate == g_application_real_activate) + { + static gboolean warned; + + if (warned) + return; + + g_warning ("Your application does not implement " + "g_application_activate() and has no handlers connected " + "to the 'activate' signal. It should do one of these."); + warned = TRUE; + } +} + +static void +g_application_real_open (GApplication *application, + GFile **files, + gint n_files, + const gchar *hint) +{ + if (!g_signal_has_handler_pending (application, + g_application_signals[SIGNAL_OPEN], + 0, TRUE) && + G_APPLICATION_GET_CLASS (application)->open == g_application_real_open) + { + static gboolean warned; + + if (warned) + return; + + g_warning ("Your application claims to support opening files " + "but does not implement g_application_open() and has no " + "handlers connected to the 'open' signal."); + warned = TRUE; + } +} + +static int +g_application_real_command_line (GApplication *application, + GApplicationCommandLine *cmdline) +{ + if (!g_signal_has_handler_pending (application, + g_application_signals[SIGNAL_COMMAND_LINE], + 0, TRUE) && + G_APPLICATION_GET_CLASS (application)->command_line == g_application_real_command_line) + { + static gboolean warned; + + if (warned) + return 1; + + g_warning ("Your application claims to support custom command line " + "handling but does not implement g_application_command_line() " + "and has no handlers connected to the 'command-line' signal."); + + warned = TRUE; + } + + return 1; +} + +static gint +g_application_real_handle_local_options (GApplication *application, + GVariantDict *options) +{ + return -1; +} + +static GVariant * +get_platform_data (GApplication *application, + GVariant *options) +{ + GVariantBuilder *builder; + GVariant *result; + + builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + + { + gchar *cwd = g_get_current_dir (); + g_variant_builder_add (builder, "{sv}", "cwd", + g_variant_new_bytestring (cwd)); + g_free (cwd); + } + + if (application->priv->flags & G_APPLICATION_SEND_ENVIRONMENT) + { + GVariant *array; + gchar **envp; + + envp = g_get_environ (); + array = g_variant_new_bytestring_array ((const gchar **) envp, -1); + g_strfreev (envp); + + g_variant_builder_add (builder, "{sv}", "environ", array); + } + + if (options) + g_variant_builder_add (builder, "{sv}", "options", options); + + G_APPLICATION_GET_CLASS (application)-> + add_platform_data (application, builder); + + result = g_variant_builder_end (builder); + g_variant_builder_unref (builder); + + return result; +} + +static void +g_application_call_command_line (GApplication *application, + const gchar * const *arguments, + GVariant *options, + gint *exit_status) +{ + if (application->priv->is_remote) + { + GVariant *platform_data; + + platform_data = get_platform_data (application, options); + *exit_status = g_application_impl_command_line (application->priv->impl, arguments, platform_data); + } + else + { + GApplicationCommandLine *cmdline; + GVariant *v; + + v = g_variant_new_bytestring_array ((const gchar **) arguments, -1); + cmdline = g_object_new (G_TYPE_APPLICATION_COMMAND_LINE, + "arguments", v, + "options", options, + NULL); + g_signal_emit (application, g_application_signals[SIGNAL_COMMAND_LINE], 0, cmdline, exit_status); + g_object_unref (cmdline); + } +} + +static gboolean +g_application_real_local_command_line (GApplication *application, + gchar ***arguments, + int *exit_status) +{ + GError *error = NULL; + GVariantDict *options; + gint n_args; + + options = g_application_parse_command_line (application, arguments, &error); + if (!options) + { + g_printerr ("%s\n", error->message); + *exit_status = 1; + return TRUE; + } + + g_signal_emit (application, g_application_signals[SIGNAL_HANDLE_LOCAL_OPTIONS], 0, options, exit_status); + + if (*exit_status >= 0) + { + g_variant_dict_unref (options); + return TRUE; + } + + if (!g_application_register (application, NULL, &error)) + { + g_printerr ("Failed to register: %s\n", error->message); + g_variant_dict_unref (options); + g_error_free (error); + *exit_status = 1; + return TRUE; + } + + n_args = g_strv_length (*arguments); + + if (application->priv->flags & G_APPLICATION_IS_SERVICE) + { + if ((*exit_status = n_args > 1)) + { + g_printerr ("GApplication service mode takes no arguments.\n"); + application->priv->flags &= ~G_APPLICATION_IS_SERVICE; + *exit_status = 1; + } + else + *exit_status = 0; + } + else if (application->priv->flags & G_APPLICATION_HANDLES_COMMAND_LINE) + { + g_application_call_command_line (application, + (const gchar **) *arguments, + g_variant_dict_end (options), + exit_status); + } + else + { + if (n_args <= 1) + { + g_application_activate (application); + *exit_status = 0; + } + + else + { + if (~application->priv->flags & G_APPLICATION_HANDLES_OPEN) + { + g_critical ("This application can not open files."); + *exit_status = 1; + } + else + { + GFile **files; + gint n_files; + gint i; + + n_files = n_args - 1; + files = g_new (GFile *, n_files); + + for (i = 0; i < n_files; i++) + files[i] = g_file_new_for_commandline_arg ((*arguments)[i + 1]); + + g_application_open (application, files, n_files, ""); + + for (i = 0; i < n_files; i++) + g_object_unref (files[i]); + g_free (files); + + *exit_status = 0; + } + } + } + + g_variant_dict_unref (options); + + return TRUE; +} + +static void +g_application_real_add_platform_data (GApplication *application, + GVariantBuilder *builder) +{ +} + +static gboolean +g_application_real_dbus_register (GApplication *application, + GDBusConnection *connection, + const gchar *object_path, + GError **error) +{ + return TRUE; +} + +static void +g_application_real_dbus_unregister (GApplication *application, + GDBusConnection *connection, + const gchar *object_path) +{ +} + +static gboolean +g_application_real_name_lost (GApplication *application) +{ + g_application_quit (application); + return TRUE; +} + +/* GObject implementation stuff {{{1 */ +static void +g_application_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GApplication *application = G_APPLICATION (object); + + switch (prop_id) + { + case PROP_APPLICATION_ID: + g_application_set_application_id (application, + g_value_get_string (value)); + break; + + case PROP_FLAGS: + g_application_set_flags (application, g_value_get_flags (value)); + break; + + case PROP_RESOURCE_BASE_PATH: + g_application_set_resource_base_path (application, g_value_get_string (value)); + break; + + case PROP_INACTIVITY_TIMEOUT: + g_application_set_inactivity_timeout (application, + g_value_get_uint (value)); + break; + + case PROP_ACTION_GROUP: + g_clear_object (&application->priv->actions); + application->priv->actions = g_value_dup_object (value); + break; + + default: + g_assert_not_reached (); + } +} + +/** + * g_application_set_action_group: + * @application: a #GApplication + * @action_group: (nullable): a #GActionGroup, or %NULL + * + * This used to be how actions were associated with a #GApplication. + * Now there is #GActionMap for that. + * + * Since: 2.28 + * + * Deprecated:2.32:Use the #GActionMap interface instead. Never ever + * mix use of this API with use of #GActionMap on the same @application + * or things will go very badly wrong. This function is known to + * introduce buggy behaviour (ie: signals not emitted on changes to the + * action group), so you should really use #GActionMap instead. + **/ +void +g_application_set_action_group (GApplication *application, + GActionGroup *action_group) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (!application->priv->is_registered); + + if (application->priv->actions != NULL) + g_object_unref (application->priv->actions); + + application->priv->actions = action_group; + + if (application->priv->actions != NULL) + g_object_ref (application->priv->actions); +} + +static void +g_application_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GApplication *application = G_APPLICATION (object); + + switch (prop_id) + { + case PROP_APPLICATION_ID: + g_value_set_string (value, + g_application_get_application_id (application)); + break; + + case PROP_FLAGS: + g_value_set_flags (value, + g_application_get_flags (application)); + break; + + case PROP_RESOURCE_BASE_PATH: + g_value_set_string (value, g_application_get_resource_base_path (application)); + break; + + case PROP_IS_REGISTERED: + g_value_set_boolean (value, + g_application_get_is_registered (application)); + break; + + case PROP_IS_REMOTE: + g_value_set_boolean (value, + g_application_get_is_remote (application)); + break; + + case PROP_INACTIVITY_TIMEOUT: + g_value_set_uint (value, + g_application_get_inactivity_timeout (application)); + break; + + case PROP_IS_BUSY: + g_value_set_boolean (value, g_application_get_is_busy (application)); + break; + + default: + g_assert_not_reached (); + } +} + +static void +g_application_constructed (GObject *object) +{ + GApplication *application = G_APPLICATION (object); + + if (g_application_get_default () == NULL) + g_application_set_default (application); + + /* People should not set properties from _init... */ + g_assert (application->priv->resource_path == NULL); + + if (application->priv->id != NULL) + { + gint i; + + application->priv->resource_path = g_strconcat ("/", application->priv->id, NULL); + + for (i = 1; application->priv->resource_path[i]; i++) + if (application->priv->resource_path[i] == '.') + application->priv->resource_path[i] = '/'; + } +} + +static void +g_application_dispose (GObject *object) +{ + GApplication *application = G_APPLICATION (object); + + if (application->priv->impl != NULL && + G_APPLICATION_GET_CLASS (application)->dbus_unregister != g_application_real_dbus_unregister) + { + static gboolean warned; + + if (!warned) + { + g_warning ("Your application did not unregister from D-Bus before destruction. " + "Consider using g_application_run()."); + } + + warned = TRUE; + } + + G_OBJECT_CLASS (g_application_parent_class)->dispose (object); +} + +static void +g_application_finalize (GObject *object) +{ + GApplication *application = G_APPLICATION (object); + + if (application->priv->inactivity_timeout_id) + g_source_remove (application->priv->inactivity_timeout_id); + + g_slist_free_full (application->priv->option_groups, (GDestroyNotify) g_option_group_unref); + if (application->priv->main_options) + g_option_group_unref (application->priv->main_options); + if (application->priv->packed_options) + g_hash_table_unref (application->priv->packed_options); + + g_free (application->priv->parameter_string); + g_free (application->priv->summary); + g_free (application->priv->description); + + g_slist_free_full (application->priv->option_strings, g_free); + + if (application->priv->impl) + g_application_impl_destroy (application->priv->impl); + g_free (application->priv->id); + + if (g_application_get_default () == application) + g_application_set_default (NULL); + + if (application->priv->actions) + g_object_unref (application->priv->actions); + + g_clear_object (&application->priv->remote_actions); + + if (application->priv->notifications) + g_object_unref (application->priv->notifications); + + g_free (application->priv->resource_path); + + G_OBJECT_CLASS (g_application_parent_class) + ->finalize (object); +} + +static void +g_application_init (GApplication *application) +{ + application->priv = g_application_get_instance_private (application); + + application->priv->actions = g_application_exported_actions_new (application); + + /* application->priv->actions is the one and only ref on the group, so when + * we dispose, the action group will die, disconnecting all signals. + */ + g_signal_connect_swapped (application->priv->actions, "action-added", + G_CALLBACK (g_action_group_action_added), application); + g_signal_connect_swapped (application->priv->actions, "action-enabled-changed", + G_CALLBACK (g_action_group_action_enabled_changed), application); + g_signal_connect_swapped (application->priv->actions, "action-state-changed", + G_CALLBACK (g_action_group_action_state_changed), application); + g_signal_connect_swapped (application->priv->actions, "action-removed", + G_CALLBACK (g_action_group_action_removed), application); +} + +static gboolean +g_application_handle_local_options_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + gint value; + + value = g_value_get_int (handler_return); + g_value_set_int (return_accu, value); + + return value < 0; +} + +static void +g_application_class_init (GApplicationClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->constructed = g_application_constructed; + object_class->dispose = g_application_dispose; + object_class->finalize = g_application_finalize; + object_class->get_property = g_application_get_property; + object_class->set_property = g_application_set_property; + + class->before_emit = g_application_real_before_emit; + class->after_emit = g_application_real_after_emit; + class->startup = g_application_real_startup; + class->shutdown = g_application_real_shutdown; + class->activate = g_application_real_activate; + class->open = g_application_real_open; + class->command_line = g_application_real_command_line; + class->local_command_line = g_application_real_local_command_line; + class->handle_local_options = g_application_real_handle_local_options; + class->add_platform_data = g_application_real_add_platform_data; + class->dbus_register = g_application_real_dbus_register; + class->dbus_unregister = g_application_real_dbus_unregister; + class->name_lost = g_application_real_name_lost; + + g_object_class_install_property (object_class, PROP_APPLICATION_ID, + g_param_spec_string ("application-id", + P_("Application identifier"), + P_("The unique identifier for the application"), + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_FLAGS, + g_param_spec_flags ("flags", + P_("Application flags"), + P_("Flags specifying the behaviour of the application"), + G_TYPE_APPLICATION_FLAGS, G_APPLICATION_FLAGS_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_RESOURCE_BASE_PATH, + g_param_spec_string ("resource-base-path", + P_("Resource base path"), + P_("The base resource path for the application"), + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_IS_REGISTERED, + g_param_spec_boolean ("is-registered", + P_("Is registered"), + P_("If g_application_register() has been called"), + FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_IS_REMOTE, + g_param_spec_boolean ("is-remote", + P_("Is remote"), + P_("If this application instance is remote"), + FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_INACTIVITY_TIMEOUT, + g_param_spec_uint ("inactivity-timeout", + P_("Inactivity timeout"), + P_("Time (ms) to stay alive after becoming idle"), + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_ACTION_GROUP, + g_param_spec_object ("action-group", + P_("Action group"), + P_("The group of actions that the application exports"), + G_TYPE_ACTION_GROUP, + G_PARAM_DEPRECATED | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GApplication:is-busy: + * + * Whether the application is currently marked as busy through + * g_application_mark_busy() or g_application_bind_busy_property(). + * + * Since: 2.44 + */ + g_object_class_install_property (object_class, PROP_IS_BUSY, + g_param_spec_boolean ("is-busy", + P_("Is busy"), + P_("If this application is currently marked busy"), + FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GApplication::startup: + * @application: the application + * + * The ::startup signal is emitted on the primary instance immediately + * after registration. See g_application_register(). + */ + g_application_signals[SIGNAL_STARTUP] = + g_signal_new (I_("startup"), G_TYPE_APPLICATION, G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GApplicationClass, startup), + NULL, NULL, NULL, G_TYPE_NONE, 0); + + /** + * GApplication::shutdown: + * @application: the application + * + * The ::shutdown signal is emitted only on the registered primary instance + * immediately after the main loop terminates. + */ + g_application_signals[SIGNAL_SHUTDOWN] = + g_signal_new (I_("shutdown"), G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GApplicationClass, shutdown), + NULL, NULL, NULL, G_TYPE_NONE, 0); + + /** + * GApplication::activate: + * @application: the application + * + * The ::activate signal is emitted on the primary instance when an + * activation occurs. See g_application_activate(). + */ + g_application_signals[SIGNAL_ACTIVATE] = + g_signal_new (I_("activate"), G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GApplicationClass, activate), + NULL, NULL, NULL, G_TYPE_NONE, 0); + + + /** + * GApplication::open: + * @application: the application + * @files: (array length=n_files) (element-type GFile): an array of #GFiles + * @n_files: the length of @files + * @hint: a hint provided by the calling instance + * + * The ::open signal is emitted on the primary instance when there are + * files to open. See g_application_open() for more information. + */ + g_application_signals[SIGNAL_OPEN] = + g_signal_new (I_("open"), G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GApplicationClass, open), + NULL, NULL, + _g_cclosure_marshal_VOID__POINTER_INT_STRING, + G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_STRING); + g_signal_set_va_marshaller (g_application_signals[SIGNAL_OPEN], + G_TYPE_FROM_CLASS (class), + _g_cclosure_marshal_VOID__POINTER_INT_STRINGv); + + /** + * GApplication::command-line: + * @application: the application + * @command_line: a #GApplicationCommandLine representing the + * passed commandline + * + * The ::command-line signal is emitted on the primary instance when + * a commandline is not handled locally. See g_application_run() and + * the #GApplicationCommandLine documentation for more information. + * + * Returns: An integer that is set as the exit status for the calling + * process. See g_application_command_line_set_exit_status(). + */ + g_application_signals[SIGNAL_COMMAND_LINE] = + g_signal_new (I_("command-line"), G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GApplicationClass, command_line), + g_signal_accumulator_first_wins, NULL, + _g_cclosure_marshal_INT__OBJECT, + G_TYPE_INT, 1, G_TYPE_APPLICATION_COMMAND_LINE); + g_signal_set_va_marshaller (g_application_signals[SIGNAL_COMMAND_LINE], + G_TYPE_FROM_CLASS (class), + _g_cclosure_marshal_INT__OBJECTv); + + /** + * GApplication::handle-local-options: + * @application: the application + * @options: the options dictionary + * + * The ::handle-local-options signal is emitted on the local instance + * after the parsing of the commandline options has occurred. + * + * You can add options to be recognised during commandline option + * parsing using g_application_add_main_option_entries() and + * g_application_add_option_group(). + * + * Signal handlers can inspect @options (along with values pointed to + * from the @arg_data of an installed #GOptionEntrys) in order to + * decide to perform certain actions, including direct local handling + * (which may be useful for options like --version). + * + * In the event that the application is marked + * %G_APPLICATION_HANDLES_COMMAND_LINE the "normal processing" will + * send the @options dictionary to the primary instance where it can be + * read with g_application_command_line_get_options_dict(). The signal + * handler can modify the dictionary before returning, and the + * modified dictionary will be sent. + * + * In the event that %G_APPLICATION_HANDLES_COMMAND_LINE is not set, + * "normal processing" will treat the remaining uncollected command + * line arguments as filenames or URIs. If there are no arguments, + * the application is activated by g_application_activate(). One or + * more arguments results in a call to g_application_open(). + * + * If you want to handle the local commandline arguments for yourself + * by converting them to calls to g_application_open() or + * g_action_group_activate_action() then you must be sure to register + * the application first. You should probably not call + * g_application_activate() for yourself, however: just return -1 and + * allow the default handler to do it for you. This will ensure that + * the `--gapplication-service` switch works properly (i.e. no activation + * in that case). + * + * Note that this signal is emitted from the default implementation of + * local_command_line(). If you override that function and don't + * chain up then this signal will never be emitted. + * + * You can override local_command_line() if you need more powerful + * capabilities than what is provided here, but this should not + * normally be required. + * + * Returns: an exit code. If you have handled your options and want + * to exit the process, return a non-negative option, 0 for success, + * and a positive value for failure. To continue, return -1 to let + * the default option processing continue. + * + * Since: 2.40 + **/ + g_application_signals[SIGNAL_HANDLE_LOCAL_OPTIONS] = + g_signal_new (I_("handle-local-options"), G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GApplicationClass, handle_local_options), + g_application_handle_local_options_accumulator, NULL, + _g_cclosure_marshal_INT__BOXED, + G_TYPE_INT, 1, G_TYPE_VARIANT_DICT); + g_signal_set_va_marshaller (g_application_signals[SIGNAL_HANDLE_LOCAL_OPTIONS], + G_TYPE_FROM_CLASS (class), + _g_cclosure_marshal_INT__BOXEDv); + + /** + * GApplication::name-lost: + * @application: the application + * + * The ::name-lost signal is emitted only on the registered primary instance + * when a new instance has taken over. This can only happen if the application + * is using the %G_APPLICATION_ALLOW_REPLACEMENT flag. + * + * The default handler for this signal calls g_application_quit(). + * + * Returns: %TRUE if the signal has been handled + * + * Since: 2.60 + */ + g_application_signals[SIGNAL_NAME_LOST] = + g_signal_new (I_("name-lost"), G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GApplicationClass, name_lost), + g_signal_accumulator_true_handled, NULL, + _g_cclosure_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + g_signal_set_va_marshaller (g_application_signals[SIGNAL_NAME_LOST], + G_TYPE_FROM_CLASS (class), + _g_cclosure_marshal_BOOLEAN__VOIDv); +} + +/* Application ID validity {{{1 */ + +/** + * g_application_id_is_valid: + * @application_id: a potential application identifier + * + * Checks if @application_id is a valid application identifier. + * + * A valid ID is required for calls to g_application_new() and + * g_application_set_application_id(). + * + * Application identifiers follow the same format as + * [D-Bus well-known bus names](https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-bus). + * For convenience, the restrictions on application identifiers are + * reproduced here: + * + * - Application identifiers are composed of 1 or more elements separated by a + * period (`.`) character. All elements must contain at least one character. + * + * - Each element must only contain the ASCII characters `[A-Z][a-z][0-9]_-`, + * with `-` discouraged in new application identifiers. Each element must not + * begin with a digit. + * + * - Application identifiers must contain at least one `.` (period) character + * (and thus at least two elements). + * + * - Application identifiers must not begin with a `.` (period) character. + * + * - Application identifiers must not exceed 255 characters. + * + * Note that the hyphen (`-`) character is allowed in application identifiers, + * but is problematic or not allowed in various specifications and APIs that + * refer to D-Bus, such as + * [Flatpak application IDs](http://docs.flatpak.org/en/latest/introduction.html#identifiers), + * the + * [`DBusActivatable` interface in the Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#dbus), + * and the convention that an application's "main" interface and object path + * resemble its application identifier and bus name. To avoid situations that + * require special-case handling, it is recommended that new application + * identifiers consistently replace hyphens with underscores. + * + * Like D-Bus interface names, application identifiers should start with the + * reversed DNS domain name of the author of the interface (in lower-case), and + * it is conventional for the rest of the application identifier to consist of + * words run together, with initial capital letters. + * + * As with D-Bus interface names, if the author's DNS domain name contains + * hyphen/minus characters they should be replaced by underscores, and if it + * contains leading digits they should be escaped by prepending an underscore. + * For example, if the owner of 7-zip.org used an application identifier for an + * archiving application, it might be named `org._7_zip.Archiver`. + * + * Returns: %TRUE if @application_id is valid + */ +gboolean +g_application_id_is_valid (const gchar *application_id) +{ + return g_dbus_is_name (application_id) && + !g_dbus_is_unique_name (application_id); +} + +/* Public Constructor {{{1 */ +/** + * g_application_new: + * @application_id: (nullable): the application id + * @flags: the application flags + * + * Creates a new #GApplication instance. + * + * If non-%NULL, the application id must be valid. See + * g_application_id_is_valid(). + * + * If no application ID is given then some features of #GApplication + * (most notably application uniqueness) will be disabled. + * + * Returns: a new #GApplication instance + **/ +GApplication * +g_application_new (const gchar *application_id, + GApplicationFlags flags) +{ + g_return_val_if_fail (application_id == NULL || g_application_id_is_valid (application_id), NULL); + + return g_object_new (G_TYPE_APPLICATION, + "application-id", application_id, + "flags", flags, + NULL); +} + +/* Simple get/set: application id, flags, inactivity timeout {{{1 */ +/** + * g_application_get_application_id: + * @application: a #GApplication + * + * Gets the unique identifier for @application. + * + * Returns: the identifier for @application, owned by @application + * + * Since: 2.28 + **/ +const gchar * +g_application_get_application_id (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), NULL); + + return application->priv->id; +} + +/** + * g_application_set_application_id: + * @application: a #GApplication + * @application_id: (nullable): the identifier for @application + * + * Sets the unique identifier for @application. + * + * The application id can only be modified if @application has not yet + * been registered. + * + * If non-%NULL, the application id must be valid. See + * g_application_id_is_valid(). + * + * Since: 2.28 + **/ +void +g_application_set_application_id (GApplication *application, + const gchar *application_id) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + + if (g_strcmp0 (application->priv->id, application_id) != 0) + { + g_return_if_fail (application_id == NULL || g_application_id_is_valid (application_id)); + g_return_if_fail (!application->priv->is_registered); + + g_free (application->priv->id); + application->priv->id = g_strdup (application_id); + + g_object_notify (G_OBJECT (application), "application-id"); + } +} + +/** + * g_application_get_flags: + * @application: a #GApplication + * + * Gets the flags for @application. + * + * See #GApplicationFlags. + * + * Returns: the flags for @application + * + * Since: 2.28 + **/ +GApplicationFlags +g_application_get_flags (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), 0); + + return application->priv->flags; +} + +/** + * g_application_set_flags: + * @application: a #GApplication + * @flags: the flags for @application + * + * Sets the flags for @application. + * + * The flags can only be modified if @application has not yet been + * registered. + * + * See #GApplicationFlags. + * + * Since: 2.28 + **/ +void +g_application_set_flags (GApplication *application, + GApplicationFlags flags) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + + if (application->priv->flags != flags) + { + g_return_if_fail (!application->priv->is_registered); + + application->priv->flags = flags; + + g_object_notify (G_OBJECT (application), "flags"); + } +} + +/** + * g_application_get_resource_base_path: + * @application: a #GApplication + * + * Gets the resource base path of @application. + * + * See g_application_set_resource_base_path() for more information. + * + * Returns: (nullable): the base resource path, if one is set + * + * Since: 2.42 + */ +const gchar * +g_application_get_resource_base_path (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), NULL); + + return application->priv->resource_path; +} + +/** + * g_application_set_resource_base_path: + * @application: a #GApplication + * @resource_path: (nullable): the resource path to use + * + * Sets (or unsets) the base resource path of @application. + * + * The path is used to automatically load various [application + * resources][gresource] such as menu layouts and action descriptions. + * The various types of resources will be found at fixed names relative + * to the given base path. + * + * By default, the resource base path is determined from the application + * ID by prefixing '/' and replacing each '.' with '/'. This is done at + * the time that the #GApplication object is constructed. Changes to + * the application ID after that point will not have an impact on the + * resource base path. + * + * As an example, if the application has an ID of "org.example.app" then + * the default resource base path will be "/org/example/app". If this + * is a #GtkApplication (and you have not manually changed the path) + * then Gtk will then search for the menus of the application at + * "/org/example/app/gtk/menus.ui". + * + * See #GResource for more information about adding resources to your + * application. + * + * You can disable automatic resource loading functionality by setting + * the path to %NULL. + * + * Changing the resource base path once the application is running is + * not recommended. The point at which the resource path is consulted + * for forming paths for various purposes is unspecified. When writing + * a sub-class of #GApplication you should either set the + * #GApplication:resource-base-path property at construction time, or call + * this function during the instance initialization. Alternatively, you + * can call this function in the #GApplicationClass.startup virtual function, + * before chaining up to the parent implementation. + * + * Since: 2.42 + */ +void +g_application_set_resource_base_path (GApplication *application, + const gchar *resource_path) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (resource_path == NULL || g_str_has_prefix (resource_path, "/")); + + if (g_strcmp0 (application->priv->resource_path, resource_path) != 0) + { + g_free (application->priv->resource_path); + + application->priv->resource_path = g_strdup (resource_path); + + g_object_notify (G_OBJECT (application), "resource-base-path"); + } +} + +/** + * g_application_get_inactivity_timeout: + * @application: a #GApplication + * + * Gets the current inactivity timeout for the application. + * + * This is the amount of time (in milliseconds) after the last call to + * g_application_release() before the application stops running. + * + * Returns: the timeout, in milliseconds + * + * Since: 2.28 + **/ +guint +g_application_get_inactivity_timeout (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), 0); + + return application->priv->inactivity_timeout; +} + +/** + * g_application_set_inactivity_timeout: + * @application: a #GApplication + * @inactivity_timeout: the timeout, in milliseconds + * + * Sets the current inactivity timeout for the application. + * + * This is the amount of time (in milliseconds) after the last call to + * g_application_release() before the application stops running. + * + * This call has no side effects of its own. The value set here is only + * used for next time g_application_release() drops the use count to + * zero. Any timeouts currently in progress are not impacted. + * + * Since: 2.28 + **/ +void +g_application_set_inactivity_timeout (GApplication *application, + guint inactivity_timeout) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + + if (application->priv->inactivity_timeout != inactivity_timeout) + { + application->priv->inactivity_timeout = inactivity_timeout; + + g_object_notify (G_OBJECT (application), "inactivity-timeout"); + } +} +/* Read-only property getters (is registered, is remote, dbus stuff) {{{1 */ +/** + * g_application_get_is_registered: + * @application: a #GApplication + * + * Checks if @application is registered. + * + * An application is registered if g_application_register() has been + * successfully called. + * + * Returns: %TRUE if @application is registered + * + * Since: 2.28 + **/ +gboolean +g_application_get_is_registered (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), FALSE); + + return application->priv->is_registered; +} + +/** + * g_application_get_is_remote: + * @application: a #GApplication + * + * Checks if @application is remote. + * + * If @application is remote then it means that another instance of + * application already exists (the 'primary' instance). Calls to + * perform actions on @application will result in the actions being + * performed by the primary instance. + * + * The value of this property cannot be accessed before + * g_application_register() has been called. See + * g_application_get_is_registered(). + * + * Returns: %TRUE if @application is remote + * + * Since: 2.28 + **/ +gboolean +g_application_get_is_remote (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), FALSE); + g_return_val_if_fail (application->priv->is_registered, FALSE); + + return application->priv->is_remote; +} + +/** + * g_application_get_dbus_connection: + * @application: a #GApplication + * + * Gets the #GDBusConnection being used by the application, or %NULL. + * + * If #GApplication is using its D-Bus backend then this function will + * return the #GDBusConnection being used for uniqueness and + * communication with the desktop environment and other instances of the + * application. + * + * If #GApplication is not using D-Bus then this function will return + * %NULL. This includes the situation where the D-Bus backend would + * normally be in use but we were unable to connect to the bus. + * + * This function must not be called before the application has been + * registered. See g_application_get_is_registered(). + * + * Returns: (transfer none): a #GDBusConnection, or %NULL + * + * Since: 2.34 + **/ +GDBusConnection * +g_application_get_dbus_connection (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), FALSE); + g_return_val_if_fail (application->priv->is_registered, FALSE); + + return g_application_impl_get_dbus_connection (application->priv->impl); +} + +/** + * g_application_get_dbus_object_path: + * @application: a #GApplication + * + * Gets the D-Bus object path being used by the application, or %NULL. + * + * If #GApplication is using its D-Bus backend then this function will + * return the D-Bus object path that #GApplication is using. If the + * application is the primary instance then there is an object published + * at this path. If the application is not the primary instance then + * the result of this function is undefined. + * + * If #GApplication is not using D-Bus then this function will return + * %NULL. This includes the situation where the D-Bus backend would + * normally be in use but we were unable to connect to the bus. + * + * This function must not be called before the application has been + * registered. See g_application_get_is_registered(). + * + * Returns: the object path, or %NULL + * + * Since: 2.34 + **/ +const gchar * +g_application_get_dbus_object_path (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), FALSE); + g_return_val_if_fail (application->priv->is_registered, FALSE); + + return g_application_impl_get_dbus_object_path (application->priv->impl); +} + + +/* Register {{{1 */ +/** + * g_application_register: + * @application: a #GApplication + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: a pointer to a NULL #GError, or %NULL + * + * Attempts registration of the application. + * + * This is the point at which the application discovers if it is the + * primary instance or merely acting as a remote for an already-existing + * primary instance. This is implemented by attempting to acquire the + * application identifier as a unique bus name on the session bus using + * GDBus. + * + * If there is no application ID or if %G_APPLICATION_NON_UNIQUE was + * given, then this process will always become the primary instance. + * + * Due to the internal architecture of GDBus, method calls can be + * dispatched at any time (even if a main loop is not running). For + * this reason, you must ensure that any object paths that you wish to + * register are registered before calling this function. + * + * If the application has already been registered then %TRUE is + * returned with no work performed. + * + * The #GApplication::startup signal is emitted if registration succeeds + * and @application is the primary instance (including the non-unique + * case). + * + * In the event of an error (such as @cancellable being cancelled, or a + * failure to connect to the session bus), %FALSE is returned and @error + * is set appropriately. + * + * Note: the return value of this function is not an indicator that this + * instance is or is not the primary instance of the application. See + * g_application_get_is_remote() for that. + * + * Returns: %TRUE if registration succeeded + * + * Since: 2.28 + **/ +gboolean +g_application_register (GApplication *application, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), FALSE); + + if (!application->priv->is_registered) + { + if (application->priv->id == NULL) + application->priv->flags |= G_APPLICATION_NON_UNIQUE; + + application->priv->impl = + g_application_impl_register (application, application->priv->id, + application->priv->flags, + application->priv->actions, + &application->priv->remote_actions, + cancellable, error); + + if (application->priv->impl == NULL) + return FALSE; + + application->priv->is_remote = application->priv->remote_actions != NULL; + application->priv->is_registered = TRUE; + + g_object_notify (G_OBJECT (application), "is-registered"); + + if (!application->priv->is_remote) + { + g_signal_emit (application, g_application_signals[SIGNAL_STARTUP], 0); + + if (!application->priv->did_startup) + g_critical ("GApplication subclass '%s' failed to chain up on" + " ::startup (from start of override function)", + G_OBJECT_TYPE_NAME (application)); + } + } + + return TRUE; +} + +/* Hold/release {{{1 */ +/** + * g_application_hold: + * @application: a #GApplication + * + * Increases the use count of @application. + * + * Use this function to indicate that the application has a reason to + * continue to run. For example, g_application_hold() is called by GTK+ + * when a toplevel window is on the screen. + * + * To cancel the hold, call g_application_release(). + **/ +void +g_application_hold (GApplication *application) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + + if (application->priv->inactivity_timeout_id) + { + g_source_remove (application->priv->inactivity_timeout_id); + application->priv->inactivity_timeout_id = 0; + } + + application->priv->use_count++; +} + +static gboolean +inactivity_timeout_expired (gpointer data) +{ + GApplication *application = G_APPLICATION (data); + + application->priv->inactivity_timeout_id = 0; + + return G_SOURCE_REMOVE; +} + + +/** + * g_application_release: + * @application: a #GApplication + * + * Decrease the use count of @application. + * + * When the use count reaches zero, the application will stop running. + * + * Never call this function except to cancel the effect of a previous + * call to g_application_hold(). + **/ +void +g_application_release (GApplication *application) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (application->priv->use_count > 0); + + application->priv->use_count--; + + if (application->priv->use_count == 0 && application->priv->inactivity_timeout) + application->priv->inactivity_timeout_id = g_timeout_add (application->priv->inactivity_timeout, + inactivity_timeout_expired, application); +} + +/* Activate, Open {{{1 */ +/** + * g_application_activate: + * @application: a #GApplication + * + * Activates the application. + * + * In essence, this results in the #GApplication::activate signal being + * emitted in the primary instance. + * + * The application must be registered before calling this function. + * + * Since: 2.28 + **/ +void +g_application_activate (GApplication *application) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (application->priv->is_registered); + + if (application->priv->is_remote) + g_application_impl_activate (application->priv->impl, + get_platform_data (application, NULL)); + + else + g_signal_emit (application, g_application_signals[SIGNAL_ACTIVATE], 0); +} + +/** + * g_application_open: + * @application: a #GApplication + * @files: (array length=n_files): an array of #GFiles to open + * @n_files: the length of the @files array + * @hint: a hint (or ""), but never %NULL + * + * Opens the given files. + * + * In essence, this results in the #GApplication::open signal being emitted + * in the primary instance. + * + * @n_files must be greater than zero. + * + * @hint is simply passed through to the ::open signal. It is + * intended to be used by applications that have multiple modes for + * opening files (eg: "view" vs "edit", etc). Unless you have a need + * for this functionality, you should use "". + * + * The application must be registered before calling this function + * and it must have the %G_APPLICATION_HANDLES_OPEN flag set. + * + * Since: 2.28 + **/ +void +g_application_open (GApplication *application, + GFile **files, + gint n_files, + const gchar *hint) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (application->priv->flags & + G_APPLICATION_HANDLES_OPEN); + g_return_if_fail (application->priv->is_registered); + + if (application->priv->is_remote) + g_application_impl_open (application->priv->impl, + files, n_files, hint, + get_platform_data (application, NULL)); + + else + g_signal_emit (application, g_application_signals[SIGNAL_OPEN], + 0, files, n_files, hint); +} + +/* Run {{{1 */ +/** + * g_application_run: + * @application: a #GApplication + * @argc: the argc from main() (or 0 if @argv is %NULL) + * @argv: (array length=argc) (element-type filename) (nullable): + * the argv from main(), or %NULL + * + * Runs the application. + * + * This function is intended to be run from main() and its return value + * is intended to be returned by main(). Although you are expected to pass + * the @argc, @argv parameters from main() to this function, it is possible + * to pass %NULL if @argv is not available or commandline handling is not + * required. Note that on Windows, @argc and @argv are ignored, and + * g_win32_get_command_line() is called internally (for proper support + * of Unicode commandline arguments). + * + * #GApplication will attempt to parse the commandline arguments. You + * can add commandline flags to the list of recognised options by way of + * g_application_add_main_option_entries(). After this, the + * #GApplication::handle-local-options signal is emitted, from which the + * application can inspect the values of its #GOptionEntrys. + * + * #GApplication::handle-local-options is a good place to handle options + * such as `--version`, where an immediate reply from the local process is + * desired (instead of communicating with an already-running instance). + * A #GApplication::handle-local-options handler can stop further processing + * by returning a non-negative value, which then becomes the exit status of + * the process. + * + * What happens next depends on the flags: if + * %G_APPLICATION_HANDLES_COMMAND_LINE was specified then the remaining + * commandline arguments are sent to the primary instance, where a + * #GApplication::command-line signal is emitted. Otherwise, the + * remaining commandline arguments are assumed to be a list of files. + * If there are no files listed, the application is activated via the + * #GApplication::activate signal. If there are one or more files, and + * %G_APPLICATION_HANDLES_OPEN was specified then the files are opened + * via the #GApplication::open signal. + * + * If you are interested in doing more complicated local handling of the + * commandline then you should implement your own #GApplication subclass + * and override local_command_line(). In this case, you most likely want + * to return %TRUE from your local_command_line() implementation to + * suppress the default handling. See + * [gapplication-example-cmdline2.c][gapplication-example-cmdline2] + * for an example. + * + * If, after the above is done, the use count of the application is zero + * then the exit status is returned immediately. If the use count is + * non-zero then the default main context is iterated until the use count + * falls to zero, at which point 0 is returned. + * + * If the %G_APPLICATION_IS_SERVICE flag is set, then the service will + * run for as much as 10 seconds with a use count of zero while waiting + * for the message that caused the activation to arrive. After that, + * if the use count falls to zero the application will exit immediately, + * except in the case that g_application_set_inactivity_timeout() is in + * use. + * + * This function sets the prgname (g_set_prgname()), if not already set, + * to the basename of argv[0]. + * + * Much like g_main_loop_run(), this function will acquire the main context + * for the duration that the application is running. + * + * Since 2.40, applications that are not explicitly flagged as services + * or launchers (ie: neither %G_APPLICATION_IS_SERVICE or + * %G_APPLICATION_IS_LAUNCHER are given as flags) will check (from the + * default handler for local_command_line) if "--gapplication-service" + * was given in the command line. If this flag is present then normal + * commandline processing is interrupted and the + * %G_APPLICATION_IS_SERVICE flag is set. This provides a "compromise" + * solution whereby running an application directly from the commandline + * will invoke it in the normal way (which can be useful for debugging) + * while still allowing applications to be D-Bus activated in service + * mode. The D-Bus service file should invoke the executable with + * "--gapplication-service" as the sole commandline argument. This + * approach is suitable for use by most graphical applications but + * should not be used from applications like editors that need precise + * control over when processes invoked via the commandline will exit and + * what their exit status will be. + * + * Returns: the exit status + * + * Since: 2.28 + **/ +int +g_application_run (GApplication *application, + int argc, + char **argv) +{ + gchar **arguments; + int status; + GMainContext *context; + gboolean acquired_context; + + g_return_val_if_fail (G_IS_APPLICATION (application), 1); + g_return_val_if_fail (argc == 0 || argv != NULL, 1); + g_return_val_if_fail (!application->priv->must_quit_now, 1); + +#ifdef G_OS_WIN32 + { + gint new_argc = 0; + + arguments = g_win32_get_command_line (); + + /* + * CommandLineToArgvW(), which is called by g_win32_get_command_line(), + * pulls in the whole command line that is used to call the program. This is + * fine in cases where the program is a .exe program, but in the cases where the + * program is a called via a script, such as PyGObject's gtk-demo.py, which is normally + * called using 'python gtk-demo.py' on Windows, the program name (argv[0]) + * returned by g_win32_get_command_line() will not be the argv[0] that ->local_command_line() + * would expect, causing the program to fail with "This application can not open files." + */ + new_argc = g_strv_length (arguments); + + if (new_argc > argc) + { + gint i; + + for (i = 0; i < new_argc - argc; i++) + g_free (arguments[i]); + + memmove (&arguments[0], + &arguments[new_argc - argc], + sizeof (arguments[0]) * (argc + 1)); + } + } +#elif defined(__APPLE__) + { + gint i, j; + + /* + * OSX adds an unexpected parameter on the format -psn_X_XXXXXX + * when opening the application using Launch Services. In order + * to avoid that GOption fails to parse this parameter we just + * skip it if it was provided. + * See: https://gitlab.gnome.org/GNOME/glib/issues/1784 + */ + arguments = g_new (gchar *, argc + 1); + for (i = 0, j = 0; i < argc; i++) + { + if (!g_str_has_prefix (argv[i], "-psn_")) + { + arguments[j] = g_strdup (argv[i]); + j++; + } + } + arguments[j] = NULL; + } +#else + { + gint i; + + arguments = g_new (gchar *, argc + 1); + for (i = 0; i < argc; i++) + arguments[i] = g_strdup (argv[i]); + arguments[i] = NULL; + } +#endif + + if (g_get_prgname () == NULL && argc > 0) + { + gchar *prgname; + + prgname = g_path_get_basename (argv[0]); + g_set_prgname (prgname); + g_free (prgname); + } + + context = g_main_context_default (); + acquired_context = g_main_context_acquire (context); + g_return_val_if_fail (acquired_context, 0); + + if (!G_APPLICATION_GET_CLASS (application) + ->local_command_line (application, &arguments, &status)) + { + GError *error = NULL; + + if (!g_application_register (application, NULL, &error)) + { + g_printerr ("Failed to register: %s\n", error->message); + g_error_free (error); + return 1; + } + + g_application_call_command_line (application, (const gchar **) arguments, NULL, &status); + } + + g_strfreev (arguments); + + if (application->priv->flags & G_APPLICATION_IS_SERVICE && + application->priv->is_registered && + !application->priv->use_count && + !application->priv->inactivity_timeout_id) + { + application->priv->inactivity_timeout_id = + g_timeout_add (10000, inactivity_timeout_expired, application); + } + + while (application->priv->use_count || application->priv->inactivity_timeout_id) + { + if (application->priv->must_quit_now) + break; + + g_main_context_iteration (context, TRUE); + status = 0; + } + + if (application->priv->is_registered && !application->priv->is_remote) + { + g_signal_emit (application, g_application_signals[SIGNAL_SHUTDOWN], 0); + + if (!application->priv->did_shutdown) + g_critical ("GApplication subclass '%s' failed to chain up on" + " ::shutdown (from end of override function)", + G_OBJECT_TYPE_NAME (application)); + } + + if (application->priv->impl) + { + g_application_impl_flush (application->priv->impl); + g_application_impl_destroy (application->priv->impl); + application->priv->impl = NULL; + } + + g_settings_sync (); + + if (!application->priv->must_quit_now) + while (g_main_context_iteration (context, FALSE)) + ; + + g_main_context_release (context); + + return status; +} + +static gchar ** +g_application_list_actions (GActionGroup *action_group) +{ + GApplication *application = G_APPLICATION (action_group); + + g_return_val_if_fail (application->priv->is_registered, NULL); + + if (application->priv->remote_actions != NULL) + return g_action_group_list_actions (G_ACTION_GROUP (application->priv->remote_actions)); + + else if (application->priv->actions != NULL) + return g_action_group_list_actions (application->priv->actions); + + else + /* empty string array */ + return g_new0 (gchar *, 1); +} + +static gboolean +g_application_query_action (GActionGroup *group, + const gchar *action_name, + gboolean *enabled, + const GVariantType **parameter_type, + const GVariantType **state_type, + GVariant **state_hint, + GVariant **state) +{ + GApplication *application = G_APPLICATION (group); + + g_return_val_if_fail (application->priv->is_registered, FALSE); + + if (application->priv->remote_actions != NULL) + return g_action_group_query_action (G_ACTION_GROUP (application->priv->remote_actions), + action_name, + enabled, + parameter_type, + state_type, + state_hint, + state); + + if (application->priv->actions != NULL) + return g_action_group_query_action (application->priv->actions, + action_name, + enabled, + parameter_type, + state_type, + state_hint, + state); + + return FALSE; +} + +static void +g_application_change_action_state (GActionGroup *action_group, + const gchar *action_name, + GVariant *value) +{ + GApplication *application = G_APPLICATION (action_group); + + g_return_if_fail (application->priv->is_remote || + application->priv->actions != NULL); + g_return_if_fail (application->priv->is_registered); + + if (application->priv->remote_actions) + g_remote_action_group_change_action_state_full (application->priv->remote_actions, + action_name, value, get_platform_data (application, NULL)); + + else + g_action_group_change_action_state (application->priv->actions, action_name, value); +} + +static void +g_application_activate_action (GActionGroup *action_group, + const gchar *action_name, + GVariant *parameter) +{ + GApplication *application = G_APPLICATION (action_group); + + g_return_if_fail (application->priv->is_remote || + application->priv->actions != NULL); + g_return_if_fail (application->priv->is_registered); + + if (application->priv->remote_actions) + g_remote_action_group_activate_action_full (application->priv->remote_actions, + action_name, parameter, get_platform_data (application, NULL)); + + else + g_action_group_activate_action (application->priv->actions, action_name, parameter); +} + +static GAction * +g_application_lookup_action (GActionMap *action_map, + const gchar *action_name) +{ + GApplication *application = G_APPLICATION (action_map); + + g_return_val_if_fail (G_IS_ACTION_MAP (application->priv->actions), NULL); + + return g_action_map_lookup_action (G_ACTION_MAP (application->priv->actions), action_name); +} + +static void +g_application_add_action (GActionMap *action_map, + GAction *action) +{ + GApplication *application = G_APPLICATION (action_map); + + g_return_if_fail (G_IS_ACTION_MAP (application->priv->actions)); + + g_action_map_add_action (G_ACTION_MAP (application->priv->actions), action); +} + +static void +g_application_remove_action (GActionMap *action_map, + const gchar *action_name) +{ + GApplication *application = G_APPLICATION (action_map); + + g_return_if_fail (G_IS_ACTION_MAP (application->priv->actions)); + + g_action_map_remove_action (G_ACTION_MAP (application->priv->actions), action_name); +} + +static void +g_application_action_group_iface_init (GActionGroupInterface *iface) +{ + iface->list_actions = g_application_list_actions; + iface->query_action = g_application_query_action; + iface->change_action_state = g_application_change_action_state; + iface->activate_action = g_application_activate_action; +} + +static void +g_application_action_map_iface_init (GActionMapInterface *iface) +{ + iface->lookup_action = g_application_lookup_action; + iface->add_action = g_application_add_action; + iface->remove_action = g_application_remove_action; +} + +/* Default Application {{{1 */ + +static GApplication *default_app; + +/** + * g_application_get_default: + * + * Returns the default #GApplication instance for this process. + * + * Normally there is only one #GApplication per process and it becomes + * the default when it is created. You can exercise more control over + * this by using g_application_set_default(). + * + * If there is no default application then %NULL is returned. + * + * Returns: (transfer none): the default application for this process, or %NULL + * + * Since: 2.32 + **/ +GApplication * +g_application_get_default (void) +{ + return default_app; +} + +/** + * g_application_set_default: + * @application: (nullable): the application to set as default, or %NULL + * + * Sets or unsets the default application for the process, as returned + * by g_application_get_default(). + * + * This function does not take its own reference on @application. If + * @application is destroyed then the default application will revert + * back to %NULL. + * + * Since: 2.32 + **/ +void +g_application_set_default (GApplication *application) +{ + default_app = application; +} + +/** + * g_application_quit: + * @application: a #GApplication + * + * Immediately quits the application. + * + * Upon return to the mainloop, g_application_run() will return, + * calling only the 'shutdown' function before doing so. + * + * The hold count is ignored. + * Take care if your code has called g_application_hold() on the application and + * is therefore still expecting it to exist. + * (Note that you may have called g_application_hold() indirectly, for example + * through gtk_application_add_window().) + * + * The result of calling g_application_run() again after it returns is + * unspecified. + * + * Since: 2.32 + **/ +void +g_application_quit (GApplication *application) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + + application->priv->must_quit_now = TRUE; +} + +/** + * g_application_mark_busy: + * @application: a #GApplication + * + * Increases the busy count of @application. + * + * Use this function to indicate that the application is busy, for instance + * while a long running operation is pending. + * + * The busy state will be exposed to other processes, so a session shell will + * use that information to indicate the state to the user (e.g. with a + * spinner). + * + * To cancel the busy indication, use g_application_unmark_busy(). + * + * Since: 2.38 + **/ +void +g_application_mark_busy (GApplication *application) +{ + gboolean was_busy; + + g_return_if_fail (G_IS_APPLICATION (application)); + + was_busy = (application->priv->busy_count > 0); + application->priv->busy_count++; + + if (!was_busy) + { + g_application_impl_set_busy_state (application->priv->impl, TRUE); + g_object_notify (G_OBJECT (application), "is-busy"); + } +} + +/** + * g_application_unmark_busy: + * @application: a #GApplication + * + * Decreases the busy count of @application. + * + * When the busy count reaches zero, the new state will be propagated + * to other processes. + * + * This function must only be called to cancel the effect of a previous + * call to g_application_mark_busy(). + * + * Since: 2.38 + **/ +void +g_application_unmark_busy (GApplication *application) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (application->priv->busy_count > 0); + + application->priv->busy_count--; + + if (application->priv->busy_count == 0) + { + g_application_impl_set_busy_state (application->priv->impl, FALSE); + g_object_notify (G_OBJECT (application), "is-busy"); + } +} + +/** + * g_application_get_is_busy: + * @application: a #GApplication + * + * Gets the application's current busy state, as set through + * g_application_mark_busy() or g_application_bind_busy_property(). + * + * Returns: %TRUE if @application is currently marked as busy + * + * Since: 2.44 + */ +gboolean +g_application_get_is_busy (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), FALSE); + + return application->priv->busy_count > 0; +} + +/* Notifications {{{1 */ + +/** + * g_application_send_notification: + * @application: a #GApplication + * @id: (nullable): id of the notification, or %NULL + * @notification: the #GNotification to send + * + * Sends a notification on behalf of @application to the desktop shell. + * There is no guarantee that the notification is displayed immediately, + * or even at all. + * + * Notifications may persist after the application exits. It will be + * D-Bus-activated when the notification or one of its actions is + * activated. + * + * Modifying @notification after this call has no effect. However, the + * object can be reused for a later call to this function. + * + * @id may be any string that uniquely identifies the event for the + * application. It does not need to be in any special format. For + * example, "new-message" might be appropriate for a notification about + * new messages. + * + * If a previous notification was sent with the same @id, it will be + * replaced with @notification and shown again as if it was a new + * notification. This works even for notifications sent from a previous + * execution of the application, as long as @id is the same string. + * + * @id may be %NULL, but it is impossible to replace or withdraw + * notifications without an id. + * + * If @notification is no longer relevant, it can be withdrawn with + * g_application_withdraw_notification(). + * + * Since: 2.40 + */ +void +g_application_send_notification (GApplication *application, + const gchar *id, + GNotification *notification) +{ + gchar *generated_id = NULL; + + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (G_IS_NOTIFICATION (notification)); + g_return_if_fail (g_application_get_is_registered (application)); + g_return_if_fail (!g_application_get_is_remote (application)); + + if (application->priv->notifications == NULL) + application->priv->notifications = g_notification_backend_new_default (application); + + if (id == NULL) + { + generated_id = g_dbus_generate_guid (); + id = generated_id; + } + + g_notification_backend_send_notification (application->priv->notifications, id, notification); + + g_free (generated_id); +} + +/** + * g_application_withdraw_notification: + * @application: a #GApplication + * @id: id of a previously sent notification + * + * Withdraws a notification that was sent with + * g_application_send_notification(). + * + * This call does nothing if a notification with @id doesn't exist or + * the notification was never sent. + * + * This function works even for notifications sent in previous + * executions of this application, as long @id is the same as it was for + * the sent notification. + * + * Note that notifications are dismissed when the user clicks on one + * of the buttons in a notification or triggers its default action, so + * there is no need to explicitly withdraw the notification in that case. + * + * Since: 2.40 + */ +void +g_application_withdraw_notification (GApplication *application, + const gchar *id) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (id != NULL); + + if (application->priv->notifications == NULL) + application->priv->notifications = g_notification_backend_new_default (application); + + g_notification_backend_withdraw_notification (application->priv->notifications, id); +} + +/* Busy binding {{{1 */ + +typedef struct +{ + GApplication *app; + gboolean is_busy; +} GApplicationBusyBinding; + +static void +g_application_busy_binding_destroy (gpointer data, + GClosure *closure) +{ + GApplicationBusyBinding *binding = data; + + if (binding->is_busy) + g_application_unmark_busy (binding->app); + + g_object_unref (binding->app); + g_slice_free (GApplicationBusyBinding, binding); +} + +static void +g_application_notify_busy_binding (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + GApplicationBusyBinding *binding = user_data; + gboolean is_busy; + + g_object_get (object, pspec->name, &is_busy, NULL); + + if (is_busy && !binding->is_busy) + g_application_mark_busy (binding->app); + else if (!is_busy && binding->is_busy) + g_application_unmark_busy (binding->app); + + binding->is_busy = is_busy; +} + +/** + * g_application_bind_busy_property: + * @application: a #GApplication + * @object: (type GObject.Object): a #GObject + * @property: the name of a boolean property of @object + * + * Marks @application as busy (see g_application_mark_busy()) while + * @property on @object is %TRUE. + * + * The binding holds a reference to @application while it is active, but + * not to @object. Instead, the binding is destroyed when @object is + * finalized. + * + * Since: 2.44 + */ +void +g_application_bind_busy_property (GApplication *application, + gpointer object, + const gchar *property) +{ + guint notify_id; + GQuark property_quark; + GParamSpec *pspec; + GApplicationBusyBinding *binding; + GClosure *closure; + + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (G_IS_OBJECT (object)); + g_return_if_fail (property != NULL); + + notify_id = g_signal_lookup ("notify", G_TYPE_OBJECT); + property_quark = g_quark_from_string (property); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property); + + g_return_if_fail (pspec != NULL && pspec->value_type == G_TYPE_BOOLEAN); + + if (g_signal_handler_find (object, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC, + notify_id, property_quark, NULL, g_application_notify_busy_binding, NULL) > 0) + { + g_critical ("%s: '%s' is already bound to the busy state of the application", G_STRFUNC, property); + return; + } + + binding = g_slice_new (GApplicationBusyBinding); + binding->app = g_object_ref (application); + binding->is_busy = FALSE; + + closure = g_cclosure_new (G_CALLBACK (g_application_notify_busy_binding), binding, + g_application_busy_binding_destroy); + g_signal_connect_closure_by_id (object, notify_id, property_quark, closure, FALSE); + + /* fetch the initial value */ + g_application_notify_busy_binding (object, pspec, binding); +} + +/** + * g_application_unbind_busy_property: + * @application: a #GApplication + * @object: (type GObject.Object): a #GObject + * @property: the name of a boolean property of @object + * + * Destroys a binding between @property and the busy state of + * @application that was previously created with + * g_application_bind_busy_property(). + * + * Since: 2.44 + */ +void +g_application_unbind_busy_property (GApplication *application, + gpointer object, + const gchar *property) +{ + guint notify_id; + GQuark property_quark; + gulong handler_id; + + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (G_IS_OBJECT (object)); + g_return_if_fail (property != NULL); + + notify_id = g_signal_lookup ("notify", G_TYPE_OBJECT); + property_quark = g_quark_from_string (property); + + handler_id = g_signal_handler_find (object, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC, + notify_id, property_quark, NULL, g_application_notify_busy_binding, NULL); + if (handler_id == 0) + { + g_critical ("%s: '%s' is not bound to the busy state of the application", G_STRFUNC, property); + return; + } + + g_signal_handler_disconnect (object, handler_id); +} + +/* Epilogue {{{1 */ +/* vim:set foldmethod=marker: */
diff --git a/gio/gapplication.h b/gio/gapplication.h new file mode 100644 index 0000000..adc32ed --- /dev/null +++ b/gio/gapplication.h
@@ -0,0 +1,252 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_APPLICATION_H__ +#define __G_APPLICATION_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_APPLICATION (g_application_get_type ()) +#define G_APPLICATION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_APPLICATION, GApplication)) +#define G_APPLICATION_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ + G_TYPE_APPLICATION, GApplicationClass)) +#define G_IS_APPLICATION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_APPLICATION)) +#define G_IS_APPLICATION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_APPLICATION)) +#define G_APPLICATION_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + G_TYPE_APPLICATION, GApplicationClass)) + +typedef struct _GApplicationPrivate GApplicationPrivate; +typedef struct _GApplicationClass GApplicationClass; + +struct _GApplication +{ + /*< private >*/ + GObject parent_instance; + + GApplicationPrivate *priv; +}; + +struct _GApplicationClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + /* signals */ + void (* startup) (GApplication *application); + + void (* activate) (GApplication *application); + + void (* open) (GApplication *application, + GFile **files, + gint n_files, + const gchar *hint); + + int (* command_line) (GApplication *application, + GApplicationCommandLine *command_line); + + /* vfuncs */ + + /** + * GApplicationClass::local_command_line: + * @application: a #GApplication + * @arguments: (inout) (array zero-terminated=1): array of command line arguments + * @exit_status: (out): exit status to fill after processing the command line. + * + * This virtual function is always invoked in the local instance. It + * gets passed a pointer to a %NULL-terminated copy of @argv and is + * expected to remove arguments that it handled (shifting up remaining + * arguments). + * + * The last argument to local_command_line() is a pointer to the @status + * variable which can used to set the exit status that is returned from + * g_application_run(). + * + * See g_application_run() for more details on #GApplication startup. + * + * Returns: %TRUE if the commandline has been completely handled + */ + gboolean (* local_command_line) (GApplication *application, + gchar ***arguments, + int *exit_status); + + void (* before_emit) (GApplication *application, + GVariant *platform_data); + void (* after_emit) (GApplication *application, + GVariant *platform_data); + void (* add_platform_data) (GApplication *application, + GVariantBuilder *builder); + void (* quit_mainloop) (GApplication *application); + void (* run_mainloop) (GApplication *application); + void (* shutdown) (GApplication *application); + + gboolean (* dbus_register) (GApplication *application, + GDBusConnection *connection, + const gchar *object_path, + GError **error); + void (* dbus_unregister) (GApplication *application, + GDBusConnection *connection, + const gchar *object_path); + gint (* handle_local_options)(GApplication *application, + GVariantDict *options); + gboolean (* name_lost) (GApplication *application); + + /*< private >*/ + gpointer padding[7]; +}; + +GLIB_AVAILABLE_IN_ALL +GType g_application_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +gboolean g_application_id_is_valid (const gchar *application_id); + +GLIB_AVAILABLE_IN_ALL +GApplication * g_application_new (const gchar *application_id, + GApplicationFlags flags); + +GLIB_AVAILABLE_IN_ALL +const gchar * g_application_get_application_id (GApplication *application); +GLIB_AVAILABLE_IN_ALL +void g_application_set_application_id (GApplication *application, + const gchar *application_id); + +GLIB_AVAILABLE_IN_2_34 +GDBusConnection * g_application_get_dbus_connection (GApplication *application); +GLIB_AVAILABLE_IN_2_34 +const gchar * g_application_get_dbus_object_path (GApplication *application); + +GLIB_AVAILABLE_IN_ALL +guint g_application_get_inactivity_timeout (GApplication *application); +GLIB_AVAILABLE_IN_ALL +void g_application_set_inactivity_timeout (GApplication *application, + guint inactivity_timeout); + +GLIB_AVAILABLE_IN_ALL +GApplicationFlags g_application_get_flags (GApplication *application); +GLIB_AVAILABLE_IN_ALL +void g_application_set_flags (GApplication *application, + GApplicationFlags flags); + +GLIB_AVAILABLE_IN_2_42 +const gchar * g_application_get_resource_base_path (GApplication *application); +GLIB_AVAILABLE_IN_2_42 +void g_application_set_resource_base_path (GApplication *application, + const gchar *resource_path); + +GLIB_DEPRECATED +void g_application_set_action_group (GApplication *application, + GActionGroup *action_group); + +GLIB_AVAILABLE_IN_2_40 +void g_application_add_main_option_entries (GApplication *application, + const GOptionEntry *entries); + +GLIB_AVAILABLE_IN_2_42 +void g_application_add_main_option (GApplication *application, + const char *long_name, + char short_name, + GOptionFlags flags, + GOptionArg arg, + const char *description, + const char *arg_description); +GLIB_AVAILABLE_IN_2_40 +void g_application_add_option_group (GApplication *application, + GOptionGroup *group); +GLIB_AVAILABLE_IN_2_56 +void g_application_set_option_context_parameter_string (GApplication *application, + const gchar *parameter_string); +GLIB_AVAILABLE_IN_2_56 +void g_application_set_option_context_summary (GApplication *application, + const gchar *summary); +GLIB_AVAILABLE_IN_2_56 +void g_application_set_option_context_description (GApplication *application, + const gchar *description); +GLIB_AVAILABLE_IN_ALL +gboolean g_application_get_is_registered (GApplication *application); +GLIB_AVAILABLE_IN_ALL +gboolean g_application_get_is_remote (GApplication *application); + +GLIB_AVAILABLE_IN_ALL +gboolean g_application_register (GApplication *application, + GCancellable *cancellable, + GError **error); + +GLIB_AVAILABLE_IN_ALL +void g_application_hold (GApplication *application); +GLIB_AVAILABLE_IN_ALL +void g_application_release (GApplication *application); + +GLIB_AVAILABLE_IN_ALL +void g_application_activate (GApplication *application); + +GLIB_AVAILABLE_IN_ALL +void g_application_open (GApplication *application, + GFile **files, + gint n_files, + const gchar *hint); + +GLIB_AVAILABLE_IN_ALL +int g_application_run (GApplication *application, + int argc, + char **argv); + +GLIB_AVAILABLE_IN_2_32 +void g_application_quit (GApplication *application); + +GLIB_AVAILABLE_IN_2_32 +GApplication * g_application_get_default (void); +GLIB_AVAILABLE_IN_2_32 +void g_application_set_default (GApplication *application); + +GLIB_AVAILABLE_IN_2_38 +void g_application_mark_busy (GApplication *application); +GLIB_AVAILABLE_IN_2_38 +void g_application_unmark_busy (GApplication *application); +GLIB_AVAILABLE_IN_2_44 +gboolean g_application_get_is_busy (GApplication *application); + +GLIB_AVAILABLE_IN_2_40 +void g_application_send_notification (GApplication *application, + const gchar *id, + GNotification *notification); +GLIB_AVAILABLE_IN_2_40 +void g_application_withdraw_notification (GApplication *application, + const gchar *id); + +GLIB_AVAILABLE_IN_2_44 +void g_application_bind_busy_property (GApplication *application, + gpointer object, + const gchar *property); + +GLIB_AVAILABLE_IN_2_44 +void g_application_unbind_busy_property (GApplication *application, + gpointer object, + const gchar *property); + +G_END_DECLS + +#endif /* __G_APPLICATION_H__ */
diff --git a/gio/gapplicationcommandline.c b/gio/gapplicationcommandline.c new file mode 100644 index 0000000..d6c5c45 --- /dev/null +++ b/gio/gapplicationcommandline.c
@@ -0,0 +1,834 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" + +#include "gapplicationcommandline.h" + +#include "glibintl.h" +#include "gfile.h" + +#include <string.h> +#include <stdio.h> + +#ifdef G_OS_UNIX +#include "gunixinputstream.h" +#endif + +#ifdef G_OS_WIN32 +#include <windows.h> +#undef environ +#include "gwin32inputstream.h" +#endif + +/** + * SECTION:gapplicationcommandline + * @title: GApplicationCommandLine + * @short_description: A command-line invocation of an application + * @include: gio/gio.h + * @see_also: #GApplication + * + * #GApplicationCommandLine represents a command-line invocation of + * an application. It is created by #GApplication and emitted + * in the #GApplication::command-line signal and virtual function. + * + * The class contains the list of arguments that the program was invoked + * with. It is also possible to query if the commandline invocation was + * local (ie: the current process is running in direct response to the + * invocation) or remote (ie: some other process forwarded the + * commandline to this process). + * + * The GApplicationCommandLine object can provide the @argc and @argv + * parameters for use with the #GOptionContext command-line parsing API, + * with the g_application_command_line_get_arguments() function. See + * [gapplication-example-cmdline3.c][gapplication-example-cmdline3] + * for an example. + * + * The exit status of the originally-invoked process may be set and + * messages can be printed to stdout or stderr of that process. The + * lifecycle of the originally-invoked process is tied to the lifecycle + * of this object (ie: the process exits when the last reference is + * dropped). + * + * The main use for #GApplicationCommandLine (and the + * #GApplication::command-line signal) is 'Emacs server' like use cases: + * You can set the `EDITOR` environment variable to have e.g. git use + * your favourite editor to edit commit messages, and if you already + * have an instance of the editor running, the editing will happen + * in the running instance, instead of opening a new one. An important + * aspect of this use case is that the process that gets started by git + * does not return until the editing is done. + * + * Normally, the commandline is completely handled in the + * #GApplication::command-line handler. The launching instance exits + * once the signal handler in the primary instance has returned, and + * the return value of the signal handler becomes the exit status + * of the launching instance. + * |[<!-- language="C" --> + * static int + * command_line (GApplication *application, + * GApplicationCommandLine *cmdline) + * { + * gchar **argv; + * gint argc; + * gint i; + * + * argv = g_application_command_line_get_arguments (cmdline, &argc); + * + * g_application_command_line_print (cmdline, + * "This text is written back\n" + * "to stdout of the caller\n"); + * + * for (i = 0; i < argc; i++) + * g_print ("argument %d: %s\n", i, argv[i]); + * + * g_strfreev (argv); + * + * return 0; + * } + * ]| + * The complete example can be found here: + * [gapplication-example-cmdline.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline.c) + * + * In more complicated cases, the handling of the comandline can be + * split between the launcher and the primary instance. + * |[<!-- language="C" --> + * static gboolean + * test_local_cmdline (GApplication *application, + * gchar ***arguments, + * gint *exit_status) + * { + * gint i, j; + * gchar **argv; + * + * argv = *arguments; + * + * i = 1; + * while (argv[i]) + * { + * if (g_str_has_prefix (argv[i], "--local-")) + * { + * g_print ("handling argument %s locally\n", argv[i]); + * g_free (argv[i]); + * for (j = i; argv[j]; j++) + * argv[j] = argv[j + 1]; + * } + * else + * { + * g_print ("not handling argument %s locally\n", argv[i]); + * i++; + * } + * } + * + * *exit_status = 0; + * + * return FALSE; + * } + * + * static void + * test_application_class_init (TestApplicationClass *class) + * { + * G_APPLICATION_CLASS (class)->local_command_line = test_local_cmdline; + * + * ... + * } + * ]| + * In this example of split commandline handling, options that start + * with `--local-` are handled locally, all other options are passed + * to the #GApplication::command-line handler which runs in the primary + * instance. + * + * The complete example can be found here: + * [gapplication-example-cmdline2.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline2.c) + * + * If handling the commandline requires a lot of work, it may + * be better to defer it. + * |[<!-- language="C" --> + * static gboolean + * my_cmdline_handler (gpointer data) + * { + * GApplicationCommandLine *cmdline = data; + * + * // do the heavy lifting in an idle + * + * g_application_command_line_set_exit_status (cmdline, 0); + * g_object_unref (cmdline); // this releases the application + * + * return G_SOURCE_REMOVE; + * } + * + * static int + * command_line (GApplication *application, + * GApplicationCommandLine *cmdline) + * { + * // keep the application running until we are done with this commandline + * g_application_hold (application); + * + * g_object_set_data_full (G_OBJECT (cmdline), + * "application", application, + * (GDestroyNotify)g_application_release); + * + * g_object_ref (cmdline); + * g_idle_add (my_cmdline_handler, cmdline); + * + * return 0; + * } + * ]| + * In this example the commandline is not completely handled before + * the #GApplication::command-line handler returns. Instead, we keep + * a reference to the #GApplicationCommandLine object and handle it + * later (in this example, in an idle). Note that it is necessary to + * hold the application until you are done with the commandline. + * + * The complete example can be found here: + * [gapplication-example-cmdline3.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline3.c) + */ + +/** + * GApplicationCommandLine: + * + * #GApplicationCommandLine is an opaque data structure and can only be accessed + * using the following functions. + */ + +/** + * GApplicationCommandLineClass: + * + * The #GApplicationCommandLineClass-struct + * contains private data only. + * + * Since: 2.28 + **/ +enum +{ + PROP_NONE, + PROP_ARGUMENTS, + PROP_OPTIONS, + PROP_PLATFORM_DATA, + PROP_IS_REMOTE +}; + +struct _GApplicationCommandLinePrivate +{ + GVariant *platform_data; + GVariant *arguments; + GVariant *options; + GVariantDict *options_dict; + gchar *cwd; /* in GLib filename encoding, not UTF-8 */ + + gchar **environ; + gint exit_status; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJECT) + +/* All subclasses represent remote invocations of some kind. */ +#define IS_REMOTE(cmdline) (G_TYPE_FROM_INSTANCE (cmdline) != \ + G_TYPE_APPLICATION_COMMAND_LINE) + +static void +grok_platform_data (GApplicationCommandLine *cmdline) +{ + GVariantIter iter; + const gchar *key; + GVariant *value; + + g_variant_iter_init (&iter, cmdline->priv->platform_data); + + while (g_variant_iter_loop (&iter, "{&sv}", &key, &value)) + if (strcmp (key, "cwd") == 0) + { + if (!cmdline->priv->cwd) + cmdline->priv->cwd = g_variant_dup_bytestring (value, NULL); + } + + else if (strcmp (key, "environ") == 0) + { + if (!cmdline->priv->environ) + cmdline->priv->environ = + g_variant_dup_bytestring_array (value, NULL); + } + + else if (strcmp (key, "options") == 0) + { + if (!cmdline->priv->options) + cmdline->priv->options = g_variant_ref (value); + } +} + +static void +g_application_command_line_real_print_literal (GApplicationCommandLine *cmdline, + const gchar *message) +{ + g_print ("%s", message); +} + +static void +g_application_command_line_real_printerr_literal (GApplicationCommandLine *cmdline, + const gchar *message) +{ + g_printerr ("%s", message); +} + +static GInputStream * +g_application_command_line_real_get_stdin (GApplicationCommandLine *cmdline) +{ +#ifdef G_OS_UNIX + return g_unix_input_stream_new (0, FALSE); +#else + return g_win32_input_stream_new (GetStdHandle (STD_INPUT_HANDLE), FALSE); +#endif +} + +static void +g_application_command_line_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); + + switch (prop_id) + { + case PROP_ARGUMENTS: + g_value_set_variant (value, cmdline->priv->arguments); + break; + + case PROP_PLATFORM_DATA: + g_value_set_variant (value, cmdline->priv->platform_data); + break; + + case PROP_IS_REMOTE: + g_value_set_boolean (value, IS_REMOTE (cmdline)); + break; + + default: + g_assert_not_reached (); + } +} + +static void +g_application_command_line_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); + + switch (prop_id) + { + case PROP_ARGUMENTS: + g_assert (cmdline->priv->arguments == NULL); + cmdline->priv->arguments = g_value_dup_variant (value); + break; + + case PROP_OPTIONS: + g_assert (cmdline->priv->options == NULL); + cmdline->priv->options = g_value_dup_variant (value); + break; + + case PROP_PLATFORM_DATA: + g_assert (cmdline->priv->platform_data == NULL); + cmdline->priv->platform_data = g_value_dup_variant (value); + if (cmdline->priv->platform_data != NULL) + grok_platform_data (cmdline); + break; + + default: + g_assert_not_reached (); + } +} + +static void +g_application_command_line_finalize (GObject *object) +{ + GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); + + if (cmdline->priv->options_dict) + g_variant_dict_unref (cmdline->priv->options_dict); + + if (cmdline->priv->options) + g_variant_unref (cmdline->priv->options); + + if (cmdline->priv->platform_data) + g_variant_unref (cmdline->priv->platform_data); + if (cmdline->priv->arguments) + g_variant_unref (cmdline->priv->arguments); + + g_free (cmdline->priv->cwd); + g_strfreev (cmdline->priv->environ); + + G_OBJECT_CLASS (g_application_command_line_parent_class) + ->finalize (object); +} + +static void +g_application_command_line_init (GApplicationCommandLine *cmdline) +{ + cmdline->priv = g_application_command_line_get_instance_private (cmdline); +} + +static void +g_application_command_line_constructed (GObject *object) +{ + GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); + + if (IS_REMOTE (cmdline)) + return; + + /* In the local case, set cmd and environ */ + if (!cmdline->priv->cwd) + cmdline->priv->cwd = g_get_current_dir (); + + if (!cmdline->priv->environ) + cmdline->priv->environ = g_get_environ (); +} + +static void +g_application_command_line_class_init (GApplicationCommandLineClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->get_property = g_application_command_line_get_property; + object_class->set_property = g_application_command_line_set_property; + object_class->finalize = g_application_command_line_finalize; + object_class->constructed = g_application_command_line_constructed; + + class->printerr_literal = g_application_command_line_real_printerr_literal; + class->print_literal = g_application_command_line_real_print_literal; + class->get_stdin = g_application_command_line_real_get_stdin; + + g_object_class_install_property (object_class, PROP_ARGUMENTS, + g_param_spec_variant ("arguments", + P_("Commandline arguments"), + P_("The commandline that caused this ::command-line signal emission"), + G_VARIANT_TYPE_BYTESTRING_ARRAY, NULL, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_OPTIONS, + g_param_spec_variant ("options", + P_("Options"), + P_("The options sent along with the commandline"), + G_VARIANT_TYPE_VARDICT, NULL, G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_PLATFORM_DATA, + g_param_spec_variant ("platform-data", + P_("Platform data"), + P_("Platform-specific data for the commandline"), + G_VARIANT_TYPE ("a{sv}"), NULL, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_IS_REMOTE, + g_param_spec_boolean ("is-remote", + P_("Is remote"), + P_("TRUE if this is a remote commandline"), + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +} + + +/** + * g_application_command_line_get_arguments: + * @cmdline: a #GApplicationCommandLine + * @argc: (out) (optional): the length of the arguments array, or %NULL + * + * Gets the list of arguments that was passed on the command line. + * + * The strings in the array may contain non-UTF-8 data on UNIX (such as + * filenames or arguments given in the system locale) but are always in + * UTF-8 on Windows. + * + * If you wish to use the return value with #GOptionContext, you must + * use g_option_context_parse_strv(). + * + * The return value is %NULL-terminated and should be freed using + * g_strfreev(). + * + * Returns: (array length=argc) (element-type filename) (transfer full) + * the string array containing the arguments (the argv) + * + * Since: 2.28 + **/ +gchar ** +g_application_command_line_get_arguments (GApplicationCommandLine *cmdline, + int *argc) +{ + gchar **argv; + gsize len; + + g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL); + + argv = g_variant_dup_bytestring_array (cmdline->priv->arguments, &len); + + if (argc) + *argc = len; + + return argv; +} + +/** + * g_application_command_line_get_options_dict: + * @cmdline: a #GApplicationCommandLine + * + * Gets the options there were passed to g_application_command_line(). + * + * If you did not override local_command_line() then these are the same + * options that were parsed according to the #GOptionEntrys added to the + * application with g_application_add_main_option_entries() and possibly + * modified from your GApplication::handle-local-options handler. + * + * If no options were sent then an empty dictionary is returned so that + * you don't need to check for %NULL. + * + * Returns: (transfer none): a #GVariantDict with the options + * + * Since: 2.40 + **/ +GVariantDict * +g_application_command_line_get_options_dict (GApplicationCommandLine *cmdline) +{ + g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL); + + if (!cmdline->priv->options_dict) + cmdline->priv->options_dict = g_variant_dict_new (cmdline->priv->options); + + return cmdline->priv->options_dict; +} + +/** + * g_application_command_line_get_stdin: + * @cmdline: a #GApplicationCommandLine + * + * Gets the stdin of the invoking process. + * + * The #GInputStream can be used to read data passed to the standard + * input of the invoking process. + * This doesn't work on all platforms. Presently, it is only available + * on UNIX when using a DBus daemon capable of passing file descriptors. + * If stdin is not available then %NULL will be returned. In the + * future, support may be expanded to other platforms. + * + * You must only call this function once per commandline invocation. + * + * Returns: (transfer full): a #GInputStream for stdin + * + * Since: 2.34 + **/ +GInputStream * +g_application_command_line_get_stdin (GApplicationCommandLine *cmdline) +{ + return G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline)->get_stdin (cmdline); +} + +/** + * g_application_command_line_get_cwd: + * @cmdline: a #GApplicationCommandLine + * + * Gets the working directory of the command line invocation. + * The string may contain non-utf8 data. + * + * It is possible that the remote application did not send a working + * directory, so this may be %NULL. + * + * The return value should not be modified or freed and is valid for as + * long as @cmdline exists. + * + * Returns: (nullable) (type filename): the current directory, or %NULL + * + * Since: 2.28 + **/ +const gchar * +g_application_command_line_get_cwd (GApplicationCommandLine *cmdline) +{ + return cmdline->priv->cwd; +} + +/** + * g_application_command_line_get_environ: + * @cmdline: a #GApplicationCommandLine + * + * Gets the contents of the 'environ' variable of the command line + * invocation, as would be returned by g_get_environ(), ie as a + * %NULL-terminated list of strings in the form 'NAME=VALUE'. + * The strings may contain non-utf8 data. + * + * The remote application usually does not send an environment. Use + * %G_APPLICATION_SEND_ENVIRONMENT to affect that. Even with this flag + * set it is possible that the environment is still not available (due + * to invocation messages from other applications). + * + * The return value should not be modified or freed and is valid for as + * long as @cmdline exists. + * + * See g_application_command_line_getenv() if you are only interested + * in the value of a single environment variable. + * + * Returns: (array zero-terminated=1) (element-type filename) (transfer none): + * the environment strings, or %NULL if they were not sent + * + * Since: 2.28 + **/ +const gchar * const * +g_application_command_line_get_environ (GApplicationCommandLine *cmdline) +{ + return (const gchar **)cmdline->priv->environ; +} + +/** + * g_application_command_line_getenv: + * @cmdline: a #GApplicationCommandLine + * @name: (type filename): the environment variable to get + * + * Gets the value of a particular environment variable of the command + * line invocation, as would be returned by g_getenv(). The strings may + * contain non-utf8 data. + * + * The remote application usually does not send an environment. Use + * %G_APPLICATION_SEND_ENVIRONMENT to affect that. Even with this flag + * set it is possible that the environment is still not available (due + * to invocation messages from other applications). + * + * The return value should not be modified or freed and is valid for as + * long as @cmdline exists. + * + * Returns: the value of the variable, or %NULL if unset or unsent + * + * Since: 2.28 + **/ +const gchar * +g_application_command_line_getenv (GApplicationCommandLine *cmdline, + const gchar *name) +{ + gint length = strlen (name); + gint i; + + /* TODO: expand on windows */ + if (cmdline->priv->environ) + for (i = 0; cmdline->priv->environ[i]; i++) + if (strncmp (cmdline->priv->environ[i], name, length) == 0 && + cmdline->priv->environ[i][length] == '=') + return cmdline->priv->environ[i] + length + 1; + + return NULL; +} + +/** + * g_application_command_line_get_is_remote: + * @cmdline: a #GApplicationCommandLine + * + * Determines if @cmdline represents a remote invocation. + * + * Returns: %TRUE if the invocation was remote + * + * Since: 2.28 + **/ +gboolean +g_application_command_line_get_is_remote (GApplicationCommandLine *cmdline) +{ + return IS_REMOTE (cmdline); +} + +/** + * g_application_command_line_print: + * @cmdline: a #GApplicationCommandLine + * @format: a printf-style format string + * @...: arguments, as per @format + * + * Formats a message and prints it using the stdout print handler in the + * invoking process. + * + * If @cmdline is a local invocation then this is exactly equivalent to + * g_print(). If @cmdline is remote then this is equivalent to calling + * g_print() in the invoking process. + * + * Since: 2.28 + **/ +void +g_application_command_line_print (GApplicationCommandLine *cmdline, + const gchar *format, + ...) +{ + gchar *message; + va_list ap; + + g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline)); + g_return_if_fail (format != NULL); + + va_start (ap, format); + message = g_strdup_vprintf (format, ap); + va_end (ap); + + G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline) + ->print_literal (cmdline, message); + g_free (message); +} + +/** + * g_application_command_line_printerr: + * @cmdline: a #GApplicationCommandLine + * @format: a printf-style format string + * @...: arguments, as per @format + * + * Formats a message and prints it using the stderr print handler in the + * invoking process. + * + * If @cmdline is a local invocation then this is exactly equivalent to + * g_printerr(). If @cmdline is remote then this is equivalent to + * calling g_printerr() in the invoking process. + * + * Since: 2.28 + **/ +void +g_application_command_line_printerr (GApplicationCommandLine *cmdline, + const gchar *format, + ...) +{ + gchar *message; + va_list ap; + + g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline)); + g_return_if_fail (format != NULL); + + va_start (ap, format); + message = g_strdup_vprintf (format, ap); + va_end (ap); + + G_APPLICATION_COMMAND_LINE_GET_CLASS (cmdline) + ->printerr_literal (cmdline, message); + g_free (message); +} + +/** + * g_application_command_line_set_exit_status: + * @cmdline: a #GApplicationCommandLine + * @exit_status: the exit status + * + * Sets the exit status that will be used when the invoking process + * exits. + * + * The return value of the #GApplication::command-line signal is + * passed to this function when the handler returns. This is the usual + * way of setting the exit status. + * + * In the event that you want the remote invocation to continue running + * and want to decide on the exit status in the future, you can use this + * call. For the case of a remote invocation, the remote process will + * typically exit when the last reference is dropped on @cmdline. The + * exit status of the remote process will be equal to the last value + * that was set with this function. + * + * In the case that the commandline invocation is local, the situation + * is slightly more complicated. If the commandline invocation results + * in the mainloop running (ie: because the use-count of the application + * increased to a non-zero value) then the application is considered to + * have been 'successful' in a certain sense, and the exit status is + * always zero. If the application use count is zero, though, the exit + * status of the local #GApplicationCommandLine is used. + * + * Since: 2.28 + **/ +void +g_application_command_line_set_exit_status (GApplicationCommandLine *cmdline, + int exit_status) +{ + g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline)); + + cmdline->priv->exit_status = exit_status; +} + +/** + * g_application_command_line_get_exit_status: + * @cmdline: a #GApplicationCommandLine + * + * Gets the exit status of @cmdline. See + * g_application_command_line_set_exit_status() for more information. + * + * Returns: the exit status + * + * Since: 2.28 + **/ +int +g_application_command_line_get_exit_status (GApplicationCommandLine *cmdline) +{ + g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), -1); + + return cmdline->priv->exit_status; +} + +/** + * g_application_command_line_get_platform_data: + * @cmdline: #GApplicationCommandLine + * + * Gets the platform data associated with the invocation of @cmdline. + * + * This is a #GVariant dictionary containing information about the + * context in which the invocation occurred. It typically contains + * information like the current working directory and the startup + * notification ID. + * + * For local invocation, it will be %NULL. + * + * Returns: (nullable): the platform data, or %NULL + * + * Since: 2.28 + **/ +GVariant * +g_application_command_line_get_platform_data (GApplicationCommandLine *cmdline) +{ + g_return_val_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline), NULL); + + if (cmdline->priv->platform_data) + return g_variant_ref (cmdline->priv->platform_data); + else + return NULL; +} + +/** + * g_application_command_line_create_file_for_arg: + * @cmdline: a #GApplicationCommandLine + * @arg: (type filename): an argument from @cmdline + * + * Creates a #GFile corresponding to a filename that was given as part + * of the invocation of @cmdline. + * + * This differs from g_file_new_for_commandline_arg() in that it + * resolves relative pathnames using the current working directory of + * the invoking process rather than the local process. + * + * Returns: (transfer full): a new #GFile + * + * Since: 2.36 + **/ +GFile * +g_application_command_line_create_file_for_arg (GApplicationCommandLine *cmdline, + const gchar *arg) +{ + g_return_val_if_fail (arg != NULL, NULL); + + if (cmdline->priv->cwd) + return g_file_new_for_commandline_arg_and_cwd (arg, cmdline->priv->cwd); + + g_warning ("Requested creation of GFile for commandline invocation that did not send cwd. " + "Using cwd of local process to resolve relative path names."); + + return g_file_new_for_commandline_arg (arg); +}
diff --git a/gio/gapplicationcommandline.h b/gio/gapplicationcommandline.h new file mode 100644 index 0000000..6610e86 --- /dev/null +++ b/gio/gapplicationcommandline.h
@@ -0,0 +1,122 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_APPLICATION_COMMAND_LINE_H__ +#define __G_APPLICATION_COMMAND_LINE_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_APPLICATION_COMMAND_LINE (g_application_command_line_get_type ()) +#define G_APPLICATION_COMMAND_LINE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_APPLICATION_COMMAND_LINE, \ + GApplicationCommandLine)) +#define G_APPLICATION_COMMAND_LINE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ + G_TYPE_APPLICATION_COMMAND_LINE, \ + GApplicationCommandLineClass)) +#define G_IS_APPLICATION_COMMAND_LINE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + G_TYPE_APPLICATION_COMMAND_LINE)) +#define G_IS_APPLICATION_COMMAND_LINE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ + G_TYPE_APPLICATION_COMMAND_LINE)) +#define G_APPLICATION_COMMAND_LINE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + G_TYPE_APPLICATION_COMMAND_LINE, \ + GApplicationCommandLineClass)) + +typedef struct _GApplicationCommandLinePrivate GApplicationCommandLinePrivate; +typedef struct _GApplicationCommandLineClass GApplicationCommandLineClass; + +struct _GApplicationCommandLine +{ + /*< private >*/ + GObject parent_instance; + + GApplicationCommandLinePrivate *priv; +}; + +struct _GApplicationCommandLineClass +{ + /*< private >*/ + GObjectClass parent_class; + + void (* print_literal) (GApplicationCommandLine *cmdline, + const gchar *message); + void (* printerr_literal) (GApplicationCommandLine *cmdline, + const gchar *message); + GInputStream * (* get_stdin) (GApplicationCommandLine *cmdline); + + gpointer padding[11]; +}; + +GLIB_AVAILABLE_IN_ALL +GType g_application_command_line_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +gchar ** g_application_command_line_get_arguments (GApplicationCommandLine *cmdline, + int *argc); + +GLIB_AVAILABLE_IN_2_40 +GVariantDict * g_application_command_line_get_options_dict (GApplicationCommandLine *cmdline); + +GLIB_AVAILABLE_IN_2_36 +GInputStream * g_application_command_line_get_stdin (GApplicationCommandLine *cmdline); + +GLIB_AVAILABLE_IN_ALL +const gchar * const * g_application_command_line_get_environ (GApplicationCommandLine *cmdline); + +GLIB_AVAILABLE_IN_ALL +const gchar * g_application_command_line_getenv (GApplicationCommandLine *cmdline, + const gchar *name); + +GLIB_AVAILABLE_IN_ALL +const gchar * g_application_command_line_get_cwd (GApplicationCommandLine *cmdline); + +GLIB_AVAILABLE_IN_ALL +gboolean g_application_command_line_get_is_remote (GApplicationCommandLine *cmdline); + +GLIB_AVAILABLE_IN_ALL +void g_application_command_line_print (GApplicationCommandLine *cmdline, + const gchar *format, + ...) G_GNUC_PRINTF(2, 3); +GLIB_AVAILABLE_IN_ALL +void g_application_command_line_printerr (GApplicationCommandLine *cmdline, + const gchar *format, + ...) G_GNUC_PRINTF(2, 3); + +GLIB_AVAILABLE_IN_ALL +int g_application_command_line_get_exit_status (GApplicationCommandLine *cmdline); +GLIB_AVAILABLE_IN_ALL +void g_application_command_line_set_exit_status (GApplicationCommandLine *cmdline, + int exit_status); + +GLIB_AVAILABLE_IN_ALL +GVariant * g_application_command_line_get_platform_data (GApplicationCommandLine *cmdline); + +GLIB_AVAILABLE_IN_2_36 +GFile * g_application_command_line_create_file_for_arg (GApplicationCommandLine *cmdline, + const gchar *arg); + +G_END_DECLS + +#endif /* __G_APPLICATION_COMMAND_LINE_H__ */
diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c new file mode 100644 index 0000000..fd9d046 --- /dev/null +++ b/gio/gapplicationimpl-dbus.c
@@ -0,0 +1,995 @@ +/* + * Copyright © 2010 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" + +#include "gapplicationimpl.h" + +#include "gactiongroup.h" +#include "gactiongroupexporter.h" +#include "gremoteactiongroup.h" +#include "gdbusactiongroup-private.h" +#include "gapplication.h" +#include "gfile.h" +#include "gdbusconnection.h" +#include "gdbusintrospection.h" +#include "gdbuserror.h" +#include "glib/gstdio.h" + +#include <string.h> +#include <stdio.h> + +#include "gapplicationcommandline.h" +#include "gdbusmethodinvocation.h" + +#ifdef G_OS_UNIX +#include "gunixinputstream.h" +#include "gunixfdlist.h" +#endif + +/* DBus Interface definition {{{1 */ + +/* For documentation of these interfaces, see + * https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI + */ +static const gchar org_gtk_Application_xml[] = + "<node>" + "<interface name='org.gtk.Application'>" + "<method name='Activate'>" + "<arg type='a{sv}' name='platform-data' direction='in'/>" + "</method>" + "<method name='Open'>" + "<arg type='as' name='uris' direction='in'/>" + "<arg type='s' name='hint' direction='in'/>" + "<arg type='a{sv}' name='platform-data' direction='in'/>" + "</method>" + "<method name='CommandLine'>" + "<arg type='o' name='path' direction='in'/>" + "<arg type='aay' name='arguments' direction='in'/>" + "<arg type='a{sv}' name='platform-data' direction='in'/>" + "<arg type='i' name='exit-status' direction='out'/>" + "</method>" + "<property name='Busy' type='b' access='read'/>" + "</interface>" + "</node>"; + +static GDBusInterfaceInfo *org_gtk_Application; + +static const gchar org_freedesktop_Application_xml[] = + "<node>" + "<interface name='org.freedesktop.Application'>" + "<method name='Activate'>" + "<arg type='a{sv}' name='platform-data' direction='in'/>" + "</method>" + "<method name='Open'>" + "<arg type='as' name='uris' direction='in'/>" + "<arg type='a{sv}' name='platform-data' direction='in'/>" + "</method>" + "<method name='ActivateAction'>" + "<arg type='s' name='action-name' direction='in'/>" + "<arg type='av' name='parameter' direction='in'/>" + "<arg type='a{sv}' name='platform-data' direction='in'/>" + "</method>" + "</interface>" + "</node>"; + +static GDBusInterfaceInfo *org_freedesktop_Application; + +static const gchar org_gtk_private_CommandLine_xml[] = + "<node>" + "<interface name='org.gtk.private.CommandLine'>" + "<method name='Print'>" + "<arg type='s' name='message' direction='in'/>" + "</method>" + "<method name='PrintError'>" + "<arg type='s' name='message' direction='in'/>" + "</method>" + "</interface>" + "</node>"; + +static GDBusInterfaceInfo *org_gtk_private_CommandLine; + +/* GApplication implementation {{{1 */ +struct _GApplicationImpl +{ + GDBusConnection *session_bus; + GActionGroup *exported_actions; + const gchar *bus_name; + guint name_lost_signal; + + gchar *object_path; + guint object_id; + guint fdo_object_id; + guint actions_id; + + gboolean properties_live; + gboolean primary; + gboolean busy; + gboolean registered; + GApplication *app; +}; + + +static GApplicationCommandLine * +g_dbus_command_line_new (GDBusMethodInvocation *invocation); + +static GVariant * +g_application_impl_get_property (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GApplicationImpl *impl = user_data; + + if (strcmp (property_name, "Busy") == 0) + return g_variant_new_boolean (impl->busy); + + g_assert_not_reached (); + + return NULL; +} + +static void +send_property_change (GApplicationImpl *impl) +{ + GVariantBuilder builder; + + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_add (&builder, + "{sv}", + "Busy", g_variant_new_boolean (impl->busy)); + + g_dbus_connection_emit_signal (impl->session_bus, + NULL, + impl->object_path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + g_variant_new ("(sa{sv}as)", + "org.gtk.Application", + &builder, + NULL), + NULL); +} + +static void +g_application_impl_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GApplicationImpl *impl = user_data; + GApplicationClass *class; + + class = G_APPLICATION_GET_CLASS (impl->app); + + if (strcmp (method_name, "Activate") == 0) + { + GVariant *platform_data; + + /* Completely the same for both freedesktop and gtk interfaces */ + + g_variant_get (parameters, "(@a{sv})", &platform_data); + + class->before_emit (impl->app, platform_data); + g_signal_emit_by_name (impl->app, "activate"); + class->after_emit (impl->app, platform_data); + g_variant_unref (platform_data); + + g_dbus_method_invocation_return_value (invocation, NULL); + } + + else if (strcmp (method_name, "Open") == 0) + { + GApplicationFlags flags; + GVariant *platform_data; + const gchar *hint; + GVariant *array; + GFile **files; + gint n, i; + + flags = g_application_get_flags (impl->app); + if ((flags & G_APPLICATION_HANDLES_OPEN) == 0) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Application does not open files"); + return; + } + + /* freedesktop interface has no hint parameter */ + if (g_str_equal (interface_name, "org.freedesktop.Application")) + { + g_variant_get (parameters, "(@as@a{sv})", &array, &platform_data); + hint = ""; + } + else + g_variant_get (parameters, "(@as&s@a{sv})", &array, &hint, &platform_data); + + n = g_variant_n_children (array); + files = g_new (GFile *, n + 1); + + for (i = 0; i < n; i++) + { + const gchar *uri; + + g_variant_get_child (array, i, "&s", &uri); + files[i] = g_file_new_for_uri (uri); + } + g_variant_unref (array); + files[n] = NULL; + + class->before_emit (impl->app, platform_data); + g_signal_emit_by_name (impl->app, "open", files, n, hint); + class->after_emit (impl->app, platform_data); + + g_variant_unref (platform_data); + + for (i = 0; i < n; i++) + g_object_unref (files[i]); + g_free (files); + + g_dbus_method_invocation_return_value (invocation, NULL); + } + + else if (strcmp (method_name, "CommandLine") == 0) + { + GApplicationFlags flags; + GApplicationCommandLine *cmdline; + GVariant *platform_data; + int status; + + flags = g_application_get_flags (impl->app); + if ((flags & G_APPLICATION_HANDLES_COMMAND_LINE) == 0) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, + "Application does not handle command line arguments"); + return; + } + + /* Only on the GtkApplication interface */ + + cmdline = g_dbus_command_line_new (invocation); + platform_data = g_variant_get_child_value (parameters, 2); + class->before_emit (impl->app, platform_data); + g_signal_emit_by_name (impl->app, "command-line", cmdline, &status); + g_application_command_line_set_exit_status (cmdline, status); + class->after_emit (impl->app, platform_data); + g_variant_unref (platform_data); + g_object_unref (cmdline); + } + else if (g_str_equal (method_name, "ActivateAction")) + { + GVariant *parameter = NULL; + GVariant *platform_data; + GVariantIter *iter; + const gchar *name; + + /* Only on the freedesktop interface */ + + g_variant_get (parameters, "(&sav@a{sv})", &name, &iter, &platform_data); + g_variant_iter_next (iter, "v", ¶meter); + g_variant_iter_free (iter); + + class->before_emit (impl->app, platform_data); + g_action_group_activate_action (impl->exported_actions, name, parameter); + class->after_emit (impl->app, platform_data); + + if (parameter) + g_variant_unref (parameter); + + g_variant_unref (platform_data); + + g_dbus_method_invocation_return_value (invocation, NULL); + } + else + g_assert_not_reached (); +} + +static gchar * +application_path_from_appid (const gchar *appid) +{ + gchar *appid_path, *iter; + + if (appid == NULL) + /* this is a private implementation detail */ + return g_strdup ("/org/gtk/Application/anonymous"); + + appid_path = g_strconcat ("/", appid, NULL); + for (iter = appid_path; *iter; iter++) + { + if (*iter == '.') + *iter = '/'; + + if (*iter == '-') + *iter = '_'; + } + + return appid_path; +} + +static void g_application_impl_stop_primary (GApplicationImpl *impl); + +static void +name_lost (GDBusConnection *bus, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + GApplicationImpl *impl = user_data; + gboolean handled; + + impl->primary = FALSE; + g_application_impl_stop_primary (impl); + g_signal_emit_by_name (impl->app, "name-lost", &handled); +} + +/* Attempt to become the primary instance. + * + * Returns %TRUE if everything went OK, regardless of if we became the + * primary instance or not. %FALSE is reserved for when something went + * seriously wrong (and @error will be set too, in that case). + * + * After a %TRUE return, impl->primary will be TRUE if we were + * successful. + */ +static gboolean +g_application_impl_attempt_primary (GApplicationImpl *impl, + GCancellable *cancellable, + GError **error) +{ + const static GDBusInterfaceVTable vtable = { + g_application_impl_method_call, + g_application_impl_get_property, + NULL /* set_property */ + }; + GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app); + GBusNameOwnerFlags name_owner_flags; + GApplicationFlags app_flags; + GVariant *reply; + guint32 rval; + + if (org_gtk_Application == NULL) + { + GError *error = NULL; + GDBusNodeInfo *info; + + info = g_dbus_node_info_new_for_xml (org_gtk_Application_xml, &error); + if G_UNLIKELY (info == NULL) + g_error ("%s", error->message); + org_gtk_Application = g_dbus_node_info_lookup_interface (info, "org.gtk.Application"); + g_assert (org_gtk_Application != NULL); + g_dbus_interface_info_ref (org_gtk_Application); + g_dbus_node_info_unref (info); + + info = g_dbus_node_info_new_for_xml (org_freedesktop_Application_xml, &error); + if G_UNLIKELY (info == NULL) + g_error ("%s", error->message); + org_freedesktop_Application = g_dbus_node_info_lookup_interface (info, "org.freedesktop.Application"); + g_assert (org_freedesktop_Application != NULL); + g_dbus_interface_info_ref (org_freedesktop_Application); + g_dbus_node_info_unref (info); + } + + /* We could possibly have been D-Bus activated as a result of incoming + * requests on either the application or actiongroup interfaces. + * Because of how GDBus dispatches messages, we need to ensure that + * both of those things are registered before we attempt to request + * our name. + * + * The action group need not be populated yet, as long as it happens + * before we return to the mainloop. The reason for that is because + * GDBus does the check to make sure the object exists from the worker + * thread but doesn't actually dispatch the action invocation until we + * hit the mainloop in this thread. There is also no danger of + * receiving 'activate' or 'open' signals until after 'startup' runs, + * for the same reason. + */ + impl->object_id = g_dbus_connection_register_object (impl->session_bus, impl->object_path, + org_gtk_Application, &vtable, impl, NULL, error); + + if (impl->object_id == 0) + return FALSE; + + impl->fdo_object_id = g_dbus_connection_register_object (impl->session_bus, impl->object_path, + org_freedesktop_Application, &vtable, impl, NULL, error); + + if (impl->fdo_object_id == 0) + return FALSE; + + impl->actions_id = g_dbus_connection_export_action_group (impl->session_bus, impl->object_path, + impl->exported_actions, error); + + if (impl->actions_id == 0) + return FALSE; + + impl->registered = TRUE; + if (!app_class->dbus_register (impl->app, + impl->session_bus, + impl->object_path, + error)) + return FALSE; + + if (impl->bus_name == NULL) + { + /* If this is a non-unique application then it is sufficient to + * have our object paths registered. We can return now. + * + * Note: non-unique applications always act as primary-instance. + */ + impl->primary = TRUE; + return TRUE; + } + + /* If this is a unique application then we need to attempt to own + * the well-known name and fall back to remote mode (!is_primary) + * in the case that we can't do that. + */ + name_owner_flags = G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE; + app_flags = g_application_get_flags (impl->app); + + if (app_flags & G_APPLICATION_ALLOW_REPLACEMENT) + { + impl->name_lost_signal = g_dbus_connection_signal_subscribe (impl->session_bus, + "org.freedesktop.DBus", + "org.freedesktop.DBus", + "NameLost", + "/org/freedesktop/DBus", + impl->bus_name, + G_DBUS_SIGNAL_FLAGS_NONE, + name_lost, + impl, + NULL); + + name_owner_flags |= G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; + } + if (app_flags & G_APPLICATION_REPLACE) + name_owner_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; + + reply = g_dbus_connection_call_sync (impl->session_bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "RequestName", + g_variant_new ("(su)", impl->bus_name, name_owner_flags), + G_VARIANT_TYPE ("(u)"), + 0, -1, cancellable, error); + + if (reply == NULL) + return FALSE; + + g_variant_get (reply, "(u)", &rval); + g_variant_unref (reply); + + /* DBUS_REQUEST_NAME_REPLY_EXISTS: 3 */ + impl->primary = (rval != 3); + + if (!impl->primary && impl->name_lost_signal) + { + g_dbus_connection_signal_unsubscribe (impl->session_bus, impl->name_lost_signal); + impl->name_lost_signal = 0; + } + + return TRUE; +} + +/* Stop doing the things that the primary instance does. + * + * This should be called if attempting to become the primary instance + * failed (in order to clean up any partial success) and should also + * be called when freeing the GApplication. + * + * It is safe to call this multiple times. + */ +static void +g_application_impl_stop_primary (GApplicationImpl *impl) +{ + GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app); + + if (impl->registered) + { + app_class->dbus_unregister (impl->app, + impl->session_bus, + impl->object_path); + impl->registered = FALSE; + } + + if (impl->object_id) + { + g_dbus_connection_unregister_object (impl->session_bus, impl->object_id); + impl->object_id = 0; + } + + if (impl->fdo_object_id) + { + g_dbus_connection_unregister_object (impl->session_bus, impl->fdo_object_id); + impl->fdo_object_id = 0; + } + + if (impl->actions_id) + { + g_dbus_connection_unexport_action_group (impl->session_bus, impl->actions_id); + impl->actions_id = 0; + } + + if (impl->name_lost_signal) + { + g_dbus_connection_signal_unsubscribe (impl->session_bus, impl->name_lost_signal); + impl->name_lost_signal = 0; + } + + if (impl->primary && impl->bus_name) + { + g_dbus_connection_call (impl->session_bus, "org.freedesktop.DBus", + "/org/freedesktop/DBus", "org.freedesktop.DBus", + "ReleaseName", g_variant_new ("(s)", impl->bus_name), + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + impl->primary = FALSE; + } +} + +void +g_application_impl_set_busy_state (GApplicationImpl *impl, + gboolean busy) +{ + if (impl->busy != busy) + { + impl->busy = busy; + send_property_change (impl); + } +} + +void +g_application_impl_destroy (GApplicationImpl *impl) +{ + g_application_impl_stop_primary (impl); + + if (impl->session_bus) + g_object_unref (impl->session_bus); + + g_free (impl->object_path); + + g_slice_free (GApplicationImpl, impl); +} + +GApplicationImpl * +g_application_impl_register (GApplication *application, + const gchar *appid, + GApplicationFlags flags, + GActionGroup *exported_actions, + GRemoteActionGroup **remote_actions, + GCancellable *cancellable, + GError **error) +{ + GDBusActionGroup *actions; + GApplicationImpl *impl; + + g_assert ((flags & G_APPLICATION_NON_UNIQUE) || appid != NULL); + + impl = g_slice_new0 (GApplicationImpl); + + impl->app = application; + impl->exported_actions = exported_actions; + + /* non-unique applications do not attempt to acquire a bus name */ + if (~flags & G_APPLICATION_NON_UNIQUE) + impl->bus_name = appid; + + impl->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, NULL); + + if (impl->session_bus == NULL) + { + /* If we can't connect to the session bus, proceed as a normal + * non-unique application. + */ + *remote_actions = NULL; + return impl; + } + + impl->object_path = application_path_from_appid (appid); + + /* Only try to be the primary instance if + * G_APPLICATION_IS_LAUNCHER was not specified. + */ + if (~flags & G_APPLICATION_IS_LAUNCHER) + { + if (!g_application_impl_attempt_primary (impl, cancellable, error)) + { + g_application_impl_destroy (impl); + return NULL; + } + + if (impl->primary) + return impl; + + /* We didn't make it. Drop our service-side stuff. */ + g_application_impl_stop_primary (impl); + + if (flags & G_APPLICATION_IS_SERVICE) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Unable to acquire bus name '%s'", appid); + g_application_impl_destroy (impl); + + return NULL; + } + } + + /* We are non-primary. Try to get the primary's list of actions. + * This also serves as a mechanism to ensure that the primary exists + * (ie: DBus service files installed correctly, etc). + */ + actions = g_dbus_action_group_get (impl->session_bus, impl->bus_name, impl->object_path); + if (!g_dbus_action_group_sync (actions, cancellable, error)) + { + /* The primary appears not to exist. Fail the registration. */ + g_application_impl_destroy (impl); + g_object_unref (actions); + + return NULL; + } + + *remote_actions = G_REMOTE_ACTION_GROUP (actions); + + return impl; +} + +void +g_application_impl_activate (GApplicationImpl *impl, + GVariant *platform_data) +{ + g_dbus_connection_call (impl->session_bus, + impl->bus_name, + impl->object_path, + "org.gtk.Application", + "Activate", + g_variant_new ("(@a{sv})", platform_data), + NULL, 0, -1, NULL, NULL, NULL); +} + +void +g_application_impl_open (GApplicationImpl *impl, + GFile **files, + gint n_files, + const gchar *hint, + GVariant *platform_data) +{ + GVariantBuilder builder; + gint i; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("(assa{sv})")); + g_variant_builder_open (&builder, G_VARIANT_TYPE_STRING_ARRAY); + for (i = 0; i < n_files; i++) + { + gchar *uri = g_file_get_uri (files[i]); + g_variant_builder_add (&builder, "s", uri); + g_free (uri); + } + g_variant_builder_close (&builder); + g_variant_builder_add (&builder, "s", hint); + g_variant_builder_add_value (&builder, platform_data); + + g_dbus_connection_call (impl->session_bus, + impl->bus_name, + impl->object_path, + "org.gtk.Application", + "Open", + g_variant_builder_end (&builder), + NULL, 0, -1, NULL, NULL, NULL); +} + +static void +g_application_impl_cmdline_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + const gchar *message; + + g_variant_get_child (parameters, 0, "&s", &message); + + if (strcmp (method_name, "Print") == 0) + g_print ("%s", message); + else if (strcmp (method_name, "PrintError") == 0) + g_printerr ("%s", message); + else + g_assert_not_reached (); + + g_dbus_method_invocation_return_value (invocation, NULL); +} + +typedef struct +{ + GMainLoop *loop; + int status; +} CommandLineData; + +static void +g_application_impl_cmdline_done (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + CommandLineData *data = user_data; + GError *error = NULL; + GVariant *reply; + +#ifdef G_OS_UNIX + reply = g_dbus_connection_call_with_unix_fd_list_finish (G_DBUS_CONNECTION (source), NULL, result, &error); +#else + reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); +#endif + + + if (reply != NULL) + { + g_variant_get (reply, "(i)", &data->status); + g_variant_unref (reply); + } + + else + { + g_printerr ("%s\n", error->message); + g_error_free (error); + data->status = 1; + } + + g_main_loop_quit (data->loop); +} + +int +g_application_impl_command_line (GApplicationImpl *impl, + const gchar * const *arguments, + GVariant *platform_data) +{ + const static GDBusInterfaceVTable vtable = { + g_application_impl_cmdline_method_call + }; + const gchar *object_path = "/org/gtk/Application/CommandLine"; + GMainContext *context; + CommandLineData data; + guint object_id G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */; + + context = g_main_context_new (); + data.loop = g_main_loop_new (context, FALSE); + g_main_context_push_thread_default (context); + + if (org_gtk_private_CommandLine == NULL) + { + GError *error = NULL; + GDBusNodeInfo *info; + + info = g_dbus_node_info_new_for_xml (org_gtk_private_CommandLine_xml, &error); + if G_UNLIKELY (info == NULL) + g_error ("%s", error->message); + org_gtk_private_CommandLine = g_dbus_node_info_lookup_interface (info, "org.gtk.private.CommandLine"); + g_assert (org_gtk_private_CommandLine != NULL); + g_dbus_interface_info_ref (org_gtk_private_CommandLine); + g_dbus_node_info_unref (info); + } + + object_id = g_dbus_connection_register_object (impl->session_bus, object_path, + org_gtk_private_CommandLine, + &vtable, &data, NULL, NULL); + /* In theory we should try other paths... */ + g_assert (object_id != 0); + +#ifdef G_OS_UNIX + { + GError *error = NULL; + GUnixFDList *fd_list; + + /* send along the stdin in case + * g_application_command_line_get_stdin_data() is called + */ + fd_list = g_unix_fd_list_new (); + g_unix_fd_list_append (fd_list, 0, &error); + g_assert_no_error (error); + + g_dbus_connection_call_with_unix_fd_list (impl->session_bus, impl->bus_name, impl->object_path, + "org.gtk.Application", "CommandLine", + g_variant_new ("(o^aay@a{sv})", object_path, arguments, platform_data), + G_VARIANT_TYPE ("(i)"), 0, G_MAXINT, fd_list, NULL, + g_application_impl_cmdline_done, &data); + g_object_unref (fd_list); + } +#else + g_dbus_connection_call (impl->session_bus, impl->bus_name, impl->object_path, + "org.gtk.Application", "CommandLine", + g_variant_new ("(o^aay@a{sv})", object_path, arguments, platform_data), + G_VARIANT_TYPE ("(i)"), 0, G_MAXINT, NULL, + g_application_impl_cmdline_done, &data); +#endif + + g_main_loop_run (data.loop); + + g_main_context_pop_thread_default (context); + g_main_context_unref (context); + g_main_loop_unref (data.loop); + + return data.status; +} + +void +g_application_impl_flush (GApplicationImpl *impl) +{ + if (impl->session_bus) + g_dbus_connection_flush_sync (impl->session_bus, NULL, NULL); +} + +GDBusConnection * +g_application_impl_get_dbus_connection (GApplicationImpl *impl) +{ + return impl->session_bus; +} + +const gchar * +g_application_impl_get_dbus_object_path (GApplicationImpl *impl) +{ + return impl->object_path; +} + +/* GDBusCommandLine implementation {{{1 */ + +typedef GApplicationCommandLineClass GDBusCommandLineClass; +static GType g_dbus_command_line_get_type (void); +typedef struct +{ + GApplicationCommandLine parent_instance; + GDBusMethodInvocation *invocation; + + GDBusConnection *connection; + const gchar *bus_name; + const gchar *object_path; +} GDBusCommandLine; + + +G_DEFINE_TYPE (GDBusCommandLine, + g_dbus_command_line, + G_TYPE_APPLICATION_COMMAND_LINE) + +static void +g_dbus_command_line_print_literal (GApplicationCommandLine *cmdline, + const gchar *message) +{ + GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline; + + g_dbus_connection_call (gdbcl->connection, + gdbcl->bus_name, + gdbcl->object_path, + "org.gtk.private.CommandLine", "Print", + g_variant_new ("(s)", message), + NULL, 0, -1, NULL, NULL, NULL); +} + +static void +g_dbus_command_line_printerr_literal (GApplicationCommandLine *cmdline, + const gchar *message) +{ + GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline; + + g_dbus_connection_call (gdbcl->connection, + gdbcl->bus_name, + gdbcl->object_path, + "org.gtk.private.CommandLine", "PrintError", + g_variant_new ("(s)", message), + NULL, 0, -1, NULL, NULL, NULL); +} + +static GInputStream * +g_dbus_command_line_get_stdin (GApplicationCommandLine *cmdline) +{ +#ifdef G_OS_UNIX + GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline; + GInputStream *result = NULL; + GDBusMessage *message; + GUnixFDList *fd_list; + + message = g_dbus_method_invocation_get_message (gdbcl->invocation); + fd_list = g_dbus_message_get_unix_fd_list (message); + + if (fd_list && g_unix_fd_list_get_length (fd_list)) + { + gint *fds, n_fds, i; + + fds = g_unix_fd_list_steal_fds (fd_list, &n_fds); + result = g_unix_input_stream_new (fds[0], TRUE); + for (i = 1; i < n_fds; i++) + (void) g_close (fds[i], NULL); + g_free (fds); + } + + return result; +#else + return NULL; +#endif +} + +static void +g_dbus_command_line_finalize (GObject *object) +{ + GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); + GDBusCommandLine *gdbcl = (GDBusCommandLine *) object; + gint status; + + status = g_application_command_line_get_exit_status (cmdline); + + g_dbus_method_invocation_return_value (gdbcl->invocation, + g_variant_new ("(i)", status)); + g_object_unref (gdbcl->invocation); + + G_OBJECT_CLASS (g_dbus_command_line_parent_class) + ->finalize (object); +} + +static void +g_dbus_command_line_init (GDBusCommandLine *gdbcl) +{ +} + +static void +g_dbus_command_line_class_init (GApplicationCommandLineClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = g_dbus_command_line_finalize; + class->printerr_literal = g_dbus_command_line_printerr_literal; + class->print_literal = g_dbus_command_line_print_literal; + class->get_stdin = g_dbus_command_line_get_stdin; +} + +static GApplicationCommandLine * +g_dbus_command_line_new (GDBusMethodInvocation *invocation) +{ + GDBusCommandLine *gdbcl; + GVariant *args; + GVariant *arguments, *platform_data; + + args = g_dbus_method_invocation_get_parameters (invocation); + + arguments = g_variant_get_child_value (args, 1); + platform_data = g_variant_get_child_value (args, 2); + gdbcl = g_object_new (g_dbus_command_line_get_type (), + "arguments", arguments, + "platform-data", platform_data, + NULL); + g_variant_unref (arguments); + g_variant_unref (platform_data); + + gdbcl->connection = g_dbus_method_invocation_get_connection (invocation); + gdbcl->bus_name = g_dbus_method_invocation_get_sender (invocation); + g_variant_get_child (args, 0, "&o", &gdbcl->object_path); + gdbcl->invocation = g_object_ref (invocation); + + return G_APPLICATION_COMMAND_LINE (gdbcl); +} + +/* Epilogue {{{1 */ + +/* vim:set foldmethod=marker: */
diff --git a/gio/gapplicationimpl.h b/gio/gapplicationimpl.h new file mode 100644 index 0000000..1e6a718 --- /dev/null +++ b/gio/gapplicationimpl.h
@@ -0,0 +1,44 @@ +#include "giotypes.h" + +typedef struct _GApplicationImpl GApplicationImpl; + +typedef struct +{ + gchar *name; + + GVariantType *parameter_type; + gboolean enabled; + GVariant *state; +} RemoteActionInfo; + +void g_application_impl_destroy (GApplicationImpl *impl); + +GApplicationImpl * g_application_impl_register (GApplication *application, + const gchar *appid, + GApplicationFlags flags, + GActionGroup *exported_actions, + GRemoteActionGroup **remote_actions, + GCancellable *cancellable, + GError **error); + +void g_application_impl_activate (GApplicationImpl *impl, + GVariant *platform_data); + +void g_application_impl_open (GApplicationImpl *impl, + GFile **files, + gint n_files, + const gchar *hint, + GVariant *platform_data); + +int g_application_impl_command_line (GApplicationImpl *impl, + const gchar *const *arguments, + GVariant *platform_data); + +void g_application_impl_flush (GApplicationImpl *impl); + +GDBusConnection * g_application_impl_get_dbus_connection (GApplicationImpl *impl); + +const gchar * g_application_impl_get_dbus_object_path (GApplicationImpl *impl); + +void g_application_impl_set_busy_state (GApplicationImpl *impl, + gboolean busy);
diff --git a/gio/gasynchelper.c b/gio/gasynchelper.c new file mode 100644 index 0000000..8b18835 --- /dev/null +++ b/gio/gasynchelper.c
@@ -0,0 +1,87 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" + +#include "gasynchelper.h" + + +/*< private > + * SECTION:gasynchelper + * @short_description: Asynchronous Helper Functions + * @include: gio/gio.h + * @see_also: #GAsyncResult + * + * Provides helper functions for asynchronous operations. + * + **/ + +#ifdef G_OS_WIN32 +gboolean +_g_win32_overlap_wait_result (HANDLE hfile, + OVERLAPPED *overlap, + DWORD *transferred, + GCancellable *cancellable) +{ + GPollFD pollfd[2]; + gboolean result = FALSE; + gint num, npoll; + +#if GLIB_SIZEOF_VOID_P == 8 + pollfd[0].fd = (gint64)overlap->hEvent; +#else + pollfd[0].fd = (gint)overlap->hEvent; +#endif + pollfd[0].events = G_IO_IN; + num = 1; + + if (g_cancellable_make_pollfd (cancellable, &pollfd[1])) + num++; + +loop: + npoll = g_poll (pollfd, num, -1); + if (npoll <= 0) + /* error out, should never happen */ + goto end; + + if (g_cancellable_is_cancelled (cancellable)) + { + /* CancelIO only cancels pending operations issued by the + * current thread and since we're doing only sync operations, + * this is safe.... */ + /* CancelIoEx is only Vista+. Since we have only one overlap + * operation on this thread, we can just use: */ + result = CancelIo (hfile); + g_warn_if_fail (result); + } + + result = GetOverlappedResult (overlap->hEvent, overlap, transferred, FALSE); + if (result == FALSE && + GetLastError () == ERROR_IO_INCOMPLETE && + !g_cancellable_is_cancelled (cancellable)) + goto loop; + +end: + if (num > 1) + g_cancellable_release_fd (cancellable); + + return result; +} +#endif
diff --git a/gio/gasynchelper.h b/gio/gasynchelper.h new file mode 100644 index 0000000..ded5a22 --- /dev/null +++ b/gio/gasynchelper.h
@@ -0,0 +1,41 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_ASYNC_HELPER_H__ +#define __G_ASYNC_HELPER_H__ + +#include <gio/gio.h> + +#ifdef G_OS_WIN32 +#include <windows.h> +#endif + +G_BEGIN_DECLS + +#ifdef G_OS_WIN32 +gboolean _g_win32_overlap_wait_result (HANDLE hfile, + OVERLAPPED *overlap, + DWORD *transferred, + GCancellable *cancellable); +#endif + +G_END_DECLS + +#endif /* __G_ASYNC_HELPER_H__ */
diff --git a/gio/gasyncinitable.c b/gio/gasyncinitable.c new file mode 100644 index 0000000..8936f98 --- /dev/null +++ b/gio/gasyncinitable.c
@@ -0,0 +1,463 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" +#include "gasyncinitable.h" +#include "gasyncresult.h" +#include "gsimpleasyncresult.h" +#include "gtask.h" +#include "glibintl.h" + + +/** + * SECTION:gasyncinitable + * @short_description: Asynchronously failable object initialization interface + * @include: gio/gio.h + * @see_also: #GInitable + * + * This is the asynchronous version of #GInitable; it behaves the same + * in all ways except that initialization is asynchronous. For more details + * see the descriptions on #GInitable. + * + * A class may implement both the #GInitable and #GAsyncInitable interfaces. + * + * Users of objects implementing this are not intended to use the interface + * method directly; instead it will be used automatically in various ways. + * For C applications you generally just call g_async_initable_new_async() + * directly, or indirectly via a foo_thing_new_async() wrapper. This will call + * g_async_initable_init_async() under the cover, calling back with %NULL and + * a set %GError on failure. + * + * A typical implementation might look something like this: + * + * |[<!-- language="C" --> + * enum { + * NOT_INITIALIZED, + * INITIALIZING, + * INITIALIZED + * }; + * + * static void + * _foo_ready_cb (Foo *self) + * { + * GList *l; + * + * self->priv->state = INITIALIZED; + * + * for (l = self->priv->init_results; l != NULL; l = l->next) + * { + * GTask *task = l->data; + * + * if (self->priv->success) + * g_task_return_boolean (task, TRUE); + * else + * g_task_return_new_error (task, ...); + * g_object_unref (task); + * } + * + * g_list_free (self->priv->init_results); + * self->priv->init_results = NULL; + * } + * + * static void + * foo_init_async (GAsyncInitable *initable, + * int io_priority, + * GCancellable *cancellable, + * GAsyncReadyCallback callback, + * gpointer user_data) + * { + * Foo *self = FOO (initable); + * GTask *task; + * + * task = g_task_new (initable, cancellable, callback, user_data); + * + * switch (self->priv->state) + * { + * case NOT_INITIALIZED: + * _foo_get_ready (self); + * self->priv->init_results = g_list_append (self->priv->init_results, + * task); + * self->priv->state = INITIALIZING; + * break; + * case INITIALIZING: + * self->priv->init_results = g_list_append (self->priv->init_results, + * task); + * break; + * case INITIALIZED: + * if (!self->priv->success) + * g_task_return_new_error (task, ...); + * else + * g_task_return_boolean (task, TRUE); + * g_object_unref (task); + * break; + * } + * } + * + * static gboolean + * foo_init_finish (GAsyncInitable *initable, + * GAsyncResult *result, + * GError **error) + * { + * g_return_val_if_fail (g_task_is_valid (result, initable), FALSE); + * + * return g_task_propagate_boolean (G_TASK (result), error); + * } + * + * static void + * foo_async_initable_iface_init (gpointer g_iface, + * gpointer data) + * { + * GAsyncInitableIface *iface = g_iface; + * + * iface->init_async = foo_init_async; + * iface->init_finish = foo_init_finish; + * } + * ]| + */ + +static void g_async_initable_real_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +static gboolean g_async_initable_real_init_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error); + + +typedef GAsyncInitableIface GAsyncInitableInterface; +G_DEFINE_INTERFACE (GAsyncInitable, g_async_initable, G_TYPE_OBJECT) + + +static void +g_async_initable_default_init (GAsyncInitableInterface *iface) +{ + iface->init_async = g_async_initable_real_init_async; + iface->init_finish = g_async_initable_real_init_finish; +} + +/** + * g_async_initable_init_async: + * @initable: a #GAsyncInitable. + * @io_priority: the [I/O priority][io-priority] of the operation + * @cancellable: optional #GCancellable object, %NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: the data to pass to callback function + * + * Starts asynchronous initialization of the object implementing the + * interface. This must be done before any real use of the object after + * initial construction. If the object also implements #GInitable you can + * optionally call g_initable_init() instead. + * + * This method is intended for language bindings. If writing in C, + * g_async_initable_new_async() should typically be used instead. + * + * When the initialization is finished, @callback will be called. You can + * then call g_async_initable_init_finish() to get the result of the + * initialization. + * + * Implementations may also support cancellation. If @cancellable is not + * %NULL, then initialization can be cancelled by triggering the cancellable + * object from another thread. If the operation was cancelled, the error + * %G_IO_ERROR_CANCELLED will be returned. If @cancellable is not %NULL, and + * the object doesn't support cancellable initialization, the error + * %G_IO_ERROR_NOT_SUPPORTED will be returned. + * + * As with #GInitable, if the object is not initialized, or initialization + * returns with an error, then all operations on the object except + * g_object_ref() and g_object_unref() are considered to be invalid, and + * have undefined behaviour. They will often fail with g_critical() or + * g_warning(), but this must not be relied on. + * + * Callers should not assume that a class which implements #GAsyncInitable can + * be initialized multiple times; for more information, see g_initable_init(). + * If a class explicitly supports being initialized multiple times, + * implementation requires yielding all subsequent calls to init_async() on the + * results of the first call. + * + * For classes that also support the #GInitable interface, the default + * implementation of this method will run the g_initable_init() function + * in a thread, so if you want to support asynchronous initialization via + * threads, just implement the #GAsyncInitable interface without overriding + * any interface methods. + * + * Since: 2.22 + */ +void +g_async_initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GAsyncInitableIface *iface; + + g_return_if_fail (G_IS_ASYNC_INITABLE (initable)); + + iface = G_ASYNC_INITABLE_GET_IFACE (initable); + + (* iface->init_async) (initable, io_priority, cancellable, callback, user_data); +} + +/** + * g_async_initable_init_finish: + * @initable: a #GAsyncInitable. + * @res: a #GAsyncResult. + * @error: a #GError location to store the error occurring, or %NULL to + * ignore. + * + * Finishes asynchronous initialization and returns the result. + * See g_async_initable_init_async(). + * + * Returns: %TRUE if successful. If an error has occurred, this function + * will return %FALSE and set @error appropriately if present. + * + * Since: 2.22 + */ +gboolean +g_async_initable_init_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error) +{ + GAsyncInitableIface *iface; + + g_return_val_if_fail (G_IS_ASYNC_INITABLE (initable), FALSE); + g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE); + + if (g_async_result_legacy_propagate_error (res, error)) + return FALSE; + + iface = G_ASYNC_INITABLE_GET_IFACE (initable); + + return (* iface->init_finish) (initable, res, error); +} + +static void +async_init_thread (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + GError *error = NULL; + + if (g_initable_init (G_INITABLE (source_object), cancellable, &error)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); +} + +static void +g_async_initable_real_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + g_return_if_fail (G_IS_INITABLE (initable)); + + task = g_task_new (initable, cancellable, callback, user_data); + g_task_set_source_tag (task, g_async_initable_real_init_async); + g_task_set_priority (task, io_priority); + g_task_run_in_thread (task, async_init_thread); + g_object_unref (task); +} + +static gboolean +g_async_initable_real_init_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error) +{ + /* For backward compatibility we have to process GSimpleAsyncResults + * even though g_async_initable_real_init_async doesn't generate + * them any more. + */ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + if (G_IS_SIMPLE_ASYNC_RESULT (res)) + { + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return TRUE; + } + G_GNUC_END_IGNORE_DEPRECATIONS + + g_return_val_if_fail (g_task_is_valid (res, initable), FALSE); + + return g_task_propagate_boolean (G_TASK (res), error); +} + +/** + * g_async_initable_new_async: + * @object_type: a #GType supporting #GAsyncInitable. + * @io_priority: the [I/O priority][io-priority] of the operation + * @cancellable: optional #GCancellable object, %NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the initialization is + * finished + * @user_data: the data to pass to callback function + * @first_property_name: (nullable): the name of the first property, or %NULL if no + * properties + * @...: the value of the first property, followed by other property + * value pairs, and ended by %NULL. + * + * Helper function for constructing #GAsyncInitable object. This is + * similar to g_object_new() but also initializes the object asynchronously. + * + * When the initialization is finished, @callback will be called. You can + * then call g_async_initable_new_finish() to get the new object and check + * for any errors. + * + * Since: 2.22 + */ +void +g_async_initable_new_async (GType object_type, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data, + const gchar *first_property_name, + ...) +{ + va_list var_args; + + va_start (var_args, first_property_name); + g_async_initable_new_valist_async (object_type, + first_property_name, var_args, + io_priority, cancellable, + callback, user_data); + va_end (var_args); +} + +/** + * g_async_initable_newv_async: + * @object_type: a #GType supporting #GAsyncInitable. + * @n_parameters: the number of parameters in @parameters + * @parameters: the parameters to use to construct the object + * @io_priority: the [I/O priority][io-priority] of the operation + * @cancellable: optional #GCancellable object, %NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the initialization is + * finished + * @user_data: the data to pass to callback function + * + * Helper function for constructing #GAsyncInitable object. This is + * similar to g_object_newv() but also initializes the object asynchronously. + * + * When the initialization is finished, @callback will be called. You can + * then call g_async_initable_new_finish() to get the new object and check + * for any errors. + * + * Since: 2.22 + * Deprecated: 2.54: Use g_object_new_with_properties() and + * g_async_initable_init_async() instead. See #GParameter for more information. + */ +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +void +g_async_initable_newv_async (GType object_type, + guint n_parameters, + GParameter *parameters, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GObject *obj; + + g_return_if_fail (G_TYPE_IS_ASYNC_INITABLE (object_type)); + + obj = g_object_newv (object_type, n_parameters, parameters); + + g_async_initable_init_async (G_ASYNC_INITABLE (obj), + io_priority, cancellable, + callback, user_data); + g_object_unref (obj); /* Passed ownership to async call */ +} +G_GNUC_END_IGNORE_DEPRECATIONS + +/** + * g_async_initable_new_valist_async: + * @object_type: a #GType supporting #GAsyncInitable. + * @first_property_name: the name of the first property, followed by + * the value, and other property value pairs, and ended by %NULL. + * @var_args: The var args list generated from @first_property_name. + * @io_priority: the [I/O priority][io-priority] of the operation + * @cancellable: optional #GCancellable object, %NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the initialization is + * finished + * @user_data: the data to pass to callback function + * + * Helper function for constructing #GAsyncInitable object. This is + * similar to g_object_new_valist() but also initializes the object + * asynchronously. + * + * When the initialization is finished, @callback will be called. You can + * then call g_async_initable_new_finish() to get the new object and check + * for any errors. + * + * Since: 2.22 + */ +void +g_async_initable_new_valist_async (GType object_type, + const gchar *first_property_name, + va_list var_args, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GObject *obj; + + g_return_if_fail (G_TYPE_IS_ASYNC_INITABLE (object_type)); + + obj = g_object_new_valist (object_type, + first_property_name, + var_args); + + g_async_initable_init_async (G_ASYNC_INITABLE (obj), + io_priority, cancellable, + callback, user_data); + g_object_unref (obj); /* Passed ownership to async call */ +} + +/** + * g_async_initable_new_finish: + * @initable: the #GAsyncInitable from the callback + * @res: the #GAsyncResult from the callback + * @error: return location for errors, or %NULL to ignore + * + * Finishes the async construction for the various g_async_initable_new + * calls, returning the created object or %NULL on error. + * + * Returns: (type GObject.Object) (transfer full): a newly created #GObject, + * or %NULL on error. Free with g_object_unref(). + * + * Since: 2.22 + */ +GObject * +g_async_initable_new_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error) +{ + if (g_async_initable_init_finish (initable, res, error)) + return g_object_ref (G_OBJECT (initable)); + else + return NULL; +}
diff --git a/gio/gasyncinitable.h b/gio/gasyncinitable.h new file mode 100644 index 0000000..f30d2ce --- /dev/null +++ b/gio/gasyncinitable.h
@@ -0,0 +1,130 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_ASYNC_INITABLE_H__ +#define __G_ASYNC_INITABLE_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> +#include <gio/ginitable.h> + +G_BEGIN_DECLS + +#define G_TYPE_ASYNC_INITABLE (g_async_initable_get_type ()) +#define G_ASYNC_INITABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ASYNC_INITABLE, GAsyncInitable)) +#define G_IS_ASYNC_INITABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ASYNC_INITABLE)) +#define G_ASYNC_INITABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_ASYNC_INITABLE, GAsyncInitableIface)) +#define G_TYPE_IS_ASYNC_INITABLE(type) (g_type_is_a ((type), G_TYPE_ASYNC_INITABLE)) + +/** + * GAsyncInitable: + * + * Interface for asynchronously initializable objects. + * + * Since: 2.22 + **/ +typedef struct _GAsyncInitableIface GAsyncInitableIface; + +/** + * GAsyncInitableIface: + * @g_iface: The parent interface. + * @init_async: Starts initialization of the object. + * @init_finish: Finishes initialization of the object. + * + * Provides an interface for asynchronous initializing object such that + * initialization may fail. + * + * Since: 2.22 + **/ +struct _GAsyncInitableIface +{ + GTypeInterface g_iface; + + /* Virtual Table */ + + void (* init_async) (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* init_finish) (GAsyncInitable *initable, + GAsyncResult *res, + GError **error); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_async_initable_get_type (void) G_GNUC_CONST; + + +GLIB_AVAILABLE_IN_ALL +void g_async_initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GLIB_AVAILABLE_IN_ALL +gboolean g_async_initable_init_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error); + +GLIB_AVAILABLE_IN_ALL +void g_async_initable_new_async (GType object_type, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data, + const gchar *first_property_name, + ...); + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + +GLIB_DEPRECATED_IN_2_54_FOR(g_object_new_with_properties and g_async_initable_init_async) +void g_async_initable_newv_async (GType object_type, + guint n_parameters, + GParameter *parameters, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +G_GNUC_END_IGNORE_DEPRECATIONS + +GLIB_AVAILABLE_IN_ALL +void g_async_initable_new_valist_async (GType object_type, + const gchar *first_property_name, + va_list var_args, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GLIB_AVAILABLE_IN_ALL +GObject *g_async_initable_new_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error); + + + +G_END_DECLS + + +#endif /* __G_ASYNC_INITABLE_H__ */
diff --git a/gio/gasyncresult.c b/gio/gasyncresult.c new file mode 100644 index 0000000..b96f1ee --- /dev/null +++ b/gio/gasyncresult.c
@@ -0,0 +1,237 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" +#include "gasyncresult.h" +#include "gsimpleasyncresult.h" +#include "glibintl.h" + + +/** + * SECTION:gasyncresult + * @short_description: Asynchronous Function Results + * @include: gio/gio.h + * @see_also: #GTask + * + * Provides a base class for implementing asynchronous function results. + * + * Asynchronous operations are broken up into two separate operations + * which are chained together by a #GAsyncReadyCallback. To begin + * an asynchronous operation, provide a #GAsyncReadyCallback to the + * asynchronous function. This callback will be triggered when the + * operation has completed, and must be run in a later iteration of + * the [thread-default main context][g-main-context-push-thread-default] + * from where the operation was initiated. It will be passed a + * #GAsyncResult instance filled with the details of the operation's + * success or failure, the object the asynchronous function was + * started for and any error codes returned. The asynchronous callback + * function is then expected to call the corresponding "_finish()" + * function, passing the object the function was called for, the + * #GAsyncResult instance, and (optionally) an @error to grab any + * error conditions that may have occurred. + * + * The "_finish()" function for an operation takes the generic result + * (of type #GAsyncResult) and returns the specific result that the + * operation in question yields (e.g. a #GFileEnumerator for a + * "enumerate children" operation). If the result or error status of the + * operation is not needed, there is no need to call the "_finish()" + * function; GIO will take care of cleaning up the result and error + * information after the #GAsyncReadyCallback returns. You can pass + * %NULL for the #GAsyncReadyCallback if you don't need to take any + * action at all after the operation completes. Applications may also + * take a reference to the #GAsyncResult and call "_finish()" later; + * however, the "_finish()" function may be called at most once. + * + * Example of a typical asynchronous operation flow: + * |[<!-- language="C" --> + * void _theoretical_frobnitz_async (Theoretical *t, + * GCancellable *c, + * GAsyncReadyCallback cb, + * gpointer u); + * + * gboolean _theoretical_frobnitz_finish (Theoretical *t, + * GAsyncResult *res, + * GError **e); + * + * static void + * frobnitz_result_func (GObject *source_object, + * GAsyncResult *res, + * gpointer user_data) + * { + * gboolean success = FALSE; + * + * success = _theoretical_frobnitz_finish (source_object, res, NULL); + * + * if (success) + * g_printf ("Hurray!\n"); + * else + * g_printf ("Uh oh!\n"); + * + * ... + * + * } + * + * int main (int argc, void *argv[]) + * { + * ... + * + * _theoretical_frobnitz_async (theoretical_data, + * NULL, + * frobnitz_result_func, + * NULL); + * + * ... + * } + * ]| + * + * The callback for an asynchronous operation is called only once, and is + * always called, even in the case of a cancelled operation. On cancellation + * the result is a %G_IO_ERROR_CANCELLED error. + * + * ## I/O Priority # {#io-priority} + * + * Many I/O-related asynchronous operations have a priority parameter, + * which is used in certain cases to determine the order in which + * operations are executed. They are not used to determine system-wide + * I/O scheduling. Priorities are integers, with lower numbers indicating + * higher priority. It is recommended to choose priorities between + * %G_PRIORITY_LOW and %G_PRIORITY_HIGH, with %G_PRIORITY_DEFAULT + * as a default. + */ + +typedef GAsyncResultIface GAsyncResultInterface; +G_DEFINE_INTERFACE (GAsyncResult, g_async_result, G_TYPE_OBJECT) + +static void +g_async_result_default_init (GAsyncResultInterface *iface) +{ +} + +/** + * g_async_result_get_user_data: + * @res: a #GAsyncResult. + * + * Gets the user data from a #GAsyncResult. + * + * Returns: (transfer full): the user data for @res. + **/ +gpointer +g_async_result_get_user_data (GAsyncResult *res) +{ + GAsyncResultIface *iface; + + g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL); + + iface = G_ASYNC_RESULT_GET_IFACE (res); + + return (* iface->get_user_data) (res); +} + +/** + * g_async_result_get_source_object: + * @res: a #GAsyncResult + * + * Gets the source object from a #GAsyncResult. + * + * Returns: (transfer full) (nullable): a new reference to the source + * object for the @res, or %NULL if there is none. + */ +GObject * +g_async_result_get_source_object (GAsyncResult *res) +{ + GAsyncResultIface *iface; + + g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL); + + iface = G_ASYNC_RESULT_GET_IFACE (res); + + return (* iface->get_source_object) (res); +} + +/** + * g_async_result_legacy_propagate_error: + * @res: a #GAsyncResult + * @error: (out): a location to propagate the error to. + * + * If @res is a #GSimpleAsyncResult, this is equivalent to + * g_simple_async_result_propagate_error(). Otherwise it returns + * %FALSE. + * + * This can be used for legacy error handling in async *_finish() + * wrapper functions that traditionally handled #GSimpleAsyncResult + * error returns themselves rather than calling into the virtual method. + * This should not be used in new code; #GAsyncResult errors that are + * set by virtual methods should also be extracted by virtual methods, + * to enable subclasses to chain up correctly. + * + * Returns: %TRUE if @error is has been filled in with an error from + * @res, %FALSE if not. + * + * Since: 2.34 + **/ +gboolean +g_async_result_legacy_propagate_error (GAsyncResult *res, + GError **error) +{ + /* This doesn't use a vmethod, because it's only for code that used + * to use GSimpleAsyncResult. (But it's a GAsyncResult method so + * that callers don't need to worry about GSimpleAsyncResult + * deprecation warnings in the future.) + */ + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + if (G_IS_SIMPLE_ASYNC_RESULT (res)) + { + return g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), + error); + } + else + return FALSE; + G_GNUC_END_IGNORE_DEPRECATIONS +} + +/** + * g_async_result_is_tagged: + * @res: a #GAsyncResult + * @source_tag: an application-defined tag + * + * Checks if @res has the given @source_tag (generally a function + * pointer indicating the function @res was created by). + * + * Returns: %TRUE if @res has the indicated @source_tag, %FALSE if + * not. + * + * Since: 2.34 + **/ +gboolean +g_async_result_is_tagged (GAsyncResult *res, + gpointer source_tag) +{ + GAsyncResultIface *iface; + + g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE); + + iface = G_ASYNC_RESULT_GET_IFACE (res); + + if (!iface->is_tagged) + return FALSE; + + return (* iface->is_tagged) (res, source_tag); +}
diff --git a/gio/gasyncresult.h b/gio/gasyncresult.h new file mode 100644 index 0000000..956cbc4 --- /dev/null +++ b/gio/gasyncresult.h
@@ -0,0 +1,85 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_ASYNC_RESULT_H__ +#define __G_ASYNC_RESULT_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_ASYNC_RESULT (g_async_result_get_type ()) +#define G_ASYNC_RESULT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ASYNC_RESULT, GAsyncResult)) +#define G_IS_ASYNC_RESULT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ASYNC_RESULT)) +#define G_ASYNC_RESULT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_ASYNC_RESULT, GAsyncResultIface)) + +/** + * GAsyncResult: + * + * Holds results information for an asynchronous operation, + * usually passed directly to an asynchronous _finish() operation. + **/ +typedef struct _GAsyncResultIface GAsyncResultIface; + + +/** + * GAsyncResultIface: + * @g_iface: The parent interface. + * @get_user_data: Gets the user data passed to the callback. + * @get_source_object: Gets the source object that issued the asynchronous operation. + * @is_tagged: Checks if a result is tagged with a particular source. + * + * Interface definition for #GAsyncResult. + **/ +struct _GAsyncResultIface +{ + GTypeInterface g_iface; + + /* Virtual Table */ + + gpointer (* get_user_data) (GAsyncResult *res); + GObject * (* get_source_object) (GAsyncResult *res); + + gboolean (* is_tagged) (GAsyncResult *res, + gpointer source_tag); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_async_result_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +gpointer g_async_result_get_user_data (GAsyncResult *res); +GLIB_AVAILABLE_IN_ALL +GObject *g_async_result_get_source_object (GAsyncResult *res); + +GLIB_AVAILABLE_IN_2_34 +gboolean g_async_result_legacy_propagate_error (GAsyncResult *res, + GError **error); +GLIB_AVAILABLE_IN_2_34 +gboolean g_async_result_is_tagged (GAsyncResult *res, + gpointer source_tag); + +G_END_DECLS + +#endif /* __G_ASYNC_RESULT_H__ */
diff --git a/gio/gbufferedinputstream.c b/gio/gbufferedinputstream.c new file mode 100644 index 0000000..f5090d0 --- /dev/null +++ b/gio/gbufferedinputstream.c
@@ -0,0 +1,1270 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * Copyright (C) 2007 Jürg Billeter + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Christian Kellner <gicmo@gnome.org> + */ + +#include "config.h" +#include "gbufferedinputstream.h" +#include "ginputstream.h" +#include "gcancellable.h" +#include "gasyncresult.h" +#include "gtask.h" +#include "gseekable.h" +#include "gioerror.h" +#include <string.h> +#include "glibintl.h" + + +/** + * SECTION:gbufferedinputstream + * @short_description: Buffered Input Stream + * @include: gio/gio.h + * @see_also: #GFilterInputStream, #GInputStream + * + * Buffered input stream implements #GFilterInputStream and provides + * for buffered reads. + * + * By default, #GBufferedInputStream's buffer size is set at 4 kilobytes. + * + * To create a buffered input stream, use g_buffered_input_stream_new(), + * or g_buffered_input_stream_new_sized() to specify the buffer's size at + * construction. + * + * To get the size of a buffer within a buffered input stream, use + * g_buffered_input_stream_get_buffer_size(). To change the size of a + * buffered input stream's buffer, use + * g_buffered_input_stream_set_buffer_size(). Note that the buffer's size + * cannot be reduced below the size of the data within the buffer. + */ + + +#define DEFAULT_BUFFER_SIZE 4096 + +struct _GBufferedInputStreamPrivate { + guint8 *buffer; + gsize len; + gsize pos; + gsize end; + GAsyncReadyCallback outstanding_callback; +}; + +enum { + PROP_0, + PROP_BUFSIZE +}; + +static void g_buffered_input_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +static void g_buffered_input_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void g_buffered_input_stream_finalize (GObject *object); + + +static gssize g_buffered_input_stream_skip (GInputStream *stream, + gsize count, + GCancellable *cancellable, + GError **error); +static void g_buffered_input_stream_skip_async (GInputStream *stream, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +static gssize g_buffered_input_stream_skip_finish (GInputStream *stream, + GAsyncResult *result, + GError **error); +static gssize g_buffered_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error); +static gssize g_buffered_input_stream_real_fill (GBufferedInputStream *stream, + gssize count, + GCancellable *cancellable, + GError **error); +static void g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream, + gssize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +static gssize g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream, + GAsyncResult *result, + GError **error); + +static void g_buffered_input_stream_seekable_iface_init (GSeekableIface *iface); +static goffset g_buffered_input_stream_tell (GSeekable *seekable); +static gboolean g_buffered_input_stream_can_seek (GSeekable *seekable); +static gboolean g_buffered_input_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error); +static gboolean g_buffered_input_stream_can_truncate (GSeekable *seekable); +static gboolean g_buffered_input_stream_truncate (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error); + +static void compact_buffer (GBufferedInputStream *stream); + +G_DEFINE_TYPE_WITH_CODE (GBufferedInputStream, + g_buffered_input_stream, + G_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (GBufferedInputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, + g_buffered_input_stream_seekable_iface_init)) + +static void +g_buffered_input_stream_class_init (GBufferedInputStreamClass *klass) +{ + GObjectClass *object_class; + GInputStreamClass *istream_class; + GBufferedInputStreamClass *bstream_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->get_property = g_buffered_input_stream_get_property; + object_class->set_property = g_buffered_input_stream_set_property; + object_class->finalize = g_buffered_input_stream_finalize; + + istream_class = G_INPUT_STREAM_CLASS (klass); + istream_class->skip = g_buffered_input_stream_skip; + istream_class->skip_async = g_buffered_input_stream_skip_async; + istream_class->skip_finish = g_buffered_input_stream_skip_finish; + istream_class->read_fn = g_buffered_input_stream_read; + + bstream_class = G_BUFFERED_INPUT_STREAM_CLASS (klass); + bstream_class->fill = g_buffered_input_stream_real_fill; + bstream_class->fill_async = g_buffered_input_stream_real_fill_async; + bstream_class->fill_finish = g_buffered_input_stream_real_fill_finish; + + g_object_class_install_property (object_class, + PROP_BUFSIZE, + g_param_spec_uint ("buffer-size", + P_("Buffer Size"), + P_("The size of the backend buffer"), + 1, + G_MAXUINT, + DEFAULT_BUFFER_SIZE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + + +} + +/** + * g_buffered_input_stream_get_buffer_size: + * @stream: a #GBufferedInputStream + * + * Gets the size of the input buffer. + * + * Returns: the current buffer size. + */ +gsize +g_buffered_input_stream_get_buffer_size (GBufferedInputStream *stream) +{ + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), 0); + + return stream->priv->len; +} + +/** + * g_buffered_input_stream_set_buffer_size: + * @stream: a #GBufferedInputStream + * @size: a #gsize + * + * Sets the size of the internal buffer of @stream to @size, or to the + * size of the contents of the buffer. The buffer can never be resized + * smaller than its current contents. + */ +void +g_buffered_input_stream_set_buffer_size (GBufferedInputStream *stream, + gsize size) +{ + GBufferedInputStreamPrivate *priv; + gsize in_buffer; + guint8 *buffer; + + g_return_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream)); + + priv = stream->priv; + + if (priv->len == size) + return; + + if (priv->buffer) + { + in_buffer = priv->end - priv->pos; + + /* Never resize smaller than current buffer contents */ + size = MAX (size, in_buffer); + + buffer = g_malloc (size); + memcpy (buffer, priv->buffer + priv->pos, in_buffer); + priv->len = size; + priv->pos = 0; + priv->end = in_buffer; + g_free (priv->buffer); + priv->buffer = buffer; + } + else + { + priv->len = size; + priv->pos = 0; + priv->end = 0; + priv->buffer = g_malloc (size); + } + + g_object_notify (G_OBJECT (stream), "buffer-size"); +} + +static void +g_buffered_input_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GBufferedInputStream *bstream; + + bstream = G_BUFFERED_INPUT_STREAM (object); + + switch (prop_id) + { + case PROP_BUFSIZE: + g_buffered_input_stream_set_buffer_size (bstream, g_value_get_uint (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_buffered_input_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GBufferedInputStreamPrivate *priv; + GBufferedInputStream *bstream; + + bstream = G_BUFFERED_INPUT_STREAM (object); + priv = bstream->priv; + + switch (prop_id) + { + case PROP_BUFSIZE: + g_value_set_uint (value, priv->len); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_buffered_input_stream_finalize (GObject *object) +{ + GBufferedInputStreamPrivate *priv; + GBufferedInputStream *stream; + + stream = G_BUFFERED_INPUT_STREAM (object); + priv = stream->priv; + + g_free (priv->buffer); + + G_OBJECT_CLASS (g_buffered_input_stream_parent_class)->finalize (object); +} + +static void +g_buffered_input_stream_seekable_iface_init (GSeekableIface *iface) +{ + iface->tell = g_buffered_input_stream_tell; + iface->can_seek = g_buffered_input_stream_can_seek; + iface->seek = g_buffered_input_stream_seek; + iface->can_truncate = g_buffered_input_stream_can_truncate; + iface->truncate_fn = g_buffered_input_stream_truncate; +} + +static void +g_buffered_input_stream_init (GBufferedInputStream *stream) +{ + stream->priv = g_buffered_input_stream_get_instance_private (stream); +} + + +/** + * g_buffered_input_stream_new: + * @base_stream: a #GInputStream + * + * Creates a new #GInputStream from the given @base_stream, with + * a buffer set to the default size (4 kilobytes). + * + * Returns: a #GInputStream for the given @base_stream. + */ +GInputStream * +g_buffered_input_stream_new (GInputStream *base_stream) +{ + GInputStream *stream; + + g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL); + + stream = g_object_new (G_TYPE_BUFFERED_INPUT_STREAM, + "base-stream", base_stream, + NULL); + + return stream; +} + +/** + * g_buffered_input_stream_new_sized: + * @base_stream: a #GInputStream + * @size: a #gsize + * + * Creates a new #GBufferedInputStream from the given @base_stream, + * with a buffer set to @size. + * + * Returns: a #GInputStream. + */ +GInputStream * +g_buffered_input_stream_new_sized (GInputStream *base_stream, + gsize size) +{ + GInputStream *stream; + + g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL); + + stream = g_object_new (G_TYPE_BUFFERED_INPUT_STREAM, + "base-stream", base_stream, + "buffer-size", (guint)size, + NULL); + + return stream; +} + +/** + * g_buffered_input_stream_fill: + * @stream: a #GBufferedInputStream + * @count: the number of bytes that will be read from the stream + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore + * @error: location to store the error occurring, or %NULL to ignore + * + * Tries to read @count bytes from the stream into the buffer. + * Will block during this read. + * + * If @count is zero, returns zero and does nothing. A value of @count + * larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error. + * + * On success, the number of bytes read into the buffer is returned. + * It is not an error if this is not the same as the requested size, as it + * can happen e.g. near the end of a file. Zero is returned on end of file + * (or if @count is zero), but never otherwise. + * + * If @count is -1 then the attempted read size is equal to the number of + * bytes that are required to fill the buffer. + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an + * operation was partially finished when the operation was cancelled the + * partial result will be returned, without an error. + * + * On error -1 is returned and @error is set accordingly. + * + * For the asynchronous, non-blocking, version of this function, see + * g_buffered_input_stream_fill_async(). + * + * Returns: the number of bytes read into @stream's buffer, up to @count, + * or -1 on error. + */ +gssize +g_buffered_input_stream_fill (GBufferedInputStream *stream, + gssize count, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStreamClass *class; + GInputStream *input_stream; + gssize res; + + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); + + input_stream = G_INPUT_STREAM (stream); + + if (count < -1) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Too large count value passed to %s"), G_STRFUNC); + return -1; + } + + if (!g_input_stream_set_pending (input_stream, error)) + return -1; + + if (cancellable) + g_cancellable_push_current (cancellable); + + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + res = class->fill (stream, count, cancellable, error); + + if (cancellable) + g_cancellable_pop_current (cancellable); + + g_input_stream_clear_pending (input_stream); + + return res; +} + +static void +async_fill_callback_wrapper (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GBufferedInputStream *stream = G_BUFFERED_INPUT_STREAM (source_object); + + g_input_stream_clear_pending (G_INPUT_STREAM (stream)); + (*stream->priv->outstanding_callback) (source_object, res, user_data); + g_object_unref (stream); +} + +/** + * g_buffered_input_stream_fill_async: + * @stream: a #GBufferedInputStream + * @count: the number of bytes that will be read from the stream + * @io_priority: the [I/O priority][io-priority] of the request + * @cancellable: (nullable): optional #GCancellable object + * @callback: (scope async): a #GAsyncReadyCallback + * @user_data: (closure): a #gpointer + * + * Reads data into @stream's buffer asynchronously, up to @count size. + * @io_priority can be used to prioritize reads. For the synchronous + * version of this function, see g_buffered_input_stream_fill(). + * + * If @count is -1 then the attempted read size is equal to the number + * of bytes that are required to fill the buffer. + */ +void +g_buffered_input_stream_fill_async (GBufferedInputStream *stream, + gssize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GBufferedInputStreamClass *class; + GError *error = NULL; + + g_return_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream)); + + if (count == 0) + { + GTask *task; + + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_source_tag (task, g_buffered_input_stream_fill_async); + g_task_return_int (task, 0); + g_object_unref (task); + return; + } + + if (count < -1) + { + g_task_report_new_error (stream, callback, user_data, + g_buffered_input_stream_fill_async, + G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Too large count value passed to %s"), + G_STRFUNC); + return; + } + + if (!g_input_stream_set_pending (G_INPUT_STREAM (stream), &error)) + { + g_task_report_error (stream, callback, user_data, + g_buffered_input_stream_fill_async, + error); + return; + } + + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + + stream->priv->outstanding_callback = callback; + g_object_ref (stream); + class->fill_async (stream, count, io_priority, cancellable, + async_fill_callback_wrapper, user_data); +} + +/** + * g_buffered_input_stream_fill_finish: + * @stream: a #GBufferedInputStream + * @result: a #GAsyncResult + * @error: a #GError + * + * Finishes an asynchronous read. + * + * Returns: a #gssize of the read stream, or `-1` on an error. + */ +gssize +g_buffered_input_stream_fill_finish (GBufferedInputStream *stream, + GAsyncResult *result, + GError **error) +{ + GBufferedInputStreamClass *class; + + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); + g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1); + + if (g_async_result_legacy_propagate_error (result, error)) + return -1; + else if (g_async_result_is_tagged (result, g_buffered_input_stream_fill_async)) + return g_task_propagate_int (G_TASK (result), error); + + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + return class->fill_finish (stream, result, error); +} + +/** + * g_buffered_input_stream_get_available: + * @stream: #GBufferedInputStream + * + * Gets the size of the available data within the stream. + * + * Returns: size of the available stream. + */ +gsize +g_buffered_input_stream_get_available (GBufferedInputStream *stream) +{ + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); + + return stream->priv->end - stream->priv->pos; +} + +/** + * g_buffered_input_stream_peek: + * @stream: a #GBufferedInputStream + * @buffer: (array length=count) (element-type guint8): a pointer to + * an allocated chunk of memory + * @offset: a #gsize + * @count: a #gsize + * + * Peeks in the buffer, copying data of size @count into @buffer, + * offset @offset bytes. + * + * Returns: a #gsize of the number of bytes peeked, or -1 on error. + */ +gsize +g_buffered_input_stream_peek (GBufferedInputStream *stream, + void *buffer, + gsize offset, + gsize count) +{ + gsize available; + gsize end; + + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); + g_return_val_if_fail (buffer != NULL, -1); + + available = g_buffered_input_stream_get_available (stream); + + if (offset > available) + return 0; + + end = MIN (offset + count, available); + count = end - offset; + + memcpy (buffer, stream->priv->buffer + stream->priv->pos + offset, count); + return count; +} + +/** + * g_buffered_input_stream_peek_buffer: + * @stream: a #GBufferedInputStream + * @count: (out): a #gsize to get the number of bytes available in the buffer + * + * Returns the buffer with the currently available bytes. The returned + * buffer must not be modified and will become invalid when reading from + * the stream or filling the buffer. + * + * Returns: (array length=count) (element-type guint8) (transfer none): + * read-only buffer + */ +const void* +g_buffered_input_stream_peek_buffer (GBufferedInputStream *stream, + gsize *count) +{ + GBufferedInputStreamPrivate *priv; + + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), NULL); + + priv = stream->priv; + + if (count) + *count = priv->end - priv->pos; + + return priv->buffer + priv->pos; +} + +static void +compact_buffer (GBufferedInputStream *stream) +{ + GBufferedInputStreamPrivate *priv; + gsize current_size; + + priv = stream->priv; + + current_size = priv->end - priv->pos; + + memmove (priv->buffer, priv->buffer + priv->pos, current_size); + + priv->pos = 0; + priv->end = current_size; +} + +static gssize +g_buffered_input_stream_real_fill (GBufferedInputStream *stream, + gssize count, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStreamPrivate *priv; + GInputStream *base_stream; + gssize nread; + gsize in_buffer; + + priv = stream->priv; + + if (count == -1) + count = priv->len; + + in_buffer = priv->end - priv->pos; + + /* Never fill more than can fit in the buffer */ + count = MIN (count, priv->len - in_buffer); + + /* If requested length does not fit at end, compact */ + if (priv->len - priv->end < count) + compact_buffer (stream); + + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + nread = g_input_stream_read (base_stream, + priv->buffer + priv->end, + count, + cancellable, + error); + + if (nread > 0) + priv->end += nread; + + return nread; +} + +static gssize +g_buffered_input_stream_skip (GInputStream *stream, + gsize count, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStream *bstream; + GBufferedInputStreamPrivate *priv; + GBufferedInputStreamClass *class; + GInputStream *base_stream; + gsize available, bytes_skipped; + gssize nread; + + bstream = G_BUFFERED_INPUT_STREAM (stream); + priv = bstream->priv; + + available = priv->end - priv->pos; + + if (count <= available) + { + priv->pos += count; + return count; + } + + /* Full request not available, skip all currently available and + * request refill for more + */ + + priv->pos = 0; + priv->end = 0; + bytes_skipped = available; + count -= available; + + if (bytes_skipped > 0) + error = NULL; /* Ignore further errors if we already read some data */ + + if (count > priv->len) + { + /* Large request, shortcut buffer */ + + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + + nread = g_input_stream_skip (base_stream, + count, + cancellable, + error); + + if (nread < 0 && bytes_skipped == 0) + return -1; + + if (nread > 0) + bytes_skipped += nread; + + return bytes_skipped; + } + + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + nread = class->fill (bstream, priv->len, cancellable, error); + + if (nread < 0) + { + if (bytes_skipped == 0) + return -1; + else + return bytes_skipped; + } + + available = priv->end - priv->pos; + count = MIN (count, available); + + bytes_skipped += count; + priv->pos += count; + + return bytes_skipped; +} + +static gssize +g_buffered_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStream *bstream; + GBufferedInputStreamPrivate *priv; + GBufferedInputStreamClass *class; + GInputStream *base_stream; + gsize available, bytes_read; + gssize nread; + + bstream = G_BUFFERED_INPUT_STREAM (stream); + priv = bstream->priv; + + available = priv->end - priv->pos; + + if (count <= available) + { + memcpy (buffer, priv->buffer + priv->pos, count); + priv->pos += count; + return count; + } + + /* Full request not available, read all currently available and + * request refill for more + */ + + memcpy (buffer, priv->buffer + priv->pos, available); + priv->pos = 0; + priv->end = 0; + bytes_read = available; + count -= available; + + if (bytes_read > 0) + error = NULL; /* Ignore further errors if we already read some data */ + + if (count > priv->len) + { + /* Large request, shortcut buffer */ + + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + + nread = g_input_stream_read (base_stream, + (char *)buffer + bytes_read, + count, + cancellable, + error); + + if (nread < 0 && bytes_read == 0) + return -1; + + if (nread > 0) + bytes_read += nread; + + return bytes_read; + } + + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + nread = class->fill (bstream, priv->len, cancellable, error); + if (nread < 0) + { + if (bytes_read == 0) + return -1; + else + return bytes_read; + } + + available = priv->end - priv->pos; + count = MIN (count, available); + + memcpy ((char *)buffer + bytes_read, (char *)priv->buffer + priv->pos, count); + bytes_read += count; + priv->pos += count; + + return bytes_read; +} + +static goffset +g_buffered_input_stream_tell (GSeekable *seekable) +{ + GBufferedInputStream *bstream; + GBufferedInputStreamPrivate *priv; + GInputStream *base_stream; + GSeekable *base_stream_seekable; + gsize available; + goffset base_offset; + + bstream = G_BUFFERED_INPUT_STREAM (seekable); + priv = bstream->priv; + + base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + return 0; + base_stream_seekable = G_SEEKABLE (base_stream); + + available = priv->end - priv->pos; + base_offset = g_seekable_tell (base_stream_seekable); + + return base_offset - available; +} + +static gboolean +g_buffered_input_stream_can_seek (GSeekable *seekable) +{ + GInputStream *base_stream; + + base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream; + return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream)); +} + +static gboolean +g_buffered_input_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStream *bstream; + GBufferedInputStreamPrivate *priv; + GInputStream *base_stream; + GSeekable *base_stream_seekable; + + bstream = G_BUFFERED_INPUT_STREAM (seekable); + priv = bstream->priv; + + base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Seek not supported on base stream")); + return FALSE; + } + + base_stream_seekable = G_SEEKABLE (base_stream); + + if (type == G_SEEK_CUR) + { + if (offset <= priv->end - priv->pos && offset >= -priv->pos) + { + priv->pos += offset; + return TRUE; + } + else + { + offset -= priv->end - priv->pos; + } + } + + if (g_seekable_seek (base_stream_seekable, offset, type, cancellable, error)) + { + priv->pos = 0; + priv->end = 0; + return TRUE; + } + else + { + return FALSE; + } +} + +static gboolean +g_buffered_input_stream_can_truncate (GSeekable *seekable) +{ + return FALSE; +} + +static gboolean +g_buffered_input_stream_truncate (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error) +{ + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Cannot truncate GBufferedInputStream")); + return FALSE; +} + +/** + * g_buffered_input_stream_read_byte: + * @stream: a #GBufferedInputStream + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore + * @error: location to store the error occurring, or %NULL to ignore + * + * Tries to read a single byte from the stream or the buffer. Will block + * during this read. + * + * On success, the byte read from the stream is returned. On end of stream + * -1 is returned but it's not an exceptional error and @error is not set. + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an + * operation was partially finished when the operation was cancelled the + * partial result will be returned, without an error. + * + * On error -1 is returned and @error is set accordingly. + * + * Returns: the byte read from the @stream, or -1 on end of stream or error. + */ +int +g_buffered_input_stream_read_byte (GBufferedInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStreamPrivate *priv; + GBufferedInputStreamClass *class; + GInputStream *input_stream; + gsize available; + gssize nread; + + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); + + priv = stream->priv; + input_stream = G_INPUT_STREAM (stream); + + if (g_input_stream_is_closed (input_stream)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, + _("Stream is already closed")); + return -1; + } + + if (!g_input_stream_set_pending (input_stream, error)) + return -1; + + available = priv->end - priv->pos; + + if (available != 0) + { + g_input_stream_clear_pending (input_stream); + return priv->buffer[priv->pos++]; + } + + /* Byte not available, request refill for more */ + + if (cancellable) + g_cancellable_push_current (cancellable); + + priv->pos = 0; + priv->end = 0; + + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + nread = class->fill (stream, priv->len, cancellable, error); + + if (cancellable) + g_cancellable_pop_current (cancellable); + + g_input_stream_clear_pending (input_stream); + + if (nread <= 0) + return -1; /* error or end of stream */ + + return priv->buffer[priv->pos++]; +} + +/* ************************** */ +/* Async stuff implementation */ +/* ************************** */ + +static void +fill_async_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GError *error; + gssize res; + GTask *task = user_data; + + error = NULL; + res = g_input_stream_read_finish (G_INPUT_STREAM (source_object), + result, &error); + if (res == -1) + g_task_return_error (task, error); + else + { + GBufferedInputStream *stream; + GBufferedInputStreamPrivate *priv; + + stream = g_task_get_source_object (task); + priv = G_BUFFERED_INPUT_STREAM (stream)->priv; + + g_assert_cmpint (priv->end + res, <=, priv->len); + priv->end += res; + + g_task_return_int (task, res); + } + + g_object_unref (task); +} + +static void +g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream, + gssize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GBufferedInputStreamPrivate *priv; + GInputStream *base_stream; + GTask *task; + gsize in_buffer; + + priv = stream->priv; + + if (count == -1) + count = priv->len; + + in_buffer = priv->end - priv->pos; + + /* Never fill more than can fit in the buffer */ + count = MIN (count, priv->len - in_buffer); + + /* If requested length does not fit at end, compact */ + if (priv->len - priv->end < count) + compact_buffer (stream); + + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_source_tag (task, g_buffered_input_stream_real_fill_async); + + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + g_input_stream_read_async (base_stream, + priv->buffer + priv->end, + count, + io_priority, + cancellable, + fill_async_callback, + task); +} + +static gssize +g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), -1); + + return g_task_propagate_int (G_TASK (result), error); +} + +typedef struct +{ + gssize bytes_skipped; + gssize count; +} SkipAsyncData; + +static void +free_skip_async_data (gpointer _data) +{ + SkipAsyncData *data = _data; + g_slice_free (SkipAsyncData, data); +} + +static void +large_skip_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = G_TASK (user_data); + SkipAsyncData *data; + GError *error; + gssize nread; + + data = g_task_get_task_data (task); + + error = NULL; + nread = g_input_stream_skip_finish (G_INPUT_STREAM (source_object), + result, &error); + + /* Only report the error if we've not already read some data */ + if (nread < 0 && data->bytes_skipped == 0) + g_task_return_error (task, error); + else + { + if (error) + g_error_free (error); + + if (nread > 0) + data->bytes_skipped += nread; + + g_task_return_int (task, data->bytes_skipped); + } + + g_object_unref (task); +} + +static void +skip_fill_buffer_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = G_TASK (user_data); + GBufferedInputStream *bstream; + GBufferedInputStreamPrivate *priv; + SkipAsyncData *data; + GError *error; + gssize nread; + gsize available; + + bstream = G_BUFFERED_INPUT_STREAM (source_object); + priv = bstream->priv; + + data = g_task_get_task_data (task); + + error = NULL; + nread = g_buffered_input_stream_fill_finish (bstream, + result, &error); + + if (nread < 0 && data->bytes_skipped == 0) + g_task_return_error (task, error); + else + { + if (error) + g_error_free (error); + + if (nread > 0) + { + available = priv->end - priv->pos; + data->count = MIN (data->count, available); + + data->bytes_skipped += data->count; + priv->pos += data->count; + } + + g_task_return_int (task, data->bytes_skipped); + } + + g_object_unref (task); +} + +static void +g_buffered_input_stream_skip_async (GInputStream *stream, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GBufferedInputStream *bstream; + GBufferedInputStreamPrivate *priv; + GBufferedInputStreamClass *class; + GInputStream *base_stream; + gsize available; + GTask *task; + SkipAsyncData *data; + + bstream = G_BUFFERED_INPUT_STREAM (stream); + priv = bstream->priv; + + data = g_slice_new (SkipAsyncData); + data->bytes_skipped = 0; + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_source_tag (task, g_buffered_input_stream_skip_async); + g_task_set_task_data (task, data, free_skip_async_data); + + available = priv->end - priv->pos; + + if (count <= available) + { + priv->pos += count; + + g_task_return_int (task, count); + g_object_unref (task); + return; + } + + /* Full request not available, skip all currently available + * and request refill for more + */ + + priv->pos = 0; + priv->end = 0; + + count -= available; + + data->bytes_skipped = available; + data->count = count; + + if (count > priv->len) + { + /* Large request, shortcut buffer */ + + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + + g_input_stream_skip_async (base_stream, + count, + io_priority, cancellable, + large_skip_callback, + task); + } + else + { + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + class->fill_async (bstream, priv->len, io_priority, cancellable, + skip_fill_buffer_callback, task); + } +} + +static gssize +g_buffered_input_stream_skip_finish (GInputStream *stream, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), -1); + + return g_task_propagate_int (G_TASK (result), error); +}
diff --git a/gio/gbufferedinputstream.h b/gio/gbufferedinputstream.h new file mode 100644 index 0000000..19c4214 --- /dev/null +++ b/gio/gbufferedinputstream.h
@@ -0,0 +1,133 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Christian Kellner <gicmo@gnome.org> + */ + +#ifndef __G_BUFFERED_INPUT_STREAM_H__ +#define __G_BUFFERED_INPUT_STREAM_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/gfilterinputstream.h> + +G_BEGIN_DECLS + +#define G_TYPE_BUFFERED_INPUT_STREAM (g_buffered_input_stream_get_type ()) +#define G_BUFFERED_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_BUFFERED_INPUT_STREAM, GBufferedInputStream)) +#define G_BUFFERED_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_BUFFERED_INPUT_STREAM, GBufferedInputStreamClass)) +#define G_IS_BUFFERED_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_BUFFERED_INPUT_STREAM)) +#define G_IS_BUFFERED_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_BUFFERED_INPUT_STREAM)) +#define G_BUFFERED_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_BUFFERED_INPUT_STREAM, GBufferedInputStreamClass)) + +/** + * GBufferedInputStream: + * + * Implements #GFilterInputStream with a sized input buffer. + **/ +typedef struct _GBufferedInputStreamClass GBufferedInputStreamClass; +typedef struct _GBufferedInputStreamPrivate GBufferedInputStreamPrivate; + +struct _GBufferedInputStream +{ + GFilterInputStream parent_instance; + + /*< private >*/ + GBufferedInputStreamPrivate *priv; +}; + +struct _GBufferedInputStreamClass +{ + GFilterInputStreamClass parent_class; + + gssize (* fill) (GBufferedInputStream *stream, + gssize count, + GCancellable *cancellable, + GError **error); + + /* Async ops: (optional in derived classes) */ + void (* fill_async) (GBufferedInputStream *stream, + gssize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + gssize (* fill_finish) (GBufferedInputStream *stream, + GAsyncResult *result, + GError **error); + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); + void (*_g_reserved5) (void); +}; + + +GLIB_AVAILABLE_IN_ALL +GType g_buffered_input_stream_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_ALL +GInputStream* g_buffered_input_stream_new (GInputStream *base_stream); +GLIB_AVAILABLE_IN_ALL +GInputStream* g_buffered_input_stream_new_sized (GInputStream *base_stream, + gsize size); + +GLIB_AVAILABLE_IN_ALL +gsize g_buffered_input_stream_get_buffer_size (GBufferedInputStream *stream); +GLIB_AVAILABLE_IN_ALL +void g_buffered_input_stream_set_buffer_size (GBufferedInputStream *stream, + gsize size); +GLIB_AVAILABLE_IN_ALL +gsize g_buffered_input_stream_get_available (GBufferedInputStream *stream); +GLIB_AVAILABLE_IN_ALL +gsize g_buffered_input_stream_peek (GBufferedInputStream *stream, + void *buffer, + gsize offset, + gsize count); +GLIB_AVAILABLE_IN_ALL +const void* g_buffered_input_stream_peek_buffer (GBufferedInputStream *stream, + gsize *count); + +GLIB_AVAILABLE_IN_ALL +gssize g_buffered_input_stream_fill (GBufferedInputStream *stream, + gssize count, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +void g_buffered_input_stream_fill_async (GBufferedInputStream *stream, + gssize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GLIB_AVAILABLE_IN_ALL +gssize g_buffered_input_stream_fill_finish (GBufferedInputStream *stream, + GAsyncResult *result, + GError **error); + +GLIB_AVAILABLE_IN_ALL +int g_buffered_input_stream_read_byte (GBufferedInputStream *stream, + GCancellable *cancellable, + GError **error); + +G_END_DECLS + +#endif /* __G_BUFFERED_INPUT_STREAM_H__ */
diff --git a/gio/gbufferedoutputstream.c b/gio/gbufferedoutputstream.c new file mode 100644 index 0000000..98bda50 --- /dev/null +++ b/gio/gbufferedoutputstream.c
@@ -0,0 +1,755 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Christian Kellner <gicmo@gnome.org> + */ + +#include "config.h" +#include "gbufferedoutputstream.h" +#include "goutputstream.h" +#include "gseekable.h" +#include "gtask.h" +#include "string.h" +#include "gioerror.h" +#include "glibintl.h" + +/** + * SECTION:gbufferedoutputstream + * @short_description: Buffered Output Stream + * @include: gio/gio.h + * @see_also: #GFilterOutputStream, #GOutputStream + * + * Buffered output stream implements #GFilterOutputStream and provides + * for buffered writes. + * + * By default, #GBufferedOutputStream's buffer size is set at 4 kilobytes. + * + * To create a buffered output stream, use g_buffered_output_stream_new(), + * or g_buffered_output_stream_new_sized() to specify the buffer's size + * at construction. + * + * To get the size of a buffer within a buffered input stream, use + * g_buffered_output_stream_get_buffer_size(). To change the size of a + * buffered output stream's buffer, use + * g_buffered_output_stream_set_buffer_size(). Note that the buffer's + * size cannot be reduced below the size of the data within the buffer. + **/ + +#define DEFAULT_BUFFER_SIZE 4096 + +struct _GBufferedOutputStreamPrivate { + guint8 *buffer; + gsize len; + goffset pos; + gboolean auto_grow; +}; + +enum { + PROP_0, + PROP_BUFSIZE, + PROP_AUTO_GROW +}; + +static void g_buffered_output_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +static void g_buffered_output_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void g_buffered_output_stream_finalize (GObject *object); + + +static gssize g_buffered_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error); +static gboolean g_buffered_output_stream_flush (GOutputStream *stream, + GCancellable *cancellable, + GError **error); +static gboolean g_buffered_output_stream_close (GOutputStream *stream, + GCancellable *cancellable, + GError **error); + +static void g_buffered_output_stream_flush_async (GOutputStream *stream, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data); +static gboolean g_buffered_output_stream_flush_finish (GOutputStream *stream, + GAsyncResult *result, + GError **error); +static void g_buffered_output_stream_close_async (GOutputStream *stream, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data); +static gboolean g_buffered_output_stream_close_finish (GOutputStream *stream, + GAsyncResult *result, + GError **error); + +static void g_buffered_output_stream_seekable_iface_init (GSeekableIface *iface); +static goffset g_buffered_output_stream_tell (GSeekable *seekable); +static gboolean g_buffered_output_stream_can_seek (GSeekable *seekable); +static gboolean g_buffered_output_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error); +static gboolean g_buffered_output_stream_can_truncate (GSeekable *seekable); +static gboolean g_buffered_output_stream_truncate (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error); + +G_DEFINE_TYPE_WITH_CODE (GBufferedOutputStream, + g_buffered_output_stream, + G_TYPE_FILTER_OUTPUT_STREAM, + G_ADD_PRIVATE (GBufferedOutputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, + g_buffered_output_stream_seekable_iface_init)) + + +static void +g_buffered_output_stream_class_init (GBufferedOutputStreamClass *klass) +{ + GObjectClass *object_class; + GOutputStreamClass *ostream_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->get_property = g_buffered_output_stream_get_property; + object_class->set_property = g_buffered_output_stream_set_property; + object_class->finalize = g_buffered_output_stream_finalize; + + ostream_class = G_OUTPUT_STREAM_CLASS (klass); + ostream_class->write_fn = g_buffered_output_stream_write; + ostream_class->flush = g_buffered_output_stream_flush; + ostream_class->close_fn = g_buffered_output_stream_close; + ostream_class->flush_async = g_buffered_output_stream_flush_async; + ostream_class->flush_finish = g_buffered_output_stream_flush_finish; + ostream_class->close_async = g_buffered_output_stream_close_async; + ostream_class->close_finish = g_buffered_output_stream_close_finish; + + g_object_class_install_property (object_class, + PROP_BUFSIZE, + g_param_spec_uint ("buffer-size", + P_("Buffer Size"), + P_("The size of the backend buffer"), + 1, + G_MAXUINT, + DEFAULT_BUFFER_SIZE, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT| + G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + + g_object_class_install_property (object_class, + PROP_AUTO_GROW, + g_param_spec_boolean ("auto-grow", + P_("Auto-grow"), + P_("Whether the buffer should automatically grow"), + FALSE, + G_PARAM_READWRITE| + G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + +} + +/** + * g_buffered_output_stream_get_buffer_size: + * @stream: a #GBufferedOutputStream. + * + * Gets the size of the buffer in the @stream. + * + * Returns: the current size of the buffer. + **/ +gsize +g_buffered_output_stream_get_buffer_size (GBufferedOutputStream *stream) +{ + g_return_val_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream), -1); + + return stream->priv->len; +} + +/** + * g_buffered_output_stream_set_buffer_size: + * @stream: a #GBufferedOutputStream. + * @size: a #gsize. + * + * Sets the size of the internal buffer to @size. + **/ +void +g_buffered_output_stream_set_buffer_size (GBufferedOutputStream *stream, + gsize size) +{ + GBufferedOutputStreamPrivate *priv; + guint8 *buffer; + + g_return_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream)); + + priv = stream->priv; + + if (size == priv->len) + return; + + if (priv->buffer) + { + size = MAX (size, priv->pos); + + buffer = g_malloc (size); + memcpy (buffer, priv->buffer, priv->pos); + g_free (priv->buffer); + priv->buffer = buffer; + priv->len = size; + /* Keep old pos */ + } + else + { + priv->buffer = g_malloc (size); + priv->len = size; + priv->pos = 0; + } + + g_object_notify (G_OBJECT (stream), "buffer-size"); +} + +/** + * g_buffered_output_stream_get_auto_grow: + * @stream: a #GBufferedOutputStream. + * + * Checks if the buffer automatically grows as data is added. + * + * Returns: %TRUE if the @stream's buffer automatically grows, + * %FALSE otherwise. + **/ +gboolean +g_buffered_output_stream_get_auto_grow (GBufferedOutputStream *stream) +{ + g_return_val_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream), FALSE); + + return stream->priv->auto_grow; +} + +/** + * g_buffered_output_stream_set_auto_grow: + * @stream: a #GBufferedOutputStream. + * @auto_grow: a #gboolean. + * + * Sets whether or not the @stream's buffer should automatically grow. + * If @auto_grow is true, then each write will just make the buffer + * larger, and you must manually flush the buffer to actually write out + * the data to the underlying stream. + **/ +void +g_buffered_output_stream_set_auto_grow (GBufferedOutputStream *stream, + gboolean auto_grow) +{ + GBufferedOutputStreamPrivate *priv; + g_return_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream)); + priv = stream->priv; + auto_grow = auto_grow != FALSE; + if (priv->auto_grow != auto_grow) + { + priv->auto_grow = auto_grow; + g_object_notify (G_OBJECT (stream), "auto-grow"); + } +} + +static void +g_buffered_output_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GBufferedOutputStream *stream; + + stream = G_BUFFERED_OUTPUT_STREAM (object); + + switch (prop_id) + { + case PROP_BUFSIZE: + g_buffered_output_stream_set_buffer_size (stream, g_value_get_uint (value)); + break; + + case PROP_AUTO_GROW: + g_buffered_output_stream_set_auto_grow (stream, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +g_buffered_output_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GBufferedOutputStream *buffered_stream; + GBufferedOutputStreamPrivate *priv; + + buffered_stream = G_BUFFERED_OUTPUT_STREAM (object); + priv = buffered_stream->priv; + + switch (prop_id) + { + case PROP_BUFSIZE: + g_value_set_uint (value, priv->len); + break; + + case PROP_AUTO_GROW: + g_value_set_boolean (value, priv->auto_grow); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +g_buffered_output_stream_finalize (GObject *object) +{ + GBufferedOutputStream *stream; + GBufferedOutputStreamPrivate *priv; + + stream = G_BUFFERED_OUTPUT_STREAM (object); + priv = stream->priv; + + g_free (priv->buffer); + + G_OBJECT_CLASS (g_buffered_output_stream_parent_class)->finalize (object); +} + +static void +g_buffered_output_stream_init (GBufferedOutputStream *stream) +{ + stream->priv = g_buffered_output_stream_get_instance_private (stream); +} + +static void +g_buffered_output_stream_seekable_iface_init (GSeekableIface *iface) +{ + iface->tell = g_buffered_output_stream_tell; + iface->can_seek = g_buffered_output_stream_can_seek; + iface->seek = g_buffered_output_stream_seek; + iface->can_truncate = g_buffered_output_stream_can_truncate; + iface->truncate_fn = g_buffered_output_stream_truncate; +} + +/** + * g_buffered_output_stream_new: + * @base_stream: a #GOutputStream. + * + * Creates a new buffered output stream for a base stream. + * + * Returns: a #GOutputStream for the given @base_stream. + **/ +GOutputStream * +g_buffered_output_stream_new (GOutputStream *base_stream) +{ + GOutputStream *stream; + + g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL); + + stream = g_object_new (G_TYPE_BUFFERED_OUTPUT_STREAM, + "base-stream", base_stream, + NULL); + + return stream; +} + +/** + * g_buffered_output_stream_new_sized: + * @base_stream: a #GOutputStream. + * @size: a #gsize. + * + * Creates a new buffered output stream with a given buffer size. + * + * Returns: a #GOutputStream with an internal buffer set to @size. + **/ +GOutputStream * +g_buffered_output_stream_new_sized (GOutputStream *base_stream, + gsize size) +{ + GOutputStream *stream; + + g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL); + + stream = g_object_new (G_TYPE_BUFFERED_OUTPUT_STREAM, + "base-stream", base_stream, + "buffer-size", size, + NULL); + + return stream; +} + +static gboolean +flush_buffer (GBufferedOutputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GBufferedOutputStreamPrivate *priv; + GOutputStream *base_stream; + gboolean res; + gsize bytes_written; + gsize count; + + priv = stream->priv; + bytes_written = 0; + base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + + g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), FALSE); + + res = g_output_stream_write_all (base_stream, + priv->buffer, + priv->pos, + &bytes_written, + cancellable, + error); + + count = priv->pos - bytes_written; + + if (count > 0) + memmove (priv->buffer, priv->buffer + bytes_written, count); + + priv->pos -= bytes_written; + + return res; +} + +static gssize +g_buffered_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + GBufferedOutputStream *bstream; + GBufferedOutputStreamPrivate *priv; + gboolean res; + gsize n; + gsize new_size; + + bstream = G_BUFFERED_OUTPUT_STREAM (stream); + priv = bstream->priv; + + n = priv->len - priv->pos; + + if (priv->auto_grow && n < count) + { + new_size = MAX (priv->len * 2, priv->len + count); + g_buffered_output_stream_set_buffer_size (bstream, new_size); + } + else if (n == 0) + { + res = flush_buffer (bstream, cancellable, error); + + if (res == FALSE) + return -1; + } + + n = priv->len - priv->pos; + + count = MIN (count, n); + memcpy (priv->buffer + priv->pos, buffer, count); + priv->pos += count; + + return count; +} + +static gboolean +g_buffered_output_stream_flush (GOutputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GBufferedOutputStream *bstream; + GOutputStream *base_stream; + gboolean res; + + bstream = G_BUFFERED_OUTPUT_STREAM (stream); + base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + + res = flush_buffer (bstream, cancellable, error); + + if (res == FALSE) + return FALSE; + + res = g_output_stream_flush (base_stream, cancellable, error); + + return res; +} + +static gboolean +g_buffered_output_stream_close (GOutputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GBufferedOutputStream *bstream; + GOutputStream *base_stream; + gboolean res; + + bstream = G_BUFFERED_OUTPUT_STREAM (stream); + base_stream = G_FILTER_OUTPUT_STREAM (bstream)->base_stream; + res = flush_buffer (bstream, cancellable, error); + + if (g_filter_output_stream_get_close_base_stream (G_FILTER_OUTPUT_STREAM (stream))) + { + /* report the first error but still close the stream */ + if (res) + res = g_output_stream_close (base_stream, cancellable, error); + else + g_output_stream_close (base_stream, cancellable, NULL); + } + + return res; +} + +static goffset +g_buffered_output_stream_tell (GSeekable *seekable) +{ + GBufferedOutputStream *bstream; + GBufferedOutputStreamPrivate *priv; + GOutputStream *base_stream; + GSeekable *base_stream_seekable; + goffset base_offset; + + bstream = G_BUFFERED_OUTPUT_STREAM (seekable); + priv = bstream->priv; + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + return 0; + + base_stream_seekable = G_SEEKABLE (base_stream); + + base_offset = g_seekable_tell (base_stream_seekable); + return base_offset + priv->pos; +} + +static gboolean +g_buffered_output_stream_can_seek (GSeekable *seekable) +{ + GOutputStream *base_stream; + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream)); +} + +static gboolean +g_buffered_output_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error) +{ + GBufferedOutputStream *bstream; + GOutputStream *base_stream; + GSeekable *base_stream_seekable; + gboolean flushed; + + bstream = G_BUFFERED_OUTPUT_STREAM (seekable); + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Seek not supported on base stream")); + return FALSE; + } + + base_stream_seekable = G_SEEKABLE (base_stream); + flushed = flush_buffer (bstream, cancellable, error); + if (!flushed) + return FALSE; + + return g_seekable_seek (base_stream_seekable, offset, type, cancellable, error); +} + +static gboolean +g_buffered_output_stream_can_truncate (GSeekable *seekable) +{ + GOutputStream *base_stream; + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + return G_IS_SEEKABLE (base_stream) && g_seekable_can_truncate (G_SEEKABLE (base_stream)); +} + +static gboolean +g_buffered_output_stream_truncate (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error) +{ + GBufferedOutputStream *bstream; + GOutputStream *base_stream; + GSeekable *base_stream_seekable; + gboolean flushed; + + bstream = G_BUFFERED_OUTPUT_STREAM (seekable); + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Truncate not supported on base stream")); + return FALSE; + } + + base_stream_seekable = G_SEEKABLE (base_stream); + + flushed = flush_buffer (bstream, cancellable, error); + if (!flushed) + return FALSE; + return g_seekable_truncate (base_stream_seekable, offset, cancellable, error); +} + +/* ************************** */ +/* Async stuff implementation */ +/* ************************** */ + +/* TODO: This should be using the base class async ops, not threads */ + +typedef struct { + + guint flush_stream : 1; + guint close_stream : 1; + +} FlushData; + +static void +free_flush_data (gpointer data) +{ + g_slice_free (FlushData, data); +} + +/* This function is used by all three (i.e. + * _write, _flush, _close) functions since + * all of them will need to flush the buffer + * and so closing and writing is just a special + * case of flushing + some addition stuff */ +static void +flush_buffer_thread (GTask *task, + gpointer object, + gpointer task_data, + GCancellable *cancellable) +{ + GBufferedOutputStream *stream; + GOutputStream *base_stream; + FlushData *fdata; + gboolean res; + GError *error = NULL; + + stream = G_BUFFERED_OUTPUT_STREAM (object); + fdata = task_data; + base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + + res = flush_buffer (stream, cancellable, &error); + + /* if flushing the buffer didn't work don't even bother + * to flush the stream but just report that error */ + if (res && fdata->flush_stream) + res = g_output_stream_flush (base_stream, cancellable, &error); + + if (fdata->close_stream) + { + + /* if flushing the buffer or the stream returned + * an error report that first error but still try + * close the stream */ + if (g_filter_output_stream_get_close_base_stream (G_FILTER_OUTPUT_STREAM (stream))) + { + if (res == FALSE) + g_output_stream_close (base_stream, cancellable, NULL); + else + res = g_output_stream_close (base_stream, cancellable, &error); + } + } + + if (res == FALSE) + g_task_return_error (task, error); + else + g_task_return_boolean (task, TRUE); +} + +static void +g_buffered_output_stream_flush_async (GOutputStream *stream, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + GTask *task; + FlushData *fdata; + + fdata = g_slice_new0 (FlushData); + fdata->flush_stream = TRUE; + fdata->close_stream = FALSE; + + task = g_task_new (stream, cancellable, callback, data); + g_task_set_source_tag (task, g_buffered_output_stream_flush_async); + g_task_set_task_data (task, fdata, free_flush_data); + g_task_set_priority (task, io_priority); + + g_task_run_in_thread (task, flush_buffer_thread); + g_object_unref (task); +} + +static gboolean +g_buffered_output_stream_flush_finish (GOutputStream *stream, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} + +static void +g_buffered_output_stream_close_async (GOutputStream *stream, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + GTask *task; + FlushData *fdata; + + fdata = g_slice_new0 (FlushData); + fdata->close_stream = TRUE; + + task = g_task_new (stream, cancellable, callback, data); + g_task_set_source_tag (task, g_buffered_output_stream_close_async); + g_task_set_task_data (task, fdata, free_flush_data); + g_task_set_priority (task, io_priority); + + g_task_run_in_thread (task, flush_buffer_thread); + g_object_unref (task); +} + +static gboolean +g_buffered_output_stream_close_finish (GOutputStream *stream, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +}
diff --git a/gio/gbufferedoutputstream.h b/gio/gbufferedoutputstream.h new file mode 100644 index 0000000..f88f279 --- /dev/null +++ b/gio/gbufferedoutputstream.h
@@ -0,0 +1,86 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Christian Kellner <gicmo@gnome.org> + */ + +#ifndef __G_BUFFERED_OUTPUT_STREAM_H__ +#define __G_BUFFERED_OUTPUT_STREAM_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/gfilteroutputstream.h> + +G_BEGIN_DECLS + +#define G_TYPE_BUFFERED_OUTPUT_STREAM (g_buffered_output_stream_get_type ()) +#define G_BUFFERED_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_BUFFERED_OUTPUT_STREAM, GBufferedOutputStream)) +#define G_BUFFERED_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_BUFFERED_OUTPUT_STREAM, GBufferedOutputStreamClass)) +#define G_IS_BUFFERED_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_BUFFERED_OUTPUT_STREAM)) +#define G_IS_BUFFERED_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_BUFFERED_OUTPUT_STREAM)) +#define G_BUFFERED_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_BUFFERED_OUTPUT_STREAM, GBufferedOutputStreamClass)) + +/** + * GBufferedOutputStream: + * + * An implementation of #GFilterOutputStream with a sized buffer. + **/ +typedef struct _GBufferedOutputStreamClass GBufferedOutputStreamClass; +typedef struct _GBufferedOutputStreamPrivate GBufferedOutputStreamPrivate; + +struct _GBufferedOutputStream +{ + GFilterOutputStream parent_instance; + + /*< protected >*/ + GBufferedOutputStreamPrivate *priv; +}; + +struct _GBufferedOutputStreamClass +{ + GFilterOutputStreamClass parent_class; + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); +}; + + +GLIB_AVAILABLE_IN_ALL +GType g_buffered_output_stream_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_ALL +GOutputStream* g_buffered_output_stream_new (GOutputStream *base_stream); +GLIB_AVAILABLE_IN_ALL +GOutputStream* g_buffered_output_stream_new_sized (GOutputStream *base_stream, + gsize size); +GLIB_AVAILABLE_IN_ALL +gsize g_buffered_output_stream_get_buffer_size (GBufferedOutputStream *stream); +GLIB_AVAILABLE_IN_ALL +void g_buffered_output_stream_set_buffer_size (GBufferedOutputStream *stream, + gsize size); +GLIB_AVAILABLE_IN_ALL +gboolean g_buffered_output_stream_get_auto_grow (GBufferedOutputStream *stream); +GLIB_AVAILABLE_IN_ALL +void g_buffered_output_stream_set_auto_grow (GBufferedOutputStream *stream, + gboolean auto_grow); + +G_END_DECLS + +#endif /* __G_BUFFERED_OUTPUT_STREAM_H__ */
diff --git a/gio/gbytesicon.c b/gio/gbytesicon.c new file mode 100644 index 0000000..ca78be1 --- /dev/null +++ b/gio/gbytesicon.c
@@ -0,0 +1,266 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2013 Canonical Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" + +#include "gbytesicon.h" +#include "gbytes.h" +#include "gicon.h" +#include "glibintl.h" +#include "gloadableicon.h" +#include "gmemoryinputstream.h" +#include "gtask.h" +#include "gioerror.h" + + +/** + * SECTION:gbytesicon + * @short_description: An icon stored in memory as a GBytes + * @include: gio/gio.h + * @see_also: #GIcon, #GLoadableIcon, #GBytes + * + * #GBytesIcon specifies an image held in memory in a common format (usually + * png) to be used as icon. + * + * Since: 2.38 + **/ + +typedef GObjectClass GBytesIconClass; + +struct _GBytesIcon +{ + GObject parent_instance; + + GBytes *bytes; +}; + +enum +{ + PROP_0, + PROP_BYTES +}; + +static void g_bytes_icon_icon_iface_init (GIconIface *iface); +static void g_bytes_icon_loadable_icon_iface_init (GLoadableIconIface *iface); +G_DEFINE_TYPE_WITH_CODE (GBytesIcon, g_bytes_icon, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_ICON, g_bytes_icon_icon_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_LOADABLE_ICON, g_bytes_icon_loadable_icon_iface_init)) + +static void +g_bytes_icon_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GBytesIcon *icon = G_BYTES_ICON (object); + + switch (prop_id) + { + case PROP_BYTES: + g_value_set_boxed (value, icon->bytes); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_bytes_icon_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GBytesIcon *icon = G_BYTES_ICON (object); + + switch (prop_id) + { + case PROP_BYTES: + icon->bytes = g_value_dup_boxed (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_bytes_icon_finalize (GObject *object) +{ + GBytesIcon *icon; + + icon = G_BYTES_ICON (object); + + g_bytes_unref (icon->bytes); + + G_OBJECT_CLASS (g_bytes_icon_parent_class)->finalize (object); +} + +static void +g_bytes_icon_class_init (GBytesIconClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = g_bytes_icon_get_property; + gobject_class->set_property = g_bytes_icon_set_property; + gobject_class->finalize = g_bytes_icon_finalize; + + /** + * GBytesIcon:bytes: + * + * The bytes containing the icon. + */ + g_object_class_install_property (gobject_class, PROP_BYTES, + g_param_spec_boxed ("bytes", + P_("bytes"), + P_("The bytes containing the icon"), + G_TYPE_BYTES, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +g_bytes_icon_init (GBytesIcon *bytes) +{ +} + +/** + * g_bytes_icon_new: + * @bytes: a #GBytes. + * + * Creates a new icon for a bytes. + * + * Returns: (transfer full) (type GBytesIcon): a #GIcon for the given + * @bytes, or %NULL on error. + * + * Since: 2.38 + **/ +GIcon * +g_bytes_icon_new (GBytes *bytes) +{ + g_return_val_if_fail (bytes != NULL, NULL); + + return g_object_new (G_TYPE_BYTES_ICON, "bytes", bytes, NULL); +} + +/** + * g_bytes_icon_get_bytes: + * @icon: a #GIcon. + * + * Gets the #GBytes associated with the given @icon. + * + * Returns: (transfer none): a #GBytes, or %NULL. + * + * Since: 2.38 + **/ +GBytes * +g_bytes_icon_get_bytes (GBytesIcon *icon) +{ + g_return_val_if_fail (G_IS_BYTES_ICON (icon), NULL); + + return icon->bytes; +} + +static guint +g_bytes_icon_hash (GIcon *icon) +{ + GBytesIcon *bytes_icon = G_BYTES_ICON (icon); + + return g_bytes_hash (bytes_icon->bytes); +} + +static gboolean +g_bytes_icon_equal (GIcon *icon1, + GIcon *icon2) +{ + GBytesIcon *bytes1 = G_BYTES_ICON (icon1); + GBytesIcon *bytes2 = G_BYTES_ICON (icon2); + + return g_bytes_equal (bytes1->bytes, bytes2->bytes); +} + +static GVariant * +g_bytes_icon_serialize (GIcon *icon) +{ + GBytesIcon *bytes_icon = G_BYTES_ICON (icon); + + return g_variant_new ("(sv)", "bytes", + g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING, bytes_icon->bytes, TRUE)); +} + +static void +g_bytes_icon_icon_iface_init (GIconIface *iface) +{ + iface->hash = g_bytes_icon_hash; + iface->equal = g_bytes_icon_equal; + iface->serialize = g_bytes_icon_serialize; +} + +static GInputStream * +g_bytes_icon_load (GLoadableIcon *icon, + int size, + char **type, + GCancellable *cancellable, + GError **error) +{ + GBytesIcon *bytes_icon = G_BYTES_ICON (icon); + + if (type) + *type = NULL; + + return g_memory_input_stream_new_from_bytes (bytes_icon->bytes); +} + +static void +g_bytes_icon_load_async (GLoadableIcon *icon, + int size, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GBytesIcon *bytes_icon = G_BYTES_ICON (icon); + GTask *task; + + task = g_task_new (icon, cancellable, callback, user_data); + g_task_set_source_tag (task, g_bytes_icon_load_async); + g_task_return_pointer (task, g_memory_input_stream_new_from_bytes (bytes_icon->bytes), g_object_unref); + g_object_unref (task); +} + +static GInputStream * +g_bytes_icon_load_finish (GLoadableIcon *icon, + GAsyncResult *res, + char **type, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (res, icon), NULL); + + if (type) + *type = NULL; + + return g_task_propagate_pointer (G_TASK (res), error); +} + +static void +g_bytes_icon_loadable_icon_iface_init (GLoadableIconIface *iface) +{ + iface->load = g_bytes_icon_load; + iface->load_async = g_bytes_icon_load_async; + iface->load_finish = g_bytes_icon_load_finish; +}
diff --git a/gio/gbytesicon.h b/gio/gbytesicon.h new file mode 100644 index 0000000..5661044 --- /dev/null +++ b/gio/gbytesicon.h
@@ -0,0 +1,52 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_BYTES_ICON_H__ +#define __G_BYTES_ICON_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_BYTES_ICON (g_bytes_icon_get_type ()) +#define G_BYTES_ICON(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_BYTES_ICON, GBytesIcon)) +#define G_IS_BYTES_ICON(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_BYTES_ICON)) + +/** + * GBytesIcon: + * + * Gets an icon for a #GBytes. Implements #GLoadableIcon. + **/ +GLIB_AVAILABLE_IN_2_38 +GType g_bytes_icon_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_2_38 +GIcon * g_bytes_icon_new (GBytes *bytes); + +GLIB_AVAILABLE_IN_2_38 +GBytes * g_bytes_icon_get_bytes (GBytesIcon *icon); + +G_END_DECLS + +#endif /* __G_BYTES_ICON_H__ */
diff --git a/gio/gcancellable.c b/gio/gcancellable.c new file mode 100644 index 0000000..e687cca --- /dev/null +++ b/gio/gcancellable.c
@@ -0,0 +1,816 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" +#include "glib.h" +#include <gioerror.h> +#include "glib-private.h" +#include "gcancellable.h" +#include "glibintl.h" + + +/** + * SECTION:gcancellable + * @short_description: Thread-safe Operation Cancellation Stack + * @include: gio/gio.h + * + * GCancellable is a thread-safe operation cancellation stack used + * throughout GIO to allow for cancellation of synchronous and + * asynchronous operations. + */ + +enum { + CANCELLED, + LAST_SIGNAL +}; + +struct _GCancellablePrivate +{ + /* Atomic so that g_cancellable_is_cancelled does not require holding the mutex. */ + gboolean cancelled; + /* Access to fields below is protected by cancellable_mutex. */ + guint cancelled_running : 1; + guint cancelled_running_waiting : 1; + + guint fd_refcount; + GWakeup *wakeup; +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE_WITH_PRIVATE (GCancellable, g_cancellable, G_TYPE_OBJECT) + +static GPrivate current_cancellable; +static GMutex cancellable_mutex; +static GCond cancellable_cond; + +static void +g_cancellable_finalize (GObject *object) +{ + GCancellable *cancellable = G_CANCELLABLE (object); + + if (cancellable->priv->wakeup) + GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup); + + G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object); +} + +static void +g_cancellable_class_init (GCancellableClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = g_cancellable_finalize; + + /** + * GCancellable::cancelled: + * @cancellable: a #GCancellable. + * + * Emitted when the operation has been cancelled. + * + * Can be used by implementations of cancellable operations. If the + * operation is cancelled from another thread, the signal will be + * emitted in the thread that cancelled the operation, not the + * thread that is running the operation. + * + * Note that disconnecting from this signal (or any signal) in a + * multi-threaded program is prone to race conditions. For instance + * it is possible that a signal handler may be invoked even after + * a call to g_signal_handler_disconnect() for that handler has + * already returned. + * + * There is also a problem when cancellation happens right before + * connecting to the signal. If this happens the signal will + * unexpectedly not be emitted, and checking before connecting to + * the signal leaves a race condition where this is still happening. + * + * In order to make it safe and easy to connect handlers there + * are two helper functions: g_cancellable_connect() and + * g_cancellable_disconnect() which protect against problems + * like this. + * + * An example of how to us this: + * |[<!-- language="C" --> + * // Make sure we don't do unnecessary work if already cancelled + * if (g_cancellable_set_error_if_cancelled (cancellable, error)) + * return; + * + * // Set up all the data needed to be able to handle cancellation + * // of the operation + * my_data = my_data_new (...); + * + * id = 0; + * if (cancellable) + * id = g_cancellable_connect (cancellable, + * G_CALLBACK (cancelled_handler) + * data, NULL); + * + * // cancellable operation here... + * + * g_cancellable_disconnect (cancellable, id); + * + * // cancelled_handler is never called after this, it is now safe + * // to free the data + * my_data_free (my_data); + * ]| + * + * Note that the cancelled signal is emitted in the thread that + * the user cancelled from, which may be the main thread. So, the + * cancellable signal should not do something that can block. + */ + signals[CANCELLED] = + g_signal_new (I_("cancelled"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GCancellableClass, cancelled), + NULL, NULL, + NULL, + G_TYPE_NONE, 0); + +} + +static void +g_cancellable_init (GCancellable *cancellable) +{ + cancellable->priv = g_cancellable_get_instance_private (cancellable); +} + +/** + * g_cancellable_new: + * + * Creates a new #GCancellable object. + * + * Applications that want to start one or more operations + * that should be cancellable should create a #GCancellable + * and pass it to the operations. + * + * One #GCancellable can be used in multiple consecutive + * operations or in multiple concurrent operations. + * + * Returns: a #GCancellable. + **/ +GCancellable * +g_cancellable_new (void) +{ + return g_object_new (G_TYPE_CANCELLABLE, NULL); +} + +/** + * g_cancellable_push_current: + * @cancellable: a #GCancellable object + * + * Pushes @cancellable onto the cancellable stack. The current + * cancellable can then be received using g_cancellable_get_current(). + * + * This is useful when implementing cancellable operations in + * code that does not allow you to pass down the cancellable object. + * + * This is typically called automatically by e.g. #GFile operations, + * so you rarely have to call this yourself. + **/ +void +g_cancellable_push_current (GCancellable *cancellable) +{ + GSList *l; + + g_return_if_fail (cancellable != NULL); + + l = g_private_get (¤t_cancellable); + l = g_slist_prepend (l, cancellable); + g_private_set (¤t_cancellable, l); +} + +/** + * g_cancellable_pop_current: + * @cancellable: a #GCancellable object + * + * Pops @cancellable off the cancellable stack (verifying that @cancellable + * is on the top of the stack). + **/ +void +g_cancellable_pop_current (GCancellable *cancellable) +{ + GSList *l; + + l = g_private_get (¤t_cancellable); + + g_return_if_fail (l != NULL); + g_return_if_fail (l->data == cancellable); + + l = g_slist_delete_link (l, l); + g_private_set (¤t_cancellable, l); +} + +/** + * g_cancellable_get_current: + * + * Gets the top cancellable from the stack. + * + * Returns: (nullable) (transfer none): a #GCancellable from the top + * of the stack, or %NULL if the stack is empty. + **/ +GCancellable * +g_cancellable_get_current (void) +{ + GSList *l; + + l = g_private_get (¤t_cancellable); + if (l == NULL) + return NULL; + + return G_CANCELLABLE (l->data); +} + +/** + * g_cancellable_reset: + * @cancellable: a #GCancellable object. + * + * Resets @cancellable to its uncancelled state. + * + * If cancellable is currently in use by any cancellable operation + * then the behavior of this function is undefined. + * + * Note that it is generally not a good idea to reuse an existing + * cancellable for more operations after it has been cancelled once, + * as this function might tempt you to do. The recommended practice + * is to drop the reference to a cancellable after cancelling it, + * and let it die with the outstanding async operations. You should + * create a fresh cancellable for further async operations. + **/ +void +g_cancellable_reset (GCancellable *cancellable) +{ + GCancellablePrivate *priv; + + g_return_if_fail (G_IS_CANCELLABLE (cancellable)); + + g_mutex_lock (&cancellable_mutex); + + priv = cancellable->priv; + + while (priv->cancelled_running) + { + priv->cancelled_running_waiting = TRUE; + g_cond_wait (&cancellable_cond, &cancellable_mutex); + } + + if (g_atomic_int_get (&priv->cancelled)) + { + if (priv->wakeup) + GLIB_PRIVATE_CALL (g_wakeup_acknowledge) (priv->wakeup); + + g_atomic_int_set (&priv->cancelled, FALSE); + } + + g_mutex_unlock (&cancellable_mutex); +} + +/** + * g_cancellable_is_cancelled: + * @cancellable: (nullable): a #GCancellable or %NULL + * + * Checks if a cancellable job has been cancelled. + * + * Returns: %TRUE if @cancellable is cancelled, + * FALSE if called with %NULL or if item is not cancelled. + **/ +gboolean +g_cancellable_is_cancelled (GCancellable *cancellable) +{ + return cancellable != NULL && g_atomic_int_get (&cancellable->priv->cancelled); +} + +/** + * g_cancellable_set_error_if_cancelled: + * @cancellable: (nullable): a #GCancellable or %NULL + * @error: #GError to append error state to + * + * If the @cancellable is cancelled, sets the error to notify + * that the operation was cancelled. + * + * Returns: %TRUE if @cancellable was cancelled, %FALSE if it was not + */ +gboolean +g_cancellable_set_error_if_cancelled (GCancellable *cancellable, + GError **error) +{ + if (g_cancellable_is_cancelled (cancellable)) + { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_CANCELLED, + _("Operation was cancelled")); + return TRUE; + } + + return FALSE; +} + +/** + * g_cancellable_get_fd: + * @cancellable: a #GCancellable. + * + * Gets the file descriptor for a cancellable job. This can be used to + * implement cancellable operations on Unix systems. The returned fd will + * turn readable when @cancellable is cancelled. + * + * You are not supposed to read from the fd yourself, just check for + * readable status. Reading to unset the readable status is done + * with g_cancellable_reset(). + * + * After a successful return from this function, you should use + * g_cancellable_release_fd() to free up resources allocated for + * the returned file descriptor. + * + * See also g_cancellable_make_pollfd(). + * + * Returns: A valid file descriptor. `-1` if the file descriptor + * is not supported, or on errors. + **/ +int +g_cancellable_get_fd (GCancellable *cancellable) +{ + GPollFD pollfd; + + if (cancellable == NULL) + return -1; + +#ifdef G_OS_WIN32 + pollfd.fd = -1; +#else + g_cancellable_make_pollfd (cancellable, &pollfd); +#endif + + return pollfd.fd; +} + +/** + * g_cancellable_make_pollfd: + * @cancellable: (nullable): a #GCancellable or %NULL + * @pollfd: a pointer to a #GPollFD + * + * Creates a #GPollFD corresponding to @cancellable; this can be passed + * to g_poll() and used to poll for cancellation. This is useful both + * for unix systems without a native poll and for portability to + * windows. + * + * When this function returns %TRUE, you should use + * g_cancellable_release_fd() to free up resources allocated for the + * @pollfd. After a %FALSE return, do not call g_cancellable_release_fd(). + * + * If this function returns %FALSE, either no @cancellable was given or + * resource limits prevent this function from allocating the necessary + * structures for polling. (On Linux, you will likely have reached + * the maximum number of file descriptors.) The suggested way to handle + * these cases is to ignore the @cancellable. + * + * You are not supposed to read from the fd yourself, just check for + * readable status. Reading to unset the readable status is done + * with g_cancellable_reset(). + * + * Returns: %TRUE if @pollfd was successfully initialized, %FALSE on + * failure to prepare the cancellable. + * + * Since: 2.22 + **/ +gboolean +g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd) +{ + g_return_val_if_fail (pollfd != NULL, FALSE); + if (cancellable == NULL) + return FALSE; + g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE); + + g_mutex_lock (&cancellable_mutex); + + cancellable->priv->fd_refcount++; + + if (cancellable->priv->wakeup == NULL) + { + cancellable->priv->wakeup = GLIB_PRIVATE_CALL (g_wakeup_new) (); + + if (g_atomic_int_get (&cancellable->priv->cancelled)) + GLIB_PRIVATE_CALL (g_wakeup_signal) (cancellable->priv->wakeup); + } + + GLIB_PRIVATE_CALL (g_wakeup_get_pollfd) (cancellable->priv->wakeup, pollfd); + + g_mutex_unlock (&cancellable_mutex); + + return TRUE; +} + +/** + * g_cancellable_release_fd: + * @cancellable: a #GCancellable + * + * Releases a resources previously allocated by g_cancellable_get_fd() + * or g_cancellable_make_pollfd(). + * + * For compatibility reasons with older releases, calling this function + * is not strictly required, the resources will be automatically freed + * when the @cancellable is finalized. However, the @cancellable will + * block scarce file descriptors until it is finalized if this function + * is not called. This can cause the application to run out of file + * descriptors when many #GCancellables are used at the same time. + * + * Since: 2.22 + **/ +void +g_cancellable_release_fd (GCancellable *cancellable) +{ + GCancellablePrivate *priv; + + if (cancellable == NULL) + return; + + g_return_if_fail (G_IS_CANCELLABLE (cancellable)); + + priv = cancellable->priv; + + g_mutex_lock (&cancellable_mutex); + g_assert (priv->fd_refcount > 0); + + priv->fd_refcount--; + if (priv->fd_refcount == 0) + { + GLIB_PRIVATE_CALL (g_wakeup_free) (priv->wakeup); + priv->wakeup = NULL; + } + + g_mutex_unlock (&cancellable_mutex); +} + +/** + * g_cancellable_cancel: + * @cancellable: (nullable): a #GCancellable object. + * + * Will set @cancellable to cancelled, and will emit the + * #GCancellable::cancelled signal. (However, see the warning about + * race conditions in the documentation for that signal if you are + * planning to connect to it.) + * + * This function is thread-safe. In other words, you can safely call + * it from a thread other than the one running the operation that was + * passed the @cancellable. + * + * If @cancellable is %NULL, this function returns immediately for convenience. + * + * The convention within GIO is that cancelling an asynchronous + * operation causes it to complete asynchronously. That is, if you + * cancel the operation from the same thread in which it is running, + * then the operation's #GAsyncReadyCallback will not be invoked until + * the application returns to the main loop. + **/ +void +g_cancellable_cancel (GCancellable *cancellable) +{ + GCancellablePrivate *priv; + + if (cancellable == NULL || g_cancellable_is_cancelled (cancellable)) + return; + + priv = cancellable->priv; + + g_mutex_lock (&cancellable_mutex); + + if (g_atomic_int_get (&priv->cancelled)) + { + g_mutex_unlock (&cancellable_mutex); + return; + } + + g_atomic_int_set (&priv->cancelled, TRUE); + priv->cancelled_running = TRUE; + + if (priv->wakeup) + GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup); + + g_mutex_unlock (&cancellable_mutex); + + g_object_ref (cancellable); + g_signal_emit (cancellable, signals[CANCELLED], 0); + + g_mutex_lock (&cancellable_mutex); + + priv->cancelled_running = FALSE; + if (priv->cancelled_running_waiting) + g_cond_broadcast (&cancellable_cond); + priv->cancelled_running_waiting = FALSE; + + g_mutex_unlock (&cancellable_mutex); + + g_object_unref (cancellable); +} + +/** + * g_cancellable_connect: + * @cancellable: A #GCancellable. + * @callback: The #GCallback to connect. + * @data: Data to pass to @callback. + * @data_destroy_func: (nullable): Free function for @data or %NULL. + * + * Convenience function to connect to the #GCancellable::cancelled + * signal. Also handles the race condition that may happen + * if the cancellable is cancelled right before connecting. + * + * @callback is called at most once, either directly at the + * time of the connect if @cancellable is already cancelled, + * or when @cancellable is cancelled in some thread. + * + * @data_destroy_func will be called when the handler is + * disconnected, or immediately if the cancellable is already + * cancelled. + * + * See #GCancellable::cancelled for details on how to use this. + * + * Since GLib 2.40, the lock protecting @cancellable is not held when + * @callback is invoked. This lifts a restriction in place for + * earlier GLib versions which now makes it easier to write cleanup + * code that unconditionally invokes e.g. g_cancellable_cancel(). + * + * Returns: The id of the signal handler or 0 if @cancellable has already + * been cancelled. + * + * Since: 2.22 + */ +gulong +g_cancellable_connect (GCancellable *cancellable, + GCallback callback, + gpointer data, + GDestroyNotify data_destroy_func) +{ + gulong id; + + g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), 0); + + g_mutex_lock (&cancellable_mutex); + + if (g_atomic_int_get (&cancellable->priv->cancelled)) + { + void (*_callback) (GCancellable *cancellable, + gpointer user_data); + + g_mutex_unlock (&cancellable_mutex); + + _callback = (void *)callback; + id = 0; + + _callback (cancellable, data); + + if (data_destroy_func) + data_destroy_func (data); + } + else + { + id = g_signal_connect_data (cancellable, "cancelled", + callback, data, + (GClosureNotify) data_destroy_func, + 0); + + g_mutex_unlock (&cancellable_mutex); + } + + + return id; +} + +/** + * g_cancellable_disconnect: + * @cancellable: (nullable): A #GCancellable or %NULL. + * @handler_id: Handler id of the handler to be disconnected, or `0`. + * + * Disconnects a handler from a cancellable instance similar to + * g_signal_handler_disconnect(). Additionally, in the event that a + * signal handler is currently running, this call will block until the + * handler has finished. Calling this function from a + * #GCancellable::cancelled signal handler will therefore result in a + * deadlock. + * + * This avoids a race condition where a thread cancels at the + * same time as the cancellable operation is finished and the + * signal handler is removed. See #GCancellable::cancelled for + * details on how to use this. + * + * If @cancellable is %NULL or @handler_id is `0` this function does + * nothing. + * + * Since: 2.22 + */ +void +g_cancellable_disconnect (GCancellable *cancellable, + gulong handler_id) +{ + GCancellablePrivate *priv; + + if (handler_id == 0 || cancellable == NULL) + return; + + g_mutex_lock (&cancellable_mutex); + + priv = cancellable->priv; + + while (priv->cancelled_running) + { + priv->cancelled_running_waiting = TRUE; + g_cond_wait (&cancellable_cond, &cancellable_mutex); + } + + g_signal_handler_disconnect (cancellable, handler_id); + + g_mutex_unlock (&cancellable_mutex); +} + +typedef struct { + GSource source; + + GCancellable *cancellable; + gulong cancelled_handler; + /* Protected by cancellable_mutex: */ + gboolean resurrected_during_cancellation; +} GCancellableSource; + +/* + * The reference count of the GSource might be 0 at this point but it is not + * finalized yet and its dispose function did not run yet, or otherwise we + * would have disconnected the signal handler already and due to the signal + * emission lock it would be impossible to call the signal handler at that + * point. That is: at this point we either have a fully valid GSource, or + * it's not disposed or finalized yet and we can still resurrect it as needed. + * + * As such we first ensure that we have a strong reference to the GSource in + * here before calling any other GSource API. + */ +static void +cancellable_source_cancelled (GCancellable *cancellable, + gpointer user_data) +{ + GSource *source = user_data; + GCancellableSource *cancellable_source = (GCancellableSource *) source; + + g_mutex_lock (&cancellable_mutex); + + /* Drop the reference added in cancellable_source_dispose(); see the comment there. + * The reference must be dropped after unlocking @cancellable_mutex since + * it could be the final reference, and the dispose function takes + * @cancellable_mutex. */ + if (cancellable_source->resurrected_during_cancellation) + { + cancellable_source->resurrected_during_cancellation = FALSE; + g_mutex_unlock (&cancellable_mutex); + g_source_unref (source); + return; + } + + g_source_ref (source); + g_mutex_unlock (&cancellable_mutex); + g_source_set_ready_time (source, 0); + g_source_unref (source); +} + +static gboolean +cancellable_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + GCancellableSourceFunc func = (GCancellableSourceFunc)callback; + GCancellableSource *cancellable_source = (GCancellableSource *)source; + + g_source_set_ready_time (source, -1); + return (*func) (cancellable_source->cancellable, user_data); +} + +static void +cancellable_source_dispose (GSource *source) +{ + GCancellableSource *cancellable_source = (GCancellableSource *)source; + + g_mutex_lock (&cancellable_mutex); + + if (cancellable_source->cancellable) + { + if (cancellable_source->cancellable->priv->cancelled_running) + { + /* There can be a race here: if thread A has called + * g_cancellable_cancel() and has got as far as committing to call + * cancellable_source_cancelled(), then thread B drops the final + * ref on the GCancellableSource before g_source_ref() is called in + * cancellable_source_cancelled(), then cancellable_source_dispose() + * will run through and the GCancellableSource will be finalised + * before cancellable_source_cancelled() gets to g_source_ref(). It + * will then be left in a state where it’s committed to using a + * dangling GCancellableSource pointer. + * + * Eliminate that race by resurrecting the #GSource temporarily, and + * then dropping that reference in cancellable_source_cancelled(), + * which should be guaranteed to fire because we’re inside a + * @cancelled_running block. + */ + g_source_ref (source); + cancellable_source->resurrected_during_cancellation = TRUE; + } + + g_clear_signal_handler (&cancellable_source->cancelled_handler, + cancellable_source->cancellable); + g_clear_object (&cancellable_source->cancellable); + } + + g_mutex_unlock (&cancellable_mutex); +} + +static gboolean +cancellable_source_closure_callback (GCancellable *cancellable, + gpointer data) +{ + GClosure *closure = data; + + GValue params = G_VALUE_INIT; + GValue result_value = G_VALUE_INIT; + gboolean result; + + g_value_init (&result_value, G_TYPE_BOOLEAN); + + g_value_init (¶ms, G_TYPE_CANCELLABLE); + g_value_set_object (¶ms, cancellable); + + g_closure_invoke (closure, &result_value, 1, ¶ms, NULL); + + result = g_value_get_boolean (&result_value); + g_value_unset (&result_value); + g_value_unset (¶ms); + + return result; +} + +static GSourceFuncs cancellable_source_funcs = +{ + NULL, + NULL, + cancellable_source_dispatch, + NULL, + (GSourceFunc)cancellable_source_closure_callback, +}; + +/** + * g_cancellable_source_new: + * @cancellable: (nullable): a #GCancellable, or %NULL + * + * Creates a source that triggers if @cancellable is cancelled and + * calls its callback of type #GCancellableSourceFunc. This is + * primarily useful for attaching to another (non-cancellable) source + * with g_source_add_child_source() to add cancellability to it. + * + * For convenience, you can call this with a %NULL #GCancellable, + * in which case the source will never trigger. + * + * The new #GSource will hold a reference to the #GCancellable. + * + * Returns: (transfer full): the new #GSource. + * + * Since: 2.28 + */ +GSource * +g_cancellable_source_new (GCancellable *cancellable) +{ + GSource *source; + GCancellableSource *cancellable_source; + + source = g_source_new (&cancellable_source_funcs, sizeof (GCancellableSource)); + g_source_set_name (source, "GCancellable"); + g_source_set_dispose_function (source, cancellable_source_dispose); + cancellable_source = (GCancellableSource *)source; + + if (cancellable) + { + cancellable_source->cancellable = g_object_ref (cancellable); + + /* We intentionally don't use g_cancellable_connect() here, + * because we don't want the "at most once" behavior. + */ + cancellable_source->cancelled_handler = + g_signal_connect (cancellable, "cancelled", + G_CALLBACK (cancellable_source_cancelled), + source); + if (g_cancellable_is_cancelled (cancellable)) + g_source_set_ready_time (source, 0); + } + + return source; +}
diff --git a/gio/gcancellable.h b/gio/gcancellable.h new file mode 100644 index 0000000..45b9a5a --- /dev/null +++ b/gio/gcancellable.h
@@ -0,0 +1,118 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_CANCELLABLE_H__ +#define __G_CANCELLABLE_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_CANCELLABLE (g_cancellable_get_type ()) +#define G_CANCELLABLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_CANCELLABLE, GCancellable)) +#define G_CANCELLABLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_CANCELLABLE, GCancellableClass)) +#define G_IS_CANCELLABLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_CANCELLABLE)) +#define G_IS_CANCELLABLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_CANCELLABLE)) +#define G_CANCELLABLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_CANCELLABLE, GCancellableClass)) + +/** + * GCancellable: + * + * Allows actions to be cancelled. + */ +typedef struct _GCancellableClass GCancellableClass; +typedef struct _GCancellablePrivate GCancellablePrivate; + +struct _GCancellable +{ + GObject parent_instance; + + /*< private >*/ + GCancellablePrivate *priv; +}; + +struct _GCancellableClass +{ + GObjectClass parent_class; + + void (* cancelled) (GCancellable *cancellable); + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); + void (*_g_reserved5) (void); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_cancellable_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +GCancellable *g_cancellable_new (void); + +/* These are only safe to call inside a cancellable op */ +GLIB_AVAILABLE_IN_ALL +gboolean g_cancellable_is_cancelled (GCancellable *cancellable); +GLIB_AVAILABLE_IN_ALL +gboolean g_cancellable_set_error_if_cancelled (GCancellable *cancellable, + GError **error); + +GLIB_AVAILABLE_IN_ALL +int g_cancellable_get_fd (GCancellable *cancellable); +GLIB_AVAILABLE_IN_ALL +gboolean g_cancellable_make_pollfd (GCancellable *cancellable, + GPollFD *pollfd); +GLIB_AVAILABLE_IN_ALL +void g_cancellable_release_fd (GCancellable *cancellable); + +GLIB_AVAILABLE_IN_ALL +GSource * g_cancellable_source_new (GCancellable *cancellable); + +GLIB_AVAILABLE_IN_ALL +GCancellable *g_cancellable_get_current (void); +GLIB_AVAILABLE_IN_ALL +void g_cancellable_push_current (GCancellable *cancellable); +GLIB_AVAILABLE_IN_ALL +void g_cancellable_pop_current (GCancellable *cancellable); +GLIB_AVAILABLE_IN_ALL +void g_cancellable_reset (GCancellable *cancellable); +GLIB_AVAILABLE_IN_ALL +gulong g_cancellable_connect (GCancellable *cancellable, + GCallback callback, + gpointer data, + GDestroyNotify data_destroy_func); +GLIB_AVAILABLE_IN_ALL +void g_cancellable_disconnect (GCancellable *cancellable, + gulong handler_id); + + +/* This is safe to call from another thread */ +GLIB_AVAILABLE_IN_ALL +void g_cancellable_cancel (GCancellable *cancellable); + +G_END_DECLS + +#endif /* __G_CANCELLABLE_H__ */
diff --git a/gio/gcharsetconverter.c b/gio/gcharsetconverter.c new file mode 100644 index 0000000..d529cbc --- /dev/null +++ b/gio/gcharsetconverter.c
@@ -0,0 +1,472 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" + +#include "gcharsetconverter.h" + +#include <errno.h> + +#include "ginitable.h" +#include "gioerror.h" +#include "glibintl.h" + + +enum { + PROP_0, + PROP_FROM_CHARSET, + PROP_TO_CHARSET, + PROP_USE_FALLBACK +}; + +/** + * SECTION:gcharsetconverter + * @short_description: Convert between charsets + * @include: gio/gio.h + * + * #GCharsetConverter is an implementation of #GConverter based on + * GIConv. + */ + +static void g_charset_converter_iface_init (GConverterIface *iface); +static void g_charset_converter_initable_iface_init (GInitableIface *iface); + +/** + * GCharsetConverter: + * + * Conversions between character sets. + */ +struct _GCharsetConverter +{ + GObject parent_instance; + + char *from; + char *to; + GIConv iconv; + gboolean use_fallback; + guint n_fallback_errors; +}; + +G_DEFINE_TYPE_WITH_CODE (GCharsetConverter, g_charset_converter, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER, + g_charset_converter_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + g_charset_converter_initable_iface_init)) + +static void +g_charset_converter_finalize (GObject *object) +{ + GCharsetConverter *conv; + + conv = G_CHARSET_CONVERTER (object); + + g_free (conv->from); + g_free (conv->to); + if (conv->iconv) + g_iconv_close (conv->iconv); + + G_OBJECT_CLASS (g_charset_converter_parent_class)->finalize (object); +} + +static void +g_charset_converter_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GCharsetConverter *conv; + + conv = G_CHARSET_CONVERTER (object); + + switch (prop_id) + { + case PROP_TO_CHARSET: + g_free (conv->to); + conv->to = g_value_dup_string (value); + break; + + case PROP_FROM_CHARSET: + g_free (conv->from); + conv->from = g_value_dup_string (value); + break; + + case PROP_USE_FALLBACK: + conv->use_fallback = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +g_charset_converter_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GCharsetConverter *conv; + + conv = G_CHARSET_CONVERTER (object); + + switch (prop_id) + { + case PROP_TO_CHARSET: + g_value_set_string (value, conv->to); + break; + + case PROP_FROM_CHARSET: + g_value_set_string (value, conv->from); + break; + + case PROP_USE_FALLBACK: + g_value_set_boolean (value, conv->use_fallback); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_charset_converter_class_init (GCharsetConverterClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = g_charset_converter_finalize; + gobject_class->get_property = g_charset_converter_get_property; + gobject_class->set_property = g_charset_converter_set_property; + + g_object_class_install_property (gobject_class, + PROP_TO_CHARSET, + g_param_spec_string ("to-charset", + P_("To Charset"), + P_("The character encoding to convert to"), + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_FROM_CHARSET, + g_param_spec_string ("from-charset", + P_("From Charset"), + P_("The character encoding to convert from"), + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_USE_FALLBACK, + g_param_spec_boolean ("use-fallback", + P_("Fallback enabled"), + P_("Use fallback (of form \\<hexval>) for invalid bytes"), + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} + +static void +g_charset_converter_init (GCharsetConverter *local) +{ +} + + +/** + * g_charset_converter_new: + * @to_charset: destination charset + * @from_charset: source charset + * @error: #GError for error reporting, or %NULL to ignore. + * + * Creates a new #GCharsetConverter. + * + * Returns: a new #GCharsetConverter or %NULL on error. + * + * Since: 2.24 + **/ +GCharsetConverter * +g_charset_converter_new (const gchar *to_charset, + const gchar *from_charset, + GError **error) +{ + GCharsetConverter *conv; + + conv = g_initable_new (G_TYPE_CHARSET_CONVERTER, + NULL, error, + "to-charset", to_charset, + "from-charset", from_charset, + NULL); + + return conv; +} + +static void +g_charset_converter_reset (GConverter *converter) +{ + GCharsetConverter *conv = G_CHARSET_CONVERTER (converter); + + if (conv->iconv == NULL) + { + g_warning ("Invalid object, not initialized"); + return; + } + + g_iconv (conv->iconv, NULL, NULL, NULL, NULL); + conv->n_fallback_errors = 0; +} + +static GConverterResult +g_charset_converter_convert (GConverter *converter, + const void *inbuf, + gsize inbuf_size, + void *outbuf, + gsize outbuf_size, + GConverterFlags flags, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + GCharsetConverter *conv; + gsize res; + GConverterResult ret; + gchar *inbufp, *outbufp; + gsize in_left, out_left; + int errsv; + gboolean reset; + + conv = G_CHARSET_CONVERTER (converter); + + if (conv->iconv == NULL) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, + _("Invalid object, not initialized")); + return G_CONVERTER_ERROR; + } + + inbufp = (char *)inbuf; + outbufp = (char *)outbuf; + in_left = inbuf_size; + out_left = outbuf_size; + reset = FALSE; + + /* if there is not input try to flush the data */ + if (inbuf_size == 0) + { + if (flags & G_CONVERTER_INPUT_AT_END || + flags & G_CONVERTER_FLUSH) + { + reset = TRUE; + } + else + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, + _("Incomplete multibyte sequence in input")); + return G_CONVERTER_ERROR; + } + } + + if (reset) + /* call g_iconv with NULL inbuf to cleanup shift state */ + res = g_iconv (conv->iconv, + NULL, &in_left, + &outbufp, &out_left); + else + res = g_iconv (conv->iconv, + &inbufp, &in_left, + &outbufp, &out_left); + + *bytes_read = inbufp - (char *)inbuf; + *bytes_written = outbufp - (char *)outbuf; + + /* Don't report error if we converted anything */ + if (res == (gsize) -1 && *bytes_read == 0) + { + errsv = errno; + + switch (errsv) + { + case EINVAL: + /* Incomplete input text */ + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, + _("Incomplete multibyte sequence in input")); + break; + + case E2BIG: + /* Not enough destination space */ + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, + _("Not enough space in destination")); + break; + + case EILSEQ: + /* Invalid code sequence */ + if (conv->use_fallback) + { + if (outbuf_size < 3) + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, + _("Not enough space in destination")); + else + { + const char hex[] = "0123456789ABCDEF"; + guint8 v = *(guint8 *)inbuf; + guint8 *out = (guint8 *)outbuf; + out[0] = '\\'; + out[1] = hex[(v & 0xf0) >> 4]; + out[2] = hex[(v & 0x0f) >> 0]; + *bytes_read = 1; + *bytes_written = 3; + in_left--; + conv->n_fallback_errors++; + goto ok; + } + } + else + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, + _("Invalid byte sequence in conversion input")); + break; + + default: + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Error during conversion: %s"), + g_strerror (errsv)); + break; + } + ret = G_CONVERTER_ERROR; + } + else + { + ok: + ret = G_CONVERTER_CONVERTED; + + if (reset && + (flags & G_CONVERTER_INPUT_AT_END)) + ret = G_CONVERTER_FINISHED; + else if (reset && + (flags & G_CONVERTER_FLUSH)) + ret = G_CONVERTER_FLUSHED; + } + + return ret; +} + +/** + * g_charset_converter_set_use_fallback: + * @converter: a #GCharsetConverter + * @use_fallback: %TRUE to use fallbacks + * + * Sets the #GCharsetConverter:use-fallback property. + * + * Since: 2.24 + */ +void +g_charset_converter_set_use_fallback (GCharsetConverter *converter, + gboolean use_fallback) +{ + use_fallback = !!use_fallback; + + if (converter->use_fallback != use_fallback) + { + converter->use_fallback = use_fallback; + g_object_notify (G_OBJECT (converter), "use-fallback"); + } +} + +/** + * g_charset_converter_get_use_fallback: + * @converter: a #GCharsetConverter + * + * Gets the #GCharsetConverter:use-fallback property. + * + * Returns: %TRUE if fallbacks are used by @converter + * + * Since: 2.24 + */ +gboolean +g_charset_converter_get_use_fallback (GCharsetConverter *converter) +{ + return converter->use_fallback; +} + +/** + * g_charset_converter_get_num_fallbacks: + * @converter: a #GCharsetConverter + * + * Gets the number of fallbacks that @converter has applied so far. + * + * Returns: the number of fallbacks that @converter has applied + * + * Since: 2.24 + */ +guint +g_charset_converter_get_num_fallbacks (GCharsetConverter *converter) +{ + return converter->n_fallback_errors; +} + +static void +g_charset_converter_iface_init (GConverterIface *iface) +{ + iface->convert = g_charset_converter_convert; + iface->reset = g_charset_converter_reset; +} + +static gboolean +g_charset_converter_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + GCharsetConverter *conv; + int errsv; + + g_return_val_if_fail (G_IS_CHARSET_CONVERTER (initable), FALSE); + + conv = G_CHARSET_CONVERTER (initable); + + if (cancellable != NULL) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Cancellable initialization not supported")); + return FALSE; + } + + conv->iconv = g_iconv_open (conv->to, conv->from); + errsv = errno; + + if (conv->iconv == (GIConv)-1) + { + if (errsv == EINVAL) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Conversion from character set “%s” to “%s” is not supported"), + conv->from, conv->to); + else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Could not open converter from “%s” to “%s”"), + conv->from, conv->to); + return FALSE; + } + + return TRUE; +} + +static void +g_charset_converter_initable_iface_init (GInitableIface *iface) +{ + iface->init = g_charset_converter_initable_init; +}
diff --git a/gio/gcharsetconverter.h b/gio/gcharsetconverter.h new file mode 100644 index 0000000..610f774 --- /dev/null +++ b/gio/gcharsetconverter.h
@@ -0,0 +1,63 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_CHARSET_CONVERTER_H__ +#define __G_CHARSET_CONVERTER_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/gconverter.h> + +G_BEGIN_DECLS + +#define G_TYPE_CHARSET_CONVERTER (g_charset_converter_get_type ()) +#define G_CHARSET_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_CHARSET_CONVERTER, GCharsetConverter)) +#define G_CHARSET_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_CHARSET_CONVERTER, GCharsetConverterClass)) +#define G_IS_CHARSET_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_CHARSET_CONVERTER)) +#define G_IS_CHARSET_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_CHARSET_CONVERTER)) +#define G_CHARSET_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_CHARSET_CONVERTER, GCharsetConverterClass)) + +typedef struct _GCharsetConverterClass GCharsetConverterClass; + +struct _GCharsetConverterClass +{ + GObjectClass parent_class; +}; + +GLIB_AVAILABLE_IN_ALL +GType g_charset_converter_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +GCharsetConverter *g_charset_converter_new (const gchar *to_charset, + const gchar *from_charset, + GError **error); +GLIB_AVAILABLE_IN_ALL +void g_charset_converter_set_use_fallback (GCharsetConverter *converter, + gboolean use_fallback); +GLIB_AVAILABLE_IN_ALL +gboolean g_charset_converter_get_use_fallback (GCharsetConverter *converter); +GLIB_AVAILABLE_IN_ALL +guint g_charset_converter_get_num_fallbacks (GCharsetConverter *converter); + +G_END_DECLS + +#endif /* __G_CHARSET_CONVERTER_H__ */
diff --git a/gio/gcocoanotificationbackend.m b/gio/gcocoanotificationbackend.m new file mode 100644 index 0000000..42cf8ab --- /dev/null +++ b/gio/gcocoanotificationbackend.m
@@ -0,0 +1,277 @@ +/* + * Copyright © 2015 Patrick Griffis + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Patrick Griffis + */ + +#include "config.h" + +#import <Cocoa/Cocoa.h> +#include "gnotificationbackend.h" +#include "gapplication.h" +#include "gaction.h" +#include "gactiongroup.h" +#include "giomodule-priv.h" +#include "gnotification-private.h" +#include "gthemedicon.h" +#include "gfileicon.h" +#include "gfile.h" + +#define G_TYPE_COCOA_NOTIFICATION_BACKEND (g_cocoa_notification_backend_get_type ()) +#define G_COCOA_NOTIFICATION_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_COCOA_NOTIFICATION_BACKEND, GCocoaNotificationBackend)) + +typedef struct _GCocoaNotificationBackend GCocoaNotificationBackend; +typedef GNotificationBackendClass GCocoaNotificationBackendClass; +struct _GCocoaNotificationBackend +{ + GNotificationBackend parent; +}; + +GType g_cocoa_notification_backend_get_type (void); + +G_DEFINE_TYPE_WITH_CODE (GCocoaNotificationBackend, g_cocoa_notification_backend, G_TYPE_NOTIFICATION_BACKEND, + _g_io_modules_ensure_extension_points_registered (); + g_io_extension_point_implement (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME, g_define_type_id, "cocoa", 200)); + +static NSString * +nsstring_from_cstr (const char *cstr) +{ + if (!cstr) + return nil; + + return [[NSString alloc] initWithUTF8String:cstr]; +} + +static NSImage* +nsimage_from_gicon (GIcon *icon) +{ + if (G_IS_FILE_ICON (icon)) + { + NSImage *image = nil; + GFile *file; + char *path; + + file = g_file_icon_get_file (G_FILE_ICON (icon)); + path = g_file_get_path (file); + if (path) + { + NSString *str_path = nsstring_from_cstr (path); + image = [[NSImage alloc] initByReferencingFile:str_path]; + + [str_path release]; + g_free (path); + } + return image; + } + else + { + g_warning ("This icon type is not handled by this NotificationBackend"); + return nil; + } +} + +static void +activate_detailed_action (const char * action) +{ + char *name; + GVariant *target; + + if (!g_str_has_prefix (action, "app.")) + { + g_warning ("Notification action does not have \"app.\" prefix"); + return; + } + + if (g_action_parse_detailed_name (action, &name, &target, NULL)) + { + g_action_group_activate_action (G_ACTION_GROUP (g_application_get_default()), name + 4, target); + g_free (name); + if (target) + g_variant_unref (target); + } +} + +@interface GNotificationCenterDelegate : NSObject<NSUserNotificationCenterDelegate> @end +@implementation GNotificationCenterDelegate + +-(void) userNotificationCenter:(NSUserNotificationCenter*) center + didActivateNotification:(NSUserNotification*) notification +{ + if ([notification activationType] == NSUserNotificationActivationTypeContentsClicked) + { + const char *action = [[notification userInfo][@"default"] UTF8String]; + if (action) + activate_detailed_action (action); + /* OSX Always activates the front window */ + } + else if ([notification activationType] == NSUserNotificationActivationTypeActionButtonClicked) + { + const char *action = [[notification userInfo][@"button0"] UTF8String]; + if (action) + activate_detailed_action (action); + } + + [center removeDeliveredNotification:notification]; +} + +@end + +static GNotificationCenterDelegate *cocoa_notification_delegate; + +static gboolean +g_cocoa_notification_backend_is_supported (void) +{ + NSBundle *bundle = [NSBundle mainBundle]; + + /* This is always actually supported, but without a bundle it does nothing */ + if (![bundle bundleIdentifier]) + return FALSE; + + return TRUE; +} + +static void +add_actions_to_notification (NSUserNotification *userNotification, + GNotification *notification) +{ + guint n_buttons = g_notification_get_n_buttons (notification); + char *action = NULL, *label = NULL; + GVariant *target = NULL; + NSMutableDictionary *user_info = nil; + + if (g_notification_get_default_action (notification, &action, &target)) + { + char *detailed_name = g_action_print_detailed_name (action, target); + NSString *action_name = nsstring_from_cstr (detailed_name); + user_info = [[NSMutableDictionary alloc] init]; + + user_info[@"default"] = action_name; + + [action_name release]; + g_free (detailed_name); + g_clear_pointer (&action, g_free); + g_clear_pointer (&target, g_variant_unref); + } + + if (n_buttons) + { + g_notification_get_button (notification, 0, &label, &action, &target); + if (label) + { + NSString *str_label = nsstring_from_cstr (label); + char *detailed_name = g_action_print_detailed_name (action, target); + NSString *action_name = nsstring_from_cstr (detailed_name); + + if (!user_info) + user_info = [[NSMutableDictionary alloc] init]; + + user_info[@"button0"] = action_name; + userNotification.actionButtonTitle = str_label; + + [str_label release]; + [action_name release]; + g_free (label); + g_free (action); + g_free (detailed_name); + g_clear_pointer (&target, g_variant_unref); + } + + if (n_buttons > 1) + g_warning ("Only a single button is currently supported by this NotificationBackend"); + } + + userNotification.userInfo = user_info; + [user_info release]; +} + +static void +g_cocoa_notification_backend_send_notification (GNotificationBackend *backend, + const gchar *cstr_id, + GNotification *notification) +{ + NSString *str_title = nil, *str_text = nil, *str_id = nil; + NSImage *content = nil; + const char *cstr; + GIcon *icon; + NSUserNotification *userNotification; + NSUserNotificationCenter *center; + + if ((cstr = g_notification_get_title (notification))) + str_title = nsstring_from_cstr (cstr); + if ((cstr = g_notification_get_body (notification))) + str_text = nsstring_from_cstr (cstr); + if (cstr_id != NULL) + str_id = nsstring_from_cstr (cstr_id); + if ((icon = g_notification_get_icon (notification))) + content = nsimage_from_gicon (icon); + /* NOTE: There is no priority */ + + userNotification = [NSUserNotification new]; + userNotification.title = str_title; + userNotification.informativeText = str_text; + userNotification.identifier = str_id; + userNotification.contentImage = content; + /* NOTE: Buttons only show up if your bundle has NSUserNotificationAlertStyle set to "alerts" */ + add_actions_to_notification (userNotification, notification); + + if (!cocoa_notification_delegate) + cocoa_notification_delegate = [[GNotificationCenterDelegate alloc] init]; + + center = [NSUserNotificationCenter defaultUserNotificationCenter]; + center.delegate = cocoa_notification_delegate; + [center deliverNotification:userNotification]; + + [str_title release]; + [str_text release]; + [str_id release]; + [content release]; + [userNotification release]; +} + +static void +g_cocoa_notification_backend_withdraw_notification (GNotificationBackend *backend, + const gchar *cstr_id) +{ + NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; + NSArray *notifications = [center deliveredNotifications]; + NSString *str_id = nsstring_from_cstr (cstr_id); + + for (NSUserNotification *notification in notifications) + { + if ([notification.identifier compare:str_id] == NSOrderedSame) + { + [center removeDeliveredNotification:notification]; + break; + } + } + + [str_id release]; +} + +static void +g_cocoa_notification_backend_init (GCocoaNotificationBackend *backend) +{ +} + +static void +g_cocoa_notification_backend_class_init (GCocoaNotificationBackendClass *klass) +{ + GNotificationBackendClass *backend_class = G_NOTIFICATION_BACKEND_CLASS (klass); + + backend_class->is_supported = g_cocoa_notification_backend_is_supported; + backend_class->send_notification = g_cocoa_notification_backend_send_notification; + backend_class->withdraw_notification = g_cocoa_notification_backend_withdraw_notification; +}
diff --git a/gio/gcontenttype-win32.c b/gio/gcontenttype-win32.c new file mode 100644 index 0000000..2f07fa3 --- /dev/null +++ b/gio/gcontenttype-win32.c
@@ -0,0 +1,426 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "gcontenttype.h" +#include "gthemedicon.h" +#include "gicon.h" +#include "glibintl.h" + +#include <windows.h> + +static char * +get_registry_classes_key (const char *subdir, + const wchar_t *key_name) +{ + wchar_t *wc_key; + HKEY reg_key = NULL; + DWORD key_type; + DWORD nbytes; + char *value_utf8; + + value_utf8 = NULL; + + nbytes = 0; + wc_key = g_utf8_to_utf16 (subdir, -1, NULL, NULL, NULL); + if (RegOpenKeyExW (HKEY_CLASSES_ROOT, wc_key, 0, + KEY_QUERY_VALUE, ®_key) == ERROR_SUCCESS && + RegQueryValueExW (reg_key, key_name, 0, + &key_type, NULL, &nbytes) == ERROR_SUCCESS && + (key_type == REG_SZ || key_type == REG_EXPAND_SZ)) + { + wchar_t *wc_temp = g_new (wchar_t, (nbytes+1)/2 + 1); + RegQueryValueExW (reg_key, key_name, 0, + &key_type, (LPBYTE) wc_temp, &nbytes); + wc_temp[nbytes/2] = '\0'; + if (key_type == REG_EXPAND_SZ) + { + wchar_t dummy[1]; + int len = ExpandEnvironmentStringsW (wc_temp, dummy, 1); + if (len > 0) + { + wchar_t *wc_temp_expanded = g_new (wchar_t, len); + if (ExpandEnvironmentStringsW (wc_temp, wc_temp_expanded, len) == len) + value_utf8 = g_utf16_to_utf8 (wc_temp_expanded, -1, NULL, NULL, NULL); + g_free (wc_temp_expanded); + } + } + else + { + value_utf8 = g_utf16_to_utf8 (wc_temp, -1, NULL, NULL, NULL); + } + g_free (wc_temp); + + } + g_free (wc_key); + + if (reg_key != NULL) + RegCloseKey (reg_key); + + return value_utf8; +} + +/*< private >*/ +void +g_content_type_set_mime_dirs (const gchar * const *dirs) +{ + /* noop on Windows */ +} + +/*< private >*/ +const gchar * const * +g_content_type_get_mime_dirs (void) +{ + const gchar * const *mime_dirs = { NULL }; + return mime_dirs; +} + +gboolean +g_content_type_equals (const gchar *type1, + const gchar *type2) +{ + char *progid1, *progid2; + gboolean res; + + g_return_val_if_fail (type1 != NULL, FALSE); + g_return_val_if_fail (type2 != NULL, FALSE); + + if (g_ascii_strcasecmp (type1, type2) == 0) + return TRUE; + + res = FALSE; + progid1 = get_registry_classes_key (type1, NULL); + progid2 = get_registry_classes_key (type2, NULL); + if (progid1 != NULL && progid2 != NULL && + strcmp (progid1, progid2) == 0) + res = TRUE; + g_free (progid1); + g_free (progid2); + + return res; +} + +gboolean +g_content_type_is_a (const gchar *type, + const gchar *supertype) +{ + gboolean res; + char *value_utf8; + + g_return_val_if_fail (type != NULL, FALSE); + g_return_val_if_fail (supertype != NULL, FALSE); + + if (g_content_type_equals (type, supertype)) + return TRUE; + + res = FALSE; + value_utf8 = get_registry_classes_key (type, L"PerceivedType"); + if (value_utf8 && strcmp (value_utf8, supertype) == 0) + res = TRUE; + g_free (value_utf8); + + return res; +} + +gboolean +g_content_type_is_mime_type (const gchar *type, + const gchar *mime_type) +{ + gchar *content_type; + gboolean ret; + + g_return_val_if_fail (type != NULL, FALSE); + g_return_val_if_fail (mime_type != NULL, FALSE); + + content_type = g_content_type_from_mime_type (mime_type); + ret = g_content_type_is_a (type, content_type); + g_free (content_type); + + return ret; +} + +gboolean +g_content_type_is_unknown (const gchar *type) +{ + g_return_val_if_fail (type != NULL, FALSE); + + return strcmp ("*", type) == 0; +} + +gchar * +g_content_type_get_description (const gchar *type) +{ + char *progid; + char *description; + + g_return_val_if_fail (type != NULL, NULL); + + progid = get_registry_classes_key (type, NULL); + if (progid) + { + description = get_registry_classes_key (progid, NULL); + g_free (progid); + + if (description) + return description; + } + + if (g_content_type_is_unknown (type)) + return g_strdup (_("Unknown type")); + + return g_strdup_printf (_("%s filetype"), type); +} + +gchar * +g_content_type_get_mime_type (const gchar *type) +{ + char *mime; + + g_return_val_if_fail (type != NULL, NULL); + + mime = get_registry_classes_key (type, L"Content Type"); + if (mime) + return mime; + else if (g_content_type_is_unknown (type)) + return g_strdup ("application/octet-stream"); + else if (*type == '.') + return g_strdup_printf ("application/x-ext-%s", type+1); + else if (strcmp ("inode/directory", type) == 0) + return g_strdup (type); + /* TODO: Map "image" to "image/ *", etc? */ + + return g_strdup ("application/octet-stream"); +} + +G_LOCK_DEFINE_STATIC (_type_icons); +static GHashTable *_type_icons = NULL; + +GIcon * +g_content_type_get_icon (const gchar *type) +{ + GIcon *themed_icon; + char *name = NULL; + + g_return_val_if_fail (type != NULL, NULL); + + /* In the Registry icons are the default value of + HKEY_CLASSES_ROOT\<progid>\DefaultIcon with typical values like: + <type>: <value> + REG_EXPAND_SZ: %SystemRoot%\System32\Wscript.exe,3 + REG_SZ: shimgvw.dll,3 + */ + G_LOCK (_type_icons); + if (!_type_icons) + _type_icons = g_hash_table_new (g_str_hash, g_str_equal); + name = g_hash_table_lookup (_type_icons, type); + if (!name && type[0] == '.') + { + /* double lookup by extension */ + gchar *key = get_registry_classes_key (type, NULL); + if (!key) + key = g_strconcat (type+1, "file\\DefaultIcon", NULL); + else + { + gchar *key2 = g_strconcat (key, "\\DefaultIcon", NULL); + g_free (key); + key = key2; + } + name = get_registry_classes_key (key, NULL); + if (name && strcmp (name, "%1") == 0) + { + g_free (name); + name = NULL; + } + if (name) + g_hash_table_insert (_type_icons, g_strdup (type), g_strdup (name)); + g_free (key); + } + + if (!name) + { + /* if no icon found, fall back to standard generic names */ + if (strcmp (type, "inode/directory") == 0) + name = "folder"; + else if (g_content_type_can_be_executable (type)) + name = "system-run"; + else + name = "text-x-generic"; + g_hash_table_insert (_type_icons, g_strdup (type), g_strdup (name)); + } + themed_icon = g_themed_icon_new (name); + G_UNLOCK (_type_icons); + + return G_ICON (themed_icon); +} + +GIcon * +g_content_type_get_symbolic_icon (const gchar *type) +{ + return g_content_type_get_icon (type); +} + +gchar * +g_content_type_get_generic_icon_name (const gchar *type) +{ + return NULL; +} + +gboolean +g_content_type_can_be_executable (const gchar *type) +{ + g_return_val_if_fail (type != NULL, FALSE); + + if (strcmp (type, ".exe") == 0 || + strcmp (type, ".com") == 0 || + strcmp (type, ".bat") == 0) + return TRUE; + + /* TODO: Also look at PATHEXT, which lists the extensions for + * "scripts" in addition to those for true binary executables. + * + * (PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH for me + * right now, for instance). And in a sense, all associated file + * types are "executable" on Windows... You can just type foo.jpg as + * a command name in cmd.exe, and it will run the application + * associated with .jpg. Hard to say what this API actually means + * with "executable". + */ + + return FALSE; +} + +static gboolean +looks_like_text (const guchar *data, + gsize data_size) +{ + gsize i; + guchar c; + for (i = 0; i < data_size; i++) + { + c = data[i]; + if (g_ascii_iscntrl (c) && !g_ascii_isspace (c) && c != '\b') + return FALSE; + } + return TRUE; +} + +gchar * +g_content_type_from_mime_type (const gchar *mime_type) +{ + char *key, *content_type; + + g_return_val_if_fail (mime_type != NULL, NULL); + + /* This is a hack to allow directories to have icons in filechooser */ + if (strcmp ("inode/directory", mime_type) == 0) + return g_strdup (mime_type); + + key = g_strconcat ("MIME\\DataBase\\Content Type\\", mime_type, NULL); + content_type = get_registry_classes_key (key, L"Extension"); + g_free (key); + + return content_type; +} + +gchar * +g_content_type_guess (const gchar *filename, + const guchar *data, + gsize data_size, + gboolean *result_uncertain) +{ + char *basename; + char *type; + char *dot; + + type = NULL; + + if (result_uncertain) + *result_uncertain = FALSE; + + /* our test suite and potentially other code used -1 in the past, which is + * not documented and not allowed; guard against that */ + g_return_val_if_fail (data_size != (gsize) -1, g_strdup ("*")); + + if (filename) + { + basename = g_path_get_basename (filename); + dot = strrchr (basename, '.'); + if (dot) + type = g_strdup (dot); + g_free (basename); + } + + if (type) + return type; + + if (data && looks_like_text (data, data_size)) + return g_strdup (".txt"); + + return g_strdup ("*"); +} + +GList * +g_content_types_get_registered (void) +{ + DWORD index; + wchar_t keyname[256]; + DWORD key_len; + char *key_utf8; + GList *types; + + types = NULL; + index = 0; + key_len = 256; + while (RegEnumKeyExW(HKEY_CLASSES_ROOT, + index, + keyname, + &key_len, + NULL, + NULL, + NULL, + NULL) == ERROR_SUCCESS) + { + key_utf8 = g_utf16_to_utf8 (keyname, -1, NULL, NULL, NULL); + if (key_utf8) + { + if (*key_utf8 == '.') + types = g_list_prepend (types, key_utf8); + else + g_free (key_utf8); + } + index++; + key_len = 256; + } + + return g_list_reverse (types); +} + +gchar ** +g_content_type_guess_for_tree (GFile *root) +{ + /* FIXME: implement */ + return NULL; +}
diff --git a/gio/gcontenttype.c b/gio/gcontenttype.c new file mode 100644 index 0000000..2716c89 --- /dev/null +++ b/gio/gcontenttype.c
@@ -0,0 +1,1526 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "gcontenttypeprivate.h" +#include "gthemedicon.h" +#include "gicon.h" +#include "gfile.h" +#include "gfileenumerator.h" +#include "gfileinfo.h" +#include "glibintl.h" + + +/** + * SECTION:gcontenttype + * @short_description: Platform-specific content typing + * @include: gio/gio.h + * + * A content type is a platform specific string that defines the type + * of a file. On UNIX it is a + * [MIME type](http://www.wikipedia.org/wiki/Internet_media_type) + * like `text/plain` or `image/png`. + * On Win32 it is an extension string like `.doc`, `.txt` or a perceived + * string like `audio`. Such strings can be looked up in the registry at + * `HKEY_CLASSES_ROOT`. + * On macOS it is a [Uniform Type Identifier](https://en.wikipedia.org/wiki/Uniform_Type_Identifier) + * such as `com.apple.application`. + **/ + +#include <dirent.h> + +#define XDG_PREFIX _gio_xdg +#include "xdgmime/xdgmime.h" + +static void tree_magic_schedule_reload (void); + +/* We lock this mutex whenever we modify global state in this module. */ +G_LOCK_DEFINE_STATIC (gio_xdgmime); + +gsize +_g_unix_content_type_get_sniff_len (void) +{ + gsize size; + + G_LOCK (gio_xdgmime); + size = xdg_mime_get_max_buffer_extents (); + G_UNLOCK (gio_xdgmime); + + return size; +} + +gchar * +_g_unix_content_type_unalias (const gchar *type) +{ + gchar *res; + + G_LOCK (gio_xdgmime); + res = g_strdup (xdg_mime_unalias_mime_type (type)); + G_UNLOCK (gio_xdgmime); + + return res; +} + +gchar ** +_g_unix_content_type_get_parents (const gchar *type) +{ + const gchar *umime; + gchar **parents; + GPtrArray *array; + int i; + + array = g_ptr_array_new (); + + G_LOCK (gio_xdgmime); + + umime = xdg_mime_unalias_mime_type (type); + + g_ptr_array_add (array, g_strdup (umime)); + + parents = xdg_mime_list_mime_parents (umime); + for (i = 0; parents && parents[i] != NULL; i++) + g_ptr_array_add (array, g_strdup (parents[i])); + + free (parents); + + G_UNLOCK (gio_xdgmime); + + g_ptr_array_add (array, NULL); + + return (gchar **)g_ptr_array_free (array, FALSE); +} + +G_LOCK_DEFINE_STATIC (global_mime_dirs); +static gchar **global_mime_dirs = NULL; + +static void +_g_content_type_set_mime_dirs_locked (const char * const *dirs) +{ + g_clear_pointer (&global_mime_dirs, g_strfreev); + + if (dirs != NULL) + { + global_mime_dirs = g_strdupv ((gchar **) dirs); + } + else + { + GPtrArray *mime_dirs = g_ptr_array_new_with_free_func (g_free); + const gchar * const *system_dirs = g_get_system_data_dirs (); + + g_ptr_array_add (mime_dirs, g_build_filename (g_get_user_data_dir (), "mime", NULL)); + for (; *system_dirs != NULL; system_dirs++) + g_ptr_array_add (mime_dirs, g_build_filename (*system_dirs, "mime", NULL)); + g_ptr_array_add (mime_dirs, NULL); /* NULL terminator */ + + global_mime_dirs = (gchar **) g_ptr_array_free (mime_dirs, FALSE); + } + + xdg_mime_set_dirs ((const gchar * const *) global_mime_dirs); + tree_magic_schedule_reload (); +} + +/** + * g_content_type_set_mime_dirs: + * @dirs: (array zero-terminated=1) (nullable): %NULL-terminated list of + * directories to load MIME data from, including any `mime/` subdirectory, + * and with the first directory to try listed first + * + * Set the list of directories used by GIO to load the MIME database. + * If @dirs is %NULL, the directories used are the default: + * + * - the `mime` subdirectory of the directory in `$XDG_DATA_HOME` + * - the `mime` subdirectory of every directory in `$XDG_DATA_DIRS` + * + * This function is intended to be used when writing tests that depend on + * information stored in the MIME database, in order to control the data. + * + * Typically, in case your tests use %G_TEST_OPTION_ISOLATE_DIRS, but they + * depend on the system’s MIME database, you should call this function + * with @dirs set to %NULL before calling g_test_init(), for instance: + * + * |[<!-- language="C" --> + * // Load MIME data from the system + * g_content_type_set_mime_dirs (NULL); + * // Isolate the environment + * g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); + * + * … + * + * return g_test_run (); + * ]| + * + * Since: 2.60 + */ +/*< private >*/ +void +g_content_type_set_mime_dirs (const gchar * const *dirs) +{ + G_LOCK (global_mime_dirs); + _g_content_type_set_mime_dirs_locked (dirs); + G_UNLOCK (global_mime_dirs); +} + +/** + * g_content_type_get_mime_dirs: + * + * Get the list of directories which MIME data is loaded from. See + * g_content_type_set_mime_dirs() for details. + * + * Returns: (transfer none) (array zero-terminated=1): %NULL-terminated list of + * directories to load MIME data from, including any `mime/` subdirectory, + * and with the first directory to try listed first + * Since: 2.60 + */ +/*< private >*/ +const gchar * const * +g_content_type_get_mime_dirs (void) +{ + const gchar * const *mime_dirs; + + G_LOCK (global_mime_dirs); + + if (global_mime_dirs == NULL) + _g_content_type_set_mime_dirs_locked (NULL); + + mime_dirs = (const gchar * const *) global_mime_dirs; + + G_UNLOCK (global_mime_dirs); + + g_assert (mime_dirs != NULL); + return mime_dirs; +} + +/** + * g_content_type_equals: + * @type1: a content type string + * @type2: a content type string + * + * Compares two content types for equality. + * + * Returns: %TRUE if the two strings are identical or equivalent, + * %FALSE otherwise. + */ +gboolean +g_content_type_equals (const gchar *type1, + const gchar *type2) +{ + gboolean res; + + g_return_val_if_fail (type1 != NULL, FALSE); + g_return_val_if_fail (type2 != NULL, FALSE); + + G_LOCK (gio_xdgmime); + res = xdg_mime_mime_type_equal (type1, type2); + G_UNLOCK (gio_xdgmime); + + return res; +} + +/** + * g_content_type_is_a: + * @type: a content type string + * @supertype: a content type string + * + * Determines if @type is a subset of @supertype. + * + * Returns: %TRUE if @type is a kind of @supertype, + * %FALSE otherwise. + */ +gboolean +g_content_type_is_a (const gchar *type, + const gchar *supertype) +{ + gboolean res; + + g_return_val_if_fail (type != NULL, FALSE); + g_return_val_if_fail (supertype != NULL, FALSE); + + G_LOCK (gio_xdgmime); + res = xdg_mime_mime_type_subclass (type, supertype); + G_UNLOCK (gio_xdgmime); + + return res; +} + +/** + * g_content_type_is_mime_type: + * @type: a content type string + * @mime_type: a mime type string + * + * Determines if @type is a subset of @mime_type. + * Convenience wrapper around g_content_type_is_a(). + * + * Returns: %TRUE if @type is a kind of @mime_type, + * %FALSE otherwise. + * + * Since: 2.52 + */ +gboolean +g_content_type_is_mime_type (const gchar *type, + const gchar *mime_type) +{ + return g_content_type_is_a (type, mime_type); +} + +/** + * g_content_type_is_unknown: + * @type: a content type string + * + * Checks if the content type is the generic "unknown" type. + * On UNIX this is the "application/octet-stream" mimetype, + * while on win32 it is "*" and on OSX it is a dynamic type + * or octet-stream. + * + * Returns: %TRUE if the type is the unknown type. + */ +gboolean +g_content_type_is_unknown (const gchar *type) +{ + g_return_val_if_fail (type != NULL, FALSE); + + return strcmp (XDG_MIME_TYPE_UNKNOWN, type) == 0; +} + + +typedef enum { + MIME_TAG_TYPE_OTHER, + MIME_TAG_TYPE_COMMENT +} MimeTagType; + +typedef struct { + int current_type; + int current_lang_level; + int comment_lang_level; + char *comment; +} MimeParser; + + +static int +language_level (const char *lang) +{ + const char * const *lang_list; + int i; + + /* The returned list is sorted from most desirable to least + desirable and always contains the default locale "C". */ + lang_list = g_get_language_names (); + + for (i = 0; lang_list[i]; i++) + if (strcmp (lang_list[i], lang) == 0) + return 1000-i; + + return 0; +} + +static void +mime_info_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + int i; + const char *lang; + MimeParser *parser = user_data; + + if (strcmp (element_name, "comment") == 0) + { + lang = "C"; + for (i = 0; attribute_names[i]; i++) + if (strcmp (attribute_names[i], "xml:lang") == 0) + { + lang = attribute_values[i]; + break; + } + + parser->current_lang_level = language_level (lang); + parser->current_type = MIME_TAG_TYPE_COMMENT; + } + else + parser->current_type = MIME_TAG_TYPE_OTHER; +} + +static void +mime_info_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + MimeParser *parser = user_data; + + parser->current_type = MIME_TAG_TYPE_OTHER; +} + +static void +mime_info_text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + MimeParser *parser = user_data; + + if (parser->current_type == MIME_TAG_TYPE_COMMENT && + parser->current_lang_level > parser->comment_lang_level) + { + g_free (parser->comment); + parser->comment = g_strndup (text, text_len); + parser->comment_lang_level = parser->current_lang_level; + } +} + +static char * +load_comment_for_mime_helper (const char *dir, + const char *basename) +{ + GMarkupParseContext *context; + char *filename, *data; + gsize len; + gboolean res; + MimeParser parse_data = {0}; + GMarkupParser parser = { + mime_info_start_element, + mime_info_end_element, + mime_info_text + }; + + filename = g_build_filename (dir, basename, NULL); + + res = g_file_get_contents (filename, &data, &len, NULL); + g_free (filename); + if (!res) + return NULL; + + context = g_markup_parse_context_new (&parser, 0, &parse_data, NULL); + res = g_markup_parse_context_parse (context, data, len, NULL); + g_free (data); + g_markup_parse_context_free (context); + + if (!res) + return NULL; + + return parse_data.comment; +} + + +static char * +load_comment_for_mime (const char *mimetype) +{ + const char * const *dirs; + char *basename; + char *comment; + gsize i; + + basename = g_strdup_printf ("%s.xml", mimetype); + + dirs = g_content_type_get_mime_dirs (); + for (i = 0; dirs[i] != NULL; i++) + { + comment = load_comment_for_mime_helper (dirs[i], basename); + if (comment) + { + g_free (basename); + return comment; + } + } + g_free (basename); + + return g_strdup_printf (_("%s type"), mimetype); +} + +/** + * g_content_type_get_description: + * @type: a content type string + * + * Gets the human readable description of the content type. + * + * Returns: a short description of the content type @type. Free the + * returned string with g_free() + */ +gchar * +g_content_type_get_description (const gchar *type) +{ + static GHashTable *type_comment_cache = NULL; + gchar *comment; + + g_return_val_if_fail (type != NULL, NULL); + + G_LOCK (gio_xdgmime); + type = xdg_mime_unalias_mime_type (type); + + if (type_comment_cache == NULL) + type_comment_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + comment = g_hash_table_lookup (type_comment_cache, type); + comment = g_strdup (comment); + G_UNLOCK (gio_xdgmime); + + if (comment != NULL) + return comment; + + comment = load_comment_for_mime (type); + + G_LOCK (gio_xdgmime); + g_hash_table_insert (type_comment_cache, + g_strdup (type), + g_strdup (comment)); + G_UNLOCK (gio_xdgmime); + + return comment; +} + +/** + * g_content_type_get_mime_type: + * @type: a content type string + * + * Gets the mime type for the content type, if one is registered. + * + * Returns: (nullable) (transfer full): the registered mime type for the + * given @type, or %NULL if unknown; free with g_free(). + */ +char * +g_content_type_get_mime_type (const char *type) +{ + g_return_val_if_fail (type != NULL, NULL); + + return g_strdup (type); +} + +static GIcon * +g_content_type_get_icon_internal (const gchar *type, + gboolean symbolic) +{ + char *mimetype_icon; + char *generic_mimetype_icon = NULL; + char *q; + char *icon_names[6]; + int n = 0; + GIcon *themed_icon; + const char *xdg_icon; + int i; + + g_return_val_if_fail (type != NULL, NULL); + + G_LOCK (gio_xdgmime); + xdg_icon = xdg_mime_get_icon (type); + G_UNLOCK (gio_xdgmime); + + if (xdg_icon) + icon_names[n++] = g_strdup (xdg_icon); + + mimetype_icon = g_strdup (type); + while ((q = strchr (mimetype_icon, '/')) != NULL) + *q = '-'; + + icon_names[n++] = mimetype_icon; + + generic_mimetype_icon = g_content_type_get_generic_icon_name (type); + if (generic_mimetype_icon) + icon_names[n++] = generic_mimetype_icon; + + if (symbolic) + { + for (i = 0; i < n; i++) + { + icon_names[n + i] = icon_names[i]; + icon_names[i] = g_strconcat (icon_names[i], "-symbolic", NULL); + } + + n += n; + } + + themed_icon = g_themed_icon_new_from_names (icon_names, n); + + for (i = 0; i < n; i++) + g_free (icon_names[i]); + + return themed_icon; +} + +/** + * g_content_type_get_icon: + * @type: a content type string + * + * Gets the icon for a content type. + * + * Returns: (transfer full): #GIcon corresponding to the content type. Free the returned + * object with g_object_unref() + */ +GIcon * +g_content_type_get_icon (const gchar *type) +{ + return g_content_type_get_icon_internal (type, FALSE); +} + +/** + * g_content_type_get_symbolic_icon: + * @type: a content type string + * + * Gets the symbolic icon for a content type. + * + * Returns: (transfer full): symbolic #GIcon corresponding to the content type. + * Free the returned object with g_object_unref() + * + * Since: 2.34 + */ +GIcon * +g_content_type_get_symbolic_icon (const gchar *type) +{ + return g_content_type_get_icon_internal (type, TRUE); +} + +/** + * g_content_type_get_generic_icon_name: + * @type: a content type string + * + * Gets the generic icon name for a content type. + * + * See the + * [shared-mime-info](http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec) + * specification for more on the generic icon name. + * + * Returns: (nullable): the registered generic icon name for the given @type, + * or %NULL if unknown. Free with g_free() + * + * Since: 2.34 + */ +gchar * +g_content_type_get_generic_icon_name (const gchar *type) +{ + const gchar *xdg_icon_name; + gchar *icon_name; + + g_return_val_if_fail (type != NULL, NULL); + + G_LOCK (gio_xdgmime); + xdg_icon_name = xdg_mime_get_generic_icon (type); + G_UNLOCK (gio_xdgmime); + + if (!xdg_icon_name) + { + const char *p; + const char *suffix = "-x-generic"; + + p = strchr (type, '/'); + if (p == NULL) + p = type + strlen (type); + + icon_name = g_malloc (p - type + strlen (suffix) + 1); + memcpy (icon_name, type, p - type); + memcpy (icon_name + (p - type), suffix, strlen (suffix)); + icon_name[(p - type) + strlen (suffix)] = 0; + } + else + { + icon_name = g_strdup (xdg_icon_name); + } + + return icon_name; +} + +/** + * g_content_type_can_be_executable: + * @type: a content type string + * + * Checks if a content type can be executable. Note that for instance + * things like text files can be executables (i.e. scripts and batch files). + * + * Returns: %TRUE if the file type corresponds to a type that + * can be executable, %FALSE otherwise. + */ +gboolean +g_content_type_can_be_executable (const gchar *type) +{ + g_return_val_if_fail (type != NULL, FALSE); + + if (g_content_type_is_a (type, "application/x-executable") || + g_content_type_is_a (type, "text/plain")) + return TRUE; + + return FALSE; +} + +static gboolean +looks_like_text (const guchar *data, gsize data_size) +{ + gsize i; + char c; + + for (i = 0; i < data_size; i++) + { + c = data[i]; + + if (g_ascii_iscntrl (c) && + !g_ascii_isspace (c) && + c != '\b') + return FALSE; + } + return TRUE; +} + +/** + * g_content_type_from_mime_type: + * @mime_type: a mime type string + * + * Tries to find a content type based on the mime type name. + * + * Returns: (nullable): Newly allocated string with content type or + * %NULL. Free with g_free() + * + * Since: 2.18 + **/ +gchar * +g_content_type_from_mime_type (const gchar *mime_type) +{ + char *umime; + + g_return_val_if_fail (mime_type != NULL, NULL); + + G_LOCK (gio_xdgmime); + /* mime type and content type are same on unixes */ + umime = g_strdup (xdg_mime_unalias_mime_type (mime_type)); + G_UNLOCK (gio_xdgmime); + + return umime; +} + +/** + * g_content_type_guess: + * @filename: (nullable): a string, or %NULL + * @data: (nullable) (array length=data_size): a stream of data, or %NULL + * @data_size: the size of @data + * @result_uncertain: (out) (optional): return location for the certainty + * of the result, or %NULL + * + * Guesses the content type based on example data. If the function is + * uncertain, @result_uncertain will be set to %TRUE. Either @filename + * or @data may be %NULL, in which case the guess will be based solely + * on the other argument. + * + * Returns: a string indicating a guessed content type for the + * given data. Free with g_free() + */ +gchar * +g_content_type_guess (const gchar *filename, + const guchar *data, + gsize data_size, + gboolean *result_uncertain) +{ + char *basename; + const char *name_mimetypes[10], *sniffed_mimetype; + char *mimetype; + int i; + int n_name_mimetypes; + int sniffed_prio; + + sniffed_prio = 0; + n_name_mimetypes = 0; + sniffed_mimetype = XDG_MIME_TYPE_UNKNOWN; + + if (result_uncertain) + *result_uncertain = FALSE; + + /* our test suite and potentially other code used -1 in the past, which is + * not documented and not allowed; guard against that */ + g_return_val_if_fail (data_size != (gsize) -1, g_strdup (XDG_MIME_TYPE_UNKNOWN)); + + G_LOCK (gio_xdgmime); + + if (filename) + { + i = strlen (filename); + if (filename[i - 1] == '/') + { + name_mimetypes[0] = "inode/directory"; + name_mimetypes[1] = NULL; + n_name_mimetypes = 1; + if (result_uncertain) + *result_uncertain = TRUE; + } + else + { + basename = g_path_get_basename (filename); + n_name_mimetypes = xdg_mime_get_mime_types_from_file_name (basename, name_mimetypes, 10); + g_free (basename); + } + } + + /* Got an extension match, and no conflicts. This is it. */ + if (n_name_mimetypes == 1) + { + gchar *s = g_strdup (name_mimetypes[0]); + G_UNLOCK (gio_xdgmime); + return s; + } + + if (data) + { + sniffed_mimetype = xdg_mime_get_mime_type_for_data (data, data_size, &sniffed_prio); + if (sniffed_mimetype == XDG_MIME_TYPE_UNKNOWN && + data && + looks_like_text (data, data_size)) + sniffed_mimetype = "text/plain"; + + /* For security reasons we don't ever want to sniff desktop files + * where we know the filename and it doesn't have a .desktop extension. + * This is because desktop files allow executing any application and + * we don't want to make it possible to hide them looking like something + * else. + */ + if (filename != NULL && + strcmp (sniffed_mimetype, "application/x-desktop") == 0) + sniffed_mimetype = "text/plain"; + } + + if (n_name_mimetypes == 0) + { + if (sniffed_mimetype == XDG_MIME_TYPE_UNKNOWN && + result_uncertain) + *result_uncertain = TRUE; + + mimetype = g_strdup (sniffed_mimetype); + } + else + { + mimetype = NULL; + if (sniffed_mimetype != XDG_MIME_TYPE_UNKNOWN) + { + if (sniffed_prio >= 80) /* High priority sniffing match, use that */ + mimetype = g_strdup (sniffed_mimetype); + else + { + /* There are conflicts between the name matches and we + * have a sniffed type, use that as a tie breaker. + */ + for (i = 0; i < n_name_mimetypes; i++) + { + if ( xdg_mime_mime_type_subclass (name_mimetypes[i], sniffed_mimetype)) + { + /* This nametype match is derived from (or the same as) + * the sniffed type). This is probably it. + */ + mimetype = g_strdup (name_mimetypes[i]); + break; + } + } + } + } + + if (mimetype == NULL) + { + /* Conflicts, and sniffed type was no help or not there. + * Guess on the first one + */ + mimetype = g_strdup (name_mimetypes[0]); + if (result_uncertain) + *result_uncertain = TRUE; + } + } + + G_UNLOCK (gio_xdgmime); + + return mimetype; +} + +static void +enumerate_mimetypes_subdir (const char *dir, + const char *prefix, + GHashTable *mimetypes) +{ + DIR *d; + struct dirent *ent; + char *mimetype; + + d = opendir (dir); + if (d) + { + while ((ent = readdir (d)) != NULL) + { + if (g_str_has_suffix (ent->d_name, ".xml")) + { + mimetype = g_strdup_printf ("%s/%.*s", prefix, (int) strlen (ent->d_name) - 4, ent->d_name); + g_hash_table_replace (mimetypes, mimetype, NULL); + } + } + closedir (d); + } +} + +static void +enumerate_mimetypes_dir (const char *dir, + GHashTable *mimetypes) +{ + DIR *d; + struct dirent *ent; + const char *mimedir; + char *name; + + mimedir = dir; + + d = opendir (mimedir); + if (d) + { + while ((ent = readdir (d)) != NULL) + { + if (strcmp (ent->d_name, "packages") != 0) + { + name = g_build_filename (mimedir, ent->d_name, NULL); + if (g_file_test (name, G_FILE_TEST_IS_DIR)) + enumerate_mimetypes_subdir (name, ent->d_name, mimetypes); + g_free (name); + } + } + closedir (d); + } +} + +/** + * g_content_types_get_registered: + * + * Gets a list of strings containing all the registered content types + * known to the system. The list and its data should be freed using + * `g_list_free_full (list, g_free)`. + * + * Returns: (element-type utf8) (transfer full): list of the registered + * content types + */ +GList * +g_content_types_get_registered (void) +{ + const char * const *dirs; + GHashTable *mimetypes; + GHashTableIter iter; + gpointer key; + gsize i; + GList *l; + + mimetypes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + dirs = g_content_type_get_mime_dirs (); + for (i = 0; dirs[i] != NULL; i++) + enumerate_mimetypes_dir (dirs[i], mimetypes); + + l = NULL; + g_hash_table_iter_init (&iter, mimetypes); + while (g_hash_table_iter_next (&iter, &key, NULL)) + { + l = g_list_prepend (l, key); + g_hash_table_iter_steal (&iter); + } + + g_hash_table_destroy (mimetypes); + + return l; +} + + +/* tree magic data */ +static GList *tree_matches = NULL; +static gboolean need_reload = FALSE; + +G_LOCK_DEFINE_STATIC (gio_treemagic); + +typedef struct +{ + gchar *path; + GFileType type; + guint match_case : 1; + guint executable : 1; + guint non_empty : 1; + guint on_disc : 1; + gchar *mimetype; + GList *matches; +} TreeMatchlet; + +typedef struct +{ + gchar *contenttype; + gint priority; + GList *matches; +} TreeMatch; + + +static void +tree_matchlet_free (TreeMatchlet *matchlet) +{ + g_list_free_full (matchlet->matches, (GDestroyNotify) tree_matchlet_free); + g_free (matchlet->path); + g_free (matchlet->mimetype); + g_slice_free (TreeMatchlet, matchlet); +} + +static void +tree_match_free (TreeMatch *match) +{ + g_list_free_full (match->matches, (GDestroyNotify) tree_matchlet_free); + g_free (match->contenttype); + g_slice_free (TreeMatch, match); +} + +static TreeMatch * +parse_header (gchar *line) +{ + gint len; + gchar *s; + TreeMatch *match; + + len = strlen (line); + + if (line[0] != '[' || line[len - 1] != ']') + return NULL; + + line[len - 1] = 0; + s = strchr (line, ':'); + + match = g_slice_new0 (TreeMatch); + match->priority = atoi (line + 1); + match->contenttype = g_strdup (s + 1); + + return match; +} + +static TreeMatchlet * +parse_match_line (gchar *line, + gint *depth) +{ + gchar *s, *p; + TreeMatchlet *matchlet; + gchar **parts; + gint i; + + matchlet = g_slice_new0 (TreeMatchlet); + + if (line[0] == '>') + { + *depth = 0; + s = line; + } + else + { + *depth = atoi (line); + s = strchr (line, '>'); + } + s += 2; + p = strchr (s, '"'); + *p = 0; + + matchlet->path = g_strdup (s); + s = p + 1; + parts = g_strsplit (s, ",", 0); + if (strcmp (parts[0], "=file") == 0) + matchlet->type = G_FILE_TYPE_REGULAR; + else if (strcmp (parts[0], "=directory") == 0) + matchlet->type = G_FILE_TYPE_DIRECTORY; + else if (strcmp (parts[0], "=link") == 0) + matchlet->type = G_FILE_TYPE_SYMBOLIC_LINK; + else + matchlet->type = G_FILE_TYPE_UNKNOWN; + for (i = 1; parts[i]; i++) + { + if (strcmp (parts[i], "executable") == 0) + matchlet->executable = 1; + else if (strcmp (parts[i], "match-case") == 0) + matchlet->match_case = 1; + else if (strcmp (parts[i], "non-empty") == 0) + matchlet->non_empty = 1; + else if (strcmp (parts[i], "on-disc") == 0) + matchlet->on_disc = 1; + else + matchlet->mimetype = g_strdup (parts[i]); + } + + g_strfreev (parts); + + return matchlet; +} + +static gint +cmp_match (gconstpointer a, gconstpointer b) +{ + const TreeMatch *aa = (const TreeMatch *)a; + const TreeMatch *bb = (const TreeMatch *)b; + + return bb->priority - aa->priority; +} + +static void +insert_match (TreeMatch *match) +{ + tree_matches = g_list_insert_sorted (tree_matches, match, cmp_match); +} + +static void +insert_matchlet (TreeMatch *match, + TreeMatchlet *matchlet, + gint depth) +{ + if (depth == 0) + match->matches = g_list_append (match->matches, matchlet); + else + { + GList *last; + TreeMatchlet *m; + + last = g_list_last (match->matches); + if (!last) + { + tree_matchlet_free (matchlet); + g_warning ("can't insert tree matchlet at depth %d", depth); + return; + } + + m = (TreeMatchlet *) last->data; + while (--depth > 0) + { + last = g_list_last (m->matches); + if (!last) + { + tree_matchlet_free (matchlet); + g_warning ("can't insert tree matchlet at depth %d", depth); + return; + } + + m = (TreeMatchlet *) last->data; + } + m->matches = g_list_append (m->matches, matchlet); + } +} + +static void +read_tree_magic_from_directory (const gchar *prefix) +{ + gchar *filename; + gchar *text; + gsize len; + gchar **lines; + gint i; + TreeMatch *match; + TreeMatchlet *matchlet; + gint depth; + + filename = g_build_filename (prefix, "treemagic", NULL); + + if (g_file_get_contents (filename, &text, &len, NULL)) + { + if (strcmp (text, "MIME-TreeMagic") == 0) + { + lines = g_strsplit (text + strlen ("MIME-TreeMagic") + 2, "\n", 0); + match = NULL; + for (i = 0; lines[i] && lines[i][0]; i++) + { + if (lines[i][0] == '[') + { + match = parse_header (lines[i]); + insert_match (match); + } + else if (match != NULL) + { + matchlet = parse_match_line (lines[i], &depth); + insert_matchlet (match, matchlet, depth); + } + else + { + g_warning ("%s: header corrupt; skipping", filename); + break; + } + } + + g_strfreev (lines); + } + else + g_warning ("%s: header not found, skipping", filename); + + g_free (text); + } + + g_free (filename); +} + +static void +tree_magic_schedule_reload (void) +{ + need_reload = TRUE; +} + +static void +xdg_mime_reload (void *user_data) +{ + tree_magic_schedule_reload (); +} + +static void +tree_magic_shutdown (void) +{ + g_list_free_full (tree_matches, (GDestroyNotify) tree_match_free); + tree_matches = NULL; +} + +static void +tree_magic_init (void) +{ + static gboolean initialized = FALSE; + gsize i; + + if (!initialized) + { + initialized = TRUE; + + xdg_mime_register_reload_callback (xdg_mime_reload, NULL, NULL); + need_reload = TRUE; + } + + if (need_reload) + { + const char * const *dirs; + + need_reload = FALSE; + + tree_magic_shutdown (); + + dirs = g_content_type_get_mime_dirs (); + for (i = 0; dirs[i] != NULL; i++) + read_tree_magic_from_directory (dirs[i]); + } +} + +/* a filtering enumerator */ + +typedef struct +{ + gchar *path; + gint depth; + gboolean ignore_case; + gchar **components; + gchar **case_components; + GFileEnumerator **enumerators; + GFile **children; +} Enumerator; + +static gboolean +component_match (Enumerator *e, + gint depth, + const gchar *name) +{ + gchar *case_folded, *key; + gboolean found; + + if (strcmp (name, e->components[depth]) == 0) + return TRUE; + + if (!e->ignore_case) + return FALSE; + + case_folded = g_utf8_casefold (name, -1); + key = g_utf8_collate_key (case_folded, -1); + + found = strcmp (key, e->case_components[depth]) == 0; + + g_free (case_folded); + g_free (key); + + return found; +} + +static GFile * +next_match_recurse (Enumerator *e, + gint depth) +{ + GFile *file; + GFileInfo *info; + const gchar *name; + + while (TRUE) + { + if (e->enumerators[depth] == NULL) + { + if (depth > 0) + { + file = next_match_recurse (e, depth - 1); + if (file) + { + e->children[depth] = file; + e->enumerators[depth] = g_file_enumerate_children (file, + G_FILE_ATTRIBUTE_STANDARD_NAME, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); + } + } + if (e->enumerators[depth] == NULL) + return NULL; + } + + while ((info = g_file_enumerator_next_file (e->enumerators[depth], NULL, NULL))) + { + name = g_file_info_get_name (info); + if (component_match (e, depth, name)) + { + file = g_file_get_child (e->children[depth], name); + g_object_unref (info); + return file; + } + g_object_unref (info); + } + + g_object_unref (e->enumerators[depth]); + e->enumerators[depth] = NULL; + g_object_unref (e->children[depth]); + e->children[depth] = NULL; + } +} + +static GFile * +enumerator_next (Enumerator *e) +{ + return next_match_recurse (e, e->depth - 1); +} + +static Enumerator * +enumerator_new (GFile *root, + const char *path, + gboolean ignore_case) +{ + Enumerator *e; + gint i; + gchar *case_folded; + + e = g_new0 (Enumerator, 1); + e->path = g_strdup (path); + e->ignore_case = ignore_case; + + e->components = g_strsplit (e->path, G_DIR_SEPARATOR_S, -1); + e->depth = g_strv_length (e->components); + if (e->ignore_case) + { + e->case_components = g_new0 (char *, e->depth + 1); + for (i = 0; e->components[i]; i++) + { + case_folded = g_utf8_casefold (e->components[i], -1); + e->case_components[i] = g_utf8_collate_key (case_folded, -1); + g_free (case_folded); + } + } + + e->children = g_new0 (GFile *, e->depth); + e->children[0] = g_object_ref (root); + e->enumerators = g_new0 (GFileEnumerator *, e->depth); + e->enumerators[0] = g_file_enumerate_children (root, + G_FILE_ATTRIBUTE_STANDARD_NAME, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); + + return e; +} + +static void +enumerator_free (Enumerator *e) +{ + gint i; + + for (i = 0; i < e->depth; i++) + { + if (e->enumerators[i]) + g_object_unref (e->enumerators[i]); + if (e->children[i]) + g_object_unref (e->children[i]); + } + + g_free (e->enumerators); + g_free (e->children); + g_strfreev (e->components); + if (e->case_components) + g_strfreev (e->case_components); + g_free (e->path); + g_free (e); +} + +static gboolean +matchlet_match (TreeMatchlet *matchlet, + GFile *root) +{ + GFile *file; + GFileInfo *info; + gboolean result; + const gchar *attrs; + Enumerator *e; + GList *l; + + e = enumerator_new (root, matchlet->path, !matchlet->match_case); + + do + { + file = enumerator_next (e); + if (!file) + { + enumerator_free (e); + return FALSE; + } + + if (matchlet->mimetype) + attrs = G_FILE_ATTRIBUTE_STANDARD_TYPE "," + G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE "," + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE; + else + attrs = G_FILE_ATTRIBUTE_STANDARD_TYPE "," + G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE; + info = g_file_query_info (file, + attrs, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); + if (info) + { + result = TRUE; + + if (matchlet->type != G_FILE_TYPE_UNKNOWN && + g_file_info_get_file_type (info) != matchlet->type) + result = FALSE; + + if (matchlet->executable && + !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) + result = FALSE; + } + else + result = FALSE; + + if (result && matchlet->non_empty) + { + GFileEnumerator *child_enum; + GFileInfo *child_info; + + child_enum = g_file_enumerate_children (file, + G_FILE_ATTRIBUTE_STANDARD_NAME, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); + + if (child_enum) + { + child_info = g_file_enumerator_next_file (child_enum, NULL, NULL); + if (child_info) + g_object_unref (child_info); + else + result = FALSE; + g_object_unref (child_enum); + } + else + result = FALSE; + } + + if (result && matchlet->mimetype) + { + if (strcmp (matchlet->mimetype, g_file_info_get_content_type (info)) != 0) + result = FALSE; + } + + if (info) + g_object_unref (info); + g_object_unref (file); + } + while (!result); + + enumerator_free (e); + + if (!matchlet->matches) + return TRUE; + + for (l = matchlet->matches; l; l = l->next) + { + TreeMatchlet *submatchlet; + + submatchlet = l->data; + if (matchlet_match (submatchlet, root)) + return TRUE; + } + + return FALSE; +} + +static void +match_match (TreeMatch *match, + GFile *root, + GPtrArray *types) +{ + GList *l; + + for (l = match->matches; l; l = l->next) + { + TreeMatchlet *matchlet = l->data; + if (matchlet_match (matchlet, root)) + { + g_ptr_array_add (types, g_strdup (match->contenttype)); + break; + } + } +} + +/** + * g_content_type_guess_for_tree: + * @root: the root of the tree to guess a type for + * + * Tries to guess the type of the tree with root @root, by + * looking at the files it contains. The result is an array + * of content types, with the best guess coming first. + * + * The types returned all have the form x-content/foo, e.g. + * x-content/audio-cdda (for audio CDs) or x-content/image-dcf + * (for a camera memory card). See the + * [shared-mime-info](http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec) + * specification for more on x-content types. + * + * This function is useful in the implementation of + * g_mount_guess_content_type(). + * + * Returns: (transfer full) (array zero-terminated=1): an %NULL-terminated + * array of zero or more content types. Free with g_strfreev() + * + * Since: 2.18 + */ +gchar ** +g_content_type_guess_for_tree (GFile *root) +{ + GPtrArray *types; + GList *l; + + types = g_ptr_array_new (); + + G_LOCK (gio_treemagic); + + tree_magic_init (); + for (l = tree_matches; l; l = l->next) + { + TreeMatch *match = l->data; + match_match (match, root, types); + } + + G_UNLOCK (gio_treemagic); + + g_ptr_array_add (types, NULL); + + return (gchar **)g_ptr_array_free (types, FALSE); +}
diff --git a/gio/gcontenttype.h b/gio/gcontenttype.h new file mode 100644 index 0000000..db2c974 --- /dev/null +++ b/gio/gcontenttype.h
@@ -0,0 +1,82 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_CONTENT_TYPE_H__ +#define __G_CONTENT_TYPE_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +GLIB_AVAILABLE_IN_ALL +gboolean g_content_type_equals (const gchar *type1, + const gchar *type2); +GLIB_AVAILABLE_IN_ALL +gboolean g_content_type_is_a (const gchar *type, + const gchar *supertype); +GLIB_AVAILABLE_IN_2_52 +gboolean g_content_type_is_mime_type (const gchar *type, + const gchar *mime_type); +GLIB_AVAILABLE_IN_ALL +gboolean g_content_type_is_unknown (const gchar *type); +GLIB_AVAILABLE_IN_ALL +gchar * g_content_type_get_description (const gchar *type); +GLIB_AVAILABLE_IN_ALL +gchar * g_content_type_get_mime_type (const gchar *type); +GLIB_AVAILABLE_IN_ALL +GIcon * g_content_type_get_icon (const gchar *type); +GLIB_AVAILABLE_IN_2_34 +GIcon * g_content_type_get_symbolic_icon (const gchar *type); +GLIB_AVAILABLE_IN_2_34 +gchar * g_content_type_get_generic_icon_name (const gchar *type); + +GLIB_AVAILABLE_IN_ALL +gboolean g_content_type_can_be_executable (const gchar *type); + +GLIB_AVAILABLE_IN_ALL +gchar * g_content_type_from_mime_type (const gchar *mime_type); + +GLIB_AVAILABLE_IN_ALL +gchar * g_content_type_guess (const gchar *filename, + const guchar *data, + gsize data_size, + gboolean *result_uncertain); + +GLIB_AVAILABLE_IN_ALL +gchar ** g_content_type_guess_for_tree (GFile *root); + +GLIB_AVAILABLE_IN_ALL +GList * g_content_types_get_registered (void); + +/*< private >*/ +#ifndef __GTK_DOC_IGNORE__ +GLIB_AVAILABLE_IN_2_60 +const gchar * const *g_content_type_get_mime_dirs (void); +GLIB_AVAILABLE_IN_2_60 +void g_content_type_set_mime_dirs (const gchar * const *dirs); +#endif /* __GTK_DOC_IGNORE__ */ + +G_END_DECLS + +#endif /* __G_CONTENT_TYPE_H__ */
diff --git a/gio/gcontenttypeprivate.h b/gio/gcontenttypeprivate.h new file mode 100644 index 0000000..768a647 --- /dev/null +++ b/gio/gcontenttypeprivate.h
@@ -0,0 +1,34 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_CONTENT_TYPE_PRIVATE_H__ +#define __G_CONTENT_TYPE_PRIVATE_H__ + +#include "gcontenttype.h" + +G_BEGIN_DECLS + +gsize _g_unix_content_type_get_sniff_len (void); +char * _g_unix_content_type_unalias (const char *type); +char **_g_unix_content_type_get_parents (const char *type); + +G_END_DECLS + +#endif /* __G_CONTENT_TYPE_PRIVATE_H__ */
diff --git a/gio/gcontextspecificgroup.c b/gio/gcontextspecificgroup.c new file mode 100644 index 0000000..ffd1307 --- /dev/null +++ b/gio/gcontextspecificgroup.c
@@ -0,0 +1,273 @@ +/* + * Copyright © 2015 Canonical Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#include "config.h" + +#include "gcontextspecificgroup.h" + +#include <glib-object.h> +#include "glib-private.h" + +typedef struct +{ + GSource source; + + GMutex lock; + gpointer instance; + GQueue pending; +} GContextSpecificSource; + +static gboolean +g_context_specific_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + GContextSpecificSource *css = (GContextSpecificSource *) source; + guint signal_id; + + g_mutex_lock (&css->lock); + + g_assert (!g_queue_is_empty (&css->pending)); + signal_id = GPOINTER_TO_UINT (g_queue_pop_head (&css->pending)); + + if (g_queue_is_empty (&css->pending)) + g_source_set_ready_time (source, -1); + + g_mutex_unlock (&css->lock); + + g_signal_emit (css->instance, signal_id, 0); + + return TRUE; +} + +static void +g_context_specific_source_finalize (GSource *source) +{ + GContextSpecificSource *css = (GContextSpecificSource *) source; + + g_mutex_clear (&css->lock); + g_queue_clear (&css->pending); +} + +static GContextSpecificSource * +g_context_specific_source_new (const gchar *name, + gpointer instance) +{ + static GSourceFuncs source_funcs = { + NULL, + NULL, + g_context_specific_source_dispatch, + g_context_specific_source_finalize + }; + GContextSpecificSource *css; + GSource *source; + + source = g_source_new (&source_funcs, sizeof (GContextSpecificSource)); + css = (GContextSpecificSource *) source; + + g_source_set_name (source, name); + + g_mutex_init (&css->lock); + g_queue_init (&css->pending); + css->instance = instance; + + return css; +} + +static gboolean +g_context_specific_group_change_state (gpointer user_data) +{ + GContextSpecificGroup *group = user_data; + + g_mutex_lock (&group->lock); + + if (group->requested_state != group->effective_state) + { + (* group->requested_func) (); + + group->effective_state = group->requested_state; + group->requested_func = NULL; + + g_cond_broadcast (&group->cond); + } + + g_mutex_unlock (&group->lock); + + return FALSE; +} + +/* this is not the most elegant way to deal with this, but it's probably + * the best. there are only two other things we could do, really: + * + * - run the start function (but not the stop function) from the user's + * thread under some sort of lock. we don't run the stop function + * from the user's thread to avoid the destroy-while-emitting problem + * + * - have some check-and-compare functionality similar to what + * gsettings does where we send an artificial event in case we notice + * a change during the potential race period (using stat, for + * example) + */ +static void +g_context_specific_group_request_state (GContextSpecificGroup *group, + gboolean requested_state, + GCallback requested_func) +{ + if (requested_state != group->requested_state) + { + if (group->effective_state != group->requested_state) + { + /* abort the currently pending state transition */ + g_assert (group->effective_state == requested_state); + + group->requested_state = requested_state; + group->requested_func = NULL; + } + else + { + /* start a new state transition */ + group->requested_state = requested_state; + group->requested_func = requested_func; + + g_main_context_invoke (GLIB_PRIVATE_CALL(g_get_worker_context) (), + g_context_specific_group_change_state, group); + } + } + + /* we only block for positive transitions */ + if (requested_state) + { + while (group->requested_state != group->effective_state) + g_cond_wait (&group->cond, &group->lock); + + /* there is no way this could go back to FALSE because the object + * that we just created in this thread would have to have been + * destroyed again (from this thread) before that could happen. + */ + g_assert (group->effective_state); + } +} + +gpointer +g_context_specific_group_get (GContextSpecificGroup *group, + GType type, + goffset context_offset, + GCallback start_func) +{ + GContextSpecificSource *css; + GMainContext *context; + + context = g_main_context_get_thread_default (); + if (!context) + context = g_main_context_default (); + + g_mutex_lock (&group->lock); + + if (!group->table) + group->table = g_hash_table_new (NULL, NULL); + + css = g_hash_table_lookup (group->table, context); + + if (!css) + { + gpointer instance; + + instance = g_object_new (type, NULL); + css = g_context_specific_source_new (g_type_name (type), instance); + G_STRUCT_MEMBER (GMainContext *, instance, context_offset) = g_main_context_ref (context); + g_source_attach ((GSource *) css, context); + + g_hash_table_insert (group->table, context, css); + } + else + g_object_ref (css->instance); + + if (start_func) + g_context_specific_group_request_state (group, TRUE, start_func); + + g_mutex_unlock (&group->lock); + + return css->instance; +} + +void +g_context_specific_group_remove (GContextSpecificGroup *group, + GMainContext *context, + gpointer instance, + GCallback stop_func) +{ + GContextSpecificSource *css; + + if (!context) + { + g_critical ("Removing %s with NULL context. This object was probably directly constructed from a " + "dynamic language. This is not a valid use of the API.", G_OBJECT_TYPE_NAME (instance)); + return; + } + + g_mutex_lock (&group->lock); + css = g_hash_table_lookup (group->table, context); + g_hash_table_remove (group->table, context); + g_assert (css); + + /* stop only if we were the last one */ + if (stop_func && g_hash_table_size (group->table) == 0) + g_context_specific_group_request_state (group, FALSE, stop_func); + + g_mutex_unlock (&group->lock); + + g_assert (css->instance == instance); + + g_source_destroy ((GSource *) css); + g_source_unref ((GSource *) css); + g_main_context_unref (context); +} + +void +g_context_specific_group_emit (GContextSpecificGroup *group, + guint signal_id) +{ + g_mutex_lock (&group->lock); + + if (group->table) + { + GHashTableIter iter; + gpointer value; + gpointer ptr; + + ptr = GUINT_TO_POINTER (signal_id); + + g_hash_table_iter_init (&iter, group->table); + while (g_hash_table_iter_next (&iter, NULL, &value)) + { + GContextSpecificSource *css = value; + + g_mutex_lock (&css->lock); + + g_queue_remove (&css->pending, ptr); + g_queue_push_tail (&css->pending, ptr); + + g_source_set_ready_time ((GSource *) css, 0); + + g_mutex_unlock (&css->lock); + } + } + + g_mutex_unlock (&group->lock); +}
diff --git a/gio/gcontextspecificgroup.h b/gio/gcontextspecificgroup.h new file mode 100644 index 0000000..74d22a4 --- /dev/null +++ b/gio/gcontextspecificgroup.h
@@ -0,0 +1,51 @@ +/* + * Copyright © 2015 Canonical Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_CONTEXT_SPECIFIC_GROUP_H__ +#define __G_CONTEXT_SPECIFIC_GROUP_H__ + +#include <glib-object.h> + +typedef struct +{ + GHashTable *table; + GMutex lock; + GCond cond; + gboolean requested_state; + GCallback requested_func; + gboolean effective_state; +} GContextSpecificGroup; + +gpointer +g_context_specific_group_get (GContextSpecificGroup *group, + GType type, + goffset context_offset, + GCallback start_func); + +void +g_context_specific_group_remove (GContextSpecificGroup *group, + GMainContext *context, + gpointer instance, + GCallback stop_func); + +void +g_context_specific_group_emit (GContextSpecificGroup *group, + guint signal_id); + +#endif /* __G_CONTEXT_SPECIFIC_GROUP_H__ */
diff --git a/gio/gconverter.c b/gio/gconverter.c new file mode 100644 index 0000000..7e5d308 --- /dev/null +++ b/gio/gconverter.c
@@ -0,0 +1,201 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" +#include "gconverter.h" +#include "glibintl.h" + + +/** + * SECTION:gconverter + * @short_description: Data conversion interface + * @include: gio/gio.h + * @see_also: #GInputStream, #GOutputStream + * + * #GConverter is implemented by objects that convert + * binary data in various ways. The conversion can be + * stateful and may fail at any place. + * + * Some example conversions are: character set conversion, + * compression, decompression and regular expression + * replace. + * + * Since: 2.24 + **/ + + +typedef GConverterIface GConverterInterface; +G_DEFINE_INTERFACE (GConverter, g_converter, G_TYPE_OBJECT) + +static void +g_converter_default_init (GConverterInterface *iface) +{ +} + +/** + * g_converter_convert: + * @converter: a #GConverter. + * @inbuf: (array length=inbuf_size) (element-type guint8): the buffer + * containing the data to convert. + * @inbuf_size: the number of bytes in @inbuf + * @outbuf: (element-type guint8) (array length=outbuf_size): a buffer to write + * converted data in. + * @outbuf_size: the number of bytes in @outbuf, must be at least one + * @flags: a #GConverterFlags controlling the conversion details + * @bytes_read: (out): will be set to the number of bytes read from @inbuf on success + * @bytes_written: (out): will be set to the number of bytes written to @outbuf on success + * @error: location to store the error occurring, or %NULL to ignore + * + * This is the main operation used when converting data. It is to be called + * multiple times in a loop, and each time it will do some work, i.e. + * producing some output (in @outbuf) or consuming some input (from @inbuf) or + * both. If its not possible to do any work an error is returned. + * + * Note that a single call may not consume all input (or any input at all). + * Also a call may produce output even if given no input, due to state stored + * in the converter producing output. + * + * If any data was either produced or consumed, and then an error happens, then + * only the successful conversion is reported and the error is returned on the + * next call. + * + * A full conversion loop involves calling this method repeatedly, each time + * giving it new input and space output space. When there is no more input + * data after the data in @inbuf, the flag %G_CONVERTER_INPUT_AT_END must be set. + * The loop will be (unless some error happens) returning %G_CONVERTER_CONVERTED + * each time until all data is consumed and all output is produced, then + * %G_CONVERTER_FINISHED is returned instead. Note, that %G_CONVERTER_FINISHED + * may be returned even if %G_CONVERTER_INPUT_AT_END is not set, for instance + * in a decompression converter where the end of data is detectable from the + * data (and there might even be other data after the end of the compressed data). + * + * When some data has successfully been converted @bytes_read and is set to + * the number of bytes read from @inbuf, and @bytes_written is set to indicate + * how many bytes was written to @outbuf. If there are more data to output + * or consume (i.e. unless the %G_CONVERTER_INPUT_AT_END is specified) then + * %G_CONVERTER_CONVERTED is returned, and if no more data is to be output + * then %G_CONVERTER_FINISHED is returned. + * + * On error %G_CONVERTER_ERROR is returned and @error is set accordingly. + * Some errors need special handling: + * + * %G_IO_ERROR_NO_SPACE is returned if there is not enough space + * to write the resulting converted data, the application should + * call the function again with a larger @outbuf to continue. + * + * %G_IO_ERROR_PARTIAL_INPUT is returned if there is not enough + * input to fully determine what the conversion should produce, + * and the %G_CONVERTER_INPUT_AT_END flag is not set. This happens for + * example with an incomplete multibyte sequence when converting text, + * or when a regexp matches up to the end of the input (and may match + * further input). It may also happen when @inbuf_size is zero and + * there is no more data to produce. + * + * When this happens the application should read more input and then + * call the function again. If further input shows that there is no + * more data call the function again with the same data but with + * the %G_CONVERTER_INPUT_AT_END flag set. This may cause the conversion + * to finish as e.g. in the regexp match case (or, to fail again with + * %G_IO_ERROR_PARTIAL_INPUT in e.g. a charset conversion where the + * input is actually partial). + * + * After g_converter_convert() has returned %G_CONVERTER_FINISHED the + * converter object is in an invalid state where its not allowed + * to call g_converter_convert() anymore. At this time you can only + * free the object or call g_converter_reset() to reset it to the + * initial state. + * + * If the flag %G_CONVERTER_FLUSH is set then conversion is modified + * to try to write out all internal state to the output. The application + * has to call the function multiple times with the flag set, and when + * the available input has been consumed and all internal state has + * been produced then %G_CONVERTER_FLUSHED (or %G_CONVERTER_FINISHED if + * really at the end) is returned instead of %G_CONVERTER_CONVERTED. + * This is somewhat similar to what happens at the end of the input stream, + * but done in the middle of the data. + * + * This has different meanings for different conversions. For instance + * in a compression converter it would mean that we flush all the + * compression state into output such that if you uncompress the + * compressed data you get back all the input data. Doing this may + * make the final file larger due to padding though. Another example + * is a regexp conversion, where if you at the end of the flushed data + * have a match, but there is also a potential longer match. In the + * non-flushed case we would ask for more input, but when flushing we + * treat this as the end of input and do the match. + * + * Flushing is not always possible (like if a charset converter flushes + * at a partial multibyte sequence). Converters are supposed to try + * to produce as much output as possible and then return an error + * (typically %G_IO_ERROR_PARTIAL_INPUT). + * + * Returns: a #GConverterResult, %G_CONVERTER_ERROR on error. + * + * Since: 2.24 + **/ +GConverterResult +g_converter_convert (GConverter *converter, + const void *inbuf, + gsize inbuf_size, + void *outbuf, + gsize outbuf_size, + GConverterFlags flags, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + GConverterIface *iface; + + g_return_val_if_fail (G_IS_CONVERTER (converter), G_CONVERTER_ERROR); + g_return_val_if_fail (outbuf_size > 0, G_CONVERTER_ERROR); + + *bytes_read = 0; + *bytes_written = 0; + + iface = G_CONVERTER_GET_IFACE (converter); + + return (* iface->convert) (converter, + inbuf, inbuf_size, + outbuf, outbuf_size, + flags, + bytes_read, bytes_written, error); +} + +/** + * g_converter_reset: + * @converter: a #GConverter. + * + * Resets all internal state in the converter, making it behave + * as if it was just created. If the converter has any internal + * state that would produce output then that output is lost. + * + * Since: 2.24 + **/ +void +g_converter_reset (GConverter *converter) +{ + GConverterIface *iface; + + g_return_if_fail (G_IS_CONVERTER (converter)); + + iface = G_CONVERTER_GET_IFACE (converter); + + (* iface->reset) (converter); +}
diff --git a/gio/gconverter.h b/gio/gconverter.h new file mode 100644 index 0000000..8716453 --- /dev/null +++ b/gio/gconverter.h
@@ -0,0 +1,96 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_CONVERTER_H__ +#define __G_CONVERTER_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_CONVERTER (g_converter_get_type ()) +#define G_CONVERTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_CONVERTER, GConverter)) +#define G_IS_CONVERTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_CONVERTER)) +#define G_CONVERTER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_CONVERTER, GConverterIface)) + +/** + * GConverter: + * + * Seek object for streaming operations. + * + * Since: 2.24 + **/ +typedef struct _GConverterIface GConverterIface; + +/** + * GConverterIface: + * @g_iface: The parent interface. + * @convert: Converts data. + * @reset: Reverts the internal state of the converter to its initial state. + * + * Provides an interface for converting data from one type + * to another type. The conversion can be stateful + * and may fail at any place. + * + * Since: 2.24 + **/ +struct _GConverterIface +{ + GTypeInterface g_iface; + + /* Virtual Table */ + + GConverterResult (* convert) (GConverter *converter, + const void *inbuf, + gsize inbuf_size, + void *outbuf, + gsize outbuf_size, + GConverterFlags flags, + gsize *bytes_read, + gsize *bytes_written, + GError **error); + void (* reset) (GConverter *converter); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_converter_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +GConverterResult g_converter_convert (GConverter *converter, + const void *inbuf, + gsize inbuf_size, + void *outbuf, + gsize outbuf_size, + GConverterFlags flags, + gsize *bytes_read, + gsize *bytes_written, + GError **error); +GLIB_AVAILABLE_IN_ALL +void g_converter_reset (GConverter *converter); + + +G_END_DECLS + + +#endif /* __G_CONVERTER_H__ */
diff --git a/gio/gconverterinputstream.c b/gio/gconverterinputstream.c new file mode 100644 index 0000000..dd84b34 --- /dev/null +++ b/gio/gconverterinputstream.c
@@ -0,0 +1,651 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" + +#include <string.h> + +#include "gconverterinputstream.h" +#include "gpollableinputstream.h" +#include "gcancellable.h" +#include "gioenumtypes.h" +#include "gioerror.h" +#include "glibintl.h" + + +/** + * SECTION:gconverterinputstream + * @short_description: Converter Input Stream + * @include: gio/gio.h + * @see_also: #GInputStream, #GConverter + * + * Converter input stream implements #GInputStream and allows + * conversion of data of various types during reading. + * + * As of GLib 2.34, #GConverterInputStream implements + * #GPollableInputStream. + **/ + +#define INITIAL_BUFFER_SIZE 4096 + +typedef struct { + char *data; + gsize start; + gsize end; + gsize size; +} Buffer; + +struct _GConverterInputStreamPrivate { + gboolean at_input_end; + gboolean finished; + gboolean need_input; + GConverter *converter; + Buffer input_buffer; + Buffer converted_buffer; +}; + +enum { + PROP_0, + PROP_CONVERTER +}; + +static void g_converter_input_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void g_converter_input_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void g_converter_input_stream_finalize (GObject *object); +static gssize g_converter_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error); + +static gboolean g_converter_input_stream_can_poll (GPollableInputStream *stream); +static gboolean g_converter_input_stream_is_readable (GPollableInputStream *stream); +static gssize g_converter_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize size, + GError **error); + +static GSource *g_converter_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable); + +static void g_converter_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GConverterInputStream, + g_converter_input_stream, + G_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (GConverterInputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + g_converter_input_stream_pollable_iface_init)) + +static void +g_converter_input_stream_class_init (GConverterInputStreamClass *klass) +{ + GObjectClass *object_class; + GInputStreamClass *istream_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->get_property = g_converter_input_stream_get_property; + object_class->set_property = g_converter_input_stream_set_property; + object_class->finalize = g_converter_input_stream_finalize; + + istream_class = G_INPUT_STREAM_CLASS (klass); + istream_class->read_fn = g_converter_input_stream_read; + + g_object_class_install_property (object_class, + PROP_CONVERTER, + g_param_spec_object ("converter", + P_("Converter"), + P_("The converter object"), + G_TYPE_CONVERTER, + G_PARAM_READWRITE| + G_PARAM_CONSTRUCT_ONLY| + G_PARAM_STATIC_STRINGS)); + +} + +static void +g_converter_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface) +{ + iface->can_poll = g_converter_input_stream_can_poll; + iface->is_readable = g_converter_input_stream_is_readable; + iface->read_nonblocking = g_converter_input_stream_read_nonblocking; + iface->create_source = g_converter_input_stream_create_source; +} + +static void +g_converter_input_stream_finalize (GObject *object) +{ + GConverterInputStreamPrivate *priv; + GConverterInputStream *stream; + + stream = G_CONVERTER_INPUT_STREAM (object); + priv = stream->priv; + + g_free (priv->input_buffer.data); + g_free (priv->converted_buffer.data); + if (priv->converter) + g_object_unref (priv->converter); + + G_OBJECT_CLASS (g_converter_input_stream_parent_class)->finalize (object); +} + +static void +g_converter_input_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GConverterInputStream *cstream; + + cstream = G_CONVERTER_INPUT_STREAM (object); + + switch (prop_id) + { + case PROP_CONVERTER: + cstream->priv->converter = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +g_converter_input_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GConverterInputStreamPrivate *priv; + GConverterInputStream *cstream; + + cstream = G_CONVERTER_INPUT_STREAM (object); + priv = cstream->priv; + + switch (prop_id) + { + case PROP_CONVERTER: + g_value_set_object (value, priv->converter); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} +static void +g_converter_input_stream_init (GConverterInputStream *stream) +{ + stream->priv = g_converter_input_stream_get_instance_private (stream); +} + +/** + * g_converter_input_stream_new: + * @base_stream: a #GInputStream + * @converter: a #GConverter + * + * Creates a new converter input stream for the @base_stream. + * + * Returns: a new #GInputStream. + **/ +GInputStream * +g_converter_input_stream_new (GInputStream *base_stream, + GConverter *converter) +{ + GInputStream *stream; + + g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL); + + stream = g_object_new (G_TYPE_CONVERTER_INPUT_STREAM, + "base-stream", base_stream, + "converter", converter, + NULL); + + return stream; +} + +static gsize +buffer_data_size (Buffer *buffer) +{ + return buffer->end - buffer->start; +} + +static gsize +buffer_tailspace (Buffer *buffer) +{ + return buffer->size - buffer->end; +} + +static char * +buffer_data (Buffer *buffer) +{ + return buffer->data + buffer->start; +} + +static void +buffer_consumed (Buffer *buffer, + gsize count) +{ + buffer->start += count; + if (buffer->start == buffer->end) + buffer->start = buffer->end = 0; +} + +static void +buffer_read (Buffer *buffer, + char *dest, + gsize count) +{ + if (count != 0) + memcpy (dest, buffer->data + buffer->start, count); + + buffer_consumed (buffer, count); +} + +static void +compact_buffer (Buffer *buffer) +{ + gsize in_buffer; + + in_buffer = buffer_data_size (buffer); + memmove (buffer->data, + buffer->data + buffer->start, + in_buffer); + buffer->end -= buffer->start; + buffer->start = 0; +} + +static void +grow_buffer (Buffer *buffer) +{ + char *data; + gsize size, in_buffer; + + if (buffer->size == 0) + size = INITIAL_BUFFER_SIZE; + else + size = buffer->size * 2; + + data = g_malloc (size); + in_buffer = buffer_data_size (buffer); + + if (in_buffer != 0) + memcpy (data, + buffer->data + buffer->start, + in_buffer); + + g_free (buffer->data); + buffer->data = data; + buffer->end -= buffer->start; + buffer->start = 0; + buffer->size = size; +} + +/* Ensures that the buffer can fit at_least_size bytes, + * *including* the current in-buffer data */ +static void +buffer_ensure_space (Buffer *buffer, + gsize at_least_size) +{ + gsize in_buffer, left_to_fill; + + in_buffer = buffer_data_size (buffer); + + if (in_buffer >= at_least_size) + return; + + left_to_fill = buffer_tailspace (buffer); + + if (in_buffer + left_to_fill >= at_least_size) + { + /* We fit in remaining space at end */ + /* If the copy is small, compact now anyway so we can fill more */ + if (in_buffer < 256) + compact_buffer (buffer); + } + else if (buffer->size >= at_least_size) + { + /* We fit, but only if we compact */ + compact_buffer (buffer); + } + else + { + /* Need to grow buffer */ + while (buffer->size < at_least_size) + grow_buffer (buffer); + } +} + +static gssize +fill_input_buffer (GConverterInputStream *stream, + gsize at_least_size, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + GConverterInputStreamPrivate *priv; + GInputStream *base_stream; + gssize nread; + + priv = stream->priv; + + buffer_ensure_space (&priv->input_buffer, at_least_size); + + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + nread = g_pollable_stream_read (base_stream, + priv->input_buffer.data + priv->input_buffer.end, + buffer_tailspace (&priv->input_buffer), + blocking, + cancellable, + error); + + if (nread > 0) + { + priv->input_buffer.end += nread; + priv->need_input = FALSE; + } + + return nread; +} + + +static gssize +read_internal (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + GConverterInputStream *cstream; + GConverterInputStreamPrivate *priv; + gsize available, total_bytes_read; + gssize nread; + GConverterResult res; + gsize bytes_read; + gsize bytes_written; + GError *my_error; + GError *my_error2; + + cstream = G_CONVERTER_INPUT_STREAM (stream); + priv = cstream->priv; + + available = buffer_data_size (&priv->converted_buffer); + + if (available > 0 && + count <= available) + { + /* Converted data available, return that */ + buffer_read (&priv->converted_buffer, buffer, count); + return count; + } + + /* Full request not available, read all currently available and request + refill/conversion for more */ + + buffer_read (&priv->converted_buffer, buffer, available); + + total_bytes_read = available; + buffer = (char *) buffer + available; + count -= available; + + /* If there is no data to convert, and no pre-converted data, + do some i/o for more input */ + if (buffer_data_size (&priv->input_buffer) == 0 && + total_bytes_read == 0 && + !priv->at_input_end) + { + nread = fill_input_buffer (cstream, count, blocking, cancellable, error); + if (nread < 0) + return -1; + if (nread == 0) + priv->at_input_end = TRUE; + } + + /* First try to convert any available data (or state) directly to the user buffer: */ + if (!priv->finished) + { + my_error = NULL; + res = g_converter_convert (priv->converter, + buffer_data (&priv->input_buffer), + buffer_data_size (&priv->input_buffer), + buffer, count, + priv->at_input_end ? G_CONVERTER_INPUT_AT_END : 0, + &bytes_read, + &bytes_written, + &my_error); + if (res != G_CONVERTER_ERROR) + { + total_bytes_read += bytes_written; + buffer_consumed (&priv->input_buffer, bytes_read); + if (res == G_CONVERTER_FINISHED) + priv->finished = TRUE; /* We're done converting */ + } + else if (total_bytes_read == 0 && + !g_error_matches (my_error, + G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT) && + !g_error_matches (my_error, + G_IO_ERROR, + G_IO_ERROR_NO_SPACE)) + { + /* No previously read data and no "special" error, return error */ + g_propagate_error (error, my_error); + return -1; + } + else + g_error_free (my_error); + } + + /* We had some pre-converted data and/or we converted directly to the + user buffer */ + if (total_bytes_read > 0) + return total_bytes_read; + + /* If there is no more to convert, return EOF */ + if (priv->finished) + { + g_assert (buffer_data_size (&priv->converted_buffer) == 0); + return 0; + } + + /* There was "complexity" in the straight-to-buffer conversion, + * convert to our own buffer and write from that. + * At this point we didn't produce any data into @buffer. + */ + + /* Ensure we have *some* initial target space */ + buffer_ensure_space (&priv->converted_buffer, count); + + while (TRUE) + { + g_assert (!priv->finished); + + /* Try to convert to our buffer */ + my_error = NULL; + res = g_converter_convert (priv->converter, + buffer_data (&priv->input_buffer), + buffer_data_size (&priv->input_buffer), + buffer_data (&priv->converted_buffer), + buffer_tailspace (&priv->converted_buffer), + priv->at_input_end ? G_CONVERTER_INPUT_AT_END : 0, + &bytes_read, + &bytes_written, + &my_error); + if (res != G_CONVERTER_ERROR) + { + priv->converted_buffer.end += bytes_written; + buffer_consumed (&priv->input_buffer, bytes_read); + + /* Maybe we consumed without producing any output */ + if (buffer_data_size (&priv->converted_buffer) == 0 && res != G_CONVERTER_FINISHED) + continue; /* Convert more */ + + if (res == G_CONVERTER_FINISHED) + priv->finished = TRUE; + + total_bytes_read = MIN (count, buffer_data_size (&priv->converted_buffer)); + buffer_read (&priv->converted_buffer, buffer, total_bytes_read); + + g_assert (priv->finished || total_bytes_read > 0); + + return total_bytes_read; + } + + /* There was some kind of error filling our buffer */ + + if (g_error_matches (my_error, + G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT) && + !priv->at_input_end) + { + /* Need more data */ + my_error2 = NULL; + nread = fill_input_buffer (cstream, + buffer_data_size (&priv->input_buffer) + 4096, + blocking, + cancellable, + &my_error2); + if (nread < 0) + { + /* Can't read any more data, return that error */ + g_error_free (my_error); + g_propagate_error (error, my_error2); + priv->need_input = TRUE; + return -1; + } + else if (nread == 0) + { + /* End of file, try INPUT_AT_END */ + priv->at_input_end = TRUE; + } + g_error_free (my_error); + continue; + } + + if (g_error_matches (my_error, + G_IO_ERROR, + G_IO_ERROR_NO_SPACE)) + { + /* Need more destination space, grow it + * Note: if we actually grow the buffer (as opposed to compacting it), + * this will double the size, not just add one byte. */ + buffer_ensure_space (&priv->converted_buffer, + priv->converted_buffer.size + 1); + g_error_free (my_error); + continue; + } + + /* Any other random error, return it */ + g_propagate_error (error, my_error); + return -1; + } + + g_assert_not_reached (); +} + +static gssize +g_converter_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return read_internal (stream, buffer, count, TRUE, cancellable, error); +} + +static gboolean +g_converter_input_stream_can_poll (GPollableInputStream *stream) +{ + GInputStream *base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + + return (G_IS_POLLABLE_INPUT_STREAM (base_stream) && + g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (base_stream))); +} + +static gboolean +g_converter_input_stream_is_readable (GPollableInputStream *stream) +{ + GInputStream *base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + GConverterInputStream *cstream = G_CONVERTER_INPUT_STREAM (stream); + + if (buffer_data_size (&cstream->priv->converted_buffer)) + return TRUE; + else if (buffer_data_size (&cstream->priv->input_buffer) && + !cstream->priv->need_input) + return TRUE; + else + return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (base_stream)); +} + +static gssize +g_converter_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + return read_internal (G_INPUT_STREAM (stream), buffer, count, + FALSE, NULL, error); +} + +static GSource * +g_converter_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + GInputStream *base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + GSource *base_source, *pollable_source; + + if (g_pollable_input_stream_is_readable (stream)) + base_source = g_timeout_source_new (0); + else + base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (base_stream), NULL); + + pollable_source = g_pollable_source_new_full (stream, base_source, + cancellable); + g_source_unref (base_source); + + return pollable_source; +} + + +/** + * g_converter_input_stream_get_converter: + * @converter_stream: a #GConverterInputStream + * + * Gets the #GConverter that is used by @converter_stream. + * + * Returns: (transfer none): the converter of the converter input stream + * + * Since: 2.24 + */ +GConverter * +g_converter_input_stream_get_converter (GConverterInputStream *converter_stream) +{ + return converter_stream->priv->converter; +}
diff --git a/gio/gconverterinputstream.h b/gio/gconverterinputstream.h new file mode 100644 index 0000000..48cc102 --- /dev/null +++ b/gio/gconverterinputstream.h
@@ -0,0 +1,80 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_CONVERTER_INPUT_STREAM_H__ +#define __G_CONVERTER_INPUT_STREAM_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/gfilterinputstream.h> +#include <gio/gconverter.h> + +G_BEGIN_DECLS + +#define G_TYPE_CONVERTER_INPUT_STREAM (g_converter_input_stream_get_type ()) +#define G_CONVERTER_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_CONVERTER_INPUT_STREAM, GConverterInputStream)) +#define G_CONVERTER_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_CONVERTER_INPUT_STREAM, GConverterInputStreamClass)) +#define G_IS_CONVERTER_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_CONVERTER_INPUT_STREAM)) +#define G_IS_CONVERTER_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_CONVERTER_INPUT_STREAM)) +#define G_CONVERTER_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_CONVERTER_INPUT_STREAM, GConverterInputStreamClass)) + +/** + * GConverterInputStream: + * + * An implementation of #GFilterInputStream that allows data + * conversion. + **/ +typedef struct _GConverterInputStreamClass GConverterInputStreamClass; +typedef struct _GConverterInputStreamPrivate GConverterInputStreamPrivate; + +struct _GConverterInputStream +{ + GFilterInputStream parent_instance; + + /*< private >*/ + GConverterInputStreamPrivate *priv; +}; + +struct _GConverterInputStreamClass +{ + GFilterInputStreamClass parent_class; + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); + void (*_g_reserved5) (void); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_converter_input_stream_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_ALL +GInputStream *g_converter_input_stream_new (GInputStream *base_stream, + GConverter *converter); +GLIB_AVAILABLE_IN_ALL +GConverter *g_converter_input_stream_get_converter (GConverterInputStream *converter_stream); + +G_END_DECLS + +#endif /* __G_CONVERTER_INPUT_STREAM_H__ */
diff --git a/gio/gconverteroutputstream.c b/gio/gconverteroutputstream.c new file mode 100644 index 0000000..c1fa29e --- /dev/null +++ b/gio/gconverteroutputstream.c
@@ -0,0 +1,689 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" + +#include <string.h> + +#include "gconverteroutputstream.h" +#include "gpollableoutputstream.h" +#include "gcancellable.h" +#include "gioenumtypes.h" +#include "gioerror.h" +#include "glibintl.h" + + +/** + * SECTION:gconverteroutputstream + * @short_description: Converter Output Stream + * @include: gio/gio.h + * @see_also: #GOutputStream, #GConverter + * + * Converter output stream implements #GOutputStream and allows + * conversion of data of various types during reading. + * + * As of GLib 2.34, #GConverterOutputStream implements + * #GPollableOutputStream. + **/ + +#define INITIAL_BUFFER_SIZE 4096 + +typedef struct { + char *data; + gsize start; + gsize end; + gsize size; +} Buffer; + +struct _GConverterOutputStreamPrivate { + gboolean at_output_end; + gboolean finished; + GConverter *converter; + Buffer output_buffer; /* To be converted and written */ + Buffer converted_buffer; /* Already converted */ +}; + +/* Buffering strategy: + * + * Each time we write we must at least consume some input, or + * return an error. Thus we start with writing all already + * converted data and *then* we start converting (reporting + * an error at any point in this). + * + * Its possible that what the user wrote is not enough data + * for the converter, so we must then buffer it in output_buffer + * and ask for more data, but we want to avoid this as much as + * possible, converting directly from the users buffer. + */ + +enum { + PROP_0, + PROP_CONVERTER +}; + +static void g_converter_output_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void g_converter_output_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void g_converter_output_stream_finalize (GObject *object); +static gssize g_converter_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error); +static gboolean g_converter_output_stream_flush (GOutputStream *stream, + GCancellable *cancellable, + GError **error); + +static gboolean g_converter_output_stream_can_poll (GPollableOutputStream *stream); +static gboolean g_converter_output_stream_is_writable (GPollableOutputStream *stream); +static gssize g_converter_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize size, + GError **error); + +static GSource *g_converter_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable); + +static void g_converter_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GConverterOutputStream, + g_converter_output_stream, + G_TYPE_FILTER_OUTPUT_STREAM, + G_ADD_PRIVATE (GConverterOutputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, + g_converter_output_stream_pollable_iface_init)) + +static void +g_converter_output_stream_class_init (GConverterOutputStreamClass *klass) +{ + GObjectClass *object_class; + GOutputStreamClass *istream_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->get_property = g_converter_output_stream_get_property; + object_class->set_property = g_converter_output_stream_set_property; + object_class->finalize = g_converter_output_stream_finalize; + + istream_class = G_OUTPUT_STREAM_CLASS (klass); + istream_class->write_fn = g_converter_output_stream_write; + istream_class->flush = g_converter_output_stream_flush; + + g_object_class_install_property (object_class, + PROP_CONVERTER, + g_param_spec_object ("converter", + P_("Converter"), + P_("The converter object"), + G_TYPE_CONVERTER, + G_PARAM_READWRITE| + G_PARAM_CONSTRUCT_ONLY| + G_PARAM_STATIC_STRINGS)); + +} + +static void +g_converter_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface) +{ + iface->can_poll = g_converter_output_stream_can_poll; + iface->is_writable = g_converter_output_stream_is_writable; + iface->write_nonblocking = g_converter_output_stream_write_nonblocking; + iface->create_source = g_converter_output_stream_create_source; +} + +static void +g_converter_output_stream_finalize (GObject *object) +{ + GConverterOutputStreamPrivate *priv; + GConverterOutputStream *stream; + + stream = G_CONVERTER_OUTPUT_STREAM (object); + priv = stream->priv; + + g_free (priv->output_buffer.data); + g_free (priv->converted_buffer.data); + if (priv->converter) + g_object_unref (priv->converter); + + G_OBJECT_CLASS (g_converter_output_stream_parent_class)->finalize (object); +} + +static void +g_converter_output_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GConverterOutputStream *cstream; + + cstream = G_CONVERTER_OUTPUT_STREAM (object); + + switch (prop_id) + { + case PROP_CONVERTER: + cstream->priv->converter = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +g_converter_output_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GConverterOutputStreamPrivate *priv; + GConverterOutputStream *cstream; + + cstream = G_CONVERTER_OUTPUT_STREAM (object); + priv = cstream->priv; + + switch (prop_id) + { + case PROP_CONVERTER: + g_value_set_object (value, priv->converter); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_converter_output_stream_init (GConverterOutputStream *stream) +{ + stream->priv = g_converter_output_stream_get_instance_private (stream); +} + +/** + * g_converter_output_stream_new: + * @base_stream: a #GOutputStream + * @converter: a #GConverter + * + * Creates a new converter output stream for the @base_stream. + * + * Returns: a new #GOutputStream. + **/ +GOutputStream * +g_converter_output_stream_new (GOutputStream *base_stream, + GConverter *converter) +{ + GOutputStream *stream; + + g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL); + + stream = g_object_new (G_TYPE_CONVERTER_OUTPUT_STREAM, + "base-stream", base_stream, + "converter", converter, + NULL); + + return stream; +} + +static gsize +buffer_data_size (Buffer *buffer) +{ + return buffer->end - buffer->start; +} + +static gsize +buffer_tailspace (Buffer *buffer) +{ + return buffer->size - buffer->end; +} + +static char * +buffer_data (Buffer *buffer) +{ + return buffer->data + buffer->start; +} + +static void +buffer_consumed (Buffer *buffer, + gsize count) +{ + buffer->start += count; + if (buffer->start == buffer->end) + buffer->start = buffer->end = 0; +} + +static void +compact_buffer (Buffer *buffer) +{ + gsize in_buffer; + + in_buffer = buffer_data_size (buffer); + memmove (buffer->data, + buffer->data + buffer->start, + in_buffer); + buffer->end -= buffer->start; + buffer->start = 0; +} + +static void +grow_buffer (Buffer *buffer) +{ + char *data; + gsize size, in_buffer; + + if (buffer->size == 0) + size = INITIAL_BUFFER_SIZE; + else + size = buffer->size * 2; + + data = g_malloc (size); + in_buffer = buffer_data_size (buffer); + + if (in_buffer != 0) + memcpy (data, + buffer->data + buffer->start, + in_buffer); + + g_free (buffer->data); + buffer->data = data; + buffer->end -= buffer->start; + buffer->start = 0; + buffer->size = size; +} + +/* Ensures that the buffer can fit at_least_size bytes, + * *including* the current in-buffer data */ +static void +buffer_ensure_space (Buffer *buffer, + gsize at_least_size) +{ + gsize in_buffer, left_to_fill; + + in_buffer = buffer_data_size (buffer); + + if (in_buffer >= at_least_size) + return; + + left_to_fill = buffer_tailspace (buffer); + + if (in_buffer + left_to_fill >= at_least_size) + { + /* We fit in remaining space at end */ + /* If the copy is small, compact now anyway so we can fill more */ + if (in_buffer < 256) + compact_buffer (buffer); + } + else if (buffer->size >= at_least_size) + { + /* We fit, but only if we compact */ + compact_buffer (buffer); + } + else + { + /* Need to grow buffer */ + while (buffer->size < at_least_size) + grow_buffer (buffer); + } +} + +static void +buffer_append (Buffer *buffer, + const char *data, + gsize data_size) +{ + buffer_ensure_space (buffer, + buffer_data_size (buffer) + data_size); + memcpy (buffer->data + buffer->end, data, data_size); + buffer->end += data_size; +} + + +static gboolean +flush_buffer (GConverterOutputStream *stream, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + GConverterOutputStreamPrivate *priv; + GOutputStream *base_stream; + gsize nwritten; + gsize available; + gboolean res; + + priv = stream->priv; + + base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + + available = buffer_data_size (&priv->converted_buffer); + if (available > 0) + { + res = g_pollable_stream_write_all (base_stream, + buffer_data (&priv->converted_buffer), + available, + blocking, + &nwritten, + cancellable, + error); + buffer_consumed (&priv->converted_buffer, nwritten); + return res; + } + return TRUE; +} + + +static gssize +write_internal (GOutputStream *stream, + const void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + GConverterOutputStream *cstream; + GConverterOutputStreamPrivate *priv; + gssize retval; + GConverterResult res; + gsize bytes_read; + gsize bytes_written; + GError *my_error; + const char *to_convert; + gsize to_convert_size, converted_bytes; + gboolean converting_from_buffer; + + cstream = G_CONVERTER_OUTPUT_STREAM (stream); + priv = cstream->priv; + + /* Write out all available pre-converted data and fail if + not possible */ + if (!flush_buffer (cstream, blocking, cancellable, error)) + return -1; + + if (priv->finished) + return 0; + + /* Convert as much as possible */ + if (buffer_data_size (&priv->output_buffer) > 0) + { + converting_from_buffer = TRUE; + buffer_append (&priv->output_buffer, buffer, count); + to_convert = buffer_data (&priv->output_buffer); + to_convert_size = buffer_data_size (&priv->output_buffer); + } + else + { + converting_from_buffer = FALSE; + to_convert = buffer; + to_convert_size = count; + } + + /* Ensure we have *some* initial target space */ + buffer_ensure_space (&priv->converted_buffer, to_convert_size); + + converted_bytes = 0; + while (!priv->finished && converted_bytes < to_convert_size) + { + /* Ensure we have *some* target space */ + if (buffer_tailspace (&priv->converted_buffer) == 0) + grow_buffer (&priv->converted_buffer); + + /* Try to convert to our buffer */ + my_error = NULL; + res = g_converter_convert (priv->converter, + to_convert + converted_bytes, + to_convert_size - converted_bytes, + buffer_data (&priv->converted_buffer) + buffer_data_size (&priv->converted_buffer), + buffer_tailspace (&priv->converted_buffer), + 0, + &bytes_read, + &bytes_written, + &my_error); + + if (res != G_CONVERTER_ERROR) + { + priv->converted_buffer.end += bytes_written; + converted_bytes += bytes_read; + + if (res == G_CONVERTER_FINISHED) + priv->finished = TRUE; + } + else + { + /* No-space errors can be handled locally: */ + if (g_error_matches (my_error, + G_IO_ERROR, + G_IO_ERROR_NO_SPACE)) + { + /* Need more destination space, grow it + * Note: if we actually grow the buffer (as opposed to compacting it), + * this will double the size, not just add one byte. */ + buffer_ensure_space (&priv->converted_buffer, + priv->converted_buffer.size + 1); + g_error_free (my_error); + continue; + } + + if (converted_bytes > 0) + { + /* We got a conversion error, but we did convert some bytes before + that, so handle those before reporting the error */ + g_error_free (my_error); + break; + } + + if (g_error_matches (my_error, + G_IO_ERROR, + G_IO_ERROR_PARTIAL_INPUT)) + { + /* Consume everything to buffer that we append to next time + we write */ + if (!converting_from_buffer) + buffer_append (&priv->output_buffer, buffer, count); + /* in the converting_from_buffer case we already appended this */ + + g_error_free (my_error); + return count; /* consume everything */ + } + + /* Converted no data and got a normal error, return it */ + g_propagate_error (error, my_error); + return -1; + } + } + + if (converting_from_buffer) + { + buffer_consumed (&priv->output_buffer, converted_bytes); + retval = count; + } + else + retval = converted_bytes; + + /* We now successfully consumed retval bytes, so we can't return an error, + even if writing this to the base stream fails. If it does we'll just + stop early and report this error when we try again on the next + write call. */ + flush_buffer (cstream, blocking, cancellable, NULL); + + return retval; +} + +static gssize +g_converter_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return write_internal (stream, buffer, count, TRUE, cancellable, error); +} + +static gboolean +g_converter_output_stream_flush (GOutputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GConverterOutputStream *cstream; + GConverterOutputStreamPrivate *priv; + GConverterResult res; + GError *my_error; + gboolean is_closing; + gboolean flushed; + gsize bytes_read; + gsize bytes_written; + + cstream = G_CONVERTER_OUTPUT_STREAM (stream); + priv = cstream->priv; + + is_closing = g_output_stream_is_closing (stream); + + /* Write out all available pre-converted data and fail if + not possible */ + if (!flush_buffer (cstream, TRUE, cancellable, error)) + return FALSE; + + /* Ensure we have *some* initial target space */ + buffer_ensure_space (&priv->converted_buffer, 1); + + /* Convert whole buffer */ + flushed = FALSE; + while (!priv->finished && !flushed) + { + /* Ensure we have *some* target space */ + if (buffer_tailspace (&priv->converted_buffer) == 0) + grow_buffer (&priv->converted_buffer); + + /* Try to convert to our buffer */ + my_error = NULL; + res = g_converter_convert (priv->converter, + buffer_data (&priv->output_buffer), + buffer_data_size (&priv->output_buffer), + buffer_data (&priv->converted_buffer) + buffer_data_size (&priv->converted_buffer), + buffer_tailspace (&priv->converted_buffer), + is_closing ? G_CONVERTER_INPUT_AT_END : G_CONVERTER_FLUSH, + &bytes_read, + &bytes_written, + &my_error); + + if (res != G_CONVERTER_ERROR) + { + priv->converted_buffer.end += bytes_written; + buffer_consumed (&priv->output_buffer, bytes_read); + + if (res == G_CONVERTER_FINISHED) + priv->finished = TRUE; + if (!is_closing && + res == G_CONVERTER_FLUSHED) + { + /* Should not have returned FLUSHED with input left */ + g_assert (buffer_data_size (&priv->output_buffer) == 0); + flushed = TRUE; + } + } + else + { + /* No-space errors can be handled locally: */ + if (g_error_matches (my_error, + G_IO_ERROR, + G_IO_ERROR_NO_SPACE)) + { + /* Need more destination space, grow it + * Note: if we actually grow the buffer (as opposed to compacting it), + * this will double the size, not just add one byte. */ + buffer_ensure_space (&priv->converted_buffer, + priv->converted_buffer.size + 1); + g_error_free (my_error); + continue; + } + + /* Any other error, including PARTIAL_INPUT can't be fixed by now + and is an error */ + g_propagate_error (error, my_error); + return FALSE; + } + } + + /* Now write all converted data to base stream */ + if (!flush_buffer (cstream, TRUE, cancellable, error)) + return FALSE; + + return TRUE; +} + +static gboolean +g_converter_output_stream_can_poll (GPollableOutputStream *stream) +{ + GOutputStream *base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + + return (G_IS_POLLABLE_OUTPUT_STREAM (base_stream) && + g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (base_stream))); +} + +static gboolean +g_converter_output_stream_is_writable (GPollableOutputStream *stream) +{ + GOutputStream *base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + + return g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (base_stream)); +} + +static gssize +g_converter_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize count, + GError **error) +{ + return write_internal (G_OUTPUT_STREAM (stream), buffer, count, FALSE, + NULL, error); +} + +static GSource * +g_converter_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable) +{ + GOutputStream *base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + GSource *base_source, *pollable_source; + + base_source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (base_stream), NULL); + pollable_source = g_pollable_source_new_full (stream, base_source, + cancellable); + g_source_unref (base_source); + + return pollable_source; +} + +/** + * g_converter_output_stream_get_converter: + * @converter_stream: a #GConverterOutputStream + * + * Gets the #GConverter that is used by @converter_stream. + * + * Returns: (transfer none): the converter of the converter output stream + * + * Since: 2.24 + */ +GConverter * +g_converter_output_stream_get_converter (GConverterOutputStream *converter_stream) +{ + return converter_stream->priv->converter; +}
diff --git a/gio/gconverteroutputstream.h b/gio/gconverteroutputstream.h new file mode 100644 index 0000000..b9a1e5d --- /dev/null +++ b/gio/gconverteroutputstream.h
@@ -0,0 +1,80 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2009 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_CONVERTER_OUTPUT_STREAM_H__ +#define __G_CONVERTER_OUTPUT_STREAM_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/gfilteroutputstream.h> +#include <gio/gconverter.h> + +G_BEGIN_DECLS + +#define G_TYPE_CONVERTER_OUTPUT_STREAM (g_converter_output_stream_get_type ()) +#define G_CONVERTER_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_CONVERTER_OUTPUT_STREAM, GConverterOutputStream)) +#define G_CONVERTER_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_CONVERTER_OUTPUT_STREAM, GConverterOutputStreamClass)) +#define G_IS_CONVERTER_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_CONVERTER_OUTPUT_STREAM)) +#define G_IS_CONVERTER_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_CONVERTER_OUTPUT_STREAM)) +#define G_CONVERTER_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_CONVERTER_OUTPUT_STREAM, GConverterOutputStreamClass)) + +/** + * GConverterOutputStream: + * + * An implementation of #GFilterOutputStream that allows data + * conversion. + **/ +typedef struct _GConverterOutputStreamClass GConverterOutputStreamClass; +typedef struct _GConverterOutputStreamPrivate GConverterOutputStreamPrivate; + +struct _GConverterOutputStream +{ + GFilterOutputStream parent_instance; + + /*< private >*/ + GConverterOutputStreamPrivate *priv; +}; + +struct _GConverterOutputStreamClass +{ + GFilterOutputStreamClass parent_class; + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); + void (*_g_reserved5) (void); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_converter_output_stream_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_ALL +GOutputStream *g_converter_output_stream_new (GOutputStream *base_stream, + GConverter *converter); +GLIB_AVAILABLE_IN_ALL +GConverter *g_converter_output_stream_get_converter (GConverterOutputStream *converter_stream); + +G_END_DECLS + +#endif /* __G_CONVERTER_OUTPUT_STREAM_H__ */
diff --git a/gio/gcredentials.c b/gio/gcredentials.c new file mode 100644 index 0000000..146829e --- /dev/null +++ b/gio/gcredentials.c
@@ -0,0 +1,674 @@ +/* GDBus - GLib D-Bus Library + * + * Copyright (C) 2008-2010 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> + +#include <gobject/gvaluecollector.h> + +#include "gcredentials.h" +#include "gcredentialsprivate.h" +#include "gnetworking.h" +#include "gioerror.h" +#include "gioenumtypes.h" + +#include "glibintl.h" + +/** + * SECTION:gcredentials + * @short_description: An object containing credentials + * @include: gio/gio.h + * + * The #GCredentials type is a reference-counted wrapper for native + * credentials. This information is typically used for identifying, + * authenticating and authorizing other processes. + * + * Some operating systems supports looking up the credentials of the + * remote peer of a communication endpoint - see e.g. + * g_socket_get_credentials(). + * + * Some operating systems supports securely sending and receiving + * credentials over a Unix Domain Socket, see + * #GUnixCredentialsMessage, g_unix_connection_send_credentials() and + * g_unix_connection_receive_credentials() for details. + * + * On Linux, the native credential type is a `struct ucred` - see the + * unix(7) man page for details. This corresponds to + * %G_CREDENTIALS_TYPE_LINUX_UCRED. + * + * On Apple operating systems (including iOS, tvOS, and macOS), + * the native credential type is a `struct xucred`. + * This corresponds to %G_CREDENTIALS_TYPE_APPLE_XUCRED. + * + * On FreeBSD, Debian GNU/kFreeBSD, and GNU/Hurd, the native + * credential type is a `struct cmsgcred`. This corresponds + * to %G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED. + * + * On NetBSD, the native credential type is a `struct unpcbid`. + * This corresponds to %G_CREDENTIALS_TYPE_NETBSD_UNPCBID. + * + * On OpenBSD, the native credential type is a `struct sockpeercred`. + * This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED. + * + * On Solaris (including OpenSolaris and its derivatives), the native + * credential type is a `ucred_t`. This corresponds to + * %G_CREDENTIALS_TYPE_SOLARIS_UCRED. + */ + +/** + * GCredentials: + * + * The #GCredentials structure contains only private data and + * should only be accessed using the provided API. + * + * Since: 2.26 + */ +struct _GCredentials +{ + /*< private >*/ + GObject parent_instance; + +#if G_CREDENTIALS_USE_LINUX_UCRED + struct ucred native; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + struct xucred native; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + struct cmsgcred native; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + struct unpcbid native; +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + struct sockpeercred native; +#elif G_CREDENTIALS_USE_SOLARIS_UCRED + ucred_t *native; +#else + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic warning "-Wcpp" + #warning Please add GCredentials support for your OS + #pragma GCC diagnostic pop + #endif +#endif +}; + +/** + * GCredentialsClass: + * + * Class structure for #GCredentials. + * + * Since: 2.26 + */ +struct _GCredentialsClass +{ + /*< private >*/ + GObjectClass parent_class; +}; + +G_DEFINE_TYPE (GCredentials, g_credentials, G_TYPE_OBJECT) + +static void +g_credentials_finalize (GObject *object) +{ +#if G_CREDENTIALS_USE_SOLARIS_UCRED + GCredentials *credentials = G_CREDENTIALS (object); + + ucred_free (credentials->native); +#endif + + if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL) + G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object); +} + + +static void +g_credentials_class_init (GCredentialsClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = g_credentials_finalize; +} + +static void +g_credentials_init (GCredentials *credentials) +{ +#if G_CREDENTIALS_USE_LINUX_UCRED + credentials->native.pid = getpid (); + credentials->native.uid = geteuid (); + credentials->native.gid = getegid (); +#elif G_CREDENTIALS_USE_APPLE_XUCRED + gsize i; + + credentials->native.cr_version = XUCRED_VERSION; + credentials->native.cr_uid = geteuid (); + credentials->native.cr_ngroups = 1; + credentials->native.cr_groups[0] = getegid (); + + /* FIXME: In principle this could use getgroups() to fill in the rest + * of cr_groups, but then we'd have to handle the case where a process + * can have more than NGROUPS groups, if that's even possible. A macOS + * user would have to develop and test this. + * + * For now we fill it with -1 (meaning "no data"). */ + for (i = 1; i < NGROUPS; i++) + credentials->native.cr_groups[i] = -1; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + memset (&credentials->native, 0, sizeof (struct cmsgcred)); + credentials->native.cmcred_pid = getpid (); + credentials->native.cmcred_euid = geteuid (); + credentials->native.cmcred_gid = getegid (); +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + credentials->native.unp_pid = getpid (); + credentials->native.unp_euid = geteuid (); + credentials->native.unp_egid = getegid (); +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + credentials->native.pid = getpid (); + credentials->native.uid = geteuid (); + credentials->native.gid = getegid (); +#elif G_CREDENTIALS_USE_SOLARIS_UCRED + credentials->native = ucred_get (P_MYID); +#endif +} + +/* ---------------------------------------------------------------------------------------------------- */ + +/** + * g_credentials_new: + * + * Creates a new #GCredentials object with credentials matching the + * the current process. + * + * Returns: A #GCredentials. Free with g_object_unref(). + * + * Since: 2.26 + */ +GCredentials * +g_credentials_new (void) +{ + return g_object_new (G_TYPE_CREDENTIALS, NULL); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +/** + * g_credentials_to_string: + * @credentials: A #GCredentials object. + * + * Creates a human-readable textual representation of @credentials + * that can be used in logging and debug messages. The format of the + * returned string may change in future GLib release. + * + * Returns: A string that should be freed with g_free(). + * + * Since: 2.26 + */ +gchar * +g_credentials_to_string (GCredentials *credentials) +{ + GString *ret; +#if G_CREDENTIALS_USE_APPLE_XUCRED + __typeof__(credentials->native.cr_ngroups) i; +#endif + + g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL); + + ret = g_string_new ("GCredentials:"); +#if G_CREDENTIALS_USE_LINUX_UCRED + g_string_append (ret, "linux-ucred:"); + if (credentials->native.pid != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid); + if (credentials->native.uid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid); + if (credentials->native.gid != -1) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid); + if (ret->str[ret->len - 1] == ',') + ret->str[ret->len - 1] = '\0'; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + g_string_append (ret, "apple-xucred:"); + g_string_append_printf (ret, "version=%u,", credentials->native.cr_version); + if (credentials->native.cr_uid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cr_uid); + for (i = 0; i < credentials->native.cr_ngroups; i++) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cr_groups[i]); + if (ret->str[ret->len - 1] == ',') + ret->str[ret->len - 1] = '\0'; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + g_string_append (ret, "freebsd-cmsgcred:"); + if (credentials->native.cmcred_pid != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_pid); + if (credentials->native.cmcred_euid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_euid); + if (credentials->native.cmcred_gid != -1) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_gid); +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + g_string_append (ret, "netbsd-unpcbid:"); + if (credentials->native.unp_pid != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_pid); + if (credentials->native.unp_euid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_euid); + if (credentials->native.unp_egid != -1) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_egid); + ret->str[ret->len - 1] = '\0'; +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + g_string_append (ret, "openbsd-sockpeercred:"); + if (credentials->native.pid != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid); + if (credentials->native.uid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid); + if (credentials->native.gid != -1) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid); + if (ret->str[ret->len - 1] == ',') + ret->str[ret->len - 1] = '\0'; +#elif G_CREDENTIALS_USE_SOLARIS_UCRED + g_string_append (ret, "solaris-ucred:"); + { + id_t id; + if ((id = ucred_getpid (credentials->native)) != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) id); + if ((id = ucred_geteuid (credentials->native)) != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) id); + if ((id = ucred_getegid (credentials->native)) != -1) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) id); + if (ret->str[ret->len - 1] == ',') + ret->str[ret->len - 1] = '\0'; + } +#else + g_string_append (ret, "unknown"); +#endif + + return g_string_free (ret, FALSE); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +#if G_CREDENTIALS_USE_LINUX_UCRED +/* + * Check whether @native contains invalid data. If getsockopt SO_PEERCRED + * is used on a TCP socket, it succeeds but yields a credentials structure + * with pid 0, uid -1 and gid -1. Similarly, if SO_PASSCRED is used on a + * receiving Unix socket when the sending socket did not also enable + * SO_PASSCRED, it can succeed but yield a credentials structure with + * pid 0, uid /proc/sys/kernel/overflowuid and gid + * /proc/sys/kernel/overflowgid. + */ +static gboolean +linux_ucred_check_valid (struct ucred *native, + GError **error) +{ + if (native->pid == 0 + || native->uid == -1 + || native->gid == -1) + { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + _("GCredentials contains invalid data")); + return FALSE; + } + + return TRUE; +} +#endif + +/** + * g_credentials_is_same_user: + * @credentials: A #GCredentials. + * @other_credentials: A #GCredentials. + * @error: Return location for error or %NULL. + * + * Checks if @credentials and @other_credentials is the same user. + * + * This operation can fail if #GCredentials is not supported on the + * the OS. + * + * Returns: %TRUE if @credentials and @other_credentials has the same + * user, %FALSE otherwise or if @error is set. + * + * Since: 2.26 + */ +gboolean +g_credentials_is_same_user (GCredentials *credentials, + GCredentials *other_credentials, + GError **error) +{ + gboolean ret; + + g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE); + g_return_val_if_fail (G_IS_CREDENTIALS (other_credentials), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + ret = FALSE; +#if G_CREDENTIALS_USE_LINUX_UCRED + if (linux_ucred_check_valid (&credentials->native, NULL) + && credentials->native.uid == other_credentials->native.uid) + ret = TRUE; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + if (credentials->native.cr_version == other_credentials->native.cr_version && + credentials->native.cr_uid == other_credentials->native.cr_uid) + ret = TRUE; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid) + ret = TRUE; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + if (credentials->native.unp_euid == other_credentials->native.unp_euid) + ret = TRUE; +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + if (credentials->native.uid == other_credentials->native.uid) + ret = TRUE; +#elif G_CREDENTIALS_USE_SOLARIS_UCRED + if (ucred_geteuid (credentials->native) == ucred_geteuid (other_credentials->native)) + ret = TRUE; +#else + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("GCredentials is not implemented on this OS")); +#endif + + return ret; +} + +static gboolean +credentials_native_type_check (GCredentialsType requested_type, + const char *op) +{ + GEnumClass *enum_class; + GEnumValue *requested; +#if G_CREDENTIALS_SUPPORTED + GEnumValue *supported; +#endif + +#if G_CREDENTIALS_SUPPORTED + if (requested_type == G_CREDENTIALS_NATIVE_TYPE) + return TRUE; +#endif + + enum_class = g_type_class_ref (g_credentials_type_get_type ()); + requested = g_enum_get_value (enum_class, requested_type); + +#if G_CREDENTIALS_SUPPORTED + supported = g_enum_get_value (enum_class, G_CREDENTIALS_NATIVE_TYPE); + g_assert (supported); + g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s " + "but only %s is supported on this platform.", + op, op, + requested ? requested->value_name : "(unknown)", + supported->value_name); +#else + g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s " + "but there is no support for GCredentials on this platform.", + op, op, + requested ? requested->value_name : "(unknown)"); +#endif + + g_type_class_unref (enum_class); + return FALSE; +} + +/** + * g_credentials_get_native: (skip) + * @credentials: A #GCredentials. + * @native_type: The type of native credentials to get. + * + * Gets a pointer to native credentials of type @native_type from + * @credentials. + * + * It is a programming error (which will cause a warning to be + * logged) to use this method if there is no #GCredentials support for + * the OS or if @native_type isn't supported by the OS. + * + * Returns: The pointer to native credentials or %NULL if the + * operation there is no #GCredentials support for the OS or if + * @native_type isn't supported by the OS. Do not free the returned + * data, it is owned by @credentials. + * + * Since: 2.26 + */ +gpointer +g_credentials_get_native (GCredentials *credentials, + GCredentialsType native_type) +{ + g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL); + + if (!credentials_native_type_check (native_type, "get")) + return NULL; + +#if G_CREDENTIALS_USE_SOLARIS_UCRED + return credentials->native; +#elif G_CREDENTIALS_SUPPORTED + return &credentials->native; +#else + g_assert_not_reached (); +#endif +} + +/** + * g_credentials_set_native: + * @credentials: A #GCredentials. + * @native_type: The type of native credentials to set. + * @native: (not nullable): A pointer to native credentials. + * + * Copies the native credentials of type @native_type from @native + * into @credentials. + * + * It is a programming error (which will cause a warning to be + * logged) to use this method if there is no #GCredentials support for + * the OS or if @native_type isn't supported by the OS. + * + * Since: 2.26 + */ +void +g_credentials_set_native (GCredentials *credentials, + GCredentialsType native_type, + gpointer native) +{ + if (!credentials_native_type_check (native_type, "set")) + return; + +#if G_CREDENTIALS_USE_SOLARIS_UCRED + memcpy (credentials->native, native, ucred_size ()); +#elif G_CREDENTIALS_SUPPORTED + memcpy (&credentials->native, native, sizeof (credentials->native)); +#else + g_assert_not_reached (); +#endif +} + +/* ---------------------------------------------------------------------------------------------------- */ + +#ifdef G_OS_UNIX +/** + * g_credentials_get_unix_user: + * @credentials: A #GCredentials + * @error: Return location for error or %NULL. + * + * Tries to get the UNIX user identifier from @credentials. This + * method is only available on UNIX platforms. + * + * This operation can fail if #GCredentials is not supported on the + * OS or if the native credentials type does not contain information + * about the UNIX user. + * + * Returns: The UNIX user identifier or -1 if @error is set. + * + * Since: 2.26 + */ +uid_t +g_credentials_get_unix_user (GCredentials *credentials, + GError **error) +{ + uid_t ret; + + g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1); + g_return_val_if_fail (error == NULL || *error == NULL, -1); + +#if G_CREDENTIALS_USE_LINUX_UCRED + if (linux_ucred_check_valid (&credentials->native, error)) + ret = credentials->native.uid; + else + ret = -1; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + if (credentials->native.cr_version == XUCRED_VERSION) + { + ret = credentials->native.cr_uid; + } + else + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + /* No point in translating the part in parentheses... */ + "%s (struct xucred cr_version %u != %u)", + _("There is no GCredentials support for your platform"), + credentials->native.cr_version, + XUCRED_VERSION); + ret = -1; + } +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + ret = credentials->native.cmcred_euid; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + ret = credentials->native.unp_euid; +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + ret = credentials->native.uid; +#elif G_CREDENTIALS_USE_SOLARIS_UCRED + ret = ucred_geteuid (credentials->native); +#else + ret = -1; + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("There is no GCredentials support for your platform")); +#endif + + return ret; +} + +/** + * g_credentials_get_unix_pid: + * @credentials: A #GCredentials + * @error: Return location for error or %NULL. + * + * Tries to get the UNIX process identifier from @credentials. This + * method is only available on UNIX platforms. + * + * This operation can fail if #GCredentials is not supported on the + * OS or if the native credentials type does not contain information + * about the UNIX process ID (for example this is the case for + * %G_CREDENTIALS_TYPE_APPLE_XUCRED). + * + * Returns: The UNIX process ID, or -1 if @error is set. + * + * Since: 2.36 + */ +pid_t +g_credentials_get_unix_pid (GCredentials *credentials, + GError **error) +{ + pid_t ret; + + g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1); + g_return_val_if_fail (error == NULL || *error == NULL, -1); + +#if G_CREDENTIALS_USE_LINUX_UCRED + if (linux_ucred_check_valid (&credentials->native, error)) + ret = credentials->native.pid; + else + ret = -1; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + ret = credentials->native.cmcred_pid; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + ret = credentials->native.unp_pid; +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + ret = credentials->native.pid; +#elif G_CREDENTIALS_USE_SOLARIS_UCRED + ret = ucred_getpid (credentials->native); +#else + /* this case includes G_CREDENTIALS_USE_APPLE_XUCRED */ + ret = -1; + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("GCredentials does not contain a process ID on this OS")); +#endif + + return ret; +} + +/** + * g_credentials_set_unix_user: + * @credentials: A #GCredentials. + * @uid: The UNIX user identifier to set. + * @error: Return location for error or %NULL. + * + * Tries to set the UNIX user identifier on @credentials. This method + * is only available on UNIX platforms. + * + * This operation can fail if #GCredentials is not supported on the + * OS or if the native credentials type does not contain information + * about the UNIX user. It can also fail if the OS does not allow the + * use of "spoofed" credentials. + * + * Returns: %TRUE if @uid was set, %FALSE if error is set. + * + * Since: 2.26 + */ +gboolean +g_credentials_set_unix_user (GCredentials *credentials, + uid_t uid, + GError **error) +{ + gboolean ret = FALSE; + + g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE); + g_return_val_if_fail (uid != -1, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + +#if G_CREDENTIALS_USE_LINUX_UCRED + credentials->native.uid = uid; + ret = TRUE; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + credentials->native.cr_uid = uid; + ret = TRUE; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + credentials->native.cmcred_euid = uid; + ret = TRUE; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + credentials->native.unp_euid = uid; + ret = TRUE; +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + credentials->native.uid = uid; + ret = TRUE; +#elif !G_CREDENTIALS_SPOOFING_SUPPORTED + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_PERMISSION_DENIED, + _("Credentials spoofing is not possible on this OS")); + ret = FALSE; +#else + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("GCredentials is not implemented on this OS")); + ret = FALSE; +#endif + + return ret; +} + +#endif /* G_OS_UNIX */
diff --git a/gio/gcredentials.h b/gio/gcredentials.h new file mode 100644 index 0000000..25cebf2 --- /dev/null +++ b/gio/gcredentials.h
@@ -0,0 +1,85 @@ +/* GDBus - GLib D-Bus Library + * + * Copyright (C) 2008-2010 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifndef __G_CREDENTIALS_H__ +#define __G_CREDENTIALS_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +#ifdef G_OS_UNIX +/* To get the uid_t type */ +#include <unistd.h> +#include <sys/types.h> +#endif + +G_BEGIN_DECLS + +#define G_TYPE_CREDENTIALS (g_credentials_get_type ()) +#define G_CREDENTIALS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_CREDENTIALS, GCredentials)) +#define G_CREDENTIALS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_CREDENTIALS, GCredentialsClass)) +#define G_CREDENTIALS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_CREDENTIALS, GCredentialsClass)) +#define G_IS_CREDENTIALS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_CREDENTIALS)) +#define G_IS_CREDENTIALS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_CREDENTIALS)) + +typedef struct _GCredentialsClass GCredentialsClass; + +GLIB_AVAILABLE_IN_ALL +GType g_credentials_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_ALL +GCredentials *g_credentials_new (void); + +GLIB_AVAILABLE_IN_ALL +gchar *g_credentials_to_string (GCredentials *credentials); + +GLIB_AVAILABLE_IN_ALL +gpointer g_credentials_get_native (GCredentials *credentials, + GCredentialsType native_type); + +GLIB_AVAILABLE_IN_ALL +void g_credentials_set_native (GCredentials *credentials, + GCredentialsType native_type, + gpointer native); + +GLIB_AVAILABLE_IN_ALL +gboolean g_credentials_is_same_user (GCredentials *credentials, + GCredentials *other_credentials, + GError **error); + +#ifdef G_OS_UNIX +GLIB_AVAILABLE_IN_2_36 +pid_t g_credentials_get_unix_pid (GCredentials *credentials, + GError **error); +GLIB_AVAILABLE_IN_ALL +uid_t g_credentials_get_unix_user (GCredentials *credentials, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_credentials_set_unix_user (GCredentials *credentials, + uid_t uid, + GError **error); +#endif + +G_END_DECLS + +#endif /* __G_DBUS_PROXY_H__ */
diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h new file mode 100644 index 0000000..13d3bf3 --- /dev/null +++ b/gio/gcredentialsprivate.h
@@ -0,0 +1,173 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2013 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef __G_CREDENTIALS_PRIVATE_H__ +#define __G_CREDENTIALS_PRIVATE_H__ + +#include "gio/gcredentials.h" +#include "gio/gnetworking.h" + +/* + * G_CREDENTIALS_SUPPORTED: + * + * Defined to 1 if GCredentials works. + */ +#undef G_CREDENTIALS_SUPPORTED + +/* + * G_CREDENTIALS_USE_LINUX_UCRED, etc.: + * + * Defined to 1 if GCredentials uses Linux `struct ucred`, etc. + */ +#undef G_CREDENTIALS_USE_LINUX_UCRED +#undef G_CREDENTIALS_USE_FREEBSD_CMSGCRED +#undef G_CREDENTIALS_USE_NETBSD_UNPCBID +#undef G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED +#undef G_CREDENTIALS_USE_SOLARIS_UCRED +#undef G_CREDENTIALS_USE_APPLE_XUCRED + +/* + * G_CREDENTIALS_NATIVE_TYPE: + * + * Defined to one of G_CREDENTIALS_TYPE_LINUX_UCRED, etc. + */ +#undef G_CREDENTIALS_NATIVE_TYPE + +/* + * G_CREDENTIALS_NATIVE_SIZE: + * + * Defined to the size of the %G_CREDENTIALS_NATIVE_TYPE + */ +#undef G_CREDENTIALS_NATIVE_SIZE + +/* + * G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED: + * + * Defined to 1 if we have a message-passing API in which credentials + * are attached to a particular message, such as `SCM_CREDENTIALS` on Linux + * or `SCM_CREDS` on FreeBSD. + */ +#undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED + +/* + * G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED: + * + * Defined to 1 if we have a `getsockopt()`-style API in which one end of + * a socket connection can directly query the credentials of the process + * that initiated the other end, such as `getsockopt SO_PEERCRED` on Linux + * or `getpeereid()` on multiple operating systems. + */ +#undef G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED + +/* + * G_CREDENTIALS_SPOOFING_SUPPORTED: + * + * Defined to 1 if privileged processes can spoof their credentials when + * using the message-passing API. + */ +#undef G_CREDENTIALS_SPOOFING_SUPPORTED + +/* + * G_CREDENTIALS_PREFER_MESSAGE_PASSING: + * + * Defined to 1 if the data structure transferred by the message-passing + * API is strictly more informative than the one transferred by the + * `getsockopt()`-style API, and hence should be preferred, even for + * protocols like D-Bus that are defined in terms of the credentials of + * the (process that opened the) socket, as opposed to the credentials + * of an individual message. + */ +#undef G_CREDENTIALS_PREFER_MESSAGE_PASSING + +/* + * G_CREDENTIALS_HAS_PID: + * + * Defined to 1 if the %G_CREDENTIALS_NATIVE_TYPE contains the process ID. + */ +#undef G_CREDENTIALS_HAS_PID + +#ifdef __linux__ +#define G_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_USE_LINUX_UCRED 1 +#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_LINUX_UCRED +#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct ucred)) +#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 +#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 1 + +#elif defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) /* Debian GNU/kFreeBSD */ || \ + defined(__GNU__) /* GNU Hurd */ || \ + defined(__DragonFly__) /* DragonFly BSD */ +#define G_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_USE_FREEBSD_CMSGCRED 1 +#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED +#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct cmsgcred)) +#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 +#define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +/* GLib doesn't implement it yet, but FreeBSD's getsockopt()-style API + * is getpeereid(), which is not as informative as struct cmsgcred - + * it does not tell us the PID. As a result, libdbus prefers to use + * SCM_CREDS, and if we implement getpeereid() in future, we should + * do the same. */ +#define G_CREDENTIALS_PREFER_MESSAGE_PASSING 1 +#define G_CREDENTIALS_HAS_PID 1 + +#elif defined(__NetBSD__) +#define G_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_USE_NETBSD_UNPCBID 1 +#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_NETBSD_UNPCBID +#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct unpcbid)) +/* #undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED */ +#define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 1 + +#elif defined(__OpenBSD__) +#define G_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED 1 +#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED +#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct sockpeercred)) +#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 1 + +#elif defined(__sun__) || defined(__illumos__) || defined (__OpenSolaris_kernel__) +#include <ucred.h> +#define G_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_USE_SOLARIS_UCRED 1 +#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_SOLARIS_UCRED +#define G_CREDENTIALS_NATIVE_SIZE (ucred_size ()) +#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 +#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 1 + +#elif defined(__APPLE__) +#include <sys/ucred.h> +#define G_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_USE_APPLE_XUCRED 1 +#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_APPLE_XUCRED +#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct xucred)) +#undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED +#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 0 + +#endif + +#endif /* __G_CREDENTIALS_PRIVATE_H__ */
diff --git a/gio/gdatagrambased.c b/gio/gdatagrambased.c new file mode 100644 index 0000000..1e1c051 --- /dev/null +++ b/gio/gdatagrambased.c
@@ -0,0 +1,474 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2015 Collabora Ltd. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Philip Withnall <philip.withnall@collabora.co.uk> + */ + +#include "config.h" + +#include "gdatagrambased.h" + +#include "gcancellable.h" +#include "gioenumtypes.h" +#include "gioerror.h" +#include "gnetworkingprivate.h" +#include "gsocketaddress.h" +#include "glibintl.h" + +/** + * SECTION:gdatagrambased + * @short_description: Low-level datagram communications interface + * @include: gio/gio.h + * @see_also: #GSocket, [<gnetworking.h>][gio-gnetworking.h] + * + * A #GDatagramBased is a networking interface for representing datagram-based + * communications. It is a more or less direct mapping of the core parts of the + * BSD socket API in a portable GObject interface. It is implemented by + * #GSocket, which wraps the UNIX socket API on UNIX and winsock2 on Windows. + * + * #GDatagramBased is entirely platform independent, and is intended to be used + * alongside higher-level networking APIs such as #GIOStream. + * + * It uses vectored scatter/gather I/O by default, allowing for many messages + * to be sent or received in a single call. Where possible, implementations of + * the interface should take advantage of vectored I/O to minimise processing + * or system calls. For example, #GSocket uses recvmmsg() and sendmmsg() where + * possible. Callers should take advantage of scatter/gather I/O (the use of + * multiple buffers per message) to avoid unnecessary copying of data to + * assemble or disassemble a message. + * + * Each #GDatagramBased operation has a timeout parameter which may be negative + * for blocking behaviour, zero for non-blocking behaviour, or positive for + * timeout behaviour. A blocking operation blocks until finished or there is an + * error. A non-blocking operation will return immediately with a + * %G_IO_ERROR_WOULD_BLOCK error if it cannot make progress. A timeout operation + * will block until the operation is complete or the timeout expires; if the + * timeout expires it will return what progress it made, or + * %G_IO_ERROR_TIMED_OUT if no progress was made. To know when a call would + * successfully run you can call g_datagram_based_condition_check() or + * g_datagram_based_condition_wait(). You can also use + * g_datagram_based_create_source() and attach it to a #GMainContext to get + * callbacks when I/O is possible. + * + * When running a non-blocking operation applications should always be able to + * handle getting a %G_IO_ERROR_WOULD_BLOCK error even when some other function + * said that I/O was possible. This can easily happen in case of a race + * condition in the application, but it can also happen for other reasons. For + * instance, on Windows a socket is always seen as writable until a write + * returns %G_IO_ERROR_WOULD_BLOCK. + * + * As with #GSocket, #GDatagramBaseds can be either connection oriented (for + * example, SCTP) or connectionless (for example, UDP). #GDatagramBaseds must be + * datagram-based, not stream-based. The interface does not cover connection + * establishment — use methods on the underlying type to establish a connection + * before sending and receiving data through the #GDatagramBased API. For + * connectionless socket types the target/source address is specified or + * received in each I/O operation. + * + * Like most other APIs in GLib, #GDatagramBased is not inherently thread safe. + * To use a #GDatagramBased concurrently from multiple threads, you must + * implement your own locking. + * + * Since: 2.48 + */ + +G_DEFINE_INTERFACE (GDatagramBased, g_datagram_based, G_TYPE_OBJECT) + +static void +g_datagram_based_default_init (GDatagramBasedInterface *iface) +{ + /* Nothing here. */ +} + +/** + * g_datagram_based_receive_messages: + * @datagram_based: a #GDatagramBased + * @messages: (array length=num_messages): an array of #GInputMessage structs + * @num_messages: the number of elements in @messages + * @flags: an int containing #GSocketMsgFlags flags for the overall operation + * @timeout: the maximum time (in microseconds) to wait, 0 to not block, or -1 + * to block indefinitely + * @cancellable: (nullable): a %GCancellable + * @error: return location for a #GError + * + * Receive one or more data messages from @datagram_based in one go. + * + * @messages must point to an array of #GInputMessage structs and + * @num_messages must be the length of this array. Each #GInputMessage + * contains a pointer to an array of #GInputVector structs describing the + * buffers that the data received in each message will be written to. + * + * @flags modify how all messages are received. The commonly available + * arguments for this are available in the #GSocketMsgFlags enum, but the + * values there are the same as the system values, and the flags + * are passed in as-is, so you can pass in system-specific flags too. These + * flags affect the overall receive operation. Flags affecting individual + * messages are returned in #GInputMessage.flags. + * + * The other members of #GInputMessage are treated as described in its + * documentation. + * + * If @timeout is negative the call will block until @num_messages have been + * received, the connection is closed remotely (EOS), @cancellable is cancelled, + * or an error occurs. + * + * If @timeout is 0 the call will return up to @num_messages without blocking, + * or %G_IO_ERROR_WOULD_BLOCK if no messages are queued in the operating system + * to be received. + * + * If @timeout is positive the call will block on the same conditions as if + * @timeout were negative. If the timeout is reached + * before any messages are received, %G_IO_ERROR_TIMED_OUT is returned, + * otherwise it will return the number of messages received before timing out. + * (Note: This is effectively the behaviour of `MSG_WAITFORONE` with + * recvmmsg().) + * + * To be notified when messages are available, wait for the %G_IO_IN condition. + * Note though that you may still receive %G_IO_ERROR_WOULD_BLOCK from + * g_datagram_based_receive_messages() even if you were previously notified of a + * %G_IO_IN condition. + * + * If the remote peer closes the connection, any messages queued in the + * underlying receive buffer will be returned, and subsequent calls to + * g_datagram_based_receive_messages() will return 0 (with no error set). + * + * If the connection is shut down or closed (by calling g_socket_close() or + * g_socket_shutdown() with @shutdown_read set, if it’s a #GSocket, for + * example), all calls to this function will return %G_IO_ERROR_CLOSED. + * + * On error -1 is returned and @error is set accordingly. An error will only + * be returned if zero messages could be received; otherwise the number of + * messages successfully received before the error will be returned. If + * @cancellable is cancelled, %G_IO_ERROR_CANCELLED is returned as with any + * other error. + * + * Returns: number of messages received, or -1 on error. Note that the number + * of messages received may be smaller than @num_messages if @timeout is + * zero or positive, if the peer closed the connection, or if @num_messages + * was larger than `UIO_MAXIOV` (1024), in which case the caller may re-try + * to receive the remaining messages. + * + * Since: 2.48 + */ +gint +g_datagram_based_receive_messages (GDatagramBased *datagram_based, + GInputMessage *messages, + guint num_messages, + gint flags, + gint64 timeout, + GCancellable *cancellable, + GError **error) +{ + GDatagramBasedInterface *iface; + gint retval; + GError *child_error = NULL; + + g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), -1); + g_return_val_if_fail (num_messages == 0 || messages != NULL, -1); + g_return_val_if_fail (cancellable == NULL || + G_IS_CANCELLABLE (cancellable), -1); + g_return_val_if_fail (error == NULL || *error == NULL, -1); + + iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based); + g_assert (iface->receive_messages != NULL); + + retval = iface->receive_messages (datagram_based, messages, num_messages, + flags, timeout, cancellable, &child_error); + + /* Postconditions. */ + g_return_val_if_fail ((retval < 0) == (child_error != NULL), -1); + g_return_val_if_fail (timeout == 0 || + !g_error_matches (child_error, G_IO_ERROR, + G_IO_ERROR_WOULD_BLOCK), -1); + g_return_val_if_fail (timeout > 0 || + !g_error_matches (child_error, G_IO_ERROR, + G_IO_ERROR_TIMED_OUT), -1); + g_return_val_if_fail (retval < 0 || (guint) retval <= num_messages, -1); + + if (child_error != NULL) + g_propagate_error (error, child_error); + + return retval; +} + +/** + * g_datagram_based_send_messages: + * @datagram_based: a #GDatagramBased + * @messages: (array length=num_messages): an array of #GOutputMessage structs + * @num_messages: the number of elements in @messages + * @flags: an int containing #GSocketMsgFlags flags + * @timeout: the maximum time (in microseconds) to wait, 0 to not block, or -1 + * to block indefinitely + * @cancellable: (nullable): a %GCancellable + * @error: return location for a #GError + * + * Send one or more data messages from @datagram_based in one go. + * + * @messages must point to an array of #GOutputMessage structs and + * @num_messages must be the length of this array. Each #GOutputMessage + * contains an address to send the data to, and a pointer to an array of + * #GOutputVector structs to describe the buffers that the data to be sent + * for each message will be gathered from. + * + * @flags modify how the message is sent. The commonly available arguments + * for this are available in the #GSocketMsgFlags enum, but the + * values there are the same as the system values, and the flags + * are passed in as-is, so you can pass in system-specific flags too. + * + * The other members of #GOutputMessage are treated as described in its + * documentation. + * + * If @timeout is negative the call will block until @num_messages have been + * sent, @cancellable is cancelled, or an error occurs. + * + * If @timeout is 0 the call will send up to @num_messages without blocking, + * or will return %G_IO_ERROR_WOULD_BLOCK if there is no space to send messages. + * + * If @timeout is positive the call will block on the same conditions as if + * @timeout were negative. If the timeout is reached before any messages are + * sent, %G_IO_ERROR_TIMED_OUT is returned, otherwise it will return the number + * of messages sent before timing out. + * + * To be notified when messages can be sent, wait for the %G_IO_OUT condition. + * Note though that you may still receive %G_IO_ERROR_WOULD_BLOCK from + * g_datagram_based_send_messages() even if you were previously notified of a + * %G_IO_OUT condition. (On Windows in particular, this is very common due to + * the way the underlying APIs work.) + * + * If the connection is shut down or closed (by calling g_socket_close() or + * g_socket_shutdown() with @shutdown_write set, if it’s a #GSocket, for + * example), all calls to this function will return %G_IO_ERROR_CLOSED. + * + * On error -1 is returned and @error is set accordingly. An error will only + * be returned if zero messages could be sent; otherwise the number of messages + * successfully sent before the error will be returned. If @cancellable is + * cancelled, %G_IO_ERROR_CANCELLED is returned as with any other error. + * + * Returns: number of messages sent, or -1 on error. Note that the number of + * messages sent may be smaller than @num_messages if @timeout is zero + * or positive, or if @num_messages was larger than `UIO_MAXIOV` (1024), in + * which case the caller may re-try to send the remaining messages. + * + * Since: 2.48 + */ +gint +g_datagram_based_send_messages (GDatagramBased *datagram_based, + GOutputMessage *messages, + guint num_messages, + gint flags, + gint64 timeout, + GCancellable *cancellable, + GError **error) +{ + GDatagramBasedInterface *iface; + gint retval; + GError *child_error = NULL; + + g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), -1); + g_return_val_if_fail (num_messages == 0 || messages != NULL, -1); + g_return_val_if_fail (cancellable == NULL || + G_IS_CANCELLABLE (cancellable), -1); + g_return_val_if_fail (error == NULL || *error == NULL, -1); + + iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based); + g_assert (iface->send_messages != NULL); + + retval = iface->send_messages (datagram_based, messages, num_messages, flags, + timeout, cancellable, &child_error); + + /* Postconditions. */ + g_return_val_if_fail ((retval < 0) == (child_error != NULL), -1); + g_return_val_if_fail (timeout == 0 || + !g_error_matches (child_error, G_IO_ERROR, + G_IO_ERROR_WOULD_BLOCK), -1); + g_return_val_if_fail (timeout > 0 || + !g_error_matches (child_error, G_IO_ERROR, + G_IO_ERROR_TIMED_OUT), -1); + g_return_val_if_fail (retval < 0 || (guint) retval <= num_messages, -1); + g_return_val_if_fail (!(timeout < 0 && num_messages > 0) || retval != 0, -1); + + if (child_error != NULL) + g_propagate_error (error, child_error); + + return retval; +} + +/** + * g_datagram_based_create_source: + * @datagram_based: a #GDatagramBased + * @condition: a #GIOCondition mask to monitor + * @cancellable: (nullable): a #GCancellable + * + * Creates a #GSource that can be attached to a #GMainContext to monitor for + * the availability of the specified @condition on the #GDatagramBased. The + * #GSource keeps a reference to the @datagram_based. + * + * The callback on the source is of the #GDatagramBasedSourceFunc type. + * + * It is meaningless to specify %G_IO_ERR or %G_IO_HUP in @condition; these + * conditions will always be reported in the callback if they are true. + * + * If non-%NULL, @cancellable can be used to cancel the source, which will + * cause the source to trigger, reporting the current condition (which is + * likely 0 unless cancellation happened at the same time as a condition + * change). You can check for this in the callback using + * g_cancellable_is_cancelled(). + * + * Returns: (transfer full): a newly allocated #GSource + * + * Since: 2.48 + */ +GSource * +g_datagram_based_create_source (GDatagramBased *datagram_based, + GIOCondition condition, + GCancellable *cancellable) +{ + GDatagramBasedInterface *iface; + + g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), NULL); + g_return_val_if_fail (cancellable == NULL || + G_IS_CANCELLABLE (cancellable), NULL); + + iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based); + g_assert (iface->create_source != NULL); + + return iface->create_source (datagram_based, condition, cancellable); +} + +/** + * g_datagram_based_condition_check: + * @datagram_based: a #GDatagramBased + * @condition: a #GIOCondition mask to check + * + * Checks on the readiness of @datagram_based to perform operations. The + * operations specified in @condition are checked for and masked against the + * currently-satisfied conditions on @datagram_based. The result is returned. + * + * %G_IO_IN will be set in the return value if data is available to read with + * g_datagram_based_receive_messages(), or if the connection is closed remotely + * (EOS); and if the datagram_based has not been closed locally using some + * implementation-specific method (such as g_socket_close() or + * g_socket_shutdown() with @shutdown_read set, if it’s a #GSocket). + * + * If the connection is shut down or closed (by calling g_socket_close() or + * g_socket_shutdown() with @shutdown_read set, if it’s a #GSocket, for + * example), all calls to this function will return %G_IO_ERROR_CLOSED. + * + * %G_IO_OUT will be set if it is expected that at least one byte can be sent + * using g_datagram_based_send_messages() without blocking. It will not be set + * if the datagram_based has been closed locally. + * + * %G_IO_HUP will be set if the connection has been closed locally. + * + * %G_IO_ERR will be set if there was an asynchronous error in transmitting data + * previously enqueued using g_datagram_based_send_messages(). + * + * Note that on Windows, it is possible for an operation to return + * %G_IO_ERROR_WOULD_BLOCK even immediately after + * g_datagram_based_condition_check() has claimed that the #GDatagramBased is + * ready for writing. Rather than calling g_datagram_based_condition_check() and + * then writing to the #GDatagramBased if it succeeds, it is generally better to + * simply try writing right away, and try again later if the initial attempt + * returns %G_IO_ERROR_WOULD_BLOCK. + * + * It is meaningless to specify %G_IO_ERR or %G_IO_HUP in @condition; these + * conditions will always be set in the output if they are true. Apart from + * these flags, the output is guaranteed to be masked by @condition. + * + * This call never blocks. + * + * Returns: the #GIOCondition mask of the current state + * + * Since: 2.48 + */ +GIOCondition +g_datagram_based_condition_check (GDatagramBased *datagram_based, + GIOCondition condition) +{ + GDatagramBasedInterface *iface; + GIOCondition out; + + g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), 0); + + iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based); + g_assert (iface->condition_check != NULL); + + out = iface->condition_check (datagram_based, condition); + + /* Postconditions. G_IO_OUT and G_IO_HUP are mutually exclusive. G_IO_IN and + * G_IO_HUP are mutually exclusive. The return value must be a subset of + * (condition | G_IO_ERR | G_IO_HUP). */ + g_return_val_if_fail ((out & (G_IO_OUT | G_IO_HUP)) != (G_IO_OUT | G_IO_HUP), + out & ~G_IO_OUT); + g_return_val_if_fail ((out & (G_IO_IN | G_IO_HUP)) != (G_IO_IN | G_IO_HUP), + out & ~G_IO_IN); + g_return_val_if_fail ((out & ~(condition | G_IO_ERR | G_IO_HUP)) == 0, + out & (condition | G_IO_ERR | G_IO_HUP)); + + return out; +} + +/** + * g_datagram_based_condition_wait: + * @datagram_based: a #GDatagramBased + * @condition: a #GIOCondition mask to wait for + * @timeout: the maximum time (in microseconds) to wait, 0 to not block, or -1 + * to block indefinitely + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Waits for up to @timeout microseconds for condition to become true on + * @datagram_based. If the condition is met, %TRUE is returned. + * + * If @cancellable is cancelled before the condition is met, or if @timeout is + * reached before the condition is met, then %FALSE is returned and @error is + * set appropriately (%G_IO_ERROR_CANCELLED or %G_IO_ERROR_TIMED_OUT). + * + * Returns: %TRUE if the condition was met, %FALSE otherwise + * + * Since: 2.48 + */ +gboolean +g_datagram_based_condition_wait (GDatagramBased *datagram_based, + GIOCondition condition, + gint64 timeout, + GCancellable *cancellable, + GError **error) +{ + GDatagramBasedInterface *iface; + gboolean out; + GError *child_error = NULL; + + g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), FALSE); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), + FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based); + g_assert (iface->condition_wait != NULL); + + out = iface->condition_wait (datagram_based, condition, timeout, + cancellable, &child_error); + + /* Postconditions. */ + g_return_val_if_fail (out == (child_error == NULL), FALSE); + + if (child_error != NULL) + g_propagate_error (error, child_error); + + return out; +}
diff --git a/gio/gdatagrambased.h b/gio/gdatagrambased.h new file mode 100644 index 0000000..838b485 --- /dev/null +++ b/gio/gdatagrambased.h
@@ -0,0 +1,144 @@ +/* + * Copyright 2015 Collabora Ltd. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Authors: Philip Withnall <philip.withnall@collabora.co.uk> + */ + +#ifndef __G_DATAGRAM_BASED_H__ +#define __G_DATAGRAM_BASED_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/giotypes.h> + +G_BEGIN_DECLS + +#define G_TYPE_DATAGRAM_BASED (g_datagram_based_get_type ()) +#define G_DATAGRAM_BASED(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_DATAGRAM_BASED, GDatagramBased)) +#define G_IS_DATAGRAM_BASED(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + G_TYPE_DATAGRAM_BASED)) +#define G_DATAGRAM_BASED_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \ + G_TYPE_DATAGRAM_BASED, \ + GDatagramBasedInterface)) +#define G_TYPE_IS_DATAGRAM_BASED(type) (g_type_is_a ((type), \ + G_TYPE_DATAGRAM_BASED)) + +/** + * GDatagramBased: + * + * Interface for socket-like objects with datagram semantics. + * + * Since: 2.48 + */ +typedef struct _GDatagramBasedInterface GDatagramBasedInterface; + +/** + * GDatagramBasedInterface: + * @g_iface: The parent interface. + * @receive_messages: Virtual method for g_datagram_based_receive_messages(). + * @send_messages: Virtual method for g_datagram_based_send_messages(). + * @create_source: Virtual method for g_datagram_based_create_source(). + * @condition_check: Virtual method for g_datagram_based_condition_check(). + * @condition_wait: Virtual method for + * g_datagram_based_condition_wait(). + * + * Provides an interface for socket-like objects which have datagram semantics, + * following the Berkeley sockets API. The interface methods are thin wrappers + * around the corresponding virtual methods, and no pre-processing of inputs is + * implemented — so implementations of this API must handle all functionality + * documented in the interface methods. + * + * Since: 2.48 + */ +struct _GDatagramBasedInterface +{ + GTypeInterface g_iface; + + /* Virtual table */ + gint (*receive_messages) (GDatagramBased *datagram_based, + GInputMessage *messages, + guint num_messages, + gint flags, + gint64 timeout, + GCancellable *cancellable, + GError **error); + gint (*send_messages) (GDatagramBased *datagram_based, + GOutputMessage *messages, + guint num_messages, + gint flags, + gint64 timeout, + GCancellable *cancellable, + GError **error); + + GSource *(*create_source) (GDatagramBased *datagram_based, + GIOCondition condition, + GCancellable *cancellable); + GIOCondition (*condition_check) (GDatagramBased *datagram_based, + GIOCondition condition); + gboolean (*condition_wait) (GDatagramBased *datagram_based, + GIOCondition condition, + gint64 timeout, + GCancellable *cancellable, + GError **error); +}; + +GLIB_AVAILABLE_IN_2_48 +GType +g_datagram_based_get_type (void); + +GLIB_AVAILABLE_IN_2_48 +gint +g_datagram_based_receive_messages (GDatagramBased *datagram_based, + GInputMessage *messages, + guint num_messages, + gint flags, + gint64 timeout, + GCancellable *cancellable, + GError **error); + +GLIB_AVAILABLE_IN_2_48 +gint +g_datagram_based_send_messages (GDatagramBased *datagram_based, + GOutputMessage *messages, + guint num_messages, + gint flags, + gint64 timeout, + GCancellable *cancellable, + GError **error); + +GLIB_AVAILABLE_IN_2_48 +GSource * +g_datagram_based_create_source (GDatagramBased *datagram_based, + GIOCondition condition, + GCancellable *cancellable); +GLIB_AVAILABLE_IN_2_48 +GIOCondition +g_datagram_based_condition_check (GDatagramBased *datagram_based, + GIOCondition condition); +GLIB_AVAILABLE_IN_2_48 +gboolean +g_datagram_based_condition_wait (GDatagramBased *datagram_based, + GIOCondition condition, + gint64 timeout, + GCancellable *cancellable, + GError **error); + +G_END_DECLS + +#endif /* __G_DATAGRAM_BASED_H__ */
diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c new file mode 100644 index 0000000..2e7750c --- /dev/null +++ b/gio/gdatainputstream.c
@@ -0,0 +1,1469 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * Copyright (C) 2007 Jürg Billeter + * Copyright © 2009 Codethink Limited + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" +#include "gdatainputstream.h" +#include "gtask.h" +#include "gcancellable.h" +#include "gioenumtypes.h" +#include "gioerror.h" +#include "glibintl.h" + +#include <string.h> + +/** + * SECTION:gdatainputstream + * @short_description: Data Input Stream + * @include: gio/gio.h + * @see_also: #GInputStream + * + * Data input stream implements #GInputStream and includes functions for + * reading structured data directly from a binary input stream. + * + **/ + +struct _GDataInputStreamPrivate { + GDataStreamByteOrder byte_order; + GDataStreamNewlineType newline_type; +}; + +enum { + PROP_0, + PROP_BYTE_ORDER, + PROP_NEWLINE_TYPE +}; + +static void g_data_input_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void g_data_input_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +G_DEFINE_TYPE_WITH_PRIVATE (GDataInputStream, + g_data_input_stream, + G_TYPE_BUFFERED_INPUT_STREAM) + + +static void +g_data_input_stream_class_init (GDataInputStreamClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->get_property = g_data_input_stream_get_property; + object_class->set_property = g_data_input_stream_set_property; + + /** + * GDataStream:byte-order: + * + * The ::byte-order property determines the byte ordering that + * is used when reading multi-byte entities (such as integers) + * from the stream. + */ + g_object_class_install_property (object_class, + PROP_BYTE_ORDER, + g_param_spec_enum ("byte-order", + P_("Byte order"), + P_("The byte order"), + G_TYPE_DATA_STREAM_BYTE_ORDER, + G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN, + G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB)); + + /** + * GDataStream:newline-type: + * + * The :newline-type property determines what is considered + * as a line ending when reading complete lines from the stream. + */ + g_object_class_install_property (object_class, + PROP_NEWLINE_TYPE, + g_param_spec_enum ("newline-type", + P_("Newline type"), + P_("The accepted types of line ending"), + G_TYPE_DATA_STREAM_NEWLINE_TYPE, + G_DATA_STREAM_NEWLINE_TYPE_LF, + G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB)); +} + +static void +g_data_input_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GDataInputStream *dstream; + + dstream = G_DATA_INPUT_STREAM (object); + + switch (prop_id) + { + case PROP_BYTE_ORDER: + g_data_input_stream_set_byte_order (dstream, g_value_get_enum (value)); + break; + + case PROP_NEWLINE_TYPE: + g_data_input_stream_set_newline_type (dstream, g_value_get_enum (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +g_data_input_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GDataInputStreamPrivate *priv; + GDataInputStream *dstream; + + dstream = G_DATA_INPUT_STREAM (object); + priv = dstream->priv; + + switch (prop_id) + { + case PROP_BYTE_ORDER: + g_value_set_enum (value, priv->byte_order); + break; + + case PROP_NEWLINE_TYPE: + g_value_set_enum (value, priv->newline_type); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} +static void +g_data_input_stream_init (GDataInputStream *stream) +{ + stream->priv = g_data_input_stream_get_instance_private (stream); + stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN; + stream->priv->newline_type = G_DATA_STREAM_NEWLINE_TYPE_LF; +} + +/** + * g_data_input_stream_new: + * @base_stream: a #GInputStream. + * + * Creates a new data input stream for the @base_stream. + * + * Returns: a new #GDataInputStream. + **/ +GDataInputStream * +g_data_input_stream_new (GInputStream *base_stream) +{ + GDataInputStream *stream; + + g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL); + + stream = g_object_new (G_TYPE_DATA_INPUT_STREAM, + "base-stream", base_stream, + NULL); + + return stream; +} + +/** + * g_data_input_stream_set_byte_order: + * @stream: a given #GDataInputStream. + * @order: a #GDataStreamByteOrder to set. + * + * This function sets the byte order for the given @stream. All subsequent + * reads from the @stream will be read in the given @order. + * + **/ +void +g_data_input_stream_set_byte_order (GDataInputStream *stream, + GDataStreamByteOrder order) +{ + GDataInputStreamPrivate *priv; + + g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream)); + + priv = stream->priv; + + if (priv->byte_order != order) + { + priv->byte_order = order; + + g_object_notify (G_OBJECT (stream), "byte-order"); + } +} + +/** + * g_data_input_stream_get_byte_order: + * @stream: a given #GDataInputStream. + * + * Gets the byte order for the data input stream. + * + * Returns: the @stream's current #GDataStreamByteOrder. + **/ +GDataStreamByteOrder +g_data_input_stream_get_byte_order (GDataInputStream *stream) +{ + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN); + + return stream->priv->byte_order; +} + +/** + * g_data_input_stream_set_newline_type: + * @stream: a #GDataInputStream. + * @type: the type of new line return as #GDataStreamNewlineType. + * + * Sets the newline type for the @stream. + * + * Note that using G_DATA_STREAM_NEWLINE_TYPE_ANY is slightly unsafe. If a read + * chunk ends in "CR" we must read an additional byte to know if this is "CR" or + * "CR LF", and this might block if there is no more data available. + * + **/ +void +g_data_input_stream_set_newline_type (GDataInputStream *stream, + GDataStreamNewlineType type) +{ + GDataInputStreamPrivate *priv; + + g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream)); + + priv = stream->priv; + + if (priv->newline_type != type) + { + priv->newline_type = type; + + g_object_notify (G_OBJECT (stream), "newline-type"); + } +} + +/** + * g_data_input_stream_get_newline_type: + * @stream: a given #GDataInputStream. + * + * Gets the current newline type for the @stream. + * + * Returns: #GDataStreamNewlineType for the given @stream. + **/ +GDataStreamNewlineType +g_data_input_stream_get_newline_type (GDataInputStream *stream) +{ + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_NEWLINE_TYPE_ANY); + + return stream->priv->newline_type; +} + +static gboolean +read_data (GDataInputStream *stream, + void *buffer, + gsize size, + GCancellable *cancellable, + GError **error) +{ + gsize available; + gssize res; + + while ((available = g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (stream))) < size) + { + res = g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (stream), + size - available, + cancellable, error); + if (res < 0) + return FALSE; + if (res == 0) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Unexpected early end-of-stream")); + return FALSE; + } + } + + /* This should always succeed, since it's in the buffer */ + res = g_input_stream_read (G_INPUT_STREAM (stream), + buffer, size, + NULL, NULL); + g_warn_if_fail (res == size); + return TRUE; +} + + +/** + * g_data_input_stream_read_byte: + * @stream: a given #GDataInputStream. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads an unsigned 8-bit/1-byte value from @stream. + * + * Returns: an unsigned 8-bit/1-byte value read from the @stream or `0` + * if an error occurred. + **/ +guchar +g_data_input_stream_read_byte (GDataInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + guchar c; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), '\0'); + + if (read_data (stream, &c, 1, cancellable, error)) + return c; + + return 0; +} + + +/** + * g_data_input_stream_read_int16: + * @stream: a given #GDataInputStream. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads a 16-bit/2-byte value from @stream. + * + * In order to get the correct byte order for this read operation, + * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order(). + * + * Returns: a signed 16-bit/2-byte value read from @stream or `0` if + * an error occurred. + **/ +gint16 +g_data_input_stream_read_int16 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + gint16 v; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); + + if (read_data (stream, &v, 2, cancellable, error)) + { + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + v = GINT16_FROM_BE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + v = GINT16_FROM_LE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + return v; + } + + return 0; +} + + +/** + * g_data_input_stream_read_uint16: + * @stream: a given #GDataInputStream. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads an unsigned 16-bit/2-byte value from @stream. + * + * In order to get the correct byte order for this read operation, + * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order(). + * + * Returns: an unsigned 16-bit/2-byte value read from the @stream or `0` if + * an error occurred. + **/ +guint16 +g_data_input_stream_read_uint16 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + guint16 v; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); + + if (read_data (stream, &v, 2, cancellable, error)) + { + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + v = GUINT16_FROM_BE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + v = GUINT16_FROM_LE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + return v; + } + + return 0; +} + + +/** + * g_data_input_stream_read_int32: + * @stream: a given #GDataInputStream. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads a signed 32-bit/4-byte value from @stream. + * + * In order to get the correct byte order for this read operation, + * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order(). + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. + * + * Returns: a signed 32-bit/4-byte value read from the @stream or `0` if + * an error occurred. + **/ +gint32 +g_data_input_stream_read_int32 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + gint32 v; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); + + if (read_data (stream, &v, 4, cancellable, error)) + { + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + v = GINT32_FROM_BE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + v = GINT32_FROM_LE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + return v; + } + + return 0; +} + + +/** + * g_data_input_stream_read_uint32: + * @stream: a given #GDataInputStream. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads an unsigned 32-bit/4-byte value from @stream. + * + * In order to get the correct byte order for this read operation, + * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order(). + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. + * + * Returns: an unsigned 32-bit/4-byte value read from the @stream or `0` if + * an error occurred. + **/ +guint32 +g_data_input_stream_read_uint32 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + guint32 v; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); + + if (read_data (stream, &v, 4, cancellable, error)) + { + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + v = GUINT32_FROM_BE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + v = GUINT32_FROM_LE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + return v; + } + + return 0; +} + + +/** + * g_data_input_stream_read_int64: + * @stream: a given #GDataInputStream. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads a 64-bit/8-byte value from @stream. + * + * In order to get the correct byte order for this read operation, + * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order(). + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. + * + * Returns: a signed 64-bit/8-byte value read from @stream or `0` if + * an error occurred. + **/ +gint64 +g_data_input_stream_read_int64 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + gint64 v; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); + + if (read_data (stream, &v, 8, cancellable, error)) + { + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + v = GINT64_FROM_BE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + v = GINT64_FROM_LE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + return v; + } + + return 0; +} + + +/** + * g_data_input_stream_read_uint64: + * @stream: a given #GDataInputStream. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads an unsigned 64-bit/8-byte value from @stream. + * + * In order to get the correct byte order for this read operation, + * see g_data_input_stream_get_byte_order(). + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. + * + * Returns: an unsigned 64-bit/8-byte read from @stream or `0` if + * an error occurred. + **/ +guint64 +g_data_input_stream_read_uint64 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + guint64 v; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); + + if (read_data (stream, &v, 8, cancellable, error)) + { + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + v = GUINT64_FROM_BE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + v = GUINT64_FROM_LE (v); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + return v; + } + + return 0; +} + +static gssize +scan_for_newline (GDataInputStream *stream, + gsize *checked_out, + gboolean *last_saw_cr_out, + int *newline_len_out) +{ + GBufferedInputStream *bstream; + GDataInputStreamPrivate *priv; + const char *buffer; + gsize start, end, peeked; + int i; + gssize found_pos; + int newline_len; + gsize available, checked; + gboolean last_saw_cr; + + priv = stream->priv; + + bstream = G_BUFFERED_INPUT_STREAM (stream); + + checked = *checked_out; + last_saw_cr = *last_saw_cr_out; + found_pos = -1; + newline_len = 0; + + start = checked; + buffer = (const char*)g_buffered_input_stream_peek_buffer (bstream, &available) + start; + end = available; + peeked = end - start; + + for (i = 0; checked < available && i < peeked; i++) + { + switch (priv->newline_type) + { + case G_DATA_STREAM_NEWLINE_TYPE_LF: + if (buffer[i] == 10) + { + found_pos = start + i; + newline_len = 1; + } + break; + case G_DATA_STREAM_NEWLINE_TYPE_CR: + if (buffer[i] == 13) + { + found_pos = start + i; + newline_len = 1; + } + break; + case G_DATA_STREAM_NEWLINE_TYPE_CR_LF: + if (last_saw_cr && buffer[i] == 10) + { + found_pos = start + i - 1; + newline_len = 2; + } + break; + default: + case G_DATA_STREAM_NEWLINE_TYPE_ANY: + if (buffer[i] == 10) /* LF */ + { + if (last_saw_cr) + { + /* CR LF */ + found_pos = start + i - 1; + newline_len = 2; + } + else + { + /* LF */ + found_pos = start + i; + newline_len = 1; + } + } + else if (last_saw_cr) + { + /* Last was cr, this is not LF, end is CR */ + found_pos = start + i - 1; + newline_len = 1; + } + /* Don't check for CR here, instead look at last_saw_cr on next byte */ + break; + } + + last_saw_cr = (buffer[i] == 13); + + if (found_pos != -1) + { + *newline_len_out = newline_len; + return found_pos; + } + } + + checked = end; + + *checked_out = checked; + *last_saw_cr_out = last_saw_cr; + return -1; +} + + +/** + * g_data_input_stream_read_line: + * @stream: a given #GDataInputStream. + * @length: (out) (optional): a #gsize to get the length of the data read in. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads a line from the data input stream. Note that no encoding + * checks or conversion is performed; the input is not guaranteed to + * be UTF-8, and may in fact have embedded NUL characters. + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. + * + * Returns: (nullable) (transfer full) (array zero-terminated=1) (element-type guint8): + * a NUL terminated byte array with the line that was read in + * (without the newlines). Set @length to a #gsize to get the length + * of the read line. On an error, it will return %NULL and @error + * will be set. If there's no content to read, it will still return + * %NULL, but @error won't be set. + **/ +char * +g_data_input_stream_read_line (GDataInputStream *stream, + gsize *length, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStream *bstream; + gsize checked; + gboolean last_saw_cr; + gssize found_pos; + gssize res; + int newline_len; + char *line; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL); + + bstream = G_BUFFERED_INPUT_STREAM (stream); + + newline_len = 0; + checked = 0; + last_saw_cr = FALSE; + + while ((found_pos = scan_for_newline (stream, &checked, &last_saw_cr, &newline_len)) == -1) + { + if (g_buffered_input_stream_get_available (bstream) == + g_buffered_input_stream_get_buffer_size (bstream)) + g_buffered_input_stream_set_buffer_size (bstream, + 2 * g_buffered_input_stream_get_buffer_size (bstream)); + + res = g_buffered_input_stream_fill (bstream, -1, cancellable, error); + if (res < 0) + return NULL; + if (res == 0) + { + /* End of stream */ + if (g_buffered_input_stream_get_available (bstream) == 0) + { + if (length) + *length = 0; + return NULL; + } + else + { + found_pos = checked; + newline_len = 0; + break; + } + } + } + + line = g_malloc (found_pos + newline_len + 1); + + res = g_input_stream_read (G_INPUT_STREAM (stream), + line, + found_pos + newline_len, + NULL, NULL); + if (length) + *length = (gsize)found_pos; + g_warn_if_fail (res == found_pos + newline_len); + line[found_pos] = 0; + + return line; +} + +/** + * g_data_input_stream_read_line_utf8: + * @stream: a given #GDataInputStream. + * @length: (out) (optional): a #gsize to get the length of the data read in. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads a UTF-8 encoded line from the data input stream. + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. + * + * Returns: (nullable) (transfer full): a NUL terminated UTF-8 string + * with the line that was read in (without the newlines). Set + * @length to a #gsize to get the length of the read line. On an + * error, it will return %NULL and @error will be set. For UTF-8 + * conversion errors, the set error domain is %G_CONVERT_ERROR. If + * there's no content to read, it will still return %NULL, but @error + * won't be set. + * + * Since: 2.30 + **/ +char * +g_data_input_stream_read_line_utf8 (GDataInputStream *stream, + gsize *length, + GCancellable *cancellable, + GError **error) +{ + char *res; + + res = g_data_input_stream_read_line (stream, length, cancellable, error); + if (!res) + return NULL; + + if (!g_utf8_validate (res, -1, NULL)) + { + g_set_error_literal (error, G_CONVERT_ERROR, + G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + _("Invalid byte sequence in conversion input")); + g_free (res); + return NULL; + } + return res; +} + +static gssize +scan_for_chars (GDataInputStream *stream, + gsize *checked_out, + const char *stop_chars, + gssize stop_chars_len) +{ + GBufferedInputStream *bstream; + const char *buffer; + gsize start, end, peeked; + int i; + gsize available, checked; + const char *stop_char; + const char *stop_end; + + bstream = G_BUFFERED_INPUT_STREAM (stream); + stop_end = stop_chars + stop_chars_len; + + checked = *checked_out; + + start = checked; + buffer = (const char *)g_buffered_input_stream_peek_buffer (bstream, &available) + start; + end = available; + peeked = end - start; + + for (i = 0; checked < available && i < peeked; i++) + { + for (stop_char = stop_chars; stop_char != stop_end; stop_char++) + { + if (buffer[i] == *stop_char) + return (start + i); + } + } + + checked = end; + + *checked_out = checked; + return -1; +} + +/** + * g_data_input_stream_read_until: + * @stream: a given #GDataInputStream. + * @stop_chars: characters to terminate the read. + * @length: (out) (optional): a #gsize to get the length of the data read in. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads a string from the data input stream, up to the first + * occurrence of any of the stop characters. + * + * Note that, in contrast to g_data_input_stream_read_until_async(), + * this function consumes the stop character that it finds. + * + * Don't use this function in new code. Its functionality is + * inconsistent with g_data_input_stream_read_until_async(). Both + * functions will be marked as deprecated in a future release. Use + * g_data_input_stream_read_upto() instead, but note that that function + * does not consume the stop character. + * + * Returns: (transfer full): a string with the data that was read + * before encountering any of the stop characters. Set @length to + * a #gsize to get the length of the string. This function will + * return %NULL on an error. + * Deprecated: 2.56: Use g_data_input_stream_read_upto() instead, which has more + * consistent behaviour regarding the stop character. + */ +char * +g_data_input_stream_read_until (GDataInputStream *stream, + const gchar *stop_chars, + gsize *length, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStream *bstream; + gchar *result; + + bstream = G_BUFFERED_INPUT_STREAM (stream); + + result = g_data_input_stream_read_upto (stream, stop_chars, -1, + length, cancellable, error); + + /* If we're not at end of stream then we have a stop_char to consume. */ + if (result != NULL && g_buffered_input_stream_get_available (bstream) > 0) + { + gsize res G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */; + gchar b; + + res = g_input_stream_read (G_INPUT_STREAM (stream), &b, 1, NULL, NULL); + g_assert (res == 1); + } + + return result; +} + +typedef struct +{ + gboolean last_saw_cr; + gsize checked; + + gchar *stop_chars; + gssize stop_chars_len; + gsize length; +} GDataInputStreamReadData; + +static void +g_data_input_stream_read_complete (GTask *task, + gsize read_length, + gsize skip_length) +{ + GDataInputStreamReadData *data = g_task_get_task_data (task); + GInputStream *stream = g_task_get_source_object (task); + char *line = NULL; + + if (read_length || skip_length) + { + gssize bytes; + + data->length = read_length; + line = g_malloc (read_length + 1); + line[read_length] = '\0'; + + /* we already checked the buffer. this shouldn't fail. */ + bytes = g_input_stream_read (stream, line, read_length, NULL, NULL); + g_assert_cmpint (bytes, ==, read_length); + + bytes = g_input_stream_skip (stream, skip_length, NULL, NULL); + g_assert_cmpint (bytes, ==, skip_length); + } + + g_task_return_pointer (task, line, g_free); + g_object_unref (task); +} + +static void +g_data_input_stream_read_line_ready (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = user_data; + GDataInputStreamReadData *data = g_task_get_task_data (task); + GBufferedInputStream *buffer = g_task_get_source_object (task); + gssize found_pos; + gint newline_len; + + if (result) + /* this is a callback. finish the async call. */ + { + GError *error = NULL; + gssize bytes; + + bytes = g_buffered_input_stream_fill_finish (buffer, result, &error); + + if (bytes <= 0) + { + if (bytes < 0) + /* stream error. */ + { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_data_input_stream_read_complete (task, data->checked, 0); + return; + } + + /* only proceed if we got more bytes... */ + } + + if (data->stop_chars) + { + found_pos = scan_for_chars (G_DATA_INPUT_STREAM (buffer), + &data->checked, + data->stop_chars, + data->stop_chars_len); + newline_len = 0; + } + else + found_pos = scan_for_newline (G_DATA_INPUT_STREAM (buffer), &data->checked, + &data->last_saw_cr, &newline_len); + + if (found_pos == -1) + /* didn't find a full line; need to buffer some more bytes */ + { + gsize size; + + size = g_buffered_input_stream_get_buffer_size (buffer); + + if (g_buffered_input_stream_get_available (buffer) == size) + /* need to grow the buffer */ + g_buffered_input_stream_set_buffer_size (buffer, size * 2); + + /* try again */ + g_buffered_input_stream_fill_async (buffer, -1, + g_task_get_priority (task), + g_task_get_cancellable (task), + g_data_input_stream_read_line_ready, + user_data); + } + else + { + /* read the line and the EOL. no error is possible. */ + g_data_input_stream_read_complete (task, found_pos, newline_len); + } +} + +static void +g_data_input_stream_read_data_free (gpointer user_data) +{ + GDataInputStreamReadData *data = user_data; + + g_free (data->stop_chars); + g_slice_free (GDataInputStreamReadData, data); +} + +static void +g_data_input_stream_read_async (GDataInputStream *stream, + const gchar *stop_chars, + gssize stop_chars_len, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GDataInputStreamReadData *data; + GTask *task; + + data = g_slice_new0 (GDataInputStreamReadData); + if (stop_chars_len == -1) + stop_chars_len = strlen (stop_chars); + data->stop_chars = g_memdup (stop_chars, stop_chars_len); + data->stop_chars_len = stop_chars_len; + data->last_saw_cr = FALSE; + + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_source_tag (task, g_data_input_stream_read_async); + g_task_set_task_data (task, data, g_data_input_stream_read_data_free); + g_task_set_priority (task, io_priority); + + g_data_input_stream_read_line_ready (NULL, NULL, task); +} + +static gchar * +g_data_input_stream_read_finish (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error) +{ + GTask *task = G_TASK (result); + gchar *line; + + line = g_task_propagate_pointer (task, error); + + if (length && line) + { + GDataInputStreamReadData *data = g_task_get_task_data (task); + + *length = data->length; + } + + return line; +} + +/** + * g_data_input_stream_read_line_async: + * @stream: a given #GDataInputStream. + * @io_priority: the [I/O priority][io-priority] of the request + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @callback: (scope async): callback to call when the request is satisfied. + * @user_data: (closure): the data to pass to callback function. + * + * The asynchronous version of g_data_input_stream_read_line(). It is + * an error to have two outstanding calls to this function. + * + * When the operation is finished, @callback will be called. You + * can then call g_data_input_stream_read_line_finish() to get + * the result of the operation. + * + * Since: 2.20 + */ +void +g_data_input_stream_read_line_async (GDataInputStream *stream, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + g_data_input_stream_read_async (stream, NULL, 0, io_priority, + cancellable, callback, user_data); +} + +/** + * g_data_input_stream_read_until_async: + * @stream: a given #GDataInputStream. + * @stop_chars: characters to terminate the read. + * @io_priority: the [I/O priority][io-priority] of the request + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @callback: (scope async): callback to call when the request is satisfied. + * @user_data: (closure): the data to pass to callback function. + * + * The asynchronous version of g_data_input_stream_read_until(). + * It is an error to have two outstanding calls to this function. + * + * Note that, in contrast to g_data_input_stream_read_until(), + * this function does not consume the stop character that it finds. You + * must read it for yourself. + * + * When the operation is finished, @callback will be called. You + * can then call g_data_input_stream_read_until_finish() to get + * the result of the operation. + * + * Don't use this function in new code. Its functionality is + * inconsistent with g_data_input_stream_read_until(). Both functions + * will be marked as deprecated in a future release. Use + * g_data_input_stream_read_upto_async() instead. + * + * Since: 2.20 + * Deprecated: 2.56: Use g_data_input_stream_read_upto_async() instead, which + * has more consistent behaviour regarding the stop character. + */ +void +g_data_input_stream_read_until_async (GDataInputStream *stream, + const gchar *stop_chars, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + g_return_if_fail (stop_chars != NULL); + + g_data_input_stream_read_async (stream, stop_chars, -1, io_priority, + cancellable, callback, user_data); +} + +/** + * g_data_input_stream_read_line_finish: + * @stream: a given #GDataInputStream. + * @result: the #GAsyncResult that was provided to the callback. + * @length: (out) (optional): a #gsize to get the length of the data read in. + * @error: #GError for error reporting. + * + * Finish an asynchronous call started by + * g_data_input_stream_read_line_async(). Note the warning about + * string encoding in g_data_input_stream_read_line() applies here as + * well. + * + * Returns: (nullable) (transfer full) (array zero-terminated=1) (element-type guint8): + * a NUL-terminated byte array with the line that was read in + * (without the newlines). Set @length to a #gsize to get the length + * of the read line. On an error, it will return %NULL and @error + * will be set. If there's no content to read, it will still return + * %NULL, but @error won't be set. + * + * Since: 2.20 + */ +gchar * +g_data_input_stream_read_line_finish (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), NULL); + + return g_data_input_stream_read_finish (stream, result, length, error); +} + +/** + * g_data_input_stream_read_line_finish_utf8: + * @stream: a given #GDataInputStream. + * @result: the #GAsyncResult that was provided to the callback. + * @length: (out) (optional): a #gsize to get the length of the data read in. + * @error: #GError for error reporting. + * + * Finish an asynchronous call started by + * g_data_input_stream_read_line_async(). + * + * Returns: (nullable) (transfer full): a string with the line that + * was read in (without the newlines). Set @length to a #gsize to + * get the length of the read line. On an error, it will return + * %NULL and @error will be set. For UTF-8 conversion errors, the set + * error domain is %G_CONVERT_ERROR. If there's no content to read, + * it will still return %NULL, but @error won't be set. + * + * Since: 2.30 + */ +gchar * +g_data_input_stream_read_line_finish_utf8 (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error) +{ + gchar *res; + + res = g_data_input_stream_read_line_finish (stream, result, length, error); + if (!res) + return NULL; + + if (!g_utf8_validate (res, -1, NULL)) + { + g_set_error_literal (error, G_CONVERT_ERROR, + G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + _("Invalid byte sequence in conversion input")); + g_free (res); + return NULL; + } + return res; +} + +/** + * g_data_input_stream_read_until_finish: + * @stream: a given #GDataInputStream. + * @result: the #GAsyncResult that was provided to the callback. + * @length: (out) (optional): a #gsize to get the length of the data read in. + * @error: #GError for error reporting. + * + * Finish an asynchronous call started by + * g_data_input_stream_read_until_async(). + * + * Since: 2.20 + * + * Returns: (transfer full): a string with the data that was read + * before encountering any of the stop characters. Set @length to + * a #gsize to get the length of the string. This function will + * return %NULL on an error. + * Deprecated: 2.56: Use g_data_input_stream_read_upto_finish() instead, which + * has more consistent behaviour regarding the stop character. + */ +gchar * +g_data_input_stream_read_until_finish (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), NULL); + + return g_data_input_stream_read_finish (stream, result, length, error); +} + +/** + * g_data_input_stream_read_upto: + * @stream: a #GDataInputStream + * @stop_chars: characters to terminate the read + * @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is + * nul-terminated + * @length: (out) (optional): a #gsize to get the length of the data read in + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore + * @error: #GError for error reporting + * + * Reads a string from the data input stream, up to the first + * occurrence of any of the stop characters. + * + * In contrast to g_data_input_stream_read_until(), this function + * does not consume the stop character. You have to use + * g_data_input_stream_read_byte() to get it before calling + * g_data_input_stream_read_upto() again. + * + * Note that @stop_chars may contain '\0' if @stop_chars_len is + * specified. + * + * The returned string will always be nul-terminated on success. + * + * Returns: (transfer full): a string with the data that was read + * before encountering any of the stop characters. Set @length to + * a #gsize to get the length of the string. This function will + * return %NULL on an error + * + * Since: 2.26 + */ +char * +g_data_input_stream_read_upto (GDataInputStream *stream, + const gchar *stop_chars, + gssize stop_chars_len, + gsize *length, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStream *bstream; + gsize checked; + gssize found_pos; + gssize res; + char *data_until; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL); + + if (stop_chars_len < 0) + stop_chars_len = strlen (stop_chars); + + bstream = G_BUFFERED_INPUT_STREAM (stream); + + checked = 0; + + while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1) + { + if (g_buffered_input_stream_get_available (bstream) == + g_buffered_input_stream_get_buffer_size (bstream)) + g_buffered_input_stream_set_buffer_size (bstream, + 2 * g_buffered_input_stream_get_buffer_size (bstream)); + + res = g_buffered_input_stream_fill (bstream, -1, cancellable, error); + if (res < 0) + return NULL; + if (res == 0) + { + /* End of stream */ + if (g_buffered_input_stream_get_available (bstream) == 0) + { + if (length) + *length = 0; + return NULL; + } + else + { + found_pos = checked; + break; + } + } + } + + data_until = g_malloc (found_pos + 1); + + res = g_input_stream_read (G_INPUT_STREAM (stream), + data_until, + found_pos, + NULL, NULL); + if (length) + *length = (gsize)found_pos; + g_warn_if_fail (res == found_pos); + data_until[found_pos] = 0; + + return data_until; +} + +/** + * g_data_input_stream_read_upto_async: + * @stream: a #GDataInputStream + * @stop_chars: characters to terminate the read + * @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is + * nul-terminated + * @io_priority: the [I/O priority][io-priority] of the request + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore + * @callback: (scope async): callback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * The asynchronous version of g_data_input_stream_read_upto(). + * It is an error to have two outstanding calls to this function. + * + * In contrast to g_data_input_stream_read_until(), this function + * does not consume the stop character. You have to use + * g_data_input_stream_read_byte() to get it before calling + * g_data_input_stream_read_upto() again. + * + * Note that @stop_chars may contain '\0' if @stop_chars_len is + * specified. + * + * When the operation is finished, @callback will be called. You + * can then call g_data_input_stream_read_upto_finish() to get + * the result of the operation. + * + * Since: 2.26 + */ +void +g_data_input_stream_read_upto_async (GDataInputStream *stream, + const gchar *stop_chars, + gssize stop_chars_len, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + g_return_if_fail (stop_chars != NULL); + + g_data_input_stream_read_async (stream, stop_chars, stop_chars_len, io_priority, + cancellable, callback, user_data); +} + +/** + * g_data_input_stream_read_upto_finish: + * @stream: a #GDataInputStream + * @result: the #GAsyncResult that was provided to the callback + * @length: (out) (optional): a #gsize to get the length of the data read in + * @error: #GError for error reporting + * + * Finish an asynchronous call started by + * g_data_input_stream_read_upto_async(). + * + * Note that this function does not consume the stop character. You + * have to use g_data_input_stream_read_byte() to get it before calling + * g_data_input_stream_read_upto_async() again. + * + * The returned string will always be nul-terminated on success. + * + * Returns: (transfer full): a string with the data that was read + * before encountering any of the stop characters. Set @length to + * a #gsize to get the length of the string. This function will + * return %NULL on an error. + * + * Since: 2.24 + */ +gchar * +g_data_input_stream_read_upto_finish (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), NULL); + + return g_data_input_stream_read_finish (stream, result, length, error); +}
diff --git a/gio/gdatainputstream.h b/gio/gdatainputstream.h new file mode 100644 index 0000000..3ad3b82 --- /dev/null +++ b/gio/gdatainputstream.h
@@ -0,0 +1,180 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_DATA_INPUT_STREAM_H__ +#define __G_DATA_INPUT_STREAM_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/gbufferedinputstream.h> + +G_BEGIN_DECLS + +#define G_TYPE_DATA_INPUT_STREAM (g_data_input_stream_get_type ()) +#define G_DATA_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DATA_INPUT_STREAM, GDataInputStream)) +#define G_DATA_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DATA_INPUT_STREAM, GDataInputStreamClass)) +#define G_IS_DATA_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DATA_INPUT_STREAM)) +#define G_IS_DATA_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DATA_INPUT_STREAM)) +#define G_DATA_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DATA_INPUT_STREAM, GDataInputStreamClass)) + +/** + * GDataInputStream: + * + * An implementation of #GBufferedInputStream that allows for high-level + * data manipulation of arbitrary data (including binary operations). + **/ +typedef struct _GDataInputStreamClass GDataInputStreamClass; +typedef struct _GDataInputStreamPrivate GDataInputStreamPrivate; + +struct _GDataInputStream +{ + GBufferedInputStream parent_instance; + + /*< private >*/ + GDataInputStreamPrivate *priv; +}; + +struct _GDataInputStreamClass +{ + GBufferedInputStreamClass parent_class; + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); + void (*_g_reserved5) (void); +}; + +GLIB_AVAILABLE_IN_ALL +GType g_data_input_stream_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_ALL +GDataInputStream * g_data_input_stream_new (GInputStream *base_stream); + +GLIB_AVAILABLE_IN_ALL +void g_data_input_stream_set_byte_order (GDataInputStream *stream, + GDataStreamByteOrder order); +GLIB_AVAILABLE_IN_ALL +GDataStreamByteOrder g_data_input_stream_get_byte_order (GDataInputStream *stream); +GLIB_AVAILABLE_IN_ALL +void g_data_input_stream_set_newline_type (GDataInputStream *stream, + GDataStreamNewlineType type); +GLIB_AVAILABLE_IN_ALL +GDataStreamNewlineType g_data_input_stream_get_newline_type (GDataInputStream *stream); +GLIB_AVAILABLE_IN_ALL +guchar g_data_input_stream_read_byte (GDataInputStream *stream, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gint16 g_data_input_stream_read_int16 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +guint16 g_data_input_stream_read_uint16 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gint32 g_data_input_stream_read_int32 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +guint32 g_data_input_stream_read_uint32 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gint64 g_data_input_stream_read_int64 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +guint64 g_data_input_stream_read_uint64 (GDataInputStream *stream, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +char * g_data_input_stream_read_line (GDataInputStream *stream, + gsize *length, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_2_30 +char * g_data_input_stream_read_line_utf8 (GDataInputStream *stream, + gsize *length, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +void g_data_input_stream_read_line_async (GDataInputStream *stream, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GLIB_AVAILABLE_IN_ALL +char * g_data_input_stream_read_line_finish (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error); +GLIB_AVAILABLE_IN_2_30 +char * g_data_input_stream_read_line_finish_utf8(GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error); +GLIB_DEPRECATED_IN_2_56_FOR (g_data_input_stream_read_upto) +char * g_data_input_stream_read_until (GDataInputStream *stream, + const gchar *stop_chars, + gsize *length, + GCancellable *cancellable, + GError **error); +GLIB_DEPRECATED_IN_2_56_FOR (g_data_input_stream_read_upto_async) +void g_data_input_stream_read_until_async (GDataInputStream *stream, + const gchar *stop_chars, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GLIB_DEPRECATED_IN_2_56_FOR (g_data_input_stream_read_upto_finish) +char * g_data_input_stream_read_until_finish (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error); + +GLIB_AVAILABLE_IN_ALL +char * g_data_input_stream_read_upto (GDataInputStream *stream, + const gchar *stop_chars, + gssize stop_chars_len, + gsize *length, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +void g_data_input_stream_read_upto_async (GDataInputStream *stream, + const gchar *stop_chars, + gssize stop_chars_len, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GLIB_AVAILABLE_IN_ALL +char * g_data_input_stream_read_upto_finish (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error); + +G_END_DECLS + +#endif /* __G_DATA_INPUT_STREAM_H__ */
diff --git a/gio/gdataoutputstream.c b/gio/gdataoutputstream.c new file mode 100644 index 0000000..4c2d251 --- /dev/null +++ b/gio/gdataoutputstream.c
@@ -0,0 +1,598 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#include "config.h" +#include <string.h> +#include "gdataoutputstream.h" +#include "gseekable.h" +#include "gioenumtypes.h" +#include "gioerror.h" +#include "glibintl.h" + + +/** + * SECTION:gdataoutputstream + * @short_description: Data Output Stream + * @include: gio/gio.h + * @see_also: #GOutputStream + * + * Data output stream implements #GOutputStream and includes functions for + * writing data directly to an output stream. + * + **/ + + + +struct _GDataOutputStreamPrivate { + GDataStreamByteOrder byte_order; +}; + +enum { + PROP_0, + PROP_BYTE_ORDER +}; + +static void g_data_output_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void g_data_output_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void g_data_output_stream_seekable_iface_init (GSeekableIface *iface); +static goffset g_data_output_stream_tell (GSeekable *seekable); +static gboolean g_data_output_stream_can_seek (GSeekable *seekable); +static gboolean g_data_output_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error); +static gboolean g_data_output_stream_can_truncate (GSeekable *seekable); +static gboolean g_data_output_stream_truncate (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error); + +G_DEFINE_TYPE_WITH_CODE (GDataOutputStream, + g_data_output_stream, + G_TYPE_FILTER_OUTPUT_STREAM, + G_ADD_PRIVATE (GDataOutputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, + g_data_output_stream_seekable_iface_init)) + + +static void +g_data_output_stream_class_init (GDataOutputStreamClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->get_property = g_data_output_stream_get_property; + object_class->set_property = g_data_output_stream_set_property; + + /** + * GDataOutputStream:byte-order: + * + * Determines the byte ordering that is used when writing + * multi-byte entities (such as integers) to the stream. + */ + g_object_class_install_property (object_class, + PROP_BYTE_ORDER, + g_param_spec_enum ("byte-order", + P_("Byte order"), + P_("The byte order"), + G_TYPE_DATA_STREAM_BYTE_ORDER, + G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN, + G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB)); + +} + +static void +g_data_output_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GDataOutputStream *dstream; + + dstream = G_DATA_OUTPUT_STREAM (object); + + switch (prop_id) + { + case PROP_BYTE_ORDER: + g_data_output_stream_set_byte_order (dstream, g_value_get_enum (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_data_output_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GDataOutputStreamPrivate *priv; + GDataOutputStream *dstream; + + dstream = G_DATA_OUTPUT_STREAM (object); + priv = dstream->priv; + + switch (prop_id) + { + case PROP_BYTE_ORDER: + g_value_set_enum (value, priv->byte_order); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_data_output_stream_init (GDataOutputStream *stream) +{ + stream->priv = g_data_output_stream_get_instance_private (stream); + stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN; +} + +static void +g_data_output_stream_seekable_iface_init (GSeekableIface *iface) +{ + iface->tell = g_data_output_stream_tell; + iface->can_seek = g_data_output_stream_can_seek; + iface->seek = g_data_output_stream_seek; + iface->can_truncate = g_data_output_stream_can_truncate; + iface->truncate_fn = g_data_output_stream_truncate; +} + +/** + * g_data_output_stream_new: + * @base_stream: a #GOutputStream. + * + * Creates a new data output stream for @base_stream. + * + * Returns: #GDataOutputStream. + **/ +GDataOutputStream * +g_data_output_stream_new (GOutputStream *base_stream) +{ + GDataOutputStream *stream; + + g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL); + + stream = g_object_new (G_TYPE_DATA_OUTPUT_STREAM, + "base-stream", base_stream, + NULL); + + return stream; +} + +/** + * g_data_output_stream_set_byte_order: + * @stream: a #GDataOutputStream. + * @order: a %GDataStreamByteOrder. + * + * Sets the byte order of the data output stream to @order. + **/ +void +g_data_output_stream_set_byte_order (GDataOutputStream *stream, + GDataStreamByteOrder order) +{ + GDataOutputStreamPrivate *priv; + g_return_if_fail (G_IS_DATA_OUTPUT_STREAM (stream)); + priv = stream->priv; + if (priv->byte_order != order) + { + priv->byte_order = order; + g_object_notify (G_OBJECT (stream), "byte-order"); + } +} + +/** + * g_data_output_stream_get_byte_order: + * @stream: a #GDataOutputStream. + * + * Gets the byte order for the stream. + * + * Returns: the #GDataStreamByteOrder for the @stream. + **/ +GDataStreamByteOrder +g_data_output_stream_get_byte_order (GDataOutputStream *stream) +{ + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN); + + return stream->priv->byte_order; +} + +/** + * g_data_output_stream_put_byte: + * @stream: a #GDataOutputStream. + * @data: a #guchar. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: a #GError, %NULL to ignore. + * + * Puts a byte into the output stream. + * + * Returns: %TRUE if @data was successfully added to the @stream. + **/ +gboolean +g_data_output_stream_put_byte (GDataOutputStream *stream, + guchar data, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); + + return g_output_stream_write_all (G_OUTPUT_STREAM (stream), + &data, 1, + &bytes_written, + cancellable, error); +} + +/** + * g_data_output_stream_put_int16: + * @stream: a #GDataOutputStream. + * @data: a #gint16. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: a #GError, %NULL to ignore. + * + * Puts a signed 16-bit integer into the output stream. + * + * Returns: %TRUE if @data was successfully added to the @stream. + **/ +gboolean +g_data_output_stream_put_int16 (GDataOutputStream *stream, + gint16 data, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); + + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + data = GINT16_TO_BE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + data = GINT16_TO_LE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + + return g_output_stream_write_all (G_OUTPUT_STREAM (stream), + &data, 2, + &bytes_written, + cancellable, error); +} + +/** + * g_data_output_stream_put_uint16: + * @stream: a #GDataOutputStream. + * @data: a #guint16. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: a #GError, %NULL to ignore. + * + * Puts an unsigned 16-bit integer into the output stream. + * + * Returns: %TRUE if @data was successfully added to the @stream. + **/ +gboolean +g_data_output_stream_put_uint16 (GDataOutputStream *stream, + guint16 data, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); + + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + data = GUINT16_TO_BE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + data = GUINT16_TO_LE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + + return g_output_stream_write_all (G_OUTPUT_STREAM (stream), + &data, 2, + &bytes_written, + cancellable, error); +} + +/** + * g_data_output_stream_put_int32: + * @stream: a #GDataOutputStream. + * @data: a #gint32. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: a #GError, %NULL to ignore. + * + * Puts a signed 32-bit integer into the output stream. + * + * Returns: %TRUE if @data was successfully added to the @stream. + **/ +gboolean +g_data_output_stream_put_int32 (GDataOutputStream *stream, + gint32 data, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); + + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + data = GINT32_TO_BE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + data = GINT32_TO_LE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + + return g_output_stream_write_all (G_OUTPUT_STREAM (stream), + &data, 4, + &bytes_written, + cancellable, error); +} + +/** + * g_data_output_stream_put_uint32: + * @stream: a #GDataOutputStream. + * @data: a #guint32. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: a #GError, %NULL to ignore. + * + * Puts an unsigned 32-bit integer into the stream. + * + * Returns: %TRUE if @data was successfully added to the @stream. + **/ +gboolean +g_data_output_stream_put_uint32 (GDataOutputStream *stream, + guint32 data, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); + + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + data = GUINT32_TO_BE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + data = GUINT32_TO_LE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + + return g_output_stream_write_all (G_OUTPUT_STREAM (stream), + &data, 4, + &bytes_written, + cancellable, error); +} + +/** + * g_data_output_stream_put_int64: + * @stream: a #GDataOutputStream. + * @data: a #gint64. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: a #GError, %NULL to ignore. + * + * Puts a signed 64-bit integer into the stream. + * + * Returns: %TRUE if @data was successfully added to the @stream. + **/ +gboolean +g_data_output_stream_put_int64 (GDataOutputStream *stream, + gint64 data, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); + + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + data = GINT64_TO_BE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + data = GINT64_TO_LE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + + return g_output_stream_write_all (G_OUTPUT_STREAM (stream), + &data, 8, + &bytes_written, + cancellable, error); +} + +/** + * g_data_output_stream_put_uint64: + * @stream: a #GDataOutputStream. + * @data: a #guint64. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: a #GError, %NULL to ignore. + * + * Puts an unsigned 64-bit integer into the stream. + * + * Returns: %TRUE if @data was successfully added to the @stream. + **/ +gboolean +g_data_output_stream_put_uint64 (GDataOutputStream *stream, + guint64 data, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); + + switch (stream->priv->byte_order) + { + case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: + data = GUINT64_TO_BE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: + data = GUINT64_TO_LE (data); + break; + case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: + default: + break; + } + + return g_output_stream_write_all (G_OUTPUT_STREAM (stream), + &data, 8, + &bytes_written, + cancellable, error); +} + +/** + * g_data_output_stream_put_string: + * @stream: a #GDataOutputStream. + * @str: a string. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @error: a #GError, %NULL to ignore. + * + * Puts a string into the output stream. + * + * Returns: %TRUE if @string was successfully added to the @stream. + **/ +gboolean +g_data_output_stream_put_string (GDataOutputStream *stream, + const char *str, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + return g_output_stream_write_all (G_OUTPUT_STREAM (stream), + str, strlen (str), + &bytes_written, + cancellable, error); +} + +static goffset +g_data_output_stream_tell (GSeekable *seekable) +{ + GOutputStream *base_stream; + GSeekable *base_stream_seekable; + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + return 0; + base_stream_seekable = G_SEEKABLE (base_stream); + return g_seekable_tell (base_stream_seekable); +} + +static gboolean +g_data_output_stream_can_seek (GSeekable *seekable) +{ + GOutputStream *base_stream; + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream)); +} + +static gboolean +g_data_output_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error) +{ + GOutputStream *base_stream; + GSeekable *base_stream_seekable; + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Seek not supported on base stream")); + return FALSE; + } + + base_stream_seekable = G_SEEKABLE (base_stream); + return g_seekable_seek (base_stream_seekable, offset, type, cancellable, error); +} + +static gboolean +g_data_output_stream_can_truncate (GSeekable *seekable) +{ + GOutputStream *base_stream; + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + return G_IS_SEEKABLE (base_stream) && g_seekable_can_truncate (G_SEEKABLE (base_stream)); +} + +static gboolean +g_data_output_stream_truncate (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error) +{ + GOutputStream *base_stream; + GSeekable *base_stream_seekable; + + base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Truncate not supported on base stream")); + return FALSE; + } + + base_stream_seekable = G_SEEKABLE (base_stream); + return g_seekable_truncate (base_stream_seekable, offset, cancellable, error); +}
diff --git a/gio/gdataoutputstream.h b/gio/gdataoutputstream.h new file mode 100644 index 0000000..62cf7b5 --- /dev/null +++ b/gio/gdataoutputstream.h
@@ -0,0 +1,125 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * 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 2.1 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 + * Lesser 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 <http://www.gnu.org/licenses/>. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_DATA_OUTPUT_STREAM_H__ +#define __G_DATA_OUTPUT_STREAM_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only <gio/gio.h> can be included directly." +#endif + +#include <gio/gfilteroutputstream.h> + +G_BEGIN_DECLS + +#define G_TYPE_DATA_OUTPUT_STREAM (g_data_output_stream_get_type ()) +#define G_DATA_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DATA_OUTPUT_STREAM, GDataOutputStream)) +#define G_DATA_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DATA_OUTPUT_STREAM, GDataOutputStreamClass)) +#define G_IS_DATA_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DATA_OUTPUT_STREAM)) +#define G_IS_DATA_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DATA_OUTPUT_STREAM)) +#define G_DATA_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DATA_OUTPUT_STREAM, GDataOutputStreamClass)) + +/** + * GDataOutputStream: + * + * An implementation of #GBufferedOutputStream that allows for high-level + * data manipulation of arbitrary data (including binary operations). + **/ +typedef struct _GDataOutputStream GDataOutputStream; +typedef struct _GDataOutputStreamClass GDataOutputStreamClass; +typedef struct _GDataOutputStreamPrivate GDataOutputStreamPrivate; + +struct _GDataOutputStream +{ + GFilterOutputStream parent_instance; + + /*< private >*/ + GDataOutputStreamPrivate *priv; +}; + +struct _GDataOutputStreamClass +{ + GFilterOutputStreamClass parent_class; + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); + void (*_g_reserved5) (void); +}; + + +GLIB_AVAILABLE_IN_ALL +GType g_data_output_stream_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_ALL +GDataOutputStream * g_data_output_stream_new (GOutputStream *base_stream); + +GLIB_AVAILABLE_IN_ALL +void g_data_output_stream_set_byte_order (GDataOutputStream *stream, + GDataStreamByteOrder order); +GLIB_AVAILABLE_IN_ALL +GDataStreamByteOrder g_data_output_stream_get_byte_order (GDataOutputStream *stream); + +GLIB_AVAILABLE_IN_ALL +gboolean g_data_output_stream_put_byte (GDataOutputStream *stream, + guchar data, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_data_output_stream_put_int16 (GDataOutputStream *stream, + gint16 data, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_data_output_stream_put_uint16 (GDataOutputStream *stream, + guint16 data, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_data_output_stream_put_int32 (GDataOutputStream *stream, + gint32 data, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_data_output_stream_put_uint32 (GDataOutputStream *stream, + guint32 data, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_data_output_stream_put_int64 (GDataOutputStream *stream, + gint64 data, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_data_output_stream_put_uint64 (GDataOutputStream *stream, + guint64 data, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_ALL +gboolean g_data_output_stream_put_string (GDataOutputStream *stream, + const char *str, + GCancellable *cancellable, + GError **error); + +G_END_DECLS + +#endif /* __G_DATA_OUTPUT_STREAM_H__ */
diff --git a/gio/gdbus-2.0/codegen/.gitignore b/gio/gdbus-2.0/codegen/.gitignore new file mode 100644 index 0000000..0015c09 --- /dev/null +++ b/gio/gdbus-2.0/codegen/.gitignore
@@ -0,0 +1,3 @@ +*.pyc +config.py +gdbus-codegen
diff --git a/gio/gdbus-2.0/codegen/__init__.py b/gio/gdbus-2.0/codegen/__init__.py new file mode 100644 index 0000000..f876f04 --- /dev/null +++ b/gio/gdbus-2.0/codegen/__init__.py
@@ -0,0 +1,27 @@ +# -*- Mode: Python -*- + +# GDBus - GLib D-Bus Library +# +# Copyright (C) 2008-2011 Red Hat, Inc. +# +# 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 2.1 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 +# Lesser 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 <http://www.gnu.org/licenses/>. +# +# Author: David Zeuthen <davidz@redhat.com> + +import os + +builddir = os.environ.get('UNINSTALLED_GLIB_BUILDDIR') + +if builddir is not None: + __path__.append(os.path.abspath(os.path.join(builddir, 'gio', 'gdbus-2.0', 'codegen')))
diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py new file mode 100644 index 0000000..5234b38 --- /dev/null +++ b/gio/gdbus-2.0/codegen/codegen.py
@@ -0,0 +1,3899 @@ +# -*- Mode: Python -*- +# coding=utf-8 + +# GDBus - GLib D-Bus Library +# +# Copyright (C) 2008-2018 Red Hat, Inc. +# Copyright (C) 2018 Iñigo Martínez <inigomartinez@gmail.com> +# +# 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 2.1 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 +# Lesser 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 <http://www.gnu.org/licenses/>. +# +# Author: David Zeuthen <davidz@redhat.com> + +import sys + +from . import config +from . import utils +from . import dbustypes +from .utils import print_error + +LICENSE_STR = '''/* + * This file is generated by gdbus-codegen, do not modify it. + * + * The license of this code is the same as for the D-Bus interface description + * it was derived from. Note that it links to GLib, so must comply with the + * LGPL linking clauses. + */\n''' + +def generate_namespace(namespace): + ns = namespace + if len(namespace) > 0: + if utils.is_ugly_case(namespace): + ns = namespace.replace('_', '') + ns_upper = namespace.upper() + '_' + ns_lower = namespace.lower() + '_' + else: + ns_upper = utils.camel_case_to_uscore(namespace).upper() + '_' + ns_lower = utils.camel_case_to_uscore(namespace).lower() + '_' + else: + ns_upper = '' + ns_lower = '' + + return (ns, ns_upper, ns_lower) + +def generate_header_guard(header_name): + # There might be more characters that are safe to use than these, but lets + # stay conservative. + safe_valid_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + return ''.join(map(lambda c: c if c in safe_valid_chars else '_', + header_name.upper())) + +class HeaderCodeGenerator: + def __init__(self, ifaces, namespace, generate_objmanager, + generate_autocleanup, header_name, input_files_basenames, + use_pragma, glib_min_required, + symbol_decorator, symbol_decorator_header, outfile): + self.ifaces = ifaces + self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) + self.generate_objmanager = generate_objmanager + self.generate_autocleanup = generate_autocleanup + self.header_guard = generate_header_guard(header_name) + self.input_files_basenames = input_files_basenames + self.use_pragma = use_pragma + self.glib_min_required = glib_min_required + self.symbol_decorator = symbol_decorator + self.symbol_decorator_header = symbol_decorator_header + self.outfile = outfile + + # ---------------------------------------------------------------------------------------------------- + + def generate_header_preamble(self): + basenames = ', '.join(self.input_files_basenames) + self.outfile.write(LICENSE_STR.format(config.VERSION, basenames)) + self.outfile.write('\n') + + if self.use_pragma: + self.outfile.write('#pragma once\n') + else: + self.outfile.write('#ifndef __{!s}__\n'.format(self.header_guard)) + self.outfile.write('#define __{!s}__\n'.format(self.header_guard)) + + if self.symbol_decorator_header is not None: + self.outfile.write('\n') + self.outfile.write('#include "%s"\n' % self.symbol_decorator_header) + + self.outfile.write('\n') + self.outfile.write('#include <gio/gio.h>\n') + self.outfile.write('\n') + self.outfile.write('G_BEGIN_DECLS\n') + self.outfile.write('\n') + + # ---------------------------------------------------------------------------------------------------- + + def declare_types(self): + for i in self.ifaces: + self.outfile.write('\n') + self.outfile.write('/* ------------------------------------------------------------------------ */\n') + self.outfile.write('/* Declarations for %s */\n'%i.name) + self.outfile.write('\n') + + # First the GInterface + self.outfile.write('#define %sTYPE_%s (%s_get_type ())\n'%(i.ns_upper, i.name_upper, i.name_lower)) + self.outfile.write('#define %s%s(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s, %s))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) + self.outfile.write('#define %sIS_%s(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) + self.outfile.write('#define %s%s_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), %sTYPE_%s, %sIface))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) + self.outfile.write('\n') + self.outfile.write('struct _%s;\n'%(i.camel_name)) + self.outfile.write('typedef struct _%s %s;\n'%(i.camel_name, i.camel_name)) + self.outfile.write('typedef struct _%sIface %sIface;\n'%(i.camel_name, i.camel_name)) + self.outfile.write('\n') + self.outfile.write('struct _%sIface\n'%(i.camel_name)) + self.outfile.write('{\n') + self.outfile.write(' GTypeInterface parent_iface;\n') + + function_pointers = {} + + # vfuncs for methods + if len(i.methods) > 0: + self.outfile.write('\n') + for m in i.methods: + key = (m.since, '_method_%s'%m.name_lower) + value = ' gboolean (*handle_%s) (\n'%(m.name_lower) + value += ' %s *object,\n'%(i.camel_name) + value += ' GDBusMethodInvocation *invocation'%() + if m.unix_fd: + value += ',\n GUnixFDList *fd_list' + for a in m.in_args: + value += ',\n %sarg_%s'%(a.ctype_in, a.name) + value += ');\n\n' + function_pointers[key] = value + + # vfuncs for signals + if len(i.signals) > 0: + self.outfile.write('\n') + for s in i.signals: + key = (s.since, '_signal_%s'%s.name_lower) + value = ' void (*%s) (\n'%(s.name_lower) + value += ' %s *object'%(i.camel_name) + for a in s.args: + value += ',\n %sarg_%s'%(a.ctype_in, a.name) + value += ');\n\n' + function_pointers[key] = value + + # vfuncs for properties + if len(i.properties) > 0: + self.outfile.write('\n') + for p in i.properties: + key = (p.since, '_prop_get_%s'%p.name_lower) + value = ' %s (*get_%s) (%s *object);\n\n'%(p.arg.ctype_in, p.name_lower, i.camel_name) + function_pointers[key] = value + + # Sort according to @since tag, then name.. this ensures + # that the function pointers don't change order assuming + # judicious use of @since + # + # Also use a proper version comparison function so e.g. + # 10.0 comes after 2.0. + # + # See https://bugzilla.gnome.org/show_bug.cgi?id=647577#c5 + # for discussion + for key in sorted(function_pointers.keys(), key=utils.version_cmp_key): + self.outfile.write('%s'%function_pointers[key]) + + self.outfile.write('};\n') + self.outfile.write('\n') + if self.generate_autocleanup == 'all': + self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') + self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, g_object_unref)\n' % (i.camel_name)) + self.outfile.write('#endif\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('GType %s_get_type (void) G_GNUC_CONST;\n'%(i.name_lower)) + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('GDBusInterfaceInfo *%s_interface_info (void);\n'%(i.name_lower)) + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('guint %s_override_properties (GObjectClass *klass, guint property_id_begin);\n'%(i.name_lower)) + self.outfile.write('\n') + + # Then method call completion functions + if len(i.methods) > 0: + self.outfile.write('\n') + self.outfile.write('/* D-Bus method call completion functions: */\n') + for m in i.methods: + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if m.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('void %s_complete_%s (\n' + ' %s *object,\n' + ' GDBusMethodInvocation *invocation'%(i.name_lower, m.name_lower, i.camel_name)) + if m.unix_fd: + self.outfile.write(',\n GUnixFDList *fd_list') + for a in m.out_args: + self.outfile.write(',\n %s%s'%(a.ctype_in, a.name)) + self.outfile.write(');\n') + self.outfile.write('\n') + self.outfile.write('\n') + + # Then signal emission functions + if len(i.signals) > 0: + self.outfile.write('\n') + self.outfile.write('/* D-Bus signal emissions functions: */\n') + for s in i.signals: + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if s.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('void %s_emit_%s (\n' + ' %s *object'%(i.name_lower, s.name_lower, i.camel_name)) + for a in s.args: + self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) + self.outfile.write(');\n') + self.outfile.write('\n') + self.outfile.write('\n') + + # Then method call declarations + if len(i.methods) > 0: + self.outfile.write('\n') + self.outfile.write('/* D-Bus method calls: */\n') + for m in i.methods: + # async begin + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if m.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('void %s_call_%s (\n' + ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + for a in m.in_args: + self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) + if self.glib_min_required >= (2, 64): + self.outfile.write(',\n GDBusCallFlags call_flags' + ',\n gint timeout_msec') + if m.unix_fd: + self.outfile.write(',\n GUnixFDList *fd_list') + self.outfile.write(',\n' + ' GCancellable *cancellable,\n' + ' GAsyncReadyCallback callback,\n' + ' gpointer user_data);\n') + self.outfile.write('\n') + # async finish + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if m.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('gboolean %s_call_%s_finish (\n' + ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + for a in m.out_args: + self.outfile.write(',\n %sout_%s'%(a.ctype_out, a.name)) + if m.unix_fd: + self.outfile.write(',\n GUnixFDList **out_fd_list') + self.outfile.write(',\n' + ' GAsyncResult *res,\n' + ' GError **error);\n') + self.outfile.write('\n') + # sync + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if m.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('gboolean %s_call_%s_sync (\n' + ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + for a in m.in_args: + self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) + if self.glib_min_required >= (2, 64): + self.outfile.write(',\n GDBusCallFlags call_flags' + ',\n gint timeout_msec') + if m.unix_fd: + self.outfile.write(',\n GUnixFDList *fd_list') + for a in m.out_args: + self.outfile.write(',\n %sout_%s'%(a.ctype_out, a.name)) + if m.unix_fd: + self.outfile.write(',\n GUnixFDList **out_fd_list') + self.outfile.write(',\n' + ' GCancellable *cancellable,\n' + ' GError **error);\n') + self.outfile.write('\n') + self.outfile.write('\n') + + # Then the property accessor declarations + if len(i.properties) > 0: + self.outfile.write('\n') + self.outfile.write('/* D-Bus property accessors: */\n') + for p in i.properties: + # getter + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if p.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s%s_get_%s (%s *object);\n'%(p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name)) + if p.arg.free_func != None: + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if p.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s%s_dup_%s (%s *object);\n'%(p.arg.ctype_in_dup, i.name_lower, p.name_lower, i.camel_name)) + # setter + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if p.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('void %s_set_%s (%s *object, %svalue);\n'%(i.name_lower, p.name_lower, i.camel_name, p.arg.ctype_in, )) + self.outfile.write('\n') + + # Then the proxy + self.outfile.write('\n') + self.outfile.write('/* ---- */\n') + self.outfile.write('\n') + self.outfile.write('#define %sTYPE_%s_PROXY (%s_proxy_get_type ())\n'%(i.ns_upper, i.name_upper, i.name_lower)) + self.outfile.write('#define %s%s_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s_PROXY, %sProxy))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) + self.outfile.write('#define %s%s_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_%s_PROXY, %sProxyClass))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) + self.outfile.write('#define %s%s_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_%s_PROXY, %sProxyClass))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) + self.outfile.write('#define %sIS_%s_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s_PROXY))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) + self.outfile.write('#define %sIS_%s_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_%s_PROXY))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) + self.outfile.write('\n') + self.outfile.write('typedef struct _%sProxy %sProxy;\n'%(i.camel_name, i.camel_name)) + self.outfile.write('typedef struct _%sProxyClass %sProxyClass;\n'%(i.camel_name, i.camel_name)) + self.outfile.write('typedef struct _%sProxyPrivate %sProxyPrivate;\n'%(i.camel_name, i.camel_name)) + self.outfile.write('\n') + self.outfile.write('struct _%sProxy\n'%(i.camel_name)) + self.outfile.write('{\n') + self.outfile.write(' /*< private >*/\n') + self.outfile.write(' GDBusProxy parent_instance;\n') + self.outfile.write(' %sProxyPrivate *priv;\n'%(i.camel_name)) + self.outfile.write('};\n') + self.outfile.write('\n') + self.outfile.write('struct _%sProxyClass\n'%(i.camel_name)) + self.outfile.write('{\n') + self.outfile.write(' GDBusProxyClass parent_class;\n') + self.outfile.write('};\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('GType %s_proxy_get_type (void) G_GNUC_CONST;\n'%(i.name_lower)) + self.outfile.write('\n') + if self.generate_autocleanup in ('objects', 'all'): + self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') + self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sProxy, g_object_unref)\n' % (i.camel_name)) + self.outfile.write('#endif\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('void %s_proxy_new (\n' + ' GDBusConnection *connection,\n' + ' GDBusProxyFlags flags,\n' + ' const gchar *name,\n' + ' const gchar *object_path,\n' + ' GCancellable *cancellable,\n' + ' GAsyncReadyCallback callback,\n' + ' gpointer user_data);\n' + %(i.name_lower)) + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s *%s_proxy_new_finish (\n' + ' GAsyncResult *res,\n' + ' GError **error);\n' + %(i.camel_name, i.name_lower)) + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s *%s_proxy_new_sync (\n' + ' GDBusConnection *connection,\n' + ' GDBusProxyFlags flags,\n' + ' const gchar *name,\n' + ' const gchar *object_path,\n' + ' GCancellable *cancellable,\n' + ' GError **error);\n' + %(i.camel_name, i.name_lower)) + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('void %s_proxy_new_for_bus (\n' + ' GBusType bus_type,\n' + ' GDBusProxyFlags flags,\n' + ' const gchar *name,\n' + ' const gchar *object_path,\n' + ' GCancellable *cancellable,\n' + ' GAsyncReadyCallback callback,\n' + ' gpointer user_data);\n' + %(i.name_lower)) + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s *%s_proxy_new_for_bus_finish (\n' + ' GAsyncResult *res,\n' + ' GError **error);\n' + %(i.camel_name, i.name_lower)) + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s *%s_proxy_new_for_bus_sync (\n' + ' GBusType bus_type,\n' + ' GDBusProxyFlags flags,\n' + ' const gchar *name,\n' + ' const gchar *object_path,\n' + ' GCancellable *cancellable,\n' + ' GError **error);\n' + %(i.camel_name, i.name_lower)) + self.outfile.write('\n') + + # Then the skeleton + self.outfile.write('\n') + self.outfile.write('/* ---- */\n') + self.outfile.write('\n') + self.outfile.write('#define %sTYPE_%s_SKELETON (%s_skeleton_get_type ())\n'%(i.ns_upper, i.name_upper, i.name_lower)) + self.outfile.write('#define %s%s_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s_SKELETON, %sSkeleton))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) + self.outfile.write('#define %s%s_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_%s_SKELETON, %sSkeletonClass))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) + self.outfile.write('#define %s%s_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_%s_SKELETON, %sSkeletonClass))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) + self.outfile.write('#define %sIS_%s_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s_SKELETON))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) + self.outfile.write('#define %sIS_%s_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_%s_SKELETON))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) + self.outfile.write('\n') + self.outfile.write('typedef struct _%sSkeleton %sSkeleton;\n'%(i.camel_name, i.camel_name)) + self.outfile.write('typedef struct _%sSkeletonClass %sSkeletonClass;\n'%(i.camel_name, i.camel_name)) + self.outfile.write('typedef struct _%sSkeletonPrivate %sSkeletonPrivate;\n'%(i.camel_name, i.camel_name)) + self.outfile.write('\n') + self.outfile.write('struct _%sSkeleton\n'%(i.camel_name)) + self.outfile.write('{\n') + self.outfile.write(' /*< private >*/\n') + self.outfile.write(' GDBusInterfaceSkeleton parent_instance;\n') + self.outfile.write(' %sSkeletonPrivate *priv;\n'%(i.camel_name)) + self.outfile.write('};\n') + self.outfile.write('\n') + self.outfile.write('struct _%sSkeletonClass\n'%(i.camel_name)) + self.outfile.write('{\n') + self.outfile.write(' GDBusInterfaceSkeletonClass parent_class;\n') + self.outfile.write('};\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('GType %s_skeleton_get_type (void) G_GNUC_CONST;\n'%(i.name_lower)) + self.outfile.write('\n') + if self.generate_autocleanup in ('objects', 'all'): + self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') + self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sSkeleton, g_object_unref)\n' % (i.camel_name)) + self.outfile.write('#endif\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s *%s_skeleton_new (void);\n'%(i.camel_name, i.name_lower)) + + self.outfile.write('\n') + + # Finally, the Object, ObjectProxy, ObjectSkeleton and ObjectManagerClient + if self.generate_objmanager: + self.outfile.write('\n') + self.outfile.write('/* ---- */\n') + self.outfile.write('\n') + self.outfile.write('#define %sTYPE_OBJECT (%sobject_get_type ())\n'%(self.ns_upper, self.ns_lower)) + self.outfile.write('#define %sOBJECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT, %sObject))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sIS_OBJECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT))\n'%(self.ns_upper, self.ns_upper)) + self.outfile.write('#define %sOBJECT_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), %sTYPE_OBJECT, %sObject))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('\n') + self.outfile.write('struct _%sObject;\n'%(self.namespace)) + self.outfile.write('typedef struct _%sObject %sObject;\n'%(self.namespace, self.namespace)) + self.outfile.write('typedef struct _%sObjectIface %sObjectIface;\n'%(self.namespace, self.namespace)) + self.outfile.write('\n') + self.outfile.write('struct _%sObjectIface\n'%(self.namespace)) + self.outfile.write('{\n' + ' GTypeInterface parent_iface;\n' + '};\n' + '\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('GType %sobject_get_type (void) G_GNUC_CONST;\n' + '\n' + %(self.ns_lower)) + if self.generate_autocleanup == 'all': + self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') + self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObject, g_object_unref)\n' % (self.namespace)) + self.outfile.write('#endif\n') + self.outfile.write('\n') + for i in self.ifaces: + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s *%sobject_get_%s (%sObject *object);\n' + %(i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace)) + for i in self.ifaces: + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('%s *%sobject_peek_%s (%sObject *object);\n' + %(i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace)) + self.outfile.write('\n') + self.outfile.write('#define %sTYPE_OBJECT_PROXY (%sobject_proxy_get_type ())\n'%(self.ns_upper, self.ns_lower)) + self.outfile.write('#define %sOBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_PROXY, %sObjectProxy))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sOBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_PROXY, %sObjectProxyClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sOBJECT_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_PROXY, %sObjectProxyClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sIS_OBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_PROXY))\n'%(self.ns_upper, self.ns_upper)) + self.outfile.write('#define %sIS_OBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_PROXY))\n'%(self.ns_upper, self.ns_upper)) + self.outfile.write('\n') + self.outfile.write('typedef struct _%sObjectProxy %sObjectProxy;\n'%(self.namespace, self.namespace)) + self.outfile.write('typedef struct _%sObjectProxyClass %sObjectProxyClass;\n'%(self.namespace, self.namespace)) + self.outfile.write('typedef struct _%sObjectProxyPrivate %sObjectProxyPrivate;\n'%(self.namespace, self.namespace)) + self.outfile.write('\n') + self.outfile.write('struct _%sObjectProxy\n'%(self.namespace)) + self.outfile.write('{\n') + self.outfile.write(' /*< private >*/\n') + self.outfile.write(' GDBusObjectProxy parent_instance;\n') + self.outfile.write(' %sObjectProxyPrivate *priv;\n'%(self.namespace)) + self.outfile.write('};\n') + self.outfile.write('\n') + self.outfile.write('struct _%sObjectProxyClass\n'%(self.namespace)) + self.outfile.write('{\n') + self.outfile.write(' GDBusObjectProxyClass parent_class;\n') + self.outfile.write('};\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('GType %sobject_proxy_get_type (void) G_GNUC_CONST;\n'%(self.ns_lower)) + self.outfile.write('\n') + if self.generate_autocleanup in ('objects', 'all'): + self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') + self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectProxy, g_object_unref)\n' % (self.namespace)) + self.outfile.write('#endif\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('%sObjectProxy *%sobject_proxy_new (GDBusConnection *connection, const gchar *object_path);\n'%(self.namespace, self.ns_lower)) + self.outfile.write('\n') + self.outfile.write('#define %sTYPE_OBJECT_SKELETON (%sobject_skeleton_get_type ())\n'%(self.ns_upper, self.ns_lower)) + self.outfile.write('#define %sOBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_SKELETON, %sObjectSkeleton))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sOBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_SKELETON, %sObjectSkeletonClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sOBJECT_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_SKELETON, %sObjectSkeletonClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sIS_OBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_SKELETON))\n'%(self.ns_upper, self.ns_upper)) + self.outfile.write('#define %sIS_OBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_SKELETON))\n'%(self.ns_upper, self.ns_upper)) + self.outfile.write('\n') + self.outfile.write('typedef struct _%sObjectSkeleton %sObjectSkeleton;\n'%(self.namespace, self.namespace)) + self.outfile.write('typedef struct _%sObjectSkeletonClass %sObjectSkeletonClass;\n'%(self.namespace, self.namespace)) + self.outfile.write('typedef struct _%sObjectSkeletonPrivate %sObjectSkeletonPrivate;\n'%(self.namespace, self.namespace)) + self.outfile.write('\n') + self.outfile.write('struct _%sObjectSkeleton\n'%(self.namespace)) + self.outfile.write('{\n') + self.outfile.write(' /*< private >*/\n') + self.outfile.write(' GDBusObjectSkeleton parent_instance;\n') + self.outfile.write(' %sObjectSkeletonPrivate *priv;\n'%(self.namespace)) + self.outfile.write('};\n') + self.outfile.write('\n') + self.outfile.write('struct _%sObjectSkeletonClass\n'%(self.namespace)) + self.outfile.write('{\n') + self.outfile.write(' GDBusObjectSkeletonClass parent_class;\n') + self.outfile.write('};\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('GType %sobject_skeleton_get_type (void) G_GNUC_CONST;\n'%(self.ns_lower)) + self.outfile.write('\n') + if self.generate_autocleanup in ('objects', 'all'): + self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') + self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectSkeleton, g_object_unref)\n' % (self.namespace)) + self.outfile.write('#endif\n') + self.outfile.write('\n') + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + self.outfile.write('%sObjectSkeleton *%sobject_skeleton_new (const gchar *object_path);\n' + %(self.namespace, self.ns_lower)) + for i in self.ifaces: + if self.symbol_decorator is not None: + self.outfile.write('%s\n' % self.symbol_decorator) + if i.deprecated: + self.outfile.write('G_GNUC_DEPRECATED ') + self.outfile.write('void %sobject_skeleton_set_%s (%sObjectSkeleton *object, %s *interface_);\n' + %(self.ns_lower, i.name_upper.lower(), self.namespace, i.camel_name)) + self.outfile.write('\n') + + self.outfile.write('/* ---- */\n') + self.outfile.write('\n') + self.outfile.write('#define %sTYPE_OBJECT_MANAGER_CLIENT (%sobject_manager_client_get_type ())\n'%(self.ns_upper, self.ns_lower)) + self.outfile.write('#define %sOBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClient))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sOBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClientClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sOBJECT_MANAGER_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClientClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) + self.outfile.write('#define %sIS_OBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_MANAGER_CLIENT))\n'%(self.ns_upper, self.ns_upper)) + self.outfile.write('#define %sIS_OBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_MANAGER_CLIENT))\n'%(self.ns_upper, self.ns_upper)) + self.outfile.write('\n') + self.outfile.write('typedef struct _%sObjectManagerClient %sObjectManagerClient;\n'%(self.namespace, self.namespace)) + self.outfile.write('typedef struct _%sObjectManagerClientClass %sObjectManagerClientClass;\n'%(self.namespace, self.namespace)) + self.outfile.write('typedef struct _%sObjectManagerClientPrivate %sObjectManagerClientPrivate;\n'%(self.namespace, self.namespace)) + self.outfile.write('\n') + self.outfile