Added Enigma game
This commit is contained in:
850
project/jni/application/enigma/src/main.cpp
Normal file
850
project/jni/application/enigma/src/main.cpp
Normal file
@@ -0,0 +1,850 @@
|
||||
/*
|
||||
* Copyright (C) 2002,2003,2004,2005 Daniel Heck
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "main.hh"
|
||||
#include "display.hh"
|
||||
#include "lua.hh"
|
||||
#include "gui/MainMenu.hh"
|
||||
#include "gui/ErrorMenu.hh"
|
||||
#include "gui/LevelPreviewCache.hh"
|
||||
#include "options.hh"
|
||||
#include "oxyd.hh"
|
||||
#include "sound.hh"
|
||||
#include "video.hh"
|
||||
#include "ecl_argp.hh"
|
||||
#include "ecl_system.hh"
|
||||
#include "errors.hh"
|
||||
#include "world.hh"
|
||||
#include "nls.hh"
|
||||
#include "LocalToXML.hh"
|
||||
#include "PreferenceManager.hh"
|
||||
#include "Utf8ToXML.hh"
|
||||
#include "XMLtoUtf8.hh"
|
||||
#include "XMLtoLocal.hh"
|
||||
#include "lev/RatingManager.hh"
|
||||
#include "lev/VolatileIndex.hh"
|
||||
#include "lev/PersistentIndex.hh"
|
||||
#include "lev/ScoreManager.hh"
|
||||
|
||||
#include "enet/enet.h"
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <xercesc/dom/DOM.hpp>
|
||||
#include <xercesc/framework/XMLRecognizer.hpp>
|
||||
#include <xercesc/util/XMLString.hpp>
|
||||
#include <xercesc/util/XMLUniDefs.hpp>
|
||||
#include <xercesc/util/PlatformUtils.hpp>
|
||||
#include <xercesc/util/XercesVersion.hpp>
|
||||
#include <SDL_image.h>
|
||||
#include <SDL_mixer.h>
|
||||
#include <SDL_ttf.h>
|
||||
|
||||
#ifdef MACOSX
|
||||
// for search paths
|
||||
#include "NSSystemDirectories.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace ecl;
|
||||
using namespace enigma;
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
||||
#ifdef WIN32
|
||||
// LoadImage is a Syscall on Windows, which gets defined to LoadImageA
|
||||
// or LoadImageW in winuser.h so we simply undefine it to use this
|
||||
// name for one of the methods
|
||||
#undef LoadImage
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
class Nulbuf : public std::streambuf {};
|
||||
Nulbuf* nullbuffer = new Nulbuf;
|
||||
}
|
||||
|
||||
/* -------------------- Variables -------------------- */
|
||||
|
||||
namespace enigma
|
||||
{
|
||||
Application app;
|
||||
|
||||
bool noAssert = true; // block expensive assert evaluations by default
|
||||
|
||||
bool WizardMode = false;
|
||||
|
||||
//! If true, do not ``grab'' the mouse and keyboard
|
||||
bool Nograb = false;
|
||||
}
|
||||
|
||||
/*! The stream object that is used for logging messages. As defined
|
||||
here, it is not connected to any file or buffer.
|
||||
|
||||
(Note: I think writing to a stream without a streambuffer *should*
|
||||
be a no-op, but it leads to crashes with g++ 2.95. to circumvent
|
||||
this, Log is initialized with a dummy streambuf in init(). ) */
|
||||
std::ostream enigma::Log(0);
|
||||
|
||||
/*! This is the stream object that is used when logging to a file. In
|
||||
this case, enigma::Log uses this object's streambuffer. */
|
||||
static std::fstream logfile;
|
||||
|
||||
/* -------------------- Functions -------------------- */
|
||||
|
||||
static void usage()
|
||||
{
|
||||
printf("Usage: %s [options] [level files]\n\n"
|
||||
"Available options :\n\n"
|
||||
" --nosound Disable music and sound\n"
|
||||
" --nomusic Disable music\n"
|
||||
" --window -w Run in a window; do not enter fullscreen mode\n"
|
||||
" --help -h Show this help\n"
|
||||
" --version Print the executable's version number\n"
|
||||
" --nograb Do not use exclusive mouse/keyboard access\n"
|
||||
" --data -d path Load data from additional directory\n"
|
||||
" --lang -l lang Set game language\n"
|
||||
" --pref -p file Use filename or dirname for preferences\n"
|
||||
"\n",
|
||||
app.progCallPath.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct AP : public ecl::ArgParser {
|
||||
public:
|
||||
// Constructor
|
||||
AP();
|
||||
|
||||
// Variables.
|
||||
bool nosound, nomusic, show_help, show_version, do_log, do_assert, force_window;
|
||||
bool dumpinfo, makepreview;
|
||||
string gamename;
|
||||
string datapath;
|
||||
string preffilename;
|
||||
std::vector<string> levelnames;
|
||||
|
||||
private:
|
||||
enum {
|
||||
OPT_WINDOW, OPT_GAME, OPT_DATA, OPT_LANG, OPT_PREF
|
||||
};
|
||||
|
||||
// ArgParser interface.
|
||||
void on_error (ErrorType t, const string &option) {
|
||||
cout << errormsg(t, option) << endl;
|
||||
show_help = true;
|
||||
}
|
||||
|
||||
void on_option (int id, const string ¶m);
|
||||
void on_argument (const string &arg);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
AP::AP() : ArgParser (app.args.begin(), app.args.end())
|
||||
{
|
||||
nosound = nomusic = show_help = show_version = do_log = do_assert = force_window = false;
|
||||
dumpinfo = makepreview = false;
|
||||
gamename = "";
|
||||
datapath = "";
|
||||
preffilename = PREFFILENAME;
|
||||
|
||||
def (&nosound, "nosound");
|
||||
def (&nomusic, "nomusic");
|
||||
def (&show_version, "version");
|
||||
def (&show_help, "help", 'h');
|
||||
def (&WizardMode, "wizard");
|
||||
def (&Nograb, "nograb");
|
||||
def (&do_log, "log");
|
||||
def (&do_assert, "assert");
|
||||
def (&dumpinfo, "dumpinfo");
|
||||
def (&makepreview, "makepreview");
|
||||
def (&force_window, "window", 'w');
|
||||
def (OPT_GAME, "game", true);
|
||||
def (OPT_DATA, "data", 'd', true);
|
||||
def (OPT_LANG, "lang", 'l', true);
|
||||
def (OPT_PREF, "pref", 'p', true);
|
||||
}
|
||||
|
||||
void AP::on_option (int id, const string ¶m)
|
||||
{
|
||||
switch (id) {
|
||||
case OPT_GAME:
|
||||
gamename = param;
|
||||
break;
|
||||
case OPT_DATA:
|
||||
// we should be able to add several paths -- file.cc has does not yet support this
|
||||
// if (datapath.empty())
|
||||
datapath = param;
|
||||
// else
|
||||
// datapath = param + ":" + datapath;
|
||||
break;
|
||||
case OPT_LANG:
|
||||
app.argumentLanguage = param;
|
||||
break;
|
||||
case OPT_PREF:
|
||||
preffilename = param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AP::on_argument (const string &arg)
|
||||
{
|
||||
levelnames.push_back (arg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! Initialize enough of the game to be able to show error messages in
|
||||
the window, not on the console. */
|
||||
|
||||
|
||||
|
||||
/* -------------------- Application -------------------- */
|
||||
|
||||
Application::Application() : wizard_mode (false), nograb (false), language (""),
|
||||
defaultLanguage (""), argumentLanguage (""), errorInit (false),
|
||||
isMakePreviews (false) {
|
||||
}
|
||||
|
||||
|
||||
void Application::init(int argc, char **argv)
|
||||
{
|
||||
progCallPath = argv[0];
|
||||
copy(argv+1, argv+argc, back_inserter(args));
|
||||
|
||||
// parse commandline arguments -- needs args
|
||||
AP ap;
|
||||
ap.parse();
|
||||
|
||||
// ----- Evaluate command line arguments.
|
||||
// start with simple actions that do not need further initialization
|
||||
if (ap.show_help || ap.show_version) {
|
||||
printf("Enigma %s\n", getVersionInfo().c_str());
|
||||
if (ap.show_help) usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//
|
||||
if (ap.makepreview) {
|
||||
ap.force_window = true;
|
||||
ap.nosound = true;
|
||||
ap.nomusic = true;
|
||||
isMakePreviews = true;
|
||||
}
|
||||
|
||||
// initialize logfile -- needs ap
|
||||
if (ap.do_log)
|
||||
enigma::Log.rdbuf(cout.rdbuf());
|
||||
else
|
||||
enigma::Log.rdbuf(::nullbuffer);
|
||||
|
||||
// initialize assertion stop flag
|
||||
if (ap.do_assert)
|
||||
enigma::noAssert = false;
|
||||
|
||||
// initialize system datapaths -- needs ap, log
|
||||
systemCmdDataPath = ap.datapath;
|
||||
initSysDatapaths(ap.preffilename);
|
||||
|
||||
// initialize XML -- needs log, datapaths
|
||||
initXerces();
|
||||
|
||||
// initialize LUA - Run initialization scripts
|
||||
lua_State *L = lua::GlobalState();
|
||||
lua::CheckedDoFile(L, app.systemFS, "startup.lua");
|
||||
|
||||
// initialize preferences -- needs LUA, XML
|
||||
if (!options::Load()) {
|
||||
fprintf(stderr, _("Error in configuration file.\n"));
|
||||
fprintf(stderr, lua::LastError (lua::GlobalState()).c_str());
|
||||
}
|
||||
prefs = PreferenceManager::instance();
|
||||
|
||||
if (ap.force_window) {
|
||||
options::SetOption("FullScreen", false);
|
||||
}
|
||||
if (isMakePreviews) {
|
||||
options::SetOption("VideoMode", 0);
|
||||
}
|
||||
|
||||
// initialize user data paths -- needs preferences, system datapaths
|
||||
initUserDatapaths();
|
||||
|
||||
// set message language
|
||||
init_i18n();
|
||||
|
||||
// ----- Initialize object repositories
|
||||
world::Init();
|
||||
if (ap.dumpinfo) {
|
||||
world::DumpObjectInfo();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// ----- Initialize SDL library
|
||||
#ifdef WIN32
|
||||
// SDL_putenv("SDL_VIDEODRIVER=directx"); //needed for SDL 1.2.12 that favors GDI which crashes on SetGamma
|
||||
#endif
|
||||
int sdl_flags = SDL_INIT_VIDEO;
|
||||
if (enigma::WizardMode)
|
||||
sdl_flags |= SDL_INIT_NOPARACHUTE;
|
||||
if (SDL_Init(sdl_flags) < 0) {
|
||||
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
atexit(SDL_Quit);
|
||||
SDL_EnableUNICODE(1);
|
||||
const SDL_version* vi = SDL_Linked_Version();
|
||||
Log << ecl::strf("SDL Version: %u.%u.%u\n", vi->major, vi->minor, vi->patch);
|
||||
|
||||
vi = TTF_Linked_Version();
|
||||
Log << ecl::strf("SDL_ttf Version: %u.%u.%u\n", vi->major, vi->minor, vi->patch);
|
||||
if(TTF_Init() == -1) {
|
||||
fprintf(stderr, "Couldn't initialize SDL_ttf: %s\n", TTF_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vi = IMG_Linked_Version();
|
||||
Log << ecl::strf("SDL_image Version: %u.%u.%u\n", vi->major, vi->minor, vi->patch);
|
||||
#ifdef SDL_IMG_INIT
|
||||
int img_flags = IMG_INIT_PNG | IMG_INIT_JPG;
|
||||
if (IMG_Init(img_flags) & img_flags != img_flags) {
|
||||
fprintf(stderr, "Couldn't initialize SDL_image: %s\n", IMG_GetError());
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ----- Initialize video subsystem
|
||||
video::Init();
|
||||
video::SetCaption ("Enigma v" PACKAGE_VERSION);
|
||||
video::SetMouseCursor(enigma::LoadImage("cur-magic"), 4, 4);
|
||||
video::ShowMouse();
|
||||
SDL_ShowCursor(0);
|
||||
errorInit = true;
|
||||
|
||||
|
||||
// ----- Initialize sound subsystem
|
||||
sound::Init(!ap.nomusic, !ap.nosound);
|
||||
lua::CheckedDoFile (L, app.systemFS, "sound-defaults.lua");
|
||||
lua::DoSubfolderfile (L, "soundsets", "soundset.lua");
|
||||
|
||||
// ----- Initialize network layer
|
||||
if (enet_initialize () != 0) {
|
||||
fprintf (stderr, "An error occurred while initializing ENet.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
// ----- Load models
|
||||
display::Init();
|
||||
|
||||
// initialize application state
|
||||
state = StateManager::instance();
|
||||
|
||||
// ----- Load level packs -- needs state
|
||||
lev::Index::initGroups();
|
||||
oxyd::Init(!isMakePreviews); // Load oxyd data files - must be first to create correct proxies
|
||||
lev::PersistentIndex::registerPersistentIndices(ap.makepreview);
|
||||
if (!isMakePreviews) {
|
||||
lua::Dofile(L, "levels/index.lua");
|
||||
lua::DoSubfolderfile(L, "levels", "index.lua");
|
||||
lua::Dofile(L, "levels/index_user.lua");
|
||||
if (!ap.levelnames.empty()) {
|
||||
lev::Index::registerIndex(new lev::VolatileIndex(INDEX_STARTUP_PACK_NAME,
|
||||
INDEX_EVERY_GROUP, ap.levelnames, INDEX_STARTUP_PACK_LOCATION));
|
||||
lev::Index::setCurrentIndex(INDEX_STARTUP_PACK_NAME);
|
||||
}
|
||||
std::vector<std::string> emptyList;
|
||||
lev::Index::registerIndex(new lev::VolatileIndex(INDEX_SEARCH_PACK_NAME,
|
||||
INDEX_DEFAULT_GROUP, emptyList, INDEX_SEARCH_PACK_LOCATION));
|
||||
}
|
||||
|
||||
lev::Proxy::countLevels();
|
||||
|
||||
// ----- Initialize sound tables -- needs sound, oxyd, video (error messages!)
|
||||
sound::InitSoundSets();
|
||||
|
||||
#if MACOSX
|
||||
updateMac1_00();
|
||||
#endif
|
||||
|
||||
// initialize random
|
||||
enigma::Randomize();
|
||||
|
||||
//
|
||||
if (isMakePreviews) {
|
||||
std::set<lev::Proxy *> proxies = lev::Proxy::getProxies();
|
||||
int size = proxies.size();
|
||||
std::set<lev::Proxy *>::iterator it;
|
||||
std::string message = ecl::strf("Make %d previews on system path '%s'",
|
||||
size, systemAppDataPath.c_str());
|
||||
Log << message;
|
||||
|
||||
Screen *scr = video::GetScreen();
|
||||
GC gc (scr->get_surface());
|
||||
Font *f = enigma::GetFont("menufont");
|
||||
f->render (gc, 80, 240, message.c_str());
|
||||
set_color(gc, 200,200,200);
|
||||
hline(gc, 170, 280, 300);
|
||||
hline(gc, 170, 300, 300);
|
||||
vline(gc, 170, 280, 20);
|
||||
vline(gc, 470, 280, 20);
|
||||
scr->update_all ();
|
||||
scr->flush_updates();
|
||||
|
||||
int i = 0;
|
||||
for (it = proxies.begin(); it != proxies.end(); it++, i++) {
|
||||
gui::LevelPreviewCache::makeSystemPreview(*it, systemAppDataPath);
|
||||
vline(gc, 170 + i*300 / size, 280, 20);
|
||||
scr->update_all ();
|
||||
scr->flush_updates();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize score -- needs random init
|
||||
lev::ScoreManager::instance();
|
||||
}
|
||||
|
||||
std::string Application::getVersionInfo() {
|
||||
std::string versionInfo;
|
||||
double enigmaVersion;
|
||||
sscanf(PACKAGE_VERSION,"%4lf",&enigmaVersion);
|
||||
if (enigmaVersion >= ENIGMACOMPATIBITLITY)
|
||||
versionInfo = "v" PACKAGE_VERSION;
|
||||
else {
|
||||
versionInfo = "v" PACKAGE_VERSION
|
||||
" (development version - v" +
|
||||
ecl::strf("%.2f",ENIGMACOMPATIBITLITY) + " compatibility branch)";
|
||||
}
|
||||
return versionInfo;
|
||||
}
|
||||
|
||||
void Application::initSysDatapaths(const std::string &prefFilename)
|
||||
{
|
||||
std::string progDir; // directory path part of args[0]
|
||||
std::string progName; // filename part of args[0]
|
||||
bool progDirExists = split_path(progCallPath, &progDir, &progName);
|
||||
std::string systemPath = SYSTEM_DATA_DIR; // substituted by configure.ac
|
||||
bool haveHome = (getenv("HOME") != 0);
|
||||
#ifdef __MINGW32__
|
||||
// windows standard user specific application data directory path
|
||||
std::string winAppDataPath = ecl::ApplicationDataPath() + "/Enigma";
|
||||
#endif
|
||||
|
||||
// systemFS
|
||||
systemFS = new GameFS();
|
||||
#ifdef __MINGW32__
|
||||
if (!progDirExists) {
|
||||
// filename only -- working dir should be on enigma as enigma
|
||||
// should never be located on exec path on windows
|
||||
systemAppDataPath = "./data";
|
||||
} else {
|
||||
// a call from elsewhere -- absolute or relative path does not matter.
|
||||
// this enables calls from a commandline.
|
||||
systemAppDataPath = progDir + "/data";
|
||||
}
|
||||
#elif MACOSX
|
||||
// Mac OS X applications are self-contained bundles,
|
||||
// i.e., directories like "Enigma.app". Resources are
|
||||
// placed in those bundles under "Enigma.app/Contents/Resources",
|
||||
// the main executable would be "Enigma.app/Contents/MacOS/enigma".
|
||||
// Here, we get the executable name, clip off the last bit, chdir into it,
|
||||
// then chdir to ../Resources. The original SDL implementation chdirs to
|
||||
// "../../..", i.e. the directory the bundle is placed in. This breaks
|
||||
// the self-containedness.
|
||||
|
||||
systemAppDataPath = progDir + "/../Resources/data";
|
||||
|
||||
#else
|
||||
// Unix -- we get our data path from the installation
|
||||
systemAppDataPath = systemPath;
|
||||
#endif
|
||||
systemFS->append_dir(systemAppDataPath);
|
||||
if (!systemCmdDataPath.empty())
|
||||
systemFS->prepend_dir(systemCmdDataPath);
|
||||
Log << "systemFS = \"" << systemFS->getDataPath() << "\"\n";
|
||||
|
||||
// l10nPath
|
||||
l10nPath = LOCALEDIR; // defined in src/Makefile.am
|
||||
#ifdef __MINGW32__
|
||||
if (progDirExists) {
|
||||
l10nPath = progDir + "/" + l10nPath;
|
||||
}
|
||||
#elif MACOSX
|
||||
l10nPath = progDir + "/../Resources/locale";
|
||||
#endif
|
||||
Log << "l10nPath = \"" << l10nPath << "\"\n";
|
||||
|
||||
|
||||
// prefPath
|
||||
if (prefFilename.find_first_of(ecl::PathSeparators) != std::string::npos) {
|
||||
// pref is a path - absolute or home relative
|
||||
prefPath = ecl::ExpandPath(prefFilename);
|
||||
if (!ecl::FolderExists(prefPath))
|
||||
if(!ecl::FolderCreate(prefPath)) {
|
||||
fprintf(stderr, ("Error cannot create pref directory.\n"));
|
||||
exit(1);
|
||||
}
|
||||
userStdPath = prefPath; // default if pref is a path
|
||||
prefPath = prefPath + ecl::PathSeparator + "." + PREFFILENAME; // include pref in user data path
|
||||
} else if (haveHome) {
|
||||
prefPath = ecl::ExpandPath("~");
|
||||
if (!ecl::FolderExists(prefPath))
|
||||
// may happen on Windows
|
||||
if(!ecl::FolderCreate(prefPath)) {
|
||||
fprintf(stderr, _("Error Home directory does not exist.\n"));
|
||||
exit(1);
|
||||
}
|
||||
#ifdef MACOSX
|
||||
userStdPathMac1_00 = prefPath + "/.enigma";
|
||||
userStdPath = prefPath + "/Library/Application Support/Enigma";
|
||||
#else
|
||||
userStdPath = prefPath + "/.enigma";
|
||||
#endif
|
||||
prefPath = prefPath + ecl::PathSeparator + "." + prefFilename;
|
||||
#ifdef __MINGW32__
|
||||
} else if (!winAppDataPath.empty()) {
|
||||
if (!ecl::FolderExists(winAppDataPath))
|
||||
// may happen on Windows
|
||||
if(!ecl::FolderCreate(winAppDataPath)) {
|
||||
fprintf(stderr, _("Error Application Data directory does not exist.\n"));
|
||||
exit(1);
|
||||
}
|
||||
Log << "winAppDataPath " << winAppDataPath << "\n";
|
||||
userStdPath = winAppDataPath;
|
||||
prefPath = winAppDataPath + ecl::PathSeparator + "." + prefFilename;
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, _("Error Home directory does not exist.\n"));
|
||||
exit(1);
|
||||
}
|
||||
Log << "prefPath = \"" << prefPath << "\"\n";
|
||||
}
|
||||
|
||||
void Application::initXerces() {
|
||||
// init XML
|
||||
try {
|
||||
// Initialize to en_US - we don't know the user prefs yet
|
||||
// If more than the error messages should be influenced we would
|
||||
// have to terminate and reinit after reading the user prefs.
|
||||
XMLPlatformUtils::Initialize();
|
||||
|
||||
// Initialize transcoding service for XML <-> utf8
|
||||
XMLTransService::Codes initResult;
|
||||
xmlUtf8Transcoder = XMLPlatformUtils::fgTransService->
|
||||
makeNewTranscoderFor(XMLRecognizer::UTF_8, initResult,
|
||||
4096); // the block size is irrelevant for utf-8
|
||||
if (initResult != XMLTransService::Ok) {
|
||||
fprintf(stderr, _("Error in XML initialization.\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static const XMLCh ls[] = { chLatin_L, chLatin_S, chNull };
|
||||
static const XMLCh core[] = { chLatin_C, chLatin_O, chLatin_R, chLatin_E, chNull };
|
||||
domImplementationLS = (DOMImplementationLS*)
|
||||
(DOMImplementationRegistry::getDOMImplementation(ls));
|
||||
domImplementationCore = (DOMImplementation*)
|
||||
(DOMImplementationRegistry::getDOMImplementation(core));
|
||||
domParserErrorHandler = new DOMErrorReporter(&Log);
|
||||
domParserSchemaResolver = new DOMSchemaResolver();
|
||||
domSerErrorHandler = new DOMErrorReporter(&Log);
|
||||
|
||||
#if _XERCES_VERSION >= 30000
|
||||
domParser = domImplementationLS->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
|
||||
DOMConfiguration *config = domParser->getDomConfig();
|
||||
|
||||
config->setParameter(XMLUni::fgDOMNamespaces, true);
|
||||
config->setParameter(XMLUni::fgXercesSchema, true);
|
||||
config->setParameter(XMLUni::fgXercesSchemaFullChecking, true);
|
||||
config->setParameter(XMLUni::fgDOMValidate, true);
|
||||
config->setParameter(XMLUni::fgDOMDatatypeNormalization, true);
|
||||
config->setParameter(XMLUni::fgDOMErrorHandler, domParserErrorHandler);
|
||||
config->setParameter(XMLUni::fgDOMResourceResolver, domParserSchemaResolver);
|
||||
|
||||
domSer = domImplementationLS->createLSSerializer();
|
||||
config = domSer->getDomConfig();
|
||||
|
||||
config->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
|
||||
config->setParameter(XMLUni::fgDOMErrorHandler, domSerErrorHandler);
|
||||
|
||||
#else
|
||||
domParser = domImplementationLS->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
|
||||
|
||||
domParser->setFeature(XMLUni::fgDOMNamespaces, true);
|
||||
domParser->setFeature(XMLUni::fgXercesSchema, true);
|
||||
domParser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
|
||||
domParser->setFeature(XMLUni::fgDOMValidation, true);
|
||||
domParser->setFeature(XMLUni::fgDOMDatatypeNormalization, true);
|
||||
domParser->setErrorHandler(domParserErrorHandler);
|
||||
domParser->setEntityResolver(domParserSchemaResolver);
|
||||
|
||||
domSer = domImplementationLS->createDOMWriter();
|
||||
domSer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
|
||||
domSer->setErrorHandler(domSerErrorHandler);
|
||||
#endif
|
||||
}
|
||||
catch (...) {
|
||||
fprintf(stderr, _("Error in XML initialization.\n"));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::initUserDatapaths() {
|
||||
// userPath
|
||||
userPath = prefs->getString("UserPath");
|
||||
if (userPath.empty()) {
|
||||
#ifdef MACOSX
|
||||
if (prefs->getInt("_MacUpdate1.00") != 1)
|
||||
userPath = userStdPathMac1_00; // empty prefs user path is 1.00 std user path
|
||||
else {
|
||||
// first installation of Enigma on a Mac
|
||||
userPath = userStdPath; // use the new path
|
||||
prefs->setProperty("UserPath", std::string(XMLtoUtf8(LocalToXML(&userPath).x_str()).c_str()));
|
||||
prefs->setProperty("UserImagePath", std::string(XMLtoUtf8(LocalToXML(&userPath).x_str()).c_str()));
|
||||
prefs->setProperty("_MacUpdate1.00", 2);
|
||||
}
|
||||
#else
|
||||
userPath = userStdPath;
|
||||
#endif
|
||||
} else {
|
||||
userPath = XMLtoLocal(Utf8ToXML(userPath.c_str()).x_str()).c_str();
|
||||
}
|
||||
Log << "userPath = \"" << userPath << "\"\n";
|
||||
|
||||
// userImagePath
|
||||
userImagePath = prefs->getString("UserImagePath");
|
||||
if (userImagePath.empty()) {
|
||||
#ifdef MACOSX
|
||||
userImagePath = userStdPathMac1_00; // empty prefs user path is 1.00 std user path
|
||||
#else
|
||||
userImagePath = userStdPath;
|
||||
#endif
|
||||
} else {
|
||||
userImagePath = XMLtoLocal(Utf8ToXML(userImagePath.c_str()).x_str()).c_str();
|
||||
}
|
||||
Log << "userImagePath = \"" << userImagePath << "\"\n";
|
||||
|
||||
// resourceFS
|
||||
resourceFS = new GameFS();
|
||||
resourceFS->append_dir(systemAppDataPath);
|
||||
#ifdef MACOSX
|
||||
// set user-visible data paths -- use it for resource paths
|
||||
NSSearchPathEnumerationState cur=NSStartSearchPathEnumeration(NSLibraryDirectory, NSAllDomainsMask);
|
||||
char path[PATH_MAX];
|
||||
|
||||
while(cur) {
|
||||
cur=NSGetNextSearchPathEnumeration(cur, path);
|
||||
resourceFS->prepend_dir(std::string(path)+"/Application Support/Enigma");
|
||||
}
|
||||
#endif
|
||||
if (!systemCmdDataPath.empty())
|
||||
resourceFS->prepend_dir(systemCmdDataPath);
|
||||
resourceFS->prepend_dir(userPath);
|
||||
if (userImagePath != userPath)
|
||||
resourceFS->prepend_dir(userImagePath);
|
||||
Log << "resourceFS = \"" << resourceFS->getDataPath() << "\"\n";
|
||||
|
||||
// create levels/auto, levels/cross, levels/legacy_dat on userPath
|
||||
if (!ecl::FolderExists(userPath + "/levels/auto"))
|
||||
ecl::FolderCreate (userPath + "/levels/auto");
|
||||
if (!ecl::FolderExists(userPath + "/levels/cross"))
|
||||
ecl::FolderCreate (userPath + "/levels/cross");
|
||||
if (!ecl::FolderExists(userPath + "/levels/legacy_dat"))
|
||||
ecl::FolderCreate (userPath + "/levels/legacy_dat");
|
||||
if (!ecl::FolderExists(userPath + "/backup"))
|
||||
ecl::FolderCreate (userPath + "/backup");
|
||||
}
|
||||
|
||||
#ifdef MACOSX
|
||||
void Application::updateMac1_00() {
|
||||
if (prefs->getInt("_MacUpdate1.00") == 0 &&
|
||||
prefs->getString("UserPath").empty() &&
|
||||
prefs->getString("UserImagePath").empty()) {
|
||||
gui::ErrorMenu m(ecl::strf(N_("Mac OS X upgrade from Enigma 1.00\n\nThe default user data path has changed from\n %s \n\nto the visible data path\n %s \n\nIf ok Enigma will move your data to this new location.\nNote that you have to restart Enigma once for completion of this update."), userStdPathMac1_00.c_str(), userStdPath.c_str()),
|
||||
N_("OK"), N_("Never"), N_("Remind"));
|
||||
m.manage();
|
||||
if (m.isRejectQuit()) {
|
||||
prefs->setProperty("_MacUpdate1.00", 2);
|
||||
} else if (m.isLaterQuit()) {
|
||||
prefs->setProperty("_MacUpdate1.00", 0);
|
||||
} else { // OK move now
|
||||
Log << "Mac update\n";
|
||||
// move
|
||||
std::system(ecl::strf("mkdir '%s' && cd ~/.enigma && tar -cf - * | (cd '%s' && tar -xf -) && cd ~ && rm -rf ~/.enigma", userStdPath.c_str(), userStdPath.c_str()).c_str());
|
||||
setUserPath("");
|
||||
setUserImagePath("");
|
||||
prefs->setProperty("_MacUpdate1.00", 2);
|
||||
prefs->shutdown();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Application::init_i18n()
|
||||
{
|
||||
// Initialize the internationalization subsystem
|
||||
|
||||
// priorities:
|
||||
// language: command-line --- user option --- system (environment)
|
||||
// defaultLanguage: command-line --- system (environment)
|
||||
app.language = app.argumentLanguage;
|
||||
app.defaultLanguage = app.argumentLanguage;
|
||||
if (app.language == "") {
|
||||
options::GetOption("Language", app.language);
|
||||
}
|
||||
if (app.defaultLanguage == "") {
|
||||
app.defaultLanguage = ecl::SysMessageLocaleName();
|
||||
if (app.language == "") {
|
||||
app.language = app.defaultLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ENABLE_NLS)
|
||||
|
||||
nls::SetMessageLocale (app.language);
|
||||
|
||||
bindtextdomain (PACKAGE_NAME, app.l10nPath.c_str());
|
||||
|
||||
// SDL_ttf does not handle arbitrary encodings, so use UTF-8
|
||||
bind_textdomain_codeset (PACKAGE_NAME, "utf-8");
|
||||
textdomain (PACKAGE_NAME);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void Application::setLanguage(std::string newLanguage)
|
||||
{
|
||||
if (newLanguage == "") {
|
||||
language = defaultLanguage;
|
||||
}
|
||||
else {
|
||||
language = newLanguage;
|
||||
}
|
||||
nls::SetMessageLocale(language);
|
||||
}
|
||||
|
||||
void Application::setUserPath(std::string newPath) {
|
||||
std::string prefUserPath = (newPath == userStdPath) ? "" : newPath;
|
||||
if ((prefUserPath.empty() && userPath != userStdPath) || (!prefUserPath.empty() && prefUserPath != userPath)) {
|
||||
// set the new userPath - used for saves
|
||||
if (prefUserPath.empty())
|
||||
userPath = userStdPath;
|
||||
else
|
||||
userPath = prefUserPath;
|
||||
|
||||
// load all resources primarily from the new path but keep the old user path
|
||||
// because the user could not yet copy his user data to the new location
|
||||
resourceFS->prepend_dir(userPath);
|
||||
|
||||
// set the new path as the users preference - the standard path is saved as ""
|
||||
#ifdef MACOSX
|
||||
// 1.00 uses "" as "~/.enigma" - we have to store the complete path
|
||||
if (prefUserPath.empty()) prefUserPath = userStdPath;
|
||||
#endif
|
||||
prefs->setProperty("UserPath", std::string(XMLtoUtf8(LocalToXML(&prefUserPath).x_str()).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::setUserImagePath(std::string newPath) {
|
||||
std::string prefUserImagePath = (newPath == userStdPath) ? "" : newPath;
|
||||
if ((prefUserImagePath.empty() && userImagePath != userStdPath) || (!prefUserImagePath.empty() && prefUserImagePath != userImagePath)) {
|
||||
// set the new userImagePath - used for saves
|
||||
if (prefUserImagePath.empty())
|
||||
userImagePath = userStdPath;
|
||||
else
|
||||
userImagePath = prefUserImagePath;
|
||||
|
||||
// load all resources primarily from the new path but keep the old user path
|
||||
// because the user could not yet copy his user data to the new location
|
||||
if (userImagePath != userPath)
|
||||
resourceFS->prepend_dir(userImagePath);
|
||||
|
||||
// set the new path as the users preference - the standard path is saved as ""
|
||||
#ifdef MACOSX
|
||||
// 1.00 uses "" as "~/.enigma" - we have to store the complete path
|
||||
if (prefUserImagePath.empty()) prefUserImagePath = userStdPath;
|
||||
#endif
|
||||
prefs->setProperty("UserImagePath", std::string(XMLtoUtf8(LocalToXML(&prefUserImagePath).x_str()).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------- Functions -------------------- */
|
||||
|
||||
void Application::shutdown()
|
||||
{
|
||||
oxyd::Shutdown();
|
||||
world::Shutdown();
|
||||
display::Shutdown();
|
||||
if (!isMakePreviews) { // avoid saves on preview generation
|
||||
lev::RatingManager::instance()->save();
|
||||
if (lev::PersistentIndex::historyIndex != NULL)
|
||||
lev::PersistentIndex::historyIndex->save();
|
||||
lev::ScoreManager::instance()->shutdown();
|
||||
app.state->shutdown();
|
||||
app.prefs->shutdown();
|
||||
}
|
||||
// now we shutdown SDL - no error reports will be possible!
|
||||
app.errorInit = false;
|
||||
video::Shutdown();
|
||||
sound::Shutdown();
|
||||
enet_deinitialize();
|
||||
lua::ShutdownGlobal();
|
||||
XMLPlatformUtils::Terminate();
|
||||
#ifdef SDL_IMG_INIT
|
||||
IMG_Quit();
|
||||
#endif
|
||||
ClearFontCache();
|
||||
TTF_Quit();
|
||||
ClearImageCache();
|
||||
delete ::nullbuffer;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try {
|
||||
app.init(argc,argv);
|
||||
if (!app.isMakePreviews)
|
||||
gui::ShowMainMenu();
|
||||
app.shutdown();
|
||||
return 0;
|
||||
}
|
||||
catch (XFrontend &e) {
|
||||
cerr << "Error: " << e.what() << endl;
|
||||
std::string message = _("Fatal Error that causes the application to quit:\n\n");
|
||||
if (app.errorInit) {
|
||||
gui::ErrorMenu m(message + e.what(), N_("Quit"));
|
||||
m.manage();
|
||||
}
|
||||
}
|
||||
catch (ecl::XGeneric &e) {
|
||||
cerr << "Error: " << e.what() << endl;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
cerr << "Error: " << e.what() << endl;
|
||||
}
|
||||
catch (...) {
|
||||
cerr << "Uncaught exception...\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user