src/events/SDL_mouse.c
author Sam Lantinga
Mon, 08 Dec 2008 00:52:12 +0000
changeset 2860 6ce28e5287e9
parent 2859 99210400e8b9
child 2940 b93965a16fe0
permissions -rw-r--r--
Date: Sun, 07 Dec 2008 13:35:23 +0100
From: Couriersud
Subject: SDL: Mouse last_x, last_y into SDL_Mouse

the attached diff moves the static vars last_x and last_y into
SDL_Mouse. These, as far as I understand it, should be tied to the
individual mouse.

The patch also makes the code check for out of window conditions of
mouse->x,y when relative movements are passed to MouseSendMotion.

Also attached is the latest DirectFB code (dfb20081208) supporting
multiple mice and keyboards. This works quite well with sdlmame now. It
however needs more testing with different directfb configurations.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* General mouse handling code for SDL */
    25 
    26 #include "SDL_events.h"
    27 #include "SDL_events_c.h"
    28 #include "default_cursor.h"
    29 
    30 
    31 static int SDL_num_mice = 0;
    32 static int SDL_current_mouse = -1;
    33 static SDL_Mouse **SDL_mice = NULL;
    34 static int *SDL_IdIndex = NULL;
    35 static int SDL_highestId = -1;
    36 
    37 
    38 /* Public functions */
    39 int
    40 SDL_MouseInit(void)
    41 {
    42     return (0);
    43 }
    44 
    45 SDL_Mouse *
    46 SDL_GetMouse(int index)
    47 {
    48     if (index < 0 || index >= SDL_num_mice) {
    49         return NULL;
    50     }
    51     return SDL_mice[index];
    52 }
    53 
    54 int
    55 SDL_SetMouseIndexId(int id, int index)
    56 {
    57     if (id < 0) {
    58         SDL_SetError("Invalid Mouse ID");
    59         return -1;
    60     }
    61     if (id > SDL_highestId) {
    62         int *indexes;
    63         int i;
    64         indexes = (int *) SDL_realloc(SDL_IdIndex, (id + 1) * sizeof(int));
    65         if (!indexes) {
    66             SDL_OutOfMemory();
    67             return -1;
    68         }
    69         SDL_IdIndex = indexes;
    70         for (i = SDL_highestId + 1; i <= id; i++)
    71             SDL_IdIndex[i] = -1;
    72         SDL_IdIndex[id] = index;
    73         SDL_highestId = id;
    74     } else {
    75         SDL_IdIndex[id] = index;
    76     }
    77     return 1;
    78 }
    79 
    80 int
    81 SDL_GetMouseIndexId(int id)
    82 {
    83     if (id < 0 || id > SDL_highestId) {
    84         return -1;
    85     }
    86     return SDL_IdIndex[id];
    87 }
    88 
    89 int
    90 SDL_AddMouse(const SDL_Mouse * mouse, int index, char *name, int pressure_max,
    91              int pressure_min, int ends)
    92 {
    93     SDL_Mouse **mice;
    94     int selected_mouse;
    95     int length;
    96 
    97     /* Add the mouse to the list of mice */
    98     if (index < 0 || index >= SDL_num_mice || SDL_mice[index]) {
    99         mice =
   100             (SDL_Mouse **) SDL_realloc(SDL_mice,
   101                                        (SDL_num_mice + 1) * sizeof(*mice));
   102         if (!mice) {
   103             SDL_OutOfMemory();
   104             return -1;
   105         }
   106 
   107         SDL_mice = mice;
   108         index = SDL_num_mice++;
   109     }
   110     SDL_mice[index] = (SDL_Mouse *) SDL_malloc(sizeof(*SDL_mice[index]));
   111     if (!SDL_mice[index]) {
   112         SDL_OutOfMemory();
   113         return -1;
   114     }
   115     *SDL_mice[index] = *mouse;
   116 
   117     /* we're setting the mouse properties */
   118     length = 0;
   119     length = SDL_strlen(name);
   120     SDL_mice[index]->name = SDL_malloc((length + 2) * sizeof(char));
   121     SDL_strlcpy(SDL_mice[index]->name, name, length + 1);
   122     SDL_mice[index]->pressure_max = pressure_max;
   123     SDL_mice[index]->pressure_min = pressure_min;
   124     SDL_mice[index]->cursor_shown = SDL_TRUE;
   125     selected_mouse = SDL_SelectMouse(index);
   126     SDL_mice[index]->cur_cursor = NULL;
   127     SDL_mice[index]->def_cursor =
   128         SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH,
   129                          DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
   130     SDL_SetCursor(SDL_mice[index]->def_cursor);
   131     /* we're assuming that all mice are in the computer sensing zone */
   132     SDL_mice[index]->proximity = SDL_TRUE;
   133     /* we're assuming that all mice are working in the absolute position mode
   134        thanx to that, the users that don't want to use many mice don't have to
   135        worry about anything */
   136     SDL_mice[index]->relative_mode = SDL_FALSE;
   137     SDL_mice[index]->current_end = 0;
   138     SDL_mice[index]->total_ends = ends;
   139     SDL_SelectMouse(selected_mouse);
   140 
   141     return index;
   142 }
   143 
   144 void
   145 SDL_DelMouse(int index)
   146 {
   147     SDL_Mouse *mouse = SDL_GetMouse(index);
   148 
   149     if (!mouse) {
   150         return;
   151     }
   152 
   153     mouse->def_cursor = NULL;
   154     SDL_free(mouse->name);
   155     while (mouse->cursors) {
   156         SDL_FreeCursor(mouse->cursors);
   157     }
   158 
   159     if (mouse->FreeMouse) {
   160         mouse->FreeMouse(mouse);
   161     }
   162     SDL_free(mouse);
   163 
   164     SDL_mice[index] = NULL;
   165 }
   166 
   167 void
   168 SDL_ResetMouse(int index)
   169 {
   170     SDL_Mouse *mouse = SDL_GetMouse(index);
   171 
   172     if (!mouse) {
   173         return;
   174     }
   175 
   176     /* FIXME */
   177 }
   178 
   179 void
   180 SDL_MouseQuit(void)
   181 {
   182     int i;
   183 
   184     for (i = 0; i < SDL_num_mice; ++i) {
   185         SDL_DelMouse(i);
   186     }
   187     SDL_num_mice = 0;
   188     SDL_current_mouse = -1;
   189 
   190     if (SDL_mice) {
   191         SDL_free(SDL_mice);
   192         SDL_mice = NULL;
   193     }
   194 }
   195 
   196 int
   197 SDL_GetNumMice(void)
   198 {
   199     return SDL_num_mice;
   200 }
   201 
   202 int
   203 SDL_SelectMouse(int index)
   204 {
   205     if (index >= 0 && index < SDL_num_mice) {
   206         SDL_current_mouse = index;
   207     }
   208     return SDL_current_mouse;
   209 }
   210 
   211 SDL_WindowID
   212 SDL_GetMouseFocusWindow(int index)
   213 {
   214     SDL_Mouse *mouse = SDL_GetMouse(index);
   215 
   216     if (!mouse) {
   217         return 0;
   218     }
   219     return mouse->focus;
   220 }
   221 
   222 static int SDLCALL
   223 FlushMouseMotion(void *param, SDL_Event * event)
   224 {
   225     if (event->type == SDL_MOUSEMOTION
   226         && event->motion.which == (Uint8) SDL_current_mouse) {
   227         return 0;
   228     } else {
   229         return 1;
   230     }
   231 }
   232 
   233 int
   234 SDL_SetRelativeMouseMode(int index, SDL_bool enabled)
   235 {
   236     SDL_Mouse *mouse = SDL_GetMouse(index);
   237 
   238     if (!mouse) {
   239         return -1;
   240     }
   241 
   242     /* Flush pending mouse motion */
   243     mouse->flush_motion = SDL_TRUE;
   244     SDL_PumpEvents();
   245     mouse->flush_motion = SDL_FALSE;
   246     SDL_FilterEvents(FlushMouseMotion, mouse);
   247 
   248     /* Set the relative mode */
   249     mouse->relative_mode = enabled;
   250 
   251     /* Update cursor visibility */
   252     SDL_SetCursor(NULL);
   253 
   254     if (!enabled) {
   255         /* Restore the expected mouse position */
   256         SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
   257     }
   258     return 0;
   259 }
   260 
   261 SDL_bool
   262 SDL_GetRelativeMouseMode(int index)
   263 {
   264     SDL_Mouse *mouse = SDL_GetMouse(index);
   265 
   266     if (!mouse) {
   267         return SDL_FALSE;
   268     }
   269     return mouse->relative_mode;
   270 }
   271 
   272 Uint8
   273 SDL_GetMouseState(int index, int *x, int *y)
   274 {
   275     SDL_Mouse *mouse = SDL_GetMouse(index);
   276 
   277     if (!mouse) {
   278         if (x) {
   279             *x = 0;
   280         }
   281         if (y) {
   282             *y = 0;
   283         }
   284         return 0;
   285     }
   286 
   287     if (x) {
   288         *x = mouse->x;
   289     }
   290     if (y) {
   291         *y = mouse->y;
   292     }
   293     return mouse->buttonstate;
   294 }
   295 
   296 Uint8
   297 SDL_GetRelativeMouseState(int index, int *x, int *y)
   298 {
   299     SDL_Mouse *mouse = SDL_GetMouse(index);
   300 
   301     if (!mouse) {
   302         if (x) {
   303             *x = 0;
   304         }
   305         if (y) {
   306             *y = 0;
   307         }
   308         return 0;
   309     }
   310 
   311     if (x) {
   312         *x = mouse->xdelta;
   313     }
   314     if (y) {
   315         *y = mouse->ydelta;
   316     }
   317     mouse->xdelta = 0;
   318     mouse->ydelta = 0;
   319     return mouse->buttonstate;
   320 }
   321 
   322 void
   323 SDL_SetMouseFocus(int id, SDL_WindowID windowID)
   324 {
   325     int index = SDL_GetMouseIndexId(id);
   326     SDL_Mouse *mouse = SDL_GetMouse(index);
   327     int i;
   328     SDL_bool focus;
   329 
   330     if (!mouse || (mouse->focus == windowID)) {
   331         return;
   332     }
   333 
   334     /* See if the current window has lost focus */
   335     if (mouse->focus) {
   336         focus = SDL_FALSE;
   337         for (i = 0; i < SDL_num_mice; ++i) {
   338             SDL_Mouse *check;
   339             if (i != index) {
   340                 check = SDL_GetMouse(i);
   341                 if (check && check->focus == mouse->focus) {
   342                     focus = SDL_TRUE;
   343                     break;
   344                 }
   345             }
   346         }
   347         if (!focus) {
   348             SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
   349         }
   350     }
   351 
   352     mouse->focus = windowID;
   353 
   354     if (mouse->focus) {
   355         focus = SDL_FALSE;
   356         for (i = 0; i < SDL_num_mice; ++i) {
   357             SDL_Mouse *check;
   358             if (i != index) {
   359                 check = SDL_GetMouse(i);
   360                 if (check && check->focus == mouse->focus) {
   361                     focus = SDL_TRUE;
   362                     break;
   363                 }
   364             }
   365         }
   366         if (!focus) {
   367             SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
   368         }
   369     }
   370 }
   371 
   372 int
   373 SDL_SendProximity(int id, int x, int y, int type)
   374 {
   375     int index = SDL_GetMouseIndexId(id);
   376     SDL_Mouse *mouse = SDL_GetMouse(index);
   377     int posted = 0;
   378 
   379     if (!mouse) {
   380         return 0;
   381     }
   382 
   383     mouse->last_x = x;
   384     mouse->last_y = y;
   385     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   386         SDL_Event event;
   387         event.proximity.which = (Uint8) index;
   388         event.proximity.x = x;
   389         event.proximity.y = y;
   390         event.proximity.cursor = mouse->current_end;
   391         event.proximity.type = type;
   392         posted = (SDL_PushEvent(&event) > 0);
   393         if (type == SDL_PROXIMITYIN) {
   394             mouse->proximity = SDL_TRUE;
   395         } else {
   396             mouse->proximity = SDL_FALSE;
   397         }
   398     }
   399     return posted;
   400 }
   401 
   402 int
   403 SDL_SendMouseMotion(int id, int relative, int x, int y, int pressure)
   404 {
   405     int index = SDL_GetMouseIndexId(id);
   406     SDL_Mouse *mouse = SDL_GetMouse(index);
   407     int posted;
   408     int xrel;
   409     int yrel;
   410     int x_max = 0, y_max = 0;
   411 
   412     if (!mouse || mouse->flush_motion) {
   413         return 0;
   414     }
   415 
   416     /* if the mouse is out of proximity we don't to want to have any motion from it */
   417     if (mouse->proximity == SDL_FALSE) {
   418         mouse->last_x = x;
   419         mouse->last_y = y;
   420         return 0;
   421     }
   422 
   423     /* the relative motion is calculated regarding the system cursor last position */
   424     if (relative) {
   425         xrel = x;
   426         yrel = y;
   427         x = (mouse->last_x + x);
   428         y = (mouse->last_y + y);
   429     } else {
   430         xrel = x - mouse->last_x;
   431         yrel = y - mouse->last_y;
   432     }
   433 
   434     /* Drop events that don't change state */
   435     if (!xrel && !yrel) {
   436 #if 0
   437         printf("Mouse event didn't change state - dropped!\n");
   438 #endif
   439         return 0;
   440     }
   441 
   442     /* Update internal mouse coordinates */
   443     if (mouse->relative_mode == SDL_FALSE) {
   444         mouse->x = x;
   445         mouse->y = y;
   446     } else {
   447         mouse->x += xrel;
   448         mouse->y += yrel;
   449     }
   450 
   451     SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
   452 
   453     /* make sure that the pointers find themselves inside the windows */
   454     /* only check if mouse->xmax is set ! */
   455     if (x_max && mouse->x > x_max) {
   456         mouse->x = x_max;
   457     } else if (mouse->x < 0) {
   458         mouse->x = 0;
   459     }
   460 
   461     if (y_max && mouse->y > y_max) {
   462         mouse->y = y_max;
   463     } else if (mouse->y < 0) {
   464         mouse->y = 0;
   465     }
   466 
   467     mouse->xdelta += xrel;
   468     mouse->ydelta += yrel;
   469     mouse->pressure = pressure;
   470 
   471     /* Move the mouse cursor, if needed */
   472     if (mouse->cursor_shown && !mouse->relative_mode &&
   473         mouse->MoveCursor && mouse->cur_cursor) {
   474         mouse->MoveCursor(mouse->cur_cursor);
   475     }
   476 
   477     /* Post the event, if desired */
   478     posted = 0;
   479     if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE &&
   480         mouse->proximity == SDL_TRUE) {
   481         SDL_Event event;
   482         event.motion.type = SDL_MOUSEMOTION;
   483         event.motion.which = (Uint8) index;
   484         event.motion.state = mouse->buttonstate;
   485         event.motion.x = mouse->x;
   486         event.motion.y = mouse->y;
   487         event.motion.pressure = mouse->pressure;
   488         event.motion.xrel = xrel;
   489         event.motion.yrel = yrel;
   490         event.motion.windowID = mouse->focus;
   491         event.motion.pressure_max = mouse->pressure_max;
   492         event.motion.pressure_min = mouse->pressure_min;
   493         event.motion.cursor = mouse->current_end;
   494         posted = (SDL_PushEvent(&event) > 0);
   495     }
   496     mouse->last_x = x;
   497     mouse->last_y = y;
   498     return posted;
   499 }
   500 
   501 int
   502 SDL_SendMouseButton(int id, Uint8 state, Uint8 button)
   503 {
   504     int index = SDL_GetMouseIndexId(id);
   505     SDL_Mouse *mouse = SDL_GetMouse(index);
   506     int posted;
   507     Uint8 type;
   508 
   509     if (!mouse) {
   510         return 0;
   511     }
   512 
   513     /* Figure out which event to perform */
   514     switch (state) {
   515     case SDL_PRESSED:
   516         if (mouse->buttonstate & SDL_BUTTON(button)) {
   517             /* Ignore this event, no state change */
   518             return 0;
   519         }
   520         type = SDL_MOUSEBUTTONDOWN;
   521         mouse->buttonstate |= SDL_BUTTON(button);
   522         break;
   523     case SDL_RELEASED:
   524         if (!(mouse->buttonstate & SDL_BUTTON(button))) {
   525             /* Ignore this event, no state change */
   526             return 0;
   527         }
   528         type = SDL_MOUSEBUTTONUP;
   529         mouse->buttonstate &= ~SDL_BUTTON(button);
   530         break;
   531     default:
   532         /* Invalid state -- bail */
   533         return 0;
   534     }
   535 
   536     /* Post the event, if desired */
   537     posted = 0;
   538     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   539         SDL_Event event;
   540         event.type = type;
   541         event.button.which = (Uint8) index;
   542         event.button.state = state;
   543         event.button.button = button;
   544         event.button.x = mouse->x;
   545         event.button.y = mouse->y;
   546         event.button.windowID = mouse->focus;
   547         posted = (SDL_PushEvent(&event) > 0);
   548     }
   549     return posted;
   550 }
   551 
   552 int
   553 SDL_SendMouseWheel(int index, int x, int y)
   554 {
   555     SDL_Mouse *mouse = SDL_GetMouse(index);
   556     int posted;
   557 
   558     if (!mouse || (!x && !y)) {
   559         return 0;
   560     }
   561 
   562     /* Post the event, if desired */
   563     posted = 0;
   564     if (SDL_ProcessEvents[SDL_MOUSEWHEEL] == SDL_ENABLE) {
   565         SDL_Event event;
   566         event.type = SDL_MOUSEWHEEL;
   567         event.wheel.which = (Uint8) index;
   568         event.wheel.x = x;
   569         event.wheel.y = y;
   570         event.wheel.windowID = mouse->focus;
   571         posted = (SDL_PushEvent(&event) > 0);
   572     }
   573     return posted;
   574 }
   575 
   576 void
   577 SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y)
   578 {
   579     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   580 
   581     if (!mouse) {
   582         return;
   583     }
   584 
   585     if (mouse->WarpMouse) {
   586         mouse->WarpMouse(mouse, windowID, x, y);
   587     } else {
   588         SDL_SetMouseFocus(SDL_current_mouse, windowID);
   589         SDL_SendMouseMotion(SDL_current_mouse, 0, x, y, 0);
   590     }
   591 }
   592 
   593 SDL_Cursor *
   594 SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
   595                  int w, int h, int hot_x, int hot_y)
   596 {
   597     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   598     SDL_Surface *surface;
   599     SDL_Cursor *cursor;
   600     int x, y;
   601     Uint32 *pixel;
   602     Uint8 datab, maskb;
   603     const Uint32 black = 0xFF000000;
   604     const Uint32 white = 0xFFFFFFFF;
   605     const Uint32 transparent = 0x00000000;
   606 
   607     if (!mouse) {
   608         SDL_SetError("No mice are initialized");
   609         return NULL;
   610     }
   611 
   612     if (!mouse->CreateCursor) {
   613         SDL_SetError("Current mouse doesn't have cursor support");
   614         return NULL;
   615     }
   616 
   617     /* Sanity check the hot spot */
   618     if ((hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h)) {
   619         SDL_SetError("Cursor hot spot doesn't lie within cursor");
   620         return NULL;
   621     }
   622 
   623     /* Make sure the width is a multiple of 8 */
   624     w = ((w + 7) & ~7);
   625 
   626     /* Create the surface from a bitmap */
   627     surface =
   628         SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
   629                              0xFF000000);
   630     if (!surface) {
   631         return NULL;
   632     }
   633     for (y = 0; y < h; ++y) {
   634         pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
   635         for (x = 0; x < w; ++x) {
   636             if ((x % 8) == 0) {
   637                 datab = *data++;
   638                 maskb = *mask++;
   639             }
   640             if (maskb & 0x80) {
   641                 *pixel++ = (datab & 0x80) ? black : white;
   642             } else {
   643                 *pixel++ = (datab & 0x80) ? black : transparent;
   644             }
   645             datab <<= 1;
   646             maskb <<= 1;
   647         }
   648     }
   649 
   650     cursor = mouse->CreateCursor(surface, hot_x, hot_y);
   651     if (cursor) {
   652         cursor->mouse = mouse;
   653         cursor->next = mouse->cursors;
   654         mouse->cursors = cursor;
   655     }
   656 
   657     SDL_FreeSurface(surface);
   658 
   659     return cursor;
   660 }
   661 
   662 /* SDL_SetCursor(NULL) can be used to force the cursor redraw,
   663    if this is desired for any reason.  This is used when setting
   664    the video mode and when the SDL window gains the mouse focus.
   665  */
   666 void
   667 SDL_SetCursor(SDL_Cursor * cursor)
   668 {
   669     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   670 
   671     if (!mouse) {
   672         SDL_SetError("No mice are initialized");
   673         return;
   674     }
   675 
   676     /* Set the new cursor */
   677     if (cursor) {
   678         /* Make sure the cursor is still valid for this mouse */
   679         SDL_Cursor *found;
   680         for (found = mouse->cursors; found; found = found->next) {
   681             if (found == cursor) {
   682                 break;
   683             }
   684         }
   685         if (!found) {
   686             SDL_SetError("Cursor not associated with the current mouse");
   687             return;
   688         }
   689         mouse->cur_cursor = cursor;
   690     } else {
   691         cursor = mouse->cur_cursor;
   692     }
   693 
   694     if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
   695         if (mouse->ShowCursor) {
   696             mouse->ShowCursor(cursor);
   697         }
   698     } else {
   699         if (mouse->ShowCursor) {
   700             mouse->ShowCursor(NULL);
   701         }
   702     }
   703 }
   704 
   705 SDL_Cursor *
   706 SDL_GetCursor(void)
   707 {
   708     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   709 
   710     if (!mouse) {
   711         return NULL;
   712     }
   713     return mouse->cur_cursor;
   714 }
   715 
   716 void
   717 SDL_FreeCursor(SDL_Cursor * cursor)
   718 {
   719     SDL_Mouse *mouse;
   720     SDL_Cursor *curr, *prev;
   721 
   722     if (!cursor) {
   723         return;
   724     }
   725     mouse = cursor->mouse;
   726 
   727     if (cursor == mouse->def_cursor) {
   728         return;
   729     }
   730     if (cursor == mouse->cur_cursor) {
   731         SDL_SetCursor(mouse->def_cursor);
   732     }
   733 
   734     for (prev = NULL, curr = mouse->cursors; curr;
   735          prev = curr, curr = curr->next) {
   736         if (curr == cursor) {
   737             if (prev) {
   738                 prev->next = curr->next;
   739             } else {
   740                 mouse->cursors = curr->next;
   741             }
   742 
   743             if (mouse->FreeCursor) {
   744                 mouse->FreeCursor(curr);
   745             }
   746             return;
   747         }
   748     }
   749 }
   750 
   751 int
   752 SDL_ShowCursor(int toggle)
   753 {
   754     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   755     SDL_bool shown;
   756 
   757     if (!mouse) {
   758         return 0;
   759     }
   760 
   761     shown = mouse->cursor_shown;
   762     if (toggle >= 0) {
   763         if (toggle) {
   764             mouse->cursor_shown = SDL_TRUE;
   765         } else {
   766             mouse->cursor_shown = SDL_FALSE;
   767         }
   768         if (mouse->cursor_shown != shown) {
   769             SDL_SetCursor(NULL);
   770         }
   771     }
   772     return shown;
   773 }
   774 
   775 char *
   776 SDL_GetMouseName(int index)
   777 {
   778     SDL_Mouse *mouse = SDL_GetMouse(index);
   779     if (!mouse) {
   780         return NULL;
   781     }
   782     return mouse->name;
   783 }
   784 
   785 void
   786 SDL_ChangeEnd(int id, int end)
   787 {
   788     int index = SDL_GetMouseIndexId(id);
   789     SDL_Mouse *mouse = SDL_GetMouse(index);
   790 
   791     if (mouse) {
   792         mouse->current_end = end;
   793     }
   794 }
   795 
   796 int
   797 SDL_GetCursorsNumber(int index)
   798 {
   799     SDL_Mouse *mouse = SDL_GetMouse(index);
   800 
   801     if (!mouse) {
   802         return -1;
   803     }
   804     return mouse->total_ends;
   805 }
   806 
   807 int
   808 SDL_GetCurrentCursor(int index)
   809 {
   810     SDL_Mouse *mouse = SDL_GetMouse(index);
   811 
   812     if (!mouse) {
   813         return -1;
   814     }
   815     return mouse->current_end;
   816 }
   817 
   818 /* vi: set ts=4 sw=4 expandtab: */