diff options
179 files changed, 28419 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..0c70587 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,50 @@ +=== No ChangeLog === + + Since this module is using git, we rely on commit messages to provide change + history. Please write commit messages in the format described at + http://live.gnome.org/Git/CommitMessages + + Below is a copy of this format: + +=== begin example commit === +tag: 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. +=== end example commit === + + - The commit message is mainly for the other people, so they should be able + to understand it now and six months later. + + - 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. + + - You can prefix the first line with one tag, to make it easier to know to + which part of the module the commit applies. For example, a commit with + "fish: Make it work with newer fortune" in the gnome-panel module clearly + applies to the fish applet. + + - The main description (the body) is normal prose and should use normal + punctuation and capital letters where appropriate. Normally, for patches + sent to a mailing list, the body is copied from there. This main + description can be empty if the change is self-explanatory (eg: "Add DOAP + file"). + + - When committing code on behalf of others use the --author option, e.g. git + commit -a --author "Joe Coder <joe@coder.org>". + + - When referring to a bug, you can use this form: bgo#12345. Use bgo for + bugzilla.gnome.org, but you can also reference bugs in other bug trackers: + rh means bugzilla.redhat.com, bnc means bugzilla.novell.com, lp means + launchpad.net, etc. Whenever possible, use the full URL of the bug, though. + + - When a commit closes a bug, the commit message should contain a line like: + Closes: http://bugzilla.gnome.org/show_bug.cgi?id=12345 + or simply: + http://bugzilla.gnome.org/show_bug.cgi?id=12345 @@ -0,0 +1,16 @@ +xdg-specs +========= + +This repository contains the XDG specifications. + +To discuss the specifications, you may use the xdg mailing list: + + http://lists.freedesktop.org/mailman/listinfo/xdg + + +How to report issues +==================== + +Issues should be reported to the freedesktop.org bug tracking system: + + https://bugs.freedesktop.org/ (product Specifications) diff --git a/autostart/.cvsignore b/autostart/.cvsignore new file mode 100644 index 0000000..f5518ef --- /dev/null +++ b/autostart/.cvsignore @@ -0,0 +1,14 @@ +config.log +config.status +config.sub +configure +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.guess +config.h +config.h.in +install-sh +missing +autostart-spec.html diff --git a/autostart/AUTHORS b/autostart/AUTHORS new file mode 100644 index 0000000..cc42641 --- /dev/null +++ b/autostart/AUTHORS @@ -0,0 +1,5 @@ +John Palmieri <johnp@redhat.com> +KĂ©vin Ottens <ervin@ipsquad.net> +Renato Caldas <seventhguardian_@hotmail.com> +Rodrigo Moya <rodrigo@gnome-db.org> +Waldo Bastian <waldo.bastian@intel.com> diff --git a/autostart/COPYING b/autostart/COPYING new file mode 100644 index 0000000..73e7995 --- /dev/null +++ b/autostart/COPYING @@ -0,0 +1,2 @@ +FIXME - we need a license for specs + diff --git a/autostart/ChangeLog b/autostart/ChangeLog new file mode 100644 index 0000000..b7b5318 --- /dev/null +++ b/autostart/ChangeLog @@ -0,0 +1,4 @@ +2006-02-13 Waldo Bastian <waldo.bastian@intel.com> + + * Import of autostart spec + diff --git a/autostart/INSTALL b/autostart/INSTALL new file mode 100644 index 0000000..56b077d --- /dev/null +++ b/autostart/INSTALL @@ -0,0 +1,236 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PREFIX', the package will +use PREFIX as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/autostart/Makefile.am b/autostart/Makefile.am new file mode 100644 index 0000000..f13d2c9 --- /dev/null +++ b/autostart/Makefile.am @@ -0,0 +1,16 @@ +HTML_FILES= autostart-spec.html + +XML_FILES= autostart-spec.xml + +EXTRA_DIST= $(HTML_FILES) $(XML_FILES) + +if XML_DOCS_ENABLED +all-local: $(HTML_FILES) +endif + +%.html: %.xml + $(XMLTO) html-nochunks $< + +maintainer-clean-local: + rm -f $(HTML_FILES) + diff --git a/autostart/NEWS b/autostart/NEWS new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/autostart/NEWS diff --git a/autostart/README b/autostart/README new file mode 100644 index 0000000..7700629 --- /dev/null +++ b/autostart/README @@ -0,0 +1,6 @@ +This is the autostart specification. + +It covers +* automatic launching of applications when the user logs in +* automatic launching of applications when a new media is mounted + diff --git a/autostart/autogen.sh b/autostart/autogen.sh new file mode 100755 index 0000000..b1376df --- /dev/null +++ b/autostart/autogen.sh @@ -0,0 +1,3 @@ +#! /bin/sh +autoreconf -v --install || exit 1 +./configure --enable-maintainer-mode "$@" diff --git a/autostart/autostart-spec.xml b/autostart/autostart-spec.xml new file mode 100644 index 0000000..ba5487e --- /dev/null +++ b/autostart/autostart-spec.xml @@ -0,0 +1,273 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ + <!ENTITY version "0.5"> + <!ENTITY dtd-version "0.5"> + ]> + +<article id="index"> + <articleinfo> + <title>Desktop Application Autostart Specification</title> + <releaseinfo>Version &version;</releaseinfo> + <date>13 February 2006</date> + <authorgroup> + <author> + <firstname>John</firstname> + <surname>Palmieri</surname> + <affiliation> + <address> + <email>johnp@redhat.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>KĂ©vin</firstname> + <surname>Ottens</surname> + <affiliation> + <address> + <email>ervin@ipsquad.net</email> + </address> + </affiliation> + </author> + <author> + <firstname>Renato</firstname> + <surname>Caldas</surname> + <affiliation> + <address> + <email>seventhguardian_@hotmail.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Rodrigo</firstname> + <surname>Moya</surname> + <affiliation> + <address> + <email>rodrigo@gnome-db.org</email> + </address> + </affiliation> + </author> + <author> + <firstname>Waldo</firstname> + <surname>Bastian</surname> + <affiliation> + <address> + <email>bastian@kde.org</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + <para> + This DRAFT document defines a method for automatically starting + applications during the startup of a desktop environment and after + mounting a removable medium. + </para> + <para> + Some of the file locations in this specification are specified based + on the <ulink url="http://standards.freedesktop.org/basedir-spec/"> + "desktop base directory specification"</ulink>. + </para> + <para> + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL + NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and + "OPTIONAL" in this document are to be interpreted as + described in RFC 2119. + </para> + </sect1> + <sect1 id="startup"> + <title>Autostart Of Applications During Startup</title> + <para> + By placing an application's .desktop file + in one of the Autostart directories the application will be + automatically launched during startup of the user's desktop environment after the user + has logged in. + </para> + <sect2> + <title>Autostart Directories</title> + <para> + The Autostart Directories are $XDG_CONFIG_DIRS/autostart as defined + in accordance with the + <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html#referencing"> + "Referencing this specification"</ulink> section in the + <ulink url="http://standards.freedesktop.org/basedir-spec/"> + "desktop base directory specification"</ulink>. + </para> + <para> + If the same filename is located under multiple Autostart Directories + only the file under the most important directory should be used. + </para> + <informalexample> + <para> + Example: If $XDG_CONFIG_HOME is not set the Autostart Directory + in the user's home directory is ~/.config/autostart/ + </para> + </informalexample> + <informalexample> + <para> + Example: If $XDG_CONFIG_DIRS is not set the system wide Autostart + Directory is /etc/xdg/autostart/ + </para> + </informalexample> + <informalexample> + <para> + Example: If $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS are not set and + the two files /etc/xdg/autostart/foo.desktop and + ~/.config/autostart/foo.desktop exist then only the file + ~/.config/autostart/foo.desktop will be used because + ~/.config/autostart/ is more important than /etc/xdg/autostart/ + </para> + </informalexample> + </sect2> + <sect2> + <title>Application .desktop Files</title> + <para> + An application .desktop file must have the format as defined in + the <ulink url="http://standards.freedesktop.org/desktop-entry-spec/"> + "Desktop Entry Specification"</ulink>. All keys should be + interpreted as defined with the following exceptions in order to + take into account that the .desktop files in an autostart directory + are not shown in a menu. + </para> + <sect3> + <title>Hidden Key</title> + <para> + When the .desktop file has the Hidden key set to true, the .desktop + file MUST be ignored. When multiple .desktop files with the + same name exists in multiple directories then only the Hidden key + in the most important .desktop file must be considered: If it is + set to true all .desktop files with the same name + in the other directories MUST be ignored as well. + </para> + </sect3> + <sect3> + <title>OnlyShowIn and NotShowIn Keys</title> + <para> + The OnlyShownIn entry may contain a list of strings identifying + the desktop environments that MUST autostart this application, + all other desktop environments MUST NOT autostart this application. + </para> + <para> + The NotShownIn entry may contain a list of strings identifying + the desktop environments that MUST NOT autostart this + application, all other desktop environments MUST autostart this + application. + </para> + <para> + Only one of these keys, either OnlyShowIn or NotShowIn, may appear + in a single .desktop file. + </para> + </sect3> + <sect3> + <title>TryExec Key</title> + <para> + A .desktop file with a non-empty TryExec field MUST NOT be + autostarted if the value of the TryExec key does NOT match with + an installed executable program. The value of the TryExec field + may either be an absolute path or the name of an executable + without any path components. If the name of an executable is + specified without any path components then the $PATH environment + is searched to find a matching executable program. + </para> + </sect3> + </sect2> + <sect2> + <title>Implementation Notes</title> + <informalexample> + <para> + If an application autostarts by having a .desktop file installed + in the system wide autostart directory, an individual user can + disable the autotomatic start of this application by placing a + .desktop file of the same name in its personal autostart directory + which contains the key Hidden=true. + </para> + </informalexample> + </sect2> + </sect1> + <sect1 id="mounting"> + <title>Autostart Of Applications After Mount</title> + <para> + When a desktop environment mounts a new medium, the medium may contain + an Autostart file that can suggest to start an application or + an Autoopen file that can suggest to open a specific file located + on the medium. + </para> + <sect2> + <title>Autostart Files</title> + <para> + When a new medium is mounted the root directory of the medium should + be checked for the following Autostart files in order of precendence: + .autorun, autorun, autorun.sh + Only the first file that is present should be considered. + </para> + <para> + The desktop environment MAY ignore Autostart files altogether + based on policy set by the user, system administrator or vendor. + </para> + <para> + The desktop environment MUST prompt the user for confirmation before + automatically starting an application. + </para> + <para> + When an Autostart file has been detected and the user has confirmed + its execution the autostart file MUST be executed with the + current working directory (CWD) set to the root directory of the + medium. + </para> + </sect2> + <sect2> + <title>Autoopen Files</title> + <para> + When a new medium is mounted and a) the medium does not contain an + Autostart file or b) a policy to ignore Autostart files is in effect + then the root directory of the medium should be checked for the + following Autoopen files in order of precedence: + .autoopen, autoopen . + Only the first file that is present should be considered. + </para> + <para> + The desktop environment MAY ignore Autoopen files altogether + based on policy set by the user, system administrator or vendor. + </para> + <para> + An Autoopen file MUST contain a single relative path that points to + a non-executable file contained on the medium. + If the file contains a newline or carriage return character then the + newline or carriage return character itself and all characters that + follow MUST be ignored. + </para> + <para> + The relative path MUST NOT contain path components that refer to a + parent directory (../) + </para> + <para> + The relative path MUST NOT point to an executable file. + </para> + <para> + The desktop environment MUST verify that the relative path points to + a file that is actually located on the medium, taking into account any + symbolic or other links and MUST ignore any relative path that + points to a file location outside the medium itself. + </para> + <para> + If the relative path points to an executable file then the desktop + environment MUST NOT execute the file. + </para> + <para> + The desktop environment MUST prompt the user for confirmation before + opening the file. + </para> + <para> + When an Autoopen file has been detected and the user has confirmed + that the file indicated in the Autoopen file should be opened then + the file indicated in the Autoopen file MUST be opened in the + application normally preferred by the user for files of its kind + UNLESS the user instructed otherwise. + </para> + </sect2> + </sect1> + +</article> + diff --git a/autostart/configure.in b/autostart/configure.in new file mode 100644 index 0000000..7df76ac --- /dev/null +++ b/autostart/configure.in @@ -0,0 +1,61 @@ +dnl -*- mode: m4 -*- +AC_PREREQ(2.52) + +AC_INIT(autostart-spec.xml) + +AM_INIT_AUTOMAKE(autostart-spec, 0.5) + +# Honor aclocal flags +ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" + + ## must come before we use the $USE_MAINTAINER_MODE variable later +AM_MAINTAINER_MODE + +AC_ARG_ENABLE(xml-docs, [ --enable-xml-docs build XML into HTML (requires xmlto)],enable_xml_docs=$enableval,enable_xml_docs=auto) + +### XML tools + +AC_PATH_PROG(XMLTO, xmlto, no) + +AC_MSG_CHECKING([whether to build XML documentation]) + +if test x$XMLTO = xno ; then + have_xmlto=no +else + have_xmlto=yes +fi + +if test x$enable_xml_docs = xauto ; then + if test x$have_xmlto = xno ; then + enable_xml_docs=no + else + enable_xml_docs=yes + fi +fi + +if test x$enable_xml_docs = xyes; then + if test x$have_xmlto = xno; then + AC_MSG_ERROR([Building XML docs explicitly required, but xmlto not found]) + fi +fi + +AM_CONDITIONAL(XML_DOCS_ENABLED, test x$enable_xml_docs = xyes) +AC_MSG_RESULT(yes) + +AC_OUTPUT([ +Makefile +]) + +dnl ========================================================================== +echo " + Autostart specification $VERSION + ============== + + prefix: ${prefix} + source code location: ${srcdir} + xmlto: ${XMLTO}" + +echo " + Maintainer mode: ${USE_MAINTAINER_MODE} + Building XML docs: ${enable_xml_docs} +" diff --git a/basedir/.gitignore b/basedir/.gitignore new file mode 100644 index 0000000..126e056 --- /dev/null +++ b/basedir/.gitignore @@ -0,0 +1 @@ +basedir-spec.html diff --git a/basedir/Makefile b/basedir/Makefile new file mode 100644 index 0000000..35a73df --- /dev/null +++ b/basedir/Makefile @@ -0,0 +1,7 @@ +all: basedir-spec.html + +%.html: %.xml + xmlto html-nochunks $< + +clean: + rm -f basedir-spec.html diff --git a/basedir/basedir-spec.xml b/basedir/basedir-spec.xml new file mode 100644 index 0000000..03a982b --- /dev/null +++ b/basedir/basedir-spec.xml @@ -0,0 +1,298 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ + ]> +<article id="index"> + <articleinfo> + <title>XDG Base Directory Specification</title> + <releaseinfo>Version 0.7</releaseinfo> + <date>24th November 2010</date> + <authorgroup> + <author> + <firstname>Waldo</firstname> + <surname>Bastian</surname> + <affiliation> + <address> + <email>bastian@kde.org</email> + </address> + </affiliation> + </author> + <author> + <firstname>Ryan</firstname> + <surname>Lortie</surname> + <affiliation> + <address> + <email>desrt@desrt.ca</email> + </address> + </affiliation> + </author> + <author> + <firstname>Lennart</firstname> + <surname>Poettering</surname> + <affiliation> + <address> + <email>lennart@poettering.net</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + <para> + Various specifications specify files and file formats. This + specification defines where these files should be looked for by + defining one or more base directories relative to which files + should be located. + </para> + </sect1> + + <sect1 id="basics"> + <title>Basics</title> + <para> + The XDG Base Directory Specification is based on the following concepts: + <itemizedlist> + <listitem> + <para> + There is a single base directory relative to which user-specific + data files should be written. This directory is defined by the + environment variable <literal>$XDG_DATA_HOME</literal>. + </para> + </listitem> + <listitem> + <para> + There is a single base directory relative to which user-specific + configuration files should be written. This directory is defined by the + environment variable <literal>$XDG_CONFIG_HOME</literal>. + </para> + </listitem> + <listitem> + <para> + There is a set of preference ordered base directories relative to + which data files should be searched. This set of directories is defined + by the environment variable <literal>$XDG_DATA_DIRS</literal>. + </para> + </listitem> + <listitem> + <para> + There is a set of preference ordered base directories relative to + which configuration files should be searched. + This set of directories is defined + by the environment variable <literal>$XDG_CONFIG_DIRS</literal>. + </para> + </listitem> + <listitem> + <para> + There is a single base directory relative to which user-specific + non-essential (cached) data should be written. + This directory is defined by the + environment variable <literal>$XDG_CACHE_HOME</literal>. + </para> + </listitem> + <listitem> + <para> + There is a single base directory relative to which + user-specific runtime files and other file objects should + be placed. This directory is defined by the environment + variable <literal>$XDG_RUNTIME_DIR</literal>. + </para> + </listitem> + </itemizedlist> + </para> + + <para>All paths set in these environment variables must be + absolute. If an implementation encounters a relative path in any + of these variables it should consider the path invalid and ignore + it.</para> + </sect1> + + + <sect1 id="variables"> + <title>Environment variables</title> + <para> + <literal>$XDG_DATA_HOME</literal> defines the base directory relative to + which user specific data files should be stored. If + <literal>$XDG_DATA_HOME</literal> is either not set or empty, a default equal to + <literal>$HOME</literal>/.local/share should be used. + </para> + <para> + <literal>$XDG_CONFIG_HOME</literal> defines the base directory relative to + which user specific configuration files should be stored. If + <literal>$XDG_CONFIG_HOME</literal> is either not set or empty, a default equal to + <literal>$HOME</literal>/.config should be used. + </para> + <para> + <literal>$XDG_DATA_DIRS</literal> defines the preference-ordered set of + base directories to search for data files in addition to the + <literal>$XDG_DATA_HOME</literal> base directory. + The directories in <literal>$XDG_DATA_DIRS</literal> should be seperated + with a colon ':'. + </para> + <para> + If <literal>$XDG_DATA_DIRS</literal> is either not set or empty, a value equal to + /usr/local/share/:/usr/share/ should be used. + </para> + <para> + <literal>$XDG_CONFIG_DIRS</literal> defines the preference-ordered set of + base directories to search for configuration files in addition to the + <literal>$XDG_CONFIG_HOME</literal> base directory. + The directories in <literal>$XDG_CONFIG_DIRS</literal> should be seperated + with a colon ':'. + </para> + <para> + If <literal>$XDG_CONFIG_DIRS</literal> is either not set or empty, a value equal to + /etc/xdg should be used. + </para> + <para> + The order of base directories denotes their importance; the first + directory listed is the most important. When the same information is + defined in multiple places the information defined relative to the more + important base directory takes precedent. The base directory defined + by <literal>$XDG_DATA_HOME</literal> is considered more important than + any of the base directories defined by <literal>$XDG_DATA_DIRS</literal>. + The base directory defined + by <literal>$XDG_CONFIG_HOME</literal> is considered more important than + any of the base directories defined by <literal>$XDG_CONFIG_DIRS</literal>. + </para> + <para> + <literal>$XDG_CACHE_HOME</literal> defines the base directory relative to + which user specific non-essential data files should be stored. If + <literal>$XDG_CACHE_HOME</literal> is either not set or empty, a default equal to + <literal>$HOME</literal>/.cache should be used. + </para> + + <para> + <literal>$XDG_RUNTIME_DIR</literal> defines the base directory + relative to which user-specific non-essential runtime files and + other file objects (such as sockets, named pipes, ...) should be + stored. The directory MUST be owned by the user, and he MUST be + the only one having read and write access to it. Its Unix access + mode MUST be 0700. + </para> + <para> + The lifetime of the directory MUST be bound to the user being + logged in. It MUST be created when the user first logs in and if + the user fully logs out the directory MUST be removed. If the + user logs in more than once he should get pointed to the same + directory, and it is mandatory that the directory continues to + exist from his first login to his last logout on the system, and + not removed in between. Files in the directory MUST not survive + reboot or a full logout/login cycle. + </para> + <para> + The directory MUST be on a local file system and not shared with + any other system. The directory MUST by fully-featured by the + standards of the operating system. More specifically, on + Unix-like operating systems AF_UNIX sockets, symbolic links, + hard links, proper permissions, file locking, sparse files, + memory mapping, file change notifications, a reliable hard link + count must be supported, and no restrictions on the file name + character set should be imposed. Files in this directory MAY be + subjected to periodic clean-up. To ensure that your files are + not removed, they should have their access time timestamp + modified at least once every 6 hours of monotonic time or the + 'sticky' bit should be set on the file. + </para> + <para> + If <literal>$XDG_RUNTIME_DIR</literal> is not set applications + should fall back to a replacement directory with similar + capabilities and print a warning message. Applications should + use this directory for communication and synchronization + purposes and should not place larger files in it, since it might + reside in runtime memory and cannot necessarily be swapped out + to disk. + </para> + </sect1> + + <sect1 id="referencing"> + <title>Referencing this specification</title> + <para> + Other specifications may reference this specification by specifying the + location of a data file as + <literal>$XDG_DATA_DIRS</literal>/subdir/filename. This implies that: + <itemizedlist> + <listitem> + <para> + Such file should be installed to <literal>$datadir</literal>/subdir/filename + with <literal>$datadir</literal> defaulting to /usr/share. + </para> + </listitem> + <listitem> + <para> + A user specific version of the data file may be created in + <literal>$XDG_DATA_HOME</literal>/subdir/filename, taking into + account the default value for <literal>$XDG_DATA_HOME</literal> if + <literal>$XDG_DATA_HOME</literal> is not set. + </para> + </listitem> + <listitem> + <para> + Lookups of the data file should search for ./subdir/filename relative to + all base directories specified by <literal>$XDG_DATA_HOME</literal> and + <literal>$XDG_DATA_DIRS</literal> . If an environment + variable is either not set or empty, its default value as defined by this specification + should be used instead. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Specifications may reference this specification by specifying the + location of a configuration file as + <literal>$XDG_CONFIG_DIRS</literal>/subdir/filename. This implies that: + <itemizedlist> + <listitem> + <para> + Default configuration files should be installed to <literal>$sysconfdir</literal>/xdg/subdir/filename + with <literal>$sysconfdir</literal> defaulting to /etc. + </para> + </listitem> + <listitem> + <para> + A user specific version of the configuration file may be created in + <literal>$XDG_CONFIG_HOME</literal>/subdir/filename, taking into + account the default value for <literal>$XDG_CONFIG_HOME</literal> if + <literal>$XDG_CONFIG_HOME</literal> is not set. + </para> + </listitem> + <listitem> + <para> + Lookups of the configuration file should search for ./subdir/filename relative to + all base directories indicated by <literal>$XDG_CONFIG_HOME</literal> and + <literal>$XDG_CONFIG_DIRS</literal> . If an environment + variable is either not set or empty, its default value as defined by this specification + should be used instead. + </para> + </listitem> + </itemizedlist> + </para> + <para> + If, when attempting to write a file, the destination + directory is non-existant an attempt should be made to create it + with permission <literal>0700</literal>. If the destination directory + exists already the permissions should not be changed. + The application should be prepared to handle the case where the file + could not be written, either because the directory was non-existant + and could not be created, or for any other reason. In such case it + may chose to present an error message to the user. + </para> + <para> + When attempting to read a file, if for any reason a file in a certain + directory is unaccessible, e.g. because the directory is non-existant, + the file is non-existant or the user is not authorized to open the file, + then the processing of the file in that directory should be skipped. + If due to this a required file could not be found at all, the + application may chose to present an error message to the user. + </para> + <para> + A specification that refers to <literal>$XDG_DATA_DIRS</literal> or + <literal>$XDG_CONFIG_DIRS</literal> should define what the behaviour + must be when a file is located under multiple base directories. + It could, for example, define that only the file under the most + important base directory should be used or, as another example, + it could define rules for merging the information from the different + files. + </para> + </sect1> + +</article> diff --git a/clipboard/clipboard-extensions.txt b/clipboard/clipboard-extensions.txt new file mode 100644 index 0000000..ceed6ca --- /dev/null +++ b/clipboard/clipboard-extensions.txt @@ -0,0 +1,39 @@ + + Selection target _NET_MAX_SELECTION_SIZE + + When a client encounters target _NET_MAX_SELECTION_SIZE in + SelectionRequest event, it should use its value as a limit for the + following targets in the same request (i.e. the request should be of type + MULTIPLE). The + _NET_MAX_SELECTION_SIZE target should be always the first target in the + MULTIPLE request. + + The target _NET_MAX_SELECTION_SIZE is a side-effect target, as described + in ICCCM section 2.6.3. When handling this target, the matching property on + the requestor window should be of type XA_INTEGER, format 32, with 2 + elements. + + If the selection owner's connection to the X server is local, the first + element is used as the limit, otherwise the second element is used as the + limit. A local connection is identified by a value of XDisplayString() with + the first character ':', for example, ":0.0". A value of -1 for either + element means no limit. + + The value should limit the sum of the sizes in the request, not separately + each of them. The client should reject subsequent targets if they would + cause the total amount of data transferred for all targets to exceed the + limit. Note that there is no requirement that if one target is rejected, + all other targets will be rejected or all that subsequent targets will be + rejected. + + Clients are not required to limit the data size precisely to the given + value. If the computation of the data size would be expensive for the + client, a certain reasonable inaccurancy is allowed. In other words, if the + client for various reasons doesn't know exact size of the data to be + transfered, it should try to estimate it, rather than transfering data with + size that is possibly magnitudes larger. + + The intent of this target is to avoid unwanted large transfers, so it + should be requsted only by xclipboard-like tools. They should use a request + of type MULTIPLE with _NET_MAX_SELECTION_SIZE as the first target in the + MULTIPLE request, with the requested target(s) after it. diff --git a/clipboard/clipboards.txt b/clipboard/clipboards.txt new file mode 100644 index 0000000..610083e --- /dev/null +++ b/clipboard/clipboards.txt @@ -0,0 +1,123 @@ +Historically, X clients have not handled cut-and-paste in a consistent +way, leading users to believe that X doesn't even have a working +clipboard. This isn't really accurate; there is a conventional +behavior, somewhat standardized in the ICCCM. But many apps don't +follow the conventional behavior. + +X has a thing called "selections" which are just clipboards, +essentially (implemented with an asynchronous protocol so you don't +actually copy data to them). There are three standard selections +defined in the ICCCM: PRIMARY, SECONDARY, and CLIPBOARD. + +The ICCCM defines these as follows: + + "The selection named by the atom PRIMARY is used for all com- + mands that take only a single argument and is the principal + means of communication between clients that use the selec- + tion mechanism. + + The selection named by the atom SECONDARY is used: + + o As the second argument to commands taking two arguments + (for example, "exchange primary and secondary selec- + tions") + + o As a means of obtaining data when there is a primary + selection and the user does not want to disturb it + + The selection named by the atom CLIPBOARD is used to hold + data that is being transferred between clients, that is, + data that usually is being cut and then pasted or copied and + then pasted." + +In addition, the ICCCM has a thing called "cut buffers" which most +clients no longer support. + +There are two historical interpretations of the ICCCM: + + a) use PRIMARY for mouse selection, middle mouse button paste, and + explicit cut/copy/paste menu items (Qt 2, GNU Emacs 20) + b) use CLIPBOARD for the Windows-style cut/copy/paste menu items; + use PRIMARY for the currently-selected text, even if it isn't + explicitly copied, and for middle-mouse-click (Netscape, Mozilla, + XEmacs, some GTK+ apps) + +No one ever does anything interesting with SECONDARY as far as I can +tell. + +The current consensus is that interpretation b) is correct. Qt 3 and +GNU Emacs 21 will use interpretation b), changing the behavior of +previous versions. + +The correct behavior can be summarized as follows: CLIPBOARD works +just like the clipboard on Mac or Windows; it only changes on explicit +cut/copy. PRIMARY is an "easter egg" for expert users, regular users +can just ignore it; it's normally pastable only via +middle-mouse-click. + +The rationale for this behavior is mostly that behavior a) has a lot +of problems, namely: + + - inconsistent with Mac/Windows + - confusingly, selecting anything overwrites the clipboard + - not efficient with a tool such as xclipboard + - you should be able to select text, then paste the clipboard + over it, but that doesn't work if the selection and + clipboard are the same + - the Copy menu item is useless and does nothing, + which is confusing + - if you think of PRIMARY as the current selection, + Cut doesn't make any sense since the selection simultaneously + disappears and becomes the current selection + +Application authors should follow the following guidelines to get +correct behavior: + + - selecting but with no explicit copy should only set PRIMARY, + never CLIPBOARD + + - middle mouse button should paste PRIMARY, never CLIPBOARD + + - explicit cut/copy commands (i.e. menu items, toolbar buttons) + should always set CLIPBOARD to the currently-selected data (i.e. + conceptually copy PRIMARY to CLIPBOARD) + + - explicit cut/copy commands should always set both CLIPBOARD and + PRIMARY, even when copying doesn't involve a selection (e.g. a + "copy url" -option which explicitly copies an url without the + url being selected first) + + - explicit paste commands should paste CLIPBOARD, not PRIMARY + + - a selection becoming unselected should never unset PRIMARY + + - possibly contradicting the ICCCM, clients don't need to support + SECONDARY, though if anyone can figure out what it's good + for they should feel free to use it for that + + - cut buffers are evil; they only support ASCII, they don't + work with many clients, and they require data to be + copied to the X server. Therefore clients should avoid + using cut buffers and use only selections. + +Apps that follow these guidelines give users a simple mental model to +understand what's going on. PRIMARY is the current selection. Middle +button pastes the current selection. CLIPBOARD is just like on +Mac/Windows. You don't have to know about PRIMARY if you're a newbie. + +I don't think there's a sane mental model if we collapse everything +into PRIMARY and ignore clipboard, see rationale above. + +A remaining somewhat odd thing about X selections is that exiting the +app you did a cut/copy from removes the cut/copied data from the +clipboard, since the selection protocol is asynchronous and requires +the source app to provide the data at paste time. The solution here +would be a standardized protocol for a "clipboard daemon" so that apps +could hand off their data to a daemon when they exit. Or +alternatively, you can run an application such as xclipboard which +constantly "harvests" clipboard selections. + +References: + - the ICCCM, obviously + - http://www.xfree86.org/~keithp/talks/selection.ps + - http://www.jwz.org/doc/x-cut-and-paste.html diff --git a/desktop-entry/.cvsignore b/desktop-entry/.cvsignore new file mode 100644 index 0000000..e2bf8b5 --- /dev/null +++ b/desktop-entry/.cvsignore @@ -0,0 +1,2 @@ +*.ps +*.html diff --git a/desktop-entry/ChangeLog b/desktop-entry/ChangeLog new file mode 100644 index 0000000..7113101 --- /dev/null +++ b/desktop-entry/ChangeLog @@ -0,0 +1,182 @@ +2008-09-12 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: reword sentence about characters allowed in + key names to avoid some ambiguity. + Patch by Simon McVittie <simon.mcvittie@collabora.co.uk> + +2008-03-04 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: bump version to 1.1-draft, so we can publish + it. See http://bugs.freedesktop.org/show_bug.cgi?id=14097 + +2007-09-10 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: fix Icon key in example: it was using the + .png extension for an icon name. Which is wrong :-) + +2007-07-27 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: don't say that the files are encoded as + lines of 8-bit characters, which is wrong for UTF-8. Use something a + bit better proposed by Matthias Clasen <mclasen@redhat.com> + Bug #11417. + +2007-05-30 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: s/DESKTOP_LAUNCH_ID/DESKTOP_STARTUP_ID/ + Thanks to Dan Winship <danw@gnome.org> for catching this. + Bug #11081. + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: scanf behavior is locale-dependent, and the + numeric type shouldn't be. Specify that the value is a floating point + number as recognized by scanf in the C locale. + Thanks to Dan Winship <danw@gnome.org> for catching this. + http://lists.freedesktop.org/archives/xdg/2007-April/009732.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: clarify description for the TryExec key. + http://lists.freedesktop.org/archives/xdg/2007-March/009556.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: change "the $PATH" to "the $PATH environment + variable". + http://lists.freedesktop.org/archives/xdg/2007-March/009552.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: improve the description of the Comment key. + http://lists.freedesktop.org/archives/xdg/2007-March/009440.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: a desktop file of type Application should + always have an Exec key. Same for Link Type and URL key. + http://lists.freedesktop.org/archives/xdg/2007-March/009437.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: desktop files of type Directory have a + .directory extension right now (at least in GNOME), but according to + the spec, this is wrong. The patch fixes this. Also, it removes a + small part of text explaining the name of a desktop file describing a + directory. + http://lists.freedesktop.org/archives/xdg/2007-March/009437.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml:clarify a bit the text about keys that only + makes sense in a specific context. Also, state that the keys should + not be used outside of this context. For example, the URL key should + not be present if the type is not Link. + http://lists.freedesktop.org/archives/xdg/2007-March/009437.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: small typo + http://lists.freedesktop.org/archives/xdg/2007-March/009437.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: this changes the type of the version from + numeric to string. It's needed if we consider the possibility that + there are some desktop entry files out there using 0.9.x as a value + for this key. The change doesn't break anything. + http://lists.freedesktop.org/archives/xdg/2007-March/009437.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: UnmountIcon is a localestring key. + http://lists.freedesktop.org/archives/xdg/2007-March/009437.html + +2007-04-28 Vincent Untz <vuntz@gnome.org> + + * desktop-entry-spec.xml: clarify that lists should always end with a + semicolon, even if there's only one value. + http://lists.freedesktop.org/archives/xdg/2007-March/009437.html + +2007-02-06 Waldo Bastian <waldo.bastian@intel.com> + * Clearify that %U may result in either local paths or file: URLs + * Deprecate %d, %n, %D and %N. They aren't usable on Gnome and + you can do the same with dirname and basename in a script. + * Clearify that %f, %u, %F or %U should only be used once. + * Clearify that these codes should be ignored if there is no file + to open. + * Forbid the use of field codes in quoted arguments. + * Clearify that %F and %U should only be used as a stand alone argument. + * Bumped version to 1.0 + +2006-10-30 Waldo Bastian <waldo.bastian@intel.com> + * Remove equal sign from reserved characters in Exec args + * Add backslash to list of reserved characters in Exec args + +2006-10-04 Waldo Bastian <waldo.bastian@intel.com> + * Deprecate %v, it is FSDevice specific + +2006-08-30 Waldo Bastian <waldo.bastian@intel.com> + * list FSDevice type as KDE specific + * refer to Icon Theme Specification + +2006-08-22 Waldo Bastian <waldo.bastian@intel.com> + * clarification of Exec key + * correction of StartupWMClass, clarify StartupNotify (Lubos Lunak) + * deprecate SortOrder and FilePattern key (Vincent Untz) + * remove section on "MIME Type caching" from spec (Vincent Untz) + * groups and keys must be unique (Vincent Untz) + See http://lists.freedesktop.org/archives/xdg/2006-August/008446.html + +2006-05-28 Vincent Untz <vuntz@gnome.org> + * cleanup of text and some reorg for clearity + * move all of the legacy-mixed encoding stuff to the appendix + * deprecate the Swallow* keys + * improve definition of group headers + * reorder the list of standard keys so they are sorted by type + See http://lists.freedesktop.org/archives/xdg/2006-May/008131.html + +Tue Jul 13 18:04:11 2004 Jonathan Blandford <jrb@gnome.org> + + * desktop-entry-spec.xml: Update the MIME description to make it + more relevent. + +2004-04-19 Mark McLoughlin <mark@skynet.ie> + + Pointed out by Ville Skyttä <ville.skytta@iki.fi> + + * desktop-entry-spec.xml: fix minor typo. + +2004-04-18 Mark McLoughlin <mark@skynet.ie> + + Patch from Ville Skyttä <ville.skytta@iki.fi> + + * desktop-entry-spec.xml: editorial changes, fixes for + typos and general cleanups. + +Mon Jul 7 18:26:14 2003 Owen Taylor <otaylor@redhat.com> + + * destop-entry-spec.sgml: Merge changes by Havoc + Pennington that had been made in web module: + + 2002/04/20: add changes posted to xdg-list a while back + +Sat Aug 24 17:00:48 2002 Owen Taylor <otaylor@redhat.com> + + * desktop-entry-spec.sgml: In legacy-mixed table, fix duplicate + pt entry, language code for Armenian. Make explicit that + language-country locale tags can match a single language in + the table. (Pablo Saratxaga) + +Tue Mar 13 12:37:03 2001 Owen Taylor <otaylor@redhat.com> + + * 0.9.3 + + * Reworked the description of encoding handling for + Legacy-Mixed for clarity and added a bit more details + on how encoding-matching should be done. + +Thu Mar 8 17:42:05 2001 Owen Taylor <otaylor@redhat.com> + + * Import into CVS. + diff --git a/desktop-entry/desktop-entry-spec.xml b/desktop-entry/desktop-entry-spec.xml new file mode 100644 index 0000000..7d99d0a --- /dev/null +++ b/desktop-entry/desktop-entry-spec.xml @@ -0,0 +1,1392 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ + ]> +<article id="index"> + <articleinfo> + <title>Desktop Entry Specification</title> + <releaseinfo>Version 1.1-draft</releaseinfo> + <date>4 Mar 2008</date> + <authorgroup> + <author> + <firstname>Preston</firstname> + <surname>Brown</surname> + <affiliation> + <address> + <email>pbrown@kde.org</email> + </address> + </affiliation> + </author> + <author> + <firstname>Jonathan</firstname> + <surname>Blandford</surname> + <affiliation> + <address> + <email>jrb@redhat.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Owen</firstname> + <surname>Taylor</surname> + <affiliation> + <address> + <email>otaylor@gtk.org</email> + </address> + </affiliation> + </author> + <author> + <firstname>Vincent</firstname> + <surname>Untz</surname> + <affiliation> + <address> + <email>vuntz@gnome.org</email> + </address> + </affiliation> + </author> + <author> + <firstname>Waldo</firstname> + <surname>Bastian</surname> + <affiliation> + <address> + <email>waldo.bastian@intel.com</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + <para> + Both the KDE and GNOME desktop environments have adopted a similar + format for "desktop entries", or configuration files describing how a + particular program is to be launched, how it appears in menus, etc. + It is to the larger community's benefit that a unified standard be + agreed upon by all parties such that interoperation between the two + environments, and indeed any additional environments that implement + the specification, becomes simpler. + </para> + </sect1> + <sect1 id="basic-format"> + <title>Basic format of the file</title> + <para> + Desktop entry files should have the <filename>.desktop</filename> + extension, except for files of <varname>Type</varname> + <constant>Directory</constant> which should have the + <filename>.directory</filename> extension. Determining file type on basis + of extension makes determining the file type very easy and quick. + When no file extension is present, the desktop system should + fall back to recognition via "magic detection". + </para> + <para> + Desktop entry files are encoded in UTF-8. A file is interpreted as a + series of lines that are separated by linefeed characters. Case is + significant everywhere in the file. + </para> + <para> + Compliant implementations MUST not remove any fields from the file, + even if they don't support them. Such fields must be maintained in a + list somewhere, and if the file is "rewritten", they will be included. + This ensures that any desktop-specific extensions will be preserved + even if another system accesses and changes the file. + </para> + <sect2 id="comments"> + <title>Comments</title> + <para> + Lines beginning with a <literal>#</literal> and blank lines are + considered comments and will be ignored, however they should be + preserved across reads and writes of the desktop entry file. + </para> + <para> + Comment lines are uninterpreted and may contain any character + (except for LF). However, using UTF-8 for comment lines that + contain characters not in ASCII is encouraged. + </para> + </sect2> + <sect2 id="group-header"> + <title>Group headers</title> + <para> + A group header with name <literal>groupname</literal> is a line in the + format: + </para> + <programlisting>[groupname]</programlisting> + <para> + Group names may contain all ASCII characters except for + <literal>[</literal> and <literal>]</literal> and control characters. + </para> + <para> + Multiple groups may not have the same name. + </para> + <para> + All <literal>{key,value}</literal> pairs following a group header until + a new group header belong to the group. + </para> + <para> + The basic format of the desktop entry file requires that there be + a group header named <literal>Desktop Entry</literal>. There may + be other groups present in the file, but this is the most + important group which explicitly needs to be supported. This + group should also be used as the "magic key" for automatic MIME + type detection. There should be nothing preceding this group in + the desktop entry file but possibly one or more comments. + </para> + </sect2> + <sect2 id="entries"> + <title>Entries</title> + <para> + Entries in the file are <literal>{key,value}</literal> pairs in the + format: + </para> + <programlisting>Key=Value</programlisting> + <para> + Space before and after the equals sign should be ignored; the + <literal>=</literal> sign is the actual delimiter. + </para> + <para> + Only the characters <literal>A-Za-z0-9-</literal> may be used in + key names. + </para> + <para> + As the case is significant, the keys <varname>Name</varname> and + <varname>NAME</varname> are not equivalent. + </para> + <para> + Multiple keys in the same group may not have the same name. Keys in + different groups may have the same name. + </para> + </sect2> + </sect1> + <sect1 id="value-types"> + <title>Possible value types</title> + <para> + The value types recognized are <literal>string</literal>, + <literal>localestring</literal>, + <literal>boolean</literal>, and + <literal>numeric</literal>. + </para> + <itemizedlist> + <listitem> + <para> + Values of type <literal>string</literal> may contain all ASCII + characters except for control characters. + </para> + </listitem> + <listitem> + <para> + Values of type <literal>localestring</literal> are user displayable, + and are encoded in UTF-8. + </para> + </listitem> + <listitem> + <para> + Values of type <literal>boolean</literal> must either be the string + <literal>true</literal> or <literal>false</literal>. + </para> + </listitem> + <listitem> + <para> + Values of type <literal>numeric</literal> must be a valid floating + point number as recognized by the <literal>%f</literal> specifier for + <function>scanf</function> in the <literal>C</literal> locale. + </para> + </listitem> + </itemizedlist> + <para> + The escape sequences <literal>\s</literal>, <literal>\n</literal>, + <literal>\t</literal>, <literal>\r</literal>, and + <literal>\\</literal> are supported for values of type + <literal>string</literal> and <literal>localestring</literal>, meaning + ASCII space, newline, tab, carriage return, and backslash, respectively. + </para> + <para> + Some keys can have multiple values. In such a case, the value of the key + is specified as a plural: for example, <literal>string(s)</literal>. The + multiple values should be separated by a semicolon, and the value of the + key should have a semicolon as trailing character. Semicolons in these + values need to be escaped using <literal>\;</literal>. + </para> + </sect1> + <sect1 id="localized-keys"> + <title>Localized values for keys</title> + <para> + Keys with type <literal>localestring</literal> may be postfixed by + [<replaceable>LOCALE</replaceable>], + where <replaceable>LOCALE</replaceable> is the locale type of the + entry. <replaceable>LOCALE</replaceable> must be of the form + <literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable>.<replaceable>ENCODING</replaceable>@<replaceable>MODIFIER</replaceable></literal>, + where + <literal>_<replaceable>COUNTRY</replaceable></literal>, + <literal>.<replaceable>ENCODING</replaceable></literal>, + and <literal>@<replaceable>MODIFIER</replaceable></literal> + may be omitted. If a postfixed key occurs, the same + key must be also present without the postfix. + </para> + <para> + When reading in the desktop entry file, the value of the key is + selected by matching the current POSIX locale for the + <varname>LC_MESSAGES</varname> category against the + <replaceable>LOCALE</replaceable> postfixes of all occurrences + of the key, with the + <literal>.<replaceable>ENCODING</replaceable></literal> part + stripped. + </para> + <para> + The matching is done as follows. If + <varname>LC_MESSAGES</varname> is of the form + <literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable>.<replaceable>ENCODING</replaceable>@<replaceable>MODIFIER</replaceable></literal>, + then it will match a key of the form + <literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable>@<replaceable>MODIFIER</replaceable></literal>. + If such a key does not exist, it will attempt to match + <literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable></literal> + followed by + <literal><replaceable>lang</replaceable>@<replaceable>MODIFIER</replaceable></literal>. + Then, a match against <replaceable>lang</replaceable> by itself + will be attempted. Finally, if no matching key is found the + required key without a locale specified is used. The encoding + from the <varname>LC_MESSAGES</varname> value is ignored + when matching. + </para> + <para> + If <varname>LC_MESSAGES</varname> does not have a <replaceable>MODIFIER</replaceable> + field, then no key with a modifier will be matched. Similarly, if + <varname>LC_MESSAGES</varname> does not have a <replaceable>COUNTRY</replaceable> + field, then no key with a country specified will be matched. If + <varname>LC_MESSAGES</varname> just has a <replaceable>lang</replaceable> field, then + it will do a straight match to a key with a similar value. The + following table lists possible matches of various <varname>LC_MESSAGES</varname> values in + the order in which they are matched. Note that the + <replaceable>ENCODING</replaceable> field isn't shown. + </para> + <table> + <title>Locale Matching</title> + <tgroup cols="2"> +<thead> + <row> + <entry><varname>LC_MESSAGES</varname> value</entry> + <entry>Possible keys in order of matching</entry> + </row> +</thead> +<tbody> + <row> + <entry><literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable>@<replaceable>MODIFIER</replaceable></literal></entry> + <entry> + <literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable>@<replaceable>MODIFIER</replaceable></literal>, + <literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable></literal>, + <literal><replaceable>lang</replaceable>@<replaceable>MODIFIER</replaceable></literal>, + <literal><replaceable>lang</replaceable></literal>, + default value + </entry> + </row> + <row> + <entry><literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable></literal></entry> + <entry> + <literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable></literal>, + <replaceable>lang</replaceable>, + default value + </entry> + </row> + <row> + <entry><literal><replaceable>lang</replaceable>@<replaceable>MODIFIER</replaceable></literal></entry> + <entry> + <literal><replaceable>lang</replaceable>@<replaceable>MODIFIER</replaceable></literal>, + <replaceable>lang</replaceable>, + default value + </entry> + </row> + <row> + <entry><replaceable>lang</replaceable></entry> + <entry> + <replaceable>lang</replaceable>, + default value + </entry> + </row> +</tbody> + </tgroup> + </table> + + <para> + For example, if the current value of the <varname>LC_MESSAGES</varname> category + is <literal>sr_YU@Latn</literal> and the desktop file includes: + </para> + <programlisting> + Name=Foo + Name[sr_YU]=... + Name[sr@Latn]=... + Name[sr]=...</programlisting> + <para> + then the value of the <varname>Name</varname> keyed by <literal>sr_YU</literal> is used. + </para> + </sect1> + <sect1 id="recognized-keys"> + <title>Recognized desktop entry keys</title> + <para> + Keys are either OPTIONAL or REQUIRED. If a key is OPTIONAL it may or + may not be present in the file. However, if it isn't, the + implementation of the standard should not blow up, it must provide + some sane defaults. + </para> + <para> + Some keys only make sense in the context when another particular key + is also present and set to a specific value. Those keys should not be + used if the particular key is not present or not set to the specific + value. For example, the <varname>Terminal</varname> key can only be used + when the value of the <varname>Type</varname> key is + <constant>Application</constant>. + </para> + <para> + If a REQUIRED key is only valid in the context of another key set to a + specific value, then it has to be present only if the other key is set to + the specific value. For example, the <varname>URL</varname> key has to be + present when and only when when the value of the <varname>Type</varname> + key is <constant>Link</constant>. + </para> + <para> + Some example keys: <varname>Name[C]</varname>, <varname>Comment[it]</varname>. + </para> + <table> + <title>Standard Keys</title> + <tgroup cols="5"> + <thead> + <row> + <entry>Key</entry> + <entry>Description</entry> + <entry>Value Type</entry> + <entry>REQ?</entry> + <entry>Type</entry> + </row> + </thead> + <tbody> + <row> + <entry id="key-type"><varname>Type</varname></entry> + <entry> + This specification defines 3 types of desktop entries: + <constant>Application</constant> (type 1), + <constant>Link</constant> (type 2) + and <constant>Directory</constant> (type 3). + To allow the addition of new types in the future, + implementations should ignore desktop entries with an + unknown type. + </entry> + <entry>string</entry> + <entry>YES</entry> + </row> + <row> + <entry id="key-version"><varname>Version</varname></entry> + <entry> + Version of the Desktop Entry Specification that the + desktop entry conforms with. Entries that confirm with this + version of the specification should use <literal>1.0</literal>. + Note that the version field is not required to be present. + </entry> + <entry>string</entry> + <entry>NO</entry> + <entry>1-3</entry> + </row> + <row> + <entry id="key-name"><varname>Name</varname></entry> + <entry> + Specific name of the application, for example "Mozilla". + </entry> + <entry>localestring</entry> + <entry>YES</entry> + <entry>1-3</entry> + </row> + <row> + <entry id="key-genericname"><varname>GenericName</varname></entry> + <entry> + Generic name of the application, for example "Web Browser". + </entry> + <entry>localestring</entry> + <entry>NO</entry> + <entry>1-3</entry> + </row> + <row> + <entry id="key-nodisplay"><varname>NoDisplay</varname></entry> + <entry> + <varname>NoDisplay</varname> means "this application exists, but don't display it in the menus". + This can be useful to e.g. associate this application with MIME types, so that + it gets launched from a file manager (or other apps), without having a menu + entry for it (there are tons of good reasons for this, including e.g. the + <literal>netscape -remote</literal>, or <literal>kfmclient openURL</literal> kind of stuff). + </entry> + <entry>boolean</entry> + <entry>NO</entry> + <entry>1-3</entry> + </row> + <row> + <entry id="key-comment"><varname>Comment</varname></entry> + <entry> + Tooltip for the entry, for example "View sites on the + Internet". The value should not be redundant with the values of + <varname>Name</varname> and <varname>GenericName</varname>. + </entry> + <entry>localestring</entry> + <entry>NO</entry> + <entry>1-3</entry> + </row> + <row> + <entry id="key-icon"><varname>Icon</varname></entry> + <entry> + Icon to display in file manager, menus, etc. If the + name is an absolute path, the given file will be + used. If the name is not an absolute path, the algorithm described + in the <ulink + url="http://freedesktop.org/wiki/Standards/icon-theme-spec">Icon + Theme Specification</ulink> will be used to locate the icon. + </entry> + <entry>localestring</entry> + <entry>NO</entry> + <entry>1-3</entry> + </row> + <row> + <entry id="key-hidden"><varname>Hidden</varname></entry> + <entry> + <varname>Hidden</varname> should have been called <varname>Deleted</varname>. + It means the user deleted (at his level) + something that was present (at an upper level, e.g. in the system dirs). It's + strictly equivalent to the <filename>.desktop</filename> file not existing at all, as far as that user is + concerned. This can also be used to "uninstall" existing files (e.g. due to a renaming) + - by letting <literal>make install</literal> install a file with <literal>Hidden=true</literal> in it. + </entry> + <entry>boolean</entry> + <entry>NO</entry> + <entry>1-3</entry> + </row> + <row> + <entry id="key-onlyshowin"><varname>OnlyShowIn</varname>, <varname>NotShowIn</varname></entry> + <entry> + A list of strings identifying the environments that should + display/not display a given desktop entry. Only one of + these keys, either <varname>OnlyShowIn</varname> or + <varname>NotShowIn</varname>, may appear in a group (for + possible values see the <ulink + url="http://www.freedesktop.org/Standards/menu-spec">Desktop + Menu Specification</ulink>). + </entry> + <entry>string(s)</entry> + <entry>NO</entry> + <entry>1-3</entry> + </row> + <row> + <entry id="key-tryexec"><varname>TryExec</varname></entry> + <entry> + Path to an executable file on disk used to determine if the program + is actually installed. If the path is not an absolute path, the file + is looked up in the $PATH environment variable. If the file is not + present or if it is not executable, the entry may be ignored (not be + used in menus, for example). + </entry> + <entry>string</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-exec"><varname>Exec</varname></entry> + <entry> + Program to execute, possibly with arguments. See the <link + linkend="exec-variables"><varname>Exec</varname> key</link> for + details on how this key works. + </entry> + <entry>string</entry> + <entry>YES</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-path"><varname>Path</varname></entry> + <entry> + If entry is of type <constant>Application</constant>, the working directory to run the program in. + </entry> + <entry>string</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-terminal"><varname>Terminal</varname></entry> + <entry> + Whether the program runs in a terminal window. + </entry> + <entry>boolean</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-actions"><varname>Actions</varname></entry> + <entry> + Identifiers for application actions. This can be used to tell the + application to make a specific action, different from the default + behavior. The <link linkend="extra-actions">Application actions</link> + section describes how actions work. + </entry> + <entry>string(s)</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-mimetype"><varname>MimeType</varname></entry> + <entry> + The MIME type(s) supported by this application. + </entry> + <entry>string(s)</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-categories"><varname>Categories</varname></entry> + <entry> + Categories in which the entry should be shown in a menu (for + possible values see the <ulink + url="http://www.freedesktop.org/Standards/menu-spec">Desktop + Menu Specification</ulink>). + </entry> + <entry>string(s)</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-keywords"><varname>Keywords</varname></entry> + <entry> + A list of strings which may be used in addition to other + metadata to describe this entry. This can be useful e.g. to + facilitate searching through entries. The values are not meant + for display, and should not be redundant with the values of + <varname>Name</varname> or <varname>GenericName</varname>. + </entry> + <entry>localestring(s)</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-startupnotify"><varname>StartupNotify</varname></entry> + <entry> + If true, it is KNOWN that the application will send a "remove" + message when started with the DESKTOP_STARTUP_ID environment variable set. + If false, it is KNOWN that the application does not work + with startup notification at all (does not shown any window, breaks + even when using StartupWMClass, etc.). + If absent, a reasonable handling is up to implementations (assuming false, + using StartupWMClass, etc.). (See the <ulink url="http://www.freedesktop.org/Standards/startup-notification-spec">Startup Notification Protocol Specification</ulink> for more details). + </entry> + <entry>boolean</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-startupwmclass"><varname>StartupWMClass</varname></entry> + <entry> + If specified, it is known that the application will map at least one + window with the given string as its WM class or WM name hint (see the <ulink url="http://www.freedesktop.org/Standards/startup-notification-spec">Startup Notification Protocol Specification</ulink> for more details). + </entry> + <entry>string</entry> + <entry>NO</entry> + <entry>1</entry> + </row> + <row> + <entry id="key-url"><varname>URL</varname></entry> + <entry> + If entry is Link type, the URL to access. + </entry> + <entry>string</entry> + <entry>YES</entry> + <entry>2</entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + <sect1 id="exec-variables"> + <title>The <varname>Exec</varname> key</title> + <para> + The <varname>Exec</varname> key must contain a command line. + A command line consists of an executable program optionally followed + by one or more arguments. + The executable program can either be specified with its full path or + with the name of the executable only. If no full path is provided the + executable is looked up in the $PATH environment variable used by the + desktop environment. + The name or path of the executable program may not contain the equal + sign ("="). Arguments are separated by a space. + </para> + <para> + Arguments may be quoted in whole. If an argument contains a reserved + character the argument must be quoted. The rules for quoting of + arguments is also applicable to the executable name or path of the + executable program as provided. + </para> + <para> + Quoting must be done by enclosing the argument between double quotes + and escaping the double quote character, backtick character ("`"), + dollar sign ("$") and backslash character ("\") by preceding it with an + additional backslash character. Implementations must undo quoting before + expanding field codes and before passing the argument to the executable + program. Reserved characters are space (" "), tab, newline, double + quote, single quote ("'"), backslash character ("\"), + greater-than sign (">"), less-than sign ("<"), + tilde ("~"), vertical bar ("|"), ampersand ("&"), semicolon (";"), + dollar sign ("$"), asterisk ("*"), question mark ("?"), hash mark ("#"), + parenthesis ("(") and (")") and backtick character ("`"). + </para> + <para> + Note that the general escape rule for values of type string states that + the backslash character can be escaped as ("\\") as well and that this + escape rule is applied before the quoting rule. As such, to + unambiguously represent a literal backslash character in a quoted + argument in a desktop entry file requires the use of four successive + backslash characters ("\\\\"). Likewise, a literal dollar sign in a + quoted argument in a desktop entry file is unambiguously represented + with ("\\$"). + </para> + <para> + A number of special field codes have been defined which will be + expanded by the file manager or program launcher when encountered + in the command line. + Field codes consist of the percentage character ("%") followed by + an alpha character. Literal percentage characters must be escaped + as <literal>%%</literal>. + Deprecated field codes should be removed from the command line and + ignored. + Field codes are expanded only once, the string that is used to + replace the field code should not be checked for field codes itself. + </para> + <para> + Command lines that contain a field code that is not listed in this + specification are invalid and must not be processed, in particular + implementations may not introduce support for field codes not listed + in this specification. Extensions, if any, should be introduced by + means of a new key. + </para> + <para> + Implementations must take care not to expand field codes into multiple + arguments unless explicitly instructed by this specification. + This means that name fields, filenames and other replacements that + can contain spaces must be passed as a single argument + to the executable program after expansion. + </para> + <para> + Although the <varname>Exec</varname> key is defined to have a value + of the type string, which is limited to ASCII characters, field code + expansion may introduce non-ASCII characters in arguments. + Implementations must take care that all characters in arguments + passed to the executable program are properly encoded according to + the applicable locale setting. + </para> + <para> + Recognized field codes are as follows: + </para> + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>Code</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>%f</literal></entry> + <entry> + A single file name, even if multiple files are selected. The system + reading the desktop entry should recognize that the program in + question cannot handle multiple file arguments, and it should + should probably spawn and execute multiple copies of a program + for each selected file if the program is not able to handle + additional file arguments. If files are not on the local file system + (i.e. are on HTTP or FTP locations), the files will be copied to the local + file system and <literal>%f</literal> will be expanded to point at the temporary + file. Used for programs that do not understand the URL syntax. + </entry> + </row> + <row> + <entry><literal>%F</literal></entry> + <entry> + A list of files. Use for apps that can open several local + files at once. + Each file is passed as a separate argument to + the executable program. + </entry> + </row> + <row> + <entry><literal>%u</literal></entry> + <entry> + A single URL. Local files may either be passed as + file: URLs or as file path. + </entry> + </row> + <row> + <entry><literal>%U</literal></entry> + <entry> + A list of URLs. + Each URL is passed as a separate argument to + the executable program. Local files may either be passed as + file: URLs or as file path. + </entry> + </row> + <row> + <entry><literal>%d</literal></entry> + <entry> + Deprecated. + </entry> + </row> + <row> + <entry><literal>%D</literal></entry> + <entry> + Deprecated. + </entry> + </row> + <row> + <entry><literal>%n</literal></entry> + <entry> + Deprecated. + </entry> + </row> + <row> + <entry><literal>%N</literal></entry> + <entry> + Deprecated. + </entry> + </row> + <row> + <entry><literal>%i</literal></entry> + <entry> + The <varname>Icon</varname> key of the desktop entry + expanded as two arguments, first + <literal>--icon</literal> and then the value of the + <varname>Icon</varname> key. Should not expand to any + arguments if the <varname>Icon</varname> key is empty + or missing. + </entry> + </row> + <row> + <entry><literal>%c</literal></entry> + <entry> + The translated name of the application as listed in + the appropriate <varname>Name</varname> key in the + desktop entry. + </entry> + </row> + <row> + <entry><literal>%k</literal></entry> + <entry> + The location of the desktop file as either a URI (if for + example gotten from the vfolder system) or a local + filename or empty if no location is known. + </entry> + </row> + <row> + <entry><literal>%v</literal></entry> + <entry> + Deprecated. + </entry> + </row> + <row> + <entry><literal>%m</literal></entry> + <entry> + Deprecated. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + <para> + A command line may contain at most one %f, %u, %F or %U field code. + If the application should not open any + file the %f, %u, %F and %U field codes must be removed from the + command line and ignored. + </para> + <para> + Field codes must not be used inside a quoted argument, the result of + field code expansion inside a quoted argument is undefined. The %F and + %U field codes may only be used as an argument on their own. + </para> + </sect1> + <sect1 id="mime-types"> + <title>Registering MIME Types</title> + <para> + The <varname>MimeType</varname> key is used to indicate the MIME + Types that an application knows how to handle. It is expected that + for some applications this list could become long. An application + is expected to be able to reasonably open files of these types + using the command listed in the <varname>Exec</varname> key. + </para> + <para> + There should be no priority for MIME Types in this field, or any + form of priority in the desktop file. Priority for applications + is handled external to the <filename>.desktop</filename> files. + </para> +<!-- + <sect2 id="mime-caching"> + <title>Caching MIME Types</title> + <para> + To make parsing of all the desktop files less costly, a + <command>update-desktop-database</command> program is provided + that will generate a cache file. The concept is identical to + that of the 'update-mime-database' program in that it lets + applications avoid reading in (potentially) hundreds of files. + It will need to be run after every desktop file is installed. + One cache file is created for every directory in + $XDG_DATA_DIRS/applications/, and will create a file called + $XDG_DATA_DIRS/applications/mimeinfo.cache. + </para> + <para> + The format of the cache is similar to that of the desktop file, + and is just a list mapping mime-types to desktop files. Here's + a quick example of what it would look like: + </para> + <programlisting>application/x-foo=foo.desktop;bar.desktop; +application/x-bar=bar.desktop;</programlisting> + <para> + Each MIME Type is listed only once per cache file, and the + desktop-id is expected to exist in that particular directory. + That is to say, if the cache file is located at + <filename>/usr/share/applications/mimeinfo.cache</filename>, + bar.desktop refers to the file + <filename>/usr/share/applications/bar.desktop</filename>. + </para> + </sect2> + <sect2 id="mime-priority"> + <title>Priority of MIME Types and desktop files</title> + <para> + There is also a preference list to determine preferred + application of a given MIME Type. It defines the 'default' + application to handle a given MIME Type. It has the same format + as the cache list. + </para> + <programlisting>mime/type=desktop-id.desktop;</programlisting> + <para> + If a mime type is listed multiple times (either in the same + file, or in another file further down the search path), the + latter mention wins. If a listed file doesn't exist, or is + precluded through the <varname>OnlyShowIn</varname> or + <varname>NotShowIn</varname> keys, they should be ignored. + This means that applications will have to keep a history of the + preferred applications that they run into, so that if the top + desktop file for a given MIME Type isn't available, the second + one can be tested, etc. + </para> + <para> + It is also worth noting who this mechanism is defined for. It + is primarily intended for use by distributors/sysadmins to + provide a sane set of defaults for their users. Additionally, + users themselves can use this mechanism to override the user + defaults. We intentionally don't provide a way for application + authors themselves to list themselves as the default for a given + type, as we felt that that cannot work. + </para> + </sect2> +--> + </sect1> + <sect1 id="extra-actions"> + <title>Additional applications actions</title> + <para> + Desktop entries of type Application can include one or more actions. An + action represents an additional way to invoke the application. + Application launchers should expose them to the user (for example, as a + submenu) within the context of the application. This is used to build + so called "Quicklists" or "Jumplists". + </para> + <sect2 id="extra-actions-identifier"> + <title>Action identifier</title> + <para> + Each action is identified by a string, following the same format + as key names (see <xref linkend="entries"/>). Each identifier is associated + with an action group that must be present in the <filename>.desktop</filename> + file. The action group is a group named <varname>Desktop Action %s</varname>, + where <varname>%s</varname> is the action identifier. + </para> + <para> + It is not valid to have an action group for an action identifier not + mentioned in the <varname>Actions</varname> key. Such an action group + must be ignored by implementors. + </para> + </sect2> + <sect2 id="extra-actions-keys"> + <title>Action keys</title> + <para> + The following keys are supported within each action group. If a + REQUIRED key is not present in an action group, then the implementor + should ignore this action. + </para> + <table> + <title>Action Specific Keys</title> + <tgroup cols="5"> + <thead> + <row> + <entry>Key</entry> + <entry>Description</entry> + <entry>Value Type</entry> + <entry>REQ?</entry> + </row> + </thead> + <tbody> + <row> + <entry id="key-action-group-name"><varname>Name</varname></entry> + <entry> + Label that will be shown to the user. Since actions are + always shown in the context of a specific application (that is, as + a submenu of a launcher), this only needs to be unambiguous within + one application and should not include the application name. + </entry> + <entry>localestring</entry> + <entry>YES</entry> + </row> + <row> + <entry id="key-action-group-icon"><varname>Icon</varname></entry> + <entry> + Icon to be shown togheter with the action. If the name is + an absolute path, the given file will be used. If the name is not + an absolute path, the algorithm described in the <ulink + url="http://freedesktop.org/wiki/Standards/icon-theme-spec">Icon + Theme Specification</ulink> will be used to locate the icon. + Implementations may choose to ignore it. + </entry> + <entry>localestring</entry> + <entry>NO</entry> + </row> + <row> + <entry id="key-action-group-osi-nsi"> + <varname>OnlyShowIn</varname>, <varname>NotShowIn</varname> + </entry> + <entry> + A list of strings identifying the environments that should + display/not display this specific action. These keys are to be + interpreted in addition to the <varname>OnlyShowIn</varname> + and <varname>NotShowIn</varname> keys of the <varname>Desktop + Entry</varname> group, and are not replacing them. Only one of + these keys, either <varname>OnlyShowIn</varname> or + <varname>NotShowIn</varname>, may appear in each action group + (for possible values see the <ulink + url="http://www.freedesktop.org/Standards/menu-spec">Desktop + Menu Specification</ulink>). + </entry> + <entry>string(s)</entry> + <entry>NO</entry> + </row> + <row> + <entry id="key-action-group-exec"><varname>Exec</varname></entry> + <entry> + Program to execute for this action, possibly with arguments. + See the <link linkend="exec-variables"><varname>Exec</varname> + key</link> for details on how this key works. + </entry> + <entry>string</entry> + <entry>YES</entry> + </row> + </tbody> + </tgroup> + </table> + </sect2> + <sect2 id="extra-actions-implementation-notes"> + <title>Implementation notes</title> + <para> + Application actions should be supported by implementors. However, in + case they are not supported, implementors can simply ignore the + <varname>Actions</varname> key and the associated <varname>Desktop + Action</varname> action groups, and keep using the <varname>Desktop + Entry</varname> group: the primary way to describe and invoke the + application is through the Name, Icon and Exec keys from the + <varname>Desktop Entry</varname> group. + </para> + <para> + It is not expected that other desktop components showing application + lists (software installers, for instance) will provide any user + interface for these actions. Therefore applications must only include + actions that make sense as general launchers. + </para> + </sect2> + </sect1> + <sect1 id="extending"> + <title>Extending the format</title> + <para> + If the standard is to be amended with a new <literal>{key,value}</literal> pair which + should be applicable to all supporting parties, a group discussion + will take place. This is the preferred method for introducing + changes. If one particular party wishes to add a field for personal + use, they should prefix the key with the string <varname>X-<replaceable>PRODUCT</replaceable></varname>, + e.g. <varname>X-NewDesktop-Foo</varname>, following the precedent set by other IETF and RFC + standards. + </para> + <para> + Alternatively, fields can be placed in their own group, where they may + then have arbitrary key names. If this is the case, the group should + follow the scheme outlined above, + i.e. <literal>[X-<replaceable>PRODUCT</replaceable> + <replaceable>GROUPNAME</replaceable>]</literal> or + something similar. These steps will avoid namespace clashes between + different yet similar environments. + </para> + </sect1> + <appendix id="example"> + <title>Example Desktop Entry File</title> + <programlisting> +[Desktop Entry] +Version=1.0 +Type=Application +Name=Foo Viewer +Comment=The best viewer for Foo objects available! +TryExec=fooview +Exec=fooview %F +Icon=fooview +MimeType=image/x-foo; +Actions=Gallery;Create; + +[Desktop Action Gallery] +Exec=fooview --gallery +Name=Browse Gallery + +[Desktop Action Create] +Exec=fooview --create-new +Name=Create a new Foo! +Icon=fooview-new + </programlisting> + </appendix> + <appendix id="kde-items"> + <title>Currently reserved for use within KDE</title> + <para> + For historical reasons KDE is using some KDE-specific extensions + that are currently not prefixed by a <literal>X-KDE-</literal> prefix. + </para> + <itemizedlist> + <listitem> + <para> + KDE specific keys: <varname>ServiceTypes</varname>, + <varname>DocPath</varname>, <varname>InitialPreference</varname> + </para> + </listitem> + <listitem> + <para> + KDE specific types: <constant>ServiceType</constant>, + <constant>Service</constant> and <constant>FSDevice</constant> + </para> + </listitem> + </itemizedlist> + <para> + KDE also used the <varname>Keywords</varname> key before it was + standardized, using commas instead of semi-colons as separators. + At the time of standardization, the field had been prefixed with a + <literal>X-KDE</literal> prefix, but the Trinity fork still used + the non-prefixed variant. + </para> + <para> + KDE uses the following additional keys for desktop entries of the + <constant>FSDevice</constant> type. + </para> + <table> + <title>FSDevice Specific Keys</title> + <tgroup cols="3"> + <thead> + <row> + <entry>Key</entry> + <entry>Description</entry> + <entry>Value Type</entry> + </row> + </thead> + <tbody> + <row> + <entry id="key-dev"><varname>Dev</varname></entry> + <entry> + The device to mount. + </entry> + <entry>string</entry> + </row> + <row> + <entry id="key-fstype"><varname>FSType</varname></entry> + <entry> + The type of file system to try to mount. + </entry> + <entry>string</entry> + </row> + <row> + <entry id="key-mountpoint"><varname>MountPoint</varname></entry> + <entry> + The mount point of the device in question. + </entry> + <entry>string</entry> + </row> + <row> + <entry id="key-readonly"><varname>ReadOnly</varname></entry> + <entry> + Specifies whether or not the device is read only. + </entry> + <entry>boolean</entry> + </row> + <row> + <entry id="key-unmounticon"><varname>UnmountIcon</varname></entry> + <entry> + Icon to display when device is not mounted. Mounted devices display icon from the <varname>Icon</varname> key. + </entry> + <entry>localestring</entry> + </row> + </tbody> + </tgroup> + </table> + </appendix> + <appendix id="deprecated-items"> + <title>Deprecated Items</title> + <para> + As this standard is quite old there are some deprecated items that + may or may not be used by several implementations. + </para> + <itemizedlist> + <listitem> + <para> + <literal>Type=MimeType</literal> is deprecated as there is a + new standard for this now, see the <ulink + url="http://www.freedesktop.org/Standards/shared-mime-info-spec">Shared + MIME-info Database specification</ulink> for more + information. In consequence the Keys + <varname>Patterns</varname> (various file name extensions + associated with the MIME type) and + <varname>DefaultApp</varname> (the default application + associated with this MIME type) are also deprecated. + </para> + </listitem> + <listitem> + <para> + Using <filename>.kdelnk</filename> instead of + <filename>.desktop</filename> as the file extension is + deprecated. + </para> + </listitem> + <listitem> + <para> + Using <literal>[KDE Desktop Entry]</literal> instead of + <literal>[Desktop Entry]</literal> as header is deprecated. + </para> + </listitem> + <listitem> + <para> + The <literal>Encoding</literal> key is deprecated. It was used to + specify whether keys of type <literal>localestring</literal> were + encoded in UTF-8 or in the specified locale. Possible values are + <literal>UTF-8</literal> and <literal>Legacy-Mixed</literal>. See + <xref linkend="legacy-mixed"/> for more details. + </para> + </listitem> + <listitem> + <para> + Deprecated <varname>Exec</varname> field codes: + <literal>%m</literal> (the mini-icon associated with the + desktop entry, this should be expanded as two arguments, + <literal>--miniicon</literal> and the content of the + <varname>MiniIcon</varname> key, it can also be ignored by + expanding it to no arguments), %v (the device as listed + in the <varname>Dev</varname> key in the desktop file), + %d (the directory of a file), %D (the directories of + files), %n (the base name of a file) and %N (the base names + of files). + </para> + </listitem> + <listitem> + <para> + Deprecated keys: <varname>MiniIcon</varname> (small icon for + menus, etc.), <varname>TerminalOptions</varname> (if the + program runs in a terminal, any options that should be + passed to the terminal emulator before actually executing + the program), <varname>Protocols</varname>, + <varname>Extensions</varname>, + <varname>BinaryPattern</varname>, + <varname>MapNotify</varname>. + </para> + </listitem> + <listitem> + <para> + The <literal>SwallowTitle</literal> and + <literal>SwallowExec</literal> keys are deprecated. + The <literal>SwallowTitle</literal> key is of type + <literal>localestring</literal> and specifies the title of the window + if is swallowed onto the panel. The <literal>SwallowExec</literal> + key is of type <literal>string</literal> and specifies the + program to exec if swallowed app is clicked. + </para> + </listitem> + <listitem> + <para> + The <literal>SortOrder</literal> key is deprecated. It is of type + <literal>string(s)</literal> and may be used to specify the order in + which to display files. The <ulink + url="http://www.freedesktop.org/Standards/menu-spec">Desktop + Menu Specification</ulink> defines another mechanism for defining the + order of menu items. + </para> + </listitem> + <listitem> + <para> + The <literal>FilePattern</literal> key is deprecated. + The value is a list of regular + expressions to match against for a file manager to determine if this + entry's icon should be displayed. Usually simply the name of the main + executable and friends. + </para> + </listitem> + <listitem> + <para> + Historically some booleans have been represented by the numeric + entries <constant>0</constant> or <constant>1</constant>. With + this version of the standard they are now to be represented as a + boolean string. However, if an implementation is reading a pre-1.0 + desktop entry, it should interpret <constant>0</constant> and + <constant>1</constant> as <constant>false</constant> and + <constant>true</constant>, respectively. + </para> + </listitem> + <listitem> + <para> + Historically lists have been comma separated. This is inconsistent with other lists which are separated by a semicolon. When reading a pre-1.0 desktop entry, comma separated lists should continue to be supported. + </para> + </listitem> + </itemizedlist> + </appendix> + <appendix id="legacy-mixed"> + <title>The <constant>Legacy-Mixed</constant> Encoding (Deprecated)</title> + <para> + The <constant>Legacy-Mixed</constant> encoding corresponds to the + traditional encoding of desktop files in older versions of the GNOME and + KDE desktop files. In this encoding, the encoding of each + <literal>localestring</literal> key is determined by the locale tag for + that key, if any, instead of being UTF-8. For keys without a locale tag, + the value must contain only ASCII characters. + </para> + <para> + If the file specifies an unsupported encoding, the implementation + should either ignore the file, or, if the user has requested a direct + operation on the file (such as opening it for editing), display an + appropriate error indication to the user. + </para> + <para> + In the absence of an <varname>Encoding</varname> key, the implementation may choose + to autodetect the encoding of the file by using such factors + as: + </para> + <itemizedlist> + <listitem> + <para> + The location of the file on the file system + </para> + </listitem> + <listitem> + <para> + Whether the contents of the file are valid UTF-8 + </para> + </listitem> + </itemizedlist> + <para> + If the implementation does not perform such auto-detection, it should + treat a file without an <varname>Encoding</varname> key in the same way as a file with an + unsupported <varname>Encoding</varname> key. + </para> + <para> + If the locale tag includes an <literal>.<replaceable>ENCODING</replaceable></literal> part, then that determines + the encoding for the line. Otherwise, the encoding is determined + by the language, or + <literal><replaceable>lang</replaceable>_<replaceable>COUNTRY</replaceable></literal> + pair from the locale tag, according to the following table. + </para> + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>Encoding</entry> + <entry>Aliases</entry> + <entry>Tags</entry> + </row> + </thead> + <tbody> + <row> + <entry>ARMSCII-8 (*)</entry><entry></entry><entry>hy</entry> + </row><row> + <entry>BIG5</entry><entry></entry><entry>zh_TW</entry> + </row><row> + <entry>CP1251</entry><entry></entry><entry>be bg</entry> + </row><row> + <entry>EUC-CN</entry><entry>GB2312</entry><entry>zh_CN</entry> + </row><row> + <entry>EUC-JP</entry><entry></entry><entry>ja</entry> + </row><row> + <entry>EUC-KR</entry><entry></entry><entry>ko</entry> + </row><row> + <entry>GEORGIAN-ACADEMY (*)</entry><entry></entry><entry></entry> + </row><row> + <entry>GEORGIAN-PS (*)</entry><entry></entry><entry>ka</entry> + </row><row> + <entry>ISO-8859-1</entry><entry></entry><entry>br ca da de en es eu fi fr gl it nl no pt sv wa</entry> + </row><row> + <entry>ISO-8859-2</entry><entry></entry><entry>cs hr hu pl ro sk sl sq sr</entry> + </row><row> + <entry>ISO-8859-3 </entry><entry></entry><entry>eo</entry> + </row><row> + <entry>ISO-8859-5</entry><entry></entry><entry>mk sp</entry> + </row><row> + <entry>ISO-8859-7</entry><entry></entry><entry>el</entry> + </row><row> + <entry>ISO-8859-9</entry><entry></entry><entry>tr</entry> + </row><row> + <entry>ISO-8859-13</entry><entry></entry><entry>lt lv mi</entry> + </row><row> + <entry>ISO-8859-14</entry><entry></entry><entry>cy ga</entry> + </row><row> + <entry>ISO-8859-15</entry><entry></entry><entry>et</entry> + </row><row> + <entry>KOI8-R</entry><entry></entry><entry>ru</entry> + </row><row> + <entry>KOI8-U</entry><entry></entry><entry>uk</entry> + </row><row> + <entry>TCVN-5712 (*)</entry><entry>TCVN</entry><entry>vi</entry> + </row><row> + <entry>TIS-620</entry><entry></entry><entry>th</entry> + </row><row> + <entry>VISCII</entry><entry></entry><entry></entry> + </row> + </tbody> + </tgroup> + </informaltable> + <variablelist> + <varlistentry> + <term>Encoding</term> + <listitem> + <para> + The name given here is listed here is typically the + canonical name for the encoding in the GNU C Library's + <function>iconv</function> facility. Encodings marked with (*) are not + currently supported by the GNU C Library; for this reason, + implementations may choose to ignore lines in desktop + files that resolve to this encoding. Desktop files with + these encodings are currently rare or non-existent. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Aliases</term> + <listitem> + <para> + Other names for the encoding found in existing desktop + files. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Tags</term> + <listitem> + <para> + Language tags for which this is the default encoding. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + This table above covers all tags and encodings that are known to + be currently in use. Implementors may choose to support + encodings not in the above set. For tags without defaults listed + in the above table, desktop file creators must specify the + <literal>.<replaceable>ENCODING</replaceable></literal> part of the locale tag. + </para> + <para> + Matching the <literal>.<replaceable>ENCODING</replaceable></literal> part of the locale tag against a locale + name or alias should be done by stripping all punctuation + characters from both the tag and the name or alias, converting + both name and alias to lowercase, and comparing the result. + This is necessary because, for example, <literal>Big5</literal> is frequently + found instead of <literal>BIG5</literal> and <literal>georgianacademy</literal> instead of + <literal>GEORGIAN-ACADEMY</literal>. Desktop files creators should, however, use + the name as it appears in the "Encoding" column above. + </para> + </appendix> +</article> diff --git a/help-system/help-system-spec.xml b/help-system/help-system-spec.xml new file mode 100644 index 0000000..ffe1a5d --- /dev/null +++ b/help-system/help-system-spec.xml @@ -0,0 +1,195 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +]> +<article id="index"> + <title>Help System Specification</title> + + <articleinfo> + <title>Help System Specification</title> + <date>2010-04-30</date> + <authorgroup> + <author> + <firstname>Shaun</firstname> + <surname>McCance</surname> + <affiliation> + <address> + <email>shaunm@gnome.org</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <section id="overview"> + <title>Overview</title> + <para>This specification provides a common directory layout and URI + scheme for locally installed help documents. Documents installed and + referenced using this system will have better interoperability between + different desktop environments and help applications.</para> + </section> + + <section id="layout"> + <title>Directory Layout</title> + + <para>A document is a collection of files, possibly from multiple + directories in a path. Documents may be in any format, or even in + multiple formats; see <xref linkend="formats"/> for details. A + document has a <emphasis>document identifier</emphasis> that + identifies it uniquely and specifies where it can be found on + the file system. A document identifier consists of one or more + characters from the following: digits (U+0030-U+0039), letters + (U+0041-U+005A and U+0061-U+007A), hyphen (U+002D), underscore + (U+005F), period (U+002E), and percent (U+0025).</para> + + <para>Document identifiers are not explicitly namespaced. To + avoid conflicts, document identifiers should start with the name + of the application or package that provides the document. In many + cases, the name of the application or package alone may be used. + Otherwise, the document identifier should start with the name + of the package or application followed by a hyphen.</para> + + <para>Documents are installed under the <filename>help</filename> + subdirectory in <envar>$XDG_DATA_HOME</envar> or in the + <envar>$XDG_DATA_DIRS</envar> path. See the + <ulink url="http://standards.freedesktop.org/basedir-spec/latest/">XDG + Base Directory Specification</ulink> for details on <envar>$XDG_DATA_HOME</envar> + and <envar>$XDG_DATA_DIRS</envar>. Each <filename>help</filename> + directory in the path contains subdirectories for languages. Each + language subdirectory contains subdirectories for documents, where + the name of each subdirectory matches the document identifier of + a document.</para> + + <para>The <emphasis>document path</emphasis> for a given document + is the list of directories of the following form:</para> + + <programlisting><replaceable>datadir</replaceable>/help/<replaceable>lang</replaceable>/<replaceable>document</replaceable></programlisting> + + <variablelist> + <varlistentry> + <term><filename><replaceable>datadir</replaceable></filename></term> + <listitem><para>Either <envar>$XDG_DATA_HOME</envar> or a directory in + the <envar>$XDG_DATA_DIRS</envar> path.</para></listitem> + </varlistentry> + <varlistentry> + <term><filename><replaceable>lang</replaceable></filename></term> + <listitem><para>The language code of a language in the user's + list of preferred languages.</para></listitem> + </varlistentry> + <varlistentry> + <term><filename><replaceable>document</replaceable></filename></term> + <listitem><para>The document identifier of the document.</para></listitem> + </varlistentry> + </variablelist> + + <para>The document path is ordered first according to the position of + <filename><replaceable>datadir</replaceable></filename> in the path, then + by the position of <filename><replaceable>lang</replaceable></filename> + in the user's preferred list of languages. So, for example, if the + user's preferred language list is <systemitem>pt_BT:pt:C</systemitem>, + then <filename>~/.local/share/help/pt/beanstalk</filename> would take + precedence over <filename>/usr/share/help/pt_BR/beanstalk</filename>.</para> + </section> + + <section id="uri-scheme"> + <title>URI Scheme</title> + + <para>Documents are referenced using the <systemitem>help:</systemitem> + URI scheme. The <systemitem>help:</systemitem> URI scheme has the + following form:</para> + + <programlisting>help:<replaceable>document</replaceable>/<replaceable>page</replaceable>?<replaceable>options</replaceable>#<replaceable>anchor</replaceable></programlisting> + + <variablelist> + <varlistentry> + <term><replaceable>document</replaceable></term> + <listitem><para>The document identifier.</para></listitem> + </varlistentry> + <varlistentry> + <term><replaceable>page</replaceable></term> + <listitem><para>An identifier for a page within the document. Documents + often consist of multiple logical pages, which may not be reflected in + the actual files on the system. The page identifier is optional. If it + is not present, the preceding <systemitem>/</systemitem> character + should be omitted.</para></listitem> + </varlistentry> + <varlistentry> + <term><replaceable>options</replaceable></term> + <listitem><para>Additional options that can influence how applications + present a document. Options are optional. If they are not present, the + preceding <systemitem>?</systemitem> character should be omitted. If + they are present, they must conform to the + <systemitem>application/x-www-form-urlencoded</systemitem> MIME type. + Options may be used, for example, to override language settings or to + provide keys for conditional processing. This specification makes no + specific recommendations for the options.</para></listitem> + </varlistentry> + <varlistentry> + <term><replaceable>anchor</replaceable></term> + <listitem><para>An anchor point within a page. Applications should + scroll to an appropriate point whenever possible. The anchor is + optional. If it is not present, the preceding <systemitem>#</systemitem> + character should be omitted.</para></listitem> + </varlistentry> + </variablelist> + + <para>Page identifiers and anchors may contain any character that is + valid in a document identifier. Some document types may have further + restrictions on page identifiers or anchors.</para> + </section> + + <section id="formats"> + <title>Help Formats</title> + + <para>Documents may be installed in any format. Not all help applications + may recognize and handle the same types of documents. Whenever possible, + help applications should support HTML. Documents may be installed in + multiple formats. Help applications choose which format to use when + multiple formats are present.</para> + + <para>For any format, a help application must map the information found + in the <systemitem>help:</systemitem> URI scheme to the information in + that format. This specification contains recommendations for finding + and handling documents in DocBook, Mallard, HTML, and XHTML.</para> + + <section id="docbook"> + <title>DocBook</title> + <para>DocBook documents have a file named <filename>index.docbook</filename> + in the document path. Any files referenced from the DocBook file, including + XML fragments included through XInclude, should be looked up according to + the document path.</para> + <para>When a help application displays a DocBook document, it will often + display it in multiple pages or chunks, rather than as a single long page. + The page identifier specifies which chunk to display. Not all applications + will split a DocBook document into chunks in the same way, so the page + identifier may not map exactly to the <sgmltag>id</sgmltag> attribute + of an element that is chunked. In this case, the applicaiton displays + the nearest enclosing chunk and treats the page identifier as an anchor + if no anchor was explicitly provided.</para> + </section> + + <section id="mallard"> + <title>Mallard</title> + <para>Mallard documents have a file named <filename>index.page</filename> + in the document path. Other page files may be different directories in + the document path. Any files referenced in any page file, including XML + fragments included through XInclude, should be looked up according to + the document path.</para> + <para>The page identifier specifies the id of a Mallard page file. The + anchor specifies the id of a section within a Mallard page file.</para> + </section> + + <section id="html"> + <title>HTML and XHTML</title> + <para>HTML documents have a file named <filename>index.html</filename> + in the document path. XHTML documents have a file named <filename>index.xhtml</filename> + in the document path. Other HTML or XHTML files in the document may + be in different directories in the document path. Any files referenced + in any HTML or XHTML page, including XML fragments included through + XInclude in XHTML, should be looked up according to the document path.</para> + <para>The page identifier specifies the base file name, without the + <filename>.html</filename> or <filename>.xhtml</filename> extension, + of an HTML or XHTML file in the document. The anchor specifies a named + anchor within the HTML or XHTML file.</para> + </section> + </section> +</article> diff --git a/menu/.cvsignore b/menu/.cvsignore new file mode 100644 index 0000000..f90eaaf --- /dev/null +++ b/menu/.cvsignore @@ -0,0 +1,11 @@ +config.log +config.status +config.sub +configure +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.guess +config.h +config.h.in diff --git a/menu/AUTHORS b/menu/AUTHORS new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/menu/AUTHORS diff --git a/menu/COPYING b/menu/COPYING new file mode 100644 index 0000000..73e7995 --- /dev/null +++ b/menu/COPYING @@ -0,0 +1,2 @@ +FIXME - we need a license for specs + diff --git a/menu/ChangeLog b/menu/ChangeLog new file mode 100644 index 0000000..025e9e1 --- /dev/null +++ b/menu/ChangeLog @@ -0,0 +1,143 @@ +2009-01-10 Vincent Untz <vuntz@gnome.org> + + * menu-spec.xml: bump version to 1.1-draft + +2009-01-10 Vincent Untz <vuntz@gnome.org> + + * menu-spec.xml: add LXDE as registered desktop environment for + OnlyShowIn. + See http://lists.freedesktop.org/archives/xdg/2008-December/010103.html + +2007-08-18 Vincent Untz <vuntz@gnome.org> + + * menu-spec.xml: accept X-Foo for environments in + OnlyShowIn/NotShowIn. + Fix bug #11564. + +2007-07-27 Vincent Untz <vuntz@gnome.org> + + * menu-spec.xml: change sysconfdir/desktop/menus/ to sysconfdir/menus/ + in one place. + Fix bug #8289. + +2007-02-06 Waldo Bastian <waldo.bastian@intel.com> + * Added scondary menu categories + * Bumped version to 1.0 + +2007-01-18 Waldo Bastian <waldo.bastian@intel.com> + + * Added support for LSB's tet testing framework + + * Renamed test to more meaningful names: + 1 -> Category + 2 -> OnlyUnallocated + 3 -> Deleted + 4 -> Move + 5 -> All + 6 -> Filename + 7 -> And + 8 -> Or + 9 -> Exclude + a -> DesktopFileID + b -> menu-multiple-matching + c -> Directory + d -> submenu-collision + e -> LegacyDir-relative + f -> Move-collapsing + g -> AppDir-relative + h -> DirectoryDir-relative + i -> DefaultMergeDirs + j -> MergeDir-relative + k -> MergeFile-relative + l -> MergeFile2 + m -> NoDisplay + n -> NoDisplay2 + o -> boolean-logic + p -> MergeFile3 + q -> MergeFile-parent + r -> MergeFile-path + s -> desktop-name-collision + t -> Move-ordering + u -> MergeFile-recursive + v -> NotOnlyUnallocated-default + w -> LegacyDir-Move + x -> Move-submenu + y -> Merge-combined + + * Added the following new tests: + AppDir + DirectoryDir + MergeDir-absolute + MergeFile-absolute + official-categories + +2006-03-28 Waldo Bastian <waldo.bastian@intel.com> + + * menu-spec.xml: Added example for installing sub-menu. + +2006-03-21 Waldo Bastian <waldo.bastian@intel.com> + + * menu-spec.xml: Recommend to use /usr/share for datadir + +2005-03-30 Waldo Bastian <bastian@kde.org> + + * menu-spec.xml: Change semantics and remove restrictions on <Move> + element to facilitate menu editing. + +2005-03-23 Waldo Bastian <bastian@kde.org> + + * menu-spec.xml: Clearify DTD conformance and version compatibility + +2005-03-22 Waldo Bastian <bastian@kde.org> + + * menu-spec.xml, menu.dtd: Added type attribute to <MergeFile> + element to facilitate menu-editing. + +2005-02-24 Waldo Bastian <bastian@kde.org> + + * menu-spec.xml: Fixed links to www.freedesktop.org + +2004-12-13 Mark McLoughlin <mark@skynet.ie> + + * menu-spec.xml: elaboration from Waldo. + +2004-12-08 Mark McLoughlin <mark@skynet.ie> + + * menu-spec.xml: make <OnlyUnallocated/> be for entries + which don't match any <Include> rule rather than entries + which don't appear in any menu. + +2004-09-03 Mark McLoughlin <mark@skynet.ie> + + * menu-spec.xml: minor typo - "This specification adds two + new fields to desktop entries" - s/two/three/ + +2004-05-07 Mark McLoughlin <mark@skynet.ie> + + * menu-spec.xml: fix typo in <Menuname> description. Its + inline_header rather than inline_title according to the DTD. + +2004-04-18 Mark McLoughlin <mark@skynet.ie> + + Patch from Ville Skyttä <ville.skytta@iki.fi> + + * menu-spec.xml: editorial changes and typo fixes. + +2003-12-12 Waldo Bastian <bastian@kde.org> + * menu-spec.xml: Correct example in "Legacy Menu Hierarchies" + +2003-11-09 Heinrich Wendel <h_wendel@cojobo.net> + * menu-spec.xml: patch for categories based on Suse 9.0 + * menu-spec.xml: Grahpics -> Graphics + * menu-spec.xml: DTD fix + * menu.dtd: added dtd + * testsuite: fixed errors highlighted by havoc + +2003-10-23 Havoc Pennington <hp@redhat.com> + + * menu-spec.xml: clarify how <Move> elements are resolved + +2003-10-21 Havoc Pennington <hp@redhat.com> + + * create autotools setup + diff --git a/menu/Makefile.am b/menu/Makefile.am new file mode 100644 index 0000000..92448da --- /dev/null +++ b/menu/Makefile.am @@ -0,0 +1,16 @@ +HTML_FILES= menu-spec.html + +XML_FILES= menu-spec.xml + +EXTRA_DIST= $(HTML_FILES) $(XML_FILES) + +if XML_DOCS_ENABLED +all-local: $(HTML_FILES) +endif + +%.html: %.xml + $(XMLTO) html-nochunks $< + +maintainer-clean-local: + rm -f $(HTML_FILES) + diff --git a/menu/NEWS b/menu/NEWS new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/menu/NEWS diff --git a/menu/README b/menu/README new file mode 100644 index 0000000..0edf632 --- /dev/null +++ b/menu/README @@ -0,0 +1 @@ +This is the specification and test suite for the menu system. diff --git a/menu/autogen.sh b/menu/autogen.sh new file mode 100755 index 0000000..b1376df --- /dev/null +++ b/menu/autogen.sh @@ -0,0 +1,3 @@ +#! /bin/sh +autoreconf -v --install || exit 1 +./configure --enable-maintainer-mode "$@" diff --git a/menu/configure.in b/menu/configure.in new file mode 100644 index 0000000..7a5a76c --- /dev/null +++ b/menu/configure.in @@ -0,0 +1,61 @@ +dnl -*- mode: m4 -*- +AC_PREREQ(2.52) + +AC_INIT(menu-spec.xml) + +AM_INIT_AUTOMAKE(desktop-menu-spec, 0.7) + +# Honor aclocal flags +ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" + + ## must come before we use the $USE_MAINTAINER_MODE variable later +AM_MAINTAINER_MODE + +AC_ARG_ENABLE(xml-docs, [ --enable-xml-docs build XML into HTML (requires xmlto)],enable_xml_docs=$enableval,enable_xml_docs=auto) + +### XML tools + +AC_PATH_PROG(XMLTO, xmlto, no) + +AC_MSG_CHECKING([whether to build XML documentation]) + +if test x$XMLTO = xno ; then + have_xmlto=no +else + have_xmlto=yes +fi + +if test x$enable_xml_docs = xauto ; then + if test x$have_xmlto = xno ; then + enable_xml_docs=no + else + enable_xml_docs=yes + fi +fi + +if test x$enable_xml_docs = xyes; then + if test x$have_xmlto = xno; then + AC_MSG_ERROR([Building XML docs explicitly required, but xmlto not found]) + fi +fi + +AM_CONDITIONAL(XML_DOCS_ENABLED, test x$enable_xml_docs = xyes) +AC_MSG_RESULT(yes) + +AC_OUTPUT([ +Makefile +]) + +dnl ========================================================================== +echo " + Menu specification $VERSION + ============== + + prefix: ${prefix} + source code location: ${srcdir} + xmlto: ${XMLTO}" + +echo " + Maintainer mode: ${USE_MAINTAINER_MODE} + Building XML docs: ${enable_xml_docs} +" diff --git a/menu/menu-spec.xml b/menu/menu-spec.xml new file mode 100644 index 0000000..7bd8568 --- /dev/null +++ b/menu/menu-spec.xml @@ -0,0 +1,2392 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ + <!ENTITY version "1.1-draft"> + <!ENTITY dtd-version "1.0"> + ]> + +<article id="index"> + <articleinfo> + <title>Desktop Menu Specification</title> + <releaseinfo>Version &version;</releaseinfo> + <date>31 March 2011</date> + <authorgroup> + <author> + <firstname>Waldo</firstname> + <surname>Bastian</surname> + <affiliation> + <address> + <email>waldo.bastian@intel.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Francois</firstname> + <surname>Gouget</surname> + <affiliation> + <address> + <email>fgouget@codeweavers.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Alex</firstname> + <surname>Graveley</surname> + <affiliation> + <address> + <email>alex@ximian.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>George</firstname> + <surname>Lebl</surname> + <affiliation> + <address> + <email>jirka@5z.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Havoc</firstname> + <surname>Pennington</surname> + <affiliation> + <address> + <email>hp@pobox.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Heinrich</firstname> + <surname>Wendel</surname> + <affiliation> + <address> + <email>h_wendel@cojobo.net</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + <para> + This document defines how to construct a user-visible hierarchy of + applications, typically displayed as a menu. It allows third-party + software to add menu items that work for all desktops, and allows system + administrators to edit menus in a way that affects all desktops. + </para> + <para> + The basic scheme is very simple. Information about each application (menu + item) is stored in a desktop entry (see <ulink + url="http://www.freedesktop.org/Standards/desktop-entry-spec">Desktop + Entry Standard</ulink>). Then an XML configuration file defines the + hierarchical arrangement (layout) of menu items, and which menu items are + actually displayed. + </para> + <para> + Things are complicated somewhat by the need to support legacy desktop + entry hierarchies, and the need to allow third parties to extend the menu + layout. Both of these issues are addressed by the idea of + <firstterm>merging</firstterm> two menu layouts. + </para> + <para> + In addition to a strict definition of the contents of each menu this + specification also foresees in a number of layout / presentation hints. + This part of the specification is optional, implementations may chose to + ignore these hints. + </para> + </sect1> + <sect1 id="paths"> + <title>File locations</title> + <para> + Files involved in this specification are located according to the <ulink + url="http://www.freedesktop.org/Standards/basedir-spec">"desktop + base directory specification"</ulink>. + </para> + <para> + Here are the files defined by this specification: + <variablelist> + <varlistentry> + +<term><varname>$XDG_CONFIG_DIRS</varname>/menus/<varname>${XDG_MENU_PREFIX}</varname>applications.menu</term> + <listitem> + <para> + This file contains the XML definition of the main application + menu layout. The first file found in the search path should be + used; other files are ignored. This implies that if the user + has their own <varname>${XDG_MENU_PREFIX}</varname>applications.menu, + it replaces the system wide one. + (Though the user's menu may explicitly merge the system wide + one.) + </para> + <para> + Systems that offer multiple desktop environments and that want + to use distinct menu layouts in the different environments can + use differently prefixed .menu files. In this case the + <varname>$XDG_MENU_PREFIX</varname> environment variable must + be set by the system to reflect the .menu file that is being + used. + </para> + <para> + For example if a system contains both the GNOME and the KDE + desktop environments it can decide to use + gnome-applications.menu as the menu layout in GNOME sessions + and kde-applications.menu as the menu layout in KDE sessions. + To correctly reflect this, it should set the + <varname>$XDG_MENU_PREFIX</varname> environment variable to + "gnome-" respectively "kde-". + </para> + <para> + Implementations may chose to use .menu files with other names + for tasks or menus other than the main application menu. Such + usage is not covered by this specification. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>$XDG_CONFIG_DIRS</varname>/menus/applications-merged/</term> + <listitem> + <para> + The default merge directories included in the + <DefaultMergeDirs> element. By convention, third parties + may add new <Menu> files in this location to create their + own sub-menus. + </para> + <para> + Note that a system that uses either gnome-applications.menu or + kde-applications.menu depending on the desktop environment in + use must still use applications-merged as the default merge + directory in both cases. + </para> + <para> + Implementations may chose to use .menu files with names other + than application.menu for tasks or menus other than the main + application menu. In that case the first part of the name of + the default merge directory is derived from the name of the + .menu file. + </para> + <para> + For example in a system that uses a preferences.menu file to + describe an additional menu, the default merge directories + included in the <DefaultMergeDirs> element in the + preferences.menu file would become + <varname>$XDG_CONFIG_DIRS</varname>/menus/preferences-merged/ + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>$XDG_DATA_DIRS</varname>/applications/</term> + <listitem> + <para> + This directory contains a .desktop file for each possible menu + item. Each directory in the <varname>$XDG_DATA_DIRS</varname> + search path should be used (i.e. desktop entries are collected + from all of them, not just the first one that exists). When two + desktop entries have the same name, the one appearing earlier in + the path is used. + </para> + <para> + The <DefaultAppDirs> element in a menu file indicates that + this default list of desktop entry locations should be scanned at + that point. If a menu file does not contain + <DefaultAppDirs>, then these locations are not scanned. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>$XDG_DATA_DIRS</varname>/desktop-directories/</term> + <listitem> + <para> + This directory contains directory entries which may be associated + with folders in the menu layout. Each directory + in the search path should be used. Only files ending in + .directory are used; other files are ignored. + </para> + <para> + The <DefaultDirectoryDirs> element in a menu file indicates that + this default list of directory entry locations should be scanned at + that point. If a menu file does not contain + <DefaultDirectoryDirs>, then these locations are not scanned. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </sect1> + <sect1 id="desktop-entry-extensions"> + <title>Extensions to the desktop entry format</title> + <para> + This specification adds three new fields to <ulink + url="http://www.freedesktop.org/Standards/desktop-entry-spec">desktop + entries</ulink>: <varname>Categories</varname>, + <varname>OnlyShowIn</varname> and <varname>NotShowIn</varname>. + </para> + <para> + The <varname>Categories</varname> field is a list of strings used to + classify menu items. For example, applications in the + <literal>AudioVideo</literal> category might end up in the + "Sound & Video" submenu. <xref linkend="category-registry"/> + enumerates the standard categories. Categories not in this document + must be prefixed by the string "X-" indicating that they are extensions. + Categories are case-sensitive. + </para> + <para> + Desktop entries should list all categories that clearly apply. They should + not list categories that only vaguely or possibly apply, because the user + will end up seeing the same desktop entry in a half-dozen places. But + it's typical that several categories will apply to a given desktop entry. + </para> + <para> + The <varname>OnlyShowIn</varname> field is a list of strings identifying + the environments that should display a given menu item. If an + <varname>OnlyShowIn</varname> field is present, a given environment should + only display the menu item if the string identifying that environment is + present. The strings are case-sensitive. <xref + linkend="onlyshowin-registry"/> enumerates the strings to use for + some common environments. + </para> + <para> + The <varname>NotShowIn</varname> field is a list of strings identifying + the environments that should not display a given menu item. If an + <varname>NotShowIn</varname> field is present, a given environment should + only display the menu item if the string identifying that environment is + not present. The strings are case-sensitive. <xref + linkend="onlyshowin-registry"/> enumerates the strings to use for + some common environments. + </para> + <para> + Environments not in this document must be prefixed by the string "X-" + indicating that they are extensions. Environments are case-sensitive. + </para> + <sect2 id="desktop-entry-extensions-examples"> + <title>Examples of using <varname>Categories</varname> and <varname>OnlyShowIn</varname></title> + <para> + A desktop entry for a Qt-based image viewer might contain + this <varname>Categories</varname> line: + <informalexample> + <programlisting> + Categories=Qt;Graphics;RasterGraphics;Viewer; + </programlisting> + </informalexample> + </para> + <para> + A desktop entry for Octave, a command-line mathematics program (which + would also have the field <literal>Terminal=true</literal>), might have: + <informalexample> + <programlisting> + Categories=ConsoleOnly;Math; + </programlisting> + </informalexample> + </para> + <para> + A desktop entry for a GNOME-specific calculator program + that should only appear in GNOME might have: + <informalexample> + <programlisting> + Categories=GNOME;Utility; + OnlyShowIn=GNOME; + </programlisting> + </informalexample> + Note that the <varname>OnlyShowIn</varname> field is a + <emphasis>list</emphasis> and thus ends in a semicolon. + </para> + </sect2> + </sect1> + <sect1 id="menu-file-format"> + <title>Format of menu files</title> + <para> + Menu files must be well-formed XML files and end in the extension + ".menu". They should also conform to the menu file DTD which implies + that implementation-specific extensions to the file format are not + allowed. Implementations may stop processing if they encounter a menu + file which does not comply with the associated DTD. Note that the + associated DTD may differ in version from the one defined in this document. + </para> + <para> + When an implementation updates an existing menu file it may need to + update the identifier to a newer version of the DTD. Implementations + should never update the identifier of an existing menu file to an + older version. In order to remain compatible with newer versions, + implementations should ignore and preserve any XML elements, + attributes and attribute values that it does not know how to handle. + </para> + <sect2 id="menu-file-doctype"> + <title>Document Type Declaration</title> + <para> + Menu files for this version of the specification must use the following + namespace, public and system identifiers: + <variablelist> + <varlistentry> + <term>Namespace</term> + <listitem> + <para> + <literal>http://www.freedesktop.org/standards/menu</literal> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Public Identifier for &version;</term> + <listitem> + <para> + <literal>PUBLIC "-//freedesktop//DTD Menu &dtd-version;//EN"</literal> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>System Identifier for &version;</term> + <listitem> + <para> +<literal>http://www.freedesktop.org/standards/menu-spec/menu-&dtd-version;.dtd</literal> + </para> + </listitem> + </varlistentry> + </variablelist> + + Here is a sample document type declaration: + <informalexample> + <programlisting> + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu &dtd-version;//EN" + "http://www.freedesktop.org/standards/menu-spec/menu-&dtd-version;.dtd"> + </programlisting> + </informalexample> + + All menu files MUST include the document type declaration, so that + implementations can adapt to different versions of this specification + (and so implementations can validate the menu file against + the DTD). + </para> + </sect2> + <sect2 id="menu-file-elements"> + <title>Elements</title> + <para> + <variablelist> + <varlistentry> + <term><Menu></term> + <listitem> + <para> + The root element is <Menu>. Each <Menu> element may + contain any number of nested <Menu> elements, indicating submenus. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><AppDir></term> + <listitem> + <para> + This element may only appear below <Menu>. The + content of this element is a directory name. Desktop entries + in this directory are scanned and added to the pool of entries + which can be included in this <Menu> and its submenus. + Only files ending in ".desktop" should be used, other files are + ignored. + </para> + <para> + Desktop entries in the pool of available entries are identified + by their <firstterm>desktop-file id</firstterm> (see <xref + linkend="term-desktop-file-id"/>). + The desktop-file id of a desktop entry is equal to its filename, + with any path components removed. + So given a <AppDir> + <filename>/foo/bar</filename> and desktop entry + <filename>/foo/bar/Hello.desktop</filename> the desktop + entry would get a desktop-file id of <filename>Hello.desktop</filename> + </para> + <para> + If the directory contains sub-directories then these sub-directories + should be (recursively) scanned as well. The name of the subdirectory + should be added as prefix to the desktop-file id together with a dash character ("-") + So given a <AppDir> + <filename>/foo/bar</filename> and desktop entry + <filename>/foo/bar/booz/Hello.desktop</filename> the desktop + entry would get a desktop-file id of <filename>booz-Hello.desktop</filename> + A desktop entry <filename>/foo/bar/bo/oz/Hello.desktop</filename> would result + in a desktop-file id of <filename>bo-oz-Hello.desktop</filename> + </para> + <para> + <AppDir> elements appearing later in the menu file have + priority in case of collisions between desktop-file ids. + </para> + <para> + If the filename given as an <AppDir> is not an absolute + path, it should be located relative to the location of the menu + file being parsed. + </para> + <para> + Duplicate <AppDir> elements (that specify the same + directory) should be ignored, but the <emphasis>last</emphasis> + duplicate in the file should be used when establishing the order + in which to scan the directories. This is important when merging + (see <xref linkend="merge-algorithm"/>). The order of + <AppDir> elements with respect to <Include> and + <Exclude> elements is not relevant, also to facilitate + merging. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><DefaultAppDirs></term> + <listitem> + <para> + This element may only appear below <Menu>. The element has + no content. The element should be treated as if it were a list + of <AppDir> elements containing the default app dir + locations + (<replaceable>datadir</replaceable>/applications/ etc.). When expanding + <DefaultAppDirs> to a list of <AppDir>, the default + locations that are earlier in the search path go later in the + <Menu> so that they have priority. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><DirectoryDir></term> + <listitem> + <para> + This element may only appear below <Menu>. The content of + this element is a directory name. Each directory listed in a + <DirectoryDir> element will be searched for directory + entries to be used when resolving the <Directory> element + for this menu and its submenus. + If the filename given as a <DirectoryDir> is not an absolute path, + it should be located relative to the location + of the menu file being parsed. + </para> + <para> + Directory entries in the pool of available entries are identified + by their <firstterm>relative path</firstterm> (see <xref + linkend="term-relative-path"/>). + </para> + <para> + If two directory entries have duplicate relative paths, the one from + the last (furthest down) element in the menu file must be used. + Only files ending in the extension ".directory" should be + loaded, other files should be ignored. + </para> + <para> + Duplicate <DirectoryDir> elements (that specify the same + directory) are handled as with duplicate <AppDir> + elements (the last duplicate is used). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><DefaultDirectoryDirs></term> + <listitem> + <para> + This element may only appear below <Menu>. The element has + no content. The element should be treated as if it were a list + of <DirectoryDir> elements containing the default desktop dir + locations + (<replaceable>datadir</replaceable>/desktop-directories/ etc.). The default + locations that are earlier in the search path go later in the + <Menu> so that they have priority. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Name></term> + <listitem> + <para> + Each <Menu> element must have a single <Name> + element. The content of the <Name> element is a name to + be used when referring to the given menu. Each submenu of a + given <Menu> must have a unique name. <Menu> + elements can thus be referenced by a menu path, for example + "Applications/Graphics." The <Name> field must not contain + the slash character ("/"); implementations should discard + any name containing a slash. See also <xref linkend="term-menu-path"/>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Directory></term> + <listitem> + <para> + Each <Menu> element has any number of <Directory> + elements. The content of the <Directory> element + is the relative path of a directory entry containing meta information + about the <Menu>, such as its icon and localized name. + If no <Directory> is specified for a <Menu>, + its <Name> field should be used as the user-visible + name of the menu. + </para> + <para> + Duplicate <Directory> elements are allowed in order + to simplify menu merging, and allow user menus to override + system menus. The last <Directory> element to appear + in the menu file "wins" and other elements are ignored, + unless the last element points to a nonexistent directory + entry, in which case the previous element should be tried instead, + and so on. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><OnlyUnallocated> and <NotOnlyUnallocated></term> + <listitem> + <para> + Each <Menu> may contain any number of + <OnlyUnallocated> and <NotOnlyUnallocated> + elements. Only the last such element to appear is relevant, as + it determines whether the <Menu> can contain any desktop + entries, or only those desktop entries that do not match other + menus. If neither <OnlyUnallocated> nor + <NotOnlyUnallocated> elements are present, the default + is <NotOnlyUnallocated>. + </para> + <para> + To handle <OnlyUnallocated>, the menu file must be + analyzed in two conceptual passes. The first pass processes + <Menu> elements that can match any desktop entry. During + this pass, each desktop entry is marked as allocated according + to whether it was matched by an <Include> rule in some + <Menu>. The second pass processes only <Menu> + elements that are restricted to unallocated desktop entries. + During the second pass, queries may only match desktop entries + that were not marked as allocated during the first pass. + See <xref linkend="query-algorithm"/>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Deleted> and <NotDeleted></term> + <listitem> + <para> + Each <Menu> may contain any number of <Deleted> and + <NotDeleted> elements. Only the last such element to + appear is relevant, as it determines whether the <Menu> + has been deleted. If neither <Deleted> nor + <NotDeleted> elements are present, the default is + <NotDeleted>. The purpose of this element is to support + menu editing. If a menu contains a <Deleted> element + not followed by a <NotDeleted> element, that menu + should be ignored. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Include></term> + <listitem> + <para> + An <Include> element is a set of rules attempting to match + some of the known desktop entries. The <Include> element + contains a list of any number of matching rules. Matching rules + are specified using the elements <And>, <Or>, + <Not>, <All>, <Filename>, and + <Category>. Each rule in a list of rules has a logical OR + relationship, that is, desktop entries which match any rule + are included in the menu. + </para> + <para> + <Include> elements must appear immediately under + <Menu> elements. The desktop entries they match are + included in the menu. <Include> and <Exclude> + elements for a given <Menu> are processed in order, + with queries earlier in the file handled first. This has + implications for merging, see <xref linkend="merge-algorithm"/>. + See <xref linkend="query-algorithm"/> for full details on + how to process <Include> and <Exclude> elements. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Exclude></term> + <listitem> + <para> + Any number of <Exclude> elements may appear below a + <Menu> element. The content of an <Exclude> element + is a list of matching rules, just as with an + <Include>. However, the desktop entries matched are + removed from the list of desktop entries included so far. (Thus + an <Exclude> element that appears before any + <Include> elements will have no effect, for example, as no + desktop entries have been included yet.) + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Filename></term> + <listitem> + <para> + The <Filename> element is the most basic matching rule. + It matches a desktop entry if the desktop entry has the given + desktop-file id. See <xref linkend="term-desktop-file-id"/>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Category></term> + <listitem> + <para> + The <Category> element is another basic matching + predicate. It matches a desktop entry if the desktop entry has + the given category in its <varname>Categories</varname> field. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><All></term> + <listitem> + <para> + The <All> element is a matching rule that matches + all desktop entries. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><And></term> + <listitem> + <para> + The <And> element contains a list of matching rules. + If each of the matching rules inside the <And> + element match a desktop entry, then the entire + <And> rule matches the desktop entry. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Or></term> + <listitem> + <para> + The <Or> element contains a list of matching rules. + If any of the matching rules inside the <Or> + element match a desktop entry, then the entire + <Or> rule matches the desktop entry. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Not></term> + <listitem> + <para> + The <Not> element contains a list of matching rules. If + any of the matching rules inside the <Not> element matches + a desktop entry, then the entire <Not> rule does + <emphasis>not</emphasis> match the desktop entry. That is, + matching rules below <Not> have a logical OR relationship. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><MergeFile [type="path"|"parent"] ></term> + <listitem> + <para> + Any number of <MergeFile> elements may be listed below a + <Menu> element, giving the name of another menu file to + be merged into this one. <xref linkend="merge-algorithm"/> + specifies how merging is done. The root <Menu> of the + merged file will be merged into the immediate parent of the + <MergeFile> element. The <Name> element of the + root <Menu> of the merged file are ignored. + </para> + <para> + If the type attribute is missing or set to "path" then the + contents of the <MergeFile> element indicates the + file to be merged. If this is not an absolute path then the + file to be merged should be located relative to the location + of the menu file that contains this <MergeFile> element. + </para> + <para> + Duplicate <MergeFile> elements (that specify the same + file) are handled as with duplicate <AppDir> + elements (the last duplicate is used). + </para> + <para> + If the type attribute is set to "parent" and the file that + contains this <MergeFile> element is located under one + of the paths specified by <varname>$XDG_CONFIG_DIRS</varname>, + the contents of the element should be ignored and the remaining + paths specified by <varname>$XDG_CONFIG_DIRS</varname> are + searched for a file with the same relative filename. The first + file encountered should be merged. There should be no + merging at all if no matching file is found. + </para> + <para> + Compatibility note: The filename specified inside the <MergeFile> + element should be ignored if the type attribute is set to "parent", + it should however be expected that implementations based on + previous versions of this specification will ignore the + type attribute and that such implementations will use the + filename inside the <MergeFile> element instead. + </para> + <para> + Example 1: If <varname>$XDG_CONFIG_HOME</varname> is "~/.config/" and + <varname>$XDG_CONFIG_DIRS</varname> is "/opt/gnome/:/etc/xdg/" + and the file ~/.config/menus/applications.menu contains + <MergeFile type="parent">/opt/kde3/etc/xdg/menus/applications.menu</MergeFile> + then the file /opt/gnome/menus/applications.menu + should be merged if it exists. If that file does not exists + then the file /etc/xdg/menus/applications.menu + should be merged instead. + </para> + <para> + Example 2: If <varname>$XDG_CONFIG_HOME</varname> is "~/.config/" and + <varname>$XDG_CONFIG_DIRS</varname> is "/opt/gnome/:/etc/xdg/" + and the file /opt/gnome/menus/applications.menu contains + <MergeFile type="parent">/opt/kde3/etc/xdg/menus/applications.menu</MergeFile> + then the file /etc/xdg/menus/applications.menu should be merged + if it exists. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><MergeDir></term> + <listitem> + <para> + Any number of <MergeDir> elements may be listed below a + <Menu> element. A <MergeDir> contains the name of a + directory. Each file in the given directory which ends in the + ".menu" extension should be merged in the same way that a + <MergeFile> would be. If the filename given as a + <MergeDir> is not an absolute path, it should be located + relative to the location of the menu file being parsed. + The files inside the merged directory are not merged in any + specified order. + </para> + <para> + Duplicate <MergeDir> elements (that specify the same + directory) are handled as with duplicate <AppDir> + elements (the last duplicate is used). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><DefaultMergeDirs></term> + <listitem> + <para> + This element may only appear below <Menu>. The element has + no content. The element should be treated as if it were a list + of <MergeDir> elements containing the default merge + directory locations. When expanding <DefaultMergeDirs> to a + list of <MergeDir>, the default locations that are earlier + in the search path go later in the <Menu> so that they + have priority. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><LegacyDir></term> + <listitem> + <para> + This element may only appear below <Menu>. The text + content of this element is a directory name. Each directory + listed in a <LegacyDir> element will be an old-style + legacy hierarchy of desktop entries, see <xref + linkend="legacy-hierarchies"/> for how to load such a + hierarchy. Implementations must not load legacy hierarchies that + are not explicitly specified in the menu file (because for + example the menu file may not be the main menu). If the + filename given as a <LegacyDir> is not an absolute path, + it should be located relative to the location of the menu file + being parsed. + </para> + <para> + Duplicate <LegacyDir> elements (that specify the same + directory) are handled as with duplicate <AppDir> + elements (the last duplicate is used). + </para> + <para> + The <LegacyDir> element may have one attribute, + <literal>prefix</literal>. Normally, given a <LegacyDir> + <filename>/foo/bar</filename> and desktop entry + <filename>/foo/bar/baz/Hello.desktop</filename> the desktop + entry would get a desktop-file id of <filename>Hello.desktop</filename>. + Given a prefix of <literal>boo-</literal>, it would instead be + assigned the desktop-file id <filename>boo-Hello.desktop</filename>. + The prefix should not contain path separator ('/') characters. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><KDELegacyDirs></term> + <listitem> + <para> + This element may only appear below <Menu>. The element has + no content. The element should be treated as if it were a list + of <LegacyDir> elements containing the traditional desktop + file locations supported by KDE with a hard coded prefix of "kde-". + When expanding <KDELegacyDirs> to a list of <LegacyDir>, the + locations that are earlier in the search path go later in the + <Menu> so that they have priority. + The search path can be obtained by running <filename>kde-config --path apps</filename> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Move></term> + <listitem> + <para> + This element may only appear below <Menu>. The + <Move> element contains pairs of <Old>/<New> + elements indicating how to rename a descendant of the current + <Menu>. If the destination path already exists, the moved + menu is merged with the destination menu (see <xref + linkend="merge-algorithm"/> for details). + </para> + <para> + <Move> is used primarily to fix up legacy directories. + For example, say you are merging a <LegacyDir> with folder + names that don't match the current hierarchy; the legacy folder + names can be moved to the new names, where they will be merged + with the new folders. + </para> + <para> + <Move> is also useful for implementing menu + editing, see <xref linkend="menu-editing"/>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Old></term> + <listitem> + <para> + This element may only appear below <Move>, and + must be followed by a <New> element. The content of both + <Old> and <New> should be a menu path + (slash-separated concatenation of <Name> fields, see + <xref linkend="term-menu-path"/>). + Paths are interpreted relative to the menu containing + the <Move> element. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><New></term> + <listitem> + <para> + This element may only appear below <Move>, and must + be preceded by an <Old> element. The <New> element + specifies the new path for the preceding <Old> element. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Layout></term> + <listitem> + <para> + The <Layout> element is an optional part of this specification. + Implementations that do not support the <Layout> element should + preserve any <Layout> elements and their contents as far as + possible. + Each <Menu> may optionally contain a <Layout> element. + If multiple elements appear then only the last such element is relevant. + The purpose of this element is to offer suggestions for the presentation + of the menu. + If a menu does not contain a <Layout> element or if it contains + an empty <Layout> element then the default layout should be used. + The <Layout> element may contain <Filename>, <Menuname>, + <Separator> and <Merge> elements. The <Layout> element + defines a suggested layout for the menu starting from top to bottom. + References to desktop entries that are not contained in this + menu as defined by the <Include> and <Exclude> elements should + be ignored. References to sub-menus that are not directly contained in this + menu as defined by the <Menu> elements should be ignored. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><DefaultLayout [show_empty="false"] [inline="false"] [inline_limit="4"] [inline_header="true"] [inline_alias="false"]></term> + <listitem> + <para> + The <DefaultLayout> element is an optional part of this specification. + Implementations that do not support the <DefaultLayout> element should + preserve any <DefaultLayout> elements and their contents as far as + possible. + Each <Menu> may optionally contain a <DefaultLayout> element + which defines the default-layout for the current menu and all its sub-menus. + If a menu has a <DefaultLayout> element then this will override + any default-layout specified by a parent menu. + The default-layout defines the suggested layout if a <Menu> element + does either not have <Layout> element or if it has an empty <Layout> element. + For explanations of the various attributes see the <Menuname> element. + If no default-layout has been specified then the layout as specified by the following + elements should be assumed: + <DefaultLayout show_empty="false" inline="false" inline_limit="4" inline_header="true" inline_alias="false"><Merge type="menus"/><Merge type="files"/></DefaultLayout> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Menuname [show_empty="..."] [inline="..."] [inline_limit="..."] [inline_header="..."] [inline_alias="..."]></term> + <listitem> + <para> + This element may only appear as a child of a <Layout> or <DefaultLayout> + menu. Its contents references an immediate sub-menu of the current menu as defined + with the <Menu> element, as such it should never contain a slash. + If no such sub-menu exists the element should be ignored. + This element may have various attributes, the default values are taken from the DefaultLayout key. + The show_empty attribute defines whether a menu that contains no desktop + entries and no sub-menus should be shown at all. The show_empty attribute + can be "true" or "false". + It may have an inline attribute that can be either "true" or "false". + If the inline attribute is "true" the menu that is referenced may be copied into the + current menu at the current point instead of being inserted as sub-menu of the current menu. + The optional inline_limit attribute defines the maximum number of entries that can be inlined. + If the sub-menu has more entries than inline_limit, the sub-menu will not be inlined. + If the inline_limit is 0 (zero) there is no limit. + The optional inline_header attribute defines whether an inlined menu should be preceded with + a header entry listing the caption of the sub-menu. + The inline_header attribute can be either "true" or "false". + The optional inline_alias attribute defines whether a single inlined entry should adopt the + caption of the inlined menu. In such case no additional header entry will be added regardless + of the value of the inline_header attribute. + The inline_alias attribute can be either "true" or "false". + Example: if a menu has a sub-menu titled "WordProcessor" with a single entry "OpenOffice 4.2", + and both inline="true" and inline_alias="true" are specified then this would result in the + "OpenOffice 4.2" entry being inlined in the current menu but the "OpenOffice 4.2" caption + of the entry would be replaced with "WordProcessor". + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Separator></term> + <listitem> + <para> + This element may only appear as a child of a <Layout> or <DefaultLayout> + menu. It indicates a suggestion to draw a visual separator at this point in the menu. + <Separator> elements at the start of a menu, at the end of a menu or that directly + follow other <Separator> elements may be ignored. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><Merge type="menus"|"files"|"all"/></term> + <listitem> + <para> + This element may only appear as a child of a <Layout> or <DefaultLayout> + menu. It indicates the point where desktop entries and sub-menus that are not explicitly + mentioned within the <Layout> or <DefaultLayout> element are to be inserted. + It has a type attribute that indicates which elements should be inserted: + type="menus" + means that all sub-menus that are not explicitly mentioned should be inserted in + alphabetical order of their visual caption at this point. + type="files" + means that all desktop entries + contained in this menu that are not explicitly mentioned should be inserted in + alphabetical order of their visual caption at this point. + type="all" means that a mix of all sub-menus + and all desktop entries that are not explicitly mentioned should be inserted in + alphabetical order of their visual caption at this point. + Each <Layout> or <DefaultLayout> element shall have exactly one <Merge type="all"> + element or it shall have exactly one <Merge type="files"> and exactly one + <Merge type="menus"> element. An exception is made for a completely empty <Layout> + element which may be used to indicate that the default-layout should be used instead. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </sect2> + </sect1> + + <sect1 id="merge-algorithm"> + <title>Merging</title> + <para> + Sometimes two menu layouts need to be merged. This is done when folding in + legacy menu hierarchies (see <xref linkend="legacy-hierarchies"/>) and also + for files specified in <MergeFile> elements. A common case is that + per-user menu files might merge the system menu file. Merging is also used + to avoid cut-and-paste, for example to include a common submenu in + multiple menu files. + </para> + <para> + Merging involves a base <Menu> and a merged <Menu>. The base + is the "target" menu and the merged <Menu> is being added to it. The + result of the merge is termed the "combined menu." + </para> + <para> + As a preparatory step, the goal is to resolve all files into + XML elements. To do so, traverse the entire menu tree. For each + <MergeFile>, <MergeDir>, or <LegacyDir> element, replace + the <MergeFile>, <MergeDir>, or <LegacyDir> element with + the child elements of the root <Menu> of the file(s) being + merged. As a special exception, remove the <Name> element from the + root element of each file being merged. To generate a + <Menu> based on a <LegacyDir>, see + <xref linkend="legacy-hierarchies"/>. + </para> + <para> + Continue processing until no <MergeFile>, <MergeDir>, or + <LegacyDir> elements remain, taking care to avoid infinite loops + caused by files that reference one another. + </para> + <para> + Once all files have been loaded into a single tree, scan the tree + recursively performing these steps to remove duplicates: + <orderedlist> + <listitem> + <para> + Consolidate child menus. Each group of child <Menu>s with the same + name must be consolidated into a single child menu with that name. + Concatenate the child elements of all menus with the same name, in + the order that they appear, and insert those elements as the + children of the <emphasis>last</emphasis> menu with that name. + Delete all the newly empty <Menu> elements, keeping the + last one. + </para> + </listitem> + <listitem> + <para> + Expand <DefaultAppDirs> and <DefaultDirectoryDirs> + elements to <AppDir> and <DirectoryDir> elements. + Consolidate duplicate <AppDir>, <DirectoryDir>, + and <Directory> elements by keeping the last one. + For <Directory> elements that refer to distinct directory + entries, all of them should be kept - if the last one points + to a nonexistent file, the one before that can be used instead, + and so forth. + </para> + </listitem> + <listitem> + <para> + Recurse into each child <Menu>, performing this list of + steps for each child in order. + </para> + </listitem> + </orderedlist> + </para> + <para> + After recursing once to remove duplicates, recurse a second time to + resolve <Move> elements for each menu starting with any child + menu before handling the more top level menus. + So the deepest menus have their <Move> operations performed first. + Within each <Menu>, execute <Move> operations in the order + that they appear. If the destination path does not exist, simply relocate + the origin <Menu> element, and change its <Name> field to + match the destination path. If the origin path does not exist, do + nothing. If both paths exist, take the origin <Menu> element, + delete its <Name> element, and prepend its remaining child elements + to the destination <Menu> element. + </para> + <para> + If any <Move> operations affect a menu, then re-run the + steps to resolve duplicates in case any duplicates have been + created. + </para> + <para> + Finally, for each <Menu> containing a <Deleted> element which + is not followed by a <NotDeleted> element, remove that menu and all + its child menus. + </para> + + <para> + Merged menu elements are kept in order because <Include> and + <Exclude> elements later in the file override <Include> and + <Exclude> elements earlier in the file. This means that if the user's + menu file merges the system menu file, the user can always override what + the system menu specifies by placing elements after the <MergeFile> + that incorporates the system file. + </para> + <para> + To prevent that a desktop entry from one party inadvertently cancels out + the desktop entry from another party because both happen to get the same + desktop-file id it is recommended that providers of desktop-files ensure that + all desktop-file ids start with a vendor prefix. A vendor prefix + consists of [a-zA-Z] and is terminated with a dash ("-"). Open Source + projects and commercial parties are encouraged to use a word or phrase, + preferably their name, as prefix for which they hold a trademark. Open Source + applications can also ask to make use of the vendor prefix of another open + source project (such as GNOME or KDE) they consider themselves affiliated + with, at the discretion of these projects. + </para> + <para> + For example, to ensure that GNOME applications start with a vendor prefix of "gnome-", + it could either add "gnome-" to all the desktop files it installs in + <filename><replaceable>datadir</replaceable>/applications/</filename> or it could + install desktop files in a <filename><replaceable>datadir</replaceable>/applications/gnome</filename> + subdirectory. When including legacy menu hierarchies the <literal>prefix</literal> argument + of the <LegacyDir> element can be used to specify a prefix. + </para> + </sect1> + + <sect1 id="query-algorithm"> + <title>Generating the menus</title> + <para> + After merging the menus, the result should be a single menu layout + description. For each <Menu>, we have a list of directories where + desktop entries can be found, a list of directories where directory + entries can be found, and a series of <Include> and <Exclude> + directives. + </para> + <para> + For each <Menu> element, build a pool of desktop entries by + collecting entries found in each <AppDir> for the menu element. If + two entries have the same desktop-file id, the entry for the earlier (closer + to the top of the file) <AppDir> must be discarded. Next, add to the + pool the entries for any <AppDir>s specified by ancestor + <Menu> elements. If a parent menu has a duplicate entry (same + desktop-file id), the entry for the child menu has priority. + </para> + <para> + Next, walk through all <Include> and <Exclude> statements. + For each <Include>, match the rules against the pool of all desktop + entries. For each desktop entry that matches one of the rules, + add it to the menu to be displayed and mark it as having been allocated. + For each <Exclude>, match the rules against the currently-included + desktop entries. For each desktop entry that matches, remove it again + from the menu. Note that an entry that is included in a menu but excluded + again by a later <Exclude> is still considered allocated (for the + purposes of <OnlyUnallocated>) even though that entry no longer + appears in the menu. + </para> + <para> + Two passes are necessary, once for regular menus where any entry may + be matched, and once for <OnlyUnallocated> menus where only entries + which have not been marked as allocated may be matched. + </para> + <para> + The result is a tree of desktop entries, of course. + </para> + </sect1> + + <sect1 id="legacy-hierarchies"> + <title>Legacy Menu Hierarchies</title> + <para> + Traditionally, menus were defined as a filesystem hierarchy, with each + filesystem directory corresponding to a submenu. Implementations of this + specification must be able to load these old-style hierarchies + as specified in this section. + </para> + <para> + The general approach is: the legacy hierarchy is converted into a + <Menu>, and then this menu layout is merged with the menu that + specified <LegacyDir>. + </para> + <para> + Desktop entries in the legacy hierarchy should be added to the pool of + desktop entries as if the <LegacyDir> were an + <AppDir>. Directory entries in the legacy hierarchy should be added + to the pool of directory entries as if the <LegacyDir> were a + <DirectoryDir>. This can be trivially implemented by adding + appropriate <AppDir> and <DirectoryDir> statements to the root + legacy <Menu>. There is one slight complexity, namely the + "prefix" attribute of <LegacyDir>. + </para> + <para> + The menu layout corresponds conceptually to the following, though actually + generating the XML is not necessary: + <itemizedlist> + <listitem> + <para> + For each directory in the legacy hierarchy, a + <Menu> is created with the same <Name> + as the directory on disk. + </para> + </listitem> + <listitem> + <para> + This menu then contains an <Include> element that includes + each desktop entry in the directory. That is, it should have a + + <Filename><replaceable>Foo/Bar/foo.desktop</replaceable></Filename> + for each desktop entry in the directory. + </para> + <para> + As a special exception, if a desktop entry in a directory contains + a <varname>Categories</varname> field, that desktop entry should + <emphasis>not</emphasis> be included in the legacy menu. + That is, no <Include> element should be generated for + the entry. This allows a desktop entry to be installed + in a legacy location but still work optimally with the + menu system specified in this document. + </para> + </listitem> + <listitem> + <para> + If the legacy directory contains a ".directory" file, then + a <Directory> element should be generated that points to said + ".directory" file. + </para> + </listitem> + <listitem> + <para> + Legacy desktop entries should not be assigned any + <varname>Categories</varname> fields if they didn't have them + already, except that all legacy entries should have the + "Legacy" category added to allow menu files to treat them + specially. (If the same directory is given as both + a <LegacyDir> and an <AppDir>, its desktop + entries should be labeled "Legacy" only if the <LegacyDir> + appears later in the file than the <AppDir>.) + </para> + </listitem> + </itemizedlist> + </para> + <para> + For example, say we have the following legacy directory hierarchy: + <informalexample> + <programlisting> + /usr/share/applnk + /usr/share/applnk/.directory + /usr/share/applnk/bar.desktop + /usr/share/applnk/System + /usr/share/applnk/System/.directory + /usr/share/applnk/System/foo.desktop + </programlisting> + </informalexample> + Conceptually that is converted to the following <Menu>: + <informalexample> + <programlisting> + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu &dtd-version;//EN" + "http://www.freedesktop.org/standards/menu-spec/menu-&dtd-version;.dtd"> + + <Menu> + <Name>Applications</Name> + <AppDir>/usr/share/applnk</AppDir> + <DirectoryDir>/usr/share/applnk</DirectoryDir> + <Directory>.directory</Directory> + <Include> + <Filename>bar.desktop</Filename> + </Include> + <Menu> + <Name>System</Name> + <AppDir>/usr/share/applnk/System</AppDir> + <DirectoryDir>/usr/share/applnk/System</DirectoryDir> + <Directory>.directory</Directory> + <Include> + <Filename>foo.desktop</Filename> + </Include> + </Menu> + </Menu> + </programlisting> + </informalexample> + This <Menu> is then merged as if it were in a file + and loaded with <MergeFile>. + </para> + </sect1> + + <sect1 id="example"> + <title>Example Menu File</title> + <para> + <informalexample> + <programlisting> + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu &dtd-version;//EN" + "http://www.freedesktop.org/standards/menu-spec/menu-&dtd-version;.dtd"> + + <Menu> + <Name>Applications</Name> + <Directory>Applications.directory</Directory> + + <-- Search the default locations --> + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + + <-- Merge third-party submenus --> + <MergeDir>applications-merged</MergeDir> + + <-- Merge legacy hierarchy --> + <LegacyDir>/usr/share/applnk</LegacyDir> + + <-- Define default layout --> + <DefaultLayout> + <Merge type="menus"/> + <Merge type="files"/> + <Separator/> + <Menuname>More</Menuname> + </DefaultLayout> + + <-- some random moves, maybe to clean up legacy dirs, + maybe from menu editing --> + <Move> + <Old>Foo</Old> + <New>Bar</New> + <Old>Foo2</Old> + <New>Bar2</New> + </Move> + + <-- A preferences submenu, kept in a separate file + so it can also be used standalone --> + <Menu> + <Name>Preferences</Name> + <Directory>Preferences.directory</Directory> + <MergeFile>preferences.menu</MergeFile> + </Menu> + + <-- An Office submenu, specified inline --> + <Menu> + <Name>Office</Name> + <Directory>Office.directory</Directory> + <Include> + <Category>Office</Category> + </Include> + <Exclude> + <Filename>foo.desktop</Filename> + </Exclude> + </Menu> + + </Menu> + </programlisting> + </informalexample> + </para> + </sect1> + + <appendix id="category-registry"> + <title>Registered Categories</title> + <para> + This section contains a number of well known categories and + suggestions on how to use them. The list of Main Categories consist + of those categories that every conforming desktop environment MUST + support. By including one of these categories in an application's + desktop entry file the application will be ensured that it will + show up in a section of the application menu dedicated to this + category. The list of Additional Categories provides categories + that can be used to provide more fine grained information about + the application. + </para> + <para> + Category-based menus based on the Main Categories listed in this + specification do not provide a complete ontology for all + available applications. Category-based menu implementations + SHOULD therefore provide a "catch-all" submenu for applications + that cannot be appropriately placed elsewhere. + </para> + <para> + The table below lists all Main Categories. + Note that category names are case-sensitive. + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Main Category</entry> + <entry>Description</entry> + <entry>Notes</entry> + </row> + </thead> + <tbody> + <row> + <entry>AudioVideo</entry> + <entry>Application for presenting, creating, or processing multimedia (audio/video)</entry> + </row><row> + <entry>Audio</entry> + <entry>An audio application</entry> + <entry>Desktop entry must include AudioVideo as well</entry> + </row><row> + <entry>Video</entry> + <entry>A video application</entry> + <entry>Desktop entry must include AudioVideo as well</entry> + </row><row> + <entry>Development</entry> + <entry>An application for development</entry> + </row><row> + <entry>Education</entry> + <entry>Educational software</entry> + </row><row> + <entry>Game</entry> + <entry>A game</entry> + </row><row> + <entry>Graphics</entry> + <entry>Application for viewing, creating, or processing graphics</entry> + </row><row> + <entry>Network</entry> + <entry>Network application such as a web browser</entry> + </row><row> + <entry>Office</entry> + <entry>An office type application</entry> + </row><row> + <entry>Settings</entry> + <entry>Settings applications</entry> + <entry>Entries may appear in a separate menu or as part of a + "Control Center"</entry> + </row><row> + <entry>System</entry> + <entry>System application, "System Tools" such as say a log viewer or network monitor</entry> + </row><row> + <entry>Utility</entry> + <entry>Small utility application, "Accessories"</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + The table below describes Additional Categories. The Related + Categories column lists one or more categories that are suggested + to be used in conjunction with the Additional Category. If multiple + Main Categories are included in a single + desktop entry file, the entry may appear more than once in the menu. + If the Related Categories column is blank, the + Additional Category can be used with any Main Category. + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Additional Category</entry> + <entry>Description</entry> + <entry>Related Categories</entry> + </row> + </thead> + <tbody> + <row> + <entry>Building</entry> + <entry>A tool to build applications</entry> + <entry>Development</entry> + + </row><row> + <entry>Debugger</entry> + <entry>A tool to debug applications</entry> + <entry>Development</entry> + + </row><row> + <entry>IDE</entry> + <entry>IDE application</entry> + <entry>Development</entry> + + </row><row> + <entry>GUIDesigner</entry> + <entry>A GUI designer application</entry> + <entry>Development</entry> + + </row><row> + <entry>Profiling</entry> + <entry>A profiling tool</entry> + <entry>Development</entry> + + </row><row> + <entry>RevisionControl</entry> + <entry>Applications like cvs or subversion</entry> + <entry>Development</entry> + + </row><row> + <entry>Translation</entry> + <entry>A translation tool</entry> + <entry>Development</entry> + + </row><row> + <entry>Calendar</entry> + <entry>Calendar application</entry> + <entry>Office</entry> + + </row><row> + <entry>ContactManagement</entry> + <entry>E.g. an address book</entry> + <entry>Office</entry> + + </row><row> + <entry>Database</entry> + <entry>Application to manage a database</entry> + <entry>Office or Development or AudioVideo</entry> + + </row><row> + <entry>Dictionary</entry> + <entry>A dictionary</entry> + <entry>Office;TextTools</entry> + + </row><row> + <entry>Chart</entry> + <entry>Chart application</entry> + <entry>Office</entry> + + </row><row> + <entry>Email</entry> + <entry>Email application</entry> + <entry>Office;Network</entry> + + </row><row> + <entry>Finance</entry> + <entry>Application to manage your finance</entry> + <entry>Office</entry> + + </row><row> + <entry>FlowChart</entry> + <entry>A flowchart application</entry> + <entry>Office</entry> + + </row><row> + <entry>PDA</entry> + <entry>Tool to manage your PDA</entry> + <entry>Office</entry> + + </row><row> + <entry>ProjectManagement</entry> + <entry>Project management application</entry> + <entry>Office;Development</entry> + + </row><row> + <entry>Presentation</entry> + <entry>Presentation software</entry> + <entry>Office</entry> + + </row><row> + <entry>Spreadsheet</entry> + <entry>A spreadsheet</entry> + <entry>Office</entry> + + </row><row> + <entry>WordProcessor</entry> + <entry>A word processor</entry> + <entry>Office</entry> + + </row><row> + <entry>2DGraphics</entry> + <entry>2D based graphical application</entry> + <entry>Graphics</entry> + + </row><row> + <entry>VectorGraphics</entry> + <entry>Application for viewing, creating, or processing vector graphics</entry> + <entry>Graphics;2DGraphics</entry> + + </row><row> + <entry>RasterGraphics</entry> + <entry>Application for viewing, creating, or processing raster (bitmap) graphics</entry> + <entry>Graphics;2DGraphics</entry> + + </row><row> + <entry>3DGraphics</entry> + <entry>Application for viewing, creating, or processing 3-D graphics</entry> + <entry>Graphics</entry> + + </row><row> + <entry>Scanning</entry> + <entry>Tool to scan a file/text</entry> + <entry>Graphics</entry> + + </row><row> + <entry>OCR</entry> + <entry>Optical character recognition application</entry> + <entry>Graphics;Scanning</entry> + + </row><row> + <entry>Photography</entry> + <entry>Camera tools, etc.</entry> + <entry>Graphics or Office</entry> + + </row><row> + <entry>Publishing</entry> + <entry>Desktop Publishing applications and Color Management tools</entry> + <entry>Graphics or Office</entry> + + </row><row> + <entry>Viewer</entry> + <entry>Tool to view e.g. a graphic or pdf file</entry> + <entry>Graphics or Office</entry> + + </row><row> + <entry>TextTools</entry> + <entry>A text tool utiliy</entry> + <entry>Utility</entry> + + </row><row> + <entry>DesktopSettings</entry> + <entry>Configuration tool for the GUI</entry> + <entry>Settings</entry> + + </row><row> + <entry>HardwareSettings</entry> + <entry>A tool to manage hardware components, like sound cards, video cards or printers</entry> + <entry>Settings</entry> + + </row><row> + <entry>Printing</entry> + <entry>A tool to manage printers</entry> + <entry>HardwareSettings;Settings</entry> + + </row><row> + <entry>PackageManager</entry> + <entry>A package manager application</entry> + <entry>Settings</entry> + + </row><row> + <entry>Dialup</entry> + <entry>A dial-up program</entry> + <entry>Network</entry> + + </row><row> + <entry>InstantMessaging</entry> + <entry>An instant messaging client</entry> + <entry>Network</entry> + + </row><row> + <entry>Chat</entry> + <entry>A chat client</entry> + <entry>Network</entry> + + </row><row> + <entry>IRCClient</entry> + <entry>An IRC client</entry> + <entry>Network</entry> + + </row><row> + <entry>FileTransfer</entry> + <entry>Tools like FTP or P2P programs</entry> + <entry>Network</entry> + + </row><row> + <entry>HamRadio</entry> + <entry>HAM radio software</entry> + <entry>Network or Audio</entry> + + </row><row> + <entry>News</entry> + <entry>A news reader or a news ticker</entry> + <entry>Network</entry> + + </row><row> + <entry>P2P</entry> + <entry>A P2P program</entry> + <entry>Network</entry> + + </row><row> + <entry>RemoteAccess</entry> + <entry>A tool to remotely manage your PC</entry> + <entry>Network</entry> + + </row><row> + <entry>Telephony</entry> + <entry>Telephony via PC</entry> + <entry>Network</entry> + + </row><row> + <entry>TelephonyTools</entry> + <entry>Telephony tools, to dial a number, manage PBX, ...</entry> + <entry>Utility</entry> + + </row><row> + <entry>VideoConference</entry> + <entry>Video Conference software</entry> + <entry>Network</entry> + + </row><row> + <entry>WebBrowser</entry> + <entry>A web browser</entry> + <entry>Network</entry> + + </row><row> + <entry>WebDevelopment</entry> + <entry>A tool for web developers</entry> + <entry>Network or Development</entry> + + </row><row> + <entry>Midi</entry> + <entry>An app related to MIDI</entry> + <entry>AudioVideo;Audio</entry> + + </row><row> + <entry>Mixer</entry> + <entry>Just a mixer</entry> + <entry>AudioVideo;Audio</entry> + + </row><row> + <entry>Sequencer</entry> + <entry>A sequencer</entry> + <entry>AudioVideo;Audio</entry> + + </row><row> + <entry>Tuner</entry> + <entry>A tuner</entry> + <entry>AudioVideo;Audio</entry> + + </row><row> + <entry>TV</entry> + <entry>A TV application</entry> + <entry>AudioVideo;Video</entry> + + </row><row> + <entry>AudioVideoEditing</entry> + <entry>Application to edit audio/video files</entry> + <entry>Audio or Video or AudioVideo</entry> + + </row><row> + <entry>Player</entry> + <entry>Application to play audio/video files</entry> + <entry>Audio or Video or AudioVideo</entry> + + </row><row> + <entry>Recorder</entry> + <entry>Application to record audio/video files</entry> + <entry>Audio or Video or AudioVideo</entry> + + </row><row> + <entry>DiscBurning</entry> + <entry>Application to burn a disc</entry> + <entry>AudioVideo</entry> + + </row><row> + <entry>ActionGame</entry> + <entry>An action game</entry> + <entry>Game</entry> + + </row><row> + <entry>AdventureGame</entry> + <entry>Adventure style game</entry> + <entry>Game</entry> + + </row><row> + <entry>ArcadeGame</entry> + <entry>Arcade style game</entry> + <entry>Game</entry> + + </row><row> + <entry>BoardGame</entry> + <entry>A board game</entry> + <entry>Game</entry> + + </row><row> + <entry>BlocksGame</entry> + <entry>Falling blocks game</entry> + <entry>Game</entry> + + </row><row> + <entry>CardGame</entry> + <entry>A card game</entry> + <entry>Game</entry> + + </row><row> + <entry>KidsGame</entry> + <entry>A game for kids</entry> + <entry>Game</entry> + + </row><row> + <entry>LogicGame</entry> + <entry>Logic games like puzzles, etc</entry> + <entry>Game</entry> + + </row><row> + <entry>RolePlaying</entry> + <entry>A role playing game</entry> + <entry>Game</entry> + + </row><row> + <entry>Simulation</entry> + <entry>A simulation game</entry> + <entry>Game</entry> + + </row><row> + <entry>SportsGame</entry> + <entry>A sports game</entry> + <entry>Game</entry> + + </row><row> + <entry>StrategyGame</entry> + <entry>A strategy game</entry> + <entry>Game</entry> + + </row><row> + <entry>Art</entry> + <entry>Software to teach arts</entry> + <entry>Education</entry> + + </row><row> + <entry>Construction</entry> + <entry></entry> + <entry>Education</entry> + + </row><row> + <entry>Music</entry> + <entry>Musical software</entry> + <entry>AudioVideo;Education</entry> + + </row><row> + <entry>Languages</entry> + <entry>Software to learn foreign languages</entry> + <entry>Education</entry> + + </row><row> + <entry>Science</entry> + <entry>Scientific software</entry> + <entry>Education</entry> + + </row><row> + <entry>ArtificialIntelligence</entry> + <entry>Artificial Intelligence software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Astronomy</entry> + <entry>Astronomy software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Biology</entry> + <entry>Biology software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Chemistry</entry> + <entry>Chemistry software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>ComputerScience</entry> + <entry>ComputerSience software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>DataVisualization</entry> + <entry>Data visualization software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Economy</entry> + <entry>Economy software</entry> + <entry>Education</entry> + + </row><row> + <entry>Electricity</entry> + <entry>Electricity software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Geography</entry> + <entry>Geography software</entry> + <entry>Education</entry> + + </row><row> + <entry>Geology</entry> + <entry>Geology software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Geoscience</entry> + <entry>Geoscience software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>History</entry> + <entry>History software</entry> + <entry>Education</entry> + + </row><row> + <entry>ImageProcessing</entry> + <entry>Image Processing software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Literature</entry> + <entry>Literature software</entry> + <entry>Education</entry> + + </row><row> + <entry>Math</entry> + <entry>Math software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>NumericalAnalysis</entry> + <entry>Numerical analysis software</entry> + <entry>Education;Science;Math</entry> + + </row><row> + <entry>MedicalSoftware</entry> + <entry>Medical software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Physics</entry> + <entry>Physics software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Robotics</entry> + <entry>Robotics software</entry> + <entry>Education;Science</entry> + + </row><row> + <entry>Sports</entry> + <entry>Sports software</entry> + <entry>Education</entry> + + </row><row> + <entry>ParallelComputing</entry> + <entry>Parallel computing software</entry> + <entry>Education;Science;ComputerScience</entry> + + </row><row> + <entry>Amusement</entry> + <entry>A simple amusement</entry> + <entry></entry> + + + </row><row> + <entry>Archiving</entry> + <entry>A tool to archive/backup data</entry> + <entry>Utility</entry> + + </row><row> + <entry>Compression</entry> + <entry>A tool to manage compressed data/archives</entry> + <entry>Utility;Archiving</entry> + + </row><row> + <entry>Electronics</entry> + <entry>Electronics software, e.g. a circuit designer</entry> + <entry></entry> + + </row><row> + <entry>Emulator</entry> + <entry>Emulator of another platform, such as a DOS emulator</entry> + <entry>System or Game</entry> + + </row><row> + <entry>Engineering</entry> + <entry>Engineering software, e.g. CAD programs</entry> + <entry></entry> + + </row><row> + <entry>FileTools</entry> + <entry>A file tool utility</entry> + <entry>Utility or System</entry> + + </row><row> + <entry>FileManager</entry> + <entry>A file manager</entry> + <entry>System;FileTools</entry> + + </row><row> + <entry>TerminalEmulator</entry> + <entry>A terminal emulator application</entry> + <entry>System</entry> + + </row><row> + <entry>Filesystem</entry> + <entry>A file system tool</entry> + <entry>System</entry> + + </row><row> + <entry>Monitor</entry> + <entry>Monitor application/applet that monitors some resource or activity</entry> + <entry>System</entry> + + </row><row> + <entry>Security</entry> + <entry>A security tool</entry> + <entry>Settings or System</entry> + + </row><row> + <entry>Accessibility</entry> + <entry>Accessibility</entry> + <entry>Settings or Utility</entry> + + </row><row> + <entry>Calculator</entry> + <entry>A calculator</entry> + <entry>Utility</entry> + + </row><row> + <entry>Clock</entry> + <entry>A clock application/applet</entry> + <entry>Utility</entry> + + </row><row> + <entry>TextEditor</entry> + <entry>A text editor</entry> + <entry>Utility</entry> + + </row><row> + <entry>Documentation</entry> + <entry>Help or documentation</entry> + <entry></entry> + + </row><row> + <entry>Adult</entry> + <entry>Application handles adult or explicit material</entry> + <entry></entry> + + </row><row> + <entry>Core</entry> + <entry>Important application, core to the desktop such as a file manager or a help browser</entry> + <entry></entry> + + </row><row> + <entry>KDE</entry> + <entry>Application based on KDE libraries</entry> + <entry>QT</entry> + + </row><row> + <entry>GNOME</entry> + <entry>Application based on GNOME libraries</entry> + <entry>GTK</entry> + + </row><row> + <entry>GTK</entry> + <entry>Application based on GTK+ libraries</entry> + <entry></entry> + + </row><row> + <entry>Qt</entry> + <entry>Application based on Qt libraries</entry> + <entry></entry> + + </row><row> + <entry>Motif</entry> + <entry>Application based on Motif libraries</entry> + <entry></entry> + + </row><row> + <entry>Java</entry> + <entry>Application based on Java GUI libraries, such as AWT or Swing</entry> + <entry></entry> + + </row><row> + <entry>ConsoleOnly</entry> + <entry>Application that only works inside a terminal (text-based or command line application)</entry> + <entry></entry> + + </row> + </tbody> + </tgroup> + </informaltable> + + </para> + <para> + The table below describes Reserved Categories. + Reserved Categories have a specific desktop specific meaning + that has not been standardized (yet). Desktop entry files that use + a reserved category MUST also include an appropriate OnlyShowIn= entry + to restrict themselves to those environments that properly support the + reserved category as used. + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>Reserved Category</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>Screensaver</entry> + <entry>A screen saver (launching this desktop entry should activate the screen saver)</entry> + </row><row> + <entry>TrayIcon</entry> + <entry>An application that is primarily an icon for the "system tray" or "notification area" (apps that open a normal window and just happen to have a tray icon as well should not list this category)</entry> + </row><row> + <entry>Applet</entry> + <entry>An applet that will run inside a panel or another such application, likely desktop specific</entry> + </row><row> + <entry>Shell</entry> + <entry>A shell (an actual specific shell such as + <filename>bash</filename> or <filename>tcsh</filename>, not a TerminalEmulator)</entry> + </row> + </tbody> + </tgroup> + </informaltable> + + </para> + </appendix> + <appendix id="onlyshowin-registry"> + <title>Registered OnlyShowIn Environments</title> + <para> + Remember, these are case-sensitive. "KDE" not "kde" should be + used. + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>OnlyShowIn Value</entry> + <entry>Environment</entry> + </row> + </thead> + <tbody> + <row> + <entry>GNOME</entry><entry>GNOME Desktop</entry> + </row><row> + <entry>KDE</entry><entry>KDE Desktop</entry> + </row><row> + <entry>LXDE</entry><entry>LXDE Desktop</entry> + </row><row> + <entry>MATE</entry><entry>MATÉ Desktop</entry> + </row><row> + <entry>Razor</entry><entry>Razor-qt Desktop</entry> + </row><row> + <entry>ROX</entry><entry>ROX Desktop</entry> + </row><row> + <entry>Unity</entry><entry>Unity Shell</entry> + </row><row> + <entry>XFCE</entry><entry>XFCE Desktop</entry> + </row><row> + <entry>Old</entry><entry>Legacy menu systems</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </appendix> + <appendix id="third-party-howto"> + <title>Integrating your application in the menus</title> + <sect1 id="adding-items"> + <title>Adding menu items</title> + <para> + The following steps describe how a third party application can add + menu items to the menu system: + <itemizedlist> + <listitem> + <para> + Install desktop entries to + <replaceable>datadir</replaceable>/applications/ for each menu + item. Please namespace the filename, as in "vendor-foo.desktop", or + use a subdirectory of + <replaceable>datadir</replaceable>/applications/ so you have + "vendor/foo.desktop." Please be sure all desktop entries are valid + (see the <ulink + url="http://www.freedesktop.org/software/desktop-file-utils/"> + desktop-file-utils</ulink> package for a validation utility). + </para> + </listitem> + <listitem> + <para> + Install an XML menu file to <replaceable>sysconfdir</replaceable>/menus/applications-merged/ to add any submenus, if your desktop entries aren't already + included in some common categories. + </para> + </listitem> + <listitem> + <para> + Install any directory entries needed for your submenus to <replaceable>datadir</replaceable>/desktop-directories/, taking care to namespace and validate + the directory entries. + </para> + </listitem> + </itemizedlist> + </para> + </sect1> + <sect1 id="locations"> + <title>Install Locations</title> + <para> + If an application is intended to be installed by root on a system wide + basis then /usr/share is recommended to be used as value for + <replaceable>datadir</replaceable> and /etc/xdg is recommended to be + used as value for <replaceable>sysconfdir</replaceable>. + In case the /usr/share hierarchy is not writable it is recommended to + use /usr/local/share as value for <replaceable>datadir</replaceable> + instead. + </para> + <para> + If an application is intended to be installed by an unprivileged user + for exclusive use by that user only then + <varname>$XDG_DATA_HOME</varname> should be used as value + for <replaceable>datadir</replaceable> and + <varname>$XDG_CONFIG_HOME</varname> should be used as value + for <replaceable>sysconfdir</replaceable>. + If <varname>$XDG_DATA_HOME</varname> is not set, the default value of + $HOME/.local/share should be used for it. + If <varname>$XDG_CONFIG_HOME</varname> is not set, the default value of + $HOME/.config should be used for it. + </para> + </sect1> + <sect1 id="menu-add-example"> + <title>Example</title> + <para> + The company ShinyThings Inc. has developed an application named + <emphasis>WebMirror 1.0</emphasis> and would like to add its own + submenu to the system menus consisting of a <emphasis>WebMirror</emphasis> + menu item and a <emphasis>WebMirror Admin Tool</emphasis> + menu item. The company will use "shinythings" as its vendor id. + For the purpose of this example all menu items will be available + in two languages, English and Dutch. + The language code for Dutch is <emphasis>nl</emphasis>. + </para> + <para> + First the company needs to create two .desktop files that describe + the two menu items: + <informalexample> + <programlisting> + <replaceable>datadir</replaceable>/applications/shinythings-webmirror.desktop: + + [Desktop Entry] + Encoding=UTF-8 + Type=Application + + Exec=webmirror + Icon=webmirror + + Name=WebMirror + Name[nl]=WebSpiegel + </programlisting> + </informalexample> + and + <informalexample> + <programlisting> + <replaceable>datadir</replaceable>/applications/shinythings-webmirror-admin.desktop: + + [Desktop Entry] + Encoding=UTF-8 + Type=Application + + Exec=webmirror-admintool + Icon=webmirror-admintool + + Name=WebMirror Admin Tool + Name[nl]=WebSpiegel Administratie Tool + </programlisting> + </informalexample> + A .directory file needs to be installed to provide a title and icon + for the sub-menu itself: + <informalexample> + <programlisting> + <replaceable>datadir</replaceable>/desktop-directories/shinythings-webmirror.directory: + + [Desktop Entry] + Encoding=UTF-8 + + Icon=webmirror + + Name=WebMirror + Name[nl]=WebSpiegel + </programlisting> + </informalexample> + And finally, a .menu file needs to be provided that links it all + togther: + <informalexample> + <programlisting> + <replaceable>sysconfdir</replaceable>/menus/application-merged/shinythings-webmirror.menu: + + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu &dtd-version;//EN" + "http://www.freedesktop.org/standards/menu-spec/menu-&dtd-version;.dtd"> + <Menu> + <Name>Applications</Name> + <Menu> + <Name>WebMirror</Name> + <Directory>shinythings-webmirror.directory</Directory> + <Include> + <Filename>shinythings-webmirror.desktop</Filename> + <Filename>shinythings-webmirror-admin.desktop</Filename> + </Include> + </Menu> + </programlisting> + </informalexample> + + </para> + </sect1> + <sect1 id="compatibility"> + <title>Backward Compatibility</title> + <para> + For a limited time, installing a directory hierarchy to + the old GNOME/KDE specific locations such as /usr/share/applnk and + /usr/share/gnome/apps will continue to work as way to add your + application to the menu system as well. There are two ways to support + both the old and new menu systems at the same time: + <itemizedlist> + <listitem> + <para> + If you add a <varname>Categories</varname> line to the desktop + entries in the legacy hierarchy, implementations of this + specification will ignore their location in the legacy hierarchy, + and arrange them according to <varname>Categories</varname> instead. + This allows you to install a single desktop file that works in all + cases, though on the down side it's in a legacy location. + </para> + </listitem> + <listitem> + <para> + If you add the line <literal>OnlyShowIn=Old;</literal> to a desktop + entry, then old legacy implementations that ignore + <varname>OnlyShowIn</varname> will still show the desktop entry, but + implementations of this specification will not. Thus you can + add an "<literal>OnlyShowIn=Old;</literal>" entry to the legacy + hierarchy, and a new-style desktop entry to + <replaceable>datadir</replaceable>/applications/, and still get + only one entry in the menus. + </para> + </listitem> + </itemizedlist> + </para> + </sect1> + </appendix> + <appendix id="implementation-notes"> + <title>Implementation notes</title> + <sect1 id="menu-editing"> + <title>Menu editing</title> + <para> + To implement menu editing, the intent is that a per-user file is + created. The per-user file should specify a <MergeFile> with the + system wide file, so that system changes are inherited. When the user + deletes a menu item, you add + <literal><Exclude><Filename>foo.desktop</Filename></Exclude></literal>. If + the user adds a menu item, you use + <literal><Include><Filename>foo.desktop</Filename></Include></literal>. + </para> + <para> + If the user moves a folder you can use <Move> elements + to represent the move. <Move> elements used for menu-editing + should always be added to the most top-level menu to ensure that moves + are performed in the order in which they are specified; moves specified + in child menus are always performed before moves specified in a more + top level menu regardless of their location in the menu file. + </para> + <para> + To delete a folder, simply append the <Deleted> element. + </para> + <para> + When adding a new folder or moving an existing folder, menu editing + implementations are advised not to re-use the menu path of a previously + deleted folder. + </para> + <para> + Menu editors probably need to do some kind of consolidation/compression + to avoid an XML tree that grows infinitely over time. + </para> + </sect1> + </appendix> + <glossary><title>Glossary</title> + <para> + This glossary defines some of the terms used in this specification. + </para> + + <glossentry id="term-desktop-entry"><glossterm>Desktop entry</glossterm> + <glossdef> + <para> + A desktop entry is a file with a name ending in the ".desktop" + extension which conforms to the <ulink + url="http://www.freedesktop.org/Standards/desktop-entry-spec">desktop + entry specification</ulink> with <literal>Type=Application</literal>. + It describes a menu item, including a name, an icon, and what to do when the item is selected. + Desktop entries are also known as ".desktop files." + </para> + </glossdef> + </glossentry> + + <glossentry id="term-desktop-file-id"><glossterm>Desktop-File Id</glossterm> + <glossdef> + <para> + The id to identify a desktop entry with. + For example, if <filename>/usr/share/applications</filename> is + specified as an <AppDir>, and <filename>/opt/ude</filename> + as <LegacyDir prefix="foo-"> + then + <filename>/usr/share/applications/foo/bar.desktop</filename>, + <filename>/usr/share/applications/foo-bar.desktop</filename> + and + <filename>/opt/ude/Settings/bar.desktop</filename> all have + the same desktop-file id <literal>foo-bar.desktop</literal> + </para> + </glossdef> + </glossentry> + + <glossentry id="term-directory-entry"><glossterm>Directory entry</glossterm> + <glossdef> + <para> + A directory entry is a file with a name ending in the ".directory" + extension which conforms to the <ulink + url="http://www.freedesktop.org/Standards/desktop-entry-spec">desktop + entry specification</ulink> with <literal>Type=Directory</literal>. + It provides a localized name and an icon for a submenu. + Directory entries are also known as ".directory files." + </para> + </glossdef> + </glossentry> + + <glossentry id="term-menu-path"><glossterm>Menu path</glossterm> + <glossdef> + <para> + A "menu path" is the path to a particular menu. Menu paths are + always "relative" so never start with a slash character. + The path to a menu is simply the <Name> of each parent + of the menu, followed by the <Name> of the menu itself. + For example, "Foo/Bar/Baz" is a valid menu path. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-relative-path"><glossterm>Relative path</glossterm> + <glossdef> + <para> + The canonical path to a directory entry, relative to the + <DirectoryDir> containing the + entry. For example, if <filename>/usr/share/desktop-directories</filename> is + specified as an <DirectoryDir>, the relative path to + <filename>/usr/share/desktop-directories/foo/bar.directory</filename> is + <filename>foo/bar.directory</filename>. + </para> + </glossdef> + </glossentry> + </glossary> +</article> + diff --git a/menu/menu.dtd b/menu/menu.dtd new file mode 100644 index 0000000..1bca3ed --- /dev/null +++ b/menu/menu.dtd @@ -0,0 +1,84 @@ +<!-- For explanations see http://www.freedesktop.org/standards/menu-spec --> +<!ELEMENT Menu ( + Name, ( + Directory + | DefaultAppDirs + | AppDir + | DefaultDirectoryDirs + | DirectoryDir + | LegacyDir + | KDELegacyDirs + | MergeFile + | DefaultMergeDirs + | MergeDir + | OnlyUnallocated + | NotOnlyUnallocated + | Deleted + | NotDeleted + | Include + | Exclude + | Move + | Menu + | Layout + | DefaultLayout + )* +)> + +<!ELEMENT Name (#PCDATA)> + +<!ELEMENT Directory (#PCDATA)> + +<!ELEMENT DefaultAppDirs EMPTY> +<!ELEMENT AppDir (#PCDATA)> + +<!ELEMENT DefaultDirectoryDirs EMPTY> +<!ELEMENT DirectoryDir (#PCDATA)> + +<!ELEMENT LegacyDir (#PCDATA)> +<!ATTLIST LegacyDir prefix CDATA #IMPLIED> +<!ELEMENT KDELegacyDirs EMPTY> + +<!ELEMENT MergeFile (#PCDATA)> +<!ATTLIST MergeFile type (path|parent) #IMPLIED> + +<!ELEMENT DefaultMergeDirs EMPTY> +<!ELEMENT MergeDir (#PCDATA)> + +<!ELEMENT OnlyUnallocated EMPTY> +<!ELEMENT NotOnlyUnallocated EMPTY> + +<!ELEMENT Deleted EMPTY> +<!ELEMENT NotDeleted EMPTY> + +<!ELEMENT Exclude ((Category|Filename|And|Or|Not|All)*)> +<!ELEMENT Include ((Category|Filename|And|Or|Not|All)*)> + +<!ELEMENT And ((Category|Filename|And|Or|Not|All)*)> +<!ELEMENT Or ((Category|Filename|And|Or|Not|All)*)> +<!ELEMENT Not ((Category|Filename|And|Or|Not|All)*)> +<!ELEMENT Filename (#PCDATA)> +<!ELEMENT Category (#PCDATA)> +<!ELEMENT All EMPTY> + +<!ELEMENT Move ((Old,New)*)> +<!ELEMENT Old (#PCDATA)> +<!ELEMENT New (#PCDATA)> + +<!ELEMENT Layout ((Filename|Menuname|Separator|Merge)*)> +<!ELEMENT DefaultLayout ((Filename|Menuname|Separator|Merge)*)> +<!ATTLIST DefaultLayout show_empty (true|false) #IMPLIED> +<!ATTLIST DefaultLayout inline (true|false) #IMPLIED> +<!ATTLIST DefaultLayout inline_limit CDATA #IMPLIED> +<!ATTLIST DefaultLayout inline_header (true|false) #IMPLIED> +<!ATTLIST DefaultLayout inline_alias (true|false) #IMPLIED> + +<!ELEMENT Menuname (#PCDATA)> +<!ATTLIST Menuname inline (true|false) #IMPLIED> +<!ATTLIST Menuname inline_limit CDATA #IMPLIED> +<!ATTLIST Menuname inline_header (true|false) #IMPLIED> +<!ATTLIST Menuname inline_alias (true|false) #IMPLIED> + +<!ELEMENT Separator EMPTY> + +<!ELEMENT Merge EMPTY> +<!ATTLIST Merge type (menus|files|all) #REQUIRED> diff --git a/menu/tests/ChangeLog b/menu/tests/ChangeLog new file mode 100644 index 0000000..ac55e4f --- /dev/null +++ b/menu/tests/ChangeLog @@ -0,0 +1,70 @@ +2005-04-25 Mark McLoughlin <mark@skynet.ie> + + * tests/u: add test for recursive inclusion of .menu files. + Also know as the "get really hosed and eat all the RAM + you can find" test. + +2005-04-20 Waldo Bastian <bastian@kde.org> + + * tests/s/result, + tests/s/test: Test that .desktop files under $HOME correctly + override .desktop files at system level + + * tests/t/result, + tests/t/test: Test order in which <Move> elements are processed + +2005-02-18 Mark McLoughlin <mark@skynet.ie> + + Make it a bit more difficult in order to catch: + http://bugzilla.gnome.org/show_bug.cgi?id=167758 + Thanks to Chris Lahey for the test case. + + * tests/o/test: put freecell.desktop in a subdirectory. + +2005-02-18 Mark McLoughlin <mark@skynet.ie> + + * tests/o/result, + tests/o/test: test that + <And><Category>foo</Category><Not><Category>foo</Category></Not></And> + doesn't match anything. + + * README: add bit about how to test the GNOME impl. + +2005-02-18 Mark McLoughlin <mark@skynet.ie> + + Problem pointed out by Waldo. + + * menutest: don't try and run the "CVS" test :) + + * tests/m/result, + tests/n/result: items in a hidden or deleted menu + should be considered allocated. + +2004-12-08 Mark McLoughlin <mark@skynet.ie> + + * tests/2/result, + tests/2/test: test the new <OnlyUnallocated> behaviour. + +2004-08-29 Mark McLoughlin <mark@skynet.ie> + + * tests/m: test for NoDisplay=true behavious in .desktop and + .directory files. + + * data/hidden.desktop, + data/hidden.directory: add. + + * data/apps.directory: add Type=Directory. + + * menutest: actually generate a test result if one doesn't + exist - makes it easier to write new tests. + +2003-10-23 Havoc Pennington <hp@redhat.com> + + * tests/f/test: remove <OnlyUnallocated/> from inside <Include> + statement, not allowed. + +2003-10-16 Havoc Pennington <hp@redhat.com> + + * menutest: cat log file on failure; print list of failed tests + when we're done + diff --git a/menu/tests/README b/menu/tests/README new file mode 100644 index 0000000..b003dc0 --- /dev/null +++ b/menu/tests/README @@ -0,0 +1,44 @@ +This directory contains regression tests for the menu-spec. + +To run these tests your menu-spec implementation should be +able to generate a menu in the following text format: + +<Full Menu Name><tab><Desktop File Id><tab><Full Path to Desktop File> + +Example: + +Editors/ kde-kwrite.desktop /home/bastian/.local/share/applications/kde-kwrite.desktop +Editors/ kde-kate.desktop /home/bastian/.local/share/applications/kde-kate.desktop +Editors/ kde-KEdit.desktop /home/bastian/.local/share/applications/kde-KEdit.desktop +Development/ kde-gideon.desktop /opt/kde3/share/applnk/Development/gideon.desktop +Development/ kde-kbabel.desktop /opt/kde3/share/applnk/Development/kbabel.desktop +Development/ kde-quanta.desktop /opt/kde3/share/applnk/Development/quanta.desktop +/ kde-Kfind.desktop /opt/kde3/share/applnk/Kfind.desktop +/ kde-Home.desktop /opt/kde3/share/applnk/Home.desktop +/ kde-Help.desktop /opt/kde3/share/applnk/Help.desktop + + + +The environment variable $MENUTEST should point to a command that is +able to generate the menu in the above format. + +To test KDE one can use: + MENUTEST="kbuildsycoca --menutest" + +With GNOME, you can use: + MENUTEST=gnome-menu-spec-test + +The menutest script should be used to run the tests. The following commands can +be used: + + MENUTEST="foo -bar" ./menutest + +to run all tests + + MENUTEST="foo -bar" TESTS="Deleted Directory" ./menutest + +to run the tests named "Deleted" and "Directory" only + +All tests contain of a test setup script named "test" and a file describing +the expected menu named "result". + diff --git a/menu/tests/TODO b/menu/tests/TODO new file mode 100644 index 0000000..6e178bf --- /dev/null +++ b/menu/tests/TODO @@ -0,0 +1,5 @@ +I hope you understand what i mean ;) + +desktop-file-id stuff & overwrite stuff absolute path + +onlyshowin - notshowin diff --git a/menu/tests/data/Help.desktop b/menu/tests/data/Help.desktop new file mode 100644 index 0000000..dc867cd --- /dev/null +++ b/menu/tests/data/Help.desktop @@ -0,0 +1,68 @@ +[Desktop Entry] +Encoding=UTF-8 +Exec=khelpcenter +Icon=khelpcenter +DocPath=khelpcenter/index.html +Type=Application +Terminal=0 + +Name=Help +Name[af]=Hulp +Name[az]=Yardım +Name[be]=Дапамога +Name[bg]=Помощ +Name[br]=Skoazell +Name[bs]=Pomoć +Name[ca]=Ajuda +Name[cs]=NápovÄ›da +Name[cy]=Cymorth +Name[da]=Hjælp +Name[de]=Hilfe +Name[el]=Βοήθεια +Name[eo]=Helpo +Name[es]=Ayuda +Name[et]=Abiinfo +Name[eu]=Laguntza +Name[fa]=راهنما +Name[fi]=Ohje +Name[fr]=Aide +Name[gl]=Axuda +Name[he]=עזרה +Name[hr]=Pomoć +Name[hu]=SegĂtsĂ©g +Name[id]=Keterangan bantu +Name[is]=HjĂ¡lp +Name[it]=Aiuto +Name[ja]=ăă«ă— +Name[ko]=ëŹ„ě›€ë§ +Name[lo]=ລະບົບຊŕ»ŕş§ŕşŤŕ»€ŕş«ŕş·ŕşĄŕş +Name[lt]=Pagalba +Name[lv]=PalÄ«dzÄ«ba +Name[mn]=ТŃŃламж +Name[mt]=Għajnuna +Name[nb]=Hjelp +Name[nn]=Hjelp +Name[nso]=Thuso +Name[oc]=Ajuda +Name[pl]=Pomoc +Name[pt]=Ajuda +Name[pt_BR]=Ajuda +Name[ro]=Ajutor +Name[ru]=Справка +Name[sk]=PomocnĂk +Name[sl]=PomoÄŤ +Name[sr]=Pomoć +Name[ss]=Sita +Name[sv]=Hjälp +Name[ta]=¯¾Å¢ +Name[th]=ระบบชŕąŕ¸§ŕ¸˘ŕą€ŕ¸«ŕ¸Ąŕ¸·ŕ¸ +Name[tr]=Yardım +Name[uk]=Довідка +Name[ven]=Thuso +Name[vi]=Trợ giĂşp +Name[wa]=Aidance +Name[xh]=Uncedo +Name[zh_CN]=帮助 +Name[zh_TW]=求助 +Name[zu]=Usizo + diff --git a/menu/tests/data/Home.desktop b/menu/tests/data/Home.desktop new file mode 100644 index 0000000..2bf8178 --- /dev/null +++ b/menu/tests/data/Home.desktop @@ -0,0 +1,127 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Application +Exec=kfmclient openProfile filemanagement +Icon=folder_home +Terminal=0 + +Name=Home +Name[af]=Huis +Name[az]=BaĹźlanğıc +Name[be]=Хатні +Name[bg]=ДомаŃна директория +Name[br]=Er-gĂÂŞr +Name[bs]=PoÄŤetak +Name[ca]=Inici +Name[cs]=MĹŻj adresář +Name[cy]=Cartref +Name[da]=Hjem +Name[de]=Persönliches Verzeichnis +Name[el]=Σπίτι +Name[eo]=Hejmo +Name[es]=Personal +Name[et]=Kodukataloog +Name[eu]=Etxea +Name[fa]=خانه +Name[fi]=Koti +Name[fr]=Dossier personnel +Name[gl]=Persoal +Name[he]=בית +Name[hr]=PoÄŤetak +Name[hu]=Saját könyvtár +Name[id]=Rumah +Name[is]=HeimasvæðiĂ° ĂÂľitt +Name[ja]=ă›ăĽă +Name[ko]=í™ +Name[lo]=ພື້ນທີŕ»ŕşŞŕ»ŕş§ŕş™ŕş•ŕş»ŕş§ +Name[lt]=PradĹľia +Name[lv]=MÄjas +Name[mn]=ĐĄŃвийн лавлах +Name[mt]=Direttorju Personali +Name[nb]=Hjem +Name[nl]=Persoonlijke map +Name[nn]=Heim +Name[nso]=Gae +Name[oc]=Inici +Name[pl]=Katalog domowy +Name[pt]=Casa +Name[ro]=AcasÄ +Name[ru]=Домой +Name[sk]=Domov +Name[sl]=Domov +Name[sr]=КориŃнички директориŃŃĐĽ +Name[ss]=Ekhaya +Name[sv]=Hem +Name[ta]=¦¾¡¼ì¸õ +Name[th]=พื้นทีŕąŕ¸Şŕąŕ¸§ŕ¸™ŕ¸•ŕ¸±ŕ¸§ +Name[tr]=BaĹźlangıç +Name[uk]=Домівка +Name[ven]=Haya +Name[wa]=MĂĄjhon +Name[xh]=Ikhaya +Name[xx]=xxHomexx +Name[zh_CN]=čµ·ç‚ą +Name[zh_TW]=家目錄 +Name[zu]=Ikhaya + +GenericName=Personal Files +GenericName[af]=Persoonlike LĂŞers +GenericName[az]=Şəxsi Fayllar +GenericName[be]=ПэрŃанальныя файлы +GenericName[bg]=Лични файлове +GenericName[br]=RestroĂÂą deoc'h +GenericName[bs]=Osobne datoteke +GenericName[ca]=Fitxers personals +GenericName[cs]=OsobnĂ soubory +GenericName[cy]=Ffeiliau Personol +GenericName[da]=Personlige filer +GenericName[de]=Eigene Dateien +GenericName[el]=Î ĎÎżĎωπικά ΑĎχεία +GenericName[eo]=Personaj dosieroj +GenericName[es]=Archivos personales +GenericName[et]=Isiklikud failid +GenericName[eu]=Fitxategi Pertsonalak +GenericName[fa]=پرŮنده‌های شخصی +GenericName[fi]=Omat tiedostot +GenericName[fr]=Fichiers personnels +GenericName[gl]=Ficheiros Persoais +GenericName[he]=קבצים ×ישיים +GenericName[hr]=Osobne datoteke +GenericName[hu]=szemĂ©lyes fájlok +GenericName[id]=File Pribadi +GenericName[is]=SkrĂ¡rnar ĂÂľĂÂnar +GenericName[it]=File personali +GenericName[ja]=個人ă®ă•ă‚ˇă‚¤ă« +GenericName[ko]=íĽěžë§Ś 쓰는 파일 +GenericName[lo]=ŕş—ŕşµŕ»ŕ»€ŕşŕş±ŕşšŕ»ŕşźŕ»‰ŕşˇŕ»ŕşĄŕş°ŕ»€ŕşŕşŕş°ŕşŞŕş˛ŕş™ŕşŞŕş§ŕ»ŕş™ŕş•ŕş»ŕş§ŕş«ŕşĄŕş·ŕşŕş·ŕ»ŕş™ŕşŻ +GenericName[lt]=AsmeninÄ—s Bylos +GenericName[lv]=PersonÄlie Faili +GenericName[mn]=Өөрийн файлŃŃĐ´ +GenericName[mt]=Fajls Personali +GenericName[nb]=Personlige filer +GenericName[nl]=persoonlijke bestanden +GenericName[nn]=Personlege filer +GenericName[nso]=Difaele tsa Botho +GenericName[oc]=FiquièRs personals +GenericName[pl]=Pliki osobiste +GenericName[pt]=Ficheiros Pessoais +GenericName[pt_BR]=Arquivos Pessoais +GenericName[ro]=FiĹźiere personale +GenericName[ru]=Личные файлы +GenericName[sk]=OsobnĂ© sĂşbory +GenericName[sl]=Osebne datoteke +GenericName[sr]=ĐžĐ˛Đ°Ń Đ´Đ¸Ń€ĐµĐşŃ‚ĐľŃ€Đ¸ŃŃĐĽ Ńадржи ваŃе личне Ń„Đ°Ńлове +GenericName[sv]=Personliga filer +GenericName[ta]=¦º¡ó¾ì §¸¡ôÒì¸û +GenericName[th]=ทีŕąŕą€ŕ¸ŕą‡ŕ¸šŕąŕ¸źŕą‰ŕ¸ˇŕąŕ¸Ąŕ¸°ŕą€ŕ¸ŕ¸ŕ¸Şŕ¸˛ŕ¸Łŕ¸Şŕąŕ¸§ŕ¸™ŕ¸•ŕ¸±ŕ¸§ หรืŕ¸ŕ¸ŕ¸·ŕąŕ¸™ ๆ +GenericName[tr]=KiĹźisel Dosyalar +GenericName[uk]=ĐžŃобиŃŃ‚Ń– файли +GenericName[ven]=Dzifaela dza vhune +GenericName[vi]=File cá nhân +GenericName[wa]=FitchĂ®s da vosse +GenericName[xh]=Iifayile Zobuqu +GenericName[xx]=xxPersonal Filesxx +GenericName[zh_CN]=个人文件 +GenericName[zh_TW]=ĺ€‹äşşćŞ”ćˇ +GenericName[zu]=Amafayela Omuntu siqu + diff --git a/menu/tests/data/KEdit.desktop b/menu/tests/data/KEdit.desktop new file mode 100644 index 0000000..4274a2b --- /dev/null +++ b/menu/tests/data/KEdit.desktop @@ -0,0 +1,34 @@ +[Desktop Entry] +Encoding=UTF-8 +BinaryPattern=kedit; +MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; +GenericName=Simple Text Editor +GenericName[ca]=Editor de text +GenericName[cs]=JednoduchĂ˝ textovĂ˝ editor +GenericName[da]=Simpel teksteditor +GenericName[es]=Editor de texto sencillo +GenericName[fr]=Éditeur de texte Ă©lĂ©mentaire +GenericName[pt_BR]=Editor de Texto Simples +GenericName[sv]=Enkel texteditor +GenericName[wa]=Simpe aspougneu di tecse +Exec=kedit -caption "%c" %i %m %u +Icon=kedit +TerminalOptions= +Path= +DocPath=kedit/index.html +Type=Application +Terminal=0 +Name=KEdit +Name[af]=Kredigeer +Name[eo]=Redaktilo +Name[hr]=UreÄ‘ivaÄŤ +Name[lv]=KRediÄŁÄ“t +Name[pl]=Edytor +Name[sv]=Kedit +Name[th]=ŕąŕ¸ŕą‰ŕą„ขข้ŕ¸ŕ¸„วาม +Name[ven]=U sengulusa ha K +Name[xh]=Abahleli Be K +Name[zh_TW]=KDE 編輯器 +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;TextEditor diff --git a/menu/tests/data/Kfind.desktop b/menu/tests/data/Kfind.desktop new file mode 100644 index 0000000..8984f18 --- /dev/null +++ b/menu/tests/data/Kfind.desktop @@ -0,0 +1,66 @@ +[Desktop Entry] +Encoding=UTF-8 +Exec=kfind %f +Icon=kfind +DocPath=kfind/index.html +TerminalOptions= +Path= +Type=Application +Terminal=0 +Name=Find Files +Name[af]=Soek LĂŞers +Name[be]=ШŃкаць файлы +Name[bg]=ТърŃене на файлове +Name[br]=Klask restroĂÂą +Name[bs]=PronaÄ‘i datoteke +Name[ca]=Cerca fitxers +Name[cs]=NajĂt soubory +Name[cy]=Canfod Ffeiliau +Name[da]=Find filer +Name[de]=Dateien suchen +Name[el]=ΕύĎεĎη αĎχείων +Name[eo]=Trovu dosierojn +Name[es]=KFind +Name[et]=Failide otsimine +Name[eu]=Fitxategiak Bilatu +Name[fa]=یاŮتن پرŮنده‌ها +Name[fi]=Etsi tiedostoja +Name[fr]=Recherche de fichiers +Name[gl]=Buscar Ficheiros +Name[he]=חפש קבצים +Name[hr]=NaÄ‘i datoteke +Name[hu]=FájlkeresĂ©s +Name[id]=Cari Berkas +Name[it]=Trova file +Name[ja]=ă•ă‚ˇă‚¤ă«ă‚’検索 +Name[ko]=파일 찾기 +Name[lo]=ຄົ້ນຫາŕ»ŕşźŕ»‰ŕşˇ +Name[lt]=Rasti bylas +Name[lv]=MeklÄ“t Failus +Name[mn]=Файл хайх +Name[mt]=Sib Fajls +Name[nb]=Finn filer +Name[nl]=Bestanden zoeken +Name[nn]=Finn filer +Name[nso]=Hwetsa Difaele +Name[oc]=Cerca fiquièrs +Name[pl]=ZnajdĹş pliki +Name[pt]=Procurar Ficheiros +Name[pt_BR]=Encontrar arquivos +Name[ro]=CautÄ fiĹźiere +Name[ru]=ПоиŃĐş файлов +Name[sk]=HÄľadaĹĄ sĂşbory +Name[sl]=Poišči datoteke +Name[sr]=Pretraga fajlova +Name[sv]=Hitta filer +Name[ta]=§¸¡ôÒì ¸ñÎÀ¢Ê +Name[th]=ค้นหาŕąŕ¸źŕą‰ŕ¸ˇ +Name[tr]=Dosyalarda Bul +Name[uk]=Знайти файли +Name[ven]=Todani faela +Name[vi]=Tìm file +Name[xh]=Fumana Iifayile +Name[zh_CN]=查找文件 +Name[zh_TW]=ĺ°‹ć‰ľćŞ”ćˇ +Name[zu]=Thola Amafayela +X-KDE-StartupNotify=true diff --git a/menu/tests/data/apps.directory b/menu/tests/data/apps.directory new file mode 100644 index 0000000..d54b4bd --- /dev/null +++ b/menu/tests/data/apps.directory @@ -0,0 +1,66 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Apps +Name[af]=Programme +Name[ar]=تطبيقات +Name[az]=Proqram TÉ™'minatları +Name[be]=ДаŃŃ‚Đ°Ńаваньні +Name[bg]=Приложения +Name[br]=ArloadoĂÂą +Name[bs]=Aplikacije +Name[ca]=Aplicacions +Name[cs]=Aplikace +Name[da]=Ăvrige programmer +Name[de]=Programme +Name[el]=ΕφαĎμογÎĎ‚ +Name[eo]=Aplikaĵoj +Name[es]=Aplicaciones +Name[et]=Rakendused +Name[eu]=Aplikazioak +Name[fa]=برنامه‌های کاربردی +Name[fi]=Sovellukset +Name[fo]=NĂ˝tsluskipanir +Name[gl]=AplicaciĂłns +Name[he]=יישומים +Name[hr]=Programi +Name[hu]=Alkalmazások +Name[id]=Aplikasi +Name[is]=Forrit +Name[it]=Applicazioni +Name[ja]=アă—ăŞă‚±ăĽă‚·ă§ăł +Name[ko]=ěť‘ěš© 프로그램 +Name[lo]=ŕşŕş±ŕşšŕşžŕşĄŕş´ŕşŕ»€ŕş„ເຊິນ +Name[lt]=Programos +Name[lv]=AplikÄcijas +Name[mk]=Đпликации +Name[mt]=Applikazzjonijiet +Name[nb]=Programmer +Name[nl]=Programma's +Name[nn]=Program +Name[nso]=Ditshomiso +Name[oc]=Aplicacions +Name[pl]=Aplikacje +Name[pt]=Aplicações +Name[pt_BR]=Aplicativos +Name[ro]=AplicaĹŁii +Name[ru]=Приложения +Name[se]=Prográmmat +Name[sk]=Aplikácie +Name[sl]=Uporabniški programi +Name[sr]=Aplikacije +Name[ss]=Ticelo +Name[sv]=Program +Name[ta]=ÀÂýÀ¡Î¸û +Name[th]=ŕąŕ¸ŕ¸žŕ¸žŕ¸Ąŕ¸´ŕą€ŕ¸„ชัน +Name[tr]=Uygulamalar +Name[uk]=Програми +Name[ven]=Apulikhesheni +Name[vi]=Chương trình +Name[wa]=Programes +Name[xh]=Izicelo +Name[zh_CN]=应用程序 +Name[zh_TW]=應用程式 +Name[zu]=Abayaleli +Type=Directory +Icon=package_applications + diff --git a/menu/tests/data/freecell.desktop b/menu/tests/data/freecell.desktop new file mode 100644 index 0000000..da6d251 --- /dev/null +++ b/menu/tests/data/freecell.desktop @@ -0,0 +1,83 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=FreeCell +Name[be]=Вольная ячэя +Name[bg]=Свободна Клетка +Name[bn]=ফ্রীসেল +Name[ca]=FreeCell +Name[cs]=FreeCell +Name[da]=Napoleon +Name[de]=FreeCell +Name[el]=FreeCell +Name[es]=FreeCell +Name[et]=Freecell +Name[fi]=Vapaakenttä +Name[fr]=Freecell +Name[ga]=FreeCell +Name[gl]=FreeCell +Name[he]=פריסל +Name[hu]=FreeCell +Name[it]=FreeCell +Name[ja]=ă•ăŞăĽă‚»ă« +Name[ko]=프리셀 +Name[lt]=FreeCell +Name[lv]=FreeCell +Name[mn]=ФриŃелл +Name[ms]=FreeCell +Name[nl]=FreeCell +Name[no]=Freecell +Name[pl]=FreeCell +Name[pt]=Freecell +Name[pt_BR]=FreeCell +Name[ru]=ФриŃелл +Name[sk]=FreeCell +Name[sl]=FreeCell +Name[sv]=Napoleon pĂĄ S:t Helena +Name[tr]=Ä°skambil falı +Name[uk]=Вільна комірка +Name[vi]=FreeCell +Name[wa]=Freecell +Name[zh_CN]=空当接龙 +Name[zh_TW]=Freecell +Comment=FreeCell game +Comment[be]=Đ“Ńльня Ńž ВольнŃŃŽ ячэю +Comment[bg]=игра Свободна Клетка +Comment[bn]=ফ্রীসেল খেলা +Comment[ca]=Joc del FreeCell +Comment[cs]=Hra FreeCell +Comment[da]=Kortspillet Napoleon +Comment[de]=FreeCell-Spiel +Comment[el]=Το παιχνίδι FreeCell +Comment[es]=Juego FreeCell +Comment[et]=Kaardimäng FreeCell +Comment[fi]=Vapaakenttä-peli +Comment[fr]=Jeu de cartes Freecell +Comment[he]=משחק פריסל +Comment[hu]=FreeCell játĂ©k +Comment[it]=FreeCell +Comment[ja]=ă•ăŞăĽă‚»ă«ă® GNOME ç‰ +Comment[lv]=FreeCell spÄ“le +Comment[mn]=GNOME ФриŃелл тоглоом +Comment[ms]=Permainan FreeCell +Comment[nl]=FreeCell Spel +Comment[no]=Spillet FreeCell +Comment[pl]=Gra FreeCell +Comment[pt]=Jogo FreeCell +Comment[pt_BR]=Jogo de FreeCell +Comment[ru]=ПаŃŃŚŃŹĐ˝Ń "Ячейка" +Comment[sk]=Hra FreeCell +Comment[sl]=Igra Freecell +Comment[sv]=Spelet Napoleon pĂĄ S:t Helena +Comment[tr]=Ä°skambil falı oyunu +Comment[uk]=Гра "Вільна комірка" +Comment[vi]=Trò chơi FreeCell +Comment[zh_TW]=Freecell 紙牌接龍éŠć˛ +Exec=freecell +Icon=gnome-cardgame.png +Terminal=false +Type=Application +Categories=GNOME;Application;Game;CardGame; +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=gnome-games +X-GNOME-Bugzilla-Component=freecell +StartupNotify=true diff --git a/menu/tests/data/gataxx.desktop b/menu/tests/data/gataxx.desktop new file mode 100644 index 0000000..10dfec6 --- /dev/null +++ b/menu/tests/data/gataxx.desktop @@ -0,0 +1,81 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=gataxx.png +Name=Gataxx +Name[am]=Gataxx +Name[be]=Gataxx +Name[bg]=Đ“Đ°Ń‚Đ°ĐşŃŃ +Name[bn]=জীঅ্যাটাক্স +Name[ca]=Gataxx +Name[cs]=Gataxx +Name[da]=Ataxx +Name[de]=Gataxx +Name[el]=Gataxx +Name[es]=Gataxx +Name[et]=Gataxx +Name[fi]=Gataxx +Name[fr]=Gataxx +Name[he]=Gataxx +Name[hu]=Gataxx +Name[it]=Gataxx +Name[ja]=Gataxx +Name[ko]=Gataxx +Name[lv]=Gataxx +Name[mn]=Gataxx +Name[ms]=Gataxx +Name[nl]=Gataxx +Name[no]=Gataxx +Name[pl]=Gataxx +Name[pt]=Gataxx +Name[pt_BR]=Gataxx +Name[ru]=Gataxx +Name[sk]=Gataxx +Name[sl]=Gataxx +Name[sv]=Gataxx +Name[tr]=Gataxx +Name[uk]=Đтаки +Name[vi]=Gataxx +Name[wa]=Gataxx +Name[zh_CN]=Gataxx +Name[zh_TW]=Gataxx +Comment=Ataxx game +Comment[be]=Đ“Ńльня Ataxx +Comment[bg]=Đгра Đ°Ń‚Đ°ĐşŃŃ +Comment[bn]=অ্যাটাক্স খেলা +Comment[ca]=Joc del Ataxx +Comment[cs]=Hra Ataxx +Comment[da]=Spillet Ataxx +Comment[de]=Ataxx-Spiel +Comment[el]=Παιχνίδι Ataxx +Comment[es]=Un juego tipo Ataxx. +Comment[et]=Mäng nimega ataxx +Comment[fi]=Ataxx-peli +Comment[fr]=Jeu Ataxx +Comment[he]=משחק Ataxx +Comment[hu]=Ataxx játĂ©k +Comment[it]=Gioco Ataxx +Comment[ja]=Ataxx ゲăĽă +Comment[lv]=Ataxx spÄ“le +Comment[mn]=Ataxx тоглоом. +Comment[ms]=Permainan Ataxx +Comment[nl]=Ataxx +Comment[no]=Ataxx-spill +Comment[pl]=Gra Ataxx +Comment[pt]=Jogo Ataxx +Comment[pt_BR]=Jogo Ataxx +Comment[ru]=Đгра ataxx +Comment[sk]=Hra Ataxx +Comment[sl]=Igra Ataxx +Comment[sv]=Spelet Ataxx +Comment[tr]=Ataxx oyunu +Comment[uk]=Гра "Đтаки" +Comment[vi]=Trò chơi Ataxx. +Comment[zh_TW]=Ataxx éŠć˛ +Exec=gataxx +Terminal=false +Type=Application +Categories=GNOME;Application;Game;BoardGame; +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=gnome-games +X-GNOME-Bugzilla-Component=gataxx +StartupNotify=true diff --git a/menu/tests/data/gideon-legacy.desktop b/menu/tests/data/gideon-legacy.desktop new file mode 100644 index 0000000..4595087 --- /dev/null +++ b/menu/tests/data/gideon-legacy.desktop @@ -0,0 +1,12 @@ +[KDE Desktop Entry] +Encoding=UTF-8 +BinaryPattern=kdevelop; +Type=Application +Exec=gideon %u +MimeType=application/x-kdevelop; +Icon=gideon +DocPath=kdevelop/index.html +Terminal=0 +Name=KDevelop 3.0 +Comment=IDE for C++/Qt/KDE +X-DCOP-ServiceType=Multi diff --git a/menu/tests/data/gideon.desktop b/menu/tests/data/gideon.desktop new file mode 100644 index 0000000..1e11dc1 --- /dev/null +++ b/menu/tests/data/gideon.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Encoding=UTF-8 +BinaryPattern=kdevelop; +Type=Application +Exec=gideon %u +MimeType=application/x-kdevelop; +Icon=gideon +DocPath=kdevelop/index.html +Terminal=0 +Name=KDevelop 3.0 +Comment=IDE for C++/Qt/KDE +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Development diff --git a/menu/tests/data/glines-2.desktop b/menu/tests/data/glines-2.desktop new file mode 100644 index 0000000..266747d --- /dev/null +++ b/menu/tests/data/glines-2.desktop @@ -0,0 +1,83 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Glines +Name[be]=Glines +Name[bg]=ГЛинии +Name[bn]=জীলাইন্‌স +Name[ca]=Glines +Name[cs]=Glines +Name[da]=Linjer +Name[de]=Glines +Name[el]=Glines +Name[es]=Glines +Name[et]=Glines +Name[eu]=Glines +Name[fi]=Glines +Name[fr]=Glines +Name[he]=Glines +Name[hu]=Glines +Name[it]=Glines +Name[ja]=Glines +Name[ko]=Glines +Name[lt]=Glines +Name[lv]=Glines +Name[mn]=Glines +Name[ms]=Glines +Name[nl]=GLines +Name[no]=Glines +Name[pl]=Glines +Name[pt]=GLinhas +Name[pt_BR]=Glines +Name[ro]=Glines +Name[ru]=Glines +Name[sk]=GÄŚiary +Name[sl]=Glines +Name[sv]=Glinjer +Name[tr]=Sıradaki toplar +Name[uk]=Ряди +Name[vi]=Glines +Name[wa]=GRoyes +Name[zh_CN]=Glines +Name[zh_TW]=Glines +Comment=Color lines game +Comment[be]=Đ“Ńльня "Каляровыя лініі" +Comment[bg]=Đгра Цветни линии +Comment[bn]=কালার লাইন্‌স খেলা +Comment[ca]=Joc de lĂnies de color +Comment[cs]=Hra BarevnĂ© linie +Comment[da]=Farvede linjer-spil +Comment[de]=Farblinienspiel +Comment[el]=Παιχνίδι ÎłĎαμμών χĎώματος +Comment[es]=Juego del tipo lĂneas de colores. +Comment[fi]=Väriviivapeli +Comment[fr]=Jeu de lignes colorĂ©es +Comment[he]=משחק שורות ×¦×‘×˘×•× ×™×•×Ş +Comment[hu]=Color lines játĂ©k +Comment[it]=Gioco Color Lines +Comment[ja]=ă‚«ă©ăĽă©ă‚¤ăłă®ă‚˛ăĽă +Comment[lv]=KrÄsu lÄ«niju spÄ“le +Comment[mn]=Өнгөт бөмбөлөг тоглоом +Comment[ms]=Permainan garisan warna +Comment[nl]=Kleurlijnen +Comment[no]=Spill med fargelinjer +Comment[pl]=Gra w kolorowe linie +Comment[pt]=Jogo das linhas coloridas +Comment[pt_BR]=Jogo de linhas coloridas +Comment[ru]=Đгра "Цветные линии" +Comment[sk]=Hra FarebnĂ© ÄŤiary +Comment[sl]=Igra barvnih ÄŤrt +Comment[sv]=Färglinjespel +Comment[tr]=Color lines oyunu +Comment[uk]=Гра "Кольорові ряди" +Comment[vi]=Trò chơi ColorLines +Comment[zh_TW]=Color lines éŠć˛ +Exec=glines +Icon=glines.png +Terminal=false +Type=Application +Categories=GNOME;Application;Game;PuzzleGame; +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=gnome-games +X-GNOME-Bugzilla-Component=glines +StartupNotify=true +NoDisplay=true diff --git a/menu/tests/data/glines.desktop b/menu/tests/data/glines.desktop new file mode 100644 index 0000000..5e5b465 --- /dev/null +++ b/menu/tests/data/glines.desktop @@ -0,0 +1,82 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Glines +Name[be]=Glines +Name[bg]=ГЛинии +Name[bn]=জীলাইন্‌স +Name[ca]=Glines +Name[cs]=Glines +Name[da]=Linjer +Name[de]=Glines +Name[el]=Glines +Name[es]=Glines +Name[et]=Glines +Name[eu]=Glines +Name[fi]=Glines +Name[fr]=Glines +Name[he]=Glines +Name[hu]=Glines +Name[it]=Glines +Name[ja]=Glines +Name[ko]=Glines +Name[lt]=Glines +Name[lv]=Glines +Name[mn]=Glines +Name[ms]=Glines +Name[nl]=GLines +Name[no]=Glines +Name[pl]=Glines +Name[pt]=GLinhas +Name[pt_BR]=Glines +Name[ro]=Glines +Name[ru]=Glines +Name[sk]=GÄŚiary +Name[sl]=Glines +Name[sv]=Glinjer +Name[tr]=Sıradaki toplar +Name[uk]=Ряди +Name[vi]=Glines +Name[wa]=GRoyes +Name[zh_CN]=Glines +Name[zh_TW]=Glines +Comment=Color lines game +Comment[be]=Đ“Ńльня "Каляровыя лініі" +Comment[bg]=Đгра Цветни линии +Comment[bn]=কালার লাইন্‌স খেলা +Comment[ca]=Joc de lĂnies de color +Comment[cs]=Hra BarevnĂ© linie +Comment[da]=Farvede linjer-spil +Comment[de]=Farblinienspiel +Comment[el]=Παιχνίδι ÎłĎαμμών χĎώματος +Comment[es]=Juego del tipo lĂneas de colores. +Comment[fi]=Väriviivapeli +Comment[fr]=Jeu de lignes colorĂ©es +Comment[he]=משחק שורות ×¦×‘×˘×•× ×™×•×Ş +Comment[hu]=Color lines játĂ©k +Comment[it]=Gioco Color Lines +Comment[ja]=ă‚«ă©ăĽă©ă‚¤ăłă®ă‚˛ăĽă +Comment[lv]=KrÄsu lÄ«niju spÄ“le +Comment[mn]=Өнгөт бөмбөлөг тоглоом +Comment[ms]=Permainan garisan warna +Comment[nl]=Kleurlijnen +Comment[no]=Spill med fargelinjer +Comment[pl]=Gra w kolorowe linie +Comment[pt]=Jogo das linhas coloridas +Comment[pt_BR]=Jogo de linhas coloridas +Comment[ru]=Đгра "Цветные линии" +Comment[sk]=Hra FarebnĂ© ÄŤiary +Comment[sl]=Igra barvnih ÄŤrt +Comment[sv]=Färglinjespel +Comment[tr]=Color lines oyunu +Comment[uk]=Гра "Кольорові ряди" +Comment[vi]=Trò chơi ColorLines +Comment[zh_TW]=Color lines éŠć˛ +Exec=glines +Icon=glines.png +Terminal=false +Type=Application +Categories=GNOME;Application;Game;PuzzleGame; +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=gnome-games +X-GNOME-Bugzilla-Component=glines +StartupNotify=true diff --git a/menu/tests/data/hidden.desktop b/menu/tests/data/hidden.desktop new file mode 100644 index 0000000..dbbbff9 --- /dev/null +++ b/menu/tests/data/hidden.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Hidden +Comment=You shouldn't see this +Exec=hidden +Type=Application +Categories=GNOME;Application;TextEditor; +NoDisplay=true diff --git a/menu/tests/data/hidden.directory b/menu/tests/data/hidden.directory new file mode 100644 index 0000000..5f1e776 --- /dev/null +++ b/menu/tests/data/hidden.directory @@ -0,0 +1,5 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Hidden +Type=Directory +NoDisplay=true diff --git a/menu/tests/data/kate.desktop b/menu/tests/data/kate.desktop new file mode 100644 index 0000000..3ca1c5d --- /dev/null +++ b/menu/tests/data/kate.desktop @@ -0,0 +1,30 @@ +[Desktop Entry] +Encoding=UTF-8 +GenericName=Advanced Text Editor +GenericName[cy]=Golygydd Testun Uwch +GenericName[da]= Avanceret teksteditor +GenericName[el]=Î ĎοχωĎημÎνος διοĎθωτής κειμÎνου +GenericName[es]=Editor de texto avanzado +GenericName[fa]=Ůیرایشگر متن پیشرŮته +GenericName[hu]=szövegszerkesztĹ‘ +GenericName[pt_BR]=Editor de Texto Avançado +GenericName[sr]=Napredni editor teksta +GenericName[sv]=Avancerad texteditor +BinaryPattern= +Name=Kate +Name[ar]=ŮŮŠŘŞ +Name[bg]=Редактор Kate +Name[eo]=Kodredaktilo +Name[fa]=Ú©ŮŰŚŘŞ +Name[ko]=ěą´í…Ś +Name[ru]=Редактор Kate +MimeType=text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;text/rdf; +Exec=kate %u +TerminalOptions= +Icon=kate +Path= +DocPath=kate/index.html +Type=Application +Terminal=0 +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;TextEditor diff --git a/menu/tests/data/kbabel.desktop b/menu/tests/data/kbabel.desktop new file mode 100644 index 0000000..2892cb8 --- /dev/null +++ b/menu/tests/data/kbabel.desktop @@ -0,0 +1,69 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=KBabel +Name[af]=Kbabel +Name[ar]=المترجم +Name[eo]=Babelo-tradukilo +Name[ko]=K바벨 +Name[pt_BR]=Editor de POTFiles +Name[sv]=Kbabel +Name[xx]=xxKBabelxx +Exec=kbabel %i %m -caption "%c" %U +Icon=kbabel +MiniIcon=kbabel +Type=Application +DocPath=kbabel/index.html +MimeType=application/x-gettext; +GenericName=Translation Tool +GenericName[af]=Vertaling Program +GenericName[ar]=أداة الترجمة +GenericName[bg]=ĐĐ˝ŃŃ‚Ń€Ńменти Đ·Đ° Превод +GenericName[bs]=Alat za prevoÄ‘enje +GenericName[ca]=Eina de traducciĂł +GenericName[cs]=PĹ™ekladatelskĂ˝ nástroj +GenericName[cy]=Erfyn Cyfieithu +GenericName[da]=Oversættelsesværktøj +GenericName[de]=Ăśbersetzungsprogramm +GenericName[el]=ΕĎγαλείο μετάφĎαĎης +GenericName[eo]=Tradukilo por Qt-programoj +GenericName[es]=Herramienta de traducciĂłn +GenericName[et]=Tõlkimise rakendus +GenericName[eu]=Itzulpenerako Tresnak +GenericName[fi]=Käännöstyökalu +GenericName[fo]=UmsetingaramboĂ° +GenericName[fr]=Outil de traduction +GenericName[he]=כלי תרגום +GenericName[hr]=UsluĹľni program za prevoÄ‘enje +GenericName[hu]=segĂ©dprogram fordĂtĂłknak +GenericName[it]=Strumento per le traduzioni +GenericName[ja]=翻訳ă„ăĽă« +GenericName[lt]=Vertimo ÄŻrankis +GenericName[lv]=Tulkošanas RÄ«ks +GenericName[mt]=Għodda tat-traduzzjoni +GenericName[nb]=Oversettingsverktøy +GenericName[nl]=vertaalprogramma +GenericName[nn]=Omsetjingsverktøy +GenericName[nso]=Sebereka sa Thlathollo +GenericName[pl]=NarzÄ™dzie dla tĹ‚umaczy +GenericName[pt]=Ferramenta de Tradução +GenericName[pt_BR]=Ferramenta de Tradução +GenericName[ro]=Utilitar de traducere +GenericName[ru]=Утилита локализации приложений +GenericName[sk]=PrekladacĂ nástroj +GenericName[sl]=Orodje za prevajanje +GenericName[sv]=Ă–versättningsverktyg +GenericName[ta]=¦Ă¡Æ¢¦ÀÂ÷ôÒì ¸ÕÅ¢ +GenericName[th]=เครืŕąŕ¸ŕ¸‡ŕ¸ˇŕ¸·ŕ¸ŕąŕ¸›ŕ¸Ąŕ¸ าษา +GenericName[tr]=Çeviri Aracı +GenericName[uk]=Đ—Đ°Ńіб для перекладів +GenericName[ven]=Zwishumiswa zwau Dologa +GenericName[vi]=CĂ´ng cụ dịch +GenericName[xh]=Isixhobo Soguqulelo lomsebenzi kolunye ulwimi +GenericName[xx]=xxTranslation Toolxx +GenericName[zh_CN]=翻译工具 +GenericName[zh_TW]=çż»čŻĺ·Ąĺ…· +GenericName[zu]=Ithuluzi Lokuguqulela +Terminal=0 +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Unique +Categories=Qt;KDE;Development diff --git a/menu/tests/data/kedit-legacy.desktop b/menu/tests/data/kedit-legacy.desktop new file mode 100644 index 0000000..fa9700e --- /dev/null +++ b/menu/tests/data/kedit-legacy.desktop @@ -0,0 +1,33 @@ +[Desktop Entry] +Encoding=UTF-8 +BinaryPattern=kedit; +MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; +GenericName=Simple Text Editor +GenericName[ca]=Editor de text +GenericName[cs]=JednoduchĂ˝ textovĂ˝ editor +GenericName[da]=Simpel teksteditor +GenericName[es]=Editor de texto sencillo +GenericName[fr]=Éditeur de texte Ă©lĂ©mentaire +GenericName[pt_BR]=Editor de Texto Simples +GenericName[sv]=Enkel texteditor +GenericName[wa]=Simpe aspougneu di tecse +Exec=kedit -caption "%c" %i %m %u +Icon=kedit +TerminalOptions= +Path= +DocPath=kedit/index.html +Type=Application +Terminal=0 +Name=KEdit +Name[af]=Kredigeer +Name[eo]=Redaktilo +Name[hr]=UreÄ‘ivaÄŤ +Name[lv]=KRediÄŁÄ“t +Name[pl]=Edytor +Name[sv]=Kedit +Name[th]=ŕąŕ¸ŕą‰ŕą„ขข้ŕ¸ŕ¸„วาม +Name[ven]=U sengulusa ha K +Name[xh]=Abahleli Be K +Name[zh_TW]=KDE 編輯器 +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi diff --git a/menu/tests/data/kwrite.desktop b/menu/tests/data/kwrite.desktop new file mode 100644 index 0000000..9804fa6 --- /dev/null +++ b/menu/tests/data/kwrite.desktop @@ -0,0 +1,84 @@ +[Desktop Entry] +Encoding=UTF-8 +GenericName=Text Editor +GenericName[af]=Teks Redigeerder +GenericName[ar]=Ů…Řرر نصŮص +GenericName[be]=ТэкŃтавы рэдактар +GenericName[bg]=ТекŃтов Редактор +GenericName[bs]=Tekst editor +GenericName[ca]=Editor de text +GenericName[cs]=TextovĂ˝ editor +GenericName[cy]=Golygydd Testun +GenericName[da]= Teksteditor +GenericName[de]=Texteditor +GenericName[el]=ΔιοĎθωτής ΚειμÎνου +GenericName[eo]=Tekstredaktilo +GenericName[es]=Editor de texto +GenericName[et]=Tekstiredaktor +GenericName[eu]=Testu Editorea +GenericName[fa]=Ůیرایشگر متن +GenericName[fi]=Tekstieditori +GenericName[fo]=Tekstritil +GenericName[fr]=Éditeur de texte +GenericName[he]=עורך ××§×ˇ× +GenericName[hr]=UreÄ‘ivaÄŤ teksta +GenericName[hu]=szövegszerkesztĹ‘ +GenericName[is]=Textaritill +GenericName[it]=Editor di testi +GenericName[ja]=ă†ă‚ă‚ąăエă‡ă‚Łă‚ż +GenericName[ko]=글월 편집기 +GenericName[lo]=ເຄືŕ»ŕşŕş‡ŕşˇŕş·ŕ»ŕşŕ»‰ŕ»„ຂຂໍ້ຄວາມ +GenericName[lt]=Teksto redaktorius +GenericName[lv]=Teksta Redaktors +GenericName[mn]=ТекŃŃ‚ боловŃŃ€ŃŃлагч +GenericName[mt]=Editur tat-test +GenericName[nb]=Skriveprogram +GenericName[nl]=teksteditor +GenericName[nn]=Skriveprogram +GenericName[nso]=Mofetosi wa Sengwalwana +GenericName[pl]=Edytor tekstowy +GenericName[pt]=Editor de Texto +GenericName[pt_BR]=Editor de Texto +GenericName[ro]=Editor de text +GenericName[ru]=ТекŃтовый редактор +GenericName[sk]=TextovĂ˝ editor +GenericName[sl]=Urejevalnik besedil +GenericName[sr]=Editor teksta +GenericName[ss]=Sihleli sembhalo +GenericName[sv]=Texteditor +GenericName[ta]=¯¨à ¦¾¡ÌôÀ¡Ç÷ +GenericName[th]=เครืŕąŕ¸ŕ¸‡ŕ¸ˇŕ¸·ŕ¸ŕąŕ¸ŕą‰ŕą„ขข้ŕ¸ŕ¸„วาม +GenericName[tr]=Metin DĂĽzenleyici +GenericName[uk]=Редактор текŃтів +GenericName[ven]=Musengulusi wa Manwalwa +GenericName[vi]=Trình soạn vÄn bản +GenericName[wa]=Aspougneu di tecse +GenericName[xh]=Umhleli Wombhalo +GenericName[zh_CN]=文本编辑器 +GenericName[zh_TW]=ć–‡ĺ—編輯器 +GenericName[zu]=Umlungisi wombhalo +BinaryPattern= +Name=KWrite +Name[af]=Kskryf +Name[ar]=Ůاتب ŮŮŠŘŻŮŠ +Name[eo]=Simpla kodredaktilo +Name[fa]=نŮشتار K +Name[fo]=KSkriva +Name[lo]=Kwrite +Name[lv]=KRakstÄ«t +Name[nso]=KNgwala +Name[ru]=Редактор KWrite +Name[sv]=Kwrite +Name[ven]=Nwala ha K +MimeType=text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;text/x-diff;text/rdf; +Exec=kwrite %u +X-KDE-StartupNotify=true +TerminalOptions= +Icon=kwrite +Path= +DocPath=kwrite/index.html +Type=Application +Terminal=0 +InitialPreference=8 +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;TextEditor diff --git a/menu/tests/data/mahjongg-2.desktop b/menu/tests/data/mahjongg-2.desktop new file mode 100644 index 0000000..95cfe27 --- /dev/null +++ b/menu/tests/data/mahjongg-2.desktop @@ -0,0 +1,86 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Mahjongg +Name[am]=á›á…ጆንግ +Name[be]=Маджонг +Name[bg]=Махджонг +Name[bn]=মাহজং +Name[ca]=Mahjongg +Name[cs]=Mahjongg +Name[da]=Mahjongg +Name[de]=Mahjongg +Name[el]=Mahjongg +Name[es]=Mahjongg +Name[et]=Mahjongg +Name[fa]=ماهجŮنگ +Name[fi]=Mahjongg +Name[fr]=Mahjongg +Name[gl]=Mahjongg +Name[he]=Mahjongg +Name[hu]=Mahjongg +Name[it]=Mahjongg +Name[ja]=GNOME 上海 +Name[ko]=ę·¸ë† ë§ěž‘ +Name[lt]=Mahjongg +Name[lv]=Mahjongg +Name[mn]=Маджонг +Name[ms]=Mahjongg +Name[nl]=Mahjongg +Name[no]=Mahjongg +Name[pl]=Mahjongg +Name[pt]=Mahjongg +Name[pt_BR]=Mahjongg +Name[ru]=Маджонг +Name[sk]=Mahjongg +Name[sl]=Mahjongg +Name[sv]=Mah Jong +Name[tr]=Mahjongg +Name[uk]=Магджонґ +Name[vi]=Mahjongg +Name[wa]=Mahjongg +Name[zh_CN]=ĺ †éş»ĺ°† +Name[zh_TW]=上海麻將 +Comment=Mahjongg game +Comment[am]=የá›á…ጆንግ ጨዋታ +Comment[be]=Đ“Ńльня Маджонг +Comment[bg]=Đгра на Махджонг +Comment[bn]=মাহজং খেলা +Comment[ca]=Joc del Mahjongg +Comment[cs]=Hra Mahjongg +Comment[da]=Mahjonggspil +Comment[de]=Mahjongg-Spiel +Comment[el]=Παιχνίδι Mahjongg +Comment[es]=Juego Mahjongg +Comment[et]=Mäng nimega mahjongg +Comment[fa]=بازی ماهجŮنگ +Comment[fi]=Mahjongg-peli +Comment[fr]=Jeu de Mahjongg +Comment[he]=משחק Mahjongg +Comment[hu]=Mahjongg játĂ©k +Comment[it]=Gioco Mahjongg +Comment[ja]=麻雀ゲăĽă +Comment[lv]=Mahjongg spÄ“le +Comment[mn]=Mahjongg тоглоом +Comment[ms]=Permainan Mahjongg +Comment[nl]=Mahjongg +Comment[no]=Mahjongg-spill +Comment[pl]=Gra Mahjongg +Comment[pt]=Jogo Mahjongg +Comment[pt_BR]=Jogo Mahjongg +Comment[ru]=Đгра Маджонг +Comment[sk]=Hra Mahjongg +Comment[sl]=Igra Mahjongg +Comment[sv]=Mah Jong-spel +Comment[tr]=Mahjongg oyunu +Comment[uk]=Гра "Магджонґ" +Comment[vi]=Trò chơi Mahjongg +Comment[zh_TW]=上海麻將éŠć˛ +Exec=mahjongg +Icon=gnome-mahjongg.png +Terminal=false +Type=Application +Categories=GNOME;Application;Development; +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=gnome-games +X-GNOME-Bugzilla-Component=mahjongg +StartupNotify=true diff --git a/menu/tests/data/mahjongg.desktop b/menu/tests/data/mahjongg.desktop new file mode 100644 index 0000000..0d5f5de --- /dev/null +++ b/menu/tests/data/mahjongg.desktop @@ -0,0 +1,86 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Mahjongg +Name[am]=á›á…ጆንግ +Name[be]=Маджонг +Name[bg]=Махджонг +Name[bn]=মাহজং +Name[ca]=Mahjongg +Name[cs]=Mahjongg +Name[da]=Mahjongg +Name[de]=Mahjongg +Name[el]=Mahjongg +Name[es]=Mahjongg +Name[et]=Mahjongg +Name[fa]=ماهجŮنگ +Name[fi]=Mahjongg +Name[fr]=Mahjongg +Name[gl]=Mahjongg +Name[he]=Mahjongg +Name[hu]=Mahjongg +Name[it]=Mahjongg +Name[ja]=GNOME 上海 +Name[ko]=ę·¸ë† ë§ěž‘ +Name[lt]=Mahjongg +Name[lv]=Mahjongg +Name[mn]=Маджонг +Name[ms]=Mahjongg +Name[nl]=Mahjongg +Name[no]=Mahjongg +Name[pl]=Mahjongg +Name[pt]=Mahjongg +Name[pt_BR]=Mahjongg +Name[ru]=Маджонг +Name[sk]=Mahjongg +Name[sl]=Mahjongg +Name[sv]=Mah Jong +Name[tr]=Mahjongg +Name[uk]=Магджонґ +Name[vi]=Mahjongg +Name[wa]=Mahjongg +Name[zh_CN]=ĺ †éş»ĺ°† +Name[zh_TW]=上海麻將 +Comment=Mahjongg game +Comment[am]=የá›á…ጆንግ ጨዋታ +Comment[be]=Đ“Ńльня Маджонг +Comment[bg]=Đгра на Махджонг +Comment[bn]=মাহজং খেলা +Comment[ca]=Joc del Mahjongg +Comment[cs]=Hra Mahjongg +Comment[da]=Mahjonggspil +Comment[de]=Mahjongg-Spiel +Comment[el]=Παιχνίδι Mahjongg +Comment[es]=Juego Mahjongg +Comment[et]=Mäng nimega mahjongg +Comment[fa]=بازی ماهجŮنگ +Comment[fi]=Mahjongg-peli +Comment[fr]=Jeu de Mahjongg +Comment[he]=משחק Mahjongg +Comment[hu]=Mahjongg játĂ©k +Comment[it]=Gioco Mahjongg +Comment[ja]=麻雀ゲăĽă +Comment[lv]=Mahjongg spÄ“le +Comment[mn]=Mahjongg тоглоом +Comment[ms]=Permainan Mahjongg +Comment[nl]=Mahjongg +Comment[no]=Mahjongg-spill +Comment[pl]=Gra Mahjongg +Comment[pt]=Jogo Mahjongg +Comment[pt_BR]=Jogo Mahjongg +Comment[ru]=Đгра Маджонг +Comment[sk]=Hra Mahjongg +Comment[sl]=Igra Mahjongg +Comment[sv]=Mah Jong-spel +Comment[tr]=Mahjongg oyunu +Comment[uk]=Гра "Магджонґ" +Comment[vi]=Trò chơi Mahjongg +Comment[zh_TW]=上海麻將éŠć˛ +Exec=mahjongg +Icon=gnome-mahjongg.png +Terminal=false +Type=Application +Categories=GNOME;Application;Game;BoardGame; +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=gnome-games +X-GNOME-Bugzilla-Component=mahjongg +StartupNotify=true diff --git a/menu/tests/data/quanta.desktop b/menu/tests/data/quanta.desktop new file mode 100644 index 0000000..4b23aef --- /dev/null +++ b/menu/tests/data/quanta.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Quanta Plus +Exec=quanta +Icon=quanta +Type=Application +MimeType=text/html +DocPath=quanta/index.html +Comment=Web Development Environment +Categories=Qt;KDE;Development diff --git a/menu/tests/expand b/menu/tests/expand new file mode 100755 index 0000000..5dbaac8 --- /dev/null +++ b/menu/tests/expand @@ -0,0 +1,12 @@ +#!/usr/bin/perl + +# This script performs expansion of environment variables of the form ${HOME} + +while(<>) +{ + while (($a) = ($_ =~ /[^\$]*\$\{([^\}]*)\}.*/)) + { + s/([^\$]*)(\$\{$a\})(.*)/$1$ENV{$a}$3/; + } + printf $_; +}
\ No newline at end of file diff --git a/menu/tests/menutest b/menu/tests/menutest new file mode 100755 index 0000000..9d37246 --- /dev/null +++ b/menu/tests/menutest @@ -0,0 +1,200 @@ +#!/bin/bash +# these vars are usable *only* for debugging purposes; they're not allowed as part of the spec, thus don't use them. +# set MENU_FAKE_PREFIX to a non empty val to force testing for if things would succeed if XDG_MENU_PREFIX were +# implemented +# set MENU_FAKE_APPLICATIONS to force a work around for applications-merged postfixing. +# +function installData() +{ + local DIR="$1" + shift + mkdir -p "${DIR}" + for file in $*; do + cp "data/${file}" "${DIR}" + WIPE[$WIPE_IDX]="${DIR}/${file}" + WIPE_IDX=$(( $WIPE_IDX + 1 )) + done +} + +function installDataAs() +{ + local DIR="$1" + mkdir -p "${DIR}" + cp "data/$2" "${DIR}/$3" + WIPE[${WIPE_IDX}]="${DIR}/${3}" + WIPE_IDX=$(( $WIPE_IDX + 1 )) +} + +setup_local_xdg_vars() { + export XDG_CONFIG_HOME="${MENUTESTDIR}/xdg_config_home" + export XDG_DATA_HOME="${MENUTESTDIR}/xdg_data_home" + export XDG_CONFIG_DIR="${MENUTESTDIR}/xdg_config_dir" + export XDG_CONFIG_DIRS="$XDG_CONFIG_DIR:${XDG_CONFIG_DIRS}2" + export XDG_DATA_DIR="${MENUTESTDIR}/xdg_data_dir" + export XDG_DATA_DIRS="$XDG_DATA_DIR:${XDG_DATA_DIR}2" + export XDG_CACHE_HOME="${MENUTESTDIR}/xdg_cache_home" +} + +setup_xdg_system_data_vars() +{ + export XDG_CACHE_HOME="${XDG_DATA_HOME:-${HOME}/.cache}" + export XDG_DATA_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}" + export XDG_CONFIG_DIR="${XDG_CONFIG_DIR:-/etc/xdg}" + if [ -z "${XDG_DATA_DIRS}" ]; then + export XDG_DATA_DIRS="/usr/local/share:/usr/share" + fi + export XDG_DATA_DIRS="${XDG_DATA_DIRS}:${MENUTESTDIR}/xdg_cache_dir" + export XDG_DATA_DIR="${XDG_DATA_DIRS//*:}" + if [ -z "${XDG_CONFIG_DIRS}" ]; then + export XDG_CONFIG_DIRS="/etc/xdg" + fi + export XDG_CONFIG_DIR="${XDG_CONFIG_DIRS/:*}" +} + +run_test() { + if [ -z "$1" ]; then + echo "requires name of test directory to run" + exit 1 + fi + local TEST="$1" + rm -rf "${MENUTESTDIR}" 2> /dev/null + mkdir "${MENUTESTDIR}" + RESULT="${TEST}/result" + + ( + unset WIPE WIPE_IDX + declare -a WIPE + declare -i WIPE_IDX=0 + unset MODE + + . ${TEST}/test + echo ">>> Running test ${TEST}, purpose $TEST_PURPOSE" + + if [ "${MODE:-local}" == "local" ]; then + setup_local_xdg_vars + elif [ "${MODE}" == "system_data" ]; then + setup_xdg_system_data_vars + else + echo "!!! unknown MODE from $TEST, bailing" + exit -1 + fi + + test_code + + declare -i IDX=0 + while [ $WIPE_IDX -gt $IDX ]; do + echo "${WIPE[$IDX]}" >> "${MENUTESTDIR}/wipe" + IDX=$(( $IDX + 1 )) + done + + DEBUG_OVERRIDES='' + [ -n "$MENU_FAKE_PREFIX" ] && DEBUG_OVERRIDES=.menu + [ -n "$MENU_FAKE_APPLICATIONS" ] && DEBUG_OVERIDES="${DEBUG_OVERRIDES} -merged" + + for x in dir home; do + for y in ${DEBUG_OVERRIDES}; do + if [ -e "${MENUTESTDIR}/xdg_config_${x}/menus/applications${y}" ]; then + ln -s applications${y} "${MENUTESTDIR}/xdg_config_${x}/menus/kde-applications${y}" + ln -s applications${y} "${MENUTESTDIR}/xdg_config_${x}/menus/gnome-applications${y}" + fi + done + unset y + done + unset x DEBUG_OVERRIDES + + $MENUTEST > ${MENUTESTDIR}/run-result 2> ${MENUTESTDIR}/log + + if [ -e "${RESULT}" ]; then + ./expand "${RESULT}" > "${MENUTESTDIR}/required-result" + fi + + if [ "$(type -t interpret_results)" == "function" ]; then + interpret_results + else + default_interpret_results + fi + ret=$? + if [ -e "${MENUTESTDIR}/wipe" ]; then + cat "${MENUTESTDIR}/wipe" | while read l; do + [ -z "$l" ] && continue + rm "$l" + done + fi + return $ret + ) +} + +default_interpret_results() { + if [ ! -e "${RESULT}" ]; then + echo "!!! Result file (${RESULT}) for ${TEST} missing" + echo '>>> Failed' + return 1 + elif diff -q "${MENUTESTDIR}/run-result" "${MENUTESTDIR}/required-result" > /dev/null; then + echo '>>> OK' + return 0 + fi + sort "${MENUTESTDIR}/run-result" > "${MENUTESTDIR}/run-result.sorted" + sort "${MENUTESTDIR}/required-result" > "${MENUTESTDIR}/required-result.sorted" + if diff -u "${MENUTESTDIR}/run-result.sorted" "${MENUTESTDIR}/required-result.sorted" > "${MENUTESTDIR}/result.diff"; then + echo '>>> OK (different order)' + return 0 + fi + grep "${MENUTESTDIR}" "${MENUTESTDIR}/run-result" > "${MENUTESTDIR}/run-result.filtered" 2> /dev/null + if diff -q "${MENUTESTDIR}/run-result.filtered" "${MENUTESTDIR}/required-result" > /dev/null; then + echo '>>> OK (additional system items)' + return 0 + fi + grep "${MENUTESTDIR}" "${MENUTESTDIR}/run-result.sorted" > "${MENUTESTDIR}/required-result.filtered" 2> /dev/null + if diff -u "${MENUTESTDIR}/run-result.filtered" "${MENUTESTDIR}/required-result.sorted" > "${MENUTESTDIR}/result.diff"; then + echo '>>> OK (different order, additional system items)' + return 0 + fi + echo '>>> Failed' + cat "${MENUTESTDIR}/result.diff" + cat "${MENUTESTDIR}/log" + return 1 +} + +if [ -z "${TESTS}" ]; then + export TESTS=`ls tests/*/test | sed -e 's:^\(\./\)\?tests/\+::' -e 's:/\+test$::'` +fi + +if [ -z "$TET_RUN" ]; then + + if [ "x${MENUTEST}" == "x" ]; then + echo 'To run the test set $MENUTEST to your menu-spec implementation.' + exit 1 + fi + + if [ "x${MENUTESTDIR}" == "x" ]; then + MENUTESTDIR=/tmp/menutestdir + echo Using ${MENUTESTDIR} as test directory, override with \$MENUTESTDIR. + else + echo Using ${MENUTESTDIR} as test directory. + fi + + export MENUTESTDIR + export USER=${USER:-test} + + + FAILED= + SUCCEEDED= + + for TESTCASE in ${TESTS}; do + if [ "${TESTCASE}" == "CVS" ]; then + continue + fi + echo + if ! run_test "tests/${TESTCASE}" ${MODE}; then + FAILED="${FAILED} ${TESTCASE}" + else + SUCCEEDED="${SUCCEEDED} ${TESTCASE}" + fi + done + + echo "OK tests: ${SUCCEEDED}" + [ -n "${FAILED}" ] && echo "Failed tests: ${FAILED}" + echo "$(echo ${SUCCEEDED} | wc -w) tests passed, $(echo ${FAILED} | wc -w) tests failed" + [ -z "${FAILED}" ] && exit 0 + exit 1 +fi diff --git a/menu/tests/tests/All/result b/menu/tests/tests/All/result new file mode 100644 index 0000000..fc75a82 --- /dev/null +++ b/menu/tests/tests/All/result @@ -0,0 +1,4 @@ +Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop +Applications/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop +Applications/ glines.desktop ${XDG_DATA_DIR}/applications/glines.desktop +Applications/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop diff --git a/menu/tests/tests/All/test b/menu/tests/tests/All/test new file mode 100644 index 0000000..e97bddc --- /dev/null +++ b/menu/tests/tests/All/test @@ -0,0 +1,26 @@ +TEST_PURPOSE="<All> Keyword" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <All/> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/And/result b/menu/tests/tests/And/result new file mode 100644 index 0000000..dc159fa --- /dev/null +++ b/menu/tests/tests/And/result @@ -0,0 +1 @@ +Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop diff --git a/menu/tests/tests/And/test b/menu/tests/tests/And/test new file mode 100644 index 0000000..31571db --- /dev/null +++ b/menu/tests/tests/And/test @@ -0,0 +1,29 @@ +TEST_PURPOSE="<And> Keyword" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <And> + <Filename>freecell.desktop</Filename> + <Category>Game</Category> + </And> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/AppDir-relative/result b/menu/tests/tests/AppDir-relative/result new file mode 100644 index 0000000..9e1d622 --- /dev/null +++ b/menu/tests/tests/AppDir-relative/result @@ -0,0 +1,3 @@ +Applications/ KEdit.desktop ${XDG_CONFIG_DIR}/menus/apps/KEdit.desktop +Applications/ kate.desktop ${XDG_CONFIG_DIR}/menus/apps/kate.desktop +Applications/ kwrite.desktop ${XDG_CONFIG_DIR}/menus/apps/kwrite.desktop diff --git a/menu/tests/tests/AppDir-relative/test b/menu/tests/tests/AppDir-relative/test new file mode 100644 index 0000000..75bd201 --- /dev/null +++ b/menu/tests/tests/AppDir-relative/test @@ -0,0 +1,27 @@ +TEST_PURPOSE="<AppDir> relative path tag ..." + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <AppDir>apps</AppDir> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData "${XDG_CONFIG_DIR}/menus/apps" kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop + installDataAs "${XDG_CONFIG_DIR}/menus/apps" kwrite.desktop should_be_ignored.notdesktop +} diff --git a/menu/tests/tests/AppDir/test b/menu/tests/tests/AppDir/test new file mode 100644 index 0000000..8faff91 --- /dev/null +++ b/menu/tests/tests/AppDir/test @@ -0,0 +1,4 @@ +. tests/AppDir-relative/test +export PATH_EXPANSION='${XDG_CONFIG_DIR}/menus/' +TEST_PURPOSE="<AppDir> absolute path" + diff --git a/menu/tests/tests/Category/result b/menu/tests/tests/Category/result new file mode 100644 index 0000000..73b00c9 --- /dev/null +++ b/menu/tests/tests/Category/result @@ -0,0 +1,3 @@ +Editors/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Editors/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Editors/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop diff --git a/menu/tests/tests/Category/test b/menu/tests/tests/Category/test new file mode 100644 index 0000000..3ee0777 --- /dev/null +++ b/menu/tests/tests/Category/test @@ -0,0 +1,29 @@ +TEST_PURPOSE="<Category> tag" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Editors</Name> + <Include> + <Category>TextEditor</Category> + <!-- note it's lowercase, this is intentional to verify + it's a case sensitive implementation --> + <Category>application</Category> + </Include> + </Menu> +</Menu> +EOF + +# Install .desktop files, freecell is daft but intentional to verify category support is case sensitive +installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop kate.desktop freecell.desktop +} diff --git a/menu/tests/tests/DefaultMergeDirs/result b/menu/tests/tests/DefaultMergeDirs/result new file mode 100644 index 0000000..9e17189 --- /dev/null +++ b/menu/tests/tests/DefaultMergeDirs/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop +Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/DefaultMergeDirs/test b/menu/tests/tests/DefaultMergeDirs/test new file mode 100644 index 0000000..3b570f2 --- /dev/null +++ b/menu/tests/tests/DefaultMergeDirs/test @@ -0,0 +1,43 @@ +TEST_PURPOSE="<DefaultMergeDirs> tag ..." + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <DefaultMergeDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + mkdir ${XDG_CONFIG_DIR}/menus/applications-merged/ + ./expand > ${XDG_CONFIG_DIR}/menus/applications-merged/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop +} diff --git a/menu/tests/tests/Deleted/result b/menu/tests/tests/Deleted/result new file mode 100644 index 0000000..c121419 --- /dev/null +++ b/menu/tests/tests/Deleted/result @@ -0,0 +1,2 @@ +BoardGames/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop +BoardGames/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop diff --git a/menu/tests/tests/Deleted/test b/menu/tests/tests/Deleted/test new file mode 100644 index 0000000..db7a413 --- /dev/null +++ b/menu/tests/tests/Deleted/test @@ -0,0 +1,35 @@ +TEST_PURPOSE="<Deleted> tag" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>BoardGames</Name> + <Include> + <Category>BoardGame</Category> + </Include> + </Menu> + <Menu> + <Name>Games</Name> + <Include> + <Category>Game</Category> + </Include> + <Deleted/> + <NotDeleted/> + <Deleted/> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/DesktopFileID/result b/menu/tests/tests/DesktopFileID/result new file mode 100644 index 0000000..9629384 --- /dev/null +++ b/menu/tests/tests/DesktopFileID/result @@ -0,0 +1,4 @@ +Applications/ company-games-freecell.desktop ${XDG_DATA_DIR}/applications/company/games/freecell.desktop +Applications/ company-games-gataxx.desktop ${XDG_DATA_DIR}/applications/company/games/gataxx.desktop +Applications/ company-games-glines.desktop ${XDG_DATA_DIR}/applications/company/games/glines.desktop +Applications/ company-games-mahjongg.desktop ${XDG_DATA_DIR}/applications/company/games/mahjongg.desktop diff --git a/menu/tests/tests/DesktopFileID/test b/menu/tests/tests/DesktopFileID/test new file mode 100644 index 0000000..ae2c679 --- /dev/null +++ b/menu/tests/tests/DesktopFileID/test @@ -0,0 +1,26 @@ +TEST_PURPOSE="DesktopFileIDs in submenus" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>Game</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications/company/games gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/Directory/result b/menu/tests/tests/Directory/result new file mode 100644 index 0000000..2cd1d1f --- /dev/null +++ b/menu/tests/tests/Directory/result @@ -0,0 +1,3 @@ +Apps/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Apps/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Apps/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop diff --git a/menu/tests/tests/Directory/test b/menu/tests/tests/Directory/test new file mode 100644 index 0000000..fe7e126 --- /dev/null +++ b/menu/tests/tests/Directory/test @@ -0,0 +1,29 @@ +TEST_PURPOSE="<Directory> tag ..." + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + + <Menu> + <Name>Applications</Name> + <Directory>apps.directory</Directory> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop + installData ${XDG_DATA_DIR}/desktop-directories apps.directory +} diff --git a/menu/tests/tests/DirectoryDir-relative/result b/menu/tests/tests/DirectoryDir-relative/result new file mode 100644 index 0000000..2cd1d1f --- /dev/null +++ b/menu/tests/tests/DirectoryDir-relative/result @@ -0,0 +1,3 @@ +Apps/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Apps/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Apps/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop diff --git a/menu/tests/tests/DirectoryDir-relative/test b/menu/tests/tests/DirectoryDir-relative/test new file mode 100644 index 0000000..4a5e039 --- /dev/null +++ b/menu/tests/tests/DirectoryDir-relative/test @@ -0,0 +1,28 @@ +TEST_PURPOSE="relative <DirectoryDir> tag ..." + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + <DirectoryDir>${PATH_EXPANSION}desktop-directories</DirectoryDir> + + <Menu> + <Name>Applications</Name> + <Directory>apps.directory</Directory> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop + installData ${XDG_CONFIG_DIR}/menus/desktop-directories apps.directory +} diff --git a/menu/tests/tests/DirectoryDir/test b/menu/tests/tests/DirectoryDir/test new file mode 100644 index 0000000..dc8bb3b --- /dev/null +++ b/menu/tests/tests/DirectoryDir/test @@ -0,0 +1,4 @@ +. tests/DirectoryDir-relative/test +export PATH_EXPANSION='${XDG_CONFIG_DIR}/menus/' +TEST_PURPOSE="<DirectoryDir> absolute path" + diff --git a/menu/tests/tests/Exclude/result b/menu/tests/tests/Exclude/result new file mode 100644 index 0000000..dfbb122 --- /dev/null +++ b/menu/tests/tests/Exclude/result @@ -0,0 +1,3 @@ +Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop +Applications/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop +Applications/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop diff --git a/menu/tests/tests/Exclude/test b/menu/tests/tests/Exclude/test new file mode 100644 index 0000000..728ec99 --- /dev/null +++ b/menu/tests/tests/Exclude/test @@ -0,0 +1,32 @@ +TEST_PURPOSE="<Exclude> Keyword" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <Or> + <Filename>freecell.desktop</Filename> + <Category>Game</Category> + </Or> + </Include> + <Exclude> + <Filename>glines.desktop</Filename> + </Exclude> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/Filename/result b/menu/tests/tests/Filename/result new file mode 100644 index 0000000..dc159fa --- /dev/null +++ b/menu/tests/tests/Filename/result @@ -0,0 +1 @@ +Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop diff --git a/menu/tests/tests/Filename/test b/menu/tests/tests/Filename/test new file mode 100644 index 0000000..b9d021d --- /dev/null +++ b/menu/tests/tests/Filename/test @@ -0,0 +1,26 @@ +TEST_PURPOSE="<Filename> tag" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <Filename>freecell.desktop</Filename> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/LegacyDir-Move/result b/menu/tests/tests/LegacyDir-Move/result new file mode 100644 index 0000000..9a2b9db --- /dev/null +++ b/menu/tests/tests/LegacyDir-Move/result @@ -0,0 +1,2 @@ +Editors/ gideon-legacy.desktop ${LEGACY_DIR}/Development/gideon-legacy.desktop +/ Home.desktop ${LEGACY_DIR}/Home.desktop diff --git a/menu/tests/tests/LegacyDir-Move/test b/menu/tests/tests/LegacyDir-Move/test new file mode 100644 index 0000000..7e6e85e --- /dev/null +++ b/menu/tests/tests/LegacyDir-Move/test @@ -0,0 +1,39 @@ +TEST_PURPOSE="move entries from <LegacyDir>" + +test_code() { + LEGACY_DIR=${MENUTESTDIR}/legacy_applnk + export LEGACY_DIR + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <LegacyDir>${LEGACY_DIR}</LegacyDir> + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + + <Menu> + <Name>Development</Name> + <Exclude> + <Filename>gideon-legacy.desktop</Filename> + </Exclude> + </Menu> + <Menu> + <Name>Editors</Name> + <Include> + <Filename>gideon-legacy.desktop</Filename> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + + installData ${LEGACY_DIR} Home.desktop + installData ${LEGACY_DIR}/Development gideon-legacy.desktop +} diff --git a/menu/tests/tests/LegacyDir-relative/result b/menu/tests/tests/LegacyDir-relative/result new file mode 100644 index 0000000..0c2af9b --- /dev/null +++ b/menu/tests/tests/LegacyDir-relative/result @@ -0,0 +1,9 @@ +Development/ gideon-legacy.desktop ${LEGACY_DIR}/Development/gideon-legacy.desktop +Development/ kbabel.desktop ${LEGACY_DIR}/Development/kbabel.desktop +Development/ quanta.desktop ${LEGACY_DIR}/Development/quanta.desktop +Editors/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Editors/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Editors/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +/ Help.desktop ${LEGACY_DIR}/Help.desktop +/ Home.desktop ${LEGACY_DIR}/Home.desktop +/ Kfind.desktop ${LEGACY_DIR}/Kfind.desktop diff --git a/menu/tests/tests/LegacyDir-relative/test b/menu/tests/tests/LegacyDir-relative/test new file mode 100644 index 0000000..5082590 --- /dev/null +++ b/menu/tests/tests/LegacyDir-relative/test @@ -0,0 +1,42 @@ +TEST_PURPOSE="Simple <LegacyDir> test" + +test_code() { + LEGACY_DIR=${MENUTESTDIR}/legacy_applnk + export LEGACY_DIR + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <LegacyDir>${LEGACY_DIR}</LegacyDir> + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + + <Menu> + <Name>Editors</Name> + <Directory>kde-editors.directory</Directory> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> + <Menu> + <Name>Development</Name> + <Directory>kde-development.directory</Directory> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop kate.desktop + installData ${LEGACY_DIR}/Development gideon-legacy.desktop kbabel.desktop quanta.desktop + installData ${LEGACY_DIR} Kfind.desktop Home.desktop Help.desktop +} + diff --git a/menu/tests/tests/Merge-combined/result b/menu/tests/tests/Merge-combined/result new file mode 100644 index 0000000..999bd1e --- /dev/null +++ b/menu/tests/tests/Merge-combined/result @@ -0,0 +1 @@ +Editors/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop diff --git a/menu/tests/tests/Merge-combined/test b/menu/tests/tests/Merge-combined/test new file mode 100644 index 0000000..07cfab3 --- /dev/null +++ b/menu/tests/tests/Merge-combined/test @@ -0,0 +1,46 @@ +TEST_PURPOSE="Merge Two Menus and a Legacy Menu" + +test_code() { + LEGACY_DIR=${MENUTESTDIR}/legacy_applnk + export LEGACY_DIR + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + <LegacyDir>${LEGACY_DIR}</LegacyDir> + + <Menu> + <Name>Development</Name> + <Include> + <Filename>kate.desktop</Filename> + </Include> + </Menu> + <Menu> + <Name>Development</Name> + <Include> + <Filename>KEdit.desktop</Filename> + </Include> + <Deleted/> + </Menu> + <Menu> + <Name>Editors</Name> + <Include> + <Filename>kwrite.desktop</Filename> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + + installData ${LEGACY_DIR}/Development gideon-legacy.desktop + installData ${XDG_DATA_DIR}/applications kate.desktop kwrite.desktop KEdit.desktop +} diff --git a/menu/tests/tests/MergeDir-absolute/test b/menu/tests/tests/MergeDir-absolute/test new file mode 100644 index 0000000..db6c895 --- /dev/null +++ b/menu/tests/tests/MergeDir-absolute/test @@ -0,0 +1,3 @@ +. tests/MergeDir-relative/test +export PATH_EXPANSION='${XDG_CONFIG_DIR}/menus/' +export TEST_PURPOSE="<MergeDir> absolute path test" diff --git a/menu/tests/tests/MergeDir-relative/result b/menu/tests/tests/MergeDir-relative/result new file mode 100644 index 0000000..9e17189 --- /dev/null +++ b/menu/tests/tests/MergeDir-relative/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop +Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/MergeDir-relative/test b/menu/tests/tests/MergeDir-relative/test new file mode 100644 index 0000000..ba96b1a --- /dev/null +++ b/menu/tests/tests/MergeDir-relative/test @@ -0,0 +1,61 @@ +TEST_PURPOSE="<MergeDir> relative path ..." + +test_code() { + # Generate applications.menu + mkdir -p "${XDG_CONFIG_DIR}/menus" + ./expand > "${XDG_CONFIG_DIR}/menus/applications.menu" <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <MergeDir>${PATH_EXPANSION}applications-merged</MergeDir> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + mkdir "${XDG_CONFIG_DIR}/menus/applications-merged/" + ./expand > "${XDG_CONFIG_DIR}/menus/applications-merged/test.menu" <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # intentional crap entry to verify it does _not_ get picked up + ./expand > "${XDG_CONFIG_DIR}/menus/applications-merged/dar.notmenu" <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>testing</Name> + <Include> + <All/> + </Include> + </Menu> +</Menu> +EOF + + + # Install .desktop files + installData "${XDG_DATA_DIR}/applications" kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop +} diff --git a/menu/tests/tests/MergeFile-absolute/test b/menu/tests/tests/MergeFile-absolute/test new file mode 100644 index 0000000..24cf669 --- /dev/null +++ b/menu/tests/tests/MergeFile-absolute/test @@ -0,0 +1,3 @@ +. tests/MergeFile-relative/test +export PATH_EXPANSION='${XDG_CONFIG_DIR}/menus/' +export TEST_PURPOSE="<MergeFile> absolute path" diff --git a/menu/tests/tests/MergeFile-parent/result b/menu/tests/tests/MergeFile-parent/result new file mode 100644 index 0000000..9e17189 --- /dev/null +++ b/menu/tests/tests/MergeFile-parent/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop +Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/MergeFile-parent/test b/menu/tests/tests/MergeFile-parent/test new file mode 100644 index 0000000..00ed006 --- /dev/null +++ b/menu/tests/tests/MergeFile-parent/test @@ -0,0 +1,61 @@ +TEST_PURPOSE="<MergeFile> tag ..." + +test_code() { + # Tests the type attribute in <MergeFile> + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_HOME}/menus + ./expand > ${XDG_CONFIG_HOME}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <MergeFile type="parent">${XDG_CONFIG_DIR}/menus/test.menu</MergeFile> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Games</Name> + <Include> + <Category>Game</Category> + </Include> + </Menu> +</Menu> +EOF + + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/MergeFile-path/result b/menu/tests/tests/MergeFile-path/result new file mode 100644 index 0000000..fbe635e --- /dev/null +++ b/menu/tests/tests/MergeFile-path/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Games/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop +Games/ glines.desktop ${XDG_DATA_DIR}/applications/glines.desktop diff --git a/menu/tests/tests/MergeFile-path/test b/menu/tests/tests/MergeFile-path/test new file mode 100644 index 0000000..97daa5c --- /dev/null +++ b/menu/tests/tests/MergeFile-path/test @@ -0,0 +1,61 @@ +TEST_PURPOSE="<MergeFile> tag ..." + +test_code() { + # Tests the type attribute in <MergeFile> + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_HOME}/menus + ./expand > ${XDG_CONFIG_HOME}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <MergeFile type="path">${XDG_CONFIG_DIR}/menus/test.menu</MergeFile> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Games</Name> + <Include> + <Category>Game</Category> + </Include> + </Menu> +</Menu> +EOF + + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/MergeFile-recursive/result b/menu/tests/tests/MergeFile-recursive/result new file mode 100644 index 0000000..9e17189 --- /dev/null +++ b/menu/tests/tests/MergeFile-recursive/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop +Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/MergeFile-recursive/test b/menu/tests/tests/MergeFile-recursive/test new file mode 100644 index 0000000..4dbab21 --- /dev/null +++ b/menu/tests/tests/MergeFile-recursive/test @@ -0,0 +1,58 @@ +TEST_PURPOSE="test elaborate recursive look in <MergeFile>s" + +test_code(){ + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <MergeFile>applications-merged/test.menu</MergeFile> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + + mkdir ${XDG_CONFIG_DIR}/menus/applications-merged/ + ./expand > ${XDG_CONFIG_DIR}/menus/applications-merged/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <MergeFile>extra/test.menu</MergeFile> +</Menu> +EOF + + mkdir ${XDG_CONFIG_DIR}/menus/applications-merged/extra/ + ./expand > ${XDG_CONFIG_DIR}/menus/applications-merged/extra/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> + + <MergeFile>../test.menu</MergeFile> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop +} diff --git a/menu/tests/tests/MergeFile-relative/result b/menu/tests/tests/MergeFile-relative/result new file mode 100644 index 0000000..9e17189 --- /dev/null +++ b/menu/tests/tests/MergeFile-relative/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop +Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/MergeFile-relative/test b/menu/tests/tests/MergeFile-relative/test new file mode 100644 index 0000000..c3478db --- /dev/null +++ b/menu/tests/tests/MergeFile-relative/test @@ -0,0 +1,44 @@ +TEST_PURPOSE="<MergeFile> tag relative path" + +test_code(){ + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <MergeFile>${PATH_EXPANSION}applications-merged/test.menu</MergeFile> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + mkdir ${XDG_CONFIG_DIR}/menus/applications-merged/ + ./expand > ${XDG_CONFIG_DIR}/menus/applications-merged/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> +<!-- test --> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop +} diff --git a/menu/tests/tests/MergeFile2/result b/menu/tests/tests/MergeFile2/result new file mode 100644 index 0000000..9e17189 --- /dev/null +++ b/menu/tests/tests/MergeFile2/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop +Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/MergeFile2/test b/menu/tests/tests/MergeFile2/test new file mode 100644 index 0000000..e5b1591 --- /dev/null +++ b/menu/tests/tests/MergeFile2/test @@ -0,0 +1,57 @@ +TEST_PURPOSE="<MergeFile> tag ..." + +test_code() { + # Tests the use of relative paths in <MergeFile> + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <MergeFile>applications-merged/test.menu</MergeFile> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + mkdir ${XDG_CONFIG_DIR}/menus/applications-merged/ + ./expand > ${XDG_CONFIG_DIR}/menus/applications-merged/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <MergeFile>extra/test.menu</MergeFile> +</Menu> +EOF + + mkdir ${XDG_CONFIG_DIR}/menus/applications-merged/extra/ + ./expand > ${XDG_CONFIG_DIR}/menus/applications-merged/extra/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop +} diff --git a/menu/tests/tests/MergeFile3/result b/menu/tests/tests/MergeFile3/result new file mode 100644 index 0000000..9e17189 --- /dev/null +++ b/menu/tests/tests/MergeFile3/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop +Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/MergeFile3/test b/menu/tests/tests/MergeFile3/test new file mode 100644 index 0000000..8781888 --- /dev/null +++ b/menu/tests/tests/MergeFile3/test @@ -0,0 +1,56 @@ +TEST_PURPOSE="<MergeFile> tag ..." + +test_code() { + # Tests the use of relative paths in <MergeFile> + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <MergeFile>test.menu</MergeFile> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> +</Menu> +EOF + + ./expand > ${XDG_CONFIG_DIR}/menus/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <MergeFile>extra/test.menu</MergeFile> +</Menu> +EOF + + mkdir ${XDG_CONFIG_DIR}/menus/extra/ + ./expand > ${XDG_CONFIG_DIR}/menus/extra/test.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop +} diff --git a/menu/tests/tests/Move-collapsing/result b/menu/tests/tests/Move-collapsing/result new file mode 100644 index 0000000..10ccec6 --- /dev/null +++ b/menu/tests/tests/Move-collapsing/result @@ -0,0 +1,4 @@ +Games/BoardGame/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop +Games/BoardGame/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop +Games/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop +Games/ glines.desktop ${XDG_DATA_DIR}/applications/glines.desktop diff --git a/menu/tests/tests/Move-collapsing/test b/menu/tests/tests/Move-collapsing/test new file mode 100644 index 0000000..b842b0a --- /dev/null +++ b/menu/tests/tests/Move-collapsing/test @@ -0,0 +1,40 @@ +TEST_PURPOSE="complicated <Move> operation" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + <Move> + <Old>Games1</Old> + <New>Games</New> + </Move> + + <Menu> + <Name>Games1</Name> + <Menu> + <Name>BoardGame</Name> + <Include> + <Category>BoardGame</Category> + </Include> + </Menu> + </Menu> + <Menu> + <Name>Games</Name> + <Include> + <Category>Game</Category> + </Include> + <OnlyUnallocated/> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/Move-ordering/result b/menu/tests/tests/Move-ordering/result new file mode 100644 index 0000000..b941f58 --- /dev/null +++ b/menu/tests/tests/Move-ordering/result @@ -0,0 +1,3 @@ +Development/ gideon.desktop ${XDG_DATA_DIR}/applications/gideon.desktop +Games-Correct/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop +Games-Correct/ glines.desktop ${XDG_DATA_DIR}/applications/glines.desktop diff --git a/menu/tests/tests/Move-ordering/test b/menu/tests/tests/Move-ordering/test new file mode 100644 index 0000000..f8883b9 --- /dev/null +++ b/menu/tests/tests/Move-ordering/test @@ -0,0 +1,49 @@ +TEST_PURPOSE="Order of <Move> operations ..." + +test_code() { + # Tests the type attribute in <MergeFile> + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <Menu> + <Name>Development</Name> + <Menu> + <Name>Games</Name> + <Include> + <Category>Game</Category> + </Include> + </Menu> + <Include> + <Category>Development</Category> + </Include> + </Menu> + <Move> + <Old>Development/Games-New</Old> + <New>Games-Correct</New> + </Move> + <Move> + <Old>Development/Games</Old> + <New>Games-Wrong</New> + </Move> + <Menu> + <Name>Development</Name> + <Move> + <Old>Games</Old> + <New>Games-New</New> + </Move> + </Menu> +</Menu> +EOF + + # Move operations in sub-menus should be performed first + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications freecell.desktop glines.desktop gideon.desktop +} diff --git a/menu/tests/tests/Move-submenu/result b/menu/tests/tests/Move-submenu/result new file mode 100644 index 0000000..f1c44ef --- /dev/null +++ b/menu/tests/tests/Move-submenu/result @@ -0,0 +1 @@ +A/B/Development/ gideon-legacy.desktop ${XDG_DATA_DIR}/applications/gideon-legacy.desktop diff --git a/menu/tests/tests/Move-submenu/test b/menu/tests/tests/Move-submenu/test new file mode 100644 index 0000000..2751983 --- /dev/null +++ b/menu/tests/tests/Move-submenu/test @@ -0,0 +1,32 @@ +TEST_PURPOSE="Move into a new Submenu" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + + <Menu> + <Name>Development</Name> + <Include> + <Filename>gideon-legacy.desktop</Filename> + </Include> + </Menu> + <Move> + <Old>Development</Old> + <New>A/B/Development</New> + </Move> +</Menu> +EOF + + # Install .desktop files + + installData ${XDG_DATA_DIR}/applications gideon-legacy.desktop +} diff --git a/menu/tests/tests/Move/result b/menu/tests/tests/Move/result new file mode 100644 index 0000000..d9a802d --- /dev/null +++ b/menu/tests/tests/Move/result @@ -0,0 +1,2 @@ +Games/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop +Games/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop diff --git a/menu/tests/tests/Move/test b/menu/tests/tests/Move/test new file mode 100644 index 0000000..9f2d162 --- /dev/null +++ b/menu/tests/tests/Move/test @@ -0,0 +1,34 @@ +TEST_PURPOSE="simple <Move> operation" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + <Move> + <Old>Foo</Old> + <New>Bar</New> + <Old>BoardGames</Old> + <New>Apps</New> + <Old>BoardGames</Old> + <New>Games</New> + </Move> + + <Menu> + <Name>BoardGames</Name> + <Include> + <Category>BoardGame</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/NoDisplay/result b/menu/tests/tests/NoDisplay/result new file mode 100644 index 0000000..7ed7169 --- /dev/null +++ b/menu/tests/tests/NoDisplay/result @@ -0,0 +1 @@ +Other/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop diff --git a/menu/tests/tests/NoDisplay/test b/menu/tests/tests/NoDisplay/test new file mode 100644 index 0000000..48e94ea --- /dev/null +++ b/menu/tests/tests/NoDisplay/test @@ -0,0 +1,37 @@ +TEST_PURPOSE="NoDisplay desktop entry values" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + + <Menu> + <Name>Shouldn't see this</Name> + <Directory>hidden.directory</Directory> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> + + <Menu> + <Name>Other</Name> + <OnlyUnallocated/> + <Include> + <All/> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop kate.desktop freecell.desktop hidden.desktop + installData ${XDG_DATA_DIR}/desktop-directories hidden.directory +} diff --git a/menu/tests/tests/NoDisplay2/result b/menu/tests/tests/NoDisplay2/result new file mode 100644 index 0000000..7ed7169 --- /dev/null +++ b/menu/tests/tests/NoDisplay2/result @@ -0,0 +1 @@ +Other/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop diff --git a/menu/tests/tests/NoDisplay2/test b/menu/tests/tests/NoDisplay2/test new file mode 100644 index 0000000..62ba5a7 --- /dev/null +++ b/menu/tests/tests/NoDisplay2/test @@ -0,0 +1,38 @@ +TEST_PURPOSE="Allocation of desktop entry values from deleted menus" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus +./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + + <Menu> + <Name>Shouldn't see this</Name> + <Directory>apps.directory</Directory> + <Include> + <Category>TextEditor</Category> + </Include> + <Deleted/> + </Menu> + + <Menu> + <Name>Other</Name> + <OnlyUnallocated/> + <Include> + <All/> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop kate.desktop freecell.desktop hidden.desktop + installData ${XDG_DATA_DIR}/desktop-directories apps.directory +} diff --git a/menu/tests/tests/NotOnlyUnallocated-default/result b/menu/tests/tests/NotOnlyUnallocated-default/result new file mode 100644 index 0000000..0c398b7 --- /dev/null +++ b/menu/tests/tests/NotOnlyUnallocated-default/result @@ -0,0 +1,2 @@ +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Editors/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop diff --git a/menu/tests/tests/NotOnlyUnallocated-default/test b/menu/tests/tests/NotOnlyUnallocated-default/test new file mode 100644 index 0000000..2f4956e --- /dev/null +++ b/menu/tests/tests/NotOnlyUnallocated-default/test @@ -0,0 +1,33 @@ +TEST_PURPOSE="Another <OnlyUnallocated> test" + +test_code() { + # Tests <OnlyUnallocated> + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <Filename>kwrite.desktop</Filename> + </Include> + </Menu> + <Menu> + <Name>Editors</Name> + <Include> + <Filename>kwrite.desktop</Filename> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop +} diff --git a/menu/tests/tests/OnlyUnallocated/result b/menu/tests/tests/OnlyUnallocated/result new file mode 100644 index 0000000..8be4bc7 --- /dev/null +++ b/menu/tests/tests/OnlyUnallocated/result @@ -0,0 +1,3 @@ +BoardGames/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop +BoardGames/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop +Games/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop diff --git a/menu/tests/tests/OnlyUnallocated/test b/menu/tests/tests/OnlyUnallocated/test new file mode 100644 index 0000000..efda0ff --- /dev/null +++ b/menu/tests/tests/OnlyUnallocated/test @@ -0,0 +1,44 @@ +TEST_PURPOSE="<OnlyAllocated> tag" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>BoardGames</Name> + <Include> + <And> + <Category>Game</Category> + <Not> + <Category>CardGame</Category> + </Not> + </And> + </Include> + <Exclude> + <Category>PuzzleGame</Category> + </Exclude> + </Menu> + <Menu> + <Name>Games</Name> + <Include> + <Category>Game</Category> + </Include> + <OnlyUnallocated/> + <NotOnlyUnallocated/> + <OnlyUnallocated/> + </Menu> +</Menu> +EOF + + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/Or/result b/menu/tests/tests/Or/result new file mode 100644 index 0000000..fc75a82 --- /dev/null +++ b/menu/tests/tests/Or/result @@ -0,0 +1,4 @@ +Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop +Applications/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop +Applications/ glines.desktop ${XDG_DATA_DIR}/applications/glines.desktop +Applications/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop diff --git a/menu/tests/tests/Or/test b/menu/tests/tests/Or/test new file mode 100644 index 0000000..cd10cfd --- /dev/null +++ b/menu/tests/tests/Or/test @@ -0,0 +1,29 @@ +TEST_PURPOSE="<Or> Keyword" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <Or> + <Filename>freecell.desktop</Filename> + <Category>Game</Category> + </Or> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop +} diff --git a/menu/tests/tests/boolean-logic/result b/menu/tests/tests/boolean-logic/result new file mode 100644 index 0000000..ea47f01 --- /dev/null +++ b/menu/tests/tests/boolean-logic/result @@ -0,0 +1,3 @@ +Apps/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Apps/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Apps/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop diff --git a/menu/tests/tests/boolean-logic/test b/menu/tests/tests/boolean-logic/test new file mode 100644 index 0000000..dc045c4 --- /dev/null +++ b/menu/tests/tests/boolean-logic/test @@ -0,0 +1,36 @@ +TEST_PURPOSE="<And><Category>foo</Category><Not><Category>foo</Category></Not></And> shouldn't match anything" + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + + <DefaultAppDirs/> + <DefaultDirectoryDirs/> + + <Menu> + <Name>Applications</Name> + <Directory>apps.directory</Directory> + <Include> + <Or> + <Category>TextEditor</Category> + <And> + <Category>Game</Category> + <Not><Category>Game</Category></Not> + </And> + </Or> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop kate.desktop + installData ${XDG_DATA_DIR}/applications/test freecell.desktop + installData ${XDG_DATA_DIR}/desktop-directories apps.directory +} diff --git a/menu/tests/tests/desktop-name-collision/result b/menu/tests/tests/desktop-name-collision/result new file mode 100644 index 0000000..e1e9221 --- /dev/null +++ b/menu/tests/tests/desktop-name-collision/result @@ -0,0 +1,3 @@ +Development/ kde-gideon.desktop ${XDG_DATA_HOME}/applications/kde-gideon.desktop +Development/ mahjongg.desktop ${XDG_DATA_HOME}/applications/mahjongg.desktop +Games/ freecell.desktop ${XDG_DATA_HOME}/applications/freecell.desktop diff --git a/menu/tests/tests/desktop-name-collision/test b/menu/tests/tests/desktop-name-collision/test new file mode 100644 index 0000000..46b5ded --- /dev/null +++ b/menu/tests/tests/desktop-name-collision/test @@ -0,0 +1,53 @@ +TEST_PURPOSE=".desktop files with same name ..." + +test_code() { + # Tests the type attribute in <MergeFile> + + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <DefaultAppDirs/> + <Menu> + <Name>Games</Name> + <Include> + <Category>Game</Category> + </Include> + </Menu> + <Menu> + <Name>Development</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications freecell.desktop glines.desktop mahjongg.desktop + + # freecell.desktop is installed twice, only the version under ${XDG_DATA_HOME}/applications + # should show up in the menu + # freecell.desktop in ${XDG_DATA_DIR}/applications should be ignored. + installData ${XDG_DATA_HOME}/applications freecell.desktop + + # ${XDG_DATA_HOME}/applications/glines.desktop has NoDisplay=true + # glines.desktop should not be shown + # glines.desktop in ${XDG_DATA_DIR}/applications should be ignored. + installDataAs ${XDG_DATA_HOME}/applications glines-2.desktop glines.desktop + + # ${XDG_DATA_HOME}/applications/mahjongg.desktop has Categories=Development + # mahjongg.desktop should be shown under the Development menu + # mahjongg.desktop in ${XDG_DATA_DIR}/applications should be ignored. + installDataAs ${XDG_DATA_HOME}/applications mahjongg-2.desktop mahjongg.desktop + + # kde/gideon.desktop and kde-gideon.desktop are equivalent + # only the version under ${XDG_DATA_HOME}/applications should show up in the menu + # gideon.desktop in ${XDG_DATA_DIR}/applications/kde should be ignored. + installDataAs ${XDG_DATA_DIR}/applications/kde gideon.desktop + installDataAs ${XDG_DATA_HOME}/applications gideon.desktop kde-gideon.desktop +} diff --git a/menu/tests/tests/menu-multiple-matching/result b/menu/tests/tests/menu-multiple-matching/result new file mode 100644 index 0000000..986c873 --- /dev/null +++ b/menu/tests/tests/menu-multiple-matching/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Applications/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/menu-multiple-matching/test b/menu/tests/tests/menu-multiple-matching/test new file mode 100644 index 0000000..d8914ab --- /dev/null +++ b/menu/tests/tests/menu-multiple-matching/test @@ -0,0 +1,36 @@ +TEST_PURPOSE="complicated rule ..." + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <And> + <Category>Game</Category> + <Category>BoardGame</Category> + </And> + <Or> + <Category>TextEditor</Category> + <Filename>quanta.desktop</Filename> + </Or> + </Include> + <Exclude> + <Filename>mahjongg.desktop</Filename> + </Exclude> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop +} diff --git a/menu/tests/tests/official-categories/categories.list b/menu/tests/tests/official-categories/categories.list new file mode 100644 index 0000000..6e2198d --- /dev/null +++ b/menu/tests/tests/official-categories/categories.list @@ -0,0 +1,10 @@ +AudioVideo +Development +Education +Game +Graphics +Network +Office +Settings +System +Utility diff --git a/menu/tests/tests/official-categories/test b/menu/tests/tests/official-categories/test new file mode 100644 index 0000000..09621cd --- /dev/null +++ b/menu/tests/tests/official-categories/test @@ -0,0 +1,73 @@ +TEST_PURPOSE="verify all required categories are supported" + +base_loc="tests/official-categories" + +test_code() +{ + local category + for category in $(< "${base_loc}/categories.list"); do + CATEGORY="${category}" ./expand "${base_loc}/unique-entry.desktop" > "data/${category}.desktop" + installData "${XDG_DATA_DIR}/applications" "${category}.desktop" + rm "data/${category}.desktop" + done +} + +query() +{ + echo "$@" + ret='' + while [ -z "$ret" ]; do + echo -n "y/n? :" + read ret + if ! [ "$ret" == "y" -o "$ret" == "n" ]; then + echo "invalid response; must be 'y' or 'n'" + ret='' + fi + done + [ "$ret" == "y" ] && return 0 + return 1 +} + +interpret_results() +{ + # inefficient, but works. + local missed='' + local correct='' + for category in $(< "${base_loc}/categories.list"); do + if grep "/${category}\.desktop" "${MENUTESTDIR}/run-result" > /dev/null; then + correct="${correct} ${category}" + else + missed="${missed} ${category}" + fi + done + if [ -z "${missed}" ]; then + echo ">>> OK" + return 0 + fi + if [ "$(echo $missed)" != "Settings" ]; then + # failures. + cat "${MENUTESTDIR}/run-result" + echo "missed categories $missed" + echo "matched ${correct}" + echo ">>> Failed (missed $(echo $missed | wc -w) out of $(wc -l "${base_loc}/categories.list")" + return 1 + fi + echo ">>> Settings failed; checking interactively" + local ret + if [ "$(id -u)" != "0" ]; then + echo ">>> Cannot go interactive due to test being ran as non-root; re-run as root" + return 1; + elif ! which xdg-desktop-menu &> /dev/null; then + echo ">>> xdg-desktop-menu is not available; cannot do interactive test" + return 1; + fi + xdg-desktop-menu install --mode system --novendor "${XDG_DATA_DIR}/applications/Settings.desktop" + ( + query "Please check for a 'menu-spec-testing' in any gnome/kde system settings panel" + ) + ret=$? + xdg-desktop-menu uninstall --mode system "${XDG_DATA_DIR}/applications/Settings.desktop" + return $(($ret)) +} + +MODE=system_data diff --git a/menu/tests/tests/official-categories/unique-entry.desktop b/menu/tests/tests/official-categories/unique-entry.desktop new file mode 100644 index 0000000..6ee3b88 --- /dev/null +++ b/menu/tests/tests/official-categories/unique-entry.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=menu-spec-testing +Exec=true +Icon=quanta +Type=Application +MimeType=text/html +Comment=menu-spec testing +Categories=${CATEGORY}; diff --git a/menu/tests/tests/submenu-collision/result b/menu/tests/tests/submenu-collision/result new file mode 100644 index 0000000..6aa47d7 --- /dev/null +++ b/menu/tests/tests/submenu-collision/result @@ -0,0 +1,5 @@ +Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop +Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop +Applications/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop +Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop +Applications/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop diff --git a/menu/tests/tests/submenu-collision/test b/menu/tests/tests/submenu-collision/test new file mode 100644 index 0000000..7d29896 --- /dev/null +++ b/menu/tests/tests/submenu-collision/test @@ -0,0 +1,32 @@ +TEST_PURPOSE="two submenus with the same name ..." + +test_code() { + # Generate applications.menu + mkdir -p ${XDG_CONFIG_DIR}/menus + ./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF + <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" + "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +<Menu> + <Name>KDE</Name> + <!-- Search the default locations --> + <DefaultAppDirs/> + + <Menu> + <Name>Applications</Name> + <Include> + <Category>TextEditor</Category> + </Include> + </Menu> + <Menu> + <Name>Applications</Name> + <Include> + <Category>Development</Category> + </Include> + </Menu> +</Menu> +EOF + + # Install .desktop files + installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop +} diff --git a/menu/tests/tet_menutest b/menu/tests/tet_menutest new file mode 100755 index 0000000..1aae67e --- /dev/null +++ b/menu/tests/tet_menutest @@ -0,0 +1,39 @@ +#!/bin/bash +TET_RUN="asdf" +export MENUTESTDIR="${MENUTESTDIR:-/tmp/menutest}" +. menutest +# hack, figure out the var to use here + +tpstart() { + tet_infoline "$*" + FAIL=N +} + +tet_startup='' +tet_cleanup='' +declare -i count=1 +iclist='' +echo $TESTS +for TESTCASE in ${TESTS}; do + [ ! -e "tests/${TESTCASE}/test" ] && continue; + # this basically curries the arg to run_test. + eval "tp${count}() { + . tests/${TESTCASE}/test + tpstart \"$(. tests/${TESTCASE}/test; echo ${TEST_PURPOSE-none stated})\"; + if ! run_test tests/\"$TESTCASE\"; then + tet_result FAIL; + else + tet_result PASS; + fi + set +x + }"; + iclist="${iclist} ic${count}" + eval "ic${count}=tp${count}" + # force subshelling, so that it doesn't pull a die on us + ((count+=1)) +done +tet_iclist=iclist +. /opt/lsb-tet3-lite/lib/posix_sh/tcm.sh +tet_outputline 100 "xdg menu test" +tet_tcm_main $tet_iclist + diff --git a/menu/tet_scen b/menu/tet_scen new file mode 100644 index 0000000..4fe544e --- /dev/null +++ b/menu/tet_scen @@ -0,0 +1,5 @@ +all + "Starting menu tests" + /tests/tet_menutest + "finished menu tests" + diff --git a/menu/tetexec.cfg b/menu/tetexec.cfg new file mode 100644 index 0000000..ea150c9 --- /dev/null +++ b/menu/tetexec.cfg @@ -0,0 +1 @@ +TET_PASS_TC_NAME=True diff --git a/recent-files/recent-file-spec.xml b/recent-files/recent-file-spec.xml new file mode 100644 index 0000000..b473de8 --- /dev/null +++ b/recent-files/recent-file-spec.xml @@ -0,0 +1,156 @@ +<?xml version="1.0"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +]> +<article id="index"> + <articleinfo> + <title>Recent File Storage Specification</title> + <releaseinfo>Version 0.2</releaseinfo> + <date>12 August 2002</date> + <authorgroup> + <author> + <firstname>James</firstname> + <surname>Willcox</surname> + <affiliation> + <address> + <email>jwillcox@gnome.org</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="overview"> + <title>Overview</title> + <para> + Many applications choose to have a menu containing a list of recently + used files, which can be used as an alternative to opening a file + selector. GNOME, and KDE applications have done this for quite some + time, and probably others have as well. + This specification aims to do the following things: + </para> + <itemizedlist mark="bullet"> + <listitem> + <para>Provide a standard mechanism for storing a list of recently used + files (really, URIs)</para> + </listitem> + <listitem> + <para>Allow for notification of changes in the list</para> + </listitem> + </itemizedlist> + <para> + Accomplishing this will make using applications that are not native + to the user's desktop a bit nicer, and give a more unified feel to + the X desktop in general. It will be especially useful to applications + that don't belong to a specific desktop at all, such as Mozilla and + Open Office, + since those applications could become compatible with all desktops + in this area without special case considerations for each one. + </para> + </sect1> + + <sect1 id="storage"> + <title>Storage</title> + <para> + For different desktops and applications to have access to the same + information, a protocol for storing the recent file list has to be + determined. An XML document will be used, of the form below: + </para> + <programlisting><![CDATA[ +<?xml version="1.0"?> +<RecentFiles> + <RecentItem> + <URI>file:///home/jwillcox/testfile.txt</URI> + <Mime-Type>text/plain</Mime-Type> + <Timestamp>1028181153</Timestamp> + <Private/> + <Groups> + <Group>Recent File Test</Group> + </Groups> + </RecentItem> + <RecentItem> + <URI>file:///home/jwillcox/recent-file-spec.xml</URI> + <Mime-Type>text/xml</Mime-Type> + <Timestamp>1028181158</Timestamp> + <Private/> + <Groups> + <Group>Recent File Test</Group> + </Groups> + </RecentItem> +</RecentFiles> + ]]></programlisting> + <para> + The URI, Mime-Type, Timestamp tags are required, but the + Private, Groups, and Group tags are not. The Timestamp tag should be + the number of + seconds sinced the Epoch when the item was added to the list. + The Group tags exist for the purpose of + making groups of items with an arbitrary set of MIME types. A single item + can belong to an unlimited number of groups. If the Private tag is + specified, it means that implementations should only include the item if + requestor has specifically asked for items in a group that the item + belongs to. For instance, maybe a file selector would like to hold a list + of directories that you have recently saved files in, and allow you to + choose from one of these next time you save a file. You wouldn't want + those directories showing up in the "Recent Documents" menu. If the items + are put into the "File Selector Save Directories" group and marked as + private, this problem is solved. + </para> + <para> + All text in the file should be stored in the UTF-8 encoding. + No local paths are allowed in the URI tag. They should be converted to a + valid + <ulink url="http://www.ietf.org/rfc/rfc2396.txt">URI</ulink> + with a "file" scheme. Items with the + same URI should not be allowed. If a duplicate is found, it should have + its timestamp updated, and any new groups added to it. No other + information should be changed. The document should be stored in + "~/.recently-used", and it should contain no more than 500 items. + </para> + <para> + Before reading or writing the document, it should be locked using the + POSIX lockf() mechanism, and unlocked when finished. + </para> + </sect1> + + <sect1 id="notification"> + <title>Notification</title> + <para> + Notification should be accomplished by simply monitoring the document for + changes. This can be done by either polling the file every so often, + or using a library like + <ulink url="http://oss.sgi.com/projects/fam/">FAM</ulink>. + </para> + </sect1> + + <appendix id="changes"> + <title>Change history</title> + <formalpara> + <title>Version 0.2, 12 August 2002, James Willcox</title> + <para> + <itemizedlist> + <listitem> + <para> + Switched from flat-file storage to XML. This was done to + facilitate easier storage of meta-data. Files can now belong + to "groups", and the timestamp is now a required piece of + meta-data. + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + <formalpara> + <title>Version 0.1, 8 July 2002, James Willcox</title> + <para> + <itemizedlist> + <listitem> + <para> + Created initial draft. + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + </appendix> +</article> diff --git a/secret-service/.gitignore b/secret-service/.gitignore new file mode 100644 index 0000000..551e415 --- /dev/null +++ b/secret-service/.gitignore @@ -0,0 +1,3 @@ + +/html/*.html +reference.xml diff --git a/secret-service/Makefile b/secret-service/Makefile new file mode 100644 index 0000000..00efeb9 --- /dev/null +++ b/secret-service/Makefile @@ -0,0 +1,17 @@ + +SPEC = org.freedesktop.Secrets.xml + +all: html/index.html + +html/index.html: reference.xml docbook-params.xsl specification.xml + xmlto --skip-validation -o html/ -x docbook-params.xsl xhtml specification.xml + +reference.xml: tools/spec-to-docbook.xsl $(SPEC) + xsltproc tools/spec-to-docbook.xsl $(SPEC) > $@ + +clean: + rm -f reference.xml + rm -f html/*.html + +upload: all + rsync -Hvax html/./ specs.freedesktop.org:/srv/specifications.freedesktop.org/www/secret-service/./ diff --git a/secret-service/README b/secret-service/README new file mode 100644 index 0000000..72a9997 --- /dev/null +++ b/secret-service/README @@ -0,0 +1,20 @@ +Generating the specification consists of separate steps: + +1. Use an xslt processor to create a DocBook XML document from the Telepathy + Introspection document using the provided stylesheet: + +$ xsltproc tools/spec-to-docbook.xsl \ + org.freedesktop.Secrets.xml >reference.xml + +2. Convert specification.xml and reference.xml to a suitable output format + (specification.xml includes reference.xml), eg html: + +$ xmlto --skip-validation -o html -p params-html.xsl xhtml specification.xml + +If you choose a different directory for html generation, be sure to copy +html/style.css to that location. + +Then open the resulting html/index.html in your favourite browser. + + +Michael Leupold <lemma@confuego.org> diff --git a/secret-service/docbook-params.xsl b/secret-service/docbook-params.xsl new file mode 100644 index 0000000..5d8591a --- /dev/null +++ b/secret-service/docbook-params.xsl @@ -0,0 +1,39 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + +<!-- + Parameters for DocBook transformation. + + Copyright (C) 2009 Michael Leupold <lemma@confuego.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 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 St, Fifth Floor, Boston, MA 02110-1301 USA +--> + + <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl"/> + + <xsl:param name="toc.max.depth">3</xsl:param> + <xsl:param name="generate.section.toc.level">0</xsl:param> + <xsl:param name="generate.toc"> + book toc + part nop + chapter toc + </xsl:param> + <xsl:param name="html.stylesheet">style.css</xsl:param> + <xsl:param name="funcsynopsis.style">ansi</xsl:param> + <xsl:param name="funcsynopsis.decoration">1</xsl:param> + <xsl:param name="refentry.generate.name">0</xsl:param> + <xsl:param name="refentry.generate.title">1</xsl:param> + +</xsl:stylesheet> diff --git a/secret-service/html/style.css b/secret-service/html/style.css new file mode 100644 index 0000000..f8a03b0 --- /dev/null +++ b/secret-service/html/style.css @@ -0,0 +1,127 @@ +/* reference.css, a stylesheet for reference documentation + * generated by the DocBook XSL Stylesheets */ +/* $Id: reference.css 8234 2009-02-09 12:10:48Z xmldoc $ */ + +div.legalnotice { + font-size: 80%; +} + +div.note, div.tip, div.warning { + margin-left: 5%; + margin-right: 10%; + padding: 5px; +} + +div.note, div.tip { + border-left: solid #d5dee3 20px; + border-right: solid #d5dee3 20px; +} + +div.note, div.tip { + border-left: solid palegreen 20px; + border-right: solid palegreen 20px; +} + +div.warning { + border-left: solid yellow 20px; + border-right: solid yellow 20px; +} + +div.note p, div.tip p, div.warning p { + margin-top: 0px; + margin-bottom: 4px; +} + +div.note h3, div.tip h3, div.warning h3 { + margin-top: 0; +} + +div.informalexample { + background-color: #d5dee3; + border-top-width: 2px; + border-top-style: double; + border-top-color: #d3d3d3; + border-bottom-width: 2px; + border-bottom-style: double; + border-bottom-color: #d3d3d3; + padding: 4px; + margin: 0em; + margin-left: 2em; +} + +pre.programlisting, pre.synopsis { + whitespace: pre; + font-family: monospace; + background-color: #d5dee3; + border-top-width: 1px; + border-top-style: single; + border-top-color: #d3d3d3; + border-bottom-width: 1px; + border-bottom-style: single; + border-bottom-color: #d3d3d3; + padding: 4px; + margin: 0em; + margin-top: 6px; + margin-bottom: 6px; +} + +div.informalexample pre { + whitespace: pre; + font-family: monospace; + border-top-width: 0px; + border-bottom-width: 0px; + padding: 0px; +} + +/* Parameter and PI titles */ + div.refnamediv h2 { + font-size: 2em; +} + +div.funcsynopsis, code.fieldsynopsis, +div.refsect2 div.refsynopsisdiv { + padding: 0.5em; + background-color: #F4F4F4; + border: 1px solid gray; + display: block; + width: 80%; +} + +div.refsynopsisdiv code.fieldsynopsis { + padding: 0; + border: 0; +} + +code.fieldsynopsis span.modifier { + min-width: 8em; + display: inline-block; +} + +code.fieldsynopsis span.type { + min-width: 11em; + display: inline-block; +} + +code.fieldsynopsis span.varname { + min-width: 11em; + display: inline-block; + font-size: 1.1em; + font-weight: bold; +} + +div.funcprototype-spacer { + max-height: 0.5em; +} + +table.funcprototype-table * td { + font-size: 0.9em; +} + +table.funcprototype-table * td code.funcdef { + font-size: 1.1em; +} + +b.fsfunc { + display: inline-block; + min-width: 11em; +}
\ No newline at end of file diff --git a/secret-service/org.freedesktop.Secrets.xml b/secret-service/org.freedesktop.Secrets.xml new file mode 100644 index 0000000..b6fba64 --- /dev/null +++ b/secret-service/org.freedesktop.Secrets.xml @@ -0,0 +1,490 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + +<!-- + * This is the well known dbus service name for controlling the + * entire daemon. The service manages collections of secrets. These + * are analogous to the gnome-keyring 'keyrings'. +--> +<tp:spec xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <tp:title>Secret Service API Specification</tp:title> + <tp:version>0.1</tp:version> + <tp:copyright> + Copyright (C) 2009 Stef Walter <stef@memberwebs.com> + </tp:copyright> + <tp:copyright> + Copyright (C) 2009 Michael Leupold <lemma@confuego.org> + </tp:copyright> + + <!-- + * ====================================================================================== + * ERROR CODES + * + --> + + <tp:errors namespace="org.freedesktop.Secret.Error"> + <tp:docstring>Errors returned by the Secret Service API.</tp:docstring> + <tp:error name="IsLocked"> + <tp:docstring>The object must be unlocked before this action can be carried out.</tp:docstring> + </tp:error> + <tp:error name="NoSession"> + <tp:docstring>The session does not exist.</tp:docstring> + </tp:error> + <tp:error name="NoSuchObject"> + <tp:docstring>No such item or collection exists.</tp:docstring> + </tp:error> + </tp:errors> + + <!-- + * ====================================================================================== + * SECRET STRUCT + * Signature: (oayays) + * + --> + + <tp:struct name="Secret"> + <tp:docstring>The Secret type holds a (possibly encoded) secret.</tp:docstring> + <tp:member type="o" name="session"> + <tp:docstring>The session that was used to encode the secret.</tp:docstring> + </tp:member> + <tp:member type="ay" name="parameters"> + <tp:docstring>Algorithm dependent parameters for secret value encoding.</tp:docstring> + </tp:member> + <tp:member type="ay" name="value"> + <tp:docstring>Possibly encoded secret value</tp:docstring> + </tp:member> + <tp:member type="s" name="content_type"> + <tp:docstring>The content type of the secret. For example: 'text/plain; charset=utf8'</tp:docstring> + </tp:member> + </tp:struct> + + <tp:mapping name="ObjectPath_Secret_Map"> + <tp:docstring>A mapping from object-paths to Secret structs</tp:docstring> + <tp:member type="o" name="Key"> + <tp:docstring>D-Bus object-path</tp:docstring> + </tp:member> + <tp:member type="(oayays)" name="Value" tp:type="Secret"> + <tp:docstring>A secret</tp:docstring> + </tp:member> + </tp:mapping> + + <!-- + * ====================================================================================== + * SERVICE INTERFACE + * + --> + + <node name="/org/freedesktop/Secrets"> + + <interface name="org.freedesktop.Secret.Service"> + + <tp:docstring> + The Secret Service manages all the sessions and collections. + </tp:docstring> + + <property name="Collections" type="ao" access="read"> + <tp:docstring>The object paths of all collections (ie: keyrings)</tp:docstring> + </property> + + <method name="OpenSession"> + <tp:docstring>Open a unique session for the caller application.</tp:docstring> + <arg name="algorithm" type="s" direction="in"> + <tp:docstring>The algorithm the caller wishes to use.</tp:docstring> + </arg> + <arg name="input" type="v" direction="in"> + <tp:docstring>Input arguments for the algorithm.</tp:docstring> + </arg> + <arg name="output" type="v" direction="out"> + <tp:docstring>Output of the session algorithm negotiation.</tp:docstring> + </arg> + <arg name="result" type="o" direction="out"> + <tp:docstring>The object path of the session, if session was created.</tp:docstring> + </arg> + </method> + + <method name="CreateCollection"> + <tp:docstring>Create a new collection with the specified properties.</tp:docstring> + <arg name="properties" type="a{sv}" direction="in"> + <tp:docstring xmlns:docbook="http://docbook.org/ns/docbook"> + <para> + Properties for the new collection. This allows setting the new collection's + properties upon its creation. All READWRITE properties are useable. Specify + the property names in full interface.Property form. + <example> + <title>Example for properties</title> + <programlisting> +<![CDATA[ +properties = { "org.freedesktop.Secret.Collection.Label": "MyCollection" } +]]> + </programlisting> + </example> + </para> + </tp:docstring> + </arg> + <arg name="alias" type="s" direction="in"> + <tp:docstring xmlns:docbook="http://docbook.org/ns/docbook"> + <para> + If creating this connection for a well known alias then a string like + <literal>default</literal>. If an collection with this well-known alias already + exists, then that collection will be returned instead of creating a new + collection. Any readwrite properties provided to this function will be set on + the collection. + </para> + <para> + Set this to an empty string if the new collection should not be associated with a + well known alias. + </para> + </tp:docstring> + </arg> + <arg name="collection" type="o" direction="out"> + <tp:docstring>The new collection object, or '/' if prompting is necessary.</tp:docstring> + </arg> + <arg name="prompt" type="o" direction="out"> + <tp:docstring>A prompt object if prompting is necessary, or '/' if no prompt was needed.</tp:docstring> + </arg> + </method> + + <method name="SearchItems"> + <tp:docstring>Find items in any collection.</tp:docstring> + <arg name="attributes" type="a{ss}" direction="in"> + <tp:docstring>Find secrets in any collection.</tp:docstring> + </arg> + <arg name="unlocked" type="ao" direction="out"> + <tp:docstring>Items found.</tp:docstring> + </arg> + <arg name="locked" type="ao" direction="out"> + <tp:docstring>Items found that require authentication.</tp:docstring> + </arg> + </method> + + <method name="Unlock"> + <tp:docstring>Unlock the specified objects.</tp:docstring> + <arg name="objects" type="ao" direction="in"> + <tp:docstring>Objects to unlock.</tp:docstring> + </arg> + <arg name="unlocked" type="ao" direction="out"> + <tp:docstring>Objects that were unlocked without a prompt.</tp:docstring> + </arg> + <arg name="prompt" type="o" direction="out"> + <tp:docstring>A prompt object which can be used to unlock the remaining objects, or the special value '/' when no prompt is necessary.</tp:docstring> + </arg> + </method> + + <method name="Lock"> + <tp:docstring>Lock the items.</tp:docstring> + <arg name="objects" type="ao" direction="in"> + <tp:docstring>Objects to lock.</tp:docstring> + </arg> + <arg name="locked" type="ao" direction="out"> + <tp:docstring>Objects that were locked without a prompt.</tp:docstring> + </arg> + <arg name="Prompt" type="o" direction="out"> + <tp:docstring>A prompt to lock the objects, or the special value '/' when no prompt is necessary.</tp:docstring> + </arg> + </method> + + <method name="GetSecrets"> + <tp:docstring>Retrieve multiple secrets from different items.</tp:docstring> + <arg name="items" type="ao" direction="in"> + <tp:docstring>Items to get secrets for.</tp:docstring> + </arg> + <arg name="session" type="o" direction="in"> + <tp:docstring>The session to use to encode the secrets.</tp:docstring> + </arg> + <arg name="secrets" type="a{o(oayays)}" direction="out" tp:type="ObjectPath_Secret_Map"> + <tp:docstring>Secrets for the items.</tp:docstring> + </arg> + </method> + + <method name="ReadAlias"> + <tp:docstring>Get the collection with the given alias.</tp:docstring> + <arg name="name" type='s' direction='in'> + <tp:docstring>An alias, such as 'default'.</tp:docstring> + </arg> + <arg name="collection" type='o' direction='out'> + <tp:docstring>The collection or the the path '/' if no such collection exists.</tp:docstring> + </arg> + </method> + + <method name="SetAlias"> + <tp:docstring>Setup a collection alias.</tp:docstring> + <arg name="name" type='s' direction='in'> + <tp:docstring>An alias, such as 'default'.</tp:docstring> + </arg> + <arg name="collection" type='o' direction='in'> + <tp:docstring> + The collection to make the alias point to. To remove an alias use the special value '/'. + </tp:docstring> + </arg> + </method> + + <signal name="CollectionCreated"> + <tp:docstring>A collection was created.</tp:docstring> + <arg name="collection" type="o"> + <tp:docstring>Collection that was created</tp:docstring> + </arg> + </signal> + + <signal name="CollectionDeleted"> + <tp:docstring>A collection was deleted.</tp:docstring> + <arg name="collection" type="o"> + <tp:docstring>Collection that was deleted.</tp:docstring> + </arg> + </signal> + + <signal name="CollectionChanged"> + <tp:docstring>A collection was changed.</tp:docstring> + <arg name="collection" type="o"> + <tp:docstring>Collection that was changed.</tp:docstring> + </arg> + </signal> + + </interface> + + </node> + + <!-- + * ====================================================================================== + * COLLECTION INTERFACE + * + --> + + <node name="/org/freedesktop/Secrets/collection/xxxx"> + + <interface name="org.freedesktop.Secret.Collection"> + + <tp:docstring>A collection of items containing secrets.</tp:docstring> + + <property name="Items" type="ao" access="read"> + <tp:docstring>Items in this collection.</tp:docstring> + </property> + + <property name="Label" type="s" access="readwrite"> + <tp:docstring>The displayable label of this collection.</tp:docstring> + </property> + + <property name="Locked" type="b" access="read"> + <tp:docstring> + Whether the collection is locked and must be authenticated by the client application. + </tp:docstring> + </property> + + <property name="Created" type="t" access="read"> + <tp:docstring>The unix time when the collection was created.</tp:docstring> + </property> + + <property name="Modified" type="t" access="read"> + <tp:docstring>The unix time when the collection was last modified.</tp:docstring> + </property> + + <method name="Delete"> + <tp:docstring>Delete this collection.</tp:docstring> + <arg name="prompt" type="o" direction="out"> + <tp:docstring>A prompt to delete the collection, or the special value '/' when no prompt is necessary.</tp:docstring> + </arg> + </method> + + <method name="SearchItems"> + <tp:docstring>Search for items in this collection matching the lookup attributes.</tp:docstring> + <arg name="attributes" type="a{ss}" direction="in"> + <tp:docstring>Attributes to match.</tp:docstring> + </arg> + <arg name="results" type="ao" direction="out"> + <tp:docstring>Items that matched the attributes.</tp:docstring> + </arg> + </method> + + <method name="CreateItem"> + <tp:docstring>Create an item with the given attributes, secret and label. If replace is set, then it replaces an item already present with the same values for the attributes.</tp:docstring> + <arg name="properties" type="a{sv}" direction="in"> + <tp:docstring>The properties for the new item.</tp:docstring> + <tp:docstring xmlns:docbook="http://docbook.org/ns/docbook"> + <para> + Properties for the new item. This allows setting the new item's + properties upon its creation. All READWRITE properties are useable. + Specify the property names in full interface.Property form. + <example> + <title>Example for properties</title> + <programlisting> +<![CDATA[ +properties = { + "org.freedesktop.Secret.Item.Label": "MyItem", + "org.freedesktop.Secret.Item.Attributes": { + "Attribute1": "Value1", + "Attribute2": "Value2" + } + } +]]> + </programlisting> + </example> + <note> + <para> + Please note that there is a distinction between the terms + <emphasis>Property</emphasis>, which refers to a D-Bus properties + of an object, and <emphasis>Attribute</emphasis>, which refers to one + of a secret item's string-valued attributes. + </para> + </note> + </para> + </tp:docstring> + </arg> + <arg name="secret" type="(oayays)" tp:type="Secret" direction="in"> + <tp:docstring>The secret to store in the item, encoded with the included session.</tp:docstring> + </arg> + <arg name="replace" type="b" direction="in"> + <tp:docstring>Whether to replace an item with the same attributes or not.</tp:docstring> + </arg> + <arg name="item" type="o" direction="out"> + <tp:docstring>The item created, or the special value '/' if a prompt is necessary.</tp:docstring> + </arg> + <arg name="prompt" type="o" direction="out"> + <tp:docstring>A prompt object, or the special value '/' if no prompt is necessary.</tp:docstring> + </arg> + </method> + + <signal name="ItemCreated"> + <tp:docstring>A new item in this collection was created.</tp:docstring> + <arg name="item" type="o"> + <tp:docstring>The item that was created.</tp:docstring> + </arg> + </signal> + + <signal name="ItemDeleted"> + <tp:docstring>An item in this collection was deleted.</tp:docstring> + + <arg name="item" type="o"> + <tp:docstring>The item that was deleted.</tp:docstring> + </arg> + </signal> + + <signal name="ItemChanged"> + <tp:docstring>An item in this collection changed.</tp:docstring> + + <arg name="item" type="o"> + <tp:docstring>The item that was changed.</tp:docstring> + </arg> + </signal> + + </interface> + + </node> + + <!-- + * ====================================================================================== + * ITEM INTERFACE + * + --> + + <node name="/org/freedesktop/Secret/collection/xxxx/iiii"> + + <interface name="org.freedesktop.Secret.Item"> + + <tp:docstring>An item contains a secret, lookup attributes and has a label.</tp:docstring> + + <property name="Locked" type="b" access="read"> + <tp:docstring>Whether the item is locked and requires authentication, or not.</tp:docstring> + </property> + + <property name="Attributes" type="a{ss}" access="readwrite"> + <tp:docstring>The lookup attributes for this item.</tp:docstring> + </property> + + <property name="Label" type="s" access="readwrite"> + <tp:docstring>The displayable label for this item.</tp:docstring> + </property> + + <property name="Created" type="t" access="read"> + <tp:docstring>The unix time when the item was created.</tp:docstring> + </property> + + <property name="Modified" type="t" access="read"> + <tp:docstring>The unix time when the item was last modified.</tp:docstring> + </property> + + <method name="Delete"> + <tp:docstring>Delete this item.</tp:docstring> + <arg name="Prompt" type="o" direction="out"> + <tp:docstring>A prompt object, or the special value '/' if no prompt is necessary.</tp:docstring> + </arg> + </method> + + <method name="GetSecret"> + <tp:docstring>Retrieve the secret for this item.</tp:docstring> + <arg name="session" type="o" direction="in"> + <tp:docstring>The session to use to encode the secret.</tp:docstring> + </arg> + <arg name="secret" type="(oayays)" tp:type="Secret" direction="out"> + <tp:docstring>The secret retrieved.</tp:docstring> + </arg> + </method> + + <method name="SetSecret"> + <tp:docstring>Set the secret for this item.</tp:docstring> + <arg name="secret" type="(oayays)" tp:type="Secret" direction="in"> + <tp:docstring>The secret to set, encoded for the included session.</tp:docstring> + </arg> + </method> + + </interface> + + </node> + + <!-- + * ====================================================================================== + * SESSION INTERFACE + * + --> + + <node name="/org/freedesktop/Secret/session/ssss"> + + <interface name="org.freedesktop.Secret.Session"> + + <tp:docstring>A session tracks state between the service and a client application.</tp:docstring> + + <method name="Close"> + <tp:docstring>Close this session.</tp:docstring> + </method> + + </interface> + + </node> + + <!-- + * ====================================================================================== + * PROMPT INTERFACE + * + --> + + <node name="/org/freedesktop/Secret/prompts/pppp"> + + <interface name="org.freedesktop.Secret.Prompt"> + <tp:docstring>A prompt necessary to complete an operation.</tp:docstring> + + <method name="Prompt"> + <tp:docstring>Perform the prompt.</tp:docstring> + <arg name="window-id" type="s" direction="in"> + <tp:docstring>Platform specific window handle to use for + showing the prompt.</tp:docstring> + </arg> + </method> + + <method name="Dismiss"> + <tp:docstring>Dismiss the prompt.</tp:docstring> + </method> + + <signal name="Completed"> + <tp:docstring>The prompt and operation completed.</tp:docstring> + <arg name="dismissed" type="b"> + <tp:docstring>Whether the prompt and operation were dismissed or not.</tp:docstring> + </arg> + <arg name="result" type="v"> + <tp:docstring>The possibly empty, operation specific, + result.</tp:docstring> + </arg> + </signal> + + </interface> + + </node> + +</tp:spec> diff --git a/secret-service/specification.xml b/secret-service/specification.xml new file mode 100644 index 0000000..507eb78 --- /dev/null +++ b/secret-service/specification.xml @@ -0,0 +1,580 @@ +<?xml version="1.0"?> +<book xml:id="index" xmlns="http://docbook.org/ns/docbook" version="5.0"> + <bookinfo> + <title>Secret Service API Draft</title> + <releaseinfo> + Secret Service 0.2 DRAFT + </releaseinfo> + + <authorgroup> + <author> + <firstname>Stef</firstname> + <surname>Walter</surname> + <affiliation> + <jobtitle>GNOME Keyring Developer</jobtitle> + <address> + <email>stefw@collabora.co.uk</email> + </address> + </affiliation> + </author> + <author> + <firstname>Michael</firstname> + <surname>Leupold</surname> + <affiliation> + <jobtitle>KWallet Developer</jobtitle> + <address> + <email>lemma@confuego.org</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2008-2011</year> + <holder>The Secret Service API Authors</holder> + </copyright> + + </bookinfo> + + <part xml:id="description"> + <title>API Documentation</title> + <chapter> + <title>Introduction</title> + + <para>The Secret Service API allows client applications to store secrets securely in a + service running in the user's login session. </para> + + <para>The secrets are usually stored in an encrypted manner by the service. The + service may need to be unlocked by the user before the secrets become available + for retrieval by client applications.</para> + + <para>The Secret Service stores a secret along with a set of lookup attributes. + The attributes can be used to look up and retrieve a secret at a later date. The + lookup attributes are not treated as secret material, and the service may choose + not to encrypt attributes when storing them to disk.</para> + + <para>This API was desigened by GNOME and KDE developers with the goal of having + a common way to store secrets. Its predecessors are the desktop-specific APIs + used by GNOME Keyring and KWallet.</para> + </chapter> + + <chapter> + <title>Secrets</title> + + <para>A secret is something an application wishes to store securely. A good example + is a password that an application needs to save and use at a later date.</para> + + <para>Within this API a secret value is treated as an array of bytes. It is + recommended that a secret consist of user-readable text, although this API has + no such requirement.</para> + + <para>Applications wishing to store multiple values as part of a single secret, may + choose to use a textual format to combine these values into one. For example, multiple + values may be combined using the 'desktop' key file format, or XML.</para> + + <para>Secrets may be <link linkend='transfer-secrets'>encrypted when transferred</link> + to or from the client application.</para> + + <para>The <link linkend='type-Secret'><classname>Secret</classname> structure</link> encapsulates + a secret value along with its transfer encryption parameters.</para> + </chapter> + + <chapter> + <title>Collection and Items</title> + + <para>Each secret is stored together with + <link linkend='lookup-attributes'>lookup attributes</link> and a label. These together + form an <link linkend='org.freedesktop.Secret.Item'>item</link>.</para> + + <para>A group of items together form a + <link linkend='org.freedesktop.Secret.Collection'>collection</link>. + A collection is similar in concept to the terms 'keyring' or 'wallet'.</para> + + <para>Collections and items are represented as DBus objects, and each has its own + object path. Under normal circumstances, the object path of a collection or item + should not change for its lifetime.</para> + + <para>It is strongly recommended that client applications use + <link linkend='lookup-attributes'>lookup attributes</link> to find items rather than + recording the object path of a stored item. This allows maximum interoperability.</para> + + <para>An item or a collection may be initially in a locked state. When in a locked + state the item or collection may not be modified in any way, and the secret may not + be read. Client applications that require access to the secret of a locked item, or + desire to modify a locked item, must <link linkend='unlocking'>unlock it</link> before use.</para> + + <para>The service must prevent modification of locked collections or items. On + such an invalid access the + <link linkend='org.freedesktop.Secret.Error.IsLocked'><errorname>IsLocked</errorname></link> + error should be raised.</para> + + <para>Client applications without special requirements should store in the default + collection. The default collection is always accessible through a + <link linkend='object-paths'>specific object path</link>.</para> + + <para>A new item can be created with the + <link linkend='org.freedesktop.Secret.Collection.CreateItem'> + <function>CreateItem()</function></link> + method on the Collection interface. When creating an item, the properties of the new + item are specified. The service may ignore or change these properties when creating + the item.</para> + + <para>When creating an item, the service may need to prompt the user for additional + information. In this case, a <link linkend='prompts'>prompt object</link> is returned. It + must be <link linkend='org.freedesktop.Secret.Prompt.Prompt'>acted upon</link> in order for + the collection to be created. In this case, the + <link linkend='org.freedesktop.Secret.Prompt.Completed'>result of the prompt</link> + will contain the object path of the new item.</para> + + <para>An item can be deleted by calling the + <link linkend='org.freedesktop.Secret.Item.Delete'><function>Delete()</function></link> + method on the Item interface.</para> + + <para>When deleting an item, the service may need to prompt the user for additional + information. In this case, a <link linkend='prompts'>prompt object</link> is returned. It + must be <link linkend='org.freedesktop.Secret.Prompt.Prompt'>acted upon</link> in order for + the item to be deleted.</para> + + <para>Client applications with special needs can create a new collection by calling the + <link linkend='org.freedesktop.Secret.Service.CreateCollection'> + <function>CreateCollection()</function></link> + method on the Service interface. When creating a collection, the properties of the new + collection are specified. The service may ignore or change these properties when creating + the collection.</para> + + <para>When creating a collection, the service may need to prompt the user for additional + information. In this case, a <link linkend='prompts'>prompt object</link> is returned. It + must be <link linkend='org.freedesktop.Secret.Prompt.Prompt'>acted upon</link> in order for + the collection to be created. In this case, the + <link linkend='org.freedesktop.Secret.Prompt.Completed'>result of the prompt</link> + will contain the object path of the new collection.</para> + + <para>A collection can be deleted by calling the + <link linkend='org.freedesktop.Secret.Collection.Delete'><function>Delete()</function></link> + method on the Collection interface.</para> + + <para>When deleting a collection, the service may need to prompt the user for additional + information. In this case, a <link linkend='prompts'>prompt object</link> is returned. It + must be <link linkend='org.freedesktop.Secret.Prompt.Prompt'>acted upon</link> in order for + the collection to be deleted.</para> + </chapter> + + <chapter xml:id="aliases"> + <title>Aliases</title> + + <para>Collections may be accessed via well known aliases. For example an alias + called <literal>default</literal> tells applications which is the default + collection to store secrets.</para> + + <para>The aliased collections will be available at a + <link linkend='object-paths'>well-known DBus object path</link>.</para> + + <para>If an application needs to create a collection with a given alias, this can + be done in a race free fashion by specifying the alias parameter of the + <link linkend='org.freedesktop.Secret.Service.CreateCollection'>CreateCollection()</link> + method on the service interface. If a collection with that alias already exists, + then it will be returned instead of creating a new one.</para> + + <para>For applications like password managers it can be useful to allow the user to + configure which collection is associated with which well known alias. To alias or + unalias a collection use the + <link linkend='org.freedesktop.Secret.Service.SetAlias'>SetAlias()</link> method on the + service interface. Use the + <link linkend='org.freedesktop.Secret.Service.ReadAlias'>ReadAlias()</link> method on the + service interface to discover which collection is associated with a given alias.</para> + </chapter> + + <chapter xml:id="lookup-attributes"> + <title>Lookup Attributes</title> + + <para>Attributes can and should be stored with a secret to facilitate lookup + of the secret at a later date.</para> + + <para>An attribute constists of a name, and a value. Both parts are simple + strings.</para> + + <para>The service may have additional requirements as to what can be present + in an attribute name. It is recommended that attribute names are human + readable, and kept simple for the sake of simplicity.</para> + + <para>During a lookup, attribute names and values are matched via case-sensitive + string equality.</para> + + <para>It's important to remember that attributes are not part of the secret. + Services implementing this API will probably store attributes in an unencrypted + manner in order to support simple and effecient lookups.</para> + + <para>In order to search for items, use the + <link linkend='org.freedesktop.Secret.Service.SearchItems'><function>SearchItems()</function></link> + method of the Service interface. The matched items will be returned in two sets. The + <parameter class='function'>unlocked</parameter> return value will contain the object paths + of all the items that are not locked. The <parameter class='function'>locked</parameter> return + value will contain object paths of items that are locked, which can be + <link linkend='unlocking'>unlocked if desired</link>.</para> + + <para>The + <link linkend='org.freedesktop.Secret.Collection.SearchItems'><function>SearchItems()</function></link> + method of the Collection interface is similar, except for it only searches a single collection.</para> + + </chapter> + + <chapter xml:id="sessions"> + <title>Sessions</title> + + <para>A session is established between a client application and a service. A session + is used to <link linkend='transfer-secrets'>transfer secrets</link> between the client + application and the service.</para> + + <para>A session is established by calling the service's + <link linkend='org.freedesktop.Secret.Service.OpenSession'> + <function>OpenSession()</function></link> + method. Once established, a session is bound to calling application's connection to + the DBus session bus.</para> + + <para>A session is closed when the client application disconnects from the DBus + session bus. Alternatively the client application can call the + <link linkend='org.freedesktop.Secret.Session.Close'><function>Close()</function></link> + method on the session interface. Once a session is closed all session specific + negotiations will be dropped by the service.</para> + + <para>More than one session may opened by a client application, although this is + not normally necessary.</para> + </chapter> + + <chapter xml:id='transfer-secrets'> + <title>Transfer of Secrets</title> + + <para>To access or store secrets, use the + <link linkend='org.freedesktop.Secret.Item.GetSecret'><function>GetSecret()</function></link>, + <link linkend='org.freedesktop.Secret.Item.SetSecret'><function>SetSecret()</function></link> + methods on the item interface, or the + <link linkend='org.freedesktop.Secret.Service.GetSecrets'><function>GetSecrets()</function></link>, + method on the service interface.</para> + + <para>You must specify a session when retrieving or storing a secret. The session + controls how the secret is encoded during transfer. Since this is a D-Bus API, the + data in all method calls and other accesses in this API will go through multiple + processes, and may be cached arbitrarilyby the OS or elsewhere.</para> + + <para>The Secrets API has provision to encrypt secrets while in transit between + the service and the client application. The encryption is not envisioned to withstand + man in the middle attacks, or other active attacks. It is envisioned to minimize + storage of plain text secrets in memory and prevent storage plain text storage of + secrets in a swap file or other caching mechanism.</para> + + <para>Many client applications may choose not to make use of the provisions to + encrypt secrets in transit. In fact for applications unable to prevent their own + memory from being paged to disk (eg: Java, C# or Python apps), transfering + encrypted secrets would be an excersize of questionable value.</para> + + <section> + <title>Negotiation of Algorithms</title> + + <para>In order to encrypt secrets in transit, the service and the client + application must agree on an algorithm, and some algorithm specific + parameters (eg: a key).</para> + + <para>When the client application opens a <link linkend='sessions'>session</link> + with the service, it calls the + <link linkend='org.freedesktop.Secret.Service.OpenSession'><function> + OpenSession()</function></link> method on the service. The algorithms argument to the + <function>OpenSession()</function> method specifies a set of algorithms to be used + together for key agreement and encryption. The other arguments are algorithm + specific.</para> + + <para>If a service does not support a specific set of algorithms, a + <errorname>org.freedesktop.DBus.Error.NotSupported</errorname> + error is returned, and the client is free to try another set of algorithms. + The <emphasis>plain</emphasis> algorithm is almost always supported.</para> + + <para>An algorithm may require that the <function>OpenSession()</function> method is + called multiple times in succession to be complete. Each iteration transfers + algorithm specific data back forth between the service and the client. The object path + '/' is returned from <function>OpenSession()</function> when session negotiation is + incomplete.</para> + + <para>None of the algorithms documented in this initial version of the specification + require multiple calls to <function>OpenSession()</function>.</para> + + <para>When <function>OpenSession()</function> completes, it returns the session object + path along with a valid session object path.</para> + + <para>Once an session algorithm has been negotiated, it is used for all transfer a + secrets whenever that session is specified along with the + <link linkend='type-Secret'><classname>secret</classname></link>.</para> + </section> + + <section> + <title>Algorithm: plain</title> + + <segmentedlist> + <?dbhtml list-presentation="list"?> + <segtitle>Session algorithm</segtitle> + <segtitle><link linkend='org.freedesktop.Secret.Service.OpenSession'> + Session input</link></segtitle> + <segtitle><link linkend='org.freedesktop.Secret.Service.OpenSession'> + Session output</link></segtitle> + <segtitle><link linkend='type-Secret'> + <classname>Secret</classname> parameter</link></segtitle> + <seglistitem> + <!-- TODO: literal? --> + <seg><emphasis>plain</emphasis></seg> + <seg>empty string</seg> + <seg>empty string</seg> + <seg>empty string</seg> + </seglistitem> + </segmentedlist> + + <para>The plain algorithm does no encryption whatsoever.</para> + + <para>It is strongly recommended that a service implementing this API support + the <emphasis>plain</emphasis> algorithm.</para> + </section> + + <section> + <title>Algorithm: dh-ietf1024-sha256-aes128-cbc-pkcs7</title> + + <segmentedlist> + <?dbhtml list-presentation="list"?> + <segtitle>Session algorithm</segtitle> + <segtitle><link linkend='org.freedesktop.Secret.Service.OpenSession'> + Session input</link></segtitle> + <segtitle><link linkend='org.freedesktop.Secret.Service.OpenSession'> + Session output</link></segtitle> + <segtitle><link linkend='type-Secret'> + <classname>Secret</classname> parameter</link></segtitle> + <seglistitem> + <!-- TODO: literal? --> + <seg><emphasis>dh-ietf1024-sha256-aes128-cbc-pkcs7</emphasis></seg> + <seg>Client DH pub key as an array of bytes</seg> + <seg>Service DH pub key as an array of bytes</seg> + <seg>16 byte AES initialization vector</seg> + </seglistitem> + </segmentedlist> + + <para>DH key agreement <citation>rfc2631</citation> is used to create a secret key + using 1024 bit parameters of the standard IETF 'Second Oakley Group' + <citation>rfc2409</citation>. The secret key is then digested into a 128-bit key + appropriate for AES. This is done using HKDF <citation>rfc5869</citation> with NULL + salt and empty info, using the SHA-2 256 hash algorithm + <citation>fips-180-3.2008</citation>. The secrets are encrypted using AES + <citation>fips-197.2001</citation> in cipher block chaining mode with pkcs7 style + padding <citation>rfc2315</citation>.</para> + + <para>The public keys are transferred as an array of bytes representing an + unsigned integer of arbitrary size, most-significant byte first (e.g., the + integer 32768 is represented as the 2-byte string 0x80 0x00)</para> + </section> + + </chapter> + + <chapter xml:id='unlocking'> + <title>Locking and Unlocking</title> + + <para>Some items and/or collections may be marked as locked by the service. + The secrets of locked items cannot be accessed. Additionally, locked items or collections + cannot be modified by the client application.</para> + + <para>It's up to the service whether to unlock items individually, or collections as a + whole. The client application should act as if it must unlock each item individually.</para> + + <para>A service may upon unlocking a collection, unlock all items in that collection. If + a service is not able to unlock an item individually, it should treat a request to unlock + an item as a request to unlock the connection that the item is in.</para> + + <para>A service may choose to unlock items or collections just for a single client + application. Alternatively the service may choose to allow any client application to access + items or collections unlocked by a another client application.</para> + + <para>A client application should always be ready to unlock the items for the secrets + it needs, or objects it must modify. It must not assume that an item is already unlocked + for whatever reason.</para> + + <para>A service may lock previously unlocked items for any reason at any time. Usually this + is done in response to user actions, timeouts, or external actions (such as the computer + sleeping). The inherent race conditions present due to this are unavoidable, and must be + handled gracefully.</para> + + <para>In order to unlock an item or collection the service's + <link linkend='org.freedesktop.Secret.Service.Unlock'> + <function>Unlock()</function></link> + method is called with one or more DBus object paths of items or collections. The + <function>Unlock()</function> will return the DBus object paths of objects it could + immediately unlock without prompting.</para> + + <para>The <function>Unlock()</function> method may also return a + <link linkend='org.freedesktop.Secret.Prompt.Prompt'>prompt object</link>. If a prompt + object is returned, it must be <link linkend='prompts'>acted upon</link> in order to complete + the unlocking of the remaining objects. The + <link linkend='org.freedesktop.Secret.Prompt.Completed'>result of the prompt</link> + will contain the object paths that were successfully unlocked by the prompt.</para> + + <para>In order to lock an item or collection the service's + <link linkend='org.freedesktop.Secret.Service.Unlock'> + <function>Lock()</function></link> + method is called with one or more DBus object paths of items or collections. The + <function>Lock()</function> will return the DBus object paths of objects it could + immediately lock without prompting.</para> + + <para>The <function>Lock()</function> method may also return a + <link linkend='org.freedesktop.Secret.Prompt.Prompt'>prompt object</link>. If a prompt + object is returned, it must be <link linkend='prompts'>acted upon</link> in order to complete + the locking of the remaining objects. The + <link linkend='org.freedesktop.Secret.Prompt.Completed'>result of the prompt</link> + will contain the object paths that were successfully locked by the prompt.</para> + </chapter> + + <chapter xml:id='prompts'> + <title>Prompts and Prompting</title> + + <para>In order to complete various operations, such as unlocking a collection, the + service may need to prompt the user for additional information, such as a master password.</para> + + <para>The prompts are displayed by the service on behalf of the client application.</para> + + <para>Operations that require a prompt to complete will return a prompt object. The client + application must then call the + <link linkend='org.freedesktop.Secret.Prompt.Prompt'><function>Prompt()</function></link> + method of the prompt object to display the prompt. Client applications can use the + <parameter class='function'>window-id</parameter> + argument to display the prompt attached to their application window.</para> + + <para>Once the user provides the additional required information to the prompt, the service + completes the operation that required the prompt. Then it emits the the + <link linkend='org.freedesktop.Secret.Prompt.Completed'><function>Completed</function></link> + signal of the prompt object. The <parameter class='function'>result</parameter> argument of + the signal contains operation an operation specific result.</para> + + <para>Either the user or the client application can dismiss a prompt. In this case the + operation that required the additional information is cancelled. The client application + can dismiss a prompt by calling the + <link linkend='org.freedesktop.Secret.Prompt.Dismiss'><function>Dismiss()</function></link> + method of the prompt object. The <function>Completed</function> signal will be emitted + with its <parameter class='function'>dismissed</parameter> argument set to + <constant>TRUE</constant>.</para> + + <para>Once the <function>Completed</function> signal is emitted on a prompt object, it + is no longer valid. Prompt objects are specific to the client application's connection + to the DBus bus. Once an application disconnects, all its prompts are no longer valid.</para> + + <para>There is an inherent race between the <function>Dismiss()</function> method and the + <function>Completed</function> signal. An application calling <function>Dismiss()</function> + must be prepared to handle the fact that the <function>Completed</function> has already been + emitted (although perhaps not received by the client). In addition the client must be prepared + to handle the fact that the prompt object is no longer valid.</para> + </chapter> + + <chapter> + <title>What's not included in the API</title> + + <para>A service may implement additional DBus interfaces for further capabilities not + included in this specification. Password management applications or other narrowly + focused tools should make use of these when necessary.</para> + + <para>This specification does not mandate the use of master passwords to lock a + collection of secrets. The service may choose to implement any method for locking + secrets.</para> + + <para>This specification does not mandate any form of access control. The service may + choose to allow certain applications to access a keyring, and others.</para> + + <para>[TODO: complete]</para> + </chapter> + + <chapter> + <title>Notes for Service Implementors</title> + + <para>[TODO: complete]</para> + </chapter> + + </part> + + <part xml:id="ref-dbus-api"> + <title>D-Bus API Reference</title> + + <chapter xml:id='object-paths'> + <title>Object Paths</title> + + <para>The various DBus object paths used with the Secret Service API are designed to be human + readable but not displayed to the user. The object path of an item or collection should + not change for its lifetime, under normal circumstances.</para> + + <programlisting>/org/freedesktop/secrets</programlisting> + <para>The object path for the service.</para> + + <programlisting>/org/freedesktop/secrets/collection/<emphasis>xxxx</emphasis></programlisting> + <para>The object path for a collection, where <emphasis>xxxx</emphasis> represents a + possibly encoded or truncated version of the initial label of the collection.</para> + + <programlisting>/org/freedesktop/secrets/collection/<emphasis>xxxx</emphasis>/<emphasis>iiii</emphasis></programlisting> + <para>The object path for an item, where <emphasis>xxxx</emphasis> is the collection (above) + and <emphasis>iiii</emphasis> is an auto-generated item specific identifier.</para> + + <programlisting>/org/freedesktop/secrets/session/<emphasis>ssss</emphasis></programlisting> + <para>The object path for a session, where <emphasis>ssss</emphasis> is an auto-generated + session specific identifier.</para> + + <programlisting>/org/freedesktop/secrets/aliases/default</programlisting> + <para>The default collection for client applications to store secrets is available under + this object path in addition to its real object path (above). Other aliases may also be + present.</para> + </chapter> + + <xi:include href="reference.xml" xpointer="interfaces" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:fallback/> + </xi:include> + <xi:include href="reference.xml" xpointer="types" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:fallback/> + </xi:include> + <xi:include href="reference.xml" xpointer="errors" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:fallback/> + </xi:include> + + </part> + + <xi:include href="xml/annotation-glossary.xml" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:fallback/> + </xi:include> + + <bibliography> + <title>References</title> + + <bibliomixed> + <abbrev>rfc2315</abbrev> + IETF <ulink url="http://www.ietf.org/rfc/rfc2315.txt">RFC 2315</ulink>: + PKCS #7: Cryptographic Message Syntax Version 1.5 + </bibliomixed> + + <bibliomixed> + <abbrev>rfc2409</abbrev> + IETF <ulink url="http://www.ietf.org/rfc/rfc2409.txt">RFC 2409</ulink>: + The Internet Key Exchange (IKE) + </bibliomixed> + + <bibliomixed> + <abbrev>rfc2631</abbrev> + IETF <ulink url="http://www.ietf.org/rfc/rfc2631.txt">RFC 2631</ulink>: + Diffie-Hellman Key Agreement Method + </bibliomixed> + + <bibliomixed> + <abbrev>rfc5869</abbrev> + IETF <ulink url="http://www.ietf.org/rfc/rfc5869.txt">RFC 5869</ulink>: + HMAC-based Extract-and-Expand Key Derivation Function (HKDF) + </bibliomixed> + + <bibliomixed> + <abbrev>fips-180-3.2008</abbrev> + NIST <ulink url="http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf">FIPS PUB 180-3</ulink>: + Secure Hash Standard (SHS), October 2008 + </bibliomixed> + + <bibliomixed> + <abbrev>fips-197.2001</abbrev> + NIST <ulink url="http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf">FIPS PUB 197</ulink>: + Advanced Encryption Standard (AES), November 2001 + </bibliomixed> + + </bibliography> + +</book> diff --git a/secret-service/tools/resolve-type.xsl b/secret-service/tools/resolve-type.xsl new file mode 100644 index 0000000..a37f2af --- /dev/null +++ b/secret-service/tools/resolve-type.xsl @@ -0,0 +1,122 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + xmlns:html="http://www.w3.org/1999/xhtml" + exclude-result-prefixes="tp html"> + +<!-- + Helper templates for Telepathy D-Bus Introspection conversion. + + Copyright (C) 2009 Michael Leupold <lemma@confuego.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 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 St, Fifth Floor, Boston, MA 02110-1301 USA +--> + + <!-- Resolve the type a node has. This will first look at tp:type and + - if not found - use the type attribute --> + <xsl:template name="ResolveType"> + <xsl:param name="node"/> + <xsl:variable name="unstripped"> + <xsl:choose> + <xsl:when test="$node//@tp:type"> + <xsl:call-template name="TpType"> + <xsl:with-param name="type" select="$node//@tp:type"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="$node//@type"> + <xsl:call-template name="DBusType"> + <xsl:with-param name="type" select="$node//@type"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + Node doesn't contain a type. + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:value-of select="translate(translate($unstripped, ' ', ''), '
', '')"/> + </xsl:template> + + <!-- Map a D-Bus type to its EggDBus counterpart --> + <xsl:template name="DBusType"> + <xsl:param name="type"/> + <xsl:choose> + <xsl:when test="$type='o'">ObjectPath</xsl:when> + <xsl:when test="$type='s'">String</xsl:when> + <xsl:when test="$type='y'">Byte</xsl:when> + <xsl:when test="$type='b'">Boolean</xsl:when> + <xsl:when test="$type='n'">Int16</xsl:when> + <xsl:when test="$type='q'">UInt16</xsl:when> + <xsl:when test="$type='i'">Int32</xsl:when> + <xsl:when test="$type='u'">UInt32</xsl:when> + <xsl:when test="$type='x'">Int64</xsl:when> + <xsl:when test="$type='t'">UInt64</xsl:when> + <xsl:when test="$type='d'">Double</xsl:when> + <xsl:when test="$type='g'">Signature</xsl:when> + <xsl:when test="$type='v'">Variant</xsl:when> + <xsl:when test="starts-with($type, 'a{')"> + Dict< + <xsl:call-template name="DBusType"> + <xsl:with-param name="type" select="substring($type, 3, 1)"/> + </xsl:call-template> + , + <xsl:call-template name="DBusType"> + <xsl:with-param name="type" select="substring($type, 4, 1)"/> + </xsl:call-template> + > + </xsl:when> + <xsl:when test="starts-with($type, 'a')"> + Array< + <xsl:call-template name="DBusType"> + <xsl:with-param name="type" select="substring($type, 2)"/> + </xsl:call-template> + > + </xsl:when> + <!-- TODO: doesn't implement dict-entries and structs --> + <xsl:otherwise> + <xsl:message terminate="yes"> + Unknown DBus Type <xsl:value-of select="$type"/> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Resolve tp:type attributes by searching for matching tp:struct + and tp:mapping elements --> + <xsl:template name="TpType"> + <xsl:param name="type"/> + <xsl:choose> + <xsl:when test="/tp:spec/tp:struct[@name=$type]"> + <xsl:value-of select="$type"/> + </xsl:when> + <xsl:when test="/tp:spec/tp:mapping[@name=$type]"> + Dict< + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="/tp:spec/tp:mapping[@name=$type]/tp:member[@name='Key']"/> + </xsl:call-template>, + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="/tp:spec/tp:mapping[@name=$type]/tp:member[@name='Value']"/> + </xsl:call-template> + > + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + Unspecified type <xsl:value-of select="$type"/>. + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> +</xsl:stylesheet> diff --git a/secret-service/tools/spec-to-docbook.xsl b/secret-service/tools/spec-to-docbook.xsl new file mode 100644 index 0000000..a6b18a3 --- /dev/null +++ b/secret-service/tools/spec-to-docbook.xsl @@ -0,0 +1,1242 @@ +<?xml version="1.0"?> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + xmlns:html="http://www.w3.org/1999/xhtml" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:docbook="http://docbook.org/ns/docbook" + exclude-result-prefixes="tp html"> + +<!-- + Telepathy D-Bus Introspection to Docbook XML translator. + Based on Telepathy's doc-generator.xsl. + + Copyright (C) 2006-2008 Collabora Limited + Copyright (C) 2009 Michael Leupold <lemma@confuego.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 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 St, Fifth Floor, Boston, MA 02110-1301 USA +--> + + <xsl:output method="xml" indent="yes" encoding="ascii" + omit-xml-declaration="no"/> + + <xsl:include href="resolve-type.xsl"/> + + <xsl:param name="allow-undefined-interfaces" select="false()"/> + + <xsl:template match="docbook:* | html:* | @*"> + <xsl:copy> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <xsl:template name="direction"> + <xsl:param name="indirection"/> + <xsl:choose> + <xsl:when test="$indirection = 'in'">IN</xsl:when> + <xsl:otherwise>OUT</xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="tp:type"> + <xsl:call-template name="tp-type"> + <xsl:with-param name="tp-type" select="string(.)"/> + </xsl:call-template> + </xsl:template> + + <!-- tp:dbus-ref: reference a D-Bus interface, signal, method or property --> + <xsl:template match="tp:dbus-ref"> + <xsl:variable name="name"> + <xsl:choose> + <xsl:when test="@namespace"> + <xsl:value-of select="@namespace"/> + <xsl:text>.</xsl:text> + </xsl:when> + </xsl:choose> + <xsl:value-of select="string(.)"/> + </xsl:variable> + + <xsl:choose> + <xsl:when test="//interface[@name=$name] + or //interface/method[concat(../@name, '.', @name)=$name] + or //interface/signal[concat(../@name, '.', @name)=$name] + or //interface/property[concat(../@name, '.', @name)=$name] + or //interface[@name=concat($name, '.DRAFT')] + or //interface/method[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + or //interface/signal[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + or //interface/property[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + "> + <link linkend="{$name}"> + <literal><xsl:value-of select="$name"/></literal> + </link> + </xsl:when> + + <xsl:when test="$allow-undefined-interfaces"> + <!-- TODO: Convert to docbook --> + <span xmlns="http://www.w3.org/1999/xhtml" title="defined elsewhere"> + <xsl:value-of select="string(.)"/> + </span> + </xsl:when> + + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: cannot find D-Bus interface, method, </xsl:text> + <xsl:text>signal or property called '</xsl:text> + <xsl:value-of select="$name"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- tp:member-ref: reference a property of the current interface --> + <xsl:template match="tp:member-ref"> + <xsl:variable name="prefix" select="concat(ancestor::interface/@name, + '.')"/> + <xsl:variable name="name" select="string(.)"/> + + <xsl:if test="not(ancestor::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: Cannot use tp:member-ref when not in an</xsl:text> + <xsl:text> <interface> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:choose> + <xsl:when test="ancestor::interface/signal[@name=$name]"/> + <xsl:when test="ancestor::interface/method[@name=$name]"/> + <xsl:when test="ancestor::interface/property[@name=$name]"/> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: interface </xsl:text> + <xsl:value-of select="ancestor::interface/@name"/> + <xsl:text> has no signal/method/property called </xsl:text> + <xsl:value-of select="$name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + + <link linkend="{$prefix}{$name}"> + <literal><xsl:value-of select="concat($prefix, $name)"/></literal> + </link> + </xsl:template> + + <xsl:template match="*" mode="identity"> + <xsl:copy> + <xsl:apply-templates mode="identity"/> + </xsl:copy> + </xsl:template> + + <xsl:template match="tp:docstring"> + <para> + <xsl:copy-of select="child::node()"/> + </para> + </xsl:template> + + <xsl:template match="tp:docstring" mode="nopara"> + <xsl:copy-of select="child::node()"/> + </xsl:template> + + <xsl:template match="tp:added"> + <para> + Added in version <xsl:value-of select="@version"/>. + <xsl:apply-templates select="node()"/> + </para> + </xsl:template> + + <xsl:template match="tp:changed"> + <xsl:choose> + <xsl:when test="node()"> + <para> + Changed in version <xsl:value-of select="@version"/>: + <xsl:apply-templates select="node()"/></para> + </xsl:when> + <xsl:otherwise> + <para>Changed in version + <xsl:value-of select="@version"/></para> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="tp:deprecated"> + <para> + Deprecated since version <xsl:value-of select="@version"/>. + <xsl:apply-templates select="node()"/> + </para> + </xsl:template> + + <xsl:template match="tp:rationale"> + <!-- TODO: special? --> + <para> + <xsl:apply-templates select="node()"/> + </para> + </xsl:template> + + <xsl:template match="tp:errors"> + <title>Errors</title> + <xsl:apply-templates/> + </xsl:template> + + <xsl:template name="generic-types"> + <chapter> + <xsl:attribute name="xml:id">types</xsl:attribute> + <title>Types</title> + <xsl:call-template name="do-types"/> + </chapter> + </xsl:template> + + <xsl:template name="do-types"> + <xsl:if test="tp:simple-type"> + <section> + <title>Simple types</title> + <xsl:apply-templates select="tp:simple-type"/> + </section> + </xsl:if> + + <xsl:if test="tp:enum"> + <section> + <title>Enumerated types</title> + <xsl:apply-templates select="tp:enum"/> + </section> + </xsl:if> + + <xsl:if test="tp:flags"> + <section> + <title>Sets of flags</title> + <xsl:apply-templates select="tp:flags"/> + </section> + </xsl:if> + + <xsl:if test="tp:struct"> + <section> + <title>Struct types</title> + <xsl:apply-templates select="tp:struct"/> + </section> + </xsl:if> + + <xsl:if test="tp:mapping"> + <section> + <title>Map types</title> + <xsl:apply-templates select="tp:mapping"/> + </section> + </xsl:if> + + <xsl:if test="tp:external-type"> + <section> + <title>Types defined elsewhere</title> + <glosslist> + <xsl:apply-templates select="tp:external-type"/> + </glosslist> + </section> + </xsl:if> + </xsl:template> + + <xsl:template match="tp:error"> + <simplesect> + <title> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat(../@namespace, '.', translate(@name, ' ', ''))"/> + </xsl:attribute> + <literal><xsl:value-of select="concat(../@namespace, '.', translate(@name, ' ', ''))"/></literal> + </title> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </simplesect> + </xsl:template> + + <xsl:template match="/tp:spec/tp:copyright"> + <!-- TODO: use <copyright> --> + <legalnotice> + <para><xsl:apply-templates mode="text"/></para> + </legalnotice> + </xsl:template> + <xsl:template match="/tp:spec/tp:license"> + <!-- TODO: right tag? --> + <legalnotice> + <para> + <xsl:apply-templates/> + </para> + </legalnotice> + </xsl:template> + + <xsl:template match="tp:copyright"/> + <xsl:template match="tp:license"/> + + <xsl:template match="interface"> + + <refentry> + <xsl:attribute name="xml:id"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <refmeta> + <refentrytitle><literal><xsl:value-of select="@name"/></literal></refentrytitle> + </refmeta> + + <refnamediv> + <refdescriptor><xsl:value-of select="@name"/></refdescriptor> + <refname><xsl:value-of select="@name"/></refname> + <refpurpose><xsl:apply-templates select="tp:docstring" mode="nopara"/></refpurpose> + </refnamediv> + + <xsl:if test="tp:added"> + <refsection> + <xsl:apply-templates select="tp:added"/> + </refsection> + </xsl:if> + <xsl:if test="tp:changed"> + <refsection> + <xsl:apply-templates select="tp:changed"/> + </refsection> + </xsl:if> + <xsl:if test="tp:deprecated"> + <refsection> + <xsl:apply-templates select="tp:deprecated"/> + </refsection> + </xsl:if> + + <xsl:if test="@tp:causes-havoc"> + <refsection> + <warning> + <para> + This interface is <xsl:value-of select="@tp:causes-havoc"/> + and is likely to cause havoc to your API/ABI if bindings are generated. + Don't include it in libraries that care about compatibility. + </para> + </warning> + </refsection> + </xsl:if> + + <xsl:if test="tp:requires"> + <refsection> + <tip> + <para>Implementations of this interface must also implement:</para> + <itemizedlist> + <xsl:for-each select="tp:requires"> + <listitem> + <para> + <link linkend="{@interface}"> + <literal><xsl:value-of select="@interface"/></literal> + </link> + </para> + </listitem> + </xsl:for-each> + </itemizedlist> + </tip> + </refsection> + </xsl:if> + + <refsynopsisdiv> + <xsl:if test="method"> + <refsect2> + <title>Methods</title> + <funcsynopsis> + <xsl:apply-templates select="method" mode="funcsynopsislinked"/> + </funcsynopsis> + </refsect2> + </xsl:if> + <xsl:if test="signal"> + <refsect2> + <title>Signals</title> + <funcsynopsis> + <xsl:apply-templates select="signal" mode="funcsynopsislinked"/> + </funcsynopsis> + </refsect2> + </xsl:if> + <xsl:if test="property"> + <refsect2> + <title>Properties</title> + <refsynopsisdiv> + <title> </title> + <xsl:apply-templates select="property" mode="fieldsynopsislinked"/> + </refsynopsisdiv> + </refsect2> + </xsl:if> + </refsynopsisdiv> + + <xsl:if test="method"> + <refsection> + <title>Methods</title> + <xsl:apply-templates select="method" mode="detail"/> + </refsection> + </xsl:if> + + <xsl:if test="signal"> + <refsection> + <title>Signals</title> + <xsl:apply-templates select="signal" mode="detail"/> + </refsection> + </xsl:if> + + <xsl:if test="tp:property"> + <refsection> + <title>Telepathy Properties</title> + <para> + Accessed using the + <link linkend="org.freedesktop.Telepathy.Properties"> + <literal>org.freedesktop.Telepathy.Properties</literal> + </link> + </para> + <glosslist> + <xsl:apply-templates select="tp:property" mode="detail"/> + </glosslist> + </refsection> + </xsl:if> + + <xsl:if test="property"> + <refsection> + <title>D-Bus Properties</title> + <para> + Accessed using the org.freedesktop.DBus.Properties interface. + </para> + <xsl:apply-templates select="property" mode="detail"/> + </refsection> + </xsl:if> + + <xsl:call-template name="do-types"/> + + </refentry> + + </xsl:template> + + <xsl:template match="tp:flags"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:flags type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:flags type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <title><literal><xsl:value-of select="@name"/></literal></title> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + <glosslist> + <xsl:variable name="value-prefix"> + <xsl:choose> + <xsl:when test="@value-prefix"> + <xsl:value-of select="@value-prefix"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:for-each select="tp:flag"> + <glossentry> + <glossterm> + <xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/> + </glossterm> + <glossdef> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </xsl:when> + <xsl:otherwise> + (Undocumented) + </xsl:otherwise> + </xsl:choose> + </glossdef> + </glossentry> + </xsl:for-each> + </glosslist> + </section> + </xsl:template> + + <xsl:template match="tp:enum"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:enum type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:enum type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <title><literal><xsl:value-of select="@name"/></literal></title> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + <glosslist> + <xsl:variable name="value-prefix"> + <xsl:choose> + <xsl:when test="@value-prefix"> + <xsl:value-of select="@value-prefix"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:for-each select="tp:enumvalue"> + <glossentry> + <glossterm> + <xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/> + </glossterm> + <glossdef> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </xsl:when> + <xsl:otherwise> + (Undocumented) + </xsl:otherwise> + </xsl:choose> + </glossdef> + </glossentry> + </xsl:for-each> + </glosslist> + </section> + </xsl:template> + + <xsl:template match="property" mode="fieldsynopsis"> + + <fieldsynopsis> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat(../@name, '.', @name)"/> + </xsl:attribute> + <modifier> + <xsl:choose> + <xsl:when test="@access = 'read'"> + <xsl:text>READ</xsl:text> + </xsl:when> + <xsl:when test="@access = 'write'"> + <xsl:text>WRITE</xsl:text> + </xsl:when> + <xsl:when test="@access = 'readwrite'"> + <xsl:text>READWRITE</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: unknown or missing value for </xsl:text> + <xsl:text>@access on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </modifier> + <type> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </type> + <varname> + <xsl:value-of select="@name"/> + </varname> + </fieldsynopsis> + + </xsl:template> + + <xsl:template match="property" mode="fieldsynopsislinked"> + + <fieldsynopsis> + <modifier> + <xsl:choose> + <xsl:when test="@access = 'read'"> + <xsl:text>READ</xsl:text> + </xsl:when> + <xsl:when test="@access = 'write'"> + <xsl:text>WRITE</xsl:text> + </xsl:when> + <xsl:when test="@access = 'readwrite'"> + <xsl:text>READWRITE</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: unknown or missing value for </xsl:text> + <xsl:text>@access on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </modifier> + <type> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </type> + <varname> + <xsl:attribute name="xlink:href"> + <xsl:value-of select="concat('#', ../@name, '.', @name)"/> + </xsl:attribute> + <xsl:value-of select="@name"/> + </varname> + </fieldsynopsis> + + </xsl:template> + + <xsl:template match="property" mode="detail"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: property </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a property of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:apply-templates select="." mode="fieldsynopsis"/> + + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </xsl:template> + + <xsl:template match="tp:property" mode="detail"> + <glossentry> + <glossterm> + <xsl:if test="@name"> + <xsl:value-of select="@name"/> â’ + </xsl:if> + <xsl:value-of select="@type"/> + </glossterm> + <glossdef> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="tp:mapping"> + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <title> + <literal><xsl:value-of select="@name"/></literal> + </title> + <xsl:apply-templates select="tp:docstring"/> + <xsl:if test="string(@array-name) != ''"> + <para> + In bindings that need a separate name, arrays of + <xsl:value-of select="@name"/> should be called + <xsl:value-of select="@array-name"/>. + </para> + </xsl:if> + <section> + <title>Members</title> + <glosslist> + <xsl:apply-templates select="tp:member" mode="description"/> + </glosslist> + </section> + </section> + </xsl:template> + + <xsl:template match="tp:docstring" mode="in-index"/> + + <xsl:template match="tp:simple-type | tp:enum | tp:flags | tp:external-type" + mode="in-index"> + â’ <xsl:value-of select="@type"/> + </xsl:template> + + <xsl:template match="tp:simple-type"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:simple-type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:simple-type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <title> + <literal><xsl:value-of select="@name"/> â’ <xsl:value-of select="@type"/></literal> + </title> + <para> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </para> + </section> + </xsl:template> + + <xsl:template match="tp:external-type"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:external-type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:external-type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <glossentry> + <glossterm> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <xsl:value-of select="@name"/> â’ <xsl:value-of select="@type"/> + </glossterm> + <glossdef>Defined by: <xsl:value-of select="@from"/></glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="tp:struct" mode="in-index"> + â’ ( <xsl:for-each select="tp:member"> + <xsl:value-of select="@type"/> + <xsl:if test="position() != last()">, </xsl:if> + </xsl:for-each> ) + </xsl:template> + + <xsl:template match="tp:mapping" mode="in-index"> + â’ a{ <xsl:for-each select="tp:member"> + <xsl:value-of select="@type"/> + <xsl:if test="position() != last()"> → </xsl:if> + </xsl:for-each> } + </xsl:template> + + <xsl:template match="tp:struct"> + <section> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat('type-', @name)"/> + </xsl:attribute> + <title> + <literal> + <xsl:value-of select="@name"/> + </literal> + </title> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + <xsl:choose> + <xsl:when test="string(@array-name) != ''"> + <para>In bindings that need a separate name, arrays of + <xsl:value-of select="@name"/> should be called + <xsl:value-of select="@array-name"/>.</para> + </xsl:when> + <xsl:otherwise> + <para>Arrays of <xsl:value-of select="@name"/> don't generally + make sense.</para> + </xsl:otherwise> + </xsl:choose> + <classsynopsis> + <ooclass> + <modifier>struct</modifier> + <classname><xsl:value-of select="@name"/></classname> + </ooclass> + <xsl:apply-templates select="tp:member" mode="fieldsynopsis"/> + </classsynopsis> + <glosslist> + <xsl:apply-templates select="tp:member" mode="description"/> + </glosslist> + </section> + </xsl:template> + + <xsl:template match="arg" mode="paramdef"> + <paramdef> + <xsl:call-template name="direction"> + <xsl:with-param name="indirection" select="@direction"/> + </xsl:call-template> + <xsl:text> </xsl:text> + <type> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </type> + <xsl:text> </xsl:text> + <parameter><xsl:value-of select="@name"/></parameter> + </paramdef> + </xsl:template> + + <xsl:template match="arg" mode="paramtable"> + <glossentry> + <glossterm><literal><xsl:value-of select="@name"/></literal></glossterm> + <glossdef> + <para><xsl:apply-templates select="tp:docstring" mode="nopara"/></para> + </glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="method|signal" mode="funcsynopsis"> + <funcsynopsis> + <funcprototype> + <funcdef> + <function> + <xsl:value-of select="@name"/> + </function> + </funcdef> + <xsl:choose> + <xsl:when test="arg"> + <xsl:apply-templates select="arg" mode="paramdef"/> + </xsl:when> + <xsl:otherwise> + <void/> + </xsl:otherwise> + </xsl:choose> + </funcprototype> + </funcsynopsis> + </xsl:template> + + <xsl:template match="method|signal" mode="funcsynopsislinked"> + <funcprototype> + <funcdef> + <function linkend="{concat(parent::interface//@name, '.', @name)}"> + <xsl:value-of select="@name"/> + </function> + </funcdef> + <xsl:choose> + <xsl:when test="arg"> + <xsl:apply-templates select="arg" mode="paramdef"/> + </xsl:when> + <xsl:otherwise> + <void/> + </xsl:otherwise> + </xsl:choose> + </funcprototype> + </xsl:template> + + <xsl:template match="method" mode="detail"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: method </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a method of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:for-each select="arg"> + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no type</xsl:text> + </xsl:message> + </xsl:if> + <xsl:choose> + <xsl:when test="@direction='in'"> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an 'in' arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + </xsl:when> + <xsl:when test="@direction='out'"> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="no"> + <xsl:text>INFO: an 'out' arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has direction neither 'in' nor 'out'</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + + <refsection> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat(../@name, concat('.', @name))"/> + </xsl:attribute> + <title> + <literal><xsl:value-of select="concat(../@name, concat('.', @name))"/></literal> + </title> + <xsl:apply-templates select="." mode="funcsynopsis"/> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + + <xsl:if test="arg"> + <glosslist> + <xsl:apply-templates select="arg" mode="paramtable"/> + </glosslist> + </xsl:if> + + <xsl:if test="tp:possible-errors"> + <formalpara> + <title>Possible errors</title> + <para> + <glosslist> + <xsl:apply-templates select="tp:possible-errors/tp:error"/> + </glosslist> + </para> + </formalpara> + </xsl:if> + </refsection> + </xsl:template> + + <xsl:template name="tp-type"> + <xsl:param name="tp-type"/> + <xsl:param name="type"/> + + <xsl:variable name="single-type"> + <xsl:choose> + <xsl:when test="contains($tp-type, '[]')"> + <xsl:value-of select="substring-before($tp-type, '[]')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tp-type"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="type-of-tp-type"> + <xsl:if test="contains($tp-type, '[]')"> + <!-- one 'a', plus one for each [ after the [], and delete all ] --> + <xsl:value-of select="concat('a', + translate(substring-after($tp-type, '[]'), '[]', 'a'))"/> + </xsl:if> + + <xsl:choose> + <xsl:when test="//tp:simple-type[@name=$single-type]"> + <xsl:value-of select="string(//tp:simple-type[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:struct[@name=$single-type]"> + <xsl:text>(</xsl:text> + <xsl:for-each select="//tp:struct[@name=$single-type]/tp:member"> + <xsl:value-of select="@type"/> + </xsl:for-each> + <xsl:text>)</xsl:text> + </xsl:when> + <xsl:when test="//tp:enum[@name=$single-type]"> + <xsl:value-of select="string(//tp:enum[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:flags[@name=$single-type]"> + <xsl:value-of select="string(//tp:flags[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:mapping[@name=$single-type]"> + <xsl:text>a{</xsl:text> + <xsl:for-each select="//tp:mapping[@name=$single-type]/tp:member"> + <xsl:value-of select="@type"/> + </xsl:for-each> + <xsl:text>}</xsl:text> + </xsl:when> + <xsl:when test="//tp:external-type[@name=$single-type]"> + <xsl:value-of select="string(//tp:external-type[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: Unable to find type '</xsl:text> + <xsl:value-of select="$tp-type"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:if test="string($type) != '' and + string($type-of-tp-type) != string($type)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: tp:type '</xsl:text> + <xsl:value-of select="$tp-type"/> + <xsl:text>' has D-Bus type '</xsl:text> + <xsl:value-of select="$type-of-tp-type"/> + <xsl:text>' but has been used with type='</xsl:text> + <xsl:value-of select="$type"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:if> + + <link linkend="type-{$single-type}"> + <literal><xsl:value-of select="concat('type-', $single-type)"/></literal> + </link> + + </xsl:template> + + <xsl:template name="parenthesized-tp-type"> + <xsl:if test="@tp:type"> + <xsl:text> (</xsl:text> + <xsl:call-template name="tp-type"> + <xsl:with-param name="tp-type" select="@tp:type"/> + <xsl:with-param name="type" select="@type"/> + </xsl:call-template> + <xsl:text>)</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="tp:member" mode="fieldsynopsis"> + <xsl:variable name="type"> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:variable> + <fieldsynopsis> + <type><xsl:value-of select="normalize-space($type)"/></type> + <varname><xsl:value-of select="@name"/></varname> + </fieldsynopsis> + </xsl:template> + + <xsl:template match="tp:member" mode="description"> + <glossentry> + <glossterm> + <varname><xsl:value-of select="@name"/></varname> + </glossterm> + <glossdef> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring" /> + </xsl:when> + <xsl:otherwise> + <!-- emphasize --> + (undocumented) + </xsl:otherwise> + </xsl:choose> + </glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="tp:possible-errors/tp:error"> + <glossentry> + <glossterm> + <xsl:value-of select="@name"/> + </glossterm> + <glossdef> + <xsl:variable name="name" select="@name"/> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring"/> + </xsl:when> + <xsl:when test="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"> + <xsl:apply-templates select="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"/> <!-- TODO: emphasize -->(generic description) + </xsl:when> + <xsl:otherwise> + (Undocumented.) + </xsl:otherwise> + </xsl:choose> + </glossdef> + </glossentry> + </xsl:template> + + <xsl:template match="signal" mode="detail"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: signal </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a signal of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:for-each select="arg"> + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no type</xsl:text> + </xsl:message> + </xsl:if> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + <xsl:choose> + <xsl:when test="not(@direction)"/> + <xsl:when test="@direction='in'"/> + <!-- This doesn't work with the DTD (see comment in DTD) + <xsl:when test="@direction='in'"> + <xsl:message terminate="no"> + <xsl:text>INFO: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has unnecessary direction 'in'</xsl:text> + </xsl:message> + </xsl:when> + --> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has direction other than 'in'</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + + <refsection> + <xsl:attribute name="xml:id"> + <xsl:value-of select="concat(../@name, concat('.', @name))"/> + </xsl:attribute> + <title> + <literal><xsl:value-of select="concat(../@name, concat('.', @name))"/></literal> + </title> + <xsl:apply-templates select="." mode="funcsynopsis"/> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + + <xsl:if test="arg"> + <glosslist> + <xsl:apply-templates select="arg" mode="paramtable"/> + </glosslist> + </xsl:if> + </refsection> + </xsl:template> + + <xsl:template match="/tp:spec"> + <book xmlns="http://docbook.org/ns/docbook" version="5.0"> + <bookinfo> + <title><xsl:value-of select="tp:title"/></title> + <xsl:apply-templates select="tp:copyright"/> + <xsl:apply-templates select="tp:license"/> + <xsl:if test="tp:docstring"> + <abstract> + <xsl:apply-templates select="tp:docstring"/> + </abstract> + </xsl:if> + <!-- TODO: Version + <xsl:if test="tp:version"> + <xsl:text> version </xsl:text> + <xsl:value-of select="tp:version"/> + </xsl:if> --> + </bookinfo> + <chapter> + <xsl:attribute name="xml:id">interfaces</xsl:attribute> + <title>Interfaces</title> + <xsl:apply-templates select="//node"/> + </chapter> + <xsl:call-template name="generic-types"/> + <xsl:if test="tp:errors"> + <chapter> + <xsl:attribute name="xml:id">errors</xsl:attribute> + <xsl:apply-templates select="tp:errors"/> + </chapter> + </xsl:if> + </book> + </xsl:template> + + <xsl:template match="node"> + <xsl:apply-templates /> + </xsl:template> + + <xsl:template match="text()"> + <xsl:if test="normalize-space(.) != ''"> + <xsl:message terminate="yes"> + <xsl:text>Stray text: {{{</xsl:text> + <xsl:value-of select="." /> + <xsl:text>}}} </xsl:text> + </xsl:message> + </xsl:if> + </xsl:template> + + <xsl:template match="*"> + <xsl:message terminate="yes"> + <xsl:text>Unrecognised element: {</xsl:text> + <xsl:value-of select="namespace-uri(.)" /> + <xsl:text>}</xsl:text> + <xsl:value-of select="local-name(.)" /> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:template> +</xsl:stylesheet> + +<!-- vim:set sw=2 sts=2 et: --> diff --git a/secret-service/tools/spec-to-introspect.xsl b/secret-service/tools/spec-to-introspect.xsl new file mode 100644 index 0000000..2468237 --- /dev/null +++ b/secret-service/tools/spec-to-introspect.xsl @@ -0,0 +1,144 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + exclude-result-prefixes="tp"> + +<!-- + Telepathy D-Bus Introspection to EggDBus Introspection format translator. + + Copyright 2009 Michael Leupold <lemma@confuego.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 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 St, Fifth Floor, Boston, MA 02110-1301 USA +--> + +<!-- + TODO: + - Enable conversion of dictionary element types (eg. "{ss}") and + struct types (eg. "(sayay)") + - unhandled: tp:simple-type, tp:enum, tp:flags, tp:external-type + - tp:docstring may contain XHTML which this template doesn't handle +--> + + <xsl:include href="resolve-type.xsl"/> + + <!-- main template --> + <xsl:template match="tp:spec"> + <node> + <xsl:apply-templates select="tp:errors"/> + <xsl:apply-templates select="tp:struct"/> + <!-- TODO: <xsl:apply-templates select="tp:mapping"/> --> + <xsl:apply-templates select="node/interface"/> + </node> + </xsl:template> + + <!-- handle most of the D-Bus introspection elements --> + <xsl:template match="interface|annotation|method|signal"> + <xsl:copy> + <xsl:for-each select="@*"> + <xsl:if test="not(starts-with(name(), 'tp:'))"> + <xsl:copy/> + </xsl:if> + </xsl:for-each> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <!-- handle the arg and property D-Bus introspection elements. + They get special handling because they may contain a tp:type + attribute --> + <xsl:template match="arg|property"> + <xsl:copy> + <xsl:for-each select="@*"> + <xsl:if test="not(starts-with(name(), 'tp:'))"> + <xsl:copy/> + </xsl:if> + </xsl:for-each> + <xsl:for-each select="@tp:type"> + <xsl:variable name="type"> + <xsl:call-template name="TpType"> + <xsl:with-param name="type" select="."/> + </xsl:call-template> + </xsl:variable> + <annotation name="org.gtk.EggDBus.Type"> + <xsl:attribute name="value"> + <xsl:value-of select="translate(translate($type, ' ', ''), '
', '')"/> + </xsl:attribute> + </annotation> + </xsl:for-each> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <!-- tp:docstring to org.gtk.EggDBus.DocString --> + <xsl:template match="tp:docstring"> + <annotation name="org.gtk.EggDBus.DocString"> + <xsl:attribute name="value"> + <xsl:value-of select="normalize-space(text())"/> + </xsl:attribute> + </annotation> + </xsl:template> + + <!-- tp:errors to org.gtk.EggDBus.DeclareErrorDomain --> + <xsl:template match="tp:errors"> + <annotation value="Error" name="org.gtk.EggDBus.DeclareErrorDomain"> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:error"/> + </annotation> + </xsl:template> + + <!-- tp:error to org.gtk.EggDBus.ErrorDomain.Member --> + <xsl:template match="tp:error"> + <annotation name="org.gtk.EggDBus.ErrorDomain.Member"> + <xsl:attribute name="value"> + <xsl:value-of select="concat(../@namespace, '.', @name)"/> + </xsl:attribute> + <xsl:apply-templates select="tp:docstring"/> + </annotation> + </xsl:template> + + <!-- tp:struct to org.gtk.EggDBus.DeclareStruct --> + <xsl:template match="tp:struct"> + <annotation name="org.gtk.EggDBus.DeclareStruct"> + <xsl:attribute name="value"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:member"/> + </annotation> + </xsl:template> + + <!-- tp:member to org.gtk.EggDBus.Struct.Member --> + <xsl:template match="tp:member"> + <xsl:variable name="type"> + <xsl:call-template name="ResolveType"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:variable> + <annotation name="org.gtk.EggDBus.Struct.Member"> + <xsl:attribute name="value"> + <xsl:value-of select="concat(normalize-space($type), ':', @name)"/> + </xsl:attribute> + <xsl:apply-templates select="tp:docstring"/> + </annotation> + </xsl:template> + + <xsl:template match="text()"/> + + <xsl:output method="xml" indent="yes" encoding="UTF-8" + omit-xml-declaration="no" + doctype-system="http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" + doctype-public="-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"/> + +</xsl:stylesheet> diff --git a/systemtray/ChangeLog b/systemtray/ChangeLog new file mode 100644 index 0000000..9487095 --- /dev/null +++ b/systemtray/ChangeLog @@ -0,0 +1,10 @@ +2009-01-10 Vincent Untz <vuntz@gnome.org> + + * systemtray-spec.xml: add _NET_SYSTEM_TRAY_VISUAL and a description of + visual and background pixmap handling.. + See http://lists.freedesktop.org/archives/xdg/2009-January/010122.html + +2004-11-30 Mark McLoughlin <mark@skynet.ie> + + * systemtray-spec.xml: add _NET_SYSTEM_TRAY_ORIENTATION. + diff --git a/systemtray/systemtray-spec.xml b/systemtray/systemtray-spec.xml new file mode 100644 index 0000000..669f3d0 --- /dev/null +++ b/systemtray/systemtray-spec.xml @@ -0,0 +1,444 @@ +<?xml version="1.0"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +]> +<article id="index"> + <articleinfo> + <title>System Tray Protocol Specification</title> + <releaseinfo>Version 0.3</releaseinfo> + <date>10 January 2009</date> + <authorgroup> + <author> + <firstname>Havoc</firstname> + <surname>Pennington</surname> + <affiliation> + <address> + <email>hp@redhat.com</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="overview"> + <title>Overview</title> + <para> + The "system tray" is an application running on a given X screen + that can display small icons provided by running + applications. Windows XP calls this feature the "notification area." + <footnote><para>According to the MSDN documentation for the + <literal>Shell_NotifyIcon()</literal> function, + "The taskbar notification area is sometimes erroneously called + the 'tray.'" So presumably "notification area" is the official + term on Windows. Parts of the docs also call it the "status + area."</para></footnote> Inspired by KDE, this specification + uses the term "system tray." + </para> + <para> + From a UI standpoint, the system tray is normally used for + transient icons that indicate some special state, while + full-blown "applets" are used for permanent dock/panel + features. For example, a system tray icon might appear to tell + the user that they have new mail, or have an incoming instant + message, or something along those lines. + </para> + <para> + The basic idea is that creating an icon in the notification + area is less annoying than popping up a dialog. However it's + also harder to notice, so Windows XP adds a feature allowing + tray icons to pop up small message balloons. (Users can disable + these via a hidden registry setting.) This specification + also supports the balloon feature. + </para> + </sect1> + + <sect1 id="definitions"> + <title>Definitions</title> + <variablelist> + <varlistentry> + <term>System tray</term> + <listitem> + <para> + The system tray is an X client which owns a special + manager selection on a given screen and provides + container windows. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Selection owner window</term> + <listitem> + <para> + The selection owner window is the window belonging to the + System Tray that owns the manager selection (as in + <literal>XGetSelectionOwner()</literal>/<literal>XSetSelectionOwner()</literal>. + Note that this probably is not the same window that's used + to contain the system tray icons. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Tray icon</term> + <listitem> + <para> + The tray icon is a window to be embedded in the + system tray. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect1> + + <sect1 id="locating"> + <title>Locating the system tray</title> + <para> + On startup, the system tray must acquire a manager selection + called <literal>_NET_SYSTEM_TRAY_Sn</literal>, replacing + <literal>n</literal> with the screen number the tray wants to + use. The conventions for manager selections are defined in the + ICCCM. + </para> + <para> + Because the selection owner window should be destroyed when the + manager selection is lost, normally the selection owner window + will not be the same as any of the user-visible windows provided + by the system tray. + </para> + <para> + A system tray that fails to get the selection or loses the + selection should assume that another system tray is running, + and let the selection owner handle tray icons. + </para> + <para> + An application wishing to provide an icon to the system tray + should first locate the system tray by requesting the owner + window of the manager selection. If the manager selection has no + owner, clients may use the method described in the ICCCM + (watching for a <literal>MANAGER</literal> client message) to be + notified when a system tray appears. + </para> + </sect1> + + <sect1 id="messages"> + <title>Opcode messages</title> + <para> + Tray icons can send "opcodes" to + the system tray. These are X client messages, sent with + <literal>NoEventMask</literal>, a + <literal>message_type</literal> of + <literal>_NET_SYSTEM_TRAY_OPCODE</literal>, and format 32. + The first data field in the message is a timestamp (the stamp + of the current event, if available, otherwise CurrentTime). + The second data field is an integer indicating the op code + of the message: + <programlisting> +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 + </programlisting> + The content remaining three data fields depends on the type of + message being sent. If they are unused by a particular + message, they should always be set to 0. + </para> + <para> + Here is an example of how to send a client message: + <programlisting><!-- +-->#include <X11/Xlib.h> + +void send_message( + Display* dpy, /* display */ + Window w, /* sender (tray icon window) */ + long message, /* message opcode */ + long data1 /* message data 1 */ + long data2 /* message data 2 */ + long data3 /* message data 3 */ +){ + XEvent ev; + + memset(&ev, 0, sizeof(ev)); + ev.xclient.type = ClientMessage; + ev.xclient.window = w; + ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False ); + ev.xclient.format = 32; + ev.xclient.data.l[0] = x_time; + ev.xclient.data.l[1] = message; + ev.xclient.data.l[2] = data1; + ev.xclient.data.l[3] = data2; + ev.xclient.data.l[4] = data3; + + trap_errors(); + XSendEvent(dpy, w, False, NoEventMask, &ev); + XSync(dpy, False); + if (untrap_errors()) { + /* Handle failure */ + } +}<!-- + --></programlisting> + + </para> + + </sect1> + + <sect1 id="docking"> + <title>Docking a tray icon</title> + <para> + A tray icon must support the "client" or "plug" side of the + XEMBED specification. XEMBED is a protocol for cross-toolkit + widget embedding. + </para> + <para> + To begin the docking process, the tray icon application sends + a client message event to the manager selection owner window, + as described in <xref linkend="messages"/>. This event + should contain the <literal>SYSTEM_TRAY_REQUEST_DOCK</literal> + opcode, <literal>xclient.data.l[2]</literal> should contain + the X window ID of the tray icon to be docked. + </para> + <para> + At this point the "embedding life cycle" explained in the XEMBED + specification begins. The XEMBED specification explains how the + embedding application will interact with the embedded tray + icon, and how the embedder/embedded relationship may be ended. + </para> + <para> + Tray icons may be assigned any size by the system tray, and + should do their best to cope with any size effectively. + </para> + </sect1> + + <sect1 id="visuals"> + <title>Visual and background pixmap handling</title> + <para> + If the _NET_SYSTEM_TRAY_VISUAL property (see below) is present, + tray icon windows should be created using that visual. If the + property is not present, then tray icon windows should be + created using the default visual of the screen. + </para> + <para> + Historically, to allow the appearance of icons with transparent + backgrounds on servers that did not support visuals with an + alpha channel or the Composite extension, a convention was + adopted where a background pixmap was set on the XEMBED embedder + window, aligned properly to match the contents of the embedder + window's parent, the tray icon window was set to have a + background of ParentRelative, and drawing of the icon done on + top of this background. + </para> + <para> + Setting the background of a window to ParentRelative when the + depth of the window does not match the depth of the window's + parent, or reparenting a window with a ParentRelative + background into a parent with a non-matching depth produces a + BadMatch error, so the embedder window must be created to match + the visual of the tray icon window, even if the tray icon window + does not have the visual provided in _NET_SYSTEM_TRAY_VISUAL. If + convenient, the tray manager may set an appropriate background + pixmap on the embedder window to provide the appearance of + transparency. However, the preferred method of transparency is + to use a visual with an alpha channel in _NET_SYSTEM_TRAY_VISUAL. + </para> + </sect1> + + <sect1 id="hints"> + <title>Tray icon hints</title> + <para> + Tray icons should set the following hints to help the system + tray provide a nice user interface. The name and icon hints + are used if the system tray needs to refer to a tray icon; + for example, the system tray may present a list of tray + icons and let the user reorder them or change their properties. + </para> + + <sect2><title>_NET_WM_NAME</title> + <programlisting><![CDATA[ +_NET_WM_NAME, UTF8_STRING +]]></programlisting> + <para> + This hint should be set as it would be for a normal toplevel + window, as defined in the Extended Window Manager Hints + Specification (EWMH). The hint MUST be in UTF-8 encoding. It + provides a human-readable, localized name for the tray icon. + </para> + </sect2> + + <sect2><title>WM_CLASS</title> + <programlisting><![CDATA[ +WM_CLASS, STRING +]]></programlisting> + <para> + This hint should be set as it would be for a normal toplevel + window, as defined in the ICCCM. The system tray can use it + to distinguish different kinds of tray icon. This is useful + for example if the system tray wants to save and restore the + positions of the icons in the tray. + </para> + </sect2> + + <sect2> + <title>_NET_WM_ICON</title> + <programlisting><![CDATA[ +_NET_WM_ICON CARDINAL[][2+n]/32 +]]></programlisting> + <para> + This hint should be set as it would be for a normal toplevel + window, as defined in the Extended Window Manager Hints + Specification (EWMH). See that specification for the format + of the icon data. + </para> + </sect2> + + </sect1> + + <sect1 id="manager-hints"> + <title>Tray manager hints</title> + <para> +The tray manager should set the following hints on the selection +owner window. + </para> + + <sect2> + <title>_NET_SYSTEM_TRAY_ORIENTATION</title> + <programlisting><![CDATA[ +_NET_SYSTEM_TRAY_ORIENTATION orientation CARDINAL/32 +]]> + #define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 + #define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1 + </programlisting> + + <para> +The property should be set by the tray manager to indicate the current +orientation of the tray. Tray icons may use this hint in order to +maintain the icon's aspect ratio and also as an indication of how the +icon contents should be laid out. + </para> + + </sect2> + + <sect2> + <title>_NET_SYSTEM_TRAY_VISUAL</title> + <programlisting><![CDATA[ +_NET_SYSTEM_TRAY_VISUAL visual_id VISUALID/32 +]]> + </programlisting> + + <para> +The property should be set by the tray manager to indicate the preferred +visual for icon windows. To avoid ambiguity about the colormap to use +this visual must either be the default visual for the screen or it +must be a TrueColor visual. If this property is set to a visual with +an alpha channel, the tray manager must use the Composite extension to +composite the icon against the background using PictOpOver. + </para> + + </sect2> + </sect1> + + <sect1 id="balloon"> + <title>Balloon messages</title> + <para> + Tray icons may ask the system tray to display a balloon message + to the user. The system tray coordinates balloon messages + to ensure that they have a consistent look-and-feel, and to + avoid displaying multiple balloon messages at once. + </para> + <para> + A balloon message is a short text message to be displayed to + the user. The message may have a timeout; if so, the message + will be taken down after the timeout expires. Messages are + displayed in a queue, as only one can appear at a time; + if a message has a timeout, the timer begins when the message + is first displayed. Users may be allowed to close messages at + any time, and may be allowed to disable all message display. + </para> + <para> + System trays may display balloon messages in any way they + see fit; for example, instead of popping up a balloon, they + could choose to put a special indicator around icons with + pending messages, and display the message on mouseover. + </para> + <para> + Balloon messages are sent from the tray icon to the system tray + selection owner window as a series of client messages. The first + client message is an opcode message, and contains the usual timestamp, + and the op code <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal>. + <literal>xclient.data.l[2]</literal> contains the timeout in + thousandths of a second or zero for infinite timeout, + <literal>xclient.data.l[3]</literal> contains the length + of the message string in bytes, not including any nul bytes, and + <literal>xclient.data.l[4]</literal> contains an ID number + for the message. This ID number should never be reused by + the same tray icon. (The simplest way to generate the ID number + is to increment it with each message sent.) + </para> + <para> + Following the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal> + op code, the tray icon should send a series of client messages + with a <literal>message_type</literal> of + <literal>_NET_SYSTEM_TRAY_MESSAGE_DATA</literal>. These client + messages must have their <literal>window</literal> field set + to the window ID of the tray icon, and have a + <literal>format</literal> of 8. + </para> + <para> + Each <literal>_NET_SYSTEM_TRAY_MESSAGE_DATA</literal> message + contains 20 bytes of the message string, up to the length given + in the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal> opcode. + If the message string is zero-length, then no messages need be + sent beyond the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal>. + A terminating nul byte should never be sent. + </para> + <para> + System trays may receive portions of messages from several + tray icons at once, so are required to reassemble the messages + based on the window ID of the tray icon. + </para> + <para> + The tray icon may wish to cancel a previously-sent balloon + message. To do so, it sends a + <literal>SYSTEM_TRAY_CANCEL_MESSAGE</literal> opcode with + <literal>data.l[2]</literal> set to the ID number of the message + to cancel. + </para> + </sect1> + + <appendix id="changes"> + <title>Change history</title> + <formalpara> + <title>Version 0.3, 10 January 2009, Owen Taylor</title> + <para> + <itemizedlist> + <listitem> + <para> + Added the _NET_SYSTEM_TRAY_VISUAL hint and a + description of visual and background pixmap handling. + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + <formalpara> + <title>Version 0.2, 23 November 2004, Mark McLoughlin</title> + <para> + <itemizedlist> + <listitem> + <para> + Added the _NET_SYSTEM_TRAY_ORIENTATION hint. + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + <formalpara> + <title>Version 0.1, 20 April 2002, Havoc Pennington</title> + <para> + <itemizedlist> + <listitem> + <para> + Created initial draft. + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + </appendix> +</article> diff --git a/trash/trashspec.html b/trash/trashspec.html new file mode 100644 index 0000000..0950084 --- /dev/null +++ b/trash/trashspec.html @@ -0,0 +1,457 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> + <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=koi8-r"> + <TITLE>Trash specification</TITLE> + <META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.0 (Linux)"> + <META NAME="AUTHOR" CONTENT="Mikhail Ramendik"> + <STYLE> + <!-- + P.sdfootnote { margin-left: 0.5cm; text-indent: -0.5cm; margin-bottom: 0cm; font-size: 80% } + A.sdfootnoteanc { font-size: 57% } + --> + </STYLE> +</HEAD> +<BODY LANG="en-US" DIR="LTR"> +<H1>The FreeDesktop.org Trash specification</H1> +<H3>Written by Mikhail Ramendik <<A HREF="mailto:mr@ramendik.ru">mr@ramendik.ru</A>></H3> +<H3>Content by David Faure <<A HREF="mailto:faure@kde.org">faure@kde.org</A>>, +Alexander Larsson <<A HREF="mailto:alexl@redhat.com">alexl@redhat.com</A>> +and others on the FreeDesktop.org mailing list</H3> +<H3>Version 0.7</H3> +<H2>Abstract</H2> +<P>The purpose of this Specification is to provide a common way in +which all “Trash can” implementations should store, list, +and undelete trashed files. By complying with this Specification, +various Trash implementations will be able to work with the same +devices and use the same Trash storage. For example, if one +implementation sends a file into the Trash can, another will be able +to list it, undelete it, or clear it from the Trash.</P> +<H2>Introduction</H2> +<P>An ability to recover accidentally deleted files has become the de +facto standard for today's desktop user experience. +</P> +<P>Users do not expect that anything they delete is permanently gone. +Instead, they are used to a “Trash can” metaphor. A +deleted document ends up in a “Trash can”, and stays +there at least for some time — until the can is manually or +automatically cleaned. +</P> +<P>This system has its own problems. Notably, cleaning disk space +becomes a two-step operation — delete files and empty trash; +this can lead to confusion for inexperienced users (“what's +taking up my space?!”). Also, it is not easy to adapt the +system to a multiuser environment. Besides, there is a potential for +abuse by uneducated users — anecdotal evidence says they +sometimes store important documents in the Trash can, and lose them +when it gets cleaned!</P> +<P>However, the benefits of this system are so great, and the user +expectation for it so high, that it definitely should be implemented +on a free desktop system. And in fact, several implementations +already exist — some as command line utilities, some as +preloaded libraries, and some as parts of major desktop environments. +For example, both Gnome and KDE have their own trash mechanisms.</P> +<P>This Specification is to provide a common way in which all Trash +can implementations should store trashed files. By complying with +this Specification, various Trash implementations will be able to +work with the same devices and use the same Trash storage. +</P> +<P>This is important, at least, for shared network resources, +removable devices, and in cases when different implementations are +used on the same machine at different moments (i.e. some users prefer +Gnome, others prefer KDE, and yet others are command-line fans).</P> +<H2>Scope and limitations</H2> +<P>This Specification only describes the Trash storage. It does <B>not</B> +limit the ways in which the actual implementations should operate, as +long as they use the same Trash storage. Command line utilities, +desktop-integrated solutions and preloaded libraries can work with +this specification. <A CLASS="sdfootnoteanc" NAME="sdfootnote1anc" HREF="#sdfootnote1sym"><SUP>1</SUP></A></P> +<P>This Specification is geared towards the Unix file system tree +approach. However, with slight modifications, it can easily be used +with another kind of file system tree (for example, with drive +letters). +</P> +<P>A multi-user environment, where users have specific numeric +identifiers, is essential for this Specification. +</P> +<P>File systems and logon systems can be +case-sensitive or non-case-sensitive; therefore, systems should +generally not allow user names that differ only in case.</P> +<H2>Definitions</H2> +<P>Trash, or Trash can — the storage of files that were trashed +(“deleted”) by the user. These files can be listed, +undeleted, or cleaned from the trash can.</P> +<P>Trashing — a “delete” operation in which files +are transferred into the Trash can.</P> +<P>Erasing — an operation in which files (possibly already in +the Trash can) are removed (unlinked) from the file system. An erased +file is generally considered to be non-recoverable; the space used by +this file is freed. [A “shredding” operation, physically +overwriting the data, may or may not accompany an erasing operation; +the question of shredding is beyond the scope of this document].</P> +<P>Original location — the name and location that a file +(currently in the trash) had prior to getting trashed.</P> +<P>Original filename — the name that a file (currently in the +trash) had prior to getting trashed. +</P> +<P>Top directory , $topdir — the directory where a file system +is mounted. “/” is the top directory for the root file +system, but not for the other mounted file systems. For example, +separate FSes can be mounted on “/home”, “/mnt/flash”, +etc. In this text, the designation “$topdir” is used for +“any top directory”.</P> +<P>User identifier , $uid — the numeric user identifier for a +user. $uid is used here as “the numeric user identifier of the +user who is currently logged on”.</P> +<P>Trash directory — a directory where trashed files, as well +as the information on their original name/location and time of +trashing, are stored. There may be several trash directories on one +system; this Specification defines their location and contents. In +this text, the designation “$trash” is used for “any +trash directory”.</P> +<P>“Home trash” directory — a user's main trash +directory. Its name and location is defined in this document.</P> +<P>The key words "MUST", "MUST NOT", "REQUIRED", +"SHALL", "SHALL NOT", "SHOULD", "SHOULD +NOT", "RECOMMENDED", "MAY", and "OPTIONAL" +in this document are to be interpreted as described in <A HREF="http://www.faqs.org/rfcs/rfc2119.html">RFC +2119</A>.</P> +<H2>Trash directories</H2> +<P>A system can have one or more trash directories. The contents of +any trash directory are to be compliant with the same standard, +described below.</P> +<P>For every user<A CLASS="sdfootnoteanc" NAME="sdfootnote2anc" HREF="#sdfootnote2sym"><SUP>2</SUP></A> +a “home trash” directory MUST be available<A CLASS="sdfootnoteanc" NAME="sdfootnote3anc" HREF="#sdfootnote3sym"><SUP>3</SUP></A>. +Its name and location are $XDG_DATA_HOME/Trash ; $XDG_DATA_HOME is +the base directory for user-specific data, as defined in the <A HREF="http://www.freedesktop.org/Standards/basedir-spec">Desktop +Base Directory Specification</A> . +</P> +<P>The “home trash” should function as the user's main +trash directory. Files that the user trashes from the same file +system (device/partition) should be stored here (see the next section +for the storage details). A “home trash” directory SHOULD +be automatically created for any new user. If this directory is +needed for a trashing operation but does not exist, the +implementation SHOULD automatically create it, without any warnings +or delays.</P> +<P>The implementation MAY also support trashing files from the rest +of the system (including other partitions, shared network resources, +and removable devices) into the “home trash” directory . +This is a “failsafe” method: trashing works for all file +locations, the user can not fill up any space except the home +directory, and as other users generally do not have access to it, no +security issues arise.</P> +<P>However, this solution leads to costly file copying (between +partitions, over the network, from a removable device, etc.) A delay +instead of a quick “delete” operation can be unpleasant +to users.</P> +<P>An implementation may choose not to support trashing in some of +these cases (notably on network resources and removable devices). +This is what some well known operating systems do.</P> +<P>It may also choose to provide trashing in the “top +directories” of some or all mounted resources. This trashing is +done in two ways, described below as (1) and (2). +</P> +<P>(1) An administrator can create an $topdir/.Trash directory. The +permissions on this directories should permit all users who can trash +files at all to write in it.; and the “sticky bit” in the +permissions must be set, if the file system supports it. +</P> +<P>When trashing a file from a non-home partition/device<A CLASS="sdfootnoteanc" NAME="sdfootnote4anc" HREF="#sdfootnote4sym"><SUP>4</SUP></A> +, an implementation (if it supports trashing in top directories) MUST +check for the presence of $topdir/.Trash.</P> +<P>When preparing a list of all trashed files (i.e. to show to the +user), an implementation also MUST check for .Trash in all top +directories that are known to it.</P> +<P>If this directory is present, the implementation MUST, by default, +check for the “sticky bit”. (It MAY provide a way for the +administrator, <I>and only the administrator</I>, to disable this +checking for a particular top directory, in order to support file +systems that do not have the “sticky bit”).</P> +<P>The implementation also MUST check that +this directory is not a symbolic link. +</P> +<P>If any of these checks fail, the +implementation MUST NOT use this directory for either trashing or +undeleting files, even is an appropriate $uid directory (see below) +already exists in it. Besides, the implementation SHOULD report the +failed check to the administrator, and MAY also report it to the +user.</P> +<P>The following paragraph applies ONLY to +the case when the implementation supports trashing in the top +directory, and a $topdir/.Trash exists and has passed the checks:</P> +<P STYLE="margin-left: 2cm">If the directory exists and passes the +checks, a subdirectory of the $topdir/.Trash directory is to be used +as the user's trash directory for this partition/device. The name of +this subdirectory is the numeric identifier of the current user +($topdir/.Trash/$uid). When trashing a file, if this directory does +not exist for the current user, the implementation MUST immediately +create it, without any warnings or delays for the user.</P> +<P>(2) If an $topdir/.Trash directory is +absent, an $topdir/.Trash-$uid directory is to be used as the user's +trash directory for this device/partition. $uid is the user's numeric +identifier.</P> +<P>The following paragraph applies ONLY to +the case when the implementation supports trashing in the top +directory, and a $topdir/.Trash does not exist or has not passed the +checks:</P> +<P STYLE="margin-left: 2cm">When trashing a file, +if an $topdir/.Trash-$uid directory does not exist, the +implementation MUST immediately create it, without any warnings or +delays for the user.</P> +<P>When trashing a file, if this directory +does not exist for the current user, the implementation MUST +immediately create it, without any warnings or delays for the user.</P> +<P><B>Notes.</B> If an implementation provides trashing in top +directories at all, it MUST support both (1) and (2). +</P> +<P>If an implementation does NOT provide such trashing, and does +provide the user with some interface to view and/or undelete trashed +files, it SHOULD make a “best effort” to show files +trashed in top directories (by both methods) to the user, among other +trashed files or in a clearly accessible separate way.</P> +<P>When trashing a file, if the method (1) fails at any point — +i.e. the $topdir/.Trash directory does not exist, or it fails the +checks, or the system refuses to create an $uid directory in it — +the implementation MUST, by default, fall back to method (2), +described below. Except for the case when $topdir/.Trash fails the +checks, the fallback must be immediate, without any warnings or +delays. The implementation MAY, however, a way for the administrator +to disable (2) completely.</P> +<P>If both (1) and (2) fail (i.e. no +$topdir/.Trash directory exists, and an attempt to create +$topdir/.Trash-$uid fails), the implementation MUST either trash the +file into the user's “home trash” or refuse to trash it. +The choice between these options can be pre-determined, or it can +depend on the particular situation (i.e. No trashing of very large +files). However, if an implementation refuses to trash a file after a +user action that generally causes trashing, it MUST clearly warn the +user about this, and request confirmation for the action.</P> +<P>For showing trashed files, implementations SHOULD support (1) and +(2) at the same time (i.e. if both $topdir/.Trash/$uid and +$topdir/.Trash-$uid are present, it should list trashed files from +both of them).</P> +<H2>Contents of a trash directory</H2> +<P>The previous section has described the location of trash +directories. This section concerns the contents of any trash +directory (including the “home trash” directory). This +trash directory will be named “$trash” here.</P> +<P>A trash directory contains two subdirectories, named <B>info </B>and +<B>files</B>.</P> +<P>The <B>$trash/files</B> directory contains the files and +directories that were trashed. When a file or directory is trashed, +it MUST be moved into this directory<A CLASS="sdfootnoteanc" NAME="sdfootnote5anc" HREF="#sdfootnote5sym"><SUP>5</SUP></A> +. The names of files in this directory are to be determined by the +implementation; the only limitation is that they must be unique +within the directory. <I>Even if a file with the same name and +location gets trashed many times, each subsequent trashing must not +overwrite a previous copy. </I>The access rights, access time, +modification time and extended attributes (if any) for a +file/directory in $trash/files SHOULD be the same as the +file/directory had before getting trashed.</P> +<P><B>IMPORTANT NOTE. While an implementation may choose to base +filenames in the $trash/files directory on the original filenames, +this is never to be taken for granted<A CLASS="sdfootnoteanc" NAME="sdfootnote6anc" HREF="#sdfootnote6sym"><SUP>6</SUP></A>. +A filename in the $trash/files directory MUST NEVER be used to +recover the original filename; use the info file (see below) for +that. </B>(If an info file corresponding to a file/directory in +$trash/files is not available, this is an emergency case, and MUST be +clearly presented as such to the user or to the system +administrator). +</P> +<P>The <B>$trash/info </B>directory contains an “information +file” for every file and directory in $trash/files. This file +MUST have exactly the same name as the file or directory in +$trash/files, plus the extension “.trashinfo”<A CLASS="sdfootnoteanc" NAME="sdfootnote7anc" HREF="#sdfootnote7sym"><SUP>7</SUP></A>. +</P> +<P>The format of this file is similar to the format of a desktop +entry file, as described in the <A HREF="http://www.freedesktop.org/Standards/desktop-entry-spec">Desktop +Entry Specification</A> . Its first line must be [Trash Info]. +</P> +<P>It also must have two lines that are +key/value pairs as described in the Desktop Entry Specification:</P> +<UL> + <LI><P>The key “Path” + contains the original location of the file/directory, as either an + absolute pathname (starting with the slash character “/”) + or a relative pathname (starting with any other character). A + relative pathname is to be from the directory in which the trash + directory resides (i.e., from $XDG_DATA_HOME for the “home + trash” directory); it MUST not include a “..” + directory, and for files not “under” that directory, + absolute pathnames must be used. The system SHOULD only support + absolute pathnames in the “home trash” directory, not in + the directories under $topdir. + </P> + <P>The value type for this key is + “string”; it should store the file name as the + sequence of bytes produced by the file system, with characters escaped + as in URLs (as defined by <A HREF="http://www.faqs.org/rfcs/rfc2396.html">RFC +2396</A>, section 2).</P> + <LI><P>The key “DeletionDate” contains + the date and time when the file/directory was trashed. The date and + time are to be in the YYYY-MM-DDThh:mm:ss + format (see <A HREF="http://www.faqs.org/rfcs/rfc3339.html">RFC + 3339</A>). The time zone should be the user's (or + filesystem's) local time. The value type for this key is “string”.</P> +</UL> +<P>Example:</P> +<PRE>[Trash Info] +Path=foo/bar/meow.bow-wow +DeletionDate=20040831T22:32:08</PRE><P> +The implementation MUST ignore any other lines in this file, except +the first line (must be [Trash Info]) and these two key/value pairs. +If a string that starts with “Path=” or “DeletionDate=” +occurs several times, the first occurence is to be used.<A CLASS="sdfootnoteanc" NAME="sdfootnote8anc" HREF="#sdfootnote8sym"><SUP>8</SUP></A></P> +<P>Note that $trash/info has no subdirectories. For a directory in +$trash/files, only an information file for its own name is needed. +This is because, when a subdirectory gets trashed, it must be moved +to $trash/files with its entire contents. The names of the files and +directories within the directory MUST NOT be altered; the +implementation also SHOULD preserve the access and modification time +for them.</P> +<P>When trashing a file or directory, the implementation MUST create +the corresponding file in $trash/info first. When trashing a file or +directory, the implementation MUST create thecorresponding file in +$trash/info first. Moreover, it MUST try to do this in an atomic +fashion, so that if two processes try trash files with the same +filename this will result in two different trash files. On Unix-line +systems this is done by generating a filename, and then opening with +O_EXCL. If that succeeds the creation was atomic (at least on the +same machine), if it fails you need to pick another filename.</P> +<H2>Implementation notes</H2> +<P>The names of the files/directories in $trash/info SHOULD be +somehow related to original file names. This can help manual recovery +in emergency cases (for example, if the corresponding info file is +lost).</P> +<P>When trashing a file or directory, the implementation should check +whether the user has the necessary permissions to delete it, before +starting the trashing operation itself.</P> +<P>When copying, rather than moving, a file into the trash (i.e. When +trashing to the “home trash” from a different partition), +exact preservation of permissions might be impossible. Notably, a +file.directory that was owned by another user will now be owned by +this user (changing owners is usually only available to root). This +should not cause the trashing operation to fail.</P> +<P>In this same situation, setting the permissions should be done +<I>after</I> writing the copied file, as they may make it +unwriteable..</P> +<P>A trashing operation might be refused because of insufficient +permissions, even when the user does have the right to delete a file +or directory. This may happen when the user has the right to delete a +file/directory, but not to read it (or, in the case of a directory, +to list it). In this case, the best solution is probably to warn the +user, offering options to delete the file/directory or leave it +alone.</P> +<P>Automatic trash cleaning may, and probably eventually should, be +implemented. But the implementation should be somehow known to the +user.</P> +<P>If a directory was trashed in its entirety, it is easiest to +undelete it or remove it from the trash only in its entirety as well, +not as separate files. The user might not have the permissions to +delete some files in it even while he does have the permission to +delete the directory!</P> +<P><B>Important note on scope</B>. This specification currently does +NOT define trashing on remote machines where multiuser permissions +are implemented but the numeric user ID is not supported, like FTP +sites and CIFS shares. In systems implementing this specification, +trashing of files from such machines is to be done only to the user's +home trash directory (if at all). A future version may address this +limitation.</P> +<H2>Administrativia</H2> +<H3>Status of this document</H3> +<P>This document is, at this moment, only a draft. It will hopefully +become an official or semi-official FreeDesktop.org specification in +the future.</P> +<P>Date of first public distribution: August 30, 2004. This document +will serve as evidence of prior art for any patent filed after this +date.</P> +<H3>Copyright and License</H3> +<P>Copyright (C) 2004 Mikhail Ramendik , <A HREF="mailto:mr@ramendik.ru">mr@ramendik.ru</A> +. +</P> +<P>The originators of the ideas that are described here did not +object to this copyright. The author is ready to transfer the +copyright to a standards body that would be committed to keeping this +specification, or any successor to it, an open standard.</P> +<P>The license: Use and distribute as you wish. If you make a +modified version and redistribute it, (a) keep the name of the author +and contributors somewhere, and (b) indicate that this is a modified +version.</P> +<P>Implementation under any license at all is explicitly allowed.</P> +<H3>Location</H3> +<P><A HREF="http://www.ramendik.ru/docs/trashspec.html">http://www.ramendik.ru/docs/trashspec.html</A> +. If this document gets hosted by FreeDesktop.org, a link to the page +will still be available at this location.</P> +<P><A HREF="http://www.ramendik.ru/docs/trashspec.0.7.html">http://www.ramendik.ru/docs/trashspec.0.7.html</A> +is the permanent location of this version. +</P> +<H3>Version history</H3> +<P>0.1 “First try”, August 30, 2004. Initial draft. +“Implementation notes” not written as yet.</P> +<P>0.2 August 30, 2004. Updated with feedback by Alexander Larsson +<<A HREF="mailto:alexl@redhat.com">alexl@redhat.com</A>> and by +Dave Cridland <<A HREF="mailto:dave@cridland.net">dave@cridland.net</A>></P> +<P>0.3 September 8, 2004. Changed the name and location of the “home +trash” directory, and introduced the generic term “home +trash”. Changed the trash info file format to a .desktop-like +one. Added directions on creation of info files and copying of +trashed files. Changed user names to user ids. Added implementation +notes. Added a copyright notice.</P> +<P>0.4 September 9, 2004. Changed [Trash entry] to [Trash info] and +fixed some typo's</P> +<P>0.5 September 9, 2004. Changed [Trash info] to [Trash Info]</P> +<P>0.6 October 8, 2004. Corrections by Alexander Larsson +<<A HREF="mailto:alexl@redhat.com">alexl@redhat.com</A>> . Also +added “note on scope”. Cleaned up HTML. Added a link to this +document on the freedesktop.org standards page</P> +<P>0.7 April 12, 2005. Added URL-style encoding for the name of the deleted file, +as implemented in KDE 3.4</P> +<P><BR><BR> +</P> +<DIV ID="sdfootnote1"> + <P CLASS="sdfootnote" STYLE="margin-bottom: 0.5cm"><A CLASS="sdfootnotesym" NAME="sdfootnote1sym" HREF="#sdfootnote1anc">1</A>However, + developers of preloaded libraries should somehow work around the + case when a desktop environment also supporting the Trash + specification is run on top of them. “Double trashing” + and “trashing of the trash” should be avoided.</P> +</DIV> +<DIV ID="sdfootnote2"> + <P CLASS="sdfootnote" STYLE="margin-bottom: 0.5cm"><A CLASS="sdfootnotesym" NAME="sdfootnote2sym" HREF="#sdfootnote2anc">2</A>To + be more precise, for every user who can use the trash facility. In + general, all human users, and possibly some “robotic” + ones like ftp, should be able to use the trash facility. + </P> +</DIV> +<DIV ID="sdfootnote3"> + <P CLASS="sdfootnote" STYLE="margin-bottom: 0.5cm"><A CLASS="sdfootnotesym" NAME="sdfootnote3sym" HREF="#sdfootnote3anc">3</A>Note + the dot in the beginning, and for case sensitive file systems, note + the case.</P> +</DIV> +<DIV ID="sdfootnote4"> + <P CLASS="sdfootnote" STYLE="margin-bottom: 0.5cm"><A CLASS="sdfootnotesym" NAME="sdfootnote4sym" HREF="#sdfootnote4anc">4</A>To + be more precise, from a partition/device different from the one on + which $XDG_DATA_HOME resides. + </P> +</DIV> +<DIV ID="sdfootnote5"> + <P CLASS="sdfootnote" STYLE="margin-bottom: 0.5cm"><A CLASS="sdfootnotesym" NAME="sdfootnote5sym" HREF="#sdfootnote5anc">5</A>“$trash/files/”, + <B>not </B>into “$trash/” as in many existing + implementations!</P> +</DIV> +<DIV ID="sdfootnote6"> + <P CLASS="sdfootnote" STYLE="margin-bottom: 0.5cm"><A CLASS="sdfootnotesym" NAME="sdfootnote6sym" HREF="#sdfootnote6anc">6</A>At + least because another implementation might trash files into the same + trash directory</P> +</DIV> +<DIV ID="sdfootnote7"> + <P CLASS="sdfootnote" STYLE="margin-bottom: 0.5cm"><A CLASS="sdfootnotesym" NAME="sdfootnote7sym" HREF="#sdfootnote7anc">7</A>For + example, if the file in $trash/files is named foo.bar , the + corresponding file in $trash/info must be named foo.bar.trashinfo</P> +</DIV> +<DIV ID="sdfootnote8"> + <P CLASS="sdfootnote" STYLE="margin-bottom: 0.5cm"><A CLASS="sdfootnotesym" NAME="sdfootnote8sym" HREF="#sdfootnote8anc">8</A>This + provides for future extension</P> +</DIV> +</BODY> +</HTML> diff --git a/web-export/README b/web-export/README new file mode 100644 index 0000000..94cbdbc --- /dev/null +++ b/web-export/README @@ -0,0 +1,9 @@ +This directory contains the files used to export the specifications on + http://specifications.freedesktop.org/ + +It's mostly two files: + + - specs.idx: information on where to fetch specific versions of different + specifications (usually CVS or git) + + - update.py: hacky script that uses specs.idx and creates html pages diff --git a/web-export/specs.idx b/web-export/specs.idx new file mode 100644 index 0000000..4d0dde1 --- /dev/null +++ b/web-export/specs.idx @@ -0,0 +1,91 @@ +git:xdg/xdg-specs:autostart/autostart-spec.xml master 0.5 autostart-spec + +git:xdg/xdg-specs:basedir/basedir-spec.xml master 0.8 basedir-spec +git:xdg/xdg-specs:basedir/basedir-spec.xml 5c950648d4e3b186bda82c0c27ef089ee6747cbd 0.7 basedir-spec +git:xdg/xdg-specs:basedir/basedir-spec.xml 2c096d0c74244bd573027b217be3a69335a923f4 0.6 basedir-spec +# Invalid docbook: +#git:xdg/xdg-specs:basedir/basedir-spec.xml c8475bef1d1f84afcc89c710b6b5b214f11a670f 0.5 basedir-spec + +icccm-extensions/selections/clipboards.txt 1.2 0.1 clipboards-spec +icccm-extensions/selections/clipboard-extensions.txt 1.1 0.1 clipboard-extensions-spec + +git:dbus/dbus:doc/introspect.dtd 7652304bff969afb3969603149bb385efe861fe8 1.0 dbus + +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml master 1.1 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml e1775a202af19adf9c73e6954293e2e95f8f13a0 1.0 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml 7d249792235d0f3b69f833f89bef545a367f0b6b 0.9.8 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml 3e675b52041139085cc280dcdf2562e38cba8a31 0.9.7 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml af1b346daa90b9cb88ec9e3b6d3ebd05942a73d7 0.9.6 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml 6855384d021d88557f80674798c584c15b547f36 0.9.5 desktop-entry-spec +# Invalid docbook: +#git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml b818b36ff0ee3c7f35df7b38db15a18b434f6375 0.9.4 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.sgml e7d2b4770815f8d8dcca934d3520d3fe55f86b09 0.9.3 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.sgml 9c493d5fca5fcceca4e1bc0b2b2ba8a13c5eb12e 0.9.2 desktop-entry-spec + +git:xdg/default-icon-theme:spec/icon-naming-spec.xml master 0.8.90 icon-naming-spec +git:xdg/default-icon-theme:spec/icon-naming-spec.xml 77bc8ba641ca24bf2e55292f7d31926d60295e5c 0.8 icon-naming-spec +git:xdg/default-icon-theme:spec/icon-naming-spec.xml aba09c448ecc055f93a959a54497ef02be4ceab2 0.7 icon-naming-spec +git:xdg/default-icon-theme:spec/icon-naming-spec.xml 678139104048733b680c331d28ee09f6f16f386c 0.6 icon-naming-spec +git:xdg/default-icon-theme:spec/icon-naming-spec.xml 1dc55c9db340a7d0a9ac84e1e42735df311cdad5 0.4 icon-naming-spec +# Invalid docbook: +#git:xdg/default-icon-theme:spec/icon-naming-spec.xml db9bb955c0cf20322b149676b908ecd69929d2f1 0.3 icon-naming-spec + +git:xdg/default-icon-theme:spec/icon-theme-spec.xml e54ef4b65ae0eab72ffe23e18a470072e1719471 0.12 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml f09150e444382a18d147ef45afa9310e2e27c713 0.11 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml 37f3118e81954b2171a333614901a0b74c295edc 0.10 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml 400de5cb3e4f8046763ce816fb93a9ec287e6e39 0.9 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml 61ce5bd0f09d5026b32f015f7f8d209524b85cf1 0.8 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml bd6077c5fc235d830d325a977770150bd2d71136 0.7 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml b1a891e95eb4f28da4e43fb6cb7a662bc0431529 0.6 icon-theme-spec + +git:xdg/xdg-specs:menu/menu-spec.xml master 1.1 menu-spec +git:xdg/xdg-specs:menu/menu-spec.xml 647153fb87e5f642a7b7a3fdcec90961f36e89ab 1.0 menu-spec +git:xdg/xdg-specs:menu/menu-spec.xml a61b06aa1aee4743f50024b0695795fe9568d929 0.92 menu-spec +git:xdg/xdg-specs:menu/menu-spec.xml 2403355e486ac6bc972fd150d38e3c44d086960a 0.91 menu-spec +git:xdg/xdg-specs:menu/menu-spec.xml e1b6bf680dc4d021e7f2122841f812975a31985c 0.9 menu-spec +# Invalid docbook: +#git:xdg/xdg-specs:menu/menu-spec.xml 7d616706bba168427214848c6fbb77da5a30e04d 0.8 menu-spec +#git:xdg/xdg-specs:menu/menu-spec.xml 28a4c60cb40502c01417bfdbd8a2e093eb4af2d9 0.7 menu-spec +#git:xdg/xdg-specs:menu/menu-spec.xml 9f969d0e6625b2da24fb971ebd3cf7f913a1c5f1 0.6 menu-spec +#git:xdg/xdg-specs:menu/menu-spec.xml c15b9df59efac72ea80fb715bf2a9d7f7afd1bba 0.5 menu-spec +#git:xdg/xdg-specs:menu/menu-spec.xml c8475bef1d1f84afcc89c710b6b5b214f11a670f 0.4 menu-spec +git:xdg/xdg-specs:menu/menu.dtd 2403355e486ac6bc972fd150d38e3c44d086960a 0.91 menu-spec + +recent-files/recent-file-spec/recent-file-spec.xml 1.1 0.2 recent-file-spec + +git:xdg/shared-mime-info:shared-mime-info-spec.xml 2f909cff817a3f08d12321769173cac2de0da1b4 0.20 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 30349a8810143c1f808a74c96bceba87d48e8364 0.19 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 1bac8224c7439452a85693dc1a25f64d3a467e7d 0.18 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 83c091bbb4d32231b308864d227ada6106bc59a5 0.17 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 6c474418318c6c192abfe0f17f85209c65bfa1cf 0.16 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 7fab0df72e558a1d651e2557d52ac37b8d5020e9 0.15 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 0239582644c9edffa7edd4562ccb967d14d63e73 0.14 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml f364fdbba5bb7fe8b69e0294aa353845515b191e 0.13 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml ad3203089d3d029b5c18ebd4baa6f7991dd9bb22 0.12 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 92cca5e4cec157f252fd77b5ce23853974603906 0.11 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml dc2724f1d1b010a80b269ef21a1e613f55170777 0.10 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml e1359233cf0544509854178e8591ed39b5ccbcdf 0.9 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 7b25e407e6dc6cda94c2fb1f83b4ac4956a22fbf 0.8 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml d08ddd99abf32cbf770fecc43f950f4a8c7a4dc0 0.7 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 1dd7f6ce4610378b970674cfef61e1bda2389ba5 0.6 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 2e3dfe6117ec97da5493669a05459fdcac914e1c 0.5 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml bfd730e142344783603ac4cdf0467ccf2e2ff1fd 0.4 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml f6fa8bf89055da53e9323aca59d5337729178ade 0.3 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml e235408efaeec39b5be22d4f1d4218da64247d74 0.2 shared-mime-info-spec + +git:startup-notification:doc/startup-notification.txt master 0.2 startup-notification-spec +git:startup-notification:doc/startup-notification.txt e1d689b36635ed632cbb91cf3104f84bd0b59bfd 0.1 startup-notification-spec + +git:xdg/xdg-specs:systemtray/systemtray-spec.xml cbe62e957475dba73d9d830dd755c76f8d3abd23 0.3 systemtray-spec +git:xdg/xdg-specs:systemtray/systemtray-spec.xml 87fb46a8631a8b509bb1b8026b88c7059f869ffd 0.2 systemtray-spec +git:xdg/xdg-specs:systemtray/systemtray-spec.xml c8475bef1d1f84afcc89c710b6b5b214f11a670f 0.1 systemtray-spec + +git:xdg/xdg-specs:wm-spec/wm-spec.xml master 1.5 wm-spec +git:xdg/xdg-specs:wm-spec/wm-spec.xml a95af55a102b0814e81095bda46a691068009c3c 1.4 wm-spec +git:xdg/xdg-specs:wm-spec/wm-spec.xml 2eafacb23421d25147533a66a9eb8f0f4650a5e4 1.3 wm-spec +git:xdg/xdg-specs:wm-spec/wm-spec.sgml d10d819f39c4c7e878288192f14248536d9d4b96 1.2 wm-spec +git:xdg/xdg-specs:wm-spec/wm-spec.sgml a6e9a0a88112e5f6ac7099530e5c732c7ec6fb7f 1.1 wm-spec +# Invalid docbook: +#git:xdg/xdg-specs:wm-spec/wm-spec.sgml b58352845cebc1d3b5754215a03ed047d1b28b11 1.0 wm-spec + +xembed/xembed/spec/xembed-spec.xml 1.2 0.5 xembed-spec diff --git a/web-export/update.py b/web-export/update.py new file mode 100755 index 0000000..cd54f28 --- /dev/null +++ b/web-export/update.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python + +# Dependencies to run this: +# - xmlto in $PATH + +# FIXME: +# - correctly handle all exceptions +# - copy dtd files where they should be +# - new structure for website: +# specs.fd.o/index.html -- general index +# specs.fd.o/desktop-entry/index.html -- index of all versions of desktop entry, with all formats +# specs.fd.o/desktop-entry/1.0/desktop-entry-spec.xml -- docbook version of the spec 1.0 +# specs.fd.o/desktop-entry/1.0/index.html -- one-page html version of the spec 1.0 +# specs.fd.o/desktop-entry/1.0/split/ -- multiple-page html version of the spec 1.0 +# specs.fd.o/desktop-entry/latest/ -- link to directory containing latest version of the spec + +import os +import sys + +import errno + +import StringIO +import hashlib +import shutil +import subprocess +import urllib +import urllib2 +import urlparse + +DEVELOPMENT = False + +CVSWEB = 'http://cvs.freedesktop.org' +GITWEB = 'http://cgit.freedesktop.org' +HASH = 'md5' + + +def safe_mkdir(dir): + if not dir: + return + + try: + os.mkdir(dir) + except OSError, e: + if e.errno != errno.EEXIST: + raise e + + +def get_hash_from_fd(fd, algo = HASH, read_blocks = 1024): + if algo not in [ 'md5' ]: + raise Exception('Internal error: hash algorithm \'%s\' not planned in code.' % algo) + + hash = hashlib.new(algo) + while True: + data = fd.read(read_blocks) + if not data: + break + hash.update(data) + return hash.digest() + + +def get_hash_from_url(url, algo = HASH): + fd = urllib2.urlopen(url, None) + digest = get_hash_from_fd(fd, algo) + fd.close() + return digest + + +def get_hash_from_path(path, algo = HASH): + fd = open(path, 'rb') + digest = get_hash_from_fd(fd, algo, read_blocks = 32768) + fd.close() + return digest + + +def get_hash_from_data(data, algo = HASH): + fd = StringIO.StringIO(data) + digest = get_hash_from_fd(fd, algo, read_blocks = 32768) + fd.close() + return digest + + +class VcsObject: + def __init__(self, vcs, repo, file, revision = None): + self.vcs = vcs + self.repo = repo + self.file = file + self.revision = revision + self.data = None + + def get_url(self): + query = {} + if self.vcs == 'git': + baseurl = GITWEB + path = '/'.join((self.repo, 'plain', self.file)) + if self.revision: + query['id'] = self.revision + elif self.vcs == 'cvs': + baseurl = CVSWEB + path = self.file + if self.revision: + query['rev'] = self.revision + else: + raise Exception('Unknown VCS: %s' % self.vcs) + + (scheme, netloc, basepath) = urlparse.urlsplit(baseurl)[0:3] + full_path = '/'.join((basepath, path)) + + query_str = urllib.urlencode(query) + return urlparse.urlunsplit((scheme, netloc, full_path, query_str, '')) + + def fetch(self): + if self.data: + return + + url = self.get_url() + fd = urllib2.urlopen(url, None) + self.data = fd.read() + fd.close() + + def get_hash(self): + self.fetch() + return get_hash_from_data(self.data) + + +class SpecObject(): + def __init__(self, vcs, spec_dir, version): + self.vcs = vcs + self.spec_dir = spec_dir + self.version = version + + basename = os.path.basename(self.vcs.file) + (self.basename_no_ext, self.ext) = os.path.splitext(basename) + + self.filename = '%s-%s%s' % (self.basename_no_ext, self.version, self.ext) + + if self.ext not in ['.xml', '.sgml', '.txt', '.dtd']: + raise Exception('Format \'%s\' not supported for %s' % (self.ext, self.vcs.get_url())) + + self.downloaded = False + self.one_chunk = False + self.multiple_chunks = False + + def download(self): + safe_mkdir(self.spec_dir) + path = os.path.join(self.spec_dir, self.filename) + + if os.path.exists(path): + current_hash = get_hash_from_path(path) + vcs_hash = self.vcs.get_hash() + if current_hash == vcs_hash: + return + + self.vcs.fetch() + fd = open(path, 'wb') + fd.write(self.vcs.data) + fd.close() + + self.downloaded = True + + def htmlize(self, force = False): + if not self.downloaded and not force: + return + + path = os.path.join(self.spec_dir, self.filename) + (path_no_ext, ext) = os.path.splitext(path) + + # One-chunk HTML + html_path = '%s%s' % (path_no_ext, '.html') + if os.path.exists(html_path): + os.unlink(html_path) + + # Multiple chunks + html_dir = os.path.join(self.spec_dir, self.version) + if os.path.exists(html_dir): + shutil.rmtree(html_dir) + + one_chunk_command = None + multiple_chunks_command = None + + if self.ext == '.xml': + one_chunk_command = ['xmlto', '-o', self.spec_dir, 'html-nochunks', path] + multiple_chunks_command = ['xmlto', '-o', html_dir, 'html', path] + elif self.ext == '.sgml': + one_chunk_command = ['docbook2html', '-o', self.spec_dir, '--nochunks', path] + multiple_chunks_command = ['docbook2html', '-o', html_dir, path] + + if one_chunk_command: + retcode = subprocess.call(one_chunk_command) + if retcode != 0: + raise Exception('Cannot convert \'%s\' to HTML.' % path) + self.one_chunk = True + + if multiple_chunks_command: + safe_mkdir(html_dir) + retcode = subprocess.call(multiple_chunks_command) + if retcode != 0: + raise Exception('Cannot convert \'%s\' to multiple-chunks HTML.' % path) + self.multiple_chunks = True + + def latestize(self): + filename_latest = '%s-latest%s' % (self.basename_no_ext, self.ext) + + path_latest = os.path.join(self.spec_dir, filename_latest) + if os.path.exists(path_latest): + os.unlink(path_latest) + os.symlink(self.filename, path_latest) + + if self.ext in ['.xml', '.sgml']: + # One-chunk HTML + html_path_latest = os.path.join(self.spec_dir, '%s-latest%s' % (self.basename_no_ext, '.html')) + if os.path.exists(html_path_latest): + os.unlink(html_path_latest) + + (filename_no_ext, ext) = os.path.splitext(self.filename) + html_filename = '%s%s' % (filename_no_ext, '.html') + html_path = os.path.join(self.spec_dir, html_filename) + if os.path.exists(html_path): + os.symlink(html_filename, html_path_latest) + + # Multiple chunks + html_dir_latest = os.path.join(self.spec_dir, 'latest') + if os.path.exists(html_dir_latest): + os.unlink(html_dir_latest) + + html_dir = os.path.join(self.spec_dir, self.version) + if os.path.exists(html_dir): + os.symlink(self.version, html_dir_latest) + + +SCRIPT = VcsObject('git', 'xdg/xdg-specs', 'web-export/update.py') +SPECS_INDEX = VcsObject('git', 'xdg/xdg-specs', 'web-export/specs.idx') + + +def is_up_to_date(): + current_hash = get_hash_from_path(__file__) + vcs_hash = SCRIPT.get_hash() + + return current_hash == vcs_hash + + +if not DEVELOPMENT: + if not is_up_to_date(): + print >>sys.stderr, 'Script is not up-to-date, please download %s' % SCRIPT.get_url() + sys.exit(1) + + SPECS_INDEX.fetch() + lines = SPECS_INDEX.data.split('\n') +else: + lines = open('specs.idx').readlines() + + +latests = [] + +for line in lines: + line = line.strip() + if not line or line.startswith('#'): + continue + + (data, revision, version, path) = line.split() + if data.startswith("git:"): + git_data = data.split(":") + vcs = VcsObject('git', git_data[1], git_data[2], revision) + else: + vcs = VcsObject('cvs', None, data, revision) + + spec = SpecObject(vcs, path, version) + + spec.download() + spec.htmlize() + + # Create latest links if it's the first time we see this spec + if (spec.spec_dir, spec.basename_no_ext) not in latests: + latests.append((spec.spec_dir, spec.basename_no_ext)) + spec.latestize() diff --git a/wm-spec/Makefile b/wm-spec/Makefile new file mode 100644 index 0000000..d7db04b --- /dev/null +++ b/wm-spec/Makefile @@ -0,0 +1,7 @@ +all: wm-spec.html + +%.html: %.xml + xmlto html-nochunks $< + +clean: + rm -f wm-spec.html diff --git a/wm-spec/wm-spec.xml b/wm-spec/wm-spec.xml new file mode 100644 index 0000000..87dc02d --- /dev/null +++ b/wm-spec/wm-spec.xml @@ -0,0 +1,2760 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +<!ENTITY version "Draft version 1.5.draft-1"> +<!ENTITY date "Fri November 29, 2011"> +]> +<article id="index"> +<articleinfo> + <authorgroup> + <corpauthor> + <ulink url="http://www.freedesktop.org">X Desktop Group</ulink> + </corpauthor> + </authorgroup> +<title>Extended Window Manager Hints</title> +<date>&date;</date> +<releaseinfo>&version;</releaseinfo> +</articleinfo> +<sect1> + <title>Introduction</title> + <sect2> + <title>Version</title> + <para> +This is &version; of the Extended Window Manager Hints (EWMH) spec, updated +&date;. The canonical home for this document is <ulink +url="http://www.freedesktop.org/standards/wm-spec/">http://www.freedesktop.org</ulink>, +which also contains directions for reporting bugs or contributing to future +versions. + </para> + </sect2> + <sect2> + <title>What is this spec?</title> + <para> +This spec defines interactions between window managers, compositing +managers, applications, and the utilities that form part of a desktop +environment. It builds on the Inter-Client Communication Conventions +Manual <citation><link linkend="ICCCM">ICCCM</link></citation>, which +defines window manager interactions at a lower level. The ICCCM does +not provide ways to implement many features that modern desktop users +expect. The GNOME and KDE desktop projects originally developed their +own extensions to the ICCCM to support these features; this spec +replaces those custom extensions with a standardized set of ICCCM +additions that any desktop environment can adopt. + </para> + </sect2> + <sect2> + <title>Language used in this specification</title> + <para> +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in RFC 2119. + </para> + <para> +The key words "Window Manager" refer to a window manager which is adopting this +specification. "Pager" refers to desktop utility applications, including +pagers and taskbars. "Application" refers to other clients. "Clients" refers +to Pagers and Applications ie. all X clients, except for the Window Manager. + </para> + </sect2> + <sect2> + <title>Prerequisites for adoption of this specification</title> + <para> +Window Managers and Clients which aim to fulfill this specification MUST adhere +to the ICCCM on which this specification builds. If this specification +explicitly modifies the ICCCM Window Managers and Clients MUST fulfill these +modifications. + </para> + </sect2> +</sect1> +<sect1> +<title>Non-ICCCM features</title> +<para>There is a number of window management features or behaviors which are +not specified in the ICCCM, but are commonly met in modern window managers and desktop environments.</para> +<sect2> +<title>Additional States</title> +<para>The ICCCM allows window managers to implement additional window states, which will +appear to clients as substates of NormalState and IconicState. Two +commonly met examples are Maximized and Shaded. A window manager may implement these +as proper substates of NormalState and IconicState, or it may treat them +as independent flags, allowing e.g. a maximized window to be iconified +and to re-appear as maximized upon de-iconification.</para> +<sect3> +<title>Maximization</title> +<para>Maximization is a very old feature of window managers. There was even a ZoomedState +in early ICCCM drafts. Maximizing a window should give it as much of the +screen area as possible (this may not be the full screen area, but only +a smaller 'workarea', since the window manager may have reserved certain areas for other +windows). A window manager is expected to remember the geometry of a maximized window +and restore it upon de-maximization. Modern window managers typically allow separate +horizontal and vertical maximization.</para> +<para>With the introduction of the Xinerama extension in X11 R6.4, maximization +has become more involved. Xinerama allows a screen to span multiple +monitors in a freely configurable geometry. In such a setting, maximizing +a window would ideally not grow it to fill the whole screen, but only the +monitor it is shown on. There are of course borderline cases for windows +crossing monitor boundaries, and 'real' maximization to the full screen may +sometimes be useful.</para> +</sect3> +<sect3> +<title>Shading</title> +<para>Some desktop environments offer shading (also known as rollup) as an alternative to +iconification. A shaded window typically shows only the titlebar, the client +window is hidden, thus shading is not useful for windows which are not +decorated with a titlebar.</para> +</sect3> +</sect2> +<sect2> +<title>Modality</title> +<para>The WM_TRANSIENT_FOR hint of the ICCCM allows clients to specify that a +toplevel window may be closed before the client finishes. A typical example +of a transient window is a dialog. Some dialogs can be open for a long time, +while the user continues to work in the main window. Other dialogs have to be +closed before the user can continue to work in the main window. This property +is called modality. While clients can implement modal windows in an ICCCM +compliant way using the globally active input model, some window managers offer support +for handling modality. +</para> +</sect2> +<sect2 id="largedesks"> +<title>Large Desktops</title> +<para>The window manager may offer to arrange the managed windows on a desktop that is +larger than the root window. The screen functions as a viewport on this large +desktop. Different policies regarding the positioning of the viewport on the +desktop can be implemented: The window manager may only allow the viewport +position to change in increments of the screen size (paging) or it may allow +arbitrary positions (scrolling).</para> +<para>To fulfill the ICCCM principle that clients should behave the same +regardless whether a window manager is running or not, window managers which +implement large desktops must interpret all client-provided geometries with +respect to the current viewport.</para> +<sect3 id="largedesksimpl"> +<title>Implementation note</title> +<para>There are two options for implementing a large desktop: The first is to +keep the managed windows (or, if reparenting, their frames) as children +of the root window. Moving the viewport is achieved by moving all managed +windows in the opposite direction.</para> +<para>The second alternative is to reparent all managed windows to a dedicated +large window (somewhat inappropriately called a 'virtual root'). Moving +the viewport is then achieved by moving the virtual root in the opposite +direction.</para> +<para>Both alternatives are completely ICCCM compliant, although the second one +may be somewhat problematic for clients trying to figure out the window manager decorations +around their toplevel windows and for clients trying to draw background +images on the root window.</para> +</sect3> +</sect2> +<sect2> +<title>Sticky windows</title> +<para>A window manager which implements a large desktop typically offers a way for the user +to make certain windows 'stick to the glass', i.e. these windows will stay +at the same position on the screen when the viewport is moved.</para> +</sect2> +<sect2> +<title>Virtual Desktops</title> +<para>Most X servers have only a single screen. The window manager may virtualize this +resource and offer multiple so-called 'virtual desktops', of which only one +can be shown on the screen at a time. There is some variation among the +features of virtual desktop implementations. There may be a fixed number +of desktops, or new ones may be created dynamically. The size of the desktops +may be fixed or variable. If the desktops are larger than the root window, +their viewports (see <xref linkend="largedesks"/>) may be independent or forced +to be at the same position.</para> +<para>A window manager which implements virtual desktops generally offers a way for the user +to move clients between desktops. Clients may be allowed to occupy more than +one desktop simultaneously.</para> +<sect3> +<title>Implementation note</title> +<para>There are at least two options for implementing virtual desktops. +The first is to use multiple virtual roots (see <xref linkend="largedesksimpl"/>) and change the current +desktop by manipulating the stacking order of the virtual roots. This is +completely ICCCM compliant, but has the issues outlined in <xref linkend="largedesksimpl"/></para> +<para>The second option is to keep all managed windows as children of the root +window and unmap the frames of those which are not on the current +desktop. Unmapped windows should be placed in IconicState, according to +the ICCCM. Windows which are actually iconified or minimized +should have the _NET_WM_STATE_HIDDEN property set, to +communicate to pagers that the window should not be represented as +"onscreen." +</para> +</sect3> +</sect2> +<sect2> +<title>Pagers</title> +<para>A pager offers a different UI for window management tasks. It shows a +miniature view of the desktop(s) representing managed windows by small +rectangles and allows the user to initiate various window manager actions by manipulating +these representations. Typically offered actions are activation (see <xref linkend="activation"/>), +moving, restacking, iconification, maximization and closing. On a large +desktop, the pager may offer a way to move the viewport. On virtual desktops, +the pager may offer ways to move windows between desktops and to change the +current desktop.</para> +</sect2> +<sect2> +<title>Taskbars</title> +<para>A taskbar offers another UI for window management tasks. It typically +represents client windows as a list of buttons labelled with the window +titles and possibly icons. Pressing a button initiates a window manager action on the +represented window, typical actions being activation and iconification. +In environments with a taskbar, icons are often considered inappropriate, +since the iconified windows are already represented in the taskbar.</para> +</sect2> +<sect2 id="activation"> +<title>Activation</title> +<para>In the X world, activating a window means to give it the input focus. +This may not be possible if the window is unmapped, because it is on a +different desktop. Thus, activating a window may involve additional steps +like moving it to the current desktop (or changing to the desktop the window +is on), deiconifying it or raising it.</para> +</sect2> +<sect2> +<title>Animated iconification</title> +<para>Some window managers display some form of animation when (de-)iconifying a window. +This may be a line drawing connecting the corners of the window with +the corners of the icon or the window may be opaquely moved and resized +on some trajectory joining the window location and the icon location.</para> +</sect2> +<sect2> +<title>Window-in-window MDI</title> +<para>Window-in-window MDI is a multiple document interface known from MS +Windows platforms. Programs employing it have a single top-level window +which contains a workspace which contains the subwindows for the open +documents. These subwindows are decorated with window manager frames and can be +manipulated within their parent window just like ordinary top-level +windows on the root window.</para> +</sect2> +<sect2> + <title>Override-redirect windows</title> + <para> +Override-redirect windows are ignored by traditional window managers, +but not by compositing managers. Compositing managers are responsible +for painting all windows to the screen, including override-redirect +windows. +</para> + <para> +To enable compositing managers to decorate override-redirect window +properly, for example by making them translucent or by changing the +shape of the windows, this spec allows clients to set properties on +override-redirect windows indicating the function of the windows. +</para> +</sect2> +<sect2> +<title>Layered stacking order</title> +<para> +Some window managers keep the toplevel windows not in a single linear stack, +but subdivide the stack into several layers. There is a lot of variation +among the features of layered stacking order implementations. The number of +layers may or may not be fixed. The layer of a toplevel window may be explicit +and directly modifiable or derived from other properties of the window, e.g. +the <emphasis>type</emphasis> of the window. The stacking order may or may not +be strict, i.e. not allow the user to raise or lower windows beyond their +layer. +</para> +</sect2> +<sect2> +<title>Scope of this spec</title> +<para>This spec tries to address the following issues:</para> +<itemizedlist> +<listitem><para>Allow clients to influence their initial state with respect +to maximization, shading, stickiness, desktop, stacking order.</para></listitem> +<listitem><para>Improve the window manager's ability to vary window +decorations and maintain the stacking order by allowing clients to hint the +window manager about the type of their windows.</para></listitem> +<listitem><para>Improve the compositing manager's ability to apply +decorations and effects to override-redirect windows</para></listitem> +<listitem><para>Enable pagers and taskbars to be implemented as separate +clients and allow them to work with any compliant window manager.</para></listitem> +</itemizedlist> +<para>This spec doesn't cover any of the following:</para> +<itemizedlist> +<listitem><para>Other IPC mechanisms like ICE or Corba.</para></listitem> +<listitem><para>Window manager configuration.</para></listitem> +<listitem><para>Window manager documentation.</para></listitem> +<listitem><para>Clients appearing on a proper subset of desktops.</para></listitem> +<listitem><para>Window-in-window MDI.</para></listitem> +</itemizedlist> +<para>The window manager is supposed to be in charge of window management +policy, so that there is consistent behavior on the user's screen no matter +who wrote the clients.</para> +<para>The spec offers a lot of external control about window manager actions. +This is intended mainly to allow pagers, taskbars and similar window manager +UIs to be implemented as separate clients. "Ordinary" clients shouldn't use +these except maybe in response to a direct user request (i.e. setting a +config option to start maximized or specifying a -desk n command line +argument).</para> +</sect2> +</sect1> +<sect1> + <title>Root Window Properties (and Related Messages)</title> + <para> +Whenever this spec speaks about <quote>sending a message to the root +window</quote>, it is understood that the client is supposed to create +a ClientMessage event with the specified contents and send it by using +a SendEvent request with the following arguments: + <programlisting><![CDATA[ +destination root +propagate False +event-mask (SubstructureNotify|SubstructureRedirect) +event the specified ClientMessage +]]></programlisting> + </para> + <sect2><title>_NET_SUPPORTED</title> + <programlisting><![CDATA[ +_NET_SUPPORTED, ATOM[]/32 +]]></programlisting> + <para> +This property MUST be set by the Window Manager to indicate which hints it +supports. For example: considering _NET_WM_STATE +both this atom and all supported states e.g. _NET_WM_STATE_MODAL, +_NET_WM_STATE_STICKY, would be listed. This assumes that backwards +incompatible changes will not be made to the hints (without being renamed). + </para> + </sect2><sect2><title>_NET_CLIENT_LIST</title> + <programlisting><![CDATA[ +_NET_CLIENT_LIST, WINDOW[]/32 +_NET_CLIENT_LIST_STACKING, WINDOW[]/32 +]]></programlisting> + <para> +These arrays contain all X Windows managed by the Window Manager. +_NET_CLIENT_LIST has initial mapping order, starting with the oldest window. +_NET_CLIENT_LIST_STACKING has bottom-to-top stacking order. These properties +SHOULD be set and updated by the Window Manager. + </para> + </sect2> + <sect2> + <title>_NET_NUMBER_OF_DESKTOPS</title> + <programlisting><![CDATA[ +_NET_NUMBER_OF_DESKTOPS, CARDINAL/32 +]]></programlisting> + <para> +This property SHOULD be set and updated by the Window Manager to indicate the +number of virtual desktops. + </para> + <para> +A Pager can request a change in the number of desktops by sending a _NET_NUMBER_OF_DESKTOPS message to the root window: + </para> + <programlisting><![CDATA[ +_NET_NUMBER_OF_DESKTOPS + message_type = _NET_NUMBER_OF_DESKTOPS + format = 32 + data.l[0] = new_number_of_desktops + other data.l[] elements = 0 +]]></programlisting> + <para> +The Window Manager is free to honor or reject this request. If the request is honored _NET_NUMBER_OF_DESKTOPS MUST be set to the new number of desktops, _NET_VIRTUAL_ROOTS MUST be set to store the new number of desktop virtual root window IDs and _NET_DESKTOP_VIEWPORT and _NET_WORKAREA must also be changed accordingly. The _NET_DESKTOP_NAMES property MAY remain unchanged. + </para> + <para> +If the number of desktops is shrinking and _NET_CURRENT_DESKTOP is out of the new range of available desktops, then this MUST be set to the last available desktop from the new set. Clients that are still present on desktops that are out of the new range MUST be moved to the very last desktop from the new set. For these _NET_WM_DESKTOP MUST be updated. + </para> + </sect2> + <sect2> + <title>_NET_DESKTOP_GEOMETRY</title> + <programlisting><![CDATA[ +_NET_DESKTOP_GEOMETRY width, height, CARDINAL[2]/32 +]]></programlisting> + <para> + Array of two cardinals that defines the common size of all desktops + (this is equal to the screen size if the Window Manager doesn't support + large desktops, otherwise it's equal to the virtual size of the + desktop). This property SHOULD be set by the Window Manager. + </para> + <para> +A Pager can request a change in the desktop geometry by sending a _NET_DESKTOP_GEOMETRY client +message to the root window: + </para> + <programlisting><![CDATA[ +_NET_DESKTOP_GEOMETRY + message_type = _NET_DESKTOP_GEOMETRY + format = 32 + data.l[0] = new_width + data.l[1] = new_height + other data.l[] elements = 0 +]]></programlisting> + <para> +The Window Manager MAY choose to ignore this message, in which case _NET_DESKTOP_GEOMETRY property will remain unchanged. + </para> + </sect2> + <sect2> + <title>_NET_DESKTOP_VIEWPORT</title> + <programlisting><![CDATA[ +_NET_DESKTOP_VIEWPORT x, y, CARDINAL[][2]/32 +]]></programlisting> + <para> +Array of pairs of cardinals that define the top left corner of each desktop's +viewport. For Window Managers that don't support large desktops, this MUST +always be set to (0,0). + </para> + <para> +A Pager can request to change the viewport for the current desktop by sending a +_NET_DESKTOP_VIEWPORT client message to the root window: + </para> + <programlisting><![CDATA[ +_NET_DESKTOP_VIEWPORT + message_type = _NET_DESKTOP_VIEWPORT + format = 32 + data.l[0] = new_vx + data.l[1] = new_vy + other data.l[] elements = 0 +]]></programlisting> + <para> +The Window Manager MAY choose to ignore this message, in which case _NET_DESKTOP_VIEWPORT property will remain unchanged. + </para> + </sect2><sect2><title>_NET_CURRENT_DESKTOP</title> + <programlisting><![CDATA[ +_NET_CURRENT_DESKTOP desktop, CARDINAL/32 +]]></programlisting> + <para> +The index of the current desktop. This is always an integer between 0 and +_NET_NUMBER_OF_DESKTOPS - 1. This MUST be set and updated by the Window +Manager. If a Pager wants to switch to another virtual desktop, it MUST send +a _NET_CURRENT_DESKTOP client message to the root window: + </para> + <programlisting><![CDATA[ +_NET_CURRENT_DESKTOP + message_type = _NET_CURRENT_DESKTOP + format = 32 + data.l[0] = new_index + data.l[1] = timestamp + other data.l[] elements = 0 +]]></programlisting> + <para> +Note that the timestamp may be 0 for clients using an older version of +this spec, in which case the timestamp field should be ignored. + </para> + </sect2><sect2><title>_NET_DESKTOP_NAMES</title> + <programlisting><![CDATA[ +_NET_DESKTOP_NAMES, UTF8_STRING[] +]]></programlisting> + <para> +The names of all virtual desktops. This is a list of NULL-terminated strings in + UTF-8 encoding <citation><link linkend="UTF8">UTF8</link></citation>. This property MAY be + changed by a Pager or the Window Manager at any time. + </para> +<para> +Note: The number of names could be different from _NET_NUMBER_OF_DESKTOPS. +If it is less than _NET_NUMBER_OF_DESKTOPS, then the desktops with high +numbers are unnamed. If it is larger than _NET_NUMBER_OF_DESKTOPS, then the +excess names outside of the _NET_NUMBER_OF_DESKTOPS are considered to be +reserved in case the number of desktops is increased. +</para> +<para> +Rationale: The name is not a necessary attribute of a virtual desktop. Thus +the availability or unavailability of names has no impact on virtual desktop +functionality. Since names are set by users and users are likely to preset +names for a fixed number of desktops, it doesn't make sense to shrink or grow +this list when the number of available desktops changes. +</para> + </sect2><sect2><title>_NET_ACTIVE_WINDOW</title> + <programlisting><![CDATA[ +_NET_ACTIVE_WINDOW, WINDOW/32 +]]></programlisting> + <para> +The window ID of the currently active window or None if no window has the focus. +This is a read-only property set by the +Window Manager. If a Client wants to activate +another window, it MUST send a _NET_ACTIVE_WINDOW client message to the root +window: + </para> + <programlisting><![CDATA[ +_NET_ACTIVE_WINDOW + window = window to activate + message_type = _NET_ACTIVE_WINDOW + format = 32 + data.l[0] = source indication + data.l[1] = timestamp + data.l[2] = requestor's currently active window, 0 if none + other data.l[] elements = 0 +]]></programlisting> + <para> +Source indication should be 1 when the request comes from an application, and 2 +when it comes from a pager. Clients using older version of this spec use 0 +as source indication, see <xref linkend="sourceindication"/> for details. +The timestamp is Client's last user activity timestamp (see _NET_WM_USER_TIME) +at the time of the request, and the currently active window +is the Client's active toplevel window, if any (the Window Manager may +be e.g. more likely to obey the request if it will mean transferring +focus from one active window to another). + </para> + <para> +Depending on the information provided with the message, the Window Manager may +decide to refuse the request (either completely ignore it, or e.g. use +_NET_WM_STATE_DEMANDS_ATTENTION). + </para> + </sect2><sect2><title>_NET_WORKAREA</title> + <programlisting><![CDATA[ +_NET_WORKAREA, x, y, width, height CARDINAL[][4]/32 +]]> + </programlisting> + <para> +This property MUST be set by the Window Manager upon calculating the work area for +each desktop. Contains a geometry for each desktop. These geometries are +specified relative to the viewport on each desktop and specify an area that is +completely contained within the viewport. + Work area SHOULD be used by desktop applications to place desktop icons appropriately. + </para> + <para> +The Window Manager SHOULD calculate this space by taking the current +page minus space occupied by dock and panel windows, as indicated by +the <link linkend="NETWMSTRUT">_NET_WM_STRUT</link> or <link +linkend="NETWMSTRUTPARTIAL">_NET_WM_STRUT_PARTIAL</link> properties set on +client windows. + </para> + </sect2> + <sect2> + <title>_NET_SUPPORTING_WM_CHECK</title> + <programlisting><![CDATA[ +_NET_SUPPORTING_WM_CHECK, WINDOW/32 +]]></programlisting> + <para> +The Window Manager MUST set this property on the root window to be the ID of a + child window created by himself, to indicate that a compliant window manager is + active. The child window MUST also have the _NET_SUPPORTING_WM_CHECK + property set to the ID of the child window. The child window MUST also + have the _NET_WM_NAME property set to the name of the Window Manager. + </para> + <para> +Rationale: The child window is used to distinguish an active Window Manager + from a stale _NET_SUPPORTING_WM_CHECK + property that happens to point to another window. If the + _NET_SUPPORTING_WM_CHECK window on the client window is missing + or not properly set, clients SHOULD assume that no conforming + Window Manager is present. + </para> + </sect2> + <sect2> + <title>_NET_VIRTUAL_ROOTS</title> + <programlisting><![CDATA[ +_NET_VIRTUAL_ROOTS, WINDOW[]/32 +]]></programlisting> + <para> +To implement virtual desktops, some Window Managers reparent client windows to +a child of the root window. Window Managers using this technique MUST set +this property to a list of IDs for windows that are acting as virtual root +windows. This property allows background setting programs to work with +virtual roots and allows clients to figure out the window manager frame windows of their +windows. + </para> + </sect2> + <sect2> + <title>_NET_DESKTOP_LAYOUT</title> + <programlisting><![CDATA[ +_NET_DESKTOP_LAYOUT, orientation, columns, rows, starting_corner CARDINAL[4]/32 +]]> + #define _NET_WM_ORIENTATION_HORZ 0 + #define _NET_WM_ORIENTATION_VERT 1 + + #define _NET_WM_TOPLEFT 0 + #define _NET_WM_TOPRIGHT 1 + #define _NET_WM_BOTTOMRIGHT 2 + #define _NET_WM_BOTTOMLEFT 3 +</programlisting> + <para> + <emphasis>This property is set by a Pager, not by the Window + Manager.</emphasis> + When setting this property, the Pager must own a manager selection (as + defined in the ICCCM 2.8). The manager selection is called + _NET_DESKTOP_LAYOUT_S<literal>n</literal> where + <literal>n</literal> is the screen number. The purpose of + this property is to allow the Window Manager to know the desktop + layout displayed by the Pager. + </para> + <para> + _NET_DESKTOP_LAYOUT describes the layout of virtual + desktops relative to each other. More specifically, it describes the layout + used by the owner of the manager selection. The Window Manager may use + this layout information or may choose to ignore it. + The property contains four values: the Pager orientation, the number of + desktops in the X direction, the number in the Y direction, and the + starting corner of the layout, i.e. the corner containing the first desktop. + </para> + <para> + Note: In order to inter-operate with Pagers implementing an earlier + draft of this document, Window Managers should accept a + _NET_DESKTOP_LAYOUT property of length 3 and + use _NET_WM_TOPLEFT as the starting corner in this case. + </para> + <para> + The virtual desktops are arranged in a rectangle with + <literal>rows</literal> rows and <literal>columns</literal> columns. + If <literal>rows</literal> times <literal>columns</literal> does not match + the total number of desktops as specified by + _NET_NUMBER_OF_DESKTOPS, the highest-numbered + workspaces are assumed to be nonexistent. Either <literal>rows</literal> or + <literal>columns</literal> (but not both) may be specified as 0 in which + case its actual value will be derived from _NET_NUMBER_OF_DESKTOPS. + </para> + <para> + When the orientation is _NET_WM_ORIENTATION_HORZ + the desktops are laid out in rows, with the first desktop in the + specified starting corner. So a layout with four columns and three rows + starting in the _NET_WM_TOPLEFT corner looks like this: +<programlisting> + +--+--+--+--+ + | 0| 1| 2| 3| + +--+--+--+--+ + | 4| 5| 6| 7| + +--+--+--+--+ + | 8| 9|10|11| + +--+--+--+--+ +</programlisting> +With starting_corner _NET_WM_BOTTOMRIGHT, it looks like this: +<programlisting> + +--+--+--+--+ + |11|10| 9| 8| + +--+--+--+--+ + | 7| 6| 5| 4| + +--+--+--+--+ + | 3| 2| 1| 0| + +--+--+--+--+ +</programlisting> + + </para> + <para> + When the orientation is _NET_WM_ORIENTATION_VERT + the layout with four columns and three rows starting in the _NET_WM_TOPLEFT + corner looks like: + +<programlisting> + +--+--+--+--+ + | 0| 3| 6| 9| + +--+--+--+--+ + | 1| 4| 7|10| + +--+--+--+--+ + | 2| 5| 8|11| + +--+--+--+--+ +</programlisting> +With starting_corner _NET_WM_TOPRIGHT, it looks like: + +<programlisting> + +--+--+--+--+ + | 9| 6| 3| 0| + +--+--+--+--+ + |10| 7| 4| 1| + +--+--+--+--+ + |11| 8| 5| 2| + +--+--+--+--+ +</programlisting> + </para> + <para> + The numbers here are the desktop numbers, as for + _NET_CURRENT_DESKTOP. + </para> + </sect2> + + <sect2><title>_NET_SHOWING_DESKTOP</title> + <programlisting><![CDATA[ +_NET_SHOWING_DESKTOP desktop, CARDINAL/32 +]]></programlisting> + <para> + Some Window Managers have a "showing the desktop" mode in which windows + are hidden, and the desktop background is displayed and focused. If a + Window Manager supports the _NET_SHOWING_DESKTOP hint, it MUST set it + to a value of 1 when the Window Manager is in "showing the desktop" mode, + and a value of zero if the Window Manager is not in this mode. + </para> + <para> + If a Pager wants to enter or leave the mode, it MUST + send a _NET_SHOWING_DESKTOP client message to the root window + requesting the change: + <programlisting><![CDATA[ +_NET_SHOWING_DESKTOP + message_type = _NET_SHOWING_DESKTOP + format = 32 + data.l[0] = boolean 0 or 1 + other data.l[] elements = 0 +]]></programlisting> + The Window Manager may choose to ignore this client message. + </para> + </sect2> + + </sect1> + <sect1> + <title>Other Root Window Messages</title> + <sect2><title>_NET_CLOSE_WINDOW</title> + <programlisting><![CDATA[ +_NET_CLOSE_WINDOW +]]></programlisting> + <para> + Pagers wanting to close a window MUST send a _NET_CLOSE_WINDOW client + message request to the root window: + </para> +<programlisting><![CDATA[ +_NET_CLOSE_WINDOW + window = window to close + message_type = _NET_CLOSE_WINDOW + format = 32 + data.l[0] = timestamp + data.l[1] = source indication + other data.l[] elements = 0 +]]></programlisting> + <para> +The Window Manager MUST then attempt to close the window specified. +See <xref linkend="sourceindication"/> for details on the source indication. + </para> + <para> + Rationale: A Window Manager might be more clever than the usual method (send WM_DELETE message if the protocol is selected, XKillClient otherwise). It might introduce a timeout, for example. Instead of duplicating the code, the Window Manager can easily do the job. + </para> + </sect2> + <sect2><title>_NET_MOVERESIZE_WINDOW</title> +<programlisting><![CDATA[ +_NET_MOVERESIZE_WINDOW + window = window to be moved or resized + message_type = _NET_MOVERESIZE_WINDOW + format = 32 + data.l[0] = gravity and flags + data.l[1] = x + data.l[2] = y + data.l[3] = width + data.l[4] = height +]]></programlisting> + <para> + The low byte of data.l[0] contains the gravity to use; it may contain + any value allowed for the WM_SIZE_HINTS.win_gravity property: + NorthWest (1), North (2), NorthEast (3), West (4), Center (5), East + (6), SouthWest (7), South (8), SouthEast (9) and Static (10). A + gravity of 0 indicates that the Window Manager should use the gravity + specified in WM_SIZE_HINTS.win_gravity. The bits 8 to 11 indicate the + presence of x, y, width and height. The bits 12 to 15 indicate the + source (see <xref linkend="sourceindication"/>), so 0001 indicates + the application and 0010 indicates a Pager or a Taskbar. + The remaining bits should be set to zero. + </para> + <para> + Pagers wanting to move or resize a window may send a + _NET_MOVERESIZE_WINDOW client message request to the root window + instead of using a ConfigureRequest. + </para> + <para> + Window Managers should treat a _NET_MOVERESIZE_WINDOW message exactly + like a ConfigureRequest (in particular, adhering to the ICCCM rules + about synthetic ConfigureNotify events), except that they should use + the gravity specified in the message. + </para> + <para> + Rationale: Using a _NET_MOVERESIZE_WINDOW message with StaticGravity + allows Pagers to exactly position and resize a window including its + decorations without knowing the size of the decorations. + </para> + </sect2> + <sect2><title>_NET_WM_MOVERESIZE</title> + <programlisting><![CDATA[ +_NET_WM_MOVERESIZE + window = window to be moved or resized + message_type = _NET_WM_MOVERESIZE + format = 32 + data.l[0] = x_root + data.l[1] = y_root + data.l[2] = direction + data.l[3] = button + data.l[4] = source indication +]]></programlisting> + <para> + This message allows Clients to initiate window movement or + resizing. They can define their own move and size + "grips", whilst letting the Window Manager control the actual operation. + This means that all moves/resizes can happen in a consistent manner as + defined by the Window Manager. See <xref linkend="sourceindication"/> + for details on the source indication. + </para> + <para> + When sending this message in response to a button press event, button + SHOULD indicate the button which was pressed, x_root and y_root MUST + indicate the position of the button press with respect to the root + window and direction MUST indicate whether this is a move or resize + event, and if it is a resize event, which edges of the window the size + grip applies to. When sending this message in response to a key event, + the direction MUST indicate whether this this is a move or resize + event and the other fields are unused. + </para> + <programlisting><![CDATA[ +#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 +#define _NET_WM_MOVERESIZE_SIZE_TOP 1 +#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 +#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 +#define _NET_WM_MOVERESIZE_SIZE_LEFT 7 +#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */ +#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */ +#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */ +#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */ +]]></programlisting> + <para> + The Client MUST release all grabs prior to sending such message (except + for the _NET_WM_MOVERESIZE_CANCEL message). + </para> + <para> + The Window Manager can use the button field to determine the + events on which it terminates the operation initiated by the + _NET_WM_MOVERESIZE message. Since there is a race condition between + a client sending the _NET_WM_MOVERESIZE message and the user releasing + the button, Window Managers are advised to offer some other means to + terminate the operation, e.g. by pressing the ESC key. The special value + _NET_WM_MOVERESIZE_CANCEL also allows clients to cancel the operation + by sending such message if they detect the release themselves + (clients should send it if they get the button release after sending + the move resize message, indicating that the WM did not get a grab in time + to get the release). + </para> + </sect2> + <sect2><title>_NET_RESTACK_WINDOW</title> + <programlisting><![CDATA[ +_NET_RESTACK_WINDOW +]]></programlisting> + <para> + Pagers wanting to restack a window SHOULD send a _NET_RESTACK_WINDOW client + message request to the root window: + </para> +<programlisting><![CDATA[ +_NET_RESTACK_WINDOW + window = window to restack + message_type = _NET_RESTACK_WINDOW + format = 32 + data.l[0] = source indication + data.l[1] = sibling window + data.l[2] = detail + other data.l[] elements = 0 +]]></programlisting> + <para> + This request is similar to ConfigureRequest with CWSibling and CWStackMode flags. It should be used only by pagers, + applications can use normal ConfigureRequests. The source indication field should be therefore set to 2, + see <xref linkend="sourceindication"/> for details. + </para> + <para> + Rationale: A Window Manager may put restrictions on configure requests from applications, for example it may + under some conditions refuse to raise a window. This request makes it clear it comes from a pager or similar + tool, and therefore the Window Manager should always obey it. + </para> + </sect2> + <sect2><title>_NET_REQUEST_FRAME_EXTENTS</title> + <programlisting><![CDATA[ +_NET_REQUEST_FRAME_EXTENTS + window = window for which to set _NET_FRAME_EXTENTS + message_type = _NET_REQUEST_FRAME_EXTENTS +]]></programlisting> + <para> +A Client whose window has not yet been mapped can request of the +Window Manager an estimate of the frame extents it will be given upon +mapping. To retrieve such an estimate, the Client MUST send a +_NET_REQUEST_FRAME_EXTENTS message to the root window. The Window +Manager MUST respond by estimating the prospective frame extents and +setting the window's _NET_FRAME_EXTENTS property accordingly. The +Client MUST handle the resulting _NET_FRAME_EXTENTS PropertyNotify +event. So that the Window Manager has a good basis for estimation, +the Client MUST set any window properties it intends to set +<emphasis>before</emphasis> sending this message. The Client MUST be able to cope +with imperfect estimates. + </para> + <para> +Rationale: A client cannot calculate the dimensions of its window's +frame before the window is mapped, but some toolkits need this +information. Asking the window manager for an estimate of the extents +is a workable solution. The estimate may depend on the current theme, +font sizes or other window properties. The client can track changes +to the frame's dimensions by listening for _NET_FRAME_EXTENTS +PropertyNotify events. + </para> + </sect2> +</sect1> + <sect1> + <title>Application Window Properties</title> + <sect2><title>_NET_WM_NAME</title> + <programlisting><![CDATA[ +_NET_WM_NAME, UTF8_STRING +]]></programlisting> + <para> +The Client SHOULD set this to the title of the window in UTF-8 encoding. If +set, the Window Manager should use this in preference to WM_NAME. + </para> + </sect2> + + <sect2><title>_NET_WM_VISIBLE_NAME</title> + <programlisting><![CDATA[ +_NET_WM_VISIBLE_NAME, UTF8_STRING +]]></programlisting> + <para> +If the Window Manager displays a window name other than _NET_WM_NAME the Window Manager MUST set this to the title displayed in UTF-8 encoding. + </para> + <para> +Rationale: This property is for Window Managers that display a title different from the _NET_WM_NAME or WM_NAME of the window (i.e. xterm <1>, xterm <2>, ... is shown, but _NET_WM_NAME / WM_NAME is still xterm for each window) thereby allowing Pagers to display the same title as the Window Manager. + </para> + </sect2> + + <sect2><title>_NET_WM_ICON_NAME</title> + <programlisting><![CDATA[ +_NET_WM_ICON_NAME, UTF8_STRING +]]></programlisting> + <para> +The Client SHOULD set this to the title of the icon for this window in UTF-8 +encoding. If set, the Window Manager should use this in preference to +WM_ICON_NAME. + </para> + </sect2> + + <sect2><title>_NET_WM_VISIBLE_ICON_NAME</title> + <programlisting><![CDATA[ +_NET_WM_VISIBLE_ICON_NAME, UTF8_STRING +]]></programlisting> + <para> +If the Window Manager displays an icon name other than _NET_WM_ICON_NAME +the Window Manager MUST set this to the title displayed in UTF-8 encoding. + </para> + </sect2> + + <sect2><title>_NET_WM_DESKTOP</title> + <programlisting><![CDATA[ +_NET_WM_DESKTOP desktop, CARDINAL/32 +]]></programlisting> + <para> +Cardinal to determine the desktop the window is in (or wants to be) starting +with 0 for the first desktop. A Client MAY choose not to set this property, +in which case the Window Manager SHOULD place it as it wishes. 0xFFFFFFFF +indicates that the window SHOULD appear on all desktops. + </para> + <para> +The Window Manager should honor _NET_WM_DESKTOP whenever a withdrawn window +requests to be mapped. + </para> + <para> +The Window Manager should remove the property whenever +a window is withdrawn but it should leave the property in place when it is +shutting down, e.g. in response to losing ownership of the WM_Sn manager +selection. + </para> + <para> +Rationale: Removing the property upon window withdrawal helps legacy +applications which want to reuse withdrawn windows. Not removing the property +upon shutdown allows the next Window Manager to restore windows to their +previous desktops. + </para> + <para> +A Client can request a change of desktop for a non-withdrawn window by sending +a _NET_WM_DESKTOP client message to the root window: + </para> + <programlisting><![CDATA[ +_NET_WM_DESKTOP + window = the respective client window + message_type = _NET_WM_DESKTOP + format = 32 + data.l[0] = new_desktop + data.l[1] = source indication + other data.l[] elements = 0 +]]></programlisting> + <para> + See <xref linkend="sourceindication"/> for details on the source + indication. + The Window Manager MUST keep this property updated on all windows. + </para> + </sect2><sect2><title>_NET_WM_WINDOW_TYPE</title> + <programlisting><![CDATA[ +_NET_WM_WINDOW_TYPE, ATOM[]/32 +]]></programlisting> + <para> +This SHOULD be set by the Client before mapping to a list of atoms indicating +the functional type of the window. This property SHOULD be used by the window +manager in determining the decoration, stacking position and other behavior +of the window. The Client SHOULD specify window types in order of preference +(the first being most preferable) but MUST include at least one of the basic +window type atoms from the list below. This is to allow for extension of the +list of types whilst providing default behavior for Window Managers that do +not recognize the extensions. + </para> + <para> +This hint SHOULD also be set for override-redirect windows to allow +compositing managers to apply consistent decorations to menus, +tooltips etc. +</para> + <para> +Rationale: This hint is intended to replace the MOTIF hints. One of the +objections to the MOTIF hints is that they are a purely visual description of +the window decoration. By describing the function of the window, the Window +Manager can apply consistent decoration and behavior to windows of the same +type. Possible examples of behavior include keeping dock/panels on top or +allowing pinnable menus / toolbars to only be hidden when another window has +focus (NextStep style). + </para> + <programlisting><![CDATA[ +_NET_WM_WINDOW_TYPE_DESKTOP, ATOM +_NET_WM_WINDOW_TYPE_DOCK, ATOM +_NET_WM_WINDOW_TYPE_TOOLBAR, ATOM +_NET_WM_WINDOW_TYPE_MENU, ATOM +_NET_WM_WINDOW_TYPE_UTILITY, ATOM +_NET_WM_WINDOW_TYPE_SPLASH, ATOM +_NET_WM_WINDOW_TYPE_DIALOG, ATOM +_NET_WM_WINDOW_TYPE_DROPDOWN_MENU, ATOM +_NET_WM_WINDOW_TYPE_POPUP_MENU, ATOM +_NET_WM_WINDOW_TYPE_TOOLTIP, ATOM +_NET_WM_WINDOW_TYPE_NOTIFICATION, ATOM +_NET_WM_WINDOW_TYPE_COMBO, ATOM +_NET_WM_WINDOW_TYPE_DND, ATOM +_NET_WM_WINDOW_TYPE_NORMAL, ATOM +]]></programlisting> + <para> +_NET_WM_WINDOW_TYPE_DESKTOP indicates a desktop feature. This can include a +single window containing desktop icons with the same dimensions as the screen, +allowing the desktop environment to have full control of the desktop, without +the need for proxying root window clicks. + </para> + <para> +_NET_WM_WINDOW_TYPE_DOCK indicates a dock or panel feature. Typically a +Window Manager would keep such windows on top of all other windows. + </para> + <para> +_NET_WM_WINDOW_TYPE_TOOLBAR and _NET_WM_WINDOW_TYPE_MENU indicate +toolbar and pinnable menu windows, respectively (i.e. toolbars and +menus "torn off" from the main application). Windows of this type may +set the WM_TRANSIENT_FOR hint indicating the main application +window. Note that the _NET_WM_WINDOW_TYPE_MENU should be set on +torn-off managed windows, where _NET_WM_WINDOW_TYPE_DROPDOWN_MENU and +_NET_WM_WINDOW_TYPE_POPUP_MENU are typically used on override-redirect +windows. + </para> + <para> +_NET_WM_WINDOW_TYPE_UTILITY indicates a small persistent utility window, such as +a palette or toolbox. It is distinct from type TOOLBAR because it does not +correspond to a toolbar torn off from the main application. It's distinct from +type DIALOG because it isn't a transient dialog, the user will probably keep it +open while they're working. Windows of this type may set the WM_TRANSIENT_FOR +hint indicating the main application window. + </para> + <para> +_NET_WM_WINDOW_TYPE_SPLASH indicates that the window is a splash screen +displayed as an application is starting up. + </para> + <para> +_NET_WM_WINDOW_TYPE_DIALOG indicates that this is a dialog window. If +_NET_WM_WINDOW_TYPE is not set, then managed windows with +WM_TRANSIENT_FOR set MUST be taken as this type. Override-redirect +windows with WM_TRANSIENT_FOR, but without _NET_WM_WINDOW_TYPE must be +taken as _NET_WM_WINDOW_TYPE_NORMAL. + </para> + <para> +_NET_WM_WINDOW_TYPE_DROPDOWN_MENU indicates that the +window in question is a dropdown menu, ie., the kind of menu that +typically appears when the user clicks on a menubar, as opposed to a +popup menu which typically appears when the user right-clicks on an +object. This property is typically used on override-redirect windows. + </para> + <para> +_NET_WM_WINDOW_TYPE_POPUP_MENU indicates that the +window in question is a popup menu, ie., the kind of menu that +typically appears when the user right clicks on an object, as opposed +to a dropdown menu which typically appears when the user clicks on a +menubar. This property is typically used on override-redirect windows. + </para> + <para> +_NET_WM_WINDOW_TYPE_TOOLTIP indicates that the window +in question is a tooltip, ie., a short piece of explanatory text that +typically appear after the mouse cursor hovers over an object for a +while. This property is typically used on override-redirect windows. + </para> + <para> +_NET_WM_WINDOW_TYPE_NOTIFICATION indicates a +notification. An example of a notification would be a bubble appearing +with informative text such as "Your laptop is running out of power" +etc. This property is typically used on override-redirect windows. + </para> + <para> +_NET_WM_WINDOW_TYPE_COMBO should be used on the windows that are +popped up by combo boxes. An example is a window that appears below a +text field with a list of suggested completions. This property is +typically used on override-redirect windows. + </para> + <para> +_NET_WM_WINDOW_TYPE_DND indicates that the window is being +dragged. Clients should set this hint when the window in question +contains a representation of an object being dragged from one place to +another. An example would be a window containing an icon that is being +dragged from one file manager window to another. This property is +typically used on override-redirect windows. + </para> + <para> +_NET_WM_WINDOW_TYPE_NORMAL indicates that this is a normal, top-level +window, either managed or override-redirect. Managed windows with +neither _NET_WM_WINDOW_TYPE nor WM_TRANSIENT_FOR set MUST be taken as +this type. Override-redirect windows without _NET_WM_WINDOW_TYPE, must +be taken as this type, whether or not they have WM_TRANSIENT_FOR set. +</para> + </sect2> + <sect2> + <title>_NET_WM_STATE</title> + <programlisting><![CDATA[ + _NET_WM_STATE, ATOM[] +]]></programlisting> + <para> +A list of hints describing the window state. Atoms present in the list MUST be +considered set, atoms not present in the list MUST be considered not set. The +Window Manager SHOULD honor +_NET_WM_STATE whenever a withdrawn window requests to be mapped. A Client +wishing to change the state of a window MUST send a _NET_WM_STATE client +message to the root window (see below). The Window Manager MUST keep this +property updated to reflect the current state of the window. + </para> + <para> +The Window Manager should remove the property whenever +a window is withdrawn, but it should leave the property in place when it is +shutting down, e.g. in response to losing ownership of the WM_Sn manager +selection. + </para> + <para> +Rationale: Removing the property upon window withdrawal helps legacy +applications which want to reuse withdrawn windows. Not removing the property +upon shutdown allows the next Window Manager to restore windows to their +previous state. + </para> + <para> +Possible atoms are: + </para> + <programlisting><![CDATA[ +_NET_WM_STATE_MODAL, ATOM +_NET_WM_STATE_STICKY, ATOM +_NET_WM_STATE_MAXIMIZED_VERT, ATOM +_NET_WM_STATE_MAXIMIZED_HORZ, ATOM +_NET_WM_STATE_SHADED, ATOM +_NET_WM_STATE_SKIP_TASKBAR, ATOM +_NET_WM_STATE_SKIP_PAGER, ATOM +_NET_WM_STATE_HIDDEN, ATOM +_NET_WM_STATE_FULLSCREEN, ATOM +_NET_WM_STATE_ABOVE, ATOM +_NET_WM_STATE_BELOW, ATOM +_NET_WM_STATE_DEMANDS_ATTENTION, ATOM +_NET_WM_STATE_FOCUSED, ATOM +]]></programlisting> + <para> +An implementation MAY add new atoms to this list. Implementations +without extensions MUST ignore any unknown atoms, effectively removing +them from the list. These extension atoms MUST NOT start with the prefix +_NET. + </para> + <para> +_NET_WM_STATE_MODAL indicates that this is a modal dialog box. +If the WM_TRANSIENT_FOR hint is set to another toplevel window, the +dialog is modal for that window; if WM_TRANSIENT_FOR is not set or set +to the root window the dialog is modal for its window group. + </para> + <para> +_NET_WM_STATE_STICKY indicates that the Window Manager SHOULD keep the +window's position fixed on the screen, even when the virtual desktop scrolls. + </para> + <para> +_NET_WM_STATE_MAXIMIZED_{VERT,HORZ} indicates that the window is +{vertically,horizontally} maximized. + </para> + <para> +_NET_WM_STATE_SHADED indicates that the window is shaded. + </para> + <para> +_NET_WM_STATE_SKIP_TASKBAR indicates that the window should not be +included on a taskbar. This hint should be requested by the +application, i.e. it indicates that the window by nature is never +in the taskbar. Applications should not set this hint if +_NET_WM_WINDOW_TYPE already conveys the exact nature of the +window. + </para> + <para> +_NET_WM_STATE_SKIP_PAGER indicates that the window should not be +included on a Pager. This hint should be requested by the application, +i.e. it indicates that the window by nature is never in the +Pager. Applications should not set this hint if _NET_WM_WINDOW_TYPE +already conveys the exact nature of the window. + </para> + <para> +_NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate +that a window would not be visible on the screen if its +desktop/viewport were active and its coordinates were within the +screen bounds. The canonical example is that minimized windows should +be in the _NET_WM_STATE_HIDDEN state. Pagers and similar applications +should use _NET_WM_STATE_HIDDEN instead of WM_STATE to decide whether +to display a window in miniature representations of the windows on a +desktop. + </para> +<para> +Implementation note: if an Application asks to toggle +_NET_WM_STATE_HIDDEN the Window Manager should probably just ignore +the request, since _NET_WM_STATE_HIDDEN is a function of some other +aspect of the window such as minimization, rather than an independent +state. +</para> + <para> +_NET_WM_STATE_FULLSCREEN indicates that the window should fill the entire + screen and have no window decorations. Additionally the Window + Manager is responsible for restoring the original geometry after a + switch from fullscreen back to normal window. For example, a + presentation program would use this hint. + </para> + <para> +_NET_WM_STATE_ABOVE indicates that the window should be on top of most +windows (see <xref linkend="STACKINGORDER"/> for details). + </para> + + <para> +_NET_WM_STATE_BELOW indicates that the window should be below most +windows (see <xref linkend="STACKINGORDER"/> for details). + </para> + + <para> + _NET_WM_STATE_ABOVE and _NET_WM_STATE_BELOW are mainly meant for user + preferences and should not be used by applications e.g. for drawing + attention to their dialogs (the Urgency + hint should be used in that case, see <xref linkend="URGENCY"/>).' + </para> + + <para> +_NET_WM_STATE_DEMANDS_ATTENTION indicates that some action in or with the window +happened. For example, it may be set by the Window Manager if the window requested +activation but the Window Manager refused it, or the application may set it if it +finished some work. This state may be set by both the Client and +the Window Manager. It should be unset by the Window Manager when it decides +the window got the required attention (usually, that it got activated). + </para> + + <para> +_NET_WM_STATE_FOCUSED indicates whether the window's decorations are drawn in an +active state. Clients MUST regard it as a read-only hint. It cannot be set at +map time or changed via a _NET_WM_STATE client message. The window given by +_NET_ACTIVE_WINDOW will usually have this hint, but at times other windows may +as well, if they have a strong association with the active window and will be +considered as a unit with it by the user. Clients that modify the appearance of +internal elements when a toplevel has keyboard focus SHOULD check for the +availability of this state in _NET_SUPPORTED and, if it is available, +use it in preference to tracking focus via FocusIn events. By doing so they will +match the window decorations and accurately reflect the intentions of the Window +Manager. + </para> + + <para> +To change the state of a mapped window, a Client MUST send a _NET_WM_STATE +client message to the root window: + </para> +<programlisting><![CDATA[ + window = the respective client window + message_type = _NET_WM_STATE + format = 32 + data.l[0] = the action, as listed below + data.l[1] = first property to alter + data.l[2] = second property to alter + data.l[3] = source indication + other data.l[] elements = 0 +]]></programlisting> + <para> +This message allows two properties to be changed simultaneously, specifically +to allow both horizontal and vertical maximization to be altered together. +l[2] MUST be set to zero if only one property is to be changed. +See <xref linkend="sourceindication"/> for details on the source indication. +l[0], the action, MUST be one of: + </para> + <programlisting><![CDATA[ +_NET_WM_STATE_REMOVE 0 /* remove/unset property */ +_NET_WM_STATE_ADD 1 /* add/set property */ +_NET_WM_STATE_TOGGLE 2 /* toggle property */ +]]></programlisting> + <para> + See also the implementation notes on <link linkend="URGENCY">urgency</link> and <link linkend="NORESIZE">fixed size windows</link>. + </para> + </sect2> + + <sect2> + <title>_NET_WM_ALLOWED_ACTIONS</title> + <programlisting><![CDATA[ +_NET_WM_ALLOWED_ACTIONS, ATOM[] +]]></programlisting> + <para> +A list of atoms indicating user operations that the Window Manager supports for +this window. Atoms present in the list indicate allowed actions, atoms not +present in the list indicate actions that are not supported for this window. +The Window Manager MUST keep this property updated to reflect the +actions which are currently "active" or "sensitive" for a window. +Taskbars, Pagers, and other tools use _NET_WM_ALLOWED_ACTIONS to +decide which actions should be made available to the user. + </para> + <para> +Possible atoms are: + </para> + <programlisting><![CDATA[ +_NET_WM_ACTION_MOVE, ATOM +_NET_WM_ACTION_RESIZE, ATOM +_NET_WM_ACTION_MINIMIZE, ATOM +_NET_WM_ACTION_SHADE, ATOM +_NET_WM_ACTION_STICK, ATOM +_NET_WM_ACTION_MAXIMIZE_HORZ, ATOM +_NET_WM_ACTION_MAXIMIZE_VERT, ATOM +_NET_WM_ACTION_FULLSCREEN, ATOM +_NET_WM_ACTION_CHANGE_DESKTOP, ATOM +_NET_WM_ACTION_CLOSE, ATOM +_NET_WM_ACTION_ABOVE, ATOM +_NET_WM_ACTION_BELOW, ATOM +]]></programlisting> + <para> +An implementation MAY add new atoms to this list. Implementations +without extensions MUST ignore any unknown atoms, effectively removing +them from the list. These extension atoms MUST NOT start with the prefix +_NET. + </para> + <para> +Note that the actions listed here are those that the <emphasis>Window +Manager</emphasis> will honor for this window. The operations must still be +requested through the normal mechanisms outlined in this specification. For +example, _NET_WM_ACTION_CLOSE does not mean that clients can send a +WM_DELETE_WINDOW message to this window; it means that clients can use a +_NET_CLOSE_WINDOW message to ask the Window Manager to do so. + </para> + <para> +Window Managers SHOULD ignore the value of _NET_WM_ALLOWED_ACTIONS when they +initially manage a window. This value may be left over from a previous Window +Manager with different policies. + </para> + <para> +_NET_WM_ACTION_MOVE indicates that the window may be moved around the screen. + </para> + <para> +_NET_WM_ACTION_RESIZE indicates that the window may be resized. +(Implementation note: Window Managers can identify a non-resizable +window because its minimum and maximum size in WM_NORMAL_HINTS will be the same.) + </para> + <para> +_NET_WM_ACTION_MINIMIZE indicates that the window may be iconified. + </para> + <para> +_NET_WM_ACTION_SHADE indicates that the window may be shaded. + </para> + <para> +_NET_WM_ACTION_STICK indicates that the window may have its sticky state +toggled (as for _NET_WM_STATE_STICKY). Note that this state has to do with +viewports, not desktops. + </para> + <para> +_NET_WM_ACTION_MAXIMIZE_HORZ indicates that the window may be maximized horizontally. + </para> + <para> +_NET_WM_ACTION_MAXIMIZE_VERT indicates that the window may be maximized vertically. + </para> + <para> +_NET_WM_ACTION_FULLSCREEN indicates that the window may be brought to + fullscreen state. + </para> + <para> +_NET_WM_ACTION_CHANGE_DESKTOP indicates that the window may be moved between desktops. + </para> + <para> +_NET_WM_ACTION_CLOSE indicates that the window may be closed (i.e. a _NET_CLOSE_WINDOW +message may be sent). + </para> + <para> +_NET_WM_ACTION_ABOVE indicates that the window may placed in the "above" layer of windows (i.e. will respond to _NET_WM_STATE_ABOVE changes; see also <xref linkend="STACKINGORDER"/> for details). + </para> + <para> +_NET_WM_ACTION_BELOW indicates that the window may placed in the "below" layer of windows (i.e. will respond to _NET_WM_STATE_BELOW changes; see also <xref linkend="STACKINGORDER"/> for details)). + </para> +</sect2> + +<sect2><title>_NET_WM_STRUT</title> + <programlisting id="NETWMSTRUT"><![CDATA[ +_NET_WM_STRUT, left, right, top, bottom, CARDINAL[4]/32 +]]></programlisting> + <para> +This property is equivalent to a _NET_WM_STRUT_PARTIAL property where all start +values are 0 and all end values are the height or width of the logical screen. +_NET_WM_STRUT_PARTIAL was introduced later than _NET_WM_STRUT, however, so +clients MAY set this property in addition to _NET_WM_STRUT_PARTIAL to ensure +backward compatibility with Window Managers supporting older versions of the +Specification. + </para> +</sect2> +<sect2><title>_NET_WM_STRUT_PARTIAL</title> + <programlisting id="NETWMSTRUTPARTIAL"><![CDATA[ +_NET_WM_STRUT_PARTIAL, left, right, top, bottom, left_start_y, left_end_y, +right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, +bottom_end_x,CARDINAL[12]/32 +]]></programlisting> + <para> +This property MUST be set by the Client if the window is to reserve space at the +edge of the screen. The property contains 4 cardinals specifying the width of +the reserved area at each border of the screen, and an additional 8 cardinals +specifying the beginning and end corresponding to each of the four struts. The +order of the values is left, right, top, bottom, left_start_y, left_end_y, +right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, +bottom_end_x. All coordinates are root window coordinates. The client MAY change +this property at any time, therefore the Window Manager MUST watch for +property notify events if the Window Manager uses this property to assign +special semantics to the window. + </para> + <para> +If both this property and the _NET_WM_STRUT property are set, the Window Manager +MUST ignore the _NET_WM_STRUT property values and use instead the values for +_NET_WM_STRUT_PARTIAL. This will ensure that Clients can safely set both +properties without giving up the improved semantics of the new property. + </para> + <para> +The purpose of struts is to reserve space at the borders of the +desktop. This is very useful for a docking area, a taskbar or a panel, +for instance. The Window Manager should take this reserved area into +account when constraining window positions - maximized windows, for +example, should not cover that area. + </para> + <para> +The start and end values associated with each strut allow areas to be +reserved which do not span the entire width or height of the screen. +Struts MUST be specified in root window coordinates, that is, they are +<emphasis>not</emphasis> relative to the edges of any view port or Xinerama +monitor. + </para> + <para> +For example, for a panel-style Client appearing at the bottom of the +screen, 50 pixels tall, and occupying the space from 200-600 pixels +from the left of the screen edge would set a bottom strut of 50, and +set bottom_start_x to 200 and bottom_end_x to 600. Another example is +a panel on a screen using the Xinerama extension. Assume that the set +up uses two monitors, one running at 1280x1024 and the other to the +right running at 1024x768, with the top edge of the two physical +displays aligned. If the panel wants to fill the entire bottom edge +of the smaller display with a panel 50 pixels tall, it should set a +bottom strut of 306, with bottom_start_x of 1280, and bottom_end_x of +2303. Note that the strut is relative to the screen edge, and not the +edge of the xinerama monitor. + </para> + <para> +Rationale: A simple "do not cover" hint is not enough for dealing with e.g. +auto-hide panels. + </para> + <para> +Notes: An auto-hide panel SHOULD set the strut to be its minimum, hidden size. +A "corner" panel that does not extend for the full length of a screen border +SHOULD only set one strut. + </para> +</sect2> +<sect2><title>_NET_WM_ICON_GEOMETRY</title> +<programlisting><![CDATA[ +_NET_WM_ICON_GEOMETRY, x, y, width, height, CARDINAL[4]/32 +]]></programlisting> + <para> +This optional property MAY be set by stand alone tools like a taskbar or an +iconbox. It specifies the geometry of a possible icon in case the window is iconified. + </para> + <para> +Rationale: This makes it possible for a Window Manager to display a nice +animation like morphing the window into its icon. + </para> + </sect2> + <sect2> + <title>_NET_WM_ICON</title> + <programlisting><![CDATA[ +_NET_WM_ICON CARDINAL[][2+n]/32 +]]></programlisting> + <para> +This is an array of possible icons for the client. This specification does +not stipulate what size these icons should be, but individual desktop +environments or toolkits may do so. The Window Manager MAY scale any of these +icons to an appropriate size. + </para> + <para> +This is an array of 32bit packed CARDINAL ARGB with high byte being A, low +byte being B. The first two cardinals are width, height. Data is in rows, left to +right and top to bottom. + </para> + </sect2> + <sect2> + <title>_NET_WM_PID</title> + <programlisting><![CDATA[ +_NET_WM_PID CARDINAL/32 +]]></programlisting> + <para> +If set, this property MUST contain the process ID of the client owning this +window. This MAY be used by the Window Manager to kill windows which do not +respond to the _NET_WM_PING protocol. + </para> + <para> +If _NET_WM_PID is set, the ICCCM-specified property WM_CLIENT_MACHINE +MUST also be set. While the ICCCM only requests that WM_CLIENT_MACHINE is set +<quote> to a string that forms the name of the machine running the client as +seen from the machine running the server</quote> conformance to this +specification requires that WM_CLIENT_MACHINE be set to the fully-qualified domain +name of the client's host. + </para> + <para> +See also the implementation notes on <link linkend="KILLINGWINDOWS">killing hung processes</link>. + </para> + </sect2> + <sect2><title>_NET_WM_HANDLED_ICONS</title> + <programlisting><![CDATA[ +_NET_WM_HANDLED_ICONS +]]></programlisting> + <para> + This property can be set by a Pager on one of its own toplevel windows + to indicate that the Window Manager need not provide icons for + iconified windows, for example if it is a taskbar and provides buttons + for iconified windows. + </para> + </sect2> + <sect2><title>_NET_WM_USER_TIME</title> + <programlisting><![CDATA[ +_NET_WM_USER_TIME CARDINAL/32 +]]></programlisting> + <para> +This property contains the XServer time at which last user activity in this +window took place. + </para> + <para> +Clients should set this property on every new toplevel window (or on the window +pointed out by the _NET_WM_USER_TIME_WINDOW property), before mapping +the window, to the timestamp of the user interaction that caused the window to +appear. A client that only deals with core events, might, for example, use the +timestamp of the last KeyPress or ButtonPress event. ButtonRelease and +KeyRelease events should not generally be considered to be user interaction, +because an application may receive KeyRelease events from global keybindings, +and generally release events may have later timestamp than actions that were +triggered by the matching press events. Clients can obtain the timestamp that +caused its first window to appear from the DESKTOP_STARTUP_ID environment +variable, if the app was launched with startup notification. If the client does +not know the timestamp of the user interaction that caused the first window to +appear (e.g. because it was not launched with startup notification), then it +should not set the property for that window. The special value of zero on a +newly mapped window can be used to request that the window not be initially +focused when it is mapped. + </para> + <para> +If the client has the active window, it should also update this property +on the window whenever there's user activity. + </para> + <para> +Rationale: This property allows a Window Manager to alter the focus, +stacking, and/or placement behavior of windows when they are +mapped depending on whether the new window was created by a user +action or is a "pop-up" window activated by a timer or some other +event. + </para> + </sect2> + + <sect2><title>_NET_WM_USER_TIME_WINDOW</title> + <programlisting><![CDATA[ +_NET_WM_USER_TIME_WINDOW WINDOW/32 +]]></programlisting> + <para> +This property contains the XID of a window on which the client sets +the _NET_WM_USER_TIME property. Clients should check whether the +window manager supports _NET_WM_USER_TIME_WINDOW and fall back to +setting the _NET_WM_USER_TIME property on the toplevel window if it +doesn't. + </para> + <para> +Rationale: Storing the frequently changing _NET_WM_USER_TIME property +on the toplevel window itself causes every application that is +interested in any of the properties of that window to be woken up +on every keypress, which is particularly bad for laptops running on +battery power. + </para> + </sect2> + + <sect2><title>_NET_FRAME_EXTENTS</title> + <programlisting><![CDATA[ +_NET_FRAME_EXTENTS, left, right, top, bottom, CARDINAL[4]/32 +]]></programlisting> + <para> +The Window Manager MUST set _NET_FRAME_EXTENTS to the extents of the +window's frame. left, right, top and bottom are widths of the +respective borders added by the Window Manager. + </para> + </sect2> + + <sect2><title>_NET_WM_OPAQUE_REGION</title> + <programlisting><![CDATA[ +_NET_WM_OPAQUE_REGION, x, y, width, height, CARDINAL[][4]/32 +]]></programlisting> + <para> +The Client MAY set this property to a list of 4-tuples [x, y, width, +height], each representing a rectangle in window coordinates where the +pixels of the window's contents have a fully opaque alpha value. If +the window is drawn by the compositor without adding any transparency, +then such a rectangle will occlude whatever is drawn behind it. When +the window has an RGB visual rather than an ARGB visual, this property +is not typically useful, since the effective opaque region of a +window is exactly the bounding region of the window as set via the +shape extension. For windows with an ARGB visual and also a bounding +region set via the shape extension, the effective opaque region is +given by the intersection of the region set by this property and the +bounding region set via the shape extension. The compositing manager +MAY ignore this hint. + </para> + <para> +Rationale: This gives the compositing manager more room for optimizations. +For example, it can avoid drawing occluded portions behind the window. + </para> + </sect2> +</sect1> +<sect1> + <title>Window Manager Protocols</title> + <sect2> + <title>_NET_WM_PING</title> + <para> +This protocol allows the Window Manager to determine if the Client is still +processing X events. This can be used by the Window Manager to determine if a +window which fails to close after being sent WM_DELETE_WINDOW has stopped +responding or has stalled for some other reason, such as waiting for user +confirmation. A Client SHOULD indicate that it is willing to participate in +this protocol by listing _NET_WM_PING in the WM_PROTOCOLS property of the +client window. + </para> + <para> +A Window Manager can use this protocol at any time by sending a client message +as follows: + </para> + <programlisting><![CDATA[ +type = ClientMessage +window = the respective client window +message_type = WM_PROTOCOLS +format = 32 +data.l[0] = _NET_WM_PING +data.l[1] = timestamp +data.l[2] = the respective client window +other data.l[] elements = 0 +]]></programlisting> + <para> +A participating Client receiving this message MUST send it back to the root +window immediately, by setting window = root, and calling XSendEvent with +the same event mask like all other root window messages in this specification use. +The Client MUST NOT alter any field in the event other than the window. This +includes all 5 longs in the data.l[5] array. The Window Manager can uniquely +identify the ping by the timestamp and the data.l[2] field if necessary. +Note that some older clients may not preserve data.l[2] through data.l[4]. + </para> + <para> +The Window Manager MAY kill the Client (using _NET_WM_PID) if it fails to +respond to this protocol within a reasonable time. + </para> + <para> +See also the implementation notes on <link linkend="KILLINGWINDOWS">killing hung processes</link>. + </para> + </sect2> + <sect2> + <title>_NET_WM_SYNC_REQUEST</title> + <para> +This protocol uses the XSync extension (see <ulink +url="http://freedesktop.org/cgi-bin/viewcvs.cgi/xorg/xc/doc/hardcopy/Xext/sync.PS.gz">the +protocol specification</ulink> and <ulink +url="http://freedesktop.org/cgi-bin/viewcvs.cgi/xorg/xc/doc/hardcopy/Xext/synclib.PS.gz"> +the library documentation</ulink>) to let client and window manager +synchronize the repaint of the window manager frame and the client +window. A client indicates that it is willing to participate in the +protocol by listing _NET_WM_SYNC_REQUEST in the WM_PROTOCOLS property +of the client window and storing the XID of an XSync counter in the +property _NET_WM_SYNC_REQUEST_COUNTER. The initial value of this +counter is not defined by this specification. + </para> + <para> +A window manager uses this protocol by preceding a ConfigureNotify +event sent to a client by a client message as follows: + </para> + <programlisting><![CDATA[ +type = ClientMessage +window = the respective client window +message_type = WM_PROTOCOLS +format = 32 +data.l[0] = _NET_WM_SYNC_REQUEST +data.l[1] = timestamp +data.l[2] = low 32 bits of the update request number +data.l[3] = high 32 bits of the update request number +other data.l[] elements = 0 +]]></programlisting> + + <para> +After receiving one or more such message/ConfigureNotify pairs, and +having handled all repainting associated with the ConfigureNotify +events, the client MUST set the _NET_WM_SYNC_REQUEST_COUNTER to the 64 +bit number indicated by the data.l[2] and data.l[3] fields of the last +client message received. + </para> + <para> +By using either the Alarm or the Await mechanisms of the XSync +extension, the window manager can know when the client has finished +handling the ConfigureNotify events. The window manager SHOULD not +resize the window faster than the client can keep up. + </para> + <para> +The update request number in the client message is determined by the +window manager subject to the restriction that it MUST NOT be 0. The +number is generally intended to be incremented by one for each message +sent. Since the initial value of the XSync counter is not defined by +this specification, the window manager MAY set the value of the XSync +counter at any time, and MUST do so when it first manages a new +window. + </para> + </sect2> + <sect2> + <title>_NET_WM_FULLSCREEN_MONITORS</title> + <programlisting><![CDATA[ +_NET_WM_FULLSCREEN_MONITORS, CARDINAL[4]/32 +]]></programlisting> + <para> +A read-only list of 4 monitor indices indicating the top, bottom, left, and +right edges of the window when the fullscreen state is enabled. The indices +are from the set returned by the Xinerama extension. + </para> + <para> +Windows transient for the window with _NET_WM_FULLSCREEN_MONITORS set, such as +those with type _NEW_WM_WINDOW_TYPE_DIALOG, are generally expected to be +positioned (e.g. centered) with respect to only one of the monitors. This +might be the monitor containing the mouse pointer or the monitor containing the +non-full-screen window. + </para> + <para> +A Client wishing to change this list MUST send a _NET_WM_FULLSCREEN_MONITORS +client message to the root window. The Window Manager MUST +keep this list updated to reflect the current state of the window. + </para> +<programlisting><![CDATA[ + window = the respective client window + message_type = _NET_WM_FULLSCREEN_MONITORS + format = 32 + data.l[0] = the monitor whose top edge defines the top edge of the fullscreen window + data.l[1] = the monitor whose bottom edge defines the bottom edge of the fullscreen window + data.l[2] = the monitor whose left edge defines the left edge of the fullscreen window + data.l[3] = the monitor whose right edge defines the right edge of the fullscreen window + data.l[4] = source indication +]]></programlisting> + <para> +See <xref linkend="sourceindication"/> for details on the source indication. + </para> + <para> +Virtual machine software may use this hint to have a virtual operating system +instance that sees multiple monitors. The application window stretches over +several monitors, giving the appearance that these monitors have been taken +over by the guest virtual machine. + </para> + <para> +This hint might also be used by a movie or presentation application allowing +users to display the media spanned over several monitors. + </para> + <para> +In both cases, the application would have some user interface allowing users +to configure which monitors the application fullscreens to. The window manager +need not provide such an interface, though it could. + </para> + <para> +In the event of a change in monitor configuration, the application is +responsible for re-computing the monitors on which it wants to appear. +The window manager may continue using the same monitor indices as before +or simply clear the list, returning to "normal" fullscreen. + </para> + </sect2> +</sect1> + + +<sect1> + <title>Other Properties</title> + <sect2> + <title>_NET_WM_FULL_PLACEMENT</title> + <para> +By including this hint in _NET_SUPPORTED the Window Manager announces +that it performs reasonable window placement for all window types it supports +(for example centering dialogs on the mainwindow or whatever handling the +Window Manager considers reasonable). This in turn means that Clients, +when they detect that this hint is supported, SHOULD NOT abuse or often even +use PPosition and USPosition hints for requesting placement. In particular: + </para> +<itemizedlist> +<listitem><para>USPosition is reserved to be used only to indicate that the position was +specified by the user and MUST NOT be used for anything else (see ICCCM +section 4.1.2.3 for details)</para></listitem> +<listitem><para>PPosition SHOULD be used for for specifying position only if a specific +position should be used. Position SHOULD NOT be specified for "default" +placement such as centering dialog windows on their mainwindow.</para></listitem> +</itemizedlist> + <para> +Rationale: Window managers can often perform better placement (that may be +even configurable) for windows than the application. However at the time of +writing this it is problematic for Window managers to decide when to use them +because many applications abuse positioning flags and/or provide unnecessary +default positions. + </para> + <para> +Note: The property is not used anywhere else besides being listed in _NET_SUPPORTED. + </para> + </sect2> +</sect1> + +<sect1> + <title>Compositing Managers</title> + <para> +A compositing manager is an X client that uses the Composite extension +to redirect all windows to offscreen pixmaps, and the Damage extension +to track when painting occur on those offscreen pixmaps. It is the +responsibility of the compositing manager to paint the pixmaps on the +screen, possibly adding effects like translucency or deformations. +</para> + <para> +This section specifies interactions between compositing managers +and applications. +</para> + <sect2> + <title>_NET_WM_CM_S<literal>n</literal> Manager Selection</title> + <para> +For each screen they manage, compositing manager MUST acquire +ownership of a selection named _NET_WM_CM_S<literal>n</literal>, where +<literal>n</literal> is the screen number. Compositing managers MUST +comply with the conventions for "Manager Selections" described in +section 2.8 of the <citation><link linkend="ICCCM">ICCCM</link></citation>. +</para> + </sect2> + <sect2> + <title>WM_TRANSIENT_FOR for override-redirect windows</title> + <para> +The WM_TRANSIENT_FOR property is defined by the <citation><link +linkend="ICCCM">ICCCM</link></citation>.for managed windows. This +specification extends the use of the property to override-redirect +windows. If an override-redirect is a pop-up on behalf of another +window, then the Client SHOULD set WM_TRANSIENT_FOR on the +override-redirect to this other window. + </para> + <para> +As an example, a Client should set WM_TRANSIENT_FOR on dropdown menus +to the toplevel application window that contains the menubar. + </para> + </sect2> +</sect1> +<sect1> + <title>Implementation notes</title> + <sect2> + <title>Desktop/workspace model</title> + <para> +This spec assumes a desktop model that consists of one or more completely +independent desktops which may or may not be larger than the screen area. +When a desktop is larger than the screen it is left to the Window Manager if +it will implement scrolling or paging. + </para> + </sect2> + <sect2> + <title>File Manager desktop</title> + <para> +This spec suggests implementing the file manager desktop by mapping a +desktop-sized window (no shape) to all desktops, with +_NET_WM_WINDOW_TYPE_DESKTOP. This makes the desktop focusable and greatly +simplifies implementation of the file manager. It is also faster than +managing lots of small shaped windows. The file manager draws the background +on this window. There should be a root property with a window handle for use +in applications that want to draw the background (xearth). + </para> + </sect2> + <sect2> + <title>Implementing enhanced support for application transient windows</title> + <para> +If the WM_TRANSIENT_FOR property is set to None or Root window, the window +should be treated as a transient for all other windows in the same group. It +has been noted that this is a slight ICCCM violation, but as this behavior is +pretty standard for many toolkits and window managers, and is extremely +unlikely to break anything, it seems reasonable to document it as standard. + </para> + </sect2> + <sect2 id="URGENCY"> + <title>Urgency</title> + <para> +Windows expecting immediate user action should indicate this using the +urgency bit in the WM_HINTS.flags property, as defined in the ICCCM. + </para> + </sect2> + <sect2 id="NORESIZE"> + <title>Fixed size windows</title> + <para> + Windows can indicate that they are non-resizable by setting minheight = maxheight and minwidth = maxwidth in the ICCCM WM_NORMAL_HINTS property. The Window Manager MAY decorate such windows differently. + </para> + </sect2> + <sect2> + <title>Pagers and Taskbars</title> + <para> + This specification attempts to make reasonable provisions for window + manager independent pagers and taskbars. Window Managers that require + / desire additional functionality beyond what can be achieved using the + mechanisms set out in this specification may choose to implement their + own pagers, which communicate with the Window Manager using further, + window manager specific hints, or some other means. + </para> + <para> + Pagers should decide whether to show a miniature version of a + window using the following guidelines: + <itemizedlist> + <listitem> + <para> + If either _NET_WM_STATE_SKIP_PAGER or + _NET_WM_STATE_HIDDEN are set on a window, then the + pager should not show that window. + </para> + </listitem> + <listitem> + <para> + The pager may choose not to display windows with + certain semantic types; this spec has no + recommendations, but common practice is to avoid + displaying _NET_WM_WINDOW_TYPE_DOCK for example. + </para> + </listitem> + <listitem> + <para> + If the _NET_WM_STATE_SKIP_PAGER and + _NET_WM_STATE_HIDDEN hints are not present, and the + Window Manager claims to support _NET_WM_STATE_HIDDEN, + then the window should be shown if it's in either + NormalState or IconicState. + </para> + </listitem> + <listitem> + <para> + For Window Managers that do not support + _NET_WM_STATE_HIDDEN, the pager should + not show windows in IconicState. These Window + Managers are probably using an older version + of this specification. + </para> + </listitem> + </itemizedlist> + </para> + </sect2> + <sect2> + <title>Window Geometry</title> + <para> +Window manager implementors should refer to the ICCCM for definitive +specifications of how to handle MapRequest and ConfigureRequest events. +However, since these aspects of the ICCCM are easily misread, this +document offers the following clarifications: + </para> + <itemizedlist> + <listitem><para> +Window Managers MUST honor the win_gravity field of WM_NORMAL_HINTS +for both MapRequest <emphasis>and</emphasis> ConfigureRequest events +(ICCCM Version 2.0, §4.1.2.3 and §4.1.5) + </para></listitem> + <listitem><para> +When generating synthetic ConfigureNotify events, the position given +MUST be the top-left corner of the client window in relation to the +origin of the root window (i.e., ignoring win_gravity) +(ICCCM Version 2.0, §4.2.3) + </para></listitem> + <listitem><para> +Window Managers maintain a reference point for each client window and place +the window relative to this reference point depending on the window's +win_gravity as follows: + </para> + <informaltable> + <tgroup cols="2"> + <tbody> + <row> + <entry>win_gravity:</entry> + <entry>placed at the reference point</entry> + </row> + <row> + <entry>StaticGravity</entry> + <entry>the left top corner of the client window</entry> + </row> + <row> + <entry>NorthWestGravity</entry> + <entry>the left top corner of the frame window</entry> + </row> + <row> + <entry>NorthGravity</entry> + <entry>the center of the frame window's top side</entry> + </row> + <row> + <entry>NorthEastGravity</entry> + <entry>the right top corner of the frame window</entry> + </row> + <row> + <entry>EastGravity</entry> + <entry>the center of the frame window's right side</entry> + </row> + <row> + <entry>SouthEastGravity</entry> + <entry>the right bottom corner of the frame window</entry> + </row> + <row> + <entry>SouthGravity</entry> + <entry>the center of the frame window's bottom side</entry> + </row> + <row> + <entry>SouthWestGravity</entry> + <entry>the left bottom corner of the frame window</entry> + </row> + <row> + <entry>WestGravity</entry> + <entry>the center of the frame window's left side</entry> + </row> + <row> + <entry>CenterGravity</entry> + <entry>the center of the frame window</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </listitem> + <listitem><para> +Applications are free to change their win_gravity setting at any time. + </para> + <para> +If an Application changes its win_gravity then the Window Manager should +adjust the reference point, so that the client window will not move as the +result. For example if the Application's win_gravity was NorthWestGravity and +reference point was at the top-left corner of the frame window, then after +change of win_gravity to SouthEastGravity the reference point should be +adjusted to point to the lower-right corner of the frame. + </para> + <note> + <para> +Changing the win_gravity for a single configure request and back afterwards is +unlikely to work as intended, due to a race condition. The window manager sees +a property notify for WM_NORMAL_HINTS, followed by the configure request, +followed by another property notify for WM_NORMAL_HINTS. By the time the +window manager gets around to request the changed WM_NORMAL_HINTS in response +to the first property notify, the server may have already processed the second +property change. + </para> + <para> +If the window manager supports it, applications should use +_NET_MOVERESIZE_WINDOW with a specified gravity to avoid this problem. + </para> + </note> + </listitem> + <listitem><para> +If the Application requests a new position (x, y) (and possibly also a +new size), the Window Manager calculates a new reference point (ref_x, ref_y), +based on the client window's (possibly new) size (width, height), border +width (bw) and win_gravity as explained in the table below. + </para> + <para> +The Window Manager will use the new reference point until the next request for +a new position. + </para> + <informaltable> + <tgroup cols="3"> + <tbody> + <row> + <entry>win_gravity:</entry> + <entry>ref_x:</entry> + <entry>ref_y:</entry> + </row> + <row> + <entry>StaticGravity</entry> + <entry>x</entry> + <entry>y</entry> + </row> + <row> + <entry>NorthWestGravity</entry> + <entry>x-bw</entry> + <entry>y-bw</entry> + </row> + <row> + <entry>NorthGravity</entry> + <entry>x+(width/2)</entry> + <entry>y-bw</entry> + </row> + <row> + <entry>NorthEastGravity</entry> + <entry>x+width+bw</entry> + <entry>y-bw</entry> + </row> + <row> + <entry>EastGravity</entry> + <entry>x+width+bw</entry> + <entry>y+(height/2)</entry> + </row> + <row> + <entry>SouthEastGravity</entry> + <entry>x+width+bw</entry> + <entry>y+height+bw</entry> + </row> + <row> + <entry>SouthGravity</entry> + <entry>x+(width/2)</entry> + <entry>y+height+bw</entry> + </row> + <row> + <entry>SouthWestGravity</entry> + <entry>x-bw</entry> + <entry>y+height+bw</entry> + </row> + <row> + <entry>WestGravity</entry> + <entry>x-bw</entry> + <entry>y+(height/2)</entry> + </row> + <row> + <entry>CenterGravity</entry> + <entry>x+(width/2)</entry> + <entry>y+(height/2)</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </listitem> + <listitem><para> +If an Application requests just a new size, its reference point does not +move. So for example if client window has win_gravity SouthEastGravity and +is resized, the bottom right corner of its frame will not move but instead +the top left corner will be adjusted by the difference in size. + </para></listitem> + <listitem><para> +When calculating the reference point at the time of initial placement, +the Window Manager should take the initial window's size into consideration, +as if it was the frame for this window. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Window-in-Window MDI</title> + <para> + The authors of this specification acknowledge that there is no standard + method to allow the Window Manager to manage windows that are part of a + Window-in-Window MDI application. Application authors are advised to + use some other form of MDI, or to propose a mechanism to be included in + a future revision of this specification. + </para> + </sect2> + <sect2 id="KILLINGWINDOWS"> + <title>Killing Hung Processes</title> + <para> +If processes fail to respond to the _NET_WM_PING protocol _NET_WM_PID may be +used in combination with the ICCCM specified WM_CLIENT_MACHINE to +attempt to kill a process. + </para> + + <para> +WM_CLIENT_MACHINE is usually set by calling XSetWMProperties(). The hostname for the current host can be be retrieved using gethostname(), when gethostname() +is not available on the platform implementors may use the value of the +nodename field of struct utsname as returned by uname(). Note also that the value of WM_CLIENT_MACHINE is not guaranteed +to be a fully fully-qualified domain name of the host. An example of how to +retrieve the hostname: + </para> + <para> + <programlisting><![CDATA[ +int net_get_hostname (char *buf, size_t maxlen) +{ +#ifdef HAVE_GETHOSTNAME + if (buf == NULL) return 0; + + gethostname (buf, maxlen); + buf [maxlen - 1] = '\0'; + + return strlen(buf); +#else + struct utsname name; + size_t len; + + if (buf == NULL) return 0; + + uname (&name); + len = strlen (name.nodename); + + if (len >= maxlen) len = maxlen - 1; + strncpy (buf, name.nodename, len); + buf[len] = '\0'; + + return len; +#endif +} +]]></programlisting> + </para> + </sect2> + + <sect2 id="STACKINGORDER"> + <title>Stacking order</title> + <para> + To obtain good interoperability between different Desktop Environments, + the following layered stacking order is recommended, from the bottom: + <itemizedlist> + <listitem><para>windows of type _NET_WM_TYPE_DESKTOP</para></listitem> + <listitem><para>windows having state _NET_WM_STATE_BELOW</para></listitem> + <listitem><para>windows not belonging in any other layer</para></listitem> + <listitem><para>windows of type _NET_WM_TYPE_DOCK (unless they have + state _NET_WM_TYPE_BELOW) and windows having state + _NET_WM_STATE_ABOVE</para></listitem> + <listitem><para>focused windows having state + _NET_WM_STATE_FULLSCREEN</para></listitem> + </itemizedlist> + </para> + <para> + Windows that are transient for another window should be kept + above this window. + </para> + <para> + The window manager may choose to put some windows in different + stacking positions, for example to allow the user to bring currently + a active window to the top and return it back when the window looses + focus. + </para> + </sect2> + + <sect2 id="sourceindication"> + <title>Source indication in requests</title> + <para> + Some requests from Clients include type of the Client, for example + the _NET_ACTIVE_WINDOW message. Currently the types can be + 1 for normal applications, and 2 for pagers and other Clients + that represent direct user actions (the Window Manager may decide + to treat requests from applications differently than requests + that are result of direct user actions). + Clients that support only older version of this spec will have 0 + as their source indication, thus not specifying their source at all. + This also may mean that some of the fields in the message comply + only with the older specification version. + </para> + </sect2> + </sect1> + <sect1> + <title>References</title> + <variablelist> + <varlistentry> + <term>[UTF8]</term> + <listitem> + <para id="UTF8"> + F. Yergeau,"UTF-8, a transformation format of ISO 10646", RFC 2279 + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>[ICCCM]</term> + <listitem> + <para id="ICCCM"> + David Rosenthal and Stuart W. Marks, "Inter-Client Communication + Conventions Manual (Version 2.0)", X Consortium Standard, X Version 11, + Release 6.3 + </para> + </listitem> + </varlistentry> + </variablelist> + </sect1> + <sect1> + <title>Copyright</title> + <para> +Copyright (C) 2000-2003 See Contributors List + </para> + <para> +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following +conditions: + </para> + <para> +The above copyright notice and this permission notice shall +be included in all copies or substantial portions of the +Software. + </para> + <para> +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + </para> + </sect1> + <sect1> + <title>Contributors</title> + + <para>Sasha Vasko</para> + <para>Bradley T. Hughes</para> + <para>Dominik Vogt</para> + <para>Havoc Pennington</para> + <para>Jeff Raven</para> + <para>Jim Gettys</para> + <para>John Harper</para> + <para>Julian Adams</para> + <para>Matthias Ettrich</para> + <para>Micheal Rogers</para> + <para>Nathan Clemons</para> + <para>Tim Janik</para> + <para>Tomi Ollila</para> + <para>Sam Lantinga</para> + <para>The Rasterman</para> + <para>Paul Warren</para> + <para>Owen Taylor</para> + <para>Marko Macek</para> + <para>Greg Badros</para> + <para>Matthias Clasen</para> + <para>David Rosenthal</para> + <para>Lubos Lunak</para> + <para>Rob Adams</para> + <para>Thomas Fitzsimmons</para> + <para>Olivier Chapuis</para> + <para>Søren Sandmann</para> + <para>Grant Patterson</para> + </sect1> + <sect1> + <title>Change history</title> + <sect2> + <title>Changes since 1.4draft</title> + <itemizedlist> + <listitem><para> +Added _NET_WM_STATE_FOCUSED. + </para></listitem> + <listitem><para> +Added _NET_WM_OPAQUE_REGION + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.3</title> + <itemizedlist> + <listitem><para> +Added _NET_WM_MOVERESIZE_CANCEL. + </para></listitem> + <listitem><para> +New window types to be used on override-redirect windows: +_NET_WM_WINDOW_TYPE_DROPDOWN_MENU, _NET_WM_WINDOW_TYPE_POPUP_MENU, +_NET_WM_WINDOW_TYPE_TOOLTIP, _NET_WM_WINDOW_TYPE_NOTIFICATION, +_NET_WM_WINDOW_TYPE_COMBO, and _NET_WM_WINDOW_TYPE_DND + </para></listitem> + <listitem><para> +New _NET_WM_CM_Sn manager selection for compositing managers. + </para></listitem> + <listitem><para> +Added note WM_TRANSIENT_FOR for override-redirect windows + </para></listitem> + <listitem><para> +Added _NET_WM_USER_TIME_WINDOW. + </para></listitem> + <listitem><para> +Added _NET_WM_FULL_PLACEMENT. + </para></listitem> + <listitem><para> +Added _NET_WM_FULLSCREEN_MONITORS. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.2</title> + <itemizedlist> + <listitem><para> +Added source indication to _NET_CLOSE_WINDOW, _NET_WM_MOVERESIZE, +_NET_MOVERESIZE_WINDOW, _NET_WM_DESKTOP and _NET_WM_STATE message. + </para></listitem> + <listitem><para> +Added _NET_WM_SYNC_REQUEST to allow synchronized repaint of +application window and window manager frame during opaque resize. + </para></listitem> + <listitem><para> +Added _NET_REQUEST_FRAME_EXTENTS and _NET_FRAME_EXTENTS to allow a +client to retrieve its window's frame extents. + </para></listitem> + <listitem><para> +Added new state _NET_WM_STATE_DEMANDS_ATTENTION. + </para></listitem> + <listitem><para> +Added timestamp, source indication and requestor's active window +fields to the _NET_ACTIVE_WINDOW message. + </para></listitem> + <listitem><para> +Added _NET_RESTACK_WINDOW message. + </para></listitem> + <listitem><para> +Added new property _NET_WM_STRUT_PARTIAL to allow partial-width struts. + </para></listitem> + <listitem><para> +Rewrote the implementation notes on "Window Movement", retitled it +to "Window Geometry". + </para></listitem> + <listitem><para> +Rewrote the implementation notes on "Urgency", making it clear that +the hint is not just about dialogs. + </para></listitem> + <listitem><para> +Fixed the specification of the X and Y members of _NET_DESKTOP_LAYOUT +and renamed them to columns and row for clarity. + </para></listitem> + <listitem><para> +Change the description of _NET_WM_STATE_MODAL to no longer require apps to +break the ICCCM for group-modal windows, but still support the +WM_TRANSIENT_FOR=root dialect. + </para></listitem> + <listitem><para> +Specified that (yet) unused fields in client messages must be set to 0. + </para></listitem> + <listitem><para> +_NET_WM_PING message now has the client window identified in data.l[2] field. + </para></listitem> + <listitem><para> +Added _NET_WM_USER_TIME to detect user activity in windows. + </para></listitem> + <listitem><para> +Explicitly specify that the window manager should restore original geometry +when _NET_WM_STATE_FULLSCREEN is reset. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.1</title> + <itemizedlist> + <listitem><para> + Changed WM_CLIENT_NAME(STRING) from suggested to required for _NET_WM_PID. + </para></listitem> + <listitem><para> + Specification and sample code for the content of WM_CLIENT_NAME(STRING). + </para></listitem> + <listitem><para> + Added _NET_WM_WINDOW_TYPE_SPLASH, _NET_WM_WINDOW_TYPE_UTILITY. + </para></listitem> + <listitem><para> + Added _NET_WM_STATE_FULLSCREEN. + </para></listitem> + <listitem><para> + Added _NET_WM_ALLOWED_ACTIONS. + </para></listitem> + <listitem><para> + Added _NET_WM_STATE_HIDDEN and clarified purpose of + _NET_WM_STATE_SKIP_PAGER and _NET_WM_STATE_SKIP_TASKBAR. Changed + section on virtual desktop implementation to suggest ICCCM compliance + regarding IconicState, using _NET_WM_STATE_HIDDEN to avoid confusion. + Added implementation note for pagers on when to display a window. + </para></listitem> + <listitem><para> + Added button field and new directions for keyboard-initiated actions + to the _NET_WM_MOVERESIZE message. + </para></listitem> + <listitem><para> + Added advice on removing _NET_WM_STATE and _NET_WM_DESKTOP when a window + is withdrawn. + </para></listitem> + <listitem><para> + Added _NET_DESKTOP_LAYOUT to allow a Pager to specify inter-desktop geometry. + </para></listitem> + <listitem><para> + Added _NET_SHOWING_DESKTOP. + </para></listitem> + <listitem><para> + Added _NET_WM_STATE_ABOVE and _NET_WM_STATE_BELOW and a recommended layered + stacking order. + </para></listitem> + <listitem><para> + Added _NET_MOVERESIZE_WINDOW. + </para></listitem> + <listitem><para> + Improve markup of citations. + </para></listitem> + <listitem><para> + Explain _NET_DESKTOP_GEOMETRY and _NET_WM_HANDLED_ICONS in more detail and + improve the explanation of WM_CLIENT_MACHINE in + <xref linkend="KILLINGWINDOWS"/>. + </para></listitem> + <listitem><para> + Add Lubos Lunak to the list of contributors. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.0</title> + <itemizedlist> + <listitem><para> +Fix doctype, add author info, update data. + </para></listitem> + <listitem><para> +Change specification description wording to be more inclusive, and to reflect the joint nature of the specification. + </para></listitem> + <listitem><para> +Fix miscellaneous typographical, grammar and spelling errors. + </para></listitem> + <listitem><para> +Clarified _NET_SUPPORTED to include ALL atoms, not just the property names. + </para></listitem> + <listitem><para> +Various corrections to use of MUST and SHOULD. + </para></listitem> + <listitem><para> +Fix problem in _NET_WM_ICON where 'bytes' should have been 'cardinals' + </para></listitem> + <listitem><para> +Replaced ISO-8559-1 characters with entities. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.0pre5</title> + <itemizedlist> + <listitem><para> +Change history moved to end. + </para></listitem> + <listitem><para> +UTF-8 Reference updated. + </para></listitem> + <listitem><para> +Window Gravity information updated. + </para></listitem> + <listitem><para> +Copyright Added. + </para></listitem> + <listitem><para> +Minor typo corrections. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.0pre4</title> + <itemizedlist> + <listitem><para> +Clarified the interpretation of client-provided geometries on large desktops. + </para></listitem> + <listitem><para> +Added more explanation for _NET_DESKTOP_NAMES. + </para></listitem> + <listitem><para> +Added _NET_WM_ICON_NAME and _NET_WM_VISIBLE_ICON_NAME. + </para></listitem> + <listitem><para> +Tried to improve the wording of _NET_WM_STRUT explanation. + </para></listitem> + <listitem><para> +Changed _NET_WORKAREA to an array of viewport-relative geometries. + </para></listitem> + <listitem><para> +Updated list of <quote>dependent</quote> properties for _NET_NUMBER_OF_DESKTOPS +to include _NET_WORKAREA and _NET_DESKTOP_VIEWPORT. + </para></listitem> + <listitem><para> +Tidied formatting of all client messages. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.0pre3</title> + <itemizedlist> + <listitem><para> +Added information about common non-ICCCM features. + </para></listitem> + <listitem><para> +Added explanation of sending messages to the root window. + </para></listitem> + <listitem><para> +Removed XA_ prefix from type names. + </para></listitem> + <listitem><para> +Clarified that <quote>mapping order</quote> refers to inital mapping +and specify the directions of both orders. + </para></listitem> + <listitem><para> +Clarified that desktops have a common size specified by _NET_DESKTOP_GEOMETRY. + </para></listitem> + <listitem><para> +Rewrote explanation of _NET_DESKTOP_VIEWPORT. + </para></listitem> + <listitem><para> +Tidied formatting of _NET_CURRENT_DESKTOP. + </para></listitem> + <listitem><para> +Replaced <quote>window handle</quote> by <quote>window ID</quote>. + </para></listitem> + <listitem><para> +Tidied formatting of _NET_WORKAREA. + </para></listitem> + <listitem><para> +Rewrote the motivation for _NET_VIRTUAL_ROOTS. + </para></listitem> + <listitem><para> +Added advice on Pointer grabs to _NET_WM_MOVERESIZE. + </para></listitem> + <listitem><para> +Fixed typos in _NET_WM_STATE. + </para></listitem> + <listitem><para> +Added _NET_WM_STATE_SKIP_PAGER. + </para></listitem> + <listitem><para> +Tidied formatting of _NET_WM_STRUT. + </para></listitem> + <listitem><para> +Tidied formatting of _NET_WM_ICON_GEOMETRY. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.0pre2</title> + <itemizedlist> + <listitem><para> +_NET_SET_NUMBER_OF_DESKTOPS -> _NET_NUMBER_OF_DESKTOPS for consistency. + </para></listitem> + <listitem><para> +_NET_WM_VISIBLE_NAME_STRING -> _NET_WM_VISIBLE_NAME for consistency. + </para></listitem> + <listitem><para> +_NET_WM_STATE: added explanation of permitted extensions. Added explanation of +being set / not set. + </para></listitem> + <listitem><para> +Spellchecked, corrected various typos. + </para></listitem> + <listitem><para> +UTF8 -> UTF-8 for consistency. + </para></listitem> + <listitem><para> +added references to the ICCCM an UTF-8 (incomplete). + </para></listitem> + <listitem><para> +added data and event formats where missing. + </para></listitem> + <listitem><para> +clarified _NET_SUPPORTING_WM_CHECK. + </para></listitem> + <listitem><para> +fixed formatting of _NET_CLOSE_WINDOW message. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.0pre1</title> + <itemizedlist> + <listitem><para> +Removed implementation note concerning Gnome's (potential) file manager behavior. + </para></listitem> + <listitem><para> +The Window Movement section of the implementation notes has been revised. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.9f</title> + <itemizedlist> + <listitem><para> +Revised revision number for first accepted release 1.9XX -> 1.0preXX. + </para></listitem> + <listitem><para> +Prerequisites for adoption of this specification added. + </para></listitem> + <listitem><para> +Tidied formatting of _NET_CURRENT_DESKTOP for consistency. + </para></listitem> + <listitem><para> +Tidied formatting of _NET_ACTIVE_WINDOW for consistency. Removed doubled text. + </para></listitem> + <listitem><para> +Tidied formatting of _NET_WM_DESKTOP for consistency. + </para></listitem> + <listitem><para> +Killing Hung Processes implementation note added. _NET_WM_PID and _NET_WM_PING now link to this. + </para></listitem> + <listitem><para> +Clarified x_root and y_root meaning for _NET_WM_MOVERESIZE. + </para></listitem> + <listitem><para> +Added contributor list. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.9e</title> + <itemizedlist> + <listitem><para> +Added _NET_WM_VISIBLE_NAME_STRING + </para></listitem> + <listitem><para> +Removed ambiguity from _NET_NUMBER_OF_DESKTOPS and _NET_DESKTOP_NAMES in combination. + </para></listitem> + <listitem><para> +Set _NET_WM_MOVERESIZE format to 32 for consistency. + </para></listitem> + <listitem><para> +Removed _NET_PROPERTIES. + </para></listitem> + <listitem><para> +Removed comment from _NET_WM_MOVERESIZE. + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.9d</title> + <itemizedlist> + <listitem><para> +Added _NET_VIRTUAL_ROOTS + </para></listitem> + <listitem><para> +Added note about ICCCM compliant window moves. + </para></listitem> + <listitem><para> +Added _NET_WM_HANDLED_ICONS + </para></listitem> + <listitem><para> +Added _NET_SUPPORTING_WM_CHECK + </para></listitem> + <listitem><para> +Removed degrees of activation + </para></listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Changes since 1.9c</title> + <itemizedlist> + <listitem> + <para> +Removed packaging of hints into 2 X properties. Jim Gettys points out that the +performance gains of fewer round trips can be better achieved using Xlib +routines. + </para> + </listitem> + <listitem> + <para> +Clarified that _NET_DESKTOP_VIEWPORT is in pixels + </para> + </listitem> + <listitem> + <para> +_NET_DESKTOP_VIEWPORT is now an array, one for each desktop, to allow for +different active viewports on different desktops + </para> + </listitem> + <listitem> + <para> +_NET_WM_STRUT now only applies on desktops on which the client is visible + </para> + </listitem> + <listitem> + <para> +Introduced RFC 2119 language, and attempted to clarify the roles of the Window +Manager, Pagers and Applications + </para> + </listitem> + <listitem> + <para> +Added _NET_WM_NAME + </para> + </listitem> + <listitem> + <para> +_NET_DESKTOP_NAMES now in UTF8 + </para> + </listitem> + <listitem> + <para> +Desktops now start from 0 + </para> + </listitem> + <listitem> + <para> +Added _NET_WM_PID + </para> + </listitem> + <listitem> + <para> +Added _NET_WM_PING protocol + </para> + </listitem> + <listitem> + <para> +Added _NET_WM_STATE_SKIP_TASKBAR + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Changes since 1.9b</title> + <itemizedlist> + <listitem><para>Removed _NET_NUMBER_OF_DESKTOPS client message, as it overlaps unnecessarily with _NET_{INSERT/DELETE}_DESKTOP.</para> + </listitem> + <listitem><para>Replaced _NET_WM_LAYER and _NET_WM_HINTS with _NET_WM_WINDOW_TYPE functional hint.</para></listitem> + <listitem><para>Changed _NET_WM_STATE to a list of atoms, for extensibility.</para></listitem> + <listitem><para>Expanded description of _NET_WORKAREA and _NET_WM_STRUT.</para></listitem> + <listitem><para>Removed _NET_WM_SIZEMOVE_NOTIFY protocol. </para></listitem> + <listitem><para>Added degrees of activation to _NET_ACTIVE_WINDOW client message</para></listitem> + <listitem><para>Added _NET_WM_ICON</para></listitem> + <listitem><para>My comments are in [[ ]]. Comments from Marko's draft are in [[MM: ]]</para></listitem> + </itemizedlist> + </sect2> + </sect1> +</article> + diff --git a/xembed/.cvsignore b/xembed/.cvsignore new file mode 100644 index 0000000..42016ba --- /dev/null +++ b/xembed/.cvsignore @@ -0,0 +1,17 @@ +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.log +config.status +config.rpath +config.sub +config.guess +config.h +config.h.in +configure +libtool +ltmain.sh +stamp-h* + + diff --git a/xembed/AUTHORS b/xembed/AUTHORS new file mode 100644 index 0000000..a8da608 --- /dev/null +++ b/xembed/AUTHORS @@ -0,0 +1,2 @@ +Test cases by Owen Taylor <otaylor@redhat.com> +Specification by Matthias Ettrich <ettrich@trolltech.com> and Owen Taylor diff --git a/xembed/ChangeLog b/xembed/ChangeLog new file mode 100644 index 0000000..530ee63 --- /dev/null +++ b/xembed/ChangeLog @@ -0,0 +1,22 @@ +Mon Apr 22 00:05:41 2002 Owen Taylor <otaylor@redhat.com> + + * tests/*: Expand the tests to tests recursively + nested embedders. + +Sun Apr 21 15:30:21 2002 Owen Taylor <otaylor@redhat.com> + + * spec/xembed-spec.xml: Typo fixes from Matthias Clasen, + spelling checked. + +Sun Apr 21 09:20:30 2002 Owen Taylor <otaylor@redhat.com> + + * Reorganize, add test cases in tests/ + +Sat Apr 20 15:46:27 2002 Owen Taylor <otaylor@redhat.com> + + * xembed-spec.xml: XML fixes. + +Sat Apr 20 13:00:18 2002 Owen Taylor <otaylor@redhat.com> + + * Import into CVS. + diff --git a/xembed/Makefile.am b/xembed/Makefile.am new file mode 100644 index 0000000..41b9ba0 --- /dev/null +++ b/xembed/Makefile.am @@ -0,0 +1,5 @@ +SUBDIRS = spec tests + +ACLOCAL_AMFLAGS = -I m4 + +EXTRA_DIST = config.rpath diff --git a/xembed/NEWS b/xembed/NEWS new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/xembed/NEWS diff --git a/xembed/README b/xembed/README new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/xembed/README diff --git a/xembed/acinclude.m4 b/xembed/acinclude.m4 new file mode 100644 index 0000000..0642754 --- /dev/null +++ b/xembed/acinclude.m4 @@ -0,0 +1,10178 @@ +## -*- autoconf -*- + +dnl This file is part of the KDE libraries/packages +dnl Copyright (C) 1997 Janos Farkas (chexum@shadow.banki.hu) +dnl (C) 1997,98,99 Stephan Kulow (coolo@kde.org) + +dnl This file is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Library General Public +dnl License as published by the Free Software Foundation; either +dnl version 2 of the License, or (at your option) any later version. + +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Library General Public License for more details. + +dnl You should have received a copy of the GNU Library General Public License +dnl along with this library; see the file COPYING.LIB. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +dnl IMPORTANT NOTE: +dnl Please do not modify this file unless you expect your modifications to be +dnl carried into every other module in the repository. If you decide that you +dnl really want to modify it, contact coolo@kde.org mentioning that you have +dnl and that the modified file should be committed to every module. +dnl +dnl Single-module modifications are best placed in configure.in for kdelibs +dnl and kdebase or configure.in.in if present. + +dnl ------------------------------------------------------------------------ +dnl Forward compatibility macros (make autoconf 2.13 look like 2.50), +dnl thanks to Raja R Harinath. +dnl ------------------------------------------------------------------------ +dnl +ifdef([_AC_PATH_X_XMKMF],[], + [AC_DEFUN([_AC_PATH_X_XMKMF],[AC_PATH_X_XMKMF])]) +ifdef([AC_OUTPUT_SUBDIRS],[], + [AC_DEFUN([AC_OUTPUT_SUBDIRS],[subdirs=$1; _AC_OUTPUT_SUBDIRS])]) + +# KDE_PATH_X_DIRECT +dnl Internal subroutine of AC_PATH_X. +dnl Set ac_x_includes and/or ac_x_libraries. +AC_DEFUN(KDE_PATH_X_DIRECT, +[if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +AC_TRY_CPP([#include <$x_direct_test_include>], +[# We can compile using X headers with no special include directory. +ac_x_includes=], +[# Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done]) +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +AC_TRY_LINK(, [${x_direct_test_function}()], +[LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries=], +[LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ + /usr/X11/lib \ + /usr/X11R6/lib \ + /usr/X11R5/lib \ + /usr/X11R4/lib \ + \ + /usr/lib/X11 \ + /usr/lib/X11R6 \ + /usr/lib/X11R5 \ + /usr/lib/X11R4 \ + \ + /usr/local/X11/lib \ + /usr/local/X11R6/lib \ + /usr/local/X11R5/lib \ + /usr/local/X11R4/lib \ + \ + /usr/local/lib/X11 \ + /usr/local/lib/X11R6 \ + /usr/local/lib/X11R5 \ + /usr/local/lib/X11R4 \ + \ + /usr/X386/lib \ + /usr/x386/lib \ + /usr/XFree86/lib/X11 \ + \ + /usr/lib \ + /usr/local/lib \ + /usr/unsupported/lib \ + /usr/athena/lib \ + /usr/local/x11r5/lib \ + /usr/lpp/Xamples/lib \ + /lib/usr/lib/X11 \ + \ + /usr/openwin/lib \ + /usr/openwin/share/lib \ + ; \ +do +dnl Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done]) +fi # $ac_x_libraries = NO +]) + + +dnl ------------------------------------------------------------------------ +dnl Find a file (or one of more files in a list of dirs) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN(AC_FIND_FILE, +[ +$3=NO +for i in $2; +do + for j in $1; + do + echo "configure: __oline__: $i/$j" >&AC_FD_CC + if test -r "$i/$j"; then + echo "taking that" >&AC_FD_CC + $3=$i + break 2 + fi + done +done +]) + +dnl KDE_FIND_PATH(programm-name, variable-name, list of directories, +dnl if-not-found, test-parameter) +AC_DEFUN(KDE_FIND_PATH, +[ + AC_MSG_CHECKING([for $1]) + if test -n "$$2"; then + kde_cv_path="$$2"; + else + kde_cache=`echo $1 | sed 'y%./+-%__p_%'` + + AC_CACHE_VAL(kde_cv_path_$kde_cache, + [ + kde_cv_path="NONE" + dirs="$3" + kde_save_IFS=$IFS + IFS=':' + for dir in $PATH; do + dirs="$dirs $dir" + done + IFS=$kde_save_IFS + + for dir in $dirs; do + if test -x "$dir/$1"; then + if test -n "$5" + then + evalstr="$dir/$1 $5 2>&1 " + if eval $evalstr; then + kde_cv_path="$dir/$1" + break + fi + else + kde_cv_path="$dir/$1" + break + fi + fi + done + + eval "kde_cv_path_$kde_cache=$kde_cv_path" + + ]) + + eval "kde_cv_path=\"`echo '$kde_cv_path_'$kde_cache`\"" + + fi + + if test -z "$kde_cv_path" || test "$kde_cv_path" = NONE; then + AC_MSG_RESULT(not found) + $4 + else + AC_MSG_RESULT($kde_cv_path) + $2=$kde_cv_path + + fi +]) + +AC_DEFUN(KDE_MOC_ERROR_MESSAGE, +[ + AC_MSG_ERROR([No Qt meta object compiler (moc) found! +Please check whether you installed Qt correctly. +You need to have a running moc binary. +configure tried to run $ac_cv_path_moc and the test didn't +succeed. If configure shouldn't have tried this one, set +the environment variable MOC to the right one before running +configure. +]) +]) + +AC_DEFUN(KDE_UIC_ERROR_MESSAGE, +[ + AC_MSG_WARN([No Qt ui compiler (uic) found! +Please check whether you installed Qt correctly. +You need to have a running uic binary. +configure tried to run $ac_cv_path_uic and the test didn't +succeed. If configure shouldn't have tried this one, set +the environment variable UIC to the right one before running +configure. +]) +]) + + +AC_DEFUN(KDE_CHECK_UIC_FLAG, +[ + AC_MSG_CHECKING([whether uic supports -$1 ]) + kde_cache=`echo $1 | sed 'y% .=/+-%____p_%'` + AC_CACHE_VAL(kde_cv_prog_uic_$kde_cache, + [ + cat >conftest.ui <<EOT + <!DOCTYPE UI><UI version="3" stdsetdef="1"></UI> +EOT + ac_uic_testrun="$UIC -$1 $2 conftest.ui >/dev/null" + if AC_TRY_EVAL(ac_uic_testrun); then + eval "kde_cv_prog_uic_$kde_cache=yes" + else + eval "kde_cv_prog_uic_$kde_cache=no" + fi + rm -f conftest* + ]) + + if eval "test \"`echo '$kde_cv_prog_uic_'$kde_cache`\" = yes"; then + AC_MSG_RESULT([yes]) + : + $3 + else + AC_MSG_RESULT([no]) + : + $4 + fi +]) + + +dnl ------------------------------------------------------------------------ +dnl Find the meta object compiler and the ui compiler in the PATH, +dnl in $QTDIR/bin, and some more usual places +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN(AC_PATH_QT_MOC_UIC, +[ + qt_bindirs="" + for dir in $kde_qt_dirs; do + qt_bindirs="$qt_bindirs $dir/bin $dir/src/moc" + done + qt_bindirs="$qt_bindirs /usr/bin /usr/X11R6/bin /usr/local/qt/bin" + if test ! "$ac_qt_bindir" = "NO"; then + qt_bindirs="$ac_qt_bindir $qt_bindirs" + fi + + KDE_FIND_PATH(moc, MOC, [$qt_bindirs], [KDE_MOC_ERROR_MESSAGE]) + if test -z "$UIC_NOT_NEEDED"; then + KDE_FIND_PATH(uic, UIC, [$qt_bindirs], [UIC=""]) + if test -z "$UIC" ; then + KDE_UIC_ERROR_MESSAGE + exit 1 + elif test $kde_qtver = 3; then + KDE_CHECK_UIC_FLAG(L,[/nonexistant],ac_uic_supports_libpath=yes,ac_uic_supports_libpath=no) + KDE_CHECK_UIC_FLAG(nounload,,ac_uic_supports_nounload=yes,ac_uic_supports_nounload=no) + + if test x$ac_uic_supports_libpath = xyes; then + UIC="$UIC -L \$(kde_widgetdir)" + fi + if test x$ac_uic_supports_nounload = xyes; then + UIC="$UIC -nounload" + fi + fi + else + UIC="echo uic not available: " + fi + + AC_SUBST(MOC) + AC_SUBST(UIC) + + UIC_TR="i18n" + if test $kde_qtver = 3; then + UIC_TR="tr2i18n" + fi + + AC_SUBST(UIC_TR) +]) + +AC_DEFUN(KDE_1_CHECK_PATHS, +[ + KDE_1_CHECK_PATH_HEADERS + + KDE_TEST_RPATH= + + if test -n "$USE_RPATH"; then + + if test -n "$kde_libraries"; then + KDE_TEST_RPATH="-R $kde_libraries" + fi + + if test -n "$qt_libraries"; then + KDE_TEST_RPATH="$KDE_TEST_RPATH -R $qt_libraries" + fi + + if test -n "$x_libraries"; then + KDE_TEST_RPATH="$KDE_TEST_RPATH -R $x_libraries" + fi + + KDE_TEST_RPATH="$KDE_TEST_RPATH $KDE_EXTRA_RPATH" + fi + +AC_MSG_CHECKING([for KDE libraries installed]) +ac_link='$LIBTOOL_SHELL --silent --mode=link ${CXX-g++} -o conftest $CXXFLAGS $all_includes $CPPFLAGS $LDFLAGS $all_libraries conftest.$ac_ext $LIBS -lkdecore $LIBQT $KDE_TEST_RPATH 1>&5' + +if AC_TRY_EVAL(ac_link) && test -s conftest; then + AC_MSG_RESULT(yes) +else + AC_MSG_ERROR([your system fails at linking a small KDE application! +Check, if your compiler is installed correctly and if you have used the +same compiler to compile Qt and kdelibs as you did use now. +For more details about this problem, look at the end of config.log.]) +fi + +if eval `KDEDIR= ./conftest 2>&5`; then + kde_result=done +else + kde_result=problems +fi + +KDEDIR= ./conftest 2> /dev/null >&5 # make an echo for config.log +kde_have_all_paths=yes + +KDE_SET_PATHS($kde_result) + +]) + +AC_DEFUN(KDE_SET_PATHS, +[ + kde_cv_all_paths="kde_have_all_paths=\"yes\" \ + kde_htmldir=\"$kde_htmldir\" \ + kde_appsdir=\"$kde_appsdir\" \ + kde_icondir=\"$kde_icondir\" \ + kde_sounddir=\"$kde_sounddir\" \ + kde_datadir=\"$kde_datadir\" \ + kde_locale=\"$kde_locale\" \ + kde_cgidir=\"$kde_cgidir\" \ + kde_confdir=\"$kde_confdir\" \ + kde_mimedir=\"$kde_mimedir\" \ + kde_toolbardir=\"$kde_toolbardir\" \ + kde_wallpaperdir=\"$kde_wallpaperdir\" \ + kde_templatesdir=\"$kde_templatesdir\" \ + kde_bindir=\"$kde_bindir\" \ + kde_servicesdir=\"$kde_servicesdir\" \ + kde_servicetypesdir=\"$kde_servicetypesdir\" \ + kde_moduledir=\"$kde_moduledir\" \ + kde_styledir=\"$kde_styledir\" \ + kde_widgetdir=\"$kde_widgetdir\" \ + kde_result=$1" +]) + +AC_DEFUN(KDE_SET_DEFAULT_PATHS, +[ +if test "$1" = "default"; then + + if test -z "$kde_htmldir"; then + kde_htmldir='\${prefix}/share/doc/HTML' + fi + if test -z "$kde_appsdir"; then + kde_appsdir='\${prefix}/share/applnk' + fi + if test -z "$kde_icondir"; then + kde_icondir='\${prefix}/share/icons' + fi + if test -z "$kde_sounddir"; then + kde_sounddir='\${prefix}/share/sounds' + fi + if test -z "$kde_datadir"; then + kde_datadir='\${prefix}/share/apps' + fi + if test -z "$kde_locale"; then + kde_locale='\${prefix}/share/locale' + fi + if test -z "$kde_cgidir"; then + kde_cgidir='\${exec_prefix}/cgi-bin' + fi + if test -z "$kde_confdir"; then + kde_confdir='\${prefix}/share/config' + fi + if test -z "$kde_mimedir"; then + kde_mimedir='\${prefix}/share/mimelnk' + fi + if test -z "$kde_toolbardir"; then + kde_toolbardir='\${prefix}/share/toolbar' + fi + if test -z "$kde_wallpaperdir"; then + kde_wallpaperdir='\${prefix}/share/wallpapers' + fi + if test -z "$kde_templatesdir"; then + kde_templatesdir='\${prefix}/share/templates' + fi + if test -z "$kde_bindir"; then + kde_bindir='\${exec_prefix}/bin' + fi + if test -z "$kde_servicesdir"; then + kde_servicesdir='\${prefix}/share/services' + fi + if test -z "$kde_servicetypesdir"; then + kde_servicetypesdir='\${prefix}/share/servicetypes' + fi + if test -z "$kde_moduledir"; then + if test "$kde_qtver" = "2"; then + kde_moduledir='\${exec_prefix}/lib/kde2' + else + kde_moduledir='\${exec_prefix}/lib/kde3' + fi + fi + if test -z "$kde_styledir"; then + kde_styledir='\${exec_prefix}/lib/kde3/plugins/styles' + fi + if test -z "$kde_widgetdir"; then + kde_widgetdir='\${exec_prefix}/lib/kde3/plugins/designer' + fi + + KDE_SET_PATHS(defaults) + +else + + if test $kde_qtver = 1; then + AC_MSG_RESULT([compiling]) + KDE_1_CHECK_PATHS + else + AC_MSG_ERROR([path checking not yet supported for KDE 2]) + fi + +fi +]) + +AC_DEFUN(KDE_CHECK_PATHS_FOR_COMPLETENESS, +[ if test -z "$kde_htmldir" || test -z "$kde_appsdir" || + test -z "$kde_icondir" || test -z "$kde_sounddir" || + test -z "$kde_datadir" || test -z "$kde_locale" || + test -z "$kde_cgidir" || test -z "$kde_confdir" || + test -z "$kde_mimedir" || test -z "$kde_toolbardir" || + test -z "$kde_wallpaperdir" || test -z "$kde_templatesdir" || + test -z "$kde_bindir" || test -z "$kde_servicesdir" || + test -z "$kde_servicetypesdir" || test -z "$kde_moduledir" || + test -z "$kde_styledir" || test -z "kde_widgetdir" + test "x$kde_have_all_paths" != "xyes"; then + kde_have_all_paths=no + fi +]) + +AC_DEFUN(KDE_MISSING_PROG_ERROR, +[ + AC_MSG_ERROR([The important program $1 was not found! +Please check whether you installed KDE correctly. +]) +]) + +AC_DEFUN(KDE_SUBST_PROGRAMS, +[ + + kde_default_bindirs="/usr/bin /usr/local/bin /opt/local/bin /usr/X11R6/bin /opt/kde/bin /opt/kde3/bin /usr/kde/bin /usr/local/kde/bin" + if test -n "$KDEDIRS"; then + kde_save_IFS=$IFS + IFS=: + for dir in $KDEDIRS; do + kde_default_bindirs="$dir/bin $kde_default_bindirs " + done + IFS=$kde_save_IFS + fi + kde_default_bindirs="$exec_prefix/bin $prefix/bin $kde_default_bindirs" + KDE_FIND_PATH(dcopidl, DCOPIDL, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidl)]) + KDE_FIND_PATH(dcopidl2cpp, DCOPIDL2CPP, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidl2cpp)]) + KDE_FIND_PATH(mcopidl, MCOPIDL, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(mcopidl)]) + KDE_FIND_PATH(artsc-config, ARTSCCONFIG, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(artsc-config)]) + KDE_FIND_PATH(kde-config, KDECONFIG, [$kde_default_bindirs]) + KDE_FIND_PATH(meinproc, MEINPROC, [$kde_default_bindirs]) + + if test -n "$MEINPROC" && test ! "$MEINPROC" = "compiled"; then + kde_sharedirs="/usr/share/kde /usr/local/share /usr/share /opt/kde3/share /opt/kde/share $prefix/share" + test -n "$KDEDIR" && kde_sharedirs="$KDEDIR/share $kde_sharedirs" + AC_FIND_FILE(apps/ksgmltools2/customization/kde-chunk.xsl, $kde_sharedirs, KDE_XSL_STYLESHEET) + if test "$KDE_XSL_STYLESHEET" = "NO"; then + KDE_XSL_STYLESHEET="" + else + KDE_XSL_STYLESHEET="$KDE_XSL_STYLESHEET/apps/ksgmltools2/customization/kde-chunk.xsl" + fi + fi + + DCOP_DEPENDENCIES='$(DCOPIDL)' + AC_SUBST(DCOPIDL) + AC_SUBST(DCOPIDL2CPP) + AC_SUBST(DCOP_DEPENDENCIES) + AC_SUBST(MCOPIDL) + AC_SUBST(ARTSCCONFIG) + AC_SUBST(KDECONFIG) + AC_SUBST(MEINPROC) + AC_SUBST(KDE_XSL_STYLESHEET) + + if test -x "$KDECONFIG"; then # it can be "compiled" + kde_libs_prefix=`$KDECONFIG --prefix` + if test -z "$kde_libs_prefix" || test ! -x "$kde_libs_prefix"; then + AC_MSG_ERROR([$KDECONFIG --prefix outputed the non existant prefix '$kde_libs_prefix' for kdelibs. + This means it has been moved since you installed it. + This won't work. Please recompile kdelibs for the new prefix. + ]) + fi + kde_libs_htmldir=`$KDECONFIG --install html --expandvars` + else + kde_libs_prefix='$(prefix)' + kde_libs_htmldir='$(kde_htmldir)' + fi + AC_SUBST(kde_libs_prefix) + AC_SUBST(kde_libs_htmldir) +])dnl + +AC_DEFUN(AC_CREATE_KFSSTND, +[ +AC_REQUIRE([AC_CHECK_RPATH]) + +AC_MSG_CHECKING([for KDE paths]) +kde_result="" +kde_cached_paths=yes +AC_CACHE_VAL(kde_cv_all_paths, +[ + KDE_SET_DEFAULT_PATHS($1) + kde_cached_paths=no +]) +eval "$kde_cv_all_paths" +KDE_CHECK_PATHS_FOR_COMPLETENESS +if test "$kde_have_all_paths" = "no" && test "$kde_cached_paths" = "yes"; then + # wrong values were cached, may be, we can set better ones + kde_result= + kde_htmldir= kde_appsdir= kde_icondir= kde_sounddir= + kde_datadir= kde_locale= kde_cgidir= kde_confdir= + kde_mimedir= kde_toolbardir= kde_wallpaperdir= kde_templatesdir= + kde_bindir= kde_servicesdir= kde_servicetypesdir= kde_moduledir= + kde_have_all_paths= + kde_styledir= + kde_widgetdir= + KDE_SET_DEFAULT_PATHS($1) + eval "$kde_cv_all_paths" + KDE_CHECK_PATHS_FOR_COMPLETENESS + kde_result="$kde_result (cache overridden)" +fi +if test "$kde_have_all_paths" = "no"; then + AC_MSG_ERROR([configure could not run a little KDE program to test the environment. +Since it had compiled and linked before, it must be a strange problem on your system. +Look at config.log for details. If you are not able to fix this, look at +http://www.kde.org/faq/installation.html or any www.kde.org mirror. +(If you're using an egcs version on Linux, you may update binutils!) +]) +else + rm -f conftest* + AC_MSG_RESULT($kde_result) +fi + +bindir=$kde_bindir + +KDE_SUBST_PROGRAMS + +]) + +AC_DEFUN(AC_SUBST_KFSSTND, +[ +AC_SUBST(kde_htmldir) +AC_SUBST(kde_appsdir) +AC_SUBST(kde_icondir) +AC_SUBST(kde_sounddir) +AC_SUBST(kde_datadir) +AC_SUBST(kde_locale) +AC_SUBST(kde_confdir) +AC_SUBST(kde_mimedir) +AC_SUBST(kde_wallpaperdir) +AC_SUBST(kde_bindir) +dnl for KDE 2 +AC_SUBST(kde_templatesdir) +AC_SUBST(kde_servicesdir) +AC_SUBST(kde_servicetypesdir) +AC_SUBST(kde_moduledir) +AC_SUBST(kde_styledir) +AC_SUBST(kde_widgetdir) +if test "$kde_qtver" = 1; then + kde_minidir="$kde_icondir/mini" +else +# for KDE 1 - this breaks KDE2 apps using minidir, but +# that's the plan ;-/ + kde_minidir="/dev/null" +fi +dnl AC_SUBST(kde_minidir) +dnl AC_SUBST(kde_cgidir) +dnl AC_SUBST(kde_toolbardir) +]) + +AC_DEFUN(KDE_MISC_TESTS, +[ + AC_LANG_C + dnl Checks for libraries. + AC_CHECK_LIB(util, main, [LIBUTIL="-lutil"]) dnl for *BSD + AC_SUBST(LIBUTIL) + AC_CHECK_LIB(compat, main, [LIBCOMPAT="-lcompat"]) dnl for *BSD + AC_SUBST(LIBCOMPAT) + kde_have_crypt= + AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"; kde_have_crypt=yes], + AC_CHECK_LIB(c, crypt, [kde_have_crypt=yes], [ + AC_MSG_WARN([you have no crypt in either libcrypt or libc. +You should install libcrypt from another source or configure with PAM +support]) + kde_have_crypt=no + ])) + AC_SUBST(LIBCRYPT) + if test $kde_have_crypt = yes; then + AC_DEFINE_UNQUOTED(HAVE_CRYPT, 1, [Defines if your system has the crypt function]) + fi + AC_CHECK_SOCKLEN_T + AC_LANG_C + AC_CHECK_LIB(dnet, dnet_ntoa, [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"]) + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + AC_CHECK_LIB(dnet_stub, dnet_ntoa, + [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"]) + fi + AC_CHECK_FUNC(inet_ntoa) + if test $ac_cv_func_inet_ntoa = no; then + AC_CHECK_LIB(nsl, inet_ntoa, X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl") + fi + AC_CHECK_FUNC(connect) + if test $ac_cv_func_connect = no; then + AC_CHECK_LIB(socket, connect, X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS", , + $X_EXTRA_LIBS) + fi + + AC_CHECK_FUNC(remove) + if test $ac_cv_func_remove = no; then + AC_CHECK_LIB(posix, remove, X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix") + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + AC_CHECK_FUNC(shmat, , + AC_CHECK_LIB(ipc, shmat, X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc")) + + # Solaris 2.6 and others need -lresolv for res_init + AC_CHECK_FUNCS(res_init, , [ + kde_libs_safe="$LIBS" + LIBS="$LIBS $X_EXTRA_LIBS -lresolv" + AC_TRY_LINK( +[ +#include <resolv.h> +], +[ +res_init(); +], + LIBRESOLV="-lresolv" + X_EXTRA_LIBS="$X_EXTRA_LIBS $LIBRESOLV" + AC_DEFINE(HAVE_RES_INIT, 1, [Define if you have the res_init function]) + ) + LIBS=$kde_libs_safe + ]) + + LIBSOCKET="$X_EXTRA_LIBS" + AC_SUBST(LIBSOCKET) + AC_SUBST(LIBRESOLV) + AC_SUBST(X_EXTRA_LIBS) + AC_CHECK_LIB(ucb, killpg, [LIBUCB="-lucb"]) dnl for Solaris2.4 + AC_SUBST(LIBUCB) + + case $host in dnl this *is* LynxOS specific + *-*-lynxos* ) + AC_MSG_CHECKING([LynxOS header file wrappers]) + [CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"] + AC_MSG_RESULT(disabled) + AC_CHECK_LIB(bsd, gethostbyname, [LIBSOCKET="-lbsd"]) dnl for LynxOS + ;; + esac + + KDE_CHECK_TYPES + KDE_CHECK_LIBDL +]) + +dnl ------------------------------------------------------------------------ +dnl Find the header files and libraries for X-Windows. Extended the +dnl macro AC_PATH_X +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN(K_PATH_X, +[ +AC_REQUIRE([KDE_MISC_TESTS])dnl + +AC_ARG_ENABLE( + embedded, + [ --enable-embedded link to Qt-embedded, don't use X], + kde_use_qt_emb=$enableval, + kde_use_qt_emb=no +) + +AC_ARG_ENABLE( + qtopia, + [ --enable-qtopia link to Qt-embedded, link to the Qtopia Environment], + kde_use_qt_emb_palm=$enableval, + kde_use_qt_emb_palm=no +) + +if test "$kde_use_qt_emb" = "no"; then + +AC_MSG_CHECKING(for X) +AC_LANG_SAVE +AC_LANG_C +AC_CACHE_VAL(kde_cv_have_x, +[# One or both of the vars are not set, and there is no cached value. +if test "{$x_includes+set}" = set || test "$x_includes" = NONE; then + kde_x_includes=NO +else + kde_x_includes=$x_includes +fi +if test "{$x_libraries+set}" = set || test "$x_libraries" = NONE; then + kde_x_libraries=NO +else + kde_x_libraries=$x_libraries +fi + +# below we use the standard autoconf calls +ac_x_libraries=$kde_x_libraries +ac_x_includes=$kde_x_includes + +KDE_PATH_X_DIRECT +dnl AC_PATH_X_XMKMF picks /usr/lib as the path for the X libraries. +dnl Unfortunately, if compiling with the N32 ABI, this is not the correct +dnl location. The correct location is /usr/lib32 or an undefined value +dnl (the linker is smart enough to pick the correct default library). +dnl Things work just fine if you use just AC_PATH_X_DIRECT. +dnl Solaris has a similar problem. AC_PATH_X_XMKMF forces x_includes to +dnl /usr/openwin/include, which doesn't work. /usr/include does work, so +dnl x_includes should be left alone. +case "$host" in +mips-sgi-irix6*) + ;; +*-*-solaris*) + ;; +*) + _AC_PATH_X_XMKMF + if test -z "$ac_x_includes"; then + ac_x_includes="." + fi + if test -z "$ac_x_libraries"; then + ac_x_libraries="/usr/lib" + fi +esac +#from now on we use our own again + +# when the user already gave --x-includes, we ignore +# what the standard autoconf macros told us. +if test "$kde_x_includes" = NO; then + kde_x_includes=$ac_x_includes +fi + +# for --x-libraries too +if test "$kde_x_libraries" = NO; then + kde_x_libraries=$ac_x_libraries +fi + +if test "$kde_x_includes" = NO; then + AC_MSG_ERROR([Can't find X includes. Please check your installation and add the correct paths!]) +fi + +if test "$kde_x_libraries" = NO; then + AC_MSG_ERROR([Can't find X libraries. Please check your installation and add the correct paths!]) +fi + +# Record where we found X for the cache. +kde_cv_have_x="have_x=yes \ + kde_x_includes=$kde_x_includes kde_x_libraries=$kde_x_libraries" +])dnl + +eval "$kde_cv_have_x" + +if test "$have_x" != yes; then + AC_MSG_RESULT($have_x) + no_x=yes +else + AC_MSG_RESULT([libraries $kde_x_libraries, headers $kde_x_includes]) +fi + +if test -z "$kde_x_includes" || test "x$kde_x_includes" = xNONE; then + X_INCLUDES="" + x_includes="."; dnl better than nothing :- + else + x_includes=$kde_x_includes + X_INCLUDES="-I$x_includes" +fi + +if test -z "$kde_x_libraries" || test "x$kde_x_libraries" = xNONE; then + X_LDFLAGS="" + x_libraries="/usr/lib"; dnl better than nothing :- + else + x_libraries=$kde_x_libraries + X_LDFLAGS="-L$x_libraries" +fi +all_includes="$X_INCLUDES" +all_libraries="$X_LDFLAGS" + +AC_SUBST(X_INCLUDES) +AC_SUBST(X_LDFLAGS) +AC_SUBST(x_libraries) +AC_SUBST(x_includes) + +# Check for libraries that X11R6 Xt/Xaw programs need. +ac_save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $X_LDFLAGS" +# SM needs ICE to (dynamically) link under SunOS 4.x (so we have to +# check for ICE first), but we must link in the order -lSM -lICE or +# we get undefined symbols. So assume we have SM if we have ICE. +# These have to be linked with before -lX11, unlike the other +# libraries we check for below, so use a different variable. +# --interran@uluru.Stanford.EDU, kb@cs.umb.edu. +AC_CHECK_LIB(ICE, IceConnectionNumber, + [LIBSM="-lSM -lICE"], , $X_EXTRA_LIBS) +AC_SUBST(LIBSM) +LDFLAGS="$ac_save_LDFLAGS" + +AC_SUBST(X_PRE_LIBS) + +LIB_X11='-lX11 $(LIBSOCKET)' +AC_SUBST(LIB_X11) + +AC_MSG_CHECKING(for libXext) +AC_CACHE_VAL(kde_cv_have_libXext, +[ +kde_ldflags_safe="$LDFLAGS" +kde_libs_safe="$LIBS" + +LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS" +LIBS="-lXext -lX11 $LIBSOCKET" + +AC_TRY_LINK([ +#include <stdio.h> +#ifdef STDC_HEADERS +# include <stdlib.h> +#endif +], +[ +printf("hello Xext\n"); +], +kde_cv_have_libXext=yes, +kde_cv_have_libXext=no + ) + +LDFLAGS=$kde_ldflags_safe +LIBS=$kde_libs_safe + ]) + +AC_MSG_RESULT($kde_cv_have_libXext) + +if test "$kde_cv_have_libXext" = "no"; then + AC_MSG_ERROR([We need a working libXext to proceed. Since configure +can't find it itself, we stop here assuming that make wouldn't find +them either.]) +fi + +AC_MSG_CHECKING(for Xinerama) + + AC_ARG_WITH(xinerama, + [ --with-xinerama enable support for Xinerama ], + [ + no_xinerama=no + ], [ + no_xinerama=yes + ] +) + +kde_save_LDFLAGS="$LDFLAGS" +kde_save_CFLAGS="$CFLAGS" +kde_save_LIBS="$LIBS" +LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS" +CFLAGS="$CFLAGS -I$x_includes" +LIBS="-lXinerama -lXext" + +if test "x$no_xinerama" = "xno"; then + + AC_CACHE_VAL(ac_cv_have_xinerama, + [ + AC_TRY_LINK([#include <X11/Xlib.h> + #include <X11/extensions/Xinerama.h>], + [XineramaIsActive(NULL);], + [ac_cv_have_xinerama="yes"], + [ac_cv_have_xinerama="no"]) + ]) +else + ac_cv_have_xinerama=no; +fi + +AC_MSG_RESULT($ac_cv_have_xinerama) + +LIBXINERAMA="" + +if test "$ac_cv_have_xinerama" = "yes"; then + AC_DEFINE(HAVE_XINERAMA, 1, [Define if you want Xinerama support]) + LIBXINERAMA="-lXinerama" +fi + +AC_SUBST(LIBXINERAMA) + +LDFLAGS="$kde_save_LDFLAGS" +CFLAGS="$kde_save_CFLAGS" +LIBS="$kde_save_LIBS" + +LIB_XEXT="-lXext" +QTE_NORTTI="" + +else + dnl We're using QT Embedded + CXXFLAGS="$CXXFLAGS -fno-rtti -DQWS" + CFLAGS="$CFLAGS -DQWS" + LDFLAGS="$LDFLAGS -DQWS" + QTE_NORTTI="-fno-rtti -DQWS" + X_PRE_LIBS="" + LIB_X11="" + LIB_XEXT="" + LIBSM="" + X_INCLUDES="" + X_LDFLAGS="" + x_includes="" + x_libraries="" + AC_SUBST(X_PRE_LIBS) + AC_SUBST(LIB_X11) + AC_SUBST(LIBSM) + AC_SUBST(X_INCLUDES) + AC_SUBST(X_LDFLAGS) + AC_SUBST(x_includes) + AC_SUBST(x_libraries) +fi +AC_SUBST(QTE_NORTTI) +AC_SUBST(LIB_XEXT) + + +AC_LANG_RESTORE + +]) + +AC_DEFUN(KDE_PRINT_QT_PROGRAM, +[ +AC_REQUIRE([KDE_USE_QT]) +cat > conftest.$ac_ext <<EOF +#include "confdefs.h" +#include <qglobal.h> +#include <qapplication.h> +EOF +if test "$kde_qtver" = "2"; then +cat >> conftest.$ac_ext <<EOF +#include <qevent.h> +#include <qstring.h> +#include <qstyle.h> +EOF + +if test $kde_qtsubver -gt 0; then +cat >> conftest.$ac_ext <<EOF +#include <qiconview.h> +EOF +fi +fi + +if test "$kde_qtver" = "3"; then +cat >> conftest.$ac_ext <<EOF +#include <qcursor.h> +#include <qstylefactory.h> +#include <private/qucomextra_p.h> +EOF +fi + +echo "#if ! ($kde_qt_verstring)" >> conftest.$ac_ext +cat >> conftest.$ac_ext <<EOF +#error 1 +#endif + +int main() { +EOF +if test "$kde_qtver" = "2"; then +cat >> conftest.$ac_ext <<EOF + QStringList *t = new QStringList(); + Q_UNUSED(t); +EOF +if test $kde_qtsubver -gt 0; then +cat >> conftest.$ac_ext <<EOF + QIconView iv(0); + iv.setWordWrapIconText(false); + QString s; + s.setLatin1("Elvis is alive", 14); +EOF +fi +fi +if test "$kde_qtver" = "3"; then +cat >> conftest.$ac_ext <<EOF + (void)QStyleFactory::create(QString::null); + QCursor c(Qt::WhatsThisCursor); +EOF +fi +cat >> conftest.$ac_ext <<EOF + return 0; +} +EOF +]) + +AC_DEFUN(KDE_USE_QT, +[ +if test -z "$1"; then + kde_qtver=3 + kde_qtsubver=1 +else + kde_qtsubver=`echo "$1" | sed -e 's#[0-9][0-9]*\.\([0-9][0-9]*\).*#\1#'` + # following is the check if subversion isn´t found in passed argument + if test "$kde_qtsubver" = "$1"; then + kde_qtsubver=1 + fi + kde_qtver=`echo "$1" | sed -e 's#^\([0-9][0-9]*\)\..*#\1#'` + if test "$kde_qtver" = "1"; then + kde_qtsubver=42 + fi +fi + +if test -z "$2"; then + if test "$kde_qtver" = "2"; then + if test $kde_qtsubver -gt 0; then + kde_qt_minversion=">= Qt 2.2.2" + else + kde_qt_minversion=">= Qt 2.0.2" + fi + fi + if test "$kde_qtver" = "3"; then + kde_qt_minversion=">= Qt 3.0.2" + fi + if test "$kde_qtver" = "1"; then + kde_qt_minversion=">= 1.42 and < 2.0" + fi +else + kde_qt_minversion=$2 +fi + +if test -z "$3"; then + if test $kde_qtver = 3; then + kde_qt_verstring="QT_VERSION >= 302" + fi + if test $kde_qtver = 2; then + if test $kde_qtsubver -gt 0; then + kde_qt_verstring="QT_VERSION >= 222" + else + kde_qt_verstring="QT_VERSION >= 200" + fi + fi + if test $kde_qtver = 1; then + kde_qt_verstring="QT_VERSION >= 142 && QT_VERSION < 200" + fi +else + kde_qt_verstring=$3 +fi + +if test $kde_qtver = 3; then + kde_qt_dirs="$QTDIR /usr/lib/qt3 /usr/lib/qt" +fi +if test $kde_qtver = 2; then + kde_qt_dirs="$QTDIR /usr/lib/qt2 /usr/lib/qt" +fi +if test $kde_qtver = 1; then + kde_qt_dirs="$QTDIR /usr/lib/qt" +fi +]) + +AC_DEFUN(KDE_CHECK_QT_DIRECT, +[ +AC_REQUIRE([KDE_USE_QT]) +AC_MSG_CHECKING([if Qt compiles without flags]) +AC_CACHE_VAL(kde_cv_qt_direct, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_LD_LIBRARY_PATH_safe=$LD_LIBRARY_PATH +ac_LIBRARY_PATH="$LIBRARY_PATH" +ac_cxxflags_safe="$CXXFLAGS" +ac_ldflags_safe="$LDFLAGS" +ac_libs_safe="$LIBS" + +CXXFLAGS="$CXXFLAGS -I$qt_includes" +LDFLAGS="$LDFLAGS $X_LDFLAGS" +if test "x$kde_use_qt_emb" != "xyes"; then +LIBS="$LIBQT -lXext -lX11 $LIBSOCKET" +else +LIBS="$LIBQT $LIBSOCKET" +fi +LD_LIBRARY_PATH= +export LD_LIBRARY_PATH +LIBRARY_PATH= +export LIBRARY_PATH + +KDE_PRINT_QT_PROGRAM + +if AC_TRY_EVAL(ac_link) && test -s conftest; then + kde_cv_qt_direct="yes" +else + kde_cv_qt_direct="no" + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +fi + +rm -f conftest* +CXXFLAGS="$ac_cxxflags_safe" +LDFLAGS="$ac_ldflags_safe" +LIBS="$ac_libs_safe" + +LD_LIBRARY_PATH="$ac_LD_LIBRARY_PATH_safe" +export LD_LIBRARY_PATH +LIBRARY_PATH="$ac_LIBRARY_PATH" +export LIBRARY_PATH +AC_LANG_RESTORE +]) + +if test "$kde_cv_qt_direct" = "yes"; then + AC_MSG_RESULT(yes) + $1 +else + AC_MSG_RESULT(no) + $2 +fi +]) + +dnl ------------------------------------------------------------------------ +dnl Try to find the Qt headers and libraries. +dnl $(QT_LDFLAGS) will be -Lqtliblocation (if needed) +dnl and $(QT_INCLUDES) will be -Iqthdrlocation (if needed) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN(AC_PATH_QT_1_3, +[ +AC_REQUIRE([K_PATH_X]) +AC_REQUIRE([KDE_USE_QT]) + +dnl ------------------------------------------------------------------------ +dnl Add configure flag to enable linking to MT version of Qt library. +dnl ------------------------------------------------------------------------ + +AC_ARG_ENABLE( + mt, + [ --disable-mt link to non-threaded Qt (deprecated)], + kde_use_qt_mt=$enableval, + [ + if test $kde_qtver = 3; then + kde_use_qt_mt=yes + else + kde_use_qt_mt=no + fi + ] +) + +USING_QT_MT="" + +dnl ------------------------------------------------------------------------ +dnl If we not get --disable-qt-mt then adjust some vars for the host. +dnl ------------------------------------------------------------------------ + +KDE_MT_LDFLAGS= +KDE_MT_LIBS= +if test "x$kde_use_qt_mt" = "xyes"; then + KDE_CHECK_THREADING + if test "x$kde_use_threading" = "xyes"; then + CPPFLAGS="$USE_THREADS -DQT_THREAD_SUPPORT $CPPFLAGS" + KDE_MT_LDFLAGS="$USE_THREADS" + KDE_MT_LIBS="$LIBPTHREAD" + else + kde_use_qt_mt=no + fi +fi +AC_SUBST(KDE_MT_LDFLAGS) +AC_SUBST(KDE_MT_LIBS) + +kde_qt_was_given=yes + +dnl ------------------------------------------------------------------------ +dnl If we haven't been told how to link to Qt, we work it out for ourselves. +dnl ------------------------------------------------------------------------ +if test -z "$LIBQT_GLOB"; then + if test "x$kde_use_qt_emb" = "xyes"; then + LIBQT_GLOB="libqte.*" + else + LIBQT_GLOB="libqt.*" + fi +fi + +if test -z "$LIBQT"; then +dnl ------------------------------------------------------------ +dnl If we got --enable-embedded then adjust the Qt library name. +dnl ------------------------------------------------------------ + if test "x$kde_use_qt_emb" = "xyes"; then + qtlib="qte" + else + qtlib="qt" + fi + + kde_int_qt="-l$qtlib" +else + kde_int_qt="$LIBQT" + kde_lib_qt_set=yes +fi + +if test -z "$LIBQPE"; then +dnl ------------------------------------------------------------ +dnl If we got --enable-palmtop then add -lqpe to the link line +dnl ------------------------------------------------------------ + if test "x$kde_use_qt_emb" = "xyes"; then + if test "x$kde_use_qt_emb_palm" = "xyes"; then + LIB_QPE="-lqpe" + else + LIB_QPE="" + fi + else + LIB_QPE="" + fi +fi + +dnl ------------------------------------------------------------------------ +dnl If we got --enable-qt-mt then adjust the Qt library name for the host. +dnl ------------------------------------------------------------------------ + +if test "x$kde_use_qt_mt" = "xyes"; then + if test -z "$LIBQT"; then + LIBQT="-l$qtlib-mt" + kde_int_qt="-l$qtlib-mt" + else + LIBQT="$qtlib-mt" + kde_int_qt="$qtlib-mt" + fi + LIBQT_GLOB="lib$qtlib-mt.*" + USING_QT_MT="using -mt" +else + LIBQT="-l$qtlib" +fi + +if test $kde_qtver != 1; then + + AC_REQUIRE([AC_FIND_PNG]) + AC_REQUIRE([AC_FIND_JPEG]) + LIBQT="$LIBQT $LIBPNG $LIBJPEG" +fi + +if test $kde_qtver = 3; then + AC_REQUIRE([KDE_CHECK_LIBDL]) + LIBQT="$LIBQT $LIBDL" +fi + +AC_MSG_CHECKING([for Qt]) + +if test "x$kde_use_qt_emb" != "xyes"; then +LIBQT="$LIBQT $X_PRE_LIBS -lXext -lX11 $LIBSM $LIBSOCKET" +fi +ac_qt_includes=NO ac_qt_libraries=NO ac_qt_bindir=NO +qt_libraries="" +qt_includes="" +AC_ARG_WITH(qt-dir, + [ --with-qt-dir=DIR where the root of Qt is installed ], + [ ac_qt_includes="$withval"/include + ac_qt_libraries="$withval"/lib + ac_qt_bindir="$withval"/bin + ]) + +AC_ARG_WITH(qt-includes, + [ --with-qt-includes=DIR where the Qt includes are. ], + [ + ac_qt_includes="$withval" + ]) + +kde_qt_libs_given=no + +AC_ARG_WITH(qt-libraries, + [ --with-qt-libraries=DIR where the Qt library is installed.], + [ ac_qt_libraries="$withval" + kde_qt_libs_given=yes + ]) + +AC_CACHE_VAL(ac_cv_have_qt, +[#try to guess Qt locations + +qt_incdirs="" +for dir in $kde_qt_dirs; do + qt_incdirs="$qt_incdirs $dir/include $dir" +done +qt_incdirs="$QTINC $qt_incdirs /usr/local/qt/include /usr/include/qt /usr/include /usr/X11R6/include/X11/qt /usr/X11R6/include/qt /usr/X11R6/include/qt2 $x_includes" +if test ! "$ac_qt_includes" = "NO"; then + qt_incdirs="$ac_qt_includes $qt_incdirs" +fi + +if test "$kde_qtver" != "1"; then + kde_qt_header=qstyle.h +else + kde_qt_header=qglobal.h +fi + +AC_FIND_FILE($kde_qt_header, $qt_incdirs, qt_incdir) +ac_qt_includes="$qt_incdir" + +qt_libdirs="" +for dir in $kde_qt_dirs; do + qt_libdirs="$qt_libdirs $dir/lib $dir" +done +qt_libdirs="$QTLIB $qt_libdirs /usr/X11R6/lib /usr/lib /usr/local/qt/lib $x_libraries" +if test ! "$ac_qt_libraries" = "NO"; then + qt_libdir=$ac_qt_libraries +else + qt_libdirs="$ac_qt_libraries $qt_libdirs" + # if the Qt was given, the chance is too big that libqt.* doesn't exist + qt_libdir=NONE + for dir in $qt_libdirs; do + try="ls -1 $dir/${LIBQT_GLOB}" + if test -n "`$try 2> /dev/null`"; then qt_libdir=$dir; break; else echo "tried $dir" >&AC_FD_CC ; fi + done +fi + +ac_qt_libraries="$qt_libdir" + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + +ac_cxxflags_safe="$CXXFLAGS" +ac_ldflags_safe="$LDFLAGS" +ac_libs_safe="$LIBS" + +CXXFLAGS="$CXXFLAGS -I$qt_incdir $all_includes" +LDFLAGS="$LDFLAGS -L$qt_libdir $all_libraries $USER_LDFLAGS $KDE_MT_LDFLAGS" +LIBS="$LIBS $LIBQT $KDE_MT_LIBS" + +KDE_PRINT_QT_PROGRAM + +if AC_TRY_EVAL(ac_link) && test -s conftest; then + rm -f conftest* +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC + ac_qt_libraries="NO" +fi +rm -f conftest* +CXXFLAGS="$ac_cxxflags_safe" +LDFLAGS="$ac_ldflags_safe" +LIBS="$ac_libs_safe" + +AC_LANG_RESTORE +if test "$ac_qt_includes" = NO || test "$ac_qt_libraries" = NO; then + ac_cv_have_qt="have_qt=no" + ac_qt_notfound="" + missing_qt_mt="" + if test "$ac_qt_includes" = NO; then + if test "$ac_qt_libraries" = NO; then + ac_qt_notfound="(headers and libraries)"; + else + ac_qt_notfound="(headers)"; + fi + else + if test "x$kde_use_qt_mt" = "xyes"; then + missing_qt_mt=" +Make sure that you have compiled Qt with thread support!" + ac_qt_notfound="(library $qtlib-mt)"; + else + ac_qt_notfound="(library $qtlib)"; + fi + fi + + AC_MSG_ERROR([Qt ($kde_qt_minversion) $ac_qt_notfound not found. Please check your installation! +For more details about this problem, look at the end of config.log.$missing_qt_mt]) +else + have_qt="yes" +fi +]) + +eval "$ac_cv_have_qt" + +if test "$have_qt" != yes; then + AC_MSG_RESULT([$have_qt]); +else + ac_cv_have_qt="have_qt=yes \ + ac_qt_includes=$ac_qt_includes ac_qt_libraries=$ac_qt_libraries" + AC_MSG_RESULT([libraries $ac_qt_libraries, headers $ac_qt_includes $USING_QT_MT]) + + qt_libraries="$ac_qt_libraries" + qt_includes="$ac_qt_includes" +fi + +if test ! "$kde_qt_libs_given" = "yes"; then +KDE_CHECK_QT_DIRECT(qt_libraries= ,[]) +fi + +AC_SUBST(qt_libraries) +AC_SUBST(qt_includes) + +if test "$qt_includes" = "$x_includes" || test -z "$qt_includes"; then + QT_INCLUDES="" +else + QT_INCLUDES="-I$qt_includes" + all_includes="$QT_INCLUDES $all_includes" +fi + +if test "$qt_libraries" = "$x_libraries" || test -z "$qt_libraries"; then + QT_LDFLAGS="" +else + QT_LDFLAGS="-L$qt_libraries" + all_libraries="$all_libraries $QT_LDFLAGS" +fi +test -z "$KDE_MT_LDFLAGS" || all_libraries="$all_libraries $KDE_MT_LDFLAGS" + +AC_SUBST(QT_INCLUDES) +AC_SUBST(QT_LDFLAGS) +AC_PATH_QT_MOC_UIC + +KDE_CHECK_QT_JPEG + +if test "x$kde_use_qt_emb" != "xyes"; then +LIB_QT="$kde_int_qt $LIBJPEG_QT "'$(LIBPNG) -lXext $(LIB_X11) $(LIBSM)' +else +LIB_QT="$kde_int_qt $LIBJPEG_QT "'$(LIBPNG)' +fi +test -z "$KDE_MT_LIBS" || LIB_QT="$LIB_QT $KDE_MT_LIBS" + +AC_SUBST(LIB_QT) +AC_SUBST(LIB_QPE) + +AC_SUBST(kde_qtver) +]) + +AC_DEFUN(AC_PATH_QT, +[ +AC_PATH_QT_1_3 +]) + +AC_DEFUN(KDE_CHECK_FINAL, +[ + AC_ARG_ENABLE(final, [ --enable-final build size optimized apps (experimental - needs lots of memory)], + kde_use_final=$enableval, kde_use_final=no) + + KDE_COMPILER_REPO + if test "x$kde_use_final" = "xyes"; then + KDE_USE_FINAL_TRUE="" + KDE_USE_FINAL_FALSE="#" + else + KDE_USE_FINAL_TRUE="#" + KDE_USE_FINAL_FALSE="" + fi + AC_SUBST(KDE_USE_FINAL_TRUE) + AC_SUBST(KDE_USE_FINAL_FALSE) + + AC_ARG_ENABLE(closure, [ --disable-closure don't delay template instantiation], + kde_use_closure=$enableval, kde_use_closure=yes) + + if test "x$kde_use_closure" = "xyes"; then + KDE_USE_CLOSURE_TRUE="" + KDE_USE_CLOSURE_FALSE="#" +# CXXFLAGS="$CXXFLAGS $REPO" + else + KDE_USE_CLOSURE_TRUE="#" + KDE_USE_CLOSURE_FALSE="" + fi + AC_SUBST(KDE_USE_CLOSURE_TRUE) + AC_SUBST(KDE_USE_CLOSURE_FALSE) +]) + +dnl ------------------------------------------------------------------------ +dnl Now, the same with KDE +dnl $(KDE_LDFLAGS) will be the kdeliblocation (if needed) +dnl and $(kde_includes) will be the kdehdrlocation (if needed) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN(AC_BASE_PATH_KDE, +[ +AC_PREREQ([2.13]) +AC_REQUIRE([AC_PATH_QT])dnl +AC_CHECK_RPATH +AC_MSG_CHECKING([for KDE]) + +if test "${prefix}" != NONE; then + kde_includes=${prefix}/include + ac_kde_includes=$prefix/include + + if test "${exec_prefix}" != NONE; then + kde_libraries=${exec_prefix}/lib + ac_kde_libraries=$exec_prefix/lib + else + kde_libraries=${prefix}/lib + ac_kde_libraries=$prefix/lib + fi +else + ac_kde_includes= + ac_kde_libraries= + kde_libraries="" + kde_includes="" +fi + +AC_CACHE_VAL(ac_cv_have_kde, +[#try to guess kde locations + +if test "$kde_qtver" = 1; then + kde_check_header="ksock.h" + kde_check_lib="libkdecore.la" +else + kde_check_header="ksharedptr.h" + kde_check_lib="libkio.la" +fi + +if test -z "$1"; then + +kde_incdirs="/usr/lib/kde/include /usr/local/kde/include /usr/local/include /usr/kde/include /usr/include/kde /usr/include /opt/kde3/include /opt/kde/include $x_includes $qt_includes" +test -n "$KDEDIR" && kde_incdirs="$KDEDIR/include $KDEDIR/include/kde $KDEDIR $kde_incdirs" +kde_incdirs="$ac_kde_includes $kde_incdirs" +AC_FIND_FILE($kde_check_header, $kde_incdirs, kde_incdir) +ac_kde_includes="$kde_incdir" + +if test -n "$ac_kde_includes" && test ! -r "$ac_kde_includes/$kde_check_header"; then + AC_MSG_ERROR([ +in the prefix, you've chosen, are no KDE headers installed. This will fail. +So, check this please and use another prefix!]) +fi + +kde_libdirs="/usr/lib/kde/lib /usr/local/kde/lib /usr/kde/lib /usr/lib/kde /usr/lib/kde3 /usr/lib /usr/X11R6/lib /usr/local/lib /opt/kde3/lib /opt/kde/lib /usr/X11R6/kde/lib" +test -n "$KDEDIR" && kde_libdirs="$KDEDIR/lib $KDEDIR $kde_libdirs" +kde_libdirs="$ac_kde_libraries $kde_libdirs" +AC_FIND_FILE($kde_check_lib, $kde_libdirs, kde_libdir) +ac_kde_libraries="$kde_libdir" + +if test -n "$ac_kde_libraries" && test ! -r "$ac_kde_libraries/$kde_check_lib"; then +AC_MSG_ERROR([ +in the prefix, you've chosen, are no KDE libraries installed. This will fail. +So, check this please and use another prefix!]) +fi +ac_kde_libraries="$kde_libdir" + +if test "$ac_kde_includes" = NO || test "$ac_kde_libraries" = NO; then + ac_cv_have_kde="have_kde=no" +else + ac_cv_have_kde="have_kde=yes \ + ac_kde_includes=$ac_kde_includes ac_kde_libraries=$ac_kde_libraries" +fi + +else dnl test -z $1 + + ac_cv_have_kde="have_kde=no" + +fi +])dnl + +eval "$ac_cv_have_kde" + +if test "$have_kde" != "yes"; then + if test "${prefix}" = NONE; then + ac_kde_prefix="$ac_default_prefix" + else + ac_kde_prefix="$prefix" + fi + if test "$exec_prefix" = NONE; then + ac_kde_exec_prefix="$ac_kde_prefix" + AC_MSG_RESULT([will be installed in $ac_kde_prefix]) + else + ac_kde_exec_prefix="$exec_prefix" + AC_MSG_RESULT([will be installed in $ac_kde_prefix and $ac_kde_exec_prefix]) + fi + + kde_libraries="${ac_kde_exec_prefix}/lib" + kde_includes=${ac_kde_prefix}/include + +else + ac_cv_have_kde="have_kde=yes \ + ac_kde_includes=$ac_kde_includes ac_kde_libraries=$ac_kde_libraries" + AC_MSG_RESULT([libraries $ac_kde_libraries, headers $ac_kde_includes]) + + kde_libraries="$ac_kde_libraries" + kde_includes="$ac_kde_includes" +fi +AC_SUBST(kde_libraries) +AC_SUBST(kde_includes) + +if test "$kde_includes" = "$x_includes" || test "$kde_includes" = "$qt_includes" || test "$kde_includes" = "/usr/include"; then + KDE_INCLUDES="" +else + KDE_INCLUDES="-I$kde_includes" + all_includes="$KDE_INCLUDES $all_includes" +fi + +KDE_LDFLAGS="-L$kde_libraries" +if test ! "$kde_libraries" = "$x_libraries" && test ! "$kde_libraries" = "$qt_libraries" ; then + all_libraries="$all_libraries $KDE_LDFLAGS" +fi + +AC_SUBST(KDE_LDFLAGS) +AC_SUBST(KDE_INCLUDES) + +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + +all_libraries="$all_libraries $USER_LDFLAGS" +all_includes="$all_includes $USER_INCLUDES" +AC_SUBST(all_includes) +AC_SUBST(all_libraries) + +AC_SUBST(AUTODIRS) +]) + +AC_DEFUN(KDE_CHECK_EXTRA_LIBS, +[ +AC_MSG_CHECKING(for extra includes) +AC_ARG_WITH(extra-includes, [ --with-extra-includes=DIR + adds non standard include paths], + kde_use_extra_includes="$withval", + kde_use_extra_includes=NONE +) +kde_extra_includes= +if test -n "$kde_use_extra_includes" && \ + test "$kde_use_extra_includes" != "NONE"; then + + ac_save_ifs=$IFS + IFS=':' + for dir in $kde_use_extra_includes; do + kde_extra_includes="$kde_extra_includes $dir" + USER_INCLUDES="$USER_INCLUDES -I$dir" + done + IFS=$ac_save_ifs + kde_use_extra_includes="added" +else + kde_use_extra_includes="no" +fi +AC_SUBST(USER_INCLUDES) + +AC_MSG_RESULT($kde_use_extra_includes) + +kde_extra_libs= +AC_MSG_CHECKING(for extra libs) +AC_ARG_WITH(extra-libs, [ --with-extra-libs=DIR adds non standard library paths], + kde_use_extra_libs=$withval, + kde_use_extra_libs=NONE +) +if test -n "$kde_use_extra_libs" && \ + test "$kde_use_extra_libs" != "NONE"; then + + ac_save_ifs=$IFS + IFS=':' + for dir in $kde_use_extra_libs; do + kde_extra_libs="$kde_extra_libs $dir" + KDE_EXTRA_RPATH="$KDE_EXTRA_RPATH -R $dir" + USER_LDFLAGS="$USER_LDFLAGS -L$dir" + done + IFS=$ac_save_ifs + kde_use_extra_libs="added" +else + kde_use_extra_libs="no" +fi + +AC_SUBST(USER_LDFLAGS) + +AC_MSG_RESULT($kde_use_extra_libs) + +]) + +AC_DEFUN(KDE_1_CHECK_PATH_HEADERS, +[ + AC_MSG_CHECKING([for KDE headers installed]) + AC_LANG_SAVE + AC_LANG_CPLUSPLUS +cat > conftest.$ac_ext <<EOF +#ifdef STDC_HEADERS +# include <stdlib.h> +#endif +#include <stdio.h> +#include "confdefs.h" +#include <kapp.h> + +int main() { + printf("kde_htmldir=\\"%s\\"\n", KApplication::kde_htmldir().data()); + printf("kde_appsdir=\\"%s\\"\n", KApplication::kde_appsdir().data()); + printf("kde_icondir=\\"%s\\"\n", KApplication::kde_icondir().data()); + printf("kde_sounddir=\\"%s\\"\n", KApplication::kde_sounddir().data()); + printf("kde_datadir=\\"%s\\"\n", KApplication::kde_datadir().data()); + printf("kde_locale=\\"%s\\"\n", KApplication::kde_localedir().data()); + printf("kde_cgidir=\\"%s\\"\n", KApplication::kde_cgidir().data()); + printf("kde_confdir=\\"%s\\"\n", KApplication::kde_configdir().data()); + printf("kde_mimedir=\\"%s\\"\n", KApplication::kde_mimedir().data()); + printf("kde_toolbardir=\\"%s\\"\n", KApplication::kde_toolbardir().data()); + printf("kde_wallpaperdir=\\"%s\\"\n", + KApplication::kde_wallpaperdir().data()); + printf("kde_bindir=\\"%s\\"\n", KApplication::kde_bindir().data()); + printf("kde_partsdir=\\"%s\\"\n", KApplication::kde_partsdir().data()); + printf("kde_servicesdir=\\"/tmp/dummy\\"\n"); + printf("kde_servicetypesdir=\\"/tmp/dummy\\"\n"); + printf("kde_moduledir=\\"/tmp/dummy\\"\n"); + printf("kde_styledir=\\"/tmp/dummy\\"\n"); + printf("kde_widgetdir=\\"/tmp/dummy\\"\n"); + return 0; + } +EOF + + ac_compile='${CXX-g++} -c $CXXFLAGS $all_includes $CPPFLAGS conftest.$ac_ext' + if AC_TRY_EVAL(ac_compile); then + AC_MSG_RESULT(yes) + else + AC_MSG_ERROR([your system is not able to compile a small KDE application! +Check, if you installed the KDE header files correctly. +For more details about this problem, look at the end of config.log.]) + fi + + AC_LANG_RESTORE +]) + +AC_DEFUN(KDE_CHECK_KDEQTADDON, +[ +AC_MSG_CHECKING(for kde-qt-addon) +AC_CACHE_VAL(kde_cv_have_kdeqtaddon, +[ + kde_ldflags_safe="$LDFLAGS" + kde_libs_safe="$LIBS" + kde_cxxflags_safe="$CXXFLAGS" + + LIBS="-lkde-qt-addon $LIBQT $LIBS" + CXXFLAGS="$CXXFLAGS -I$prefix/include -I$prefix/include/kde $all_includes" + LDFLAGS="$LDFLAGS $all_libraries $USER_LDFLAGS" + + AC_TRY_LINK([ + #include <qdom.h> + ], + [ + QDomDocument doc; + ], + kde_cv_have_kdeqtaddon=yes, + kde_cv_have_kdeqtaddon=no + ) + + LDFLAGS=$kde_ldflags_safe + LIBS=$kde_libs_safe + CXXFLAGS=$kde_cxxflags_safe +]) + +AC_MSG_RESULT($kde_cv_have_kdeqtaddon) + +if test "$kde_cv_have_kdeqtaddon" = "no"; then + AC_MSG_ERROR([Can't find libkde-qt-addon. You need to install it first. +It is a separate package (and CVS module) named kde-qt-addon.]) +fi +]) + +AC_DEFUN(KDE_CHECK_KIMGIO, +[ + AC_REQUIRE([AC_BASE_PATH_KDE]) + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + AC_REQUIRE([AC_FIND_TIFF]) + AC_REQUIRE([AC_FIND_JPEG]) + AC_REQUIRE([AC_FIND_PNG]) + AC_REQUIRE([KDE_CREATE_LIBS_ALIASES]) + + if test "$1" = "existance"; then + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + kde_save_LIBS="$LIBS" + LIBS="$LIBS $all_libraries $LIBJPEG $LIBTIFF $LIBPNG $LIBQT -lm" + AC_CHECK_LIB(kimgio, kimgioRegister, [ + LIBKIMGIO_EXISTS=yes],LIBKIMGIO_EXISTS=no) + LIBS="$kde_save_LIBS" + AC_LANG_RESTORE + else + LIBKIMGIO_EXISTS=yes + fi + + if test "$LIBKIMGIO_EXISTS" = "yes"; then + LIB_KIMGIO='-lkimgio' + else + LIB_KIMGIO='' + fi + AC_SUBST(LIB_KIMGIO) +]) + +AC_DEFUN(KDE_CREATE_LIBS_ALIASES, +[ + AC_REQUIRE([KDE_MISC_TESTS]) + AC_REQUIRE([KDE_CHECK_LIBDL]) + AC_REQUIRE([K_PATH_X]) + +if test $kde_qtver = 3; then + LIB_KDECORE='-lkdecore' + AC_SUBST(LIB_KDECORE) + LIB_KDEUI='-lkdeui' + AC_SUBST(LIB_KDEUI) + LIB_KIO='-lkio' + AC_SUBST(LIB_KIO) + LIB_SMB='-lsmb' + AC_SUBST(LIB_SMB) + LIB_KAB='-lkab' + AC_SUBST(LIB_KAB) + LIB_KHTML='-lkhtml' + AC_SUBST(LIB_KHTML) + LIB_KSPELL='-lkspell' + AC_SUBST(LIB_KSPELL) + LIB_KPARTS='-lkparts' + AC_SUBST(LIB_KPARTS) + LIB_KDEPRINT='-lkdeprint' + AC_SUBST(LIB_KDEPRINT) +# these are for backward compatibility + LIB_KSYCOCA='-lkio' + AC_SUBST(LIB_KSYCOCA) + LIB_KFILE='-lkio' + AC_SUBST(LIB_KFILE) +elif test $kde_qtver = 2; then + LIB_KDECORE='-lkdecore' + AC_SUBST(LIB_KDECORE) + LIB_KDEUI='-lkdeui' + AC_SUBST(LIB_KDEUI) + LIB_KIO='-lkio' + AC_SUBST(LIB_KIO) + LIB_KSYCOCA='-lksycoca' + AC_SUBST(LIB_KSYCOCA) + LIB_SMB='-lsmb' + AC_SUBST(LIB_SMB) + LIB_KFILE='-lkfile' + AC_SUBST(LIB_KFILE) + LIB_KAB='-lkab' + AC_SUBST(LIB_KAB) + LIB_KHTML='-lkhtml' + AC_SUBST(LIB_KHTML) + LIB_KSPELL='-lkspell' + AC_SUBST(LIB_KSPELL) + LIB_KPARTS='-lkparts' + AC_SUBST(LIB_KPARTS) + LIB_KDEPRINT='-lkdeprint' + AC_SUBST(LIB_KDEPRINT) +else + LIB_KDECORE='-lkdecore -lXext $(LIB_QT)' + AC_SUBST(LIB_KDECORE) + LIB_KDEUI='-lkdeui $(LIB_KDECORE)' + AC_SUBST(LIB_KDEUI) + LIB_KFM='-lkfm $(LIB_KDECORE)' + AC_SUBST(LIB_KFM) + LIB_KFILE='-lkfile $(LIB_KFM) $(LIB_KDEUI)' + AC_SUBST(LIB_KFILE) + LIB_KAB='-lkab $(LIB_KIMGIO) $(LIB_KDECORE)' + AC_SUBST(LIB_KAB) +fi +]) + +AC_DEFUN(AC_PATH_KDE, +[ + AC_BASE_PATH_KDE + AC_ARG_ENABLE(path-check, [ --disable-path-check don't try to find out, where to install], + [ + if test "$enableval" = "no"; + then ac_use_path_checking="default" + else ac_use_path_checking="" + fi + ], + [ + if test "$kde_qtver" = 1; + then ac_use_path_checking="" + else ac_use_path_checking="default" + fi + ] + ) + + AC_CREATE_KFSSTND($ac_use_path_checking) + + AC_SUBST_KFSSTND + KDE_CREATE_LIBS_ALIASES +]) + +dnl obsolete +AC_DEFUN(AC_CHECK_SETENV, +[ + AC_OBSOLETE([$0], [; instead use AC_CHECK_FUNCS([setenv unsetenv])])dnl + AC_CHECK_FUNCS([setenv unsetenv]) +]) + +AC_DEFUN(AC_CHECK_GETDOMAINNAME, +[ +AC_MSG_CHECKING(for getdomainname) +AC_CACHE_VAL(ac_cv_func_getdomainname, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +save_CXXFLAGS="$CXXFLAGS" +kde_safe_LIBS="$LIBS" +LIBS="$LIBS $X_EXTRA_LIBS" +if test "$GCC" = "yes"; then +CXXFLAGS="$CXXFLAGS -pedantic-errors" +fi +AC_TRY_COMPILE([ +#include <stdlib.h> +#include <unistd.h> +], +[ +char buffer[200]; +getdomainname(buffer, 200); +], +ac_cv_func_getdomainname=yes, +ac_cv_func_getdomainname=no) +CXXFLAGS="$save_CXXFLAGS" +LIBS=$kde_safe_LIBS +AC_LANG_RESTORE +]) +AC_MSG_RESULT($ac_cv_func_getdomainname) + +AC_MSG_CHECKING([if getdomainname needs custom prototype]) +AC_CACHE_VAL(ac_cv_proto_getdomainname, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +if eval "test \"`echo $ac_cv_func_getdomainname`\" = yes"; then + ac_cv_proto_getdomainname=no +else + kde_safe_libs=$LIBS + LIBS="$LIBS $X_EXTRA_LIBS" + AC_TRY_LINK([ +#include <stdlib.h> +#include <unistd.h> + +extern "C" int getdomainname (char *, int); +], +[ +char buffer[200]; +getdomainname(buffer, 200); +], + ac_cv_func_getdomainname=yes + ac_cv_proto_getdomainname=yes, + AC_MSG_RESULT([fatal error]) + AC_MSG_ERROR([getdomainname unavailable])) +fi +LIBS=$kde_safe_libs +AC_LANG_RESTORE +]) +AC_MSG_RESULT($ac_cv_proto_getdomainname) + +if eval "test \"`echo $ac_cv_func_getdomainname`\" = yes"; then + AC_DEFINE(HAVE_GETDOMAINNAME, 1, [Define if you have getdomainname]) +fi +if eval "test \"`echo $ac_cv_proto_getdomainname`\" = no"; then + AC_DEFINE(HAVE_GETDOMAINNAME_PROTO, 1, + [Define if you have getdomainname prototype]) +fi + +]) + +AC_DEFUN(AC_CHECK_GETHOSTNAME, +[ + +AC_MSG_CHECKING([for gethostname]) +AC_CACHE_VAL(ac_cv_func_gethostname, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +save_CXXFLAGS="$CXXFLAGS" +if test "$GCC" = "yes"; then +CXXFLAGS="$CXXFLAGS -pedantic-errors" +fi +AC_TRY_LINK([ +#include <stdlib.h> +#include <unistd.h> +], +[ +char buffer[200]; +gethostname(buffer, 200); +], +ac_cv_func_gethostname=yes, +ac_cv_func_gethostname=no) +CXXFLAGS="$save_CXXFLAGS" +AC_LANG_RESTORE +]) +AC_MSG_RESULT($ac_cv_func_gethostname) + +AC_MSG_CHECKING([if gethostname needs custom prototype]) +AC_CACHE_VAL(ac_cv_proto_gethostname, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +if eval "test \"`echo $ac_cv_func_gethostname`\" = yes"; then + ac_cv_proto_gethostname=no +else + AC_TRY_LINK([ +#include <stdlib.h> +#include <unistd.h> + +extern "C" int gethostname (char *, int); +], +[ +char buffer[200]; +gethostname(buffer, 200); +], + ac_cv_func_gethostname=yes + ac_cv_proto_gethostname=yes, + AC_MSG_RESULT([fatal error]) + AC_MSG_ERROR(gethostname unavailable)) +fi +AC_LANG_RESTORE +]) +AC_MSG_RESULT($ac_cv_proto_gethostname) + +if eval "test \"`echo $ac_cv_proto_gethostname`\" = no"; then + AC_DEFINE(HAVE_GETHOSTNAME_PROTO, 1, + [Define if you have gethostname prototype]) +fi +if eval "test \"`echo $ac_cv_func_gethostname`\" = yes"; then + AC_DEFINE(HAVE_GETHOSTNAME, 1, [Define if you have gethostname]) +fi +]) + +AC_DEFUN(AC_CHECK_USLEEP, +[ +AC_MSG_CHECKING([for usleep]) +AC_CACHE_VAL(ac_cv_func_usleep, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_libs_safe="$LIBS" +LIBS="$LIBS $LIBUCB" +AC_TRY_LINK([ +#include <stdlib.h> +#include <unistd.h> +], +[ +usleep(200); +], +ac_cv_func_usleep=yes, +ac_cv_func_usleep=no) +LIBS="$ac_libs_safe" +AC_LANG_RESTORE +]) +AC_MSG_RESULT($ac_cv_func_usleep) +if eval "test \"`echo $ac_cv_func_usleep`\" = yes"; then + AC_DEFINE(HAVE_USLEEP, 1, [Define if you have the usleep function]) +fi +]) + +AC_DEFUN(AC_CHECK_RANDOM, +[ +AC_MSG_CHECKING([for random]) +AC_CACHE_VAL(ac_cv_func_random, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_libs_safe="$LIBS" +LIBS="$LIBS $LIBUCB" +AC_TRY_LINK([ +#include <stdlib.h> +], +[ +random(); +], +ac_cv_func_random=yes, +ac_cv_func_random=no) +LIBS="$ac_libs_safe" +AC_LANG_RESTORE +]) +AC_MSG_RESULT($ac_cv_func_random) +if eval "test \"`echo $ac_cv_func_random`\" = yes"; then + AC_DEFINE(HAVE_RANDOM, 1, [Define if you have random]) +fi +]) + +AC_DEFUN(AC_FIND_GIF, + [AC_MSG_CHECKING([for giflib]) +AC_CACHE_VAL(ac_cv_lib_gif, +[ac_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes"; then +LIBS="$all_libraries -lgif -lX11 $LIBSOCKET" +else +LIBS="$all_libraries -lgif" +fi +AC_TRY_LINK(dnl +[ +#ifdef __cplusplus +extern "C" { +#endif +int GifLastError(void); +#ifdef __cplusplus +} +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +], + [return GifLastError();], + eval "ac_cv_lib_gif=yes", + eval "ac_cv_lib_gif=no") +LIBS="$ac_save_LIBS" +])dnl +if eval "test \"`echo $ac_cv_lib_gif`\" = yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_LIBGIF, 1, [Define if you have libgif]) +else + AC_MSG_ERROR(You need giflib30. Please install the kdesupport package) +fi +]) + +AC_DEFUN(KDE_FIND_JPEG_HELPER, +[ +AC_MSG_CHECKING([for libjpeg$2]) +AC_CACHE_VAL(ac_cv_lib_jpeg_$1, +[ +AC_LANG_C +ac_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS -ljpeg$2 -lm" +ac_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK( +[/* Override any gcc2 internal prototype to avoid an error. */ +struct jpeg_decompress_struct; +typedef struct jpeg_decompress_struct * j_decompress_ptr; +typedef int size_t; +#ifdef __cplusplus +extern "C" { +#endif + void jpeg_CreateDecompress(j_decompress_ptr cinfo, + int version, size_t structsize); +#ifdef __cplusplus +} +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +], + [jpeg_CreateDecompress(0L, 0, 0);], + eval "ac_cv_lib_jpeg_$1=-ljpeg$2", + eval "ac_cv_lib_jpeg_$1=no") +LIBS="$ac_save_LIBS" +CFLAGS="$ac_save_CFLAGS" +]) + +if eval "test ! \"`echo $ac_cv_lib_jpeg_$1`\" = no"; then + LIBJPEG="$ac_cv_lib_jpeg_$1" + AC_MSG_RESULT($ac_cv_lib_jpeg_$1) +else + AC_MSG_RESULT(no) + $3 +fi + +]) + +AC_DEFUN(AC_FIND_JPEG, +[ +dnl first look for libraries +KDE_FIND_JPEG_HELPER(6b, 6b, + KDE_FIND_JPEG_HELPER(normal, [], + [ + LIBJPEG= + ] + ) +) + +dnl then search the headers (can't use simply AC_TRY_xxx, as jpeglib.h +dnl requires system dependent includes loaded before it) +jpeg_incdirs="/usr/include /usr/local/include $kde_extra_includes" +AC_FIND_FILE(jpeglib.h, $jpeg_incdirs, jpeg_incdir) +test "x$jpeg_incdir" = xNO && jpeg_incdir= + +dnl if headers _and_ libraries are missing, this is no error, and we +dnl continue with a warning (the user will get no jpeg support in khtml) +dnl if only one is missing, it means a configuration error, but we still +dnl only warn +if test -n "$jpeg_incdir" && test -n "$LIBJPEG" ; then + AC_DEFINE_UNQUOTED(HAVE_LIBJPEG, 1, [Define if you have libjpeg]) +else + if test -n "$jpeg_incdir" || test -n "$LIBJPEG" ; then + AC_MSG_WARN([ +There is an installation error in jpeg support. You seem to have only one +of either the headers _or_ the libraries installed. You may need to either +provide correct --with-extra-... options, or the development package of +libjpeg6b. You can get a source package of libjpeg from http://www.ijg.org/ +Disabling JPEG support. +]) + else + AC_MSG_WARN([libjpeg not found. disable JPEG support.]) + fi + jpeg_incdir= + LIBJPEG= +fi + +AC_SUBST(LIBJPEG) +]) + +AC_DEFUN(KDE_CHECK_QT_JPEG, +[ +AC_MSG_CHECKING([if Qt needs $LIBJPEG]) +AC_CACHE_VAL(kde_cv_qt_jpeg, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS $LIBQT" +LIBS=`echo $LIBS | sed "s/$LIBJPEG//"` +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK( +[#include <qapplication.h>], + [ + int argc; + char** argv; + QApplication app(argc, argv);], + eval "kde_cv_qt_jpeg=no", + eval "kde_cv_qt_jpeg=yes") +LIBS="$ac_save_LIBS" +CXXFLAGS="$ac_save_CXXFLAGS" +AC_LANG_RESTORE +]) + +if eval "test ! \"`echo $kde_cv_qt_jpeg`\" = no"; then + AC_MSG_RESULT(yes) + LIBJPEG_QT='$(LIBJPEG)' +else + AC_MSG_RESULT(no) + LIBJPEG_QT= +fi + +]) + +AC_DEFUN(AC_FIND_ZLIB, +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_MSG_CHECKING([for libz]) +AC_CACHE_VAL(ac_cv_lib_z, +[ +AC_LANG_C +kde_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS -lz $LIBSOCKET" +kde_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK(dnl +[ +#include<zlib.h> +], + [return (zlibVersion() == ZLIB_VERSION); ], + eval "ac_cv_lib_z='-lz'", + eval "ac_cv_lib_z=no") +LIBS="$kde_save_LIBS" +CFLAGS="$kde_save_CFLAGS" +])dnl +if test ! "$ac_cv_lib_z" = no; then + AC_DEFINE_UNQUOTED(HAVE_LIBZ, 1, [Define if you have libz]) + LIBZ="$ac_cv_lib_z" + AC_SUBST(LIBZ) + AC_MSG_RESULT($ac_cv_lib_z) +else + AC_MSG_ERROR(not found. Check your installation and look into config.log) + LIBZ="" + AC_SUBST(LIBZ) +fi +]) + +AC_DEFUN(KDE_TRY_TIFFLIB, +[ +AC_MSG_CHECKING([for libtiff $1]) + +AC_CACHE_VAL(kde_cv_libtiff_$1, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +kde_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes"; then +LIBS="$all_libraries $USER_LDFLAGS -l$1 $LIBJPEG $LIBZ -lX11 $LIBSOCKET -lm" +else +LIBS="$all_libraries $USER_LDFLAGS -l$1 $LIBJPEG $LIBZ -lm" +fi +kde_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES" + +AC_TRY_LINK(dnl +[ +#include<tiffio.h> +], + [return (TIFFOpen( "", "r") == 0); ], +[ + kde_cv_libtiff_$1="-l$1 $LIBJPEG $LIBZ" +], [ + kde_cv_libtiff_$1=no +]) + +LIBS="$kde_save_LIBS" +CXXFLAGS="$kde_save_CXXFLAGS" +AC_LANG_RESTORE +]) + +if test "$kde_cv_libtiff_$1" = "no"; then + AC_MSG_RESULT(no) + LIBTIFF="" + $3 +else + LIBTIFF="$kde_cv_libtiff_$1" + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_LIBTIFF, 1, [Define if you have libtiff]) + $2 +fi + +]) + +AC_DEFUN(AC_FIND_TIFF, +[ +AC_REQUIRE([K_PATH_X]) +AC_REQUIRE([AC_FIND_ZLIB]) +AC_REQUIRE([AC_FIND_JPEG]) +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + +KDE_TRY_TIFFLIB(tiff, [], + KDE_TRY_TIFFLIB(tiff34)) + +AC_SUBST(LIBTIFF) +]) + + +AC_DEFUN(AC_FIND_PNG, +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_REQUIRE([AC_FIND_ZLIB]) +AC_MSG_CHECKING([for libpng]) +AC_CACHE_VAL(ac_cv_lib_png, +[ +kde_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes"; then +LIBS="$LIBS $all_libraries $USER_LDFLAGS -lpng $LIBZ -lm -lX11 $LIBSOCKET" +else +LIBS="$LIBS $all_libraries $USER_LDFLAGS -lpng $LIBZ -lm" +fi +kde_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" +AC_LANG_C +AC_TRY_LINK(dnl + [ + #include<png.h> + ], + [ + png_structp png_ptr = png_create_read_struct( /* image ptr */ + PNG_LIBPNG_VER_STRING, 0, 0, 0 ); + return( png_ptr != 0 ); + ], + eval "ac_cv_lib_png='-lpng $LIBZ -lm'", + eval "ac_cv_lib_png=no" +) +LIBS="$kde_save_LIBS" +CFLAGS="$kde_save_CFLAGS" +])dnl +if eval "test ! \"`echo $ac_cv_lib_png`\" = no"; then + AC_DEFINE_UNQUOTED(HAVE_LIBPNG, 1, [Define if you have libpng]) + LIBPNG="$ac_cv_lib_png" + AC_SUBST(LIBPNG) + AC_MSG_RESULT($ac_cv_lib_png) +else + AC_MSG_RESULT(no) + LIBPNG="" + AC_SUBST(LIBPNG) +fi +]) + +AC_DEFUN(AC_CHECK_BOOL, +[ + AC_DEFINE_UNQUOTED(HAVE_BOOL, 1, [You _must_ have bool]) +]) + +AC_DEFUN(AC_CHECK_GNU_EXTENSIONS, +[ +AC_MSG_CHECKING(if you need GNU extensions) +AC_CACHE_VAL(ac_cv_gnu_extensions, +[ +cat > conftest.c << EOF +#include <features.h> + +#ifdef __GNU_LIBRARY__ +yes +#endif +EOF + +if (eval "$ac_cpp conftest.c") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_gnu_extensions=yes +else + ac_cv_gnu_extensions=no +fi +]) + +AC_MSG_RESULT($ac_cv_gnu_extensions) +if test "$ac_cv_gnu_extensions" = "yes"; then + AC_DEFINE_UNQUOTED(_GNU_SOURCE, 1, [Define if you need to use the GNU extensions]) +fi +]) + +AC_DEFUN(KDE_CHECK_COMPILER_FLAG, +[ +AC_MSG_CHECKING(whether $CXX supports -$1) +kde_cache=`echo $1 | sed 'y% .=/+-%____p_%'` +AC_CACHE_VAL(kde_cv_prog_cxx_$kde_cache, +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -$1" + AC_TRY_LINK([],[ return 0; ], [eval "kde_cv_prog_cxx_$kde_cache=yes"], []) + CXXFLAGS="$save_CXXFLAGS" + AC_LANG_RESTORE +]) +if eval "test \"`echo '$kde_cv_prog_cxx_'$kde_cache`\" = yes"; then + AC_MSG_RESULT(yes) + : + $2 +else + AC_MSG_RESULT(no) + : + $3 +fi +]) + +dnl AC_REMOVE_FORBIDDEN removes forbidden arguments from variables +dnl use: AC_REMOVE_FORBIDDEN(CC, [-forbid -bad-option whatever]) +dnl it's all white-space separated +AC_DEFUN(AC_REMOVE_FORBIDDEN, +[ __val=$$1 + __forbid=" $2 " + if test -n "$__val"; then + __new="" + ac_save_IFS=$IFS + IFS=" " + for i in $__val; do + case "$__forbid" in + *" $i "*) AC_MSG_WARN([found forbidden $i in $1, removing it]) ;; + *) # Careful to not add spaces, where there were none, because otherwise + # libtool gets confused, if we change e.g. CXX + if test -z "$__new" ; then __new=$i ; else __new="$__new $i" ; fi ;; + esac + done + IFS=$ac_save_IFS + $1=$__new + fi +]) + +dnl AC_VALIDIFY_CXXFLAGS checks for forbidden flags the user may have given +AC_DEFUN(AC_VALIDIFY_CXXFLAGS, +[dnl +if test "x$kde_use_qt_emb" != "xyes"; then + AC_REMOVE_FORBIDDEN(CXX, [-fno-rtti -rpath]) + AC_REMOVE_FORBIDDEN(CXXFLAGS, [-fno-rtti -rpath]) +else + AC_REMOVE_FORBIDDEN(CXX, [-rpath]) + AC_REMOVE_FORBIDDEN(CXXFLAGS, [-rpath]) +fi +]) + +AC_DEFUN(AC_CHECK_COMPILERS, +[ + AC_ARG_ENABLE(debug,[ --enable-debug[=ARG] enables debug symbols (yes|no|full) [default=no]], + [ + case $enableval in + yes) + kde_use_debug_code="yes" + kde_use_debug_define=no + ;; + full) + kde_use_debug_code="full" + kde_use_debug_define=no + ;; + *) + kde_use_debug_code="no" + kde_use_debug_define=yes + ;; + esac + ], + [kde_use_debug_code="no" + kde_use_debug_define=no + ]) + + dnl Just for configure --help + AC_ARG_ENABLE(dummyoption,[ --disable-debug disables debug output and debug symbols [default=no]],[],[]) + + AC_ARG_ENABLE(strict,[ --enable-strict compiles with strict compiler options (may not work!)], + [ + if test $enableval = "no"; then + kde_use_strict_options="no" + else + kde_use_strict_options="yes" + fi + ], [kde_use_strict_options="no"]) + + AC_ARG_ENABLE(warnings,[ --enable-warnings compiles with -Wall and similiar], + [ + if test $enableval = "no"; then + kde_use_warnings="no" + else + kde_use_warnings="yes" + fi + ], [kde_use_warnings="no"]) + + dnl enable warnings for debug build + if test "$kde_use_debug_code" != "no"; then + kde_use_warnings=yes + fi + + AC_ARG_ENABLE(profile,[ --enable-profile creates profiling infos [default=no]], + [kde_use_profiling=$enableval], + [kde_use_profiling="no"] + ) + + dnl this prevents stupid AC_PROG_CC to add "-g" to the default CFLAGS + CFLAGS=" $CFLAGS" + + AC_PROG_CC + + AC_PROG_CPP + + if test "$GCC" = "yes"; then + if test "$kde_use_debug_code" != "no"; then + if test $kde_use_debug_code = "full"; then + CFLAGS="-g3 $CFLAGS" + else + CFLAGS="-g -O2 $CFLAGS" + fi + else + CFLAGS="-O2 $CFLAGS" + fi + fi + + if test "$kde_use_debug_define" = "yes"; then + CFLAGS="-DNDEBUG $CFLAGS" + fi + + + case "$host" in + *-*-sysv4.2uw*) CFLAGS="-D_UNIXWARE $CFLAGS";; + *-*-sysv5uw7*) CFLAGS="-D_UNIXWARE7 $CFLAGS";; + esac + + if test -z "$LDFLAGS" && test "$kde_use_debug_code" = "no" && test "$GCC" = "yes"; then + LDFLAGS="" + fi + + CXXFLAGS=" $CXXFLAGS" + + AC_PROG_CXX + + if test "$GXX" = "yes" || test "$CXX" = "KCC"; then + if test "$kde_use_debug_code" != "no"; then + if test "$CXX" = "KCC"; then + CXXFLAGS="+K0 -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings $CXXFLAGS" + else + if test "$kde_use_debug_code" = "full"; then + CXXFLAGS="-g3 $CXXFLAGS" + else + CXXFLAGS="-g -O2 $CXXFLAGS" + fi + fi + KDE_CHECK_COMPILER_FLAG(fno-builtin,[CXXFLAGS="-fno-builtin $CXXFLAGS"]) + + dnl convenience compiler flags + KDE_CHECK_COMPILER_FLAG(Woverloaded-virtual, [WOVERLOADED_VIRTUAL="-Woverloaded-virtual"], [WOVERLOADED_VRITUAL=""]) + AC_SUBST(WOVERLOADED_VIRTUAL) + else + if test "$CXX" = "KCC"; then + CXXFLAGS="+K3 $CXXFLAGS" + else + CXXFLAGS="-O2 $CXXFLAGS" + fi + fi + fi + + if test "$kde_use_debug_define" = "yes"; then + CXXFLAGS="-DNDEBUG -DNO_DEBUG $CXXFLAGS" + fi + + if test "$kde_use_profiling" = "yes"; then + KDE_CHECK_COMPILER_FLAG(pg, + [ + CFLAGS="-pg $CFLAGS" + CXXFLAGS="-pg $CXXFLAGS" + ]) + fi + + if test "$kde_use_warnings" = "yes"; then + if test "$GCC" = "yes"; then + case $host in + *-*-linux-gnu) + CFLAGS="-ansi -W -Wall -pedantic -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -D_XOPEN_SOURCE=500 -D_BSD_SOURCE $CFLAGS" + CXXFLAGS="-ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion $CXXFLAGS" + ;; + esac + CXXFLAGS="-Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings $CXXFLAGS" + KDE_CHECK_COMPILER_FLAG(Wundef,[CXXFLAGS="-Wundef $CXXFLAGS"]) + KDE_CHECK_COMPILER_FLAG(Wbad-function-cast,[CXXFLAGS="-Wbad-function-cast $CXXFLAGS"]) + KDE_CHECK_COMPILER_FLAG(Wno-long-long,[CXXFLAGS="-Wno-long-long $CXXFLAGS"]) + KDE_CHECK_COMPILER_FLAG(Wnon-virtual-dtor,[CXXFLAGS="-Wnon-virtual-dtor $CXXFLAGS"]) + fi + fi + + if test "$GCC" = "yes" && test "$kde_use_strict_options" = "yes"; then + CXXFLAGS="-Wcast-qual -Wshadow -Wcast-align $CXXFLAGS" + fi + + if test "$GXX" = "yes"; then + KDE_CHECK_COMPILER_FLAG(fno-exceptions,[CXXFLAGS="$CXXFLAGS -fno-exceptions"]) + KDE_CHECK_COMPILER_FLAG(fno-check-new, [CXXFLAGS="$CXXFLAGS -fno-check-new"]) + KDE_CHECK_COMPILER_FLAG(fexceptions, [USE_EXCEPTIONS="-fexceptions"], USE_EXCEPTIONS= ) + fi + if test "$CXX" = "KCC"; then + dnl unfortunately we currently cannot disable exception support in KCC + dnl because doing so is binary incompatible and Qt by default links with exceptions :-( + dnl KDE_CHECK_COMPILER_FLAG(-no_exceptions,[CXXFLAGS="$CXXFLAGS --no_exceptions"]) + dnl KDE_CHECK_COMPILER_FLAG(-exceptions, [USE_EXCEPTIONS="--exceptions"], USE_EXCEPTIONS= ) + + AC_ARG_ENABLE(pch,[ --enable-pch enables precompiled header support (currently only KCC) [default=no]], + [ + kde_use_pch=$enableval + ],[kde_use_pch=no]) + + if test "$kde_use_pch" = "yes"; then + dnl TODO: support --pch-dir! + KDE_CHECK_COMPILER_FLAG(-pch,[CXXFLAGS="$CXXFLAGS --pch"]) + dnl the below works (but the dir must exist), but it's + dnl useless for a whole package. + dnl The are precompiled headers for each source file, so when compiling + dnl from scratch, it doesn't make a difference, and they take up + dnl around ~5Mb _per_ sourcefile. + dnl KDE_CHECK_COMPILER_FLAG(-pch_dir /tmp, + dnl [CXXFLAGS="$CXXFLAGS --pch_dir `pwd`/pcheaders"]) + fi + dnl this flag controls inlining. by default KCC inlines in optimisation mode + dnl all implementations that are defined inside the class {} declaration. + dnl because of templates-compatibility with broken gcc compilers, this + dnl can cause excessive inlining. This flag limits it to a sane level + KDE_CHECK_COMPILER_FLAG(-inline_keyword_space_time=6,[CXXFLAGS="$CXXFLAGS --inline_keyword_space_time=6"]) + KDE_CHECK_COMPILER_FLAG(-inline_auto_space_time=2,[CXXFLAGS="$CXXFLAGS --inline_auto_space_time=2"]) + KDE_CHECK_COMPILER_FLAG(-inline_implicit_space_time=2.0,[CXXFLAGS="$CXXFLAGS --inline_implicit_space_time=2.0"]) + KDE_CHECK_COMPILER_FLAG(-inline_generated_space_time=2.0,[CXXFLAGS="$CXXFLAGS --inline_generated_space_time=2.0"]) + dnl Some source files are shared between multiple executables + dnl (or libraries) and some of those need template instantiations. + dnl In that case KCC needs to compile those sources with + dnl --one_instantiation_per_object. To make it easy for us we compile + dnl _all_ objects with that flag (--one_per is a shorthand). + KDE_CHECK_COMPILER_FLAG(-one_per, [CXXFLAGS="$CXXFLAGS --one_per"]) + fi + AC_SUBST(USE_EXCEPTIONS) + dnl obsolete macro - provided to keep things going + USE_RTTI= + AC_SUBST(USE_RTTI) + + case "$host" in + *-*-irix*) test "$GXX" = yes && CXXFLAGS="-D_LANGUAGE_C_PLUS_PLUS -D__LANGUAGE_C_PLUS_PLUS $CXXFLAGS" ;; + *-*-sysv4.2uw*) CXXFLAGS="-D_UNIXWARE $CXXFLAGS";; + *-*-sysv5uw7*) CXXFLAGS="-D_UNIXWARE7 $CXXFLAGS";; + *-*-solaris*) + if test "$GXX" = yes; then + libstdcpp=`$CXX -print-file-name=libstdc++.so` + if test ! -f $libstdcpp; then + AC_MSG_ERROR([You've compiled gcc without --enable-shared. This doesn't work with KDE. Please recompile gcc with --enable-shared to receive a libstdc++.so]) + fi + fi + ;; + esac + + AC_VALIDIFY_CXXFLAGS + + AC_PROG_CXXCPP + + # the following is to allow programs, that are known to + # have problems when compiled with -O2 + if test -n "$CXXFLAGS"; then + kde_safe_IFS=$IFS + IFS=" " + NOOPT_CXXFLAGS="" + for i in $CXXFLAGS; do + case $i in + -O*) + ;; + *) + NOOPT_CXXFLAGS="$NOOPT_CXXFLAGS $i" + ;; + esac + done + IFS=$kde_safe_IFS + fi + + if test -n "$CFLAGS"; then + kde_safe_IFS=$IFS + IFS=" " + NOOPT_CFLAGS="" + for i in $CFLAGS; do + case $i in + -O*) + ;; + *) + NOOPT_CFLAGS="$NOOPT_CFLAGS $i" + ;; + esac + done + IFS=$kde_safe_IFS + fi + + if test "x$kde_use_qt_emb" = "xyes"; then + NOOPT_CXXFLAGS="$NOOPT_CXXFLAGS -fno-rtti -DQWS" + fi + + AC_SUBST(NOOPT_CXXFLAGS) + AC_SUBST(NOOPT_CFLAGS) + + KDE_CHECK_FINAL + + ifdef([AM_DEPENDENCIES], AC_REQUIRE([KDE_ADD_DEPENDENCIES]), []) + + KDE_CXXFLAGS= + AC_SUBST(KDE_CXXFLAGS) +]) + +AC_DEFUN(KDE_ADD_DEPENDENCIES, +[ + [A]M_DEPENDENCIES(CC) + [A]M_DEPENDENCIES(CXX) +]) + +dnl just a wrapper to clean up configure.in +AC_DEFUN(KDE_PROG_LIBTOOL, +[ +AC_REQUIRE([AC_CHECK_COMPILERS]) +AC_REQUIRE([AC_ENABLE_SHARED]) +AC_REQUIRE([AC_ENABLE_STATIC]) + +AC_REQUIRE([AC_LIBTOOL_DLOPEN]) + +AC_LANG_SAVE +AC_LANG_C +AC_OBJEXT +AC_EXEEXT +AC_LANG_RESTORE + +AM_PROG_LIBTOOL +AC_LIBTOOL_CXX + +LIBTOOL_SHELL="/bin/sh ./libtool" +# LIBTOOL="$LIBTOOL --silent" +KDE_PLUGIN="-avoid-version -module -no-undefined \$(KDE_RPATH) \$(KDE_MT_LDFLAGS)" +AC_SUBST(KDE_PLUGIN) + +AC_ARG_ENABLE(objprelink, [ --enable-objprelink prelink apps using objprelink (experimental [only tested on linux/386])], + kde_use_objprelink=$enableval, kde_use_objprelink=no) + if test "x$kde_use_objprelink" = "xyes"; then + + KDE_FIND_PATH(objprelink, OBJPRELINK, [], [kde_use_objprelink=no]) + + if test "x$kde_use_objprelink" = "xyes"; then + AC_MSG_CHECKING([Patching libtool to run objprelink.]) + mv libtool libtool.orig + cat > libtool <<\EOF +#! /bin/sh +for n ; do case $n in + *.o) test -r $n && echo objprelink $n && objprelink $n ;; + *.lo) m=`basename $n .lo`".o" && test -r $m && echo objprelink $m && objprelink $m + m=".libs/$m" && test -r $m && echo objprelink $m && objprelink $m ;; +esac; done +EOF + cat >> libtool libtool.orig + rm libtool.orig + chmod a+x libtool + AC_MSG_RESULT(done) + fi + fi +]) + +AC_DEFUN(KDE_CHECK_TYPES, +[ AC_CHECK_SIZEOF(int, 4)dnl + AC_CHECK_SIZEOF(long, 4)dnl + AC_CHECK_SIZEOF(char *, 4)dnl + AC_CHECK_SIZEOF(char, 1)dnl +])dnl + +AC_DEFUN(KDE_DO_IT_ALL, +[ +AC_CANONICAL_SYSTEM +AC_ARG_PROGRAM +AM_INIT_AUTOMAKE($1, $2) +AM_DISABLE_LIBRARIES +AC_PREFIX_DEFAULT(${KDEDIR:-/usr/local/kde}) +AC_CHECK_COMPILERS +KDE_PROG_LIBTOOL +AM_KDE_WITH_NLS +AC_PATH_KDE +]) + +AC_DEFUN(AC_CHECK_RPATH, +[ +AC_MSG_CHECKING(for rpath) +AC_ARG_ENABLE(rpath, + [ --disable-rpath do not use the rpath feature of ld], + USE_RPATH=$enableval, USE_RPATH=yes) + +if test -z "$KDE_RPATH" && test "$USE_RPATH" = "yes"; then + + KDE_RPATH="-R \$(kde_libraries)" + + if test -n "$qt_libraries"; then + KDE_RPATH="$KDE_RPATH -R \$(qt_libraries)" + fi + dnl $x_libraries is set to /usr/lib in case + if test -n "$X_LDFLAGS"; then + KDE_RPATH="$KDE_RPATH -R \$(x_libraries)" + fi + if test -n "$KDE_EXTRA_RPATH"; then + KDE_RPATH="$KDE_RPATH \$(KDE_EXTRA_RPATH)" + fi +fi +AC_SUBST(KDE_EXTRA_RPATH) +AC_SUBST(KDE_RPATH) +AC_MSG_RESULT($USE_RPATH) +]) + +dnl Check for the type of the third argument of getsockname +AC_DEFUN(AC_CHECK_SOCKLEN_T, [ + AC_MSG_CHECKING(for socklen_t) + AC_CACHE_VAL(ac_cv_socklen_t, [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ +#include <sys/types.h> +#include <sys/socket.h> + ],[ +socklen_t a=0; +getsockname(0,(struct sockaddr*)0, &a); + ], + ac_cv_socklen_t=socklen_t, + AC_TRY_COMPILE([ +#include <sys/types.h> +#include <sys/socket.h> + ],[ +int a=0; +getsockname(0,(struct sockaddr*)0, &a); + ], + ac_cv_socklen_t=int, + ac_cv_socklen_t=size_t + ) + ) + AC_LANG_RESTORE + ]) + + AC_MSG_RESULT($ac_cv_socklen_t) + if test "$ac_cv_socklen_t" != "socklen_t"; then + AC_DEFINE_UNQUOTED(socklen_t, $ac_cv_socklen_t, + [Define the real type of socklen_t]) + fi + AC_DEFINE_UNQUOTED(ksize_t, socklen_t, [Compatibility define]) + +]) + +dnl This is a merge of some macros out of the gettext aclocal.m4 +dnl since we don't need anything, I took the things we need +dnl the copyright for them is: +dnl > +dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +dnl This Makefile.in is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. +dnl > +dnl for this file it is relicensed under LGPL + +AC_DEFUN(AM_KDE_WITH_NLS, + [ + dnl If we use NLS figure out what method + + AM_PATH_PROG_WITH_TEST_KDE(MSGFMT, msgfmt, + [test -n "`$ac_dir/$ac_word --version 2>&1 | grep 'GNU gettext'`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + + if test -z "`$GMSGFMT --version 2>&1 | grep 'GNU gettext'`"; then + AC_MSG_RESULT([found msgfmt program is not GNU msgfmt; ignore it]) + GMSGFMT=":" + fi + MSGFMT=$GMSGFMT + AC_SUBST(GMSGFMT) + AC_SUBST(MSGFMT) + + AM_PATH_PROG_WITH_TEST_KDE(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext programs is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + AC_SUBST(XGETTEXT) + + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper <drepper@cygnus.com>, 1996. + +# serial 1 +# Stephan Kulow: I appended a _KDE against name conflicts + +dnl AM_PATH_PROG_WITH_TEST_KDE(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AM_PATH_PROG_WITH_TEST_KDE, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + + +# Check whether LC_MESSAGES is available in <locale.h>. +# Ulrich Drepper <drepper@cygnus.com>, 1995. + +# serial 1 + +AC_DEFUN(AM_LC_MESSAGES, + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your locale.h file contains LC_MESSAGES]) + fi + fi]) + +dnl From Jim Meyering. +dnl FIXME: migrate into libit. + +AC_DEFUN([AM_FUNC_OBSTACK], +[AC_CACHE_CHECK([for obstacks], am_cv_func_obstack, + [AC_TRY_LINK([#include "obstack.h"], + [struct obstack *mem;obstack_free(mem,(char *) 0)], + am_cv_func_obstack=yes, + am_cv_func_obstack=no)]) + if test $am_cv_func_obstack = yes; then + AC_DEFINE(HAVE_OBSTACK) + else + LIBOBJS="$LIBOBJS obstack.o" + fi +]) + +dnl From Jim Meyering. Use this if you use the GNU error.[ch]. +dnl FIXME: Migrate into libit + +AC_DEFUN([AM_FUNC_ERROR_AT_LINE], +[AC_CACHE_CHECK([for error_at_line], am_cv_lib_error_at_line, + [AC_TRY_LINK([],[error_at_line(0, 0, "", 0, "");], + am_cv_lib_error_at_line=yes, + am_cv_lib_error_at_line=no)]) + if test $am_cv_lib_error_at_line = no; then + LIBOBJS="$LIBOBJS error.o" + fi + AC_SUBST(LIBOBJS)dnl +]) + +# Macro to add for using GNU gettext. +# Ulrich Drepper <drepper@cygnus.com>, 1995. + +# serial 1 +# Stephan Kulow: I put a KDE in it to avoid name conflicts + +AC_DEFUN(AM_KDE_GNU_GETTEXT, + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([AM_KDE_WITH_NLS])dnl + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h string.h values.h alloca.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next]) + + AC_MSG_CHECKING(for stpcpy) + AC_CACHE_VAL(kde_cv_func_stpcpy, + [ + kde_safe_cxxflags=$CXXFLAGS + CXXFLAGS="-Wmissing-prototypes -Werror" + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ + #include <string.h> + ], + [ + char buffer[200]; + stpcpy(buffer, buffer); + ], + kde_cv_func_stpcpy=yes, + kde_cv_func_stpcpy=no) + AC_LANG_RESTORE + CXXFLAGS=$kde_safe_cxxflags + ]) + AC_MSG_RESULT($kde_cv_func_stpcpy) + if eval "test \"`echo $kde_cv_func_stpcpy`\" = yes"; then + AC_DEFINE(HAVE_STPCPY, 1, [Define if you have stpcpy]) + fi + + AM_LC_MESSAGES + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + ]) + +AC_DEFUN(AC_HAVE_XPM, + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$XPM_LDFLAGS" && XPM_LDFLAGS= + test -z "$XPM_INCLUDE" && XPM_INCLUDE= + + AC_ARG_WITH(xpm, [ --without-xpm disable color pixmap XPM tests], + xpm_test=$withval, xpm_test="yes") + if test "x$xpm_test" = xno; then + ac_cv_have_xpm=no + else + AC_MSG_CHECKING(for XPM) + AC_CACHE_VAL(ac_cv_have_xpm, + [ + AC_LANG_C + ac_save_ldflags="$LDFLAGS" + ac_save_cflags="$CFLAGS" + if test "x$kde_use_qt_emb" != "xyes"; then + LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS $LDFLAGS $XPM_LDFLAGS $all_libraries -lXpm -lX11 -lXext $LIBZ $LIBSOCKET" + else + LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS $LDFLAGS $XPM_LDFLAGS $all_libraries -lXpm $LIBZ $LIBSOCKET" + fi + CFLAGS="$CFLAGS $X_INCLUDES $USER_INCLUDES" + test -n "$XPM_INCLUDE" && CFLAGS="-I$XPM_INCLUDE $CFLAGS" + AC_TRY_LINK([#include <X11/xpm.h>],[], + ac_cv_have_xpm="yes",ac_cv_have_xpm="no") + LDFLAGS="$ac_save_ldflags" + CFLAGS="$ac_save_cflags" + ])dnl + + if test "$ac_cv_have_xpm" = no; then + AC_MSG_RESULT(no) + XPM_LDFLAGS="" + XPMINC="" + $2 + else + AC_DEFINE(HAVE_XPM, 1, [Define if you have XPM support]) + if test "$XPM_LDFLAGS" = ""; then + XPMLIB='-lXpm $(LIB_X11)' + else + XPMLIB="-L$XPM_LDFLAGS -lXpm "'$(LIB_X11)' + fi + if test "$XPM_INCLUDE" = ""; then + XPMINC="" + else + XPMINC="-I$XPM_INCLUDE" + fi + AC_MSG_RESULT(yes) + $1 + fi + fi + AC_SUBST(XPMINC) + AC_SUBST(XPMLIB) +]) + +AC_DEFUN(AC_HAVE_DPMS, + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$DPMS_LDFLAGS" && DPMS_LDFLAGS= + test -z "$DPMS_INCLUDE" && DPMS_INCLUDE= + DPMS_LIB= + + AC_ARG_WITH(dpms, [ --without-dpms disable DPMS power saving], + dpms_test=$withval, dpms_test="yes") + if test "x$dpms_test" = xno; then + ac_cv_have_dpms=no + else + AC_MSG_CHECKING(for DPMS) + dnl Note: ac_cv_have_dpms can be no, yes, or -lXdpms. + dnl 'yes' means DPMS_LIB="", '-lXdpms' means DPMS_LIB="-lXdpms". + AC_CACHE_VAL(ac_cv_have_dpms, + [ + if test "x$kde_use_qt_emb" = "xyes"; then + AC_MSG_RESULT(no) + ac_cv_have_dpms="no" + else + AC_LANG_C + ac_save_ldflags="$LDFLAGS" + ac_save_cflags="$CFLAGS" + ac_save_libs="$LIBS" + LDFLAGS="$LDFLAGS $DPMS_LDFLAGS $all_libraries -lX11 -lXext $LIBSOCKET" + CFLAGS="$CFLAGS $X_INCLUDES" + test -n "$DPMS_INCLUDE" && CFLAGS="-I$DPMS_INCLUDE $CFLAGS" + AC_TRY_LINK([ + #include <X11/Xproto.h> + #include <X11/X.h> + #include <X11/Xlib.h> + #include <X11/extensions/dpms.h> + int foo_test_dpms() + { return DPMSSetTimeouts( 0, 0, 0, 0 ); }],[], + ac_cv_have_dpms="yes", [ + LDFLAGS="$ac_save_ldflags" + CFLAGS="$ac_save_cflags" + LDFLAGS="$LDFLAGS $DPMS_LDFLAGS $all_libraries -lX11 -lXext $LIBSOCKET" + LIBS="$LIBS -lXdpms" + CFLAGS="$CFLAGS $X_INCLUDES" + test -n "$DPMS_INCLUDE" && CFLAGS="-I$DPMS_INCLUDE $CFLAGS" + AC_TRY_LINK([ + #include <X11/Xproto.h> + #include <X11/X.h> + #include <X11/Xlib.h> + #include <X11/extensions/dpms.h> + int foo_test_dpms() + { return DPMSSetTimeouts( 0, 0, 0, 0 ); }],[], + [ + ac_cv_have_dpms="-lXdpms" + ],ac_cv_have_dpms="no") + ]) + LDFLAGS="$ac_save_ldflags" + CFLAGS="$ac_save_cflags" + LIBS="$ac_save_libs" + fi + ])dnl + + if test "$ac_cv_have_dpms" = no; then + AC_MSG_RESULT(no) + DPMS_LDFLAGS="" + DPMSINC="" + $2 + else + AC_DEFINE(HAVE_DPMS, 1, [Define if you have DPMS support]) + if test "$ac_cv_have_dpms" = "-lXdpms"; then + DPMS_LIB="-lXdpms" + fi + if test "$DPMS_LDFLAGS" = ""; then + DPMSLIB="$DPMS_LIB "'$(LIB_X11)' + else + DPMSLIB="$DPMS_LDFLAGS $DPMS_LIB "'$(LIB_X11)' + fi + if test "$DPMS_INCLUDE" = ""; then + DPMSINC="" + else + DPMSINC="-I$DPMS_INCLUDE" + fi + AC_MSG_RESULT(yes) + $1 + fi + fi + AC_SUBST(DPMSINC) + AC_SUBST(DPMSLIB) +]) + +AC_DEFUN(AC_HAVE_GL, + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$GL_LDFLAGS" && GL_LDFLAGS= + test -z "$GL_INCLUDE" && GL_INCLUDE= + + AC_ARG_WITH(gl, [ --without-gl disable 3D GL modes], + gl_test=$withval, gl_test="yes") + if test "x$kde_use_qt_emb" = "xyes"; then + # GL and Qt Embedded is a no-go for now. + ac_cv_have_gl=no + elif test "x$gl_test" = xno; then + ac_cv_have_gl=no + else + AC_MSG_CHECKING(for GL) + AC_CACHE_VAL(ac_cv_have_gl, + [ + AC_LANG_C + ac_save_ldflags="$LDFLAGS" + ac_save_cflags="$CFLAGS" + LDFLAGS="$LDFLAGS $GL_LDFLAGS $X_LDFLAGS $all_libraries -lMesaGL -lMesaGLU" + test "x$kde_use_qt_emb" != xyes && LDFLAGS="$LDFLAGS -lX11" + LDFLAGS="$LDFLAGS $LIB_XEXT -lm $LIBSOCKET" + CFLAGS="$CFLAGS $X_INCLUDES" + test -n "$GL_INCLUDE" && CFLAGS="-I$GL_INCLUDE $CFLAGS" + AC_TRY_LINK([#include <GL/gl.h> +#include <GL/glu.h> +], [], + ac_cv_have_gl="mesa", ac_cv_have_gl="no") + if test "x$ac_cv_have_gl" = "xno"; then + LDFLAGS="$ac_save_ldflags $X_LDFLAGS $GL_LDFLAGS $all_libraries -lGL -lGLU" + test "x$kde_use_qt_emb" != xyes && LDFLAGS="$LDFLAGS -lX11" + LDFLAGS="$LDFLAGS $LIB_XEXT -lm $LIBSOCKET" + CFLAGS="$ac_save_cflags $X_INCLUDES" + test -n "$GL_INCLUDE" && CFLAGS="-I$GL_INCLUDE $CFLAGS" + AC_TRY_LINK([#include <GL/gl.h> +#include <GL/glu.h> +], [], + ac_cv_have_gl="yes", ac_cv_have_gl="no") + fi + LDFLAGS="$ac_save_ldflags" + CFLAGS="$ac_save_cflags" + ])dnl + + if test "$ac_cv_have_gl" = "no"; then + AC_MSG_RESULT(no) + GL_LDFLAGS="" + GLINC="" + $2 + else + AC_DEFINE(HAVE_GL, 1, [Defines if you have GL (Mesa, OpenGL, ...)]) + if test "$GL_LDFLAGS" = ""; then + if test "$ac_cv_have_gl" = "mesa"; then + GLLIB='-lMesaGL -lMesaGLU $(LIB_X11)' + else + GLLIB='-lGL -lGLU $(LIB_X11)' + fi + else + if test "$ac_cv_have_gl" = "mesa"; then + GLLIB="$GL_LDFLAGS -lMesaGL -lMesaGLU "'$(LIB_X11)' + else + GLLIB="$GL_LDFLAGS -lGL -lGLU "'$(LIB_X11)' + fi + fi + if test "$GL_INCLUDE" = ""; then + GLINC="" + else + GLINC="-I$GL_INCLUDE" + fi + AC_MSG_RESULT($ac_cv_have_gl) + $1 + fi + fi + AC_SUBST(GLINC) + AC_SUBST(GLLIB) +]) + + + dnl shadow password and PAM magic - maintained by ossi@kde.org + +AC_DEFUN(KDE_PAM, [ + AC_REQUIRE([KDE_CHECK_LIBDL]) + + AC_ARG_WITH(pam, + [ --with-pam[=ARG] enable support for PAM: ARG=[yes|no|service name]], + [ if test "x$withval" = "xyes"; then + use_pam=yes + pam_service=kde + elif test "x$withval" = "xno"; then + use_pam=no + else + use_pam=yes + pam_service=$withval + fi + ac_cv_path_pam="use_pam=$use_pam pam_service=$pam_service" + ], [ + AC_CACHE_VAL(ac_cv_path_pam, + [ use_pam=no + AC_CHECK_LIB(pam, pam_start, + [ AC_CHECK_HEADER(security/pam_appl.h, + [ use_pam=yes + pam_service=kde ]) + ], , $LIBDL) + ac_cv_path_pam="use_pam=$use_pam pam_service=$pam_service" + ]) + ]) + eval "$ac_cv_path_pam" + + AC_MSG_CHECKING(for PAM) + if test "x$use_pam" = xno; then + AC_MSG_RESULT(no) + PAMLIBS="" + else + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PAM, 1, [Defines if you have PAM (Pluggable Authentication Modules)]) + PAMLIBS="$PAM_MISC_LIB -lpam $LIBDL" + + dnl test whether struct pam_message is const (Linux) or not (Sun) + AC_MSG_CHECKING(for const pam_message) + AC_EGREP_HEADER([struct pam_message], security/pam_appl.h, + [ AC_EGREP_HEADER([const struct pam_message], security/pam_appl.h, + [AC_MSG_RESULT([const: Linux-type PAM])], + [AC_MSG_RESULT([nonconst: Sun-type PAM]) + AC_DEFINE(PAM_MESSAGE_NONCONST, 1, [Define if your PAM support takes non-const arguments (Solaris)])] + )], + [AC_MSG_RESULT([not found - assume const, Linux-type PAM])]) + fi + + AC_SUBST(PAMLIBS) +]) + +dnl DEF_PAM_SERVICE(arg name, full name, define name) +AC_DEFUN(DEF_PAM_SERVICE, [ + AC_ARG_WITH($1-pam, + [ --with-$1-pam=[val] override PAM service from --with-pam for $2], + [ if test "x$use_pam" = xyes; then + $3_PAM_SERVICE="$withval" + else + AC_MSG_ERROR([Cannot use use --with-$1-pam, as no PAM was detected. +You may want to enforce it by using --with-pam.]) + fi + ], + [ if test "x$use_pam" = xyes; then + $3_PAM_SERVICE="$pam_service" + fi + ]) + if test -n "$$3_PAM_SERVICE"; then + AC_MSG_RESULT([The PAM service used by $2 will be $$3_PAM_SERVICE]) + AC_DEFINE_UNQUOTED($3_PAM_SERVICE, "$$3_PAM_SERVICE", [The PAM service to be used by $2]) + fi + AC_SUBST($3_PAM_SERVICE) +]) + +AC_DEFUN(KDE_SHADOWPASSWD, [ + AC_REQUIRE([KDE_PAM]) + + AC_CHECK_LIB(shadow, getspent, + [ LIBSHADOW="-lshadow" + ac_use_shadow=yes + ], + [ dnl for UnixWare + AC_CHECK_LIB(gen, getspent, + [ LIBGEN="-lgen" + ac_use_shadow=yes + ], + [ AC_CHECK_FUNC(getspent, + [ ac_use_shadow=yes ], + [ ac_use_shadow=no ]) + ]) + ]) + AC_SUBST(LIBSHADOW) + AC_SUBST(LIBGEN) + + AC_MSG_CHECKING([for shadow passwords]) + + AC_ARG_WITH(shadow, + [ --with-shadow If you want shadow password support ], + [ if test "x$withval" != "xno"; then + use_shadow=yes + else + use_shadow=no + fi + ], [ + use_shadow="$ac_use_shadow" + ]) + + if test "x$use_shadow" = xyes; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SHADOW, 1, [Define if you use shadow passwords]) + else + AC_MSG_RESULT(no) + LIBSHADOW= + LIBGEN= + fi + + dnl finally make the relevant binaries setuid root, if we have shadow passwds. + dnl this still applies, if we could use it indirectly through pam. + if test "x$use_shadow" = xyes || + ( test "x$use_pam" = xyes && test "x$ac_use_shadow" = xyes ); then + case $host in + *-*-freebsd* | *-*-netbsd* | *-*-openbsd*) + SETUIDFLAGS="-m 4755 -o root";; + *) + SETUIDFLAGS="-m 4755";; + esac + fi + AC_SUBST(SETUIDFLAGS) + +]) + +AC_DEFUN(KDE_PASSWDLIBS, [ + AC_REQUIRE([KDE_MISC_TESTS]) dnl for LIBCRYPT + AC_REQUIRE([KDE_PAM]) + AC_REQUIRE([KDE_SHADOWPASSWD]) + + if test "x$use_pam" = "xyes"; then + PASSWDLIBS="$PAMLIBS" + else + PASSWDLIBS="$LIBCRYPT $LIBSHADOW $LIBGEN" + fi + + dnl FreeBSD uses a shadow-like setup, where /etc/passwd holds the users, but + dnl /etc/master.passwd holds the actual passwords. /etc/master.passwd requires + dnl root to read, so kcheckpass needs to be root (even when using pam, since pam + dnl may need to read /etc/master.passwd). + case $host in + *-*-freebsd*) + SETUIDFLAGS="-m 4755 -o root" + ;; + *) + ;; + esac + + AC_SUBST(PASSWDLIBS) +]) + +AC_DEFUN(KDE_CHECK_LIBDL, +[ +AC_CHECK_LIB(dl, dlopen, [ +LIBDL="-ldl" +ac_cv_have_dlfcn=yes +]) + +AC_CHECK_LIB(dld, shl_unload, [ +LIBDL="-ldld" +ac_cv_have_shload=yes +]) + +AC_SUBST(LIBDL) +]) + +AC_DEFUN(KDE_CHECK_DLOPEN, +[ +KDE_CHECK_LIBDL +AC_CHECK_HEADERS(dlfcn.h dl.h) +if test "$ac_cv_header_dlfcn_h" = "no"; then + ac_cv_have_dlfcn=no +fi + +if test "$ac_cv_header_dl_h" = "no"; then + ac_cv_have_shload=no +fi + +dnl XXX why change enable_dlopen? its already set by autoconf's AC_ARG_ENABLE +dnl (MM) +AC_ARG_ENABLE(dlopen, +[ --disable-dlopen link statically [default=no]] , +enable_dlopen=$enableval, +enable_dlopen=yes) + +# override the user's opinion, if we know it better ;) +if test "$ac_cv_have_dlfcn" = "no" && test "$ac_cv_have_shload" = "no"; then + enable_dlopen=no +fi + +if test "$ac_cv_have_dlfcn" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_DLFCN, 1, [Define if you have dlfcn]) +fi + +if test "$ac_cv_have_shload" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_SHLOAD, 1, [Define if you have shload]) +fi + +if test "$enable_dlopen" = no ; then + test -n "$1" && eval $1 +else + test -n "$2" && eval $2 +fi + +]) + +AC_DEFUN(KDE_CHECK_DYNAMIC_LOADING, +[ +KDE_CHECK_DLOPEN(libtool_enable_shared=yes, libtool_enable_static=no) +KDE_PROG_LIBTOOL +AC_MSG_CHECKING([dynamic loading]) +eval "`egrep '^build_libtool_libs=' libtool`" +if test "$build_libtool_libs" = "yes" && test "$enable_dlopen" = "yes"; then + dynamic_loading=yes + AC_DEFINE_UNQUOTED(HAVE_DYNAMIC_LOADING) +else + dynamic_loading=no +fi +AC_MSG_RESULT($dynamic_loading) +if test "$dynamic_loading" = "yes"; then + $1 +else + $2 +fi +]) + +AC_DEFUN(KDE_ADD_INCLUDES, +[ +if test -z "$1"; then + test_include="Pix.h" +else + test_include="$1" +fi + +AC_MSG_CHECKING([for libg++ ($test_include)]) + +AC_CACHE_VAL(kde_cv_libgpp_includes, +[ +kde_cv_libgpp_includes=no + + for ac_dir in \ + \ + /usr/include/g++ \ + /usr/include \ + /usr/unsupported/include \ + /opt/include \ + $extra_include \ + ; \ + do + if test -r "$ac_dir/$test_include"; then + kde_cv_libgpp_includes=$ac_dir + break + fi + done +]) + +AC_MSG_RESULT($kde_cv_libgpp_includes) +if test "$kde_cv_libgpp_includes" != "no"; then + all_includes="-I$kde_cv_libgpp_includes $all_includes $USER_INCLUDES" +fi +]) +]) + + +AC_DEFUN(KDE_CHECK_MICO, +[ +AC_REQUIRE([KDE_CHECK_LIBDL]) +AC_REQUIRE([KDE_MISC_TESTS]) +AC_MSG_CHECKING(for MICO) + +if test -z "$MICODIR"; then + kde_micodir=/usr/local + else + kde_micodir="$MICODIR" +fi + +AC_ARG_WITH(micodir, + [ --with-micodir=micodir where mico is installed ], + kde_micodir=$withval, + kde_micodir=$kde_micodir +) + +AC_CACHE_VAL(kde_cv_mico_incdir, +[ + mico_incdirs="$kde_micodir/include /usr/include /usr/local/include /usr/local/include /opt/local/include $kde_extra_includes" +AC_FIND_FILE(CORBA.h, $mico_incdirs, kde_cv_mico_incdir) + +]) +kde_micodir=`echo $kde_cv_mico_incdir | sed -e 's#/include##'` + +if test ! -r $kde_micodir/include/CORBA.h; then + AC_MSG_ERROR([No CORBA.h found, specify another micodir]) +fi + +AC_MSG_RESULT($kde_micodir) + +MICO_INCLUDES=-I$kde_micodir/include +AC_SUBST(MICO_INCLUDES) +MICO_LDFLAGS=-L$kde_micodir/lib +AC_SUBST(MICO_LDFLAGS) +micodir=$kde_micodir +AC_SUBST(micodir) + +AC_MSG_CHECKING([for MICO version]) +AC_CACHE_VAL(kde_cv_mico_version, +[ +AC_LANG_C +cat >conftest.$ac_ext <<EOF +#include <stdio.h> +#include <mico/version.h> +int main() { + + printf("MICO_VERSION=%s\n",MICO_VERSION); + return (0); +} +EOF +ac_compile='${CC-gcc} $CFLAGS $MICO_INCLUDES conftest.$ac_ext -o conftest' +if AC_TRY_EVAL(ac_compile); then + if eval `./conftest 2>&5`; then + kde_cv_mico_version=$MICO_VERSION + else + AC_MSG_ERROR([your system is not able to execute a small application to + find MICO version! Check $kde_micodir/include/mico/version.h]) + fi +else + AC_MSG_ERROR([your system is not able to compile a small application to + find MICO version! Check $kde_micodir/include/mico/version.h]) +fi +]) + +dnl installed MICO version +mico_v_maj=`echo $kde_cv_mico_version | sed -e 's/^\(.*\)\..*\..*$/\1/'` +mico_v_mid=`echo $kde_cv_mico_version | sed -e 's/^.*\.\(.*\)\..*$/\1/'` +mico_v_min=`echo $kde_cv_mico_version | sed -e 's/^.*\..*\.\(.*\)$/\1/'` + +if test "x$1" = "x"; then + req_version="2.3.0" +else + req_version=$1 +fi + +dnl required MICO version +req_v_maj=`echo $req_version | sed -e 's/^\(.*\)\..*\..*$/\1/'` +req_v_mid=`echo $req_version | sed -e 's/^.*\.\(.*\)\..*$/\1/'` +req_v_min=`echo $req_version | sed -e 's/^.*\..*\.\(.*\)$/\1/'` + +if test "$mico_v_maj" -lt "$req_v_maj" || \ + ( test "$mico_v_maj" -eq "$req_v_maj" && \ + test "$mico_v_mid" -lt "$req_v_mid" ) || \ + ( test "$mico_v_mid" -eq "$req_v_mid" && \ + test "$mico_v_min" -lt "$req_v_min" ) + +then + AC_MSG_ERROR([found MICO version $kde_cv_mico_version but version $req_version \ +at least is required. You should upgrade MICO.]) +else + AC_MSG_RESULT([$kde_cv_mico_version (minimum version $req_version, ok)]) +fi + +LIBMICO="-lmico$kde_cv_mico_version $LIBCRYPT $LIBSOCKET $LIBDL" +AC_SUBST(LIBMICO) +if test -z "$IDL"; then + IDL='$(kde_bindir)/cuteidl' +fi +AC_SUBST(IDL) +IDL_DEPENDENCIES='$(kde_includes)/CUTE.h' +AC_SUBST(IDL_DEPENDENCIES) + +idldir="\$(includedir)/idl" +AC_SUBST(idldir) + +]) + +AC_DEFUN(KDE_CHECK_MINI_STL, +[ +AC_REQUIRE([KDE_CHECK_MICO]) + +AC_MSG_CHECKING(if we use mico's mini-STL) +AC_CACHE_VAL(kde_cv_have_mini_stl, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +kde_save_cxxflags="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $MICO_INCLUDES" +AC_TRY_COMPILE( +[ +#include <mico/config.h> +], +[ +#ifdef HAVE_MINI_STL +#error "nothing" +#endif +], +kde_cv_have_mini_stl=no, +kde_cv_have_mini_stl=yes) +CXXFLAGS="$kde_save_cxxflags" +AC_LANG_RESTORE +]) + +if test "x$kde_cv_have_mini_stl" = "xyes"; then + AC_MSG_RESULT(yes) + $1 +else + AC_MSG_RESULT(no) + $2 +fi +]) + +]) + + +AC_DEFUN(KDE_CHECK_LIBPTHREAD, +[ +AC_CHECK_LIB(pthread, pthread_create, [LIBPTHREAD="-lpthread"] ) +AC_SUBST(LIBPTHREAD) +]) + +AC_DEFUN(KDE_CHECK_PTHREAD_OPTION, +[ + AC_ARG_ENABLE(kernel-threads, [ --enable-kernel-threads Enable the use of the LinuxThreads port on FreeBSD/i386 only.], + kde_use_kernthreads=$enableval, kde_use_kernthreads=no) + + if test "$kde_use_kernthreads" = "yes"; then + ac_save_CXXFLAGS="$CXXFLAGS" + ac_save_CFLAGS="$CFLAGS" + CXXFLAGS="-I/usr/local/include/pthread/linuxthreads $CXXFLAGS" + CFLAGS="-I/usr/local/include/pthread/linuxthreads $CFLAGS" + AC_CHECK_HEADERS(pthread/linuxthreads/pthread.h) + CXXFLAGS="$ac_save_CXXFLAGS" + CFLAGS="$ac_save_CFLAGS" + if test "$ac_cv_header_pthread_linuxthreads_pthread_h" = "no"; then + kde_use_kernthreads=no + else + dnl Add proper -I and -l statements + AC_CHECK_LIB(lthread, pthread_join, [LIBPTHREAD="-llthread -llgcc_r"]) dnl for FreeBSD + if test "x$LIBPTHREAD" = "x"; then + kde_use_kernthreads=no + else + USE_THREADS="-D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads" + fi + fi + else + USE_THREADS="" + if test -z "$LIBPTHREAD"; then + KDE_CHECK_COMPILER_FLAG(pthread, [USE_THREADS="-pthread"] ) + fi + fi + + case $host_os in + solaris*) + KDE_CHECK_COMPILER_FLAG(mt, [USE_THREADS="-mt"]) + CPPFLAGS="$CPPFLAGS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DUSE_SOLARIS -DSVR4" + ;; + freebsd*) + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" + ;; + aix*) + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" + LIBPTHREAD="$LIBPTHREAD -lc_r" + ;; + linux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" + if test "$CXX" = "KCC"; then + CXXFLAGS="$CXXFLAGS --thread_safe" + NOOPT_CXXFLAGS="$NOOPT_CXXFLAGS --thread_safe" + fi + ;; + *) + ;; + esac + AC_SUBST(USE_THREADS) + AC_SUBST(LIBPTHREAD) +]) + +AC_DEFUN(KDE_CHECK_THREADING, +[ + AC_REQUIRE([KDE_CHECK_LIBPTHREAD]) + AC_REQUIRE([KDE_CHECK_PTHREAD_OPTION]) + dnl default is yes if libpthread is found and no if no libpthread is available + if test -z "$LIBPTHREAD"; then + if test -z "$USE_THREADS"; then + kde_check_threading_default=no + else + kde_check_threading_default=yes + fi + else + kde_check_threading_default=yes + fi + AC_ARG_ENABLE(threading, [ --disable-threading disables threading even if libpthread found ], + kde_use_threading=$enableval, kde_use_threading=$kde_check_threading_default) + if test "x$kde_use_threading" = "xyes"; then + AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define if you have a working libpthread (will enable threaded code)]) + fi +]) + +AC_DEFUN(KDE_TRY_LINK_PYTHON, +[ +if test "$kde_python_link_found" = no; then + +if test "$1" = normal; then + AC_MSG_CHECKING(if a Python application links) +else + AC_MSG_CHECKING(if Python depends on $2) +fi + +AC_CACHE_VAL(kde_cv_try_link_python_$1, +[ +AC_LANG_SAVE +AC_LANG_C +kde_save_cflags="$CFLAGS" +CFLAGS="$CFLAGS $PYTHONINC" +kde_save_libs="$LIBS" +LIBS="$LIBS $LIBPYTHON $2 $LIBDL $LIBSOCKET" +kde_save_ldflags="$LDFLAGS" +LDFLAGS="$LDFLAGS $PYTHONLIB" + +AC_TRY_LINK( +[ +#include <Python.h> +],[ + PySys_SetArgv(1, 0); +], + [kde_cv_try_link_python_$1=yes], + [kde_cv_try_link_python_$1=no] +) +CFLAGS="$kde_save_cflags" +LIBS="$kde_save_libs" +LDFLAGS="$kde_save_ldflags" +]) + +if test "$kde_cv_try_link_python_$1" = "yes"; then + AC_MSG_RESULT(yes) + kde_python_link_found=yes + if test ! "$1" = normal; then + LIBPYTHON="$LIBPYTHON $2" + fi + $3 +else + AC_MSG_RESULT(no) + $4 +fi +AC_LANG_RESTORE + +fi + +]) + +AC_DEFUN(KDE_CHECK_PYTHON_DIR, +[ +AC_MSG_CHECKING([for Python directory]) + +AC_CACHE_VAL(kde_cv_pythondir, +[ + if test -z "$PYTHONDIR"; then + kde_cv_pythondir=/usr/local + else + kde_cv_pythondir="$PYTHONDIR" + fi +]) + +AC_ARG_WITH(pythondir, +[ --with-pythondir=pythondir use python installed in pythondir ], +[ + ac_python_dir=$withval +], ac_python_dir=$kde_cv_pythondir +) + +AC_MSG_RESULT($ac_python_dir) +]) + +AC_DEFUN(KDE_CHECK_PYTHON_INTERN, +[ +AC_REQUIRE([KDE_CHECK_LIBDL]) +AC_REQUIRE([KDE_CHECK_LIBPTHREAD]) +AC_REQUIRE([KDE_CHECK_PYTHON_DIR]) + +if test -z "$1"; then + version="1.5" +else + version="$1" +fi + +AC_MSG_CHECKING([for Python$version]) + +python_incdirs="$ac_python_dir/include /usr/include /usr/local/include/ $kde_extra_includes" +AC_FIND_FILE(Python.h, $python_incdirs, python_incdir) +if test ! -r $python_incdir/Python.h; then + AC_FIND_FILE(python$version/Python.h, $python_incdirs, python_incdir) + python_incdir=$python_incdir/python$version + if test ! -r $python_incdir/Python.h; then + python_incdir=no + fi +fi + +PYTHONINC=-I$python_incdir + +python_libdirs="$ac_python_dir/lib /usr/lib /usr/local /usr/lib $kde_extra_libs" +AC_FIND_FILE(libpython$version.a, $python_libdirs, python_libdir) +if test ! -r $python_libdir/libpython$version.a; then + AC_FIND_FILE(python$version/config/libpython$version.a, $python_libdirs, python_libdir) + python_libdir=$python_libdir/python$version/config + if test ! -r $python_libdir/libpython$version.a; then + python_libdir=no + fi +fi + +PYTHONLIB=-L$python_libdir +kde_orig_LIBPYTHON=$LIBPYTHON +if test -z "$LIBPYTHON"; then + LIBPYTHON=-lpython$version +fi + +python_libdirs="$ac_python_dir/lib /usr/lib /usr/local /usr/lib $kde_extra_libs" +AC_FIND_FILE(python$version/copy.py, $python_libdirs, python_moddir) +python_moddir=$python_moddir/python$version +if test ! -r $python_moddir/copy.py; then + python_moddir=no +fi + +PYTHONMODDIR=$python_moddir + +AC_MSG_RESULT(header $python_incdir library $python_libdir modules $python_moddir) + +if test x$python_incdir = xno || test x$python_libdir = xno || test x$python_moddir = xno; then + LIBPYTHON=$kde_orig_LIBPYTHON + test "x$PYTHONLIB" = "x-Lno" && PYTHONLIB="" + test "x$PYTHONINC" = "x-Ino" && PYTHONINC="" + $2 +else + dnl Note: this test is very weak + kde_python_link_found=no + KDE_TRY_LINK_PYTHON(normal) + KDE_TRY_LINK_PYTHON(m, -lm) + KDE_TRY_LINK_PYTHON(pthread, $LIBPTHREAD) + KDE_TRY_LINK_PYTHON(tcl, -ltcl) + KDE_TRY_LINK_PYTHON(db2, -ldb2) + KDE_TRY_LINK_PYTHON(m_and_thread, [$LIBPTHREAD -lm]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_util, [$LIBPTHREAD -lm -lutil]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db3, [$LIBPTHREAD -lm -ldb-3 -lutil]) + KDE_TRY_LINK_PYTHON(pthread_and_db3, [$LIBPTHREAD -ldb-3]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db, [$LIBPTHREAD -lm -ldb -ltermcap -lutil]) + KDE_TRY_LINK_PYTHON(pthread_and_dl, [$LIBPTHREAD $LIBDL -lutil -lreadline -lncurses -lm]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db_special, [$LIBPTHREAD -lm -ldb -lutil], [], + [AC_MSG_WARN([it seems, Python depends on another library. + Pleae set LIBPYTHON to '-lpython$version -lotherlib' before calling configure to fix this + and contact the authors to let them know about this problem]) + ]) + + LIBPYTHON="$LIBPYTHON $LIBDL $LIBSOCKET" + AC_SUBST(PYTHONINC) + AC_SUBST(PYTHONLIB) + AC_SUBST(LIBPYTHON) + AC_SUBST(PYTHONMODDIR) + AC_DEFINE(HAVE_PYTHON, 1, [Define if you have the development files for python]) +fi + +]) + + +AC_DEFUN(KDE_CHECK_PYTHON, +[ + KDE_CHECK_PYTHON_INTERN("2.2", + [KDE_CHECK_PYTHON_INTERN("2.1", + [KDE_CHECK_PYTHON_INTERN("2.0", [ KDE_CHECK_PYTHON_INTERN($1, $2) ]) + ])]) +]) + +AC_DEFUN(KDE_CHECK_STL_SGI, +[ + AC_MSG_CHECKING([if STL implementation is SGI like]) + AC_CACHE_VAL(kde_cv_stl_type_sgi, + [ + AC_TRY_COMPILE([ +#include <string> +using namespace std; +],[ + string astring="Hallo Welt."; + astring.erase(0, 6); // now astring is "Welt" + return 0; +], kde_cv_stl_type_sgi=yes, + kde_cv_stl_type_sgi=no) +]) + + AC_MSG_RESULT($kde_cv_stl_type_sgi) + + if test "$kde_cv_stl_type_sgi" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_SGI_STL, 1, [Define if you have a STL implementation by SGI]) + fi +]) + +AC_DEFUN(KDE_CHECK_STL_HP, +[ + AC_MSG_CHECKING([if STL implementation is HP like]) + AC_CACHE_VAL(kde_cv_stl_type_hp, + [ + AC_TRY_COMPILE([ +#include <string> +using namespace std; +],[ + string astring="Hello World"; + astring.remove(0, 6); // now astring is "World" + return 0; +], kde_cv_stl_type_hp=yes, + kde_cv_stl_type_hp=no) +]) + AC_MSG_RESULT($kde_cv_stl_type_hp) + + if test "$kde_cv_stl_type_hp" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_HP_STL, 1, [Define if you have a STL implementation by HP]) + fi +]) + +AC_DEFUN(KDE_CHECK_STL, +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="`echo $CXXFLAGS | sed s/-fno-exceptions//`" + KDE_CHECK_STL_SGI + + if test "$kde_cv_stl_type_sgi" = "no"; then + KDE_CHECK_STL_HP + + if test "$kde_cv_stl_type_hp" = "no"; then + AC_MSG_ERROR("no known STL type found - did you forget to install libstdc++[-devel] ?") + fi + fi + + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE +]) + +AC_DEFUN(AC_FIND_QIMGIO, + [AC_REQUIRE([AC_FIND_JPEG]) +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_MSG_CHECKING([for qimgio]) +AC_CACHE_VAL(ac_cv_lib_qimgio, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_save_LIBS="$LIBS" +ac_save_CXXFLAGS="$CXXFLAGS" +LIBS="$all_libraries -lqimgio -lpng -lz $LIBJPEG $LIBQT" +CXXFLAGS="$CXXFLAGS -I$qt_incdir $all_includes" +AC_TRY_RUN(dnl +[ +#include <qimageio.h> +#include <qstring.h> +int main() { + QString t = "hallo"; + t.fill('t'); + qInitImageIO(); +} +], + ac_cv_lib_qimgio=yes, + ac_cv_lib_qimgio=no, + ac_cv_lib_qimgio=no) +LIBS="$ac_save_LIBS" +CXXFLAGS="$ac_save_CXXFLAGS" +AC_LANG_RESTORE +])dnl +if eval "test \"`echo $ac_cv_lib_qimgio`\" = yes"; then + LIBQIMGIO="-lqimgio -lpng -lz $LIBJPEG" + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_QIMGIO, 1, [Define if you have the Qt extension qimgio available]) + AC_SUBST(LIBQIMGIO) +else + AC_MSG_RESULT(not found) +fi +]) + +AC_DEFUN(KDE_CHECK_ANSI, +[ +]) + +AC_DEFUN(KDE_CHECK_INSURE, +[ + AC_ARG_ENABLE(insure, [ --enable-insure use insure++ for debugging [default=no]], + [ + if test $enableval = "no"; dnl + then ac_use_insure="no" + else ac_use_insure="yes" + fi + ], [ac_use_insure="no"]) + + AC_MSG_CHECKING(if we will use Insure++ to debug) + AC_MSG_RESULT($ac_use_insure) + if test "$ac_use_insure" = "yes"; dnl + then CC="insure"; CXX="insure"; dnl CFLAGS="$CLAGS -fno-rtti -fno-exceptions "???? + fi +]) + +AC_DEFUN(AM_DISABLE_LIBRARIES, +[ + AC_PROVIDE([AM_ENABLE_STATIC]) + AC_PROVIDE([AM_ENABLE_SHARED]) + enable_static=no + enable_shared=yes +]) + + +AC_DEFUN(AC_CHECK_UTMP_FILE, +[ + AC_MSG_CHECKING([for utmp file]) + + AC_CACHE_VAL(kde_cv_utmp_file, + [ + kde_cv_utmp_file=no + + for ac_file in \ + \ + /var/run/utmp \ + /var/adm/utmp \ + /etc/utmp \ + ; \ + do + if test -r "$ac_file"; then + kde_cv_utmp_file=$ac_file + break + fi + done + ]) + + if test "$kde_cv_utmp_file" != "no"; then + AC_DEFINE_UNQUOTED(UTMP, "$kde_cv_utmp_file", [Define the file for utmp entries]) + $1 + AC_MSG_RESULT($kde_cv_utmp_file) + else + $2 + AC_MSG_RESULT([non found]) + fi +]) + + +AC_DEFUN(KDE_CREATE_SUBDIRSLIST, +[ + +DO_NOT_COMPILE="$DO_NOT_COMPILE CVS debian bsd-port admin" + +if test ! -s $srcdir/subdirs; then + dnl Note: Makefile.common creates subdirs, so this is just a fallback + TOPSUBDIRS="" + files=`cd $srcdir && ls -1` + dirs=`for i in $files; do if test -d $i; then echo $i; fi; done` + for i in $dirs; do + echo $i >> $srcdir/subdirs + done +fi + +if test -s $srcdir/inst-apps; then + ac_topsubdirs="`cat $srcdir/inst-apps`" +else + ac_topsubdirs="`cat $srcdir/subdirs`" +fi + +for i in $ac_topsubdirs; do + AC_MSG_CHECKING([if $i should be compiled]) + if test -d $srcdir/$i; then + install_it="yes" + for j in $DO_NOT_COMPILE; do + if test $i = $j; then + install_it="no" + fi + done + else + install_it="no" + fi + AC_MSG_RESULT($install_it) + if test $install_it = "yes"; then + TOPSUBDIRS="$TOPSUBDIRS $i" + fi +done + +AC_SUBST(TOPSUBDIRS) +]) + +AC_DEFUN(KDE_CHECK_NAMESPACES, +[ +AC_MSG_CHECKING(whether C++ compiler supports namespaces) +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +AC_TRY_COMPILE([ +], +[ +namespace Foo { + extern int i; + namespace Bar { + extern int i; + } +} + +int Foo::i = 0; +int Foo::Bar::i = 1; +],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_NAMESPACES) +], [ +AC_MSG_RESULT(no) +]) +AC_LANG_RESTORE +]) + +AC_DEFUN(KDE_CHECK_NEWLIBS, +[ + +]) + +dnl ------------------------------------------------------------------------ +dnl Check for S_ISSOCK macro. Doesn't exist on Unix SCO. faure@kde.org +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN(AC_CHECK_S_ISSOCK, +[ +AC_MSG_CHECKING(for S_ISSOCK) +AC_CACHE_VAL(ac_cv_have_s_issock, +[ +AC_LANG_SAVE +AC_LANG_C +AC_TRY_LINK( +[ +#include <sys/stat.h> +], +[ +struct stat buff; +int b = S_ISSOCK( buff.st_mode ); +], +ac_cv_have_s_issock=yes, +ac_cv_have_s_issock=no) +AC_LANG_RESTORE +]) +AC_MSG_RESULT($ac_cv_have_s_issock) +if test "$ac_cv_have_s_issock" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_S_ISSOCK, 1, [Define if sys/stat.h declares S_ISSOCK.]) +fi +]) + +dnl ------------------------------------------------------------------------ +dnl Check for MAXPATHLEN macro, defines KDEMAXPATHLEN. faure@kde.org +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN(AC_CHECK_KDEMAXPATHLEN, +[ +AC_MSG_CHECKING(for MAXPATHLEN) +AC_CACHE_VAL(ac_cv_maxpathlen, +[ +AC_LANG_C +cat > conftest.$ac_ext <<EOF +#ifdef STDC_HEADERS +# include <stdlib.h> +#endif +#include <stdio.h> +#include <sys/param.h> +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +KDE_HELLO MAXPATHLEN + +EOF + +ac_try="$ac_cpp conftest.$ac_ext 2>/dev/null | grep '^KDE_HELLO' >conftest.out" + +if AC_TRY_EVAL(ac_try) && test -s conftest.out; then + ac_cv_maxpathlen=`sed 's#KDE_HELLO ##' conftest.out` +else + ac_cv_maxpathlen=1024 +fi + +rm conftest.* + +]) +AC_MSG_RESULT($ac_cv_maxpathlen) +AC_DEFINE_UNQUOTED(KDEMAXPATHLEN,$ac_cv_maxpathlen, [Define a safe value for MAXPATHLEN] ) +]) + +dnl ------------------------------------------------------------------------- +dnl See if the compiler supports a template repository bero@redhat.de +dnl ------------------------------------------------------------------------- +AC_DEFUN(KDE_COMPILER_REPO, +[ + REPO="" + NOREPO="" + + KDE_CHECK_COMPILER_FLAG(frepo, + [ + REPO="-frepo" + NOREPO="-fno-repo" + ]) + + if test -z "$REPO"; then + KDE_CHECK_COMPILER_FLAG(instances=explicit, + [ + REPO="-instances=explicit" + NOREPO="-instances=extern" + ]) + fi + + if test -n "$REPO"; then + AC_DEFINE_UNQUOTED(HAVE_TEMPLATE_REPOSITORY, 1, + [C++ compiler supports template repository]) + $1 + fi + + AC_SUBST(REPO) + AC_SUBST(NOREPO) +]) + +AC_DEFUN(KDE_CHECK_HEADER, +[ + AC_LANG_SAVE + kde_safe_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $all_includes" + AC_LANG_CPLUSPLUS + AC_CHECK_HEADER($1, $2, $3) + CPPFLAGS=$kde_safe_cppflags + AC_LANG_RESTORE +]) + +AC_DEFUN(KDE_FAST_CONFIGURE, +[ + dnl makes configure fast (needs perl) + AC_ARG_ENABLE(fast-perl, [ --disable-fast-perl disable fast Makefile generation (needs perl)], + with_fast_perl=$enableval, with_fast_perl=yes) +]) + +AC_DEFUN(KDE_CONF_FILES, +[ + val= + if test -f $srcdir/configure.files ; then + val=`sed -e 's%^%\$(top_srcdir)/%' $srcdir/configure.files` + fi + CONF_FILES= + if test -n "$val" ; then + for i in $val ; do + CONF_FILES="$CONF_FILES $i" + done + fi + AC_SUBST(CONF_FILES) +])dnl + +AC_DEFUN(KDE_SET_PREFIX, +[ + unset CDPATH + dnl make $KDEDIR the default for the installation + AC_PREFIX_DEFAULT(${KDEDIR:-/usr/local/kde}) + + if test "x$prefix" = "xNONE"; then + prefix=$ac_default_prefix + ac_configure_args="$ac_configure_args --prefix=$prefix" + fi + KDE_FAST_CONFIGURE + KDE_CONF_FILES +]) + +pushdef([AC_PROG_INSTALL], +[ + dnl our own version, testing for a -p flag + popdef([AC_PROG_INSTALL]) + dnl as AC_PROG_INSTALL works as it works we first have + dnl to save if the user didn't specify INSTALL, as the + dnl autoconf one overwrites INSTALL and we have no chance to find + dnl out afterwards + test -n "$INSTALL" && kde_save_INSTALL_given=$INSTALL + test -n "$INSTALL_PROGRAM" && kde_save_INSTALL_PROGRAM_given=$INSTALL_PROGRAM + test -n "$INSTALL_SCRIPT" && kde_save_INSTALL_SCRIPT_given=$INSTALL_SCRIPT + AC_PROG_INSTALL + + if test -z "$kde_save_INSTALL_given" ; then + # OK, user hasn't given any INSTALL, autoconf found one for us + # now we test, if it supports the -p flag + AC_MSG_CHECKING(for -p flag to install) + rm -f confinst.$$.* > /dev/null 2>&1 + echo "Testtest" > confinst.$$.orig + ac_res=no + if ${INSTALL} -p confinst.$$.orig confinst.$$.new > /dev/null 2>&1 ; then + if test -f confinst.$$.new ; then + # OK, -p seems to do no harm to install + INSTALL="${INSTALL} -p" + ac_res=yes + fi + fi + rm -f confinst.$$.* + AC_MSG_RESULT($ac_res) + fi + dnl the following tries to resolve some signs and wonders coming up + dnl with different autoconf/automake versions + dnl e.g.: + dnl *automake 1.4 install-strip sets A_M_INSTALL_PROGRAM_FLAGS to -s + dnl and has INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(A_M_INSTALL_PROGRAM_FLAGS) + dnl it header-vars.am, so there the actual INSTALL_PROGRAM gets the -s + dnl *automake 1.4a (and above) use INSTALL_STRIP_FLAG and only has + dnl INSTALL_PROGRAM = @INSTALL_PROGRAM@ there, but changes the + dnl install-@DIR@PROGRAMS targets to explicitly use that flag + dnl *autoconf 2.13 is dumb, and thinks it can use INSTALL_PROGRAM as + dnl INSTALL_SCRIPT, which breaks with automake <= 1.4 + dnl *autoconf >2.13 (since 10.Apr 1999) has not that failure + dnl *sometimes KDE does not use the install-@DIR@PROGRAM targets from + dnl automake (due to broken Makefile.am or whatever) to install programs, + dnl and so does not see the -s flag in automake > 1.4 + dnl to clean up that mess we: + dnl +set INSTALL_PROGRAM to use INSTALL_STRIP_FLAG + dnl which cleans KDE's program with automake > 1.4; + dnl +set INSTALL_SCRIPT to only use INSTALL, to clean up autoconf's problems + dnl with automake<=1.4 + dnl note that dues to this sometimes two '-s' flags are used (if KDE + dnl properly uses install-@DIR@PROGRAMS, but I don't care + dnl + dnl And to all this comes, that I even can't write in comments variable + dnl names used by automake, because it is so stupid to think I wanted to + dnl _use_ them, therefor I have written A_M_... instead of AM_ + dnl hmm, I wanted to say something ... ahh yes: Arghhh. + + if test -z "$kde_save_INSTALL_PROGRAM_given" ; then + INSTALL_PROGRAM='${INSTALL} $(INSTALL_STRIP_FLAG)' + fi + if test -z "$kde_save_INSTALL_SCRIPT_given" ; then + INSTALL_SCRIPT='${INSTALL}' + fi +])dnl + +AC_DEFUN(KDE_LANG_CPLUSPLUS, +[AC_LANG_CPLUSPLUS +ac_link='rm -rf SunWS_cache; ${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +pushdef([AC_LANG_CPLUSPLUS], [popdef([AC_LANG_CPLUSPLUS]) KDE_LANG_CPLUSPLUS]) +]) + +pushdef([AC_LANG_CPLUSPLUS], +[popdef([AC_LANG_CPLUSPLUS]) +KDE_LANG_CPLUSPLUS +]) + +AC_DEFUN(KDE_CHECK_LONG_LONG, +[ +AC_MSG_CHECKING(for long long) +AC_CACHE_VAL(kde_cv_c_long_long, +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_LINK([], [ + long long foo = 0; + foo = foo+1; + ], + kde_cv_c_long_long=yes, kde_cv_c_long_long=no) + AC_LANG_RESTORE +]) +AC_MSG_RESULT($kde_cv_c_long_long) +if test "$kde_cv_c_long_long" = yes; then + AC_DEFINE(HAVE_LONG_LONG, 1, [Define if you have long long as datatype]) +fi +]) + +AC_DEFUN(KDE_CHECK_LIB, +[ + kde_save_LDFLAGS="$LDFLAGS" + dnl AC_CHECK_LIB modifies LIBS, so save it here + kde_save_LIBS="$LIBS" + LDFLAGS="$LDFLAGS $all_libraries" + case $host_os in + aix*) LDFLAGS="-brtl $LDFLAGS" + test "$GCC" = yes && LDFLAGS="-Wl,$LDFLAGS" + ;; + esac + AC_CHECK_LIB($1, $2, $3, $4, $5) + LDFLAGS="$kde_save_LDFLAGS" + LIBS="$kde_save_LIBS" +]) + + + + +AC_DEFUN(KDE_CHECK_INITGROUPS, +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_CHECK_FUNCS(initgroups) + if test "x$ac_cv_func_initgroups" = "xyes"; then + case $host_os in + aix*) AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_MSG_CHECKING([for initgroups prototype]) + AC_CACHE_VAL(kde_cv_check_initgroups_proto, + [ AC_TRY_COMPILE( + [ #include <grp.h> + ], + [ char buffer[10]; + gid_t id; + int x = initgroups(buffer,id); + ], + kde_cv_check_initgroups_proto=yes, + kde_cv_check_initgroups_proto=no) + ]) + AC_MSG_RESULT($kde_cv_check_initgroups_proto) + AC_LANG_RESTORE + ;; + *) + kde_cv_check_initgroups_proto=yes + ;; + esac + else + kde_cv_check_initgroups_proto=no + fi + if test "x$kde_cv_check_initgroups_proto" = "xyes"; then + kde_check_initgroups_proto=1 + else + kde_check_initgroups_proto=0 + fi + AC_DEFINE_UNQUOTED(HAVE_INITGROUPS_PROTO,$kde_check_initgroups_proto, + [initgroups may exist but not its prototype (e.g. AIX<4.3.3:8)]) +]) + + +AC_DEFUN(KDE_CHECK_JAVA_DIR, +[ +AC_MSG_CHECKING([for Java directory]) + +AC_ARG_WITH(java, +[ --with-java=javadir use java installed in javadir, --without-java disables ], +[ ac_java_dir=$withval +], ac_java_dir="" +) + +dnl at this point ac_java_dir is either a dir, 'no' to disable, or '' to say look in $PATH +if test "x$ac_java_dir" = "xno"; then + kde_cv_java_bindir=no + kde_cv_java_includedir=no + kde_java_libjvmdir=no + kde_java_libhpidir=no +else + if test "x$ac_java_dir" = "x"; then + dnl No option set -> look in $PATH + AC_CACHE_VAL(kde_cv_java_bindir, + [ + dnl First look for javac in $PATH. If not found we'll look at the option. + KDE_FIND_PATH(javac, JAVAC, [], []) + if test -n "$JAVAC"; then + kde_cv_java_bindir=`echo $JAVAC | sed -e 's,/javac$,/,'` + dnl this substitution might not work - well, we test for jni.h below + kde_cv_java_includedir=`echo $kde_cv_java_bindir | sed -e 's,bin/$,include/,'` + else + kde_cv_java_bindir=no + fi + ]) + else + dnl config option set + kde_cv_java_bindir=$ac_java_dir/bin + kde_cv_java_includedir=$ac_java_dir/include + fi +fi + +dnl At this point kde_cv_java_bindir and kde_cv_java_includedir are either set or "no" +if test "x$kde_cv_java_bindir" != "xno"; then + + dnl Look for libjvm.so + kde_java_libjvmdir=`find $kde_cv_java_bindir/.. -name libjvm.so | sed 's,libjvm.so,,'|head -n 1` + dnl Look for libhpi.so and avoid green threads + kde_java_libhpidir=`find $kde_cv_java_bindir/.. -name libhpi.so | grep -v green | sed 's,libhpi.so,,'` + + dnl Now check everything's fine under there + + if test ! -x "$kde_cv_java_bindir/javac"; then + AC_MSG_ERROR([javac not found under $kde_cv_java_bindir - it seems you passed a wrong --with-java.]) + fi + if test ! -x "$kde_cv_java_bindir/javah"; then + AC_MSG_ERROR([javah not found under $kde_cv_java_bindir. javac was found though! Use --with-java or --without-java.]) + fi + if test ! -x "$kde_cv_java_bindir/jar"; then + AC_MSG_ERROR([jar not found under $kde_cv_java_bindir. javac was found though! Use --with-java or --without-java.]) + fi + if test ! -r "$kde_cv_java_includedir/jni.h"; then + AC_MSG_ERROR([jni.h not found under $kde_cv_java_includedir. Use --with-java or --without-java.]) + fi + if test ! -r "$kde_java_libjvmdir/libjvm.so"; then + AC_MSG_ERROR([libjvm.so not found under $kde_java_libjvmdir. Use --without-java.]) + fi + if test ! -r "$kde_java_libhpidir/libhpi.so"; then + AC_MSG_ERROR([libhpi.so not found under $kde_java_libhpidir. Use --without-java.]) + fi + + jni_includes="-I$kde_cv_java_includedir" + dnl Strange thing, jni.h requires jni_md.h which is under genunix here.. + dnl and under linux here.. + test -d "$kde_cv_java_includedir/linux" && jni_includes="$jni_includes -I$kde_cv_java_includedir/linux" + test -d "$kde_cv_java_includedir/genunix" && jni_includes="$jni_includes -I$kde_cv_java_includedir/genunix" + + dnl Check for JNI version + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_cxxflags_safe="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $all_includes $jni_includes" + + AC_TRY_COMPILE([ +#include <jni.h> + ], + [ +#ifndef JNI_VERSION_1_2 +Syntax Error +#endif + ],[ kde_jni_works=yes ], + [ kde_jni_works=no ]) + + if test $kde_jni_works = no; then + AC_MSG_ERROR([Incorrect version of $kde_cv_java_includedir/jni.h. + You need to have Java Development Kit (JDK) version 1.2. + + Use --with-java to specify another location. + Use --without-java to configure without java support. + Or download a newer JDK and try again. + See e.g. http://java.sun.com/products/jdk/1.2 ]) + fi + + CXXFLAGS="$ac_cxxflags_safe" + AC_LANG_RESTORE + + dnl All tests ok, inform and subst the variables + AC_MSG_RESULT([javac/javah/jar in $kde_cv_java_bindir, jni.h in $kde_cv_java_includedir]) + + JAVAC=$kde_cv_java_bindir/javac + AC_SUBST(JAVAC) + JAVAH=$kde_cv_java_bindir/javah + AC_SUBST(JAVAH) + JAR=$kde_cv_java_bindir/jar + AC_SUBST(JAR) + AC_SUBST(jni_includes) + JVMLIBS="-L$kde_java_libjvmdir -ljvm -L$kde_java_libhpidir -lhpi" + AC_SUBST(JVMLIBS) +fi +]) + +dnl this is a redefinition of autoconf 2.5x's AC_FOREACH. +dnl When the argument list becomes big, as in KDE for AC_OUTPUT in +dnl big packages, m4_foreach is dog-slow. So use our own version of +dnl it. (matz@kde.org) +m4_define([mm_foreach], +[m4_pushdef([$1])_mm_foreach($@)m4_popdef([$1])]) +m4_define([mm_car], [[$1]]) +m4_define([mm_car2], [[$@]]) +m4_define([_mm_foreach], +[m4_if(m4_quote($2), [], [], + [m4_define([$1], [mm_car($2)])$3[]_mm_foreach([$1], + mm_car2(m4_shift($2)), + [$3])])]) +m4_define([AC_FOREACH], +[mm_foreach([$1], m4_split(m4_normalize([$2])), [$3])]) + +AC_DEFUN(KDE_NEED_FLEX, +[ +kde_libs_safe=$LIBS +LIBS="$LIBS $USER_LDFLAGS" +AM_PROG_LEX +LIBS=$kde_libs_safe +if test -z "$LEXLIB"; then + AC_MSG_ERROR([You need to have flex installed.]) +fi +AC_SUBST(LEXLIB) +]) + +AC_DEFUN(AC_PATH_QTOPIA, +[ + dnl TODO: use AC_CACHE_VAL + + if test -z "$1"; then + qtopia_minver_maj=1 + qtopia_minver_min=5 + qtopia_minver_pat=0 + else + qtopia_minver_maj=`echo "$1" | sed -e "s/^\(.*\)\..*\..*$/\1/"` + qtopia_minver_min=`echo "$1" | sed -e "s/^.*\.\(.*\)\..*$/\1/"` + qtopia_minver_pat=`echo "$1" | sed -e "s/^.*\..*\.\(.*\)$/\1/"` + fi + + qtopia_minver="$qtopia_minver_maj$qtopia_minver_min$qtopia_minver_pat" + qtopia_minverstr="$qtopia_minver_maj.$qtopia_minver_min.$qtopia_minver_pat" + + AC_REQUIRE([AC_PATH_QT]) + + AC_MSG_CHECKING([for Qtopia]) + + LIB_QTOPIA="-lqpe" + AC_SUBST(LIB_QTOPIA) + + kde_qtopia_dirs="$QPEDIR /opt/Qtopia" + + ac_qtopia_incdir=NO + + AC_ARG_WITH(qtopia-dir, + [ --with-qtopia-dir=DIR where the root of Qtopia is installed ], + [ ac_qtopia_incdir="$withval"/include] ) + + qtopia_incdirs="" + for dir in $kde_qtopia_dirs; do + qtopia_incdirs="$qtopia_incdirs $dir/include" + done + + if test ! "$ac_qtopia_incdir" = "NO"; then + qtopia_incdirs="$ac_qtopia_incdir $qtopia_incdirs" + fi + + qtopia_incdir="" + AC_FIND_FILE(qpe/qpeapplication.h, $qtopia_incdirs, qtopia_incdir) + ac_qtopia_incdir="$qtopia_incdir" + + if test -z "$qtopia_incdir"; then + AC_MSG_ERROR([Cannot find Qtopia headers. Please check your installation.]) + fi + + qtopia_ver_maj=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION "\(.*\)\..*\..*".*,\1,p'`; + qtopia_ver_min=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION ".*\.\(.*\)\..*".*,\1,p'`; + qtopia_ver_pat=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION ".*\..*\.\(.*\)".*,\1,p'`; + + qtopia_ver="$qtopia_ver_maj$qtopia_ver_min$qtopia_ver_pat" + qtopia_verstr="$qtopia_ver_maj.$qtopia_ver_min.$qtopia_ver_pat" + if test "$qtopia_ver" -lt "$qtopia_minver"; then + AC_MSG_ERROR([found Qtopia version $qtopia_verstr but version $qtopia_minverstr +is required.]) + fi + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + ac_cxxflags_safe="$CXXFLAGS" + ac_ldflags_safe="$LDFLAGS" + ac_libs_safe="$LIBS" + + CXXFLAGS="$CXXFLAGS -I$qtopia_incdir $all_includes" + LDFLAGS="$LDFLAGS $QT_LDFLAGS $all_libraries $USER_LDFLAGS $KDE_MT_LDFLAGS" + LIBS="$LIBS $LIB_QTOPIA $LIBQT" + + cat > conftest.$ac_ext <<EOF +#include "confdefs.h" +#include <qpe/qpeapplication.h> +#include <qpe/version.h> + +int main( int argc, char **argv ) +{ + QPEApplication app( argc, argv ); + return 0; +} +EOF + + if AC_TRY_EVAL(ac_link) && test -s conftest; then + rm -f conftest* + else + rm -f conftest* + AC_MSG_ERROR([Cannot link small Qtopia Application. For more details look at +the end of config.log]) + fi + + CXXFLAGS="$ac_cxxflags_safe" + LDFLAGS="$ac_ldflags_safe" + LIBS="$ac_libs_safe" + + AC_LANG_RESTORE + + QTOPIA_INCLUDES="-I$qtopia_incdir" + AC_SUBST(QTOPIA_INCLUDES) + + AC_MSG_RESULT([found version $qtopia_verstr with headers at $qtopia_incdir]) +]) + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program 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 +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## As a special exception to the GNU General Public License, if you +## distribute this file as part of a program that contains a +## configuration script generated by Autoconf, you may include it under +## the same distribution terms that you use for the rest of that program. + +# serial 47 AC_PROG_LIBTOOL + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl +AC_REQUIRE([LT_AC_PROG_SED])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + ;; + *) + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="[$]2" +])# _LT_AC_SYS_COMPILER + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +[$]* +EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string="`eval $cmd`") 2>/dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +AC_DIVERT_POP +])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + + # recent cygwin and mingw systems supply a stub DllMain which the user + # can override, but on older systems we have to supply one + AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain, + [AC_TRY_LINK([], + [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*); + DllMain (0, 0, 0);], + [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])]) + + case $host/$CC in + *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*) + # old mingw systems require "-dll" to link a DLL, while more recent ones + # require "-mdll" + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -mdll" + AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch, + [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])]) + CFLAGS="$SAVE_CFLAGS" ;; + *-*-cygwin* | *-*-pw32*) + # cygwin systems need to pass --dll to the linker, and not link + # crt.o which will require a WinMain@16 definition. + lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;; + esac + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $3" + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + if (eval $ac_compile 2>conftest.err) && test -s $ac_outfile; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + else + $2=yes + fi + fi + $rm conftest* + CFLAGS="$save_CFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + testring="ABCD" + + case $host_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$testring" 2>/dev/null` \ + = "XX$testring") >/dev/null 2>&1 && + new_result=`expr "X$testring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + testring=$testring$testring + done + testring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# -------------------- +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ------------------------------------------------------------------ +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +[#line __oline__ "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_unknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + cygwin* | mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + ifelse([$1],[],[save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"], + [$1],[CXX],[save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -o out/conftest2.$ac_objext"], + [$1],[GCJ],[save_GCJFLAGS="$GCJFLAGS" + GCJFLAGS="$GCJFLAGS -o out/conftest2.$ac_objext"]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + # According to Tom Tromey, Ian Lance Taylor reported there are C compilers + # that will create temporary files in the current directory regardless of + # the output directory. Thus, making CWD read-only will cause this test + # to fail, enabling locking or at least warning the user not to do parallel + # builds. + chmod -w . + + if (eval $ac_compile 2>out/conftest.err) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s out/conftest.err; then + # Append any errors to the config.log. + cat out/conftest.err 1>&AS_MESSAGE_LOG_FD + else + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + ifelse([$1],[],[CFLAGS="$save_CFLAGS"], + [$1],[CXX],[CXXFLAGS="$save_CXXFLAGS"], + [$1],[GCJ],[GCJFLAGS="$save_GCJFLAGS"]) + chmod u+w . + $rm conftest* out/* + rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var $1)"; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so$major' + ;; + +aix4* | aix5*) + version_type=linux + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}.so$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}.so' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + need_version=no + need_lib_prefix=no + case $GCC,$host_os in + yes,cygwin*) + library_names_spec='$libname.dll.a' + sys_lib_search_path_spec="/lib /lib/w32api /usr/lib /usr/local/lib" + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll' + postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog .libs/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + ;; + yes,mingw*) + library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://"` + if echo "$sys_lib_search_path_spec" | [egrep ';[C-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | sed -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | sed -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + yes,pw32*) + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' + ;; + *) + library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)' + soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + if test "$host_cpu" = ia64; then + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + else + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' + soname_spec='${libname}${release}.sl$major' + fi + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) version_type=irix ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' + soname_spec='${libname}${release}.so$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + need_lib_prefix=no + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' + soname_spec='$libname.so.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags=TAGS], + [include additional configurations @<:@CXX,GCJ@:>@])], + [tagnames="$withval"], + [tagnames="CXX,GCJ" + case $host_os in + mingw*|cygwin*) tagnames="$tagnames,RC" ;; + esac]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | sed -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + AC_LIBTOOL_LANG_CXX_CONFIG + ;; + + GCJ) + AC_LIBTOOL_LANG_GCJ_CONFIG + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + available_tags="$available_tags $tagname" + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 dll's +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +#- set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + egrep "$file_magic_regex" > /dev/null; then + : + else + cat <<EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the path to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$lt_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_PROG_LD_GNU +])# AC_PROG_LD + + +# AC_PROG_LD_GNU +# -------------- +AC_DEFUN([AC_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + lt_cv_prog_gnu_ld=yes +else + lt_cv_prog_gnu_ld=no +fi]) +with_gnu_ld=$lt_cv_prog_gnu_ld +])# AC_PROG_LD_GNU + + +# AC_PROG_LD_RELOAD_FLAG +# ---------------------- +# find reload flag for linker +# -- PORTME Some linkers may need a different reload flag. +AC_DEFUN([AC_PROG_LD_RELOAD_FLAG], +[AC_CACHE_CHECK([for $LD option to reload object files], + lt_cv_ld_reload_flag, + [lt_cv_ld_reload_flag='-r']) +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +])# AC_PROG_LD_RELOAD_FLAG + + +# AC_DEPLIBS_CHECK_METHOD +# ----------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], +[AC_CACHE_CHECK([how to recognise dependant libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given egrep regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi4*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin* | mingw* | pw32*) + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' + lt_cv_file_magic_cmd='/usr/bin/file -L' + case "$host_os" in + rhapsody* | darwin1.[[012]]) + lt_cv_file_magic_test_file=`/System/Library/Frameworks/System.framework/System` + ;; + *) # Darwin 1.3 on + lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' + ;; + esac + ;; + +freebsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + if test "$host_cpu" = ia64; then + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + else + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + fi + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + irix5* | nonstopux*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1" + ;; + esac + lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + case $host_cpu in + alpha* | hppa* | i*86 | ia64* | m68* | mips | mipsel | powerpc* | sparc* | s390* | sh*) + lt_cv_deplibs_check_method=pass_all ;; + *) + # glibc up to 2.1.1 does not perform some relocations on ARM + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; + esac + lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' + else + lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + fi + ;; + +osf3* | osf4* | osf5*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' + lt_cv_file_magic_test_file=/shlib/libc.so + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + lt_cv_file_magic_test_file=/lib/libc.so + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + esac + ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the path to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/${ac_tool_prefix}nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + if ("$tmp_nm" -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then + lt_cv_path_NM="$tmp_nm -B" + break + elif ("$tmp_nm" -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + lt_cv_path_NM="$tmp_nm -p" + break + else + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$lt_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32*) + # These system don't have libm + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, main, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, main, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will +# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided and an installed libltdl is not found, it is +# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' +# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single +# quotes!). If your package is not flat and you're not using automake, +# define top_builddir and top_srcdir appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, main, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# If this macro is not defined by Autoconf, define it here. +ifdef([AC_PROVIDE_IFELSE], + [], + [define([AC_PROVIDE_IFELSE], + [ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) +])# _LT_AC_LANG_CXX + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# -------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([AC_PROG_RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='main(){return(0);}' + +_LT_AC_SYS_COMPILER + +# +# Check for any special shared library compilation flags. +# +_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= +if test "$GCC" = no; then + case $host_os in + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' + ;; + esac +fi +if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then + AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) + if echo "$old_CC $old_CFLAGS " | egrep -e "[[ ]]$]_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[[ ]]" >/dev/null; then : + else + AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) + _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no + fi +fi + + +# +# Check to make sure the static flag actually works. +# +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_DLOPEN_SELF($1) + +# Report which librarie types wil actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C test sources. +ac_ext=cc + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int char *[]) { return(0); }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${CXX-"c++"} +set dummy $CC +compiler="[$]2" +_LT_AC_TAGVAR(compiler, $1)=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if eval "`$CC -print-prog-name=ld` --version 2>&1" | \ + egrep 'GNU ld' > /dev/null; then + with_gnu_ld=yes + + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + egrep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | egrep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux*) + if test $with_gnu_ld = no; then + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + else + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + fi + fi + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + else + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + fi + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + case $host_os in + hpux9*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + ;; + *) + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + fi + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_os in + hpux9*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + ;; + *) + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + fi + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + irix5* | irix6*) + case $cc_basename in + CC) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='templib=`echo $lib | sed -e "s/\.so\..*/\.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='templib=`echo $lib | sed -e "s/\.so\..*/\.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest.so 2>&1 | egrep "ld"`; rm -f libconftest.so; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + cxx) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | sed "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + # NetBSD uses g++ - do we need to do anything? + ;; + osf3*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='templib=`echo $lib | sed -e "s/\.so\..*/\.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | sed "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | egrep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='templib=`echo $lib | sed -e "s/\.so\..*/\.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | sed "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | egrep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sco*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | egrep "\-R|\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | egrep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $linker_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | egrep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $linker_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | egrep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# Figure out "hidden" C++ library dependencies from verbose +# compiler output whening linking a shared library. +cat > conftest.$ac_ext <<EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +EOF + + +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`" + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then + _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then + _LT_AC_TAGVAR(predep_objects, $1)="$p" + else + _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then + _LT_AC_TAGVAR(postdep_objects, $1)="$p" + else + _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out +else + echo "libtool.m4: error: problem compiling C++ test program" +fi + +$rm -f confest.$objext + +case " $_LT_AC_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; +*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes ;; +esac + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_DLOPEN_SELF($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_CXX_CONFIG + + +# AC_LIBTOOL_LANG_GCJ_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) +AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], +[AC_LANG_SAVE + +# Source file extension for C test sources. +ac_ext=java + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +set dummy $CC +compiler="[$]2" +_LT_AC_TAGVAR(compiler, $1)=$CC + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_DLOPEN_SELF($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_GCJ_CONFIG + + +# AC_LIBTOOL_LANG_RC_CONFIG +# -------------------------- +# Ensure that the configuration vars for the Windows resource compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) +AC_DEFUN([_LT_AC_LANG_RC_CONFIG], +[AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +set dummy $CC +compiler="[$]2" +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_RC_CONFIG + + +# AC_LIBTOOL_CONFIG([TAGNAME]) +# ---------------------------- +# If TAGNAME is not passed, then create an initial libtool script +# with a default configuration from the untagged config vars. Otherwise +# add code to config.status for appending the configuration named by +# TAGNAME from the matching tagged config vars. +AC_DEFUN([AC_LIBTOOL_CONFIG], +[# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS RANLIB LN_S LTCC NM SED SHELL \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + _LT_AC_TAGVAR(compiler, $1) \ + _LT_AC_TAGVAR(CC, $1) \ + _LT_AC_TAGVAR(LD, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ + _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ + _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ + _LT_AC_TAGVAR(old_archive_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ + _LT_AC_TAGVAR(predep_objects, $1) \ + _LT_AC_TAGVAR(postdep_objects, $1) \ + _LT_AC_TAGVAR(predeps, $1) \ + _LT_AC_TAGVAR(postdeps, $1) \ + _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ + _LT_AC_TAGVAR(archive_cmds, $1) \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ + _LT_AC_TAGVAR(postinstall_cmds, $1) \ + _LT_AC_TAGVAR(postuninstall_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ + _LT_AC_TAGVAR(allow_undefined_flag, $1) \ + _LT_AC_TAGVAR(no_undefined_flag, $1) \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ + _LT_AC_TAGVAR(exclude_expsyms, $1) \ + _LT_AC_TAGVAR(include_expsyms, $1); do + + case $var in + _LT_AC_TAGVAR(old_archive_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ + _LT_AC_TAGVAR(archive_cmds, $1) | \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\[$]0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'` + ;; + esac + +ifelse([$1], [], + [cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + AC_MSG_NOTICE([creating $ofile])], + [cfgfile="$ofile"]) + + cat <<__EOF__ >> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A sed program that does not truncate output. +SED=$lt_SED + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + + cygwin* | mingw* | pw32* | os2*) + cat <<'EOF' >> "$cfgfile" + # This is a source program that is used to create dlls on Windows + # Don't remove nor modify the starting and closing comments + _LT_AC_FILE_LTDLL_C + # This is a source program that is used to create import libraries + # on Windows for dlls which lack them. Don't remove nor modify the + # starting and closing comments + _LT_AC_FILE_IMPGEN_C +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions -c conftest.$ac_ext], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +solaris* | sysv5*) + symcode='[[BDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $host_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[[ABCDGISTW]]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat <<EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <<EOF >> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + cygwin* | mingw* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX, but not for PA HP-UX. + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + fi + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + *) + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + cxx) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + sco*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + *) + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + unixware*) + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + cygwin* | mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX, but not for PA HP-UX. + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + fi + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + cygwin* | mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + if test "x$host_vendor" = xsni; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-LD' + else + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + fi + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) -DPIC], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) -DPIC" + ;; +esac +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | egrep '(GNU)' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + cygwin* | mingw* | pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an egrep regular expression of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + + extract_expsyms_cmds='test -f $output_objdir/impgen.c || \ + sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~ + test -f $output_objdir/impgen.exe || (cd $output_objdir && \ + if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \ + else $CC -o impgen impgen.c ; fi)~ + $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def' + + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib' + + # cygwin and mingw dlls have different entry points and sets of symbols + # to exclude. + # FIXME: what about values for MSVC? + dll_entry=__cygwin_dll_entry@12 + dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~ + case $host_os in + mingw*) + # mingw values + dll_entry=_DllMainCRTStartup@12 + dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~ + ;; + esac + + # mingw and cygwin differ, and it's simplest to just exclude the union + # of the two symbol sets. + dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 + + # recent cygwin and mingw systems supply a stub DllMain which the user + # can override, but on older systems we have to supply one (in ltdll.c) + if test "x$lt_cv_need_dllmain" = "xyes"; then + ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext " + ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~ + test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~' + else + ltdll_obj= + ltdll_cmds= + fi + + # Extract the symbol export list from an `--export-all' def file, + # then regenerate the def file from the symbol export list, so that + # the compiled dll only exports the symbol export list. + # Be careful not to strip the DATA tag left by newer dlltools. + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"' + $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ + sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols' + + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is. + # If DATA tags from a recent dlltool are present, honour them! + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`head -1 $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname-def; + else + echo EXPORTS > $output_objdir/$soname-def; + _lt_hint=1; + cat $export_symbols | while read symbol; do + set dummy \$symbol; + case \[$]# in + 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;; + *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;; + esac; + _lt_hint=`expr 1 + \$_lt_hint`; + done; + fi~ + '"$ltdll_cmds"' + $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~ + $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~ + $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags' + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + case $host_os in + cygwin* | mingw* | pw32*) + # dlltool doesn't understand --whole-archive et. al. + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + ;; + *) + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + ;; + esac + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | egrep '(GNU)' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi4*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + ;; + + darwin* | rhapsody*) + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + esac + + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. Also zsh mangles + # `"' quotes if we put them in here... so don't! + _LT_AC_TAGVAR(archive_cmds, $1)='$CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring' + # We need to add '_' to the symbols in $export_symbols first + #_LT_AC_TAGVAR(archive_expsym_cmds, $1)="$_LT_AC_TAGVAR(archive_cmds, $1)"' && strip -s $export_symbols' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9* | hpux10* | hpux11*) + if test "$GCC" = yes; then + case $host_os in + hpux9*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + ;; + *) + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + esac + else + case $host_os in + hpux9*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + ;; + *) + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + ;; + esac + fi + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + else + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + fi + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + if test "x$host_vendor" = xsni; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + fi + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4.2uw2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv5*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes +if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + echo 'static int dummy;' > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac +fi +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include <windows.h> +# #undef WIN32_LEAN_AND_MEAN +# #include <stdio.h> +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include <cygwin/cygwin_dll.h> +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_FILE_IMPGEN_C +# -------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_IMPGEN_C], [ +# /* impgen.c starts here */ +# /* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +# +# This file is part of GNU libtool. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# */ +# +# #include <stdio.h> /* for printf() */ +# #include <unistd.h> /* for open(), lseek(), read() */ +# #include <fcntl.h> /* for O_RDONLY, O_BINARY */ +# #include <string.h> /* for strdup() */ +# +# /* O_BINARY isn't required (or even defined sometimes) under Unix */ +# #ifndef O_BINARY +# #define O_BINARY 0 +# #endif +# +# static unsigned int +# pe_get16 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[2]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 2); +# return b[0] + (b[1]<<8); +# } +# +# static unsigned int +# pe_get32 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[4]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 4); +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# static unsigned int +# pe_as32 (ptr) +# void *ptr; +# { +# unsigned char *b = ptr; +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# int +# main (argc, argv) +# int argc; +# char *argv[]; +# { +# int dll; +# unsigned long pe_header_offset, opthdr_ofs, num_entries, i; +# unsigned long export_rva, export_size, nsections, secptr, expptr; +# unsigned long name_rvas, nexp; +# unsigned char *expdata, *erva; +# char *filename, *dll_name; +# +# filename = argv[1]; +# +# dll = open(filename, O_RDONLY|O_BINARY); +# if (dll < 1) +# return 1; +# +# dll_name = filename; +# +# for (i=0; filename[i]; i++) +# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') +# dll_name = filename + i +1; +# +# pe_header_offset = pe_get32 (dll, 0x3c); +# opthdr_ofs = pe_header_offset + 4 + 20; +# num_entries = pe_get32 (dll, opthdr_ofs + 92); +# +# if (num_entries < 1) /* no exports */ +# return 1; +# +# export_rva = pe_get32 (dll, opthdr_ofs + 96); +# export_size = pe_get32 (dll, opthdr_ofs + 100); +# nsections = pe_get16 (dll, pe_header_offset + 4 +2); +# secptr = (pe_header_offset + 4 + 20 + +# pe_get16 (dll, pe_header_offset + 4 + 16)); +# +# expptr = 0; +# for (i = 0; i < nsections; i++) +# { +# char sname[8]; +# unsigned long secptr1 = secptr + 40 * i; +# unsigned long vaddr = pe_get32 (dll, secptr1 + 12); +# unsigned long vsize = pe_get32 (dll, secptr1 + 16); +# unsigned long fptr = pe_get32 (dll, secptr1 + 20); +# lseek(dll, secptr1, SEEK_SET); +# read(dll, sname, 8); +# if (vaddr <= export_rva && vaddr+vsize > export_rva) +# { +# expptr = fptr + (export_rva - vaddr); +# if (export_rva + export_size > vaddr + vsize) +# export_size = vsize - (export_rva - vaddr); +# break; +# } +# } +# +# expdata = (unsigned char*)malloc(export_size); +# lseek (dll, expptr, SEEK_SET); +# read (dll, expdata, export_size); +# erva = expdata - export_rva; +# +# nexp = pe_as32 (expdata+24); +# name_rvas = pe_as32 (expdata+32); +# +# printf ("EXPORTS\n"); +# for (i = 0; i<nexp; i++) +# { +# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4); +# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i); +# } +# +# return 0; +# } +# /* impgen.c ends here */ +])# _LT_AC_FILE_IMPGEN_C + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext" + fi + done + done +done + + # Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. +: ${TMPDIR=/tmp} +{ + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=$TMPDIR/sed$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + { (exit 1); exit 1; } +} + _max=0 + _count=0 + # Add /usr/xpg4/bin/sed as it is typically found on Solaris + # along with /bin/sed that truncates output. + for _sed in $_sed_list /usr/xpg4/bin/sed; do + test ! -f ${_sed} && break + cat /dev/null > "$tmp/sed.in" + _count=0 + echo $ECHO_N "0123456789$ECHO_C" >"$tmp/sed.in" + # Check for GNU sed and select it if it is found. + if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then + lt_cv_path_SED=${_sed} + break; + fi + while true; do + cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp" + mv "$tmp/sed.tmp" "$tmp/sed.in" + cp "$tmp/sed.in" "$tmp/sed.nl" + echo >>"$tmp/sed.nl" + ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break + cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break + # 10000 chars as input seems more than enough + test $_count -gt 10 && break + _count=`expr $_count + 1` + if test $_count -gt $_max; then + _max=$_count + lt_cv_path_SED=$_sed + fi + done + done + rm -rf "$tmp" +]) +AC_MSG_RESULT([$SED]) +]) diff --git a/xembed/autogen.sh b/xembed/autogen.sh new file mode 100755 index 0000000..46e5206 --- /dev/null +++ b/xembed/autogen.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir +PROJECT=XEmbed +TEST_TYPE=-e +FILE=spec/xembed-spec.xml + +DIE=0 + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile $PROJECT." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile $PROJECT." + echo "Get ftp://ftp.cygnus.com/pub/home/tromey/automake-1.2d.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +test $TEST_TYPE $FILE || { + echo "You must run this script in the top-level $PROJECT directory" + exit 1 +} + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +case $CC in +*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;; +esac + +libtoolize --force --copy +aclocal $ACLOCAL_FLAGS + +# optionally use autoheader +(autoheader --version) < /dev/null > /dev/null 2>&1 && autoheader + +automake -a $am_opt +autoconf +cd $ORIGDIR + +$srcdir/configure --enable-maintainer-mode "$@" + +echo +echo "Now type 'make' to compile $PROJECT." diff --git a/xembed/configure.in b/xembed/configure.in new file mode 100644 index 0000000..8e1cbfd --- /dev/null +++ b/xembed/configure.in @@ -0,0 +1,45 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(spec/xembed-spec.xml) + +dnl $Format: "AM_INIT_AUTOMAKE(xembed, $ReleaseVersion$)" $ +AM_INIT_AUTOMAKE(xembed, 0.5) + +dnl Specify a configuration file +AM_CONFIG_HEADER(config.h) + +dnl Initialize libtool +AM_PROG_LIBTOOL + +dnl Initialize maintainer mode +AM_MAINTAINER_MODE + +AC_PROG_CC +AM_PROG_CC_STDC +AC_PROG_INSTALL + +changequote(,)dnl +if test "x$GCC" = "xyes"; then + case " $CFLAGS " in + *[\ \ ]-Wall[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wall" ;; + esac +fi +changequote([,])dnl + +dnl Check for GTK+ +dnl +AM_PATH_GTK_2_0(2.0.0,:, AC_MSG_ERROR([GTK+-2.0.0 or better required])) + +dnl Checks for KDE +dnl +KDE_USE_QT(3) +AC_PATH_KDE + +dnl Output the Makefiles + +AC_OUTPUT([ +Makefile +spec/Makefile +tests/Makefile +]) diff --git a/xembed/spec/.cvsignore b/xembed/spec/.cvsignore new file mode 100644 index 0000000..4879615 --- /dev/null +++ b/xembed/spec/.cvsignore @@ -0,0 +1,5 @@ +Makefile.in +Makefile +*.stamp +*.ps +html diff --git a/xembed/spec/Makefile.am b/xembed/spec/Makefile.am new file mode 100644 index 0000000..9611f10 --- /dev/null +++ b/xembed/spec/Makefile.am @@ -0,0 +1,17 @@ +EXTRA_DIST = xembed-spec.xml + +html-build.stamp: xembed-spec.xml + sdir=`cd $(srcdir) && pwd` && \ + rm -rf html && mkdir html && \ + cd html && \ + docbook2html $$sdir/xembed-spec.xml && \ + touch ../html-build.stamp + +xembed-spec.ps: xembed-spec.xml + docbook2ps $(srcdir)/xembed-spec.xml + +all-local: html-build.stamp xembed-spec.ps + +clean-local: + rm -rf html-build.stamp html xembed-spec.ps + diff --git a/xembed/spec/xembed-spec.xml b/xembed/spec/xembed-spec.xml new file mode 100644 index 0000000..78734a5 --- /dev/null +++ b/xembed/spec/xembed-spec.xml @@ -0,0 +1,1407 @@ +<?xml version="1.0"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +]> +<article id="index"> + <articleinfo> + <title>XEmbed Protocol Specification</title> + <releaseinfo>Version 0.5</releaseinfo> + <date>15 April 2002</date> + <authorgroup> + <author> + <firstname>Mathias</firstname> + <surname>Ettrich</surname> + <affiliation> + <address> + <email>ettrich@trolltech.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Owen</firstname> + <surname>Taylor</surname> + <affiliation> + <address> + <email>otaylor@redhat.com</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="overview"> + <title>Overview</title> + <para> + XEmbed is a protocol that uses basic X mechanisms such as client + messages and reparenting windows to provide embedding of a + control from one application into another application. Some + of the goals of the XEmbed design are: + </para> + <orderedlist> + <listitem> + <para> + Support for out-of process controls, written in any toolkit + or even plain Xlib. + </para> + </listitem> + <listitem> + <para> + Support for in-process-controls when mixing different + toolkits in one process. + </para> + </listitem> + <listitem> + <para> + Smooth integration of the embedding application and embedded client + in areas such as input device handling and visual feedback. + </para> + </listitem> + <listitem> + <para> + Easy implementation. A full implementation supporting all + details correctly may require minor toolkit modifications, + but it should be possible to get basic functionality going + in less than 1000 lines of code. + </para> + </listitem> + </orderedlist> + <para> + Goal 1 is the most urgent one. A embedding specification allows + developers to write applets for whatever desktop the user is + using in whatever toolkit they prefer. Goal 2 is more of + something to keep in mind than a immediate requirement. While + there are other ways to mix two or more toolkits, using XEmbed + might be the easiest and thus most comfortable way. Goal 3 + describes the targeted level of integration. The users should + not necessarily notice that they work with embedded controls; + devices like the keyboard and the mouse should work as expected, + inactive windows should look like they are inactive, and so + forth. The level of integration may, however, be limited by goal + 4. In order for the protocol to be successful, it's crucial to + get implementations for the most important toolkits. Thus, the + implementation should not require too much coding and no or only + few modifications to the toolkit's kernel. + </para> + <para> + At the time of writing, an implementation of XEmbed is included + in GTK+-2.0 that mostly conforms to this version of the + specification. The main area of divergence is in the area of + accelerators, where a simpler scheme is implemented than the + XEMBED_REGISTER_ACCELERATOR, XEMBED_UNREGISTER_ACCELERATOR + accelerator scheme described here. The KDE libraries (libkdeui) + include QXEmbed, a mostly-complete implementation for Qt of an + earlier version of the protocol. + </para> + </sect1> + <sect1 id="definitions"> + <title>Definitions</title> + <variablelist> + <varlistentry> + <term>Active</term> + <listitem> + <para> + A toplevel window is <firstterm>active</firstterm> if it + currently is receiving keyboard events. (The window or a + descendant has the X keyboard focus.) A widget within the + toplevel is active if the toplevel is active, regardless + of whether that widget has the input focus within the + toplevel. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Client</term> + <listitem> + <para> + In an embedding situation, the <firstterm>client</firstterm> is + the window that is embedded into an embedder. Sometimes also + called a plug. (Note that the usage here should not be + confused with the typical X usage of "client" to mean an application + connecting to the X server. That is always referred to as + an application in this document) + </para> + <remark> + [ Should we replace client by some other term in + this document to avoid the confusion? ] + </remark> + </listitem> + </varlistentry> + <varlistentry> + <term>Embedder</term> + <listitem> + <para> + In an embedding situation, the <firstterm>embedder</firstterm> + is the graphical location that embeds an external + client. Sometimes also called a socket or site. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Focused</term> + <listitem> + <para> + A widget is <firstterm>focused</firstterm> if it receives + keyboard events within its toplevel. This is without + regard to whether the toplevel is active, and has nothing + to do with the X keyboard focus. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect1> + <sect1 id="rationale"> + <title>Rationale and discussion</title> + <para> + The basis for handling embedding is that the embedder acts like + a "window manager" for the client. (The window management + protocol is defined in the X Inter-Client Communications Manual + or ICCCM). The embedder selects with SubstructureRedirectMask + on its window so that it can intercept, and then the client + window is reparented (using + <function>XReparentWindow()</function>) + as a child of the embedder window. Because of the substructure redirect, the + embedder is able to intercept calls to move or resize the client + window, and handle them as appropriate to the location in the + embedding application. (Map requests are also redirected, but + XEmbed actually handles map requests separately... see the + description of the XEMBED_MAPPED flag.) + </para> + <para> + The window management protocol is sufficient to handle the + basics of visual embedding, but has deficiencies in other areas + that prevent it from providing natural integration between + toolkits. These areas include: + </para> + + <simplelist> + <member>window activation state</member> + <member>keyboard focus</member> + <member>tab focus chain</member> + <member>keyboard short cuts / accelerators</member> + <member>modality</member> + <member>drag and drop (XDND)</member> + </simplelist> + + <para> + The XEmbed protocol is mainly concerned with communicating + additional information between embedder and client to handle + these areas. Communication in XEmbed is done by forwarding + slightly modified XEvents using + <function>XSendEvent()</function>, + by sending special XEmbed messages, and by setting X properties. In addition, + standard ICCCM features like WMNormalHints are used where + appropriate. + </para> + <para> + The next sections explain why these problems occur with the + simple "window management" approach and how XEmbed solves them. + </para> + + <sect2> + <title>Window activation state</title> + <para> + A widget has to know the activation state of its toplevel + window. This enables input widgets like a line editor, to display + a blinking cursor only when the user can actually type into it. In + addition, certain GUI styles choose to display inactive windows + differently, typically with a lighter and less contrasting color + palette. + </para> + <para> + Unfortunately, there are no such messages like WindowActivate + or WindowDeactivate in the X protocol. Instead, a window knows + that it is active when it receives keyboard focus (FocusIn + event with certain modes) or looses it (FocusOut event with certain + modes). This applies to embedded child windows only, when the + mouse pointer points onto one of the child's subwindows in the very + moment the window manager puts the X focus on the toplevel + window. For that reason, XEmbed requires the embedders to pass + XEMBED_WINDOW_ACTIVATE and XEMBED_WINDOW_DEACTIVATE messages to + their respective clients whenever they get or loose X keyboard + </para> + </sect2> + + <sect2> + <title>Keyboard focus</title> + <para> + The delivery of keyboard events in X is designed in a way that + does not correspond to the typical operation of modern + toolkits; instead it seems designed to allow things to allow + things to work without either a window manager or a focus + handling in the toolkit. Typically, key events are sent to the + window which has the X input focus (set with + XSetInputFocus()). However, if the mouse pointer is inside + that focus window, the event is sent to the subwindow of the + focus window that is under the moues pointer. In modern toolkits, + the X input focus is typically left on the toplevel window and + a separate logical input focus is implemented within the + toolkit. The toolkit ignores the window that the key event is + actually sent to (which might be a scrollbar or other random + widget within the toplevel, depending on where the mouse + pointer is), and distributes key events to widget with the + logical input focus. + </para> + <para> + So, for standard operation, the behavior where key events are sent + to the window with the mouse pointer is simply ignored. But + with embedded windows, it causes problems, since, if the + mouse pointer is within the embedded window, the outer toolkit + doesn't see any key events, even if the logical keyboard focus + is elsewhere within the outer toolkits toplevel window. + </para> + <para> + Previous embedding techniques therefore required clients to + forward any key event they receive (KeyPress and KeyRelease) to + their respective embedder. In order to support multiple levels of + embedding, events that stem from a SendEvent request had to be + forwarded as well. While this is a possible solution, it adds both + race conditions and inefficiency. + </para> + <para> + The solution proposed by XEmbed is is to beat X11 with its own + weapons: The topmost toolkit is <emphasis>required</emphasis> + to keep the X input focus on one of its own windows without + any embedded children. Keeping the focus on such a window + ensures that key events are always delivered to the outer + toolkit and thus can be forwarded easily to any embedded + window. This also makes it possible to use this part of XEmbed + with clients that do not support the protocol at all, without + breaking keyboard input for the embedding application. + </para> + <para> + In detail, the topmost embedder creates a not-visible X Window to + hold the focus, the focus proxy. (It might be a 1x1 child + window of toplevel located at -1,-1.) Since the focus proxy isn't + an ancestor of the client window, the X focus can never move + into the client window because of the mouse pointer location. + In other words, whenever the outer window is activated + (receives the X input focus), it has to put the X focus on the + FocusProxy by calling <function>XSetInputFocus()</function>. + </para> + <para> + The trouble with this is, that you should not use <function>XSetInputFocus()</function> + without a proper time stamp from the Server, to avoid race + conditions. Unfortunately, the FocusIn event does not carry a + timestamp. The solution to this is, to ask the window manager for + the WM_TAKE_FOCUS window protocol. Thus, whenever the window is + activated, it will receive a WM_PROTOCOLS client message with + data.l[0] being WM_TAKE_FOCUS and data.l[1] being a proper + timestamp. This timestamp can be used safely for the call to + <function>XSetInputFocus()</function>. + </para> + <para> + If an embedder widget gets the logical input focus, it sends + an XEMBED_FOCUS_IN message to its client. The client that + receives this messages knows that its logical focus is now + also the logical focus of the application window and will + react accordingly. If its logical focus lies on the line + editor control mentioned above, and the window is active, the + editor will show a blinking cursor after processing this + message. + </para> + <para> + In a similar fashion, if the embedder looses focus, it sends + an XEMBED_FOCUS_OUT message. + </para> + </sect2> + <sect2> + <title>Tab focus chain</title> + <para> + X does not have a concept of a tab focus chain, it is up to the + toolkit or the application to implement it. Since the concept + is standard among almost all toolkits, XEmbed supports it. An + XEmbed client integrates perfectly in the embedder's tab focus + chain, i.e. the user can tab onto the client, through all its + widgets and back to the outer world without noticing that they + traversed an external window. + </para> + <para> + As explained in the previous section, an embedder sends an + XEMBED_FOCUS_IN message to its client when it gets focus. The + detail code of this message is per default 0, that is, + XEMBED_FOCUS_CURRENT. It indicates that the clients keeps its own + logical focus where it was. To support tabbing, XEmbed provides + two more detail codes, namely XEMBED_FOCUS_FIRST and + XEMBED_FOCUS_LAST, that indicate that the client should move + its focus to the beginning or end of the focus chain. + </para> + <para> + When the user tabs to the very end of a client's tab chain, the + client follows the request (i.e. it puts its logical focus back to + the beginning its tab chain) and sends an XEMBED_FOCUS_NEXT + message to the embedder. If the embedder has siblings that accept + tab focus, it will do a virtual tab forward. As a result, it will + loose focus itself and consequently send an XEMBED_FOCUS_OUT + message to the client. As expected, the client's line edit control + from the previous example will stop blinking. + </para> + <para> + Backward tabbing is done exactly in the same manner, using the + XEMBED_FOCUS_PREV message. + </para> + </sect2> + <sect2> + <title>Keyboard short cuts / accelerators</title> + <para> + XEmbed is designed in such a way, that keyboard events are + received by the toplevel window, and then sent down the focus + focus chain. Toolkits will usually check for shortcuts or + accelerators before sending the event to the focus widget. If + such a shortcut is defined, the respective action is taken + rather than passing the event through to the focus + widget. This means, accelerators in the outmost window always + work properly, whereas accelerators defined inside an embedded + client only work if that client actually has focus. XEmbed + solves this problem with two messages, + XEMBED_REGISTER_ACCELERATOR and XEMBED_UNREGISTER_ACCELERATOR. + With XEMBED_REGISTER_ACCELERATOR, a client can reserve a + certain key/modifier combination as shortcut or + accelerator. The message is passed through to the topmost + embedder, where the key combination is stored. An + XEMBED_UNREGISTER_ACCELERATOR message releases the key again. + </para> + </sect2> + <sect2> + <title>Modality</title> + <para> + If an application window is shadowed by a modal dialog, no user + input is supposed to get through. The XEmbed design ensures this + for keyboard input, because the toplevel window knows about its + modal state and will not pass key events through. Embedded clients + thus inherit the modality from the topmost embedder. Mouse input, + however, is sent directly to the embedded clients by the X-Server, + unaffected by the modality of the application window. To give + clients the possibility to behave correctly when being shadowed by + a modal dialog, an embedder can choose to send an + XEMBED_MODALITY_ON message to its client when it becomes shadowed, + and an XEMBED_MODALITY_OFF message when it leaves modality + again. If the client contains embedders itself, those have to pass + both messages through to their clients. + </para> + </sect2> + <sect2> + <title>Drag and drop (XDND)</title> + <para> + XDND drag-and-drop does not work with reparented external + windows, since messages are exchanged with the toplevel window + only. This is done for performance reasons. While it is cheap to + get the window under the mouse pointer, it is very expensive to + get a window under another window. Unfortunately, this is required + quite often when dragging objects around, since the pointer + may overlap the drag icon. + </para> + <para> + Solving the drag-and-drop problem, however, is quite easy, + since the XDND protocol was carefully designed in a way that + makes it possible to support embedded windows. Basically, the + embedder has to operate as drag-and-drop proxy for the client. Any + XDND messages like XdndEnter, Xdnd,Leave, etc. simply have to be + passed through. A toolkit's XDND implementation has to take this + situation in consideration. + </para> + </sect2> + </sect1> + <sect1 id="lifecycle"> + <title>Embedding life cycle</title> + <para> + The protocol is started by the embedder. The window ID of + the client window is passed (by unspecified means) to the + embedding application, and the embedder calls + <function>XReparentWindow()</function> to reparent the client + window into the embedder window. + </para> + <para> + Implementations may choose to support an alternate method of + beginning the protocol where the window ID of the embedder + is passed to client application and the client creates a window + within the embedder, or reparents an existing window into + the embedder's window. Which method of starting XEmbed is + used a matter up to higher level agreement and outside the + scope of this specification. + </para> + <para> + In either case the client window must have a property called + _XEMBED_INFO on it. This property has type _XEMBED_INFO + and format 32. The contents of the property are: + </para> + <table> + <title>_XEMBED_INFO</title> + <tgroup cols="3"> + <thead> + <row> + <entry>Field</entry><entry>Type</entry><entry>Comments</entry> + </row> + </thead> + <tbody> + <row> + <entry>version</entry><entry>CARD32</entry><entry>The protocol version</entry> + </row> + <row> + <entry>flags</entry><entry>CARD32</entry><entry>A bitfield of flags</entry> + </row> + </tbody> + </tgroup> + </table> + <para> + The <structfield>version</structfield> field indicates the + maximum version of the protocol that the client supports. + The embedder should retrieve this field and set the data2 field + of the XEMBED_EMBEDDED_NOTIFY to + Min (<structfield>version</structfield>, <replaceable>max version supported by embedder</replaceable>). + The version number corresponding to the current version of the + protocol is 0. + <remark>[Should the version be defined as (Major << 16 | Minor) ?]</remark> + </para> + <para> + The currently defined bit in the + <structfield>flags</structfield> field is: + </para> + <programlisting><!-- +-->/* Flags for _XEMBED_INFO */ +#define XEMBED_MAPPED (1 << 0)<!-- + --></programlisting> + <variablelist> + <varlistentry> + <term>XEMBED_MAPPED</term> + <listitem> + <para> + If set the client should be mapped. The embedder must + track the flags field by selecting for PropertyNotify + events on the client and map and unmap the client + appropriately. (The embedder can leave the client unmapped + when this bit is set, but should immediately unmap the + client upon detecting that the bit has been unset.) + </para> + <remark> + Rationale: the reason for using this bit rather than + MapRequest events is so that the client can reliably + control it's map state before the inception of the + protocol without worry that the client window will + become visible as a child of the root window. + </remark> + </listitem> + </varlistentry> + </variablelist> + <para> + To support future expansion, all fields not currently defined + must be set to zero. To add proprietary extensions to the + XEMBED protocol, an application must use a separate property, rather + than using unused bits in the struct field or extending the + _XEMBED_INFO property. + </para> + <para> + At the start of the protocol, the embedder first sends an + XEMBED_EMBEDDED_NOTIFY message, then sends + XEMBED_FOCUS_IN, XEMBED_WINDOW_ACTIVATE, and XEMBED_MODALITY_ON + messages as necessary to synchronize the state of the + client with that of the embedder. Before any of these messages + received, the state of the client is: + <simplelist> + <member>Not focused</member> + <member>Not active</member> + <member>Modality off</member> + </simplelist> + </para> + <para> + If the embedder is geometry managed and can change its size, it + should obey the client's WMNormalHints settings. Note that + most toolkits will not have equivalents for all the hints in + the WMNormalHints settings, clients must not assume that the + requested hints will be obeyed exactly. The + <structfield>width_inc</structfield>, + <structfield>height_inc</structfield>, + <structfield>min_aspect</structfield>, and + <structfield>max_aspect</structfield> fields are examples of + fields from WMNormalHints that are unlikely to be supported + by embedders. + </para> + <para> + The protocol ends in one of three ways: + </para> + <orderedlist> + <listitem> + <para> + The embedder can unmap the client and reparent the client + window to the root window. If the client receives an + ReparentNotify event, it should check the + <structfield>parent</structfield> field of the + <structname>XReparentEvent</structname> structure. If this + is the root window of the window's screen, then the protocol + is finished and there is no further interaction. If it + is a window other than the root window, then the protocol + continues with the new parent acting as the embedder window. + </para> + </listitem> + <listitem> + <para> + The client can reparent its window out of the embedder + window. If the embedder receives a ReparentNotify signal + with the <structfield>window</structfield> field being the + current client and the <structfield>parent</structfield> + field being a different window, this indicates the end + of the protocol. + </para> + <remark> + [ GTK+ doesn't currently handle this; but it seems useful + to allow the protocol to be ended in a non-destructive + fashion from either end. ] + </remark> + </listitem> + <listitem> + <para> + The client can destroy its window. + </para> + </listitem> + </orderedlist> + </sect1> + <sect1 id="messages"> + <title>Message Specifications</title> + <para> + An XEmbed message is an X11 client message with message type + "_XEMBED". The format is 32, the first three data longs carry the + toolkit's X time (l[0]), the message's major opcode (l[1]) and the + message's detail code (l[2]). If no detail is required, the value + passed has to be 0. The remaining two data longs (l[3] and l[4]) + are reserved for data1 and data2. Unused bytes of the client + message are set to 0. The event is sent to the target window with + no event mask and propagation turned off. + </para> + <para> + The valid XEmbed messages are: + </para> + <programlisting><!-- +-->/* XEMBED messages */ +#define XEMBED_EMBEDDED_NOTIFY 0 +#define XEMBED_WINDOW_ACTIVATE 1 +#define XEMBED_WINDOW_DEACTIVATE 2 +#define XEMBED_REQUEST_FOCUS 3 +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 +#define XEMBED_FOCUS_NEXT 6 +#define XEMBED_FOCUS_PREV 7 +/* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */ +#define XEMBED_MODALITY_ON 10 +#define XEMBED_MODALITY_OFF 11 +#define XEMBED_REGISTER_ACCELERATOR 12 +#define XEMBED_UNREGISTER_ACCELERATOR 13 +#define XEMBED_ACTIVATE_ACCELERATOR 14<!-- + --></programlisting> + <para> + A detail code is required for XEMBED_FOCUS_IN. The following values + are valid: + </para> + <programlisting><!-- +-->/* Details for XEMBED_FOCUS_IN: */ +#define XEMBED_FOCUS_CURRENT 0 +#define XEMBED_FOCUS_FIRST 1 +#define XEMBED_FOCUS_LAST 2<!-- + --></programlisting> + <sect2> + <title>XEMBED_EMBEDDED_NOTIFY</title> + <para> + Sent from the embedder to the client on embedding, after + reparenting and mapping the client's X window. A client that + receives this messages knows that its window was embedded by an + XEmbed site and not simply reparented by a window manager. To support toolkits + that do not keep track of reparenting events, the message carries + the embedder's window handle as data1: + </para> + <table> + <title>XEMBED_EMBEDDED_NOTIFY</title> + <tgroup cols="2"> + <tbody> + <row> + <entry>data1</entry><entry>The embedder's window handle.</entry> + </row> + <row> + <entry>data2</entry><entry>The protocol version in use + (see the description of _XEMBED_INFO).</entry> + </row> + </tbody> + </tgroup> + </table> + </sect2> + <sect2> + <title>XEMBED_WINDOW_ACTIVATE / XEMBED_WINDOW_DEACTIVATE</title> + <para> + Sent from the embedder to the client when the window becomes + active or inactive, i.e. when the window gets or looses the + keyboard input focus. If the client contains embedders itself, + those have to pass the message through to their clients. + </para> + <para> + Note that no XEMBED_FOCUS_IN or XEMBED_FOCUS_OUT messages + should be sent when the toplevel window gains or loses + focus. The XEMBED_FOCUS_IN and XEMBED_FOCUS_OUT messages + refer only to focus <firstterm>within</firstterm> the + toplevel window and are independent of toplevel activation + state. This independence is necessary so that input focus + within a toplevel can be moved programmatically when the + toplevel doesn't have input focus. + </para> + <remark> + [ GTK+ is currently in violation of the preceding note, + and sends FOCUS_IN and FOCUS_OUT only when the toplevel + is active. See + <ulink + url="http://bugzilla.gnome.org/show_bug.cgi?id=67943">GNOME bug #67943</ulink> ] + </remark> + <para> + Widgets within the client should typically be displayed with + the focus only when the client both has focus and is active. + </para> + </sect2> + <sect2> + <title>XEMBED_REQUEST_FOCUS</title> + <para> + Sent from the client to the embedder when the client wants + focus. The most common occasion is when the user clicks into one + of the client's child widgets, for example a line editor, in order + to type something in. + </para> + <para> + The message is passed along to the topmost embedder that + eventually responds with a XEMBED_FOCUS_IN message. The focus in + message is passed all the way back until it reaches the original + focus requester. In the end, not only the original client has + focus, but also all its ancestor embedders. + </para> + </sect2> + <sect2> + <title>XEMBED_FOCUS_IN</title> + <para> + Sent from the embedder to the client when it gets focus. The + detail code determines, where the client shall move its own + logical focus to. Three possibilities exist: + </para> + <variablelist> + <varlistentry> + <term>XEMBED_FOCUS_CURRENT</term> + <listitem> + <para> + Normal activation, does not move the clients logical + focus. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>XEMBED_FOCUS_FIRST</term> + <listitem> + <para> + Used when the user tabs onto a client. It indicates that + the client should put its logical focus onto the widget + that comes first in its own tab focus chain. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>XEMBED_FOCUS_LIST</term> + <listitem> + <para> + Used when the user tabs onto a client. It indicates that + the client should put its logical focus onto the widget + that comes first in its own tab focus chain. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + <sect2> + <title>XEMBED_FOCUS_OUT</title> + <para> + Sent from the embedder to the client when it looses focus. + </para> + </sect2> + <sect2> + <title>XEMBED_FOCUS_NEXT</title> + <para> + Sent from the client to the embedder when it reaches the end of + its logical tab chain after the user tabbed forward. If the + embedder has siblings that accept tab focus, it will do a virtual + tab forward. As a result, it will loose focus itself and + consequently send an XEMBED_FOCUS_OUT message to the client + </para> + </sect2> + <sect2> + <title>XEMBED_FOCUS_PREV</title> + <para> + Sent from the client to the embedder when it reaches the + beginning of its logical tab chain after the user tabbed + backward. If the embedder has siblings that accept tab focus, it + will do a virtual tab backward. As a result, it will loose focus + itself and consequently send an XEMBED_FOCUS_OUT message to the + client + </para> + </sect2> + <sect2> + <title>XEMBED_REGISTER_ACCELERATOR / XEMBED_UNREGISTER_ACCELERATOR</title> + <para> + A client that needs to reserve a certain key/modifier + combination as shortcut or accelerators, sends a XEMBED_REGISTER_ACCELERATOR + message to its embedder. As long as the embedder itself is a child + of a client, the accelerator will be propagated up to the toplevel. + </para> + <table> + <title>XEMBED_REGISTER_ACCELERATOR</title> + <tgroup cols="2"> + <tbody> + <row> + <entry>detail</entry><entry>accelerator_id</entry> + </row> + <row> + <entry>data1</entry><entry>X key symbol</entry> + </row> + <row> + <entry>data2</entry><entry>bit field of modifier values</entry> + </row> + </tbody> + </tgroup> + </table> + <para> + The accelerator_id is used to identify the accelerator when + activating the accelerator. The reason for using an + accelerator ID instead of identifying accelerators simply by + key symbol and modifiers is to allow the correct handling of + overloaded accelerators with embedded widgets. (An accelerator + is overloaded if there multiple accelerators on the same key, + usually because of accidental collisions.) When an overloaded + accelerator is pressed repeatedly, the toplevel activates + accelerators on that key in round-robin fashion. If this + round-robin behavior is not supported by the embedding + toolkit, picking an arbitrary accelerator for the key and + activating it is acceptable. Well designed applications should + avoid collisions in any case. + </para> + <note> + <para> + Ordering the round-robin of conflicting accelerators + in a predictable (geometric or in focus chain) order + is desirable. This can be achieved if the toplevel sorts + the conflicting accelerators as if they applied to the + client instead of widgets within the client and then + each client does the same sort on the subset of conflicting + accelerators within it. To get this to work properly + if there are conflicting accelerators within a client, say widget + A and B both have the same mnemonic, then instead of + registering one accelerator for widget A and one for + widget B, the client should register two accelerators that + corresponds to both A and B, and then when + XEMBED_ACTIVATE_ACCELERATOR is received for either + accelerator, implement round robin between A and B + with the correct sorting. + </para> + </note> + <para> + The modified bit field is a bitwise OR of values indicating + various modifiers; these indicate logical accelerator + keys rather than corresponding directly to the bits in + the XKeyEvent state field. + </para> + <programlisting><!-- +-->/* Modifiers field for XEMBED_REGISTER_ACCELERATOR */ +#define XEMBED_MODIFIER_SHIFT (1 << 0) +#define XEMBED_MODIFIER_CONTROL (1 << 1) +#define XEMBED_MODIFIER_ALT (1 << 2) +#define XEMBED_MODIFIER_SUPER (1 << 3) +#define XEMBED_MODIFIER_HYPER (1 << 4)<!-- + --></programlisting> + <para> + (Meta is intentionally left out here because if you try to separate + Alt and Meta, a large fraction of users will experience problems + with their keyboard setups... there is no reliably standard + of which one is the primary modifier key and on the Alt key.) + </para> + <para> + On activation, the topmost embedder will send + XEMBED_ACTIVATE_ACCELERATOR to its client; if the + accelerator was registered by an embedder inside that + client, the embedder will send XEMBED_ACTIVATE_ACCELERATOR + to its client and so forth. + </para> + <para> + Note that the assignment of ID's is private for each pair + of client and embedder and when accelerators are being + propagated through multiple client/embedder pairs, a + different accelerator ID may be used for each pair. + </para> + <para> + The XEMBED_UNREGISTER_ACCELERATOR message releases the key + combination again. + </para> + <table> + <title>XEMBED_UNREGISTER_ACCELERATOR</title> + <tgroup cols="2"> + <tbody> + <row> + <entry>detail</entry><entry>integer ID passed + to XEMBED_REGISTER_ACCELERATOR</entry> + </row> + </tbody> + </tgroup> + </table> + <para> + Hint to implementors: It is the responsibility of the + embedder to keep track of all forwarded accelerators + and to remove them when the client window dies. + </para> + </sect2> + <sect2> + <title>XEMBED_ACTIVATE_ACCELERATOR</title> + <para> + The XEMBED_ACTIVATE_ACCELERATOR message is sent when a + accelerator previously registered with + XEMBED_REGISTER_ACCELERATOR is activated on the toplevel + containing the embedder. + </para> + <table> + <title>XEMBED_ACTIVATE_ACCELERATOR</title> + <tgroup cols="2"> + <tbody> + <row> + <entry>detail</entry><entry>integer ID passed + when registering the accelerator</entry> + </row> + <row> + <entry>data1</entry><entry>flags.</entry> + </row> + </tbody> + </tgroup> + </table> + <para> + The following bit is defined for the flags field; all + other bits must be zero. + </para> + <programlisting><!-- +-->/* Flags for XEMBED_ACTIVATE_ACCELERATOR */ +#define XEMBED_ACCELERATOR_OVERLOADED (1 << 0)<!-- + --> + </programlisting> + <variablelist> + <varlistentry> + <term>XEMBED_ACCELERATOR_OVERLOADED</term> + <listitem> + <para> + This flag indicates that multiple accelerators exist for + the key combination within the toplevel. The toolkit + may modify the behavior of the accelerator based on + this value. For instance, if the accelerator is a + mnemonic for a button, it might activate the the button + immediately if the accelerator is not overloaded, but + when overloaded, it would only focus the button. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + <sect2> + <title>XEMBED_MODALITY_ON / XEMBED_MODALITY_OFF</title> + <para> + Sent from the embedder to the client when the window becomes + shadowed by a modal dialog, or when it is released again. If the + client contains embedders itself, those have to pass the message + through to their clients. An embedded control should ignore + mouse input while modality is active. Note that that keyboard + input is blocked anyway by XEmbed, since the topmost embedder will + not pass keyboard events through in modal state. + </para> + </sect2> + </sect1> + + <sect1 id="techniques"> + <title>Techniques</title> + + <sect2> + <title>Handling errors</title> + <para> + Implementors of the XEmbed protocol should handle the other + party disappearing at any point. For this reason X errors + must be trapped when performing any operation with a window + not created by the application. This is done by using + <function>XSetErrorHandler()</function>. + A sample implementation of trapping errors in C looks like: + </para> + <programlisting><!-- +-->#include <X11/Xlib.h> + +static int trapped_error_code = 0; +static int (*old_error_handler) (Display *, XErrorEvent *); + +static int +error_handler(Display *display, + XErrorEvent *error) +{ + trapped_error_code = error->error_code; + return 0; +} + +void +trap_errors(void) +{ + trapped_error_code = 0; + old_error_handler = XSetErrorHandler(error_handler); +} + +int +untrap_errors(void) +{ + XSetErrorHandler(old_error_handler); + return trapped_error_code; +}<!-- + --></programlisting> + </sect2> + <sect2> + <title>Forwarding X Events</title> + <para> + An XEmbed embedder has to forward key-press and key-release + events to its respective client. + </para> + <para> + Key events are forwarded by changing the event's window field + to the window handle of the client and sending the modified + message via <function>XSendEvent()</function> to the embedder, + with no event mask and propagation turned off. + </para> + <para> + Note: XEmbed requires toolkits to handle key-events that come + from a SendEvent request. That means, if somebody can access + your X-Server, it's possible to fake keyboard input. Given + that most toolkits accept sent key events today anyway and the + X Server is typically protected through magic cookie + authorization, this is not considered to be an + issue. Applications with higher security requirements may + choose not to use embedded components, though, and to filter + out any events coming from <function>XSendEvent()</function>. + </para> + <para> + Given that Window client is the client's window handle, + here is a piece of code of an imaginary event-loop in C that does + the forwarding. + </para> + <programlisting><!-- +-->#include <X11/Xlib.h> + +void handle_event( + Display* dpy, /* display */ + XEvent* ev /* event */ +){ + if ( ev->type == KeyPress || ev->type == KeyRelease ) { + ev->xkey.window = client; + trap_errors(); + XSendEvent( dpy, client, False, NoEventMask, ev ); + XSync( dpy, False ); + if (untrap_errors()) { + /* Handle failure */ + } + + return; + } + ... /* normal event handling */ +}<!-- + --></programlisting> + </sect2> + <sect2> + <title>Sending XEmbed messages</title> + <para> + Given that Time x_time contains the timestamp from the event + currently being processed. (CurrentTime is generally the best + choice if no event is being processed), here is a valid + implementation in C of sending an XEMBED message: + </para> + <programlisting><!-- +-->#include <X11/Xlib.h> + +void send_xembed_message( + Display* dpy, /* display */ + Window w, /* receiver */ + long message, /* message opcode */ + long detail /* message detail */ + long data1 /* message data 1 */ + long data2 /* message data 2 */ +){ + XEvent ev; + memset(&ev, 0, sizeof(ev)); + ev.xclient.type = ClientMessage; + ev.xclient.window = w; + ev.xclient.message_type = XInternAtom( dpy, "_XEMBED", False ); + ev.xclient.format = 32; + ev.xclient.data.l[0] = x_time; + ev.xclient.data.l[1] = message; + ev.xclient.data.l[2] = detail; + ev.xclient.data.l[3] = data1; + ev.xclient.data.l[4] = data2; + trap_errors(); + XSendEvent(dpy, w, False, NoEventMask, &ev); + XSync(dpy, False); + if (untrap_errors()) { + /* Handle failure */ + } +}<!-- + --></programlisting> + </sect2> + </sect1> + <sect1 id="issues"> + <title>Issues</title> + <sect2> + <title>Implementation of modality</title> + <para> + The protocol could be simplified by removing the + XEMBED_MODALITY_ON and XEMBED_MODALITY_OFF messages in favor + of requiring the embedder to map an input-only window over + it's child when it beings shadowed by a modal grab. + </para> + <para> + One possible reason for the current protocol is that a toolkit + might want to have elements such as scrollbars that remain + active even when grab shadowed. (I know of no toolkit that + actually implements this.) + </para> + </sect2> + <sect2> + <title>Clarify function of timestamps</title> + <para> + The function of the timestamp arguments needs to be clarified, + as well as the requirements for what should be passed + in the field. The original draft of the specification + contained the text about the determining the timestamp. + </para> + <blockquote> + <para> + The x time is to be updated whenever the toolkit receives an + event from the server that carries a timestamp. XEmbed client + messages qualify for that. + </para> + <para> + Hint to implementors: Check that the xembed time stamp + is actually later than your current x time. While this cannot + happen with ordinary XEvents, delayed client messages may have + this effect. Be prepared that evil implementations may even + pass CurrentTime sometimes. + </para> + </blockquote> + <para> + But I [OWT] wouldn't agree with this advice. The point + of a timestamp is to make sure that when events are processed + out of order, the event generated last by the user wins + for shared resources such as input focus, selections, and + grabs. An example of where this can matter is if you have + </para> + <programlisting><!-- +--> Toplevel Window + Embedder + Client + Text Entry 1 + Embedder + Client + Text Entry 2<!-- + --></programlisting> + <para> + If the entries are set to select the text on focus in, and the + user hits TAB in quick succession, then the timestamps on the + FOCUS_IN events are what makes sure that Entry 2 actually ends + up owning the PRIMARY selection, instead of it being a race + between the two clients. But in situations like this having + the correct timestamp only matters if a user action triggers + the behavior. + </para> + <para> + Hence the advice that the timestamp should be the time from + the event currently being processed. + </para> + <para> + If no explicit user action is involved, then the + best thing to do is to use CurrentTime; using the timestamp + from the last X event received can cause problems if the + ultimate trigger of the behavior is a timeout or network + and the last X event happened some time in the distant past. + </para> + </sect2> + <sect2> + <title>Complexity of accelerator handling</title> + <para> + The current specification for accelerator handling is a little + complex. Most of the complexity (the accelerator IDs) comes + from the need to handle conflicting accelerators. + GTK+ currently implements a simpler scheme where grabs are + identified only by key symbol and modifier and conflicting + mnemonic resolution doesn't work across embedder/client + interfaces. + </para> + </sect2> + <sect2> + <title>Infinite loops in focusing</title> + <para> + There is the potential for infinite loops of focusing - + Consider the case: + </para> + <programlisting><!-- +--> Toplevel Window + Embedder + Client<!-- + --></programlisting> + <para> + Where there are no focusable sites in the client or in the + toplevel window. Then if <keysym>Tab</keysym> is pressed, the embedder + will send: FOCUS_IN/FOCUS_FIRST to the client, the client will + send FOCUS_NEXT to the embedder, the toplevel window will + wrap the focus around and send FOCUS_IN/FOCUS_FIRST to the + client... + </para> + <para> + The minimum mechanism that seems necessary to prevent this + loop is a serial number in the FOCUS_IN/FOCUS_FIRST message + that is repeated in a resulting FOCUS_NEXT message. + </para> + <para> + A possibly better way of handling this could be to make FOCUS_IN have + an explicit response; that, is, add a XEMBED_FOCUS_IN_RESPONSE + that the client must send to the embedder after receipt + of a FOCUS_IN message. + </para> + + <table> + <title>XEMBED_FOCUS_IN_RESPONSE</title> + <tgroup cols="2"> + <tbody> + <row> + <entry>detail</entry><entry>1 if the client accepted the focus, 0 otherwise</entry> + </row> + <row> + <entry>data1</entry><entry>serial number from XEMBED_FOCUS_IN</entry> + </row> + </tbody> + </tgroup> + </table> + <para> + The main problem with requiring a response here is that caller + needs to wait for the return event, and to handle cases like + parent (client 1) => child (client 2) => grandchild (client 1), + it probably needs to process all sorts of incoming events at + this point. If the user hits <keysym>Tab</keysym><keysym>Tab</keysym> + in quick succession things could get very complicated. + </para> + </sect2> + <sect2> + <title>Robustness</title> + <para> + The protocol, as currently constituted, is not robust against + the embedder crashing. This will result in the embedder + window being destroyed by the X server, and, as a consequence + client's window being unexpectedly destroyed, which will likely cause the + client to die with a BadWindow error. + </para> + <para> + To fix this requires an X protocol extension which extends + the functionality of <function>XChangeSaveSet()</function> in + two areas: + </para> + <itemizedlist> + <listitem> + <para> + Allow it to be specified that the saved window should be + reparented to the root window rather than to the nearest + parent. (The nearest parent typically being the window + manager's frame window, reparenting to the nearest + parent only saves the client until the window manager + cleans up and destroys the frame window.) + </para> + </listitem> + <listitem> + <para> + Allow it to be specified that the saved window should be + unmapped rather than then mapped. (Without this capability + the client will mapped as a child of the root window, + which will be confusing to the user.) + </para> + </listitem> + </itemizedlist> + </sect2> + <sect2> + <title>Sensitivity</title> + <para> + Toolkits such as Qt and GTK+ have a concept of disabled + widgets. This notion is typically hierarchical, so if + the embedder or a ancestry of the embedder becomes + insensitive, widgets inside the client should be displayed as, + and act insensitive as well. + </para> + </sect2> + <sect2> + <title>Directional focusing</title> + <para> + Some toolkits, such as GTK+, support, along with the standard + concept of a focus chain, the idea of <firstterm>directional + focusing</firstterm>; it's possible in some cases to navigate + focus using the arrow keys. To do this perfectly, you need + to have information about the coordinates of the original + focus window, which is hard to do in an embedding context, + but a good approximation is to, when focusing into a + container, provide the side of the container where focus + is coming from and to focus the "middle widget" on this side. + </para> + <para> + This could be supported by adding an extra data field to + to the XEMBED_FOCUS_FIRST/XEMBED_FOCUS_LAST subtypes + of XEMBED_FOCUS_IN and to XEMBED_FOCUS_NEXT and + XEMBED_FOCUS_PREV, which would contain: + </para> + <programlisting><!-- +-->/* Directions for focusing */ +#define XEMBED_DIRECTION_DEFAULT 0 +#define XEMBED_DIRECTION_UP_DOWN 1 +#define XEMBED_DIRECTION_LEFT_RIGHT 2<!-- + --></programlisting> + <para> + Applications supporting only normal tab focusing would always + pass XEMBED_DIRECTION_DEFAULT and treat all received + directions as XEMBED_DIRECTION_DEFAULT. + </para> + <para> + The argument against supporting this is that it's a rather + confusing feature to start with (many widgets eat arrow keys + for other purposes), and becomes more confusing if you have + a application containing widgets from different toolkits, + some of which support it, some of which don't. + </para> + </sect2> + <sect2> + <title>Modal dialogs</title> + <para> + The specification doesn't have any provisions for handling the + case where an embedded client wants to put up a dialog. Such a + dialog should be transient-for the real toplevel window, and, + if modal, should block the entire toplevel window. To fully + implement this, you would need some concept of an application + that spanned multiple toplevel windows in multiple clients. + </para> + </sect2> + <sect2> + <title>Propagation of key presses</title> + <para> + It's frequently useful to have key bindings that trigger on + a widget if the focus is on a child of that widget. For + instance, <keysym>Control</keysym><keysym>PageUp</keysym> + and <keysym>Control</keysym><keysym>PageUp</keysym> switch + pages in a notebook widget when the focus is on a child + of the notebook. The XEmbed spec currently has no handling + of this situation. + </para> + <para> + The simplest solution would be to specify that if the client + widget doesn't handle a key press sent to it, it then sends + the event back to the embedder. Some care would be required + in the embedder handle infinite loops, but it shouldn't + be that bad. + </para> + </sect2> + <sect2> + <title>Handling of toplevel modes</title> + <para> + GTK+-2.0 contains a feature for key navigation of tooltips + where Control-F1 toggles a "tooltips keyboard mode" where + the tooltip for the currently focused window is displayed. + There is no way of propagating this across XEMBED. + This feature could clearly be implemented the same + way as XEMBED_WINDOW_ACTIVATE, but adding a pair of + messages for every feature of this type seems excessive. + </para> + <para> + A possible alternate idea would be to add a _XEMBED_STATE + property that the embedder sets on the client window which + is a list of atoms. This could actually be used to + replace XEMBED_WINDOW_ACTIVATE, and XEMBED_MODALITY_ON, + simplifying the protocol. + </para> + <para> + There are some race conditions in maintaining this property + if the client is allowed to reparent itself out of the + embedder that would have to be considered. + </para> + </sect2> + </sect1> + <appendix id="changes"> + <title>Change history</title> + <formalpara> + <title>"Version 1.0 DRAFT 1", 22 April 2000, Matthias Ettrich</title> + <para> + </para> + </formalpara> + <formalpara> + <title>"Version 1.0 DRAFT 2", 15 August 2000, Matthias Ettrich</title> + <para> + </para> + </formalpara> + <formalpara> + <title>Version 0.5, 19 April 2002, Owen Taylor</title> + <para> + <itemizedlist> + <listitem> + <para> + Add the life-cycle chapter, including _XEMBED_INFO + property, and the XEMBED_MAPPED flags. + </para> + </listitem> + <listitem> + <para> + Define the data2 for XEMBED_EMBEDDED_NOTIFY to be the + protocol version in use. + </para> + </listitem> + <listitem> + <para> + Replaced XEMBED_GRAB_KEY scheme for handling accelerators + with XEMBED_REGISTER_ACCELERATOR. + </para> + </listitem> + <listitem> + <para> + Removed text "This also means that the client has to + prepare for becoming visible anytime without filing a map + request itself" from the description of + XEMBED_EMBEDDED_NOTIFY". + </para> + </listitem> + <listitem> + <para> + Added text about the independence of FOCUS_IN/OUT and + ACTIVATE/DEACTIVATE to the description of + XEMBED_WINDOW_ACTIVATE / XEMBED_WINDOW_DEACTIVATE. + </para> + </listitem> + <listitem> + <para> + Added note about fields in WMNormalHints not necessarily + being obeyed by embedders. + </para> + </listitem> + <listitem> + <para> + Removed mention of XEMBED_PROCESS_NEXT_EVENT, which is + no longer part of the protocol. + </para> + </listitem> + <listitem> + <para> + Added definitions of "Active" and "Focused" to the + definitions section. + </para> + </listitem> + <listitem> + <para> + Added issues and change history sections. + </para> + </listitem> + <listitem> + <para> + Lots of textual editing for clarity, style consistency. + </para> + </listitem> + <listitem> + <para> + Converted to docbook format. + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + </appendix> +</article> diff --git a/xembed/tests/.cvsignore b/xembed/tests/.cvsignore new file mode 100644 index 0000000..2bffb50 --- /dev/null +++ b/xembed/tests/.cvsignore @@ -0,0 +1,9 @@ +.deps +.libs +Makefile +Makefile.in +gtk-client +gtk-embedder +qt-client +qt-embedder +moc_* diff --git a/xembed/tests/Makefile.am b/xembed/tests/Makefile.am new file mode 100644 index 0000000..ecce952 --- /dev/null +++ b/xembed/tests/Makefile.am @@ -0,0 +1,39 @@ +noinst_PROGRAMS = qt-client qt-embedder gtk-client gtk-embedder + +INCLUDES = @all_includes@ @GTK_CFLAGS@ -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED + +# +# Qt Examples +# + +qt_libs = $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) $(LIB_KFILE) $(LIBSOCKET) + +BUILT_SOURCES=moc_qt-client.cpp moc_qt-embedder.cpp moc_qt-common.cpp + +moc_qt-client.cpp: qt-client.h + $(MOC) $< -o $@ + +moc_qt-embedder.cpp: qt-embedder.h + $(MOC) $< -o $@ + +moc_qt-common.cpp: qt-common.h + $(MOC) $< -o $@ + +qt_client_SOURCES = qt-client.cpp qt-client.h qt-common.cpp qt-common.h +qt_client_LDADD = $(qt_libs) moc_qt-client.$(OBJEXT) moc_qt-common.$(OBJEXT) + +qt_embedder_SOURCES = qt-embedder.cpp qt-embedder.h qt-common.cpp qt-common.h +qt_embedder_LDADD = $(qt_libs) moc_qt-embedder.$(OBJEXT) moc_qt-common.$(OBJEXT) + +CLEANFILES = moc_qt-client.cpp moc_qt-embedder.cpp moc_qt-common.cpp + +# +# GTK+ examples +# + +gtk_client_SOURCES = gtk-client.c gtk-common.c gtk-common.h +gtk_client_LDADD = $(GTK_LIBS) + +gtk_embedder_SOURCES = gtk-embedder.c gtk-common.c gtk-common.h +gtk_embedder_LDADD = $(GTK_LIBS) + diff --git a/xembed/tests/gtk-client.c b/xembed/tests/gtk-client.c new file mode 100644 index 0000000..e881d48 --- /dev/null +++ b/xembed/tests/gtk-client.c @@ -0,0 +1,202 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <gtk/gtk.h> + +#include "gtk-common.h" + +static void +remove_buttons (GtkWidget *widget, GtkWidget *other_button) +{ + gtk_widget_destroy (other_button); + gtk_widget_destroy (widget); +} + +static gboolean +blink_cb (gpointer data) +{ + GtkWidget *widget = data; + + gtk_widget_show (widget); + g_object_set_data (G_OBJECT (widget), "blink", GPOINTER_TO_UINT (0)); + + return FALSE; +} + +static void +blink (GtkWidget *widget, + GtkWidget *window) +{ + guint blink_timeout = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (window), "blink")); + + if (!blink_timeout) + { + blink_timeout = g_timeout_add (1000, blink_cb, window); + gtk_widget_hide (window); + + g_object_set_data (G_OBJECT (window), "blink", GUINT_TO_POINTER (blink_timeout)); + } +} + +static void +remote_destroy (GtkWidget *window) +{ + guint blink_timeout = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (window), "blink")); + if (blink_timeout) + g_source_remove (blink_timeout); + + gtk_main_quit (); +} + +static void +add_buttons (GtkWidget *widget, GtkWidget *box) +{ + GtkWidget *add_button; + GtkWidget *remove_button; + + add_button = gtk_button_new_with_mnemonic ("_Add"); + gtk_box_pack_start (GTK_BOX (box), add_button, TRUE, TRUE, 0); + gtk_widget_show (add_button); + + g_signal_connect (add_button, "clicked", + G_CALLBACK (add_buttons), box); + + remove_button = gtk_button_new_with_mnemonic ("_Remove"); + gtk_box_pack_start (GTK_BOX (box), remove_button, TRUE, TRUE, 0); + gtk_widget_show (remove_button); + + g_signal_connect (remove_button, "clicked", + G_CALLBACK (remove_buttons), add_button); +} + +void +add_child (GtkWidget *vbox, + gboolean qt) +{ + Socket *socket = socket_new (); + + gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0); + gtk_widget_show (socket->box); + + socket_start_child (socket, FALSE, qt); +} + +void +add_gtk_child (GtkWidget *widget, + GtkWidget *vbox) +{ + add_child (vbox, FALSE); +} + +void +add_qt_child (GtkWidget *widget, + GtkWidget *vbox) +{ + add_child (vbox, TRUE); +} + +guint32 +create_child_plug (guint32 xid) +{ + GtkWidget *window; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *entry; + GtkWidget *button; + GtkWidget *label; + GtkWidget *frame; + + window = gtk_plug_new (xid); + + frame = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (window), frame); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (frame), vbox); + + gtk_container_set_border_width (GTK_CONTAINER (vbox), 3); + + g_signal_connect (window, "destroy", + G_CALLBACK (remote_destroy), NULL); + gtk_container_set_border_width (GTK_CONTAINER (window), 0); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); + + label = gtk_label_new ("GTK+"); + gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); + + entry = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); + + button = gtk_button_new_with_mnemonic ("_Close"); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); + + g_signal_connect_swapped (button, "clicked", + G_CALLBACK (gtk_widget_destroy), window); + + button = gtk_button_new_with_mnemonic ("_Blink"); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); + g_signal_connect (button, "clicked", + G_CALLBACK (blink), window); + + button = gtk_button_new_with_mnemonic ("Add _GTK+"); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); + g_signal_connect (button, "clicked", + G_CALLBACK (add_gtk_child), vbox); + + button = gtk_button_new_with_mnemonic ("Add _Qt"); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); + g_signal_connect (button, "clicked", + G_CALLBACK (add_qt_child), vbox); + + add_buttons (NULL, hbox); + + gtk_widget_show_all (window); + + if (GTK_WIDGET_REALIZED (window)) + return gtk_plug_get_id (GTK_PLUG (window)); + else + return 0; +} + +int +main (int argc, char *argv[]) +{ + guint32 xid; + guint32 plug_xid; + + gtk_init (&argc, &argv); + + if (argc != 1 && argc != 2) + { + fprintf (stderr, "Usage: testsocket_child [WINDOW_ID]\n"); + exit (1); + } + + if (argc == 2) + { + xid = strtol (argv[1], NULL, 0); + if (xid == 0) + { + fprintf (stderr, "Invalid window id '%s'\n", argv[1]); + exit (1); + } + + create_child_plug (xid); + } + else + { + plug_xid = create_child_plug (0); + printf ("%d\n", plug_xid); + fflush (stdout); + } + + gtk_main (); + + wait_for_children (); + + return 0; +} + + diff --git a/xembed/tests/gtk-common.c b/xembed/tests/gtk-common.c new file mode 100644 index 0000000..abb2294 --- /dev/null +++ b/xembed/tests/gtk-common.c @@ -0,0 +1,182 @@ +#include <stdlib.h> +#include <stdio.h> + +#include <gtk/gtk.h> + +#include "gtk-common.h" + +static int n_children = 0; + +struct _Child +{ + Socket *socket; +}; + +static void +plug_added (GtkWidget *widget, + Socket *socket) +{ + g_print ("Plug added to socket\n"); + + gtk_widget_show (socket->socket); + gtk_widget_hide (socket->frame); +} + +static gboolean +plug_removed (GtkWidget *widget, + Socket *socket) +{ + g_print ("Plug removed from socket\n"); + + gtk_widget_hide (socket->socket); + gtk_widget_show (socket->frame); + + return TRUE; +} + +static void +socket_destroy (GtkWidget *widget, + Socket *socket) +{ + if (socket->child) + socket->child->socket = NULL; + g_free (socket); +} + +Socket * +socket_new (void) +{ + GtkWidget *label; + + Socket *socket = g_new (Socket, 1); + + socket->box = gtk_vbox_new (FALSE, 0); + + socket->socket = gtk_socket_new (); + + gtk_box_pack_start (GTK_BOX (socket->box), socket->socket, TRUE, TRUE, 0); + + socket->frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (socket->frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (socket->box), socket->frame, TRUE, TRUE, 0); + gtk_widget_show (socket->frame); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), "<span color=\"red\">Empty</span>"); + gtk_container_add (GTK_CONTAINER (socket->frame), label); + gtk_widget_show (label); + + g_signal_connect (socket->socket, "plug_added", + G_CALLBACK (plug_added), socket); + g_signal_connect (socket->socket, "plug_removed", + G_CALLBACK (plug_removed), socket); + g_signal_connect_after (socket->socket, "destroy", + G_CALLBACK (socket_destroy), socket); + + socket->child = NULL; + + return socket; +} + +static gboolean +child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data) +{ + GIOStatus status; + GError *error = NULL; + Child *child = data; + char *line; + gsize term; + int xid; + + status = g_io_channel_read_line (channel, &line, NULL, &term, &error); + switch (status) + { + case G_IO_STATUS_NORMAL: + if (child->socket && !GTK_SOCKET (child->socket->socket)->plug_window) + { + line[term] = '\0'; + xid = strtol (line, NULL, 0); + if (xid == 0) + { + fprintf (stderr, "Invalid window id '%s'\n", line); + } + else + { + gtk_socket_add_id (GTK_SOCKET (child->socket->socket), xid); + } + } + g_free (line); + return TRUE; + case G_IO_STATUS_AGAIN: + return TRUE; + case G_IO_STATUS_EOF: + n_children--; + if (child->socket) + child->socket->child = NULL; + g_free (child); + g_io_channel_shutdown (channel, FALSE, NULL); + return FALSE; + case G_IO_STATUS_ERROR: + fprintf (stderr, "Error reading fd from child: %s\n", error->message); + exit (1); + return FALSE; + default: + g_assert_not_reached (); + return FALSE; + } + +} + +void +socket_start_child (Socket *socket, + gboolean active, + gboolean qt) +{ + char *argv[3] = { NULL, NULL, NULL }; + char buffer[20]; + int out_fd; + GIOChannel *channel; + GError *error = NULL; + + socket->child = g_new (Child, 1); + socket->child->socket = socket; + + argv[0] = qt ? "./qt-client" : "./gtk-client"; + + if (active) + { + sprintf(buffer, "%#lx", (gulong) gtk_socket_get_id (GTK_SOCKET (socket->socket))); + argv[1] = buffer; + } + + if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, &out_fd, NULL, &error)) + { + fprintf (stderr, "Can't exec %s: %s\n", argv[0], error->message); + exit (1); + } + + n_children++; + channel = g_io_channel_unix_new (out_fd); + g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, &error); + if (error) + { + fprintf (stderr, "Error making channel non-blocking: %s\n", error->message); + exit (1); + } + + g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, socket->child); + g_io_channel_unref (channel); +} + +void +wait_for_children () +{ + if (n_children) + { + g_print ("Waiting for children to exit\n"); + + while (n_children) + g_main_context_iteration (NULL, TRUE); + } + +} diff --git a/xembed/tests/gtk-common.h b/xembed/tests/gtk-common.h new file mode 100644 index 0000000..ac77d46 --- /dev/null +++ b/xembed/tests/gtk-common.h @@ -0,0 +1,22 @@ +typedef struct _Child Child; +typedef struct _Socket Socket; + +struct _Socket +{ + GtkWidget *box; + GtkWidget *frame; + GtkWidget *socket; + + Child *child; +}; + + +void wait_for_children (void); + +Socket *socket_new (void); +void socket_start_child (Socket *socket, + gboolean active, + gboolean qt); + + + diff --git a/xembed/tests/gtk-embedder.c b/xembed/tests/gtk-embedder.c new file mode 100644 index 0000000..d3a7495 --- /dev/null +++ b/xembed/tests/gtk-embedder.c @@ -0,0 +1,163 @@ +#include <gtk/gtk.h> + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "gtk-common.h" + +GSList *sockets = NULL; + +GtkWidget *window; +GtkWidget *vbox; + +static void +quit_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *message_dialog = gtk_message_dialog_new (GTK_WINDOW (window), 0, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + "Really Quit?"); + gtk_dialog_add_buttons (GTK_DIALOG (message_dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_QUIT, GTK_RESPONSE_YES, + NULL); + + gtk_dialog_set_default_response (GTK_DIALOG (message_dialog), GTK_RESPONSE_YES); + + if (gtk_dialog_run (GTK_DIALOG (message_dialog)) == GTK_RESPONSE_YES) + gtk_widget_destroy (window); + + gtk_widget_destroy (message_dialog); +} + +static GtkItemFactoryEntry menu_items[] = +{ + { "/_File", NULL, 0, 0, "<Branch>" }, + { "/File/_Quit", "<control>Q", quit_cb, 0 }, +}; + +static void +socket_destroyed (GtkWidget *widget, + Socket *socket) +{ + sockets = g_slist_remove (sockets, socket); +} + +static void +remove_child (void) +{ + if (sockets) + { + Socket *socket = sockets->data; + gtk_widget_destroy (socket->box); + } +} + +void +add_child (gboolean active, + gboolean qt) +{ + Socket *socket = socket_new (); + + gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0); + gtk_widget_show (socket->box); + + sockets = g_slist_prepend (sockets, socket); + + socket_start_child (socket, active, qt); + + g_signal_connect (socket->socket, "destroy", + G_CALLBACK (socket_destroyed), socket); +} + +void +add_active_gtk_child (void) +{ + add_child (TRUE, FALSE); +} + +void +add_passive_gtk_child (void) +{ + add_child (FALSE, FALSE); +} + +void +add_active_qt_child (void) +{ + add_child (TRUE, TRUE); +} + +void +add_passive_qt_child (void) +{ + add_child (FALSE, TRUE); +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *button; + GtkWidget *hbox; + GtkAccelGroup *accel_group; + GtkItemFactory *item_factory; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + gtk_window_set_title (GTK_WINDOW (window), "Socket Test"); + gtk_container_set_border_width (GTK_CONTAINER (window), 0); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window), vbox); + + accel_group = gtk_accel_group_new (); + gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); + item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group); + + + gtk_item_factory_create_items (item_factory, + G_N_ELEMENTS (menu_items), menu_items, + NULL); + + gtk_box_pack_start (GTK_BOX (vbox), + gtk_item_factory_get_widget (item_factory, "<main>"), + FALSE, FALSE, 0); + + button = gtk_button_new_with_label ("Add Active Qt Child"); + gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", G_CALLBACK (add_active_qt_child), NULL); + + button = gtk_button_new_with_label ("Add Passive Qt Child"); + gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", GTK_SIGNAL_FUNC (add_passive_qt_child), NULL); + + button = gtk_button_new_with_label ("Add Active GTK+ Child"); + gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", G_CALLBACK (add_active_gtk_child), NULL); + + button = gtk_button_new_with_label ("Add Passive GTK+ Child"); + gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", G_CALLBACK (add_passive_gtk_child), NULL); + + button = gtk_button_new_with_label ("Remove Last Child"); + gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", G_CALLBACK (remove_child), NULL); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + gtk_widget_show_all (window); + + gtk_main (); + + wait_for_children (); + + return 0; +} diff --git a/xembed/tests/qt-client.cpp b/xembed/tests/qt-client.cpp new file mode 100644 index 0000000..ef40739 --- /dev/null +++ b/xembed/tests/qt-client.cpp @@ -0,0 +1,127 @@ +#include <kapp.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qtimer.h> + +#include <qxembed.h> + +#include "qt-client.h" +#include "qt-common.h" + +XEmbedQtButtonBox::XEmbedQtButtonBox (QWidget *parent, XEmbedQtClient *client) + : QWidget (parent) +{ + QHBoxLayout *layout = new QHBoxLayout (this); + layout->setAutoAdd (TRUE); + + QPushButton *button; + + button = new QPushButton( "&Add", this ); + QObject::connect (button, SIGNAL(clicked()), client, SLOT(addButtons())); + + button = new QPushButton( "&Remove", this ); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(close())); +} + + +XEmbedQtClient::XEmbedQtClient () +{ + setFrameStyle (QFrame::Box | QFrame::Sunken); + + QVBoxLayout *vlayout = new QVBoxLayout (this); + + vlayout->setAutoAdd (TRUE); + vlayout->setMargin (5); + + hbox_ = new QHBox (this); + + new QLabel ("Qt", hbox_); + + new QLineEdit (hbox_); + + QPushButton *button; + + button = new QPushButton( "&Close", hbox_ ); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(close())); + + button = new QPushButton( "&Blink", hbox_ ); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(blink())); + + button = new QPushButton( "Add >K+", hbox_ ); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(addGtkChild())); + + button = new QPushButton( "Add &Qt", hbox_ ); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(addQtChild())); + + addButtons(); +} + +void +XEmbedQtClient::blink() +{ + hide (); + + QTimer *timer = new QTimer ( this ); + QObject::connect (timer, SIGNAL(timeout()), this, SLOT(show())); + timer->start (1000, TRUE); +} + +void +XEmbedQtClient::addGtkChild() +{ + new XEmbedQtChildSite (this, FALSE, FALSE); +} + +void +XEmbedQtClient::addQtChild() +{ + new XEmbedQtChildSite (this, FALSE, TRUE); +} + +void +XEmbedQtClient::addButtons () +{ + XEmbedQtButtonBox *box = new XEmbedQtButtonBox (hbox_, this); + box->show(); +} + +int main( int argc, char **argv ) +{ + KApplication a( argc, argv, "qt-client" ); + WId embedder_xid, client_xid; + XEmbedQtClient *client; + + if (argc != 1 && argc != 2) + { + fprintf (stderr, "Usage: qt-client [WINDOW_ID]\n"); + exit (1); + } + + QXEmbed::initialize (); + + if (argc == 2) + { + embedder_xid = strtol (argv[1], NULL, 0); + if (embedder_xid == 0) + { + fprintf (stderr, "Invalid window id '%s'\n", argv[1]); + exit (1); + } + + client = new XEmbedQtClient (); + QXEmbed::embedClientIntoWindow (client, embedder_xid); + } + else + { + client = new XEmbedQtClient (); + printf ("%d\n", client->winId()); + fflush (stdout); + } + + a.setMainWidget( client ); + + return a.exec(); +} diff --git a/xembed/tests/qt-client.h b/xembed/tests/qt-client.h new file mode 100644 index 0000000..0ec1d66 --- /dev/null +++ b/xembed/tests/qt-client.h @@ -0,0 +1,34 @@ +#include <qframe.h> + +class QHBox; + +class XEmbedQtClient; + +class XEmbedQtButtonBox : public QWidget +{ + Q_OBJECT + + public: + + XEmbedQtButtonBox (QWidget *parent, XEmbedQtClient *client); +}; + +class XEmbedQtClient : public QFrame +{ + Q_OBJECT + + public: + + XEmbedQtClient (); + + public slots: + void addButtons (); + + private: + QHBox *hbox_; + + private slots: + void blink(); + void addGtkChild(); + void addQtChild(); +}; diff --git a/xembed/tests/qt-common.cpp b/xembed/tests/qt-common.cpp new file mode 100644 index 0000000..9021d7e --- /dev/null +++ b/xembed/tests/qt-common.cpp @@ -0,0 +1,30 @@ +#include "qt-common.h" + +#include <qprocess.h> + +XEmbedQtChildSite::XEmbedQtChildSite (QWidget *parent, bool active, bool isQt) + : QXEmbed (parent) +{ + show (); + + QProcess *proc = new QProcess (this); + + proc->setCommunication (QProcess::Stdout); + + if (isQt) + proc->addArgument ("./qt-client"); + else + proc->addArgument ("./gtk-client"); + + if (active) + proc->addArgument (QString::number (winId ())); + + proc->start (); + + if (!active) + { + QString pid_str = proc->readLineStdout (); + embed (pid_str.toLong ()); + } +} + diff --git a/xembed/tests/qt-common.h b/xembed/tests/qt-common.h new file mode 100644 index 0000000..28cc56f --- /dev/null +++ b/xembed/tests/qt-common.h @@ -0,0 +1,10 @@ +#include <qxembed.h> + +class XEmbedQtChildSite : public QXEmbed +{ + Q_OBJECT + + public: + + XEmbedQtChildSite (QWidget *parent, bool active, bool isQt); +}; diff --git a/xembed/tests/qt-embedder.cpp b/xembed/tests/qt-embedder.cpp new file mode 100644 index 0000000..e004204 --- /dev/null +++ b/xembed/tests/qt-embedder.cpp @@ -0,0 +1,111 @@ +#include <kapp.h> +#include <qmenubar.h> +#include <qmessagebox.h> +#include <qpopupmenu.h> +#include <qpushbutton.h> +#include <qvbox.h> + +#include "qt-common.h" +#include "qt-embedder.h" + +XEmbedQtEmbedder::XEmbedQtEmbedder () +{ + // Create menu + QPopupMenu *file_menu = new QPopupMenu (this); + + menuBar()->insertItem ("&File", file_menu); + + file_menu->insertItem( "&Quit", this, SLOT( maybeQuit() ), CTRL+Key_Q ); + + vbox_ = new QVBox (this); + + setCentralWidget (vbox_); + + QPushButton *button; + + button = new QPushButton ("Add Active GTK+ Child", vbox_); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(addActiveGtkChild())); + + button = new QPushButton ("Add Passive GTK+ Child", vbox_); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(addPassiveGtkChild())); + + button = new QPushButton ("Add Active Qt Child", vbox_); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(addActiveQtChild())); + + button = new QPushButton ("Add Passive Qt Child", vbox_); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(addPassiveQtChild())); + + button = new QPushButton ("Remove Last Child", vbox_); + QObject::connect (button, SIGNAL(clicked()), this, SLOT(removeChild())); +} + +void +XEmbedQtEmbedder::addChild (bool active, bool isQt) +{ + XEmbedQtChildSite *site = new XEmbedQtChildSite (vbox_, active, isQt); + + embedders_.append (site); +} + +void +XEmbedQtEmbedder::addActiveGtkChild () +{ + addChild (TRUE, FALSE); +} + +void +XEmbedQtEmbedder::addPassiveGtkChild () +{ + addChild (FALSE, FALSE); +} + +void +XEmbedQtEmbedder::addActiveQtChild () +{ + addChild (TRUE, TRUE); +} + +void +XEmbedQtEmbedder::addPassiveQtChild () +{ + addChild (FALSE, TRUE); +} + +void +XEmbedQtEmbedder::removeChild () +{ + if (!embedders_.isEmpty ()) + { + embedders_.getLast()->close(); + embedders_.removeLast(); + } +} + +void +XEmbedQtEmbedder::maybeQuit () +{ + QMessageBox mb( "qt-embedder", "Really Quit?", + QMessageBox::Information, + QMessageBox::Yes | QMessageBox::Default, + QMessageBox::Cancel | QMessageBox::Escape, + 0, this ); + mb.setButtonText( QMessageBox::Yes, "&Quit" ); + mb.setButtonText( QMessageBox::No, "Cancel"); + + if (mb.exec() == QMessageBox::Yes) + { + qApp->closeAllWindows (); + } +} + +int main( int argc, char **argv ) +{ + KApplication a( argc, argv, "qt-embedder" ); + + XEmbedQtEmbedder *embedder = new XEmbedQtEmbedder (); + + a.setMainWidget( embedder ); + embedder->show(); + + return a.exec(); +} diff --git a/xembed/tests/qt-embedder.h b/xembed/tests/qt-embedder.h new file mode 100644 index 0000000..ab678f9 --- /dev/null +++ b/xembed/tests/qt-embedder.h @@ -0,0 +1,28 @@ +#include <qmainwindow.h> +#include <qptrlist.h> + +class QVBox; + +class XEmbedQtEmbedder : public QMainWindow +{ + Q_OBJECT + + public: + + XEmbedQtEmbedder (); + + private: + QVBox *vbox_; + QPtrList<QWidget> embedders_; + + void addChild (bool active, bool isQt); + + private slots: + + void addActiveGtkChild (); + void addPassiveGtkChild (); + void addActiveQtChild (); + void addPassiveQtChild (); + void removeChild (); + void maybeQuit (); +}; |