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
This commit is contained in:
s_nakamoto 2009-11-05 04:41:36 +00:00
parent b7362c07ae
commit e4c05d3177
23 changed files with 2187 additions and 304 deletions

73
build-unix.txt Normal file
View File

@ -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

View File

@ -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.

10
db.cpp
View File

@ -62,9 +62,9 @@ CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
if (fShutdown) if (fShutdown)
return; return;
string strDataDir = GetDataDir(); string strDataDir = GetDataDir();
string strLogDir = strDataDir + "\\database"; string strLogDir = strDataDir + "/database";
_mkdir(strLogDir.c_str()); _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()); printf("dbenv.open strLogDir=%s strErrorFile=%s\n", strLogDir.c_str(), strErrorFile.c_str());
dbenv.set_lg_dir(strLogDir.c_str()); dbenv.set_lg_dir(strLogDir.c_str());
@ -411,7 +411,6 @@ bool CAddrDB::WriteAddress(const CAddress& addr)
bool CAddrDB::LoadAddresses() bool CAddrDB::LoadAddresses()
{ {
CRITICAL_BLOCK(cs_mapIRCAddresses)
CRITICAL_BLOCK(cs_mapAddresses) CRITICAL_BLOCK(cs_mapAddresses)
{ {
// Load user provided addresses // Load user provided addresses
@ -425,10 +424,7 @@ bool CAddrDB::LoadAddresses()
{ {
CAddress addr(psz, NODE_NETWORK); CAddress addr(psz, NODE_NETWORK);
if (addr.IsValid()) if (addr.IsValid())
{
AddAddress(*this, addr); AddAddress(*this, addr);
mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
}
} }
} }
catch (...) { } catch (...) { }
@ -678,7 +674,7 @@ void ThreadFlushWalletDB(void* parg)
if (nRefCount == 0 && !fShutdown) if (nRefCount == 0 && !fShutdown)
{ {
// Flush wallet.dat so it's self contained // Flush wallet.dat so it's self contained
nLastFlushed == nWalletDBUpdated; nLastFlushed = nWalletDBUpdated;
int64 nStart = GetTimeMillis(); int64 nStart = GetTimeMillis();
dbenv.txn_checkpoint(0, 0, 0); dbenv.txn_checkpoint(0, 0, 0);
dbenv.lsn_reset(strFile.c_str(), 0); dbenv.lsn_reset(strFile.c_str(), 0);

View File

@ -17,16 +17,18 @@
#endif #endif
#define _WIN32_IE 0x0400 #define _WIN32_IE 0x0400
#define WIN32_LEAN_AND_MEAN 1 #define WIN32_LEAN_AND_MEAN 1
#define __STDC_LIMIT_MACROS // to enable UINT64_MAX from stdint.h
#include <wx/wx.h> #include <wx/wx.h>
#include <wx/clipbrd.h> #include <wx/clipbrd.h>
#include <wx/snglinst.h> #include <wx/snglinst.h>
#include <wx/taskbar.h> #include <wx/taskbar.h>
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
#include <wx/utils.h>
#include <openssl/ecdsa.h> #include <openssl/ecdsa.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <openssl/ripemd.h> #include <openssl/ripemd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
@ -50,22 +52,28 @@
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp> #include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp> #include <boost/tuple/tuple_io.hpp>
#include <boost/array.hpp> #include <boost/array.hpp>
#ifdef __WXMSW__ #ifdef __WXMSW__
#include <windows.h> #include <windows.h>
#include <winsock2.h> #include <winsock2.h>
#include <mswsock.h> #include <mswsock.h>
#include <shlobj.h> #include <shlobj.h>
#include <shlwapi.h> #include <shlwapi.h>
#include <io.h> #include <io.h>
#include <process.h> #include <process.h>
#else #else
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <unistd.h> #include <netdb.h>
#endif #include <unistd.h>
#include <errno.h>
#include <boost/filesystem.hpp>
#include <boost/thread/thread.hpp>
#include <boost/algorithm/string.hpp>
#endif
#pragma hdrstop #pragma hdrstop
using namespace std; using namespace std;
@ -88,3 +96,11 @@ using namespace boost;
#include "market.h" #include "market.h"
#include "uibase.h" #include "uibase.h"
#include "ui.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"

16
irc.cpp
View File

@ -4,10 +4,7 @@
#include "headers.h" #include "headers.h"
int nGotIRCAddresses = 0;
map<vector<unsigned char>, CAddress> mapIRCAddresses;
CCriticalSection cs_mapIRCAddresses;
@ -259,16 +256,7 @@ void ThreadIRCSeed(void* parg)
CAddrDB addrdb; CAddrDB addrdb;
if (AddAddress(addrdb, addr)) if (AddAddress(addrdb, addr))
printf("IRC got new address\n"); printf("IRC got new address\n");
else nGotIRCAddresses++;
{
// 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));
} }
else else
{ {

4
irc.h
View File

@ -4,7 +4,5 @@
extern bool RecvLine(SOCKET hSocket, string& strLine); extern bool RecvLine(SOCKET hSocket, string& strLine);
extern void ThreadIRCSeed(void* parg); extern void ThreadIRCSeed(void* parg);
extern bool fRestartIRCSeed;
extern map<vector<unsigned char>, CAddress> mapIRCAddresses; extern int nGotIRCAddresses;
extern CCriticalSection cs_mapIRCAddresses;

View File

@ -100,13 +100,10 @@ bool AddToWallet(const CWalletTx& wtxIn)
if (fInsertedNew) if (fInsertedNew)
wtx.nTimeReceived = GetAdjustedTime(); wtx.nTimeReceived = GetAdjustedTime();
//// debug print bool fUpdated = false;
printf("AddToWallet %s %s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), fInsertedNew ? "new" : "update");
if (!fInsertedNew) if (!fInsertedNew)
{ {
// Merge // Merge
bool fUpdated = false;
if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock) if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
{ {
wtx.hashBlock = wtxIn.hashBlock; wtx.hashBlock = wtxIn.hashBlock;
@ -128,13 +125,15 @@ bool AddToWallet(const CWalletTx& wtxIn)
wtx.fSpent = wtxIn.fSpent; wtx.fSpent = wtxIn.fSpent;
fUpdated = true; 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 // Write to disk
if (!wtx.WriteToDisk()) if (fInsertedNew || fUpdated)
return false; if (!wtx.WriteToDisk())
return false;
// Notify UI // Notify UI
vWalletUpdated.push_back(hash); 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()) 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 prev is coinbase, check that it's matured
if (txPrev.IsCoinBase()) if (txPrev.IsCoinBase())
@ -1217,7 +1216,7 @@ bool CBlock::AcceptBlock()
if (nTime <= pindexPrev->GetMedianTimePast()) if (nTime <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early"); 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 if (nBestHeight > 31000) // 25620 + 5320
foreach(const CTransaction& tx, vtx) foreach(const CTransaction& tx, vtx)
if (!tx.IsFinal(nTime)) if (!tx.IsFinal(nTime))
@ -1384,7 +1383,7 @@ FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszM
{ {
if (nFile == -1) if (nFile == -1)
return NULL; 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) if (!file)
return NULL; return NULL;
if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w')) if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
@ -1718,6 +1717,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (strCommand == "version") if (strCommand == "version")
{ {
// Each connection can only send one version message // Each connection can only send one version message
@ -1765,6 +1765,10 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->fSuccessfullyConnected = true; pfrom->fSuccessfullyConnected = true;
// Update the last seen time
if (pfrom->fNetworkNode)
AddressCurrentlyConnected(pfrom->addr);
printf("version message: version %d\n", pfrom->nVersion); printf("version message: version %d\n", pfrom->nVersion);
} }
@ -1781,23 +1785,16 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vector<CAddress> vAddr; vector<CAddress> vAddr;
vRecv >> 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 // Store the new addresses
CAddrDB addrdb; CAddrDB addrdb;
foreach(const CAddress& addr, vAddr) foreach(CAddress& addr, vAddr)
{ {
if (fShutdown) if (fShutdown)
return true; return true;
AddAddress(addrdb, addr); addr.nTime = GetAdjustedTime();
if (pfrom->fGetAddr)
addr.nTime -= 5 * 24 * 60 * 60;
AddAddress(addrdb, addr, false);
pfrom->AddAddressKnown(addr); pfrom->AddAddressKnown(addr);
if (!pfrom->fGetAddr && addr.IsRoutable()) if (!pfrom->fGetAddr && addr.IsRoutable())
{ {
@ -1816,6 +1813,10 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vector<CInv> vInv; vector<CInv> vInv;
vRecv >> vInv; vRecv >> vInv;
// Update the last seen time for this node's address
if (pfrom->fNetworkNode)
AddressCurrentlyConnected(pfrom->addr);
CTxDB txdb("r"); CTxDB txdb("r");
foreach(const CInv& inv, vInv) foreach(const CInv& inv, vInv)
{ {
@ -2099,6 +2100,25 @@ bool SendMessages(CNode* pto)
if (pto->nVersion == 0) if (pto->nVersion == 0)
return true; 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 // Message: addr
@ -2187,7 +2207,7 @@ void GenerateBitcoins(bool fGenerate)
} }
if (fGenerateBitcoins) if (fGenerateBitcoins)
{ {
int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS")); int nProcessors = wxThread::GetCPUCount();
printf("%d processors\n", nProcessors); printf("%d processors\n", nProcessors);
if (nProcessors < 1) if (nProcessors < 1)
nProcessors = 1; nProcessors = 1;

8
main.h
View File

@ -968,6 +968,14 @@ public:
return error("CBlock::WriteToDisk() : ftell failed"); return error("CBlock::WriteToDisk() : ftell failed");
fileout << *this; 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; return true;
} }

86
makefile.unix Normal file
View File

@ -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

183
net.cpp
View File

@ -3,7 +3,6 @@
// file license.txt or http://www.opensource.org/licenses/mit-license.php. // file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h" #include "headers.h"
#include <winsock2.h>
void ThreadMessageHandler2(void* parg); void ThreadMessageHandler2(void* parg);
void ThreadSocketHandler2(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()) if (!addr.IsRoutable())
return false; return false;
if (addr.ip == addrLocalHost.ip) if (addr.ip == addrLocalHost.ip)
return false; return false;
if (fCurrentlyOnline)
addr.nTime = GetAdjustedTime();
CRITICAL_BLOCK(cs_mapAddresses) CRITICAL_BLOCK(cs_mapAddresses)
{ {
map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey()); map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
@ -219,26 +220,49 @@ bool AddAddress(CAddrDB& addrdb, const CAddress& addr)
} }
else else
{ {
bool fUpdated = false;
CAddress& addrFound = (*it).second; CAddress& addrFound = (*it).second;
if ((addrFound.nServices | addr.nServices) != addrFound.nServices) if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
{ {
// Services have been added // Services have been added
addrFound.nServices |= addr.nServices; addrFound.nServices |= addr.nServices;
addrdb.WriteAddress(addrFound); fUpdated = true;
return true;
} }
else if (addrFound.nTime < GetAdjustedTime() - 24 * 60 * 60) int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
if (addrFound.nTime < addr.nTime - nUpdateInterval)
{ {
// Periodically update most recently seen time // Periodically update most recently seen time
addrFound.nTime = GetAdjustedTime(); addrFound.nTime = addr.nTime;
addrdb.WriteAddress(addrFound); fUpdated = true;
return false;
} }
if (fUpdated)
addrdb.WriteAddress(addrFound);
} }
} }
return false; 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);
}
}
}
}
@ -398,9 +422,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
printf("connected %s\n", addrConnect.ToStringLog().c_str()); printf("connected %s\n", addrConnect.ToStringLog().c_str());
// Set to nonblocking // Set to nonblocking
u_long nOne = 1; #ifdef __WXMSW__
u_long nOne = 1;
if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError()); 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 // Add node
CNode* pnode = new CNode(hSocket, addrConnect, false); CNode* pnode = new CNode(hSocket, addrConnect, false);
@ -418,7 +447,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
else else
{ {
CRITICAL_BLOCK(cs_mapAddresses) CRITICAL_BLOCK(cs_mapAddresses)
mapAddresses[addrConnect.GetKey()].nLastFailed = GetTime(); mapAddresses[addrConnect.GetKey()].nLastFailed = GetAdjustedTime();
return NULL; return NULL;
} }
} }
@ -432,7 +461,7 @@ void CNode::DoDisconnect()
// If outbound and never got version message, mark address as failed // If outbound and never got version message, mark address as failed
if (!fInbound && !fSuccessfullyConnected) if (!fInbound && !fSuccessfullyConnected)
CRITICAL_BLOCK(cs_mapAddresses) 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 // 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. // 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_sec = 0;
timeout.tv_usec = 50000; // frequency to poll pnode->vSend timeout.tv_usec = 50000; // frequency to poll pnode->vSend
struct fd_set fdsetRecv; fd_set fdsetRecv;
struct fd_set fdsetSend; fd_set fdsetSend;
FD_ZERO(&fdsetRecv); FD_ZERO(&fdsetRecv);
FD_ZERO(&fdsetSend); FD_ZERO(&fdsetSend);
SOCKET hSocketMax = 0; SOCKET hSocketMax = 0;
@ -599,7 +628,11 @@ void ThreadSocketHandler2(void* parg)
if (FD_ISSET(hListenSocket, &fdsetRecv)) if (FD_ISSET(hListenSocket, &fdsetRecv))
{ {
struct sockaddr_in sockaddr; struct sockaddr_in sockaddr;
#ifdef __WXMSW__
int len = sizeof(sockaddr); int len = sizeof(sockaddr);
#else
socklen_t len = sizeof(sockaddr);
#endif
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
CAddress addr(sockaddr); CAddress addr(sockaddr);
if (hSocket == INVALID_SOCKET) if (hSocket == INVALID_SOCKET)
@ -765,14 +798,12 @@ void ThreadOpenConnections2(void* parg)
} }
// Initiate network connections // Initiate network connections
int nTry = 0;
bool fIRCOnly = false;
const int nMaxConnections = 15;
loop loop
{ {
// Wait // Wait
vnThreadsRunning[1]--; vnThreadsRunning[1]--;
Sleep(500); Sleep(500);
const int nMaxConnections = 15;
while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size()) while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
{ {
CheckForShutdown(1); CheckForShutdown(1);
@ -781,93 +812,55 @@ void ThreadOpenConnections2(void* parg)
vnThreadsRunning[1]++; vnThreadsRunning[1]++;
CheckForShutdown(1); CheckForShutdown(1);
// //
// The IP selection process is designed to limit vulnerability to address flooding. // Choose an address to connect to based on most recently seen
// 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 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect
fIRCOnly = !fIRCOnly; set<unsigned int> setConnected;
if (mapIRCAddresses.empty()) CRITICAL_BLOCK(cs_vNodes)
fIRCOnly = false; foreach(CNode* pnode, vNodes)
else if (nTry++ < 30 && vNodes.size() < nMaxConnections/2) setConnected.insert(pnode->addr.ip);
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) CRITICAL_BLOCK(cs_mapAddresses)
{ {
vIPC.reserve(mapAddresses.size());
unsigned int nPrev = 0;
foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses) foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
{ {
const CAddress& addr = item.second; const CAddress& addr = item.second;
if (!addr.IsIPv4()) if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip))
continue;
if (fIRCOnly && !mapIRCAddresses.count(item.first))
continue; continue;
// Taking advantage of mapAddresses being in sorted order, // Limit retry frequency
// with IPs of the same class C grouped together. if (GetAdjustedTime() < addr.nLastFailed + nDelay)
unsigned int ipC = addr.ip & nIPCMask; continue;
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 if (addrConnect.IsValid())
unsigned int ipC = vIPC[GetRand(vIPC.size())]; OpenNetworkConnection(addrConnect);
// 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;
} }
} }
@ -989,6 +982,7 @@ bool StartNode(string& strError)
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices)); pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
strError = ""; strError = "";
#ifdef __WXMSW__
// Sockets startup // Sockets startup
WSADATA wsadata; WSADATA wsadata;
int ret = WSAStartup(MAKEWORD(2,2), &wsadata); int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
@ -998,6 +992,7 @@ bool StartNode(string& strError)
printf("%s\n", strError.c_str()); printf("%s\n", strError.c_str());
return false; return false;
} }
#endif
// Get local host ip // Get local host ip
char pszHostName[255]; char pszHostName[255];
@ -1029,10 +1024,14 @@ bool StartNode(string& strError)
} }
// Set to nonblocking, incoming connections will also inherit this // Set to nonblocking, incoming connections will also inherit this
#ifdef __WXMSW__
u_long nOne = 1; u_long nOne = 1;
if (ioctlsocket(hListenSocket, FIONBIO, &nOne) == SOCKET_ERROR) 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()); printf("%s\n", strError.c_str());
return false; return false;
} }
@ -1041,7 +1040,7 @@ bool StartNode(string& strError)
// IP address, and port for the socket that is being bound // IP address, and port for the socket that is being bound
int nRetryLimit = 15; int nRetryLimit = 15;
struct sockaddr_in sockaddr = addrLocalHost.GetSockAddr(); 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(); int nErr = WSAGetLastError();
if (nErr == WSAEADDRINUSE) if (nErr == WSAEADDRINUSE)
@ -1131,7 +1130,9 @@ bool StopNode()
Sleep(50); Sleep(50);
// Sockets shutdown // Sockets shutdown
#ifdef __WXMSW__
WSACleanup(); WSACleanup();
#endif
return true; return true;
} }

3
net.h
View File

@ -22,7 +22,8 @@ enum
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet); bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
bool GetMyExternalIP(unsigned int& ipRet); 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* FindNode(unsigned int ip);
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0); CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1); void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);

103
ui.cpp
View File

@ -260,7 +260,8 @@ void AddPendingReplyEvent3(void* pevthandler, CDataStream& vRecv)
CDataStream GetStreamFromEvent(const wxCommandEvent& event) CDataStream GetStreamFromEvent(const wxCommandEvent& event)
{ {
wxString strData = event.GetString(); 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)); SetIcon(wxICON(bitcoin));
ptaskbaricon = new CMyTaskBarIcon(); 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 // Init column headers
int nDateWidth = DateTimeStr(1229413914).size() * 6 + 8; int nDateWidth = DateTimeStr(1229413914).size() * 6 + 8;
if (!strstr(DateTimeStr(1229413914).c_str(), "2008")) if (!strstr(DateTimeStr(1229413914).c_str(), "2008"))
@ -909,15 +896,17 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
{ {
TRY_CRITICAL_BLOCK(cs_mapWallet) TRY_CRITICAL_BLOCK(cs_mapWallet)
{ {
bool fInserted = false; string strTop;
if (m_listCtrl->GetItemCount())
strTop = (string)m_listCtrl->GetItemText(0);
foreach(uint256 hash, vWalletUpdated) foreach(uint256 hash, vWalletUpdated)
{ {
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash); map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
if (mi != mapWallet.end()) if (mi != mapWallet.end())
fInserted |= InsertTransaction((*mi).second, false); InsertTransaction((*mi).second, false);
} }
vWalletUpdated.clear(); vWalletUpdated.clear();
if (fInserted) if (m_listCtrl->GetItemCount() && strTop != (string)m_listCtrl->GetItemText(0))
m_listCtrl->ScrollList(0, INT_MAX); 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); string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);
m_statusBar->SetStatusText(strStatus, 2); m_statusBar->SetStatusText(strStatus, 2);
#ifdef __WXMSW__
m_listCtrl->OnPaint(event); m_listCtrl->OnPaint(event);
#endif
} }
@ -1407,7 +1398,7 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
m_checkBoxLimitProcessors->SetValue(fLimitProcessors); m_checkBoxLimitProcessors->SetValue(fLimitProcessors);
m_spinCtrlLimitProcessors->Enable(fLimitProcessors); m_spinCtrlLimitProcessors->Enable(fLimitProcessors);
m_spinCtrlLimitProcessors->SetValue(nLimitProcessors); m_spinCtrlLimitProcessors->SetValue(nLimitProcessors);
int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS")); int nProcessors = wxThread::GetCPUCount();
if (nProcessors < 1) if (nProcessors < 1)
nProcessors = 999; nProcessors = 999;
m_spinCtrlLimitProcessors->SetRange(1, nProcessors); m_spinCtrlLimitProcessors->SetRange(1, nProcessors);
@ -1549,17 +1540,11 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose); 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 //// todo: should add a display of your balance for convenience
// Set Icon // Set Icon
wxBitmap bmpSend(wxT("send16"), wxBITMAP_TYPE_RESOURCE);
bmpSend.SetMask(new wxMask(wxBitmap(wxT("send16masknoshadow"), wxBITMAP_TYPE_RESOURCE)));
wxIcon iconSend; wxIcon iconSend;
iconSend.CopyFromBitmap(bmpSend); iconSend.CopyFromBitmap(wxBitmap(send16noshadow_xpm));
SetIcon(iconSend); SetIcon(iconSend);
wxCommandEvent event; wxCommandEvent event;
@ -2231,10 +2214,8 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
m_listCtrl->SetFocus(); m_listCtrl->SetFocus();
// Set Icon // Set Icon
wxBitmap bmpAddressBook(wxT("addressbook16"), wxBITMAP_TYPE_RESOURCE);
bmpAddressBook.SetMask(new wxMask(wxBitmap(wxT("addressbook16mask"), wxBITMAP_TYPE_RESOURCE)));
wxIcon iconAddressBook; wxIcon iconAddressBook;
iconAddressBook.CopyFromBitmap(bmpAddressBook); iconAddressBook.CopyFromBitmap(wxBitmap(addressbook16_xpm));
SetIcon(iconAddressBook); SetIcon(iconAddressBook);
// Fill listctrl with address book data // Fill listctrl with address book data
@ -3345,7 +3326,7 @@ bool CMyApp::OnInit2()
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)); _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
#endif #endif
#ifdef __WXDEBUG__ #if defined(__WXMSW__) && defined(__WXDEBUG__)
// Disable malfunctioning wxWidgets debug assertion // Disable malfunctioning wxWidgets debug assertion
g_isPainting = 10000; g_isPainting = 10000;
#endif #endif
@ -3362,8 +3343,7 @@ bool CMyApp::OnInit2()
" -gen=0\t\t Don't generate coins\n" " -gen=0\t\t Don't generate coins\n"
" -min\t\t Start minimized\n" " -min\t\t Start minimized\n"
" -datadir=<dir>\t Specify data directory\n" " -datadir=<dir>\t Specify data directory\n"
" -proxy=<ip:port>\t Connect through socks4 proxy,\n" " -proxy=<ip:port>\t Connect through socks4 proxy\n"
" \t\t e.g. -proxy=127.0.0.1:9050 to use TOR\n"
" -addnode=<ip>\t Add a node to connect to\n" " -addnode=<ip>\t Add a node to connect to\n"
" -connect=<ip>\t Connect only to the specified node\n" " -connect=<ip>\t Connect only to the specified node\n"
" -?\t\t This help message\n"; " -?\t\t This help message\n";
@ -3386,6 +3366,8 @@ bool CMyApp::OnInit2()
unsigned int nStart = GetTime(); unsigned int nStart = GetTime();
loop loop
{ {
// TODO: find out how to do this in Linux, or replace with wxWidgets commands
#ifdef __WXMSW__
// Show the previous instance and exit // Show the previous instance and exit
HWND hwndPrev = FindWindow("wxWindowClassNR", "Bitcoin"); HWND hwndPrev = FindWindow("wxWindowClassNR", "Bitcoin");
if (hwndPrev) if (hwndPrev)
@ -3395,6 +3377,7 @@ bool CMyApp::OnInit2()
SetForegroundWindow(hwndPrev); SetForegroundWindow(hwndPrev);
return false; return false;
} }
#endif
if (GetTime() > nStart + 60) if (GetTime() > nStart + 60)
return false; return false;
@ -3421,7 +3404,7 @@ bool CMyApp::OnInit2()
fPrintToDebugger = true; fPrintToDebugger = true;
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); 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")) if (mapArgs.count("-dropmessages"))
{ {
@ -3493,12 +3476,36 @@ bool CMyApp::OnInit2()
return false; 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.count("-gen"))
{ {
if (mapArgs["-gen"].empty()) if (mapArgs["-gen"].empty())
fGenerateBitcoins = true; fGenerateBitcoins = true;
else else
fGenerateBitcoins = atoi(mapArgs["-gen"].c_str()); fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0);
} }
if (mapArgs.count("-proxy")) if (mapArgs.count("-proxy"))
@ -3511,9 +3518,6 @@ bool CMyApp::OnInit2()
OnExit(); OnExit();
return false; return false;
} }
CWalletDB walletdb;
walletdb.WriteSetting("fUseProxy", fUseProxy);
walletdb.WriteSetting("addrProxy", addrProxy);
} }
if (mapArgs.count("-addnode")) if (mapArgs.count("-addnode"))
@ -3522,6 +3526,7 @@ bool CMyApp::OnInit2()
foreach(string strAddr, mapMultiArgs["-addnode"]) foreach(string strAddr, mapMultiArgs["-addnode"])
{ {
CAddress addr(strAddr, NODE_NETWORK); CAddress addr(strAddr, NODE_NETWORK);
addr.nTime = 0; // so it won't relay unless successfully connected
if (addr.IsValid()) if (addr.IsValid())
AddAddress(addrdb, addr); AddAddress(addrdb, addr);
} }
@ -3559,7 +3564,11 @@ bool CMyApp::OnInit2()
// //
// Tests // Tests
// //
#ifdef __WXMSW__
if (argc >= 2 && stricmp(argv[1], "-send") == 0) if (argc >= 2 && stricmp(argv[1], "-send") == 0)
#else
if (argc >= 2 && strcmp(argv[1], "-send") == 0)
#endif
{ {
int64 nValue = 1; int64 nValue = 1;
if (argc >= 3) 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) string MyGetSpecialFolderPath(int nFolder, bool fCreate)
{ {
@ -3737,7 +3747,10 @@ void SetStartOnSystemStartup(bool fAutoStart)
CoUninitialize(); CoUninitialize();
} }
} }
#else
bool GetStartOnSystemStartup() { return false; }
void SetStartOnSystemStartup(bool fAutoStart) { }
#endif

View File

@ -7,6 +7,10 @@
#include "uibase.h" #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 ) 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->SetToolSeparation( 1 );
m_toolBar->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) ); 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_BUTTONSEND, wxT("&Send Coins"), wxBitmap( send20_xpm ), 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_BUTTONRECEIVE, wxT("&Address Book"), wxBitmap( addressbook20_xpm ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
m_toolBar->Realize(); m_toolBar->Realize();
m_statusBar = this->CreateStatusBar( 1, wxST_SIZEGRIP, wxID_ANY ); 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 ); 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 ); 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 ); m_staticText36 = new wxStaticText( this, wxID_ANY, wxT("Pay &To:"), wxDefaultPosition, wxSize( -1,-1 ), wxALIGN_RIGHT );

View File

@ -225,7 +225,7 @@
</object> </object>
</object> </object>
</object> </object>
<object class="wxToolBar" expanded="0"> <object class="wxToolBar" expanded="1">
<property name="bg"></property> <property name="bg"></property>
<property name="bitmapsize">20,20</property> <property name="bitmapsize">20,20</property>
<property name="context_help"></property> <property name="context_help"></property>
@ -273,7 +273,7 @@
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
<object class="tool" expanded="1"> <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="id">wxID_BUTTONSEND</property>
<property name="kind">wxITEM_NORMAL</property> <property name="kind">wxITEM_NORMAL</property>
<property name="label">&amp;Send Coins</property> <property name="label">&amp;Send Coins</property>
@ -287,7 +287,7 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
<object class="tool" expanded="1"> <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="id">wxID_BUTTONRECEIVE</property>
<property name="kind">wxITEM_NORMAL</property> <property name="kind">wxITEM_NORMAL</property>
<property name="label">&amp;Address Book</property> <property name="label">&amp;Address Book</property>
@ -1685,7 +1685,7 @@
</object> </object>
</object> </object>
</object> </object>
<object class="Dialog" expanded="1"> <object class="Dialog" expanded="0">
<property name="bg"></property> <property name="bg"></property>
<property name="center"></property> <property name="center"></property>
<property name="context_help"></property> <property name="context_help"></property>
@ -3699,7 +3699,7 @@
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticBitmap" expanded="1"> <object class="wxStaticBitmap" expanded="1">
<property name="bg"></property> <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="context_help"></property>
<property name="enabled">1</property> <property name="enabled">1</property>
<property name="fg"></property> <property name="fg"></property>

View File

@ -38,8 +38,10 @@ public:
ppmutexOpenSSL[i] = new wxMutex(); ppmutexOpenSSL[i] = new wxMutex();
CRYPTO_set_locking_callback(locking_callback); CRYPTO_set_locking_callback(locking_callback);
#ifdef __WXMSW__
// Seed random number generator with screen scrape and other hardware sources // Seed random number generator with screen scrape and other hardware sources
RAND_screen(); RAND_screen();
#endif
// Seed random number generator with performance counter // Seed random number generator with performance counter
RandAddSeed(); RandAddSeed();
@ -325,8 +327,8 @@ void ParseParameters(int argc, char* argv[])
pszValue = strchr(psz, '='); pszValue = strchr(psz, '=');
*pszValue++ = '\0'; *pszValue++ = '\0';
} }
strlwr(psz);
#ifdef __WXMSW__ #ifdef __WXMSW__
_strlwr(psz);
if (psz[0] == '/') if (psz[0] == '/')
psz[0] = '-'; psz[0] = '-';
#endif #endif
@ -343,9 +345,13 @@ void ParseParameters(int argc, char* argv[])
void FormatException(char* pszMessage, std::exception* pex, const char* pszThread) void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
{ {
#ifdef __WXMSW__
char pszModule[MAX_PATH]; char pszModule[MAX_PATH];
pszModule[0] = '\0'; pszModule[0] = '\0';
GetModuleFileName(NULL, pszModule, sizeof(pszModule)); GetModuleFileName(NULL, pszModule, sizeof(pszModule));
#else
const char* pszModule = wxStandardPaths::Get().GetExecutablePath().mb_str();
#endif
if (pex) if (pex)
snprintf(pszMessage, 1000, snprintf(pszMessage, 1000,
"EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread); "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);

40
util.h
View File

@ -55,9 +55,34 @@ inline T& REF(const T& val)
} }
#ifndef __WXMSW__ #ifndef __WXMSW__
#define closesocket(s) close(s) #define _UI64_MAX UINT64_MAX
#define INVALID_SOCKET (SOCKET)(~0) #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; 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 #endif
@ -120,7 +145,7 @@ public:
protected: protected:
wxMutex mutex; wxMutex mutex;
public: public:
explicit CCriticalSection() { } explicit CCriticalSection() : mutex(wxMUTEX_RECURSIVE) { }
~CCriticalSection() { } ~CCriticalSection() { }
void Enter() { mutex.Lock(); } void Enter() { mutex.Lock(); }
void Leave() { mutex.Unlock(); } void Leave() { mutex.Unlock(); }
@ -183,7 +208,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
// print to debug.log // print to debug.log
char pszFile[MAX_PATH+100]; char pszFile[MAX_PATH+100];
GetDataDir(pszFile); GetDataDir(pszFile);
strlcat(pszFile, "\\debug.log", sizeof(pszFile)); strlcat(pszFile, "/debug.log", sizeof(pszFile));
FILE* fileout = fopen(pszFile, "a"); FILE* fileout = fopen(pszFile, "a");
if (fileout) if (fileout)
{ {
@ -354,13 +379,6 @@ inline int64 GetTimeMillis()
return wxGetLocalTimeMillis().GetValue(); return wxGetLocalTimeMillis().GetValue();
} }
#ifndef __WXMSW__
inline void Sleep(unsigned int nMilliseconds)
{
wxMilliSleep(nMilliseconds);
}
#endif

278
xpm/addressbook16.xpm Normal file
View File

@ -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 : ",
": : : : : : : : : : : : : : : : "
};

282
xpm/addressbook20.xpm Normal file
View File

@ -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.> > ",
"> > > > > > > > > > > > > > > > > > > > ",
"> > > > > > > > > > > > > > > > > > > > "
};

304
xpm/bitcoin.xpm Normal file
View File

@ -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"
};

41
xpm/check.xpm Normal file
View File

@ -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"
};

278
xpm/send16.xpm Normal file
View File

@ -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 "
};

278
xpm/send16noshadow.xpm Normal file
View File

@ -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 "
};

282
xpm/send20.xpm Normal file
View File

@ -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 < , # # # # # # # # # # "
};