changeset 143:acae4b87419a draft

GUI-less build target bitcoind that links to wxBase and shouldn't need GTK, split init and shutdown from ui.cpp into init.cpp, support wxUSE_GUI=0 -- version 0.2.7
author s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
date Thu, 25 Feb 2010 21:55:27 +0000
parents 993a3e02f1d7
children d09e6527fec2
files headers.h init.cpp init.h main.cpp main.h makefile.mingw makefile.unix makefile.vc rpc.cpp serialize.h ui.cpp ui.h util.cpp
diffstat 13 files changed, 818 insertions(+), 774 deletions(-) [+]
line wrap: on
line diff
--- a/headers.h
+++ b/headers.h
@@ -21,9 +21,11 @@
 #include <wx/wx.h>
 #include <wx/clipbrd.h>
 #include <wx/snglinst.h>
-#include <wx/taskbar.h>
 #include <wx/stdpaths.h>
 #include <wx/utils.h>
+#if wxUSE_GUI
+#include <wx/taskbar.h>
+#endif
 #include <openssl/ecdsa.h>
 #include <openssl/evp.h>
 #include <openssl/rand.h>
@@ -100,8 +102,11 @@
 #include "irc.h"
 #include "main.h"
 #include "rpc.h"
+#if wxUSE_GUI
 #include "uibase.h"
+#endif
 #include "ui.h"
+#include "init.h"
 
 #include "xpm/addressbook16.xpm"
 #include "xpm/addressbook20.xpm"
new file mode 100644
--- /dev/null
+++ b/init.cpp
@@ -0,0 +1,625 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
+#include "headers.h"
+
+
+
+
+void ExitTimeout(void* parg)
+{
+#ifdef __WXMSW__
+    Sleep(5000);
+    ExitProcess(0);
+#endif
+}
+
+void Shutdown(void* parg)
+{
+    static CCriticalSection cs_Shutdown;
+    static bool fTaken;
+    bool fFirstThread;
+    CRITICAL_BLOCK(cs_Shutdown)
+    {
+        fFirstThread = !fTaken;
+        fTaken = true;
+    }
+    static bool fExit;
+    if (fFirstThread)
+    {
+        fShutdown = true;
+        nTransactionsUpdated++;
+        DBFlush(false);
+        StopNode();
+        DBFlush(true);
+        CreateThread(ExitTimeout, NULL);
+        Sleep(50);
+        printf("Bitcoin exiting\n\n");
+        fExit = true;
+        exit(0);
+    }
+    else
+    {
+        while (!fExit)
+            Sleep(500);
+        Sleep(100);
+        ExitThread(0);
+    }
+}
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Startup folder
+//
+
+#ifdef __WXMSW__
+typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
+
+string MyGetSpecialFolderPath(int nFolder, bool fCreate)
+{
+    char pszPath[MAX_PATH+100] = "";
+
+    // SHGetSpecialFolderPath is not usually available on NT 4.0
+    HMODULE hShell32 = LoadLibraryA("shell32.dll");
+    if (hShell32)
+    {
+        PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath =
+            (PSHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
+        if (pSHGetSpecialFolderPath)
+            (*pSHGetSpecialFolderPath)(NULL, pszPath, nFolder, fCreate);
+        FreeModule(hShell32);
+    }
+
+    // Backup option
+    if (pszPath[0] == '\0')
+    {
+        if (nFolder == CSIDL_STARTUP)
+        {
+            strcpy(pszPath, getenv("USERPROFILE"));
+            strcat(pszPath, "\\Start Menu\\Programs\\Startup");
+        }
+        else if (nFolder == CSIDL_APPDATA)
+        {
+            strcpy(pszPath, getenv("APPDATA"));
+        }
+    }
+
+    return pszPath;
+}
+
+string StartupShortcutPath()
+{
+    return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
+}
+
+bool GetStartOnSystemStartup()
+{
+    return wxFileExists(StartupShortcutPath());
+}
+
+void SetStartOnSystemStartup(bool fAutoStart)
+{
+    // If the shortcut exists already, remove it for updating
+    remove(StartupShortcutPath().c_str());
+
+    if (fAutoStart)
+    {
+        CoInitialize(NULL);
+
+        // Get a pointer to the IShellLink interface.
+        IShellLink* psl = NULL;
+        HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
+                                CLSCTX_INPROC_SERVER, IID_IShellLink,
+                                reinterpret_cast<void**>(&psl));
+
+        if (SUCCEEDED(hres))
+        {
+            // Get the current executable path
+            TCHAR pszExePath[MAX_PATH];
+            GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
+
+            // Set the path to the shortcut target
+            psl->SetPath(pszExePath);
+            PathRemoveFileSpec(pszExePath);
+            psl->SetWorkingDirectory(pszExePath);
+            psl->SetShowCmd(SW_SHOWMINNOACTIVE);
+
+            // Query IShellLink for the IPersistFile interface for
+            // saving the shortcut in persistent storage.
+            IPersistFile* ppf = NULL;
+            hres = psl->QueryInterface(IID_IPersistFile,
+                                       reinterpret_cast<void**>(&ppf));
+            if (SUCCEEDED(hres))
+            {
+                WCHAR pwsz[MAX_PATH];
+                // Ensure that the string is ANSI.
+                MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
+                // Save the link by calling IPersistFile::Save.
+                hres = ppf->Save(pwsz, TRUE);
+                ppf->Release();
+            }
+            psl->Release();
+        }
+        CoUninitialize();
+    }
+}
+#else
+bool GetStartOnSystemStartup() { return false; }
+void SetStartOnSystemStartup(bool fAutoStart) { }
+#endif
+
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// CMyApp
+//
+
+// Define a new application
+class CMyApp: public wxApp
+{
+public:
+    wxLocale m_locale;
+
+    CMyApp(){};
+    ~CMyApp(){};
+    bool OnInit();
+    bool OnInit2();
+    int OnExit();
+
+    // Hook Initialize so we can start without GUI
+    virtual bool Initialize(int& argc, wxChar** argv);
+
+    // 2nd-level exception handling: we get all the exceptions occurring in any
+    // event handler here
+    virtual bool OnExceptionInMainLoop();
+
+    // 3rd, and final, level exception handling: whenever an unhandled
+    // exception is caught, this function is called
+    virtual void OnUnhandledException();
+
+    // and now for something different: this function is called in case of a
+    // crash (e.g. dereferencing null pointer, division by 0, ...)
+    virtual void OnFatalException();
+};
+
+IMPLEMENT_APP(CMyApp)
+
+bool CMyApp::Initialize(int& argc, wxChar** argv)
+{
+    if (argc > 1 && argv[1][0] != '-' && (!fWindows || argv[1][0] != '/') &&
+        wxString(argv[1]) != "start")
+    {
+        fCommandLine = true;
+    }
+    else if (!fGUI)
+    {
+        fDaemon = true;
+    }
+    else
+    {
+        // wxApp::Initialize will remove environment-specific parameters,
+        // so it's too early to call ParseParameters yet
+        for (int i = 1; i < argc; i++)
+        {
+            wxString str = argv[i];
+            #ifdef __WXMSW__
+            if (str.size() >= 1 && str[0] == '/')
+                str[0] = '-';
+            str = str.MakeLower();
+            #endif
+            // haven't decided which argument to use for this yet
+            if (str == "-daemon" || str == "-d" || str == "start")
+                fDaemon = true;
+        }
+    }
+
+    if (fDaemon)
+        fprintf(stdout, "bitcoin server starting\n");
+
+#ifdef __WXGTK__
+    if (fDaemon || fCommandLine)
+    {
+        // Call the original Initialize while suppressing error messages
+        // and ignoring failure.  If unable to initialize GTK, it fails
+        // near the end so hopefully the last few things don't matter.
+        {
+            wxLogNull logNo;
+            wxApp::Initialize(argc, argv);
+        }
+
+        if (fDaemon)
+        {
+            // Daemonize
+            pid_t pid = fork();
+            if (pid < 0)
+            {
+                fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
+                return false;
+            }
+            if (pid > 0)
+                pthread_exit((void*)0);
+        }
+
+        return true;
+    }
+#endif
+
+    return wxApp::Initialize(argc, argv);
+}
+
+bool CMyApp::OnInit()
+{
+    bool fRet = false;
+    try
+    {
+        fRet = OnInit2();
+    }
+    catch (std::exception& e) {
+        PrintException(&e, "OnInit()");
+    } catch (...) {
+        PrintException(NULL, "OnInit()");
+    }
+    if (!fRet)
+        Shutdown(NULL);
+    return fRet;
+}
+
+extern int g_isPainting;
+
+bool CMyApp::OnInit2()
+{
+#ifdef _MSC_VER
+    // Turn off microsoft heap dump noise
+    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
+    _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
+#endif
+#if defined(__WXMSW__) && defined(__WXDEBUG__) && wxUSE_GUI
+    // Disable malfunctioning wxWidgets debug assertion
+    g_isPainting = 10000;
+#endif
+#if wxUSE_GUI
+    wxImage::AddHandler(new wxPNGHandler);
+#endif
+#ifdef __WXMSW__
+    SetAppName("Bitcoin");
+#else
+    SetAppName("bitcoin");
+    umask(077);
+#endif
+#ifdef __WXMSW__
+#if wxUSE_UNICODE
+    // Hack to set wxConvLibc codepage to UTF-8 on Windows,
+    // may break if wxMBConv_win32 implementation in strconv.cpp changes.
+    class wxMBConv_win32 : public wxMBConv
+    {
+    public:
+        long m_CodePage;
+        size_t m_minMBCharWidth;
+    };
+    if (((wxMBConv_win32*)&wxConvLibc)->m_CodePage == CP_ACP)
+        ((wxMBConv_win32*)&wxConvLibc)->m_CodePage = CP_UTF8;
+#endif
+#endif
+
+    // Load locale/<lang>/LC_MESSAGES/bitcoin.mo language file
+    m_locale.Init(wxLANGUAGE_DEFAULT, 0);
+    m_locale.AddCatalogLookupPathPrefix("locale");
+    if (!fWindows)
+    {
+        m_locale.AddCatalogLookupPathPrefix("/usr/share/locale");
+        m_locale.AddCatalogLookupPathPrefix("/usr/local/share/locale");
+    }
+    m_locale.AddCatalog("wxstd"); // wxWidgets standard translations, if any
+    m_locale.AddCatalog("bitcoin");
+
+    //
+    // Parameters
+    //
+    if (fCommandLine)
+    {
+        int ret = CommandLineRPC(argc, argv);
+        exit(ret);
+    }
+
+    ParseParameters(argc, argv);
+    if (mapArgs.count("-?") || mapArgs.count("--help"))
+    {
+        wxString strUsage = string() +
+            _("Usage: bitcoin [options]") + "\t\t\t\t\t\t\n" +
+            _("Options:\n") +
+            "  -gen            \t\t  " + _("Generate coins\n") +
+            "  -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") +
+            "  -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");
+
+        if (fWindows && fGUI)
+        {
+            // Remove spaces, the tabs make the columns line up in the message box
+            for (int i = 0; i < 50; i++)
+                strUsage.Replace(" \t", "\t");
+            wxMessageBox(strUsage, "Bitcoin", wxOK);
+        }
+        else
+        {
+            // Remove tabs
+            strUsage.Replace("\t", "");
+            fprintf(stderr, "%s", ((string)strUsage).c_str());
+        }
+        return false;
+    }
+
+    if (mapArgs.count("-datadir"))
+        strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
+
+    if (mapArgs.count("-debug"))
+        fDebug = true;
+
+    if (mapArgs.count("-printtodebugger"))
+        fPrintToDebugger = true;
+
+    if (!fDebug && !pszSetDataDir[0])
+        ShrinkDebugFile();
+    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+    printf("Bitcoin version 0.%d.%d%s beta, OS version %s\n", VERSION/100, VERSION%100, pszSubVer, ((string)wxGetOsDescription()).c_str());
+    printf("System default language is %d %s\n", m_locale.GetSystemLanguage(), ((string)m_locale.GetSysName()).c_str());
+    printf("Language file %s (%s)\n", (string("locale/") + (string)m_locale.GetCanonicalName() + "/LC_MESSAGES/bitcoin.mo").c_str(), ((string)m_locale.GetLocale()).c_str());
+
+    if (mapArgs.count("-loadblockindextest"))
+    {
+        CTxDB txdb("r");
+        txdb.LoadBlockIndex();
+        PrintBlockTree();
+        return false;
+    }
+
+    //
+    // Limit to single instance per user
+    // Required to protect the database files if we're going to keep deleting log.*
+    //
+#ifdef __WXMSW__
+    // todo: wxSingleInstanceChecker wasn't working on Linux, never deleted its lock file
+    //  maybe should go by whether successfully bind port 8333 instead
+    wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH");
+    for (int i = 0; i < strMutexName.size(); i++)
+        if (!isalnum(strMutexName[i]))
+            strMutexName[i] = '.';
+    wxSingleInstanceChecker* psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
+    if (psingleinstancechecker->IsAnotherRunning())
+    {
+        printf("Existing instance found\n");
+        unsigned int nStart = GetTime();
+        loop
+        {
+            // TODO: find out how to do this in Linux, or replace with wxWidgets commands
+            // Show the previous instance and exit
+            HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin");
+            if (hwndPrev)
+            {
+                if (IsIconic(hwndPrev))
+                    ShowWindow(hwndPrev, SW_RESTORE);
+                SetForegroundWindow(hwndPrev);
+                return false;
+            }
+
+            if (GetTime() > nStart + 60)
+                return false;
+
+            // Resume this instance if the other exits
+            delete psingleinstancechecker;
+            Sleep(1000);
+            psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
+            if (!psingleinstancechecker->IsAnotherRunning())
+                break;
+        }
+    }
+#endif
+
+    // Bind to the port early so we can tell if another instance is already running.
+    // This is a backup to wxSingleInstanceChecker, which doesn't work on Linux.
+    string strErrors;
+    if (!BindListenPort(strErrors))
+    {
+        wxMessageBox(strErrors, "Bitcoin");
+        return false;
+    }
+
+    //
+    // Load data files
+    //
+    bool fFirstRun;
+    strErrors = "";
+    int64 nStart;
+
+    printf("Loading addresses...\n");
+    nStart = GetTimeMillis();
+    if (!LoadAddresses())
+        strErrors += _("Error loading addr.dat      \n");
+    printf(" addresses   %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+
+    printf("Loading block index...\n");
+    nStart = GetTimeMillis();
+    if (!LoadBlockIndex())
+        strErrors += _("Error loading blkindex.dat      \n");
+    printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+
+    printf("Loading wallet...\n");
+    nStart = GetTimeMillis();
+    if (!LoadWallet(fFirstRun))
+        strErrors += _("Error loading wallet.dat      \n");
+    printf(" wallet      %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+
+    printf("Done loading\n");
+
+        //// debug print
+        printf("mapBlockIndex.size() = %d\n",   mapBlockIndex.size());
+        printf("nBestHeight = %d\n",            nBestHeight);
+        printf("mapKeys.size() = %d\n",         mapKeys.size());
+        printf("mapPubKeys.size() = %d\n",      mapPubKeys.size());
+        printf("mapWallet.size() = %d\n",       mapWallet.size());
+        printf("mapAddressBook.size() = %d\n",  mapAddressBook.size());
+
+    if (!strErrors.empty())
+    {
+        wxMessageBox(strErrors, "Bitcoin");
+        return false;
+    }
+
+    // Add wallet transactions that aren't already in a block to mapTransactions
+    ReacceptWalletTransactions();
+
+    //
+    // Parameters
+    //
+    if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree"))
+    {
+        PrintBlockTree();
+        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);
+                block.BuildMerkleTree();
+                block.print();
+                printf("\n");
+                nFound++;
+            }
+        }
+        if (nFound == 0)
+            printf("No blocks matching %s were found\n", strMatch.c_str());
+        return false;
+    }
+
+    if (mapArgs.count("-gen"))
+    {
+        if (mapArgs["-gen"].empty())
+            fGenerateBitcoins = true;
+        else
+            fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0);
+    }
+
+    if (mapArgs.count("-proxy"))
+    {
+        fUseProxy = true;
+        addrProxy = CAddress(mapArgs["-proxy"]);
+        if (!addrProxy.IsValid())
+        {
+            wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
+            return false;
+        }
+    }
+
+    if (mapArgs.count("-addnode"))
+    {
+        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(addr);
+        }
+    }
+
+    //
+    // Create the main window and start the node
+    //
+    if (!fDaemon)
+        CreateMainWindow();
+
+    if (!CheckDiskSpace())
+        return false;
+
+    RandAddSeedPerfmon();
+
+    if (!CreateThread(StartNode, NULL))
+        wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
+
+    if (mapArgs.count("-server") || fDaemon)
+        CreateThread(ThreadRPCServer, NULL);
+
+    if (fFirstRun)
+        SetStartOnSystemStartup(true);
+
+    return true;
+}
+
+int CMyApp::OnExit()
+{
+    Shutdown(NULL);
+    return wxApp::OnExit();
+}
+
+bool CMyApp::OnExceptionInMainLoop()
+{
+    try
+    {
+        throw;
+    }
+    catch (std::exception& e)
+    {
+        PrintException(&e, "CMyApp::OnExceptionInMainLoop()");
+        wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
+        Sleep(1000);
+        throw;
+    }
+    catch (...)
+    {
+        PrintException(NULL, "CMyApp::OnExceptionInMainLoop()");
+        wxLogWarning("Unknown exception");
+        Sleep(1000);
+        throw;
+    }
+    return true;
+}
+
+void CMyApp::OnUnhandledException()
+{
+    // this shows how we may let some exception propagate uncaught
+    try
+    {
+        throw;
+    }
+    catch (std::exception& e)
+    {
+        PrintException(&e, "CMyApp::OnUnhandledException()");
+        wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
+        Sleep(1000);
+        throw;
+    }
+    catch (...)
+    {
+        PrintException(NULL, "CMyApp::OnUnhandledException()");
+        wxLogWarning("Unknown exception");
+        Sleep(1000);
+        throw;
+    }
+}
+
+void CMyApp::OnFatalException()
+{
+    wxMessageBox(_("Program has crashed and will terminate.  "), "Bitcoin", wxOK | wxICON_ERROR);
+}
new file mode 100644
--- /dev/null
+++ b/init.h
@@ -0,0 +1,7 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
+void Shutdown(void* parg);
+bool GetStartOnSystemStartup();
+void SetStartOnSystemStartup(bool fAutoStart);
--- a/main.cpp
+++ b/main.cpp
@@ -55,6 +55,8 @@
 CAddress addrIncoming;
 int fLimitProcessors = false;
 int nLimitProcessors = 1;
+int fMinimizeToTray = true;
+int fMinimizeOnClose = true;
 
 
 
@@ -2990,7 +2992,7 @@
     if (nValue <= 0)
         return _("Invalid amount");
     if (nValue + nTransactionFee > GetBalance())
-        return _("You don't have enough money");
+        return _("Insufficient funds");
 
     // Parse bitcoin address
     CScript scriptPubKey;
--- a/main.h
+++ b/main.h
@@ -45,6 +45,8 @@
 extern CAddress addrIncoming;
 extern int fLimitProcessors;
 extern int nLimitProcessors;
+extern int fMinimizeToTray;
+extern int fMinimizeOnClose;
 
 
 
--- a/makefile.mingw
+++ b/makefile.mingw
@@ -18,69 +18,59 @@
  -L"/openssl/out" \
  -L"/wxwidgets/lib/gcc_lib"
 
+WXLIBS= \
+ -l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd
+
 LIBS= \
  -l libboost_system-mgw34-mt-d -l libboost_filesystem-mgw34-mt-d \
  -l db_cxx \
  -l eay32 \
- -l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd \
  -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
 
 WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH
 DEBUGFLAGS=-g -D__WXDEBUG__
 CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
-HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
-
+HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
+    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h
 
 
 all: bitcoin.exe
 
 
-headers.h.gch: headers.h            $(HEADERS)
-	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)
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/net.o: net.cpp                  $(HEADERS)
+headers.h.gch: headers.h $(HEADERS)
 	g++ -c $(CFLAGS) -o $@ $<
 
-obj/main.o: main.cpp                $(HEADERS) sha.h
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/ui.o: ui.cpp                    $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/uibase.o: uibase.cpp            uibase.h
+obj/%.o: %.cpp $(HEADERS) headers.h.gch
 	g++ -c $(CFLAGS) -o $@ $<
 
-obj/sha.o: sha.cpp                  sha.h
+obj/sha.o: sha.cpp sha.h
 	g++ -c $(CFLAGS) -O3 -o $@ $<
 
-obj/irc.o: irc.cpp                  $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/rpc.o: rpc.cpp                  $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
-
 obj/ui_res.o: ui.rc  rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
 	windres $(WXDEFS) $(INCLUDEPATHS) -o $@ -i $<
 
+OBJS= \
+    obj/util.o \
+    obj/script.o \
+    obj/db.o \
+    obj/net.o \
+    obj/irc.o \
+    obj/main.o \
+    obj/rpc.o \
+    obj/init.o
+
+bitcoin.exe: $(OBJS) obj/ui.o obj/uibase.o obj/sha.o obj/ui_res.o
+	g++ $(CFLAGS) -mwindows -Wl,--subsystem,windows -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
 
 
-OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o \
-        obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o \
-        obj/ui_res.o
+obj/nogui/%.o: %.cpp $(HEADERS)
+	g++ -c $(CFLAGS) -DwxUSE_GUI=0 -o $@ $<
 
-bitcoin.exe: headers.h.gch $(OBJS)
-	-kill /f bitcoin.exe
-	g++ $(CFLAGS) -mwindows -Wl,--subsystem,windows -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
+bitcoind.exe: $(OBJS:obj/%=obj/nogui/%) obj/sha.o obj/ui_res.o
+	g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -l wxbase29ud $(LIBS)
+
 
 clean:
 	-del /Q obj\*
+	-del /Q obj\nogui\*
 	-del /Q headers.h.gch
--- a/makefile.unix
+++ b/makefile.unix
@@ -13,66 +13,61 @@
  -L"/usr/lib" \
  -L"/usr/local/lib"
 
+WXLIBS= \
+ -Wl,-Bstatic \
+   -l wx_gtk2ud-2.9 \
+ -Wl,-Bdynamic \
+   -l gtk-x11-2.0 -l SM
+
 LIBS= \
  -Wl,-Bstatic \
    -l boost_system-mt -l boost_filesystem-mt \
    -l db_cxx \
-   -l wx_gtk2ud-2.9 \
  -Wl,-Bdynamic \
    -l crypto \
-   -l gtk-x11-2.0 -l gthread-2.0 -l SM
+   -l gthread-2.0
 
 WXDEFS=-D__WXGTK__ -DNOPCH
 DEBUGFLAGS=-g -D__WXDEBUG__
 CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
-HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
-
+HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
+    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h
 
 
 all: bitcoin
 
 
-headers.h.gch: headers.h            $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/util.o: util.cpp                $(HEADERS)
+headers.h.gch: headers.h $(HEADERS)
 	g++ -c $(CFLAGS) -o $@ $<
 
-obj/script.o: script.cpp            $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/db.o: db.cpp                    $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/net.o: net.cpp                  $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/main.o: main.cpp                $(HEADERS) sha.h
+obj/%.o: %.cpp $(HEADERS) headers.h.gch
 	g++ -c $(CFLAGS) -o $@ $<
 
-obj/ui.o: ui.cpp                    $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/uibase.o: uibase.cpp            uibase.h
-	g++ -c $(CFLAGS) -o $@ $<
-
-obj/sha.o: sha.cpp                  sha.h
+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/irc.o \
+    obj/main.o \
+    obj/rpc.o \
+    obj/init.o
 
-obj/rpc.o: rpc.cpp                  $(HEADERS)
-	g++ -c $(CFLAGS) -o $@ $<
+bitcoin: $(OBJS) obj/ui.o obj/uibase.o obj/sha.o
+	g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
 
 
+obj/nogui/%.o: %.cpp $(HEADERS)
+	g++ -c $(CFLAGS) -DwxUSE_GUI=0 -o $@ $<
 
-OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o \
-        obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o
+bitcoind: $(OBJS:obj/%=obj/nogui/%) obj/sha.o
+	g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -l wx_baseud-2.9 $(LIBS)
 
-bitcoin: headers.h.gch $(OBJS)
-	g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
 
 clean:
 	-rm obj/*
+	-rm obj/nogui/*
 	-rm headers.h.gch
--- a/makefile.vc
+++ b/makefile.vc
@@ -28,57 +28,80 @@
 WXDEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
 DEBUGFLAGS=/Zi /Od /D__WXDEBUG__
 CFLAGS=/c /nologo /Ob0 /MDd /EHsc /GR /Zm300 $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
-HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
-
+HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
+    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h
 
 
 all: bitcoin.exe
 
 
-obj\util.obj: util.cpp        $(HEADERS)
-    cl $(CFLAGS) /Fo$@ %s
+.cpp{obj}.obj:
+	cl $(CFLAGS) /Fo$@ %s
 
-obj\script.obj: script.cpp    $(HEADERS)
-    cl $(CFLAGS) /Fo$@ %s
+obj\util.obj: $(HEADERS)
 
-obj\db.obj: db.cpp            $(HEADERS)
-    cl $(CFLAGS) /Fo$@ %s
+obj\script.obj: $(HEADERS)
+
+obj\db.obj: $(HEADERS)
 
-obj\net.obj: net.cpp          $(HEADERS)
-    cl $(CFLAGS) /Fo$@ %s
+obj\net.obj: $(HEADERS)
 
-obj\main.obj: main.cpp        $(HEADERS) sha.h
-    cl $(CFLAGS) /Fo$@ %s
+obj\irc.obj: $(HEADERS)
 
-obj\ui.obj: ui.cpp            $(HEADERS)
-    cl $(CFLAGS) /Fo$@ %s
+obj\main.obj: $(HEADERS)
 
-obj\uibase.obj: uibase.cpp    uibase.h
-    cl $(CFLAGS) /Fo$@ %s
+obj\rpc.obj: $(HEADERS)
+
+obj\init.obj: $(HEADERS)
 
-obj\sha.obj: sha.cpp          sha.h
-    cl $(CFLAGS) /O2 /Fo$@ %s
+obj\ui.obj: $(HEADERS)
 
-obj\irc.obj:  irc.cpp         $(HEADERS)
-    cl $(CFLAGS) /Fo$@ %s
+obj\uibase.obj: $(HEADERS)
 
-obj\rpc.obj:  rpc.cpp         $(HEADERS)
-    cl $(CFLAGS) /Fo$@ %s
+obj\sha.obj: sha.cpp sha.h
+	cl $(CFLAGS) /O2 /Fo$@ %s
 
 obj\ui.res: ui.rc  rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
-    rc $(INCLUDEPATHS) $(WXDEFS) /Fo$@ %s
+	rc $(INCLUDEPATHS) $(WXDEFS) /Fo$@ %s
 
+OBJS= \
+    obj\util.obj \
+    obj\script.obj \
+    obj\db.obj \
+    obj\net.obj \
+    obj\irc.obj \
+    obj\main.obj \
+    obj\rpc.obj \
+    obj\init.obj
+
+bitcoin.exe: $(OBJS) obj\ui.obj obj\uibase.obj obj\sha.obj obj\ui.res
+	link /nologo /DEBUG /SUBSYSTEM:WINDOWS /OUT:$@ $(LIBPATHS) $** $(LIBS)
 
 
-OBJS=obj\util.obj obj\script.obj obj\db.obj obj\net.obj obj\main.obj \
-    obj\ui.obj obj\uibase.obj obj\sha.obj obj\irc.obj obj\rpc.obj \
-    obj\ui.res
+.cpp{obj\nogui}.obj:
+	cl $(CFLAGS) /DwxUSE_GUI=0 /Fo$@ %s
+
+obj\nogui\util.obj: $(HEADERS)
+
+obj\nogui\script.obj: $(HEADERS)
+
+obj\nogui\db.obj: $(HEADERS)
+
+obj\nogui\net.obj: $(HEADERS)
 
-bitcoin.exe: $(OBJS)
-    -kill /f bitcoin.exe & sleep 1
-    link /nologo /DEBUG /SUBSYSTEM:WINDOWS /OUT:$@ $(LIBPATHS) $** $(LIBS)
+obj\nogui\irc.obj: $(HEADERS)
+
+obj\nogui\main.obj: $(HEADERS)
+
+obj\nogui\rpc.obj: $(HEADERS)
+
+obj\nogui\init.obj: $(HEADERS)
+
+bitcoind.exe: $(OBJS:obj\=obj\nogui\) obj\sha.obj obj\ui.res
+	link /nologo /DEBUG /OUT:$@ $(LIBPATHS) $** $(LIBS)
+
 
 clean:
-    -del /Q obj\*
-    -del *.ilk
-    -del *.pdb
+	-del /Q obj\*
+	-del *.ilk
+	-del *.pdb
--- a/rpc.cpp
+++ b/rpc.cpp
@@ -676,18 +676,18 @@
         string strResult = (result.type() == str_type ? result.get_str() : write_string(result, true));
         if (result.type() != null_type)
         {
-            if (fWindows)
+            if (fWindows && fGUI)
                 // Windows GUI apps can't print to command line,
-                // so for now settle for a message box yuck
-                wxMessageBox(strResult.c_str(), "Bitcoin", wxOK);
+                // so settle for a message box yuck
+                MyMessageBox(strResult.c_str(), "Bitcoin", wxOK);
             else
                 fprintf(stdout, "%s\n", strResult.c_str());
         }
         return 0;
     }
     catch (std::exception& e) {
-        if (fWindows)
-            wxMessageBox(strprintf("error: %s\n", e.what()).c_str(), "Bitcoin", wxOK);
+        if (fWindows && fGUI)
+            MyMessageBox(strprintf("error: %s\n", e.what()).c_str(), "Bitcoin", wxOK);
         else
             fprintf(stderr, "error: %s\n", e.what());
     } catch (...) {
--- a/serialize.h
+++ b/serialize.h
@@ -19,7 +19,7 @@
 class CDataStream;
 class CAutoFile;
 
-static const int VERSION = 206;
+static const int VERSION = 207;
 static const char* pszSubVer = ".0";
 
 
--- a/ui.cpp
+++ b/ui.cpp
@@ -7,36 +7,16 @@
 #include <crtdbg.h>
 #endif
 
-bool GetStartOnSystemStartup();
-void SetStartOnSystemStartup(bool fAutoStart);
-
 
 
 DEFINE_EVENT_TYPE(wxEVT_UITHREADCALL)
 
 CMainFrame* pframeMain = NULL;
 CMyTaskBarIcon* ptaskbaricon = NULL;
-extern int g_isPainting;
 bool fClosedToTray = false;
 
-// Settings
-int fMinimizeToTray = true;
-int fMinimizeOnClose = true;
-
-
 
 
-int MyMessageBox(const wxString& message, const wxString& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1)
-{
-    if (fDaemon)
-    {
-        printf("wxMessageBox %s: %s\n", string(caption).c_str(), string(message).c_str());
-        fprintf(stderr, "%s: %s\n", string(caption).c_str(), string(message).c_str());
-        return wxOK;
-    }
-    return wxMessageBox(message, caption, style, parent, x, y);
-}
-#define wxMessageBox  MyMessageBox
 
 
 
@@ -48,47 +28,6 @@
 // Util
 //
 
-void ExitTimeout(void* parg)
-{
-#ifdef __WXMSW__
-    Sleep(5000);
-    ExitProcess(0);
-#endif
-}
-
-void Shutdown(void* parg)
-{
-    static CCriticalSection cs_Shutdown;
-    static bool fTaken;
-    bool fFirstThread;
-    CRITICAL_BLOCK(cs_Shutdown)
-    {
-        fFirstThread = !fTaken;
-        fTaken = true;
-    }
-    static bool fExit;
-    if (fFirstThread)
-    {
-        fShutdown = true;
-        nTransactionsUpdated++;
-        DBFlush(false);
-        StopNode();
-        DBFlush(true);
-        CreateThread(ExitTimeout, NULL);
-        Sleep(50);
-        printf("Bitcoin exiting\n\n");
-        fExit = true;
-        exit(0);
-    }
-    else
-    {
-        while (!fExit)
-            Sleep(500);
-        Sleep(100);
-        ExitThread(0);
-    }
-}
-
 void HandleCtrlA(wxKeyEvent& event)
 {
     // Ctrl-a select all
@@ -312,7 +251,7 @@
     m_staticTextBalance->SetSize(140, 17);
     // resize to fit ubuntu's huge default font
     dResize = 1.22;
-    SetSize(dResize * GetSize().GetWidth(), 1.09 * GetSize().GetHeight());
+    SetSize(dResize * GetSize().GetWidth(), 1.15 * GetSize().GetHeight());
 #endif
     m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
     m_listCtrl->SetFocus();
@@ -1630,7 +1569,6 @@
 
 
 
-
 //////////////////////////////////////////////////////////////////////////////
 //
 // CAboutDialog
@@ -2014,7 +1952,7 @@
     // Make sure we have enough money
     if (nPrice + nTransactionFee > GetBalance())
     {
-        Error(_("You don't have enough money"));
+        Error(_("Insufficient funds"));
         return;
     }
 
@@ -2081,7 +2019,7 @@
             return;
         if (nPrice + nTransactionFee > GetBalance())
         {
-            Error(_("You don't have enough money"));
+            Error(_("Insufficient funds"));
             return;
         }
         CKey key;
@@ -2562,601 +2500,21 @@
 
 
 
-//////////////////////////////////////////////////////////////////////////////
-//
-// CMyApp
-//
-
-// Define a new application
-class CMyApp: public wxApp
-{
-public:
-    wxLocale m_locale;
-
-    CMyApp(){};
-    ~CMyApp(){};
-    bool OnInit();
-    bool OnInit2();
-    int OnExit();
-
-    // Hook Initialize so we can start without GUI
-    virtual bool Initialize(int& argc, wxChar** argv);
-
-    // 2nd-level exception handling: we get all the exceptions occurring in any
-    // event handler here
-    virtual bool OnExceptionInMainLoop();
-
-    // 3rd, and final, level exception handling: whenever an unhandled
-    // exception is caught, this function is called
-    virtual void OnUnhandledException();
-
-    // and now for something different: this function is called in case of a
-    // crash (e.g. dereferencing null pointer, division by 0, ...)
-    virtual void OnFatalException();
-};
-
-IMPLEMENT_APP(CMyApp)
-
-bool CMyApp::Initialize(int& argc, wxChar** argv)
-{
-    if (argc > 1 && argv[1][0] != '-' && (!fWindows || argv[1][0] != '/') &&
-        wxString(argv[1]) != "start")
-    {
-        fCommandLine = true;
-    }
-    else
-    {
-        // wxApp::Initialize will remove environment-specific parameters,
-        // so it's too early to call ParseParameters yet
-        for (int i = 1; i < argc; i++)
-        {
-            wxString str = argv[i];
-            #ifdef __WXMSW__
-            if (str.size() >= 1 && str[0] == '/')
-                str[0] = '-';
-            str = str.MakeLower();
-            #endif
-            // haven't decided which argument to use for this yet
-            if (str == "-daemon" || str == "-d" || str == "start")
-                fDaemon = true;
-        }
-    }
-
-#ifdef __WXGTK__
-    if (fDaemon || fCommandLine)
-    {
-        // Call the original Initialize while suppressing error messages
-        // and ignoring failure.  If unable to initialize GTK, it fails
-        // near the end so hopefully the last few things don't matter.
-        {
-            wxLogNull logNo;
-            wxApp::Initialize(argc, argv);
-        }
-
-        if (fDaemon)
-        {
-            fprintf(stdout, "bitcoin server starting\n");
-
-            // Daemonize
-            pid_t pid = fork();
-            if (pid < 0)
-            {
-                fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
-                return false;
-            }
-            if (pid > 0)
-                pthread_exit((void*)0);
-        }
-
-        return true;
-    }
-#endif
-
-    return wxApp::Initialize(argc, argv);
-}
-
-bool CMyApp::OnInit()
-{
-    bool fRet = false;
-    try
-    {
-        fRet = OnInit2();
-    }
-    catch (std::exception& e) {
-        PrintException(&e, "OnInit()");
-    } catch (...) {
-        PrintException(NULL, "OnInit()");
-    }
-    if (!fRet)
-        Shutdown(NULL);
-    return fRet;
-}
-
-bool CMyApp::OnInit2()
-{
-#ifdef _MSC_VER
-    // Turn off microsoft heap dump noise
-    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
-    _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
-#endif
-#if defined(__WXMSW__) && defined(__WXDEBUG__)
-    // Disable malfunctioning wxWidgets debug assertion
-    g_isPainting = 10000;
-#endif
-    wxImage::AddHandler(new wxPNGHandler);
-#ifdef __WXMSW__
-    SetAppName("Bitcoin");
-#else
-    SetAppName("bitcoin");
-    umask(077);
-#endif
-#ifdef __WXMSW__
-#if wxUSE_UNICODE
-    // Hack to set wxConvLibc codepage to UTF-8 on Windows,
-    // may break if wxMBConv_win32 implementation in strconv.cpp changes.
-    class wxMBConv_win32 : public wxMBConv
-    {
-    public:
-        long m_CodePage;
-        size_t m_minMBCharWidth;
-    };
-    if (((wxMBConv_win32*)&wxConvLibc)->m_CodePage == CP_ACP)
-        ((wxMBConv_win32*)&wxConvLibc)->m_CodePage = CP_UTF8;
-#endif
-#endif
-
-    // Load locale/<lang>/LC_MESSAGES/bitcoin.mo language file
-    m_locale.Init(wxLANGUAGE_DEFAULT, 0);
-    m_locale.AddCatalogLookupPathPrefix("locale");
-    if (!fWindows)
-    {
-        m_locale.AddCatalogLookupPathPrefix("/usr/share/locale");
-        m_locale.AddCatalogLookupPathPrefix("/usr/local/share/locale");
-    }
-    m_locale.AddCatalog("wxstd"); // wxWidgets standard translations, if any
-    m_locale.AddCatalog("bitcoin");
-
-    //
-    // Parameters
-    //
-    if (fCommandLine)
-    {
-        int ret = CommandLineRPC(argc, argv);
-        exit(ret);
-    }
-
-    ParseParameters(argc, argv);
-    if (mapArgs.count("-?") || mapArgs.count("--help"))
-    {
-        wxString strUsage = string() +
-            _("Usage: bitcoin [options]") + "\t\t\t\t\t\t\n" +
-            _("Options:\n") +
-            "  -gen            \t\t  " + _("Generate coins\n") +
-            "  -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") +
-            "  -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");
-
-        if (fWindows)
-        {
-            // Remove spaces, the tabs make the columns line up in the message box
-            for (int i = 0; i < 50; i++)
-                strUsage.Replace(" \t", "\t");
-            wxMessageBox(strUsage, "Bitcoin", wxOK);
-        }
-        else
-        {
-            // Remove tabs
-            strUsage.Replace("\t", "");
-            fprintf(stderr, "%s", ((string)strUsage).c_str());
-        }
-        return false;
-    }
-
-    if (mapArgs.count("-datadir"))
-        strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
-
-    if (mapArgs.count("-debug"))
-        fDebug = true;
-
-    if (mapArgs.count("-printtodebugger"))
-        fPrintToDebugger = true;
-
-    if (!fDebug && !pszSetDataDir[0])
-        ShrinkDebugFile();
-    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
-    printf("Bitcoin version 0.%d.%d%s beta, OS version %s\n", VERSION/100, VERSION%100, pszSubVer, ((string)wxGetOsDescription()).c_str());
-    printf("System default language is %d %s\n", m_locale.GetSystemLanguage(), ((string)m_locale.GetSysName()).c_str());
-    printf("Language file %s (%s)\n", (string("locale/") + (string)m_locale.GetCanonicalName() + "/LC_MESSAGES/bitcoin.mo").c_str(), ((string)m_locale.GetLocale()).c_str());
-
-    if (mapArgs.count("-loadblockindextest"))
-    {
-        CTxDB txdb("r");
-        txdb.LoadBlockIndex();
-        PrintBlockTree();
-        return false;
-    }
-
-    //
-    // Limit to single instance per user
-    // Required to protect the database files if we're going to keep deleting log.*
-    //
-#ifdef __WXMSW__
-    // todo: wxSingleInstanceChecker wasn't working on Linux, never deleted its lock file
-    //  maybe should go by whether successfully bind port 8333 instead
-    wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH");
-    for (int i = 0; i < strMutexName.size(); i++)
-        if (!isalnum(strMutexName[i]))
-            strMutexName[i] = '.';
-    wxSingleInstanceChecker* psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
-    if (psingleinstancechecker->IsAnotherRunning())
-    {
-        printf("Existing instance found\n");
-        unsigned int nStart = GetTime();
-        loop
-        {
-            // TODO: find out how to do this in Linux, or replace with wxWidgets commands
-            // Show the previous instance and exit
-            HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin");
-            if (hwndPrev)
-            {
-                if (IsIconic(hwndPrev))
-                    ShowWindow(hwndPrev, SW_RESTORE);
-                SetForegroundWindow(hwndPrev);
-                return false;
-            }
-
-            if (GetTime() > nStart + 60)
-                return false;
-
-            // Resume this instance if the other exits
-            delete psingleinstancechecker;
-            Sleep(1000);
-            psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
-            if (!psingleinstancechecker->IsAnotherRunning())
-                break;
-        }
-    }
-#endif
-
-    // Bind to the port early so we can tell if another instance is already running.
-    // This is a backup to wxSingleInstanceChecker, which doesn't work on Linux.
-    string strErrors;
-    if (!BindListenPort(strErrors))
-    {
-        wxMessageBox(strErrors, "Bitcoin");
-        return false;
-    }
-
-    //
-    // Load data files
-    //
-    bool fFirstRun;
-    strErrors = "";
-    int64 nStart;
-
-    printf("Loading addresses...\n");
-    nStart = GetTimeMillis();
-    if (!LoadAddresses())
-        strErrors += _("Error loading addr.dat      \n");
-    printf(" addresses   %15"PRI64d"ms\n", GetTimeMillis() - nStart);
-
-    printf("Loading block index...\n");
-    nStart = GetTimeMillis();
-    if (!LoadBlockIndex())
-        strErrors += _("Error loading blkindex.dat      \n");
-    printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
-
-    printf("Loading wallet...\n");
-    nStart = GetTimeMillis();
-    if (!LoadWallet(fFirstRun))
-        strErrors += _("Error loading wallet.dat      \n");
-    printf(" wallet      %15"PRI64d"ms\n", GetTimeMillis() - nStart);
-
-    printf("Done loading\n");
-
-        //// debug print
-        printf("mapBlockIndex.size() = %d\n",   mapBlockIndex.size());
-        printf("nBestHeight = %d\n",            nBestHeight);
-        printf("mapKeys.size() = %d\n",         mapKeys.size());
-        printf("mapPubKeys.size() = %d\n",      mapPubKeys.size());
-        printf("mapWallet.size() = %d\n",       mapWallet.size());
-        printf("mapAddressBook.size() = %d\n",  mapAddressBook.size());
-
-    if (!strErrors.empty())
-    {
-        wxMessageBox(strErrors, "Bitcoin");
-        return false;
-    }
-
-    // Add wallet transactions that aren't already in a block to mapTransactions
-    ReacceptWalletTransactions();
-
-    //
-    // Parameters
-    //
-    if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree"))
-    {
-        PrintBlockTree();
-        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);
-                block.BuildMerkleTree();
-                block.print();
-                printf("\n");
-                nFound++;
-            }
-        }
-        if (nFound == 0)
-            printf("No blocks matching %s were found\n", strMatch.c_str());
-        return false;
-    }
-
-    if (mapArgs.count("-gen"))
-    {
-        if (mapArgs["-gen"].empty())
-            fGenerateBitcoins = true;
-        else
-            fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0);
-    }
-
-    if (mapArgs.count("-proxy"))
-    {
-        fUseProxy = true;
-        addrProxy = CAddress(mapArgs["-proxy"]);
-        if (!addrProxy.IsValid())
-        {
-            wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
-            return false;
-        }
-    }
-
-    if (mapArgs.count("-addnode"))
-    {
-        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(addr);
-        }
-    }
-
-    //
-    // Create the main frame window
-    //
-    if (!fDaemon)
-    {
-        pframeMain = new CMainFrame(NULL);
-        if (mapArgs.count("-min"))
-            pframeMain->Iconize(true);
-        pframeMain->Show(true);  // have to show first to get taskbar button to hide
-        if (fMinimizeToTray && pframeMain->IsIconized())
-            fClosedToTray = true;
-        pframeMain->Show(!fClosedToTray);
-        ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);
-
-        CreateThread(ThreadDelayedRepaint, NULL);
-    }
-
-    if (!CheckDiskSpace())
-        return false;
-
-    RandAddSeedPerfmon();
-
-    if (!CreateThread(StartNode, NULL))
-        wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
-
-    if (mapArgs.count("-server") || fDaemon)
-        CreateThread(ThreadRPCServer, NULL);
-
-    if (fFirstRun)
-        SetStartOnSystemStartup(true);
-
-
-    //
-    // 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)
-            ParseMoney(argv[2], nValue);
-
-        string strAddress;
-        if (argc >= 4)
-            strAddress = argv[3];
-        CAddress addr(strAddress);
-
-        CWalletTx wtx;
-        wtx.mapValue["to"] = strAddress;
-        wtx.mapValue["from"] = addrLocalHost.ToString();
-        wtx.mapValue["message"] = "command line send";
-
-        // Send to IP address
-        CSendingDialog* pdialog = new CSendingDialog(pframeMain, addr, nValue, wtx);
-        if (!pdialog->ShowModal())
-            return false;
-    }
-
-    return true;
-}
-
-int CMyApp::OnExit()
-{
-    Shutdown(NULL);
-    return wxApp::OnExit();
-}
-
-bool CMyApp::OnExceptionInMainLoop()
-{
-    try
-    {
-        throw;
-    }
-    catch (std::exception& e)
-    {
-        PrintException(&e, "CMyApp::OnExceptionInMainLoop()");
-        wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
-        Sleep(1000);
-        throw;
-    }
-    catch (...)
-    {
-        PrintException(NULL, "CMyApp::OnExceptionInMainLoop()");
-        wxLogWarning("Unknown exception");
-        Sleep(1000);
-        throw;
-    }
-    return true;
-}
-
-void CMyApp::OnUnhandledException()
-{
-    // this shows how we may let some exception propagate uncaught
-    try
-    {
-        throw;
-    }
-    catch (std::exception& e)
-    {
-        PrintException(&e, "CMyApp::OnUnhandledException()");
-        wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
-        Sleep(1000);
-        throw;
-    }
-    catch (...)
-    {
-        PrintException(NULL, "CMyApp::OnUnhandledException()");
-        wxLogWarning("Unknown exception");
-        Sleep(1000);
-        throw;
-    }
-}
-
-void CMyApp::OnFatalException()
-{
-    wxMessageBox(_("Program has crashed and will terminate.  "), "Bitcoin", wxOK | wxICON_ERROR);
-}
 
 
 
-
-
-#ifdef __WXMSW__
-typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
-
-string MyGetSpecialFolderPath(int nFolder, bool fCreate)
-{
-    char pszPath[MAX_PATH+100] = "";
-
-    // SHGetSpecialFolderPath is not usually available on NT 4.0
-    HMODULE hShell32 = LoadLibraryA("shell32.dll");
-    if (hShell32)
-    {
-        PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath =
-            (PSHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
-        if (pSHGetSpecialFolderPath)
-            (*pSHGetSpecialFolderPath)(NULL, pszPath, nFolder, fCreate);
-        FreeModule(hShell32);
-    }
-
-    // Backup option
-    if (pszPath[0] == '\0')
-    {
-        if (nFolder == CSIDL_STARTUP)
-        {
-            strcpy(pszPath, getenv("USERPROFILE"));
-            strcat(pszPath, "\\Start Menu\\Programs\\Startup");
-        }
-        else if (nFolder == CSIDL_APPDATA)
-        {
-            strcpy(pszPath, getenv("APPDATA"));
-        }
-    }
-
-    return pszPath;
-}
-
-string StartupShortcutPath()
-{
-    return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
-}
-
-bool GetStartOnSystemStartup()
-{
-    return wxFileExists(StartupShortcutPath());
-}
-
-void SetStartOnSystemStartup(bool fAutoStart)
+void CreateMainWindow()
 {
-    // If the shortcut exists already, remove it for updating
-    remove(StartupShortcutPath().c_str());
-
-    if (fAutoStart)
-    {
-        CoInitialize(NULL);
-
-        // Get a pointer to the IShellLink interface.
-        IShellLink* psl = NULL;
-        HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
-                                CLSCTX_INPROC_SERVER, IID_IShellLink,
-                                reinterpret_cast<void**>(&psl));
-
-        if (SUCCEEDED(hres))
-        {
-            // Get the current executable path
-            TCHAR pszExePath[MAX_PATH];
-            GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
-
-            // Set the path to the shortcut target
-            psl->SetPath(pszExePath);
-            PathRemoveFileSpec(pszExePath);
-            psl->SetWorkingDirectory(pszExePath);
-            psl->SetShowCmd(SW_SHOWMINNOACTIVE);
-
-            // Query IShellLink for the IPersistFile interface for
-            // saving the shortcut in persistent storage.
-            IPersistFile* ppf = NULL;
-            hres = psl->QueryInterface(IID_IPersistFile,
-                                       reinterpret_cast<void**>(&ppf));
-            if (SUCCEEDED(hres))
-            {
-                WCHAR pwsz[MAX_PATH];
-                // Ensure that the string is ANSI.
-                MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
-                // Save the link by calling IPersistFile::Save.
-                hres = ppf->Save(pwsz, TRUE);
-                ppf->Release();
-            }
-            psl->Release();
-        }
-        CoUninitialize();
-    }
+    pframeMain = new CMainFrame(NULL);
+    if (mapArgs.count("-min"))
+        pframeMain->Iconize(true);
+    pframeMain->Show(true);  // have to show first to get taskbar button to hide
+    if (fMinimizeToTray && pframeMain->IsIconized())
+        fClosedToTray = true;
+    pframeMain->Show(!fClosedToTray);
+    ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);
+    CreateThread(ThreadDelayedRepaint, NULL);
 }
-#else
-bool GetStartOnSystemStartup() { return false; }
-void SetStartOnSystemStartup(bool fAutoStart) { }
-#endif
 
 
 
@@ -3166,4 +2524,3 @@
 
 
 
-
--- a/ui.h
+++ b/ui.h
@@ -4,27 +4,62 @@
 
 DECLARE_EVENT_TYPE(wxEVT_UITHREADCALL, -1)
 
-
-extern map<string, string> mapArgs;
+#if wxUSE_GUI
+static const bool fGUI=true;
+#else
+static const bool fGUI=false;
+#endif
 
-// Settings
-extern int fMinimizeToTray;
-extern int fMinimizeOnClose;
+inline int MyMessageBox(const wxString& message, const wxString& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1)
+{
+#if wxUSE_GUI
+    if (!fDaemon)
+        return wxMessageBox(message, caption, style, parent, x, y);
+#endif
+    printf("wxMessageBox %s: %s\n", string(caption).c_str(), string(message).c_str());
+    fprintf(stderr, "%s: %s\n", string(caption).c_str(), string(message).c_str());
+    return wxOK;
+}
+#define wxMessageBox  MyMessageBox
+
 
 
 
 void HandleCtrlA(wxKeyEvent& event);
 string FormatTxStatus(const CWalletTx& wtx);
 void UIThreadCall(boost::function0<void>);
-void MainFrameRepaint();
-void Shutdown(void* parg);
 int ThreadSafeMessageBox(const string& message, const string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1);
 bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent);
+void MainFrameRepaint();
+void CreateMainWindow();
 
 
 
 
 
+#if !wxUSE_GUI
+inline int ThreadSafeMessageBox(const string& message, const string& caption, int style, wxWindow* parent, int x, int y)
+{
+    return MyMessageBox(message, caption, style, parent, x, y);
+}
+
+inline bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent)
+{
+    return true;
+}
+
+inline void MainFrameRepaint()
+{
+}
+
+inline void CreateMainWindow()
+{
+}
+#else // wxUSE_GUI
+
+
+
+
 
 class CMainFrame : public CMainFrameBase
 {
@@ -331,3 +366,5 @@
 
 DECLARE_EVENT_TABLE()
 };
+
+#endif // wxUSE_GUI
--- a/util.cpp
+++ b/util.cpp
@@ -459,6 +459,7 @@
         mapCache[pszEnglish] = pszCached;
         return pszCached;
     }
+    return NULL;
 }
 
 
@@ -502,8 +503,8 @@
     FormatException(pszMessage, pex, pszThread);
     printf("\n\n************************\n%s\n", pszMessage);
     fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
-    if (wxTheApp && !fDaemon)
-        wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
+    if (wxTheApp && !fDaemon && fGUI)
+        MyMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
     throw;
     //DebugBreak();
 }