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