]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/options.cxx
Break viewmgr.hxx dependency on on viewer.hxx.
[flightgear.git] / src / Main / options.cxx
index f6de4c80d36598e5d3ff244a5af3c6a0eb5abda7..ad17068e682f48494c07c76a0aa5a11ab0b83697 100644 (file)
@@ -16,7 +16,7 @@
 //
 // 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 // $Id$
 
 #include <string.h>            // strcmp()
 #include <algorithm>
 
-#include STL_STRING
+#include <iostream>
+#include <string>
 
 #include <plib/ul.h>
 
 #include <simgear/math/sg_random.h>
+#include <simgear/props/props_io.hxx>
 #include <simgear/misc/sgstream.hxx>
 #include <simgear/misc/sg_path.hxx>
+#include <simgear/scene/material/mat.hxx>
 
 // #include <Include/general.hxx>
 // #include <Airports/simple.hxx>
 // #include <Cockpit/cockpit.hxx>
 // #include <FDM/flight.hxx>
-// #include <FDM/UIUCModel/uiuc_aircraftdir.h>
 
 #include <Autopilot/route_mgr.hxx>
 #include <GUI/gui.h>
 #include "options.hxx"
 #include "util.hxx"
 #include "viewmgr.hxx"
+#include <Main/viewer.hxx>
 
+using std::string;
+using std::sort;
+using std::cout;
+using std::cerr;
+using std::endl;
 
-SG_USING_STD(string);
-SG_USING_STD(sort);
-SG_USING_NAMESPACE(std);
-
+#ifndef VERSION
+#define VERSION "CVS "__DATE__
+#endif
 
 #define NEW_DEFAULT_MODEL_HZ 120
 
@@ -72,34 +79,23 @@ enum
     FG_OPTIONS_OK = 0,
     FG_OPTIONS_HELP = 1,
     FG_OPTIONS_ERROR = 2,
-    FG_OPTIONS_VERBOSE_HELP = 3,
-    FG_OPTIONS_SHOW_AIRCRAFT = 4
+    FG_OPTIONS_EXIT = 3,
+    FG_OPTIONS_VERBOSE_HELP = 4,
+    FG_OPTIONS_SHOW_AIRCRAFT = 5
 };
 
 static double
 atof( const string& str )
 {
-
-#ifdef __MWERKS__
-    // -dw- if ::atof is called, then we get an infinite loop
-    return std::atof( str.c_str() );
-#else
     return ::atof( str.c_str() );
-#endif
 }
 
 static int
 atoi( const string& str )
 {
-#ifdef __MWERKS__
-    // -dw- if ::atoi is called, then we get an infinite loop
-    return std::atoi( str.c_str() );
-#else
     return ::atoi( str.c_str() );
-#endif
 }
 
-
 /**
  * Set a few fail-safe default property values.
  *
@@ -111,7 +107,7 @@ void
 fgSetDefaults ()
 {
     // set a possibly independent location for scenery data
-    char *envp = ::getenv( "FG_SCENERY" );
+    const char *envp = ::getenv( "FG_SCENERY" );
 
     if ( envp != NULL ) {
        // fg_root could be anywhere, so default to environmental
@@ -127,8 +123,8 @@ fgSetDefaults ()
     fgSetDouble("/position/altitude-ft", -9999.0);
 
                                // Orientation
-    fgSetDouble("/orientation/heading-deg", 270);
-    fgSetDouble("/orientation/roll-deg", 0);
+    fgSetDouble("/orientation/heading-deg", 9999.0);
+    fgSetDouble("/orientation/roll-deg", 0.0);
     fgSetDouble("/orientation/pitch-deg", 0.424);
 
                                // Velocities
@@ -146,8 +142,8 @@ fgSetDefaults ()
     fgSetDouble("/sim/presets/latitude-deg", 9999.0);
     fgSetDouble("/sim/presets/altitude-ft", -9999.0);
 
-    fgSetDouble("/sim/presets/heading-deg", 270);
-    fgSetDouble("/sim/presets/roll-deg", 0);
+    fgSetDouble("/sim/presets/heading-deg", 9999.0);
+    fgSetDouble("/sim/presets/roll-deg", 0.0);
     fgSetDouble("/sim/presets/pitch-deg", 0.424);
 
     fgSetString("/sim/presets/speed-set", "knots");
@@ -172,15 +168,21 @@ fgSetDefaults ()
     // fgSetString("/sim/startup/mouse-pointer", "disabled");
     fgSetString("/sim/control-mode", "joystick");
     fgSetBool("/sim/auto-coordination", false);
-#if !defined(WIN32)
-    fgSetString("/sim/startup/browser-app", "netscape");
-#else
+#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
+    envp = ::getenv( "WEBBROWSER" );
+    if (!envp) envp = "netscape";
+    fgSetString("/sim/startup/browser-app", envp);
 #endif
     fgSetString("/sim/logging/priority", "alert");
 
                                // Features
-    fgSetBool("/sim/hud/antialiased", false);
+    fgSetBool("/sim/hud/color/antialiased", false);
     fgSetBool("/sim/hud/enable3d", true);
     fgSetBool("/sim/hud/visibility", false);
     fgSetBool("/sim/panel/visibility", true);
@@ -199,6 +201,8 @@ fgSetDefaults ()
     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);
     fgSetBool("/sim/rendering/horizon-effect", false);
     fgSetBool("/sim/rendering/enhanced-lighting", false);
@@ -225,14 +229,11 @@ fgSetDefaults ()
     fgSetBool("/sim/freeze/clock", false);
     fgSetBool("/sim/freeze/fuel", false);
 
-#ifdef FG_MPLAYER_AS
     fgSetString("/sim/multiplay/callsign", "callsign");
     fgSetString("/sim/multiplay/rxhost", "0");
     fgSetString("/sim/multiplay/txhost", "0");
     fgSetInt("/sim/multiplay/rxport", 0);
     fgSetInt("/sim/multiplay/txport", 0);
-#endif
-
 }
 
 static bool
@@ -490,7 +491,7 @@ parse_fov( const string& arg ) {
     if ( fov < FG_FOV_MIN ) { fov = FG_FOV_MIN; }
     if ( fov > FG_FOV_MAX ) { fov = FG_FOV_MAX; }
 
-    fgSetDouble("/sim/current-view/field-of-view", fov);
+    fgSetDouble("/sim/view[0]/config/default-field-of-view-deg", fov);
 
     // printf("parse_fov(): result = %.4f\n", fov);
 
@@ -502,7 +503,7 @@ parse_fov( const string& arg ) {
 //
 // Format is "--protocol=medium,direction,hz,medium_options,..."
 //
-//   protocol = { native, nmea, garmin, fgfs, rul, pve, etc. }
+//   protocol = { native, nmea, garmin, AV400, AV400Sim, fgfs, rul, pve, etc. }
 //   medium = { serial, socket, file, etc. }
 //   direction = { in, out, bi }
 //   hz = number of times to process channel per second (floating
@@ -526,64 +527,58 @@ parse_fov( const string& arg ) {
 static bool
 add_channel( const string& type, const string& channel_str ) {
     SG_LOG(SG_GENERAL, SG_INFO, "Channel string = " << channel_str );
-
     globals->get_channel_options_list()->push_back( type + "," + channel_str );
-    
-    // cout << "here" << endl;
-
     return true;
 }
 
-// The parse wp and parse flight-plan options don't work anymore, because 
+
+// The parse wp and parse flight-plan options don't work anymore, because
 // the route manager and the airport subsystems have not yet been initialized
-// at this stage. 
+// at this stage.
 
 // Parse --wp=ID[@alt]
-static void 
+static void
 parse_wp( const string& arg ) {
     string_list *waypoints = globals->get_initial_waypoints();
     if (!waypoints) {
         waypoints = new string_list;
+        globals->set_initial_waypoints(waypoints);
     }
     waypoints->push_back(arg);
-    globals->set_initial_waypoints(waypoints);
 }
 
 
 // Parse --flight-plan=[file]
-static bool 
+static bool
 parse_flightplan(const string& arg)
 {
-  string_list *waypoints = globals->get_initial_waypoints();
-  if (!waypoints)
-    waypoints = new string_list;
-  sg_gzifstream in(arg.c_str());
-  if ( !in.is_open() ) {
-    return false;
-  }
-  while ( true ) {
-    string line;
-    
-#if defined( macintosh )
-    getline( in, line, '\r' );
-#else
-    getline( in, line, '\n' );
-#endif
-    
-    // catch extraneous (DOS) line ending character
-    if ( line[line.length() - 1] < 32 ) {
-      line = line.substr( 0, line.length()-1 );
+    string_list *waypoints = globals->get_initial_waypoints();
+    if (!waypoints) {
+        waypoints = new string_list;
+        globals->set_initial_waypoints(waypoints);
     }
-    
-    if ( in.eof() ) {
-      break;
+
+    sg_gzifstream in(arg.c_str());
+    if ( !in.is_open() )
+        return false;
+
+    while ( true ) {
+        string line;
+        getline( in, line, '\n' );
+
+        // catch extraneous (DOS) line ending character
+        if ( line[line.length() - 1] < 32 )
+            line = line.substr( 0, line.length()-1 );
+
+        if ( in.eof() )
+            break;
+
+        waypoints->push_back(line);
     }
-    waypoints->push_back(line);
-  }
-  globals->set_initial_waypoints(waypoints);
-  return true;
+    return true;
 }
 
+
 static int
 fgOptLanguage( const char *arg )
 {
@@ -597,6 +592,8 @@ clearLocation ()
     fgSetString("/sim/presets/airport-id", "");
     fgSetString("/sim/presets/vor-id", "");
     fgSetString("/sim/presets/ndb-id", "");
+    fgSetString("/sim/presets/carrier", "");
+    fgSetString("/sim/presets/parkpos", "");
     fgSetString("/sim/presets/fix", "");
 }
 
@@ -616,6 +613,21 @@ fgOptNDB( const char * arg )
     return FG_OPTIONS_OK;
 }
 
+static int
+fgOptCarrier( const char * arg )
+{
+    clearLocation();
+    fgSetString("/sim/presets/carrier", arg);
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptParkpos( const char * arg )
+{
+    fgSetString("/sim/presets/parkpos", arg);
+    return FG_OPTIONS_OK;
+}
+
 static int
 fgOptFIX( const char * arg )
 {
@@ -860,7 +872,7 @@ fgSetupProxy( const char *arg )
 {
     string options = arg;
     string host, port, auth;
-    unsigned int pos;
+    string::size_type pos;
 
     host = port = auth = "";
     if ((pos = options.find("@")) != string::npos) 
@@ -984,7 +996,7 @@ fgOptRandomWind( const char *arg )
 static int
 fgOptWind( const char *arg )
 {
-    double min_hdg, max_hdg, speed, gust;
+    double min_hdg = 0.0, max_hdg = 0.0, speed = 0.0, gust = 0.0;
     if (!parse_wind( arg, &min_hdg, &max_hdg, &speed, &gust)) {
        SG_LOG( SG_GENERAL, SG_ALERT, "bad wind value " << arg );
        return FG_OPTIONS_ERROR;
@@ -1041,7 +1053,7 @@ fgOptConfig( const char *arg )
        readProperties(file, globals->get_props());
     } catch (const sg_exception &e) {
        string message = "Error loading config file: ";
-       message += e.getFormattedMessage();
+       message += e.getFormattedMessage() + e.getOrigin();
        SG_LOG(SG_INPUT, SG_ALERT, message);
        exit(2);
     }
@@ -1135,6 +1147,75 @@ fgOptDME( const char *arg )
     return FG_OPTIONS_OK;
 }
 
+static int
+fgOptLivery( const char *arg )
+{
+    string opt = arg;
+    string livery_path = "livery/" + opt;
+    fgSetString("/sim/model/texture-path", livery_path.c_str() );
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptScenario( const char *arg )
+{
+    SGPropertyNode_ptr ai_node = fgGetNode( "/sim/ai", true );
+    vector<SGPropertyNode_ptr> scenarii = ai_node->getChildren( "scenario" );
+    int index = -1;
+    for ( size_t i = 0; i < scenarii.size(); ++i ) {
+        int ind = scenarii[i]->getIndex();
+        if ( index < ind ) {
+            index = ind;
+        }
+    }
+    SGPropertyNode_ptr scenario = ai_node->getNode( "scenario", index + 1, true );
+    scenario->setStringValue( arg );
+    ai_node->setBoolValue( "enabled", true );
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptRunway( const char *arg )
+{
+    fgSetString("/sim/presets/runway", arg );
+    fgSetBool("/sim/presets/runway-requested", true );
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptParking( const char *arg )
+{
+    cerr << "Processing argument " << arg << endl;
+    fgSetString("/sim/presets/parking", arg );
+    fgSetBool  ("/sim/presets/parking-requested", true );
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptVersion( const char *arg )
+{
+    cerr << VERSION << endl;
+    cerr << "FG_ROOT=" << globals->get_fg_root() << endl;
+    cerr << "FG_HOME=" << fgGetString("/sim/fg-home") << endl;
+    return FG_OPTIONS_EXIT;
+}
+
+static int
+fgOptFpe(const char* arg)
+{
+    // Actually handled in bootstrap.cxx
+    return FG_OPTIONS_OK;
+}
+
+static int
+fgOptFgviewer(const char* arg)
+{
+    // Actually handled in bootstrap.cxx
+    return FG_OPTIONS_OK;
+}
+
+
+
 static map<string,size_t> fgOptionMap;
 
 /*
@@ -1155,7 +1236,7 @@ where:
              value set to the property if has_param is false
  func      : function called if type==OPTION_FUNC. if has_param is true,
              the value is passed to the function as a string, otherwise,
-             0 is passed. 
+             s_param is passed.
 
     For OPTION_DOUBLE and OPTION_INT, the parameter value is converted into a
     double or an integer and set to the property.
@@ -1166,12 +1247,12 @@ where:
 
 enum OptionType { OPTION_BOOL, OPTION_STRING, OPTION_DOUBLE, OPTION_INT, OPTION_CHANNEL, OPTION_FUNC };
 struct OptionDesc {
-    char *option;
+    const char *option;
     bool has_param;
     enum OptionType type;
-    char *property;
+    const char *property;
     bool b_param;
-    char *s_param;
+    const char *s_param;
     int (*func)( const char * );
     } fgOptionArray[] = {
        
@@ -1187,7 +1268,8 @@ struct OptionDesc {
     {"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-real-weather-fetch",   false, OPTION_BOOL,   "/environment/params/real-world-weather-fetch", false, "", 0 },
-    {"enable-real-weather-fetch",    false, OPTION_BOOL,   "/environment/params/real-world-weather-fetch", true, "", 0 },
+    {"enable-real-weather-fetch",    false, OPTION_BOOL,   "/environment/params/real-world-weather-fetch", true,  "", 0 },
+    {"metar",                        true,  OPTION_STRING, "/environment/metar/data", false, "", 0 },
     {"disable-ai-models",            false, OPTION_BOOL,   "/sim/ai/enabled", false, "", 0 },
     {"enable-ai-models",             false, OPTION_BOOL,   "/sim/ai/enabled", true, "", 0 },
     {"disable-freeze",               false, OPTION_BOOL,   "/sim/freeze/master", false, "", 0 },
@@ -1198,8 +1280,8 @@ struct OptionDesc {
     {"enable-clock-freeze",          false, OPTION_BOOL,   "/sim/freeze/clock", true, "", 0 },
     {"disable-hud-3d",               false, OPTION_BOOL,   "/sim/hud/enable3d", false, "", 0 },
     {"enable-hud-3d",                false, OPTION_BOOL,   "/sim/hud/enable3d", true, "", 0 },
-    {"disable-anti-alias-hud",       false, OPTION_BOOL,   "/sim/hud/antialiased", false, "", 0 },
-    {"enable-anti-alias-hud",        false, OPTION_BOOL,   "/sim/hud/antialiased", 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,   "/sim/auto-coordination", false, "", 0 },
     {"enable-auto-coordination",     false, OPTION_BOOL,   "/sim/auto-coordination", true, "", 0 },
@@ -1211,13 +1293,14 @@ struct OptionDesc {
     {"disable-sound",                false, OPTION_BOOL,   "/sim/sound/pause", true, "", 0 },
     {"enable-sound",                 false, OPTION_BOOL,   "/sim/sound/pause", false, "", 0 },
     {"airport",                      true,  OPTION_STRING, "/sim/presets/airport-id", false, "", 0 },
-    {"airport-id",                   true,  OPTION_STRING, "/sim/presets/airport-id", false, "", 0 },
-    {"runway",                       true,  OPTION_STRING, "/sim/presets/runway", false, "", 0 },
+    {"runway",                       true,  OPTION_FUNC,   "", false, "", fgOptRunway },
     {"vor",                          true,  OPTION_FUNC,   "", false, "", fgOptVOR },
     {"ndb",                          true,  OPTION_FUNC,   "", false, "", fgOptNDB },
+    {"carrier",                      true,  OPTION_FUNC,   "", false, "", fgOptCarrier },
+    {"parkpos",                      true,  OPTION_FUNC,   "", false, "", fgOptParkpos },
     {"fix",                          true,  OPTION_FUNC,   "", false, "", fgOptFIX },
-    {"offset-distance",              true,  OPTION_DOUBLE, "/sim/presets/offset-distance", false, "", 0 },
-    {"offset-azimuth",               true,  OPTION_DOUBLE, "/sim/presets/offset-azimuth", false, "", 0 },
+    {"offset-distance",              true,  OPTION_DOUBLE, "/sim/presets/offset-distance-nm", false, "", 0 },
+    {"offset-azimuth",               true,  OPTION_DOUBLE, "/sim/presets/offset-azimuth-deg", false, "", 0 },
     {"lon",                          true,  OPTION_FUNC,   "", false, "", fgOptLon },
     {"lat",                          true,  OPTION_FUNC,   "", false, "", fgOptLat },
     {"altitude",                     true,  OPTION_FUNC,   "", false, "", fgOptAltitude },
@@ -1264,12 +1347,15 @@ struct OptionDesc {
     {"aspect-ratio-multiplier",      true,  OPTION_DOUBLE, "/sim/current-view/aspect-ratio-multiplier", false, "", 0 },
     {"disable-fullscreen",           false, OPTION_BOOL,   "/sim/startup/fullscreen", false, "", 0 },
     {"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 },
     {"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 },
     {"geometry",                     true,  OPTION_FUNC,   "", false, "", fgOptGeometry },
@@ -1277,6 +1363,7 @@ struct OptionDesc {
     {"units-feet",                   false, OPTION_STRING, "/sim/startup/units", false, "feet", 0 },
     {"units-meters",                 false, OPTION_STRING, "/sim/startup/units", false, "meters", 0 },
     {"timeofday",                    true,  OPTION_STRING, "/sim/startup/time-offset-type", false, "noon", 0 },
+    {"season",                       true,  OPTION_STRING, "/sim/startup/season", false, "summer", 0 },
     {"time-offset",                  true,  OPTION_FUNC,   "", false, "", fgOptTimeOffset },
     {"time-match-real",              false, OPTION_STRING, "/sim/startup/time-offset-type", false, "system-offset", 0 },
     {"time-match-local",             false, OPTION_STRING, "/sim/startup/time-offset-type", false, "latitude-offset", 0 },
@@ -1296,6 +1383,8 @@ struct OptionDesc {
     {"native-fdm",                   true,  OPTION_CHANNEL, "", false, "", 0 },
     {"native-gui",                   true,  OPTION_CHANNEL, "", false, "", 0 },
     {"opengc",                       true,  OPTION_CHANNEL, "", false, "", 0 },
+    {"AV400",                        true,  OPTION_CHANNEL, "", false, "", 0 },
+    {"AV400Sim",                     true,  OPTION_CHANNEL, "", false, "", 0 },
     {"garmin",                       true,  OPTION_CHANNEL, "", false, "", 0 },
     {"nmea",                         true,  OPTION_CHANNEL, "", false, "", 0 },
     {"generic",                      true,  OPTION_CHANNEL, "", false, "", 0 },
@@ -1307,10 +1396,8 @@ struct OptionDesc {
     {"joyclient",                    true,  OPTION_CHANNEL, "", false, "", 0 },
     {"jsclient",                     true,  OPTION_CHANNEL, "", false, "", 0 },
     {"proxy",                        true,  OPTION_FUNC,    "", false, "", fgSetupProxy },
-#ifdef FG_MPLAYER_AS
     {"callsign",                     true, OPTION_STRING,  "sim/multiplay/callsign", false, "", 0 },
     {"multiplay",                    true,  OPTION_CHANNEL, "", false, "", 0 },
-#endif
     {"trace-read",                   true,  OPTION_FUNC,   "", false, "", fgOptTraceRead },
     {"trace-write",                  true,  OPTION_FUNC,   "", false, "", fgOptTraceWrite },
     {"log-level",                    true,  OPTION_FUNC,   "", false, "", fgOptLogLevel },
@@ -1325,6 +1412,7 @@ struct OptionDesc {
     {"flight-plan",                  true,  OPTION_FUNC,   "", false, "", fgOptFlightPlan },
     {"config",                       true,  OPTION_FUNC,   "", false, "", fgOptConfig },
     {"aircraft",                     true,  OPTION_STRING, "/sim/aircraft", false, "", 0 },
+    {"vehicle",                      true,  OPTION_STRING, "/sim/aircraft", false, "", 0 },
     {"failure",                      true,  OPTION_FUNC,   "", false, "", fgOptFailure },
     {"com1",                         true,  OPTION_DOUBLE, "/instrumentation/comm[0]/frequencies/selected-mhz", false, "", 0 },
     {"com2",                         true,  OPTION_DOUBLE, "/instrumentation/comm[1]/frequencies/selected-mhz", false, "", 0 },
@@ -1333,10 +1421,63 @@ struct OptionDesc {
     {"adf",                          true,  OPTION_FUNC,   "", false, "", fgOptADF },
     {"dme",                          true,  OPTION_FUNC,   "", false, "", fgOptDME },
     {"min-status",                   true,  OPTION_STRING,  "/sim/aircraft-min-status", false, "all", 0 },
+    {"livery",                       true,  OPTION_FUNC,   "", false, "", fgOptLivery },
+    {"ai-scenario",                  true,  OPTION_FUNC,   "", false, "", fgOptScenario },
+    {"parking-id",                   true,  OPTION_FUNC,   "", false, "", fgOptParking  },
+    {"version",                      false, OPTION_FUNC,   "", false, "", fgOptVersion },
+    {"enable-fpe",                  false, OPTION_FUNC,   "", false, "", fgOptFpe},
+    {"fgviewer",                    false, OPTION_FUNC,   "", false, "", fgOptFgviewer},
     {0}
 };
 
 
+// Set a property for the --prop: option. Syntax: --prop:[<type>:]<name>=<value>
+// <type> can be "double" etc. but also only the first letter "d".
+// Examples:  --prop:alpha=1  --prop:bool:beta=true  --prop:d:gamma=0.123
+static bool
+set_property(const string& arg)
+{
+    string::size_type pos = arg.find('=');
+    if (pos == arg.npos || pos == 0 || pos + 1 == arg.size())
+        return false;
+
+    string name = arg.substr(0, pos);
+    string value = arg.substr(pos + 1);
+    string type;
+    pos = name.find(':');
+
+    if (pos != name.npos && pos != 0 && pos + 1 != name.size()) {
+        type = name.substr(0, pos);
+        name = name.substr(pos + 1);
+    }
+    SGPropertyNode *n = fgGetNode(name.c_str(), true);
+
+    bool writable = n->getAttribute(SGPropertyNode::WRITE);
+    if (!writable)
+        n->setAttribute(SGPropertyNode::WRITE, true);
+
+    bool ret = false;
+    if (type.empty())
+        ret = n->setUnspecifiedValue(value.c_str());
+    else if (type == "s" || type == "string")
+        ret = n->setStringValue(value.c_str());
+    else if (type == "d" || type == "double")
+        ret = n->setDoubleValue(strtod(value.c_str(), 0));
+    else if (type == "f" || type == "float")
+        ret = n->setFloatValue(atof(value.c_str()));
+    else if (type == "l" || type == "long")
+        ret =  n->setLongValue(strtol(value.c_str(), 0, 0));
+    else if (type == "i" || type == "int")
+        ret =  n->setIntValue(atoi(value.c_str()));
+    else if (type == "b" || type == "bool")
+        ret =  n->setBoolValue(value == "true" || atoi(value.c_str()) != 0);
+
+    if (!writable)
+        n->setAttribute(SGPropertyNode::WRITE, false);
+    return ret;
+}
+
+
 // Parse a single option
 static int
 parse_option (const string& arg)
@@ -1361,24 +1502,18 @@ parse_option (const string& arg)
     } else if ( arg.find( "--show-aircraft") == 0) {
         return(FG_OPTIONS_SHOW_AIRCRAFT);
     } else if ( arg.find( "--prop:" ) == 0 ) {
-        string assign = arg.substr(7);
-       string::size_type pos = assign.find('=');
-       if ( pos == arg.npos || pos == 0 ) {
-           SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
-           return FG_OPTIONS_ERROR;
-       }
-       string name = assign.substr(0, pos);
-       string value = assign.substr(pos + 1);
-       fgSetString(name.c_str(), value.c_str());
-       // SG_LOG(SG_GENERAL, SG_INFO, "Setting default value of property "
-       //        << name << " to \"" << value << '"');
+        if (!set_property(arg.substr(7))) {
+            SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
+            return FG_OPTIONS_ERROR;
+        }
     } else if ( arg.find( "--" ) == 0 ) {
         size_t pos = arg.find( '=' );
-        string arg_name;
+        string arg_name, arg_value;
         if ( pos == string::npos ) {
             arg_name = arg.substr( 2 );
         } else {
             arg_name = arg.substr( 2, pos - 2 );
+            arg_value = arg.substr( pos + 1);
         }
         map<string,size_t>::iterator it = fgOptionMap.find( arg_name );
         if ( it != fgOptionMap.end() ) {
@@ -1388,9 +1523,9 @@ parse_option (const string& arg)
                     fgSetBool( pt->property, pt->b_param );
                     break;
                 case OPTION_STRING:
-                    if ( pt->has_param && pos != string::npos ) {
-                        fgSetString( pt->property, arg.substr( pos + 1 ).c_str() );
-                    } else if ( !pt->has_param && pos == string::npos ) {
+                    if ( pt->has_param && !arg_value.empty() ) {
+                        fgSetString( pt->property, arg_value.c_str() );
+                    } else if ( !pt->has_param && arg_value.empty() ) {
                         fgSetString( pt->property, pt->s_param );
                     } else if ( pt->has_param ) {
                         SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
@@ -1401,25 +1536,25 @@ parse_option (const string& arg)
                     }
                     break;
                 case OPTION_DOUBLE:
-                    if ( pos != string::npos ) {
-                        fgSetDouble( pt->property, atof( arg.substr( pos + 1 ) ) );
+                    if ( !arg_value.empty() ) {
+                        fgSetDouble( pt->property, atof( arg_value ) );
                     } else {
                         SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
                         return FG_OPTIONS_ERROR;
                     }
                     break;
                 case OPTION_INT:
-                    if ( pos != string::npos ) {
-                        fgSetInt( pt->property, atoi( arg.substr( pos + 1 ) ) );
+                    if ( !arg_value.empty() ) {
+                        fgSetInt( pt->property, atoi( arg_value ) );
                     } else {
                         SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
                         return FG_OPTIONS_ERROR;
                     }
                     break;
                 case OPTION_CHANNEL:
-                    if ( pt->has_param && pos != string::npos ) {
-                        add_channel( pt->option, arg.substr( pos + 1 ) );
-                    } else if ( !pt->has_param && pos == string::npos ) {
+                    if ( pt->has_param && !arg_value.empty() ) {
+                        add_channel( pt->option, arg_value );
+                    } else if ( !pt->has_param && arg_value.empty() ) {
                         add_channel( pt->option, pt->s_param );
                     } else if ( pt->has_param ) {
                         SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
@@ -1430,10 +1565,10 @@ parse_option (const string& arg)
                     }
                     break;
                 case OPTION_FUNC:
-                    if ( pt->has_param && pos != string::npos ) {
-                        return pt->func( arg.substr( pos + 1 ).c_str() );
-                    } else if ( !pt->has_param && pos == string::npos ) {
-                        return pt->func( 0 );
+                    if ( pt->has_param && !arg_value.empty() ) {
+                        return pt->func( arg_value.c_str() );
+                    } else if ( !pt->has_param && arg_value.empty() ) {
+                        return pt->func( pt->s_param );
                     } else if ( pt->has_param ) {
                         SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
                         return FG_OPTIONS_ERROR;
@@ -1487,6 +1622,9 @@ fgParseArgs (int argc, char **argv)
                fgShowAircraft(path, true);
                exit(0);
             }
+
+            else if (result == FG_OPTIONS_EXIT)
+               exit(0);
          }
        } else {
          in_options = false;
@@ -1517,20 +1655,9 @@ fgParseOptions (const string& path) {
     SG_LOG( SG_GENERAL, SG_INFO, "Processing config file: " << path );
 
     in >> skipcomment;
-#ifndef __MWERKS__
     while ( ! in.eof() ) {
-#else
-    char c = '\0';
-    while ( in.get(c) && c != '\0' ) {
-       in.putback(c);
-#endif
        string line;
-
-#if defined( macintosh )
-        getline( in, line, '\r' );
-#else
        getline( in, line, '\n' );
-#endif
 
         // catch extraneous (DOS) line ending character
         int i;
@@ -1563,7 +1690,7 @@ fgUsage (bool verbose)
 
     try {
         fgLoadProps("options.xml", &options_root);
-    } catch (const sg_exception &ex) {
+    } catch (const sg_exception &) {
         cout << "Unable to read the help file." << endl;
         cout << "Make sure the file options.xml is located in the FlightGear base directory," << endl;
         cout << "and the location of the base directory is specified by setting $FG_ROOT or" << endl;
@@ -1595,7 +1722,7 @@ fgUsage (bool verbose)
             SGPropertyNode *short_name = option[k]->getNode("short");
             SGPropertyNode *key = option[k]->getNode("key");
             SGPropertyNode *arg = option[k]->getNode("arg");
-            bool brief = option[k]->getNode("brief");
+            bool brief = option[k]->getNode("brief") != 0;
 
             if ((brief || verbose) && name) {
                 string tmp = name->getStringValue();
@@ -1612,21 +1739,21 @@ fgUsage (bool verbose)
                     tmp.append(", -");
                     tmp.append(short_name->getStringValue());
                 }
-
-                char cstr[96];
+                               
                 if (tmp.size() <= 25) {
-                    snprintf(cstr, 96, "   --%-27s", tmp.c_str());
+                    msg+= "   --";
+                    msg += tmp;
+                    msg.append( 27-tmp.size(), ' ');
                 } else {
-                    snprintf(cstr, 96, "\n   --%s\n%32c", tmp.c_str(), ' ');
+                    msg += "\n   --";
+                    msg += tmp + '\n';
+                    msg.append(32, ' ');
                 }
-
                 // There may be more than one <description> tag assosiated
                 // with one option
 
-                msg += cstr;
-                vector<SGPropertyNode_ptr>desc =
-                                          option[k]->getChildren("description");
-
+                vector<SGPropertyNode_ptr> desc;
+                desc = option[k]->getChildren("description");
                 if (desc.size() > 0) {
                    for ( unsigned int l = 0; l < desc.size(); l++) {
 
@@ -1641,9 +1768,7 @@ fgUsage (bool verbose)
                          string t_str = trans_desc[m]->getStringValue();
 
                          if ((m > 0) || ((l > 0) && m == 0)) {
-                            snprintf(cstr, 96, "%32c", ' ');
-                            msg += cstr;
-
+                            msg.append( 32, ' ');
                          }
 
                          // If the string is too large to fit on the screen,
@@ -1652,9 +1777,8 @@ fgUsage (bool verbose)
                          while ( t_str.size() > 47 ) {
 
                             unsigned int m = t_str.rfind(' ', 47);
-                            msg += t_str.substr(0, m);
-                            snprintf(cstr, 96, "\n%32c", ' ');
-                            msg += cstr;
+                            msg += t_str.substr(0, m) + '\n';
+                            msg.append( 32, ' ');
 
                             t_str.erase(t_str.begin(), t_str.begin() + m + 1);
                         }
@@ -1665,8 +1789,8 @@ fgUsage (bool verbose)
             }
         }
 
-        SGPropertyNode *name =
-                            locale->getNode(section[j]->getStringValue("name"));
+        SGPropertyNode *name;
+        name = locale->getNode(section[j]->getStringValue("name"));
 
         if (!msg.empty() && name) {
            cout << endl << name->getStringValue() << ":" << endl;
@@ -1691,9 +1815,9 @@ unsigned 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[][20]= {"alpha","beta","early-production","production",0}; 
+  const char* levels[] = {"alpha","beta","early-production","production"}; 
 
-  for (unsigned int i=0; i<(sizeof(levels)/sizeof(levels[0])-1);i++) 
+  for (size_t i=0; i<(sizeof(levels)/sizeof(levels[0]));i++) 
     if (strcmp(str,levels[i])==0)
       return i;
 
@@ -1708,7 +1832,7 @@ static void fgSearchAircraft(const SGPath &path, string_list &aircraft,
    ulDirEnt* dire;
    ulDir *dirp = ulOpenDir(path.str().c_str());
    if (dirp == NULL) {
-      cerr << "Unable to open aircraft directory." << endl;
+      cerr << "Unable to open aircraft directory '" << path.str() << '\'' << endl;
       exit(-1);
    }
 
@@ -1749,25 +1873,27 @@ static void fgSearchAircraft(const SGPath &path, string_list &aircraft,
                status = node->getNode("status");
           }
 
-          char cstr[96];
-         //additionally display status information where it is available
-          
-          if (strlen(dire->d_name) <= 27) {
-             snprintf(cstr, 96, "   %-27s  %s", dire->d_name,
-                      (desc) ? desc->getStringValue() : "");
-
-          } else {
-             snprintf(cstr, 96, "   %-27s\n%32c%s", dire->d_name, ' ',
-                      (desc) ? desc->getStringValue() : "");
+          //additionally display status information where it is available
+
+          string descStr("   ");
+          descStr += dire->d_name;
+          if (desc) {
+              if (descStr.size() <= 27+3) {
+                descStr.append(29+3-descStr.size(), ' ');
+              } else {
+                descStr += '\n';
+                descStr.append( 32, ' ');
+              }
+              descStr += desc->getStringValue();
           }
-
-         SGPropertyNode * required_status
+  
+          SGPropertyNode * required_status
                              = fgGetNode ("/sim/aircraft-min-status", true);
          
          // If the node holds the value "all", then there wasn't any status 
          // level specified, so we simply go ahead and output ALL aircraft
          if (strcmp(required_status->getStringValue(),"all")==0) {        
-                 aircraft.push_back(cstr);
+                 aircraft.push_back(descStr);
                  }
          else
          {
@@ -1779,7 +1905,7 @@ static void fgSearchAircraft(const SGPath &path, string_list &aircraft,
          //Compare (minimally) required status level with actual aircraft status:
           if ( getNumMaturity(status->getStringValue() ) >= 
                getNumMaturity(required_status->getStringValue() ) )
-                                 aircraft.push_back(cstr); }
+                                 aircraft.push_back(descStr); }
                                                  
          }