<?xml version="1.0"?>

<!--
     For information on how to use this feature, see
     Docs/README.location-in-air 
-->

<PropertyList>
  <name>location-in-air</name>
  <layout>vbox</layout>
  <halign>left</halign>

  <nasal> <!-- line zero -->
    <open>

      var verbose = 0;
      if (verbose) {
# Display on console the mess that we have inherited:
          props.dump(props.globals.getNode("/fdm/jsbsim/sim-time-sec"));
          props.dump(props.globals.getNode("/orientation"));
          props.dump(props.globals.getNode("/velocities"));
      }

      var self = cmdarg();
      me = "/sim/gui/dialogs/location-in-air";
      magvar = getprop("/environment/magnetic-variation-deg");
      setprop(me, "reciprocate", 1);

      pow = func {
        return math.exp(arg[1]*math.ln(arg[0]));
      }

# The reciprocal heading.  Angles in degrees.
      reciprocal = func(angle){
        if (angle == nil or angle == "") return "";
        angle = string.trim(angle);
        var catch = [];
        var rslt = 0;
        call(func{rslt = 180 + angle},[],nil,nil,catch);
        if (size(catch)) return "???";
        if (rslt > 360) rslt -= 360;
        return sprintf("%03d", rslt);
      }

# Dispatch table.  Binds "bearing" to reciprocal of "radial"
# and vice versa.
      last_input = "";
      dispatch = {
        "bearing" : func() {
          var val = getprop(me, "bearing-deg-mag");
          #print("bearing script called: ", val);
          setprop(me, "radial-deg-mag", reciprocal(val));
        },
        "radial" : func() {
          var val = getprop(me, "radial-deg-mag");
          #print("radial script called: ", val);
          setprop(me, "bearing-deg-mag", reciprocal(val));
        },
      };

# "Common key" functions for all input boxes.
# The only ones of interest have implementations
# in the dispatch table above.
      dispatch_inputs = func(new_input){
        fgcommand("dialog-apply", self);
        #printf("dispatch_inputs: '%8s' --> '%8s'", last_input, new_input);
        foreach (k; keys(dispatch)) {
          if (k == last_input) call(dispatch[k]);
        }
        last_input = new_input;
        fgcommand("dialog-update", self);
      }

      mynode = props.globals.getNode(me, 1);
      mode = {
        "airport-btn": mynode.getNode("airport-btn", 1),
        "lonlat-btn":  mynode.getNode("lonlat-btn", 1),
        "vor-btn":     mynode.getNode("vor-btn", 1),
        "ndb-btn":     mynode.getNode("ndb-btn", 1),
        "fix-btn":     mynode.getNode("fix-btn", 1),
        "ppos-btn":    mynode.getNode("ppos-btn", 1),
      };

# Function to push a radio button and clear all the others:
      set_radio = func(m) {
        #print("set_radio: ", m);
        dispatch_inputs("");
        foreach (k; keys(mode)) {
          mode[k].setBoolValue(m == k);
        }
      }

# Initialize all the radio buttons:
      initialized = 0;
      foreach (k; keys(mode)) {
        if (mode[k].getType() == "NONE") {
          mode[k].setBoolValue(0);
        }
        initialized += mode[k].getBoolValue();
      }
      if (!initialized) {
        set_radio("airport-btn");
      }

# We make a private copy of each of the FDM "preset"
# variables, so we don't need to worry about whether 
# the FDM will mess with them later.
     
      var presetvars = props.globals.getNode("/sim/presets").getChildren();

# Inherit a few things from the presets on the fgfs command line:
      if (!getprop(me, "did1")) {
        setprop(me, "did1", 1);         # inherit only once

# Copy each inherited variable.
        foreach (nnn ; presetvars) {
          var ttt = nnn.getType();
          var value = nnn.getValue();
          var varname = nnn.getName();
# Make sure we assign a _string_ (not a numeric) to
# our copy of the variable.
# The reason for that is so that (later) we can distinguish
# between "" (which means take the default)
# and zero (which means the user wants a value of zero).
          if (ttt == "STRING") {
            setprop(me, varname, value);
          } elsif (value != nil) {      
            # must be some kind of numeric
            var fmt = "%1.0f";
            if (varname == "longitude-deg" or varname == "latitude-deg"){
              fmt = "%1.4f";
            }
            setprop(me, varname, sprintf(fmt, value))
          } else {
            setprop(me, varname, "");
          }
        }

# Now fix up a few of the inherited values, 
# taking care of special cases:

# Relocating to surface doesn't make sense;
# we are supposed to be relocating aloft:
        alt = getprop("/sim/presets/altitude-ft");
        if (alt == -9999) {
          alt = "";
        }  # else accept "inherited" reset-to-air altitude
        setprop(me, "altitude-ft", alt);

# Inherit preset airspeed from command line:
        ktas = getprop("/sim/presets/airspeed-kt");
        if (ktas == 0) {
          ktas = "";
        }
        setprop(me, "airspeed-kt", ktas);       

# Probably never a good idea to inherit a heading;
        setprop(me, "heading-deg-mag", "");

      }  # end inheriting things

# The "normalize attitude" flag defaults to true:
      if (getprop(me, "normalize") == nil) {
        setprop(me, "normalize", 1);
      }

# Hint:  you can read all of these useful quantities using:
# http://localhost:5400/sim/gui/dialogs/location-in-air

      setprop(me, "prior/altitude-agl-ft",
        sprintf("%5.2f", getprop("/position/altitude-agl-ft")));

# Copy positions of some cockpit flight controls:
      copycontrol = func(vvv, factor){
        setprop(me, "prior", vvv,
          sprintf("%5.2f", factor * getprop("/controls/flight", vvv)));
      }
      copycontrol("aileron", 1);
      copycontrol("aileron-trim", 1);
      copycontrol("elevator", -1);
      copycontrol("elevator-trim", -1);
      copycontrol("rudder", 1);
      copycontrol("rudder-trim", 1);

# The rule is, if it doesn't say "mag" in the name, it
# is a true bearing, not a magnetic bearing.
# Like the FDM, we do as much as possible with true 
# bearings internally.

# When displaying magnetic bearings to a user,
# we convert them /immediately/ beforehand to magnetic
# by subtracting magvar.
# Similarly, when getting magnetic bearings from the user,
# we convert them /immediately/ afterward to true
# by adding magvar.

      prior_heading_deg_mag = getprop("/orientation/heading-deg") - magvar;
      setprop(me, "prior/heading-deg-mag", sprintf("%d", prior_heading_deg_mag));
      setprop(me, "prior/throttle", sprintf("%5.2f", 
                getprop("/controls/engines/engine/throttle")));

      xx = sprintf("%1.4f", getprop("/position/latitude-deg"));
      setprop(me, "prior/latitude-deg", xx);
      setprop(me, "this-latitude-deg", xx);
      xx = sprintf("%1.4f", getprop("/position/longitude-deg"));
      setprop(me, "prior/longitude-deg", xx);
      setprop(me, "this-longitude-deg", xx);
      setprop(me, "prior/slp",
        sprintf("%5.2f", getprop("/environment/pressure-sea-level-inhg")));
      if (0) {
        nn = 0.1903;
        kk = 1.313e-5;
        Phg = getprop("/environment/pressure-inhg");
        alt = getprop("/position/altitude-ft");
        qnh = pow(pow(Phg, nn) + kk * alt, 1/nn);
        setprop(me, "prior/qnh", sprintf("%5.2f", qnh));
        Rgas = 8.31432;         # [J/K/mole] gas constant
        inch = 0.0254;          # [m] definition of inch
        foot = 12*inch;
        slug = 14.59390;                # [kg]
        inHg = 101325.0/ 29.92126; # [Pa]
        rho = getprop("/environment/density-slugft3")*slug/foot/foot/foot;
        T = 273.15 + getprop("/environment/temperature-degc");
        P = Phg * inHg;
        mM = Rgas * T * rho / P;
        print("alt: ", alt, "  mM: ",  mM, "  P: ",  P, "  T: ", T, "  rho: ", rho);
        setprop(me, "prior/molar-mass", sprintf("%8.4f", mM));
      }

    </open>

    <close>   # just kept for educational purposes :-)

# Note that I would like to use the degree /symbol/
# rather than spelling out "deg" in the dialog labels.
# The utf-8 for this symbol is (°).
# However, alas, putting that into the label produces
# no visible result.  Rumor suggests that we are using
# a font that doesn't have a glyph for this character.

    </close>
  </nasal>

  <text>
    <label>Location In Air</label>
  </text>

  <hrule/>

  <text>
    <label>Reference Point</label>
  </text>

  <group>
    <layout>table</layout>
    <halign>left</halign>
    <radio>
      <row>0</row><col>0</col>
      <live>true</live>
      <property>/sim/gui/dialogs/location-in-air/airport-btn</property>
      <binding>
        <command>dialog-apply</command>
      </binding>
      <binding>
        <command>nasal</command>
        <script>set_radio("airport-btn")</script>
      </binding>
    </radio>
    <text>
      <row>0</row><col>1</col>
      <halign>left</halign>
      <label>Airport:</label>
    </text>
    <input>
      <row>0</row><col>2</col>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/airport-id</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>

    <text>
      <row>0</row><col>3</col>
      <label>Runway:</label>
    </text>
    <input>
      <row>0</row><col>4</col>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/runway</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>

    <radio>
      <row>1</row><col>0</col>
      <live>true</live>
      <property>/sim/gui/dialogs/location-in-air/lonlat-btn</property>
      <binding>
        <command>dialog-apply</command>
      </binding>
      <binding>
        <command>nasal</command>
        <script>set_radio("lonlat-btn")</script>
      </binding>
    </radio>
    <text>
      <row>1</row><col>1</col>
      <halign>left</halign>
      <label>Latitude:</label>
    </text>
    <input>
      <row>1</row><col>2</col>
      <pref-width>130</pref-width>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/latitude-deg</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>
    <text>
      <row>1</row><col>3</col>
      <halign>left</halign>
      <label>Longitude:</label>
    </text>
    <input>
      <row>1</row><col>4</col>
      <pref-width>130</pref-width>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/longitude-deg</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>

    <radio>
      <row>2</row><col>0</col>
      <live>true</live>
      <property>/sim/gui/dialogs/location-in-air/vor-btn</property>
      <binding>
        <command>dialog-apply</command>
      </binding>
      <binding>
        <command>nasal</command>
        <script>set_radio("vor-btn")</script>
      </binding>
    </radio>
    <text>
      <row>2</row><col>1</col>
      <halign>left</halign>
      <label>VOR:</label>
    </text>
    <input>
      <row>2</row><col>2</col>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/vor-id</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>

    <radio>
      <row>3</row><col>0</col>
      <live>true</live>
      <property>/sim/gui/dialogs/location-in-air/ndb-btn</property>
      <binding>
        <command>dialog-apply</command>
      </binding>
      <binding>
        <command>nasal</command>
        <script>set_radio("ndb-btn")</script>
      </binding>
    </radio>
    <text>
      <row>3</row><col>1</col>
      <halign>left</halign>
      <label>NDB:</label>
    </text>
    <input>
      <row>3</row><col>2</col>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/ndb-id</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>
    <text>
      <row>3</row><col>3</col>
      <halign>left</halign>
      <label>(3-letter ID)</label>
    </text>

    <radio>
      <row>4</row><col>0</col>
      <live>true</live>
      <property>/sim/gui/dialogs/location-in-air/fix-btn</property>
      <binding>
        <command>dialog-apply</command>
      </binding>
      <binding>
        <command>nasal</command>
        <script>set_radio("fix-btn")</script>
      </binding>
    </radio>
    <text>
      <row>4</row><col>1</col>
      <halign>left</halign>
      <label>Waypoint:</label>
    </text>
    <input>
      <row>4</row><col>2</col>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/fix</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>
    <text>
      <row>4</row><col>3</col>
      <halign>left</halign>
      <label>(5-character ID)</label>
    </text>

    <radio>
      <row>5</row><col>0</col>
      <live>true</live>
      <property>/sim/gui/dialogs/location-in-air/ppos-btn</property>
      <binding>
        <command>dialog-apply</command>
      </binding>
      <binding>
        <command>nasal</command>
        <script>set_radio("ppos-btn")</script>
      </binding>
    </radio>
    <text>
      <row>5</row><col>1</col>
      <halign>left</halign>
      <label>Here</label>
    </text>
    <text>
      <row>5</row><col>2</col>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/this-latitude-deg</property>
    </text>
    <text>
      <row>5</row><col>4</col>
      <halign>left</halign>
      <property>/sim/gui/dialogs/location-in-air/this-longitude-deg</property>
    </text>

  </group>

  <text>
    <label>Offset from Reference Point</label>
  </text>

  <group>
    <layout>table</layout>
    <text>
      <row>0</row><col>0</col>
      <halign>right</halign>
      <label>Distance:</label>
    </text>
    <input>
      <row>0</row><col>1</col>
      <property>/sim/gui/dialogs/location-in-air/offset-distance-nm</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>
    <text>
      <row>0</row><col>2</col>
      <halign>left</halign>
      <label>nm    </label>
    </text>

    <text>
      <row>0</row><col>3</col>
      <halign>right</halign>
      <label>Radial from ref:</label>
    </text>
    <input>
      <row>0</row><col>4</col>
      <property>/sim/gui/dialogs/location-in-air/radial-deg-mag</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("radial");</script>
      </binding>
    </input>
    <text>
      <row>0</row><col>5</col>
      <halign>left</halign>
      <label>deg mag</label>
    </text>

    <checkbox>
      <row>1</row><col>2</col>
      <halign>right</halign>
      <property>/sim/gui/dialogs/location-in-air/reciprocate</property>
      <binding>
        <command>nasal</command>
        <script>
          dispatch_inputs("");
          var b = getprop(me, "bearing-deg-mag");
          var r = getprop(me, "radial-deg-mag");
          setprop(me, "bearing-deg-mag", r);
          setprop(me, "radial-deg-mag", b);
          setprop(me, "reciprocate", 1);
          fgcommand("dialog-update", self);
        </script>
      </binding>
    </checkbox>

    <text>
      <row>1</row><col>3</col>
      <halign>right</halign>
      <label>Bearing to ref:</label>
    </text>
    <input>
      <row>1</row><col>4</col>
      <property>/sim/gui/dialogs/location-in-air/bearing-deg-mag</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("bearing");</script>
      </binding>
    </input>
    <text>
      <row>1</row><col>5</col>
      <halign>left</halign>
      <label>deg mag</label>
    </text>


    <text>
      <row>2</row><col>0</col>
      <halign>right</halign>
      <label>Altitude:</label>
    </text>
    <input>
      <row>2</row><col>1</col>
      <property>/sim/gui/dialogs/location-in-air/altitude-ft</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>
    <text>
      <row>2</row><col>2</col>
      <halign>left</halign>
      <label>ft MSL</label>
    </text>

    <text>
      <row>2</row><col>3</col>
      <halign>right</halign>
      <label>Glideslope:</label>
    </text>
    <text>
      <row>2</row><col>4</col>
      <halign>center</halign>
      <label>INOP</label>
    </text>

    <!-- input>
      Does not work.  Backend has not worked for years.
      <row>2</row><col>4</col>
      <property>/sim/gui/dialogs/location-in-air/glideslope-deg</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input -->
    <text>
      <row>2</row><col>5</col>
      <halign>left</halign>
      <label>deg</label>
    </text>


    <text>
      <row>3</row><col>0</col>
      <halign>right</halign>
      <label>Airspeed</label>
    </text>
    <input>
      <row>3</row><col>1</col>
      <property>/sim/gui/dialogs/location-in-air/airspeed-kt</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>
    <text>
      <row>3</row><col>2</col>
      <halign>left</halign>
      <label>kt</label>
    </text>


    <text>
      <row>3</row><col>3</col>
      <halign>right</halign>
      <label>Heading:</label>
    </text>
    <input>
      <row>3</row><col>4</col>
      <property>/sim/gui/dialogs/location-in-air/heading-deg-mag</property>
      <binding>
        <command>nasal</command>
        <script>dispatch_inputs("");</script>
      </binding>
    </input>
    <text>
      <row>3</row><col>5</col>
      <halign>left</halign>
      <label>deg mag</label>
    </text>

  </group>

  <group>
    <layout>hbox</layout>
    <default-padding>10</default-padding>

    <button>
      <legend>OK</legend>
      <default>true</default>
      <equal>true</equal>
      <binding>
        <command>nasal</command>
        <script>
          dispatch_inputs("");
          fgcommand("dialog-apply", self);

          #props.dump(props.globals.getNode("/sim/presets"));

# First, clear out all the FDM's "presets":
          foreach (nnn ; presetvars) {
            if (nnn.getName() != "speed-set") nnn.setValue("");
          }

# Special treatment for some presets; they
# are numeric, not strings, so setting them to "" 
# would be the same as zero, which would be in-range.
          setprop("/sim/presets/longitude-deg", -9999);
          setprop("/sim/presets/latitude-deg", -9999);
          setprop("/sim/presets/altitude-ft", -9999);

# Special treatment for variables that we might need
# to give nonzero values, but not part of our dialog:
          setprop("/sim/presets/trim", 0);      # as it should be
          setprop("/sim/presets/trim", 1);      # kludge!  FIXME!
          setprop("/sim/presets/onground", 0);

#### Next, set some presets according to our dialog.
# Some support routines:
          fixup = func(varname){
            setprop("/sim/presets", varname, getprop(me, varname));
          }

          checkup = func(button, varname){
            if (mode[button].getBoolValue()) {
              fixup(varname);
            }
          }

# First, handle the input boxes related to radio buttons:
          checkup("airport-btn", "airport-id");
          checkup("airport-btn", "runway");
          checkup("lonlat-btn", "latitude-deg");
          checkup("lonlat-btn", "longitude-deg");
          checkup("vor-btn", "vor-id");
          checkup("ndb-btn", "ndb-id");
          checkup("fix-btn", "fix");
          
# The "here" button i.e. present position is tricky:

          if (mode["ppos-btn"].getBoolValue()) {
            setprop("/sim/presets/latitude-deg", 
               getprop("/position/latitude-deg"));
            setprop("/sim/presets/longitude-deg", 
               getprop("/position/longitude-deg"));
          }

######
# Now for the popup items that are /not/ connected to radio buttons;
# there should be six of them:

# The glideslope feature does not work.  It has not worked for many years.
#INOP     fixup("glideslope-deg");

# Did user specify a heading?
          hdg_mag = getprop(me, "heading-deg-mag");

# If not, heading defaults to current heading
          if (hdg_mag == "") {
# prior heading was computed in the "open" section above:
            hdg_mag = prior_heading_deg_mag;
          }
          setprop("/sim/presets/heading-deg", num(hdg_mag) + magvar);
          setprop(me, "last-heading-deg-mag", hdg_mag);

# The distance from the reference point:
          offset = getprop(me, "offset-distance-nm");

# Preset azimuth defaults to current heading;
# otherwise use bearing (not radial),
# because that's what the FDM is expecting.
          magvar = getprop("/environment/magnetic-variation-deg");
          az = getprop(me, "bearing-deg-mag");
          if (az == "") az = hdg_mag;
          az += magvar;       # az now /true/ bearing

# Handle negative offsets:
          if (!offset){
            offset = 0;
          }
          if (offset &lt; 0) {
            offset = - offset;
            az += 180;
          }
# Prettify the variable, in case anybody dumps it:
          while (az &gt; 360){
            az -= 360;
          }
          setprop("/sim/presets/offset-azimuth-deg", az);
          setprop("/sim/presets/offset-distance-nm", offset);

# Altitude defaults to current altitude,
# which makes a lot of sense if we are relocating FROM AIR to air
# but maybe not so much if we are relocating from ground to air.
          alt = getprop(me, "altitude-ft");
          if (alt == "") {
            alt = getprop("/position/altitude-ft");
          }
          setprop("/sim/presets/altitude-ft", alt);

# airspeed defaults to current airspeed
          ktas = getprop(me, "airspeed-kt");
          if (ktas == "") {
            ktas = getprop("/velocities/airspeed-kt");
          }
          setprop("/sim/presets/airspeed-kt", ktas);

# Save magneto, throttle, gear, trim, and view settings 
# from the ravages of presets-commit.

          enode = props.globals.getNode("/controls/engines");
          engs = enode.getChildren("engine");
          magvec = [];
          thrvec = [];
          setsize(magvec, size(engs));
          setsize(thrvec, size(engs));
          for(ii=0; ii &lt; size(engs); ii=ii+1) {
            magvec[ii] = engs[ii].getNode("magnetos", 1).getValue();
            thrvec[ii] = engs[ii].getNode("throttle", 1).getValue();
          }
          atrim = getprop("/controls/flight/aileron-trim");
          etrim = getprop("/controls/flight/elevator-trim");
          rtrim = getprop("/controls/flight/rudder-trim");
          gear_down = getprop("/controls/gear/gear-down");

          view_field = getprop("/sim/current-view/field-of-view");
          view_hdg = getprop("/sim/current-view/goal-heading-offset-deg");
          view_pitch = getprop("/sim/current-view/goal-pitch-offset-deg");

# I don't think this works.
# It is NOT SAFE to brutally set the roll angle etc.;
# it just causes the FDM to reset and/or crash.
# It might be OK to set the _presets_  but I'm 
# not sure if that actually does anything.
          if (0 and getprop(me, "normalize")){
            if (abs(getprop("/orientation/pitch-deg")) > 45) {
              print("Normalizing pitch, was: ", getprop("/orientation/pitch-deg"));
              setprop("/orientation/pitch-deg", 0);
              setprop("/orientation/pitch-rate-degps", 0);
            }
            if (abs(getprop("/orientation/roll-deg")) > 45) {
              print("Normalizing roll, was: ", getprop("/orientation/roll-deg"));
              setprop("/orientation/roll-deg", 0);
              setprop("/orientation/roll-rate-degps", 0);
            }
          }

# kludge:
   setprop("/sim/presets/roll-deg", 10);
   setprop("/sim/presets/pitch-deg", 1.23);
   setprop("/sim/presets/heading-deg", 45);

          if (verbose) {
# Display on console what we have done:
            props.dump(props.globals.getNode("/fdm/jsbsim/sim-time-sec"));
            props.dump(props.globals.getNode("/sim/presets"));
          }

#         This is a nasty thing;  lots of brutal side-effects:
#         vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 
          fgcommand("presets-commit");
#         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

          if (verbose) {
# Display on console the mess that presets-commit has made:
            props.dump(props.globals.getNode("/fdm/jsbsim/sim-time-sec"));
            props.dump(props.globals.getNode("/orientation"));
            props.dump(props.globals.getNode("/velocities"));
          }

# Restore magneto, throttle, view, and trim settings 
# after the ravages of presets-commit.

          lim = size(magvec);           # same as size of thrvec

          enode = props.globals.getNode("/controls/engines");
          engs = enode.getChildren("engine");

          for(ii=0; ii &lt; lim; ii=ii+1) {
            thismag = magvec[ii];
            engs[ii].getNode("magnetos", 1).setValue(thismag);
# Throttle setting doesn't work in JSBSim
# (but works OK in larcsim):
            engs[ii].getNode("throttle", 1).setValue(thrvec[ii]);
          }
          
          setprop("/controls/flight/aileron-trim", atrim);
          setprop("/controls/flight/elevator-trim", etrim);
          setprop("/controls/flight/rudder-trim", rtrim);
          setprop("/controls/gear/gear-down", gear_down);

          setprop("/sim/current-view/field-of-view", view_field);
          setprop("/sim/current-view/goal-heading-offset-deg", view_hdg);
          setprop("/sim/current-view/goal-pitch-offset-deg", view_pitch);

# Last but not least, notify people that we may have moved to 
# a new location:
          setprop("/position/attention", 1);

          fgcommand("dialog-close", self);
        </script>
      </binding>

##      <binding>
##        <command>dialog-close</command>
##      </binding>
    </button>

    <button>
      <legend>Cancel</legend>
      <equal>true</equal>
      <key>Esc</key>
      <binding>
        <command>nasal</command>
        <script>
          dispatch_inputs("");
          fgcommand("dialog-close", self);
        </script>
      </binding>
##      <binding>
##        <command>dialog-close</command>
##      </binding>
    </button>

    <text>
      <label>Normalize attitude:</label>
    </text>
    
    <checkbox>
      <property>/sim/gui/dialogs/location-in-air/normalize</property>
    </checkbox>

  </group>
</PropertyList>
