src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Sat, 13 Apr 2013 21:29:36 -0400
changeset 32 0e6f8855a779
parent 31 066b1f18cc89
child 33 4e9cde983cdc
permissions -rw-r--r--
Implemented mousewheel event.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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 
    22 /* This file contains functions for backwards compatibility with SDL 1.2 */
    23 
    24 #include "SDL20_include_wrapper.h"
    25 
    26 #if !SDL_VERSION_ATLEAST(2,0,0)
    27 #error You need to compile against SDL 2.0 headers.
    28 #endif
    29 
    30 #include <stdarg.h>
    31 
    32 //#include "video/SDL_sysvideo.h"
    33 //#include "video/SDL_pixels_c.h"
    34 //#include "render/SDL_yuv_sw_c.h"
    35 
    36 // !!! IMPLEMENT_ME SDL_ConvertSurface
    37 // !!! IMPLEMENT_ME SDL_GetKeyName
    38 // !!! IMPLEMENT_ME SDL_GetKeyState
    39 // !!! IMPLEMENT_ME SDL_GetModState
    40 // !!! IMPLEMENT_ME SDL_GetRelativeMouseState
    41 // !!! IMPLEMENT_ME SDL_LockSurface
    42 // !!! IMPLEMENT_ME SDL_LowerBlit
    43 // !!! IMPLEMENT_ME SDL_SetColorKey
    44 // !!! IMPLEMENT_ME SDL_SetModState
    45 // !!! IMPLEMENT_ME SDL_SoftStretch
    46 // !!! IMPLEMENT_ME SDL_UnlockSurface
    47 // !!! IMPLEMENT_ME SDL_UpperBlit
    48 // !!! IMPLEMENT_ME X11_KeyToUnicode
    49 
    50 
    51 #define SDL20_SYM(rc,fn,params,args,ret) \
    52     typedef rc (*SDL20_##fn##_t) params; \
    53     static SDL20_##fn##_t SDL20_##fn = NULL;
    54 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
    55     SDL20_SYM(rc,fn,params,args,ret)
    56 #include "SDL20_syms.h"
    57 #undef SDL20_SYM_PASSTHROUGH
    58 #undef SDL20_SYM
    59 
    60 typedef void (*SDL20_SetError_t)(const char *fmt, ...);
    61 static SDL20_SetError_t SDL20_SetError = NULL;
    62 
    63 /* these are macros in the SDL headers, so make our own. */
    64 #define SDL20_OutOfMemory()	SDL20_Error(SDL_ENOMEM)
    65 #define SDL20_Unsupported()	SDL20_Error(SDL_UNSUPPORTED)
    66 #define SDL20_InvalidParamError(param)	SDL20_SetError("Parameter '%s' is invalid", (param))
    67 
    68 
    69 #define SDL12_INIT_TIMER       0x00000001
    70 #define SDL12_INIT_AUDIO       0x00000010
    71 #define SDL12_INIT_VIDEO       0x00000020
    72 #define SDL12_INIT_CDROM       0x00000100
    73 #define SDL12_INIT_JOYSTICK    0x00000200
    74 #define SDL12_INIT_NOPARACHUTE 0x00100000
    75 #define SDL12_INIT_EVENTTHREAD 0x01000000
    76 #define SDL12_INIT_EVERYTHING  0x0000FFFF
    77 
    78 typedef struct SDL12_Palette
    79 {
    80     int       ncolors;
    81     SDL_Color *colors;
    82 } SDL12_Palette;
    83 
    84 typedef struct SDL12_PixelFormat
    85 {
    86     SDL12_Palette *palette;
    87     Uint8 BitsPerPixel;
    88     Uint8 BytesPerPixel;
    89     Uint8 Rloss;
    90     Uint8 Gloss;
    91     Uint8 Bloss;
    92     Uint8 Aloss;
    93     Uint8 Rshift;
    94     Uint8 Gshift;
    95     Uint8 Bshift;
    96     Uint8 Ashift;
    97     Uint32 Rmask;
    98     Uint32 Gmask;
    99     Uint32 Bmask;
   100     Uint32 Amask;
   101     Uint32 colorkey;
   102     Uint8 alpha;
   103 } SDL12_PixelFormat;
   104 
   105 typedef struct SDL12_Surface
   106 {
   107     Uint32 flags;
   108     SDL12_PixelFormat *format;
   109     int w;
   110     int h;
   111     Uint16 pitch;
   112     void *pixels;
   113     int offset;
   114     SDL_Surface *hwdata; /* the real SDL 1.2 has an opaque pointer to a platform-specific thing here. */
   115     SDL_Rect clip_rect;
   116     Uint32 unused1;
   117     Uint32 locked;
   118     void *blitmap;
   119     unsigned int format_version;
   120     int refcount;
   121 } SDL12_Surface;
   122 
   123 typedef struct
   124 {
   125     Uint32 hw_available :1;
   126     Uint32 wm_available :1;
   127     Uint32 UnusedBits1  :6;
   128     Uint32 UnusedBits2  :1;
   129     Uint32 blit_hw      :1;
   130     Uint32 blit_hw_CC   :1;
   131     Uint32 blit_hw_A    :1;
   132     Uint32 blit_sw      :1;
   133     Uint32 blit_sw_CC   :1;
   134     Uint32 blit_sw_A    :1;
   135     Uint32 blit_fill    :1;
   136     Uint32 UnusedBits3  :16;
   137     Uint32 video_mem;
   138     SDL_PixelFormat *vfmt;
   139     int current_w;
   140     int current_h;
   141 } SDL12_VideoInfo;
   142 
   143 
   144 #define SDL12_HWSURFACE 0x00000001
   145 #define SDL12_ASYNCBLIT 0x00000004
   146 #define SDL12_ANYFORMAT 0x10000000
   147 #define SDL12_HWPALETTE 0x20000000
   148 #define SDL12_DOUBLEBUF 0x40000000
   149 #define SDL12_FULLSCREEN 0x80000000
   150 #define SDL12_OPENGL 0x00000002
   151 #define SDL12_OPENGLBLIT 0x0000000A
   152 #define SDL12_RESIZABLE 0x00000010
   153 #define SDL12_NOFRAME 0x00000020
   154 #define SDL12_HWACCEL 0x00000100
   155 #define SDL12_SRCCOLORKEY 0x00001000
   156 #define SDL12_RLEACCELOK 0x00002000
   157 #define SDL12_RLEACCEL 0x00004000
   158 #define SDL12_SRCALPHA 0x00010000
   159 #define SDL12_PREALLOC 0x01000000
   160 
   161 typedef enum
   162 {
   163     SDL12_NOEVENT = 0,
   164     SDL12_ACTIVEEVENT,
   165     SDL12_KEYDOWN,
   166     SDL12_KEYUP,
   167     SDL12_MOUSEMOTION,
   168     SDL12_MOUSEBUTTONDOWN,
   169     SDL12_MOUSEBUTTONUP,
   170     SDL12_JOYAXISMOTION,
   171     SDL12_JOYBALLMOTION,
   172     SDL12_JOYHATMOTION,
   173     SDL12_JOYBUTTONDOWN,
   174     SDL12_JOYBUTTONUP,
   175     SDL12_QUIT,
   176     SDL12_SYSWMEVENT,
   177     SDL12_EVENT_RESERVEDA,
   178     SDL12_EVENT_RESERVEDB,
   179     SDL12_VIDEORESIZE,
   180     SDL12_VIDEOEXPOSE,
   181     SDL12_USEREVENT = 24,
   182     SDL12_NUMEVENTS = 32
   183 } SDL12_EventType;
   184 
   185 
   186 #define SDL12_APPMOUSEFOCUS (1<<0)
   187 #define SDL12_APPINPUTFOCUS (1<<1)
   188 #define SDL12_APPACTIVE     (1<<2)
   189 
   190 typedef struct
   191 {
   192     Uint8 type;
   193     Uint8 gain;
   194     Uint8 state;
   195 } SDL12_ActiveEvent;
   196 
   197 typedef struct
   198 {
   199     Uint8 type;
   200     Uint8 which;
   201     Uint8 state;
   202     //FIXME: SDL12_keysym keysym;
   203 } SDL12_KeyboardEvent;
   204 
   205 typedef struct
   206 {
   207     Uint8 type;
   208     Uint8 which;
   209     Uint8 state;
   210     Uint16 x, y;
   211     Sint16 xrel;
   212     Sint16 yrel;
   213 } SDL12_MouseMotionEvent;
   214 
   215 typedef struct
   216 {
   217     Uint8 type;
   218     Uint8 which;
   219     Uint8 button;
   220     Uint8 state;
   221     Uint16 x, y;
   222 } SDL12_MouseButtonEvent;
   223 
   224 typedef struct
   225 {
   226     Uint8 type;
   227     Uint8 which;
   228     Uint8 axis;
   229     Sint16 value;
   230 } SDL12_JoyAxisEvent;
   231 
   232 typedef struct
   233 {
   234     Uint8 type;
   235     Uint8 which;
   236     Uint8 ball;
   237     Sint16 xrel;
   238     Sint16 yrel;
   239 } SDL12_JoyBallEvent;
   240 
   241 typedef struct
   242 {
   243     Uint8 type;
   244     Uint8 which;
   245     Uint8 hat;
   246     Uint8 value;
   247 } SDL12_JoyHatEvent;
   248 
   249 typedef struct
   250 {
   251     Uint8 type;
   252     Uint8 which;
   253     Uint8 button;
   254     Uint8 state;
   255 } SDL12_JoyButtonEvent;
   256 
   257 typedef struct
   258 {
   259     Uint8 type;
   260     int w;
   261     int h;
   262 } SDL12_ResizeEvent;
   263 
   264 typedef struct
   265 {
   266     Uint8 type;
   267 } SDL12_ExposeEvent;
   268 
   269 typedef struct
   270 {
   271     Uint8 type;
   272 } SDL12_QuitEvent;
   273 
   274 typedef struct
   275 {
   276     Uint8 type;
   277     int code;
   278     void *data1;
   279     void *data2;
   280 } SDL12_UserEvent;
   281 
   282 typedef struct
   283 {
   284     Uint8 type;
   285     void *msg;
   286 } SDL12_SysWMEvent;
   287 
   288 typedef union
   289 {
   290     Uint8 type;
   291     SDL12_ActiveEvent active;
   292     SDL12_KeyboardEvent key;
   293     SDL12_MouseMotionEvent motion;
   294     SDL12_MouseButtonEvent button;
   295     SDL12_JoyAxisEvent jaxis;
   296     SDL12_JoyBallEvent jball;
   297     SDL12_JoyHatEvent jhat;
   298     SDL12_JoyButtonEvent jbutton;
   299     SDL12_ResizeEvent resize;
   300     SDL12_ExposeEvent expose;
   301     SDL12_QuitEvent quit;
   302     SDL12_UserEvent user;
   303     SDL12_SysWMEvent syswm;
   304 } SDL12_Event;
   305 
   306 typedef int (SDLCALL *SDL12_EventFilter)(const SDL12_Event *event12);
   307 static int EventFilter20to12(void *data, SDL_Event *event20);
   308 
   309 typedef Uint32 (SDLCALL *SDL12_TimerCallback)(Uint32 interval);
   310 typedef SDL_TimerCallback SDL12_NewTimerCallback;
   311 
   312 typedef struct
   313 {
   314     SDL_Rect area;
   315     Sint16 hot_x;
   316     Sint16 hot_y;
   317     Uint8 *data;
   318     Uint8 *mask;
   319     Uint8 *save[2];
   320     SDL_Cursor *wm_cursor;  /* the real SDL 1.2 has an opaque pointer to a platform-specific cursor here. */
   321 } SDL12_Cursor;
   322 
   323 typedef enum
   324 {
   325     SDL12_GL_RED_SIZE,
   326     SDL12_GL_GREEN_SIZE,
   327     SDL12_GL_BLUE_SIZE,
   328     SDL12_GL_ALPHA_SIZE,
   329     SDL12_GL_BUFFER_SIZE,
   330     SDL12_GL_DOUBLEBUFFER,
   331     SDL12_GL_DEPTH_SIZE,
   332     SDL12_GL_STENCIL_SIZE,
   333     SDL12_GL_ACCUM_RED_SIZE,
   334     SDL12_GL_ACCUM_GREEN_SIZE,
   335     SDL12_GL_ACCUM_BLUE_SIZE,
   336     SDL12_GL_ACCUM_ALPHA_SIZE,
   337     SDL12_GL_STEREO,
   338     SDL12_GL_MULTISAMPLEBUFFERS,
   339     SDL12_GL_MULTISAMPLESAMPLES,
   340     SDL12_GL_ACCELERATED_VISUAL,
   341     SDL12_GL_SWAP_CONTROL,
   342     SDL12_GL_MAX_ATTRIBUTE
   343 } SDL12_GLattr;
   344 
   345 static SDL12_VideoInfo VideoInfo;
   346 static SDL_Window *VideoWindow20 = NULL;
   347 static SDL12_Surface *WindowSurface = NULL;
   348 static SDL12_Surface *VideoSurface = NULL;
   349 static SDL12_Surface *ShadowSurface = NULL;
   350 static SDL12_Surface *PublicSurface = NULL;
   351 static SDL_GLContext *VideoContext = NULL;
   352 static Uint32 VideoFlags = 0;
   353 static SDL_Rect VideoViewport;
   354 static char *WindowTitle = NULL;
   355 static char *WindowIconTitle = NULL;
   356 static SDL_Surface *VideoIcon;
   357 static int EnabledUnicode = 0;
   358 static int VideoDisplayIndex = 0;
   359 static int CDRomInit = 0;
   360 static SDL12_EventFilter EventFilter12 = NULL;
   361 static SDL12_Cursor *CurrentCursor = NULL;
   362 static Uint8 EventStates[SDL12_NUMEVENTS];
   363 static int SwapInterval = 0;
   364 
   365 // !!! FIXME: need a mutex for the event queue.
   366 #define SDL12_MAXEVENTS 128
   367 typedef struct EventQueueType
   368 {
   369     SDL12_Event event12;
   370     struct EventQueueType *next;
   371 } EventQueueType;
   372 
   373 static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
   374 static EventQueueType *EventQueueHead = NULL;
   375 static EventQueueType *EventQueueTail = NULL;
   376 static EventQueueType *EventQueueAvailable = NULL;
   377 
   378 /* Obviously we can't use SDL_LoadObject() to load SDL2.  :)  */
   379 #if defined(_WINDOWS)
   380     #define WIN32_LEAN_AND_MEAN 1
   381     #include <windows.h>
   382     #define SDL20_LIBNAME "SDL2.dll"
   383     static HANDLE Loaded_SDL20 = NULL;
   384     #define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
   385     #define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
   386     #define CloseSDL20Library() { { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   387 #elif defined(unix) || defined(__APPLE__)
   388     #include <dlfcn.h>
   389     #ifdef __APPLE__
   390     #define SDL20_LIBNAME "libSDL2.dylib"
   391     #else
   392     #define SDL20_LIBNAME "libSDL2-2.0.so.0"
   393     #endif
   394     static void *Loaded_SDL20 = NULL;
   395     #define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL)) != NULL)
   396     #define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
   397     #define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   398 #else
   399     #error Please define your platform.
   400 #endif
   401 
   402 static void *
   403 LoadSDL20Symbol(const char *fn, int *okay)
   404 {
   405     void *retval = NULL;
   406     if (*okay)  /* only bother trying if we haven't previously failed. */
   407     {
   408         retval = LookupSDL20Sym(fn);
   409         if (retval == NULL)
   410             *okay = 0;
   411     }
   412     return retval;
   413 }
   414 
   415 static void
   416 UnloadSDL20(void)
   417 {
   418     #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = NULL;
   419     #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) SDL20_##fn = NULL;
   420     #include "SDL20_syms.h"
   421     #undef SDL20_SYM_PASSTHROUGH
   422     #undef SDL20_SYM
   423     SDL20_SetError = NULL;
   424     CloseSDL20Library();
   425 }
   426 
   427 static int
   428 LoadSDL20(void)
   429 {
   430     int okay = 1;
   431     if (!Loaded_SDL20)
   432     {
   433         okay = LoadSDL20Library();
   434         #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
   435         #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) SDL20_SYM(rc,fn,params,args,ret)
   436         #include "SDL20_syms.h"
   437         #undef SDL20_SYM_PASSTHROUGH
   438         #undef SDL20_SYM
   439         SDL20_SetError = (SDL20_SetError_t) LoadSDL20Symbol("SDL_SetError", &okay);
   440         if (!okay)
   441             UnloadSDL20();
   442     }
   443     return okay;
   444 }
   445 
   446 
   447 static int
   448 GetVideoDisplay()
   449 {
   450     // !!! FIXME: cache this value during SDL_Init() so it doesn't change.
   451     const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
   452     if ( !variable ) {
   453         variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
   454     }
   455     if ( variable ) {
   456         return SDL_atoi(variable);
   457     } else {
   458         return 0;
   459     }
   460 }
   461 
   462 static int
   463 DoSDLInit(const int justsubs, Uint32 sdl12flags)
   464 {
   465     Uint32 sdl20flags = 0;
   466     int rc;
   467 
   468     if (!LoadSDL20())
   469         return -1;
   470 
   471     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   472     SETFLAG(TIMER);
   473     SETFLAG(AUDIO);
   474     SETFLAG(VIDEO);
   475     SETFLAG(JOYSTICK);
   476     SETFLAG(NOPARACHUTE);
   477     #undef SETFLAG
   478 
   479     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   480     if (sdl12flags & SDL12_INIT_CDROM)
   481         CDRomInit = 1;
   482 
   483     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   484 
   485     rc = justsubs ? SDL20_InitSubSystem(sdl20flags) : SDL20_Init(sdl20flags);
   486     if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO))
   487     {
   488         int i;
   489         for (i = 0; i < SDL12_MAXEVENTS-1; i++)
   490             EventQueuePool[i].next = &EventQueuePool[i+1];
   491         EventQueuePool[SDL12_MAXEVENTS-1].next = NULL;
   492         EventQueueHead = EventQueueTail = NULL;
   493         EventQueueAvailable = EventQueuePool;
   494         SDL_memset(EventStates, SDL_ENABLE, sizeof (EventStates)); /* on by default */
   495         EventStates[SDL12_SYSWMEVENT] = SDL_IGNORE;  /* off by default. */
   496         SDL20_SetEventFilter(EventFilter20to12, NULL);
   497         VideoDisplayIndex = GetVideoDisplay();
   498         SwapInterval = 0;
   499     }
   500 
   501     return rc;
   502 }
   503 
   504 int
   505 SDL_InitSubSystem(Uint32 sdl12flags)
   506 {
   507     return DoSDLInit(1, sdl12flags);
   508 }
   509 
   510 int
   511 SDL_Init(Uint32 sdl12flags)
   512 {
   513     return DoSDLInit(0, sdl12flags);
   514 }
   515 
   516 Uint32
   517 SDL_WasInit(Uint32 sdl12flags)
   518 {
   519     // !!! FIXME: this is cut and pasted several places.
   520     Uint32 sdl20flags = 0;
   521     Uint32 extraflags = 0;
   522 
   523     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   524     SETFLAG(TIMER);
   525     SETFLAG(AUDIO);
   526     SETFLAG(VIDEO);
   527     SETFLAG(JOYSTICK);
   528     SETFLAG(NOPARACHUTE);
   529     #undef SETFLAG
   530 
   531     if ((sdl12flags & SDL12_INIT_CDROM) && (CDRomInit))
   532         extraflags |= SDL12_INIT_CDROM;
   533 
   534     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   535 
   536     // !!! FIXME: convert back to 1.2
   537     return SDL20_WasInit(sdl20flags) | extraflags;
   538 }
   539 
   540 void
   541 SDL_QuitSubSystem(Uint32 sdl12flags)
   542 {
   543     Uint32 sdl20flags = 0;
   544 
   545     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   546     SETFLAG(TIMER);
   547     SETFLAG(AUDIO);
   548     SETFLAG(VIDEO);
   549     SETFLAG(JOYSTICK);
   550     SETFLAG(NOPARACHUTE);
   551     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   552     #undef SETFLAG
   553 
   554     if (sdl12flags & SDL12_INIT_CDROM)
   555         CDRomInit = 0;
   556 
   557     // !!! FIXME: reset a bunch of other global variables too.
   558     if (sdl12flags & SDL12_INIT_VIDEO) {
   559         EventFilter12 = NULL;
   560         EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   561         CurrentCursor = NULL;
   562         SDL20_FreeFormat(VideoInfo.vfmt);
   563         SDL_zero(VideoInfo);
   564     }
   565 
   566     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   567     SDL20_QuitSubSystem(sdl20flags);
   568 
   569     // !!! FIXME: UnloadSDL20() ?
   570 }
   571 
   572 void
   573 SDL_Quit(void)
   574 {
   575     // !!! FIXME: reset a bunch of other global variables too.
   576     EventFilter12 = NULL;
   577     EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   578     CurrentCursor = NULL;
   579     SDL20_FreeFormat(VideoInfo.vfmt);
   580     SDL_zero(VideoInfo);
   581     CDRomInit = 0;
   582     SDL20_Quit();
   583     UnloadSDL20();
   584 }
   585 
   586 void
   587 SDL_SetError(const char *fmt, ...)
   588 {
   589     char *str = NULL;
   590     va_list ap;
   591     va_start(ap, fmt);
   592     vasprintf(&str, fmt, ap);
   593     va_end(ap);
   594     if (!str)
   595         SDL20_OutOfMemory();
   596     else
   597     {
   598         SDL20_SetError("%s", str);
   599         free(str);
   600     }
   601 }
   602 
   603 const char *
   604 SDL_GetError(void)
   605 {
   606     if (!Loaded_SDL20)
   607     {
   608         static const char noload_errstr[] = "Failed to load SDL 2.0 shared library";
   609         return noload_errstr;
   610     }
   611     return SDL20_GetError();
   612 }
   613 
   614 
   615 static const char *
   616 GetDriverName(const char *name, char *namebuf, int maxlen)
   617 {
   618     if (name) {
   619         if (namebuf) {
   620             SDL20_strlcpy(namebuf, name, maxlen);
   621             return namebuf;
   622         } else {
   623             return name;
   624         }
   625     }
   626     return NULL;
   627 }
   628 
   629 const char *
   630 SDL_AudioDriverName(char *namebuf, int maxlen)
   631 {
   632     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
   633 }
   634 
   635 const char *
   636 SDL_VideoDriverName(char *namebuf, int maxlen)
   637 {
   638     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
   639 }
   640 
   641 int
   642 SDL_PollEvent(SDL12_Event *event12)
   643 {
   644     EventQueueType *next;
   645 
   646     SDL20_PumpEvents();  /* this will run our filter and build our 1.2 queue. */
   647 
   648     if (EventQueueHead == NULL)
   649         return 0;  /* no events at the moment. */
   650 
   651     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
   652     next = EventQueueHead->next;
   653     EventQueueHead->next = EventQueueAvailable;
   654     EventQueueAvailable = EventQueueHead;
   655     EventQueueHead = next;
   656     return 1;
   657 }
   658 
   659 int
   660 SDL_PushEvent(SDL12_Event *event12)
   661 {
   662     EventQueueType *item = EventQueueAvailable;
   663     if (item == NULL)
   664         return -1;  /* no space available at the moment. */
   665 
   666     EventQueueAvailable = item->next;
   667     if (EventQueueTail)
   668         EventQueueTail->next = item;
   669     else
   670         EventQueueHead = EventQueueTail = item;
   671     item->next = NULL;
   672 
   673     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
   674     return 0;
   675 }
   676 
   677 int
   678 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
   679 {
   680     if (action == SDL_ADDEVENT)
   681     {
   682         int i;
   683         for (i = 0; i < numevents; i++)
   684         {
   685             if (SDL_PushEvent(&events12[i]) == -1)
   686                 break;  /* out of space for more events. */
   687         }
   688         return i;
   689     }
   690     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
   691     {
   692         const SDL_bool isGet = (action == SDL_GETEVENT);
   693         EventQueueType *prev = NULL;
   694         EventQueueType *item = EventQueueHead;
   695         EventQueueType *next = NULL;
   696         int chosen = 0;
   697         while (chosen < numevents)
   698         {
   699             EventQueueType *nextPrev = item;
   700             if (!item)
   701                 break;  /* no more events at the moment. */
   702 
   703             next = item->next;  /* copy, since we might overwrite item->next */
   704 
   705             if (mask & (1<<item->event12.type))
   706             {
   707                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
   708                 if (isGet)  /* remove from list? */
   709                 {
   710                     if (prev != NULL)
   711                         prev->next = next;
   712                     if (item == EventQueueHead)
   713                         EventQueueHead = next;
   714                     if (item == EventQueueTail)
   715                         EventQueueTail = prev;
   716 
   717                     /* put it back in the free pool. */
   718                     item->next = EventQueueAvailable;
   719                     EventQueueAvailable = item;
   720                     nextPrev = prev;  /* previous item doesn't change. */
   721                 }
   722             }
   723 
   724             item = next;
   725             prev = nextPrev;
   726         }
   727         return chosen;
   728     }
   729 
   730     return 0;
   731 }
   732 
   733 int
   734 SDL_WaitEvent(SDL12_Event *event12)
   735 {
   736     /* In 1.2, this only fails (-1) if you haven't SDL_Init()'d. */
   737     while (!SDL_PollEvent(event12))
   738         SDL_Delay(10);
   739     return 1;
   740 }
   741 
   742 static SDL_bool
   743 PushEventIfNotFiltered(SDL12_Event *event12)
   744 {
   745     if (event12->type != SDL12_NOEVENT)
   746     {
   747         if (EventStates[event12->type] != SDL_IGNORE)
   748         {
   749             if ((!EventFilter12) || (EventFilter12(event12)))
   750                 return (SDL_PushEvent(event12) == 0);
   751         }
   752     }
   753     return SDL_FALSE;
   754 }
   755 
   756 Uint8 SDL_GetMouseState(int *x, int *y);
   757 
   758 
   759 Uint8
   760 SDL_EventState(Uint8 type, int state)
   761 {
   762     /* the values of "state" match between 1.2 and 2.0 */
   763     const Uint8 retval = EventStates[type];
   764     SDL12_Event e;
   765 
   766     if (state != SDL_QUERY)
   767         EventStates[type] = state;
   768     if (state == SDL_IGNORE)  /* drop existing events of this type. */
   769         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
   770 
   771     return retval;
   772 }
   773 
   774 static int
   775 EventFilter20to12(void *data, SDL_Event *event20)
   776 {
   777     const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
   778     SDL12_Event event12;
   779     int x, y;
   780 
   781     SDL_assert(data == NULL);  /* currently unused. */
   782 
   783     SDL_zero(event12);
   784 
   785     switch (event20->type)
   786     {
   787         case SDL_QUIT:
   788             event12.type = SDL12_QUIT;
   789             break;
   790 
   791         case SDL_WINDOWEVENT:
   792             switch (event20->window.event)
   793             {
   794                 case SDL_WINDOWEVENT_CLOSE:
   795                     event12.type = SDL12_QUIT;
   796                     break;
   797 
   798                 case SDL_WINDOWEVENT_SHOWN:
   799                 case SDL_WINDOWEVENT_EXPOSED:
   800                     event12.type = SDL12_VIDEOEXPOSE;
   801                     break;
   802 
   803                 case SDL_WINDOWEVENT_RESIZED:
   804                 case SDL_WINDOWEVENT_SIZE_CHANGED:  // !!! FIXME: what's the difference between RESIZED and SIZE_CHANGED?
   805                     event12.type = SDL12_VIDEORESIZE;
   806                     event12.resize.w = event20->window.data1;
   807                     event12.resize.h = event20->window.data2;
   808                     break;
   809 
   810                 case SDL_WINDOWEVENT_MINIMIZED:
   811                     event12.type = SDL12_ACTIVEEVENT;
   812                     event12.active.gain = 0;
   813                     event12.active.state = SDL12_APPACTIVE;
   814                     break;
   815 
   816                 case SDL_WINDOWEVENT_RESTORED:
   817                     event12.type = SDL12_ACTIVEEVENT;
   818                     event12.active.gain = 1;
   819                     event12.active.state = SDL12_APPACTIVE;
   820                     break;
   821 
   822                 case SDL_WINDOWEVENT_ENTER:
   823                     event12.type = SDL12_ACTIVEEVENT;
   824                     event12.active.gain = 1;
   825                     event12.active.state = SDL12_APPMOUSEFOCUS;
   826                     break;
   827 
   828                 case SDL_WINDOWEVENT_LEAVE:
   829                     event12.type = SDL12_ACTIVEEVENT;
   830                     event12.active.gain = 0;
   831                     event12.active.state = SDL12_APPMOUSEFOCUS;
   832                     break;
   833 
   834                 case SDL_WINDOWEVENT_FOCUS_GAINED:
   835                     event12.type = SDL12_ACTIVEEVENT;
   836                     event12.active.gain = 1;
   837                     event12.active.state = SDL12_APPINPUTFOCUS;
   838                     break;
   839 
   840                 case SDL_WINDOWEVENT_FOCUS_LOST:
   841                     event12.type = SDL12_ACTIVEEVENT;
   842                     event12.active.gain = 0;
   843                     event12.active.state = SDL12_APPINPUTFOCUS;
   844                     break;
   845             }
   846             break;
   847 
   848         // !!! FIXME: this is sort of a mess to convert.
   849         //case SDL_SYSWMEVENT:
   850 
   851         // !!! FIXME: write me
   852         case SDL_KEYDOWN:
   853         case SDL_KEYUP:
   854             return 0;
   855 
   856         // !!! FIXME: write me
   857         case SDL_TEXTEDITING:
   858         case SDL_TEXTINPUT:
   859             return 0;
   860 
   861         case SDL_MOUSEMOTION:
   862         	event12.type = SDL12_MOUSEMOTION;
   863             event12.motion.which = (Uint8) event20->motion.which;
   864             event12.motion.state = event20->motion.state;
   865             event12.motion.x = (Uint16) event20->motion.x;
   866             event12.motion.y = (Uint16) event20->motion.y;
   867             event12.motion.xrel = (Sint16) event20->motion.xrel;
   868             event12.motion.yrel = (Sint16) event20->motion.yrel;
   869             break;
   870 
   871         case SDL_MOUSEBUTTONDOWN:
   872         	event12.type = SDL12_MOUSEBUTTONDOWN;
   873             event12.button.which = (Uint8) event20->button.which;
   874             event12.button.button = event20->button.button;
   875             event12.button.state = event20->button.state;
   876             event12.button.x = (Uint16) event20->button.x;
   877             event12.button.y = (Uint16) event20->button.y;
   878             break;
   879 
   880         case SDL_MOUSEBUTTONUP:
   881         	event12.type = SDL12_MOUSEBUTTONUP;
   882             event12.button.which = (Uint8) event20->button.which;
   883             event12.button.button = event20->button.button;
   884             event12.button.state = event20->button.state;
   885             event12.button.x = (Uint16) event20->button.x;
   886             event12.button.y = (Uint16) event20->button.y;
   887             break;
   888 
   889         case SDL_MOUSEWHEEL:
   890             if (event20->wheel.y == 0)
   891                 break;  /* don't support horizontal wheels in 1.2. */
   892 
   893             event12.type = SDL12_MOUSEBUTTONDOWN;
   894             event12.button.which = (Uint8) event20->wheel.which;
   895             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
   896             event12.button.state = SDL_GetMouseState(&x, &y);
   897             event12.button.x = (Uint16) x;
   898             event12.button.y = (Uint16) y;
   899             PushEventIfNotFiltered(&event12);
   900 
   901             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
   902             break;
   903 
   904         case SDL_JOYAXISMOTION:
   905             event12.type = SDL12_JOYAXISMOTION;
   906             event12.jaxis.which = (Uint8) event20->jaxis.which;
   907             event12.jaxis.axis = event20->jaxis.axis;
   908             event12.jaxis.value = event20->jaxis.value;
   909             break;
   910 
   911         case SDL_JOYBALLMOTION:
   912             event12.type = SDL12_JOYBALLMOTION;
   913             event12.jball.which = (Uint8) event20->jball.which;
   914             event12.jball.ball = event20->jball.ball;
   915             event12.jball.xrel = event20->jball.xrel;
   916             event12.jball.yrel = event20->jball.yrel;
   917             break;
   918 
   919         case SDL_JOYHATMOTION:
   920             event12.type = SDL12_JOYHATMOTION;
   921             event12.jhat.which = (Uint8) event20->jhat.which;
   922             event12.jhat.hat = event20->jhat.hat;
   923             event12.jhat.value = event20->jhat.value;
   924             break;
   925 
   926         case SDL_JOYBUTTONDOWN:
   927             event12.type = SDL12_JOYBUTTONDOWN;
   928             event12.jbutton.which = (Uint8) event20->jbutton.which;
   929             event12.jbutton.button = event20->jbutton.button;
   930             event12.jbutton.state = event20->jbutton.state;
   931             break;
   932 
   933         case SDL_JOYBUTTONUP:
   934             event12.type = SDL12_JOYBUTTONUP;
   935             event12.jbutton.which = (Uint8) event20->jbutton.which;
   936             event12.jbutton.button = event20->jbutton.button;
   937             event12.jbutton.state = event20->jbutton.state;
   938             break;
   939 
   940         //case SDL_JOYDEVICEADDED:
   941         //case SDL_JOYDEVICEREMOVED:
   942 	    //case SDL_CONTROLLERAXISMOTION:
   943 	    //case SDL_CONTROLLERBUTTONDOWN:
   944 	    //case SDL_CONTROLLERBUTTONUP:
   945 	    //case SDL_CONTROLLERDEVICEADDED:
   946 	    //case SDL_CONTROLLERDEVICEREMOVED:
   947 	    //case SDL_CONTROLLERDEVICEREMAPPED:
   948         //case SDL_FINGERDOWN:
   949         //case SDL_FINGERUP:
   950         //case SDL_FINGERMOTION:
   951         //case SDL_DOLLARGESTURE:
   952         //case SDL_DOLLARRECORD:
   953         //case SDL_MULTIGESTURE:
   954         //case SDL_CLIPBOARDUPDATE:
   955         //case SDL_DROPFILE:
   956 
   957         default:
   958             return 0;  /* drop everything else. */
   959     }
   960 
   961     PushEventIfNotFiltered(&event12);
   962 
   963     return 0;  /* always drop it from the 2.0 event queue. */
   964 }
   965 
   966 void
   967 SDL_SetEventFilter(SDL12_EventFilter filter12)
   968 {
   969     /* We always have a filter installed, but will call the app's too. */
   970     EventFilter12 = filter12;
   971 }
   972 
   973 SDL12_EventFilter
   974 SDL_GetEventFilter(void)
   975 {
   976     return EventFilter12;
   977 }
   978 
   979 
   980 SDL12_Surface *
   981 Surface20to12(SDL_Surface *surface20)
   982 {
   983     SDL12_Surface *surface12 = NULL;
   984     SDL12_Palette *palette12 = NULL;
   985     SDL12_PixelFormat *format12 = NULL;
   986     Uint32 flags = 0;
   987 
   988     if (!surface20)
   989         return NULL;
   990 
   991     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
   992     if (!surface12)
   993         goto failed;
   994 
   995     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
   996     if (!palette12)
   997         goto failed;
   998 
   999     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  1000     if (!format12)
  1001         goto failed;
  1002 
  1003     SDL_zerop(palette12);
  1004     palette12->ncolors = surface20->format->palette->ncolors;
  1005     palette12->colors = surface20->format->palette->colors;
  1006 
  1007     SDL_zerop(format12);
  1008     format12->palette = palette12;
  1009     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  1010     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  1011     format12->Rloss = surface20->format->Rloss;
  1012     format12->Gloss = surface20->format->Gloss;
  1013     format12->Bloss = surface20->format->Bloss;
  1014     format12->Aloss = surface20->format->Aloss;
  1015     format12->Rshift = surface20->format->Rshift;
  1016     format12->Gshift = surface20->format->Gshift;
  1017     format12->Bshift = surface20->format->Bshift;
  1018     format12->Ashift = surface20->format->Ashift;
  1019     format12->Rmask = surface20->format->Rmask;
  1020     format12->Gmask = surface20->format->Gmask;
  1021     format12->Bmask = surface20->format->Bmask;
  1022     format12->Amask = surface20->format->Amask;
  1023     /* !!! FIXME: format12->colorkey; */
  1024     /* !!! FIXME: format12->alpha; */
  1025 
  1026     SDL_zerop(surface12);
  1027     flags = surface20->flags;
  1028     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  1029     MAPSURFACEFLAGS(PREALLOC);
  1030     MAPSURFACEFLAGS(RLEACCEL);
  1031     MAPSURFACEFLAGS(DONTFREE);
  1032     #undef MAPSURFACEFLAGS
  1033     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  1034 
  1035     surface12->format = format12;
  1036     surface12->w = surface20->w;
  1037     surface12->h = surface20->h;
  1038     surface12->pitch = (Uint16) surface20->pitch;  /* !!! FIXME: make sure this fits in a Uint16 */
  1039     surface12->pixels = surface20->pixels;
  1040     surface12->offset = 0;
  1041     surface12->hwdata = surface20;
  1042     SDL20_memcpy(&surface12->clip_rect, &surface20->clip_rect, sizeof (SDL_Rect));
  1043     surface12->refcount = surface20->refcount;
  1044 
  1045     return surface12;
  1046 
  1047 failed:
  1048     SDL20_free(surface12);
  1049     SDL20_free(palette12);
  1050     SDL20_free(format12);
  1051     return NULL;
  1052 }
  1053 
  1054 SDL12_Surface *
  1055 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1056 {
  1057     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  1058     SDL12_Surface *surface12 = Surface20to12(surface20);
  1059     if (!surface12) {
  1060         SDL20_FreeSurface(surface20);
  1061         return NULL;
  1062     }
  1063 
  1064     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  1065     return surface12;
  1066 }
  1067 
  1068 SDL12_Surface *
  1069 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1070 {
  1071     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  1072     SDL12_Surface *surface12 = Surface20to12(surface20);
  1073     if (!surface12) {
  1074         SDL20_FreeSurface(surface20);
  1075         return NULL;
  1076     }
  1077 
  1078     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  1079     return surface12;
  1080 }
  1081 
  1082 void SDL_FreeSurface(SDL12_Surface *surface12)
  1083 {
  1084     if (surface12) {
  1085         SDL20_FreeSurface(surface12->hwdata);
  1086         if (surface12->format) {
  1087             SDL20_free(surface12->format->palette);
  1088             SDL20_free(surface12->format);
  1089         }
  1090         SDL20_free(surface12);
  1091     }
  1092 }
  1093 
  1094 void
  1095 SDL_GetClipRect(SDL12_Surface *surface12, SDL_Rect *rect)
  1096 {
  1097     if (surface12 && rect)
  1098 	    SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL_Rect));
  1099 }
  1100 
  1101 SDL_bool
  1102 SDL_SetClipRect(SDL12_Surface *surface12, const SDL_Rect *rect)
  1103 {
  1104     SDL_bool retval = SDL_FALSE;
  1105     if (surface12)
  1106     {
  1107         retval = SDL20_SetClipRect(surface12->hwdata, rect);
  1108         SDL20_GetClipRect(surface12->hwdata, &surface12->clip_rect);
  1109     }
  1110     return retval;
  1111 }
  1112 
  1113 int
  1114 SDL_FillRect(SDL12_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1115 {
  1116     const SDL_Rect orig_dstrect = *dstrect;
  1117     const int retval = SDL20_FillRect(dst->hwdata, &orig_dstrect, color);
  1118     if (retval != -1)
  1119     {
  1120         if (dstrect)  /* 1.2 stores the clip intersection in dstrect */
  1121             SDL20_IntersectRect(&orig_dstrect, &dst->clip_rect, dstrect);
  1122     }
  1123     return retval;
  1124 }
  1125 
  1126 
  1127 static SDL_PixelFormat *
  1128 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  1129 {
  1130     palette20->ncolors = format12->palette->ncolors;
  1131     palette20->colors = format12->palette->colors;
  1132     palette20->version = 1;
  1133     palette20->refcount = 1;
  1134     format20->format = SDL_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1135     format20->palette = palette20;
  1136     format20->BitsPerPixel = format12->BitsPerPixel;
  1137     format20->BytesPerPixel = format12->BytesPerPixel;
  1138     format20->Rmask = format12->Rmask;
  1139     format20->Gmask = format12->Gmask;
  1140     format20->Bmask = format12->Bmask;
  1141     format20->Amask = format12->Amask;
  1142     format20->Rloss = format12->Rloss;
  1143     format20->Gloss = format12->Gloss;
  1144     format20->Bloss = format12->Bloss;
  1145     format20->Aloss = format12->Aloss;
  1146     format20->Rshift = format12->Rshift;
  1147     format20->Gshift = format12->Gshift;
  1148     format20->Bshift = format12->Bshift;
  1149     format20->Ashift = format12->Ashift;
  1150     format20->refcount = 1;
  1151     format20->next = NULL;
  1152     return format20;
  1153 }
  1154 
  1155 Uint32
  1156 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1157 {
  1158     /* This is probably way slower than apps expect. */
  1159     SDL_PixelFormat format20;
  1160     SDL_Palette palette20;
  1161     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1162 }
  1163 
  1164 Uint32
  1165 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1166 {
  1167     /* This is probably way slower than apps expect. */
  1168     SDL_PixelFormat format20;
  1169     SDL_Palette palette20;
  1170     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1171 }
  1172 
  1173 void
  1174 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1175 {
  1176     /* This is probably way slower than apps expect. */
  1177     SDL_PixelFormat format20;
  1178     SDL_Palette palette20;
  1179     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1180 }
  1181 
  1182 void
  1183 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1184 {
  1185     /* This is probably way slower than apps expect. */
  1186     SDL_PixelFormat format20;
  1187     SDL_Palette palette20;
  1188     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1189 }
  1190 
  1191 const SDL12_VideoInfo *
  1192 SDL_GetVideoInfo(void)
  1193 {
  1194     SDL_DisplayMode mode;
  1195 
  1196     if (!VideoInfo.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1197         VideoInfo.vfmt = SDL20_AllocFormat(mode.format);
  1198         VideoInfo.current_w = mode.w;
  1199         VideoInfo.current_h = mode.h;
  1200         // !!! FIXME
  1201         //VideoInfo.wm_available = 1;
  1202         //VideoInfo.video_mem = 1024 * 256;
  1203     }
  1204     return &VideoInfo;
  1205 }
  1206 
  1207 int
  1208 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1209 {
  1210     int i, nummodes, actual_bpp = 0;
  1211 
  1212     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1213         return 0;
  1214     }
  1215 
  1216     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1217         SDL_DisplayMode mode;
  1218         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1219         return SDL_BITSPERPIXEL(mode.format);
  1220     }
  1221 
  1222     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1223     for (i = 0; i < nummodes; ++i) {
  1224         SDL_DisplayMode mode;
  1225         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1226         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1227             if (!mode.format) {
  1228                 return bpp;
  1229             }
  1230             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1231                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1232             }
  1233         }
  1234     }
  1235     return actual_bpp;
  1236 }
  1237 
  1238 SDL_Rect **
  1239 SDL_ListModes(const SDL12_PixelFormat *format, Uint32 flags)
  1240 {
  1241     int i, nmodes;
  1242     SDL_Rect **modes;
  1243 
  1244     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1245         return NULL;
  1246     }
  1247 
  1248     if (!(flags & SDL12_FULLSCREEN)) {
  1249         return (SDL_Rect **) (-1);
  1250     }
  1251 
  1252     if (!format) {
  1253         format = VideoInfo.vfmt;
  1254     }
  1255 
  1256     /* !!! FIXME: Memory leak */
  1257     nmodes = 0;
  1258     modes = NULL;
  1259     for (i = 0; i < SDL20_GetNumDisplayModes(VideoDisplayIndex); ++i) {
  1260         SDL_DisplayMode mode;
  1261         int bpp;
  1262 
  1263         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1264         if (!mode.w || !mode.h) {
  1265             return (SDL_Rect **) (-1);
  1266         }
  1267         
  1268         /* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
  1269         if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
  1270             bpp = SDL_BITSPERPIXEL(mode.format);
  1271         } else {
  1272             bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
  1273         }
  1274 
  1275         if (bpp != format->BitsPerPixel) {
  1276             continue;
  1277         }
  1278         if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
  1279             && modes[nmodes - 1]->h == mode.h) {
  1280             continue;
  1281         }
  1282 
  1283         modes = SDL20_realloc(modes, (nmodes + 2) * sizeof(*modes));
  1284         if (!modes) {
  1285             return NULL;
  1286         }
  1287         modes[nmodes] = (SDL_Rect *) SDL20_malloc(sizeof(SDL_Rect));
  1288         if (!modes[nmodes]) {
  1289             return NULL;
  1290         }
  1291         modes[nmodes]->x = 0;
  1292         modes[nmodes]->y = 0;
  1293         modes[nmodes]->w = mode.w;
  1294         modes[nmodes]->h = mode.h;
  1295         ++nmodes;
  1296     }
  1297     if (modes) {
  1298         modes[nmodes] = NULL;
  1299     }
  1300     return modes;
  1301 }
  1302 
  1303 void
  1304 SDL_FreeCursor(SDL12_Cursor *cursor12)
  1305 {
  1306     if (cursor12)
  1307     {
  1308         if (cursor12->wm_cursor)
  1309             SDL20_FreeCursor(cursor12->wm_cursor);
  1310         SDL20_free(cursor12->data);
  1311         SDL20_free(cursor12->mask);
  1312         SDL20_free(cursor12);
  1313     }
  1314 }
  1315 
  1316 SDL12_Cursor *
  1317 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1318 {
  1319     const size_t datasize = h * (w / 8);
  1320     SDL_Cursor *cursor20 = NULL;
  1321     SDL12_Cursor *retval = NULL;
  1322 
  1323     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1324     if (!retval)
  1325         goto outofmem;
  1326 
  1327     SDL_zerop(retval);
  1328 
  1329     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1330     if (!retval->data)
  1331         goto outofmem;
  1332 
  1333     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1334     if (!retval->mask)
  1335         goto outofmem;
  1336 
  1337     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1338     if (!cursor20)
  1339         goto failed;
  1340 
  1341     retval->area.w = w;
  1342     retval->area.h = h;
  1343     retval->hot_x = hot_x;
  1344     retval->hot_y = hot_y;
  1345     retval->wm_cursor = cursor20;
  1346     /* we always leave retval->save as null pointers. */
  1347 
  1348     SDL20_memcpy(retval->data, data, datasize);
  1349     SDL20_memcpy(retval->mask, mask, datasize);
  1350 
  1351     return retval;
  1352 
  1353 outofmem:
  1354     SDL20_OutOfMemory();
  1355 
  1356 failed:
  1357     SDL_FreeCursor(retval);
  1358     return NULL;
  1359 }
  1360 
  1361 void
  1362 SDL_SetCursor(SDL12_Cursor *cursor)
  1363 {
  1364     CurrentCursor = cursor;
  1365     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1366 }
  1367 
  1368 SDL12_Cursor *
  1369 SDL_GetCursor(void)
  1370 {
  1371     return CurrentCursor;
  1372 }
  1373 
  1374 static void
  1375 GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
  1376 {
  1377     int display = VideoDisplayIndex;
  1378     const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
  1379     const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
  1380     if (window) {
  1381         if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
  1382             return;
  1383         }
  1384         if (SDL_strcmp(window, "center") == 0) {
  1385             center = window;
  1386         }
  1387     }
  1388     if (center) {
  1389         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1390         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1391     }
  1392 }
  1393 
  1394 static void
  1395 ClearVideoSurface()
  1396 {
  1397     if (ShadowSurface) {
  1398         SDL20_FillRect(ShadowSurface, NULL,
  1399             SDL20_MapRGB(ShadowSurface->format, 0, 0, 0));
  1400     }
  1401     SDL20_FillRect(WindowSurface, NULL, 0);
  1402     SDL20_UpdateWindowSurface(VideoWindow20);
  1403 }
  1404 
  1405 static void
  1406 SetupScreenSaver(int flags12)
  1407 {
  1408     const char *env;
  1409     SDL_bool allow_screensaver;
  1410 
  1411     /* Allow environment override of screensaver disable */
  1412     env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1413     if (env) {
  1414         allow_screensaver = SDL_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1415     } else if (flags12 & SDL12_FULLSCREEN) {
  1416         allow_screensaver = SDL_FALSE;
  1417     } else {
  1418         allow_screensaver = SDL_TRUE;
  1419     }
  1420     if (allow_screensaver) {
  1421         SDL20_EnableScreenSaver();
  1422     } else {
  1423         SDL20_DisableScreenSaver();
  1424     }
  1425 }
  1426 
  1427 static int
  1428 ResizeVideoMode(int width, int height, int bpp, Uint32 flags12)
  1429 {
  1430     int w, h;
  1431 
  1432     /* We can't resize something we don't have... */
  1433     if (!VideoSurface) {
  1434         return -1;
  1435     }
  1436 
  1437     /* We probably have to recreate the window in fullscreen mode */
  1438     if (flags12 & SDL12_FULLSCREEN) {
  1439         return -1;
  1440     }
  1441 
  1442     /* I don't think there's any change we can gracefully make in flags */
  1443     if (flags12 != VideoFlags) {
  1444         return -1;
  1445     }
  1446     if (bpp != VideoSurface->format->BitsPerPixel) {
  1447         return -1;
  1448     }
  1449 
  1450     /* Resize the window */
  1451     SDL20_GetWindowSize(VideoWindow20, &w, &h);
  1452     if (w != width || h != height) {
  1453         SDL20_SetWindowSize(VideoWindow20, width, height);
  1454     }
  1455 
  1456     /* If we're in OpenGL mode, just resize the stub surface and we're done! */
  1457     if (flags12 & SDL12_OPENGL) {
  1458         VideoSurface->w = width;
  1459         VideoSurface->h = height;
  1460         return 0;
  1461     }
  1462 
  1463     WindowSurface = SDL20_GetWindowSurface(VideoWindow20);
  1464     if (!WindowSurface) {
  1465         return -1;
  1466     }
  1467     if (VideoSurface->format != WindowSurface->format) {
  1468         return -1;
  1469     }
  1470     VideoSurface->w = width;
  1471     VideoSurface->h = height;
  1472     VideoSurface->pixels = WindowSurface->pixels;
  1473     VideoSurface->pitch = WindowSurface->pitch;
  1474     SDL20_SetClipRect(VideoSurface, NULL);
  1475 
  1476     if (ShadowSurface) {
  1477         ShadowSurface->w = width;
  1478         ShadowSurface->h = height;
  1479         ShadowSurface->pitch = SDL20_CalculatePitch(ShadowSurface);
  1480         ShadowSurface->pixels =
  1481             SDL20_realloc(ShadowSurface->pixels,
  1482                         ShadowSurface->h * ShadowSurface->pitch);
  1483         SDL20_SetClipRect(ShadowSurface, NULL);
  1484         SDL20_InvalidateMap(ShadowSurface->map);
  1485     } else {
  1486         PublicSurface = VideoSurface;
  1487     }
  1488 
  1489     ClearVideoSurface();
  1490 
  1491     return 0;
  1492 }
  1493 
  1494 SDL_Surface *
  1495 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1496 {
  1497     SDL_DisplayMode desktop_mode;
  1498     int display = VideoDisplayIndex;
  1499     int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
  1500     int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
  1501     int window_w;
  1502     int window_h;
  1503     Uint32 window_flags20;
  1504     Uint32 surface_flags12;
  1505 
  1506     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1507         if (SDL_Init(SDL12_INIT_VIDEO | SDL12_INIT_NOPARACHUTE) < 0) {
  1508             return NULL;
  1509         }
  1510     }
  1511 
  1512     SDL20_GetDesktopDisplayMode(display, &desktop_mode);
  1513 
  1514     if (width == 0) {
  1515         width = desktop_mode.w;
  1516     }
  1517     if (height == 0) {
  1518         height = desktop_mode.h;
  1519     }
  1520     if (bpp == 0) {
  1521         bpp = SDL_BITSPERPIXEL(desktop_mode.format);
  1522     }
  1523 
  1524     /* See if we can simply resize the existing window and surface */
  1525     if (ResizeVideoMode(width, height, bpp, flags12) == 0) {
  1526         return PublicSurface;
  1527     }
  1528 
  1529     /* Destroy existing window */
  1530     PublicSurface = NULL;
  1531     if (ShadowSurface) {
  1532         ShadowSurface->flags &= ~SDL_DONTFREE;
  1533         SDL20_FreeSurface(ShadowSurface);
  1534         ShadowSurface = NULL;
  1535     }
  1536     if (VideoSurface) {
  1537         VideoSurface->flags &= ~SDL_DONTFREE;
  1538         SDL20_FreeSurface(VideoSurface);
  1539         VideoSurface = NULL;
  1540     }
  1541     if (VideoContext) {
  1542         /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
  1543         SDL20_GL_DeleteContext(VideoContext);
  1544         VideoContext = NULL;
  1545     }
  1546     if (VideoWindow20) {
  1547         SDL20_GetWindowPosition(VideoWindow20, &window_x, &window_y);
  1548         SDL20_DestroyWindow(VideoWindow20);
  1549     }
  1550 
  1551     /* Create a new window */
  1552     window_flags20 = SDL_WINDOW_SHOWN;
  1553     if (flags12 & SDL12_FULLSCREEN) {
  1554         window_flags20 |= SDL_WINDOW_FULLSCREEN;
  1555     }
  1556     if (flags12 & SDL12_OPENGL) {
  1557         window_flags20 |= SDL_WINDOW_OPENGL;
  1558     }
  1559     if (flags12 & SDL12_RESIZABLE) {
  1560         window_flags20 |= SDL_WINDOW_RESIZABLE;
  1561     }
  1562     if (flags12 & SDL12_NOFRAME) {
  1563         window_flags20 |= SDL_WINDOW_BORDERLESS;
  1564     }
  1565     GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
  1566     VideoWindow20 =
  1567         SDL20_CreateWindow(WindowTitle, window_x, window_y, width, height,
  1568                          window_flags20);
  1569     if (!VideoWindow20) {
  1570         return NULL;
  1571     }
  1572     SDL20_SetWindowIcon(VideoWindow20, VideoIcon);
  1573 
  1574     SetupScreenSaver(flags12);
  1575 
  1576     window_flags20 = SDL_GetWindowFlags(VideoWindow20);
  1577     surface_flags12 = 0;
  1578     if (window_flags20 & SDL_WINDOW_FULLSCREEN) {
  1579         surface_flags12 |= SDL_FULLSCREEN;
  1580     }
  1581     if ((window_flags & SDL_WINDOW_OPENGL) && (flags12 & SDL_OPENGL)) {
  1582         surface_flags12 |= SDL_OPENGL;
  1583     }
  1584     if (window_flags & SDL_WINDOW_RESIZABLE) {
  1585         surface_flags12 |= SDL_RESIZABLE;
  1586     }
  1587     if (window_flags & SDL_WINDOW_BORDERLESS) {
  1588         surface_flags12 |= SDL_NOFRAME;
  1589     }
  1590 
  1591     VideoFlags = flags12;
  1592 
  1593     /* If we're in OpenGL mode, just create a stub surface and we're done! */
  1594     if (flags12 & SDL_OPENGL) {
  1595 
  1596         VideoContext = SDL_GL_CreateContext(VideoWindow20);
  1597         if (!VideoContext) {
  1598             return NULL;
  1599         }
  1600         if (SDL_GL_MakeCurrent(VideoWindow20, VideoContext) < 0) {
  1601             return NULL;
  1602         }
  1603 
  1604         SDL20_GL_SetSwapInterval(SwapInterval);  /* don't care if this fails. */
  1605 
  1606         VideoSurface =
  1607             SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
  1608         if (!VideoSurface) {
  1609             return NULL;
  1610         }
  1611         VideoSurface->flags |= surface_flags12;
  1612         PublicSurface = VideoSurface;
  1613         return PublicSurface;
  1614     }
  1615 
  1616     /* Create the screen surface */
  1617     WindowSurface = SDL_GetWindowSurface(VideoWindow20);
  1618     if (!WindowSurface) {
  1619         return NULL;
  1620     }
  1621 
  1622     /* Center the public surface in the window surface */
  1623     SDL_GetWindowSize(VideoWindow20, &window_w, &window_h);
  1624     VideoViewport.x = (window_w - width)/2;
  1625     VideoViewport.y = (window_h - height)/2;
  1626     VideoViewport.w = width;
  1627     VideoViewport.h = height;
  1628 
  1629     VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  1630     VideoSurface->flags |= surface_flags12;
  1631     VideoSurface->flags |= SDL12_DONTFREE;
  1632     SDL_FreeFormat(VideoSurface->format);
  1633     VideoSurface->format = WindowSurface->format;
  1634     VideoSurface->format->refcount++;
  1635     VideoSurface->w = width;
  1636     VideoSurface->h = height;
  1637     VideoSurface->pitch = WindowSurface->pitch;
  1638     VideoSurface->pixels = (void *)((Uint8 *)WindowSurface->pixels +
  1639         VideoViewport.y * VideoSurface->pitch +
  1640         VideoViewport.x  * VideoSurface->format->BytesPerPixel);
  1641     SDL_SetClipRect(VideoSurface, NULL);
  1642 
  1643     /* Create a shadow surface if necessary */
  1644     if ((bpp != VideoSurface->format->BitsPerPixel)
  1645         && !(flags12 & SDL12_ANYFORMAT)) {
  1646         ShadowSurface =
  1647             SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
  1648         if (!ShadowSurface) {
  1649             return NULL;
  1650         }
  1651         ShadowSurface->flags |= surface_flags12;
  1652         ShadowSurface->flags |= SDL12_DONTFREE;
  1653 
  1654         /* 8-bit ShadowSurface surfaces report that they have exclusive palette */
  1655         if (ShadowSurface->format->palette) {
  1656             ShadowSurface->flags |= SDL12_HWPALETTE;
  1657             SDL_DitherColors(ShadowSurface->format->palette->colors,
  1658                              ShadowSurface->format->BitsPerPixel);
  1659         }
  1660         SDL_FillRect(ShadowSurface, NULL,
  1661             SDL_MapRGB(ShadowSurface->format, 0, 0, 0));
  1662     }
  1663     PublicSurface =
  1664         (ShadowSurface ? ShadowSurface : VideoSurface);
  1665 
  1666     ClearVideoSurface();
  1667 
  1668     /* We're finally done! */
  1669     return PublicSurface;
  1670 }
  1671 
  1672 SDL_Surface *
  1673 SDL_GetVideoSurface(void)
  1674 {
  1675     return PublicSurface;
  1676 }
  1677 
  1678 int
  1679 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
  1680 {
  1681     if (flag & SDL_SRCALPHA) {
  1682         /* According to the docs, value is ignored for alpha surfaces */
  1683         if (surface->format->Amask) {
  1684             value = 0xFF;
  1685         }
  1686         SDL_SetSurfaceAlphaMod(surface, value);
  1687         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
  1688     } else {
  1689         SDL_SetSurfaceAlphaMod(surface, 0xFF);
  1690         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
  1691     }
  1692     SDL_SetSurfaceRLE(surface, (flag & SDL_RLEACCEL));
  1693 
  1694     return 0;
  1695 }
  1696 
  1697 SDL12_Surface *
  1698 SDL_DisplayFormat(SDL12_Surface *surface12)
  1699 {
  1700     SDL12_PixelFormat *format;
  1701 
  1702     if (!PublicSurface) {
  1703         SDL20_SetError("No video mode has been set");
  1704         return NULL;
  1705     }
  1706     format = PublicSurface->format;
  1707 
  1708     /* Set the flags appropriate for copying to display surface */
  1709     return SDL_ConvertSurface(surface, format, SDL12_RLEACCEL);
  1710 }
  1711 
  1712 SDL12_Surface *
  1713 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  1714 {
  1715     SDL_PixelFormat *vf;
  1716     SDL_PixelFormat *format;
  1717     SDL_Surface *converted;
  1718     /* default to ARGB8888 */
  1719     Uint32 amask = 0xff000000;
  1720     Uint32 rmask = 0x00ff0000;
  1721     Uint32 gmask = 0x0000ff00;
  1722     Uint32 bmask = 0x000000ff;
  1723 
  1724     if (!PublicSurface) {
  1725         SDL_SetError("No video mode has been set");
  1726         return NULL;
  1727     }
  1728     vf = PublicSurface->format;
  1729 
  1730     switch (vf->BytesPerPixel) {
  1731     case 2:
  1732         /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
  1733            For anything else (like ARGB4444) it doesn't matter
  1734            since we have no special code for it anyway */
  1735         if ((vf->Rmask == 0x1f) &&
  1736             (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
  1737             rmask = 0xff;
  1738             bmask = 0xff0000;
  1739         }
  1740         break;
  1741 
  1742     case 3:
  1743     case 4:
  1744         /* Keep the video format, as long as the high 8 bits are
  1745            unused or alpha */
  1746         if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
  1747             rmask = 0xff;
  1748             bmask = 0xff0000;
  1749         }
  1750         break;
  1751 
  1752     default:
  1753         /* We have no other optimised formats right now. When/if a new
  1754            optimised alpha format is written, add the converter here */
  1755         break;
  1756     }
  1757     format = SDL_AllocFormat(SDL_MasksToPixelFormatEnum(32, rmask,
  1758                                                             gmask,
  1759                                                             bmask,
  1760                                                             amask));
  1761     if (!format) {
  1762         return NULL;
  1763     }
  1764     converted = SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
  1765     SDL_FreeFormat(format);
  1766     return converted;
  1767 }
  1768 
  1769 void
  1770 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
  1771 {
  1772     int i;
  1773 
  1774     if (screen == ShadowSurface) {
  1775         for (i = 0; i < numrects; ++i) {
  1776             SDL_BlitSurface(ShadowSurface, &rects[i], VideoSurface,
  1777                             &rects[i]);
  1778         }
  1779 
  1780         /* Fall through to video surface update */
  1781         screen = VideoSurface;
  1782     }
  1783     if (screen == VideoSurface) {
  1784         if (VideoViewport.x || VideoViewport.y) {
  1785             SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
  1786             SDL_Rect *stackrect;
  1787             const SDL_Rect *rect;
  1788             
  1789             /* Offset all the rectangles before updating */
  1790             for (i = 0; i < numrects; ++i) {
  1791                 rect = &rects[i];
  1792                 stackrect = &stackrects[i];
  1793                 stackrect->x = VideoViewport.x + rect->x;
  1794                 stackrect->y = VideoViewport.y + rect->y;
  1795                 stackrect->w = rect->w;
  1796                 stackrect->h = rect->h;
  1797             }
  1798             SDL_UpdateWindowSurfaceRects(VideoWindow20, stackrects, numrects);
  1799             SDL_stack_free(stackrects);
  1800         } else {
  1801             SDL_UpdateWindowSurfaceRects(VideoWindow20, rects, numrects);
  1802         }
  1803     }
  1804 }
  1805 
  1806 void
  1807 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  1808 {
  1809     if (screen) {
  1810         SDL_Rect rect;
  1811 
  1812         /* Fill the rectangle */
  1813         rect.x = (int) x;
  1814         rect.y = (int) y;
  1815         rect.w = (int) (w ? w : screen->w);
  1816         rect.h = (int) (h ? h : screen->h);
  1817         SDL_UpdateRects(screen, 1, &rect);
  1818     }
  1819 }
  1820 
  1821 int
  1822 SDL_Flip(SDL_Surface * screen)
  1823 {
  1824     SDL_UpdateRect(screen, 0, 0, 0, 0);
  1825     return 0;
  1826 }
  1827 
  1828 void
  1829 SDL_WM_SetCaption(const char *title, const char *icon)
  1830 {
  1831     if (WindowTitle) {
  1832         SDL20_free(WindowTitle);
  1833     }
  1834     if (WindowIconTitle) {
  1835         SDL20_free(WindowIconTitle);
  1836     }
  1837     WindowTitle = title ? SDL_strdup(title) : NULL;
  1838     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  1839     SDL_SetWindowTitle(VideoWindow20, WindowTitle);
  1840 }
  1841 
  1842 void
  1843 SDL_WM_GetCaption(const char **title, const char **icon)
  1844 {
  1845     if (title) {
  1846         *title = WindowTitle;
  1847     }
  1848     if (icon) {
  1849         *icon = WindowIconTitle;
  1850     }
  1851 }
  1852 
  1853 void
  1854 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
  1855 {
  1856     // !!! FIXME: free previous icon?
  1857     VideoIcon = icon;
  1858     ++VideoIcon->refcount;
  1859 }
  1860 
  1861 int
  1862 SDL_WM_IconifyWindow(void)
  1863 {
  1864     SDL_MinimizeWindow(VideoWindow20);
  1865     return 0;
  1866 }
  1867 
  1868 int
  1869 SDL_WM_ToggleFullScreen(SDL_Surface * surface)
  1870 {
  1871     int length;
  1872     void *pixels;
  1873     Uint8 *src, *dst;
  1874     int row;
  1875     int window_w;
  1876     int window_h;
  1877 
  1878     if (!PublicSurface) {
  1879         SDL_SetError("SDL_SetVideoMode() hasn't been called");
  1880         return 0;
  1881     }
  1882 
  1883     /* Copy the old bits out */
  1884     length = PublicSurface->w * PublicSurface->format->BytesPerPixel;
  1885     pixels = SDL20_malloc(PublicSurface->h * length);
  1886     if (pixels && PublicSurface->pixels) {
  1887         src = (Uint8*)PublicSurface->pixels;
  1888         dst = (Uint8*)pixels;
  1889         for (row = 0; row < PublicSurface->h; ++row) {
  1890             SDL_memcpy(dst, src, length);
  1891             src += PublicSurface->pitch;
  1892             dst += length;
  1893         }
  1894     }
  1895 
  1896     /* Do the physical mode switch */
  1897     if (SDL_GetWindowFlags(VideoWindow20) & SDL_WINDOW_FULLSCREEN) {
  1898         if (SDL_SetWindowFullscreen(VideoWindow20, 0) < 0) {
  1899             return 0;
  1900         }
  1901         PublicSurface->flags &= ~SDL_FULLSCREEN;
  1902     } else {
  1903         if (SDL_SetWindowFullscreen(VideoWindow20, 1) < 0) {
  1904             return 0;
  1905         }
  1906         PublicSurface->flags |= SDL_FULLSCREEN;
  1907     }
  1908 
  1909     /* Recreate the screen surface */
  1910     WindowSurface = SDL_GetWindowSurface(VideoWindow20);
  1911     if (!WindowSurface) {
  1912         /* We're totally hosed... */
  1913         return 0;
  1914     }
  1915 
  1916     /* Center the public surface in the window surface */
  1917     SDL_GetWindowSize(VideoWindow20, &window_w, &window_h);
  1918     VideoViewport.x = (window_w - VideoSurface->w)/2;
  1919     VideoViewport.y = (window_h - VideoSurface->h)/2;
  1920     VideoViewport.w = VideoSurface->w;
  1921     VideoViewport.h = VideoSurface->h;
  1922 
  1923     /* Do some shuffling behind the application's back if format changes */
  1924     if (VideoSurface->format->format != WindowSurface->format->format) {
  1925         if (ShadowSurface) {
  1926             if (ShadowSurface->format->format == WindowSurface->format->format) {
  1927                 /* Whee!  We don't need a shadow surface anymore! */
  1928                 VideoSurface->flags &= ~SDL_DONTFREE;
  1929                 SDL_FreeSurface(VideoSurface);
  1930                 SDL20_free(ShadowSurface->pixels);
  1931                 VideoSurface = ShadowSurface;
  1932                 VideoSurface->flags |= SDL_PREALLOC;
  1933                 ShadowSurface = NULL;
  1934             } else {
  1935                 /* No problem, just change the video surface format */
  1936                 SDL_FreeFormat(VideoSurface->format);
  1937                 VideoSurface->format = WindowSurface->format;
  1938                 VideoSurface->format->refcount++;
  1939                 SDL_InvalidateMap(ShadowSurface->map);
  1940             }
  1941         } else {
  1942             /* We can make the video surface the shadow surface */
  1943             ShadowSurface = VideoSurface;
  1944             ShadowSurface->pitch = SDL_CalculatePitch(ShadowSurface);
  1945             ShadowSurface->pixels = SDL20_malloc(ShadowSurface->h * ShadowSurface->pitch);
  1946             if (!ShadowSurface->pixels) {
  1947                 /* Uh oh, we're hosed */
  1948                 ShadowSurface = NULL;
  1949                 return 0;
  1950             }
  1951             ShadowSurface->flags &= ~SDL_PREALLOC;
  1952 
  1953             VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  1954             VideoSurface->flags = ShadowSurface->flags;
  1955             VideoSurface->flags |= SDL_PREALLOC;
  1956             SDL_FreeFormat(VideoSurface->format);
  1957             VideoSurface->format = WindowSurface->format;
  1958             VideoSurface->format->refcount++;
  1959             VideoSurface->w = ShadowSurface->w;
  1960             VideoSurface->h = ShadowSurface->h;
  1961         }
  1962     }
  1963 
  1964     /* Update the video surface */
  1965     VideoSurface->pitch = WindowSurface->pitch;
  1966     VideoSurface->pixels = (void *)((Uint8 *)WindowSurface->pixels +
  1967         VideoViewport.y * VideoSurface->pitch +
  1968         VideoViewport.x  * VideoSurface->format->BytesPerPixel);
  1969     SDL_SetClipRect(VideoSurface, NULL);
  1970 
  1971     /* Copy the old bits back */
  1972     if (pixels) {
  1973         src = (Uint8*)pixels;
  1974         dst = (Uint8*)PublicSurface->pixels;
  1975         for (row = 0; row < PublicSurface->h; ++row) {
  1976             SDL_memcpy(dst, src, length);
  1977             src += length;
  1978             dst += PublicSurface->pitch;
  1979         }
  1980         SDL_Flip(PublicSurface);
  1981         SDL20_free(pixels);
  1982     }
  1983 
  1984     /* We're done! */
  1985     return 1;
  1986 }
  1987 
  1988 typedef enum
  1989 {
  1990     SDL12_GRAB_QUERY = -1,
  1991     SDL12_GRAB_OFF = 0,
  1992     SDL12_GRAB_ON = 1
  1993 } SDL12_GrabMode;
  1994 
  1995 SDL12_GrabMode
  1996 SDL_WM_GrabInput(SDL12_GrabMode mode)
  1997 {
  1998     if (mode != SDL12_GRAB_QUERY) {
  1999         SDL_SetWindowGrab(VideoWindow20, (mode == SDL_GRAB_ON));
  2000     }
  2001     return SDL_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2002 }
  2003 
  2004 Uint8
  2005 SDL_GetMouseState(int *x, int *y)
  2006 {
  2007     const Uint32 state20 = SDL20_GetMouseState(x, y);
  2008     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  2009 
  2010     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  2011     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
  2012         retval |= (1<<5);
  2013     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
  2014         retval |= (1<<6);
  2015 
  2016     return retval;
  2017 }
  2018 
  2019 void
  2020 SDL_WarpMouse(Uint16 x, Uint16 y)
  2021 {
  2022     SDL_WarpMouseInWindow(VideoWindow20, x, y);
  2023 }
  2024 
  2025 Uint8
  2026 SDL_GetAppState(void)
  2027 {
  2028     Uint8 state = 0;
  2029     Uint32 flags = 0;
  2030 
  2031     flags = SDL_GetWindowFlags(VideoWindow20);
  2032     if ((flags & SDL_WINDOW_SHOWN) && !(flags & SDL_WINDOW_MINIMIZED)) {
  2033         state |= SDL_APPACTIVE;
  2034     }
  2035     if (flags & SDL_WINDOW_INPUT_FOCUS) {
  2036         state |= SDL_APPINPUTFOCUS;
  2037     }
  2038     if (flags & SDL_WINDOW_MOUSE_FOCUS) {
  2039         state |= SDL_APPMOUSEFOCUS;
  2040     }
  2041     return state;
  2042 }
  2043 
  2044 const SDL_version *
  2045 SDL_Linked_Version(void)
  2046 {
  2047     static SDL_version version;
  2048     SDL_VERSION(&version);
  2049     return &version;
  2050 }
  2051 
  2052 int
  2053 SDL_SetPalette(SDL_Surface * surface, int flags, const SDL_Color * colors,
  2054                int firstcolor, int ncolors)
  2055 {
  2056     return SDL_SetColors(surface, colors, firstcolor, ncolors);
  2057 }
  2058 
  2059 int
  2060 SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
  2061               int ncolors)
  2062 {
  2063     if (SDL_SetPaletteColors
  2064         (surface->format->palette, colors, firstcolor, ncolors) == 0) {
  2065         return 1;
  2066     } else {
  2067         return 0;
  2068     }
  2069 }
  2070 
  2071 int
  2072 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2073 {
  2074     return SDL_GetWindowWMInfo(VideoWindow20, info);
  2075 }
  2076 
  2077 #if 0
  2078 void
  2079 SDL_MoveCursor(int x, int y)
  2080 {
  2081     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2082 
  2083     /* Erase and update the current mouse position */
  2084     if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
  2085         /* Erase and redraw mouse cursor in new position */
  2086         SDL_LockCursor();
  2087         SDL_EraseCursor(VideoSurface);
  2088         SDL_cursor->area.x = (x - SDL_cursor->hot_x);
  2089         SDL_cursor->area.y = (y - SDL_cursor->hot_y);
  2090         SDL_DrawCursor(VideoSurface);
  2091         SDL_UnlockCursor();
  2092     } else if (_this->MoveWMCursor) {
  2093         _this->MoveWMCursor(_this, x, y);
  2094     }
  2095 }
  2096 
  2097 /* Keep track of the current cursor colors */
  2098 static int palette_changed = 1;
  2099 static Uint8 pixels8[2];
  2100 
  2101 void
  2102 SDL_CursorPaletteChanged(void)
  2103 {
  2104     palette_changed = 1;
  2105 }
  2106 
  2107 void
  2108 SDL_MouseRect(SDL_Rect * area)
  2109 {
  2110     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2111     int clip_diff;
  2112 
  2113     *area = SDL_cursor->area;
  2114     if (area->x < 0) {
  2115         area->w += area->x;
  2116         area->x = 0;
  2117     }
  2118     if (area->y < 0) {
  2119         area->h += area->y;
  2120         area->y = 0;
  2121     }
  2122     clip_diff = (area->x + area->w) - VideoSurface->w;
  2123     if (clip_diff > 0) {
  2124         area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
  2125     }
  2126     clip_diff = (area->y + area->h) - VideoSurface->h;
  2127     if (clip_diff > 0) {
  2128         area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
  2129     }
  2130 }
  2131 
  2132 static void
  2133 SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
  2134 {
  2135     const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
  2136     int i, w, h;
  2137     Uint8 *data, datab;
  2138     Uint8 *mask, maskb;
  2139 
  2140     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  2141     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  2142     switch (screen->format->BytesPerPixel) {
  2143 
  2144     case 1:
  2145         {
  2146             Uint8 *dst;
  2147             int dstskip;
  2148 
  2149             if (palette_changed) {
  2150                 pixels8[0] =
  2151                     (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  2152                 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  2153                 palette_changed = 0;
  2154             }
  2155             dst = (Uint8 *) screen->pixels +
  2156                 (SDL_cursor->area.y + area->y) * screen->pitch +
  2157                 SDL_cursor->area.x;
  2158             dstskip = screen->pitch - area->w;
  2159 
  2160             for (h = area->h; h; h--) {
  2161                 for (w = area->w / 8; w; w--) {
  2162                     maskb = *mask++;
  2163                     datab = *data++;
  2164                     for (i = 0; i < 8; ++i) {
  2165                         if (maskb & 0x80) {
  2166                             *dst = pixels8[datab >> 7];
  2167                         }
  2168                         maskb <<= 1;
  2169                         datab <<= 1;
  2170                         dst++;
  2171                     }
  2172                 }
  2173                 dst += dstskip;
  2174             }
  2175         }
  2176         break;
  2177 
  2178     case 2:
  2179         {
  2180             Uint16 *dst;
  2181             int dstskip;
  2182 
  2183             dst = (Uint16 *) screen->pixels +
  2184                 (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
  2185                 SDL_cursor->area.x;
  2186             dstskip = (screen->pitch / 2) - area->w;
  2187 
  2188             for (h = area->h; h; h--) {
  2189                 for (w = area->w / 8; w; w--) {
  2190                     maskb = *mask++;
  2191                     datab = *data++;
  2192                     for (i = 0; i < 8; ++i) {
  2193                         if (maskb & 0x80) {
  2194                             *dst = (Uint16) pixels[datab >> 7];
  2195                         }
  2196                         maskb <<= 1;
  2197                         datab <<= 1;
  2198                         dst++;
  2199                     }
  2200                 }
  2201                 dst += dstskip;
  2202             }
  2203         }
  2204         break;
  2205 
  2206     case 3:
  2207         {
  2208             Uint8 *dst;
  2209             int dstskip;
  2210 
  2211             dst = (Uint8 *) screen->pixels +
  2212                 (SDL_cursor->area.y + area->y) * screen->pitch +
  2213                 SDL_cursor->area.x * 3;
  2214             dstskip = screen->pitch - area->w * 3;
  2215 
  2216             for (h = area->h; h; h--) {
  2217                 for (w = area->w / 8; w; w--) {
  2218                     maskb = *mask++;
  2219                     datab = *data++;
  2220                     for (i = 0; i < 8; ++i) {
  2221                         if (maskb & 0x80) {
  2222                             SDL_memset(dst, pixels[datab >> 7], 3);
  2223                         }
  2224                         maskb <<= 1;
  2225                         datab <<= 1;
  2226                         dst += 3;
  2227                     }
  2228                 }
  2229                 dst += dstskip;
  2230             }
  2231         }
  2232         break;
  2233 
  2234     case 4:
  2235         {
  2236             Uint32 *dst;
  2237             int dstskip;
  2238 
  2239             dst = (Uint32 *) screen->pixels +
  2240                 (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
  2241                 SDL_cursor->area.x;
  2242             dstskip = (screen->pitch / 4) - area->w;
  2243 
  2244             for (h = area->h; h; h--) {
  2245                 for (w = area->w / 8; w; w--) {
  2246                     maskb = *mask++;
  2247                     datab = *data++;
  2248                     for (i = 0; i < 8; ++i) {
  2249                         if (maskb & 0x80) {
  2250                             *dst = pixels[datab >> 7];
  2251                         }
  2252                         maskb <<= 1;
  2253                         datab <<= 1;
  2254                         dst++;
  2255                     }
  2256                 }
  2257                 dst += dstskip;
  2258             }
  2259         }
  2260         break;
  2261     }
  2262 }
  2263 
  2264 static void
  2265 SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
  2266 {
  2267     const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
  2268     int h;
  2269     int x, minx, maxx;
  2270     Uint8 *data, datab = 0;
  2271     Uint8 *mask, maskb = 0;
  2272     Uint8 *dst;
  2273     int dstbpp, dstskip;
  2274 
  2275     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  2276     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  2277     dstbpp = screen->format->BytesPerPixel;
  2278     dst = (Uint8 *) screen->pixels +
  2279         (SDL_cursor->area.y + area->y) * screen->pitch +
  2280         SDL_cursor->area.x * dstbpp;
  2281     dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
  2282 
  2283     minx = area->x;
  2284     maxx = area->x + area->w;
  2285     if (screen->format->BytesPerPixel == 1) {
  2286         if (palette_changed) {
  2287             pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  2288             pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  2289             palette_changed = 0;
  2290         }
  2291         for (h = area->h; h; h--) {
  2292             for (x = 0; x < SDL_cursor->area.w; ++x) {
  2293                 if ((x % 8) == 0) {
  2294                     maskb = *mask++;
  2295                     datab = *data++;
  2296                 }
  2297                 if ((x >= minx) && (x < maxx)) {
  2298                     if (maskb & 0x80) {
  2299                         SDL_memset(dst, pixels8[datab >> 7], dstbpp);
  2300                     }
  2301                 }
  2302                 maskb <<= 1;
  2303                 datab <<= 1;
  2304                 dst += dstbpp;
  2305             }
  2306             dst += dstskip;
  2307         }
  2308     } else {
  2309         for (h = area->h; h; h--) {
  2310             for (x = 0; x < SDL_cursor->area.w; ++x) {
  2311                 if ((x % 8) == 0) {
  2312                     maskb = *mask++;
  2313                     datab = *data++;
  2314                 }
  2315                 if ((x >= minx) && (x < maxx)) {
  2316                     if (maskb & 0x80) {
  2317                         SDL_memset(dst, pixels[datab >> 7], dstbpp);
  2318                     }
  2319                 }
  2320                 maskb <<= 1;
  2321                 datab <<= 1;
  2322                 dst += dstbpp;
  2323             }
  2324             dst += dstskip;
  2325         }
  2326     }
  2327 }
  2328 
  2329 /* This handles the ugly work of converting the saved cursor background from
  2330    the pixel format of the shadow surface to that of the video surface.
  2331    This is only necessary when blitting from a shadow surface of a different
  2332    pixel format than the video surface, and using a software rendered cursor.
  2333 */
  2334 static void
  2335 SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
  2336 {
  2337     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2338     SDL_BlitInfo info;
  2339     SDL_loblit RunBlit;
  2340 
  2341     /* Make sure we can steal the blit mapping */
  2342     if (screen->map->dst != VideoSurface) {
  2343         return;
  2344     }
  2345 
  2346     /* Set up the blit information */
  2347     info.s_pixels = SDL_cursor->save[1];
  2348     info.s_width = w;
  2349     info.s_height = h;
  2350     info.s_skip = 0;
  2351     info.d_pixels = SDL_cursor->save[0];
  2352     info.d_width = w;
  2353     info.d_height = h;
  2354     info.d_skip = 0;
  2355     info.aux_data = screen->map->sw_data->aux_data;
  2356     info.src = screen->format;
  2357     info.table = screen->map->table;
  2358     info.dst = VideoSurface->format;
  2359     RunBlit = screen->map->sw_data->blit;
  2360 
  2361     /* Run the actual software blit */
  2362     RunBlit(&info);
  2363 }
  2364 
  2365 void
  2366 SDL_DrawCursorNoLock(SDL_Surface * screen)
  2367 {
  2368     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2369     SDL_Rect area;
  2370 
  2371     /* Get the mouse rectangle, clipped to the screen */
  2372     SDL_MouseRect(&area);
  2373     if ((area.w == 0) || (area.h == 0)) {
  2374         return;
  2375     }
  2376 
  2377     /* Copy mouse background */
  2378     {
  2379         int w, h, screenbpp;
  2380         Uint8 *src, *dst;
  2381 
  2382         /* Set up the copy pointers */
  2383         screenbpp = screen->format->BytesPerPixel;
  2384         if ((screen == VideoSurface) ||
  2385             FORMAT_EQUAL(screen->format, VideoSurface->format)) {
  2386             dst = SDL_cursor->save[0];
  2387         } else {
  2388             dst = SDL_cursor->save[1];
  2389         }
  2390         src = (Uint8 *) screen->pixels + area.y * screen->pitch +
  2391             area.x * screenbpp;
  2392 
  2393         /* Perform the copy */
  2394         w = area.w * screenbpp;
  2395         h = area.h;
  2396         while (h--) {
  2397             SDL_memcpy(dst, src, w);
  2398             dst += w;
  2399             src += screen->pitch;
  2400         }
  2401     }
  2402 
  2403     /* Draw the mouse cursor */
  2404     area.x -= SDL_cursor->area.x;
  2405     area.y -= SDL_cursor->area.y;
  2406     if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
  2407         SDL_DrawCursorFast(screen, &area);
  2408     } else {
  2409         SDL_DrawCursorSlow(screen, &area);
  2410     }
  2411 }
  2412 
  2413 void
  2414 SDL_DrawCursor(SDL_Surface * screen)
  2415 {
  2416     /* Lock the screen if necessary */
  2417     if (screen == NULL) {
  2418         return;
  2419     }
  2420     if (SDL_MUSTLOCK(screen)) {
  2421         if (SDL_LockSurface(screen) < 0) {
  2422             return;
  2423         }
  2424     }
  2425 
  2426     SDL_DrawCursorNoLock(screen);
  2427 
  2428     /* Unlock the screen and update if necessary */
  2429     if (SDL_MUSTLOCK(screen)) {
  2430         SDL_UnlockSurface(screen);
  2431     }
  2432     if (screen->flags & SDL_SCREEN_SURFACE) {
  2433         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2434         SDL_Window *window;
  2435         SDL_Rect area;
  2436 
  2437         window = SDL_GetWindowFromSurface(screen);
  2438         if (!window) {
  2439             return;
  2440         }
  2441 
  2442         SDL_MouseRect(&area);
  2443 
  2444         if (_this->UpdateWindowSurface) {
  2445             _this->UpdateWindowSurface(_this, window, 1, &area);
  2446         }
  2447     }
  2448 }
  2449 
  2450 void
  2451 SDL_EraseCursorNoLock(SDL_Surface * screen)
  2452 {
  2453     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2454     SDL_Window *window;
  2455     SDL_Rect area;
  2456 
  2457     /* Get the window associated with the surface */
  2458     window = SDL_GetWindowFromSurface(screen);
  2459     if (!window || !window->surface) {
  2460         return;
  2461     }
  2462 
  2463     /* Get the mouse rectangle, clipped to the screen */
  2464     SDL_MouseRect(&area);
  2465     if ((area.w == 0) || (area.h == 0)) {
  2466         return;
  2467     }
  2468 
  2469     /* Copy mouse background */
  2470     {
  2471         int w, h, screenbpp;
  2472         Uint8 *src, *dst;
  2473 
  2474         /* Set up the copy pointers */
  2475         screenbpp = screen->format->BytesPerPixel;
  2476         if ((screen->flags & SDL_SCREEN_SURFACE) ||
  2477             FORMAT_EQUAL(screen->format, window->surface->format)) {
  2478             src = SDL_cursor->save[0];
  2479         } else {
  2480             src = SDL_cursor->save[1];
  2481         }
  2482         dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
  2483             area.x * screenbpp;
  2484 
  2485         /* Perform the copy */
  2486         w = area.w * screenbpp;
  2487         h = area.h;
  2488         while (h--) {
  2489             SDL_memcpy(dst, src, w);
  2490             src += w;
  2491             dst += screen->pitch;
  2492         }
  2493 
  2494         /* Perform pixel conversion on cursor background */
  2495         if (src > SDL_cursor->save[1]) {
  2496             SDL_ConvertCursorSave(screen, area.w, area.h);
  2497         }
  2498     }
  2499 }
  2500 
  2501 void
  2502 SDL_EraseCursor(SDL_Surface * screen)
  2503 {
  2504     /* Lock the screen if necessary */
  2505     if (screen == NULL) {
  2506         return;
  2507     }
  2508     if (SDL_MUSTLOCK(screen)) {
  2509         if (SDL_LockSurface(screen) < 0) {
  2510             return;
  2511         }
  2512     }
  2513 
  2514     SDL_EraseCursorNoLock(screen);
  2515 
  2516     /* Unlock the screen and update if necessary */
  2517     if (SDL_MUSTLOCK(screen)) {
  2518         SDL_UnlockSurface(screen);
  2519     }
  2520     if (screen->flags & SDL_SCREEN_SURFACE) {
  2521         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2522         SDL_Window *window;
  2523         SDL_Rect area;
  2524 
  2525         window = SDL_GetWindowFromSurface(screen);
  2526         if (!window) {
  2527             return;
  2528         }
  2529 
  2530         SDL_MouseRect(&area);
  2531 
  2532         if (_this->UpdateWindowSurface) {
  2533             _this->UpdateWindowSurface(_this, window, 1, &area);
  2534         }
  2535     }
  2536 }
  2537 
  2538 /* Reset the cursor on video mode change
  2539    FIXME:  Keep track of all cursors, and reset them all.
  2540  */
  2541 void
  2542 SDL_ResetCursor(void)
  2543 {
  2544     int savelen;
  2545 
  2546     if (SDL_cursor) {
  2547         savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
  2548         SDL_cursor->area.x = 0;
  2549         SDL_cursor->area.y = 0;
  2550         SDL_memset(SDL_cursor->save[0], 0, savelen);
  2551     }
  2552 }
  2553 #endif
  2554 
  2555 struct private_yuvhwdata
  2556 {
  2557     SDL_SW_YUVTexture *texture;
  2558     SDL_Surface *display;
  2559     Uint32 display_format;
  2560 };
  2561 
  2562 SDL_Overlay *
  2563 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
  2564 {
  2565     SDL_Overlay *overlay;
  2566     Uint32 texture_format;
  2567     SDL_SW_YUVTexture *texture;
  2568 
  2569     if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
  2570         SDL_SetError("YUV overlays are not supported in OpenGL mode");
  2571         return NULL;
  2572     }
  2573 
  2574     if (display != PublicSurface) {
  2575         SDL_SetError("YUV display is only supported on the screen surface");
  2576         return NULL;
  2577     }
  2578 
  2579     switch (format) {
  2580     case SDL_YV12_OVERLAY:
  2581         texture_format = SDL_PIXELFORMAT_YV12;
  2582         break;
  2583     case SDL_IYUV_OVERLAY:
  2584         texture_format = SDL_PIXELFORMAT_IYUV;
  2585         break;
  2586     case SDL_YUY2_OVERLAY:
  2587         texture_format = SDL_PIXELFORMAT_YUY2;
  2588         break;
  2589     case SDL_UYVY_OVERLAY:
  2590         texture_format = SDL_PIXELFORMAT_UYVY;
  2591         break;
  2592     case SDL_YVYU_OVERLAY:
  2593         texture_format = SDL_PIXELFORMAT_YVYU;
  2594         break;
  2595     default:
  2596         SDL_SetError("Unknown YUV format");
  2597         return NULL;
  2598     }
  2599 
  2600     overlay = (SDL_Overlay *) SDL20_malloc(sizeof(*overlay));
  2601     if (!overlay) {
  2602         SDL20_OutOfMemory();
  2603         return NULL;
  2604     }
  2605     SDL_zerop(overlay);
  2606 
  2607     overlay->hwdata =
  2608         (struct private_yuvhwdata *) SDL20_malloc(sizeof(*overlay->hwdata));
  2609     if (!overlay->hwdata) {
  2610         SDL20_free(overlay);
  2611         SDL20_OutOfMemory();
  2612         return NULL;
  2613     }
  2614 
  2615     texture = SDL_SW_CreateYUVTexture(texture_format, w, h);
  2616     if (!texture) {
  2617         SDL20_free(overlay->hwdata);
  2618         SDL20_free(overlay);
  2619         return NULL;
  2620     }
  2621     overlay->hwdata->texture = texture;
  2622     overlay->hwdata->display = NULL;
  2623     overlay->hwdata->display_format = SDL_PIXELFORMAT_UNKNOWN;
  2624 
  2625     overlay->format = format;
  2626     overlay->w = w;
  2627     overlay->h = h;
  2628     if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
  2629         overlay->planes = 3;
  2630     } else {
  2631         overlay->planes = 1;
  2632     }
  2633     overlay->pitches = texture->pitches;
  2634     overlay->pixels = texture->planes;
  2635 
  2636     return overlay;
  2637 }
  2638 
  2639 int
  2640 SDL_LockYUVOverlay(SDL_Overlay * overlay)
  2641 {
  2642     SDL_Rect rect;
  2643     void *pixels;
  2644     int pitch;
  2645 
  2646     if (!overlay) {
  2647         SDL_SetError("Passed a NULL overlay");
  2648         return -1;
  2649     }
  2650 
  2651     rect.x = 0;
  2652     rect.y = 0;
  2653     rect.w = overlay->w;
  2654     rect.h = overlay->h;
  2655 
  2656     if (SDL_SW_LockYUVTexture(overlay->hwdata->texture, &rect, &pixels, &pitch) < 0) {
  2657         return -1;
  2658     }
  2659 
  2660     overlay->pixels[0] = (Uint8 *) pixels;
  2661     overlay->pitches[0] = pitch;
  2662     switch (overlay->format) {
  2663     case SDL_YV12_OVERLAY:
  2664     case SDL_IYUV_OVERLAY:
  2665         overlay->pitches[1] = pitch / 2;
  2666         overlay->pitches[2] = pitch / 2;
  2667         overlay->pixels[1] =
  2668             overlay->pixels[0] + overlay->pitches[0] * overlay->h;
  2669         overlay->pixels[2] =
  2670             overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
  2671         break;
  2672     case SDL_YUY2_OVERLAY:
  2673     case SDL_UYVY_OVERLAY:
  2674     case SDL_YVYU_OVERLAY:
  2675         break;
  2676     }
  2677     return 0;
  2678 }
  2679 
  2680 void
  2681 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
  2682 {
  2683     if (!overlay) {
  2684         return;
  2685     }
  2686 
  2687     SDL_SW_UnlockYUVTexture(overlay->hwdata->texture);
  2688 }
  2689 
  2690 int
  2691 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
  2692 {
  2693     SDL_Surface *display;
  2694     SDL_Rect src_rect;
  2695     SDL_Rect dst_rect;
  2696     void *pixels;
  2697 
  2698     if (!overlay || !dstrect) {
  2699         SDL_SetError("Passed a NULL overlay or dstrect");
  2700         return -1;
  2701     }
  2702 
  2703     display = overlay->hwdata->display;
  2704     if (display != VideoSurface) {
  2705         overlay->hwdata->display = display = VideoSurface;
  2706         overlay->hwdata->display_format = SDL_MasksToPixelFormatEnum(
  2707                                                 display->format->BitsPerPixel,
  2708                                                 display->format->Rmask,
  2709                                                 display->format->Gmask,
  2710                                                 display->format->Bmask,
  2711                                                 display->format->Amask);
  2712     }
  2713 
  2714     src_rect.x = 0;
  2715     src_rect.y = 0;
  2716     src_rect.w = overlay->w;
  2717     src_rect.h = overlay->h;
  2718 
  2719     if (!SDL_IntersectRect(&display->clip_rect, dstrect, &dst_rect)) {
  2720         return 0;
  2721     }
  2722      
  2723     pixels = (void *)((Uint8 *)display->pixels +
  2724                         dst_rect.y * display->pitch +
  2725                         dst_rect.x * display->format->BytesPerPixel);
  2726 
  2727     if (SDL_SW_CopyYUVToRGB(overlay->hwdata->texture, &src_rect,
  2728                             overlay->hwdata->display_format,
  2729                             dst_rect.w, dst_rect.h,
  2730                             pixels, display->pitch) < 0) {
  2731         return -1;
  2732     }
  2733     SDL_UpdateWindowSurface(VideoWindow20);
  2734     return 0;
  2735 }
  2736 
  2737 void
  2738 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
  2739 {
  2740     if (!overlay) {
  2741         return;
  2742     }
  2743     if (overlay->hwdata) {
  2744         if (overlay->hwdata->texture) {
  2745             SDL_SW_DestroyYUVTexture(overlay->hwdata->texture);
  2746         }
  2747         SDL20_free(overlay->hwdata);
  2748     }
  2749     SDL20_free(overlay);
  2750 }
  2751 
  2752 int
  2753 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2754 {
  2755     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2756     {
  2757         SDL_SetError("Unknown GL attribute");
  2758         return -1;
  2759     }
  2760 
  2761     /* swap control was moved out of this API, everything else lines up. */
  2762     if (attr == SDL12_GL_SWAP_CONTROL)
  2763     {
  2764         SwapInterval = value;
  2765         return 0;
  2766     }
  2767 
  2768     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2769 }
  2770 
  2771 int
  2772 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2773 {
  2774     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2775     {
  2776         SDL_SetError("Unknown GL attribute");
  2777         return -1;
  2778     }
  2779 
  2780     /* swap control was moved out of this API, everything else lines up. */
  2781     if (attr == SDL12_GL_SWAP_CONTROL)
  2782     {
  2783         *value = SDL20_GL_GetSwapInterval();
  2784         return 0;
  2785     }
  2786 
  2787     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2788 }
  2789 
  2790 
  2791 void
  2792 SDL_GL_SwapBuffers(void)
  2793 {
  2794     SDL_GL_SwapWindow(VideoWindow20);
  2795 }
  2796 
  2797 int
  2798 SDL_SetGamma(float red, float green, float blue)
  2799 {
  2800     Uint16 red_ramp[256];
  2801     Uint16 green_ramp[256];
  2802     Uint16 blue_ramp[256];
  2803 
  2804     SDL_CalculateGammaRamp(red, red_ramp);
  2805     if (green == red) {
  2806         SDL_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2807     } else {
  2808         SDL_CalculateGammaRamp(green, green_ramp);
  2809     }
  2810     if (blue == red) {
  2811         SDL_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2812     } else {
  2813         SDL_CalculateGammaRamp(blue, blue_ramp);
  2814     }
  2815     return SDL_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2816 }
  2817 
  2818 int
  2819 SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, const Uint16 * blue)
  2820 {
  2821     return SDL_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2822 }
  2823 
  2824 int
  2825 SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue)
  2826 {
  2827     return SDL_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2828 }
  2829 
  2830 int
  2831 SDL_EnableKeyRepeat(int delay, int interval)
  2832 {
  2833     return 0;
  2834 }
  2835 
  2836 void
  2837 SDL_GetKeyRepeat(int *delay, int *interval)
  2838 {
  2839     if (delay) {
  2840         *delay = SDL_DEFAULT_REPEAT_DELAY;
  2841     }
  2842     if (interval) {
  2843         *interval = SDL_DEFAULT_REPEAT_INTERVAL;
  2844     }
  2845 }
  2846 
  2847 
  2848 
  2849 
  2850 int
  2851 SDL_EnableUNICODE(int enable)
  2852 {
  2853     int previous = EnabledUnicode;
  2854 
  2855     switch (enable) {
  2856     case 1:
  2857         EnabledUnicode = 1;
  2858         SDL_StartTextInput();
  2859         break;
  2860     case 0:
  2861         EnabledUnicode = 0;
  2862         SDL_StopTextInput();
  2863         break;
  2864     }
  2865     return previous;
  2866 }
  2867 
  2868 static Uint32
  2869 SDL_SetTimerCallback(Uint32 interval, void* param)
  2870 {
  2871     return ((SDL12_TimerCallback)param)(interval);
  2872 }
  2873 
  2874 int
  2875 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  2876 {
  2877     static SDL_TimerID compat_timer;
  2878 
  2879     if (compat_timer) {
  2880         SDL20_RemoveTimer(compat_timer);
  2881         compat_timer = 0;
  2882     }
  2883 
  2884     if (interval && callback) {
  2885         compat_timer = SDL20_AddTimer(interval, SDL_SetTimerCallback, callback);
  2886         if (!compat_timer) {
  2887             return -1;
  2888         }
  2889     }
  2890     return 0;
  2891 }
  2892 
  2893 int
  2894 SDL_putenv(const char *_var)
  2895 {
  2896     char *ptr = NULL;
  2897     char *var = SDL_strdup(_var);
  2898     if (var == NULL) {
  2899         return -1;  /* we don't set errno. */
  2900     }
  2901 
  2902     ptr = SDL_strchr(var, '=');
  2903     if (ptr == NULL) {
  2904         SDL20_free(var);
  2905         return -1;
  2906     }
  2907 
  2908     *ptr = '\0';  /* split the string into name and value. */
  2909     SDL_setenv(var, ptr + 1, 1);
  2910     SDL20_free(var);
  2911     return 0;
  2912 }
  2913 
  2914 
  2915 
  2916 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2917 
  2918 typedef void *SDL12_CD;  /* close enough.  :) */
  2919 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2920 
  2921 static int
  2922 CDUnsupported(void)
  2923 {
  2924     SDL_SetError("CD interface is unsupported");
  2925     return -1;
  2926 }
  2927 
  2928 int
  2929 SDL_CDNumDrives(void)
  2930 {
  2931     return 0;  /* !!! FIXME: should return -1 without SDL_INIT_CDROM */
  2932 }
  2933 
  2934 const char *SDL_CDName(int drive) { CDUnsupported(); return NULL; }
  2935 SDL12_CD * SDL_CDOpen(int drive) { CDUnsupported(); return NULL; }
  2936 SDL12_CDstatus SDL_CDStatus(SDL12_CD *cdrom) { return CDUnsupported(); }
  2937 int SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return CDUnsupported(); }
  2938 int SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return CDUnsupported(); }
  2939 int SDL_CDPause(SDL12_CD *cdrom) { return CDUnsupported(); }
  2940 int SDL_CDResume(SDL12_CD *cdrom) { return CDUnsupported(); }
  2941 int SDL_CDStop(SDL12_CD *cdrom) { return CDUnsupported(); }
  2942 int SDL_CDEject(SDL12_CD *cdrom) { return CDUnsupported(); }
  2943 void SDL_CDClose(SDL12_CD *cdrom) {}
  2944 
  2945 
  2946 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2947 SDL_Thread *
  2948 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2949 {
  2950     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2951 }
  2952 #else
  2953 SDL_Thread *
  2954 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2955 {
  2956     return SDL20_CreateThread(fn, NULL, data);
  2957 }
  2958 #endif
  2959 
  2960 
  2961 /* !!! FIXME: Removed from 2.0; do nothing. We can't even report failure. */
  2962 void SDL_KillThread(SDL_Thread *thread) {}
  2963 
  2964 /* This changed from an opaque pointer to an int in 2.0. */
  2965 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2966 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2967 
  2968 
  2969 SDL12_TimerID
  2970 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  2971 {
  2972     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2973 }
  2974 
  2975 SDL_bool
  2976 SDL_RemoveTimer(SDL12_TimerID id)
  2977 {
  2978     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2979 }
  2980 
  2981 
  2982 typedef struct SDL12_RWops {
  2983     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  2984     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  2985     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  2986     int (SDLCALL *close)(struct SDL12_RWops *context);
  2987     Uint32 type;
  2988     void *padding[8];
  2989     SDL_RWops *rwops20;
  2990 } SDL12_RWops;
  2991 
  2992 
  2993 SDL12_RWops *
  2994 SDL_AllocRW(void)
  2995 {
  2996     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  2997     if (!rwops)
  2998         SDL20_OutOfMemory();
  2999     return rwops;
  3000 }
  3001 
  3002 void
  3003 SDL_FreeRW(SDL12_RWops *rwops12)
  3004 {
  3005     SDL20_free(rwops12);
  3006 }
  3007 
  3008 static int SDLCALL
  3009 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  3010 {
  3011     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  3012 }
  3013 
  3014 static int SDLCALL
  3015 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  3016 {
  3017     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  3018 }
  3019 
  3020 static int SDLCALL
  3021 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  3022 {
  3023     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  3024 }
  3025 
  3026 static int SDLCALL
  3027 RWops20to12_close(struct SDL12_RWops *rwops12)
  3028 {
  3029     int rc = 0;
  3030     if (rwops12)
  3031     {
  3032         rc = rwops12->rwops20->close(rwops12->rwops20);
  3033         if (rc == 0)
  3034             SDL_FreeRW(rwops12);
  3035     }
  3036     return rc;
  3037 }
  3038 
  3039 static SDL12_RWops *
  3040 RWops20to12(SDL_RWops *rwops20)
  3041 {
  3042     SDL12_RWops *rwops12;
  3043 
  3044     if (!rwops20)
  3045         return NULL;
  3046 
  3047     rwops12 = SDL_AllocRW();
  3048     if (!rwops12)
  3049         return NULL;
  3050 
  3051     SDL_zerop(rwops12);
  3052     rwops12->type = rwops20->type;
  3053     rwops12->rwops20 = rwops20;
  3054     rwops12->seek = RWops20to12_seek;
  3055     rwops12->read = RWops20to12_read;
  3056     rwops12->write = RWops20to12_write;
  3057     rwops12->close = RWops20to12_close;
  3058 
  3059     return rwops12;
  3060 }
  3061 
  3062 SDL12_RWops *
  3063 SDL_RWFromFile(const char *file, const char *mode)
  3064 {
  3065     return RWops20to12(SDL20_RWFromFile(file, mode));
  3066 }
  3067 
  3068 SDL12_RWops *
  3069 SDL_RWFromFP(FILE *io, int autoclose)
  3070 {
  3071     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  3072 }
  3073 
  3074 SDL12_RWops *
  3075 SDL_RWFromMem(void *mem, int size)
  3076 {
  3077     return RWops20to12(SDL20_RWFromMem(mem, size));
  3078 }
  3079 
  3080 SDL12_RWops *
  3081 SDL_RWFromConstMem(const void *mem, int size)
  3082 {
  3083     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  3084 }
  3085 
  3086 #define READ_AND_BYTESWAP(endian, bits) \
  3087     Uint##bits SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  3088         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  3089         return SDL_Swap##endian##bits(val); \
  3090     }
  3091 
  3092 READ_AND_BYTESWAP(LE,16)
  3093 READ_AND_BYTESWAP(BE,16)
  3094 READ_AND_BYTESWAP(LE,32)
  3095 READ_AND_BYTESWAP(BE,32)
  3096 READ_AND_BYTESWAP(LE,64)
  3097 READ_AND_BYTESWAP(BE,64)
  3098 #undef READ_AND_BYTESWAP
  3099 
  3100 #define BYTESWAP_AND_WRITE(endian, bits) \
  3101     int SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  3102         val = SDL_Swap##endian##bits(val); \
  3103         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  3104     }
  3105 BYTESWAP_AND_WRITE(LE,16)
  3106 BYTESWAP_AND_WRITE(BE,16)
  3107 BYTESWAP_AND_WRITE(LE,32)
  3108 BYTESWAP_AND_WRITE(BE,32)
  3109 BYTESWAP_AND_WRITE(LE,64)
  3110 BYTESWAP_AND_WRITE(BE,64)
  3111 #undef BYTESWAP_AND_WRITE
  3112 
  3113 /* Things that _should_ be binary compatible pass right through... */
  3114 #define SDL20_SYM(rc,fn,params,args,ret)
  3115 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
  3116     rc SDL_##fn params { ret SDL20_##fn args; }
  3117 #include "SDL20_syms.h"
  3118 #undef SDL20_SYM_PASSTHROUGH
  3119 #undef SDL20_SYM
  3120 
  3121 
  3122 static Sint64 SDLCALL
  3123 RWops12to20_size(struct SDL_RWops *rwops20)
  3124 {
  3125     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3126     int size = rwops20->hidden.unknown.data2;
  3127     int pos;
  3128 
  3129     if (size != -1)
  3130         return size;
  3131 
  3132     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  3133     if (pos == -1)
  3134         return -1;
  3135 
  3136     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  3137     if (size == -1)
  3138         return -1;
  3139 
  3140     rwops12->seek(rwops12, pos, SEEK_SET);  /* !!! FIXME: and if this fails? */
  3141     rwops20->hidden.unknown.data2 = size;
  3142     return size;
  3143 }
  3144 
  3145 static Sint64
  3146 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  3147 {
  3148     /* !!! FIXME: fail if (offset) is too big */
  3149     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3150     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  3151 }
  3152 
  3153 static size_t SDLCALL
  3154 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  3155 {
  3156     /* !!! FIXME: fail if (size) or (maxnum) is too big */
  3157     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3158     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  3159 }
  3160 
  3161 static size_t SDLCALL
  3162 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  3163 {
  3164     /* !!! FIXME: fail if (size) or (maxnum) is too big */
  3165     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3166     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  3167 }
  3168 
  3169 static int SDLCALL
  3170 RWops12to20_close(struct SDL_RWops *rwops20)
  3171 {
  3172     int rc = 0;
  3173     if (rwops20)
  3174     {
  3175         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3176         rc = rwops12->close(rwops12);
  3177         if (rc == 0)
  3178             SDL20_FreeRW(rwops20);
  3179     }
  3180     return rc;
  3181 }
  3182 
  3183 static SDL_RWops *
  3184 RWops12to20(SDL12_RWops *rwops12)
  3185 {
  3186     SDL_RWops *rwops20;
  3187 
  3188     if (!rwops12)
  3189         return NULL;
  3190 
  3191     rwops20 = SDL20_AllocRW();
  3192     if (!rwops20)
  3193         return NULL;
  3194 
  3195     SDL_zerop(rwops20);
  3196     rwops20->type = rwops12->type;
  3197     rwops20->hidden.unknown.data1 = rwops12;
  3198     rwops20->hidden.unknown.data2 = -1;  /* cached size of stream */
  3199     rwops20->size = RWops12to20_size;
  3200     rwops20->seek = RWops12to20_seek;
  3201     rwops20->read = RWops12to20_read;
  3202     rwops20->write = RWops12to20_write;
  3203     rwops20->close = RWops12to20_close;
  3204     return rwops20;
  3205 }
  3206 
  3207 SDL12_Surface *
  3208 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  3209 {
  3210     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3211     SDL_Surface *retval = SDL20_LoadBMP_RW(rwops20, freerwops12);
  3212     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3213         SDL20_FreeRW(rwops20);
  3214     // !!! FIXME: wrap surface.
  3215     return retval;
  3216 }
  3217 
  3218 int
  3219 SDL_SaveBMP_RW(SDL12_Surface *surface, SDL12_RWops *rwops12, int freerwops12)
  3220 {
  3221     // !!! FIXME: wrap surface.
  3222     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3223     const int retval = SDL20_SaveBMP_RW(surface, rwops20, freerwops12);
  3224     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3225         SDL20_FreeRW(rwops20);
  3226     return retval;
  3227 }
  3228 
  3229 SDL_AudioSpec *
  3230 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  3231                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  3232 {
  3233     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3234     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  3235     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3236         SDL20_FreeRW(rwops20);
  3237     return retval;
  3238 }
  3239 
  3240 /* vi: set ts=4 sw=4 expandtab: */