[Pkg-wmaker-commits] [wmcube] 07/67: Imported Upstream version 0.99-pre1

Doug Torrance dtorrance-guest at moszumanska.debian.org
Tue Aug 25 03:22:11 UTC 2015


This is an automated email from the git hooks/post-receive script.

dtorrance-guest pushed a commit to branch master
in repository wmcube.

commit 925287ee5f00726853410f387b9bb4566cbd5595
Author: Doug Torrance <dtorrance at monmouthcollege.edu>
Date:   Sat Jan 10 23:09:27 2015 -0600

    Imported Upstream version 0.99-pre1
---
 3dObjects/2planes-solid.wmc                      |   23 -
 3dObjects/4d.wmc                                 |   59 -
 3dObjects/8star-small.wmc                        |   40 -
 3dObjects/8star.wmc                              |   40 -
 3dObjects/CONTRIBUTE                             |   51 -
 3dObjects/README                                 |   54 -
 3dObjects/ball.wmc                               |   83 --
 3dObjects/celtic.wmc                             |   71 --
 3dObjects/cross.wmc                              |   63 -
 3dObjects/cross2.wmc                             |   51 -
 3dObjects/cross3.wmc                             |   95 --
 3dObjects/crystal.wmc                            |  108 --
 3dObjects/cube.wmc                               |   24 -
 3dObjects/diamond.wmc                            |   66 --
 3dObjects/e.wmc                                  |   69 --
 3dObjects/e2.wmc                                 |  160 ---
 3dObjects/foo.wmc                                |  149 ---
 3dObjects/gnustep.wmc                            |  110 --
 3dObjects/hyperpyramid.wmc                       |   54 -
 3dObjects/jeep.wmc                               |  157 ---
 3dObjects/multicube.wmc                          |   83 --
 3dObjects/pyramid.wmc                            |   16 -
 3dObjects/shield.wmc                             |  197 ----
 3dObjects/spaceshuttle.wmc                       |  382 ------
 3dObjects/spiral.wmc                             |   49 -
 3dObjects/star.wmc                               |   95 --
 3dObjects/starcube.wmc                           |   69 --
 CHANGES                                          |   22 +-
 INSTALL                                          |   37 -
 Makefile                                         |   58 +
 README                                           |  124 +-
 TODO                                             |    8 -
 WmcObject.cc                                     |  619 ++++++++++
 WmcObject.h                                      |   96 ++
 cpumoncc/README                                  |   70 ++
 cpumoncc/base/BaseCpuMonitor.h                   |  112 ++
 cpumoncc/darwin/CpuMonitor.cc                    |   41 +
 cpumoncc/darwin/CpuMonitor.h                     |   39 +
 cpumoncc/darwin/Makefile                         |   41 +
 cpumoncc/freebsd/CpuMonitor.cc                   |   80 ++
 cpumoncc/freebsd/CpuMonitor.h                    |   52 +
 cpumoncc/freebsd/Makefile                        |   41 +
 cpumoncc/linux/CpuMonitor.cc                     |  100 ++
 cpumoncc/linux/CpuMonitor.h                      |   45 +
 cpumoncc/linux/Makefile                          |   40 +
 cpumoncc/netbsd/CpuMonitor.cc                    |  113 ++
 cpumoncc/netbsd/CpuMonitor.h                     |   43 +
 cpumoncc/netbsd/Makefile                         |   40 +
 cpumoncc/openbsd/CpuMonitor.cc                   |   42 +
 cpumoncc/openbsd/CpuMonitor.h                    |   38 +
 cpumoncc/openbsd/Makefile                        |   40 +
 cpumoncc/programs/Makefile                       |   14 +
 cpumoncc/programs/README                         |   17 +
 cpumoncc/programs/cpu.cc                         |   56 +
 cpumoncc/programs/cpuload.cc                     |   60 +
 cpumoncc/solaris/CpuMonitor.cc                   |  141 +++
 cpumoncc/solaris/CpuMonitor.h                    |   53 +
 cpumoncc/solaris/Makefile                        |   40 +
 COPYING => wmapp/COPYING                         |   11 +-
 wmapp/Changelog                                  |   82 ++
 wmapp/Changelog.Jason                            |  154 +++
 wmapp/FAQ.txt                                    |  278 +++++
 wmapp/Makefile                                   |   35 +
 wmapp/README                                     |   66 ++
 wmapp/Widgets.txt                                |   49 +
 wmapp/colors.h                                   |   54 +
 wmapp/example1/Makefile                          |   13 +
 wmapp/example1/debian-tiny.xpm                   |   50 +
 wmapp/example1/window0.cc                        |  204 ++++
 wmapp/example1/window1.cc                        |   86 ++
 wmapp/example1/wmexample.cc                      |   39 +
 wmapp/example2/Makefile                          |   13 +
 wmapp/example2/wmairtrafficcontrol.cc            |   80 ++
 wmapp/example2/wmradar.cc                        |  220 ++++
 wmapp/example2/wmradar.h                         |   44 +
 wmapp/wmapp.cc                                   |  378 ++++++
 wmapp/wmapp.h                                    |  170 +++
 wmapp/wmbutton.cc                                |   59 +
 wmapp/wmbutton.h                                 |   18 +
 wmapp/wmcallback.cc                              |   34 +
 wmapp/wmcallback.h                               |  113 ++
 wmapp/wmcanvas.cc                                |  160 +++
 wmapp/wmcanvas.h                                 |   68 ++
 wmapp/wmclickable.h                              |   21 +
 wmapp/wmellipse.cc                               |   58 +
 wmapp/wmellipse.h                                |   21 +
 wmapp/wmframe.cc                                 |  303 +++++
 wmapp/wmframe.h                                  |  109 ++
 wmapp/wmhistory.cc                               |   67 ++
 wmapp/wmhistory.h                                |   71 ++
 wmapp/wmimage.cc                                 |   91 ++
 wmapp/wmimage.h                                  |   52 +
 wmapp/wmled.cc                                   |   12 +
 wmapp/wmled.h                                    |   34 +
 wmapp/wmmeter.h                                  |   57 +
 wmapp/wmmeterbar.cc                              |   80 ++
 wmapp/wmmeterbar.h                               |   47 +
 wmapp/wmslider.cc                                |   42 +
 wmapp/wmslider.h                                 |   32 +
 wmapp/wmtextbar.cc                               |   63 +
 wmapp/wmtextbar.h                                |   57 +
 wmapp/wmwidget.cc                                |   99 ++
 wmapp/wmwidget.h                                 |  367 ++++++
 wmapp/wmwindow.cc                                |  114 ++
 wmapp/wmwindow.h                                 |  130 +++
 wmapp/xpm/charmap-large.xpm                      |   74 ++
 wmapp/xpm/charmap-medium.xpm                     |   62 +
 wmapp/xpm/charmap-small.xpm                      |   62 +
 wmapp/xpm/checkbox.xpm                           |   14 +
 wmapp/xpm/emptybar.xpm                           |   62 +
 wmapp/xpm/fullbar.xpm                            |   62 +
 wmapp/xpm/leds.xpm                               |   14 +
 wmapp/xpm/tile.xpm                               |  121 ++
 wmapp/xpm/xbutton.xpm                            |   14 +
 wmapp/xwrapper.cc                                |  329 ++++++
 wmapp/xwrapper.h                                 |  140 +++
 3dObjects/ball-solid.wmc => wmc/ball.wmc         |   53 +
 wmc/cossin.wmc                                   |  362 ++++++
 wmc/coussin.bande.diag.wmc                       |  124 ++
 {3dObjects => wmc}/cross2-solid.wmc              |    0
 {3dObjects => wmc}/cross3-solid.wmc              |    0
 3dObjects/cube-solid.wmc => wmc/cube.wmc         |   16 +
 wmc/diamond.wmc                                  |  107 ++
 3dObjects/dice-solid.wmc => wmc/dice.wmc         |   45 +
 wmc/hyp_par.wmc                                  |   70 ++
 wmc/judaspriest.wmc                              |  239 ++++
 {3dObjects => wmc}/peace.wmc                     |    2 +
 {3dObjects => wmc}/radioactive.wmc               |    2 +
 3dObjects/cross4-solid.wmc => wmc/star-solid.wmc |   48 +-
 {3dObjects => wmc}/wmlogo.wmc                    |    2 +
 wmcube.cc                                        |  695 +++++++++++
 wmcube.h                                         |  118 ++
 wmcube/Makefile                                  |   39 -
 wmcube/Makefile.FREEBSD                          |   38 -
 wmcube/Makefile.LINUX                            |   39 -
 wmcube/Makefile.NETBSD                           |   36 -
 wmcube/Makefile.OPENBSD                          |   37 -
 wmcube/Makefile.SOLARIS                          |   38 -
 wmcube/wmcube.c                                  | 1351 ----------------------
 wmcube/wmcube.xpm                                |  142 ---
 wmgeneral/list.c                                 |  169 ---
 wmgeneral/list.h                                 |   59 -
 wmgeneral/misc.c                                 |  164 ---
 wmgeneral/misc.h                                 |    9 -
 wmgeneral/wmgeneral.c                            |  481 --------
 wmgeneral/wmgeneral.h                            |   59 -
 146 files changed, 9448 insertions(+), 5195 deletions(-)

diff --git a/3dObjects/2planes-solid.wmc b/3dObjects/2planes-solid.wmc
deleted file mode 100644
index b884b35..0000000
--- a/3dObjects/2planes-solid.wmc
+++ /dev/null
@@ -1,23 +0,0 @@
-WMCUBE_COORDINATES
-1  -180 -180  180
-2   180 -180  180
-3   180  180  80
-4  -180  180  80
-5  -180 -180 -180
-6   180 -180 -180
-7   180  180 -80
-8  -180  180 -80
-
-WMCUBE_PLANES
-1 2 3
-1 3 4
-2 1 4
-2 4 3
-
-5 6 7
-5 7 8
-6 5 7
-7 5 8
-
-
-
diff --git a/3dObjects/4d.wmc b/3dObjects/4d.wmc
deleted file mode 100644
index 21716d1..0000000
--- a/3dObjects/4d.wmc
+++ /dev/null
@@ -1,59 +0,0 @@
-WMCUBE_COORDINATES
-  1 -51 50 0
-  2 0 50 51
-  3 51 50 0
-  4 0 50 -51
-
-  5 74 0 0
-  6 37 0 64
-  7 -37 0 64
-  8 -74 0 0
-  9 -37 0 -64
-  10 37 0 -64
-
-  11 -51 -50 0
-  12 0 -50 51
-  13 51 -50 0
-  14 0 -50 -51
-
-
-  15 0 100 0
-  16 0 -100 0
-
-  WMCUBE_LINES
-
-  15 1
-  15 2
-  15 3
-  15 4
-
-  1 5
-  1 6
-  1 7
-  2 5
-  2 8
-  2 9
-  3 6
-  3 8
-  3 10
-  4 7
-  4 9
-  4 10
-
-  5 11
-  5 12
-  6 11
-  6 13
-  7 12
-  7 13
-  8 11
-  8 14
-  9 12
-  9 14
-  10 13
-  10 14
-
-  11 16
-  12 16
-  13 16
-  14 16
diff --git a/3dObjects/8star-small.wmc b/3dObjects/8star-small.wmc
deleted file mode 100644
index 35dddf5..0000000
--- a/3dObjects/8star-small.wmc
+++ /dev/null
@@ -1,40 +0,0 @@
-WMCUBE_COORDINATES
-   1  -50 -50 0
-   2   50 -50 0
-   3   50  50 0
-   4  -50  50 0
-   5    0   0  71
-   6    0   0  -71
-   7       0       82      58
-   8       82      0       58
-   9       0       -82     58
-   10      -82     0       58
-   11      0       82      -58
-   12      82      0       -58
-   13      0       -82     -58
-   14      -82     0       -58
-   WMCUBE_LINES
-   2 8
-   2 9
-   2 12
-   2 13
-   4 7
-   4 10
-   4 11
-   4 14
-   1 9
-   1 10
-   1 13
-   1 14
-   3 7
-   3 8
-   3 11
-   3 12
-   5 7
-   5 8
-   5 9
-   5 10
-   6 11
-   6 12
-   6 13
-   6 14
diff --git a/3dObjects/8star.wmc b/3dObjects/8star.wmc
deleted file mode 100644
index c04e721..0000000
--- a/3dObjects/8star.wmc
+++ /dev/null
@@ -1,40 +0,0 @@
-WMCUBE_COORDINATES
-   1  -10 -10 0
-   2   10 -10 0
-   3   10  10 0
-   4  -10  10 0
-   5    0   0  21
-   6    0   0  -21
-   7       0       82      58
-   8       82      0       58
-   9       0       -82     58
-   10      -82     0       58
-   11      0       82      -58
-   12      82      0       -58
-   13      0       -82     -58
-   14      -82     0       -58
-   WMCUBE_LINES
-   2 8
-   2 9
-   2 12
-   2 13
-   4 7
-   4 10
-   4 11
-   4 14
-   1 9
-   1 10
-   1 13
-   1 14
-   3 7
-   3 8
-   3 11
-   3 12
-   5 7
-   5 8
-   5 9
-   5 10
-   6 11
-   6 12
-   6 13
-   6 14
diff --git a/3dObjects/CONTRIBUTE b/3dObjects/CONTRIBUTE
deleted file mode 100644
index 3743655..0000000
--- a/3dObjects/CONTRIBUTE
+++ /dev/null
@@ -1,51 +0,0 @@
-These are the people who have contributed by making objects for wmCube:
-
-FuzzyBear <flung at andrew.cmu.edu>
-
-	- 4d.wmc
-	- crystal.wmc
-	- starcube.wmc
-
-Peter Kokles <kokles at bb.telecom.sk>
-	
-	- celtic.wmc
-	- multicube.wmc
-	- peace.wmc
-	- radioactive.wmc
-	- shield.wmc
-
-Jeff Frasca <phaedrus at thereactor.cleptoscastle.com>
-
-	- spiral.wmc
-
-Axel Ahrens <ahrens at ewerk.de>
-
-	- hyperpyramid.wmc
-
-Aaron Benner <benner at mcn.net>
-	
-	- 8star.wmc
-	- 8star-small.wmc
-
-Per �kergren <akeper-8 at student.luth.se>
-
-	- e.wmc
-	- e2.wmc
-
-Adam Hapworth <adamh at mint.net>
-
-	- foo.wmc
-	- jeep.wmc
-
-tarzeau <tarzeau at space.ch>
-
-	- spaceshuttle.wmc
-
-Rafael Garcia-Suarez <garcia-suarez at kazibao.net>
-
-	- wmlogo.wmc
-
-Nicolas Mieville <nm at altern.org>
-
-	- diamond.wmc
-	- gnustep.wmc
diff --git a/3dObjects/README b/3dObjects/README
deleted file mode 100644
index a5cad75..0000000
--- a/3dObjects/README
+++ /dev/null
@@ -1,54 +0,0 @@
-The object-files to be used with wmCube has the
-following format:
-
-WMCUBE_COORDINATES
-
-1   50  -40   30
-2  -50   50  -30
-3  -20   70  -20
-^   ^    ^    ^
-|   |    |    \__ Z-coordinate relative the center  
-|   |     \______ Y-coordinate relative the center
-|    \___________ X-coordinate relative the center
- \_______________ Coordinate index
-
-
-The indexes must be 1,2,3...n on a object with n coordinates.
-The center of the object is the coordinate the object will 
-revolve around (0,0,0);
-
-The next section is either (case sensitive):
-
-* WMCUBE_LINES
-
-1 2
-2 3
-3 1
-
-These are the coordinates wmCube will draw lines
-between. 
-
-or
-
-* WMCUBE_PLANES
-
-1 2 3
-2 3 1
-1 3 2
-2 1 3
-
-These are the coordinates wmCube will use as corner-
-coordinates for a plane. The tricky part is that the
-plane will be drawn only if you list the coordinates
-making up the plane in clockwise order. In the example
-above, the first two rows making up planes with coordinates
-1 2 3 and 2 3 1 will NOT be drawn until the object 
-has rotated some X degrees but the other two will be
-drawn at once. Its kinda hard to explain, just try and you
-will eventually understand how it works.
-
-
-Done! Save the file with a .wmc suffix (preferably) and try 
-running wmCube with the -o option and it will tell you if 
-something is wrong with the object. Otherwise enjoy and
-remember to send me all the cool objects you create :-)
diff --git a/3dObjects/ball.wmc b/3dObjects/ball.wmc
deleted file mode 100644
index 5a0d8be..0000000
--- a/3dObjects/ball.wmc
+++ /dev/null
@@ -1,83 +0,0 @@
-WMCUBE_COORDINATES
-1  -100 -100  100
-2   100 -100  100
-3   100  100  100
-4  -100  100  100
-5  -100 -100 -100
-6   100 -100 -100
-7   100  100 -100
-8  -100  100 -100
-9   -50 -150  -50
-10   50 -150  -50
-11  150  -50  -50
-12  150   50  -50
-13   50  150  -50
-14  -50  150  -50
-15 -150   50  -50
-16 -150  -50  -50
-17 -150  -50   50
-18  -50 -150   50
-19   50 -150   50
-20  150  -50   50
-21  150   50   50
-22   50  150   50
-23  -50  150   50
-24 -150   50   50
-25  -50  -50  150
-26   50  -50  150
-27   50   50  150
-28  -50   50  150
-29  -50  -50 -150
-30   50  -50 -150
-31   50   50 -150
-32  -50   50 -150
-
-WMCUBE_LINES
-9 10
-10 6
-6 11
-11 12
-12 7
-7 13
-13 14
-14 8
-8 15
-15 16
-16 5
-5 9
-17 1
-1 18
-18 19
-19 2
-2 20
-20 21
-21 3
-3 22
-22 23
-23 4
-4 24
-24 17
-9 18
-10 19
-11 20
-12 21
-13 22
-14 23
-15 24
-16 17
-25 26
-26 27
-27 28
-28 25
-25 1
-26 2
-27 3
-28 4
-29 30
-30 31
-31 32
-32 29
-5 29
-6 30
-7 31
-8 32
diff --git a/3dObjects/celtic.wmc b/3dObjects/celtic.wmc
deleted file mode 100644
index 5f45232..0000000
--- a/3dObjects/celtic.wmc
+++ /dev/null
@@ -1,71 +0,0 @@
-WMCUBE_COORDINATES
-1  -40  40  40
-2  -40 -40  40
-3   40 -40  40
-4   40  40  40
-5  -60  20  20
-6  -60 -20  20
-7   60 -20  20
-8   60  20  20 
-9  -20  60  20
-10 -20 -60  20
-11  20 -60  20
-12  20  60  20
-13 -40  40 -40
-14 -40 -40 -40
-15  40 -40 -40
-16  40  40 -40
-17 -60  20 -20
-18 -60 -20 -20
-19  60 -20 -20
-20  60  20 -20 
-21 -20  60 -20
-22 -20 -60 -20
-23  20 -60 -20
-24  20  60 -20
-25  20  20  60
-26 -20  20  60
-27  20 -20  60
-28 -20 -20  60    
-29  20  20 -60
-30 -20  20 -60
-31  20 -20 -60
-32 -20 -20 -60    
-
-WMCUBE_LINES
-8 18
-20 6
-5 19
-7 17
-8 20
-7 19
-5 17
-6 18
-8 7
-20 19
-5 6
-17 18
-25 26
-26 28
-28 27
-27 25
-29 30
-30 32
-32 31
-31 29
-25 32
-28 29
-26 31
-27 30
-9 23
-11 21
-10 24
-12 22
-24 12
-23 11
-9 21
-10 22
-11 10
-9 12
-23 22
-24 21
diff --git a/3dObjects/cross.wmc b/3dObjects/cross.wmc
deleted file mode 100644
index 72e9cf6..0000000
--- a/3dObjects/cross.wmc
+++ /dev/null
@@ -1,63 +0,0 @@
-WMCUBE_COORDINATES
-1   -50  -50   50
-2    50  -50   50
-3    50   50   50
-4   -50   50   50
-5   -50  -50  -50
-6    50  -50  -50
-7    50   50  -50
-8   -50   50  -50
-9   -50 -150  -50
-10   50 -150  -50
-11  150  -50  -50
-12  150   50  -50
-13   50  150  -50
-14  -50  150  -50
-15 -150   50  -50
-16 -150  -50  -50
-17 -150  -50   50
-18  -50 -150   50
-19   50 -150   50
-20  150  -50   50
-21  150   50   50
-22   50  150   50
-23  -50  150   50
-24 -150   50   50
-
-WMCUBE_LINES
-1 5
-2 6
-7 3
-8 4
-9 10
-10 6
-6 11
-11 12
-12 7
-7 13
-13 14
-14 8
-8 15
-15 16
-16 5
-5 9
-17 1
-1 18
-18 19
-19 2
-2 20
-20 21
-21 3
-3 22
-22 23
-23 4
-4 24
-24 17
-9 18
-10 19
-11 20
-12 21
-13 22
-14 23
-15 24
-16 17
diff --git a/3dObjects/cross2.wmc b/3dObjects/cross2.wmc
deleted file mode 100644
index 61b5a39..0000000
--- a/3dObjects/cross2.wmc
+++ /dev/null
@@ -1,51 +0,0 @@
-WMCUBE_COORDINATES
-1   -50  -50   50
-2    50  -50   50
-3    50   50   50
-4   -50   50   50
-5   -50  -50  -50
-6    50  -50  -50
-7    50   50  -50
-8   -50   50  -50
-9   -50 -150  -50
-10   50 -150  -50
-11  150  -50  -50
-12  150   50  -50
-13   50  150  -50
-14  -50  150  -50
-15 -150   50  -50
-16 -150  -50  -50
-17 -150  -50   50
-18  -50 -150   50
-19   50 -150   50
-20  150  -50   50
-21  150   50   50
-22   50  150   50
-23  -50  150   50
-24 -150   50   50
-
-WMCUBE_LINES
-9 10
-10 6
-6 11
-11 12
-12 7
-7 13
-13 14
-14 8
-8 15
-15 16
-16 5
-5 9
-17 1
-1 18
-18 19
-19 2
-2 20
-20 21
-21 3
-3 22
-22 23
-23 4
-4 24
-24 17
diff --git a/3dObjects/cross3.wmc b/3dObjects/cross3.wmc
deleted file mode 100644
index 6916934..0000000
--- a/3dObjects/cross3.wmc
+++ /dev/null
@@ -1,95 +0,0 @@
-WMCUBE_COORDINATES
-1   -50  -50   50
-2    50  -50   50
-3    50   50   50
-4   -50   50   50
-5   -50  -50  -50
-6    50  -50  -50
-7    50   50  -50
-8   -50   50  -50
-9   -50 -150  -50
-10   50 -150  -50
-11  150  -50  -50
-12  150   50  -50
-13   50  150  -50
-14  -50  150  -50
-15 -150   50  -50
-16 -150  -50  -50
-17 -150  -50   50
-18  -50 -150   50
-19   50 -150   50
-20  150  -50   50
-21  150   50   50
-22   50  150   50
-23  -50  150   50
-24 -150   50   50
-25  -50  -50  150
-26   50  -50  150
-27   50   50  150
-28  -50   50  150
-29  -50  -50 -150
-30   50  -50 -150
-31   50   50 -150
-32  -50   50 -150
-
-WMCUBE_LINES
-1 5
-2 6
-7 3
-8 4
-9 10
-10 6
-6 11
-11 12
-12 7
-7 13
-13 14
-14 8
-8 15
-15 16
-16 5
-5 9
-17 1
-1 18
-18 19
-19 2
-2 20
-20 21
-21 3
-3 22
-22 23
-23 4
-4 24
-24 17
-9 18
-10 19
-11 20
-12 21
-13 22
-14 23
-15 24
-16 17
-25 26
-26 27
-27 28
-28 25
-25 1
-26 2
-27 3
-28 4
-5 6
-6 7
-7 8
-8 5
-29 30
-30 31
-31 32
-32 29
-5 29
-6 30
-7 31
-8 32
-1 2
-2 3
-3 4 
-4 1
diff --git a/3dObjects/crystal.wmc b/3dObjects/crystal.wmc
deleted file mode 100644
index e2341ce..0000000
--- a/3dObjects/crystal.wmc
+++ /dev/null
@@ -1,108 +0,0 @@
-WMCUBE_COORDINATES
-  1 0 0 0
-
-  2 150 0 0
-  3 0 150 0
-  4 0 0 150
-  5 -150 0 0
-  6 0 -150 0
-  7 0 0 -150
-
-  8 100 -30 -30
-  9 100 -30 30
-  10 100 30 30
-  11 100 30 -30
-
-  12 30 100 -30
-  13 30 100 30
-  14 -30 100 30
-  15 -30 100 -30
-
-  16 -100 -30 -30
-  17 -100 -30 30
-  18 -100 30 30
-  19 -100 30 -30
-
-  20 30 -100 -30
-  21 30 -100 30
-  22 -30 -100 30
-  23 -30 -100 -30
-
-  24 30 -30 100
-  25 30 30 100
-  26 -30 30 100
-  27 -30 -30 100
-
-  28 30 -30 -100
-  29 30 30 -100
-  30 -30 30 -100
-  31 -30 -30 -100
-
-  WMCUBE_LINES
-
-  1 11
-  1 8
-  1 9
-  1 10
-
-  1 15
-  1 12
-  1 13
-  1 14
-
-  1 18
-  1 19
-  1 16
-  1 17
-
-  1 20
-  1 21
-  1 22
-  1 23
-
-  1 27
-  1 24
-  1 25
-  1 26
-
-  1 31
-  1 28
-  1 29
-  1 30
-
-  2 8
-  2 9
-  2 10
-  2 11
-
-  3 15
-  3 12
-  3 13
-  3 14
-
-  4 27
-  4 24
-  4 25
-  4 26
-
-  5 16
-  5 17
-  5 18
-  5 19
-
-  6 20
-  6 21
-  6 22
-  6 23
-
-  7 31
-  7 28
-  7 29
-  7 30
-
-  1 2
-  1 3
-  1 4
-  1 5
-  1 6
-  1 7
diff --git a/3dObjects/cube.wmc b/3dObjects/cube.wmc
deleted file mode 100644
index a55e975..0000000
--- a/3dObjects/cube.wmc
+++ /dev/null
@@ -1,24 +0,0 @@
-WMCUBE_COORDINATES
-1  -180 -180  180
-2   180 -180  180
-3   180  180  180
-4  -180  180  180
-5  -180 -180 -180
-6   180 -180 -180
-7   180  180 -180
-8  -180  180 -180
-
-WMCUBE_LINES
-1 2 
-2 3 
-3 4
-4 1
-5 6
-6 7
-7 8
-8 5
-1 5
-2 6
-3 7
-4 8
-
diff --git a/3dObjects/diamond.wmc b/3dObjects/diamond.wmc
deleted file mode 100644
index 06347f8..0000000
--- a/3dObjects/diamond.wmc
+++ /dev/null
@@ -1,66 +0,0 @@
-WMCUBE_COORDINATES
-
-1  -50  0   0    
-2  -35  0  35    
-3    0  0  50    
-4   35  0  35    
-5   50  0   0    
-6   35  0 -35    
-7    0  0 -50    
-8  -35  0 -35    
-
-9  -32  10  13   
-10 -13  10  32   
-11  13  10  32   
-12  32  10  13   
-13  32  10 -13   
-14  13  10 -32   
-15 -13  10 -32   
-16 -32  10 -13   
-
-17    0  -60  0   
-WMCUBE_LINES
-
-1 2
-2 3
-3 4
-4 5
-5 6
-6 7
-7 8
-8 1
-
-9 10
-10 11
-11 12
-12 13
-13 14
-14 15
-15 16
-16 9
-
-1 9
-1 8
-2 10
-2 9
-3 11
-3 10
-4 12
-4 11
-5 13
-5 12
-6 14
-6 13
-7 15
-7 14
-8 16
-8 15
-
-17 1
-17 2
-17 3
-17 4
-17 5
-17 6
-17 7
-17 8
diff --git a/3dObjects/e.wmc b/3dObjects/e.wmc
deleted file mode 100644
index 7c78070..0000000
--- a/3dObjects/e.wmc
+++ /dev/null
@@ -1,69 +0,0 @@
-WMCUBE_COORDINATES
-1  -60 -120  30
-2   80 -120  30
-3   80 -60  30
-4    0 -60  30
-5    0 -20  30
-6   40 -20  30
-7   40  20  30
-8    0  20  30
-9    0  60  30
-10  80  60  30
-11  80  120  30
-12 -60  120  30
-13 -60 -120 -30
-14  80 -120 -30
-15  80 -60 -30
-16   0 -60 -30
-17   0 -20 -30
-18  40 -20 -30
-19  40  20 -30
-20   0  20 -30
-21   0  60 -30
-22  80  60 -30
-23  80  120 -30
-24  -60 120 -30
-
-
-WMCUBE_LINES
-1 2
-2 3
-3 4
-4 5
-5 6
-6 7
-7 8
-8 9
-9 10
-10 11
-11 12
- 1 12
-13 14
-14 15
-15 16
-16 17
-17 18
-18 19
-19 20
-20 21
-21 22
-22 23
-23 24
-13 24
-
-1 13
-2 14
-3 15
-4 16 
-5 17
-6 18
-7 19
-8 20 
-9 21
-10 22
-11 23 
-12 24
-
-
-
-
diff --git a/3dObjects/e2.wmc b/3dObjects/e2.wmc
deleted file mode 100644
index cd80bd6..0000000
--- a/3dObjects/e2.wmc
+++ /dev/null
@@ -1,160 +0,0 @@
-WMCUBE_COORDINATES
-1  -60 -120  30
-2   80 -120  30
-3   80 -60  30
-4    0 -60  30
-5    0 -20  30
-6   40 -20  30
-7   40  20  30
-8    0  20  30
-9    0  60  30
-10  80  60  30
-11  80  120  30
-12 -60  120  30
-13 -60 -120 -30
-14  80 -120 -30
-15  80 -60 -30
-16   0 -60 -30
-17   0 -20 -30
-18  40 -20 -30
-19  40  20 -30
-20   0  20 -30
-21   0  60 -30
-22  80  60 -30
-23  80  120 -30
-24  -60 120 -30
-
-25 -60 -10 0
-26 -60 -40 0
-27 -80 -10 0
-28 -80 -40 0
-29 -80 -10 -15
-30 -80 -40 -15
-31 -80 -20 -20
-32 -80 -30 -20
-33 -80 -20 -30
-34 -80 -30 -30
-
-35 -60 -60  0
-36 -60 -90 0
-37 -80 -60  0
-38 -80 -90 0
-39 -80 -60 -15
-40 -80 -90 -15
-41 -80 -70 -20
-42 -80 -80 -20
-43 -80 -70 -30
-44 -80 -80 -30
-
-45 -60 10 0
-46 -60 40 0
-47 -80 10 0
-48 -80 40 0
-49 -80 10 -15
-50 -80 40 -15
-51 -80 20 -20
-52 -80 30 -20
-53 -80 20 -30
-54 -80 30 -30
-
-55 -60 60  0
-56 -60 90 0
-57 -80 60  0
-58 -80 90 0
-59 -80 60 -15
-60 -80 90 -15
-61 -80 70 -20
-62 -80 80 -20
-63 -80 70 -30
-64 -80 80 -30
-WMCUBE_LINES
-1 2
-2 3
-3 4
-4 5
-5 6
-6 7
-7 8
-8 9
-9 10
-10 11
-11 12
- 1 12
-13 14
-14 15
-15 16
-16 17
-17 18
-18 19
-19 20
-20 21
-21 22
-22 23
-23 24
-13 24
-1 13
-2 14
-3 15
-4 16 
-5 17
-6 18
-7 19
-8 20 
-9 21
-10 22
-11 23 
-12 24
-
-25 26
-27 28
-25 27
-26 28
-27 29
-28 30
-29 31
-30 32
-31 33
-32 34
-33 34
-
-
-35 36
-37 38
-35 37
-36 38
-37 39
-38 40
-39 41
-40 42
-41 43
-42 44
-43 44
-
-45 46
-47 48
-45 47
-46 48
-47 49
-48 50
-49 51
-50 52
-51 53
-52 54
-53 54
-
-55 56
-57 58
-55 57
-56 58
-57 59
-58 60
-59 61
-60 62
-61 63
-62 64
-63 64
-
-
-
-
-
diff --git a/3dObjects/foo.wmc b/3dObjects/foo.wmc
deleted file mode 100644
index 04add8f..0000000
--- a/3dObjects/foo.wmc
+++ /dev/null
@@ -1,149 +0,0 @@
-WMCUBE_COORDINATES
-   1 -190 110 50
-   2 -190 -90 50
-   3 -160 -90 50
-   4 -160 20 50
-   5 -90 20 50
-   6 -90 50 50
-   7 -160 50 50
-   8 -160 80 50
-   9 -90 80 50
-   10 -90 110 50
-
-   11 -190 110 0
-   12 -190 -90 0
-   13 -160 -90 0
-   14 -160 20 0
-   15 -90 20 0
-   16 -90 50 0
-   17 -160 50 0
-   18 -160 80 0
-   19 -90 80 0
-   20 -90 110 0
-
-
-   21 -50 110 50
-   22 60 110 50 
-   23 60 -90 50
-   24 -50 -90 50
-   25 -20 -50 50
-   26 40 -50 50
-   27 40 70 50
-   28 -20 70 50
-
-   29 -50 110 0
-   30 60 110 0 
-   31 60 -90 0
-   32 -50 -90 0
-   33 -20 -50 0
-   34 20 -50 0
-   35 20 70 0
-   36 -20 70 0
-
-
-   37 110 110 50
-   38 210 110 50
-   39 210 -90 50
-   40 110 -90 50
-   41 130 -50 50
-   42 190 -50 50
-   43 190 70 50
-   44 130 70 50
-
-   45 110 110 0
-   46 210 110 0
-   47 210 -90 0
-   48 110 -90 0
-   49 130 -50 0
-   50 190 -50 0
-   51 190 70 0
-   52 130 70 0
-
-
-   WMCUBE_LINES
-   1 2
-   2 3
-   3 4
-   4 5
-   5 6
-   6 7
-   7 8
-   8 9
-   9 10
-   10 1
-
-   11 12
-   12 13
-   13 14
-   14 15
-   15 16
-   16 17
-   17 18
-   18 19
-   19 20
-   20 11
-
-   1 11
-   2 12
-   3 13
-   4 14
-   5 15
-   6 16
-   7 17
-   8 18
-   9 19
-   10 20
-
-   21 22
-   22 23
-   23 24
-   24 21
-   25 26
-   26 27
-   27 28
-   28 25
-
-   29 30
-   30 31
-   31 32
-   32 29
-   33 34
-   34 35
-   35 36
-   36 33
-
-   21 29
-   22 30
-   23 31
-   24 32
-   25 33
-   26 34
-   27 35
-   28 36
-
-   37 38
-   38 39
-   39 40
-   40 37
-   41 42
-   42 43
-   43 44
-   44 41
-
-   45 46
-   46 47
-   47 48
-   48 45
-   49 50
-   50 51
-   51 52
-   52 49
-
-   37 45
-   38 46
-   39 47
-   40 48
-   41 49
-   42 50
-   43 51
-   44 52
diff --git a/3dObjects/gnustep.wmc b/3dObjects/gnustep.wmc
deleted file mode 100644
index 5884a86..0000000
--- a/3dObjects/gnustep.wmc
+++ /dev/null
@@ -1,110 +0,0 @@
-WMCUBE_COORDINATES
-
-1 50  0 -10
-2 46 19 -10
-3 35 35 -10
-4 19 46 -10
-5  0 50 -10
-6 -19 46 -10
-7 -35 35 -10
-8 -46 19 -10
-9 -50 0 -10
-10 -46 -19 -10
-11 -35 -35 -10
-12 -19 -46 -10
-13   0 -50 -10
-14  19 -46 -10
-15  35 -35 -10
-16  46 -19 -10
-17 -25 35 -10
-18 -25  0 -10
-19  25  0 -10
-20  25 -35 -10
-
-21 50  0 10
-22 46 19 10
-23 35 35 10
-24 19 46 10
-25  0 50 10 
-26 -19 46 10
-27 -35 35 10
-28 -46 19 10
-29 -50 0 10
-30 -46 -19 10
-31 -35 -35 10
-32 -19 -46 10
-33   0 -50 10
-34  19 -46 10
-35  35 -35 10
-36  46 -19 10
-37 -25 35 10
-38 -25  0 10
-39  25  0 10
-40  25 -35 10
-WMCUBE_LINES
-
-1 2
-2 3
-3 4
-4 5
-5 6
-6 7
-7 8
-8 9
-9 10
-10 11
-11 12
-12 13
-13 14
-14 15
-15 16
-16 1
-7 17
-17 18
-18 19
-19 20
-20 15
-
-21 22
-22 23
-23 24
-24 25
-25 26
-26 27
-27 28
-28 29
-29 30
-30 31
-31 32
-32 33
-33 34
-34 35
-35 36
-36 21
-27 37
-37 38
-38 39
-39 40
-40 35
-
-17 37
-18 38
-19 39
-20 40
-
-1 21
-2 22
-3 23
-4 24
-5 25
-6 26
-7 27
-8 28
-9 29
-10 30
-11 31
-12 32
-13 33
-14 34
-15 35
-16 36
diff --git a/3dObjects/hyperpyramid.wmc b/3dObjects/hyperpyramid.wmc
deleted file mode 100644
index 588d802..0000000
--- a/3dObjects/hyperpyramid.wmc
+++ /dev/null
@@ -1,54 +0,0 @@
-WMCUBE_COORDINATES
-1	300	0	0
-2	-150	260	0
-3	-150	-260	0
-4	50	87	0
-5	-100	0	0
-6	50	-87	0
-7	0	0	90
-8	50	87	-250
-9	-100	0	-250
-10	50	-87	-250
-11	0	0	-90
-12	100	0	-50
-13	-87	100	-50
-14	-87	-100	-50
-
-WMCUBE_LINES
-1 4
-4 2
-2 5
-5 3
-3 6
-6 1
-1 7
-2 7
-3 7
-4 7
-5 7
-6 7
-4 8
-5 9
-6 10
-8 11
-9 11
-10 11
-1 12
-8 12
-10 12
-4 12
-6 12
-11 12
-4 13
-2 13
-5 13
-8 13
-9 13
-11 13
-5 14
-3 14
-6 14
-11 14
-9 14
-10 14
-
diff --git a/3dObjects/jeep.wmc b/3dObjects/jeep.wmc
deleted file mode 100644
index 5fb8f1d..0000000
--- a/3dObjects/jeep.wmc
+++ /dev/null
@@ -1,157 +0,0 @@
-WMCUBE_COORDINATES
-   1 -150 -20 0
-   2 -150 50 0
-   3 -40 50 0
-   4 -40 20 0
-   5 30 20 0
-   6 30 60 0 
-   7 20 130 0
-   8 30 50 0
-   9 160 50 0 
-   10 160 -20 0
-   11 140 -20 0
-   12 130 0 0 
-   13 90 0 0 
-   14 80 -20 0
-   15 80 -40 0
-   16 100 -60 0
-   17 110 -60 0 
-   18 140 -40 0
-   19 -70 -20 0
-   20 -70 -40 0
-   21 -90 -60 0
-   22 -110 -60 0
-   23 -130 -40 0
-   24 -130 -20 0
-   25 -120 0 0
-   26 -80 0 0
-   27 -150 50 0
-   28 -80 120 0
-   29 -80 50 0 
-   30 90 40 0
-   31 170 40 0 
-   32 180 30 0 
-   33 180 10 0 
-   34 160 10 0
-   35 80 -10 0
-   36 -80 -10 0
-
-   37 -150 -20 100
-   38 -150 50 100
-   39 -40 50 100
-   40 -40 20 100
-   41 30 20 100
-   42 30 60 100 
-   43 20 130 100
-   44 30 50 100
-   45 160 50 100 
-   46 160 -20 100
-   47 140 -20 100
-   48 130 0 100 
-   49 90 0 100 
-   50 80 -20 100
-   51 80 -40 100
-   52 100 -60 100
-   53 110 -60 100 
-   54 140 -40 100
-   55 -70 -20 100
-   56 -70 -40 100
-   57 -90 -60 100
-   58 -110 -60 100
-   59 -130 -40 100
-   60 -130 -20 100
-   61 -120 0 100
-   62 -80 0 100
-   63 -150 50 100
-   64 -80 120 100
-   65 -80 50 100 
-   66 90 40 100
-   67 170 40 100 
-   68 180 30 100 
-   69 180 10 100 
-   70 160 10 100
-   71 80 -10 100
-   72 -80 -10 100
-
-   WMCUBE_LINES
-   1 2
-   2 3
-   3 4
-   4 5
-   5 6
-   6 7 
-   8 9 
-   9 10
-   10 11
-   11 12
-   12 13
-   13 14
-   14 15
-   15 16
-   16 17
-   17 18
-   35 36
-   19 20 
-   20 21
-   21 22
-   22 23
-   23 24
-   24 1
-   24 25
-   25 26
-   27 28
-   28 29
-   30 31
-   31 32
-   32 33
-   33 34
-   18 11
-
-   37 38
-   38 39 
-   39 40
-   40 41
-   41 42
-   42 43
-   44 45
-   45 46
-   46 47
-   47 48
-   48 49
-   49 50 
-   50 51
-   51 52
-   52 53
-   53 54
-   71 72
-   55 56
-   56 57
-   57 58
-   58 59
-   59 60
-   60 37
-   60 61
-   61 62
-   63 64
-   64 65
-   66 67
-   67 68
-   68 69
-   69 70
-   54 47
-
-   1 37
-   2 38
-   3 39
-   4 40
-   5 41
-   6 42
-   7 43
-   8 44
-   9 45
-   10 46
-   11 47
-   35 71
-   36 72
-   24 60
-   28 64
diff --git a/3dObjects/multicube.wmc b/3dObjects/multicube.wmc
deleted file mode 100644
index ba05439..0000000
--- a/3dObjects/multicube.wmc
+++ /dev/null
@@ -1,83 +0,0 @@
-WMCUBE_COORDINATES
-1  -40  40  40
-2  -40 -40  40
-3   40 -40  40
-4   40  40  40
-5  -60  20  20
-6  -60 -20  20
-7   60 -20  20
-8   60  20  20 
-9  -20  60  20
-10 -20 -60  20
-11  20 -60  20
-12  20  60  20
-13 -40  40 -40
-14 -40 -40 -40
-15  40 -40 -40
-16  40  40 -40
-17 -60  20 -20
-18 -60 -20 -20
-19  60 -20 -20
-20  60  20 -20 
-21 -20  60 -20
-22 -20 -60 -20
-23  20 -60 -20
-24  20  60 -20
-25  20  20  60
-26 -20  20  60
-27  20 -20  60
-28 -20 -20  60    
-29  20  20 -60
-30 -20  20 -60
-31  20 -20 -60
-32 -20 -20 -60    
-
-WMCUBE_LINES
-1 2
-2 3
-3 4
-4 1
-5 6
-6 7
-7 8
-8 5
-9 10
-10 11
-11 12
-12 9
-13 14
-14 15
-15 16
-16 13
-1 13
-2 14
-3 15
-4 16
-17 18
-18 19
-19 20
-20 17
-8 20
-5 17
-6 18
-7 19
-21 22
-22 23
-23 24
-24 21
-12 24
-23 11
-9 21
-10 22
-25 26
-26 28
-27 28
-27 25
-25 29
-26 30
-28 31
-27 32
-29 30
-30 32
-31 32
-31 29
diff --git a/3dObjects/pyramid.wmc b/3dObjects/pyramid.wmc
deleted file mode 100644
index 99a618c..0000000
--- a/3dObjects/pyramid.wmc
+++ /dev/null
@@ -1,16 +0,0 @@
-WMCUBE_COORDINATES
-1  -150 -150 -150
-2   150 -150 -150
-3   150  150 -150
-4  -150  150 -150
-5     0    0  250
-WMCUBE_LINES
-1 2
-2 3 
-3 4
-4 1
-1 5
-2 5
-3 5
-4 5
-
diff --git a/3dObjects/shield.wmc b/3dObjects/shield.wmc
deleted file mode 100644
index 3451f45..0000000
--- a/3dObjects/shield.wmc
+++ /dev/null
@@ -1,197 +0,0 @@
-WMCUBE_COORDINATES
-1      -76     112     -10
-2       76     112     -10
-3      -10      99     -10
-4       10      99     -10
-5       10      75     -10
-6       33      75     -10
-7       33      55     -10
-8       10      55     -10
-9      -10      55     -10
-10     -33      55     -10
-11     -33      75     -10
-12     -10      75     -10 
-13     -55      20     -10 
-14     -10      20     -10
-15      10      20     -10
-16      55      20     -10 
-17      55       0     -10
-18      10       0     -10
-19     -10       0     -10
-20     -55       0     -10 
-21     -76       0     -10 
-22     -72     -29     -10
-23     -59     -56     -10 
-24     -34     -79     -10  
-25       0     -89     -10 
-26      35     -79     -10
-27      59     -56     -10
-28      72     -27     -10
-29      76       0     -10
-30     -53     -48     -10
-31     -45     -42     -10
-32     -36     -40     -10
-33     -26     -42     -10
-34     -19     -35     -10
-35     -10     -32     -10
-36       0     -30     -10
-37      10     -32     -10
-38      19     -35     -10
-39      26     -42     -10
-40      36     -40     -10
-41      45     -42     -10
-42      53     -48     -10
-43     -76     112      20
-44      76     112      20
-45     -10      99      20
-46      10      99      20
-47      10      75      20
-48      33      75      20
-49      33      55      20
-50      10      55      20
-51     -10      55      20
-52     -33      55      20
-53     -33      75      20
-54      10      75      20
-55     -55      20      20
-56     -10      20      20
-57      10      20      20
-58      55      20      20
-59      55       0      20
-60      10       0      20
-61     -10       0      20
-62     -55       0      20
-63     -76       0      20
-64     -72     -29      20
-65     -59     -56      20
-66     -34     -79      20
-67       0     -89      20
-68      35     -79      20
-69      59     -56      20
-70      72     -27      20
-71      76       0      20
-72     -53     -48      20
-73     -45     -42      20
-74     -36     -40      20
-75     -26     -42      20
-76     -19     -35      20
-77     -10     -32      20
-78       0     -30      20
-79      10     -32      20
-80      19     -35      20
-81      26     -42      20
-82      36     -40      20
-83      45     -42      20
-84      53     -48      20
-
-
-WMCUBE_LINES
-1 2
-2 29
-29 28
-28 27
-27 26
-26 25 
-25 24
-24 23
-23 22
-22 21
-21 1
-3 4
-4 5
-5 6
-6 7
-7 8
-8 15
-15 16
-16 17
-17 18
-18 37
-35 19
-19 20
-20 13
-13 14
-14 9
-9 10
-10 11
-11 12
-12 3
-23 30
-30 31
-31 32
-32 33
-33 34
-34 35
-35 36
-36 37
-37 38
-38 39
-39 40
-40 41
-41 42
-42 27
-43 44
-44 71
-71 70
-70 69
-69 68
-68 67
-67 66
-66 65
-45 46
-46 47
-47 48
-48 49
-49 50
-50 57
-57 58
-58 59
-59 60
-60 79
-35 61
-61 62
-62 55
-55 56
-56 51
-51 52
-52 53
-53 54
-54 45
-65 72
-72 73
-73 74
-74 75
-75 76
-76 77
-77 78
-78 79
-79 80
-80 81
-81 82
-82 83
-83 84
-84 69
-43 63
-63 64
-64 65
-1 43
-2 44
-3 45
-4 46
-5 47
-6 48
-7 49
-8 50
-15 57
-16 58
-17 59
-18 60
-19 61
-20 62
-13 55
-14 56
-9 51
-10 52
-11 53
-12 54
-67 25
diff --git a/3dObjects/spaceshuttle.wmc b/3dObjects/spaceshuttle.wmc
deleted file mode 100644
index d7b1d1d..0000000
--- a/3dObjects/spaceshuttle.wmc
+++ /dev/null
@@ -1,382 +0,0 @@
-WMCUBE_COORDINATES
-1 -44 0 14
-2 55 0 15
-3 60 0 10
-4 83 0 0
-5 86 0 -3
-6 85 0 -6
-7 77 0 -10
-8 45 0 -12
-9 -44 0 14
-10 -45 0 19
-11 -45 0 19
-12 -82 0 52
-13 -92 0 52
-14 -94 0 51
-15 -80 0 22
-16 -70 0 18
-17 -68 -16 -13
-18 -61 -58 -9
-19 -54 -58 -9
-20 -42 -56 -10
-21 -13 -26 -12
-22 47 -13 -10
-23 -68 16 -13
-24 -61 58 -9
-25 -54 58 -9
-26 -42 55 -10
-27 -13 27 -12
-28 47 13 -10
-29 45 -13 -14
-30 45 -13 9
-31 45 -9 13
-32 45 -4 15
-33 45 4 15
-34 45 9 13
-35 45 13 9
-36 45 13 -14
-37 -45 -13 -14
-38 -45 -13 9
-39 -45 -9 13
-40 -45 -4 15
-41 -45 4 15
-42 -45 9 13
-43 -45 13 9
-44 -45 13 -14
-45 45 13 -4
-46 48 13 -4
-47 78 7 -4
-48 85 3 -4
-49 86 0 -4
-50 45 -13 -4
-51 48 -13 -4
-52 78 -7 -4
-53 85 -3 -4
-54 86 0 -4
-55 45 13 -12
-56 -42 13 -15
-57 -72 13 -14
-58 45 -13 -12
-59 -42 -13 -15
-60 -72 -13 -14
-61 45 13 -12
-62 45 -13 -12
-63 -72 13 -14
-64 -72 -13 -14
-65 -72 14 -14
-66 -84 14 -13
-67 -72 14 -12
-68 -72 -14 -14
-69 -84 -14 -13
-70 -72 -14 -12
-71 -84 14 -13
-72 -84 -14 -13
-73 -72 16 -12
-74 -70 14 4
-75 -69 2 16
-76 -69 -2 16
-77 -70 -15 4
-78 -72 -16 -12
-79 -56 57 -9
-80 -56 16 -13
-81 -56 -57 -9
-82 -56 -16 -13
-83 -93 0 48
-84 -87 0 48
-85 -70 0 23
-86 -80 0 23
-87 -69 15 4
-88 -69 18 12
-89 -69 10 20
-90 -69 2 16
-91 -69 -15 4
-92 -69 -19 12
-93 -69 -11 20
-94 -69 -2 16
-95 -69 15 4
-96 -44 13 5
-97 -69 2 16
-98 -44 2 14
-99 -69 18 12
-100 -52 18 13
-101 -69 10 20
-102 -52 10 21
-103 -52 18 13
-104 -52 -10 21
-105 -52 18 13
-106 -44 13 5
-107 -52 10 21
-108 -44 2 14
-109 -69 -15 4
-110 -44 -13 5
-111 -69 -2 16
-112 -44 -2 14
-113 -69 -19 12
-114 -52 -19 13
-115 -69 -11 20
-116 -52 -10 21
-117 -52 -19 13
-118 -52 -10 21
-119 -52 -19 13
-120 -44 -13 5
-121 -52 -10 21
-122 -44 -2 14
-123 -80 0 16
-124 -81 3 14
-125 -82 3 8
-126 -83 0 6
-127 -82 -3 8
-128 -81 -3 14
-129 -80 0 16
-130 -80 0 16
-131 -69 0 12
-132 -83 0 6
-133 -70 0 4
-134 -82 3 11
-135 -69 2 8
-136 -82 -3 11
-137 -69 -2 -8
-138 -69 0 12
-139 -69 2 8
-140 -70 0 4
-141 -69 -2 8
-142 -69 0 12
-143 -83 8 2
-144 -84 13 -1
-145 -85 13 -6
-146 -85 8 -9
-147 -85 3 -6
-148 -84 3 -1
-149 -83 8 2
-150 -83 8 2
-151 -72 7 -2
-152 -85 8 -9
-153 -73 7 -9
-154 -84 13 -3
-155 -73 10 -5
-156 -84 3 -3
-157 -73 4 -5
-158 -72 7 -2
-159 -73 10 -5
-160 -73 7 -9
-161 -73 4 -5
-162 -72 7 -2
-163 -83 -8 2
-164 -84 -13 -1
-165 -85 -13 -6
-166 -85 -8 -9
-167 -85 -4 -6
-168 -84 -4 -1
-169 -83 -8 2
-170 -83 -8 2
-171 -72 -7 -2
-172 -85 -8 -9
-173 -73 -7 -9
-174 -84 -13 -3
-175 -73 -10 -5
-176 -84 -4 -3
-177 -73 -4 -5
-178 -72 -7 -2
-179 -73 -10 -5
-180 -73 -7 -9
-181 -73 -4 -5
-182 -72 -7 -2
-183 61 2 10
-184 60 5 10
-185 57 5 13
-186 58 3 13
-187 61 2 10
-188 61 -2 10
-189 60 -5 10
-190 57 -5 13
-191 58 -3 13
-192 61 -2 10
-193 60 5 10
-194 57 9 8
-195 55 7 12
-196 57 5 13
-197 60 -5 10
-198 57 -9 8
-199 55 -7 12
-200 57 -5 13
-201 57 9 8
-202 53 10 9
-203 53 7 12
-204 55 7 12
-205 57 -9 8
-206 53 -10 9
-207 53 -7 12
-208 55 -7 12
-209 45 13 5
-210 -45 13 4
-211 45 -13 5
-212 -45 -13 4
-213 45 13 -12
-214 48 13 -12
-215 78 6 -9
-216 85 3 -5
-217 86 0 -4
-218 45 -13 -12
-219 48 -13 -12
-220 78 -7 -9
-221 85 -3 -5
-222 86 0 -4
-223 0 0 0
-WMCUBE_LINES
-2 1
-3 2
-4 3
-5 4
-6 5
-7 6
-8 7
-10 9
-12 11
-13 12
-14 13
-15 14
-16 15
-18 17
-19 18
-20 19
-21 20
-22 21
-24 23
-25 24
-26 25
-27 26
-28 27
-30 29
-31 30
-32 31
-33 32
-34 33
-35 34
-36 35
-38 37
-39 38
-40 39
-41 40
-42 41
-43 42
-44 43
-46 45
-47 46
-48 47
-49 48
-51 50
-52 51
-53 52
-54 53
-56 55
-57 56
-59 58
-60 59
-62 61
-64 63
-66 65
-67 66
-69 68
-70 69
-72 71
-74 73
-75 74
-76 75
-77 76
-78 77
-80 79
-82 81
-84 83
-85 84
-86 85
-88 87
-89 88
-90 89
-92 91
-93 92
-94 93
-96 95
-98 97
-100 99
-102 101
-104 103
-106 105
-108 107
-110 109
-112 111
-114 113
-116 115
-118 117
-120 119
-122 121
-124 123
-125 124
-126 125
-127 126
-128 127
-129 128
-131 130
-133 132
-135 134
-137 136
-139 138
-140 139
-141 140
-142 141
-144 143
-145 144
-146 145
-147 146
-148 147
-149 148
-151 150
-153 152
-155 154
-157 156
-159 158
-160 159
-161 160
-162 161
-164 163
-165 164
-166 165
-167 166
-168 167
-169 168
-171 170
-173 172
-175 174
-177 176
-179 178
-180 179
-181 180
-182 181
-184 183
-185 184
-186 185
-187 186
-189 188
-190 189
-191 190
-192 191
-194 193
-195 194
-196 195
-198 197
-199 198
-200 199
-202 201
-203 202
-204 203
-206 205
-207 206
-208 207
-210 209
-212 211
-214 213
-215 214
-216 215
-217 216
-219 218
-220 219
-221 220
\ No newline at end of file
diff --git a/3dObjects/spiral.wmc b/3dObjects/spiral.wmc
deleted file mode 100644
index 0af2d4f..0000000
--- a/3dObjects/spiral.wmc
+++ /dev/null
@@ -1,49 +0,0 @@
-WMCUBE_COORDINATES
-
-1    80    0    0
-2     0  -90   25
-3  -100    0   50
-4     0  110   75
-5   120    0  100
-6     0 -130  125
-7  -140    0  150
-8     0  150  175
-9   160    0  200
-10    0   70  -25
-11  -60    0  -50
-12    0  -50  -75
-13   40    0 -100
-14    0   30 -125
-15  -20    0 -150
-16    0  -10 -175
-17    0    0 -200
-18    0 -160  200
-19 -160    0  200
-20    0  160  200
-
-WMCUBE_LINES
-
-1 2
-2 3
-3 4
-4 5
-5 6
-6 7 
-7 8
-8 9
-1 10
-10 11
-11 12
-12 13
-13 14
-14 15
-15 16
-16 17
-17 9
-17 18
-17 19
-17 20
-9 18
-18 19
-19 20
-20 9
diff --git a/3dObjects/star.wmc b/3dObjects/star.wmc
deleted file mode 100644
index 1fd0b24..0000000
--- a/3dObjects/star.wmc
+++ /dev/null
@@ -1,95 +0,0 @@
-WMCUBE_COORDINATES
-1   -90  -90   90
-2    90  -90   90
-3    90   90   90
-4   -90   90   90
-5   -90  -90  -90
-6    90  -90  -90
-7    90   90  -90
-8   -90   90  -90
-9   -10 -350  -10
-10   10 -350  -10
-11  350  -10  -10
-12  350   10  -10
-13   10  350  -10
-14  -10  350  -10
-15 -350   10  -10
-16 -350  -10  -10
-17 -350  -10   10
-18  -10 -350   10
-19   10 -350   10
-20  350  -10   10
-21  350   10   10
-22   10  350   10
-23  -10  350   10
-24 -350   10   10
-25  -10  -10  350
-26   10  -10  350
-27   10   10  350
-28  -10   10  350
-29  -10  -10 -350
-30   10  -10 -350
-31   10   10 -350
-32  -10   10 -350
-
-WMCUBE_LINES
-1 5
-2 6
-7 3
-8 4
-9 10
-10 6
-6 11
-11 12
-12 7
-7 13
-13 14
-14 8
-8 15
-15 16
-16 5
-5 9
-17 1
-1 18
-18 19
-19 2
-2 20
-20 21
-21 3
-3 22
-22 23
-23 4
-4 24
-24 17
-9 18
-10 19
-11 20
-12 21
-13 22
-14 23
-15 24
-16 17
-25 26
-26 27
-27 28
-28 25
-25 1
-26 2
-27 3
-28 4
-5 6
-6 7
-7 8
-8 5
-29 30
-30 31
-31 32
-32 29
-5 29
-6 30
-7 31
-8 32
-1 2
-2 3
-3 4 
-4 1
diff --git a/3dObjects/starcube.wmc b/3dObjects/starcube.wmc
deleted file mode 100644
index a7bc2df..0000000
--- a/3dObjects/starcube.wmc
+++ /dev/null
@@ -1,69 +0,0 @@
-WMCUBE_COORDINATES
-  1  -100 -100  100
-  2   100 -100  100
-  3   100  100  100
-  4  -100  100  100
-  5  -100 -100 -100
-  6   100 -100 -100
-  7   100  100 -100
-  8  -100  100 -100
-
-  9  75 0 0
-  10 0 75 0
-  11 0 0 75
-  12 -75 0 0
-  13 0 -75 0
-  14 0 0 -75
-
-  15  -75 -75  75
-  16   75 -75  75
-  17   75  75  75
-  18  -75  75  75
-  19  -75 -75 -75
-  20   75 -75 -75
-  21   75  75 -75
-  22  -75  75 -75
-
-  WMCUBE_LINES
-  1 2
-  2 3
-  3 4
-  4 1
-  5 6
-  6 7
-  7 8
-  8 5
-  1 5
-  2 6
-  3 7
-  4 8
-
-  9 15
-  9 18
-  9 19
-  9 22
-
-  10 15
-  10 16
-  10 19
-  10 20
-
-  11 19
-  11 20
-  11 21
-  11 22
-
-  12 16
-  12 17
-  12 20
-  12 21
-
-  13 17
-  13 18
-  13 21
-  13 22
-
-  14 15
-  14 16
-  14 17
-  14 18
diff --git a/CHANGES b/CHANGES
index 5b38c4e..730b2fa 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,24 @@
-wmcube 0.98:
+wmCube 0.99-pre1
+	* Rewrite to C++ using the wmApp toolkit.
+		- Full color depth
+		- User definable for/background colors 
+		- User definable shading
+		- New window layout added with cpu meter
+		- Switch to classic (simple) layout with a mouseclick
+	* Uses the CpuMonitorCC library (also in pre-stage)
+	* Place lightsource with mouseclick or have it move around by itself
+	* Solid wireframe mode added
+	* "Reflex" effect
+	* 3- and 5-button mouse (mouse wheel support)
+	* wmc file format updates
+		- Both planes and lines in the same file (preferably even)
+		- No specific order of sections is required
+		- Comments allowed (all lines starting with a #)
+		- Should be fully backwards compatible
+	* If no object(s) defined looks in /usr/share/wmcube
+	* Rewritten scandir function to be POSIX compliant
+
+wmCube 0.98:
 	* Added solid flat-shading to 3d-engine
 	* New tag in object-files (WMCUBE_PLANES) for solid objects
 
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index 8cae7e6..0000000
--- a/INSTALL
+++ /dev/null
@@ -1,37 +0,0 @@
-Requirements
---------------------------------------------------------------
-
-- Linux (glibc 2.1) (Tested on various distributions)
-  or Solaris 8 Sparc/x86 (should work on Solaris 2.x and 7) 
-  or OpenBSD
-  or FreeBSD 3-stable, 4-stable 
-  or NetBSD
-
-- root access
-
-	To be able to install the application system-wide
-	you need root access.
-
-Installation
---------------------------------------------------------------
-1)  % tar -zxvf wmcube-0.98.tar.gz
-
-2)  % cd wmcube/wmcube
-
-3)  % make                 (if you are running Linux) or
-    % make -f Makefile.xxx (where xxx is the OS you running) 
-
-Optional 
-
-4)  % su root
-
-5)  % make install
-
-6)  % wmcube & (or wmcube -h for command line options).
-
-General Notes
---------------------------------------------------------------
-Note 1: If "make install" fails on your system, please edit
-        the Makefile to set the paths according to your setup.
-        "make install" defaults to /usr/local/bin, $HOME & /etc.
-
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ba39bd9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,58 @@
+#
+# wmCube 0.99-pre1
+#
+# To make wmcube compile on another OS change the following things:
+#
+# CXXFLAGS -D: FREEBSD/NETBSD/SOLARIS/OPENBSD/DARWIN
+# CPUMONCC_OS: freebsd/netbsd/solaris/openbsd/darwin (you will also have
+# to make sure that the makefile in the cpumoncc/$(CPUMONCC_OS) directory
+# is working.
+# LFLAGS: Modify/Add any necessary libraries here.
+#
+#
+CXX= g++
+CXXFLAGS=-O2 -DLINUX
+CPUMONCC_OS=linux
+WMCUBE_LIBS=-Lwmapp -lwmapp -Lcpumoncc/$(CPUMONCC_OS) -lcpumoncc
+LFLAGS=$(WMCUBE_LIBS) -L/usr/X11R6/lib -lXpm -lXext -lX11 
+OBJECTS = WmcObject.o
+TARGET = wmcube
+
+$(TARGET): wmcube.cc cpumoncc/$(CPUMONCC_OS)/libcpumoncc.a wmapp/libwmapp.a $(OBJECTS)
+	@@echo "###############################################################"
+	@@echo "#"
+	@@echo "# I am now building the actual wmCube application."
+	@@echo "#" 
+	@@echo "###############################################################"
+	$(CXX) $(CXXFLAGS) $(OBJECTS) $< -o $@ $(LFLAGS)
+
+cpumoncc/$(CPUMONCC_OS)/libcpumoncc.a:
+	@@echo "###############################################################"
+	@@echo "# I am now building the cpumoncc library in 'cpumoncc/$(CPUMONCC_OS)'."
+	@@echo "# Please modify/verify the makefile in that directory before"
+	@@echo "# reporting an error as a bug."
+	@@echo "###############################################################"
+	cd cpumoncc/$(CPUMONCC_OS); make; cd ../..
+	
+wmapp/libwmapp.a:
+	@@echo "###############################################################"
+	@@echo "# I am now building the wmapp library in 'wmapp'"
+	@@echo "# Please modify/verify the makefile in that directory before"
+	@@echo "# reporting an error as a bug."
+	@@echo "###############################################################"
+	cd wmapp; make; cd ..
+
+install: $(TARGET)
+	cp -Rf wmc /usr/share/wmcube
+	cp wmcube /usr/local/bin
+	chmod 755 /usr/local/bin/wmcube
+        chown root:root /usr/local/bin/wmcube
+
+clean:
+	rm -f *.o *\~ $(TARGET)
+	cd wmapp; make clean; cd ..
+	cd cpumoncc/$(CPUMONCC_OS); make clean; cd ../..
+	
+install_clean:
+	rm -fr /usr/share/wmcube
+	rm /usr/local/bin/wmcube
diff --git a/README b/README
index 9275d45..18affb7 100644
--- a/README
+++ b/README
@@ -1,41 +1,83 @@
-wmCube 0.98
---------------------------------------------------------------
-Author:	Robert Kling
-	robkli-8 at student.luth.se
-	http://boombox.campus.luth.se
-
-Contributions by:
-	Thorsten Jens (thodi at et-inf.fho-emden.de)
- 	Jakob Borg (email-adress goes here)
-	Dan Price (dp at rampant.org)
-	Brian Joseph Czapiga (rys at godsey.net)
-	Tai-hwa Liang (avatar at mmlab.cse.yzu.edu.tw)
-	Jared Smolens (jsmolens+ at andrew.cmu.edu)
-
-Description
---------------------------------------------------------------
-
-wmCube is a dockapp that displays a realtime rotating 3d-object 
-and the current CPU load.
-
-Files
---------------------------------------------------------------
-3dObjects/	In here you will find bundled object-files.
-README		This file.
-INSTALL		Installation instructions.
-CHANGES		Description of changes.
-TODO		Things I've already planned for wmCube
-COPYING		GNU General Public License Version 2.
-
-Bugs
---------------------------------------------------------------
-If you discover any bugs in this software, please send a 
-bugreport to robkli-8 at student.luth.se and describe the
-problem as detailed as you can.
-
-Copyright
---------------------------------------------------------------
-wmCube is Copyright (C) 2000/01 by Robert Kling, Lulea SWEDEN
-
-wmCube is licensed through the GNU General Public License.
-Read the COPYING file for the complete GNU license.
+wmCube 0.99-pre1
+(C) Copyright 2003 Robert Kling
+robkli-8 at student.luth.se
+http://kling.mine.nu/wmcube.htm
+
+DESCRIPTION
+wmCube is a dockapp for monitoring the cpu load. A 3D object spins
+faster/slower relative to the load and you can even design your own
+objects for it. Objects can be traditional wireframe or solid shaded or 
+a combination of the two.
+
+REQUIREMENTS
+wmCube uses the CpuMonitorCC (cpumoncc) library (spawned from 
+previous versions of wmCube) to read the cpu load which supports a 
+range of different operating systems. Further, the wmApp toolkit is 
+used to do the drawing to the X server. Both cpumoncc and wmApp 
+are included in the distribution, versions 0.0.1-pre1 and 0.0.4.1
+respectively.
+
+INSTALL
+THIS PRE-VERSION ONLY WORKS ON LINUX! Please report
+all bugs. Note though that wmCube _should_ compile on all archs
+supported in earlier versions by simply editing the Makefile for
+the particular OS in the cpumoncc directory as well as copying 
+and modifying the main makefile. IF YOU GET WMCUBE 
+WORKING IN ANOTHER OS THAN LINUX, PLEASE SEND
+ME THE SUCCESSFUL MAKEFILES OR A PATCH! (sorry
+for the shouting)
+
+To install wmCube:
+
+# make
+
+then as root
+
+# make install
+
+This will install wmc-objects into /usr/share/wmcube
+and the binary into /usr/local/bin.
+
+Alternatively you can run wmcube with '-o <directory>' which will
+load objects from the <directory>. More objects will
+be bundled in the stable release.
+
+USAGE
+
+# wmcube -h
+
+will give you a list of all availible command line options. When
+running you control the program by clicking with your mouse on the
+canvas where the object is displayed.
+
+For a 3-button mouse:
+
+First mouse button (left):
+	Upper left corner: Switches between new and classic window mode.
+	Left hand side: Zoom away from the object.
+	Right hand side: Zoom in on the object.
+	Upper edge: Scroll in the next object from below.
+	Lower edge: Scroll in the previous object from above.
+	In the middle (approx): Change 3d mode on object.
+	
+Second mouse button (middle button):
+	Changes 3d mode on object.
+	
+Third mouse button (right):
+	Sets the position of the lightsource.
+	
+For a 5-button mouse (mouse wheel):
+Exactly the same as 3-button mouse except
+that you can also zoom in/out with the wheel
+(button 4 and 5).
+
+CONTRIBUTIONS
+I only test wmCube thoroughly on Linux so anyone running on a
+different OS/architecture please let me now if there are any bugs.
+Suggestions, patches etc. are also very welcome. If you package
+wmCube for a certain distribution/OS and it is not represented on
+this page feel free to send it to me. You can also send me new
+objects (if they're cool) and I will include them in the next release
+alt. put them up on this page. Make sure to put a comment
+(new in 0.99) with your name etc in the wmc-file if you want credit 
+for them.
\ No newline at end of file
diff --git a/TODO b/TODO
deleted file mode 100644
index 01df841..0000000
--- a/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-TODO list for wmCube future versions
---------------------------------------------------------------
-
-* Ports to more OS's.
-* Goroud shading, texture mapping (hmm.. do I smell overkill?)
-
-If you have any suggestions, ideas, comments of how to make 
-this app better please send it to robkli-8 at student.luth.se.
diff --git a/WmcObject.cc b/WmcObject.cc
new file mode 100644
index 0000000..e5c5a0f
--- /dev/null
+++ b/WmcObject.cc
@@ -0,0 +1,619 @@
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <iostream>
+#include <stdexcept>
+#include <vector>
+#include "wmapp/wmcanvas.h"
+#include "WmcObject.h"
+
+using namespace std;
+
+#define DEBUG    0
+#define PDEBUG() if (DEBUG)
+
+#define CHECK(a, b, c)     (((b) < (a)) || ((b) > (c))) ? true : false
+#define ROUND(a)           ((a) - floor((a)) >= 0.5) ? (int)ceil((a)) : (int)floor((a))
+#define PI                 3.14159265368979
+#define PI2                6.283185307
+#define invPI              0.318309885
+#define WMC_COMMENT_CHAR   '#'
+#define VERTEX_SCALE       200.0
+
+/**********************************
+ Color related stuff
+*/
+
+#define REFLEX       0.04 // Do the reflexy thing if the shading is less than this
+#define REFLEX_COLOR 0xAACEEE
+#define WIRE_COLOR   0x20B2AE
+#define CYAN         0x20B2AE
+#define SHADING      90.0
+
+/*******************************************************************
+
+ WmcObject::WmcObject()
+ 
+ Creates a new (default)
+
+********************************************************************/
+WmcObject::WmcObject()
+{
+  const char *filename = { "/tmp/default_cube.wmc" };
+  FILE *fp = fopen(filename, "w");
+  fwrite(default_cube, sizeof(unsigned char), strlen(default_cube), fp);
+  fclose(fp);
+  	
+  load(filename);
+
+  lightsource.x = 0;
+  lightsource.y = -1;
+  lightsource.z = 1;
+
+  xoff = 26;
+  yoff = 20;
+  zoff = 3000;
+
+  color = CYAN;
+  shading = SHADING / 100.0;
+}
+
+/*******************************************************************
+
+ WmcObject::WmcObject(const char *filename)
+
+********************************************************************/
+WmcObject::WmcObject(const char *filename)
+{
+  load(filename);
+
+  lightsource.x = 0;
+  lightsource.y = -1;
+  lightsource.z = 1;
+
+  xoff = 26;
+  yoff = 20;
+  zoff = 3000;
+
+  color = CYAN;
+  shading = SHADING / 100.0;
+}
+
+/*******************************************************************
+
+ WmcObject::~WmcObject()
+
+********************************************************************/
+WmcObject::~WmcObject()
+{
+}
+
+void WmcObject::setColorShading(unsigned icolor, float ishading)
+{
+	color = icolor;
+	shading = ishading / 100.0;;
+}
+
+void WmcObject::setMode(int m)
+{
+  PDEBUG() printf("setting mode %d\n", m);
+  switch (m)
+    {
+    case WIREFRAME:
+      PDEBUG() printf("setting wireframe mode\n", m);
+      if (lines) mode = WIREFRAME;
+      break;
+    case SOLID:
+      PDEBUG() printf("setting solid mode\n", m);
+      if (planes) mode = SOLID;
+      break;
+    case SOLID_WIRE:
+      PDEBUG() printf("setting solid wire mode\n", m);
+      if (planes && lines) mode = SOLID_WIRE;
+      break;
+    default:
+      break;
+    }
+}
+
+void WmcObject::setYOffset(int pixels)
+{
+  yoff = pixels;
+}
+
+void WmcObject::modifyZOffset(int idepth)
+{
+  if (zoff + idepth >= 2 * VERTEX_SCALE) 
+    zoff += idepth;
+}
+
+void WmcObject::setLightSource(float xc, float yc, float zc)
+{
+  lightsource.x = xc;
+  lightsource.y = yc;
+  lightsource.z = zc;
+}
+
+
+/*******************************************************************
+
+ int WmcObject::freadline(FILE *fp, int maxlen, char *dest)
+
+ Reads a line of chars of maximum 'maxlen' length from file 'fp' 
+ into buffer 'dest'. Discards comments (returns length 0) otherwise
+ return the true length of the row.
+
+********************************************************************/
+int WmcObject::freadline(FILE *fp, int maxlen, char *dest)
+{
+  int cnt = 0;
+  bzero(dest, maxlen);
+  if (feof(fp)) return 0;
+  fread(&dest[cnt++], 1, 1, fp);
+  while ((dest[cnt - 1] != '\n') && (!feof(fp)) && (cnt < maxlen)) fread(&dest[cnt++], 1, 1, fp);
+  dest[cnt - 1] = 0;
+  if (dest[0] == WMC_COMMENT_CHAR) return 0;
+  return cnt - 1;
+}
+
+/*******************************************************************
+ 
+ bool WmcObject::loadVertices(const char *filename)
+
+********************************************************************/
+bool WmcObject::loadVertices(const char *filename)
+{
+  Vertex vtmp;
+  int n = 0;
+  char tmp[64], tmp2[64];
+  FILE *fp;
+  float max = 0;
+  
+  PDEBUG() printf("Loading vertices...\n");
+
+  if ((fp = fopen(filename,"r")) == NULL)
+    throw runtime_error("WmcObject::load: object file not found.");
+    
+  do
+    {
+      freadline(fp, 63, tmp);
+      if (feof(fp)) return false;
+    }
+  while (!strstr(tmp,"WMCUBE_COORDINATES"));
+
+  do
+    {
+      int len = freadline(fp, 63, tmp);
+      //printf("\"%s\"\n",tmp);
+
+      if (!strstr(tmp,"WMCUBE_PLANES") && !strstr(tmp,"WMCUBE_LINES") && (len > 5))
+	{
+	  if (sizeof(float) == sizeof(double))
+	    sscanf(tmp,"%63s %lf %lf %lf", tmp2, &vtmp.x, &vtmp.y, &vtmp.z);
+	  else
+	    sscanf(tmp,"%63s %f %f %f", tmp2, &vtmp.x, &vtmp.y, &vtmp.z);
+
+	  n = atoi(tmp2);
+
+	  // Save maximum scalar product for scaling
+	  if (sqrt(vtmp.x*vtmp.x + vtmp.y*vtmp.y + vtmp.z*vtmp.z) > max)
+	    max = sqrt(vtmp.x * vtmp.x + vtmp.y*vtmp.y + vtmp.z*vtmp.z);
+
+	  vertex.push_back(vtmp);
+	  //printf("%d: %f %f %f\n", n, vertex.back().x, vertex.back().y, vertex.back().z);
+
+	  if (n != vertex.size())
+	    {
+	      fclose(fp);
+	      throw runtime_error("WmcObject::load: Error in objectfile: the"
+				  "coordinates must be listed in order 1..n.");
+	    }
+	}
+    }
+	
+  while (!strstr(tmp,"WMCUBE_LINES") && !strstr(tmp,"WMCUBE_PLANES") && (!feof(fp)));
+
+  // Scale the vertices to 0..200
+  for (int i = 0; i < vertex.size(); i++)
+    {
+      vertex.at(i).x = VERTEX_SCALE / max * vertex.at(i).x;
+      vertex.at(i).y = VERTEX_SCALE / max * vertex.at(i).y;
+      vertex.at(i).z = VERTEX_SCALE / max * vertex.at(i).z;
+      rvertex.push_back(vertex.at(i));
+    }
+
+  fclose(fp);
+
+  return true;
+}
+
+/*******************************************************************
+
+ bool WmcObject::loadLines(const char *filename)
+
+********************************************************************/
+bool WmcObject::loadLines(const char *filename)
+{
+  Line ltmp;
+  char tmp[64];
+  int iltmp[3];
+  FILE *fp;
+
+  if ((fp = fopen(filename,"r")) == NULL)
+    throw runtime_error("WmcObject::load: object file not found.\n");
+
+  do
+    {
+      freadline(fp, 63, tmp);
+      if (feof(fp)) return false;
+    }
+  while (!strstr(tmp,"WMCUBE_LINES"));
+
+  PDEBUG() printf("Loading lines...\n");
+
+  do
+    {
+      int len = freadline(fp, 63, tmp);
+
+      if (!strstr(tmp,"WMCUBE_COORDINATES") && !strstr(tmp,"WMCUBE_PLANES") && (len > 2))
+	{
+	  sscanf(tmp, "%d %d", &iltmp[0], &iltmp[1]);
+	  
+	  if (CHECK(0, iltmp[0] - 1, vertex.size()) || CHECK(0, iltmp[1] - 1, vertex.size()))
+	    { 
+	      fclose(fp);
+	      throw runtime_error("WmcObject::load: Error in objectfile (WMCUBE_LINES section):"
+				  "invalid coordinates.");
+	    }
+	  
+	  ltmp.a = &rvertex[iltmp[0] - 1];
+	  ltmp.b = &rvertex[iltmp[1] - 1];
+	  line.push_back(ltmp);
+	  //printf("%d %d\n",  iltmp[0], iltmp[1]);
+	}
+    }
+  while (!strstr(tmp,"WMCUBE_COORDINATES") && !strstr(tmp,"WMCUBE_PLANES") && !feof(fp));
+
+  fclose(fp);
+
+  return true;
+}
+
+/*******************************************************************
+
+ bool WmcObject::loadPlanes(const char *filename)
+
+********************************************************************/
+bool WmcObject::loadPlanes(const char *filename)
+{
+  Plane ptmp;
+  char tmp[64];
+  int iptmp[3];
+  FILE *fp;
+
+  if ((fp = fopen(filename,"r")) == NULL)
+    throw runtime_error("WmcObject::load: object file not found.");
+
+  do
+    {
+      freadline(fp, 63, tmp);
+      if (feof(fp)) return false;
+    }
+  while (!strstr(tmp,"WMCUBE_PLANES"));
+
+  PDEBUG() printf("Loading planes...\n");
+
+  do
+    {
+      int len = freadline(fp, 63, tmp);
+
+      if (!strstr(tmp,"WMCUBE_COORDINATES") && !strstr(tmp,"WMCUBE_LINES") && (len > 4))
+	{
+	  sscanf(tmp,"%d %d %d", &iptmp[0], &iptmp[1], &iptmp[2]);
+
+	  if (CHECK(0,    iptmp[0] - 1, rvertex.size())
+	      || CHECK(0, iptmp[1] - 1, rvertex.size())
+	      || CHECK(0, iptmp[2] - 1, rvertex.size())) 
+	    { 
+	      fclose(fp);
+	      throw runtime_error("WmcObject::load: Error in objectfile (WMCUBE_PLANES section): "
+				  "invalid coordinates.");
+	    }
+	  
+	  ptmp.a = &rvertex[iptmp[0] - 1];
+	  ptmp.b = &rvertex[iptmp[1] - 1];
+	  ptmp.c = &rvertex[iptmp[2] - 1];
+	  ptmp.ab = -1;
+	  ptmp.bc = -1;
+	  ptmp.ac = -1;
+	  plane.push_back(ptmp);
+	  //printf("%d %d %d\n", iptmp[0], iptmp[1], iptmp[2]); fflush(stdout);
+	}
+    }
+  while (!strstr(tmp,"WMCUBE_LINES") && !strstr(tmp,"WMCUBE_COORDINATES") && !feof(fp));
+
+  fclose(fp);
+
+  if (lines)
+    {
+      // Check which lines to draw for SOLID_WIRE mode
+
+      for (int i = 0; i < plane.size(); i++)
+	for (int j = 0; j < line.size(); j++)
+	  {
+	    if (verticesBelongToLine(plane[i].a, plane[i].b, line[j])) plane[i].ab = j;
+	    if (verticesBelongToLine(plane[i].b, plane[i].c, line[j])) plane[i].bc = j;
+	    if (verticesBelongToLine(plane[i].a, plane[i].c, line[j])) plane[i].ac = j;
+	  }
+    }
+ 
+  return true;
+}
+
+bool WmcObject::verticesBelongToLine(Vertex *first, Vertex *second, Line l)
+{
+  if ((first == l.a && second == l.b) || (second == l.a && first == l.b))
+    return true;
+  
+  return false;
+}
+
+/*******************************************************************
+
+ bool WmcObject::load(const char *filename)
+
+********************************************************************/
+bool WmcObject::load(const char *filename)
+{
+  try 
+    {
+      loadVertices(filename);
+      lines  = loadLines(filename);
+      planes = loadPlanes(filename);
+    }
+  catch (exception &e)
+    {
+      cout << e.what() << endl; 
+    }
+
+  if (!lines && !planes)
+    throw runtime_error("WmcObject::load: no WMCUBE_PLANES or WMCUBE_LINES section found in file.");
+
+  if (planes && lines)
+  	mode = SOLID_WIRE;
+  else if (planes)
+  	mode = SOLID;
+  else
+  	mode = WIREFRAME;
+  
+  return true;
+}
+
+/*******************************************************************
+ 
+ void WmcObject::rotate(int ixang, int iyang, int izang)
+
+ Rotates the object from it's current configuration by ixang, iyang
+ and izang degrees.
+
+********************************************************************/
+void WmcObject::rotate(float ixang, float iyang, float izang)
+{
+  static float xang = 0;
+  static float yang = 0;
+  static float zang = 0;
+  float tx, ty, tz;
+
+  xang = (xang + ixang > PI2) ? xang + ixang - PI2 : xang + ixang;
+  yang = (yang + iyang > PI2) ? yang + iyang - PI2 : yang + iyang;
+  zang = (zang + izang > PI2) ? zang + izang - PI2 : zang + izang;
+	
+  for (int i = 0; i < vertex.size(); i++)
+    {
+      tx = cos(yang) * vertex[i].x - sin(yang) * vertex[i].z;
+      tz = sin(yang) * vertex[i].x + cos(yang) * vertex[i].z;
+      ty = cos(zang) * vertex[i].y - sin(zang) * tx;
+
+      rvertex[i].x = cos(zang) * tx + sin(zang) * vertex[i].y;
+      rvertex[i].y = sin(xang) * tz + cos(xang) * ty;
+      rvertex[i].z = cos(xang) * tz - sin(xang) * ty;
+    }
+
+  // Calculate plane color before distorting it with perspective
+  for (int i = 0; i < plane.size(); i++)
+    plane[i].color = luminate(plane[i]);
+    
+  // Add perspective
+  for (int i = 0; i < vertex.size(); i++)
+    {   
+      rvertex[i].x = 256 * rvertex[i].x / (2 * rvertex[i].z - zoff) + xoff;
+      rvertex[i].y = 256 * rvertex[i].y / (2 * rvertex[i].z - zoff) + yoff;
+    }
+}
+
+/*******************************************************************
+
+ void WmcObject::draw(WMCanvas *icanvas)
+ 
+ Draws the WmcObject on the WMCanvas icanvas. Defaults to planes if
+ available, otherwise wireframe is used. Buffered mode is used
+ so canvas->display() must be called at the end.
+
+********************************************************************/
+void WmcObject::draw(WMCanvas *icanvas)
+{
+  canvas = icanvas;
+
+  canvas->setbuffered(true);
+  
+  switch (mode)
+  {
+  	case WIREFRAME:
+  	canvas->setcolor((WMColor::WMColor)WIRE_COLOR);
+  	for (int i = 0; i < line.size(); i++)
+		canvas->draw_line((int)(line[i].a->x), (int)(line[i].a->y),(int)(line[i].b->x), (int)(line[i].b->y));
+  	break;
+  	
+  	case SOLID:
+  	sort(plane);
+	for (int i = 0; i < plane.size(); i++)
+		if (visible(plane[i])) drawTriangle(plane[i]);
+  	break;
+  	
+  	case SOLID_WIRE:
+  	sort(plane);
+	for (int i = 0; i < plane.size(); i++)
+		if (visible(plane[i])) drawTriangle(plane[i], true);
+  	break;
+  }
+
+  canvas->display();
+}
+
+/*******************************************************************
+
+ bool WmcObject::visible(Plane p)
+ 
+ Returns true if the plane is visible (has positive z-component).
+
+********************************************************************/
+bool WmcObject::visible(Plane p)
+{
+  //return normal(p).z > 0.0; // Also works but no need computing x- and y-components
+  return ((p.a->x - p.c->x) * (p.b->y - p.c->y) - (p.b->x - p.c->x) * (p.a->y - p.c->y)) > 0.0;
+}
+
+/*******************************************************************
+
+ Vertex WmcObject::normal(Plane p)
+ 
+ Returns plane p's normal.
+
+********************************************************************/
+Vertex WmcObject::normal(Plane p)
+{
+  Vertex ret;
+  float x1 = p.a->x - p.c->x, y1 = p.a->y - p.c->y, z1 = p.a->z - p.c->z;
+  float x2 = p.b->x - p.c->x, y2 = p.b->y - p.c->y, z2 = p.b->z - p.c->z;
+  ret.x = y1 * z2 - y2 * z1;
+  ret.y = x2 * z1 - x1 * z2;
+  ret.z = x1 * y2 - y1 * x2;
+
+  return ret;
+}
+
+/*******************************************************************
+
+ float WmcObject::luminate(Plane p)
+ 
+ Returns the luminousity _DECREASE_ for plane p in the range 0..1.
+ This is based solely on the angle between the plane's normal and
+ the lightsource vector, i.e the distance between the lightsource
+ and plane is _not_ taken into account (which would be easy to fake).
+
+********************************************************************/
+float WmcObject::luminate(Plane p)
+{
+  Vertex pn      = normal(p);
+  float sp_pn  = sqrt(pn.x * pn.x + pn.y * pn.y + pn.z * pn.z);
+  float sp_lum = sqrt(lightsource.x * lightsource.x + lightsource.y * lightsource.y 
+			+ lightsource.z * lightsource.z);
+  float pn_lum = pn.x * lightsource.x + pn.y * lightsource.y + pn.z * lightsource.z;
+  
+  return invPI * acos((pn_lum / (sp_pn * sp_lum)));
+}
+
+/*******************************************************************
+
+ void WmcObject::sort(vector<Plane> &plane)
+ 
+ Insertion-sorts a vector of planes by the sum of their z-components.
+
+********************************************************************/
+void WmcObject::sort(vector<Plane> &plane)
+{
+  int i, j, k;
+  float key;
+  float temparr[plane.size()];
+  Plane ptmp;
+  
+  for (i = 0; i < plane.size(); i++)
+    temparr[i] = plane[i].a->z + plane[i].b->z + plane[i].c->z;
+  
+  for (j = 1; j < plane.size(); j++)
+    {
+      ptmp = plane[j];
+      key = temparr[j];
+      i = j - 1;
+      
+      while ((i > -1) && (temparr[i] > key)) 
+ 	{
+	  plane[i+1]   = plane[i];
+ 	  temparr[i+1] = temparr[i];
+	  i--;
+	} 
+      
+      plane[i+1]   = ptmp;							
+      temparr[i+1] = key;
+    }
+}
+
+/*******************************************************************
+
+ void WmcObject::drawTriangle(Plane p)
+
+ Draws a filled polygon using the builtin routine from wmapp which
+ in turn uses the builtin routine in X. Sadly enough it is uglier
+ than my own original routine due to some corner pixel that gets
+ plotted sometime. Plane color is computed  using the global
+ variables colX and colX_dec and 'p.color'. 
+
+********************************************************************/
+void WmcObject::drawTriangle(Plane p, bool wire)
+{
+  X::XPoint xp;
+  vector<X::XPoint> points;
+  unsigned char R = 0, G = 0, B = 0;
+  unsigned composit = 0;
+
+  xp.x = (int)p.a->x;
+  xp.y = (int)p.a->y;
+  points.push_back(xp);
+  xp.x = (int)p.b->x;
+  xp.y = (int)p.b->y;
+  points.push_back(xp);
+  xp.x = (int)p.c->x;
+  xp.y = (int)p.c->y;
+  points.push_back(xp);
+
+  R = (unsigned char)(color >> 16);
+  G = (unsigned char)(color >> 8 );
+  B = (unsigned char)(color      );
+  
+  R -= (unsigned char)((float)R * p.color * shading);
+  G -= (unsigned char)((float)G * p.color * shading);
+  B -= (unsigned char)((float)B * p.color * shading);
+  
+  composit = (R << 16) + (G << 8) + B;
+
+  // If the plane is almost purpendicular to the lightsource fake a 'reflex'
+  if (p.color < REFLEX) composit = REFLEX_COLOR;
+
+  canvas->setcolor((WMColor::WMColor)composit);
+  canvas->fill_polygon(points);
+
+  if (!wire) return;
+  
+  canvas->setcolor((WMColor::WMColor)WIRE_COLOR);
+  
+  if (p.ab > -1)
+    canvas->draw_line((int)(line[p.ab].a->x), (int)(line[p.ab].a->y),
+		      (int)(line[p.ab].b->x), (int)(line[p.ab].b->y));
+  if (p.bc > -1)
+    canvas->draw_line((int)(line[p.bc].a->x), (int)(line[p.bc].a->y),
+		      (int)(line[p.bc].b->x), (int)(line[p.bc].b->y));
+  if (p.ac > -1)
+    canvas->draw_line((int)(line[p.ac].a->x), (int)(line[p.ac].a->y),
+		      (int)(line[p.ac].b->x), (int)(line[p.ac].b->y));
+
+}
diff --git a/WmcObject.h b/WmcObject.h
new file mode 100644
index 0000000..cfb8b1f
--- /dev/null
+++ b/WmcObject.h
@@ -0,0 +1,96 @@
+#ifndef _WMCOBJECT_H_
+#define _WMCOBJECT_H_
+
+#include <vector>
+#include "wmapp/wmcanvas.h"
+
+typedef struct { float x, y, z; } Vertex;
+typedef struct { Vertex *a, *b, *c; float color; int ab, bc, ac; } Plane;
+typedef struct { Vertex *a, *b; } Line;
+typedef enum { WIREFRAME, SOLID, SOLID_WIRE, NUM_MODES };
+
+class WmcObject
+{
+public:
+  WmcObject();
+  WmcObject(const char *);
+  ~WmcObject();
+
+  void setMode(int m);
+  void setColorShading(unsigned color, float shading);
+  void rotate(float xang, float yang, float zang);
+  void draw(WMCanvas *icanvas);
+
+  void setYOffset(int pixels);
+  void modifyZOffset(int idepth);
+  void setLightSource(float xc, float yc, float zc);
+  
+private:
+  
+  bool   load(const char *);
+  bool   loadVertices(const char *);
+  bool   loadPlanes(const char *);
+  bool   loadLines(const char *);
+  int    freadline(FILE *fp, int maxlen, char *dest);
+  void   sort(vector<Plane> &plane);
+  bool   visible(Plane p);
+  float  luminate(Plane p);
+  Vertex normal(Plane p);
+  void   drawTriangle(Plane p, bool wire = false);
+  bool   verticesBelongToLine(Vertex *first, Vertex *second, Line l);
+  
+  vector<Vertex> vertex;
+  vector<Vertex> rvertex;
+  vector<Plane>  plane;
+  vector<Line>   line;
+
+  WMCanvas		*canvas;
+  Vertex		lightsource;
+  bool			lines, planes;  
+  int			xoff, yoff, zoff;
+  int			mode;
+  unsigned int	color;
+  float			shading;
+};
+
+const char default_cube[] = 
+{ ""
+"# The original cube by Robert Kling\n"
+"WMCUBE_COORDINATES\n"
+"1  -180 -180  180\n"
+"2   180 -180  180\n"
+"3   180  180  180\n"
+"4  -180  180  180\n"
+"5  -180 -180 -180\n"
+"6   180 -180 -180\n"
+"7   180  180 -180\n"
+"8  -180  180 -180\n"
+"WMCUBE_LINES\n"
+"1 2\n" 
+"2 3\n"
+"3 4\n"
+"4 1\n"
+"5 6\n"
+"6 7\n"
+"7 8\n"
+"8 5\n"
+"1 5\n"
+"2 6\n"
+"3 7\n"
+"4 8\n"
+"WMCUBE_PLANES\n"
+"1 2 3\n"
+"1 3 4\n"
+"2 6 7\n"
+"2 7 3\n"
+"5 1 4\n"
+"5 4 8\n"
+"5 2 1\n"
+"5 6 2\n"
+"4 3 8\n"
+"3 7 8\n"
+"6 5 8\n"
+"6 8 7"
+};
+
+#endif
diff --git a/cpumoncc/README b/cpumoncc/README
new file mode 100644
index 0000000..3b3da91
--- /dev/null
+++ b/cpumoncc/README
@@ -0,0 +1,70 @@
+CpuMonitorCC (cpumoncc)
+Version: 0.0.1-pre1 (aka "Expect Things To Be Broken")
+
+(C) Copyright 2003 Robert Kling
+
+robkli-8 at student.luth.se
+http://kling.mine.nu
+
+DESCRIPTION
+
+This is a small library for reading the instantaneous cpu load
+in many different operating systems. It started out as a part of
+wmCube but as it [wmCube] got ported to more and more OS's it 
+seemed tidier to put the OS-specific code into its
+on package. As the name implies it is written in C++.
+
+REQUIREMENTS/FEATURES
+
+Supported systems and their features so far are:
+
+    * Darwin - Basic functionality.
+    * FreeBSD - Basic functionality, discarding of 'nice' processes.
+    * Linux - Multiprocessor support, discarding of 'nice' processes.
+    * NetBSD - Basic functionality, discarding of 'nice' processes.
+    * OpenBSD - Basic functionality.
+    * Solaris - Multiprocessor support.
+    
+INSTALLATION
+
+Change to the directory of the OS your building cpumoncc for.
+Type (as root):
+
+make install
+
+To build the programs that come with cpumoncc, go into the directory
+'programs' and type
+
+make
+
+and optionally, as root
+
+make install
+
+CONTRIBUTIONS
+
+Solaris codebase by Dan Price (dp at rampant.org)
+OpenBSD codebase by Brian Joseph Czapiga (rys at godsey.net)
+FreeBSD codebase by Tai-hwa Liang (avatar at mmlab.cse.yzu.edu.tw)
+NetBSD codebase by Jared Smolens <jsmolens+ at andrew.cmu.edu>
+
+I only test cpumoncc thoroughly on Linux so anyone running on a 
+different OS/architecture please let me now if there are any bugs
+or if everything's hunky dory. Suggestions, patches, more ports 
+etc. are also very welcome.
+
+LICENSE
+     
+cpumoncc 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.
+
+cpumoncc 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 cpumoncc; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
diff --git a/cpumoncc/base/BaseCpuMonitor.h b/cpumoncc/base/BaseCpuMonitor.h
new file mode 100644
index 0000000..3577c7d
--- /dev/null
+++ b/cpumoncc/base/BaseCpuMonitor.h
@@ -0,0 +1,112 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/*
+
+ This is the base class which all cpu monitors should inherit
+ from. Best is to use one of the existing monitors as a
+ template when writing a new one. By inheriting this base
+ class it can be as simple as implementing just one function
+ to support a new operating system. This function is
+ getLoad() which should return the (average (in the case of
+ a smp-system)) intermediate cpu-load in the range [0.0, 1.0]
+ multiplied by the inherited protected variable 'range'.
+
+*/
+
+#ifndef _BASECPUMONITOR_H_
+#define _BASECPUMONITOR_H_
+
+#include <stdio.h>
+#include <stdexcept>
+
+#define CPUMONCC_VERSION "0.0.1-pre1"
+#define CPUMONCC_DATE "2003-02-14"
+
+using namespace std;
+
+class BaseCpuMonitor
+{
+public:
+  
+  BaseCpuMonitor();
+  virtual float getLoad() = 0;
+  void setRange(float);
+  bool saveInternals(const char *);
+  bool loadInternals(const char *);
+  
+protected:
+  
+  int   which_cpu;
+  bool  use_nice;
+  int   previous_total;
+  int   previous_used;
+  float range;
+};
+
+inline BaseCpuMonitor::BaseCpuMonitor()
+{
+	which_cpu = -1;
+  	use_nice = true;
+  	previous_total = 0;
+  	previous_used = 0;
+  	// Set default range to percent
+  	range = 100.0;
+}
+
+inline void BaseCpuMonitor::setRange(float irange)
+{
+  	range = irange;
+}
+
+inline bool BaseCpuMonitor::saveInternals(const char *filename)
+{
+	int count;
+	FILE *fp = fopen(filename, "w");
+		
+	if (fp == 0) return false;
+	
+	count = fprintf(fp, "%d %d", previous_used, previous_total);
+	fclose(fp);
+	
+	if (count != 2) return false;	
+
+	return true;
+}
+
+inline bool BaseCpuMonitor::loadInternals(const char *filename)
+{
+	int count;
+	FILE *fp = fopen(filename, "r");
+		
+	if (fp == 0) return false;
+	
+	count = fscanf(fp, "%d %d", &previous_used, &previous_total);
+	fclose(fp);
+	
+	if (count != 2) return false;	
+
+	return true;
+}
+
+
+#endif
diff --git a/cpumoncc/darwin/CpuMonitor.cc b/cpumoncc/darwin/CpuMonitor.cc
new file mode 100644
index 0000000..b98a800
--- /dev/null
+++ b/cpumoncc/darwin/CpuMonitor.cc
@@ -0,0 +1,41 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/Darwin
+
+#include "CpuMonitor.h"
+
+CpuMonitor::CpuMonitor() : BaseCpuMonitor()
+{
+}
+
+float CpuMonitor::getLoad()
+{
+  float t;
+  double avenrun[3];
+  getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
+  
+  // t = 0..100
+  t = 2 * (((5.0*avenrun[0] + 0.5) > 50) ? 50 : (5.0*avenrun[0] + 0.5));
+
+  return range * t / 100.0;
+}
diff --git a/cpumoncc/darwin/CpuMonitor.h b/cpumoncc/darwin/CpuMonitor.h
new file mode 100644
index 0000000..d317820
--- /dev/null
+++ b/cpumoncc/darwin/CpuMonitor.h
@@ -0,0 +1,39 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/Darwin
+
+#ifndef _CPUMONITOR_H_
+#define _CPUMONITOR_H_
+
+#include <stdlib.h>
+#include "BaseCpuMonitor.h"
+
+class CpuMonitor : public BaseCpuMonitor
+{
+public:
+  
+  CpuMonitor();
+  float getLoad();
+};
+
+#endif
diff --git a/cpumoncc/darwin/Makefile b/cpumoncc/darwin/Makefile
new file mode 100644
index 0000000..2732a39
--- /dev/null
+++ b/cpumoncc/darwin/Makefile
@@ -0,0 +1,41 @@
+#####################################################
+#
+# To compile cpumoncc for a different OS/architecture you
+# will need to modify the variablese below to match your system.
+#
+# For system wide installation type (as root):
+#
+# make install
+#
+# This will install the static library in $(LIBINSTALL) and
+# the header files in $(HINSTALL)/cpumoncc.
+#
+#####################################################
+
+CXX=g++
+CXXFLAGS=
+HINSTALL=/usr/include
+LIBINSTALL=/usr/lib
+
+#####################################################
+
+TARGET=libcpumoncc.a
+
+$(TARGET): CpuMonitor.o
+	ar rcs $(TARGET) $^
+
+CpuMonitor.o: copy_base
+
+copy_base:
+	cp ../base/BaseCpuMonitor.h .
+        
+install: $(TARGET)
+	mkdir -p $(HINSTALL)/cpumoncc
+	cp *.h $(HINSTALL)/cpumoncc
+	install -m 644 $(TARGET) $(LIBINSTALL)
+
+clean:
+	rm -f *~ core *.o cpu $(TARGET) BaseCpuMonitor.h
+	rm -fr $(HINSTALL)/cpumoncc
+	rm -f $(LIBINSTALL)/$(TARGET)
+	
diff --git a/cpumoncc/freebsd/CpuMonitor.cc b/cpumoncc/freebsd/CpuMonitor.cc
new file mode 100644
index 0000000..726d33b
--- /dev/null
+++ b/cpumoncc/freebsd/CpuMonitor.cc
@@ -0,0 +1,80 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/FreeBSD
+
+#include "CpuMonitor.h"
+
+CpuMonitor::CpuMonitor() : BaseCpuMonitor()
+{
+  initialize();
+}
+
+CpuMonitor::CpuMonitor(bool nice) : BaseCpuMonitor()
+{
+  use_nice = nice;
+  initialize();
+}
+
+CpuMonitor::~CpuMonitor()
+{
+  kvm_close(kd);
+}
+
+void CpuMonitor::initialize()
+{
+  nlst[0].n_name = "_cp_time";
+  nlst[1].n_name = NULL;
+
+  if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
+    throw runtime_error("CpuMonitor: unable to open kvm.");
+  
+  kvm_nlist(kd, nlst);
+  
+  if (nlst[0].n_type == 0)
+    throw runtime_error("CpuMonitor: unable to get nlist.");
+}
+
+float CpuMonitor::getLoad()
+{
+  int total, used;
+  int cpu,nice,system,idle;
+  unsigned long int cpu_time[CPUSTATES];
+  float t;
+
+  if (kvm_read(kd, nlst[0].n_value, &cpu_time, sizeof(cpu_time)) != sizeof(cpu_time))
+    throw runtime_error("CpuMonitor: error reading kvm.");
+  
+  cpu = cpu_time[CP_USER];
+  nice = cpu_time[CP_NICE];
+  system = cpu_time[CP_SYS];
+  idle = cpu_time[CP_IDLE];
+  
+  used = cpu + system + use_nice*nice;
+  total = used + idle + (1-use_nice)*nice;
+  
+  t = range * (float)(used - previous_used) / (float)(total - previous_total);
+  previous_total = total;
+  previous_used = used;
+  
+  return t;
+}
diff --git a/cpumoncc/freebsd/CpuMonitor.h b/cpumoncc/freebsd/CpuMonitor.h
new file mode 100644
index 0000000..a03ca3f
--- /dev/null
+++ b/cpumoncc/freebsd/CpuMonitor.h
@@ -0,0 +1,52 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/FreeBSD
+
+#ifndef _CPUMONITOR_H_
+#define _CPUMONITOR_H_
+
+#include <kvm.h>
+#include <nlist.h>
+#include <fcntl.h>
+#include <sys/dkstat.h>
+#include "BaseCpuMonitor.h"
+
+class CpuMonitor : public BaseCpuMonitor
+{
+public:
+  
+  CpuMonitor();
+  CpuMonitor(bool nice);
+  ~CpuMonitor();
+  
+  float getLoad();
+
+private:
+
+  void initialize();
+  
+  kvm_t        *kd;
+  struct nlist nlst[2];
+};
+
+#endif
diff --git a/cpumoncc/freebsd/Makefile b/cpumoncc/freebsd/Makefile
new file mode 100644
index 0000000..9346f23
--- /dev/null
+++ b/cpumoncc/freebsd/Makefile
@@ -0,0 +1,41 @@
+######################################################
+#
+# To compile cpumoncc for a different OS/architecture you
+# will need to modify the variablese below to match your system.
+#
+# For system wide installation type (as root):
+#
+# make install
+#
+# This will install the static library in $(LIBINSTALL) and
+# the header files in $(HINSTALL)/cpumoncc.
+#
+#####################################################
+
+CXX=g++
+CXXFLAGS=-lkvm
+HINSTALL=/usr/include
+LIBINSTALL=/usr/lib
+
+#####################################################
+
+TARGET=libcpumoncc.a
+
+$(TARGET): CpuMonitor.o
+	ar rcs $(TARGET) $^
+
+CpuMonitor.o: copy_base
+
+copy_base:
+	cp ../base/BaseCpuMonitor.h .
+        
+install: $(TARGET)
+	mkdir -p $(HINSTALL)/cpumoncc
+	cp *.h $(HINSTALL)/cpumoncc
+	install -m 644 $(TARGET) $(LIBINSTALL)
+
+clean:
+	rm -f *~ core *.o cpu $(TARGET) BaseCpuMonitor.h
+	rm -fr $(HINSTALL)/cpumoncc
+	rm -f $(LIBINSTALL)/$(TARGET)
+	
\ No newline at end of file
diff --git a/cpumoncc/linux/CpuMonitor.cc b/cpumoncc/linux/CpuMonitor.cc
new file mode 100644
index 0000000..bd4396b
--- /dev/null
+++ b/cpumoncc/linux/CpuMonitor.cc
@@ -0,0 +1,100 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/Linux
+
+#include <stdio.h>
+#include "CpuMonitor.h"
+
+CpuMonitor::CpuMonitor() : BaseCpuMonitor()
+{
+  initialize();
+}
+
+CpuMonitor::CpuMonitor(int cpu) : BaseCpuMonitor()
+{
+  which_cpu = cpu;
+  initialize();
+}
+
+CpuMonitor::CpuMonitor(int cpu, bool nice) : BaseCpuMonitor()
+{
+  which_cpu = cpu;
+  use_nice = nice;
+  initialize();
+}
+
+void CpuMonitor::initialize()
+{
+  FILE *fp;
+  int i;
+  char cpuid[6];
+  char check_cpu[6];
+  char tmp[32];
+
+  if ((fp = fopen("/proc/stat","r")) == NULL) 
+    throw runtime_error("CpuMonitor: no /proc/stat found.");
+
+  if (which_cpu == -1) return;
+
+  snprintf(check_cpu, 6, "cpu%d", which_cpu);
+  //printf("Monitoring %s (%d)\n", check_cpu, which_cpu);
+
+  for (i = -2; i < which_cpu; i++) 
+    {
+      fscanf(fp, "%5s %31s %31s %31s %31s", cpuid, tmp, tmp, tmp, tmp);
+      //fscanf(fp, "%5s" , cpuid); printf("%s ", cpuid);
+      //fscanf(fp, "%31s", tmp  ); printf("%s ", tmp);
+      //fscanf(fp, "%31s", tmp  ); printf("%s ", tmp);
+      //fscanf(fp, "%31s", tmp  ); printf("%s ", tmp);
+      //fscanf(fp, "%31s", tmp  ); printf("%s\n", tmp); fflush(stdout);
+    }
+	
+  if (strcmp(check_cpu, cpuid) != 0)
+    throw runtime_error("CpuMonitor: could not read cpu-load.");
+}
+
+float CpuMonitor::getLoad()
+{
+  int total, used, i;
+  char cpuid[6];
+  int cpu,nice,system,idle;
+  float t;
+  FILE *fp;
+	
+  fp = fopen("/proc/stat","r");
+
+  for (i = -2; i < which_cpu; i++)
+    fscanf(fp,"%5s %d %d %d %d", cpuid, &cpu, &nice, &system, &idle);
+	
+  fclose(fp);
+
+  used = cpu + system + use_nice * nice;
+  total = used + idle + (1-use_nice) * nice;
+
+  t = range * (float)(used - previous_used) / (float)(total - previous_total);
+  previous_total = total;
+  previous_used = used;
+	
+  return t;
+}
+
diff --git a/cpumoncc/linux/CpuMonitor.h b/cpumoncc/linux/CpuMonitor.h
new file mode 100644
index 0000000..82bd910
--- /dev/null
+++ b/cpumoncc/linux/CpuMonitor.h
@@ -0,0 +1,45 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/Linux
+
+#ifndef _CPUMONITOR_H_
+#define _CPUMONITOR_H_
+
+#include "BaseCpuMonitor.h"
+
+class CpuMonitor : public BaseCpuMonitor
+{
+public:
+  
+  CpuMonitor();
+  CpuMonitor(int cpu);
+  CpuMonitor(int cpu, bool nice);
+  
+  float getLoad();
+
+private:
+
+  void initialize();
+};
+
+#endif
diff --git a/cpumoncc/linux/Makefile b/cpumoncc/linux/Makefile
new file mode 100644
index 0000000..ebe980a
--- /dev/null
+++ b/cpumoncc/linux/Makefile
@@ -0,0 +1,40 @@
+######################################################
+#
+# To compile cpumoncc for a different OS/architecture you
+# will need to modify the variablese below to match your system.
+#
+# For system wide installation type (as root):
+#
+# make install
+#
+# This will install the static library in $(LIBINSTALL) and
+# the header files in $(HINSTALL)/cpumoncc.
+#
+#####################################################
+
+CXX=g++
+CXXFLAGS=
+HINSTALL=/usr/include
+LIBINSTALL=/usr/lib
+
+#####################################################
+
+TARGET=libcpumoncc.a
+
+$(TARGET): CpuMonitor.o
+	ar rcs $(TARGET) $^
+
+CpuMonitor.o: copy_base
+
+copy_base:
+	cp ../base/BaseCpuMonitor.h .
+        
+install: $(TARGET)
+	mkdir -p $(HINSTALL)/cpumoncc
+	cp *.h $(HINSTALL)/cpumoncc
+	install -m 644 $(TARGET) $(LIBINSTALL)
+
+clean:
+	rm -f *~ core *.o cpu $(TARGET) BaseCpuMonitor.h
+#	rm -fr $(HINSTALL)/cpumoncc
+#	rm -f $(LIBINSTALL)/$(TARGET)
diff --git a/cpumoncc/netbsd/CpuMonitor.cc b/cpumoncc/netbsd/CpuMonitor.cc
new file mode 100644
index 0000000..33d2fb0
--- /dev/null
+++ b/cpumoncc/netbsd/CpuMonitor.cc
@@ -0,0 +1,113 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/NetBSD
+
+#include <stdlib.h>
+#include <sys/sched.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include "CpuMonitor.h"
+
+CpuMonitor::CpuMonitor() : BaseCpuMonitor()
+{
+  for (int i = i < CPUSTATES; i++) last_cp_time[i] = 0;
+}
+
+CpuMonitor::CpuMonitor(bool nice) : BaseCpuMonitor()
+{
+  use_nice = nice;
+  for (int i = i < CPUSTATES; i++) last_cp_time[i] = 0;
+}
+
+float CpuMonitor::getLoad()
+{
+  u_int64_t curr_cp_time[CPUSTATES];
+  u_int64_t total_time = 0, idle_time = 0;
+  int mib[2];
+  int i;
+  size_t ssize;
+  const int IDLE_TIME = 4;
+  const int NICE_TIME = 1;
+        
+  ssize = sizeof ( curr_cp_time );
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_CP_TIME;
+  
+  if ( sysctl ( mib, 2, curr_cp_time, &ssize, NULL, 0 ) ) 
+    throw runtime_error("CpuMonitor: unable to read CP_TIME from sysctl()\n");
+
+  if ( !use_nice ) 
+    curr_cp_time[NICE_TIME] = 0;
+
+  /* NetBSD gives 5 CPUSTATES - 
+   * User, Nice, System, Interrupt, Idle 
+   */
+  idle_time = curr_cp_time[IDLE_TIME] - last_cp_time[IDLE_TIME];
+  for ( i = 0; i < CPUSTATES; i++ )
+  {
+    total_time += ( curr_cp_time[i] - last_cp_time[i] ); 
+    last_cp_time[i] = curr_cp_time[i];
+  }
+
+  /* Calculate the % CPU usage as the User+Nice+System+Interrupt/Total
+   * for the interval
+   */
+  return range * (int) ( total_time - idle_time ) / total_time;
+}
+
+/*
+ * Overloads base class
+ */
+bool CpuMonitor::saveInternals(const char *filename)
+{
+	int count = 0;
+	FILE *fp = fopen(filename, "w");
+		
+	if (fp == 0) return false;
+	
+	for ( i = 0; i < CPUSTATES; i++ )
+		count += fprintf(fp, "%d", last_cp_time[i]);
+	
+	fclose(fp);
+	
+	if (count != CPUSTATES) return false;
+
+	return true;
+}
+
+bool CpuMonitor::loadInternals(const char *filename)
+{
+	int count = 0;
+	FILE *fp = fopen(filename, "r");
+		
+	if (fp == 0) return false;
+	
+	for ( i = 0; i < CPUSTATES; i++ )
+		count += fscanf(fp, "%d", &last_cp_time[i]);
+	
+	fclose(fp);
+	
+	if (count != CPUSTATES) return false;	
+
+	return true;
+}
diff --git a/cpumoncc/netbsd/CpuMonitor.h b/cpumoncc/netbsd/CpuMonitor.h
new file mode 100644
index 0000000..1be7fd0
--- /dev/null
+++ b/cpumoncc/netbsd/CpuMonitor.h
@@ -0,0 +1,43 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/NetBSD
+
+#ifndef _CPUMONITOR_H_
+#define _CPUMONITOR_H_
+
+#include "BaseCpuMonitor.h"
+
+class CpuMonitor : public BaseCpuMonitor
+{
+public:
+  
+  CpuMonitor();
+  CpuMonitor(bool nice);
+  float getLoad();
+
+private:
+  
+  u_int64_t last_cp_time[CPUSTATES];  
+};
+
+#endif
diff --git a/cpumoncc/netbsd/Makefile b/cpumoncc/netbsd/Makefile
new file mode 100644
index 0000000..ccc3b93
--- /dev/null
+++ b/cpumoncc/netbsd/Makefile
@@ -0,0 +1,40 @@
+######################################################
+#
+# To compile cpumoncc for a different OS/architecture you
+# will need to modify the variablese below to match your system.
+#
+# For system wide installation type (as root):
+#
+# make install
+#
+# This will install the static library in $(LIBINSTALL) and
+# the header files in $(HINSTALL)/cpumoncc.
+#
+#####################################################
+
+CXX=g++
+CXXFLAGS=
+HINSTALL=/usr/include
+LIBINSTALL=/usr/lib
+
+#####################################################
+
+TARGET=libcpumoncc.a
+
+$(TARGET): CpuMonitor.o
+	ar rcs $(TARGET) $^
+
+CpuMonitor.o: copy_base
+
+copy_base:
+	cp ../base/BaseCpuMonitor.h .
+        
+install: $(TARGET)
+	mkdir -p $(HINSTALL)/cpumoncc
+	cp *.h $(HINSTALL)/cpumoncc
+	install -m 644 $(TARGET) $(LIBINSTALL)
+
+clean:
+	rm -f *~ core *.o cpu $(TARGET) BaseCpuMonitor.h
+	rm -fr $(HINSTALL)/cpumoncc
+	rm -f $(LIBINSTALL)/$(TARGET)
\ No newline at end of file
diff --git a/cpumoncc/openbsd/CpuMonitor.cc b/cpumoncc/openbsd/CpuMonitor.cc
new file mode 100644
index 0000000..0287f4c
--- /dev/null
+++ b/cpumoncc/openbsd/CpuMonitor.cc
@@ -0,0 +1,42 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/OpenBSD
+
+#include <stdlib.h>
+#include "CpuMonitor.h"
+
+CpuMonitor::CpuMonitor() : BaseCpuMonitor()
+{
+}
+
+float CpuMonitor::getLoad()
+{
+  float t;
+  double avenrun[3];
+  getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
+  
+  // t = 0..100
+  t = 2 * (((5.0*avenrun[0] + 0.5) > 50) ? 50 : (5.0*avenrun[0] + 0.5));
+
+  return range * t / 100.0;
+}
diff --git a/cpumoncc/openbsd/CpuMonitor.h b/cpumoncc/openbsd/CpuMonitor.h
new file mode 100644
index 0000000..9117592
--- /dev/null
+++ b/cpumoncc/openbsd/CpuMonitor.h
@@ -0,0 +1,38 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/OpenBSD
+
+#ifndef _CPUMONITOR_H_
+#define _CPUMONITOR_H_
+
+#include "BaseCpuMonitor.h"
+
+class CpuMonitor : public BaseCpuMonitor
+{
+public:
+  
+  CpuMonitor();
+  float getLoad();
+};
+
+#endif
diff --git a/cpumoncc/openbsd/Makefile b/cpumoncc/openbsd/Makefile
new file mode 100644
index 0000000..b6334cb
--- /dev/null
+++ b/cpumoncc/openbsd/Makefile
@@ -0,0 +1,40 @@
+######################################################
+#
+# To compile cpumoncc for a different OS/architecture you
+# will need to modify the variablese below to match your system.
+#
+# For system wide installation type (as root):
+#
+# make install
+#
+# This will install the static library in $(LIBINSTALL) and
+# the header files in $(HINSTALL)/cpumoncc.
+#
+#####################################################
+
+CXX=g++
+CXXFLAGS=
+HINSTALL=/usr/include
+LIBINSTALL=/usr/lib
+
+#####################################################
+
+TARGET=libcpumoncc.a
+
+$(TARGET): CpuMonitor.o
+	ar rcs $(TARGET) $^
+
+CpuMonitor.o: copy_base
+
+copy_base:
+	cp ../base/BaseCpuMonitor.h .
+        
+install: $(TARGET)
+	mkdir -p $(HINSTALL)/cpumoncc
+	cp *.h $(HINSTALL)/cpumoncc
+	install -m 644 $(TARGET) $(LIBINSTALL)
+
+clean:
+	rm -f *~ core *.o cpu $(TARGET) BaseCpuMonitor.h
+	rm -fr $(HINSTALL)/cpumoncc
+	rm -f $(LIBINSTALL)/$(TARGET)
diff --git a/cpumoncc/programs/Makefile b/cpumoncc/programs/Makefile
new file mode 100644
index 0000000..3bff6a4
--- /dev/null
+++ b/cpumoncc/programs/Makefile
@@ -0,0 +1,14 @@
+CXX=g++
+CXXFLAGS=
+TARGET=cpu
+	
+all: cpu.cc cpuload.cc
+	$(CXX) $(CXXFLAGS) -o cpu cpu.cc -lcpumoncc
+	$(CXX) $(CXXFLAGS) -o cpuload cpuload.cc -lcpumoncc
+	
+install: all
+	cp cpu /usr/bin
+	cp cpuload /usr/bin
+	
+clean:
+	rm -f *~ core *.o cpu cpuload /usr/bin/cpu /usr/bin/cpuload
diff --git a/cpumoncc/programs/README b/cpumoncc/programs/README
new file mode 100644
index 0000000..7809f2a
--- /dev/null
+++ b/cpumoncc/programs/README
@@ -0,0 +1,17 @@
+These are two small programs that show how to use the cpumoncc library.
+
+The first one, cpu, is a 'state-ful' cpu monitor that returns the average 
+cpu load for the elapsed time between now and the last time you
+ran the program. Useful (in a geeky way) in promts for example:
+
+geoff at rama [CPU: 1%] ~/workspace/cpumoncc > ls
+README  base  darwin  freebsd  linux  netbsd  openbsd  programs  solaris
+geoff at rama [CPU: 4%] ~/workspace/cpumoncc >
+
+This particular prompt is (in bash): 
+PS1='\u@\h [CPU: `cpu`%] \w > '
+
+
+The second program, cpuload, is a simple text mode cpu monitor.
+
+To build these programs type 'make'. To install, type, as root, 'make install'.
\ No newline at end of file
diff --git a/cpumoncc/programs/cpu.cc b/cpumoncc/programs/cpu.cc
new file mode 100644
index 0000000..993d3d8
--- /dev/null
+++ b/cpumoncc/programs/cpu.cc
@@ -0,0 +1,56 @@
+/*
+  
+ cpu.cc v0.0.1
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/*
+ * Note that this program will compile for all on os's supported
+ * by cpumoncc altough it will only function properly on the 
+ * os's with a valid implementation of load/saveInternals. With
+ * version 0.0.1-pre1 of cpumoncc they are lacking for OpenBSD 
+ * and Darwin. cpumoncc must be installed for this program to
+ * compile.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <cpumoncc/CpuMonitor.h>
+
+char filename[256];
+
+FILE *fp;
+CpuMonitor *cpu = new CpuMonitor();
+
+int main()
+{
+	// Necessary monitor internals will be saved in /home/username/.cpu
+	strncpy(filename, getenv("HOME"), 245);
+	strncat(filename, "/.cpu", 6);
+    
+    cpu->loadInternals(filename);
+    printf("%.0f", cpu->getLoad());
+    cpu->saveInternals(filename);
+    
+    delete cpu;
+			
+	return 0;	
+}
diff --git a/cpumoncc/programs/cpuload.cc b/cpumoncc/programs/cpuload.cc
new file mode 100644
index 0000000..65f4d21
--- /dev/null
+++ b/cpumoncc/programs/cpuload.cc
@@ -0,0 +1,60 @@
+/*
+  
+ cpuload.cc v0.0.1
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <iostream>
+#include <cpumoncc/CpuMonitor.h>
+
+#define U_POLL_INTERVAL 500000
+
+char filename[256];
+
+FILE *fp;
+CpuMonitor *cpumon = new CpuMonitor();
+
+int prev_used, prev_total;
+
+int main()
+{
+	while (1)
+    {
+      try
+      { 
+	  	printf("\rLoad: %.2f%%  ", cpumon->getLoad()); fflush(stdout);
+	  }
+	  catch (exception e)
+	  {
+	  	cout << e.what();
+	  	return -1;
+	  }
+      
+      usleep(U_POLL_INTERVAL);
+    }
+    
+    delete cpumon;
+			
+	return 0;	
+}
diff --git a/cpumoncc/solaris/CpuMonitor.cc b/cpumoncc/solaris/CpuMonitor.cc
new file mode 100644
index 0000000..b26cef6
--- /dev/null
+++ b/cpumoncc/solaris/CpuMonitor.cc
@@ -0,0 +1,141 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/Solaris
+
+#include "CpuMonitor.h"
+
+CpuMonitor::CpuMonitor() : BaseCpuMonitor()
+{
+  initialize();
+}
+
+CpuMonitor::CpuMonitor(int cpu) : BaseCpuMonitor()
+{
+  which_cpu = cpu;
+  initialize();
+}
+
+void CpuMonitor::initialize()
+{
+  kstat_t *ksp;
+  int i = 0;
+
+  if (kc == NULL)
+    if ((kc = kstat_open()) == NULL)
+      throw runtime_error("CpuMonitor: can't open /dev/kstat.");
+  
+  if (which_cpu != -1)
+    {
+      /*
+       * User selected to monitor a particlur CPU. Find it...
+     */
+      for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
+	if ((strcmp(ksp->ks_module, "cpu_stat") == 0) && (ksp->ks_instance == which_cpu))
+	  {
+	    the_cpu = ksp;
+	    break;
+	  }
+      if (the_cpu == NULL) throw runtime_error("CpuMonitor: Cpu not found.");
+    }
+  else
+    {
+      /*
+       * User selected to monitor all CPUs.  First, count them.
+	 */
+      for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
+	if (strcmp(ksp->ks_module, "cpu_stat") == 0) i++;
+	
+      if (cpu_ksp_list) free(cpu_ksp_list);
+	
+      cpu_ksp_list = (kstat_t **) calloc(i * sizeof (kstat_t *), 1); 
+      ncpus = i;
+
+      /*
+       * stash the ksp for each CPU.
+       */
+      i = 0;
+      for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
+	if (strcmp(ksp->ks_module, "cpu_stat") == 0) 
+	  {
+	    cpu_ksp_list[i] = ksp;
+	    i++;
+	  }
+    }
+}
+
+float CpuMonitor::getLoad()
+{
+  int i;
+  cpu_stat_t stat;
+  int used, total, user = 0, wait = 0, kern = 0, idle = 0;
+  float t;
+
+  /*
+   * Read each cpu's data.  If the kstat chain has changed (a state change
+   * has happened, maybe a new cpu was added to the system or one went
+   * away), then reinitialize everything with initialize().  Finally,
+   * recursively call getLoad().
+   *
+   * We'll need to do a little better than this in the future, since we
+   * could recurse too much in the pathological case here.
+   */
+  if (which_cpu == -1)
+    {
+      for (i = 0; i < ncpus; i++)
+	{
+	  if (kstat_read(kc, cpu_ksp_list[i], (void *)&stat) == -1)
+	    {
+	      // Dont try-catch, let the caller of first getLoad() do that
+	      initialize();
+	      
+	      return getLoad();
+	    }
+	  user += stat.cpu_sysinfo.cpu[CPU_USER];   /* user */
+	  wait += stat.cpu_sysinfo.cpu[CPU_WAIT];   /* io wait */
+	  kern += stat.cpu_sysinfo.cpu[CPU_KERNEL]; /* sys */
+	  idle += stat.cpu_sysinfo.cpu[CPU_IDLE]; /*idle("free")*/
+	}
+    }
+  else
+    {
+      if (kstat_read(kc, the_cpu, (void *)&stat) == -1)
+	{
+	  // Dont try-catch, let the caller of first getLoad() do that
+	  initialize();
+	  
+	  return getLoad();
+	}
+      user += stat.cpu_sysinfo.cpu[CPU_USER];    /* user */
+      wait += stat.cpu_sysinfo.cpu[CPU_WAIT];    /* io wait */
+      kern += stat.cpu_sysinfo.cpu[CPU_KERNEL];  /* sys */
+      idle += stat.cpu_sysinfo.cpu[CPU_IDLE];    /* idle("free") */
+    }
+  
+  used = user + wait + kern;
+  total = used + idle;
+  t = range * (float)(used - previous_used) /  (float)(total - previous_total);
+  previous_total = total;
+  previous_used = used;
+  
+  return t;
+}
diff --git a/cpumoncc/solaris/CpuMonitor.h b/cpumoncc/solaris/CpuMonitor.h
new file mode 100644
index 0000000..5a1f00c
--- /dev/null
+++ b/cpumoncc/solaris/CpuMonitor.h
@@ -0,0 +1,53 @@
+/*
+
+ Copyright (C) 2003 Robert Kling, robkli-8 at student.luth.se
+
+ This file is part of CpuMonitorCC (cpumoncc)
+     
+ cpumoncc 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.
+
+ cpumoncc 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 cpumoncc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+// CpuMonitorCC/Solaris
+
+#ifndef _CPUMONITOR_H_
+#define _CPUMONITOR_H_
+
+#include <sys/types.h>
+#include <sys/sysinfo.h>
+#include <kstat.h>
+#include "BaseCpuMonitor.h"
+
+class CpuMonitor : public BaseCpuMonitor
+{
+public:
+  
+  CpuMonitor();
+  CpuMonitor(int cpu);
+  ~CpuMonitor();
+
+  float getLoad();
+
+private:
+
+  void initialize();
+  
+  kstat_ctl_t *kc;
+  kstat_t **cpu_ksp_list;
+  kstat_t *the_cpu;
+  int ncpus;
+};
+
+#endif
diff --git a/cpumoncc/solaris/Makefile b/cpumoncc/solaris/Makefile
new file mode 100644
index 0000000..84d09e3
--- /dev/null
+++ b/cpumoncc/solaris/Makefile
@@ -0,0 +1,40 @@
+######################################################
+#
+# To compile cpumoncc for a different OS/architecture you
+# will need to modify the variablese below to match your system.
+#
+# For system wide installation type (as root):
+#
+# make install
+#
+# This will install the static library in $(LIBINSTALL) and
+# the header files in $(HINSTALL)/cpumoncc.
+#
+#####################################################
+
+CXX=g++
+CXXFLAGS=-L/opt/sfw/lib -L/usr/local/lib -R/opt/sfw/lib -R/usr/local/lib -lkstat
+HINSTALL=/usr/include
+LIBINSTALL=/usr/lib
+
+#####################################################
+
+TARGET=libcpumoncc.a
+
+$(TARGET): CpuMonitor.o
+	ar rcs $(TARGET) $^
+
+CpuMonitor.o: copy_base
+
+copy_base:
+	cp ../base/BaseCpuMonitor.h .
+        
+install: $(TARGET)
+	mkdir -p $(HINSTALL)/cpumoncc
+	cp *.h $(HINSTALL)/cpumoncc
+	install -m 644 $(TARGET) $(LIBINSTALL)
+
+clean:
+	rm -f *~ core *.o cpu $(TARGET) BaseCpuMonitor.h
+	rm -fr $(HINSTALL)/cpumoncc
+	rm -f $(LIBINSTALL)/$(TARGET)
\ No newline at end of file
diff --git a/COPYING b/wmapp/COPYING
similarity index 98%
rename from COPYING
rename to wmapp/COPYING
index a43ea21..5197aee 100644
--- a/COPYING
+++ b/wmapp/COPYING
@@ -2,7 +2,7 @@
 		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                          675 Mass Ave, Cambridge, MA 02139, USA
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
 
 		     END OF TERMS AND CONDITIONS
 

-	Appendix: How to Apply These Terms to Your New Programs
+	    How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
 the "copyright" line and a pointer to where the full notice is found.
 
     <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
+    Copyright (C) yyyy  <name of author>
 
     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
@@ -305,14 +305,15 @@ the "copyright" line and a pointer to where the full notice is found.
 
     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., 675 Mass Ave, Cambridge, MA 02139, USA.
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
 
 Also add information on how to contact you by electronic and paper mail.
 
 If the program is interactive, make it output a short notice like this
 when it starts in an interactive mode:
 
-    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision version 69, Copyright (C) year name of author
     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type `show c' for details.
diff --git a/wmapp/Changelog b/wmapp/Changelog
new file mode 100644
index 0000000..fe9961f
--- /dev/null
+++ b/wmapp/Changelog
@@ -0,0 +1,82 @@
+Changelog for WMApp
+
+Version		Changes
+-------		-------
+0.0.4.1		* Bug fixes for 0.0.4:
+		* remove stray inline keyword from wmwidget.cc
+		* fix masking of shaped widgets in a non-transparent frame
+		* fix interpolation in WMEllipse::draw_border()
+		* remove WMCanvas::copy_buffer(); use WMCanvas::display()
+		  instead
+		* make planes in example2/wmradar.cc still light up when
+		  speed == 0; other cosmetic changes
+		* fix indentation in xwrapper.cc
+
+0.0.4		* this version of WMApp brought to you by Jason (see
+		  Changelog.Jason for greater detail)
+		* Improve consistency by changing header #include statements
+		  and class inheritance tree in places
+		* Add draw_arc() and fill_arc() functions to XWrapper and
+		  WMCanvas classes
+		* Add WMWidget::contains() function and give each pixmap its
+		  own GC to make creation of shaped widgets easier
+		* Add WMClickable base class
+		* Add WMEllipse base class: places its contents in an ellipse
+		  when inherited from
+		* Replace Color typedef with Color class, adding useful
+		  Color::alpha_blend() static function
+		* New example game, wmatc (WM Air Traffic Control), to
+		  illustrate integration of several widgets
+		* Fix bug that forced a need for setaspectratios() to always
+		  be called, even in case with only one child widget
+
+0.0.3		* Makefile simplification by Jason
+		* Tidy up the internals of WMCallback class, by Jason
+		* Each widget now has its own .h and .cc files for better
+		  source code modularity (delete the ones you don't need)
+		* Additions of WMCanvas draw_lines(), fill_polygon() methods
+		  by Jason
+		* Addition of buffered drawing mode for WMCanvas
+		* Optimization of WMImage real_display() function
+		* Clean up code for WMCanvas now that WMImage::icon() is
+		  the same size as the widget sans border
+
+0.0.2		* Addition of WMMouseClick::relative_to(WMWidget), allowing
+		  to more easily find the location of a mouseclick within
+		  a widget.
+		* Added b_* functions, giving coordinates of that part of a
+		  widget contained inside its border.
+		* Break up the example program into different files for
+		  clarity.
+		* Fix problem with WMImage not displaying background color
+		  in some circumstances.
+		* Renamed some member functions for greater consistency
+		  (setcallback() -> addcallback(), for instance)
+		* Changed API for timed interval functions in WMWindow.
+		* The order in which the two prototypes of callback functions
+		  are executed may now be interleaved.
+		* Add a WMCanvas widget for drawing purposes; the wmexample
+		  program (file example/window1.cc) shows how it may be used.
+		* Update FAQ.
+
+0.0.1		* New widget: WMSlider
+		* Buttons now depress when clicked upon.
+		* Any widget can now have a border, not just a WMFrame.
+		* Now easy to determine which mouse button was clicked.
+		* Widgets other than WMButton and WMWindow can have
+		  callbacks attached; see new FAQ.txt for details.
+		* Changes by Jason: (see Changelog.Jason for details)
+		* Fixed X resource leak
+		* Changed all instances of "NULL" to "0"
+		* Removed redundant constructors
+		* Cleaned up some code formatting
+
+0.0.0.20020502	* Added Changelog, small edits to README
+		* Sample program now called wmexample
+
+0.0.0.20020501	* Merged Jason's additions of WMHistory and WMMeterBar
+
+0.0.0.20011212	* First version of library in a usable form
+
+-Kevin B. McCarty <kmccarty at princeton.edu>
+
diff --git a/wmapp/Changelog.Jason b/wmapp/Changelog.Jason
new file mode 100644
index 0000000..dca2522
--- /dev/null
+++ b/wmapp/Changelog.Jason
@@ -0,0 +1,154 @@
+2003-01-05
+
+  * example2/wmradar.cc: Make planes still light up when speed == 0 (oops).
+    Other cosmetic changes.
+
+  * wmellipse.cc (draw_border(...)): Fix interpolation.
+
+  * wmwllipse.h: Remove obsolete comment.
+
+  * wmframe.cc: Fix masking when frame isn't transparent.
+
+  * wmframe.h: Add clipping mask data member. Move clip() to wmframe.cc.
+
+  * xwrapper.cc (draw_horizontal_gradient,draw_vertical_gradient):
+    Reformat indentation (it was so ugly!).
+
+  * FAQ.txt: Remove notes about ellipse/frame clipping bugs.
+
+  * wmcanvas.cc: Note that copy_buffer() is just a partial reimplementation
+    of WMImage::real_display(). So wBuffered is really just a class-wide
+    dodisplay setting. As such, replace calls to copy_buffer() with
+    display(). Might want to rename some things in light of this, as well as
+    remove copy_buffer().
+
+Some other days:
+
+  * example2/{wmradar.cc,wmradar.h,wmairtrafficcontrol.cc}: New example game
+    demonstrating the integration of several widgets.
+
+2002-12-28
+
+  * wmclickable.h: New class for clickable widgets.
+
+  * wmwindow.h wmframe.h, wmframe.cc, wmcallback.h: Use WMClickable.
+
+2002-12-21
+
+  * wmapp.cc: WMFrameBorderBright is too dim. Other dockapps look like
+    they use 0xC8C[38]C8.
+
+  * xwrapper.h, xwrapper.cc: Give each pixmap its own GC, and set clipping
+    mask to dest.mask if it's there. Enables me to remove kludgy use_mask().
+
+  * wmimage.cc, wmapp.cc, wmapp.h, wmcanvas.cc: Remove use_mask().
+
+  * wmimage.h, wmimage.cc: New function seticon(bool) to set a blank
+    b_width() by b_height() icon.
+
+  * wmcanvas.h, wmcanvas.cc: New functions draw_arc() and fill_arc().
+
+2002-12-20
+
+  * wmellipse.h, wmellipse.cc: New class WMEllipse, places its contents in
+    an ellipse.
+
+  * wmwidget.h: Add contains() function to WMWidget. This enables the
+    creation of arbitrarily shaped viewports, in the style of WMEllipse.
+  
+  * wmapp.h, wmapp.cc: Add use_mask() function, to muck with GC masking.
+    Needed so that WMEllipse is humanly possible.
+    Whenever drawing to the window, call app()->use_mask(true). When
+    drawing on any other pixmap, call use_mask(false). Default setting is
+    true. A better solution would be to have one GC for each window, and a
+    single GC for everything else.
+
+  * wmimage.cc, wmcanvas.cc: Modify to use use_mask.
+
+  * xwrapper.h, xwrapper.cc: New functions draw_arc() and fill_arc().
+  
+  * wmwidget.h, various: Put back WMFrame for parent().
+
+  * Widgets.txt: Update.
+
+2002-12-19
+
+  * xwapper.h: Fix header inclusion order problems. Now you can
+    #include "xwrapper.h" anywhere you like.
+
+  * wmframe.h, wmframe.cc: Simplify and improve consistency by inheriting
+    from WMCallback.
+
+  * wmwindow.h: Only inherit from WMFrame.
+
+  * various: Reorder #include statements to include only necessary files.
+    Use WMWidget* instead of WMFrame* for parent().
+
+  * Makefile, example/Makefile: Tweak.
+
+2002-05-08
+
+  * xwrapper.cc:
+  "Fixed" X memory leak caused by repetitive calls to XAllocColor. <rant>
+  Bizarrly, there doesn't appear to be a way to get the colormap index of an
+  RGB color without allocating it. Ideally, you would only allocate each color
+  once, but the only apparent way to do this is to keep your own custom
+  colormap with reference counts, since X won't tell you the index of a color
+  without allocating it. And without reference counts, the only way to keep
+  from allocating repeatedly is to deallocate after each allocation. But this
+  means that you're using colors which haven't been allocated. Realistically,
+  this doesn't matter except in 8 bit mode, where there aren't enough colors
+  for the spectrum-style WMMeterBar. In order to display well in 8 bit mode,
+  it seems that major color management is necessary, as X is far too stupid to
+  do it for us. Maybe I should look at Berlin again. </rant>
+
+2002-05-07
+
+  * wmwidgets.cc, wmwidgets.h, wmapp.h, wmextras.h xwrapper.cc,
+    example/wmexample.cc, FAQ.txt:
+  Removed all pointer comparisons/assignments to NULL. NULL isn't type-safe,
+  and in C++, "if (ptr != NULL)" is the same as "if (ptr)" because "No object
+  is allocated with the address 0" (Stroustrup 88).
+
+  * wmapp.cc, wmwidgets.cc:
+  Removed more redundant constructor calls.
+
+  * wmwidgets.cc, wmwidgets.h:
+  - Slight formatting fix again.
+  - Wrote a destructor for WMWindow to deallocate its pixmaps.
+  - Made initpixmaps() be called only once for each window. This fixes a
+    memory leak in X that occurred when switching windows.
+
+  * wmapp.cc, wmapp.h:
+  - Wrote a short destructor to deallocate windows (probably unnecessary).
+  - delete[]'d character arrays after XSetClassHint().
+
+  * xwrapper.cc, xwrapper.h:
+  Wrote a free_pixmap() function to complement create_pixmap (don't call
+  create_pixmap() on an existing pixmap without freeing it first!).
+
+2002-05-06
+  
+  * xwrapper.cc:
+  - Cleaned up get_point() a little.
+  - Added simple deallocation in Xwrapper::~Xwrapper ().
+
+  * wmapp.cc:69
+  Removed redundant assignment to static Xwrapper object after it was
+  already constructed (which caused my previous modification to crash due to
+  the destructor being called twice).
+
+  * wmwidgets.txt:
+  Added WMSlider to the class hierarchy and removed tabs.
+
+  * wmextras.h:
+  Removed redundant calls to base class constructors and members.
+  
+2002-05-05
+
+  * wmextras.cc:
+  Merged slider_click() and slider_scroll() into one, simpler/more readable
+  function.
+
+  * wmwidgets.cc:
+  Cleaned up my formatting a little.
diff --git a/wmapp/FAQ.txt b/wmapp/FAQ.txt
new file mode 100644
index 0000000..dd87cf8
--- /dev/null
+++ b/wmapp/FAQ.txt
@@ -0,0 +1,278 @@
+WMApp DockApp Library -- FAQ
+
+Starred items below are new or significantly updated for the latest release
+of WMApp, 0.0.4, or bug-fix release 0.0.4.1.
+
+1. Widget Layout
+	1.1. Can I specify widget positions in absolute coordinates?
+	*1.2. Help! My layout is all messed up!
+	1.3. Widgets that are all supposed to be the same size aren't.
+	1.4. How do I keep a frame from having transparent padding?
+
+2. Callbacks and timed-execution functions
+	2.1. How do I write a callback function?
+	2.2. Can I attach a callback to widgets other than the WMButton?
+	2.3. Which mouse button was pressed?
+	2.4. At what location was the widget clicked?
+	2.5. What is the story with callbacks on a WMWindow? (a.k.a.
+		executing functions at regular intervals)
+
+3. Specific widget questions
+	*3.1. How to use a WMCanvas?
+	*3.2. How to use a WMEllipse?
+	*3.3. How to create other shapes of widget?
+
+4. Memory issues
+	4.1. Why do I get a (segmentation fault | runtime error saying "pure
+		virtual function called") in my program?
+
+1.1. Can I specify widget positions in absolute coordinates?
+
+Yes, if you really must.
+
+Make sure the widget fits inside its parent widget, or there will probably be
+a mess.  The easiest way to do this is probably to set its position relative
+to its parent's:
+
+	widget.setposition(WMRectangle(parent.left()+wleft, parent.top()+wtop,
+			   wwidth, wheight));
+
+where wleft, wtop are the desired coordinates of the widget relative to the
+top left corner of its parent.  Remember that the 56x56 pixel WMWindow will
+have a different offset in Afterstep vs. WindowMaker mode, so at least
+operate relative to a previously declared WMWindow in all of your coordinates.
+
+If you are using both absolute positioning and automatic layout with
+setaspectratios(), you may get unexpected results.  See 1.3 for a better way.
+
+1.2. Help! My layout is all messed up!
+
+Always lay out widgets in the order from parent to child:
+
+	window.addchild(frame1);
+	window.addchild(frame2);
+	window.setaspectratios(2, 3);
+
+	frame1.addchild(textbar);
+	frame1.addchild(led);
+	frame1.addchild(meterbar);
+	textbar.setwidth(24);
+	frame1.setaspectratios(0, 4, 1);
+	// etc.
+
+Always set the border and padding for a frame before calling setaspectratios()
+on it.  [As of WMApp 0.0.4, you no longer have to call setaspectratios()
+explicitly when a frame has only one child, or when you want all children of a
+frame to be of equal size.]  And don't forget that borders around any widgets
+are included in their dimensions.
+
+1.3. Widgets that are all supposed to be the same size aren't.
+
+This is due to rounding in the process of setting widget aspect ratios.
+All accumulated rounding error ends up on the last widget in the frame.
+(TODO: spread out the rounding error more evenly)
+
+If you are a stickler for accuracy, you can draw your widget layout on
+a 56x56 grid.  Use the grid to determine the exact sizes, then in all calls
+to setaspectratios(), use these sizes.
+
+1.4. How do I keep a frame from having transparent padding?
+
+	frame.settransparency(false);
+
+Note: In order for a frame to _have_ transparent padding, its border thickness
+must also be zero.
+
+2.1. How do I write a callback function?
+
+There are two types of callback, with the prototypes
+
+	void callback1(const WMApp *a, void *data)
+	void callback2(const WMApp *a, WMWidget *w, void *data)
+
+First you write a function with one of these prototypes.  For instance,
+to exit the application, the callback function is simply
+
+	void halt(const WMApp *a, void *) { a->stop(); }
+
+Any additional data needed by the callback function may be passed as a pointer
+to void.  For convenience, you may pass in the address of one WMWidget to the
+second callback prototype without dealing with pointers to void.  Dynamic
+casting in the body of the callback function may be necessary; see the example
+program code in example/window0.cc for details.
+
+Given this, you may attach callbacks to a WMButton or other WMCallback object
+as follows:
+
+	button.addcallback(stop, 0 /* no additional data needed */);
+	button.addcallback(another_callback, &other_widget, &some_data);
+
+(Notice that the name changed from setcallback to addcallback!)
+When a WMButton is pressed, all the callbacks will be executed in the order
+in which they were attached.
+
+2.2. Can I attach a callback to widgets other than the WMButton or WMWindow?
+
+Yes!  Define a new class that inherits from both the desired widget and from
+WMCallback.  For example, the following code lets you clear a WMHistory
+widget by clicking on it.
+
+Note: if you are using a pointer to the inherited class as the "void *"
+argument of a callback function, be sure to first statically cast it to a
+"WMWidget *".  Dynamic casts from "void *" aren't guaranteed to work in C++.
+
+	// Define the new class
+	class WMHistoryCallback : public WMCallback, public WMHistory {
+	    public: WMHistoryCallback() : WMCallback(), WMHistory() { }
+	};
+
+	// Callback to clear a WMHistory widget when it's clicked on
+	void clearhistory(const WMApp *a, WMWidget *w, void *)
+	{       
+	    WMHistoryCallback *h = dynamic_cast<WMHistoryCallback *>(w);
+
+	    // check that dynamic_cast doesn't return null pointer!  maybe you
+	    // even want "assert(h)" instead of "if (h)"
+	    if (h) h->clear();
+	}
+
+	int main(int argc, char **argv)
+	{
+	    WMApp::initialize(argc, argv);
+	
+	    WMHistoryCallback h;
+	    h.addcallback(clearhistory, &h, 0);
+	    // ...
+	}
+
+2.3. Which mouse button was pressed?
+
+This can be retrieved from the application class.  The following code
+fragment is a callback that will execute only when mouse button 1 is
+released:
+
+	void callback(WMApp *a, void *)
+	{
+	    if (a->mouseclick().button != Button1) return;
+	    // body of function goes here
+	}
+
+Recall that in most cases (if XFree86 has been set up correctly), the "up" and
+"down" directions of a mouse scroll wheel correspond to Button4 and Button5.
+But don't forget while designing your program interface that not everyone has a
+scroll-wheel mouse!
+
+2.4. At what location was the widget clicked?
+
+Position of the mouse click relative to the _application_ may be retrieved
+within a callback via a->mouseclick().x and a->mouseclick().y .  Note that
+these are the coordinates of the cursor when the mouse button is _released_,
+which is when the callbacks are executed.  To make these coordinates useful,
+you probably want to use a->mouseclick().relative_to(w).x and .y, where w is a
+pointer to the widget executing the callback.  This gives the coordinates
+of the mouseclick relative to the left and top bounds of the widget.  You
+can get the coordinates relative only to the part of the widget INSIDE its
+border using the b_relative_to() function.
+
+The most recent mouse button release may also be examined outside any callback
+functions.  Keep in mind that this will not necessarily correspond to the
+execution of any callback functions, since the mouse may have been clicked
+over a widget with no callbacks.
+
+2.5. What is the story with callbacks on a WMWindow? (a.k.a. executing
+functions at regular intervals)
+
+In version 0.0.1, there existed a WMWindow::setcallback() method.  This
+actually didn't set callbacks, but instead set functions to execute at regular
+intervals (for use in clocks, timing out internet connections, etc.).  Since
+the name was confusing, in 0.0.2 I've replaced it by the
+WMWindow::add_timed_function() method.
+
+As with callbacks, there are two types of possible timed-execution functions:
+
+	void timed_function1(WMApp *, WMWidget *);
+	void timed_function2(WMApp *, WMWidget *, void * data);
+
+They should be attached to a window as follows:
+
+	window.add_timed_function(period, timed_function1, &some_data);
+	window.add_timed_function(period, timed_function2, &a_widget, &data);
+
+where "period" is an integer that specifies how often the timed-execution
+function should run, in centiseconds (e.g. to run a function every 5 seconds,
+use a period of 500).  You can change this base time interval of 10 millisec
+using the WMWindow::setupdatefreq() member function.
+
+Of course, these regular intervals are not exact, since they do not take into
+account the times needed to redraw widgets, execute callback functions, and
+execute the timed-execution functions themselves.  Don't rely on them for
+air traffic control.  (Of course, Jason went ahead and did just that --
+see the code in the example2 directory, or just "make wmatc")
+
+For an example use, see the code for the clock in example/window0.cc.
+
+3.1. How to use a WMCanvas?
+
+The canvas widget may be used in two modes: buffered and unbuffered.  To
+switch between them: wmcanvas_ptr->setbuffered(true) [or false, whichever].
+In unbuffered mode (the default), any drawings upon the widget will immediately
+be copied to the WMWindow pixmap, and will show up the next time the
+WMApp::repaint() method is called.  In buffered mode, changes to the WMCanvas
+will not be copied to the WMWindow's pixmap until the WMCanvas::display()
+method is called.  The advantage to buffered mode is that it uses less CPU
+and it lets you make a number of changes that display all at once.
+
+There are a number of drawing functions available.  WMCanvas is stateful, so
+you must set the drawing color with WMCanvas::setcolor each time you want to
+draw in a different color.  Having set the desired color (if unset, it defaults
+to the traditional WMApp foreground turquoise-ish color), you may use various
+drawing methods.  The x and y coordinates in these drawing methods are always
+relative to the INSIDE of the WMCanvas widget (i.e. not including the border).
+
+setcolor(Color c)
+	Set the current drawing color to c.
+draw_point(int x, int y)
+	Draw a [1-pixel wide] point at position (x,y).
+draw_line(int x1, int y1, int x2, int y2)
+	Draw a line from (x1,y1) to (x2,y2).
+draw_lines(const vector<X::XPoint> & points)
+	Draw a set of connected lines (think connect-the-dots) from point to
+	point.
+
+The full list of drawing methods may of course be found in wmcanvas.h.
+For a somewhat trivial example use of a WMCanvas with an attached callback
+function (the world's dumbest paint program), see the code located in
+example1/window1.cc.  A more interesting use is prototyped in
+example2/wmradar.h.
+
+3.2. How to use a WMEllipse?
+
+To create an elliptical widget, make a new class that inherits from both the
+desired widget and from the WMEllipse.  This will usually work trivially as
+shown in the two example programs.
+
+3.3. How to create other shapes of widget?
+
+Using wmellipse.h and wmellipse.cc as models, you just have to write a
+"contains" method that specifies which points are inside the borders of
+your shape, and a "draw_border" method that tells how to draw a border for
+your shape.  Inherit from both your shape and from some WMWidget.  Clipping,
+execution of callbacks when the mouse is clicked inside your shape, and so on,
+will be done automagically by the library.
+
+4.1. Why do I get a (segmentation fault | runtime error saying "pure virtual
+function called") in my program?
+
+If you write a function that returns a WMFrame or WMWindow complete with
+all its child widgets set up, the child widgets must have been either declared
+static inside that function, or else allocated on the heap with "new".
+Otherwise they do not exist in memory at the time the WMApp tries to display
+them.  This is clearly bad :-)
+
+I presume that the misleading "pure virtual function called" error occurs
+because the run-time type identification of the C++ program sees garbage at a
+memory location which is supposed to be a class inherited from WMWidget.  Then,
+having no idea what to make of the garbage, the program casts it to the base
+class WMWidget, resulting in a call to WMWidget::real_display(), a pure virtual
+function.  Or something like that.
+
diff --git a/wmapp/Makefile b/wmapp/Makefile
new file mode 100644
index 0000000..2b773fb
--- /dev/null
+++ b/wmapp/Makefile
@@ -0,0 +1,35 @@
+export CXX     = g++
+export CFLAGS  = -fPIC -g -Wall -pedantic -O2
+export LFLAGS  = -L$(CURDIR) -L/usr/X11R6/lib -lXpm -lXext -lX11 -lwmapp
+
+SOURCES = $(wildcard *.cc)
+OBJECTS = $(SOURCES:.cc=.o)
+
+libwmapp.a: $(OBJECTS)
+	ar rcs libwmapp.a $^
+
+%.d: %.cc
+	@set -e; $(CXX) -MM $(CFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
+		   [ -s $@ ] || rm -f $@
+
+-include $(SOURCES:.cc=.d)
+
+%.o:
+	$(CXX) $(CFLAGS) -c $< -o $@
+
+wmexample: libwmapp.a
+	$(MAKE) -C example1
+
+wmatc: libwmapp.a
+	$(MAKE) -C example2
+
+clean:
+	-rm -f tags *.o *.d *\~ libwmapp.a
+	$(MAKE) -C example1 clean
+	$(MAKE) -C example2 clean
+	
+dist-clean: clean
+	-rm -f libwmapp.a wmexample wmatc
+
+.PHONY:	all clean dist-clean wmexample wmatc
+
diff --git a/wmapp/README b/wmapp/README
new file mode 100644
index 0000000..71f8a0c
--- /dev/null
+++ b/wmapp/README
@@ -0,0 +1,66 @@
+WMApp: version 0.0.4.1
+Copyright (C) 2001-2003 Kevin and Jason McCarty <kmccarty at princeton.edu>
+			and others (see code for details)
+Licensed under the GNU GPL (see COPYING file).
+
+This is WMApp, a C++ graphics library written exclusively for developing
+WindowMaker dockapps.  If you like dockapps, but you also like C++ and you
+are tired of trying to work with the code in wmgeneral.c, this library is
+for you!
+
+For an example program based on this library, check out the source code
+in the example directory.  This program is long on eyecandy and short
+on usefulness, but it gives an idea of what is possible.  "make wmexample"
+to build it.
+
+Features
+--------
+- Dockapp windows are set up automatically for you.
+- State model: a dockapp may be in one of several states ("windows"), which
+  can each look different and have different functionality
+- On-the-fly clipping; no more masking xpms needed!
+- Simple callback model: attach as many callback functions to each button
+  as desired.  Callbacks can take arbitrary data as an argument, change
+  the properties of other widgets, and even switch between dockapp states.
+- You may automatically execute a list of functions (different for each window)
+  at set intervals of time.  Useful for clocks, CPU load displays, etc.
+- Numerous widgets, all with the familiar dockapp look.  The color scheme
+  of many may be changed.  Many common WindowMaker dockapps could already
+  be rewritten to use this library.
+
+Widgets
+-------
+- Text box for conveying information; comes with three font sizes.
+- Progress meter to show changes in a quantity, e.g. percent download.
+- History display to show how a quantity changes over time, e.g. CPU load.
+- Buttons (optionally with an image) that can have callback functions set
+  and can be activated and deactivated.
+- Images that may display an XPM icon.
+- Glowing LED-type things that may be in one of four states:
+  off, green, yellow, and red.
+- Frames in which widgets (including other frames) may be nested.  Frames
+  may have a border and / or padding between their contents.
+- Sliders that may be moved up and down with the mouse wheel
+  (or by clicking) to set a value.
+- Canvas that may be drawn upon with various drawing functions.
+
+Most of the above widgets may also inherit from one or more of the following
+for additional features:
+
+- Elliptical widget that clips contents to an ellipse
+- Callback widget that can execute actions when clicked upon
+
+Limitations
+-----------
+- Still not guaranteed not to leak memory or X resources
+- API is not guaranteed to be backwards compatible when it changes
+  (note the version number)
+- The executables produced with this library are several times larger
+  than those created using wmgeneral.c.
+- WMApp does not support dynamic widget resizing.
+- Text box fonts do not have lowercase letters.  (They can easily be
+  implemented -- just edit the character maps in the xpm directory --
+  but I think they would look quite bad due to the small fonts.)
+- Changing the color of the fonts is not supported at runtime.  (You can
+  of course do this at compile time by editing the font XPMs.)
+
diff --git a/wmapp/Widgets.txt b/wmapp/Widgets.txt
new file mode 100644
index 0000000..e5722e3
--- /dev/null
+++ b/wmapp/Widgets.txt
@@ -0,0 +1,49 @@
+WMWidgets Class Hierarchy
+
+Note: * represents widgets which cannot be instantiated, only inherited from
+Only public inheritances are shown in this diagram.
+
+WMWidget* - Base class for all widgets
+  |
+  +--WMEllipse* - Inherited widgets are displayed inside an ellipse
+  |
+  +--WMTextBar - Draw a string of text
+  |
+  +--WMMeter* - Base class for meter widgets
+  |    |
+  |    +--WMMeterBar - A bar that displays a quantity by ranging from
+  |         |          empty to full
+  |         +--WMSlider - A bar that can be slid up or down to set a value
+  |                       (also inherits from WMCallback)
+  |
+  +--WMHistory - Show a graph of how a quantity has been varying with time
+  |
+  +--WMImage - Display an XPM on a region of the window
+  |    |
+  |    +--WMCanvas - Display a region which may be changed by drawing functions
+  |    |
+  |    +--WMLED - Display an image of an LED in one of four states
+  |    |
+  |    +--WMButton - A button which, when pressed, executes one or more
+  |        ^         callback functions
+  |        |       - may also have an image on it
+  |        |
+  +--WMCallback* - A widget that can execute callback functions when clicked
+  |   ^
+  |   |
+  |  WMClickable* - (does not inherit from WMWidget)
+  |   |             Inherited widgets must specify what happens when
+  |   |             a mouse button is pressed or released, by defining
+  |   |		    press() and release() methods.
+  |   v
+  +--WMFrame - A widget which contains other widgets and may have an optional
+       |       border
+       +--WMWindow - The topmost level widget.  All other widgets must be
+                     contained (recursively) by this widget in order to be
+                     displayed
+  
+
+WMApp - Contains one or more WMWindows.  Only one WMWindow may be displayed
+        on screen at a time.  (WMWindows are still active in the background
+        when not displayed, unless they are set otherwise.)
+
diff --git a/wmapp/colors.h b/wmapp/colors.h
new file mode 100644
index 0000000..b7eedce
--- /dev/null
+++ b/wmapp/colors.h
@@ -0,0 +1,54 @@
+#ifndef WM_COLORS_H
+#define WM_COLORS_H
+
+#define SLICE(_int, _bit) (((_int) >> (_bit)) & 0xff)
+
+class Color {
+  unsigned char _R, _G, _B;
+
+ public:
+  Color(unsigned long int li = 0) 
+    : _R(SLICE(li, 16)), _G(SLICE(li, 8)), _B(SLICE(li, 0)) { }
+  Color(int R, int G, int B) : _R(R), _G(G), _B(B) { }
+  
+  bool operator ==   (const Color & c) const
+    { return _R == c._R && _G == c._G && _B == c._B; }
+  bool operator !=   (const Color & c) const
+    { return ! operator==(c); }
+
+  unsigned char r() const { return _R; }
+  unsigned char g() const { return _G; }
+  unsigned char b() const { return _B; }
+  
+  static Color alpha_blend(const Color & c1, const Color & c2, double weight1)
+  {       
+    double weight2 = 1.0 - weight1;
+    int r = static_cast<int>(c1.r() * weight1 + c2.r() * weight2 + 0.5);
+    int g = static_cast<int>(c1.g() * weight1 + c2.g() * weight2 + 0.5);
+    int b = static_cast<int>(c1.b() * weight1 + c2.b() * weight2 + 0.5);
+    return Color(r, g, b);
+  }
+};
+
+#undef SLICE
+
+#define WMColor(x) (WMApp::colormap[static_cast<int>(WMColor:: x)])
+
+namespace WMColor {
+  enum WMColor {
+    Background, // Background of WMFrames and WMImages
+    Dim,	// Dark drawing color
+    Medium,	// Medium drawing color
+    Bright,	// Light drawing color
+    ButtonFace,	// Color of face of buttons
+    ButtonBorderDim,	// Colors of borders of WMButtons
+    ButtonBorderMedium,
+    ButtonBorderBright,
+    FrameBorderDim,	// Colors of borders of WMFrames
+    FrameBorderMedium,
+    FrameBorderBright
+  };
+  const int numcolors = 11;
+}
+
+#endif
diff --git a/wmapp/example1/Makefile b/wmapp/example1/Makefile
new file mode 100644
index 0000000..d6a5575
--- /dev/null
+++ b/wmapp/example1/Makefile
@@ -0,0 +1,13 @@
+OBJECTS = wmexample.o window0.o window1.o
+
+../wmexample: $(OBJECTS) ../libwmapp.a
+	$(CXX) $(CFLAGS) $(OBJECTS) $(LFLAGS) -o $@
+
+$(OBJECTS): %.o: %.cc ../*.h
+	$(CXX) $(CFLAGS) -c $< -o $@
+
+clean:
+	rm -f *.o *\~
+
+.PHONY:	clean
+
diff --git a/wmapp/example1/debian-tiny.xpm b/wmapp/example1/debian-tiny.xpm
new file mode 100644
index 0000000..065ed64
--- /dev/null
+++ b/wmapp/example1/debian-tiny.xpm
@@ -0,0 +1,50 @@
+/* XPM */
+static char * debian_tiny_xpm[] = {
+"9 9 38 1",
+" 	c None",
+".	c #AEAAAE",
+"+	c #AB9194",
+"@	c #A87173",
+"#	c #AA8487",
+"$	c #AEA5A9",
+"%	c #A76568",
+"&	c #A23B3D",
+"*	c #A9787B",
+"=	c #A76C6F",
+"-	c #A03132",
+";	c #AC999C",
+">	c #AC9396",
+",	c #A65E60",
+"'	c #AEA9AD",
+")	c #AD9598",
+"!	c #AE9DA1",
+"~	c #A97C7F",
+"{	c #A96E70",
+"]	c #A76A6C",
+"^	c #ADA0A4",
+"/	c #AD9B9F",
+"(	c #AD989C",
+"_	c #AD9B9E",
+":	c #A86E70",
+"<	c #A86D70",
+"[	c #AEA6AA",
+"}	c #AE9DA0",
+"|	c #AC8689",
+"1	c #AA797C",
+"2	c #AD9DA1",
+"3	c #AA8689",
+"4	c #A97679",
+"5	c #AD8C8F",
+"6	c #AB8184",
+"7	c #A6585A",
+"8	c #A97476",
+"9	c #AE9EA2",
+"...+@#$..",
+"..%&*=-;.",
+".>,')!~{.",
+".]^/(._:.",
+".<[}|[12.",
+".34.56/..",
+".'7[.....",
+"..^89....",
+"....$...."};
diff --git a/wmapp/example1/window0.cc b/wmapp/example1/window0.cc
new file mode 100644
index 0000000..032a74e
--- /dev/null
+++ b/wmapp/example1/window0.cc
@@ -0,0 +1,204 @@
+#include "../wmapp.h"
+#include "../wmframe.h"
+#include "../wmwindow.h"
+#include "../wmtextbar.h"
+#include "../wmslider.h"
+#include "../wmled.h"
+#include "../wmmeterbar.h"
+#include "../wmhistory.h"
+#include "../wmbutton.h"
+#include "../wmellipse.h"
+
+#include "../xpm/checkbox.xpm"
+#include "../xpm/xbutton.xpm"
+#include "debian-tiny.xpm"
+
+// for the clock:
+#include <time.h>
+#include <sys/timeb.h>
+
+// This file defines a window that contains various widgets to demonstrate
+// the WMApp library.  Also it is shown how to make a clock widget.
+
+// Callbacks for the buttons -----------------------------------------------
+
+// This one ends the program (always useful) and will be attached to the
+// button with the "X".
+void
+halt(const WMApp *a, void *) { a->stop(); }
+
+// The following three callbacks will be attached to the checkbox button:
+
+// This one changes the state of the middle LED if mousebutton 1 is clicked.
+void
+ledset(const WMApp *a, WMWidget *w, void *)
+{
+  if (a->mouseclick().button != Button1) return;
+
+  WMLed *l = dynamic_cast<WMLed *>(w);
+  if (l) {
+    l->setled(static_cast<WMLed::LedState>((1 + l->led()) % 4));
+    a->repaint();
+  }
+}
+
+// This one toggles the style of the vertical meter if button 2 is clicked.
+void
+togglegraphstyle (const WMApp *a, WMWidget *w, void *)
+{
+  if (a->mouseclick().button != Button2) return;
+	
+  WMMeterBar *m = dynamic_cast<WMMeterBar *>(w);
+  if (m) {
+    m->setstyle(static_cast<WMMeterBar::Style>((1 + m->style()) % 3));
+    m->setorientation((m->orientation() == Orientation::Horizontal) ? 
+      Orientation::Vertical : Orientation::Horizontal);
+    a->repaint();
+  }
+}
+
+// This one toggles whether the "close" button can be pressed if mouse
+// button 3 is clicked.
+void
+toggleclose(const WMApp *a, WMWidget *w, void *)
+{
+  if (a->mouseclick().button != Button3) return;
+	
+  WMButton *b = dynamic_cast<WMButton *>(w);
+  if (b && b->is_active()) b->deactivate();
+  else if (b && !b->is_active()) b->activate();
+}
+
+// This callback will be attached to the Debian button.  It switches
+// between windows.
+// Note: if the last statement in a callback function requests
+// a switch to a new window, you don't need a "repaint()".
+void
+switch_to_1(const WMApp *a, void *)
+{ a->switch_to(1); }
+
+// Define a class that will be a WMHistory widget with callbacks
+class WMHistCallback : public WMCallback, public WMHistory, public WMEllipse {
+ public: WMHistCallback() : WMCallback(), WMHistory(), WMEllipse() { }
+};
+
+// Callback to clear this widget when it's clicked on
+void
+clearhistory(const WMApp *a, WMWidget *w, void *)
+{
+  WMHistCallback *h = dynamic_cast<WMHistCallback *>(w);
+  if (h) h->clear();
+}
+     
+// Callbacks for the windows -----------------------------------------------
+// Window callbacks are executed every 50 milliseconds (by default; you
+// can set this value) for the currently displayed window.
+
+// This function will update the time on the clock display every 5 seconds.
+void
+displaytime(const WMApp *a, WMWidget *w, void *)
+{
+  struct timeb currenttime;
+  string timestr;
+  WMTextBar *b = dynamic_cast<WMTextBar *>(w);
+  
+  if (!b) return;
+  ftime(&currenttime);
+  // extract current time from date-and-time string
+  timestr = string(ctime(&currenttime.time) + 11);
+  b->settext(timestr);
+  a->repaint();
+}
+
+// make random increments to the meterbar and history every 150 ms
+void
+updatehist (const WMApp *a, WMWidget *w1, void *w2)
+{
+  WMMeterBar *b = dynamic_cast<WMMeterBar *>(w1);
+  if (b) {
+    int increment = static_cast<int>(b->value() - 13 
+		    + 31 * static_cast<float>(rand()) / RAND_MAX) + 307;
+    //I added 307 becuase gcc does bad things to a signed dividend in a modulus,
+    //which makes for *interesting* results
+ 
+    b->setvalue(increment % 307, 306);
+  }
+  
+  WMHistory *h = dynamic_cast<WMHistory *>(static_cast<WMWidget *>(w2));
+  if (b && h) h->setvalue(b->value());
+  a->repaint();
+}
+ 
+// The function where we lay out all the widgets ---------------------------
+
+void
+makewindow0(WMWindow *w0)
+{
+  // Everything following is GUI boilerplate code.
+  static WMFrame top, mid, bottom, topright, botright;
+  static WMTextBar time("00:00", 0);
+  static WMSlider slider(30, 50);
+  static WMLed l, m, r;
+  static WMMeterBar meterbar;
+  static WMHistCallback history;
+  static WMButton debian, go, stop;
+  
+  w0->add_timed_function(500, displaytime, &time, 0);
+  w0->add_timed_function(15, updatehist, &meterbar,
+		         dynamic_cast<WMWidget *>(&history));
+  w0->addchild(top);
+  w0->addchild(mid);
+  w0->addchild(bottom);
+  w0->setorientation(Orientation::Vertical);
+  w0->setaspectratios(1, 2, 1);
+
+  top.addchild(time);
+  top.addchild(topright);
+  top.setaspectratios(6, 5);
+
+  mid.addchild(history);
+  mid.addchild(slider);
+  slider.setorientation(Orientation::Vertical);
+  mid.setaspectratios(3, 1);
+  
+  bottom.addchild(meterbar);
+  bottom.addchild(botright);
+  bottom.setaspectratios(1, 2);
+  
+  topright.addchild(l);
+  topright.addchild(m);
+  topright.addchild(r);
+  topright.setpadding(0);
+  topright.setborder(1);
+
+  botright.addchild(debian);
+  botright.addchild(go);
+  botright.addchild(stop);
+  botright.setpadding(0);
+  botright.setborder(1);
+  
+  l.setled(WMLed::Good);
+  r.setled(WMLed::Error);
+
+  // should set initial total of seconds
+  srand(std::time(0));
+  meterbar.setstyle(WMMeterBar::Spectrum);
+  meterbar.setvalue(150, false);
+  meterbar.settotal(306, false);
+  history.settotal(306, false);
+  history.addcallback(clearhistory, &history, 0);
+  
+  debian.seticon(debian_tiny_xpm);
+  debian.addcallback(switch_to_1, 0);
+  
+  go.seticon(checkbox_xpm);
+  go.addcallback(ledset, &m, 0);
+  go.addcallback(toggleclose, &stop, 0);
+  go.addcallback(togglegraphstyle, &meterbar, 0);
+  
+  // Let's start this button out in an inactive state, just for fun.
+  stop.deactivate();
+  stop.seticon(xbutton_xpm);
+  stop.addcallback(halt, 0);
+}
+
diff --git a/wmapp/example1/window1.cc b/wmapp/example1/window1.cc
new file mode 100644
index 0000000..644cad5
--- /dev/null
+++ b/wmapp/example1/window1.cc
@@ -0,0 +1,86 @@
+#include "../wmapp.h"
+#include "../wmwindow.h"
+#include "../wmframe.h"
+#include "../wmcanvas.h"
+#include "../wmbutton.h"
+#include "../wmellipse.h"
+#include "debian-tiny.xpm"
+
+// This file creates a window with a small, very simple paint program.
+
+// Define a class that will be a WMCanvas widget with callbacks
+class WMPainter : public WMCallback, public WMCanvas, public WMEllipse {
+  public: WMPainter() : WMCallback(), WMCanvas() { }
+};
+
+// Make one of the buttons elliptical.
+class WMEllipticalButton : public WMEllipse, public WMButton {
+  public: WMEllipticalButton() : WMEllipse(), WMButton() { }
+};
+
+// Callback to paint onto this widget when it's clicked on
+void
+paint(const WMApp *a, WMWidget *w, void *)
+{
+  WMMouseClick click = a->mouseclick().b_relative_to(w);
+  WMPainter *p = dynamic_cast<WMPainter *>(w);
+  // draw a 3x3 square at the mouse location clicked upon
+  if (p) p->fill_rectangle(click.x - 2, click.y - 2, 3, 3);
+  a->repaint();
+}
+
+// Callbacks for the buttons -----------------------------------------------
+
+// This callback changes the current paint color of the WMCanvas, depending
+// upon which button was pressed.
+void
+changecolor(const WMApp *a, WMWidget *w, void *color)
+{
+  WMColor::WMColor c = *static_cast<WMColor::WMColor *>(color);
+  WMPainter *wp = dynamic_cast<WMPainter *>(w);
+  if (wp) wp->setcolor(c);
+}
+
+// This callback will be attached to the big button
+// on the second window.  It switches between windows.
+// Note: if the last statement in a callback function requests
+// a switch to a new window, you don't need a "repaint()".
+void
+switch_to_0(const WMApp *a, void *)
+{ a->switch_to(0); }
+
+void makewindow1(WMWindow *w1)
+{
+  static WMEllipticalButton debianwin;
+  static WMEllipticalButton colorbutton[4];
+  static WMFrame top, topleft, bottom;
+  static WMPainter drawing;
+  static int colors[4] = { 0x000000, 0xFF0000, 0x00FF00, 0x0000FF };
+  
+  w1->addchild(top);
+  w1->addchild(bottom);
+  w1->setorientation(Orientation::Vertical);
+  w1->setaspectratios(1, 3);
+
+  top.addchild(topleft);
+  top.addchild(debianwin);
+  top.setaspectratios(4, 1);
+  
+  topleft.setpadding(0);
+  topleft.setborder(1);
+  topleft.settransparency(false);
+  
+  for (unsigned int i = 0; i < 4; i++) {
+    colorbutton[i].setbgcolor(colors[i]);
+    colorbutton[i].addcallback(changecolor, &drawing, colors + i);
+    topleft.addchild(colorbutton[i]);
+  }
+  
+  debianwin.seticon(debian_tiny_xpm);
+  debianwin.addcallback(switch_to_0, 0);
+  
+  drawing.addcallback(paint, &drawing);
+  bottom.addchild(drawing);
+  drawing.setborder(4);
+}
+
diff --git a/wmapp/example1/wmexample.cc b/wmapp/example1/wmexample.cc
new file mode 100644
index 0000000..b83b72c
--- /dev/null
+++ b/wmapp/example1/wmexample.cc
@@ -0,0 +1,39 @@
+#include "../wmapp.h"
+#include "../wmwindow.h"
+
+// This is an example WindowMaker dockapp program written using the
+// WMApp dockapp library.  The first window shows off various widgets
+// and demonstrates how to make a clock.  The second window illustrates
+// a miniature paint program.
+
+extern void makewindow0(WMWindow *w0_ptr); // see window0.cc
+extern void makewindow1(WMWindow *w1_ptr); // see window1.cc
+
+// The main() function, where we lay out all the widgets -------------------
+// The files window0.cc and window1.cc are much more interesting.
+
+int main(int argc, char *argv[])
+{
+  // This should always be the very first line in the main() function of
+  // a WMApplication:
+  WMApp::initialize(argc, argv);
+
+  WMApp a;
+  WMWindow w0, w1;
+  makewindow0(&w0);
+  makewindow1(&w1);
+
+  // Attach windows to the application
+  a.addwindow(w0);
+  a.addwindow(w1);
+
+  // This makes everything go.
+  a.run();
+
+  // Any cleanup code after the window closes should go here.
+  // (In this case, none is needed.)
+  
+  return 0;
+}
+
+
diff --git a/wmapp/example2/Makefile b/wmapp/example2/Makefile
new file mode 100644
index 0000000..b8ed170
--- /dev/null
+++ b/wmapp/example2/Makefile
@@ -0,0 +1,13 @@
+OBJECTS = wmairtrafficcontrol.o wmradar.o
+
+../wmatc: $(OBJECTS) ../libwmapp.a
+	$(CXX) $(CFLAGS) $(OBJECTS) $(LFLAGS) -o $@
+
+$(OBJECTS): %.o: %.cc ../*.h wmradar.h
+	$(CXX) $(CFLAGS) -c $< -o $@
+
+clean:
+	rm -f *.o *\~
+
+.PHONY:	clean
+
diff --git a/wmapp/example2/wmairtrafficcontrol.cc b/wmapp/example2/wmairtrafficcontrol.cc
new file mode 100644
index 0000000..89df1ce
--- /dev/null
+++ b/wmapp/example2/wmairtrafficcontrol.cc
@@ -0,0 +1,80 @@
+#include <ctime>
+#include <cstdlib>
+#include "wmradar.h"
+#include "../wmslider.h"
+#include "../wmcallback.h"
+#include "../wmapp.h"
+#include "../wmwindow.h"
+#include "../wmframe.h"
+#include "../wmbutton.h"
+#include "../xpm/xbutton.xpm"
+
+//WM Air Traffic Control: The FAQ said don't rely on callback timings for
+//air traffic control, so I did.
+//
+//Click on the radar to change the nearest plane's heading towards that point.
+//Move the slider to change the planes' speed.
+//If two planes collide, they will disappear, a red point will appear, and
+//the score will be incremented.
+
+void
+halt(const WMApp *a, void *) { a->stop(); }
+
+void add_plane(const WMApp* a, WMWidget* w, void*)
+{
+  if (!(std::rand() % 3))
+  {
+    WMRadar* r = dynamic_cast<WMRadar*>(w);
+    if (r)
+      r->add_plane();
+  }
+}
+
+void increment_time(const WMApp* a, WMWidget* w, void*)
+{
+  WMRadar* r = dynamic_cast<WMRadar*>(w);
+  if (r)
+    r->increment_time();
+  a->repaint();
+}
+
+int main(int argc, char *argv[])
+{
+  WMApp::initialize(argc, argv);
+
+  WMApp a;
+  WMWindow win;
+
+  WMTextBar score;
+  WMSlider speed;
+  WMRadar radar(&score, &speed);
+  WMFrame left, right;
+  WMButton quit;
+  
+  win.add_timed_function(1, increment_time, &radar, 0);
+  win.add_timed_function(80, add_plane, &radar, 0);
+  win.addchild(left);
+  win.addchild(right);
+  win.setaspectratios(50, 15);
+
+  left.addchild(radar);
+  left.addchild(score);
+  left.setorientation(Orientation::Vertical);
+  left.setaspectratios(50, 15);
+
+  right.addchild(speed);
+  right.addchild(quit);
+  right.setorientation(Orientation::Vertical);
+  right.setaspectratios(50, 15);
+
+  quit.seticon(xbutton_xpm);
+  quit.addcallback(halt, 0);
+
+  speed.setorientation(Orientation::Vertical);
+
+  std::srand(std::time(0));
+  
+  a.addwindow(win);
+  a.run();
+  return 0;
+}
diff --git a/wmapp/example2/wmradar.cc b/wmapp/example2/wmradar.cc
new file mode 100644
index 0000000..8344c1e
--- /dev/null
+++ b/wmapp/example2/wmradar.cc
@@ -0,0 +1,220 @@
+#include <cstdlib>
+#include <cmath>
+#include <sstream>
+#include <iomanip>
+#include "wmradar.h"
+#include "../wmapp.h"
+
+using std::sin;
+using std::cos;
+using std::atan2;
+
+WMRadar::WMRadar(WMTextBar* t, WMSlider* s)
+: angle(0), text_score(t), speed(s)
+{
+  setbuffered(true);
+  text_score->settext("     0", false);
+  speed->settotal(50, false);
+  speed->setvalue(8, false);
+}
+
+void
+WMRadar::real_display()
+{
+  if (!p_icon())
+    seticon(false);
+  setcolor(WMColor(Background));
+  fill_rectangle(0, 0, b_width(), b_height()); //clear background
+
+  setcolor(WMColor(Dim));
+  for (double i = 0; i < 2 * M_PI; i += M_PI_4)
+    draw_line(b_width() / 2, b_height() / 2, (1 + cos(i)) * b_width() / 2,
+        (1 - sin(i)) * b_height() / 2); //draw radial lines
+  
+  draw_arc(b_width() / 3, b_height() / 3, b_width() / 3 - 1, b_height() / 3 - 1,
+      0, 360 * 64);
+  draw_arc(b_width() / 6, b_height() / 6, 2 * b_width() / 3,
+      2 * b_height() / 3, 0, 360 * 64); //draw circles
+
+  setcolor(Color(255, 0, 0));
+  for (clist::const_iterator i = collisions.begin(); i != collisions.end(); ++i)
+    fill_arc(i->x - 1, i->y - 1, 3, 3, 0, 360 * 64); //draw collision points
+  
+  std::vector<X::XPoint> points(3);
+  for (plist::const_iterator i = planes.begin(); i != planes.end(); ++i)
+  {
+    setcolor(Color(0, 255 * i->brightness, 0)); // achieve a fading effect
+    points[0].x = i->x;
+    points[0].y = i->y;
+    points[1].x = int(i->x) + 7 * cos(i->direction + 5.5 * M_PI / 6);
+    points[1].y = int(i->y) - 7 * sin(i->direction + 5.5 * M_PI / 6);
+    points[2].x = int(i->x) + 7 * cos(i->direction + 6.5 * M_PI / 6);
+    points[2].y = int(i->y) - 7 * sin(i->direction + 6.5 * M_PI / 6);
+    // construct an isoceles triangle pointing in plane's direction of motion
+    fill_polygon(points); // and draw it
+  }
+
+  setcolor(Color(0, 255, 0));
+  draw_line(b_width() / 2, b_height() / 2, (1 + cos(angle)) * b_width() / 2,
+      (1 - sin(angle)) * b_height() / 2); //draw radar line
+
+  WMImage::real_display(); //update window
+}
+
+double rand(double low, double high)
+{
+  return low + std::rand() * (high - low) / RAND_MAX;
+}
+
+void
+WMRadar::add_plane()
+{
+  if (planes.size() > 4)
+    return;
+
+  double theta = rand(0, 2 * M_PI); //put plane somewhere along edge
+  plane p = { (1 + cos(theta)) * b_width() / 2,
+    (1 - sin(theta)) * b_height() / 2,
+    rand(theta + 3 * M_PI_4, theta + 5 * M_PI_4), //direction pointing inwards
+    0.5 }; //brightness
+
+  planes.push_back(p);
+}
+
+inline double dist2 (double x1, double y1, double x2, double y2)
+{ //return distance squared between points
+  return std::pow(x1 - x2, 2) + std::pow(y1 - y2, 2);
+}
+
+inline double norm_angle(double angle)
+{ //return angle shifted into the range [0, 2pi)
+  return angle - 2 * M_PI * std::floor(angle / (2 * M_PI));
+}
+
+bool
+WMRadar::release(int, int x, int y)
+{
+  if (wPressed)
+  {
+    wPressed = false;
+    if (contains(x, y) && planes.size())
+    {
+      int newx = x - b_left(),
+          newy = y - b_top();
+      plist::iterator closest;
+      double mindist2 = 10000;
+      for (plist::iterator i = planes.begin(); i != planes.end(); ++i)
+      {
+        double d2 = dist2(i->x, i->y, newx, newy);
+        if (d2 < mindist2)
+        {
+          mindist2 = d2;
+          closest = i;
+        }
+      }
+      closest->direction = norm_angle(atan2(double(int(closest->y) - newy),
+          double(newx - int(closest->x))));
+      //change nearest plane's direction towards (x, y)
+    }
+    return true;
+  }
+  else return false;
+}
+
+void
+WMRadar::increment_time()
+{
+  for (plist::iterator i = planes.begin(); i != planes.end();)
+  { //Collision test planes
+    if (!contains(i->x + left(), i->y + top()))
+      ++i;
+    else
+    {
+      plist::iterator j = i;
+      bool collided = false;
+      for (++j; j != planes.end();)
+        if (dist2(i->x, i->y, j->x, j->y) <= 0.75)
+        { //remove each collided plane and increment score
+          j = planes.erase(j);
+          collided = true;
+          increment_score();
+        }
+        else
+          ++j;
+      if (collided)
+      {
+        increment_score();
+        collision c = { i->x, i->y };
+        collisions.push_back(c); //make record of collision location
+        i = planes.erase(i);
+      }
+      else
+        ++i;
+    }
+  }
+    
+  const double angleinc = M_PI / 125;
+
+  for (plist::iterator i = planes.begin(); i != planes.end();)
+  {
+    double incx = speed->value() * cos(i->direction) / 100;
+    double incy = -speed->value() * sin(i->direction) / 100;
+    double nextx = i->x + incx;
+    double nexty = i->y + incy;
+    
+    //to check if a plane crossed the radar line, approximate the plane's path
+    //as an arc:
+    double& l_start_angle = angle; //make an interval of radar line's angles
+    const double l_end_angle = l_start_angle + angleinc;
+
+    //make an interval of the plane's angles
+    double p_start_angle = norm_angle(atan2(b_height() / 2 - i->y,
+          i->x - b_width() / 2));
+    double p_end_angle = norm_angle(atan2(b_height() / 2 - nexty,
+          nextx - b_width() / 2));
+
+    const double crossp = (b_width() / 2 - i->x) * incy
+      - (b_height() / 2 - i->y) * incx; //test whether plane is moving in
+      //a positive or a negative angle
+    if (crossp < 0.0) //make angle increase counterclockwise
+    {
+      const double temp = p_start_angle;
+      p_start_angle = p_end_angle;
+      p_end_angle = temp;
+    }
+    if (p_end_angle < p_start_angle)
+      p_end_angle += 2 * M_PI; //make sure end is > start
+
+    //intersect radar line interval and plane interval. If result is non-empty,
+    //there was an intersection.
+    if (std::min(p_end_angle, l_end_angle)
+        >= std::max(p_start_angle, l_start_angle))
+      i->brightness = 1.0; //if plane crossed radar line, make it bright
+    else
+      i->brightness *= 0.996; //otherwise decay brightness
+    
+
+    i->x = nextx; //update plane's position
+    i->y = nexty;
+    if (!WMWidget::contains(i->x + b_left(), i->y + b_top()))
+      i = planes.erase(i); //cull planes outside of radar
+    else
+      ++i;
+  }
+
+  angle = norm_angle(angle + angleinc); //increment radar direction
+
+  display();
+}
+
+void
+WMRadar::increment_score ()
+{
+  using namespace std;
+  istringstream in(text_score->text()); //get string from textbar
+  int score;
+  in >> score; //extract score
+  ostringstream out;
+  out << setw(6) << setfill(' ') << score + 1; //increment and put in a string
+  text_score->settext(out.str()); //put back in textbar
+}
diff --git a/wmapp/example2/wmradar.h b/wmapp/example2/wmradar.h
new file mode 100644
index 0000000..228cdc6
--- /dev/null
+++ b/wmapp/example2/wmradar.h
@@ -0,0 +1,44 @@
+#ifndef _WMRADAR_H
+#define _WMRADAR_H
+
+#include <list>
+#include "../wmellipse.h"
+#include "../wmcanvas.h"
+#include "../wmcallback.h"
+#include "../wmtextbar.h"
+#include "../wmslider.h"
+
+class WMRadar : public WMCanvas, public WMCallback, public WMEllipse {
+private:
+  struct plane
+  {
+    double x, y, direction, brightness;
+  };
+  typedef std::list<plane> plist;
+  
+  struct collision
+  { int x, y; };
+  typedef std::list<collision> clist;
+  
+  plist planes;
+  clist collisions;
+  double angle;
+
+  WMTextBar* text_score;
+  WMSlider* speed;
+
+protected:
+  void real_display();
+
+public:
+  WMRadar(WMTextBar*, WMSlider*);
+  
+  void add_plane();
+  bool release(int button, int x, int y); //change nearest plane's direction
+  void increment_time();
+
+private:
+  void increment_score();
+};
+
+#endif  //_WMRADAR_H
diff --git a/wmapp/wmapp.cc b/wmapp/wmapp.cc
new file mode 100644
index 0000000..e335318
--- /dev/null
+++ b/wmapp/wmapp.cc
@@ -0,0 +1,378 @@
+#include <string>
+#include "wmapp.h"
+#include "wmwindow.h"
+
+using std::string;
+
+namespace Unix {
+  extern "C" {
+#   include <unistd.h> // for usleep()
+  }
+};
+
+// All the xpms we need:
+namespace Xpms {
+# include "xpm/charmap-small.xpm"
+# include "xpm/charmap-medium.xpm"
+# include "xpm/charmap-large.xpm"
+# include "xpm/checkbox.xpm"
+# include "xpm/xbutton.xpm"
+# include "xpm/leds.xpm"
+# include "xpm/emptybar.xpm"
+# include "xpm/fullbar.xpm"
+# include "xpm/tile.xpm"
+};
+
+// Xlib doesn't seem to work if these are class members.
+// They're declared as extern in xwrapper.h.
+X::Window wActiveWin, wProgramWin;
+X::Atom	deleteWin;
+X::Atom	_XA_GNUSTEP_WM_FUNC;
+
+// static class members of WMApp declared here:
+
+Xwrapper WMApp::Xw;
+WMPixmap WMApp::char_pixmaps[3];
+WMPixmap WMApp::checkbox_pixmap, WMApp::xbutton_pixmap, WMApp::leds_pixmap[4];
+WMPixmap WMApp::emptybar_pixmap, WMApp::fullbar_pixmap;
+WMPixmap WMApp::tile_pixmap;
+Color WMApp::colormap[WMColor::numcolors];
+
+char ** WMApp::wArgv;
+string WMApp::wName;
+int WMApp::wArgc;
+int WMApp::wWindowSize;
+enum WindowManager::WindowManager WMApp::wManager;
+
+
+// initialize: static function to create pixmaps and set default colors.
+// This should be called as the very first line of a program using this
+// library.
+void
+WMApp::initialize(int argc, char *argv[])
+{
+  static bool inited = false;
+  if (inited) return;
+
+  wArgc = argc;
+  wName = (argc && argv) ? string(argv[0]) : string("WMApplication");
+  wArgv = argv;
+  deleteWin = X::XInternAtom(Xw.xdisplay(), "WM_DELETE_WINDOW", false);
+  _XA_GNUSTEP_WM_FUNC = X::XInternAtom(Xw.xdisplay(),
+		  		       "_GNUSTEP_WM_FUNCTION", false);
+  
+  // create all the required pixmaps
+  Xw.create_pixmap(char_pixmaps[0],	Xpms::charmap_small_xpm);
+  Xw.create_pixmap(char_pixmaps[1],	Xpms::charmap_medium_xpm);
+  Xw.create_pixmap(char_pixmaps[2],	Xpms::charmap_large_xpm);
+  Xw.create_pixmap(checkbox_pixmap,	Xpms::checkbox_xpm);
+  Xw.create_pixmap(xbutton_pixmap,	Xpms::xbutton_xpm);
+  Xw.create_pixmap(fullbar_pixmap,	Xpms::fullbar_xpm);
+  Xw.create_pixmap(emptybar_pixmap,	Xpms::emptybar_xpm);
+  Xw.create_pixmap(tile_pixmap,		Xpms::tile_xpm);
+
+  // create four LED pixmaps
+  WMPixmap all_leds_pixmap;
+  int ledwidth = 4, ledheight = 4;
+  
+  Xw.create_pixmap(all_leds_pixmap, Xpms::leds_xpm);
+  for (unsigned int s = 0; s < 4; s++) {
+    leds_pixmap[s].attr.width = ledwidth;
+    leds_pixmap[s].attr.width = ledheight;
+    Xw.create_pixmap(leds_pixmap[s], ledwidth, ledheight);
+    Xw.copy_rectangle(all_leds_pixmap, leds_pixmap[s], ledwidth * s, 0,
+		     ledwidth, ledheight, 0, 0);
+  }
+
+# define colormap(x) colormap[static_cast<int>(WMColor:: x)]
+  // create colormap
+  // XXX: eventually, read from RC file
+  colormap(Background)		= 0x212121;
+  colormap(Dim)			= 0x283C28;
+  colormap(Medium)		= 0x188A86;
+  colormap(Bright)		= 0x20B2AE;
+  colormap(ButtonFace)		= 0xAEAAAE;
+  colormap(ButtonBorderDim)	= 0;
+  colormap(ButtonBorderMedium)	= 0x86828E;
+  colormap(ButtonBorderBright)	= 0xF7F3FF;
+  colormap(FrameBorderDim)	= 0;
+  colormap(FrameBorderMedium)	= 0;
+  colormap(FrameBorderBright)	= 0xC8C8C8; //0xAEAAAE;
+# undef colormap
+
+  inited = true;
+
+  // set the window behavior from command-line options
+  wManager = WindowManager::Other;
+  wWindowSize = 64;
+  
+  for (int i = 1; i < wArgc && strcmp(wArgv[i], "--"); i++) {
+    if (strcmp(wArgv[i], "-w") == 0) {
+      wManager = WindowManager::WindowMaker; break;
+    }
+    else if (strcmp(wArgv[i], "-a") == 0) {
+      wManager = WindowManager::Afterstep;
+      wWindowSize = 56;
+      break;
+    }
+  }
+}  
+
+// Here begin the magic Xlib incantations required to create a dockapp window.
+// I have no idea how this works, it just does.  Code mostly obtained from
+// wmsmixer by Damian Kramer, based in turn upon wmmixer by Sam Hawker.
+
+// simple function to create an XWindow	
+void
+WMApp::create_window(X::Window *dest, int left, int top) const
+{
+  X::XClassHint classHint;
+
+  *dest = X::XCreateSimpleWindow(Xw.xdisplay(), Xw.xrootwin(), left, top,
+				 wWindowSize, wWindowSize, 0, 0, 0);
+
+  //XXX: May be able to get away without allocating new char arrays, but I don't
+  //trust X not to modify them.
+  classHint.res_name = new char[wName.size() + 1];
+  classHint.res_class = new char[wName.size() + 1];
+  strcpy(classHint.res_name, wName.c_str());
+  strcpy(classHint.res_class, wName.c_str());
+  X::XSetClassHint(Xw.xdisplay(), *dest, &classHint);
+  delete[] classHint.res_name;
+  delete[] classHint.res_class;
+}
+
+// This function sets up the X window.
+// Called from WMApp::run()
+void WMApp::Xsetup()
+{
+  X::Display *	display = Xw.xdisplay();
+  
+  X::XWMHints   wmhints;
+  X::XSizeHints shints;
+  int		winsize = wWindowSize;
+  bool		pos;
+
+  shints.x = shints.y = shints.flags = 0;
+  pos = (X::XWMGeometry(display, X::XDefaultScreen(display), "" /*geometry*/,
+			0, 0, &shints, &shints.x, &shints.y, &shints.width, &shints.height,
+      &shints.win_gravity) & X_MACRO(XValue | YValue));
+  shints.min_width = shints.min_height = winsize;
+  shints.max_width = shints.max_height = winsize;
+  shints.base_width = shints.base_height = winsize;
+  shints.flags = X_MACRO(PMinSize | PMaxSize | PBaseSize);
+  create_window(&wProgramWin, shints.x, shints.y);
+
+  if (pos || wManager == WindowManager::WindowMaker
+	|| wManager == WindowManager::Afterstep)
+    shints.flags |= X_MACRO(USPosition);
+
+  if (wManager == WindowManager::WindowMaker) {
+    wmhints.initial_state = X_MACRO(WithdrawnState);
+    wmhints.flags = X_MACRO(WindowGroupHint | StateHint | IconWindowHint);
+    create_window(&wActiveWin, shints.x, shints.y);
+    wmhints.icon_window = wActiveWin;
+  }
+  else {
+    wmhints.initial_state = X_MACRO(NormalState);
+    wmhints.flags = X_MACRO(WindowGroupHint | StateHint);
+    wActiveWin = wProgramWin;
+  }
+
+  wmhints.window_group = wProgramWin;
+  X::XSetWMHints(display, wProgramWin, &wmhints);
+  X::XSetWMNormalHints(display, wProgramWin, &shints);
+  if (wArgc > 0)
+    X::XSetCommand(display, wProgramWin, wArgv, wArgc);
+  X::XStoreName(display, wProgramWin, wName.c_str());
+  X::XSetIconName(display, wProgramWin, wName.c_str());
+  X::XSetWMProtocols(display, wActiveWin, &deleteWin, 1);
+}
+
+// This function masks out the "clear" parts of the X window.
+// Called from WMWindow::real_display()
+void
+WMApp::mask() const
+{
+  X::Display * display = Xw.xdisplay();
+  WMPixmap pixmap = current()->pixmap();
+
+  if (wManager == WindowManager::WindowMaker ||
+      wManager == WindowManager::Afterstep)
+    // apply the mask if using a compliant window manager
+    X::XShapeCombineMask(display, wActiveWin, X_MACRO(ShapeBounding),
+		         0, 0, pixmap.mask, X_MACRO(ShapeSet));
+  else
+    // otherwise, create a tile background for the window
+    Xw.copy_rectangle(tile_pixmap, pixmap.pixmap, 0, 0, wWindowSize,
+        wWindowSize);
+
+  Xw.fill_rectangle(pixmap, 0, 0, wWindowSize, wWindowSize,
+      WMColor(Background));
+}
+
+// This function redraws the X window if necessary.
+// Called from WMWindow::real_display()
+void
+WMApp::repaint() const
+{
+  X::XEvent xev;
+
+  Xw.copy_rectangle(current()->pixmap(), wActiveWin,
+                    0, 0, wWindowSize, wWindowSize);
+
+  while (X::XCheckTypedEvent(Xw.xdisplay(), X_MACRO(Expose), &xev))
+    /* loop */;
+  X::XFlush(Xw.xdisplay());
+}
+
+// This function displays the X window.
+// Called from WMWindow::real_activate()
+void
+WMApp::Xshow() const
+{
+  X::Display * display = Xw.xdisplay();
+  
+  // request input events and map the window
+  X::XSelectInput(display, wActiveWin,
+		  X_MACRO(ExposureMask | ButtonPressMask | ButtonReleaseMask)
+		  | X_MACRO(ButtonMotionMask));
+  X::XMapWindow(display, wProgramWin);
+  repaint();
+  
+  // loop over X events and callbacks
+  Xwait();	
+}
+
+// This function waits for X events, redraws the window when necessary,
+// and calls callbacks of the window.
+void
+WMApp::Xwait() const
+{
+  X::Display * display = Xw.xdisplay();
+  X::XEvent xev;
+
+  while (true) {
+    // sleep for the specified time in milliseconds
+    Unix::usleep(1000 * current()->updatefreq());
+    // execute any timed functions which need it
+    current()->run_timed_functions();
+
+    // execute any pending X events
+    while (XPending(display)) {
+      X::XNextEvent(display, &xev);
+
+      switch (xev.type) {
+        case Expose:
+          repaint();
+	  break;
+	case ButtonPress:
+	  current()->press(xev.xbutton.button, xev.xbutton.x, xev.xbutton.y);
+	  break;
+	case ButtonRelease:
+	  wMouseEvent.button = xev.xbutton.button;
+	  wMouseEvent.x = xev.xbutton.x;
+	  wMouseEvent.y = xev.xbutton.y;
+	  current()->release(xev.xbutton.button, xev.xbutton.x, xev.xbutton.y);
+	  if (done()) return;
+	  break;
+	case ClientMessage:
+	  if (static_cast<unsigned int>(xev.xclient.data.l[0]) == deleteWin)
+	    { stop(); return; }
+	  break;
+	default: break;
+      }
+    }
+  }
+}
+
+// End of magic Xlib incantations.
+
+// The following functions deal with setting the state of the application
+// and running it.
+
+void
+WMApp::switch_to(WMWindow *w) const
+{
+  for (unsigned int i = 0; i < wWindows.size(); i++)
+    if (w == wWindows[i]) {
+      switch_to(i);
+      return;
+    }
+}
+
+void
+WMApp::switch_to(WMWindow &w) const { switch_to(&w); }
+
+// run: This function starts the GUI of the dockapp.  Call it as the
+// last line in a program using this library.  Calling run() with no
+// argument starts the program on the first window.  You can also
+// call run(WMWindow *), run(WMWindow &), or run(unsigned int) in order
+// to start with a different window.
+//
+// So your program in the simplest case should look like this:
+//
+// int main(int argc, char *argv[]) {
+//   WMApp::initialize(argc, argv);
+//   WMWindow w;
+//   WMApp a = WMApp(w);
+//   // layout the window and set up callbacks here
+//   // ...
+//   a.addwindow(w);
+//   a.run();
+//   return 0;
+// }
+
+void
+WMApp::run(WMWindow *w)
+{
+  for (unsigned int i = 0; i < wWindows.size(); i++)
+    if (w == wWindows[i]) {
+      run(i);
+      return;
+    }
+}
+
+void
+WMApp::run(WMWindow &w) { run(&w); }
+
+void
+WMApp::run(int w) { run(static_cast<unsigned int>(w)); }
+
+void
+WMApp::run(unsigned int w)
+{
+  if (w >= wWindows.size()) return;
+
+  // set up pointers from windows to "this"
+  for (unsigned int i = 0; i < wWindows.size(); i++)
+    wWindows[i]->wApp = this;
+  
+  Xsetup();
+  wActiveWindow = wNextWindow = w;
+
+  while (wFinished == false) {
+    // This function does not exit until wNextWindow != wActiveWindow
+    // or wFinished == true.  User interaction happens in here.
+    current()->display();
+
+    // To switch to a different window, set a callback on a button within
+    // this window, like this:
+    // 	void callback1(const WMApp *a, void *) { a->switch_to(5); }
+    // To exit the program, likewise, you need a callback like
+    // 	void callback2(const WMApp *a, void *) { a->stop(); }
+    // (Alternately you could put the window on a timer by setting one of
+    // these as a callback of the window itself, substituting WMWindow for
+    // WMButton in the function definitions.)
+
+    wActiveWindow = wNextWindow;
+
+    // if we have switched to a different window, continue with that one.
+  }
+
+  // otherwise, exit the WMApp::run() function.  (Normally a call like
+  // wm_app->run(); will be the last in a program's main() function,
+  // in which case we also exit the program.)
+  return;
+}
+
diff --git a/wmapp/wmapp.h b/wmapp/wmapp.h
new file mode 100644
index 0000000..66c022f
--- /dev/null
+++ b/wmapp/wmapp.h
@@ -0,0 +1,170 @@
+#include <vector>
+#include <string>
+#include "wmwidget.h"
+#include "xwrapper.h"
+#include "colors.h"
+
+#ifndef _WMAPP_H
+#define _WMAPP_H
+
+class WMWindow;
+
+namespace WindowManager {
+  enum WindowManager { WindowMaker, Afterstep, Other };
+};
+
+struct WMMouseClick {
+  int button;
+  int x;
+  int y;
+
+  WMMouseClick(int Button = Button1, int X = 0, int Y = 0);
+  WMMouseClick relative_to(const WMWidget &w) const;
+  WMMouseClick relative_to(const WMWidget *w) const;
+  WMMouseClick b_relative_to(const WMWidget &w) const;
+  WMMouseClick b_relative_to(const WMWidget *w) const;
+};
+
+inline WMMouseClick::WMMouseClick(int Button, int X, int Y)
+: button(Button), x(X), y(Y) { }
+
+inline WMMouseClick
+WMMouseClick::relative_to(const WMWidget &w) const
+{ return WMMouseClick(button, x - w.left(), y - w.top()); }
+
+inline WMMouseClick
+WMMouseClick::relative_to(const WMWidget *w) const
+{ return relative_to(*w); }
+
+inline WMMouseClick
+WMMouseClick::b_relative_to(const WMWidget &w) const
+{ return WMMouseClick(button, x - w.b_left(), y - w.b_top()); }
+
+inline WMMouseClick
+WMMouseClick::b_relative_to(const WMWidget *w) const
+{ return b_relative_to(*w); }
+
+class WMApp {
+ private:
+  static int		wWindowSize;
+  static int		wArgc;
+  static char **	wArgv;
+  static std::string		wName;
+
+  std::vector<WMWindow *>	wWindows;
+  mutable int		wActiveWindow;
+  mutable int		wNextWindow;
+  mutable bool		wFinished;
+  mutable WMMouseClick	wMouseEvent;
+  
+  void create_window(X::Window *dest, int left, int top) const;
+  void Xsetup();
+  void Xwait() const;
+	
+ public:
+  static WindowManager::WindowManager wManager;
+  static Xwrapper Xw;
+  static WMPixmap char_pixmaps[3];
+  static WMPixmap checkbox_pixmap, xbutton_pixmap, leds_pixmap[4];
+  static WMPixmap emptybar_pixmap, fullbar_pixmap;
+  static WMPixmap tile_pixmap;
+  static Color colormap[WMColor::numcolors];
+
+  // Always call this function first in main():
+  static void initialize(int argc = 0, char *argv[] = 0);
+  static unsigned int size();
+  
+  WMApp();
+  ~WMApp();
+
+  void addwindow(WMWindow *);
+  void addwindow(WMWindow &);
+
+  // Use this call to start the GUI.
+  void run(unsigned int window = 0);
+  void run(int window);
+  void run(WMWindow &);
+  void run(WMWindow *);
+
+  // Use these within callbacks of windows or buttons in order to switch
+  // to a different window, or to exit the GUI.
+  void switch_to(unsigned int window) const;
+  void switch_to(int window) const;
+  void switch_to(WMWindow &) const;
+  void switch_to(WMWindow *) const;
+  void stop() const;
+
+  // Use this within callbacks of windows or buttons in order to play
+  // with other widgets.
+  WMWindow * window(unsigned int) const;
+  WMWindow * current() const;
+  unsigned int currentnum() const;
+
+  // Use this within callbacks to see which mouse button was pressed
+  // and where.
+  const WMMouseClick & mouseclick() const;
+
+  // Windows use this call to see if it's time for them to exit yet.
+  bool done() const;
+
+  // utility functions for windows
+  void mask() const;
+  void repaint() const;
+  void Xshow() const;
+};
+
+inline
+WMApp::WMApp()
+: wActiveWindow(0), wNextWindow(0), wFinished(false) { }
+
+inline
+WMApp::~WMApp()
+{
+  if (wProgramWin == wActiveWin)
+    X::XDestroyWindow(Xw.xdisplay(), wProgramWin);
+  else {
+    X::XDestroyWindow(Xw.xdisplay(), wProgramWin);
+    X::XDestroyWindow(Xw.xdisplay(), wActiveWin);
+  }
+}
+
+inline void
+WMApp::addwindow(WMWindow *w) { wWindows.push_back(w); }
+
+inline void
+WMApp::addwindow(WMWindow &w) { wWindows.push_back(&w); }
+
+inline unsigned int
+WMApp::size() { return wWindowSize; }
+
+inline WMWindow *
+WMApp::window(unsigned int i) const
+{ return i < wWindows.size() ? wWindows[i] : 0; }
+
+inline WMWindow *
+WMApp::current() const { return wWindows[wActiveWindow]; }
+
+inline unsigned int
+WMApp::currentnum() const { return wActiveWindow; }
+
+inline const WMMouseClick &
+WMApp::mouseclick() const { return wMouseEvent; }
+
+inline void
+WMApp::switch_to(unsigned int window) const
+{ if (window < wWindows.size()) wNextWindow = window; }
+
+inline void
+WMApp::switch_to(int window) const
+{
+  if (window >= 0 && window < static_cast<int>(wWindows.size()))
+    wNextWindow = window;
+}
+
+inline void
+WMApp::stop() const { wFinished = true; }
+
+inline bool
+WMApp::done() const { return wFinished || wActiveWindow != wNextWindow; }
+
+#endif
diff --git a/wmapp/wmbutton.cc b/wmapp/wmbutton.cc
new file mode 100644
index 0000000..2989a03
--- /dev/null
+++ b/wmapp/wmbutton.cc
@@ -0,0 +1,59 @@
+#include "wmbutton.h"
+#include "wmapp.h"
+#include "wmwindow.h"
+
+// functions for WMButton ------------------------------------------------
+
+WMButton::WMButton()
+{
+  setborder(1);
+  setbgcolor(WMColor(ButtonFace), false);
+  set_top_left_c(WMColor(ButtonBorderBright));
+  set_bottom_right_c(WMColor(ButtonBorderDim));
+}
+
+void
+WMButton::real_display()
+{
+  if (is_active())
+    WMImage::real_display();
+  else
+    // If button is not clickable, don't draw an icon.
+    // Note: If the button has no icon, I recommend that you change its
+    // background color from the default; otherwise the button will always
+    // look as if it is disabled.
+    WMApp::Xw.fill_rectangle(window()->pixmap(), b_position(),
+		    	     WMColor(ButtonFace));
+}
+
+bool 
+WMButton::press(int button, int x, int y)
+{ 
+  if (contains(x, y)) {
+    if (is_active()) {
+      wPressed = true;
+      set_top_left_c(WMColor(ButtonBorderDim));
+      set_bottom_right_c(WMColor(ButtonBorderBright));
+      draw_border();
+      app()->repaint();
+    }
+    return true;
+  }
+  else return false;
+}
+
+bool
+WMButton::release(int button, int x, int y)
+{
+  if (wPressed) {
+    wPressed = false;
+    set_top_left_c(WMColor(ButtonBorderBright));
+    set_bottom_right_c(WMColor(ButtonBorderDim));
+    draw_border();
+    app()->repaint();
+    if (contains(x, y))
+      execute();
+    return true;
+  }
+  else return false;
+}
diff --git a/wmapp/wmbutton.h b/wmapp/wmbutton.h
new file mode 100644
index 0000000..83fa1d9
--- /dev/null
+++ b/wmapp/wmbutton.h
@@ -0,0 +1,18 @@
+#include "wmimage.h"
+#include "wmcallback.h"
+
+#ifndef _WMBUTTON_H
+#define _WMBUTTON_H
+
+// WMButton: An image that can execute callback functions when clicked upon
+class WMButton : public WMCallback, public WMImage {
+ private:
+  void real_display();
+  
+ public:
+  WMButton();
+  bool press(int button, int x, int y);
+  bool release(int button, int x, int y);
+};
+
+#endif
diff --git a/wmapp/wmcallback.cc b/wmapp/wmcallback.cc
new file mode 100644
index 0000000..9fb2a94
--- /dev/null
+++ b/wmapp/wmcallback.cc
@@ -0,0 +1,34 @@
+#include "wmcallback.h"
+
+// functions for WMCallback ----------------------------------------------
+
+void
+WMCallback::execute()
+{
+  // execute all callbacks for this object, in order
+  for (unsigned int i = 0; i < numcallbacks(); i++)
+    runcallback(i);
+}
+
+bool
+WMCallback::press(int button, int x, int y)
+{
+  if (contains(x, y)) {
+    wPressed = true;
+    return true;
+  }
+  else return false;
+}
+
+bool
+WMCallback::release(int button, int x, int y)
+{
+  if (wPressed) {
+    wPressed = false;
+    if (contains(x,y))
+      execute();
+    return true;
+  }
+  else return false;
+}
+
diff --git a/wmapp/wmcallback.h b/wmapp/wmcallback.h
new file mode 100644
index 0000000..de9aab4
--- /dev/null
+++ b/wmapp/wmcallback.h
@@ -0,0 +1,113 @@
+#include <vector>
+#include "wmwidget.h"
+#include "wmclickable.h"
+
+#ifndef _WMCALLBACK_H
+#define _WMCALLBACK_H
+
+using std::vector;
+
+// WMCallback: A class capable of setting and executing callback functions.
+class WMCallback : public virtual WMWidget, public virtual WMClickable {
+ public:
+  typedef void (* data_func)(const WMApp *, void *);
+  typedef void (* widget_func)(const WMApp *, WMWidget *, void *);
+
+ private:
+  class callback {
+    public: virtual void execute(const WMApp *) = 0;
+  };
+  
+  class data_callback : public callback {
+    data_func		func;
+    void *		data;
+   public:
+    data_callback(data_func, void *);
+    void execute(const WMApp *);
+  };
+
+  class widget_callback : public callback {
+    widget_func		func;
+    WMWidget *		widget;
+    void *		data;
+   public:
+    widget_callback(widget_func, WMWidget *, void *);
+    void execute(const WMApp *);
+  };
+
+  vector<callback*> wCallback;
+ 
+ public:
+  WMCallback();
+  WMCallback(data_func, void * = 0);
+  WMCallback(widget_func, WMWidget *, void * = 0);
+  virtual ~WMCallback() { clearcallbacks(); }
+  
+  unsigned int numcallbacks() const;
+  void addcallback(data_func, void * = 0);
+  void addcallback(widget_func, WMWidget *, void * = 0);
+  void runcallback(unsigned int i);
+  void clearcallbacks();
+  
+  // check to see if a mouse click hit the widget; if so, run callbacks
+  virtual bool press(int button, int x, int y);
+  virtual bool release(int button, int x, int y);  
+  virtual void execute();
+};
+
+// inline functions for WMCallback ---------------------------------------
+
+inline
+WMCallback::data_callback::data_callback(data_func f, void *datap)
+: func(f), data(datap) { }
+
+inline void
+WMCallback::data_callback::execute(const WMApp *app)
+{ (func)(app, data); }
+
+inline
+WMCallback::widget_callback::widget_callback
+(widget_func f, WMWidget *w, void *datap)
+: func(f), widget(w), data(datap) { }
+
+inline void
+WMCallback::widget_callback::execute(const WMApp *app)
+{ (func)(app, widget, data); }
+
+inline
+WMCallback::WMCallback()
+{ }
+
+inline
+WMCallback::WMCallback(data_func f, void *data)
+{ addcallback(f, data); }
+
+inline
+WMCallback::WMCallback(widget_func f, WMWidget *w, void *data)
+{ addcallback(f, w, data); }
+
+inline void
+WMCallback::addcallback(data_func f, void *data)
+{ wCallback.push_back(new data_callback(f, data)); }
+  
+inline void
+WMCallback::addcallback(widget_func f, WMWidget *w, void *data)
+{ wCallback.push_back(new widget_callback(f, w, data)); }
+
+inline void
+WMCallback::runcallback(unsigned int i)
+{ wCallback[i]->execute(app()); }
+
+inline unsigned int
+WMCallback::numcallbacks() const { return wCallback.size(); }
+
+inline void
+WMCallback::clearcallbacks()
+{
+  for (vector<callback *>::iterator i = wCallback.begin();
+      i != wCallback.end(); ++i)
+    delete *i;
+  wCallback.clear();
+}
+
+#endif
diff --git a/wmapp/wmcanvas.cc b/wmapp/wmcanvas.cc
new file mode 100644
index 0000000..e1cf273
--- /dev/null
+++ b/wmapp/wmcanvas.cc
@@ -0,0 +1,160 @@
+#include <vector>
+#include "wmcanvas.h"
+#include "wmwindow.h"
+#include "wmapp.h"
+
+// functions for WMCanvas ------------------------------------------------
+
+WMCanvas::WMCanvas(const WMPixmap * pm)
+: WMImage(pm), wCurrentColor(WMColor(Bright)), wBuffered(false) { }
+
+WMCanvas::WMCanvas(const WMPixmap & pm)
+: WMImage(pm), wCurrentColor(WMColor(Bright)), wBuffered(false) { }
+
+WMCanvas::WMCanvas(char *xpm[])
+: WMImage(xpm), wCurrentColor(WMColor(Bright)), wBuffered(false) { }
+
+// these are all variants of the drawing functions in xwrapper.h.
+// Unlike there, they are relative to the borders of the widget.
+// Note that icon() should return an XPM which is the dimension of
+// the WMCanvas _minus_ the border thickness.
+
+/*void
+WMCanvas::copy_buffer()
+{
+  WMApp::Xw.copy_rectangle(*icon(), window()->pixmap(), 0, 0,
+		           b_width(), b_height(), b_left(), b_top());
+//  draw_border();
+}*/
+
+// don't use this macro in your programs, it's just to make my life easier in
+// the WMCanvas method definitions
+#define COPY_BUFFER() if (! buffered()) { display() /*copy_buffer()*/; }
+
+Color
+WMCanvas::get_point(int rel_x, int rel_y) const
+{ return WMApp::Xw.get_point(*icon(), rel_x, rel_y); }
+
+void
+WMCanvas::draw_point(int rel_x, int rel_y)
+{
+  WMApp::Xw.draw_point(*p_icon(), rel_x, rel_y, color());
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::draw_line(int rel_x1, int rel_y1, int rel_x2, int rel_y2)
+{
+  WMApp::Xw.draw_line(*p_icon(), rel_x1, rel_y1, rel_x2, rel_y2, color());
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::draw_arc(int x, int y, int width, int height, int angle1, int angle2)
+{
+  WMApp::Xw.draw_arc(*p_icon(), x, y, width, height, angle1, angle2, color());
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::draw_lines(const vector<X::XPoint>& points)
+{
+  X::XPoint *p = new X::XPoint[points.size()];
+  for (size_t i = 0; i < points.size(); ++i)
+  {
+    p[i].x = points[i].x;
+    p[i].y = points[i].y;
+  }
+  WMApp::Xw.draw_lines(*p_icon(), p, points.size(), color());
+  delete[] p;
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::draw_horizontal_gradient(int rel_x1, int rel_y1, int rel_x2,
+				   int rel_y2, Color c1, Color c2, double amt)
+{
+  WMApp::Xw.draw_horizontal_gradient(*p_icon(), rel_x1, rel_y1, rel_x2, rel_y2,
+				     c1, c2, amt);
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::draw_vertical_gradient(int rel_x1, int rel_y1, int rel_x2,
+				 int rel_y2, Color c1, Color c2, double amt)
+{
+  WMApp::Xw.draw_vertical_gradient(*p_icon(), rel_x1, rel_y1, rel_x2, rel_y2,
+				   c1, c2, amt);
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::empty_rectangle(int rel_x, int rel_y, int w, int h, int thickness)
+{
+  WMApp::Xw.draw_border(*p_icon(), rel_x, rel_y, w, h, thickness,
+		        color(), color(), color());
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::empty_rectangle(const WMRectangle & rel_posn, int thickness)
+{
+  WMApp::Xw.draw_border(*p_icon(), rel_posn, thickness,
+		  	color(), color(), color());
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::fill_rectangle(int rel_x, int rel_y, int w, int h)
+{
+  WMApp::Xw.fill_rectangle(*p_icon(), rel_x, rel_y, w, h, color());
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::fill_rectangle(const WMRectangle & rel_posn)
+{
+  WMApp::Xw.fill_rectangle(*p_icon(), rel_posn, color());
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::fill_arc(int x, int y, int width, int height, int angle1, int angle2)
+{
+  WMApp::Xw.fill_arc(*p_icon(), x, y, width, height, angle1, angle2, color());
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::fill_polygon(const vector<X::XPoint>& points, Xwrapper::XShape shape)
+{
+  X::XPoint *p = new X::XPoint[points.size()];
+  for (size_t i = 0; i < points.size(); ++i)
+  {
+    p[i].x = points[i].x;
+    p[i].y = points[i].y;
+  }
+  WMApp::Xw.fill_polygon(*p_icon(), p, points.size(), color(), shape);
+  delete[] p;
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::copy_rectangle(const WMPixmap & source, int source_x, int source_y,
+                         int source_w, int source_h, int dest_x, int dest_y)
+{
+  WMApp::Xw.copy_rectangle(source, *p_icon(), source_x, source_y,
+			   source_w, source_h, dest_x, dest_y);
+  COPY_BUFFER();
+}
+
+void
+WMCanvas::copy_rectangle(const WMPixmap & source, const WMRectangle & posn,
+                         int dest_x, int dest_y)
+{
+  WMApp::Xw.copy_rectangle(source, *p_icon(), posn, dest_x, dest_y);
+  COPY_BUFFER();
+}
+
+#undef COPY_BUFFER
+
diff --git a/wmapp/wmcanvas.h b/wmapp/wmcanvas.h
new file mode 100644
index 0000000..aa596fc
--- /dev/null
+++ b/wmapp/wmcanvas.h
@@ -0,0 +1,68 @@
+#include <vector>
+#include "wmimage.h"
+
+#ifndef _WMCANVAS_H
+#define _WMCANVAS_H
+
+using std::vector;
+
+// WMCanvas: a widget inheriting from WMImage that allows you to change the
+// image using drawing functions
+class WMCanvas : public virtual WMImage {
+  Color wCurrentColor;
+  bool wBuffered;
+ public:
+  WMCanvas(const WMPixmap * pm = 0);
+  WMCanvas(const WMPixmap & pm);
+  WMCanvas(char *xpm[]);
+
+  void setcolor(Color);
+  void setbuffered(bool);
+  Color color() const;
+  bool buffered() const;
+  
+  // these are all variants of the drawing functions in xwrapper.h.
+  // Unlike there, they are relative to the borders of the widget.
+  Color get_point(int rel_x, int rel_y) const;
+  void draw_point(int rel_x, int rel_y);
+  void draw_line(int rel_x1, int rel_y1, int rel_x2, int rel_y2);
+  void draw_arc(int x, int y, int width, int height, int angle1, int angle2);
+      //angles are in units of degrees * 64
+  void draw_lines(const vector<X::XPoint>& points);
+      //X::XPoint is simply a struct { short x, y };
+  void draw_horizontal_gradient(int rel_x1, int rel_y1, int rel_x2, int rel_y2,
+		  		Color c1, Color c2, double amount = 1.0);
+  void draw_vertical_gradient(int rel_x1, int rel_y1, int rel_x2, int rel_y2,
+		  	      Color c1, Color c2, double amount = 1.0);
+  void empty_rectangle(int rel_x, int rel_y, int width, int height,
+		       int thickness);
+  void empty_rectangle(const WMRectangle & rel_posn, int thickness);
+  void fill_rectangle(int rel_x, int rel_y, int width, int height);
+  void fill_rectangle(const WMRectangle & rel_posn);
+  void fill_arc(int x, int y, int width, int height, int angle1, int angle2);
+      //angles are in units of degrees * 64
+  void fill_polygon(const vector<X::XPoint>& points,
+      Xwrapper::XShape shape = Xwrapper::complex);
+      //see xwrapper.h for the meaning of shape
+  void copy_rectangle(const WMPixmap & source, int source_x, int source_y,
+		      int source_w, int source_h,
+		      int dest_x = 0, int dest_y = 0);
+  void copy_rectangle(const WMPixmap & source, const WMRectangle & posn,
+		      int dest_x = 0, int dest_y = 0);
+};
+
+// inline functions for WMCanvas -----------------------------------------
+
+inline void
+WMCanvas::setcolor(Color c) { wCurrentColor = c; }
+
+inline void
+WMCanvas::setbuffered(bool b) { wBuffered = b; }
+
+inline Color
+WMCanvas::color() const { return wCurrentColor; }
+
+inline bool
+WMCanvas::buffered() const { return wBuffered; }
+
+#endif
diff --git a/wmapp/wmclickable.h b/wmapp/wmclickable.h
new file mode 100644
index 0000000..419386a
--- /dev/null
+++ b/wmapp/wmclickable.h
@@ -0,0 +1,21 @@
+#ifndef _WMCLICKABLE_H
+#define _WMCLICKABLE_H
+
+// WMClickable: Widgets that are clickable should inherit from this class.
+class WMClickable {
+ protected:
+  bool wPressed;
+ public:
+  WMClickable();
+  virtual ~WMClickable() { }
+  
+  virtual bool press(int button, int x, int y) = 0;
+  virtual bool release(int button, int x, int y) = 0;
+};
+
+// inline functions for WMClickable --------------------------------------
+
+inline WMClickable::WMClickable()
+: wPressed(false) { }
+
+#endif
diff --git a/wmapp/wmellipse.cc b/wmapp/wmellipse.cc
new file mode 100644
index 0000000..4bbe1c7
--- /dev/null
+++ b/wmapp/wmellipse.cc
@@ -0,0 +1,58 @@
+#include <cmath>
+#include "wmellipse.h"
+#include "wmwindow.h"
+#include "wmapp.h"
+
+// functions for WMEllipse -----------------------------------------------
+
+void
+WMEllipse::draw_border()
+{ WMEllipse::draw_border(top_left_c(), bottom_right_c(), 5 /* steps */); }
+
+void
+WMEllipse::draw_border(Color c1, Color c2, int steps)
+{
+  if (border()) {
+    X::XGCValues gcv;
+    gcv.line_width = border();
+    X::XChangeGC(WMApp::Xw.xdisplay(), window()->pixmap().gc,
+        X_MACRO(GCLineWidth), &gcv);
+
+    // These dimensions are all experimentally determined :)
+    int l = left() + (border() - 1) / 2,
+        t = top() + (border() - 1) / 2,
+        w = width() - border() + (1 - border() % 2),
+        h = height() - border() + (1 - border() % 2);
+
+    const double weight_inc = 1.0 / (steps + 1);
+    const double angle_inc = 45 / steps;
+    for (double weight = weight_inc, angle = 0; angle < 44;
+        weight += weight_inc, angle += angle_inc)
+    {
+      Color c = Color::alpha_blend(c1, c2, weight);
+      WMApp::Xw.draw_arc(window()->pixmap(), l, t, w, h, (int)(angle * 64),
+          (int)(angle_inc * 64), c);
+      WMApp::Xw.draw_arc(window()->pixmap(), l, t, w, h, (int)((270 - angle) * 64),
+          (int)(-angle_inc * 64), c);
+    }
+      
+    WMApp::Xw.draw_arc(window()->pixmap(), l, t, w, h, 45 * 64, 180 * 64, c1);
+    WMApp::Xw.draw_arc(window()->pixmap(), l, t, w, h, 270 * 64, 90 * 64, c2);
+    
+    gcv.line_width = 0;
+    X::XChangeGC(WMApp::Xw.xdisplay(), window()->pixmap().gc,
+        X_MACRO(GCLineWidth), &gcv);
+  }
+}
+
+bool
+WMEllipse::contains(int x, int y) const
+{
+  double h_axis = std::ldexp(double(width()), -1);
+  double v_axis = std::ldexp(double(height()), -1);
+  double xc = (h_axis + left() - 0.5 - x) / h_axis;
+  xc *= xc;
+  double yc = (v_axis + top() - 0.5 - y) / v_axis;
+  yc *= yc;
+  return ((xc + yc) <= 1.0);
+}
diff --git a/wmapp/wmellipse.h b/wmapp/wmellipse.h
new file mode 100644
index 0000000..b26000e
--- /dev/null
+++ b/wmapp/wmellipse.h
@@ -0,0 +1,21 @@
+#include "wmwidget.h"
+
+#ifndef _WMELLIPSE_H
+#define _WMELLIPSE_H
+
+// WMEllipse: Widgets inherited from this class will be displayed within an
+// elliptical border. Simply inherit from WMEllipse and the desired widget.
+// Note: In order to get a circle, you must make the widget's width the same
+// as its height, for example by placing it inside a WMFrame with padding.
+class WMEllipse : public virtual WMWidget {
+ protected:
+  virtual void	  draw_border(Color c1, Color c2, int nsteps);
+  virtual void    draw_border();
+
+ public:
+  bool contains(int x, int y) const;
+
+  virtual ~WMEllipse() { }
+};
+
+#endif
diff --git a/wmapp/wmframe.cc b/wmapp/wmframe.cc
new file mode 100644
index 0000000..197e744
--- /dev/null
+++ b/wmapp/wmframe.cc
@@ -0,0 +1,303 @@
+#include <iostream>
+#include <cstdarg>
+#include "wmframe.h"
+#include "wmclickable.h"
+#include "wmwindow.h"
+#include "wmapp.h"
+
+using std::cerr;
+using std::endl;
+
+// functions for WMFrame -------------------------------------------------
+
+WMFrame::~WMFrame()
+{
+  if (wClipMask) {
+    WMApp::Xw.free_pixmap(*wClipMask);
+    delete wClipMask;
+  }
+}
+
+void
+WMFrame::real_display()
+{
+  if (border() || !transparency())
+    // fill frame with background color before adding children
+    WMApp::Xw.fill_rectangle(window()->pixmap(), b_position(),
+  	     		     WMColor(Background));
+}
+
+void
+WMFrame::display()
+{
+  if (!(parent() && parent()->is_displayed())) return;
+  real_display();
+  setdisplayed(true);
+
+  X::GC old_gc = 0;
+  if (wClipMask) {
+    // keep children from drawing where they shouldn't
+    old_gc = window()->pixmap().gc;
+    window()->pixmap().gc = wClipMask->gc;
+  }
+  for (unsigned int i = 0; i < numchildren(); i++)
+    child(i)->display();
+  if (wClipMask)
+    window()->pixmap().gc = old_gc;
+
+  draw_border();
+}
+
+void
+WMFrame::hide()
+{
+  if (!is_displayed()) return;
+  for (unsigned int i = 0; i < numchildren(); i++)
+    child(i)->hide();
+  real_hide();
+  setdisplayed(false);
+}
+
+void
+WMFrame::activate()
+{
+  if (is_active()) return;
+  setactive(true);
+  for (unsigned int i = 0; i < numchildren(); i++)
+    child(i)->activate();
+  real_activate();
+  if (app()->done()) return;
+  if (is_displayed()) display();
+}
+
+void
+WMFrame::deactivate()
+{ 
+  if (!is_active()) return;
+  real_deactivate();
+  for (unsigned int i = 0; i < numchildren(); i++)
+    child(i)->deactivate();
+  setactive(false);
+  if (is_displayed()) display();
+}
+
+bool
+WMFrame::addchild(WMWidget *w)
+{
+  if (is_displayed()) return false;
+
+  // child cannot already have a parent
+  if (w->parent()) {
+    cerr << "WMError: Reparenting child widget " << w << " to " << this
+	    << " not allowed" << endl;
+    return false;
+  }
+
+  // child cannot recursively contain "this"
+  const WMWidget *test = this;
+  while ((test = test->parent()))
+    if (test == w) {
+      cerr << "WMError: Widget " << w << " cannot be its own ancestor" << endl;
+      return false;
+    }
+  
+  w->setparent(this);
+  wChildren.push_back(w);
+  return true;
+}
+
+bool
+WMFrame::removechild(WMWidget *w)
+{
+  if (is_displayed()) return false;
+  for (unsigned int i = 0; i < numchildren(); i++)
+    if (w == child(i)) {
+      child(i)->setparent(0);
+      wChildren.erase(wChildren.begin() + i);
+      return true;
+    }
+  cerr << "WMError: Widget " << w << " is not a child of " << this << endl;
+  return false;
+}
+
+void
+WMFrame::clip(char *xpm_array[65])
+{ 
+  if (! is_displayed()) setaspectratios();
+  for (unsigned int i = 0; i < numchildren(); i++)
+    child(i)->clip(xpm_array);
+
+  if (! transparency() || border()) { // create a mask for drawing children
+    if (!wClipMask) {
+      wClipMask = new WMPixmap;
+      WMApp::Xw.create_pixmap(*wClipMask, xpm_array);
+      X::XFreePixmap(WMApp::Xw.xdisplay(), wClipMask->pixmap);
+      // free unused pixmap
+      wClipMask->pixmap = wClipMask->mask;
+      wClipMask->mask = 0; // muck around so xwrapper::free_pixmap works right
+      X::XSetClipMask(WMApp::Xw.xdisplay(), wClipMask->gc, wClipMask->pixmap);
+    }
+    
+    for (int col = left(); col < right(); col++)
+      for (int row = top(); row < bottom(); row++)
+        xpm_array[row + 3][col] = contains(col, row) ? 'X' : ' ';
+    // clip in the whole frame on the window's mask, but don't let widgets
+    // draw outside the frame
+  }
+}
+
+bool
+WMFrame::press(int button, int x, int y)
+{
+  WMClickable	*c;
+  
+  if (!contains(x, y)) {
+    return false; // button pressed is not within this frame
+  }
+    
+  for (unsigned int i = 0; i < numchildren(); i++)
+    if ((c = dynamic_cast<WMClickable *>(child(i))))
+      if (c->press(button, x, y)) return true;
+  return false;
+}
+
+// If the mouse button is released over the WMWidget on which it was
+// initially pressed, that widget's callbacks should be executed.
+bool 
+WMFrame::release(int button, int x, int y)
+{
+  WMClickable	*c;
+  
+  for (unsigned int i = 0; i < numchildren(); i++)
+    if ((c = dynamic_cast<WMClickable *>(child(i))))
+      if (c->release(button, x, y)) return true; 
+  return false;
+}
+
+// This function needs to be fixed to take care of leftover space if the
+// integer division wipes out a remainder.
+bool
+WMFrame::setaspectratios(vector<int> r)
+{
+  int totalspace = 0, availablespace;
+  if (wRatiosSet || numchildren() == 0) return true; // nothing to do
+
+  // if insufficient space to display any children, return an error
+  if (width() < 2 * border() || height() < 2 * border())
+    { cerr << "WMError: Frame " << this << " too small" << endl; return false; }
+
+  if (r.size() > 0) {
+    // Widgets that do not already have a size, for whom there is no
+    // corresponding element in the vector of size ratios, will be
+    // made size zero
+    while (r.size() < numchildren())
+      r.push_back(0);
+  }
+  
+  // calculate total space consumed by widgets with known sizes
+  for (unsigned int i = 0; i < numchildren(); i++)
+    totalspace += child(i)->par_to_parent();
+  availablespace = b_parallel() - totalspace - (numchildren() - 1) * padding();
+
+  // If widgets of known size take up more space than the frame has,
+  // rescale them in proportion and do not display the other widgets.
+  if (availablespace < 1) {
+    int numgoodchildren = 0;
+    for (unsigned int i = 0; i < numchildren(); i++) {
+      if (child(i)->par_to_parent() > 0)
+	numgoodchildren++;
+    }
+    availablespace = b_parallel() - (numgoodchildren - 1) * padding();
+    if (availablespace < 1 || numgoodchildren == 0) {
+      // not enough space, even for only the known-size widgets
+      cerr << "WMError: Frame " << this << " too small" << endl;
+      return false;
+    }
+
+    for (unsigned int i = 0; i < numchildren(); i++) {
+      if (child(i)->par_to_parent() > 0) {
+	double ratio = child(i)->par_to_parent() / totalspace;
+	child(i)->set_par_to_parent(static_cast<int>
+				    (ratio * availablespace));
+      }
+    }
+  }
+  
+  else { // Otherwise, scale the unknown-sized widgets appropriately.
+    double ratiosum = 0;
+    for (unsigned int i = 0; i < numchildren(); i++) {
+      if (child(i)->par_to_parent() == 0)
+	ratiosum += ((r.size() > 0) ? r[i] : 1.0);
+    }
+    for (unsigned int i = 0; i < numchildren(); i++)
+      if (child(i)->par_to_parent() == 0) {
+	double ratio = (r.size() ? r[i] : 1.0) / ratiosum;
+	child(i)->set_par_to_parent(static_cast<int>
+				    (ratio * availablespace));
+      }
+  }
+  
+  // Scale widgets in the perpendicular direction if necessary
+  for (unsigned int i = 0; i < numchildren(); i++)
+    if (child(i)->perp_to_parent() <= 0
+	|| child(i)->perp_to_parent() > b_perpend())
+      child(i)->set_perp_to_parent(b_perpend());
+  
+  // Finally, set the location of all these child widgets.
+  int posn = 0;
+  for (unsigned int i = 0; i < numchildren(); i++) {
+    if (child(i)->width() && child(i)->height()) {
+      if (orientation() == Orientation::Horizontal) {
+	child(i)->setleft(b_left() + posn);
+	child(i)->settop(b_top());
+      }
+      else {
+	child(i)->setleft(b_left());
+	child(i)->settop(b_top() + posn);
+      }
+      posn += child(i)->par_to_parent() + padding();
+    }
+  }
+
+  // Deal with rounding errors: if the last widget doesn't reach all the
+  // way to the end of the parent, force it to.  This isn't the best way
+  // to do this, but it's the easiest :)
+  if (child(numchildren() - 1)->par_to_parent()) {
+    WMWidget *lastchild = child(numchildren() - 1);
+    if (orientation() == Orientation::Horizontal)
+      lastchild->setwidth(right() - border() - lastchild->left());
+    else
+      lastchild->setheight(bottom() - border() - lastchild->top());
+  }
+    
+  wRatiosSet = true;
+  return true;
+}
+
+// varargs version for people too lazy to create an std::vector.
+// Use with caution: the number of arguments MUST equal the number
+// of children, since we can't check the number of arguments of a
+// varargs function within the function.  I'm not sure what happens
+// if you try to provide this function with fewer arguments than
+// the widget has children, but I imagine it's bad.
+bool
+WMFrame::setaspectratios(int ratio, ...)
+{
+  if (numchildren() < 1)
+    // nothing to do, return OK
+    return true;
+	
+  std::va_list args;
+  vector<int> v = vector<int>();
+  v.push_back(ratio);
+
+  va_start(args, ratio);
+  for (unsigned int i = 1; i < numchildren(); i++) {
+    ratio = va_arg(args, int);
+    v.push_back(ratio);
+  }
+  va_end(args);
+
+  return setaspectratios(v);
+}
+
diff --git a/wmapp/wmframe.h b/wmapp/wmframe.h
new file mode 100644
index 0000000..977268b
--- /dev/null
+++ b/wmapp/wmframe.h
@@ -0,0 +1,109 @@
+#include <vector>
+#include "wmwidget.h"
+#include "wmclickable.h"
+#include "xwrapper.h"
+
+#ifndef _WMFRAME_H
+#define _WMFRAME_H
+
+using std::vector;
+
+// WMFrame: A widget that can contain other widgets
+class WMFrame : public virtual WMClickable, public virtual WMWidget {
+ private:
+  int			wPadding;
+  bool			wRatiosSet;
+  bool			wTransparentPadding;
+  WMPixmap		*wClipMask;
+
+ protected:
+  vector<WMWidget *>    wChildren;
+  virtual void real_display();
+  
+ public:	 
+  WMFrame();
+  virtual ~WMFrame();
+  
+  WMWidget * child(int i) const;
+  unsigned int numchildren() const;
+  bool addchild(WMWidget &child);
+  bool addchild(WMWidget *child);
+  bool removechild(WMWidget &child);
+  bool removechild(WMWidget *child);
+
+  void clip(char *xpm_array[65]);
+  virtual void display();
+  virtual void hide();
+  virtual void activate();
+  virtual void deactivate();
+
+  int padding() const;
+  bool transparency() const;
+  
+  void setpadding(int);
+  void settransparency(bool);
+  
+  // what to do if a mouse button is pressed?
+  bool press(int button, int x, int y);
+  bool release(int button, int x, int y);
+  
+  // NOTE: The setaspectratios() function must be called on frames / windows
+  // in order from Parent to Child widgets!
+  //
+  // if passed no argument, this function allots equal space to
+  // all child widgets that do not already have a declared size.
+  // Otherwise, it uses the vector or va_list it's passed as a list of how
+  // the widgets should be sized relative to each other. Note that even though 
+  // widgets with non-zero sizes are not resized, the vector of sizes must
+  // contain dummy place-holder arguments for them anyway.
+  //
+  // For example, if the frame contains 4 widgets a,b,c,d, of which b already
+  // has a known (non-zero) size, and you call this function with argument
+  // being the vector (5,4,3), then widget a will be allotted 5/(5+3) = 5/8
+  // and widget c will be allotted 3/(5+3) = 3/8 of the space not already
+  // allotted to widget b.  Widget d will not be displayed. On the other hand,
+  // if you call this function with no argument, then a, c, and d will EACH be
+  // allocated 1/3 of the space not already taken by widget b.
+  //
+  // This function, however it is called, will scale widgets to the
+  // perpendicular size of the frame if their perpendicular dimension is not
+  // known.  If the perpendicular size of the widget IS known, it will be
+  // rescaled only if the widget is larger than the frame in that dimension.
+  bool setaspectratios(vector<int> ratiolist = vector<int>());
+
+  // a va_list version for people too lazy to create an std::vector:
+  bool setaspectratios(int ratio1, ...);
+};
+
+// inline functions for WMFrame ------------------------------------------
+
+inline WMFrame::WMFrame()
+: wPadding(2), wRatiosSet(false), wTransparentPadding(true), wClipMask(0),
+  wChildren() { setborder(0); }
+
+inline unsigned int
+WMFrame::numchildren() const { return wChildren.size(); }
+
+inline WMWidget *
+WMFrame::child(int i) const { return wChildren[i]; }
+
+inline bool
+WMFrame::addchild(WMWidget &child) { return addchild(&child); }
+
+inline bool
+WMFrame::removechild(WMWidget &child) { return removechild(&child); }
+
+inline int
+WMFrame::padding() const { return wPadding; }
+
+inline bool
+WMFrame::transparency() const { return wTransparentPadding; }
+
+inline void
+WMFrame::setpadding(int p) { if (!is_displayed()) wPadding = p; }
+    
+inline void
+WMFrame::settransparency(bool b)
+{ if (!is_displayed()) wTransparentPadding = b; }
+
+#endif
diff --git a/wmapp/wmhistory.cc b/wmapp/wmhistory.cc
new file mode 100644
index 0000000..5900069
--- /dev/null
+++ b/wmapp/wmhistory.cc
@@ -0,0 +1,67 @@
+#include <iostream>
+#include "wmhistory.h"
+#include "wmwindow.h"
+#include "wmapp.h"
+
+using std::cerr;
+using std::endl;
+
+// functions for WMHistory -----------------------------------------------
+// added by Jason
+
+void WMHistory::setvalue (int value, int index, bool dodisplay)
+{
+  if (index == -1)
+  {
+    wValues.pop_back();
+    wValues.push_front(value);
+  }
+  else
+    wValues[index] = value;
+  if (dodisplay)
+    display();
+}
+
+void WMHistory::setvalues (const vector<int>& values, bool dodisplay)
+{
+  vector<int>::const_iterator src = values.begin();
+  deque<int>::iterator dest = wValues.begin();
+  while (src != values.end() && dest != wValues.end())
+    *dest++ = *src++;
+  while (dest != wValues.end())
+    *dest++ = 0;
+  if (dodisplay)
+    display();
+}
+
+void WMHistory::clear(bool dodisplay)
+{ setvalues(vector<int>(0), dodisplay); }
+
+void WMHistory::real_display ()
+// XXX: Currently no vertical style, since it doesn't make a lot of sense
+{
+  WMApp::Xw.fill_rectangle(window()->pixmap(), b_position(),
+		  	   WMColor(Background));
+  if (!wTotal)
+    return;
+  if (width() < 2 * border() || height() < 2 * border())
+    { cerr << "WMError: History " << this << " too small" << endl; return; }
+
+  for (int x = 0; x < b_width(); x++)
+  {
+    int h = static_cast<int> (fraction(x) * b_height());
+    if (h < 1)
+      continue;
+    else if (h == 1)
+      WMApp::Xw.draw_point(window()->pixmap(), b_right() - 1 - x, b_bottom() - 1
+		           , WMColor(Bright));
+    else
+    {
+      WMApp::Xw.draw_line(window()->pixmap(), b_right() - 1 - x, b_bottom() - h,
+		          b_right() - 1 - x, b_bottom() - h + 1, WMColor(Bright));
+      if (h > 2)
+        WMApp::Xw.draw_line(window()->pixmap(), b_right() - 1 - x, b_bottom() - h + 2, b_right() - 1 - x, b_bottom() - 1, WMColor(Medium));
+    }
+  }
+}
+
diff --git a/wmapp/wmhistory.h b/wmapp/wmhistory.h
new file mode 100644
index 0000000..cd7c4cc
--- /dev/null
+++ b/wmapp/wmhistory.h
@@ -0,0 +1,71 @@
+#include <vector>
+#include <deque>
+#include "wmwidget.h"
+
+#ifndef _WMHISTORY_H
+#define _WMHISTORY_H
+
+using std::vector;
+using std::deque;
+
+// WMHistory: a progress / load meter showing a history
+// added by Jason
+// XXX: Should we have an option to rescale the graph automatically?
+class WMHistory : public virtual WMWidget {
+ private:
+  static const int size = 64; //Number of values that we keep around
+  deque<int> wValues;
+  int wTotal;
+  void real_display();
+
+ public:
+  WMHistory();
+  WMHistory(int total);
+  WMHistory(const vector<int>& values, int total);
+  // XXX: Too lazy to make any other constructors.
+
+  // All indexed functions refer to the element added that many units ago.
+  // An index of -1 therefore appends a new value to the graph.
+  void setvalue(int value, int index = -1, bool dodisplay = true);
+
+  //setvalues zeros the history before copying the given values in.
+  void setvalues(const vector<int>& values, bool dodisplay = true);
+  void setvalues(const vector<int>& values, int total, bool dodisplay = true);
+  void clear(bool dodisplay = true);
+  
+  void settotal(int total, bool dodisplay = true);
+
+  int value(int index = 0) const;
+  int total() const;
+  double fraction(int index = 0) const;
+};
+
+// inline functions for WMHistory ----------------------------------------
+
+inline WMHistory::WMHistory ()
+: wValues(WMHistory::size, 0), wTotal(0) { }
+
+inline WMHistory::WMHistory (int total)
+: wValues(WMHistory::size, 0), wTotal(total) { }
+
+inline WMHistory::WMHistory (const vector<int>& values, int total)
+: wValues(size), wTotal(total)
+{ setvalues(values, false); }
+
+inline void WMHistory::setvalues(const vector<int>& values, int total,
+  bool dodisplay)
+{ wTotal = total; setvalues(values, dodisplay); }
+
+inline void WMHistory::settotal (int total, bool dodisplay)
+{ wTotal = total; if (dodisplay) display(); }
+
+inline int WMHistory::value (int index) const
+{ return wValues[index]; }
+
+inline int WMHistory::total () const
+{ return wTotal; }
+
+inline double WMHistory::fraction (int index) const
+{ return static_cast<double>(wValues[index]) / wTotal; }
+
+#endif
diff --git a/wmapp/wmimage.cc b/wmapp/wmimage.cc
new file mode 100644
index 0000000..9d2b115
--- /dev/null
+++ b/wmapp/wmimage.cc
@@ -0,0 +1,91 @@
+#include <iostream>
+#include "wmimage.h"
+#include "wmwindow.h"
+#include "wmapp.h"
+
+using std::cerr;
+using std::endl;
+
+// functions for WMImage -------------------------------------------------
+
+WMImage::WMImage(const WMPixmap *pm)
+: wBGColor(WMColor(Background)) { seticon(pm); }
+
+WMImage::WMImage(const WMPixmap &pm)
+: wBGColor(WMColor(Background)) { seticon(pm); }
+
+WMImage::WMImage(char *xpm[])
+: wBGColor(WMColor(Background)) { seticon(xpm); }
+
+WMImage::~WMImage()
+{ if (icon()) WMApp::Xw.free_pixmap(wIcon); }
+
+void
+WMImage::seticon(bool dodisplay)
+{
+  if (icon()) WMApp::Xw.free_pixmap(wIcon);
+  if(WMApp::Xw.create_pixmap(wIcon, b_width(), b_height()))
+  {
+    WMApp::Xw.fill_rectangle(wIcon, 0, 0, b_width(), b_height(), bgcolor());
+    wIconPtr = &wIcon;
+    if (dodisplay) display();
+  }
+  else wIconPtr = 0;
+}
+
+void
+WMImage::seticon(const WMPixmap &pm, bool dodisplay)
+{
+  if (icon()) WMApp::Xw.free_pixmap(wIcon);
+  if (WMApp::Xw.create_pixmap(wIcon, pm))
+    { wIconPtr = &wIcon; if (dodisplay) display(); }
+  else wIconPtr = 0;
+}
+
+void
+WMImage::seticon(char *xpm[], bool dodisplay)
+{
+  if (icon()) WMApp::Xw.free_pixmap(wIcon);
+  if (WMApp::Xw.create_pixmap(wIcon, xpm))
+    { wIconPtr = &wIcon; if (dodisplay) display(); }
+  else wIconPtr = 0;
+}
+
+void
+WMImage::real_display()
+{
+  const int imgwidth = icon() ? icon()->attr.width : 0;
+  const int imgheight = icon() ? icon()->attr.height : 0;
+
+  // if no icon, create an icon that consists only of the background color
+  if (! icon())
+    seticon(false);
+
+  // if widget is not big enough to hold icon, complain about it
+  else if (imgwidth > b_width() || imgheight > b_height()) {
+    cerr << "WMError: Image " << this << " too small for icon" << endl;
+    return;
+  }
+
+  // if icon is smaller than widget, color in the rest with background color
+  else if (imgwidth < b_width() || imgheight < b_height()) {
+    WMPixmap temp;
+      
+    // Blit background color onto rectangle
+    WMApp::Xw.create_pixmap(temp, b_width(), b_height());
+    WMApp::Xw.fill_rectangle(temp, 0, 0, b_width(), b_height(), bgcolor());
+    // center icon onto background
+    WMApp::Xw.copy_rectangle(*icon(), temp, 0, 0, imgwidth, imgheight,
+		     (b_width() - imgwidth) / 2, (b_height() - imgheight) / 2);
+    // swap pixmaps
+    WMApp::Xw.free_pixmap(wIcon);
+    WMApp::Xw.create_pixmap(wIcon, temp);
+    WMApp::Xw.free_pixmap(temp);
+  }
+
+  // if we get here, widget (minus border) and icon are the same size -
+  // hallelujah!
+  WMApp::Xw.copy_rectangle(*icon(), window()->pixmap(), 0, 0,
+		  	   b_width(), b_height(), b_left(), b_top());
+}
+
diff --git a/wmapp/wmimage.h b/wmapp/wmimage.h
new file mode 100644
index 0000000..899c31f
--- /dev/null
+++ b/wmapp/wmimage.h
@@ -0,0 +1,52 @@
+#include "wmwidget.h"
+#include "xwrapper.h"
+
+#ifndef _WMIMAGE_H
+#define _WMIMAGE_H
+
+// WMImage: a widget that displays a picture in Xpm format
+class WMImage : public virtual WMWidget {
+ private:
+  WMPixmap		wIcon;
+  WMPixmap *		wIconPtr;
+
+ protected:
+  Color			wBGColor;
+  virtual void 		real_display();
+  WMPixmap *		p_icon();
+
+ public:
+  WMImage(const WMPixmap * pm = 0);
+  WMImage(const WMPixmap & pm);
+  WMImage(char *xpm[]);
+  virtual ~WMImage();
+
+  void seticon(bool dodisplay = true); //make an empty icon
+  void seticon(const WMPixmap *, bool dodisplay = true);
+  void seticon(const WMPixmap &, bool dodisplay = true);
+  void seticon(char *xpm[], bool dodisplay = true);
+  void setbgcolor(Color, bool dodisplay = true);
+  Color bgcolor() const;
+  const WMPixmap * icon() const;
+};
+
+// inline functions for WMImage ------------------------------------------
+
+inline void
+WMImage::seticon(const WMPixmap *pm, bool dodisplay)
+{ if (pm) seticon(*pm, dodisplay); else wIconPtr = 0; }
+
+inline void
+WMImage::setbgcolor(Color c, bool dodisplay)
+{ wBGColor = c; if (dodisplay) display(); }
+
+inline Color
+WMImage::bgcolor() const { return wBGColor; }
+
+inline WMPixmap *
+WMImage::p_icon() { return wIconPtr; }
+
+inline const WMPixmap *
+WMImage::icon() const { return wIconPtr; }
+
+#endif
diff --git a/wmapp/wmled.cc b/wmapp/wmled.cc
new file mode 100644
index 0000000..4c08b2a
--- /dev/null
+++ b/wmapp/wmled.cc
@@ -0,0 +1,12 @@
+#include "wmled.h"
+#include "wmapp.h"
+
+// functions for WMLed ---------------------------------------------------
+
+void
+WMLed::real_display()
+{
+  seticon(WMApp::leds_pixmap[static_cast<int>(led())], false);
+  if (icon()) WMImage::real_display();
+}
+
diff --git a/wmapp/wmled.h b/wmapp/wmled.h
new file mode 100644
index 0000000..5cf71de
--- /dev/null
+++ b/wmapp/wmled.h
@@ -0,0 +1,34 @@
+#include "wmimage.h"
+
+#ifndef _WMLED_H
+#define _WMLED_H
+
+// WMLed: displays a round LED-type thing with a different color depending on
+// its status.
+class WMLed : public virtual WMImage {
+ public:
+  enum LedState { Off, Good, Warning, Error };
+
+ private:
+  enum LedState wState;
+  void real_display();
+ 
+ public:
+  WMLed(LedState s = Off);
+  void setled(enum LedState s, bool dodisplay = true);
+  enum LedState led() const;
+};
+
+// inline functions for WMLed --------------------------------------------
+
+inline WMLed::WMLed(enum LedState s)
+: wState(s) { setborder(0); }
+
+inline void 
+WMLed::setled(enum LedState s, bool dodisplay)
+{ wState = s; if (dodisplay) display(); }
+
+inline enum WMLed::LedState
+WMLed::led() const { return wState; }
+
+#endif
diff --git a/wmapp/wmmeter.h b/wmapp/wmmeter.h
new file mode 100644
index 0000000..0239781
--- /dev/null
+++ b/wmapp/wmmeter.h
@@ -0,0 +1,57 @@
+#include "wmwidget.h"
+
+#ifndef _WMMETER_H
+#define _WMMETER_H
+
+// WMMeter: Base class for widgets that display a state of progress or load.
+// Cannot be instantiated (inherits the pure virtual function real_display).
+class WMMeter : public virtual WMWidget {
+ private:
+  int wValue, wTotal;
+  
+ public:
+  WMMeter();
+  WMMeter(int total);
+  WMMeter(int value, int total);
+  
+  virtual void setvalue(int value, bool dodisplay = true);
+  virtual void settotal(int total, bool dodisplay = true);
+
+  int value() const;
+  int total() const;
+  double fraction() const;
+};
+
+// inline functions for WMMeter ------------------------------------------
+
+inline WMMeter::WMMeter()
+: wValue(0), wTotal(0) { }
+
+inline WMMeter::WMMeter(int total)
+: wValue(0), wTotal(total) { }
+
+inline WMMeter::WMMeter(int val, int total)
+: wValue(val), wTotal(total) { }
+
+inline void
+WMMeter::setvalue(int val, bool dodisplay)
+{ wValue = val; if (dodisplay) display(); }
+
+inline void
+WMMeter::settotal(int total, bool dodisplay)
+{ wTotal = total; if (dodisplay) display(); }
+
+inline int
+WMMeter::value() const { return wValue; }
+
+inline int
+WMMeter::total() const { return wTotal; }
+
+inline double
+WMMeter::fraction() const
+{
+  if (wTotal == 0) return 0;
+  else return static_cast<double>(wValue) / wTotal;
+}		  
+
+#endif
diff --git a/wmapp/wmmeterbar.cc b/wmapp/wmmeterbar.cc
new file mode 100644
index 0000000..2ec6dfd
--- /dev/null
+++ b/wmapp/wmmeterbar.cc
@@ -0,0 +1,80 @@
+#include <iostream>
+#include <algorithm> // for max()
+#include "wmmeterbar.h"
+#include "wmwindow.h"
+#include "wmapp.h"
+
+using std::cerr;
+using std::endl;
+
+// functions for WMMeterBar ----------------------------------------------
+// added by Jason
+
+void
+WMMeterBar::real_display()
+{
+  if ((orientation() == Orientation::Horizontal && width() < 2 * border())
+      || (orientation() == Orientation::Vertical && height() < 2 * border()))
+    { cerr << "WMError: Meter Bar " << this << " too small" << endl; return; }
+
+  //first draw desired background 
+  switch (style())
+  {                     
+    case Spectrum:              
+      if (orientation() == Orientation::Horizontal)
+        WMApp::Xw.draw_horizontal_gradient(window()->pixmap(),
+            b_left(), b_top(), b_right(), b_bottom(), 0x5C00, 0x5C0000);
+      else
+        WMApp::Xw.draw_vertical_gradient(window()->pixmap(),
+	    b_left(), b_top(), b_right(), b_bottom(), 0x5C0000, 0x5C00);
+      break;
+    case Spec_No_BG:
+      WMApp::Xw.fill_rectangle(window()->pixmap(), b_position(),
+          WMColor(Background));
+      break;
+    case Blue:
+      WMApp::Xw.fill_rectangle(window()->pixmap(), b_position(),
+          WMColor(Background));
+      if (orientation() == Orientation::Horizontal)
+        for (int x = 0; x < b_width(); x += 2)
+          WMApp::Xw.draw_line(window()->pixmap(), x + b_left(), b_top(),
+              x + b_left(), b_bottom(), 0x004941);
+      else
+        for (int y = 0; y < b_height(); y += 2)
+          WMApp::Xw.draw_line(window()->pixmap(), b_left(),
+              b_bottom() - y, b_right(), b_bottom() - y, 0x004941);
+      break;
+  }
+
+  //then draw the progress bar
+  if (total() && value())
+  switch (style())
+  {
+    case Spectrum:
+    case Spec_No_BG:
+      if (orientation() == Orientation::Horizontal)
+        WMApp::Xw.draw_horizontal_gradient(window()->pixmap(),
+            b_left(), b_top(), b_right(), b_bottom(),
+	    0xFF00, 0xFF0000, fraction());
+      else
+        WMApp::Xw.draw_vertical_gradient(window()->pixmap(),
+	    b_left(), b_bottom(), b_right(), b_top(),
+            0xFF00, 0xFF0000, fraction());
+      break;
+    case Blue:
+      if (orientation() == Orientation::Horizontal)
+        for (int x = 0;
+	     x < static_cast<int>(std::min(1.0, fraction()) * b_width());
+	     x += 2)
+          WMApp::Xw.draw_line(window()->pixmap(), x + b_left(), b_top(),
+              x + b_left(), b_bottom(), WMColor(Bright));
+      else
+        for (int y = 0;
+	     y < static_cast<int>(std::min(1.0, fraction()) * b_height());
+	     y += 2)
+          WMApp::Xw.draw_line(window()->pixmap(), b_left(), b_bottom() - y,
+	      b_right(), b_bottom() - y, WMColor(Bright));
+      break;
+  }
+}
+
diff --git a/wmapp/wmmeterbar.h b/wmapp/wmmeterbar.h
new file mode 100644
index 0000000..00a4c0e
--- /dev/null
+++ b/wmapp/wmmeterbar.h
@@ -0,0 +1,47 @@
+#include "wmmeter.h"
+
+#ifndef _WMMETERBAR_H
+#define _WMMETERBAR_H
+
+// WMMeterBar: a progress bar showing the instantaneous progress or load
+// added by Jason
+class WMMeterBar : public virtual WMMeter {
+ public:
+  // The styles correspond to those in wmmon, wmtop, and wmsmixer respectively: 
+  // green-to-red bar on dark green-to-red background; likewise on dark
+  // colorless background; and turquoise hashmarks on dark background.
+  enum Style { Spectrum, Spec_No_BG, Blue };
+
+ private:
+  enum Style wStyle;
+
+ protected:
+  void real_display();
+
+ public:
+  WMMeterBar();
+  WMMeterBar(int total);
+  WMMeterBar(int value, int total);
+    
+  void setstyle(enum Style, bool dodisplay = true);
+  enum Style style() const;
+};
+
+// inline functions for WMMeterBar ---------------------------------------
+
+inline WMMeterBar::WMMeterBar() : WMMeter() { }
+
+inline WMMeterBar::WMMeterBar(int total) : WMMeter()
+{ settotal(total); }
+
+inline WMMeterBar::WMMeterBar(int val, int total) : WMMeter()
+{ settotal(total); setvalue(val); }
+
+inline void
+WMMeterBar::setstyle(enum Style s, bool dodisplay)
+{ wStyle = s; if (dodisplay) display(); }
+
+inline enum WMMeterBar::Style
+WMMeterBar::style() const { return wStyle; }
+
+#endif
diff --git a/wmapp/wmslider.cc b/wmapp/wmslider.cc
new file mode 100644
index 0000000..e73fd1e
--- /dev/null
+++ b/wmapp/wmslider.cc
@@ -0,0 +1,42 @@
+#include <algorithm>  // for max, min
+#include "wmslider.h"
+#include "wmapp.h"
+
+void slider_click(const WMApp *a, WMWidget *w, void *)
+{
+  WMSlider *s;
+  if (!(s = dynamic_cast<WMSlider *>(w))) return;
+
+  const WMMouseClick click = a->mouseclick().b_relative_to(w);
+  int newval;
+
+  if (click.button > Button3) {
+    const int increment = s->total() / 10;
+    newval = s->value() + (click.button == Button4 ? increment : -increment);
+  }
+  else {
+    const int xrel = click.x;
+    // the messy definition of yrel is due to widget layout using a downward-
+    // going y-axis, but WMMeterBars using an upward-going y-axis
+    const int yrel = s->b_height() - click.y;
+    const int rel = (s->orientation() == Orientation::Horizontal) ? xrel : yrel;
+    newval = (rel * s->total()) / s->b_parallel();
+  }
+
+  s->setvalue(std::max(0, std::min(s->total(), newval)));
+  a->repaint();
+}
+
+void
+WMSlider::attach_callbacks()
+{
+  addcallback(slider_click, this, 0);
+}
+
+// clearcallbacks() shouldn't delete the main callback function of this class
+void
+WMSlider::clearcallbacks()
+{
+  WMCallback::clearcallbacks();
+  WMSlider::attach_callbacks();
+}
diff --git a/wmapp/wmslider.h b/wmapp/wmslider.h
new file mode 100644
index 0000000..a706f1c
--- /dev/null
+++ b/wmapp/wmslider.h
@@ -0,0 +1,32 @@
+#include "wmcallback.h"
+#include "wmmeterbar.h"
+
+#ifndef _WMSLIDER_H
+#define _WMSLIDER_H
+
+// WMSlider: a bar that can be slid up or down to set a value.
+// Derived from WMMeterBar and WMCallback.
+class WMSlider : public WMCallback, public WMMeterBar {
+ private:
+  void attach_callbacks();
+  
+ public:
+  WMSlider();
+  WMSlider(int total);
+  WMSlider(int value, int total);
+
+  void clearcallbacks();
+};
+
+inline WMSlider::WMSlider()
+{ setstyle(Blue, false); attach_callbacks(); }
+
+inline WMSlider::WMSlider(int total)
+: WMMeterBar(total)
+{ setstyle(Blue, false); attach_callbacks(); }
+
+inline WMSlider::WMSlider(int value, int total)
+: WMMeterBar(value, total)
+{ setstyle(Blue, false); attach_callbacks(); }
+
+#endif
diff --git a/wmapp/wmtextbar.cc b/wmapp/wmtextbar.cc
new file mode 100644
index 0000000..7cb9ec3
--- /dev/null
+++ b/wmapp/wmtextbar.cc
@@ -0,0 +1,63 @@
+#include <iostream>
+#include "wmtextbar.h"
+#include "wmwindow.h"
+#include "wmapp.h"
+
+using std::cerr;
+using std::endl;
+
+// functions for WMTextBar -----------------------------------------------
+
+void
+WMTextBar::real_display()
+{
+  int charwidth, charheight, xbase, ybase;
+
+  // Blit background color onto rectangle
+  WMApp::Xw.fill_rectangle(window()->pixmap(), b_position(),
+		  	   WMColor(Background));
+
+  switch (fontsize()) {
+    case 0: charwidth = 5, charheight = 9; break;
+    case 1: charwidth = 6, charheight = 9; break;
+    case 2: charwidth = 7, charheight = 11; break;
+    default:
+      cerr << "WMError: Text bar " << this << " has bad font size "
+	   << fontsize() << endl;
+      return;
+  }
+
+  if (b_width() < charwidth || b_height() < charheight)
+    { cerr << "WMError: Text bar " << this << " too small" << endl; return; }
+  
+  xbase = b_left(), ybase = b_top();
+  // center the characters in the direction perpendicular to their orientation
+  if (orientation() == Orientation::Horizontal)
+    ybase += (b_height() - charheight) / 2;
+  else
+    xbase += (b_width() - charwidth) / 2;
+
+  // plot characters onto X display
+  for (unsigned int i = 0; xbase + charwidth < b_right()
+		&& ybase + charheight < b_bottom(); i++) {
+    unsigned char c = text(i);
+    if (c > ' ' && c <= 127) // 7-bit printable ASCII
+      // note: for a degree character, use ASCII 127 (DEL)
+      WMApp::Xw.copy_rectangle(app()->char_pixmaps[fontsize()],
+			       window()->pixmap(),
+      /* source X-Y coords  */ charwidth * (c % 16), charheight * (c / 16 - 2),
+      /* source width/height*/ charwidth, charheight,
+      /* destination coords */ xbase, ybase);
+    else
+      // no pixmap for this character; display a blank.
+      WMApp::Xw.copy_rectangle(app()->char_pixmaps[fontsize()],
+		      	       window()->pixmap(), 0, 0,
+			       charwidth, charheight, xbase, ybase);
+
+    if (orientation() == Orientation::Horizontal)
+      xbase += charwidth;
+    else
+      ybase += charheight;
+  }
+}
+
diff --git a/wmapp/wmtextbar.h b/wmapp/wmtextbar.h
new file mode 100644
index 0000000..9e0307b
--- /dev/null
+++ b/wmapp/wmtextbar.h
@@ -0,0 +1,57 @@
+#include "wmwidget.h"
+#include <string>
+
+#ifndef _WMTEXTBAR_H
+#define _WMTEXTBAR_H
+
+using std::string;
+
+// WMTextBar: a place to draw text in.
+class WMTextBar : public virtual WMWidget {
+ private:
+  string wText;
+  int wFontsize;
+  void real_display();
+ 
+ public:
+  WMTextBar(const string & text = "", int fontsize = 1);
+  ~WMTextBar();
+
+  void settext(const string & text, bool dodisplay = true);
+  void setfont(int fontsize, bool dodisplay = true);
+  const string & text() const;
+  char text(unsigned int) const;
+  int fontsize() const;
+  int size() const;
+};
+
+// inline functions for WMTextBar ----------------------------------------
+
+inline WMTextBar::WMTextBar(const string &text, int fontsize)
+: wText(text), wFontsize(fontsize)
+{ }
+
+inline WMTextBar::~WMTextBar() { }
+
+inline void
+WMTextBar::settext(const string &text, bool dodisplay)
+{ wText = text; if (dodisplay) display(); }
+
+inline void
+WMTextBar::setfont(int fontsize, bool dodisplay)
+{ wFontsize = fontsize; if (dodisplay) display(); }
+
+inline const string &
+WMTextBar::text() const { return wText; }
+
+inline char
+WMTextBar::text(unsigned int posn) const
+{ return (posn >= wText.size()) ? ' ' : wText[posn]; }
+
+inline int
+WMTextBar::fontsize() const { return wFontsize; }
+	
+inline int
+WMTextBar::size() const { return wText.size(); }
+
+#endif
diff --git a/wmapp/wmwidget.cc b/wmapp/wmwidget.cc
new file mode 100644
index 0000000..14c8bc3
--- /dev/null
+++ b/wmapp/wmwidget.cc
@@ -0,0 +1,99 @@
+#include "wmwidget.h"
+#include "wmwindow.h"
+#include "wmapp.h"
+
+// functions for WMWidget ------------------------------------------------
+
+WMWidget::WMWidget(const WMRectangle &posn, Orientation::Orientation o)
+: wOrientation(o), wPosition(posn), wBorder(1),
+  wTopLeft(WMColor(FrameBorderDim)), wBottomRight(WMColor(FrameBorderBright)),
+  wParent(0), wDisplayed(false), wActive(true)
+{ }
+
+int
+WMWidget::par_to_parent() const
+{
+  if (!parent()) return -1;
+  return (parent()->orientation() == Orientation::Horizontal) ?
+          position().width() : position().height();
+}
+
+int
+WMWidget::perp_to_parent() const
+{
+  if (!parent()) return -1;
+  return (parent()->orientation() == Orientation::Horizontal) ?
+          position().height() : position().width();
+}
+
+void
+WMWidget::set_par_to_parent(int p)
+{
+  if (wParent && !wDisplayed)
+    ((wParent->wOrientation == Orientation::Horizontal) ?
+     wPosition.setwidth(p) : wPosition.setheight(p));
+}
+
+void
+WMWidget::set_perp_to_parent(int p)
+{
+  if (wParent && !wDisplayed)
+    ((wParent->wOrientation == Orientation::Horizontal) ?
+     wPosition.setheight(p) : wPosition.setwidth(p));
+}
+
+const WMWindow *
+WMWidget::window() const { return wParent ? wParent->window() : 0; }
+
+WMApp *
+WMWidget::app() const { return wParent ? wParent->app() : 0; }
+
+void
+WMWidget::display()
+{
+  if (!(parent() && parent()->is_displayed())) return;
+  real_display();
+  draw_border();
+  setdisplayed(true);
+}
+
+void
+WMWidget::draw_border()
+{
+  if (border() && 2 * border() < width() && 2 * border() < height())
+    WMApp::Xw.draw_border(window()->pixmap(), position(), border(),
+			  top_left_c(), bottom_right_c(),
+			  Color::alpha_blend(top_left_c(), bottom_right_c(),
+				  	     0.5));  
+}
+  
+void
+WMWidget::hide()
+{
+  if (!is_displayed()) return;
+  real_hide();
+  setdisplayed(false);
+}
+
+void
+WMWidget::activate()
+{
+  if (is_active()) return;
+  real_activate();
+  setactive(true);
+  if (is_displayed()) display();
+}
+
+void
+WMWidget::deactivate()
+{ 
+  if (!is_active()) return;
+  real_deactivate();
+  setactive(false);
+  if (is_displayed()) display();
+}
+
+void
+WMWidget::real_hide()
+{ if (window()) WMApp::Xw.clear_rectangle(window()->pixmap(), position()); }
+
diff --git a/wmapp/wmwidget.h b/wmapp/wmwidget.h
new file mode 100644
index 0000000..38213e0
--- /dev/null
+++ b/wmapp/wmwidget.h
@@ -0,0 +1,367 @@
+#include "colors.h"
+
+#ifndef _WMWIDGET_H
+#define _WMWIDGET_H
+
+// needed forward declarations
+class WMApp;
+class WMWindow;
+class WMFrame;
+
+// Classes for writing complicated WindowMaker Dockapp programs! Yaay!
+// Note: I'm lazy, so ALL LAYOUT has to be done statically before the
+// WMApp starts to run.
+
+namespace Orientation {
+  enum Orientation { Horizontal, Vertical };
+};
+
+class WMRectangle {
+ private:
+  int wLeft, wTop, wWidth, wHeight;
+ public:
+  WMRectangle(int Left = 0, int Top = 0, int Width = 0, int Height = 0);
+  WMRectangle(const WMRectangle &r);
+  WMRectangle & operator = (const WMRectangle &r);
+  ~WMRectangle();
+
+  int left() const;
+  int right() const;
+  int top() const;
+  int bottom() const;
+  int width() const;
+  int height() const;
+  bool contains(int x, int y) const;
+
+  void setleft(int);
+  void settop(int);
+  void setwidth(int);
+  void setheight(int);
+};
+
+// WMWidget: the base class for all Dockapp widgets.  Cannot be instantiated.
+class WMWidget {
+ private:
+  enum Orientation::Orientation	wOrientation;
+  WMRectangle			wPosition;
+  int				wBorder;
+  Color				wTopLeft, wBottomRight;
+  const WMFrame *		wParent;
+  bool  	                wDisplayed;
+  bool				wActive;
+  
+ protected:
+  // these functions do the actual work of displaying a widget.
+  virtual void real_display() = 0;
+  virtual void draw_border();
+  virtual void real_hide();
+  
+  // colors for border of widget
+  Color top_left_c() const;
+  Color bottom_right_c() const;
+  void set_top_left_c(const Color & c);
+  void set_bottom_right_c(const Color & c);
+  
+  virtual void real_activate()   { } // these will be no-ops except
+  virtual void real_deactivate() { } // for clickable widgets
+ 
+  void setactive(bool);
+  void setdisplayed(bool);
+  
+ public:
+  WMWidget(const WMRectangle &layout = WMRectangle(0, 0, 0, 0),
+	   Orientation::Orientation o = Orientation::Horizontal);
+  virtual ~WMWidget();
+
+  virtual WMApp *app() const;
+  virtual const WMWindow *window() const;
+  virtual const WMFrame *parent() const;
+  virtual void setparent(const WMFrame *); // should be protected, but then
+  virtual void setparent(const WMFrame &); // WMFrame can't use on children
+  virtual void clip(char *xpm_array[65]);
+  
+  virtual void setposition(const WMRectangle &posn);
+  void setorientation(Orientation::Orientation o);
+
+  // these functions do all the busywork of displaying a widget.
+  virtual void display();	// over-ridden by WMFrame
+  virtual void hide();		// in order to act recursively
+  virtual void activate();	// on all child widgets
+  virtual void deactivate();	//
+  
+  const WMRectangle & position() const;
+  enum Orientation::Orientation orientation() const;
+  virtual bool contains(int x, int y) const;
+
+  int top() const;
+  int left() const;
+  int bottom() const;
+  int right() const;
+  int border() const;
+  
+  int width() const;
+  int height() const;  
+  int parallel() const;		// dimension parallel to orientation
+  int perpend() const;		// dimension perpendicular to orientation
+  int par_to_parent() const;	// dimension parallel to parent's orientation
+  int perp_to_parent() const;	// dimension perp. to parent's orientation
+
+  // like above, but only considering the part of the widget INSIDE its border
+  WMRectangle b_position() const;
+  int b_top() const;
+  int b_left() const;
+  int b_bottom() const;
+  int b_right() const;
+  int b_width() const;
+  int b_height() const;  
+  int b_parallel() const;
+  int b_perpend() const;
+  int b_par_to_parent() const;
+  int b_perp_to_parent() const;
+ 
+  // "set" accessor functions
+  void settop(int);
+  void setleft(int);
+  void setborder(int);
+  
+  void setwidth(int);
+  void setheight(int);
+  void setparallel(int);
+  void setperpend(int);
+  void set_par_to_parent(int);
+  void set_perp_to_parent(int);
+  
+  bool is_displayed() const;
+  bool is_active() const;
+};
+
+
+// inline functions for WMRectangle --------------------------------------
+
+inline WMRectangle::WMRectangle(int Left, int Top, int Width, int Height)
+: wLeft(Left), wTop(Top), wWidth(Width), wHeight(Height)
+{ }
+
+inline WMRectangle::WMRectangle(const WMRectangle &r)
+: wLeft(r.wLeft), wTop(r.wTop), wWidth(r.wWidth), wHeight(r.wHeight)
+{ }
+
+inline WMRectangle::~WMRectangle() { }
+
+inline WMRectangle &
+WMRectangle::operator = (const WMRectangle &r)
+{
+  wLeft = r.wLeft, wTop = r.wTop, wWidth = r.wWidth, wHeight = r.wHeight;
+  return *this;
+}
+
+inline int
+WMRectangle::left() const { return wLeft; }
+
+inline int
+WMRectangle::right() const { return wLeft + wWidth; }
+
+inline int
+WMRectangle::top() const { return wTop; }
+
+inline int
+WMRectangle::bottom() const { return wTop + wHeight; }
+
+inline int
+WMRectangle::width() const { return wWidth; }
+
+inline int
+WMRectangle::height() const { return wHeight; }
+
+inline void
+WMRectangle::setleft(int l) { wLeft = l; }
+
+inline void
+WMRectangle::settop(int t) { wTop = t; }
+
+inline void
+WMRectangle::setwidth(int w) { wWidth = w; }
+
+inline void
+WMRectangle::setheight(int h) { wHeight = h; }
+
+inline bool
+WMRectangle::contains(int x, int y) const
+{ return x >= left() && x < right() && y >= top() && y < bottom(); }
+
+// inline functions for WMWidget -----------------------------------------
+
+inline WMWidget::~WMWidget() { }
+
+inline const WMFrame *
+WMWidget::parent() const { return wParent; }
+
+inline void
+WMWidget::clip(char *xpm_array[65])
+{
+  for (int col = left(); col < right(); col++)
+    for (int row = top(); row < bottom(); row++)
+      if (contains(col, row))
+        xpm_array[row + 3][col] = 'X';
+}
+
+inline void
+WMWidget::setparent(const WMFrame *f) { wParent = f; }
+
+inline void
+WMWidget::setparent(const WMFrame &f) { wParent = &f; }
+
+inline void
+WMWidget::setactive(bool b) { wActive = b; }
+	
+inline void
+WMWidget::setdisplayed(bool b) { wDisplayed = b; }
+
+inline Color
+WMWidget::top_left_c() const { return wTopLeft; }
+
+inline Color
+WMWidget::bottom_right_c() const { return wBottomRight; }
+
+inline void 
+WMWidget::set_top_left_c(const Color & c) { wTopLeft = c; }
+
+inline void
+WMWidget::set_bottom_right_c(const Color & c) { wBottomRight = c; }
+
+inline void
+WMWidget::setposition(const WMRectangle &posn)
+{ if (!wDisplayed) wPosition = posn; }
+
+inline void
+WMWidget::setorientation(Orientation::Orientation o)
+{ if (!wDisplayed) wOrientation = o; }
+
+inline const WMRectangle &
+WMWidget::position() const { return wPosition; }
+
+inline enum Orientation::Orientation
+WMWidget::orientation() const { return wOrientation; }
+
+inline bool
+WMWidget::contains(int x, int y) const { return position().contains(x, y); }
+
+inline int
+WMWidget::top() const { return position().top(); }
+
+inline int
+WMWidget::left() const { return position().left(); }
+
+inline int
+WMWidget::bottom() const { return position().bottom(); }
+
+inline int
+WMWidget::right() const { return position().right(); }
+
+inline int
+WMWidget::border() const { return wBorder; }
+
+inline int
+WMWidget::width() const { return position().width(); }
+
+inline int
+WMWidget::height() const { return position().height(); }
+
+inline int
+WMWidget::parallel() const
+{
+  return (orientation() == Orientation::Horizontal) ?
+	  position().width() : position().height();
+}
+
+inline int
+WMWidget::perpend() const
+{
+  return (orientation() == Orientation::Horizontal) ?
+	  position().height() : position().width();
+}
+
+// like above, but only considering the part of the widget INSIDE its border:
+
+inline WMRectangle
+WMWidget::b_position() const
+{
+  return WMRectangle(left() + border(), top() + border(),
+		     width() - 2 * border(), height() - 2 * border());
+}
+
+inline int
+WMWidget::b_top() const { return top() + border(); }
+
+inline int
+WMWidget::b_left() const { return left() + border(); }
+
+inline int
+WMWidget::b_bottom() const { return bottom() - border(); }
+
+inline int
+WMWidget::b_right() const { return right() - border(); }
+
+inline int
+WMWidget::b_width() const { return width() - 2 * border(); }
+
+inline int
+WMWidget::b_height() const { return height() - 2 * border(); }
+
+inline int
+WMWidget::b_parallel() const { return parallel() - 2 * border(); }
+
+inline int
+WMWidget::b_perpend() const { return perpend() - 2 * border(); }
+
+inline int
+WMWidget::b_par_to_parent() const { return par_to_parent() - 2 * border(); }
+
+inline int
+WMWidget::b_perp_to_parent() const { return perp_to_parent() - 2 * border(); }
+
+// "set" accessor functions:
+
+inline void
+WMWidget::setwidth(int w)
+{ if (!wDisplayed) wPosition.setwidth(w); }
+
+inline void
+WMWidget::setheight(int h)
+{ if (!wDisplayed) wPosition.setheight(h); }
+
+inline void
+WMWidget::settop(int t)
+{ if (!wDisplayed) wPosition.settop(t); }
+
+inline void
+WMWidget::setleft(int l)
+{ if (!wDisplayed) wPosition.setleft(l); }
+
+inline void
+WMWidget::setborder(int b)
+{ if (!wDisplayed) wBorder = b; }
+
+inline void
+WMWidget::setparallel(int p)
+{
+  if (!wDisplayed)
+    ((wOrientation == Orientation::Horizontal) ?
+     wPosition.setwidth(p) : wPosition.setheight(p));
+}
+
+inline void
+WMWidget::setperpend(int p)
+{
+  if (!wDisplayed)
+    ((wOrientation == Orientation::Horizontal) ?
+     wPosition.setheight(p) : wPosition.setwidth(p));
+}
+
+inline bool
+WMWidget::is_displayed() const { return wDisplayed; }
+
+inline bool
+WMWidget::is_active() const { return wActive; }
+
+#endif
diff --git a/wmapp/wmwindow.cc b/wmapp/wmwindow.cc
new file mode 100644
index 0000000..71a7e98
--- /dev/null
+++ b/wmapp/wmwindow.cc
@@ -0,0 +1,114 @@
+#include <iostream>
+#include "wmwindow.h"
+#include "wmapp.h"
+
+using std::cerr;
+using std::endl;
+
+// functions for WMWindow ------------------------------------------------
+
+// this is here instead of inlined due to dependency on WMApp
+WMWindow::WMWindow()
+: WMFrame(), wApp(0), wUpdateFreq(10 /* milliseconds */),
+  wCounter(0), wFuncPeriod()
+{ 
+  setpadding(2);
+  setborder(0);
+
+  pixmap().pixmap = 0;
+  //use this as a flag determining whether the pixmaps are initialized
+
+  int offset = WMApp::size() / 2 - 28;
+  setposition(WMRectangle(offset, offset, 56, 56));
+} 
+
+WMWindow::~WMWindow ()
+{
+  if (pixmap().pixmap) { //only free if it was actually allocated
+    WMApp::Xw.free_pixmap(pixmap());
+  }
+}
+
+void
+WMWindow::run_timed_functions()
+{
+  for (unsigned int i = 0; i < numcallbacks(); i++)
+    if (! (wCounter % wFuncPeriod[i])) {
+      runcallback(i);
+    }
+  wCounter++;
+}
+
+void
+WMWindow::initpixmaps()
+{
+  // Xlib has no facility to create a mask on the fly from an xpm (at least
+  // not that I know about), so we have to do it the hard way, initializing a
+  // mask from a char* array:
+
+  char *mask_xpm[67];
+  for (unsigned int i = 0; i < 67; i++)
+    mask_xpm[i] = new char[65];
+
+  strcpy(mask_xpm[0], "64 64 2 1");		// width, height, #colors, (?)
+  strcpy(mask_xpm[1], "       c None");		// transparent
+  strcpy(mask_xpm[2], "X      c #000000");	// black
+  for (unsigned int i = 3; i < 67; i++)
+    strcpy(mask_xpm[i], // string with 64 spaces --v
+      "                                                                ");
+  //   0123456789012345678901234567890123456789012345678901234567890123
+  //             1         2         3         4         5         6
+  
+  // now mask out where we want to display things
+  for (unsigned int i = 0; i < numchildren(); i++)
+    child(i)->clip(mask_xpm);
+
+  // finally, create the pixmap and mask
+  WMApp::Xw.create_pixmap(pixmap(), mask_xpm);
+  WMApp::Xw.fill_rectangle(pixmap(), 0, 0, 64, 64, 0xFFFFFF /*white*/);
+
+  // clean up
+  for (unsigned int i = 0; i < 67; i++)
+    delete [] mask_xpm[i];
+}
+
+void
+WMWindow::display()
+{
+  // obviously, we replace the check for existence of a parent
+  // with check for existence of an app
+  if (!app()) {
+    cerr << "WMError: Window " << this << "has no parent application" << endl;
+    return;
+  }
+
+  real_display();
+  setdisplayed(true);
+  for (unsigned int i = 0; i < numchildren(); i++)
+    child(i)->display();
+  
+  // show the window and start running the GUI and callbacks
+  app()->Xshow();
+
+  // don't get here until the GUI has been requested to switch to 
+  // a different window (via a callback), or to exit
+  return;
+}
+
+void
+WMWindow::real_display()
+{
+  if (!wPixmap.pixmap)
+    initpixmaps(); //call this function only once
+  
+  // apply the mask to the application window so that areas not included
+  // in any widget are clear to the icon tile below
+  app()->mask();
+}
+
+void
+WMWindow::real_activate() { display(); }
+
+void
+WMWindow::real_deactivate() { hide(); }
+
diff --git a/wmapp/wmwindow.h b/wmapp/wmwindow.h
new file mode 100644
index 0000000..20a4ef5
--- /dev/null
+++ b/wmapp/wmwindow.h
@@ -0,0 +1,130 @@
+#include "wmframe.h"
+#include "wmcallback.h"
+#include "xwrapper.h"
+
+#ifndef _WMWINDOW_H
+#define _WMWINDOW_H
+
+class WMApp;
+
+// WMWindow: A 64x64 pixel square containing a number of widgets.  You can
+// set it to run callback functions at regular intervals.  Only one WMWindow
+// may be displayed at once.  This is controlled by the WMApp containing a
+// vector of WMWindows.
+class WMWindow : private WMCallback, public WMFrame {
+ friend class WMApp;
+
+ private:
+  WMApp *		wApp;
+  mutable WMPixmap	wPixmap;
+
+  // how often to execute callbacks and update display, in milliseconds
+  int		wUpdateFreq;
+  int		wCounter;
+  // list of periods of individual callbacks (in units of wUpdateFreq)
+  vector<int>	wFuncPeriod;
+
+  void initpixmaps();
+  void real_display();
+  void real_activate();
+  void real_deactivate();
+
+  // should be called only by a WMApp.
+  void display();
+  void hide();
+  void activate();
+  void deactivate();
+  void run_timed_functions();
+
+ public:
+  WMWindow();
+  ~WMWindow();
+
+  const WMWindow * window() const; // returns "this"
+
+  // override these to make them no-ops; windows have no parents
+  WMFrame *parent();
+  void setparent(const WMFrame *);
+  void setparent(const WMFrame &);
+  
+  WMApp * app() const;
+  int updatefreq() const;
+  WMPixmap & pixmap() const;
+
+  void setapp(WMApp *);
+
+  void setupdatefreq(int milliseconds);
+  void add_timed_function(int period, data_func d, void * = 0);
+  void add_timed_function(int period, widget_func w, WMWidget *, void * = 0);
+  void clear_timed_functions();
+
+  bool press(int button, int x, int y);
+  bool release(int button, int x, int y);
+};
+
+// inline functions for WMWindow -----------------------------------------
+
+inline void
+WMWindow::activate() { WMFrame::activate(); }
+
+inline void
+WMWindow::deactivate() { WMFrame::deactivate(); }
+
+inline void
+WMWindow::hide() { WMFrame::hide(); }
+
+inline const WMWindow *
+WMWindow::window() const { return this; }
+
+inline WMFrame *
+WMWindow::parent() { return 0; }
+
+inline void
+WMWindow::setparent(const WMFrame *) { }
+
+inline void
+WMWindow::setparent(const WMFrame &) { }
+
+inline WMApp *
+WMWindow::app() const { return wApp; }
+
+inline int
+WMWindow::updatefreq() const { return wUpdateFreq; }
+
+inline void
+WMWindow::setupdatefreq(int milliseconds) { wUpdateFreq = milliseconds; }
+
+inline void
+WMWindow::add_timed_function(int period, data_func f, void *datap)
+{
+  WMCallback::addcallback(f, datap);
+  wFuncPeriod.push_back(period);
+}
+
+inline void
+WMWindow::add_timed_function(int period, widget_func f, WMWidget *w,
+		             void *datap)
+{
+  WMCallback::addcallback(f, w, datap);
+  wFuncPeriod.push_back(period);
+}
+
+inline void
+WMWindow::clear_timed_functions()
+{
+  WMCallback::clearcallbacks();
+  wFuncPeriod.clear();
+}
+  
+inline WMPixmap &
+WMWindow::pixmap() const { return wPixmap; }
+
+inline bool
+WMWindow::press(int button, int x, int y)
+{ return WMFrame::press(button, x, y); }
+
+inline bool
+WMWindow::release(int button, int x, int y)
+{ return WMFrame::release(button, x, y); }
+
+#endif
diff --git a/wmapp/xpm/charmap-large.xpm b/wmapp/xpm/charmap-large.xpm
new file mode 100644
index 0000000..037ca2f
--- /dev/null
+++ b/wmapp/xpm/charmap-large.xpm
@@ -0,0 +1,74 @@
+/* XPM */
+static char * charmap_large_xpm[] = {
+"112 66 5 1",
+" 	c None",
+".	c #282828",
+"+	c #004941",
+"@	c #20B2AE",
+"#	c #188A86",
+"................................................................................................................",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+"................................................................................................................",
+"................................................................................................................",
+"..@@@@...++++#.#@@@@#.#@@@@#.#++++#.#@@@@#.#@@@@#.#@@@@#.#@@@@#.#@@@@#.........++++...++++...++++...++++...++++.",
+". at ....@.+.... at .+....@.+.... at .@.... at .@....+. at ....+.+....@. at ....@. at ....@... at ....+....+.+....+.+....+.+....+.+....+",
+". at ....@.+.... at .+....@.+.... at .@.... at .@....+. at ....+.+....@. at ....@. at ....@... at ....+....+.+....+.+....+.+....+.+....+",
+". at ....@.+.... at .+....@.+.... at .@.... at .@....+. at ....+.+....@. at ....@. at ....@........+....+.+....+.+....+.+....+.+....+",
+".#++++#..++++#.#@@@@#.#@@@@#.#@@@@#.#@@@@#.#@@@@#..++++#.#@@@@#.#@@@@#.........++++...++++...++++...++++...++++.",
+". at ....@.+.... at .@....+.+.... at .+....@.+.... at .@.... at .+....@. at ....@.+.... at ........+....+.+....+.+....+.+....+.+....+",
+". at ....@.+.... at .@....+.+.... at .+....@.+.... at .@.... at .+....@. at ....@.+.... at ...@....+....+.+....+.+....+.+....+.+....+",
+". at ....@.+.... at .@....+.+.... at .+....@.+.... at .@.... at .+....@. at ....@.+.... at ...@....+....+.+....+.+....+.+....+.+....+",
+"..@@@@...++++#.#@@@@#.#@@@@#..++++#.#@@@@#.#@@@@#..++++#.#@@@@#.#@@@@#.........++++...++++...++++...++++...++++.",
+"................................................................................................................",
+"................................................................................................................",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+"................................................................................................................",
+"................................................................................................................",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+"................................................................................................................",
+"................................................................................................................",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+"................................................................................................................",
+"................................................................................................................",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+".+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+.+....+",
+"..++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++...++++.",
+"................................................................................................................"};
diff --git a/wmapp/xpm/charmap-medium.xpm b/wmapp/xpm/charmap-medium.xpm
new file mode 100644
index 0000000..99a87a7
--- /dev/null
+++ b/wmapp/xpm/charmap-medium.xpm
@@ -0,0 +1,62 @@
+/* XPM */
+static char * charmap_medium_xpm[] = {
+"96 54 5 1",
+" 	c None",
+".	c #282828",
+"+	c #004941",
+"@	c #20B2AE",
+"#	c #188A86",
+"................................................................................................",
+"..+++...+++...+++...+++...+++...+++...+++...+++... at ++...++@...+++...+++.........+++.........++##",
+".+...+.+...+.+...+.+...+.+...+.+...+.+...+.+...+. at ...+.+...@.+...+.+. at .+.......+...+.......+..@+",
+".+...+.+...+.+...+.+...+.+...+.+...+.+...+.+...+. at ...+.+...@.+...+.+. at .+.......+...+.......+.##+",
+"..+++...+++...+++...+++...+++...+++...+++...+++..#+++...+++#..+++..#@@@#........#@@.........+ at +.",
+".+...+.+...+.+...+.+...+.+...+.+...+.+...+.+...+. at ...+.+...@.+...+.+. at .+.......+...+.......+##.+",
+".+...+.+...+.+...+.+...+.+...+.+...+.+...+.+...+. at ...+.+...@.+...+.+. at .+....@..+...+.......+ at ..+",
+"..+++...+++...+++...+++...+++...+++...+++...+++... at ++...++@...+++...+++....##...+++...#@...##++.",
+"................................................................................................",
+"................................................................................................",
+"..@@@...+++#.#@@@#.#@@@#. at +++@.#@@@#.#@@@#.#@@@#.#@@@#.#@@@#..............+++...+++...+++...+++.",
+". at ...@.+... at .+...@.+... at .@... at .@...+. at ...+.+...@. at ...@. at ...@.............+...+.+...+.+...+.+...+",
+". at ...@.+... at .+...@.+... at .@... at .@...+. at ...+.+...@. at ...@. at ...@..#@....#@...+...+.+...+.+...+.+...+",
+".#+++#..+++#.#@@@#..@@@#.#@@@#.@@@@#.#@@@#..+++#.#@@@#.#@@@#..............+++...+++...+++...+++.",
+". at ...@.+... at .@...+.+... at .+...@.+... at .@... at .+...@. at ...@.+... at .............+...+.+...+.+...+.+...+",
+". at ...@.+... at .@...+.+... at .+...@.+... at .@... at .+...@. at ...@.+... at ..#@..... at ...+...+.+...+.+...+.+...+",
+"..@@@...+++ at .#@@@#.#@@@#..+++#.#@@@#.#@@@#..+++ at .#@@@#.#@@@#........##....+++...+++...+++...+++.",
+"................................................................................................",
+"................................................................................................",
+".+@@@+.+@@@+.#@@@...@@@#.#@@@..#@@@#.#@@@#.#@@@#.#+++#..@@@...+++#.#+++#.#+++.. at +++@.#@@@..#@@@#",
+". at ...@. at ...@. at ...@. at ...+.@... at .@...+. at ...+.@...+. at ...@.+. at .+.+...@. at ...@. at ...+.@@.@@. at ...@. at ...@",
+". at ...@. at ...@. at ...@. at ...+.@... at .@...+. at ...+.@...+. at ...@.+. at .+.+...@. at ..@.. at ...+.@. at .@. at ...@. at ...@",
+".#+@@#.#@@@#.#@@@..#+++..#+++#.#@@@..#@@@..#+#@#.#@@@#..+#+...+++#.#@@...#+++..#+++#.#+++#.#+++#",
+". at .@@+. at ...@. at ...@. at ...+.@... at .@...+. at ...+.@... at .@... at .+.@.+.+... at .@.. at ..@...+. at ...@. at ...@. at ...@",
+". at ...+.@... at .@... at .@...+. at ...@. at ...+.@...+. at ...@. at ...@.+. at .+.@... at .@... at .@...+. at ...@. at ...@. at ...@",
+".#@@@#.#+++#.#@@@...@@@#.#@@@..#@@@#.#+++..#@@@#.#+++#..@@@..#@@@#.#+++#.#@@@#.#+++#.#+++#.#@@@#",
+"................................................................................................",
+"................................................................................................",
+".#@@@#.#@@@#.#@@@#.#@@@#.#@@@#.#+++#.#+++#.#+++#.#+++#.#+++#.#@@@#.#@++..##++...++@#..+++...+++.",
+". at ...@. at ...@. at ...@. at ...+.+.@.+. at ...@. at ...@. at ...@. at ...@. at ...@.+... at .@...+.+ at ..+.+...@.+...+.+...+",
+". at ...@. at ...@. at ...@. at ...+.+.@.+. at ...@. at ...@. at ...@.. at .@.. at ...@.+.. at +.@...+.+##.+.+... at .+...+.+...+",
+".#@@@#.#@++#.#@@@..#@@@#..+#+..#+++#.#+++#.#+++#... at ...#@@@#..+ at +..#+++...+ at +...+++#..+++...+++.",
+". at ...+.@. at .@. at ...@.+... at .+.@.+. at ...@. at ...@. at .@. at ..@. at ..+...@.+ at ..+.@...+.+.##+.+... at .+...+.+...+",
+". at ...+.@..@@. at ...@.+... at .+.@.+. at ...@. at ...@.@@.@@. at ...@.+... at .@...+. at ...+.+..@+.+... at .+...+.+...+",
+".#+++..#@@@#.#+++#.#@@@#..+#+..#@@@#..#@#..#+++#.#+++#.#@@@#.#@@@#.#@++...++##..++@#..+++..#@@@#",
+"................................................................................................",
+"................................................................................................",
+"..+++..+@@@+.#@@@...@@@#.#@@@..#@@@#.#@@@#.#@@@#.#+++#..@@@...+++#.#+++#.#+++.. at +++@.#@@@..#@@@#",
+".+...+. at ...@. at ...@. at ...+.@... at .@...+. at ...+.@...+. at ...@.+. at .+.+...@. at ...@. at ...+.@@.@@. at ...@. at ...@",
+".+...+. at ...@. at ...@. at ...+.@... at .@...+. at ...+.@...+. at ...@.+. at .+.+...@. at ..@.. at ...+.@. at .@. at ...@. at ...@",
+"..+++..#@@@#.#@@@..#+++..#+++#.#@@@..#@@@..#+#@#.#@@@#..+#+...+++#.#@@...#+++..#+++#.#+++#.#+++#",
+".+...+. at ...@. at ...@. at ...+.@... at .@...+. at ...+.@... at .@... at .+.@.+.+... at .@.. at ..@...+. at ...@. at ...@. at ...@",
+".+...+. at ...@. at ...@. at ...+.@... at .@...+. at ...+.@... at .@... at .+.@.+. at ...@. at ...@. at ...+.@... at .@... at .@...@",
+"..+++..#+++#.#@@@...@@@#.#@@@..#@@@#.#+++..#@@@#.#+++#..@@@..#@@@#.#+++#.#@@@#.#+++#.#+++#.#@@@#",
+"................................................................................................",
+"................................................................................................",
+".#@@@#.#@@@#.#@@@#.#@@@#.#@@@#.#+++#.#+++#.#+++#.#+++#.#+++#.#@@@#..++ at ...+#+... at ++...+++..+@+..",
+". at ...@. at ...@. at ...@. at ...+.+.@.+. at ...@. at ...@. at ...@. at ...@. at ...@.+... at .+.@.+.+. at .+.+.@.+.+...+. at .@..",
+". at ...@. at ...@. at ...@. at ...+.+.@.+. at ...@. at ...@. at ...@.. at .@.. at ...@.+.. at +.+.@.+.+. at .+.+.@.+.+...+.+ at +..",
+".#@@@#.#@++#.#@@@..#@@@#..+#+..#+++#.#+++#.#+++#... at ...#@@@#..+ at +...@#+...+#+...+#@...+++.......",
+". at ...+.@. at .@. at ...@.+... at .+.@.+. at ...@. at ...@. at .@. at ..@. at ..+...@.+ at ..+.+.@.+.+. at .+.+.@.+.+...+......",
+". at ...+.@..@@. at ...@.+... at .+.@.+. at ...@. at ...@.@@.@@. at ...@.+... at .@...+.+. at .+.+.@.+.+. at .+.+...+......",
+".#+++..#@@@#.#+++#.#@@@#..+#+..#@@@#..#@#..#+++#.#+++#.#@@@#.#@@@#..++ at ...+#+... at ++...+++.......",
+"................................................................................................"};
diff --git a/wmapp/xpm/charmap-small.xpm b/wmapp/xpm/charmap-small.xpm
new file mode 100644
index 0000000..13ff702
--- /dev/null
+++ b/wmapp/xpm/charmap-small.xpm
@@ -0,0 +1,62 @@
+/* XPM */
+static char * charmap_small_xpm[] = {
+"80 54 5 1",
+" 	c None",
+".	c #282828",
+"+	c #004941",
+"@	c #20B2AE",
+"#	c #188A86",
+"................................................................................",
+"..++...++...++...++...++...++...++...++... at +...+@...++.............++........++.",
+".+..+.+..+.+..+.+..+.+..+.+..+.+..+.+..+. at ..+.+..@.+..+.. at ........+..+......+.@+",
+".+..+.+..+.+..+.+..+.+..+.+..+.+..+.+..+. at ..+.+..@.+..+.. at ........+..+......+##+",
+"..++...++...++...++...++...++...++...++..#++...++#..++..@@@.......#@@........ at +.",
+".+..+.+..+.+..+.+..+.+..+.+..+.+..+.+..+. at ..+.+..@.+..+.. at ........+..+......##.+",
+".+..+.+..+.+..+.+..+.+..+.+..+.+..+.+..+. at ..+.+..@.+..+.. at .....@..+..+...... at ..+",
+"..++...++...++...++...++...++...++...++... at +...+@...++........##...++...#@...++.",
+"................................................................................",
+"................................................................................",
+"..@@...++#.#@@#.#@@#.#++#.#@@#.#@@#.#@@#.#@@#.#@@#............++...++...++...++.",
+". at ..@.+.. at .+..@.+.. at .@.. at .@..+. at ..+.+..@. at ..@. at ..@...........+..+.+..+.+..+.+..+",
+". at ..@.+.. at .+..@.+.. at .@.. at .@..+. at ..+.+..@. at ..@. at ..@..#@...#@..+..+.+..+.+..+.+..+",
+".#++#..++#.#@@#.#@@#.#@@#.@@@#.#@@#..++#.#@@#.#@@#............++...++...++...++.",
+". at ..@.+.. at .@..+.+.. at .+..@.+.. at .@.. at .+..@. at ..@.+.. at ...........+..+.+..+.+..+.+..+",
+". at ..@.+.. at .@..+.+.. at .+..@.+.. at .@.. at .+..@. at ..@.+.. at ..#@.... at ..+..+.+..+.+..+.+..+",
+"..@@...++ at .#@@#.#@@#..++#.#@@#.#@@#..++#.#@@#.#@@#.......##...++...++...++...++.",
+"................................................................................",
+"................................................................................",
+".+@@+.+@@+.#@@...@@#.#@@..#@@#.#@@#.#@@#.#++#.@@@...++#.#++#.#++.. at ..@.#@@..#@@#",
+". at ..@. at ..@. at ..@. at ..+.@.. at .@..+. at ..+.@..+. at ..@.+ at .+.+..@. at ..@. at ..+.@@@@. at ..@. at ..@",
+". at ..@. at ..@. at ..@. at ..+.@.. at .@..+. at ..+.@..+. at ..@.+ at .+.+..@. at .@.. at ..+.@##@. at ..@. at ..@",
+".#+@@.#@@#.#@@..#+++.#++#.#@@..#@@..#+@#.#@@#..#+...++#.#@...#++..#++#.#++#.#++#",
+". at .@#. at ..@. at ..@. at ..+.@.. at .@..+. at ..+.@.. at .@.. at .+@.+.+.. at .@. at ..@..+. at ..@. at ..@. at ..@",
+". at ..+.@.. at .@.. at .@..+. at ..@. at ..+.@..+. at ..@. at ..@.+ at .+.@.. at .@.. at .@..+. at ..@. at ..@. at ..@",
+".#@@..#++#.#@@...@@#.#@@..#@@#.#++..#@@#.#++#.@@@..#@@#.#++#.#@@#.#++#.#++#.#@@#",
+"................................................................................",
+"................................................................................",
+".#@@#.#@@#.#@@#.#@@#.@@@#.#++#.#++#.#++#.#++#.#++#.#@@#.@@+...++...+@@..++...++.",
+". at ..@. at ..@. at ..@. at ..+.+@.+. at ..@. at ..@. at ..@. at ..@. at ..@.+.. at .@..+. at ..+.+..@.+..+.+..+",
+". at ..@. at ..@. at ..@. at ..+.+@.+. at ..@. at ..@. at ..@. at ..@. at ..@.+. at +.@..+.##.+.+.. at .+..+.+..+",
+".#@@#.#++#.#@@..#@@#..#+..#++#.#++#.#++#..@@...@@#..##..#++... at +...++#..++...++.",
+". at ..+.@##@. at ..@.+.. at .+@.+. at ..@. at ..@.@##@. at ..@.+.. at .+@.+. at ..+.+##+.+.. at .+..+.+..+",
+". at ..+.@.@@. at ..@.+.. at .+@.+. at ..@. at ..@.@@@@. at ..@.+.. at .@..+. at ..+.+.@+.+.. at .+..+.+..+",
+".#++..#@@#.#++#.#@@#..#+..#@@#..#@.. at ..@.#++#.#@@#.#@@#.@@+...++...+@@..++..#@@#",
+"................................................................................",
+"................................................................................",
+"..++..+@@+.#@@...@@#.#@@..#@@#.#@@#.#@@#.#++#.@@@...++#.#++#.#++.. at ..@.#@@..#@@#",
+".+..+. at ..@. at ..@. at ..+.@.. at .@..+. at ..+.@..+. at ..@.+ at .+.+..@. at ..@. at ..+.@@@@. at ..@. at ..@",
+".+..+. at ..@. at ..@. at ..+.@.. at .@..+. at ..+.@..+. at ..@.+ at .+.+..@. at .@.. at ..+.@##@. at ..@. at ..@",
+"..++..#@@#.#@@..#+++.#++#.#@@..#@@..#+@#.#@@#..#+...++#.#@...#++..#++#.#++#.#++#",
+".+..+. at ..@. at ..@. at ..+.@.. at .@..+. at ..+.@.. at .@.. at .+@.+.+.. at .@. at ..@..+. at ..@. at ..@. at ..@",
+".+..+. at ..@. at ..@. at ..+.@.. at .@..+. at ..+.@.. at .@.. at .+@.+. at ..@. at ..@. at ..+.@.. at .@.. at .@..@",
+"..++..#++#.#@@...@@#.#@@..#@@#.#++..#@@#.#++#.@@@..#@@#.#++#.#@@#.#++#.#++#.#@@#",
+"................................................................................",
+"................................................................................",
+".#@@#.#@@#.#@@#.#@@#.@@@#.#++#.#++#.#++#.#++#.#++#.#@@#..#@...#+...@#...++..+ at +.",
+". at ..@. at ..@. at ..@. at ..+.+@.+. at ..@. at ..@. at ..@. at ..@. at ..@.+.. at .+@.+.+ at .+.+.@+.+..+. at .@.",
+". at ..@. at ..@. at ..@. at ..+.+@.+. at ..@. at ..@. at ..@. at ..@. at ..@.+. at +.+@.+.+ at .+.+.@+.+..+.+ at +.",
+".#@@#.#++#.#@@..#@@#..#+..#++#.#++#.#++#..@@...@@#..##..@#+...#+...+#@..++......",
+". at ..+.@##@. at ..@.+.. at .+@.+. at ..@. at ..@.@##@. at ..@.+.. at .+@.+.+ at .+.+@.+.+. at +.+..+.....",
+". at ..+.@.@@. at ..@.+.. at .+@.+. at ..@. at ..@.@@@@. at ..@.+.. at .@..+.+ at .+.+@.+.+. at +.+..+.....",
+".#++..#@@#.#++#.#@@#..#+..#@@#..#@.. at ..@.#++#.#@@#.#@@#..#@...#+...@#...++......",
+"................................................................................"};
diff --git a/wmapp/xpm/checkbox.xpm b/wmapp/xpm/checkbox.xpm
new file mode 100644
index 0000000..7b4b0e9
--- /dev/null
+++ b/wmapp/xpm/checkbox.xpm
@@ -0,0 +1,14 @@
+/* XPM */
+static char * checkbox_xpm[] = {
+"9 9 2 1",
+".	c #AEAAAE",
+"+	c #000000",
+".........",
+"......++.",
+".....+++.",
+".++.+++..",
+".+++++...",
+".++++....",
+".+++.....",
+".++......",
+"........."};
diff --git a/wmapp/xpm/emptybar.xpm b/wmapp/xpm/emptybar.xpm
new file mode 100644
index 0000000..e369631
--- /dev/null
+++ b/wmapp/xpm/emptybar.xpm
@@ -0,0 +1,62 @@
+/* XPM for empty bar - taken from wmtop's progress bar, dimmed with GIMP */
+static char * emptybar_xpm[] = {
+"58 1 58 1",
+" 	c None",
+".	c #007007",
+"+	c #026D07",
+"@	c #046C07",
+"#	c #066A07",
+"$	c #086706",
+"%	c #0A6506",
+"&	c #0C6406",
+"*	c #0E6206",
+"=	c #105F06",
+"-	c #115E06",
+";	c #145C06",
+">	c #165905",
+",	c #185705",
+"'	c #1A5605",
+")	c #1C5405",
+"!	c #1E5105",
+"~	c #1F5005",
+"{	c #224E05",
+"]	c #244C04",
+"^	c #264904",
+"/	c #284804",
+"(	c #2A4604",
+"_	c #2C4304",
+":	c #2D4204",
+"<	c #304004",
+"[	c #323E03",
+"}	c #343B03",
+"|	c #353A03",
+"1	c #383803",
+"2	c #3A3503",
+"3	c #3B3403",
+"4	c #3E3203",
+"5	c #403003",
+"6	c #422D03",
+"7	c #432C03",
+"8	c #462A03",
+"9	c #482803",
+"0	c #492603",
+"a	c #4C2403",
+"b	c #4E2202",
+"c	c #501F02",
+"d	c #511E02",
+"e	c #541C02",
+"f	c #561A02",
+"g	c #571802",
+"h	c #591602",
+"i	c #5C1401",
+"j	c #5E1101",
+"k	c #5F1001",
+"l	c #620E01",
+"m	c #640C01",
+"n	c #650A01",
+"o	c #670801",
+"p	c #6A0600",
+"q	c #6C0400",
+"r	c #6D0200",
+"s	c #700000",
+"..+@#$%&*=-;>,')!~{]^/(_:<[}|1234567890abcdefghijklmnopqrs"};
diff --git a/wmapp/xpm/fullbar.xpm b/wmapp/xpm/fullbar.xpm
new file mode 100644
index 0000000..f5c3986
--- /dev/null
+++ b/wmapp/xpm/fullbar.xpm
@@ -0,0 +1,62 @@
+/* XPM for full progress bar - taken from wmtop */
+static char * fullbar_xpm[] = {
+"58 1 58 1",
+" 	c None",
+".	c #00FF0F",
+"+	c #04FA0F",
+"@	c #09F50F",
+"#	c #0DF10F",
+"$	c #12EC0E",
+"%	c #16E80E",
+"&	c #1BE30E",
+"*	c #1FDF0D",
+"=	c #24DA0D",
+"-	c #28D60D",
+";	c #2DD10D",
+">	c #32CC0C",
+",	c #36C80C",
+"'	c #3BC30C",
+")	c #3FBF0B",
+"!	c #44BA0B",
+"~	c #48B60B",
+"{	c #4DB10B",
+"]	c #51AD0A",
+"^	c #56A80A",
+"/	c #5BA30A",
+"(	c #5F9F09",
+"_	c #649A09",
+":	c #689609",
+"<	c #6D9109",
+"[	c #718D08",
+"}	c #768808",
+"|	c #7A8408",
+"1	c #7F7F07",
+"2	c #847A07",
+"3	c #887607",
+"4	c #8D7107",
+"5	c #916D06",
+"6	c #966806",
+"7	c #9A6406",
+"8	c #9F5F05",
+"9	c #A35B05",
+"0	c #A85605",
+"a	c #AD5105",
+"b	c #B14D04",
+"c	c #B64804",
+"d	c #BA4404",
+"e	c #BF3F03",
+"f	c #C33B03",
+"g	c #C83603",
+"h	c #CC3203",
+"i	c #D12D02",
+"j	c #D62802",
+"k	c #DA2402",
+"l	c #DF1F01",
+"m	c #E31B01",
+"n	c #E81601",
+"o	c #EC1201",
+"p	c #F10D00",
+"q	c #F50900",
+"r	c #FA0400",
+"s	c #FF0000",
+"..+@#$%&*=-;>,')!~{]^/(_:<[}|1234567890abcdefghijklmnopqrs"};
diff --git a/wmapp/xpm/leds.xpm b/wmapp/xpm/leds.xpm
new file mode 100644
index 0000000..a9d1fa5
--- /dev/null
+++ b/wmapp/xpm/leds.xpm
@@ -0,0 +1,14 @@
+/* XPM for LED lights - taken from wmppp */
+static char * leds_xpm[] = {
+"16 4 7 1",
+" 	c None",
+".	c #202020",
+"+	c #283C38",
+"@	c #00EB00",
+"#	c #E7C308",
+"$	c #B60418",
+"%	c #F7F3FF",
+".++..@@..##..$$.",
+"++++@%@@#%##$%$$",
+"++++@@@@####$$$$",
+".++..@@..##..$$."};
diff --git a/wmapp/xpm/tile.xpm b/wmapp/xpm/tile.xpm
new file mode 100644
index 0000000..e65c234
--- /dev/null
+++ b/wmapp/xpm/tile.xpm
@@ -0,0 +1,121 @@
+/* XPM */
+static char *tile_xpm[] = {
+"64 64 54 1",
+" 	c #F3CEF3CEF3CE",
+".	c #000000000000",
+"X	c #514461856185",
+"o	c #A289A289B2CA",
+"O	c #A289A289A289",
+"+	c #A2899248B2CA",
+"@	c #9248A289A289",
+"#	c #A2899248A289",
+"$	c #92489248A289",
+"%	c #924892489248",
+"&	c #92488207A289",
+"*	c #820792489248",
+"=	c #924882079248",
+"-	c #820782079248",
+";	c #820782078207",
+":	c #820771C69248",
+">	c #618551446185",
+",	c #9248A289B2CA",
+"<	c #92489248B2CA",
+"1	c #82079248A289",
+"2	c #82078207A289",
+"3	c #71C682079248",
+"4	c #71C682078207",
+"5	c #514451446185",
+"6	c #514451445144",
+"7	c #820771C68207",
+"8	c #410351445144",
+"9	c #514441035144",
+"0	c #71C671C69248",
+"q	c #71C671C68207",
+"w	c #71C671C671C6",
+"e	c #410341035144",
+"r	c #71C661858207",
+"t	c #618571C68207",
+"y	c #410351444103",
+"u	c #410341034103",
+"i	c #618571C671C6",
+"p	c #410330C24103",
+"a	c #30C241034103",
+"s	c #71C6618571C6",
+"d	c #6185618571C6",
+"f	c #618561858207",
+"g	c #30C230C230C2",
+"h	c #618561856185",
+"j	c #30C230C24103",
+"k	c #5144618571C6",
+"l	c #30C2410330C2",
+"z	c #6185514471C6",
+"x	c #208130C230C2",
+"c	c #30C2208130C2",
+"v	c #5144514471C6",
+"b	c #2081208130C2",
+"n	c #208120812081",
+"m	c #410330C25144",
+"                                                               .",
+"                                                              X.",
+"  oOoO+O+O+O+@#$+@#$#$#$$$#$$%&%&%&%&*&*&*=-=*=-=-=--;---;:;:;>.",
+"  oo at o,o at o@o at +@+@<@$@$@$@$@$1$$$*$*$*&*&*2*&*2*-*-*-----3-3-4-X.",
+"  oO+OoO#O+@#@#@#$#@#$#%#$$%$%$%&%&*=%&*=*=*=-=-=--;-;-;:;:;:;5.",
+"  ,ooo at +@+ at +@+@<@#@<@$$$$$$$$$*$1$*&*&*&*&*2*---*-----3---4:4:6.",
+"  +O+O+O+@#$#@#$#$#$$%$$$%&%&%&%&*=*&*=-=*=---=--;---;:;:4:;:45.",
+"  @o at o@o at +@+@<@$@$@$$$@$1$1$*$*$*&*&*2*=*2*-*-*-----4-3-4:4-4:6.",
+"  +O#O+@#@#@#$#$#$#%#%$%&%$%&%&*=*&*=*=*=-=-=--;-;-;:;:;:;:4745.",
+"  @+ at +@+ at +@<@#@$@$$$$$$$$$*$*$*&*&*&*&*2*---*-----3---4:4:4:4:8.",
+"  #O+@#$#@#$#$#$$%$$$%&%&%&%&*=*&*=-=-=---=--;:;-;:;:4:4:474:49.",
+"  @o@<@+@<@$@$@$$$$$1$1$*$*$*&*&*2*=*2*-*-*-----4-4-4:4:4:4:408.",
+"  +@#@#@#$#$#$$%#%$%&%$%&%&*=*&*=*=*=-=-=--;-;-;:;:;:;:474747q9.",
+"  @+ at +@<@$$$@$$$$$1$$$*&*$*&*&*&*&*2*---------3-3-4:4:4:4:404q8.",
+"  #$#@#$#$#$$%$$$%&%&%&%&*=-&*=-=-=---=--;:;:;:;:4:4:474:47q7q9.",
+"  @#@<@$@$@$$$$$*$1$*$*$*&*&*2*-*2*-*-*-3---4-4-4:4:4:4:404q4q8.",
+"  #@#$#$#$$%$%$%&%$%&%&*=*=*=-=*=-=;=--;-;-;:;:47;:474747q7q7q9.",
+"  @<@$$$@$$$$$1$$$*&*&*&*&*&*=*2*---------4-3-4:4:4:4:404qq04q8.",
+"  #$#$#$$%$%$%&%&%&%&*=-&*=-=-=------;:;:;:;:4:4:47q747qqq7qqq9.",
+"  @$@$@$$$$$*$1$*$*$*&*&*2*-*-*---*-3-3-4-4-4:4:4:4:404q4q4qqq8.",
+"  #$#$$%$%$%&%&%&%&*=*=*=-=-=-=;=--;:;-;:;:474:474747q7q7qqwqw9.",
+"  $$@$$$$$*$$$*&*&*&*&*2*=*2*---------4-3-4:4:4:4:404qqq4qqqqqe.",
+"  #$$%$%$%&%&*&%&*=-&*=-=-=------;:;:;:;:4:4:47q7q7qqq7qqwrqqw9.",
+"  @$$$$$*$1$*&*$*2*&*2*-*-*-----3-3-4-4-4:4:404:404q4q4qqqqqtqy.",
+"  $%$%$%&%&%=%&*=*=*=-=-=--;=--;:;-;:;:474:474747q7q7qqwqwqwrwe.",
+"  $$$$*$1$*&*&*&*&*2*--2*-----3---4:3-4:4:4:4:404qqqqqqqqqtqtqu.",
+"  &%$%&%&*&*&*=-=*=-=-=--;---;:;:;:;:4:4:47q7q7qqq7qqwrqrwrwrip.",
+"  $$*$*$*&*&*2*&*2*-*-*-----3-3-4-4-4:4:404q404q4q4qtqqqiqtqiru.",
+"  $%&%&*=%&*=*=*=-=-=--;-;-;:;-;:;:474:47q747q7q7qqwqwqwrwrirwu.",
+"  *$1$*&*&*&*&*2*---*-----3---4:4:4:4:4:4:404qqqqqqqqqtqtqirira.",
+"  &%&*=*&*=-=*=-=-=--;---;:;:;:;:4:4:47q7q7qqqqqqwrqrwrwriririp.",
+"  *$*&*&*2*&*2*-*-*-----3-3-4-4-4:4:404q4q4qqq4qtqtqiqiqiriqira.",
+"  &*=*&*=*=*=-=-=--;-;-;:;:;:;:474:47q7q7q7q7qqwrwqwrwrirwrisip.",
+"  *&*&*&*&*2*---*-----3---4:4:4:4:404:404qqqqqqqqqtqtqiriririra.",
+"  =*&*=-=*=---=--;---;:;:4:;:474:47q7q7qqqqqqwrwrwrwriririsdrdp.",
+"  *&*2*=*2*-*-*-----4-3-4:4-4:4:404q4q4qqqqqtqtqiqiqiriqifirifa.",
+"  &*=*=*=-=-=--;-;-;:;:;:;:474747q7q7qqq7qqwrwqwrwrirwrisisisdp.",
+"  *&*&*2*---*-----3-3-4:4:4:4:404qq04qqqqqtqqqirtqiririririfida.",
+"  =-=-=---=--;:;-;:;:4:4:474:47q7q7qqqqqqwrwrwrwriririsdrdsdddp.",
+"  *=*2*-*-*-----4-4-4:4:4:4:404q4q4qqqqqtqtqiqiqiriqifififidida.",
+"  =*=-=-=--;-;-;:;:4:;:474747q7q7qqwqwqwrwqwrwrirwrisdsisdsdsdp.",
+"  *2*---------4-3-4:4:4:4:404qq04qqqqqtqqqiririririririfidddddg.",
+"  =---=--;:;:;:;:4:4:474:47q7q7qqqqqqwrwrwrwriririsdsdsddddddhj.",
+"  *---*-3---4-4-4:4:4:4:404q4q4qqqqqtqtqiqiqiririfififidddidkdl.",
+"  =;=--;:;-;:;:474:474747q7q7qqwqwqwrwrwrwrirwrisdsdsdsdsddhzhj.",
+"  --------4-3-4:4:4:4:404qq04qqqqqtqqqiririririfirifidddddddddx.",
+"  ---;:;:;:;:4:4:47q747qqq7qqwqqqwrwrirwriririsdsdsddddddhzhzhc.",
+"  --3-3-4-4-4:4:4:4:404q4q4qqqqqtqtqiriqiririfififidddddkdkdXdx.",
+"  -;:;-;:;:474:474747q7q7qqwqwqwrwrwrwrisisisdsdsdddsddhzhdhzhg.",
+"  ----4-3-4:4:4:4:404qqq4qqqqqtqtqiriririrififdfidddddkdddkzkdx.",
+"  :;:;:;:4:4:47q7q7qqq7qqwrqqwrwriririririsdsdsddddddhzhzhzhzXc.",
+"  3-4-4-4:4:404:404q4q4qqqqqtqtqiriqiririfidididddddkdkdXdXdXzx.",
+"  -;:;:474:47q747q7q7qqwqwqwrwrirwrisisisdsdsddddddhzhdhzhzXzhc.",
+"  4:4-4:4:4:4:404qqqqqqqqqtqtqiriririrififdfidddddkdddkzkdXzXzx.",
+"  :;:4:4:47q7q7qqq7qqwrqrwrwriririsirisdsdsddddddhzhzhzhzXzXzXc.",
+"  4-4:4:404q404qqq4qtqqqiqtqiriqiririfidididddddkdkdXdXdXzXzXvx.",
+"  :474:47q7q7q7q7qqwrwqwrwrirwrisisisdsdsddddddhzhzhzhzXzhzX>5c.",
+"  4:4:4:4:404qqqqqqqqqtqtqiririririfiddfidddddkdddXzkdXzXzXvXzx.",
+"  :4:47q7q7qqqqqqwrwrwrwriririsdrisdddsddddddhzhzXzhzXzXzX>5>5c.",
+"  4:404q4q4qqqqqtqtqiqiqiriqiririfidididddddkdkdXzXdXzXzXvXvXvx.",
+"  :47q7q7q7q7qqwrwqwrwrirwrisisisdsdsddhdddhzhzhzhzXzXzX>5>5>5b.",
+"  404:404qqqqqqqqqiqtqiririririfidddidddddkdkdXzkzXzXzXvXv5vX5n.",
+"  >65656569698989y9e9u9ueumueupupapaplpgjgjgjgcgcgcgcxcbcncnbnb.",
+" ..............................................................."};
diff --git a/wmapp/xpm/xbutton.xpm b/wmapp/xpm/xbutton.xpm
new file mode 100644
index 0000000..ba8e5e9
--- /dev/null
+++ b/wmapp/xpm/xbutton.xpm
@@ -0,0 +1,14 @@
+/* XPM */
+static char * xbutton_xpm[] = {
+"9 9 2 1",
+".	c #AEAAAE",
+"+	c #000000",
+".........",
+".++...++.",
+".+++.+++.",
+"..+++++..",
+"...+++...",
+"..+++++..",
+".+++.+++.",
+".++...++.",
+"........."};
diff --git a/wmapp/xwrapper.cc b/wmapp/xwrapper.cc
new file mode 100644
index 0000000..44000e2
--- /dev/null
+++ b/wmapp/xwrapper.cc
@@ -0,0 +1,329 @@
+#include <iostream>
+#include "xwrapper.h"
+#include "wmwidget.h"
+using std::cerr;
+using std::endl;
+
+// This class includes most of the crap normally required to do X stuff.
+
+Xwrapper::Xwrapper()
+{
+  xDisplay = X::XOpenDisplay(0);
+  if (!xDisplay) { cerr << "Xwrapper: Could not open X display!" << endl; }
+  xRootWindow = DefaultRootWindow(xDisplay);
+  X::XGetWindowAttributes(xDisplay, xRootWindow, &xAttributes);
+
+  X::XGCValues gcv;
+  gcv.graphics_exposures = false;
+  xGC = X::XCreateGC(xDisplay, xRootWindow,
+		     X_MACRO(GCGraphicsExposures), &gcv);
+}
+
+Xwrapper::~Xwrapper()
+{
+  //XXX: This is only the beginning...
+  X::XFreeGC(xDisplay, xGC);
+  X::XCloseDisplay(xDisplay);
+}
+
+void
+Xwrapper::set_GC(X::GC gc, Color c) const
+{
+  X::XSetForeground(xDisplay, gc, color_to_xcolor(c));
+  X::XSetFillStyle(xDisplay, gc, X_MACRO(FillSolid));
+}
+
+unsigned long
+Xwrapper::color_to_xcolor(Color c) const
+{
+  X::XColor xcolor;
+
+  xcolor.pixel = 0;
+  xcolor.flags = X_MACRO(DoRed | DoGreen | DoBlue);
+  // map the range 0 -> 0xff to the range 0 -> 0xffff
+  // (X insists on using "short" for color values)
+  xcolor.red =   c.r() * 0x0101;
+  xcolor.green = c.g() * 0x0101;
+  xcolor.blue =  c.b() * 0x0101;
+
+  if (X::XAllocColor(xDisplay, xAttributes.colormap, &xcolor))
+    X::XFreeColors(xDisplay, xAttributes.colormap, &xcolor.pixel, 1, 0);
+    //XXX: This is an incredibly stupid solution, but it works above 8-bit
+    //color. It appears that decent color management is a shortcoming of X.
+  return xcolor.pixel;
+}
+
+Color 
+Xwrapper::get_point(const WMPixmap& src, int x, int y) const
+{
+  //magic incantaions to read a pixel from a pixmap
+  X::XGCValues gcvalues;
+  X::XGetGCValues(xDisplay, src.gc, GCPlaneMask, &gcvalues);
+
+  // XXX: Surely there's a better way than allocating an image every time
+  X::XImage* dest = XGetImage(xDisplay, src.pixmap, 0, 0, src.attr.width, src.attr.height, gcvalues.plane_mask, XYPixmap);
+
+  Color color = XGetPixel(dest, x, y);
+  XDestroyImage(dest);
+  return color;
+}
+
+bool
+Xwrapper::create_pixmap(WMPixmap & dest, char * pixmap_bytes[]) const
+{
+  dest.attr.exactColors = false;
+  dest.attr.closeness = 40000;
+  dest.attr.valuemask = X_MACRO(XpmExactColors | XpmCloseness |
+				XpmReturnPixels | XpmReturnExtensions);
+  int error = X::XpmCreatePixmapFromData(xDisplay, xRootWindow, pixmap_bytes,
+		  			 &dest.pixmap, &dest.mask, &dest.attr);
+  if (error == X_MACRO(XpmSuccess)) {
+    X::XGCValues gcv;
+    gcv.clip_mask = dest.mask;
+    dest.gc = X::XCreateGC(xDisplay, dest.pixmap, X_MACRO(GCClipMask), &gcv);
+    return true;
+  }
+  else return false;
+}
+
+bool
+Xwrapper::create_pixmap(WMPixmap & dest, const WMPixmap & source) const
+{
+  create_pixmap(dest, source.attr.width, source.attr.height);
+  copy_rectangle(source, dest, 0, 0, source.attr.width, source.attr.height,
+		 0, 0);
+  return true;
+}
+
+bool
+Xwrapper::create_pixmap(WMPixmap & dest, const WMPixmap * source) const
+{ return source ? create_pixmap(dest, *source) : false; }
+
+bool
+Xwrapper::create_pixmap(WMPixmap & dest, int width, int height) const
+{
+  dest.attr.width = width;
+  dest.attr.height = height;
+  dest.pixmap = X::XCreatePixmap(xDisplay, xRootWindow, width, height,
+				 DefaultDepth(xDisplay,
+				 DefaultScreen(xDisplay)));
+  dest.mask = 0; //hope XCreateFoo never returns 0
+  X::XGCValues gcv;
+  dest.gc = X::XCreateGC(xDisplay, dest.pixmap, X_MACRO(None), &gcv);
+  return true;
+}
+
+bool
+Xwrapper::create_pixmap(WMPixmap & dest, int width, int height, int depth) const
+{
+  dest.attr.width = width;
+  dest.attr.height = height;
+  dest.pixmap = X::XCreatePixmap(xDisplay, xRootWindow, width, height, depth);
+  dest.mask = 0; //hope XCreateFoo never returns 0
+  X::XGCValues gcv;
+  dest.gc = X::XCreateGC(xDisplay, dest.pixmap, X_MACRO(None), &gcv);
+  return true;
+}
+
+void
+Xwrapper::free_pixmap(WMPixmap & dest) const
+{
+  X::XFreeGC(xDisplay, dest.gc);
+  X::XFreePixmap(xDisplay, dest.pixmap);
+  if (dest.mask) X::XFreePixmap(xDisplay, dest.mask);
+}
+
+void
+Xwrapper::draw_point(WMPixmap & dest, int x, int y, Color c) const
+{
+  set_GC(dest.gc, c);
+  X::XDrawPoint(xDisplay, dest.pixmap, dest.gc, x, y);
+}
+
+void
+Xwrapper::draw_line(WMPixmap & dest, int x1, int y1, int x2, int y2,
+		    Color c) const
+{
+  set_GC(dest.gc, c);
+  X::XDrawLine(xDisplay, dest.pixmap, dest.gc, x1, y1, x2, y2);
+}
+
+void
+Xwrapper::draw_arc(WMPixmap & dest, int x, int y, int width, int height,
+        int angle1, int angle2, Color c)
+{
+  set_GC(dest.gc, c);
+  X::XDrawArc(xDisplay, dest.pixmap, dest.gc, x, y, width, height, angle1,
+      angle2);
+}
+
+void
+Xwrapper::draw_lines(WMPixmap & dest, const X::XPoint* points, int npoints,
+        Color c) const
+{
+  set_GC(dest.gc, c);
+  X::XDrawLines(xDisplay, dest.pixmap, dest.gc, const_cast<X::XPoint*>(points),
+      npoints, X_MACRO(CoordModeOrigin));
+}
+
+void    
+Xwrapper::draw_horizontal_gradient(WMPixmap & dest, int x1, int y1, int x2,
+        int y2, Color c1, Color c2, double amount)
+{
+  if (!(x2 - x1) || !amount)
+    return; //gradient isn't wide enough, or none of it is to be drawn      
+  if (x1 > x2) //put x1 on left while keeping colors straight
+  {
+    int tempx = x2; x2 = x1; x1 = tempx;
+    Color tempc = c2; c2 = c1; c1 = tempc;
+  }
+
+  int glinesm1 = x2 - x1;
+  int glines = glinesm1 + 1; //number of lines in the full gradient
+  double dlines = glines * amount; //number of lines that we want to show
+  int tdlines = static_cast<int> (dlines); //number of lines truncated to int
+  double residue = dlines - tdlines; //amount left over from integer truncation
+  for (int x = 0; x < tdlines; x++)
+    draw_line(dest, x1 + x, y1, x1 + x, y2, Color::alpha_blend(c2, c1,
+          1.0 * x / glinesm1));
+  if (tdlines < glines) //correct undrawn line by using alpha blending
+  {
+    Color backcolor = get_point(dest, x1 + tdlines, y1);
+    Color forecolor = Color::alpha_blend(c2, c1, 1.0 * tdlines / glinesm1);
+    Color color = Color::alpha_blend(forecolor, backcolor, residue);
+    draw_line(dest, x1 + tdlines, y1, x1 + tdlines, y2, color);
+  }
+}
+
+void
+Xwrapper::draw_vertical_gradient(WMPixmap & dest, int x1, int y1, int x2,
+                                int y2, Color c1, Color c2, double amount)
+{
+  if (!(y2 - y1) || !amount)
+    return; //gradient isn't high enough, or none of it is to be drawn      
+  if (y1 > y2) //put y1 on left while keeping colors straight
+  {
+    int tempy = y2; y2 = y1; y1 = tempy;
+    Color tempc = c2; c2 = c1; c1 = tempc;
+  }
+
+  int glinesm1 = y2 - y1;
+  int glines = glinesm1 + 1; //number of lines in the full gradient
+  double dlines = glines * amount; //number of lines that we want to show
+  int tdlines = static_cast<int> (dlines); //number of lines truncated to int
+  double residue = dlines - tdlines; //amount left over from integer truncation
+  for (int y = 0; y < tdlines; y++)
+    draw_line(dest, x1, y1 + y, x2, y1 + y, Color::alpha_blend(c2, c1,
+          1.0 * y / glinesm1));
+  if (tdlines < glines) //correct undrawn line by using alpha blending
+  {
+    Color backcolor = get_point(dest, x1, y1 + tdlines);
+    Color forecolor = Color::alpha_blend(c2, c1, 1.0 * tdlines / glinesm1);
+    Color color = Color::alpha_blend(forecolor, backcolor, residue);
+    draw_line(dest, x1, y1 + tdlines, x2, y1 + tdlines, color);
+  }
+}
+
+void
+Xwrapper::draw_border(WMPixmap & dest, int x, int y, int width, int height,
+		      int thickness, Color topleft, Color botright,
+		      Color corner) const
+{
+  if (width / 2 < thickness || height / 2 < thickness) return;
+
+  fill_rectangle(dest, x, y, width, thickness, topleft);
+  fill_rectangle(dest, x, y, thickness, height, topleft);
+  fill_rectangle(dest, x, y + height - thickness, width, thickness, botright);
+  fill_rectangle(dest, x + width - thickness, y, thickness, height, botright);
+  fill_rectangle(dest, x, y + height - thickness, thickness, thickness, corner);
+  fill_rectangle(dest, x + width - thickness, y, thickness, thickness, corner);
+}
+
+void
+Xwrapper::draw_border(WMPixmap & dest, const WMRectangle & r, int thickness,
+		      Color topleft, Color botright, Color corner) const
+{
+  draw_border(dest, r.left(), r.top(), r.width(), r.height(), thickness,
+	      topleft, botright, corner);
+}
+
+void
+Xwrapper::fill_rectangle(WMPixmap & dest, int x, int y,
+			 int width, int height, Color c) const
+{
+  set_GC(dest.gc, c);
+  X::XFillRectangle(xDisplay, dest.pixmap, dest.gc, x, y, width, height);
+}
+
+void
+Xwrapper::fill_rectangle(WMPixmap & dest, const WMRectangle & r, Color c)
+const
+{ fill_rectangle(dest, r.left(), r.top(), r.width(), r.height(), c); }
+
+void
+Xwrapper::fill_arc(WMPixmap & dest, int x, int y, int width, int height,
+        int angle1, int angle2, Color c)
+{
+  set_GC(dest.gc, c);
+  X::XFillArc(xDisplay, dest.pixmap, dest.gc, x, y, width, height, angle1,
+      angle2);
+}
+
+void
+Xwrapper::fill_polygon(WMPixmap & dest, const X::XPoint* points, int npoints,
+        Color c, XShape shape) const
+{
+  set_GC(dest.gc, c);
+  X::XFillPolygon(xDisplay, dest.pixmap, dest.gc,
+      const_cast<X::XPoint*>(points), npoints, shape,
+      X_MACRO(CoordModeOrigin));
+}
+
+void
+Xwrapper::clear_rectangle(WMPixmap & dest, int x, int y,
+			  int width, int height) const
+{
+  X::XClearArea(xDisplay, dest.pixmap, x, y, width, height,
+		/* don't generate expose events */ false);
+}
+
+void
+Xwrapper::clear_rectangle(WMPixmap & dest, const WMRectangle & r) const
+{ clear_rectangle(dest, r.left(), r.top(), r.width(), r.height()); }
+
+void
+Xwrapper::copy_rectangle(const WMPixmap & source, WMPixmap & dest,
+			 int source_x, int source_y,
+			 int source_w, int source_h,
+			 int dest_x, int dest_y) const
+{
+  X::XCopyArea(xDisplay, source.pixmap, dest.pixmap, dest.gc, source_x,
+      source_y, source_w, source_h, dest_x, dest_y);
+}
+
+void
+Xwrapper::copy_rectangle(const WMPixmap & source, WMPixmap & dest,
+			 const WMRectangle & r, int dest_x, int dest_y) const
+{
+  copy_rectangle(source, dest, r.left(), r.top(), r.width(), r.height(),
+		 dest_x, dest_y);
+}
+
+void
+Xwrapper::copy_rectangle(const WMPixmap & source, X::Drawable & dest,
+			 int source_x, int source_y,
+			 int source_w, int source_h,
+			 int dest_x, int dest_y) const
+{
+  X::XCopyArea(xDisplay, source.pixmap, dest, xGC, source_x, source_y,
+               source_w, source_h, dest_x, dest_y);
+}
+
+void
+Xwrapper::copy_rectangle(const WMPixmap & source, X::Drawable & dest,
+			 const WMRectangle & r, int dest_x, int dest_y) const
+{
+  copy_rectangle(source, dest, r.left(), r.top(), r.width(), r.height(),
+		 dest_x, dest_y);
+}
+
diff --git a/wmapp/xwrapper.h b/wmapp/xwrapper.h
new file mode 100644
index 0000000..4f1b038
--- /dev/null
+++ b/wmapp/xwrapper.h
@@ -0,0 +1,140 @@
+#include "colors.h"
+
+#ifndef _MY_XWRAPPER_H
+#define _MY_XWRAPPER_H
+
+//These must be included here so that important types and functions aren't
+//dragged into the X namespace, but left undefined in the global namespace.
+extern "C" {
+#   include <stddef.h>
+#   include <stdlib.h>
+#   include <sys/types.h>
+#   include <malloc.h>
+}
+namespace X {
+  // Unfortunately, many common X calls are actually macros and the X::
+  // prefix must be avoided when using them.  Still, it is nice to use
+  // a separate namespace whenever possible.
+
+  // the next line ensures that X macros are expanded correctly into functions
+  // in the X namespace, since _XPrivDisplay appears to be the only
+  // real X object used by all X macros:
+# define _XPrivDisplay X::_XPrivDisplay
+
+  // this is just so I can easily see which identifiers are macros from Xlib
+  // that can't be prefixed by "X::"
+# define X_MACRO(x) (x)
+
+  extern "C" {
+#   include <X11/X.h>
+#   include <X11/Xlib.h>
+#   include <X11/xpm.h>
+#   include <X11/extensions/shape.h>
+  }
+};
+
+// forward declaration for rectangle
+struct WMRectangle;
+
+struct WMPixmap {
+  X::Pixmap pixmap;
+  X::Pixmap mask;
+  X::GC     gc;
+  X::XpmAttributes attr;
+};
+
+// global X thingies
+extern X::Window wActiveWin, wProgramWin;
+extern X::Atom deleteWin, _XA_GNUSTEP_WM_FUNC;
+
+class Xwrapper {
+ private:
+  X::Display *		xDisplay;
+  X::Window		xRootWindow;
+  X::XWindowAttributes	xAttributes;
+  mutable X::GC		xGC;
+
+  unsigned long color_to_xcolor(Color) const;
+  void		set_GC(X::GC, Color) const;
+  
+ public:
+  Xwrapper();
+  ~Xwrapper();
+
+  X::Display *		xdisplay() const;
+  const X::Window	xrootwin() const;
+  X::GC			get_GC() const;
+  
+  bool create_pixmap(WMPixmap & dest, char * pixmap_bytes[]) const;
+  bool create_pixmap(WMPixmap & dest, const WMPixmap & source) const;
+  bool create_pixmap(WMPixmap & dest, const WMPixmap * source) const;
+  bool create_pixmap(WMPixmap & dest, int width, int height) const;
+  bool create_pixmap(WMPixmap & dest, int width, int height, int depth) const;
+
+  void free_pixmap(WMPixmap & dest) const;
+
+  Color get_point(const WMPixmap & src, int x, int y) const;
+  
+  void draw_point(WMPixmap & dest, int x, int y, Color c) const;
+  void draw_line(WMPixmap & dest, int x1, int y1, int x2, int y2, Color c)
+	  const;
+  void draw_arc(WMPixmap & dest, int x, int y, int width, int height,
+      int angle1, int angle2, Color c); //angles are in units of degrees * 64
+  void draw_lines(WMPixmap & dest, const X::XPoint* points, int npoints,
+      Color c) const; //X::XPoint is simply a struct { short x, y };
+
+  // draws a color gradient from left to right or bottom to top from color1
+  // to color2. amount is the proportion of the gradient to draw i.e. 0.5
+  // draws half the gradient. It should always be at least 2 pixels wide.
+  void draw_horizontal_gradient(WMPixmap & dest, int x1, int y1, int x2, int y2, Color c1, Color c2, double amount = 1.0);
+  void draw_vertical_gradient(WMPixmap & dest, int x1, int y1, int x2, int y2, Color c1, Color c2, double amount = 1.0);
+  
+  void draw_border(WMPixmap & dest, int x, int y, int width, int height,
+		   int thickness, Color topleft, Color botright, Color corner)
+	  const;
+  void draw_border(WMPixmap & dest, const WMRectangle & posn, int thickness,
+		   Color topleft, Color botright, Color corner) const;
+  
+  void fill_rectangle(WMPixmap & dest, int x, int y, int width, int height,
+		      Color c) const;
+  void fill_rectangle(WMPixmap & dest, const WMRectangle & posn, Color c)
+	  const;
+
+  void fill_arc(WMPixmap & dest, int x, int y, int width, int height,
+      int angle1, int angle2, Color c); //angles are in units of degrees * 64
+
+  enum XShape { complex = X_MACRO(Complex), convex = X_MACRO(Convex),
+    nonconvex = X_MACRO(Nonconvex) };
+  void fill_polygon(WMPixmap & dest, const X::XPoint* points, int npoints,
+      Color c, XShape shape = complex) const;
+      //shape is simply a hint to the X server about what type of shape is
+      //being drawn. See XFillPolygon(3) for a complete description.
+  
+  void clear_rectangle(WMPixmap & dest, int x, int y, int width, int height)
+	  const;
+  void clear_rectangle(WMPixmap & dest, const WMRectangle & posn) const;
+  
+  void copy_rectangle(const WMPixmap & source, WMPixmap & dest,
+		      int source_x, int source_y, int source_w, int source_h,
+		      int dest_x = 0, int dest_y = 0) const;
+  void copy_rectangle(const WMPixmap & source, WMPixmap & dest,
+		      const WMRectangle & posn, int dest_x = 0, int dest_y = 0)
+	  	      const;
+  void copy_rectangle(const WMPixmap & source, X::Drawable & dest,
+		      int source_x, int source_y, int source_w, int source_h,
+		      int dest_x = 0, int dest_y = 0) const;
+  void copy_rectangle(const WMPixmap & source, X::Drawable & dest,
+		      const WMRectangle & posn, int dest_x = 0, int dest_y = 0)
+	  	      const;
+};
+
+inline X::Display *
+Xwrapper::xdisplay() const { return xDisplay; }
+
+inline const X::Window
+Xwrapper::xrootwin() const { return xRootWindow; }
+
+inline X::GC
+Xwrapper::get_GC() const { return xGC; }
+
+#endif
diff --git a/3dObjects/ball-solid.wmc b/wmc/ball.wmc
similarity index 77%
rename from 3dObjects/ball-solid.wmc
rename to wmc/ball.wmc
index fa6f2ff..79b795f 100644
--- a/3dObjects/ball-solid.wmc
+++ b/wmc/ball.wmc
@@ -1,3 +1,5 @@
+# By wmCube author Robert Kling
+
 WMCUBE_COORDINATES
 1  -100 -100  100
 2   100 -100  100
@@ -31,6 +33,57 @@ WMCUBE_COORDINATES
 30   50  -50 -150
 31   50   50 -150
 32  -50   50 -150
+
+WMCUBE_LINES
+9 10
+10 6
+6 11
+11 12
+12 7
+7 13
+13 14
+14 8
+8 15
+15 16
+16 5
+5 9
+17 1
+1 18
+18 19
+19 2
+2 20
+20 21
+21 3
+3 22
+22 23
+23 4
+4 24
+24 17
+9 18
+10 19
+11 20
+12 21
+13 22
+14 23
+15 24
+16 17
+25 26
+26 27
+27 28
+28 25
+25 1
+26 2
+27 3
+28 4
+29 30
+30 31
+31 32
+32 29
+5 29
+6 30
+7 31
+8 32
+
 WMCUBE_PLANES
 1 18 19
 1 19 2
diff --git a/wmc/cossin.wmc b/wmc/cossin.wmc
new file mode 100755
index 0000000..93dd0a1
--- /dev/null
+++ b/wmc/cossin.wmc
@@ -0,0 +1,362 @@
+WMCUBE_COORDINATES
+1 100 0 0
+2 54.030230586814 84.1470984807897 45.4648713412841
+3 -41.6146836547142 90.9297426825682 -37.8401247653964
+4 -98.9992496600445 14.1120008059867 -13.9707749099463
+5 -65.3643620863612 -75.6802495307928 49.4679123311691
+6 28.3662185463226 -95.8924274663138 -27.2010555444685
+7 96.0170286650366 -27.9415498198926 -26.8286459000217
+8 75.3902254343305 65.6986598718789 49.5303677847435
+9 -14.5500033808614 98.9358246623382 -14.3951658332533
+10 -91.1130261884677 41.2118485241757 -37.5493623385838
+11 -83.9071529076452 -54.402111088937 45.6472625363814
+12 0.442569798805079 -99.9990206550704 -0.442565464520194
+13 84.3853958732492 -53.6572918000435 -45.2789181003312
+14 90.7446781450196 42.0167036826641 38.1279225239801
+15 13.6737218207834 99.060735569487 13.5452894153935
+16 -75.9687912858821 65.0287840157117 -49.4015812046431
+17 -95.7659480323385 -28.7903316665065 27.5713340620845
+18 -27.5163338051597 -96.1397491879557 26.4541343060012
+19 66.031670824408 -75.0987246771676 -49.5889426721558
+20 98.8704618186669 14.9877209662952 14.8184289354693
+21 40.8082061813392 91.2945250727628 37.2556580239674
+22 -54.7729260224268 83.6655638536056 -45.8260773957817
+23 -99.9960826394637 -0.885130929040388 0.885096255270679
+24 -53.2833020333398 -84.6220404175171 45.0894173824405
+25 42.4179007336997 -90.5578362006624 -38.4127330661833
+26 99.1202811863474 -13.2351750097773 -13.1187426851964
+27 64.691932232864 76.2558450479603 49.3313796020243
+28 -29.2138808733836 95.6375928404503 -27.9394524425808
+29 -96.2605866313567 27.0905788307869 -26.0775501043456
+30 -74.8057529689 -66.3633884212967 49.6436324042268
+31 15.4251449887584 -98.8031624092862 -15.2405310551108
+32 91.4742357804531 -40.4037645323065 -36.9590348324611
+33 83.422336050651 55.1426681241691 46.0013019098395
+34 -1.32767472230595 99.9911860107267 -1.32755770119834
+35 -84.8570274784605 52.9082686120024 -44.8963840344646
+36 -90.3692205091507 -42.8182669496151 38.6945340778945
+37 -12.7963689627405 -99.1778853443116 12.6911681381018
+38 76.5414051945343 -64.3538133357 -49.2573130234124
+39 95.5073644047295 29.6368578709385 28.305381844909
+40 26.6642932359937 96.3795386284088 25.6989227993768
+41 -66.6938061652262 74.5113160479349 -49.6944326961688
+42 -98.7339277523826 -15.8622668804709 15.6614391216543
+43 -39.9985314988351 -91.6521547915634 36.6595160036646
+44 55.5113301520626 -83.1774742628598 -46.172922350203
+45 99.9843308647691 1.77019251054136 1.76991513668303
+46 52.532198881773 85.0903524534118 44.6998331800279
+47 -43.2177944884778 90.1788347648809 -38.9733034807902
+48 -99.2335469150929 12.3573122745224 -12.2625992733827
+49 -64.01443394692 -76.8254661323667 49.1793872717172
+50 30.0592543743637 -95.3752652759472 -28.6690935995211
+51 96.4966028492113 -26.2374853703929 -25.3182820554879
+52 74.2154196813783 67.0229175843375 49.7413395679203
+53 -16.2990780795705 98.6627592040485 -16.0811201581265
+54 -91.8282786212119 39.5925150181834 -36.3571250040426
+55 -82.930983286315 -55.8789048851616 46.3409252708893
+56 2.21267562619557 -99.975517335862 -2.21213390425355
+57 85.3220107722584 -52.1551002086912 -44.4997802183417
+58 89.9866826969194 43.6164755247825 39.2490194340655
+59 11.9180135448819 99.2872648084537 11.8330696682143
+60 -77.1080222975845 63.6738007139138 -49.0976084522042
+61 -95.2412980415156 -30.4810621102217 29.0305592106157
+62 -25.8101635938267 -96.6117770008393 24.9356576948197
+63 67.3507162323586 -73.9180696649223 -49.784349344459
+64 98.589658158255 16.7355700302807 16.4995412836891
+65 39.185723042955 92.0026038196791 36.0518855250866
+66 -56.2453851238172 82.6828679490103 -46.5052975093381
+67 -99.964745596635 -2.65511540239668 2.65417935730291
+68 -51.7769799789505 -85.5519978975322 44.2962408229974
+69 44.0143022496041 -89.7927680689291 -39.5216603361444
+70 99.3390379722272 -11.4784813783187 -11.4026129750431
+71 63.33192030863 77.3890681557889 49.0119829720156
+72 -30.9022728166071 95.1054653254375 -29.3897503583703
+73 -96.7250588273882 25.3823362762036 -24.5510796949235
+74 -73.6192718227316 -67.6771956887308 49.8234586560887
+75 17.1717341830778 -98.5146260468247 -16.9166697162138
+76 92.1751269724749 -38.778163540943 -35.7438214814582
+77 82.4331331107558 56.610763689818 46.6660261874431
+78 -3.09750317312165 99.9520158580731 -3.09601686280287
+79 -85.7803093244988 51.3978455987535 -44.089230940739
+80 -89.5970946790963 -44.4112668707508 39.7912048263728
+81 -11.0387243839048 -99.3888653923375 10.9712629189502
+82 77.6685982021631 -62.9887994274454 -48.922517539669
+83 94.9677697882543 31.3228782433085 29.7466389011604
+84 24.9540117973338 96.8364461100185 24.1645781864128
+85 -68.0023495587339 73.3190320073292 -49.858664438704
+86 -98.4376643394042 -17.6075619948587 17.3324727748515
+87 -38.3698444949742 -92.345844700406 35.4329570091161
+88 56.9750334265312 -82.1817836630823 -46.8230987125607
+89 99.9373283695125 3.53983027336607 3.53761180401726
+90 51.0177044941669 86.0069405812453 43.8787667902134
+91 -44.807361612917 89.3996663600558 -40.0576317866915
+92 -99.4367460928201 10.5987511751157 -10.5390532950096
+93 -62.6444447910339 -77.9466069615805 48.8292191645315
+94 31.7428701519702 -94.8282141269947 -30.1011968777642
+95 96.9459366669988 -24.5251985467654 -23.7761834506029
+96 73.017356099482 68.3261714736121 49.88996393403
+97 -18.0430449291084 98.3587745434345 -17.7469178825923
+98 -92.5147536596414 37.9607739027522 -35.1193164634246
+99 -81.9288245291459 -57.3381871990423 46.9765027784966
+100 3.98208803931389 -99.9206834186354 -3.97892958321418
+101 86.2318872287684 -50.6365641109759 -43.6648648606997
+102 89.200486978816 45.2025787178351 40.3209203432915
+103 10.1585703696621 99.4826791358406 10.1060179656396
+104 -78.2230889887116 62.2988631442349 -48.7320951562705
+105 -94.6868010751213 -32.1622403162531 30.453396509553
+106 -24.0959049236201 -97.0535283537485 23.3859259171379
+107 68.6486550906984 -72.7142500080853 -49.9173546898386
+108 98.2779582041221 18.4781744560667 18.159972568818
+109 37.5509597767012 92.6818505417785 34.8029244172456
+110 -57.7002178942952 81.6742606636317 -47.1262263664701
+111 -99.9020813314648 -4.4242678085071 4.41993562437658
+112 -50.2544319145385 -86.4551448610608 43.4475419108175
+113 45.5969104444276 -88.9995604366833 -40.5810498682487
+114 99.5266636217131 -9.7181905893209 -9.67219085795039
+115 61.952061255921 78.498038868131 48.6311531242812
+116 -32.5809805219964 94.543533402477 -30.8032102026682
+117 -97.1592190628802 23.6661393364286 -22.9938361616071
+118 -72.4097196700474 -68.9697940935389 49.9408345601404
+119 18.9129420528958 -98.1952169044084 -18.5716044718461
+120 92.8471320739076 -37.140410143809 -34.4838056590133
+121 81.4180970526562 58.0611184212314 47.2722577460558
+122 -4.86636092001539 99.881522472358 -4.86059537591122
+123 -86.676709105198 49.8713153896394 -43.2268149672136
+124 -88.7968906691855 -45.9903490689591 40.8379999811404
+125 -9.27762045976609 -99.5686986889179 9.2376059610859
+126 78.7714512144235 -61.6040459188656 -48.5264009770903
+127 94.3984139152314 32.9990825673782 31.1506105501826
+128 23.2359102029658 97.2630067242408 22.5999449031492
+129 -69.2895821920165 72.1037710501732 -49.9604017053531
+130 -98.1105522649388 -19.3473392038468 18.9817813414652
+131 -36.7291330454696 -93.0105950186762 34.1619851907925
+132 58.4208817109289 -81.16033871367 -47.4145854761024
+133 99.8590072439991 5.30835871460582 5.30087431335569
+134 49.487222040343 86.8965756214236 43.0027013232285
+135 -46.3828868851872 88.5924816459948 -41.091750550642
+136 -99.6087835141185 8.83686861040014 -8.80229732356057
+137 -61.25482394961 -79.0433206722889 48.4178469217362
+138 33.4165382630761 -94.2514454558251 -31.4955703342481
+139 97.3648893049518 -22.8052259500861 -22.2042830020455
+140 71.7964101410472 69.6080131224741 49.9760545924455
+141 -19.7813574004268 98.0239659440312 -19.3904710414615
+142 -93.172236174352 36.3171365373259 -33.8374882263192
+143 -80.9009906953598 -58.7795007167406 47.5531984056293
+144 5.75025253491242 -99.8345360873918 -5.7407379420833
+145 87.1147401032343 -49.1021593898469 -42.775218537541
+146 88.38633737085 46.7745162045133 41.3422816961041
+147 8.39594367418485 99.6469173121774 8.36629905059196
+148 -79.3136419166478 60.9044021883292 -48.3054994631265
+149 -94.1026309029144 -33.8333394324276 31.8380625282276
+150 -22.3740950135584 -97.4648648094495 21.8068814573024
+151 69.9250806478375 -71.4876429629165 -49.9877919950575
+152 97.9354596376429 20.2149881415654 19.797641552137
+153 35.9044286891116 93.3320523748862 33.5103401890253
+154 -59.1369684144325 80.6400580775486 -47.6880856746999
+155 -99.80810948185 -6.19203372560573 6.18015180000565
+156 -48.7161349803341 -87.3311982774648 42.544384432793
+157 47.1652293561339 -88.1784618814781 -41.5895737891102
+158 99.6830993361718 -7.95485428747221 -7.92964530142864
+159 60.552787498699 79.5824096527455 48.1893674033711
+160 -34.2494779115907 93.9519731713148 -32.1780602988131
+161 -97.5629312795237 21.9425258379005 -21.4077714042226
+162 -71.1774755635724 -70.2407785577371 49.9956129935963
+163 20.6482229337811 -97.845035079338 -20.203260972818
+164 93.490040489975 -35.4910175844935 -33.1805667100472
+165 80.3775459710974 59.4932778023209 47.8192367152731
+166 -6.63369363356237 99.7797279449891 -6.6190814602726
+167 -87.5459459043705 48.3291563728257 -42.3102170941926
+168 -87.9688592495152 -47.5550186871899 41.8336074550147
+169 -7.51360908983532 -99.717328877408 7.49237028667391
+170 79.8496186162556 -60.1999867677605 -48.069459841093
+171 93.7994752119442 34.664945549703 32.5155370081276
+172 21.5105268762141 97.6590867943566 21.0069841119653
+173 -70.55510066863 70.8659140182323 -49.9995169753086
+174 -97.7526940402531 -21.0810532913481 20.6072975243543
+175 -35.0769113209131 -93.6461974251213 32.848193626217
+176 59.84842190141 -80.1134595178041 -47.9466412520307
+177 99.7493920327152 7.07522360803452 7.05749253396957
+178 47.9412311470322 87.7589787777116 42.0727348680976
+179 -47.9438765629173 87.7575335804269 -42.0743635744605
+180 -99.7496052654355 7.07221672389912 -7.05450826560549
+181 -59.8460069057858 -80.115263573383 47.9457861707153
+
+WMCUBE_PLANES
+1 2 3
+2 3 4
+3 4 5
+4 5 6
+5 6 7
+6 7 8
+7 8 9
+8 9 10
+9 10 11
+10 11 12
+11 12 13
+12 13 14
+13 14 15
+14 15 16
+15 16 17
+16 17 18
+17 18 19
+18 19 20
+19 20 21
+20 21 22
+21 22 23
+22 23 24
+23 24 25
+24 25 26
+25 26 27
+26 27 28
+27 28 29
+28 29 30
+29 30 31
+30 31 32
+31 32 33
+32 33 34
+33 34 35
+34 35 36
+35 36 37
+36 37 38
+37 38 39
+38 39 40
+39 40 41
+40 41 42
+41 42 43
+42 43 44
+43 44 45
+44 45 46
+45 46 47
+46 47 48
+47 48 49
+48 49 50
+49 50 51
+50 51 52
+51 52 53
+52 53 54
+53 54 55
+54 55 56
+55 56 57
+56 57 58
+57 58 59
+58 59 60
+59 60 61
+60 61 62
+61 62 63
+62 63 64
+63 64 65
+64 65 66
+65 66 67
+66 67 68
+67 68 69
+68 69 70
+69 70 71
+70 71 72
+71 72 73
+72 73 74
+73 74 75
+74 75 76
+75 76 77
+76 77 78
+77 78 79
+78 79 80
+79 80 81
+80 81 82
+81 82 83
+82 83 84
+83 84 85
+84 85 86
+85 86 87
+86 87 88
+87 88 89
+88 89 90
+89 90 91
+90 91 92
+91 92 93
+92 93 94
+93 94 95
+94 95 96
+95 96 97
+96 97 98
+97 98 99
+98 99 100
+99 100 101
+100 101 102
+101 102 103
+102 103 104
+103 104 105
+104 105 106
+105 106 107
+106 107 108
+107 108 109
+108 109 110
+109 110 111
+110 111 112
+111 112 113
+112 113 114
+113 114 115
+114 115 116
+115 116 117
+116 117 118
+117 118 119
+118 119 120
+119 120 121
+120 121 122
+121 122 123
+122 123 124
+123 124 125
+124 125 126
+125 126 127
+126 127 128
+127 128 129
+128 129 130
+129 130 131
+130 131 132
+131 132 133
+132 133 134
+133 134 135
+134 135 136
+135 136 137
+136 137 138
+137 138 139
+138 139 140
+139 140 141
+140 141 142
+141 142 143
+142 143 144
+143 144 145
+144 145 146
+145 146 147
+146 147 148
+147 148 149
+148 149 150
+149 150 151
+150 151 152
+151 152 153
+152 153 154
+153 154 155
+154 155 156
+155 156 157
+156 157 158
+157 158 159
+158 159 160
+159 160 161
+160 161 162
+161 162 163
+162 163 164
+163 164 165
+164 165 166
+165 166 167
+166 167 168
+167 168 169
+168 169 170
+169 170 171
+170 171 172
+171 172 173
+172 173 174
+173 174 175
+174 175 176
+175 176 177
+176 177 178
+177 178 179
+178 179 180
diff --git a/wmc/coussin.bande.diag.wmc b/wmc/coussin.bande.diag.wmc
new file mode 100755
index 0000000..7287b32
--- /dev/null
+++ b/wmc/coussin.bande.diag.wmc
@@ -0,0 +1,124 @@
+WMCUBE_COORDINATES
+1 -3 -3 -0.989992496600445
+2 -3 -2 -0.923561053656561
+3 -3 -1 -0.875844530679003
+4 -3 0 -0.858525596664594
+5 -3 1 -0.875844530679003
+6 -3 2 -0.923561053656561
+7 -3 3 -0.989992496600445
+8 -2 -3 -0.923561053656561
+9 -2 -2 -0.416146836547142
+10 -2 -1 -0.0516802364419242
+11 -2 0 0.0806046117362795
+12 -2 1 -0.0516802364419242
+13 -2 2 -0.416146836547142
+14 -2 3 -0.923561053656561
+15 -1 -3 -0.875844530679003
+16 -1 -2 -0.0516802364419242
+17 -1 -1 0.54030230586814
+18 -1 0 0.755165123780746
+19 -1 1 0.54030230586814
+20 -1 2 -0.0516802364419242
+21 -1 3 -0.875844530679003
+22 0 -3 -0.858525596664594
+23 0 -2 0.0806046117362795
+24 0 -1 0.755165123780746
+25 0 0 1
+26 0 1 0.755165123780746
+27 0 2 0.0806046117362795
+28 0 3 -0.858525596664594
+29 1 -3 -0.875844530679003
+30 1 -2 -0.0516802364419242
+31 1 -1 0.54030230586814
+32 1 0 0.755165123780746
+33 1 1 0.54030230586814
+34 1 2 -0.0516802364419242
+35 1 3 -0.875844530679003
+36 2 -3 -0.923561053656561
+37 2 -2 -0.416146836547142
+38 2 -1 -0.0516802364419242
+39 2 0 0.0806046117362795
+40 2 1 -0.0516802364419242
+41 2 2 -0.416146836547142
+42 2 3 -0.923561053656561
+43 3 -3 -0.989992496600445
+44 3 -2 -0.923561053656561
+45 3 -1 -0.875844530679003
+46 3 0 -0.858525596664594
+47 3 1 -0.875844530679003
+48 3 2 -0.923561053656561
+49 3 3 -0.989992496600445
+
+WMCUBE_PLANES
+1 8 2
+8 2 9
+2 3 9
+9 10 3
+3 10 4
+10 4 11
+4 5 11
+11 12 5
+5 12 6
+12 6 13
+6 7 13
+13 14 7
+8 9 15
+15 16 9
+9 16 10
+16 10 17
+10 11 17
+17 18 11
+11 18 12
+18 12 19
+12 13 19
+19 20 13
+13 20 14
+20 14 21
+15 22 16
+22 16 23
+16 17 23
+23 24 17
+17 24 18
+24 18 25
+18 19 25
+25 26 19
+19 26 20
+26 20 27
+20 21 27
+27 28 21
+22 23 29
+29 30 23
+23 30 24
+30 24 31
+24 25 31
+31 32 25
+25 32 26
+32 26 33
+26 27 33
+33 34 27
+27 34 28
+34 28 35
+29 36 30
+36 30 37
+30 31 37
+37 38 31
+31 38 32
+38 32 39
+32 33 39
+39 40 33
+33 40 34
+40 34 41
+34 35 41
+41 42 35
+36 37 43
+43 44 37
+37 44 38
+44 38 45
+38 39 45
+45 46 39
+39 46 40
+46 40 47
+40 41 47
+47 48 41
+41 48 42
+48 42 49
diff --git a/3dObjects/cross2-solid.wmc b/wmc/cross2-solid.wmc
similarity index 100%
rename from 3dObjects/cross2-solid.wmc
rename to wmc/cross2-solid.wmc
diff --git a/3dObjects/cross3-solid.wmc b/wmc/cross3-solid.wmc
similarity index 100%
rename from 3dObjects/cross3-solid.wmc
rename to wmc/cross3-solid.wmc
diff --git a/3dObjects/cube-solid.wmc b/wmc/cube.wmc
similarity index 72%
rename from 3dObjects/cube-solid.wmc
rename to wmc/cube.wmc
index 31d6a7b..58219d0 100644
--- a/3dObjects/cube-solid.wmc
+++ b/wmc/cube.wmc
@@ -1,3 +1,5 @@
+# By wmCube author Robert Kling
+
 WMCUBE_COORDINATES
 1  -180 -180  180
 2   180 -180  180
@@ -8,6 +10,20 @@ WMCUBE_COORDINATES
 7   180  180 -180
 8  -180  180 -180
 
+WMCUBE_LINES
+1 2 
+2 3 
+3 4
+4 1
+5 6
+6 7
+7 8
+8 5
+1 5
+2 6
+3 7
+4 8
+
 WMCUBE_PLANES
 1 2 3
 1 3 4
diff --git a/wmc/diamond.wmc b/wmc/diamond.wmc
new file mode 100644
index 0000000..9821455
--- /dev/null
+++ b/wmc/diamond.wmc
@@ -0,0 +1,107 @@
+# This object is somewhat broken
+# Originally by Nicolas Mieville <nm at altern.org>
+
+WMCUBE_COORDINATES
+
+1  -50  0   0
+2  -35  0  35
+3    0  0  50
+4   35  0  35
+5   50  0   0
+6   35  0 -35
+7    0  0 -50
+8  -35  0 -35
+9  -32  17  13
+10 -13  17  32
+11  13  17  32
+12  32  17  13
+13  32  17 -13
+14  13  17 -32
+15 -13  17 -32
+16 -32  17 -13
+17  0  -60  0
+18   0   17  0
+
+WMCUBE_LINES
+
+1 2
+2 3
+3 4
+4 5
+5 6
+6 7
+7 8
+8 1
+
+9 10
+10 11
+11 12
+12 13
+13 14
+14 15
+15 16
+16 9
+
+1 9
+1 8
+2 10
+2 9
+3 11
+3 10
+4 12
+4 11
+5 13
+5 12
+6 14
+6 13
+7 15
+7 14
+8 16
+8 15
+
+17 1
+17 2
+17 3
+17 4
+17 5
+17 6
+17 7
+17 8
+
+WMCUBE_PLANES
+
+17 1 2
+17 2 3
+17 3 4
+17 4 5
+17 5 6
+17 6 7
+17 7 8
+17 8 1
+
+2 1 9
+2 9 10
+3 2 10
+3 10 11
+4 3 11
+4 11 12
+5 4 12
+5 12 13
+6 5 13
+6 13 14
+7 6 14
+7 14 15
+8 7 15
+8 15 16
+9 8 16
+9 1 16
+1 8 16
+
+9 18 10
+10 18 11
+11 18 12
+12 18 13
+13 18 14
+14 18 15
+15 18 16
+16 18 9
diff --git a/3dObjects/dice-solid.wmc b/wmc/dice.wmc
similarity index 78%
rename from 3dObjects/dice-solid.wmc
rename to wmc/dice.wmc
index cd561df..2de7139 100644
--- a/3dObjects/dice-solid.wmc
+++ b/wmc/dice.wmc
@@ -1,3 +1,5 @@
+# By Robert Kling
+
 WMCUBE_COORDINATES
 1   -70 -120  120
 2    70 -120  120
@@ -26,6 +28,49 @@ WMCUBE_COORDINATES
 23  120  120 -70
 24 -120  120 -70
 
+WMCUBE_LINES
+
+1 2
+2 3
+3 4
+4 5
+5 6
+6 7
+7 8
+8 1
+
+9 10
+10 11
+11 12
+12 13
+13 14
+14 15
+15 16
+16 9
+
+1 17
+2 18
+3 18
+4 19
+5 19
+6 20
+7 20
+8 17
+
+9 21
+10 22
+11 22
+12 23
+13 23
+14 24
+15 24
+16 21
+
+17 21
+18 22
+19 23
+20 24
+
 WMCUBE_PLANES
 
 17 1 8
diff --git a/wmc/hyp_par.wmc b/wmc/hyp_par.wmc
new file mode 100644
index 0000000..1119522
--- /dev/null
+++ b/wmc/hyp_par.wmc
@@ -0,0 +1,70 @@
+WMCUBE_COORDINATES
+1 50 50 50
+2 -50 50 50
+3 -50 -50 50
+4 50 -50 50
+5 50 50 -50
+6 -50 50 -50
+7 -50 -50 -50
+8 50 -50 -50
+9 50 40 40
+10 -50 -40 40
+11 50 30 30
+12 -50 -30 30
+13 50 20 20
+14 -50 -20 20
+15 50 10 10
+16 -50 -10 10
+17 50 0 0
+18 -50 0 0
+19 50 -10 -10
+20 -50 10 -10
+21 50 -20 -20
+22 -50 20 -20
+23 50 -30 -30
+24 -50 30 -30
+25 50 -40 -40
+26 -50 40 -40
+27 -40 -40 50
+28 -40 40 -50
+29 -30 -30 50
+30 -30 30 -50
+31 -20 -20 50
+32 -20 20 -50
+
+33 -10 -10 50
+34 -10 10 -50
+35 0 0 50
+36 0 0 -50
+37 10 10 50
+38 10 -10 -50
+39 20 20 50
+40 20 -20 -50
+41 30 30 50
+42 30 -30 -50
+43 40 40 50
+44 40 -40 -50
+
+WMCUBE_LINES
+9 10
+11 12
+13 14
+15 16
+17 18
+19 20
+21 22
+23 24
+25 26
+27 28
+29 30
+31 32
+33 34
+35 36
+37 38
+39 40
+41 42
+43 44
+1 8
+8 6
+6 3
+3 1
diff --git a/wmc/judaspriest.wmc b/wmc/judaspriest.wmc
new file mode 100644
index 0000000..75f79db
--- /dev/null
+++ b/wmc/judaspriest.wmc
@@ -0,0 +1,239 @@
+WMCUBE_COORDINATES
+1     -66    100  35
+2     -27    17   35
+3     -106   17   35
+4     -130   55   35
+5     -162   21   35
+6     -117  -62   35
+7     -68   -108  35
+8     -7    -108  35
+9     -28   -60   35
+10    -64   -60   35
+11    -90   -24   35
+12    -8    -24   35
+13    37  -118    35
+14    83  -118    35
+15    37  -24     35
+16    120 -24     35
+17    114 -68     35
+18    101 -68     35
+19    122 -115    35
+20    146 -115    35
+21    164 -44     35
+22    132 27      35
+23    84  52      35
+24    101 17      35
+25    18  17      35
+26    -11   74    35
+
+27    -66    100  -35
+28    -27    17   -35
+29    -106   17   -35
+30    -130   55   -35
+31    -162   21   -35
+32    -117  -62   -35
+33    -68   -108  -35
+34    -7    -108  -35
+35    -28   -60   -35
+36    -64   -60   -35
+37    -90   -24   -35
+38    -8    -24   -35
+39    37  -118    -35
+40    83  -118    -35
+41    37  -24     -35
+42    120 -24     -35
+43    114 -68     -35
+44    101 -68     -35
+45    122 -115    -35
+46    146 -115    -35
+47    164 -44     -35
+48    132 27      -35
+49    84  52      -35
+50    101 17      -35
+51    18  17      -35
+52    -11   74    -35
+
+
+WMCUBE_LINES
+1 2
+2 3
+3 4
+4 5
+5 6
+6 7
+7 8
+8 9
+9 10
+10 11
+11 12
+12 13
+13 14
+14 15
+15 16
+16 17
+17 18
+18 19
+19 20
+20 21
+21 22
+22 23
+23 24
+24 25
+25 26
+26 1
+
+27 28
+28 29
+29 30
+30 31
+31 32
+32 33
+33 34
+34 35
+35 36
+36 37
+37 38
+38 39
+39 40
+40 41
+41 42
+42 43
+43 44
+44 45
+45 46
+46 47
+47 48
+48 49
+49 50
+50 51
+51 52
+52 27
+
+1  27
+2  28
+3  29
+4  30
+5  31
+6  32
+7  33
+8  34
+9  35
+10 36
+11 37
+12 38
+13 39
+14 40
+15 41
+16 42
+17 43
+18 44
+19 45
+20 46
+21 47
+22 48
+23 49
+24 50
+25 51
+26 52
+
+WMCUBE_PLANES
+1 2 26
+26 2 25
+26 2 15
+24 3 11
+24 11 16
+15 12 13
+15 2 13
+15 13 14
+23 24 22
+22 24 16
+22 16 21
+21 16 17
+21 17 20
+17 19 20
+17 18 19
+4 5 3
+3 5 6
+3 6 11
+11 6 10
+10 6 7
+9 10 7
+9 7 8
+
+52 28 27
+51 28 52
+41 28 52
+37 29 50
+42 37 50
+39 38 41
+39 28 41
+40 39 41
+48 50 49
+42 50 48
+47 42 48
+43 42 47
+46 43 47
+46 45 43
+45 44 43
+29 31 30
+32 31 29
+37 32 29
+36 32 37
+33 32 36
+33 36 35
+34 33 35
+
+13 1 27
+27 39 13
+28 29 3
+28 3 2
+29 24 50
+24 29 3
+30 4 29
+29 4 3
+31 4 30
+4 31 5
+32 6 5
+5 31 32
+7 6 32
+7 32 33
+33 34 7
+7 34 8
+8 35 9
+35 8 34
+36 9 35
+9 36 10
+10 37 11
+37 10 36
+12 37 38
+37 12 11
+13 40 14
+13 39 40
+14 41 15
+41 14 40
+16 41 42
+41 16 15
+42 16 37
+11 37 16
+17 16 42
+43 17 42
+17 43 44
+18 17 44
+44 19 18
+19 44 45
+20 45 46
+45 20 19
+20 47 21
+47 20 46
+21 48 22
+48 21 47
+22 49 23
+49 22 48
+23 49 24
+50 24 49
+51 24 50
+24 51 25
+25 52 26
+52 25 51
+27 1 52
+1 26 52
\ No newline at end of file
diff --git a/3dObjects/peace.wmc b/wmc/peace.wmc
similarity index 98%
rename from 3dObjects/peace.wmc
rename to wmc/peace.wmc
index 22b57cb..ff28e65 100644
--- a/3dObjects/peace.wmc
+++ b/wmc/peace.wmc
@@ -1,3 +1,5 @@
+#By Peter Kokles <kokles at bb.telecom.sk>
+
 WMCUBE_COORDINATES
 1        0     -120     10 
 2      -46     -111     10
diff --git a/3dObjects/radioactive.wmc b/wmc/radioactive.wmc
similarity index 98%
rename from 3dObjects/radioactive.wmc
rename to wmc/radioactive.wmc
index 675ee08..87f49f5 100644
--- a/3dObjects/radioactive.wmc
+++ b/wmc/radioactive.wmc
@@ -1,3 +1,5 @@
+#By Peter Kokles <kokles at bb.telecom.sk>
+
 WMCUBE_COORDINATES
 1        0        0     0
 2        5      -19     0       
diff --git a/3dObjects/cross4-solid.wmc b/wmc/star-solid.wmc
similarity index 60%
rename from 3dObjects/cross4-solid.wmc
rename to wmc/star-solid.wmc
index 371d57e..a52f95f 100644
--- a/3dObjects/cross4-solid.wmc
+++ b/wmc/star-solid.wmc
@@ -7,30 +7,30 @@ WMCUBE_COORDINATES
 6    50  -50  -50
 7    50   50  -50
 8   -50   50  -50
-9   -50 -300  -50
-10   50 -300  -50
-11  300  -50  -50
-12  300   50  -50
-13   50  300  -50
-14  -50  300  -50
-15 -300   50  -50
-16 -300  -50  -50
-17 -300  -50   50
-18  -50 -300   50
-19   50 -300   50
-20  300  -50   50
-21  300   50   50
-22   50  300   50
-23  -50  300   50
-24 -300   50   50
-25  -50  -50  300
-26   50  -50  300
-27   50   50  300
-28  -50   50  300
-29  -50  -50 -300
-30   50  -50 -300
-31   50   50 -300
-32  -50   50 -300
+9   -10 -150  -10
+10   10 -150  -10
+11  150  -10  -10
+12  150   10  -10
+13   10  150  -10
+14  -10  150  -10
+15 -150   10  -10
+16 -150  -10  -10
+17 -150  -10   10
+18  -10 -150   10
+19   10 -150   10
+20  150  -10   10
+21  150   10   10
+22   10  150   10
+23  -10  150   10
+24 -150   10   10
+25  -10  -10  150
+26   10  -10  150
+27   10   10  150
+28  -10   10  150
+29  -10  -10 -150
+30   10  -10 -150
+31   10   10 -150
+32  -10   10 -150
 
 WMCUBE_PLANES
 1 18 19
diff --git a/3dObjects/wmlogo.wmc b/wmc/wmlogo.wmc
similarity index 92%
rename from 3dObjects/wmlogo.wmc
rename to wmc/wmlogo.wmc
index 8051cee..9378f68 100644
--- a/3dObjects/wmlogo.wmc
+++ b/wmc/wmlogo.wmc
@@ -1,3 +1,5 @@
+# By Rafael Garcia-Suarez <garcia-suarez at kazibao.net>
+
 WMCUBE_COORDINATES
    1 30 -30 10
    2 -30 -30 10
diff --git a/wmcube.cc b/wmcube.cc
new file mode 100644
index 0000000..d529026
--- /dev/null
+++ b/wmcube.cc
@@ -0,0 +1,695 @@
+#include <stdio.h>
+#include <stdexcept>
+#include <sys/types.h>
+#include <dirent.h>
+#include <iostream>
+#include <vector>
+#include <math.h>
+#include <unistd.h>
+
+#include "WmcObject.h"
+#include "wmcube.h"
+
+using namespace std;
+
+/**************************************************
+
+ Defines
+
+**************************************************/
+
+#define DEFAULT_WMC_PATH "/usr/share/wmcube"
+#define WMC_REDRAW 2 // centiseconds (= 50 fps)
+#define CANVAS_BGCOLOR 0x202020
+#define CYAN 0x20B2AE
+
+#define WINDOW_NEW 	0
+#define WINDOW_CLASSIC	1
+
+// Rotation speed (in radians) for each screen update
+#define ROT_SPEED_X (float)clopt_rspeed * (0.005 + (float)cpu_load / 3000.0)
+#define ROT_SPEED_Y (float)clopt_rspeed * (0.005 + (float)cpu_load / 3500.0)
+#define ROT_SPEED_Z (float)clopt_rspeed * (0.005 + (float)cpu_load / 4000.0)
+
+// Placement for the objects in new/classic mode
+#define XOFF_NEW 27
+#define YOFF_NEW 20
+#define ZOFF_NEW 400
+#define XOFF_CLASSIC XOFF_NEW
+#define YOFF_CLASSIC 27
+#define ZOFF_CLASSIC -ZOFF_NEW
+
+/**************************************************
+
+ Function predeclaration
+
+**************************************************/
+
+// Timer and widget callbacks
+void gatherStatistics(const WMApp *a, void *);
+void displayWmcObject(const WMApp *a, WMWidget *w, void *);
+void displayCpuText(const WMApp *a, WMWidget *w, void *);
+void displayCpuMeter(const WMApp *a, WMWidget *w, void *);
+void canvasClicked(const WMApp *a, WMWidget *w, void *);
+
+// Other funcs
+void switchWindow(WmcObject *currentwmc);
+void scanWmcDirectory(const char *dirname);
+char *nextObject();
+char *prevObject();
+void clearCanvas(WMCanvas *canvas);
+bool checkMouseRegion(const WMCanvas *c, int button, int ulx, int uly, int lrx, int lry);
+
+/**************************************************
+
+ Global variables
+
+**************************************************/
+
+// "Main" variables
+WMApp 		wmcube;
+CpuMonitor 	*cpumon = 0;
+WmcObject 	*wmc, *wmcnew, *wmcold;
+int 		cpu_load = 0;
+int 		switching = 0;
+int			xoff = XOFF_NEW, yoff = YOFF_NEW, zoff = ZOFF_NEW;
+
+// A list of available object's filenames and an iterator
+vector <char *> objects;
+vector <char *>::const_iterator obj_iterator;
+
+// Variables for command line options (set to their defaults)
+char	*clopt_object 	= 0;
+int	 	 clopt_cpu 		= -1;
+int	 	 clopt_update 	= 50;
+int		 clopt_window 	= WINDOW_NEW; 
+float	 clopt_rspeed 	= 3;
+bool	 clopt_nice 	= true;
+unsigned clopt_fgcolor 	= CYAN;
+float 	 clopt_shade 	= 90.0;
+unsigned clopt_bgcolor 	= CANVAS_BGCOLOR;
+int	 	 clopt_invert	= false;
+int		 clopt_mode 	= SOLID;
+bool	 clopt_lsource 	= false;
+bool	 clopt_wheel 	= false;
+bool	 clopt_help		= false;
+
+/**************************************************
+
+ Main
+
+**************************************************/ 
+int main(int argc, char *argv[])
+{
+  WMApp::initialize(argc, argv);
+	
+  /**************************************************
+
+    Parse command line parameters
+  
+  ***************************************************/
+  int  c = 0;
+  char clstr[64] = "";
+  
+  for (int i = 0; i < NUM_CL_OPT; i++)
+    {
+      clstr[c++] = CL_OPT[i].c;
+      if (strlen(CL_OPT[i].parms) > 0) clstr[c++] = ':';
+    }
+  
+  clstr[c] = 0;
+  
+  while ((c = getopt (argc, argv, clstr)) != -1)
+    {
+      switch (c)
+		{
+		case CL_OPT_OBJECT_INT:
+		  clopt_object = strndup(optarg, 256);
+		  break;
+		case CL_OPT_CPU_INT:
+		  clopt_cpu = atoi(optarg);
+		  break;
+		case CL_OPT_UPDATE_INT:
+		  clopt_update = atoi(optarg);
+		  break;
+		case CL_OPT_WINDOW_INT:
+		  clopt_window = WINDOW_CLASSIC;
+		  break;
+		case CL_OPT_RSPEED_INT:
+		  clopt_rspeed = atoi(optarg);
+		  break;
+		case CL_OPT_NICE_INT:
+		  clopt_nice = false;
+		  break;
+		case CL_OPT_FGCOLOR_INT:
+		  sscanf(optarg, "%x", &clopt_fgcolor);
+		  //printf("FGCOLOR = 0x%X   shade = %.3f\n", clopt_fgcolor, clopt_shade); 
+		  break;
+		case CL_OPT_SHADE_INT:
+		  clopt_shade = atoi(optarg);
+		  break;
+		case CL_OPT_BGCOLOR_INT:
+		  sscanf(optarg, "%x", &clopt_bgcolor);
+		  //printf("BGCOLOR = 0x%X\n", clopt_bgcolor); 
+		  break;
+		case CL_OPT_INVERT_INT:
+		  clopt_invert = true;
+		  break;
+		case CL_OPT_MODE_INT:
+		  clopt_mode = atoi(optarg);
+		  break;
+		case CL_OPT_LSOURCE_INT:
+		  clopt_lsource = true;
+		  break;
+		case CL_OPT_WHEEL_INT:
+		  clopt_wheel = true;
+		  break;
+		case CL_OPT_HELP_INT:
+		  clopt_help = true;
+		  printUsage();
+		  break;
+		default:
+		  clopt_help = true;
+		  printUsage();
+		  break;
+		}
+    }
+  
+  
+  /**************************************************
+    
+     Set up cpu monitor
+    
+  ***************************************************/
+    
+    try
+      {
+	
+#ifdef DARWIN
+  		cpumon = new CpuMonitor();
+#endif
+	
+#ifdef FREEBSD
+  		cpumon = new CpuMonitor(clopt_nice);
+#endif
+	
+#ifdef LINUX
+  		cpumon = new CpuMonitor(clopt_cpu, clopt_nice);
+#endif
+	
+#ifdef NETBSD
+  		cpumon = new CpuMonitor(clopt_nice);
+#endif
+	
+#ifdef OPENBSD
+  		cpumon = new CpuMonitor();
+#endif
+	
+#ifdef SOLARIS
+  		cpumon = new CpuMonitor(clopt_cpu);
+#endif
+	
+      }
+    catch (exception &e)
+      {
+		cout << e.what() << endl;
+		return -1;
+      }
+    
+    cpumon->setRange(99); // Only two digits fits in text area
+    
+    /**************************************************
+      
+      Scan wmc-directory and load (initial) object
+      
+    **************************************************/
+    try
+      {
+		if (clopt_object == 0)
+	  	{
+	  		scanWmcDirectory(DEFAULT_WMC_PATH);
+	  		wmc = (objects.size() > 0) ? new WmcObject(nextObject()) : new WmcObject();
+	  	}
+		else
+	  	{
+	    	scanWmcDirectory(clopt_object);
+	    	wmc = (objects.size() > 0) ? new WmcObject(nextObject()) : new WmcObject(clopt_object);
+	  	}
+      }
+    catch (exception &e)
+    {
+		cout << e.what() << endl;
+		return -1;
+    }
+    
+    wmc->setColorShading(clopt_fgcolor, clopt_shade);
+	wmc->setMode(clopt_mode);
+
+    printf("Objects in %s: %d\n", DEFAULT_WMC_PATH, objects.size());
+    
+    /***********************************************************************
+    
+      Set up the new style window	
+    
+    ***********************************************************************/
+    
+    WMWindow nw;
+    WMFrame nmain, bottom, botleft, botright;
+    WMCanvasCallback ncanvas;
+    WMTextBar cpu("00", 0);
+    WMMeterBar meter(0, 100);
+    
+    nw.setpadding(1);
+    nw.addchild(nmain);
+    nw.addchild(bottom);
+    nw.setorientation(Orientation::Vertical);
+    nw.setaspectratios(80, 21);
+    nw.add_timed_function(clopt_update, gatherStatistics, 0);
+    nw.add_timed_function(clopt_update, displayCpuText,  &cpu, 0);
+    nw.add_timed_function(clopt_update, displayCpuMeter, &meter, 0);
+    nw.add_timed_function(WMC_REDRAW, displayWmcObject, &ncanvas, wmc);
+
+    ncanvas.addcallback(canvasClicked, &ncanvas, 0);	
+  
+    ncanvas.setbuffered(true);
+    meter.setstyle(WMMeterBar::Blue);
+  
+    //bottom.setpadding(2);
+    //bottom.setborder(0);
+    nmain.addchild(ncanvas);
+    bottom.addchild(botleft);
+    bottom.addchild(botright);
+    bottom.setorientation(Orientation::Horizontal);
+    bottom.setaspectratios(4, 11);
+
+    meter.setorientation(Orientation::Horizontal);
+
+    botleft.addchild(cpu);
+    botright.setorientation(Orientation::Vertical);
+    botright.setpadding(2);
+    botright.addchild(meter);
+
+  	/***********************************************************************
+
+     Set up the classic style window
+
+  	***********************************************************************/
+  
+	WMWindow cw;
+	WMCanvasCallback ccanvas;
+	    
+	cw.setpadding(1);
+	cw.addchild(ccanvas);
+	cw.setaspectratios(1, 1);
+	cw.add_timed_function(clopt_update, gatherStatistics, 0);
+	cw.add_timed_function(WMC_REDRAW, displayWmcObject, &ccanvas, wmc);
+	
+	ccanvas.addcallback(canvasClicked, &ccanvas, 0);
+	ccanvas.setbuffered(true);
+	  
+	/***********************************************************************
+	
+	   Ok we're more or less set to go..
+	  
+	***********************************************************************/
+	
+	wmcube.addwindow(nw);
+	wmcube.addwindow(cw);
+	
+	// If the user selected to start in classic mode...
+	if (clopt_window == WINDOW_CLASSIC)
+	{
+		// .. we need to tell switchWindow that we currently are in new mode.
+  		clopt_window = WINDOW_NEW;
+  		switchWindow(wmc);	
+		wmcube.run(cw);
+	}
+	else
+		wmcube.run(nw);
+	
+	delete cpumon;
+	delete wmc;
+	
+	return 0;
+}
+
+/********************************************************************************
+
+ void switchWindow(WmcObject *currentwmc)
+
+ Switch between new/classic mode. 
+
+********************************************************************************/
+void switchWindow(WmcObject *currentwmc)
+{
+  //printf("switching windows\n"); fflush(stdout);
+  
+  if (clopt_window == WINDOW_CLASSIC)
+    {
+		clopt_window = WINDOW_NEW;
+		xoff = XOFF_NEW;
+		yoff = YOFF_NEW;
+		zoff = ZOFF_NEW;
+	}
+  else
+    {
+		clopt_window = WINDOW_CLASSIC;
+		xoff = XOFF_CLASSIC;
+		yoff = YOFF_CLASSIC;
+		zoff = ZOFF_CLASSIC;
+    }
+    
+  wmcube.switch_to(clopt_window);	
+  
+  // Zoom/translate object to fit current canvas size
+  currentwmc->modifyZOffset(zoff);
+  currentwmc->setYOffset(yoff);
+}
+
+/********************************************************************************
+
+ void canvasClicked(const WMApp *a, WMWidget *w, void *)
+
+ Event callback for everything that has to do with the canvas that the object(s)
+ are being drawn in.
+
+********************************************************************************/
+#define ZOOM_STEP     100
+#define LSOURCE_Z_OFF 10
+
+void canvasClicked(const WMApp *a, WMWidget *w, void *)
+{
+  WMCanvas *c = dynamic_cast<WMCanvas *>(w);
+  WmcObject *current;
+
+  if (!c) return;
+
+  current = switching ? wmcnew : wmc;
+  
+  /*
+    Mouse-wheel zoom in and out (unless clopt_wheel == true).
+  */
+  if (((a->mouseclick().button == Button4) && (!clopt_wheel)) || 
+  		checkMouseRegion(c, Button1, 47, 12, 65, 48))
+  {
+    current->modifyZOffset(-ZOOM_STEP);
+    return;
+  }  
+  if (((a->mouseclick().button == Button5) && (!clopt_wheel))  || 
+  		checkMouseRegion(c, Button1, 0, 12, 16, 48))
+  {
+    current->modifyZOffset( ZOOM_STEP);
+    return;
+  }
+  
+  /*
+    Switch window mode
+  */
+  if (checkMouseRegion(c, Button1, 0, 0, 13, 13)) 
+	{
+  		switchWindow(current);
+  		return;
+	}
+	 
+  /*
+    Switch 3d mode
+  */
+  if ((a->mouseclick().button == Button2) || checkMouseRegion(c, Button1, 15, yoff-10, 48, yoff+10))
+	{			
+  		current->setMode(++clopt_mode % NUM_MODES);
+  		return;
+	}
+    
+  /*
+    Change lightsource position with right mouse button
+  */
+  if (a->mouseclick().button == Button3)
+  {
+    current->setLightSource(xoff - a->mouseclick().relative_to(c).x, 
+    						yoff - a->mouseclick().relative_to(c).y,
+			    			LSOURCE_Z_OFF);
+	return;
+  }
+  
+  /*
+    Switch objects (if not already doing so)
+  */
+ if ((switching == 0) && (objects.size() > 0))
+    {
+      // Store a pointer to the old object so we can delete it later
+      wmcold = wmc;
+      
+      // Switch object with mousewheel instead of zooming
+      if ((a->mouseclick().button == Button4) && clopt_wheel)
+		{
+	  		// Scrolling object up with mousewheel
+	  		switching = 1;
+	  		wmcnew = new WmcObject(nextObject());
+		}
+      else if ((a->mouseclick().button == Button5) && clopt_wheel)
+		{
+	 		// Scrolling object down with mousewheel
+	  		switching = -1;
+	  		wmcnew = new WmcObject(prevObject());
+		}
+      // Switch objects by clicking
+      else if (checkMouseRegion(c, Button1, 12, 0, 60, yoff - 5))
+		{
+	  		// Scrolling object up by clicking top of canvas
+	  		switching = 1;
+	  		wmcnew = new WmcObject(nextObject());
+		}
+      else if (checkMouseRegion(c, Button1, 12, yoff + 5, 60, 60))
+		{
+	  		// Scrolling object down by clicking bottom of canvas
+	  		switching = -1;
+	  		wmcnew = new WmcObject(prevObject());
+		}
+		
+		if (clopt_window == WINDOW_CLASSIC) wmcnew->modifyZOffset(ZOFF_CLASSIC);
+		wmcnew->setColorShading(clopt_fgcolor, clopt_shade);
+		wmcnew->setMode(clopt_mode % NUM_MODES);
+				
+		return;
+    }
+}
+
+/********************************************************************************
+
+ bool checkMouseRegion(const WMCanvas *c, int button, int ulx, int uly, int lrx, int lry)
+
+ ulx = upper left x, go figure on the rest..
+
+********************************************************************************/
+
+bool checkMouseRegion(const WMCanvas *c, int button, int ulx, int uly, int lrx, int lry)
+{
+	if ((c->app())->mouseclick().button != button) return false;
+	if (((c->app())->mouseclick().relative_to(c).y > lry) || 
+		((c->app())->mouseclick().relative_to(c).y < uly)) return false;
+	if (((c->app())->mouseclick().relative_to(c).x < ulx) || 
+		((c->app())->mouseclick().relative_to(c).x > lrx)) return false;
+	
+	return true;	
+}
+
+/********************************************************************************
+
+ void displayWmcObject(const WMApp *a, WMWidget *w, void *)
+
+ Timer-callback for drawing the object(s) in the canvas that is passed in w.
+
+ Defines are for the scroll-in/out-speed of the objects (SCROLL_SPEED) as well 
+ as the initial displacement from the center for the new object (INITIAL_DISP).
+
+ Variable 'switching' take on values -1 (scrolling down), 0 (not switching)
+ and 1 (scrolling up).
+
+********************************************************************************/
+#define SCROLL_SPEED 2.0
+#define INITIAL_DISP switching * 2 * yoff
+
+void displayWmcObject(const WMApp *a, WMWidget *w, void *)
+{
+  static float yd = 0.0;
+  int local_yoff;
+  static float mlight = 0.0;
+  WMCanvas *c = dynamic_cast<WMCanvas *>(w);
+
+  if (!c) return;
+
+  clearCanvas(c);
+  
+  if (switching != 0)
+    {
+      /*
+		We're currently switching objects - do alot of magic.
+		Basically we're scrolling 'wmcnew' in from top/bottom
+		while simultanously scrolling 'wmc' out. 
+      */
+      yd += SCROLL_SPEED;
+      local_yoff = yoff - switching * (int)yd;
+      
+      wmc->rotate(ROT_SPEED_X, ROT_SPEED_Y, ROT_SPEED_Z);
+      wmc->setYOffset(local_yoff);
+      wmc->draw(c);
+
+      wmcnew->setYOffset(yoff + INITIAL_DISP - switching * (int)yd);
+      wmcnew->rotate(ROT_SPEED_X, ROT_SPEED_Y, ROT_SPEED_Z);
+      wmcnew->draw(c);
+      
+      if (yd >= switching * INITIAL_DISP)
+      	{
+	  		// Finished switching, delete the old object
+	  		switching = 0;
+	  		yd = 0.0;
+	  		mlight = 0.0;
+	  		wmc = wmcnew;
+	  		delete wmcold;
+		}
+    }
+  else
+    {
+      wmc->rotate(ROT_SPEED_X, ROT_SPEED_Y, ROT_SPEED_Z);
+            
+      if (clopt_lsource)
+		{
+      	   wmc->setLightSource(55.0 * cos(mlight*0.002), 50.0 * sin(mlight*0.040), LSOURCE_Z_OFF);
+           mlight += 1.0;
+		}
+
+      wmc->draw(c);
+    }
+  
+  a->repaint();
+}
+
+/********************************************************************************
+
+ void gatherStatistics(const WMApp *a, void *)
+
+ Store the polled cpu-load in variable 'cpu_load'
+ 
+********************************************************************************/
+void gatherStatistics(const WMApp *a, void *)
+{ 
+  cpu_load = (int)cpumon->getLoad();
+}
+
+/********************************************************************************
+
+ void displayCpuText(const WMApp *a, WMWidget *w, void *)'
+
+ Display the cpu-load in the textbar passed in w.
+ 
+********************************************************************************/
+void displayCpuText(const WMApp *a, WMWidget *w, void *)
+{
+  char tmp[6];
+  WMTextBar *b = dynamic_cast<WMTextBar*>(w);
+  
+  if (!b) return;
+
+  sprintf(tmp, "%2d", cpu_load);
+  b->settext(tmp);
+  a->repaint();
+}
+
+/********************************************************************************
+
+ void displayCpuMeter(const WMApp *a, WMWidget *w, void *)
+ 
+ Display the cpu-load in the meterbar passed in w.
+ 
+********************************************************************************/
+void displayCpuMeter(const WMApp *a, WMWidget *w, void *)
+{
+  WMMeterBar *m = dynamic_cast<WMMeterBar *>(w);
+  
+  if (!m) return;
+  
+  m->setvalue(cpu_load, true);
+  a->repaint();
+}
+
+/********************************************************************************
+
+ char *nextObject()
+
+ Returns the next objects' filename
+ 
+********************************************************************************/
+char *nextObject()
+{
+  if (obj_iterator == objects.end() - 1)
+    obj_iterator = objects.begin();
+  else
+    obj_iterator++;
+
+  //printf("returning next Object = %s\n", *obj_iterator); fflush(stdout);
+  
+  return *obj_iterator;
+}
+
+/********************************************************************************
+
+ char *prevObject()
+
+ Returns the previous objects' filename
+ 
+********************************************************************************/
+char *prevObject()
+{
+  if (obj_iterator == objects.begin())
+    obj_iterator = objects.end() - 1;
+  else
+    obj_iterator--;
+    
+  //printf("returning previous Object = %s\n", *obj_iterator); fflush(stdout);
+
+  return *obj_iterator;
+}
+
+/********************************************************************************
+
+ int scanWmcDirectory(const char *dirname)
+
+ Scans the directory 'dirname' and stores the full pathname of all found
+ wmc-files in the global vector 'objects'. This code should be POSIX compliant
+ which the old code was not (didnt work on Solaris for example). Objects are
+ listed in some seemingly random order (creation time?).
+ 
+********************************************************************************/
+void scanWmcDirectory(const char *dirname)
+{
+  DIR *dir_stream = opendir(dirname);
+  struct dirent *dirp;
+  char *strp;
+
+  if (dir_stream == NULL)
+    return; //throw runtime_error("scanWmcDirectory: Could not open directory.");
+
+  for (dirp = readdir(dir_stream); dirp != NULL; dirp = readdir(dir_stream))
+    {
+      if (strstr(dirp->d_name, ".wmc"))
+		{
+		  // Make sure there's space for the dirname, a slash, filename and terminating zero
+		  strp = new char[strlen(dirname) + strlen(dirp->d_name) + 2];
+		  strcpy(strp, dirname);
+		  strcat(strp, "/");
+		  strcat(strp, dirp->d_name);
+		  objects.push_back(strp);
+		  //printf("%s\n", objects[objects.size() - 1]);
+		}
+    }
+  
+  obj_iterator = objects.begin();
+  closedir(dir_stream);
+}
+
+void clearCanvas(WMCanvas *canvas)
+{
+  canvas->setcolor((WMColor::WMColor)clopt_bgcolor);
+  canvas->fill_rectangle(0, 0, 54, 54);
+  //canvas->draw_vertical_gradient(0,0,53,40, 0x000000, 0x555555);
+}
diff --git a/wmcube.h b/wmcube.h
new file mode 100644
index 0000000..d9052b5
--- /dev/null
+++ b/wmcube.h
@@ -0,0 +1,118 @@
+#ifndef _WMCUBE_HPP_
+#define _WMCUBE_HPP_
+
+#include "wmapp/wmwidget.h"
+#include "wmapp/wmapp.h"
+#include "wmapp/wmwindow.h"
+#include "wmapp/wmframe.h"
+#include "wmapp/wmcanvas.h"
+#include "wmapp/wmmeterbar.h"
+#include "wmapp/wmtextbar.h"
+#include "wmapp/wmcallback.h"
+
+#ifdef DARWIN
+#include "cpumoncc/darwin/CpuMonitor.h"
+#endif
+#ifdef FREEBSD
+#include "cpumoncc/freebsd/CpuMonitor.h"
+#endif
+#ifdef LINUX
+#include "cpumoncc/linux/CpuMonitor.h"
+#endif
+#ifdef NETBSD
+#include "cpumoncc/netbsd/CpuMonitor.h"
+#endif
+#ifdef OPENBSD
+#include "cpumoncc/openbsd/CpuMonitor.h"
+#endif
+#ifdef SOLARIS
+#include "cpumoncc/solaris/CpuMonitor.h"
+#endif
+
+#define WMCUBE_VERSION "0.99-pre1"
+#define WMCUBE_RELDATE "2003-02-28"
+
+typedef struct
+{ 
+   const int  c; 
+   const char *parms;
+   const char *desc;
+} 
+cl_opt;
+
+#define CL_OPT_OBJECT_INT  (int)'o'
+#define CL_OPT_CPU_INT     (int)'c'
+#define CL_OPT_UPDATE_INT  (int)'u'
+#define CL_OPT_WINDOW_INT  (int)'k'
+#define CL_OPT_RSPEED_INT  (int)'r'    
+#define CL_OPT_NICE_INT    (int)'n'
+#define CL_OPT_FGCOLOR_INT (int)'f'
+#define CL_OPT_SHADE_INT   (int)'s'    
+#define CL_OPT_BGCOLOR_INT (int)'b'
+#define CL_OPT_INVERT_INT  (int)'i'    
+#define CL_OPT_MODE_INT    (int)'m'    
+#define CL_OPT_LSOURCE_INT (int)'l'
+#define CL_OPT_WHEEL_INT   (int)'w'
+#define CL_OPT_HELP_INT   (int)'h'
+
+const cl_opt CL_OPT_OBJECT =	{ CL_OPT_OBJECT_INT,"filename/directory","load wmc-object or scan a directory for objects"};
+const cl_opt CL_OPT_CPU	= 		{ CL_OPT_CPU_INT    ,"X","monitor cpu X (starts with 0, default average over all)" };
+const cl_opt CL_OPT_UPDATE = 	{ CL_OPT_UPDATE_INT ,"X","read cpu load every X centiseconds (default 50)" };
+const cl_opt CL_OPT_WINDOW =	{ CL_OPT_WINDOW_INT,"","start in classic mode" };
+const cl_opt CL_OPT_RSPEED =	{ CL_OPT_RSPEED_INT ,"X","rotating speed 0-9 (default 3)" };
+const cl_opt CL_OPT_NICE =		{ CL_OPT_NICE_INT, "","exclude nice processes" };
+const cl_opt CL_OPT_FGCOLOR =	{ CL_OPT_FGCOLOR_INT,"0xXXXXXX","solid/wireframe color (default CYANish color)" };
+const cl_opt CL_OPT_SHADE =		{ CL_OPT_SHADE_INT,"X","amount of shading on solid objects 0-100 (default 80)" };
+const cl_opt CL_OPT_BGCOLOR =	{ CL_OPT_BGCOLOR_INT,"0xXXXXXX","background color (default 0x202020)" };
+const cl_opt CL_OPT_INVERT =	{ CL_OPT_INVERT_INT, "","invert rotating speed/cpu load relationship" };
+const cl_opt CL_OPT_MODE =		{ CL_OPT_MODE_INT,"wire/solid/solidwire","default mode for objects with multiple modes" };
+const cl_opt CL_OPT_LSOURCE =	{ CL_OPT_LSOURCE_INT,"","moving light source (default clickable light source)" };
+const cl_opt CL_OPT_WHEEL =		{ CL_OPT_WHEEL_INT,"","switch object with mouse wheel (default zoom)" };
+const cl_opt CL_OPT_HELP =		{ CL_OPT_HELP_INT,"","print help" };
+
+#define NUM_CL_OPT 11
+
+const cl_opt CL_OPT[NUM_CL_OPT] =
+{
+	CL_OPT_OBJECT,	
+	CL_OPT_CPU,
+	CL_OPT_UPDATE,
+	CL_OPT_WINDOW, 
+	CL_OPT_RSPEED, 
+	CL_OPT_NICE, 
+	CL_OPT_FGCOLOR, 
+	CL_OPT_SHADE, 
+	CL_OPT_BGCOLOR, 
+	//CL_OPT_INVERT, 
+	//CL_OPT_MODE, 
+	CL_OPT_LSOURCE, 
+	//CL_OPT_WHEEL,
+	CL_OPT_HELP
+};
+
+void printUsage()
+{
+  printf("wmCube %s (%s) (C) Robert Kling 2003\n\n", WMCUBE_VERSION, WMCUBE_RELDATE);
+  printf("Usage: wmcube [options]\n\n");
+
+  for (int i = 0; i < NUM_CL_OPT; i++)
+	{
+		
+		printf(" -%c %s", CL_OPT[i].c, CL_OPT[i].parms);
+		for (int j = 0; j < 22 - strlen(CL_OPT[i].parms); j++) printf(" ");
+		printf("%s\n", CL_OPT[i].desc);
+	}
+
+//  printf("\nThe -c option is only availible on Linux and Solaris.");
+//  printf("\nThe -n option is only availible on FreeBSD, Linux and NetBSD.\n\n"); 
+  fflush(stdout);
+}
+
+class WMCanvasCallback : public WMCallback, public WMCanvas
+{
+public:
+  WMCanvasCallback() : WMCallback(), WMCanvas() { }
+};
+
+
+#endif
diff --git a/wmcube/Makefile b/wmcube/Makefile
deleted file mode 100644
index 1410b29..0000000
--- a/wmcube/Makefile
+++ /dev/null
@@ -1,39 +0,0 @@
-CC = gcc
-OS = -DLINUX
-
-LIBDIR = -L/usr/X11R6/lib
-LIBDIR = -L/usr/X11R6/lib
-INCDIR = -I/usr/X11R6/share/include
-
-# Edit OSLIBS as appropriate to include OS specific libraries.
-
-OSLIBS =
-LIBS   = -lXpm -lXext -lX11 -lm $(OSLIBS)
-CFLAGS = -Wall -O2 $(OS)
-
-OBJS =	wmcube.o \
-	../wmgeneral/wmgeneral.o \
-	../wmgeneral/misc.o \
-	../wmgeneral/list.o
-
-.c.o:
-	$(CC) $(CFLAGS) $(INCDIR) -c $< -o $*.o
-
-wmcube: $(OBJS)
-	$(CC) -o wmcube $^ -lXext $(LIBDIR) $(LIBS)
-
-
-all:: wmcube
-
-clean::
-	for i in $(OBJS) ; do \
-		rm -f $$i ; \
-	done
-	rm -f wmcube
-	rm -f *~
-
-install:: wmcube
-	cp -f wmcube /usr/local/bin/
-	chmod 755 /usr/local/bin/wmcube
-	chown root:root /usr/local/bin/wmcube
-	@echo "wmCube installation finished..."
diff --git a/wmcube/Makefile.FREEBSD b/wmcube/Makefile.FREEBSD
deleted file mode 100644
index 815e32d..0000000
--- a/wmcube/Makefile.FREEBSD
+++ /dev/null
@@ -1,38 +0,0 @@
-CC = gcc
-OS = -DFREEBSD
-
-LIBDIR = -L/usr/X11R6/lib
-LIBDIR = -L/usr/X11R6/lib
-INCDIR = -I/usr/X11R6/include
-
-# Edit OSLIBS as appropriate to include OS specific libraries.
-
-OSLIBS = -lkvm
-LIBS   = -lXpm -lXext -lX11 -lm $(OSLIBS)
-CFLAGS = -Wall -O2 $(OS)
-
-OBJS =	wmcube.o \
-	../wmgeneral/wmgeneral.o \
-	../wmgeneral/misc.o \
-	../wmgeneral/list.o
-
-.c.o:
-	$(CC) $(CFLAGS) $(INCDIR) -c $< -o $*.o
-
-wmcube: $(OBJS)
-	$(CC) -o wmcube $(OBJS) -lXext $(LIBDIR) $(LIBS)
-
-all:: wmcube
-
-clean::
-	for i in $(OBJS) ; do \
-		rm -f $$i ; \
-	done
-	rm -f wmcube
-	rm -f *~
-
-install:: wmcube
-	cp -f wmcube /usr/local/bin/
-	chmod g+s /usr/local/bin/wmcube
-	chown root.kmem /usr/local/bin/wmcube
-	@echo "wmCube installation finished..."
diff --git a/wmcube/Makefile.LINUX b/wmcube/Makefile.LINUX
deleted file mode 100644
index 1410b29..0000000
--- a/wmcube/Makefile.LINUX
+++ /dev/null
@@ -1,39 +0,0 @@
-CC = gcc
-OS = -DLINUX
-
-LIBDIR = -L/usr/X11R6/lib
-LIBDIR = -L/usr/X11R6/lib
-INCDIR = -I/usr/X11R6/share/include
-
-# Edit OSLIBS as appropriate to include OS specific libraries.
-
-OSLIBS =
-LIBS   = -lXpm -lXext -lX11 -lm $(OSLIBS)
-CFLAGS = -Wall -O2 $(OS)
-
-OBJS =	wmcube.o \
-	../wmgeneral/wmgeneral.o \
-	../wmgeneral/misc.o \
-	../wmgeneral/list.o
-
-.c.o:
-	$(CC) $(CFLAGS) $(INCDIR) -c $< -o $*.o
-
-wmcube: $(OBJS)
-	$(CC) -o wmcube $^ -lXext $(LIBDIR) $(LIBS)
-
-
-all:: wmcube
-
-clean::
-	for i in $(OBJS) ; do \
-		rm -f $$i ; \
-	done
-	rm -f wmcube
-	rm -f *~
-
-install:: wmcube
-	cp -f wmcube /usr/local/bin/
-	chmod 755 /usr/local/bin/wmcube
-	chown root:root /usr/local/bin/wmcube
-	@echo "wmCube installation finished..."
diff --git a/wmcube/Makefile.NETBSD b/wmcube/Makefile.NETBSD
deleted file mode 100644
index 7d212aa..0000000
--- a/wmcube/Makefile.NETBSD
+++ /dev/null
@@ -1,36 +0,0 @@
-CC = gcc
-OS = -DNETBSD
-
-LIBDIR = -L/usr/X11R6/lib -L./libdocapp/
-
-# Edit OSLIBS as appropriate to include OS specific libraries.
-
-OSLIBS = 
-LIBS   = -lXpm -lXext -lX11 -lm $(OSLIBS)
-CFLAGS = -Wall -I/usr/X11R6/include -O2 $(OS)
-
-OBJS =	wmcube.o \
-		../wmgeneral/wmgeneral.o \
-		../wmgeneral/misc.o \
-		../wmgeneral/list.o
-
-.c.o:
-	$(CC) $(CFLAGS) $(INCDIR) -c $< -o $*.o
-
-wmcube: $(OBJS)
-	$(CC) -o wmcube -lXext $(LIBDIR) $(LIBS) $(OBJS)
-
-all:: wmcube
-
-clean::
-	for i in $(OBJS) ; do \
-		rm -f $$i ; \
-	done
-	rm -f wmcube
-	rm -f *~
-
-install:: wmcube
-	cp -f wmcube /usr/local/bin/
-	chmod 755 /usr/local/bin/wmcube
-	chown root:root /usr/local/bin/wmcube
-	@echo "wmCube installation finished..."
diff --git a/wmcube/Makefile.OPENBSD b/wmcube/Makefile.OPENBSD
deleted file mode 100644
index 3cbae90..0000000
--- a/wmcube/Makefile.OPENBSD
+++ /dev/null
@@ -1,37 +0,0 @@
-CC = gcc
-OS = -DOPENBSD
-
-LIBDIR = -L/usr/X11R6/lib -L./libdocapp/
-
-# Edit OSLIBS as appropriate to include OS specific libraries.
-
-OSLIBS = 
-LIBS   = -lXpm -lXext -lX11 -lm $(OSLIBS)
-INCLUDES = -I/usr/X11R6/include
-CFLAGS = -Wall -O2 $(OS) $(INCLUDES)
-
-OBJS =	wmcube.o \
-		../wmgeneral/wmgeneral.o \
-		../wmgeneral/misc.o \
-		../wmgeneral/list.o
-
-.c.o:
-	$(CC) $(CFLAGS) $(INCDIR) -c $< -o $*.o
-
-wmcube: $(OBJS)
-	$(CC) -o wmcube $^ -lXext $(LIBDIR) $(LIBS) $>
-
-all:: wmcube
-
-clean::
-	for i in $(OBJS) ; do \
-		rm -f $$i ; \
-	done
-	rm -f wmcube
-	rm -f *~
-
-install:: wmcube
-	cp -f wmcube /usr/local/bin/
-	chmod 755 /usr/local/bin/wmcube
-	chown root:root /usr/local/bin/wmcube
-	@echo "wmCube installation finished..."
diff --git a/wmcube/Makefile.SOLARIS b/wmcube/Makefile.SOLARIS
deleted file mode 100644
index 5ebc893..0000000
--- a/wmcube/Makefile.SOLARIS
+++ /dev/null
@@ -1,38 +0,0 @@
-CC = gcc
-OS = -DSOLARIS
-
-LIBDIR = -L/usr/X11R6/lib
-LIBDIR = -L/usr/openwin/lib -L/opt/sfw/lib -L/usr/local/lib -R/usr/openwin/lib -R/opt/sfw/lib -R/usr/local/lib
-INCDIR = -I/usr/openwin/include -I/opt/sfw/include -I/usr/local/include
-
-# Edit OSLIBS as appropriate to include OS specific libraries.
-
-OSLIBS = -lkstat
-LIBS   = -lXpm -lXext -lX11 -lm $(OSLIBS)
-CFLAGS = -Wall -O2 $(OS)
-
-OBJS =	wmcube.o \
-	../wmgeneral/wmgeneral.o \
-	../wmgeneral/misc.o \
-	../wmgeneral/list.o
-
-.c.o:
-	$(CC) $(CFLAGS) $(INCDIR) -c $< -o $*.o
-
-wmcube: $(OBJS)
-	$(CC) -o wmcube $^ -lXext $(LIBDIR) $(LIBS)
-
-all:: wmcube
-
-clean::
-	for i in $(OBJS) ; do \
-		rm -f $$i ; \
-	done
-	rm -f wmcube
-	rm -f *~
-
-install:: wmcube
-	cp -f wmcube /usr/local/bin/
-	chmod 755 /usr/local/bin/wmcube
-	chown root:root /usr/local/bin/wmcube
-	@echo "wmCube installation finished..."
diff --git a/wmcube/wmcube.c b/wmcube/wmcube.c
deleted file mode 100644
index a586b55..0000000
--- a/wmcube/wmcube.c
+++ /dev/null
@@ -1,1351 +0,0 @@
-/*
-
- wmcube.c 
- Version 0.98 (2000-10-20)
-
- Robert Kling (robkli-8 at student.luth.se)
- http://boombox.campus.luth.se/projects.php
-
- Contributions:
- 	-n option patch by Thorsten Jens (thodi at et-inf.fho-emden.de) (2000-05-12)
- 	Various bugfixes and optimizations by Jakob Borg (2000-05-13)
-	Solaris Port by Dan Price (dp at rampant.org) (2000-07-16)
-	OpenBSD Port by Brian Joseph Czapiga (rys at godsey.net) (2000-07-19)
-	FreeBSD Port by Tai-hwa Liang (avatar at mmlab.cse.yzu.edu.tw) (2000-07-20)
-	NetBSD Port by Jared Smolens <jsmolens+ at andrew.cmu.edu> (2000-09-23)
-
- This software is licensed through the GNU General Public Licence.
- 
- See http://www.BenSinclair.com/dockapp/ for more wm dock apps.
-
- If you want to port wmcube to another OS the system specific code is
- sectioned the bottom of this file. See instructions there.
-
-*/
-
-#define WMCUBE_VERSION "0.98"
-#define REV_DATE "2000-10-23"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <math.h>
-
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-
-#include <utmp.h>
-#include <dirent.h>
-
-#include <X11/Xlib.h>
-#include <X11/xpm.h>
-#include <X11/extensions/shape.h>
-
-#ifdef FREEBSD
-#include <kvm.h>
-#endif
-
-#include "../wmgeneral/wmgeneral.h"
-#include "../wmgeneral/misc.h"
-
-#include "wmcube.xpm"
-char wmcube_mask_bits[64*64];
-int  wmcube_mask_width = 64;
-int  wmcube_mask_height = 64;
-
-#define CHAR_WIDTH 5
-#define CHAR_HEIGHT 7
-#define PI 3.1415926535
-
-//**** Graphics ***********************************
-
-void putpixel(int x, int y, int c);
-void line(int x1, int y1, int x2, int y2, int c);
-void hline(int x1, int x2, int y, int c);
-void triangle(int x1, int y1, int x2, int y2, int x3, int y3, int c);
-void BlitString(char *name, int x, int y);
-void BlitNum(int num, int x, int y);
-void clearscr();
-void draw();
-void startup_seq();
-
-//**** 3d specific ********************************
-
-void setupobj(char *filename) ;
-void setUpAngles();
-void rotate(int xang, int yang, int zang);
-int  normal(float p1[], float p2[], float p3[]);
-int  luminate(float p1[], float p2[], float p3[]);
-void sortz(int nofelements);
-
-//**** Application Management, I/O etc. ***********
-
-void print_help();
-int  loadobj(char *filename);
-void mem_alloc_error(void *block);
-int	 scan4objects(char *dir);
-int  next_object();
-void die();
-
-//**** System specific functions ******************
-
-int  init_calc_cpu();
-int  calc_cpu_total();
-
-//**** Global variables ***************************
-
-int 	xcenter, ycenter, zoff;
-double	cost[361], sint[361];
-double  acost[100];
-float 	**matrix;
-float	**rmatrix;
-int		**planes;
-int		*plane_color;
-int		*zorder;
-int		*cline;
-int		nofcoords, noflines, nofplanes;
-char	*objects[1000];
-int		nof_objects = 0;
-int		show_load = 1;
-int		use_nice = 1;
-int		which_cpu = -1;
-int		planesORlines = 1;
-char 	*pname;
-
-float	lum_vector[3] = { 0, 0, 100 };  // Lightsource vector
-
-#ifdef FREEBSD
-static kvm_t            *kd;
-static struct nlist     nlst[] = { {"_cp_time"}, {0} };
-#endif
-
-int main(int argc, char **argv)
-{
-	int		j, i = 0, rot_speed = 0, cpu_usage = 0, rot_step = 1;
-	long	screen_speed = 10000;    // microseconds between screen updates (approx.)
-	long	cpu_update = 490000;     // microseconds between cpu update (approx.)
-	int		but_stat = -1;
-	int		loop = 0;
-	XEvent	Event;
-
-	char	*rotdiv = {"25"};
-	char	*rotstep = {"1"};
-	char	*obj_filename = {""};
-	int		rot;
-	int 	cube_color = 1;
-	int 	c = 0;
-	int		invert_speed = 0;
-
-	pname = strrchr(argv[0], '/');
-	if (pname == NULL) pname = argv[0];
-
-	srand((unsigned)time(NULL));
-	opterr = 0;
-	
-	while ((c = getopt (argc, argv, "d:nhpbir:o:c:")) != -1) {
-		switch (c)
-		{
-			case 'c':
-				which_cpu = atoi(optarg);
-				break;
-			case 'd':
-				rotstep = optarg;
-				break;
-			case 'h':
-				print_help();
-				return 1;
-			case 'i':
-				invert_speed = 1;
-				break;
-			case 'p':
-				show_load = 0;
-				break;
-			case 'b':
-				cube_color = 2;
-				break;
-			case 'r':
-				rotdiv = optarg;
-				break;
-			case 'o':
-				obj_filename = optarg;
-				break;
-			case 'n':
-				use_nice = 0;
-				break;
-			case '?':
-					print_help();
-					return 1;
-			default:
-				abort();
-		}
-	}
-
-	/*
-	 * Validate that wmcube can run on this system given the parameters,
-	 * then setup the statistics gathering subsystem.
-	 */
-	 
-	if (init_calc_cpu() != 0) die();
-
-	/*
-	 * Scan directory for .wmc files and choose one randomly. If the user 
-	 * specified a particular file, load that one.
-	 */
-
-#ifndef SOLARIS  // scan4objects doesnt work on Solaris, load object immediatly
-	scan4objects(obj_filename);
-	
-	if (nof_objects != 0)
-		next_object();
-	else
-#endif
-		setupobj(obj_filename);
-	 	
-	/*
-	 * Various initializion stuff for the 3d-engine etc.
-	 */
-
-	setUpAngles();
-
-	rot = atoi(rotdiv);
-	if ((rot >= 1) && (rot <=100)) ; else rot = 25;
-
-	rot_step = atoi(rotstep);
-	if (rot_step < 0) rot_step = -rot_step;	
-
-	if (calc_cpu_total() == -1)	die();
-
-	cpu_update /= screen_speed;
-
-	createXBMfromXPM(wmcube_mask_bits, wmcube_xpm, wmcube_mask_width, wmcube_mask_height);
-	openXwindow(argc, argv, wmcube_xpm, wmcube_mask_bits, wmcube_mask_width, wmcube_mask_height);
-
-	startup_seq();
-	
-	if (calc_cpu_total() == -1) die();
-
-	// index, left, top, right, bottom
-	AddMouseRegion(1,  45,  45, 58, 58);  // + Zoom In
-	AddMouseRegion(5,  5, 45, 20, 58);	  // - Zoom Out
-	AddMouseRegion(3,  21, 45, 45, 58);	  //   Show cpu-load
- 	AddMouseRegion(2,  5, 5, 55, 45);	  // Everywhere else (almost) to change object
-
- 	/*
- 	 * Main loop begins here
- 	 */
-
-	while (1)
-	{
-		i = (i+rot_speed+rot_step) % 360;
-		
-		clearscr();
-		rotate(i,i,i);
-		
-		draw(cube_color);
-
-		if (show_load) {
-			BlitNum(cpu_usage,24,49);
-			BlitString("Z",38,49);
-		}
-
-		RedrawWindow();
-		
-		if (loop++ == cpu_update) { 
-			loop = 0;
-
-			/*
-			 * call calc_cpu_total to update statistics.  If some
-			 * sort of bad event occurs, calc_cpu_total will return
-			 * -1, and we exit.
-			 */
-			 
-			if ((cpu_usage = calc_cpu_total()) == -1) {
-				die();
-			}
-			rot_speed =  abs( invert_speed*(100 / rot) - cpu_usage / rot);
-		}
-		
-      // X Events
-		
-		while (XPending(display))
-		{
-			XNextEvent(display, &Event);
-			switch (Event.type)
-			{
-				case Expose:
-					RedrawWindow();
-					break;
-				case DestroyNotify:
-					XCloseDisplay(display);
-					exit(0);
-					break;
-				case ButtonPress:
-					j = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
-					but_stat = j;
-					
-					break;
-				case ButtonRelease:
-					j = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
-					
-					switch(j)
-					{
-						case 1:
-							if (zoff > 750) {
-								BlitString("�",48,48);
-								RedrawWindow();
-								zoff -= 150;
-							}
-							break;
-
-						case 2:
-							next_object();
-							break;
-
-						case 3:
-							if (show_load == 1) show_load = 0; else show_load = 1;						
-							ycenter = 15 - 2*show_load;
-							break;
-
-						case 5:
-							BlitString("�",11,49);
-							RedrawWindow();
-							zoff += 150;
-							break;
-					}
-			}	
-			break;
-		}
-		usleep(screen_speed);
-	}
-
-	/*
-	 * Free up memory used by the object (dirty...)
-	 */
-
-	free(matrix);
-	free(rmatrix);
-	free(cline);	
-
-	return 1;
-}
-
-
-//**** Graphics ***********************************
-//*************************************************
-
-void startup_seq() 
-{
-	char *tmp = malloc(32);
-	int oldzoff = 3600;
-
-	sprintf(tmp,"V%s",WMCUBE_VERSION);
-	
-	RedrawWindow();
-	BlitString("WMCUBE",13,22);
-	BlitString(tmp,15,31);
-	RedrawWindow();
-	RedrawWindow();
-	usleep(3000000);
-	RedrawWindow();
-	
-	zoff = 1200;
-
-	for (;zoff < oldzoff; zoff += 35)
-	{
-		rotate((zoff-1200)/8,0,0);
-		clearscr();
-		BlitString("WMCUBE",13,22);
-		BlitString(tmp,15,31);
-		draw(1);
-		RedrawWindow();
-		usleep(9000);
-	}
-
-	zoff = 3600;
-}	
-
-void draw(int color)
-{
-	int i;
-
-	if (planesORlines) {
-
-		sortz(nofplanes);
-		for (i = 0; i < nofplanes; i++) {
-	    	if (normal(rmatrix[planes[zorder[i]][0]], rmatrix[planes[zorder[i]][1]], rmatrix[planes[zorder[i]][2]]) > 0) {	
-			
-			triangle(xcenter+rmatrix[planes[zorder[i]][0]][0], ycenter+rmatrix[planes[zorder[i]][0]][1],
-				 	 xcenter+rmatrix[planes[zorder[i]][1]][0], ycenter+rmatrix[planes[zorder[i]][1]][1],
-					 xcenter+rmatrix[planes[zorder[i]][2]][0], ycenter+rmatrix[planes[zorder[i]][2]][1], plane_color[zorder[i]]);
-			}
-		}
-		
-	} else {
-		for (i = 0; i < noflines; i += 2)
-			line(xcenter+rmatrix[cline[i  ]-1][0], ycenter+rmatrix[cline[i  ]-1][1],
-		 	 	 xcenter+rmatrix[cline[i+1]-1][0], ycenter+rmatrix[cline[i+1]-1][1],color);
-	}
-}
-
-void putpixel(int x, int y,int c)
-{
-	if ((x > 4) && (x < 59) && (y > 4) && (y < 59))
-		copyXPMArea(160-c,0,1,1,x,y);
-}
-
-void hline(int x1, int x2, int y, int c)
-{
-	if ((y > 4) && (y < 59)) {
-		if (x1 <= 4) x1 = 5;  else if (x1 > 57) return; 
-		if (x2 > 57) x2 = 57; else if (x2 <= 4) return; 
-
-		copyXPMArea(105, 56+c + 9*(c/18), x2-x1, 1, x1, y);
-	}
-}
-
-void triangle(int x1, int y1, int x2, int y2, int x3, int y3, int c) // Draws a filled triangle
-{
-    int k,k2,x,x_2,i, tmp1; 
-
-    int x1t, x2t;
-			    
-    if (y3<y2)
-    {
-		tmp1=y2;
-		y2=y3;
-		y3=tmp1;
-		tmp1=x2;
-		x2=x3;
-		x3=tmp1;
-    }
-
-    if (y2<y1)
-    {
-		tmp1=y1;
-		y1=y2;
-		y2=tmp1;
-		tmp1=x1;
-		x1=x2;
-		x2=tmp1;
-    }
-
-    if (y3<y2)
-    {
-		tmp1=y2;
-		y2=y3;
-		y3=tmp1;
-		tmp1=x2;
-		x2=x3;
-		x3=tmp1;
-    }
-    
-    if (y1!=y3)	k=((x1-x3) << 6) / (y1-y3);
-    else k=(x1-x3) << 6;
-
-	if (y1!=y2)	k2=((x1-x2) << 6) / (y1-y2);
-    else k2=(x1-x2) << 6;
-
-    x=x1 << 6;
-    x_2=x;
-    i=y1;
-
-    if (i!=y2)
-	do
-	{
-	    x+=k;
-	    x_2+=k2;
-	    i++;
-	  
-		if ((x1t = x >> 6) >  (x2t = x_2 >> 6))
-			hline(x2t, x1t, i, c);
-		else
-			hline(x1t, x2t, i, c);
-	}
-	while (i!=y2);
-
-    if (i==y3) return;
-
-    if (y2!=y3) k2=((x2-x3) << 6) / (y2-y3);
-    else k2=((x2-x3) << 6);
-
-    x_2=x2 << 6;
-    i=y2;
-    do
-    {
-		x+=k;
-		x_2+=k2;
-		i++;
-
-		if ((x1t = x >> 6) >  (x2t = x_2 >> 6))
-			hline(x2t, x1t, i, c);
-		else
-			hline(x1t, x2t, i, c);
-    }
-    while (i!=y3);
-}
-
-void clearscr()
-{
-	copyXPMArea(78,0,56,56,4,4);
-}
-
-// Blits a string at given co-ordinates
-void BlitString(char *name, int x, int y)
-{
-	int		i;
-	int		c;
-	int		k;
-	
-	k = x;
-	
-	copyXPMArea(73,64,1,8,k-1,y);
-	
-	for (i=0; name[i]; i++)
-	{  
-		c = toupper(name[i]); 
-      //printf("%c",c);
-		
-		if (c >= 'A' && c <= 'Z')
-		{   // its a letter
-			c -= 'A';
-			if ( k > -2) copyXPMArea(c * 6, 74, 6, 8, k, y);
-			k += 6;
-		} else
-		if (c >= '0' && c<= ':')
-		{   // its a number or symbol
-			c -= '0';
-			if ( k > -2) copyXPMArea(c * 6, 64, 6, 8, k, y);
-			k += 6;
-		} else
-		if (c == 246) {
-			if ( k > -2) copyXPMArea(0, 84, 6, 9, k, y);
-			k += 6;
-		} else
-		if (c == 228) {
-			if ( k > -2) copyXPMArea(6, 84, 6, 9, k, y);
-			k += 6;
-		} else
-		if (c == 229) {
-			if ( k > -2) copyXPMArea(12, 84, 6, 9, k, y);
-			k += 6;
-		} else
-		{   // its a blank or something else
-			if ( k > -2) copyXPMArea(73,64,6,8,k,y);
-			k += 6;
-		}
-		if (k >= 58) break;
-	}
-	copyXPMArea(73,64,1,8,k,y);
-	
-}
-
-// Blits number to given coordinates.. two 0's, right justified
-
-void BlitNum(int num, int x, int y)
-{
-	char buf[1024];
-	int newx=x;
-	
-	if (num > 99)
-	{
-		newx -= CHAR_WIDTH;
-	}
-	
-	if (num > 999)
-	{
-		newx -= CHAR_WIDTH;
-	}
-	
-	sprintf(buf, "%02i", num);
-	
-	BlitString(buf, newx, y);
-}
-
-void line(int x1, int y1, int x2, int y2, int c)
-{
-	int i, deltax, deltay, numpixels,
-	d, dinc1, dinc2,
-	x, xinc1, xinc2,
-	y, yinc1, yinc2;
-	
-	deltax = abs(x2 - x1);
-	deltay = abs(y2 - y1);
-	if (deltax >= deltay)
-	{
-		numpixels = deltax + 1;
-		d = (deltay << 1) - deltax;
-		dinc1 = deltay << 1;
-		dinc2 = (deltay - deltax) << 1;
-		xinc1 = 1;
-		xinc2 = 1;
-		yinc1 = 0;
-		yinc2 = 1;
-	}
-	else
-	{
-		numpixels = deltay + 1;
-		d = (deltax << 1) - deltay;
-		dinc1 = deltax << 1;
-		dinc2 = (deltax - deltay) << 1;
-		xinc1 = 0;
-		xinc2 = 1;
-		yinc1 = 1;
-		yinc2 = 1;
-	}
-	if (x1 > x2)
-	{
-		xinc1 = - xinc1;
-		xinc2 = - xinc2;
-	}
-	if (y1 > y2)
-	{
-		yinc1 = - yinc1;
-		yinc2 = - yinc2;
-	}
-	x = x1;
-	y = y1;
-	for (i=1; i<numpixels; i++)
-	{
-		putpixel(x, y, c);
-		if (d < 0)
-		{
-			d = d + dinc1;
-			x = x + xinc1;
-			y = y + yinc1;
-		}
-		else
-		{
-			d = d + dinc2;
-			x = x + xinc2;
-			y = y + yinc2;
-		}
-	}
-}
-
-
-//**** 3d specific ********************************
-//*************************************************
-
-void rotate(int xang, int yang, int zang)
-{
-	float tx, ty, tz;
-	int i;
-	
-	for (i = 0; i < nofcoords; i++) 
-	{
-		tx = cost[yang]*matrix[i][0]-sint[yang]*matrix[i][2];
-		tz = sint[yang]*matrix[i][0]+cost[yang]*matrix[i][2];
-		ty = cost[zang]*matrix[i][1]-sint[zang]*tx;
-
-		rmatrix[i][0] = (cost[zang]*tx+sint[zang]*matrix[i][1]);
-		rmatrix[i][1] = (sint[xang]*tz+cost[xang]*ty);
-		rmatrix[i][2] = (cost[xang]*tz-sint[xang]*ty);
-	}
-
-	if (planesORlines)
-		for (i = 0; i < nofplanes; i++)
-			if (normal(rmatrix[planes[i][0]], rmatrix[planes[i][1]], rmatrix[planes[i][2]]) > 0)
-				plane_color[i] = luminate(rmatrix[planes[i][0]], rmatrix[planes[i][1]], rmatrix[planes[i][2]]);
-
-	for (i = 0; i < nofcoords; i++) {	
-  		// Perspective correcting lines...
-		rmatrix[i][0] = (rmatrix[i][0] *256) / (2*rmatrix[i][2] - zoff) + xcenter;
-		rmatrix[i][1] = (rmatrix[i][1] *256) / (2*rmatrix[i][2] - zoff) + ycenter;
-	}
-}
-
-void sortz(int nofelements) {   // Insertion-sort the planes in increasing z-distance
-
-	int i, j, k;
-	float key;
-	float temparr[nofelements];
-
-	for (i = 0; i < nofelements; i++) 
-    {
-   		zorder[i] = i;
-   		temparr[i] = rmatrix[planes[i][0]][2]+rmatrix[planes[i][1]][2]+rmatrix[planes[i][2]][2];
-    }
-
-	for (j = 1; j < nofelements; j++) {
-		
-		key = temparr[j];
-		k = zorder[j];
-		i = j - 1;
-			
-		while ((i > -1) && (temparr[i] > key)) {
-			temparr[i+1] = temparr[i];
-			zorder[i+1] = zorder[i--];
-		}
-
-		zorder[i+1] = k;										
-		temparr[i+1] = key;
-	}
-}
-
-int normal(float p1[], float p2[], float p3[])
-{
-		return ((p1[0]-p3[0])*(p2[1]-p3[1])-(p2[0]-p3[0])*(p1[1]-p3[1]));
-}
-
-int luminate(float p1[], float p2[], float p3[])
-{
-      double x1 = (float)(p1[0]-p3[0]), y1 = (float)(p1[1]-p3[1]),  z1 = (float)(p1[2]-p3[2]);
-      double x2 = (float)(p2[0]-p3[0]), y2 = (float)(p2[1]-p3[1]),  z2 = (float)(p2[2]-p3[2]);
-      double nx = y1*z2-y2*z1, ny =-(x1*z2-x2*z1),nz = x1*y2-y1*x2;
-
-	  return (int)(53 * (acost[(int)(50 + 50*(nx*lum_vector[0]+ny*lum_vector[1]+nz*lum_vector[2])/
-				  					(sqrt(nx*nx+ny*ny+nz*nz)*
-				   					sqrt(lum_vector[0]*lum_vector[0]+lum_vector[1]*lum_vector[1]+
-				   					lum_vector[2]*lum_vector[2])))] / PI));	
-
-	  // Do I smell optimization? :-)				   						
-}
-
-void setUpAngles()
-{
-	int i;
-	for (i = 0; i < 361; i++) {
-		cost[i] = cos((double)i*(2*PI/(double)360));
-		sint[i] = sin((double)i*(2*PI/(double)360));
-	}
-
-	for (i = 0; i < 100; i++) acost[i] = acos((double)(-50+i)/50);
-}
-
-void setupobj(char *filename) 
-{
-	int i, j = 0;
-	int biggest = 0;
-	float scale = 1;
-
-	xcenter = 16;
-	ycenter = 15 - 2*show_load;
-	
-	if (strcmp(filename,"") != 0)
-		loadobj(filename);
-	else
-	{
-		nofcoords = 8;
-		noflines = 24;
-		nofplanes = 12;
-		planesORlines = 1;
-
-		matrix = 		(float **)malloc(nofcoords*sizeof(float *)); mem_alloc_error(matrix);
-		planes = 		(int **)malloc(nofplanes*sizeof(int *)); mem_alloc_error(planes);
-		plane_color =	(int *)malloc(nofplanes*sizeof(int)); mem_alloc_error(plane_color);
-		zorder = 		(int *)malloc(nofplanes*sizeof(int)); mem_alloc_error(zorder);
-
-		for (i = 0; i < nofplanes; i++) zorder[i] = i;
-		
-		for (i = 0; i < nofcoords; i++) { 
-			matrix[i] = (float *)malloc(3*sizeof(float));
-			mem_alloc_error(matrix[i]);
-		}
-
-		for (i = 0; i < nofplanes; i++) { 
-			planes[i] = (int *)malloc(3*sizeof(int));
-			mem_alloc_error(planes[i]);
-		}
-
-		cline = (int *)malloc((noflines+1)*sizeof(int)); mem_alloc_error(cline);
-	
-		matrix[0][0] = -180; matrix[0][1] = -180; matrix[0][2] =  180; // 0
-		matrix[1][0] =  180; matrix[1][1] = -180; matrix[1][2] =  180; // 1
-		matrix[2][0] =  180; matrix[2][1] =  180; matrix[2][2] =  180; // 2
-		matrix[3][0] = -180; matrix[3][1] =  180; matrix[3][2] =  180; // 3
-		matrix[4][0] = -180; matrix[4][1] = -180; matrix[4][2] = -180; // 4
-		matrix[5][0] =  180; matrix[5][1] = -180; matrix[5][2] = -180; // 5
-		matrix[6][0] =  180; matrix[6][1] =  180; matrix[6][2] = -180; // 6
-		matrix[7][0] = -180; matrix[7][1] =  180; matrix[7][2] = -180; // 7
-
-		cline[0] = 1;  cline[1] = 2;
-		cline[2] = 2;  cline[3] = 3;
-		cline[4] = 3;  cline[5] = 4;
-		cline[6] = 4;  cline[7] = 1;
-		cline[8] = 5;  cline[9] = 6;
-		cline[10] = 6; cline[11] = 7;
-		cline[12] = 7; cline[13] = 8;
-		cline[14] = 8; cline[15] = 5;
-		cline[16] = 1; cline[17] = 5;
-		cline[18] = 2; cline[19] = 6;
-		cline[20] = 3; cline[21] = 7;
-		cline[22] = 4; cline[23] = 8;
-
-		planes[0][0] = 0; planes[0][1] = 1; planes[0][2] = 3;
-		planes[1][0] = 1; planes[1][1] = 2; planes[1][2] = 3;		
-		planes[2][0] = 1; planes[2][1] = 5; planes[2][2] = 6;
-		planes[3][0] = 1; planes[3][1] = 6; planes[3][2] = 2;
-
-		planes[4][0] = 4; planes[4][1] = 0; planes[4][2] = 3;
-		planes[5][0] = 4; planes[5][1] = 3; planes[5][2] = 7;		
-		planes[6][0] = 3; planes[6][1] = 2; planes[6][2] = 7;
-		planes[7][0] = 7; planes[7][1] = 2; planes[7][2] = 6;
-
-		planes[8][0] = 4;  planes[8][1] = 1;  planes[8][2] = 0;
-		planes[9][0] = 4;  planes[9][1] = 5;  planes[9][2] = 1;		
-		planes[10][0] = 5; planes[10][1] = 4; planes[10][2] = 7;
-		planes[11][0] = 5; planes[11][1] = 7; planes[11][2] = 6;
-	}
-
- 	rmatrix = (float **)realloc(rmatrix,nofcoords*sizeof(float *)); mem_alloc_error(rmatrix);
- 	for (i = 0; i < nofcoords; i++) { 
- 		rmatrix[i] = (float *)malloc(3*sizeof(float));
- 		mem_alloc_error(rmatrix[i]);
- 	}
-
-	/*
-	 * Find the longest discance between all coordinates relative to the origin
-	 */
-
-	for (i = 0; i < nofcoords; i++) {
-		j = (int)sqrt((pow(matrix[i][0],2)+pow(matrix[i][1],2)+pow(matrix[i][2],2)));
-		if (j > biggest) biggest = j;
-	}
-
-	/*
-	 * Scale every coordinate using the calculated factor
-	 */
-
-	scale = 280 / (float)biggest;	
-
-	for (i = 0; i < nofcoords; i++) {
-		matrix[i][0] *= scale;
-		matrix[i][1] *= scale;
-		matrix[i][2] *= scale;
-	}
-}
-
-
-
-
-//**** Application Management, I/O etc. ***********
-//*************************************************
-
-void print_help() {
-	printf("\nwmCube %s (%s)\n\n", WMCUBE_VERSION, REV_DATE);
-	
-#ifndef SOLARIS
-	printf("  -o <filename or directory>: load external 3d-object(s).\n\n");
-#else
-	printf("  -o <filename>: load external 3d-object.\n\n");
-#endif
-
-	printf("  -d x: rotate x degrees/step when the cpu is idle. (default 1)\n");
-	printf("  -r x: rotate 1 degree faster every x percent of cpu-usage. (default 25)\n");
-
-#ifdef LINUX
-	printf("  -c x: which cpu (0,1,2..) to monitor. (default average over all)\n");
-	printf("  -n  : exclude \"nice\" processes. (default OFF)\n");
-#endif
-
-#ifdef SOLARIS
-	printf("  -c x: which cpu (0,1,2..) to monitor. (default average over all)\n");
-#endif
-
-#ifdef FREEBSD
-	printf("  -n  : exclude \"nice\" processes. (default OFF)\n");
-#endif
-
-#ifdef NETBSD
-	printf("  -n  : exclude \"nice\" processes. (default OFF)\n");
-#endif
-
-	printf("  -b  : draw the cube in a brighter color. (default OFF)\n");
-	printf("  -i  : invert cube speed. (default OFF)\n");
-	printf("  -p  : do not display cpu-load (default OFF)\n");
-	printf("  -h  : display this helptext.\n\n");	
-}
-
-void die()
-{
-	fprintf(stderr, "%s: exiting", pname);
-	exit (1);
-}
-
-#ifndef SOLARIS 	// scan4objects doesnt work on Solaris because of alphasort
-int scan4objects(char *dir) 
-{
-	struct dirent **names;
-	int n;
-
-	n = scandir(dir,&names,0,alphasort);
-		
-	while (n-- > 0) 
-		if (strstr(names[n]->d_name,".wmc") != NULL)
-		{			
-			objects[nof_objects] = (char *)malloc(strlen(dir)+strlen(names[n]->d_name)+2);
-			strcpy(objects[nof_objects],dir);
-			if (dir[strlen(dir)] != '/') strcat(objects[nof_objects],"/");
-			strcat(objects[nof_objects++],names[n]->d_name);
-		}
-
-	return nof_objects;
-}
-#endif
-
-int next_object()
-{
-	if (nof_objects == 0) return -1;
-	setupobj(objects[rand() % (nof_objects )]);
-	
-	return 0;
-}
-
-
-int loadobj(char *filename) {
-	
-	FILE *fp;
-	char tmp[64] = {""};
-	int i = 0, counter = 1;
-
-	//printf("\nLoading file %s...",filename); fflush(stdout);
-	
-	if ((fp = fopen(filename,"rt")) == NULL) {
-		printf("\nERROR: wmCube object-file not found (%s).\n\n",filename);
-		exit(0);
-	}
-
-	fscanf(fp,"%s",tmp);
-	
-	if (strcmp(tmp,"WMCUBE_COORDINATES") != 0) { 
-		printf("\nError in objectfile: it must start with WMCUBE_COORDINATES\n\n");
-		fclose(fp);
-		exit(0);
-	}
-
-	fscanf(fp,"%s",tmp);
-	counter = atoi(tmp);
-
-	while ((strcmp(tmp,"WMCUBE_LINES") != 0) && (strcmp(tmp,"WMCUBE_PLANES") != 0)) {		
-
-	 	matrix = (float **)realloc(matrix,(i+1)*sizeof(float *)); mem_alloc_error(matrix);
-		matrix[i] = (float *)malloc(3*sizeof(float)); mem_alloc_error(matrix[i]);
-		fscanf(fp,"%f %f %f",&matrix[i][0],&matrix[i][1],&matrix[i][2]);
-		//printf("\n%d: %f %f %f",atoi(tmp), matrix[i][0],matrix[i][1],matrix[i][2]);
-
-		if (atoi(tmp) != (++i)) { 
-			
-			printf("\nError in objectfile (WMCUBE_COORDINATES section):\n"
-					 "the coordinates must be listed in order 1..n\n\n");
-			fclose(fp);
-			exit(0);
-		}
-		fscanf(fp,"%s",tmp);
-
-		if (feof(fp)) {
-			printf("\nError in objectfile: you must have a section WMCUBE_LINES or WMCUBE_PLANES\n\n");
-			fclose(fp);
-			exit(0);
-		}
-	}
- 
-	nofcoords = i;
-	i = 0;
-
-	if (strcmp(tmp,"WMCUBE_LINES") == 0) {
-
-		planesORlines = 0;
-		while (1) {
-		
-			cline = (int *)realloc(cline,(i+2)*sizeof(int)); mem_alloc_error(cline);
-			fscanf(fp,"%d %d",&cline[i++],&cline[i++]);
-			//printf("\n%d %d",cline[i-2],cline[i-1]);
-			if (feof(fp)) break;
-		
-			if (cline[i-2] > nofcoords || cline[i-1] > nofcoords) { 
-				printf("\nError in objectfile (WMCUBE_LINES section):\n"
-					   "coordinates %d or/and %d doesnt exist\n\n",cline[i-2],cline[i-1]);
-				fclose(fp);
-				exit(0);
-			}
-		}
-		noflines = i-2;
-	}
-	else if (strcmp(tmp,"WMCUBE_PLANES") == 0) {
-	
-		planesORlines = 1;
-		while (1) {	
-			planes = (int **)realloc(planes,(i+1)*sizeof(int *)); mem_alloc_error(planes);
-			planes[i] = (int *)malloc(3*sizeof(int)); mem_alloc_error(planes[i]);
-			fscanf(fp,"%d %d %d",&planes[i][0],&planes[i][1],&planes[i][2]);
-			//printf("\n%d: %d %d %d",i,planes[i][0],planes[i][1],planes[i][2]);
-
-			planes[i][0]--; planes[i][1]--; planes[i][2]--;
-			//printf("\n%d: %d %d %d\n",i,planes[i][0],planes[i][1],planes[i][2]);
-			
-			if (feof(fp)) break;
-		
-			if (planes[i][0] > nofcoords || planes[i][1] > nofcoords || planes[i][2] > nofcoords) { 
-				printf("\nError in objectfile (WMCUBE_PLANES section):\n"
-				 	   "coordinates %d or/and %d or/and %d doesnt exist\n\n",planes[i][0],planes[i][1],planes[i][2]);
-				fclose(fp);
-				exit(0);
-			}
-			i++;		
-		}
-		nofplanes = i;
-		plane_color =	(int *)malloc(nofplanes*sizeof(int)); mem_alloc_error(plane_color);
-		zorder =		(int *)malloc(nofplanes*sizeof(int)); mem_alloc_error(zorder);
-		for (i = 0; i < nofplanes; i++) zorder[i] = i;
-		
-	} else {
-		printf("\nError in objectfile: you must have a section WMCUBE_LINES or WMCUBE_PLANES\n\n");
-		fclose(fp);
-		exit(0);
-	}
-
-	fclose(fp);
-	return 1;
-}
-
-void mem_alloc_error(void *block) {
-	if (block == NULL) {
-		printf("\nError allocating memory!\n\n");
-		exit(0);
-	}
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
- * Begin System Specific Code.  If you wish to port wmcube to a new platform,
- * you'll need to implement the following operations:
- *
- * int init_calc_cpu();
- * 	Perform feature tests to determine whether wmcube can run, and set up
- * 	any files/data structures/etc. to gather statistics.
- *
- * int calc_cpu_total();
- * 	return an integer reflecting the current CPU load
- */
-
-#if defined LINUX
-
-/*
- * init_calc_cpu doesn't have much to do on Linux, but it can check to see if
- * /proc/stat is available; if the user selected to monitor a particular CPU,
- * it can check it's existence.
- */
-int init_calc_cpu()
-{
-	FILE *fp;
-	int i;
-	char cpuid[6];
-	char check_cpu[6];
-
-	sprintf(check_cpu, "cpu%d", which_cpu);
-
-	if ((fp = fopen("/proc/stat","rb")) == NULL) {
-		perror("/proc/stat required for this system");
-		return -1;
-	}
-
-	if (which_cpu == -1)
-		return 0;
-
-	for (i = -2; i < which_cpu; i++) {
-                fscanf(fp, "%s", cpuid);
-        }
-
-	if (strcmp(check_cpu,cpuid) != 0) {
-                fprintf(stderr, "ERROR: could not read cpu-load on %s. Are you "
-		    "sure you have an SMP system?\n",check_cpu);
-                return -1;
-        }
-	return (0); 
-}
-
-int calc_cpu_total() {
-	int total, used, t=0, i;
-	static int previous_total = 0, previous_used = 0;
-	char cpuid[6];
-	int cpu,nice,system,idle;
-	FILE *fp;
-	
-	fp = fopen("/proc/stat","rt");
-
-	for (i = -2; i < which_cpu; i++) {
-		fscanf(fp,"%s %d %d %d %d",cpuid,&cpu,&nice,&system,&idle);
-	}
-
-	fclose(fp);
-
-	used = cpu + system + use_nice*nice;
-	total = used + idle + (1-use_nice)*nice;
-
-	t = 100 * (double)(used - previous_used) / (double)(total - previous_total);
-	previous_total = total;
-	previous_used = used;
-	
-	return t;
-}
-
-#elif defined SOLARIS
-#include <sys/types.h>
-#include <sys/sysinfo.h>
-#include <kstat.h>
-
-static kstat_ctl_t *kc;
-static kstat_t **cpu_ksp_list;
-static kstat_t *the_cpu;
-static int ncpus;
-
-/*
- * The biggest subtlety of the Solaris port is that init_calc_cpu can be called
- * after the initial program setup.  This occurs when a 'kstat state change'
- * occurs.  Usually this means that a CPU has been taken on or off-line using
- * the psradm command.  Another possibility is that on server systems, a new
- * CPU might have been hot-added to a running system.
- *
- * As a result, init_calc_cpu frees any resources it might have setup if needed,
- * and reinitializes everything.
- */
-int init_calc_cpu()
-{
-	kstat_t *ksp;
-	int i = 0;
-
-	if (kc == NULL) {
-		if ((kc = kstat_open()) == NULL) {
-			fprintf(stderr, "wmcube: can't open /dev/kstat\n");
-			return -1;
-		}
-	}
-
-	if (which_cpu != -1) {
-		/*
-		 * User selected to monitor a particlur CPU.  find it...
-		 */
-		for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
-			if ((strcmp(ksp->ks_module, "cpu_stat") == 0) &&
-			    (ksp->ks_instance == which_cpu)) {
-				the_cpu = ksp;
-				break;
-			}
-		}
-		if (the_cpu == NULL) {
-			fprintf(stderr, "CPU %d not found\n", which_cpu);
-			return -1;
-		}
-	} else {
-		/*
-		 * User selected to monitor all CPUs.  First, count them.
-		 */
-		for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
-			if (strcmp(ksp->ks_module, "cpu_stat") == 0)
-				i++;
-		}
-
-		if (cpu_ksp_list) {
-			free(cpu_ksp_list);
-		}
-		cpu_ksp_list = (kstat_t **) calloc(i * sizeof (kstat_t *), 1); 
-		ncpus = i;
-
-		/*
-		 * stash the ksp for each CPU.
-		 */
-		i = 0;
-		for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
-			if (strcmp(ksp->ks_module, "cpu_stat") == 0) {
-				cpu_ksp_list[i] = ksp;
-				i++;
-			}
-		}
-	}
-	return 0;
-}
-
-int calc_cpu_total()
-{
-	int i;
-	cpu_stat_t stat;
-	static int previous_total = 0, previous_used = 0;
-	int used, total, t, user = 0, wait = 0, kern = 0, idle = 0;
-
-	/*
-	 * Read each cpu's data.  If the kstat chain has changed (a state change
-	 * has happened, maybe a new cpu was added to the system or one went
-	 * away), then reinitialize everything with init_calc_cpu().  Finally,
-	 * recursively call calc_cpu_total.
-	 *
-	 * We'll need to do a little better than this in the future, since we
-	 * could recurse too much in the pathological case here.
-	 */
-	if (which_cpu == -1) {
-		for (i = 0; i < ncpus; i++) {
-			if (kstat_read(kc, cpu_ksp_list[i],
-			    (void *)&stat) == -1) {
-				if (init_calc_cpu() != 0) {
-					fprintf(stderr, "failed to "
-					    "reinitialize following state "
-					    "change\n");
-					return (-1);
-				}
-				return (calc_cpu_total());
-			}
-			user += stat.cpu_sysinfo.cpu[CPU_USER];   /* user */
-			wait += stat.cpu_sysinfo.cpu[CPU_WAIT];   /* io wait */
-			kern += stat.cpu_sysinfo.cpu[CPU_KERNEL]; /* sys */
-			idle += stat.cpu_sysinfo.cpu[CPU_IDLE]; /*idle("free")*/
-		}
-	} else {
-		if (kstat_read(kc, the_cpu, (void *)&stat) == -1) {
-			if (init_calc_cpu() != 0) {
-				fprintf(stderr, "failed to reinitialize "
-				    "following state change\n");
-				return (-1);
-			}
-			return (calc_cpu_total());
-		}
-		user += stat.cpu_sysinfo.cpu[CPU_USER];    /* user */
-		wait += stat.cpu_sysinfo.cpu[CPU_WAIT];    /* io wait */
-		kern += stat.cpu_sysinfo.cpu[CPU_KERNEL];  /* sys */
-		idle += stat.cpu_sysinfo.cpu[CPU_IDLE];    /* idle("free") */
-	}
-
-	used = user + wait + kern;
-	total = used + idle;
-	t = 100 * (double)(used - previous_used) /
-	    (double)(total - previous_total);
-	previous_total = total;
-	previous_used = used;
-	return (t);
-}
-
-#elif defined FREEBSD
-#include <nlist.h>
-#include <fcntl.h>
-#include <sys/dkstat.h>
-
-int init_calc_cpu()
-{
-
-        if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
-        {
-                printf("\nError: unable to open kvm\n\n");
-                exit(0);
-        }
-        kvm_nlist(kd, nlst);
-        if (nlst[0].n_type == 0) 
-        {
-                printf("\nError: unable to get nlist\n\n");
-                exit(1);
-        }
-
-        return 0;
-}
-
-int calc_cpu_total() {
-        int total, used, t=0;
-        static int previous_total = 0, previous_used = 0;
-        int cpu,nice,system,idle;
-        unsigned long int cpu_time[CPUSTATES];
-
-        if (kvm_read(kd, nlst[0].n_value, &cpu_time, sizeof(cpu_time))
-                != sizeof(cpu_time))
-        {
-                printf("\nError reading kvm\n\n");
-                exit(0);
-        }
-
-        cpu = cpu_time[CP_USER];
-        nice = cpu_time[CP_NICE];
-        system = cpu_time[CP_SYS];
-        idle = cpu_time[CP_IDLE];
-
-        used = cpu + system + use_nice*nice;
-        total = used + idle + (1-use_nice)*nice;
-
-        t = 100 * (double)(used - previous_used) / (double)(total - previous_total);
-        previous_total = total;
-        previous_used = used;
-
-        return t;
-}
-
-#elif defined OPENBSD
-
-int init_calc_cpu()
-{
-	return 0;
-}
-
-int calc_cpu_total() {
-        double avenrun[3];
-        
-        (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
-        return(((5.0*avenrun[0] + 0.5) > 50) ? 50 : (5.0*avenrun[0] + 0.5))*2;
-}
-
-
-#elif defined NETBSD /* END OPENBSD */
-#include <sys/sched.h>
-#include <sys/sysctl.h>
-
-int init_calc_cpu () 
-{
-        return 0;
-}
-
-int calc_cpu_total ()
-{
-        static u_int64_t last_cp_time[CPUSTATES] = { 0, 0, 0, 0, 0 };
-        u_int64_t        curr_cp_time[CPUSTATES];
-        u_int64_t        total_time = 0, idle_time = 0;
-        int mib[2];
-        int i;
-        size_t ssize;
-        const int IDLE_TIME = 4;
-        const int NICE_TIME = 1;
-        
-        ssize = sizeof ( curr_cp_time );
-        mib[0] = CTL_KERN;
-        mib[1] = KERN_CP_TIME;
-        if ( sysctl ( mib, 2, curr_cp_time, &ssize, NULL, 0 ) ) { 
-                fprintf ( stderr, "wmcube: unable to read CP_TIME from sysctl()\n" );
-                exit ( 0 );
-        }
-        if ( !use_nice ) 
-                curr_cp_time[NICE_TIME] = 0;
-
-        /* NetBSD gives 5 CPUSTATES - 
-         * User, Nice, System, Interrupt, Idle 
-         */
-        idle_time = curr_cp_time[IDLE_TIME] - last_cp_time[IDLE_TIME];
-        for ( i = 0; i < CPUSTATES; i++ ) {
-                total_time += ( curr_cp_time[i] - last_cp_time[i] ); 
-                last_cp_time[i] = curr_cp_time[i];
-        }
-
-        /* Calculate the % CPU usage as the User+Nice+System+Interrupt/Total
-         * for the interval
-         */
-        return ( 100 * (int) ( total_time - idle_time ) / total_time );
-
-}
-
-#else /* END NETBSD */
-
-/*
- * This is a stub which will compile for platforms other than LINUX or SOLARIS.
- * Use these to start your port to a new platform.
- */
-int init_calc_cpu()
-{
-	return 0;
-}
-
-int calc_cpu_total()
-{
-	return 0;
-}
-
-#endif /* OS SPECIFIC CODE */
diff --git a/wmcube/wmcube.xpm b/wmcube/wmcube.xpm
deleted file mode 100644
index f72c004..0000000
--- a/wmcube/wmcube.xpm
+++ /dev/null
@@ -1,142 +0,0 @@
-/* XPM */
-static char * wmcube_xpm[] = {
-"160 100 39 1",
-" 	c blue",
-".	c #202020",
-"X	c black",
-"o	c #C7C3C7",
-"O	c #20B2AE",
-"+	c #007D71",
-"@	c #B60418",
-"#	c #00EB00",
-"$	c #283C38",
-"%	c #F7F3FF",
-"&	c #004941",
-"!	c #1A8E8A",
-"A	c #20AFAB",
-"B	c #1FACA9",
-"C	c #1EA9A5",
-"D	c #1EA5A1",
-"E	c #1DA19E",
-"F	c #1C9C99",
-"G	c #1B9894",
-"H	c #1B928F",
-"I	c #1A8E8A",
-"J	c #198985",
-"K	c #178480",
-"L	c #177F7B",
-"M	c #167A77",
-"N	c #157672",
-"P	c #14716E",
-"Q	c #136C69",
-"R	c #136764",
-"S	c #116360",
-"T	c #115E5A",
-"U	c #115D5B",
-"V	c #0F5956",
-"W	c #0F5351",
-"Y	c #0E4E4D",
-"Z	c #0E4E4C",
-"1	c #0D4A48",
-"2	c #0C4644",
-"3	c #0C4240",
-"                                                                XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                        O!",
-"                                                                .............oX......................................................o                          ",
-"                                                                .............oX......................................................o                          ",
-"                                                                .............oX......................................................o                          ",
-"    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX    .............oX......................................................o                          ",
-"    .......................................................o    .............oX......................................................o                          ",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX..............................................&&......o..........................",
-"    .......................................................o    .............oX..............................................&&......o..........................",
-"    .......................................................o    .............oX.....&&&&&&.................................&&&&&&....o..........................",
-"    .......................................................o    .............oX.....&&&&&&.................................&&&&&&....o..........................",
-"    .......................................................o    .............oX..............................................&&......o..........................",
-"    .......................................................o    .............oX..............................................&&......o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    .............oX......................................................o..........................",
-"    .......................................................o    oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo..........................",
-"    .......................................................o    .                                       OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"    .......................................................o    .                                       AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
-"    .......................................................o    .                                       BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
-"    oooooooooooooooooooooooooooooooooooooooooooooooooooooooo    .                                       CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC",
-"                                                                .                                       EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE",
-"                                                                .                                       FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
-"                                                                .                                       GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
-"                                                                .                                       HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH",
-"...............................................................................                         IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
-"..OOO.....+..+OOO+.+OOO+.+...+.+OOO+.+OOO+.+OOO+.+OOO+.+OOO+...................                         JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ",
-".O...O....O......O.....O.O...O.O.....O.........O.O...O.O...O............O......                         KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK",
-".O...O....O......O.....O.O...O.O.....O.........O.O...O.O...O............O......                         LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL",
-".+...+....+..+OOO+..OOO+.+OOO+.+OOO+.+OOO+.....+.&OOO&.+OOO+...........O.......                         MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM",
-".O...O....O..O.........O.....O.....O.O...O.....O.O...O.....O...........O.......                         NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN",
-".O...O....O..O.........O.....O.....O.O...O.....O.O...O.....O...O...O..O.....O..                         PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
-"..OOO.....O..+OOO+.+OOO+.....+.+OOO+.+OOO+.....+.+OOO+.+OOO+...+...+..O.....+..                         QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ",
-"...............................................................................                         RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR",
-"                                                                                                        SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS",
-"................................................................................................................................................................",
-".&OOO&.+OOO..+OOO+.+OOO..+OOO+.+OOO+.+OOO+.+...+...+.......+.+...+.+.....O...O.+OOO..+OOO+.+OOO+.+OOO+.+OOO+.+OOO+.+OOO+.+...+.+...+.+...+.+...+.+...+..........",
-".O...O.O...O.O.....O...O.O.....O.....O.....O...O...O.......O.O...O.O.....OO.OO.O...O.O...O.O...O.O...O.O...O.O.......O...O...O.O...O.O...O.O...O.O...O.O...O....",
-".O...O.O...O.O.....O...O.O.....O.....O.....O...O...O.......O.O..O..O.....O.O.O.O...O.O...O.O...O.O...O.O...O.O.......O...O...O.O...O.O...O..O.O..O...O....O.....",
-".+OOO+.+OOO..+.....+...+.+OOO..+OOO..+.OO+.+OOO+...+.......+.+OO&..+.....+...+.+...+.+...+.+OOO+.+O..+.+OOO..+OOO+...+...+...+.+...+.+...+..&O&..+OOO+...O......",
-".O...O.O...O.O.....O...O.O.....O.....O...O.O...O...O.......O.O..O..O.....O...O.O...O.O...O.O.....O.O.O.O...O.....O...O...O...O.O+.+O.O.O.O..O.O......O..O.......",
-".O...O.O...O.O.....O...O.O.....O.....O...O.O...O...O.......O.O...O.O.....O...O.O...O.O...O.O.....O..OO.O...O.....O...O...O...O..O+O..OO.OO.O...O.....O.O...O....",
-".+...+.+OOO..+OOO+.OOOO..+OOO+.O.....+OOO+.+...+...O...+OOO+.+...+.+OOO&.+...+.O...O.+OOO+.+.....+OOO+.+...+.+OOO+...+...&OOOO...O...O...O.+...O.+OOO+..........",
-"................................................................................................................................................................",
-"                                                                                                        TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT",
-"...............O...                                                                                     UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU",
-"...++..............                                                                                     VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
-"...++........&OOO&.                                                                                     WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW",
-".++++++++++++O...O.                                                                                     YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
-".++++++++++++O...O.                                                                                     ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
-"...++........+OOO+.                                                                                     11111111111111111111111111111111111111111111111111111111",
-"...++........O...O.                                                                                     22222222222222222222222222222222222222222222222222222222",
-".............+...+.                                                                                     33333333333333333333333333333333333333333333333333333333",
-"...................                                                                                                                                             ",
-"                                                                                                                                                                ",
-"                                                                                                                                                                ",
-"                                                                                                                                                                ",
-"                                                                                                                                                                ",
-"                                                                                                                                                                ",
-"                                                                                                                                                                ",
-"                                                                                                                                                                "};
diff --git a/wmgeneral/list.c b/wmgeneral/list.c
deleted file mode 100644
index f804b2c..0000000
--- a/wmgeneral/list.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Generic single linked list to keep various information 
-   Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-
-Author: Kresten Krab Thorup
-
-Many modifications by Alfredo K. Kojima
- 
-
-This file is part of GNU CC.
-
-GNU CC 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, or (at your option)
-any later version.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with files compiled with
-   GCC to produce an executable, this does not cause the resulting executable
-   to be covered by the GNU General Public License. This exception does not
-   however invalidate any other reasons why the executable file might be
-   covered by the GNU General Public License.  */
-
-#include "list.h"
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#include <stdlib.h>
-
-/* Return a cons cell produced from (head . tail) */
-
-INLINE LinkedList* 
-list_cons(void* head, LinkedList* tail)
-{
-  LinkedList* cell;
-
-  cell = (LinkedList*)malloc(sizeof(LinkedList));
-  cell->head = head;
-  cell->tail = tail;
-  return cell;
-}
-
-/* Return the length of a list, list_length(NULL) returns zero */
-
-INLINE int
-list_length(LinkedList* list)
-{
-  int i = 0;
-  while(list)
-    {
-      i += 1;
-      list = list->tail;
-    }
-  return i;
-}
-
-/* Return the Nth element of LIST, where N count from zero.  If N 
-   larger than the list length, NULL is returned  */
-
-INLINE void*
-list_nth(int index, LinkedList* list)
-{
-  while(index-- != 0)
-    {
-      if(list->tail)
-	list = list->tail;
-      else
-	return 0;
-    }
-  return list->head;
-}
-
-/* Remove the element at the head by replacing it by its successor */
-
-INLINE void
-list_remove_head(LinkedList** list)
-{
-  if (!*list) return;  
-  if ((*list)->tail)
-    {
-      LinkedList* tail = (*list)->tail; /* fetch next */
-      *(*list) = *tail;		/* copy next to list head */
-      free(tail);			/* free next */
-    }
-  else				/* only one element in list */
-    {
-      free(*list);
-      (*list) = 0;
-    }
-}
-
-
-/* Remove the element with `car' set to ELEMENT */
-/*
-INLINE void
-list_remove_elem(LinkedList** list, void* elem)
-{
-  while (*list)
-    {
-      if ((*list)->head == elem)
-        list_remove_head(list);
-      *list = (*list ? (*list)->tail : NULL);
-    }
-}*/
-
-INLINE LinkedList *
-list_remove_elem(LinkedList* list, void* elem)
-{
-    LinkedList *tmp;
-    
-    if (list) {
-	if (list->head == elem) {
-	    tmp = list->tail;
-	    free(list);
-	    return tmp;
-	}
-	list->tail = list_remove_elem(list->tail, elem);
-	return list;
-    }
-    return NULL;
-}
-
-
-/* Return element that has ELEM as car */
-
-INLINE LinkedList*
-list_find(LinkedList* list, void* elem)
-{
-  while(list)
-    {
-    if (list->head == elem)
-      return list;
-    list = list->tail;
-    }
-  return NULL;
-}
-
-/* Free list (backwards recursive) */
-
-INLINE void
-list_free(LinkedList* list)
-{
-  if(list)
-    {
-      list_free(list->tail);
-      free(list);
-    }
-}
-
-/* Map FUNCTION over all elements in LIST */
-
-INLINE void
-list_mapcar(LinkedList* list, void(*function)(void*))
-{
-  while(list)
-    {
-      (*function)(list->head);
-      list = list->tail;
-    }
-}
diff --git a/wmgeneral/list.h b/wmgeneral/list.h
deleted file mode 100644
index af0f22c..0000000
--- a/wmgeneral/list.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Generic single linked list to keep various information 
-   Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-Author: Kresten Krab Thorup
-
-This file is part of GNU CC.
-
-GNU CC 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, or (at your option)
-any later version.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with files compiled with
-   GCC to produce an executable, this does not cause the resulting executable
-   to be covered by the GNU General Public License. This exception does not
-   however invalidate any other reasons why the executable file might be
-   covered by the GNU General Public License.  */
-
-#ifndef __LIST_H_
-#define __LIST_H_
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-# define INLINE inline
-#else
-# define INLINE
-#endif
-
-typedef struct LinkedList {
-  void *head;
-  struct LinkedList *tail;
-} LinkedList;
-
-INLINE LinkedList* list_cons(void* head, LinkedList* tail);
-
-INLINE int list_length(LinkedList* list);
-
-INLINE void* list_nth(int index, LinkedList* list);
-
-INLINE void list_remove_head(LinkedList** list);
-
-INLINE LinkedList *list_remove_elem(LinkedList* list, void* elem);
-
-INLINE void list_mapcar(LinkedList* list, void(*function)(void*));
-
-INLINE LinkedList*list_find(LinkedList* list, void* elem);
-
-INLINE void list_free(LinkedList* list);
-
-#endif
diff --git a/wmgeneral/misc.c b/wmgeneral/misc.c
deleted file mode 100644
index 34281e2..0000000
--- a/wmgeneral/misc.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* dock.c- built-in Dock module for WindowMaker
- * 
- *  WindowMaker window manager
- * 
- *  Copyright (c) 1997 Alfredo K. Kojima
- * 
- *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "list.h"
-#include "misc.h"
-
-/*
- *----------------------------------------------------------------------
- * parse_command--
- * 	Divides a command line into a argv/argc pair.
- *---------------------------------------------------------------------- 
- */
-#define PRC_ALPHA	0
-#define PRC_BLANK	1
-#define PRC_ESCAPE	2
-#define PRC_DQUOTE	3
-#define PRC_EOS		4
-#define PRC_SQUOTE	5
-
-typedef struct {
-    short nstate;
-    short output;
-} DFA;
-
-
-static DFA mtable[9][6] = {
-    {{3,1},{0,0},{4,0},{1,0},{8,0},{6,0}},
-    {{1,1},{1,1},{2,0},{3,0},{5,0},{1,1}},
-    {{1,1},{1,1},{1,1},{1,1},{5,0},{1,1}},
-    {{3,1},{5,0},{4,0},{1,0},{5,0},{6,0}},
-    {{3,1},{3,1},{3,1},{3,1},{5,0},{3,1}},
-    {{-1,-1},{0,0},{0,0},{0,0},{0,0},{0,0}}, /* final state */
-    {{6,1},{6,1},{7,0},{6,1},{5,0},{3,0}},
-    {{6,1},{6,1},{6,1},{6,1},{5,0},{6,1}},
-    {{-1,-1},{0,0},{0,0},{0,0},{0,0},{0,0}}, /* final state */
-};
-
-char*
-next_token(char *word, char **next)
-{
-    char *ptr;
-    char *ret, *t;
-    int state, ctype;
-
-    t = ret = malloc(strlen(word)+1);
-    ptr = word;
-    
-    state = 0;
-    *t = 0;
-    while (1) {
-	if (*ptr==0) 
-	    ctype = PRC_EOS;
-	else if (*ptr=='\\')
-	    ctype = PRC_ESCAPE;
-	else if (*ptr=='"')
-	    ctype = PRC_DQUOTE;
-	else if (*ptr=='\'')
-	    ctype = PRC_SQUOTE;
-	else if (*ptr==' ' || *ptr=='\t')
-	    ctype = PRC_BLANK;
-	else
-	    ctype = PRC_ALPHA;
-
-	if (mtable[state][ctype].output) {
-	    *t = *ptr; t++;
-	    *t = 0;
-	}
-	state = mtable[state][ctype].nstate;
-	ptr++;
-	if (mtable[state][0].output<0) {
-	    break;
-	}
-    }
-
-    if (*ret==0)
-	t = NULL;
-    else
-	t = strdup(ret);
-
-    free(ret);
-    
-    if (ctype==PRC_EOS)
-	*next = NULL;
-    else
-	*next = ptr;
-    
-    return t;
-}
-
-
-extern void
-parse_command(char *command, char ***argv, int *argc)
-{
-    LinkedList *list = NULL;
-    char *token, *line;
-    int count, i;
-
-    line = command;
-    do {
-	token = next_token(line, &line);
-	if (token) {	    
-	    list = list_cons(token, list);
-	}
-    } while (token!=NULL && line!=NULL);
-
-    count = list_length(list);
-    *argv = malloc(sizeof(char*)*count);
-    i = count;
-    while (list!=NULL) {
-	(*argv)[--i] = list->head;
-	list_remove_head(&list);
-    }
-    *argc = count;
-}
-
-extern pid_t
-execCommand(char *command)
-{
-    pid_t pid;
-    char **argv;
-    int argc;
-
-    parse_command(command, &argv, &argc);
-    
-    if (argv==NULL) {
-        return 0;
-    }
-    
-    if ((pid=fork())==0) {
-        char **args;
-        int i;
-        
-        args = malloc(sizeof(char*)*(argc+1));
-        if (!args)
-          exit(10);
-        for (i=0; i<argc; i++) {
-            args[i] = argv[i];
-        }
-        args[argc] = NULL;
-        execvp(argv[0], args);
-        exit(10);
-    }
-    return pid;
-}
diff --git a/wmgeneral/misc.h b/wmgeneral/misc.h
deleted file mode 100644
index 602e1b7..0000000
--- a/wmgeneral/misc.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __MISC_H
-#define __MISC_H
-
-#include <unistd.h>
-
-extern void parse_command(char *, char ***, int *);
-
-extern pid_t execCommand(char *);
-#endif /* __MISC_H */
diff --git a/wmgeneral/wmgeneral.c b/wmgeneral/wmgeneral.c
deleted file mode 100644
index 56b7bd6..0000000
--- a/wmgeneral/wmgeneral.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
-	Best viewed with vim5, using ts=4
-
-	wmgeneral was taken from wmppp.
-
-	It has a lot of routines which most of the wm* programs use.
-
-	------------------------------------------------------------
-
-	Author: Martijn Pieterse (pieterse at xs4all.nl)
-
-	---
-	CHANGES:
-    ---
-    14/09/1998 (Dave Clark, clarkd at skyia.com)
-        * Updated createXBMfromXPM routine
-        * Now supports >256 colors
-	11/09/1998 (Martijn Pieterse, pieterse at xs4all.nl)
-		* Removed a bug from parse_rcfile. You could
-		  not use "start" in a command if a label was 
-		  also start.
-		* Changed the needed geometry string.
-		  We don't use window size, and don't support
-		  negative positions.
-	03/09/1998 (Martijn Pieterse, pieterse at xs4all.nl)
-		* Added parse_rcfile2
-	02/09/1998 (Martijn Pieterse, pieterse at xs4all.nl)
-		* Added -geometry support (untested)
-	28/08/1998 (Martijn Pieterse, pieterse at xs4all.nl)
-		* Added createXBMfromXPM routine
-		* Saves a lot of work with changing xpm's.
-	02/05/1998 (Martijn Pieterse, pieterse at xs4all.nl)
-		* changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
-		* debugged the parse_rc file.
-	30/04/1998 (Martijn Pieterse, pieterse at xs4all.nl)
-		* Ripped similar code from all the wm* programs,
-		  and put them in a single file.
-
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <stdarg.h>
-
-#include <X11/Xlib.h>
-#include <X11/xpm.h>
-#include <X11/extensions/shape.h>
-
-#include "wmgeneral.h"
-
-  /*****************/
- /* X11 Variables */
-/*****************/
-
-Window		Root;
-int			screen;
-int			x_fd;
-int			d_depth;
-XSizeHints	mysizehints;
-XWMHints	mywmhints;
-Pixel		back_pix, fore_pix;
-char		*Geometry = "";
-Window		iconwin, win;
-GC			NormalGC;
-XpmIcon		wmgen;
-Pixmap		pixmask;
-
-  /*****************/
- /* Mouse Regions */
-/*****************/
-
-typedef struct {
-	int		enable;
-	int		top;
-	int		bottom;
-	int		left;
-	int		right;
-} MOUSE_REGION;
-
-MOUSE_REGION	mouse_region[MAX_MOUSE_REGION];
-
-  /***********************/
- /* Function Prototypes */
-/***********************/
-
-static void GetXPM(XpmIcon *, char **);
-static Pixel GetColor(char *);
-void RedrawWindow(void);
-void AddMouseRegion(int, int, int, int, int);
-int CheckMouseRegion(int, int);
-
-/*******************************************************************************\
-|* parse_rcfile																   *|
-\*******************************************************************************/
-
-void parse_rcfile(const char *filename, rckeys *keys) {
-
-	char	*p,*q;
-	char	temp[128];
-	char	*tokens = " :\t\n";
-	FILE	*fp;
-	int		i,key;
-
-	fp = fopen(filename, "r");
-	if (fp) {
-		while (fgets(temp, 128, fp)) {
-			key = 0;
-			q = strdup(temp);
-			q = strtok(q, tokens);
-			while (key >= 0 && keys[key].label) {
-				if ((!strcmp(q, keys[key].label))) {
-					p = strstr(temp, keys[key].label);
-					p += strlen(keys[key].label);
-					p += strspn(p, tokens);
-					if ((i = strcspn(p, "#\n"))) p[i] = 0;
-					free(*keys[key].var);
-					*keys[key].var = strdup(p);
-					key = -1;
-				} else key++;
-			}
-			free(q);
-		}
-		fclose(fp);
-	}
-}
-
-/*******************************************************************************\
-|* parse_rcfile2															   *|
-\*******************************************************************************/
-
-void parse_rcfile2(const char *filename, rckeys2 *keys) {
-
-	char	*p;
-	char	temp[128];
-	char	*tokens = " :\t\n";
-	FILE	*fp;
-	int		i,key;
-	char	*family = NULL;
-
-	fp = fopen(filename, "r");
-	if (fp) {
-		while (fgets(temp, 128, fp)) {
-			key = 0;
-			while (key >= 0 && keys[key].label) {
-				if ((p = strstr(temp, keys[key].label))) {
-					p += strlen(keys[key].label);
-					p += strspn(p, tokens);
-					if ((i = strcspn(p, "#\n"))) p[i] = 0;
-					free(*keys[key].var);
-					*keys[key].var = strdup(p);
-					key = -1;
-				} else key++;
-			}
-		}
-		fclose(fp);
-	}
-	free(family);
-}
-
-
-/*******************************************************************************\
-|* GetXPM																	   *|
-\*******************************************************************************/
-
-static void GetXPM(XpmIcon *wmgen, char *pixmap_bytes[]) {
-
-	XWindowAttributes	attributes;
-	int					err;
-
-	/* For the colormap */
-	XGetWindowAttributes(display, Root, &attributes);
-
-	wmgen->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
-
-	err = XpmCreatePixmapFromData(display, Root, pixmap_bytes, &(wmgen->pixmap),
-					&(wmgen->mask), &(wmgen->attributes));
-	
-	if (err != XpmSuccess) {
-		fprintf(stderr, "Not enough free colorcells.\n");
-		exit(1);
-	}
-}
-
-/*******************************************************************************\
-|* GetColor																	   *|
-\*******************************************************************************/
-
-static Pixel GetColor(char *name) {
-
-	XColor				color;
-	XWindowAttributes	attributes;
-
-	XGetWindowAttributes(display, Root, &attributes);
-
-	color.pixel = 0;
-	if (!XParseColor(display, attributes.colormap, name, &color)) {
-		fprintf(stderr, "wm.app: can't parse %s.\n", name);
-	} else if (!XAllocColor(display, attributes.colormap, &color)) {
-		fprintf(stderr, "wm.app: can't allocate %s.\n", name);
-	}
-	return color.pixel;
-}
-
-/*******************************************************************************\
-|* flush_expose																   *|
-\*******************************************************************************/
-
-static int flush_expose(Window w) {
-
-	XEvent 		dummy;
-	int			i=0;
-
-	while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
-		i++;
-
-	return i;
-}
-
-/*******************************************************************************\
-|* RedrawWindow																   *|
-\*******************************************************************************/
-
-void RedrawWindow(void) {
-	
-	flush_expose(iconwin);
-	XCopyArea(display, wmgen.pixmap, iconwin, NormalGC, 
-				0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
-	flush_expose(win);
-	XCopyArea(display, wmgen.pixmap, win, NormalGC,
-				0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
-}
-
-/*******************************************************************************\
-|* RedrawWindowXY															   *|
-\*******************************************************************************/
-
-void RedrawWindowXY(int x, int y) {
-	
-	flush_expose(iconwin);
-	XCopyArea(display, wmgen.pixmap, iconwin, NormalGC, 
-				x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
-	flush_expose(win);
-	XCopyArea(display, wmgen.pixmap, win, NormalGC,
-				x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
-}
-
-/*******************************************************************************\
-|* AddMouseRegion															   *|
-\*******************************************************************************/
-
-void AddMouseRegion(int index, int left, int top, int right, int bottom) {
-
-	if (index < MAX_MOUSE_REGION) {
-		mouse_region[index].enable = 1;
-		mouse_region[index].top = top;
-		mouse_region[index].left = left;
-		mouse_region[index].bottom = bottom;
-		mouse_region[index].right = right;
-	}
-}
-
-/*******************************************************************************\
-|* CheckMouseRegion															   *|
-\*******************************************************************************/
-
-int CheckMouseRegion(int x, int y) {
-
-	int		i;
-	int		found;
-
-	found = 0;
-
-	for (i=0; i<MAX_MOUSE_REGION && !found; i++) {
-		if (mouse_region[i].enable &&
-			x <= mouse_region[i].right &&
-			x >= mouse_region[i].left &&
-			y <= mouse_region[i].bottom &&
-			y >= mouse_region[i].top)
-			found = 1;
-	}
-	if (!found) return -1;
-	return (i-1);
-}
-
-/*******************************************************************************\
-|* createXBMfromXPM															   *|
-\*******************************************************************************/
-void createXBMfromXPM(char *xbm, char **xpm, int sx, int sy) {
-
-	int		i,j,k;
-	int		width, height, numcol, depth;
-    int 	zero=0;
-	unsigned char	bwrite;
-    int		bcount;
-    int     curpixel;
-	
-	sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &depth);
-
-
-    for (k=0; k!=depth; k++)
-    {
-        zero <<=8;
-        zero |= xpm[1][k];
-    }
-        
-	for (i=numcol+1; i < numcol+sy+1; i++) {
-		bcount = 0;
-		bwrite = 0;
-		for (j=0; j<sx*depth; j+=depth) {
-            bwrite >>= 1;
-
-            curpixel=0;
-            for (k=0; k!=depth; k++)
-            {
-                curpixel <<=8;
-                curpixel |= xpm[i][j+k];
-            }
-                
-            if ( curpixel != zero ) {
-				bwrite += 128;
-			}
-			bcount++;
-			if (bcount == 8) {
-				*xbm = bwrite;
-				xbm++;
-				bcount = 0;
-				bwrite = 0;
-			}
-		}
-	}
-}
-
-/*******************************************************************************\
-|* copyXPMArea																   *|
-\*******************************************************************************/
-
-void copyXPMArea(int x, int y, int sx, int sy, int dx, int dy) {
-
-	XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
-
-}
-
-/*******************************************************************************\
-|* copyXBMArea																   *|
-\*******************************************************************************/
-
-void copyXBMArea(int x, int y, int sx, int sy, int dx, int dy) {
-
-	XCopyArea(display, wmgen.mask, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
-}
-
-
-/*******************************************************************************\
-|* setMaskXY																   *|
-\*******************************************************************************/
-
-void setMaskXY(int x, int y) {
-
-	 XShapeCombineMask(display, win, ShapeBounding, x, y, pixmask, ShapeSet);
-	 XShapeCombineMask(display, iconwin, ShapeBounding, x, y, pixmask, ShapeSet);
-}
-
-/*******************************************************************************\
-|* openXwindow																   *|
-\*******************************************************************************/
-void openXwindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bits, int pixmask_width, int pixmask_height) {
-
-	unsigned int	borderwidth = 1;
-	XClassHint		classHint;
-	char			*display_name = NULL;
-	char			*wname = argv[0];
-	XTextProperty	name;
-
-	XGCValues		gcv;
-	unsigned long	gcm;
-
-	char			*geometry = NULL;
-
-	int				dummy=0;
-	int				i, wx, wy;
-
-	for (i=1; argv[i]; i++) {
-		if (!strcmp(argv[i], "-display")) {
-			display_name = argv[i+1];
-			i++;
-		}
-		if (!strcmp(argv[i], "-geometry")) {
-			geometry = argv[i+1];
-			i++;
-		}
-	}
-
-	if (!(display = XOpenDisplay(display_name))) {
-		fprintf(stderr, "%s: can't open display %s\n", 
-						wname, XDisplayName(display_name));
-		exit(1);
-	}
-	screen  = DefaultScreen(display);
-	Root    = RootWindow(display, screen);
-	d_depth = DefaultDepth(display, screen);
-	x_fd    = XConnectionNumber(display);
-
-	/* Convert XPM to XImage */
-	GetXPM(&wmgen, pixmap_bytes);
-
-	/* Create a window to hold the stuff */
-	mysizehints.flags = USSize | USPosition;
-	mysizehints.x = 0;
-	mysizehints.y = 0;
-
-	back_pix = GetColor("white");
-	fore_pix = GetColor("black");
-
-	XWMGeometry(display, screen, Geometry, NULL, borderwidth, &mysizehints,
-				&mysizehints.x, &mysizehints.y,&mysizehints.width,&mysizehints.height, &dummy);
-
-	mysizehints.width = 64;
-	mysizehints.height = 64;
-		
-	win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
-				mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
-	
-	iconwin = XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
-				mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
-
-	/* Activate hints */
-	XSetWMNormalHints(display, win, &mysizehints);
-	classHint.res_name = wname;
-	classHint.res_class = wname;
-	XSetClassHint(display, win, &classHint);
-
-	XSelectInput(display, win, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
-	XSelectInput(display, iconwin, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
-
-	if (XStringListToTextProperty(&wname, 1, &name) == 0) {
-		fprintf(stderr, "%s: can't allocate window name\n", wname);
-		exit(1);
-	}
-
-	XSetWMName(display, win, &name);
-
-	/* Create GC for drawing */
-	
-	gcm = GCForeground | GCBackground | GCGraphicsExposures;
-	gcv.foreground = fore_pix;
-	gcv.background = back_pix;
-	gcv.graphics_exposures = 0;
-	NormalGC = XCreateGC(display, Root, gcm, &gcv);
-
-	/* ONLYSHAPE ON */
-
-	pixmask = XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width, pixmask_height);
-
-	XShapeCombineMask(display, win, ShapeBounding, 0, 0, pixmask, ShapeSet);
-	XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, pixmask, ShapeSet);
-
-	/* ONLYSHAPE OFF */
-
-	mywmhints.initial_state = WithdrawnState;
-	mywmhints.icon_window = iconwin;
-	mywmhints.icon_x = mysizehints.x;
-	mywmhints.icon_y = mysizehints.y;
-	mywmhints.window_group = win;
-	mywmhints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
-
-	XSetWMHints(display, win, &mywmhints);
-
-	XSetCommand(display, win, argv, argc);
-	XMapWindow(display, win);
-
-	if (geometry) {
-		if (sscanf(geometry, "+%d+%d", &wx, &wy) != 2) {
-			fprintf(stderr, "Bad geometry string.\n");
-			exit(1);
-		}
-		XMoveWindow(display, win, wx, wy);
-	}
-}
diff --git a/wmgeneral/wmgeneral.h b/wmgeneral/wmgeneral.h
deleted file mode 100644
index e9d6ca6..0000000
--- a/wmgeneral/wmgeneral.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef WMGENERAL_H_INCLUDED
-#define WMGENERAL_H_INCLUDED
-
-  /***********/
- /* Defines */
-/***********/
-
-#define MAX_MOUSE_REGION (16)
-
-  /************/
- /* Typedefs */
-/************/
-
-typedef struct _rckeys rckeys;
-
-struct _rckeys {
-	const char	*label;
-	char		**var;
-};
-
-typedef struct _rckeys2 rckeys2;
-
-struct _rckeys2 {
-	const char	*family;
-	const char	*label;
-	char		**var;
-};
-
-typedef struct {
-	Pixmap			pixmap;
-	Pixmap			mask;
-	XpmAttributes	attributes;
-} XpmIcon;
-
-  /*******************/
- /* Global variable */
-/*******************/
-
-Display		*display;
-
-  /***********************/
- /* Function Prototypes */
-/***********************/
-
-void AddMouseRegion(int index, int left, int top, int right, int bottom);
-int CheckMouseRegion(int x, int y);
-
-void openXwindow(int argc, char *argv[], char **, char *, int, int);
-void RedrawWindow(void);
-void RedrawWindowXY(int x, int y);
-
-void createXBMfromXPM(char *, char **, int, int);
-void copyXPMArea(int, int, int, int, int, int);
-void copyXBMArea(int, int, int, int, int, int);
-void setMaskXY(int, int);
-
-void parse_rcfile(const char *, rckeys *);
-
-#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-wmaker/wmcube.git



More information about the Pkg-wmaker-commits mailing list