[sawfish] added debian packaging scripts based on the official ones



commit 4c1aa73f9e1662ae7f76d2abb12b1eb272d5f416
Author: Christopher Roy Bratusek <chris nanolx org>
Date:   Sat Oct 24 23:26:43 2009 +0200

    added debian packaging scripts based on the official ones

 ChangeLog                          |    2 +
 configure.in                       |    4 +
 debian/README.Debian               |   45 ++
 debian/README.sawfish-data         |    5 +
 debian/README.source               |   57 ++
 debian/README.themes               |    1 +
 debian/changelog.in                |    5 +
 debian/clean                       |   15 +
 debian/compat                      |    1 +
 debian/control                     |   65 +++
 debian/copyright                   |   44 ++
 debian/postinst                    |   18 +
 debian/postrm                      |   10 +
 debian/preinst                     |    9 +
 debian/prerm                       |   11 +
 debian/rules                       |  163 ++++++
 debian/sawfish-data.info           |    1 +
 debian/sawfish-data.install.in     |    8 +
 debian/sawfish-dbg.links           |    1 +
 debian/sawfish-lisp-source.links   |    1 +
 debian/sawfish-lisp-source.lintian |    1 +
 debian/sawfish.dirs                |    5 +
 debian/sawfish.el                  | 1003 ++++++++++++++++++++++++++++++++++++
 debian/sawfish.emacsen-install     |   41 ++
 debian/sawfish.emacsen-remove      |   15 +
 debian/sawfish.emacsen-startup     |   11 +
 debian/sawfish.install             |    9 +
 debian/sawfish.links               |    1 +
 debian/watch                       |    3 +
 src/display.c                      |   20 +-
 30 files changed, 1572 insertions(+), 3 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0eb0f30..a8d5874 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,8 @@
 	* scripts/Makefile.in
 	* scripts/sawfish-about.jl.in: switched from custom about-dialog to GtkAboutDialog
 
+	* debian/*: added debian packaging scripts based on the official ones
+
 2009-10-24  Teika kazura <teika lavabit com>
 	* lisp/sawfish/wm/user.jl
 	* man/news.texi: minor news & comment fix.
diff --git a/configure.in b/configure.in
index 7376a9d..3d4f55a 100644
--- a/configure.in
+++ b/configure.in
@@ -338,8 +338,11 @@ if test "x$KDEDIR" = x; then
 	KDEDIR="/usr/share/apps/"
 fi
 
+gitdate=`date +%y%m%d`
+
 dnl Nonstandard exported symbols
 AC_SUBST(version)
+AC_SUBST(gitdate)
 AC_SUBST(subversion)
 AC_SUBST(sawfishdir)
 AC_SUBST(sawfishexecdir)
@@ -403,6 +406,7 @@ scripts/Makefile
 sounds/Makefile
 src/Makefile
 themes/Makefile
+debian/changelog
 ])
 
 AC_OUTPUT
diff --git a/debian/README.Debian b/debian/README.Debian
new file mode 100644
index 0000000..7e813be
--- /dev/null
+++ b/debian/README.Debian
@@ -0,0 +1,45 @@
+Sawfish for Debian
+------------------
+
+The sawfish package includes sawfish.el, written by Dave Pearson
+<davep davep org>, which is normally distributed from his web site
+http://www.davep.org/sawfish/
+
+For each upstream release you need to restart sawfish with :
+
+sawfish-client -f restart
+
+I'll close all bugs report related to this feature.
+
+Also if you have this error:
+
+$ sawfish-ui 
+error--> (file-error "No such file or directory" "gui/gtk")
+
+This is because you have mixed up Ximian packages and Debian packages.
+You need to replace all Ximian packages related to sawfish by the Debian
+packages (rep, rep-gtk, librep9).
+
+Why this doesn't work ?
+
+Because Ximian doesn't follow the Debian policy (Chapter 12.1) :
+
+     If a program needs to specify an _architecture specification string_
+     in some place, the following format should be used:
+
+                    <arch>-<os>
+
+     where <arch>' is one of the following: i386, alpha, arm, m68k,
+     powerpc, sparc and <os>' is one of: linux, gnu.  Use of _gnu_ in this
+     string is reserved for the GNU/Hurd operating system.
+
+I'll close all bugs report related to this feature too.
+
+Since GNOME 2 use AA (Anti Aliased) fonts, you should remove/disable usage
+of libgdkxft0.
+
+If rep take 100% CPU when you try to access to custom popup menu (with
+middle mouse click on the root window), you should install the
+gnome-control-center package or forget to access this menu entry.
+
+Christian
diff --git a/debian/README.sawfish-data b/debian/README.sawfish-data
new file mode 100644
index 0000000..71f40fa
--- /dev/null
+++ b/debian/README.sawfish-data
@@ -0,0 +1,5 @@
+This package contains the architecture independent data for sawfish,
+that is the compiled lisp files and the translations. It is unlikely
+to be of any use if you don't have sawfish installed.
+
+If you want to see the lisp code, install sawfish-lisp-source.
diff --git a/debian/README.source b/debian/README.source
new file mode 100644
index 0000000..8646078
--- /dev/null
+++ b/debian/README.source
@@ -0,0 +1,57 @@
+This package uses quilt to manage all modifications to the upstream
+source.  Changes are stored in the source package as diffs in
+debian/patches and applied during the build.
+
+To configure quilt to use debian/patches instead of patches, you want
+either to export QUILT_PATCHES=debian/patches in your environment
+or use this snippet in your ~/.quiltrc:
+
+    for where in ./ ../ ../../ ../../../ ../../../../ ../../../../../; do
+        if [ -e ${where}debian/rules -a -d ${where}debian/patches ]; then
+                export QUILT_PATCHES=debian/patches
+        fi
+    done
+
+To get the fully patched source after unpacking the source package, cd to
+the root level of the source package and run:
+
+    quilt push -a
+
+The last patch listed in debian/patches/series will become the current
+patch.
+
+To add a new set of changes, first run quilt push -a, and then run:
+
+    quilt new <patch>
+
+where <patch> is a descriptive name for the patch, used as the filename in
+debian/patches.  Then, for every file that will be modified by this patch,
+run:
+
+    quilt add <file>
+
+before editing those files.  You must tell quilt with quilt add what files
+will be part of the patch before making changes or quilt will not work
+properly.  After editing the files, run:
+
+    quilt refresh
+
+to save the results as a patch.
+
+Alternately, if you already have an external patch and you just want to
+add it to the build system, run quilt push -a and then:
+
+    quilt import -P <patch> /path/to/patch
+    quilt push -a
+
+(add -p 0 to quilt import if needed). <patch> as above is the filename to
+use in debian/patches.  The last quilt push -a will apply the patch to
+make sure it works properly.
+
+To remove an existing patch from the list of patches that will be applied,
+run:
+
+    quilt delete <patch>
+
+You may need to run quilt pop -a to unapply patches first before running
+this command.
diff --git a/debian/README.themes b/debian/README.themes
new file mode 100644
index 0000000..bd5603c
--- /dev/null
+++ b/debian/README.themes
@@ -0,0 +1 @@
+This directory is the central location for Sawfish themes.
\ No newline at end of file
diff --git a/debian/changelog.in b/debian/changelog.in
new file mode 100644
index 0000000..41d41b7
--- /dev/null
+++ b/debian/changelog.in
@@ -0,0 +1,5 @@
+sawfish (1:@version ~@gitdate -1nano) unstable; urgency=low
+
+  * New upstream GIT
+
+ -- Christopher Roy Bratusek <zanghar freenet de>  Sat, 24 Oct 2009 22:55:17 +0200
diff --git a/debian/clean b/debian/clean
new file mode 100644
index 0000000..88f7a54
--- /dev/null
+++ b/debian/clean
@@ -0,0 +1,15 @@
+configure
+aclocal.m4
+libtool
+config.guess
+config.sub
+po/messages
+po/*mo
+po/Makefile
+themes/*.tar.gz
+lisp/sawfish/gtk/widgets/font.jl
+debian/sawfish-lisp-source.install
+debian/sawfish-data.install
+DOC
+FAQ
+USERDOC
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..b3f7770
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,65 @@
+Source: sawfish
+Section: x11
+Build-Conflicts: autoconf2.13, automake1.4
+Priority: optional
+Maintainer: Christopher Roy Bratusek <zanghar freenet de>
+Standards-Version: 3.8.3
+Build-Depends: gettext (>= 0.10.37), debhelper (>= 7.0.0), libxinerama-dev,
+ rep-gtk (>= 1:0.90.0), libgmp3-dev (>= 4.1.4-8),
+ texinfo (<< 4.11) | texinfo (>= 4.11.dfsg.1-3), 
+ libgtk2.0-dev (>= 2.12), libxrender-dev, libxext-dev,
+ autotools-dev, automake1.10, quilt (>=0.40), librep-dev (>= 0.90.1),
+ rep, libtool
+Homepage: http://sawfish.wikia.com/
+
+Package: sawfish
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, librep9 (>=0.90.0), rep,
+ rep-gtk (>= 0.18.4), gnome-terminal | x-terminal-emulator,
+ sawfish-data (= ${source:Version})
+Suggests: menu, gnome-control-center, yelp
+Provides: x-window-manager
+Replaces: sawfish-lisp-source (<= 0.38-6), sawfish2
+Conflicts: sawfish2, sawfish-themer, menu (<< 2.1.14)
+Description: a window manager for X11
+ Sawfish is an extensible window manager using an Emacs Lisp-like scripting
+ language. All window decorations are configurable, the basic idea is to
+ have as much user-interface policy as possible controlled through the Lisp
+ language.
+
+Package: sawfish-dbg
+Architecture: any
+Depends: ${misc:Depends}, sawfish (= ${binary:Version}),
+ sawfish-data (= ${source:Version})
+Recommends: sawfish-lisp-source
+Section: debug
+Priority: extra
+Description: sawfish debugging symbols
+ This package contains the debugging symbols from the sawfish window manager.
+ It is not needed for normal operation of the package.
+ .
+ Install it if you need to debug problems in sawfish. You will also almost
+ certainly need sawfish-lisp-source in that case.
+
+Package: sawfish-data
+Architecture: all
+Depends: ${misc:Depends}
+Replaces: sawfish (<< 1:1.5.0-1)
+Conflicts: sawfish (<= 1:1.3+cvs20060518-2)
+Description: sawfish architecture independent data
+ This package contains the architecture independent lisp compiled files
+ and other data, such as theme pixmaps. It is unlikely to be of any
+ use without the sawfish window manager.
+ .
+ The lisp source files are in the sawfish-lisp-source package.
+
+Package: sawfish-lisp-source
+Architecture: all
+Depends: ${misc:Depends}, sawfish-data (= ${source:Version})
+Recommends: sawfish
+Description: sawfish lisp files
+ This package contains the lisp source files in case you want to modify,
+ study or debug the behaviour of the window manager.
+ .
+ It is not required for normal use of sawfish and not installing it will save
+ space in small systems.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..ca60345
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,44 @@
+This package was debianized by Mikolaj J. Habryn <dichro rcpt to> on
+Tue, 19 Oct 1999 16:12:32 +1000.
+
+It was downloaded from
+https://sourceforge.net/project/showfiles.php?group_id=32&package_id=17
+
+Upstream Author: John Harper <jsh unfactored org> and the sawfish community.
+
+Copyright (C) 1997-1998 Stuart Parmenter and Elliot Lee
+Copyright (C) 1999 Ryan Lovett <ryan ocf berkeley edu>
+Copyright (C) 1999-2002 John Harper
+Copyright (C) 2000 Topi Paavola <tjp iki fi>
+Copyright (C) 2000 Unai Uribarri <unaiur telecable es>
+Copyright (C) 2000-2001 Kai Grossjohann <Kai Grossjohann CS Uni-Dortmund DE>
+Copyright (C) 2001 Eazel, Inc
+Copyright (C) 2002 mx & ta
+
+License:
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+On Debian systems, the complete text of the GNU General Public License
+version 2 can be found in /usr/share/common-licenses/GPL-2 file.
+
+The Debian package itself is
+
+Copyright (C) 1999-2000 Mikolaj J. Habryn
+Copyright (C) 2000 Ian McKellar
+Copyright (C) 2000-2006 Christian Marillat
+Copyright (C) 2006-2009 Rodrigo Gallardo
+
+And is distributed under the same terms as sawfish.
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..e69de29
diff --git a/debian/postinst b/debian/postinst
new file mode 100644
index 0000000..bb3bc2e
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,18 @@
+#!/bin/sh -e
+
+if [ "$1" = "configure" ]; then
+
+# Touch all jlc files
+  find /usr/share/sawfish/*/lisp -name *.jlc | xargs touch
+
+# Because dh_installwm don't install a slave manpage
+  update-alternatives --install /usr/bin/x-window-manager \
+  x-window-manager /usr/bin/sawfish 70 \
+  --slave /usr/share/man/man1/x-window-manager.1.gz \
+  x-window-manager.1.gz /usr/share/man/man1/sawfish.1.gz
+
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/postrm b/debian/postrm
new file mode 100644
index 0000000..e7d75b8
--- /dev/null
+++ b/debian/postrm
@@ -0,0 +1,10 @@
+#! /bin/sh -e
+
+if [ "$1" = purge ]; then
+    rm -rf /etc/X11/sawfish 2>/dev/null || true
+    rm -rf /var/lib/sawfish 2>/dev/null || true
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/preinst b/debian/preinst
new file mode 100644
index 0000000..8174461
--- /dev/null
+++ b/debian/preinst
@@ -0,0 +1,9 @@
+#! /bin/sh -e
+
+if [ -d /var/lib/sawfish ]; then
+    rm -rf /var/lib/sawfish 2>/dev/null || true
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/prerm b/debian/prerm
new file mode 100644
index 0000000..1521d1f
--- /dev/null
+++ b/debian/prerm
@@ -0,0 +1,11 @@
+#!/bin/sh -e
+
+if [ "$1" = "remove" ]; then
+
+# Because dh_installwm don't remove a slave manpage
+  update-alternatives --remove x-window-manager /usr/bin/sawfish
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..b4e642e
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,163 @@
+#!/usr/bin/make -f
+
+export DH_VERBOSE=1
+
+include /usr/share/quilt/quilt.make
+
+version = $(shell sed -n 's/version="\(.*\)"/\1/p' configure.in | head -n 1)
+
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
+  confflags += --build $(DEB_HOST_GNU_TYPE)
+else
+  confflags += --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
+endif
+
+CFLAGS += -Wall -g -fno-strict-aliasing
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+	CFLAGS += -O0
+else
+	CFLAGS += -O2
+endif
+
+LC_ALL=
+LINGUAS=
+LANG=
+export LC_ALL LINGUAS LANG
+
+configure: configure-stamp
+configure-stamp: $(QUILT_STAMPFN)
+	dh_testdir
+
+	cp /usr/share/misc/config.guess .
+	cp /usr/share/misc/config.sub .
+
+	aclocal-1.10
+	autoconf
+
+	CFLAGS="$(CFLAGS)" ./configure --prefix=/usr --with-readline \
+	--libexecdir=/usr/lib $(confflags)
+
+# Get rid of rpath
+	set -e; \
+	 tmpfile=`mktemp`; \
+	 sed "s/^REP_LIBS=\(.*\)-Wl,--rpath -Wl,[^ ]* \(.*\)$$/REP_LIBS=\1 \2/" Makedefs >$$tmpfile ;\
+	 mv $$tmpfile Makedefs
+
+	touch configure-stamp
+
+build: build-stamp
+build-stamp: configure-stamp
+
+	$(MAKE)
+
+	touch build-stamp
+
+clean:
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp configure-stamp
+
+	[ ! -f Makefile ] || $(MAKE) distclean
+
+	rm -rf src/.libexec
+	rm -rf src/.libs
+	rm -rf autom4te.cache/
+
+	dh_clean
+	$(MAKE) -f debian/rules unpatch
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_installdirs
+
+	$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
+
+# Fixup libdir in .la files
+	find debian/tmp -name \*.la | while read file; do \
+	  libdir=`echo $$file | sed -e 's debian/tmp\(.*\)/[^/]*la$$ \1@' `; \
+	  tmpfile=`mktemp`; \
+	  sed "s ^libdir= *@libdir='$$libdir'@" $$file >$$tmpfile; \
+	  mv $$tmpfile $$file; \
+	done
+
+# Remove info files installed by Makefile. dh_installinfo will do it again without creating info.dir
+	find debian -type d -name info | xargs rm -rf
+
+	[ ! -f debian/sawfish-lisp-source.install ] || rm debian/sawfish-lisp-source.install
+	find debian/tmp/usr/share/sawfish/*/lisp -name \*.jl | \
+	 cut -d/ -f3- | grep -v 'autoload\|custom-defaults' > debian/sawfish-lisp-source.install
+
+	cp debian/sawfish-data.install.in debian/sawfish-data.install
+	find debian/tmp/usr/share/sawfish/*/lisp -name \*.jlc | \
+	 cut -d/ -f3- | grep -v 'main' >> debian/sawfish-data.install
+
+	dh_install --fail-missing
+
+# These are scripts. (Actually, they are /usr/bin/sawfish-config before and after compiling)
+# Should that be a symlink?
+	chmod a+x debian/sawfish/usr/share/sawfish/$(version)/lisp/sawfish/cfg/main.jlc
+	chmod a+x debian/sawfish-lisp-source/usr/share/sawfish/$(version)/lisp/sawfish/cfg/main.jl
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+	dh_testdir -i
+	dh_testroot -i
+	dh_installdocs -psawfish-data FAQ NEWS README TODO OPTIONS KEYBINDINGS USERDOC
+	dh_installinfo -psawfish-data
+	dh_installexamples -psawfish-data
+	dh_installmenu -psawfish-data
+	dh_installchangelogs -psawfish-data
+	dh_link -i
+	dh_compress -i
+	dh_fixperms -i
+	dh_installdeb -i
+	dh_gencontrol -i
+	dh_md5sums -i
+	dh_builddeb -i
+
+# Build architecture-dependent files here.
+binary-arch: build install
+	dh_testdir
+	dh_testroot
+	dh_installmenu -a
+	dh_installman -a
+	dh_installemacsen -a -psawfish
+	dh_link -a
+	dh_strip -a --dbg-package=sawfish-dbg
+	dh_compress -a
+	dh_fixperms -a
+	dh_installdeb -a
+	dh_shlibdeps -a
+	dh_gencontrol -a
+	dh_md5sums -a
+	dh_builddeb -a
+
+binary: binary-indep binary-arch
+
+# Obtain upstream source snapshot from svn. Leaves it in
+# debian/sawfish_$version.orig.tar.gz
+# By default will get the latest version available, but can be controlled
+# by setting SVN_REV before calling make
+
+SVN_REPO ?= svn://svn.gnome.org/svn/sawfish/trunk
+SVN_REV  ?= $(shell LANG=C svn info $(SVN_REPO) | grep Revision: | cut -d: -f 2 | sed 's/^ *\([^ ]*\) *$$/\1/')
+export_dir = debian/tmp-src
+
+source:
+	dh_testdir
+	mkdir -p $(export_dir)
+	svn export -q -r $(SVN_REV) $(SVN_REPO) $(export_dir)/sawfish
+# remove unneeded files
+	cd $(export_dir)/sawfish; \
+	 find . -name .cvsignore | xargs rm
+	cd $(export_dir); \
+	  tar czf ../sawfish_$$(sed -n 's/version="\(.*\)"/\1/p' sawfish/configure.in | head -n 1)+svn$(SVN_REV).orig.tar.gz sawfish
+	-rm -rf $(export_dir)
+
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/debian/sawfish-data.info b/debian/sawfish-data.info
new file mode 100644
index 0000000..d94b8dd
--- /dev/null
+++ b/debian/sawfish-data.info
@@ -0,0 +1 @@
+man/sawfish.info*
diff --git a/debian/sawfish-data.install.in b/debian/sawfish-data.install.in
new file mode 100644
index 0000000..6765d4e
--- /dev/null
+++ b/debian/sawfish-data.install.in
@@ -0,0 +1,8 @@
+debian/README.themes usr/share/sawfish/themes
+usr/share/locale
+usr/share/sawfish/*/lisp/sawfish/wm/autoload.jl
+usr/share/sawfish/*/lisp/sawfish/wm/custom-defaults.jl
+usr/share/sawfish/*/monitor.png
+usr/share/sawfish/*/sounds
+usr/share/sawfish/*/themes
+usr/share/man/man1/sawfish*.gz
diff --git a/debian/sawfish-dbg.links b/debian/sawfish-dbg.links
new file mode 100644
index 0000000..bb74d90
--- /dev/null
+++ b/debian/sawfish-dbg.links
@@ -0,0 +1 @@
+usr/share/doc/sawfish-data usr/share/doc/sawfish-dbg
diff --git a/debian/sawfish-lisp-source.links b/debian/sawfish-lisp-source.links
new file mode 100644
index 0000000..b0f7bc0
--- /dev/null
+++ b/debian/sawfish-lisp-source.links
@@ -0,0 +1 @@
+usr/share/doc/sawfish-data usr/share/doc/sawfish-lisp-source
diff --git a/debian/sawfish-lisp-source.lintian b/debian/sawfish-lisp-source.lintian
new file mode 100644
index 0000000..f9370bc
--- /dev/null
+++ b/debian/sawfish-lisp-source.lintian
@@ -0,0 +1 @@
+sawfish-lisp-source: script-not-executable ./usr/share/sawfish/1.3/lisp/sawfish/ui/main.jl
diff --git a/debian/sawfish.dirs b/debian/sawfish.dirs
new file mode 100644
index 0000000..44adb57
--- /dev/null
+++ b/debian/sawfish.dirs
@@ -0,0 +1,5 @@
+etc/emacs/site-start.d
+usr/share/emacs/site-lisp/sawfish
+usr/share/gnome/wm-properties
+usr/share/xsessions
+var/lib/sawfish
diff --git a/debian/sawfish.el b/debian/sawfish.el
new file mode 100644
index 0000000..f1fdc85
--- /dev/null
+++ b/debian/sawfish.el
@@ -0,0 +1,1003 @@
+;;; sawfish.el --- Sawfish mode.
+;; Copyright 1999,2000,2001,2002,2003,2004 by Dave Pearson <davep davep org>
+;; $Revision: 1.32 $
+
+;; sawfish.el is free software distributed under the terms of the GNU
+;; General Public Licence, version 2. For details see the file COPYING.
+
+;;; Commentary:
+;;
+;; sawfish.el is an emacs mode for writing code for the sawfish window
+;; manager <URL:http://sawmill.sourceforge.net/>. As well as providing a
+;; programming mode it also allows for direct interaction with the running
+;; window manager.
+;;
+;; The latest sawfish.el is always available from:
+;;
+;;   <URL:http://www.davep.org/emacs/#sawfish.el>
+
+;;; THANKS:
+;;
+;; John Harper <john dcs warwick ac uk> for help regarding sawfish and rep.
+;;
+;; Stefan Monnier for finding the font-lock (or lack of) with derived modes
+;; problem and providing a fix for GNU Emacs.
+;;
+;; Jan Vroonhof for his invaluable pointers regarding XEmacs.
+;;
+;; Hubert Selhofer for the code to syntax highlight "#||#" comments, for the
+;; GNU emacs font-lock code to provide support for various rep and sawfish
+;; "keywords" and for the GNU emacs emacs-lisp menu removal kludge.
+;;
+;; Kai Grossjohann for his enhancments to `sawfish-console'.
+;;
+;; Markus Holmberg for the code that improves integration with info.
+
+;;; BUGS:
+;;
+;; o The handling of the apropos buffer totally breaks down under XEmacs.
+;;
+;; o sawfish.el needs a total rewrite. When I started this mode rep (the
+;;   lisp that sawfish is based around) was an elisp-a-like. Since then it
+;;   has turned into a scheme-a-like that happens to retain some
+;;   elisp-a-like bits. Ideally a new sawfish.el would be written in terms
+;;   of a librep.el which would be a ground-up-rewritten mode for dealing
+;;   with rep.
+
+;;; INSTALLATION:
+;;
+;; o Drop sawfish.el somwehere into your `load-path'. Try your site-lisp
+;;   directory for example (you might also want to byte-compile the file).
+;;
+;; o Add autoloads for the various sawfish functions to ~/.emacs. At the
+;;   very least you want to do something like:
+;;
+;;   (autoload 'sawfish-mode "sawfish" "sawfish-mode" t)
+;;
+;; o Add the following to ~/.emacs to ensure that sawfish mode is used when
+;;   you go to edit sawfish code:
+;;
+;;   (setq auto-mode-alist (cons '("\\.sawfishrc$"  . sawfish-mode) auto-mode-alist)
+;;         auto-mode-alist (cons '("\\.jl$"         . sawfish-mode) auto-mode-alist)
+;;         auto-mode-alist (cons '("\\.sawfish/rc$" . sawfish-mode) auto-mode-alist))
+
+;;; Code:
+
+;; Things we need:
+(eval-when-compile
+  (require 'cl)
+  (require 'info))
+(require 'thingatpt)
+(require 'font-lock)
+(require 'regexp-opt)
+(require 'pp)
+(require 'easymenu)
+(require 'inf-lisp)
+
+;; Shut the compiler up.
+(eval-when-compile
+
+  ;; Keep everyone quiet.
+  (defvar sawfish-mode-map)
+  (defvar sawfish-mode-menu)
+  
+  ;; Things to keep XEmacs quiet.
+  (unless (boundp 'font-lock-defaults-alist)
+    (defvar font-lock-defaults-alist))
+  
+  ;; Things to keep GNU Emacs quiet.
+  (unless (boundp 'delete-menu-item)
+    (defun delete-menu-item (path)
+      nil)))
+
+;; Attempt to handle older/other emacs.
+(eval-and-compile
+  ;; If customize isn't available just use defvar instead.
+  (unless (fboundp 'defgroup)
+    (defmacro defgroup  (&rest rest) nil)
+    (defmacro defcustom (symbol init docstring &rest rest)
+      `(defvar ,symbol ,init ,docstring))))
+
+;; Customize options.
+
+(defgroup sawfish nil
+  "Mode for editing the configuration of and interacting with the sawfish
+window manager."
+  :group 'languages
+  :prefix "sawfish-")
+
+(defcustom sawfish-client "sawfish-client"
+  "*Command for interacting with the window manager."
+  :type  'string
+  :group 'sawfish)
+
+(defcustom sawfish-exec-parameter "-e"
+  "*Parameter for `sawfish-client' that tells it to eval a form and exit."
+  :type  'string
+  :group 'sawfish)
+
+(defcustom sawfish-interactive-parameter "-"
+  "*Interactive mode parameter for `sawfish-client'."
+  :type  'string
+  :group 'sawfish)
+
+(defcustom sawfish-result-buffer "*sawfish*"
+  "*Name of the long result display buffer."
+  :type  'string
+  :group 'sawfish)
+
+(defcustom sawfish-help-buffer "*sawfish-help*"
+  "*Name of the sawfish help buffer."
+  :type  'string
+  :group 'sawfish)
+
+(defcustom sawfish-apropos-buffer "*sawfish-apropos*"
+  "*Name of the sawfish apropos buffer."
+  :type  'string
+  :group 'sawfish)
+
+(defcustom sawfish-scratch-buffer "*sawfish-scratch*"
+  "*Name of the sawfish scratch buffer."
+  :type  'string
+  :group 'sawfish)
+
+(defcustom sawfish-buffer-symbol-lists t
+  "*Buffer the lists of function and variable names?"
+  :type  'boolean
+  :group 'sawfish)
+
+(defcustom sawfish-apropos-searches-info-files t
+  "*Search info files for apropos \"one-liner\" help?
+
+This variable controls the action of the sawfish apropos functions. When nil
+the apropos functions won't go looking in the sawfish info files for a
+one-line doc-string to display in the apropos buffer if the symbol doesn't
+have a doc-string. This will make apropos calls a lot faster."
+  :type  'boolean
+  :group 'sawfish)
+
+(defcustom sawfish-mode-hook nil
+  "*List of hooks to execute on entry to sawfish-mode."
+  :type  'hook
+  :group 'sawfish)
+
+(defcustom sawfish-info-files '(("sawfish" "Function Index" "Variable Index")
+                                ("librep"  "Function Index" "Variable Index"))
+  "*List of info files to search when looking for info documentation.
+
+This is a list of lists. Each entry in the list is of the format:
+
+  (INFO-FILE FUNCTION-INDEX VARIABLE-INDEX)"
+  :type  '(repeat (list    :tag "Info file information"
+                   (string :tag "Info file name")
+                   (string :tag "Function index name")
+                   (string :tag "Variable index name")))
+  :group 'sawfish)
+
+(defcustom sawfish-comint-prompt "^sawfish% "
+  "*Regular expression for matching the sawfish-client prompt."
+  :type  'regexp
+  :group 'sawfish)
+
+(defcustom sawfish-extra-keyword-list
+  '("add-frame-style" "call-after-load" "call-after-property-changed" 
+    "call-after-state-changed" "custom-set-property")
+  "List of extra keywords for Sawfish used in highlighting.
+Highlight these expressions with `font-lock-keyword-face'."
+  :group 'sawfish
+  :type '(repeat (string :tag "Keyword: ")))
+
+(defcustom sawfish-warning-keyword-list 
+  '("fixme" "FIXME" "Fixme" "fix me" "Fix me" "!!!" "Grrr" "Bummer")
+  "List of keywords for Sawfish used in highlighting.
+Highlight these expressions with `font-lock-warning-face' even if
+already fontified."
+  :group 'sawfish
+  :type '(repeat (string :tag "Keyword: ")))
+
+;; Non customising variables.
+
+(defvar sawfish-function-list nil
+  "List of sawfish functions.")
+
+(defvar sawfish-variable-list nil
+  "List of sawfish variables.")
+
+(defvar sawfish-function-p '(lambda (s)
+                             (and
+                              (boundp s)
+                              (or
+                               (functionp (symbol-value s))
+                               (macrop (symbol-value s))
+                               (special-form-p (symbol-value s)))))
+  "Closure to pass to sawfish-client for testing if a symbol is a function.")
+
+(defvar sawfish-variable-p `(lambda (s)
+                             (and (boundp s)
+                              (not (,sawfish-function-p s))))
+  "Closure to pass to sawfish-client for testing if a symbol is a variable.")
+
+(defvar sawfish-read-expression-map nil
+  "Minibuffer keymap used for reading sawfish lisp expressions.")
+
+(defvar sawfish-interaction-mode-map nil
+  "Keymap for use with `sawfish-interaction'.")
+
+(defvar sawfish-read-expression-history nil
+  "History list for `sawfish-eval-expression'.")
+
+(defvar sawfish-describe-symbol
+  '(lambda (s)
+    (if (boundp s)
+        (cond ((special-form-p      (symbol-value s)) "Special form")
+              ((macrop              (symbol-value s)) "Macro")
+              ((subrp               (symbol-value s)) "Built-in function")
+              ((commandp            (symbol-value s)) "Command")
+              ((functionp           (symbol-value s)) "Function")
+              ((binding-immutable-p               s ) "Constant")
+              (t                                      "Variable"))
+      "Symbol"))
+  "Closure to pass to sawfish-client that will describe a symbol's binding.")
+
+;; Constants.
+
+(defconst sawfish-defines-regexp
+    (concat "(\\("
+            (regexp-opt 
+             ;; A cute way to obtain the list below would be:
+             ;; (sawfish-code (mapcar symbol-name (apropos "^define")))
+             ;;
+             ;; It would, however, mean that you'd have a list of "keywords"
+             ;; define in your running instance of sawfish. It would also
+             ;; mean that you'd have to have sawfish running at the time
+             ;; that this constant is defined.
+             (list 
+              "define" "define-command-args" "define-command-to-screen"
+              "define-custom-deserializer" "define-custom-serializer"
+              "define-custom-setter" "define-datum-printer"
+              "define-file-handler" "define-focus-mode"
+              "define-frame-class" "define-frame-type-mapper"
+              "define-interface" "define-linear-viewport-commands"
+              "define-match-window-formatter"
+              "define-match-window-group" "define-match-window-property"
+              "define-match-window-setter" "define-parse"
+              "define-placement-mode" "define-record-type"
+              "define-record-discloser" "define-scan-body"
+              "define-scan-form" "define-scan-internals"
+              "define-structure" "define-value"
+              "define-window-animator"))
+            "\\)\\>[ \t'(]*\\(\\sw+\\)?")
+  "List of define-structures known by Sawfish.")
+
+(defconst sawfish-additional-keywords
+    (append lisp-font-lock-keywords-2
+            (list 
+             ;; highlight define-* 
+             (list
+              sawfish-defines-regexp
+              '(1 font-lock-keyword-face)
+              `(,(regexp-opt-depth sawfish-defines-regexp)
+                font-lock-variable-name-face nil t))
+             ;; extra keywords
+             (if sawfish-extra-keyword-list
+                 (list (concat "\\<" 
+                               `,(regexp-opt sawfish-extra-keyword-list) 
+                               "\\>")
+                       '(0 font-lock-keyword-face)))
+             ;; highlight warnings
+             (if sawfish-warning-keyword-list
+                 (list (concat "\\<" 
+                               `,(regexp-opt sawfish-warning-keyword-list) 
+                               "\\>")
+                       '(0 font-lock-warning-face prepend)))))
+  "Some additonal keywords to highlight in `sawfish-mode'.")
+
+;; Main code:
+
+;;;###autoload
+(define-derived-mode sawfish-mode emacs-lisp-mode "Sawfish"
+  "Major mode for editing sawfish files and for interacting with sawfish.
+
+Special commands:
+
+\\{sawfish-mode-map}"
+  ;; `define-derived-mode' in both GNU Emacs and XEmacs doesn't appear to
+  ;; derive the font-lock settings. So, depending on the editor in use we
+  ;; need to drag those settings down to us in different ways (hmm)....
+  (if (and (boundp 'running-xemacs) (symbol-value 'running-xemacs))
+      ;; XEmacs appears to do something like this...
+      (put 'sawfish-mode 'font-lock-defaults 
+           (get 'emacs-lisp-mode 'font-lock-defaults))
+    ;; ...with GNU Emacs we need to pull it from `font-lock-defaults-alist'.
+    (unless font-lock-defaults
+      (set (make-local-variable 'font-lock-defaults)
+           (cdr (assoc 'emacs-lisp-mode font-lock-defaults-alist)))
+      ;; Add the additional font-lock pattern to `font-lock-defaults'
+      ;; only once
+      (unless (memq 'sawfish-additional-keywords (car font-lock-defaults))
+        (setq font-lock-defaults (copy-alist font-lock-defaults))
+        (setcar font-lock-defaults 
+                (append (car font-lock-defaults) 
+                        '(sawfish-additional-keywords))))))
+  ;; Menu stuff.
+  (if (and (boundp 'running-xemacs) (symbol-value 'running-xemacs))
+      ;; XEmacs.
+      (progn
+        ;; For some odd reason `delete-menu-item' doesn't seem to always work.
+        ;; Anyone know why?
+        (delete-menu-item '("Emacs-Lisp"))
+        ;; XEmacs seems to require that you add the menu yourself.
+        (easy-menu-add sawfish-mode-menu))
+    ;; See the end of this file for the code that removes the emacs lisp
+    ;; menu.
+    )
+  ;; Add support for #| ... |# style comments (call it style b) see GNU
+  ;; Emacs Lisp Reference Manual (Rev. 2.5), p. 673-675
+  (modify-syntax-entry ?# "' 14b")      ; quote or comment (style b)
+  (modify-syntax-entry ?| "_ 23b")      ; symbol or comment (style b)
+  (modify-syntax-entry ?\n ">a")        ; end comment (style a)
+  ;; The following adds some indentation information to help sawfish-mode
+  ;; (rep is a sort of elisp/scheme hybrid with some extra stuff of its own,
+  ;; we inherit from emacs-lisp-mode so we need to add a sprinkle of scheme
+  ;; support).
+  (loop for sym in '((define                  . 1)
+                     (define-interface        . 1)
+                     (define-record-discloser . 1)
+                     (define-record-type      . 1)
+                     (define-structure        . 3)
+                     (letrec                  . 1)
+                     (structure               . 2)
+                     (with-output-to-screen   . 0))
+        do (unless (get (car sym) 'lisp-indent-function)
+             (put (car sym) 'lisp-indent-function (cdr sym)))))
+
+(defun sawfish-eval (sexp &optional target-buffer)
+  "Pass SEXP to sawfish for evaluation.
+
+SEXP can either be a list or a string.
+
+If passed the result of the evaluation is inserted into TARGET-BUFFER."
+  (call-process sawfish-client nil target-buffer nil sawfish-exec-parameter
+                (if (stringp sexp) sexp (format "%S" sexp))))
+
+(defun sawfish-string-readable-p (sexp)
+  "Can string SEXP be safely `read'?"
+  (not (string-match "#<\\w+" sexp)))
+
+(defun sawfish-buffer-readable-p (&optional buffer)
+  "Can the content of BUFFER be safely `read'?"
+  (sawfish-string-readable-p
+   (with-current-buffer (or buffer (current-buffer))
+     (buffer-string))))
+
+(defun sawfish-eval-noread (sexp)
+  "Eval SEXP and return the result without `read'ing it."
+  (with-temp-buffer
+    (sawfish-eval sexp t)
+    (buffer-substring-no-properties (point-min) (1- (point-max)))))
+
+(defun sawfish-eval-read (sexp)
+  "Eval SEXP and return the result of `read'ing the result.
+
+SEXP can either be a list or a string."
+  (let ((result (sawfish-eval-noread sexp)))
+    (if (sawfish-string-readable-p result)
+        (read result)
+      result)))
+
+;;;###autoload
+(defun sawfish-eval-region (start end &optional target-buffer)
+  "Evaluate the region bounded by START and END.
+
+TARGET-BUFFER is the optional target for the return value of the
+evaluation."
+  (interactive "r")
+  (sawfish-eval (buffer-substring-no-properties start end) target-buffer))
+
+;;;###autoload
+(defun sawfish-eval-buffer ()
+  "Evaluate the whole buffer."
+  (interactive)
+  (sawfish-eval-region (point-min) (point-max) nil))
+
+;;;###autoload
+(defun sawfish-eval-defun (insert-value)
+  "Evaluate the top level form at or near `point'.
+
+INSERT-VALUE is a prefix parameter, if it is non-NIL the value of the
+expression is inserted into the buffer after the form."
+  (interactive "P")
+  (save-restriction
+    (save-excursion
+      (narrow-to-defun)
+      (setf (point) (point-max))
+      (let ((result (sawfish-eval-last-sexp nil)))
+        (if insert-value
+            (let ((standard-output (current-buffer)))
+              (setf (point) (point-min))
+              (end-of-defun)
+              (unless (bolp)
+                (terpri))
+              (princ result)
+              (terpri))
+          (sawfish-output result))))))
+
+;;;###autoload
+(defun sawfish-eval-expression (sexp &optional insert-value)
+  "Evaluate SEXP and display the value in the minibuffer.
+
+If the optional parameter INSERT-VALUE is supplied as a non-NIL value the
+value of SEXP will be inserted into the current buffer."
+  (interactive
+   (list
+    (read-from-minibuffer "Sawfish Eval: " nil sawfish-read-expression-map t 'sawfish-read-expression-history)
+    current-prefix-arg))
+  (let ((result (sawfish-eval-noread sexp)))
+    (if insert-value
+        (let ((standard-output (current-buffer)))
+          (princ result))
+      (sawfish-output result))))
+
+(defun sawfish-output (output)
+  "Display output either in mini-buffer or a seperate buffer.
+
+If the output is empty then the string \"No output\" is displayed.
+
+If the output is one line long and the length of the line is less than the
+`frame-width' then it is displayed using `message'.
+
+If the output has multiple lines or is longer than `frame-width' then a new
+buffer is opened and the text is displayed there. The name of the buffer is
+set by the variable `sawfish-result-buffer'"
+  (with-temp-buffer
+    (let ((temp-buffer (current-buffer)))
+      (insert output)
+      (let ((lines (count-lines (point-min) (point-max))))
+        (cond
+          ((zerop lines)                ; Nothing to display.
+           (message "No output"))
+          ((and (= 1 lines)             ; If there is only one line
+                (< (- (point-max)       ; and it isn't too wide for
+                      (point-min))      ; the display.
+                   (frame-width)))
+           (setf (point) (point-min))
+           (replace-string "\n" "")     ; Strip any trailing EOLs.
+           (when (get-buffer-window sawfish-result-buffer)
+             ;; The long result buffer is visible, delete it.
+             (delete-window (get-buffer-window sawfish-result-buffer)))
+           (message "%s" (buffer-string)))
+          (t                            ; Too large for message area, use a buffer.
+           (with-output-to-temp-buffer sawfish-result-buffer
+             (with-current-buffer sawfish-result-buffer
+               (if (sawfish-string-readable-p output)
+                   (pp (read output) (current-buffer))
+                 (setf (buffer-string) (format "%s" (with-current-buffer temp-buffer
+                                                      (buffer-string)))))
+               (shrink-window-if-larger-than-buffer (display-buffer (current-buffer))))
+             (bury-buffer (current-buffer)))))))))
+
+(defun sawfish-insert (string)
+  "Insert STRING into `current-buffer', pretty print if at all possible."
+  (if (sawfish-string-readable-p string)
+      (pp (read string) (current-buffer))
+    (insert string)))
+
+;;;###autoload
+(defun sawfish-eval-last-sexp (to-buffer)
+  "Version of `eval-last-sexp' that interacts with sawfish."
+  (interactive "P")
+  (let ((home-buffer (current-buffer)))
+    (with-temp-buffer
+      (let ((temp-buffer (current-buffer)))
+        (with-current-buffer home-buffer
+          (sawfish-eval-region (save-excursion
+                                 (backward-sexp)
+                                 (point))
+                               (point)
+                               temp-buffer)
+          (funcall (if to-buffer
+                       #'sawfish-insert
+                     #'sawfish-output)
+                   (with-current-buffer temp-buffer (buffer-string))))))))
+
+;;;###autoload
+(defun sawfish-eval-print-last-sexp ()
+  (interactive)
+  (insert "\n")
+  (sawfish-eval-last-sexp t))
+
+(defmacro sawfish-code (&rest body)
+  "Pass BODY to sawfish for evaluation."
+  `(sawfish-eval-read (cons 'progn (quote ,body))))
+
+(defun sawfish-load-helpers ()
+  "Load modules that help us work with sawfish."
+  (sawfish-code
+    (require 'rep.structures)
+    (require 'lisp-doc)))
+
+(defun sawfish-load-symbols (&optional force)
+  "Loads the names of the sawfish functions and variables."
+  (unless (and (not (or force (not sawfish-buffer-symbol-lists)))
+               sawfish-function-list sawfish-variable-list)
+    (setq sawfish-function-list nil
+          sawfish-variable-list nil)
+    (flet ((sawfish-fun-p (sym) (second sym))
+           (sawfish-var-p (sym) (third sym)))
+      (loop for sym in (sawfish-eval-read
+                        `(mapcar (lambda (sym)
+                                   (list
+                                    (symbol-name sym)
+                                    (or (macrop sym) (,sawfish-function-p sym))
+                                    (,sawfish-variable-p sym)))
+                          (apropos ".")))
+            if (sawfish-fun-p sym) do (push (list (car sym)) sawfish-function-list)
+            if (sawfish-var-p sym) do (push (list (car sym)) sawfish-variable-list)))))
+
+(defun sawfish-documentation (symbol &optional is-variable)
+  "Get the documentation for SYMBOL."
+  (sawfish-eval-read `(documentation (quote ,symbol) ,is-variable)))
+
+(defun sawfish-funcall-at-point ()
+  "Try and work out the function being called at or near `point'."
+  ;; `thing-at-point', when trying to grab a list, doesn't appear to do what
+  ;; I need most of the time. I need to figure out what is wrong or write
+  ;; something better.
+  (let ((list (thing-at-point 'list)))
+    (when list
+      (let ((fun (symbol-name (car (read list)))))
+        (when (assoc fun sawfish-function-list)
+          fun)))))
+
+(defun sawfish-variable-at-point ()
+  "Try and work out the variable being called at or near `point'."
+  (let ((sym (thing-at-point 'symbol)))
+    (when sym
+      (let ((var (symbol-name (read sym))))
+        (when (assoc var sawfish-variable-list)
+          var)))))
+
+(defun sawfish-describe-ask (default description lookups)
+  "Ask the user for a symbol.
+
+The symbol will be described as DESCRIPTION with a completing read using
+LOOKUPS for the completion. DEFAULT should be a function that returns a
+default value for the read."
+  (sawfish-load-symbols)
+  (intern (completing-read (format "Sawfish %s: " description)
+                           (symbol-value lookups)
+                           nil
+                           t
+                           (funcall default))))
+
+(defun sawfish-describe-ask-function ()
+  "Ask for a function name."
+  (sawfish-describe-ask #'sawfish-funcall-at-point "function" 'sawfish-function-list))
+
+(defun sawfish-describe-ask-variable ()
+  "Ask for a variable name."
+  (sawfish-describe-ask #'sawfish-variable-at-point "variable" 'sawfish-variable-list))
+
+(defun sawfish-info-function-index (info-file)
+  "Return the name of the function index from INFO-FILE.
+
+This function is used to pull information from the entries found in the
+variable `sawfish-info-files'."
+  (cadr info-file))
+
+(defun sawfish-info-variable-index (info-file)
+  "Return the name of the variable index from INFO-FILE.
+
+This function is used to pull information from the entries found in the
+variable `sawfish-info-files'."
+  (car (cddr info-file)))
+
+(defun sawfish-info-index-function (is-variable)
+  "Return the a function for accessing the info file list."
+  (if is-variable #'sawfish-info-variable-index #'sawfish-info-function-index))
+
+(defun sawfish-describe-show (symbol &optional is-variable)
+  "Show the sawfish description for SYMBOL."
+  (with-output-to-temp-buffer sawfish-help-buffer
+    (princ (format "`%s' is a %s" symbol
+                   (sawfish-eval-read `(,sawfish-describe-symbol (quote ,symbol)))))
+    (when is-variable
+      (princ "\n\nValue:\n\n")
+      (pp (sawfish-eval-read symbol)))
+    (princ "\n\nDocumentation:\n\n")
+    (let ((doc (or (sawfish-documentation symbol is-variable)
+                   (sawfish-search-and-grab-info (sawfish-info-index-function is-variable) symbol))))
+      (if doc
+          (princ doc)
+        (princ (format "%s is undocumented" symbol))))
+    (let ((plist (sawfish-eval-read `(symbol-plist (quote ,symbol)))))
+      (when (and plist (listp plist))
+        (princ "\n\nProperty list for symbol:\n")
+        (loop for prop on plist by #'cddr
+              do (princ (format "\n%s: %S" (car prop) (cadr prop))))))))
+
+;;;###autoload
+(defun sawfish-describe-function (function)
+  "Display the doc-string for FUNCTION."
+  (interactive (list (sawfish-describe-ask-function)))
+  (sawfish-load-helpers)
+  (sawfish-describe-show function))
+
+;;;###autoload
+(defun sawfish-describe-variable (variable)
+  "Display the doc-string for VARIABLE."
+  (interactive (list (sawfish-describe-ask-variable)))
+  (sawfish-load-helpers)  
+  (sawfish-describe-show variable t))
+
+(defun sawfish-find-info-entry (info-file node symbol)
+  "Try to find SYMBOL in NODE of INFO-FILE.
+
+If the symbol isn't found the Info buffer is killed and the function returns
+nil, otherwise the Info buffer is left as the `current-buffer'."
+  (condition-case nil
+      (progn
+        (require 'info)
+        (Info-find-node info-file node)
+        (Info-menu (format "%s" symbol))
+        t)
+    (error
+     (when (string= (buffer-name) "*info*")
+       (kill-buffer (current-buffer)))
+     nil)))
+
+(defun sawfish-jump-to-info-documentaiton (symbol)
+  "Jump to the documentation for SYMBOL in an info buffer.
+
+Returns NIL if the documentation could not be found. Note that the
+`current-buffer' must be the info buffer you are searching."
+  (prog1
+      (search-forward-regexp (format "^ - .*: %s" symbol) nil t)
+    (beginning-of-line)))
+
+(defun sawfish-extract-info-entry (symbol)
+  "Extract the info documentation for SYMBOL as a string."
+  (when (sawfish-jump-to-info-documentaiton symbol)
+    ;; For some odd reason, in XEmacs, the `current-buffer' inside
+    ;; `with-output-to-string' is the string output buffer, not your
+    ;; `current-buffer' before the call to `with-output-to-string'. Bizarre!
+    ;; GNU emacs does the right thing.
+    ;;
+    ;; Anyway, to get round this odd behaviour you'll see lots of pointless
+    ;; calls to `with-current-buffer' <sigh>.
+    (let ((info-buffer (current-buffer)))
+      (with-output-to-string nil
+        (princ (with-current-buffer info-buffer
+                 (buffer-substring-no-properties
+                  (+ (point) 3)         ; Strip the leading " - ".
+                  (save-excursion
+                    (end-of-line)
+                    (point)))))
+        (terpri)
+        (terpri)
+        (with-current-buffer info-buffer
+          (forward-line))
+        (loop while (with-current-buffer info-buffer
+                      ;; I'm not 100% sure what to look for when trying to
+                      ;; find the end of a info entry. This seems to work.
+                      (and (not (eobp))
+                           (or (looking-at "^     ")
+                               (looking-at "^ *$"))))
+              do (let ((eol (with-current-buffer info-buffer
+                              (save-excursion
+                                (end-of-line)
+                                (point)))))
+                   (princ (with-current-buffer info-buffer
+                            (buffer-substring-no-properties
+                             (min (+ (point) 5) eol) ; Strip the leading white space.
+                             eol))))
+              (terpri)
+              (with-current-buffer info-buffer
+                (forward-line)))))))
+
+(defun sawfish-search-and-grab-info (index-function symbol)
+  "Look for SYMBOL in all the sawfish info files, return the docs.
+
+INDEX-FUNCTION is used to decide which index name will be searched. The
+function is used to access the lists in `sawfish-info-files'."
+  (save-excursion
+    (loop for info-file in sawfish-info-files
+          if (sawfish-find-info-entry (car info-file) (funcall index-function info-file) symbol)
+          return (prog1 (sawfish-extract-info-entry symbol) (kill-buffer (current-buffer)))
+          finally return nil)))
+
+(defun sawfish-search-info-files (index-function symbol)
+  "Look for SYMBOL in all the sawfish info files.
+
+INDEX-FUNCTION is used to decide which index name will be searched. The
+function is used to access the lists in `sawfish-info-files'."
+  (loop for info-file in sawfish-info-files
+        if (sawfish-find-info-entry (car info-file) (funcall index-function info-file) symbol) return t
+        finally (error "No info documentation found for %s" symbol)))
+
+(defun sawfish-search-info-files-for-function (function)
+  "Search for info documentation for FUNCTION."
+  (sawfish-search-info-files #'sawfish-info-function-index function))
+
+(defun sawfish-search-info-files-for-variable (variable)
+  "Search for info documentation for VARIABLE."
+  (sawfish-search-info-files #'sawfish-info-variable-index variable))
+
+;;;###autoload
+(defun sawfish-info-function (function)
+  "Display the Info documentation for FUNCTION."
+  (interactive (list (sawfish-describe-ask-function)))
+  (sawfish-search-info-files-for-function function)
+  (sawfish-jump-to-info-documentaiton function))
+
+;;;###autoload
+(defun sawfish-info-variable (variable)
+  "Display the Info documentation for VARIABLE."
+  (interactive (list (sawfish-describe-ask-variable)))
+  (sawfish-search-info-files-for-variable variable)
+  (sawfish-jump-to-info-documentaiton variable))
+
+(defsubst sawfish-apropos-symbol (sym)
+  "`sawfish-apropos' support function."
+  (nth 0 sym))
+
+(defsubst sawfish-apropos-symbol-name (sym)
+  "`sawfish-apropos' support function."
+  (symbol-name (sawfish-apropos-symbol sym)))
+
+(defsubst sawfish-apropos-description (sym)
+  "`sawfish-apropos' support function."
+  (nth 1 sym))
+
+(defsubst sawfish-apropos-variable-p (sym)
+  "`sawfish-apropos' support function."
+  (nth 2 sym))
+
+(defsubst sawfish-apropos-doc-string (sym)
+  "`sawfish-apropos' support function."
+  (nth 3 sym))
+
+(defun sawfish-doc-string-first-line (doc-string)
+  "Given doc string DOC-STRING return the first line.
+
+If the doc-string is NIL (no documentation) then \"Undocumented\" is
+returned."
+  (if doc-string
+      (with-temp-buffer
+        (insert doc-string)
+        (setf (point) (point-min))
+        (end-of-line)
+        (buffer-substring-no-properties (point-min) (point)))
+    "Undocumented"))
+
+(defun sawfish-remove-info-one-liner-intro (doc-string)
+  "Remove the leading symbol type text from an info derived doc-string."
+  (when doc-string
+    (with-temp-buffer
+      (insert doc-string)
+      (setf (point) (point-min))
+      (if (search-forward-regexp ": +" nil t)
+          (buffer-substring-no-properties (point) (point-max))
+        doc-string))))
+
+(defun sawfish-apropos-insert-link (sym)
+  "Insert a documentation link for SYM into the apropos buffer."
+  (let ((start (point)))
+    (insert (sawfish-apropos-symbol-name sym))
+    (put-text-property start (point) 'face 'bold))
+  (insert "\n  ")
+  (let ((start (point)))
+    (insert (sawfish-apropos-description sym) ":")
+    (put-text-property start (point) 'mouse-face 'highlight)
+    (let ((local-map (make-sparse-keymap))
+          (desc      `(lambda ()
+                       (interactive)
+                       (,(if (sawfish-apropos-variable-p sym)
+                             #'sawfish-describe-variable #'sawfish-describe-function)
+                        (quote ,(sawfish-apropos-symbol sym))))))
+      (define-key local-map [mouse-2] desc)
+      (define-key local-map [return] desc)
+      (put-text-property (- start 2) (point) 'local-map local-map)))
+  (insert " "
+          (sawfish-doc-string-first-line (or (sawfish-apropos-doc-string sym)
+                                             (and sawfish-apropos-searches-info-files
+                                                  (sawfish-remove-info-one-liner-intro
+                                                   (sawfish-search-and-grab-info
+                                                    (sawfish-info-index-function 
+                                                     (sawfish-apropos-variable-p sym))
+                                                    (sawfish-apropos-symbol sym))))))
+          "\n"))
+
+;;;###autoload
+(defun sawfish-apropos (regexp)
+  "Show all bound sawfish symbols whose names match REGEXP."
+  (interactive "sSawfish Apropos (regexp): ")
+  (sawfish-load-helpers)
+  (let ((hits (sort (sawfish-eval-read
+                     `(progn
+                       (require (quote lisp-doc))
+                       (mapcar
+                        (lambda (s)
+                          (list s
+                                (,sawfish-describe-symbol s)
+                                (,sawfish-variable-p s)
+                                (documentation s (,sawfish-variable-p s))))
+                        (apropos ,regexp))))
+                    (lambda (symX symY)
+                      (string< (sawfish-apropos-symbol-name symX)
+                               (sawfish-apropos-symbol-name symY))))))
+    (if (not (zerop (length hits)))
+        (with-output-to-temp-buffer sawfish-apropos-buffer
+          (with-current-buffer sawfish-apropos-buffer
+            (setf (buffer-string) "")
+            (loop for sym in hits do (sawfish-apropos-insert-link sym))))
+      (message "No apropos matches for `%s'" regexp))))
+
+;;;###autoload
+(defun sawfish-complete-symbol ()
+  "Attempt to complete the symbol at `point'."
+  (interactive)
+  (let ((sym (thing-at-point 'symbol)))
+    (when sym
+      (let* ((sym        (symbol-name (read sym)))
+             (sym-re     (concat "^" (regexp-quote sym)))
+             (completion (sawfish-eval-read
+                          `(complete-string ,sym (mapcar symbol-name (apropos ,sym-re))))))
+        (if completion
+            (if (equal completion sym)
+                (let ((sym-list (sawfish-eval-read `(mapcar symbol-name (apropos ,(format "^%s" sym))))))
+                  (when (> (length sym-list) 1)
+                    (with-output-to-temp-buffer "*Completions*"
+                      (display-completion-list
+                       (sawfish-eval-read `(mapcar symbol-name (apropos ,sym-re)))))))
+              (let ((bounds (bounds-of-thing-at-point 'symbol)))
+                (delete-region (car bounds) (cdr bounds))
+                (insert completion)))
+          (error "No completion for `%s'" sym))))))
+
+;;;###autoload
+(defun sawfish-info ()
+  "View the sawfish info file."
+  (interactive)
+  (info "sawfish"))
+
+;;;###autoload
+(defun sawfish-rep-info ()
+  "View the librep info file."
+  (interactive)
+  (info "librep"))
+
+(define-derived-mode sawfish-console-mode inferior-lisp-mode
+  "*sawfish-console*" nil
+  (make-local-variable 'inferior-lisp-prompt)
+  (setq inferior-lisp-prompt sawfish-comint-prompt))
+
+;;;###autoload
+(defun sawfish-console ()
+  "Run the sawfish client as an inferior lisp."
+  (interactive)
+  ;; TODO: How to set lisp-*-command variables for this particular
+  ;; instantiation of the inferior lisp buffer?
+  (unless (comint-check-proc "*sawfish-client*")
+    (set-buffer (make-comint "sawfish-client" sawfish-client nil sawfish-interactive-parameter))
+    (sawfish-console-mode))
+  (set (make-local-variable 'inferior-lisp-buffer) "*sawfish-client*")
+  (pop-to-buffer "*sawfish-client*"))
+
+(defun sawfish-interaction-mode ()
+  "Extend `sawfish-mode' for use with `sawfish-interaction'."
+  (sawfish-mode)
+  (setq major-mode 'sawfish-interaction-mode
+        mode-name  "sawfish interaction")
+  (use-local-map sawfish-interaction-mode-map))
+
+;;;###autoload
+(defun sawfish-interaction ()
+  "Create a sawfish interaction buffer."
+  (interactive)
+  (let ((new-buffer (not (get-buffer sawfish-scratch-buffer))))
+    (switch-to-buffer (get-buffer-create sawfish-scratch-buffer))
+    (when new-buffer
+      (insert ";; This buffer is for interacting with the sawfish window manager.\n\n")))
+  (sawfish-interaction-mode))
+
+;; Define the sawfish-mode keymap.
+(define-key sawfish-mode-map [(control x) (control e)]             #'sawfish-eval-last-sexp)
+(define-key sawfish-mode-map [(meta control x)]                    #'sawfish-eval-defun)
+(define-key sawfish-mode-map [(meta :)]                            #'sawfish-eval-expression)
+(define-key sawfish-mode-map [(control c) (control h) ?a]          #'sawfish-apropos)
+(define-key sawfish-mode-map [(control c) (control h) ?f]          #'sawfish-describe-function)
+(define-key sawfish-mode-map [(control c) (control h) (control f)] #'sawfish-info-function)
+(define-key sawfish-mode-map [(control c) (control h) ?v]          #'sawfish-describe-variable)
+(define-key sawfish-mode-map [(control c) (control h) (control v)] #'sawfish-info-variable)
+(define-key sawfish-mode-map [(meta tab)]                          #'sawfish-complete-symbol)
+(define-key sawfish-mode-map [(control c) (control h) ?i]          #'sawfish-info)
+(define-key sawfish-mode-map [(control meta :)]                    #'eval-expression)
+
+;; Define the minibuffer keymap.
+(unless sawfish-read-expression-map
+  (setq sawfish-read-expression-map (make-sparse-keymap))
+  (set-keymap-parent sawfish-read-expression-map minibuffer-local-map)
+  (define-key sawfish-read-expression-map [(meta tab)] #'sawfish-complete-symbol))
+
+;; Define the sawfish-interaction keymap.
+(unless sawfish-interaction-mode-map
+  (setq sawfish-interaction-mode-map (make-sparse-keymap))
+  (set-keymap-parent sawfish-interaction-mode-map sawfish-mode-map)
+  (define-key sawfish-interaction-mode-map [(control j)] #'sawfish-eval-print-last-sexp))
+
+;; Further define the sawfish-console-mode keymap. It is initialised already
+;; because of define-derived-mode.
+(define-key sawfish-console-mode-map [(tab)]                               #'sawfish-complete-symbol)
+(define-key sawfish-console-mode-map [(control c) (control h) ?a]          #'sawfish-apropos)
+(define-key sawfish-console-mode-map [(control c) (control h) ?f]          #'sawfish-describe-function)
+(define-key sawfish-console-mode-map [(control c) (control h) (control f)] #'sawfish-info-function)
+(define-key sawfish-console-mode-map [(control c) (control h) ?v]          #'sawfish-describe-variable)
+(define-key sawfish-console-mode-map [(control c) (control h) (control v)] #'sawfish-info-variable)
+
+;; Indentation hints for macros and functions provided by sawfish.el
+(put 'sawfish-code 'lisp-indent-function 0)
+
+;;; Menus
+
+;; GNU Emacs/XEmacs difference crap.
+(defun sawfish-region-active-p ()
+  "Is there an active region?"
+  (if (and (boundp 'running-xemacs) (symbol-value 'running-xemacs))
+      (funcall (symbol-function 'region-exists-p))
+    (symbol-value 'mark-active)))
+  
+(easy-menu-define sawfish-mode-menu sawfish-mode-map "sawfish commands"
+  '("Sawfish"
+    ["Indent Line"                     lisp-indent-line          t]
+    ["Indent Region"                   indent-region             (sawfish-region-active-p)]
+    ["Comment Out Region"              comment-region            (sawfish-region-active-p)]
+    "----"
+    ["Evaluate Last S-expression"      sawfish-eval-last-sexp    t]
+    ["Evaluate Top Level Form"         sawfish-eval-defun        t]
+    ["Evaluate Region"                 sawfish-eval-region       (sawfish-region-active-p)]
+    ["Evaluate Buffer"                 sawfish-eval-buffer       t]
+    ["Evaluate Expression"             sawfish-eval-expression   t]
+    "----"
+    ["Describe Sawfish Variable"       sawfish-describe-variable t]
+    ["Describe Sawfish Function"       sawfish-describe-function t]
+    ["Info on Variable"                sawfish-info-variable     t]
+    ["Info on Function"                sawfish-info-function     t]
+    ["Apropos"                         sawfish-apropos           t]
+    "----"
+    ["Open Sawfish Interaction Buffer" sawfish-interaction       t]
+    ["Open Sawfish Console"            sawfish-console           t]
+    "----"
+    ["Read Sawfish Documentation"      sawfish-info              t]
+    ["Read librep Documentation"       sawfish-rep-info          t]))
+
+;; GNU emacs emacs-lisp menu removal kludge.
+
+(defvar sawfish-gnu-emacs-menu-kludged nil
+  "Check if we've kludged the menu in GNU emacs.")
+
+(unless (and (boundp 'running-xemacs) (symbol-value 'running-xemacs))
+  (unless sawfish-gnu-emacs-menu-kludged
+    (let ((old-emacs-lisp-mode-map (copy-keymap emacs-lisp-mode-map)))
+      ;; Remove the binding for the emacs-lisp menu.
+      (define-key emacs-lisp-mode-map [menu-bar emacs-lisp] 'undefinded)
+      ;; Initialise sawfish-mode.
+      (with-temp-buffer (sawfish-mode))
+      ;; Restore the emacs-lisp-mode keymap.
+      (setq emacs-lisp-mode-map (copy-keymap old-emacs-lisp-mode-map)))
+    (setq sawfish-gnu-emacs-menu-kludged t)))
+
+;; Helpful hints for info lookups (provided by Markus Holmberg).
+
+(eval-after-load "info-look"
+  '(info-lookup-maybe-add-help
+    :mode 'sawfish-mode
+    :regexp "[^()`',\" \t\n]+"
+    :doc-spec '(("(sawfish)Function Index" nil "^ - [^:]+: " "\\b")
+                ("(sawfish)Variable Index" nil "^ - [^:]+: " "\\b")
+                ("(librep)Function Index"  nil "^ - [^:]+: " "\\b")
+                ("(librep)Variable Index"  nil "^ - [^:]+: " "\\b"))))
+
+(provide 'sawfish)
+
+;;; sawfish.el ends here
diff --git a/debian/sawfish.emacsen-install b/debian/sawfish.emacsen-install
new file mode 100644
index 0000000..d8d7553
--- /dev/null
+++ b/debian/sawfish.emacsen-install
@@ -0,0 +1,41 @@
+#! /bin/sh -e
+# /usr/lib/emacsen-common/packages/install/sawfish
+
+FLAVOR=$1
+PACKAGE=sawfish
+
+if [ ${FLAVOR} = emacs ]; then exit 0; fi
+
+echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR}
+
+FLAVORTEST=`echo $FLAVOR | cut -c-6`
+if [ ${FLAVORTEST} = xemacs ] ; then
+    SITEFLAG="-no-site-file"
+else
+    SITEFLAG="--no-site-file"
+fi
+FLAGS="${SITEFLAG} -q -batch -l path.el -f batch-byte-compile"
+
+ELDIR=/usr/share/emacs/site-lisp/${PACKAGE}
+ELCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE}
+
+# Install-info-altdir does not actually exist. 
+# Maybe somebody will write it.
+if test -x /usr/sbin/install-info-altdir; then
+    echo install/${PACKAGE}: install Info links for ${FLAVOR}
+    install-info-altdir --quiet --section "" "" --dirname=${FLAVOR} /usr/info/${PACKAGE}.info.gz
+fi
+
+install -m 755 -d ${ELCDIR}
+cd ${ELDIR}
+FILES=`echo *.el`
+cp ${FILES} ${ELCDIR}
+cd ${ELCDIR}
+
+cat << EOF > path.el
+(setq load-path (cons "." load-path) byte-compile-warnings nil)
+EOF
+${FLAVOR} ${FLAGS} ${FILES}
+rm -f *.el path.el
+
+exit 0
diff --git a/debian/sawfish.emacsen-remove b/debian/sawfish.emacsen-remove
new file mode 100644
index 0000000..4cd4e32
--- /dev/null
+++ b/debian/sawfish.emacsen-remove
@@ -0,0 +1,15 @@
+#!/bin/sh -e
+# /usr/lib/emacsen-common/packages/remove/sawfish
+
+FLAVOR=$1
+PACKAGE=sawfish
+
+if [ ${FLAVOR} != emacs ]; then
+    if test -x /usr/sbin/install-info-altdir; then
+        echo remove/${PACKAGE}: removing Info links for ${FLAVOR}
+        install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/info/a2ps.info.gz
+    fi
+
+    echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR}
+    rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE}
+fi
diff --git a/debian/sawfish.emacsen-startup b/debian/sawfish.emacsen-startup
new file mode 100644
index 0000000..6431b7c
--- /dev/null
+++ b/debian/sawfish.emacsen-startup
@@ -0,0 +1,11 @@
+;; -*-emacs-lisp-*-
+
+(setq load-path (cons (concat "/usr/share/"
+                              (symbol-name flavor)
+			      "/site-lisp/sawfish") load-path))
+
+(autoload 'sawfish-mode "sawfish" "sawfish-mode" t)
+
+(setq auto-mode-alist (cons '("\\.sawfishrc$"  . sawfish-mode) auto-mode-alist)
+auto-mode-alist (cons '("\\.jl$"         . sawfish-mode) auto-mode-alist)
+auto-mode-alist (cons '("\\.sawfish/rc$" . sawfish-mode) auto-mode-alist))
diff --git a/debian/sawfish.install b/debian/sawfish.install
new file mode 100644
index 0000000..78d9f5b
--- /dev/null
+++ b/debian/sawfish.install
@@ -0,0 +1,9 @@
+debian/sawfish.el   usr/share/emacs/site-lisp/sawfish
+usr/share/applications/sawfish.desktop
+usr/share/gnome/wm-properties/sawfish-wm.desktop
+usr/share/apps/ksmserver/windowmanagers/sawfish.desktop
+usr/share/sawfish/sawfish.png
+usr/share/xsessions/sawfish.desktop
+usr/share/sawfish/*/lisp/sawfish/cfg/main.jlc
+usr/lib
+usr/bin
diff --git a/debian/sawfish.links b/debian/sawfish.links
new file mode 100644
index 0000000..6090aa2
--- /dev/null
+++ b/debian/sawfish.links
@@ -0,0 +1 @@
+usr/share/doc/sawfish-data usr/share/doc/sawfish
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..2b423fa
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,3 @@
+version=3
+
+http://sf.net/sawmill/sawfish-([\d.]+)\.tar\.(?::gz|bz2) debian
diff --git a/src/display.c b/src/display.c
index cbc509a..e21f35d 100644
--- a/src/display.c
+++ b/src/display.c
@@ -82,9 +82,23 @@ error_handler (Display *dpy, XErrorEvent *ev)
 	if (w != NULL)
 	{
 	    DB(("error_handler (%s)\n", rep_STR(w->name)));
-	    
+
 	    if (!WINDOW_IS_GONE_P (w))
-		remove_window (w, TRUE, TRUE);
+           {
+               /* don't unmap a window that had send an X_ConfigureWindow request */
+               if(
+                   /*     ev->type == 0 what is the "type" ? but I've seen that type is always 0 */
+                   /*&&*/ ev->error_code==BadWindow /* the window is bad, because it is not configured yet */
+                     &&   ev->request_code==X_ConfigureWindow
+                     &&   ev->minor_code==0 /* X_ConfigureWindow is not in an Xlib extension, so it must be 0 */
+               )
+               {
+                   return 0;
+               } else
+               {
+                   remove_window (w, TRUE, TRUE);
+               }
+           }
 
 	    /* so we call emit_pending_destroys () at some point */
 	    rep_mark_input_pending (ConnectionNumber (dpy));
@@ -442,7 +456,7 @@ void
 send_client_message (Window w, Atom a, Time time)
 {
   XClientMessageEvent ev;
-  
+
   ev.type = ClientMessage;
   ev.window = w;
   ev.message_type = xa_wm_protocols;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]