From 5893de13ffe0b66360ac5bb9f519c039e44ddaf1 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 29 May 2001 22:31:04 +0000
Subject: [PATCH] 1. Fixed FGInput bug preventing same key from being bound
 separately with different modifiers (the format of the key bindings has
 changed again slightly, adding a <code>..</code> element; see keyboard.xml
 for details).

2. Modified FGInput to try default modifiers for ctrl, shift, and alt
when the initial bindings fail (i.e. you don't have to specify
mod-shift explicitly for upper-case 'P' any more).

3. Fixed problems with properties and panel reloading reported by
Martin Dressler and John Check.

4. Updated preferences.xml to get rid of obsolete references to
/controls/brakes/left and /controls/brakes/right (as reported by John
Check).


There were also two non-bugs reported by John Check:

(a) Differential braking doesn't work (John was using the obsolete
properties from #4 above).

(b) Duplicates show up in the property tree using the telnet interface
(the property tree doesn't show indices, and John was seeing separate
entries for each possible engine, etc.).
---
 src/Cockpit/panel.cxx |   8 +-
 src/Cockpit/panel.hxx |   1 +
 src/Input/input.cxx   | 558 ++++++++++++++++++++++--------------------
 3 files changed, 294 insertions(+), 273 deletions(-)

diff --git a/src/Cockpit/panel.cxx b/src/Cockpit/panel.cxx
index 6825dca4e..e0cf55d9e 100644
--- a/src/Cockpit/panel.cxx
+++ b/src/Cockpit/panel.cxx
@@ -135,7 +135,8 @@ FGPanel::FGPanel (int window_x, int window_y, int window_w, int window_h)
     _mouseInstrument(0),
     _winx(window_x), _winy(window_y), _winw(window_w), _winh(window_h),
     _width(_winw), _height(int(_winh * 0.5768 + 1)),
-    _x_offset(0), _y_offset(0), _view_height(int(_winh * 0.4232))
+    _x_offset(0), _y_offset(0), _view_height(int(_winh * 0.4232)),
+    _bound(false)
 {
   setVisibility(fgPanelVisible());
 }
@@ -146,7 +147,8 @@ FGPanel::FGPanel (int window_x, int window_y, int window_w, int window_h)
  */
 FGPanel::~FGPanel ()
 {
-  unbind();
+  if (_bound)
+    unbind();
   for (instrument_list_type::iterator it = _instruments.begin();
        it != _instruments.end();
        it++) {
@@ -185,6 +187,7 @@ FGPanel::bind ()
   fgTie("/sim/panel/visibility", &_visibility);
   fgTie("/sim/panel/x-offset", &_x_offset);
   fgTie("/sim/panel/y-offset", &_y_offset);
+  _bound = true;
 }
 
 
@@ -197,6 +200,7 @@ FGPanel::unbind ()
   fgUntie("/sim/panel/visibility");
   fgUntie("/sim/panel/x-offset");
   fgUntie("/sim/panel/y-offset");
+  _bound = false;
 }
 
 
diff --git a/src/Cockpit/panel.hxx b/src/Cockpit/panel.hxx
index bcc9c5959..2fed9bc08 100644
--- a/src/Cockpit/panel.hxx
+++ b/src/Cockpit/panel.hxx
@@ -180,6 +180,7 @@ private:
   int _x_offset;
   int _y_offset;
   int _view_height;
+  bool _bound;
   
   ssgTexture * _bg;
 				// List of instruments in panel.
diff --git a/src/Input/input.cxx b/src/Input/input.cxx
index f3dcdb756..b45e1b20d 100644
--- a/src/Input/input.cxx
+++ b/src/Input/input.cxx
@@ -71,152 +71,152 @@ SG_USING_STD(string);
 ////////////////////////////////////////////////////////////////////////
 
 FGBinding::FGBinding ()
-    : _action(ACTION_NONE), _node(0), _adjust_step(0), _assign_value(0)
+  : _action(ACTION_NONE), _node(0), _adjust_step(0), _assign_value(0)
 {
 }
 
 FGBinding::FGBinding (const SGPropertyNode * node)
-    : _action(ACTION_NONE), _node(0), _adjust_step(0), _assign_value(0)
+  : _action(ACTION_NONE), _node(0), _adjust_step(0), _assign_value(0)
 {
-    read(node);
+  read(node);
 }
 
 FGBinding::~FGBinding ()
 {
-    // no op
+  // no op
 }
 
 void
 FGBinding::setAction (Action action)
 {
-    _action = action;
+  _action = action;
 }
 
 void
 FGBinding::setProperty (SGPropertyNode * node)
 {
-    _node = node;
+  _node = node;
 }
 
 void
 FGBinding::setAdjustStep (const SGValue * step)
 {
-    _adjust_step = step;
+  _adjust_step = step;
 }
 
 void
 FGBinding::setAssignValue (const SGValue * value)
 {
-    _assign_value = value;
+  _assign_value = value;
 }
 
 void
 FGBinding::read (const SGPropertyNode * node)
 {
-    if (node->hasValue("action")) {
-        string action = node->getStringValue("action");
-        if (action == "none")
-            _action = ACTION_NONE;
-        else if (action == "switch")
-            _action = ACTION_SWITCH;
-        else if (action == "adjust")
-            _action = ACTION_ADJUST;
-        else if (action == "assign")
-            _action = ACTION_ASSIGN;
-        else
-            SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unrecognized action type "
-                   << action);
-    }
+  if (node->hasValue("action")) {
+    string action = node->getStringValue("action");
+    if (action == "none")
+      _action = ACTION_NONE;
+    else if (action == "switch")
+      _action = ACTION_SWITCH;
+    else if (action == "adjust")
+      _action = ACTION_ADJUST;
+    else if (action == "assign")
+      _action = ACTION_ASSIGN;
+    else
+      SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unrecognized action type "
+	     << action);
+  }
 
-    if (node->hasValue("control"))
-        _node = fgGetNode(node->getStringValue("control"), true);
+  if (node->hasValue("control"))
+    _node = fgGetNode(node->getStringValue("control"), true);
 
-    if (node->hasValue("step"))
-        _adjust_step = node->getChild("step")->getValue();
+  if (node->hasValue("step"))
+    _adjust_step = node->getChild("step")->getValue();
 
-    if (node->hasValue("value"))
-        _assign_value = node->getChild("value")->getValue();
+  if (node->hasValue("value"))
+    _assign_value = node->getChild("value")->getValue();
 }
 
 void
 FGBinding::fire () const
 {
-    if (_node == 0) {
-        SG_LOG(SG_INPUT, SG_ALERT, "No control property attached to binding");
-        return;
+  if (_node == 0) {
+    SG_LOG(SG_INPUT, SG_ALERT, "No control property attached to binding");
+    return;
+  }
+
+  switch (_action) {
+
+  case ACTION_NONE:
+    break;
+
+  case ACTION_SWITCH:
+    _node->setBoolValue(!_node->getBoolValue());
+    break;
+
+  case ACTION_ADJUST:
+    if  (_adjust_step == 0) {
+      SG_LOG(SG_INPUT, SG_ALERT, "No step provided for adjust binding");
+      break;
     }
-
-    switch (_action) {
-
-    case ACTION_NONE:
-        break;
-
-    case ACTION_SWITCH:
-        _node->setBoolValue(!_node->getBoolValue());
-        break;
-
-    case ACTION_ADJUST:
-        if  (_adjust_step == 0) {
-            SG_LOG(SG_INPUT, SG_ALERT, "No step provided for adjust binding");
-            break;
-        }
-        switch (_node->getType()) {
-        case SGValue::BOOL:
-            if (_adjust_step->getBoolValue())
-                _node->setBoolValue(!_node->getBoolValue());
-            break;
-        case SGValue::INT:
-            _node->setIntValue(_node->getIntValue() + _adjust_step->getIntValue());
-            break;
-        case SGValue::LONG:
-            _node->setLongValue(_node->getLongValue() + _adjust_step->getLongValue());
-            break;
-        case SGValue::FLOAT:
-            _node->setFloatValue(_node->getFloatValue()
-                                 + _adjust_step->getFloatValue());
-            break;
-        case SGValue::DOUBLE:
-        case SGValue::UNKNOWN:	// force to double
-            _node->setDoubleValue(_node->getDoubleValue()
-                                  + _adjust_step->getDoubleValue());
-            break;
-        case SGValue::STRING:
-            SG_LOG(SG_INPUT, SG_ALERT, "Cannot increment or decrement string value"
-                   << _node->getStringValue());
-            break;
-        }
-        break;
-
-    case ACTION_ASSIGN:
-        if  (_assign_value == 0) {
-            SG_LOG(SG_INPUT, SG_ALERT, "No value provided for assign binding");
-            break;
-        }
-        switch (_node->getType()) {
-        case SGValue::BOOL:
-            _node->setBoolValue(_assign_value->getBoolValue());
-            break;
-        case SGValue::INT:
-            _node->setIntValue(_assign_value->getIntValue());
-            break;
-        case SGValue::LONG:
-            _node->setLongValue(_assign_value->getLongValue());
-            break;
-        case SGValue::FLOAT:
-            _node->setFloatValue(_assign_value->getFloatValue());
-            break;
-        case SGValue::DOUBLE:
-            _node->setDoubleValue(_assign_value->getDoubleValue());
-            break;
-        case SGValue::STRING:
-            _node->setStringValue(_assign_value->getStringValue());
-            break;
-        case SGValue::UNKNOWN:
-            _node->setUnknownValue(_assign_value->getStringValue());
-            break;
-        }
-        break;
+    switch (_node->getType()) {
+    case SGValue::BOOL:
+      if (_adjust_step->getBoolValue())
+	_node->setBoolValue(!_node->getBoolValue());
+      break;
+    case SGValue::INT:
+      _node->setIntValue(_node->getIntValue() + _adjust_step->getIntValue());
+      break;
+    case SGValue::LONG:
+      _node->setLongValue(_node->getLongValue() + _adjust_step->getLongValue());
+      break;
+    case SGValue::FLOAT:
+      _node->setFloatValue(_node->getFloatValue()
+			   + _adjust_step->getFloatValue());
+      break;
+    case SGValue::DOUBLE:
+    case SGValue::UNKNOWN:	// force to double
+      _node->setDoubleValue(_node->getDoubleValue()
+			    + _adjust_step->getDoubleValue());
+      break;
+    case SGValue::STRING:
+      SG_LOG(SG_INPUT, SG_ALERT, "Cannot increment or decrement string value"
+	     << _node->getStringValue());
+      break;
     }
+    break;
+
+  case ACTION_ASSIGN:
+    if  (_assign_value == 0) {
+      SG_LOG(SG_INPUT, SG_ALERT, "No value provided for assign binding");
+      break;
+    }
+    switch (_node->getType()) {
+    case SGValue::BOOL:
+      _node->setBoolValue(_assign_value->getBoolValue());
+      break;
+    case SGValue::INT:
+      _node->setIntValue(_assign_value->getIntValue());
+      break;
+    case SGValue::LONG:
+      _node->setLongValue(_assign_value->getLongValue());
+      break;
+    case SGValue::FLOAT:
+      _node->setFloatValue(_assign_value->getFloatValue());
+      break;
+    case SGValue::DOUBLE:
+      _node->setDoubleValue(_assign_value->getDoubleValue());
+      break;
+    case SGValue::STRING:
+      _node->setStringValue(_assign_value->getStringValue());
+      break;
+    case SGValue::UNKNOWN:
+      _node->setUnknownValue(_assign_value->getStringValue());
+      break;
+    }
+    break;
+  }
 }
 
 
@@ -225,7 +225,7 @@ FGBinding::fire () const
 // Implementation of FGInput.
 ////////////////////////////////////////////////////////////////////////
 
-// From main.cxx
+				// From main.cxx
 extern void fgReshape( int width, int height );
 
 FGInput current_input;
@@ -233,102 +233,101 @@ FGInput current_input;
 
 FGInput::FGInput ()
 {
-    // no op
+  // no op
 }
 
 FGInput::~FGInput ()
 {
-    // no op
+  // no op
 }
 
 void
 FGInput::init ()
 {
-    // Read the keyboard bindings.
-    // TODO: zero the old bindings first.
-    const SGPropertyNode * keyboard =
-        globals->get_props()->getNode("/input/keyboard", true);
-    vector<const SGPropertyNode *> keys = keyboard->getChildren("key");
+				// Read the keyboard bindings.
+				// TODO: zero the old bindings first.
+  const SGPropertyNode * keyboard =
+    globals->get_props()->getNode("/input/keyboard", true);
+  vector<const SGPropertyNode *> keys = keyboard->getChildren("key");
 
-    for (unsigned int i = 0; i < keys.size(); i++) {
-        int code = keys[i]->getIndex();
-        int modifiers = FG_MOD_NONE;
-        if (keys[i]->getBoolValue("mod-shift"))
-            modifiers |= FG_MOD_SHIFT;
-        if (keys[i]->getBoolValue("mod-ctrl"))
-            modifiers |= FG_MOD_CTRL;
-        if (keys[i]->getBoolValue("mod-alt"))
-            modifiers |= FG_MOD_ALT;
+  for (unsigned int i = 0; i < keys.size(); i++) {
+    int code = keys[i]->getIntValue("code", -1);
+    int modifiers = FG_MOD_NONE;
+    if (keys[i]->getBoolValue("mod-shift"))
+      modifiers |= FG_MOD_SHIFT;
+    if (keys[i]->getBoolValue("mod-ctrl"))
+      modifiers |= FG_MOD_CTRL;
+    if (keys[i]->getBoolValue("mod-alt"))
+      modifiers |= FG_MOD_ALT;
 
-        if (code < 0) {
-            SG_LOG(SG_INPUT, SG_ALERT, "Key stroke not bound = "
-                   << keys[i]->getStringValue("name", "[unnamed]"));
-        } else {
-            SG_LOG(SG_INPUT, SG_INFO, "Binding key " << code
-                   << " with modifiers " << modifiers);
-            vector<const SGPropertyNode *> bindings =
-                keys[i]->getChildren("binding");
-            for (unsigned int j = 0; j < bindings.size(); j++) {
-                SG_LOG(SG_INPUT, SG_INFO, "  Adding binding " << j);
-                _key_bindings[modifiers][code].push_back(FGBinding(bindings[j]));
-            }
-        }
+    if (code < 0) {
+      SG_LOG(SG_INPUT, SG_ALERT, "No code provided for key "
+	     << keys[i]->getStringValue("name", "[unnamed]"));
+    } else {
+      SG_LOG(SG_INPUT, SG_INFO, "Binding key " << code
+	     << " with modifiers " << modifiers);
+      vector<const SGPropertyNode *> bindings =
+	keys[i]->getChildren("binding");
+      for (unsigned int j = 0; j < bindings.size(); j++) {
+	SG_LOG(SG_INPUT, SG_INFO, "  Adding binding " << j);
+	_key_bindings[modifiers][code].push_back(FGBinding(bindings[j]));
+      }
     }
+  }
 }
 
 void
 FGInput::bind ()
 {
-    // no op
+  // no op
 }
 
 void
 FGInput::unbind ()
 {
-    // no op
+  // no op
 }
 
 void 
 FGInput::update ()
 {
-    // we'll do something here with the joystick
+  // we'll do something here with the joystick
 }
 
 void
 FGInput::doKey (int k, int modifiers, int x, int y)
 {
-    float fov, tmp;
-    static bool winding_ccw = true;
-    int speed;
+  float fov, tmp;
+  static bool winding_ccw = true;
+  int speed;
 
-    SG_LOG(SG_INPUT, SG_INFO, "User pressed key " << k
-           << " with modifiers " << modifiers);
+  SG_LOG(SG_INPUT, SG_INFO, "User pressed key " << k
+	 << " with modifiers " << modifiers);
 
-    if (_key_bindings[modifiers].find(k) != _key_bindings[modifiers].end()) {
-        const vector<FGBinding> &bindings = _key_bindings[modifiers][k];
-        for (unsigned int i = 0; i < bindings.size(); i++) {
-            bindings[i].fire();
-        }
-        return;
-    }
+  const vector<FGBinding> * bindings = _find_bindings(k, modifiers);
+  if (bindings != 0) {
+    for (unsigned int i = 0; i < bindings->size(); i++)
+      (*bindings)[i].fire();
+    return;
+  }
 
-    SG_LOG(SG_INPUT, SG_INFO, "(No user binding.)");
+  SG_LOG(SG_INPUT, SG_INFO, "(No user binding.)");
 
-    // Use the old, default actions.
-    FGInterface *f = current_aircraft.fdm_state;
-    FGViewer *v = globals->get_current_view();
+				// Use the old, default actions.
+  FGInterface *f = current_aircraft.fdm_state;
+  FGViewer *v = globals->get_current_view();
   
-    // everything after here will be removed sooner or later...
+  // everything after here will be removed sooner or later...
 
-    if (modifiers & FG_MOD_SHIFT) {
+  if (modifiers & FG_MOD_SHIFT) {
 
 	switch (k) {
 	case 7: // Ctrl-G key
 	    current_autopilot->set_AltitudeMode( 
-                                                FGAutopilot::FG_ALTITUDE_GS1 );
+                  FGAutopilot::FG_ALTITUDE_GS1 );
 	    current_autopilot->set_AltitudeEnabled(
-                                                   ! current_autopilot->get_AltitudeEnabled()
-                                                   );
+		  ! current_autopilot->get_AltitudeEnabled()
+	        );
 	    return;
 	case 18: // Ctrl-R key
 	    // temporary
@@ -341,15 +340,15 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 	    return;
 	case 19: // Ctrl-S key
 	    current_autopilot->set_AutoThrottleEnabled(
-                                                       ! current_autopilot->get_AutoThrottleEnabled()
-                                                       );
+		  ! current_autopilot->get_AutoThrottleEnabled()
+	        );
 	    return;
 	case 20: // Ctrl-T key
 	    current_autopilot->set_AltitudeMode( 
-                                                FGAutopilot::FG_ALTITUDE_TERRAIN );
+                  FGAutopilot::FG_ALTITUDE_TERRAIN );
 	    current_autopilot->set_AltitudeEnabled(
-                                                   ! current_autopilot->get_AltitudeEnabled()
-                                                   );
+		  ! current_autopilot->get_AltitudeEnabled()
+	        );
 	    return;
 	case 49: // numeric keypad 1
 	    v->set_goal_view_offset( SGD_PI * 0.75 );
@@ -420,7 +419,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 #endif
 	    return;
 
-            // START SPECIALS
+// START SPECIALS
 
  	case 256+GLUT_KEY_F1: {
  	    ifstream input("fgfs.sav");
@@ -456,6 +455,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
             current_panel->unbind();
             delete current_panel;
             current_panel = new_panel;
+	    current_panel->bind();
             return;
 	}
 	case 256+GLUT_KEY_F4: {
@@ -529,7 +529,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 	    v->set_goal_view_offset( SGD_PI * 1.75 );
 	    return;
 
-            // END SPECIALS
+// END SPECIALS
 
 	}
 
@@ -632,7 +632,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 	    ConfirmExitDialog();
 	    return;
 
-            // START SPECIALS
+// START SPECIALS
 
 	case 256+GLUT_KEY_F2: // F2 Reload Tile Cache...
 	    {
@@ -644,8 +644,8 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 		if ( global_tile_mgr.init() ) {
 		    // Load the local scenery data
 		    global_tile_mgr.update( 
-                                           cur_fdm_state->get_Longitude() * SGD_RADIANS_TO_DEGREES,
-                                           cur_fdm_state->get_Latitude() * SGD_RADIANS_TO_DEGREES );
+		        cur_fdm_state->get_Longitude() * SGD_RADIANS_TO_DEGREES,
+			cur_fdm_state->get_Latitude() * SGD_RADIANS_TO_DEGREES );
 		} else {
 		    SG_LOG( SG_GENERAL, SG_ALERT, 
 			    "Error in Tile Manager initialization!" );
@@ -653,7 +653,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 		}
 		BusyCursor(1);
 		if ( !freeze )
-                    globals->set_freeze( false );
+		   globals->set_freeze( false );
 		return;
 	    }
 	case 256+GLUT_KEY_F3: // F3 Take a screen shot
@@ -666,28 +666,28 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 	    if ( current_autopilot->get_HeadingMode() !=
 		 FGAutopilot::FG_HEADING_WAYPOINT ) {
 		current_autopilot->set_HeadingMode(
-                                                   FGAutopilot::FG_HEADING_WAYPOINT );
+		    FGAutopilot::FG_HEADING_WAYPOINT );
 		current_autopilot->set_HeadingEnabled( true );
 	    } else {
 		current_autopilot->set_HeadingMode(
-                                                   FGAutopilot::FG_TC_HEADING_LOCK );
+		    FGAutopilot::FG_TC_HEADING_LOCK );
 	    }
 	    return;
 	case 256+GLUT_KEY_F8: {// F8 toggles fog ... off fastest nicest...
 	    const string &fog = fgGetString("/sim/rendering/fog");
 	    if (fog == "disabled") {
-                fgSetString("/sim/rendering/fog", "fastest");
-                SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=fastest");
+	      fgSetString("/sim/rendering/fog", "fastest");
+	      SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=fastest");
 	    } else if (fog == "fastest") {
-                fgSetString("/sim/rendering/fog", "nicest");
-                SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=nicest");
+	      fgSetString("/sim/rendering/fog", "nicest");
+	      SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=nicest");
 	    } else if (fog == "nicest") {
-                fgSetString("/sim/rendering/fog", "disabled");
-                SG_LOG(SG_INPUT, SG_INFO, "Fog disabled");
+	      fgSetString("/sim/rendering/fog", "disabled");
+	      SG_LOG(SG_INPUT, SG_INFO, "Fog disabled");
 	    } else {
-                fgSetString("/sim/rendering/fog", "disabled");
-                SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized fog type "
-                       << fog << ", changed to 'disabled'");
+	      fgSetString("/sim/rendering/fog", "disabled");
+	      SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized fog type "
+		     << fog << ", changed to 'disabled'");
 	    }
  	    return;
 	}
@@ -715,7 +715,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 	    return;
 	}
 
-        // END SPECIALS
+// END SPECIALS
 
     }
 }
@@ -724,112 +724,128 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 void
 FGInput::action (const SGPropertyNode * binding)
 {
-    const string &action = binding->getStringValue("action", "");
-    const string &control = binding->getStringValue("control", "");
-    bool repeatable = binding->getBoolValue("repeatable", false);
-    int step = binding->getIntValue("step", 0.0);
+  const string &action = binding->getStringValue("action", "");
+  const string &control = binding->getStringValue("control", "");
+  bool repeatable = binding->getBoolValue("repeatable", false);
+  int step = binding->getIntValue("step", 0.0);
 
-    if (control == "") {
-        SG_LOG(SG_INPUT, SG_ALERT, "No control specified for key "
-               << binding->getIndex());
-        return;
-    }
+  if (control == "") {
+    SG_LOG(SG_INPUT, SG_ALERT, "No control specified for key "
+	   << binding->getIndex());
+    return;
+  }
 
-    else if (action == "") {
-        SG_LOG(SG_INPUT, SG_ALERT, "No action specified for key "
-               << binding->getIndex());
-        return;
-    }
+  else if (action == "") {
+    SG_LOG(SG_INPUT, SG_ALERT, "No action specified for key "
+	   << binding->getIndex());
+    return;
+  }
 
-    else if (action == "switch") {
-        fgSetBool(control, !fgGetBool(control));
-    }
+  else if (action == "switch") {
+    fgSetBool(control, !fgGetBool(control));
+  }
 
-    else if (action == "adjust") {
-        const SGValue * step = binding->getValue("step");
-        if (step == 0) {
-            SG_LOG(SG_INPUT, SG_ALERT, "No step supplied for adjust action for key "
-                   << binding->getIndex());
-            return;
-        }
-        SGValue * target = fgGetValue(control, true);
-        // Use the target's type...
-        switch (target->getType()) {
-        case SGValue::BOOL:
-        case SGValue::INT:
-            target->setIntValue(target->getIntValue() + step->getIntValue());
-            break;
-        case SGValue::LONG:
-            target->setLongValue(target->getLongValue() + step->getLongValue());
-            break;
-        case SGValue::FLOAT:
-            target->setFloatValue(target->getFloatValue() + step->getFloatValue());
-            break;
-        case SGValue::DOUBLE:
-        case SGValue::UNKNOWN:	// treat unknown as a double
-            target->setDoubleValue(target->getDoubleValue()
-                                   + step->getDoubleValue());
-            break;
-        case SGValue::STRING:
-            SG_LOG(SG_INPUT, SG_ALERT, "Failed attempt to adjust string property "
-                   << control);
-            break;
-        }
+  else if (action == "adjust") {
+    const SGValue * step = binding->getValue("step");
+    if (step == 0) {
+      SG_LOG(SG_INPUT, SG_ALERT, "No step supplied for adjust action for key "
+	     << binding->getIndex());
+      return;
     }
+    SGValue * target = fgGetValue(control, true);
+				// Use the target's type...
+    switch (target->getType()) {
+    case SGValue::BOOL:
+    case SGValue::INT:
+      target->setIntValue(target->getIntValue() + step->getIntValue());
+      break;
+    case SGValue::LONG:
+      target->setLongValue(target->getLongValue() + step->getLongValue());
+      break;
+    case SGValue::FLOAT:
+      target->setFloatValue(target->getFloatValue() + step->getFloatValue());
+      break;
+    case SGValue::DOUBLE:
+    case SGValue::UNKNOWN:	// treat unknown as a double
+      target->setDoubleValue(target->getDoubleValue()
+			     + step->getDoubleValue());
+      break;
+    case SGValue::STRING:
+      SG_LOG(SG_INPUT, SG_ALERT, "Failed attempt to adjust string property "
+	     << control);
+      break;
+    }
+  }
 
-    else if (action == "assign") {
-        const SGValue * value = binding->getValue("value");
-        if (value == 0) {
-            SG_LOG(SG_INPUT, SG_ALERT, "No value supplied for assign action for key "
-                   << binding->getIndex());
-            return;
-        }
-        SGValue * target = fgGetValue(control, true);
-        // Use the target's type...
-        switch (target->getType()) {
-        case SGValue::BOOL:
-            target->setBoolValue(value->getBoolValue());
-            break;
-        case SGValue::INT:
-            target->setIntValue(value->getIntValue());
-            break;
-        case SGValue::LONG:
-            target->setLongValue(value->getLongValue());
-            break;
-        case SGValue::FLOAT:
-            target->setFloatValue(value->getFloatValue());
-            break;
-        case SGValue::DOUBLE:
-            target->setDoubleValue(value->getDoubleValue());
-            break;
-        case SGValue::STRING:
-            target->setStringValue(value->getStringValue());
-            break;
-        case SGValue::UNKNOWN:
-            target->setUnknownValue(value->getStringValue());
-            break;
-        }
+  else if (action == "assign") {
+    const SGValue * value = binding->getValue("value");
+    if (value == 0) {
+      SG_LOG(SG_INPUT, SG_ALERT, "No value supplied for assign action for key "
+	     << binding->getIndex());
+      return;
     }
+    SGValue * target = fgGetValue(control, true);
+				// Use the target's type...
+    switch (target->getType()) {
+    case SGValue::BOOL:
+      target->setBoolValue(value->getBoolValue());
+      break;
+    case SGValue::INT:
+      target->setIntValue(value->getIntValue());
+      break;
+    case SGValue::LONG:
+      target->setLongValue(value->getLongValue());
+      break;
+    case SGValue::FLOAT:
+      target->setFloatValue(value->getFloatValue());
+      break;
+    case SGValue::DOUBLE:
+      target->setDoubleValue(value->getDoubleValue());
+      break;
+    case SGValue::STRING:
+      target->setStringValue(value->getStringValue());
+      break;
+    case SGValue::UNKNOWN:
+      target->setUnknownValue(value->getStringValue());
+      break;
+    }
+  }
 
-    else {
-        SG_LOG(SG_INPUT, SG_ALERT, "Unknown action " << action
-               << " for key " << binding->getIndex());
-    }
+  else {
+    SG_LOG(SG_INPUT, SG_ALERT, "Unknown action " << action
+	   << " for key " << binding->getIndex());
+  }
 }
 
 
-#if 0
-FGViewer *v = globals->get_current_view();
+const vector<FGBinding> *
+FGInput::_find_bindings (int k, int modifiers)
+{
+  keyboard_map::const_iterator it = _key_bindings[modifiers].find(k);
 
-SG_LOG( SG_INPUT, SG_DEBUG, "Special key hit = " << k );
+				// Try it straight, first.
+  if (it != _key_bindings[modifiers].end())
+    return &(_key_bindings[modifiers][k]);
 
-if ( GLUT_ACTIVE_SHIFT && glutGetModifiers() ) {
-    SG_LOG( SG_INPUT, SG_DEBUG, " SHIFTED" );
-    switch (k)
-        } else
-        }
+				// Try removing the control modifier
+				// for control keys.
+  else if ((modifiers&FG_MOD_CTRL) && iscntrl(k))
+    return _find_bindings(k, modifiers&~FG_MOD_CTRL);
 
-#endif
+				// Try removing shift modifier 
+				// for upper case or any punctuation
+				// (since different keyboards will
+				// shift different punctuation types)
+  else if ((modifiers&FG_MOD_SHIFT) && (isupper(k) || ispunct(k)))
+    return _find_bindings(k, modifiers&~FG_MOD_SHIFT);
 
+				// Try removing alt modifier for
+				// high-bit characters.
+  else if ((modifiers&FG_MOD_ALT) && k >= 128 && k < 256)
+    return _find_bindings(k, modifiers&~FG_MOD_ALT);
+
+  else
+    return 0;
+}
 
 // end of input.cxx