[Pkg-wmaker-commits] [wmgtemp] 01/10: wmgtemp: Add verson 1.1 to repository.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Thu Feb 2 14:18:40 UTC 2017


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

dtorrance-guest pushed a commit to branch upstream
in repository wmgtemp.

commit ee333c717bdd6a04c98543933c12295ca84fad46
Author: Doug Torrance <dtorrance at piedmont.edu>
Date:   Wed Feb 1 21:51:55 2017 -0500

    wmgtemp: Add verson 1.1 to repository.
    
    From
    http://fluxcode.net/files/wmgtemp-1.1.tar.gz
---
 Artistic                       |  131 +++++
 BUGS                           |    0
 CREDITS                        |   13 +
 ChangeLog                      |  323 ++++++++++++
 INSTALL                        |    5 +
 Makefile                       |   17 +
 README                         |   42 ++
 TODO                           |   14 +
 examples/wmgtemprc             |   22 +
 src/.deps                      |    2 +
 src/Makefile                   |   32 ++
 src/wmgeneral/list.c           |  169 +++++++
 src/wmgeneral/list.h           |   59 +++
 src/wmgeneral/misc.c           |  164 ++++++
 src/wmgeneral/misc.h           |    9 +
 src/wmgeneral/wmgeneral.c      |  483 ++++++++++++++++++
 src/wmgeneral/wmgeneral.h      |   59 +++
 src/wmgtemp-interface-mask.xbm |   46 ++
 src/wmgtemp-interface.xpm      |  120 +++++
 src/wmgtemp.c                  | 1083 ++++++++++++++++++++++++++++++++++++++++
 wmgtemp.1                      |  153 ++++++
 21 files changed, 2946 insertions(+)

diff --git a/Artistic b/Artistic
new file mode 100644
index 0000000..5f22124
--- /dev/null
+++ b/Artistic
@@ -0,0 +1,131 @@
+
+
+
+
+			 The "Artistic License"
+
+				Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+	"Package" refers to the collection of files distributed by the
+	Copyright Holder, and derivatives of that collection of files
+	created through textual modification.
+
+	"Standard Version" refers to such a Package if it has not been
+	modified, or has been modified in accordance with the wishes
+	of the Copyright Holder as specified below.
+
+	"Copyright Holder" is whoever is named in the copyright or
+	copyrights for the package.
+
+	"You" is you, if you're thinking about copying or distributing
+	this Package.
+
+	"Reasonable copying fee" is whatever you can justify on the
+	basis of media cost, duplication charges, time of people involved,
+	and so on.  (You will not be required to justify it to the
+	Copyright Holder, but only to the computing community at large
+	as a market that must bear the fee.)
+
+	"Freely Available" means that no fee is charged for the item
+	itself, though there may be fees involved in handling the item.
+	It also means that recipients of the item may redistribute it
+	under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder.  A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+    a) place your modifications in the Public Domain or otherwise make them
+    Freely Available, such as by posting said modifications to Usenet or
+    an equivalent medium, or placing the modifications on a major archive
+    site such as uunet.uu.net, or by allowing the Copyright Holder to include
+    your modifications in the Standard Version of the Package.
+
+    b) use the modified Package only within your corporation or organization.
+
+    c) rename any non-standard executables so the names do not conflict
+    with standard executables, which must also be provided, and provide
+    a separate manual page for each non-standard executable that clearly
+    documents how it differs from the Standard Version.
+
+    d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+    a) distribute a Standard Version of the executables and library files,
+    together with instructions (in the manual page or equivalent) on where
+    to get the Standard Version.
+
+    b) accompany the distribution with the machine-readable source of
+    the Package with your modifications.
+
+    c) give non-standard executables non-standard names, and clearly
+    document the differences in manual pages (or equivalent), together
+    with instructions on where to get the Standard Version.
+
+    d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package.  You may charge any fee you choose for support of this
+Package.  You may not charge a fee for this Package itself.  However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own.  You may embed this Package's interpreter within
+an executable of yours (by linking); this shall be construed as a mere
+form of aggregation, provided that the complete Standard Version of the
+interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package.  If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of this Package with a commercial distribution is always
+permitted provided that the use of this Package is embedded; that is,
+when no overt attempt is made to make this Package's interfaces visible
+to the end user of the commercial distribution.  Such use shall not be
+construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+				The End
diff --git a/BUGS b/BUGS
new file mode 100644
index 0000000..e69de29
diff --git a/CREDITS b/CREDITS
new file mode 100644
index 0000000..dcd643a
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,13 @@
+Here are a list of people that have contributed to the project
+and whose help and advice is greatly appreciated.
+
+Damian Kramer <psiren at hibernaculum.demon.co.uk>
+Jon Kinred <compart at one.net.au> - W83781D, W83627HF support.
+William Martin <bill at dunfoamin.org> - AS99127F support.
+Dennis Schneider <sdans at web.de> - ADM1021 support.
+Per Larsson <albatorsk at comatosehitmen.com> IT87 support.
+Antti Pyykko <pyksy at pyksy.fi> - lm_sensors3 support, -c option.
+Ben Spencer <dangerous.ben at gmail.com> - drawing fix.
+Robert Cernansky <hslists at zoznam.sk> - testing.
+Ludwig Nussel <lugwig.nussell at web.de> - removed usleep, bugfixes.
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..d1d20b3
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,323 @@
+Project Version : rel-1_1
+2010-06-21 11:54  kronos
+
+	* src/: wmgtemp-interface.xpm, wmgtemp.c: applied patch from Ludwig
+	  Nussell re: t flag and degree drawing
+
+2010-06-21 11:54  kronos
+
+	* CREDITS: applied path from Ludwig Nussell re: t flag and degree
+	  drawing
+
+2010-03-26 21:27  kronos
+
+	* CREDITS: dev
+
+2010-03-26 21:22  kronos
+
+	* BUGS: rc segfault bug fixed
+
+2010-03-26 21:21  kronos
+
+	* CREDITS: minor update
+
+2010-03-26 21:15  kronos
+
+	* wmgtemp.1: update man page
+
+2010-03-26 21:09  kronos
+
+	* CREDITS, src/wmgtemp.c, src/wmgeneral/wmgeneral.c: fixed segfault
+	  in wmgeneral. compiles with lm_sensors3, can now specify the
+	  sensors config. added chip selection option
+
+2007-06-14 11:01  kronos
+
+	* Makefile, wmgtemp.1, src/Makefile, src/wmgtemp.c: merged patch
+	  from Josip Rodin and Lugwig Nussel
+
+2003-06-10 19:33  kronos
+
+	* src/wmgtemp.c: added version to help screen
+
+2003-06-10 19:29  kronos
+
+	* README, wmgtemp.1, examples/wmgtemprc, src/wmgtemp.c: added
+	  feature1/2 options, added quiet option
+
+2003-03-12 00:57  kronos
+
+	* CREDITS, src/wmgtemp.c: removed multiline string literal,
+	  deprecated in gcc-3.2
+
+2002-06-14 02:21  kronos
+
+	* README, src/Makefile: now usiing dynamic chipset detection
+
+2002-02-24 21:27  kronos
+
+	* wmgtemp.1: removed suported sensors stuff
+
+2002-02-24 21:24  kronos
+
+	* CREDITS: fixed typo in email
+
+2002-02-24 21:19  kronos
+
+	* src/wmgtemp.c: switched t autodetection of chips
+
+2001-06-09 03:49  kronos
+
+	* CREDITS, README, wmgtemp.1, src/wmgtemp.c: merged in ADM1021
+	  support re Dennis Schneider <sdans at wed.de>. Added temperature
+	  swapping
+
+2001-04-17 01:53  kronos
+
+	* README: added AS99127F to sensor  lis
+
+2001-04-17 01:48  kronos
+
+	* src/wmgtemp.1x: removed coz i wrote a better one and added it
+	  somewhere else and forgot about this one
+
+2001-04-17 01:45  kronos
+
+	* Makefile: Modified manpage install - actually works this time,
+	  that'll teach me for doing it at work and not testing it ;)
+
+2001-04-17 01:45  kronos
+
+	* wmgtemp.1: HELP for ckable tempscale indicator - cycling.
+
+2001-04-17 01:44  kronos
+
+	* src/wmgtemp.c: Added clickable tempscale indicator - cycling.
+
+2001-04-13 15:29  kronos
+
+	* INSTALL, Makefile: Added manpage install
+
+2001-04-13 02:04  kronos
+
+	* wmgtemp.1: Initial add of manpage
+
+2001-04-13 02:02  kronos
+
+	* CREDITS, src/wmgtemp.c: Added support for AS99127F and fixed the
+	  bug that stopped the temps being displayed in other scales
+
+2001-02-28 20:55  kronos
+
+	* src/wmgtemp.c: Corrected help screen defailt temps for min and
+	  max
+
+2001-02-28 20:53  kronos
+
+	* TODO: updated with doneness
+
+2001-02-28 20:41  kronos
+
+	* src/wmgtemp-interface.xpm: Changed high temp viewing indicator
+	  light to amber
+
+2001-02-28 20:34  kronos
+
+	* src/wmgtemp.c: Fixed typo in help, removed extra -h flag on help
+	  screen, correct processing of -u flag.
+
+2001-02-28 16:50  kronos
+
+	* src/wmgtemp.c: Changed summink to test email notification
+
+2001-02-28 16:47  kronos
+
+	* src/wmgtemp.c: testing email notifications
+
+2001-02-28 14:48  kronos
+
+	* src/wmgtemp.c: Fixed lagging screen drawing
+
+2001-02-28 14:47  kronos
+
+	* examples/wmgtemprc: Initial add
+
+2001-02-28 14:46  kronos
+
+	* BUGS: added blurb
+
+2001-02-27 20:57  kronos
+
+	* README: Added guff
+
+2001-02-27 20:34  kronos
+
+	* BUGS: Added
+
+2001-02-27 20:28  kronos
+
+	* src/: wmgtemp-interface.xpm, wmgtemp.c: Changed commandline
+	  processing to getopt, Added rcfile processing, Added MAX temp
+	  viewing indicator light
+
+2001-02-26 20:45  kronos
+
+	* src/: wmgtemp-interface.xpm, wmgtemp.c: Last commit added support
+	  for W83781D and W83627HF. This: Added support for optional
+	  displaying of CPU/SYS temp on graph.
+
+2001-02-26 17:15  kronos
+
+	* src/: wmgtemp-interface.xpm, wmgtemp.c: Added HIGH temp
+	  displaying, execing of command at given temp
+
+2001-02-26 14:15  kronos
+
+	* CREDITS: Added note for Jon Kinred <compart at one.net.au>
+
+2001-02-26 14:14  kronos
+
+	* src/wmgtemp.c: W83781D, W83627HF support.
+
+2001-02-23 21:01  kronos
+
+	* src/wmgtemp.1x: Added manpage
+
+2001-02-22 21:13  kronos
+
+	* INSTALL: updated instructions
+
+2001-02-22 21:12  kronos
+
+	* Makefile: Added missing install option
+
+2001-02-22 21:08  kronos
+
+	* TODO: checked off completed ideas
+
+2001-02-22 20:57  kronos
+
+	* src/wmgtemp.c: Converted to use signals - xevents weren't being
+	  handled in a timely manner
+
+2001-02-22 20:22  kronos
+
+	* src/wmgtemp.c: Code cleanup
+
+2001-02-21 20:38  kronos
+
+	* src/wmgtemp.c: moved drawing of range lines
+
+2001-02-21 20:05  kronos
+
+	* src/: wmgtemp-interface.xpm, wmgtemp.c: Revamped graph rescaling,
+	  not so zoomy
+
+2001-02-16 19:42  kronos
+
+	* src/wmgtemp.c: Updated usage
+
+2001-02-16 19:40  kronos
+
+	* src/Makefile: Added 'depend' back in, oops!
+
+2001-02-16 19:40  kronos
+
+	* src/.deps: New
+
+2001-02-16 19:33  kronos
+
+	* src/wmgtemp.c: tidied a few things
+
+2001-02-16 19:29  kronos
+
+	* src/Makefile: removed 'depend', not needed
+
+2001-02-16 19:23  kronos
+
+	* src/: .xvpics/wmgtemp-interface.xpm, .xvpics/wmlm_master.xpm,
+	  .deps: Removed, shouldn't be maintained by cvs
+
+2001-02-16 19:06  kronos
+
+	* CREDITS: Initial
+
+2001-02-16 18:56  kronos
+
+	* TODO: Checked off completed items
+
+2001-02-16 18:53  kronos
+
+	* src/wmgtemp.h: Removed coz it ain't needed
+
+2001-02-16 18:48  kronos
+
+	* src/: wmgtemp.c: Added CPU temp warning lights
+
+2001-02-16 14:55  kronos
+
+	* src/wmgtemp.c: Got rid of a few of the if's in temperature
+	  scaling
+
+2001-02-16 14:46  kronos
+
+	* src/: wmgtemp.c, wmgtemp.h: Modified graph to scale on the fly
+	  depending on temperature ranges of displayed values.
+
+2001-02-09 21:52  kronos
+
+	* src/wmgtemp.c: added checking for invalid delay
+
+2001-02-09 21:50  kronos
+
+	* src/wmgtemp.c: corrected update delay message
+
+2001-02-09 21:46  kronos
+
+	* src/wmgtemp.c: changed error message for unsupported chip
+
+2001-02-09 21:40  kronos
+
+	* src/: wmgtemp-interface.xpm, wmgtemp.c, wmgtemp.h: Adding
+	  structure to make supporting other chipssets easier
+
+2001-02-07 18:58  kronos
+
+	* TODO: added ideas while i still remember them
+
+2001-02-07 18:52  kronos
+
+	* src/wmgtemp.c: added usage for block and line
+
+2001-02-07 18:51  kronos
+
+	* TODO: added ideas while i still remember them
+
+2001-02-07 18:47  kronos
+
+	* Artistic, INSTALL, README, TODO: Initial
+
+2001-02-07 18:34  kronos
+
+	* src/: wmgtemp.c, wmgtemp.h: added rudimentary graph drawing
+
+2001-02-07 17:28  kronos
+
+	* Makefile, src/.deps, src/Makefile,
+	  src/wmgtemp-interface-mask.xbm, src/wmgtemp-interface.xpm,
+	  src/wmgtemp.c, src/wmgtemp.h, src/wmgeneral/misc.c,
+	  src/wmgeneral/misc.h, src/wmgeneral/wmgeneral.c,
+	  src/wmgeneral/wmgeneral.h, src/wmgeneral/list.c,
+	  src/wmgeneral/list.h, src/.xvpics/wmgtemp-interface.xpm,
+	  src/.xvpics/wmlm_master.xpm: Initial revision
+
+2001-02-07 17:28  kronos
+
+	* Makefile, src/.deps, src/Makefile,
+	  src/wmgtemp-interface-mask.xbm, src/wmgtemp-interface.xpm,
+	  src/wmgtemp.c, src/wmgtemp.h, src/wmgeneral/misc.c,
+	  src/wmgeneral/misc.h, src/wmgeneral/wmgeneral.c,
+	  src/wmgeneral/wmgeneral.h, src/wmgeneral/list.c,
+	  src/wmgeneral/list.h, src/.xvpics/wmgtemp-interface.xpm,
+	  src/.xvpics/wmlm_master.xpm: initial import of tidied up version
+
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..bd5f9d2
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,5 @@
+1.	make depend
+2.	make
+3.	su root
+4.	make install
+5.	make install.man (optional)
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1d5e696
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+INSTALL=install
+MANINSTDIR=/usr/local/man/man1
+MANPAGE=wmgtemp.1
+
+all:    
+	( cd src && $(MAKE) )
+
+depend:    
+	( cd src && $(MAKE) depend )
+
+install:    
+	( cd src && $(MAKE) install INSTDIR=$(INSTDIR) )
+	$(INSTALL) -d $(MANINSTDIR)
+	$(INSTALL) -m 755 -c $(MANPAGE) $(MANINSTDIR)/$(MANPAGE)
+
+clean:
+	( cd src && $(MAKE) clean)
diff --git a/README b/README
new file mode 100644
index 0000000..8ab779e
--- /dev/null
+++ b/README
@@ -0,0 +1,42 @@
+-------------------------------------------------------------------------
+You may distribute this program under the terms of the Artistic
+License.
+                                                                           
+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 Artistic
+License for more details.
+-------------------------------------------------------------------------
+
+wmgtemp is a dock app intended for use with WindowMaker.
+It displays the CPU and SYS temperatures (both in numerically and 
+graphically) of motherboards that use the VIA686A chipset. Currently 
+this is the only chipset that is supported but I have the intention of
+adding support for other chipsets in the future.
+
+Interface Features:
+	Clicking on the temperature toggles displaying of maximum reached
+	temperature. This mode is indicated by a green upward pointing
+	arrow to the left of the temperature.
+
+	Clicking on CPU or SYS toggles displaying of that temperature
+	type on the graph. The temperature value will still be displayed
+	numerically however.
+
+	Clicking on the Graph area will cycle through the graph types.
+
+	When the bounds of the graph are exceeded the graph will be rescaled
+	the show the current temperature and a line will be drawn to indicate
+	the bound(red for upper bound, blue for lower bound). As soon as
+	all temperatures being displayed are within a bound, the graph will
+	be rescaled back to normal size.
+
+Supported Sensors:
+	  Unlike other versions, this version tries to auto detects sensors.
+	  This means it should work with any sensors that lm_sensors supports.
+
+
+
+Send any bug reports and ideas to:
+
+Roger Dunce (kronos at fluxcode.net)
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..b6b83d9
--- /dev/null
+++ b/TODO
@@ -0,0 +1,14 @@
+o  Make the graph scalable. - DONE
+o  Add temperature range indicators. - DONE (warning lights)
+o  Add support for windowmaker properties rather than crappy command line
+   flags that are used currently.
+o  Put proper installation together.
+o  Add support for more chipsets
+o  Add abitily to change graph types by clicking on graph area. - DONE
+o  Add max reached temps, eg click CPU and temp is displayed in a different
+   colour and displays the maximum temp.(possibly draws a horizontal line in 
+   the graph too to indcate where that lies on current graph) - DONE:
+     Simply changes the colour of the temperature value to red.
+     Independant clicking of CPU and SYS temps.
+   
+o  Add ability to exec a program when a given temp is reached. - DONE
\ No newline at end of file
diff --git a/examples/wmgtemprc b/examples/wmgtemprc
new file mode 100644
index 0000000..5721130
--- /dev/null
+++ b/examples/wmgtemprc
@@ -0,0 +1,22 @@
+# Graph style, 'block' or 'line', 'b' and 'l' for the lazy
+graph: block
+# Scale type, 'celcius', 'fahrenheit' or 'kelvin', 'c', 'f' or 'k' for the lazy.
+scale: celcius
+# High CPU temperature (red light)
+high: 50
+# Warning CPU temperature(amber light)
+warn: 45
+# Upper bound of graph
+max: 35
+# Lower bound of graph
+min: 20
+# Execute a command at this temperature
+execat: 80
+# What to execute at the above temperature.
+exec: xmessage "Ouch, I'm HOT!"
+# Update delay in seconds
+update: 2
+# Use temp3 for second sensor
+feature2:temp3
+# Be quiet
+quiet:y
diff --git a/src/.deps b/src/.deps
new file mode 100755
index 0000000..5abdddc
--- /dev/null
+++ b/src/.deps
@@ -0,0 +1,2 @@
+wmgtemp.o: wmgtemp.c wmgeneral/wmgeneral.h wmgeneral/misc.h \
+ wmgtemp-interface.xpm wmgtemp-interface-mask.xbm
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..49a761d
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,32 @@
+CC      = gcc
+INSTALL = /usr/bin/install
+LIB     = lib
+LDFLAGS = -L/usr/X11R6/$(LIB) -lXpm -lXext -lX11 -lsensors
+BINARY  = wmgtemp
+CCFLAGS = -Wall -g
+INSTDIR = /usr/local/bin
+
+OFILES  = wmgtemp.o \
+	./wmgeneral/wmgeneral.o \
+	./wmgeneral/misc.o \
+	./wmgeneral/list.o
+
+%.o:
+	$(CC) $(CCFLAGS) -c $*.c -o $*.o
+
+$(BINARY): $(OFILES)
+	$(CC) $(OFILES) $(LDFLAGS) -o $(BINARY)
+
+clean:
+	@ $(RM) $(OFILES) *~ "#"* $(BINARY)
+
+install::
+	$(INSTALL) -m 755 -c $(BINARY) $(INSTDIR)/$(BINARY)
+
+depend:
+	@ $(CC) -MM *.c > .deps
+
+count:
+	@ wc -l *.c *.h | sort
+
+include .deps
diff --git a/src/wmgeneral/list.c b/src/wmgeneral/list.c
new file mode 100644
index 0000000..f804b2c
--- /dev/null
+++ b/src/wmgeneral/list.c
@@ -0,0 +1,169 @@
+/* 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/src/wmgeneral/list.h b/src/wmgeneral/list.h
new file mode 100644
index 0000000..af0f22c
--- /dev/null
+++ b/src/wmgeneral/list.h
@@ -0,0 +1,59 @@
+/* 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/src/wmgeneral/misc.c b/src/wmgeneral/misc.c
new file mode 100644
index 0000000..34281e2
--- /dev/null
+++ b/src/wmgeneral/misc.c
@@ -0,0 +1,164 @@
+/* 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/src/wmgeneral/misc.h b/src/wmgeneral/misc.h
new file mode 100644
index 0000000..602e1b7
--- /dev/null
+++ b/src/wmgeneral/misc.h
@@ -0,0 +1,9 @@
+#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/src/wmgeneral/wmgeneral.c b/src/wmgeneral/wmgeneral.c
new file mode 100644
index 0000000..30c39bf
--- /dev/null
+++ b/src/wmgeneral/wmgeneral.c
@@ -0,0 +1,483 @@
+/*
+	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, *t;
+	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);
+			t = strtok(q, tokens);
+			if(t) {
+				while (key >= 0 && keys[key].label) {
+					if ((!strcmp(t, 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/src/wmgeneral/wmgeneral.h b/src/wmgeneral/wmgeneral.h
new file mode 100644
index 0000000..e9d6ca6
--- /dev/null
+++ b/src/wmgeneral/wmgeneral.h
@@ -0,0 +1,59 @@
+#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
diff --git a/src/wmgtemp-interface-mask.xbm b/src/wmgtemp-interface-mask.xbm
new file mode 100644
index 0000000..aadcedd
--- /dev/null
+++ b/src/wmgtemp-interface-mask.xbm
@@ -0,0 +1,46 @@
+/* Created with The GIMP */
+#define wmgtemp_interface_mask_width 62
+#define wmgtemp_interface_mask_height 62
+static unsigned char wmgtemp_interface_mask_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+   0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3f };
diff --git a/src/wmgtemp-interface.xpm b/src/wmgtemp-interface.xpm
new file mode 100644
index 0000000..af270e7
--- /dev/null
+++ b/src/wmgtemp-interface.xpm
@@ -0,0 +1,120 @@
+/* XPM */
+static char * wmgtemp_interface_xpm[] = {
+"83 90 27 1",
+" 	c None",
+".	c #0000FF",
+"+	c #202020",
+"@	c #00FFFF",
+"#	c #1C8C8C",
+"$	c #004941",
+"%	c #000000",
+"&	c #333133",
+"*	c #666366",
+"=	c #202322",
+"-	c #999599",
+";	c #22332F",
+">	c #20B2AE",
+",	c #188A86",
+"'	c #212F2C",
+")	c #C7C3C7",
+"!	c #202121",
+"~	c #0D4039",
+"{	c #202423",
+"]	c #06443D",
+"^	c #FF0000",
+"/	c #451A1A",
+"(	c #07C907",
+"_	c #00FF00",
+":	c #D99800",
+"<	c #E0BA00",
+"[	c #AA0000",
+"..............................................................   +@#$ $$           ",
+".%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&*   +@#$ $$           ",
+".%++++++++++++++++++++++++++++++++++++++=+++=+=++++++++=+++++-   +@#$ >>           ",
+".%+++++++++;>>>,+,>>>,+,$$$,+++$++;$$$;+;$$$;+'$$$;+>>+'$$$;+)   +@#$ >>           ",
+".%+++;$;+++>+++$+>+++>+>+++>++;$;+$+++$+$+++$+$+++$+>>+$+++$+)   +@#$              ",
+".%++;$$$;++>+++$+>+++>+>+++>++$$$+$+++$+$+++$!~+++$++++$+++~!)   +@#$              ",
+".%++$$$$$++,$$$;+,>>>,+,$$$,++++++;$$$;=;$$$;!;$$$;=++='$$$;{)   +@#$              ",
+".%++;$$$;++>+++$+>+++$+>+++>++++++$+++$+$+++$+$+++$++++$+++$+)   +@#$              ",
+".%+++;$;+++>+++$+>+++$+>+++>++++++]+++$+$+++$+$+++$++++$+++$+)   +@#$              ",
+".%+++++++++;>>>,+,$$$;+,>>>,++++++'$$$;+;$$$;='$$$;=+++;$$$;+)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   +@#$              ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)                     ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   ;>>>,+,>>>,+,$$$, ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   >+++$+>+++>+>+++> ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   >+++$+>+++>+>+++> ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   ,$$$;+,>>>,+,$$$, ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   >+++$+>+++$+>+++> ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   >+++$+>+++$+>+++> ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   ;>>>,+,$$$;+,>>>, ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   ,>>>,+,$$$,+,>>>, ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   >+++$+>+++>+>+++$ ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   >+++$+>+++>+>+++$ ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   ,>>>,+,>>>,+,>>>, ",
+".%$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$)   $+++>+$+>+$+$+++> ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)   $+++>+$+>+$+$+++> ",
+".%+++++++++,>>>,+,$$$,+,>>>,+++$++;$$$;+;$$$;+;$$$;+>>+;$$$;+)   ,>>>,+;$>$;+,>>>, ",
+".%+++;$;+++>+++$+>+++>+>+++$++;$;+$+++$+$+++$+$+++$+>>+$+++$+)                     ",
+".%++;$$$;++>+++$+>+++>+>+++$++$$$+$+++$+$+++$+$+++$++++$+++$+)                     ",
+".%++$$$$$++,>>>,+,>>>,+,>>>,++++++;$$$;+;$$$;+;$$$;++++;$$$;+)                     ",
+".%++;$$$;++$+++>+$+>+$+$+++>++++++$+++$+$+++$+$+++$++++$+++$+)                     ",
+".%+++;$;+++$+++>+$+>+$+$+++>++++++$+++$+$+++$+$+++$++++$+++$+)                     ",
+".%+++++++++,>>>,+;$>$;+,>>>,++++++;$$$;+;$$$;+;$$$;++++;$$$;+)                     ",
+".%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)                     ",
+".&-)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))                     ",
+"                                                                                   ",
+"                                                                                   ",
+"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+;>>>;+;$$$,+,>>>,+,>>>,+,$$$,+,>>>,+,>>>,+,>>>,+,>>>,+,>>>,+;>>>,+,>>>,+,$$$,;$$$;",
+"+>+++>+$+++>+$+++>+$+++>+>+++>+>+++$+>+++$+$+++>+>+++>+>+++>+>+++$+>+++$+>+++>$+++$",
+"+>+++>+$+++>+$+++>+$+++>+>+++>+>+++$+>+++$+$+++>+>+++>+>+++>+>+++$+>+++$+>+++>$+++$",
+"+,$$$,+;$$$,+,>>>,+;>>>,+,>>>,+,>>>,+,>>>,+;$$$,+,>>>,+,>>>,+,$$$;+,>>>;+,>>>;;$$$;",
+"+>+++>+$+++>+>+++$+$+++>+$+++>+$+++>+>+++>+$+++>+>+++>+$+++>+>+++$+>+++$+>+++>$+++$",
+"+>+++>+$+++>+>+++$+$+++>+$+++>+$+++>+>+++>+$+++>+>+++>+$+++>+>+++$+>+++$+>+++>$+++$",
+"+;>>>;+;$$$,+,>>>,+,>>>,+;$$$,+,>>>,+,>>>,+;$$$,+,>>>,+,>>>,+;>>>,+,$$$;+,$$$,;$$$;",
+"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                        ",
+"...........................................................                        ",
+"/;$;/+(_(++:<:+/[^[/++$+++<+                                                       ",
+";$$$;(___(:<<<:[^^^[+;$;+:<:                                                       ",
+"$$$$$_____<<<<<^^^^^+$$$+<<<                                                       ",
+";$$$;(___(:<<<:[^^^[                                                               ",
+"/;$;/+(_(++:<:+/[^[/                                                               ",
+"+++++++++++++++++++                                                                ",
+"+;>$>;+;>>>;+,;;;,+                                                                ",
+"+>+>+>+>+++>+>+++>+                                                                ",
+"+>+>+>+>+++>+>+++>+                                                                ",
+"+,$$$,+,>>>,+;>>>;+                                                                ",
+"+>+++>+>+++>+>+++>+                                                                ",
+"+>+++>+>+++>+>+++>+                                                                ",
+"+,;;;,+,$$$,+,;;;,+                                                                ",
+"+++++++++++++++++++                                                                ",
+"                                                                                   "};
diff --git a/src/wmgtemp.c b/src/wmgtemp.c
new file mode 100644
index 0000000..b8951c7
--- /dev/null
+++ b/src/wmgtemp.c
@@ -0,0 +1,1083 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <time.h>
+#include <X11/Xlib.h>
+#include <X11/xpm.h>
+#include <X11/extensions/shape.h>
+#include <sensors/sensors.h>
+#include <sensors/error.h>
+#include "wmgeneral/wmgeneral.h"
+#include "wmgeneral/misc.h"
+#include "wmgtemp-interface.xpm"
+#include "wmgtemp-interface-mask.xbm"
+#include <math.h>
+#include <signal.h>
+#include <getopt.h>
+
+/* Defines */
+#define BitOff(a,x)  ((void)((a) &= ~(1 << (x))))
+#define BitOn(a,x)   ((void)((a) |=  (1 << (x))))
+#define BitFlip(a,x) ((void)((a) ^=  (1 << (x))))
+#define IsOn(a,x)    ((a) & (1 << (x)))
+
+// Display flags.
+#define CPU               0
+#define SYS               1
+#define WARN_NONE         2
+#define WARN_WARN         3
+#define WARN_HIGH         4
+#define TSCALE_CELCIUS    5
+#define TSCALE_FAHRENHEIT 6
+#define TSCALE_KELVIN     7
+#define GRAPH_LINE        8
+#define GRAPH_BLOCK       9
+#define HIGH_CPU         10
+#define HIGH_SYS         11
+
+#define D_MIN 0
+#define D_MAX 1
+
+#define CPU_YPOS 3
+#define SYS_YPOS 53
+
+#define BLOCK 0
+#define LINE  1
+
+#define DEBUG 0 /* 0 disable 1 enable  */
+
+#define OPT_STRING "g:sS:hH:w:m:M:a:e:u:1:2:c:tq"
+
+#define TEMPTOFAHRENHEIT(t) ((int)((t * (1.8) + 32)))
+#define TEMPTOKELVIN(t)     ((int)(t + 273))
+#define TEMPTOCELCIUS(t)    (t)
+#define TEMPTODISPLAYSCALE(temp, display_flags) (IsOn((display_flags), TSCALE_CELCIUS) ? TEMPTOCELCIUS((temp)) : (IsOn((display_flags), TSCALE_KELVIN) ? TEMPTOKELVIN((temp)) : TEMPTOFAHRENHEIT((temp))))
+
+/* Prototypes */
+int init_sensors();
+int process_config(int argc, char **argv);
+int recompute_range(double cpu_high, double cpu_low, double sys_high, double sys_low);
+void display_usage();
+void process_xevents();
+void draw_scale_indicator();
+void add_to_graph(double temp, int type, short blank, double range, int pos);
+void draw_range_line(double temp, double range, short type);
+void update_display();
+void update_sensor_data();
+void do_sensors(int val);
+inline double highest_temp(double *temp_array);
+inline double lowest_temp(double *temp_array);
+inline void draw_temp(short value, int type);
+inline void draw_warning_lights(double current_temp);
+inline void draw_max(int type);
+inline void blank_max(int type);
+inline void draw_type(int type);
+inline void blank_type(int type);
+inline void cycle_temptype();
+
+/* Globals */
+int delay      = 1;
+const sensors_chip_name *name;
+char *exec_app = NULL;
+char *rc_config = NULL;
+
+short SENSOR_DISP   = 0;
+int SUBFEAT_NUM_CPU = 0;
+int SUBFEAT_NUM_SYS = 0;
+
+double cpu_history[59];
+double sys_history[59];
+
+double display_min = 20;
+double display_max = 35;
+
+double range_upper = 35;
+double range_lower = 20;
+double range_step  = 5.0;
+
+double warn_temp = 45;
+double high_temp = 50;
+
+double run_cpu_high = 0;
+double run_sys_high = 0;
+
+double execat       = 0;
+short  execed       = 0;
+short  swap_types   = 0;
+
+char *sensor_feature1 = "temp1";
+char *sensor_feature2 = "temp2";
+char *sensor_chip = NULL;
+
+short quiet = 0;
+
+int main(int argc, char **argv) {
+  char *chipname = NULL;
+  int chip_nr = 0;
+  int i = 0;
+  int tmp_swap;
+
+  const sensors_feature* feature = NULL;
+  const sensors_subfeature* subfeature_cpu = NULL;
+  const sensors_subfeature* subfeature_sys = NULL;
+  short chip_found = -1;
+
+  BitOn(SENSOR_DISP, WARN_NONE);
+  BitOn(SENSOR_DISP, TSCALE_CELCIUS);
+  BitOn(SENSOR_DISP, GRAPH_LINE);
+
+  /* *conffname = "/etc/sensors3.conf";  */
+
+  if(!process_config(argc, argv)) {
+    exit(-1);
+  }
+  
+  if(!init_sensors()) {
+    exit(-1);
+  }
+  
+  /* Get the chip name */
+  name = sensors_get_detected_chips(NULL, &chip_nr);
+  while(name != NULL && chip_found == -1) {
+    if (!sensor_chip || strcmp(name->prefix, (const char *)sensor_chip) == 0) {
+      i = 0;
+      while ((feature = sensors_get_features(name, &i))) {
+        if(strcmp(feature->name, (const char *)sensor_feature1) == 0) {
+          subfeature_cpu = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
+          SUBFEAT_NUM_CPU = subfeature_cpu->number;
+          BitOn(SENSOR_DISP, CPU);
+          chip_found = 1;
+        }
+        if(strcmp(feature->name, (const char *)sensor_feature2) == 0) {
+          subfeature_sys = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
+          SUBFEAT_NUM_SYS = subfeature_sys->number;
+          BitOn(SENSOR_DISP, SYS);
+          chip_found = 1;
+        }
+      }
+    }
+
+    if(chip_found == 1) {
+      chipname = name->prefix;
+    }
+    else {
+      name = sensors_get_detected_chips(NULL, &chip_nr);
+    }
+  }
+  if(chip_found == -1) {
+    fprintf(stderr,"wmgtemp: Unable to find temperature sensing feature.\n");
+    exit(0);
+  }
+
+  /* output the name of the sensor if found. */
+  if(quiet == 0)
+    printf("wmgtemp: Primary Sensor - %s on %s\n", name->prefix, sensors_get_adapter_name(&name->bus));
+  
+  if(swap_types) {
+    if(quiet == 0)
+      printf("wmgtemp: swapping temps\n");
+    tmp_swap = SUBFEAT_NUM_SYS;
+    SUBFEAT_NUM_SYS = SUBFEAT_NUM_CPU;
+    SUBFEAT_NUM_CPU = tmp_swap;
+    tmp_swap = SENSOR_DISP;
+    if(IsOn(tmp_swap, CPU)) {
+      BitOn(SENSOR_DISP, SYS);
+    } else {
+      BitOff(SENSOR_DISP, SYS);
+    }
+    if(IsOn(tmp_swap, SYS)) {
+      BitOn(SENSOR_DISP, CPU);
+    } else {
+      BitOff(SENSOR_DISP, CPU);
+    }
+  }
+
+  chip_nr = 0;
+
+  openXwindow(argc, argv, wmgtemp_interface_xpm, wmgtemp_interface_mask_bits,
+	      wmgtemp_interface_mask_width, wmgtemp_interface_mask_height);
+
+  AddMouseRegion(0, 2, 12, 61, 51);  /* Graph area */
+  AddMouseRegion(1, 34, 2, 51, 11);  /* CPU temp area */
+  AddMouseRegion(2, 34, 52, 51, 61); /* SYS temp area */
+  AddMouseRegion(3, 10, CPU_YPOS, 28, CPU_YPOS + 7);  /* CPU label area */
+  AddMouseRegion(4, 10, SYS_YPOS, 28, SYS_YPOS + 7); /* SYS label area */
+  AddMouseRegion(5, 55, CPU_YPOS, 60, CPU_YPOS + 7); /* CPU C/K/F scale indicator */
+  AddMouseRegion(6, 55, SYS_YPOS, 60, SYS_YPOS + 7); /* SYS C/K/F scale indicator */
+  
+  // Add blanking of SYS and CPU for chip type.
+  // <<==---
+  if(!IsOn(SENSOR_DISP, CPU)) {
+    blank_type(CPU);
+  }
+  if(!IsOn(SENSOR_DISP, SYS)) {
+    blank_type(SYS);
+  }
+
+  draw_scale_indicator();
+
+  // Initialise the temperature arrays.
+  for(i = 0; i < 59; i++) {
+    cpu_history[i] = -1;
+    sys_history[i] = -1;
+  }
+
+  do_sensors(0);
+  RedrawWindow();
+    
+  process_xevents();
+  
+  return 0;
+}
+
+void draw_scale_indicator() {
+  if(IsOn(SENSOR_DISP, TSCALE_CELCIUS)) {
+    if(IsOn(SENSOR_DISP, CPU)) {
+      copyXPMArea(61, 65, 5, 7, 55, CPU_YPOS);
+      copyXPMArea(70,  2, 2, 2, 52, CPU_YPOS);
+    }
+    if(IsOn(SENSOR_DISP, SYS)) {
+      copyXPMArea(61, 65, 5, 7, 55, SYS_YPOS);
+      copyXPMArea(70,  2, 2, 2, 52, SYS_YPOS);
+    }
+  }
+  else if(IsOn(SENSOR_DISP, TSCALE_FAHRENHEIT)) {
+    if(IsOn(SENSOR_DISP, CPU)) {
+      copyXPMArea(67, 65, 5, 7, 55, CPU_YPOS);
+      copyXPMArea(70,  2, 2, 2, 52, CPU_YPOS);
+    }
+    if(IsOn(SENSOR_DISP, SYS)) {
+      copyXPMArea(67, 65, 5, 7, 55, SYS_YPOS);
+      copyXPMArea(70,  2, 2, 2, 52, SYS_YPOS);
+    }
+  }
+  else if(IsOn(SENSOR_DISP, TSCALE_KELVIN)) {
+    if(IsOn(SENSOR_DISP, CPU)) {
+      copyXPMArea(73, 65, 5, 7, 55, CPU_YPOS);
+      copyXPMArea(70,  0, 2, 2, 52, CPU_YPOS);
+    }
+    if(IsOn(SENSOR_DISP, SYS)) {
+      copyXPMArea(73, 65, 5, 7, 55, SYS_YPOS);
+      copyXPMArea(70,  0, 2, 2, 52, SYS_YPOS);
+    }
+  }
+}
+
+void process_xevents() {
+  int button_area = 0;
+  int* xfds = NULL;
+  int fdcount = 0;
+  struct pollfd* pfds = NULL;
+  XEvent Event;
+  Status ret;
+  time_t lastupdate = 0;
+    
+  ret = XInternalConnectionNumbers(display, &xfds, &fdcount);
+  if(!ret) {
+    fdcount = 0;
+    if(xfds) {
+      XFree(xfds);
+    }
+    xfds = NULL;
+  }
+  
+  int i;
+  pfds = (struct pollfd*)malloc((fdcount+1)*sizeof(struct pollfd));
+  if(!pfds) {
+    perror("malloc");
+    exit(EXIT_FAILURE);
+  }
+  
+  for(i=0; i < fdcount; ++i) {
+    pfds[i].fd = xfds[i];
+    pfds[i].events = POLLIN | POLLPRI;
+  }
+  
+  if(xfds) {
+    XFree(xfds);
+  }
+  
+  pfds[fdcount].fd = ConnectionNumber(display);
+  pfds[fdcount].events = POLLIN | POLLPRI;
+  
+  while(1) {
+    poll(pfds, fdcount + 1, delay * 1000);
+    
+    if(time(NULL) - lastupdate >= delay) {
+      lastupdate = time(NULL);
+      do_sensors(0);
+    }
+    
+    while(XPending(display)) {
+      XNextEvent(display, &Event);
+      switch(Event.type) {
+      case Expose:
+	RedrawWindow();
+	break;
+      case DestroyNotify:
+	XCloseDisplay(display);
+	exit(0);
+	break;
+      case ButtonRelease:
+	button_area = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
+	switch(button_area) {
+	case 0:
+	  if(IsOn(SENSOR_DISP, GRAPH_LINE)) {
+	    BitOff(SENSOR_DISP, GRAPH_LINE);
+	    BitOn(SENSOR_DISP, GRAPH_BLOCK);
+	  }
+	  else if(IsOn(SENSOR_DISP, GRAPH_BLOCK)) {
+	    BitOff(SENSOR_DISP, GRAPH_BLOCK);
+	    BitOn(SENSOR_DISP, GRAPH_LINE);
+	  }
+	  update_display();
+	  RedrawWindow();
+	  break;
+	case 1:
+	  if(IsOn(SENSOR_DISP, HIGH_CPU)) {
+	    BitOff(SENSOR_DISP, HIGH_CPU);
+	    blank_max(CPU);
+	  } 
+	  else {
+	    BitOn(SENSOR_DISP, HIGH_CPU);
+	    draw_max(CPU);
+	  }
+	  update_display();
+	  RedrawWindow();
+	  break;
+	case 2:
+	  if(IsOn(SENSOR_DISP, HIGH_SYS)) {
+	    BitOff(SENSOR_DISP, HIGH_SYS);
+	    blank_max(SYS);
+	  } 
+	  else {
+	    BitOn(SENSOR_DISP, HIGH_SYS);
+	    draw_max(SYS);
+	  }
+	  update_display();
+	  RedrawWindow();
+	  break;
+	case 3:
+	  if(SUBFEAT_NUM_CPU) {
+	    if(IsOn(SENSOR_DISP, CPU)) {
+	      BitOff(SENSOR_DISP, CPU); 
+	      blank_type(CPU);
+	    }
+	    else {
+	      BitOn(SENSOR_DISP, CPU);
+	      draw_type(CPU);
+	      draw_scale_indicator();
+	    }
+	  }
+	  update_display();
+	  RedrawWindow();
+	  break;
+	case 4:
+	  if(SUBFEAT_NUM_SYS) {
+	    if(IsOn(SENSOR_DISP, SYS)) {
+	      BitOff(SENSOR_DISP, SYS);
+	      blank_type(SYS);
+	    } 
+	    else {
+	      BitOn(SENSOR_DISP, SYS);
+	      draw_type(SYS);
+	      draw_scale_indicator();
+	    }
+	  }
+	  update_display();
+	  RedrawWindow();
+	  break;
+	case 5:
+	case 6:
+	  cycle_temptype();
+	  draw_scale_indicator();
+	  update_display();
+	  RedrawWindow();
+	  break;
+	}
+	break;
+      }
+    }
+  }
+}
+
+void do_sensors(int val) {
+
+  update_sensor_data();
+  update_display();
+  RedrawWindow();
+  
+  if(execat != 0 && cpu_history[58] >= execat && !execed) {
+    execed = 1;
+    execCommand(exec_app);
+  }
+  if(execat != 0 && cpu_history[58] < execat && execed) {
+    execed = 0;
+  }
+}
+
+
+void update_sensor_data() {
+  int i = 0;
+  double cpu_high = highest_temp(cpu_history);
+  double sys_high = highest_temp(sys_history);
+
+  /* Shift the arrays */
+  for(i = 0; i < 59; i++) {
+    cpu_history[i] = cpu_history[i + 1];
+    sys_history[i] = sys_history[i + 1];
+  }
+  
+  // Read the new values from the sensors into the temperature arrays.
+  if(IsOn(SENSOR_DISP, SYS)) sensors_get_value(name, SUBFEAT_NUM_SYS, &sys_history[58]);
+  if(IsOn(SENSOR_DISP, CPU)) sensors_get_value(name, SUBFEAT_NUM_CPU, &cpu_history[58]);
+
+  // Update the run high/low values.
+  if(cpu_high > run_cpu_high)
+    run_cpu_high = cpu_high;
+  if(sys_high > run_sys_high)
+    run_sys_high = sys_high;
+}
+
+
+void update_display() {
+  int j = 0;
+
+
+  // Rescale the display if needed.
+  while(recompute_range(highest_temp(cpu_history), lowest_temp(cpu_history),
+			highest_temp(sys_history), lowest_temp(sys_history)));
+
+  // Display warning.
+  draw_warning_lights(cpu_history[58]);
+  
+  // ReDraw temperature numbers
+  if(IsOn(SENSOR_DISP, CPU)) {
+    copyXPMArea(78, 65, 5, 7, 34, CPU_YPOS);
+    copyXPMArea(78, 65, 5, 7, 40, CPU_YPOS);
+    copyXPMArea(78, 65, 5, 7, 46, CPU_YPOS);
+    draw_temp(TEMPTODISPLAYSCALE(IsOn(SENSOR_DISP, HIGH_CPU) == 0 ? cpu_history[58] : run_cpu_high, SENSOR_DISP), CPU);
+  }
+  if(IsOn(SENSOR_DISP, SYS)) {
+    copyXPMArea(78, 65, 5, 7, 34, SYS_YPOS);
+    copyXPMArea(78, 65, 5, 7, 40, SYS_YPOS);
+    copyXPMArea(78, 65, 5, 7, 46, SYS_YPOS);
+    draw_temp(TEMPTODISPLAYSCALE(IsOn(SENSOR_DISP, HIGH_SYS) == 0 ? sys_history[58] : run_sys_high, SENSOR_DISP), SYS);
+  }
+
+
+  // ReDraw the graph
+  for(j = 0; j < 59; j++) {
+    // Clear a line
+    copyXPMArea(65, 0, 1, 39, j + 2, 12);
+    
+    if(sys_history[j] < cpu_history[j]) {
+      // Draw the temperatures on the graph.
+      if(IsOn(SENSOR_DISP, CPU)) {
+        add_to_graph(cpu_history[j], CPU, 1, range_upper - range_lower, j + 2);
+      }
+      if(IsOn(SENSOR_DISP, SYS)) {
+        add_to_graph(sys_history[j], SYS, 0, range_upper - range_lower, j + 2);
+      }
+    }
+    else {
+      if(IsOn(SENSOR_DISP, SYS)) {
+        add_to_graph(sys_history[j], SYS, 0, range_upper - range_lower, j + 2);
+      }
+      if(IsOn(SENSOR_DISP, CPU)) {
+        add_to_graph(cpu_history[j], CPU, 1, range_upper - range_lower, j + 2);
+      }
+    }
+  }
+  
+  // Draw range lines if needed
+  if(range_upper > display_max) {
+    draw_range_line(display_max, range_upper - range_lower, D_MAX);
+  }
+  if(range_lower < display_min) {
+    draw_range_line(display_min, range_upper - range_lower, D_MIN);
+  }
+}
+
+int recompute_range(double cpu_high, double cpu_low, double sys_high, double sys_low)
+{
+  short modified = 0;
+  
+  if(IsOn(SENSOR_DISP, CPU)) {
+    if(cpu_high > range_upper) {
+      range_upper += range_step;
+      modified = 1;
+    }
+    if(cpu_low < range_lower) { 
+      range_lower -= range_step;  
+      modified = 1;  
+    }  
+  }
+  if(IsOn(SENSOR_DISP, SYS)) {
+    if(sys_high > range_upper) {
+      range_upper += range_step;
+      modified = 1;
+    }
+    if(sys_low < range_lower) {  
+      range_lower -= range_step;  
+      modified = 1;  
+    }  
+  }
+  
+  // --------
+  if(IsOn(SENSOR_DISP, CPU) && IsOn(SENSOR_DISP, SYS)) {
+    if((cpu_high < (range_upper - range_step) && 
+	sys_high < (range_upper - range_step)) && 
+       (range_upper - range_step) >= display_max) {
+      range_upper -= range_step;
+      modified = 1;
+    }
+    if((cpu_low > (range_lower + range_step) && 
+	sys_low > (range_lower + range_step)) && 
+       (range_lower + range_step) <= display_min ) {  
+      range_lower += range_step;  
+      modified = 1;  
+    }  
+  }
+  else if(IsOn(SENSOR_DISP, CPU) && !IsOn(SENSOR_DISP, SYS)) {
+    if(cpu_high < (range_upper - range_step) && 
+       (range_upper - range_step) >= display_max) {
+      range_upper -= range_step;
+      modified = 1;
+    }    
+    if(cpu_low > (range_lower + range_step) && 
+       (range_lower + range_step) <= display_min) { 
+      range_lower += range_step;  
+      modified = 1;  
+    } 
+  }
+  else if(!IsOn(SENSOR_DISP, CPU) && IsOn(SENSOR_DISP, SYS)) {
+    if(sys_high < (range_upper - range_step) && 
+       (range_upper - range_step) >= display_max) {
+      range_upper -= range_step;
+      modified = 1;
+    }    
+    if(sys_low > (range_lower + range_step) && 
+       (range_lower + range_step) <= display_min) { 
+      range_lower += range_step;  
+      modified = 1;  
+    }
+  }
+
+  return modified;
+}
+
+inline double highest_temp(double *temp_array) {
+  int i = 0;
+  double high = 0;
+  for(i = 0; i < 59; i++) {
+    if(temp_array[i] > high)
+      high = temp_array[i];
+  }
+  return high;
+}
+
+inline double lowest_temp(double *temp_array) {
+  int i = 0;
+  double low = 500;
+  for(i = 0; i < 59; i++) {
+    if((temp_array[i] < low) && (temp_array[i] != -1))
+      low = temp_array[i];
+  }
+  return low;
+}
+
+void add_to_graph(double temp, int type, short blank, double range, int pos) {
+  double each = (double)39 / range;
+  short length = each * (temp - range_lower);
+
+  // Draw the graphs
+  //  if(IsOn(SENSOR_DISP, GRAPH_BLOCK)) {
+  //    copyXPMArea(type == CPU ? 67 : 68, 0, 1, length, pos, 51 - length);
+  //  }
+  //  else if(IsOn(SENSOR_DISP, GRAPH_LINE)) {
+  //    copyXPMArea(type == CPU ? 67 : 68, 0, 1, 1, pos, 51 - length);
+  //  }
+
+  // Do not draw the graphs if the temperature data does not make sense
+  // Orginially used the code above but change supplied to fix issues seen by Ben Spencer.
+  // Couldn't be arsed to find the real cause as I don't use the app myself anymore.
+  // Doesn't seem to break anything though
+  if ((temp >= range_lower) && (temp <= range_upper)) {
+    // Draw the graphs
+    if(IsOn(SENSOR_DISP, GRAPH_BLOCK)) {
+      copyXPMArea(type == CPU ? 67 : 68, 0, 1, length, pos, 51 - length);
+    }
+    else if(IsOn(SENSOR_DISP, GRAPH_LINE)) {
+      copyXPMArea(type == CPU ? 67 : 68, 0, 1, 1, pos, 51 - length);
+    }
+  }
+}
+
+
+inline void draw_temp(short value, int type) {
+  short digit;
+
+  if(value > 0) {
+    digit = value % 10;
+    copyXPMArea((digit * 6) + 1, 65, 5, 7, 46, type == CPU ? CPU_YPOS : SYS_YPOS);
+    if(value > 9) {
+      digit = ((value % 100) - digit) / 10;
+      copyXPMArea((digit * 6) + 1, 65, 5, 7, 40, type == CPU ? CPU_YPOS : SYS_YPOS);
+      if(value > 99) {
+	digit = (value - (value % 100)) / 100;
+	copyXPMArea((digit * 6) + 1, 65, 5, 7, 34, type == CPU ? CPU_YPOS : SYS_YPOS);
+      }
+    }
+  } 
+}
+
+
+inline void draw_clear_temps() {
+  if(IsOn(SENSOR_DISP, CPU)) {
+    copyXPMArea(78, 65, 5, 7, 34, CPU_YPOS);
+    copyXPMArea(78, 65, 5, 7, 40, CPU_YPOS);
+    copyXPMArea(78, 65, 5, 7, 46, CPU_YPOS);
+  }
+  if(IsOn(SENSOR_DISP, SYS)) {
+    copyXPMArea(78, 65, 5, 7, 34, SYS_YPOS);
+    copyXPMArea(78, 65, 5, 7, 40, SYS_YPOS);
+    copyXPMArea(78, 65, 5, 7, 46, SYS_YPOS);
+  }
+}
+
+void draw_range_line(double temp, double range, short type) {
+  double each = (double)39 / range;
+  short length = each * (temp - range_lower);
+
+  copyXPMArea(0, type == D_MAX ? 73 : 74, 59, 1, 2, 51 - length);
+}
+
+
+int init_sensors() {
+  FILE *config_file;
+  int res;
+
+  config_file = fopen(rc_config, "r");
+
+  if(config_file == NULL) {
+    fprintf(stderr, "Error opening %s\n", rc_config);
+    return 0;
+  }
+
+  res = sensors_init(config_file);
+
+  if(res != 0) {
+    fprintf(stderr,"Error initializing sensors: %s\n", sensors_strerror(res));
+    return 0;
+  }
+
+  if(fclose(config_file))
+    perror("Error closing sensors config");
+
+  return 1;
+}
+
+void display_usage() {
+  printf("wmgtemp v0.9\n" \
+	 "Usage: wmgtemp [options]\n" \
+	 "Options:\n" \
+	 "   -S, --sensorconf=PATH  Specify sensors config file PATH\n" \
+	 "                          [Default: /etc/sensors.conf]\n" \
+	 "   -s, --scale=SCALE      Display temperatures in SCALE\n" \
+	 "                          SCALE=kelvin, fahrenheit\n" \
+	 "                          [Default: celcius]\n" \
+	 "   -g, --graph=STYLE      Display graph as STYLE\n" \
+	 "                          STYLE=line, block\n" \
+	 "                          [Default: line]\n" \
+	 "   -H, --high=TEMP        Display red warning light at TEMP degrees celcius\n" \
+	 "                          [Default: 50]\n" \
+	 "   -w, --warn=TEMP        Display amber warning light at TEMP degrees celcius\n" \
+	 "                          [Default: 45]\n" \
+	 "   -u, --update=SEC       Update the display every SEC seconds\n" \
+	 "                          [Default: 1]\n" \
+	 "   -m, --min=TEMP         Set lower bound of the graph to TEMP degrees celcius\n" \
+	 "                          [Default: 20]\n" \
+	 "   -M, --max=TEMP         Set upper bound of the graph to TEMP degrees celcius\n" \
+	 "                          [Default: 35]\n" \
+	 "   -1, --feature1=F1      Set the feature for CPU\n" \
+	 "                          [Default: temp1]\n" \
+	 "   -2, --feature2=F2      Set the feature for SYS\n" \
+	 "                          [Default: temp2]\n" \
+	 "   -c, --chip=NAME        Use sensor chip matching NAME\n" \
+	 "                          [Default: use any]\n" \
+	 "   -a, --execat=TEMP      Execute a command at TEMP degrees celcius\n" \
+	 "   -e, --exec=COMMAND     Execute COMMAND when 'execat' temperature is reached\n" \
+	 "   -t, --swap             Swap CPU and SYS temps\n" \
+	 "   -q, --quiet            Don't display any messages\n" \
+	 "   -h, --help             Displays this help screen\n");
+}
+
+void draw_warning_lights(double current_temp) {
+  if(current_temp >= warn_temp && IsOn(SENSOR_DISP, WARN_NONE)) {
+    // Switch from ok to warning.
+    BitOff(SENSOR_DISP, WARN_NONE);
+    BitOn(SENSOR_DISP, WARN_WARN);
+    copyXPMArea(10, 75, 5, 5, 4, 4);
+  }
+  if(current_temp < warn_temp && IsOn(SENSOR_DISP, WARN_WARN)) {
+    // Switch from warning to ok.
+    BitOff(SENSOR_DISP, WARN_WARN);
+    BitOn(SENSOR_DISP, WARN_NONE);
+    copyXPMArea(0, 75, 5, 5, 4, 4);
+  }
+  if(current_temp >= high_temp && IsOn(SENSOR_DISP, WARN_WARN)) {
+    // Switch from warning to high.
+    BitOff(SENSOR_DISP, WARN_WARN);
+    BitOn(SENSOR_DISP, WARN_HIGH);
+    copyXPMArea(15, 75, 5, 5, 4, 4);
+  }
+  if(current_temp < high_temp && IsOn(SENSOR_DISP, WARN_HIGH)) {
+    // Switch from high to warning.
+    BitOff(SENSOR_DISP, WARN_HIGH);
+    BitOn(SENSOR_DISP, WARN_WARN);
+    copyXPMArea(10, 75, 5, 5, 4, 4);
+  }
+}
+
+inline void blank_type(int type) {
+  switch(type) {
+  case CPU:
+    copyXPMArea(78, 65, 5, 7, 11, CPU_YPOS);
+    copyXPMArea(78, 65, 5, 7, 17, CPU_YPOS);
+    copyXPMArea(78, 65, 5, 7, 23, CPU_YPOS);
+
+    copyXPMArea(70, 0, 2, 2, 52, CPU_YPOS);
+
+    copyXPMArea(78, 65, 5, 7, 34, CPU_YPOS);
+    copyXPMArea(78, 65, 5, 7, 40, CPU_YPOS);
+    copyXPMArea(78, 65, 5, 7, 46, CPU_YPOS);
+
+    copyXPMArea(78, 65, 5, 7, 55, CPU_YPOS);
+    break;
+  case SYS:
+    copyXPMArea(78, 65, 5, 7, 11, SYS_YPOS);
+    copyXPMArea(78, 65, 5, 7, 17, SYS_YPOS);
+    copyXPMArea(78, 65, 5, 7, 23, SYS_YPOS);
+
+    copyXPMArea(70, 0, 2, 2, 52, SYS_YPOS);
+
+    copyXPMArea(78, 65, 5, 7, 34, SYS_YPOS);
+    copyXPMArea(78, 65, 5, 7, 40, SYS_YPOS);
+    copyXPMArea(78, 65, 5, 7, 46, SYS_YPOS);
+
+    copyXPMArea(78, 65, 5, 7, 55, SYS_YPOS);
+    break;
+  }
+}
+
+inline void draw_max(int type) {
+  //  copyXPMArea(1, 81, 17, 7, 11, type == CPU ? CPU_YPOS : SYS_YPOS);
+  copyXPMArea(24, 75, 4, 3, 29, type == CPU ? CPU_YPOS : SYS_YPOS);
+}
+
+inline void blank_max(int type) {
+  //  copyXPMArea(1, 81, 17, 7, 11, type == CPU ? CPU_YPOS : SYS_YPOS);
+  copyXPMArea(20, 75, 4, 3, 29, type == CPU ? CPU_YPOS : SYS_YPOS);
+}
+
+inline void draw_type(int type) {
+  switch(type) {
+  case CPU:
+    copyXPMArea(65, 40, 17, 7, 11, CPU_YPOS);
+    break;
+  case SYS:
+    copyXPMArea(65, 47, 17, 7, 11, SYS_YPOS);
+    break;
+  }
+}
+
+inline void cycle_temptype() {
+  if(IsOn(SENSOR_DISP, TSCALE_CELCIUS)) {
+    BitOff(SENSOR_DISP, TSCALE_CELCIUS);
+    BitOn(SENSOR_DISP, TSCALE_KELVIN);
+  }
+  else if(IsOn(SENSOR_DISP, TSCALE_KELVIN)) {
+    BitOff(SENSOR_DISP, TSCALE_KELVIN);
+    BitOn(SENSOR_DISP, TSCALE_FAHRENHEIT);
+  }
+  else if(IsOn(SENSOR_DISP, TSCALE_FAHRENHEIT)) {
+    BitOff(SENSOR_DISP, TSCALE_FAHRENHEIT);
+    BitOn(SENSOR_DISP, TSCALE_CELCIUS);
+  }
+}
+
+
+int process_config(int argc, char **argv) {
+  char *rc_graph  = NULL;
+  char *rc_scale  = NULL;
+  char *rc_high   = NULL;
+  char *rc_warn   = NULL;
+  char *rc_min    = NULL;
+  char *rc_max    = NULL;
+  char *rc_execat = NULL;
+  char *rc_exec   = NULL;
+  char *rc_delay  = NULL;
+  char *rc_swap   = NULL;
+  char *rc_feature1 = NULL;
+  char *rc_feature2 = NULL;
+  char *rc_quiet  = NULL;
+  char *rc_chip   = NULL;
+  short parse_ok  = 1;
+  int opt_index;
+  int opt;
+  char *p;
+  char temp[128];
+
+  rckeys wmgtemp_keys[] = {
+    { "graph", &rc_graph },
+    { "scale", &rc_scale },
+    { "high", &rc_high },
+    { "warn", &rc_warn },
+    { "min", &rc_min },
+    { "max", &rc_max },
+    { "execat", &rc_execat },
+    { "exec", &rc_exec },
+    { "update", &rc_delay },
+    { "swap", &rc_swap },
+    { "quiet", &rc_quiet },
+    { "feature1", &rc_feature1 },
+    { "feature2", &rc_feature2 },
+    { "chip", &rc_chip },
+    { "sensorconf", &rc_config },
+    { NULL, NULL }
+  };
+  
+  static struct option long_options[] = {
+    {"graph",  required_argument, 0, 'g'},
+    {"scale",  required_argument, 0, 's'},
+    {"high",   required_argument, 0, 'H'},
+    {"warn",   required_argument, 0, 'w'},
+    {"min",    required_argument, 0, 'm'},
+    {"max",    required_argument, 0, 'M'},
+    {"execat", required_argument, 0, 'a'},
+    {"exec",   required_argument, 0, 'e'},
+    {"update", required_argument, 0, 'u'},
+    {"feature1", required_argument, 0, '1'},
+    {"feature2", required_argument, 0, '2'},
+    {"chip",   required_argument, 0, 'c'},
+    {"sensorconf", required_argument, 0, 'S'},
+    {"swap",   no_argument,       0, 't'},
+    {"quiet",   no_argument,       0, 'q'},
+    {"help",   no_argument,       0, 'h'},
+    {0, 0, 0, 0}
+  };
+  
+  p = getenv("HOME");
+  strcpy(temp, p);
+  strcat(temp, "/.wmgtemprc");
+  parse_rcfile(temp, wmgtemp_keys);
+
+  // Do getopt stuff.
+  while ((opt = getopt_long(argc, argv, OPT_STRING, long_options, &opt_index)) != -1) {
+    switch(opt) {
+    case 'g':
+      rc_graph = strdup(optarg);
+      break;
+    case 's':
+      rc_scale = strdup(optarg);
+      break;
+    case 'H':
+      rc_high = strdup(optarg);
+      break;
+    case 'w':
+      rc_warn = strdup(optarg);
+      break;
+    case 'm':
+      rc_min = strdup(optarg);
+      break;
+    case 'M':
+      rc_max = strdup(optarg);
+      break;
+    case 'a':
+      rc_execat = strdup(optarg);
+      break;
+    case 'e':
+      rc_exec = strdup(optarg);
+      break;
+    case 'u':
+      rc_delay = strdup(optarg);
+      break;
+    case '1':
+      rc_feature1 = strdup(optarg);
+      break;
+    case '2':
+      rc_feature2 = strdup(optarg);
+      break;
+    case 'c':
+      rc_chip = strdup(optarg);
+      break;
+    case 'S':
+      rc_config = strdup(optarg);
+      break;
+    case 'q':
+      rc_quiet = "y";
+      break;
+    case 't':
+      rc_swap = "y";
+      break;
+    case 'h':
+      display_usage();
+      exit(0);
+    default:
+      display_usage();
+      exit(-1);
+    }
+  }
+
+  if(rc_quiet != NULL) {
+    if(!strncmp(rc_quiet, "y", 1)) {
+      quiet = 1;
+    }
+  }
+
+  if(rc_feature1 != NULL) {
+    sensor_feature1 = strdup(rc_feature1);
+  }
+  if(rc_feature2 != NULL) {
+    sensor_feature2 = strdup(rc_feature2);
+  }
+  if(rc_chip != NULL) {
+    sensor_chip = strdup(rc_chip);
+  }
+  if(rc_config == NULL) {
+    rc_config = "/etc/sensors.conf";
+  }
+
+  if(rc_graph != NULL) {
+    if(!strncmp(rc_graph, "l", 1)) {
+      BitOff(SENSOR_DISP, GRAPH_BLOCK);
+      BitOn(SENSOR_DISP, GRAPH_LINE);
+    }
+    else if(!strncmp(rc_graph, "b", 1)) {
+      BitOff(SENSOR_DISP, GRAPH_LINE);
+      BitOn(SENSOR_DISP, GRAPH_BLOCK);
+    }
+    else {
+      printf("Invalid graph type: %s\n", rc_graph);
+      parse_ok = 0;
+    }
+  }
+  if(rc_scale != NULL) {
+    if(!strncmp(rc_scale, "c", 1)) {
+    }
+    else if(!strncmp(rc_scale, "f", 1)) {
+      BitOff(SENSOR_DISP, TSCALE_KELVIN);
+      BitOff(SENSOR_DISP, TSCALE_CELCIUS);
+      BitOn(SENSOR_DISP, TSCALE_FAHRENHEIT);
+    }
+    else if(!strncmp(rc_scale, "k", 1)) {
+      BitOff(SENSOR_DISP, TSCALE_CELCIUS);
+      BitOff(SENSOR_DISP, TSCALE_FAHRENHEIT);
+      BitOn(SENSOR_DISP, TSCALE_KELVIN);
+    }
+    else {
+      printf("Invalid scale type: %s\n", rc_scale);
+      parse_ok = 0;
+    }
+  }
+
+  if(rc_high != NULL) {
+    high_temp = (double)atoi(rc_high);
+    if(!high_temp) {
+      printf("Invalid temperature\n");
+      parse_ok = 0;
+    }
+    else {
+      if(quiet == 0)
+	printf("wmgtemp: high temp set to %d degrees celcius.\n", (int)high_temp);
+    }
+  }
+  if(rc_warn != NULL) {
+    warn_temp = (double)atoi(rc_warn);
+    if(!warn_temp) {
+      printf("Invalid temperature\n");
+      parse_ok = 0;
+    }
+    else {
+      if(quiet == 0)
+	printf("wmgtemp: warning temp set to %d degrees celcius.\n", (int)warn_temp);
+    }
+  }
+  if(rc_max != NULL) {
+    display_max = range_upper = (double)atoi(rc_max);
+    if(!range_upper) {
+      printf("Invalid temperature\n");
+      parse_ok = 0;
+    }
+    else {
+      if(quiet == 0)
+	printf("wmgtemp: Upper range set to %d degrees celcius.\n", (int)range_upper);
+    }
+  }
+  if(rc_min != NULL) {
+    display_min = range_lower = (double)atoi(rc_min);
+    if(!range_lower) {
+      printf("Invalid temperature\n");
+      parse_ok = 0;
+    }
+    else {
+      if(quiet == 0)
+	printf("wmgtemp: Lower range set to %d degrees celcius.\n", (int)range_lower);
+    }
+  }
+  if(rc_delay != NULL) {
+    delay = atoi(rc_delay);
+    if(!delay) {
+      printf("Invalid delay\n");
+      parse_ok = 0;
+    }
+    else {
+      if(quiet == 0)
+	printf("wmgtemp: update delay set to %d seconds.\n", delay);
+    }
+  }
+  if(rc_execat != NULL) {
+    execat = (double)atoi(rc_execat);
+    if(!execat) {
+      printf("Invalid temperature\n");
+      parse_ok = 0;
+    }
+    else {
+      if(rc_exec != NULL) {
+	if(strcmp(rc_exec, "")) {
+	  exec_app = strdup(rc_exec);
+	  printf("wmgtemp: Executing \"%s\" at %d degrees celcius.\n", exec_app, (int)execat);
+	}
+	else {
+	  printf("You must supply an command to execute\n");
+	  parse_ok = 0;
+	}
+      }
+      else {
+	printf("You must supply an command to execute\n");
+	parse_ok = 0;
+      }
+    }
+  }
+  if(rc_swap != NULL) {
+    if(!strncmp(rc_swap, "y", 1)) {
+      swap_types = 1;
+    }
+    else if(!strncmp(rc_swap, "n", 1)) {
+      swap_types = 0;
+    }
+    else {
+      printf("Supply 'y' or 'n' for swap temps\n");
+      parse_ok = 0;
+    }
+  }
+
+  return parse_ok;
+}
+
diff --git a/wmgtemp.1 b/wmgtemp.1
new file mode 100644
index 0000000..bf34ab7
--- /dev/null
+++ b/wmgtemp.1
@@ -0,0 +1,153 @@
+.\" Hey, Emacs!  This is an -*- nroff -*- source file.
+.TH "wmgtemp" 1 "February 2001" ""
+.SH NAME
+wmgtemp \- Temperature sensor dock app for Window Maker
+.SH SYNOPSIS
+.B wmgtemp
+.I "[options]"
+.SH "DESCRIPTION"
+wmgtemp is a dock-app for Window Maker that graphically displays the CPU and
+System temperatures using the lm_sensors package. It displays the CPU and
+System temperature values, a scaling graph of temperature history,
+high-temperature warning lights and temperatures in degrees Celsius,
+Fahrenheit or Kelvin.
+.PP
+The temperature graph is auto scaling, meaning that if the max or min temperature boundary is crossed the graph will be scaled to display the temperature. A red line marks the upper boundary whereas a blue line indicates the lower boundary. When all the temperatures being displayed are within the boundaries the graph will be scaled back to the preset values for min/max and the boundary indicator lines will be removed.
+.PP
+The high temperature warning lights located on the left of the temperature type indicators show amber or red when the warning or high temperatures are reached respectively. Normal operating temperature is indicated by no light.
+.SH "OPTIONS"
+.TP
+.B \-h, \-\-help
+display the usage information
+.TP
+.B \-s, \-\-scale=SCALE
+show temperatures using SCALE temperature scale. SCALE=celcius, fahrenheit or kelvin.
+.br
+\fBDefault\fP: celcius
+.TP
+.B \-S, \-\-sensorconf=PATH
+specify the PATH to the lm_sensors config
+.br
+\fBDefault\fP: /etc/sensors.conf
+.TP
+.B \-g, \-\-graph=STYLE
+display graph as STYLE. STYLE=line or block.
+.br
+\fBDefault\fP: line
+.TP
+
+.B \-H, \-\-high=TEMP
+display red warning light at TEMP degrees celcius.
+.br
+\fBDefault\fP: 50
+.TP
+
+.B \-w, \-\-warn=TEMP
+display amber warning light at TEMP degrees celcius.
+.br
+\fBDefault\fP: 45
+
+.TP
+.B \-u, \-\-update=SEC
+update the display every SEC seconds.
+.br
+\fBDefault\fP: 1
+
+.TP
+.B \-m, \-\-min=TEMP
+set the lower bound of the graph to TEMP degrees celcius.
+.br
+\fBDefault\fP: 20
+
+.TP
+.B \-M, \-\-max=TEMP
+set the upper bound of the graph to TEMP degrees celcius.
+.br
+\fBDefault\fP: 35
+
+.TP
+.B \-1, \-\-feature1=F1
+set the feature for CPU
+.br
+\fBDefault\fP: temp1
+
+.TP
+.B \-2, \-\-feature2=F2
+set the feature for SYS
+.br
+\fBDefault\fP: temp2
+
+.TP
+.B \-c, \-\-chip=CHIP
+specify the chip sensor to use
+.br
+\fBDefault\fP: auto
+
+.TP
+.B \-a, \-\-execat=TEMP
+execute a command at TEMP degrees celcius.
+.br
+\fBDefault\fP: none
+
+.TP
+.B \-e, \-\-exec=COMMAND
+execute COMMAND when the 'execat' temperature is reached.
+.br
+\fBDefault\fP: none
+
+.TP
+.B \-t, \-\-swap
+swap/transpose temperature values
+
+.TP
+.B \-q, \-\-quiet
+Don't display any messages
+
+.PP
+.SH FILES
+~/.wmgtemprc	User configuration.
+.PP
+The format of this file is:
+.nf
+.IP
+# wmgtemp example config
+scale:celcius
+graph:line
+high:50
+warn:45
+update:1
+min:25
+max:35
+execat:80
+exec:shutdown -h 10
+swap:n
+quiet:y
+feature1:temp1
+feature2:temp2
+.PP
+.SH USAGE
+.SS Graph
+You can cycle through the graph types by clicking on the graph display area.
+.PP
+.SS High Temperature Toggle
+You can toggle the displaying of high temperatures by click on the temperature for the corrosponding temperature. The viewing of high temperatures is indicated by an amber arrow to the left of the temperature. The current temperatures will continue to be displayed on the graph.
+.PP
+.SH
+.SS Temperature display TOGGLE
+You may toggle the displaying of a temperature on the graph by clicking on the corrosponding type. e.g To toggle the display of the CPU temperature click on CPU. The type indicator (CPU or SYS) will disappear and the temperature will not be displayed on the graph, although the temperature value will continue to be displayed.
+.PP
+.SH
+.SS Temperature Scale Cycling
+You may change the scale the temperatures are displayed in by clicking on either of the CPU or SYS scale indicators. The cycle order is \fBC\fP -> \fBK\fP -> \fBF\fP
+.PP
+.SH BUGS
+Blank lines in the config file cause a Segmentation Fault.
+.PP
+.SH SEE ALSO
+.BR sensors.conf (5),
+.BR libsensors (3),
+.BR wmaker (1x)
+.SH AUTHOR
+wmgtemp was written by Roger Dunce <kronos at fluxcode.net>
+
+

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



More information about the Pkg-wmaker-commits mailing list