src/joystick/SDL_gamecontroller.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 07 Jul 2014 10:26:28 -0700
changeset 8976 1a5d959d7b32
parent 8972 dfc759d7486f
child 9194 583176c5982f
permissions -rw-r--r--
Fixed mingw64 build and warnings
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../SDL_internal.h"
    22 
    23 /* This is the game controller API for Simple DirectMedia Layer */
    24 
    25 #include "SDL_events.h"
    26 #include "SDL_assert.h"
    27 #include "SDL_sysjoystick.h"
    28 #include "SDL_hints.h"
    29 #include "SDL_gamecontrollerdb.h"
    30 
    31 #if !SDL_EVENTS_DISABLED
    32 #include "../events/SDL_events_c.h"
    33 #endif
    34 #define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
    35 
    36 #define SDL_CONTROLLER_PLATFORM_FIELD "platform:"
    37 
    38 /* a list of currently opened game controllers */
    39 static SDL_GameController *SDL_gamecontrollers = NULL;
    40 
    41 /* keep track of the hat and mask value that transforms this hat movement into a button/axis press */
    42 struct _SDL_HatMapping
    43 {
    44     int hat;
    45     Uint8 mask;
    46 };
    47 
    48 #define k_nMaxReverseEntries 20
    49 
    50 /**
    51  * We are encoding the "HAT" as 0xhm. where h == hat ID and m == mask
    52  * MAX 4 hats supported
    53  */
    54 #define k_nMaxHatEntries 0x3f + 1
    55 
    56 /* our in memory mapping db between joystick objects and controller mappings */
    57 struct _SDL_ControllerMapping
    58 {
    59     SDL_JoystickGUID guid;
    60     const char *name;
    61 
    62     /* mapping of axis/button id to controller version */
    63     int axes[SDL_CONTROLLER_AXIS_MAX];
    64     int buttonasaxis[SDL_CONTROLLER_AXIS_MAX];
    65 
    66     int buttons[SDL_CONTROLLER_BUTTON_MAX];
    67     int axesasbutton[SDL_CONTROLLER_BUTTON_MAX];
    68     struct _SDL_HatMapping hatasbutton[SDL_CONTROLLER_BUTTON_MAX];
    69 
    70     /* reverse mapping, joystick indices to buttons */
    71     SDL_GameControllerAxis raxes[k_nMaxReverseEntries];
    72     SDL_GameControllerAxis rbuttonasaxis[k_nMaxReverseEntries];
    73 
    74     SDL_GameControllerButton rbuttons[k_nMaxReverseEntries];
    75     SDL_GameControllerButton raxesasbutton[k_nMaxReverseEntries];
    76     SDL_GameControllerButton rhatasbutton[k_nMaxHatEntries];
    77 
    78 };
    79 
    80 
    81 /* our hard coded list of mapping support */
    82 typedef struct _ControllerMapping_t
    83 {
    84     SDL_JoystickGUID guid;
    85     char *name;
    86     char *mapping;
    87     struct _ControllerMapping_t *next;
    88 } ControllerMapping_t;
    89 
    90 static ControllerMapping_t *s_pSupportedControllers = NULL;
    91 static ControllerMapping_t *s_pXInputMapping = NULL;
    92 
    93 /* The SDL game controller structure */
    94 struct _SDL_GameController
    95 {
    96     SDL_Joystick *joystick; /* underlying joystick device */
    97     int ref_count;
    98     Uint8 hatState[4]; /* the current hat state for this controller */
    99     struct _SDL_ControllerMapping mapping; /* the mapping object for this controller */
   100     struct _SDL_GameController *next; /* pointer to next game controller we have allocated */
   101 };
   102 
   103 
   104 int SDL_PrivateGameControllerAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis, Sint16 value);
   105 int SDL_PrivateGameControllerButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button, Uint8 state);
   106 
   107 /*
   108  * Event filter to fire controller events from joystick ones
   109  */
   110 int SDL_GameControllerEventWatcher(void *userdata, SDL_Event * event)
   111 {
   112     switch(event->type) {
   113     case SDL_JOYAXISMOTION:
   114         {
   115             SDL_GameController *controllerlist;
   116 
   117             if (event->jaxis.axis >= k_nMaxReverseEntries) break;
   118 
   119             controllerlist = SDL_gamecontrollers;
   120             while (controllerlist) {
   121                 if (controllerlist->joystick->instance_id == event->jaxis.which) {
   122                     if (controllerlist->mapping.raxes[event->jaxis.axis] >= 0) /* simple axis to axis, send it through */ {
   123                         SDL_GameControllerAxis axis = controllerlist->mapping.raxes[event->jaxis.axis];
   124                         Sint16 value = event->jaxis.value;
   125                         switch (axis) {
   126                             case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
   127                             case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
   128                                 /* Shift it to be 0 - 32767. */
   129                                 value = value / 2 + 16384;
   130                             default:
   131                                 break;
   132                         }
   133                         SDL_PrivateGameControllerAxis(controllerlist, axis, value);
   134                     } else if (controllerlist->mapping.raxesasbutton[event->jaxis.axis] >= 0) { /* simulate an axis as a button */
   135                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.raxesasbutton[event->jaxis.axis], ABS(event->jaxis.value) > 32768/2 ? SDL_PRESSED : SDL_RELEASED);
   136                     }
   137                     break;
   138                 }
   139                 controllerlist = controllerlist->next;
   140             }
   141         }
   142         break;
   143     case SDL_JOYBUTTONDOWN:
   144     case SDL_JOYBUTTONUP:
   145         {
   146             SDL_GameController *controllerlist;
   147 
   148             if (event->jbutton.button >= k_nMaxReverseEntries) break;
   149 
   150             controllerlist = SDL_gamecontrollers;
   151             while (controllerlist) {
   152                 if (controllerlist->joystick->instance_id == event->jbutton.which) {
   153                     if (controllerlist->mapping.rbuttons[event->jbutton.button] >= 0) { /* simple button as button */
   154                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rbuttons[event->jbutton.button], event->jbutton.state);
   155                     } else if (controllerlist->mapping.rbuttonasaxis[event->jbutton.button] >= 0) { /* an button pretending to be an axis */
   156                         SDL_PrivateGameControllerAxis(controllerlist, controllerlist->mapping.rbuttonasaxis[event->jbutton.button], event->jbutton.state > 0 ? 32767 : 0);
   157                     }
   158                     break;
   159                 }
   160                 controllerlist = controllerlist->next;
   161             }
   162         }
   163         break;
   164     case SDL_JOYHATMOTION:
   165         {
   166             SDL_GameController *controllerlist;
   167 
   168             if (event->jhat.hat >= 4) break;
   169 
   170             controllerlist = SDL_gamecontrollers;
   171             while (controllerlist) {
   172                 if (controllerlist->joystick->instance_id == event->jhat.which) {
   173                     Uint8 bSame = controllerlist->hatState[event->jhat.hat] & event->jhat.value;
   174                     /* Get list of removed bits (button release) */
   175                     Uint8 bChanged = controllerlist->hatState[event->jhat.hat] ^ bSame;
   176                     /* the hat idx in the high nibble */
   177                     int bHighHat = event->jhat.hat << 4;
   178 
   179                     if (bChanged & SDL_HAT_DOWN)
   180                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_DOWN], SDL_RELEASED);
   181                     if (bChanged & SDL_HAT_UP)
   182                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_UP], SDL_RELEASED);
   183                     if (bChanged & SDL_HAT_LEFT)
   184                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_LEFT], SDL_RELEASED);
   185                     if (bChanged & SDL_HAT_RIGHT)
   186                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_RIGHT], SDL_RELEASED);
   187 
   188                     /* Get list of added bits (button press) */
   189                     bChanged = event->jhat.value ^ bSame;
   190 
   191                     if (bChanged & SDL_HAT_DOWN)
   192                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_DOWN], SDL_PRESSED);
   193                     if (bChanged & SDL_HAT_UP)
   194                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_UP], SDL_PRESSED);
   195                     if (bChanged & SDL_HAT_LEFT)
   196                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_LEFT], SDL_PRESSED);
   197                     if (bChanged & SDL_HAT_RIGHT)
   198                         SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_RIGHT], SDL_PRESSED);
   199 
   200                     /* update our state cache */
   201                     controllerlist->hatState[event->jhat.hat] = event->jhat.value;
   202 
   203                     break;
   204                 }
   205                 controllerlist = controllerlist->next;
   206             }
   207         }
   208         break;
   209     case SDL_JOYDEVICEADDED:
   210         {
   211             if (SDL_IsGameController(event->jdevice.which)) {
   212                 SDL_Event deviceevent;
   213                 deviceevent.type = SDL_CONTROLLERDEVICEADDED;
   214                 deviceevent.cdevice.which = event->jdevice.which;
   215                 SDL_PushEvent(&deviceevent);
   216             }
   217         }
   218         break;
   219     case SDL_JOYDEVICEREMOVED:
   220         {
   221             SDL_GameController *controllerlist = SDL_gamecontrollers;
   222             while (controllerlist) {
   223                 if (controllerlist->joystick->instance_id == event->jdevice.which) {
   224                     SDL_Event deviceevent;
   225                     deviceevent.type = SDL_CONTROLLERDEVICEREMOVED;
   226                     deviceevent.cdevice.which = event->jdevice.which;
   227                     SDL_PushEvent(&deviceevent);
   228                     break;
   229                 }
   230                 controllerlist = controllerlist->next;
   231             }
   232         }
   233         break;
   234     default:
   235         break;
   236     }
   237 
   238     return 1;
   239 }
   240 
   241 /*
   242  * Helper function to scan the mappings database for a controller with the specified GUID
   243  */
   244 ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickGUID *guid)
   245 {
   246     ControllerMapping_t *pSupportedController = s_pSupportedControllers;
   247     while (pSupportedController) {
   248         if (SDL_memcmp(guid, &pSupportedController->guid, sizeof(*guid)) == 0) {
   249             return pSupportedController;
   250         }
   251         pSupportedController = pSupportedController->next;
   252     }
   253     return NULL;
   254 }
   255 
   256 /*
   257  * Helper function to determine pre-calculated offset to certain joystick mappings
   258  */
   259 ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
   260 {
   261 #if SDL_JOYSTICK_XINPUT
   262     if (SDL_SYS_IsXInputGamepad_DeviceIndex(device_index) && s_pXInputMapping) {
   263         return s_pXInputMapping;
   264     }
   265     else
   266 #endif /* SDL_JOYSTICK_XINPUT */
   267     {
   268         SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
   269         return SDL_PrivateGetControllerMappingForGUID(&jGUID);
   270     }
   271 }
   272 
   273 static const char* map_StringForControllerAxis[] = {
   274     "leftx",
   275     "lefty",
   276     "rightx",
   277     "righty",
   278     "lefttrigger",
   279     "righttrigger",
   280     NULL
   281 };
   282 
   283 /*
   284  * convert a string to its enum equivalent
   285  */
   286 SDL_GameControllerAxis SDL_GameControllerGetAxisFromString(const char *pchString)
   287 {
   288     int entry;
   289     if (!pchString || !pchString[0])
   290         return SDL_CONTROLLER_AXIS_INVALID;
   291 
   292     for (entry = 0; map_StringForControllerAxis[entry]; ++entry) {
   293         if (!SDL_strcasecmp(pchString, map_StringForControllerAxis[entry]))
   294             return entry;
   295     }
   296     return SDL_CONTROLLER_AXIS_INVALID;
   297 }
   298 
   299 /*
   300  * convert an enum to its string equivalent
   301  */
   302 const char* SDL_GameControllerGetStringForAxis(SDL_GameControllerAxis axis)
   303 {
   304     if (axis > SDL_CONTROLLER_AXIS_INVALID && axis < SDL_CONTROLLER_AXIS_MAX) {
   305         return map_StringForControllerAxis[axis];
   306     }
   307     return NULL;
   308 }
   309 
   310 static const char* map_StringForControllerButton[] = {
   311     "a",
   312     "b",
   313     "x",
   314     "y",
   315     "back",
   316     "guide",
   317     "start",
   318     "leftstick",
   319     "rightstick",
   320     "leftshoulder",
   321     "rightshoulder",
   322     "dpup",
   323     "dpdown",
   324     "dpleft",
   325     "dpright",
   326     NULL
   327 };
   328 
   329 /*
   330  * convert a string to its enum equivalent
   331  */
   332 SDL_GameControllerButton SDL_GameControllerGetButtonFromString(const char *pchString)
   333 {
   334     int entry;
   335     if (!pchString || !pchString[0])
   336         return SDL_CONTROLLER_BUTTON_INVALID;
   337 
   338     for (entry = 0; map_StringForControllerButton[entry]; ++entry) {
   339         if (SDL_strcasecmp(pchString, map_StringForControllerButton[entry]) == 0)
   340             return entry;
   341     }
   342     return SDL_CONTROLLER_BUTTON_INVALID;
   343 }
   344 
   345 /*
   346  * convert an enum to its string equivalent
   347  */
   348 const char* SDL_GameControllerGetStringForButton(SDL_GameControllerButton axis)
   349 {
   350     if (axis > SDL_CONTROLLER_BUTTON_INVALID && axis < SDL_CONTROLLER_BUTTON_MAX) {
   351         return map_StringForControllerButton[axis];
   352     }
   353     return NULL;
   354 }
   355 
   356 /*
   357  * given a controller button name and a joystick name update our mapping structure with it
   358  */
   359 void SDL_PrivateGameControllerParseButton(const char *szGameButton, const char *szJoystickButton, struct _SDL_ControllerMapping *pMapping)
   360 {
   361     int iSDLButton = 0;
   362     SDL_GameControllerButton button;
   363     SDL_GameControllerAxis axis;
   364     button = SDL_GameControllerGetButtonFromString(szGameButton);
   365     axis = SDL_GameControllerGetAxisFromString(szGameButton);
   366     iSDLButton = SDL_atoi(&szJoystickButton[1]);
   367 
   368     if (szJoystickButton[0] == 'a') {
   369         if (iSDLButton >= k_nMaxReverseEntries) {
   370             SDL_SetError("Axis index too large: %d", iSDLButton);
   371             return;
   372         }
   373         if (axis != SDL_CONTROLLER_AXIS_INVALID) {
   374             pMapping->axes[ axis ] = iSDLButton;
   375             pMapping->raxes[ iSDLButton ] = axis;
   376         } else if (button != SDL_CONTROLLER_BUTTON_INVALID) {
   377             pMapping->axesasbutton[ button ] = iSDLButton;
   378             pMapping->raxesasbutton[ iSDLButton ] = button;
   379         } else {
   380             SDL_assert(!"How did we get here?");
   381         }
   382 
   383     } else if (szJoystickButton[0] == 'b') {
   384         if (iSDLButton >= k_nMaxReverseEntries) {
   385             SDL_SetError("Button index too large: %d", iSDLButton);
   386             return;
   387         }
   388         if (button != SDL_CONTROLLER_BUTTON_INVALID) {
   389             pMapping->buttons[ button ] = iSDLButton;
   390             pMapping->rbuttons[ iSDLButton ] = button;
   391         } else if (axis != SDL_CONTROLLER_AXIS_INVALID) {
   392             pMapping->buttonasaxis[ axis ] = iSDLButton;
   393             pMapping->rbuttonasaxis[ iSDLButton ] = axis;
   394         } else {
   395             SDL_assert(!"How did we get here?");
   396         }
   397     } else if (szJoystickButton[0] == 'h') {
   398         int hat = SDL_atoi(&szJoystickButton[1]);
   399         int mask = SDL_atoi(&szJoystickButton[3]);
   400         if (hat >= 4) {
   401             SDL_SetError("Hat index too large: %d", iSDLButton);
   402         }
   403 
   404         if (button != SDL_CONTROLLER_BUTTON_INVALID) {
   405             int ridx;
   406             pMapping->hatasbutton[ button ].hat = hat;
   407             pMapping->hatasbutton[ button ].mask = mask;
   408             ridx = (hat << 4) | mask;
   409             pMapping->rhatasbutton[ ridx ] = button;
   410         } else if (axis != SDL_CONTROLLER_AXIS_INVALID) {
   411             SDL_assert(!"Support hat as axis");
   412         } else {
   413             SDL_assert(!"How did we get here?");
   414         }
   415     }
   416 }
   417 
   418 
   419 /*
   420  * given a controller mapping string update our mapping object
   421  */
   422 static void
   423 SDL_PrivateGameControllerParseControllerConfigString(struct _SDL_ControllerMapping *pMapping, const char *pchString)
   424 {
   425     char szGameButton[20];
   426     char szJoystickButton[20];
   427     SDL_bool bGameButton = SDL_TRUE;
   428     int i = 0;
   429     const char *pchPos = pchString;
   430 
   431     SDL_memset(szGameButton, 0x0, sizeof(szGameButton));
   432     SDL_memset(szJoystickButton, 0x0, sizeof(szJoystickButton));
   433 
   434     while (pchPos && *pchPos) {
   435         if (*pchPos == ':') {
   436             i = 0;
   437             bGameButton = SDL_FALSE;
   438         } else if (*pchPos == ' ') {
   439 
   440         } else if (*pchPos == ',') {
   441             i = 0;
   442             bGameButton = SDL_TRUE;
   443             SDL_PrivateGameControllerParseButton(szGameButton, szJoystickButton, pMapping);
   444             SDL_memset(szGameButton, 0x0, sizeof(szGameButton));
   445             SDL_memset(szJoystickButton, 0x0, sizeof(szJoystickButton));
   446 
   447         } else if (bGameButton) {
   448             if (i >= sizeof(szGameButton)) {
   449                 SDL_SetError("Button name too large: %s", szGameButton);
   450                 return;
   451             }
   452             szGameButton[i] = *pchPos;
   453             i++;
   454         } else {
   455             if (i >= sizeof(szJoystickButton)) {
   456                 SDL_SetError("Joystick button name too large: %s", szJoystickButton);
   457                 return;
   458             }
   459             szJoystickButton[i] = *pchPos;
   460             i++;
   461         }
   462         pchPos++;
   463     }
   464 
   465     SDL_PrivateGameControllerParseButton(szGameButton, szJoystickButton, pMapping);
   466 
   467 }
   468 
   469 /*
   470  * Make a new button mapping struct
   471  */
   472 void SDL_PrivateLoadButtonMapping(struct _SDL_ControllerMapping *pMapping, SDL_JoystickGUID guid, const char *pchName, const char *pchMapping)
   473 {
   474     int j;
   475 
   476     pMapping->guid = guid;
   477     pMapping->name = pchName;
   478 
   479     /* set all the button mappings to non defaults */
   480     for (j = 0; j < SDL_CONTROLLER_AXIS_MAX; j++) {
   481         pMapping->axes[j] = -1;
   482         pMapping->buttonasaxis[j] = -1;
   483     }
   484     for (j = 0; j < SDL_CONTROLLER_BUTTON_MAX; j++) {
   485         pMapping->buttons[j] = -1;
   486         pMapping->axesasbutton[j] = -1;
   487         pMapping->hatasbutton[j].hat = -1;
   488     }
   489 
   490     for (j = 0; j < k_nMaxReverseEntries; j++) {
   491         pMapping->raxes[j] = SDL_CONTROLLER_AXIS_INVALID;
   492         pMapping->rbuttonasaxis[j] = SDL_CONTROLLER_AXIS_INVALID;
   493         pMapping->rbuttons[j] = SDL_CONTROLLER_BUTTON_INVALID;
   494         pMapping->raxesasbutton[j] = SDL_CONTROLLER_BUTTON_INVALID;
   495     }
   496 
   497     for (j = 0; j < k_nMaxHatEntries; j++) {
   498         pMapping->rhatasbutton[j] = SDL_CONTROLLER_BUTTON_INVALID;
   499     }
   500 
   501     SDL_PrivateGameControllerParseControllerConfigString(pMapping, pchMapping);
   502 }
   503 
   504 
   505 /*
   506  * grab the guid string from a mapping string
   507  */
   508 char *SDL_PrivateGetControllerGUIDFromMappingString(const char *pMapping)
   509 {
   510     const char *pFirstComma = SDL_strchr(pMapping, ',');
   511     if (pFirstComma) {
   512         char *pchGUID = SDL_malloc(pFirstComma - pMapping + 1);
   513         if (!pchGUID) {
   514             SDL_OutOfMemory();
   515             return NULL;
   516         }
   517         SDL_memcpy(pchGUID, pMapping, pFirstComma - pMapping);
   518         pchGUID[ pFirstComma - pMapping ] = 0;
   519         return pchGUID;
   520     }
   521     return NULL;
   522 }
   523 
   524 
   525 /*
   526  * grab the name string from a mapping string
   527  */
   528 char *SDL_PrivateGetControllerNameFromMappingString(const char *pMapping)
   529 {
   530     const char *pFirstComma, *pSecondComma;
   531     char *pchName;
   532 
   533     pFirstComma = SDL_strchr(pMapping, ',');
   534     if (!pFirstComma)
   535         return NULL;
   536 
   537     pSecondComma = SDL_strchr(pFirstComma + 1, ',');
   538     if (!pSecondComma)
   539         return NULL;
   540 
   541     pchName = SDL_malloc(pSecondComma - pFirstComma);
   542     if (!pchName) {
   543         SDL_OutOfMemory();
   544         return NULL;
   545     }
   546     SDL_memcpy(pchName, pFirstComma + 1, pSecondComma - pFirstComma);
   547     pchName[ pSecondComma - pFirstComma - 1 ] = 0;
   548     return pchName;
   549 }
   550 
   551 
   552 /*
   553  * grab the button mapping string from a mapping string
   554  */
   555 char *SDL_PrivateGetControllerMappingFromMappingString(const char *pMapping)
   556 {
   557     const char *pFirstComma, *pSecondComma;
   558 
   559     pFirstComma = SDL_strchr(pMapping, ',');
   560     if (!pFirstComma)
   561         return NULL;
   562 
   563     pSecondComma = SDL_strchr(pFirstComma + 1, ',');
   564     if (!pSecondComma)
   565         return NULL;
   566 
   567     return SDL_strdup(pSecondComma + 1); /* mapping is everything after the 3rd comma */
   568 }
   569 
   570 void SDL_PrivateGameControllerRefreshMapping(ControllerMapping_t *pControllerMapping)
   571 {
   572     SDL_GameController *gamecontrollerlist = SDL_gamecontrollers;
   573     while (gamecontrollerlist) {
   574         if (!SDL_memcmp(&gamecontrollerlist->mapping.guid, &pControllerMapping->guid, sizeof(pControllerMapping->guid))) {
   575             SDL_Event event;
   576             event.type = SDL_CONTROLLERDEVICEREMAPPED;
   577             event.cdevice.which = gamecontrollerlist->joystick->instance_id;
   578             SDL_PushEvent(&event);
   579 
   580             /* Not really threadsafe.  Should this lock access within SDL_GameControllerEventWatcher? */
   581             SDL_PrivateLoadButtonMapping(&gamecontrollerlist->mapping, pControllerMapping->guid, pControllerMapping->name, pControllerMapping->mapping);
   582         }
   583 
   584         gamecontrollerlist = gamecontrollerlist->next;
   585     }
   586 }
   587 
   588 /*
   589  * Add or update an entry into the Mappings Database
   590  */
   591 int
   592 SDL_GameControllerAddMappingsFromRW(SDL_RWops * rw, int freerw)
   593 {
   594     const char *platform = SDL_GetPlatform();
   595     int controllers = 0;
   596     char *buf, *line, *line_end, *tmp, *comma, line_platform[64];
   597     size_t db_size, platform_len;
   598     
   599     if (rw == NULL) {
   600         return SDL_SetError("Invalid RWops");
   601     }
   602     db_size = (size_t)SDL_RWsize(rw);
   603     
   604     buf = (char *)SDL_malloc(db_size + 1);
   605     if (buf == NULL) {
   606         if (freerw) {
   607             SDL_RWclose(rw);
   608         }
   609         return SDL_SetError("Could allocate space to not read DB into memory");
   610     }
   611     
   612     if (SDL_RWread(rw, buf, db_size, 1) != 1) {
   613         if (freerw) {
   614             SDL_RWclose(rw);
   615         }
   616         SDL_free(buf);
   617         return SDL_SetError("Could not read DB");
   618     }
   619     
   620     if (freerw) {
   621         SDL_RWclose(rw);
   622     }
   623     
   624     buf[db_size] = '\0';
   625     line = buf;
   626     
   627     while (line < buf + db_size) {
   628         line_end = SDL_strchr(line, '\n');
   629         if (line_end != NULL) {
   630             *line_end = '\0';
   631         } else {
   632             line_end = buf + db_size;
   633         }
   634         
   635         /* Extract and verify the platform */
   636         tmp = SDL_strstr(line, SDL_CONTROLLER_PLATFORM_FIELD);
   637         if (tmp != NULL) {
   638             tmp += SDL_strlen(SDL_CONTROLLER_PLATFORM_FIELD);
   639             comma = SDL_strchr(tmp, ',');
   640             if (comma != NULL) {
   641                 platform_len = comma - tmp + 1;
   642                 if (platform_len + 1 < SDL_arraysize(line_platform)) {
   643                     SDL_strlcpy(line_platform, tmp, platform_len);
   644                     if (SDL_strncasecmp(line_platform, platform, platform_len) == 0 &&
   645                         SDL_GameControllerAddMapping(line) > 0) {
   646                         controllers++;
   647                     }
   648                 }
   649             }
   650         }
   651         
   652         line = line_end + 1;
   653     }
   654 
   655     SDL_free(buf);
   656     return controllers;
   657 }
   658 
   659 /*
   660  * Add or update an entry into the Mappings Database
   661  */
   662 int
   663 SDL_GameControllerAddMapping(const char *mappingString)
   664 {
   665     char *pchGUID;
   666     char *pchName;
   667     char *pchMapping;
   668     SDL_JoystickGUID jGUID;
   669     ControllerMapping_t *pControllerMapping;
   670     SDL_bool is_xinput_mapping = SDL_FALSE;
   671 
   672     pchGUID = SDL_PrivateGetControllerGUIDFromMappingString(mappingString);
   673     if (!pchGUID) {
   674         return SDL_SetError("Couldn't parse GUID from %s", mappingString);
   675     }
   676     if (!SDL_strcasecmp(pchGUID, "xinput")) {
   677         is_xinput_mapping = SDL_TRUE;
   678     }
   679     jGUID = SDL_JoystickGetGUIDFromString(pchGUID);
   680     SDL_free(pchGUID);
   681 
   682     pchName = SDL_PrivateGetControllerNameFromMappingString(mappingString);
   683     if (!pchName) {
   684         return SDL_SetError("Couldn't parse name from %s", mappingString);
   685     }
   686 
   687     pchMapping = SDL_PrivateGetControllerMappingFromMappingString(mappingString);
   688     if (!pchMapping) {
   689         SDL_free(pchName);
   690         return SDL_SetError("Couldn't parse %s", mappingString);
   691     }
   692 
   693     pControllerMapping = SDL_PrivateGetControllerMappingForGUID(&jGUID);
   694 
   695     if (pControllerMapping) {
   696         /* Update existing mapping */
   697         SDL_free(pControllerMapping->name);
   698         pControllerMapping->name = pchName;
   699         SDL_free(pControllerMapping->mapping);
   700         pControllerMapping->mapping = pchMapping;
   701         /* refresh open controllers */
   702         SDL_PrivateGameControllerRefreshMapping(pControllerMapping);
   703         return 0;
   704     } else {
   705         pControllerMapping = SDL_malloc(sizeof(*pControllerMapping));
   706         if (!pControllerMapping) {
   707             SDL_free(pchName);
   708             SDL_free(pchMapping);
   709             return SDL_OutOfMemory();
   710         }
   711         if (is_xinput_mapping) {
   712             s_pXInputMapping = pControllerMapping;
   713         }
   714         pControllerMapping->guid = jGUID;
   715         pControllerMapping->name = pchName;
   716         pControllerMapping->mapping = pchMapping;
   717         pControllerMapping->next = s_pSupportedControllers;
   718         s_pSupportedControllers = pControllerMapping;
   719         return 1;
   720     }
   721 }
   722 
   723 /*
   724  * Get the mapping string for this GUID
   725  */
   726 char *
   727 SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid)
   728 {
   729     char *pMappingString = NULL;
   730     ControllerMapping_t *mapping = SDL_PrivateGetControllerMappingForGUID(&guid);
   731     if (mapping) {
   732         char pchGUID[33];
   733         size_t needed;
   734         SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID));
   735         /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */
   736         needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1;
   737         pMappingString = SDL_malloc(needed);
   738         SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping);
   739     }
   740     return pMappingString;
   741 }
   742 
   743 /*
   744  * Get the mapping string for this device
   745  */
   746 char *
   747 SDL_GameControllerMapping(SDL_GameController * gamecontroller)
   748 {
   749     return SDL_GameControllerMappingForGUID(gamecontroller->mapping.guid);
   750 }
   751 
   752 static void
   753 SDL_GameControllerLoadHints()
   754 {
   755     const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLERCONFIG);
   756     if (hint && hint[0]) {
   757         size_t nchHints = SDL_strlen(hint);
   758         char *pUserMappings = SDL_malloc(nchHints + 1);
   759         char *pTempMappings = pUserMappings;
   760         SDL_memcpy(pUserMappings, hint, nchHints);
   761         pUserMappings[nchHints] = '\0';
   762         while (pUserMappings) {
   763             char *pchNewLine = NULL;
   764 
   765             pchNewLine = SDL_strchr(pUserMappings, '\n');
   766             if (pchNewLine)
   767                 *pchNewLine = '\0';
   768 
   769             SDL_GameControllerAddMapping(pUserMappings);
   770 
   771             if (pchNewLine) {
   772                 pUserMappings = pchNewLine + 1;
   773             } else {
   774                 pUserMappings = NULL;
   775             }
   776         }
   777         SDL_free(pTempMappings);
   778     }
   779 }
   780 
   781 /*
   782  * Initialize the game controller system, mostly load our DB of controller config mappings
   783  */
   784 int
   785 SDL_GameControllerInit(void)
   786 {
   787     int i = 0;
   788     const char *pMappingString = NULL;
   789     s_pSupportedControllers = NULL;
   790     pMappingString = s_ControllerMappings[i];
   791     while (pMappingString) {
   792         SDL_GameControllerAddMapping(pMappingString);
   793 
   794         i++;
   795         pMappingString = s_ControllerMappings[i];
   796     }
   797 
   798     /* load in any user supplied config */
   799     SDL_GameControllerLoadHints();
   800 
   801     /* watch for joy events and fire controller ones if needed */
   802     SDL_AddEventWatch(SDL_GameControllerEventWatcher, NULL);
   803 
   804     /* Send added events for controllers currently attached */
   805     for (i = 0; i < SDL_NumJoysticks(); ++i) {
   806         if (SDL_IsGameController(i)) {
   807             SDL_Event deviceevent;
   808             deviceevent.type = SDL_CONTROLLERDEVICEADDED;
   809             deviceevent.cdevice.which = i;
   810             SDL_PushEvent(&deviceevent);
   811         }
   812     }
   813 
   814     return (0);
   815 }
   816 
   817 
   818 /*
   819  * Get the implementation dependent name of a controller
   820  */
   821 const char *
   822 SDL_GameControllerNameForIndex(int device_index)
   823 {
   824     ControllerMapping_t *pSupportedController =  SDL_PrivateGetControllerMapping(device_index);
   825     if (pSupportedController) {
   826         return pSupportedController->name;
   827     }
   828     return NULL;
   829 }
   830 
   831 
   832 /*
   833  * Return 1 if the joystick at this device index is a supported controller
   834  */
   835 SDL_bool
   836 SDL_IsGameController(int device_index)
   837 {
   838     ControllerMapping_t *pSupportedController =  SDL_PrivateGetControllerMapping(device_index);
   839     if (pSupportedController) {
   840         return SDL_TRUE;
   841     }
   842 
   843     return SDL_FALSE;
   844 }
   845 
   846 /*
   847  * Open a controller for use - the index passed as an argument refers to
   848  * the N'th controller on the system.  This index is the value which will
   849  * identify this controller in future controller events.
   850  *
   851  * This function returns a controller identifier, or NULL if an error occurred.
   852  */
   853 SDL_GameController *
   854 SDL_GameControllerOpen(int device_index)
   855 {
   856     SDL_GameController *gamecontroller;
   857     SDL_GameController *gamecontrollerlist;
   858     ControllerMapping_t *pSupportedController = NULL;
   859 
   860     if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
   861         SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
   862         return (NULL);
   863     }
   864 
   865     gamecontrollerlist = SDL_gamecontrollers;
   866     /* If the controller is already open, return it */
   867     while (gamecontrollerlist) {
   868         if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == gamecontrollerlist->joystick->instance_id) {
   869                 gamecontroller = gamecontrollerlist;
   870                 ++gamecontroller->ref_count;
   871                 return (gamecontroller);
   872         }
   873         gamecontrollerlist = gamecontrollerlist->next;
   874     }
   875 
   876     /* Find a controller mapping */
   877     pSupportedController =  SDL_PrivateGetControllerMapping(device_index);
   878     if (!pSupportedController) {
   879         SDL_SetError("Couldn't find mapping for device (%d)", device_index);
   880         return (NULL);
   881     }
   882 
   883     /* Create and initialize the joystick */
   884     gamecontroller = (SDL_GameController *) SDL_malloc((sizeof *gamecontroller));
   885     if (gamecontroller == NULL) {
   886         SDL_OutOfMemory();
   887         return NULL;
   888     }
   889 
   890     SDL_memset(gamecontroller, 0, (sizeof *gamecontroller));
   891     gamecontroller->joystick = SDL_JoystickOpen(device_index);
   892     if (!gamecontroller->joystick) {
   893         SDL_free(gamecontroller);
   894         return NULL;
   895     }
   896 
   897     SDL_PrivateLoadButtonMapping(&gamecontroller->mapping, pSupportedController->guid, pSupportedController->name, pSupportedController->mapping);
   898 
   899     /* Add joystick to list */
   900     ++gamecontroller->ref_count;
   901     /* Link the joystick in the list */
   902     gamecontroller->next = SDL_gamecontrollers;
   903     SDL_gamecontrollers = gamecontroller;
   904 
   905     SDL_SYS_JoystickUpdate(gamecontroller->joystick);
   906 
   907     return (gamecontroller);
   908 }
   909 
   910 /*
   911  * Manually pump for controller updates.
   912  */
   913 void
   914 SDL_GameControllerUpdate(void)
   915 {
   916     /* Just for API completeness; the joystick API does all the work. */
   917     SDL_JoystickUpdate();
   918 }
   919 
   920 
   921 /*
   922  * Get the current state of an axis control on a controller
   923  */
   924 Sint16
   925 SDL_GameControllerGetAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis)
   926 {
   927     if (!gamecontroller)
   928         return 0;
   929 
   930     if (gamecontroller->mapping.axes[axis] >= 0) {
   931         Sint16 value = (SDL_JoystickGetAxis(gamecontroller->joystick, gamecontroller->mapping.axes[axis]));
   932         switch (axis) {
   933             case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
   934             case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
   935                 /* Shift it to be 0 - 32767. */
   936                 value = value / 2 + 16384;
   937             default:
   938                 break;
   939         }
   940         return value;
   941     } else if (gamecontroller->mapping.buttonasaxis[axis] >= 0) {
   942         Uint8 value;
   943         value = SDL_JoystickGetButton(gamecontroller->joystick, gamecontroller->mapping.buttonasaxis[axis]);
   944         if (value > 0)
   945             return 32767;
   946         return 0;
   947     }
   948     return 0;
   949 }
   950 
   951 
   952 /*
   953  * Get the current state of a button on a controller
   954  */
   955 Uint8
   956 SDL_GameControllerGetButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button)
   957 {
   958     if (!gamecontroller)
   959         return 0;
   960 
   961     if (gamecontroller->mapping.buttons[button] >= 0) {
   962         return (SDL_JoystickGetButton(gamecontroller->joystick, gamecontroller->mapping.buttons[button]));
   963     } else if (gamecontroller->mapping.axesasbutton[button] >= 0) {
   964         Sint16 value;
   965         value = SDL_JoystickGetAxis(gamecontroller->joystick, gamecontroller->mapping.axesasbutton[button]);
   966         if (ABS(value) > 32768/2)
   967             return 1;
   968         return 0;
   969     } else if (gamecontroller->mapping.hatasbutton[button].hat >= 0) {
   970         Uint8 value;
   971         value = SDL_JoystickGetHat(gamecontroller->joystick, gamecontroller->mapping.hatasbutton[button].hat);
   972 
   973         if (value & gamecontroller->mapping.hatasbutton[button].mask)
   974             return 1;
   975         return 0;
   976     }
   977 
   978     return 0;
   979 }
   980 
   981 /*
   982  * Return if the joystick in question is currently attached to the system,
   983  *  \return 0 if not plugged in, 1 if still present.
   984  */
   985 SDL_bool
   986 SDL_GameControllerGetAttached(SDL_GameController * gamecontroller)
   987 {
   988     if (!gamecontroller)
   989         return SDL_FALSE;
   990 
   991     return SDL_JoystickGetAttached(gamecontroller->joystick);
   992 }
   993 
   994 
   995 /*
   996  * Get the number of multi-dimensional axis controls on a joystick
   997  */
   998 const char *
   999 SDL_GameControllerName(SDL_GameController * gamecontroller)
  1000 {
  1001     if (!gamecontroller)
  1002         return NULL;
  1003 
  1004     return (gamecontroller->mapping.name);
  1005 }
  1006 
  1007 
  1008 /*
  1009  * Get the joystick for this controller
  1010  */
  1011 SDL_Joystick *SDL_GameControllerGetJoystick(SDL_GameController * gamecontroller)
  1012 {
  1013     if (!gamecontroller)
  1014         return NULL;
  1015 
  1016     return gamecontroller->joystick;
  1017 }
  1018 
  1019 /**
  1020  * Get the SDL joystick layer binding for this controller axis mapping
  1021  */
  1022 SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis)
  1023 {
  1024     SDL_GameControllerButtonBind bind;
  1025     SDL_memset(&bind, 0x0, sizeof(bind));
  1026 
  1027     if (!gamecontroller || axis == SDL_CONTROLLER_AXIS_INVALID)
  1028         return bind;
  1029 
  1030     if (gamecontroller->mapping.axes[axis] >= 0) {
  1031         bind.bindType = SDL_CONTROLLER_BINDTYPE_AXIS;
  1032         bind.value.button = gamecontroller->mapping.axes[axis];
  1033     } else if (gamecontroller->mapping.buttonasaxis[axis] >= 0) {
  1034         bind.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON;
  1035         bind.value.button = gamecontroller->mapping.buttonasaxis[axis];
  1036     }
  1037 
  1038     return bind;
  1039 }
  1040 
  1041 
  1042 /**
  1043  * Get the SDL joystick layer binding for this controller button mapping
  1044  */
  1045 SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button)
  1046 {
  1047     SDL_GameControllerButtonBind bind;
  1048     SDL_memset(&bind, 0x0, sizeof(bind));
  1049 
  1050     if (!gamecontroller || button == SDL_CONTROLLER_BUTTON_INVALID)
  1051         return bind;
  1052 
  1053     if (gamecontroller->mapping.buttons[button] >= 0) {
  1054         bind.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON;
  1055         bind.value.button = gamecontroller->mapping.buttons[button];
  1056     } else if (gamecontroller->mapping.axesasbutton[button] >= 0) {
  1057         bind.bindType = SDL_CONTROLLER_BINDTYPE_AXIS;
  1058         bind.value.axis = gamecontroller->mapping.axesasbutton[button];
  1059     } else if (gamecontroller->mapping.hatasbutton[button].hat >= 0) {
  1060         bind.bindType = SDL_CONTROLLER_BINDTYPE_HAT;
  1061         bind.value.hat.hat = gamecontroller->mapping.hatasbutton[button].hat;
  1062         bind.value.hat.hat_mask = gamecontroller->mapping.hatasbutton[button].mask;
  1063     }
  1064 
  1065     return bind;
  1066 }
  1067 
  1068 
  1069 /*
  1070  * Close a joystick previously opened with SDL_JoystickOpen()
  1071  */
  1072 void
  1073 SDL_GameControllerClose(SDL_GameController * gamecontroller)
  1074 {
  1075     SDL_GameController *gamecontrollerlist, *gamecontrollerlistprev;
  1076 
  1077     if (!gamecontroller)
  1078         return;
  1079 
  1080     /* First decrement ref count */
  1081     if (--gamecontroller->ref_count > 0) {
  1082         return;
  1083     }
  1084 
  1085     SDL_JoystickClose(gamecontroller->joystick);
  1086 
  1087     gamecontrollerlist = SDL_gamecontrollers;
  1088     gamecontrollerlistprev = NULL;
  1089     while (gamecontrollerlist) {
  1090         if (gamecontroller == gamecontrollerlist) {
  1091             if (gamecontrollerlistprev) {
  1092                 /* unlink this entry */
  1093                 gamecontrollerlistprev->next = gamecontrollerlist->next;
  1094             } else {
  1095                 SDL_gamecontrollers = gamecontroller->next;
  1096             }
  1097 
  1098             break;
  1099         }
  1100         gamecontrollerlistprev = gamecontrollerlist;
  1101         gamecontrollerlist = gamecontrollerlist->next;
  1102     }
  1103 
  1104     SDL_free(gamecontroller);
  1105 }
  1106 
  1107 
  1108 /*
  1109  * Quit the controller subsystem
  1110  */
  1111 void
  1112 SDL_GameControllerQuit(void)
  1113 {
  1114     ControllerMapping_t *pControllerMap;
  1115     while (SDL_gamecontrollers) {
  1116         SDL_gamecontrollers->ref_count = 1;
  1117         SDL_GameControllerClose(SDL_gamecontrollers);
  1118     }
  1119 
  1120     while (s_pSupportedControllers) {
  1121         pControllerMap = s_pSupportedControllers;
  1122         s_pSupportedControllers = s_pSupportedControllers->next;
  1123         SDL_free(pControllerMap->name);
  1124         SDL_free(pControllerMap->mapping);
  1125         SDL_free(pControllerMap);
  1126     }
  1127 
  1128     SDL_DelEventWatch(SDL_GameControllerEventWatcher, NULL);
  1129 
  1130 }
  1131 
  1132 /*
  1133  * Event filter to transform joystick events into appropriate game controller ones
  1134  */
  1135 int
  1136 SDL_PrivateGameControllerAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis, Sint16 value)
  1137 {
  1138     int posted;
  1139 
  1140     /* translate the event, if desired */
  1141     posted = 0;
  1142 #if !SDL_EVENTS_DISABLED
  1143     if (SDL_GetEventState(SDL_CONTROLLERAXISMOTION) == SDL_ENABLE) {
  1144         SDL_Event event;
  1145         event.type = SDL_CONTROLLERAXISMOTION;
  1146         event.caxis.which = gamecontroller->joystick->instance_id;
  1147         event.caxis.axis = axis;
  1148         event.caxis.value = value;
  1149         posted = SDL_PushEvent(&event) == 1;
  1150     }
  1151 #endif /* !SDL_EVENTS_DISABLED */
  1152     return (posted);
  1153 }
  1154 
  1155 
  1156 /*
  1157  * Event filter to transform joystick events into appropriate game controller ones
  1158  */
  1159 int
  1160 SDL_PrivateGameControllerButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button, Uint8 state)
  1161 {
  1162     int posted;
  1163 #if !SDL_EVENTS_DISABLED
  1164     SDL_Event event;
  1165 
  1166     if (button == SDL_CONTROLLER_BUTTON_INVALID)
  1167         return (0);
  1168 
  1169     switch (state) {
  1170     case SDL_PRESSED:
  1171         event.type = SDL_CONTROLLERBUTTONDOWN;
  1172         break;
  1173     case SDL_RELEASED:
  1174         event.type = SDL_CONTROLLERBUTTONUP;
  1175         break;
  1176     default:
  1177         /* Invalid state -- bail */
  1178         return (0);
  1179     }
  1180 #endif /* !SDL_EVENTS_DISABLED */
  1181 
  1182     /* translate the event, if desired */
  1183     posted = 0;
  1184 #if !SDL_EVENTS_DISABLED
  1185     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  1186         event.cbutton.which = gamecontroller->joystick->instance_id;
  1187         event.cbutton.button = button;
  1188         event.cbutton.state = state;
  1189         posted = SDL_PushEvent(&event) == 1;
  1190     }
  1191 #endif /* !SDL_EVENTS_DISABLED */
  1192     return (posted);
  1193 }
  1194 
  1195 /*
  1196  * Turn off controller events
  1197  */
  1198 int
  1199 SDL_GameControllerEventState(int state)
  1200 {
  1201 #if SDL_EVENTS_DISABLED
  1202     return SDL_IGNORE;
  1203 #else
  1204     const Uint32 event_list[] = {
  1205         SDL_CONTROLLERAXISMOTION, SDL_CONTROLLERBUTTONDOWN, SDL_CONTROLLERBUTTONUP,
  1206         SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED, SDL_CONTROLLERDEVICEREMAPPED,
  1207     };
  1208     unsigned int i;
  1209 
  1210     switch (state) {
  1211     case SDL_QUERY:
  1212         state = SDL_IGNORE;
  1213         for (i = 0; i < SDL_arraysize(event_list); ++i) {
  1214             state = SDL_EventState(event_list[i], SDL_QUERY);
  1215             if (state == SDL_ENABLE) {
  1216                 break;
  1217             }
  1218         }
  1219         break;
  1220     default:
  1221         for (i = 0; i < SDL_arraysize(event_list); ++i) {
  1222             SDL_EventState(event_list[i], state);
  1223         }
  1224         break;
  1225     }
  1226     return (state);
  1227 #endif /* SDL_EVENTS_DISABLED */
  1228 }
  1229 
  1230 /* vi: set ts=4 sw=4 expandtab: */