aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2009-11-05 04:41:36 +0000
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2009-11-05 04:41:36 +0000
commite4c05d31778a85014b2a52e2f20753b38dfbf950 (patch)
tree8b82ec196f05e1297dd87e0d857507f8ea1cf975
parentb7362c07ae42ac4282361ee95b82424d502f1b82 (diff)
downloadbitcoin-e4c05d31778a85014b2a52e2f20753b38dfbf950.tar.xz
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
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@32 1a98c847-1fd6-4fd8-948a-caf3550aa51b
-rw-r--r--build-unix.txt73
-rw-r--r--build.txt88
-rw-r--r--db.cpp10
-rw-r--r--headers.h38
-rw-r--r--irc.cpp16
-rw-r--r--irc.h4
-rw-r--r--main.cpp68
-rw-r--r--main.h8
-rw-r--r--makefile.unix86
-rw-r--r--net.cpp177
-rw-r--r--net.h3
-rw-r--r--ui.cpp103
-rw-r--r--uibase.cpp10
-rw-r--r--uiproject.fbp10
-rw-r--r--util.cpp8
-rw-r--r--util.h40
-rw-r--r--xpm/addressbook16.xpm278
-rw-r--r--xpm/addressbook20.xpm282
-rw-r--r--xpm/bitcoin.xpm304
-rw-r--r--xpm/check.xpm41
-rw-r--r--xpm/send16.xpm278
-rw-r--r--xpm/send16noshadow.xpm278
-rw-r--r--xpm/send20.xpm282
23 files changed, 2184 insertions, 301 deletions
diff --git a/build-unix.txt b/build-unix.txt
new file mode 100644
index 0000000000..6b29e1e5c4
--- /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
diff --git a/build.txt b/build.txt
deleted file mode 100644
index 4368af855a..0000000000
--- 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.
diff --git a/db.cpp b/db.cpp
index f9e25834d0..b702b0cbac 100644
--- a/db.cpp
+++ b/db.cpp
@@ -62,9 +62,9 @@ CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
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::WriteAddress(const CAddress& addr)
bool CAddrDB::LoadAddresses()
{
- CRITICAL_BLOCK(cs_mapIRCAddresses)
CRITICAL_BLOCK(cs_mapAddresses)
{
// Load user provided addresses
@@ -425,10 +424,7 @@ bool CAddrDB::LoadAddresses()
{
CAddress addr(psz, NODE_NETWORK);
if (addr.IsValid())
- {
AddAddress(*this, addr);
- mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
- }
}
}
catch (...) { }
@@ -678,7 +674,7 @@ void ThreadFlushWalletDB(void* parg)
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);
diff --git a/headers.h b/headers.h
index f00b7dde05..c7f3cd8514 100644
--- 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 @@ using namespace boost;
#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"
diff --git a/irc.cpp b/irc.cpp
index f839dc5224..4d4ed0f414 100644
--- 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 @@ void ThreadIRCSeed(void* parg)
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
{
diff --git a/irc.h b/irc.h
index 91c3ffe686..c69fd9ee97 100644
--- 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;
diff --git a/main.cpp b/main.cpp
index ade3b51c77..2119495e64 100644
--- a/main.cpp
+++ b/main.cpp
@@ -100,13 +100,10 @@ bool AddToWallet(const CWalletTx& wtxIn)
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 @@ bool AddToWallet(const CWalletTx& wtxIn)
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 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
}
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 @@ bool CBlock::AcceptBlock()
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 @@ FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszM
{
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 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
+
if (strCommand == "version")
{
// Each connection can only send one version message
@@ -1765,6 +1765,10 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
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 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
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 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
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 @@ bool SendMessages(CNode* pto)
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 @@ void GenerateBitcoins(bool fGenerate)
}
if (fGenerateBitcoins)
{
- int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS"));
+ int nProcessors = wxThread::GetCPUCount();
printf("%d processors\n", nProcessors);
if (nProcessors < 1)
nProcessors = 1;
diff --git a/main.h b/main.h
index a0258cf2ce..6d8f0ed87c 100644
--- a/main.h
+++ b/main.h
@@ -968,6 +968,14 @@ public:
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;
}
diff --git a/makefile.unix b/makefile.unix
new file mode 100644
index 0000000000..c62efc008f
--- /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
diff --git a/net.cpp b/net.cpp
index 8ccf48b819..c14061e7d3 100644
--- 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 GetMyExternalIP(unsigned int& ipRet)
-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 @@ bool AddAddress(CAddrDB& addrdb, const CAddress& addr)
}
else
{
+ bool fUpdated = false;
CAddress& addrFound = (*it).second;
if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
{
// Services have been added
addrFound.nServices |= addr.nServices;
- addrdb.WriteAddress(addrFound);
- return true;
+ 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;
}
- else if (addrFound.nTime < GetAdjustedTime() - 24 * 60 * 60)
+ if (fUpdated)
+ addrdb.WriteAddress(addrFound);
+ }
+ }
+ 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 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
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 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
else
{
CRITICAL_BLOCK(cs_mapAddresses)
- mapAddresses[addrConnect.GetKey()].nLastFailed = GetTime();
+ mapAddresses[addrConnect.GetKey()].nLastFailed = GetAdjustedTime();
return NULL;
}
}
@@ -432,7 +461,7 @@ void CNode::DoDisconnect()
// 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 @@ void ThreadSocketHandler2(void* parg)
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 @@ void ThreadSocketHandler2(void* parg)
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 @@ void ThreadOpenConnections2(void* parg)
}
// 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 @@ void ThreadOpenConnections2(void* parg)
vnThreadsRunning[1]++;
CheckForShutdown(1);
-
//
- // 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.
+ // Choose an address to connect to based on most recently seen
//
+ CAddress addrConnect;
+ int64 nBestTime = 0;
+ int64 nDelay = ((60 * 60) << vNodes.size());
+ if (vNodes.size() >= 3)
+ nDelay *= 4;
+ if (nGotIRCAddresses > 0)
+ nDelay *= 100;
+
+ // 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);
- // 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;
-
- // 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())
- continue;
- if (fIRCOnly && !mapIRCAddresses.count(item.first))
+ if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip))
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);
- }
- }
- if (vIPC.empty())
- continue;
-
- // Choose a random class C
- unsigned int ipC = vIPC[GetRand(vIPC.size())];
+ // Limit retry frequency
+ if (GetAdjustedTime() < addr.nLastFailed + nDelay)
+ continue;
- // 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;
- }
+ // Try again only after all addresses had a first attempt
+ int64 nTime = addr.nTime;
+ if (addr.nLastFailed > addr.nTime)
+ nTime -= 365 * 24 * 60 * 60;
- 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;
+ // Randomize the order a little, putting the standard port first
+ nTime += GetRand(1 * 60 * 60);
+ if (addr.port != DEFAULT_PORT)
+ nTime -= 1 * 60 * 60;
- int64 nRandomizer = (addr.nLastFailed * addr.ip * 7777U) % 20000;
- if (GetTime() - addr.nLastFailed > nDelay * nRandomizer / 10000)
- mapIP[addr.ip].push_back(addr);
+ if (nTime > nBestTime)
+ {
+ nBestTime = nTime;
+ addrConnect = 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 @@ bool StartNode(string& strError)
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 @@ bool StartNode(string& strError)
printf("%s\n", strError.c_str());
return false;
}
+#endif
// Get local host ip
char pszHostName[255];
@@ -1029,10 +1024,14 @@ bool StartNode(string& strError)
}
// 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 @@ bool StartNode(string& strError)
// 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 @@ bool StopNode()
Sleep(50);
// Sockets shutdown
+#ifdef __WXMSW__
WSACleanup();
+#endif
return true;
}
diff --git a/net.h b/net.h
index 7716426f04..275a4cb88b 100644
--- a/net.h
+++ b/net.h
@@ -22,7 +22,8 @@ enum
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);
diff --git a/ui.cpp b/ui.cpp
index 9185b8159f..212548199f 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -260,7 +260,8 @@ void AddPendingReplyEvent3(void* pevthandler, CDataStream& vRecv)
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 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
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 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
{
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 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
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 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
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 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
}
- if (fUseProxy != m_checkBoxUseProxy->GetValue())
- {
- fUseProxy = m_checkBoxUseProxy->GetValue();
- walletdb.WriteSetting("fUseProxy", fUseProxy);
- }
+ fUseProxy = m_checkBoxUseProxy->GetValue();
+ walletdb.WriteSetting("fUseProxy", fUseProxy);
- if (addrProxy != GetProxyAddr())
- {
- addrProxy = GetProxyAddr();
- walletdb.WriteSetting("addrProxy", addrProxy);
- }
+ addrProxy = GetProxyAddr();
+ walletdb.WriteSetting("addrProxy", addrProxy);
}
@@ -1608,10 +1593,8 @@ CSendDialog::CSendDialog(wxWindow* parent, const wxString& strAddress) : CSendDi
//// 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 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
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 @@ bool CMyApp::OnInit2()
_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 @@ bool CMyApp::OnInit2()
" -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 @@ bool CMyApp::OnInit2()
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 @@ bool CMyApp::OnInit2()
SetForegroundWindow(hwndPrev);
return false;
}
+#endif
if (GetTime() > nStart + 60)
return false;
@@ -3421,7 +3404,7 @@ bool CMyApp::OnInit2()
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 @@ bool CMyApp::OnInit2()
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 @@ bool CMyApp::OnInit2()
OnExit();
return false;
}
- CWalletDB walletdb;
- walletdb.WriteSetting("fUseProxy", fUseProxy);
- walletdb.WriteSetting("addrProxy", addrProxy);
}
if (mapArgs.count("-addnode"))
@@ -3522,6 +3526,7 @@ bool CMyApp::OnInit2()
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 @@ bool CMyApp::OnInit2()
//
// 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 @@ void CMyApp::OnFatalException()
-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,7 +3747,10 @@ void SetStartOnSystemStartup(bool fAutoStart)
CoUninitialize();
}
}
-
+#else
+bool GetStartOnSystemStartup() { return false; }
+void SetStartOnSystemStartup(bool fAutoStart) { }
+#endif
diff --git a/uibase.cpp b/uibase.cpp
index b03e578bd8..bb564e9960 100644
--- 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 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
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 @@ CSendDialogBase::CSendDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
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 );
diff --git a/uiproject.fbp b/uiproject.fbp
index 313e5aa6cc..7bce7349f5 100644
--- 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>
diff --git a/util.cpp b/util.cpp
index 23b59f11f7..d2e624d676 100644
--- a/util.cpp
+++ b/util.cpp
@@ -38,8 +38,10 @@ public:
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 @@ void ParseParameters(int argc, char* argv[])
pszValue = strchr(psz, '=');
*pszValue++ = '\0';
}
- strlwr(psz);
#ifdef __WXMSW__
+ _strlwr(psz);
if (psz[0] == '/')
psz[0] = '-';
#endif
@@ -343,9 +345,13 @@ void ParseParameters(int argc, char* argv[])
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);
diff --git a/util.h b/util.h
index 822a049ce7..3bc7c798a5 100644
--- a/util.h
+++ b/util.h
@@ -55,9 +55,34 @@ inline T& REF(const T& val)
}
#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 @@ public:
protected:
wxMutex mutex;
public:
- explicit CCriticalSection() { }
+ explicit CCriticalSection() : mutex(wxMUTEX_RECURSIVE) { }
~CCriticalSection() { }
void Enter() { mutex.Lock(); }
void Leave() { mutex.Unlock(); }
@@ -183,7 +208,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
// 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 @@ inline int64 GetTimeMillis()
return wxGetLocalTimeMillis().GetValue();
}
-#ifndef __WXMSW__
-inline void Sleep(unsigned int nMilliseconds)
-{
- wxMilliSleep(nMilliseconds);
-}
-#endif
-
diff --git a/xpm/addressbook16.xpm b/xpm/addressbook16.xpm
new file mode 100644
index 0000000000..471f700c70
--- /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 : ",
+": : : : : : : : : : : : : : : : "
+};
diff --git a/xpm/addressbook20.xpm b/xpm/addressbook20.xpm
new file mode 100644
index 0000000000..48df12d801
--- /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.> > ",
+"> > > > > > > > > > > > > > > > > > > > ",
+"> > > > > > > > > > > > > > > > > > > > "
+};
diff --git a/xpm/bitcoin.xpm b/xpm/bitcoin.xpm
new file mode 100644
index 0000000000..166d5aa6e4
--- /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"
+};
diff --git a/xpm/check.xpm b/xpm/check.xpm
new file mode 100644
index 0000000000..8f0b9d28ec
--- /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"
+};
diff --git a/xpm/send16.xpm b/xpm/send16.xpm
new file mode 100644
index 0000000000..1eeceb4ec7
--- /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 "
+};
diff --git a/xpm/send16noshadow.xpm b/xpm/send16noshadow.xpm
new file mode 100644
index 0000000000..d1b482ef97
--- /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 "
+};
diff --git a/xpm/send20.xpm b/xpm/send20.xpm
new file mode 100644
index 0000000000..597ea146d1
--- /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 < , # # # # # # # # # # "
+};