src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 07 Mar 2013 00:59:19 -0500
changeset 10 e6176c053187
parent 9 408821d72ab2
child 11 ed314328463b
permissions -rw-r--r--
sdl12-compat: Filled in some timer and rwops APIs.
     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 "SDL.h"
    25 
    26 #if !SDL_VERSION_ATLEAST(2,0,0)
    27 #error You need to compile against SDL 2.0 headers.
    28 #endif
    29 
    30 #include "SDL_syswm.h"
    31 
    32 //#include "video/SDL_sysvideo.h"
    33 //#include "video/SDL_pixels_c.h"
    34 //#include "render/SDL_yuv_sw_c.h"
    35 
    36 // !!! IMPLEMENT_ME SDL_AudioInit
    37 // !!! IMPLEMENT_ME SDL_AudioQuit
    38 // !!! IMPLEMENT_ME SDL_ConvertSurface
    39 // !!! IMPLEMENT_ME SDL_CreateCursor
    40 // !!! IMPLEMENT_ME SDL_CreateRGBSurface
    41 // !!! IMPLEMENT_ME SDL_CreateRGBSurfaceFrom
    42 // !!! IMPLEMENT_ME SDL_CreateThread
    43 // !!! IMPLEMENT_ME SDL_Error
    44 // !!! IMPLEMENT_ME SDL_EventState
    45 // !!! IMPLEMENT_ME SDL_FillRect
    46 // !!! IMPLEMENT_ME SDL_FreeCursor
    47 // !!! IMPLEMENT_ME SDL_FreeSurface
    48 // !!! IMPLEMENT_ME SDL_GL_GetAttribute
    49 // !!! IMPLEMENT_ME SDL_GL_GetProcAddress
    50 // !!! IMPLEMENT_ME SDL_GL_LoadLibrary
    51 // !!! IMPLEMENT_ME SDL_GL_Lock
    52 // !!! IMPLEMENT_ME SDL_GL_SetAttribute
    53 // !!! IMPLEMENT_ME SDL_GL_Unlock
    54 // !!! IMPLEMENT_ME SDL_GL_UpdateRects
    55 // !!! IMPLEMENT_ME SDL_GetClipRect
    56 // !!! IMPLEMENT_ME SDL_GetCursor
    57 // !!! IMPLEMENT_ME SDL_GetEventFilter
    58 // !!! IMPLEMENT_ME SDL_GetKeyName
    59 // !!! IMPLEMENT_ME SDL_GetKeyState
    60 // !!! IMPLEMENT_ME SDL_GetModState
    61 // !!! IMPLEMENT_ME SDL_GetMouseState
    62 // !!! IMPLEMENT_ME SDL_GetRGB
    63 // !!! IMPLEMENT_ME SDL_GetRGBA
    64 // !!! IMPLEMENT_ME SDL_GetRelativeMouseState
    65 // !!! IMPLEMENT_ME SDL_InitSubSystem
    66 // !!! IMPLEMENT_ME SDL_LoadBMP_RW
    67 // !!! IMPLEMENT_ME SDL_LoadWAV_RW
    68 // !!! IMPLEMENT_ME SDL_LockSurface
    69 // !!! IMPLEMENT_ME SDL_LowerBlit
    70 // !!! IMPLEMENT_ME SDL_MapRGB
    71 // !!! IMPLEMENT_ME SDL_MapRGBA
    72 // !!! IMPLEMENT_ME SDL_PeepEvents
    73 // !!! IMPLEMENT_ME SDL_PollEvent
    74 // !!! IMPLEMENT_ME SDL_PumpEvents
    75 // !!! IMPLEMENT_ME SDL_PushEvent
    76 // !!! IMPLEMENT_ME SDL_QuitSubSystem
    77 // !!! IMPLEMENT_ME SDL_SaveBMP_RW
    78 // !!! IMPLEMENT_ME SDL_SetClipRect
    79 // !!! IMPLEMENT_ME SDL_SetColorKey
    80 // !!! IMPLEMENT_ME SDL_SetCursor
    81 // !!! IMPLEMENT_ME SDL_SetError
    82 // !!! IMPLEMENT_ME SDL_SetEventFilter
    83 // !!! IMPLEMENT_ME SDL_SetModState
    84 // !!! IMPLEMENT_ME SDL_ShowCursor
    85 // !!! IMPLEMENT_ME SDL_SoftStretch
    86 // !!! IMPLEMENT_ME SDL_UnlockSurface
    87 // !!! IMPLEMENT_ME SDL_UpperBlit
    88 // !!! IMPLEMENT_ME SDL_VideoInit
    89 // !!! IMPLEMENT_ME SDL_VideoQuit
    90 // !!! IMPLEMENT_ME SDL_WaitEvent
    91 // !!! IMPLEMENT_ME SDL_WasInit
    92 // !!! IMPLEMENT_ME SDL_iconv
    93 // !!! IMPLEMENT_ME SDL_iconv_string
    94 // !!! IMPLEMENT_ME SDL_lltoa
    95 // !!! IMPLEMENT_ME SDL_ltoa
    96 // !!! IMPLEMENT_ME SDL_revcpy
    97 // !!! IMPLEMENT_ME SDL_strlcat
    98 // !!! IMPLEMENT_ME SDL_strlcpy
    99 // !!! IMPLEMENT_ME SDL_strlwr
   100 // !!! IMPLEMENT_ME SDL_strrev
   101 // !!! IMPLEMENT_ME SDL_strupr
   102 // !!! IMPLEMENT_ME SDL_ulltoa
   103 // !!! IMPLEMENT_ME SDL_ultoa
   104 // !!! IMPLEMENT_ME X11_KeyToUnicode
   105 
   106 
   107 #define SDL20_SYM(rc,fn,params,args,ret) \
   108     typedef rc (*SDL20_##fn##_t) params; \
   109     static SDL20_##fn##_t SDL20_##fn = NULL;
   110 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
   111     SDL20_SYM(rc,fn,params,args,ret)
   112 #include "SDL20_syms.h"
   113 #undef SDL20_SYM_PASSTHROUGH
   114 #undef SDL20_SYM
   115 
   116 
   117 
   118 
   119 #define SDL12_INIT_TIMER       0x00000001
   120 #define SDL12_INIT_AUDIO       0x00000010
   121 #define SDL12_INIT_VIDEO       0x00000020
   122 #define SDL12_INIT_CDROM       0x00000100
   123 #define SDL12_INIT_JOYSTICK    0x00000200
   124 #define SDL12_INIT_NOPARACHUTE 0x00100000
   125 #define SDL12_INIT_EVENTTHREAD 0x01000000
   126 #define SDL12_INIT_EVERYTHING  0x0000FFFF
   127 
   128 typedef struct
   129 {
   130 	Uint32 hw_available :1;	/**< Flag: Can you create hardware surfaces? */
   131 	Uint32 wm_available :1;	/**< Flag: Can you talk to a window manager? */
   132 	Uint32 UnusedBits1  :6;
   133 	Uint32 UnusedBits2  :1;
   134 	Uint32 blit_hw      :1;	/**< Flag: Accelerated blits HW --> HW */
   135 	Uint32 blit_hw_CC   :1;	/**< Flag: Accelerated blits with Colorkey */
   136 	Uint32 blit_hw_A    :1;	/**< Flag: Accelerated blits with Alpha */
   137 	Uint32 blit_sw      :1;	/**< Flag: Accelerated blits SW --> HW */
   138 	Uint32 blit_sw_CC   :1;	/**< Flag: Accelerated blits with Colorkey */
   139 	Uint32 blit_sw_A    :1;	/**< Flag: Accelerated blits with Alpha */
   140 	Uint32 blit_fill    :1;	/**< Flag: Accelerated color fill */
   141 	Uint32 UnusedBits3  :16;
   142 	Uint32 video_mem;	/**< The total amount of video memory (in K) */
   143 	SDL_PixelFormat *vfmt;	/**< Value: The format of the video surface */
   144 	int    current_w;	/**< Value: The current video mode width */
   145 	int    current_h;	/**< Value: The current video mode height */
   146 } SDL12_VideoInfo;
   147 
   148 typedef struct SDL12_Palette {
   149 	int       ncolors;
   150 	SDL_Color *colors;
   151 } SDL12_Palette;
   152 
   153 /** Everything in the pixel format structure is read-only */
   154 typedef struct SDL12_PixelFormat {
   155 	SDL12_Palette *palette;
   156 	Uint8  BitsPerPixel;
   157 	Uint8  BytesPerPixel;
   158 	Uint8  Rloss;
   159 	Uint8  Gloss;
   160 	Uint8  Bloss;
   161 	Uint8  Aloss;
   162 	Uint8  Rshift;
   163 	Uint8  Gshift;
   164 	Uint8  Bshift;
   165 	Uint8  Ashift;
   166 	Uint32 Rmask;
   167 	Uint32 Gmask;
   168 	Uint32 Bmask;
   169 	Uint32 Amask;
   170 
   171 	/** RGB color key information */
   172 	Uint32 colorkey;
   173 	/** Alpha value information (per-surface alpha) */
   174 	Uint8  alpha;
   175 } SDL12_PixelFormat;
   176 
   177 #define SDL12_SWSURFACE	0x00000000	/**< Surface is in system memory */
   178 #define SDL12_HWSURFACE	0x00000001	/**< Surface is in video memory */
   179 #define SDL12_ASYNCBLIT	0x00000004	/**< Use asynchronous blits if possible */
   180 #define SDL12_ANYFORMAT	0x10000000	/**< Allow any video depth/pixel-format */
   181 #define SDL12_HWPALETTE	0x20000000	/**< Surface has exclusive palette */
   182 #define SDL12_DOUBLEBUF	0x40000000	/**< Set up double-buffered video mode */
   183 #define SDL12_FULLSCREEN	0x80000000	/**< Surface is a full screen display */
   184 #define SDL12_OPENGL      0x00000002      /**< Create an OpenGL rendering context */
   185 #define SDL12_OPENGLBLIT	0x0000000A	/**< Create an OpenGL rendering context and use it for blitting */
   186 #define SDL12_RESIZABLE	0x00000010	/**< This video mode may be resized */
   187 #define SDL12_NOFRAME	0x00000020	/**< No window caption or edge frame */
   188 
   189 #define SDL12_HWACCEL	0x00000100	/**< Blit uses hardware acceleration */
   190 #define SDL12_SRCCOLORKEY	0x00001000	/**< Blit uses a source color key */
   191 #define SDL12_RLEACCELOK	0x00002000	/**< Private flag */
   192 #define SDL12_RLEACCEL	0x00004000	/**< Surface is RLE encoded */
   193 #define SDL12_SRCALPHA	0x00010000	/**< Blit uses source alpha blending */
   194 #define SDL12_PREALLOC	0x01000000	/**< Surface uses preallocated memory */
   195 
   196 
   197 static SDL_Window *SDL_VideoWindow = NULL;
   198 static SDL_Surface *SDL_WindowSurface = NULL;
   199 static SDL_Surface *SDL_VideoSurface = NULL;
   200 static SDL_Surface *SDL_ShadowSurface = NULL;
   201 static SDL_Surface *SDL_PublicSurface = NULL;
   202 static SDL_GLContext *SDL_VideoContext = NULL;
   203 static Uint32 SDL_VideoFlags = 0;
   204 static SDL_Rect SDL_VideoViewport;
   205 static char *wm_title = NULL;
   206 static char *wm_icon_caption = NULL;
   207 static SDL_Surface *SDL_VideoIcon;
   208 static int SDL_enabled_UNICODE = 0;
   209 static int SDL_VideoDisplayIndex = 0;
   210 
   211 /* Obviously we can't use SDL_LoadObject() to load SDL2.  :)  */
   212 #if defined(_WINDOWS)
   213     #define SDL20_LIBNAME "SDL2.dll"
   214     static HANDLE Loaded_SDL20 = NULL;
   215     #define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
   216     #define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
   217     #define CloseSDL20Library() { { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   218 #elif defined(unix)
   219     #ifdef __APPLE__
   220     #define SDL20_LIBNAME "libSDL2.dylib"
   221     #else
   222     #define SDL20_LIBNAME "libSDL2-2.0.so.0"
   223     #endif
   224     static void *Loaded_SDL20 = NULL;
   225     #define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL)) != NULL)
   226     #define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
   227     #define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   228 #else
   229     #error Please define your platform.
   230 #endif
   231 
   232 static void *
   233 LoadSDL20Symbol(const char *fn, int *okay)
   234 {
   235     void *retval = NULL;
   236     if (*okay)  /* only bother trying if we haven't previously failed. */
   237     {
   238         retval = LookupSDL20Sym(fn);
   239         if (retval == NULL)
   240             *okay = 0;
   241     }
   242     return retval;
   243 }
   244 
   245 static void
   246 UnloadSDL20(void)
   247 {
   248     #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = NULL;
   249     #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) SDL20_##fn = NULL;
   250     #include "SDL20_syms.h"
   251     #undef SDL20_SYM_PASSTHROUGH
   252     #undef SDL20_SYM
   253     CloseSDL20Library();
   254 }
   255 
   256 static int
   257 LoadSDL20(void)
   258 {
   259     int okay = 1;
   260     if (!Loaded_SDL20)
   261     {
   262         okay = LoadSDL20Library();
   263         #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
   264         #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) SDL20_SYM(rc,fn,params,args,ret)
   265         #include "SDL20_syms.h"
   266         #undef SDL20_SYM_PASSTHROUGH
   267         #undef SDL20_SYM
   268         if (!okay)
   269             UnloadSDL20();
   270     }
   271     return okay;
   272 }
   273 
   274 
   275 static int
   276 GetVideoDisplay()
   277 {
   278     // !!! FIXME: cache this value during SDL_Init() so it doesn't change.
   279     const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
   280     if ( !variable ) {
   281         variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
   282     }
   283     if ( variable ) {
   284         return SDL_atoi(variable);
   285     } else {
   286         return 0;
   287     }
   288 }
   289 
   290 int
   291 SDL_Init(Uint32 sdl12flags)
   292 {
   293     Uint32 sdl20flags = 0;
   294     int rc;
   295 
   296     if (!LoadSDL20())
   297         return -1;
   298 
   299     #define SETFLAG(x) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag)
   300     SETFLAG(TIMER);
   301     SETFLAG(AUDIO);
   302     SETFLAG(VIDEO);
   303     SETFLAG(JOYSTICK);
   304     SETFLAG(NOPARACHUTE);
   305     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   306     #undef SETFLAG
   307 
   308     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   309 
   310     rc = SDL20_Init(sdl20flags);
   311     if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO))
   312         SDL_VideoDisplayIndex = GetVideoDisplay();
   313     return rc;
   314 }
   315 
   316 void
   317 SDL_Quit(void)
   318 {
   319     SDL20_Quit();
   320     UnloadSDL20();
   321 }
   322 
   323 
   324 char *
   325 SDL_GetError(void)
   326 {
   327     if (!Loaded_SDL20)
   328     {
   329         static char noload_errstr[] = "Failed to load SDL 2.0 shared library";
   330         return noload_errstr;
   331     }
   332     return SDL20_GetError();
   333 }
   334 
   335 
   336 static const char *
   337 GetDriverName(const char *name, char *namebuf, int maxlen)
   338 {
   339     if (name) {
   340         if (namebuf) {
   341             SDL20_strlcpy(namebuf, name, maxlen);
   342             return namebuf;
   343         } else {
   344             return name;
   345         }
   346     }
   347     return NULL;
   348 }
   349 
   350 const char *
   351 SDL_AudioDriverName(char *namebuf, int maxlen)
   352 {
   353     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
   354 }
   355 
   356 const char *
   357 SDL_VideoDriverName(char *namebuf, int maxlen)
   358 {
   359     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
   360 }
   361 
   362 const SDL12_VideoInfo *
   363 SDL_GetVideoInfo(void)
   364 {
   365     static SDL12_VideoInfo info;
   366     SDL_DisplayMode mode;
   367 
   368     /* !!! FIXME: Memory leak, compatibility code, who cares? */
   369     if (!info.vfmt && SDL20_GetDesktopDisplayMode(SDL_VideoDisplayIndex, &mode) == 0) {
   370         info.vfmt = SDL20_AllocFormat(mode.format);
   371         info.current_w = mode.w;
   372         info.current_h = mode.h;
   373         // !!! FIXME
   374         //info.wm_available = 1;
   375         //info.video_mem = 1024 * 256;
   376     }
   377     return &info;
   378 }
   379 
   380 int
   381 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
   382 {
   383     int i, nummodes, actual_bpp = 0;
   384 
   385     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
   386         return 0;
   387     }
   388 
   389     if (!(sdl12flags & SDL12_FULLSCREEN)) {
   390         SDL_DisplayMode mode;
   391         SDL20_GetDesktopDisplayMode(SDL_VideoDisplayIndex, &mode);
   392         return SDL_BITSPERPIXEL(mode.format);
   393     }
   394 
   395     nummodes = SDL20_GetNumDisplayModes(SDL_VideoDisplayIndex);
   396     for (i = 0; i < nummodes; ++i) {
   397         SDL_DisplayMode mode;
   398         SDL20_GetDisplayMode(SDL_VideoDisplayIndex, i, &mode);
   399         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
   400             if (!mode.format) {
   401                 return bpp;
   402             }
   403             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
   404                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
   405             }
   406         }
   407     }
   408     return actual_bpp;
   409 }
   410 
   411 SDL_Rect **
   412 SDL_ListModes(const SDL12_PixelFormat * format, Uint32 flags)
   413 {
   414     int i, nmodes;
   415     SDL_Rect **modes;
   416 
   417     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
   418         return NULL;
   419     }
   420 
   421     if (!(flags & SDL12_FULLSCREEN)) {
   422         return (SDL_Rect **) (-1);
   423     }
   424 
   425     if (!format) {
   426         format = SDL_GetVideoInfo()->vfmt;
   427     }
   428 
   429     /* Memory leak, but this is a compatibility function, who cares? */
   430     nmodes = 0;
   431     modes = NULL;
   432     for (i = 0; i < SDL20_GetNumDisplayModes(SDL_VideoDisplayIndex); ++i) {
   433         SDL_DisplayMode mode;
   434         int bpp;
   435 
   436         SDL20_GetDisplayMode(SDL_VideoDisplayIndex, i, &mode);
   437         if (!mode.w || !mode.h) {
   438             return (SDL_Rect **) (-1);
   439         }
   440         
   441         /* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
   442         if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
   443             bpp = SDL_BITSPERPIXEL(mode.format);
   444         } else {
   445             bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
   446         }
   447 
   448         if (bpp != format->BitsPerPixel) {
   449             continue;
   450         }
   451         if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
   452             && modes[nmodes - 1]->h == mode.h) {
   453             continue;
   454         }
   455 
   456         modes = SDL_realloc(modes, (nmodes + 2) * sizeof(*modes));
   457         if (!modes) {
   458             return NULL;
   459         }
   460         modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
   461         if (!modes[nmodes]) {
   462             return NULL;
   463         }
   464         modes[nmodes]->x = 0;
   465         modes[nmodes]->y = 0;
   466         modes[nmodes]->w = mode.w;
   467         modes[nmodes]->h = mode.h;
   468         ++nmodes;
   469     }
   470     if (modes) {
   471         modes[nmodes] = NULL;
   472     }
   473     return modes;
   474 }
   475 
   476 static int
   477 SDL_CompatEventFilter(void *userdata, SDL_Event * event)
   478 {
   479     SDL_Event fake;
   480 
   481     switch (event->type) {
   482     case SDL_WINDOWEVENT:
   483         switch (event->window.event) {
   484         case SDL_WINDOWEVENT_EXPOSED:
   485             if (!SDL_HasEvent(SDL_VIDEOEXPOSE)) {
   486                 fake.type = SDL_VIDEOEXPOSE;
   487                 SDL_PushEvent(&fake);
   488             }
   489             break;
   490         case SDL_WINDOWEVENT_RESIZED:
   491             SDL_FlushEvent(SDL_VIDEORESIZE);
   492             /* We don't want to expose that the window width and height will
   493                be different if we don't get the desired fullscreen mode.
   494             */
   495             if (SDL_VideoWindow && !(SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN)) {
   496                 fake.type = SDL_VIDEORESIZE;
   497                 fake.resize.w = event->window.data1;
   498                 fake.resize.h = event->window.data2;
   499                 SDL_PushEvent(&fake);
   500             }
   501             break;
   502         case SDL_WINDOWEVENT_MINIMIZED:
   503             fake.type = SDL_ACTIVEEVENT;
   504             fake.active.gain = 0;
   505             fake.active.state = SDL_APPACTIVE;
   506             SDL_PushEvent(&fake);
   507             break;
   508         case SDL_WINDOWEVENT_RESTORED:
   509             fake.type = SDL_ACTIVEEVENT;
   510             fake.active.gain = 1;
   511             fake.active.state = SDL_APPACTIVE;
   512             SDL_PushEvent(&fake);
   513             break;
   514         case SDL_WINDOWEVENT_ENTER:
   515             fake.type = SDL_ACTIVEEVENT;
   516             fake.active.gain = 1;
   517             fake.active.state = SDL_APPMOUSEFOCUS;
   518             SDL_PushEvent(&fake);
   519             break;
   520         case SDL_WINDOWEVENT_LEAVE:
   521             fake.type = SDL_ACTIVEEVENT;
   522             fake.active.gain = 0;
   523             fake.active.state = SDL_APPMOUSEFOCUS;
   524             SDL_PushEvent(&fake);
   525             break;
   526         case SDL_WINDOWEVENT_FOCUS_GAINED:
   527             fake.type = SDL_ACTIVEEVENT;
   528             fake.active.gain = 1;
   529             fake.active.state = SDL_APPINPUTFOCUS;
   530             SDL_PushEvent(&fake);
   531             break;
   532         case SDL_WINDOWEVENT_FOCUS_LOST:
   533             fake.type = SDL_ACTIVEEVENT;
   534             fake.active.gain = 0;
   535             fake.active.state = SDL_APPINPUTFOCUS;
   536             SDL_PushEvent(&fake);
   537             break;
   538         case SDL_WINDOWEVENT_CLOSE:
   539             fake.type = SDL_QUIT;
   540             SDL_PushEvent(&fake);
   541             break;
   542         }
   543     case SDL_KEYDOWN:
   544     case SDL_KEYUP:
   545         {
   546             Uint32 unicode = 0;
   547             if (event->key.type == SDL_KEYDOWN && event->key.keysym.sym < 256) {
   548                 unicode = event->key.keysym.sym;
   549                 if (unicode >= 'a' && unicode <= 'z') {
   550                     int shifted = !!(event->key.keysym.mod & KMOD_SHIFT);
   551                     int capslock = !!(event->key.keysym.mod & KMOD_CAPS);
   552                     if ((shifted ^ capslock) != 0) {
   553                         unicode = SDL_toupper(unicode);
   554                     }
   555                 }
   556             }
   557             if (unicode) {
   558                 event->key.keysym.unicode = unicode;
   559             }
   560             break;
   561         }
   562     case SDL_TEXTINPUT:
   563         {
   564             /* FIXME: Generate an old style key repeat event if needed */
   565             //printf("TEXTINPUT: '%s'\n", event->text.text);
   566             break;
   567         }
   568     case SDL_MOUSEMOTION:
   569         {
   570             event->motion.x -= SDL_VideoViewport.x;
   571             event->motion.y -= SDL_VideoViewport.y;
   572             break;
   573         }
   574     case SDL_MOUSEBUTTONDOWN:
   575     case SDL_MOUSEBUTTONUP:
   576         {
   577             event->button.x -= SDL_VideoViewport.x;
   578             event->button.y -= SDL_VideoViewport.y;
   579             break;
   580         }
   581     case SDL_MOUSEWHEEL:
   582         {
   583             Uint8 button;
   584             int x, y;
   585 
   586             if (event->wheel.y == 0) {
   587                 break;
   588             }
   589 
   590             SDL_GetMouseState(&x, &y);
   591 
   592             if (event->wheel.y > 0) {
   593                 button = SDL_BUTTON_WHEELUP;
   594             } else {
   595                 button = SDL_BUTTON_WHEELDOWN;
   596             }
   597 
   598             fake.button.button = button;
   599             fake.button.x = x;
   600             fake.button.y = y;
   601             fake.button.windowID = event->wheel.windowID;
   602 
   603             fake.type = SDL_MOUSEBUTTONDOWN;
   604             fake.button.state = SDL_PRESSED;
   605             SDL_PushEvent(&fake);
   606 
   607             fake.type = SDL_MOUSEBUTTONUP;
   608             fake.button.state = SDL_RELEASED;
   609             SDL_PushEvent(&fake);
   610             break;
   611         }
   612 
   613     }
   614     return 1;
   615 }
   616 
   617 static void
   618 GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
   619 {
   620     int display = SDL_VideoDisplayIndex;
   621     const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
   622     const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
   623     if (window) {
   624         if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
   625             return;
   626         }
   627         if (SDL_strcmp(window, "center") == 0) {
   628             center = window;
   629         }
   630     }
   631     if (center) {
   632         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
   633         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
   634     }
   635 }
   636 
   637 static void
   638 ClearVideoSurface()
   639 {
   640     if (SDL_ShadowSurface) {
   641         SDL_FillRect(SDL_ShadowSurface, NULL,
   642             SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
   643     }
   644     SDL_FillRect(SDL_WindowSurface, NULL, 0);
   645     SDL_UpdateWindowSurface(SDL_VideoWindow);
   646 }
   647 
   648 static void
   649 SetupScreenSaver(int flags)
   650 {
   651     const char *env;
   652     SDL_bool allow_screensaver;
   653 
   654     /* Allow environment override of screensaver disable */
   655     env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
   656     if (env) {
   657         allow_screensaver = SDL_atoi(env) ? SDL_TRUE : SDL_FALSE;
   658     } else if (flags & SDL_FULLSCREEN) {
   659         allow_screensaver = SDL_FALSE;
   660     } else {
   661         allow_screensaver = SDL_TRUE;
   662     }
   663     if (allow_screensaver) {
   664         SDL_EnableScreenSaver();
   665     } else {
   666         SDL_DisableScreenSaver();
   667     }
   668 }
   669 
   670 static int
   671 SDL_ResizeVideoMode(int width, int height, int bpp, Uint32 flags)
   672 {
   673     int w, h;
   674 
   675     /* We can't resize something we don't have... */
   676     if (!SDL_VideoSurface) {
   677         return -1;
   678     }
   679 
   680     /* We probably have to recreate the window in fullscreen mode */
   681     if (flags & SDL_FULLSCREEN) {
   682         return -1;
   683     }
   684 
   685     /* I don't think there's any change we can gracefully make in flags */
   686     if (flags != SDL_VideoFlags) {
   687         return -1;
   688     }
   689     if (bpp != SDL_VideoSurface->format->BitsPerPixel) {
   690         return -1;
   691     }
   692 
   693     /* Resize the window */
   694     SDL_GetWindowSize(SDL_VideoWindow, &w, &h);
   695     if (w != width || h != height) {
   696         SDL_SetWindowSize(SDL_VideoWindow, width, height);
   697     }
   698 
   699     /* If we're in OpenGL mode, just resize the stub surface and we're done! */
   700     if (flags & SDL_OPENGL) {
   701         SDL_VideoSurface->w = width;
   702         SDL_VideoSurface->h = height;
   703         return 0;
   704     }
   705 
   706     SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
   707     if (!SDL_WindowSurface) {
   708         return -1;
   709     }
   710     if (SDL_VideoSurface->format != SDL_WindowSurface->format) {
   711         return -1;
   712     }
   713     SDL_VideoSurface->w = width;
   714     SDL_VideoSurface->h = height;
   715     SDL_VideoSurface->pixels = SDL_WindowSurface->pixels;
   716     SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
   717     SDL_SetClipRect(SDL_VideoSurface, NULL);
   718 
   719     if (SDL_ShadowSurface) {
   720         SDL_ShadowSurface->w = width;
   721         SDL_ShadowSurface->h = height;
   722         SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
   723         SDL_ShadowSurface->pixels =
   724             SDL_realloc(SDL_ShadowSurface->pixels,
   725                         SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
   726         SDL_SetClipRect(SDL_ShadowSurface, NULL);
   727         SDL_InvalidateMap(SDL_ShadowSurface->map);
   728     } else {
   729         SDL_PublicSurface = SDL_VideoSurface;
   730     }
   731 
   732     ClearVideoSurface();
   733 
   734     return 0;
   735 }
   736 
   737 SDL_Surface *
   738 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
   739 {
   740     SDL_DisplayMode desktop_mode;
   741     int display = SDL_VideoDisplayIndex;
   742     int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
   743     int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
   744     int window_w;
   745     int window_h;
   746     Uint32 window_flags;
   747     Uint32 surface_flags;
   748 
   749     if (!SDL_GetVideoDevice()) {
   750         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
   751             return NULL;
   752         }
   753     }
   754 
   755     SDL_GetDesktopDisplayMode(display, &desktop_mode);
   756 
   757     if (width == 0) {
   758         width = desktop_mode.w;
   759     }
   760     if (height == 0) {
   761         height = desktop_mode.h;
   762     }
   763     if (bpp == 0) {
   764         bpp = SDL_BITSPERPIXEL(desktop_mode.format);
   765     }
   766 
   767     /* See if we can simply resize the existing window and surface */
   768     if (SDL_ResizeVideoMode(width, height, bpp, flags) == 0) {
   769         return SDL_PublicSurface;
   770     }
   771 
   772     /* Destroy existing window */
   773     SDL_PublicSurface = NULL;
   774     if (SDL_ShadowSurface) {
   775         SDL_ShadowSurface->flags &= ~SDL_DONTFREE;
   776         SDL_FreeSurface(SDL_ShadowSurface);
   777         SDL_ShadowSurface = NULL;
   778     }
   779     if (SDL_VideoSurface) {
   780         SDL_VideoSurface->flags &= ~SDL_DONTFREE;
   781         SDL_FreeSurface(SDL_VideoSurface);
   782         SDL_VideoSurface = NULL;
   783     }
   784     if (SDL_VideoContext) {
   785         /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
   786         SDL_GL_DeleteContext(SDL_VideoContext);
   787         SDL_VideoContext = NULL;
   788     }
   789     if (SDL_VideoWindow) {
   790         SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
   791         SDL_DestroyWindow(SDL_VideoWindow);
   792     }
   793 
   794     /* Set up the event filter */
   795     if (!SDL_GetEventFilter(NULL, NULL)) {
   796         SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
   797     }
   798 
   799     /* Create a new window */
   800     window_flags = SDL_WINDOW_SHOWN;
   801     if (flags & SDL_FULLSCREEN) {
   802         window_flags |= SDL_WINDOW_FULLSCREEN;
   803     }
   804     if (flags & SDL_OPENGL) {
   805         window_flags |= SDL_WINDOW_OPENGL;
   806     }
   807     if (flags & SDL_RESIZABLE) {
   808         window_flags |= SDL_WINDOW_RESIZABLE;
   809     }
   810     if (flags & SDL_NOFRAME) {
   811         window_flags |= SDL_WINDOW_BORDERLESS;
   812     }
   813     GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
   814     SDL_VideoWindow =
   815         SDL_CreateWindow(wm_title, window_x, window_y, width, height,
   816                          window_flags);
   817     if (!SDL_VideoWindow) {
   818         return NULL;
   819     }
   820     SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
   821 
   822     SetupScreenSaver(flags);
   823 
   824     window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
   825     surface_flags = 0;
   826     if (window_flags & SDL_WINDOW_FULLSCREEN) {
   827         surface_flags |= SDL_FULLSCREEN;
   828     }
   829     if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
   830         surface_flags |= SDL_OPENGL;
   831     }
   832     if (window_flags & SDL_WINDOW_RESIZABLE) {
   833         surface_flags |= SDL_RESIZABLE;
   834     }
   835     if (window_flags & SDL_WINDOW_BORDERLESS) {
   836         surface_flags |= SDL_NOFRAME;
   837     }
   838 
   839     SDL_VideoFlags = flags;
   840 
   841     /* If we're in OpenGL mode, just create a stub surface and we're done! */
   842     if (flags & SDL_OPENGL) {
   843         SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow);
   844         if (!SDL_VideoContext) {
   845             return NULL;
   846         }
   847         if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
   848             return NULL;
   849         }
   850         SDL_VideoSurface =
   851             SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
   852         if (!SDL_VideoSurface) {
   853             return NULL;
   854         }
   855         SDL_VideoSurface->flags |= surface_flags;
   856         SDL_PublicSurface = SDL_VideoSurface;
   857         return SDL_PublicSurface;
   858     }
   859 
   860     /* Create the screen surface */
   861     SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
   862     if (!SDL_WindowSurface) {
   863         return NULL;
   864     }
   865 
   866     /* Center the public surface in the window surface */
   867     SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
   868     SDL_VideoViewport.x = (window_w - width)/2;
   869     SDL_VideoViewport.y = (window_h - height)/2;
   870     SDL_VideoViewport.w = width;
   871     SDL_VideoViewport.h = height;
   872 
   873     SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
   874     SDL_VideoSurface->flags |= surface_flags;
   875     SDL_VideoSurface->flags |= SDL_DONTFREE;
   876     SDL_FreeFormat(SDL_VideoSurface->format);
   877     SDL_VideoSurface->format = SDL_WindowSurface->format;
   878     SDL_VideoSurface->format->refcount++;
   879     SDL_VideoSurface->w = width;
   880     SDL_VideoSurface->h = height;
   881     SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
   882     SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
   883         SDL_VideoViewport.y * SDL_VideoSurface->pitch +
   884         SDL_VideoViewport.x  * SDL_VideoSurface->format->BytesPerPixel);
   885     SDL_SetClipRect(SDL_VideoSurface, NULL);
   886 
   887     /* Create a shadow surface if necessary */
   888     if ((bpp != SDL_VideoSurface->format->BitsPerPixel)
   889         && !(flags & SDL_ANYFORMAT)) {
   890         SDL_ShadowSurface =
   891             SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
   892         if (!SDL_ShadowSurface) {
   893             return NULL;
   894         }
   895         SDL_ShadowSurface->flags |= surface_flags;
   896         SDL_ShadowSurface->flags |= SDL_DONTFREE;
   897 
   898         /* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
   899         if (SDL_ShadowSurface->format->palette) {
   900             SDL_ShadowSurface->flags |= SDL_HWPALETTE;
   901             SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
   902                              SDL_ShadowSurface->format->BitsPerPixel);
   903         }
   904         SDL_FillRect(SDL_ShadowSurface, NULL,
   905             SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
   906     }
   907     SDL_PublicSurface =
   908         (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
   909 
   910     ClearVideoSurface();
   911 
   912     /* We're finally done! */
   913     return SDL_PublicSurface;
   914 }
   915 
   916 SDL_Surface *
   917 SDL_GetVideoSurface(void)
   918 {
   919     return SDL_PublicSurface;
   920 }
   921 
   922 int
   923 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
   924 {
   925     if (flag & SDL_SRCALPHA) {
   926         /* According to the docs, value is ignored for alpha surfaces */
   927         if (surface->format->Amask) {
   928             value = 0xFF;
   929         }
   930         SDL_SetSurfaceAlphaMod(surface, value);
   931         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
   932     } else {
   933         SDL_SetSurfaceAlphaMod(surface, 0xFF);
   934         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
   935     }
   936     SDL_SetSurfaceRLE(surface, (flag & SDL_RLEACCEL));
   937 
   938     return 0;
   939 }
   940 
   941 SDL_Surface *
   942 SDL_DisplayFormat(SDL_Surface * surface)
   943 {
   944     SDL_PixelFormat *format;
   945 
   946     if (!SDL_PublicSurface) {
   947         SDL_SetError("No video mode has been set");
   948         return NULL;
   949     }
   950     format = SDL_PublicSurface->format;
   951 
   952     /* Set the flags appropriate for copying to display surface */
   953     return SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
   954 }
   955 
   956 SDL_Surface *
   957 SDL_DisplayFormatAlpha(SDL_Surface * surface)
   958 {
   959     SDL_PixelFormat *vf;
   960     SDL_PixelFormat *format;
   961     SDL_Surface *converted;
   962     /* default to ARGB8888 */
   963     Uint32 amask = 0xff000000;
   964     Uint32 rmask = 0x00ff0000;
   965     Uint32 gmask = 0x0000ff00;
   966     Uint32 bmask = 0x000000ff;
   967 
   968     if (!SDL_PublicSurface) {
   969         SDL_SetError("No video mode has been set");
   970         return NULL;
   971     }
   972     vf = SDL_PublicSurface->format;
   973 
   974     switch (vf->BytesPerPixel) {
   975     case 2:
   976         /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
   977            For anything else (like ARGB4444) it doesn't matter
   978            since we have no special code for it anyway */
   979         if ((vf->Rmask == 0x1f) &&
   980             (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
   981             rmask = 0xff;
   982             bmask = 0xff0000;
   983         }
   984         break;
   985 
   986     case 3:
   987     case 4:
   988         /* Keep the video format, as long as the high 8 bits are
   989            unused or alpha */
   990         if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
   991             rmask = 0xff;
   992             bmask = 0xff0000;
   993         }
   994         break;
   995 
   996     default:
   997         /* We have no other optimised formats right now. When/if a new
   998            optimised alpha format is written, add the converter here */
   999         break;
  1000     }
  1001     format = SDL_AllocFormat(SDL_MasksToPixelFormatEnum(32, rmask,
  1002                                                             gmask,
  1003                                                             bmask,
  1004                                                             amask));
  1005     if (!format) {
  1006         return NULL;
  1007     }
  1008     converted = SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
  1009     SDL_FreeFormat(format);
  1010     return converted;
  1011 }
  1012 
  1013 int
  1014 SDL_Flip(SDL_Surface * screen)
  1015 {
  1016     SDL_UpdateRect(screen, 0, 0, 0, 0);
  1017     return 0;
  1018 }
  1019 
  1020 void
  1021 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  1022 {
  1023     if (screen) {
  1024         SDL_Rect rect;
  1025 
  1026         /* Fill the rectangle */
  1027         rect.x = (int) x;
  1028         rect.y = (int) y;
  1029         rect.w = (int) (w ? w : screen->w);
  1030         rect.h = (int) (h ? h : screen->h);
  1031         SDL_UpdateRects(screen, 1, &rect);
  1032     }
  1033 }
  1034 
  1035 void
  1036 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
  1037 {
  1038     int i;
  1039 
  1040     if (screen == SDL_ShadowSurface) {
  1041         for (i = 0; i < numrects; ++i) {
  1042             SDL_BlitSurface(SDL_ShadowSurface, &rects[i], SDL_VideoSurface,
  1043                             &rects[i]);
  1044         }
  1045 
  1046         /* Fall through to video surface update */
  1047         screen = SDL_VideoSurface;
  1048     }
  1049     if (screen == SDL_VideoSurface) {
  1050         if (SDL_VideoViewport.x || SDL_VideoViewport.y) {
  1051             SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
  1052             SDL_Rect *stackrect;
  1053             const SDL_Rect *rect;
  1054             
  1055             /* Offset all the rectangles before updating */
  1056             for (i = 0; i < numrects; ++i) {
  1057                 rect = &rects[i];
  1058                 stackrect = &stackrects[i];
  1059                 stackrect->x = SDL_VideoViewport.x + rect->x;
  1060                 stackrect->y = SDL_VideoViewport.y + rect->y;
  1061                 stackrect->w = rect->w;
  1062                 stackrect->h = rect->h;
  1063             }
  1064             SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, stackrects, numrects);
  1065             SDL_stack_free(stackrects);
  1066         } else {
  1067             SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, rects, numrects);
  1068         }
  1069     }
  1070 }
  1071 
  1072 void
  1073 SDL_WM_SetCaption(const char *title, const char *icon)
  1074 {
  1075     if (wm_title) {
  1076         SDL_free(wm_title);
  1077     }
  1078     if (wm_icon_caption) {
  1079         SDL_free(wm_icon_caption);
  1080     }
  1081     wm_title = title ? SDL_strdup(title) : NULL;
  1082     wm_icon_caption = icon ? SDL_strdup(icon) : NULL;
  1083     SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
  1084 }
  1085 
  1086 void
  1087 SDL_WM_GetCaption(const char **title, const char **icon)
  1088 {
  1089     if (title) {
  1090         *title = wm_title;
  1091     }
  1092     if (icon) {
  1093         *icon = wm_icon_caption;
  1094     }
  1095 }
  1096 
  1097 void
  1098 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
  1099 {
  1100     // !!! FIXME: free previous icon?
  1101     SDL_VideoIcon = icon;
  1102     ++SDL_VideoIcon->refcount;
  1103 }
  1104 
  1105 int
  1106 SDL_WM_IconifyWindow(void)
  1107 {
  1108     SDL_MinimizeWindow(SDL_VideoWindow);
  1109     return 0;
  1110 }
  1111 
  1112 int
  1113 SDL_WM_ToggleFullScreen(SDL_Surface * surface)
  1114 {
  1115     int length;
  1116     void *pixels;
  1117     Uint8 *src, *dst;
  1118     int row;
  1119     int window_w;
  1120     int window_h;
  1121 
  1122     if (!SDL_PublicSurface) {
  1123         SDL_SetError("SDL_SetVideoMode() hasn't been called");
  1124         return 0;
  1125     }
  1126 
  1127     /* Copy the old bits out */
  1128     length = SDL_PublicSurface->w * SDL_PublicSurface->format->BytesPerPixel;
  1129     pixels = SDL_malloc(SDL_PublicSurface->h * length);
  1130     if (pixels && SDL_PublicSurface->pixels) {
  1131         src = (Uint8*)SDL_PublicSurface->pixels;
  1132         dst = (Uint8*)pixels;
  1133         for (row = 0; row < SDL_PublicSurface->h; ++row) {
  1134             SDL_memcpy(dst, src, length);
  1135             src += SDL_PublicSurface->pitch;
  1136             dst += length;
  1137         }
  1138     }
  1139 
  1140     /* Do the physical mode switch */
  1141     if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
  1142         if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
  1143             return 0;
  1144         }
  1145         SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
  1146     } else {
  1147         if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) {
  1148             return 0;
  1149         }
  1150         SDL_PublicSurface->flags |= SDL_FULLSCREEN;
  1151     }
  1152 
  1153     /* Recreate the screen surface */
  1154     SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
  1155     if (!SDL_WindowSurface) {
  1156         /* We're totally hosed... */
  1157         return 0;
  1158     }
  1159 
  1160     /* Center the public surface in the window surface */
  1161     SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
  1162     SDL_VideoViewport.x = (window_w - SDL_VideoSurface->w)/2;
  1163     SDL_VideoViewport.y = (window_h - SDL_VideoSurface->h)/2;
  1164     SDL_VideoViewport.w = SDL_VideoSurface->w;
  1165     SDL_VideoViewport.h = SDL_VideoSurface->h;
  1166 
  1167     /* Do some shuffling behind the application's back if format changes */
  1168     if (SDL_VideoSurface->format->format != SDL_WindowSurface->format->format) {
  1169         if (SDL_ShadowSurface) {
  1170             if (SDL_ShadowSurface->format->format == SDL_WindowSurface->format->format) {
  1171                 /* Whee!  We don't need a shadow surface anymore! */
  1172                 SDL_VideoSurface->flags &= ~SDL_DONTFREE;
  1173                 SDL_FreeSurface(SDL_VideoSurface);
  1174                 SDL_free(SDL_ShadowSurface->pixels);
  1175                 SDL_VideoSurface = SDL_ShadowSurface;
  1176                 SDL_VideoSurface->flags |= SDL_PREALLOC;
  1177                 SDL_ShadowSurface = NULL;
  1178             } else {
  1179                 /* No problem, just change the video surface format */
  1180                 SDL_FreeFormat(SDL_VideoSurface->format);
  1181                 SDL_VideoSurface->format = SDL_WindowSurface->format;
  1182                 SDL_VideoSurface->format->refcount++;
  1183                 SDL_InvalidateMap(SDL_ShadowSurface->map);
  1184             }
  1185         } else {
  1186             /* We can make the video surface the shadow surface */
  1187             SDL_ShadowSurface = SDL_VideoSurface;
  1188             SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
  1189             SDL_ShadowSurface->pixels = SDL_malloc(SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
  1190             if (!SDL_ShadowSurface->pixels) {
  1191                 /* Uh oh, we're hosed */
  1192                 SDL_ShadowSurface = NULL;
  1193                 return 0;
  1194             }
  1195             SDL_ShadowSurface->flags &= ~SDL_PREALLOC;
  1196 
  1197             SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  1198             SDL_VideoSurface->flags = SDL_ShadowSurface->flags;
  1199             SDL_VideoSurface->flags |= SDL_PREALLOC;
  1200             SDL_FreeFormat(SDL_VideoSurface->format);
  1201             SDL_VideoSurface->format = SDL_WindowSurface->format;
  1202             SDL_VideoSurface->format->refcount++;
  1203             SDL_VideoSurface->w = SDL_ShadowSurface->w;
  1204             SDL_VideoSurface->h = SDL_ShadowSurface->h;
  1205         }
  1206     }
  1207 
  1208     /* Update the video surface */
  1209     SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
  1210     SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
  1211         SDL_VideoViewport.y * SDL_VideoSurface->pitch +
  1212         SDL_VideoViewport.x  * SDL_VideoSurface->format->BytesPerPixel);
  1213     SDL_SetClipRect(SDL_VideoSurface, NULL);
  1214 
  1215     /* Copy the old bits back */
  1216     if (pixels) {
  1217         src = (Uint8*)pixels;
  1218         dst = (Uint8*)SDL_PublicSurface->pixels;
  1219         for (row = 0; row < SDL_PublicSurface->h; ++row) {
  1220             SDL_memcpy(dst, src, length);
  1221             src += length;
  1222             dst += SDL_PublicSurface->pitch;
  1223         }
  1224         SDL_Flip(SDL_PublicSurface);
  1225         SDL_free(pixels);
  1226     }
  1227 
  1228     /* We're done! */
  1229     return 1;
  1230 }
  1231 
  1232 SDL_GrabMode
  1233 SDL_WM_GrabInput(SDL_GrabMode mode)
  1234 {
  1235     if (mode != SDL_GRAB_QUERY) {
  1236         SDL_SetWindowGrab(SDL_VideoWindow, mode);
  1237     }
  1238     return (SDL_GrabMode) SDL_GetWindowGrab(SDL_VideoWindow);
  1239 }
  1240 
  1241 void
  1242 SDL_WarpMouse(Uint16 x, Uint16 y)
  1243 {
  1244     SDL_WarpMouseInWindow(SDL_VideoWindow, x, y);
  1245 }
  1246 
  1247 Uint8
  1248 SDL_GetAppState(void)
  1249 {
  1250     Uint8 state = 0;
  1251     Uint32 flags = 0;
  1252 
  1253     flags = SDL_GetWindowFlags(SDL_VideoWindow);
  1254     if ((flags & SDL_WINDOW_SHOWN) && !(flags & SDL_WINDOW_MINIMIZED)) {
  1255         state |= SDL_APPACTIVE;
  1256     }
  1257     if (flags & SDL_WINDOW_INPUT_FOCUS) {
  1258         state |= SDL_APPINPUTFOCUS;
  1259     }
  1260     if (flags & SDL_WINDOW_MOUSE_FOCUS) {
  1261         state |= SDL_APPMOUSEFOCUS;
  1262     }
  1263     return state;
  1264 }
  1265 
  1266 const SDL_version *
  1267 SDL_Linked_Version(void)
  1268 {
  1269     static SDL_version version;
  1270     SDL_VERSION(&version);
  1271     return &version;
  1272 }
  1273 
  1274 int
  1275 SDL_SetPalette(SDL_Surface * surface, int flags, const SDL_Color * colors,
  1276                int firstcolor, int ncolors)
  1277 {
  1278     return SDL_SetColors(surface, colors, firstcolor, ncolors);
  1279 }
  1280 
  1281 int
  1282 SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
  1283               int ncolors)
  1284 {
  1285     if (SDL_SetPaletteColors
  1286         (surface->format->palette, colors, firstcolor, ncolors) == 0) {
  1287         return 1;
  1288     } else {
  1289         return 0;
  1290     }
  1291 }
  1292 
  1293 int
  1294 SDL_GetWMInfo(SDL_SysWMinfo * info)
  1295 {
  1296     return SDL_GetWindowWMInfo(SDL_VideoWindow, info);
  1297 }
  1298 
  1299 #if 0
  1300 void
  1301 SDL_MoveCursor(int x, int y)
  1302 {
  1303     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1304 
  1305     /* Erase and update the current mouse position */
  1306     if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
  1307         /* Erase and redraw mouse cursor in new position */
  1308         SDL_LockCursor();
  1309         SDL_EraseCursor(SDL_VideoSurface);
  1310         SDL_cursor->area.x = (x - SDL_cursor->hot_x);
  1311         SDL_cursor->area.y = (y - SDL_cursor->hot_y);
  1312         SDL_DrawCursor(SDL_VideoSurface);
  1313         SDL_UnlockCursor();
  1314     } else if (_this->MoveWMCursor) {
  1315         _this->MoveWMCursor(_this, x, y);
  1316     }
  1317 }
  1318 
  1319 /* Keep track of the current cursor colors */
  1320 static int palette_changed = 1;
  1321 static Uint8 pixels8[2];
  1322 
  1323 void
  1324 SDL_CursorPaletteChanged(void)
  1325 {
  1326     palette_changed = 1;
  1327 }
  1328 
  1329 void
  1330 SDL_MouseRect(SDL_Rect * area)
  1331 {
  1332     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1333     int clip_diff;
  1334 
  1335     *area = SDL_cursor->area;
  1336     if (area->x < 0) {
  1337         area->w += area->x;
  1338         area->x = 0;
  1339     }
  1340     if (area->y < 0) {
  1341         area->h += area->y;
  1342         area->y = 0;
  1343     }
  1344     clip_diff = (area->x + area->w) - SDL_VideoSurface->w;
  1345     if (clip_diff > 0) {
  1346         area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
  1347     }
  1348     clip_diff = (area->y + area->h) - SDL_VideoSurface->h;
  1349     if (clip_diff > 0) {
  1350         area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
  1351     }
  1352 }
  1353 
  1354 static void
  1355 SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
  1356 {
  1357     const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
  1358     int i, w, h;
  1359     Uint8 *data, datab;
  1360     Uint8 *mask, maskb;
  1361 
  1362     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  1363     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  1364     switch (screen->format->BytesPerPixel) {
  1365 
  1366     case 1:
  1367         {
  1368             Uint8 *dst;
  1369             int dstskip;
  1370 
  1371             if (palette_changed) {
  1372                 pixels8[0] =
  1373                     (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  1374                 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  1375                 palette_changed = 0;
  1376             }
  1377             dst = (Uint8 *) screen->pixels +
  1378                 (SDL_cursor->area.y + area->y) * screen->pitch +
  1379                 SDL_cursor->area.x;
  1380             dstskip = screen->pitch - area->w;
  1381 
  1382             for (h = area->h; h; h--) {
  1383                 for (w = area->w / 8; w; w--) {
  1384                     maskb = *mask++;
  1385                     datab = *data++;
  1386                     for (i = 0; i < 8; ++i) {
  1387                         if (maskb & 0x80) {
  1388                             *dst = pixels8[datab >> 7];
  1389                         }
  1390                         maskb <<= 1;
  1391                         datab <<= 1;
  1392                         dst++;
  1393                     }
  1394                 }
  1395                 dst += dstskip;
  1396             }
  1397         }
  1398         break;
  1399 
  1400     case 2:
  1401         {
  1402             Uint16 *dst;
  1403             int dstskip;
  1404 
  1405             dst = (Uint16 *) screen->pixels +
  1406                 (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
  1407                 SDL_cursor->area.x;
  1408             dstskip = (screen->pitch / 2) - area->w;
  1409 
  1410             for (h = area->h; h; h--) {
  1411                 for (w = area->w / 8; w; w--) {
  1412                     maskb = *mask++;
  1413                     datab = *data++;
  1414                     for (i = 0; i < 8; ++i) {
  1415                         if (maskb & 0x80) {
  1416                             *dst = (Uint16) pixels[datab >> 7];
  1417                         }
  1418                         maskb <<= 1;
  1419                         datab <<= 1;
  1420                         dst++;
  1421                     }
  1422                 }
  1423                 dst += dstskip;
  1424             }
  1425         }
  1426         break;
  1427 
  1428     case 3:
  1429         {
  1430             Uint8 *dst;
  1431             int dstskip;
  1432 
  1433             dst = (Uint8 *) screen->pixels +
  1434                 (SDL_cursor->area.y + area->y) * screen->pitch +
  1435                 SDL_cursor->area.x * 3;
  1436             dstskip = screen->pitch - area->w * 3;
  1437 
  1438             for (h = area->h; h; h--) {
  1439                 for (w = area->w / 8; w; w--) {
  1440                     maskb = *mask++;
  1441                     datab = *data++;
  1442                     for (i = 0; i < 8; ++i) {
  1443                         if (maskb & 0x80) {
  1444                             SDL_memset(dst, pixels[datab >> 7], 3);
  1445                         }
  1446                         maskb <<= 1;
  1447                         datab <<= 1;
  1448                         dst += 3;
  1449                     }
  1450                 }
  1451                 dst += dstskip;
  1452             }
  1453         }
  1454         break;
  1455 
  1456     case 4:
  1457         {
  1458             Uint32 *dst;
  1459             int dstskip;
  1460 
  1461             dst = (Uint32 *) screen->pixels +
  1462                 (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
  1463                 SDL_cursor->area.x;
  1464             dstskip = (screen->pitch / 4) - area->w;
  1465 
  1466             for (h = area->h; h; h--) {
  1467                 for (w = area->w / 8; w; w--) {
  1468                     maskb = *mask++;
  1469                     datab = *data++;
  1470                     for (i = 0; i < 8; ++i) {
  1471                         if (maskb & 0x80) {
  1472                             *dst = pixels[datab >> 7];
  1473                         }
  1474                         maskb <<= 1;
  1475                         datab <<= 1;
  1476                         dst++;
  1477                     }
  1478                 }
  1479                 dst += dstskip;
  1480             }
  1481         }
  1482         break;
  1483     }
  1484 }
  1485 
  1486 static void
  1487 SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
  1488 {
  1489     const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
  1490     int h;
  1491     int x, minx, maxx;
  1492     Uint8 *data, datab = 0;
  1493     Uint8 *mask, maskb = 0;
  1494     Uint8 *dst;
  1495     int dstbpp, dstskip;
  1496 
  1497     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  1498     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  1499     dstbpp = screen->format->BytesPerPixel;
  1500     dst = (Uint8 *) screen->pixels +
  1501         (SDL_cursor->area.y + area->y) * screen->pitch +
  1502         SDL_cursor->area.x * dstbpp;
  1503     dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
  1504 
  1505     minx = area->x;
  1506     maxx = area->x + area->w;
  1507     if (screen->format->BytesPerPixel == 1) {
  1508         if (palette_changed) {
  1509             pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  1510             pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  1511             palette_changed = 0;
  1512         }
  1513         for (h = area->h; h; h--) {
  1514             for (x = 0; x < SDL_cursor->area.w; ++x) {
  1515                 if ((x % 8) == 0) {
  1516                     maskb = *mask++;
  1517                     datab = *data++;
  1518                 }
  1519                 if ((x >= minx) && (x < maxx)) {
  1520                     if (maskb & 0x80) {
  1521                         SDL_memset(dst, pixels8[datab >> 7], dstbpp);
  1522                     }
  1523                 }
  1524                 maskb <<= 1;
  1525                 datab <<= 1;
  1526                 dst += dstbpp;
  1527             }
  1528             dst += dstskip;
  1529         }
  1530     } else {
  1531         for (h = area->h; h; h--) {
  1532             for (x = 0; x < SDL_cursor->area.w; ++x) {
  1533                 if ((x % 8) == 0) {
  1534                     maskb = *mask++;
  1535                     datab = *data++;
  1536                 }
  1537                 if ((x >= minx) && (x < maxx)) {
  1538                     if (maskb & 0x80) {
  1539                         SDL_memset(dst, pixels[datab >> 7], dstbpp);
  1540                     }
  1541                 }
  1542                 maskb <<= 1;
  1543                 datab <<= 1;
  1544                 dst += dstbpp;
  1545             }
  1546             dst += dstskip;
  1547         }
  1548     }
  1549 }
  1550 
  1551 /* This handles the ugly work of converting the saved cursor background from
  1552    the pixel format of the shadow surface to that of the video surface.
  1553    This is only necessary when blitting from a shadow surface of a different
  1554    pixel format than the video surface, and using a software rendered cursor.
  1555 */
  1556 static void
  1557 SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
  1558 {
  1559     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1560     SDL_BlitInfo info;
  1561     SDL_loblit RunBlit;
  1562 
  1563     /* Make sure we can steal the blit mapping */
  1564     if (screen->map->dst != SDL_VideoSurface) {
  1565         return;
  1566     }
  1567 
  1568     /* Set up the blit information */
  1569     info.s_pixels = SDL_cursor->save[1];
  1570     info.s_width = w;
  1571     info.s_height = h;
  1572     info.s_skip = 0;
  1573     info.d_pixels = SDL_cursor->save[0];
  1574     info.d_width = w;
  1575     info.d_height = h;
  1576     info.d_skip = 0;
  1577     info.aux_data = screen->map->sw_data->aux_data;
  1578     info.src = screen->format;
  1579     info.table = screen->map->table;
  1580     info.dst = SDL_VideoSurface->format;
  1581     RunBlit = screen->map->sw_data->blit;
  1582 
  1583     /* Run the actual software blit */
  1584     RunBlit(&info);
  1585 }
  1586 
  1587 void
  1588 SDL_DrawCursorNoLock(SDL_Surface * screen)
  1589 {
  1590     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1591     SDL_Rect area;
  1592 
  1593     /* Get the mouse rectangle, clipped to the screen */
  1594     SDL_MouseRect(&area);
  1595     if ((area.w == 0) || (area.h == 0)) {
  1596         return;
  1597     }
  1598 
  1599     /* Copy mouse background */
  1600     {
  1601         int w, h, screenbpp;
  1602         Uint8 *src, *dst;
  1603 
  1604         /* Set up the copy pointers */
  1605         screenbpp = screen->format->BytesPerPixel;
  1606         if ((screen == SDL_VideoSurface) ||
  1607             FORMAT_EQUAL(screen->format, SDL_VideoSurface->format)) {
  1608             dst = SDL_cursor->save[0];
  1609         } else {
  1610             dst = SDL_cursor->save[1];
  1611         }
  1612         src = (Uint8 *) screen->pixels + area.y * screen->pitch +
  1613             area.x * screenbpp;
  1614 
  1615         /* Perform the copy */
  1616         w = area.w * screenbpp;
  1617         h = area.h;
  1618         while (h--) {
  1619             SDL_memcpy(dst, src, w);
  1620             dst += w;
  1621             src += screen->pitch;
  1622         }
  1623     }
  1624 
  1625     /* Draw the mouse cursor */
  1626     area.x -= SDL_cursor->area.x;
  1627     area.y -= SDL_cursor->area.y;
  1628     if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
  1629         SDL_DrawCursorFast(screen, &area);
  1630     } else {
  1631         SDL_DrawCursorSlow(screen, &area);
  1632     }
  1633 }
  1634 
  1635 void
  1636 SDL_DrawCursor(SDL_Surface * screen)
  1637 {
  1638     /* Lock the screen if necessary */
  1639     if (screen == NULL) {
  1640         return;
  1641     }
  1642     if (SDL_MUSTLOCK(screen)) {
  1643         if (SDL_LockSurface(screen) < 0) {
  1644             return;
  1645         }
  1646     }
  1647 
  1648     SDL_DrawCursorNoLock(screen);
  1649 
  1650     /* Unlock the screen and update if necessary */
  1651     if (SDL_MUSTLOCK(screen)) {
  1652         SDL_UnlockSurface(screen);
  1653     }
  1654     if (screen->flags & SDL_SCREEN_SURFACE) {
  1655         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1656         SDL_Window *window;
  1657         SDL_Rect area;
  1658 
  1659         window = SDL_GetWindowFromSurface(screen);
  1660         if (!window) {
  1661             return;
  1662         }
  1663 
  1664         SDL_MouseRect(&area);
  1665 
  1666         if (_this->UpdateWindowSurface) {
  1667             _this->UpdateWindowSurface(_this, window, 1, &area);
  1668         }
  1669     }
  1670 }
  1671 
  1672 void
  1673 SDL_EraseCursorNoLock(SDL_Surface * screen)
  1674 {
  1675     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1676     SDL_Window *window;
  1677     SDL_Rect area;
  1678 
  1679     /* Get the window associated with the surface */
  1680     window = SDL_GetWindowFromSurface(screen);
  1681     if (!window || !window->surface) {
  1682         return;
  1683     }
  1684 
  1685     /* Get the mouse rectangle, clipped to the screen */
  1686     SDL_MouseRect(&area);
  1687     if ((area.w == 0) || (area.h == 0)) {
  1688         return;
  1689     }
  1690 
  1691     /* Copy mouse background */
  1692     {
  1693         int w, h, screenbpp;
  1694         Uint8 *src, *dst;
  1695 
  1696         /* Set up the copy pointers */
  1697         screenbpp = screen->format->BytesPerPixel;
  1698         if ((screen->flags & SDL_SCREEN_SURFACE) ||
  1699             FORMAT_EQUAL(screen->format, window->surface->format)) {
  1700             src = SDL_cursor->save[0];
  1701         } else {
  1702             src = SDL_cursor->save[1];
  1703         }
  1704         dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
  1705             area.x * screenbpp;
  1706 
  1707         /* Perform the copy */
  1708         w = area.w * screenbpp;
  1709         h = area.h;
  1710         while (h--) {
  1711             SDL_memcpy(dst, src, w);
  1712             src += w;
  1713             dst += screen->pitch;
  1714         }
  1715 
  1716         /* Perform pixel conversion on cursor background */
  1717         if (src > SDL_cursor->save[1]) {
  1718             SDL_ConvertCursorSave(screen, area.w, area.h);
  1719         }
  1720     }
  1721 }
  1722 
  1723 void
  1724 SDL_EraseCursor(SDL_Surface * screen)
  1725 {
  1726     /* Lock the screen if necessary */
  1727     if (screen == NULL) {
  1728         return;
  1729     }
  1730     if (SDL_MUSTLOCK(screen)) {
  1731         if (SDL_LockSurface(screen) < 0) {
  1732             return;
  1733         }
  1734     }
  1735 
  1736     SDL_EraseCursorNoLock(screen);
  1737 
  1738     /* Unlock the screen and update if necessary */
  1739     if (SDL_MUSTLOCK(screen)) {
  1740         SDL_UnlockSurface(screen);
  1741     }
  1742     if (screen->flags & SDL_SCREEN_SURFACE) {
  1743         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1744         SDL_Window *window;
  1745         SDL_Rect area;
  1746 
  1747         window = SDL_GetWindowFromSurface(screen);
  1748         if (!window) {
  1749             return;
  1750         }
  1751 
  1752         SDL_MouseRect(&area);
  1753 
  1754         if (_this->UpdateWindowSurface) {
  1755             _this->UpdateWindowSurface(_this, window, 1, &area);
  1756         }
  1757     }
  1758 }
  1759 
  1760 /* Reset the cursor on video mode change
  1761    FIXME:  Keep track of all cursors, and reset them all.
  1762  */
  1763 void
  1764 SDL_ResetCursor(void)
  1765 {
  1766     int savelen;
  1767 
  1768     if (SDL_cursor) {
  1769         savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
  1770         SDL_cursor->area.x = 0;
  1771         SDL_cursor->area.y = 0;
  1772         SDL_memset(SDL_cursor->save[0], 0, savelen);
  1773     }
  1774 }
  1775 #endif
  1776 
  1777 struct private_yuvhwdata
  1778 {
  1779     SDL_SW_YUVTexture *texture;
  1780     SDL_Surface *display;
  1781     Uint32 display_format;
  1782 };
  1783 
  1784 SDL_Overlay *
  1785 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
  1786 {
  1787     SDL_Overlay *overlay;
  1788     Uint32 texture_format;
  1789     SDL_SW_YUVTexture *texture;
  1790 
  1791     if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
  1792         SDL_SetError("YUV overlays are not supported in OpenGL mode");
  1793         return NULL;
  1794     }
  1795 
  1796     if (display != SDL_PublicSurface) {
  1797         SDL_SetError("YUV display is only supported on the screen surface");
  1798         return NULL;
  1799     }
  1800 
  1801     switch (format) {
  1802     case SDL_YV12_OVERLAY:
  1803         texture_format = SDL_PIXELFORMAT_YV12;
  1804         break;
  1805     case SDL_IYUV_OVERLAY:
  1806         texture_format = SDL_PIXELFORMAT_IYUV;
  1807         break;
  1808     case SDL_YUY2_OVERLAY:
  1809         texture_format = SDL_PIXELFORMAT_YUY2;
  1810         break;
  1811     case SDL_UYVY_OVERLAY:
  1812         texture_format = SDL_PIXELFORMAT_UYVY;
  1813         break;
  1814     case SDL_YVYU_OVERLAY:
  1815         texture_format = SDL_PIXELFORMAT_YVYU;
  1816         break;
  1817     default:
  1818         SDL_SetError("Unknown YUV format");
  1819         return NULL;
  1820     }
  1821 
  1822     overlay = (SDL_Overlay *) SDL_malloc(sizeof(*overlay));
  1823     if (!overlay) {
  1824         SDL_OutOfMemory();
  1825         return NULL;
  1826     }
  1827     SDL_zerop(overlay);
  1828 
  1829     overlay->hwdata =
  1830         (struct private_yuvhwdata *) SDL_malloc(sizeof(*overlay->hwdata));
  1831     if (!overlay->hwdata) {
  1832         SDL_free(overlay);
  1833         SDL_OutOfMemory();
  1834         return NULL;
  1835     }
  1836 
  1837     texture = SDL_SW_CreateYUVTexture(texture_format, w, h);
  1838     if (!texture) {
  1839         SDL_free(overlay->hwdata);
  1840         SDL_free(overlay);
  1841         return NULL;
  1842     }
  1843     overlay->hwdata->texture = texture;
  1844     overlay->hwdata->display = NULL;
  1845     overlay->hwdata->display_format = SDL_PIXELFORMAT_UNKNOWN;
  1846 
  1847     overlay->format = format;
  1848     overlay->w = w;
  1849     overlay->h = h;
  1850     if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
  1851         overlay->planes = 3;
  1852     } else {
  1853         overlay->planes = 1;
  1854     }
  1855     overlay->pitches = texture->pitches;
  1856     overlay->pixels = texture->planes;
  1857 
  1858     return overlay;
  1859 }
  1860 
  1861 int
  1862 SDL_LockYUVOverlay(SDL_Overlay * overlay)
  1863 {
  1864     SDL_Rect rect;
  1865     void *pixels;
  1866     int pitch;
  1867 
  1868     if (!overlay) {
  1869         SDL_SetError("Passed a NULL overlay");
  1870         return -1;
  1871     }
  1872 
  1873     rect.x = 0;
  1874     rect.y = 0;
  1875     rect.w = overlay->w;
  1876     rect.h = overlay->h;
  1877 
  1878     if (SDL_SW_LockYUVTexture(overlay->hwdata->texture, &rect, &pixels, &pitch) < 0) {
  1879         return -1;
  1880     }
  1881 
  1882     overlay->pixels[0] = (Uint8 *) pixels;
  1883     overlay->pitches[0] = pitch;
  1884     switch (overlay->format) {
  1885     case SDL_YV12_OVERLAY:
  1886     case SDL_IYUV_OVERLAY:
  1887         overlay->pitches[1] = pitch / 2;
  1888         overlay->pitches[2] = pitch / 2;
  1889         overlay->pixels[1] =
  1890             overlay->pixels[0] + overlay->pitches[0] * overlay->h;
  1891         overlay->pixels[2] =
  1892             overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
  1893         break;
  1894     case SDL_YUY2_OVERLAY:
  1895     case SDL_UYVY_OVERLAY:
  1896     case SDL_YVYU_OVERLAY:
  1897         break;
  1898     }
  1899     return 0;
  1900 }
  1901 
  1902 void
  1903 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
  1904 {
  1905     if (!overlay) {
  1906         return;
  1907     }
  1908 
  1909     SDL_SW_UnlockYUVTexture(overlay->hwdata->texture);
  1910 }
  1911 
  1912 int
  1913 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
  1914 {
  1915     SDL_Surface *display;
  1916     SDL_Rect src_rect;
  1917     SDL_Rect dst_rect;
  1918     void *pixels;
  1919 
  1920     if (!overlay || !dstrect) {
  1921         SDL_SetError("Passed a NULL overlay or dstrect");
  1922         return -1;
  1923     }
  1924 
  1925     display = overlay->hwdata->display;
  1926     if (display != SDL_VideoSurface) {
  1927         overlay->hwdata->display = display = SDL_VideoSurface;
  1928         overlay->hwdata->display_format = SDL_MasksToPixelFormatEnum(
  1929                                                 display->format->BitsPerPixel,
  1930                                                 display->format->Rmask,
  1931                                                 display->format->Gmask,
  1932                                                 display->format->Bmask,
  1933                                                 display->format->Amask);
  1934     }
  1935 
  1936     src_rect.x = 0;
  1937     src_rect.y = 0;
  1938     src_rect.w = overlay->w;
  1939     src_rect.h = overlay->h;
  1940 
  1941     if (!SDL_IntersectRect(&display->clip_rect, dstrect, &dst_rect)) {
  1942         return 0;
  1943     }
  1944      
  1945     pixels = (void *)((Uint8 *)display->pixels +
  1946                         dst_rect.y * display->pitch +
  1947                         dst_rect.x * display->format->BytesPerPixel);
  1948 
  1949     if (SDL_SW_CopyYUVToRGB(overlay->hwdata->texture, &src_rect,
  1950                             overlay->hwdata->display_format,
  1951                             dst_rect.w, dst_rect.h,
  1952                             pixels, display->pitch) < 0) {
  1953         return -1;
  1954     }
  1955     SDL_UpdateWindowSurface(SDL_VideoWindow);
  1956     return 0;
  1957 }
  1958 
  1959 void
  1960 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
  1961 {
  1962     if (!overlay) {
  1963         return;
  1964     }
  1965     if (overlay->hwdata) {
  1966         if (overlay->hwdata->texture) {
  1967             SDL_SW_DestroyYUVTexture(overlay->hwdata->texture);
  1968         }
  1969         SDL_free(overlay->hwdata);
  1970     }
  1971     SDL_free(overlay);
  1972 }
  1973 
  1974 void
  1975 SDL_GL_SwapBuffers(void)
  1976 {
  1977     SDL_GL_SwapWindow(SDL_VideoWindow);
  1978 }
  1979 
  1980 int
  1981 SDL_SetGamma(float red, float green, float blue)
  1982 {
  1983     Uint16 red_ramp[256];
  1984     Uint16 green_ramp[256];
  1985     Uint16 blue_ramp[256];
  1986 
  1987     SDL_CalculateGammaRamp(red, red_ramp);
  1988     if (green == red) {
  1989         SDL_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  1990     } else {
  1991         SDL_CalculateGammaRamp(green, green_ramp);
  1992     }
  1993     if (blue == red) {
  1994         SDL_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  1995     } else {
  1996         SDL_CalculateGammaRamp(blue, blue_ramp);
  1997     }
  1998     return SDL_SetWindowGammaRamp(SDL_VideoWindow, red_ramp, green_ramp, blue_ramp);
  1999 }
  2000 
  2001 int
  2002 SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, const Uint16 * blue)
  2003 {
  2004     return SDL_SetWindowGammaRamp(SDL_VideoWindow, red, green, blue);
  2005 }
  2006 
  2007 int
  2008 SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue)
  2009 {
  2010     return SDL_GetWindowGammaRamp(SDL_VideoWindow, red, green, blue);
  2011 }
  2012 
  2013 int
  2014 SDL_EnableKeyRepeat(int delay, int interval)
  2015 {
  2016     return 0;
  2017 }
  2018 
  2019 void
  2020 SDL_GetKeyRepeat(int *delay, int *interval)
  2021 {
  2022     if (delay) {
  2023         *delay = SDL_DEFAULT_REPEAT_DELAY;
  2024     }
  2025     if (interval) {
  2026         *interval = SDL_DEFAULT_REPEAT_INTERVAL;
  2027     }
  2028 }
  2029 
  2030 int
  2031 SDL_EnableUNICODE(int enable)
  2032 {
  2033     int previous = SDL_enabled_UNICODE;
  2034 
  2035     switch (enable) {
  2036     case 1:
  2037         SDL_enabled_UNICODE = 1;
  2038         SDL_StartTextInput();
  2039         break;
  2040     case 0:
  2041         SDL_enabled_UNICODE = 0;
  2042         SDL_StopTextInput();
  2043         break;
  2044     }
  2045     return previous;
  2046 }
  2047 
  2048 static Uint32
  2049 SDL_SetTimerCallback(Uint32 interval, void* param)
  2050 {
  2051     return ((SDL_OldTimerCallback)param)(interval);
  2052 }
  2053 
  2054 int
  2055 SDL_SetTimer(Uint32 interval, SDL_OldTimerCallback callback)
  2056 {
  2057     static SDL_TimerID compat_timer;
  2058 
  2059     if (compat_timer) {
  2060         SDL20_RemoveTimer(compat_timer);
  2061         compat_timer = 0;
  2062     }
  2063 
  2064     if (interval && callback) {
  2065         compat_timer = SDL20_AddTimer(interval, SDL_SetTimerCallback, callback);
  2066         if (!compat_timer) {
  2067             return -1;
  2068         }
  2069     }
  2070     return 0;
  2071 }
  2072 
  2073 int
  2074 SDL_putenv(const char *_var)
  2075 {
  2076     char *ptr = NULL;
  2077     char *var = SDL_strdup(_var);
  2078     if (var == NULL) {
  2079         return -1;  /* we don't set errno. */
  2080     }
  2081 
  2082     ptr = SDL_strchr(var, '=');
  2083     if (ptr == NULL) {
  2084         SDL_free(var);
  2085         return -1;
  2086     }
  2087 
  2088     *ptr = '\0';  /* split the string into name and value. */
  2089     SDL_setenv(var, ptr + 1, 1);
  2090     SDL_free(var);
  2091     return 0;
  2092 }
  2093 
  2094 
  2095 
  2096 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2097 
  2098 typedef void *SDL12_CD;  /* close enough.  :) */
  2099 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2100 
  2101 static int
  2102 CDUnsupported(void)
  2103 {
  2104     SDL_SetError("CD interface is unsupported");
  2105     return -1;
  2106 }
  2107 
  2108 int
  2109 SDL_CDNumDrives(void)
  2110 {
  2111     return 0;  /* !!! FIXME: should return -1 without SDL_INIT_CDROM */
  2112 }
  2113 
  2114 const char *SDL_CDName(int drive) { CDUnsupported(); return NULL; }
  2115 SDL12_CD * SDL_CDOpen(int drive) { CDUnsupported(); return NULL; }
  2116 SDL12_CDstatus SDL_CDStatus(SDL_CD *cdrom) { return CDUnsupported(); }
  2117 int SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return CDUnsupported(); }
  2118 int SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return CDUnsupported(); }
  2119 int SDL_CDPause(SDL12_CD *cdrom) { return CDUnsupported(); }
  2120 int SDL_CDResume(SDL12_CD *cdrom) { return CDUnsupported(); }
  2121 int SDL_CDStop(SDL12_CD *cdrom) { return CDUnsupported(); }
  2122 int SDL_CDEject(SDL12_CD *cdrom) { return CDUnsupported(); }
  2123 void SDL_CDClose(SDL12_CD *cdrom) {}
  2124 
  2125 /* !!! FIXME: Removed from 2.0; do nothing. We can't even report failure. */
  2126 void SDL_KillThread(SDL_Thread *thread) {}
  2127 
  2128 /* This changed from an opaque pointer to an int in 2.0. */
  2129 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2130 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2131 
  2132 SDL12_TimerID
  2133 SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param)
  2134 {
  2135     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2136 }
  2137 
  2138 SDL_bool
  2139 SDL_RemoveTimer(SDL12_TimerID id)
  2140 {
  2141     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2142 }
  2143 
  2144 
  2145 typedef struct SDL12_RWops {
  2146     int (SDLCALL *seek)(struct SDL_RWops *context, int offset, int whence);
  2147     int (SDLCALL *read)(struct SDL_RWops *context, void *ptr, int size, int maxnum);
  2148     int (SDLCALL *write)(struct SDL_RWops *context, const void *ptr, int size, int num);
  2149     int (SDLCALL *close)(struct SDL_RWops *context);
  2150     Uint32 type;
  2151     void *padding[8];
  2152     SDL_RWops *rwops20;
  2153 } SDL12_RWops;
  2154 
  2155 
  2156 SDL12_RWops *
  2157 SDL_AllocRW(void)
  2158 {
  2159     SDL12_RWops *rwops = (SDL12_RWops *) SDL_malloc(sizeof (SDL12_RWops));
  2160     if (!rwops)
  2161         SDL20_OutOfMemory();
  2162     return rwops;
  2163 }
  2164 
  2165 void
  2166 SDL_FreeRW(SDL12_RWops *rwops12)
  2167 {
  2168     SDL_free(rwops12);
  2169 }
  2170 
  2171 static int SDLCALL
  2172 WrapRWops_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  2173 {
  2174     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  2175 }
  2176 
  2177 static int SDLCALL
  2178 WrapRWops_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  2179 {
  2180     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  2181 }
  2182 
  2183 static int SDLCALL
  2184 WrapRWops_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  2185 {
  2186     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  2187 }
  2188 
  2189 static int SDLCALL
  2190 WrapRWops_close(struct SDL12_RWops *rwops12)
  2191 {
  2192     int rc = 0;
  2193     if (rwops12)
  2194     {
  2195         rc = rwops12->rwops20->close(rwops12->rwops20);
  2196         if (rc == 0)
  2197             SDL_FreeRW(rwops12);
  2198     }
  2199     return rc;
  2200 }
  2201 
  2202 static SDL12_RWops *
  2203 WrapRWops(SDL12_RWops *rwops12, SDL_RWops *rwops20)
  2204 {
  2205     if (!rwops20)
  2206     {
  2207         SDL_FreeRW(rwops12);
  2208         return NULL;
  2209     }
  2210     SDL_zerop(rwops12);
  2211     rwops12->type = rwops20->type;
  2212     rwops12->rwops20 = rwops20;
  2213     rwops12->seek = WrapRWops_seek;
  2214     rwops12->read = WrapRWops_read;
  2215     rwops12->write = WrapRWops_write;
  2216     rwops12->close = WrapRWops_close;
  2217 }
  2218 
  2219 SDL12_RWops *
  2220 SDL_RWFromFile(const char *file, const char *mode)
  2221 {
  2222     SDL12_RWops *rwops12 = SDL_AllocRW();
  2223     return rwops12 ? WrapRWops(rwops12, SDL20_RWFromFile(file, mode)) : NULL;
  2224 }
  2225 
  2226 SDL12_RWops *
  2227 SDL_RWFromFP(FILE *io, int autoclose)
  2228 {
  2229     SDL12_RWops *rwops12 = SDL_AllocRW();
  2230     return rwops12 ? WrapRWops(rwops12, SDL20_RWFromFP(io, autoclose)) : NULL;
  2231 }
  2232 
  2233 SDL12_RWops *
  2234 SDL_RWFromMem(void *mem, int size)
  2235 {
  2236     SDL12_RWops *rwops12 = SDL_AllocRW();
  2237     return rwops12 ? WrapRWops(rwops12, SDL20_RWFromMem(mem, size)) : NULL;
  2238 }
  2239 
  2240 SDL12_RWops *
  2241 SDL_RWFromConstMem(const void *mem, int size)
  2242 {
  2243     SDL12_RWops *rwops12 = SDL_AllocRW();
  2244     return rwops12 ? WrapRWops(rwops12, SDL20_RWFromConstMem(mem, size)) : NULL;
  2245 }
  2246 
  2247 #define READ_AND_BYTESWAP(endian, bits) \
  2248     Uint##bits SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  2249         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  2250         return SDL_Swap##endian##bits(val); \
  2251     }
  2252 
  2253 READ_AND_BYTESWAP(LE,16)
  2254 READ_AND_BYTESWAP(BE,16)
  2255 READ_AND_BYTESWAP(LE,32)
  2256 READ_AND_BYTESWAP(BE,32)
  2257 READ_AND_BYTESWAP(LE,64)
  2258 READ_AND_BYTESWAP(BE,64)
  2259 #undef READ_AND_BYTESWAP
  2260 
  2261 #define BYTESWAP_AND_WRITE(endian, bits) \
  2262     int SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##endian##bits val) { \
  2263         val = SDL_Swap##endian##bits(val); \
  2264         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  2265     }
  2266 BYTESWAP_AND_WRITE(LE,16)
  2267 BYTESWAP_AND_WRITE(BE,16)
  2268 BYTESWAP_AND_WRITE(LE,32)
  2269 BYTESWAP_AND_WRITE(BE,32)
  2270 BYTESWAP_AND_WRITE(LE,64)
  2271 BYTESWAP_AND_WRITE(BE,64)
  2272 #undef BYTESWAP_AND_WRITE
  2273 
  2274 /* Things that _should_ be binary compatible pass right through... */
  2275 #define SDL20_SYM(rc,fn,params,args,ret)
  2276 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
  2277     rc SDL_##fn params { ret SDL20_##fn args; }
  2278 #include "SDL20_syms.h"
  2279 #undef SDL20_SYM_PASSTHROUGH
  2280 #undef SDL20_SYM
  2281 
  2282 /* vi: set ts=4 sw=4 expandtab: */