Use snprintf or _snprintf instead of the potentially dangerous sprintf
[freeglut] / src / freeglut_joystick.c
index 9348d13..8260340 100644 (file)
  *  Many thanks for Steve Baker for permission to pull from that library.
  */
 
-#if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+#if HAVE_SYS_PARAM_H
 #    include <sys/param.h>
 #endif
 
-#ifdef HAVE_CONFIG_H
-#    include "config.h"
-#endif
-
-#include "../include/GL/freeglut.h"
-#include "freeglut_internal.h"
-
 /*
  * Initial defines from "js.h" starting around line 33 with the existing "freeglut_joystick.c"
  * interspersed
  */
-#define _JS_MAX_BUTTONS 32
 
+/* XXX It might be better to poll the operating system for the numbers of buttons and
+ * XXX axes and then dynamically allocate the arrays.
+ */
+#define _JS_MAX_BUTTONS 32
 
 #if TARGET_HOST_MACINTOSH
 #    define _JS_MAX_AXES  9
 #    include <IOKit/hid/IOHIDLib.h>
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
 #    define _JS_MAX_AXES  8
 #    include <windows.h>
 #    include <mmsystem.h>
-#    include <string.h>
 #    include <regstr.h>
 
 #endif
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #    define _JS_MAX_AXES 16
+#    if HAVE_SYS_IOCTL_H
+#        include <sys/ioctl.h>
+#    endif
+#    if HAVE_FCNTL_H
+#        include <fcntl.h>
+#    endif
+#    include <errno.h>
 #    if defined(__FreeBSD__) || defined(__NetBSD__)
-/* XXX The next line is an unjustified hack which needs to be changed by someone who
- * XXX is familiar with *nix, BSD, and USB joysticks.
- */
+/* XXX The below hack is done until freeglut's autoconf is updated. */
 #        define HAVE_USB_JS    1
 
-#        include <sys/ioctl.h>
-#        include <machine/joystick.h>         /* For analog joysticks */
-
-#        if __FreeBSD_version >= 500000
+#        if defined(__FreeBSD__)
 #            include <sys/joystick.h>
 #        else
-#            include <machine/joystick.h>
+/*
+ * XXX NetBSD/amd64 systems may find that they have to steal the
+ * XXX /usr/include/machine/joystick.h from a NetBSD/i386 system.
+ * XXX I cannot comment whether that works for the interface, but
+ * XXX it lets you compile...(^&  I do not think that we can do away
+ * XXX with this header.
+ */
+#            include <machine/joystick.h>         /* For analog joysticks */
 #        endif
 #        define JS_DATA_TYPE joystick
 #        define JS_RETURN (sizeof(struct JS_DATA_TYPE))
 #    endif
 
-#    include <unistd.h>
-#    include <fcntl.h>
-#    include <errno.h>
-
 #    if defined(__linux__)
-#        include <sys/ioctl.h>
 #        include <linux/joystick.h>
 
 /* check the joystick driver version */
 #define JS_TRUE  1
 #define JS_FALSE 0
 
-/*
- * BSD defines from "jsBSD.cxx" around lines 42-270
- */
+/* BSD defines from "jsBSD.cxx" around lines 42-270 */
 
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 
 #    ifdef HAVE_USB_JS
 #        if defined(__NetBSD__)
-/*
- * XXX Apparently another ugly hack which someone who knows BSD and USBHID needs to solve
- */
+/* XXX The below hack is done until freeglut's autoconf is updated. */
 #            define HAVE_USBHID_H 1
 #            ifdef HAVE_USBHID_H
 #                include <usbhid.h>
 #                include <usb.h>
 #            endif
 #        elif defined(__FreeBSD__)
-#            include <libusbhid.h>
+#            if __FreeBSD_version < 500000
+#                include <libusbhid.h>
+#            else
+/* XXX The below hack is done until freeglut's autoconf is updated. */
+#                define HAVE_USBHID_H 1
+#                include <usbhid.h>
+#            endif
 #        endif
 #        include <dev/usb/usb.h>
 #        include <dev/usb/usbhid.h>
@@ -227,7 +230,7 @@ static int fghJoystickFindUSBdev(char *name, char *out, int outlen)
   static int protection_warned = 0;
 
   for (i = 0; i < 16; i++) {
-    sprintf(buf, "%s%d", USBDEV, i);
+    snprintf(buf, sizeof(buf), "%s%d", USBDEV, i);
     f = open(buf, O_RDONLY);
     if (f >= 0) {
       cp = fghJoystickWalkUSBdev(f, name, out, outlen);
@@ -236,8 +239,7 @@ static int fghJoystickFindUSBdev(char *name, char *out, int outlen)
         return 1;
     } else if (errno == EACCES) {
       if (!protection_warned) {
-        fprintf(stderr, "Can't open %s for read!\n",
-          buf);
+        fgWarning ( "Can't open %s for read!", buf );
         protection_warned = 1;
       }
     }
@@ -258,7 +260,7 @@ static int fghJoystickInitializeHID(struct os_specific_s *os,
 
     if ( ( rd = hid_get_report_desc( os->fd ) ) == 0 )
     {
-        fprintf( stderr, "error: %s: %s", os->fname, strerror( errno ) );
+        fgWarning ( "error: %s: %s", os->fname, strerror( errno ) );
         return FALSE;
     }
 
@@ -268,8 +270,7 @@ static int fghJoystickInitializeHID(struct os_specific_s *os,
         if( ioctl( os->fd, USB_GET_REPORT_ID, &report_id ) < 0)
         {
             /*** XXX {report_id} may not be the right variable? ***/
-            fprintf( stderr, "error: %s%d: %s",
-                     UHIDDEV, report_id, strerror( errno ) );
+            fgWarning ( "error: %s%d: %s", UHIDDEV, report_id, strerror( errno ) );
             return FALSE;
         }
 
@@ -384,20 +385,20 @@ struct tagSFG_Joystick
          maxReport[_JS_MAX_AXES];
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     JOYCAPS     jsCaps;
     JOYINFOEX   js;
     UINT        js_id;
 #endif
 
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #   if defined(__FreeBSD__) || defined(__NetBSD__)
        struct os_specific_s *os;
 #   endif
 
 #   ifdef JS_NEW
-       struct js_event     js         ;
+       struct js_event     js;
        int          tmp_buttons;
        float        tmp_axes [ _JS_MAX_AXES ];
 #   else
@@ -432,14 +433,13 @@ io_object_t ioDevices[K_NUM_DEVICES];
 static void fghJoystickFindDevices ( SFG_Joystick* joy, mach_port_t );
 static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick* joy, io_object_t );
 
-void fghJoystickEnumerateElements ( SFG_Joystick* joy, CFTypeRef element );
+static void fghJoystickEnumerateElements ( SFG_Joystick* joy, CFTypeRef element );
 /* callback for CFArrayApply */
 static void fghJoystickElementEnumerator ( SFG_Joystick* joy, void *element, void* vjs );
-void fghJoystickParseElement ( SFG_Joystick* joy, CFDictionaryRef element );
 
-void fghJoystickAddAxisElement ( SFG_Joystick* joy, CFDictionaryRef axis );
-void fghJoystickAddButtonElement ( SFG_Joystick* joy, CFDictionaryRef button );
-void fghJoystickAddHatElement ( SFG_Joystick* joy, CFDictionaryRef hat );
+static void fghJoystickAddAxisElement ( SFG_Joystick* joy, CFDictionaryRef axis );
+static void fghJoystickAddButtonElement ( SFG_Joystick* joy, CFDictionaryRef button );
+static void fghJoystickAddHatElement ( SFG_Joystick* joy, CFDictionaryRef hat );
 #endif
 
 
@@ -447,7 +447,6 @@ void fghJoystickAddHatElement ( SFG_Joystick* joy, CFDictionaryRef hat );
  * The static joystick structure pointer
  */
 #define MAX_NUM_JOYSTICKS  2
-static int fgNumberOfJoysticks = 0;
 static SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ];
 
 
@@ -456,7 +455,7 @@ static SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ];
  */
 static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
 {
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     MMRESULT status;
 #else
     int status;
@@ -517,7 +516,7 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
             IOHIDEventStruct hidEvent;
             (*(joy->hidDev))->getElementValue ( joy->hidDev, buttonCookies[i], &hidEvent );
             if ( hidEvent.value )
-                *buttons |= 1 << i; 
+                *buttons |= 1 << i;
         }
     }
 
@@ -532,7 +531,7 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
     }
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     status = joyGetPosEx( joy->js_id, &joy->js );
 
     if ( status != JOYERR_NOERROR )
@@ -598,7 +597,7 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
     }
 #endif
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #    if defined(__FreeBSD__) || defined(__NetBSD__)
     if ( joy->os->is_analog )
     {
@@ -657,9 +656,9 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
                if (usage > 0 && usage < _JS_MAX_BUTTONS + 1)
                {
                    if (d)
-                       joy->os->cache_buttons |= (1 << usage - 1);
+                       joy->os->cache_buttons |=  (1 << ( usage - 1 ));
                    else
-                       joy->os->cache_buttons &= ~(1 << usage - 1);
+                       joy->os->cache_buttons &= ~(1 << ( usage - 1 ));
                }
             }
         }
@@ -719,13 +718,13 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
             break;
 
         default:
-            fgWarning ( "%s", "PLIB_JS: Unrecognised /dev/js return!?!" );
+            fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" );
 
             /* use the old values */
 
             if ( buttons != NULL ) *buttons = joy->tmp_buttons;
             if ( axes    != NULL )
-                memcpy ( axes, joy->tmp_axes, sizeof(float) * num_axes );
+                memcpy ( axes, joy->tmp_axes, sizeof(float) * joy->num_axes );
 
             return;
         }
@@ -846,7 +845,7 @@ static int fghJoystickFindDevices ( SFG_Joystick *joy, mach_port_t masterPort )
 
     rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator);
     if (rv != kIOReturnSuccess || !hidIterator) {
-      fgWarning ( "%s", "no joystick (HID) devices found");
+      fgWarning( "no joystick (HID) devices found" );
       return;
     }
 
@@ -879,7 +878,7 @@ static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick *joy, io_object
     IOReturn rv;
     CFMutableDictionaryRef cfProperties;
 
-#if 0  
+#if 0
     /* comment copied from darwin/SDL_sysjoystick.c */
     /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also
      * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties
@@ -889,21 +888,21 @@ static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick *joy, io_object
 
     rv = IORegistryEntryGetParentEntry (ioDev, kIOServicePlane, &parent1);
     if (rv != kIOReturnSuccess) {
-        fgWarning ( "%s", "error getting device entry parent");
+        fgWarning ( "error getting device entry parent");
         return NULL;
     }
 
     rv = IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2);
     if (rv != kIOReturnSuccess) {
-        fgWarning ( "%s", "error getting device entry parent 2");
+        fgWarning ( "error getting device entry parent 2");
         return NULL;
     }
 #endif
 
-    rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/, 
+    rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/,
         &cfProperties, kCFAllocatorDefault, kNilOptions);
     if (rv != kIOReturnSuccess || !cfProperties) {
-        fgWarning ( "%s", "error getting device properties");
+        fgWarning ( "error getting device properties");
         return NULL;
     }
 
@@ -917,96 +916,38 @@ static void fghJoystickElementEnumerator ( SFG_Joystick *joy, void *element, voi
             return;
     }
 
-      static_cast<jsJoystick*>(vjs)->parseElement ( (CFDictionaryRef) element );        
+      static_cast<jsJoystick*>(vjs)->parseElement ( (CFDictionaryRef) element );
 }
 
 /** element enumerator function : pass NULL for top-level*/
 static void fghJoystickEnumerateElements ( SFG_Joystick *joy, CFTypeRef element )
 {
-      assert(CFGetTypeID(element) == CFArrayGetTypeID());
+      FREEGLUT_INTERNAL_ERROR_EXIT( (CFGetTypeID(element) == CFArrayGetTypeID(),
+                                    "Joystick element type mismatch",
+                                    "fghJoystickEnumerateElements" );
 
       CFRange range = {0, CFArrayGetCount ((CFArrayRef)element)};
-      CFArrayApplyFunction((CFArrayRef) element, range, 
+      CFArrayApplyFunction((CFArrayRef) element, range,
             &fghJoystickElementEnumerator, joy );
 }
 
-static void fghJoystickParseElement ( SFG_Joystick *joy, CFDictionaryRef element )
-{
-    CFTypeRef refPage = CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementUsagePageKey));
-    CFTypeRef refUsage = CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementUsageKey));
-
-    long type, page, usage;
-
-    CFNumberGetValue((CFNumberRef)
-        CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementTypeKey)), 
-        kCFNumberLongType, &type);
-
-    switch ( typ e) {
-    case kIOHIDElementTypeInput_Misc:
-    case kIOHIDElementTypeInput_Axis:
-    case kIOHIDElementTypeInput_Button:
-        printf("got input element...");
-        CFNumberGetValue( (CFNumberRef) refUsage, kCFNumberLongType, &usage );
-        CFNumberGetValue( (CFNumberRef) refPage, kCFNumberLongType, &page );
-
-        if (page == kHIDPage_GenericDesktop) {    
-            switch ( usage ) /* look at usage to determine function */
-            {
-            case kHIDUsage_GD_X:
-            case kHIDUsage_GD_Y:
-            case kHIDUsage_GD_Z:
-            case kHIDUsage_GD_Rx:
-            case kHIDUsage_GD_Ry:
-            case kHIDUsage_GD_Rz:
-            case kHIDUsage_GD_Slider: /* for throttle / trim controls */
-                printf(" axis\n");
-                fghJoystickAddAxisElement((CFDictionaryRef) element);
-                break;
-
-            case kHIDUsage_GD_Hatswitch:
-                printf(" hat\n");
-                fghJoystickAddHatElement((CFDictionaryRef) element);
-                break;
-
-            default:
-                printf("input type element has weird usage (%x)\n", usage);
-                break;
-            }
-        } else if (page == kHIDPage_Button) {
-            printf(" button\n");
-            fghJoystickAddButtonElement((CFDictionaryRef) element);
-        } else
-            printf("input type element has weird page (%x)\n", page);
-        break;
-
-    case kIOHIDElementTypeCollection:
-        fghJoystickEnumerateElements (
-            CFDictionaryGetValue ( element, CFSTR(kIOHIDElementKey) )
-        );
-        break;
-
-    default:
-        break;
-    }  
-}
-
 static void fghJoystickAddAxisElement ( SFG_Joystick *joy, CFDictionaryRef axis )
 {
     long cookie, lmin, lmax;
     int index = joy->num_axes++;
 
     CFNumberGetValue ((CFNumberRef)
-        CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementCookieKey) ), 
+        CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementCookieKey) ),
         kCFNumberLongType, &cookie);
 
     axisCookies[index] = (IOHIDElementCookie) cookie;
 
     CFNumberGetValue ((CFNumberRef)
-        CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMinKey) ), 
+        CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMinKey) ),
         kCFNumberLongType, &lmin);
 
     CFNumberGetValue ((CFNumberRef)
-        CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMaxKey) ), 
+        CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMaxKey) ),
         kCFNumberLongType, &lmax);
 
     joy->min[index] = lmin;
@@ -1020,7 +961,7 @@ static void fghJoystickAddButtonElement ( SFG_Joystick *joy, CFDictionaryRef but
 {
     long cookie;
     CFNumberGetValue ((CFNumberRef)
-            CFDictionaryGetValue ( button, CFSTR(kIOHIDElementCookieKey) ), 
+            CFDictionaryGetValue ( button, CFSTR(kIOHIDElementCookieKey) ),
             kCFNumberLongType, &cookie);
 
     joy->buttonCookies[num_buttons++] = (IOHIDElementCookie) cookie;
@@ -1034,11 +975,13 @@ static void fghJoystickAddHatElement ( SFG_Joystick *joy, CFDictionaryRef button
 }
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
 /* Inspired by
    http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp
  */
-#    pragma comment (lib, "advapi32.lib")
+#    if FREEGLUT_LIB_PRAGMAS
+#        pragma comment (lib, "advapi32.lib")
+#    endif
 
 static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_sz )
 {
@@ -1054,9 +997,9 @@ static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_
         return 0;
 
     /* Open .. MediaResources\CurrentJoystickSettings */
-    sprintf ( buffer, "%s\\%s\\%s",
-              REGSTR_PATH_JOYCONFIG, joy->jsCaps.szRegKey,
-              REGSTR_KEY_JOYCURR );
+    _snprintf ( buffer, sizeof(buffer), "%s\\%s\\%s",
+                REGSTR_PATH_JOYCONFIG, joy->jsCaps.szRegKey,
+                REGSTR_KEY_JOYCURR );
 
     lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
 
@@ -1066,7 +1009,7 @@ static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_
     dwcb = sizeof(OEMKey);
 
     /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */
-    sprintf ( buffer, "Joystick%d%s", joy->js_id + 1, REGSTR_VAL_JOYOEMNAME );
+    _snprintf ( buffer, sizeof(buffer), "Joystick%d%s", joy->js_id + 1, REGSTR_VAL_JOYOEMNAME );
 
     lr = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEMKey, &dwcb);
     RegCloseKey ( hKey );
@@ -1074,7 +1017,7 @@ static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_
     if ( lr != ERROR_SUCCESS ) return 0;
 
     /* Open OEM Key from ...MediaProperties */
-    sprintf ( buffer, "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );
+    _snprintf ( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );
 
     lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey );
 
@@ -1096,7 +1039,7 @@ static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_
 
 static void fghJoystickOpen( SFG_Joystick* joy )
 {
-    int i;
+    int i = 0;
 #if TARGET_HOST_MACINTOSH
     OSStatus err;
 #endif
@@ -1110,40 +1053,46 @@ static void fghJoystickOpen( SFG_Joystick* joy )
         CFDictionaryRef props;
     CFTypeRef topLevelElement;
 #endif
-#if TARGET_HOST_UNIX_X11
-#    if defined(__FreeBSD__) || defined(__NetBSD__)
+#if TARGET_HOST_POSIX_X11
+#    if defined( __FreeBSD__ ) || defined( __NetBSD__ )
        char *cp;
 #    endif
 #    ifdef JS_NEW
        unsigned char u;
 #    else
-       int counter;
+#      if defined( __linux__ ) || TARGET_HOST_SOLARIS
+         int counter = 0;
+#      endif
 #    endif
 #endif
 
-    /* Default values (for no joystick -- each conditional will reset the error flag) */
+    /* Silence gcc, the correct #ifdefs would be too fragile... */
+    (void)i;
+
+    /*
+     * Default values (for no joystick -- each conditional will reset the
+     * error flag)
+     */
     joy->error = TRUE;
     joy->num_axes = joy->num_buttons = 0;
-    joy->name [0] = '\0';
+    joy->name[ 0 ] = '\0';
 
 #if TARGET_HOST_MACINTOSH
-    /*
-     * XXX FIXME: get joystick name in Mac
-     */
+    /* XXX FIXME: get joystick name in Mac */
 
-    err = ISpStartup ();
+    err = ISpStartup( );
 
-    if ( err == noErr )
+    if( err == noErr )
     {
-#define ISP_CHECK_ERR(x) if ( x != noErr ) { joy->error = GL_TRUE; return; }
+#define ISP_CHECK_ERR(x) if( x != noErr ) { joy->error = GL_TRUE; return; }
 
         joy->error = GL_TRUE;
 
         /* initialize the needs structure */
-        ISpNeed temp_isp_needs[isp_num_needs] =
+        ISpNeed temp_isp_needs[ isp_num_needs ] =
         {
-          { "\pX-Axis",    128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
-          { "\pY-Axis",    128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
+          { "\pX-Axis",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
+          { "\pY-Axis",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
           { "\pZ-Axis",    128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
           { "\pR-Axis",    128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
           { "\pAxis   4",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
@@ -1186,7 +1135,7 @@ static void fghJoystickOpen( SFG_Joystick* joy )
           { "\pButton 31", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
         };
 
-        memcpy ( joy->isp_needs, temp_isp_needs, sizeof(temp_isp_needs) );
+        memcpy( joy->isp_needs, temp_isp_needs, sizeof (temp_isp_needs ) );
 
 
         /* next two calls allow keyboard and mouse to emulate other input
@@ -1201,22 +1150,25 @@ static void fghJoystickOpen( SFG_Joystick* joy )
           ISP_CHECK_ERR(err)
         */
 
-        err = ISpElement_NewVirtualFromNeeds ( joy->isp_num_needs, joy->isp_needs, joy->isp_elem, 0 );
-        ISP_CHECK_ERR(err)
+        err = ISpElement_NewVirtualFromNeeds( joy->isp_num_needs,
+                                              joy->isp_needs, joy->isp_elem,
+                                              0 );
+        ISP_CHECK_ERR( err )
 
-        err = ISpInit ( joy->isp_num_needs, joy->isp_needs, joy->isp_elem, 'freeglut', nil, 0, 128, 0 );
-        ISP_CHECK_ERR(err)
+        err = ISpInit( joy->isp_num_needs, joy->isp_needs, joy->isp_elem,
+                       'freeglut', nil, 0, 128, 0 );
+        ISP_CHECK_ERR( err )
 
         joy->num_buttons = joy->isp_num_needs - joy->isp_num_axis;
         joy->num_axes    = joy->isp_num_axis;
 
-        for ( i = 0; i < joy->num_axes; i++ )
+        for( i = 0; i < joy->num_axes; i++ )
         {
-          joy->dead_band [ i ] = 0;
-          joy->saturate  [ i ] = 1;
-          joy->center    [ i ] = kISpAxisMiddle;
-          joy->max       [ i ] = kISpAxisMaximum;
-          joy->min       [ i ] = kISpAxisMinimum;
+            joy->dead_band[ i ] = 0;
+            joy->saturate [ i ] = 1;
+            joy->center   [ i ] = kISpAxisMiddle;
+            joy->max      [ i ] = kISpAxisMaximum;
+            joy->min      [ i ] = kISpAxisMinimum;
         }
 
         joy->error = GL_FALSE;
@@ -1226,49 +1178,56 @@ static void fghJoystickOpen( SFG_Joystick* joy )
 #endif
 
 #if TARGET_HOST_MAC_OSX
-    if (joy->id >= numDevices) {
-        fgWarning ( "%s", "device index out of range in fgJoystickOpen()");
+    if( joy->id >= numDevices )
+    {
+        fgWarning( "device index out of range in fgJoystickOpen()" );
         return;
     }
 
     /* create device interface */
-    rv = IOCreatePlugInInterfaceForService ( ioDevices[joy->id], 
-                                             kIOHIDDeviceUserClientTypeID,
-                                             kIOCFPlugInInterfaceID,
-                                             &plugin, &score);
+    rv = IOCreatePlugInInterfaceForService( ioDevices[ joy->id ],
+                                            kIOHIDDeviceUserClientTypeID,
+                                            kIOCFPlugInInterfaceID,
+                                            &plugin, &score );
 
-    if (rv != kIOReturnSuccess) {
-        fgWarning ( "%s", "error creating plugin for io device");
+    if( rv != kIOReturnSuccess )
+    {
+        fgWarning( "error creating plugin for io device" );
         return;
     }
 
-    pluginResult = (*plugin)->QueryInterface ( plugin, 
-                    CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), &(LPVOID) joy->hidDev );
+    pluginResult = ( *plugin )->QueryInterface(
+        plugin,
+        CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
+        &( LPVOID )joy->hidDev
+    );
 
-    if ( pluginResult != S_OK )
-        fgWarning ( "%s", "QI-ing IO plugin to HID Device interface failed");
+    if( pluginResult != S_OK )
+        fgWarning ( "QI-ing IO plugin to HID Device interface failed" );
 
-    (*plugin)->Release(plugin); /* don't leak a ref */
-    if (joy->hidDev == NULL) return;
+    ( *plugin )->Release( plugin ); /* don't leak a ref */
+    if( joy->hidDev == NULL )
+        return;
 
     /* store the interface in this instance */
-    rv = (*(joy->hidDev))->open(joy->hidDev, 0);
-    if (rv != kIOReturnSuccess) {
-        fgWarning ( "%s", "error opening device interface");
+    rv = ( *( joy->hidDev ) )->open( joy->hidDev, 0 );
+    if( rv != kIOReturnSuccess )
+    {
+        fgWarning( "error opening device interface");
         return;
     }
 
-    props = getCFProperties(ioDevices[joy->id]);
+    props = getCFProperties( ioDevices[ joy->id ] );
 
     /* recursively enumerate all the bits */
-    CFTypeRef topLevelElement = 
-                      CFDictionaryGetValue ( props, CFSTR ( kIOHIDElementKey ) );
-    enumerateElements ( topLevelElement );
+    CFTypeRef topLevelElement =
+        CFDictionaryGetValue( props, CFSTR( kIOHIDElementKey ) );
+    enumerateElements( topLevelElement );
 
-    CFRelease ( props );
+    CFRelease( props );
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     joy->js.dwFlags = JOY_RETURNALL;
     joy->js.dwSize  = sizeof( joy->js );
 
@@ -1278,7 +1237,7 @@ static void fghJoystickOpen( SFG_Joystick* joy )
         ( joyGetDevCaps( joy->js_id, &joy->jsCaps, sizeof( joy->jsCaps ) ) !=
           JOYERR_NOERROR );
 
-    if ( joy->jsCaps.wNumAxes == 0 )
+    if( joy->jsCaps.wNumAxes == 0 )
     {
         joy->num_axes = 0;
         joy->error = GL_TRUE;
@@ -1288,104 +1247,103 @@ static void fghJoystickOpen( SFG_Joystick* joy )
         /* Device name from jsCaps is often "Microsoft PC-joystick driver",
          * at least for USB.  Try to get the real name from the registry.
          */
-        if ( ! fghJoystickGetOEMProductName ( joy, joy->name, sizeof(joy->name) ) )
+        if ( ! fghJoystickGetOEMProductName( joy, joy->name,
+                                             sizeof( joy->name ) ) )
         {
-            fgWarning ( "%s", "JS: Failed to read joystick name from registry" );
-            strncpy ( joy->name, joy->jsCaps.szPname, sizeof(joy->name) );
+            fgWarning( "JS: Failed to read joystick name from registry" );
+            strncpy( joy->name, joy->jsCaps.szPname, sizeof( joy->name ) );
         }
 
         /* Windows joystick drivers may provide any combination of
          * X,Y,Z,R,U,V,POV - not necessarily the first n of these.
          */
-        if ( joy->jsCaps.wCaps & JOYCAPS_HASPOV )
+        if( joy->jsCaps.wCaps & JOYCAPS_HASPOV )
         {
             joy->num_axes = _JS_MAX_AXES;
-            joy->min [ 7 ] = -1.0; joy->max [ 7 ] = 1.0;  /* POV Y */
-            joy->min [ 6 ] = -1.0; joy->max [ 6 ] = 1.0;  /* POV X */
+            joy->min[ 7 ] = -1.0; joy->max[ 7 ] = 1.0;  /* POV Y */
+            joy->min[ 6 ] = -1.0; joy->max[ 6 ] = 1.0;  /* POV X */
         }
         else
             joy->num_axes = 6;
 
-        joy->min[ 5 ] = (float) joy->jsCaps.wVmin;
-        joy->max[ 5 ] = (float) joy->jsCaps.wVmax;
-        joy->min[ 4 ] = (float) joy->jsCaps.wUmin;
-        joy->max[ 4 ] = (float) joy->jsCaps.wUmax;
-        joy->min[ 3 ] = (float) joy->jsCaps.wRmin;
-        joy->max[ 3 ] = (float) joy->jsCaps.wRmax;
-        joy->min[ 2 ] = (float) joy->jsCaps.wZmin;
-        joy->max[ 2 ] = (float) joy->jsCaps.wZmax;
-        joy->min[ 1 ] = (float) joy->jsCaps.wYmin;
-        joy->max[ 1 ] = (float) joy->jsCaps.wYmax;
-        joy->min[ 0 ] = (float) joy->jsCaps.wXmin;
-        joy->max[ 0 ] = (float) joy->jsCaps.wXmax;
+        joy->min[ 5 ] = ( float )joy->jsCaps.wVmin;
+        joy->max[ 5 ] = ( float )joy->jsCaps.wVmax;
+        joy->min[ 4 ] = ( float )joy->jsCaps.wUmin;
+        joy->max[ 4 ] = ( float )joy->jsCaps.wUmax;
+        joy->min[ 3 ] = ( float )joy->jsCaps.wRmin;
+        joy->max[ 3 ] = ( float )joy->jsCaps.wRmax;
+        joy->min[ 2 ] = ( float )joy->jsCaps.wZmin;
+        joy->max[ 2 ] = ( float )joy->jsCaps.wZmax;
+        joy->min[ 1 ] = ( float )joy->jsCaps.wYmin;
+        joy->max[ 1 ] = ( float )joy->jsCaps.wYmax;
+        joy->min[ 0 ] = ( float )joy->jsCaps.wXmin;
+        joy->max[ 0 ] = ( float )joy->jsCaps.wXmax;
     }
 
-    /*
-     * Guess all the rest judging on the axes extremals
-     */
+    /* Guess all the rest judging on the axes extremals */
     for( i = 0; i < joy->num_axes; i++ )
     {
-        joy->center   [ i ] = (joy->max[i] + joy->min[i]) * 0.5f;
+        joy->center   [ i ] = ( joy->max[ i ] + joy->min[ i ] ) * 0.5f;
         joy->dead_band[ i ] = 0.0f;
         joy->saturate [ i ] = 1.0f;
     }
 #endif
 
-#if TARGET_HOST_UNIX_X11
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-    for ( i = 0; i < _JS_MAX_AXES; i++ )
-        joy->os->cache_axes [ i ] = 0.0f;
+#if TARGET_HOST_POSIX_X11
+#if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+    for( i = 0; i < _JS_MAX_AXES; i++ )
+        joy->os->cache_axes[ i ] = 0.0f;
 
     joy->os->cache_buttons = 0;
 
-    joy->os->fd = open ( joy->os->fname, O_RDONLY | O_NONBLOCK);
+    joy->os->fd = open( joy->os->fname, O_RDONLY | O_NONBLOCK);
 
-    if ( joy->os->fd < 0 && errno == EACCES)
-      fgWarning ( "%s exists but is not readable by you\n", joy->os->fname );
+    if( joy->os->fd < 0 && errno == EACCES )
+        fgWarning ( "%s exists but is not readable by you", joy->os->fname );
 
-    joy->error = ( joy->os->fd < 0 );
+    joy->error =( joy->os->fd < 0 );
 
-    if ( joy->error )
-      return;
+    if( joy->error )
+        return;
 
     joy->num_axes = 0;
     joy->num_buttons = 0;
-    if ( joy->os->is_analog )
+    if( joy->os->is_analog )
     {
         FILE *joyfile;
-        char joyfname [ 1024 ];
+        char joyfname[ 1024 ];
         int noargs, in_no_axes;
 
-        float axes  [ _JS_MAX_AXES ];
-        int buttons [ _JS_MAX_AXES ];
+        float axes [ _JS_MAX_AXES ];
+        int buttons[ _JS_MAX_AXES ];
 
         joy->num_axes    =  2;
         joy->num_buttons = 32;
 
-        fghJoystickRawRead ( joy, buttons, axes );
-        joy->error = axes[0] < -1000000000.0f;
-        if ( joy->error )
-          return;
+        fghJoystickRawRead( joy, buttons, axes );
+        joy->error = axes[ 0 ] < -1000000000.0f;
+        if( joy->error )
+            return;
 
-        sprintf( joyfname, "%s/.joy%drc", getenv ( "HOME" ), joy->id );
+        snprintf( joyfname, sizeof(buffer), "%s/.joy%drc", getenv( "HOME" ), joy->id );
 
-        joyfile = fopen ( joyfname, "r" );
-        joy->error = ( joyfile == NULL );
-        if ( joy->error )
-          return;
+        joyfile = fopen( joyfname, "r" );
+        joy->error =( joyfile == NULL );
+        if( joy->error )
+            return;
 
-        noargs = fscanf ( joyfile, "%d%f%f%f%f%f%f", &in_no_axes,
-                          &joy->min [ 0 ], &joy->center [ 0 ], &joy->max [ 0 ],
-                          &joy->min [ 1 ], &joy->center [ 1 ], &joy->max [ 1 ] );
+        noargs = fscanf( joyfile, "%d%f%f%f%f%f%f", &in_no_axes,
+                         &joy->min[ 0 ], &joy->center[ 0 ], &joy->max[ 0 ],
+                         &joy->min[ 1 ], &joy->center[ 1 ], &joy->max[ 1 ] );
         joy->error = noargs != 7 || in_no_axes != _JS_MAX_AXES;
-        fclose ( joyfile );
-        if ( joy->error )
-          return;
+        fclose( joyfile );
+        if( joy->error )
+            return;
 
-        for ( i = 0; i < _JS_MAX_AXES; i++ )
+        for( i = 0; i < _JS_MAX_AXES; i++ )
         {
-            joy->dead_band [ i ] = 0.0f;
-            joy->saturate  [ i ] = 1.0f;
+            joy->dead_band[ i ] = 0.0f;
+            joy->saturate [ i ] = 1.0f;
         }
 
         return;    /* End of analog code */
@@ -1395,49 +1353,49 @@ static void fghJoystickOpen( SFG_Joystick* joy )
     if( ! fghJoystickInitializeHID( joy->os, &joy->num_axes,
                                     &joy->num_buttons ) )
     {
-        close ( joy->os->fd );
+        close( joy->os->fd );
         joy->error = GL_TRUE;
         return;
     }
 
-    cp = strrchr(joy->os->fname, '/');
-    if ( cp ) {
-        if ( fghJoystickFindUSBdev ( &cp[1], joy->name, sizeof(joy->name) ) == 0 )
-            strcpy ( joy->name, &cp[1] );
+    cp = strrchr( joy->os->fname, '/' );
+    if( cp )
+    {
+        if( fghJoystickFindUSBdev( &cp[1], joy->name, sizeof( joy->name ) ) ==
+            0 )
+            strcpy( joy->name, &cp[1] );
     }
 
-    if ( joy->num_axes > _JS_MAX_AXES )
+    if( joy->num_axes > _JS_MAX_AXES )
         joy->num_axes = _JS_MAX_AXES;
 
-    for ( i = 0; i < _JS_MAX_AXES; i++ )
+    for( i = 0; i < _JS_MAX_AXES; i++ )
     {
         /* We really should get this from the HID, but that data seems
          * to be quite unreliable for analog-to-USB converters. Punt for
          * now.
          */
-        if ( joy->os->axes_usage [ i ] == HUG_HAT_SWITCH )
+        if( joy->os->axes_usage[ i ] == HUG_HAT_SWITCH )
         {
-            joy->max       [ i ] = 1.0f;
-            joy->center    [ i ] = 0.0f;
-            joy->min       [ i ] = -1.0f;
+            joy->max   [ i ] = 1.0f;
+            joy->center[ i ] = 0.0f;
+            joy->min   [ i ] = -1.0f;
         }
         else
         {
-            joy->max       [ i ] = 255.0f;
-            joy->center    [ i ] = 127.0f;
-            joy->min       [ i ] = 0.0f;
+            joy->max   [ i ] = 255.0f;
+            joy->center[ i ] = 127.0f;
+            joy->min   [ i ] = 0.0f;
         }
 
-        joy->dead_band [ i ] = 0.0f;
-        joy->saturate  [ i ] = 1.0f;
+        joy->dead_band[ i ] = 0.0f;
+        joy->saturate[ i ] = 1.0f;
     }
 #    endif
 #endif
 
-#if defined(__linux__)
-    /*
-     * Default for older Linux systems.
-     */
+#if defined( __linux__ ) || TARGET_HOST_SOLARIS
+    /* Default for older Linux systems. */
     joy->num_axes    =  2;
     joy->num_buttons = 32;
 
@@ -1450,25 +1408,23 @@ static void fghJoystickOpen( SFG_Joystick* joy )
 
     joy->fd = open( joy->fname, O_RDONLY );
 
-    joy->error = (joy->fd < 0);
+    joy->error =( joy->fd < 0 );
 
-    if ( joy->error )
+    if( joy->error )
         return;
 
-    /*
-     * Set the correct number of axes for the linux driver
-     */
+    /* Set the correct number of axes for the linux driver */
 #    ifdef JS_NEW
-    /* Melchior Franz's fixes for big-endian Linuxes since writing 
-     *  to the upper byte of an uninitialized word doesn't work. 
-     *  9 April 2003 
+    /* Melchior Franz's fixes for big-endian Linuxes since writing
+     *  to the upper byte of an uninitialized word doesn't work.
+     *  9 April 2003
      */
-    ioctl ( joy->fd, JSIOCGAXES   , &u ); 
+    ioctl( joy->fd, JSIOCGAXES, &u );
     joy->num_axes = u;
-    ioctl ( joy->fd, JSIOCGBUTTONS, &u );
+    ioctl( joy->fd, JSIOCGBUTTONS, &u );
     joy->num_buttons = u;
-    ioctl ( joy->fd, JSIOCGNAME ( sizeof(joy->name) ), joy->name );
-    fcntl ( joy->fd, F_SETFL      , O_NONBLOCK   );
+    ioctl( joy->fd, JSIOCGNAME( sizeof( joy->name ) ), joy->name );
+    fcntl( joy->fd, F_SETFL, O_NONBLOCK );
 #    endif
 
     /*
@@ -1483,7 +1439,7 @@ static void fghJoystickOpen( SFG_Joystick* joy )
     counter = 0;
 
     do
-    { 
+    {
         fghJoystickRawRead( joy, NULL, joy->center );
         counter++;
     } while( !joy->error &&
@@ -1495,7 +1451,7 @@ static void fghJoystickOpen( SFG_Joystick* joy )
         joy->error = GL_TRUE;
 #    endif
 
-    for ( i = 0; i < _JS_MAX_AXES; i++ )
+    for( i = 0; i < _JS_MAX_AXES; i++ )
     {
 #    ifdef JS_NEW
         joy->max   [ i ] =  32767.0f;
@@ -1515,105 +1471,129 @@ static void fghJoystickOpen( SFG_Joystick* joy )
 /*
  * This function replaces the constructor method in the JS library.
  */
-void fgJoystickInit( int ident )
+static void fghJoystickInit( int ident )
 {
-    if ( ident >= MAX_NUM_JOYSTICKS )
-      fgError( "Too large a joystick number" );
+    if( ident >= MAX_NUM_JOYSTICKS )
+      fgError( "Too large a joystick number: %d", ident );
 
-    if( fgJoystick[ident] )
-        fgError( "illegal attempt to initialize joystick device" );
+    if( fgJoystick[ ident ] )
+        fgError( "illegal attempt to initialize joystick device again" );
 
-    fgJoystick[ident] = ( SFG_Joystick * )calloc( sizeof( SFG_Joystick ), 1 );
+    fgJoystick[ ident ] =
+        ( SFG_Joystick * )calloc( sizeof( SFG_Joystick ), 1 );
 
     /* Set defaults */
-    fgJoystick[ident]->num_axes = fgJoystick[ident]->num_buttons = 0;
-    fgJoystick[ident]->error = GL_TRUE;
+    fgJoystick[ ident ]->num_axes = fgJoystick[ ident ]->num_buttons = 0;
+    fgJoystick[ ident ]->error = GL_TRUE;
 
 #if TARGET_HOST_MACINTOSH
-    fgJoystick[ident]->id = ident;
-    sprintf ( fgJoystick[ident]->fname, "/dev/js%d", ident ); /* FIXME */
-    fgJoystick[ident]->error = GL_FALSE;
+    fgJoystick[ ident ]->id = ident;
+    snprintf( fgJoystick[ ident ]->fname, sizeof(fgJoystick[ ident ]->fname), "/dev/js%d", ident ); /* FIXME */
+    fgJoystick[ ident ]->error = GL_FALSE;
 #endif
 
 #if TARGET_HOST_MAC_OSX
-    fgJoystick[ident]->id = ident;
-    fgJoystick[ident]->error = GL_FALSE;
-    fgJoystick[ident]->num_axes = 0;
-    fgJoystick[ident]->num_buttons = 0;
+    fgJoystick[ ident ]->id = ident;
+    fgJoystick[ ident ]->error = GL_FALSE;
+    fgJoystick[ ident ]->num_axes = 0;
+    fgJoystick[ ident ]->num_buttons = 0;
 
-    if (numDevices < 0) {
+    if( numDevices < 0 )
+    {
         /* do first-time init (since we can't over-ride jsInit, hmm */
         numDevices = 0;
 
         mach_port_t masterPort;
-        IOReturn rv = IOMasterPort ( bootstrap_port, &masterPort );
-        if ( rv != kIOReturnSuccess ) {
-            fgWarning ( "%s", "error getting master Mach port");
+        IOReturn rv = IOMasterPort( bootstrap_port, &masterPort );
+        if( rv != kIOReturnSuccess )
+        {
+            fgWarning( "error getting master Mach port" );
             return;
         }
-        fghJoystickFindDevices ( masterPort );
+        fghJoystickFindDevices( masterPort );
     }
 
-    if ( ident >= numDevices ) {
-        fgJoystick[ident]->error = GL_TRUE;
+    if ( ident >= numDevices )
+    {
+        fgJoystick[ ident ]->error = GL_TRUE;
         return;
     }
 
     /* get the name now too */
-    CFDictionaryRef properties = getCFProperties(ioDevices[ident]);
-    CFTypeRef ref = CFDictionaryGetValue (properties, CFSTR(kIOHIDProductKey));
+    CFDictionaryRef properties = getCFProperties( ioDevices[ ident ] );
+    CFTypeRef ref = CFDictionaryGetValue( properties,
+                                          CFSTR( kIOHIDProductKey ) );
     if (!ref)
-      ref = CFDictionaryGetValue (properties, CFSTR("USB Product Name"));
+        ref = CFDictionaryGetValue(properties, CFSTR( "USB Product Name" ) );
 
-    if (!ref || !CFStringGetCString ((CFStringRef) ref, name, 128, CFStringGetSystemEncoding ())) {
-      fgWarning ( "%s", "error getting device name");
-      name[0] = '\0';
+    if( !ref ||
+        !CFStringGetCString( ( CFStringRef )ref, name, 128,
+                             CFStringGetSystemEncoding( ) ) )
+    {
+        fgWarning( "error getting device name" );
+        name[ 0 ] = '\0';
     }
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     switch( ident )
     {
     case 0:
-        fgJoystick[ident]->js_id = JOYSTICKID1;
-        fgJoystick[ident]->error = GL_FALSE;
+        fgJoystick[ ident ]->js_id = JOYSTICKID1;
+        fgJoystick[ ident ]->error = GL_FALSE;
         break;
     case 1:
-        fgJoystick[ident]->js_id = JOYSTICKID2;
-        fgJoystick[ident]->error = GL_FALSE;
+        fgJoystick[ ident ]->js_id = JOYSTICKID2;
+        fgJoystick[ ident ]->error = GL_FALSE;
         break;
     default:
-        fgJoystick[ident]->num_axes = 0;
-        fgJoystick[ident]->error = GL_TRUE;
+        fgJoystick[ ident ]->num_axes = 0;
+        fgJoystick[ ident ]->error = GL_TRUE;
         return;
     }
 #endif
 
-#if TARGET_HOST_UNIX_X11
-#    if defined(__FreeBSD__) || defined(__NetBSD__)
-    fgJoystick[ident]->id = ident;
-    fgJoystick[ident]->error = GL_FALSE;
-
-    fgJoystick[ident]->os = calloc (1, sizeof (struct os_specific_s));
-    memset ( fgJoystick[ident]->os, 0, sizeof(struct os_specific_s) );
-    if (ident < USB_IDENT_OFFSET)
-        fgJoystick[ident]->os->is_analog = 1;
-    if (fgJoystick[ident]->os->is_analog)
-        sprintf ( fgJoystick[ident]->os->fname, "%s%d", AJSDEV, ident );
+#if TARGET_HOST_POSIX_X11
+#    if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+    fgJoystick[ ident ]->id = ident;
+    fgJoystick[ ident ]->error = GL_FALSE;
+
+    fgJoystick[ ident ]->os = calloc( 1, sizeof( struct os_specific_s ) );
+    memset( fgJoystick[ ident ]->os, 0, sizeof( struct os_specific_s ) );
+    if( ident < USB_IDENT_OFFSET )
+        fgJoystick[ ident ]->os->is_analog = 1;
+    if( fgJoystick[ ident ]->os->is_analog )
+        snprintf( fgJoystick[ ident ]->os->fname, sizeof(fgJoystick[ ident ]->os->fname), "%s%d", AJSDEV, ident );
     else
-        sprintf ( fgJoystick[ident]->os->fname, "%s%d", UHIDDEV, ident - USB_IDENT_OFFSET );
-#    elif defined(__linux__)
-    fgJoystick[ident]->id = ident;
-    fgJoystick[ident]->error = GL_FALSE;
+        snprintf( fgJoystick[ ident ]->os->fname, sizeof(fgJoystick[ ident ]->os->fname), "%s%d", UHIDDEV,
+                 ident - USB_IDENT_OFFSET );
+#    elif defined( __linux__ )
+    fgJoystick[ ident ]->id = ident;
+    fgJoystick[ ident ]->error = GL_FALSE;
 
-    sprintf ( fgJoystick[ident]->fname, "/dev/input/js%d", ident );
+    snprintf( fgJoystick[ident]->fname, sizeof(fgJoystick[ident]->fname), "/dev/input/js%d", ident );
 
-    if ( access ( fgJoystick[ident]->fname, F_OK ) != 0 )
-        sprintf ( fgJoystick[ident]->fname, "/dev/js%d", ident );
+    if( access( fgJoystick[ ident ]->fname, F_OK ) != 0 )
+        snprintf( fgJoystick[ ident ]->fname, sizeof(fgJoystick[ ident ]->fname), "/dev/js%d", ident );
 #    endif
 #endif
 
-    fghJoystickOpen ( fgJoystick[ident] );
+    fghJoystickOpen( fgJoystick[ ident  ] );
+}
+
+/*
+ * Try initializing all the joysticks (well, both of them)
+ */
+void fgInitialiseJoysticks ( void )
+{
+    if( !fgState.JoysticksInitialised )
+    {
+        int ident ;
+        for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
+            fghJoystickInit( ident );
+
+        fgState.JoysticksInitialised = GL_TRUE;
+    }
 }
 
 /*
@@ -1622,47 +1602,49 @@ void fgJoystickInit( int ident )
 void fgJoystickClose( void )
 {
     int ident ;
-    for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
+    for( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
     {
-        if ( fgJoystick[ident] )
+        if( fgJoystick[ ident ] )
         {
 
 #if TARGET_HOST_MACINTOSH
-            ISpSuspend  ();
-            ISpStop     ();
-            ISpShutdown ();
+            ISpSuspend( );
+            ISpStop( );
+            ISpShutdown( );
 #endif
 
 #if TARGET_HOST_MAC_OSX
-            (*(fgJoystick[ident]->hidDev))->close(fgJoystick[ident]->hidDev);
+            ( *( fgJoystick[ ident ]->hidDev ) )->
+                close( fgJoystick[ ident ]->hidDev );
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
             /* Do nothing special */
 #endif
 
-#if TARGET_HOST_UNIX_X11
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-            if ( fgJoystick[ident]->os )
+#if TARGET_HOST_POSIX_X11
+#if defined( __FreeBSD__ ) || defined( __NetBSD__ )
+            if( fgJoystick[ident]->os )
             {
-                if ( ! fgJoystick[ident]->error )
-                    close ( fgJoystick[ident]->os->fd );
+                if( ! fgJoystick[ ident ]->error )
+                    close( fgJoystick[ ident ]->os->fd );
 #ifdef HAVE_USB_JS
-                if ( fgJoystick[ident]->os->hids )
-                    free (fgJoystick[ident]->os->hids);
-                if ( fgJoystick[ident]->os->hid_data_buf )
-                    free (fgJoystick[ident]->os->hid_data_buf);
+                if( fgJoystick[ ident ]->os->hids )
+                    free (fgJoystick[ ident ]->os->hids);
+                if( fgJoystick[ ident ]->os->hid_data_buf )
+                    free( fgJoystick[ ident ]->os->hid_data_buf );
 #endif
-                free (fgJoystick[ident]->os);
+                free( fgJoystick[ident]->os );
             }
 #endif
 
             if( ! fgJoystick[ident]->error )
-                close( fgJoystick[ident]->fd );
+                close( fgJoystick[ ident ]->fd );
 #endif
 
-            free( fgJoystick[ident] );
-            fgJoystick[ident] = NULL;  /* show joystick has been deinitialized */
+            free( fgJoystick[ ident ] );
+            fgJoystick[ ident ] = NULL;
+            /* show joystick has been deinitialized */
         }
     }
 }
@@ -1680,54 +1662,119 @@ void fgJoystickPollWindow( SFG_Window* window )
     freeglut_return_if_fail( window );
     freeglut_return_if_fail( FETCH_WCB( *window, Joystick ) );
 
-    for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
+    for( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
     {
-        if ( fgJoystick[ident] )
+        if( fgJoystick[ident] )
         {
             fghJoystickRead( fgJoystick[ident], &buttons, axes );
 
-            if ( !fgJoystick[ident]->error )
+            if( !fgJoystick[ident]->error )
                 INVOKE_WCB( *window, Joystick,
                             ( buttons,
-                              (int) (axes[ 0 ] * 1000.0f ),
-                              (int) (axes[ 1 ] * 1000.0f ),
-                              (int) (axes[ 2 ] * 1000.0f ) )
-                          );
+                              (int) ( axes[ 0 ] * 1000.0f ),
+                              (int) ( axes[ 1 ] * 1000.0f ),
+                              (int) ( axes[ 2 ] * 1000.0f ) )
+                );
         }
     }
 }
 
 /*
- * PWO: These jsJoystick class methods have not been implemented.
- *      We might consider adding such functions to freeglut-2.0.
+ * Implementation for glutDeviceGet(GLUT_HAS_JOYSTICK)
  */
-int  getNumAxes ( int ident )
-    { return fgJoystick[ident]->num_axes; }
-int  notWorking ( int ident )
-    { return fgJoystick[ident]->error; }
-
-float getDeadBand ( int ident, int axis )
-    { return fgJoystick[ident]->dead_band [ axis ]; }
-void  setDeadBand ( int ident, int axis, float db )
-    { fgJoystick[ident]->dead_band [ axis ] = db; }
-
-float getSaturation ( int ident, int axis )
-    { return fgJoystick[ident]->saturate [ axis ]; }
-void  setSaturation ( int ident, int axis, float st )
-    { fgJoystick[ident]->saturate [ axis ] = st; }
-
-void setMinRange ( int ident, float *axes )
-    { memcpy ( fgJoystick[ident]->min   , axes, fgJoystick[ident]->num_axes * sizeof(float) ); }
-void setMaxRange ( int ident, float *axes )
-    { memcpy ( fgJoystick[ident]->max   , axes, fgJoystick[ident]->num_axes * sizeof(float) ); }
-void setCenter   ( int ident, float *axes )
-    { memcpy ( fgJoystick[ident]->center, axes, fgJoystick[ident]->num_axes * sizeof(float) ); }
-
-void getMinRange ( int ident, float *axes )
-    { memcpy ( axes, fgJoystick[ident]->min   , fgJoystick[ident]->num_axes * sizeof(float) ); }
-void getMaxRange ( int ident, float *axes )
-    { memcpy ( axes, fgJoystick[ident]->max   , fgJoystick[ident]->num_axes * sizeof(float) ); }
-void getCenter   ( int ident, float *axes )
-    { memcpy ( axes, fgJoystick[ident]->center, fgJoystick[ident]->num_axes * sizeof(float) ); }
+int fgJoystickDetect( void )
+{
+    int ident;
+
+    fgInitialiseJoysticks ();
+
+    if ( !fgState.JoysticksInitialised )
+        return 0;
+
+    for( ident=0; ident<MAX_NUM_JOYSTICKS; ident++ )
+        if( fgJoystick[ident] && !fgJoystick[ident]->error )
+            return 1;
+
+    return 0;
+}
+
+/*
+ * Joystick information functions
+ */
+int  glutJoystickGetNumAxes( int ident )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetNumAxes" );
+    return fgJoystick[ ident ]->num_axes;
+}
+int  glutJoystickGetNumButtons( int ident )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetNumButtons" );
+    return fgJoystick[ ident ]->num_buttons;
+}
+int  glutJoystickNotWorking( int ident )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickNotWorking" );
+    return fgJoystick[ ident ]->error;
+}
+
+float glutJoystickGetDeadBand( int ident, int axis )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetDeadBand" );
+    return fgJoystick[ ident ]->dead_band [ axis ];
+}
+void  glutJoystickSetDeadBand( int ident, int axis, float db )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetDeadBand" );
+    fgJoystick[ ident ]->dead_band[ axis ] = db;
+}
+
+float glutJoystickGetSaturation( int ident, int axis )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetSaturation" );
+    return fgJoystick[ ident ]->saturate[ axis ];
+}
+void  glutJoystickSetSaturation( int ident, int axis, float st )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetSaturation" );
+    fgJoystick[ ident ]->saturate [ axis ] = st;
+}
+
+void glutJoystickSetMinRange( int ident, float *axes )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetMinRange" );
+    memcpy( fgJoystick[ ident ]->min, axes,
+            fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+void glutJoystickSetMaxRange( int ident, float *axes )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetMaxRange" );
+    memcpy( fgJoystick[ ident ]->max, axes,
+            fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+void glutJoystickSetCenter( int ident, float *axes )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetCenter" );
+    memcpy( fgJoystick[ ident ]->center, axes,
+            fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+
+void glutJoystickGetMinRange( int ident, float *axes )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetMinRange" );
+    memcpy( axes, fgJoystick[ ident ]->min,
+            fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+void glutJoystickGetMaxRange( int ident, float *axes )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetMaxRange" );
+    memcpy( axes, fgJoystick[ ident ]->max,
+            fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
+void glutJoystickGetCenter( int ident, float *axes )
+{
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetCenter" );
+    memcpy( axes, fgJoystick[ ident ]->center,
+            fgJoystick[ ident ]->num_axes * sizeof( float ) );
+}
 
 /*** END OF FILE ***/