Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Total rewrite to use s-expressions

  • Loading branch information...
commit a9e0f7900e637d7c7096fa64518b0ffa2ed44ae0 1 parent a6b7c06
Ross Burton authored
Showing with 2,989 additions and 2,425 deletions.
  1. +7 −0 ChangeLog
  2. +229 −0 INSTALL
  3. +2 −28 Makefile.am
  4. +8 −0 NEWS
  5. +51 −37 README
  6. +11 −3 TODO
  7. +19 −28 configure.in
  8. +6 −2 devilspie.1
  9. +0 −28 devilspie.dtd
  10. +0 −8 devilspie.gladep
  11. +0 −46 docs2html.xsl
  12. +6 −17 po/POTFILES.in
  13. +251 −232 po/de.po
  14. +0 −111 sample-config.xml
  15. +3 −37 src/.cvsignore
  16. +15 −103 src/Makefile.am
  17. +328 −0 src/actions.c
  18. +48 −0 src/actions.h
  19. +0 −619 src/config-parser.c
  20. +0 −6 src/config-parser.h
  21. +0 −34 src/devilspie-action-debug.gob
  22. +0 −96 src/devilspie-action-decorate.gob
  23. +0 −37 src/devilspie-action-hide.gob
  24. +0 −47 src/devilspie-action-layer.gob
  25. +0 −99 src/devilspie-action-resize.gob
  26. +0 −55 src/devilspie-action-savegeometry.gob
  27. +0 −114 src/devilspie-action-setwintype.gob
  28. +0 −54 src/devilspie-action-setworkspace.gob
  29. +0 −52 src/devilspie-action-shade.gob
  30. +0 −25 src/devilspie-action.gob
  31. +0 −22 src/devilspie-matcher-always.gob
  32. +0 −140 src/devilspie-matcher-windowname.gob
  33. +0 −21 src/devilspie-matcher.gob
  34. +82 −49 src/devilspie.c
  35. +41 −0 src/devilspie.h
  36. +0 −100 src/doc-generator.c
  37. +1,308 −0 src/e-sexp.c
  38. +151 −0 src/e-sexp.h
  39. +0 −91 src/flurb.c
  40. +0 −15 src/flurb.h
  41. +95 −0 src/logical.c
  42. +32 −0 src/logical.h
  43. +62 −0 src/matchers.c
  44. +32 −0 src/matchers.h
  45. +0 −59 src/parser-test.c
  46. +174 −0 src/parser.c
  47. +25 −0 src/parser.h
  48. +0 −7 src/tristate-dummy.gob
  49. +3 −3 src/xutils.c
View
7 ChangeLog
@@ -1,3 +1,10 @@
+2005-09-27 Ross Burton <ross@burtonini.com>
+
+ * */*:
+ Utter, complete, and total rewrite from scratch. XML is dead, long
+ live s-expressions with logical operations! This rewrite was
+ sponsored by Lars Damerow <lars@pixar.com>.
+
2005-09-26 Ross Burton <ross@burtonini.com>
* src/Makefile.am:
View
229 INSTALL
@@ -0,0 +1,229 @@
+Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 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=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH 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=PATH' 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
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`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.
+
View
30 Makefile.am
@@ -1,41 +1,15 @@
SUBDIRS = po src
-#
-# Man page
-#
-
man_MANS = devilspie.1
-#
-# The Matcher/Action reference documentation
-#
-
-noinst_DATA = devilspie-reference.html
-
-docs.xml:
- $(top_builddir)/src/doc-generator $@
-.INTERMEDIATE: docs.xml
-
-devilspie-reference.html: docs2html.xsl docs.xml
- xsltproc -o $@ $^
-CLEANFILES = docs.xml devilspie-reference.html
-
-#
-# The rest
-#
-
EXTRA_DIST = \
- devilspie.spec.in \
- devilspie.spec \
autogen.sh \
+ devilspie.spec.in devilspie.spec \
$(addsuffix .in, $(INTLTOOL_BUILT)) \
- sample-config.xml \
- devilspie.dtd \
- docs2html.xsl \
$(man_MANS)
INTLTOOL_BUILT = \
intltool-extract \
intltool-merge \
intltool-update
-CLEANFILES += $(INTLTOOL_BUILT)
+CLEANFILES = $(INTLTOOL_BUILT)
View
8 NEWS
@@ -1,3 +1,11 @@
+Devil's Pie "Trying To Make Their Paper" 0.12
+=============================================
+
+* Quit if no flurbs were loaded
+* Use GOption
+* Major code cleanup
+
+
Devil's Pie "Used To Love You" 0.11
===================================
View
88 README
@@ -1,7 +1,7 @@
Devil's Pie
===========
-Copyright (C) 2002-4, Ross Burton <ross@burtonini.com>
+Copyright (C) 2002-5, Ross Burton <ross@burtonini.com>
A window-matching utility, inspired by Sawfish's "Matched Windows" option and
@@ -24,55 +24,69 @@ Debian packages of the latest released version. These are available from
http://www.burtonini.com/debian/
A .spec file is provided for RPM-based distributions, but I didn't write it and
-don't support it.
+don't support it. It may or may not work.
Configuration
-------------
-The default configuration file to read is ~/.devilspie.xml. However, if there
-are arguments to devilspie then that file will be opened instead.
+Devil's Pie 0.13 was a complete redesign and rewrite, so everything you knew
+about it is probably wrong.
-The format of this file is simple. It's a collection of 'flurbs'. Each flurb
-contains one or several matchers and one or several actions. Each matcher or
-action may contain one or several properties. You should have a look at the
-included DTD for more details. The DTD will make creating valid files much
-easier in SGML editors, such as XEmacs+psgml (this DTD is installed correctly on
-Debian). A GUI builder is planned, if I can think of a good interface for it.
+Devi's Pie is configured by reading a number of files from two locations:
+$HOME/.devilspie/ and $SYSCONFDIR/devilspie (typically /etc/devilspie). Devil's
+Pie will read s-expressions from every .ds file in those paths. Note that
+currently only the first s-expressions is parsed, but this will be fixed
+shortly. S-expressions are familiar to most Emacs users and in the limited use
+they have in Devil's Pie are trivially learnt by example.
-See devilspie-reference.html for a complete list of matchers and actions. This is
-generated from the source so should be totally up to date. Unless otherwise
-stated, all properties contain a tristate value which can either be TRUE, FALSE,
-or UNSET.
+The basic model is that every time a window is created, the s-expressions are
+evaluated. The window is available to the functions you call as an implicit
+argument, so you can concentrate on defining the logic.
-There is a working example configuration file in sample-config.xml.
+If you want to see information about every window when it is created, in
+~/.devilspies/test.ds put:
+ (debug)
-Running
--------
+When this is evaluated, the "debug" function is called and it outputs the window
+title, geometry, etc.
-Just run devilspie as a normal user. The best way is to run it in your session
-(for example in Desktop Preferences -> Advanced -> Sessions -> Startup
-Programs). If you don't wish to use ~/.devilspie.xml as the configuration file,
-specify it as an argument (i.e. devilspie /home/share/devilspie-common.xml).
+Of course performing the same action to every window is no fun. What if you
+want XMMS to start on the second workspace?
+
+ (if (is (application_name) "XMMS") (set_workspace 2))
+
+The "if" function evaluates the first argument as a true/false value, and if it
+is true then it evaluates the second argument, and if false it evaluates the
+third argument (which can be omitted). The "is" function compares two strings
+for equality, returning true if they are identical. The "application_name"
+function returns the name of the application which created the window, and
+"XMMS" is a literal string. So if the application name is "XMMS", then the
+second argument will be evaluated. This is a call to "set_workspace" with the
+integer argument 2, which moves the current window onto the second workspace.
+
+To perform multiple actions use (begin ...):
+ (if (matches (window_name) "^Character.+") (begin maximize (set_workspace 2)))
-Architecture
-------------
+Here "matches" interprets the second argument as a regular expression and
+evaulates that against the first argument. "window_name" is the title of the
+current window, and "maximize" simply maximises the current window. So this
+s-expression puts the window on workspace 2, maximised, if the window name
+begins with "Character" and has more characters in (note .+ rather than .*).
-After the configuration file has been read and parsed, devilspie sits in a GLib
-main loop waiting on libwnck to notify itself about window creation. When a
-window is created, devilspie iterates through every "Flurb" (a set of matches
-and actions) and executes every matcher. If they all return true, then all of
-the actions are executed.
+I will write more documentation in the future but for now you'll have to look at
+the "symbols" array in src/parser.c to see what functions are available.
-Matchers and Actions are GObjects, subclasses of DevilsPieMatcher and
-DevilsPieAction. They must export any properties they support via GObject
-properties. I recommend using GOB to write these, as it makes it much easier.
-When GOB supports it, the Matcher and Action classes will become pure
-interfaces, but for now they are abstract classes.
-Many properties use a tristate variable type called DevilsPieTriState, which
-supports TRUE, FALSE, and UNSET. The declaration of this is a bit hacky at the
-moment as GOB doesn't allow a .gob file without a class. I could be a real man
-and write this class manually... but I'm lazy.
+Running
+-------
+
+Just run devilspie as a normal user. The best way is to run it in your session
+(for example in Desktop Preferences -> Advanced -> Sessions -> Startup
+Programs).
+
+If you are testing some s-expressions, you can specify them on the command line
+to load just those files instead of the files specified above. To turn on some
+debugging information, pass --debug.
View
14 TODO
@@ -1,6 +1,14 @@
TODO for Devil's Pie
-* Catch events on window move and resize too
+S-Exp Port:
+* Execute command
+* Set opacity
+* Documentation generator
+* Test suite to verify logical ops at least
+* Parse multiple expressions in files
+
+General Improvements:
+* Catch events on window move and resize too?
* Add ability to insert self into session on startup
-* Use gnome-vfs to monitor the configuration file, and re-read it when
- it is changed. This is fairly trivial, props to the gnome-vfs guys.
+* Use gnome-vfs to monitor the configuration file
+* UTF-8 safe string comparison functions
View
47 configure.in
@@ -1,9 +1,9 @@
# Initial blurb
AC_PREREQ(2.52)
-AC_INIT(devilspie, 0.11 , http://www.burtonini.com/)
+AC_INIT(devilspie, 0.13 , http://www.burtonini.com/)
AC_CONFIG_SRCDIR(src/devilspie.c)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
-AM_CONFIG_HEADER(config.h)
+AM_CONFIG_HEADER(src/config.h)
# Honor aclocal flags
ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS"
@@ -20,48 +20,39 @@ AC_PROG_CC
AM_PROG_CC_STDC
AC_HEADER_STDC
GNOME_COMPILE_WARNINGS(yes)
+
AC_PROG_INTLTOOL([0.20])
+ALL_LINGUAS="de"
+AM_GLIB_GNU_GETTEXT
-# We really need gob2 to build.
-GOB2_CHECK(2.0.3)
-dnl TODO: say something if GOB2 is not found
+# Check that we actually have the libraries required to build
+PKG_CHECK_MODULES(WNCK,
+ glib-2.0 >= 2.6
+ gdk-2.0
+ libwnck-1.0 >= 0.17)
+AC_SUBST(WNCK_CFLAGS)
+AC_SUBST(WNCK_LIBS)
-PKG_CHECK_MODULES(TMP_WNCK, libwnck-1.0 >= 2.9.92,
+# See if we have new libwnck with timestamp arguments
+PKG_CHECK_MODULES(WNCK_VER, libwnck-1.0 >= 2.9.92,
wnck_new="yes", wnck_new="no")
if test "x$wnck_new" = "xyes"; then
AC_DEFINE(NEED_TIMESTAMPS,1,[Define to 1 if timestamps are needed to wnck functions])
fi
-# Check that we actually have the libraries required to
-# build. Versioned dependancy on libwnck as essential API additions
-# were made in 0.17.
-dnl TODO: make libxml conditional and don't build docs if it isn't present
-PKG_CHECK_MODULES(WNCK,
- glib-2.0 >= 2.6
- gtk+-2.0
- libwnck-1.0 >= 0.17
- libxml-2.0)
-AC_SUBST(WNCK_CFLAGS)
-AC_SUBST(WNCK_LIBS)
-
-# Now check if we have the set_fullscreen function. At some point we can support
-# only wnck >= 2.8.0.1 and this test can go.
+# Check if we have the set_fullscreen function
AC_CHECK_LIB(wnck-1, wnck_window_set_fullscreen,
have_fullscreen=1, have_fullscreen=0)
AC_DEFINE_UNQUOTED(HAVE_FULLSCREEN, $have_fullscreen, [set_fullscreen is available])
+AC_CHECK_LIB(wnck-1, wnck_window_set_window_type,
+ have_set_wintype=1, have_set_wintype=0)
+AC_DEFINE_UNQUOTED(HAVE_SET_WINDOW_TYPE, $have_set_wintype, [set_window_type is available])
+
# Check for the POSIX regexpr functions and headers
AC_CHECK_FUNCS([regcomp regexec regfree])
AC_CHECK_HEADERS([sys/types.h regex.h])
-AC_CHECK_PROG(HAVE_XSLTPROC,xsltproc, yes)
-if test "x$HAVE_XSLTPROC" != "xyes"; then
- AC_MSG_ERROR([Cannot find xsltproc. This is needed to build the reference documentation.])
-fi
-
-ALL_LINGUAS="de"
-AM_GLIB_GNU_GETTEXT
-
AC_OUTPUT([
devilspie.spec
Makefile
View
8 devilspie.1
@@ -1,17 +1,21 @@
.TH devilspie 1
.SH NAME
devilspie \- perform actions on windows as they are created
+
.SH SYNOPSIS
.B devilspie
.I "configuration-file"
+
.SH "DESCRIPTION"
.BR devilspie
is a program which can detect windows as they are created, and perform
actions on them if they match as set of criteria.
-The configuration file is a XML file. For now, the documentation for
-this file is in the example configuration file, and the relevant DTD.
+The configuration files are a set of s-expressions. For documentation and
+examples, see /usr/share/doc/devilspie/.
+
.SH BUGS
This manpage is useless, as it was thrown together on a train.
+
.SH AUTHOR
This manual page was written by Ross Burton <ross@burtonini.com>.
View
28 devilspie.dtd
@@ -1,28 +0,0 @@
-<!--
-This is the DTD for Devil's Pie configuration files
-Author: Ross Burton <ross@burtonini.com>
--->
-
-<!--
-Root element
--->
-
-<!ELEMENT devilspie (flurb)*>
-
-<!ELEMENT flurb (matchers, actions)>
-<!ATTLIST flurb name CDATA #IMPLIED>
-
-<!ELEMENT matchers (matcher)*>
-<!ELEMENT actions (action)*>
-
-<!ELEMENT matcher (property)*>
-<!ATTLIST matcher name CDATA #REQUIRED>
-
-<!ELEMENT action (property)*>
-<!ATTLIST action name CDATA #REQUIRED>
-
-<!ELEMENT property EMPTY>
-<!ATTLIST property
- name CDATA #REQUIRED
- value CDATA #REQUIRED
->
View
8 devilspie.gladep
@@ -1,8 +0,0 @@
-<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
-
-<glade-project>
- <name>devilspie</name>
- <program_name>devilspie</program_name>
- <gnome_support>FALSE</gnome_support>
-</glade-project>
View
46 docs2html.xsl
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- version="1.0">
-
- <xsl:output method="html"/>
-
- <xsl:template match="/">
- <html>
- <head>
- <title>Devil's Pie Matcher/Action Documentation</title>
- </head>
- <body>
- <h1>Devil's Pie Matcher/Action Documentation</h1>
- <xsl:apply-templates/>
- </body>
- </html>
- </xsl:template>
-
- <xsl:template match="matchers">
- <h2>Matchers</h2>
- <xsl:apply-templates/>
- </xsl:template>
-
- <xsl:template match="actions">
- <h2>Actions</h2>
- <xsl:apply-templates/>
- </xsl:template>
-
- <xsl:template match="matcher|action">
- <h3><xsl:value-of select="@name"/></h3>
- <xsl:apply-templates/>
- </xsl:template>
-
- <xsl:template match="property">
- <p>
- <tt><xsl:value-of select="@name"/> (<xsl:value-of select="@type"/>)</tt>: <xsl:value-of select="@nick"/>
- <br/>
- <xsl:if test="@minimum">
- Range: <xsl:value-of select="@minimum"/> to <xsl:value-of select="@maximum"/>
- <br/>
- </xsl:if>
- <xsl:apply-templates/>
- </p>
- </xsl:template>
-
-</xsl:stylesheet>
View
23 po/POTFILES.in
@@ -1,18 +1,7 @@
-src/config-parser.c
-src/devilspie-action-debug.gob
-src/devilspie-action-decorate.gob
-src/devilspie-action-exec.gob
-src/devilspie-action.gob
-src/devilspie-action-hide.gob
-src/devilspie-action-layer.gob
-src/devilspie-action-resize.gob
-src/devilspie-action-savegeometry.gob
-src/devilspie-action-setgeometry.gob
-src/devilspie-action-setwintype.gob
-src/devilspie-action-setworkspace.gob
-src/devilspie-matcher-always.gob
-src/devilspie-matcher.gob
-src/devilspie-matcher-windowname.gob
+src/actions.c
src/devilspie.c
-src/flurb.c
-src/tristate-dummy.gob
+src/e-sexp.c
+src/logical.c
+src/matchers.c
+src/parser.c
+src/xutils.c
View
483 po/de.po
@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: devilspie CVS (HEAD)\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2005-06-15 13:57+0200\n"
+"POT-Creation-Date: 2005-09-27 11:49+0100\n"
"PO-Revision-Date: 2005-07-04 17:15+0200\n"
"Last-Translator: Hendrik Richter <hendi@gnome-de.org>\n"
"Language-Team: German <gnome-de@gnome.org>\n"
@@ -19,317 +19,339 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: ../src/config-parser.c:171
-#, c-format
-msgid "Attribute \"%s\" repeated twice on the same <%s> element"
-msgstr "Das Attribut »%s« wurde im selben <%s>-Element mehrfach wiederholt"
+#: ../src/actions.c:40
+#, fuzzy, c-format
+msgid "Window Title: '%s'; Application Name: '%s'; Geometry: %dx%d+%d+%d\n"
+msgstr ""
+"Fenstertitel: »%s«; Anwendungsname: »%s«; Rolle: »%s«; Geometrie: »%dx%d+%d+%"
+"d«\n"
-#: ../src/config-parser.c:189
-#, c-format
-msgid "Attribute \"%s\" is invalid on <%s> element in this context"
+#: ../src/actions.c:50
+#, fuzzy
+msgid "Setting fullscreen\n"
+msgstr "Vollständiger Bildschirm"
+
+#: ../src/actions.c:56
+#, fuzzy
+msgid "Maximising\n"
+msgstr "Maximiert"
+
+#: ../src/actions.c:62
+#, fuzzy
+msgid "Maximising vertically\n"
+msgstr "Vertikal minimiert"
+
+#: ../src/actions.c:68
+#, fuzzy
+msgid "Maximising horizontally\n"
+msgstr "Horizontal maximiert"
+
+#: ../src/actions.c:74
+#, fuzzy
+msgid "Minimising\n"
+msgstr "Minimiert"
+
+#: ../src/actions.c:80
+msgid "Setting sticky\n"
msgstr ""
-"Das Attribut »%s« ist in diesem Zusammenhang ungültig, darf also nicht auf "
-"das <%s>-Element angewandt werden"
-#: ../src/config-parser.c:215
-#, c-format
-msgid "Line %d character %d: %s"
-msgstr "Zeile %d, Zeichen %d: %s"
+#: ../src/actions.c:86
+msgid "Unsetting sticky\n"
+msgstr ""
-#: ../src/config-parser.c:326 ../src/config-parser.c:365
-#: ../src/config-parser.c:404
+#: ../src/actions.c:106
#, c-format
-msgid "No \"name\" attribute on element <%s>"
-msgstr "Kein »name«-Attribut im Element <%s>"
+msgid "Workspace number %d does not exist"
+msgstr "Arbeitsflächennummer %d existiert nicht"
-#: ../src/config-parser.c:331
+#: ../src/actions.c:110
#, c-format
-msgid "No \"value\" attribute on element <%s>"
-msgstr "Kein »value«-Attribut im Element <%s>"
+msgid "Changing workspace to %d\n"
+msgstr ""
-#: ../src/config-parser.c:372
-#, c-format
-msgid "Requested type %s is not a known Matcher"
-msgstr "Der angeforderte Typ %s ist keine bekannte Bedingung"
+#: ../src/actions.c:116
+#, fuzzy
+msgid "Skipping tasklist\n"
+msgstr "Fensterliste übergehen"
-#: ../src/config-parser.c:398
-#, c-format
-msgid "Could not parse attributes of <%s>"
-msgstr "Die Attribute von »%s« konnten nicht verarbeitet werden"
+#: ../src/actions.c:122
+#, fuzzy
+msgid "Skipping pager\n"
+msgstr "Umschalter übergehen"
-#: ../src/config-parser.c:411
-#, c-format
-msgid "Requested type %s is not a known Action"
-msgstr "Der angeforderte Typ %s ist keine bekannte Aktion"
+#: ../src/actions.c:132
+msgid "Setting above\n"
+msgstr ""
-#: ../src/config-parser.c:436
-#, c-format
-msgid "Outermost element in config files must be <devilspie> not <%s>"
+#: ../src/actions.c:142
+msgid "Setting below\n"
msgstr ""
-"Das äußerste Element in Konfigurationsdateien muss <devilspie> sein, nicht <%"
-"s>"
-#: ../src/config-parser.c:452
-#, c-format
-msgid "Only <flurb> elements are allowed inside <devilspie> not <%s>"
+#: ../src/actions.c:165
+msgid "Removed decorations\n"
msgstr ""
-"In <devilspie>-Elementen sind ausschließlich <flurb>-Elemente erlaubt, keine "
-"<%s>-Elemente"
-#: ../src/config-parser.c:463
+#: ../src/config-sexp.c:72 ../src/config-sexp.c:118 ../src/config-sexp.c:164
#, c-format
-msgid ""
-"Only <matchers> and <actions> elements are allowed inside <blurb> not <%s>"
+msgid "Loading %s\n"
msgstr ""
-"In <blurb>-Elementen sind ausschließlich <matchers>- und <actions>-Elemente "
-"erlaubt, keine <%s>-Elemente"
-#: ../src/config-parser.c:474
+#: ../src/config-sexp.c:75
#, c-format
-msgid "Only <matcher> elements are allowed inside <matchers> not <%s>"
+msgid "%s is not a normal file, skipping\n"
msgstr ""
-"In <matchers>-Elementen sind ausschließlich <matcher>-Elemente erlaubt, "
-"keine <%s>-Elemente"
-#: ../src/config-parser.c:485
+#: ../src/config-sexp.c:84
#, c-format
-msgid "Only <property> elements are allowed inside <matcher> not <%s>"
+msgid "Cannot open %s\n"
msgstr ""
-"In <matcher>-Elementen sind ausschließlich <property>-Elemente erlaubt, "
-"keine <%s>-Elemente"
-#: ../src/config-parser.c:491 ../src/config-parser.c:518
+#: ../src/config-sexp.c:100 ../src/config-sexp.c:143
#, c-format
-msgid "Element <%s> is not allowed inside <property>"
-msgstr "Im <property>-Element ist das <%s>-Element nicht erlaubt"
+msgid "Cannot parse %s: %s\n"
+msgstr ""
-#: ../src/config-parser.c:501
+#: ../src/config-sexp.c:121
#, c-format
-msgid "Only <action> elements are allowed inside <actions> not <%s>"
+msgid "Cannot open file %s: %s\n"
msgstr ""
-"Im <actions>-Element sind ausschließlich <action>-Elemente erlaubt, keine <%"
-"s>-Elemente"
-#: ../src/config-parser.c:512
+#: ../src/config-sexp.c:167
+#, fuzzy, c-format
+msgid "%s doesn't exist\n"
+msgstr "Die Datei %s existiert nicht\n"
+
+#: ../src/config-sexp.c:172
#, c-format
-msgid "Only <property> elements are allowed inside <action> not <%s>"
+msgid "%s isn't a directory\n"
msgstr ""
-"Im <action>-Element sind ausschließlich <property>-Elemente erlaubt, keine <%"
-"s>-Elemente"
-#: ../src/config-parser.c:533
+#: ../src/config-sexp.c:178
#, c-format
-msgid "Can not close element <%s> outside of the root element"
+msgid "Cannot open %s: %s\n"
+msgstr ""
+
+#: ../src/devilspie.c:90
+msgid "Apply to all existing windows instead of just new windows."
+msgstr ""
+
+#: ../src/devilspie.c:91
+msgid "Output debug information"
+msgstr ""
+
+#: ../src/devilspie.c:92
+msgid "Configuration files to use"
msgstr ""
-"Element <%s> darf nicht außerhalb des Wurzelelements geschlossen werden"
-#: ../src/config-parser.c:582
+#: ../src/devilspie.c:112
#, c-format
-msgid "No text is allowed inside element <%d>"
-msgstr "Im Element <%d> ist kein Text erlaubt"
+msgid "Devil's Pie %s starting...\n"
+msgstr ""
+
+#: ../src/devilspie.c:124
+msgid "No s-expressions loaded, quiting\n"
+msgstr ""
-#: ../src/devilspie-action-debug.gob:25
+#: ../src/logical.c:82
#, c-format
-msgid ""
-"Window title: \"%s\"; Application name: \"%s\"; Role: \"%s\"; Geometry: \"%dx"
-"%d+%d+%d\"\n"
+msgid "Invalid regular expression '%s': %s"
msgstr ""
-"Fenstertitel: »%s«; Anwendungsname: »%s«; Rolle: »%s«; Geometrie: »%dx%d+%d+%"
-"d«\n"
-#: ../src/devilspie-action-decorate.gob:39
-msgid "Decorated windows"
-msgstr "Dekorierte Fenster"
+#~ msgid "Attribute \"%s\" repeated twice on the same <%s> element"
+#~ msgstr "Das Attribut »%s« wurde im selben <%s>-Element mehrfach wiederholt"
-#: ../src/devilspie-action-decorate.gob:40
-msgid "Window is decorated (OpenBox + Motif WM hints)"
-msgstr "Fenster ist dekoriert (OpenBox + Motif WM Hinweise)"
+#~ msgid "Attribute \"%s\" is invalid on <%s> element in this context"
+#~ msgstr ""
+#~ "Das Attribut »%s« ist in diesem Zusammenhang ungültig, darf also nicht "
+#~ "auf das <%s>-Element angewandt werden"
-#: ../src/devilspie-action-exec.gob:31
-msgid "Command to execute"
-msgstr "Auszuführender Befehl"
+#~ msgid "Line %d character %d: %s"
+#~ msgstr "Zeile %d, Zeichen %d: %s"
-#: ../src/devilspie-action-exec.gob:32
-msgid ""
-"This command and any arguments will be run. The title of the window and the "
-"window ID will be passed to the command as the first and second arguments"
-msgstr ""
-"Dieser Befehl wird mit allen Argumenten ausgeführt. Der Titel des Fensters "
-"und die Fensterkennung werden dem Befehl als erstes und zweites Argument "
-"übergeben."
+#~ msgid "No \"name\" attribute on element <%s>"
+#~ msgstr "Kein »name«-Attribut im Element <%s>"
-#: ../src/devilspie-action-hide.gob:14
-msgid "Skip Pager"
-msgstr "Umschalter übergehen"
+#~ msgid "No \"value\" attribute on element <%s>"
+#~ msgstr "Kein »value«-Attribut im Element <%s>"
-#: ../src/devilspie-action-hide.gob:15
-msgid "Window does not appear in the pager"
-msgstr "Fenster erscheint nicht im Arbeitsflächen-Umschalter"
+#~ msgid "Requested type %s is not a known Matcher"
+#~ msgstr "Der angeforderte Typ %s ist keine bekannte Bedingung"
-#: ../src/devilspie-action-hide.gob:21
-msgid "Skip Task List"
-msgstr "Fensterliste übergehen"
+#~ msgid "Could not parse attributes of <%s>"
+#~ msgstr "Die Attribute von »%s« konnten nicht verarbeitet werden"
-#: ../src/devilspie-action-hide.gob:22
-msgid "Window does not appear in the task list"
-msgstr "Fenster erscheint nicht in der Fensterliste"
+#~ msgid "Requested type %s is not a known Action"
+#~ msgstr "Der angeforderte Typ %s ist keine bekannte Aktion"
-#: ../src/devilspie-action-layer.gob:19
-msgid "Above windows?"
-msgstr "Vor den Fenstern?"
+#~ msgid "Outermost element in config files must be <devilspie> not <%s>"
+#~ msgstr ""
+#~ "Das äußerste Element in Konfigurationsdateien muss <devilspie> sein, "
+#~ "nicht <%s>"
-#: ../src/devilspie-action-layer.gob:20
-msgid "Window is above all others"
-msgstr "Fenster befindet sich vor allen anderen"
+#~ msgid "Only <flurb> elements are allowed inside <devilspie> not <%s>"
+#~ msgstr ""
+#~ "In <devilspie>-Elementen sind ausschließlich <flurb>-Elemente erlaubt, "
+#~ "keine <%s>-Elemente"
-#: ../src/devilspie-action-resize.gob:18
-msgid "Maximized"
-msgstr "Maximiert"
+#~ msgid ""
+#~ "Only <matchers> and <actions> elements are allowed inside <blurb> not <%s>"
+#~ msgstr ""
+#~ "In <blurb>-Elementen sind ausschließlich <matchers>- und <actions>-"
+#~ "Elemente erlaubt, keine <%s>-Elemente"
-#: ../src/devilspie-action-resize.gob:19
-msgid "Window is maximized on the screen"
-msgstr "Fenster wird auf dem Bildschirm maximiert"
+#~ msgid "Only <matcher> elements are allowed inside <matchers> not <%s>"
+#~ msgstr ""
+#~ "In <matchers>-Elementen sind ausschließlich <matcher>-Elemente erlaubt, "
+#~ "keine <%s>-Elemente"
-#: ../src/devilspie-action-resize.gob:25
-msgid "Maximized Horizontally"
-msgstr "Horizontal maximiert"
+#~ msgid "Only <property> elements are allowed inside <matcher> not <%s>"
+#~ msgstr ""
+#~ "In <matcher>-Elementen sind ausschließlich <property>-Elemente erlaubt, "
+#~ "keine <%s>-Elemente"
-#: ../src/devilspie-action-resize.gob:26
-msgid "Window is maximized horizontally on the screen"
-msgstr "Fenster wird auf dem Bildschirm horizontal maximiert"
+#~ msgid "Element <%s> is not allowed inside <property>"
+#~ msgstr "Im <property>-Element ist das <%s>-Element nicht erlaubt"
-#: ../src/devilspie-action-resize.gob:32
-msgid "Minimized Vertically"
-msgstr "Vertikal minimiert"
+#~ msgid "Only <action> elements are allowed inside <actions> not <%s>"
+#~ msgstr ""
+#~ "Im <actions>-Element sind ausschließlich <action>-Elemente erlaubt, keine "
+#~ "<%s>-Elemente"
-#: ../src/devilspie-action-resize.gob:33
-msgid "Window is minimized vertically on the screen"
-msgstr "Fenster wird auf dem Bildschirm vertikal minimiert"
+#~ msgid "Only <property> elements are allowed inside <action> not <%s>"
+#~ msgstr ""
+#~ "Im <action>-Element sind ausschließlich <property>-Elemente erlaubt, "
+#~ "keine <%s>-Elemente"
-#: ../src/devilspie-action-resize.gob:39
-msgid "Minimized"
-msgstr "Minimiert"
+#~ msgid "Can not close element <%s> outside of the root element"
+#~ msgstr ""
+#~ "Element <%s> darf nicht außerhalb des Wurzelelements geschlossen werden"
-#: ../src/devilspie-action-resize.gob:40
-msgid "Window is minimized"
-msgstr "Fenster wird minimiert"
+#~ msgid "No text is allowed inside element <%d>"
+#~ msgstr "Im Element <%d> ist kein Text erlaubt"
-#: ../src/devilspie-action-resize.gob:46
-msgid "Full screen"
-msgstr "Vollständiger Bildschirm"
+#~ msgid "Decorated windows"
+#~ msgstr "Dekorierte Fenster"
-#: ../src/devilspie-action-resize.gob:47
-msgid "Window fills the screen"
-msgstr "Fenster füllt den ganzen Bildschirm"
+#~ msgid "Window is decorated (OpenBox + Motif WM hints)"
+#~ msgstr "Fenster ist dekoriert (OpenBox + Motif WM Hinweise)"
-#: ../src/devilspie-action-savegeometry.gob:24
-#, c-format
-msgid "Window %s geometry changed"
-msgstr "Geometrie des Fensters %s geändert"
+#~ msgid "Command to execute"
+#~ msgstr "Auszuführender Befehl"
-#: ../src/devilspie-action-savegeometry.gob:31
-#, c-format
-msgid "Window %s closed"
-msgstr "Fenster %s geschlossen"
+#~ msgid ""
+#~ "This command and any arguments will be run. The title of the window and "
+#~ "the window ID will be passed to the command as the first and second "
+#~ "arguments"
+#~ msgstr ""
+#~ "Dieser Befehl wird mit allen Argumenten ausgeführt. Der Titel des "
+#~ "Fensters und die Fensterkennung werden dem Befehl als erstes und zweites "
+#~ "Argument übergeben."
-#: ../src/devilspie-action-savegeometry.gob:35
-msgid "Starting SaveGeometry action"
-msgstr "Aktion »SaveGeometry« wird gestartet"
+#~ msgid "Window does not appear in the pager"
+#~ msgstr "Fenster erscheint nicht im Arbeitsflächen-Umschalter"
-#: ../src/devilspie-action-setgeometry.gob:14
-msgid "X offset"
-msgstr "X-Versatz"
+#~ msgid "Window does not appear in the task list"
+#~ msgstr "Fenster erscheint nicht in der Fensterliste"
-#: ../src/devilspie-action-setgeometry.gob:15
-msgid "Horizontal offset of the window"
-msgstr "Horizontaler Versatz des Fensters"
+#~ msgid "Above windows?"
+#~ msgstr "Vor den Fenstern?"
-#: ../src/devilspie-action-setgeometry.gob:21
-msgid "Y offset"
-msgstr "Y-Versatz"
+#~ msgid "Window is above all others"
+#~ msgstr "Fenster befindet sich vor allen anderen"
-#: ../src/devilspie-action-setgeometry.gob:22
-msgid "Vertical offset of the window"
-msgstr "Vertikaler Versatz des Fensters"
+#~ msgid "Window is maximized on the screen"
+#~ msgstr "Fenster wird auf dem Bildschirm maximiert"
-#: ../src/devilspie-action-setgeometry.gob:28
-msgid "Width"
-msgstr "Breite"
+#~ msgid "Window is maximized horizontally on the screen"
+#~ msgstr "Fenster wird auf dem Bildschirm horizontal maximiert"
-#: ../src/devilspie-action-setgeometry.gob:29
-msgid "Width of the window"
-msgstr "Breite des Fensters"
+#~ msgid "Window is minimized vertically on the screen"
+#~ msgstr "Fenster wird auf dem Bildschirm vertikal minimiert"
-#: ../src/devilspie-action-setgeometry.gob:35
-msgid "Height"
-msgstr "Höhe"
+#~ msgid "Window is minimized"
+#~ msgstr "Fenster wird minimiert"
-#: ../src/devilspie-action-setgeometry.gob:36
-msgid "Height of the window"
-msgstr "Höhe des Fensters"
+#~ msgid "Window fills the screen"
+#~ msgstr "Fenster füllt den ganzen Bildschirm"
-#: ../src/devilspie-action-setwintype.gob:71
-msgid "Window type hint"
-msgstr "Fenstertyp-Hinweis"
+#~ msgid "Window %s geometry changed"
+#~ msgstr "Geometrie des Fensters %s geändert"
-#: ../src/devilspie-action-setwintype.gob:72
-msgid "The window type hint"
-msgstr "Der Fenstertyp-Hinweis"
+#~ msgid "Window %s closed"
+#~ msgstr "Fenster %s geschlossen"
-#: ../src/devilspie-action-setworkspace.gob:15
-msgid "Pinned"
-msgstr "Auf allen Arbeitsflächen"
+#~ msgid "Starting SaveGeometry action"
+#~ msgstr "Aktion »SaveGeometry« wird gestartet"
-#: ../src/devilspie-action-setworkspace.gob:16
-msgid "Window is pinned on all workspaces, aka sticky"
-msgstr "Fenster wird auf alle Arbeitsflächen gelegt"
+#~ msgid "X offset"
+#~ msgstr "X-Versatz"
-#: ../src/devilspie-action-setworkspace.gob:22
-msgid "Workspace"
-msgstr "Arbeitsfläche"
+#~ msgid "Horizontal offset of the window"
+#~ msgstr "Horizontaler Versatz des Fensters"
-#: ../src/devilspie-action-setworkspace.gob:23
-msgid "Which workspace to move this window to (numbered)"
-msgstr ""
-"Auf welche Arbeitsfläche soll dieses Fenster verschoben werden "
-"(durchgezählt)?"
+#~ msgid "Y offset"
+#~ msgstr "Y-Versatz"
-#: ../src/devilspie-action-setworkspace.gob:38
-#, c-format
-msgid "Workspace number %d does not exist"
-msgstr "Arbeitsflächennummer %d existiert nicht"
+#~ msgid "Vertical offset of the window"
+#~ msgstr "Vertikaler Versatz des Fensters"
-#: ../src/devilspie-matcher-windowname.gob:65
-msgid "Window title regexp"
-msgstr "Regulärer Ausdruck im Fenstertitel"
+#~ msgid "Width"
+#~ msgstr "Breite"
-#: ../src/devilspie-matcher-windowname.gob:66
-msgid "The regular expression that should match the window title"
-msgstr "Der reguläre Ausdruck, der im Fenstertitel vorkommen muss"
+#~ msgid "Width of the window"
+#~ msgstr "Breite des Fensters"
-#: ../src/devilspie-matcher-windowname.gob:77
-msgid "Application name regexp"
-msgstr "Regulärer Ausdruck im Anwendungsnamen"
+#~ msgid "Height"
+#~ msgstr "Höhe"
-#: ../src/devilspie-matcher-windowname.gob:78
-msgid ""
-"The regular expression that should match the name of the application (as "
-"determined by libwnck)"
-msgstr ""
-"Der reguläre Ausdruck, der im Namen der Anwendung vorkommen muss (dieser "
-"wird von libwnck ermittelt)"
+#~ msgid "Height of the window"
+#~ msgstr "Höhe des Fensters"
-#: ../src/devilspie-matcher-windowname.gob:90
-msgid "Window role regexp"
-msgstr "Regulärer Ausdruck in der Fensterrolle"
+#~ msgid "Window type hint"
+#~ msgstr "Fenstertyp-Hinweis"
-#: ../src/devilspie-matcher-windowname.gob:91
-msgid ""
-"The regular expression that should match the role of the window (set by "
-"WM_WINDOW_ROLE atom)"
-msgstr ""
-"Der Reguläre Ausdruck, der in der Rolle des Fensters vorkommen muss (diese "
-"wird mittels des WM_WINDOW_ROLE-Atoms festgelegt)"
+#~ msgid "The window type hint"
+#~ msgstr "Der Fenstertyp-Hinweis"
+
+#~ msgid "Pinned"
+#~ msgstr "Auf allen Arbeitsflächen"
+
+#~ msgid "Window is pinned on all workspaces, aka sticky"
+#~ msgstr "Fenster wird auf alle Arbeitsflächen gelegt"
+
+#~ msgid "Workspace"
+#~ msgstr "Arbeitsfläche"
+
+#~ msgid "Which workspace to move this window to (numbered)"
+#~ msgstr ""
+#~ "Auf welche Arbeitsfläche soll dieses Fenster verschoben werden "
+#~ "(durchgezählt)?"
+
+#~ msgid "Window title regexp"
+#~ msgstr "Regulärer Ausdruck im Fenstertitel"
+
+#~ msgid "The regular expression that should match the window title"
+#~ msgstr "Der reguläre Ausdruck, der im Fenstertitel vorkommen muss"
+
+#~ msgid "Application name regexp"
+#~ msgstr "Regulärer Ausdruck im Anwendungsnamen"
+
+#~ msgid ""
+#~ "The regular expression that should match the name of the application (as "
+#~ "determined by libwnck)"
+#~ msgstr ""
+#~ "Der reguläre Ausdruck, der im Namen der Anwendung vorkommen muss (dieser "
+#~ "wird von libwnck ermittelt)"
+
+#~ msgid "Window role regexp"
+#~ msgstr "Regulärer Ausdruck in der Fensterrolle"
+
+#~ msgid ""
+#~ "The regular expression that should match the role of the window (set by "
+#~ "WM_WINDOW_ROLE atom)"
+#~ msgstr ""
+#~ "Der Reguläre Ausdruck, der in der Rolle des Fensters vorkommen muss "
+#~ "(diese wird mittels des WM_WINDOW_ROLE-Atoms festgelegt)"
#~ msgid "*"
#~ msgstr "*"
@@ -380,6 +402,3 @@ msgstr ""
#~ "Verwendung: devilspie [Konfigurationsdatei]\n"
#~ "Falls Sie keine Konfigurationsdatei übergeben, wird ~/.devilspie.xml "
#~ "verwendet.\n"
-
-#~ msgid "File %s does not exist\n"
-#~ msgstr "Die Datei %s existiert nicht\n"
View
111 sample-config.xml
@@ -1,111 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE devilspie SYSTEM "devilspie.dtd">
-
-<!-- The root element is devilspie -->
-<devilspie>
-
- <!--
- This starts a new flurb, which is a set of matchers and actions.
- This flurb matches all windows, and prints out the window name and application name
- -->
- <flurb name="Print Window Names">
- <matchers>
- <!-- this is a matcher which always returns true. The full class name must be used -->
- <matcher name="DevilsPieMatcherAlways"/>
- </matchers>
- <actions>
- <!-- this action prints out the window and application name -->
- <action name="DevilsPieActionDebug"/>
- </actions>
- </flurb>
-
- <!--
- This flurb is actually useful. Match any XChat window, and pin it so that it
- appears on all workspaces.
- -->
- <flurb name="X-Chat on all Desktops">
- <matchers>
- <matcher name="DevilsPieMatcherWindowName">
- <property name="application_name" value="Xchat"/>
- </matcher>
- </matchers>
- <actions>
- <action name="DevilsPieActionSetWorkspace">
- <property name="pinned" value="TRUE"/>
- </action>
- </actions>
- </flurb>
-
- <flurb>
- <matchers>
- <matcher name="DevilsPieMatcherWindowName">
- <property name="window_title" value="gnome-panel"/>
- </matcher>
- </matchers>
- <actions>
- <action name="DevilsPieActionLayer">
- <property name="above" value="FALSE"/>
- </action>
- </actions>
- </flurb>
-
- <!--
- This will put all GNOME Calculators on the second workspace.
- Note that the workspace number is a 1-based index, not a
- 0-based index.
- -->
- <flurb>
- <matchers>
- <matcher name="DevilsPieMatcherWindowName">
- <property name="application_name" value="Gnome-calculator"/>
- </matcher>
- </matchers>
- <actions>
- <action name="DevilsPieActionSetWorkspace">
- <property name="workspace_index" value="2"/>
- </action>
- <action name="DevilsPieActionHide">
- <property name="skip_tasklist" value="TRUE"/>
- </action>
- </actions>
- </flurb>
-
-
- <!--
- Start Galeon browser without window decorations on 3rd workspace
- -->
- <flurb>
- <matchers>
- <matcher name="DevilsPieMatcherWindowName">
- <property name="application_name" value="Galeon"/>
- </matcher>
- </matchers>
- <actions>
- <action name="DevilsPieActionDecorate">
- <property name="decorated" value="FALSE"/>
- </action>
- <action name="DevilsPieActionSetWorkspace">
- <property name="workspace_index" value="3"/>
- </action>
- </actions>
- </flurb>
-
- <!--
- Move all GNOME Dictionary windows to 200x200, 100 px wide and 50 px high.
- -->
- <flurb>
- <matchers>
- <matcher name="DevilsPieMatcherWindowName">
- <property name="application_name" value="gnome-dictionary"/>
- </matcher>
- </matchers>
- <actions>
- <action name="DevilsPieActionSetGeometry">
- <property name="xoffset" value="200"/>
- <property name="yoffset" value="200"/>
- <property name="width" value="100"/>
- <property name="height" value="50"/>
- </action>
- </actions>
- </flurb>
-</devilspie>
View
40 src/.cvsignore
@@ -1,40 +1,6 @@
Makefile
Makefile.in
devilspie
-devilspie-action-debug.c
-devilspie-action-debug.h
-devilspie-action-decorate.c
-devilspie-action-decorate.h
-devilspie-action-exec.c
-devilspie-action-exec.h
-devilspie-action-hide.c
-devilspie-action-hide.h
-devilspie-action-layer.c
-devilspie-action-layer.h
-devilspie-action-resize.c
-devilspie-action-resize.h
-devilspie-action-opacity.c
-devilspie-action-opacity.h
-devilspie-action-savegeometry.c
-devilspie-action-savegeometry.h
-devilspie-action-setgeometry.c
-devilspie-action-setgeometry.h
-devilspie-action-setwintype.c
-devilspie-action-setwintype.h
-devilspie-action-setworkspace.c
-devilspie-action-setworkspace.h
-devilspie-action-shade.c
-devilspie-action-shade.h
-devilspie-action.c
-devilspie-action.h
-devilspie-matcher-always.c
-devilspie-matcher-always.h
-devilspie-matcher-windowname-private.h
-devilspie-matcher-windowname.c
-devilspie-matcher-windowname.h
-devilspie-matcher.c
-devilspie-matcher.h
-doc-generator
-parser-test
-tristate-dummy.c
-tristate-dummy.h
+config.h
+config.h.in
+stamp-h1
View
118 src/Makefile.am
@@ -1,120 +1,32 @@
-# We only install devilspie at the moment
+# The main binary
bin_PROGRAMS = devilspie
-# Build but don't install the doc generator
-noinst_PROGRAMS = doc-generator
-
-# Build the parser test if we are running tests
-check_PROGRAMS = parser-test
-TESTS = parser-test
-
devilspie_SOURCES = \
- ${BUILT_SOURCES} \
- config-parser.c \
- flurb.h \
- flurb.c \
devilspie.h \
devilspie.c \
xutils.h \
- xutils.c
-
-doc_generator_SOURCES = \
- ${BUILT_SOURCES} \
- flurb.h \
- flurb.c \
- xutils.h \
xutils.c \
- doc-generator.c
-
-parser_test_SOURCES = \
- ${BUILT_SOURCES} \
- config-parser.c \
- flurb.h \
- flurb.c \
- xutils.h \
- xutils.c \
- devilspie.h \
- parser-test.c
-
-INCLUDES = \
+ e-sexp.h \
+ e-sexp.c \
+ parser.h \
+ parser.c \
+ logical.h \
+ logical.c \
+ matchers.h \
+ matchers.c \
+ actions.h \
+ actions.c
+
+AM_CPPFLAGS = \
$(WNCK_CFLAGS) \
-DLOCALEDIR=\""$(datadir)/locale"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
-DDATADIR=\""$(datadir)"\" \
-DG_DISABLE_DEPRECATED \
-DGDK_DISABLE_DEPRECATED \
-DGTK_DISABLE_DEPRECATED \
-DWNCK_I_KNOW_THIS_IS_UNSTABLE
-AM_CFLAGS = -Wall
+AM_CFLAGS = @WARN_CFLAGS@
LDADD = ${WNCK_LIBS}
-
-# The long list of sources which are generated from .gob files.
-BUILT_SOURCES = \
- tristate-dummy.c \
- tristate-dummy.h \
- devilspie-matcher.c \
- devilspie-matcher.h \
- devilspie-matcher-windowname.c \
- devilspie-matcher-windowname.h \
- devilspie-matcher-windowname-private.h \
- devilspie-matcher-always.c \
- devilspie-matcher-always.h \
- devilspie-action.c \
- devilspie-action.h \
- devilspie-action-debug.c \
- devilspie-action-debug.h \
- devilspie-action-decorate.c \
- devilspie-action-decorate.h \
- devilspie-action-exec.c \
- devilspie-action-exec.h \
- devilspie-action-hide.c \
- devilspie-action-hide.h \
- devilspie-action-layer.c \
- devilspie-action-layer.h \
- devilspie-action-opacity.c \
- devilspie-action-opacity.h \
- devilspie-action-resize.c \
- devilspie-action-resize.h \
- devilspie-action-shade.c \
- devilspie-action-shade.h \
- devilspie-action-savegeometry.c \
- devilspie-action-savegeometry.h \
- devilspie-action-setgeometry.c \
- devilspie-action-setgeometry.h \
- devilspie-action-setwintype.c \
- devilspie-action-setwintype.h \
- devilspie-action-setworkspace.c \
- devilspie-action-setworkspace.h
-
-# Leaving this list in as a reminder that some day most of this file
-# should involve $(addprefix) functions, if only automake suported
-# them.
-devilspie_GOBS = \
- tristate-dummy \
- devilspie-matcher \
- devilspie-matcher-windowname \
- devilspie-matcher-always \
- devilspie-action \
- devilspie-action-debug \
- devilspie-action-decorate \
- devilspie-action-exec \
- devilspie-action-hide \
- devilspie-action-layer \
- devilspie-action-opacity \
- devilspie-action-resize \
- devilspie-action-shade \
- devilspie-action-savegeometry \
- devilspie-action-setgeometry \
- devilspie-action-setwintype \
- devilspie-action-setworkspace
-
-# Must distribute the gob files!
-EXTRA_DIST = $(addsuffix .gob, ${devilspie_GOBS})
-
-CLEANFILES = ${BUILT_SOURCES}
-
-SUFFIXES = .gob
-
-%.c %.h %-private.h: %.gob
- @GOB2@ $<
View
328 src/actions.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2005 Ross Burton <ross@burtonini.com>
+ *
+ * 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 <config.h>
+#include <libwnck/application.h>
+#include <libwnck/window.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "e-sexp.h"
+#include "xutils.h"
+#include "devilspie.h"
+#include "actions.h"
+
+/*
+ * Actions to perform on windows.
+ */
+
+/**
+ * Debugging function, outputs the current window's title, name, role and geometry.
+ */
+ESExpResult *func_debug(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ gint xoffset, yoffset, width, height;
+
+ wnck_window_get_geometry(c->window, &xoffset, &yoffset, &width, &height);
+
+ if (argc == 1 && argv[0]->type == ESEXP_RES_STRING)
+ g_print("%s\n", argv[0]->value.string);
+
+ g_print(_("Window Title: '%s'; Application Name: '%s'; Geometry: %dx%d+%d+%d\n"),
+ wnck_window_get_name (c->window),
+ wnck_application_get_name (wnck_window_get_application (c->window)),
+ width, height, xoffset, yoffset);
+
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Make the current window fullscreen.
+ */
+ESExpResult *func_fullscreen(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ wnck_window_set_fullscreen (c->window, TRUE);
+ if (debug) g_printerr(_("Setting fullscreen\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Maximise the current window.
+ */
+ESExpResult *func_maximize(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ /* TODO: take an boolean to unmaximize */
+ wnck_window_maximize (c->window);
+ if (debug) g_printerr(_("Maximising\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Maximise vertically the current window.
+ */
+ESExpResult *func_maximize_vertically(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ /* TODO: take an boolean to unmaximize_vertically */
+ wnck_window_maximize_vertically (c->window);
+ if (debug) g_printerr(_("Maximising vertically\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Maximise horizontally the current window.
+ */
+ESExpResult *func_maximize_horizontally(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ /* TODO: take an boolean to unmaximize_horizontally */
+ wnck_window_maximize_horizontally (c->window);
+ if (debug) g_printerr(_("Maximising horizontally\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Minimise the current window.
+ */
+ESExpResult *func_minimize(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ /* TODO: take an boolean to unminimize */
+ wnck_window_minimize (c->window);
+ if (debug) g_printerr(_("Minimising\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Shade ("roll up") the current window.
+ */
+ESExpResult *func_shade(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ wnck_window_shade (c->window);
+ if (debug) g_printerr(_("Shaded\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Unshade ("roll down") the current window.
+ */
+ESExpResult *func_unshade(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ wnck_window_unshade (c->window);
+ if (debug) g_printerr(_("Unshaded\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Pin the current window to all workspaces.
+ */
+ESExpResult *func_pin(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ wnck_window_stick (c->window);
+ if (debug) g_printerr(_("Setting sticky\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Unpin the current window from all workspaces.
+ */
+ESExpResult *func_unpin(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ wnck_window_unstick (c->window);
+ if (debug) g_printerr(_("Unsetting sticky\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Move the window to a specific workspace number, counting from 1.
+ */
+ESExpResult *func_set_workspace(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ WnckScreen *screen;
+ WnckWorkspace *workspace;
+ int num;
+
+ if (argc != 1 || argv[0]->type != ESEXP_RES_INT) {
+ g_printerr(_("set_workspace expects a single integer argument\n"));
+ return e_sexp_result_new_bool (f, FALSE);
+ }
+
+ num = argv[0]->value.number;
+
+ screen = wnck_window_get_screen(c->window);
+ /* Adjust for 0-offset in workspaces list */
+ workspace = wnck_screen_get_workspace(screen, num-1);
+ if (!workspace) {
+ g_warning(_("Workspace number %d does not exist"), num);
+ }
+ wnck_window_move_to_workspace(c->window, workspace);
+
+ if (debug) g_printerr(_("Changing workspace to %d\n"), num);
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Remove the current window from the window list.
+ */
+ESExpResult *func_skip_tasklist(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ wnck_window_set_skip_tasklist (c->window, TRUE);
+ if (debug) g_printerr(_("Skipping tasklist\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Remove the current window from the pager.
+ */
+ESExpResult *func_skip_pager(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ wnck_window_set_skip_pager (c->window, TRUE);
+ if (debug) g_printerr(_("Skipping pager\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Set the current window to be above all normal windows.
+ */
+ESExpResult *func_above(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ my_wnck_change_state (my_wnck_window_get_xscreen(c->window),
+ wnck_window_get_xid(c->window),
+ TRUE,
+ my_wnck_atom_get ("_NET_WM_STATE_ABOVE"),
+ 0);
+ if (debug) g_printerr(_("Setting above\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Set the current window to be below all normal windows.
+ */
+ESExpResult *func_below(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ my_wnck_change_state (my_wnck_window_get_xscreen(c->window),
+ wnck_window_get_xid(c->window),
+ TRUE,
+ my_wnck_atom_get ("_NET_WM_STATE_BELOW"),
+ 0);
+ if (debug) g_printerr(_("Setting below\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+/**
+ * Remove the window manager decorations from the current window.
+ */
+ESExpResult *func_undecorate(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
+#define MWM_HINTS_DECORATIONS (1L << 1)
+ struct {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long inputMode;
+ unsigned long status;
+ } hints = {0,};
+
+ hints.flags = MWM_HINTS_DECORATIONS;
+ hints.decorations = 0;
+
+ XChangeProperty(GDK_DISPLAY(), wnck_window_get_xid (c->window),
+ my_wnck_atom_get ("_MOTIF_WM_HINTS"),
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *)&hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
+
+ if (debug) g_printerr(_("Removed decorations\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
+
+#if ! HAVE_SET_WINDOW_TYPE
+/*
+ * This function is only available in recent libwncks, so include it here if it
+ * isn't present.
+ */
+static void my_wnck_window_set_window_type (WnckWindow *window, WnckWindowType wintype)
+{
+ Atom atom;
+
+ g_return_if_fail (WNCK_IS_WINDOW (window));
+
+ switch (wintype) {
+ case WNCK_WINDOW_NORMAL:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_NORMAL");
+ break;
+ case WNCK_WINDOW_DESKTOP:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_DESKTOP");
+ break;
+ case WNCK_WINDOW_DOCK:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
+ break;
+ case WNCK_WINDOW_DIALOG:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_DIALOG");
+ break;
+ case WNCK_WINDOW_MODAL_DIALOG:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_MODAL_DIALOG");
+ break;
+ case WNCK_WINDOW_TOOLBAR:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_TOOLBAR");
+ break;
+ case WNCK_WINDOW_MENU:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_MENU");
+ break;
+ case WNCK_WINDOW_UTILITY:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_UTILITY");
+ break;
+ case WNCK_WINDOW_SPLASHSCREEN:
+ atom = my_wnck_atom_get ("_NET_WM_WINDOW_TYPE_SPLASHSCREEN");
+ break;
+ default:
+ return;
+ }
+ my_wnck_error_trap_push ();
+
+ XChangeProperty (GDK_DISPLAY(), wnck_window_get_xid(window),
+ my_wnck_atom_get ("_NET_WM_WINDOW_TYPE"),
+ XA_ATOM, 32, PropModeReplace, (guchar *)&atom, 1);
+
+ my_wnck_error_trap_pop ();
+}
+#define wnck_window_set_window_type(a, b) my_wnck_window_set_window_type(a, b)
+#endif
+
+/**
+ * Set the window type of the current window.
+ *
+ * Accepted values are: normal, dialog, menu, toolbar, splashscreen, utility,
+ * dock, desktop.
+ */
+ESExpResult *func_wintype(ESExp *f, int argc, ESExpResult **argv, Context *c) {
+ const char *str;
+ WnckWindowType wintype;
+
+ if (argc != 1 || argv[0]->type == ESEXP_RES_STRING) {
+ g_printerr(_("wintype expects a single string argument\n"));
+ return e_sexp_result_new_bool (f, FALSE);
+ }
+
+ str = argv[0]->value.string;
+ if (g_ascii_strcasecmp (str, "normal") == 0)
+ wintype = WNCK_WINDOW_NORMAL;
+ else if (g_ascii_strcasecmp (str, "dialog") == 0)
+ wintype = WNCK_WINDOW_DIALOG;
+ else if (g_ascii_strcasecmp (str, "menu") == 0)
+ wintype = WNCK_WINDOW_MENU;
+ else if (g_ascii_strcasecmp (str, "toolbar") == 0)
+ wintype = WNCK_WINDOW_TOOLBAR;
+ else if (g_ascii_strcasecmp (str, "splashscreen") == 0)
+ wintype = WNCK_WINDOW_SPLASHSCREEN;
+ else if (g_ascii_strcasecmp (str, "utility") == 0)
+ wintype = WNCK_WINDOW_UTILITY;
+ else if (g_ascii_strcasecmp (str, "dock") == 0)
+ wintype = WNCK_WINDOW_DOCK;
+ else if (g_ascii_strcasecmp (str, "desktop") == 0)
+ wintype = WNCK_WINDOW_DESKTOP;
+ else {
+ g_printerr(_("Unknown window type '%s'"), str);
+ return e_sexp_result_new_bool (f, FALSE);
+ }
+
+ wnck_window_set_window_type (c->window, wintype);
+
+ if (debug) g_printerr(_("Set wintype\n"));
+ return e_sexp_result_new_bool (f, TRUE);
+}
View
48 src/actions.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005 Ross Burton <ross@burtonini.com>
+ *
+ * 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.
+ */
+
+#ifndef _ACTIONS_H
+#define _ACTIONS_H
+
+#include "e-sexp.h"
+
+ESExpResult *func_debug(ESExp *f, int argc, ESExpResult **argv, Context *c);
+
+ESExpResult *func_fullscreen(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_maximize(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_maximize_vertically(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_maximize_horizontally(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_minimize(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_shade(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_unshade(ESExp *f, int argc, ESExpResult **argv, Context *c);
+
+ESExpResult *func_pin(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_unpin(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_set_workspace(ESExp *f, int argc, ESExpResult **argv, Context *c);
+
+ESExpResult *func_skip_tasklist(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_skip_pager(ESExp *f, int argc, ESExpResult **argv, Context *c);
+
+ESExpResult *func_above(ESExp *f, int argc, ESExpResult **argv, Context *c);
+ESExpResult *func_below(ESExp *f, int argc, ESExpResult **argv, Context *c);
+
+ESExpResult *func_undecorate(ESExp *f, int argc, ESExpResult **argv, Context *c);
+
+ESExpResult *func_wintype(ESExp *f, int argc, ESExpResult **argv, Context *c);
+
+#endif /* _ACTIONS_H */
View
619 src/config-parser.c
@@ -1,619 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <glib-object.h>
-#include <glib/gi18n.h>
-#include "devilspie-matcher.h"
-#include "devilspie-action.h"
-#include "tristate-dummy.h"
-#include "flurb.h"
-
-extern GList *flurbs;
-
-/*
- * BIG TODO:
- * Use this GError thing we hear so much about... :)
- */
-
-typedef enum {
- STATE_START,
- STATE_DEVILSPIE,
- STATE_FLURB,
- STATE_MATCHERS,
- STATE_MATCHER,
- STATE_MATCHER_PROPERTY,
- STATE_ACTIONS,
- STATE_ACTION,
- STATE_ACTION_PROPERTY
-} ParseState;
-
-typedef struct {
- /* The current state of the parse */
- GSList *states;
- /* A list of flurbs defined */
- GList *flurbs;
- /* A Flurb being worked on */
- Flurb *flurb;
- /* The DevilsPie::Matcher being worked on */
- DevilsPieMatcher *matcher;
- /* The DevilsPie::Action being worked on */
- DevilsPieAction *action;
-} ParseInfo;
-
-static void set_error (GError **err,
- GMarkupParseContext *context,
- int error_domain,
- int error_code,
- const char *format,
- ...) G_GNUC_PRINTF (5, 6);
-
-static void push_state (ParseInfo *info,
- ParseState state);
-static void pop_state (ParseInfo *info);
-static ParseState peek_state (ParseInfo *info);
-
-static void start_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error);
-static void end_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error);
-static void text_handler (GMarkupParseContext *context,
- const gchar *text,
- gsize text_len,
- gpointer user_data,
- GError **error);
-
-static GMarkupParser devilspie_config_parser = {
- start_element_handler,
- end_element_handler,
- text_handler,
- NULL,
- NULL
-};
-
-/* Stolen from Metacity */
-static gboolean
-all_whitespace (const char *text, int text_len) {
- const char *p, *end;
- p = text;
- end = text + text_len;
- while (p != end) {
- if (!g_ascii_isspace (*p)) return FALSE;
- p = g_utf8_next_char (p);
- }
- return TRUE;
-}
-
-typedef struct
-{
- const char *name;
- const char **retloc;
-} LocateAttr;
-
-static gboolean
-locate_attributes (GMarkupParseContext *context,
- const char *element_name,
- const char **attribute_names,
- const char **attribute_values,
- GError **error,
- const char *first_attribute_name,
- const char **first_attribute_retloc,
- ...)
-{
- va_list args;
- const char *name;
- const char **retloc;
- int n_attrs;
-#define MAX_ATTRS 24
- LocateAttr attrs[MAX_ATTRS];
- gboolean retval;
- int i;
-
- g_return_val_if_fail (first_attribute_name != NULL, FALSE);
- g_return_val_if_fail (first_attribute_retloc != NULL, FALSE);
-
- retval = TRUE;
-
- n_attrs = 1;
- attrs[0].name = first_attribute_name;
- attrs[0].retloc = first_attribute_retloc;
- *first_attribute_retloc = NULL;
-
- va_start (args, first_attribute_retloc);
-
- name = va_arg (args, const char*);
- retloc = va_arg (args, const char**);
-
- while (name != NULL)
- {
- g_return_val_if_fail (retloc != NULL, FALSE);
-
- g_assert (n_attrs < MAX_ATTRS);
-
- attrs[n_attrs].name = name;
- attrs[n_attrs].retloc = retloc;
- n_attrs += 1;
- *retloc = NULL;
-
- name = va_arg (args, const char*);
- retloc = va_arg (args, const char**);
- }
-
- va_end (args);
-
- if (!retval)
- return retval;
-
- i = 0;
- while (attribute_names[i])
- {
- int j;
- gboolean found;
-
- found = FALSE;
- j = 0;
- while (j < n_attrs)
- {
- if (strcmp (attrs[j].name, attribute_names[i]) == 0)
- {
- retloc = attrs[j].retloc;
-
- if (*retloc != NULL)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Attribute \"%s\" repeated twice on the same <%s> element"),
- attrs[j].name, element_name);
- retval = FALSE;
- goto out;
- }
-
- *retloc = attribute_values[i];
- found = TRUE;
- }
-
- ++j;
- }
-
- if (!found)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Attribute \"%s\" is invalid on <%s> element in this context"),
- attribute_names[i], element_name);
- retval = FALSE;
- goto out;
- }
-
- ++i;
- }
-
- out:
- return retval;
-}
-
-static void
-set_error (GError **err, GMarkupParseContext *context, int error_domain,
- int error_code, const char *format, ...) {
- int line, ch;
- va_list args;
- char *str;
-
- g_markup_parse_context_get_position (context, &line, &ch);
-
- va_start (args, format);
- str = g_strdup_vprintf (format, args);
- va_end (args);
-
- g_set_error (err, error_domain, error_code,_("Line %d character %d: %s"),
- line, ch, str);
-
- g_free (str);
-}
-
-static void
-parse_info_init(ParseInfo *info) {
- info->states = g_slist_prepend (NULL, GINT_TO_POINTER (STATE_START));
- info->flurbs = NULL;
-}
-
-static void
-parse_info_free (ParseInfo *info) {
- g_slist_free (info->states);
- /* We don't free the contents of the list as ownership has been
- passed on */
- /* g_list_free (info->flurbs); */
-}
-
-static void
-push_state (ParseInfo *info, ParseState state) {
- info->states = g_slist_prepend (info->states, GINT_TO_POINTER (state));
-}
-
-static void
-pop_state (ParseInfo *info) {
- g_return_if_fail (info->states != NULL);
- info->states = g_slist_remove (info->states, info->states->data);
-}
-
-static ParseState
-peek_state (ParseInfo *info) {
- g_return_val_if_fail (info->states != NULL, STATE_START);
- return GPOINTER_TO_INT (info->states->data);
-}
-
-static void
-set_property_with_data(GObject *object, const char *property_name, const char *data)
-{
- GParamSpec *property_spec;
- GValue *value;
-
- property_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(object), property_name);
- if (property_spec == NULL) {
- g_warning("ignoring unknown property \"%s\"\n", property_name);
- return;
- }
- value = g_new0(GValue, 1);
- if (g_type_is_a(property_spec->value_type, G_TYPE_STRING)) {
- g_value_init (value, G_TYPE_STRING);
- g_value_set_string(value, data);
- g_object_set_property(object, property_name, value);
- } else if (g_type_is_a(property_spec->value_type, G_TYPE_INT)) {
- int i;
- g_value_init (value, G_TYPE_INT);
- i = strtol(data, (char**)NULL, 10); /* if I put 0 is it clever? */
- g_value_set_int(value, i);
- g_object_set_property(object, property_name, value);
- } else if (g_type_is_a(property_spec->value_type, G_TYPE_DOUBLE)) {
- double d;
- g_value_init (value, G_TYPE_DOUBLE);
- d = strtod(data, (char**)NULL);
- g_value_set_double(value, d);
- g_object_set_property(object, property_name, value);
- } else if (g_type_is_a(property_spec->value_type, G_TYPE_BOOLEAN)) {
- /*
- * TODO: decide whether we want a 0/1 representation of boolean,
- * or a 'true'/'false' representation.
- */
- int i;
- g_value_init (value, G_TYPE_BOOLEAN);
- i = strtol(data, (char**)NULL, 10); /* if I put 0 is it clever? */
- g_value_set_boolean(value, (gboolean)i);
- g_object_set_property(object, property_name, value);
- } else if (g_type_is_a(property_spec->value_type, DEVILSPIE_TYPE_TRISTATE)) {
- DevilsPieTriState tri;
- g_value_init (value, DEVILSPIE_TYPE_TRISTATE);
- if (!strcmp(data, "TRUE")) {
- tri = TRI_TRUE;
- } else if (!strcmp(data, "FALSE")) {
- tri = TRI_FALSE;
- } else {
- tri = TRI_UNSET;
- }
- g_value_set_enum(value, tri);
- g_object_set_property(object, property_name, value);
- } else {
- g_assert_not_reached();
- }
- g_free(value);
-}
-
-static void
-parse_property (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- ParseInfo *info,
- GError **error)
-{
- const char *name;
- const char *value;
-
- if (!locate_attributes (context, element_name,
- attribute_names, attribute_values, error,
- "name", &name,
- "value", &value,
- NULL)) return;
- if (name == NULL) {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"name\" attribute on element <%s>"), element_name);
- return;
- }
- if (value == NULL) {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"value\" attribute on element <%s>"), element_name);
- return;
- }
- switch (peek_state(info)) {
- case STATE_MATCHER_PROPERTY:
- set_property_with_data (G_OBJECT (info->matcher), name, value);
- break;
- case STATE_ACTION_PROPERTY:
- set_property_with_data (G_OBJECT (info->action), name, value);
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-static DevilsPieMatcher*
-create_matcher (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- ParseInfo *info,
- GError **error)
-{
- const char *type_name;
- GType matcher_type;
- DevilsPieMatcher *matcher;
-
- if (!locate_attributes (context, element_name,
- attribute_names, attribute_values, error,
- "name", &type_name,
- NULL)) return NULL;
-
- if (type_name == NULL) {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"name\" attribute on element <%s>"), element_name);
- return NULL;
- }
-
- matcher_type = g_type_from_name (type_name);
- if (!g_type_is_a(matcher_type, devilspie_matcher_get_type())) {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Requested type %s is not a known Matcher"), type_name);
- return NULL;
- }
-
- matcher = g_object_new (matcher_type, NULL);
- return matcher;
-}
-
-static DevilsPieAction*
-create_action (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- ParseInfo *info,
- GError **error)
-{
- const char *type_name;
- GType action_type;
- DevilsPieAction *action;
-
- if (!locate_attributes (context, element_name,
- attribute_names, attribute_values, error,
- "name", &type_name,
- NULL)) {
- if (!error)
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Could not parse attributes of <%s>"), element_name);
- return NULL;
- }
-
- if (type_name == NULL) {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"name\" attribute on element <%s>"), element_name);
- return NULL;
- }
-
- action_type = g_type_from_name (type_name);
- if (!g_type_is_a(action_type, devilspie_action_get_type())) {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Requested type %s is not a known Action"), type_name);
- return NULL;
- }
-
- action = g_object_new (action_type, NULL);
- return action;
-}
-
-static void
-start_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error)
-{
- ParseInfo *info;
- info = (ParseInfo*)user_data;
-
- switch (peek_state(info)) {
- case STATE_START:
- if (strcmp (element_name, "devilspie") == 0) {
- push_state(info, STATE_DEVILSPIE);
- } else {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Outermost element in config files must be <devilspie> not <%s>"),
- element_name);
- }
- break;
- case STATE_DEVILSPIE:
- if (strcmp (element_name, "flurb") == 0) {
- const char* name;
- push_state(info, STATE_FLURB);
- if (!locate_attributes (context, element_name,
- attribute_names, attribute_values, error,
- "name", &name, NULL)) return;
- info->flurb = g_new0 (Flurb, 1);
- info->flurb->name = g_strdup(name);
- info->flurbs = g_list_append(info->flurbs, info->flurb);
- } else {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Only <flurb> elements are allowed inside <devilspie> not <%s>"),
- element_name);
- }
- break;
- case STATE_FLURB:
- if (strcmp (element_name, "matchers") == 0) {
- push_state(info, STATE_MATCHERS);
- } else if (strcmp (element_name, "actions") == 0) {
- push_state(info, STATE_ACTIONS);
- } else {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Only <matchers> and <actions> elements are allowed inside <blurb> not <%s>"),
- element_name);
- }
- break;
- case STATE_MATCHERS:
- if (strcmp (element_name, "matcher") == 0) {
- push_state(info, STATE_MATCHER);
- info->matcher = create_matcher (context, element_name, attribute_names,
- attribute_values, info, error);
- } else {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Only <matcher> elements are allowed inside <matchers> not <%s>"),
- element_name);
- }
- break;
- case STATE_MATCHER:
- if (strcmp (element_name, "property") == 0) {
- push_state(info, STATE_MATCHER_PROPERTY);
- parse_property (context, element_name, attribute_names,
- attribute_values, info, error);
- } else {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Only <property> elements are allowed inside <matcher> not <%s>"),
- element_name);
- }
- break;
- case STATE_MATCHER_PROPERTY: