[Pkg-wmaker-commits] [wmacpi] 42/105: Imported Upstream version 2.1
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Tue Aug 18 01:13:43 UTC 2015
This is an automated email from the git hooks/post-receive script.
dtorrance-guest pushed a commit to branch master
in repository wmacpi.
commit c74c0fac249ff2391b011167f1ed1a907a1c6d47
Author: Doug Torrance <dtorrance at monmouthcollege.edu>
Date: Mon Nov 24 05:55:08 2014 -0600
Imported Upstream version 2.1
---
AUTHORS | 3 +
ChangeLog | 270 ++++++++++++++
INSTALL | 34 +-
Makefile | 68 +++-
README | 93 +++--
TODO | 49 +++
acpi.1 | 1 +
acpi.c | 128 +++++++
debian/changelog | 147 ++++++++
debian/compat | 1 +
debian/control | 20 ++
debian/copyright | 27 ++
debian/dirs | 1 +
debian/docs | 3 +
debian/menu | 2 +
debian/rules | 90 +++++
debian/watch | 2 +
libacpi.c | 881 +++++++++++++++++++++++++++++++++++++--------
libacpi.h | 144 ++++++++
libapm.c | 91 -----
master.xpm | 162 ++++-----
master_low.xpm | 152 ++++----
wmacpi.1 | 165 +++++++++
wmacpi.c | 1059 ++++++++++++++++++++++++++++++++++--------------------
wmacpi.h | 49 +--
25 files changed, 2722 insertions(+), 920 deletions(-)
diff --git a/AUTHORS b/AUTHORS
index ed910da..6f804d2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,6 @@
+Simon Fowler <simon at dreamcraft.com.au>
+ Complete rewriting of the code from wmacpi-1.34.
+
timecop
timecop at japan.co.jp
all the code
diff --git a/ChangeLog b/ChangeLog
index 5bb8f42..dfa719f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,273 @@
+2005 February 2 2.1
+ Finalised libdockapp-0.5.0 port - no changes from 2.1rc1.
+
+2005 Jan 5 2.1rc1
+ Typo fix in the manpage.
+
+ Ported to libdockapp-0.5.0 - all this needed was changing the
+ type of the dockapp width and height to unsigned short.
+
+2004 October 24 2.0
+ Upped version number to 2.0.
+
+ Small typo fixes.
+
+ wmacpi 2.0 goes gold . . .
+
+2004 September 28 2.0rc1
+ Added support for switching to capacity mode automatically, on
+ detecting dodgy reports from the battery.
+
+ Added support for capacity mode on charging, with automatic
+ enabling as per discharging.
+
+ Various cleanups.
+
+ Hopefully last release before the final 2.0.
+
+2004 August 18 1.99r7
+ Implemented the libdockapp port - this seems to close Debian bug
+ #227819, but it hasn't received sufficient testing.
+
+ Implemented a capacity mode for calculating time remaining (as
+ opposed to the normal current rate mode) - this mode samples the
+ remaining capacity of the battery and notes the time at which it
+ was sampled, and uses a history of samples to estimate the rate of
+ drain on the battery. From there it calculates a value for time
+ remaining.
+
+ Also, various cleanups have gone in:
+
+ * a reworking of the scrolling code
+
+ * generic battery number support (rather than just
+ using two pixmaps, one for b1 and one for b2)
+
+ * stopped the battery glyph from blinking when running on AC
+
+2004 July 19 1.99r6
+ Fix for Debian bug #250792 - the parser for the acpi files was
+ too stupid to deal with error conditions. I've now added some
+ basic checking to make it handle the error that caused the bug
+ report, but I'll need to add more later.
+
+2004 April 23 1.99r5
+ Collected fixes for the collected fixes below . . .
+
+ * Manpage fixes, to reflect the reality of the current code.
+
+ * Code cleanups, to make a few things more sensible. Most notably,
+ the interface for setting the samplerate has changed so that it's
+ no longer inverted and illogical - you now say how many times you
+ want to sample per minute.
+
+ * Fixed an issue with initialisation - I'd moved the power_init()
+ call below the options parsing code, without dealing with the -m
+ option properly. The end result was that if you told it to monitor
+ a battery number, it would fail saying the battery didn't exist. I
+ moved the check for this out of the options parsing and after the
+ power_init() call.
+
+ * Fixed a leaking file descriptor in init_ac_adapters.
+
+ * Implemented a way to handle changing batteries - reinitialise
+ the battery info periodically. I don't know of a better way to do
+ that, since we'd have to do all that parsing anyway to find out if
+ it had changed . . .
+
+ libdockapp is waiting, but I think that's the only change left
+ without more bug repots . . .
+
+2004 April 15 1.99r4
+ Collected fixes for various small issues.
+
+ * Fixed a problem with placement of the window when using the
+ click to place mode - turned out to be a sizehints problem.
+
+ * Some fixes to the manpage.
+
+ * Reenabled the CLI build by default - the Debian patches can
+ handle disabling it themselves.
+
+ * Added a way to disable the scrolling message, since some users
+ find this annoying.
+
+ I've left the big changes that are needed (like using libdockapp,
+ in the hope that it'll solve the docking problems) until later, so
+ that I can get these smaller fixes out. Hopefully soon . . .
+
+2004 January 12 1.99r3
+ . . . and a fix for a fix that didn't fix it . . .
+
+2004 January 12 1.99r2
+ Some cleanups and bugfixes found by the wonderful Debian users.
+
+ It's finally in testing!
+
+2003 November 23 1.99
+ Finally claimed the wmacpi name as my own . . .
+
+ Renamed wmacpi-ng and acpi-ng, renamed the header files, fixed up
+ the makefile.
+
+ For the Debian package, also made compilation of the command line
+ tool optional, defaulting to not building it. This is because
+ after the renaming, my acpi clashes with the acpi package that's
+ already in Debian. The command line functionality is now
+ accessible via the -w option to wmacpi.
+
+ This is wmacpi 1.99, so that I can have a release packaged and in
+ Debian before going to 2.0, so that any bugs that are left can be
+ found by all the extra users.
+
+2003 September 26 0.99
+ Fix the last of the old wmacpi code oddities (specifically, the
+ APMInfo struct, which was a completely inappropriate name given we
+ no longer deal with APM, and because of the various code
+ refactoring).
+
+ I think this is probably as good as I can make it without getting
+ more feedback and the like, so I'm going to make this version
+ 0.99, preliminary to either wmacpi-ng 1.0 or wmacpi 2.0 (depending
+ which direction I go with that).
+
+2003 September 23 0.92
+ Fix a few more bugs, and include an option to allow the user to
+ specify how often to sample the ACPI data - some BIOSes disable
+ all interrupts while reading from the battery, which apparently
+ causes some interactivity issues. I have no idea why reading once
+ every three seconds (which is our default), but there've been some
+ complaints.
+
+ Also fixed acpi-ng to properly handle the -a option.
+
+2003 August 6 0.91
+ Fix a problem I'm seeing with docking the app - if the window name
+ is set to "acpi" rather than "apm" it doesn't dock . . .
+
+2003 July 16 0.90
+ Make the time display show '--:--' instead of '00:00' when the
+ time remaining is 0 - I think this is reasonable, since it'll only
+ get into this state when the present rate value is 0. This only
+ happens when the battery is fully charged and neither discharging
+ or charging, or when the battery is completely drained. In any of
+ these states the time remaining is of very little interest, so we
+ don't lose anything. We also get to handle the (sadly, very
+ common) case where the ACPI subsystem doesn't report sane values
+ for the things we depend on.
+
+2003 July 11 0.50a2
+ Make the time display show nothing (as opposed to 00:00) when the
+ time remaining is unknown, as requested by Emma Jane Hogbin.
+
+ Respect the critical level specified on the command line, and add
+ a new message to differentiate between the command line critical
+ level and the critical state reported by the battery.
+
+ Speed up the message scrolling, so that there isn't quite such a
+ painful delay between repeats. Also, up the speed when the battery
+ is low, more when it's critical, and scroll continuously when it's
+ hardware critical.
+
+ Finally, add support for disabling the blinking power and battery
+ glyphs from the command line, as requested by Sebastian
+ Henschel. We still blink the battery glyph when the battery
+ reports hardware critical level - I think that's worth being a bit
+ annoying about.
+
+ Also, added an acpi-ng manpage.
+
+2003 July 11 0.50a1
+ Properly fix the AC adapter issue - it's not much use adding the
+ infrastructure and then forgetting to fix the code that uses it.
+
+ Fix the time disiplay so that it doesn't try to display values
+ greater than 99:59, since the display area won't fit anything
+ beyond that.
+
+2003 July 10 0.50a
+ Bugfixes, to handle two problems: the case where something like
+ the present rate or some such is "unknown" (reported initially by
+ Emma Jane Hogbin, and where the AC adapter is called something
+ other than "AC" (reported by Sebastian Henschel). This an 'a'
+ release because I can't test these myself . . .
+
+2003 July 6 0.50
+ Finally got rid of that annoying button - that space now contains
+ a 'B 1' or 'B 2' (only those two at present, since I'm too lazy to
+ fix it so that the number is generic. It should work fine for
+ anyone who doesn't have a freakish system with more than two
+ batteries . . .)
+
+ A few more code cleanups.
+
+2003 July 1 0.19
+ libacpi cleanups and reworking - we now handle the charging
+ battery case properly, it seems.
+
+ Also, some attempts to make error printing a bit cleaner; still a
+ long way to go on that, though . . .
+
+2003 June 24 0.15
+ Removed process_plugin_timer(), since it was doing nothing useful
+ at all . . .
+
+2003 June 23 0.14
+ Removed libapm.c - wmacpi-ng is specifically for ACPI, with no APM
+ support.
+
+2003 June 23 0.13
+ Some more code cleanups, designed to move libacpi to more of a
+ library than something built into wmacpi-ng. This is useful with
+ the seperate programs, though at present it's not used much.
+
+2003 June 21 0.12
+ Added a command line tool, acpi-ng to query battery status from
+ the command line.
+
+2003 May 30 0.11
+ Implemented multiple battery support, and averaging of the samples
+ in an attempt to even out the jumpiness of the timer.
+
+2003 May 30 0.10
+ More major code cleanups: in particular the handling of the power
+ panel and the message has been cleaned up so that it's actually
+ sane and clean.
+
+ Next step from here is to actually implement handling of multiple
+ batteries, so that if there's a fully charge second battery
+ available it reports the correct time remaining (based on the
+ present rate of power consumption and the sum of the two battery's
+ remaining capacities).
+
+2003 May 29 0.3
+ Some major reworking of the internals, to help fix the handling of
+ multiple batteries and such things.
+
+2003 May 26 0.2a
+ Code cleanups to fix various problems with corner cases.
+
+2003 May 26 0.2
+ Added support for multiple batteries: I took the simple route of
+ displaying only one battery per instance - to do more I'd need to
+ hack with the display code, and I'm not ready for that yet.
+
+ Added a -m option to specify the battery number to monitor.
+
+2003 May 26 0.1
+ Changed package completely, to support the new ACPI code as of
+ 2.4.21-rc2.
+
+ Since this code hasn't been touched in more than a year, I figure
+ I might as well have a go at hacking on it . . .
+
+ -- Simon Fowler, <simon at dreamcraft.com.au>
+
+2002 Feb 17 1.34
+ Updated ACPI statistics gathering code for the latest ACPI patch from
+ Intel. Now uses/checks for subsystem version 20020214+. Redone the version
+ check a little bit.
+
2001 Apr 29 1.33
Little fix to ACPI version check so that I don't have to make a new
version each time a new kernel comes out
diff --git a/INSTALL b/INSTALL
index 01b1e42..b456969 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,10 +1,24 @@
-to install:
-
-* vi Makefile
-* change what you want, according to instructions, save Makefile
-* make
-* copy wmacpi somewhere useful
-* dance
-* <somewhere useful>/wmacpi &
-* phear
-(if it doesn't work, skip the phear step)
+The basic install is very simple: make, make install.
+
+You can change the default install prefix (/usr/local) by specifying
+it in the make install command, eg: make install PREFIX=/usr
+
+To build the command line tool, either uncomment the BUILD_CLI=1 line
+in the Makefile, or specify BUILD_CLI=1 on the make command line. ie,
+make BUILD_CLI=1
+make install BUILD_CLI=1
+
+As of 2.1 wmacpi requires libdockapp-0.5.0 - the tarball is available
+from the same place as the wmacpi tarball. If you're running Debian
+testing you just need to install libdockapp-dev.
+
+No uninstall is supported, but isn't exactly difficult to delete all
+the files by hand . . .
+
+Files installed (paths relative to PREFIX):
+bin/wmacpi
+bin/acpi
+man/man1/wmacpi.1
+man/man1/acpi.1
+
+Simon Fowler <simon at dreamcraft.com.au>, 2005-01-05
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 79f379c..4d53ae1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,25 +1,71 @@
# set options. pick one, acpi or apm. comment out the other one. don't
# uncomment both, bad things will happen :)
-OPT = -O3 -DACPI
-#OPT = -O3 -DAPM
+OPT := -O2
+
+# uncomment this to build the command line acpi tool
+BUILD_CLI = 1
# uncomment this to make wmacpi use less system colors (looks uglier too)
#OPT += -DLOW_COLOR
# debugging options (don't bother with these)
-#OPT = -pg -g -DPRO -DACPI
+#OPT = -pg -g
+
+CC := gcc
+CFLAGS := $(OPT) -Wall -W -g -ansi -I/usr/X11R6/include
+LDFLAGS := $(OPT) -L/usr/X11R6/lib -lX11 -lXpm -lXext -ldockapp
+
+WMSRC := wmacpi.c libacpi.c
+HEADERS := libacpi.h wmacpi.h
+targets := wmacpi
+doc_targets := wmacpi.1
+
+ifdef BUILD_CLI
+targets += acpi
+doc_targets += acpi.1
+endif
+
+PREFIX := /usr/local
+
+all: $(targets)
-CC = gcc
-CFLAGS = $(OPT) -Wall -ansi -I/usr/X11R6/include
-LDFLAGS = $(OPT) -L/usr/X11R6/lib -lX11 -lXpm -lXext
+# build the list of object files
+WMOBJ := $(patsubst %.c,%.o,$(filter %.c,$(WMSRC)))
-SRCS = wmacpi.c libapm.c libacpi.c
-OBJS = wmacpi.o libapm.o libacpi.o
+# include per-file dependencies
+include $(WMOBJ:.o=.d)
-all: wmacpi
+wmacpi: $(WMOBJ)
+ $(CC) $(LDFLAGS) -o $@ $^
-wmacpi: $(OBJS)
+# for the Debian package, we want to make building the command line tools
+# optional. So, we hide all the necessary stuff here . . .
+ifdef BUILD_CLI
+CLSRC := acpi.c libacpi.c
+CLOBJ := $(patsubst %.c,%.o,$(filter %.c,$(CLSRC)))
+include $(CLOBJ:.o=.d)
+
+acpi: $(CLOBJ)
+ $(CC) $(LDFLAGS) -o $@ $^
+endif
+
+# build per-file dependencies - note that -MM may not be supported
+# in gcc versions older than 2.95.4, but most likely is.
+%.d: %.c
+ gcc -MM $(CFLAGS) $< > $@
clean:
- rm -f *.o *~ wmacpi trace *.out *.bb *.bbg
+ rm -f TAGS *.o *~ trace *.out *.bb *.bbg
+
+clean-all: clean
+ rm -f *.d $(targets)
+
+install: $(targets)
+ install -d $(PREFIX)/bin/
+ install -pc $(targets) $(PREFIX)/bin/
+ install -d $(PREFIX)/man/man1/
+ install -pc $(doc_targets) $(PREFIX)/man/man1/
+
+tags:
+ etags $(WMSRC) $(CLSRC) $(HEADERS)
diff --git a/README b/README
index 91e454d..97fcb19 100644
--- a/README
+++ b/README
@@ -5,59 +5,50 @@ Usage:
+-------------+
|battery graph| <- visual percentage battery remaining
|[:][=] [100%]| <- [:] - on AC (blink when charging) [=] - on battery
-|[00:00] [///]| <- [00:00] time remaining [///] timer mode switch
+|[00:00] [bX]| <- [00:00] time remaining [bX] battery being monitored.
|status area| <- messages scroll here
+-------------+
see wmacpi -h for some command line switches
-Timer mode, available only when "on-battery", keeps track how long your laptop
-has been away from AC power. Clicking the button toggles between timer and
-standard "time remaining" mode.
-
-******************************************************************************
-
-Implementation of "ACPI" mode:
-
-As far as I know, there aren't any tools available right now to process battery
-statistics provided in /proc/power by ACPI stuff in 2.4.x kernels. This is my
-attempt to have a usable dockapp battery monitor for ACPI laptop systems.
-Since version 1.32 I've added some code to detect multiple batteries. However
-it's not fully implemented yet, and while it will detect and enumerate
-batteries, the statistics reported are for the first found battery.
- * Your battery is "Control Method" type
- * Your ACPI BIOS is supported by current version of ACPI in kernel
- 2.4.2 + patches
- * You applied acpi subsystem patch version 20010313 (from intel.com)
-
-If you are still using plain 2.4.2 kernel, keep using wmacpi 1.21.
-To use ACPI support, just follow "INSTALL" instructions. Makefile has been
-updated to include -DACPI. If you don't have ACPI, you don't need this version
-of wmapm. Information below only applies to APM systems, without ACPI support.
-
-Implementation of "APM" mode
-
-This works on all machines that have a standard non-borked APM implementation.
-For people with broken APM implementations, I added some stuff, which was
-sent to me by Daniel Pittman <daniel at rimspace.net>, to compensate for some
-of the stupidity. If you see dumb behaviour from wmapm, consider editing
-wmapm.c and uncomment one, or both, of these lines (on lines 19 and 20):
-
-#define RETARDED_APM if your bios thinks the battery is charging all the time
-when it's on AC power. What this will do is stop "charging" process as soon
-as the battery reaches 100%.
-
-#define STUPID_APM if your bios shows -1 minutes remaining when AC is plugged
-in, or when battery is charging.
-
-If your bios is even dumber than this, and you come up with another special
-case that needs to be handled, feel free to #ifdef it under <badword>_APM and
-send me a diff -u. I will include it in the next version. Any of these
-changes would have to go into acquire_apm_info. Note, I changed format of
-apminfo structure to get rid of redundancy - now there is only one power state
-variable, which keeps track whether we are on AC, charging, battery, etc.
-
-Note, all the *_APM stuff is untested - my laptop has a working BIOS :) If you
-test this and it doesn't work as advertised, go ahead and send me a fix.
-
- -timecop
+**********************************************************************
+
+wmacpi is a dockapp ACPI battery monitor for modern kernels (ie,
+2.4.17 or later, and 2.6 kernels). Basically, it opens various files
+under /proc/acpi, reads status information from them, and then
+displays summaries.
+
+Version 1.99 and later provides full support for multiple
+batteries. You can tell it to monitor a particular battery with the -m
+option, which will display the percentage remaining and current status
+message for that battery. The time remaining and AC/battery status are
+global - the time remaining is calculated based on all batteries found
+on the system. When charging, the time displayed is the time remaining
+until the battery is fully charged - this only works sensibly if your
+ACPI system is implemented properly (far, far too many laptops have
+buggered ACPI implementations).
+
+The displayed time is averaged over 50 samples, each taken every three
+seconds (by default). This greatly improves the accuracy of the
+numbers - on my laptop, the time remaining seems to be overstated by a
+good hour or so if you only sample once compared to fifty times.
+
+Some ACPI implementations are stupid enough to block interrupts while
+reading status information from the battery over a slow bus - this
+means that on such b0rken laptops, running an ACPI battery monitor
+could affect interactivity. To provide a workaround for this, current
+versions of wmacpi supports setting the sample rate from the command
+line. The default -s setting is 100, which translates to once every
+three seconds. -s 10 will sample every 30 seconds, -s 1 every 300
+seconds. -s 1000 will sample every 0.3 seconds - don't do that unless
+you're just having fun . . .
+
+Also provided is a command line tool to report the battery status. By
+default this will only sample once, but with the -a option you can
+specify a number. Be aware that it will try to take all those samples
+in the space of one second, so if your ACPI implementation is b0rken
+this could have adverse effects.
+
+Please report bugs to <simon at dreamcraft.com.au>.
+
+Simon Fowler, 2003-11-23.
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..ef29553
--- /dev/null
+++ b/TODO
@@ -0,0 +1,49 @@
+2004 January 18 1.99r3
+ * Correctly handle changing batteries at runtime, if possible. Note
+ the bug reported by Joey Hess against wmacpi 1.33 . . .
+
+2003 November 23 1.99
+ * Expand libacpi to handle everything else under
+ /proc/acpi. Basically, make it into a full ACPI reporting library.
+
+ * Make the command line tool a complete replacement for Grahame
+ Bowland's acpi tool, so that wmacpi won't conflict with it.
+
+2003 July 6 0.50
+ * Fix the non-deb installation - as it stands, it doesn't even try.
+
+ * Yet more cleanups.
+
+2003 June 24 0.14
+
+ * Still more code cleanups - there's a considerable amount of dumb
+ stuff in there still . . .
+
+ * Display time left for battery charging. But first make sure that
+ this will actually work with other systems.
+
+ * Turn libacpi into a real library?
+
+2003 May 30 0.10
+
+ * More code cleanups, particularly in the various display functions.
+
+ * Full handling of multiple batteries.
+
+ * Add some kind of progressive display of power consumption, roughly
+ similar to what wmmon displays for cpu usage (possibly as a
+ completely seperate display mode, or possibly as a replacement for
+ the (completely useless) button).
+
+ * Drop APM support (maybe?).
+
+2003 May 26 0.2a
+
+ * Restructure power state handling - split it into a boolean AC
+ on/off and a battery status flag.
+
+ * Expand the APMInfo struct to be more useful.
+
+ * Code cleanups . . .
+
+ -- Simon Fowler, <simon at dreamcraft.com.au>
diff --git a/acpi.1 b/acpi.1
new file mode 100644
index 0000000..c286484
--- /dev/null
+++ b/acpi.1
@@ -0,0 +1 @@
+.so man1/wmacpi.1
diff --git a/acpi.c b/acpi.c
new file mode 100644
index 0000000..85a6c84
--- /dev/null
+++ b/acpi.c
@@ -0,0 +1,128 @@
+/*
+ * acpi-ng: command line acpi battery status tool.
+ *
+ * Written by Simon Fowler <simon at dreamcraft.com.au>, 2003-06-20.
+ * Copyright 2003-06-20 Dreamcraft Pty Ltd.
+ *
+ * This file is distributed under the GNU General Public License,
+ * version 2. Please see the COPYING file for details.
+ */
+
+/*
+ * 2003-06-20.
+ * I'm getting sick of not having a convenient way to query battery
+ * status on the command line, so I'm hacking up this - a quick little
+ * command line tool to display current battery status, using the same
+ * libacpi code as wmacpi-ng.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include "libacpi.h"
+
+#define ACPI_VER "2.1"
+
+global_t *globals;
+
+void usage(char *name)
+{
+ printf("%s: query battery status on ACPI enabled systems.\n"
+ "Usage:\n"
+ "%s [-h] [-a samples]\n"
+ " h - display this help information\n"
+ " a - average remaining time over some number of samples\n"
+ " much more accurate than using a single sample\n"
+ " v - increase verbosity\n",
+ name, name);
+}
+
+void print_version(void)
+{
+ printf("acpi version %s\n", ACPI_VER);
+ printf(" Using libacpi version %s\n", LIBACPI_VER);
+}
+
+int main(int argc, char *argv[])
+{
+ int i, j, ch;
+ int sleep_time = 0;
+ int samples = 1;
+ battery_t *binfo;
+ adapter_t *ap;
+
+ while((ch = getopt(argc, argv, "hvVa:")) != EOF) {
+ switch(ch) {
+ case 'h':
+ usage(argv[0]);
+ return 0;
+ case 'v':
+ verbosity++;
+ break;
+ case 'V':
+ print_version();
+ return 0;
+ case 'a':
+ if(optarg != NULL) {
+ samples = atoi(optarg);
+ if(samples > 1000 || samples <= 0) {
+ fprintf(stderr, "Please specify a reasonable number of samples\n");
+ exit(1);
+ }
+ }
+ pinfo("samples: %d\n", samples);
+ sleep_time = 1000000/samples;
+ break;
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ }
+
+ globals = (global_t *) malloc(sizeof(global_t));
+
+ power_init(globals);
+ /* we want to acquire samples over some period of time, so . . . */
+ for(i = 0; i < samples + 2; i++) {
+ for(j = 0; j < globals->battery_count; j++)
+ acquire_batt_info(globals, j);
+ acquire_global_info(globals);
+ usleep(sleep_time);
+ }
+
+ ap = &globals->adapter;
+ if(ap->power == AC) {
+ printf("On AC Power");
+ for(i = 0; i < globals->battery_count; i++) {
+ binfo = &batteries[i];
+ if(binfo->present && (binfo->charge_state == CHARGE)) {
+ printf("; Battery %s charging", binfo->name);
+ printf(", currently at %2d%%", binfo->percentage);
+ if(binfo->charge_time >= 0)
+ printf(", %2d:%02d remaining",
+ binfo->charge_time/60,
+ binfo->charge_time%60);
+ }
+ }
+ printf("\n");
+ } else if(ap->power == BATT) {
+ printf("On Battery");
+ for(i = 0; i < globals->battery_count; i++) {
+ binfo = &batteries[i];
+ if(binfo->present && (binfo->percentage >= 0))
+ printf(", Battery %s at %d%%", binfo->name,
+ binfo->percentage);
+ }
+ if(globals->rtime >= 0)
+ printf("; %d:%02d remaining", globals->rtime/60,
+ globals->rtime%60);
+ printf("\n");
+ }
+ return 0;
+}
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..5778797
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,147 @@
+wmacpi-ng (0.99-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at dreamcraft.com.au> Fri, 26 Sep 2003 13:48:55 +1000
+
+wmacpi-ng (0.92-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at dreamcraft.com.au> Tue, 23 Sep 2003 11:57:09 +1000
+
+wmacpi-ng (0.91-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at dreamcraft.com.au> Wed, 6 Aug 2003 18:32:11 +1000
+
+wmacpi-ng (0.90-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Wed, 16 Jul 2003 18:52:04 +1000
+
+wmacpi-ng (0.50a2-1) unstable; urgency=low
+
+ * New alpha upstream version.
+
+ -- Simon Fowler <simon at dreamcraft.com.au> Fri, 11 Jul 2003 14:29:44 +1000
+
+wmacpi-ng (0.50a1-1) unstable; urgency=low
+
+ * New alpha upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Thu, 10 Jul 2003 11:46:11 +1000
+
+wmacpi-ng (0.50a-1) unstable; urgency=low
+
+ * New alpha upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Thu, 10 Jul 2003 00:07:44 +1000
+
+wmacpi-ng (0.50-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Sun, 6 Jul 2003 16:50:59 +1000
+
+wmacpi-ng (0.19-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Wed, 2 Jul 2003 00:55:36 +1000
+
+wmacpi-ng (0.15-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Tue, 24 Jun 2003 00:38:26 +1000
+
+wmacpi-ng (0.14-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Tue, 24 Jun 2003 00:00:26 +1000
+
+wmacpi-ng (0.13-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Mon, 23 Jun 2003 23:49:05 +1000
+
+wmacpi-ng (0.12-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Sat, 21 Jun 2003 12:24:43 +1000
+
+wmacpi-ng (0.11-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at hollie.himi.private> Fri, 30 May 2003 23:42:12 +1000
+
+wmacpi-ng (0.10-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at dreamcraft.com.au> Fri, 30 May 2003 13:35:50 +1000
+
+wmacpi-ng (0.2a-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Simon Fowler <simon at dreamcraft.com.au> Mon, 26 May 2003 22:08:45 +1000
+
+wmacpi-ng (0.2-1) unstable; urgency=low
+
+ * New version.
+
+ -- Simon Fowler <simon at dreamcraft.com.au> Mon, 26 May 2003 18:59:16 +1000
+
+wmacpi-ng (0.1-1) unstable; urgency=low
+
+ * New package, since the current version doesn't work with kernel
+ 2.4.21-rc2.
+
+ -- Simon Fowler <simon at dreamcraft.com.au> Mon, 26 May 2003 14:01:40 +1000
+
+wmacpi (1.34-1) unstable; urgency=low
+
+ * New maintainer.
+ * New upstream release (closes: #143387).
+ * debian/control:
+ - Updated description.
+ - Bumped Standards-Version to 3.5.9.
+ - Updated build-dependency on debhelper to >= 4.
+ - Changed priority to "optional".
+ - Added a recommendation on "wmaker".
+ * debian/compat:
+ - Introduced this file and set its contents to "4".
+ * debian/copyright:
+ - Updated maintainer and homepage infos.
+ * debian/rules:
+ - Made some minor modifications to comply with policy.
+ * debian/watch:
+ - Introduced this file, which seems to be currently useless, though. the
+ web server does not allow browsing in the necessary directories.
+ * debian/docs:
+ - Included AUTHORS.
+ * debian/wmacpi.1:
+ - Updated man page to reflect current parameters of wmacpi.
+
+ -- Sebastian Henschel <shensche at kodeaffe.de> Sat, 19 Apr 2003 17:09:11 +0200
+
+wmacpi (1.33-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Simon Richter <sjr at debian.org> Mon, 28 May 2001 01:49:55 +0200
+
+wmacpi (1.31-1) unstable; urgency=low
+
+ * Initial Release (Closes: #90347).
+
+ -- Simon Richter <Simon.Richter at phobos.fs.tum.de> Mon, 19 Mar 2001 23:26:49 +0100
+
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..b8626c4
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+4
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..8b9e99f
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,20 @@
+Source: wmacpi
+Section: x11
+Priority: optional
+Maintainer: Simon Fowler <simon at dreamcraft.com.au>
+Build-Depends: debhelper (>= 4), xlibs-dev
+Standards-Version: 3.5.9
+
+Package: wmacpi
+Architecture: i386
+Depends: ${shlibs:Depends}
+Recommends: wmaker
+Description: An ACPI battery monitor for WindowMaker
+ This is a battery monitor that uses ACPI to query the battery status.
+ This version should work with all recent kernels, both 2.4 and 2.6.
+ .
+ This is a reworked version to handle modern kernels, done by Simon
+ Fowler <simon at dreamcraft.com.au>
+ .
+ Author: Simon Fowler <simon at dreamcraft.com.au>
+ Homepage: http://himi.org/wmacpi-ng/
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..dfd7321
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,27 @@
+This package was debianized by Simon Richter <Simon.Richter at phobos.fs.tum.de> on
+Mon, 19 Mar 2001 23:26:49 +0100.
+It was taken over by Sebastian Henschel <shensche at kodeaffe.de> on Sat, 19 Apr 2003 15:31:00 +0200.
+
+It was downloaded from http://www.ne.jp/asahi/linux/timecop/
+
+Upstream Author: Timecop <timecop at japan.co.jp>
+
+Copyright:
+
+ This package 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; version 2 dated June, 1991.
+
+ This package 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 package; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+On Debian GNU/Linux systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..e772481
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1 @@
+usr/bin
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..9bce069
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,3 @@
+README
+AUTHORS
+TODO
\ No newline at end of file
diff --git a/debian/menu b/debian/menu
new file mode 100644
index 0000000..10c6503
--- /dev/null
+++ b/debian/menu
@@ -0,0 +1,2 @@
+?package(wmacpi):needs=X11 section=Apps/System\
+ title="wmacpi" command="/usr/bin/wmacpi"
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..5cc82ce
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,90 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+INSTALLDIR=$(CURDIR)/debian/wmacpi
+
+# These are used for cross-compiling and for saving the configure script
+# # from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS = "-Wall -g -O0"
+else
+ CFLAGS = "-Wall -g -O2"
+endif
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+
+ touch configure-stamp
+
+build: configure-stamp build-stamp
+build-stamp:
+ dh_testdir
+
+ # Add here commands to compile the package.
+ $(MAKE)
+
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+
+ # Add here commands to clean up after the build process.
+ -$(MAKE) clean-all
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/wmacpi.
+ install -o root -g root -m 755 wmacpi $(INSTALLDIR)/usr/bin/
+# install -o root -g root -m 755 acpi-ng $(INSTALLDIR)/usr/bin/
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+# dh_installdebconf
+ dh_installdocs
+# dh_installexamples
+ dh_installmenu
+# dh_installemacsen
+# dh_installpam
+# dh_installinit
+# dh_installcron
+ dh_installman wmacpi.1 # acpi.1
+# dh_installinfo
+# dh_undocumented
+ dh_installchangelogs ChangeLog
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+# dh_makeshlibs
+ dh_installdeb
+# dh_perl
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..ff95adf
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,2 @@
+version=2
+http://www.ne.jp/asahi/linux/timecop/software/wmacpi-(.*)\.tar\.gz debian uupdate
diff --git a/libacpi.c b/libacpi.c
index 0d04c92..6ea74d6 100644
--- a/libacpi.c
+++ b/libacpi.c
@@ -1,213 +1,792 @@
+#define _GNU_SOURCE
+
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
+#include <time.h>
-#include "wmacpi.h"
-
-#define MAXBATT 8
+#include "libacpi.h"
-#ifdef ACPI
-#ifdef PRO
extern char *state[];
-#endif
-extern APMInfo *apminfo;
-static char batteries[MAXBATT][128];
-static char battinfo[MAXBATT][128];
-int batt_count;
-/* temp buffer */
-char buf[512];
+/* extern global_t *globals; */
/* local proto */
-int acpi_get_design_cap(int battery);
+int acpi_get_design_cap(int batt);
-/* see if we have ACPI support and check version */
-int power_init(void)
+/* initialise the batteries */
+int init_batteries(global_t *globals)
{
- FILE *acpi;
- char buf[4096];
DIR *battdir;
struct dirent *batt;
char *name;
- char *tmp;
-
- if (!(acpi = fopen("/proc/acpi/info", "r"))) {
- fprintf(stderr, "This system does not support ACPI\n");
- return 1;
- }
-
- /* okay, now see if we got the right version */
- fread(buf, 4096, 1, acpi);
- tmp = strstr(buf, "ersion:");
- if (tmp) {
- tmp += 16;
- if (atoi(tmp) < 20010313) {
- fprintf(stderr, "This version requires ACPI subsystem version 20010313\n");
- fclose(acpi);
- return 1;
- }
- } else {
- fprintf(stderr, "Perhaps old ACPI subsystem - consider upgrading to\n"
- "at least version 20010313\n");
- fclose(acpi);
- return 1;
- }
-
- /* yep, all good */
- fclose(acpi);
-
+ char *names[MAXBATT];
+ int i, j;
+
/* now enumerate batteries */
- batt_count = 0;
+ globals->battery_count = 0;
battdir = opendir("/proc/acpi/battery");
if (battdir == NULL) {
- fprintf(stderr, "No batteries or ACPI not supported\n");
+ pfatal("No batteries or ACPI not supported\n");
return 1;
}
while ((batt = readdir(battdir))) {
+ /* there's a serious problem with this code when there's
+ * more than one battery: the readdir won't return the
+ * entries in sorted order, so battery one won't
+ * necessarily be the first one returned. So, we need
+ * to sort them ourselves before adding them to the
+ * batteries array. */
name = batt->d_name;
/* skip . and .. */
if (!strncmp(".", name, 1) || !strncmp("..", name, 2))
continue;
- sprintf(batteries[batt_count], "/proc/acpi/battery/%s/status", name);
- sprintf(battinfo[batt_count], "/proc/acpi/battery/%s/info", name);
- eprint(1, "battery detected at %s\n", batteries[batt_count]);
- batt_count++;
+ names[globals->battery_count] = strdup(name);
+ globals->battery_count++;
}
closedir(battdir);
+ /* A nice quick insertion sort, ala CLR. */
+ {
+ char *tmp1, *tmp2;
+
+ for (i = 1; i < globals->battery_count; i++) {
+ tmp1 = names[i];
+ j = i - 1;
+ while ((j >= 0) && ((strcmp(tmp1, names[j])) < 0)) {
+ tmp2 = names[j+1];
+ names[j+1] = names[j];
+ names[j] = tmp2;
+ }
+ }
+ }
+
+ for (i = 0; i < globals->battery_count; i++) {
+ snprintf(batteries[i].name, MAX_NAME, "%s", names[i]);
+ snprintf(batteries[i].info_file, MAX_NAME,
+ "/proc/acpi/battery/%s/info", names[i]);
+ snprintf(batteries[i].state_file, MAX_NAME,
+ "/proc/acpi/battery/%s/state", names[i]);
+ pdebug("battery detected at %s\n", batteries[i].info_file);
+ pinfo("found battery %s\n", names[i]);
+ }
+
/* tell user some info */
- eprint(1, "%d batteries detected\n", batt_count);
- fprintf(stderr, "wmacpi: found %d batter%s\n", batt_count,
- (batt_count == 1) ? "y" : "ies");
+ pdebug("%d batteries detected\n", globals->battery_count);
+ pinfo("libacpi: found %d batter%s\n", globals->battery_count,
+ (globals->battery_count == 1) ? "y" : "ies");
return 0;
}
-int acpi_get_design_cap(int battery)
+/* a stub that just calls the current function */
+int reinit_batteries(global_t *globals)
{
- FILE *acpi;
- char *ptr;
- int design_cap;
+ pdebug("reinitialising batteries\n");
+ return init_batteries(globals);
+}
- if (battery > MAXBATT)
- return -1;
+/* the actual name of the subdirectory under ac_adapter may
+ * be anything, so we need to read the directory and use the
+ * name we find there. */
+int init_ac_adapters(global_t *globals)
+{
+ DIR *acdir;
+ struct dirent *adapter;
+ adapter_t *ap = &globals->adapter;
+ char *name;
+
+ acdir = opendir("/proc/acpi/ac_adapter");
+ if (acdir == NULL) {
+ pfatal("Unable to open /proc/acpi/ac_adapter -"
+ " are you sure this system supports ACPI?\n");
+ return 1;
+ }
+ name = NULL;
+ while ((adapter = readdir(acdir)) != NULL) {
+ name = adapter->d_name;
- if (!(acpi = fopen(battinfo[battery], "r")))
- return -1;
+ if (!strncmp(".", name, 1) || !strncmp("..", name, 2))
+ continue;
+ pdebug("found adapter %s\n", name);
+ }
+ closedir(acdir);
+ /* we /should/ only see one filename other than . and .. so
+ * we'll just use the last value name acquires . . . */
+ ap->name = strdup(name);
+ snprintf(ap->state_file, MAX_NAME, "/proc/acpi/ac_adapter/%s/state",
+ ap->name);
+ pinfo("libacpi: found ac adapter %s\n", ap->name);
- fread(buf, 512, 1, acpi);
+ return 0;
+}
+
+/* stub that does nothing but call the normal init function */
+int reinit_ac_adapters(global_t *globals)
+{
+ pdebug("reinitialising ac adapters\n");
+ return init_ac_adapters(globals);
+}
+
+/* see if we have ACPI support and check version */
+int power_init(global_t *globals)
+{
+ FILE *acpi;
+ char buf[4096];
+ int acpi_ver = 0;
+ int retval;
+
+ if (!(acpi = fopen("/proc/acpi/info", "r"))) {
+ pfatal("This system does not support ACPI\n");
+ return 1;
+ }
+
+ /* okay, now see if we got the right version */
+ fread(buf, 4096, 1, acpi);
+ acpi_ver = strtol(buf + 25, NULL, 10);
+ pinfo("ACPI version detected: %d\n", acpi_ver);
+ if (acpi_ver < 20020214) {
+ pfatal("This version requires ACPI subsystem version 20020214\n");
+ fclose(acpi);
+ return 1;
+ }
+ /* yep, all good */
fclose(acpi);
- if ((ptr = strstr(buf, "Last Full Capacity"))) {
- ptr += 25;
- sscanf(ptr, "%d", &design_cap);
- eprint(1, "last full capacity: %d\n", design_cap);
+ if (!(retval = init_batteries(globals)))
+ retval = init_ac_adapters(globals);
+
+ return retval;
+}
+
+/* reinitialise everything, to deal with changing batteries or ac adapters */
+int power_reinit(global_t *globals)
+{
+ FILE *acpi;
+ int retval;
+
+ if (!(acpi = fopen("/proc/acpi/info", "r"))) {
+ pfatal("Could not reopen ACPI info file - does this system support ACPI?\n");
+ return 1;
+ }
+
+ if (!(retval = reinit_batteries(globals)))
+ retval = reinit_ac_adapters(globals);
+
+ return retval;
+}
+
+char *get_value(char *string)
+{
+ char *retval;
+ int i;
+
+ if (string == NULL)
+ return NULL;
+
+ i = 0;
+ while (string[i] != ':') i++;
+ while (!isalnum(string[i])) i++;
+ retval = (string + i);
+
+ return retval;
+}
+
+int check_error(char *buf)
+{
+ if(strstr(buf, "ERROR") != NULL)
+ return 1;
+ return 0;
+}
+
+power_state_t get_power_status(global_t *globals)
+{
+ FILE *file;
+ char buf[1024];
+ char *val;
+ adapter_t *ap = &globals->adapter;
+
+ if ((file = fopen(ap->state_file, "r")) == NULL) {
+ snprintf(buf, 1024, "Could not open state file %s", ap->state_file);
+ perror(buf);
+ return PS_ERR;
+ }
+
+ fgets(buf, 1024, file);
+ fclose(file);
+ val = get_value(buf);
+ if ((strncmp(val, "on-line", 7)) == 0)
+ return AC;
+ else
+ return BATT;
+}
+
+int get_battery_info(int batt_no)
+{
+ FILE *file;
+ battery_t *info = &batteries[batt_no];
+ char buf[1024];
+ char *entry;
+ int buflen;
+ char *val;
+
+ if ((file = fopen(info->info_file, "r")) == NULL) {
+ /* this is cheating, but string concatenation should work . . . */
+ pfatal("Could not open %s:", info->info_file );
+ perror(NULL);
+ return 0;
+ }
+
+ /* grab the contents of the file */
+ buflen = fread(buf, sizeof(buf), 1, file);
+ fclose(file);
+
+ /* check to see if there were any errors reported in the file */
+ if(check_error(buf)) {
+ pinfo("Error reported in file %s - discarding data\n",
+ info->info_file);
+ return 0;
+ }
+
+ /* check to see if battery is present */
+ entry = strstr(buf, "present:");
+ val = get_value(entry);
+ if ((strncmp(val, "yes", 3)) == 0) {
+ info->present = 1;
} else {
- /* hack. if there isnt any info on last capacity, we are
- * screwed, but let's not come back here again */
- design_cap = -1;
- eprint(1, "Cannot retrieve design capacity!");
+ pinfo("Battery %s not present\n", info->name);
+ info->present = 0;
+ return 0;
}
- return design_cap;
+ /* get design capacity
+ * note that all these integer values can also contain the
+ * string 'unknown', so we need to check for this. */
+ entry = strstr(buf, "design capacity:");
+ val = get_value(entry);
+ if (val[0] == 'u')
+ info->design_cap = -1;
+ else
+ info->design_cap = strtoul(val, NULL, 10);
+
+ /* get last full capacity */
+ entry = strstr(buf, "last full capacity:");
+ val = get_value(entry);
+ if (val[0] == 'u')
+ info->last_full_cap = -1;
+ else
+ info->last_full_cap = strtoul(val, NULL, 10);
+
+ /* get design voltage */
+ entry = strstr(buf, "design voltage:");
+ val = get_value(entry);
+ if (val[0] == 'u')
+ info->design_voltage = -1;
+ else
+ info->design_voltage = strtoul(val, NULL, 10);
+
+
+ if ((file = fopen(info->state_file, "r")) == NULL) {
+ perr("Could not open %s:", info->state_file );
+ perror(NULL);
+ return 0;
+ }
+
+ /* grab the file contents */
+ memset(buf, 0, sizeof(buf));
+ buflen = fread(buf, sizeof(buf), 1, file);
+ fclose(file);
+
+ /* check to see if there were any errors reported in the file */
+ if(check_error(buf)) {
+ pinfo("Error reported in file %s - discarding data\n",
+ info->state_file);
+ return 0;
+ }
+ /* check to see if battery is present */
+ entry = strstr(buf, "present:");
+ val = get_value(entry);
+ if ((strncmp(val, "yes", 3)) == 0) {
+ info->present = 1;
+ } else {
+ info->present = 0;
+ perr("Battery %s no longer present\n", info->name);
+ return 0;
+ }
+
+ /* get capacity state
+ * note that this has only two values (at least, in the 2.4.21-rc2
+ * source code) - ok and critical. */
+ entry = strstr(buf, "capacity state:");
+ val = get_value(entry);
+ if (val[0] == 'u')
+ info->capacity_state = CS_ERR;
+ else if ((strncmp(val, "ok", 2)) == 0)
+ info->capacity_state = OK;
+ else
+ info->capacity_state = CRITICAL;
+
+ /* get charging state */
+ entry = strstr(buf, "charging state:");
+ val = get_value(entry);
+ if (val[0] == 'u')
+ info->charge_state = CH_ERR;
+ else if ((strncmp(val, "discharging", 10)) == 0)
+ info->charge_state = DISCHARGE;
+ else
+ info->charge_state = CHARGE;
+
+ /* get current rate of burn
+ * note that if it's on AC, this will report 0 */
+ entry = strstr(buf, "present rate:");
+ val = get_value(entry);
+ if (val[0] == 'u') {
+ info->present_rate = -1;
+ } else {
+ int rate;
+ rate = strtoul(val, NULL, 10);
+ if (rate != 0)
+ info->present_rate = rate;
+ }
+
+ /* get remaining capacity */
+ entry = strstr(buf, "remaining capacity:");
+ val = get_value(entry);
+ if (val[0] == 'u')
+ info->remaining_cap = -1;
+ else
+ info->remaining_cap = strtoul(val, NULL, 10);
+
+ /* get current voltage */
+ entry = strstr(buf, "present voltage:");
+ val = get_value(entry);
+ if (val[0] == 'u')
+ info->present_voltage = -1;
+ else
+ info->present_voltage = strtoul(val, NULL, 10);
+
+ return 1;
}
-void acquire_info(void)
+/*
+ * 2003-7-1.
+ * In order to make this code more convenient for things other than
+ * just plain old wmacpi-ng I'm breaking the basic functionality
+ * up into several chunks: collecting and collating info for a
+ * single battery, calculating the global info (such as rtime), and
+ * some stuff to provide a similar interface to now.
+ */
+
+/* calculate the percentage remaining, using the values of
+ * remaining capacity and last full capacity, as outlined in
+ * the ACPI spec v2.0a, section 3.9.3. */
+static int calc_remaining_percentage(int batt)
{
- FILE *acpi;
- char *ptr;
- char stat;
+ float rcap, lfcap;
+ battery_t *binfo;
+ int retval;
+
+ binfo = &batteries[batt];
+
+ rcap = (float)binfo->remaining_cap;
+ lfcap = (float)binfo->last_full_cap;
+
+ /* we use -1 to indicate that the value is unknown . . . */
+ if (rcap < 0) {
+ perr("unknown percentage value\n");
+ retval = -1;
+ } else {
+ if (lfcap <= 0)
+ lfcap = 1;
+ retval = (int)((rcap/lfcap) * 100.0);
+ pdebug("percent: %d\n", retval);
+ }
+ return retval;
+}
+
+/* check to see if we've been getting bad data from the batteries - if
+ * we get more than some limit we switch to using the remaining capacity
+ * for the calculations. */
+static enum rtime_mode check_rt_mode(global_t *globals)
+{
+ int i;
+ int bad_limit = 5;
+ battery_t *binfo;
+
+ /* if we were told what to do, we should keep doing it */
+ if(globals->rt_forced)
+ return globals->rt_mode;
+
+ for(i = 0; i < MAXBATT; i++) {
+ binfo = &batteries[i];
+ if(binfo->present && globals->adapter.power == BATT) {
+ if(binfo->present_rate <= 0) {
+ pdebug("Bad report from %s\n", binfo->name);
+ binfo->bad_count++;
+ }
+ }
+ }
+ for(i = 0; i < MAXBATT; i++) {
+ binfo = &batteries[i];
+ if(binfo->bad_count > bad_limit) {
+ if(globals->rt_mode != RT_CAP)
+ pinfo("More than %d bad reports from %s; "
+ "Switching to remaining capacity mode\n",
+ bad_limit, binfo->name);
+ return RT_CAP;
+ }
+ }
+ return RT_RATE;
+}
+
+/* calculate remaining time until the battery is charged.
+ * when charging, the battery state file reports the
+ * current being used to charge the battery. We can use
+ * this and the remaining capacity to work out how long
+ * until it reaches the last full capacity of the battery.
+ * XXX: make sure this is actually portable . . . */
+static int calc_charge_time_rate(int batt)
+{
+ float rcap, lfcap;
+ battery_t *binfo;
+ int charge_time = 0;
+
+ binfo = &batteries[batt];
+
+ if (binfo->charge_state == CHARGE) {
+ if (binfo->present_rate == -1) {
+ perr("unknown present rate\n");
+ charge_time = -1;
+ } else {
+ lfcap = (float)binfo->last_full_cap;
+ rcap = (float)binfo->remaining_cap;
+
+ charge_time = (int)(((lfcap - rcap)/binfo->present_rate) * 60.0);
+ }
+ } else
+ if (binfo->charge_time)
+ charge_time = 0;
+ return charge_time;
+}
+
+/* we need to calculate the present rate the same way we do in rt_cap
+ * mode, and then use that to estimate charge time. This will
+ * necessarily be even less accurate than it is for remaining time, but
+ * it's just as neessary . . . */
+static int calc_charge_time_cap(int batt)
+{
+ static float cap_samples[CAP_SAMPLES];
+ static int time_samples[CAP_SAMPLES];
+ static int sample_count = 0;
+ static int current = 0;
+ static int old = 1;
+ int rtime;
+ int tdiff;
+ float cdiff;
+ float current_rate;
+ battery_t *binfo = &batteries[batt];
+
+ cap_samples[current] = (float) binfo->remaining_cap;
+ time_samples[current] = time(NULL);
+
+ if (sample_count == 0) {
+ /* we can't do much if we don't have any data . . . */
+ current_rate = 0;
+ } else if (sample_count < CAP_SAMPLES) {
+ /* if we have less than SAMPLES samples so far, we use the first
+ * sample and the current one */
+ cdiff = cap_samples[current] - cap_samples[0];
+ tdiff = time_samples[current] - time_samples[0];
+ current_rate = cdiff/tdiff;
+ } else {
+ /* if we have more than SAMPLES samples, we use the oldest
+ * current one, which at this point is current + 1. This will
+ * wrap the same way that current will wrap, but one cycle
+ * ahead */
+ cdiff = cap_samples[current] - cap_samples[old];
+ tdiff = time_samples[current] - time_samples[old];
+ current_rate = cdiff/(float)tdiff;
+ }
+ if (current_rate == 0)
+ rtime = 0;
+ else {
+ float cap_left = (float)(binfo->last_full_cap - binfo->remaining_cap);
+ rtime = (int)(cap_left/(current_rate * 60.0));
+ }
+ sample_count++, current++, old++;
+ if (current >= CAP_SAMPLES)
+ current = 0;
+ if (old >= CAP_SAMPLES)
+ old = 0;
+
+ pdebug("cap charge time rem: %d\n", rtime);
+ return rtime;
+}
- static int dcap = 0xdeadbeef;
+static int calc_charge_time(global_t *globals, int batt)
+{
+ int ctime = 0;
- int percent = 100; /* battery percentage */
- int ptemp, rate, rtime = 0;
+ globals->rt_mode = check_rt_mode(globals);
- if (dcap == 0xdeadbeef) {
- /* get from first battery for now */
- dcap = acpi_get_design_cap(0);
+ switch(globals->rt_mode) {
+ case RT_RATE:
+ ctime = calc_charge_time_rate(batt);
+ break;
+ case RT_CAP:
+ ctime = calc_charge_time_cap(batt);
+ break;
}
+ return ctime;
+}
- if (!(acpi = fopen(batteries[0], "r")))
+void acquire_batt_info(global_t *globals, int batt)
+{
+ battery_t *binfo;
+ adapter_t *ap = &globals->adapter;
+
+ get_battery_info(batt);
+
+ binfo = &batteries[batt];
+
+ if (!binfo->present) {
+ binfo->percentage = 0;
+ binfo->valid = 0;
+ binfo->charge_time = 0;
+ globals->rtime = 0;
return;
+ }
- eprint(1, "opened acpi file successfully");
- fread(buf, 512, 1, acpi);
- fclose(acpi);
+ binfo->percentage = calc_remaining_percentage(batt);
+
+ /* set the battery's capacity state, based (at present) on some
+ * guesstimated values: more than 75% == HIGH, 25% to 75% MED, and
+ * less than 25% is LOW. Less than globals->crit_level is CRIT. */
+ if (binfo->percentage == -1)
+ binfo->state = BS_ERR;
+ if (binfo->percentage < globals->crit_level)
+ binfo->state = CRIT;
+ else if (binfo->percentage > 75)
+ binfo->state = HIGH;
+ else if (binfo->percentage > 25)
+ binfo->state = MED;
+ else
+ binfo->state = LOW;
- /* This section of the code will calculate "percentage remaining"
- * using battery capacity, and the following formula (acpi spec 3.9.2):
- * percentage = (current_capacity / last_full_capacity) * 100; */
- if ((ptr = strstr(buf, "Remaining Capacity"))) {
- ptr += 25;
- sscanf(ptr, "%d", &ptemp);
- eprint(1, "capacity: %d\n", ptemp);
- percent = (float)((float)ptemp / (float)dcap) * 100;
- eprint(1, "percent: %d\n", percent);
- }
- apminfo->percentage = percent;
-
- /* this section of code will calculate "time remaining"
- * using battery remaining capacity, and battery "rate" (3.9.3) */
- if ((ptr = strstr(buf, "Present Rate"))) {
- ptr += 25;
- sscanf(ptr, "%d", &rate);
- eprint(1, "rate: %d\n", rate);
- if (rate <= 0)
- rate = 0;
- /* time remaining in minutes */
- rtime = ((float)((float)ptemp / (float)rate)) * 60;
- if (rtime <= 0)
- rtime = 0;
- eprint(1, "time rem: %d\n", rtime);
- }
- apminfo->rtime = rtime;
-
- if ((ptr = strstr(buf, "State:"))) {
- /* found battery discharging. This is used to determine if
- * we are on AC power or not. Notice check for "ch" later on */
- stat = *(ptr + 25);
- if (stat == 'o') /* "ok" : charged, on ac power */
- apminfo->power = POWER;
- else
- /* we set this, and later on use percentage
- * value to determine high/med/low */
- apminfo->power = HIGH;
-
- /* but if we are on power, we might be charging too. Check. */
- if ((ptr = strstr(buf, "State:"))) {
- /* found battery charging line. We will change power state
- * if we are on power, and charging. */
- stat = *(ptr + 25);
- /* this is seriously stupid - but we catch "critical" */
- if (stat == 'c' && (*(ptr + 26) == 'h'))
- apminfo->power = CHARGING;
+ /* we need to /know/ that we've got a valid state for the
+ * globals->power value . . . .*/
+ ap->power = get_power_status(globals);
+
+ if ((ap->power != AC) && (binfo->charge_state == DISCHARGE)) {
+ /* we're not on power, and not charging. So we might as well
+ * check if we're at a critical battery level, and calculate
+ * other interesting stuff . . . */
+ if (binfo->capacity_state == CRITICAL) {
+ pinfo("Received critical battery status");
+ ap->power = HARD_CRIT;
}
}
+
+ binfo->charge_time = calc_charge_time(globals, batt);
- /* we are not on power, and not charging. So, it would make sense
- * to check if battery is "critical low", and calculate interesting
- * things like battery HIGH/LOW, and maybe battery usage LOAD
- * This will be replaced with some code to allow setting user-specified
- * low / critical alarms */
- if ((apminfo->power != POWER) && (apminfo->power != CHARGING)) {
- eprint(1, "entering battery status check");
- if ((ptr = strstr(buf, "State:"))) {
- stat = *(ptr + 25);
- /* only check "c" here because we already caught "CHarging" earlier
- * and also look into crit_level */
- if (stat == 'c' || (apminfo->percentage <= apminfo->crit_level)) {
- /* nothing else to do here - critical battery. get out */
- eprint(1, "Received critical battery status");
- apminfo->power = CRIT;
- }
+ /* and finally, we tell anyone who wants to use this information
+ * that it's now valid . . .*/
+ binfo->valid = 1;
+}
+
+void acquire_all_batt_info(global_t *globals)
+{
+ int i;
+
+ for(i = 0; i < globals->battery_count; i++)
+ acquire_batt_info(globals, i);
+}
+
+/*
+ * One of the feature requests I've had is for some way to deal with
+ * batteries that are too dumb or too b0rken to report a present rate
+ * value. The way to do this, obviously, is to record the time that
+ * samples were taken and use that information to calculate the rate
+ * at which the battery is draining/charging. This still won't help
+ * systems where the battery doesn't even report the remaining
+ * capacity, but without the present rate or the remaining capacity, I
+ * don't think there's /anything/ we can do to work around it.
+ *
+ * So, what we need to do is provide a way to use a different method
+ * to calculate the time remaining. What seems most sensible is to
+ * split out the code to calculate it into a seperate function, and
+ * then provide multiple implementations . . .
+ */
+
+/*
+ * the default implementation - if present rate and remaining capacity
+ * are both reported correctly, we use them.
+ */
+int calc_time_remaining_rate(global_t *globals)
+{
+ int i;
+ int rtime;
+ float rcap = 0;
+ float rate = 0;
+ battery_t *binfo;
+ static float rate_samples[SAMPLES];
+ static int sample_count = 0;
+ static int j = 0;
+ static int n = 0;
+
+ /* calculate the time remaining, using the battery's remaining
+ * capacity and the reported burn rate (3.9.3).
+ * For added accuracy, we average the value over the last
+ * SAMPLES number of calls, or for anything less than this we
+ * simply report the raw number. */
+ /* XXX: this needs to correctly handle the case where
+ * any of the values used is unknown (which we flag using
+ * -1). */
+ for (i = 0; i < globals->battery_count; i++) {
+ binfo = &batteries[i];
+ if (binfo->present && binfo->valid) {
+ rcap += (float)binfo->remaining_cap;
+ rate += (float)binfo->present_rate;
}
}
- process_plugin_timer();
+ rate_samples[j] = rate;
+ j++, sample_count++;
+ if (j >= SAMPLES)
+ j = 0;
+
+ /* for the first SAMPLES number of calls we calculate the
+ * average based on sample_count, then we use SAMPLES to
+ * calculate the rolling average. */
+
+ /* when this fails, n should be equal to SAMPLES. */
+ if (sample_count < SAMPLES)
+ n++;
+ for (i = 0, rate = 0; i < n; i++) {
+ /* if any of our samples are invalid, we drop
+ * straight out, and flag our unknown values. */
+ if (rate_samples[i] < 0) {
+ rate = -1;
+ rtime = -1;
+ goto out;
+ }
+ rate += rate_samples[i];
+ }
+ rate = rate/(float)n;
+
+ if ((rcap < 1) || (rate < 1)) {
+ rtime = 0;
+ goto out;
+ }
+ if (rate <= 0)
+ rate = 1;
+ /* time remaining in minutes */
+ rtime = (int)((rcap/rate) * 60.0);
+ if(rtime <= 0)
+ rtime = 0;
+ out:
+ pdebug("discharge time rem: %d\n", rtime);
+ return rtime;
+}
+
+/*
+ * the alternative implementation - record the time at which each
+ * sample was taken, and then use the difference between the latest
+ * sample and the one SAMPLES ago to calculate the difference over
+ * that time, and from there the rate of change of capacity.
+ *
+ * XXX: this code sucks, but largely because batteries aren't exactly
+ * precision instruments - mine only report with about 70mAH
+ * resolution, so they don't report any changes until the difference
+ * is 70mAH. This means that calculating the current rate from the
+ * remaining capacity is very choppy . . .
+ *
+ * To fix this, we should calculate an average over some number of
+ * samples at the old end of the set - this would smooth out the
+ * transitions.
+ */
+int calc_time_remaining_cap(global_t *globals)
+{
+ static float cap_samples[CAP_SAMPLES];
+ static int time_samples[CAP_SAMPLES];
+ static int sample_count = 0;
+ static int current = 0;
+ static int old = 1;
+ battery_t *binfo;
+ int i;
+ int rtime;
+ int tdiff;
+ float cdiff;
+ float cap = 0;
+ float current_rate;
+
+ for (i = 0; i < globals->battery_count; i++) {
+ binfo = &batteries[i];
+ if (binfo->present && binfo->valid)
+ cap += binfo->remaining_cap;
+ }
+ cap_samples[current] = cap;
+ time_samples[current] = time(NULL);
+
+ if (sample_count == 0) {
+ /* we can't do much if we don't have any data . . . */
+ current_rate = 0;
+ } else if (sample_count < CAP_SAMPLES) {
+ /* if we have less than SAMPLES samples so far, we use the first
+ * sample and the current one */
+ cdiff = cap_samples[0] - cap_samples[current];
+ tdiff = time_samples[current] - time_samples[0];
+ current_rate = cdiff/tdiff;
+ } else {
+ /* if we have more than SAMPLES samples, we use the oldest
+ * current one, which at this point is current + 1. This will
+ * wrap the same way that current will wrap, but one cycle
+ * ahead */
+ cdiff = cap_samples[old] - cap_samples[current];
+ tdiff = time_samples[current] - time_samples[old];
+ current_rate = cdiff/tdiff;
+ }
+ if (current_rate == 0)
+ rtime = 0;
+ else
+ rtime = (int)(cap_samples[current]/(current_rate * 60.0));
+
+ sample_count++, current++, old++;
+ if (current >= CAP_SAMPLES)
+ current = 0;
+ if (old >= CAP_SAMPLES)
+ old = 0;
+
+ pdebug("cap discharge time rem: %d\n", rtime);
+ return rtime;
+}
+
+void acquire_global_info(global_t *globals)
+{
+ adapter_t *ap = &globals->adapter;
- eprint(1, "current state: %s (%d)", state[apminfo->power], apminfo->power);
+ globals->rt_mode = check_rt_mode(globals);
+
+ switch(globals->rt_mode) {
+ case RT_RATE:
+ globals->rtime = calc_time_remaining_rate(globals);
+ break;
+ case RT_CAP:
+ globals->rtime = calc_time_remaining_cap(globals);
+ break;
+ }
+
+ /* get the power status.
+ * note that this is actually reported seperately from the
+ * battery info, under /proc/acpi/ac_adapter/AC/state */
+ ap->power = get_power_status(globals);
+}
+
+void acquire_all_info(global_t *globals)
+{
+ acquire_all_batt_info(globals);
+ acquire_global_info(globals);
}
-#endif /* ACPI */
diff --git a/libacpi.h b/libacpi.h
new file mode 100644
index 0000000..7cdaf5d
--- /dev/null
+++ b/libacpi.h
@@ -0,0 +1,144 @@
+#ifndef _LIBACPI_H_
+#define _LIBACPI_H_
+
+
+#define LIBACPI_VER "0.92"
+
+/* Here because we need it for definitions in this file . . . */
+#define MAX_NAME 128
+#define MAXBATT 8
+#define SAMPLES 50
+#define CAP_SAMPLES (SAMPLES*10)
+
+typedef enum {
+ REMAIN,
+ TIMER
+} DspMode;
+
+typedef enum {
+ AC,
+ BATT,
+ PS_ERR,
+} power_state_t;
+
+typedef enum {
+ HIGH,
+ MED,
+ LOW,
+ CRIT,
+ HARD_CRIT,
+ BS_ERR,
+} batt_state_t;
+
+typedef enum {
+ CHARGE,
+ DISCHARGE,
+ CH_ERR,
+} charge_state_t;
+
+typedef enum {
+ OK,
+ CRITICAL,
+ CS_ERR,
+} cap_state_t;
+
+typedef struct {
+ /* general info */
+ char name[MAX_NAME];
+ /* these two are conveniences */
+ char info_file[MAX_NAME];
+ char state_file[MAX_NAME];
+ int present;
+ int design_cap; /* assuming mAh */
+ int last_full_cap;
+ int design_voltage; /* in mV */
+ /* state info */
+ cap_state_t capacity_state;
+ charge_state_t charge_state;
+ int present_rate; /* in mAh */
+ int remaining_cap; /* in mAh */
+ int present_voltage; /* in mV */
+ /* calculated states */
+ batt_state_t state;
+ int percentage; /* stored here because this is a per battery thing */
+ int charge_time; /* time left to charge this battery */
+ /* and a flag to indicate that this is valid . . . */
+ int valid;
+ /* number of times we've gotten bad info on this battery's present rate */
+ int bad_count;
+} battery_t;
+
+typedef struct {
+ char *name;
+ char state_file[MAX_NAME];
+ power_state_t power;
+} adapter_t;
+
+/* how to calculate the time remaining */
+enum rtime_mode {
+ RT_RATE, /* using the current rate, as per the ACPI spec */
+ RT_CAP, /* using the remaining capacity over time */
+};
+
+typedef struct {
+ int rtime; /* remaining time */
+ int timer; /* how long been on battery? */
+ int crit_level; /* anything below this is critical low */
+ int battery_count; /* number of batteries found */
+ enum rtime_mode rt_mode; /* remaining time mode */
+ int rt_forced; /* was our rt_mode forced? if so, we do what we were told */
+ battery_t *binfo; /* pointer to the battery being monitored */
+ adapter_t adapter;
+} global_t;
+
+/*
+ * Moving percentage to the battery is right, but I think we need a global
+ * remaining capacity somewhere, too . . .
+ */
+
+/*
+ * To provide a convenient debugging function . . .
+ *
+ * It's a macro because I'm too lazy to deal with varargs.
+ */
+
+#define pdebug(fmt, arg...) \
+ do { \
+ if (verbosity > 2) \
+ fprintf(stderr, fmt, ##arg); \
+ } while (0)
+
+#define pinfo(fmt, arg...) \
+ do { \
+ if (verbosity > 1) \
+ fprintf(stderr, fmt, ##arg); \
+ } while (0)
+
+#define perr(fmt, arg...) \
+ do { \
+ if (verbosity > 0) \
+ fprintf(stderr, fmt, ##arg); \
+ } while (0)
+
+#define pfatal(fmt, arg...) \
+ fprintf(stderr, fmt, ##arg) \
+
+
+/* Since these /are/ needed here . . . */
+battery_t batteries[MAXBATT];
+int verbosity;
+
+/* check if apm/acpi is enabled, etc */
+int power_init(global_t *globals);
+/* reinitialise everything */
+int power_reinit(global_t *globals);
+int reinit_ac_adapters(global_t *globals);
+int reinit_batteries(global_t *globals);
+
+/* fill global_t with data */
+void acquire_batt_info(global_t *globals, int batt);
+void acquire_all_batt_info(global_t *globals);
+void acquire_global_info(global_t *globals);
+void acquire_all_info(global_t *globals);
+
+#endif /* _WMACPI_H_ */
diff --git a/libapm.c b/libapm.c
deleted file mode 100644
index 684da76..0000000
--- a/libapm.c
+++ /dev/null
@@ -1,91 +0,0 @@
-#include <stdio.h>
-#include "wmacpi.h"
-
-#ifdef APM
-#ifdef PRO
-extern char *state[];
-#endif
-extern APMInfo *apminfo;
-extern int crit_level;
-
-int power_init(void)
-{
- FILE *apm;
-
- if (!(apm = fopen("/proc/apm", "r"))) {
- fprintf(stderr, "This system does not support APM\n");
- return 1;
- }
- fclose(apm);
-
- return 0;
-}
-
-void acquire_info(void)
-{
- FILE *apm;
- char buf[256];
- char min[10];
-
- int ac_line, batt, percent, rtime;
-
-#ifdef PRO
- /* testing */
- if (!(apm = fopen("apm", "r")))
- return;
-#else
- if (!(apm = fopen("/proc/apm", "r")))
- return;
-#endif
-
- fgets(buf, 255, apm);
- sscanf(buf, "%*s %*s %*s %x %x %*s %d%% %d %s",
- &ac_line, &batt, &percent, &rtime, min);
-
- eprint(0, "%02x %02x, %03d%%, %d", ac_line, batt, percent, rtime);
- apminfo->percentage = percent;
- apminfo->rtime = rtime;
-
- switch (ac_line) {
- case 0: /* on battery. calculate status. handle charging under AC */
- switch (batt) {
- case 0:
- apminfo->power = HIGH;
- break;
- case 1:
- apminfo->power = LOW;
- break;
- case 2:
- apminfo->power = CRIT;
- break;
- }
-
- /* check user-defined critical alarm */
- if (apminfo->percentage <= apminfo->crit_level)
- apminfo->power = CRIT;
-
- break;
- case 1: /* on AC power. Check if battery is being charged */
-#ifdef RETARDED_APM
- /* this is incase your battery is "charging" all the fucking time,
- * even when it's actually done charging */
- if ((batt == 3) && (percent != 100))
-#else
- if (batt == 3)
-#endif
- apminfo->power = CHARGING;
- else
- apminfo->power = POWER;
- break;
-#ifdef STUPID_APM
- /* treatment for GAY apm bioses that show wrong time
- * remaining when AC is plugged in */
- apminfo->rtime = 0;
-#endif
- }
- fclose(apm);
- process_plugin_timer();
-
- eprint(1, "current state: %s (%d)", state[apminfo->power], apminfo->power);
-}
-#endif /* APM */
diff --git a/master.xpm b/master.xpm
index 30c5d58..e958772 100644
--- a/master.xpm
+++ b/master.xpm
@@ -1,6 +1,6 @@
/* XPM */
static char * master_xpm[] = {
-"157 88 116 2",
+"157 88 100 2",
" c None",
". c #000000",
"+ c #FF0000",
@@ -93,30 +93,14 @@ static char * master_xpm[] = {
"Y c #054000",
"Z c #034000",
"` c #C7C7C7",
-" . c #303030",
+" . c #004941",
".. c #20B2AE",
-"+. c #004941",
-"@. c #188A86",
-"#. c #DAF5B2",
-"$. c #355600",
-"%. c #FEFFFF",
-"&. c #AAAFA9",
-"*. c #315900",
-"=. c #D0D2D1",
-"-. c #FDFEF6",
-";. c #FF2D00",
-">. c #DA0710",
-",. c #F3FFF9",
-"'. c #A5F812",
-"). c #A7ACB2",
-"!. c #4F5354",
-"~. c #87F91F",
-"{. c #94F625",
-"]. c #C0C6BC",
-"^. c #22B2AE",
-"/. c #027E72",
-"(. c #034A40",
-"_. c #107D79",
+"+. c #303030",
+"@. c #027E72",
+"#. c #188A86",
+"$. c #22B2AE",
+"%. c #034A40",
+"&. c #107D79",
" . + @ # $ % & * = - % ; > , ' % ) ! ~ { % ] ^ / ( % _ : < [ % } | 1 2 % 3 4 5 6 % 7 8 9 0 % a b c d % e f g h ",
" . + @ # $ % & * = - % ; > , ' % ) ! ~ { % ] ^ / ( % _ : < [ % } | 1 2 % 3 4 5 6 % 7 8 9 0 % a b c d % e f g h ",
" . + @ # $ % & * = - % ; > , ' % ) ! ~ { % ] ^ / ( % _ : < [ % } | 1 2 % 3 4 5 6 % 7 8 9 0 % a b c d % e f g h ",
@@ -130,78 +114,78 @@ static char * master_xpm[] = {
" . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
" . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
" . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
-" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
-" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % % % % % % % % % % % % % % % % % % % ` . . . . .% . . . .% . . . .% . . . .% . . . .% . . . .% . . . .% . . . .% . . . .% . . . .% . . . . ",
-" . % % % % % % ..........% % % % ....................% % ` . % % % % % +.+.+.% % % +.+.+.% % % ..% % % % % ` . ",
-" . % % % % % ..% % % % ......% % ..% % % % % % % % ..% % ` . % % +.% +.% % % +.% +.% % % +.% ..% ..% ..% % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ",
-" . % % % % % ..% % % % ..% % % % ..% % % % % % % % ....% ` . % % +.% +.% % % +.% +.% % % +.% % ..% ..% % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ",
-" . % % % ......% % % % ..% % % % ..% % % % % % % % ....% ` . % % % % % +.+.+.% % % +.+.+.% % % % ..% % % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ",
-" . % % ..% % ..% % % % ......% % ..% % % % % % % % ....% ` . % % +.% +.% % % +.% +.% % % +.% % ..% ..% % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ",
-" . % ..% % % % ..........% % % % ..% % % % % % % % ..% % ` . % % +.% +.% % % +.% +.% % % +.% ..% ..% ..% % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ",
-" . % ..% % % % % % % % % % % % % ....................% % ` . % % % % % +.+.+.% % % +.+.+.% % % % % ..% % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % % % % % % % % % % % % % % % % % % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % % % % % % % % % % % % % % % % % % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z ",
+" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % . . . .% % % . . . .% % % % % % % . . . .% % % . . . .% % ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % .% % % % .% .% % % % .% % ..% % .% % % % .% .% % % % .% ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % % % % % % % % % % % % % % % % % % % ` . +.+.+.+.% +.+.+.+.% +.+.+.+.% +.+.+.+.% +.+.+.+.% +.+.+.+.% +.+.+.+.% +.+.+.+.% +.+.+.+.% +.+.+.+.% +.+.+.+. % .% % % % .% .% % % % .% % ..% % .% % % % .% .% % % % .% ",
+" . % % % % % % ..........% % % % ....................% % ` . % % % % % . . .% % % . . .% % % ..% % % % % ` . % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% ",
+" . % % % % % ..% % % % ......% % ..% % % % % % % % ..% % ` . % % .% .% % % .% .% % % .% ..% ..% ..% % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z % @......... at .% @......... at .% % % % % @......... at .% @......... at .% ",
+" . % % % % % ..% % % % ..% % % % ..% % % % % % % % ....% ` . % % .% .% % % .% .% % % .% % ..% ..% % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
+" . % % % ......% % % % ..% % % % ..% % % % % % % % ....% ` . % % % % % . . .% % % . . .% % % % ..% % % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z % .% % % % .% .% % % % .% % ..% % .% % % % .% .% % % % .% ",
+" . % % ..% % ..% % % % ......% % ..% % % % % % % % ....% ` . % % .% .% % % .% .% % % .% % ..% ..% % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z % .% % % % .% .% % % % .% % ..% % .% % % % .% .% % % % .% ",
+" . % ..% % % % ..........% % % % ..% % % % % % % % ..% % ` . % % .% .% % % .% .% % % .% ..% ..% ..% % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% ",
+" . % ..% % % % % % % % % % % % % ....................% % ` . % % % % % . . .% % % . . .% % % % % ..% % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % % % % % % % % % % % % % % % % % % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z % % . . . .% % % . . . .% % % % % % % . . . .% % % . . . .% % ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % % % % % % % % % % % % % % % % % % % ` . i j k l % m n o p % q r s t % u v w x % y z A B % C D E F % G H I J % K L M N % O P Q R % S T U V % W X Y Z % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` . ",
" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
-" . % % ......% % % +.+.+. at .% @....... at .% @....... at .% @.+.+.+. at .% @....... at .% @....... at .% @....... at .% @....... at .% @....... at .% % ..% % % % % % % ",
-" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ` . % ..% % % ..% +.% % % ..% +.% % % ..% +.% % % ..% ..% % % ..% ..% % % +.% ..% % % +.% +.% % % ..% ..% % % ..% ..% % % ..% ..% ..% ..% % ..% ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . #.$.$.. %.%.%.%.%.%.%.%.%.&.% ` . % ..% % % ..% +.% % % ..% +.% % % ..% +.% % % ..% ..% % % ..% ..% % % +.% ..% % % +.% +.% % % ..% ..% % % ..% ..% % % ..% % ..% ..% % % @.% ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . $.*.*.. %.=.=.=.=.=.=.=.=.&.% ` . % @.+.+.+. at .% % +.+.+. at .% @....... at .% % ...... at .% @....... at .% @....... at .% @....... at .% % +.+.+. at .% @....... at .% @....... at .% % % ..% % % % % % ",
-" . % % % +.+.+.+.% % % +.+.+.+.% % % % % % % +.+.+.+.% % % +.+.+.+.% % % ` . $.*.*.. %.=.=.=.=.=.=.=.=.&.% ` . % ..% % % ..% +.% % % ..% ..% % % +.% +.% % % ..% +.% % % ..% +.% % % ..% ..% % % ..% +.% % % ..% ..% % % ..% +.% % % ..% % ..% ..% % % % % ",
-" . % % +.% % % % +.% +.% % % % +.% % +.% % +.% % % % +.% +.% % % % +.% % ` . . . . . %.=.=.=.=.=.=.=.=.&.% ` . % ..% % % ..% +.% % % ..% ..% % % +.% +.% % % ..% +.% % % ..% +.% % % ..% ..% % % ..% +.% % % ..% ..% % % ..% +.% % % ..% ..% ..% ..% % ..% -.;.;. ",
-" . % % +.% % % % +.% +.% % % % +.% % +.% % +.% % % % +.% +.% % % % +.% % ` . %.%.%.%.%.=.=.=.=.=.=.=.=.&.% ` . % % ......% % % +.+.+. at .% @....... at .% @....... at .% % +.+.+. at .% @....... at .% @....... at .% % +.+.+. at .% @....... at .% @....... at .% % % % ..% % % @.% ;.;.;. ",
-" . % % +.% % % % +.% +.% % % % +.% % % % % +.% % % % +.% +.% % % % +.% % ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ;.;.>. ",
-" . % % +.% % % % +.% +.% % % % +.% % % % % +.% % % % +.% +.% % % % +.% % ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` . ",
-" . % % % +.+.+.+.% % % +.+.+.+.% % % % % % % +.+.+.+.% % % +.+.+.+.% % % ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % . . . . . . . . . . . . . . . . ` . . . . . . . . . . . . . . . . ` ",
-" . % % +.% % % % +.% +.% % % % +.% % % % % +.% % % % +.% +.% % % % +.% % ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` . % % % % % % ..........% % % % ....................% % % @.% % ......% % % ......% % % ..% % % % . ,.'.'.. ).).).).).).).).).!.% ` . #.$.$.. %.%.%.%.%.%.%.%.%.&.% ` ",
-" . % % +.% % % % +.% +.% % % % +.% % % % % +.% % % % +.% +.% % % % +.% % ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` . % % % % % ..% % % % ......% % ..% % % % % % % % ..% % % ..% ..% % % ..% ..% % % ..% ..% ..% ..% . '.~.{.. ).].].].].].].].].!.% ` . $.*.*.. %.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % +.% % % % +.% +.% % % % +.% % +.% % +.% % % % +.% +.% % % % +.% % ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` . % % % % % ..% % % % ..% % % % ..% % % % % % % % ....% % ..% ..% % % ..% ..% % % ..% % ..% ..% % . '.{.{.. ).].].].].].].].].!.% ` . $.*.*.. %.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % +.% % % % +.% +.% % % % +.% % +.% % +.% % % % +.% +.% % % % +.% % ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` . % % % ......% % % % ..% % % % ..% % % % % % % % ....% % @.% @.+.+.+. at .% @.+.+.+. at .% % % ..% % % . . . . . ).].].].].].].].].!.% ` . . . . . %.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % % +.+.+.+.% % % +.+.+.+.% % % % % % % +.+.+.+.% % % +.+.+.+.% % % ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` . % % ..% % ..% % % % ......% % ..% % % % % % % % ....% % ..% ..% % % ..% ..% % % ..% % ..% ..% % . ).).).).).].].].].].].].].!.% ` . %.%.%.%.%.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . %.&.&.&.&.&.&.&.&.&.&.&.&.&.% ` . % ..% % % % ..........% % % % ..% % % % % % % % ..% % % ..% ..% % % ..% ..% % % ..% ..% ..% ..% . ).].].].].].].].].].].].].!.% ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . . . . . . . . . . . . . . . % ` . % ..% % % % % % % % % % % % % ....................% % % @.% % ......% % % ......% % % % % ..% % . ).].].].].].].].].].].].].!.% ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` ",
-" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % . ).].].].].].].].].].].].].!.% ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` ",
-" . . ).].].].].].].].].].].].].!.% ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % . ).].].].].].].].].].].].].!.% ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` ",
-" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % % % % % % +.+.+.+.+.% % % % +.+.+.+.+.+.+.+.+.+.% % % % % % +.+.+.% % % +.+.+.% % % +.% % % % . ).].].].].].].].].].].].].!.% ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % +.% % % % +.+.+.% % +.% % % % % % % % +.% % % +.% +.% % % +.% +.% % % +.% +.% +.% +.% . ).].].].].].].].].].].].].!.% ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % +.% % % % +.% % % % +.% % % % % % % % +.+.% % +.% +.% % % +.% +.% % % +.% % +.% +.% % . ).].].].].].].].].].].].].!.% ` . %.=.=.=.=.=.=.=.=.=.=.=.=.&.% ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % +.+.+.% % % % +.% % % % +.% % % % % % % % +.+.% % % % % +.+.+.% % % +.+.+.% % % % +.% % % . ).!.!.!.!.!.!.!.!.!.!.!.!.!.% ` . %.&.&.&.&.&.&.&.&.&.&.&.&.&.% ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % +.% % +.% % % % +.+.+.% % +.% % % % % % % % +.+.% % +.% +.% % % +.% +.% % % +.% % +.% +.% % . . . . . . . . . . . . . . . % ` . . . . . . . . . . . . . . . % ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % +.% % % % +.+.+.+.+.% % % % +.% % % % % % % % +.% % % +.% +.% % % +.% +.% % % +.% +.% +.% +.% ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % +.% % % % % % % % % % % % % +.+.+.+.+.+.+.+.+.+.% % % % % % +.+.+.% % % +.+.+.% % % % % +.% % ",
+" . % % ......% % % . . .#.% #.......#.% #.......#.% #. . . .#.% #.......#.% #.......#.% #.......#.% #.......#.% #.......#.% % ..% % % % % % % ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ` . % ..% % % ..% .% % % ..% .% % % ..% .% % % ..% ..% % % ..% ..% % % .% ..% % % .% .% % % ..% ..% % % ..% ..% % % ..% ..% ..% ..% % ..% ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` % % % % % % % % % % % % % % % % ` . % ..% % % ..% .% % % ..% .% % % ..% .% % % ..% ..% % % ..% ..% % % .% ..% % % .% .% % % ..% ..% % % ..% ..% % % ..% % ..% ..% % % #.% ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` % % % % % % % % % % % % % % % % ` . % #. . . .#.% % . . .#.% #.......#.% % ......#.% #.......#.% #.......#.% #.......#.% % . . .#.% #.......#.% #.......#.% % % ..% % % % % % ",
+" . % % % . . . .% % % . . . .% % % % % % % . . . .% % % . . . .% % % ` % % % % % % % % % . . . .% % % ` . % ..% % % ..% .% % % ..% ..% % % .% .% % % ..% .% % % ..% .% % % ..% ..% % % ..% .% % % ..% ..% % % ..% .% % % ..% % ..% ..% % % % % ",
+" . % % .% % % % .% .% % % % .% % .% % .% % % % .% .% % % % .% % ` % % % % % % % % .% % % % .% % ` . % ..% % % ..% .% % % ..% ..% % % .% .% % % ..% .% % % ..% .% % % ..% ..% % % ..% .% % % ..% ..% % % ..% .% % % ..% ..% ..% ..% % ..% ",
+" . % % .% % % % .% .% % % % .% % .% % .% % % % .% .% % % % .% % ` % $.$.$.$.% % % .% % % % .% % ` . % % ......% % % . . .#.% #.......#.% #.......#.% % . . .#.% #.......#.% #.......#.% % . . .#.% #.......#.% #.......#.% % % % ..% % % #.% ",
+" . % % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% % ` % $.% % % $.% % .% % % % .% % ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
+" . % % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% % ` % $.% % % $.% % .% % % % .% % ` . ",
+" . % % % . . . .% % % . . . .% % % % % % % . . . .% % % . . . .% % % ` % $.% % % $.% % % . . . .% % % ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % . . . . . . . . . . . . . . . . ` ",
+" . % % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% % ` % $.$.$.$.% % % .% % % % .% % ` . % % % % % % ..........% % % % ....................% % % #.% % ......% % % ......% % % ..% % % % % % % % % % % % % % % % % % % % ` ",
+" . % % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% % ` % $.% % % $.% % .% % % % .% % ` . % % % % % ..% % % % ......% % ..% % % % % % % % ..% % % ..% ..% % % ..% ..% % % ..% ..% ..% ..% % % % % % % % % % % % % % % % % ` ",
+" . % % .% % % % .% .% % % % .% % .% % .% % % % .% .% % % % .% % ` % $.% % % $.% % .% % % % .% % ` . % % % % % ..% % % % ..% % % % ..% % % % % % % % ....% % ..% ..% % % ..% ..% % % ..% % ..% ..% % % % % % % % % % % . . . .% % % ` ",
+" . % % .% % % % .% .% % % % .% % .% % .% % % % .% .% % % % .% % ` % $.% % % $.% % .% % % % .% % ` . % % % ......% % % % ..% % % % ..% % % % % % % % ....% % #.% #. . . .#.% #. . . .#.% % % ..% % % % % % % % % % % .% % % % .% % ` ",
+" . % % % . . . .% % % . . . .% % % % % % % . . . .% % % . . . .% % % ` % $.$.$.$.% % % % . . . .% % % ` . % % ..% % ..% % % % ......% % ..% % % % % % % % ....% % ..% ..% % % ..% ..% % % ..% % ..% ..% % % $.$.$.$.% % % .% % % % .% % ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` % % % % % % % % % % % % % % % % ` . % ..% % % % ..........% % % % ..% % % % % % % % ..% % % ..% ..% % % ..% ..% % % ..% ..% ..% ..% % $.% % % $.% % .% % % % .% % ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` % % % % % % % % % % % % % % % % ` . % ..% % % % % % % % % % % % % ....................% % % #.% % ......% % % ......% % % % % ..% % % $.% % % $.% % .% % % % .% % ` ",
+" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % $.% % % $.% % % . . . .% % % ` ",
+" . % $.$.$.$.% % % .% % % % .% % ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % $.% % % $.% % .% % % % .% % ` ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % % % % % % . . . . .% % % % . . . . . . . . . .% % % % % % . . .% % % . . .% % % .% % % % % $.% % % $.% % .% % % % .% % ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % .% % % % . . .% % .% % % % % % % % .% % % .% .% % % .% .% % % .% .% .% .% % $.% % % $.% % .% % % % .% % ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % .% % % % .% % % % .% % % % % % % % . .% % .% .% % % .% .% % % .% % .% .% % % $.$.$.$.% % % % . . . .% % % ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % . . .% % % % .% % % % .% % % % % % % % . .% % % % % . . .% % % . . .% % % % .% % % % % % % % % % % % % % % % % % % ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % .% % .% % % % . . .% % .% % % % % % % % . .% % .% .% % % .% .% % % .% % .% .% % % % % % % % % % % % % % % % % % ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % .% % % % . . . . .% % % % .% % % % % % % % .% % % .% .% % % .% .% % % .% .% .% .% ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % .% % % % % % % % % % % % % . . . . . . . . . .% % % % % % . . .% % % . . .% % % % % .% % ",
" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . ",
" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
-" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % ^.^.^.% % % % % % /.% /.^.^.^./.% /.^.^.^./.% /.% % % /.% /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% % % % % % % % % % % % % % % % % % % ",
-" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` . % ^.% % % ^.% % % % % ^.% % % % % ^.% % % % % ^.% ^.% % % ^.% ^.% % % % % ^.% % % % % % % % % ^.% ^.% % % ^.% ^.% % % ^.% % % % % % % % % % % % % % % % % % % ",
-" . % ^.% % % ^.% % % % % ^.% % % % % ^.% % % % % ^.% ^.% % % ^.% ^.% % % % % ^.% % % % % % % % % ^.% ^.% % % ^.% ^.% % % ^.% % % % % % % % % % % % % % % % % % % ",
-" . % /.% % % /.% % % % % /.% /.^.^.^./.% % ^.^.^./.% /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% % % % % /.% (.^.^.^.(.% /.^.^.^./.% /.^.^.^./.% % % % % % % % % % % % % ",
-" . % ^.% % % ^.% % % % % ^.% ^.% % % % % % % % % ^.% % % % % ^.% % % % % ^.% ^.% % % ^.% % % % % ^.% ^.% % % ^.% % % % % ^.% % % % % % % % % % % % % % % % % % % ",
-" . % ^.% % % ^.% % % % % ^.% ^.% % % % % % % % % ^.% % % % % ^.% % % % % ^.% ^.% % % ^.% % % % % ^.% ^.% % % ^.% % % % % ^.% % % % % % % % % % % % % % % % % % % ",
-". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % % ^.^.^.% % % % % % ^.% /.^.^.^./.% /.^.^.^./.% % % % % /.% /.^.^.^./.% /.^.^.^./.% % % % % /.% /.^.^.^./.% /.^.^.^./.% % % % % % % % % % % % % % % % % ^.% ",
+" . % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ` . % % $.$.$.% % % % % % @.% @.$.$.$. at .% @.$.$.$. at .% @.% % % @.% @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% % % % % % % % % % % % % % % % % % % ",
+" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` . % $.% % % $.% % % % % $.% % % % % $.% % % % % $.% $.% % % $.% $.% % % % % $.% % % % % % % % % $.% $.% % % $.% $.% % % $.% % % % % % % % % % % % % % % % % % % ",
+" . % $.% % % $.% % % % % $.% % % % % $.% % % % % $.% $.% % % $.% $.% % % % % $.% % % % % % % % % $.% $.% % % $.% $.% % % $.% % % % % % % % % % % % % % % % % % % ",
+" . % @.% % % @.% % % % % @.% @.$.$.$. at .% % $.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% % % % % @.% %.$.$.$.%.% @.$.$.$. at .% @.$.$.$. at .% % % % % % % % % % % % % ",
+" . % $.% % % $.% % % % % $.% $.% % % % % % % % % $.% % % % % $.% % % % % $.% $.% % % $.% % % % % $.% $.% % % $.% % % % % $.% % % % % % % % % % % % % % % % % % % ",
+" . % $.% % % $.% % % % % $.% $.% % % % % % % % % $.% % % % % $.% % % % % $.% $.% % % $.% % % % % $.% $.% % % $.% % % % % $.% % % % % % % % % % % % % % % % % % % ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % % $.$.$.% % % % % % $.% @.$.$.$. at .% @.$.$.$. at .% % % % % @.% @.$.$.$. at .% @.$.$.$. at .% % % % % @.% @.$.$.$. at .% @.$.$.$. at .% % % % % % % % % % % % % % % % % $.% ",
" % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
-"% (.^.^.^.(.% /.^.^.^.% % /.^.^.^./.% /.^.^.^.% % /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% /.% % % /.% % % /.% % % % % % % /.% /.% % % /.% /.% % % % % ^.% % % ^.% /.^.^.^.% % /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% /.^.^.^./.% /.% % % /.% /.% % % /.% /.% % % /.% /.% % % /.% /.% % % /.% /.^.^.^./.% ",
-"% ^.% % % ^.% ^.% % % ^.% ^.% % % % % ^.% % % ^.% ^.% % % % % ^.% % % % % ^.% % % % % ^.% % % ^.% % % ^.% % % % % % % ^.% ^.% % % ^.% ^.% % % % % ^.^.% ^.^.% ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % % % % % ^.% % % ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% % % % % ^.% ",
-"% ^.% % % ^.% ^.% % % ^.% ^.% % % % % ^.% % % ^.% ^.% % % % % ^.% % % % % ^.% % % % % ^.% % % ^.% % % ^.% % % % % % % ^.% ^.% % ^.(.% ^.% % % % % ^.% ^.% ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % % % % % ^.% % % ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% (.^.% ^.(.% ^.% % % ^.% % % % ^.(.% ",
-"% /.^.^.^./.% /.^.^.^.% % /.% % % % % /.% % % /.% /.^.^.^.% % /.^.^.^.% % /.(.^.^./.% /.^.^.^./.% % % /.% % % % % % % /.% /.^.^.(.% % /.% % % % % /.% % % /.% /.% % % /.% /.% % % /.% /.^.^.^./.% /.^.% % /.% /.^.^.^.% % /.^.^.^./.% % % /.% % % /.% % % /.% /.% % % /.% /.% % % /.% % (.^.(.% % /.^.^.^./.% % (.^.(.% % ",
-"% ^.% % % ^.% ^.% % % ^.% ^.% % % % % ^.% % % ^.% ^.% % % % % ^.% % % % % ^.% % % ^.% ^.% % % ^.% % % ^.% % % % % % % ^.% ^.% % ^.(.% ^.% % % % % ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % % % ^.% ^.% ^.% ^.% % % ^.% % % % % ^.% % % ^.% % % ^.% % % ^.% ^.% % % ^.% ^.% ^.% ^.% (.^.% ^.(.% % % % % ^.% (.^.% % % % ",
-"% ^.% % % ^.% ^.% % % ^.% ^.% % % % % ^.% % % ^.% ^.% % % % % ^.% % % % % ^.% % % ^.% ^.% % % ^.% % % ^.% % % % % % % ^.% ^.% % % ^.% ^.% % % % % ^.% % % ^.% ^.% % % ^.% ^.% % % ^.% ^.% % % % % ^.% % ^.^.% ^.% % % ^.% % % % % ^.% % % ^.% % % ^.% % % ^.% ^.% % % ^.% ^.^.% ^.^.% ^.% % % ^.% % % % % ^.% ^.% % % % % ",
-"% /.% % % /.% /.^.^.^.% % /.^.^.^./.% ^.^.^.^.% % /.^.^.^./.% ^.% % % % % /.^.^.^./.% /.% % % /.% % % ^.% % % /.^.^.^./.% /.% % % /.% /.^.^.^.(.% /.% % % /.% ^.% % % ^.% /.^.^.^./.% /.% % % % % /.^.^.^./.% /.% % % /.% /.^.^.^./.% % % /.% % % (.^.^.^.^.% % ^.^.^.% % ^.% % % ^.% /.% % % ^.% /.^.^.^./.% /.^.^.^./.% ",
+"% %.$.$.$.%.% @.$.$.$.% % @.$.$.$. at .% @.$.$.$.% % @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% @.% % % @.% % % @.% % % % % % % @.% @.% % % @.% @.% % % % % $.% % % $.% @.$.$.$.% % @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% @.$.$.$. at .% @.% % % @.% @.% % % @.% @.% % % @.% @.% % % @.% @.% % % @.% @.$.$.$. at .% ",
+"% $.% % % $.% $.% % % $.% $.% % % % % $.% % % $.% $.% % % % % $.% % % % % $.% % % % % $.% % % $.% % % $.% % % % % % % $.% $.% % % $.% $.% % % % % $.$.% $.$.% $.% % % $.% $.% % % $.% $.% % % $.% $.% % % $.% $.% % % $.% $.% % % % % % % $.% % % $.% % % $.% $.% % % $.% $.% % % $.% $.% % % $.% $.% % % $.% % % % % $.% ",
+"% $.% % % $.% $.% % % $.% $.% % % % % $.% % % $.% $.% % % % % $.% % % % % $.% % % % % $.% % % $.% % % $.% % % % % % % $.% $.% % $.%.% $.% % % % % $.% $.% $.% $.% % % $.% $.% % % $.% $.% % % $.% $.% % % $.% $.% % % $.% $.% % % % % % % $.% % % $.% % % $.% $.% % % $.% $.% % % $.% %.$.% $.%.% $.% % % $.% % % % $.%.% ",
+"% @.$.$.$. at .% @.$.$.$.% % @.% % % % % @.% % % @.% @.$.$.$.% % @.$.$.$.% % @.%.$.$. at .% @.$.$.$. at .% % % @.% % % % % % % @.% @.$.$.%.% % @.% % % % % @.% % % @.% @.% % % @.% @.% % % @.% @.$.$.$. at .% @.$.% % @.% @.$.$.$.% % @.$.$.$. at .% % % @.% % % @.% % % @.% @.% % % @.% @.% % % @.% % %.$.%.% % @.$.$.$. at .% % %.$.%.% % ",
+"% $.% % % $.% $.% % % $.% $.% % % % % $.% % % $.% $.% % % % % $.% % % % % $.% % % $.% $.% % % $.% % % $.% % % % % % % $.% $.% % $.%.% $.% % % % % $.% % % $.% $.% % % $.% $.% % % $.% $.% % % % % $.% $.% $.% $.% % % $.% % % % % $.% % % $.% % % $.% % % $.% $.% % % $.% $.% $.% $.% %.$.% $.%.% % % % % $.% %.$.% % % % ",
+"% $.% % % $.% $.% % % $.% $.% % % % % $.% % % $.% $.% % % % % $.% % % % % $.% % % $.% $.% % % $.% % % $.% % % % % % % $.% $.% % % $.% $.% % % % % $.% % % $.% $.% % % $.% $.% % % $.% $.% % % % % $.% % $.$.% $.% % % $.% % % % % $.% % % $.% % % $.% % % $.% $.% % % $.% $.$.% $.$.% $.% % % $.% % % % % $.% $.% % % % % ",
+"% @.% % % @.% @.$.$.$.% % @.$.$.$. at .% $.$.$.$.% % @.$.$.$. at .% $.% % % % % @.$.$.$. at .% @.% % % @.% % % $.% % % @.$.$.$. at .% @.% % % @.% @.$.$.$.%.% @.% % % @.% $.% % % $.% @.$.$.$. at .% @.% % % % % @.$.$.$. at .% @.% % % @.% @.$.$.$. at .% % % @.% % % %.$.$.$.$.% % $.$.$.% % $.% % % $.% @.% % % $.% @.$.$.$. at .% @.$.$.$. at .% ",
"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ",
-"% % ........% % % +.+.+.+._.% _......... at .% _........._.% _.+.+.+.+._.% _........._.% _......... at .% _........._.% _......... at .% _......... at .% % % % % % % ........% % % ........% % % % % % % ........% % % ........% % % % +.+.+.+.% % % +.+.+.+.% % % % % % % +.+.+.+.% % % +.+.+.+.% % % % ^.+.+.+.^.% ",
-"% ..% % % % ..% +.% % % % ..% +.% % % % ..% +.% % % % ..% ..% % % % ..% ..% % % % +.% ..% % % % +.% +.% % % % ..% ..% % % % ..% ..% % % % ..% % ..% % % ..% % % % ..% ..% % % % ..% % ..% % ..% % % % ..% ..% % % % ..% % +.% % % % +.% +.% % % % +.% % +.% % +.% % % % +.% +.% % % % +.% % ^.% ^.% ^.+.% ",
-"% ..% % % % ..% +.% % % % ..% +.% % % % ..% +.% % % % ..% ..% % % % ..% ..% % % % +.% ..% % % % +.% +.% % % % ..% ..% % % % ..% ..% % % % ..% % ..% % % ..% % % % ..% ..% % % % ..% % ..% % ..% % % % ..% ..% % % % ..% % +.% % % % +.% +.% % % % +.% % +.% % +.% % % % +.% +.% % % % +.% % +.^.% ^.% +.% ",
-"% ..% % % % ..% +.% % % % ..% +.% % % % ..% +.% % % % ..% ..% % % % ..% ..% % % % +.% ..% % % % +.% +.% % % % ..% ..% % % % ..% ..% % % % ..% % % % % % ..% % % % ..% ..% % % % ..% % % % % ..% % % % ..% ..% % % % ..% % +.% % % % +.% +.% % % % +.% % % % % +.% % % % +.% +.% % % % +.% % +.% ^.% ^.+.% ",
-"% ..% % % % ..% +.% % % % ..% +.% % % % ..% +.% % % % ..% ..% % % % ..% ..% % % % +.% ..% % % % +.% +.% % % % ..% ..% % % % ..% ..% % % % ..% % % % % % ..% % % % ..% ..% % % % ..% % % % % ..% % % % ..% ..% % % % ..% % +.% % % % +.% +.% % % % +.% % % % % +.% % % % +.% +.% % % % +.% % +.^.% ^.% ^.% ",
-"% _.+.+.+.+._.% % +.+.+.+._.% _........._.% _........._.% _........._.% _........._.% _........._.% % +.+.+.+._.% _........._.% _........._.% % % % % % _.+.+.+.+._.% _.+.+.+.+._.% % % % % _.+.+.+.+._.% _.+.+.+.+._.% % % +.+.+.+.% % % +.+.+.+.% % % % % % % +.+.+.+.% % % +.+.+.+.% % % ^.+.+.+.^.% % ",
-"% ..% % % % ..% +.% % % % ..% ..% % % % +.% +.% % % % ..% +.% % % % ..% +.% % % % ..% ..% % % % ..% +.% % % % ..% ..% % % % ..% +.% % % % ..% % % % % % ..% % % % ..% ..% % % % ..% % % % % ..% % % % ..% ..% % % % ..% % +.% % % % +.% +.% % % % +.% % % % % +.% % % % +.% +.% % % % +.% % +.% % % % +.% ",
-"% ..% % % % ..% +.% % % % ..% ..% % % % +.% +.% % % % ..% +.% % % % ..% +.% % % % ..% ..% % % % ..% +.% % % % ..% ..% % % % ..% +.% % % % ..% % % % % % ..% % % % ..% ..% % % % ..% % % % % ..% % % % ..% ..% % % % ..% % +.% % % % +.% +.% % % % +.% % % % % +.% % % % +.% +.% % % % +.% % ^.^.^.^.^.+.% ",
-"% ..% % % % ..% +.% % % % ..% ..% % % % +.% +.% % % % ..% +.% % % % ..% +.% % % % ..% ..% % % % ..% +.% % % % ..% ..% % % % ..% +.% % % % ..% % ..% % % ..% % % % ..% ..% % % % ..% % ..% % ..% % % % ..% ..% % % % ..% % +.% % % % +.% +.% % % % +.% % +.% % +.% % % % +.% +.% % % % +.% % ^.% % % ^.^.% ",
-"% ..% % % % ..% +.% % % % ..% ..% % % % +.% +.% % % % ..% +.% % % % ..% +.% % % % ..% ..% % % % ..% +.% % % % ..% ..% % % % ..% +.% % % % ..% % ..% % % ..% % % % ..% ..% % % % ..% % ..% % ..% % % % ..% ..% % % % ..% % +.% % % % +.% +.% % % % +.% % +.% % +.% % % % +.% +.% % % % +.% % ^.% % % ^.^.% ",
-"% % ........% % % +.+.+.+._.% _........._.% _........._.% % +.+.+.+._.% _........._.% _........._.% % +.+.+.+._.% _........._.% _........._.% % % % % % % ........% % % ........% % % % % % % ........% % % ........% % % % +.+.+.+.% % % +.+.+.+.% % % % % % % +.+.+.+.% % % +.+.+.+.% % % ^.^.^.^.^.% % ",
+"% % ........% % % . . . .&.% &.........#.% &.........&.% &. . . . .&.% &.........&.% &.........#.% &.........&.% &.........#.% &.........#.% % % % % % % ........% % % ........% % % % % % % ........% % % ........% % % % . . . .% % % . . . .% % % % % % % . . . .% % % . . . .% % % % $. . . .$.% ",
+"% ..% % % % ..% .% % % % ..% .% % % % ..% .% % % % ..% ..% % % % ..% ..% % % % .% ..% % % % .% .% % % % ..% ..% % % % ..% ..% % % % ..% % ..% % % ..% % % % ..% ..% % % % ..% % ..% % ..% % % % ..% ..% % % % ..% % .% % % % .% .% % % % .% % .% % .% % % % .% .% % % % .% % $.% $.% $. .% ",
+"% ..% % % % ..% .% % % % ..% .% % % % ..% .% % % % ..% ..% % % % ..% ..% % % % .% ..% % % % .% .% % % % ..% ..% % % % ..% ..% % % % ..% % ..% % % ..% % % % ..% ..% % % % ..% % ..% % ..% % % % ..% ..% % % % ..% % .% % % % .% .% % % % .% % .% % .% % % % .% .% % % % .% % .$.% $.% .% ",
+"% ..% % % % ..% .% % % % ..% .% % % % ..% .% % % % ..% ..% % % % ..% ..% % % % .% ..% % % % .% .% % % % ..% ..% % % % ..% ..% % % % ..% % % % % % ..% % % % ..% ..% % % % ..% % % % % ..% % % % ..% ..% % % % ..% % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% % .% $.% $. .% ",
+"% ..% % % % ..% .% % % % ..% .% % % % ..% .% % % % ..% ..% % % % ..% ..% % % % .% ..% % % % .% .% % % % ..% ..% % % % ..% ..% % % % ..% % % % % % ..% % % % ..% ..% % % % ..% % % % % ..% % % % ..% ..% % % % ..% % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% % .$.% $.% $.% ",
+"% &. . . . .&.% % . . . .&.% &.........&.% &.........&.% &.........&.% &.........&.% &.........&.% % . . . .&.% &.........&.% &.........&.% % % % % % &. . . . .&.% &. . . . .&.% % % % % &. . . . .&.% &. . . . .&.% % % . . . .% % % . . . .% % % % % % % . . . .% % % . . . .% % % $. . . .$.% % ",
+"% ..% % % % ..% .% % % % ..% ..% % % % .% .% % % % ..% .% % % % ..% .% % % % ..% ..% % % % ..% .% % % % ..% ..% % % % ..% .% % % % ..% % % % % % ..% % % % ..% ..% % % % ..% % % % % ..% % % % ..% ..% % % % ..% % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% % .% % % % .% ",
+"% ..% % % % ..% .% % % % ..% ..% % % % .% .% % % % ..% .% % % % ..% .% % % % ..% ..% % % % ..% .% % % % ..% ..% % % % ..% .% % % % ..% % % % % % ..% % % % ..% ..% % % % ..% % % % % ..% % % % ..% ..% % % % ..% % .% % % % .% .% % % % .% % % % % .% % % % .% .% % % % .% % $.$.$.$.$. .% ",
+"% ..% % % % ..% .% % % % ..% ..% % % % .% .% % % % ..% .% % % % ..% .% % % % ..% ..% % % % ..% .% % % % ..% ..% % % % ..% .% % % % ..% % ..% % % ..% % % % ..% ..% % % % ..% % ..% % ..% % % % ..% ..% % % % ..% % .% % % % .% .% % % % .% % .% % .% % % % .% .% % % % .% % $.% % % $.$.% ",
+"% ..% % % % ..% .% % % % ..% ..% % % % .% .% % % % ..% .% % % % ..% .% % % % ..% ..% % % % ..% .% % % % ..% ..% % % % ..% .% % % % ..% % ..% % % ..% % % % ..% ..% % % % ..% % ..% % ..% % % % ..% ..% % % % ..% % .% % % % .% .% % % % .% % .% % .% % % % .% .% % % % .% % $.% % % $.$.% ",
+"% % ........% % % . . . .&.% &.........&.% &.........&.% % . . . .&.% &.........&.% &.........&.% % . . . .&.% &.........&.% &.........&.% % % % % % % ........% % % ........% % % % % % % ........% % % ........% % % % . . . .% % % . . . .% % % % % % % . . . .% % % . . . .% % % $.$.$.$.$.% % ",
"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "};
diff --git a/master_low.xpm b/master_low.xpm
index 2156b41..1d91d52 100644
--- a/master_low.xpm
+++ b/master_low.xpm
@@ -1,6 +1,6 @@
/* XPM */
-static char * master_xpm[] = {
-"157 88 20 1",
+static char * master_low_xpm[] = {
+"157 88 18 1",
" c None",
". c #000000",
"+ c #FF0000",
@@ -11,16 +11,14 @@ static char * master_xpm[] = {
"& c #403B00",
"* c #034000",
"= c #AAAFA9",
-"- c #20B2AE",
-"; c #004941",
-"> c #188A86",
-", c #D0D2D1",
-"' c #FEFFFF",
-") c #4F5354",
-"! c #22B2AE",
-"~ c #027E72",
-"{ c #034A40",
-"] c #107D79",
+"- c #004941",
+"; c #20B2AE",
+"> c #027E72",
+", c #188A86",
+"' c #22B2AE",
+") c #C7C7C7",
+"! c #034A40",
+"~ c #107D79",
" . ++++ at ++++@++++@####@####@####@####@$$$$@$$$$@$$$$@$$$$ ",
" . ++++ at ++++@++++@####@####@####@####@$$$$@$$$$@$$$$@$$$$ ",
" . ++++ at ++++@++++@####@####@####@####@$$$$@$$$$@$$$$@$$$$ ",
@@ -34,78 +32,78 @@ static char * master_xpm[] = {
" .%%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@****= . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
" .%%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@****= . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
" .%%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@****= . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
-" ======================================================== . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
-" . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
-" ............................. ......................... . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@= .@@@@@@@@@@@@@@@@@@@@@@@= . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
-" .@@@@@@-----@@@@----------@@= .@@@@@;;;@@@;;;@@@-@@@@@= . ",
-" .@@@@@-@@@@---@@-@@@@@@@@-@@= .@@;@;@@@;@;@@@;@- at -@-@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** ",
-" .@@@@@-@@@@-@@@@-@@@@@@@@--@= .@@;@;@@@;@;@@@;@@- at -@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** ",
-" .@@@---@@@@-@@@@-@@@@@@@@--@= .@@@@@;;;@@@;;;@@@@-@@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** ",
-" .@@-@@-@@@@---@@-@@@@@@@@--@= .@@;@;@@@;@;@@@;@@- at -@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** ",
-" . at -@@@@-----@@@@-@@@@@@@@-@@= .@@;@;@@@;@;@@@;@- at -@-@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** ",
-" . at -@@@@@@@@@@@@@----------@@= .@@@@@;;;@@@;;;@@@@@-@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@= .@@@@@@@@@@@@@@@@@@@@@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@= .@@@@@@@@@@@@@@@@@@@@@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** ",
+" ======================================================== . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
+" . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@----@@@----@@@@@@@----@@@----@@ ",
+" ............................. ......................... . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @-@@@@- at -@@@@-@@;@@-@@@@- at -@@@@-@ ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@= .@@@@@@@@@@@@@@@@@@@@@@@= . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @-@@@@- at -@@@@-@@;@@-@@@@- at -@@@@-@ ",
+" .@@@@@@;;;;;@@@@;;;;;;;;;;@@= .@@@@@---@@@---@@@;@@@@@= . @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ ",
+" .@@@@@;@@@@;;;@@;@@@@@@@@;@@= .@@- at -@@@- at -@@@-@;@;@;@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** @>;;;;>@>;;;;>@@@@@>;;;;>@>;;;;>@ ",
+" .@@@@@;@@@@;@@@@;@@@@@@@@;;@= .@@- at -@@@- at -@@@-@@;@;@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
+" .@@@;;;@@@@;@@@@;@@@@@@@@;;@= .@@@@@---@@@---@@@@;@@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** @-@@@@- at -@@@@-@@;@@-@@@@- at -@@@@-@ ",
+" .@@;@@;@@@@;;;@@;@@@@@@@@;;@= .@@- at -@@@- at -@@@-@@;@;@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** @-@@@@- at -@@@@-@@;@@-@@@@- at -@@@@-@ ",
+" .@;@@@@;;;;;@@@@;@@@@@@@@;@@= .@@- at -@@@- at -@@@-@;@;@;@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ ",
+" .@;@@@@@@@@@@@@@;;;;;;;;;;@@= .@@@@@---@@@---@@@@@;@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@= .@@@@@@@@@@@@@@@@@@@@@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** @@----@@@----@@@@@@@----@@@----@@ ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@= .@@@@@@@@@@@@@@@@@@@@@@@= . %%%%@%%%%@%%%%@&&&&@&&&&@&&&&@&&&&@****@****@****@**** @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
" ============================= ========================= . ",
" . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
-" . @@---@@@;;;>@>--->@>--->@>;;;>@>--->@>--->@>--->@>--->@>--->@@-@@@@@@@ ",
-" ..................................... ................= . @-@@@-@;@@@-@;@@@-@;@@@- at -@@@- at -@@@;@-@@@;@;@@@- at -@@@- at -@@@- at -@- at -@@-@ ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= .,**.'''''''''=@= . @-@@@-@;@@@-@;@@@-@;@@@- at -@@@- at -@@@;@-@@@;@;@@@- at -@@@- at -@@@-@@- at -@@@>@ ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= .***.',,,,,,,,=@= . @>;;;>@@;;;>@>--->@@--->@>--->@>--->@>--->@@;;;>@>--->@>--->@@@-@@@@@@ ",
-" .@@@;;;;@@@;;;;@@@@@@@;;;;@@@;;;;@@@= .***.',,,,,,,,=@= . @-@@@-@;@@@- at -@@@;@;@@@-@;@@@-@;@@@- at -@@@-@;@@@- at -@@@-@;@@@-@@- at -@@@@@ ",
-" .@@;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@@= .....',,,,,,,,=@= . @-@@@-@;@@@- at -@@@;@;@@@-@;@@@-@;@@@- at -@@@-@;@@@- at -@@@-@;@@@- at -@- at -@@-@ ,++ ",
-" .@@;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@@= .''''',,,,,,,,=@= . @@---@@@;;;>@>--->@>--->@@;;;>@>--->@>--->@@;;;>@>--->@>--->@@@@-@@@>@ +++ ",
-" .@@;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@@= .',,,,,,,,,,,,=@= . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +++ ",
-" .@@;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@@= .',,,,,,,,,,,,=@= . ",
-" .@@@;;;;@@@;;;;@@@@@@@;;;;@@@;;;;@@@= .',,,,,,,,,,,,=@= . @@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ ................= ................= ",
-" .@@;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@@= .',,,,,,,,,,,,=@= . @@@@@@-----@@@ @----------@@ @>@@---@@@---@@@-@@@@ .,$$.))))))))))@= .,**.'''''''''=@= ",
-" .@@;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@@= .',,,,,,,,,,,,=@= . @@@@@-@@@@---@ @-@@@@@@@@-@@ @- at -@@@- at -@@@- at -@- at -@ .$$$.),,,,,,,,=@= .***.',,,,,,,,=@= ",
-" .@@;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@@= .',,,,,,,,,,,,=@= . @@@@@-@@@@-@@@ @-@@@@@@@@--@ @- at -@@@- at -@@@-@@- at -@@ .$$$.),,,,,,,,=@= .***.',,,,,,,,=@= ",
-" .@@;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@@= .',,,,,,,,,,,,=@= . @@@---@@@@-@@@ @-@@@@@@@@--@ @>@>;;;>@>;;;>@@@-@@@ .....),,,,,,,,=@= .....',,,,,,,,=@= ",
-" .@@@;;;;@@@;;;;@@@@@@@;;;;@@@;;;;@@@= .',,,,,,,,,,,,=@= . @@-@@-@@@@---@ @-@@@@@@@@--@ @- at -@@@- at -@@@-@@- at -@@ .))))),,,,,,,,=@= .''''',,,,,,,,=@= ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= .'=============@= . @-@@@@-----@@@ @-@@@@@@@@-@@ @- at -@@@- at -@@@- at -@- at -@ .),,,,,,,,,,,,=@= .',,,,,,,,,,,,=@= ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= ...............@= . @-@@@@@@@@@@@@ @----------@@ @>@@---@@@---@@@@@-@@ .),,,,,,,,,,,,=@= .',,,,,,,,,,,,=@= ",
-" ===================================== ================= . @@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ .),,,,,,,,,,,,=@= .',,,,,,,,,,,,=@= ",
-" . .),,,,,,,,,,,,=@= .',,,,,,,,,,,,=@= ",
-" . @@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ .),,,,,,,,,,,,=@= .',,,,,,,,,,,,=@= ",
-" ........................................................ . @@@@@@;;;;;@@@ @;;;;;;;;;;@@ @@@@;;;@@@;;;@@@;@@@@ .),,,,,,,,,,,,=@= .',,,,,,,,,,,,=@= ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@@@@;@@@@;;;@ @;@@@@@@@@;@@ @;@;@@@;@;@@@;@;@;@;@ .),,,,,,,,,,,,=@= .',,,,,,,,,,,,=@= ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@@@@;@@@@;@@@ @;@@@@@@@@;;@ @;@;@@@;@;@@@;@@;@;@@ .),,,,,,,,,,,,=@= .',,,,,,,,,,,,=@= ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@@;;;@@@@;@@@ @;@@@@@@@@;;@ @@@@;;;@@@;;;@@@@;@@@ .)=============@= .'=============@= ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@;@@;@@@@;;;@ @;@@@@@@@@;;@ @;@;@@@;@;@@@;@@;@;@@ ...............@= ...............@= ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @;@@@@;;;;;@@@ @;@@@@@@@@;@@ @;@;@@@;@;@@@;@;@;@;@ ================= ================= ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @;@@@@@@@@@@@@ @;;;;;;;;;;@@ @@@@;;;@@@;;;@@@@@;@@ ",
+" . @@;;;@@@---,@,;;;,@,;;;,@,---,@,;;;,@,;;;,@,;;;,@,;;;,@,;;;,@@;@@@@@@@ ",
+" ..................................... ................= . @;@@@;@-@@@;@-@@@;@-@@@;@;@@@;@;@@@-@;@@@- at -@@@;@;@@@;@;@@@;@;@;@;@@;@ ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= @@@@@@@@@@@@@@@@= . @;@@@;@-@@@;@-@@@;@-@@@;@;@@@;@;@@@-@;@@@- at -@@@;@;@@@;@;@@@;@@;@;@@@,@ ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= @@@@@@@@@@@@@@@@= . @,---,@@---,@,;;;,@@;;;,@,;;;,@,;;;,@,;;;,@@---,@,;;;,@,;;;,@@@;@@@@@@ ",
+" .@@@----@@@----@@@@@@@----@@@----@@@= @@@@@@@@@----@@@= . @;@@@;@-@@@;@;@@@- at -@@@;@-@@@;@-@@@;@;@@@;@-@@@;@;@@@;@-@@@;@@;@;@@@@@ ",
+" .@@-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@@= @@@@@@@@-@@@@-@@= . @;@@@;@-@@@;@;@@@- at -@@@;@-@@@;@-@@@;@;@@@;@-@@@;@;@@@;@-@@@;@;@;@;@@;@ ",
+" .@@-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@@= @''''@@@-@@@@-@@= . @@;;;@@@---,@,;;;,@,;;;,@@---,@,;;;,@,;;;,@@---,@,;;;,@,;;;,@@@@;@@@,@ ",
+" .@@-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@@= @'@@@'@@-@@@@-@@= . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
+" .@@-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@@= @'@@@'@@-@@@@-@@= . ",
+" .@@@----@@@----@@@@@@@----@@@----@@@= @'@@@'@@@----@@@= . @@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ ................) ",
+" .@@-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@@= @''''@@@-@@@@-@@= . @@@@@@;;;;;@@@ @;;;;;;;;;;@@ @,@@;;;@@@;;;@@@;@@@@ @@@@@@@@@@@@@@@@) ",
+" .@@-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@@= @'@@@'@@-@@@@-@@= . @@@@@;@@@@;;;@ @;@@@@@@@@;@@ @;@;@@@;@;@@@;@;@;@;@ @@@@@@@@@@@@@@@@) ",
+" .@@-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@@= @'@@@'@@-@@@@-@@= . @@@@@;@@@@;@@@ @;@@@@@@@@;;@ @;@;@@@;@;@@@;@@;@;@@ @@@@@@@@@----@@@) ",
+" .@@-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@@= @'@@@'@@-@@@@-@@= . @@@;;;@@@@;@@@ @;@@@@@@@@;;@ @,@,---,@,---,@@@;@@@ @@@@@@@@-@@@@-@@) ",
+" .@@@----@@@----@@@@@@@----@@@----@@@= @''''@@@@----@@@= . @@;@@;@@@@;;;@ @;@@@@@@@@;;@ @;@;@@@;@;@@@;@@;@;@@ @''''@@@-@@@@-@@) ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= @@@@@@@@@@@@@@@@= . @;@@@@;;;;;@@@ @;@@@@@@@@;@@ @;@;@@@;@;@@@;@;@;@;@ @'@@@'@@-@@@@-@@) ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= @@@@@@@@@@@@@@@@= . @;@@@@@@@@@@@@ @;;;;;;;;;;@@ @,@@;;;@@@;;;@@@@@;@@ @'@@@'@@-@@@@-@@) ",
+" ===================================== ================= . @@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ @'@@@'@@@----@@@) ",
+" . @''''@@@-@@@@-@@) ",
+" . @@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ @'@@@'@@-@@@@-@@) ",
+" ........................................................ . @@@@@@-----@@@ @----------@@ @@@@---@@@---@@@-@@@@ @'@@@'@@-@@@@-@@) ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@@@@-@@@@---@ @-@@@@@@@@-@@ @- at -@@@- at -@@@- at -@- at -@ @'@@@'@@-@@@@-@@) ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@@@@-@@@@-@@@ @-@@@@@@@@--@ @- at -@@@- at -@@@-@@- at -@@ @''''@@@@----@@@) ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@@---@@@@-@@@ @-@@@@@@@@--@ @@@@---@@@---@@@@-@@@ @@@@@@@@@@@@@@@@) ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@-@@-@@@@---@ @-@@@@@@@@--@ @- at -@@@- at -@@@-@@- at -@@ @@@@@@@@@@@@@@@@) ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @-@@@@-----@@@ @-@@@@@@@@-@@ @- at -@@@- at -@@@- at -@- at -@ ))))))))))))))))) ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @-@@@@@@@@@@@@ @----------@@ @@@@---@@@---@@@@@-@@ ",
" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ ",
" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . ",
" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@ ",
-" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@!!!@@@@@@~@~!!!~@~!!!~@~@@@~@~!!!~@~!!!~@~!!!~@~!!!~@~!!!~@@@@@@@@@@@@@ @@@@@@ ",
-" ======================================================== . @!@@@!@@@@@!@@@@@!@@@@@!@!@@@!@!@@@@@!@@@@@@@@@!@!@@@!@!@@@!@@@@@@@@@@@@@ @@@@@@ ",
-" . @!@@@!@@@@@!@@@@@!@@@@@!@!@@@!@!@@@@@!@@@@@@@@@!@!@@@!@!@@@!@@@@@@@@@@@@@ @@@@@@ ",
-" . @~@@@~@@@@@~@~!!!~@@!!!~@~!!!~@~!!!~@~!!!~@@@@@~@{!!!{@~!!!~@~!!!~@@@@@@@ @@@@@@ ",
-" . @!@@@!@@@@@!@!@@@@@@@@@!@@@@@!@@@@@!@!@@@!@@@@@!@!@@@!@@@@@!@@@@@@@@@@@@@ @@@@@@ ",
-" . @!@@@!@@@@@!@!@@@@@@@@@!@@@@@!@@@@@!@!@@@!@@@@@!@!@@@!@@@@@!@@@@@@@@@@@@@ @@@@@@ ",
-"................................................................. @@!!!@@@@@@!@~!!!~@~!!!~@@@@@~@~!!!~@~!!!~@@@@@~@~!!!~@~!!!~@@@@@@@@@@@@@ @@@@!@ ",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= . @@'''@@@@@@>@>'''>@>'''>@>@@@>@>'''>@>'''>@>'''>@>'''>@>'''>@@@@@@@@@@@@@ @@@@@@ ",
+" ======================================================== . @'@@@'@@@@@'@@@@@'@@@@@'@'@@@'@'@@@@@'@@@@@@@@@'@'@@@'@'@@@'@@@@@@@@@@@@@ @@@@@@ ",
+" . @'@@@'@@@@@'@@@@@'@@@@@'@'@@@'@'@@@@@'@@@@@@@@@'@'@@@'@'@@@'@@@@@@@@@@@@@ @@@@@@ ",
+" . @>@@@>@@@@@>@>'''>@@'''>@>'''>@>'''>@>'''>@@@@@>@!'''!@>'''>@>'''>@@@@@@@ @@@@@@ ",
+" . @'@@@'@@@@@'@'@@@@@@@@@'@@@@@'@@@@@'@'@@@'@@@@@'@'@@@'@@@@@'@@@@@@@@@@@@@ @@@@@@ ",
+" . @'@@@'@@@@@'@'@@@@@@@@@'@@@@@'@@@@@'@'@@@'@@@@@'@'@@@'@@@@@'@@@@@@@@@@@@@ @@@@@@ ",
+"................................................................. @@'''@@@@@@'@>'''>@>'''>@@@@@>@>'''>@>'''>@@@@@>@>'''>@>'''>@@@@@@@@@@@@@ @@@@'@ ",
" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
-"@{!!!{@~!!!@@~!!!~@~!!!@@~!!!~@~!!!~@~!!!~@~@@@~@@@~@@@@@@@~@~@@@~@~@@@@@!@@@!@~!!!@@~!!!~@~!!!~@~!!!~@~!!!~@~!!!~@~!!!~@~@@@~@~@@@~@~@@@~@~@@@~@~@@@~@~!!!~@",
-"@!@@@!@!@@@!@!@@@@@!@@@!@!@@@@@!@@@@@!@@@@@!@@@!@@@!@@@@@@@!@!@@@!@!@@@@@!!@!!@!@@@!@!@@@!@!@@@!@!@@@!@!@@@!@!@@@@@@@!@@@!@@@!@!@@@!@!@@@!@!@@@!@!@@@!@@@@@!@",
-"@!@@@!@!@@@!@!@@@@@!@@@!@!@@@@@!@@@@@!@@@@@!@@@!@@@!@@@@@@@!@!@@!{@!@@@@@!@!@!@!@@@!@!@@@!@!@@@!@!@@@!@!@@@!@!@@@@@@@!@@@!@@@!@!@@@!@!@@@!@{!@!{@!@@@!@@@@!{@",
-"@~!!!~@~!!!@@~@@@@@~@@@~@~!!!@@~!!!@@~{!!~@~!!!~@@@~@@@@@@@~@~!!{@@~@@@@@~@@@~@~@@@~@~@@@~@~!!!~@~!@@~@~!!!@@~!!!~@@@~@@@~@@@~@~@@@~@~@@@~@@{!{@@~!!!~@@{!{@@",
-"@!@@@!@!@@@!@!@@@@@!@@@!@!@@@@@!@@@@@!@@@!@!@@@!@@@!@@@@@@@!@!@@!{@!@@@@@!@@@!@!@@@!@!@@@!@!@@@@@!@!@!@!@@@!@@@@@!@@@!@@@!@@@!@!@@@!@!@!@!@{!@!{@@@@@!@{!@@@@",
-"@!@@@!@!@@@!@!@@@@@!@@@!@!@@@@@!@@@@@!@@@!@!@@@!@@@!@@@@@@@!@!@@@!@!@@@@@!@@@!@!@@@!@!@@@!@!@@@@@!@@!!@!@@@!@@@@@!@@@!@@@!@@@!@!@@@!@!!@!!@!@@@!@@@@@!@!@@@@@",
-"@~@@@~@~!!!@@~!!!~@!!!!@@~!!!~@!@@@@@~!!!~@~@@@~@@@!@@@~!!!~@~@@@~@~!!!{@~@@@~@!@@@!@~!!!~@~@@@@@~!!!~@~@@@~@~!!!~@@@~@@@{!!!!@@!!!@@!@@@!@~@@@!@~!!!~@~!!!~@",
+"@!'''!@>'''@@>'''>@>'''@@>'''>@>'''>@>'''>@>@@@>@@@>@@@@@@@>@>@@@>@>@@@@@'@@@'@>'''@@>'''>@>'''>@>'''>@>'''>@>'''>@>'''>@>@@@>@>@@@>@>@@@>@>@@@>@>@@@>@>'''>@",
+"@'@@@'@'@@@'@'@@@@@'@@@'@'@@@@@'@@@@@'@@@@@'@@@'@@@'@@@@@@@'@'@@@'@'@@@@@''@''@'@@@'@'@@@'@'@@@'@'@@@'@'@@@'@'@@@@@@@'@@@'@@@'@'@@@'@'@@@'@'@@@'@'@@@'@@@@@'@",
+"@'@@@'@'@@@'@'@@@@@'@@@'@'@@@@@'@@@@@'@@@@@'@@@'@@@'@@@@@@@'@'@@'!@'@@@@@'@'@'@'@@@'@'@@@'@'@@@'@'@@@'@'@@@'@'@@@@@@@'@@@'@@@'@'@@@'@'@@@'@!'@'!@'@@@'@@@@'!@",
+"@>'''>@>'''@@>@@@@@>@@@>@>'''@@>'''@@>!''>@>'''>@@@>@@@@@@@>@>''!@@>@@@@@>@@@>@>@@@>@>@@@>@>'''>@>'@@>@>'''@@>'''>@@@>@@@>@@@>@>@@@>@>@@@>@@!'!@@>'''>@@!'!@@",
+"@'@@@'@'@@@'@'@@@@@'@@@'@'@@@@@'@@@@@'@@@'@'@@@'@@@'@@@@@@@'@'@@'!@'@@@@@'@@@'@'@@@'@'@@@'@'@@@@@'@'@'@'@@@'@@@@@'@@@'@@@'@@@'@'@@@'@'@'@'@!'@'!@@@@@'@!'@@@@",
+"@'@@@'@'@@@'@'@@@@@'@@@'@'@@@@@'@@@@@'@@@'@'@@@'@@@'@@@@@@@'@'@@@'@'@@@@@'@@@'@'@@@'@'@@@'@'@@@@@'@@''@'@@@'@@@@@'@@@'@@@'@@@'@'@@@'@''@''@'@@@'@@@@@'@'@@@@@",
+"@>@@@>@>'''@@>'''>@''''@@>'''>@'@@@@@>'''>@>@@@>@@@'@@@>'''>@>@@@>@>'''!@>@@@>@'@@@'@>'''>@>@@@@@>'''>@>@@@>@>'''>@@@>@@@!''''@@'''@@'@@@'@>@@@'@>'''>@>'''>@",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@",
-"@@----@@@;;;;]@]---->@]----]@];;;;]@]----]@]---->@]----]@]---->@]---->@@@@@ @@----@@@----@@@@@@@----@@@----@@ @@;;;;@@@;;;;@@@@@@@;;;;@@@;;;;@@ @@!;;;!@",
-"@-@@@@-@;@@@@-@;@@@@-@;@@@@- at -@@@@- at -@@@@;@-@@@@;@;@@@@- at -@@@@- at -@@@@-@@-@@ @-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@ @;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@ @!@!@!;@",
-"@-@@@@-@;@@@@-@;@@@@-@;@@@@- at -@@@@- at -@@@@;@-@@@@;@;@@@@- at -@@@@- at -@@@@-@@-@@ @-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@ @;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@ @;!@!@;@",
-"@-@@@@-@;@@@@-@;@@@@-@;@@@@- at -@@@@- at -@@@@;@-@@@@;@;@@@@- at -@@@@- at -@@@@-@@@@@ @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ @;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@ @;@!@!;@",
-"@-@@@@-@;@@@@-@;@@@@-@;@@@@- at -@@@@- at -@@@@;@-@@@@;@;@@@@- at -@@@@- at -@@@@-@@@@@ @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ @;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@ @;!@!@!@",
-"@];;;;]@@;;;;]@]----]@]----]@]----]@]----]@]----]@@;;;;]@]----]@]----]@@@@@ @];;;;]@];;;;]@@@@@];;;;]@];;;;]@ @@;;;;@@@;;;;@@@@@@@;;;;@@@;;;;@@ @!;;;!@@",
-"@-@@@@-@;@@@@- at -@@@@;@;@@@@-@;@@@@-@;@@@@- at -@@@@-@;@@@@- at -@@@@-@;@@@@-@@@@@ @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ @;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@ @;@@@@;@",
-"@-@@@@-@;@@@@- at -@@@@;@;@@@@-@;@@@@-@;@@@@- at -@@@@-@;@@@@- at -@@@@-@;@@@@-@@@@@ @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ @;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@ @!!!!!;@",
-"@-@@@@-@;@@@@- at -@@@@;@;@@@@-@;@@@@-@;@@@@- at -@@@@-@;@@@@- at -@@@@-@;@@@@-@@-@@ @-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@ @;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@ @!@@@!!@",
-"@-@@@@-@;@@@@- at -@@@@;@;@@@@-@;@@@@-@;@@@@- at -@@@@-@;@@@@- at -@@@@-@;@@@@-@@-@@ @-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@ @;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@ @!@@@!!@",
-"@@----@@@;;;;]@]----]@]----]@@;;;;]@]----]@]----]@@;;;;]@]----]@]----]@@@@@ @@----@@@----@@@@@@@----@@@----@@ @@;;;;@@@;;;;@@@@@@@;;;;@@@;;;;@@ @!!!!!@@",
+"@@;;;;@@@----~@~;;;;,@~;;;;~@~----~@~;;;;~@~;;;;,@~;;;;~@~;;;;,@~;;;;,@@@@@ @@;;;;@@@;;;;@@@@@@@;;;;@@@;;;;@@ @@----@@@----@@@@@@@----@@@----@@ @@'---'@",
+"@;@@@@;@-@@@@;@-@@@@;@-@@@@;@;@@@@;@;@@@@-@;@@@@- at -@@@@;@;@@@@;@;@@@@;@@;@@ @;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@ @-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@ @'@'@'-@",
+"@;@@@@;@-@@@@;@-@@@@;@-@@@@;@;@@@@;@;@@@@-@;@@@@- at -@@@@;@;@@@@;@;@@@@;@@;@@ @;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@ @-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@ @-'@'@-@",
+"@;@@@@;@-@@@@;@-@@@@;@-@@@@;@;@@@@;@;@@@@-@;@@@@- at -@@@@;@;@@@@;@;@@@@;@@@@@ @;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@ @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ @-@'@'-@",
+"@;@@@@;@-@@@@;@-@@@@;@-@@@@;@;@@@@;@;@@@@-@;@@@@- at -@@@@;@;@@@@;@;@@@@;@@@@@ @;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@ @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ @-'@'@'@",
+"@~----~@@----~@~;;;;~@~;;;;~@~;;;;~@~;;;;~@~;;;;~@@----~@~;;;;~@~;;;;~@@@@@ @~----~@~----~@@@@@~----~@~----~@ @@----@@@----@@@@@@@----@@@----@@ @'---'@@",
+"@;@@@@;@-@@@@;@;@@@@- at -@@@@;@-@@@@;@-@@@@;@;@@@@;@-@@@@;@;@@@@;@-@@@@;@@@@@ @;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@ @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ @-@@@@-@",
+"@;@@@@;@-@@@@;@;@@@@- at -@@@@;@-@@@@;@-@@@@;@;@@@@;@-@@@@;@;@@@@;@-@@@@;@@@@@ @;@@@@;@;@@@@;@@@@@;@@@@;@;@@@@;@ @-@@@@- at -@@@@-@@@@@-@@@@- at -@@@@-@ @'''''-@",
+"@;@@@@;@-@@@@;@;@@@@- at -@@@@;@-@@@@;@-@@@@;@;@@@@;@-@@@@;@;@@@@;@-@@@@;@@;@@ @;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@ @-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@ @'@@@''@",
+"@;@@@@;@-@@@@;@;@@@@- at -@@@@;@-@@@@;@-@@@@;@;@@@@;@-@@@@;@;@@@@;@-@@@@;@@;@@ @;@@@@;@;@@@@;@@;@@;@@@@;@;@@@@;@ @-@@@@- at -@@@@-@@-@@-@@@@- at -@@@@-@ @'@@@''@",
+"@@;;;;@@@----~@~;;;;~@~;;;;~@@----~@~;;;;~@~;;;;~@@----~@~;;;;~@~;;;;~@@@@@ @@;;;;@@@;;;;@@@@@@@;;;;@@@;;;;@@ @@----@@@----@@@@@@@----@@@----@@ @'''''@@",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@"};
diff --git a/wmacpi.1 b/wmacpi.1
new file mode 100644
index 0000000..47c02c5
--- /dev/null
+++ b/wmacpi.1
@@ -0,0 +1,165 @@
+.TH WMACPI 1 "August 15 2004"
+.SH NAME
+wmacpi \- Battery status monitor for systems supporting ACPI
+.SH NAME
+acpi \- Query battery status for systems supporting ACPI
+.SH SYNOPSIS
+.B wmacpi
+[
+.RI -c
+value ]
+[
+.RI -d
+display ]
+[
+.RI -m
+battery no ]
+[
+.RI -s
+sample rate ]
+[
+.RI -f
+]
+[
+.RI -v
+]
+[
+.RI -n
+]
+[
+.RI -w
+]
+[
+.RI -a
+samples ]
+[
+.RI -V
+]
+[
+.RI -h
+]
+.PP
+.B acpi
+[
+.RI -a
+samples ]
+[
+.RI -v
+]
+[
+.RI -V
+]
+]
+.RI -b
+]
+[
+.RI -r
+]
+[
+.RI -h
+]
+.SH DESCRIPTION
+This manual page documents briefly the
+.B wmacpi
+command.
+.PP
+.B wmacpi
+is a program that displays the current battery status in a WindowMaker
+dock app, on systems that support Intel's Advanced Configuration and
+Power Interface specification (ACPI).
+.PP
+The program monitors a battery, displaying its current percentage
+charge via a bar and a numeric value. It also displays the current
+power status for the system, the time remaining (calculated based on
+the remaining battery capacity and the current rate of power usage),
+and a scrolling message with some hopefully useful information.
+.PP
+Clicking on the window cycles through the batteries that the ACPI
+system knows about.
+.PP
+.B acpi
+queries the battery status from the command line. It prints the power
+status, the percentage remaining for each battery found, and the time
+remaining if the system is on battery, or the time remaining for each
+battery to reach full charge if the batteries are charging.
+.SH OPTIONS
+.B wmacpi
+.TP
+.B \-c percentage
+Set critical low alarm at <value>% (default: 10%).
+.TP
+.B \-d display
+Set the X display to open the window on.
+.TP
+.B \-m battery number
+Set the battery to monitor initially.
+.TP
+.B \-s sample rate
+Set the rate at which to sample the ACPI data, in number of times per
+minute. Minimum is 1, ie once a minute, default is 20, maximum is 600.
+.TP
+.B \-n
+Disable blinking power glyph when charging. Note that it still blinks when
+the battery reports its capacity state as critical.
+.TP
+.B \-f
+Force the use of capacity mode for calculating time remaining. By defalt
+.B wmacpi
+will use the reported values of remaining capacity and present rate to
+calculate the time remaining on battery. This flag will force the use
+of the remaining capacity and time samples to calculate the present
+rate of drain, and from there the time remaining. Note that this mode
+of calculation generally underreports the time remaining. This mode
+works around certain buggy ACPI BIOSes that fail to report the current
+rate.
+.TP
+.B \-w
+Run wmacpi in command line mode - this operates identically to
+.B acpi
+..
+.TP
+.B \-a num
+Average the time remaining over num samples. This greatly improves the
+accuracy of the reported time remaining.
+.TP
+.B \-v
+Increase the verbosity of the program. Can be used more than once -
+each successive use increases the verbosity.
+.TP
+.B \-V
+Print the version information.
+.TP
+.B \-b
+Enable blinking of the power glyph when charging the batteries.
+.TP
+.B \-r
+Disable scrolling message.
+.TP
+.B \-h
+Display help.
+.TP
+.B acpi
+.TP
+.B \-a num
+Average the time remaining over num samples. This greatly improves the
+accuracy of the reported time remaining.
+.TP
+.B \-v
+Increase the verbosity of the program, as for
+.B wmacpi
+.TP
+.B \-V
+Print the version information.
+.TP
+.B \-h
+Display help.
+.SH AUTHOR
+.B wmacpi
+was originally written by Tim Copperfield <timecop at japan.co.jp>, then
+completely rewritten after 1.34 by Simon Fowler <simon at dreamcraft.com.au>.
+.PP
+This manual page was originally written by Simon Richter
+<sjr at debian.org> for the Debian GNU/Linux system, and then updated by
+Simon Fowler.
+.br
+Last modification by Simon Fowler <simon at dreamcraft.com.au>, 2004-08-15.
diff --git a/wmacpi.c b/wmacpi.c
index c5c48e5..5d44550 100644
--- a/wmacpi.c
+++ b/wmacpi.c
@@ -1,5 +1,5 @@
-/* apm/acpi dockapp - phear it 1.3
- * Copyright (C) 2000, 2001 timecop at japan.co.jp
+/* apm/acpi dockapp - phear it 1.34
+ * Copyright (C) 2000, 2001, 2002 timecop at japan.co.jp
*
* 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
@@ -16,13 +16,10 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/* #define RETARDED_APM */
-/* #define STUPID_APM */
-/* see README if you need to #define these or not. No user serviceable
- * parts below */
-
#define _GNU_SOURCE
+#include <dockapp.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -37,178 +34,230 @@
#include <X11/extensions/shape.h>
#include <X11/xpm.h>
+#include "libacpi.h"
#include "wmacpi.h"
-#if defined(ACPI) && defined(APM)
-# error Cannot compile with ACPI and APM compiled in. Please select only one.
-#endif
+#define WMACPI_VER "2.1"
/* main pixmap */
#ifdef LOW_COLOR
#include "master_low.xpm"
+static char **master_xpm = master_low_xpm;
#else
#include "master.xpm"
#endif
-typedef struct {
- Display *display; /* X11 display struct */
- int screen; /* current screen */
- Window root; /* root window */
- Window win; /* one window */
- Window iconwin; /* another one */
- Pixmap pixmap; /* UI pixmap, window pixmap */
- Pixmap mask; /* mask pixmap for shape */
- GC gc; /* main drawing GC */
+struct dockapp {
+ Display *display; /* display */
+ Window win; /* main window */
+ Pixmap pixmap; /* main pixmap */
+ Pixmap mask; /* mask pixmap */
Pixmap text; /* pixmap for text scroller */
+ unsigned short width; /* width of pixmap */
+ unsigned short height; /* height of pixmap */
+ int screen; /* current screen */
int tw; /* text width inside text pixmap */
int update; /* need to redraw? */
- int pressed; /* is the button pressed? */
- DspMode dspmode; /* time remaining or battery timer */
- Mode blink; /* should we blink the LED? (critical battery) */
-} Dockapp;
-
-/* for debug printing */
-#ifdef PRO
-char *state[] = { "AC", "Charging", "High", "Low", "Crit" };
-#endif
+ int blink; /* should we blink the LED? (critical battery) */
+ int bell; /* bell on critical low, or not? */
+ int scroll; /* scroll message text? */
+ int scroll_reset; /* reset the scrolling text */
+};
/* globals */
-Dockapp *dockapp;
-APMInfo *apminfo;
-int count = 0; /* global timer variable */
-int noisy_critical = 0; /* ring xbell annoyingly if critical? */
-
-/* proto for local stuff */
-static void new_window(char *name);
-static int open_display(char *display);
-static void redraw_window(void);
-static void render_text(char *string);
-static void scroll_text(int x, int y, int width, int tw, int reset);
-static void display_percentage(int percent);
-static void display_state(void);
-static void display_time(int minutes);
-static void blink_button(Mode mode);
-
-#define copy_xpm_area(x, y, w, h, dx, dy) \
-{ \
- XCopyArea(dockapp->display, dockapp->pixmap, dockapp->pixmap, \
- dockapp->gc, x, y, w, h, dx, dy); \
- dockapp->update = 1; \
+struct dockapp *dockapp;
+/* global_t *globals; */
+
+/* this gives us a variable scroll rate, depending on the importance of the
+ * message . . . */
+#define DEFAULT_SCROLL_RESET 150;
+int scroll_reset = DEFAULT_SCROLL_RESET;
+
+/* copy a chunk of pixmap around the app */
+static void copy_xpm_area(int x, int y, int w, int h, int dx, int dy)
+{
+ XCopyArea(DADisplay, dockapp->pixmap, dockapp->pixmap,
+ DAGC, x, y, w, h, dx, dy);
+ dockapp->update = 1;
+}
+
+/* display AC power symbol */
+static void display_power_glyph(void)
+{
+ copy_xpm_area(67, 38, 12, 7, 6, 17);
+}
+
+/* get rid of AC power symbol */
+static void kill_power_glyph(void)
+{
+ copy_xpm_area(67, 48, 12, 7, 6, 17);
+}
+
+/* display battery symbol */
+static void display_battery_glyph(void)
+{
+ copy_xpm_area(82, 38, 12, 7, 20, 17);
+}
+
+/* get rid of battery symbol */
+static void kill_battery_glyph(void)
+{
+ copy_xpm_area(82, 48, 12, 7, 20, 17);
+}
+
+/* clear the time display */
+static void clear_time_display(void)
+{
+ copy_xpm_area(114, 76, 31, 11, 7, 32);
+}
+
+/* set time display to -- -- */
+static void invalid_time_display(void)
+{
+ copy_xpm_area(122, 13, 31, 11, 7, 32);
+}
+
+static void reset_scroll(void) {
+ dockapp->scroll_reset = 1;
+}
+
+static void clear_text_area(void) {
+ copy_xpm_area(66, 9, 52, 7, 6, 50);
}
static void redraw_window(void)
{
if (dockapp->update) {
- eprint(1, "redrawing window");
- XCopyArea(dockapp->display, dockapp->pixmap, dockapp->iconwin,
- dockapp->gc, 0, 0, 64, 64, 0, 0);
XCopyArea(dockapp->display, dockapp->pixmap, dockapp->win,
- dockapp->gc, 0, 0, 64, 64, 0, 0);
+ DAGC, 0, 0, 64, 64, 0, 0);
dockapp->update = 0;
}
}
-static void new_window(char *name)
+static void new_window(char *display, char *name, int argc, char **argv)
{
- XpmAttributes attr;
- Pixel fg, bg;
- XGCValues gcval;
- XSizeHints sizehints;
- XClassHint classhint;
- XWMHints wmhints;
-
- dockapp->screen = DefaultScreen(dockapp->display);
- dockapp->root = DefaultRootWindow(dockapp->display);
-
- sizehints.flags = USSize;
- sizehints.width = 64;
- sizehints.height = 64;
-
- fg = BlackPixel(dockapp->display, dockapp->screen);
- bg = WhitePixel(dockapp->display, dockapp->screen);
-
- dockapp->win = XCreateSimpleWindow(dockapp->display, dockapp->root,
- 0, 0, sizehints.width,
- sizehints.height, 1, fg, bg);
- dockapp->iconwin =
- XCreateSimpleWindow(dockapp->display, dockapp->win, 0, 0,
- sizehints.width, sizehints.height, 1, fg, bg);
-
- XSetWMNormalHints(dockapp->display, dockapp->win, &sizehints);
- classhint.res_name = name;
- classhint.res_class = name;
- XSetClassHint(dockapp->display, dockapp->win, &classhint);
+ /* Initialise the dockapp window and appicon */
+ DAInitialize(display, name, 64, 64, argc, argv);
+ dockapp->display = DADisplay;
+ dockapp->win = DAWindow;
XSelectInput(dockapp->display, dockapp->win,
- ExposureMask | ButtonPressMask | ButtonReleaseMask |
- StructureNotifyMask);
- XSelectInput(dockapp->display, dockapp->iconwin,
- ExposureMask | ButtonPressMask | ButtonReleaseMask |
- StructureNotifyMask);
-
- XStoreName(dockapp->display, dockapp->win, name);
- XSetIconName(dockapp->display, dockapp->win, name);
-
- gcval.foreground = fg;
- gcval.background = bg;
- gcval.graphics_exposures = False;
-
- dockapp->gc =
- XCreateGC(dockapp->display, dockapp->win,
- GCForeground | GCBackground | GCGraphicsExposures,
- &gcval);
-
- attr.exactColors = 0;
- attr.alloc_close_colors = 1;
- attr.closeness = 1L << 15;
- attr.valuemask = XpmExactColors | XpmAllocCloseColors | XpmCloseness;
- if (XpmCreatePixmapFromData(dockapp->display, dockapp->win,
- master_xpm, &dockapp->pixmap,
- &dockapp->mask, &attr) != XpmSuccess) {
- fprintf(stderr, "FATAL: Not enough colors for main pixmap!\n");
- exit(1);
- }
+ ExposureMask | ButtonPressMask | ButtonReleaseMask |
+ StructureNotifyMask);
+
+ /* create the main pixmap . . . */
+ DAMakePixmapFromData(master_xpm, &dockapp->pixmap, &dockapp->mask,
+ &dockapp->width, &dockapp->height);
+ DASetPixmap(dockapp->pixmap);
+ DASetShape(dockapp->mask);
/* text area is 318x7, or 53 characters long */
dockapp->text = XCreatePixmap(dockapp->display, dockapp->win, 318, 7,
DefaultDepth(dockapp->display,
dockapp->screen));
if (!dockapp->text) {
- fprintf(stderr, "FATAL: Cannot create text scroll pixmap!\n");
+ pfatal("FATAL: Cannot create text scroll pixmap!\n");
exit(1);
}
+ DAShow();
+}
- XShapeCombineMask(dockapp->display, dockapp->win, ShapeBounding, 0, 0,
- dockapp->mask, ShapeSet);
- XShapeCombineMask(dockapp->display, dockapp->iconwin, ShapeBounding, 0,
- 0, dockapp->mask, ShapeSet);
-
- wmhints.initial_state = WithdrawnState;
- wmhints.flags = StateHint;
- wmhints.icon_window = dockapp->iconwin;
- wmhints.icon_x = sizehints.x;
- wmhints.icon_y = sizehints.y;
- wmhints.window_group = dockapp->win;
- wmhints.flags =
- StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
- XSetWMHints(dockapp->display, dockapp->win, &wmhints);
-
- XMapWindow(dockapp->display, dockapp->win);
+static void copy_to_text_buffer(int sx, int sy, int w, int h, int dx, int dy)
+{
+ XCopyArea(dockapp->display, dockapp->pixmap, dockapp->text,
+ DAGC, sx, sy, w, h, dx, dy);
+}
+
+static void copy_to_text_area(int sx, int sy, int w, int h, int dx, int dy)
+{
+ XCopyArea(dockapp->display, dockapp->text, dockapp->pixmap,
+ DAGC, sx, sy, w, h, dx, dy);
+}
+
+static void scroll_text(void)
+{
+ static int start, end, stop;
+ int x = 6; /* x coord of the start of the text area */
+ int y = 50; /* y coord */
+ int width = 52; /* width of the text area */
+ int height = 7; /* height of the text area */
+ int tw = dockapp->tw; /* width of the rendered text */
+ int sx, dx, w;
+
+ if (!dockapp->scroll)
+ return;
+
+ /*
+ * Conceptually this is viewing the text through a scrolling
+ * window - the window starts out with the end immediately before
+ * the text, and stops when the start of the window is immediately
+ * after the end of the text.
+ *
+ * We begin with the start of the window at pixel (0 - width) and
+ * as we scroll we render only the portion of the window above
+ * pixel 0. The destination of the copy during this period starts
+ * out at the end of the text area and works left as more of the
+ * text is being copied, until a full window is being copied.
+ *
+ * As the end of the window moves out past the end of the text, we
+ * want to keep the destination at the beginning of the text area,
+ * but copy a smaller and smaller chunk of the text. Eventually the
+ * start of the window will scroll past the end of the text, at
+ * which point we stop doing any work and wait to be reset.
+ */
+
+ if (dockapp->scroll_reset) {
+ start = 0 - width;
+ end = 0;
+ stop = 0;
+ clear_text_area();
+ dockapp->scroll_reset = 0;
+ }
+
+ if (stop)
+ return;
+
+ w = 52;
+ if (end < 52)
+ w = end;
+ else if (end > tw)
+ w = 52 - (end - tw);
+
+ dx = x + 52 - w;
+ if (end > tw)
+ dx = x;
+
+ sx = start;
+ if (start < 0)
+ sx = 0;
+
+ if (start > tw)
+ stop = 1;
+
+ clear_text_area();
+ copy_to_text_area(sx, 0, w, height, dx, y);
+ start += 2;
+ end += 2;
+
+ dockapp->update = 1;
}
static void render_text(char *string)
{
int i, c, k;
- if (strlen(string) > 53)
+ /* drop out immediately if scrolling is disabled - we don't render
+ * any text at all, since there's not much else we could do
+ * sensibly without scrolling. */
+ if (!dockapp->scroll)
return;
- eprint(1, "rendering: %s", string);
+ if (strlen(string) > 53)
+ return;
/* prepare the text area by clearing it */
for (i = 0; i < 54; i++) {
- XCopyArea(dockapp->display, dockapp->pixmap, dockapp->text,
- dockapp->gc, 133, 57, 6, 8, i * 6, 0);
+ copy_to_text_buffer(133, 57, 6, 8, i * 6, 0);
}
k = 0;
@@ -216,86 +265,34 @@ static void render_text(char *string)
c = toupper(string[i]);
if (c >= 'A' && c <= 'Z') { /* letter */
c = c - 'A';
- XCopyArea(dockapp->display, dockapp->pixmap, dockapp->text,
- dockapp->gc, c * 6, 67, 6, 7, k, 0);
+ copy_to_text_buffer(c * 6, 67, 6, 7, k, 0);
} else if (c >= '0' && c <= '9') { /* number */
c = c - '0';
- XCopyArea(dockapp->display, dockapp->pixmap, dockapp->text,
- dockapp->gc, c * 6 + 66, 58, 6, 7, k, 0);
+ copy_to_text_buffer(c * 6 + 66, 58, 6, 7, k, 0);
} else if (c == '.') {
- XCopyArea(dockapp->display, dockapp->pixmap, dockapp->text,
- dockapp->gc, 140, 58, 6, 7, k, 0);
+ copy_to_text_buffer(140, 58, 6, 7, k, 0);
} else if (c == '-') {
- XCopyArea(dockapp->display, dockapp->pixmap, dockapp->text,
- dockapp->gc, 126, 58, 6, 7, k, 0);
+ copy_to_text_buffer(126, 58, 6, 7, k, 0);
}
k += 6;
}
dockapp->tw = k; /* length of text segment */
/* re-scroll the message */
- scroll_text(6, 50, 52, dockapp->tw, 1);
- /* reset the scroll repeat counter */
- count = 0;
-}
-
-static int open_display(char *display)
-{
- dockapp->display = XOpenDisplay(display);
- if (!dockapp->display) {
- fprintf(stderr, "Unable to open display '%s'\n", display);
- return 1;
- }
- return 0;
-}
-
-static void scroll_text(int x, int y, int width, int tw, int reset)
-{
- static int pos, first, stop;
-
- if (reset) {
- pos = 0;
- first = 0;
- stop = 0;
- XCopyArea(dockapp->display, dockapp->pixmap, dockapp->text,
- dockapp->gc, 0, 0, width, 7, x, y);
- }
-
- if (stop) {
- return;
- }
-
- if ((first == 0) && pos == 0) {
- pos = width;
- first = 1;
- }
-
- if (pos == (0 - tw - 2)) {
- first = 1;
- pos = width;
- stop = 1;
- return;
- }
- pos -= 2;
-
- eprint(0, "scrolling");
-
- if (pos > 0) {
- copy_xpm_area(66, 9, pos, 7, x, y); /* clear */
- XCopyArea(dockapp->display, dockapp->text, dockapp->pixmap,
- dockapp->gc, 0, 0, width - pos, 7, x + pos, y);
- } else { /* don't need to clear, already in text */
- XCopyArea(dockapp->display, dockapp->text, dockapp->pixmap,
- dockapp->gc, abs(pos), 0, width, 7, x, y);
- }
- dockapp->update = 1;
+ reset_scroll();
+ scroll_text();
}
static void display_percentage(int percent)
{
- static int op = -1, obar;
+ static int op = -1;
+ static unsigned int obar;
unsigned int bar;
+ int width = 54; /* width of the bar */
+ float ratio = 100.0/width; /* ratio between the current percentage
+ * and the number of pixels in the bar */
- eprint(1, "received: %d\n", percent);
+ if (percent == -1)
+ percent = 0;
if (op == percent)
return;
@@ -314,7 +311,7 @@ static void display_percentage(int percent)
copy_xpm_area(95, 37, 21, 9, 37, 16); /* 100% */
op = percent;
- bar = percent / 1.8518;
+ bar = (int)((float)percent / ratio);
if (bar == obar)
return;
@@ -328,30 +325,29 @@ static void display_percentage(int percent)
static void display_time(int minutes)
{
static int ohour = -1, omin = -1;
- static int counter;
int hour, min, tmp;
- if (minutes == -1) { /* error - blink 00:00 */
- counter++;
- if (counter == 5) {
- copy_xpm_area(80, 76, 31, 11, 7, 32);
- } else if (counter == 10) {
- copy_xpm_area(114, 76, 31, 11, 7, 32);
- }
- if (counter > 10)
- counter = 0;
+ if (minutes <= 0) { /* error - clear the display */
+ invalid_time_display();
ohour = omin = -1;
return;
}
/* render time on the display */
hour = minutes / 60;
- min = minutes % 60;
+ /* our display area only fits %2d:%2d, so we need to make sure
+ * what we're displaying will fit in those constraints. I don't
+ * think we're likely to see any batteries that do more than
+ * 100 hours any time soon, so it's fairly safe. */
+ if (hour >= 100) {
+ hour = 99;
+ min = 59;
+ } else
+ min = minutes % 60;
if (hour == ohour && min == omin)
return;
- eprint(0, "redrawing time");
tmp = hour / 10;
copy_xpm_area(tmp * 7 + 1, 76, 6, 11, 7, 32);
tmp = hour % 10;
@@ -365,139 +361,328 @@ static void display_time(int minutes)
omin = min;
}
-static void display_state(void)
+/*
+ * The reworked state handling stuff.
+ */
+
+/* set the current state of the power panel */
+enum panel_states {
+ PS_AC,
+ PS_BATT,
+ PS_NULL,
+};
+
+static void really_blink_power_glyph(void)
{
- static int dopower;
- static int docharging;
- static int dobattery;
- static int docritical;
- static int counter;
-
- switch (apminfo->power) {
- case POWER:
- eprint(0, "selected ac power case");
- if (!dopower) {
- dopower = 1;
- docharging = 0;
- dobattery = 0;
- dockapp->blink = OFF;
- copy_xpm_area(67, 38, 12, 7, 6, 17);
- copy_xpm_area(82, 48, 11, 7, 20, 17);
- render_text("On AC power");
+ static int counter = 0;
+
+ if (counter == 10)
+ display_power_glyph();
+ else if (counter == 20)
+ kill_power_glyph();
+ else if (counter > 30)
+ counter = 0;
+ counter++;
+}
+
+static void blink_power_glyph(void)
+{
+ if (dockapp->blink)
+ really_blink_power_glyph();
+}
+
+static void really_blink_battery_glyph(void)
+{
+ static int counter = 0;
+
+ if (counter == 10)
+ display_battery_glyph();
+ else if (counter == 20)
+ kill_battery_glyph();
+ else if (counter > 30)
+ counter = 0;
+ counter++;
+}
+
+static void blink_battery_glyph(void)
+{
+ if (dockapp->blink)
+ really_blink_battery_glyph();
+}
+
+static void set_power_panel(global_t *globals)
+{
+ enum panel_states power = PS_NULL;
+ battery_t *binfo = globals->binfo;
+ adapter_t *ap = &globals->adapter;
+
+ if (ap->power == AC) {
+ if (power != PS_AC) {
+ power = PS_AC;
+ kill_battery_glyph();
+ display_power_glyph();
}
- break;
- case CHARGING:
- eprint(0, "selected charging case");
- counter++;
- if (counter == 10) {
- copy_xpm_area(67, 38, 12, 7, 6, 17);
- } else if (counter == 20) {
- copy_xpm_area(67, 48, 12, 7, 6, 17);
+ } else if (ap->power == BATT) {
+ if (power != PS_BATT) {
+ power = PS_BATT;
+ kill_power_glyph();
+ display_battery_glyph();
}
- if (counter > 20)
- counter = 0;
- if (!docharging) {
- render_text("Battery is charging");
- /* get rid of battery symbol */
- copy_xpm_area(82, 48, 12, 7, 20, 17);
- /* housekeeping */
- dockapp->blink = OFF;
- docharging = 1;
- dopower = 0;
- dobattery = 0;
+ }
+
+ if (binfo->charge_state == CHARGE)
+ blink_power_glyph();
+
+ if ((binfo->state == CRIT) && (ap->power == BATT))
+ blink_battery_glyph();
+
+ if (binfo->state == HARD_CRIT) {
+ really_blink_battery_glyph();
+ /* we only do this here because it'd be obnoxious to
+ * do it anywhere else. */
+ if (dockapp->bell) {
+ XBell(dockapp->display, 100);
}
- break;
- case HIGH:
- case LOW:
- case CRIT:
- eprint(0, "selected battery case");
- if (!dobattery) {
- render_text("On Battery");
- /* display battery symbol */
- copy_xpm_area(82, 38, 12, 7, 20, 17);
- /* get rid of AC power symbol */
- copy_xpm_area(67, 48, 12, 7, 6, 17);
- dobattery = 1;
- dopower = 0;
- docharging = 0;
+ }
+}
+
+void scroll_faster(double factor) {
+ scroll_reset = scroll_reset * factor;
+}
+
+void scroll_slower(double factor) {
+ scroll_reset = scroll_reset * factor;
+}
+
+void reset_scroll_speed(void) {
+ scroll_reset = DEFAULT_SCROLL_RESET;
+}
+
+/*
+ * The message that needs to be displayed needs to be decided
+ * according to a heirarchy: a message like not present needs to take
+ * precedence over a global thing like the current power status, and
+ * something like a low battery warning should take precedence over
+ * the "on battery" message. Likewise, a battery charging message
+ * needs to take precedence over the on ac power message. The other
+ * question is how much of a precedence local messages should take
+ * over global ones . . .
+ *
+ * So, there are three possible sets of messages: not present, on-line
+ * and off-line messages. We need to decide which of those sets is
+ * appropriate right now, and then decide within them.
+ */
+enum messages {
+ M_NP, /* not present */
+ M_AC, /* on ac power */
+ M_CH, /* battery charging */
+ M_BATT, /* on battery */
+ M_LB, /* low battery */
+ M_CB, /* critical low battery */
+ M_HCB, /* battery reported critical capacity state */
+ M_NULL, /* empty starting state */
+};
+
+static void set_message(global_t *globals)
+{
+ static enum messages state = M_NULL;
+ battery_t *binfo = globals->binfo;
+ adapter_t *ap = &globals->adapter;
+
+ /* battery not present case */
+ if (!binfo->present) {
+ if (state != M_NP) {
+ state = M_NP;
+ reset_scroll_speed();
+ render_text("not present");
}
- if (apminfo->power == CRIT) {
- dockapp->blink = BLINK;
- if (!docritical) {
- render_text("Battery Critical Low");
- docritical = 1;
+ } else if (ap->power == AC) {
+ if (binfo->charge_state == CHARGE) {
+ if (state != M_CH) {
+ state = M_CH;
+ reset_scroll_speed();
+ render_text("battery charging");
}
} else {
- if (docritical) {
- render_text("On Battery");
- docritical = 0;
+ if (state != M_AC) {
+ state = M_AC;
+ reset_scroll_speed();
+ render_text("on ac power");
}
- dockapp->blink = OFF;
}
- break;
- }
+ } else {
+ if (binfo->state == CRIT) {
+ if (state != M_CB) {
+ state = M_CB;
+ scroll_faster(0.75);
+ render_text("critical low battery");
+ }
+ } else if (binfo->state == HARD_CRIT) {
+ if (state != M_HCB) {
+ state = M_HCB;
+ scroll_faster(0.5);
+ render_text("hard critical low battery");
+ }
+ } else if (binfo->state == LOW) {
+ if (state != M_LB) {
+ state = M_LB;
+ scroll_faster(0.85);
+ render_text("low battery");
+ }
+ } else {
+ if (state != M_BATT) {
+ state = M_BATT;
+ reset_scroll_speed();
+ render_text("on battery");
+ }
+ }
+ }
}
-static void blink_button(Mode mode)
+void set_time_display(global_t *globals)
{
- static int counter;
- static int clear;
+ if (globals->binfo->charge_state == CHARGE)
+ display_time(globals->binfo->charge_time);
+ else if (globals->binfo->charge_state == DISCHARGE)
+ display_time(globals->rtime);
+ else
+ invalid_time_display();
+}
- if ((mode == OFF) && !clear) {
- eprint(0, "we are off");
- copy_xpm_area(136, 38, 3, 3, 44, 30);
- clear = 1;
- return;
- }
- if (mode != BLINK)
- return;
+void set_batt_id_area(int bno)
+{
+ int w = 7; /* Width of the number */
+ int h = 11; /* Height of the number */
+ int dx = 50; /* x coord of the target area */
+ int dy = 31; /* y coord of the target area */
+ int sx = (bno + 1) * 7; /* source x coord */
+ int sy = 76; /* source y coord */
+
+ copy_xpm_area(sx, sy, w, h, dx, dy);
+}
- counter++;
+void usage(char *name)
+{
+ printf("%s - help\t\t[simon at dreamcraft.com.au]\n\n"
+ "-d display\t\tdisplay on remote display <display>\n"
+ "-b\t\t\tenable blinking of various UI elements\n"
+ "-r\t\t\tdisable scrolling message\n"
+ "-c value\t\tset critical low alarm at <value> percent\n"
+ "\t\t\t(default: 10 percent)\n"
+ "-m <battery number>\tbattery number to monitor\n"
+ "-s <sample rate>\tnumber of times per minute to sample battery information\n"
+ "\t\t\tdefault 20 (once every three seconds)\n"
+ "-f\t\t\tforce the use of capacity mode for calculating time remaining\n"
+ "-n\t\t\tdo not blink\n"
+ "-w\t\t\trun in command line mode\n"
+ "-a <samples>\t\tsamples to average over (cli mode only)\n"
+ "-v\t\t\tincrease verbosity\n"
+ "\t\t\tcan be used multiple times to increase verbosity further\n"
+ "-h\t\t\tdisplay this help\n",
+ name);
+}
- if (counter == 5) {
- copy_xpm_area(137, 33, 3, 3, 44, 30);
- clear = 0;
- } else if (counter == 10) {
- copy_xpm_area(136, 38, 3, 3, 44, 30);
- clear = 0;
- /* make some noise */
- if (noisy_critical)
- XBell(dockapp->display, 100);
+void print_version(void)
+{
+ printf("wmacpi version %s\n", WMACPI_VER);
+ printf(" Using libacpi version %s\n", LIBACPI_VER);
+}
+
+void cli_wmacpi(global_t *globals, int samples)
+{
+ int i, j, sleep_time = 0;
+ battery_t *binfo;
+ adapter_t *ap;
+
+ pdebug("samples: %d\n", samples);
+ if(samples > 1)
+ sleep_time = 1000000/samples;
+
+ /* we want to acquire samples over some period of time, so . . . */
+ for(i = 0; i < samples + 2; i++) {
+ for(j = 0; j < globals->battery_count; j++)
+ acquire_batt_info(globals, j);
+ acquire_global_info(globals);
+ usleep(sleep_time);
}
- if (counter > 10)
- counter = 0;
+
+ ap = &globals->adapter;
+ if(ap->power == AC) {
+ printf("On AC Power");
+ for(i = 0; i < globals->battery_count; i++) {
+ binfo = &batteries[i];
+ if(binfo->present && (binfo->charge_state == CHARGE)) {
+ printf("; Battery %s charging", binfo->name);
+ printf(", currently at %2d%%", binfo->percentage);
+ if(binfo->charge_time >= 0)
+ printf(", %2d:%02d remaining",
+ binfo->charge_time/60,
+ binfo->charge_time%60);
+ }
+ }
+ printf("\n");
+ } else if(ap->power == BATT) {
+ printf("On Battery");
+ for(i = 0; i < globals->battery_count; i++) {
+ binfo = &batteries[i];
+ if(binfo->present && (binfo->percentage >= 0))
+ printf(", Battery %s at %d%%", binfo->name,
+ binfo->percentage);
+ }
+ if(globals->rtime >= 0)
+ printf("; %d:%02d remaining", globals->rtime/60,
+ globals->rtime%60);
+ printf("\n");
+ }
+ return;
}
int main(int argc, char **argv)
{
char *display = NULL;
- char ch;
- int update = 0;
-
- dockapp = calloc(1, sizeof(Dockapp));
- apminfo = calloc(1, sizeof(APMInfo));
-
- dockapp->blink = OFF;
- apminfo->crit_level = 10;
-
- /* see if whatever we want to use is supported */
- if (power_init()) {
- /* power_init functions handle printing error messages */
- exit(1);
- }
-
+ int ch;
+ int sample_count = 0;
+ int batt_reinit, ac_reinit;
+ int batt_count = 0;
+ int ac_count = 0;
+ int cli = 0, samples = 1;
+ int samplerate = 20;
+ int sleep_rate = 10;
+ int sleep_time = 1000000/sleep_rate;
+ int scroll_count = 0;
+ enum rtime_mode rt_mode = RT_RATE;
+ int rt_forced = 0;
+ battery_t *binfo;
+ global_t *globals;
+
+ dockapp = calloc(1, sizeof(struct dockapp));
+ globals = calloc(1, sizeof(global_t));
+
+ dockapp->blink = 1;
+ dockapp->bell = 0;
+ dockapp->scroll = 1;
+ dockapp->scroll_reset = 0;
+ globals->crit_level = 10;
+ battery_no = 1;
+
+ /* after this many samples, we reinit the battery and AC adapter
+ * information.
+ * XXX: make these configurable . . . */
+ batt_reinit = 100;
+ ac_reinit = 1000;
+
+ /* this needs to be up here because we need to know what batteries
+ * are available /before/ we can decide if the battery we want to
+ * monitor is available. */
/* parse command-line options */
- while ((ch = getopt(argc, argv, "bd:c:h")) != EOF) {
+ while ((ch = getopt(argc, argv, "d:c:m:s:a:fhnwbrvV")) != EOF) {
switch (ch) {
- case 'b':
- noisy_critical = 1;
- break;
case 'c':
if (optarg) {
- apminfo->crit_level = atoi(optarg);
- if ((apminfo->crit_level < 0) || (apminfo->crit_level > 100)) {
+ globals->crit_level = atoi(optarg);
+ if ((globals->crit_level < 0) || (globals->crit_level > 100)) {
fprintf(stderr, "Please use values between 0 and 100%%\n");
- apminfo->crit_level = 10;
+ globals->crit_level = 10;
fprintf(stderr, "Using default value of 10%%\n");
}
}
@@ -506,36 +691,115 @@ int main(int argc, char **argv)
if (optarg)
display = strdup(optarg);
break;
+ case 'm':
+ if (optarg) {
+ battery_no = atoi(optarg);
+ if (battery_no >= MAXBATT) {
+ fprintf(stderr, "Please specify a battery number below %d\n",
+ MAXBATT);
+ return 1;
+ }
+ pinfo("Monitoring battery %d\n", battery_no);
+ }
+ break;
+ case 's':
+ if (optarg) {
+ samplerate = atoi(optarg);
+ if (samplerate == 0) samplerate = 1;
+ if (samplerate > 600) samplerate = 600;
+ } else {
+ usage(argv[0]);
+ exit(1);
+ }
+ break;
+ case 'f':
+ rt_mode = RT_CAP;
+ rt_forced = 1;
+ break;
case 'h':
- printf("wmacpi - help\t\t[timecop at japan.co.jp]\n\n"
- "-d display\t\tdisplay on remote display <display>\n"
- "-b\t\t\tmake noise when battery is critical low (beep)\n"
- "-c value\t\tset critical low alarm at <value> percent\n"
- "\t\t\t(default: 10 percent)\n"
- "-h\t\t\tdisplay this help\n");
+ usage(argv[0]);
+ return 0;
+ case 'v':
+ verbosity++;
+ break;
+ case 'V':
+ print_version();
return 0;
+ case 'n':
+ dockapp->blink = 0;
+ break;
+ case 'w':
+ cli = 1;
+ break;
+ case 'a':
+ if(optarg != NULL) {
+ samples = atoi(optarg);
+ if(samples > 1000 || samples <= 0) {
+ fprintf(stderr, "Please specify a reasonable number of samples\n");
+ exit(1);
+ }
+ }
+ break;
+ case 'b':
+ dockapp->blink = 1;
+ break;
+ case 'r':
+ dockapp->scroll = 0;
break;
+ default:
+ usage(argv[0]);
+ return 1;
}
}
+
+ if (power_init(globals))
+ /* power_init functions handle printing error messages */
+ exit(1);
- /* open local or command-line specified display */
- if (open_display(display))
+ globals->rt_mode = rt_mode;
+ globals->rt_forced = rt_forced;
+
+ if (battery_no > globals->battery_count) {
+ pfatal("Battery %d not available for monitoring.\n", battery_no);
exit(1);
+ }
+
+ /* check for cli mode */
+ if (cli) {
+ cli_wmacpi(globals, samples);
+ exit(0);
+ }
+ /* check to see if we've got a valid DISPLAY env variable, as a simple check to see if
+ * we're running under X */
+ if (!getenv("DISPLAY")) {
+ pdebug("Not running under X - using cli mode\n");
+ cli_wmacpi(globals, samples);
+ exit(0);
+ }
+
+ battery_no--;
/* make new dockapp window */
- new_window("apm");
+ /* Don't even /think/ of asking me why, but if I set the window name to
+ * "acpi", the app refuses to dock properly - it's just plain /weird/.
+ * So, wmacpi it is . . . */
+ new_window(display, "wmacpi", argc, argv);
/* get initial statistics */
- acquire_info();
-
- dockapp->dspmode = REMAIN;
+ acquire_all_info(globals);
+ binfo = &batteries[battery_no];
+ globals->binfo = binfo;
+ pinfo("monitoring battery %s\n", binfo->name);
+ clear_time_display();
+ set_power_panel(globals);
+ set_message(globals);
+ set_batt_id_area(battery_no);
/* main loop */
while (1) {
XEvent event;
while (XPending(dockapp->display)) {
- eprint(0, "X11 activity");
XNextEvent(dockapp->display, &event);
switch (event.type) {
case Expose:
@@ -549,86 +813,93 @@ int main(int argc, char **argv)
exit(0);
break;
case ButtonPress:
- /* press event */
- if (event.xbutton.x >= 44 && event.xbutton.x <= 57 &&
- event.xbutton.y >= 30 && event.xbutton.y <= 43) {
- eprint(0, "inside button!");
- dockapp->pressed = 1;
- copy_xpm_area(118, 38, 15, 15, 44, 30);
- }
break;
case ButtonRelease:
- /* release event */
- if (event.xbutton.x >= 44 && event.xbutton.x <= 57 &&
- event.xbutton.y >= 30 && event.xbutton.y <= 43 &&
- dockapp->pressed) {
- /* handle button press */
- eprint(0, "release still inside button!");
- dockapp->pressed = 0;
- copy_xpm_area(136, 38, 15, 15, 44, 30);
- if ((apminfo->power != POWER) && (apminfo->power != CHARGING)) {
- dockapp->dspmode = !dockapp->dspmode;
- eprint(1, "Mode: %d", dockapp->dspmode);
- }
- /* end button press handler */
- }
- if (dockapp->pressed) {
- copy_xpm_area(136, 38, 15, 15, 44, 30);
- dockapp->pressed = 0;
- }
+ /* cycle through the known batteries. */
+ battery_no++;
+ battery_no = battery_no % globals->battery_count;
+ globals->binfo = &batteries[battery_no];
+ binfo = globals->binfo;
+ pinfo("changing to monitor battery %s\n", binfo->name);
+ set_batt_id_area(battery_no);
+ dockapp->update = 1;
break;
}
}
- if (update++ == 30) {
- eprint(1, "polling apm");
- acquire_info();
- update = 0;
- }
+ /* XXX: some laptops have problems with sampling the battery
+ * regularly - apparently, the BIOS disables interrupts while
+ * reading from the battery, which is generally on a slow bus
+ * and is a slow device, so you get significant periods without
+ * interrupts. This causes interactivity to suffer . . .
+ *
+ * My proposed workaround is to allow the user to set the sample
+ * rate - it defaults to ten, but can be set lower (or higher).
+ *
+ * The only problem with this is that we need to sample less
+ * frequently, while still allowing the app to update normally.
+ * That means calling redraw_window() and all the set_*() functions
+ * normally, but only calling acquire_all_info() every so often.
+ * As it stands, we only call acquire_all_info() once every three
+ * seconds (once every thirty updates) . . . I'm not entirely sure
+ * /how/ this could cause interactivity problems, but hey . . .
+ *
+ * So, given the base rate of once every three seconds, we want to
+ * change this test to . . . */
+ /* Okay, this needs /fixing/ - it's ridiculous. We should be giving
+ * the user the option of saying how many times per minute the
+ * battery should be sampled, defaulting to 20 times.
+ *
+ * We sleep for one tenth of a second at a time, so 60 seconds
+ * translates to 600 sleeps. So, we change the default sample
+ * rate to 20, and the calculation below becomes . . .*/
+ if (sample_count++ == ((sleep_rate*60)/samplerate)) {
+ acquire_all_info(globals);
+
+ /* we need to be able to reinitialise batteries and adapters, because
+ * they change - you can hotplug batteries on most laptops these days
+ * and who knows what kind of shit will be happening soon . . . */
+ if (batt_count++ >= batt_reinit) {
+ if(reinit_batteries(globals))
+ pfatal("Oh my god, the batteries are gone!\n");
+ batt_count = 0;
+ }
- if (count++ == 256) {
- scroll_text(6, 50, 52, dockapp->tw, 1);
- count = 0;
+ if (ac_count++ >= ac_reinit) {
+ if(reinit_ac_adapters(globals))
+ pfatal("What happened to our AC adapters?!?\n");
+ ac_count = 0;
+ }
+ sample_count = 0;
}
- /* it's okay to test here because display_time will not draw anything
- * unless there is a change. Also if we switched power states from
- * battery to charging/etc, we need to exit from "timer" mode */
- if (dockapp->dspmode == REMAIN || apminfo->power == POWER || apminfo->power == CHARGING) {
- display_time(apminfo->rtime);
- } else {
- display_time((time(NULL) - apminfo->timer) / 60);
+ if (scroll_count++ >= scroll_reset) {
+ reset_scroll();
+ scroll_count = 0;
}
- display_state();
- blink_button(dockapp->blink);
- display_percentage(apminfo->percentage);
- scroll_text(6, 50, 52, dockapp->tw, 0);
+ /* The old code had some kind of weird crap with timers and the like.
+ * As far as I can tell, it's meaningless - the time we want to display
+ * is the time calculated from the remaining capacity, as per the
+ * ACPI spec. The only thing I'd change is the handling of a charging
+ * state: my best guess, based on the behaviour I'm seeing with my
+ * Lifebook, is that the present rate value when charging is the rate
+ * at which the batteries are being charged, which would mean I'd just
+ * need to reverse the rtime calculation to be able to work out how
+ * much time remained until the batteries were fully charged . . .
+ * That would be rather useful, though given it would vary rather a lot
+ * it seems likely that it'd be little more than a rough guesstimate. */
+ set_time_display(globals);
+ set_power_panel(globals);
+ set_message(globals);
+ display_percentage(binfo->percentage);
+ scroll_text();
/* redraw_window, if anything changed - determined inside
* redraw_window. */
redraw_window();
- usleep(100000);
- }
- return 0;
-}
-
-/* this handles enabling "on-battery" timer. It only needs to happen once
- * for each unplug event. Functions from libapm and libacpi call this to
- * start the timer */
-void process_plugin_timer(void)
-{
- static int timer;
- if ((apminfo->power != POWER) && (apminfo->power != CHARGING) && !timer) {
- eprint(1, "not AC and not charging, and timer is not started");
- eprint(1, "starting battery timer");
- apminfo->timer = time(NULL);
- timer = 1;
+ usleep(sleep_time);
}
- if (((apminfo->power == POWER) || (apminfo->power == CHARGING)) && timer) {
- eprint(1, "disabling battery timer");
- timer = 0;
- }
-
+ return 0;
}
diff --git a/wmacpi.h b/wmacpi.h
index e9c15a5..a49acdf 100644
--- a/wmacpi.h
+++ b/wmacpi.h
@@ -1,52 +1,9 @@
#ifndef _WMACPI_H_
#define _WMACPI_H_
-#ifdef PRO
-#define eprint(level, fmt, arg...) \
- switch (level) { \
- case 0: \
- break; \
- case 1: \
- fprintf(stderr, __FUNCTION__": " fmt, ##arg); \
- fprintf(stderr, "\n"); \
- break; \
- }
-#else
-#define eprint(level, fmt, arg...) \
- do { } while (0)
-#endif
+#include "libacpi.h"
-typedef enum {
- REMAIN,
- TIMER
-} DspMode;
-
-typedef enum {
- BLINK,
- OFF
-} Mode;
-
-typedef enum {
- POWER, /* on AC, Battery charged */
- CHARGING, /* on AC, Charging */
- HIGH, /* on Battery, HIGH */
- LOW, /* on Battery, LOW */
- CRIT /* on Battery, CRIT */
-} State;
-
-typedef struct {
- State power; /* power state: Battery levels or AC */
- int percentage; /* battery percentage (-1 if no battery) */
- int rtime; /* remaining time */
- int timer; /* how long been on battery? */
- int crit_level; /* anything below this is critical low */
-} APMInfo;
-
-/* detect plugin events */
-void process_plugin_timer(void);
-/* check if apm/acpi is enabled, etc */
-int power_init(void);
-/* fill APMInfo with data */
-void acquire_info(void);
+/* we need to make these available generally. */
+int battery_no;
#endif /* _WMACPI_H_ */
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-wmaker/wmacpi.git
More information about the Pkg-wmaker-commits
mailing list