changeset 105:82029e9d9dc2 draft

unix build merged in, bitmap resources from xpm instead of rc, better addr relay, better selection of addrs by time last seen for faster connect
author s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
date Thu, 05 Nov 2009 04:41:36 +0000
parents 5cda4bd17fd4
children 94f188e0e0f1
files build-unix.txt build.txt db.cpp headers.h irc.cpp irc.h main.cpp main.h makefile.unix net.cpp net.h ui.cpp uibase.cpp uiproject.fbp util.cpp util.h xpm/addressbook16.xpm xpm/addressbook20.xpm xpm/bitcoin.xpm xpm/check.xpm xpm/send16.xpm xpm/send16noshadow.xpm xpm/send20.xpm
diffstat 23 files changed, 2197 insertions(+), 314 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/build-unix.txt
@@ -0,0 +1,73 @@
+Bitcoin v0.2.0 BETA
+
+Copyright (c) 2009 Satoshi Nakamoto
+Distributed under the MIT/X11 software license, see the accompanying
+file license.txt or http://www.opensource.org/licenses/mit-license.php.
+This product includes software developed by the OpenSSL Project for use in
+the OpenSSL Toolkit (http://www.openssl.org/).  This product includes
+cryptographic software written by Eric Young (eay@cryptsoft.com).
+
+
+UNIX BUILD NOTES
+
+
+Dependencies
+------------
+apt-get install build-essential
+apt-get install libgtk2.0-dev
+apt-get install libssl-dev
+
+Libraries you need to obtain separately and build:
+              default path   download
+wxWidgets      \wxwidgets     http://www.wxwidgets.org/downloads/
+Berkeley DB    \db            http://www.oracle.com/technology/software/products/berkeley-db/index.html
+Boost          \boost         http://www.boost.org/users/download/
+
+Their licenses:
+wxWidgets      LGPL 2.1 with very liberal exceptions
+Berkeley DB    New BSD license with additional requirement that linked software must be free open source
+Boost          MIT-like license
+
+Versions used in this release:
+GCC          4.3.3
+OpenSSL      0.9.8k
+wxWidgets    2.8.9
+Berkeley DB  4.7.25.NC
+Boost        1.40.0
+
+
+Notes
+-----
+The UI layout is edited with wxFormBuilder.  Open the project file
+uiproject.fbp.  It generates uibase.cpp and uibase.h, which define base
+classes that do the rote work of constructing all the UI elements.
+
+The release is built with GCC and then "strip bitcoin" to strip the debug
+symbols, which reduces the executable size by about 90%.
+
+
+wxWidgets
+---------
+cd /usr/local/wxWidgets-2.8.9
+mkdir buildgtk
+cd buildgtk
+../configure --with-gtk --enable-debug --disable-shared --enable-monolithic
+make
+su
+make install
+ldconfig
+
+
+Berkeley DB
+-----------
+cd /usr/local/db-4.7.25.NC/build_unix
+../dist/configure --enable-cxx
+make
+
+
+Boost
+-----
+cd /usr/local/boost_1_40_0
+su
+./bootstrap.sh
+./bjam install
deleted file mode 100644
--- a/build.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-BitCoin v0.1.6 BETA
-
-Copyright (c) 2009 Satoshi Nakamoto
-Distributed under the MIT/X11 software license, see the accompanying
-file license.txt or http://www.opensource.org/licenses/mit-license.php.
-This product includes software developed by the OpenSSL Project for use in
-the OpenSSL Toolkit (http://www.openssl.org/).  This product includes
-cryptographic software written by Eric Young (eay@cryptsoft.com).
-
-
-Compilers Supported
--------------------
-MinGW GCC (v3.4.5)
-Microsoft Visual C++ 6.0 SP6
-
-
-Dependencies
-------------
-Libraries you need to obtain separately to build:
-
-              default path   download
-wxWidgets      \wxwidgets     http://www.wxwidgets.org/downloads/
-                                or prebuilt: http://wxpack.sourceforge.net
-OpenSSL        \openssl       http://www.openssl.org/source/
-Berkeley DB    \db            http://www.oracle.com/technology/software/products/berkeley-db/index.html
-Boost          \boost         http://www.boost.org/users/download/
-
-Their licenses:
-wxWidgets      LGPL 2.1 with very liberal exceptions
-OpenSSL        Old BSD license with the problematic advertising requirement
-Berkeley DB    New BSD license with additional requirement that linked software must be free open source
-Boost          MIT-like license
-
-
-Notes
------
-The UI layout is edited with wxFormBuilder.  Open the project file
-uiproject.fbp.  It generates uibase.cpp and uibase.h, which define base
-classes that do the rote work of constructing all the UI elements.
-
-The release is built with GCC and then "strip bitcoin.exe" to strip the debug
-symbols, which reduces the executable size by about 90%.
-
-
-OpenSSL
--------
-Bitcoin does not use any encryption.  If you want to do a no-everything
-build of OpenSSL to exclude encryption routines, a few patches are required.
-(OpenSSL v0.9.8h)
-
-Edit engines\e_gmp.c and put this #ifndef around #include <openssl/rsa.h>
-  #ifndef OPENSSL_NO_RSA
-  #include <openssl/rsa.h>
-  #endif
-
-Add this to crypto\err\err_all.c before the ERR_load_crypto_strings line:
-  void ERR_load_RSA_strings(void) { }
-
-Edit ms\mingw32.bat and replace the Configure line's parameters with this
-no-everything list.  You have to put this in the batch file because batch
-files can't take more than 9 command line parameters.
-  perl Configure mingw threads no-rc2 no-rc4 no-rc5 no-idea no-des no-bf no-cast no-aes no-camellia no-seed no-rsa no-dh
-
-Also REM out the following line in ms\mingw32.bat.  The build fails after it's
-already finished building libeay32, which is all we care about, but the
-failure aborts the script before it runs dllwrap to generate libeay32.dll.
-  REM  if errorlevel 1 goto end
-
-Build
-  ms\mingw32.bat
-
-If you want to use it with MSVC, generate the .lib file
-  lib /machine:i386 /def:ms\libeay32.def /out:out\libeay32.lib
-
-
-Berkeley DB
------------
-Using MinGW and MSYS:
-cd \db\build_unix
-sh ../dist/configure --enable-mingw --enable-cxx
-make
-
-
-Boost
------
-If you have trouble compiling Boost with Microsoft Visual C++ 6.0, try going
-back to Boost version 1.35.  It looks like they may be starting to reduce
-support for MSVC 6.0.
--- a/db.cpp
+++ b/db.cpp
@@ -62,9 +62,9 @@
             if (fShutdown)
                 return;
             string strDataDir = GetDataDir();
-            string strLogDir = strDataDir + "\\database";
+            string strLogDir = strDataDir + "/database";
             _mkdir(strLogDir.c_str());
-            string strErrorFile = strDataDir + "\\db.log";
+            string strErrorFile = strDataDir + "/db.log";
             printf("dbenv.open strLogDir=%s strErrorFile=%s\n", strLogDir.c_str(), strErrorFile.c_str());
 
             dbenv.set_lg_dir(strLogDir.c_str());
@@ -411,7 +411,6 @@
 
 bool CAddrDB::LoadAddresses()
 {
-    CRITICAL_BLOCK(cs_mapIRCAddresses)
     CRITICAL_BLOCK(cs_mapAddresses)
     {
         // Load user provided addresses
@@ -425,10 +424,7 @@
                 {
                     CAddress addr(psz, NODE_NETWORK);
                     if (addr.IsValid())
-                    {
                         AddAddress(*this, addr);
-                        mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
-                    }
                 }
             }
             catch (...) { }
@@ -678,7 +674,7 @@
                     if (nRefCount == 0 && !fShutdown)
                     {
                         // Flush wallet.dat so it's self contained
-                        nLastFlushed == nWalletDBUpdated;
+                        nLastFlushed = nWalletDBUpdated;
                         int64 nStart = GetTimeMillis();
                         dbenv.txn_checkpoint(0, 0, 0);
                         dbenv.lsn_reset(strFile.c_str(), 0);
--- a/headers.h
+++ b/headers.h
@@ -17,16 +17,18 @@
 #endif
 #define _WIN32_IE 0x0400
 #define WIN32_LEAN_AND_MEAN 1
+#define __STDC_LIMIT_MACROS // to enable UINT64_MAX from stdint.h
 #include <wx/wx.h>
 #include <wx/clipbrd.h>
 #include <wx/snglinst.h>
 #include <wx/taskbar.h>
 #include <wx/stdpaths.h>
+#include <wx/utils.h>
 #include <openssl/ecdsa.h>
 #include <openssl/evp.h>
 #include <openssl/rand.h>
 #include <openssl/sha.h>
-#include <openssl/ripemd.h>
+#include <openssl/ripemd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
@@ -50,22 +52,28 @@
 #include <boost/tuple/tuple.hpp>
 #include <boost/tuple/tuple_comparison.hpp>
 #include <boost/tuple/tuple_io.hpp>
-#include <boost/array.hpp>
-
+#include <boost/array.hpp>
+
 #ifdef __WXMSW__
 #include <windows.h>
 #include <winsock2.h>
-#include <mswsock.h>
+#include <mswsock.h>
 #include <shlobj.h>
-#include <shlwapi.h>
-#include <io.h>
-#include <process.h>
-#else
+#include <shlwapi.h>
+#include <io.h>
+#include <process.h>
+#else
 #include <sys/time.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <boost/filesystem.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/algorithm/string.hpp>
+#endif
 
 #pragma hdrstop
 using namespace std;
@@ -88,3 +96,11 @@
 #include "market.h"
 #include "uibase.h"
 #include "ui.h"
+
+#include "xpm/addressbook16.xpm"
+#include "xpm/addressbook20.xpm"
+#include "xpm/bitcoin.xpm"
+#include "xpm/check.xpm"
+#include "xpm/send16.xpm"
+#include "xpm/send16noshadow.xpm"
+#include "xpm/send20.xpm"
--- a/irc.cpp
+++ b/irc.cpp
@@ -4,10 +4,7 @@
 
 #include "headers.h"
 
-
-map<vector<unsigned char>, CAddress> mapIRCAddresses;
-CCriticalSection cs_mapIRCAddresses;
-
+int nGotIRCAddresses = 0;
 
 
 
@@ -259,16 +256,7 @@
                     CAddrDB addrdb;
                     if (AddAddress(addrdb, addr))
                         printf("IRC got new address\n");
-                    else
-                    {
-                        // make it try connecting again
-                        CRITICAL_BLOCK(cs_mapAddresses)
-                            if (mapAddresses.count(addr.GetKey()))
-                                mapAddresses[addr.GetKey()].nLastFailed = 0;
-                    }
-
-                    CRITICAL_BLOCK(cs_mapIRCAddresses)
-                        mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
+                    nGotIRCAddresses++;
                 }
                 else
                 {
--- a/irc.h
+++ b/irc.h
@@ -4,7 +4,5 @@
 
 extern bool RecvLine(SOCKET hSocket, string& strLine);
 extern void ThreadIRCSeed(void* parg);
-extern bool fRestartIRCSeed;
 
-extern map<vector<unsigned char>, CAddress> mapIRCAddresses;
-extern CCriticalSection cs_mapIRCAddresses;
+extern int nGotIRCAddresses;
--- a/main.cpp
+++ b/main.cpp
@@ -100,13 +100,10 @@
         if (fInsertedNew)
             wtx.nTimeReceived = GetAdjustedTime();
 
-        //// debug print
-        printf("AddToWallet %s  %s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), fInsertedNew ? "new" : "update");
-
+        bool fUpdated = false;
         if (!fInsertedNew)
         {
             // Merge
-            bool fUpdated = false;
             if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
             {
                 wtx.hashBlock = wtxIn.hashBlock;
@@ -128,13 +125,15 @@
                 wtx.fSpent = wtxIn.fSpent;
                 fUpdated = true;
             }
-            if (!fUpdated)
-                return true;
         }
 
+        //// debug print
+        printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+
         // Write to disk
-        if (!wtx.WriteToDisk())
-            return false;
+        if (fInsertedNew || fUpdated)
+            if (!wtx.WriteToDisk())
+                return false;
 
         // Notify UI
         vWalletUpdated.push_back(hash);
@@ -820,7 +819,7 @@
             }
 
             if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
-                return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size());
+                return error("ConnectInputs() : %s prevout.n out of range %d %d %d prev tx %s\n%s", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,6).c_str(), txPrev.ToString().c_str());
 
             // If prev is coinbase, check that it's matured
             if (txPrev.IsCoinBase())
@@ -1217,7 +1216,7 @@
     if (nTime <= pindexPrev->GetMedianTimePast())
         return error("AcceptBlock() : block's timestamp is too early");
 
-    // Check that all transactions are finalized (starting around 30 Nov 2009)
+    // Check that all transactions are finalized (starting around Dec 2009)
     if (nBestHeight > 31000) // 25620 + 5320
         foreach(const CTransaction& tx, vtx)
             if (!tx.IsFinal(nTime))
@@ -1384,7 +1383,7 @@
 {
     if (nFile == -1)
         return NULL;
-    FILE* file = fopen(strprintf("%s\\blk%04d.dat", GetDataDir().c_str(), nFile).c_str(), pszMode);
+    FILE* file = fopen(strprintf("%s/blk%04d.dat", GetDataDir().c_str(), nFile).c_str(), pszMode);
     if (!file)
         return NULL;
     if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
@@ -1718,6 +1717,7 @@
 
 
 
+
     if (strCommand == "version")
     {
         // Each connection can only send one version message
@@ -1765,6 +1765,10 @@
 
         pfrom->fSuccessfullyConnected = true;
 
+        // Update the last seen time
+        if (pfrom->fNetworkNode)
+            AddressCurrentlyConnected(pfrom->addr);
+
         printf("version message: version %d\n", pfrom->nVersion);
     }
 
@@ -1781,23 +1785,16 @@
         vector<CAddress> vAddr;
         vRecv >> vAddr;
 
-        // Clear addrknown lists periodically to allow refresh broadcasts
-        static int64 nLastClearedAddrKnown;
-        if (nLastClearedAddrKnown < GetAdjustedTime() - 24 * 60 * 60)
-        {
-            nLastClearedAddrKnown = GetAdjustedTime();
-            CRITICAL_BLOCK(cs_vNodes)
-                foreach(CNode* pnode, vNodes)
-                    pnode->setAddrKnown.clear();
-        }
-
         // Store the new addresses
         CAddrDB addrdb;
-        foreach(const CAddress& addr, vAddr)
+        foreach(CAddress& addr, vAddr)
         {
             if (fShutdown)
                 return true;
-            AddAddress(addrdb, addr);
+            addr.nTime = GetAdjustedTime();
+            if (pfrom->fGetAddr)
+                addr.nTime -= 5 * 24 * 60 * 60;
+            AddAddress(addrdb, addr, false);
             pfrom->AddAddressKnown(addr);
             if (!pfrom->fGetAddr && addr.IsRoutable())
             {
@@ -1816,6 +1813,10 @@
         vector<CInv> vInv;
         vRecv >> vInv;
 
+        // Update the last seen time for this node's address
+        if (pfrom->fNetworkNode)
+            AddressCurrentlyConnected(pfrom->addr);
+
         CTxDB txdb("r");
         foreach(const CInv& inv, vInv)
         {
@@ -2099,6 +2100,25 @@
         if (pto->nVersion == 0)
             return true;
 
+        // Address refresh broadcast
+        static int64 nLastRebroadcast;
+        if (nLastRebroadcast < GetTime() - 24 * 60 * 60) // every 24 hours
+        {
+            nLastRebroadcast = GetTime();
+            CRITICAL_BLOCK(cs_vNodes)
+            {
+                foreach(CNode* pnode, vNodes)
+                {
+                    // Periodically clear setAddrKnown to allow refresh broadcasts
+                    pnode->setAddrKnown.clear();
+
+                    // Rebroadcast our address
+                    if (addrLocalHost.IsRoutable() && !fUseProxy)
+                        pnode->PushAddress(addrLocalHost);
+                }
+            }
+        }
+
 
         //
         // Message: addr
@@ -2187,7 +2207,7 @@
     }
     if (fGenerateBitcoins)
     {
-        int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS"));
+        int nProcessors = wxThread::GetCPUCount();
         printf("%d processors\n", nProcessors);
         if (nProcessors < 1)
             nProcessors = 1;
--- a/main.h
+++ b/main.h
@@ -968,6 +968,14 @@
             return error("CBlock::WriteToDisk() : ftell failed");
         fileout << *this;
 
+        // Flush stdio buffers and commit to disk before returning
+        fflush(fileout);
+#ifdef __WXMSW__
+        _commit(_fileno(fileout));
+#else
+        fsync(fileno(fileout));
+#endif
+
         return true;
     }
 
new file mode 100644
--- /dev/null
+++ b/makefile.unix
@@ -0,0 +1,86 @@
+# Copyright (c) 2009 Satoshi Nakamoto
+# Distributed under the MIT/X11 software license, see the accompanying
+# file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
+
+ifneq "$(BUILD)" "debug"
+ifneq "$(BUILD)" "release"
+BUILD=debug
+endif
+endif
+ifeq "$(BUILD)" "debug"
+D=d
+DEBUGFLAGS=-g -D__WXDEBUG__
+endif
+
+
+
+INCLUDEPATHS=-I"/usr/include" \
+             -I"/usr/local/boost_1_40_0" \
+             -I"/usr/local/db-4.7.25.NC/build_unix" \
+             -I"/usr/local/include/wx-2.8" \
+             -I"/usr/local/lib/wx/include/gtk2-ansi-debug-static-2.8"
+
+LIBPATHS=-L"/usr/lib" \
+         -L"/usr/local/lib" \
+         -L"/usr/local/db-4.7.25.NC/build_unix"
+
+LIBS= \
+ -Wl,-Bstatic -l boost_thread -l boost_system -l boost_filesystem -Wl,-Bdynamic \
+ -Wl,-Bstatic -l db_cxx -l wx_gtk2$(D)-2.8 -Wl,-Bdynamic \
+ -l crypto \
+ -l gtk-x11-2.0 -l gthread-2.0 -l SM
+WXDEFS=-D__WXGTK__ -DNOPCH
+CFLAGS=-O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
+HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
+
+
+
+all: bitcoin
+
+
+headers.h.gch: headers.h $(HEADERS) net.h irc.h market.h uibase.h ui.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/util.o: util.cpp		    $(HEADERS)
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/script.o: script.cpp	    $(HEADERS)
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/db.o: db.cpp		    $(HEADERS) market.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/net.o: net.cpp		    $(HEADERS) net.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/main.o: main.cpp		    $(HEADERS) net.h market.h sha.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/market.o: market.cpp	    $(HEADERS) market.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/ui.o: ui.cpp		    $(HEADERS) net.h uibase.h ui.h market.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/uibase.o: uibase.cpp	    uibase.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/sha.o: sha.cpp		    sha.h
+	g++ -c $(CFLAGS) -O3 -o $@ $<
+
+obj/irc.o:  irc.cpp		    $(HEADERS)
+	g++ -c $(CFLAGS) -o $@ $<
+
+
+
+
+OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
+	obj/ui.o obj/uibase.o obj/sha.o obj/irc.o 
+
+bitcoin: headers.h.gch $(OBJS)
+	g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
+
+clean:
+	-rm obj/*
+	-rm headers.h.gch
--- a/net.cpp
+++ b/net.cpp
@@ -3,7 +3,6 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
-#include <winsock2.h>
 
 void ThreadMessageHandler2(void* parg);
 void ThreadSocketHandler2(void* parg);
@@ -201,12 +200,14 @@
 
 
 
-bool AddAddress(CAddrDB& addrdb, const CAddress& addr)
+bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline)
 {
     if (!addr.IsRoutable())
         return false;
     if (addr.ip == addrLocalHost.ip)
         return false;
+    if (fCurrentlyOnline)
+        addr.nTime = GetAdjustedTime();
     CRITICAL_BLOCK(cs_mapAddresses)
     {
         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
@@ -219,24 +220,47 @@
         }
         else
         {
+            bool fUpdated = false;
             CAddress& addrFound = (*it).second;
             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
             {
                 // Services have been added
                 addrFound.nServices |= addr.nServices;
+                fUpdated = true;
+            }
+            int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
+            if (addrFound.nTime < addr.nTime - nUpdateInterval)
+            {
+                // Periodically update most recently seen time
+                addrFound.nTime = addr.nTime;
+                fUpdated = true;
+            }
+            if (fUpdated)
                 addrdb.WriteAddress(addrFound);
-                return true;
-            }
-            else if (addrFound.nTime < GetAdjustedTime() - 24 * 60 * 60)
+        }
+    }
+    return false;
+}
+
+void AddressCurrentlyConnected(const CAddress& addr)
+{
+    CRITICAL_BLOCK(cs_mapAddresses)
+    {
+        // Only if it's been published already
+        map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
+        if (it != mapAddresses.end())
+        {
+            CAddress& addrFound = (*it).second;
+            int64 nUpdateInterval = 60 * 60;
+            if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
             {
                 // Periodically update most recently seen time
                 addrFound.nTime = GetAdjustedTime();
+                CAddrDB addrdb;
                 addrdb.WriteAddress(addrFound);
-                return false;
             }
         }
     }
-    return false;
 }
 
 
@@ -398,9 +422,14 @@
         printf("connected %s\n", addrConnect.ToStringLog().c_str());
 
         // Set to nonblocking
-        u_long nOne = 1;
+#ifdef __WXMSW__
+		u_long nOne = 1;
         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
+#else
+        if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
+            printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
+#endif
 
         // Add node
         CNode* pnode = new CNode(hSocket, addrConnect, false);
@@ -418,7 +447,7 @@
     else
     {
         CRITICAL_BLOCK(cs_mapAddresses)
-            mapAddresses[addrConnect.GetKey()].nLastFailed = GetTime();
+            mapAddresses[addrConnect.GetKey()].nLastFailed = GetAdjustedTime();
         return NULL;
     }
 }
@@ -432,7 +461,7 @@
     // If outbound and never got version message, mark address as failed
     if (!fInbound && !fSuccessfullyConnected)
         CRITICAL_BLOCK(cs_mapAddresses)
-            mapAddresses[addr.GetKey()].nLastFailed = GetTime();
+            mapAddresses[addr.GetKey()].nLastFailed = GetAdjustedTime();
 
     // All of a nodes broadcasts and subscriptions are automatically torn down
     // when it goes down, so a node has to stay up to keep its broadcast going.
@@ -549,8 +578,8 @@
         timeout.tv_sec  = 0;
         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
 
-        struct fd_set fdsetRecv;
-        struct fd_set fdsetSend;
+        fd_set fdsetRecv;
+        fd_set fdsetSend;
         FD_ZERO(&fdsetRecv);
         FD_ZERO(&fdsetSend);
         SOCKET hSocketMax = 0;
@@ -599,7 +628,11 @@
         if (FD_ISSET(hListenSocket, &fdsetRecv))
         {
             struct sockaddr_in sockaddr;
+#ifdef __WXMSW__
             int len = sizeof(sockaddr);
+#else
+            socklen_t len = sizeof(sockaddr);
+#endif
             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
             CAddress addr(sockaddr);
             if (hSocket == INVALID_SOCKET)
@@ -765,14 +798,12 @@
     }
 
     // Initiate network connections
-    int nTry = 0;
-    bool fIRCOnly = false;
-    const int nMaxConnections = 15;
     loop
     {
         // Wait
         vnThreadsRunning[1]--;
         Sleep(500);
+        const int nMaxConnections = 15;
         while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
         {
             CheckForShutdown(1);
@@ -781,93 +812,55 @@
         vnThreadsRunning[1]++;
         CheckForShutdown(1);
 
-
+        //
+        // Choose an address to connect to based on most recently seen
         //
-        // The IP selection process is designed to limit vulnerability to address flooding.
-        // Any class C (a.b.c.?) has an equal chance of being chosen, then an IP is
-        // chosen within the class C.  An attacker may be able to allocate many IPs, but
-        // they would normally be concentrated in blocks of class C's.  They can hog the
-        // attention within their class C, but not the whole IP address space overall.
-        // A lone node in a class C will get as much attention as someone holding all 255
-        // IPs in another class C.
-        //
+        CAddress addrConnect;
+        int64 nBestTime = 0;
+        int64 nDelay = ((60 * 60) << vNodes.size());
+        if (vNodes.size() >= 3)
+            nDelay *= 4;
+        if (nGotIRCAddresses > 0)
+            nDelay *= 100;
 
-        // Every other try is with IRC addresses only
-        fIRCOnly = !fIRCOnly;
-        if (mapIRCAddresses.empty())
-            fIRCOnly = false;
-        else if (nTry++ < 30 && vNodes.size() < nMaxConnections/2)
-            fIRCOnly = true;
+        // Do this here so we don't have to critsect vNodes inside mapAddresses critsect
+        set<unsigned int> setConnected;
+        CRITICAL_BLOCK(cs_vNodes)
+            foreach(CNode* pnode, vNodes)
+                setConnected.insert(pnode->addr.ip);
 
-        // Make a list of unique class C's
-        unsigned char pchIPCMask[4] = { 0xff, 0xff, 0xff, 0x00 };
-        unsigned int nIPCMask = *(unsigned int*)pchIPCMask;
-        vector<unsigned int> vIPC;
-        CRITICAL_BLOCK(cs_mapIRCAddresses)
         CRITICAL_BLOCK(cs_mapAddresses)
         {
-            vIPC.reserve(mapAddresses.size());
-            unsigned int nPrev = 0;
             foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
             {
                 const CAddress& addr = item.second;
-                if (!addr.IsIPv4())
+                if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip))
                     continue;
-                if (fIRCOnly && !mapIRCAddresses.count(item.first))
+
+                // Limit retry frequency
+                if (GetAdjustedTime() < addr.nLastFailed + nDelay)
                     continue;
 
-                // Taking advantage of mapAddresses being in sorted order,
-                // with IPs of the same class C grouped together.
-                unsigned int ipC = addr.ip & nIPCMask;
-                if (ipC != nPrev)
-                    vIPC.push_back(nPrev = ipC);
+                // Try again only after all addresses had a first attempt
+                int64 nTime = addr.nTime;
+                if (addr.nLastFailed > addr.nTime)
+                    nTime -= 365 * 24 * 60 * 60;
+
+                // Randomize the order a little, putting the standard port first
+                nTime += GetRand(1 * 60 * 60);
+                if (addr.port != DEFAULT_PORT)
+                    nTime -= 1 * 60 * 60;
+
+                if (nTime > nBestTime)
+                {
+                    nBestTime = nTime;
+                    addrConnect = addr;
+                }
             }
         }
-        if (vIPC.empty())
-            continue;
 
-        // Choose a random class C
-        unsigned int ipC = vIPC[GetRand(vIPC.size())];
-
-        // Organize all addresses in the class C by IP
-        map<unsigned int, vector<CAddress> > mapIP;
-        CRITICAL_BLOCK(cs_mapIRCAddresses)
-        CRITICAL_BLOCK(cs_mapAddresses)
-        {
-            int64 nDelay = ((30 * 60) << vNodes.size());
-            if (!fIRCOnly)
-            {
-                nDelay *= 2;
-                if (vNodes.size() >= 3)
-                    nDelay *= 4;
-                if (!mapIRCAddresses.empty())
-                    nDelay *= 100;
-            }
-
-            for (map<vector<unsigned char>, CAddress>::iterator mi = mapAddresses.lower_bound(CAddress(ipC, 0).GetKey());
-                 mi != mapAddresses.upper_bound(CAddress(ipC | ~nIPCMask, 0xffff).GetKey());
-                 ++mi)
-            {
-                const CAddress& addr = (*mi).second;
-                if (fIRCOnly && !mapIRCAddresses.count((*mi).first))
-                    continue;
-
-                int64 nRandomizer = (addr.nLastFailed * addr.ip * 7777U) % 20000;
-                if (GetTime() - addr.nLastFailed > nDelay * nRandomizer / 10000)
-                    mapIP[addr.ip].push_back(addr);
-            }
-        }
-        if (mapIP.empty())
-            continue;
-
-        // Choose a random IP in the class C
-        map<unsigned int, vector<CAddress> >::iterator mi = mapIP.begin();
-        advance(mi, GetRand(mapIP.size()));
-
-        // Once we've chosen an IP, we'll try every given port before moving on
-        foreach(const CAddress& addrConnect, (*mi).second)
-            if (OpenNetworkConnection(addrConnect))
-                break;
+        if (addrConnect.IsValid())
+            OpenNetworkConnection(addrConnect);
     }
 }
 
@@ -989,6 +982,7 @@
         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
     strError = "";
 
+#ifdef __WXMSW__
     // Sockets startup
     WSADATA wsadata;
     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
@@ -998,6 +992,7 @@
         printf("%s\n", strError.c_str());
         return false;
     }
+#endif
 
     // Get local host ip
     char pszHostName[255];
@@ -1029,10 +1024,14 @@
     }
 
     // Set to nonblocking, incoming connections will also inherit this
+#ifdef __WXMSW__
     u_long nOne = 1;
     if (ioctlsocket(hListenSocket, FIONBIO, &nOne) == SOCKET_ERROR)
+#else
+    if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
+#endif
     {
-        strError = strprintf("Error: Couldn't set properties on socket for incoming connections (ioctlsocket returned error %d)", WSAGetLastError());
+        strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
         printf("%s\n", strError.c_str());
         return false;
     }
@@ -1041,7 +1040,7 @@
     // IP address, and port for the socket that is being bound
     int nRetryLimit = 15;
     struct sockaddr_in sockaddr = addrLocalHost.GetSockAddr();
-    if (bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
+    if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
     {
         int nErr = WSAGetLastError();
         if (nErr == WSAEADDRINUSE)
@@ -1131,7 +1130,9 @@
     Sleep(50);
 
     // Sockets shutdown
+#ifdef __WXMSW__
     WSACleanup();
+#endif
     return true;
 }
 
--- a/net.h
+++ b/net.h
@@ -22,7 +22,8 @@
 
 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
 bool GetMyExternalIP(unsigned int& ipRet);
-bool AddAddress(CAddrDB& addrdb, const CAddress& addr);
+bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline=true);
+void AddressCurrentlyConnected(const CAddress& addr);
 CNode* FindNode(unsigned int ip);
 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
--- a/ui.cpp
+++ b/ui.cpp
@@ -260,7 +260,8 @@
 CDataStream GetStreamFromEvent(const wxCommandEvent& event)
 {
     wxString strData = event.GetString();
-    return CDataStream(strData.begin(), strData.begin() + event.GetInt(), SER_NETWORK);
+    const char* pszBegin = strData.c_str();
+    return CDataStream(pszBegin, pszBegin + event.GetInt(), SER_NETWORK);
 }
 
 
@@ -288,20 +289,6 @@
     SetIcon(wxICON(bitcoin));
     ptaskbaricon = new CMyTaskBarIcon();
 
-    // Init toolbar with transparency masked bitmaps
-    m_toolBar->ClearTools();
-
-    //// shouldn't have to do mask separately anymore, bitmap alpha support added in wx 2.8.9,
-    wxBitmap bmpSend(wxT("send20"), wxBITMAP_TYPE_RESOURCE);
-    bmpSend.SetMask(new wxMask(wxBitmap(wxT("send20mask"), wxBITMAP_TYPE_RESOURCE)));
-    m_toolBar->AddTool(wxID_BUTTONSEND, wxT("&Send Coins"), bmpSend, wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString);
-
-    wxBitmap bmpAddressBook(wxT("addressbook20"), wxBITMAP_TYPE_RESOURCE);
-    bmpAddressBook.SetMask(new wxMask(wxBitmap(wxT("addressbook20mask"), wxBITMAP_TYPE_RESOURCE)));
-    m_toolBar->AddTool(wxID_BUTTONRECEIVE, wxT("&Address Book"), bmpAddressBook, wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString);
-
-    m_toolBar->Realize();
-
     // Init column headers
     int nDateWidth = DateTimeStr(1229413914).size() * 6 + 8;
     if (!strstr(DateTimeStr(1229413914).c_str(), "2008"))
@@ -909,15 +896,17 @@
         {
             TRY_CRITICAL_BLOCK(cs_mapWallet)
             {
-                bool fInserted = false;
+                string strTop;
+                if (m_listCtrl->GetItemCount())
+                    strTop = (string)m_listCtrl->GetItemText(0);
                 foreach(uint256 hash, vWalletUpdated)
                 {
                     map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
                     if (mi != mapWallet.end())
-                        fInserted |= InsertTransaction((*mi).second, false);
+                        InsertTransaction((*mi).second, false);
                 }
                 vWalletUpdated.clear();
-                if (fInserted)
+                if (m_listCtrl->GetItemCount() && strTop != (string)m_listCtrl->GetItemText(0))
                     m_listCtrl->ScrollList(0, INT_MAX);
             }
         }
@@ -954,7 +943,9 @@
     string strStatus = strprintf("     %d connections     %d blocks     %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);
     m_statusBar->SetStatusText(strStatus, 2);
 
+#ifdef __WXMSW__
     m_listCtrl->OnPaint(event);
+#endif
 }
 
 
@@ -1407,7 +1398,7 @@
     m_checkBoxLimitProcessors->SetValue(fLimitProcessors);
     m_spinCtrlLimitProcessors->Enable(fLimitProcessors);
     m_spinCtrlLimitProcessors->SetValue(nLimitProcessors);
-    int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS"));
+    int nProcessors = wxThread::GetCPUCount();
     if (nProcessors < 1)
         nProcessors = 999;
     m_spinCtrlLimitProcessors->SetRange(1, nProcessors);
@@ -1549,17 +1540,11 @@
         walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
     }
 
-    if (fUseProxy != m_checkBoxUseProxy->GetValue())
-    {
-        fUseProxy = m_checkBoxUseProxy->GetValue();
-        walletdb.WriteSetting("fUseProxy", fUseProxy);
-    }
-
-    if (addrProxy != GetProxyAddr())
-    {
-        addrProxy = GetProxyAddr();
-        walletdb.WriteSetting("addrProxy", addrProxy);
-    }
+    fUseProxy = m_checkBoxUseProxy->GetValue();
+    walletdb.WriteSetting("fUseProxy", fUseProxy);
+
+    addrProxy = GetProxyAddr();
+    walletdb.WriteSetting("addrProxy", addrProxy);
 }
 
 
@@ -1608,10 +1593,8 @@
     //// todo: should add a display of your balance for convenience
 
     // Set Icon
-    wxBitmap bmpSend(wxT("send16"), wxBITMAP_TYPE_RESOURCE);
-    bmpSend.SetMask(new wxMask(wxBitmap(wxT("send16masknoshadow"), wxBITMAP_TYPE_RESOURCE)));
     wxIcon iconSend;
-    iconSend.CopyFromBitmap(bmpSend);
+    iconSend.CopyFromBitmap(wxBitmap(send16noshadow_xpm));
     SetIcon(iconSend);
 
     wxCommandEvent event;
@@ -2231,10 +2214,8 @@
     m_listCtrl->SetFocus();
 
     // Set Icon
-    wxBitmap bmpAddressBook(wxT("addressbook16"), wxBITMAP_TYPE_RESOURCE);
-    bmpAddressBook.SetMask(new wxMask(wxBitmap(wxT("addressbook16mask"), wxBITMAP_TYPE_RESOURCE)));
     wxIcon iconAddressBook;
-    iconAddressBook.CopyFromBitmap(bmpAddressBook);
+    iconAddressBook.CopyFromBitmap(wxBitmap(addressbook16_xpm));
     SetIcon(iconAddressBook);
 
     // Fill listctrl with address book data
@@ -3345,7 +3326,7 @@
     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
 #endif
-#ifdef __WXDEBUG__
+#if defined(__WXMSW__) && defined(__WXDEBUG__)
     // Disable malfunctioning wxWidgets debug assertion
     g_isPainting = 10000;
 #endif
@@ -3362,8 +3343,7 @@
             "  -gen=0\t\t  Don't generate coins\n"
             "  -min\t\t  Start minimized\n"
             "  -datadir=<dir>\t  Specify data directory\n"
-            "  -proxy=<ip:port>\t  Connect through socks4 proxy,\n"
-            "  \t\t     e.g. -proxy=127.0.0.1:9050 to use TOR\n"
+            "  -proxy=<ip:port>\t  Connect through socks4 proxy\n"
             "  -addnode=<ip>\t  Add a node to connect to\n"
             "  -connect=<ip>\t  Connect only to the specified node\n"
             "  -?\t\t  This help message\n";
@@ -3386,6 +3366,8 @@
         unsigned int nStart = GetTime();
         loop
         {
+            // TODO: find out how to do this in Linux, or replace with wxWidgets commands
+#ifdef __WXMSW__
             // Show the previous instance and exit
             HWND hwndPrev = FindWindow("wxWindowClassNR", "Bitcoin");
             if (hwndPrev)
@@ -3395,6 +3377,7 @@
                 SetForegroundWindow(hwndPrev);
                 return false;
             }
+#endif
 
             if (GetTime() > nStart + 60)
                 return false;
@@ -3421,7 +3404,7 @@
         fPrintToDebugger = true;
 
     printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
-    printf("Bitcoin version %d, Windows version %08x\n", VERSION, GetVersion());
+    printf("Bitcoin version %d, OS version %s\n", VERSION, wxGetOsDescription().mb_str());
 
     if (mapArgs.count("-dropmessages"))
     {
@@ -3493,12 +3476,36 @@
         return false;
     }
 
+    if (mapArgs.count("-printblock"))
+    {
+        string strMatch = mapArgs["-printblock"];
+        int nFound = 0;
+        for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
+        {
+            uint256 hash = (*mi).first;
+            if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
+            {
+                CBlockIndex* pindex = (*mi).second;
+                CBlock block;
+                block.ReadFromDisk(pindex, true);
+                block.BuildMerkleTree();
+                block.print();
+                printf("\n");
+                nFound++;
+            }
+        }
+        if (nFound == 0)
+            printf("No blocks matching %s were found\n", strMatch.c_str());
+        OnExit();
+        return false;
+    }
+
     if (mapArgs.count("-gen"))
     {
         if (mapArgs["-gen"].empty())
             fGenerateBitcoins = true;
         else
-            fGenerateBitcoins = atoi(mapArgs["-gen"].c_str());
+            fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0);
     }
 
     if (mapArgs.count("-proxy"))
@@ -3511,9 +3518,6 @@
             OnExit();
             return false;
         }
-        CWalletDB walletdb;
-        walletdb.WriteSetting("fUseProxy", fUseProxy);
-        walletdb.WriteSetting("addrProxy", addrProxy);
     }
 
     if (mapArgs.count("-addnode"))
@@ -3522,6 +3526,7 @@
         foreach(string strAddr, mapMultiArgs["-addnode"])
         {
             CAddress addr(strAddr, NODE_NETWORK);
+            addr.nTime = 0; // so it won't relay unless successfully connected
             if (addr.IsValid())
                 AddAddress(addrdb, addr);
         }
@@ -3559,7 +3564,11 @@
     //
     // Tests
     //
+#ifdef __WXMSW__
     if (argc >= 2 && stricmp(argv[1], "-send") == 0)
+#else
+    if (argc >= 2 && strcmp(argv[1], "-send") == 0)
+#endif
     {
         int64 nValue = 1;
         if (argc >= 3)
@@ -3646,7 +3655,8 @@
 
 
 
-typedef WINSHELLAPI BOOL WINAPI (*PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
+#ifdef __WXMSW__
+typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
 
 string MyGetSpecialFolderPath(int nFolder, bool fCreate)
 {
@@ -3737,14 +3747,17 @@
         CoUninitialize();
     }
 }
-
-
-
-
-
-
-
-
-
-
-
+#else
+bool GetStartOnSystemStartup() { return false; }
+void SetStartOnSystemStartup(bool fAutoStart) { }
+#endif
+
+
+
+
+
+
+
+
+
+
--- a/uibase.cpp
+++ b/uibase.cpp
@@ -7,6 +7,10 @@
 
 #include "uibase.h"
 
+#include "xpm/addressbook20.xpm"
+#include "xpm/check.xpm"
+#include "xpm/send20.xpm"
+
 ///////////////////////////////////////////////////////////////////////////
 
 CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
@@ -60,8 +64,8 @@
 	m_toolBar->SetToolSeparation( 1 );
 	m_toolBar->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) );
 	
-	m_toolBar->AddTool( wxID_BUTTONSEND, wxT("&Send Coins"), wxBitmap( wxT("send20"), wxBITMAP_TYPE_RESOURCE ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
-	m_toolBar->AddTool( wxID_BUTTONRECEIVE, wxT("&Address Book"), wxBitmap( wxT("addressbook20"), wxBITMAP_TYPE_RESOURCE ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
+	m_toolBar->AddTool( wxID_BUTTONSEND, wxT("&Send Coins"), wxBitmap( send20_xpm ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
+	m_toolBar->AddTool( wxID_BUTTONRECEIVE, wxT("&Address Book"), wxBitmap( addressbook20_xpm ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
 	m_toolBar->Realize();
 	
 	m_statusBar = this->CreateStatusBar( 1, wxST_SIZEGRIP, wxID_ANY );
@@ -666,7 +670,7 @@
 	
 	bSizer47->Add( 0, 0, 1, wxEXPAND, 5 );
 	
-	m_bitmapCheckMark = new wxStaticBitmap( this, wxID_ANY, wxICON( check ), wxDefaultPosition, wxSize( 16,16 ), 0 );
+	m_bitmapCheckMark = new wxStaticBitmap( this, wxID_ANY, wxBitmap( check_xpm ), wxDefaultPosition, wxSize( 16,16 ), 0 );
 	bSizer47->Add( m_bitmapCheckMark, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 	
 	m_staticText36 = new wxStaticText( this, wxID_ANY, wxT("Pay &To:"), wxDefaultPosition, wxSize( -1,-1 ), wxALIGN_RIGHT );
--- a/uiproject.fbp
+++ b/uiproject.fbp
@@ -225,7 +225,7 @@
                     </object>
                 </object>
             </object>
-            <object class="wxToolBar" expanded="0">
+            <object class="wxToolBar" expanded="1">
                 <property name="bg"></property>
                 <property name="bitmapsize">20,20</property>
                 <property name="context_help"></property>
@@ -273,7 +273,7 @@
                 <event name="OnSize"></event>
                 <event name="OnUpdateUI"></event>
                 <object class="tool" expanded="1">
-                    <property name="bitmap">send20; Load From Resource</property>
+                    <property name="bitmap">xpm/send20.xpm; Load From File</property>
                     <property name="id">wxID_BUTTONSEND</property>
                     <property name="kind">wxITEM_NORMAL</property>
                     <property name="label">&amp;Send Coins</property>
@@ -287,7 +287,7 @@
                     <event name="OnUpdateUI"></event>
                 </object>
                 <object class="tool" expanded="1">
-                    <property name="bitmap">addressbook20; Load From Resource</property>
+                    <property name="bitmap">xpm/addressbook20.xpm; Load From File</property>
                     <property name="id">wxID_BUTTONRECEIVE</property>
                     <property name="kind">wxITEM_NORMAL</property>
                     <property name="label">&amp;Address Book</property>
@@ -1685,7 +1685,7 @@
                 </object>
             </object>
         </object>
-        <object class="Dialog" expanded="1">
+        <object class="Dialog" expanded="0">
             <property name="bg"></property>
             <property name="center"></property>
             <property name="context_help"></property>
@@ -3699,7 +3699,7 @@
                                     <property name="proportion">0</property>
                                     <object class="wxStaticBitmap" expanded="1">
                                         <property name="bg"></property>
-                                        <property name="bitmap">check; Load From Icon Resource [-1; -1]</property>
+                                        <property name="bitmap">xpm/check.xpm; Load From File</property>
                                         <property name="context_help"></property>
                                         <property name="enabled">1</property>
                                         <property name="fg"></property>
--- a/util.cpp
+++ b/util.cpp
@@ -38,8 +38,10 @@
             ppmutexOpenSSL[i] = new wxMutex();
         CRYPTO_set_locking_callback(locking_callback);
 
+#ifdef __WXMSW__
         // Seed random number generator with screen scrape and other hardware sources
         RAND_screen();
+#endif
 
         // Seed random number generator with performance counter
         RandAddSeed();
@@ -325,8 +327,8 @@
             pszValue = strchr(psz, '=');
             *pszValue++ = '\0';
         }
-        strlwr(psz);
         #ifdef __WXMSW__
+        _strlwr(psz);
         if (psz[0] == '/')
             psz[0] = '-';
         #endif
@@ -343,9 +345,13 @@
 
 void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
 {
+#ifdef __WXMSW__
     char pszModule[MAX_PATH];
     pszModule[0] = '\0';
     GetModuleFileName(NULL, pszModule, sizeof(pszModule));
+#else
+    const char* pszModule = wxStandardPaths::Get().GetExecutablePath().mb_str();
+#endif
     if (pex)
         snprintf(pszMessage, 1000,
             "EXCEPTION: %s       \n%s       \n%s in %s       \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
--- a/util.h
+++ b/util.h
@@ -55,9 +55,34 @@
 }
 
 #ifndef __WXMSW__
-#define closesocket(s)  close(s)
-#define INVALID_SOCKET  (SOCKET)(~0)
+#define _UI64_MAX           UINT64_MAX
+#define _I64_MAX            INT64_MAX
+#define WSAGetLastError()   errno
+#define WSAEWOULDBLOCK      EWOULDBLOCK
+#define WSAEMSGSIZE         EMSGSIZE
+#define WSAEINTR            EINTR
+#define WSAEINPROGRESS      EINPROGRESS
+#define WSAEADDRINUSE       EADDRINUSE
+#define closesocket(s)      close(s)
+#define INVALID_SOCKET      (SOCKET)(~0)
+#define SOCKET_ERROR        -1
 typedef u_int SOCKET;
+#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
+#define strlwr(psz)         to_lower(psz)
+#define _strlwr(psz)        to_lower(psz)
+#define _mkdir(psz)         filesystem::create_directory(psz)
+#define MAX_PATH            1024
+#define Sleep(n)            wxMilliSleep(n)
+#define Beep(n1,n2)         (0)
+inline int _beginthread(void(*pfn)(void*), unsigned nStack, void* parg) { thread(bind(pfn, parg)); return 0; }
+inline void _endthread() { pthread_exit(NULL); }
+inline int GetCurrentThread() { return 0; }
+// threads are processes on linux, so setpriority affects just the one thread
+inline void SetThreadPriority(int nThread, int nPriority) { setpriority(PRIO_PROCESS, getpid(), nPriority); }
+#define THREAD_PRIORITY_LOWEST          PRIO_MIN
+#define THREAD_PRIORITY_BELOW_NORMAL    2
+#define THREAD_PRIORITY_NORMAL          0
+#define THREAD_PRIORITY_ABOVE_NORMAL    0
 #endif
 
 
@@ -120,7 +145,7 @@
 protected:
     wxMutex mutex;
 public:
-    explicit CCriticalSection() { }
+    explicit CCriticalSection() : mutex(wxMUTEX_RECURSIVE) { }
     ~CCriticalSection() { }
     void Enter() { mutex.Lock(); }
     void Leave() { mutex.Unlock(); }
@@ -183,7 +208,7 @@
         // print to debug.log
         char pszFile[MAX_PATH+100];
         GetDataDir(pszFile);
-        strlcat(pszFile, "\\debug.log", sizeof(pszFile));
+        strlcat(pszFile, "/debug.log", sizeof(pszFile));
         FILE* fileout = fopen(pszFile, "a");
         if (fileout)
         {
@@ -354,13 +379,6 @@
     return wxGetLocalTimeMillis().GetValue();
 }
 
-#ifndef __WXMSW__
-inline void Sleep(unsigned int nMilliseconds)
-{
-    wxMilliSleep(nMilliseconds);
-}
-#endif
-
 
 
 
new file mode 100644
--- /dev/null
+++ b/xpm/addressbook16.xpm
@@ -0,0 +1,278 @@
+/* XPM */
+static char * addressbook16_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 256 2",
+"   c #FFFFFF",
+".  c #F7FFFF",
+"X  c #F7F7FF",
+"o  c #EFF7FF",
+"O  c #E6EFF7",
+"+  c #E6E6F7",
+"@  c #CEE6F7",
+"#  c #DEDEEF",
+"$  c #D6DEEF",
+"%  c #D6DEE6",
+"&  c #CEDEF7",
+"*  c #CEDEEF",
+"=  c #EFF708",
+"-  c #C5DEF7",
+";  c #CED6EF",
+":  c None",
+">  c #C5D6E6",
+",  c #BDD6F7",
+"<  c #BDD6EF",
+"1  c #D6CECE",
+"2  c #BDCEE6",
+"3  c #BDC5E6",
+"4  c #B5C5DE",
+"5  c #BDD631",
+"6  c #ADBDDE",
+"7  c #B5B5BD",
+"8  c #A5B5D6",
+"9  c #00FFFF",
+"0  c #9CB5CE",
+"q  c #9CADD6",
+"w  c #94A5D6",
+"e  c #8CA5D6",
+"r  c #8CA5CE",
+"t  c #8CA5C5",
+"y  c #849CC5",
+"u  c #7B9CD6",
+"i  c #7B9CCE",
+"p  c #31BDCE",
+"a  c #6B9CD6",
+"s  c #00F708",
+"d  c #8494AD",
+"f  c #7B94B5",
+"g  c #6B94D6",
+"h  c #6B9C84",
+"j  c #7B8CAD",
+"k  c #738CAD",
+"l  c #638CC5",
+"z  c #10CE42",
+"x  c #638CBD",
+"c  c #7B849C",
+"v  c #73849C",
+"b  c #6B84A5",
+"n  c #7B7BA5",
+"m  c #6B849C",
+"M  c #7B8C42",
+"N  c #5A84C5",
+"B  c #29AD6B",
+"V  c #F74A4A",
+"C  c #6384A5",
+"Z  c #5284C5",
+"A  c #637BA5",
+"S  c #637B9C",
+"D  c #9C637B",
+"F  c #6B7B5A",
+"G  c #637394",
+"H  c #52739C",
+"J  c #5A7384",
+"K  c #526B94",
+"L  c #426B94",
+"P  c #52638C",
+"I  c #426B7B",
+"U  c #5A5A8C",
+"Y  c #524A7B",
+"T  c #425273",
+"R  c #21636B",
+"E  c #106394",
+"W  c #106B52",
+"Q  c #3A4273",
+"!  c #31426B",
+"~  c #523163",
+"^  c #29426B",
+"/  c #293A63",
+"(  c #213A63",
+")  c #193A63",
+"_  c #193163",
+"`  c #19315A",
+"'  c #212963",
+"]  c #10315A",
+"[  c #082952",
+"{  c #FFCC33",
+"}  c #33FF33",
+"|  c #66FF33",
+" . c #99FF33",
+".. c #CCFF33",
+"X. c #FFFF33",
+"o. c #000066",
+"O. c #330066",
+"+. c #660066",
+"@. c #990066",
+"#. c #CC0066",
+"$. c #FF0066",
+"%. c #003366",
+"&. c #333366",
+"*. c #663366",
+"=. c #993366",
+"-. c #CC3366",
+";. c #FF3366",
+":. c #006666",
+">. c #336666",
+",. c #666666",
+"<. c #996666",
+"1. c #CC6666",
+"2. c #009966",
+"3. c #339966",
+"4. c #669966",
+"5. c #999966",
+"6. c #CC9966",
+"7. c #FF9966",
+"8. c #00CC66",
+"9. c #33CC66",
+"0. c #99CC66",
+"q. c #CCCC66",
+"w. c #FFCC66",
+"e. c #00FF66",
+"r. c #33FF66",
+"t. c #99FF66",
+"y. c #CCFF66",
+"u. c #FF00CC",
+"i. c #CC00FF",
+"p. c #009999",
+"a. c #993399",
+"s. c #990099",
+"d. c #CC0099",
+"f. c #000099",
+"g. c #333399",
+"h. c #660099",
+"j. c #CC3399",
+"k. c #FF0099",
+"l. c #006699",
+"z. c #336699",
+"x. c #663399",
+"c. c #996699",
+"v. c #CC6699",
+"b. c #FF3399",
+"n. c #339999",
+"m. c #669999",
+"M. c #999999",
+"N. c #CC9999",
+"B. c #FF9999",
+"V. c #00CC99",
+"C. c #33CC99",
+"Z. c #66CC66",
+"A. c #99CC99",
+"S. c #CCCC99",
+"D. c #FFCC99",
+"F. c #00FF99",
+"G. c #33FF99",
+"H. c #66CC99",
+"J. c #99FF99",
+"K. c #CCFF99",
+"L. c #FFFF99",
+"P. c #0000CC",
+"I. c #330099",
+"U. c #6600CC",
+"Y. c #9900CC",
+"T. c #CC00CC",
+"R. c #003399",
+"E. c #3333CC",
+"W. c #6633CC",
+"Q. c #9933CC",
+"!. c #CC33CC",
+"~. c #FF33CC",
+"^. c #0066CC",
+"/. c #3366CC",
+"(. c #666699",
+"). c #9966CC",
+"_. c #CC66CC",
+"`. c #FF6699",
+"'. c #0099CC",
+"]. c #3399CC",
+"[. c #6699CC",
+"{. c #9999CC",
+"}. c #CC99CC",
+"|. c #FF99CC",
+" X c #00CCCC",
+".X c #33CCCC",
+"XX c #66CCCC",
+"oX c #99CCCC",
+"OX c #CCCCCC",
+"+X c #FFCCCC",
+"@X c #00FFCC",
+"#X c #33FFCC",
+"$X c #66FF99",
+"%X c #99FFCC",
+"&X c #CCFFCC",
+"*X c #FFFFCC",
+"=X c #3300CC",
+"-X c #6600FF",
+";X c #9900FF",
+":X c #0033CC",
+">X c #3333FF",
+",X c #6633FF",
+"<X c #9933FF",
+"1X c #CC33FF",
+"2X c #FF33FF",
+"3X c #0066FF",
+"4X c #3366FF",
+"5X c #6666CC",
+"6X c #9966FF",
+"7X c #CC66FF",
+"8X c #FF66CC",
+"9X c #0099FF",
+"0X c #3399FF",
+"qX c #6699FF",
+"wX c #9999FF",
+"eX c #CC99FF",
+"rX c #FF99FF",
+"tX c #00CCFF",
+"yX c #33CCFF",
+"uX c #66CCFF",
+"iX c #99CCFF",
+"pX c #CCCCFF",
+"aX c #FFCCFF",
+"sX c #33FFFF",
+"dX c #66FFCC",
+"fX c #99FFFF",
+"gX c #CCFFFF",
+"hX c #FF6666",
+"jX c #66FF66",
+"kX c #FFFF66",
+"lX c #6666FF",
+"zX c #FF66FF",
+"xX c #66FFFF",
+"cX c #A50021",
+"vX c #5F5F5F",
+"bX c #777777",
+"nX c #868686",
+"mX c #969696",
+"MX c #CBCBCB",
+"NX c #B2B2B2",
+"BX c #D7D7D7",
+"VX c #DDDDDD",
+"CX c #E3E3E3",
+"ZX c #EAEAEA",
+"AX c #F1F1F1",
+"SX c #F8F8F8",
+"DX c #FFFBF0",
+"FX c #A0A0A4",
+"GX c #808080",
+"HX c #FF0000",
+"JX c #00FF00",
+"KX c #FFFF00",
+"LX c #0000FF",
+"PX c #FF00FF",
+"IX c #00FFFF",
+"UX c #FFFFFF",
+/* pixels */
+": : : : : : : : : : : : : : : : ",
+": : H H H A d : 7 G K H H : : : ",
+"n n c     X 4 k j X     b n n : ",
+"n 2 c $ 8 6 4 x < + 4 4 C V ~ : ",
+"n * c X o $ y N u 6 $ + b D Y : ",
+"n * c     X > g ,       S z R : ",
+"n * c * r r y g , 6 r q S s W : ",
+"n * c     X 4 N u +     m B I : ",
+"n * c     X ; a -       S 5 F : ",
+"n * c * r r r g -       S = M : ",
+"n * c     X 4 N -       m h J : ",
+"n * c     X ; a -       A 9 E : ",
+"n * ( ] ` ^ P l y T / / ( p L : ",
+"n O     > 0 f ) ! t 8     % n : ",
+"U U U U U U U ' Q U U U U U U : ",
+": : : : : : : : : : : : : : : : "
+};
new file mode 100644
--- /dev/null
+++ b/xpm/addressbook20.xpm
@@ -0,0 +1,282 @@
+/* XPM */
+static char * addressbook20_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"20 20 256 2",
+"   c #FFFFFF",
+".  c #F7FFFF",
+"X  c #F7F7FF",
+"o  c #EFF7FF",
+"O  c #EFF7F7",
+"+  c #E6EFFF",
+"@  c #E6EFF7",
+"#  c #DEEFFF",
+"$  c #DEE6F7",
+"%  c #DEE6EF",
+"&  c #D6E6F7",
+"*  c #FFFF00",
+"=  c #DEDEE6",
+"-  c #D6DEE6",
+";  c #D6D6DE",
+":  c #CED6E6",
+">  c None",
+",  c #C5D6E6",
+"<  c #C5CEE6",
+"1  c #B5CEEF",
+"2  c #C5C5C5",
+"3  c #C5DE31",
+"4  c #B5C5DE",
+"5  c #BDC5C5",
+"6  c #ADC5EF",
+"7  c #B5C5CE",
+"8  c #BDBDBD",
+"9  c #B5BDCE",
+"0  c #ADBDDE",
+"q  c #ADBDD6",
+"w  c #B5CE52",
+"e  c #ADB5C5",
+"r  c #00FFFF",
+"t  c #A5B5C5",
+"y  c #9CB5CE",
+"u  c #94B5DE",
+"i  c #9CADD6",
+"p  c #A5ADB5",
+"a  c #94ADDE",
+"s  c #94ADD6",
+"d  c #9CADBD",
+"f  c #8CADDE",
+"g  c #BD9CA5",
+"h  c #9CA5BD",
+"j  c #9CA5B5",
+"k  c #29D6E6",
+"l  c #8CA5CE",
+"z  c #849CCE",
+"x  c #6BA5C5",
+"c  c #739CDE",
+"v  c #00FF00",
+"b  c #739CD6",
+"n  c #7B94CE",
+"m  c #8494AD",
+"M  c #7394CE",
+"N  c #7B94B5",
+"B  c #4AB584",
+"V  c #848CB5",
+"C  c #6B94CE",
+"Z  c #6394D6",
+"A  c #6394CE",
+"S  c #7B8CAD",
+"D  c #6B8CC5",
+"F  c #738CAD",
+"G  c #5294B5",
+"H  c #6B84C5",
+"J  c #7384A5",
+"K  c #73849C",
+"L  c #738494",
+"P  c #FF4A4A",
+"I  c #FF4A42",
+"U  c #737B8C",
+"Y  c #637BAD",
+"T  c #527BBD",
+"R  c #637394",
+"E  c #637352",
+"W  c #5A6B8C",
+"Q  c #526B9C",
+"!  c #63638C",
+"~  c #5A734A",
+"^  c #4A6B9C",
+"/  c #526B63",
+"(  c #0884A5",
+")  c #526384",
+"_  c #52637B",
+"`  c #4A6B5A",
+"'  c #52636B",
+"]  c #525A8C",
+"[  c #525A7B",
+"{  c #426363",
+"}  c #4A5A7B",
+"|  c #425A8C",
+" . c #196B94",
+".. c #3A5A8C",
+"X. c #3A5A84",
+"o. c #087B4A",
+"O. c #21636B",
+"+. c #634263",
+"@. c #3A527B",
+"#. c #424A84",
+"$. c #315284",
+"%. c #295284",
+"&. c #3A4A6B",
+"*. c #42427B",
+"=. c #424273",
+"-. c #294A84",
+";. c #3A3A73",
+":. c #194284",
+">. c #104A63",
+",. c #213A6B",
+"<. c #31316B",
+"1. c #21315A",
+"2. c #212163",
+"3. c #08295A",
+"4. c #082152",
+"5. c #101952",
+"6. c #CC9966",
+"7. c #FF9966",
+"8. c #00CC66",
+"9. c #33CC66",
+"0. c #99CC66",
+"q. c #CCCC66",
+"w. c #FFCC66",
+"e. c #00FF66",
+"r. c #33FF66",
+"t. c #99FF66",
+"y. c #CCFF66",
+"u. c #FF00CC",
+"i. c #CC00FF",
+"p. c #009999",
+"a. c #993399",
+"s. c #990099",
+"d. c #CC0099",
+"f. c #000099",
+"g. c #333399",
+"h. c #660099",
+"j. c #CC3399",
+"k. c #FF0099",
+"l. c #006699",
+"z. c #336699",
+"x. c #663399",
+"c. c #996699",
+"v. c #CC6699",
+"b. c #FF3399",
+"n. c #339999",
+"m. c #669999",
+"M. c #999999",
+"N. c #CC9999",
+"B. c #FF9999",
+"V. c #00CC99",
+"C. c #33CC99",
+"Z. c #66CC66",
+"A. c #99CC99",
+"S. c #CCCC99",
+"D. c #FFCC99",
+"F. c #00FF99",
+"G. c #33FF99",
+"H. c #66CC99",
+"J. c #99FF99",
+"K. c #CCFF99",
+"L. c #FFFF99",
+"P. c #0000CC",
+"I. c #330099",
+"U. c #6600CC",
+"Y. c #9900CC",
+"T. c #CC00CC",
+"R. c #003399",
+"E. c #3333CC",
+"W. c #6633CC",
+"Q. c #9933CC",
+"!. c #CC33CC",
+"~. c #FF33CC",
+"^. c #0066CC",
+"/. c #3366CC",
+"(. c #666699",
+"). c #9966CC",
+"_. c #CC66CC",
+"`. c #FF6699",
+"'. c #0099CC",
+"]. c #3399CC",
+"[. c #6699CC",
+"{. c #9999CC",
+"}. c #CC99CC",
+"|. c #FF99CC",
+" X c #00CCCC",
+".X c #33CCCC",
+"XX c #66CCCC",
+"oX c #99CCCC",
+"OX c #CCCCCC",
+"+X c #FFCCCC",
+"@X c #00FFCC",
+"#X c #33FFCC",
+"$X c #66FF99",
+"%X c #99FFCC",
+"&X c #CCFFCC",
+"*X c #FFFFCC",
+"=X c #3300CC",
+"-X c #6600FF",
+";X c #9900FF",
+":X c #0033CC",
+">X c #3333FF",
+",X c #6633FF",
+"<X c #9933FF",
+"1X c #CC33FF",
+"2X c #FF33FF",
+"3X c #0066FF",
+"4X c #3366FF",
+"5X c #6666CC",
+"6X c #9966FF",
+"7X c #CC66FF",
+"8X c #FF66CC",
+"9X c #0099FF",
+"0X c #3399FF",
+"qX c #6699FF",
+"wX c #9999FF",
+"eX c #CC99FF",
+"rX c #FF99FF",
+"tX c #00CCFF",
+"yX c #33CCFF",
+"uX c #66CCFF",
+"iX c #99CCFF",
+"pX c #CCCCFF",
+"aX c #FFCCFF",
+"sX c #33FFFF",
+"dX c #66FFCC",
+"fX c #99FFFF",
+"gX c #CCFFFF",
+"hX c #FF6666",
+"jX c #66FF66",
+"kX c #FFFF66",
+"lX c #6666FF",
+"zX c #FF66FF",
+"xX c #66FFFF",
+"cX c #A50021",
+"vX c #5F5F5F",
+"bX c #777777",
+"nX c #868686",
+"mX c #969696",
+"MX c #CBCBCB",
+"NX c #B2B2B2",
+"BX c #D7D7D7",
+"VX c #DDDDDD",
+"CX c #E3E3E3",
+"ZX c #EAEAEA",
+"AX c #F1F1F1",
+"SX c #F8F8F8",
+"DX c #FFFBF0",
+"FX c #A0A0A4",
+"GX c #808080",
+"HX c #FF0000",
+"JX c #00FF00",
+"KX c #FFFF00",
+"LX c #0000FF",
+"PX c #FF00FF",
+"IX c #00FFFF",
+"UX c #FFFFFF",
+/* pixels */
+"> > > > > > > > > > > > > > > > > > > > ",
+"> > > > > > > > > > > > > > > > > > > > ",
+"> > U $.| | ^ S 2 > p W | | @.L > > > > ",
+"8 5 R -       < Y j S O     - ) g e > > ",
+"! V K -       % a Q #       - +.P <.> > ",
+"! & K - 0 z n D C b f n n z q +.P <.> > ",
+"! & K -       % M A 1       - %.G #.> > ",
+"! & K -       % u b #       - o.v >.> > ",
+"! & K - 0 z n H M b 6 z n z q o.v >.> > ",
+"! & K -     X - M A a       - O.B @.> > ",
+"! & K -     X % u b #       - ` 3 / > > ",
+"! & K - 0 l i 4 u b #       - ~ * E > > ",
+"! & K - X o $ s T b #       - { w ' > > ",
+"! & K -       % f b #       -  .k -.> > ",
+"! & K m d t 7 , u b # ; 9 9 h ( r :.> > ",
+"! & h _ _ [ &.4.$.A ,.1.} _ _ F x ] > > ",
+"! @       , y N _ 3._ N y ,     @ ! > > ",
+"*.*.*.*.*.*.*.*.;.5.*.*.*.*.*.*.*.2.> > ",
+"> > > > > > > > > > > > > > > > > > > > ",
+"> > > > > > > > > > > > > > > > > > > > "
+};
new file mode 100644
--- /dev/null
+++ b/xpm/bitcoin.xpm
@@ -0,0 +1,304 @@
+/* XPM */
+static char * bitcoin_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 250 2",
+"   c #725203",
+".  c #795603",
+"X  c #7D5903",
+"o  c #76560B",
+"O  c #77590E",
+"+  c #795A0D",
+"@  c #7B5D14",
+"#  c #7C5F18",
+"$  c #7D6019",
+"%  c #825D05",
+"&  c #856007",
+"*  c #86620B",
+"=  c #8B660B",
+"-  c #8E690E",
+";  c #906A0F",
+":  c #8F6B17",
+">  c #83641C",
+",  c #8D6C1E",
+"<  c #926C11",
+"1  c #967014",
+"2  c #997215",
+"3  c #9C761B",
+"4  c #9E791D",
+"5  c #A37C1E",
+"6  c #816520",
+"7  c #876A25",
+"8  c #8E6E22",
+"9  c #866A29",
+"0  c #896E2C",
+"q  c #8E7020",
+"w  c #937324",
+"e  c #997722",
+"r  c #9E7B25",
+"t  c #94762B",
+"y  c #967828",
+"u  c #9A7B2D",
+"i  c #8B7131",
+"p  c #9E7E31",
+"a  c #947839",
+"s  c #A37D22",
+"d  c #A68125",
+"f  c #AA8325",
+"g  c #AE8827",
+"h  c #A6832D",
+"j  c #AA852B",
+"k  c #AD892B",
+"l  c #B08727",
+"z  c #B28827",
+"x  c #B08729",
+"c  c #B38B2C",
+"v  c #B88E2F",
+"b  c #B8902D",
+"n  c #A38334",
+"m  c #A98632",
+"M  c #AB8A34",
+"N  c #A4873C",
+"B  c #A78A3D",
+"V  c #AC8B3C",
+"C  c #B38D32",
+"Z  c #BA8F30",
+"A  c #B28E3C",
+"S  c #B69332",
+"D  c #BC9433",
+"F  c #BF9832",
+"G  c #B4923C",
+"H  c #BA963D",
+"J  c #B7993E",
+"K  c #BE9A3B",
+"L  c #C1932F",
+"P  c #C39732",
+"I  c #C49935",
+"U  c #C59C3A",
+"Y  c #C99E3D",
+"T  c #C2A13F",
+"R  c #CDA23F",
+"E  c #9D8342",
+"W  c #AB8C43",
+"Q  c #B28E40",
+"!  c #AE9144",
+"~  c #AE914A",
+"^  c #B49445",
+"/  c #BC9B44",
+"(  c #B3964D",
+")  c #B5994C",
+"_  c #BD9B4A",
+"`  c #A98F50",
+"'  c #B19553",
+"]  c #B59A54",
+"[  c #BD9F51",
+"{  c #B59B5C",
+"}  c #B89D5C",
+"|  c #BEA155",
+" . c #BDA35D",
+".. c #B59C61",
+"X. c #B99F66",
+"o. c #BCA363",
+"O. c #BDA56C",
+"+. c #BCA571",
+"@. c #BDA873",
+"#. c #BFAA78",
+"$. c #C49D43",
+"%. c #C99F45",
+"&. c #C29E4B",
+"*. c #C5A144",
+"=. c #CCA244",
+"-. c #C5A44B",
+";. c #CAA54B",
+":. c #C8A84C",
+">. c #D0A644",
+",. c #D3AA44",
+"<. c #D3AC4C",
+"1. c #D8AD4D",
+"2. c #DAB046",
+"3. c #DCB24E",
+"4. c #C3A454",
+"5. c #CBA751",
+"6. c #CCAA53",
+"7. c #C1A65B",
+"8. c #C8A75A",
+"9. c #CBAC5B",
+"0. c #D0A650",
+"q. c #D2AC53",
+"w. c #DAAD54",
+"e. c #D3AD5C",
+"r. c #CFB259",
+"t. c #D4B156",
+"y. c #DDB454",
+"u. c #D4B25C",
+"i. c #DAB65A",
+"p. c #D7B95F",
+"a. c #DEBA5E",
+"s. c #E2B555",
+"d. c #E5BA53",
+"f. c #E1B55A",
+"g. c #E5BC5C",
+"h. c #EABF5D",
+"j. c #C1A761",
+"k. c #C4AA63",
+"l. c #CBAE63",
+"z. c #CBB166",
+"x. c #CBB26C",
+"c. c #D4B263",
+"v. c #DAB462",
+"b. c #D6B864",
+"n. c #DCB965",
+"m. c #D3B669",
+"M. c #DCB768",
+"N. c #D4BA6E",
+"B. c #DCBB6C",
+"V. c #CDB672",
+"C. c #D2B972",
+"Z. c #DBBE72",
+"A. c #E4BC62",
+"S. c #E9BE62",
+"D. c #E2BD6C",
+"F. c #E0BF72",
+"G. c #E6C05E",
+"H. c #EFC05D",
+"J. c #F0C15B",
+"K. c #DFC167",
+"L. c #D7C069",
+"P. c #DDC36D",
+"I. c #DBC376",
+"U. c #D4C17B",
+"Y. c #DAC17B",
+"T. c #D8C878",
+"R. c #E4C362",
+"E. c #EBC364",
+"W. c #E3C865",
+"Q. c #EDC866",
+"!. c #E4C36A",
+"~. c #E9C66B",
+"^. c #ECCA6B",
+"/. c #F1C564",
+"(. c #F8C765",
+"). c #F5CB66",
+"_. c #F8CC67",
+"`. c #F6CC6A",
+"'. c #F9CD6B",
+"]. c #EED26A",
+"[. c #F2D06F",
+"{. c #FBD26D",
+"}. c #E4C374",
+"|. c #EBC474",
+" X c #E1C972",
+".X c #EDCD72",
+"XX c #E4C57A",
+"oX c #E9C67C",
+"OX c #E5C87C",
+"+X c #EACA7D",
+"@X c #F2CC74",
+"#X c #FBCF71",
+"$X c #EED174",
+"%X c #ECD37B",
+"&X c #F4D274",
+"*X c #FDD473",
+"=X c #FFD975",
+"-X c #F4D57C",
+";X c #FCD57A",
+":X c #F3DA7C",
+">X c #FEDB7C",
+",X c #FFE37D",
+"<X c #DCC683",
+"1X c #E4C681",
+"2X c #E4CA84",
+"3X c #EBCD83",
+"4X c #E4CE8B",
+"5X c #EDCE8A",
+"6X c #EED186",
+"7X c #E5D08E",
+"8X c #EDD38B",
+"9X c #FBD581",
+"0X c #F5DB84",
+"qX c #FCDC83",
+"wX c #F2D38C",
+"eX c #F5DA8D",
+"rX c #FCDD8A",
+"tX c #EAD493",
+"yX c #EDDB94",
+"uX c #EDD898",
+"iX c #F1D594",
+"pX c #F5DB93",
+"aX c #F3DD9E",
+"sX c #F5E184",
+"dX c #FFE384",
+"fX c #FFE883",
+"gX c #F3E18D",
+"hX c #FEE38B",
+"jX c #FFEB8D",
+"kX c #FEE594",
+"lX c #FFEC93",
+"zX c #FEE599",
+"xX c #FFEB9B",
+"cX c #FFF296",
+"vX c #FFF39B",
+"bX c #FFF99C",
+"nX c #F3DFA0",
+"mX c #F6E2A3",
+"MX c #F8E5A5",
+"NX c #F4EAA4",
+"BX c #FEECA3",
+"VX c #FAE7A9",
+"CX c #FEEBAD",
+"ZX c #FFF2AD",
+"AX c #FEF4B4",
+"SX c #FFFAB5",
+"DX c #F9F7B9",
+"FX c #FFFCBC",
+"GX c #FFFDC2",
+"HX c None",
+/* pixels */
+"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX#.O.{ ~ W W ~ { o.O.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXO.W h j s f g b b S k f d 4 e ` HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHXHXHX' h f l U 1.H./.{.{.,X>X=XQ.s.=.v 5 1 < E HXHXHXHXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHX' g f F d.).).{.{.=X=X=X{.{.{.`.`.`.).g.U f 2 * a HXHXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXV f b G.J.{.{.{.*X=X,X=X*X{.`.).`.).).{.`.{./.U 5 ; + HXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHX} h g 1.)._._.{.,X*X=X,X{.{.)._.).).`.`.`.{.*X*X*X`.y.g 2 & $ HXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHX{ j c G.).{.{.{.=X,X{.{.J.d.2.R 2.,.3.g.`.&X;X;X;X&X[.{.`.I 3 & + HXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHX{ d D /.{.{.*X=X=X*X).3.R I I I P F F U $.;.n.-XrXrX;X&X;X>XdX:.4 X o HXHXHXHXHXHXHX",
+"HXHXHXHXHX..j v /.*X=X=X=X=X`.1.R R R R I I I P K U *.e.D.|.}.+XrXqXhXhXdXfX:.4 X o HXHXHXHXHXHX",
+"HXHXHXHXHXh v `.{.>X,X*X{.g.>.Y R I I I I I I U U ;.t.D.|.oXB.z.F.kXvXcXjXjXjX/ 1 . + HXHXHXHXHX",
+"HXHXHXHXV g Q.=X=X>X>X'.>.Y Y U R I I I P P I U U <.n.~.}.F.XXXX}.%XbXbXcXcXcXsXc =   # HXHXHXHX",
+"HXHXHX} j t.>X>X>X*X'.>.U U I U P U U I P P I U T 6.M.D.oX5XwXeXeXqX0XvXbXbXcXjXW.5 %   HXHXHXHX",
+"HXHXHXM G hXhXqX>X*X<.U U U I I I I I I D D U T T -.9.B.3XpXpXzXgXqX:X:XbXbXcXjXfXT <   o HXHXHX",
+"HXHX} k  XlXkXkXrXA.$.D Z Z Z v v v b b v D U U *.-.9.B.OX2XOXI.P.L.K.W.$XbXcXjX,X].d %   9 HXHX",
+"HXHXV J xXxXxXxXrX5.&.A M m m m h h n s 5 g S K *.:.8.4.| k.x.C.N.z.7.) :.$XjXfX,X,XT ;   o HXHX",
+"HXHXM L.vXxXxXxXF._ MXCXCXCXCXCXCXCXCXmXY.h g K *./ ^ Y.mXCXCXCXCXCXCXVXZ.4.hXfX,X,XW.4 X   HXHX",
+"HX] k gXxXxXxXgXe.V MXCXCXCXCXVXCXCXCXCXCXyXh D G [ mXCXCXCXCXCXCXCXCXCX4XG ~.fX,X,X,Xg &   $ HX",
+"HXV J vXxXxXxX6Xe.V MXCXCXCXCXk.N VXCXCXCXVX| h ^ MXCXCXCXCXuX( n V l.mX4XA y.fX,X,X=XT ;     HX",
+"HXk r.xXxXxXxX|.v.V MXCXCXCXCXo.> 4XCXCXCXCXx.w tXCXCXCXCXnXn V / / M V m.&.t.=X,X,X=Xy.2 o   HX",
+"HXk P.xXvXxXxX|.M.Q nXCXCXCXCXj.w <XCXCXCXCXz.W CXCXCXCXCXk.V e.a.i.:.-.;.e.f.@X>X>X=XH.5 X   $ ",
+"o.k %XvXbXBXkX|.D.Q nXCXCXCXCXj., 7XCXCXCXCX~ k.CXCXCXCXCXV &.n.R.g.G.g.S.S.S.(.qX*X=X`.5 X   $ ",
+" .k 0XvXvXvXrX@XD.^ VXCXCXCXCXx.~ VXCXCXCX<Xe C.CXCXCXCXMXn q.R.R.h.S.E.E.E.S.S.>X=X*X*Xd X   $ ",
+"{ k sXcXvXBXeX@XD.( nXCXCXCXCXCXCXCXCXVXo., u T.CXCXCXVXmXn t.E.g.g.h.S.g.S.f.A.>X;X*X*Xf &   o ",
+"{ k sXjXlXcX0X~.n.^ MXCXCXCXCXCXCXCXCXCXCXU.t U.CXCXCXCXmXM p.~.W.g.s.s.s.s.f.A.>X*X*X*Xj %     ",
+"o.k :XjXlXlX-XD.v.A MXCXCXCXCXj.t mXCXCXCXCX .x.CXCXCXCXVXV p.$X^.E.g.s.w.w.w.A.9X;X*X*Xf X     ",
+"o.g ].dXjXhX-Xn.e.V MXCXCXCXCXj.8 <XCXCXCXCX<X] CXCXCXCXCX^ r.$X$X~.A.s.w.1.q.S.qX>X*X#X5 X   O ",
+"HXj K.dXdXhX9Xv.9.M MXCXCXCXCXk.a Z.CXCXCXCX7Xu CXCXCXCXCXV./ !.$X~.f.5.%.0.q.S.>X*X*XE.5 X   # ",
+"HXj t.dX,XdXdXi.6.N MXCXCXCXCXo.q <XCXCXCXCX<Xy 4XCXCXCXCXMX) / e.6./ _ C.U ;.`.;X*X#Xs.1 .   @ ",
+"HXj K >XqXqXqX!.6.m MXCXCXCXCXV.' VXCXCXZXCXk.! ] VXCXCXCXCXVXC.[ 7.Z.VX2Xx %.#X#X'.'.%.- o   6 ",
+"HX( g &X>X>XdX-X5.M MXCXCXCXCXCXCXCXCXCXCX7X) m.9. .MXCXCXCXCXCXCXCXCXCX2Xs 1.'.`.'.'.x %     HX",
+"HXO.j y.>X>X>X>X6.! zXMXMXMXMXMXMXMXMXuXx.( N.8X6Xz.) C.uXCXCXCXCXCXVX7X4.c h.'.(.(.s.5 X     HX",
+"HXHXj H &X=X:X>X~./ V h y u n n n N W ( 7.Z.8XpXpX+Xm.| V V ^ ) ( m e 3 s R (.(.'.'.Y ; .   > HX",
+"HXHX} f G.&X&X&X:Xt._ / ) _ 4.8.l.m.B.Z.2XwXpXeXwX6X+XP.c.8.-./ C x x z P J.(.'.(./.5 %     HXHX",
+"HXHXHXh D &X&X&X&X@X:.4.5.9.c.m.F.OX+XwXwXwXwX6X3XOX}.D.D.v.w.%.Y I P P d.(.(.'.'.=.< .   + HXHX",
+"HXHXHX] d y.[.&X&X&X~.:.4.9.e.M.B.}.oX3X5X3X3X+X}.F.M.e.0.0.0.%.%.Y Y s.#X#X#X#XS.s %     HXHXHX",
+"HXHXHXHXm g `.@X&X&X&X~.5.6.e.b.B.}.XX+X3XOX}.I.F.F.D.e.e.e.e.e.q.0.A.;X;X#X-X@XZ = o   + HXHXHX",
+"HXHXHXHX..j D @X&X&X&X&X@Xp.u.M.D.}.XXOXOXZ.Z.XX1XOXoXoXF.F.F.M.D.6XrXqX9X9X9X%.1 .     HXHXHXHX",
+"HXHXHXHXHX' f $.&X&X&X>XqXqX XB.D.!.XXXXZ.XXOX5XwXwXwXwXiXwXwXnXVXZXBXxXzXxXb.r X     $ HXHXHXHX",
+"HXHXHXHXHXHX~ j ;.qXqXqXqXrXkXrX+XD.Z.Z.XX1X2X5X5X5XwXwXiXnXCXGXGXFXFXSXAXT.s %     @ HXHXHXHXHX",
+"HXHXHXHXHXHXHX~ j -.0XrXzXxXzXzXzXzXwX3XXXXXOX1X2X5XpXmXAXFXGXGXGXFXFXSXL.r %     O HXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHX! j / gXSXSXZXxXzXzXkXxXzXBXBXBXZXCXAXAXAXAXSXSXSXSXNX| 3 &     O HXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHX} n V U.DXSXBXzXkXkXkXxXxXxXBXxXBXBXCXZXZXZXAXAXU.M < .     @ HXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHXV d G Z.pXzXkXzXjXkXkXxXzXxXxXxXBXBXZXNXT.G 3 * .     9 HXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHXHX@.u s k -.K.6XhXjXhXkXlXzXzXzXeXOX9.k 3 = X     O HXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHXHXHXHX..w < s j k K -.;.:.-./ C j 4 < & .     O HXHXHXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXE * = - - < < - = & X .       0 HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
+"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXi 7 7 @ o o O > 0 i HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX"
+};
new file mode 100644
--- /dev/null
+++ b/xpm/check.xpm
@@ -0,0 +1,41 @@
+/* XPM */
+static char * check_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 3 1",
+"  c #008000",
+". c #00FF00",
+"X c None",
+/* pixels */
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXX   XXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXX .  XXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX .. XXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX .  XXXXXXXXXXXX",
+"XXXXXXXXXXXXXXX .. XXXXXXXXXXXXX",
+"XXXXXXXXXXX  XX .  XXXXXXXXXXXXX",
+"XXXXXXXXXXX .  .. XXXXXXXXXXXXXX",
+"XXXXXXXXXXX .. .  XXXXXXXXXXXXXX",
+"XXXXXXXXXXXX ... XXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXX .  XXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXX  XXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+};
new file mode 100644
--- /dev/null
+++ b/xpm/send16.xpm
@@ -0,0 +1,278 @@
+/* XPM */
+static char * send16_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 256 2",
+"   c #ADF7AD",
+".  c #9CFF9C",
+"X  c None",
+"o  c #ADEFAD",
+"O  c #94FF94",
+"+  c #D6CECE",
+"@  c #8CFF8C",
+"#  c #CECECE",
+"$  c #CECEC5",
+"%  c #84FF84",
+"&  c #CEC5C5",
+"*  c #73FF73",
+"=  c #C5C5C5",
+"-  c #6BFF6B",
+";  c #73F773",
+":  c #C5BDBD",
+">  c #6BF76B",
+",  c #BDBDBD",
+"<  c #63F763",
+"1  c #B5B5B5",
+"2  c #52F752",
+"3  c #42FF42",
+"4  c #3AFF3A",
+"5  c #ADADAD",
+"6  c #ADADA5",
+"7  c #4AEF4A",
+"8  c #29FF29",
+"9  c #A5A5A5",
+"0  c #42E642",
+"q  c #9CA59C",
+"w  c #3AE63A",
+"e  c #10FF10",
+"r  c #08FF08",
+"t  c #949C94",
+"y  c #00FF00",
+"u  c #00F700",
+"i  c #8C948C",
+"p  c #00EF00",
+"a  c #08E608",
+"s  c #10DE10",
+"d  c #00E600",
+"f  c #00DE00",
+"g  c #19C519",
+"h  c #00CE00",
+"j  c #00C500",
+"k  c #008C00",
+"l  c #008400",
+"z  c #669900",
+"x  c #999900",
+"c  c #CC9900",
+"v  c #FF9900",
+"b  c #00CC00",
+"n  c #33CC00",
+"m  c #66CC00",
+"M  c #99CC00",
+"N  c #CCCC00",
+"B  c #FFCC00",
+"V  c #66FF00",
+"C  c #99FF00",
+"Z  c #CCFF00",
+"A  c #000033",
+"S  c #330033",
+"D  c #660033",
+"F  c #990033",
+"G  c #CC0033",
+"H  c #FF0033",
+"J  c #003333",
+"K  c #333333",
+"L  c #663333",
+"P  c #993333",
+"I  c #CC3333",
+"U  c #FF3333",
+"Y  c #006633",
+"T  c #336633",
+"R  c #666633",
+"E  c #996633",
+"W  c #CC6633",
+"Q  c #FF6633",
+"!  c #009933",
+"~  c #339933",
+"^  c #669933",
+"/  c #999933",
+"(  c #CC9933",
+")  c #FF9933",
+"_  c #00CC33",
+"`  c #33CC33",
+"'  c #66CC33",
+"]  c #99CC33",
+"[  c #CCCC33",
+"{  c #FFCC33",
+"}  c #33FF33",
+"|  c #66FF33",
+" . c #99FF33",
+".. c #CCFF33",
+"X. c #FFFF33",
+"o. c #000066",
+"O. c #330066",
+"+. c #660066",
+"@. c #990066",
+"#. c #CC0066",
+"$. c #FF0066",
+"%. c #003366",
+"&. c #333366",
+"*. c #663366",
+"=. c #993366",
+"-. c #CC3366",
+";. c #FF3366",
+":. c #006666",
+">. c #336666",
+",. c #666666",
+"<. c #996666",
+"1. c #CC6666",
+"2. c #009966",
+"3. c #339966",
+"4. c #669966",
+"5. c #999966",
+"6. c #CC9966",
+"7. c #FF9966",
+"8. c #00CC66",
+"9. c #33CC66",
+"0. c #99CC66",
+"q. c #CCCC66",
+"w. c #FFCC66",
+"e. c #00FF66",
+"r. c #33FF66",
+"t. c #99FF66",
+"y. c #CCFF66",
+"u. c #FF00CC",
+"i. c #CC00FF",
+"p. c #009999",
+"a. c #993399",
+"s. c #990099",
+"d. c #CC0099",
+"f. c #000099",
+"g. c #333399",
+"h. c #660099",
+"j. c #CC3399",
+"k. c #FF0099",
+"l. c #006699",
+"z. c #336699",
+"x. c #663399",
+"c. c #996699",
+"v. c #CC6699",
+"b. c #FF3399",
+"n. c #339999",
+"m. c #669999",
+"M. c #999999",
+"N. c #CC9999",
+"B. c #FF9999",
+"V. c #00CC99",
+"C. c #33CC99",
+"Z. c #66CC66",
+"A. c #99CC99",
+"S. c #CCCC99",
+"D. c #FFCC99",
+"F. c #00FF99",
+"G. c #33FF99",
+"H. c #66CC99",
+"J. c #99FF99",
+"K. c #CCFF99",
+"L. c #FFFF99",
+"P. c #0000CC",
+"I. c #330099",
+"U. c #6600CC",
+"Y. c #9900CC",
+"T. c #CC00CC",
+"R. c #003399",
+"E. c #3333CC",
+"W. c #6633CC",
+"Q. c #9933CC",
+"!. c #CC33CC",
+"~. c #FF33CC",
+"^. c #0066CC",
+"/. c #3366CC",
+"(. c #666699",
+"). c #9966CC",
+"_. c #CC66CC",
+"`. c #FF6699",
+"'. c #0099CC",
+"]. c #3399CC",
+"[. c #6699CC",
+"{. c #9999CC",
+"}. c #CC99CC",
+"|. c #FF99CC",
+" X c #00CCCC",
+".X c #33CCCC",
+"XX c #66CCCC",
+"oX c #99CCCC",
+"OX c #CCCCCC",
+"+X c #FFCCCC",
+"@X c #00FFCC",
+"#X c #33FFCC",
+"$X c #66FF99",
+"%X c #99FFCC",
+"&X c #CCFFCC",
+"*X c #FFFFCC",
+"=X c #3300CC",
+"-X c #6600FF",
+";X c #9900FF",
+":X c #0033CC",
+">X c #3333FF",
+",X c #6633FF",
+"<X c #9933FF",
+"1X c #CC33FF",
+"2X c #FF33FF",
+"3X c #0066FF",
+"4X c #3366FF",
+"5X c #6666CC",
+"6X c #9966FF",
+"7X c #CC66FF",
+"8X c #FF66CC",
+"9X c #0099FF",
+"0X c #3399FF",
+"qX c #6699FF",
+"wX c #9999FF",
+"eX c #CC99FF",
+"rX c #FF99FF",
+"tX c #00CCFF",
+"yX c #33CCFF",
+"uX c #66CCFF",
+"iX c #99CCFF",
+"pX c #CCCCFF",
+"aX c #FFCCFF",
+"sX c #33FFFF",
+"dX c #66FFCC",
+"fX c #99FFFF",
+"gX c #CCFFFF",
+"hX c #FF6666",
+"jX c #66FF66",
+"kX c #FFFF66",
+"lX c #6666FF",
+"zX c #FF66FF",
+"xX c #66FFFF",
+"cX c #A50021",
+"vX c #5F5F5F",
+"bX c #777777",
+"nX c #868686",
+"mX c #969696",
+"MX c #CBCBCB",
+"NX c #B2B2B2",
+"BX c #D7D7D7",
+"VX c #DDDDDD",
+"CX c #E3E3E3",
+"ZX c #EAEAEA",
+"AX c #F1F1F1",
+"SX c #F8F8F8",
+"DX c #FFFBF0",
+"FX c #A0A0A4",
+"GX c #808080",
+"HX c #FF0000",
+"JX c #00FF00",
+"KX c #FFFF00",
+"LX c #0000FF",
+"PX c #FF00FF",
+"IX c #00FFFF",
+"UX c #FFFFFF",
+/* pixels */
+"X X X X X X X k k X X X X X X X ",
+"X X X X X X X k j k X X X X X X ",
+"X X X X X X X k o j k X X X X X ",
+"X X X X X X X k * o j k X X X X ",
+"l k k k k k k k * * . j k X X X ",
+"l @ @ @ @ @ @ @ 4 e e % j k X X ",
+"l O 3 8 e r r r r r r e ; j k X ",
+"l @ e e r r r r r u p a f < j k ",
+"l @ r u p a a a a a f f w j k i ",
+"l O ; ; ; ; ; < a f b 0 j k t : ",
+"l k k k k k k k s j 7 j k q = X ",
+"X $ = = = = = k g 7 j k 9 & X X ",
+"X X X X X X X k 2 j k 6 $ X X X ",
+"X X X X X X X k j k 5 + X X X X ",
+"X X X X X X X k k 1 + X X X X X ",
+"X X X X X X X = , X X X X X X X "
+};
new file mode 100644
--- /dev/null
+++ b/xpm/send16noshadow.xpm
@@ -0,0 +1,278 @@
+/* XPM */
+static char * send16noshadow_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 256 2",
+"   c #ADF7AD",
+".  c #9CFF9C",
+"X  c None",
+"o  c #ADEFAD",
+"O  c #94FF94",
+"+  c #D6CECE",
+"@  c #8CFF8C",
+"#  c #CECECE",
+"$  c #CECEC5",
+"%  c #84FF84",
+"&  c #CEC5C5",
+"*  c #73FF73",
+"=  c #C5C5C5",
+"-  c #6BFF6B",
+";  c #73F773",
+":  c #C5BDBD",
+">  c #6BF76B",
+",  c #BDBDBD",
+"<  c #63F763",
+"1  c #B5B5B5",
+"2  c #52F752",
+"3  c #42FF42",
+"4  c #3AFF3A",
+"5  c #ADADAD",
+"6  c #ADADA5",
+"7  c #4AEF4A",
+"8  c #29FF29",
+"9  c #A5A5A5",
+"0  c #42E642",
+"q  c #9CA59C",
+"w  c #3AE63A",
+"e  c #10FF10",
+"r  c #08FF08",
+"t  c #949C94",
+"y  c #00FF00",
+"u  c #00F700",
+"i  c #8C948C",
+"p  c #00EF00",
+"a  c #08E608",
+"s  c #10DE10",
+"d  c #00E600",
+"f  c #00DE00",
+"g  c #19C519",
+"h  c #00CE00",
+"j  c #00C500",
+"k  c #008C00",
+"l  c #008400",
+"z  c #669900",
+"x  c #999900",
+"c  c #CC9900",
+"v  c #FF9900",
+"b  c #00CC00",
+"n  c #33CC00",
+"m  c #66CC00",
+"M  c #99CC00",
+"N  c #CCCC00",
+"B  c #FFCC00",
+"V  c #66FF00",
+"C  c #99FF00",
+"Z  c #CCFF00",
+"A  c #000033",
+"S  c #330033",
+"D  c #660033",
+"F  c #990033",
+"G  c #CC0033",
+"H  c #FF0033",
+"J  c #003333",
+"K  c #333333",
+"L  c #663333",
+"P  c #993333",
+"I  c #CC3333",
+"U  c #FF3333",
+"Y  c #006633",
+"T  c #336633",
+"R  c #666633",
+"E  c #996633",
+"W  c #CC6633",
+"Q  c #FF6633",
+"!  c #009933",
+"~  c #339933",
+"^  c #669933",
+"/  c #999933",
+"(  c #CC9933",
+")  c #FF9933",
+"_  c #00CC33",
+"`  c #33CC33",
+"'  c #66CC33",
+"]  c #99CC33",
+"[  c #CCCC33",
+"{  c #FFCC33",
+"}  c #33FF33",
+"|  c #66FF33",
+" . c #99FF33",
+".. c #CCFF33",
+"X. c #FFFF33",
+"o. c #000066",
+"O. c #330066",
+"+. c #660066",
+"@. c #990066",
+"#. c #CC0066",
+"$. c #FF0066",
+"%. c #003366",
+"&. c #333366",
+"*. c #663366",
+"=. c #993366",
+"-. c #CC3366",
+";. c #FF3366",
+":. c #006666",
+">. c #336666",
+",. c #666666",
+"<. c #996666",
+"1. c #CC6666",
+"2. c #009966",
+"3. c #339966",
+"4. c #669966",
+"5. c #999966",
+"6. c #CC9966",
+"7. c #FF9966",
+"8. c #00CC66",
+"9. c #33CC66",
+"0. c #99CC66",
+"q. c #CCCC66",
+"w. c #FFCC66",
+"e. c #00FF66",
+"r. c #33FF66",
+"t. c #99FF66",
+"y. c #CCFF66",
+"u. c #FF00CC",
+"i. c #CC00FF",
+"p. c #009999",
+"a. c #993399",
+"s. c #990099",
+"d. c #CC0099",
+"f. c #000099",
+"g. c #333399",
+"h. c #660099",
+"j. c #CC3399",
+"k. c #FF0099",
+"l. c #006699",
+"z. c #336699",
+"x. c #663399",
+"c. c #996699",
+"v. c #CC6699",
+"b. c #FF3399",
+"n. c #339999",
+"m. c #669999",
+"M. c #999999",
+"N. c #CC9999",
+"B. c #FF9999",
+"V. c #00CC99",
+"C. c #33CC99",
+"Z. c #66CC66",
+"A. c #99CC99",
+"S. c #CCCC99",
+"D. c #FFCC99",
+"F. c #00FF99",
+"G. c #33FF99",
+"H. c #66CC99",
+"J. c #99FF99",
+"K. c #CCFF99",
+"L. c #FFFF99",
+"P. c #0000CC",
+"I. c #330099",
+"U. c #6600CC",
+"Y. c #9900CC",
+"T. c #CC00CC",
+"R. c #003399",
+"E. c #3333CC",
+"W. c #6633CC",
+"Q. c #9933CC",
+"!. c #CC33CC",
+"~. c #FF33CC",
+"^. c #0066CC",
+"/. c #3366CC",
+"(. c #666699",
+"). c #9966CC",
+"_. c #CC66CC",
+"`. c #FF6699",
+"'. c #0099CC",
+"]. c #3399CC",
+"[. c #6699CC",
+"{. c #9999CC",
+"}. c #CC99CC",
+"|. c #FF99CC",
+" X c #00CCCC",
+".X c #33CCCC",
+"XX c #66CCCC",
+"oX c #99CCCC",
+"OX c #CCCCCC",
+"+X c #FFCCCC",
+"@X c #00FFCC",
+"#X c #33FFCC",
+"$X c #66FF99",
+"%X c #99FFCC",
+"&X c #CCFFCC",
+"*X c #FFFFCC",
+"=X c #3300CC",
+"-X c #6600FF",
+";X c #9900FF",
+":X c #0033CC",
+">X c #3333FF",
+",X c #6633FF",
+"<X c #9933FF",
+"1X c #CC33FF",
+"2X c #FF33FF",
+"3X c #0066FF",
+"4X c #3366FF",
+"5X c #6666CC",
+"6X c #9966FF",
+"7X c #CC66FF",
+"8X c #FF66CC",
+"9X c #0099FF",
+"0X c #3399FF",
+"qX c #6699FF",
+"wX c #9999FF",
+"eX c #CC99FF",
+"rX c #FF99FF",
+"tX c #00CCFF",
+"yX c #33CCFF",
+"uX c #66CCFF",
+"iX c #99CCFF",
+"pX c #CCCCFF",
+"aX c #FFCCFF",
+"sX c #33FFFF",
+"dX c #66FFCC",
+"fX c #99FFFF",
+"gX c #CCFFFF",
+"hX c #FF6666",
+"jX c #66FF66",
+"kX c #FFFF66",
+"lX c #6666FF",
+"zX c #FF66FF",
+"xX c #66FFFF",
+"cX c #A50021",
+"vX c #5F5F5F",
+"bX c #777777",
+"nX c #868686",
+"mX c #969696",
+"MX c #CBCBCB",
+"NX c #B2B2B2",
+"BX c #D7D7D7",
+"VX c #DDDDDD",
+"CX c #E3E3E3",
+"ZX c #EAEAEA",
+"AX c #F1F1F1",
+"SX c #F8F8F8",
+"DX c #FFFBF0",
+"FX c #A0A0A4",
+"GX c #808080",
+"HX c #FF0000",
+"JX c #00FF00",
+"KX c #FFFF00",
+"LX c #0000FF",
+"PX c #FF00FF",
+"IX c #00FFFF",
+"UX c #FFFFFF",
+/* pixels */
+"X X X X X X X k k X X X X X X X ",
+"X X X X X X X k j k X X X X X X ",
+"X X X X X X X k o j k X X X X X ",
+"X X X X X X X k * o j k X X X X ",
+"l k k k k k k k * * . j k X X X ",
+"l @ @ @ @ @ @ @ 4 e e % j k X X ",
+"l O 3 8 e r r r r r r e ; j k X ",
+"l @ e e r r r r r u p a f < j k ",
+"l @ r u p a a a a a f f w j k X ",
+"l O ; ; ; ; ; < a f b 0 j k X X ",
+"l k k k k k k k s j 7 j k X X X ",
+"X X X X X X X k g 7 j k X X X X ",
+"X X X X X X X k 2 j k X X X X X ",
+"X X X X X X X k j k X X X X X X ",
+"X X X X X X X k k X X X X X X X ",
+"X X X X X X X X X X X X X X X X "
+};
new file mode 100644
--- /dev/null
+++ b/xpm/send20.xpm
@@ -0,0 +1,282 @@
+/* XPM */
+static char * send20_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"20 20 256 2",
+"   c #CEFFCE",
+".  c #BDFFBD",
+"X  c #C5F7C5",
+"o  c #B5FFB5",
+"O  c #ADFFAD",
+"+  c #A5FFA5",
+"@  c #9CFF9C",
+"#  c None",
+"$  c #94FF94",
+"%  c #D6CECE",
+"&  c #8CFF8C",
+"*  c #CECEC5",
+"=  c #84FF84",
+"-  c #94EF94",
+";  c #7BFF7B",
+":  c #CEC5C5",
+">  c #73FF73",
+",  c #C5C5C5",
+"<  c #C5C5BD",
+"1  c #6BFF6B",
+"2  c #BDC5B5",
+"3  c #63FF63",
+"4  c #6BF76B",
+"5  c #BDBDBD",
+"6  c #BDBDB5",
+"7  c #5AFF5A",
+"8  c #63F763",
+"9  c #B5BDB5",
+"0  c #B5BDAD",
+"q  c #52FF52",
+"w  c #BDB5B5",
+"e  c #5AF75A",
+"r  c #B5B5B5",
+"t  c #B5B5AD",
+"y  c #52F752",
+"u  c #42FF42",
+"i  c #52EF52",
+"p  c #ADADAD",
+"a  c #ADADA5",
+"s  c #4AEF4A",
+"d  c #31FF31",
+"f  c #29FF29",
+"g  c #A5A5A5",
+"h  c #21FF21",
+"j  c #5AD65A",
+"k  c #42E642",
+"l  c #94AD94",
+"z  c #4ADE4A",
+"x  c #3AE63A",
+"c  c #5ACE5A",
+"v  c #10FF10",
+"b  c #9C9C9C",
+"n  c #31E631",
+"m  c #08FF08",
+"M  c #949C94",
+"N  c #84A584",
+"B  c #00FF00",
+"V  c #3AD63A",
+"C  c #52C552",
+"Z  c #00F700",
+"A  c #8C948C",
+"S  c #849484",
+"D  c #00EF00",
+"F  c #739C73",
+"G  c #08E608",
+"H  c #4AB54A",
+"J  c #31C531",
+"K  c #00E600",
+"L  c #739473",
+"P  c #00DE00",
+"I  c #63945A",
+"U  c #6B8C6B",
+"Y  c #00D600",
+"T  c #42A542",
+"R  c #638C63",
+"E  c #00CE00",
+"W  c #21B521",
+"Q  c #5A8C5A",
+"!  c #00C500",
+"~  c #528C52",
+"^  c #3A9C3A",
+"/  c #4A8C4A",
+"(  c #00BD00",
+")  c #319431",
+"_  c #219C21",
+"`  c #318C31",
+"'  c #3A843A",
+"]  c #219421",
+"[  c #298C29",
+"{  c #318431",
+"}  c #218C21",
+"|  c #218C19",
+" . c #198C19",
+".. c #218421",
+"X. c #297B29",
+"o. c #198419",
+"O. c #217B21",
+"+. c #108410",
+"@. c #197B19",
+"#. c #CC0066",
+"$. c #FF0066",
+"%. c #003366",
+"&. c #333366",
+"*. c #663366",
+"=. c #993366",
+"-. c #CC3366",
+";. c #FF3366",
+":. c #006666",
+">. c #336666",
+",. c #666666",
+"<. c #996666",
+"1. c #CC6666",
+"2. c #009966",
+"3. c #339966",
+"4. c #669966",
+"5. c #999966",
+"6. c #CC9966",
+"7. c #FF9966",
+"8. c #00CC66",
+"9. c #33CC66",
+"0. c #99CC66",
+"q. c #CCCC66",
+"w. c #FFCC66",
+"e. c #00FF66",
+"r. c #33FF66",
+"t. c #99FF66",
+"y. c #CCFF66",
+"u. c #FF00CC",
+"i. c #CC00FF",
+"p. c #009999",
+"a. c #993399",
+"s. c #990099",
+"d. c #CC0099",
+"f. c #000099",
+"g. c #333399",
+"h. c #660099",
+"j. c #CC3399",
+"k. c #FF0099",
+"l. c #006699",
+"z. c #336699",
+"x. c #663399",
+"c. c #996699",
+"v. c #CC6699",
+"b. c #FF3399",
+"n. c #339999",
+"m. c #669999",
+"M. c #999999",
+"N. c #CC9999",
+"B. c #FF9999",
+"V. c #00CC99",
+"C. c #33CC99",
+"Z. c #66CC66",
+"A. c #99CC99",
+"S. c #CCCC99",
+"D. c #FFCC99",
+"F. c #00FF99",
+"G. c #33FF99",
+"H. c #66CC99",
+"J. c #99FF99",
+"K. c #CCFF99",
+"L. c #FFFF99",
+"P. c #0000CC",
+"I. c #330099",
+"U. c #6600CC",
+"Y. c #9900CC",
+"T. c #CC00CC",
+"R. c #003399",
+"E. c #3333CC",
+"W. c #6633CC",
+"Q. c #9933CC",
+"!. c #CC33CC",
+"~. c #FF33CC",
+"^. c #0066CC",
+"/. c #3366CC",
+"(. c #666699",
+"). c #9966CC",
+"_. c #CC66CC",
+"`. c #FF6699",
+"'. c #0099CC",
+"]. c #3399CC",
+"[. c #6699CC",
+"{. c #9999CC",
+"}. c #CC99CC",
+"|. c #FF99CC",
+" X c #00CCCC",
+".X c #33CCCC",
+"XX c #66CCCC",
+"oX c #99CCCC",
+"OX c #CCCCCC",
+"+X c #FFCCCC",
+"@X c #00FFCC",
+"#X c #33FFCC",
+"$X c #66FF99",
+"%X c #99FFCC",
+"&X c #CCFFCC",
+"*X c #FFFFCC",
+"=X c #3300CC",
+"-X c #6600FF",
+";X c #9900FF",
+":X c #0033CC",
+">X c #3333FF",
+",X c #6633FF",
+"<X c #9933FF",
+"1X c #CC33FF",
+"2X c #FF33FF",
+"3X c #0066FF",
+"4X c #3366FF",
+"5X c #6666CC",
+"6X c #9966FF",
+"7X c #CC66FF",
+"8X c #FF66CC",
+"9X c #0099FF",
+"0X c #3399FF",
+"qX c #6699FF",
+"wX c #9999FF",
+"eX c #CC99FF",
+"rX c #FF99FF",
+"tX c #00CCFF",
+"yX c #33CCFF",
+"uX c #66CCFF",
+"iX c #99CCFF",
+"pX c #CCCCFF",
+"aX c #FFCCFF",
+"sX c #33FFFF",
+"dX c #66FFCC",
+"fX c #99FFFF",
+"gX c #CCFFFF",
+"hX c #FF6666",
+"jX c #66FF66",
+"kX c #FFFF66",
+"lX c #6666FF",
+"zX c #FF66FF",
+"xX c #66FFFF",
+"cX c #A50021",
+"vX c #5F5F5F",
+"bX c #777777",
+"nX c #868686",
+"mX c #969696",
+"MX c #CBCBCB",
+"NX c #B2B2B2",
+"BX c #D7D7D7",
+"VX c #DDDDDD",
+"CX c #E3E3E3",
+"ZX c #EAEAEA",
+"AX c #F1F1F1",
+"SX c #F8F8F8",
+"DX c #FFFBF0",
+"FX c #A0A0A4",
+"GX c #808080",
+"HX c #FF0000",
+"JX c #00FF00",
+"KX c #FFFF00",
+"LX c #0000FF",
+"PX c #FF00FF",
+"IX c #00FFFF",
+"UX c #FFFFFF",
+/* pixels */
+"# # # # # # # # # # # # # # # # # # # # ",
+"# # # # # # # ` 0 # # # # # # # # # # # ",
+"# # # # # # # ..` l # # # # # # # # # # ",
+"# # # # # # # [ X ) N # # # # # # # # # ",
+"# # # # # # # [ &X. ^ F # # # # # # # # ",
+"# # # # # # # } o & o T I : # # # # # # ",
+"` ` ` ` ` ` ` ` + 7 ; + H ~ < # # # # # ",
+"` = = = = = = - @ d v h $ C ' 5 # # # # ",
+"` = = 3 u h v v v m m m v ; c { 6 # # # ",
+"` = f v v m m m m m m Z G G 4 j ..t # # ",
+"` = v m m m Z Z D D G G G P n ; _ R 5 # ",
+"` = m Z G G G G G G G P Y x 4 _ Q g # # ",
+"` = $ $ $ $ $ & e P P E k 8  .U g # # # ",
+"..[ ......[ [ ] e Y ! s i o.L p # # # # ",
+"# # 5 6 6 6 9 ..i ( i z o.S t # # # # # ",
+"# # # # # # # } i i V O.A r # # # # # # ",
+"# # # # # # # } 7 J X.M 6 # # # # # # # ",
+"# # # # # # # | W ' b < # # # # # # # # ",
+"# # # # # # # @.~ g , # # # # # # # # # ",
+"# # # # # # # 6 < , # # # # # # # # # # "
+};