1
0
forked from 0ad/0ad
0ad/source/tools/atlas/AtlasUI/Misc/DLLInterface.cpp
Ykkrosh a1a7dac59c # Integrated Actor Viewer and Actor Editor tools
ObjectManager: Removed ObjectTypes because it hasn't been used for
years.
Atlas: Fixed leak when saving with Xerces. Changed range of water
shininess slider.
Actor Editor: Relabelled "Freq" to "Ratio". Made modal dialogs use the
correct parent.

This was SVN commit r4376.
2006-09-22 17:43:00 +00:00

233 lines
5.3 KiB
C++

#include "stdafx.h"
#include "DLLInterface.h"
#include "General/AtlasEventLoop.h"
#include "General/Datafile.h"
#include "ActorEditor/ActorEditor.h"
#include "ActorViewer/ActorViewer.h"
#include "ArchiveViewer/ArchiveViewer.h"
#include "ColourTester/ColourTester.h"
#include "FileConverter/FileConverter.h"
#include "ScenarioEditor/ScenarioEditor.h"
#include "GameInterface/MessagePasser.h"
#include "wx/config.h"
#include "wx/debugrpt.h"
#include "wx/file.h"
// Shared memory allocation functions
ATLASDLLIMPEXP void* ShareableMalloc(size_t n)
{
// TODO: make sure this is thread-safe everywhere. (It is in MSVC with the
// multithreaded CRT.)
return malloc(n);
}
ATLASDLLIMPEXP void ShareableFree(void* p)
{
free(p);
}
// Define the function pointers that we'll use when calling those functions.
// (The game loads the addresses of the above functions, then does the same.)
namespace AtlasMessage
{
void* (*ShareableMallocFptr) (size_t) = &ShareableMalloc;
void (*ShareableFreeFptr) (void*) = &ShareableFree;
}
// Global variables, to remember state between DllMain and StartWindow and OnInit
wxString g_InitialWindowType;
HINSTANCE g_Module;
bool g_IsLoaded = false;
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID WXUNUSED(lpReserved))
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_Module = hModule;
return TRUE;
case DLL_PROCESS_DETACH:
if (g_IsLoaded)
{
wxEntryCleanup();
g_IsLoaded = false;
}
break;
}
return TRUE;
}
using namespace AtlasMessage;
MessagePasser* AtlasMessage::g_MessagePasser = NULL;
ATLASDLLIMPEXP void Atlas_SetMessagePasser(MessagePasser* passer)
{
g_MessagePasser = passer;
}
ATLASDLLIMPEXP void Atlas_StartWindow(const wchar_t* type)
{
g_InitialWindowType = type;
wxEntry(g_Module);
}
ATLASDLLIMPEXP void Atlas_DisplayError(const wchar_t* text, unsigned int WXUNUSED(flags))
{
// This is called from the game thread.
// wxLog appears to be thread-safe, so that's okay.
wxLogError(L"%s", text);
// TODO: wait for user response (if possible) before returning,
// and return their status (break/continue/debug/etc), but only in
// cases where we're certain it won't deadlock (i.e. the UI event loop
// is still running and won't block before showing the dialog to the user)
// and where it matters (i.e. errors, not warnings (unless they're going to
// turn into errors after continuing))
// TODO: 'text' (or at least some copy of it) appears to get leaked when
// this function is called
}
class AtlasDLLApp : public wxApp
{
public:
virtual bool OnInit()
{
// _CrtSetBreakAlloc(5632);
if (! wxIsDebuggerRunning())
wxHandleFatalExceptions();
// Initialise the global config file
wxConfigBase::Set(new wxConfig(_T("Atlas Editor"), _T("Wildfire Games")));
// Assume that the .exe is located in .../binaries/system. (We can't
// just use the cwd, since that isn't correct when being executed by
// dragging-and-dropping onto the program in Explorer.)
Datafile::SetSystemDirectory(argv[0]);
// Display the appropriate window
wxFrame* frame;
#define MAYBE(t) if (g_InitialWindowType == _T(#t)) frame = new t(NULL); else
MAYBE(ActorEditor)
MAYBE(ActorViewer)
MAYBE(ArchiveViewer)
MAYBE(ColourTester)
MAYBE(FileConverter)
MAYBE(ScenarioEditor)
#undef MAYBE
// else
{
wxFAIL_MSG(_("Internal error: invalid window type"));
return false;
}
frame->Show();
SetTopWindow(frame);
AtlasWindow* win = wxDynamicCast(frame, AtlasWindow);
if (win)
{
// One argument => argv[1] is probably a filename to open
if (argc > 1)
{
wxChar* filename = argv[1];
if (filename[0] != _T('-')) // ignore -options
{
if (wxFile::Exists(filename))
{
win->OpenFile(filename);
}
else
wxLogError(_("Cannot find file '%s'"), filename);
}
}
}
return true;
}
bool OpenDirectory(const wxString& dir)
{
// Code largely copied from wxLaunchDefaultBrowser:
// (TODO: portability)
typedef HINSTANCE (WINAPI *LPShellExecute)(HWND hwnd, const wxChar* lpOperation,
const wxChar* lpFile,
const wxChar* lpParameters,
const wxChar* lpDirectory,
INT nShowCmd);
HINSTANCE hShellDll = ::LoadLibrary(_T("shell32.dll"));
if (hShellDll == NULL)
return false;
LPShellExecute lpShellExecute =
(LPShellExecute) ::GetProcAddress(hShellDll,
wxString(_T("ShellExecute")
#ifdef _UNICODE
_T("W")
#else
_T("A")
#endif
).mb_str(wxConvLocal));
if (lpShellExecute == NULL)
return false;
/*HINSTANCE nResult =*/ (*lpShellExecute)(NULL, _T("explore"), dir.c_str(), NULL, NULL, SW_SHOWNORMAL);
// ignore return value, since we're not going to do anything if this fails
::FreeLibrary(hShellDll);
return true;
}
virtual void OnFatalException()
{
wxDebugReport report;
wxDebugReportPreviewStd preview;
report.AddAll();
if (preview.Show(report))
{
wxString dir = report.GetDirectory(); // save the string, since it gets cleared by Process
report.Process();
OpenDirectory(dir);
}
}
/* Disabled (and should be removed if it turns out to be unnecessary)
- see MessagePasserImpl.cpp for information
virtual int MainLoop()
{
// Override the default MainLoop so that we can provide our own event loop
wxEventLoop* old = m_mainLoop;
m_mainLoop = new AtlasEventLoop;
int ret = m_mainLoop->Run();
delete m_mainLoop;
m_mainLoop = old;
return ret;
}
*/
};
IMPLEMENT_APP_NO_MAIN(AtlasDLLApp)