From 05a2eff317bebe1072f8d4d5c3b23796622e22e1 Mon Sep 17 00:00:00 2001
From: Erik Hofman <erik@ehofman.com>
Date: Mon, 11 Apr 2011 10:06:57 +0200
Subject: [PATCH 1/4] One step ahead of JSBSim CVS.

---
 src/FDM/JSBSim/FGFDMExec.cpp                  |  45 ++++---
 src/FDM/JSBSim/FGFDMExec.h                    |  16 ++-
 .../initialization/FGInitialCondition.cpp     |  35 +++--
 src/FDM/JSBSim/initialization/FGTrim.cpp      |  24 +---
 src/FDM/JSBSim/initialization/FGTrim.h        |   5 +-
 .../JSBSim/input_output/FGPropertyManager.cpp |  71 +++++++---
 .../JSBSim/input_output/FGPropertyManager.h   |  52 ++++++--
 src/FDM/JSBSim/input_output/FGScript.cpp      |  40 +++++-
 src/FDM/JSBSim/input_output/FGScript.h        |   8 +-
 src/FDM/JSBSim/input_output/FGXMLElement.cpp  |   8 +-
 src/FDM/JSBSim/math/FGCondition.cpp           |  31 +++--
 src/FDM/JSBSim/math/FGCondition.h             |   6 +-
 src/FDM/JSBSim/math/FGFunction.cpp            |  20 +--
 src/FDM/JSBSim/math/FGParameter.h             |   6 +-
 src/FDM/JSBSim/math/FGPropertyValue.cpp       |  38 ++++--
 src/FDM/JSBSim/math/FGPropertyValue.h         |  16 ++-
 src/FDM/JSBSim/math/FGRealValue.h             |   3 +-
 src/FDM/JSBSim/math/FGTable.h                 |   6 +-
 src/FDM/JSBSim/models/FGAerodynamics.cpp      |  42 +++---
 src/FDM/JSBSim/models/FGAerodynamics.h        |  26 ++--
 src/FDM/JSBSim/models/FGAtmosphere.cpp        |   3 +-
 src/FDM/JSBSim/models/FGAuxiliary.cpp         |  26 ++--
 src/FDM/JSBSim/models/FGBuoyantForces.cpp     |  25 ++--
 src/FDM/JSBSim/models/FGFCS.cpp               |  13 +-
 src/FDM/JSBSim/models/FGFCS.h                 |   6 +-
 src/FDM/JSBSim/models/FGLGear.cpp             |  14 +-
 src/FDM/JSBSim/models/FGModel.cpp             |   6 +-
 src/FDM/JSBSim/models/FGOutput.cpp            |  65 +++++----
 src/FDM/JSBSim/models/FGOutput.h              |   9 +-
 src/FDM/JSBSim/models/FGPropagate.cpp         |  60 ++++-----
 src/FDM/JSBSim/models/FGPropagate.h           |  20 ++-
 src/FDM/JSBSim/models/FGPropulsion.cpp        |  17 ++-
 .../models/flight_control/FGActuator.cpp      |  26 +++-
 .../models/flight_control/FGDeadBand.cpp      |   2 +-
 .../models/flight_control/FGFCSComponent.cpp  |  33 +----
 .../models/flight_control/FGFCSComponent.h    |   8 +-
 .../models/flight_control/FGFCSFunction.cpp   |   2 +-
 .../JSBSim/models/flight_control/FGFilter.cpp |   2 +-
 .../JSBSim/models/flight_control/FGGain.cpp   |   4 +-
 .../models/flight_control/FGKinemat.cpp       |   2 +-
 .../JSBSim/models/flight_control/FGPID.cpp    |   4 +-
 .../JSBSim/models/flight_control/FGSensor.cpp |   4 +-
 .../JSBSim/models/flight_control/FGSwitch.cpp |  11 +-
 .../JSBSim/models/flight_control/FGSwitch.h   |   9 +-
 .../JSBSim/models/propulsion/FGElectric.cpp   |  21 ++-
 src/FDM/JSBSim/models/propulsion/FGElectric.h |   9 +-
 src/FDM/JSBSim/models/propulsion/FGEngine.cpp |   9 +-
 src/FDM/JSBSim/models/propulsion/FGEngine.h   |  10 +-
 src/FDM/JSBSim/models/propulsion/FGForce.cpp  |  19 ++-
 src/FDM/JSBSim/models/propulsion/FGPiston.cpp |   9 +-
 src/FDM/JSBSim/models/propulsion/FGPiston.h   |   7 +-
 .../JSBSim/models/propulsion/FGPropeller.cpp  |  11 +-
 .../JSBSim/models/propulsion/FGPropeller.h    |   6 +-
 src/FDM/JSBSim/models/propulsion/FGRocket.cpp |   4 +-
 src/FDM/JSBSim/models/propulsion/FGRotor.cpp  | 121 +++++++++++++----
 src/FDM/JSBSim/models/propulsion/FGRotor.h    |  49 +++++--
 .../JSBSim/models/propulsion/FGThruster.cpp   |  10 +-
 src/FDM/JSBSim/models/propulsion/FGThruster.h |   7 +-
 .../JSBSim/models/propulsion/FGTurbine.cpp    |   8 +-
 .../JSBSim/models/propulsion/FGTurboProp.cpp  | 125 +++++++++++-------
 .../JSBSim/models/propulsion/FGTurboProp.h    |  28 ++--
 61 files changed, 796 insertions(+), 526 deletions(-)
 mode change 100644 => 100755 src/FDM/JSBSim/input_output/FGPropertyManager.cpp
 mode change 100644 => 100755 src/FDM/JSBSim/input_output/FGScript.cpp
 mode change 100644 => 100755 src/FDM/JSBSim/input_output/FGXMLElement.cpp
 mode change 100644 => 100755 src/FDM/JSBSim/math/FGFunction.cpp
 mode change 100644 => 100755 src/FDM/JSBSim/math/FGParameter.h
 mode change 100644 => 100755 src/FDM/JSBSim/math/FGPropertyValue.cpp
 mode change 100644 => 100755 src/FDM/JSBSim/math/FGPropertyValue.h
 mode change 100644 => 100755 src/FDM/JSBSim/models/FGAuxiliary.cpp
 mode change 100644 => 100755 src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
 mode change 100644 => 100755 src/FDM/JSBSim/models/propulsion/FGTurboProp.h

diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp
index ade4209cd..a3b08a49e 100644
--- a/src/FDM/JSBSim/FGFDMExec.cpp
+++ b/src/FDM/JSBSim/FGFDMExec.cpp
@@ -71,7 +71,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.84 2011/01/16 16:26:14 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.91 2011/04/05 20:20:21 andgi Exp $";
 static const char *IdHdr = ID_FDMEXEC;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -116,6 +116,10 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
   dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is
                   // run in standalone mode with no initialization file.
 
+  AircraftPath = "aircraft";
+  EnginePath = "engine";
+  SystemsPath = "systems";
+
   try {
     char* num = getenv("JSBSIM_DEBUG");
     if (num) debug_lvl = atoi(num); // set debug level
@@ -154,12 +158,13 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
 
   Constructing = true;
   typedef int (FGFDMExec::*iPMF)(void) const;
-//  instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis);
-  instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim);
-  instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions);
+//  instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
+  instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
+  instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
   instance->Tie("simulation/terminate", (int *)&Terminate);
   instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
   instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel);
+  instance->Tie("simulation/frame", (int *)&Frame, false);
 
   Constructing = false;
 }
@@ -350,6 +355,8 @@ bool FGFDMExec::RunIC(void)
 
 void FGFDMExec::Initialize(FGInitialCondition *FGIC)
 {
+  Setsim_time(0.0);
+
   Propagate->SetInitialState( FGIC );
 
   Atmosphere->Run();
@@ -358,6 +365,9 @@ void FGFDMExec::Initialize(FGInitialCondition *FGIC)
                           FGIC->GetWindDFpsIC() );
 
   FGColumnVector3 vAeroUVW;
+
+  //ToDo: move this to the Auxiliary class !?
+
   vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED();
 
   double alpha, beta;
@@ -629,7 +639,9 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
 
     // Process the output element[s]. This element is OPTIONAL, and there may be more than one.
     unsigned int idx=0;
-    typedef int (FGOutput::*iOPMF)(void) const;
+    typedef double (FGOutput::*iOPMF)(void) const;
+    typedef int (FGFDMExec::*iOPV)(void) const;
+    typedef void (FGFDMExec::*vOPI)(int) const;
     element = document->FindElement("output");
     while (element) {
       if (debug_lvl > 0) cout << endl << "  Output data set: " << idx << "  ";
@@ -643,7 +655,8 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
       } else {
         Outputs.push_back(Output);
         string outputProp = CreateIndexedPropertyName("simulation/output",idx);
-        instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate);
+        instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate, false);
+        instance->Tie("simulation/force-output", this, (iOPV)0, &FGFDMExec::ForceOutput, false);
         idx++;
       }
       element = document->FindNextElement("output");
@@ -679,15 +692,6 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
          << fgdef << endl;
   }
 
-  // Late bind previously undefined FCS inputs.
-  try {
-    FCS->LateBind();
-  } catch (string prop) {
-    cerr << endl << fgred << "  Could not late bind property " << prop 
-         << ". Aborting." << reset << endl;
-    result = false;
-  }
-
   if (result) {
     struct PropertyCatalogStructure masterPCS;
     masterPCS.base_string = "";
@@ -918,6 +922,13 @@ void FGFDMExec::EnableOutput(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+void FGFDMExec::ForceOutput(int idx)
+{
+  if (idx >= 0 && idx < Outputs.size()) Outputs[idx]->Print();
+}
+	
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 bool FGFDMExec::SetOutputDirectives(const string& fname)
 {
   bool result;
@@ -930,9 +941,9 @@ bool FGFDMExec::SetOutputDirectives(const string& fname)
 
   if (result) {
     Outputs.push_back(Output);
-    typedef int (FGOutput::*iOPMF)(void) const;
+    typedef double (FGOutput::*iOPMF)(void) const;
     string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1);
-    instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate);
+    instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate, false);
   }
 
   return result;
diff --git a/src/FDM/JSBSim/FGFDMExec.h b/src/FDM/JSBSim/FGFDMExec.h
index b982654e7..5f103fe15 100644
--- a/src/FDM/JSBSim/FGFDMExec.h
+++ b/src/FDM/JSBSim/FGFDMExec.h
@@ -44,11 +44,9 @@ INCLUDES
 #include <vector>
 #include <string>
 
-//#include "models/FGModel.h"
 #include "models/FGOutput.h"
 #include "models/FGInput.h"
 #include "initialization/FGTrim.h"
-#include "initialization/FGInitialCondition.h"
 #include "FGJSBBase.h"
 #include "input_output/FGPropertyManager.h"
 #include "input_output/FGGroundCallback.h"
@@ -60,7 +58,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.56 2010/11/18 20:37:10 jberndt Exp $"
+#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.63 2011/02/19 16:44:41 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -183,7 +181,7 @@ CLASS DOCUMENTATION
                                 property actually maps toa function call of DoTrim().
 
     @author Jon S. Berndt
-    @version $Revision: 1.56 $
+    @version $Revision: 1.63 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -286,8 +284,11 @@ public:
 
   /** Loads a script
       @param Script the full path name and file name for the script to be loaded.
+      @param deltaT The simulation integration step size, if given.  If no value is supplied
+                    then 0.0 is used and the value is expected to be supplied in
+                    the script file itself.
       @return true if successfully loadsd; false otherwise. */
-  bool LoadScript(const string& Script, double deltaT);
+  bool LoadScript(const string& Script, double deltaT=0.0);
 
   /** Sets the path to the engine config file directories.
       @param path path to the directory under which engine config
@@ -401,6 +402,9 @@ public:
     */
   bool SetOutputDirectives(const string& fname);
 
+  /** Forces the specified output object to print its items once */
+  void ForceOutput(int idx=0);
+
   /** Sets (or overrides) the output filename
       @param fname the name of the file to output data to
       @return true if successful, false if there is no output specified for the flight model */
@@ -514,7 +518,7 @@ public:
       @param rootDir the string containing the root directory. */
   void SetRootDir(const string& rootDir) {RootDir = rootDir;}
 
-  /** Retrieves teh Root Directory.
+  /** Retrieves the Root Directory.
       @return the string representing the root (base) JSBSim directory. */
   const string& GetRootDir(void) const {return RootDir;}
 
diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp
index f9bbc5415..0dbcf88ce 100644
--- a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp
+++ b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp
@@ -61,7 +61,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.56 2011/01/23 12:13:44 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.59 2011/04/03 13:18:51 bcoconni Exp $";
 static const char *IdHdr = ID_INITIALCONDITION;
 
 //******************************************************************************
@@ -700,6 +700,8 @@ void FGInitialCondition::SetAltitudeASLFtIC(double alt)
     case setve:
       SetVtrueFpsIC(ve0 * sqrt(rho/rhoSL));
       break;
+    default: // Make the compiler stop complaining about missing enums
+      break;
   }
 
   position.SetRadius(alt + sea_level_radius);
@@ -998,6 +1000,18 @@ bool FGInitialCondition::Load_v1(void)
     SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf"));
   }
 
+  // Refer to Stevens and Lewis, 1.5-14a, pg. 49.
+  // This is the rotation rate of the "Local" frame, expressed in the local frame.
+  double radInv = 1.0 / position.GetRadius();
+  FGColumnVector3 vOmegaLocal = FGColumnVector3(
+   radInv*vUVW_NED(eEast),
+  -radInv*vUVW_NED(eNorth),
+  -radInv*vUVW_NED(eEast)*position.GetTanLatitude() );
+
+  p = vOmegaLocal(eP);
+  q = vOmegaLocal(eR);
+  r = vOmegaLocal(eQ);
+
   return result;
 }
 
@@ -1032,7 +1046,7 @@ bool FGInitialCondition::Load_v2(void)
         if (position_el->FindElement("radius")) {
           position.SetRadius(position_el->FindElementValueAsNumberConvertTo("radius", "FT"));
         } else if (position_el->FindElement("altitudeAGL")) {
-          position.SetRadius(sea_level_radius + terrain_elevation + position_el->FindElementValueAsNumberConvertTo("altitude", "FT"));
+          position.SetRadius(sea_level_radius + terrain_elevation + position_el->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
         } else if (position_el->FindElement("altitudeMSL")) {
           position.SetRadius(sea_level_radius + position_el->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
         } else {
@@ -1096,7 +1110,7 @@ bool FGInitialCondition::Load_v2(void)
       //
       // Or, using quaternions (note reverse ordering compared to matrix representation):
       //
-      // Q_b/l = Q_e/l * Q_b/i
+      // Q_b/l = Q_i/l * Q_b/i
 
       FGQuaternion QuatI2Body = FGQuaternion(vOrient);
       QuatI2Body.Normalize();
@@ -1196,6 +1210,9 @@ bool FGInitialCondition::Load_v2(void)
   
   FGColumnVector3 vLocalRate;
   Element* attrate_el = document->FindElement("attitude_rate");
+
+  // Refer to Stevens and Lewis, 1.5-14a, pg. 49.
+  // This is the rotation rate of the "Local" frame, expressed in the local frame.
   double radInv = 1.0 / position.GetRadius();
   FGColumnVector3 vOmegaLocal = FGColumnVector3(
    radInv*vUVW_NED(eEast),
@@ -1209,11 +1226,11 @@ bool FGInitialCondition::Load_v2(void)
     FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC");
 
     if (frame == "eci") {
-      vLocalRate = Tl2b * (position.GetTi2l() * (vAttRate - vOmegaEarth) - vOmegaLocal);
+      vLocalRate = Tl2b * position.GetTi2l() * (vAttRate - vOmegaEarth);
     } else if (frame == "ecef") {
-      vLocalRate = Tl2b * (position.GetTec2l() * vAttRate - vOmegaLocal);
+      vLocalRate = Tl2b * position.GetTec2l() * vAttRate;
     } else if (frame == "local") {
-      vLocalRate = vAttRate;
+      vLocalRate = vAttRate + vOmegaLocal;
     } else if (!frame.empty()) { // misspelling of frame
       
       cerr << endl << fgred << "  Attitude rate frame type: \"" << frame
@@ -1221,11 +1238,11 @@ bool FGInitialCondition::Load_v2(void)
       result = false;
 
     } else if (frame.empty()) {
-    
+      vLocalRate = vOmegaLocal;
     }
-    
+
   } else { // Body frame attitude rate assumed 0 relative to local.
-      vLocalRate.InitMatrix();
+      vLocalRate = vOmegaLocal;
   }
 
   p = vLocalRate(eP);
diff --git a/src/FDM/JSBSim/initialization/FGTrim.cpp b/src/FDM/JSBSim/initialization/FGTrim.cpp
index 6b0cd81c0..cc863c85d 100644
--- a/src/FDM/JSBSim/initialization/FGTrim.cpp
+++ b/src/FDM/JSBSim/initialization/FGTrim.cpp
@@ -41,19 +41,10 @@ scheme. */
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include <cstdlib>
 #include <iomanip>
 #include "FGTrim.h"
-#include "models/FGAtmosphere.h"
-#include "FGInitialCondition.h"
-#include "models/FGAircraft.h"
-#include "models/FGMassBalance.h"
 #include "models/FGGroundReactions.h"
 #include "models/FGInertial.h"
-#include "models/FGAerodynamics.h"
-#include "models/FGPropulsion.h"
-#include "models/propulsion/FGEngine.h"
-#include "math/FGColumnVector3.h"
 
 #if _MSC_VER
 #pragma warning (disable : 4786 4788)
@@ -63,7 +54,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGTrim.cpp,v 1.13 2010/04/23 17:23:40 dpculp Exp $";
+static const char *IdSrc = "$Id: FGTrim.cpp,v 1.15 2011/02/19 16:29:29 bcoconni Exp $";
 static const char *IdHdr = ID_TRIM;
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -241,7 +232,7 @@ bool FGTrim::DoTrim(void) {
 
   fdmex->DisableOutput();
 
-  setEngineTrimMode(true);
+  fdmex->SetTrimStatus(true);
 
   fgic->SetPRadpsIC(0.0);
   fgic->SetQRadpsIC(0.0);
@@ -358,7 +349,7 @@ bool FGTrim::DoTrim(void) {
   for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
     fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
   }
-  setEngineTrimMode(false);
+  fdmex->SetTrimStatus(false);
   fdmex->EnableOutput();
   return !trim_failed;
 }
@@ -625,15 +616,6 @@ void FGTrim::setDebug(void) {
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTrim::setEngineTrimMode(bool mode) {
-  FGPropulsion* prop = fdmex->GetPropulsion();
-  for (unsigned int i=0; i<prop->GetNumEngines(); i++) {
-    prop->GetEngine(i)->SetTrimMode(mode);
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
 void FGTrim::SetMode(TrimMode tt) {
     ClearStates();
     mode=tt;
diff --git a/src/FDM/JSBSim/initialization/FGTrim.h b/src/FDM/JSBSim/initialization/FGTrim.h
index 0d6e3092c..518077f38 100644
--- a/src/FDM/JSBSim/initialization/FGTrim.h
+++ b/src/FDM/JSBSim/initialization/FGTrim.h
@@ -60,7 +60,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TRIM "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $"
+#define ID_TRIM "$Id: FGTrim.h,v 1.8 2011/01/24 13:01:55 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -120,7 +120,7 @@ CLASS DOCUMENTATION
     @endcode
     
     @author Tony Peden
-    @version "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $"
+    @version "$Id: FGTrim.h,v 1.8 2011/01/24 13:01:55 jberndt Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -176,7 +176,6 @@ private:
   void setupTurn(void);
 
   void updateRates(void);
-  void setEngineTrimMode(bool mode);
   void setDebug(void);
 
 public:
diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp
old mode 100644
new mode 100755
index c0218ec20..6d907924e
--- a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp
+++ b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp
@@ -49,17 +49,17 @@ COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
 namespace JSBSim {
 
 bool FGPropertyManager::suppress_warning = true;
-std::vector<std::string> FGPropertyManager::tied_properties;
+std::vector<SGPropertyNode_ptr> FGPropertyManager::tied_properties;
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 void FGPropertyManager::Unbind(void)
 {
-    vector<string>::iterator it;
+    vector<SGPropertyNode_ptr>::iterator it;
+
     for (it = tied_properties.begin();it < tied_properties.end();it++)
-    {
-        Untie(*it);
-    }
+        (*it)->untie();
+
     tied_properties.clear();
 }
 
@@ -102,7 +102,6 @@ FGPropertyManager::GetNode (const string &relpath, int index, bool create)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-
 bool FGPropertyManager::HasNode (const string &path)
 {
   // Checking if a node exists shouldn't write a warning if it doesn't exist
@@ -314,11 +313,17 @@ void FGPropertyManager::Untie (const string &name)
 
 void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
 {
-  if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer), useDefault))
+  SGPropertyNode* property = getNode(name.c_str(), true);
+  if (!property) {
+    cerr << "Could not get or create property " << name << endl;
+    return;
+  }
+
+  if (!property->tie(SGRawValuePointer<bool>(pointer), useDefault))
     cerr << "Failed to tie property " << name << " to a pointer" << endl;
   else {
-    tied_properties.push_back(name);
-    if (debug_lvl & 0x20) std::cout << name << std::endl;
+    tied_properties.push_back(property);
+    if (debug_lvl & 0x20) cout << name << endl;
   }
 }
 
@@ -327,11 +332,17 @@ void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
 void FGPropertyManager::Tie (const string &name, int *pointer,
                                           bool useDefault )
 {
-  if (!tie(name.c_str(), SGRawValuePointer<int>(pointer), useDefault))
+  SGPropertyNode* property = getNode(name.c_str(), true);
+  if (!property) {
+    cerr << "Could not get or create property " << name << endl;
+    return;
+  }
+
+  if (!property->tie(SGRawValuePointer<int>(pointer), useDefault))
     cerr << "Failed to tie property " << name << " to a pointer" << endl;
   else {
-    tied_properties.push_back(name);
-    if (debug_lvl & 0x20) std::cout << name << std::endl;
+    tied_properties.push_back(property);
+    if (debug_lvl & 0x20) cout << name << endl;
   }
 }
 
@@ -340,11 +351,17 @@ void FGPropertyManager::Tie (const string &name, int *pointer,
 void FGPropertyManager::Tie (const string &name, long *pointer,
                                           bool useDefault )
 {
-  if (!tie(name.c_str(), SGRawValuePointer<long>(pointer), useDefault))
+  SGPropertyNode* property = getNode(name.c_str(), true);
+  if (!property) {
+    cerr << "Could not get or create property " << name << endl;
+    return;
+  }
+
+  if (!property->tie(SGRawValuePointer<long>(pointer), useDefault))
     cerr << "Failed to tie property " << name << " to a pointer" << endl;
   else {
-    tied_properties.push_back(name);
-    if (debug_lvl & 0x20) std::cout << name << std::endl;
+    tied_properties.push_back(property);
+    if (debug_lvl & 0x20) cout << name << endl;
   }
 }
 
@@ -353,11 +370,17 @@ void FGPropertyManager::Tie (const string &name, long *pointer,
 void FGPropertyManager::Tie (const string &name, float *pointer,
                                           bool useDefault )
 {
-  if (!tie(name.c_str(), SGRawValuePointer<float>(pointer), useDefault))
+  SGPropertyNode* property = getNode(name.c_str(), true);
+  if (!property) {
+    cerr << "Could not get or create property " << name << endl;
+    return;
+  }
+
+  if (!property->tie(SGRawValuePointer<float>(pointer), useDefault))
     cerr << "Failed to tie property " << name << " to a pointer" << endl;
   else {
-    tied_properties.push_back(name);
-    if (debug_lvl & 0x20) std::cout << name << std::endl;
+    tied_properties.push_back(property);
+    if (debug_lvl & 0x20) cout << name << endl;
   }
 }
 
@@ -365,11 +388,17 @@ void FGPropertyManager::Tie (const string &name, float *pointer,
 
 void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault)
 {
-  if (!tie(name.c_str(), SGRawValuePointer<double>(pointer), useDefault))
+  SGPropertyNode* property = getNode(name.c_str(), true);
+  if (!property) {
+    cerr << "Could not get or create property " << name << endl;
+    return;
+  }
+
+  if (!property->tie(SGRawValuePointer<double>(pointer), useDefault))
     cerr << "Failed to tie property " << name << " to a pointer" << endl;
   else {
-    tied_properties.push_back(name);
-    if (debug_lvl & 0x20) std::cout << name << std::endl;
+    tied_properties.push_back(property);
+    if (debug_lvl & 0x20) cout << name << endl;
   }
 }
 
diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.h b/src/FDM/JSBSim/input_output/FGPropertyManager.h
index a08f89681..f877bfcdd 100644
--- a/src/FDM/JSBSim/input_output/FGPropertyManager.h
+++ b/src/FDM/JSBSim/input_output/FGPropertyManager.h
@@ -53,7 +53,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.17 2010/07/08 11:36:28 jberndt Exp $"
+#define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.20 2011/02/13 00:42:45 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -77,7 +77,7 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
 {
   private:
     static bool suppress_warning;
-    static std::vector<std::string> tied_properties;
+    static std::vector<SGPropertyNode_ptr> tied_properties;
   public:
     /// Constructor
     FGPropertyManager(void) {suppress_warning = false;}
@@ -532,10 +532,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
     template <class V> inline void
     Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true)
     {
-      if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter), useDefault))
-        std::cout << "Failed to tie property " << name << " to functions" << std::endl;
+      SGPropertyNode* property = getNode(name.c_str(), true);
+      if (!property) {
+        std::cerr << "Could not get or create property " << name << std::endl;
+        return;
+      }
+
+      if (!property->tie(SGRawValueFunctions<V>(getter, setter), useDefault))
+        std::cerr << "Failed to tie property " << name << " to functions" << std::endl;
       else {
-        tied_properties.push_back(name);
+        tied_properties.push_back(property);
         if (debug_lvl & 0x20) std::cout << name << std::endl;
       }
     }
@@ -562,10 +568,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
     template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
                                 void (*setter)(int, V) = 0, bool useDefault = true)
     {
-      if (!tie(name.c_str(), SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
-        std::cout << "Failed to tie property " << name << " to indexed functions" << std::endl;
+      SGPropertyNode* property = getNode(name.c_str(), true);
+      if (!property) {
+        std::cerr << "Could not get or create property " << name << std::endl;
+        return;
+      }
+
+      if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
+        std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl;
       else {
-        tied_properties.push_back(name);
+        tied_properties.push_back(property);
         if (debug_lvl & 0x20) std::cout << name << std::endl;
       }
     }
@@ -594,10 +606,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
     Tie (const std::string &name, T * obj, V (T::*getter)() const,
            void (T::*setter)(V) = 0, bool useDefault = true)
     {
-      if (!tie(name.c_str(), SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
-        std::cout << "Failed to tie property " << name << " to object methods" << std::endl;
+      SGPropertyNode* property = getNode(name.c_str(), true);
+      if (!property) {
+        std::cerr << "Could not get or create property " << name << std::endl;
+        return;
+      }
+
+      if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
+        std::cerr << "Failed to tie property " << name << " to object methods" << std::endl;
       else {
-        tied_properties.push_back(name);
+        tied_properties.push_back(property);
         if (debug_lvl & 0x20) std::cout << name << std::endl;
       }
     }
@@ -625,10 +643,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
     Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
                          void (T::*setter)(int, V) = 0, bool useDefault = true)
     {
-      if (!tie(name.c_str(), SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
-        std::cout << "Failed to tie property " << name << " to indexed object methods" << std::endl;
+      SGPropertyNode* property = getNode(name.c_str(), true);
+      if (!property) {
+        std::cerr << "Could not get or create property " << name << std::endl;
+        return;
+      }
+
+      if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
+        std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl;
       else {
-        tied_properties.push_back(name);
+        tied_properties.push_back(property);
         if (debug_lvl & 0x20) std::cout << name << std::endl;
       }
    }
diff --git a/src/FDM/JSBSim/input_output/FGScript.cpp b/src/FDM/JSBSim/input_output/FGScript.cpp
old mode 100644
new mode 100755
index e20e8c1f2..60d39ed9b
--- a/src/FDM/JSBSim/input_output/FGScript.cpp
+++ b/src/FDM/JSBSim/input_output/FGScript.cpp
@@ -54,7 +54,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGScript.cpp,v 1.43 2011/01/16 15:27:34 jberndt Exp $";
+static const char *IdSrc = "$Id: FGScript.cpp,v 1.46 2011/02/18 12:44:16 jberndt Exp $";
 static const char *IdHdr = ID_FGSCRIPT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -78,12 +78,19 @@ FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
 
 FGScript::~FGScript()
 {
-  unsigned int i;
+  unsigned int i, j;
 
-  for (i=0; i<local_properties.size(); i++) delete local_properties[i];
+  for (i=0; i<local_properties.size(); i++) {
+    delete local_properties[i]->value;
+    delete local_properties[i];
+  }
   local_properties.clear();
 
-  for (i=0; i<Events.size(); i++) delete Events[i].Condition;
+  for (i=0; i<Events.size(); i++) {
+    delete Events[i].Condition;
+    for (j=0; j<Events[i].Functions.size(); j++)
+      delete Events[i].Functions[j];
+  }
   Events.clear();
 
   Debug(1);
@@ -139,6 +146,8 @@ bool FGScript::LoadScript(string script, double deltaT)
   StartTime = run_element->GetAttributeValueAsNumber("start");
   FDMExec->Setsim_time(StartTime);
   EndTime   = run_element->GetAttributeValueAsNumber("end");
+  // Make sure that the desired time is reached and executed.
+  EndTime += 0.99*FDMExec->GetDeltaT();
 
   if (deltaT == 0.0)
     dt = run_element->GetAttributeValueAsNumber("dt");
@@ -240,11 +249,13 @@ bool FGScript::LoadScript(string script, double deltaT)
         newCondition = new FGCondition(condition_element, PropertyManager);
       } catch(string str) {
         cout << endl << fgred << str << reset << endl << endl;
+        delete newEvent;
         return false;
       }
       newEvent->Condition = newCondition;
     } else {
       cerr << "No condition specified in script event " << newEvent->Name << endl;
+      delete newEvent;
       return false;
     }
 
@@ -258,16 +269,29 @@ bool FGScript::LoadScript(string script, double deltaT)
     // Notify about when this event is triggered?
     if ((notify_element = event_element->FindElement("notify")) != 0) {
       newEvent->Notify = true;
+      // Check here for new <description> tag that gets echoed
+      string notify_description = notify_element->FindElementValue("description");
+      if (!notify_description.empty()) {
+        newEvent->Description = notify_description;
+      }
       notify_property_element = notify_element->FindElement("property");
       while (notify_property_element) {
         notifyPropertyName = notify_property_element->GetDataLine();
         if (PropertyManager->GetNode(notifyPropertyName)) {
           newEvent->NotifyProperties.push_back( PropertyManager->GetNode(notifyPropertyName) );
+          string caption_attribute = notify_property_element->GetAttributeValue("caption");
+          if (caption_attribute.empty()) {
+            newEvent->DisplayString.push_back(notifyPropertyName);
+          } else {
+            newEvent->DisplayString.push_back(caption_attribute);
+          }
         } else {
           cout << endl << fgred << "  Could not find the property named "
                << notifyPropertyName << " in script" << endl << "  \""
                << ScriptName << "\". Execution is aborted. Please recheck "
                << "your input files and scripts." << reset << endl;
+          delete newEvent->Condition;
+          delete newEvent;
           return false;
         }
         notify_property_element = notify_element->FindNextElement("property");
@@ -339,7 +363,7 @@ bool FGScript::RunScript(void)
   double currentTime = FDMExec->GetSimTime();
   double newSetValue = 0;
 
-  if (currentTime > EndTime) return false; //Script done!
+  if (currentTime > EndTime) return false;
 
   // Iterate over all events.
   for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
@@ -426,8 +450,12 @@ bool FGScript::RunScript(void)
       if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
         cout << endl << "  Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
              << " executed at time: " << currentTime << endl;
+        if (!Events[ev_ctr].Description.empty()) {
+          cout << "    " << Events[ev_ctr].Description << endl;
+        }
         for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
-          cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
+//          cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
+          cout << "    " << Events[ev_ctr].DisplayString[j]
                << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
         }
         cout << endl;
diff --git a/src/FDM/JSBSim/input_output/FGScript.h b/src/FDM/JSBSim/input_output/FGScript.h
index 9f8d3ef8e..1ef0cfaa3 100644
--- a/src/FDM/JSBSim/input_output/FGScript.h
+++ b/src/FDM/JSBSim/input_output/FGScript.h
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FGSCRIPT "$Id: FGScript.h,v 1.18 2010/04/11 13:44:42 jberndt Exp $"
+#define ID_FGSCRIPT "$Id: FGScript.h,v 1.20 2011/02/11 12:43:28 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -157,7 +157,7 @@ CLASS DOCUMENTATION
     comes the &quot;run&quot; section, where the conditions are
     described in &quot;event&quot; clauses.</p>
     @author Jon S. Berndt
-    @version "$Id: FGScript.h,v 1.18 2010/04/11 13:44:42 jberndt Exp $"
+    @version "$Id: FGScript.h,v 1.20 2011/02/11 12:43:28 jberndt Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -178,7 +178,7 @@ public:
       has been supplied on the command line, it will be override the script-
       specified simulation step size.
       @param script the filename (including path name, if any) for the script.
-      @param deltaT a simulation step size from the command line
+      @param deltaT a simulation step size.
       @return true if successful */
   bool LoadScript(string script, double deltaT);
 
@@ -215,8 +215,10 @@ private:
     double           StartTime;
     double           TimeSpan;
     string           Name;
+    string           Description;
     vector <FGPropertyManager*>  SetParam;
     vector <FGPropertyManager*>  NotifyProperties;
+    vector <string>              DisplayString;
     vector <eAction> Action;
     vector <eType>   Type;
     vector <double>  SetValue;
diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.cpp b/src/FDM/JSBSim/input_output/FGXMLElement.cpp
old mode 100644
new mode 100755
index 832b2c8c6..383603d32
--- a/src/FDM/JSBSim/input_output/FGXMLElement.cpp
+++ b/src/FDM/JSBSim/input_output/FGXMLElement.cpp
@@ -42,7 +42,7 @@ FORWARD DECLARATIONS
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.31 2010/09/29 02:22:03 jberndt Exp $";
+static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.32 2011/02/13 00:42:45 jberndt Exp $";
 static const char *IdHdr = ID_XMLELEMENT;
 
 bool Element::converterIsInitialized = false;
@@ -64,6 +64,8 @@ Element::Element(const string& nm)
     // Length
     convert["M"]["FT"] = 3.2808399;
     convert["FT"]["M"] = 1.0/convert["M"]["FT"];
+    convert["KM"]["FT"] = 3280.8399;
+    convert["FT"]["KM"] = 1.0/convert["KM"]["FT"];
     convert["FT"]["IN"] = 12.0;
     convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
     convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
@@ -121,6 +123,8 @@ Element::Element(const string& nm)
     convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
     convert["M/SEC"]["FT/SEC"] = 3.2808399;
     convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"];
+    convert["KM/SEC"]["FT/SEC"] = 3280.8399;
+    convert["FT/SEC"]["KM/SEC"] = 1.0/convert["KM/SEC"]["FT/SEC"];
     // Torque
     convert["FT*LBS"]["N*M"] = 1.35581795;
     convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
@@ -153,6 +157,7 @@ Element::Element(const string& nm)
 
     // Length
     convert["M"]["M"] = 1.00;
+    convert["KM"]["KM"] = 1.00;
     convert["FT"]["FT"] = 1.00;
     convert["IN"]["IN"] = 1.00;
     // Area
@@ -195,6 +200,7 @@ Element::Element(const string& nm)
     convert["KTS"]["KTS"] = 1.00;
     convert["M/S"]["M/S"] = 1.0;
     convert["M/SEC"]["M/SEC"] = 1.0;
+    convert["KM/SEC"]["KM/SEC"] = 1.0;
     // Torque
     convert["FT*LBS"]["FT*LBS"] = 1.00;
     convert["N*M"]["N*M"] = 1.00;
diff --git a/src/FDM/JSBSim/math/FGCondition.cpp b/src/FDM/JSBSim/math/FGCondition.cpp
index 2a1ffd47f..7f7e9057e 100644
--- a/src/FDM/JSBSim/math/FGCondition.cpp
+++ b/src/FDM/JSBSim/math/FGCondition.cpp
@@ -35,6 +35,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGCondition.h"
+#include "FGPropertyValue.h"
 #include "input_output/FGXMLElement.h"
 #include "input_output/FGPropertyManager.h"
 #include <iostream>
@@ -44,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGCondition.cpp,v 1.13 2010/07/14 05:50:40 ehofman Exp $";
+static const char *IdSrc = "$Id: FGCondition.cpp,v 1.14 2011/04/05 20:20:21 andgi Exp $";
 static const char *IdHdr = ID_CONDITION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -122,12 +123,11 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
     exit(-1);
   }
 
-  TestParam1 = PropertyManager->GetNode(property1, false);
-  if (!TestParam1) {
-      cerr << fgred << "  In condition: " << test << ". Unknown property "
-           << property1 << " referenced." << endl
-           << "Creating property.  Check usage." << reset << endl;
-      TestParam1 = PropertyManager->GetNode(property1, true);
+  FGPropertyManager *node = PropertyManager->GetNode(property1, false);
+  if (node) {
+    TestParam1 = new FGPropertyValue(node);
+  } else {
+    TestParam1 = new FGPropertyValue(property1, PropertyManager);
   }
   Comparison = mComparison[conditional];
   if (Comparison == ecUndef) {
@@ -136,12 +136,11 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
   if (is_number(property2)) {
     TestValue = atof(property2.c_str());
   } else {
-    TestParam2 = PropertyManager->GetNode(property2, false);
-    if (!TestParam2) {
-        cerr << fgred << "  In condition: " << test << ". Unknown property "
-             << property2 << " referenced." << endl
-             << "Creating property.  Check usage." << reset << endl;
-        TestParam2 = PropertyManager->GetNode(property2, true);
+    node = PropertyManager->GetNode(property2, false);
+    if (node) {
+      TestParam2 = new FGPropertyValue(node);
+    } else {
+      TestParam2 = new FGPropertyValue(property2, PropertyManager);
     }
   }
 }
@@ -267,11 +266,11 @@ void FGCondition::PrintCondition(void )
 
   } else {
     if (TestParam2 != 0L)
-      cout << "    " << TestParam1->GetRelativeName() << " "
+      cout << "    " << TestParam1->GetName() << " "
     		         << conditional << " "
-    		         << TestParam2->GetRelativeName();
+    		         << TestParam2->GetName();
     else
-      cout << "    " << TestParam1->GetRelativeName() << " "
+      cout << "    " << TestParam1->GetName() << " "
                      << conditional << " " << TestValue;
   }
 }
diff --git a/src/FDM/JSBSim/math/FGCondition.h b/src/FDM/JSBSim/math/FGCondition.h
index 2cd75bdfb..06632a76d 100644
--- a/src/FDM/JSBSim/math/FGCondition.h
+++ b/src/FDM/JSBSim/math/FGCondition.h
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_CONDITION "$Id: FGCondition.h,v 1.5 2009/10/24 22:59:30 jberndt Exp $"
+#define ID_CONDITION "$Id: FGCondition.h,v 1.6 2011/04/05 20:20:21 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -53,6 +53,7 @@ FORWARD DECLARATIONS
 namespace JSBSim {
 
 class FGPropertyManager;
+class FGPropertyValue;
 class Element;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -82,7 +83,8 @@ private:
   std::map <std::string, eComparison> mComparison;
   eLogic Logic;
 
-  FGPropertyManager *TestParam1, *TestParam2, *PropertyManager;
+  FGPropertyManager *PropertyManager;
+  FGPropertyValue *TestParam1, *TestParam2;
   double TestValue;
   eComparison Comparison;
   bool isGroup;
diff --git a/src/FDM/JSBSim/math/FGFunction.cpp b/src/FDM/JSBSim/math/FGFunction.cpp
old mode 100644
new mode 100755
index 9ad7c7a99..c0d2e6afd
--- a/src/FDM/JSBSim/math/FGFunction.cpp
+++ b/src/FDM/JSBSim/math/FGFunction.cpp
@@ -43,7 +43,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFunction.cpp,v 1.35 2010/08/28 12:41:56 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFunction.cpp,v 1.36 2011/04/05 20:20:21 andgi Exp $";
 static const char *IdHdr = ID_FUNCTION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -177,9 +177,10 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
         newNode = PropertyManager->GetNode(property_name);
         Parameters.push_back(new FGPropertyValue( newNode ));
       } else {
-        cerr << fgcyan << "The property " + property_name + " is initially undefined."
+        cerr << fgcyan << "Warning: The property " + property_name + " is initially undefined."
              << reset << endl;
-        Parameters.push_back(new FGPropertyValue( property_name ));
+        Parameters.push_back(new FGPropertyValue( property_name,
+                                                  PropertyManager ));
       }
     } else if (operation == value_string || operation == v_string) {
       Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
@@ -252,17 +253,8 @@ double FGFunction::GetValue(void) const
 
   if (cached) return cachedValue;
 
-  try {
-    temp = Parameters[0]->GetValue();
-  } catch (string prop) {
-    if (PropertyManager->HasNode(prop)) {
-      ((FGPropertyValue*)Parameters[0])->SetNode(PropertyManager->GetNode(prop));
-      temp = Parameters[0]->GetValue();
-    } else {
-      throw("Property " + prop + " was not defined anywhere.");
-    }
-  }
-
+  temp = Parameters[0]->GetValue();
+  
   switch (Type) {
   case eTopLevel:
     break;
diff --git a/src/FDM/JSBSim/math/FGParameter.h b/src/FDM/JSBSim/math/FGParameter.h
old mode 100644
new mode 100755
index 85b43b1af..c1d66fc20
--- a/src/FDM/JSBSim/math/FGParameter.h
+++ b/src/FDM/JSBSim/math/FGParameter.h
@@ -40,7 +40,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PARAMETER "$Id: FGParameter.h,v 1.5 2009/08/30 03:51:28 jberndt Exp $"
+#define ID_PARAMETER "$Id: FGParameter.h,v 1.6 2011/04/05 20:20:21 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -65,6 +65,10 @@ class FGParameter : public FGJSBBase
 public:
   virtual ~FGParameter(void) {};
   virtual double GetValue(void) const = 0;
+  virtual std::string GetName(void) const = 0;
+
+  // SGPropertyNode impersonation.
+  double getDoubleValue(void) const { return GetValue(); }
 
 protected:
 };
diff --git a/src/FDM/JSBSim/math/FGPropertyValue.cpp b/src/FDM/JSBSim/math/FGPropertyValue.cpp
old mode 100644
new mode 100755
index 0824a607b..7f448da3c
--- a/src/FDM/JSBSim/math/FGPropertyValue.cpp
+++ b/src/FDM/JSBSim/math/FGPropertyValue.cpp
@@ -6,6 +6,7 @@ Date started: 12/10/2004
 Purpose: Stores property values
 
  ------------- Copyright (C) 2001  Jon S. Berndt (jon@jsbsim.org) -------------
+ ------ Copyright (C) 2010 - 2011  Anders Gidenstam (anders(at)gidenstam.org) -
 
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free Software
@@ -32,36 +33,53 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.6 2010/08/24 10:30:14 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.7 2011/04/05 20:20:21 andgi Exp $";
 static const char *IdHdr = ID_PROPERTYVALUE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode) : PropertyManager(propNode)
+FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode)
+  : PropertyManager(0L), PropertyNode(propNode)
 {
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGPropertyValue::FGPropertyValue(std::string propName) : PropertyManager(0L)
+FGPropertyValue::FGPropertyValue(std::string propName, FGPropertyManager* propertyManager)
+  : PropertyManager(propertyManager), PropertyNode(0L), PropertyName(propName)
 {
-  PropertyName = propName;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 double FGPropertyValue::GetValue(void) const
 {
-  double val;
-  try {
-    val = PropertyManager->getDoubleValue();
-  } catch (...) {
-    throw(PropertyName);
+  FGPropertyManager* node = PropertyNode;
+
+  if (!PropertyNode) {
+    // The node cannot be cached since this is a const method.
+    node = PropertyManager->GetNode(PropertyName);
+    
+    if (!node) {
+      throw(std::string("FGPropertyValue::GetValue() The property " +
+                        PropertyName + " does not exist."));
+    }
   }
 
-  return val;
+  return node->getDoubleValue();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+std::string FGPropertyValue::GetName(void) const
+{
+  if (PropertyNode) {
+    return PropertyNode->GetName();
+  } else {
+    return PropertyName;
+  }
 }
 
 }
diff --git a/src/FDM/JSBSim/math/FGPropertyValue.h b/src/FDM/JSBSim/math/FGPropertyValue.h
old mode 100644
new mode 100755
index 753df7c62..c716cf599
--- a/src/FDM/JSBSim/math/FGPropertyValue.h
+++ b/src/FDM/JSBSim/math/FGPropertyValue.h
@@ -5,6 +5,7 @@ Author: Jon Berndt
 Date started: December 10 2004
 
  ------------- Copyright (C) 2001  Jon S. Berndt (jon@jsbsim.org) -------------
+ ------ Copyright (C) 2010 - 2011  Anders Gidenstam (anders(at)gidenstam.org) -
 
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free Software
@@ -41,7 +42,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.8 2010/08/24 10:30:14 jberndt Exp $"
+#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.9 2011/04/05 20:20:21 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -53,8 +54,8 @@ namespace JSBSim {
 CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-  /** Represents a property value
-      @author Jon Berndt
+  /** Represents a property value which can use late binding.
+      @author Jon Berndt, Anders Gidenstam
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -66,14 +67,17 @@ class FGPropertyValue : public FGParameter
 public:
 
   FGPropertyValue(FGPropertyManager* propNode);
-  FGPropertyValue(std::string propName);
+  FGPropertyValue(std::string propName, FGPropertyManager* propertyManager);
   ~FGPropertyValue() {};
 
   double GetValue(void) const;
-  void SetNode(FGPropertyManager* node) {PropertyManager = node;} 
+  void SetNode(FGPropertyManager* node) {PropertyNode = node;} 
+
+  std::string GetName(void) const;
 
 private:
-  FGPropertyManager* PropertyManager;
+  FGPropertyManager* PropertyManager; // Property root used to do late binding.
+  FGPropertyManager* PropertyNode;
   std::string PropertyName;
 };
 
diff --git a/src/FDM/JSBSim/math/FGRealValue.h b/src/FDM/JSBSim/math/FGRealValue.h
index 277c595c1..9564eabf7 100644
--- a/src/FDM/JSBSim/math/FGRealValue.h
+++ b/src/FDM/JSBSim/math/FGRealValue.h
@@ -40,7 +40,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_REALVALUE "$Id: FGRealValue.h,v 1.4 2009/08/30 03:51:28 jberndt Exp $"
+#define ID_REALVALUE "$Id: FGRealValue.h,v 1.5 2011/04/05 20:20:21 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -68,6 +68,7 @@ public:
   ~FGRealValue() {};
 
   double GetValue(void) const;
+  std::string GetName(void) const {return "constant";}
 
 private:
   double Value;
diff --git a/src/FDM/JSBSim/math/FGTable.h b/src/FDM/JSBSim/math/FGTable.h
index 2f2e271cd..3d2224981 100644
--- a/src/FDM/JSBSim/math/FGTable.h
+++ b/src/FDM/JSBSim/math/FGTable.h
@@ -47,7 +47,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TABLE "$Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $"
+#define ID_TABLE "$Id: FGTable.h,v 1.13 2011/04/05 20:20:21 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
 @endcode
 
 @author Jon S. Berndt
-@version $Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $
+@version $Id: FGTable.h,v 1.13 2011/04/05 20:20:21 andgi Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -292,6 +292,8 @@ public:
 
   void Print(void);
 
+  std::string GetName(void) const {return Name;}
+
 private:
   enum type {tt1D, tt2D, tt3D} Type;
   enum axis {eRow=0, eColumn, eTable};
diff --git a/src/FDM/JSBSim/models/FGAerodynamics.cpp b/src/FDM/JSBSim/models/FGAerodynamics.cpp
index 21583363b..0f08c0160 100644
--- a/src/FDM/JSBSim/models/FGAerodynamics.cpp
+++ b/src/FDM/JSBSim/models/FGAerodynamics.cpp
@@ -52,7 +52,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.36 2011/01/19 12:41:19 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.37 2011/03/11 13:02:26 jberndt Exp $";
 static const char *IdHdr = ID_AERODYNAMICS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -80,7 +80,7 @@ FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
 
   axisType = atNone;
 
-  Coeff = new CoeffArray[6];
+  AeroFunctions = new AeroFunctionArray[6];
 
   impending_stall = stall_hyst = 0.0;
   alphaclmin = alphaclmax = 0.0;
@@ -103,10 +103,10 @@ FGAerodynamics::~FGAerodynamics()
   unsigned int i,j;
 
   for (i=0; i<6; i++)
-    for (j=0; j<Coeff[i].size(); j++)
-      delete Coeff[i][j];
+    for (j=0; j<AeroFunctions[i].size(); j++)
+      delete AeroFunctions[i][j];
 
-  delete[] Coeff;
+  delete[] AeroFunctions;
 
   delete AeroRPShift;
 
@@ -142,7 +142,7 @@ bool FGAerodynamics::Run(void)
   const double alpha=FDMExec->GetAuxiliary()->Getalpha();
   const double twovel=2*FDMExec->GetAuxiliary()->GetVt();
   const double qbar = FDMExec->GetAuxiliary()->Getqbar();
-  const double wingarea = FDMExec->GetAircraft()->GetWingArea();
+  const double wingarea = FDMExec->GetAircraft()->GetWingArea();  // TODO: Make these constants constant!
   const double wingspan = FDMExec->GetAircraft()->GetWingSpan();
   const double wingchord = FDMExec->GetAircraft()->Getcbar();
   const double wingincidence = FDMExec->GetAircraft()->GetWingIncidence();
@@ -177,8 +177,8 @@ bool FGAerodynamics::Run(void)
   vFnative.InitMatrix();
 
   for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
-    for (ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) {
-      vFnative(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue();
+    for (ctr=0; ctr < AeroFunctions[axis_ctr].size(); ctr++) {
+      vFnative(axis_ctr+1) += AeroFunctions[axis_ctr][ctr]->GetValue();
     }
   }
 
@@ -224,8 +224,8 @@ bool FGAerodynamics::Run(void)
   vMoments = vDXYZcg*vForces; // M = r X F
 
   for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
-    for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) {
-      vMoments(axis_ctr+1) += Coeff[axis_ctr+3][ctr]->GetValue();
+    for (ctr = 0; ctr < AeroFunctions[axis_ctr+3].size(); ctr++) {
+      vMoments(axis_ctr+1) += AeroFunctions[axis_ctr+3][ctr]->GetValue();
     }
   }
 
@@ -349,7 +349,7 @@ bool FGAerodynamics::Load(Element *element)
 
   axis_element = document->FindElement("axis");
   while (axis_element) {
-    CoeffArray ca;
+    AeroFunctionArray ca;
     axis = axis_element->GetAttributeValue("name");
     function_element = axis_element->FindElement("function");
     while (function_element) {
@@ -363,7 +363,7 @@ bool FGAerodynamics::Load(Element *element)
       }
       function_element = axis_element->FindNextElement("function");
     }
-    Coeff[AxisIdx[axis]] = ca;
+    AeroFunctions[AxisIdx[axis]] = ca;
     axis_element = document->FindNextElement("axis");
   }
 
@@ -427,35 +427,35 @@ void FGAerodynamics::DetermineAxisSystem()
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGAerodynamics::GetCoefficientStrings(const string& delimeter) const
+string FGAerodynamics::GetAeroFunctionStrings(const string& delimeter) const
 {
-  string CoeffStrings = "";
+  string AeroFunctionStrings = "";
   bool firstime = true;
   unsigned int axis, sd;
 
   for (axis = 0; axis < 6; axis++) {
-    for (sd = 0; sd < Coeff[axis].size(); sd++) {
+    for (sd = 0; sd < AeroFunctions[axis].size(); sd++) {
       if (firstime) {
         firstime = false;
       } else {
-        CoeffStrings += delimeter;
+        AeroFunctionStrings += delimeter;
       }
-      CoeffStrings += Coeff[axis][sd]->GetName();
+      AeroFunctionStrings += AeroFunctions[axis][sd]->GetName();
     }
   }
-  return CoeffStrings;
+  return AeroFunctionStrings;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGAerodynamics::GetCoefficientValues(const string& delimeter) const
+string FGAerodynamics::GetAeroFunctionValues(const string& delimeter) const
 {
   ostringstream buf;
 
   for (unsigned int axis = 0; axis < 6; axis++) {
-    for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) {
+    for (unsigned int sd = 0; sd < AeroFunctions[axis].size(); sd++) {
       if (buf.tellp() > 0) buf << delimeter;
-      buf << setw(9) << Coeff[axis][sd]->GetValue();
+      buf << setw(9) << AeroFunctions[axis][sd]->GetValue();
     }
   }
 
diff --git a/src/FDM/JSBSim/models/FGAerodynamics.h b/src/FDM/JSBSim/models/FGAerodynamics.h
index a5e278195..c6638b411 100644
--- a/src/FDM/JSBSim/models/FGAerodynamics.h
+++ b/src/FDM/JSBSim/models/FGAerodynamics.h
@@ -52,7 +52,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.21 2010/11/18 12:38:06 jberndt Exp $"
+#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.22 2011/03/11 13:02:26 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -89,7 +89,7 @@ CLASS DOCUMENTATION
          {function contents}
        </function>
        <axis name="{LIFT | DRAG | SIDE | ROLL | PITCH | YAW}">
-         {force coefficient definitions}
+         {force or moment definitions}
        </axis>
        {additional axis definitions}
     </aerodynamics>
@@ -103,13 +103,13 @@ CLASS DOCUMENTATION
     <br>
     2) Axial-Normal coordinate system:
     @code
-       <axis name="{AXIAL | NORMAL}">
+       <axis name="{AXIAL | NORMAL | SIDE}">
     @endcode
     <br>
     Systems may NOT be combined, or a load error will occur.
 
     @author Jon S. Berndt, Tony Peden
-    @version $Revision: 1.21 $
+    @version $Revision: 1.22 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -186,16 +186,16 @@ public:
   void SetAlphaCLMax(double tt) { alphaclmax=tt; }
   void SetAlphaCLMin(double tt) { alphaclmin=tt; }
 
-  /** Gets the strings for the current set of coefficients.
+  /** Gets the strings for the current set of aero functions.
       @param delimeter either a tab or comma string depending on output type
-      @return a string containing the descriptive names for all coefficients */
-  std::string GetCoefficientStrings(const std::string& delimeter) const;
+      @return a string containing the descriptive names for all aero functions */
+  std::string GetAeroFunctionStrings(const std::string& delimeter) const;
 
-  /** Gets the coefficient values.
+  /** Gets the aero function values.
       @param delimeter either a tab or comma string depending on output type
       @return a string containing the numeric values for the current set of
-      coefficients */
-  std::string GetCoefficientValues(const std::string& delimeter) const;
+      aero functions */
+  std::string GetAeroFunctionValues(const std::string& delimeter) const;
 
   /** Calculates and returns the wind-to-body axis transformation matrix.
       @return a reference to the wind-to-body transformation matrix.
@@ -207,15 +207,15 @@ public:
       */
   FGMatrix33& GetTb2w(void);
 
-  std::vector <FGFunction*> * GetCoeff(void) const { return Coeff; }
+  std::vector <FGFunction*> * GetAeroFunctions(void) const { return AeroFunctions; }
 
 private:
   enum eAxisType {atNone, atLiftDrag, atAxialNormal, atBodyXYZ} axisType;
   typedef std::map<std::string,int> AxisIndex;
   AxisIndex AxisIdx;
   FGFunction* AeroRPShift;
-  typedef vector <FGFunction*> CoeffArray;
-  CoeffArray* Coeff;
+  typedef vector <FGFunction*> AeroFunctionArray;
+  AeroFunctionArray* AeroFunctions;
   FGColumnVector3 vFnative;
   FGColumnVector3 vFw;
   FGColumnVector3 vForces;
diff --git a/src/FDM/JSBSim/models/FGAtmosphere.cpp b/src/FDM/JSBSim/models/FGAtmosphere.cpp
index f40fabcb5..992e7952e 100644
--- a/src/FDM/JSBSim/models/FGAtmosphere.cpp
+++ b/src/FDM/JSBSim/models/FGAtmosphere.cpp
@@ -61,7 +61,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.41 2010/11/30 12:19:57 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.42 2011/02/18 12:44:16 jberndt Exp $";
 static const char *IdHdr = ID_ATMOSPHERE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -124,6 +124,7 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
 
 FGAtmosphere::~FGAtmosphere()
 {
+  delete(POE_Table);
   Debug(1);
 }
 
diff --git a/src/FDM/JSBSim/models/FGAuxiliary.cpp b/src/FDM/JSBSim/models/FGAuxiliary.cpp
old mode 100644
new mode 100755
index 1dd3e2207..36c1e084a
--- a/src/FDM/JSBSim/models/FGAuxiliary.cpp
+++ b/src/FDM/JSBSim/models/FGAuxiliary.cpp
@@ -59,7 +59,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.45 2010/11/18 12:38:06 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.47 2011/03/29 11:49:27 jberndt Exp $";
 static const char *IdHdr = ID_AUXILIARY;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -180,33 +180,30 @@ bool FGAuxiliary::Run()
   vAeroUVW = vUVW - wind;
 
   Vt = vAeroUVW.Magnitude();
+  double Vt2 = Vt*Vt;
+  alpha = beta = adot = bdot = 0;
+  double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
+
   if ( Vt > 1.0 ) {
     if (vAeroUVW(eW) != 0.0)
       alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
     if (vAeroUVW(eV) != 0.0)
-      beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV),
-             sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
+      beta = mUW > 0.0 ? atan2(vAeroUVW(eV), sqrt(mUW)) : 0.0;
 
-    double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
     double signU=1;
     if (vAeroUVW(eU) < 0.0) signU=-1;
 
-    if ( mUW < 1.0 ) {
-      adot = 0.0;
-      bdot = 0.0;
-    } else {
+    if ( mUW >= 1.0 ) {
       adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW;
-      bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU)
-              + vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
+      bdot = (signU*mUW*vUVWdot(eV)
+             - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU) + vAeroUVW(eW)*vUVWdot(eW)))/(Vt2*sqrt(mUW));
     }
-  } else {
-    alpha = beta = adot = bdot = 0;
   }
 
   Re = Vt * FDMExec->GetAircraft()->Getcbar() / FDMExec->GetAtmosphere()->GetKinematicViscosity();
 
-  qbar = 0.5*density*Vt*Vt;
-  qbarUW = 0.5*density*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
+  qbar = 0.5*density*Vt2;
+  qbarUW = 0.5*density*(mUW);
   qbarUV = 0.5*density*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV));
   Mach = Vt / soundspeed;
   MachU = vMachUVW(eU) = vAeroUVW(eU) / soundspeed;
@@ -291,6 +288,7 @@ bool FGAuxiliary::Run()
 //
 // A positive headwind is blowing with you, a negative headwind is blowing against you.
 // psi is the direction the wind is blowing *towards*.
+// ToDo: should this simply be in the atmosphere class? Same with Get Crosswind.
 
 double FGAuxiliary::GetHeadWind(void) const
 {
diff --git a/src/FDM/JSBSim/models/FGBuoyantForces.cpp b/src/FDM/JSBSim/models/FGBuoyantForces.cpp
index b3808d70f..d12777478 100644
--- a/src/FDM/JSBSim/models/FGBuoyantForces.cpp
+++ b/src/FDM/JSBSim/models/FGBuoyantForces.cpp
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.14 2010/11/18 12:38:06 jberndt Exp $";
+static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.16 2011/03/23 11:58:29 jberndt Exp $";
 static const char *IdHdr = ID_BUOYANTFORCES;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -213,13 +213,13 @@ string FGBuoyantForces::GetBuoyancyStrings(string delimeter)
   }
 
   for (axis = 0; axis < 6; axis++) {
-    for (sd = 0; sd < Coeff[axis].size(); sd++) {
+    for (sd = 0; sd < AeroFunctions[axis].size(); sd++) {
       if (firstime) {
         firstime = false;
       } else {
         CoeffStrings += delimeter;
       }
-      CoeffStrings += Coeff[axis][sd]->GetName();
+      CoeffStrings += AeroFunctions[axis][sd]->GetName();
     }
   }
 */
@@ -243,13 +243,13 @@ string FGBuoyantForces::GetBuoyancyValues(string delimeter)
   }
 
   for (unsigned int axis = 0; axis < 6; axis++) {
-    for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) {
+    for (unsigned int sd = 0; sd < AeroFunctions[axis].size(); sd++) {
       if (firstime) {
         firstime = false;
       } else {
         SDValues += delimeter;
       }
-      SDValues += Coeff[axis][sd]->GetValueAsString();
+      SDValues += AeroFunctions[axis][sd]->GetValueAsString();
     }
   }
 */
@@ -260,19 +260,20 @@ string FGBuoyantForces::GetBuoyancyValues(string delimeter)
 
 void FGBuoyantForces::bind(void)
 {
-  typedef double (FGBuoyantForces::*PMF)(int) const;
+  typedef double (FGBuoyantForces::*PGF)(int) const;
+  typedef void   (FGBuoyantForces::*PSF)(int, double);
   PropertyManager->Tie("moments/l-buoyancy-lbsft", this, eL,
-                       (PMF)&FGBuoyantForces::GetMoments);
+                       (PGF)&FGBuoyantForces::GetMoments, (PSF)0, false);
   PropertyManager->Tie("moments/m-buoyancy-lbsft", this, eM,
-                       (PMF)&FGBuoyantForces::GetMoments);
+                       (PGF)&FGBuoyantForces::GetMoments, (PSF)0, false);
   PropertyManager->Tie("moments/n-buoyancy-lbsft", this, eN,
-                       (PMF)&FGBuoyantForces::GetMoments);
+                       (PGF)&FGBuoyantForces::GetMoments, (PSF)0, false);
   PropertyManager->Tie("forces/fbx-buoyancy-lbs", this, eX,
-                       (PMF)&FGBuoyantForces::GetForces);
+                       (PGF)&FGBuoyantForces::GetForces, (PSF)0, false);
   PropertyManager->Tie("forces/fby-buoyancy-lbs", this, eY,
-                       (PMF)&FGBuoyantForces::GetForces);
+                       (PGF)&FGBuoyantForces::GetForces, (PSF)0, false);
   PropertyManager->Tie("forces/fbz-buoyancy-lbs", this, eZ,
-                       (PMF)&FGBuoyantForces::GetForces);
+                       (PGF)&FGBuoyantForces::GetForces, (PSF)0, false);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/models/FGFCS.cpp b/src/FDM/JSBSim/models/FGFCS.cpp
index f0b77007d..a3b7e91bc 100644
--- a/src/FDM/JSBSim/models/FGFCS.cpp
+++ b/src/FDM/JSBSim/models/FGFCS.cpp
@@ -63,7 +63,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFCS.cpp,v 1.72 2010/11/18 12:38:06 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFCS.cpp,v 1.73 2011/04/05 20:20:21 andgi Exp $";
 static const char *IdHdr = ID_FCS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -182,17 +182,6 @@ bool FGFCS::InitModel(void)
 
   return true;
 }
-  
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGFCS::LateBind(void)
-{
-  unsigned int i;
-
-  for (i=0; i<Systems.size(); i++) Systems[i]->LateBind();
-  for (i=0; i<APComponents.size(); i++) APComponents[i]->LateBind();
-  for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->LateBind();
-}
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // Notes: In this logic the default engine commands are set. This is simply a
diff --git a/src/FDM/JSBSim/models/FGFCS.h b/src/FDM/JSBSim/models/FGFCS.h
index a17509212..6b97297d5 100644
--- a/src/FDM/JSBSim/models/FGFCS.h
+++ b/src/FDM/JSBSim/models/FGFCS.h
@@ -51,7 +51,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCS "$Id: FGFCS.h,v 1.31 2010/09/22 11:33:40 jberndt Exp $"
+#define ID_FCS "$Id: FGFCS.h,v 1.35 2011/04/05 20:20:21 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -168,7 +168,7 @@ CLASS DOCUMENTATION
     @property gear/tailhook-pos-norm
 
     @author Jon S. Berndt
-    @version $Revision: 1.31 $
+    @version $Revision: 1.35 $
     @see FGActuator
     @see FGDeadBand
     @see FGFCSFunction
@@ -540,7 +540,7 @@ public:
 
   FGPropertyManager* GetPropertyManager(void) { return PropertyManager; }
 
-  void LateBind(void);
+  bool GetTrimStatus(void) const { return FDMExec->GetTrimStatus(); }
 
 private:
   double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd;
diff --git a/src/FDM/JSBSim/models/FGLGear.cpp b/src/FDM/JSBSim/models/FGLGear.cpp
index 596e495f0..4a4c9946f 100644
--- a/src/FDM/JSBSim/models/FGLGear.cpp
+++ b/src/FDM/JSBSim/models/FGLGear.cpp
@@ -62,7 +62,7 @@ DEFINITIONS
 GLOBAL DATA
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-static const char *IdSrc = "$Id: FGLGear.cpp,v 1.79 2010/11/28 13:20:47 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGLGear.cpp,v 1.80 2011/01/24 13:01:56 jberndt Exp $";
 static const char *IdHdr = ID_LGEAR;
 
 // Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
@@ -374,13 +374,15 @@ FGColumnVector3& FGLGear::GetBodyForces(void)
     }
   }
 
-  ReportTakeoffOrLanding();
+  if (!fdmex->GetTrimStatus()) {
+    ReportTakeoffOrLanding();
 
-  // Require both WOW and LastWOW to be true before checking crash conditions
-  // to allow the WOW flag to be used in terminating a scripted run.
-  if (WOW && lastWOW) CrashDetect();
+    // Require both WOW and LastWOW to be true before checking crash conditions
+    // to allow the WOW flag to be used in terminating a scripted run.
+    if (WOW && lastWOW) CrashDetect();
 
-  lastWOW = WOW;
+    lastWOW = WOW;
+  }
 
   return FGForce::GetBodyForces();
 }
diff --git a/src/FDM/JSBSim/models/FGModel.cpp b/src/FDM/JSBSim/models/FGModel.cpp
index 71f6cb3ed..df7ffbdd0 100644
--- a/src/FDM/JSBSim/models/FGModel.cpp
+++ b/src/FDM/JSBSim/models/FGModel.cpp
@@ -57,7 +57,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGModel.cpp,v 1.16 2010/11/18 12:38:06 jberndt Exp $";
+static const char *IdSrc = "$Id: FGModel.cpp,v 1.17 2011/02/16 12:30:53 jberndt Exp $";
 static const char *IdHdr = ID_MODEL;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -77,7 +77,7 @@ FGModel::FGModel(FGFDMExec* fdmex)
   //must be brought up now.
   PropertyManager = FDMExec->GetPropertyManager();
 
-  exe_ctr     = 1;
+  exe_ctr     = 0;
   rate        = 1;
 
   if (debug_lvl & 2) cout << "              FGModel Base Class" << endl;
@@ -105,7 +105,7 @@ bool FGModel::Run()
 
   if (rate == 1) return false; // Fast exit if nothing to do
 
-  if (exe_ctr >= rate) exe_ctr = 1;
+  if (exe_ctr >= rate) exe_ctr = 0;
 
   if (exe_ctr++ == 1) return false;
   else              return true;
diff --git a/src/FDM/JSBSim/models/FGOutput.cpp b/src/FDM/JSBSim/models/FGOutput.cpp
index 3e5c986c6..ab70cb2d2 100644
--- a/src/FDM/JSBSim/models/FGOutput.cpp
+++ b/src/FDM/JSBSim/models/FGOutput.cpp
@@ -74,7 +74,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGOutput.cpp,v 1.50 2010/11/18 12:38:06 jberndt Exp $";
+static const char *IdSrc = "$Id: FGOutput.cpp,v 1.54 2011/03/11 13:02:26 jberndt Exp $";
 static const char *IdHdr = ID_OUTPUT;
 
 // (stolen from FGFS native_fdm.cxx)
@@ -182,21 +182,9 @@ bool FGOutput::Run(void)
 {
   if (FGModel::Run()) return true;
 
-  if (enabled && !FDMExec->IntegrationSuspended()&& !FDMExec->Holding()) {
+  if (enabled && !FDMExec->IntegrationSuspended() && !FDMExec->Holding()) {
     RunPreFunctions();
-    if (Type == otSocket) {
-      SocketOutput();
-    } else if (Type == otFlightGear) {
-      FlightGearSocketOutput();
-    } else if (Type == otCSV || Type == otTab) {
-      DelimitedOutput(Filename);
-    } else if (Type == otTerminal) {
-      // Not done yet
-    } else if (Type == otNone) {
-      // Do nothing
-    } else {
-      // Not a valid type of output
-    }
+    Print();
     RunPostFunctions();
   }
   return false;
@@ -204,6 +192,25 @@ bool FGOutput::Run(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+void FGOutput::Print(void)
+{
+  if (Type == otSocket) {
+    SocketOutput();
+  } else if (Type == otFlightGear) {
+    FlightGearSocketOutput();
+  } else if (Type == otCSV || Type == otTab) {
+    DelimitedOutput(Filename);
+  } else if (Type == otTerminal) {
+    // Not done yet
+  } else if (Type == otNone) {
+    // Do nothing
+  } else {
+    // Not a valid type of output
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 void FGOutput::SetType(const string& type)
 {
   if (type == "CSV") {
@@ -296,6 +303,7 @@ void FGOutput::DelimitedOutput(const string& fname)
       outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
       outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter;
       outstream << "V_{X_{inertial}} (ft/s)" + delimeter + "V_{Y_{inertial}} (ft/s)" + delimeter + "V_{Z_{inertial}} (ft/s)" + delimeter;
+      outstream << "V_{X_{ecef}} (ft/s)" + delimeter + "V_{Y_{ecef}} (ft/s)" + delimeter + "V_{Z_{ecef}} (ft/s)" + delimeter;
       outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)";
     }
     if (SubSystems & ssForces) {
@@ -359,8 +367,8 @@ void FGOutput::DelimitedOutput(const string& fname)
       outstream << "Distance AGL (ft)" + delimeter;
       outstream << "Terrain Elevation (ft)";
     }
-    if (SubSystems & ssCoefficients) {
-      scratch = Aerodynamics->GetCoefficientStrings(delimeter);
+    if (SubSystems & ssAeroFunctions) {
+      scratch = Aerodynamics->GetAeroFunctionStrings(delimeter);
       if (scratch.length() != 0) outstream << delimeter << scratch;
     }
     if (SubSystems & ssFCS) {
@@ -415,6 +423,7 @@ void FGOutput::DelimitedOutput(const string& fname)
     outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
     outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
     outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter;
+    outstream << Propagate->GetECEFVelocity().Dump(delimeter) << delimeter;
     outstream << Propagate->GetVel().Dump(delimeter);
     outstream.precision(10);
   }
@@ -475,8 +484,8 @@ void FGOutput::DelimitedOutput(const string& fname)
     outstream << Propagate->GetTerrainElevation();
     outstream.precision(10);
   }
-  if (SubSystems & ssCoefficients) {
-    scratch = Aerodynamics->GetCoefficientValues(delimeter);
+  if (SubSystems & ssAeroFunctions) {
+    scratch = Aerodynamics->GetAeroFunctionValues(delimeter);
     if (scratch.length() != 0) outstream << delimeter << scratch;
   }
   if (SubSystems & ssFCS) {
@@ -826,8 +835,8 @@ void FGOutput::SocketOutput(void)
         socket->Append("Latitude (deg)");
         socket->Append("Longitude (deg)");
     }
-    if (SubSystems & ssCoefficients) {
-      scratch = Aerodynamics->GetCoefficientStrings(",");
+    if (SubSystems & ssAeroFunctions) {
+      scratch = Aerodynamics->GetAeroFunctionStrings(",");
       if (scratch.length() != 0) socket->Append(scratch);
     }
     if (SubSystems & ssFCS) {
@@ -932,8 +941,8 @@ void FGOutput::SocketOutput(void)
     socket->Append(Propagate->GetLocation().GetLatitudeDeg());
     socket->Append(Propagate->GetLocation().GetLongitudeDeg());
   }
-  if (SubSystems & ssCoefficients) {
-    scratch = Aerodynamics->GetCoefficientValues(",");
+  if (SubSystems & ssAeroFunctions) {
+    scratch = Aerodynamics->GetAeroFunctionValues(",");
     if (scratch.length() != 0) socket->Append(scratch);
   }
   if (SubSystems & ssFCS) {
@@ -974,7 +983,7 @@ bool FGOutput::Load(Element* element)
 {
   string parameter="";
   string name="";
-  int OutRate = 0;
+  double OutRate = 0.0;
   unsigned int port;
   Element *property_element;
 
@@ -1003,7 +1012,7 @@ bool FGOutput::Load(Element* element)
     BaseFilename = Filename = name;
   }
   if (!document->GetAttributeValue("rate").empty()) {
-    OutRate = (int)document->GetAttributeValueAsNumber("rate");
+    OutRate = document->GetAttributeValueAsNumber("rate");
   } else {
     OutRate = 1;
   }
@@ -1027,7 +1036,7 @@ bool FGOutput::Load(Element* element)
   if (document->FindElementValue("position") == string("ON"))
     SubSystems += ssPropagate;
   if (document->FindElementValue("coefficients") == string("ON"))
-    SubSystems += ssCoefficients;
+    SubSystems += ssAeroFunctions;
   if (document->FindElementValue("ground_reactions") == string("ON"))
     SubSystems += ssGroundReactions;
   if (document->FindElementValue("fcs") == string("ON"))
@@ -1058,7 +1067,7 @@ bool FGOutput::Load(Element* element)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGOutput::SetRate(int rtHz)
+void FGOutput::SetRate(double rtHz)
 {
   rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz);
   if (rtHz > 0) {
@@ -1128,7 +1137,7 @@ void FGOutput::Debug(int from)
       if (SubSystems & ssMoments)         cout << "    Moments parameters logged" << endl;
       if (SubSystems & ssAtmosphere)      cout << "    Atmosphere parameters logged" << endl;
       if (SubSystems & ssMassProps)       cout << "    Mass parameters logged" << endl;
-      if (SubSystems & ssCoefficients)    cout << "    Coefficient parameters logged" << endl;
+      if (SubSystems & ssAeroFunctions)    cout << "    Coefficient parameters logged" << endl;
       if (SubSystems & ssPropagate)       cout << "    Propagate parameters logged" << endl;
       if (SubSystems & ssGroundReactions) cout << "    Ground parameters logged" << endl;
       if (SubSystems & ssFCS)             cout << "    FCS parameters logged" << endl;
diff --git a/src/FDM/JSBSim/models/FGOutput.h b/src/FDM/JSBSim/models/FGOutput.h
index d03ac5981..e22dc1319 100644
--- a/src/FDM/JSBSim/models/FGOutput.h
+++ b/src/FDM/JSBSim/models/FGOutput.h
@@ -51,7 +51,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_OUTPUT "$Id: FGOutput.h,v 1.19 2010/10/31 04:48:46 jberndt Exp $"
+#define ID_OUTPUT "$Id: FGOutput.h,v 1.22 2011/03/11 13:02:26 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -124,7 +124,7 @@ CLASS DOCUMENTATION
     propulsion       ON|OFF
 </pre>
     NOTE that Time is always output with the data.
-    @version $Id: FGOutput.h,v 1.19 2010/10/31 04:48:46 jberndt Exp $
+    @version $Id: FGOutput.h,v 1.22 2011/03/11 13:02:26 jberndt Exp $
  */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -140,6 +140,7 @@ public:
   bool InitModel(void);
   bool Run(void);
 
+  void Print(void);
   void DelimitedOutput(const std::string&);
   void SocketOutput(void);
   void FlightGearSocketOutput(void);
@@ -153,7 +154,7 @@ public:
   void SetSubsystems(int tt) {SubSystems = tt;}
   void SetOutputFileName(const std::string& fname) {Filename = fname;}
   void SetDirectivesFile(const std::string& fname) {DirectivesFile = fname;}
-  void SetRate(int rt);
+  void SetRate(double rt);
   void Enable(void) { enabled = true; }
   void Disable(void) { enabled = false; }
   bool Toggle(void) {enabled = !enabled; return enabled;}
@@ -171,7 +172,7 @@ public:
     /** Subsystem: Moments (= 32)            */ ssMoments         = 32,
     /** Subsystem: Atmosphere (= 64)         */ ssAtmosphere      = 64,
     /** Subsystem: Mass Properties (= 128)   */ ssMassProps       = 128,
-    /** Subsystem: Coefficients (= 256)      */ ssCoefficients    = 256,
+    /** Subsystem: Coefficients (= 256)      */ ssAeroFunctions    = 256,
     /** Subsystem: Propagate (= 512)         */ ssPropagate       = 512,
     /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024,
     /** Subsystem: FCS (= 2048)              */ ssFCS             = 2048,
diff --git a/src/FDM/JSBSim/models/FGPropagate.cpp b/src/FDM/JSBSim/models/FGPropagate.cpp
index 4d1ef44a8..ae2174df9 100644
--- a/src/FDM/JSBSim/models/FGPropagate.cpp
+++ b/src/FDM/JSBSim/models/FGPropagate.cpp
@@ -71,29 +71,35 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.76 2011/01/16 16:10:59 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.85 2011/04/03 19:24:58 jberndt Exp $";
 static const char *IdHdr = ID_PROPAGATE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex),
-LocalTerrainRadius(0), SeaLevelRadius(0), VehicleRadius(0)
+FGPropagate::FGPropagate(FGFDMExec* fdmex)
+  : FGModel(fdmex),
+    LocalTerrainRadius(0),
+    SeaLevelRadius(0),
+    VehicleRadius(0)
 {
   Debug(0);
   Name = "FGPropagate";
   gravType = gtWGS84;
  
-  vPQRdot.InitMatrix();
+  vPQRidot.InitMatrix();
   vQtrndot = FGQuaternion(0,0,0);
-  vUVWdot.InitMatrix();
+  vUVWidot.InitMatrix();
   vInertialVelocity.InitMatrix();
 
-  integrator_rotational_rate = eAdamsBashforth2;
-  integrator_translational_rate = eTrapezoidal;
-  integrator_rotational_position = eAdamsBashforth2;
-  integrator_translational_position = eTrapezoidal;
+  /// These define the indices use to select the various integrators.
+  // eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3, eAdamsBashforth4};
+
+  integrator_rotational_rate = eRectEuler;
+  integrator_translational_rate = eAdamsBashforth2;
+  integrator_rotational_position = eRectEuler;
+  integrator_translational_position = eAdamsBashforth3;
 
   VState.dqPQRidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
   VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
@@ -124,9 +130,9 @@ bool FGPropagate::InitModel(void)
   VState.vLocation.SetEllipse(FDMExec->GetInertial()->GetSemimajor(), FDMExec->GetInertial()->GetSemiminor());
   vOmegaEarth = FGColumnVector3( 0.0, 0.0, FDMExec->GetInertial()->omega() ); // Earth rotation vector
 
-  vPQRdot.InitMatrix();
+  vPQRidot.InitMatrix();
   vQtrndot = FGQuaternion(0,0,0);
-  vUVWdot.InitMatrix();
+  vUVWidot.InitMatrix();
   vInertialVelocity.InitMatrix();
 
   VState.dqPQRidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
@@ -189,23 +195,13 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
   VehicleRadius = GetRadius();
   double radInv = 1.0/VehicleRadius;
 
-  // Refer to Stevens and Lewis, 1.5-14a, pg. 49.
-  // This is the rotation rate of the "Local" frame, expressed in the local frame.
-
-  FGColumnVector3 vOmegaLocal = FGColumnVector3(
-     radInv*vVel(eEast),
-    -radInv*vVel(eNorth),
-    -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
-
   // Set the angular velocities of the body frame relative to the ECEF frame,
-  // expressed in the body frame. Effectively, this is:
-  //   w_b/e = w_b/l + w_l/e
+  // expressed in the body frame.
   VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(),
                                  FGIC->GetQRadpsIC(),
-                                 FGIC->GetRRadpsIC() ) + Tl2b*vOmegaLocal;
+                                 FGIC->GetRRadpsIC() );
 
   VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
-  VState.vPQRi_i = Tb2i * VState.vPQRi;
 
   // Make an initial run and set past values
   InitializeDerivatives();
@@ -245,11 +241,10 @@ bool FGPropagate::Run(void)
   CalculateUVWdot();           // Translational rate derivative
   ResolveFrictionForces(dt);   // Update rate derivatives with friction forces
   CalculateQuatdot();          // Angular orientation derivative
-  CalculateUVW();              // Translational position derivative (velocities are integrated in the inertial frame)
 
   // Propagate rotational / translational velocity, angular /translational position, respectively.
 
-  Integrate(VState.vPQRi_i,           vPQRidot,          VState.dqPQRidot,          dt, integrator_rotational_rate); // ECI  integration
+  Integrate(VState.vPQRi,             vPQRidot,          VState.dqPQRidot,          dt, integrator_rotational_rate);
   Integrate(VState.qAttitudeECI,      vQtrndot,          VState.dqQtrndot,          dt, integrator_rotational_position);
   Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position);
   Integrate(VState.vInertialVelocity, vUVWidot,          VState.dqUVWidot,          dt, integrator_translational_rate);
@@ -278,12 +273,13 @@ bool FGPropagate::Run(void)
   //    orientation quaternion and vLocation vector.
   UpdateBodyMatrices();
 
+  CalculateUVW();              // Translational position derivative (velocities are integrated in the inertial frame)
+
   // Set auxililary state variables
   RecomputeLocalTerrainRadius();
 
   VehicleRadius = GetRadius(); // Calculate current aircraft radius from center of planet
 
-  VState.vPQRi = Ti2b * VState.vPQRi_i;
   VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
 
   VState.qAttitudeLocal = Tl2b.GetQuaternion();
@@ -321,8 +317,8 @@ void FGPropagate::CalculatePQRdot(void)
   // moments and the total inertial angular velocity expressed in the body
   // frame.
 
-  vPQRdot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi));
-  vPQRidot = Tb2i * vPQRdot;
+  vPQRidot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi));
+  vPQRdot = vPQRidot - VState.vPQRi * (Ti2b * vOmegaEarth);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -605,7 +601,7 @@ void FGPropagate::ResolveFrictionForces(double dt)
   vUVWdot += invMass * Fc;
   vUVWidot += invMass * Tb2i * Fc;
   vPQRdot += Jinv * Mc;
-  vPQRidot += Tb2i* Jinv * Mc;
+  vPQRidot += Jinv * Mc;
 
   // Save the value of the Lagrange multipliers to accelerate the convergence
   // of the Gauss-Seidel algorithm at next iteration.
@@ -658,8 +654,7 @@ void FGPropagate::SetInertialVelocity(FGColumnVector3 Vi) {
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 void FGPropagate::SetInertialRates(FGColumnVector3 vRates) {
-  VState.vPQRi_i = vRates;
-  VState.vPQRi = Ti2b * VState.vPQRi_i;
+  VState.vPQRi = Ti2b * vRates;
   VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
 }
 
@@ -681,7 +676,7 @@ void FGPropagate::InitializeDerivatives(void)
   VState.dqQtrndot.clear();
   for (int i=0; i<4; i++) {
     VState.dqPQRidot.push_front(vPQRidot);
-    VState.dqUVWidot.push_front(vUVWdot);
+    VState.dqUVWidot.push_front(vUVWidot);
     VState.dqInertialVelocity.push_front(VState.vInertialVelocity);
     VState.dqQtrndot.push_front(vQtrndot);
   }
@@ -739,7 +734,6 @@ void FGPropagate::SetVState(const VehicleState& vstate)
   vVel = Tb2l * VState.vUVW;
   VState.vPQR = vstate.vPQR;
   VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
-  VState.vPQRi_i = Tb2i * VState.vPQRi;
   VState.vInertialPosition = vstate.vInertialPosition;
 
   InitializeDerivatives();
diff --git a/src/FDM/JSBSim/models/FGPropagate.h b/src/FDM/JSBSim/models/FGPropagate.h
index 107b3989b..26b2ad73e 100644
--- a/src/FDM/JSBSim/models/FGPropagate.h
+++ b/src/FDM/JSBSim/models/FGPropagate.h
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.55 2011/01/16 16:10:59 bcoconni Exp $"
+#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.58 2011/04/03 19:24:58 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -102,7 +102,7 @@ CLASS DOCUMENTATION
     @endcode
 
     @author Jon S. Berndt, Mathias Froehlich
-    @version $Id: FGPropagate.h,v 1.55 2011/01/16 16:10:59 bcoconni Exp $
+    @version $Id: FGPropagate.h,v 1.58 2011/04/03 19:24:58 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -135,11 +135,6 @@ public:
         units rad/sec */
     FGColumnVector3 vPQRi;
 
-    /** The angular velocity vector for the vehicle body frame relative to the
-        ECI frame, expressed in the ECI frame.
-        units rad/sec */
-    FGColumnVector3 vPQRi_i;
-
     /** The current orientation of the vehicle, that is, the orientation of the
         body frame relative to the local, NED frame. */
     FGQuaternion qAttitudeLocal;
@@ -338,6 +333,10 @@ public:
   */
   const FGColumnVector3& GetInertialPosition(void) const { return VState.vInertialPosition; }
 
+  /** Calculates and retrieves the velocity vector relative to the earth centered earth fixed (ECEF) frame.
+  */
+  const FGColumnVector3 GetECEFVelocity(void) const {return Tb2ec * VState.vUVW; }
+
   /** Returns the current altitude above sea level.
       This function returns the altitude above sea level.
       units ft
@@ -581,8 +580,8 @@ public:
   void RecomputeLocalTerrainRadius(void);
 
   void NudgeBodyLocation(FGColumnVector3 deltaLoc) {
-    vDeltaXYZEC = Tb2ec*deltaLoc;
-    VState.vLocation -= vDeltaXYZEC;
+    VState.vInertialPosition -= Tb2i*deltaLoc;
+    VState.vLocation -= Tb2ec*deltaLoc;
   }
 
   struct LagrangeMultiplier {
@@ -602,8 +601,7 @@ private:
   struct VehicleState VState;
 
   FGColumnVector3 vVel;
-  FGColumnVector3 vPQRdot;
-  FGColumnVector3 vPQRidot;
+  FGColumnVector3 vPQRdot, vPQRidot;
   FGColumnVector3 vUVWdot, vUVWidot;
   FGColumnVector3 vInertialVelocity;
   FGColumnVector3 vLocation;
diff --git a/src/FDM/JSBSim/models/FGPropulsion.cpp b/src/FDM/JSBSim/models/FGPropulsion.cpp
index 05a2da4c4..da82acf51 100644
--- a/src/FDM/JSBSim/models/FGPropulsion.cpp
+++ b/src/FDM/JSBSim/models/FGPropulsion.cpp
@@ -65,7 +65,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.43 2010/11/18 12:38:06 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.45 2011/02/13 00:42:45 jberndt Exp $";
 static const char *IdHdr = ID_PROPULSION;
 
 extern short debug_lvl;
@@ -194,14 +194,16 @@ bool FGPropulsion::GetSteadyState(void)
   double currentThrust = 0, lastThrust = -1;
   int steady_count = 0, j = 0;
   bool steady = false;
+  bool TrimMode = FDMExec->GetTrimStatus();
 
   vForces.InitMatrix();
   vMoments.InitMatrix();
 
   if (!FGModel::Run()) {
+    FDMExec->SetTrimStatus(true);
+
     for (unsigned int i=0; i<numEngines; i++) {
 //      cout << "  Finding steady state for engine " << i << endl;
-      Engines[i]->SetTrimMode(true);
       steady=false;
       steady_count=0;
       j=0;
@@ -225,9 +227,10 @@ bool FGPropulsion::GetSteadyState(void)
 //      }
       vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
       vMoments += Engines[i]->GetMoments();     // sum body frame moments
-      Engines[i]->SetTrimMode(false);
     }
 
+    FDMExec->SetTrimStatus(TrimMode);
+
     return false;
   } else {
     return true;
@@ -648,13 +651,13 @@ void FGPropulsion::bind(void)
   IsBound = true;
   PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, false);
   if (HaveTurbineEngine) {
-    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
-    PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   true);
+    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  false);
+    PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   false);
   }
 
   if (HavePistonEngine) {
-    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
-    PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
+    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  false);
+    PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, false);
   }
 
   PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
diff --git a/src/FDM/JSBSim/models/flight_control/FGActuator.cpp b/src/FDM/JSBSim/models/flight_control/FGActuator.cpp
index 4c58bebfd..bfbd25920 100644
--- a/src/FDM/JSBSim/models/flight_control/FGActuator.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGActuator.cpp
@@ -43,7 +43,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGActuator.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $";
+static const char *IdSrc = "$Id: FGActuator.cpp,v 1.17 2011/02/13 00:42:45 jberndt Exp $";
 static const char *IdHdr = ID_ACTUATOR;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -114,10 +114,12 @@ bool FGActuator::Run(void )
                   // the Input will be further processed and the eventual Output
                   // will be overwritten from this perfect value.
 
-  if (lag != 0.0)              Lag();        // models actuator lag
-  if (rate_limit != 0)         RateLimit();  // limit the actuator rate
+  if (!fcs->GetTrimStatus()) {
+    if (lag != 0.0)              Lag();        // models actuator lag
+    if (rate_limit != 0)         RateLimit();  // limit the actuator rate
+  }
   if (deadband_width != 0.0)   Deadband();
-  if (hysteresis_width != 0.0) Hysteresis();
+  if (!fcs->GetTrimStatus() && hysteresis_width != 0.0) Hysteresis();
   if (bias != 0.0)             Bias();       // models a finite bias
 
   if (fail_stuck) Output = PreviousOutput;
@@ -187,6 +189,18 @@ void FGActuator::RateLimit(void)
 
 void FGActuator::Deadband(void)
 {
+  // Note: this function acts cumulatively on the "Output" parameter. So, "Output"
+  // is - for the purposes of this Deadband method - really the input to the
+  // method.
+  double input = Output;
+
+  if (input < -deadband_width/2.0) {
+    Output = (input + deadband_width/2.0);
+  } else if (input > deadband_width/2.0) {
+    Output = (input - deadband_width/2.0);
+  } else {
+    Output = 0.0;
+  }
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -232,9 +246,9 @@ void FGActuator::Debug(int from)
   if (debug_lvl & 1) { // Standard console startup message output
     if (from == 0) { // Constructor
       if (InputSigns[0] < 0)
-        cout << "      INPUT: -" << InputNodes[0]->getName() << endl;
+        cout << "      INPUT: -" << InputNames[0] << endl;
       else
-        cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+        cout << "      INPUT: " << InputNames[0] << endl;
 
       if (IsOutput) {
         for (unsigned int i=0; i<OutputNodes.size(); i++)
diff --git a/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp b/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp
index 0158b6356..361afb66a 100644
--- a/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp
@@ -142,7 +142,7 @@ void FGDeadBand::Debug(int from)
 
   if (debug_lvl & 1) { // Standard console startup message output
     if (from == 0) { // Constructor
-      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+      cout << "      INPUT: " << InputNodes[0]->GetName() << endl;
       if (WidthPropertyNode != 0) {
         cout << "      DEADBAND WIDTH: " << WidthPropertyNode->GetName() << endl;
       } else {
diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
index 6cdf9ab83..4ea969774 100644
--- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
@@ -40,6 +40,7 @@ INCLUDES
 #include "FGFCSComponent.h"
 #include "input_output/FGPropertyManager.h"
 #include "input_output/FGXMLElement.h"
+#include "math/FGPropertyValue.h"
 #include <iostream>
 #include <cstdlib>
 
@@ -47,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.29 2010/09/07 00:40:03 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.30 2011/04/05 20:20:21 andgi Exp $";
 static const char *IdHdr = ID_FCSCOMPONENT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -111,8 +112,6 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
 
   Name = element->GetAttributeValue("name");
 
-  FGPropertyManager *tmp=0;
-
   input_element = element->FindElement("input");
   while (input_element) {
     input = input_element->GetDataLine();
@@ -122,14 +121,14 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
     } else {
       InputSigns.push_back( 1.0);
     }
+    FGPropertyManager* node = 0L;
     if (PropertyManager->HasNode(input)) {
-      tmp = PropertyManager->GetNode(input);
+      node = PropertyManager->GetNode(input);
+      InputNodes.push_back(new FGPropertyValue( node ));
     } else {
-      tmp = 0L;
-      // cerr << fgcyan << "In component: " + Name + " property "
-      //      + input + " is initially undefined." << reset << endl;
+      InputNodes.push_back(new FGPropertyValue( input,
+                                                PropertyManager ));
     }
-    InputNodes.push_back( tmp );
     InputNames.push_back( input );
 
     input_element = element->FindNextElement("input");
@@ -238,24 +237,6 @@ void FGFCSComponent::Clip(void)
   }
 }
 
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGFCSComponent::LateBind(void)
-{
-  FGPropertyManager* node = 0L;
-
-  for (unsigned int i=0; i<InputNodes.size(); i++) {
-    if (!InputNodes[i]) {
-      if (PropertyManager->HasNode(InputNames[i])) {
-        node = PropertyManager->GetNode(InputNames[i]);
-        InputNodes[i] = node;
-      } else {
-        throw(InputNames[i]);
-      }
-    }
-  }
-}
-
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //
 // The old way of naming FCS components allowed upper or lower case, spaces, etc.
diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
index 7889cd948..7ad58de0a 100644
--- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
+++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
@@ -38,6 +38,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGJSBBase.h"
+#include "math/FGParameter.h"
 #include <string>
 #include <vector>
 
@@ -45,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $"
+#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.18 2011/04/05 20:20:21 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -80,7 +81,7 @@ CLASS DOCUMENTATION
     - FGActuator
 
     @author Jon S. Berndt
-    @version $Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $
+    @version $Id: FGFCSComponent.h,v 1.18 2011/04/05 20:20:21 andgi Exp $
     @see Documentation for the FGFCS class, and for the configuration file class
 */
 
@@ -98,7 +99,6 @@ public:
 
   virtual bool Run(void);
   virtual void SetOutput(void);
-  void LateBind(void);
   double GetOutput (void) const {return Output;}
   std::string GetName(void) const {return Name;}
   std::string GetType(void) const { return Type; }
@@ -111,7 +111,7 @@ protected:
   std::vector <FGPropertyManager*> OutputNodes;
   FGPropertyManager* ClipMinPropertyNode;
   FGPropertyManager* ClipMaxPropertyNode;
-  std::vector <FGPropertyManager*> InputNodes;
+  std::vector <FGParameter*> InputNodes;
   std::vector <std::string> InputNames;
   std::vector <float> InputSigns;
   std::vector <double> output_array;
diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp
index c6a352f3b..a9143f42a 100644
--- a/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp
@@ -121,7 +121,7 @@ void FGFCSFunction::Debug(int from)
   if (debug_lvl & 1) { // Standard console startup message output
     if (from == 0) { // Constructor
       if (InputNodes.size()>0)
-        cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+        cout << "      INPUT: " << InputNodes[0]->GetName() << endl;
 //    cout << "      Function: " << endl;
       if (IsOutput) {
         for (unsigned int i=0; i<OutputNodes.size(); i++)
diff --git a/src/FDM/JSBSim/models/flight_control/FGFilter.cpp b/src/FDM/JSBSim/models/flight_control/FGFilter.cpp
index 2aab6e2b8..54739e837 100644
--- a/src/FDM/JSBSim/models/flight_control/FGFilter.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGFilter.cpp
@@ -259,7 +259,7 @@ void FGFilter::Debug(int from)
 
   if (debug_lvl & 1) { // Standard console startup message output
     if (from == 0) { // Constructor
-      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+      cout << "      INPUT: " << InputNodes[0]->GetName() << endl;
         switch (FilterType) {
         case eLag:
           if (PropertySign[1] < 0.0) sgn="-";
diff --git a/src/FDM/JSBSim/models/flight_control/FGGain.cpp b/src/FDM/JSBSim/models/flight_control/FGGain.cpp
index e52cd37e6..fac82ab61 100644
--- a/src/FDM/JSBSim/models/flight_control/FGGain.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGGain.cpp
@@ -209,9 +209,9 @@ void FGGain::Debug(int from)
   if (debug_lvl & 1) { // Standard console startup message output
     if (from == 0) { // Constructor
       if (InputSigns[0] < 0)
-        cout << "      INPUT: -" << InputNodes[0]->getName() << endl;
+        cout << "      INPUT: -" << InputNodes[0]->GetName() << endl;
       else
-        cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+        cout << "      INPUT: " << InputNodes[0]->GetName() << endl;
 
       if (GainPropertyNode != 0) {
         cout << "      GAIN: " << GainPropertyNode->GetName() << endl;
diff --git a/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp b/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp
index 525fcee37..4a597f7b4 100644
--- a/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp
@@ -188,7 +188,7 @@ void FGKinemat::Debug(int from)
 
   if (debug_lvl & 1) { // Standard console startup message output
     if (from == 0) { // Constructor
-      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+      cout << "      INPUT: " << InputNodes[0]->GetName() << endl;
       cout << "      DETENTS: " << NumDetents << endl;
       for (int i=0;i<NumDetents;i++) {
         cout << "        " << Detents[i] << " " << TransitionTimes[i] << endl;
diff --git a/src/FDM/JSBSim/models/flight_control/FGPID.cpp b/src/FDM/JSBSim/models/flight_control/FGPID.cpp
index ac265b8ff..6556ecdb7 100644
--- a/src/FDM/JSBSim/models/flight_control/FGPID.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGPID.cpp
@@ -189,9 +189,9 @@ void FGPID::Debug(int from)
   if (debug_lvl & 1) { // Standard console startup message output
     if (from == 0) { // Constructor
       if (InputSigns[0] < 0)
-        cout << "      INPUT: -" << InputNodes[0]->getName() << endl;
+        cout << "      INPUT: -" << InputNodes[0]->GetName() << endl;
       else
-        cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+        cout << "      INPUT: " << InputNodes[0]->GetName() << endl;
 
       if (IsOutput) {
         for (unsigned int i=0; i<OutputNodes.size(); i++)
diff --git a/src/FDM/JSBSim/models/flight_control/FGSensor.cpp b/src/FDM/JSBSim/models/flight_control/FGSensor.cpp
index 1f46dc954..60b5f955a 100644
--- a/src/FDM/JSBSim/models/flight_control/FGSensor.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGSensor.cpp
@@ -293,9 +293,9 @@ void FGSensor::Debug(int from)
     if (from == 0) { // Constructor
       if (InputSigns.size() > 0) {
         if (InputSigns[0] < 0)
-          cout << "      INPUT: -" << InputNodes[0]->getName() << endl;
+          cout << "      INPUT: -" << InputNodes[0]->GetName() << endl;
         else
-          cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+          cout << "      INPUT: " << InputNodes[0]->GetName() << endl;
       }
       if (bits != 0) {
         if (quant_property.empty())
diff --git a/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp b/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp
index 4e68ea7ff..cea9f583e 100644
--- a/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp
@@ -69,7 +69,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.19 2009/10/24 22:59:30 jberndt Exp $";
+static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.20 2011/04/05 20:20:21 andgi Exp $";
 static const char *IdHdr = ID_SWITCH;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -135,7 +135,13 @@ FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
           } else {
             current_test->sign = 1.0;
           }
-          current_test->OutputProp = PropertyManager->GetNode(value);
+          FGPropertyManager *node = PropertyManager->GetNode(value, false);
+          if (node) {
+            current_test->OutputProp = new FGPropertyValue(node);
+          } else {
+            current_test->OutputProp = new FGPropertyValue(value,
+                                                           PropertyManager);
+          }
         }
       }
     }
@@ -151,6 +157,7 @@ FGSwitch::~FGSwitch()
 {
   for (unsigned int i=0; i<tests.size(); i++) {
     for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j];
+    delete tests[i]->OutputProp;
     delete tests[i];
   }
 
diff --git a/src/FDM/JSBSim/models/flight_control/FGSwitch.h b/src/FDM/JSBSim/models/flight_control/FGSwitch.h
index a230aef7e..cca141b0f 100644
--- a/src/FDM/JSBSim/models/flight_control/FGSwitch.h
+++ b/src/FDM/JSBSim/models/flight_control/FGSwitch.h
@@ -40,12 +40,13 @@ INCLUDES
 #include "FGFCSComponent.h"
 #include "input_output/FGXMLElement.h"
 #include "math/FGCondition.h"
+#include "math/FGPropertyValue.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_SWITCH "$Id: FGSwitch.h,v 1.13 2009/10/02 10:30:09 jberndt Exp $"
+#define ID_SWITCH "$Id: FGSwitch.h,v 1.14 2011/04/05 20:20:21 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -124,7 +125,7 @@ ap/attitude_hold takes the value 1), the value of the switch component will be
 whatever value fcs/roll-ap-error-summer is.
 
 @author Jon S. Berndt
-@version $Id: FGSwitch.h,v 1.13 2009/10/02 10:30:09 jberndt Exp $
+@version $Id: FGSwitch.h,v 1.14 2011/04/05 20:20:21 andgi Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -156,12 +157,12 @@ private:
     vector <FGCondition*> conditions;
     eLogic Logic;
     double OutputVal;
-    FGPropertyManager *OutputProp;
+    FGPropertyValue *OutputProp;
     float sign;
 
     double GetValue(void) {
       if (OutputProp == 0L) return OutputVal;
-      else                  return OutputProp->getDoubleValue()*sign;
+      else                  return OutputProp->GetValue()*sign;
     }
 
     test(void) { // constructor for the test structure
diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp
index 1138d820c..cbcb9220a 100644
--- a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp
@@ -50,7 +50,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGElectric.cpp,v 1.9 2010/08/21 17:13:48 jberndt Exp $";
+static const char *IdSrc = "$Id: FGElectric.cpp,v 1.10 2011/03/10 01:35:25 dpculp Exp $";
 static const char *IdHdr = ID_ELECTRIC;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -92,16 +92,21 @@ void FGElectric::Calculate(void)
   RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
 
   HP = PowerWatts * Throttle / hptowatts;
-
-  PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
-
-  Thruster->Calculate(PowerAvailable);
+  
+  Thruster->Calculate(HP * hptoftlbssec);
 
   RunPostFunctions();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+double FGElectric::CalcFuelNeed(void)
+{
+  return 0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 string FGElectric::GetEngineLabels(const string& delimiter)
 {
   std::ostringstream buf;
@@ -174,10 +179,4 @@ void FGElectric::Debug(int from)
   }
 }
 
-double
-FGElectric::CalcFuelNeed(void)
-{
-  return 0;
-}
-
 } // namespace JSBSim
diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.h b/src/FDM/JSBSim/models/propulsion/FGElectric.h
index 268522956..28c703dee 100644
--- a/src/FDM/JSBSim/models/propulsion/FGElectric.h
+++ b/src/FDM/JSBSim/models/propulsion/FGElectric.h
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ELECTRIC "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $";
+#define ID_ELECTRIC "$Id: FGElectric.h,v 1.10 2011/03/10 01:35:25 dpculp Exp $";
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -65,7 +65,7 @@ CLASS DOCUMENTATION
     there is no battery model available, so this motor does not consume any
     energy.  There is no internal friction.
     @author David Culp
-    @version "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $"
+    @version "$Id: FGElectric.h,v 1.10 2011/03/10 01:35:25 dpculp Exp $"
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -81,7 +81,7 @@ public:
   ~FGElectric();
 
   void Calculate(void);
-  double GetPowerAvailable(void) {return PowerAvailable;}
+  double GetPowerAvailable(void) {return (HP * hptoftlbssec);}
   double getRPM(void) {return RPM;}
   std::string GetEngineLabels(const std::string& delimiter);
   std::string GetEngineValues(const std::string& delimiter);
@@ -91,7 +91,6 @@ private:
   double CalcFuelNeed(void);
 
   double BrakeHorsePower;
-  double PowerAvailable;
 
   // timestep
   double dt;
@@ -101,7 +100,7 @@ private:
 
   double PowerWatts;         // maximum engine power
   double RPM;                // revolutions per minute
-  double HP;
+  double HP;                 // engine output, in horsepower
 
   void Debug(int from);
 };
diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp
index e48e27426..707d425e4 100644
--- a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp
@@ -54,7 +54,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGEngine.cpp,v 1.40 2010/10/15 11:32:41 jberndt Exp $";
+static const char *IdSrc = "$Id: FGEngine.cpp,v 1.42 2011/03/03 12:16:26 jberndt Exp $";
 static const char *IdHdr = ID_ENGINE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -151,6 +151,8 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
   PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust);
   property_name = base_property_name + "/fuel-flow-rate-pps";
   PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate);
+  property_name = base_property_name + "/fuel-used-lbs";
+  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelUsedLbs);
 
   PostLoad(engine_element, PropertyManager, to_string(EngineNumber));
 
@@ -177,11 +179,11 @@ void FGEngine::ResetToIC(void)
   FuelExpended = 0.0;
   Starved = Running = Cranking = false;
   PctPower = 0.0;
-  TrimMode = false;
   FuelFlow_gph = 0.0;
   FuelFlow_pph = 0.0;
   FuelFlowRate = 0.0;
   FuelFreeze = false;
+  FuelUsedLbs = 0.0;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -194,7 +196,7 @@ void FGEngine::ResetToIC(void)
 void FGEngine::ConsumeFuel(void)
 {
   if (FuelFreeze) return;
-  if (TrimMode) return;
+  if (FDMExec->GetTrimStatus()) return;
 
   unsigned int i;
   double Fshortage, FuelNeeded;
@@ -240,6 +242,7 @@ void FGEngine::ConsumeFuel(void)
     Tank = Propulsion->GetTank(FeedList[i]);
     Tank->Drain(FuelNeeded); 
   }
+  FuelUsedLbs += FuelToBurn;
 
 }
 
diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.h b/src/FDM/JSBSim/models/propulsion/FGEngine.h
index c25eebfc0..03b774d94 100644
--- a/src/FDM/JSBSim/models/propulsion/FGEngine.h
+++ b/src/FDM/JSBSim/models/propulsion/FGEngine.h
@@ -55,7 +55,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ENGINE "$Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $"
+#define ID_ENGINE "$Id: FGEngine.h,v 1.23 2011/03/03 12:16:26 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -118,7 +118,7 @@ CLASS DOCUMENTATION
 	documentation for engine and thruster classes.
 </pre>     
     @author Jon S. Berndt
-    @version $Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $
+    @version $Id: FGEngine.h,v 1.23 2011/03/03 12:16:26 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -146,6 +146,7 @@ public:
   virtual double getFuelFlow_gph () const {return FuelFlow_gph;}
   virtual double getFuelFlow_pph () const {return FuelFlow_pph;}
   virtual double GetFuelFlowRate(void) const {return FuelFlowRate;}
+  virtual double GetFuelUsedLbs(void) const {return FuelUsedLbs;}
   virtual bool   GetStarved(void) { return Starved; }
   virtual bool   GetRunning(void) const { return Running; }
   virtual bool   GetCranking(void) { return Cranking; }
@@ -173,9 +174,6 @@ public:
 
   virtual double GetPowerAvailable(void) {return 0.0;};
 
-  virtual bool GetTrimMode(void) {return TrimMode;}
-  virtual void SetTrimMode(bool state) {TrimMode = state;}
-
   virtual FGColumnVector3& GetBodyForces(void);
   virtual FGColumnVector3& GetMoments(void);
 
@@ -219,12 +217,12 @@ protected:
   bool  Starved;
   bool  Running;
   bool  Cranking;
-  bool  TrimMode;
   bool  FuelFreeze;
 
   double FuelFlow_gph;
   double FuelFlow_pph;
   double FuelDensity;
+  double FuelUsedLbs;
 
   FGFDMExec*      FDMExec;
   FGAtmosphere*   Atmosphere;
diff --git a/src/FDM/JSBSim/models/propulsion/FGForce.cpp b/src/FDM/JSBSim/models/propulsion/FGForce.cpp
index 0180d18e4..0bebb1772 100644
--- a/src/FDM/JSBSim/models/propulsion/FGForce.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGForce.cpp
@@ -53,7 +53,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGForce.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $";
+static const char *IdSrc = "$Id: FGForce.cpp,v 1.15 2011/02/17 00:20:52 jberndt Exp $";
 static const char *IdHdr = ID_FORCE;
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -62,9 +62,20 @@ FGForce::FGForce(FGFDMExec *FDMExec) :
                  fdmex(FDMExec),
                  ttype(tNone)
 {
-  mT(1,1) = 1; //identity matrix
-  mT(2,2) = 1;
-  mT(3,3) = 1;
+  vFn.InitMatrix();
+  vMn.InitMatrix();
+  vH.InitMatrix();
+  vOrient.InitMatrix();
+  vXYZn.InitMatrix();
+  vActingXYZn.InitMatrix();
+
+  vFb.InitMatrix();
+  vM.InitMatrix();
+  vDXYZ.InitMatrix();
+
+  mT.InitMatrix(1., 0., 0.,
+                0., 1., 0.,
+                0., 0., 1.);
 
   Debug(0);
 }
diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
index 522a0b2fe..7726306bf 100644
--- a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
@@ -53,7 +53,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPiston.cpp,v 1.54 2010/11/30 12:17:10 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPiston.cpp,v 1.55 2011/03/10 01:35:25 dpculp Exp $";
 static const char *IdHdr = ID_PISTON;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -442,8 +442,7 @@ void FGPiston::Calculate(void)
     ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
   }
 
-  PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
-  Thruster->Calculate(PowerAvailable);
+  Thruster->Calculate(HP * hptoftlbssec);
 
   RunPostFunctions();
 }
@@ -872,7 +871,7 @@ string FGPiston::GetEngineLabels(const string& delimiter)
 {
   std::ostringstream buf;
 
-  buf << Name << " Power Available (engine " << EngineNumber << " in HP)" << delimiter
+  buf << Name << " Power Available (engine " << EngineNumber << " in ft-lbs/sec)" << delimiter
       << Name << " HP (engine " << EngineNumber << ")" << delimiter
       << Name << " equivalent ratio (engine " << EngineNumber << ")" << delimiter
       << Name << " MAP (engine " << EngineNumber << " in inHg)" << delimiter
@@ -887,7 +886,7 @@ string FGPiston::GetEngineValues(const string& delimiter)
 {
   std::ostringstream buf;
 
-  buf << PowerAvailable << delimiter << HP << delimiter
+  buf << (HP * hptoftlbssec) << delimiter << HP << delimiter
       << equivalence_ratio << delimiter << ManifoldPressure_inHg << delimiter
       << Thruster->GetThrusterValues(EngineNumber, delimiter);
 
diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.h b/src/FDM/JSBSim/models/propulsion/FGPiston.h
index 510c6e6f2..a8019e5aa 100644
--- a/src/FDM/JSBSim/models/propulsion/FGPiston.h
+++ b/src/FDM/JSBSim/models/propulsion/FGPiston.h
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PISTON "$Id: FGPiston.h,v 1.25 2010/11/30 12:17:10 jberndt Exp $";
+#define ID_PISTON "$Id: FGPiston.h,v 1.26 2011/03/10 01:35:25 dpculp Exp $";
 #define FG_MAX_BOOST_SPEEDS 3
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -182,7 +182,7 @@ CLASS DOCUMENTATION
     @author Dave Luff (engine operational code)
     @author David Megginson (initial porting and additional code)
     @author Ron Jensen (additional engine code)
-    @version $Id: FGPiston.h,v 1.25 2010/11/30 12:17:10 jberndt Exp $
+    @version $Id: FGPiston.h,v 1.26 2011/03/10 01:35:25 dpculp Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -201,7 +201,7 @@ public:
   std::string GetEngineValues(const std::string& delimiter);
 
   void Calculate(void);
-  double GetPowerAvailable(void) const {return PowerAvailable;}
+  double GetPowerAvailable(void) const {return (HP * hptoftlbssec);}
   double CalcFuelNeed(void);
 
   void ResetToIC(void);
@@ -227,7 +227,6 @@ private:
   double FMEP;
   double FMEPDynamic;
   double FMEPStatic;
-  double PowerAvailable;
 
   // timestep
   double dt;
diff --git a/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp b/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp
index f83f961b8..d5ed3813d 100644
--- a/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.32 2010/10/21 03:27:40 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.33 2011/03/10 01:35:25 dpculp Exp $";
 static const char *IdHdr = ID_PROPELLER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -185,23 +185,22 @@ FGPropeller::~FGPropeller()
 // We must be getting the aerodynamic velocity here, NOT the inertial velocity.
 // We need the velocity with respect to the wind.
 //
-// Note that PowerAvailable is the excess power available after the drag of the
-// propeller has been subtracted. At equilibrium, PowerAvailable will be zero -
-// indicating that the propeller will not accelerate or decelerate.
 // Remembering that Torque * omega = Power, we can derive the torque on the
 // propeller and its acceleration to give a new RPM. The current RPM will be
 // used to calculate thrust.
 //
 // Because RPM could be zero, we need to be creative about what RPM is stated as.
 
-double FGPropeller::Calculate(double PowerAvailable)
+double FGPropeller::Calculate(double EnginePower)
 {
-  double omega, alpha, beta;
+  double omega, alpha, beta, PowerAvailable;
 
   double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU);
   double rho = fdmex->GetAtmosphere()->GetDensity();
   double RPS = RPM/60.0;
 
+  PowerAvailable = EnginePower - GetPowerRequired();
+
   // Calculate helical tip Mach
   double Area = 0.25*Diameter*Diameter*M_PI;
   double Vtip = RPS * Diameter * M_PI;
diff --git a/src/FDM/JSBSim/models/propulsion/FGPropeller.h b/src/FDM/JSBSim/models/propulsion/FGPropeller.h
index ea7953e1e..3e9c3c259 100644
--- a/src/FDM/JSBSim/models/propulsion/FGPropeller.h
+++ b/src/FDM/JSBSim/models/propulsion/FGPropeller.h
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPELLER "$Id: FGPropeller.h,v 1.16 2010/04/09 12:44:06 jberndt Exp $"
+#define ID_PROPELLER "$Id: FGPropeller.h,v 1.17 2011/03/10 01:35:25 dpculp Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -141,7 +141,7 @@ CLASS DOCUMENTATION
     <li>Various NACA Technical Notes and Reports</li>
     </ul>
     @author Jon S. Berndt
-    @version $Id: FGPropeller.h,v 1.16 2010/04/09 12:44:06 jberndt Exp $
+    @version $Id: FGPropeller.h,v 1.17 2011/03/10 01:35:25 dpculp Exp $
     @see FGEngine
     @see FGThruster
 */
@@ -247,7 +247,7 @@ public:
       accelerate the prop. It could be negative, dictating that the propeller
       would be slowed.
       @return the thrust in pounds */
-  double Calculate(double PowerAvailable);
+  double Calculate(double EnginePower);
   FGColumnVector3 GetPFactor(void);
   string GetThrusterLabels(int id, string delimeter);
   string GetThrusterValues(int id, string delimeter);
diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp
index 3fef49616..f8fb091cb 100644
--- a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp
@@ -49,7 +49,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGRocket.cpp,v 1.22 2010/12/30 13:35:09 jberndt Exp $";
+static const char *IdSrc = "$Id: FGRocket.cpp,v 1.23 2011/01/24 13:01:56 jberndt Exp $";
 static const char *IdHdr = ID_ROCKET;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -202,7 +202,7 @@ void FGRocket::ConsumeFuel(void)
   double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0;
 
   if (FuelFreeze) return;
-  if (TrimMode) return;
+  if (FDMExec->GetTrimStatus()) return;
 
   // Count how many assigned tanks have fuel for this engine at this time.
   // If there is/are fuel tanks but no oxidizer tanks, this indicates
diff --git a/src/FDM/JSBSim/models/propulsion/FGRotor.cpp b/src/FDM/JSBSim/models/propulsion/FGRotor.cpp
index 5c69728f2..1ac58405a 100644
--- a/src/FDM/JSBSim/models/propulsion/FGRotor.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGRotor.cpp
@@ -34,6 +34,8 @@ HISTORY
 11/15/10  T.Kreitler treated flow solver bug, flow and torque calculations 
                      simplified, tiploss influence removed from flapping angles
 01/10/11  T.Kreitler changed to single rotor model
+03/06/11  T.Kreitler added brake, clutch, and experimental free-wheeling-unit,
+                     reasonable estimate for inflowlag
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 INCLUDES
@@ -56,7 +58,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGRotor.cpp,v 1.11 2011/01/17 22:09:59 jberndt Exp $";
+static const char *IdSrc = "$Id: FGRotor.cpp,v 1.12 2011/03/10 01:35:25 dpculp Exp $";
 static const char *IdHdr = ID_ROTOR;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -109,7 +111,11 @@ FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num)
 
   // control
   ControlMap(eMainCtrl),
-  CollectiveCtrl(0.0), LateralCtrl(0.0), LongitudinalCtrl(0.0)
+  CollectiveCtrl(0.0), LateralCtrl(0.0), LongitudinalCtrl(0.0),
+  BrakeCtrlNorm(0.0), MaxBrakePower(0.0),
+
+  // free-wheeling-unit (FWU)
+  FreeWheelPresent(0), FreeWheelThresh(0.0), FreeWheelTransmission(0.0)
 
 {
   FGColumnVector3 location(0.0, 0.0, 0.0), orientation(0.0, 0.0, 0.0);
@@ -190,6 +196,9 @@ FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num)
   // calculation would cause jumps too. 1Hz seems sufficient.
   damp_hagl = Filter(1.0,dt);
 
+  // avoid too abrupt changes in power transmission
+  FreeWheelLag = Filter(200.0,dt);
+
   // enable import-export
   BindModel();
 
@@ -248,7 +257,7 @@ double FGRotor::ConfigValue(Element* el, const string& ename, double default_val
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 // 1. read configuration and try to fill holes, ymmv
-// 2. calculate derived parameters and transforms
+// 2. calculate derived parameters
 void FGRotor::Configure(Element* rotor_element)
 {
 
@@ -279,22 +288,24 @@ void FGRotor::Configure(Element* rotor_element)
 
   estimate = sqr(BladeChord) * sqr(Radius - HingeOffset) * 0.57;
   BladeFlappingMoment = ConfigValueConv(rotor_element, "flappingmoment", estimate, "SLUG*FT2");   
-  BladeFlappingMoment = Constrain(0.001, BladeFlappingMoment, 1e9);
+  BladeFlappingMoment = Constrain(1.0e-6, BladeFlappingMoment, 1e9);
 
   // guess mass from moment of a thin stick, and multiply by the blades cg distance
   estimate = ( 3.0 * BladeFlappingMoment / sqr(Radius) ) * (0.45 * Radius) ;
   BladeMassMoment = ConfigValue(rotor_element, "massmoment", estimate); // unit is slug-ft
   BladeMassMoment = Constrain(0.001, BladeMassMoment, 1e9);
 
-  TipLossB = ConfigValue(rotor_element, "tiplossfactor", 1.0, silent);
-
   estimate = 1.1 * BladeFlappingMoment * BladeNum;
   PolarMoment = ConfigValueConv(rotor_element, "polarmoment", estimate, "SLUG*FT2");
-  PolarMoment = Constrain(0.001, PolarMoment, 1e9);
+  PolarMoment = Constrain(1e-6, PolarMoment, 1e9);
 
-  InflowLag = ConfigValue(rotor_element, "inflowlag", 0.2, yell); // fixme, depends on size
-  InflowLag = Constrain(1e-6, InflowLag, 2.0);
+  // "inflowlag" is treated further down.
 
+  TipLossB = ConfigValue(rotor_element, "tiplossfactor", 1.0, silent);
+
+  estimate = 0.01 * PolarMoment ; // guesses for huey, bo105 20-30hp
+  MaxBrakePower  = ConfigValueConv(rotor_element, "maxbrakepower", estimate, "HP");
+  MaxBrakePower *= hptoftlbssec;
 
   // ground effect
   if (rotor_element->FindElement("cgroundeffect")) {
@@ -309,6 +320,17 @@ void FGRotor::Configure(Element* rotor_element)
   GroundEffectExp = ConfigValue(rotor_element, "groundeffectexp", 0.0);
   GroundEffectShift = ConfigValueConv(rotor_element, "groundeffectshift", 0.0, "FT");
 
+  // handle optional free-wheeling-unit (FWU)
+  FreeWheelPresent = 0;
+  FreeWheelTransmission = 1.0;
+  if (rotor_element->FindElement("freewheelthresh")) {
+    FreeWheelThresh = rotor_element->FindElementValueAsNumber("freewheelthresh");
+    if (FreeWheelThresh > 1.0) {
+      FreeWheelPresent = 1;
+      FreeWheelTransmission = 0.0;
+    }
+  }
+
   // precalc often used powers
   R[0]=1.0; R[1]=Radius;   R[2]=R[1]*R[1]; R[3]=R[2]*R[1]; R[4]=R[3]*R[1];
   B[0]=1.0; B[1]=TipLossB; B[2]=B[1]*B[1]; B[3]=B[2]*B[1]; B[4]=B[3]*B[1];
@@ -317,6 +339,13 @@ void FGRotor::Configure(Element* rotor_element)
   LockNumberByRho = LiftCurveSlope * BladeChord * R[4] / BladeFlappingMoment;
   Solidity = BladeNum * BladeChord / (M_PI * Radius);
 
+  // estimate inflow lag, see /GE49/ eqn(1)
+  double omega_tmp = (NominalRPM/60.0)*2.0*M_PI;
+  estimate = 16.0/(LockNumberByRho*rho * omega_tmp ); // 16/(gamma*Omega)
+  // printf("# Est. InflowLag: %f\n", estimate);
+  InflowLag = ConfigValue(rotor_element, "inflowlag", estimate, yell);
+  InflowLag = Constrain(1.0e-6, InflowLag, 2.0);
+
   return;
 } // Configure
 
@@ -362,7 +391,7 @@ FGColumnVector3 FGRotor::fus_angvel_body2ca( const FGColumnVector3 &pqr)
   av_w_fus(eP)=   av_s_fus(eP)*cos(beta_orient) + av_s_fus(eQ)*sin(beta_orient);
   av_w_fus(eQ)= - av_s_fus(eP)*sin(beta_orient) + av_s_fus(eQ)*cos(beta_orient);
   av_w_fus(eR)=   av_s_fus(eR);
-         
+
   return av_w_fus;
 }
 
@@ -382,7 +411,7 @@ void FGRotor::calc_flow_and_thrust( double theta_0, double Uw, double Ww,
 
   double ct_over_sigma = 0.0;
   double c0, ct_l, ct_t0, ct_t1;
-  double mu2;  
+  double mu2;
 
   mu = Uw/(Omega*Radius); // /SH79/ eqn(24)
   mu2 = sqr(mu);
@@ -390,7 +419,7 @@ void FGRotor::calc_flow_and_thrust( double theta_0, double Uw, double Ww,
   ct_t0 = (1.0/3.0*B[3] + 1.0/2.0 * TipLossB*mu2 - 4.0/(9.0*M_PI) * mu*mu2 ) * theta_0;
   ct_t1 = (1.0/4.0*B[4] + 1.0/4.0 * B[2]*mu2) * BladeTwist;
 
-  ct_l  = (1.0/2.0*B[2] + 1.0/4.0 * mu2) * lambda; // first time  
+  ct_l  = (1.0/2.0*B[2] + 1.0/4.0 * mu2) * lambda; // first time
 
   c0 = (LiftCurveSlope/2.0)*(ct_l + ct_t0 + ct_t1) * Solidity;
   c0 = c0 / ( 2.0 * sqrt( sqr(mu) + sqr(lambda) ) + 1e-15);
@@ -473,7 +502,7 @@ void FGRotor::calc_flapping_angles(double theta_0, const FGColumnVector3 &pqr_fu
 
 void FGRotor::calc_drag_and_side_forces(double theta_0)
 {
-  double cy_over_sigma  ;
+  double cy_over_sigma;
   double t075 = theta_0 + 0.75 * BladeTwist;
 
   H_drag = Thrust * a_dw;
@@ -494,7 +523,7 @@ void FGRotor::calc_drag_and_side_forces(double theta_0)
 
 // Simplified version of /SH79/ eqn(36). Uses an estimate for blade drag
 // (a new config parameter to come...).
-// From "Bramwell's Helicopter Dynamics" � second edition, eqn(3.43) and (3.44)
+// From "Bramwell's Helicopter Dynamics", second edition, eqn(3.43) and (3.44)
 
 void FGRotor::calc_torque(double theta_0)
 {
@@ -560,7 +589,7 @@ void FGRotor::CalcStatePart1(void)
   FGColumnVector3 vHub_ca, avFus_ca;
 
   double h_agl_ft, filtered_hagl = 0.0;
-  double ge_factor = 1.0;  
+  double ge_factor = 1.0;
 
   // fetch needed values from environment
   Vt = fdmex->GetAuxiliary()->GetVt(); // total vehicle velocity including wind
@@ -637,18 +666,52 @@ void FGRotor::CalcStatePart2(double PowerAvailable)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGRotor::GetPowerRequired(void)
-{
-  CalcStatePart1();
-  PowerRequired = Torque * Omega;
-  return PowerRequired;
+// Simulation of a free-wheeling-unit (FWU). Might need improvements.
+
+void FGRotor::calc_freewheel_state(double p_source, double p_load) {
+
+  // engine is off/detached, release.
+  if (p_source<1e-3) { 
+    FreeWheelTransmission = 0.0;
+    return;
+  }
+
+  // engine is driving the rotor, engage.
+  if (p_source >= p_load) {
+    FreeWheelTransmission = 1.0;
+    return;
+  }
+
+  // releases if engine is detached, but stays calm if
+  // the load changes due to rotor dynamics.
+  if (p_source > 0.0 && p_load/(p_source+0.1) > FreeWheelThresh ) {
+    FreeWheelTransmission = 0.0;
+    return;
+  }
+
+  return;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGRotor::Calculate(double PowerAvailable)
+double FGRotor::Calculate(double EnginePower)
 {
-  CalcStatePart2(PowerAvailable);
+  double FWmult = 1.0;
+  double DeltaPower;
+
+  CalcStatePart1();
+
+  PowerRequired = Torque * Omega + BrakeCtrlNorm * MaxBrakePower;
+
+  if (FreeWheelPresent) {
+    calc_freewheel_state(EnginePower * ClutchCtrlNorm, PowerRequired);
+    FWmult = FreeWheelLag.execute(FreeWheelTransmission);
+  }
+
+  DeltaPower = EnginePower * ClutchCtrlNorm * FWmult - PowerRequired;
+
+  CalcStatePart2(DeltaPower);
+
   return Thrust;
 }
 
@@ -702,7 +765,7 @@ bool FGRotor::BindModel(void)
 
   property_name = base_property_name + "/phi-downwash-rad";
   PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetPhiDW );
-  
+
   switch (ControlMap) {
     case eTailCtrl:
       property_name = base_property_name + "/antitorque-ctrl-rad";
@@ -725,6 +788,11 @@ bool FGRotor::BindModel(void)
       PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetLongitudinalCtrl, &FGRotor::SetLongitudinalCtrl);
   }
 
+  property_name = base_property_name + "/brake-ctrl-norm";
+  PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetBrakeCtrl, &FGRotor::SetBrakeCtrl);
+  property_name = base_property_name + "/free-wheel-transmission";
+  PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetFreeWheelTransmission);
+
   if (ExternalRPM) {
     if (RPMdefinition == -1) {
       property_name = base_property_name + "/x-rpm-dict";
@@ -826,6 +894,7 @@ void FGRotor::Debug(int from)
       cout << "      Tip Loss = " << TipLossB << endl;
       cout << "      Lock Number = " << LockNumberByRho * 0.002356 << " (SL)" << endl;
       cout << "      Solidity = " << Solidity << endl;
+      cout << "      Max Brake Power = " << MaxBrakePower/hptoftlbssec << " HP" << endl;
 
       switch (ControlMap) {
         case eTailCtrl:    ControlMapName = "Tail Rotor";   break;
@@ -834,6 +903,12 @@ void FGRotor::Debug(int from)
       }
       cout << "      Control Mapping = " << ControlMapName << endl;
 
+      if (FreeWheelPresent) {
+        cout << "      Free Wheel Threshold = " << FreeWheelThresh << endl;
+      } else {
+        cout << "      No FWU present" << endl;
+      }
+
     }
   }
   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
diff --git a/src/FDM/JSBSim/models/propulsion/FGRotor.h b/src/FDM/JSBSim/models/propulsion/FGRotor.h
index 9892baa37..02fbf9295 100644
--- a/src/FDM/JSBSim/models/propulsion/FGRotor.h
+++ b/src/FDM/JSBSim/models/propulsion/FGRotor.h
@@ -27,6 +27,7 @@ HISTORY
 --------------------------------------------------------------------------------
 01/01/10  T.Kreitler test implementation
 01/10/11  T.Kreitler changed to single rotor model
+03/06/11  T.Kreitler added brake, clutch, and experimental free-wheeling-unit
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 SENTRY
@@ -45,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ROTOR "$Id: FGRotor.h,v 1.8 2011/01/17 22:09:59 jberndt Exp $"
+#define ID_ROTOR "$Id: FGRotor.h,v 1.9 2011/03/10 01:35:25 dpculp Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -76,12 +77,15 @@ CLASS DOCUMENTATION
   <polarmoment unit="{MOMENT}"> {number} </polarmoment>
   <inflowlag> {number} </inflowlag>
   <tiplossfactor> {number} </tiplossfactor>
+  <maxbrakepower unit="{POWER}"> {number} </maxbrakepower>
 
   <controlmap> {MAIN|TAIL|TANDEM} </controlmap>
   <ExternalRPM> {number} </ExternalRPM>
 
   <groundeffectexp> {number} </groundeffectexp>
   <groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift>
+
+  <freewheelthresh> {number} </freewheelthresh>
 </rotor>
 
 //  LENGTH means any of the supported units, same for ANGLE and MOMENT.
@@ -108,10 +112,11 @@ CLASS DOCUMENTATION
     \<massmoment>         - Blade mass moment. Mass of a single blade times the blade's
                              cg-distance from the hub, optional.
     \<polarmoment>        - Moment of inertia for the whole rotor disk, optional.
-    \<inflowlag>          - Rotor inflow time constant, sec. Smaller values yield to
-                              quicker responses to control input (defaults to 0.2).
+    \<inflowlag>          - Rotor inflow time constant, sec. Smaller values yield to quicker
+                              responses (typical values for main rotor: 0.1 - 0.2 s).
     \<tiplossfactor>      - Tip-loss factor. The Blade fraction that produces lift.
                               Value usually ranges between 0.95 - 1.0, optional (B).
+    \<maxbrakepower>      - Rotor brake, 20-30 hp should work for a mid size helicopter.
 
     \<controlmap>         - Defines the control inputs used (see notes).
     \<ExternalRPM>        - Links the rotor to another rotor, or an user controllable property.
@@ -125,6 +130,10 @@ CLASS DOCUMENTATION
                             Omitting or setting to 0.0 disables the effect calculation.
     \<groundeffectshift>  - Further adjustment of ground effect, approx. hub height or slightly above. 
 
+    \<freewheelthresh>    - Ratio of thruster power to engine power. The FWU will release when above
+                              the threshold. The value shouldn't be too close to 1.0, 1.5 seems ok.
+                              0 disables this feature, which is also the default.
+
 </pre>
 
 <h3>Notes:</h3>  
@@ -165,8 +174,6 @@ CLASS DOCUMENTATION
 
   <h4>- Engine issues -</h4>
 
-    Currently the rotor can only be driven with piston and electrical engines. An adaption
-    for the turboprop engine might become available in the future.
     In order to keep the rotor speed constant, use of a RPM-Governor system is 
     encouraged (see examples).
 
@@ -188,11 +195,13 @@ CLASS DOCUMENTATION
     <dt>/AM50/</dt><dd>Amer, Kenneth B.,"Theory of Helicopter Damping in Pitch or Roll and a
               Comparison With Flight Measurements", NACA TN-2136, 1950.</dd>
     <dt>/TA77/</dt><dd>Talbot, Peter D., Corliss, Lloyd D., "A Mathematical Force and Moment
-              Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd>   
+              Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd> 
+    <dt>/GE49/</dt><dd>Gessow, Alfred, Amer, Kenneth B. "An Introduction to the Physical 
+              Aspects of Helicopter Stability", NACA TN-1982, 1949.</dd>  
     </dl>
 
     @author Thomas Kreitler
-    @version $Id: FGRotor.h,v 1.8 2011/01/17 22:09:59 jberndt Exp $
+    @version $Id: FGRotor.h,v 1.9 2011/03/10 01:35:25 dpculp Exp $
   */
 
 
@@ -216,14 +225,11 @@ public:
   /// Destructor for FGRotor
   ~FGRotor();
 
-  /** Returns the power required by the rotor. Well, to achieve this the rotor
-      is cycled through the whole machinery, yielding to a new state.
-      (hmm, sort of a huge side effect)
-  */
-  double GetPowerRequired(void);
+  /** Returns the power required by the rotor. */
+  double GetPowerRequired(void)const { return PowerRequired; }
 
   /** Returns the scalar thrust of the rotor, and adjusts the RPM value. */
-  double Calculate(double PowerAvailable);
+  double Calculate(double EnginePower);
 
 
   /// Retrieves the RPMs of the rotor.
@@ -257,6 +263,8 @@ public:
   double GetCT(void) const { return C_T; }
   /// Retrieves the torque
   double GetTorque(void) const { return Torque; }
+  /// Retrieves the state of the free-wheeling-unit (FWU).
+  double GetFreeWheelTransmission(void) const { return FreeWheelTransmission; }
   
   /// Downwash angle - currently only valid for a rotor that spins horizontally
   double GetThetaDW(void) const { return theta_downwash; }
@@ -269,6 +277,8 @@ public:
   double GetLateralCtrl(void) const { return LateralCtrl; }
   /// Retrieves the longitudinal control input in radians.
   double GetLongitudinalCtrl(void) const { return LongitudinalCtrl; }
+  /// Retrieves the normalized brake control input.
+  double GetBrakeCtrl(void) const { return BrakeCtrlNorm; }
 
   /// Sets the collective control input in radians.
   void SetCollectiveCtrl(double c) { CollectiveCtrl = c; }
@@ -276,6 +286,8 @@ public:
   void SetLateralCtrl(double c) { LateralCtrl = c; }
   /// Sets the longitudinal control input in radians.
   void SetLongitudinalCtrl(double c) { LongitudinalCtrl = c; }
+  /// Sets the normalized brake control input.
+  void SetBrakeCtrl(double c) { BrakeCtrlNorm = c; }
 
   // Stubs. Only main rotor RPM is returned
   string GetThrusterLabels(int id, string delimeter);
@@ -303,6 +315,8 @@ private:
   void calc_drag_and_side_forces(double theta_0);
   void calc_torque(double theta_0);
 
+  void calc_freewheel_state(double pwr_in, double pwr_out);
+
   // transformations
   FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr, 
                                    double a_ic = 0.0 , double b_ic = 0.0 );
@@ -380,6 +394,15 @@ private:
   double LateralCtrl;
   double LongitudinalCtrl;
 
+  double BrakeCtrlNorm, MaxBrakePower;
+
+  // free-wheeling-unit (FWU)
+  int    FreeWheelPresent;        // 'installed' or not
+  double FreeWheelThresh;         // when to release
+  Filter FreeWheelLag;
+  double FreeWheelTransmission;   // state, 0: free, 1:locked
+
+
 };
 
 }
diff --git a/src/FDM/JSBSim/models/propulsion/FGThruster.cpp b/src/FDM/JSBSim/models/propulsion/FGThruster.cpp
index 5af8c1ddd..147aad5da 100644
--- a/src/FDM/JSBSim/models/propulsion/FGThruster.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGThruster.cpp
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGThruster.cpp,v 1.13 2010/08/21 22:56:11 jberndt Exp $";
+static const char *IdSrc = "$Id: FGThruster.cpp,v 1.14 2011/03/10 01:35:25 dpculp Exp $";
 static const char *IdHdr = ID_THRUSTER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -66,6 +66,7 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
 
   GearRatio = 1.0;
   ReverserAngle = 0.0;
+  ClutchCtrlNorm = 1.0;
   EngineNum = num;
   PropertyManager = FDMExec->GetPropertyManager();
 
@@ -98,6 +99,13 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
                                                           &FGThruster::SetReverserAngle);
   }
 
+  if (el->GetName() == "rotor") // At this time only a rotor can have a clutch.
+  {
+    property_name = base_property_name + "/clutch-ctrl-norm";
+    PropertyManager->Tie( property_name.c_str(), (FGThruster *)this, &FGThruster::GetClutchCtrl,
+                                                          &FGThruster::SetClutchCtrl);
+  }
+
   Debug(0);
 }
 
diff --git a/src/FDM/JSBSim/models/propulsion/FGThruster.h b/src/FDM/JSBSim/models/propulsion/FGThruster.h
index 118005f5a..4ef760e98 100644
--- a/src/FDM/JSBSim/models/propulsion/FGThruster.h
+++ b/src/FDM/JSBSim/models/propulsion/FGThruster.h
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_THRUSTER "$Id: FGThruster.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $"
+#define ID_THRUSTER "$Id: FGThruster.h,v 1.16 2011/03/10 01:35:25 dpculp Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -74,7 +74,7 @@ CLASS DOCUMENTATION
     1.57 (pi/2) results in no thrust at all.
  
     @author Jon Berndt
-    @version $Id: FGThruster.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $
+    @version $Id: FGThruster.h,v 1.16 2011/03/10 01:35:25 dpculp Exp $
     */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -105,6 +105,8 @@ public:
   string GetName(void) {return Name;}
   void SetReverserAngle(double angle) {ReverserAngle = angle;}
   double GetReverserAngle(void) const {return ReverserAngle;}
+  double GetClutchCtrl(void) const { return ClutchCtrlNorm; }
+  void SetClutchCtrl(double c) { ClutchCtrlNorm = c; }
   virtual double GetRPM(void) const { return 0.0; };
   double GetGearRatio(void) {return GearRatio; }
   virtual string GetThrusterLabels(int id, string delimeter);
@@ -119,6 +121,7 @@ protected:
   double GearRatio;
   double ThrustCoeff;
   double ReverserAngle;
+  double ClutchCtrlNorm;  
   int EngineNum;
   FGPropertyManager* PropertyManager;
   virtual void Debug(int from);
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
index 485c01c94..d7277ba87 100644
--- a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
@@ -51,7 +51,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.29 2010/08/31 04:01:32 jberndt Exp $";
+static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.31 2011/03/03 12:16:26 jberndt Exp $";
 static const char *IdHdr = ID_TURBINE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -74,6 +74,7 @@ FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number)
   BypassRatio = BleedDemand = 0.0;
   IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0;
   N1_spinup = 1.0; N2_spinup = 3.0; 
+  EPR = 1.0;
 
   ResetToIC();
 
@@ -96,6 +97,9 @@ FGTurbine::~FGTurbine()
 
 void FGTurbine::ResetToIC(void)
 {
+    
+  FGEngine::ResetToIC();
+    
   N1 = N2 = 0.0;
   N2norm = 0.0;
   correctedTSFC = TSFC;
@@ -534,6 +538,8 @@ void FGTurbine::bindmodel()
   PropertyManager->Tie( property_name.c_str(), &Seized);
   property_name = base_property_name + "/stalled";
   PropertyManager->Tie( property_name.c_str(), &Stalled);
+  property_name = base_property_name + "/bleed-factor";
+  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this, &FGTurbine::GetBleedDemand, &FGTurbine::SetBleedDemand);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
old mode 100644
new mode 100755
index 981319961..acc35cca2
--- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
@@ -34,6 +34,7 @@ based on parameters given in the engine config file for this class
 HISTORY
 --------------------------------------------------------------------------------
 05/14/2004  Created
+02/08/2011  T. Kreitler, added rotor support
 
 //JVK (mark)
 
@@ -45,6 +46,7 @@ INCLUDES
 #include <sstream>
 #include "FGTurboProp.h"
 #include "FGPropeller.h"
+#include "FGRotor.h"
 #include "models/FGPropulsion.h"
 #include "models/FGAuxiliary.h"
 
@@ -52,7 +54,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.17 2010/08/21 17:13:48 jberndt Exp $";
+static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.19 2011/03/10 01:35:25 dpculp Exp $";
 static const char *IdHdr = ID_TURBOPROP;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -64,8 +66,10 @@ FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number)
     ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL)
 {
   SetDefaults();
+  thrusterType = Thruster->GetType();
 
   Load(exec, el);
+  bindmodel();
   Debug(0);
 }
 
@@ -101,6 +105,7 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
     MaxN2 = el->FindElementValueAsNumber("maxn2");
   if (el->FindElement("betarangeend"))
     BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0;
+  BetaRangeThrottleEnd = Constrain(0.0, BetaRangeThrottleEnd, 0.99999);
   if (el->FindElement("reversemaxpower"))
     ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0;
 
@@ -146,10 +151,10 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
   delay=1;
   N1_factor = MaxN1 - IdleN1;
   N2_factor = MaxN2 - IdleN2;
-  OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
+  OilTemp_degK = Auxiliary->GetTAT_C() + 273.0;
   if (IdleFF==-1) IdleFF = pow(MilThrust, 0.2) * 107.0;  // just an estimate
 
-  cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << "\n";
+  // cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << endl;
 
   return true;
 }
@@ -162,29 +167,29 @@ void FGTurboProp::Calculate(void)
 {
   RunPreFunctions();
 
-  TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
+  TAT = Auxiliary->GetTAT_C();
   dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
 
-  ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
+  Throttle = FCS->GetThrottlePos(EngineNumber);
 
-  Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
-  if (Thruster->GetType() == FGThruster::ttPropeller) {
+  RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
+  if (thrusterType == FGThruster::ttPropeller) {
     ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
     ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
     ((FGPropeller*)Thruster)->SetReverse(Reversed);
     if (Reversed) {
-      ((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd);
+      ((FGPropeller*)Thruster)->SetReverseCoef(Throttle);
     } else {
       ((FGPropeller*)Thruster)->SetReverseCoef(0.0);
     }
-  }
 
-  if (Reversed) {
-    if (ThrottleCmd < BetaRangeThrottleEnd) {
-        ThrottleCmd = 0.0;  // idle when in Beta-range
-    } else {
-      // when reversed:
-      ThrottleCmd = (ThrottleCmd-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
+    if (Reversed) {
+      if (Throttle < BetaRangeThrottleEnd) {
+          Throttle = 0.0;  // idle when in Beta-range
+      } else {
+        // when reversed:
+        Throttle = (Throttle-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
+      }
     }
   }
 
@@ -223,36 +228,41 @@ void FGTurboProp::Calculate(void)
     StartTime=-1;
   }
 
-  if (Condition < 1) {
-    if (Ielu_max_torque > 0
-      && -Ielu_max_torque > ((FGPropeller*)(Thruster))->GetTorque()
-      && ThrottleCmd >= OldThrottle ) {
-      ThrottleCmd = OldThrottle - 0.1 * dt; //IELU down
-      Ielu_intervent = true;
-    } else if (Ielu_max_torque > 0 && Ielu_intervent && ThrottleCmd >= OldThrottle) {
-      ThrottleCmd = OldThrottle;
-      ThrottleCmd = OldThrottle + 0.05 * dt; //IELU up
-      Ielu_intervent = true;
+  // limiter intervention wanted?
+  if (Ielu_max_torque > 0.0) {
+    double torque = 0.0;
+    
+    if (thrusterType == FGThruster::ttPropeller) {
+      torque = ((FGPropeller*)(Thruster))->GetTorque();
+    } else if (thrusterType == FGThruster::ttRotor) {
+      torque = ((FGRotor*)(Thruster))->GetTorque();
+    }
+
+    if (Condition < 1) {
+      if ( abs(torque) > Ielu_max_torque && Throttle >= OldThrottle ) {
+        Throttle = OldThrottle - 0.1 * dt; //IELU down
+        Ielu_intervent = true;
+      } else if ( Ielu_intervent && Throttle >= OldThrottle) {
+        Throttle = OldThrottle + 0.05 * dt; //IELU up
+        Ielu_intervent = true;
+      } else {
+        Ielu_intervent = false;
+      }
     } else {
       Ielu_intervent = false;
     }
-  } else {
-    Ielu_intervent = false;
+    OldThrottle = Throttle;
   }
-  OldThrottle = ThrottleCmd;
 
   switch (phase) {
-    case tpOff:    Eng_HP = Off(); break;
-    case tpRun:    Eng_HP = Run(); break;
-    case tpSpinUp: Eng_HP = SpinUp(); break;
-    case tpStart:  Eng_HP = Start(); break;
-    default: Eng_HP = 0;
+    case tpOff:    HP = Off(); break;
+    case tpRun:    HP = Run(); break;
+    case tpSpinUp: HP = SpinUp(); break;
+    case tpStart:  HP = Start(); break;
+    default: HP = 0;
   }
-
-  //printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power);
-  PowerAvailable = (Eng_HP * hptoftlbssec) - Thruster->GetPowerRequired();
-
-  Thruster->Calculate(PowerAvailable);
+ 
+  Thruster->Calculate(HP * hptoftlbssec);
 
   RunPostFunctions();
 }
@@ -280,7 +290,7 @@ double FGTurboProp::Off(void)
   ConsumeFuel(); // for possible setting Starved = false when fuel tank
                  // is refilled (fuel crossfeed etc.)
 
-  if (Prop_RPM>5) return -0.012; // friction in engine when propeller spining (estimate)
+  if (RPM>5) return -0.012; // friction in engine when propeller spining (estimate)
   return 0.0;
 }
 
@@ -293,9 +303,9 @@ double FGTurboProp::Run(void)
 
 //---
   double old_N1 = N1;
-  N1 = ExpSeek(&N1, IdleN1 + ThrottleCmd * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
+  N1 = ExpSeek(&N1, IdleN1 + Throttle * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
 
-  EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+  EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
   EngPower_HP *= EnginePowerVC->GetValue();
   if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
 
@@ -346,7 +356,7 @@ double FGTurboProp::SpinUp(void)
   OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
   NozzlePosition = 1.0;
 
-  EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+  EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
   EngPower_HP *= EnginePowerVC->GetValue();
   if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
 
@@ -366,13 +376,15 @@ double FGTurboProp::SpinUp(void)
 
 double FGTurboProp::Start(void)
 {
-  double EngPower_HP,eff_coef;
+  double EngPower_HP = 0.0;
+  double eff_coef;
+
   EngStarting = false;
   if ((N1 > 15.0) && !Starved) {       // minimum 15% N2 needed for start
     double old_N1 = N1;
     Cranking = true;                   // provided for sound effects signal
     if (N1 < IdleN1) {
-      EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+      EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
       EngPower_HP *= EnginePowerVC->GetValue();
       if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
       N1 = ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4);
@@ -391,7 +403,6 @@ double FGTurboProp::Start(void)
       Starter = false;
       Cranking = false;
       FuelFlow_pph = 0;
-      EngPower_HP=0.0;
     }
   } else {                 // no start if N2 < 15% or Starved
     phase = tpOff;
@@ -449,13 +460,14 @@ void FGTurboProp::SetDefaults(void)
 {
 //  Name = "Not defined";
   N1 = N2 = 0.0;
+  HP = 0.0;
   Type = etTurboprop;
   MilThrust = 10000.0;
   IdleN1 = 30.0;
   IdleN2 = 60.0;
   MaxN1 = 100.0;
   MaxN2 = 100.0;
-  ThrottleCmd = 0.0;
+  Throttle = 0.0;
   InletPosition = 1.0;
   NozzlePosition = 1.0;
   Reversed = false;
@@ -472,6 +484,11 @@ void FGTurboProp::SetDefaults(void)
   Ielu_intervent=false;
 
   Idle_Max_Delay = 1.0;
+
+  Throttle = OldThrottle = 0.0;
+  ITT_Delay = 0.05;
+  ReverseMaxPower = 0.0;
+  BetaRangeThrottleEnd = 0.0;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -495,9 +512,9 @@ string FGTurboProp::GetEngineValues(const string& delimiter)
 {
   std::ostringstream buf;
 
-  buf << PowerAvailable << delimiter
-      << N1 << delimiter
+  buf << N1 << delimiter
       << N2 << delimiter
+      << HP << delimiter
       << Thruster->GetThrusterValues(EngineNumber,delimiter);
 
   return buf.str();
@@ -524,10 +541,18 @@ void FGTurboProp::bindmodel()
   base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
   property_name = base_property_name + "/n1";
   PropertyManager->Tie( property_name.c_str(), &N1);
-  property_name = base_property_name + "/n2";
-  PropertyManager->Tie( property_name.c_str(), &N2);
+  // property_name = base_property_name + "/n2";
+  // PropertyManager->Tie( property_name.c_str(), &N2);
   property_name = base_property_name + "/reverser";
   PropertyManager->Tie( property_name.c_str(), &Reversed);
+  property_name = base_property_name + "/power-hp";
+  PropertyManager->Tie( property_name.c_str(), &HP);
+  property_name = base_property_name + "/itt-c";
+  PropertyManager->Tie( property_name.c_str(), &Eng_ITT_degC);
+  property_name = base_property_name + "/engtemp-c";
+  PropertyManager->Tie( property_name.c_str(), &Eng_Temperature);
+  property_name = base_property_name + "/ielu_intervent";
+  PropertyManager->Tie( property_name.c_str(), &Ielu_intervent);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.h b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h
old mode 100644
new mode 100755
index c73c0b765..1c5f48ae9
--- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.h
+++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h
@@ -27,6 +27,7 @@
 HISTORY
 --------------------------------------------------------------------------------
 05/14/2004  Created
+02/08/2011  T. Kreitler, added rotor support
 
 //JVK (mark)
 
@@ -46,7 +47,7 @@ INCLUDES
 #include "input_output/FGXMLElement.h"
 #include "math/FGTable.h"
 
-#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.12 2010/08/21 18:08:37 jberndt Exp $"
+#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.14 2011/03/10 01:35:25 dpculp Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -107,11 +108,10 @@ public:
   void Calculate(void);
   double CalcFuelNeed(void);
 
-  inline double GetPowerAvailable(void) const {return (Eng_HP * hptoftlbssec);}
-  inline double GetPowerAvailable_HP(void) const {return (Eng_HP);}
-  inline double GetPropRPM(void) const {return (Prop_RPM);}
-  inline double GetThrottleCmd(void) const {return (ThrottleCmd);}
-  inline bool GetIeluIntervent(void) const { return Ielu_intervent; }
+  double GetPowerAvailable(void) const { return (HP * hptoftlbssec); }
+  double GetRPM(void) const { return (RPM); }
+  double GetIeluThrottle(void) const { return (Throttle); }
+  bool GetIeluIntervent(void) const { return Ielu_intervent; }
 
   double Seek(double* var, double target, double accel, double decel);
   double ExpSeek(double* var, double target, double accel, double decel);
@@ -165,9 +165,8 @@ private:
   double dt;               ///< Simulator time slice
   double N1_factor;        ///< factor to tie N1 and throttle
   double N2_factor;        ///< factor to tie N2 and throttle
-  double ThrottleCmd;      ///< FCS-supplied throttle position
+  double Throttle;         ///< FCS-supplied throttle position
   double TAT;              ///< total air temperature (deg C)
-  double PowerAvailable;
   bool Stalled;            ///< true if engine is compressor-stalled
   bool Seized;             ///< true if inner spool is seized
   bool Overtemp;           ///< true if EGT exceeds limits
@@ -189,26 +188,27 @@ private:
   double BetaRangeThrottleEnd; // coef (0-1) where is end of beta-range
   double ReverseMaxPower;      // coef (0-1) multiplies max throttle on reverse
 
-  double Idle_Max_Delay;       // time delay for exponencial
+  double Idle_Max_Delay;       // time delay for exponential
   double MaxPower;             // max engine power [HP]
-  double StarterN1;	       // rotates of generator maked by starter [%]
+  double StarterN1;            // rotates of generator maked by starter [%]
   double MaxStartingTime;      // maximal time for start [s] (-1 means not used)
-  double Prop_RPM;             // propeller RPM
+  double RPM;                  // shaft RPM
   double Velocity;
   double rho;
   double PSFC;                 // Power specific fuel comsumption [lb/(HP*hr)] at best efficiency
 
-  double Eng_HP;               // current engine power
+  double HP;                   // engine power output
 
-  double StartTime;	       // engine strating time [s] (0 when start button pushed)
+  double StartTime;            // engine starting time [s] (0 when start button pushed)
 
-  double  ITT_Delay;	       // time delay for exponencial grow of ITT
+  double  ITT_Delay;           // time delay for exponential growth of ITT
   double  Eng_ITT_degC;
   double  Eng_Temperature;     // temperature inside engine
 
   bool EngStarting;            // logicaly output - TRUE if engine is starting
   bool GeneratorPower;
   int Condition;
+  int thrusterType;            // the attached thruster
 
   double Off(void);
   double Run(void);

From 8513a057f3251181ed1f855153e60904bf536932 Mon Sep 17 00:00:00 2001
From: Anders Gidenstam <anders@gidenstam.org>
Date: Wed, 13 Apr 2011 21:06:05 +0200
Subject: [PATCH 2/4] Fixed some memory leaks. Thanks to Andreas Gaeb for
 reporting.

---
 src/FDM/JSBSim/math/FGCondition.cpp                     | 2 ++
 src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp | 3 +++
 src/FDM/JSBSim/models/flight_control/FGFCSComponent.h   | 4 ++--
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/FDM/JSBSim/math/FGCondition.cpp b/src/FDM/JSBSim/math/FGCondition.cpp
index 7f7e9057e..719a3e79d 100644
--- a/src/FDM/JSBSim/math/FGCondition.cpp
+++ b/src/FDM/JSBSim/math/FGCondition.cpp
@@ -173,6 +173,8 @@ void FGCondition::InitializeConditionals(void)
 
 FGCondition::~FGCondition(void)
 {
+  delete TestParam1;
+  delete TestParam2;
   for (unsigned int i=0; i<conditions.size(); i++) delete conditions[i];
 
   Debug(1);
diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
index 4ea969774..64a764927 100644
--- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
@@ -199,6 +199,9 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
 FGFCSComponent::~FGFCSComponent()
 {
   Debug(1);
+  for (unsigned int i=0; i<InputNodes.size(); i++) {
+    delete InputNodes[i];
+  }
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
index 7ad58de0a..02bca98bd 100644
--- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
+++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
@@ -38,7 +38,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGJSBBase.h"
-#include "math/FGParameter.h"
+#include "math/FGPropertyValue.h"
 #include <string>
 #include <vector>
 
@@ -111,7 +111,7 @@ protected:
   std::vector <FGPropertyManager*> OutputNodes;
   FGPropertyManager* ClipMinPropertyNode;
   FGPropertyManager* ClipMaxPropertyNode;
-  std::vector <FGParameter*> InputNodes;
+  std::vector <FGPropertyValue*> InputNodes;
   std::vector <std::string> InputNames;
   std::vector <float> InputSigns;
   std::vector <double> output_array;

From 1456635c558aa95c898d01f5c7ad50a773f6ff58 Mon Sep 17 00:00:00 2001
From: ThorstenB <brehmt@gmail.com>
Date: Wed, 13 Apr 2011 21:30:11 +0200
Subject: [PATCH 3/4] Fixed minor memory leak on joystick reload.

---
 src/Input/FGJoystickInput.cxx | 25 ++++++++++++++++++++-----
 src/Input/FGJoystickInput.hxx |  2 ++
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/src/Input/FGJoystickInput.cxx b/src/Input/FGJoystickInput.cxx
index cf7cc3319..afc7ad8fd 100644
--- a/src/Input/FGJoystickInput.cxx
+++ b/src/Input/FGJoystickInput.cxx
@@ -55,10 +55,15 @@ FGJoystickInput::joystick::joystick ()
 
 FGJoystickInput::joystick::~joystick ()
 {
-//  delete js? why not?
-//   delete js;
+  //  delete js? no, since js == this - and we're in the destructor already.
   delete[] axes;
   delete[] buttons;
+  jsnum = 0;
+  js = NULL;
+  naxes = 0;
+  nbuttons = 0;
+  axes = NULL;
+  buttons = NULL;
 }
 
 
@@ -68,13 +73,24 @@ FGJoystickInput::FGJoystickInput()
 
 FGJoystickInput::~FGJoystickInput()
 {
+    _remove();
 }
 
+void FGJoystickInput::_remove()
+{
+    SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
+    js_nodes->removeChildren("js", false);
+    for (int i = 0; i < MAX_JOYSTICKS; i++)
+    {
+        if (bindings[i].js)
+            delete bindings[i].js;
+        bindings[i].js = NULL;
+    }
+}
 
 void FGJoystickInput::init()
 {
   jsInit();
-                                // TODO: zero the old bindings first.
   SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick bindings");
   SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
 
@@ -121,8 +137,7 @@ void FGJoystickInput::init()
 
 void FGJoystickInput::reinit() {
   SG_LOG(SG_INPUT, SG_DEBUG, "Re-Initializing joystick bindings");
-  SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
-  js_nodes->removeChildren("js", false);
+  _remove();
   FGJoystickInput::init();
   FGJoystickInput::postinit();
 }
diff --git a/src/Input/FGJoystickInput.hxx b/src/Input/FGJoystickInput.hxx
index 039401e29..392fc54b3 100644
--- a/src/Input/FGJoystickInput.hxx
+++ b/src/Input/FGJoystickInput.hxx
@@ -52,6 +52,8 @@ public:
   static const int MAX_JOYSTICK_BUTTONS = 32;
 
 private:
+   void _remove();
+
   /**
    * Settings for a single joystick axis.
    */

From f44dd244624adce06601fbb916fc792334a3fe52 Mon Sep 17 00:00:00 2001
From: Torsten Dreyer <Torsten@t3r.de>
Date: Thu, 14 Apr 2011 11:11:17 +0200
Subject: [PATCH 4/4] Initial commit of the fgpanel code

fgpanel is basically the stripped down 2D-Panel code from
FlightGear. It is designed as a standalone lightweight panel
rendering engine to draw 2d panels on a lowcost computer/graphic card
without 3d acceleration at reasonablel framerates.

Patches for inclusion into the build system will follow.
---
 utils/fgpanel/.gitignore                   |   7 +
 utils/fgpanel/ApplicationProperties.hxx    |  31 +
 utils/fgpanel/FGFontCache.cxx              | 208 +++++
 utils/fgpanel/FGFontCache.hxx              |  86 ++
 utils/fgpanel/FGGLApplication.cxx          |  94 ++
 utils/fgpanel/FGGLApplication.hxx          |  48 +
 utils/fgpanel/FGPNGTextureLoader.cxx       | 142 +++
 utils/fgpanel/FGPNGTextureLoader.hxx       |  26 +
 utils/fgpanel/FGPanelApplication.cxx       | 279 ++++++
 utils/fgpanel/FGPanelApplication.hxx       |  55 ++
 utils/fgpanel/FGPanelProtocol.cxx          | 154 ++++
 utils/fgpanel/FGPanelProtocol.hxx          |  41 +
 utils/fgpanel/FGRGBTextureLoader.cxx       | 504 +++++++++++
 utils/fgpanel/FGRGBTextureLoader.hxx       |  26 +
 utils/fgpanel/FGTextureLoaderInterface.hxx |  27 +
 utils/fgpanel/Makefile.am                  |  20 +
 utils/fgpanel/README                       | 148 ++++
 utils/fgpanel/main.cxx                     |  30 +
 utils/fgpanel/panel.cxx                    | 962 +++++++++++++++++++++
 utils/fgpanel/panel.hxx                    | 451 ++++++++++
 utils/fgpanel/panel_io.cxx                 | 591 +++++++++++++
 utils/fgpanel/panel_io.hxx                 |  40 +
 22 files changed, 3970 insertions(+)
 create mode 100644 utils/fgpanel/.gitignore
 create mode 100644 utils/fgpanel/ApplicationProperties.hxx
 create mode 100644 utils/fgpanel/FGFontCache.cxx
 create mode 100644 utils/fgpanel/FGFontCache.hxx
 create mode 100644 utils/fgpanel/FGGLApplication.cxx
 create mode 100644 utils/fgpanel/FGGLApplication.hxx
 create mode 100644 utils/fgpanel/FGPNGTextureLoader.cxx
 create mode 100644 utils/fgpanel/FGPNGTextureLoader.hxx
 create mode 100644 utils/fgpanel/FGPanelApplication.cxx
 create mode 100644 utils/fgpanel/FGPanelApplication.hxx
 create mode 100644 utils/fgpanel/FGPanelProtocol.cxx
 create mode 100644 utils/fgpanel/FGPanelProtocol.hxx
 create mode 100644 utils/fgpanel/FGRGBTextureLoader.cxx
 create mode 100644 utils/fgpanel/FGRGBTextureLoader.hxx
 create mode 100644 utils/fgpanel/FGTextureLoaderInterface.hxx
 create mode 100644 utils/fgpanel/Makefile.am
 create mode 100644 utils/fgpanel/README
 create mode 100644 utils/fgpanel/main.cxx
 create mode 100644 utils/fgpanel/panel.cxx
 create mode 100644 utils/fgpanel/panel.hxx
 create mode 100644 utils/fgpanel/panel_io.cxx
 create mode 100644 utils/fgpanel/panel_io.hxx

diff --git a/utils/fgpanel/.gitignore b/utils/fgpanel/.gitignore
new file mode 100644
index 000000000..fd82bd006
--- /dev/null
+++ b/utils/fgpanel/.gitignore
@@ -0,0 +1,7 @@
+fgpanel
+*.o
+*.obj
+.deps
+*.Po
+Makefile
+Makefile.in
diff --git a/utils/fgpanel/ApplicationProperties.hxx b/utils/fgpanel/ApplicationProperties.hxx
new file mode 100644
index 000000000..f5578feb2
--- /dev/null
+++ b/utils/fgpanel/ApplicationProperties.hxx
@@ -0,0 +1,31 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef __APPLICATION_PROPERTIES
+#define __APPLICATION_PROPERTIES
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props.hxx>
+#include "FGFontCache.hxx"
+class ApplicationProperties {
+public:
+  static double getDouble( const char * name, double def = 0.0 );
+  static SGPath GetRootPath( const char * subDir = NULL );
+  static SGPropertyNode_ptr Properties;
+  static std::string root;
+  static FGFontCache fontCache;
+};
+#endif
diff --git a/utils/fgpanel/FGFontCache.cxx b/utils/fgpanel/FGFontCache.cxx
new file mode 100644
index 000000000..129e24743
--- /dev/null
+++ b/utils/fgpanel/FGFontCache.cxx
@@ -0,0 +1,208 @@
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+using namespace std;
+#include <map>
+#include <algorithm>
+#include "ApplicationProperties.hxx"
+#include "FGFontCache.hxx"
+////////////////////////////////////////////////////////////////////////
+// FGFontCache class.
+////////////////////////////////////////////////////////////////////////
+
+//extern puFont FONT_HELVETICA_14;
+//extern puFont FONT_SANS_12B;
+
+namespace
+{
+struct GuiFont
+{
+    const char *name;
+    puFont *font;
+    struct Predicate
+        : public std::unary_function<const GuiFont, bool>
+    {
+        Predicate(const char* name_) : name(name_) {}
+        bool operator() (const GuiFont& f1) const
+        {
+            return ::strcmp(f1.name, name) == 0;
+        }
+        const char* name;
+    };
+};
+
+const GuiFont guifonts[] = {
+    { "default",      &PUFONT_HELVETICA_12 },
+    { "FIXED_8x13",   &PUFONT_8_BY_13 },
+    { "FIXED_9x15",   &PUFONT_9_BY_15 },
+    { "TIMES_10",     &PUFONT_TIMES_ROMAN_10 },
+    { "TIMES_24",     &PUFONT_TIMES_ROMAN_24 },
+    { "HELVETICA_10", &PUFONT_HELVETICA_10 },
+    { "HELVETICA_12", &PUFONT_HELVETICA_12 },
+//    { "HELVETICA_14", &FONT_HELVETICA_14 },
+    { "HELVETICA_18", &PUFONT_HELVETICA_18 }
+//    { "SANS_12B",     &FONT_SANS_12B }
+};
+
+const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])];
+}
+
+FGFontCache::FGFontCache() :
+    _initialized(false)
+{
+}
+
+FGFontCache::~FGFontCache()
+{
+   PuFontMap::iterator it, end = _puFonts.end();
+   for (it = _puFonts.begin(); it != end; ++it)
+       delete it->second;
+}
+
+inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
+                                                   const FntParams& f2) const
+{
+    int comp = f1.name.compare(f2.name);
+    if (comp < 0)
+        return true;
+    else if (comp > 0)
+        return false;
+    if (f1.size < f2.size)
+        return true;
+    else if (f1.size > f2.size)
+        return false;
+    return f1.slant < f2.slant;
+}
+
+struct FGFontCache::fnt *
+FGFontCache::getfnt(const char *name, float size, float slant)
+{
+    string fontName(name);
+    FntParams fntParams(fontName, size, slant);
+    PuFontMap::iterator i = _puFonts.find(fntParams);
+    if (i != _puFonts.end())
+        return i->second;
+    // fntTexFont s are all preloaded into the _texFonts map
+    TexFontMap::iterator texi = _texFonts.find(fontName);
+    fntTexFont* texfont = 0;
+    puFont* pufont = 0;
+    if (texi != _texFonts.end()) {
+        texfont = texi->second;
+    } else {
+        const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
+                                              GuiFont::Predicate(name));
+        if (guifont != guifontsEnd) {
+            pufont = guifont->font;
+        }
+    }
+    fnt* f = new fnt;
+    if (pufont) {
+        f->pufont = pufont;
+    } else if (texfont) {
+        f->texfont = texfont;
+        f->pufont = new puFont;
+        f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
+    } else {
+        f->pufont = guifonts[0].font;
+    }
+    _puFonts[fntParams] = f;
+    return f;
+}
+
+puFont *
+FGFontCache::get(const char *name, float size, float slant)
+{
+    return getfnt(name, size, slant)->pufont;
+}
+
+fntTexFont *
+FGFontCache::getTexFont(const char *name, float size, float slant)
+{
+    init();
+    return getfnt(name, size, slant)->texfont;
+}
+
+puFont *
+FGFontCache::get(SGPropertyNode *node)
+{
+    if (!node)
+        return get("Helvetica.txf", 15.0, 0.0);
+
+    const char *name = node->getStringValue("name", "Helvetica.txf");
+    float size = node->getFloatValue("size", 15.0);
+    float slant = node->getFloatValue("slant", 0.0);
+
+    return get(name, size, slant);
+}
+
+void FGFontCache::init()
+{
+    if (!_initialized) {
+        char *envp = ::getenv("FG_FONTS");
+        if (envp != NULL) {
+            _path.set(envp);
+        } else {
+            _path.set(ApplicationProperties::GetRootPath("Fonts").str());
+        }
+        _initialized = true;
+    }
+}
+
+SGPath
+FGFontCache::getfntpath(const char *name)
+{
+    init();
+    SGPath path(_path);
+    if (name && std::string(name) != "") {
+        path.append(name);
+        if (path.exists())
+            return path;
+    }
+
+    path = SGPath(_path);
+    path.append("Helvetica.txf");
+    
+    return path;
+}
+
+bool FGFontCache::initializeFonts()
+{
+    static string fontext("txf");
+    init();
+    ulDir* fontdir = ulOpenDir(_path.c_str());
+    if (!fontdir)
+        return false;
+    const ulDirEnt *dirEntry;
+    while ((dirEntry = ulReadDir(fontdir)) != 0) {
+        SGPath path(_path);
+        path.append(dirEntry->d_name);
+        if (path.extension() == fontext) {
+            fntTexFont* f = new fntTexFont;
+            if (f->load((char *)path.c_str()))
+                _texFonts[string(dirEntry->d_name)] = f;
+            else
+                delete f;
+        }
+    }
+    ulCloseDir(fontdir);
+    return true;
+}
+
+// end of new_gui.cxx
+
diff --git a/utils/fgpanel/FGFontCache.hxx b/utils/fgpanel/FGFontCache.hxx
new file mode 100644
index 000000000..81202eee4
--- /dev/null
+++ b/utils/fgpanel/FGFontCache.hxx
@@ -0,0 +1,86 @@
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef __FGFONTCACHE_HXX
+#define __FGFONTCACHE_HXX
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props.hxx>
+#include <plib/pu.h>
+/**
+ * A class to keep all fonts available for future use.
+ * This also assures a font isn't resident more than once.
+ */
+class FGFontCache {
+private:
+    // The parameters of a request to the cache.
+    struct FntParams
+    {
+        const std::string name;
+        const float size;
+        const float slant;
+        FntParams() : size(0.0f), slant(0.0f) {}
+        FntParams(const FntParams& rhs)
+            : name(rhs.name), size(rhs.size), slant(rhs.slant)
+        {
+        }
+        FntParams(const std::string& name_, float size_, float slant_)
+            : name(name_), size(size_), slant(slant_)
+        {
+        }
+    };
+    struct FntParamsLess
+        : public std::binary_function<const FntParams, const FntParams, bool>
+    {
+        bool operator() (const FntParams& f1, const FntParams& f2) const;
+    };
+    struct fnt {
+        fnt(puFont *pu = 0) : pufont(pu), texfont(0) {}
+        ~fnt() { if (texfont) { delete pufont; delete texfont; } }
+        // Font used by plib GUI code
+        puFont *pufont;
+        // TXF font
+        fntTexFont *texfont;
+    };
+    // Path to the font directory
+    SGPath _path;
+
+    typedef map<const string, fntTexFont*> TexFontMap;
+    typedef map<const FntParams, fnt*, FntParamsLess> PuFontMap;
+    TexFontMap _texFonts;
+    PuFontMap _puFonts;
+
+    bool _initialized;
+    struct fnt *getfnt(const char *name, float size, float slant);
+    void init();
+
+public:
+    FGFontCache();
+    ~FGFontCache();
+
+    puFont *get(const char *name, float size=15.0, float slant=0.0);
+    puFont *get(SGPropertyNode *node);
+
+    fntTexFont *getTexFont(const char *name, float size=15.0, float slant=0.0);
+
+    SGPath getfntpath(const char *name);
+    /**
+     * Preload all the fonts in the FlightGear font directory. It is
+     * important to load the font textures early, with the proper
+     * graphics context current, so that no plib (or our own) code
+     * tries to load a font from disk when there's no current graphics
+     * context.
+     */
+    bool initializeFonts();
+};
+#endif
diff --git a/utils/fgpanel/FGGLApplication.cxx b/utils/fgpanel/FGGLApplication.cxx
new file mode 100644
index 000000000..5c52943b2
--- /dev/null
+++ b/utils/fgpanel/FGGLApplication.cxx
@@ -0,0 +1,94 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#include "FGGLApplication.hxx"
+#include "GL/gl.h"
+#include "GL/glut.h"
+
+#include <iostream>
+#include <exception>
+#include <stdio.h>
+
+FGGLApplication * FGGLApplication::application = NULL;
+
+FGGLApplication::FGGLApplication( const char * aName, int argc, char ** argv ) :
+  gameMode(false),
+  name( aName )
+{
+  if( application != NULL ) {
+    std::cerr << "Only one instance of FGGLApplication allowed!" << std::endl;
+    throw std::exception();
+  }
+  application = this;  
+
+  glutInit( &argc, argv );
+}
+
+FGGLApplication::~FGGLApplication()
+{
+}
+
+void FGGLApplication::DisplayCallback()
+{
+  if( application ) application->Display();
+}
+
+void FGGLApplication::IdleCallback()
+{
+  if( application ) application->Idle();
+}
+
+void FGGLApplication::KeyCallback( unsigned char key, int x, int y )
+{
+  if( application ) application->Key( key, x, y );
+}
+
+void FGGLApplication::ReshapeCallback( int width, int height )
+{
+  if( application ) application->Reshape( width, height );
+}
+
+void FGGLApplication::Run( int glutMode, bool gameMode, int width, int height, int bpp )
+{
+  glutInitDisplayMode(glutMode);
+  if( gameMode ) {
+    width = glutGet(GLUT_SCREEN_WIDTH);
+    height = glutGet(GLUT_SCREEN_HEIGHT);
+    char game_mode_str[20];
+    snprintf(game_mode_str, 20, "%dx%d:%d", width, height, bpp );
+    glutGameModeString( game_mode_str );
+    glutEnterGameMode();
+    this->gameMode = gameMode;
+  } else {
+    if( width == -1 ) 
+      width = glutGet(GLUT_SCREEN_WIDTH);
+
+    if( height == -1 )
+      height = glutGet(GLUT_SCREEN_HEIGHT);
+
+    glutInitDisplayMode(glutMode);
+//    glutInitWindowSize(width, height);
+    windowId = glutCreateWindow(name);
+  }
+  Init();
+
+  glutKeyboardFunc(FGGLApplication::KeyCallback);
+  glutIdleFunc(FGGLApplication::IdleCallback);
+  glutDisplayFunc(FGGLApplication::DisplayCallback);
+  glutReshapeFunc(FGGLApplication::ReshapeCallback);
+  glutMainLoop();
+}
diff --git a/utils/fgpanel/FGGLApplication.hxx b/utils/fgpanel/FGGLApplication.hxx
new file mode 100644
index 000000000..aba699fa8
--- /dev/null
+++ b/utils/fgpanel/FGGLApplication.hxx
@@ -0,0 +1,48 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef __FGGLAPPLICATION_HXX
+#define __FGGLAPPLICATION_HXX
+
+class FGGLApplication {
+public:
+  FGGLApplication( const char * name, int argc, char ** argv );
+  virtual ~FGGLApplication();
+  void Run( int glutMode, bool gameMode, int widht=-1, int height=-1, int bpp = 32 );
+protected:
+  virtual void Key( unsigned char key, int x, int y ) {}
+  virtual void Idle() {}
+  virtual void Display() {}
+  virtual void Reshape( int width, int height ) {}
+
+  virtual void Init() {}
+
+  int windowId;
+  bool gameMode;
+
+  const char * name;
+
+  static FGGLApplication * application;
+private:
+  static void KeyCallback( unsigned char key, int x, int y );
+  static void IdleCallback();
+  static void DisplayCallback();
+  static void ReshapeCallback( int width, int height );
+
+};
+
+#endif
diff --git a/utils/fgpanel/FGPNGTextureLoader.cxx b/utils/fgpanel/FGPNGTextureLoader.cxx
new file mode 100644
index 000000000..236792b57
--- /dev/null
+++ b/utils/fgpanel/FGPNGTextureLoader.cxx
@@ -0,0 +1,142 @@
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#include "FGPNGTextureLoader.hxx"
+
+#include <GL/glu.h>
+#include <png.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+GLuint FGPNGTextureLoader::loadTexture( const string & filename )
+{
+  //header for testing if it is a png
+  png_byte header[8];
+  
+  //open file as binary
+  FILE *fp = fopen(filename.c_str(), "rb");
+  if (!fp) {
+    return NOTEXTURE;
+  }
+  
+  //read the header
+  fread(header, 1, 8, fp);
+  
+  //test if png
+  int is_png = !png_sig_cmp(header, 0, 8);
+  if (!is_png) {
+    fclose(fp);
+    return NOTEXTURE;
+  }
+  
+  //create png struct
+  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
+      NULL, NULL);
+  if (!png_ptr) {
+    fclose(fp);
+    return (NOTEXTURE);
+  }
+  
+  //create png info struct
+  png_infop info_ptr = png_create_info_struct(png_ptr);
+  if (!info_ptr) {
+    png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
+    fclose(fp);
+    return (NOTEXTURE);
+  }
+
+  //create png info struct
+  png_infop end_info = png_create_info_struct(png_ptr);
+  if (!end_info) {
+    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
+    fclose(fp);
+    return (NOTEXTURE);
+  }
+
+  //png error stuff, not sure libpng man suggests this.
+  if (setjmp(png_jmpbuf(png_ptr))) {
+    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+    fclose(fp);
+    return (NOTEXTURE);
+  }
+
+  //init png reading
+  png_init_io(png_ptr, fp);
+  
+  //let libpng know you already read the first 8 bytes
+  png_set_sig_bytes(png_ptr, 8);
+
+  // read all the info up to the image data
+  png_read_info(png_ptr, info_ptr);
+
+  //variables to pass to get info
+  int bit_depth, color_type;
+  png_uint_32 twidth, theight;
+
+  // get info about png
+  png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
+      NULL, NULL, NULL);
+
+  // Update the png info struct.
+  png_read_update_info(png_ptr, info_ptr);
+
+  // Row size in bytes.
+  int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+  // Allocate the image_data as a big block, to be given to opengl
+  png_byte *image_data = new png_byte[rowbytes * theight];
+  if (!image_data) {
+    //clean up memory and close stuff
+    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+    fclose(fp);
+    return NOTEXTURE;
+  }
+
+  //row_pointers is for pointing to image_data for reading the png with libpng
+  png_bytep *row_pointers = new png_bytep[theight];
+  if (!row_pointers) {
+    //clean up memory and close stuff
+    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+    delete[] image_data;
+    fclose(fp);
+    return NOTEXTURE;
+  }
+  // set the individual row_pointers to point at the correct offsets of image_data
+  for (png_uint_32 i = 0; i < theight; ++i)
+    row_pointers[theight - 1 - i] = image_data + i * rowbytes;
+
+  //read the png into image_data through row_pointers
+  png_read_image(png_ptr, row_pointers);
+
+  //Now generate the OpenGL texture object
+  GLuint texture;
+  glGenTextures(1, &texture);
+  glBindTexture(GL_TEXTURE_2D, texture);
+  gluBuild2DMipmaps( GL_TEXTURE_2D, 4, twidth, theight, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image_data );
+  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+//  glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, twidth, theight, 0,
+//      GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
+//  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+  //clean up memory and close stuff
+  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+  delete[] image_data;
+  delete[] row_pointers;
+  fclose(fp);
+  return texture;
+}
diff --git a/utils/fgpanel/FGPNGTextureLoader.hxx b/utils/fgpanel/FGPNGTextureLoader.hxx
new file mode 100644
index 000000000..e8bbfa48c
--- /dev/null
+++ b/utils/fgpanel/FGPNGTextureLoader.hxx
@@ -0,0 +1,26 @@
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef __FGPNGTEXTURELOADER_HXX
+#define __FGPNGTEXTURELOADER_HXX
+
+#include "FGTextureLoaderInterface.hxx"
+
+class FGPNGTextureLoader : public FGTextureLoaderInterface {
+public:
+  virtual GLuint loadTexture( const std::string & filename );
+
+  const static GLuint NOTEXTURE = 0;
+};
+#endif
diff --git a/utils/fgpanel/FGPanelApplication.cxx b/utils/fgpanel/FGPanelApplication.cxx
new file mode 100644
index 000000000..e01f20695
--- /dev/null
+++ b/utils/fgpanel/FGPanelApplication.cxx
@@ -0,0 +1,279 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#include "FGPanelApplication.hxx"
+#include <GL/gl.h>
+#include <GL/glut.h>
+
+#include <simgear/math/SGMisc.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props_io.hxx>
+#include <simgear/structure/exception.hxx>
+
+#include <iostream>
+
+#include "panel_io.hxx"
+#include "ApplicationProperties.hxx"
+
+using namespace std;
+
+inline static string ParseArgs( int argc, char ** argv, const string & token )
+{
+  for( int i = 0; i < argc; i++ ) {
+    string arg = argv[i];
+    if( arg.find( token ) == 0 )
+      return arg.substr( token.length() );
+  }
+  return "";
+}
+
+inline static string ParseArgs( int argc, char ** argv, const char * token )
+{
+  string s = token;
+  return ParseArgs( argc, argv, s );
+}
+
+#include "FGPNGTextureLoader.hxx"
+#include "FGRGBTextureLoader.hxx"
+static FGPNGTextureLoader pngTextureLoader;
+static FGRGBTextureLoader rgbTextureLoader;
+
+FGPanelApplication::FGPanelApplication( int argc, char ** argv ) :
+  FGGLApplication( "FlightGear Panel", argc, argv )
+{
+  sglog().setLogLevels( SG_ALL, SG_WARN );
+  FGCroppedTexture::registerTextureLoader( "png", &pngTextureLoader );
+  FGCroppedTexture::registerTextureLoader( "rgb", &rgbTextureLoader );
+
+  string panelFilename;
+  string fgRoot;
+
+  for( int i = 1; i < argc; i++ ) {
+    panelFilename = ParseArgs( argc, argv, "--panel=" );
+    fgRoot        = ParseArgs( argc, argv, "--fg-root=" );
+  }
+
+  if( fgRoot.length() > 0 )
+    ApplicationProperties::root = fgRoot;
+
+  if( panelFilename.length() == 0 ) {
+    cerr << "Need a panel filename. Use --panel=path_to_filename" << endl; 
+    throw exception();
+  }
+
+  try {
+    SGPath tpath = ApplicationProperties::GetRootPath( panelFilename.c_str() );
+    readProperties( tpath.str(), ApplicationProperties::Properties );
+  }
+  catch( sg_io_exception & e ) {
+    cerr << e.getFormattedMessage() << endl;
+    throw;
+  }
+
+  for( int i = 1; i < argc; i++ ) {
+    string arg = argv[i];
+    if( arg.find( "--prop:" ) == 0 ) {
+      string s2 = arg.substr( 7 );
+      unsigned p = s2.find( "=" );
+      if( p != string::npos ) {
+        string propertyName = s2.substr( 0, p );
+        string propertyValue = s2.substr( p+1 );
+        ApplicationProperties::Properties->getNode( propertyName.c_str(), true )->setValue( propertyValue.c_str() );
+      }
+    }
+  }
+
+  SGPropertyNode_ptr n;
+  if( (n = ApplicationProperties::Properties->getNode( "panel" )) != NULL )
+    panel = FGReadablePanel::read( n );
+
+  protocol = new FGPanelProtocol( ApplicationProperties::Properties->getNode( "communication", true ) );
+  protocol->init();
+}
+
+FGPanelApplication::~FGPanelApplication()
+{
+}
+
+void FGPanelApplication::Run()
+{
+  int mode = GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE;
+  int w = panel == NULL ? 0 : panel->getWidth();
+  int h = panel == NULL ? 0 : panel->getHeight();
+  if( w == 0 && h == 0 ) {
+    w = 1024;
+    h = 768;
+  } else if( w == 0 ) {
+    w = h / 0.75;
+  } else if( h == 0 ) { 
+    h = w * 0.75;
+  }
+  
+  bool gameMode = ApplicationProperties::Properties->getNode( "game-mode", true )->getBoolValue();
+  FGGLApplication::Run( mode, gameMode, w, h );
+}
+
+void FGPanelApplication::Init()
+{
+  glAlphaFunc(GL_GREATER, 0.1);
+  glutSetCursor( GLUT_CURSOR_NONE );
+  ApplicationProperties::fontCache.initializeFonts();  
+}
+
+void FGPanelApplication::Reshape( int width, int height )
+{
+  this->width = width;
+  this->height = height;
+  glViewport(0, 0, (GLsizei) width, (GLsizei) height);
+}
+
+void FGPanelApplication::Idle()
+{
+  double d = glutGet(GLUT_ELAPSED_TIME);
+
+  double dt = Sleep();
+  if( dt == 0 )
+    return;
+
+  if( panel != NULL )
+    panel->update( dt );
+
+  glutSwapBuffers();
+
+  if( protocol != NULL )
+    protocol->update( dt );
+
+  static double dsum = 0.0;
+  static unsigned cnt = 0;
+  dsum += glutGet(GLUT_ELAPSED_TIME)-d;
+  cnt++;
+  if( dsum > 1000.0 ) {
+    ApplicationProperties::Properties->getNode( "/sim/frame-rate", true )->setDoubleValue(cnt*1000.0/dsum );
+    dsum = 0.0;
+    cnt = 0;
+  }
+}
+
+void FGPanelApplication::Key( unsigned char key, int x, int y )
+{
+  switch( key ) {
+    case 0x1b:
+      if( gameMode ) glutLeaveGameMode();
+      else           glutDestroyWindow( windowId );
+      break;
+  }
+}
+
+double FGPanelApplication::Sleep()
+{
+  SGTimeStamp current_time_stamp;
+  static SGTimeStamp last_time_stamp;
+
+  if ( last_time_stamp.get_seconds() == 0 )
+    last_time_stamp.stamp();
+
+  double model_hz = 60;
+  double throttle_hz = ApplicationProperties::getDouble("/sim/frame-rate-throttle-hz", 0.0);
+  if ( throttle_hz > 0.0 ) {
+    // optionally throttle the frame rate (to get consistent frame
+    // rates or reduce cpu usage.
+
+    double frame_us = 1.0e6 / throttle_hz;
+
+    // sleep based timing loop.
+    //
+    // Calling sleep, even usleep() on linux is less accurate than
+    // we like, but it does free up the cpu for other tasks during
+    // the sleep so it is desirable.  Because of the way sleep()
+    // is implemented in consumer operating systems like windows
+    // and linux, you almost always sleep a little longer than the
+    // requested amount.
+    //
+    // To combat the problem of sleeping too long, we calculate the
+    // desired wait time and shorten it by 2000us (2ms) to avoid
+    // [hopefully] over-sleep'ing.  The 2ms value was arrived at
+    // via experimentation.  We follow this up at the end with a
+    // simple busy-wait loop to get the final pause timing exactly
+    // right.
+    //
+    // Assuming we don't oversleep by more than 2000us, this
+    // should be a reasonable compromise between sleep based
+    // waiting, and busy waiting.
+
+    // sleep() will always overshoot by a bit so undersleep by
+    // 2000us in the hopes of never oversleeping.
+    frame_us -= 2000.0;
+    if ( frame_us < 0.0 ) {
+      frame_us = 0.0;
+    }
+    current_time_stamp.stamp();
+
+    /* Convert to ms */
+    double elapsed_us = (current_time_stamp - last_time_stamp).toUSecs();
+    if ( elapsed_us < frame_us ) {
+      double requested_us = frame_us - elapsed_us;
+      usleep ( (useconds_t)(requested_us ) ) ;
+    }
+    // busy wait timing loop.
+    //
+    // This yields the most accurate timing.  If the previous
+    // usleep() call is omitted this will peg the cpu
+    // (which is just fine if FG is the only app you care about.)
+    current_time_stamp.stamp();
+    SGTimeStamp next_time_stamp = last_time_stamp;
+    next_time_stamp += SGTimeStamp::fromSec(1e-6*frame_us);
+    while ( current_time_stamp < next_time_stamp ) {
+      current_time_stamp.stamp();
+    }
+
+  } else {
+    current_time_stamp.stamp();
+  }
+
+  double real_delta_time_sec = double(current_time_stamp.toUSecs() - last_time_stamp.toUSecs()) / 1000000.0;
+  last_time_stamp = current_time_stamp;
+//fprintf(stdout,"\r%4.1lf ", 1/real_delta_time_sec );
+//fflush(stdout);
+
+  // round the real time down to a multiple of 1/model-hz.
+  // this way all systems are updated the _same_ amount of dt.
+  static double reminder = 0.0;
+  static long global_multi_loop = 0;
+  real_delta_time_sec += reminder;
+  global_multi_loop = long(floor(real_delta_time_sec*model_hz));
+  global_multi_loop = SGMisc<long>::max(0, global_multi_loop);
+  reminder = real_delta_time_sec - double(global_multi_loop)/double(model_hz);
+  return double(global_multi_loop)/double(model_hz);
+}
+
+double ApplicationProperties::getDouble( const char * name, double def )
+{
+  SGPropertyNode_ptr n = ApplicationProperties::Properties->getNode( name, false );
+  if( n == NULL ) return def;
+  return n->getDoubleValue();
+}
+SGPath ApplicationProperties::GetRootPath( const char * sub )
+{
+  SGPath path( ApplicationProperties::root );
+  if( sub != NULL )
+    path.append( sub );
+  return path;
+}
+
+std::string ApplicationProperties::root = ".";
+SGPropertyNode_ptr ApplicationProperties::Properties = new SGPropertyNode;
+FGFontCache ApplicationProperties::fontCache;
diff --git a/utils/fgpanel/FGPanelApplication.hxx b/utils/fgpanel/FGPanelApplication.hxx
new file mode 100644
index 000000000..f2652ee3a
--- /dev/null
+++ b/utils/fgpanel/FGPanelApplication.hxx
@@ -0,0 +1,55 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef __FGPANELAPPLICATION_HXX
+#define __FGPANELAPPLICATION_HXX
+
+#include "FGGLApplication.hxx"
+#include "FGPanelProtocol.hxx"
+
+#include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/props/props.hxx>
+
+#include <string>
+
+#include "panel.hxx"
+
+class FGPanelApplication : public FGGLApplication {
+public:
+  FGPanelApplication( int argc, char ** argv );
+  ~FGPanelApplication();
+
+  void Run();
+
+protected:
+  virtual void Key( unsigned char key, int x, int y );
+  virtual void Idle();
+//  virtual void Display();
+  virtual void Reshape( int width, int height );
+
+  virtual void Init();
+
+  double Sleep();
+
+  SGSharedPtr<FGPanel> panel;
+  SGSharedPtr<FGPanelProtocol> protocol;
+
+  int width;
+  int height;
+};
+
+#endif
diff --git a/utils/fgpanel/FGPanelProtocol.cxx b/utils/fgpanel/FGPanelProtocol.cxx
new file mode 100644
index 000000000..0743724c8
--- /dev/null
+++ b/utils/fgpanel/FGPanelProtocol.cxx
@@ -0,0 +1,154 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#include "FGPanelProtocol.hxx"
+#include "ApplicationProperties.hxx"
+#include <simgear/io/sg_socket.hxx>
+#include <simgear/misc/strutils.hxx>
+
+class PropertySetter {
+public:
+  PropertySetter( SGPropertyNode_ptr node ) : _node(node) {}
+  virtual void setValue( const char * value ) = 0;
+protected:
+  SGPropertyNode_ptr _node;
+};
+
+class BoolPropertySetter : public PropertySetter {
+public:
+  BoolPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
+  virtual void setValue( const char * value ) {
+    _node->setBoolValue( atoi( value ) != 0 );
+  }
+};
+
+class IntPropertySetter : public PropertySetter {
+public:
+  IntPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
+  virtual void setValue( const char * value ) {
+    _node->setIntValue( atol( value ) );
+  }
+};
+
+class FloatPropertySetter : public PropertySetter {
+public:
+  FloatPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
+  virtual void setValue( const char * value ) {
+    _node->setFloatValue( strtof( value, NULL ) );
+  }
+};
+
+class DoublePropertySetter : public PropertySetter {
+public:
+  DoublePropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
+  virtual void setValue( const char * value ) {
+    _node->setDoubleValue( strtod( value, NULL ) );
+  }
+};
+
+class StringPropertySetter : public PropertySetter {
+public:
+  StringPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
+  virtual void setValue( const char * value ) {
+    _node->setStringValue( value );
+  }
+};
+
+FGPanelProtocol::FGPanelProtocol( SGPropertyNode_ptr aRoot )
+  : SGSubsystem(),
+   root(aRoot),
+   io(NULL)
+{
+  SGPropertyNode_ptr outputNode = root->getNode( "protocol/generic/output" );
+  if( outputNode ) {
+    vector<SGPropertyNode_ptr> chunks = outputNode->getChildren( "chunk" );
+    for( vector<SGPropertyNode_ptr>::size_type i = 0; i < chunks.size(); i++ ) {
+      SGPropertyNode_ptr chunk = chunks[i];
+
+      SGPropertyNode_ptr nodeNode = chunk->getNode("node", false );
+      if( nodeNode == NULL )
+        continue;
+
+      SGPropertyNode_ptr node = ApplicationProperties::Properties->getNode( nodeNode->getStringValue(), true );
+
+      string type = "";
+      SGPropertyNode_ptr typeNode = chunk->getNode( "type", false );
+      if( typeNode != NULL ) type = typeNode->getStringValue();
+      if( type == "float" ) {
+        propertySetterVector.push_back( new FloatPropertySetter( node ) );
+      } else if( type == "double" || type == "fixed" ) {
+        propertySetterVector.push_back( new DoublePropertySetter( node ) );
+      } else if( type == "bool" || type == "boolean" ) {
+        propertySetterVector.push_back( new BoolPropertySetter( node ) );
+      } else if( type == "string" ) {
+        propertySetterVector.push_back( new StringPropertySetter( node ) );
+      } else {
+        propertySetterVector.push_back( new IntPropertySetter( node ) );
+      }
+    }
+  }
+}
+
+FGPanelProtocol::~FGPanelProtocol()
+{
+  for( PropertySetterVector::size_type i = 0; i < propertySetterVector.size(); i++ )
+    delete propertySetterVector[i];
+}
+
+void FGPanelProtocol::update( double dt )
+{
+  char buf[8192];
+
+  if( io == NULL )
+    return;
+
+  int length = io->readline( buf, sizeof(buf)-1 );
+  buf[sizeof(buf)-1] = 0;
+  if ( length > 0 ) {
+    vector<string> tokens = simgear::strutils::split( buf, "," );
+    for( vector<string>::size_type i = 0; i < tokens.size(); i++ ) {
+      if( i < propertySetterVector.size() )
+        propertySetterVector[i]->setValue( tokens[i].c_str() );
+    }
+  }
+}
+
+void FGPanelProtocol::init()
+{
+  SGPropertyNode_ptr listenNode = root->getNode( "listen" );
+  if( listenNode == NULL ) {
+    return;
+  }
+
+  string hostname = listenNode->getNode( "host", true )->getStringValue();
+  string port = listenNode->getNode( "port", true )->getStringValue();
+  string style = listenNode->getNode( "style", true )->getStringValue();
+
+  if( io != NULL )
+    delete io;
+
+  io = new SGSocket( hostname, port, style );
+
+  if( !io->open( SG_IO_IN ) ) {
+    cerr << "can't open socket " << style << ":" << hostname << ":" << port << endl;
+  }
+}
+
+void FGPanelProtocol::reinit()
+{
+  init();
+}
diff --git a/utils/fgpanel/FGPanelProtocol.hxx b/utils/fgpanel/FGPanelProtocol.hxx
new file mode 100644
index 000000000..5b08daf7f
--- /dev/null
+++ b/utils/fgpanel/FGPanelProtocol.hxx
@@ -0,0 +1,41 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef __FGPANELPROTOCOL_HXX
+#define __FGPANELPROTOCOL_HXX
+#include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/props/props.hxx>
+#include <simgear/io/iochannel.hxx>
+class PropertySetter;
+
+typedef vector<PropertySetter*> PropertySetterVector;
+class FGPanelProtocol : public SGSubsystem {
+public:
+  FGPanelProtocol( SGPropertyNode_ptr root );
+  virtual ~FGPanelProtocol();
+  virtual void init();
+  virtual void reinit();
+  virtual void update( double dt );
+
+protected:
+
+private:
+  SGPropertyNode_ptr root;
+  SGIOChannel * io;
+  PropertySetterVector propertySetterVector;
+};
+#endif
diff --git a/utils/fgpanel/FGRGBTextureLoader.cxx b/utils/fgpanel/FGRGBTextureLoader.cxx
new file mode 100644
index 000000000..faf136942
--- /dev/null
+++ b/utils/fgpanel/FGRGBTextureLoader.cxx
@@ -0,0 +1,504 @@
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+// From the OpenSceneGraph distribution ReaderWriterRGB.cpp
+// Reader for sgi's .rgb format.
+// specification can be found at http://local.wasp.uwa.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html
+
+#include "FGRGBTextureLoader.hxx"
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+typedef struct _rawImageRec
+{
+    unsigned short imagic;
+    unsigned short type;
+    unsigned short dim;
+    unsigned short sizeX, sizeY, sizeZ;
+    unsigned long min, max;
+    unsigned long wasteBytes;
+    char name[80];
+    unsigned long colorMap;
+    std::istream *file;
+    unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
+    unsigned long rleEnd;
+    GLuint *rowStart;
+    GLint *rowSize;
+    GLenum swapFlag;
+    short bpc;
+  
+    typedef unsigned char * BytePtr;
+
+    bool needsBytesSwapped()
+    {
+        union {
+            int testWord;
+            char testByte[sizeof(int)];
+        }endianTest; 
+        endianTest.testWord = 1;
+        if( endianTest.testByte[0] == 1 )
+            return true;
+        else
+            return false;
+    }
+
+    template <class T>
+    inline void swapBytes(  T &s )
+    {
+        if( sizeof( T ) == 1 ) 
+            return;
+
+        T d = s;
+        BytePtr sptr = (BytePtr)&s;
+        BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
+
+        for( unsigned int i = 0; i < sizeof(T); i++ )
+            *(sptr++) = *(dptr--);
+    }
+
+    void swapBytes()
+    {
+        swapBytes( imagic );
+        swapBytes( type );
+        swapBytes( dim );
+        swapBytes( sizeX );
+        swapBytes( sizeY );
+        swapBytes( sizeZ );
+        swapBytes( wasteBytes );
+        swapBytes( min );
+        swapBytes( max );
+        swapBytes( colorMap );
+    }
+} rawImageRec;
+
+static void ConvertShort(unsigned short *array, long length)
+{
+    unsigned long b1, b2;
+    unsigned char *ptr;
+
+    ptr = (unsigned char *)array;
+    while (length--)
+    {
+        b1 = *ptr++;
+        b2 = *ptr++;
+        *array++ = (unsigned short) ((b1 << 8) | (b2));
+    }
+}
+
+static void ConvertLong(GLuint *array, long length)
+{
+    unsigned long b1, b2, b3, b4;
+    unsigned char *ptr;
+
+    ptr = (unsigned char *)array;
+    while (length--)
+    {
+        b1 = *ptr++;
+        b2 = *ptr++;
+        b3 = *ptr++;
+        b4 = *ptr++;
+        *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
+    }
+}
+
+
+static void RawImageClose(rawImageRec *raw)
+{
+    if (raw)
+    {
+        
+        if (raw->tmp) delete [] raw->tmp;
+        if (raw->tmpR) delete [] raw->tmpR;
+        if (raw->tmpG) delete [] raw->tmpG;
+        if (raw->tmpB) delete [] raw->tmpB;
+        if (raw->tmpA) delete [] raw->tmpA;
+
+        if (raw->rowStart) delete [] raw->rowStart;        
+        if (raw->rowSize) delete [] raw->rowSize;        
+
+        delete raw;
+    }
+}
+
+
+static rawImageRec *RawImageOpen(std::istream& fin)
+{
+    union
+    {
+        int testWord;
+        char testByte[4];
+    } endianTest;
+    rawImageRec *raw;
+    int x;
+
+    raw = new rawImageRec;
+    if (raw == NULL)
+    {
+//        notify(WARN)<< "Out of memory!"<< std::endl;
+        return NULL;
+    }
+
+    //Set istream pointer
+    raw->file = &fin;
+
+    endianTest.testWord = 1;
+    if (endianTest.testByte[0] == 1)
+    {
+        raw->swapFlag = GL_TRUE;
+    }
+    else
+    {
+        raw->swapFlag = GL_FALSE;
+    }
+
+    fin.read((char*)raw,12);
+    if (!fin.good())
+        return NULL;
+
+    if (raw->swapFlag)
+    {
+        ConvertShort(&raw->imagic, 6);
+    }
+
+    raw->tmp = raw->tmpR = raw->tmpG = raw->tmpB = raw->tmpA = 0L;
+    raw->rowStart = 0;
+    raw->rowSize = 0;
+    raw->bpc = (raw->type & 0x00FF);
+
+    raw->tmp = new unsigned char [raw->sizeX*256*raw->bpc];
+    if (raw->tmp == NULL )
+    {
+//        notify(FATAL)<< "Out of memory!"<< std::endl;
+        RawImageClose(raw);
+        return NULL;
+    }
+
+    if( raw->sizeZ >= 1 )
+    {
+        if( (raw->tmpR = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
+        {
+//            notify(FATAL)<< "Out of memory!"<< std::endl;
+            RawImageClose(raw);
+            return NULL;
+        }
+    }
+    if( raw->sizeZ >= 2 )
+    {
+        if( (raw->tmpG = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
+        {
+//            notify(FATAL)<< "Out of memory!"<< std::endl;
+            RawImageClose(raw);
+            return NULL;
+        }
+    }
+    if( raw->sizeZ >= 3 )
+    {
+        if( (raw->tmpB = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
+        {
+//            notify(FATAL)<< "Out of memory!"<< std::endl;
+            RawImageClose(raw);
+            return NULL;
+        }
+    }
+    if (raw->sizeZ >= 4)
+    {
+        if( (raw->tmpA = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
+        {
+//            notify(FATAL)<< "Out of memory!"<< std::endl;
+            RawImageClose(raw);
+            return NULL;
+        }
+    }
+    
+    if ((raw->type & 0xFF00) == 0x0100)
+    {
+        unsigned int ybyz = raw->sizeY * raw->sizeZ;
+        if ( (raw->rowStart = new GLuint [ybyz]) == NULL )
+        {
+//            notify(FATAL)<< "Out of memory!"<< std::endl;
+            RawImageClose(raw);
+            return NULL;
+        }
+
+        if ( (raw->rowSize = new GLint [ybyz]) == NULL )
+        {
+//            notify(FATAL)<< "Out of memory!"<< std::endl;
+            RawImageClose(raw);
+            return NULL;
+        }
+        x = ybyz * sizeof(GLuint);
+        raw->rleEnd = 512 + (2 * x);
+                fin.seekg(512,std::ios::beg);
+        fin.read((char*)raw->rowStart,x);
+        fin.read((char*)raw->rowSize,x);
+        if (raw->swapFlag)
+        {
+            ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
+            ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
+        }
+    }
+    return raw;
+}
+
+
+static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
+{
+    unsigned char *iPtr, *oPtr;
+    unsigned short pixel;
+    int count, done = 0;
+    unsigned short *tempShort;
+
+    if ((raw->type & 0xFF00) == 0x0100)
+    {
+        raw->file->seekg((long) raw->rowStart[y+z*raw->sizeY], std::ios::beg);
+        raw->file->read((char*)raw->tmp, (unsigned int)raw->rowSize[y+z*raw->sizeY]);
+
+        iPtr = raw->tmp;
+        oPtr = buf;
+        while (!done)
+        {
+            if (raw->bpc == 1)
+                pixel = *iPtr++;
+            else
+            {
+                tempShort = reinterpret_cast<unsigned short*>(iPtr);
+                pixel = *tempShort;
+                tempShort++;
+                iPtr = reinterpret_cast<unsigned char *>(tempShort);
+            }
+            
+            if(raw->bpc != 1)
+                ConvertShort(&pixel, 1);
+
+            count = (int)(pixel & 0x7F);
+            
+            // limit the count value to the remiaing row size
+            if (oPtr + count*raw->bpc > buf + raw->sizeX*raw->bpc)
+            {
+                count = ( (buf + raw->sizeX*raw->bpc) - oPtr ) / raw->bpc;
+            }
+                
+            if (count<=0)
+            {
+                done = 1;
+                return;
+            }
+            
+            if (pixel & 0x80)
+            {
+                while (count--)
+                {
+                    if(raw->bpc == 1)
+                        *oPtr++ = *iPtr++;
+                    else{
+                        tempShort = reinterpret_cast<unsigned short*>(iPtr);
+                        pixel = *tempShort;
+                        tempShort++;
+                        iPtr = reinterpret_cast<unsigned char *>(tempShort);
+                        
+                        ConvertShort(&pixel, 1);
+
+                        tempShort = reinterpret_cast<unsigned short*>(oPtr);
+                        *tempShort = pixel;
+                        tempShort++;
+                        oPtr = reinterpret_cast<unsigned char *>(tempShort);
+                    }
+                }
+            }
+            else
+            {
+                if (raw->bpc == 1)
+                {
+                    pixel = *iPtr++;
+                }
+                else
+                {
+                    tempShort = reinterpret_cast<unsigned short*>(iPtr);
+                    pixel = *tempShort;
+                    tempShort++;
+                    iPtr = reinterpret_cast<unsigned char *>(tempShort);
+                }
+                if(raw->bpc != 1)
+                    ConvertShort(&pixel, 1);
+                while (count--)
+                {
+                    if(raw->bpc == 1)
+                        *oPtr++ = pixel;
+                    else
+                    {
+                        tempShort = reinterpret_cast<unsigned short*>(oPtr);
+                        *tempShort = pixel;
+                        tempShort++;
+                        oPtr = reinterpret_cast<unsigned char *>(tempShort);
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        raw->file->seekg(512+(y*raw->sizeX*raw->bpc)+(z*raw->sizeX*raw->sizeY*raw->bpc),std::ios::beg);
+        raw->file->read((char*)buf, raw->sizeX*raw->bpc);
+        if(raw->swapFlag && raw->bpc != 1){
+            ConvertShort(reinterpret_cast<unsigned short*>(buf), raw->sizeX);
+        }
+    }
+}
+
+
+static void RawImageGetData(rawImageRec *raw, unsigned char **data )
+{
+    unsigned char *ptr;
+    int i, j;
+    unsigned short *tempShort;
+
+    //     // round the width to a factor 4
+    //     int width = (int)(floorf((float)raw->sizeX/4.0f)*4.0f);
+    //     if (width!=raw->sizeX) width += 4;
+
+    // byte aligned.
+    
+//    osg::notify(osg::INFO)<<"raw->sizeX = "<<raw->sizeX<<std::endl;
+//    osg::notify(osg::INFO)<<"raw->sizeY = "<<raw->sizeY<<std::endl;
+//    osg::notify(osg::INFO)<<"raw->sizeZ = "<<raw->sizeZ<<std::endl;
+//    osg::notify(osg::INFO)<<"raw->bpc = "<<raw->bpc<<std::endl;
+    
+    *data = new unsigned char [(raw->sizeX)*(raw->sizeY)*(raw->sizeZ)*(raw->bpc)];
+
+    ptr = *data;
+    for (i = 0; i < (int)(raw->sizeY); i++)
+    {
+        if( raw->sizeZ >= 1 )
+            RawImageGetRow(raw, raw->tmpR, i, 0);
+        if( raw->sizeZ >= 2 )
+            RawImageGetRow(raw, raw->tmpG, i, 1);
+        if( raw->sizeZ >= 3 )
+            RawImageGetRow(raw, raw->tmpB, i, 2);
+        if( raw->sizeZ >= 4 )
+            RawImageGetRow(raw, raw->tmpA, i, 3);
+        for (j = 0; j < (int)(raw->sizeX); j++)
+        {
+          if(raw->bpc == 1){
+            if( raw->sizeZ >= 1 )
+                *ptr++ = *(raw->tmpR + j);
+            if( raw->sizeZ >= 2 )
+                *ptr++ = *(raw->tmpG + j);
+            if( raw->sizeZ >= 3 )
+                *ptr++ = *(raw->tmpB + j);
+            if( raw->sizeZ >= 4 )
+                *ptr++ = *(raw->tmpA + j);
+          }else{
+            if( raw->sizeZ >= 1 )
+            {
+                tempShort = reinterpret_cast<unsigned short*>(ptr);
+                *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpR) + j);
+                tempShort++;
+                ptr = reinterpret_cast<unsigned char *>(tempShort);
+            }
+            if( raw->sizeZ >= 2 )
+            {
+                tempShort = reinterpret_cast<unsigned short*>(ptr);
+                *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpG) + j);
+                tempShort++;
+                ptr = reinterpret_cast<unsigned char *>(tempShort);
+            }
+            if( raw->sizeZ >= 3 )
+            {
+                tempShort = reinterpret_cast<unsigned short*>(ptr);
+                *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpB) + j);
+                tempShort++;
+                ptr = reinterpret_cast<unsigned char *>(tempShort);
+            }
+            if( raw->sizeZ >= 4 )
+            {
+                tempShort = reinterpret_cast<unsigned short*>(ptr);
+                *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpA) + j);
+                tempShort++;
+                ptr = reinterpret_cast<unsigned char *>(tempShort);
+            }
+          }
+        }
+        //         // pad the image width with blanks to bring it up to the rounded width.
+        //         for(;j<width;++j) *ptr++ = 0;
+    }
+}
+
+
+//            supportsExtension("rgb","rgb image format");
+//            supportsExtension("rgba","rgba image format");
+//            supportsExtension("sgi","sgi image format");
+//            supportsExtension("int","int image format");
+//            supportsExtension("inta","inta image format");
+//            supportsExtension("bw","bw image format");
+        
+        GLuint readRGBStream(std::istream& fin)
+        {
+            rawImageRec *raw;
+
+            if( (raw = RawImageOpen(fin)) == NULL )
+            {
+                return 0;
+            }
+
+            int s = raw->sizeX;
+            int t = raw->sizeY;
+//            int r = 1;
+
+        #if 0
+            int internalFormat = raw->sizeZ == 3 ? GL_RGB5 :
+            raw->sizeZ == 4 ? GL_RGB5_A1 : GL_RGB;
+        #else
+//            int internalFormat = raw->sizeZ;
+        #endif
+            unsigned int pixelFormat =
+                raw->sizeZ == 1 ? GL_LUMINANCE :
+                raw->sizeZ == 2 ? GL_LUMINANCE_ALPHA :
+                raw->sizeZ == 3 ? GL_RGB :
+                raw->sizeZ == 4 ? GL_RGBA : (GLenum)-1;
+            GLint component = raw->sizeZ;
+
+            unsigned int dataType = raw->bpc == 1 ? GL_UNSIGNED_BYTE :
+              GL_UNSIGNED_SHORT;
+
+            unsigned char *data;
+            RawImageGetData(raw, &data);
+            RawImageClose(raw);
+
+  GLuint texture;
+  glGenTextures(1, &texture);
+  glBindTexture(GL_TEXTURE_2D, texture);
+  gluBuild2DMipmaps( GL_TEXTURE_2D, component, s, t, pixelFormat, dataType, (GLvoid*)data );
+  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+
+            delete []data;
+            return texture;
+        }
+
+GLuint FGRGBTextureLoader::loadTexture( const std::string & filename )
+{
+  GLuint texture = NOTEXTURE;
+  std::ifstream istream(filename.c_str(), std::ios::in | std::ios::binary );
+  texture = readRGBStream(istream);
+  istream.close();
+  return texture;
+}
+
diff --git a/utils/fgpanel/FGRGBTextureLoader.hxx b/utils/fgpanel/FGRGBTextureLoader.hxx
new file mode 100644
index 000000000..e3c27664b
--- /dev/null
+++ b/utils/fgpanel/FGRGBTextureLoader.hxx
@@ -0,0 +1,26 @@
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef __FGRGBTEXTURELOADER_HXX
+#define __FGRGBTEXTURELOADER_HXX
+
+#include "FGTextureLoaderInterface.hxx"
+
+class FGRGBTextureLoader : public FGTextureLoaderInterface {
+public:
+  virtual GLuint loadTexture( const std::string & filename );
+
+  const static GLuint NOTEXTURE = 0;
+};
+#endif
diff --git a/utils/fgpanel/FGTextureLoaderInterface.hxx b/utils/fgpanel/FGTextureLoaderInterface.hxx
new file mode 100644
index 000000000..58c15b853
--- /dev/null
+++ b/utils/fgpanel/FGTextureLoaderInterface.hxx
@@ -0,0 +1,27 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef __FGTEXTURELOADERINTERFACE_HXX
+#define __FGTEXTURELOADERINTERFACE_HXX
+
+#include <GL/gl.h>
+#include <string>
+class FGTextureLoaderInterface {
+public:
+  virtual GLuint loadTexture( const std::string & filename ) = 0;
+};
+#endif
diff --git a/utils/fgpanel/Makefile.am b/utils/fgpanel/Makefile.am
new file mode 100644
index 000000000..58804e9c5
--- /dev/null
+++ b/utils/fgpanel/Makefile.am
@@ -0,0 +1,20 @@
+AM_CXXFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\"
+
+bin_PROGRAMS = fgpanel
+
+fgpanel_SOURCES = main.cxx \
+		FGGLApplication.cxx FGGLApplication.hxx \
+		FGPanelApplication.cxx FGPanelApplication.hxx \
+                FGPNGTextureLoader.cxx FGPNGTextureLoader.hxx FGTextureLoaderInterface.hxx \
+                FGRGBTextureLoader.cxx FGRGBTextureLoader.hxx \
+		FGPanelProtocol.cxx \
+		FGFontCache.cxx \
+		panel.cxx panel.hxx \
+		panel_io.cxx panel_io.hxx
+
+LIBS =
+
+fgpanel_LDADD = \
+	-lGLU -lglut -lsgmath -lsgprops -lsgio -lsgdebug -lsgmisc -lsgstructure -lsgxml -lsgtiming \
+	-lplibpu -lplibfnt -lplibul \
+	-lrt -lpng
diff --git a/utils/fgpanel/README b/utils/fgpanel/README
new file mode 100644
index 000000000..a1199d2c9
--- /dev/null
+++ b/utils/fgpanel/README
@@ -0,0 +1,148 @@
+=====================================================================
+This is fgpanel - basically the stripped down 2D-Panel code from
+FlightGear. It is designed as a standalone lightweight panel 
+rendering engine to draw 2d panels on a lowcost computer/graphic card
+without 3d acceleration at reasonablel framerates.
+
+=====================================================================
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+=====================================================================
+Usage
+start fgpanel with
+fgpanel --fg-root=/path/to/fg/data --panel=Aircraft/MyAircraft/Panels/MyPanel.xml
+with the command args set to
+--fg-root shall point to the directory where your FGDATA lives
+  NOTE: you don't need a full copy of FGDATA, just the panel definition files for
+  your aircraft, e.g.
+  - Aircraft/MyAircraft/Panels/*
+  - Aircraft/Instruments/* (if referenced)
+
+-panel shall point to a panel-configuration file, relative to FGDATA
+
+start flightgear with
+fgfs --generic=socket,out,10,239.24.10.64,5432,udp,../Aircraft/MyAircraft/Panels/SampleProtocol
+
+=====================================================================
+Sample:
+
+Create the sample files within your aicraft directory, preferrable under Panels
+MyPanel.xml
+sample-2d-panel.xml
+SampleProtocol.xml
+
+=====================================================================
+Sample panel configuration file (MyPanel.xml)
+<PropertyList>
+
+  <!-- true: run full-screen, false; run in window -->
+  <game-mode type="bool">false</game-mode>
+
+  <!-- include the panel definitions (2d-panel syntax)-->
+  <panel include="sample-2d-panel.xml"/>
+
+  <!-- compose your property-tree here -->
+  <sim>
+    <panel>
+      <flip-x type="bool">false</flip-x>
+    </panel>
+    <instrument-options>
+      <omit-knobs type="bool">true</omit-knobs>
+    </instrument-options>
+  </sim>
+
+  <!-- network communication settings -->
+  <communication>
+    <listen>
+      <!-- interface to bind to, 
+           leave empty for all interfaces -->
+      <host>239.24.10.64</host> <!-- multicast address! -->
+      <port>5432</port> <!-- tcp port to listen to -->
+      <style>udp</style> <!-- udp or tcp (forget about tcp!) -->
+    </listen>
+
+    <!-- the generic protocol definition 
+         same as used for fgfs --generic=foobar option
+    -->
+    <protocol include="SampleProtocol.xml"/>
+  </communication>
+</PropertyList>
+
+=====================================================================
+Sampe 2d-panel configuration file sample-2d-panel.xml
+To be included from the panel configuration file
+
+<?xml version="1.0"?>
+<PropertyList>
+    <name>Sample Instrument Panel</name>
+    <w>375</w> <!-- screen width: 375mm -->
+    <h>305</h> <!-- screen height: 305mm -->
+    <instruments>
+        <!-- use FlightGear's c172 attitude indicator -->
+        <instrument include="../../Instruments/ati-c172s.xml">
+            <name>Attitude Gyro</name>
+            <x alias="../../../params/col-2"/>
+            <y alias="../../../params/row-1"/>
+            <w>80</w>
+            <h>80</h>
+        </instrument>
+    </instruments>
+</PropertyList>
+
+=====================================================================
+Sample protocol configuration file to drive the AI (SampleProtocol.xml)
+<?xml version="1.0"?>
+
+<PropertyList>
+ <generic>
+
+  <output>
+   <line_separator>newline</line_separator>
+   <var_separator>,</var_separator>
+
+   <chunk>
+    <type>float</type>
+    <format>%.2f</format>
+    <node>/position/altitude-agl-ft</node>
+   </chunk>
+
+   <chunk>
+    <type>float</type>
+    <format>%.2f</format>
+    <node>/instrumentation/attitude-indicator/indicated-roll-deg</node>
+   </chunk>
+
+   <chunk>
+    <type>float</type>
+    <format>%.2f</format>
+    <node>/instrumentation/attitude-indicator/indicated-pitch-deg</node>
+   </chunk>
+
+   <chunk>
+    <type>float</type>
+    <format>%.2f</format>
+    <node>/instrumentation/attitude-indicator/horizon-offset-deg</node>
+   </chunk>
+
+   <chunk>
+    <type>float</type>
+    <format>%.4e</format>
+    <node>/instrumentation/attitude-indicator/spin</node>
+   </chunk>
+  </output>
+ </generic>
+</PropertyList>
+
+=====================================================================
diff --git a/utils/fgpanel/main.cxx b/utils/fgpanel/main.cxx
new file mode 100644
index 000000000..80215e94a
--- /dev/null
+++ b/utils/fgpanel/main.cxx
@@ -0,0 +1,30 @@
+//
+//  Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#include "FGPanelApplication.hxx"
+
+int main( int argc, char ** argv )
+{
+  try {
+    FGPanelApplication app(argc,argv);
+    app.Run();
+    return 0;
+  }
+  catch( ... ) {
+    cerr << "Sorry, your program terminated." << endl;
+  }
+}
diff --git a/utils/fgpanel/panel.cxx b/utils/fgpanel/panel.cxx
new file mode 100644
index 000000000..89044997f
--- /dev/null
+++ b/utils/fgpanel/panel.cxx
@@ -0,0 +1,962 @@
+//  panel.cxx - default, 2D single-engine prop instrument panel
+//
+//  Written by David Megginson, started January 2000.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+//  $Id: panel.cxx,v 1.44 2006/09/05 20:28:48 curt Exp $
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H          
+#  include <windows.h>
+#endif
+
+#include <stdio.h>	// sprintf
+#include <string.h>
+
+#include <simgear/compiler.h>
+
+#include <GL/glut.h>
+
+#include <plib/fnt.h>
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/sg_path.hxx>
+
+#include "panel.hxx"
+#include "ApplicationProperties.hxx"
+////////////////////////////////////////////////////////////////////////
+// Local functions.
+////////////////////////////////////////////////////////////////////////
+
+class FGDummyTextureLoader : public FGTextureLoaderInterface {
+public:
+  virtual GLuint loadTexture( const string & filename );
+};
+
+GLuint FGDummyTextureLoader::loadTexture( const string & filename )
+{
+  GLuint _texture = 0;
+  glGenTextures( 1, &_texture );
+  glBindTexture( GL_TEXTURE_2D, _texture );
+
+//  glTexEnvi       ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
+//  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ) ;
+//  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ) ;
+//  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ;
+//  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ;
+
+  GLubyte image[ 2 * 2 * 3 ] ;
+
+  /* Red and white chequerboard */
+  image [ 0 ] = 255 ; image [ 1 ] =  0  ; image [ 2 ] =  0  ;
+  image [ 3 ] = 255 ; image [ 4 ] = 255 ; image [ 5 ] = 255 ;
+  image [ 6 ] = 255 ; image [ 7 ] = 255 ; image [ 8 ] = 255 ;
+  image [ 9 ] = 255 ; image [ 10] =  0  ; image [ 11] =  0  ;
+
+  glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, 2, 2, 0,
+        GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image);
+
+  return _texture;
+}
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGCropped Texture.
+////////////////////////////////////////////////////////////////////////
+
+GLuint FGCroppedTexture::current_bound_texture = 0;
+map<string,GLuint> FGCroppedTexture::cache;
+map<string,FGTextureLoaderInterface*> FGCroppedTexture::textureLoader;
+static FGDummyTextureLoader dummyTextureLoader;
+
+FGCroppedTexture::FGCroppedTexture (const string &path,
+				    float minX, float minY,
+				    float maxX, float maxY)
+  : _path(path),
+    _minX(minX), _minY(minY), _maxX(maxX), _maxY(maxY), _texture(0)
+{
+}
+
+FGCroppedTexture::~FGCroppedTexture ()
+{
+}
+
+void FGCroppedTexture::bind( bool doGLBind )
+{
+  if( _texture == 0 ) {
+    SG_LOG( SG_COCKPIT, SG_DEBUG, "First bind of texture " << _path );
+    if( cache.count(_path) > 0 ) {
+      _texture = cache[_path];
+      SG_LOG( SG_COCKPIT, SG_DEBUG, "Using texture " << _path << " from cache (#" << _texture << ")" );
+    } else {
+      SGPath tpath = ApplicationProperties::GetRootPath(_path.c_str());
+      string extension = tpath.extension();
+      FGTextureLoaderInterface * loader = &dummyTextureLoader;
+      if( textureLoader.count( extension ) == 0 ) {
+        SG_LOG( SG_COCKPIT, SG_ALERT, "Can't handle textures of type " << extension );
+      } else {
+        loader = textureLoader[extension];
+      }
+
+      _texture = loader->loadTexture( tpath.c_str() );
+      SG_LOG( SG_COCKPIT, SG_DEBUG, "Texture " << tpath.c_str() << " loaded from file as #" << _texture );
+      
+      cache[_path] = _texture;
+    }
+  }
+
+  if( !doGLBind || current_bound_texture == _texture )
+    return;
+
+  glBindTexture( GL_TEXTURE_2D, _texture );
+  current_bound_texture = _texture;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGPanel.
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * Constructor.
+ */
+FGPanel::FGPanel ( SGPropertyNode_ptr root)
+  : _root(root),
+    _flipx(root->getNode("/sim/panel/flip-x", true)),
+    _rotate(root->getNode("/sim/panel/rotate-deg", true)),
+    _bg_width(1.0), _bg_height(1.0),
+    initDisplayList(0)
+{
+}
+
+
+/**
+ * Destructor.
+ */
+FGPanel::~FGPanel ()
+{
+  for (instrument_list_type::iterator it = _instruments.begin();
+       it != _instruments.end();
+       it++) {
+    delete *it;
+    *it = 0;
+  }
+}
+
+
+/**
+ * Add an instrument to the panel.
+ */
+void
+FGPanel::addInstrument (FGPanelInstrument * instrument)
+{
+  _instruments.push_back(instrument);
+}
+
+
+/**
+ * Initialize the panel.
+ */
+void
+FGPanel::init ()
+{
+}
+
+
+/**
+ * Bind panel properties.
+ */
+void
+FGPanel::bind ()
+{
+}
+
+
+/**
+ * Unbind panel properties.
+ */
+void
+FGPanel::unbind ()
+{
+}
+
+GLuint FGPanel::getInitDisplayList()
+{
+  if( initDisplayList != 0 ) return initDisplayList;
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  if ( _flipx->getBoolValue() ) {
+    gluOrtho2D( _width, 0, _height, 0 ); /* up side down */
+  } else {
+    gluOrtho2D( 0, _width, 0, _height ); /* right side up */
+  }
+
+  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+  
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  glClear( GL_COLOR_BUFFER_BIT);
+
+  // save some state
+  glPushAttrib( GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT
+                | GL_TEXTURE_BIT | GL_PIXEL_MODE_BIT | GL_CULL_FACE 
+                | GL_DEPTH_BUFFER_BIT );
+
+  // Draw the background
+  glEnable(GL_TEXTURE_2D);
+
+  glDisable(GL_LIGHTING);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_ALPHA_TEST);
+  glEnable(GL_COLOR_MATERIAL);
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_BACK);
+  glDisable(GL_DEPTH_TEST);
+
+  if (_bg != NULL) {
+    _bg->bind();
+//    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    glBegin(GL_QUADS);
+    glTexCoord2f(0.0, 0.0); glVertex2f(0, 0);
+    glTexCoord2f(_bg_width, 0.0); glVertex2f(_width, 0);
+    glTexCoord2f(_bg_width, _bg_height); glVertex2f(_width, _height);
+    glTexCoord2f(0.0, _bg_height); glVertex2f(0, _height);
+    glEnd();
+  } else if( _mbg[0] != NULL ) {
+    for (int i = 0; i < 4; i ++) {
+      // top row of textures...(1,3,5,7)
+      _mbg[i*2]->bind();
+//      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+      glBegin(GL_QUADS);
+      glTexCoord2f(0.0, 0.0); glVertex2f(i*_width/4,     _height/2);
+      glTexCoord2f(1.0, 0.0); glVertex2f((i+1)*_width/4, _height/2);
+      glTexCoord2f(1.0, 1.0); glVertex2f((i+1)*_width/4, _height);
+      glTexCoord2f(0.0, 1.0); glVertex2f(i*_width/4,     _height);
+      glEnd();
+      // bottom row of textures...(2,4,6,8)
+      _mbg[i*2+1]->bind();
+//      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+      glBegin(GL_QUADS);
+      glTexCoord2f(0.0, 0.0); glVertex2f( i*_width/4,     0);
+      glTexCoord2f(1.0, 0.0); glVertex2f( (i+1)*_width/4, 0);
+      glTexCoord2f(1.0, 1.0); glVertex2f( (i+1)*_width/4, _height/2);
+      glTexCoord2f(0.0, 1.0); glVertex2f( i*_width/4,     _height/2);
+      glEnd();
+    }
+  } else {
+    float c[4];
+    glGetFloatv( GL_CURRENT_COLOR, c );
+    glColor4f( 0.0, 0.0, 0.0, 1.0 );
+    glBegin(GL_QUADS);
+    glVertex2f(0, 0);
+    glVertex2f(_width, 0);
+    glVertex2f(_width, _height);
+    glVertex2f(0, _height);
+    glEnd();
+    glColor4fv( c );
+  }
+
+
+  return initDisplayList;  
+}
+
+void
+FGPanel::update (double dt)
+{
+  glCallList(getInitDisplayList());
+
+  // Draw the instruments.
+  // Syd Adams: added instrument clipping
+  instrument_list_type::const_iterator current = _instruments.begin();
+  instrument_list_type::const_iterator end = _instruments.end();
+
+  GLdouble blx[4]={1.0,0.0,0.0,0.0};
+  GLdouble bly[4]={0.0,1.0,0.0,0.0};
+  GLdouble urx[4]={-1.0,0.0,0.0,0.0};
+  GLdouble ury[4]={0.0,-1.0,0.0,0.0};
+
+  for ( ; current != end; current++) {
+    FGPanelInstrument * instr = *current;
+    glPushMatrix();
+    glTranslated(instr->getXPos(), instr->getYPos(), 0);
+
+    int ix= instr->getWidth();
+    int iy= instr->getHeight();
+    glPushMatrix();
+    glTranslated(-ix/2,-iy/2,0);
+    glClipPlane(GL_CLIP_PLANE0,blx);
+    glClipPlane(GL_CLIP_PLANE1,bly);
+    glEnable(GL_CLIP_PLANE0);
+    glEnable(GL_CLIP_PLANE1);
+
+    glTranslated(ix,iy,0);
+    glClipPlane(GL_CLIP_PLANE2,urx);
+    glClipPlane(GL_CLIP_PLANE3,ury);
+    glEnable(GL_CLIP_PLANE2);
+    glEnable(GL_CLIP_PLANE3);
+    glPopMatrix();
+    instr->draw();
+
+    glPopMatrix();
+  }
+
+  glDisable(GL_CLIP_PLANE0);
+  glDisable(GL_CLIP_PLANE1);
+  glDisable(GL_CLIP_PLANE2);
+  glDisable(GL_CLIP_PLANE3);
+
+  // restore some original state
+  glPopAttrib();
+}
+
+#if 0
+/**
+ * Update the panel.
+ */
+void
+FGPanel::update (double dt)
+{
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  if ( _flipx->getBoolValue() ) {
+    gluOrtho2D( _width, 0, _height, 0 ); /* up side down */
+  } else {
+    gluOrtho2D( 0, _width, 0, _height ); /* right side up */
+  }
+
+  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+  
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  
+  draw();
+}
+
+void FGPanel::draw()
+{
+  glClear( GL_COLOR_BUFFER_BIT);
+
+  // save some state
+  glPushAttrib( GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT
+                | GL_TEXTURE_BIT | GL_PIXEL_MODE_BIT | GL_CULL_FACE 
+                | GL_DEPTH_BUFFER_BIT );
+
+  // Draw the background
+  glEnable(GL_TEXTURE_2D);
+
+  glDisable(GL_LIGHTING);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_ALPHA_TEST);
+  glEnable(GL_COLOR_MATERIAL);
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_BACK);
+  glDisable(GL_DEPTH_TEST);
+
+  if (_bg != NULL) {
+    _bg->bind();
+//    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    glBegin(GL_QUADS);
+    glTexCoord2f(0.0, 0.0); glVertex2f(0, 0);
+    glTexCoord2f(_bg_width, 0.0); glVertex2f(_width, 0);
+    glTexCoord2f(_bg_width, _bg_height); glVertex2f(_width, _height);
+    glTexCoord2f(0.0, _bg_height); glVertex2f(0, _height);
+    glEnd();
+  } else if( _mbg[0] != NULL ) {
+    for (int i = 0; i < 4; i ++) {
+      // top row of textures...(1,3,5,7)
+      _mbg[i*2]->bind();
+//      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+      glBegin(GL_QUADS);
+      glTexCoord2f(0.0, 0.0); glVertex2f(i*_width/4,     _height/2);
+      glTexCoord2f(1.0, 0.0); glVertex2f((i+1)*_width/4, _height/2);
+      glTexCoord2f(1.0, 1.0); glVertex2f((i+1)*_width/4, _height);
+      glTexCoord2f(0.0, 1.0); glVertex2f(i*_width/4,     _height);
+      glEnd();
+      // bottom row of textures...(2,4,6,8)
+      _mbg[i*2+1]->bind();
+//      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+      glBegin(GL_QUADS);
+      glTexCoord2f(0.0, 0.0); glVertex2f( i*_width/4,     0);
+      glTexCoord2f(1.0, 0.0); glVertex2f( (i+1)*_width/4, 0);
+      glTexCoord2f(1.0, 1.0); glVertex2f( (i+1)*_width/4, _height/2);
+      glTexCoord2f(0.0, 1.0); glVertex2f( i*_width/4,     _height/2);
+      glEnd();
+    }
+  } else {
+    float c[4];
+    glGetFloatv( GL_CURRENT_COLOR, c );
+    glColor4f( 0.0, 0.0, 0.0, 1.0 );
+    glBegin(GL_QUADS);
+    glVertex2f(0, 0);
+    glVertex2f(_width, 0);
+    glVertex2f(_width, _height);
+    glVertex2f(0, _height);
+    glEnd();
+    glColor4fv( c );
+  }
+
+  // Draw the instruments.
+  // Syd Adams: added instrument clipping
+  instrument_list_type::const_iterator current = _instruments.begin();
+  instrument_list_type::const_iterator end = _instruments.end();
+
+  GLdouble blx[4]={1.0,0.0,0.0,0.0};
+  GLdouble bly[4]={0.0,1.0,0.0,0.0};
+  GLdouble urx[4]={-1.0,0.0,0.0,0.0};
+  GLdouble ury[4]={0.0,-1.0,0.0,0.0};
+
+  for ( ; current != end; current++) {
+    FGPanelInstrument * instr = *current;
+    glPushMatrix();
+    glTranslated(instr->getXPos(), instr->getYPos(), 0);
+
+    int ix= instr->getWidth();
+    int iy= instr->getHeight();
+    glPushMatrix();
+    glTranslated(-ix/2,-iy/2,0);
+    glClipPlane(GL_CLIP_PLANE0,blx);
+    glClipPlane(GL_CLIP_PLANE1,bly);
+    glEnable(GL_CLIP_PLANE0);
+    glEnable(GL_CLIP_PLANE1);
+
+    glTranslated(ix,iy,0);
+    glClipPlane(GL_CLIP_PLANE2,urx);
+    glClipPlane(GL_CLIP_PLANE3,ury);
+    glEnable(GL_CLIP_PLANE2);
+    glEnable(GL_CLIP_PLANE3);
+    glPopMatrix();
+    instr->draw();
+
+    glPopMatrix();
+  }
+
+  glDisable(GL_CLIP_PLANE0);
+  glDisable(GL_CLIP_PLANE1);
+  glDisable(GL_CLIP_PLANE2);
+  glDisable(GL_CLIP_PLANE3);
+
+  // restore some original state
+  glPopAttrib();
+}
+#endif
+
+/**
+ * Set the panel's background texture.
+ */
+void
+FGPanel::setBackground (FGCroppedTexture_ptr texture)
+{
+  _bg = texture;
+}
+
+/**
+ * Set the panel's multiple background textures.
+ */
+void
+FGPanel::setMultiBackground (FGCroppedTexture_ptr texture, int idx)
+{
+  _bg = 0;
+  _mbg[idx] = texture;
+}
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGPanelTransformation.
+////////////////////////////////////////////////////////////////////////
+
+FGPanelTransformation::FGPanelTransformation ()
+  : table(0)
+{
+}
+
+FGPanelTransformation::~FGPanelTransformation ()
+{
+  delete table;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGPanelInstrument.
+////////////////////////////////////////////////////////////////////////
+
+
+FGPanelInstrument::FGPanelInstrument ()
+{
+  setPosition(0, 0);
+  setSize(0, 0);
+}
+
+FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
+{
+  setPosition(x, y);
+  setSize(w, h);
+}
+
+FGPanelInstrument::~FGPanelInstrument ()
+{
+}
+
+void
+FGPanelInstrument::setPosition (int x, int y)
+{
+  _x = x;
+  _y = y;
+}
+
+void
+FGPanelInstrument::setSize (int w, int h)
+{
+  _w = w;
+  _h = h;
+}
+
+int
+FGPanelInstrument::getXPos () const
+{
+  return _x;
+}
+
+int
+FGPanelInstrument::getYPos () const
+{
+  return _y;
+}
+
+int
+FGPanelInstrument::getWidth () const
+{
+  return _w;
+}
+
+int
+FGPanelInstrument::getHeight () const
+{
+  return _h;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGLayeredInstrument.
+////////////////////////////////////////////////////////////////////////
+
+FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
+  : FGPanelInstrument(x, y, w, h)
+{
+}
+
+FGLayeredInstrument::~FGLayeredInstrument ()
+{
+  for (layer_list::iterator it = _layers.begin(); it != _layers.end(); it++) {
+    delete *it;
+    *it = 0;
+  }
+}
+
+void
+FGLayeredInstrument::draw ()
+{
+  if (!test())
+    return;
+  
+  for (int i = 0; i < (int)_layers.size(); i++) {
+    glPushMatrix();
+    _layers[i]->draw();
+    glPopMatrix();
+  }
+}
+
+int
+FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
+{
+  int n = _layers.size();
+  if (layer->getWidth() == -1) {
+    layer->setWidth(getWidth());
+  }
+  if (layer->getHeight() == -1) {
+    layer->setHeight(getHeight());
+  }
+  _layers.push_back(layer);
+  return n;
+}
+
+int
+FGLayeredInstrument::addLayer (FGCroppedTexture_ptr texture, int w, int h)
+{
+  return addLayer(new FGTexturedLayer(texture, w, h));
+}
+
+void
+FGLayeredInstrument::addTransformation (FGPanelTransformation * transformation)
+{
+  int layer = _layers.size() - 1;
+  _layers[layer]->addTransformation(transformation);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGInstrumentLayer.
+////////////////////////////////////////////////////////////////////////
+
+FGInstrumentLayer::FGInstrumentLayer (int w, int h)
+  : _w(w),
+    _h(h)
+{
+}
+
+FGInstrumentLayer::~FGInstrumentLayer ()
+{
+  for (transformation_list::iterator it = _transformations.begin();
+       it != _transformations.end();
+       it++) {
+    delete *it;
+    *it = 0;
+  }
+}
+
+void
+FGInstrumentLayer::transform () const
+{
+  transformation_list::const_iterator it = _transformations.begin();
+  transformation_list::const_iterator last = _transformations.end();
+  while (it != last) {
+    FGPanelTransformation *t = *it;
+    if (t->test()) {
+      float val = (t->node == 0 ? 0.0 : t->node->getFloatValue());
+
+      if (t->has_mod)
+          val = fmod(val, t->mod);
+      if (val < t->min) {
+	val = t->min;
+      } else if (val > t->max) {
+	val = t->max;
+      }
+
+      if (t->table==0) {
+	val = val * t->factor + t->offset;
+      } else {
+	val = t->table->interpolate(val) * t->factor + t->offset;
+     }
+      
+      switch (t->type) {
+      case FGPanelTransformation::XSHIFT:
+	glTranslatef(val, 0.0, 0.0);
+	break;
+      case FGPanelTransformation::YSHIFT:
+	glTranslatef(0.0, val, 0.0);
+	break;
+      case FGPanelTransformation::ROTATION:
+	glRotatef(-val, 0.0, 0.0, 1.0);
+	break;
+      }
+    }
+    it++;
+  }
+}
+
+void
+FGInstrumentLayer::addTransformation (FGPanelTransformation * transformation)
+{
+  _transformations.push_back(transformation);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGGroupLayer.
+////////////////////////////////////////////////////////////////////////
+
+FGGroupLayer::FGGroupLayer ()
+{
+}
+
+FGGroupLayer::~FGGroupLayer ()
+{
+  for (unsigned int i = 0; i < _layers.size(); i++)
+    delete _layers[i];
+}
+
+void
+FGGroupLayer::draw ()
+{
+  if (test()) {
+    transform();
+    int nLayers = _layers.size();
+    for (int i = 0; i < nLayers; i++)
+      _layers[i]->draw( );
+  }
+}
+
+void
+FGGroupLayer::addLayer (FGInstrumentLayer * layer)
+{
+  _layers.push_back(layer);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGTexturedLayer.
+////////////////////////////////////////////////////////////////////////
+
+
+FGTexturedLayer::FGTexturedLayer (FGCroppedTexture_ptr texture, int w, int h)
+  : FGInstrumentLayer(w, h),
+    _emissive(false),
+    displayList(0)
+{
+  setTexture(texture);
+}
+
+
+FGTexturedLayer::~FGTexturedLayer ()
+{
+}
+
+GLuint
+FGTexturedLayer::getDisplayList()
+{
+  if( displayList != 0 )
+    return displayList;
+
+  int w2 = _w / 2;
+  int h2 = _h / 2;
+
+  _texture->bind( false );
+  displayList = glGenLists(1);
+  glNewList(displayList,GL_COMPILE_AND_EXECUTE);
+    glBindTexture( GL_TEXTURE_2D, _texture->getTexture() );
+    glBegin(GL_QUADS);
+      glTexCoord2f(_texture->getMinX(), _texture->getMinY()); glVertex2f(-w2, -h2);
+      glTexCoord2f(_texture->getMaxX(), _texture->getMinY()); glVertex2f(w2, -h2);
+      glTexCoord2f(_texture->getMaxX(), _texture->getMaxY()); glVertex2f(w2, h2);
+      glTexCoord2f(_texture->getMinX(), _texture->getMaxY()); glVertex2f(-w2, h2);
+    glEnd();
+  glEndList();
+
+  return displayList;
+}
+
+void
+FGTexturedLayer::draw ( )
+{
+  if (test()) {
+    transform();
+    glCallList(getDisplayList());
+  }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGTextLayer.
+////////////////////////////////////////////////////////////////////////
+
+fntRenderer FGTextLayer::text_renderer;
+
+FGTextLayer::FGTextLayer (int w, int h)
+  : FGInstrumentLayer(w, h), _pointSize(14.0), _font_name("Helvetica.txf")
+{
+  _then.stamp();
+  _color[0] = _color[1] = _color[2] = 0.0;
+  _color[3] = 1.0;
+}
+
+FGTextLayer::~FGTextLayer ()
+{
+  chunk_list::iterator it = _chunks.begin();
+  chunk_list::iterator last = _chunks.end();
+  for ( ; it != last; it++) {
+    delete *it;
+  }
+}
+
+void
+FGTextLayer::draw ()
+{
+  if (test()) {
+    float c[4];
+    glGetFloatv( GL_CURRENT_COLOR, c );
+    glColor4fv(_color);
+    transform();
+
+    text_renderer.setFont(ApplicationProperties::fontCache.getTexFont(_font_name.c_str()));
+
+    text_renderer.setPointSize(_pointSize);
+    text_renderer.begin();
+    text_renderer.start3f(0, 0, 0);
+
+    _now.stamp();
+    long diff = (_now - _then).toUSecs();
+
+    if (diff > 100000 || diff < 0 ) {
+      // ( diff < 0 ) is a sanity check and indicates our time stamp
+      // difference math probably overflowed.  We can handle a max
+      // difference of 35.8 minutes since the returned value is in
+      // usec.  So if the panel is left off longer than that we can
+      // over flow the math with it is turned back on.  This (diff <
+      // 0) catches that situation, get's us out of trouble, and
+      // back on track.
+      recalc_value();
+      _then = _now;
+    }
+
+    // Something is goofy.  The code in this file renders only CCW
+    // polygons, and I have verified that the font code in plib
+    // renders only CCW trianbles.  Yet they come out backwards.
+    // Something around here or in plib is either changing the winding
+    // order or (more likely) pushing a left-handed matrix onto the
+    // stack.  But I can't find it; get out the chainsaw...
+    glFrontFace(GL_CW);
+    text_renderer.puts((char *)(_value.c_str()));
+    glFrontFace(GL_CCW);
+
+    text_renderer.end();
+    glColor4fv( c );
+  }
+}
+
+void
+FGTextLayer::addChunk (FGTextLayer::Chunk * chunk)
+{
+  _chunks.push_back(chunk);
+}
+
+void
+FGTextLayer::setColor (float r, float g, float b)
+{
+  _color[0] = r;
+  _color[1] = g;
+  _color[2] = b;
+  _color[3] = 1.0;
+}
+
+void
+FGTextLayer::setPointSize (float size)
+{
+  _pointSize = size;
+}
+
+void
+FGTextLayer::setFontName(const string &name)
+{
+  _font_name = name + ".txf";
+}
+
+
+void
+FGTextLayer::setFont(fntFont * font)
+{
+  FGTextLayer::text_renderer.setFont(font);
+}
+
+
+void
+FGTextLayer::recalc_value () const
+{
+  _value = "";
+  chunk_list::const_iterator it = _chunks.begin();
+  chunk_list::const_iterator last = _chunks.end();
+  for ( ; it != last; it++) {
+    _value += (*it)->getValue();
+  }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGTextLayer::Chunk.
+////////////////////////////////////////////////////////////////////////
+
+FGTextLayer::Chunk::Chunk (const string &text, const string &fmt)
+  : _type(FGTextLayer::TEXT), _fmt(fmt)
+{
+  _text = text;
+  if (_fmt.empty()) 
+    _fmt = "%s";
+}
+
+FGTextLayer::Chunk::Chunk (ChunkType type, const SGPropertyNode * node,
+			   const string &fmt, float mult, float offs,
+                           bool truncation)
+  : _type(type), _fmt(fmt), _mult(mult), _offs(offs), _trunc(truncation)
+{
+  if (_fmt.empty()) {
+    if (type == TEXT_VALUE)
+      _fmt = "%s";
+    else
+      _fmt = "%.2f";
+  }
+  _node = node;
+}
+
+const char *
+FGTextLayer::Chunk::getValue () const
+{
+  if (test()) {
+    _buf[0] = '\0';
+    switch (_type) {
+    case TEXT:
+      sprintf(_buf, _fmt.c_str(), _text.c_str());
+      return _buf;
+    case TEXT_VALUE:
+      sprintf(_buf, _fmt.c_str(), _node->getStringValue());
+      break;
+    case DOUBLE_VALUE:
+      double d = _offs + _node->getFloatValue() * _mult;
+      if (_trunc)  d = (d < 0) ? -floor(-d) : floor(d);
+      sprintf(_buf, _fmt.c_str(), d);
+      break;
+    }
+    return _buf;
+  } else {
+    return "";
+  }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGSwitchLayer.
+////////////////////////////////////////////////////////////////////////
+
+FGSwitchLayer::FGSwitchLayer ()
+  : FGGroupLayer()
+{
+}
+
+void
+FGSwitchLayer::draw ()
+{
+  if (test()) {
+    transform();
+    int nLayers = _layers.size();
+    for (int i = 0; i < nLayers; i++) {
+      if (_layers[i]->test()) {
+          _layers[i]->draw();
+          return;
+      }
+    }
+  }
+}
+
+
+// end of panel.cxx
diff --git a/utils/fgpanel/panel.hxx b/utils/fgpanel/panel.hxx
new file mode 100644
index 000000000..44ce96a05
--- /dev/null
+++ b/utils/fgpanel/panel.hxx
@@ -0,0 +1,451 @@
+//  panel.hxx - generic support classes for a 2D panel.
+//
+//  Written by David Megginson, started January 2000.
+//  Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+//  $Id$
+
+#ifndef __PANEL_HXX
+#define __PANEL_HXX
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <plib/fnt.h>
+
+#include <simgear/props/condition.hxx>
+#include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/math/interpolater.hxx>
+#include <simgear/sg_inlines.h>
+#include "FGTextureLoaderInterface.hxx"
+
+class FGPanelInstrument;
+
+
+////////////////////////////////////////////////////////////////////////
+// Texture management.
+////////////////////////////////////////////////////////////////////////
+
+class FGCroppedTexture;
+typedef SGSharedPtr<FGCroppedTexture> FGCroppedTexture_ptr;
+/**
+ * Cropped texture (should migrate out into FGFS).
+ *
+ * This structure wraps an SSG texture with cropping information.
+ */
+class FGCroppedTexture : public SGReferenced
+{
+public:
+  FGCroppedTexture (const string &path,
+		  float _minX = 0.0, float _minY = 0.0,
+		  float _maxX = 1.0, float _maxY = 1.0);
+
+  virtual ~FGCroppedTexture ();
+
+  virtual void setPath (const string &path) { _path = path; }
+
+  virtual const string &getPath () const { return _path; }
+
+  virtual void setCrop (float minX, float minY, float maxX, float maxY) {
+    _minX = minX; _minY = minY; _maxX = maxX; _maxY = maxY;
+  }
+
+  static void registerTextureLoader( const string & extension, FGTextureLoaderInterface * loader ) {
+    if( textureLoader.count( extension ) == 0 )
+      textureLoader[extension] = loader;
+  }
+
+  virtual float getMinX () const { return _minX; }
+  virtual float getMinY () const { return _minY; }
+  virtual float getMaxX () const { return _maxX; }
+  virtual float getMaxY () const { return _maxY; }
+  GLuint getTexture() const { return _texture; }
+
+  virtual void bind( bool doGLBind = true );
+
+private:
+  string _path;
+  float _minX, _minY, _maxX, _maxY;
+
+  GLuint _texture;
+  static GLuint current_bound_texture;
+  static map<string,GLuint> cache;
+  static map<string,FGTextureLoaderInterface*> textureLoader;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Top-level panel.
+////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Instrument panel class.
+ *
+ * The panel is a container that has a background texture and holds
+ * zero or more instruments.  The panel will order the instruments to
+ * redraw themselves when necessary, and will pass mouse clicks on to
+ * the appropriate instruments for processing.
+ */
+class FGPanel : public SGSubsystem
+{
+public:
+
+  FGPanel ( SGPropertyNode_ptr root );
+  virtual ~FGPanel ();
+
+				// Update the panel (every frame).
+  virtual void init ();
+  virtual void bind ();
+  virtual void unbind ();
+//  virtual void draw ();
+  virtual void update (double dt);
+
+				// transfer pointer ownership!!!
+  virtual void addInstrument (FGPanelInstrument * instrument);
+
+				// Background texture.
+  virtual void setBackground (FGCroppedTexture_ptr texture);
+  inline void setBackgroundWidth( double d ) {
+    _bg_width = d;
+  }
+
+  inline void setBackgroundHeight( double d ) {
+    _bg_height = d;
+  }
+
+				// Background multiple textures.
+  virtual void setMultiBackground (FGCroppedTexture_ptr texture , int idx);
+
+				// Full width of panel.
+  virtual void setWidth (int width) { _width = width; }
+  virtual int getWidth () const { return _width; }
+
+				// Full height of panel.
+  virtual void setHeight (int height) { _height = height; }
+  virtual int getHeight () const { return _height; }
+
+private:
+
+  typedef vector<FGPanelInstrument *> instrument_list_type;
+  int _width;
+  int _height;
+
+  SGPropertyNode_ptr _root;
+  SGPropertyNode_ptr _flipx;
+  SGPropertyNode_ptr _rotate;
+
+  FGCroppedTexture_ptr _bg;
+  double _bg_width;
+  double _bg_height;
+  FGCroppedTexture_ptr _mbg[8];
+				// List of instruments in panel.
+  instrument_list_type _instruments;
+
+  GLuint initDisplayList;
+
+  GLuint getInitDisplayList();
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Transformations.
+////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * A transformation for a layer.
+ */
+class FGPanelTransformation : public SGConditional
+{
+public:
+
+  enum Type {
+    XSHIFT,
+    YSHIFT,
+    ROTATION
+  };
+
+  FGPanelTransformation ();
+  virtual ~FGPanelTransformation ();
+
+  Type type;
+  SGConstPropertyNode_ptr node;
+  float min;
+  float max;
+  bool has_mod;
+  float mod;
+  float factor;
+  float offset;
+  SGInterpTable * table;
+};
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Layers
+////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * A single layer of a multi-layered instrument.
+ *
+ * Each layer can be subject to a series of transformations based
+ * on current FGFS instrument readings: for example, a texture
+ * representing a needle can rotate to show the airspeed.
+ */
+class FGInstrumentLayer : public SGConditional
+{
+public:
+
+  FGInstrumentLayer (int w = -1, int h = -1);
+  virtual ~FGInstrumentLayer ();
+
+  virtual void draw () = 0;
+  virtual void transform () const;
+
+  virtual int getWidth () const { return _w; }
+  virtual int getHeight () const { return _h; }
+  virtual void setWidth (int w) { _w = w; }
+  virtual void setHeight (int h) { _h = h; }
+
+				// Transfer pointer ownership!!
+				// DEPRECATED
+  virtual void addTransformation (FGPanelTransformation * transformation);
+
+protected:
+  int _w, _h;
+
+  typedef vector<FGPanelTransformation *> transformation_list;
+  transformation_list _transformations;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Instruments.
+////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Abstract base class for a panel instrument.
+ *
+ * A panel instrument consists of zero or more actions, associated
+ * with mouse clicks in rectangular areas.  Currently, the only
+ * concrete class derived from this is FGLayeredInstrument, but others
+ * may show up in the future (some complex instruments could be 
+ * entirely hand-coded, for example).
+ */
+class FGPanelInstrument : public SGConditional
+{
+public:
+  FGPanelInstrument ();
+  FGPanelInstrument (int x, int y, int w, int h);
+  virtual ~FGPanelInstrument ();
+
+  virtual void draw () = 0;
+
+  virtual void setPosition(int x, int y);
+  virtual void setSize(int w, int h);
+
+  virtual int getXPos () const;
+  virtual int getYPos () const;
+  virtual int getWidth () const;
+  virtual int getHeight () const;
+
+protected:
+  int _x, _y, _w, _h;
+};
+
+
+/**
+ * An instrument constructed of multiple layers.
+ *
+ * Each individual layer can be rotated or shifted to correspond
+ * to internal FGFS instrument readings.
+ */
+class FGLayeredInstrument : public FGPanelInstrument
+{
+public:
+  FGLayeredInstrument (int x, int y, int w, int h);
+  virtual ~FGLayeredInstrument ();
+
+  virtual void draw ();
+
+				// Transfer pointer ownership!!
+  virtual int addLayer (FGInstrumentLayer *layer);
+  virtual int addLayer (FGCroppedTexture_ptr texture, int w = -1, int h = -1);
+
+				// Transfer pointer ownership!!
+  virtual void addTransformation (FGPanelTransformation * transformation);
+
+protected:
+  typedef vector<FGInstrumentLayer *> layer_list;
+  layer_list _layers;
+};
+
+
+/**
+ * An instrument layer containing a group of sublayers.
+ *
+ * This class is useful for gathering together a group of related
+ * layers, either to hold in an external file or to work under
+ * the same condition.
+ */
+class FGGroupLayer : public FGInstrumentLayer
+{
+public:
+  FGGroupLayer ();
+  virtual ~FGGroupLayer ();
+  virtual void draw ();
+				// transfer pointer ownership
+  virtual void addLayer (FGInstrumentLayer * layer);
+protected:
+  vector<FGInstrumentLayer *> _layers;
+};
+
+
+/**
+ * A textured layer of an instrument.
+ *
+ * This is a layer holding a single texture.  Normally, the texture's
+ * backgound should be transparent so that lower layers and the panel
+ * background can show through.
+ */
+class FGTexturedLayer : public FGInstrumentLayer
+{
+public:
+  FGTexturedLayer (int w = -1, int h = -1) : FGInstrumentLayer(w, h) {}
+  FGTexturedLayer (FGCroppedTexture_ptr texture, int w = -1, int h = -1);
+  virtual ~FGTexturedLayer ();
+
+  virtual void draw ();
+
+  virtual void setTexture (FGCroppedTexture_ptr texture) {
+    _texture = texture;
+  }
+  FGCroppedTexture_ptr getTexture() { return _texture; }
+
+  void setEmissive(bool e) { _emissive = e; }
+
+private:
+  GLuint getDisplayList();
+
+  FGCroppedTexture_ptr _texture;
+  bool _emissive;
+  GLuint displayList;
+};
+
+
+/**
+ * A text layer of an instrument.
+ *
+ * This is a layer holding a string of static and/or generated text.
+ * It is useful for instruments that have text displays, such as
+ * a chronometer, GPS, or NavCom radio.
+ */
+class FGTextLayer : public FGInstrumentLayer
+{
+public:
+  enum ChunkType {
+    TEXT,
+    TEXT_VALUE,
+    DOUBLE_VALUE
+  };
+
+  class Chunk : public SGConditional
+  {
+  public:
+    Chunk (const string &text, const string &fmt = "%s");
+    Chunk (ChunkType type, const SGPropertyNode * node,
+	   const string &fmt = "", float mult = 1.0, float offs = 0.0,
+           bool truncation = false);
+
+    const char * getValue () const;
+  private:
+    ChunkType _type;
+    string _text;
+    SGConstPropertyNode_ptr _node;
+    string _fmt;
+    float _mult;
+    float _offs;
+    bool _trunc;
+    mutable char _buf[1024];
+    
+  };
+
+  FGTextLayer (int w = -1, int h = -1);
+  virtual ~FGTextLayer ();
+
+  virtual void draw ();
+
+				// Transfer pointer!!
+  virtual void addChunk (Chunk * chunk);
+  virtual void setColor (float r, float g, float b);
+  virtual void setPointSize (float size);
+  virtual void setFontName ( const string &name );
+  virtual void setFont (fntFont * font);
+
+private:
+
+  void recalc_value () const;
+
+  typedef vector<Chunk *> chunk_list;
+  chunk_list _chunks;
+  float _color[4];
+
+  float _pointSize;
+  mutable string _font_name;
+  mutable string _value;
+  mutable SGTimeStamp _then;
+  mutable SGTimeStamp _now;
+
+  static fntRenderer text_renderer;
+};
+
+
+/**
+ * A group layer that switches among its children.
+ *
+ * The first layer that passes its condition will be drawn, and
+ * any following layers will be ignored.
+ */
+class FGSwitchLayer : public FGGroupLayer
+{
+public:
+				// Transfer pointers!!
+  FGSwitchLayer ();
+  virtual void draw ();
+
+};
+
+
+#endif // __PANEL_HXX
+
+// end of panel.hxx
+
+
+
diff --git a/utils/fgpanel/panel_io.cxx b/utils/fgpanel/panel_io.cxx
new file mode 100644
index 000000000..9f5084cd3
--- /dev/null
+++ b/utils/fgpanel/panel_io.cxx
@@ -0,0 +1,591 @@
+//  panel_io.cxx - I/O for 2D panel.
+//
+//  Written by David Megginson, started January 2000.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+//  $Id: panel_io.cxx,v 1.26 2006/08/10 11:12:39 mfranz Exp $
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#  include <windows.h>
+#endif
+
+#include <string.h>		// for strcmp()
+
+#include <simgear/compiler.h>
+#include <simgear/structure/exception.hxx>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props.hxx>
+#include <simgear/props/condition.hxx>
+
+#include "panel.hxx"
+#include "panel_io.hxx"
+#include "ApplicationProperties.hxx"
+
+
+////////////////////////////////////////////////////////////////////////
+// Read and construct a panel.
+//
+// The panel is specified as a regular property list, and each of the
+// instruments is its own, separate property list (and thus, a separate
+// XML document).  The functions in this section read in the files
+// as property lists, then extract properties to set up the panel
+// itself.
+//
+// A panel contains zero or more instruments.
+//
+// An instrument contains one or more layers and zero or more actions.
+//
+// A layer contains zero or more transformations.
+//
+// Some special types of layers also contain other objects, such as 
+// chunks of text or other layers.
+//
+// There are currently four types of layers:
+//
+// 1. Textured Layer (type="texture"), the default
+// 2. Text Layer (type="text")
+// 3. Switch Layer (type="switch")
+// 4. Built-in Layer (type="built-in", must also specify class)
+//
+// The only built-in layer so far is the ribbon for the magnetic compass
+// (class="compass-ribbon").
+//
+// There are three types of actions:
+//
+// 1. Adjust (type="adjust"), the default
+// 2. Swap (type="swap")
+// 3. Toggle (type="toggle")
+//
+// There are three types of transformations:
+//
+// 1. X shift (type="x-shift"), the default
+// 2. Y shift (type="y-shift")
+// 3. Rotation (type="rotation")
+//
+// Each of these may be associated with a property, so that a needle
+// will rotate with the airspeed, for example, or may have a fixed
+// floating-point value.
+////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Read a cropped texture from the instrument's property list.
+ *
+ * The x1 and y1 properties give the starting position of the texture
+ * (between 0.0 and 1.0), and the the x2 and y2 properties give the
+ * ending position.  For example, to use the bottom-left quarter of a
+ * texture, x1=0.0, y1=0.0, x2=0.5, y2=0.5.
+ */
+static FGCroppedTexture_ptr
+readTexture (const SGPropertyNode * node)
+{
+    return new FGCroppedTexture(node->getStringValue("path"),
+			     node->getFloatValue("x1"),
+			     node->getFloatValue("y1"),
+			     node->getFloatValue("x2", 1.0),
+			     node->getFloatValue("y2", 1.0));
+    SG_LOG(SG_COCKPIT, SG_DEBUG, "Read texture " << node->getName());
+}
+
+/**
+ * Test for a condition in the current node.
+ */
+
+////////////////////////////////////////////////////////////////////////
+// Read a condition and use it if necessary.
+////////////////////////////////////////////////////////////////////////
+
+static void
+readConditions (SGConditional *component, const SGPropertyNode *node)
+{
+  const SGPropertyNode * conditionNode = node->getChild("condition");
+  if (conditionNode != 0)
+				// The top level is implicitly AND
+    component->setCondition(sgReadCondition(ApplicationProperties::Properties,
+                                            conditionNode) );
+  ;
+}
+
+
+/**
+ * Read a transformation from the instrument's property list.
+ *
+ * The panel module uses the transformations to slide or spin needles,
+ * knobs, and other indicators, and to place layers in the correct
+ * positions.  Every layer starts centered exactly on the x,y co-ordinate,
+ * and many layers need to be moved or rotated simply to display the
+ * instrument correctly.
+ *
+ * There are three types of transformations:
+ *
+ * "x-shift" - move the layer horizontally.
+ *
+ * "y-shift" - move the layer vertically.
+ *
+ * "rotation" - rotate the layer.
+ *
+ * Each transformation may have a fixed offset, and may also have
+ * a floating-point property value to add to the offset.  The
+ * floating-point property may be clamped to a minimum and/or
+ * maximum range and scaled (after clamping).
+ *
+ * Note that because of the way OpenGL works, transformations will
+ * appear to be applied backwards.
+ */
+static FGPanelTransformation *
+readTransformation (const SGPropertyNode * node, float w_scale, float h_scale)
+{
+  FGPanelTransformation * t = new FGPanelTransformation;
+
+  string name = node->getName();
+  string type = node->getStringValue("type");
+  string propName = node->getStringValue("property", "");
+  const SGPropertyNode * target = 0;
+
+  if (type.empty()) {
+    SG_LOG( SG_COCKPIT, SG_INFO,
+            "No type supplied for transformation " << name
+            << " assuming \"rotation\"" );
+    type = "rotation";
+  }
+
+  if (!propName.empty())
+    target = ApplicationProperties::Properties->getNode(propName.c_str(), true);
+
+  t->node = target;
+  t->min = node->getFloatValue("min", -9999999);
+  t->max = node->getFloatValue("max", 99999999);
+  t->has_mod = node->hasChild("modulator");
+  if (t->has_mod)
+      t->mod = node->getFloatValue("modulator");
+  t->factor = node->getFloatValue("scale", 1.0);
+  t->offset = node->getFloatValue("offset", 0.0);
+
+
+				// Check for an interpolation table
+  const SGPropertyNode * trans_table = node->getNode("interpolation");
+  if (trans_table != 0) {
+    SG_LOG( SG_COCKPIT, SG_INFO, "Found interpolation table with "
+            << trans_table->nChildren() << " children" );
+    t->table = new SGInterpTable();
+    for (int i = 0; i < trans_table->nChildren(); i++) {
+      const SGPropertyNode * node = trans_table->getChild(i);
+      if (!strcmp(node->getName(), "entry")) {
+	double ind = node->getDoubleValue("ind", 0.0);
+	double dep = node->getDoubleValue("dep", 0.0);
+	SG_LOG( SG_COCKPIT, SG_INFO, "Adding interpolation entry "
+                << ind << "==>" << dep );
+	t->table->addEntry(ind, dep);
+      } else {
+	SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
+                << " in interpolation" );
+      }
+    }
+  } else {
+    t->table = 0;
+  }
+  
+				// Move the layer horizontally.
+  if (type == "x-shift") {
+    t->type = FGPanelTransformation::XSHIFT;
+//     t->min *= w_scale; //removed by Martin Dressler
+//     t->max *= w_scale; //removed by Martin Dressler
+    t->offset *= w_scale;
+    t->factor *= w_scale; //Added by Martin Dressler
+  } 
+
+				// Move the layer vertically.
+  else if (type == "y-shift") {
+    t->type = FGPanelTransformation::YSHIFT;
+    //t->min *= h_scale; //removed
+    //t->max *= h_scale; //removed
+    t->offset *= h_scale;
+    t->factor *= h_scale; //Added
+  } 
+
+				// Rotate the layer.  The rotation
+				// is in degrees, and does not need
+				// to scale with the instrument size.
+  else if (type == "rotation") {
+    t->type = FGPanelTransformation::ROTATION;
+  } 
+
+  else {
+    SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized transformation type " << type );
+    delete t;
+    return 0;
+  }
+
+  readConditions(t, node);
+  SG_LOG( SG_COCKPIT, SG_DEBUG, "Read transformation " << name );
+  return t;
+}
+
+
+/**
+ * Read a chunk of text from the instrument's property list.
+ *
+ * A text layer consists of one or more chunks of text.  All chunks
+ * share the same font size and color (and eventually, font), but
+ * each can come from a different source.  There are three types of
+ * text chunks:
+ *
+ * "literal" - a literal text string (the default)
+ *
+ * "text-value" - the current value of a string property
+ *
+ * "number-value" - the current value of a floating-point property.
+ *
+ * All three may also include a printf-style format string.
+ */
+FGTextLayer::Chunk *
+readTextChunk (const SGPropertyNode * node)
+{
+  FGTextLayer::Chunk * chunk;
+  string name = node->getStringValue("name");
+  string type = node->getStringValue("type");
+  string format = node->getStringValue("format");
+
+				// Default to literal text.
+  if (type.empty()) {
+    SG_LOG( SG_COCKPIT, SG_INFO, "No type provided for text chunk " << name
+            << " assuming \"literal\"");
+    type = "literal";
+  }
+
+				// A literal text string.
+  if (type == "literal") {
+    string text = node->getStringValue("text");
+    chunk = new FGTextLayer::Chunk(text, format);
+  }
+
+				// The value of a string property.
+  else if (type == "text-value") {
+    SGPropertyNode * target =
+      ApplicationProperties::Properties->getNode( node->getStringValue("property"), true);
+    chunk = new FGTextLayer::Chunk(FGTextLayer::TEXT_VALUE, target, format);
+  }
+
+				// The value of a float property.
+  else if (type == "number-value") {
+    string propName = node->getStringValue("property");
+    float scale = node->getFloatValue("scale", 1.0);
+    float offset = node->getFloatValue("offset", 0.0);
+    bool truncation = node->getBoolValue("truncate", false);
+    SGPropertyNode * target = ApplicationProperties::Properties->getNode(propName.c_str(), true);
+    chunk = new FGTextLayer::Chunk(FGTextLayer::DOUBLE_VALUE, target,
+				   format, scale, offset, truncation);
+  }
+
+				// Unknown type.
+  else {
+    SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized type " << type
+            << " for text chunk " << name );
+    return 0;
+  }
+
+  readConditions(chunk, node);
+  return chunk;
+}
+
+
+/**
+ * Read a single layer from an instrument's property list.
+ *
+ * Each instrument consists of one or more layers stacked on top
+ * of each other; the lower layers show through only where the upper
+ * layers contain an alpha component.  Each layer can be moved
+ * horizontally and vertically and rotated using transformations.
+ *
+ * This module currently recognizes four kinds of layers:
+ *
+ * "texture" - a layer containing a texture (the default)
+ *
+ * "text" - a layer containing text
+ *
+ * "switch" - a layer that switches between two other layers
+ *   based on the current value of a boolean property.
+ *
+ * "built-in" - a hard-coded layer supported by C++ code in FlightGear.
+ *
+ * Currently, the only built-in layer class is "compass-ribbon".
+ */
+static FGInstrumentLayer *
+readLayer (const SGPropertyNode * node, float w_scale, float h_scale)
+{
+  FGInstrumentLayer * layer = NULL;
+  string name = node->getStringValue("name");
+  string type = node->getStringValue("type");
+  int w = node->getIntValue("w", -1);
+  int h = node->getIntValue("h", -1);
+  bool emissive = node->getBoolValue("emissive", false);
+  if (w != -1)
+    w = int(w * w_scale);
+  if (h != -1)
+    h = int(h * h_scale);
+
+
+  if (type.empty()) {
+    SG_LOG( SG_COCKPIT, SG_INFO,
+            "No type supplied for layer " << name
+            << " assuming \"texture\"" );
+    type = "texture";
+  }
+
+
+				// A textured instrument layer.
+  if (type == "texture") {
+    FGCroppedTexture_ptr texture = readTexture(node->getNode("texture"));
+    layer = new FGTexturedLayer(texture, w, h);
+    if (emissive) {
+      FGTexturedLayer *tl=(FGTexturedLayer*)layer;
+      tl->setEmissive(true);
+    }
+
+  }
+				// A group of sublayers.
+  else if (type == "group") {
+    layer = new FGGroupLayer();
+    for (int i = 0; i < node->nChildren(); i++) {
+      const SGPropertyNode * child = node->getChild(i);
+      if (!strcmp(child->getName(), "layer"))
+	((FGGroupLayer *)layer)->addLayer(readLayer(child, w_scale, h_scale));
+    }
+  }
+
+
+				// A textual instrument layer.
+  else if (type == "text") {
+    FGTextLayer * tlayer = new FGTextLayer(w, h); // FIXME
+
+				// Set the text color.
+    float red = node->getFloatValue("color/red", 0.0);
+    float green = node->getFloatValue("color/green", 0.0);
+    float blue = node->getFloatValue("color/blue", 0.0);
+    tlayer->setColor(red, green, blue);
+
+				// Set the point size.
+    float pointSize = node->getFloatValue("point-size", 10.0) * w_scale;
+    tlayer->setPointSize(pointSize);
+
+				// Set the font.
+    string fontName = node->getStringValue("font", "Helvetica");
+    tlayer->setFontName(fontName);
+
+    const SGPropertyNode * chunk_group = node->getNode("chunks");
+    if (chunk_group != 0) {
+      int nChunks = chunk_group->nChildren();
+      for (int i = 0; i < nChunks; i++) {
+	const SGPropertyNode * node = chunk_group->getChild(i);
+	if (!strcmp(node->getName(), "chunk")) {
+	  FGTextLayer::Chunk * chunk = readTextChunk(node);
+	  if (chunk != 0)
+	    tlayer->addChunk(chunk);
+	} else {
+	  SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
+                  << " in chunks" );
+	}
+      }
+      layer = tlayer;
+    }
+  }
+
+				// A switch instrument layer.
+  else if (type == "switch") {
+    layer = new FGSwitchLayer();
+    for (int i = 0; i < node->nChildren(); i++) {
+      const SGPropertyNode * child = node->getChild(i);
+      if (!strcmp(child->getName(), "layer"))
+	((FGGroupLayer *)layer)->addLayer(readLayer(child, w_scale, h_scale));
+    }
+  }
+
+				// An unknown type.
+  else {
+    SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized layer type " << type );
+    delete layer;
+    return 0;
+  }
+  
+  //
+  // Get the transformations for each layer.
+  //
+  const SGPropertyNode * trans_group = node->getNode("transformations");
+  if (trans_group != 0) {
+    int nTransformations = trans_group->nChildren();
+    for (int i = 0; i < nTransformations; i++) {
+      const SGPropertyNode * node = trans_group->getChild(i);
+      if (!strcmp(node->getName(), "transformation")) {
+	FGPanelTransformation * t = readTransformation(node, w_scale, h_scale);
+	if (t != 0)
+	  layer->addTransformation(t);
+      } else {
+	SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
+                << " in transformations" );
+      }
+    }
+  }
+
+  readConditions(layer, node);
+  SG_LOG( SG_COCKPIT, SG_DEBUG, "Read layer " << name );
+  return layer;
+}
+
+
+/**
+ * Read an instrument from a property list.
+ *
+ * The instrument consists of a preferred width and height
+ * (the panel may override these), together with a list of layers
+ * and a list of actions to be performed when the user clicks 
+ * the mouse over the instrument.  All co-ordinates are relative
+ * to the instrument's position, so instruments are fully relocatable;
+ * likewise, co-ordinates for actions and transformations will be
+ * scaled automatically if the instrument is not at its preferred size.
+ */
+static FGPanelInstrument *
+readInstrument (const SGPropertyNode * node)
+{
+  const string name = node->getStringValue("name");
+  int x = node->getIntValue("x", -1);
+  int y = node->getIntValue("y", -1);
+  int real_w = node->getIntValue("w", -1);
+  int real_h = node->getIntValue("h", -1);
+  int w = node->getIntValue("w-base", -1);
+  int h = node->getIntValue("h-base", -1);
+
+  if (x == -1 || y == -1) {
+    SG_LOG( SG_COCKPIT, SG_ALERT,
+            "x and y positions must be specified and > 0" );
+    return 0;
+  }
+
+  float w_scale = 1.0;
+  float h_scale = 1.0;
+  if (real_w != -1) {
+    w_scale = float(real_w) / float(w);
+    w = real_w;
+  }
+  if (real_h != -1) {
+    h_scale = float(real_h) / float(h);
+    h = real_h;
+  }
+
+  SG_LOG( SG_COCKPIT, SG_DEBUG, "Reading instrument " << name );
+
+  FGLayeredInstrument * instrument =
+    new FGLayeredInstrument(x, y, w, h);
+
+  //
+  // Get the layers for the instrument.
+  //
+  const SGPropertyNode * layer_group = node->getNode("layers");
+  if (layer_group != 0) {
+    int nLayers = layer_group->nChildren();
+    for (int i = 0; i < nLayers; i++) {
+      const SGPropertyNode * node = layer_group->getChild(i);
+      if (!strcmp(node->getName(), "layer")) {
+	FGInstrumentLayer * layer = readLayer(node, w_scale, h_scale);
+	if (layer != 0)
+	  instrument->addLayer(layer);
+      } else {
+	SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
+                << " in layers" );
+      }
+    }
+  }
+
+  readConditions(instrument, node);
+  SG_LOG( SG_COCKPIT, SG_DEBUG, "Done reading instrument " << name );
+  return instrument;
+}
+
+
+/**
+ * Construct the panel from a property tree.
+ */
+SGSharedPtr<FGPanel>
+FGReadablePanel::read(SGPropertyNode_ptr root)
+{
+  SG_LOG( SG_COCKPIT, SG_INFO, "Reading properties for panel " <<
+          root->getStringValue("name", "[Unnamed Panel]") );
+
+  FGPanel * panel = new FGPanel(root);
+  panel->setWidth(root->getIntValue("w", 1024));
+  panel->setHeight(root->getIntValue("h", 443));
+
+  SG_LOG( SG_COCKPIT, SG_INFO, "Size=" << panel->getWidth() << "x" << panel->getHeight() );
+
+  // Assign the background texture, if any, or a bogus chequerboard.
+  //
+  string bgTexture = root->getStringValue("background");
+  if( !bgTexture.empty() )
+    panel->setBackground( new FGCroppedTexture( bgTexture ) );
+  panel->setBackgroundWidth( root->getDoubleValue( "background-width", 1.0 ) );
+  panel->setBackgroundHeight( root->getDoubleValue( "background-height", 1.0 ) );
+  SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << bgTexture );
+
+  //
+  // Get multibackground if any...
+  //
+  for( int i = 0; i < 8; i++ ) {
+    SGPropertyNode * mbgNode = root->getChild( "multibackground", i );
+    string mbgTexture;
+    if( mbgNode != NULL ) mbgTexture = mbgNode->getStringValue();
+    if( mbgTexture.empty() ) {
+      if( i == 0 ) break; // if first texture is missing, ignore the rest
+      else mbgTexture = "FOO"; // if others are missing - set default texture
+    }
+    panel->setMultiBackground( new FGCroppedTexture(mbgTexture), i );
+    SG_LOG( SG_COCKPIT, SG_INFO, "Set multi-background texture" << i << " to " << mbgTexture );
+  }
+  //
+  // Create each instrument.
+  //
+  SG_LOG( SG_COCKPIT, SG_INFO, "Reading panel instruments" );
+  const SGPropertyNode * instrument_group = root->getChild("instruments");
+  if (instrument_group != 0) {
+    int nInstruments = instrument_group->nChildren();
+    for (int i = 0; i < nInstruments; i++) {
+      const SGPropertyNode * node = instrument_group->getChild(i);
+      if (!strcmp(node->getName(), "instrument")) {
+        FGPanelInstrument * instrument = readInstrument(node);
+        if (instrument != 0)
+          panel->addInstrument(instrument);
+      } else {
+        SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
+        << " in instruments section" );
+      }
+    }
+  }
+  SG_LOG( SG_COCKPIT, SG_INFO, "Done reading panel instruments" );
+
+
+  //
+  // Return the new panel.
+  //
+  return panel;
+}
+
+// end of panel_io.cxx
+
+
+
diff --git a/utils/fgpanel/panel_io.hxx b/utils/fgpanel/panel_io.hxx
new file mode 100644
index 000000000..e353ce04e
--- /dev/null
+++ b/utils/fgpanel/panel_io.hxx
@@ -0,0 +1,40 @@
+//  panel_io.cxx - I/O for 2D panel.
+//
+//  Written by David Megginson, started January 2000.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+//  $Id: panel_io.hxx,v 1.6 2006/04/17 13:03:43 mfranz Exp $
+
+#ifndef __PANEL_IO_HXX
+#define __PANEL_IO_HXX
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#  include <windows.h>
+#endif
+
+#include "panel.hxx"
+
+class FGReadablePanel : public FGPanel {
+public:
+  static SGSharedPtr<FGPanel> read(SGPropertyNode_ptr root);
+};
+
+
+#endif // __PANEL_IO_HXX