summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-02-11 14:59:17 +0400
committerIgor Pashev <pashev.igor@gmail.com>2013-02-11 14:59:17 +0400
commita232a950cc15b2c6e3427b59d4f90006a70e04f6 (patch)
tree903fe3c3d4258b04bd61ba8bda78dba5ad727efe /tools
downloadlibcuba-a232a950cc15b2c6e3427b59d4f90006a70e04f6.tar.gz
Imported Upstream version 3.0+20111124upstream/3.0+20111124upstream
Diffstat (limited to 'tools')
-rwxr-xr-xtools/fcc53
-rwxr-xr-xtools/mcc115
-rwxr-xr-xtools/mkstatic30
-rw-r--r--tools/partview.cpp261
-rw-r--r--tools/partview.m40
-rw-r--r--tools/partview.pro6
-rw-r--r--tools/print.xpm258
-rw-r--r--tools/quit.xpm346
8 files changed, 1109 insertions, 0 deletions
diff --git a/tools/fcc b/tools/fcc
new file mode 100755
index 0000000..9dcefa1
--- /dev/null
+++ b/tools/fcc
@@ -0,0 +1,53 @@
+#! /bin/sh
+# script to compile C programs that are linked
+# against Fortran libraries
+# last modified 19 Jul 11 th
+
+args=
+objs=
+ldflags=
+fldflags=
+compileonly=
+
+cc="${REALCC:-cc}"
+cxx="${REALCXX:-c++}"
+test `basename $0` = f++ && cc="$cxx"
+
+while test $# -gt 0 ; do
+ case "$1" in
+ -arch)
+ shift
+ ;;
+ -st | -b32 | -b64)
+ ;; # ignore mcc-specific flags
+ -Wno-long-double)
+ ;; # mcc adds this on Macs & gcc 4 doesn't like it
+ -[Ll]* | -Wl*)
+ ldflags="$ldflags '$1'"
+ ;;
+ *.tm.o)
+ objs="'$1' $objs"
+ ;;
+ *.a | *.o | *.so)
+ objs="$objs '$1'"
+ ;;
+ *.cc)
+ args="$args '$1'"
+ cc="$cxx"
+ ;;
+ -c)
+ compileonly="-c"
+ ;;
+ -o)
+ args="$args -o '$2'"
+ shift
+ ;;
+ *)
+ args="$args '$1'"
+ ;;
+ esac
+ shift
+done
+
+eval "set -x ; exec $cc $args ${compileonly:-$objs $ldflags $fldflags}"
+
diff --git a/tools/mcc b/tools/mcc
new file mode 100755
index 0000000..e0296b6
--- /dev/null
+++ b/tools/mcc
@@ -0,0 +1,115 @@
+#! /bin/sh
+# this script jumps in if there is no working mcc on the path:
+# - on Mac OS it (hopefully) figures out the location of mcc,
+# - on Cygwin it substitutes mcc completely
+# last modified 19 Jul 11 th
+
+
+sdkpath()
+{
+ mathcmd="$1"
+ shift
+ mathcmd=`IFS=:
+ PATH="$PATH:$*" which $mathcmd`
+
+ eval `"$mathcmd" -run '
+ Print["sysid=\"", $SystemID, "\""];
+ Print["topdir=\"", $TopDirectory, "\""];
+ Exit[]' < /dev/null | tr '\r' ' ' | tail -2`
+
+ # check whether Cygwin's dlltool can handle 64-bit DLLs
+ test "$sysid" = Windows-x86-64 && {
+ ${DLLTOOL:-dlltool} --help | grep x86-64 > /dev/null || sysid=Windows
+ }
+
+ topdir=`cd "$topdir" ; echo $PWD`
+
+ for sdk in \
+ "$topdir/SystemFiles/Links/MathLink/DeveloperKit/$sysid/CompilerAdditions" \
+ "$topdir/SystemFiles/Links/MathLink/DeveloperKit/CompilerAdditions" \
+ "$topdir/AddOns/MathLink/DeveloperKit/$sysid/CompilerAdditions" ; do
+ test -d "$sdk" && return
+ done
+
+ echo "MathLink SDK not found" 1>&2
+ exit 1
+}
+
+
+cygmcc()
+{
+ sdkpath math \
+ "`cygpath '$ProgramW6432'`/Wolfram Research/Mathematica"/* \
+ "`cygpath '$PROGRAMFILES'`/Wolfram Research/Mathematica"/*
+
+ for sdk in "$sdk"/m* ; do
+ break
+ done
+
+ cache=MLcyg-cache
+ test -d $cache || mkdir $cache
+
+ MLversion=3
+ for OSbits in 32 64 ; do
+ dllname=ml${OSbits}i$MLversion
+ libname="$sdk/lib/${dllname}m.lib"
+ test -f "$libname" && break
+ done
+
+ lib="$cache/${dllname}m"
+ test -f "$lib.a" || {
+ ( echo "EXPORTS"
+ ${NM:-nm} -C --defined-only "$libname" | awk '/ T [^.]/ { print $3 }'
+ ) > "$lib.def"
+ ${DLLTOOL:-dlltool} -k --dllname "$dllname.dll" \
+ --def "$lib.def" --output-lib "$lib.a"
+ }
+
+ tmp=
+ args="-DWIN$OSbits -I'$sdk/include'"
+ for arg in "$@" ; do
+ case "$arg" in
+ *.tm)
+ cp "$arg" "$arg.tm"
+ "$sdk"/bin/mprep -lines -o "$arg.c" "$arg.tm"
+ tmp="$tmp '$arg.c' '$arg.tm'"
+ args="$args '$arg.c'" ;;
+ *)
+ args="$args '$arg'" ;;
+ esac
+ done
+
+ trap "rm -f $tmp" 0 1 2 3 15
+ eval "set -x ; ${CC:-gcc} $args $lib.a -mwindows"
+}
+
+
+macmcc()
+{
+ sdkpath MathKernel \
+ /Applications/Mathematica*/Contents/MacOS \
+ $HOME/Desktop/Mathematica*/Contents/MacOS
+ exec "$sdk/mcc" "$@"
+}
+
+
+defaultmcc()
+{
+ sdkpath math \
+ /usr/local/bin \
+ /usr/local/Wolfram/bin \
+ /usr/local/Wolfram/Mathematica/*/Executables \
+ /opt/Wolfram/bin \
+ /opt/Wolfram/Mathematica/*/Executables
+ exec "$sdk/mcc" "$@"
+}
+
+
+shopt -s nullglob 2> /dev/null
+
+case `uname -s` in
+Darwin) macmcc "$@" ;;
+CYG*) cygmcc "$@" ;;
+*) defaultmcc "$@" ;;
+esac
+
diff --git a/tools/mkstatic b/tools/mkstatic
new file mode 100755
index 0000000..d816fcd
--- /dev/null
+++ b/tools/mkstatic
@@ -0,0 +1,30 @@
+#! /bin/sh
+
+exe=
+mach=
+mlmach=
+case `uname -s` in
+Linux) tag=Linux
+ st=-static
+ mach=-m32
+ mlmach=-b32
+ ;;
+Darwin) tag=Mac
+ st=-static-libgcc
+ ;;
+CYG*) tag=Windows
+ export CC=i686-pc-mingw32-gcc
+ st="-static -static-libgcc"
+ exe=.exe
+ ;;
+esac
+
+./configure CFLAGS="-O3 -fomit-frame-pointer -ffast-math $st $mach" MCFLAGS="-st $mlmach"
+
+make math
+
+for file in Vegas Suave Divonne Cuhre ; do
+ gzip $file$exe
+ mv $file$exe.gz $file$exe-$tag.gz
+done
+
diff --git a/tools/partview.cpp b/tools/partview.cpp
new file mode 100644
index 0000000..490c280
--- /dev/null
+++ b/tools/partview.cpp
@@ -0,0 +1,261 @@
+/*
+ partview.cpp
+ Partition viewer for Cuba
+ last modified 15 Feb 11 th
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <QWidget>
+#include <QMainWindow>
+#include <QTabWidget>
+#include <QAction>
+#include <QToolBar>
+#include <QPainter>
+#include <QPrinter>
+#include <QPrintDialog>
+#include <QApplication>
+#include <QColorGroup>
+
+#include <list>
+
+#include "quit.xpm"
+#include "print.xpm"
+
+// --------------------------------------------------------------
+
+class PartitionPlane : public QWidget
+{
+public:
+ PartitionPlane( const int dimx, const int dimy, QWidget *parent = 0 )
+ : QWidget(parent), m_dimx(dimx), m_dimy(dimy), m_got(0) {
+ }
+
+ void addBound( const int dim, const double lower, const double upper );
+
+ void drawRegion( QPainter *p, const QRect &r );
+ void drawRegions( QPainter *p );
+
+ QSize sizeHint() const {
+ return QSize(InitialSize, InitialSize);
+ }
+
+ QString filename() const {
+ return QString("%1-%2.ps").arg(m_dimx).arg(m_dimy);
+ }
+
+protected:
+ void paintEvent( QPaintEvent * ) {
+ QPainter p(this);
+ drawRegions( &p );
+ }
+
+private:
+ int m_dimx, m_dimy, m_got;
+ int m_xlower, m_xupper, m_ylower, m_yupper;
+
+ typedef std::list<QRect> regionList;
+ typedef regionList::iterator regionIt;
+ regionList m_regions;
+
+ enum {
+ Hue = 0, // red
+ InitialSize = 400,
+ CoordScale = 4*InitialSize };
+};
+
+
+void PartitionPlane::addBound( const int dim,
+ const double lower, const double upper )
+{
+ if( dim == m_dimx ) {
+ m_xlower = int(CoordScale*lower);
+ m_xupper = int(CoordScale*upper);
+ m_got |= 1;
+ }
+ if( dim == m_dimy ) {
+ m_ylower = int(CoordScale*lower);
+ m_yupper = int(CoordScale*upper);
+ m_got |= 2;
+ }
+
+ if( m_got == 3 ) {
+ m_got = 0;
+
+ const QRect rect = QRect(m_xlower, CoordScale - m_yupper,
+ m_xupper - m_xlower + 1, m_yupper - m_ylower + 1);
+
+ const int area = rect.width()*rect.height();
+ regionIt r;
+
+ for( r = m_regions.begin(); r != m_regions.end(); ++r ) {
+ if( rect == *r ) return;
+ if( area > (*r).width()*(*r).height() ) break;
+ }
+ m_regions.insert(r, rect);
+
+ QPainter p(this);
+ drawRegion( &p, rect );
+ }
+}
+
+
+void PartitionPlane::drawRegion( QPainter *p, const QRect &r )
+{
+ p->setWindow(0, 0, CoordScale, CoordScale);
+
+ QColor c;
+ const double ratio = r.width()*r.height()/
+ double(CoordScale*CoordScale);
+ const int saturation = int(255/(M_PI/2)*asin(1 - ratio));
+ c.setHsv( Hue, saturation, 255 );
+ p->setBrush(c);
+
+ p->setPen(palette().foreground().color());
+
+ p->drawRect(r);
+}
+
+
+void PartitionPlane::drawRegions( QPainter *p )
+{
+ for( regionIt r = m_regions.begin(); r != m_regions.end(); ++r )
+ drawRegion( p, *r );
+}
+
+
+// --------------------------------------------------------------
+
+class PartitionViewer : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ PartitionViewer( QWidget *parent );
+ void addPlane( const int dimx, const int dimy );
+ void addBound( const int dim, const double lower, const double upper );
+ int count() const { return m_tabs->count(); }
+ void tabupdate() {
+ if( m_tabs->currentWidget() != 0 ) m_tabs->currentWidget()->update();
+ }
+
+public slots:
+ void print();
+
+private:
+ QTabWidget *m_tabs;
+ QPrinter *m_printer;
+};
+
+
+PartitionViewer::PartitionViewer( QWidget *parent = 0 )
+: QMainWindow(parent)
+{
+ setWindowTitle(tr("Cuba Partition Viewer"));
+
+ QToolBar *toolbar = new QToolBar(this);
+ addToolBar(Qt::LeftToolBarArea, toolbar);
+
+ QAction *quit = new QAction( QPixmap(quit_xpm), tr("&Quit"), this );
+ connect( quit, SIGNAL(activated()), qApp, SLOT(quit()) );
+ toolbar->addAction(quit);
+
+#ifndef QT_NO_PRINTER
+ QAction *print = new QAction( QPixmap(print_xpm), tr("&Print..."), this );
+ connect( print, SIGNAL(activated()), this, SLOT(print()) );
+ toolbar->addAction(print);
+
+ m_printer = new QPrinter;
+#endif
+
+ m_tabs = new QTabWidget(this);
+ setCentralWidget(m_tabs);
+}
+
+
+void PartitionViewer::addPlane( const int dimx, const int dimy )
+{
+ PartitionPlane *plane = new PartitionPlane(dimx, dimy, this);
+ m_tabs->addTab( plane, tr("%1-%2 plane").arg(dimx).arg(dimy) );
+}
+
+
+void PartitionViewer::addBound( const int dim,
+ const double lower, const double upper )
+{
+ for( int index = 0; index < m_tabs->count(); ++index ) {
+ PartitionPlane *plane = (PartitionPlane *)m_tabs->widget(index);
+ if( plane ) plane->addBound(dim, lower, upper);
+ }
+}
+
+
+void PartitionViewer::print()
+{
+#ifndef QT_NO_PRINTER
+ PartitionPlane *plane = (PartitionPlane *)m_tabs->currentWidget();
+ if( !plane ) return;
+
+ QPrintDialog printDialog(m_printer, this);
+ if( printDialog.exec() == QDialog::Accepted ) {
+ QPainter p;
+ if( p.begin(m_printer) ) {
+ p.setViewport( QRect(QPoint(0, 0), plane->sizeHint()) );
+ plane->drawRegions( &p );
+ }
+ }
+#endif
+}
+
+
+#include "partview.moc"
+
+// --------------------------------------------------------------
+
+int main( int argc, char **argv )
+{
+ QApplication app(argc, argv);
+ PartitionViewer partview;
+
+ argc = (argc - 1) & -2;
+
+ for( int arg = 0; arg < argc; ) {
+ const int dimx = atoi(argv[++arg]);
+ const int dimy = atoi(argv[++arg]);
+ if( dimx > 0 && dimy > 0 ) partview.addPlane(dimx, dimy);
+ }
+
+ if( partview.count() == 0 ) {
+ fprintf(stderr, "Usage: %s dimx dimy ...\n"
+ "reads Cuba's verbose = 3 output from stdin and displays\n"
+ "the dimx-dimy plane of the tessellation on screen.\n"
+ "Each pair of dimensions is shown in a separate window.\n\n",
+ argv[0]);
+ exit(1);
+ }
+
+ partview.show();
+
+ int dim = 0;
+ char line[128];
+
+ while( fgets(line, sizeof line, stdin) ) {
+ double lower, upper;
+
+ fputs(line, stdout);
+
+ if( sscanf(line, "%*[^(](%lf) - (%lf)", &lower, &upper) == 2 )
+ partview.addBound(++dim, lower, upper);
+ else dim = 0;
+
+ app.processEvents();
+ }
+
+ fflush(stdout);
+ partview.tabupdate();
+ return app.exec();
+}
+
diff --git a/tools/partview.m b/tools/partview.m
new file mode 100644
index 0000000..579f4f2
--- /dev/null
+++ b/tools/partview.m
@@ -0,0 +1,40 @@
+(*
+ partview.m
+ A partition viewer for Cuba results in Mathematica
+ last modified 4 Feb 05 th
+*)
+
+
+BeginPackage["Cuba`"]
+
+PartView::usage = "For a Cuba result obtained with Regions -> True,
+PartView[result, dimx, dimy] displays the dimx-dimy plane of the
+tessellation used in the integration."
+
+Rect::usage = "Rect[{x1, y1}, {x2, y2}] is the graphics primitive used
+by PartView to render a rectangle."
+
+Begin["`PartView`"]
+
+PartView[expr_, dimx_Integer, dimy_Integer] :=
+Block[ {r, g, maxarea},
+ r = Cases[expr,
+ Region[ll_, ur_, ___] :> {ll[[{dimx, dimy}]], ur[[{dimx, dimy}]]},
+ Infinity];
+ maxarea = Times@@ (Max/@ #2 - Min/@ #1 &)@@ Transpose[r, {3, 1, 2}];
+ (Show[#]; #)& @ Graphics[Apply[Rect, r, 1], AspectRatio -> 1]
+]
+
+maxarea = 1
+
+Rect[{l_, d_}, {r_, u_}] := {
+ { Hue[0, (ArcSin[1 - (r - l) (u - d)/maxarea]/(Pi/2))^2, 1],
+ Rectangle[{l, d}, {r, u}] },
+ { RGBColor[0, 0, 0],
+ Line[{{l, d}, {r, d}, {r, u}, {l, u}, {l, d}}] }
+}
+
+End[]
+
+EndPackage[]
+
diff --git a/tools/partview.pro b/tools/partview.pro
new file mode 100644
index 0000000..7084a85
--- /dev/null
+++ b/tools/partview.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+CONFIG += qt release
+SOURCES += partview.cpp
+HEADERS += quit.xpm print.xpm
+DESTDIR = .
+MOC_DIR = .
diff --git a/tools/print.xpm b/tools/print.xpm
new file mode 100644
index 0000000..7368f3c
--- /dev/null
+++ b/tools/print.xpm
@@ -0,0 +1,258 @@
+/* XPM */
+static const char * print_xpm[] = {
+"48 48 207 2",
+" c None",
+". c #929292",
+"+ c #A0A0A0",
+"@ c #9E9E9E",
+"# c #9D9D9D",
+"$ c #9C9C9C",
+"% c #9B9B9B",
+"& c #9A9A9A",
+"* c #999999",
+"= c #DADADA",
+"- c #FFFFFF",
+"; c #FCFCFC",
+"> c #F9F9F9",
+", c #F7F7F7",
+"' c #F4F4F4",
+") c #EBEBEB",
+"! c #323232",
+"~ c #D7D7D7",
+"{ c #F1F1F1",
+"] c #EFEFEF",
+"^ c #ECECEC",
+"/ c #E3E3E3",
+"( c #313131",
+"_ c #FEFEFE",
+": c #F6F6F6",
+"< c #EEEEEE",
+"[ c #E9E9E9",
+"} c #E1E1E1",
+"| c #333333",
+"1 c #D8D8D8",
+"2 c #F3F3F3",
+"3 c #E6E6E6",
+"4 c #DEDEDE",
+"5 c #E7E7E7",
+"6 c #E4E4E4",
+"7 c #DDDDDD",
+"8 c #343434",
+"9 c #DBDBDB",
+"0 c #363636",
+"a c #DCDCDC",
+"b c #373737",
+"c c #DFDFDF",
+"d c #393939",
+"e c #D9D9D9",
+"f c #D5D5D5",
+"g c #E0E0E0",
+"h c #D6D6D6",
+"i c #D3D3D3",
+"j c #3B3B3B",
+"k c #E2E2E2",
+"l c #D4D4D4",
+"m c #D1D1D1",
+"n c #3C3C3C",
+"o c #D0D0D0",
+"p c #CECECE",
+"q c #3E3E3E",
+"r c #CDCDCD",
+"s c #797979",
+"t c #F0F0F0",
+"u c #EDEDED",
+"v c #E8E8E8",
+"w c #E5E5E5",
+"x c #737373",
+"y c #6C6C6C",
+"z c #959595",
+"A c #C5C5C5",
+"B c #757575",
+"C c #8B8B8B",
+"D c #878787",
+"E c #858585",
+"F c #838383",
+"G c #828282",
+"H c #808080",
+"I c #7E7E7E",
+"J c #7D7D7D",
+"K c #7B7B7B",
+"L c #7A7A7A",
+"M c #777777",
+"N c #767676",
+"O c #747474",
+"P c #717171",
+"Q c #707070",
+"R c #6E6E6E",
+"S c #6D6D6D",
+"T c #6B6B6B",
+"U c #606060",
+"V c #D2D2D2",
+"W c #5E5E5E",
+"X c #5A5A5A",
+"Y c #5B5B5B",
+"Z c #595959",
+"` c #585858",
+" . c #565656",
+".. c #555555",
+"+. c #545454",
+"@. c #535353",
+"#. c #515151",
+"$. c #4F4F4F",
+"%. c #4E4E4E",
+"&. c #4D4D4D",
+"*. c #494949",
+"=. c #8F8F8F",
+"-. c #FBFBFB",
+";. c #EAEAEA",
+">. c #B3B3B3",
+",. c #FDFDFD",
+"'. c #FAFAFA",
+"). c #CCCCCC",
+"!. c #CACACA",
+"~. c #BDBDBD",
+"{. c #3A3A3A",
+"]. c #676767",
+"^. c #F8F8F8",
+"/. c #C4C4C4",
+"(. c #B0B0B0",
+"_. c #A1A1A1",
+":. c #B8B8B8",
+"<. c #F8F6F8",
+"[. c #B5B5B5",
+"}. c #E9F2E9",
+"|. c #ACCEAC",
+"1. c #B9D3B9",
+"2. c #F5F7F5",
+"3. c #7C7C7C",
+"4. c #FDFAFD",
+"5. c #7CC57C",
+"6. c #5BD55B",
+"7. c #39C339",
+"8. c #FFFBFF",
+"9. c #76C776",
+"0. c #05BF05",
+"a. c #07B507",
+"b. c #8CCB8C",
+"c. c #4B4B4B",
+"d. c #F5F6F5",
+"e. c #B2D1B2",
+"f. c #CADFCA",
+"g. c #FCFAFC",
+"h. c #2E2E2E",
+"i. c #F9F8F9",
+"j. c #FFFCFF",
+"k. c #C0C0C0",
+"l. c #A6A6A6",
+"m. c #C2C2C2",
+"n. c #AAAAAA",
+"o. c #C3C3C3",
+"p. c #ABABAB",
+"q. c #A3A3A3",
+"r. c #CFCFCF",
+"s. c #C8C8C8",
+"t. c #C7C7C7",
+"u. c #C9C9C9",
+"v. c #909090",
+"w. c #8D8D8D",
+"x. c #8E8E8E",
+"y. c #626262",
+"z. c #A2A2A2",
+"A. c #BFBFBF",
+"B. c #000000",
+"C. c #464646",
+"D. c #B1B1B1",
+"E. c #BBBBBB",
+"F. c #252525",
+"G. c #3D3D3D",
+"H. c #010101",
+"I. c #727272",
+"J. c #BEBEBE",
+"K. c #292929",
+"L. c #BABABA",
+"M. c #B6B6B6",
+"N. c #030303",
+"O. c #888888",
+"P. c #C1C1C1",
+"Q. c #9F9F9F",
+"R. c #131313",
+"S. c #B7B7B7",
+"T. c #B9B9B9",
+"U. c #8C8C8C",
+"V. c #B4B4B4",
+"W. c #BCBCBC",
+"X. c #111111",
+"Y. c #303030",
+"Z. c #474747",
+"`. c #101010",
+" + c #505050",
+".+ c #ACACAC",
+"++ c #AEAEAE",
+"@+ c #616161",
+"#+ c #8A8A8A",
+"$+ c #A5A5A5",
+"%+ c #F5F5F5",
+"&+ c #F2F2F2",
+"*+ c #272727",
+"=+ c #1B1B1B",
+"-+ c #454545",
+";+ c #949494",
+">+ c #121212",
+",+ c #AFAFAF",
+"'+ c #979797",
+")+ c #404040",
+"!+ c #787878",
+"~+ c #646464",
+"{+ c #5F5F5F",
+"]+ c #5D5D5D",
+"^+ c #5C5C5C",
+"/+ c #575757",
+"(+ c #434343",
+" . + @ @ @ @ @ @ @ @ @ @ @ # $ % & * * * * ",
+" = - - - - - - - - - - - - - - ; > , ' ' ) ! ",
+" ~ - - - - - - - - - - - ; > , ' { ] ^ ^ / ( ",
+" ~ - - - - - - - - - _ ; > : ' { < ^ [ [ } | ",
+" 1 - - - - - - - - _ ; > : 2 { < ) [ 3 3 4 | ",
+" = - - - - - - - - ; > , ' { ] ^ [ 5 6 6 7 8 ",
+" 9 - - - - - - _ ; > : ' { < ^ [ 3 6 } } 9 0 ",
+" a - - - - - _ ; > : 2 { < ) [ 3 / } 4 7 1 b ",
+" 4 - - - - - ; > , ' { ] ^ [ 5 6 } c a 9 ~ d ",
+" c - - - _ ; > : ' { < ^ [ 3 6 } 4 a e 1 f d ",
+" g - - _ ; > : 2 { < ) [ 3 / } 4 9 e h f i j ",
+" k - - ; > , ' { ] ^ [ 5 6 } c a e ~ l i m n ",
+" / - ; > : ' { < ^ [ 3 6 } 4 a e h l m o p q ",
+" / - > : 2 { < ) [ 3 / } 4 9 e h i m p r r b ",
+" s ) - - - _ ; > : ' t u ) v w / c a = ~ f m x y ",
+" z A d B C D E F G H I J K L s M N O x P Q R S T | F a U ",
+" V 6 W X X X X X X X Y Y Z ` ` ...+.@.#.#.$.%.&.*.=.c % ",
+" ) - - - - - - - - - - - - _ -., ' { < ;.5 6 g 7 9 i o >.( ",
+" #.2 - - - - - - - - - ,.'.: 2 t u [ 3 / g 7 = h i o ).!.~.{. ",
+" ].C ^.- - - - - - - - ; > : 2 t < ;.5 6 } 4 a 1 f V o ).!./.I .. ",
+" x (.i ] - - - - - - - - - - - _ _ _ _ _ ,.,.,.,.,.,.; ; ; ; -.-.; ,.] m _... ",
+" Q :.<.- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ' [.Z ",
+" 1 - }.|.1.2.- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A ",
+" 3.,.4.5.6.7.5.- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - u Y ",
+" (._ 8.9.0.a.b.- ,.; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ,._ @ ",
+" c.9 '.-.d.e.f.g.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.,.9 h. ",
+" K ] , , i.j.8.^., , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ^.] X ",
+" _.{ { ' ' ' 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 ' ' ' 2 u F ",
+" :.;./ 5 u ] t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t ] u v 6 5 % ",
+" k.6 4 7 4 g / w v ;.) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ;.[ 3 / } c 4 4 6 l. ",
+" m.4 = = = = e e = 9 c g k k / 6 w w w w w w w w w w w w w w 6 / k k } c a = e e e = = = g n. ",
+" o.e f f f f f f f f l l f f f f h h ~ ~ 1 1 1 1 1 1 1 ~ h h f f f f l l f f f f f f f f a p. ",
+" ~.f m m m m m m m m m m m m m m m m m o o o o o o o o m m m m m m m m m m m m m m m m m h l. ",
+" [.m r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r ).m + ",
+" q.r.s.s.s.t.o h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h r t.s.s.u.).v. ",
+" w.!./././.u.x.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.z.u././.A u.O ",
+" ].m.k.A.A.!.&.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.N !.A.A.k.A C. ",
+" c.D.~.E.E.A @.B.B.B.B.F.G.j j j j j j j j j j j j j j {.{.{.{.{.{.n ( H.B.B.B.I./.E.E.J.p.K. ",
+" & L.M.M.k.$.B.B.B.N.O.= f l l l l l l l l f l i o p ).!.s.A m.P./.Q.R.B.B.B.].~.S.S.T.U. ",
+" U ~.M.V.W.Z X.X.X.Y.V 3 k k k k k k k k k k g 7 = e h i m p ).!.s.k.Z.`.X.X.].>.[.S.S. + ",
+" L n.:.T.W.A.~.:.n.; _ _ _ _ _ _ _ _ _ _ -.> : 2 { < ;.v w k g 7 4 Q..+A.J.++V.:.l.y ",
+" ! @+#+$+[.E.# J.- - - - - - - - - - ,.'.^.%+&+t ^ [ 5 6 } c a a m.z.L.V.z.E W *+ ",
+" =+-+S U.&+- - - - - - - - - ,.'., %+&+] ^ [ 3 6 } 4 a 1 h m ;+].q >+ ",
+" ,+- - - - - - - - - ; '., ' &+] ^ [ 3 / } 4 9 1 f V f '+ ",
+" [ - - - - - - - - _ '.^.%+&+t u [ 5 6 } c a e h i o m J.)+ ",
+" z.- - - - - - - - - - - _ -.^.%+&+] u ;.5 w } 4 a = ~ f 1 !+ ",
+" @.~+y.y.y.y.y.y.y.@+{+{+{+{+W ]+^+^+X X X Z Z ` ` /+..../+(+ ",
+" "};
diff --git a/tools/quit.xpm b/tools/quit.xpm
new file mode 100644
index 0000000..57d45c7
--- /dev/null
+++ b/tools/quit.xpm
@@ -0,0 +1,346 @@
+/* XPM */
+static const char * quit_xpm[] = {
+"48 48 295 2",
+" c None",
+". c #A62212",
+"+ c #B03B2A",
+"@ c #B95440",
+"# c #BF644E",
+"$ c #BE634D",
+"% c #BE634C",
+"& c #BE624C",
+"* c #BE624B",
+"= c #BE614A",
+"- c #BD614A",
+"; c #BD6049",
+"> c #BD6048",
+", c #BD5F48",
+"' c #BD5F46",
+") c #BD5E46",
+"! c #BC5E45",
+"~ c #BC5D44",
+"{ c #BC5D43",
+"] c #BC5C43",
+"^ c #BB5C42",
+"/ c #BB5A42",
+"( c #BB5A41",
+"_ c #BB5A40",
+": c #BA5940",
+"< c #B54B34",
+"[ c #AE3623",
+"} c #B95541",
+"| c #D2997F",
+"1 c #D9A88D",
+"2 c #D8A78B",
+"3 c #D8A68A",
+"4 c #D8A689",
+"5 c #D7A487",
+"6 c #D7A286",
+"7 c #D7A285",
+"8 c #D5A082",
+"9 c #D5A081",
+"0 c #D49E7F",
+"a c #D49E7E",
+"b c #D49D7D",
+"c c #D39B7B",
+"d c #D39B79",
+"e c #D39A78",
+"f c #D29977",
+"g c #D29775",
+"h c #D19674",
+"i c #D19573",
+"j c #D09471",
+"k c #CF936F",
+"l c #CF926E",
+"m c #CE916D",
+"n c #CE906C",
+"o c #CE8F6A",
+"p c #CD8D69",
+"q c #C8805D",
+"r c #B44A31",
+"s c #A92B1A",
+"t c #CD8971",
+"u c #D9A98F",
+"v c #D09275",
+"w c #C87E5E",
+"x c #C97E5E",
+"y c #C87E5D",
+"z c #C87F5E",
+"A c #C97F5D",
+"B c #C87F5D",
+"C c #C87F5C",
+"D c #C9805D",
+"E c #C8805C",
+"F c #C9805C",
+"G c #C8815C",
+"H c #C9815C",
+"I c #CA8861",
+"J c #CC8B65",
+"K c #CC8A64",
+"L c #C26F4F",
+"M c #A82918",
+"N c #D2997C",
+"O c #BD5E3B",
+"P c #BA5531",
+"Q c #BA5631",
+"R c #BA5732",
+"S c #BB5935",
+"T c #BB5A36",
+"U c #BB5C37",
+"V c #BC5E38",
+"W c #BD5F39",
+"X c #BD603A",
+"Y c #BD613B",
+"Z c #BE633C",
+"` c #BE643E",
+" . c #BE653F",
+".. c #BE6740",
+"+. c #BF6841",
+"@. c #C06A43",
+"#. c #C06B44",
+"$. c #C26D45",
+"%. c #C26E46",
+"&. c #C26F48",
+"*. c #C27149",
+"=. c #C4724B",
+"-. c #C4744C",
+";. c #C4744D",
+">. c #C4754E",
+",. c #C57750",
+"'. c #C67B54",
+"). c #CA8760",
+"!. c #CA8962",
+"~. c #BF6849",
+"{. c #BB5836",
+"]. c #C57852",
+"^. c #C57953",
+"/. c #C67D55",
+"(. c #C9855F",
+"_. c #C9865F",
+":. c #B3462E",
+"<. c #C67C54",
+"[. c #C77D56",
+"}. c #C77F58",
+"|. c #C8835D",
+"1. c #C47652",
+"2. c #CF8667",
+"3. c #E5B39E",
+"4. c #FCE1D4",
+"5. c #FFECE2",
+"6. c #FFEDE3",
+"7. c #F8D9C9",
+"8. c #E2AF96",
+"9. c #C77B56",
+"0. c #C77E57",
+"a. c #C8815A",
+"b. c #C88059",
+"c. c #AC3420",
+"d. c #D49073",
+"e. c #FFEBE2",
+"f. c #FFFFFF",
+"g. c #F9DACC",
+"h. c #CF8967",
+"i. c #B2442C",
+"j. c #C36C49",
+"k. c #FBDFD3",
+"l. c #E4B39B",
+"m. c #C8825C",
+"n. c #C77C55",
+"o. c #B54E32",
+"p. c #FFF6EF",
+"q. c #FFEEE4",
+"r. c #FFF9F1",
+"s. c #F9DCCE",
+"t. c #C67B53",
+"u. c #B54D31",
+"v. c #DCA187",
+"w. c #C97E59",
+"x. c #E4B29A",
+"y. c #FADECF",
+"z. c #C9855E",
+"A. c #C57850",
+"B. c #B54C31",
+"C. c #FFEBE1",
+"D. c #DCA086",
+"E. c #CA815D",
+"F. c #E6B9A0",
+"G. c #C87F59",
+"H. c #C5764F",
+"I. c #B54B30",
+"J. c #DFA78F",
+"K. c #D18B6B",
+"L. c #D39374",
+"M. c #E9C0AA",
+"N. c #CE8B67",
+"O. c #B54B2F",
+"P. c #FFFFFC",
+"Q. c #D79678",
+"R. c #EEC7B3",
+"S. c #FADED0",
+"T. c #F0CEBA",
+"U. c #C4734C",
+"V. c #B44A2E",
+"W. c #DA9C82",
+"X. c #F7D7C8",
+"Y. c #EFC8B4",
+"Z. c #CD8964",
+"`. c #C87F58",
+" + c #C3714A",
+".+ c #B4492D",
+"++ c #F7D4C7",
+"@+ c #CC815F",
+"#+ c #EFC8B5",
+"$+ c #F0CDBA",
+"%+ c #E3B49B",
+"&+ c #CD8B67",
+"*+ c #C77F59",
+"=+ c #FFFFFD",
+"-+ c #FFF8F0",
+";+ c #EFC9B5",
+">+ c #D29574",
+",+ c #F1D1BD",
+"'+ c #B3482C",
+")+ c #EDC3AF",
+"!+ c #EFCAB6",
+"~+ c #FFECDF",
+"{+ c #CE906B",
+"]+ c #C06C44",
+"^+ c #B3462B",
+"/+ c #EDC4B0",
+"(+ c #F0CAB6",
+"_+ c #FFF3EB",
+":+ c #FFF6EC",
+"<+ c #CF916D",
+"[+ c #B3452A",
+"}+ c #F0CCB8",
+"|+ c #FFF5EB",
+"1+ c #FFF6ED",
+"2+ c #C87F5A",
+"3+ c #B24429",
+"4+ c #EDC5B1",
+"5+ c #F0CCB9",
+"6+ c #B24329",
+"7+ c #FFEFE5",
+"8+ c #D49C7B",
+"9+ c #F3D4C3",
+"0+ c #B24227",
+"a+ c #FDE3D7",
+"b+ c #EDC9B3",
+"c+ c #E6BDA5",
+"d+ c #BD623C",
+"e+ c #B24126",
+"f+ c #F3D1C0",
+"g+ c #F0CEBB",
+"h+ c #D19472",
+"i+ c #BD613A",
+"j+ c #B14126",
+"k+ c #D49676",
+"l+ c #F1CFBB",
+"m+ c #F7DBCA",
+"n+ c #FDE7DA",
+"o+ c #D39C7C",
+"p+ c #C97F5C",
+"q+ c #B14025",
+"r+ c #E8BCA6",
+"s+ c #D59979",
+"t+ c #D9A182",
+"u+ c #E9C2AA",
+"v+ c #DAA789",
+"w+ c #BB5D37",
+"x+ c #B13F24",
+"y+ c #FFFAF2",
+"z+ c #DBA587",
+"A+ c #F2D2C0",
+"B+ c #F0D0BC",
+"C+ c #B03E23",
+"D+ c #CA825E",
+"E+ c #FADFD1",
+"F+ c #D89E7F",
+"G+ c #E8C0A8",
+"H+ c #FFFDF7",
+"I+ c #FDE8DB",
+"J+ c #D7A185",
+"K+ c #C97F5E",
+"L+ c #BA5834",
+"M+ c #B03C23",
+"N+ c #FBE2D3",
+"O+ c #F1D0BD",
+"P+ c #D7A486",
+"Q+ c #B03B22",
+"R+ c #CD8863",
+"S+ c #FFF2E8",
+"T+ c #F5D8C7",
+"U+ c #C97F5F",
+"V+ c #B95530",
+"W+ c #AF3A21",
+"X+ c #E6BAA2",
+"Y+ c #DEAF93",
+"Z+ c #D9A88C",
+"`+ c #C97E5F",
+" @ c #B8532F",
+".@ c #AC341D",
+"+@ c #E3B49A",
+"@@ c #F6D9C8",
+"#@ c #FFF7EE",
+"$@ c #EFCEBA",
+"%@ c #DAA687",
+"&@ c #C06848",
+"*@ c #B8502E",
+"=@ c #A92B18",
+"-@ c #D5A085",
+";@ c #B54A2A",
+">@ c #BE6141",
+",@ c #B84F2D",
+"'@ c #AC321C",
+")@ c #BF694A",
+"!@ c #B14024",
+"~@ c #C26D4D",
+"{@ c #A72413",
+" ",
+" ",
+" ",
+" ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . + @ # # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ . . . ",
+" . . } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r . . ",
+" . s t u 1 v w x y y z y A A A B C D E E F F E G G G G G H G I J K L M . ",
+" . . t u N O P Q R S T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.. . ",
+" . } u N {.P Q R S T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.].^./.(._.:.. ",
+" . . | 1 O P Q R S T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.].^.<.[.}.|.1.. . ",
+" . + 1 v P Q R S T U V W X Y Z 2.3.4.5.6.6.6.7.8.9.=.-.;.>.,.].^.<.[.0.}.a.b.c.. ",
+" . @ 2 w Q R S T U V W X Y d.e.f.f.f.f.f.f.f.f.f.f.g.h.>.,.].^.<.[.0.}.a.b.0.i.. ",
+" . # 3 x R S T U V W X j.k.f.f.f.f.f.f.f.f.f.f.f.f.f.f.l.].^.<.[.0.}.a.m.b.n.o.. ",
+" . # 4 y S T U V W X j.p.f.f.f.f.f.f.q.q.q.r.f.f.f.f.f.f.s.<.[.0.}.a.m.|.b.t.u.. ",
+" . $ 5 y T U V W X j.p.f.f.f.f.6.v.$.%.&.*.=.w.x.f.f.f.f.f.y.0.}.a.m.|.z.b.A.B.. ",
+" . % 6 z U V W X Y C.f.f.f.f.D.#.$.%.&.*.=.-.;.>.E.s.f.f.f.f.F.a.m.|.z.).G.H.I.. ",
+" . & 7 y V W X Y J.f.f.f.f.K.#.$.%.&.8.f.f.L.>.,.].^.M.f.f.f.f.N.|.z.).I }.;.O.. ",
+" . * 8 A W X Y Z P.f.f.f.Q.#.$.%.&.*.f.f.f.R.,.].^.<.[.S.f.f.f.T.z.).I !.}.U.V.. ",
+" . = 9 A X Y Z W.f.f.f.X.#.$.%.&.*.=.f.f.f.Y.].^.<.[.0.Z.f.f.f.f.).I !.K `. +.+. ",
+" . - 0 A Y Z ` ++f.f.f.@+$.%.&.*.=.-.f.f.f.#+^.<.[.0.}.a.$+f.f.f.%+!.K &+*+&..+. ",
+" . ; a B Z ` .=+f.f.-+$.%.&.*.=.-.;.f.f.f.;+<.[.0.}.a.m.>+f.f.f.,+K &+p *+%.'+. ",
+" . > b C ` ...f.f.f.)+%.&.*.=.-.;.>.f.f.f.!+[.0.}.a.m.|.z.f.f.f.~+&+p {+G.]+^+. ",
+" . , c D ...+.f.f.f./+&.*.=.-.;.>.,.f.f.f.(+0.}.a.m.|.z.)._+f.f.:+p {+<+G.@.[+. ",
+" . ' d E ..+.@.f.f.f./+*.=.-.;.>.,.].f.f.f.}+}.a.m.|.z.).I |+f.f.1+{+<+k 2++.3+. ",
+" . ) e E +.@.#.f.f.f.4+=.-.;.>.,.].^.f.f.f.5+a.m.|.z.).I !.f.f.f.1+<+k i 2+ .6+. ",
+" . ! f F @.#.$.=+f.f.7+-.;.>.,.].^.<.f.f.f.$+m.|.z.).I !.8+f.f.f.9+k i h 2+` 0+. ",
+" . ~ g F #.$.%.a+f.f.f.h.>.,.].^.<.[.f.f.f.$+|.z.).I !.K b+f.f.f.c+i h f C d+e+. ",
+" . { h E $.%.&.8.f.f.f.f+,.].^.<.[.0.f.f.f.g+z.).I !.K h+f.f.f.f.i h f d C i+j+. ",
+" . ] i G %.&.*.=.f.f.f.f.k+^.<.[.0.}.f.f.f.l+).I !.K &+m+f.f.f.n+h f d o+p+W q+. ",
+" . ^ j G &.*.=.-.r+f.f.f.f.s+[.0.}.a.$+f.f.t+I !.K &+u+f.f.f.f.v+f d o+a A w+x+. ",
+" . / k G *.=.-.;.>.y+f.f.f.f.z+}.a.m.|.z.).I !.K &+A+f.f.f.f.B+f d o+a 9 z T C+. ",
+" . ( l G =.-.;.>.,.D+f.f.f.f.f.E+F+|.z.).I !.K G+H+f.f.f.f.I+f d o+a 9 J+K+L+M+. ",
+" . _ m G -.;.>.,.].^.s+f.f.f.f.f.f.f.N+O+O+|+f.f.f.f.f.f.I+f d o+a 9 J+P+z R Q+. ",
+" . : n H ;.>.,.].^.<.[.R+S+f.f.f.f.f.f.f.f.f.f.f.f.f.f.T+f d o+a 9 J+P+4 U+V+W+. ",
+" . < o G >.,.].^.<.[.0.}.a.X+f.f.f.f.f.f.f.f.f.f.f.7+Y+f d o+a 9 J+P+4 Z+`+ @.@. ",
+" . [ p I ,.].^.<.[.0.}.a.m.|.z.+@@@|+f.f.f.f.#@$@%@h f d o+a 9 J+P+4 Z+u &@*@=@. ",
+" . . q J '.^.<.[.0.}.a.m.|.z.).I !.K &+p {+<+k i h f d o+a 9 J+P+4 Z+u -@*@;@. . ",
+" . r K )./.[.0.}.a.m.|.z.).I !.K &+p {+<+k i h f d o+a 9 J+P+4 Z+u 3 >@,@'@. ",
+" . . )@!.(.}.}.a.m.|.z.).I !.K &+p {+<+k i h f d o+a 9 J+P+4 Z+u -@>@,@!@. . ",
+" . M ~@_.|.a.b.b.b.b.G.}.}.`.*+*+G.G.2+2+2+C C p+A z K+z U+`+&@*@,@!@{@. ",
+" . . :.1.b.0.n.t.A.H.;.U. +&.%.]+@.+. .` d+i+W w+T L+R V+ @*@;@'@. . ",
+" . . . c.i.o.u.B.I.O.V..+.+'+^+[+3+6+0+e+j+q+x+C+M+Q+W+.@=@. . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" ",
+" ",
+" ",
+" "};