]> git.mxchange.org Git - flightgear.git/blobdiff - src/Joystick/joystick.cxx
Fixes to jsbsim.
[flightgear.git] / src / Joystick / joystick.cxx
index 37d7102174c7e213f6e7f1842eda8f648518ad52..b0daf424bccb1864175d9abfae8347b45f128bc3 100644 (file)
@@ -30,6 +30,8 @@
 #  include <windows.h>                     
 #endif
 
+#include <math.h>
+
 #include <string>
 
 #include <simgear/misc/props.hxx>
 
 using std::string;
 
+#ifdef WIN32
+static const int MAX_JOYSTICKS = 2;
+#else
 static const int MAX_JOYSTICKS = 10;
-static const int MAX_AXES = 10;
+#endif
+static const int MAX_AXES = _JS_MAX_AXES;
 static const int MAX_BUTTONS = 10;
 
 
@@ -48,16 +54,16 @@ static const int MAX_BUTTONS = 10;
  * Property names for joysticks and axes.
  */
 static const char * jsNames[] = {
-  "js0", "js1", "js2", "js3", "js4",
-  "js5", "js6", "js7", "js8", "js9"
+    "js0", "js1", "js2", "js3", "js4",
+    "js5", "js6", "js7", "js8", "js9"
 };
 static const char * axisNames[] = {
-  "axis0", "axis1", "axis2", "axis3", "axis4",
-  "axis5", "axis6", "axis7", "axis8", "axis9"
+    "axis0", "axis1", "axis2", "axis3", "axis4",
+    "axis5", "axis6", "axis7", "axis8", "axis9"
 };
 static const char * buttonNames[] = {
-  "button0", "button1", "button2", "button3", "button4",
-  "button5", "button6", "button7", "button8", "button9"
+    "button0", "button1", "button2", "button3", "button4",
+    "button5", "button6", "button7", "button8", "button9"
 };
 
 
@@ -65,13 +71,13 @@ static const char * buttonNames[] = {
  * Settings for a single axis.
  */
 struct axis {
-  axis () : value(0), offset(0.0), factor(1.0),
-           last_value(9999999), tolerance(0.002) {}
-  SGValue * value;
-  float offset;
-  float factor;
-  float last_value;
-  float tolerance;
+    axis () : value(0), offset(0.0), factor(1.0),
+       last_value(9999999), tolerance(0.002) {}
+    SGValue * value;
+    float offset;
+    float factor;
+    float last_value;
+    float tolerance;
 };
 
 
@@ -79,18 +85,18 @@ struct axis {
  * Settings for a single button.
  */
 struct button {
-  enum Action {
-    TOGGLE,
-    SWITCH,
-    ADJUST
-  };
-  button () : value(0), step(0.0), action(ADJUST), isRepeatable(true),
-             lastState(-1) {}
-  SGValue * value;
-  float step;
-  Action action;
-  bool isRepeatable;
-  int lastState;
+    enum Action {
+       TOGGLE,
+       SWITCH,
+       ADJUST
+    };
+    button () : value(0), step(0.0), action(ADJUST), isRepeatable(true),
+       lastState(-1) {}
+    SGValue * value;
+    float step;
+    Action action;
+    bool isRepeatable;
+    int lastState;
 };
 
 
@@ -98,10 +104,16 @@ struct button {
  * Settings for a single joystick.
  */
 struct joystick {
-  virtual ~joystick () { delete js; delete axes; }
-  jsJoystick * js;
-  axis * axes;
-  button * buttons;
+    virtual ~joystick () {
+       delete js;
+       delete axes;
+       delete buttons;
+    }
+    int naxes;
+    int nbuttons;
+    jsJoystick * js;
+    axis * axes;
+    button * buttons;
 };
 
 
@@ -117,91 +129,92 @@ static joystick joysticks[MAX_JOYSTICKS];
 static void
 setupDefaults ()
 {
-  SGPropertyList &props = current_properties;
-
-                               // Default axis 0 to aileron
-  if (!props.getValue("/input/js0/axis0/control")) {
-    props.setStringValue("/input/js0/axis0/control", "/controls/aileron");
-    props.setFloatValue("/input/js0/axis0/dead-band", 0.1);
-  }
-
-                               // Default axis 1 to elevator
-  if (!props.getValue("/input/js0/axis1/control")) {
-    props.setStringValue("/input/js0/axis1/control", "/controls/elevator");
-    props.setFloatValue("/input/js0/axis1/dead-band", 0.1);
-    props.setFloatValue("/input/js0/axis1/factor", -1.0);
-  }
-
-                               // Default axis 2 to throttle
-                               // We need to fiddle with the offset
-                               // and factor to make it work
-  if (!props.getValue("/input/js0/axis2/control")) {
-    props.setStringValue("/input/js0/axis2/control", "/controls/throttle");
-    props.setFloatValue("/input/js0/axis2/dead-band", 0.0);
-    props.setFloatValue("/input/js0/axis2/offset", -1.0);
-    props.setFloatValue("/input/js0/axis2/factor", -0.5);
-  }
-
-                               // Default axis 3 to rudder
-  if (!props.getValue("/input/js0/axis3/control")) {
-    props.setStringValue("/input/js0/axis3/control", "/controls/rudder");
-    props.setFloatValue("/input/js0/axis3/dead-band", 0.3);
-  }
-
-                               // Default button 0 to all brakes
-  if (!props.getValue("/input/js0/button0/control")) {
-    props.setStringValue("/input/js0/button0/action", "switch");
-    props.setStringValue("/input/js0/button0/control", "/controls/brake");
-    props.setFloatValue("/input/js0/button0/step", 1.0);
-    props.setFloatValue("/input/js0/button0/repeatable", false);
-  }
-
-                               // Default button 1 to left brake.
-  if (!props.getValue("/input/js0/button1/control")) {
-    props.setStringValue("/input/js0/button1/action", "switch");
-    props.setStringValue("/input/js0/button1/control", "/controls/left-brake");
-    props.setFloatValue("/input/js0/button1/step", 1.0);
-    props.setFloatValue("/input/js0/button1/repeatable", false);
-  }
-
-                               // Default button 2 to right brake.
-  if (!props.getValue("/input/js0/button2/control")) {
-    props.setStringValue("/input/js0/button2/action", "switch");
-    props.setStringValue("/input/js0/button2/control",
-                        "/controls/right-brake");
-    props.setFloatValue("/input/js0/button2/step", 1.0);
-    props.setFloatValue("/input/js0/button2/repeatable", false);
-  }
-
-                               // Default buttons 3 and 4 to elevator trim
-  if (!props.getValue("/input/js0/button3/control")) {
-    props.setStringValue("/input/js0/button3/action", "adjust");
-    props.setStringValue("/input/js0/button3/control",
-                        "/controls/elevator-trim");
-    props.setFloatValue("/input/js0/button3/step", 0.001);
-    props.setBoolValue("/input/js0/button3/repeatable", true);
-  }
-  if (!props.getValue("/input/js0/button4/control")) {
-    props.setStringValue("/input/js0/button4/action", "adjust");
-    props.setStringValue("/input/js0/button4/control",
-                        "/controls/elevator-trim");
-    props.setFloatValue("/input/js0/button4/step", -0.001);
-    props.setBoolValue("/input/js0/button4/repeatable", true);
-  }
-
-                               // Default buttons 5 and 6 to flaps
-  if (!props.getValue("/input/js0/button5/control")) {
-    props.setStringValue("/input/js0/button5/action", "adjust");
-    props.setStringValue("/input/js0/button5/control", "/controls/flaps");
-    props.setFloatValue("/input/js0/button5/step", -0.34);
-    props.setBoolValue("/input/js0/button5/repeatable", false);
-  }
-  if (!props.getValue("/input/js0/button6/control")) {
-    props.setStringValue("/input/js0/button6/action", "adjust");
-    props.setStringValue("/input/js0/button6/control", "/controls/flaps");
-    props.setFloatValue("/input/js0/button6/step", 0.34);
-    props.setBoolValue("/input/js0/button6/repeatable", false);
-  }
+    SGPropertyList &props = current_properties;
+
+    // Default axis 0 to aileron
+    if (!props.getValue("/input/js0/axis0/control")) {
+       props.setStringValue("/input/js0/axis0/control", "/controls/aileron");
+       props.setDoubleValue("/input/js0/axis0/dead-band", 0.1);
+    }
+
+    // Default axis 1 to elevator
+    if (!props.getValue("/input/js0/axis1/control")) {
+       props.setStringValue("/input/js0/axis1/control", "/controls/elevator");
+       props.setDoubleValue("/input/js0/axis1/dead-band", 0.1);
+       props.setDoubleValue("/input/js0/axis1/factor", -1.0);
+    }
+
+    // Default axis 2 to rudder
+    if (!props.getValue("/input/js0/axis2/control")) {
+       props.setStringValue("/input/js0/axis2/control", "/controls/rudder");
+       props.setDoubleValue("/input/js0/axis2/dead-band", 0.1);
+    }
+
+    // Default axis 3 to throttle
+    // We need to fiddle with the offset
+    // and factor to make it work
+    if (!props.getValue("/input/js0/axis3/control")) {
+       props.setStringValue("/input/js0/axis3/control", "/controls/throttle");
+       props.setDoubleValue("/input/js0/axis3/dead-band", 0.0);
+       props.setDoubleValue("/input/js0/axis3/offset", -1.0);
+       props.setDoubleValue("/input/js0/axis3/factor", -0.5);
+    }
+
+    // Default button 0 to all brakes
+    if (!props.getValue("/input/js0/button0/control")) {
+       props.setStringValue("/input/js0/button0/action", "switch");
+       props.setStringValue("/input/js0/button0/control", "/controls/brakes/all");
+       props.setDoubleValue("/input/js0/button0/step", 1.0);
+       props.setDoubleValue("/input/js0/button0/repeatable", false);
+    }
+
+    // Default button 1 to left brake.
+    if (!props.getValue("/input/js0/button1/control")) {
+       props.setStringValue("/input/js0/button1/action", "switch");
+       props.setStringValue("/input/js0/button1/control",
+                            "/controls/brakes/left");
+       props.setDoubleValue("/input/js0/button1/step", 1.0);
+       props.setDoubleValue("/input/js0/button1/repeatable", false);
+    }
+
+    // Default button 2 to right brake.
+    if (!props.getValue("/input/js0/button2/control")) {
+       props.setStringValue("/input/js0/button2/action", "switch");
+       props.setStringValue("/input/js0/button2/control",
+                            "/controls/brakes/right");
+       props.setDoubleValue("/input/js0/button2/step", 1.0);
+       props.setDoubleValue("/input/js0/button2/repeatable", false);
+    }
+
+    // Default buttons 3 and 4 to elevator trim
+    if (!props.getValue("/input/js0/button3/control")) {
+       props.setStringValue("/input/js0/button3/action", "adjust");
+       props.setStringValue("/input/js0/button3/control",
+                            "/controls/elevator-trim");
+       props.setDoubleValue("/input/js0/button3/step", 0.001);
+       props.setBoolValue("/input/js0/button3/repeatable", true);
+    }
+    if (!props.getValue("/input/js0/button4/control")) {
+       props.setStringValue("/input/js0/button4/action", "adjust");
+       props.setStringValue("/input/js0/button4/control",
+                            "/controls/elevator-trim");
+       props.setDoubleValue("/input/js0/button4/step", -0.001);
+       props.setBoolValue("/input/js0/button4/repeatable", true);
+    }
+
+    // Default buttons 5 and 6 to flaps
+    if (!props.getValue("/input/js0/button5/control")) {
+       props.setStringValue("/input/js0/button5/action", "adjust");
+       props.setStringValue("/input/js0/button5/control", "/controls/flaps");
+       props.setDoubleValue("/input/js0/button5/step", -0.34);
+       props.setBoolValue("/input/js0/button5/repeatable", false);
+    }
+    if (!props.getValue("/input/js0/button6/control")) {
+       props.setStringValue("/input/js0/button6/action", "adjust");
+       props.setStringValue("/input/js0/button6/control", "/controls/flaps");
+       props.setDoubleValue("/input/js0/button6/step", 0.34);
+       props.setBoolValue("/input/js0/button6/repeatable", false);
+    }
 }
 
 
@@ -211,209 +224,220 @@ setupDefaults ()
 int
 fgJoystickInit() 
 {
-  bool seen_joystick = false;
+    bool seen_joystick = false;
 
-  FG_LOG(FG_INPUT, FG_INFO, "Initializing joysticks");
+    FG_LOG(FG_INPUT, FG_INFO, "Initializing joysticks");
 
-  setupDefaults();
-
-  for (int i = 0; i < MAX_JOYSTICKS; i++) {
-    jsJoystick * js = new jsJoystick(i);
-    joysticks[i].js = js;
-    if (js->notWorking()) {
-      FG_LOG(FG_INPUT, FG_INFO, "Joystick " << i << " not found");
-      continue;
-    }
+    setupDefaults();
 
-    FG_LOG(FG_INPUT, FG_INFO, "Initializing joystick " << i);
-    seen_joystick = true;
-
-                               // Set up range arrays
-    float minRange[js->getNumAxes()];
-    float maxRange[js->getNumAxes()];
-    float center[js->getNumAxes()];
-
-                               // Initialize with default values
-    js->getMinRange(minRange);
-    js->getMaxRange(maxRange);
-    js->getCenter(center);
-
-                               // Allocate axes and buttons
-    joysticks[i].axes = new axis[js->getNumAxes()];
-    joysticks[i].buttons = new button[MAX_BUTTONS];
-
-
-    //
-    // Initialize the axes.
-    //
-    for (int j = 0; j < min(js->getNumAxes(), MAX_AXES); j++) {
-      axis &a = joysticks[i].axes[j];
-
-      string base = "/input/";
-      base += jsNames[i];
-      base += '/';
-      base += axisNames[j];
-      FG_LOG(FG_INPUT, FG_INFO, "  Axis " << j << ':');
-
-                               // Control property
-      string name = base;
-      name += "/control";
-      SGValue * value = current_properties.getValue(name);
-      if (value == 0) {
-       FG_LOG(FG_INPUT, FG_INFO, "    no control defined");
-       continue;
-      }
-      const string &control = value->getStringValue();
-      a.value = current_properties.getValue(control, true);
-      FG_LOG(FG_INPUT, FG_INFO, "    using control " << control);
-
-                               // Dead band
-      name = base;
-      name += "/dead-band";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       js->setDeadBand(j, value->getFloatValue());
-      FG_LOG(FG_INPUT, FG_INFO, "    dead-band is " << js->getDeadBand(j));
-
-                               // Offset
-      name = base;
-      name += "/offset";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       a.offset = value->getFloatValue();
-      FG_LOG(FG_INPUT, FG_INFO, "    offset is " << a.offset);
-
-
-                               // Factor
-      name = base;
-      name += "/factor";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       a.factor = value->getFloatValue();
-      FG_LOG(FG_INPUT, FG_INFO, "    factor is " << a.factor);
-
-
-                               // Tolerance
-      name = base;
-      name += "/tolerance";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       a.tolerance = value->getFloatValue();
-      FG_LOG(FG_INPUT, FG_INFO, "    tolerance is " << a.tolerance);
-
-
-                               // Saturation
-      name = base;
-      name += "/saturation";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       js->setSaturation(j, value->getFloatValue());
-      FG_LOG(FG_INPUT, FG_INFO, "    saturation is " << js->getSaturation(j));
-
-                               // Minimum range
-      name = base;
-      name += "/min-range";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       minRange[j] = value->getFloatValue();
-      FG_LOG(FG_INPUT, FG_INFO, "    min-range is " << minRange[j]);
-
-                               // Maximum range
-      name = base;
-      name += "/max-range";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       maxRange[j] = value->getFloatValue();
-      FG_LOG(FG_INPUT, FG_INFO, "    max-range is " << maxRange[j]);
-
-                               // Center
-      name = base;
-      name += "/center";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       center[j] = value->getFloatValue();
-      FG_LOG(FG_INPUT, FG_INFO, "    center is " << center[j]);
-    }
+    for (int i = 0; i < MAX_JOYSTICKS; i++) {
+       jsJoystick * js = new jsJoystick(i);
+       joysticks[i].js = js;
+       if (js->notWorking()) {
+           FG_LOG(FG_INPUT, FG_INFO, "Joystick " << i << " not found");
+           continue;
+       }
+#ifdef WIN32
+       JOYCAPS jsCaps ;
+       joyGetDevCaps( i, &jsCaps, sizeof(jsCaps) );
+       int nbuttons = jsCaps.wNumButtons;
+#else
+       int nbuttons = MAX_BUTTONS;
+#endif
+       
+       int naxes = js->getNumAxes();
+       joysticks[i].naxes = naxes;
+       joysticks[i].nbuttons = nbuttons;
+
+       FG_LOG(FG_INPUT, FG_INFO, "Initializing joystick " << i);
+       seen_joystick = true;
+
+       // Set up range arrays
+       float minRange[naxes];
+       float maxRange[naxes];
+       float center[naxes];
+
+       // Initialize with default values
+       js->getMinRange(minRange);
+       js->getMaxRange(maxRange);
+       js->getCenter(center);
+
+       // Allocate axes and buttons
+       joysticks[i].axes = new axis[naxes];
+       joysticks[i].buttons = new button[nbuttons];
+
+
+       //
+       // Initialize the axes.
+       //
+       for (int j = 0; j < naxes; j++) {
+           axis &a = joysticks[i].axes[j];
+
+           string base = "/input/";
+           base += jsNames[i];
+           base += '/';
+           base += axisNames[j];
+           FG_LOG(FG_INPUT, FG_INFO, "  Axis " << j << ':');
+
+           // Control property
+           string name = base;
+           name += "/control";
+           SGValue * value = current_properties.getValue(name);
+           if (value == 0) {
+               FG_LOG(FG_INPUT, FG_INFO, "    no control defined");
+               continue;
+           }
+           const string &control = value->getStringValue();
+           a.value = current_properties.getValue(control, true);
+           FG_LOG(FG_INPUT, FG_INFO, "    using control " << control);
+
+           // Dead band
+           name = base;
+           name += "/dead-band";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               js->setDeadBand(j, value->getDoubleValue());
+           FG_LOG(FG_INPUT, FG_INFO, "    dead-band is " << js->getDeadBand(j));
+
+           // Offset
+           name = base;
+           name += "/offset";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               a.offset = value->getDoubleValue();
+           FG_LOG(FG_INPUT, FG_INFO, "    offset is " << a.offset);
+
+
+           // Factor
+           name = base;
+           name += "/factor";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               a.factor = value->getDoubleValue();
+           FG_LOG(FG_INPUT, FG_INFO, "    factor is " << a.factor);
+
+
+           // Tolerance
+           name = base;
+           name += "/tolerance";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               a.tolerance = value->getDoubleValue();
+           FG_LOG(FG_INPUT, FG_INFO, "    tolerance is " << a.tolerance);
+
+
+           // Saturation
+           name = base;
+           name += "/saturation";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               js->setSaturation(j, value->getDoubleValue());
+           FG_LOG(FG_INPUT, FG_INFO, "    saturation is " << js->getSaturation(j));
+
+           // Minimum range
+           name = base;
+           name += "/min-range";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               minRange[j] = value->getDoubleValue();
+           FG_LOG(FG_INPUT, FG_INFO, "    min-range is " << minRange[j]);
+
+           // Maximum range
+           name = base;
+           name += "/max-range";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               maxRange[j] = value->getDoubleValue();
+           FG_LOG(FG_INPUT, FG_INFO, "    max-range is " << maxRange[j]);
+
+           // Center
+           name = base;
+           name += "/center";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               center[j] = value->getDoubleValue();
+           FG_LOG(FG_INPUT, FG_INFO, "    center is " << center[j]);
+       }
 
 
-    //
-    // Initialize the buttons.
-    //
-    for (int j = 0; j < MAX_BUTTONS; j++) {
-      button &b = joysticks[i].buttons[j];
+       //
+       // Initialize the buttons.
+       //
+       for (int j = 0; j < nbuttons; j++) {
+           button &b = joysticks[i].buttons[j];
       
-      string base = "/input/";
-      base += jsNames[i];
-      base += '/';
-      base += buttonNames[j];
-      FG_LOG(FG_INPUT, FG_INFO, "  Button " << j << ':');
-
-                               // Control property
-      string name = base;
-      name += "/control";
-      cout << "Trying name " << name << endl;
-      SGValue * value = current_properties.getValue(name);
-      if (value == 0) {
-       FG_LOG(FG_INPUT, FG_INFO, "    no control defined");
-       continue;
-      }
-      const string &control = value->getStringValue();
-      b.value = current_properties.getValue(control, true);
-      FG_LOG(FG_INPUT, FG_INFO, "    using control " << control);
-
-                               // Step
-      name = base;
-      name += "/step";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       b.step = value->getFloatValue();
-      FG_LOG(FG_INPUT, FG_INFO, "    step is " << b.step);
-
-                               // Type
-      name = base;
-      name += "/action";
-      value = current_properties.getValue(name);
-      string action = "adjust";
-      if (value != 0)
-       action = value->getStringValue();
-      if (action == "toggle") {
-       b.action = button::TOGGLE;
-       b.isRepeatable = false;
-      } else if (action == "switch") {
-       b.action = button::SWITCH;
-       b.isRepeatable = false;
-      } else if (action == "adjust") {
-       b.action = button::ADJUST;
-       b.isRepeatable = true;
-      } else {
-       FG_LOG(FG_INPUT, FG_ALERT, "    unknown action " << action);
-       action = "adjust";
-       b.action = button::ADJUST;
-       b.isRepeatable = true;
-      }
-      FG_LOG(FG_INPUT, FG_INFO, "    action is " << action);
-
-                               // Repeatability.
-      name = base;
-      name += "/repeatable";
-      value = current_properties.getValue(name);
-      if (value != 0)
-       b.isRepeatable = value->getBoolValue();
-      FG_LOG(FG_INPUT, FG_INFO, (b.isRepeatable ?
-            "    repeatable" : "    not repeatable"));
-    }
+           string base = "/input/";
+           base += jsNames[i];
+           base += '/';
+           base += buttonNames[j];
+           FG_LOG(FG_INPUT, FG_INFO, "  Button " << j << ':');
+
+           // Control property
+           string name = base;
+           name += "/control";
+           cout << "Trying name " << name << endl;
+           SGValue * value = current_properties.getValue(name);
+           if (value == 0) {
+               FG_LOG(FG_INPUT, FG_INFO, "    no control defined");
+               continue;
+           }
+           const string &control = value->getStringValue();
+           b.value = current_properties.getValue(control, true);
+           FG_LOG(FG_INPUT, FG_INFO, "    using control " << control);
+
+           // Step
+           name = base;
+           name += "/step";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               b.step = value->getDoubleValue();
+           FG_LOG(FG_INPUT, FG_INFO, "    step is " << b.step);
+
+           // Type
+           name = base;
+           name += "/action";
+           value = current_properties.getValue(name);
+           string action = "adjust";
+           if (value != 0)
+               action = value->getStringValue();
+           if (action == "toggle") {
+               b.action = button::TOGGLE;
+               b.isRepeatable = false;
+           } else if (action == "switch") {
+               b.action = button::SWITCH;
+               b.isRepeatable = false;
+           } else if (action == "adjust") {
+               b.action = button::ADJUST;
+               b.isRepeatable = true;
+           } else {
+               FG_LOG(FG_INPUT, FG_ALERT, "    unknown action " << action);
+               action = "adjust";
+               b.action = button::ADJUST;
+               b.isRepeatable = true;
+           }
+           FG_LOG(FG_INPUT, FG_INFO, "    action is " << action);
+
+           // Repeatability.
+           name = base;
+           name += "/repeatable";
+           value = current_properties.getValue(name);
+           if (value != 0)
+               b.isRepeatable = value->getBoolValue();
+           FG_LOG(FG_INPUT, FG_INFO, (b.isRepeatable ?
+                                      "    repeatable" : "    not repeatable"));
+       }
 
-    js->setMinRange(minRange);
-    js->setMaxRange(maxRange);
-    js->setCenter(center);
-  }
+       js->setMinRange(minRange);
+       js->setMaxRange(maxRange);
+       js->setCenter(center);
+    }
 
-  if (seen_joystick)
-    FG_LOG(FG_INPUT, FG_INFO, "Done initializing joysticks");
-  else
-    FG_LOG(FG_INPUT, FG_ALERT, "No joysticks detected");
+    if (seen_joystick)
+       FG_LOG(FG_INPUT, FG_INFO, "Done initializing joysticks");
+    else
+       FG_LOG(FG_INPUT, FG_ALERT, "No joysticks detected");
 
-  return seen_joystick;
+    return seen_joystick;
 }
 
 
@@ -423,112 +447,112 @@ fgJoystickInit()
 int
 fgJoystickRead()
 {
-  int buttons;
+    int buttons;
 
-  for (int i = 0; i < MAX_JOYSTICKS; i++) {
-    jsJoystick * js = joysticks[i].js;
-    float axis_values[js->getNumAxes()];
-    if (js->notWorking()) {
-      continue;
-    }
+    for (int i = 0; i < MAX_JOYSTICKS; i++) {
+       jsJoystick * js = joysticks[i].js;
+       float axis_values[joysticks[i].naxes];
+       if (js->notWorking()) {
+           continue;
+       }
 
-    js->read(&buttons, axis_values);
-
-    //
-    // Axes
-    //
-    for (int j = 0; j < min(MAX_AXES, js->getNumAxes()); j++) {
-      bool flag = true;
-      axis &a = joysticks[i].axes[j];
-
-                               // If the axis hasn't changed, don't
-                               // force the value.
-      if (fabs(axis_values[j] - a.last_value) <= a.tolerance)
-       continue;
-      else
-       a.last_value = axis_values[j];
-
-      if (a.value)
-       flag = a.value->setDoubleValue((axis_values[j] + a.offset) *
-                                      a.factor);
-      if (!flag)
-       FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick "
-              << i << ", axis " << j);
-    }
+       js->read(&buttons, axis_values);
 
-    //
-    // Buttons
-    //
-    for (int j = 0; j < MAX_BUTTONS; j++) {
-      bool flag;
-      button &b = joysticks[i].buttons[j];
-      if (b.value == 0)
-       continue;
-
-                               // Button is on.
-      if ((buttons & (1 << j)) > 0) {
-                               // Repeating?
-       if (b.lastState == 1 && !b.isRepeatable)
-         continue;
-
-       switch (b.action) {
-       case button::TOGGLE:
-         if (b.step != 0.0) {
-           if (b.value->getDoubleValue() == 0.0)
-             flag = b.value->setDoubleValue(b.step);
-           else
-             flag = b.value->setDoubleValue(0.0);
-         } else {
-           if (b.value->getBoolValue())
-             flag = b.value->setBoolValue(false);
+       //
+       // Axes
+       //
+       for (int j = 0; j < joysticks[i].naxes; j++) {
+           bool flag = true;
+           axis &a = joysticks[i].axes[j];
+
+           // If the axis hasn't changed, don't
+           // force the value.
+           if (fabs(axis_values[j] - a.last_value) <= a.tolerance)
+               continue;
            else
-             flag = b.value->setBoolValue(true);
-         }
-         break;
-       case button::SWITCH:
-         flag = b.value->setDoubleValue(b.step);
-         break;
-       case button::ADJUST:
-         if (!b.value->setDoubleValue(b.value->getDoubleValue() + b.step))
-           FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick "
-                  << i << ", axis " << j);
-         break;
-       default:
-         flag = false;
-         break;
-       }
-       b.lastState = 1;
-
-                               // Button is off
-      } else {
-                               // Repeating?
-       if (b.lastState == 0 && !b.isRepeatable)
-         continue;
-
-       switch (b.action) {
-       case button::TOGGLE:
-         // no op
-         break;
-       case button::SWITCH:
-         flag = b.value->setDoubleValue(0.0);
-         break;
-       case button::ADJUST:
-         // no op
-         break;
-       default:
-         flag = false;
-         break;
+               a.last_value = axis_values[j];
+
+           if (a.value)
+               flag = a.value->setDoubleValue((axis_values[j] + a.offset) *
+                                              a.factor);
+           if (!flag)
+               FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick "
+                      << i << ", axis " << j);
        }
 
-       b.lastState = 0;
-      }
-      if (!flag)
-       FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for "
-              << jsNames[i] << ' ' << buttonNames[j]);
+       //
+       // Buttons
+       //
+       for (int j = 0; j < joysticks[i].nbuttons; j++) {
+           bool flag;
+           button &b = joysticks[i].buttons[j];
+           if (b.value == 0)
+               continue;
+
+           // Button is on.
+           if ((buttons & (1 << j)) > 0) {
+               // Repeating?
+               if (b.lastState == 1 && !b.isRepeatable)
+                   continue;
+
+               switch (b.action) {
+               case button::TOGGLE:
+                   if (b.step != 0.0) {
+                       if (b.value->getDoubleValue() == 0.0)
+                           flag = b.value->setDoubleValue(b.step);
+                       else
+                           flag = b.value->setDoubleValue(0.0);
+                   } else {
+                       if (b.value->getBoolValue())
+                           flag = b.value->setBoolValue(false);
+                       else
+                           flag = b.value->setBoolValue(true);
+                   }
+                   break;
+               case button::SWITCH:
+                   flag = b.value->setDoubleValue(b.step);
+                   break;
+               case button::ADJUST:
+                   if (!b.value->setDoubleValue(b.value->getDoubleValue() + b.step))
+                       FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick "
+                              << i << ", axis " << j);
+                   break;
+               default:
+                   flag = false;
+                   break;
+               }
+               b.lastState = 1;
+
+               // Button is off
+           } else {
+               // Repeating?
+               if (b.lastState == 0 && !b.isRepeatable)
+                   continue;
+
+               switch (b.action) {
+               case button::TOGGLE:
+                   // no op
+                   break;
+               case button::SWITCH:
+                   flag = b.value->setDoubleValue(0.0);
+                   break;
+               case button::ADJUST:
+                   // no op
+                   break;
+               default:
+                   flag = false;
+                   break;
+               }
+
+               b.lastState = 0;
+           }
+           if (!flag)
+               FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for "
+                      << jsNames[i] << ' ' << buttonNames[j]);
+       }
     }
-  }
 
-  return true;
+    return true;
 }
 
 // end of joystick.cxx