src/video/SDL_cursor.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SDL_CursorQuit
  2. SDL_CursorInit
  3. SDL_LockCursor
  4. SDL_UnlockCursor
  5. SDL_CreateCursor
  6. SDL_SetCursor
  7. SDL_GetCursor
  8. SDL_FreeCursor
  9. SDL_ShowCursor
  10. SDL_WarpMouse
  11. SDL_MoveCursor
  12. SDL_CursorPaletteChanged
  13. SDL_MouseRect
  14. SDL_DrawCursorFast
  15. SDL_DrawCursorSlow
  16. SDL_ConvertCursorSave
  17. SDL_DrawCursorNoLock
  18. SDL_DrawCursor
  19. SDL_EraseCursorNoLock
  20. SDL_EraseCursor
  21. SDL_ResetCursor

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 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     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_cursor.c,v 1.7.2.12 2001/02/11 06:57:37 hercules Exp $";
  26 #endif
  27 
  28 /* General cursor handling code for SDL */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <string.h>
  33 
  34 #include "SDL_mutex.h"
  35 #include "SDL_error.h"
  36 #include "SDL_video.h"
  37 #include "SDL_mouse.h"
  38 #include "SDL_blit.h"
  39 #include "SDL_events_c.h"
  40 #include "SDL_sysvideo.h"
  41 #include "SDL_sysevents.h"
  42 #include "SDL_cursor_c.h"
  43 #include "SDL_pixels_c.h"
  44 #include "default_cursor.h"
  45 
  46 /* These are static for our cursor handling code */
  47 volatile int SDL_cursorstate = CURSOR_VISIBLE;
  48 SDL_Cursor *SDL_cursor = NULL;
  49 static SDL_Cursor *SDL_defcursor = NULL;
  50 SDL_mutex *SDL_cursorlock = NULL;
  51 
  52 /* Public functions */
  53 void SDL_CursorQuit(void)
     /* [<][>][^][v][top][bottom][index][help] */
  54 {
  55         if ( SDL_cursor != NULL ) {
  56                 SDL_Cursor *cursor;
  57 
  58                 SDL_cursorstate &= ~CURSOR_VISIBLE;
  59                 if ( SDL_cursor != SDL_defcursor ) {
  60                         SDL_FreeCursor(SDL_cursor);
  61                 }
  62                 SDL_cursor = NULL;
  63                 if ( SDL_defcursor != NULL ) {
  64                         cursor = SDL_defcursor;
  65                         SDL_defcursor = NULL;
  66                         SDL_FreeCursor(cursor);
  67                 }
  68         }
  69         if ( SDL_cursorlock != NULL ) {
  70                 SDL_DestroyMutex(SDL_cursorlock);
  71                 SDL_cursorlock = NULL;
  72         }
  73 }
  74 int SDL_CursorInit(Uint32 multithreaded)
     /* [<][>][^][v][top][bottom][index][help] */
  75 {
  76         /* We don't have mouse focus, and the cursor isn't drawn yet */
  77         SDL_cursorstate = CURSOR_VISIBLE;
  78 
  79         /* Create the default cursor */
  80         if ( SDL_defcursor == NULL ) {
  81                 SDL_defcursor = SDL_CreateCursor(default_cdata, default_cmask,
  82                                         DEFAULT_CWIDTH, DEFAULT_CHEIGHT,
  83                                                 DEFAULT_CHOTX, DEFAULT_CHOTY);
  84                 SDL_SetCursor(SDL_defcursor);
  85         }
  86 
  87         /* Create a lock if necessary */
  88         if ( multithreaded ) {
  89                 SDL_cursorlock = SDL_CreateMutex();
  90         }
  91 
  92         /* That's it! */
  93         return(0);
  94 }
  95 
  96 /* Multi-thread support for cursors */
  97 #ifndef SDL_LockCursor
  98 void SDL_LockCursor(void)
     /* [<][>][^][v][top][bottom][index][help] */
  99 {
 100         if ( SDL_cursorlock ) {
 101                 SDL_mutexP(SDL_cursorlock);
 102         }
 103 }
 104 #endif
 105 #ifndef SDL_UnlockCursor
 106 void SDL_UnlockCursor(void)
     /* [<][>][^][v][top][bottom][index][help] */
 107 {
 108         if ( SDL_cursorlock ) {
 109                 SDL_mutexV(SDL_cursorlock);
 110         }
 111 }
 112 #endif
 113 
 114 /* Software cursor drawing support */
 115 SDL_Cursor * SDL_CreateCursor (Uint8 *data, Uint8 *mask, 
     /* [<][>][^][v][top][bottom][index][help] */
 116                                         int w, int h, int hot_x, int hot_y)
 117 {
 118         SDL_VideoDevice *video = current_video;
 119         int savelen;
 120         int i;
 121         SDL_Cursor *cursor;
 122 
 123         /* Make sure the width is a multiple of 8 */
 124         w = ((w+7)&~7);
 125 
 126         /* Sanity check the hot spot */
 127         if ( (hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h) ) {
 128                 SDL_SetError("Cursor hot spot doesn't lie within cursor");
 129                 return(NULL);
 130         }
 131 
 132         /* Allocate memory for the cursor */
 133         cursor = (SDL_Cursor *)malloc(sizeof *cursor);
 134         if ( cursor == NULL ) {
 135                 SDL_OutOfMemory();
 136                 return(NULL);
 137         }
 138         savelen = (w*4)*h;
 139         cursor->area.x = 0;
 140         cursor->area.y = 0;
 141         cursor->area.w = w;
 142         cursor->area.h = h;
 143         cursor->hot_x = hot_x;
 144         cursor->hot_y = hot_y;
 145         cursor->data = (Uint8 *)malloc((w/8)*h*2);
 146         cursor->mask = cursor->data+((w/8)*h);
 147         cursor->save[0] = (Uint8 *)malloc(savelen*2);
 148         cursor->save[1] = cursor->save[0] + savelen;
 149         cursor->wm_cursor = NULL;
 150         if ( ! cursor->data || ! cursor->save[0] ) {
 151                 SDL_FreeCursor(cursor);
 152                 SDL_OutOfMemory();
 153                 return(NULL);
 154         }
 155         for ( i=((w/8)*h)-1; i>=0; --i ) {
 156                 cursor->data[i] = data[i];
 157                 cursor->mask[i] = mask[i] | data[i];
 158         }
 159         memset(cursor->save[0], 0, savelen*2);
 160 
 161         /* If the window manager gives us a good cursor, we're done! */
 162         if ( video->CreateWMCursor ) {
 163                 cursor->wm_cursor = video->CreateWMCursor(video, data, mask,
 164                                                         w, h, hot_x, hot_y);
 165         } else {
 166                 cursor->wm_cursor = NULL;
 167         }
 168         return(cursor);
 169 }
 170 
 171 /* SDL_SetCursor(NULL) can be used to force the cursor redraw,
 172    if this is desired for any reason.  This is used when setting
 173    the video mode and when the SDL window gains the mouse focus.
 174  */
 175 void SDL_SetCursor (SDL_Cursor *cursor)
     /* [<][>][^][v][top][bottom][index][help] */
 176 {
 177         SDL_VideoDevice *video = current_video;
 178         SDL_VideoDevice *this  = current_video;
 179 
 180         /* Make sure that the video subsystem has been initialized */
 181         if ( ! video ) {
 182                 return;
 183         }
 184 
 185         /* Prevent the event thread from moving the mouse */
 186         SDL_LockCursor();
 187 
 188         /* Set the new cursor */
 189         if ( cursor && (cursor != SDL_cursor) ) {
 190                 /* Erase the current mouse position */
 191                 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
 192                         SDL_EraseCursor(SDL_VideoSurface);
 193                 } else if ( video->MoveWMCursor ) {
 194                         /* If the video driver is moving the cursor directly,
 195                            it needs to hide the old cursor before (possibly)
 196                            showing the new one.  (But don't erase NULL cursor)
 197                          */
 198                         if ( SDL_cursor ) {
 199                                 video->ShowWMCursor(this, NULL);
 200                         }
 201                 }
 202                 SDL_cursor = cursor;
 203         }
 204 
 205         /* Draw the new mouse cursor */
 206         if ( SDL_cursor && (SDL_cursorstate&CURSOR_VISIBLE) ) {
 207                 /* Use window manager cursor if possible */
 208                 if ( SDL_cursor->wm_cursor && 
 209                      video->ShowWMCursor(this, SDL_cursor->wm_cursor) )
 210                         SDL_cursorstate &= ~CURSOR_USINGSW;
 211                 else {
 212                         SDL_cursorstate |= CURSOR_USINGSW;
 213                         if ( video->ShowWMCursor ) {
 214                                 video->ShowWMCursor(this, NULL);
 215                         }
 216                         { int x, y;
 217                                 SDL_GetMouseState(&x, &y);
 218                                 SDL_cursor->area.x = (x - SDL_cursor->hot_x);
 219                                 SDL_cursor->area.y = (y - SDL_cursor->hot_y);
 220                         }
 221                         SDL_DrawCursor(SDL_VideoSurface);
 222                 }
 223         } else {
 224                 /* Erase window manager mouse (cursor not visible) */
 225                 if ( SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW) ) {
 226                         SDL_EraseCursor(SDL_VideoSurface);
 227                 } else {
 228                         if ( video ) {
 229                                 video->ShowWMCursor(this, NULL);
 230                         }
 231                 }
 232         }
 233         SDL_UnlockCursor();
 234 }
 235 
 236 SDL_Cursor * SDL_GetCursor (void)
     /* [<][>][^][v][top][bottom][index][help] */
 237 {
 238         return(SDL_cursor);
 239 }
 240 
 241 void SDL_FreeCursor (SDL_Cursor *cursor)
     /* [<][>][^][v][top][bottom][index][help] */
 242 {
 243         if ( cursor ) {
 244                 if ( cursor == SDL_cursor ) {
 245                         SDL_SetCursor(SDL_defcursor);
 246                 }
 247                 if ( cursor != SDL_defcursor ) {
 248                         if ( cursor->data ) {
 249                                 free(cursor->data);
 250                         }
 251                         if ( cursor->save[0] ) {
 252                                 free(cursor->save[0]);
 253                         }
 254                         if ( cursor->wm_cursor ) {
 255                                 SDL_VideoDevice *video = current_video;
 256                                 SDL_VideoDevice *this  = current_video;
 257                                 video->FreeWMCursor(this, cursor->wm_cursor);
 258                         }
 259                         free(cursor);
 260                 }
 261         }
 262 }
 263 
 264 int SDL_ShowCursor (int toggle)
     /* [<][>][^][v][top][bottom][index][help] */
 265 {
 266         int showing;
 267 
 268         showing = (SDL_cursorstate & CURSOR_VISIBLE);
 269         if ( toggle >= 0 ) {
 270                 SDL_LockCursor();
 271                 if ( toggle ) {
 272                         SDL_cursorstate |= CURSOR_VISIBLE;
 273                 } else {
 274                         SDL_cursorstate &= ~CURSOR_VISIBLE;
 275                 }
 276                 SDL_UnlockCursor();
 277                 if ( (SDL_cursorstate & CURSOR_VISIBLE) != showing ) {
 278                         SDL_VideoDevice *video = current_video;
 279                         SDL_VideoDevice *this  = current_video;
 280 
 281                         SDL_SetCursor(NULL);
 282                         if ( video && video->CheckMouseMode ) {
 283                                 video->CheckMouseMode(this);
 284                         }
 285                 }
 286         } else {
 287                 /* Query current state */ ;
 288         }
 289         return(showing ? 1 : 0);
 290 }
 291 
 292 void SDL_WarpMouse (Uint16 x, Uint16 y)
     /* [<][>][^][v][top][bottom][index][help] */
 293 {
 294         SDL_VideoDevice *video = current_video;
 295         SDL_VideoDevice *this  = current_video;
 296 
 297         /* This generates a mouse motion event */
 298         if ( video->WarpWMCursor ) {
 299                 video->WarpWMCursor(this, x, y);
 300         } else {
 301                 x += (this->screen->offset % this->screen->pitch) /
 302                       this->screen->format->BytesPerPixel;
 303                 y += (this->screen->offset / this->screen->pitch);
 304                 SDL_PrivateMouseMotion(0, 0, x, y);
 305         }
 306 }
 307 
 308 void SDL_MoveCursor(int x, int y)
     /* [<][>][^][v][top][bottom][index][help] */
 309 {
 310         SDL_VideoDevice *video = current_video;
 311 
 312         /* Erase and update the current mouse position */
 313         if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
 314                 /* Erase and redraw mouse cursor in new position */
 315                 SDL_LockCursor();
 316                 SDL_EraseCursor(SDL_VideoSurface);
 317                 SDL_cursor->area.x = (x - SDL_cursor->hot_x);
 318                 SDL_cursor->area.y = (y - SDL_cursor->hot_y);
 319                 SDL_DrawCursor(SDL_VideoSurface);
 320                 SDL_UnlockCursor();
 321         } else if ( video->MoveWMCursor ) {
 322                 video->MoveWMCursor(video, x, y);
 323         }
 324 }
 325 
 326 /* Keep track of the current cursor colors */
 327 static int palette_changed = 1;
 328 static Uint32 pixels8[2];
 329 
 330 void SDL_CursorPaletteChanged(void)
     /* [<][>][^][v][top][bottom][index][help] */
 331 {
 332         palette_changed = 1;
 333 }
 334 
 335 void SDL_MouseRect(SDL_Rect *area)
     /* [<][>][^][v][top][bottom][index][help] */
 336 {
 337         int clip_diff;
 338 
 339         *area = SDL_cursor->area;
 340         if ( area->x < 0 ) {
 341                 area->w += area->x;
 342                 area->x = 0;
 343         }
 344         if ( area->y < 0 ) {
 345                 area->h += area->y;
 346                 area->y = 0;
 347         }
 348         clip_diff = (area->x+area->w)-SDL_VideoSurface->w;
 349         if ( clip_diff > 0 ) {
 350                 area->w -= clip_diff;
 351         }
 352         clip_diff = (area->y+area->h)-SDL_VideoSurface->h;
 353         if ( clip_diff > 0 ) {
 354                 area->h -= clip_diff;
 355         }
 356 }
 357 
 358 static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area)
     /* [<][>][^][v][top][bottom][index][help] */
 359 {
 360         const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
 361         int i, w, h;
 362         Uint8 *data, datab;
 363         Uint8 *mask, maskb;
 364 
 365         data = SDL_cursor->data + area->y * SDL_cursor->area.w/8;
 366         mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8;
 367         switch (screen->format->BytesPerPixel) {
 368 
 369             case 1: {
 370                 Uint8 *dst;
 371                 int dstskip;
 372 
 373                 if ( palette_changed ) {
 374                         pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255);
 375                         pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0);
 376                         palette_changed = 0;
 377                 }
 378                 dst = (Uint8 *)screen->pixels +
 379                        (SDL_cursor->area.y+area->y)*screen->pitch +
 380                        SDL_cursor->area.x;
 381                 dstskip = screen->pitch-area->w;
 382 
 383                 for ( h=area->h; h; h-- ) {
 384                         for ( w=area->w/8; w; w-- ) {
 385                                 maskb = *mask++;
 386                                 datab = *data++;
 387                                 for ( i=0; i<8; ++i ) {
 388                                         if ( maskb & 0x80 ) {
 389                                                 *dst = pixels8[datab>>7];
 390                                         }
 391                                         maskb <<= 1;
 392                                         datab <<= 1;
 393                                         dst++;
 394                                 }
 395                         }
 396                         dst += dstskip;
 397                 }
 398             }
 399             break;
 400 
 401             case 2: {
 402                 Uint16 *dst;
 403                 int dstskip;
 404 
 405                 dst = (Uint16 *)screen->pixels +
 406                        (SDL_cursor->area.y+area->y)*screen->pitch/2 +
 407                        SDL_cursor->area.x;
 408                 dstskip = (screen->pitch/2)-area->w;
 409 
 410                 for ( h=area->h; h; h-- ) {
 411                         for ( w=area->w/8; w; w-- ) {
 412                                 maskb = *mask++;
 413                                 datab = *data++;
 414                                 for ( i=0; i<8; ++i ) {
 415                                         if ( maskb & 0x80 ) {
 416                                                 *dst = pixels[datab>>7];
 417                                         }
 418                                         maskb <<= 1;
 419                                         datab <<= 1;
 420                                         dst++;
 421                                 }
 422                         }
 423                         dst += dstskip;
 424                 }
 425             }
 426             break;
 427 
 428             case 3: {
 429                 Uint8 *dst;
 430                 int dstskip;
 431 
 432                 dst = (Uint8 *)screen->pixels +
 433                        (SDL_cursor->area.y+area->y)*screen->pitch +
 434                        SDL_cursor->area.x*3;
 435                 dstskip = screen->pitch-area->w*3;
 436 
 437                 for ( h=area->h; h; h-- ) {
 438                         for ( w=area->w/8; w; w-- ) {
 439                                 maskb = *mask++;
 440                                 datab = *data++;
 441                                 for ( i=0; i<8; ++i ) {
 442                                         if ( maskb & 0x80 ) {
 443                                                 memset(dst,pixels[datab>>7],3);
 444                                         }
 445                                         maskb <<= 1;
 446                                         datab <<= 1;
 447                                         dst += 3;
 448                                 }
 449                         }
 450                         dst += dstskip;
 451                 }
 452             }
 453             break;
 454 
 455             case 4: {
 456                 Uint32 *dst;
 457                 int dstskip;
 458 
 459                 dst = (Uint32 *)screen->pixels +
 460                        (SDL_cursor->area.y+area->y)*screen->pitch/4 +
 461                        SDL_cursor->area.x;
 462                 dstskip = (screen->pitch/4)-area->w;
 463 
 464                 for ( h=area->h; h; h-- ) {
 465                         for ( w=area->w/8; w; w-- ) {
 466                                 maskb = *mask++;
 467                                 datab = *data++;
 468                                 for ( i=0; i<8; ++i ) {
 469                                         if ( maskb & 0x80 ) {
 470                                                 *dst = pixels[datab>>7];
 471                                         }
 472                                         maskb <<= 1;
 473                                         datab <<= 1;
 474                                         dst++;
 475                                 }
 476                         }
 477                         dst += dstskip;
 478                 }
 479             }
 480             break;
 481         }
 482 }
 483 
 484 static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area)
     /* [<][>][^][v][top][bottom][index][help] */
 485 {
 486         const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
 487         int h;
 488         int x, minx, maxx;
 489         Uint8 *data, datab = 0;
 490         Uint8 *mask, maskb = 0;
 491         Uint8 *dst;
 492         int dstbpp, dstskip;
 493 
 494         data = SDL_cursor->data + area->y * SDL_cursor->area.w/8;
 495         mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8;
 496         dstbpp = screen->format->BytesPerPixel;
 497         dst = (Uint8 *)screen->pixels +
 498                        (SDL_cursor->area.y+area->y)*screen->pitch +
 499                        SDL_cursor->area.x*dstbpp;
 500         dstskip = screen->pitch-SDL_cursor->area.w*dstbpp;
 501 
 502         minx = area->x;
 503         maxx = area->x+area->w;
 504         if ( screen->format->BytesPerPixel == 1 ) {
 505                 if ( palette_changed ) {
 506                         pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255);
 507                         pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0);
 508                         palette_changed = 0;
 509                 }
 510                 for ( h=area->h; h; h-- ) {
 511                         for ( x=0; x<SDL_cursor->area.w; ++x ) {
 512                                 if ( (x%8) == 0 ) {
 513                                         maskb = *mask++;
 514                                         datab = *data++;
 515                                 }
 516                                 if ( (x >= minx) && (x < maxx) ) {
 517                                         if ( maskb & 0x80 ) {
 518                                                 memset(dst, pixels8[datab>>7], dstbpp);
 519                                         }
 520                                 }
 521                                 maskb <<= 1;
 522                                 datab <<= 1;
 523                                 dst += dstbpp;
 524                         }
 525                         dst += dstskip;
 526                 }
 527         } else {
 528                 for ( h=area->h; h; h-- ) {
 529                         for ( x=0; x<SDL_cursor->area.w; ++x ) {
 530                                 if ( (x%8) == 0 ) {
 531                                         maskb = *mask++;
 532                                         datab = *data++;
 533                                 }
 534                                 if ( (x >= minx) && (x < maxx) ) {
 535                                         if ( maskb & 0x80 ) {
 536                                                 memset(dst, pixels[datab>>7], dstbpp);
 537                                         }
 538                                 }
 539                                 maskb <<= 1;
 540                                 datab <<= 1;
 541                                 dst += dstbpp;
 542                         }
 543                         dst += dstskip;
 544                 }
 545         }
 546 }
 547 
 548 /* This handles the ugly work of converting the saved cursor background from
 549    the pixel format of the shadow surface to that of the video surface.
 550    This is only necessary when blitting from a shadow surface of a different
 551    pixel format than the video surface, and using a software rendered cursor.
 552 */
 553 static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h)
     /* [<][>][^][v][top][bottom][index][help] */
 554 {
 555         SDL_BlitInfo info;
 556         SDL_loblit RunBlit;
 557 
 558         /* Make sure we can steal the blit mapping */
 559         if ( screen->map->dst != SDL_VideoSurface ) {
 560                 return;
 561         }
 562 
 563         /* Set up the blit information */
 564         info.s_pixels = SDL_cursor->save[1];
 565         info.s_width = w;
 566         info.s_height = h;
 567         info.s_skip = 0;
 568         info.d_pixels = SDL_cursor->save[0];
 569         info.d_width = w;
 570         info.d_height = h;
 571         info.d_skip = 0;
 572         info.aux_data = screen->map->sw_data->aux_data;
 573         info.src = screen->format;
 574         info.table = screen->map->table;
 575         info.dst = SDL_VideoSurface->format;
 576         RunBlit = screen->map->sw_data->blit;
 577 
 578         /* Run the actual software blit */
 579         RunBlit(&info);
 580 }
 581 
 582 void SDL_DrawCursorNoLock(SDL_Surface *screen)
     /* [<][>][^][v][top][bottom][index][help] */
 583 {
 584         SDL_Rect area;
 585 
 586         /* Get the mouse rectangle, clipped to the screen */
 587         SDL_MouseRect(&area);
 588         if ( (area.w == 0) || (area.h == 0) ) {
 589                 return;
 590         }
 591 
 592         /* Copy mouse background */
 593         { int w, h, screenbpp;
 594           Uint8 *src, *dst;
 595 
 596           /* Set up the copy pointers */
 597           screenbpp = screen->format->BytesPerPixel;
 598           if ( (screen == SDL_VideoSurface) ||
 599                   FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) {
 600                 dst = SDL_cursor->save[0];
 601           } else {
 602                 dst = SDL_cursor->save[1];
 603           }
 604           src = (Uint8 *)screen->pixels + area.y * screen->pitch +
 605                                           area.x * screenbpp;
 606 
 607           /* Perform the copy */
 608           w = area.w*screenbpp;
 609           h = area.h;
 610           while ( h-- ) {
 611                   memcpy(dst, src, w);
 612                   dst += w;
 613                   src += screen->pitch;
 614           }
 615         }
 616 
 617         /* Draw the mouse cursor */
 618         area.x -= SDL_cursor->area.x;
 619         area.y -= SDL_cursor->area.y;
 620         if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) {
 621                 SDL_DrawCursorFast(screen, &area);
 622         } else {
 623                 SDL_DrawCursorSlow(screen, &area);
 624         }
 625 }
 626 
 627 void SDL_DrawCursor(SDL_Surface *screen)
     /* [<][>][^][v][top][bottom][index][help] */
 628 {
 629         /* Lock the screen if necessary */
 630         if ( screen == NULL ) {
 631                 return;
 632         }
 633         if ( SDL_MUSTLOCK(screen) ) {
 634                 if ( SDL_LockSurface(screen) < 0 ) {
 635                         return;
 636                 }
 637         }
 638 
 639         SDL_DrawCursorNoLock(screen);
 640 
 641         /* Unlock the screen and update if necessary */
 642         if ( SDL_MUSTLOCK(screen) ) {
 643                 SDL_UnlockSurface(screen);
 644         }
 645         if ( (screen == SDL_VideoSurface) &&
 646              ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) {
 647                 SDL_VideoDevice *video = current_video;
 648                 SDL_VideoDevice *this  = current_video;
 649                 SDL_Rect area;
 650 
 651                 SDL_MouseRect(&area);
 652 
 653                 /* This can be called before a video mode is set */
 654                 if ( video->UpdateRects ) {
 655                         video->UpdateRects(this, 1, &area);
 656                 }
 657         }
 658 }
 659 
 660 void SDL_EraseCursorNoLock(SDL_Surface *screen)
     /* [<][>][^][v][top][bottom][index][help] */
 661 {
 662         SDL_Rect area;
 663 
 664         /* Get the mouse rectangle, clipped to the screen */
 665         SDL_MouseRect(&area);
 666         if ( (area.w == 0) || (area.h == 0) ) {
 667                 return;
 668         }
 669 
 670         /* Copy mouse background */
 671         { int w, h, screenbpp;
 672           Uint8 *src, *dst;
 673 
 674           /* Set up the copy pointers */
 675           screenbpp = screen->format->BytesPerPixel;
 676           if ( (screen == SDL_VideoSurface) ||
 677                   FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) {
 678                 src = SDL_cursor->save[0];
 679           } else {
 680                 src = SDL_cursor->save[1];
 681           }
 682           dst = (Uint8 *)screen->pixels + area.y * screen->pitch +
 683                                           area.x * screenbpp;
 684 
 685           /* Perform the copy */
 686           w = area.w*screenbpp;
 687           h = area.h;
 688           while ( h-- ) {
 689                   memcpy(dst, src, w);
 690                   src += w;
 691                   dst += screen->pitch;
 692           }
 693 
 694           /* Perform pixel conversion on cursor background */
 695           if ( src > SDL_cursor->save[1] ) {
 696                 SDL_ConvertCursorSave(screen, area.w, area.h);
 697           }
 698         }
 699 }
 700 
 701 void SDL_EraseCursor(SDL_Surface *screen)
     /* [<][>][^][v][top][bottom][index][help] */
 702 {
 703         /* Lock the screen if necessary */
 704         if ( screen == NULL ) {
 705                 return;
 706         }
 707         if ( SDL_MUSTLOCK(screen) ) {
 708                 if ( SDL_LockSurface(screen) < 0 ) {
 709                         return;
 710                 }
 711         }
 712 
 713         SDL_EraseCursorNoLock(screen);
 714 
 715         /* Unlock the screen and update if necessary */
 716         if ( SDL_MUSTLOCK(screen) ) {
 717                 SDL_UnlockSurface(screen);
 718         }
 719         if ( (screen == SDL_VideoSurface) &&
 720              ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) {
 721                 SDL_VideoDevice *video = current_video;
 722                 SDL_VideoDevice *this  = current_video;
 723                 SDL_Rect area;
 724 
 725                 SDL_MouseRect(&area);
 726                 video->UpdateRects(this, 1, &area);
 727         }
 728 }
 729 
 730 /* Reset the cursor on video mode change
 731    FIXME:  Keep track of all cursors, and reset them all.
 732  */
 733 void SDL_ResetCursor(void)
     /* [<][>][^][v][top][bottom][index][help] */
 734 {
 735         int savelen;
 736 
 737         if ( SDL_cursor ) {
 738                 savelen = SDL_cursor->area.w*4*SDL_cursor->area.h;
 739                 SDL_cursor->area.x = 0;
 740                 SDL_cursor->area.y = 0;
 741                 memset(SDL_cursor->save[0], 0, savelen);
 742         }
 743 }

/* [<][>][^][v][top][bottom][index][help] */