]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/options.cxx
Fix stray back-button in Qt launcher
[flightgear.git] / src / Main / options.cxx
index 2666b1b5bf27907d30243136d15df03cc4355af3..77cba345cb36dd7247fbd0199a789f8950ea9c84 100644 (file)
 
 #include <boost/foreach.hpp>
 
-#include <math.h>              // rint()
+#include <cmath>        // rint()
 #include <stdio.h>
-#include <stdlib.h>            // atof(), atoi()
-#include <string.h>            // strcmp()
+#include <stdlib.h>     // atof(), atoi()
+#include <string.h>     // strcmp()
 #include <algorithm>
 
 #include <iostream>
 #include <string>
+#include <sstream>
 
 #include <simgear/math/sg_random.h>
 #include <simgear/props/props_io.hxx>
 #include <simgear/sound/soundmgr_openal.hxx>
 #include <simgear/misc/strutils.hxx>
 #include <Autopilot/route_mgr.hxx>
+#include <Aircraft/replay.hxx>
+
 #include <GUI/gui.h>
+#include <GUI/MessageBox.hxx>
+#if defined(HAVE_QT)
+#include <GUI/QtLauncher.hxx>
+#include <GUI/SetupRootDialog.hxx>
+#endif
 
+#include <Main/locale.hxx>
 #include "globals.hxx"
 #include "fg_init.hxx"
 #include "fg_props.hxx"
 #include "options.hxx"
 #include "util.hxx"
-#include "viewmgr.hxx"
-#include <Main/viewer.hxx>
+#include "main.hxx"
+#include "locale.hxx"
+#include <Viewer/view.hxx>
+#include <Viewer/viewmgr.hxx>
 #include <Environment/presets.hxx>
+#include <Network/http/httpd.hxx>
+#include "AircraftDirVisitorBase.hxx"
 
 #include <osg/Version>
-
-#if defined( HAVE_VERSION_H ) && HAVE_VERSION_H
-#  include <Include/version.h>
-#  include <simgear/version.h>
-#else
-#  include <Include/no_version.h>
-#endif
-
-#ifdef __APPLE__
-#  include <CoreFoundation/CoreFoundation.h>
-#endif
+#include <Include/version.h>
+#include <simgear/version.h>
 
 using std::string;
 using std::sort;
@@ -82,22 +86,9 @@ using std::endl;
 using std::vector;
 using std::cin;
 
-#define NEW_DEFAULT_MODEL_HZ 120
-
-// defined in bootstrap.cxx
-extern char *homedir;
-extern char *hostname;
+using namespace flightgear;
 
-enum
-{
-    FG_OPTIONS_OK = 0,
-    FG_OPTIONS_HELP = 1,
-    FG_OPTIONS_ERROR = 2,
-    FG_OPTIONS_EXIT = 3,
-    FG_OPTIONS_VERBOSE_HELP = 4,
-    FG_OPTIONS_SHOW_AIRCRAFT = 5,
-    FG_OPTIONS_SHOW_SOUND_DEVICES = 6
-};
+#define NEW_DEFAULT_MODEL_HZ 120
 
 static flightgear::Options* shared_instance = NULL;
 
@@ -122,8 +113,7 @@ static int fgSetupProxy( const char *arg );
  * in case, we provide some initial sane values here. This method
  * should be invoked *before* reading any init files.
  */
-static void
-fgSetDefaults ()
+void fgSetDefaults ()
 {
 
                                // Position (deliberately out of range)
@@ -169,25 +159,11 @@ fgSetDefaults ()
     fgSetBool("/sim/presets/trim", false);
 
                                // Miscellaneous
-    fgSetBool("/sim/startup/game-mode", false);
     fgSetBool("/sim/startup/splash-screen", true);
-    fgSetBool("/sim/startup/intro-music", true);
     // we want mouse-pointer to have an undefined value if nothing is
     // specified so we can do the right thing for voodoo-1/2 cards.
     // fgSetString("/sim/startup/mouse-pointer", "disabled");
-    fgSetString("/sim/control-mode", "joystick");
     fgSetBool("/controls/flight/auto-coordination", false);
-#if defined(WIN32)
-    fgSetString("/sim/startup/browser-app", "webrun.bat");
-#elif defined(__APPLE__)
-    fgSetString("/sim/startup/browser-app", "open");
-#elif defined(sgi)
-    fgSetString("/sim/startup/browser-app", "launchWebJumper");
-#else
-    const char* browserEnv = ::getenv( "WEBBROWSER" );
-    if (!browserEnv) browserEnv = "netscape";
-    fgSetString("/sim/startup/browser-app", browserEnv);
-#endif
     fgSetString("/sim/logging/priority", "alert");
 
                                // Features
@@ -197,20 +173,19 @@ fgSetDefaults ()
     fgSetBool("/sim/panel/visibility", true);
     fgSetBool("/sim/sound/enabled", true);
     fgSetBool("/sim/sound/working", true);
+    fgSetBool("/sim/fgcom/enabled", false);
 
                                // Flight Model options
     fgSetString("/sim/flight-model", "jsb");
     fgSetString("/sim/aero", "c172");
     fgSetInt("/sim/model-hz", NEW_DEFAULT_MODEL_HZ);
-    fgSetInt("/sim/speed-up", 1);
+    fgSetDouble("/sim/speed-up", 1.0);
 
                                // Rendering options
     fgSetString("/sim/rendering/fog", "nicest");
     fgSetBool("/environment/clouds/status", true);
     fgSetBool("/sim/startup/fullscreen", false);
     fgSetBool("/sim/rendering/shading", true);
-    fgSetBool("/sim/rendering/skyblend", true);
-    fgSetBool("/sim/rendering/textures", true);
     fgTie( "/sim/rendering/filtering", SGGetTextureFilter, SGSetTextureFilter, false);
     fgSetInt("/sim/rendering/filtering", 1);
     fgSetBool("/sim/rendering/wireframe", false);
@@ -219,9 +194,9 @@ fgSetDefaults ()
     fgSetBool("/sim/rendering/distance-attenuation", false);
     fgSetBool("/sim/rendering/specular-highlight", true);
     fgSetString("/sim/rendering/materials-file", "materials.xml");
-    fgSetInt("/sim/startup/xsize", 800);
-    fgSetInt("/sim/startup/ysize", 600);
-    fgSetInt("/sim/rendering/bits-per-pixel", 16);
+    fgSetInt("/sim/startup/xsize", 1024);
+    fgSetInt("/sim/startup/ysize", 768);
+    fgSetInt("/sim/rendering/bits-per-pixel", 32);
     fgSetString("/sim/view-mode", "pilot");
     fgSetDouble("/sim/current-view/heading-offset-deg", 0);
 
@@ -246,18 +221,152 @@ fgSetDefaults ()
     fgSetInt("/sim/multiplay/rxport", 0);
     fgSetInt("/sim/multiplay/txport", 0);
     
-    fgSetString("/sim/version/flightgear", FLIGHTGEAR_VERSION);
-    fgSetString("/sim/version/simgear", SG_STRINGIZE(SIMGEAR_VERSION));
-    fgSetString("/sim/version/openscenegraph", osgGetVersion());
-    fgSetString("/sim/version/revision", REVISION);
-    fgSetInt("/sim/version/build-number", HUDSON_BUILD_NUMBER);
-    fgSetString("/sim/version/build-id", HUDSON_BUILD_ID);
-  
-  char* envp = ::getenv( "http_proxy" );
+    SGPropertyNode* v = globals->get_props()->getNode("/sim/version", true);
+    v->setValueReadOnly("flightgear", FLIGHTGEAR_VERSION);
+    v->setValueReadOnly("simgear", SG_STRINGIZE(SIMGEAR_VERSION));
+    v->setValueReadOnly("openscenegraph", osgGetVersion());
+    v->setValueReadOnly("openscenegraph-thread-safe-reference-counting",
+                         osg::Referenced::getThreadSafeReferenceCounting());
+    v->setValueReadOnly("revision", REVISION);
+    v->setValueReadOnly("build-number", HUDSON_BUILD_NUMBER);
+    v->setValueReadOnly("build-id", HUDSON_BUILD_ID);
+    v->setValueReadOnly("hla-support", bool(FG_HAVE_HLA));
+#if defined(FG_NIGHTLY)
+    v->setValueReadOnly("nightly-build", true);
+#else
+    v->setValueReadOnly("nightly-build", false);
+#endif
+    
+    char* envp = ::getenv( "http_proxy" );
     if( envp != NULL )
       fgSetupProxy( envp );
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// helper object to implement the --show-aircraft command.
+// resides here so we can share the fgFindAircraftInDir template above,
+// and hence ensure this command lists exectly the same aircraft as the normal
+// loading path.
+class ShowAircraft : public AircraftDirVistorBase
+{
+public:
+    ShowAircraft()
+    {
+        _minStatus = getNumMaturity(fgGetString("/sim/aircraft-min-status", "all"));
+    }
+    
+    
+    void show(const vector<SGPath> & path_list)
+    {
+               for (vector<SGPath>::const_iterator p = path_list.begin();
+                        p != path_list.end(); ++p)
+                       visitDir(*p, 0);
+        
+        simgear::requestConsole(); // ensure console is shown on Windows
+        
+        std::sort(_aircraft.begin(), _aircraft.end(), ciLessLibC());
+        cout << "Available aircraft:" << endl;
+        for ( unsigned int i = 0; i < _aircraft.size(); i++ ) {
+            cout << _aircraft[i] << endl;
+        }
+    }
+    
+private:
+    virtual VisitResult visit(const SGPath& path)
+    {
+        SGPropertyNode root;
+        try {
+            readProperties(path.str(), &root);
+        } catch (sg_exception& ) {
+            return VISIT_CONTINUE;
+        }
+        
+        int maturity = 0;
+        string descStr("   ");
+        descStr += path.file();
+        // trim common suffix from file names
+        int nPos = descStr.rfind("-set.xml");
+        if (nPos == (int)(descStr.size() - 8)) {
+            descStr.resize(nPos);
+        }
+        
+        SGPropertyNode *node = root.getNode("sim");
+        if (node) {
+            SGPropertyNode* desc = node->getNode("description");
+            // if a status tag is found, read it in
+            if (node->hasValue("status")) {
+                maturity = getNumMaturity(node->getStringValue("status"));
+            }
+            
+            if (desc) {
+                if (descStr.size() <= 27+3) {
+                    descStr.append(29+3-descStr.size(), ' ');
+                } else {
+                    descStr += '\n';
+                    descStr.append( 32, ' ');
+                }
+                descStr += desc->getStringValue();
+            }
+        } // of have 'sim' node
+        
+        if (maturity >= _minStatus) {
+            _aircraft.push_back(descStr);
+        }
+        
+        return VISIT_CONTINUE;
+    }
+    
+    
+    int getNumMaturity(const char * str)
+    {
+        // changes should also be reflected in $FG_ROOT/data/options.xml &
+        // $FG_ROOT/data/Translations/string-default.xml
+        const char* levels[] = {"alpha","beta","early-production","production"};
+        
+        if (!strcmp(str, "all")) {
+            return 0;
+        }
+        
+        for (size_t i=0; i<(sizeof(levels)/sizeof(levels[0]));i++)
+            if (strcmp(str,levels[i])==0)
+                return i;
+        
+        return 0;
+    }
+    
+    // recommended in Meyers, Effective STL when internationalization and embedded
+    // NULLs aren't an issue.  Much faster than the STL or Boost lex versions.
+    struct ciLessLibC : public std::binary_function<string, string, bool>
+    {
+        bool operator()(const std::string &lhs, const std::string &rhs) const
+        {
+            return strcasecmp(lhs.c_str(), rhs.c_str()) < 0 ? 1 : 0;
+        }
+    };
+    
+    int _minStatus;
+    string_list _aircraft;
+};
+
+/*
+ * Search in the current directory, and in on directory deeper
+ * for <aircraft>-set.xml configuration files and show the aircaft name
+ * and the contents of the<description> tag in a sorted manner.
+ *
+ * @parampath the directory to search for configuration files
+ */
+void fgShowAircraft(const vector<SGPath> &path_list)
+{
+    ShowAircraft s;
+    s.show(path_list);
+    
+#ifdef _MSC_VER
+    cout << "Hit a key to continue..." << endl;
+    std::cin.get();
+#endif
+}
+
+
 static bool
 parse_wind (const string &wind, double * min_hdg, double * max_hdg,
            double * speed, double * gust)
@@ -423,8 +532,8 @@ parse_date( const string& date, const char* timeType)
     int year,month,day,hour,minute,second;
     char *argument, *date_str;
 
-    SGTime CurrentTime = SGTime();
-    CurrentTime.update(0,0,0,0);
+    SGTime CurrentTime;
+    CurrentTime.update(SGGeod(),0,0);
 
     // FIXME This should obtain system/aircraft/GMT time depending on timeType
     pCurrentTime = CurrentTime.getGmt();
@@ -562,13 +671,6 @@ add_channel( const string& type, const string& channel_str ) {
     return true;
 }
 
-static int
-fgOptLanguage( const char *arg )
-{
-    globals->set_locale( fgInitLocale( arg ) );
-    return FG_OPTIONS_OK;
-}
-
 static void
 clearLocation ()
 {
@@ -742,14 +844,22 @@ fgOptMach( const char *arg )
 static int
 fgOptRoc( const char *arg )
 {
-    fgSetDouble("/velocities/vertical-speed-fps", atof(arg)/60);
+    fgSetDouble("/sim/presets/vertical-speed-fps", atof(arg)/60);
     return FG_OPTIONS_OK;
 }
 
 static int
 fgOptFgScenery( const char *arg )
 {
-    globals->append_fg_scenery(arg);
+    globals->append_fg_scenery(arg, true);
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptTerrasyncDir( const char *arg )
+{
+    globals->append_fg_scenery(arg, true);
+    fgSetString("/sim/terrasync/scenery-dir", arg);
     return FG_OPTIONS_OK;
 }
 
@@ -855,6 +965,27 @@ fgOptStartDateGmt( const char *arg )
     return FG_OPTIONS_OK;
 }
 
+static int
+fgOptJpgHttpd( const char * arg )
+{
+  SG_LOG(SG_ALL,SG_ALERT,
+   "the option --jpg-httpd is no longer supported! Please use --httpd instead."
+   " URL for the screenshot within the new httpd is http://YourFgServer:xxxx/screenshot");
+  return FG_OPTIONS_EXIT;
+}
+
+static int
+fgOptHttpd( const char * arg )
+{
+    // port may be any valid address:port notation
+    // like 127.0.0.1:8080
+    // or just the port 8080
+    string port = simgear::strutils::strip(string(arg));
+    if( port.empty() ) return FG_OPTIONS_ERROR;
+    fgSetString( string(flightgear::http::PROPERTY_ROOT).append("/options/listening-port").c_str(), port );
+    return FG_OPTIONS_OK;
+}
+
 static int
 fgSetupProxy( const char *arg )
 {
@@ -965,6 +1096,18 @@ fgOptVisibilityMiles( const char *arg )
     return FG_OPTIONS_OK;
 }
 
+static int
+fgOptMetar( const char *arg )
+{
+    // The given METAR string cannot be effective without disabling
+    // real weather fetching.
+    fgSetBool("/environment/realwx/enabled", false);
+    // The user-supplied METAR string
+    fgSetString("/environment/metar/data", arg);
+
+    return FG_OPTIONS_OK;
+}
+
 static int
 fgOptRandomWind( const char *arg )
 {
@@ -1029,12 +1172,12 @@ fgOptConfig( const char *arg )
 {
     string file = arg;
     try {
-       readProperties(file, globals->get_props());
+        readProperties(file, globals->get_props());
     } catch (const sg_exception &e) {
-       string message = "Error loading config file: ";
-       message += e.getFormattedMessage() + e.getOrigin();
-       SG_LOG(SG_INPUT, SG_ALERT, message);
-       exit(2);
+        string message = "Error loading config file: ";
+        message += e.getFormattedMessage() + e.getOrigin();
+        SG_LOG(SG_INPUT, SG_ALERT, message);
+        return FG_OPTIONS_ERROR;
     }
     return FG_OPTIONS_OK;
 }
@@ -1165,16 +1308,6 @@ fgOptScenario( const char *arg )
     }
     SGPropertyNode_ptr scenario = ai_node->getNode( "scenario", index + 1, true );
     scenario->setStringValue( arg );
-    ai_node->setBoolValue( "enabled", true );
-    return FG_OPTIONS_OK;
-}
-
-static int
-fgOptNoScenarios( const char *arg )
-{
-    SGPropertyNode_ptr ai_node = fgGetNode( "/sim/ai", true );
-    ai_node->removeChildren("scenario",false);
-    ai_node->setBoolValue( "enabled", false );
     return FG_OPTIONS_OK;
 }
 
@@ -1202,7 +1335,7 @@ fgOptVersion( const char *arg )
     cerr << "Revision: " << REVISION << endl;
     cerr << "Build-Id: " << HUDSON_BUILD_ID << endl;
     cerr << "FG_ROOT=" << globals->get_fg_root() << endl;
-    cerr << "FG_HOME=" << fgGetString("/sim/fg-home") << endl;
+    cerr << "FG_HOME=" << globals->get_fg_home() << endl;
     cerr << "FG_SCENERY=";
 
     int didsome = 0;
@@ -1215,6 +1348,7 @@ fgOptVersion( const char *arg )
     }
     cerr << endl;
     cerr << "SimGear version: " << SG_STRINGIZE(SIMGEAR_VERSION) << endl;
+    cerr << "OSG version: " << osgGetVersion() << endl;
     cerr << "PLIB version: " << PLIB_VERSION << endl;
     return FG_OPTIONS_EXIT;
 }
@@ -1240,6 +1374,30 @@ fgOptCallSign(const char * arg)
     return FG_OPTIONS_OK;
 }
 
+static int
+fgOptIgnoreAutosave(const char* arg)
+{
+    fgSetBool("/sim/startup/ignore-autosave", true);
+    // don't overwrite autosave on exit
+    fgSetBool("/sim/startup/save-on-exit", false);
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptEnableFreeze(const char* arg)
+{
+    fgSetBool("/sim/freeze/master", true);
+    fgSetBool("/sim/freeze/clock", true);
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptDisableFreeze(const char* arg)
+{
+    fgSetBool("/sim/freeze/master", false);
+    fgSetBool("/sim/freeze/clock", false);
+    return FG_OPTIONS_OK;
+}
 
 // Set a property for the --prop: option. Syntax: --prop:[<type>:]<name>=<value>
 // <type> can be "double" etc. but also only the first letter "d".
@@ -1288,6 +1446,43 @@ fgOptSetProperty(const char* raw)
   return ret ? FG_OPTIONS_OK : FG_OPTIONS_ERROR;
 }
 
+static int
+fgOptLoadTape(const char* arg)
+{
+  // load a flight recorder tape but wait until the fdm is initialized
+  class DelayedTapeLoader : SGPropertyChangeListener {
+  public:
+    DelayedTapeLoader( const char * tape ) :
+      _tape(tape)
+    {
+      SGPropertyNode_ptr n = fgGetNode("/sim/signals/fdm-initialized", true);
+      n->addChangeListener( this );
+    }
+
+    virtual ~ DelayedTapeLoader() {}
+
+    virtual void valueChanged(SGPropertyNode * node)
+    {
+      node->removeChangeListener( this );
+
+      // tell the replay subsystem to load the tape
+      FGReplay* replay = (FGReplay*) globals->get_subsystem("replay");
+      SGPropertyNode_ptr arg = new SGPropertyNode();
+      arg->setStringValue("tape", _tape );
+      arg->setBoolValue( "same-aircraft", 0 );
+      replay->loadTape(arg);
+
+      delete this; // commence suicide
+    }
+  private:
+    std::string _tape;
+
+  };
+
+  new DelayedTapeLoader(arg);
+  return FG_OPTIONS_OK;
+}
+
 
 
 /*
@@ -1330,26 +1525,31 @@ struct OptionDesc {
     int (*func)( const char * );
     } fgOptionArray[] = {
 
-    {"language",                     true,  OPTION_FUNC,   "", false, "", fgOptLanguage },
-    {"disable-game-mode",            false, OPTION_BOOL,   "/sim/startup/game-mode", false, "", 0 },
-    {"enable-game-mode",             false, OPTION_BOOL,   "/sim/startup/game-mode", true, "", 0 },
+    {"language",                     true,  OPTION_IGNORE, "", false, "", 0 },
+       {"console",                      false, OPTION_IGNORE,   "", false, "", 0 },
+    {"launcher",                     false, OPTION_IGNORE,   "", false, "", 0 },
+    {"disable-rembrandt",            false, OPTION_BOOL,   "/sim/rendering/rembrandt/enabled", false, "", 0 },
+    {"enable-rembrandt",             false, OPTION_BOOL,   "/sim/rendering/rembrandt/enabled", true, "", 0 },
+    {"renderer",                     true,  OPTION_STRING, "/sim/rendering/rembrandt/renderer", false, "", 0 },
     {"disable-splash-screen",        false, OPTION_BOOL,   "/sim/startup/splash-screen", false, "", 0 },
     {"enable-splash-screen",         false, OPTION_BOOL,   "/sim/startup/splash-screen", true, "", 0 },
-    {"disable-intro-music",          false, OPTION_BOOL,   "/sim/startup/intro-music", false, "", 0 },
-    {"enable-intro-music",           false, OPTION_BOOL,   "/sim/startup/intro-music", true, "", 0 },
     {"disable-mouse-pointer",        false, OPTION_STRING, "/sim/startup/mouse-pointer", false, "disabled", 0 },
     {"enable-mouse-pointer",         false, OPTION_STRING, "/sim/startup/mouse-pointer", false, "enabled", 0 },
     {"disable-random-objects",       false, OPTION_BOOL,   "/sim/rendering/random-objects", false, "", 0 },
     {"enable-random-objects",        false, OPTION_BOOL,   "/sim/rendering/random-objects", true, "", 0 },
+    {"disable-random-vegetation",    false, OPTION_BOOL,   "/sim/rendering/random-vegetation", false, "", 0 },
+    {"enable-random-vegetation",     false, OPTION_BOOL,   "/sim/rendering/random-vegetation", true, "", 0 },
+    {"disable-random-buildings",     false, OPTION_BOOL,   "/sim/rendering/random-buildings", false, "", 0 },
+    {"enable-random-buildings",      false, OPTION_BOOL,   "/sim/rendering/random-buildings", true, "", 0 },
     {"disable-real-weather-fetch",   false, OPTION_BOOL,   "/environment/realwx/enabled", false, "", 0 },
     {"enable-real-weather-fetch",    false, OPTION_BOOL,   "/environment/realwx/enabled", true,  "", 0 },
-    {"metar",                        true,  OPTION_STRING, "/environment/metar/data", false, "", 0 },
+    {"metar",                        true,  OPTION_FUNC,   "", false, "", fgOptMetar },
     {"disable-ai-models",            false, OPTION_BOOL,   "/sim/ai/enabled", false, "", 0 },
     {"enable-ai-models",             false, OPTION_BOOL,   "/sim/ai/enabled", true, "", 0 },
     {"disable-ai-traffic",           false, OPTION_BOOL,   "/sim/traffic-manager/enabled", false, "", 0 },
     {"enable-ai-traffic",            false, OPTION_BOOL,   "/sim/traffic-manager/enabled", true,  "", 0 },
-    {"disable-freeze",               false, OPTION_BOOL,   "/sim/freeze/master", false, "", 0 },
-    {"enable-freeze",                false, OPTION_BOOL,   "/sim/freeze/master", true, "", 0 },
+    {"disable-freeze",               false, OPTION_FUNC,   "", false, "", fgOptDisableFreeze },
+    {"enable-freeze",                false, OPTION_FUNC,   "", true, "", fgOptEnableFreeze },
     {"disable-fuel-freeze",          false, OPTION_BOOL,   "/sim/freeze/fuel", false, "", 0 },
     {"enable-fuel-freeze",           false, OPTION_BOOL,   "/sim/freeze/fuel", true, "", 0 },
     {"disable-clock-freeze",         false, OPTION_BOOL,   "/sim/freeze/clock", false, "", 0 },
@@ -1358,7 +1558,6 @@ struct OptionDesc {
     {"enable-hud-3d",                false, OPTION_BOOL,   "/sim/hud/enable3d[1]", true, "", 0 },
     {"disable-anti-alias-hud",       false, OPTION_BOOL,   "/sim/hud/color/antialiased", false, "", 0 },
     {"enable-anti-alias-hud",        false, OPTION_BOOL,   "/sim/hud/color/antialiased", true, "", 0 },
-    {"control",                      true,  OPTION_STRING, "/sim/control-mode", false, "", 0 },
     {"disable-auto-coordination",    false, OPTION_BOOL,   "/controls/flight/auto-coordination", false, "", 0 },
     {"enable-auto-coordination",     false, OPTION_BOOL,   "/controls/flight/auto-coordination", true, "", 0 },
     {"browser-app",                  true,  OPTION_STRING, "/sim/startup/browser-app", false, "", 0 },
@@ -1403,7 +1602,8 @@ struct OptionDesc {
     {"aero",                         true,  OPTION_STRING, "/sim/aero", false, "", 0 },
     {"aircraft-dir",                 true,  OPTION_IGNORE,   "", false, "", 0 },
     {"model-hz",                     true,  OPTION_INT,    "/sim/model-hz", false, "", 0 },
-    {"speed",                        true,  OPTION_INT,    "/sim/speed-up", false, "", 0 },
+    {"max-fps",                      true,  OPTION_DOUBLE, "/sim/frame-rate-throttle-hz", false, "", 0 },
+    {"speed",                        true,  OPTION_DOUBLE, "/sim/speed-up", false, "", 0 },
     {"trim",                         false, OPTION_BOOL,   "/sim/presets/trim", true, "", 0 },
     {"notrim",                       false, OPTION_BOOL,   "/sim/presets/trim", false, "", 0 },
     {"on-ground",                    false, OPTION_BOOL,   "/sim/presets/onground", true, "", 0 },
@@ -1429,19 +1629,19 @@ struct OptionDesc {
     {"enable-fullscreen",            false, OPTION_BOOL,   "/sim/startup/fullscreen", true, "", 0 },
     {"disable-save-on-exit",         false, OPTION_BOOL,   "/sim/startup/save-on-exit", false, "", 0 },
     {"enable-save-on-exit",          false, OPTION_BOOL,   "/sim/startup/save-on-exit", true, "", 0 },
+    {"read-only",                    false, OPTION_BOOL,   "/sim/fghome-readonly", true, "", 0 },
+    {"ignore-autosave",              false, OPTION_FUNC,   "", false, "", fgOptIgnoreAutosave },
+    {"restore-defaults",             false, OPTION_BOOL,   "/sim/startup/restore-defaults", true, "", 0 },
     {"shading-flat",                 false, OPTION_BOOL,   "/sim/rendering/shading", false, "", 0 },
     {"shading-smooth",               false, OPTION_BOOL,   "/sim/rendering/shading", true, "", 0 },
-    {"disable-skyblend",             false, OPTION_BOOL,   "/sim/rendering/skyblend", false, "", 0 },
-    {"enable-skyblend",              false, OPTION_BOOL,   "/sim/rendering/skyblend", true, "", 0 },
-    {"disable-textures",             false, OPTION_BOOL,   "/sim/rendering/textures", false, "", 0 },
-    {"enable-textures",              false, OPTION_BOOL,   "/sim/rendering/textures", true, "", 0 },
     {"texture-filtering",            false, OPTION_INT,    "/sim/rendering/filtering", 1, "", 0 },
     {"disable-wireframe",            false, OPTION_BOOL,   "/sim/rendering/wireframe", false, "", 0 },
     {"enable-wireframe",             false, OPTION_BOOL,   "/sim/rendering/wireframe", true, "", 0 },
     {"materials-file",               true,  OPTION_STRING, "/sim/rendering/materials-file", false, "", 0 },
     {"disable-terrasync",            false, OPTION_BOOL,   "/sim/terrasync/enabled", false, "", 0 },
     {"enable-terrasync",             false, OPTION_BOOL,   "/sim/terrasync/enabled", true, "", 0 },
-    {"terrasync-dir",                true,  OPTION_STRING, "/sim/terrasync/scenery-dir", false, "", 0 },
+    {"terrasync-dir",                true,  OPTION_FUNC,   "", false, "", fgOptTerrasyncDir },
+    {"download-dir",                 true,  OPTION_STRING, "/sim/paths/download-dir", false, "", 0 },
     {"geometry",                     true,  OPTION_FUNC,   "", false, "", fgOptGeometry },
     {"bpp",                          true,  OPTION_FUNC,   "", false, "", fgOptBpp },
     {"units-feet",                   false, OPTION_STRING, "/sim/startup/units", false, "feet", 0 },
@@ -1458,10 +1658,8 @@ struct OptionDesc {
     {"hud-culled",                   false, OPTION_STRING, "/sim/hud/frame-stat-type", false, "culled", 0 },
     {"atcsim",                       true,  OPTION_CHANNEL, "", false, "dummy", 0 },
     {"atlas",                        true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
-    {"httpd",                        true,  OPTION_CHANNEL, "", false, "", 0 },
-#ifdef FG_JPEG_SERVER
-    {"jpg-httpd",                    true,  OPTION_CHANNEL, "", false, "", 0 },
-#endif
+    {"httpd",                        true,  OPTION_FUNC   , "", false, "", fgOptHttpd },
+    {"jpg-httpd",                    true,  OPTION_FUNC,    "", false, "", fgOptJpgHttpd },
     {"native",                       true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"native-ctrls",                 true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"native-fdm",                   true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
@@ -1472,6 +1670,7 @@ struct OptionDesc {
     {"AV400WSimA",                   true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"AV400WSimB",                   true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"garmin",                       true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
+    {"igc",                          true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"nmea",                         true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"generic",                      true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"props",                        true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
@@ -1484,8 +1683,9 @@ struct OptionDesc {
     {"proxy",                        true,  OPTION_FUNC,    "", false, "", fgSetupProxy },
     {"callsign",                     true,  OPTION_FUNC,    "", false, "", fgOptCallSign},
     {"multiplay",                    true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
-#ifdef FG_HAVE_HLA
+#if FG_HAVE_HLA
     {"hla",                          true,  OPTION_CHANNEL, "", false, "", 0 },
+    {"hla-local",                    true,  OPTION_CHANNEL, "", false, "", 0 },
 #endif
     {"trace-read",                   true,  OPTION_FUNC | OPTION_MULTI,   "", false, "", fgOptTraceRead },
     {"trace-write",                  true,  OPTION_FUNC | OPTION_MULTI,   "", false, "", fgOptTraceWrite },
@@ -1504,6 +1704,10 @@ struct OptionDesc {
     {"aircraft",                     true,  OPTION_STRING, "/sim/aircraft", false, "", 0 },
     {"vehicle",                      true,  OPTION_STRING, "/sim/aircraft", false, "", 0 },
     {"failure",                      true,  OPTION_FUNC | OPTION_MULTI,   "", false, "", fgOptFailure },
+#ifdef ENABLE_IAX
+    {"enable-fgcom",                 false, OPTION_BOOL,   "/sim/fgcom/enabled", true, "", 0 },
+    {"disable-fgcom",                false, OPTION_BOOL,   "/sim/fgcom/enabled", false, "", 0 },
+#endif
     {"com1",                         true,  OPTION_DOUBLE, "/instrumentation/comm[0]/frequencies/selected-mhz", false, "", 0 },
     {"com2",                         true,  OPTION_DOUBLE, "/instrumentation/comm[1]/frequencies/selected-mhz", false, "", 0 },
     {"nav1",                         true,  OPTION_FUNC,   "", false, "", fgOptNAV1 },
@@ -1515,12 +1719,13 @@ struct OptionDesc {
     {"min-status",                   true,  OPTION_STRING,  "/sim/aircraft-min-status", false, "all", 0 },
     {"livery",                       true,  OPTION_FUNC,   "", false, "", fgOptLivery },
     {"ai-scenario",                  true,  OPTION_FUNC | OPTION_MULTI,   "", false, "", fgOptScenario },
-    {"disable-ai-scenarios",         false, OPTION_FUNC,   "", false, "", fgOptNoScenarios},
     {"parking-id",                   true,  OPTION_FUNC,   "", false, "", fgOptParking  },
     {"version",                      false, OPTION_FUNC,   "", false, "", fgOptVersion },
     {"enable-fpe",                   false, OPTION_IGNORE,   "", false, "", 0},
     {"fgviewer",                     false, OPTION_IGNORE,   "", false, "", 0},
+    {"no-default-config",            false, OPTION_IGNORE, "", false, "", 0},
     {"prop",                         true,  OPTION_FUNC | OPTION_MULTI,   "", false, "", fgOptSetProperty},
+    {"load-tape",                    true,  OPTION_FUNC,   "", false, "", fgOptLoadTape },
     {0}
 };
 
@@ -1564,6 +1769,22 @@ public:
     
     return it; // not found
   }
+
+    OptionValueVec::iterator findValue(const string& key)
+    {
+        OptionValueVec::iterator it = values.begin();
+        for (; it != values.end(); ++it) {
+            if (!it->desc) {
+                continue; // ignore markers
+            }
+
+            if (it->desc->option == key) {
+                return it;
+            }
+        } // of set values iteration
+        
+        return it; // not found
+    }
   
   OptionDesc* findOption(const string& key) const
   {
@@ -1660,7 +1881,7 @@ public:
   }
   
   /**
-   * given a current iterator into the values, find the preceeding group marker,
+   * given a current iterator into the values, find the preceding group marker,
    * or return the beginning of the value vector.
    */
   OptionValueVec::const_iterator rfindGroup(OptionValueVec::const_iterator pos) const
@@ -1676,8 +1897,9 @@ public:
   
   bool showHelp,
     verbose,
-    showAircraft;
-
+    showAircraft,
+    shouldLoadDefaultConfig;
+    
   OptionDescDict options;
   OptionValueVec values;
   simgear::PathList propertyFiles;
@@ -1698,6 +1920,7 @@ Options::Options() :
   p->showHelp = false;
   p->verbose = false;
   p->showAircraft = false;
+  p->shouldLoadDefaultConfig = true;
   
 // build option map
   OptionDesc *desc = &fgOptionArray[ 0 ];
@@ -1713,8 +1936,6 @@ Options::~Options()
   
 void Options::init(int argc, char **argv, const SGPath& appDataPath)
 {
-  fgSetDefaults();
-  
 // first, process the command line
   bool inOptions = true;
   for (int i=1; i<argc; ++i) {
@@ -1731,18 +1952,30 @@ void Options::init(int argc, char **argv, const SGPath& appDataPath)
       SGPath f(argv[i]);
       if (!f.exists()) {
         SG_LOG(SG_GENERAL, SG_ALERT, "config file not found:" << f.str());
-        return;
+      } else {
+        p->propertyFiles.push_back(f);
       }
-      
-      p->propertyFiles.push_back(f);
     }
   } // of arguments iteration
   p->insertGroupMarker(); // command line is one group
   
+  // establish log-level before anything else - otherwise it is not possible
+  // to show extra (debug/info/warning) messages for the start-up phase.
+  fgOptLogLevel(valueForOption("log-level", "alert").c_str());
+
+  if (!p->shouldLoadDefaultConfig) {
+    setupRoot(argc, argv);
+    return;
+  }
+  
 // then config files
   SGPath config;
-  
-  if( homedir && hostname && strlen(hostname) > 0 ) {
+  std::string homedir;
+  if (getenv("HOME")) {
+    homedir = getenv("HOME");
+  }
+    
+  if( !homedir.empty() && !hostname.empty() ) {
     // Check for ~/.fgfsrc.hostname
     config.set(homedir);
     config.append(".fgfsrc");
@@ -1752,7 +1985,7 @@ void Options::init(int argc, char **argv, const SGPath& appDataPath)
   }
   
 // Check for ~/.fgfsrc
-  if( homedir ) {
+  if( !homedir.empty() ) {
     config.set(homedir);
     config.append(".fgfsrc");
     readConfig(config);
@@ -1766,33 +1999,47 @@ void Options::init(int argc, char **argv, const SGPath& appDataPath)
   }
   
 // setup FG_ROOT
-  setupRoot();
+  setupRoot(argc, argv);
   
-// system.fgfsrc handling
-  if( hostname && strlen(hostname) > 0 ) {
+// system.fgfsrc is disabled, as we no longer allow anything in fgdata to set
+// fg-root/fg-home/fg-aircraft and hence control what files Nasal can access
+  std::string name_for_error = homedir.empty() ? appDataConfig.str() : config.str();
+  if( ! hostname.empty() ) {
     config.set(globals->get_fg_root());
     config.append( "system.fgfsrc" );
     config.concat( "." );
     config.concat( hostname );
-    readConfig(config);
+    if (config.exists()) {
+      flightgear::fatalMessageBox("Unsupported configuration",
+        "You have a " + config.str() + " file, which is no longer processed for security reasons",
+        "If you created this file intentionally, please move it to " + name_for_error);
+    }
   }
 
   config.set(globals->get_fg_root());
   config.append( "system.fgfsrc" );
-  readConfig(config);
+  if (config.exists()) {
+    flightgear::fatalMessageBox("Unsupported configuration",
+      "You have a " + config.str() + " file, which is no longer processed for security reasons",
+      "If you created this file intentionally, please move it to " + name_for_error);
+  }
 }
-  
-void Options::initAircraft()
+
+void Options::initPaths()
 {
-  BOOST_FOREACH(const string& paths, valuesForOption("fg-aircraft")) {
-    globals->append_aircraft_paths(paths);
-  }
-  
-  const char* envp = ::getenv("FG_AIRCRAFT");
-  if (envp) {
-    globals->append_aircraft_paths(envp);
-  }
+    BOOST_FOREACH(const string& paths, valuesForOption("fg-aircraft")) {
+        globals->append_aircraft_paths(paths);
+    }
+
+    const char* envp = ::getenv("FG_AIRCRAFT");
+    if (envp) {
+        globals->append_aircraft_paths(envp);
+    }
+
+}
 
+void Options::initAircraft()
+{
   string aircraft;
   if (isOptionSet("aircraft")) {
     aircraft = valueForOption("aircraft");
@@ -1806,18 +2053,39 @@ void Options::initAircraft()
   } else {
     SG_LOG(SG_INPUT, SG_INFO, "No user specified aircraft, using default" );
   }
-  
+    
   if (p->showAircraft) {
+       vector<SGPath> path_list;
+
     fgOptLogLevel( "alert" );
-    SGPath path( globals->get_fg_root() );
-    path.append("Aircraft");
-    fgShowAircraft(path);
+
+    // First place to check is the 'Aircraft' sub-directory in $FG_ROOT
+
+       path_list.push_back( SGPath( globals->get_fg_root() ) );
+       path_list.back().append("Aircraft");
+
+    // Additionally, aircraft may also be found in user-defined places
+       // (via $FG_AIRCRAFT or with the '--fg-aircraft' option)
+
+       string_list aircraft_paths = globals->get_aircraft_paths();
+       for (string_list::iterator it = aircraft_paths.begin();
+                it != aircraft_paths.end(); ++it)
+         path_list.push_back( SGPath(*it));
+
+    fgShowAircraft(path_list);
     exit(0);
   }
   
   if (isOptionSet("aircraft-dir")) {
-    // set this now, so it's available in FindAndCacheAircraft
-    fgSetString("/sim/aircraft-dir", valueForOption("aircraft-dir"));
+    SGPath aircraftDirPath(valueForOption("aircraft-dir"));
+
+    // Set this now, so it's available in FindAndCacheAircraft. Use realpath()
+    // as in FGGlobals::append_aircraft_path(), otherwise fgValidatePath()
+    // will deny access to resources under this path if one of its components
+    // is a symlink (which is not a problem, since it was given as is by the
+    // user---this is very different from a symlink *under* the aircraft dir
+    // or a scenery dir).
+    fgSetString("/sim/aircraft-dir", aircraftDirPath.realpath().c_str());
   }
 }
   
@@ -1828,7 +2096,9 @@ void Options::processArgResult(int result)
   else if (result == FG_OPTIONS_VERBOSE_HELP)
     p->verbose = true;
   else if (result == FG_OPTIONS_SHOW_AIRCRAFT) {
-    p->showAircraft = true;    
+    p->showAircraft = true;
+  } else if (result == FG_OPTIONS_NO_DEFAULT_CONFIG) {
+    p->shouldLoadDefaultConfig = false;
   } else if (result == FG_OPTIONS_SHOW_SOUND_DEVICES) {
     SGSoundMgr smgr;
     
@@ -1843,6 +2113,7 @@ void Options::processArgResult(int result)
       cout << i << ".  \"" << devices[i] << "\"" << endl;
     }
     devices.clear();
+    smgr.stop();
     exit(0);
   } else if (result == FG_OPTIONS_EXIT) {
     exit(0);
@@ -1888,6 +2159,9 @@ int Options::parseOption(const string& s)
   } else if ( (s == "--verbose") || (s == "-v") ) {
     // verbose help/usage request
     return FG_OPTIONS_VERBOSE_HELP;
+  } else if ((s == "--console") || (s == "-c")) {
+         simgear::requestConsole();
+         return FG_OPTIONS_OK;
   } else if (s.find("-psn") == 0) {
     // on Mac, when launched from the GUI, we are passed the ProcessSerialNumber
     // as an argument (and no others). Silently ignore the argument here.
@@ -1896,6 +2170,8 @@ int Options::parseOption(const string& s)
     return(FG_OPTIONS_SHOW_AIRCRAFT);
   } else if ( s.find( "--show-sound-devices") == 0) {
     return(FG_OPTIONS_SHOW_SOUND_DEVICES);
+  } else if ( s.find( "--no-default-config") == 0) {
+    return FG_OPTIONS_NO_DEFAULT_CONFIG;
   } else if ( s.find( "--prop:") == 0) {
     // property setting has a slightly different syntax, so fudge things
     OptionDesc* desc = p->findOption("prop");
@@ -1918,7 +2194,7 @@ int Options::parseOption(const string& s)
     
     return addOption(key, value);
   } else {
-    SG_LOG(SG_GENERAL, SG_ALERT, "unknown option:" << s);
+      flightgear::modalMessageBox("Unknown option", "Unknown command-line option: " + s);
     return FG_OPTIONS_ERROR;
   }
 }
@@ -1927,14 +2203,14 @@ int Options::addOption(const string &key, const string &value)
 {
   OptionDesc* desc = p->findOption(key);
   if (!desc) {
-    SG_LOG(SG_GENERAL, SG_ALERT, "unknown option:" << key);
+    flightgear::modalMessageBox("Unknown option", "Unknown command-line option: " + key);
     return FG_OPTIONS_ERROR;
   }
   
   if (!(desc->type & OPTION_MULTI)) {
     OptionValueVec::const_iterator it = p->findValue(key);
     if (it != p->values.end()) {
-      SG_LOG(SG_GENERAL, SG_INFO, "multiple values forbidden for option:" << key << ", ignoring:" << value);
+      SG_LOG(SG_GENERAL, SG_WARN, "multiple values forbidden for option:" << key << ", ignoring:" << value);
       return FG_OPTIONS_OK;
     }
   }
@@ -1942,7 +2218,35 @@ int Options::addOption(const string &key, const string &value)
   p->values.push_back(OptionValue(desc, value));
   return FG_OPTIONS_OK;
 }
-  
+
+int Options::setOption(const string &key, const string &value)
+{
+    OptionDesc* desc = p->findOption(key);
+    if (!desc) {
+        flightgear::modalMessageBox("Unknown option", "Unknown command-line option: " + key);
+        return FG_OPTIONS_ERROR;
+    }
+
+    if (!(desc->type & OPTION_MULTI)) {
+        OptionValueVec::iterator it = p->findValue(key);
+        if (it != p->values.end()) {
+            // remove existing valye
+            p->values.erase(it);
+        }
+    }
+    
+    p->values.push_back(OptionValue(desc, value));
+    return FG_OPTIONS_OK;
+}
+
+void Options::clearOption(const std::string& key)
+{
+    OptionValueVec::iterator it = p->findValue(key);
+    for (; it != p->values.end(); it = p->findValue(key)) {
+        p->values.erase(it);
+    }
+}
+
 bool Options::isOptionSet(const string &key) const
 {
   OptionValueVec::const_iterator it = p->findValue(key);
@@ -1975,14 +2279,29 @@ string_list Options::valuesForOption(const std::string& key) const
   
   return result;
 }
-  
-void Options::processOptions()
+
+string defaultDownloadDir()
+{
+#if defined(SG_WINDOWS)
+    SGPath p(SGPath::documents());
+    p.append("FlightGear");
+#else
+    SGPath p(globals->get_fg_home());
+#endif
+    return p.str();
+}
+
+OptionResult Options::processOptions()
 {
+  // establish locale before showing help (this selects the default locale,
+  // when no explicit option was set)
+  globals->get_locale()->selectLanguage(valueForOption("language").c_str());
+
   // now FG_ROOT is setup, process various command line options that bail us
   // out quickly, but rely on aircraft / root settings
   if (p->showHelp) {
     showUsage();
-    exit(0);
+      return FG_OPTIONS_EXIT;
   }
   
   // processing order is complicated. We must process groups LIFO, but the
@@ -1991,7 +2310,7 @@ void Options::processOptions()
   // in practice this means system.fgfsrc must be *processed* before
   // .fgfsrc, which must be processed before the command line args, and so on.
   OptionValueVec::const_iterator groupEnd = p->values.end();
-    
+
   while (groupEnd != p->values.begin()) {
     OptionValueVec::const_iterator groupBegin = p->rfindGroup(groupEnd);
   // run over the group in FIFO order
@@ -2002,24 +2321,23 @@ void Options::processOptions()
       {
           case FG_OPTIONS_ERROR:
               showUsage();
-              exit(-1); // exit and return an error
+              return FG_OPTIONS_ERROR;
+              
           case FG_OPTIONS_EXIT:
-              exit(0);  // clean exit
-              break;
+              return FG_OPTIONS_EXIT;
+              
           default:
               break;
       }
+        if (it->desc) {
+            SG_LOG(SG_GENERAL, SG_INFO, "\toption:" << it->desc->option << " = " << it->value);
+        }
     }
     
     groupEnd = groupBegin;
   }
-  
+
   BOOST_FOREACH(const SGPath& file, p->propertyFiles) {
-    if (!file.exists()) {
-      SG_LOG(SG_GENERAL, SG_ALERT, "config file not found:" << file.str());
-      continue;
-    }
-    
     SG_LOG(SG_GENERAL, SG_INFO,
            "Reading command-line property file " << file.str());
          readProperties(file.str(), globals->get_props());
@@ -2028,51 +2346,73 @@ void Options::processOptions()
 // now options are process, do supplemental fixup
   const char *envp = ::getenv( "FG_SCENERY" );
   if (envp) {
-    globals->append_fg_scenery(envp);
+    globals->append_fg_scenery(envp, true);
   }
-    
+
+// download dir fix-up
+    string downloadDir = simgear::strutils::strip(fgGetString("/sim/paths/download-dir"));
+    if (downloadDir.empty()) {
+        downloadDir = defaultDownloadDir();
+        SG_LOG(SG_GENERAL, SG_INFO, "Using default download dir: " << downloadDir);
+    } else {
+        simgear::Dir d(downloadDir);
+        if (!d.exists()) {
+            SG_LOG(SG_GENERAL, SG_INFO, "Creating requested download dir: " << downloadDir);
+            d.create(0755);
+        }
+    }
+
 // terrasync directory fixup
-  if (fgGetBool("/sim/terrasync/enabled")) {
-    string terrasyncDir = fgGetString("/sim/terrasync/scenery-dir");
-    if (terrasyncDir.empty()) {
-      SGPath p(fgGetString("/sim/fg-home"));
+    string terrasyncDir = simgear::strutils::strip(fgGetString("/sim/terrasync/scenery-dir"));
+  if (terrasyncDir.empty()) {
+      SGPath p(downloadDir);
       p.append("TerraSync");
-      if (!p.exists()) {
-        simgear::Dir dd(p);
-        dd.create(0700);
-      }
-      
       terrasyncDir = p.str();
-      SG_LOG(SG_GENERAL, SG_INFO,
-             "Using default TerraSync dir: " << terrasyncDir);
-      fgSetString("/sim/terrasync/scenery-dir", terrasyncDir);
-    }
-    
+
+      simgear::Dir d(terrasyncDir);
+      if (!d.exists()) {
+          d.create(0755);
+      }
+
+         SG_LOG(SG_GENERAL, SG_INFO, "Using default TerraSync: " << terrasyncDir);
+      fgSetString("/sim/terrasync/scenery-dir", p.str());
+  } else {
+      SG_LOG(SG_GENERAL, SG_INFO, "Using explicit TerraSync dir: " << terrasyncDir);
+  }
+
+    // check if we setup a scenery path so far
+    bool addFGDataScenery = globals->get_fg_scenery().empty();
+
+    // always add the terrasync location, regardless of whether terrasync
+    // is enabled or not. This allows us to toggle terrasync on/off at
+    // runtime and have things work as expected
     const string_list& scenery_paths(globals->get_fg_scenery());
     if (std::find(scenery_paths.begin(), scenery_paths.end(), terrasyncDir) == scenery_paths.end()) {
-      // terrasync dir is not in the scenery paths, add it
-      globals->append_fg_scenery(terrasyncDir);
+        // terrasync dir is not in the scenery paths, add it
+        globals->append_fg_scenery(terrasyncDir);
     }
-  }
-  
-  if (globals->get_fg_scenery().empty()) {
-    // no scenery paths set *at all*, use the data in FG_ROOT
-    SGPath root(globals->get_fg_root());
-    root.append("Scenery");
-    globals->append_fg_scenery(root.str());
-  }
+
+    if (addFGDataScenery) {
+        // no scenery paths set at all, use the data in FG_ROOT
+        // ensure this path is added last
+        SGPath root(globals->get_fg_root());
+        root.append("Scenery");
+        globals->append_fg_scenery(root.str());
+    }
+
+  return FG_OPTIONS_OK;
 }
   
 void Options::showUsage() const
 {
   fgOptLogLevel( "alert" );
   
-  SGPropertyNode *locale = globals->get_locale();
+  FGLocale *locale = globals->get_locale();
   SGPropertyNode options_root;
   
-  SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on Windows
+  simgear::requestConsole(); // ensure console is shown on Windows
   cout << endl;
-  
+
   try {
     fgLoadProps("options.xml", &options_root);
   } catch (const sg_exception &) {
@@ -2083,17 +2423,23 @@ void Options::showUsage() const
     
     exit(-1);
   }
-  
+
   SGPropertyNode *options = options_root.getNode("options");
   if (!options) {
     SG_LOG( SG_GENERAL, SG_ALERT,
            "Error reading options.xml: <options> directive not found." );
     exit(-1);
   }
-  
-  SGPropertyNode *usage = locale->getNode(options->getStringValue("usage"));
+
+  if (!locale->loadResource("options"))
+  {
+      cout << "Unable to read the language resource." << endl;
+      exit(-1);
+  }
+
+  const char* usage = locale->getLocalizedString(options->getStringValue("usage"), "options");
   if (usage) {
-    cout << "Usage: " << usage->getStringValue() << endl;
+    cout << usage << endl;
   }
   
   vector<SGPropertyNode_ptr>section = options->getChildren("section");
@@ -2134,21 +2480,17 @@ void Options::showUsage() const
           msg += tmp + '\n';
           msg.append(32, ' ');
         }
-        // There may be more than one <description> tag assosiated
+        // There may be more than one <description> tag associated
         // with one option
         
         vector<SGPropertyNode_ptr> desc;
         desc = option[k]->getChildren("description");
-        if (desc.size() > 0) {
+        if (! desc.empty()) {
           for ( unsigned int l = 0; l < desc.size(); l++) {
-            
-            // There may be more than one translation line.
-            
             string t = desc[l]->getStringValue();
-            SGPropertyNode *n = locale->getNode("strings");
-            vector<SGPropertyNode_ptr>trans_desc =
-            n->getChildren(t.substr(8).c_str());
-            
+
+            // There may be more than one translation line.
+            vector<SGPropertyNode_ptr>trans_desc = locale->getLocalizedStrings(t.c_str(),"options");
             for ( unsigned int m = 0; m < trans_desc.size(); m++ ) {
               string t_str = trans_desc[m]->getStringValue();
               
@@ -2174,19 +2516,18 @@ void Options::showUsage() const
       }
     }
     
-    SGPropertyNode *name;
-    name = locale->getNode(section[j]->getStringValue("name"));
-    
+    const char* name = locale->getLocalizedString(section[j]->getStringValue("name"),"options");
     if (!msg.empty() && name) {
-      cout << endl << name->getStringValue() << ":" << endl;
+      cout << endl << name << ":" << endl;
       cout << msg;
       msg.erase();
     }
   }
   
   if ( !p->verbose ) {
-    cout << endl;
-    cout << "For a complete list of options use --help --verbose" << endl;
+    const char* verbose_help = locale->getLocalizedString(options->getStringValue("verbose-help"),"options");
+    if (verbose_help)
+        cout << endl << verbose_help << endl;
   }
 #ifdef _MSC_VER
   std::cout << "Hit a key to continue..." << std::endl;
@@ -2200,33 +2541,13 @@ string Options::platformDefaultRoot() const
   return "../data";
 }
 
-#elif defined(_WIN32)
+#elif defined(SG_WINDOWS)
 string Options::platformDefaultRoot() const
 {
   return "..\\data";
 }
-#elif defined(__APPLE__)
-string Options::platformDefaultRoot() const
-{
-  /*
-   The following code looks for the base package inside the application 
-   bundle, in the standard Contents/Resources location. 
-   */
-  CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
-  
-  // look for a 'data' subdir
-  CFURLRef dataDir = CFURLCreateCopyAppendingPathComponent(NULL, resourcesUrl, CFSTR("data"), true);
-  
-  // now convert down to a path, and the a c-string
-  CFStringRef path = CFURLCopyFileSystemPath(dataDir, kCFURLPOSIXPathStyle);
-  string root = CFStringGetCStringPtr(path, CFStringGetSystemEncoding());
-  
-  CFRelease(resourcesUrl);
-  CFRelease(dataDir);
-  CFRelease(path);
-  
-  return root;
-}
+#elif defined(SG_MAC)
+// platformDefaultRoot defined in CocoaHelpers.mm
 #else
 string Options::platformDefaultRoot() const
 {
@@ -2234,44 +2555,99 @@ string Options::platformDefaultRoot() const
 }
 #endif
   
-void Options::setupRoot()
+void Options::setupRoot(int argc, char **argv)
 {
-  string root;
+    string root;
+    bool usingDefaultRoot = false;
+
   if (isOptionSet("fg-root")) {
     root = valueForOption("fg-root"); // easy!
+    SG_LOG(SG_GENERAL, SG_INFO, "set from command-line argument: fg_root = " << root );
   } else {
   // Next check if fg-root is set as an env variable
     char *envp = ::getenv( "FG_ROOT" );
     if ( envp != NULL ) {
       root = envp;
+      SG_LOG(SG_GENERAL, SG_INFO, "set from FG_ROOT env var: fg_root = " << root );
     } else {
-      root = platformDefaultRoot();
+#if defined(HAVE_QT)
+        flightgear::initApp(argc, argv);
+        root = SetupRootDialog::restoreUserSelectedRoot();
+#endif
+        if (root.empty()) {
+            usingDefaultRoot = true;
+            root = platformDefaultRoot();
+            SG_LOG(SG_GENERAL, SG_INFO, "platform default fg_root = " << root );
+        } else {
+            SG_LOG(SG_GENERAL, SG_INFO, "Qt launcher set fg_root = " << root );
+        }
     }
   } 
   
-  SG_LOG(SG_INPUT, SG_INFO, "fg_root = " << root );
   globals->set_fg_root(root);
-  
-// validate it
-  static char required_version[] = FLIGHTGEAR_VERSION;
-  string base_version = fgBasePackageVersion();
-  if ( !(base_version == required_version) ) {
-    // tell the operator how to use this application
+    static char required_version[] = FLIGHTGEAR_VERSION;
+    string base_version = fgBasePackageVersion(root);
+
+#if defined(HAVE_QT)
+    // note we never end up here if restoring a user selected root via
+    // the Qt GUI, since that code pre-validates the path. But if we're using
+    // a command-line, env-var or default root this check can fail and
+    // we still want to use the GUI in that case
+    if (base_version != required_version) {
+        flightgear::initApp(argc, argv);
+        SetupRootDialog::runDialog(usingDefaultRoot);
+    }
+#else
+    // validate it
+    if (base_version.empty()) {
+        flightgear::fatalMessageBox("Base package not found",
+                                    "Required data files not found, check your installation.",
+                                    "Looking for base-package files at: '" + root + "'");
+
+        exit(-1);
+    }
     
-    SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on windows
-    cerr << endl << "Base package check failed:" << endl \
-    << "  Version " << base_version << " found at: " \
-    << globals->get_fg_root() << endl \
-    << "  Version " << required_version << " is required." << endl \
-    << "Please upgrade/downgrade base package and set the path to your fgdata" << endl \
-    << "with --fg-root=path_to_your_fgdata" << endl;
-#ifdef _MSC_VER
-    cerr << "Hit a key to continue..." << endl;
-    cin.get();
-#endif
+    if (base_version != required_version) {
+      flightgear::fatalMessageBox("Base package version mismatch",
+                                  "Version check failed: please check your installation.",
+                                  "Found data files for version '" + base_version +
+                                  "' at '" + globals->get_fg_root() + "', version '"
+                                  + required_version + "' is required.");
+
     exit(-1);
   }
+#endif
 }
   
+bool Options::shouldLoadDefaultConfig() const
+{
+  return p->shouldLoadDefaultConfig;
+}
+
+bool Options::checkForArg(int argc, char* argv[], const char* checkArg)
+{
+    for (int i = 0; i < argc; ++i) {
+        char* arg = argv[i];
+        if (arg == 0) {
+            continue;
+        }
+
+        if (*arg != '-') { // we only care about args with a leading hypen
+            continue;
+        }
+
+        arg++;
+        if (*arg == '-') { // skip double hypens
+            arg++;
+        }
+
+        if (strcmp(arg, checkArg) == 0) {
+            return true;
+        }
+    }
+    
+    return false;
+}
+    
 } // of namespace flightgear