From c2430126d75318508836a24f90d3524320190465 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Thu, 25 Feb 2010 21:55:27 +0000 Subject: 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 git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@71 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- headers.h | 7 +- init.cpp | 625 +++++++++++++++++++++++++++++++++++++++++++++++++++++ init.h | 7 + main.cpp | 4 +- main.h | 2 + makefile.mingw | 62 +++--- makefile.unix | 61 +++--- makefile.vc | 87 +++++--- rpc.cpp | 10 +- serialize.h | 2 +- ui.cpp | 669 ++------------------------------------------------------- ui.h | 49 ++++- util.cpp | 5 +- 13 files changed, 817 insertions(+), 773 deletions(-) create mode 100644 init.cpp create mode 100644 init.h diff --git a/headers.h b/headers.h index 7fb227ec42..3c8d32cad9 100644 --- a/headers.h +++ b/headers.h @@ -21,9 +21,11 @@ #include #include #include -#include #include #include +#if wxUSE_GUI +#include +#endif #include #include #include @@ -100,8 +102,11 @@ using namespace boost; #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" diff --git a/init.cpp b/init.cpp new file mode 100644 index 0000000000..06d8f4c933 --- /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(&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(&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//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= \t " + _("Specify data directory\n") + + " -proxy=\t " + _("Connect through socks4 proxy\n") + + " -addnode= \t " + _("Add a node to connect to\n") + + " -connect= \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::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); +} diff --git a/init.h b/init.h new file mode 100644 index 0000000000..bd5e365941 --- /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); diff --git a/main.cpp b/main.cpp index bd69de92a4..f7416230f6 100644 --- a/main.cpp +++ b/main.cpp @@ -55,6 +55,8 @@ int64 nTransactionFee = 0; CAddress addrIncoming; int fLimitProcessors = false; int nLimitProcessors = 1; +int fMinimizeToTray = true; +int fMinimizeOnClose = true; @@ -2990,7 +2992,7 @@ string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtx 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; diff --git a/main.h b/main.h index 452ce85b63..83b8469937 100644 --- a/main.h +++ b/main.h @@ -45,6 +45,8 @@ extern int64 nTransactionFee; extern CAddress addrIncoming; extern int fLimitProcessors; extern int nLimitProcessors; +extern int fMinimizeToTray; +extern int fMinimizeOnClose; diff --git a/makefile.mingw b/makefile.mingw index 2644cbaad1..449a96072c 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -18,69 +18,59 @@ LIBPATHS= \ -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) - g++ -c $(CFLAGS) -o $@ $< - -obj/main.o: main.cpp $(HEADERS) sha.h +headers.h.gch: headers.h $(HEADERS) g++ -c $(CFLAGS) -o $@ $< -obj/ui.o: ui.cpp $(HEADERS) +obj/%.o: %.cpp $(HEADERS) headers.h.gch 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 $@ $< - -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) + +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 \ - obj/ui_res.o +bitcoind.exe: $(OBJS:obj/%=obj/nogui/%) obj/sha.o obj/ui_res.o + g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -l wxbase29ud $(LIBS) -bitcoin.exe: headers.h.gch $(OBJS) - -kill /f bitcoin.exe - g++ $(CFLAGS) -mwindows -Wl,--subsystem,windows -o $@ $(LIBPATHS) $(OBJS) $(LIBS) clean: -del /Q obj\* + -del /Q obj\nogui\* -del /Q headers.h.gch diff --git a/makefile.unix b/makefile.unix index a8ec936776..10c4eece73 100644 --- a/makefile.unix +++ b/makefile.unix @@ -13,66 +13,61 @@ LIBPATHS= \ -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) - 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 - g++ -c $(CFLAGS) -o $@ $< - -obj/ui.o: ui.cpp $(HEADERS) +headers.h.gch: headers.h $(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 $@ $< +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 diff --git a/makefile.vc b/makefile.vc index c407be3d2f..41f13522a0 100644 --- a/makefile.vc +++ b/makefile.vc @@ -28,57 +28,80 @@ LIBS= \ 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\util.obj: $(HEADERS) -obj\script.obj: script.cpp $(HEADERS) - cl $(CFLAGS) /Fo$@ %s +obj\script.obj: $(HEADERS) -obj\db.obj: db.cpp $(HEADERS) - cl $(CFLAGS) /Fo$@ %s +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\sha.obj: sha.cpp sha.h - cl $(CFLAGS) /O2 /Fo$@ %s +obj\init.obj: $(HEADERS) -obj\irc.obj: irc.cpp $(HEADERS) - cl $(CFLAGS) /Fo$@ %s +obj\ui.obj: $(HEADERS) -obj\rpc.obj: rpc.cpp $(HEADERS) - cl $(CFLAGS) /Fo$@ %s +obj\uibase.obj: $(HEADERS) + +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) + + +.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) + +obj\nogui\irc.obj: $(HEADERS) + +obj\nogui\main.obj: $(HEADERS) +obj\nogui\rpc.obj: $(HEADERS) +obj\nogui\init.obj: $(HEADERS) -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 +bitcoind.exe: $(OBJS:obj\=obj\nogui\) obj\sha.obj obj\ui.res + link /nologo /DEBUG /OUT:$@ $(LIBPATHS) $** $(LIBS) -bitcoin.exe: $(OBJS) - -kill /f bitcoin.exe & sleep 1 - link /nologo /DEBUG /SUBSYSTEM:WINDOWS /OUT:$@ $(LIBPATHS) $** $(LIBS) clean: - -del /Q obj\* - -del *.ilk - -del *.pdb + -del /Q obj\* + -del *.ilk + -del *.pdb diff --git a/rpc.cpp b/rpc.cpp index 7f3e71dbac..f298137aa2 100644 --- a/rpc.cpp +++ b/rpc.cpp @@ -676,18 +676,18 @@ int CommandLineRPC(int argc, char *argv[]) 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 (...) { diff --git a/serialize.h b/serialize.h index 8fb72a0aab..5399c23d02 100644 --- a/serialize.h +++ b/serialize.h @@ -19,7 +19,7 @@ class CScript; class CDataStream; class CAutoFile; -static const int VERSION = 206; +static const int VERSION = 207; static const char* pszSubVer = ".0"; diff --git a/ui.cpp b/ui.cpp index 748b4dad93..efb05385ec 100644 --- a/ui.cpp +++ b/ui.cpp @@ -7,38 +7,18 @@ #include #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 @@ int MyMessageBox(const wxString& message, const wxString& caption="Message", int // 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 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) 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 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event) - ////////////////////////////////////////////////////////////////////////////// // // CAboutDialog @@ -2014,7 +1952,7 @@ void CSendingDialog::StartTransfer() // 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 @@ void CSendingDialog::OnReply2(CDataStream& vRecv) return; if (nPrice + nTransactionFee > GetBalance()) { - Error(_("You don't have enough money")); + Error(_("Insufficient funds")); return; } CKey key; @@ -2562,602 +2500,21 @@ wxMenu* CMyTaskBarIcon::CreatePopupMenu() -////////////////////////////////////////////////////////////////////////////// -// -// 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//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= \t " + _("Specify data directory\n") + - " -proxy=\t " + _("Connect through socks4 proxy\n") + - " -addnode= \t " + _("Add a node to connect to\n") + - " -connect= \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::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(&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(&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 - diff --git a/ui.h b/ui.h index acabd5514a..e944eb9339 100644 --- a/ui.h +++ b/ui.h @@ -4,26 +4,61 @@ DECLARE_EVENT_TYPE(wxEVT_UITHREADCALL, -1) +#if wxUSE_GUI +static const bool fGUI=true; +#else +static const bool fGUI=false; +#endif -extern map mapArgs; +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 -// Settings -extern int fMinimizeToTray; -extern int fMinimizeOnClose; void HandleCtrlA(wxKeyEvent& event); string FormatTxStatus(const CWalletTx& wtx); void UIThreadCall(boost::function0); -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 @@ public: DECLARE_EVENT_TABLE() }; + +#endif // wxUSE_GUI diff --git a/util.cpp b/util.cpp index 6ea735d1e2..d90cdc48f9 100644 --- a/util.cpp +++ b/util.cpp @@ -459,6 +459,7 @@ const char* wxGetTranslation(const char* pszEnglish) mapCache[pszEnglish] = pszCached; return pszCached; } + return NULL; } @@ -502,8 +503,8 @@ void PrintException(std::exception* pex, const char* pszThread) 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(); } -- cgit v1.2.3