]> git.mxchange.org Git - flightgear.git/blob - src/Main/options.cxx
Minor tweaks to sound subsystem update rates.
[flightgear.git] / src / Main / options.cxx
1 // options.cxx -- class to handle command line options
2 //
3 // Written by Curtis Olson, started April 1998.
4 //
5 // Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #include <simgear/compiler.h>
29 #include <simgear/misc/exception.hxx>
30
31 #include <math.h>               // rint()
32 #include <stdio.h>
33 #include <stdlib.h>             // atof(), atoi()
34 #include <string.h>             // strcmp()
35
36 #include STL_STRING
37
38 #include <simgear/math/sg_random.h>
39 #include <simgear/misc/sgstream.hxx>
40 #include <simgear/misc/sg_path.hxx>
41 #include <simgear/route/route.hxx>
42 #include <simgear/route/waypoint.hxx>
43
44 // #include <Include/general.hxx>
45 // #include <Airports/simple.hxx>
46 // #include <Cockpit/cockpit.hxx>
47 // #include <FDM/flight.hxx>
48 // #include <FDM/UIUCModel/uiuc_aircraftdir.h>
49 #ifdef FG_NETWORK_OLK
50 #  include <NetworkOLK/network.h>
51 #endif
52
53 #include <GUI/gui.h>
54
55 #include "globals.hxx"
56 #include "fg_init.hxx"
57 #include "fg_props.hxx"
58 #include "options.hxx"
59 #include "viewmgr.hxx"
60
61 SG_USING_STD(string);
62 SG_USING_NAMESPACE(std);
63
64
65 #define NEW_DEFAULT_MODEL_HZ 120
66
67 enum
68 {
69     FG_OPTIONS_OK = 0,
70     FG_OPTIONS_HELP = 1,
71     FG_OPTIONS_ERROR = 2,
72     FG_OPTIONS_VERBOSE_HELP = 3
73 };
74
75 static double
76 atof( const string& str )
77 {
78
79 #ifdef __MWERKS__ 
80     // -dw- if ::atof is called, then we get an infinite loop
81     return std::atof( str.c_str() );
82 #else
83     return ::atof( str.c_str() );
84 #endif
85 }
86
87 static int
88 atoi( const string& str )
89 {
90 #ifdef __MWERKS__ 
91     // -dw- if ::atoi is called, then we get an infinite loop
92     return std::atoi( str.c_str() );
93 #else
94     return ::atoi( str.c_str() );
95 #endif
96 }
97
98
99 /**
100  * Set a few fail-safe default property values.
101  *
102  * These should all be set in $FG_ROOT/preferences.xml, but just
103  * in case, we provide some initial sane values here. This method 
104  * should be invoked *before* reading any init files.
105  */
106 void
107 fgSetDefaults ()
108 {
109     // set a possibly independent location for scenery data
110     char *envp = ::getenv( "FG_SCENERY" );
111
112     if ( envp != NULL ) {
113         // fg_root could be anywhere, so default to environmental
114         // variable $FG_ROOT if it is set.
115         globals->set_fg_scenery(envp);
116     } else {
117         // Otherwise, default to Scenery being in $FG_ROOT/Scenery
118         globals->set_fg_scenery("");
119     }
120                                 // Position (deliberately out of range)
121     fgSetDouble("/position/longitude-deg", 9999.0);
122     fgSetDouble("/position/latitude-deg", 9999.0);
123     fgSetDouble("/position/altitude-ft", -9999.0);
124
125                                 // Orientation
126     fgSetDouble("/orientation/heading-deg", 270);
127     fgSetDouble("/orientation/roll-deg", 0);
128     fgSetDouble("/orientation/pitch-deg", 0.424);
129
130                                 // Velocities
131     fgSetString("/sim/startup/speed-set", "knots");
132     fgSetDouble("/velocities/uBody-fps", 0.0);
133     fgSetDouble("/velocities/vBody-fps", 0.0);
134     fgSetDouble("/velocities/wBody-fps", 0.0);
135     fgSetDouble("/velocities/speed-north-fps", 0.0);
136     fgSetDouble("/velocities/speed-east-fps", 0.0);
137     fgSetDouble("/velocities/speed-down-fps", 0.0);
138     fgSetDouble("/velocities/airspeed-kt", 0.0);
139     fgSetDouble("/velocities/mach", 0.0);
140
141                                 // Miscellaneous
142     fgSetBool("/sim/startup/game-mode", false);
143     fgSetBool("/sim/startup/splash-screen", true);
144     fgSetBool("/sim/startup/intro-music", true);
145     // we want mouse-pointer to have an undefined value if nothing is
146     // specified so we can do the right thing for voodoo-1/2 cards.
147     // fgSetString("/sim/startup/mouse-pointer", "disabled");
148     fgSetString("/sim/control-mode", "joystick");
149     fgSetBool("/sim/auto-coordination", false);
150 #if !defined(WIN32)
151     fgSetString("/sim/startup/browser-app", "netscape");
152 #else
153     fgSetString("/sim/startup/browser-app", "webrun.bat");
154 #endif
155                                 // Features
156     fgSetBool("/sim/hud/visibility", false);
157     fgSetBool("/sim/panel/visibility", true);
158     fgSetBool("/sim/sound/audible", true);
159     fgSetBool("/sim/hud/antialiased", false);
160
161                                 // Flight Model options
162     fgSetString("/sim/flight-model", "jsb");
163     fgSetString("/sim/aero", "c172");
164     fgSetInt("/sim/model-hz", NEW_DEFAULT_MODEL_HZ);
165     fgSetInt("/sim/speed-up", 1);
166     fgSetBool("/sim/startup/trim", false);
167     fgSetBool("/sim/startup/onground", true);
168
169                                 // Rendering options
170     fgSetString("/sim/rendering/fog", "nicest");
171     fgSetBool("/environment/clouds/status", true);
172     fgSetBool("/sim/startup/fullscreen", false);
173     fgSetBool("/sim/rendering/shading", true);
174     fgSetBool("/sim/rendering/skyblend", true);
175     fgSetBool("/sim/rendering/textures", true);
176     fgSetBool("/sim/rendering/wireframe", false);
177     fgSetInt("/sim/startup/xsize", 800);
178     fgSetInt("/sim/startup/ysize", 600);
179     fgSetInt("/sim/rendering/bits-per-pixel", 16);
180     fgSetString("/sim/view-mode", "pilot");
181     fgSetDouble("/sim/current-view/heading-offset-deg", 0);
182     fgSetDouble("/environment/visibility-m", 20000);
183
184                                 // HUD options
185     fgSetString("/sim/startup/units", "feet");
186     fgSetString("/sim/hud/frame-stat-type", "tris");
187         
188                                 // Time options
189     fgSetInt("/sim/startup/time-offset", 0);
190     fgSetString("/sim/startup/time-offset-type", "system-offset");
191     fgSetLong("/sim/time/cur-time-override", 0);
192
193     fgSetBool("/sim/networking/network-olk", false);
194     fgSetString("/sim/networking/call-sign", "Johnny");
195
196                                 // Freeze options
197     fgSetBool("/sim/freeze/master", false);
198     fgSetBool("/sim/freeze/position", false);
199     fgSetBool("/sim/freeze/clock", false);
200     fgSetBool("/sim/freeze/fuel", false);
201 }
202
203
204 static bool
205 parse_wind (const string &wind, double * min_hdg, double * max_hdg,
206             double * speed, double * gust)
207 {
208   string::size_type pos = wind.find('@');
209   if (pos == string::npos)
210     return false;
211   string dir = wind.substr(0, pos);
212   string spd = wind.substr(pos+1);
213   pos = dir.find(':');
214   if (pos == string::npos) {
215     *min_hdg = *max_hdg = atof(dir.c_str());
216   } else {
217     *min_hdg = atof(dir.substr(0,pos).c_str());
218     *max_hdg = atof(dir.substr(pos+1).c_str());
219   }
220   pos = spd.find(':');
221   if (pos == string::npos) {
222     *speed = *gust = atof(spd.c_str());
223   } else {
224     *speed = atof(spd.substr(0,pos).c_str());
225     *gust = atof(spd.substr(pos+1).c_str());
226   }
227   return true;
228 }
229
230 // parse a time string ([+/-]%f[:%f[:%f]]) into hours
231 static double
232 parse_time(const string& time_in) {
233     char *time_str, num[256];
234     double hours, minutes, seconds;
235     double result = 0.0;
236     int sign = 1;
237     int i;
238
239     time_str = (char *)time_in.c_str();
240
241     // printf("parse_time(): %s\n", time_str);
242
243     // check for sign
244     if ( strlen(time_str) ) {
245         if ( time_str[0] == '+' ) {
246             sign = 1;
247             time_str++;
248         } else if ( time_str[0] == '-' ) {
249             sign = -1;
250             time_str++;
251         }
252     }
253     // printf("sign = %d\n", sign);
254
255     // get hours
256     if ( strlen(time_str) ) {
257         i = 0;
258         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
259             num[i] = time_str[0];
260             time_str++;
261             i++;
262         }
263         if ( time_str[0] == ':' ) {
264             time_str++;
265         }
266         num[i] = '\0';
267         hours = atof(num);
268         // printf("hours = %.2lf\n", hours);
269
270         result += hours;
271     }
272
273     // get minutes
274     if ( strlen(time_str) ) {
275         i = 0;
276         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
277             num[i] = time_str[0];
278             time_str++;
279             i++;
280         }
281         if ( time_str[0] == ':' ) {
282             time_str++;
283         }
284         num[i] = '\0';
285         minutes = atof(num);
286         // printf("minutes = %.2lf\n", minutes);
287
288         result += minutes / 60.0;
289     }
290
291     // get seconds
292     if ( strlen(time_str) ) {
293         i = 0;
294         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
295             num[i] = time_str[0];
296             time_str++;
297             i++;
298         }
299         num[i] = '\0';
300         seconds = atof(num);
301         // printf("seconds = %.2lf\n", seconds);
302
303         result += seconds / 3600.0;
304     }
305
306     return(sign * result);
307 }
308
309
310 // parse a date string (yyyy:mm:dd:hh:mm:ss) into a time_t (seconds)
311 static long int 
312 parse_date( const string& date)
313 {
314     struct tm gmt;
315     char * date_str, num[256];
316     int i;
317     // initialize to zero
318     gmt.tm_sec = 0;
319     gmt.tm_min = 0;
320     gmt.tm_hour = 0;
321     gmt.tm_mday = 0;
322     gmt.tm_mon = 0;
323     gmt.tm_year = 0;
324     gmt.tm_isdst = 0; // ignore daylight savings time for the moment
325     date_str = (char *)date.c_str();
326     // get year
327     if ( strlen(date_str) ) {
328         i = 0;
329         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
330             num[i] = date_str[0];
331             date_str++;
332             i++;
333         }
334         if ( date_str[0] == ':' ) {
335             date_str++;
336         }
337         num[i] = '\0';
338         gmt.tm_year = atoi(num) - 1900;
339     }
340     // get month
341     if ( strlen(date_str) ) {
342         i = 0;
343         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
344             num[i] = date_str[0];
345             date_str++;
346             i++;
347         }
348         if ( date_str[0] == ':' ) {
349             date_str++;
350         }
351         num[i] = '\0';
352         gmt.tm_mon = atoi(num) -1;
353     }
354     // get day
355     if ( strlen(date_str) ) {
356         i = 0;
357         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
358             num[i] = date_str[0];
359             date_str++;
360             i++;
361         }
362         if ( date_str[0] == ':' ) {
363             date_str++;
364         }
365         num[i] = '\0';
366         gmt.tm_mday = atoi(num);
367     }
368     // get hour
369     if ( strlen(date_str) ) {
370         i = 0;
371         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
372             num[i] = date_str[0];
373             date_str++;
374             i++;
375         }
376         if ( date_str[0] == ':' ) {
377             date_str++;
378         }
379         num[i] = '\0';
380         gmt.tm_hour = atoi(num);
381     }
382     // get minute
383     if ( strlen(date_str) ) {
384         i = 0;
385         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
386             num[i] = date_str[0];
387             date_str++;
388             i++;
389         }
390         if ( date_str[0] == ':' ) {
391             date_str++;
392         }
393         num[i] = '\0';
394         gmt.tm_min = atoi(num);
395     }
396     // get second
397     if ( strlen(date_str) ) {
398         i = 0;
399         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
400             num[i] = date_str[0];
401             date_str++;
402             i++;
403         }
404         if ( date_str[0] == ':' ) {
405             date_str++;
406         }
407         num[i] = '\0';
408         gmt.tm_sec = atoi(num);
409     }
410     time_t theTime = sgTimeGetGMT( gmt.tm_year, gmt.tm_mon, gmt.tm_mday,
411                                    gmt.tm_hour, gmt.tm_min, gmt.tm_sec );
412     //printf ("Date is %s\n", ctime(&theTime));
413     //printf ("in seconds that is %d\n", theTime);
414     //exit(1);
415     return (theTime);
416 }
417
418
419 // parse angle in the form of [+/-]ddd:mm:ss into degrees
420 static double
421 parse_degree( const string& degree_str) {
422     double result = parse_time( degree_str );
423
424     // printf("Degree = %.4f\n", result);
425
426     return(result);
427 }
428
429
430 // parse time offset string into seconds
431 static int
432 parse_time_offset( const string& time_str) {
433     int result;
434
435     // printf("time offset = %s\n", time_str);
436
437 #ifdef HAVE_RINT
438     result = (int)rint(parse_time(time_str) * 3600.0);
439 #else
440     result = (int)(parse_time(time_str) * 3600.0);
441 #endif
442
443     // printf("parse_time_offset(): %d\n", result);
444
445     return( result );
446 }
447
448
449 // Parse --fov=x.xx type option 
450 static double
451 parse_fov( const string& arg ) {
452     double fov = atof(arg);
453
454     if ( fov < FG_FOV_MIN ) { fov = FG_FOV_MIN; }
455     if ( fov > FG_FOV_MAX ) { fov = FG_FOV_MAX; }
456
457     fgSetDouble("/sim/current-view/field-of-view", fov);
458
459     // printf("parse_fov(): result = %.4f\n", fov);
460
461     return fov;
462 }
463
464
465 // Parse I/O channel option
466 //
467 // Format is "--protocol=medium,direction,hz,medium_options,..."
468 //
469 //   protocol = { native, nmea, garmin, fgfs, rul, pve, etc. }
470 //   medium = { serial, socket, file, etc. }
471 //   direction = { in, out, bi }
472 //   hz = number of times to process channel per second (floating
473 //        point values are ok.
474 //
475 // Serial example "--nmea=serial,dir,hz,device,baud" where
476 // 
477 //  device = OS device name of serial line to be open()'ed
478 //  baud = {300, 1200, 2400, ..., 230400}
479 //
480 // Socket exacmple "--native=socket,dir,hz,machine,port,style" where
481 // 
482 //  machine = machine name or ip address if client (leave empty if server)
483 //  port = port, leave empty to let system choose
484 //  style = tcp or udp
485 //
486 // File example "--garmin=file,dir,hz,filename" where
487 // 
488 //  filename = file system file name
489
490 static bool 
491 add_channel( const string& type, const string& channel_str ) {
492     // cout << "Channel string = " << channel_str << endl;
493
494     globals->get_channel_options_list()->push_back( type + "," + channel_str );
495
496     return true;
497 }
498
499
500 static void
501 setup_wind (double min_hdg, double max_hdg, double speed, double gust)
502 {
503   fgSetDouble("/environment/wind-from-heading-deg", min_hdg);
504   fgSetDouble("/environment/params/min-wind-from-heading-deg", min_hdg);
505   fgSetDouble("/environment/params/max-wind-from-heading-deg", max_hdg);
506   fgSetDouble("/environment/wind-speed-kt", speed);
507   fgSetDouble("/environment/params/base-wind-speed-kt", speed);
508   fgSetDouble("/environment/params/gust-wind-speed-kt", gust);
509
510   SG_LOG(SG_GENERAL, SG_INFO, "WIND: " << min_hdg << '@' << 
511          speed << " knots" << endl);
512
513 #ifdef FG_WEATHERCM
514   // convert to fps
515   speed *= SG_NM_TO_METER * SG_METER_TO_FEET * (1.0/3600);
516   while (min_hdg > 360)
517     min_hdg -= 360;
518   while (min_hdg <= 0)
519     min_hdg += 360;
520   min_hdg *= SGD_DEGREES_TO_RADIANS;
521   fgSetDouble("/environment/wind-from-north-fps", speed * cos(dir));
522   fgSetDouble("/environment/wind-from-east-fps", speed * sin(dir));
523 #endif // FG_WEATHERCM
524 }
525
526
527 // Parse --wp=ID[@alt]
528 static bool 
529 parse_wp( const string& arg ) {
530     string id, alt_str;
531     double alt = 0.0;
532
533     string::size_type pos = arg.find( "@" );
534     if ( pos != string::npos ) {
535         id = arg.substr( 0, pos );
536         alt_str = arg.substr( pos + 1 );
537         // cout << "id str = " << id << "  alt str = " << alt_str << endl;
538         alt = atof( alt_str.c_str() );
539         if ( !strcmp(fgGetString("/sim/startup/units"), "feet") ) {
540             alt *= SG_FEET_TO_METER;
541         }
542     } else {
543         id = arg;
544     }
545
546     FGAirport a;
547     if ( fgFindAirportID( id, &a ) ) {
548         SGWayPoint wp( a.longitude, a.latitude, alt, SGWayPoint::WGS84, id );
549         globals->get_route()->add_waypoint( wp );
550
551         return true;
552     } else {
553         return false;
554     }
555 }
556
557
558 // Parse --flight-plan=[file]
559 static bool 
560 parse_flightplan(const string& arg)
561 {
562     sg_gzifstream in(arg.c_str());
563     if ( !in.is_open() ) {
564         return false;
565     }
566     while ( true ) {
567         string line;
568
569 #if defined( macintosh )
570         getline( in, line, '\r' );
571 #else
572         getline( in, line, '\n' );
573 #endif
574
575         // catch extraneous (DOS) line ending character
576         if ( line[line.length() - 1] < 32 ) {
577             line = line.substr( 0, line.length()-1 );
578         }
579
580         if ( in.eof() ) {
581             break;
582         }
583         parse_wp(line);
584     }
585
586     return true;
587 }
588
589
590 // Parse a single option
591 static int 
592 parse_option (const string& arg) 
593 {
594     // General Options
595     if ( (arg == "--help") || (arg == "-h") ) {
596         // help/usage request
597         return(FG_OPTIONS_HELP);
598     } else if ( (arg == "--verbose") || (arg == "-v") ) {
599         // verbose help/usage request
600         return(FG_OPTIONS_VERBOSE_HELP);
601     } else if ( arg == "--disable-game-mode") {
602         fgSetBool("/sim/startup/game-mode", false);
603     } else if ( arg == "--enable-game-mode" ) {
604         fgSetBool("/sim/startup/game-mode", true);
605     } else if ( arg == "--disable-splash-screen" ) {
606         fgSetBool("/sim/startup/splash-screen", false); 
607     } else if ( arg == "--enable-splash-screen" ) {
608         fgSetBool("/sim/startup/splash-screen", true);
609     } else if ( arg == "--disable-intro-music" ) {
610         fgSetBool("/sim/startup/intro-music", false);
611     } else if ( arg == "--enable-intro-music" ) {
612         fgSetBool("/sim/startup/intro-music", true);
613     } else if ( arg == "--disable-mouse-pointer" ) {
614         fgSetString("/sim/startup/mouse-pointer", "disabled");
615     } else if ( arg == "--enable-mouse-pointer" ) {
616         fgSetString("/sim/startup/mouse-pointer", "enabled");
617     } else if ( arg == "--disable-random-objects" ) {
618         fgSetBool("/sim/rendering/random-objects", false);
619     } else if ( arg == "--enable-random-objects" ) {
620         fgSetBool("/sim/rendering/random-objects", true);
621     } else if ( arg == "--disable-freeze" ) {
622         fgSetBool("/sim/freeze/master", false);
623     } else if ( arg == "--enable-freeze" ) {
624         fgSetBool("/sim/freeze/master", true);
625     } else if ( arg == "--disable-fuel-freeze" ) {
626         fgSetBool("/sim/freeze/fuel", false);
627     } else if ( arg == "--enable-fuel-freeze" ) {
628         fgSetBool("/sim/freeze/fuel", true);
629     } else if ( arg == "--disable-clock-freeze" ) {
630         fgSetBool("/sim/freeze/clock", false);
631     } else if ( arg == "--enable-clock-freeze" ) {
632         fgSetBool("/sim/freeze/clock", true);
633     } else if ( arg == "--disable-anti-alias-hud" ) {
634         fgSetBool("/sim/hud/antialiased", false);
635     } else if ( arg == "--enable-anti-alias-hud" ) {
636         fgSetBool("/sim/hud/antialiased", true);
637     } else if ( arg.find( "--control=") == 0 ) {
638         fgSetString("/sim/control-mode", arg.substr(10).c_str());
639     } else if ( arg == "--disable-auto-coordination" ) {
640         fgSetBool("/sim/auto-coordination", false);
641     } else if ( arg == "--enable-auto-coordination" ) {
642         fgSetBool("/sim/auto-coordination", true);
643     } else if ( arg.find( "--browser-app=") == 0 ) {
644         fgSetString("/sim/startup/browser-app", arg.substr(14).c_str());
645     } else if ( arg == "--disable-hud" ) {
646         fgSetBool("/sim/hud/visibility", false);
647     } else if ( arg == "--enable-hud" ) {
648         fgSetBool("/sim/hud/visibility", true);
649     } else if ( arg == "--disable-panel" ) {
650         fgSetBool("/sim/panel/visibility", false);
651     } else if ( arg == "--enable-panel" ) {
652         fgSetBool("/sim/panel/visibility", true);
653     } else if ( arg == "--disable-sound" ) {
654         fgSetBool("/sim/sound/audible", false);
655     } else if ( arg == "--enable-sound" ) {
656         fgSetBool("/sim/sound/audible", true);
657     } else if ( arg.find( "--airport-id=") == 0 ) {
658                                 // NB: changed property name!!!
659         fgSetString("/sim/startup/airport-id", arg.substr(13).c_str());
660     } else if ( arg.find( "--offset-distance=") == 0 ) {
661         fgSetDouble("/sim/startup/offset-distance", atof(arg.substr(18)));
662     } else if ( arg.find( "--offset-azimuth=") == 0 ) {
663         fgSetDouble("/sim/startup/offset-azimuth", atof(arg.substr(17))); 
664     } else if ( arg.find( "--lon=" ) == 0 ) {
665         fgSetDouble("/position/longitude-deg",
666                               parse_degree(arg.substr(6)));
667         fgSetString("/sim/startup/airport-id", "");
668     } else if ( arg.find( "--lat=" ) == 0 ) {
669         fgSetDouble("/position/latitude-deg",
670                               parse_degree(arg.substr(6)));
671         fgSetString("/sim/startup/airport-id", "");
672     } else if ( arg.find( "--altitude=" ) == 0 ) {
673         fgSetBool("/sim/startup/onground", false);
674         if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
675             fgSetDouble("/position/altitude-ft", atof(arg.substr(11)));
676         else
677             fgSetDouble("/position/altitude-ft",
678                         atof(arg.substr(11)) * SG_METER_TO_FEET);
679     } else if ( arg.find( "--uBody=" ) == 0 ) {
680         fgSetString("/sim/startup/speed-set", "UVW");
681         if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
682           fgSetDouble("/velocities/uBody-fps", atof(arg.substr(8)));
683         else
684           fgSetDouble("/velocities/uBody-fps",
685                                atof(arg.substr(8)) * SG_METER_TO_FEET);
686     } else if ( arg.find( "--vBody=" ) == 0 ) {
687         fgSetString("/sim/startup/speed-set", "UVW");
688         if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
689           fgSetDouble("/velocities/vBody-fps", atof(arg.substr(8)));
690         else
691           fgSetDouble("/velocities/vBody-fps",
692                                atof(arg.substr(8)) * SG_METER_TO_FEET);
693     } else if ( arg.find( "--wBody=" ) == 0 ) {
694         fgSetString("/sim/startup/speed-set", "UVW");
695         if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
696           fgSetDouble("/velocities/wBody-fps", atof(arg.substr(8)));
697         else
698           fgSetDouble("/velocities/wBody-fps",
699                                atof(arg.substr(8)) * SG_METER_TO_FEET);
700     } else if ( arg.find( "--vNorth=" ) == 0 ) {
701         fgSetString("/sim/startup/speed-set", "NED");
702         if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
703           fgSetDouble("/velocities/speed-north-fps", atof(arg.substr(9)));
704         else
705           fgSetDouble("/velocities/speed-north-fps",
706                                atof(arg.substr(9)) * SG_METER_TO_FEET);
707     } else if ( arg.find( "--vEast=" ) == 0 ) {
708         fgSetString("/sim/startup/speed-set", "NED");
709         if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
710           fgSetDouble("/velocities/speed-east-fps", atof(arg.substr(8)));
711         else
712           fgSetDouble("/velocities/speed-east-fps",
713                       atof(arg.substr(8)) * SG_METER_TO_FEET);
714     } else if ( arg.find( "--vDown=" ) == 0 ) {
715         fgSetString("/sim/startup/speed-set", "NED");
716         if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
717           fgSetDouble("/velocities/speed-down-fps", atof(arg.substr(8)));
718         else
719           fgSetDouble("/velocities/speed-down-fps",
720                                atof(arg.substr(8)) * SG_METER_TO_FEET);
721     } else if ( arg.find( "--vc=" ) == 0) {
722         fgSetString("/sim/startup/speed-set", "knots");
723         fgSetDouble("/velocities/airspeed-kt", atof(arg.substr(5)));
724     } else if ( arg.find( "--mach=" ) == 0) {
725         fgSetString("/sim/startup/speed-set", "mach");
726         fgSetDouble("/velocities/mach", atof(arg.substr(7)));
727     } else if ( arg.find( "--heading=" ) == 0 ) {
728         fgSetDouble("/orientation/heading-deg", atof(arg.substr(10)));
729     } else if ( arg.find( "--roll=" ) == 0 ) {
730         fgSetDouble("/orientation/roll-deg", atof(arg.substr(7)));
731     } else if ( arg.find( "--pitch=" ) == 0 ) {
732         fgSetDouble("/orientation/pitch-deg", atof(arg.substr(8)));
733     } else if ( arg.find( "--glideslope=" ) == 0 ) {
734         fgSetDouble("/velocities/glideslope", atof(arg.substr(13))
735                                           *SG_DEGREES_TO_RADIANS);
736     }  else if ( arg.find( "--roc=" ) == 0 ) {
737         fgSetDouble("/velocities/vertical-speed-fps", atof(arg.substr(6))/60);
738     } else if ( arg.find( "--fg-root=" ) == 0 ) {
739         globals->set_fg_root(arg.substr( 10 ));
740     } else if ( arg.find( "--fg-scenery=" ) == 0 ) {
741         globals->set_fg_scenery(arg.substr( 13 ));
742     } else if ( arg.find( "--fdm=" ) == 0 ) {
743         fgSetString("/sim/flight-model", arg.substr(6).c_str());
744     } else if ( arg.find( "--aero=" ) == 0 ) {
745         fgSetString("/sim/aero", arg.substr(7).c_str());
746     } else if ( arg.find( "--aircraft-dir=" ) == 0 ) {
747         fgSetString("/sim/aircraft-dir", arg.substr(15).c_str());
748     } else if ( arg.find( "--model-hz=" ) == 0 ) {
749         fgSetInt("/sim/model-hz", atoi(arg.substr(11)));
750     } else if ( arg.find( "--speed=" ) == 0 ) {
751         fgSetInt("/sim/speed-up", atoi(arg.substr(8)));
752     } else if ( arg.find( "--trim") == 0) {
753         fgSetBool("/sim/startup/trim", true);
754     } else if ( arg.find( "--notrim") == 0) {
755         fgSetBool("/sim/startup/trim", false);
756     } else if ( arg.find( "--on-ground") == 0) {
757         fgSetBool("/sim/startup/onground", true);
758     } else if ( arg.find( "--in-air") == 0) {
759         fgSetBool("/sim/startup/onground", false);
760     } else if ( arg == "--fog-disable" ) {
761         fgSetString("/sim/rendering/fog", "disabled");
762     } else if ( arg == "--fog-fastest" ) {
763         fgSetString("/sim/rendering/fog", "fastest");
764     } else if ( arg == "--fog-nicest" ) {
765         fgSetString("/sim/fog", "nicest");
766     } else if ( arg == "--disable-clouds" ) {
767         fgSetBool("/environment/clouds/status", false);
768     } else if ( arg == "--enable-clouds" ) {
769         fgSetBool("/environment/clouds/status", true);
770     } else if ( arg.find( "--fov=" ) == 0 ) {
771         parse_fov( arg.substr(6) );
772     } else if ( arg == "--disable-fullscreen" ) {
773         fgSetBool("/sim/startup/fullscreen", false);
774     } else if ( arg== "--enable-fullscreen") {
775         fgSetBool("/sim/startup/fullscreen", true);
776     } else if ( arg == "--shading-flat") {
777         fgSetBool("/sim/rendering/shading", false);
778     } else if ( arg == "--shading-smooth") {
779         fgSetBool("/sim/rendering/shading", true);
780     } else if ( arg == "--disable-skyblend") {
781         fgSetBool("/sim/rendering/skyblend", false);
782     } else if ( arg== "--enable-skyblend" ) {
783         fgSetBool("/sim/rendering/skyblend", true);
784     } else if ( arg == "--disable-textures" ) {
785         fgSetBool("/sim/rendering/textures", false);
786     } else if ( arg == "--enable-textures" ) {
787         fgSetBool("/sim/rendering/textures", true);
788     } else if ( arg == "--disable-wireframe" ) {
789         fgSetBool("/sim/rendering/wireframe", false);
790     } else if ( arg == "--enable-wireframe" ) {
791         fgSetBool("/sim/rendering/wireframe", true);
792     } else if ( arg.find( "--geometry=" ) == 0 ) {
793         bool geometry_ok = true;
794         int xsize = 0, ysize = 0;
795         string geometry = arg.substr( 11 );
796         string::size_type i = geometry.find('x');
797
798         if (i != string::npos) {
799             xsize = atoi(geometry.substr(0, i));
800             ysize = atoi(geometry.substr(i+1));
801         } else {
802             geometry_ok = false;
803         }
804
805         if ( xsize <= 0 || ysize <= 0 ) {
806             xsize = 640;
807             ysize = 480;
808             geometry_ok = false;
809         }
810
811         if ( !geometry_ok ) {
812             SG_LOG( SG_GENERAL, SG_ALERT, "Unknown geometry: " << geometry );
813             SG_LOG( SG_GENERAL, SG_ALERT,
814                     "Setting geometry to " << xsize << 'x' << ysize << '\n');
815         } else {
816           SG_LOG( SG_GENERAL, SG_INFO,
817                   "Setting geometry to " << xsize << 'x' << ysize << '\n');
818           fgSetInt("/sim/startup/xsize", xsize);
819           fgSetInt("/sim/startup/ysize", ysize);
820         }
821     } else if ( arg.find( "--bpp=" ) == 0 ) {
822         string bits_per_pix = arg.substr( 6 );
823         if ( bits_per_pix == "16" ) {
824             fgSetInt("/sim/rendering/bits-per-pixel", 16);
825         } else if ( bits_per_pix == "24" ) {
826             fgSetInt("/sim/rendering/bits-per-pixel", 24);
827         } else if ( bits_per_pix == "32" ) {
828             fgSetInt("/sim/rendering/bits-per-pixel", 32);
829         } else {
830           SG_LOG(SG_GENERAL, SG_ALERT, "Unsupported bpp " << bits_per_pix);
831         }
832     } else if ( arg == "--units-feet" ) {
833         fgSetString("/sim/startup/units", "feet");
834     } else if ( arg == "--units-meters" ) {
835         fgSetString("/sim/startup/units", "meters");
836     } else if ( arg.find( "--time-offset" ) == 0 ) {
837         fgSetInt("/sim/startup/time-offset",
838                  parse_time_offset( (arg.substr(14)) ));
839         fgSetString("/sim/startup/time-offset-type", "system-offset");
840     } else if ( arg.find( "--time-match-real") == 0 ) {
841         fgSetString("/sim/startup/time-offset-type", "system-offset");
842     } else if ( arg.find( "--time-match-local") == 0 ) {
843         fgSetString("/sim/startup/time-offset-type", "latitude-offset");
844     } else if ( arg.find( "--start-date-sys=") == 0 ) {
845         fgSetInt("/sim/startup/time-offset", parse_date((arg.substr(17))));
846         fgSetString("/sim/startup/time-offset-type", "system");
847     } else if ( arg.find( "--start-date-lat=") == 0 ) {
848         fgSetInt("/sim/startup/time-offset", parse_date((arg.substr(17))));
849         fgSetString("/sim/startup/time-offset-type", "latitude");
850     } else if ( arg.find( "--start-date-gmt=") == 0 ) {
851         fgSetInt("/sim/startup/time-offset", parse_date((arg.substr(17))));
852         fgSetString("/sim/startup/time-offset-type", "gmt");
853     } else if ( arg == "--hud-tris" ) {
854         fgSetString("/sim/hud/frame-stat-type", "tris");
855     } else if ( arg == "--hud-culled" ) {
856         fgSetString("/sim/hud/frame-stat-type", "culled");
857     } else if ( arg.find( "--atc610x" ) == 0 ) {
858         add_channel( "atc610x", "dummy" );
859     } else if ( arg.find( "--atlas=" ) == 0 ) {
860         add_channel( "atlas", arg.substr(8) );
861     } else if ( arg.find( "--httpd=" ) == 0 ) {
862         add_channel( "httpd", arg.substr(8) );
863 #ifdef FG_JPEG_SERVER
864     } else if ( arg.find( "--jpg-httpd=" ) == 0 ) {
865         add_channel( "jpg-httpd", arg.substr(12) );
866 #endif
867     } else if ( arg.find( "--native=" ) == 0 ) {
868         add_channel( "native", arg.substr(9) );
869     } else if ( arg.find( "--native-ctrls=" ) == 0 ) {
870         add_channel( "native_ctrls", arg.substr(15) );
871     } else if ( arg.find( "--native-fdm=" ) == 0 ) {
872         add_channel( "native_fdm", arg.substr(13) );
873     } else if ( arg.find( "--opengc=" ) == 0 ) {
874         // char stop;
875         // cout << "Adding channel for OpenGC Display" << endl; cin >> stop;
876         add_channel( "opengc", arg.substr(9) );
877     } else if ( arg.find( "--garmin=" ) == 0 ) {
878         add_channel( "garmin", arg.substr(9) );
879     } else if ( arg.find( "--nmea=" ) == 0 ) {
880         add_channel( "nmea", arg.substr(7) );
881     } else if ( arg.find( "--props=" ) == 0 ) {
882         add_channel( "props", arg.substr(8) );
883     } else if ( arg.find( "--telnet=" ) == 0 ) {
884         add_channel( "telnet", arg.substr(9) );
885     } else if ( arg.find( "--pve=" ) == 0 ) {
886         add_channel( "pve", arg.substr(6) );
887     } else if ( arg.find( "--ray=" ) == 0 ) {
888         add_channel( "ray", arg.substr(6) );
889     } else if ( arg.find( "--rul=" ) == 0 ) {
890         add_channel( "rul", arg.substr(6) );
891     } else if ( arg.find( "--joyclient=" ) == 0 ) {
892         add_channel( "joyclient", arg.substr(12) );
893 #ifdef FG_NETWORK_OLK
894     } else if ( arg == "--disable-network-olk" ) {
895         fgSetBool("/sim/networking/olk", false);
896     } else if ( arg== "--enable-network-olk") {
897         fgSetBool("/sim/networking/olk", true);
898     } else if ( arg == "--net-hud" ) {
899         fgSetBool("/sim/hud/net-display", true);
900         net_hud_display = 1;    // FIXME
901     } else if ( arg.find( "--net-id=") == 0 ) {
902         fgSetString("sim/networking/call-sign", arg.substr(9).c_str());
903 #endif
904     } else if ( arg.find( "--prop:" ) == 0 ) {
905         string assign = arg.substr(7);
906         string::size_type pos = assign.find('=');
907         if ( pos == arg.npos || pos == 0 ) {
908             SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
909             return FG_OPTIONS_ERROR;
910         }
911         string name = assign.substr(0, pos);
912         string value = assign.substr(pos + 1);
913         fgSetString(name.c_str(), value.c_str());
914         // SG_LOG(SG_GENERAL, SG_INFO, "Setting default value of property "
915         //        << name << " to \"" << value << '"');
916     } else if ( arg.find("--trace-read=") == 0) {
917         string name = arg.substr(13);
918         SG_LOG(SG_GENERAL, SG_INFO, "Tracing reads for property " << name);
919         fgGetNode(name.c_str(), true)
920           ->setAttribute(SGPropertyNode::TRACE_READ, true);
921     } else if ( arg.find("--trace-write=") == 0) {
922         string name = arg.substr(14);
923         SG_LOG(SG_GENERAL, SG_INFO, "Tracing writes for property " << name);
924         fgGetNode(name.c_str(), true)
925           ->setAttribute(SGPropertyNode::TRACE_WRITE, true);
926     } else if ( arg.find( "--view-offset=" ) == 0 ) {
927         // $$$ begin - added VS Renganathan, 14 Oct 2K
928         // for multi-window outside window imagery
929         string woffset = arg.substr( 14 );
930         double default_view_offset = 0.0;
931         if ( woffset == "LEFT" ) {
932                default_view_offset = SGD_PI * 0.25;
933         } else if ( woffset == "RIGHT" ) {
934             default_view_offset = SGD_PI * 1.75;
935         } else if ( woffset == "CENTER" ) {
936             default_view_offset = 0.00;
937         } else {
938             default_view_offset = atof( woffset.c_str() ) * SGD_DEGREES_TO_RADIANS;
939         }
940         /* apparently not used (CLO, 11 Jun 2002) 
941            FGViewer *pilot_view =
942               (FGViewer *)globals->get_viewmgr()->get_view( 0 ); */
943         // this will work without calls to the viewer...
944         fgSetDouble( "/sim/current-view/heading-offset-deg",
945                      default_view_offset  * SGD_RADIANS_TO_DEGREES );
946     // $$$ end - added VS Renganathan, 14 Oct 2K
947     } else if ( arg.find( "--visibility=" ) == 0 ) {
948         fgSetDouble("/environment/visibility-m", atof(arg.substr(13)));
949     } else if ( arg.find( "--visibility-miles=" ) == 0 ) {
950         double visibility = atof(arg.substr(19)) * 5280.0 * SG_FEET_TO_METER;
951         fgSetDouble("/environment/visibility-m", visibility);
952     } else if ( arg.find( "--random-wind" ) == 0 ) {
953         double min_hdg = sg_random() * 360.0;
954         double max_hdg = min_hdg + (20 - sqrt(sg_random() * 400));
955         double speed = 40 - sqrt(sg_random() * 1600.0);
956         double gust = speed + (10 - sqrt(sg_random() * 100));
957         setup_wind(min_hdg, max_hdg, speed, gust);
958     } else if ( arg.find( "--wind=" ) == 0 ) {
959         double min_hdg, max_hdg, speed, gust;
960         if (!parse_wind(arg.substr(7), &min_hdg, &max_hdg, &speed, &gust)) {
961           SG_LOG( SG_GENERAL, SG_ALERT, "bad wind value " << arg.substr(7) );
962           return FG_OPTIONS_ERROR;
963         }
964         setup_wind(min_hdg, max_hdg, speed, gust);
965     } else if ( arg.find( "--wp=" ) == 0 ) {
966         parse_wp( arg.substr( 5 ) );
967     } else if ( arg.find( "--flight-plan=") == 0) {
968         parse_flightplan ( arg.substr (14) );
969     } else if ( arg.find( "--config=" ) == 0 ) {
970         string file = arg.substr(9);
971         try {
972           readProperties(file, globals->get_props());
973         } catch (const sg_exception &e) {
974           string message = "Error loading config file: ";
975           message += e.getFormattedMessage();
976           SG_LOG(SG_INPUT, SG_ALERT, message);
977           exit(2);
978         }
979     } else if ( arg.find( "--aircraft=" ) == 0 ) {
980         // read in the top level aircraft definition file
981         SGPath apath( globals->get_fg_root() );
982         apath.append( "Aircraft" );
983         apath.append( arg.substr(11) );
984         apath.concat( "-set.xml" );
985         SG_LOG(SG_INPUT, SG_INFO, "Reading aircraft: " << arg.substr(11)
986             << " from " << apath.str());
987         readProperties( apath.str(), globals->get_props() );
988     } else {
989         SG_LOG( SG_GENERAL, SG_ALERT, "Unknown option '" << arg << "'" );
990         return FG_OPTIONS_ERROR;
991     }
992     
993     return FG_OPTIONS_OK;
994 }
995
996
997 // Scan the command line options for an fg_root definition and set
998 // just that.
999 string
1000 fgScanForRoot (int argc, char **argv) 
1001 {
1002     int i = 1;
1003
1004     SG_LOG(SG_GENERAL, SG_INFO, "Scanning for root: command line");
1005
1006     while ( i < argc ) {
1007         SG_LOG( SG_GENERAL, SG_DEBUG, "argv[" << i << "] = " << argv[i] );
1008
1009         string arg = argv[i];
1010         if ( arg.find( "--fg-root=" ) == 0 ) {
1011             return arg.substr( 10 );
1012         }
1013
1014         i++;
1015     }
1016
1017     return "";
1018 }
1019
1020
1021 // Scan the config file for an fg_root definition and set just that.
1022 string
1023 fgScanForRoot (const string& path)
1024 {
1025     sg_gzifstream in( path );
1026     if ( !in.is_open() )
1027       return "";
1028
1029     SG_LOG( SG_GENERAL, SG_INFO, "Scanning for root: " << path );
1030
1031     in >> skipcomment;
1032 #ifndef __MWERKS__
1033     while ( ! in.eof() ) {
1034 #else
1035     char c = '\0';
1036     while ( in.get(c) && c != '\0' ) {
1037         in.putback(c);
1038 #endif
1039         string line;
1040
1041 #if defined( macintosh )
1042         getline( in, line, '\r' );
1043 #else
1044         getline( in, line, '\n' );
1045 #endif
1046
1047         // catch extraneous (DOS) line ending character
1048         if ( line[line.length() - 1] < 32 ) {
1049             line = line.substr( 0, line.length()-1 );
1050         }
1051
1052         if ( line.find( "--fg-root=" ) == 0 ) {
1053             return line.substr( 10 );
1054         }
1055
1056         in >> skipcomment;
1057     }
1058
1059     return "";
1060 }
1061
1062
1063 // Parse the command line options
1064 void
1065 fgParseArgs (int argc, char **argv)
1066 {
1067     bool in_options = true;
1068     bool verbose = false;
1069     bool help = false;
1070
1071     SG_LOG(SG_GENERAL, SG_INFO, "Processing command line arguments");
1072
1073     for (int i = 1; i < argc; i++) {
1074         string arg = argv[i];
1075
1076         if (in_options && (arg.find('-') == 0)) {
1077           if (arg == "--") {
1078             in_options = false;
1079           } else {
1080             int result = parse_option(arg);
1081             if ((result == FG_OPTIONS_HELP) || (result == FG_OPTIONS_ERROR))
1082               help = true;
1083
1084             else if (result == FG_OPTIONS_VERBOSE_HELP)
1085               verbose = true;
1086           }
1087         } else {
1088           in_options = false;
1089           SG_LOG(SG_GENERAL, SG_INFO,
1090                  "Reading command-line property file " << arg);
1091           readProperties(arg, globals->get_props());
1092         }
1093     }
1094
1095     if (help) {
1096        fgUsage(verbose);
1097        exit(0);
1098     }
1099
1100     SG_LOG(SG_GENERAL, SG_INFO, "Finished command line arguments");
1101 }
1102
1103
1104 // Parse config file options
1105 void
1106 fgParseOptions (const string& path) {
1107     sg_gzifstream in( path );
1108     if ( !in.is_open() ) {
1109         return;
1110     }
1111
1112     SG_LOG( SG_GENERAL, SG_INFO, "Processing config file: " << path );
1113
1114     in >> skipcomment;
1115 #ifndef __MWERKS__
1116     while ( ! in.eof() ) {
1117 #else
1118     char c = '\0';
1119     while ( in.get(c) && c != '\0' ) {
1120         in.putback(c);
1121 #endif
1122         string line;
1123
1124 #if defined( macintosh )
1125         getline( in, line, '\r' );
1126 #else
1127         getline( in, line, '\n' );
1128 #endif
1129
1130         // catch extraneous (DOS) line ending character
1131         if ( line[line.length() - 1] < 32 ) {
1132             line = line.substr( 0, line.length()-1 );
1133         }
1134
1135         if ( parse_option( line ) == FG_OPTIONS_ERROR ) {
1136             SG_LOG( SG_GENERAL, SG_ALERT, 
1137                     "Config file parse error: " << path << " '" 
1138                     << line << "'" );
1139             fgUsage();
1140             exit(-1);
1141         }
1142         in >> skipcomment;
1143     }
1144 }
1145
1146
1147 // Print usage message
1148 void 
1149 fgUsage (bool verbose)
1150 {
1151     SGPropertyNode options_root;
1152     SGPath opath( globals->get_fg_root() );
1153     opath.append( "options.xml" );
1154
1155     cout << "" << endl;
1156
1157     try {
1158         readProperties(opath.c_str(), &options_root);
1159     } catch (const sg_exception &ex) {
1160         cout << "Unable to read the help file." << endl;
1161         cout << "Make sure the file options.xml is located in the FlightGear base directory," << endl;
1162         cout << "and the location of the base directory is specified bij setting $FG_ROOT or" << endl;
1163         cout << "by adding --fg-root=path as a program argument." << endl;
1164         
1165         exit(-1);
1166     }
1167
1168     SGPropertyNode *options = options_root.getNode("options");
1169     if (!options) {
1170         SG_LOG( SG_GENERAL, SG_ALERT,
1171                 "Error reading options.xml: <options> directive not found." );
1172         exit(-1);
1173     }
1174
1175     SGPropertyNode *usage = options->getNode("usage");
1176     if (usage) {
1177         cout << "Usage: " << usage->getStringValue() << endl;
1178     }
1179
1180     vector<SGPropertyNode_ptr>section = options->getChildren("section");
1181     for (unsigned int j = 0; j < section.size(); j++) {
1182         string msg = "";
1183
1184         vector<SGPropertyNode_ptr>option = section[j]->getChildren("option");
1185         for (unsigned int k = 0; k < option.size(); k++) {
1186
1187             SGPropertyNode *name = option[k]->getNode("name");
1188             SGPropertyNode *short_name = option[k]->getNode("short");
1189             SGPropertyNode *key = option[k]->getNode("key");
1190             SGPropertyNode *arg = option[k]->getNode("arg");
1191             bool brief = option[k]->getNode("brief");
1192
1193             if ((brief || verbose) && name) {
1194                 string tmp = name->getStringValue();
1195
1196                 if (key){
1197                     tmp.append(":");
1198                     tmp.append(key->getStringValue());
1199                 }
1200                 if (arg) {
1201                     tmp.append("=");
1202                     tmp.append(arg->getStringValue());
1203                 }
1204                 if (short_name) {
1205                     tmp.append(", -");
1206                     tmp.append(short_name->getStringValue());
1207                 }
1208
1209                 char cstr[96];
1210                 if (tmp.size() <= 25) {
1211                     snprintf(cstr, 96, "   --%-27s", tmp.c_str());
1212                 } else {
1213                     snprintf(cstr, 96, "\n   --%s\n%32c", tmp.c_str(), ' ');
1214                 }
1215
1216                 msg += cstr;
1217                 SGPropertyNode *desc = option[k]->getNode("description");
1218                 if (desc) {
1219                     msg += desc->getStringValue();
1220
1221                     for ( unsigned int l = 1;
1222                           (desc = option[k]->getNode("description", l, false));
1223                           l++ )
1224                     {
1225                         snprintf(cstr, 96, "\n%32c%s", ' ',
1226                                  desc->getStringValue());
1227                         msg += cstr;
1228                     }
1229                     msg += '\n';
1230                 }
1231             }
1232         }
1233
1234         SGPropertyNode *name = section[j]->getNode("name");
1235         if (!msg.empty() && name) {
1236            cout << endl << name->getStringValue() << ":" << endl;
1237            cout << msg;
1238            msg.erase();
1239         }
1240     }
1241
1242     if ( !verbose ) {
1243         cout << endl;
1244         cout << "For a complete list of options use --help --verbose" << endl;
1245     }
1246 }