]> git.mxchange.org Git - flightgear.git/commitdiff
1. Fixed FGInput bug preventing same key from being bound separately
authorcurt <curt>
Tue, 29 May 2001 22:31:04 +0000 (22:31 +0000)
committercurt <curt>
Tue, 29 May 2001 22:31:04 +0000 (22:31 +0000)
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
src/Cockpit/panel.hxx
src/Input/input.cxx

index 6825dca4ea4aba53f27daac554c54399837725ed..e0cf55d9ec11698281db556df1c16c952dd26176 100644 (file)
@@ -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;
 }
 
 
index bcc9c5959bdbfa6a90d47e29aba0ad49a62e01ed..2fed9bc08982ea0a9366684029d6fc83250f799a 100644 (file)
@@ -180,6 +180,7 @@ private:
   int _x_offset;
   int _y_offset;
   int _view_height;
+  bool _bound;
   
   ssgTexture * _bg;
                                // List of instruments in panel.
index f3dcdb756afbc885836ef3e2d4c4cb6467cb04ba..b45e1b20dc2893b03cfc5b9abfd66d18b8028f70 100644 (file)
@@ -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("control"))
-        _node = fgGetNode(node->getStringValue("control"), true);
-
-    if (node->hasValue("step"))
-        _adjust_step = node->getChild("step")->getValue();
-
-    if (node->hasValue("value"))
-        _assign_value = node->getChild("value")->getValue();
+  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("step"))
+    _adjust_step = node->getChild("step")->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) {
+  switch (_action) {
 
-    case ACTION_NONE:
-        break;
+  case ACTION_NONE:
+    break;
 
-    case ACTION_SWITCH:
-        _node->setBoolValue(!_node->getBoolValue());
-        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_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;
+  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");
-
-    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;
-
-        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]));
-            }
-        }
+                               // 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]->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, "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);
-
-    if (control == "") {
-        SG_LOG(SG_INPUT, SG_ALERT, "No control specified for key "
-               << binding->getIndex());
-        return;
+  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;
+  }
+
+  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 == "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;
     }
-
-    else if (action == "") {
-        SG_LOG(SG_INPUT, SG_ALERT, "No action specified 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 == "switch") {
-        fgSetBool(control, !fgGetBool(control));
+  }
+
+  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;
     }
-
-    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;
-        }
+    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();
-
-SG_LOG( SG_INPUT, SG_DEBUG, "Special key hit = " << k );
-
-if ( GLUT_ACTIVE_SHIFT && glutGetModifiers() ) {
-    SG_LOG( SG_INPUT, SG_DEBUG, " SHIFTED" );
-    switch (k)
-        } else
-        }
-
-#endif
-
+const vector<FGBinding> *
+FGInput::_find_bindings (int k, int modifiers)
+{
+  keyboard_map::const_iterator it = _key_bindings[modifiers].find(k);
+
+                               // Try it straight, first.
+  if (it != _key_bindings[modifiers].end())
+    return &(_key_bindings[modifiers][k]);
+
+                               // Try removing the control modifier
+                               // for control keys.
+  else if ((modifiers&FG_MOD_CTRL) && iscntrl(k))
+    return _find_bindings(k, modifiers&~FG_MOD_CTRL);
+
+                               // 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