Forráskód Böngészése

locale: Implemented SDL_GetPreferredLocales().

This was something I proposed a long time ago, Sylvain Becker did
additional work on it, then back to me.

Fixes Bugzilla #2131.
Ryan C. Gordon 5 éve
szülő
commit
fa23e3d00b
42 módosított fájl, 1318 hozzáadás és 4 törlés
  1. 2 0
      Android.mk
  2. 43 1
      CMakeLists.txt
  3. 1 0
      Makefile.in
  4. 3 1
      Makefile.os2
  5. 4 0
      VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj
  6. 12 0
      VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj.filters
  7. 4 0
      VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj
  8. 12 0
      VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters
  9. 4 0
      VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj
  10. 12 0
      VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters
  11. 4 0
      VisualC/SDL/SDL.vcxproj
  12. 6 0
      VisualC/SDL/SDL.vcxproj.filters
  13. 57 0
      Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
  14. 64 0
      Xcode/SDL/SDL.xcodeproj/project.pbxproj
  15. 42 1
      configure
  16. 29 0
      configure.ac
  17. 1 0
      include/SDL.h
  18. 2 0
      include/SDL_events.h
  19. 15 0
      include/SDL_hints.h
  20. 101 0
      include/SDL_locale.h
  21. 78 0
      src/core/android/SDL_android.c
  22. 3 0
      src/core/android/SDL_android.h
  23. 1 0
      src/dynapi/SDL_dynapi_overrides.h
  24. 1 0
      src/dynapi/SDL_dynapi_procs.h
  25. 6 0
      src/events/SDL_events.c
  26. 1 0
      src/events/SDL_events_c.h
  27. 103 0
      src/locale/SDL_locale.c
  28. 29 0
      src/locale/SDL_syslocale.h
  29. 32 0
      src/locale/android/SDL_syslocale.c
  30. 33 0
      src/locale/dummy/SDL_syslocale.c
  31. 72 0
      src/locale/emscripten/SDL_syslocale.c
  32. 75 0
      src/locale/haiku/SDL_syslocale.cc
  33. 76 0
      src/locale/macosx/SDL_syslocale.m
  34. 110 0
      src/locale/unix/SDL_syslocale.c
  35. 119 0
      src/locale/windows/SDL_syslocale.c
  36. 58 0
      src/locale/winrt/SDL_syslocale.c
  37. 5 0
      src/main/haiku/SDL_BApp.h
  38. 12 0
      src/video/cocoa/SDL_cocoaevents.m
  39. 5 0
      test/Makefile.in
  40. 1 0
      test/README
  41. 13 1
      test/configure
  42. 67 0
      test/testlocale.c

+ 2 - 0
Android.mk

@@ -35,6 +35,8 @@ LOCAL_SRC_FILES := \
 	$(wildcard $(LOCAL_PATH)/src/joystick/hidapi/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/joystick/virtual/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \
+	$(wildcard $(LOCAL_PATH)/src/locale/*.c) \
+	$(wildcard $(LOCAL_PATH)/src/locale/android/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/power/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/power/android/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/filesystem/android/*.c) \

+ 43 - 1
CMakeLists.txt

@@ -307,7 +307,7 @@ endif()
 
 set(SDL_SUBSYSTEMS
     Atomic Audio Video Render Events Joystick Haptic Power Threads Timers
-    File Loadso CPUinfo Filesystem Dlopen Sensor)
+    File Loadso CPUinfo Filesystem Dlopen Sensor Locale)
 foreach(_SUB ${SDL_SUBSYSTEMS})
   string(TOUPPER ${_SUB} _OPT)
   if (NOT DEFINED SDL_${_OPT}_ENABLED_BY_DEFAULT)
@@ -404,6 +404,7 @@ file(GLOB SOURCE_FILES
   ${SDL2_SOURCE_DIR}/src/events/*.c
   ${SDL2_SOURCE_DIR}/src/file/*.c
   ${SDL2_SOURCE_DIR}/src/libm/*.c
+  ${SDL2_SOURCE_DIR}/src/locale/*.c
   ${SDL2_SOURCE_DIR}/src/render/*.c
   ${SDL2_SOURCE_DIR}/src/render/*/*.c
   ${SDL2_SOURCE_DIR}/src/stdlib/*.c
@@ -885,6 +886,8 @@ if(SDL_POWER)
   file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/*.c)
   set(SOURCE_FILES ${SOURCE_FILES} ${POWER_SOURCES})
 endif()
+
+
 # TODO: in configure.ac, the test for LOADSO and SDL_DLOPEN is a bit weird:
 # if LOADSO is not wanted, SDL_LOADSO_DISABLED is set
 # If however on Unix or APPLE dlopen() is detected via CheckDLOPEN(),
@@ -993,6 +996,11 @@ if(ANDROID)
     set(SOURCE_FILES ${SOURCE_FILES} ${ANDROID_POWER_SOURCES})
     set(HAVE_SDL_POWER TRUE)
   endif()
+  if(SDL_LOCALE)
+    file(GLOB ANDROID_LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/android/*.c)
+    set(SOURCE_FILES ${SOURCE_FILES} ${ANDROID_LOCALE_SOURCES})
+    set(HAVE_SDL_LOCALE TRUE)
+  endif()
   if(SDL_TIMERS)
     set(SDL_TIMER_UNIX 1)
     file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c)
@@ -1083,6 +1091,11 @@ elseif(EMSCRIPTEN)
     set(SOURCE_FILES ${SOURCE_FILES} ${EM_POWER_SOURCES})
     set(HAVE_SDL_POWER TRUE)
   endif()
+  if(SDL_LOCALE)
+    file(GLOB LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/emscripten/*.c)
+    set(SOURCE_FILES ${SOURCE_FILES} ${LOCALE_SOURCES})
+    set(HAVE_SDL_LOCALE TRUE)
+  endif()
   if(SDL_TIMERS)
     set(SDL_TIMER_UNIX 1)
     file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c)
@@ -1272,6 +1285,12 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS)
     endif()
   endif()
 
+  if(SDL_LOCALE)
+    file(GLOB LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/unix/*.c)
+    set(SOURCE_FILES ${SOURCE_FILES} ${LOCALE_SOURCES})
+    set(HAVE_SDL_LOCALE TRUE)
+  endif()
+
   if(SDL_FILESYSTEM)
     set(SDL_FILESYSTEM_UNIX 1)
     file(GLOB FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/unix/*.c)
@@ -1438,6 +1457,12 @@ elseif(WINDOWS)
     set(HAVE_SDL_POWER TRUE)
   endif()
 
+  if(SDL_LOCALE)
+    file(GLOB LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/windows/*.c)
+    set(SOURCE_FILES ${SOURCE_FILES} ${LOCALE_SOURCES})
+    set(HAVE_SDL_LOCALE TRUE)
+  endif()
+
   if(SDL_FILESYSTEM)
     set(SDL_FILESYSTEM_WINDOWS 1)
     file(GLOB FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/windows/*.c)
@@ -1629,6 +1654,12 @@ elseif(APPLE)
     set(HAVE_SDL_POWER TRUE)
   endif()
 
+  if(SDL_LOCALE)
+    file(GLOB LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/macosx/*.m)
+    set(SOURCE_FILES ${SOURCE_FILES} ${LOCALE_SOURCES})
+    set(HAVE_SDL_LOCALE TRUE)
+  endif()
+
   if(SDL_TIMERS)
     set(SDL_TIMER_UNIX 1)
     file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c)
@@ -1837,6 +1868,12 @@ elseif(HAIKU)
     set(HAVE_SDL_TIMERS TRUE)
   endif()
 
+  if(SDL_LOCALE)
+    file(GLOB LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/haiku/*.cc)
+    set(SOURCE_FILES ${SOURCE_FILES} ${LOCALE_SOURCES})
+    set(HAVE_SDL_LOCALE TRUE)
+  endif()
+
   CheckPTHREAD()
 
 elseif(RISCOS)
@@ -1899,6 +1936,11 @@ if(NOT HAVE_SDL_FILESYSTEM)
   file(GLOB FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/dummy/*.c)
   set(SOURCE_FILES ${SOURCE_FILES} ${FILESYSTEM_SOURCES})
 endif()
+if(NOT HAVE_SDL_LOCALE)
+  set(SDL_LOCALE_DISABLED 1)
+  file(GLOB LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/dummy/*.c)
+  set(SOURCE_FILES ${SOURCE_FILES} ${LOCALE_SOURCES})
+endif()
 
 # We always need to have threads and timers around
 if(NOT HAVE_SDL_THREADS)

+ 1 - 0
Makefile.in

@@ -82,6 +82,7 @@ HDRS = \
 	SDL_keyboard.h \
 	SDL_keycode.h \
 	SDL_loadso.h \
+	SDL_locale.h \
 	SDL_log.h \
 	SDL_main.h \
 	SDL_messagebox.h \

+ 3 - 1
Makefile.os2

@@ -60,6 +60,8 @@ SRCS+= SDL_dummysensor.c
 
 SRCS+= SDL_dynapi.c
 
+SRCS+= SDL_locale.c SDL_syslocale.c
+
 OBJS = $(SRCS:.c=.obj)
 MOBJS= $(MSRCS:.c=.obj)
 
@@ -68,7 +70,7 @@ MOBJS= $(MSRCS:.c=.obj)
 
 .c: ./src;./src/dynapi;./src/audio;./src/cpuinfo;./src/events;./src/file;./src/haptic;./src/joystick;./src/power;./src/render;./src/render/software;./src/sensor;./src/stdlib;./src/thread;./src/timer;./src/video;./src/video/yuv2rgb;./src/atomic;./src/audio/disk;
 .c: ./src/haptic/dummy;./src/joystick/dummy;./src/audio/dummy;./src/video/dummy;./src/sensor/dummy;
-.c: ./src/loadso/dummy;./src/filesystem/dummy;./src/timer/dummy;./src/thread/generic;
+.c: ./src/loadso/dummy;./src/filesystem/dummy;./src/timer/dummy;./src/thread/generic;./src/locale/unix
 
 all: $(DLLFILE) $(LIBFILE) .symbolic
 

+ 4 - 0
VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj

@@ -52,6 +52,7 @@
     <ClInclude Include="..\..\include\SDL_keyboard.h" />
     <ClInclude Include="..\..\include\SDL_keycode.h" />
     <ClInclude Include="..\..\include\SDL_loadso.h" />
+    <ClInclude Include="..\..\include\SDL_locale.h" />
     <ClInclude Include="..\..\include\SDL_log.h" />
     <ClInclude Include="..\..\include\SDL_main.h" />
     <ClInclude Include="..\..\include\SDL_mouse.h" />
@@ -118,6 +119,7 @@
     <ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
     <ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h" />
     <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
+    <ClInclude Include="..\..\src\locale\SDL_syslocale.h" />
     <ClInclude Include="..\..\src\render\direct3d11\SDL_render_winrt.h" />
     <ClInclude Include="..\..\src\render\direct3d11\SDL_shaders_d3d11.h" />
     <ClInclude Include="..\..\src\render\opengles2\SDL_gles2funcs.h" />
@@ -249,6 +251,8 @@
     <ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
     <ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
+    <ClCompile Include="..\..\src\locale\SDL_locale.c" />
+    <ClCompile Include="..\..\src\locale\winrt\SDL_syslocale.c" />
     <ClCompile Include="..\..\src\power\SDL_power.c" />
     <ClCompile Include="..\..\src\power\winrt\SDL_syspower.cpp" />
     <ClCompile Include="..\..\src\render\direct3d11\SDL_render_d3d11.c" />

+ 12 - 0
VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj.filters

@@ -84,6 +84,9 @@
     <ClInclude Include="..\..\include\SDL_loadso.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\SDL_locale.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\SDL_log.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -321,6 +324,9 @@
     <ClInclude Include="..\..\src\SDL_internal.h">
       <Filter>Source Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\locale\SDL_syslocale.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\src\thread\SDL_systhread.h">
       <Filter>Source Files</Filter>
     </ClInclude>
@@ -614,6 +620,12 @@
     <ClCompile Include="..\..\src\SDL_log.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\locale\SDL_locale.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\locale\winrt\SDL_syslocale.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\stdlib\SDL_getenv.c">
       <Filter>Source Files</Filter>
     </ClCompile>

+ 4 - 0
VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj

@@ -44,6 +44,7 @@
     <ClInclude Include="..\..\include\SDL_keyboard.h" />
     <ClInclude Include="..\..\include\SDL_keycode.h" />
     <ClInclude Include="..\..\include\SDL_loadso.h" />
+    <ClInclude Include="..\..\include\SDL_locale.h" />
     <ClInclude Include="..\..\include\SDL_log.h" />
     <ClInclude Include="..\..\include\SDL_main.h" />
     <ClInclude Include="..\..\include\SDL_mouse.h" />
@@ -124,6 +125,7 @@
     <ClInclude Include="..\..\src\SDL_fatal.h" />
     <ClInclude Include="..\..\src\SDL_hints_c.h" />
     <ClInclude Include="..\..\src\SDL_internal.h" />
+    <ClInclude Include="..\..\src\locale\SDL_syslocale.h" />
     <ClInclude Include="..\..\src\sensor\dummy\SDL_dummysensor.h" />
     <ClInclude Include="..\..\src\sensor\SDL_sensor_c.h" />
     <ClInclude Include="..\..\src\sensor\SDL_syssensor.h" />
@@ -245,6 +247,8 @@
     <ClCompile Include="..\..\src\SDL_error.c" />
     <ClCompile Include="..\..\src\SDL_hints.c" />
     <ClCompile Include="..\..\src\SDL_log.c" />
+    <ClCompile Include="..\..\src\locale\SDL_locale.c" />
+    <ClCompile Include="..\..\src\locale\winrt\SDL_syslocale.c" />
     <ClCompile Include="..\..\src\sensor\dummy\SDL_dummysensor.c" />
     <ClCompile Include="..\..\src\sensor\SDL_sensor.c" />
     <ClCompile Include="..\..\src\stdlib\SDL_getenv.c" />

+ 12 - 0
VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters

@@ -84,6 +84,9 @@
     <ClInclude Include="..\..\include\SDL_loadso.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\SDL_locale.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\SDL_log.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -306,6 +309,9 @@
     <ClInclude Include="..\..\src\SDL_internal.h">
       <Filter>Source Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\locale\SDL_syslocale.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\src\thread\SDL_systhread.h">
       <Filter>Source Files</Filter>
     </ClInclude>
@@ -578,6 +584,12 @@
     <ClCompile Include="..\..\src\SDL_log.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\locale\SDL_locale.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\locale\winrt\SDL_syslocale.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\stdlib\SDL_getenv.c">
       <Filter>Source Files</Filter>
     </ClCompile>

+ 4 - 0
VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj

@@ -52,6 +52,7 @@
     <ClInclude Include="..\..\include\SDL_keyboard.h" />
     <ClInclude Include="..\..\include\SDL_keycode.h" />
     <ClInclude Include="..\..\include\SDL_loadso.h" />
+    <ClInclude Include="..\..\include\SDL_locale.h" />
     <ClInclude Include="..\..\include\SDL_log.h" />
     <ClInclude Include="..\..\include\SDL_main.h" />
     <ClInclude Include="..\..\include\SDL_mouse.h" />
@@ -139,6 +140,7 @@
     <ClInclude Include="..\..\src\SDL_fatal.h" />
     <ClInclude Include="..\..\src\SDL_hints_c.h" />
     <ClInclude Include="..\..\src\SDL_internal.h" />
+    <ClInclude Include="..\..\src\locale\SDL_syslocale.h" />
     <ClInclude Include="..\..\src\sensor\dummy\SDL_dummysensor.h" />
     <ClInclude Include="..\..\src\sensor\SDL_sensor_c.h" />
     <ClInclude Include="..\..\src\sensor\SDL_syssensor.h" />
@@ -277,6 +279,8 @@
     <ClCompile Include="..\..\src\SDL_error.c" />
     <ClCompile Include="..\..\src\SDL_hints.c" />
     <ClCompile Include="..\..\src\SDL_log.c" />
+    <ClInclude Include="..\..\src\locale\SDL_locale.c" />
+    <ClInclude Include="..\..\src\locale\winrt\SDL_syslocale.c" />
     <ClCompile Include="..\..\src\sensor\dummy\SDL_dummysensor.c" />
     <ClCompile Include="..\..\src\sensor\SDL_sensor.c" />
     <ClCompile Include="..\..\src\stdlib\SDL_getenv.c" />

+ 12 - 0
VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters

@@ -84,6 +84,9 @@
     <ClInclude Include="..\..\include\SDL_loadso.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\SDL_locale.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\SDL_log.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -306,6 +309,9 @@
     <ClInclude Include="..\..\src\SDL_internal.h">
       <Filter>Source Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\locale\SDL_syslocale.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\src\thread\SDL_thread_c.h">
       <Filter>Source Files</Filter>
     </ClInclude>
@@ -596,6 +602,12 @@
     <ClCompile Include="..\..\src\SDL_log.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\locale\SDL_locale.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\locale\winrt\SDL_syslocale.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\stdlib\SDL_getenv.c">
       <Filter>Source Files</Filter>
     </ClCompile>

+ 4 - 0
VisualC/SDL/SDL.vcxproj

@@ -239,6 +239,7 @@
     <ClInclude Include="..\..\include\SDL_keyboard.h" />
     <ClInclude Include="..\..\include\SDL_keycode.h" />
     <ClInclude Include="..\..\include\SDL_loadso.h" />
+    <ClInclude Include="..\..\include\SDL_locale.h" />
     <ClInclude Include="..\..\include\SDL_log.h" />
     <ClInclude Include="..\..\include\SDL_main.h" />
     <ClInclude Include="..\..\include\SDL_messagebox.h" />
@@ -331,6 +332,7 @@
     <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
     <ClInclude Include="..\..\src\libm\math_libm.h" />
     <ClInclude Include="..\..\src\libm\math_private.h" />
+    <ClInclude Include="..\..\src\locale\SDL_syslocale.h" />
     <ClInclude Include="..\..\src\render\direct3d11\SDL_shaders_d3d11.h" />
     <ClInclude Include="..\..\src\render\direct3d\SDL_shaders_d3d.h" />
     <ClInclude Include="..\..\src\render\opengl\SDL_glfuncs.h" />
@@ -463,6 +465,8 @@
     <ClCompile Include="..\..\src\libm\s_sin.c" />
     <ClCompile Include="..\..\src\libm\s_tan.c" />
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
+    <ClCompile Include="..\..\src\locale\SDL_locale.c" />
+    <ClCompile Include="..\..\src\locale\windows\SDL_syslocale.c" />
     <ClCompile Include="..\..\src\power\SDL_power.c" />
     <ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
     <ClCompile Include="..\..\src\render\direct3d11\SDL_shaders_d3d11.c" />

+ 6 - 0
VisualC/SDL/SDL.vcxproj.filters

@@ -84,6 +84,9 @@
     <ClInclude Include="..\..\include\SDL_loadso.h">
       <Filter>API Headers</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\SDL_locale.h">
+      <Filter>API Headers</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\SDL_log.h">
       <Filter>API Headers</Filter>
     </ClInclude>
@@ -269,6 +272,7 @@
     <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
     <ClInclude Include="..\..\src\libm\math_libm.h" />
     <ClInclude Include="..\..\src\libm\math_private.h" />
+    <ClInclude Include="..\..\src\locale\SDL_syslocale.h" />
     <ClInclude Include="..\..\src\render\direct3d\SDL_shaders_d3d.h" />
     <ClInclude Include="..\..\src\render\direct3d11\SDL_shaders_d3d11.h" />
     <ClInclude Include="..\..\src\render\opengl\SDL_glfuncs.h" />
@@ -401,6 +405,8 @@
     <ClCompile Include="..\..\src\libm\s_sin.c" />
     <ClCompile Include="..\..\src\libm\s_tan.c" />
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
+    <ClCompile Include="..\..\src\locale\SDL_locale.c" />
+    <ClCompile Include="..\..\src\locale\windows\SDL_syslocale.c" />
     <ClCompile Include="..\..\src\power\SDL_power.c" />
     <ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
     <ClCompile Include="..\..\src\render\direct3d\SDL_render_d3d.c" />

+ 57 - 0
Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj

@@ -343,6 +343,22 @@
 		55FFA91A2122302B00D7CBED /* SDL_syspower.h in Headers */ = {isa = PBXBuildFile; fileRef = 55FFA9192122302B00D7CBED /* SDL_syspower.h */; };
 		566726451DF72CF5001DD3DB /* SDL_dataqueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 566726431DF72CF5001DD3DB /* SDL_dataqueue.c */; };
 		566726461DF72CF5001DD3DB /* SDL_dataqueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 566726441DF72CF5001DD3DB /* SDL_dataqueue.h */; };
+		566E26EE2462770300718109 /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26ED2462770300718109 /* SDL_locale.h */; };
+		566E26EF2462770300718109 /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26ED2462770300718109 /* SDL_locale.h */; };
+		566E26F02462770300718109 /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26ED2462770300718109 /* SDL_locale.h */; };
+		566E26F12462770300718109 /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26ED2462770300718109 /* SDL_locale.h */; };
+		566E26F22462770300718109 /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26ED2462770300718109 /* SDL_locale.h */; };
+		566E26F82462774E00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26F42462774E00718109 /* SDL_syslocale.h */; };
+		566E26F92462774E00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26F42462774E00718109 /* SDL_syslocale.h */; };
+		566E26FA2462774E00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26F42462774E00718109 /* SDL_syslocale.h */; };
+		566E26FD2462774E00718109 /* SDL_syslocale.m in Sources */ = {isa = PBXBuildFile; fileRef = 566E26F62462774E00718109 /* SDL_syslocale.m */; };
+		566E26FE2462774E00718109 /* SDL_syslocale.m in Sources */ = {isa = PBXBuildFile; fileRef = 566E26F62462774E00718109 /* SDL_syslocale.m */; };
+		566E26FF2462774E00718109 /* SDL_syslocale.m in Sources */ = {isa = PBXBuildFile; fileRef = 566E26F62462774E00718109 /* SDL_syslocale.m */; };
+		566E27002462774E00718109 /* SDL_syslocale.m in Sources */ = {isa = PBXBuildFile; fileRef = 566E26F62462774E00718109 /* SDL_syslocale.m */; };
+		566E27032462774E00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26F72462774E00718109 /* SDL_locale.c */; };
+		566E27042462774E00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26F72462774E00718109 /* SDL_locale.c */; };
+		566E27052462774E00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26F72462774E00718109 /* SDL_locale.c */; };
+		566E27062462774E00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26F72462774E00718109 /* SDL_locale.c */; };
 		56A6702E18565E450007D20F /* SDL_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A6702D18565E450007D20F /* SDL_internal.h */; };
 		56A6703518565E760007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A6703118565E760007D20F /* SDL_dynapi_overrides.h */; };
 		56A6703618565E760007D20F /* SDL_dynapi_procs.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A6703218565E760007D20F /* SDL_dynapi_procs.h */; };
@@ -982,6 +998,10 @@
 		55FFA9192122302B00D7CBED /* SDL_syspower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_syspower.h; sourceTree = "<group>"; };
 		566726431DF72CF5001DD3DB /* SDL_dataqueue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dataqueue.c; sourceTree = "<group>"; };
 		566726441DF72CF5001DD3DB /* SDL_dataqueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dataqueue.h; sourceTree = "<group>"; };
+		566E26ED2462770300718109 /* SDL_locale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_locale.h; sourceTree = "<group>"; };
+		566E26F42462774E00718109 /* SDL_syslocale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_syslocale.h; path = locale/SDL_syslocale.h; sourceTree = "<group>"; };
+		566E26F62462774E00718109 /* SDL_syslocale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_syslocale.m; sourceTree = "<group>"; };
+		566E26F72462774E00718109 /* SDL_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_locale.c; path = locale/SDL_locale.c; sourceTree = "<group>"; };
 		56A6702D18565E450007D20F /* SDL_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_internal.h; sourceTree = "<group>"; };
 		56A6703118565E760007D20F /* SDL_dynapi_overrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dynapi_overrides.h; sourceTree = "<group>"; };
 		56A6703218565E760007D20F /* SDL_dynapi_procs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dynapi_procs.h; sourceTree = "<group>"; };
@@ -1384,6 +1404,25 @@
 			name = Frameworks;
 			sourceTree = "<group>";
 		};
+		566E26F32462773A00718109 /* locale */ = {
+			isa = PBXGroup;
+			children = (
+				566E26F52462774E00718109 /* macosx */,
+				566E26F72462774E00718109 /* SDL_locale.c */,
+				566E26F42462774E00718109 /* SDL_syslocale.h */,
+			);
+			name = locale;
+			sourceTree = "<group>";
+		};
+		566E26F52462774E00718109 /* macosx */ = {
+			isa = PBXGroup;
+			children = (
+				566E26F62462774E00718109 /* SDL_syslocale.m */,
+			);
+			name = macosx;
+			path = locale/macosx;
+			sourceTree = "<group>";
+		};
 		56A6702F18565E4F0007D20F /* dynapi */ = {
 			isa = PBXGroup;
 			children = (
@@ -1656,6 +1695,7 @@
 				AA7558781595D55500BBD41B /* SDL_keyboard.h */,
 				AA7558791595D55500BBD41B /* SDL_keycode.h */,
 				AA75587A1595D55500BBD41B /* SDL_loadso.h */,
+				566E26ED2462770300718109 /* SDL_locale.h */,
 				AA75587B1595D55500BBD41B /* SDL_log.h */,
 				AA75587C1595D55500BBD41B /* SDL_main.h */,
 				AA9FF9501637C6E5000DF050 /* SDL_messagebox.h */,
@@ -1708,6 +1748,7 @@
 				F35CEA6E20F51B7F003ECE98 /* hidapi */,
 				FD5F9D080E0E08B3008E885B /* joystick */,
 				FD8BD8150E27E25900B52CD5 /* loadso */,
+				566E26F32462773A00718109 /* locale */,
 				F3E3C65322406963007D243C /* main */,
 				56ED04DE118A8E9A00A56AA6 /* power */,
 				041B2CE312FA0F680087D585 /* render */,
@@ -1968,9 +2009,11 @@
 				52ED1DA2222889500061FCE0 /* SDL_audio.h in Headers */,
 				52ED1DA3222889500061FCE0 /* SDL_syspower.h in Headers */,
 				52ED1DA4222889500061FCE0 /* SDL_blendmode.h in Headers */,
+				566E26F92462774E00718109 /* SDL_syslocale.h in Headers */,
 				52ED1DA5222889500061FCE0 /* SDL_sensor_c.h in Headers */,
 				52ED1DA6222889500061FCE0 /* SDL_clipboard.h in Headers */,
 				52ED1DA7222889500061FCE0 /* SDL_config_iphoneos.h in Headers */,
+				566E26EF2462770300718109 /* SDL_locale.h in Headers */,
 				52ED1DA8222889500061FCE0 /* SDL_config.h in Headers */,
 				52ED1DA9222889500061FCE0 /* SDL_copying.h in Headers */,
 				52ED1DAA222889500061FCE0 /* SDL_egl_c.h in Headers */,
@@ -2043,6 +2086,7 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				566E26F12462770300718109 /* SDL_locale.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2106,9 +2150,11 @@
 				F3E3C6902241389A007D243C /* SDL_audio.h in Headers */,
 				F3E3C6912241389A007D243C /* SDL_syspower.h in Headers */,
 				F3E3C6922241389A007D243C /* SDL_blendmode.h in Headers */,
+				566E26FA2462774E00718109 /* SDL_syslocale.h in Headers */,
 				F3E3C6932241389A007D243C /* SDL_sensor_c.h in Headers */,
 				F3E3C6942241389A007D243C /* SDL_clipboard.h in Headers */,
 				F3E3C6952241389A007D243C /* SDL_config_iphoneos.h in Headers */,
+				566E26F02462770300718109 /* SDL_locale.h in Headers */,
 				F3E3C6962241389A007D243C /* SDL_config.h in Headers */,
 				F3E3C6972241389A007D243C /* SDL_copying.h in Headers */,
 				F3E3C6982241389A007D243C /* SDL_egl_c.h in Headers */,
@@ -2181,6 +2227,7 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				566E26F22462770300718109 /* SDL_locale.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2260,6 +2307,7 @@
 				AA7558A61595D55500BBD41B /* SDL_gesture.h in Headers */,
 				AA7558A71595D55500BBD41B /* SDL_haptic.h in Headers */,
 				AA7558A81595D55500BBD41B /* SDL_hints.h in Headers */,
+				566E26F82462774E00718109 /* SDL_syslocale.h in Headers */,
 				566726461DF72CF5001DD3DB /* SDL_dataqueue.h in Headers */,
 				F30D9C9F212CD0990047DF2E /* SDL_syssensor.h in Headers */,
 				AA7558AA1595D55500BBD41B /* SDL_joystick.h in Headers */,
@@ -2290,6 +2338,7 @@
 				AA7558BE1595D55500BBD41B /* SDL_scancode.h in Headers */,
 				AA7558BF1595D55500BBD41B /* SDL_shape.h in Headers */,
 				AA7558C01595D55500BBD41B /* SDL_stdinc.h in Headers */,
+				566E26EE2462770300718109 /* SDL_locale.h in Headers */,
 				FAD4F7021BA3C4E8008346CE /* SDL_sysjoystick_c.h in Headers */,
 				AA7558C11595D55500BBD41B /* SDL_surface.h in Headers */,
 				AA7558C21595D55500BBD41B /* SDL_system.h in Headers */,
@@ -2539,6 +2588,7 @@
 				52ED1DFC222889500061FCE0 /* SDL_rwops.c in Sources */,
 				52ED1DFD222889500061FCE0 /* hid.m in Sources */,
 				52ED1DFE222889500061FCE0 /* SDL_vulkan_utils.c in Sources */,
+				566E27042462774E00718109 /* SDL_locale.c in Sources */,
 				52ED1DFF222889500061FCE0 /* SDL_error.c in Sources */,
 				52ED1E00222889500061FCE0 /* SDL.c in Sources */,
 				52ED1E01222889500061FCE0 /* SDL_syscond.c in Sources */,
@@ -2550,6 +2600,7 @@
 				52ED1E07222889500061FCE0 /* SDL_getenv.c in Sources */,
 				52ED1E08222889500061FCE0 /* SDL_iconv.c in Sources */,
 				52ED1E09222889500061FCE0 /* SDL_malloc.c in Sources */,
+				566E26FE2462774E00718109 /* SDL_syslocale.m in Sources */,
 				A7FF6B6323AC3BC6005876C6 /* SDL_hidapi_gamecube.c in Sources */,
 				52ED1E0A222889500061FCE0 /* SDL_hidapi_xbox360.c in Sources */,
 				52ED1E0B222889500061FCE0 /* SDL_qsort.c in Sources */,
@@ -2673,6 +2724,7 @@
 				F3E3C6EA2241389A007D243C /* SDL_rwops.c in Sources */,
 				F3E3C6EB2241389A007D243C /* hid.m in Sources */,
 				F3E3C6EC2241389A007D243C /* SDL_vulkan_utils.c in Sources */,
+				566E27062462774E00718109 /* SDL_locale.c in Sources */,
 				F3E3C6ED2241389A007D243C /* SDL_error.c in Sources */,
 				F3E3C6EE2241389A007D243C /* SDL.c in Sources */,
 				F3E3C6EF2241389A007D243C /* SDL_syscond.c in Sources */,
@@ -2684,6 +2736,7 @@
 				F3E3C6F52241389A007D243C /* SDL_getenv.c in Sources */,
 				F3E3C6F62241389A007D243C /* SDL_iconv.c in Sources */,
 				F3E3C6F72241389A007D243C /* SDL_malloc.c in Sources */,
+				566E27002462774E00718109 /* SDL_syslocale.m in Sources */,
 				A7FF6B6523AC3BC6005876C6 /* SDL_hidapi_gamecube.c in Sources */,
 				F3E3C6F82241389A007D243C /* SDL_hidapi_xbox360.c in Sources */,
 				F3E3C6F92241389A007D243C /* SDL_qsort.c in Sources */,
@@ -2847,7 +2900,9 @@
 				FAB598731BB5C31600BE72C5 /* SDL_iconv.c in Sources */,
 				FAB598741BB5C31600BE72C5 /* SDL_malloc.c in Sources */,
 				FAB598751BB5C31600BE72C5 /* SDL_qsort.c in Sources */,
+				566E27052462774E00718109 /* SDL_locale.c in Sources */,
 				F36839CE214790950000F255 /* SDL_dummysensor.c in Sources */,
+				566E26FF2462774E00718109 /* SDL_syslocale.m in Sources */,
 				A7C19D2B212E552C00DF2152 /* SDL_displayevents.c in Sources */,
 				FAB598761BB5C31600BE72C5 /* SDL_stdlib.c in Sources */,
 				FAB598771BB5C31600BE72C5 /* SDL_string.c in Sources */,
@@ -2931,6 +2986,7 @@
 				FD6526760DE8FCDD002AD96B /* SDL_rwops.c in Sources */,
 				F30D9CC6212CE92C0047DF2E /* hid.m in Sources */,
 				4D7517201EE1D98200820EEA /* SDL_vulkan_utils.c in Sources */,
+				566E27032462774E00718109 /* SDL_locale.c in Sources */,
 				FD6526780DE8FCDD002AD96B /* SDL_error.c in Sources */,
 				FD65267A0DE8FCDD002AD96B /* SDL.c in Sources */,
 				FD65267B0DE8FCDD002AD96B /* SDL_syscond.c in Sources */,
@@ -2942,6 +2998,7 @@
 				FD3F4A760DEA620800C5B771 /* SDL_getenv.c in Sources */,
 				FD3F4A770DEA620800C5B771 /* SDL_iconv.c in Sources */,
 				FD3F4A780DEA620800C5B771 /* SDL_malloc.c in Sources */,
+				566E26FD2462774E00718109 /* SDL_syslocale.m in Sources */,
 				A7FF6B6223AC3BC6005876C6 /* SDL_hidapi_gamecube.c in Sources */,
 				F3BDD79220F51CB8004ECBF3 /* SDL_hidapi_xbox360.c in Sources */,
 				FD3F4A790DEA620800C5B771 /* SDL_qsort.c in Sources */,

+ 64 - 0
Xcode/SDL/SDL.xcodeproj/project.pbxproj

@@ -17,6 +17,10 @@
 		564624381FF821DA0074AC87 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 564624371FF821CB0074AC87 /* Metal.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
 		5646243B1FF822100074AC87 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 564624351FF821B80074AC87 /* QuartzCore.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
 		5646243C1FF822170074AC87 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 564624371FF821CB0074AC87 /* Metal.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+		566E267A2462701100718109 /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26792462701100718109 /* SDL_locale.h */; };
+		566E26CF246274CC00718109 /* SDL_syslocale.m in Sources */ = {isa = PBXBuildFile; fileRef = 566E26CC246274CB00718109 /* SDL_syslocale.m */; };
+		566E26D8246274CC00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26CD246274CB00718109 /* SDL_locale.c */; };
+		566E26E1246274CC00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26CE246274CC00718109 /* SDL_syslocale.h */; };
 		567E2F2117C44C35005F1892 /* SDL_filesystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 567E2F2017C44C35005F1892 /* SDL_filesystem.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		56C5237F1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E951D8B69D600B177DD /* CoreAudio.framework */; };
 		56C523811D8F498C001F2F30 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D0D08310675DD9004B05EF /* CoreFoundation.framework */; };
@@ -3983,6 +3987,10 @@
 		4D4820431F0F10B400EDC31C /* SDL_vulkan.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_vulkan.h; sourceTree = "<group>"; };
 		564624351FF821B80074AC87 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		564624371FF821CB0074AC87 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
+		566E26792462701100718109 /* SDL_locale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_locale.h; sourceTree = "<group>"; };
+		566E26CC246274CB00718109 /* SDL_syslocale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDL_syslocale.m; path = locale/macosx/SDL_syslocale.m; sourceTree = "<group>"; };
+		566E26CD246274CB00718109 /* SDL_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_locale.c; path = locale/SDL_locale.c; sourceTree = "<group>"; };
+		566E26CE246274CC00718109 /* SDL_syslocale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_syslocale.h; path = locale/SDL_syslocale.h; sourceTree = "<group>"; };
 		567E2F2017C44C35005F1892 /* SDL_filesystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_filesystem.h; sourceTree = "<group>"; };
 		5C2EF7001FC9EF0F003F5197 /* SDL_egl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_egl.h; sourceTree = "<group>"; };
 		75E09158241EA924004729E1 /* SDL_virtualjoystick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_virtualjoystick.c; sourceTree = "<group>"; };
@@ -4662,6 +4670,7 @@
 				AA7557DA1595D4D800BBD41B /* SDL_keyboard.h */,
 				AA7557DB1595D4D800BBD41B /* SDL_keycode.h */,
 				AA7557DC1595D4D800BBD41B /* SDL_loadso.h */,
+				566E26792462701100718109 /* SDL_locale.h */,
 				AA7557DD1595D4D800BBD41B /* SDL_log.h */,
 				AA7557DE1595D4D800BBD41B /* SDL_main.h */,
 				AA9FF9591637CBF9000DF050 /* SDL_messagebox.h */,
@@ -4760,6 +4769,7 @@
 				A7D8A79D23E2513E00DCD162 /* joystick */,
 				A7D8A91123E2514000DCD162 /* libm */,
 				A7D8A85D23E2513F00DCD162 /* loadso */,
+				566E26CB246274AE00718109 /* locale */,
 				A7D8A5AC23E2513D00DCD162 /* main */,
 				A7D8A7DF23E2513F00DCD162 /* power */,
 				A7D8A8DA23E2514000DCD162 /* render */,
@@ -4826,6 +4836,24 @@
 			name = Frameworks;
 			sourceTree = "<group>";
 		};
+		566E26CB246274AE00718109 /* locale */ = {
+			isa = PBXGroup;
+			children = (
+				566E26EA246274E800718109 /* macosx */,
+				566E26CD246274CB00718109 /* SDL_locale.c */,
+				566E26CE246274CC00718109 /* SDL_syslocale.h */,
+			);
+			name = locale;
+			sourceTree = "<group>";
+		};
+		566E26EA246274E800718109 /* macosx */ = {
+			isa = PBXGroup;
+			children = (
+				566E26CC246274CB00718109 /* SDL_syslocale.m */,
+			);
+			name = macosx;
+			sourceTree = "<group>";
+		};
 		75E09157241EA924004729E1 /* virtual */ = {
 			isa = PBXGroup;
 			children = (
@@ -5734,6 +5762,7 @@
 				A75FCD2323E25AB700529352 /* SDL_uikitmessagebox.h in Headers */,
 				A75FCD2423E25AB700529352 /* SDL_x11messagebox.h in Headers */,
 				A75FCD2523E25AB700529352 /* SDL_thread_c.h in Headers */,
+				566E26812462701100718109 /* SDL_locale.h in Headers */,
 				A75FCD2623E25AB700529352 /* SDL_cocoamessagebox.h in Headers */,
 				A75FCD2723E25AB700529352 /* SDL_x11shape.h in Headers */,
 				A75FCD2823E25AB700529352 /* SDL_cpuinfo.h in Headers */,
@@ -5816,6 +5845,7 @@
 				A75FCD7323E25AB700529352 /* SDL_yuv_c.h in Headers */,
 				A75FCD7423E25AB700529352 /* scancodes_xfree86.h in Headers */,
 				A75FCD7523E25AB700529352 /* SDL_syspower.h in Headers */,
+				566E26E8246274CC00718109 /* SDL_syslocale.h in Headers */,
 				A75FDAFA23E35ED600529352 /* SDL_config_iphoneos.h in Headers */,
 				A75FCD7623E25AB700529352 /* SDL_x11clipboard.h in Headers */,
 				A75FCD7723E25AB700529352 /* SDL_name.h in Headers */,
@@ -5975,6 +6005,7 @@
 				A75FCEDC23E25AC700529352 /* SDL_uikitmessagebox.h in Headers */,
 				A75FCEDD23E25AC700529352 /* SDL_x11messagebox.h in Headers */,
 				A75FCEDE23E25AC700529352 /* SDL_thread_c.h in Headers */,
+				566E26822462701100718109 /* SDL_locale.h in Headers */,
 				A75FCEDF23E25AC700529352 /* SDL_cocoamessagebox.h in Headers */,
 				A75FCEE023E25AC700529352 /* SDL_x11shape.h in Headers */,
 				A75FCEE123E25AC700529352 /* SDL_cpuinfo.h in Headers */,
@@ -6057,6 +6088,7 @@
 				A75FCF2C23E25AC700529352 /* SDL_yuv_c.h in Headers */,
 				A75FCF2D23E25AC700529352 /* scancodes_xfree86.h in Headers */,
 				A75FCF2E23E25AC700529352 /* SDL_syspower.h in Headers */,
+				566E26E9246274CC00718109 /* SDL_syslocale.h in Headers */,
 				A75FDAFB23E35ED700529352 /* SDL_config_iphoneos.h in Headers */,
 				A75FCF2F23E25AC700529352 /* SDL_x11clipboard.h in Headers */,
 				A75FCF3023E25AC700529352 /* SDL_name.h in Headers */,
@@ -6240,6 +6272,7 @@
 				A769B0AA23E259AE00872273 /* SDL_uikitmessagebox.h in Headers */,
 				A769B0AB23E259AE00872273 /* SDL_x11messagebox.h in Headers */,
 				A769B0AC23E259AE00872273 /* SDL_thread_c.h in Headers */,
+				566E267F2462701100718109 /* SDL_locale.h in Headers */,
 				A769B0AD23E259AE00872273 /* SDL_cocoamessagebox.h in Headers */,
 				A769B0AE23E259AE00872273 /* SDL_x11shape.h in Headers */,
 				A769B0AF23E259AE00872273 /* SDL_cpuinfo.h in Headers */,
@@ -6322,6 +6355,7 @@
 				A769B0FB23E259AE00872273 /* SDL_yuv_c.h in Headers */,
 				A769B0FC23E259AE00872273 /* scancodes_xfree86.h in Headers */,
 				A769B0FD23E259AE00872273 /* SDL_syspower.h in Headers */,
+				566E26E6246274CC00718109 /* SDL_syslocale.h in Headers */,
 				A75FDAF923E35ED500529352 /* SDL_config_iphoneos.h in Headers */,
 				A769B0FE23E259AE00872273 /* SDL_x11clipboard.h in Headers */,
 				A769B0FF23E259AE00872273 /* SDL_name.h in Headers */,
@@ -6638,10 +6672,12 @@
 				A7D8B39923E2514200DCD162 /* SDL_blit_copy.h in Headers */,
 				A7D8B22B23E2514200DCD162 /* gl2.h in Headers */,
 				A7D88A5023E2437C00DCD162 /* SDL_shape.h in Headers */,
+				566E26E2246274CC00718109 /* SDL_syslocale.h in Headers */,
 				A7D88A5123E2437C00DCD162 /* SDL_stdinc.h in Headers */,
 				A7D8ACCA23E2514100DCD162 /* SDL_uikitappdelegate.h in Headers */,
 				A7D8BBB823E254E400DCD162 /* SDL_sysjoystick_c.h in Headers */,
 				A7D8B3B123E2514200DCD162 /* SDL_yuv_c.h in Headers */,
+				566E267B2462701100718109 /* SDL_locale.h in Headers */,
 				A7D8B1F523E2514200DCD162 /* SDL_x11dyn.h in Headers */,
 				A7D8AC8823E2514100DCD162 /* SDL_uikitviewcontroller.h in Headers */,
 				A7D8AC0A23E2514100DCD162 /* SDL_shape_internals.h in Headers */,
@@ -6882,10 +6918,12 @@
 				A7D88C0823E24BED00DCD162 /* SDL_scancode.h in Headers */,
 				A7D8B39A23E2514200DCD162 /* SDL_blit_copy.h in Headers */,
 				A7D8B22C23E2514200DCD162 /* gl2.h in Headers */,
+				566E26E3246274CC00718109 /* SDL_syslocale.h in Headers */,
 				A7D88C0A23E24BED00DCD162 /* SDL_shape.h in Headers */,
 				A7D88C0C23E24BED00DCD162 /* SDL_stdinc.h in Headers */,
 				A7D8ACCB23E2514100DCD162 /* SDL_uikitappdelegate.h in Headers */,
 				A7D8B3B223E2514200DCD162 /* SDL_yuv_c.h in Headers */,
+				566E267C2462701100718109 /* SDL_locale.h in Headers */,
 				A7D8B1F623E2514200DCD162 /* SDL_x11dyn.h in Headers */,
 				A7D8AC8923E2514100DCD162 /* SDL_uikitviewcontroller.h in Headers */,
 				A7D8AC0B23E2514100DCD162 /* SDL_shape_internals.h in Headers */,
@@ -6969,6 +7007,7 @@
 				A7D8AC9723E2514100DCD162 /* SDL_uikitmessagebox.h in Headers */,
 				A7D8B15023E2514200DCD162 /* SDL_x11messagebox.h in Headers */,
 				A7D8B3F023E2514300DCD162 /* SDL_thread_c.h in Headers */,
+				566E267E2462701100718109 /* SDL_locale.h in Headers */,
 				A7D8AF0A23E2514100DCD162 /* SDL_cocoamessagebox.h in Headers */,
 				A7D8B16823E2514200DCD162 /* SDL_x11shape.h in Headers */,
 				A7D88D2723E24D3B00DCD162 /* SDL_cpuinfo.h in Headers */,
@@ -7051,6 +7090,7 @@
 				A7D8B3B423E2514200DCD162 /* SDL_yuv_c.h in Headers */,
 				A7D8BBA323E2514500DCD162 /* scancodes_xfree86.h in Headers */,
 				A7D8B5D923E2514300DCD162 /* SDL_syspower.h in Headers */,
+				566E26E5246274CC00718109 /* SDL_syslocale.h in Headers */,
 				A75FDAF823E35ED500529352 /* SDL_config_iphoneos.h in Headers */,
 				A7D8B21023E2514200DCD162 /* SDL_x11clipboard.h in Headers */,
 				A7D88D3923E24D3B00DCD162 /* SDL_name.h in Headers */,
@@ -7185,6 +7225,7 @@
 				A7D8BBE023E2574800DCD162 /* SDL_uikitopenglview.h in Headers */,
 				A7D8B4AC23E2514300DCD162 /* SDL_gamecontrollerdb.h in Headers */,
 				A7D8B9EF23E2514400DCD162 /* SDL_drawpoint.h in Headers */,
+				566E26E1246274CC00718109 /* SDL_syslocale.h in Headers */,
 				A7D8B39E23E2514200DCD162 /* SDL_RLEaccel_c.h in Headers */,
 				A7D8B44023E2514300DCD162 /* SDL_sysmutex_c.h in Headers */,
 				A7D8BA4323E2514400DCD162 /* SDL_glesfuncs.h in Headers */,
@@ -7321,6 +7362,7 @@
 				A7D8BB9F23E2514500DCD162 /* scancodes_xfree86.h in Headers */,
 				A7D8BBE623E2574800DCD162 /* SDL_uikitviewcontroller.h in Headers */,
 				A7D8AF1E23E2514100DCD162 /* SDL_cocoamouse.h in Headers */,
+				566E267A2462701100718109 /* SDL_locale.h in Headers */,
 				A7D8BBEA23E2574800DCD162 /* SDL_uikitwindow.h in Headers */,
 				A7D8AE8E23E2514100DCD162 /* SDL_cocoakeyboard.h in Headers */,
 				A7D8BA4F23E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
@@ -7484,6 +7526,7 @@
 				A7D8BA7623E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
 				A7D8B42B23E2514300DCD162 /* SDL_systhread_c.h in Headers */,
 				AA7558231595D4D800BBD41B /* SDL_keycode.h in Headers */,
+				566E26E4246274CC00718109 /* SDL_syslocale.h in Headers */,
 				A7D8B20923E2514200DCD162 /* SDL_x11keyboard.h in Headers */,
 				A7D8AE9123E2514100DCD162 /* SDL_cocoakeyboard.h in Headers */,
 				A7D8B1F123E2514200DCD162 /* SDL_x11framebuffer.h in Headers */,
@@ -7552,6 +7595,7 @@
 				A7D8BB6023E2514500DCD162 /* scancodes_linux.h in Headers */,
 				A7D8B1F723E2514200DCD162 /* SDL_x11dyn.h in Headers */,
 				A7D8BB6623E2514500DCD162 /* SDL_touch_c.h in Headers */,
+				566E267D2462701100718109 /* SDL_locale.h in Headers */,
 				A7D8B4AF23E2514300DCD162 /* SDL_gamecontrollerdb.h in Headers */,
 				A7D8AEEB23E2514100DCD162 /* SDL_cocoavulkan.h in Headers */,
 				A7D8B23323E2514200DCD162 /* gl2platform.h in Headers */,
@@ -7724,6 +7768,7 @@
 				A7D8BBB023E2514500DCD162 /* SDL_windowevents_c.h in Headers */,
 				DB313FD917554B71006C0E22 /* SDL_joystick.h in Headers */,
 				A7D8AF0523E2514100DCD162 /* SDL_cocoavideo.h in Headers */,
+				566E26E7246274CC00718109 /* SDL_syslocale.h in Headers */,
 				DB313FDA17554B71006C0E22 /* SDL_keyboard.h in Headers */,
 				A7D8ACC223E2514100DCD162 /* SDL_uikitevents.h in Headers */,
 				A7D8BB3E23E2514500DCD162 /* SDL_gesture_c.h in Headers */,
@@ -7792,6 +7837,7 @@
 				A7D8AC0223E2514100DCD162 /* SDL_nullevents_c.h in Headers */,
 				A7D8B58623E2514300DCD162 /* SDL_sysjoystick.h in Headers */,
 				A7D8BBCF23E2561600DCD162 /* SDL_steamcontroller.h in Headers */,
+				566E26802462701100718109 /* SDL_locale.h in Headers */,
 				A7D8BB6223E2514500DCD162 /* scancodes_linux.h in Headers */,
 				A7D8B1F923E2514200DCD162 /* SDL_x11dyn.h in Headers */,
 				A7D8BB6823E2514500DCD162 /* SDL_touch_c.h in Headers */,
@@ -8393,6 +8439,7 @@
 				A75FCE2C23E25AB700529352 /* SDL_cocoakeyboard.m in Sources */,
 				A75FCE2D23E25AB700529352 /* SDL_dynapi.c in Sources */,
 				A75FCE2E23E25AB700529352 /* SDL_shaders_gl.c in Sources */,
+				566E26DF246274CC00718109 /* SDL_locale.c in Sources */,
 				A75FCE2F23E25AB700529352 /* e_log.c in Sources */,
 				A75FCE3023E25AB700529352 /* SDL_cocoamessagebox.m in Sources */,
 				A75FCE3123E25AB700529352 /* SDL_blendfillrect.c in Sources */,
@@ -8465,6 +8512,7 @@
 				A75FCE7523E25AB700529352 /* SDL_rect.c in Sources */,
 				A75FCE7623E25AB700529352 /* SDL_cocoaopengles.m in Sources */,
 				A75FCE7723E25AB700529352 /* SDL_qsort.c in Sources */,
+				566E26D6246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A75FCE7823E25AB700529352 /* SDL_hidapi_switch.c in Sources */,
 				A75FCE7923E25AB700529352 /* SDL_strtokr.c in Sources */,
 				A75FCE7A23E25AB700529352 /* SDL_clipboardevents.c in Sources */,
@@ -8589,6 +8637,7 @@
 				A75FCFE523E25AC700529352 /* SDL_cocoakeyboard.m in Sources */,
 				A75FCFE623E25AC700529352 /* SDL_dynapi.c in Sources */,
 				A75FCFE723E25AC700529352 /* SDL_shaders_gl.c in Sources */,
+				566E26E0246274CC00718109 /* SDL_locale.c in Sources */,
 				A75FCFE823E25AC700529352 /* e_log.c in Sources */,
 				A75FCFE923E25AC700529352 /* SDL_cocoamessagebox.m in Sources */,
 				A75FCFEA23E25AC700529352 /* SDL_blendfillrect.c in Sources */,
@@ -8661,6 +8710,7 @@
 				A75FD02E23E25AC700529352 /* SDL_rect.c in Sources */,
 				A75FD02F23E25AC700529352 /* SDL_cocoaopengles.m in Sources */,
 				A75FD03023E25AC700529352 /* SDL_qsort.c in Sources */,
+				566E26D7246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A75FD03123E25AC700529352 /* SDL_hidapi_switch.c in Sources */,
 				A75FD03223E25AC700529352 /* SDL_strtokr.c in Sources */,
 				A75FD03323E25AC700529352 /* SDL_clipboardevents.c in Sources */,
@@ -8879,12 +8929,14 @@
 				A769B1FD23E259AE00872273 /* SDL_blit_auto.c in Sources */,
 				A769B1FE23E259AE00872273 /* SDL_x11keyboard.c in Sources */,
 				A769B1FF23E259AE00872273 /* SDL_keyboard.c in Sources */,
+				566E26DD246274CC00718109 /* SDL_locale.c in Sources */,
 				A769B20123E259AE00872273 /* SDL_rect.c in Sources */,
 				A769B20223E259AE00872273 /* SDL_cocoaopengles.m in Sources */,
 				A769B20323E259AE00872273 /* SDL_qsort.c in Sources */,
 				A75FDB5223E39D1700529352 /* hid.m in Sources */,
 				A769B20423E259AE00872273 /* SDL_hidapi_switch.c in Sources */,
 				A769B20523E259AE00872273 /* SDL_strtokr.c in Sources */,
+				566E26D4246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A769B20623E259AE00872273 /* SDL_clipboardevents.c in Sources */,
 				A769B20723E259AE00872273 /* SDL_x11framebuffer.c in Sources */,
 				A769B20823E259AE00872273 /* k_cos.c in Sources */,
@@ -9097,10 +9149,12 @@
 				A7D8AAB123E2514100DCD162 /* SDL_syshaptic.c in Sources */,
 				A7D8B5CA23E2514300DCD162 /* SDL_rwopsbundlesupport.m in Sources */,
 				A7D8AC1023E2514100DCD162 /* SDL_video.c in Sources */,
+				566E26D0246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A7D8AB5623E2514100DCD162 /* SDL_offscreenopengl.c in Sources */,
 				A7D8ACC423E2514100DCD162 /* SDL_uikitmetalview.m in Sources */,
 				A7D8BA5C23E2514400DCD162 /* SDL_shaders_gles2.c in Sources */,
 				A7D8B14123E2514200DCD162 /* SDL_blit_1.c in Sources */,
+				566E26D9246274CC00718109 /* SDL_locale.c in Sources */,
 				A7D8B17D23E2514200DCD162 /* SDL_x11dyn.c in Sources */,
 				A7D8BB1623E2514500DCD162 /* SDL_mouse.c in Sources */,
 				A7D8BADA23E2514500DCD162 /* e_rem_pio2.c in Sources */,
@@ -9292,10 +9346,12 @@
 				A7D8AAB223E2514100DCD162 /* SDL_syshaptic.c in Sources */,
 				A7D8B5CB23E2514300DCD162 /* SDL_rwopsbundlesupport.m in Sources */,
 				A7D8AC1123E2514100DCD162 /* SDL_video.c in Sources */,
+				566E26D1246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A7D8AB5723E2514100DCD162 /* SDL_offscreenopengl.c in Sources */,
 				A7D8ACC523E2514100DCD162 /* SDL_uikitmetalview.m in Sources */,
 				A7D8BA5D23E2514400DCD162 /* SDL_shaders_gles2.c in Sources */,
 				A7D8B14223E2514200DCD162 /* SDL_blit_1.c in Sources */,
+				566E26DA246274CC00718109 /* SDL_locale.c in Sources */,
 				A7D8B17E23E2514200DCD162 /* SDL_x11dyn.c in Sources */,
 				A7D8BB1723E2514500DCD162 /* SDL_mouse.c in Sources */,
 				A7D8BADB23E2514500DCD162 /* e_rem_pio2.c in Sources */,
@@ -9466,12 +9522,14 @@
 				A7D8AD2723E2514100DCD162 /* SDL_blit_auto.c in Sources */,
 				A7D8B1AA23E2514200DCD162 /* SDL_x11keyboard.c in Sources */,
 				A7D8BB6D23E2514500DCD162 /* SDL_keyboard.c in Sources */,
+				566E26DC246274CC00718109 /* SDL_locale.c in Sources */,
 				A7D8ACEB23E2514100DCD162 /* SDL_rect.c in Sources */,
 				A7D8AE9E23E2514100DCD162 /* SDL_cocoaopengles.m in Sources */,
 				A7D8B96C23E2514400DCD162 /* SDL_qsort.c in Sources */,
 				A75FDB5123E39D1700529352 /* hid.m in Sources */,
 				A7D8B55523E2514300DCD162 /* SDL_hidapi_switch.c in Sources */,
 				A7D8B96623E2514400DCD162 /* SDL_strtokr.c in Sources */,
+				566E26D3246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A7D8BB7923E2514500DCD162 /* SDL_clipboardevents.c in Sources */,
 				A7D8B18623E2514200DCD162 /* SDL_x11framebuffer.c in Sources */,
 				A7D8BAB923E2514400DCD162 /* k_cos.c in Sources */,
@@ -9635,6 +9693,7 @@
 				A7D8BB0923E2514500DCD162 /* k_tan.c in Sources */,
 				A7D8B15E23E2514200DCD162 /* SDL_x11vulkan.c in Sources */,
 				A7D8B8A823E2514400DCD162 /* SDL_diskaudio.c in Sources */,
+				566E26CF246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A7D8AFC023E2514200DCD162 /* SDL_egl.c in Sources */,
 				A7D8AC3323E2514100DCD162 /* SDL_RLEaccel.c in Sources */,
 				A7D8BBB123E2514500DCD162 /* SDL_assert.c in Sources */,
@@ -9706,6 +9765,7 @@
 				A7D8B15823E2514200DCD162 /* SDL_x11opengl.c in Sources */,
 				A7D8AEA023E2514100DCD162 /* SDL_cocoavulkan.m in Sources */,
 				A7D8AB6123E2514100DCD162 /* SDL_offscreenwindow.c in Sources */,
+				566E26D8246274CC00718109 /* SDL_locale.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -9805,6 +9865,7 @@
 				A7D8B5F623E2514300DCD162 /* SDL_syspower.c in Sources */,
 				A7D8B1C723E2514200DCD162 /* SDL_x11touch.c in Sources */,
 				A7D8B95323E2514400DCD162 /* SDL_iconv.c in Sources */,
+				566E26DB246274CC00718109 /* SDL_locale.c in Sources */,
 				A7D8BAA023E2514400DCD162 /* s_fabs.c in Sources */,
 				A7D8B1E523E2514200DCD162 /* SDL_x11shape.c in Sources */,
 				A7D8BC0423E2574800DCD162 /* SDL_uikitvulkan.m in Sources */,
@@ -9880,6 +9941,7 @@
 				A7D8AC1223E2514100DCD162 /* SDL_video.c in Sources */,
 				A7D8AB5823E2514100DCD162 /* SDL_offscreenopengl.c in Sources */,
 				A7D8BA5E23E2514400DCD162 /* SDL_shaders_gles2.c in Sources */,
+				566E26D2246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A7D8B14323E2514200DCD162 /* SDL_blit_1.c in Sources */,
 				A7D8B17F23E2514200DCD162 /* SDL_x11dyn.c in Sources */,
 				A7D8BB1823E2514500DCD162 /* SDL_mouse.c in Sources */,
@@ -9999,6 +10061,7 @@
 				A7D8B76323E2514300DCD162 /* SDL_sysloadso.c in Sources */,
 				A7D8B16F23E2514200DCD162 /* SDL_x11xinput2.c in Sources */,
 				A7D8B5F823E2514300DCD162 /* SDL_syspower.c in Sources */,
+				566E26DE246274CC00718109 /* SDL_locale.c in Sources */,
 				A7D8B1C923E2514200DCD162 /* SDL_x11touch.c in Sources */,
 				A7D8B95523E2514400DCD162 /* SDL_iconv.c in Sources */,
 				A7D8BAA223E2514400DCD162 /* s_fabs.c in Sources */,
@@ -10074,6 +10137,7 @@
 				A7D8ACC823E2514100DCD162 /* SDL_uikitmetalview.m in Sources */,
 				A7D8BBBA23E2560600DCD162 /* SDL_steamcontroller.c in Sources */,
 				A7D8BA6023E2514400DCD162 /* SDL_shaders_gles2.c in Sources */,
+				566E26D5246274CC00718109 /* SDL_syslocale.m in Sources */,
 				A7D8B14523E2514200DCD162 /* SDL_blit_1.c in Sources */,
 				A7D8B18123E2514200DCD162 /* SDL_x11dyn.c in Sources */,
 				A7D8BB1A23E2514500DCD162 /* SDL_mouse.c in Sources */,

+ 42 - 1
configure

@@ -770,6 +770,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -981,6 +982,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE}'
@@ -1233,6 +1235,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1370,7 +1381,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1523,6 +1534,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -17309,6 +17321,7 @@ SOURCES="$SOURCES $srcdir/src/thread/*.c"
 SOURCES="$SOURCES $srcdir/src/timer/*.c"
 SOURCES="$SOURCES $srcdir/src/video/*.c"
 SOURCES="$SOURCES $srcdir/src/video/yuv2rgb/*.c"
+SOURCES="$SOURCES $srcdir/src/locale/*.c"
 
 
 # Check whether --enable-atomic was given.
@@ -24659,6 +24672,8 @@ CheckNoStrictAliasing
 
 CheckEventSignals
 
+have_locale=no
+
 case "$host" in
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
         case "$host" in
@@ -24746,6 +24761,9 @@ case "$host" in
         CheckRPATH
         CheckVivanteVideo
 
+        SOURCES="$SOURCES $srcdir/src/locale/unix/*.c"
+        have_locale=yes
+
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
           case $ARCH in
@@ -24923,6 +24941,10 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
         # Set up the core platform files
         SOURCES="$SOURCES $srcdir/src/core/windows/*.c"
 
+        # Use the Windows locale APIs.
+        SOURCES="$SOURCES $srcdir/src/locale/windows/*.c"
+        have_locale=yes
+
         # Set up files for the video library
         if test x$enable_video = xyes; then
 
@@ -25174,6 +25196,11 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
             SOURCES="$SOURCES $srcdir/src/filesystem/haiku/*.cc"
             have_filesystem=yes
         fi
+
+        # Set up files for the locale library
+        SOURCES="$SOURCES $srcdir/src/locale/haiku/*.cc"
+        have_locale=yes
+
         # The Haiku platform requires special setup.
         SOURCES="$srcdir/src/main/haiku/*.cc $SOURCES"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lroot -lbe -lmedia -lgame -ldevice -ltextencoding"
@@ -25216,6 +25243,10 @@ fi
         CheckVulkan
         CheckPTHREAD
 
+        # Set up files for the locale library
+        SOURCES="$SOURCES $srcdir/src/locale/macosx/*.m"
+        have_locale=yes
+
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
 
@@ -25337,6 +25368,10 @@ $as_echo "#define SDL_VIDEO_RENDER_OGL_ES2 1" >>confdefs.h
         CheckPTHREAD
         CheckHIDAPI
 
+        # Set up files for the locale library
+        SOURCES="$SOURCES $srcdir/src/locale/macosx/*.m"
+        have_locale=yes
+
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
 
@@ -25492,6 +25527,9 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
             SOURCES="$SOURCES $srcdir/src/timer/unix/*.c"
             have_timers=yes
         fi
+        # Set up files for the locale library
+        SOURCES="$SOURCES $srcdir/src/locale/emscripten/*.c"
+        have_locale=yes
         ;;
     *-*-riscos*)
         ARCH=riscos
@@ -25549,6 +25587,9 @@ INSTALL_SDL2_CONFIG=$enable_sdl2_config
 
 # Verify that we have all the platform specific files we need
 
+if test x$have_locale != xyes; then
+    SOURCES="$SOURCES $srcdir/src/locale/dummy/*.c"
+fi
 if test x$have_joystick != xyes; then
     if test x$enable_joystick = xyes; then
 

+ 29 - 0
configure.ac

@@ -413,6 +413,7 @@ SOURCES="$SOURCES $srcdir/src/thread/*.c"
 SOURCES="$SOURCES $srcdir/src/timer/*.c"
 SOURCES="$SOURCES $srcdir/src/video/*.c"
 SOURCES="$SOURCES $srcdir/src/video/yuv2rgb/*.c"
+SOURCES="$SOURCES $srcdir/src/locale/*.c"
 
 dnl Enable/disable various subsystems of the SDL library
 
@@ -3439,6 +3440,8 @@ CheckNoStrictAliasing
 dnl Do this for every platform, but for some it doesn't mean anything, but better to catch it here anyhow.
 CheckEventSignals
 
+have_locale=no
+
 dnl Set up the configuration based on the host platform!
 case "$host" in
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
@@ -3527,6 +3530,9 @@ case "$host" in
         CheckRPATH
         CheckVivanteVideo
 
+        SOURCES="$SOURCES $srcdir/src/locale/unix/*.c"
+        have_locale=yes
+
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
           case $ARCH in
@@ -3676,6 +3682,10 @@ case "$host" in
         # Set up the core platform files
         SOURCES="$SOURCES $srcdir/src/core/windows/*.c"
 
+        # Use the Windows locale APIs.
+        SOURCES="$SOURCES $srcdir/src/locale/windows/*.c"
+        have_locale=yes
+
         # Set up files for the video library
         if test x$enable_video = xyes; then
             AC_DEFINE(SDL_VIDEO_DRIVER_WINDOWS, 1, [ ])
@@ -3847,6 +3857,11 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
             SOURCES="$SOURCES $srcdir/src/filesystem/haiku/*.cc"
             have_filesystem=yes
         fi
+
+        # Set up files for the locale library
+        SOURCES="$SOURCES $srcdir/src/locale/haiku/*.cc"
+        have_locale=yes
+
         # The Haiku platform requires special setup.
         SOURCES="$srcdir/src/main/haiku/*.cc $SOURCES"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lroot -lbe -lmedia -lgame -ldevice -ltextencoding"
@@ -3867,6 +3882,10 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         CheckVulkan
         CheckPTHREAD
 
+        # Set up files for the locale library
+        SOURCES="$SOURCES $srcdir/src/locale/macosx/*.m"
+        have_locale=yes
+
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
             AC_DEFINE(SDL_AUDIO_DRIVER_COREAUDIO, 1, [ ])
@@ -3966,6 +3985,10 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         CheckPTHREAD
         CheckHIDAPI
 
+        # Set up files for the locale library
+        SOURCES="$SOURCES $srcdir/src/locale/macosx/*.m"
+        have_locale=yes
+
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
             AC_DEFINE(SDL_AUDIO_DRIVER_COREAUDIO, 1, [ ])
@@ -4093,6 +4116,9 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
             SOURCES="$SOURCES $srcdir/src/timer/unix/*.c"
             have_timers=yes
         fi
+        # Set up files for the locale library
+        SOURCES="$SOURCES $srcdir/src/locale/emscripten/*.c"
+        have_locale=yes
         ;;
     *-*-riscos*)
         ARCH=riscos
@@ -4141,6 +4167,9 @@ AC_SUBST([INSTALL_SDL2_CONFIG], [$enable_sdl2_config])
 
 # Verify that we have all the platform specific files we need
 
+if test x$have_locale != xyes; then
+    SOURCES="$SOURCES $srcdir/src/locale/dummy/*.c"
+fi
 if test x$have_joystick != xyes; then
     if test x$enable_joystick = xyes; then
         AC_DEFINE(SDL_JOYSTICK_DUMMY, 1, [ ])

+ 1 - 0
include/SDL.h

@@ -59,6 +59,7 @@
 #include "SDL_timer.h"
 #include "SDL_version.h"
 #include "SDL_video.h"
+#include "SDL_locale.h"
 
 #include "begin_code.h"
 /* Set up for C function definitions, even when using C++ */

+ 2 - 0
include/SDL_events.h

@@ -85,6 +85,8 @@ typedef enum
                                      Called on Android in onResume()
                                 */
 
+    SDL_LOCALECHANGED,  /**< The user's locale preferences have changed. */
+
     /* Display events */
     SDL_DISPLAYEVENT   = 0x150,  /**< Display state change */
 

+ 15 - 0
include/SDL_hints.h

@@ -1348,6 +1348,21 @@ extern "C" {
 #define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME"
 
 
+/**
+ *  \brief Override for SDL_GetPreferredLocales()
+ *
+ *  If set, this will be favored over anything the OS might report for the
+ *  user's preferred locales. Changing this hint at runtime will not generate
+ *  a SDL_LOCALECHANGED event (but if you can change the hint, you can push
+ *  your own event, if you want).
+ *
+ *  The format of this hint is a comma-separated list of language and locale,
+ *  combined with an underscore, as is a common format: "en_GB". Locale is
+ *  optional: "en". So you might have a list like this: "en_GB,jp,es_PT"
+ */
+#define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES"
+
+
 /**
  *  \brief  An enumeration of hint priorities
  */

+ 101 - 0
include/SDL_locale.h

@@ -0,0 +1,101 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL_locale.h
+ *
+ *  Include file for SDL locale services
+ */
+
+#ifndef _SDL_locale_h
+#define _SDL_locale_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+
+typedef struct SDL_Locale
+{
+    const char *language;  /**< A language name, like "en" for English. */
+    const char *country;  /**< A country, like "US" for America. Can be NULL. */
+} SDL_Locale;
+
+/**
+ *  \brief Report the user's preferred locale.
+ *
+ *  This returns an array of SDL_Locale structs, the final item zeroed out.
+ *  When the caller is done with this array, it should call SDL_free() on
+ *  the returned value; all the memory involved is allocated in a single
+ *  block, so a single SDL_free() will suffice.
+ *
+ *  Returned language strings are in the format xx, where 'xx' is an ISO-639
+ *  language specifier (such as "en" for English, "de" for German, etc).
+ *  Country strings are in the format YY, where "YY" is an ISO-3166 country
+ *  code (such as "US" for the United States, "CA" for Canada, etc). Country
+ *  might be NULL if there's no specific guidance on them (so you might get
+ *  { "en", "US" } for American English, but { "en", NULL } means "English
+ *  language, generically"). Language strings are never NULL, except to
+ *  terminate the array.
+ *
+ *  Please note that not all of these strings are 2 characters; some are
+ *  three or more.
+ *
+ *  The returned list of locales are in the order of the user's preference.
+ *  For example, a German citizen that is fluent in US English and knows
+ *  enough Japanese to navigate around Tokyo might have a list like:
+ *  { "de", "en_US", "jp", NULL }. Someone from England might prefer British
+ *  English (where "color" is spelled "colour", etc), but will settle for
+ *  anything like it: { "en_GB", "en", NULL }.
+ *
+ *  This function returns NULL on error, including when the platform does not
+ *  supply this information at all.
+ *
+ *  This might be a "slow" call that has to query the operating system. It's
+ *  best to ask for this once and save the results. However, this list can
+ *  change, usually because the user has changed a system preference outside
+ *  of your program; SDL will send an SDL_LOCALECHANGED event in this case,
+ *  if possible, and you can call this function again to get an updated copy
+ *  of preferred locales.
+ *
+ *   \return array of locales, terminated with a locale with a NULL language
+ *           field. Will return NULL on error.
+ */
+extern DECLSPEC SDL_Locale * SDLCALL SDL_GetPreferredLocales(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_locale_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 78 - 0
src/core/android/SDL_android.c

@@ -44,6 +44,8 @@
 #include "../../haptic/android/SDL_syshaptic_c.h"
 
 #include <android/log.h>
+#include <android/configuration.h>
+#include <android/asset_manager_jni.h>
 #include <sys/system_properties.h>
 #include <pthread.h>
 #include <sys/types.h>
@@ -2796,6 +2798,82 @@ SDL_bool Android_JNI_RequestPermission(const char *permission)
 	return bPermissionRequestResult;
 }
 
+int Android_JNI_GetLocale(char *buf, size_t buflen)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    JNIEnv* env = Android_JNI_GetEnv();
+    int retval = -1;
+
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    if (!LocalReferenceHolder_Init(&refs, env)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return -1;
+    }
+
+    SDL_assert(buflen > 6);
+
+    jmethodID mid;
+    jobject context;
+    jobject assetManager;
+
+    /* context = SDLActivity.getContext(); */
+    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+            "getContext","()Landroid/content/Context;");
+    context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
+
+    /* assetManager = context.getAssets(); */
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
+            "getAssets", "()Landroid/content/res/AssetManager;");
+    assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
+
+
+    /* API from NDK: android/configuration.h */
+    /* API from NDK: android/asset_manager_jni.h */
+    AAssetManager* asset_mgr = AAssetManager_fromJava(env, assetManager);
+    AConfiguration *cfg = AConfiguration_new();
+
+    if (asset_mgr && cfg)
+    {
+        char language[2] = {};
+        char country[2] = {};
+        size_t id = 0;
+
+        AConfiguration_fromAssetManager(cfg, asset_mgr);
+        AConfiguration_getLanguage(cfg, language);
+        AConfiguration_getCountry(cfg, country);
+
+        retval = 0;
+
+        /* copy language (not null terminated) */
+        if (language[0]) {
+            buf[id++] = language[0];
+            if (language[1]) {
+                buf[id++] = language[1];
+            }
+        }
+
+        buf[id++] = '_';
+
+        /* copy country (not null terminated) */
+        if (country[0]) {
+            buf[id++] = country[0];
+            if (country[1]) {
+                buf[id++] = country[1];
+            }
+        }
+        
+        buf[id++] = '\0';
+        SDL_assert(id <= buflen);
+    }
+
+    if (cfg) {
+        AConfiguration_delete(cfg);
+    }
+
+    LocalReferenceHolder_Cleanup(&refs);
+    return retval;
+}
+
 #endif /* __ANDROID__ */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 3 - 0
src/core/android/SDL_android.h

@@ -104,6 +104,9 @@ void Android_JNI_InitTouch(void);
 JNIEnv *Android_JNI_GetEnv(void);
 int Android_JNI_SetupThread(void);
 
+/* Locale */
+int Android_JNI_GetLocale(char *buf, size_t buflen);
+
 /* Generic messages */
 int Android_JNI_SendMessage(int command, int param);
 

+ 1 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -763,3 +763,4 @@
 #define SDL_Metal_GetDrawableSize SDL_Metal_GetDrawableSize_REAL
 #define SDL_trunc SDL_trunc_REAL
 #define SDL_truncf SDL_truncf_REAL
+#define SDL_GetPreferredLocales SDL_GetPreferredLocales_REAL

+ 1 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -822,3 +822,4 @@ SDL_DYNAPI_PROC(void*,SDL_Metal_GetLayer,(SDL_MetalView a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_Metal_GetDrawableSize,(SDL_Window *a, int *b, int *c),(a,b,c),)
 SDL_DYNAPI_PROC(double,SDL_trunc,(double a),(a),return)
 SDL_DYNAPI_PROC(float,SDL_truncf,(float a),(a),return)
+SDL_DYNAPI_PROC(SDL_Locale *,SDL_GetPreferredLocales,(void),(),return)

+ 6 - 0
src/events/SDL_events.c

@@ -1009,6 +1009,12 @@ SDL_SendKeymapChangedEvent(void)
     return SDL_SendAppEvent(SDL_KEYMAPCHANGED);
 }
 
+int
+SDL_SendLocaleChangedEvent(void)
+{
+    return SDL_SendAppEvent(SDL_LOCALECHANGED);
+}
+
 int
 SDL_EventsInit(void)
 {

+ 1 - 0
src/events/SDL_events_c.h

@@ -46,6 +46,7 @@ extern void SDL_QuitInterrupt(void);
 extern int SDL_SendAppEvent(SDL_EventType eventType);
 extern int SDL_SendSysWMEvent(SDL_SysWMmsg * message);
 extern int SDL_SendKeymapChangedEvent(void);
+extern int SDL_SendLocaleChangedEvent(void);
 
 extern int SDL_SendQuit(void);
 

+ 103 - 0
src/locale/SDL_locale.c

@@ -0,0 +1,103 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../SDL_internal.h"
+#include "SDL_syslocale.h"
+#include "SDL_hints.h"
+
+static SDL_Locale *
+build_locales_from_csv_string(char *csv)
+{
+    size_t num_locales = 1;  /* at least one */
+    size_t slen;
+    size_t alloclen;
+    char *ptr;
+    SDL_Locale *loc;
+    SDL_Locale *retval;
+
+    if (!csv || !csv[0]) {
+        return NULL;  /* nothing to report */
+    }
+
+    for (ptr = csv; *ptr; ptr++) {
+        if (*ptr == ',') {
+            num_locales++;
+        }
+    }
+
+    num_locales++;  /* one more for terminator */
+
+    slen = ((size_t) (ptr - csv)) + 1;  /* strlen(csv) + 1 */
+    alloclen = slen + (num_locales * sizeof (SDL_Locale));
+
+    loc = retval = (SDL_Locale *) SDL_calloc(1, alloclen);
+    if (!retval) {
+        SDL_OutOfMemory();
+        return NULL;  /* oh well */
+    }
+    ptr = (char *) (retval + num_locales);
+    SDL_strlcpy(ptr, csv, slen);
+
+    while (SDL_TRUE) {  /* parse out the string */
+        while (*ptr == ' ') ptr++;  /* skip whitespace. */
+        if (*ptr == '\0') {
+            break;
+        }
+        loc->language = ptr++;
+        while (SDL_TRUE) {
+            const char ch = *ptr;
+            if (ch == '_') {
+                *(ptr++) = '\0';
+                loc->country = ptr;
+            } else if (ch == ' ') {
+                *(ptr++) = '\0';  /* trim ending whitespace and keep going. */
+            } else if (ch == ',') {
+                *(ptr++) = '\0';
+                loc++;
+                break;
+            } else if (ch == '\0') {
+                loc++;
+                break;
+            } else {
+                ptr++;  /* just keep going, still a valid string */
+            }
+        }
+    }
+
+    return retval;
+}
+
+SDL_Locale *
+SDL_GetPreferredLocales(void)
+{
+    char locbuf[128];  /* enough for 21 "xx_YY," language strings. */
+    const char *hint = SDL_GetHint(SDL_HINT_PREFERRED_LOCALES);
+    if (hint) {
+        SDL_strlcpy(locbuf, hint, sizeof (locbuf));
+    } else {
+        SDL_zeroa(locbuf);
+        SDL_SYS_GetPreferredLocales(locbuf, sizeof (locbuf));
+    }
+    return build_locales_from_csv_string(locbuf);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 29 - 0
src/locale/SDL_syslocale.h

@@ -0,0 +1,29 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+/* This is the system specific header for the SDL locale API */
+
+#include "SDL_locale.h"
+
+extern void SDL_SYS_GetPreferredLocales(char *buf, size_t buflen);
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 32 - 0
src/locale/android/SDL_syslocale.c

@@ -0,0 +1,32 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+#include "../SDL_syslocale.h"
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{
+    Android_JNI_GetLocale(buf, buflen);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 33 - 0
src/locale/dummy/SDL_syslocale.c

@@ -0,0 +1,33 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+#include "../SDL_syslocale.h"
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{
+    /* dummy implementation. Caller already zero'd out buffer. */
+    SDL_Unsupported();
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 72 - 0
src/locale/emscripten/SDL_syslocale.c

@@ -0,0 +1,72 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <emscripten.h>
+
+#include "../../SDL_internal.h"
+#include "../SDL_syslocale.h"
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{
+    EM_ASM({
+        var buf = $0;
+        var buflen = $1;
+        var list = undefined;
+
+        if (navigator.languages && navigator.languages.length) {
+            list = navigator.languages;
+        } else {
+            var oneOfThese = navigator.userLanguage || navigator.language || navigator.browserLanguage || navigator.systemLanguage;
+            if (oneOfThese !== undefined) {
+                list = [ oneOfThese ];
+            }
+        }
+
+        if (list === undefined) {
+            return;  /* we've got nothing. */
+        }
+
+        var str = "";  /* Can't do list.join() because we need to fit in buflen. */
+        for (var i = 0; i < list.length; i++) {
+            var item = list[i];
+            if ((str.length + item.length + 1) > buflen) {
+                break;   /* don't add, we're out of space. */
+            }
+            if (str.length > 0) {
+                str += ",";
+            }
+            str += item;
+        }
+
+        str = str.replace(/-/g, "_");
+        if (buflen > str.length) {
+            buflen = str.length;  /* clamp to size of string. */
+        }
+
+        for (var i = 0; i < buflen; i++) {
+            setValue(buf + i, str.charCodeAt(i), "i8");  /* fill in C array. */
+        }
+    }, buf, buflen);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 75 - 0
src/locale/haiku/SDL_syslocale.cc

@@ -0,0 +1,75 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <LocaleRoster.h>
+
+#include "../../SDL_internal.h"
+#include "../SDL_syslocale.h"
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{
+    BLocaleRoster *roster = BLocaleRoster::Default();
+    roster->Refresh();
+
+    BMessage msg;
+    if (roster->GetPreferredLanguages(&msg) != B_OK) {
+        SDL_SetError("BLocaleRoster couldn't get preferred languages");
+        return;
+    }
+
+    const char *key = "language";
+    type_code typ = B_ANY_TYPE;
+    int32 numlangs = 0;
+    if ((msg.GetInfo(key, &typ, &numlangs) != B_OK) || (typ != B_STRING_TYPE)) {
+        SDL_SetError("BLocaleRoster message was wrong");
+        return;
+    }
+
+    for (int32 i = 0; i < numlangs; i++) {
+        const char *str = NULL;
+        if (msg.FindString(key, i, &str) != B_OK) {
+            continue;
+        }
+
+        const size_t len = SDL_strlen(str);
+        if (buflen <= len) {
+            break;  // can't fit it, we're done.
+        }
+
+        SDL_strlcpy(buf, str, buflen);
+        buf += len;
+        buflen -= len;
+
+        if (i < (numlangs - 1)) {
+            if (buflen <= 1) {
+                break;  // out of room, stop looking.
+            }
+            buf[0] = ',';  // add a comma between entries.
+            buf[1] = '\0';
+            buf++;
+            buflen--;
+        }
+    }
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 76 - 0
src/locale/macosx/SDL_syslocale.m

@@ -0,0 +1,76 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+#include "../SDL_syslocale.h"
+
+#import <Foundation/Foundation.h>
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{ @autoreleasepool {
+    NSArray *languages = NSLocale.preferredLanguages;
+    size_t numlangs = 0;
+    size_t i;
+
+    numlangs = (size_t) [languages count];
+
+    for (i = 0; i < numlangs; i++) {
+        NSString *nsstr = [languages objectAtIndex:i];
+        size_t len;
+        char *ptr;
+
+        if (nsstr == nil) {
+            break;
+        }
+
+        [nsstr getCString:buf maxLength:buflen encoding:NSASCIIStringEncoding];
+        len = SDL_strlen(buf);
+
+        // convert '-' to '_'...
+        //  These are always full lang-COUNTRY, so we search from the back,
+        //  so things like zh-Hant-CN find the right '-' to convert.
+        if ((ptr = SDL_strrchr(buf, '-')) != NULL) {
+            *ptr = '_';
+        }
+
+        if (buflen <= len) {
+            *buf = '\0';  // drop this one and stop, we can't fit anymore.
+            break;
+        }
+
+        buf += len;
+        buflen -= len;
+
+        if (i < (numlangs - 1)) {
+            if (buflen <= 1) {
+                break;  // out of room, stop looking.
+            }
+            buf[0] = ',';  // add a comma between entries.
+            buf[1] = '\0';
+            buf++;
+            buflen--;
+        }
+    }
+}}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 110 - 0
src/locale/unix/SDL_syslocale.c

@@ -0,0 +1,110 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+#include "../SDL_syslocale.h"
+#include "SDL_assert.h"
+
+static void
+normalize_locale_str(char *dst, char *str, size_t buflen)
+{
+    char *ptr;
+
+    ptr = SDL_strchr(str, '.');  /* chop off encoding if specified. */
+    if (ptr != NULL) {
+        *ptr = '\0';
+    }
+
+    ptr = SDL_strchr(str, '@');  /* chop off extra bits if specified. */
+    if (ptr != NULL) {
+        *ptr = '\0';
+    }
+
+    /* The "C" locale isn't useful for our needs, ignore it if you see it. */
+    if ((str[0] == 'C') && (str[1] == '\0')) {
+        return;
+    }
+
+    if (*str) {
+        if (*dst) {
+            SDL_strlcat(dst, ",", buflen);  /* SDL has these split by commas */
+        }
+        SDL_strlcat(dst, str, buflen);
+    }
+}
+
+static void
+normalize_locales(char *dst, char *src, size_t buflen)
+{
+    char *ptr;
+
+    /* entries are separated by colons */
+    while ((ptr = SDL_strchr(src, ':')) != NULL) {
+        *ptr = '\0';
+        normalize_locale_str(dst, src, buflen);
+        src = ptr + 1;
+    }
+    normalize_locale_str(dst, src, buflen);
+}
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{
+    /* !!! FIXME: should we be using setlocale()? Or some D-Bus thing? */
+    SDL_bool isstack;
+    const char *envr;
+    char *tmp;
+
+    SDL_assert(buflen > 0);
+    tmp = SDL_small_alloc(char, buflen, &isstack);
+    if (!tmp) {
+        SDL_OutOfMemory();
+        return;
+    }
+
+    *tmp = '\0';
+
+    /* LANG is the primary locale (maybe) */
+    envr = SDL_getenv("LANG");
+    if (envr) {
+        SDL_strlcpy(tmp, envr, buflen);
+    }
+
+    /* fallback languages */
+    envr = SDL_getenv("LANGUAGE");
+    if (envr) {
+        if (*tmp) {
+            SDL_strlcat(tmp, ":", buflen);
+        }
+        SDL_strlcat(tmp, envr, buflen);
+    }
+
+    if (*tmp == '\0') {
+        SDL_SetError("LANG environment variable isn't set");
+    } else {
+        normalize_locales(buf, tmp, buflen);
+    }
+
+    SDL_small_free(tmp, isstack);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 119 - 0
src/locale/windows/SDL_syslocale.c

@@ -0,0 +1,119 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+#include "../../core/windows/SDL_windows.h"
+#include "../SDL_syslocale.h"
+#include "SDL_assert.h"
+
+typedef BOOL (WINAPI *pfnGetUserPreferredUILanguages)(DWORD,PULONG,PZZWSTR,PULONG);
+#ifndef MUI_LANGUAGE_NAME
+#define MUI_LANGUAGE_NAME 0x8 
+#endif
+
+static pfnGetUserPreferredUILanguages pGetUserPreferredUILanguages = NULL;
+static HMODULE kernel32 = 0;
+
+
+/* this is the fallback for WinXP...one language, not a list. */
+static void
+SDL_SYS_GetPreferredLocales_winxp(char *buf, size_t buflen)
+{
+    const char **retval = NULL;
+    char lang[16];
+    char country[16];
+
+	const int langrc = GetLocaleInfoA(LOCALE_USER_DEFAULT,
+                                      LOCALE_SISO639LANGNAME,
+                                      lang, sizeof (lang));
+
+	const int ctryrc =  GetLocaleInfoA(LOCALE_USER_DEFAULT,
+                                       LOCALE_SISO3166CTRYNAME,
+                                       country, sizeof (country));
+
+    /* Win95 systems will fail, because they don't have LOCALE_SISO*NAME ... */
+    if (langrc == 0) {
+        SDL_SetError("Couldn't obtain language info");
+    } else {
+        SDL_snprintf(buf, buflen, "%s%s%s", lang, ctryrc ? "_" : "", ctryrc ? country : "");
+    }
+}
+
+/* this works on Windows Vista and later. */
+static void
+SDL_SYS_GetPreferredLocales_vista(char *buf, size_t buflen)
+{
+    ULONG numlangs = 0;
+    WCHAR *wbuf = NULL;
+    ULONG wbuflen = 0;
+    SDL_bool isstack;
+
+    SDL_assert(pGetUserPreferredUILanguages != NULL);
+    pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numlangs, NULL, &wbuflen);
+
+    wbuf = SDL_small_alloc(WCHAR, wbuflen, &isstack);
+    if (!wbuf) {
+        SDL_OutOfMemory();
+        return;
+    }
+
+    if (!pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numlangs, wbuf, &wbuflen)) {
+        SDL_SYS_GetPreferredLocales_winxp(buf, buflen);  /* oh well, try the fallback. */
+    } else {
+        const ULONG endidx = SDL_min(buflen, wbuflen - 1);
+        ULONG str_start = 0;
+        ULONG i;
+        for (i = 0; i < endidx; i++) {
+            const char ch = (char) wbuf[i];  /* these should all be low-ASCII, safe to cast */
+            if (ch == '\0') {
+                buf[i] = ',';  /* change null separators to commas */
+                str_start = i;
+            } else if (ch == '-') {
+                buf[i] = '_';  /* change '-' to '_' */
+            } else {
+                buf[i] = ch;   /* copy through as-is. */
+            }
+        }
+        buf[str_start] = '\0';  /* terminate string, chop off final ',' */
+    }
+
+    SDL_small_free(wbuf, isstack);
+}
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{
+    if (!kernel32) {
+        kernel32 = LoadLibraryW(L"kernel32.dll");
+        if (kernel32) {
+            pGetUserPreferredUILanguages = (pfnGetUserPreferredUILanguages) GetProcAddress(kernel32, "GetUserPreferredUILanguages");
+        }
+    }
+
+    if (pGetUserPreferredUILanguages == NULL) {
+        SDL_SYS_GetPreferredLocales_winxp(buf, buflen);  /* this is always available */
+    } else {
+        SDL_SYS_GetPreferredLocales_vista(buf, buflen);  /* available on Vista and later. */
+    }
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 58 - 0
src/locale/winrt/SDL_syslocale.c

@@ -0,0 +1,58 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <Windows.h>
+
+#include "../../SDL_internal.h"
+#include "../SDL_syslocale.h"
+
+/*using namespace Windows::Graphics::Display;*/
+#include <wchar.h>
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{
+    WCHAR wbuffer[128] = L"";
+    int ret = 0;
+
+    /* !!! FIXME: do we not have GetUserPreferredUILanguages on WinPhone or UWP? */
+# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+    ret = GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_SNAME, wbuffer, SDL_arraylen(wbuffer));
+# else
+    ret = GetSystemDefaultLocaleName(wbuffer, SDL_arraysize(wbuffer));
+# endif
+
+    if (ret > 0)
+    {
+        /* Need to convert LPWSTR to LPSTR, that is wide char to char. */
+        int i;
+
+        if (ret >= (buflen - 1) ) {
+            ret = (int) (buflen - 1);
+        }
+        for (i = 0; i < ret; i++) {
+            buf[i] = (char) wbuffer[i];  /* assume this was ASCII anyhow. */
+        }
+    }
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 5 - 0
src/main/haiku/SDL_BApp.h

@@ -22,6 +22,7 @@
 #define SDL_BAPP_H
 
 #include <InterfaceKit.h>
+#include <LocaleRoster.h>
 #if SDL_VIDEO_OPENGL
 #include <OpenGLKit.h>
 #endif
@@ -153,6 +154,10 @@ public:
             _HandleWindowResized(message);
             break;
 
+        case B_LOCALE_CHANGED:
+            SDL_SendLocaleChangedEvent();
+            break;
+
         case BAPP_SCREEN_CHANGED:
             /* TODO: Handle screen resize or workspace change */
             break;

+ 12 - 0
src/video/cocoa/SDL_cocoaevents.m

@@ -117,6 +117,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
 }
 
 - (id)init;
+- (void)localeDidChange:(NSNotification *)notification;
 @end
 
 @implementation SDLAppDelegate : NSObject
@@ -137,6 +138,11 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
                    selector:@selector(focusSomeWindow:)
                        name:NSApplicationDidBecomeActiveNotification
                      object:nil];
+
+        [center addObserver:self
+                   selector:@selector(localeDidChange:)
+                       name:NSCurrentLocaleDidChangeNotification
+                     object:nil];
     }
 
     return self;
@@ -148,6 +154,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
 
     [center removeObserver:self name:NSWindowWillCloseNotification object:nil];
     [center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
+    [center removeObserver:self name:NSCurrentLocaleDidChangeNotification object:nil];
 
     [super dealloc];
 }
@@ -226,6 +233,11 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
     }
 }
 
+- (void)localeDidChange:(NSNotification *)notification;
+{
+    SDL_SendLocaleChangedEvent();
+}
+
 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
 {
     return (BOOL)SDL_SendDropFile(NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL);

+ 5 - 0
test/Makefile.in

@@ -37,6 +37,7 @@ TARGETS = \
 	testjoystick$(EXE) \
 	testkeys$(EXE) \
 	testloadso$(EXE) \
+	testlocale$(EXE) \
 	testlock$(EXE) \
 	testmessage$(EXE) \
 	testmultiaudio$(EXE) \
@@ -303,6 +304,10 @@ controllermap$(EXE): $(srcdir)/controllermap.c
 testvulkan$(EXE): $(srcdir)/testvulkan.c
 	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
 
+testlocale$(EXE): $(srcdir)/testlocale.c
+	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
+
+
 
 clean:
 	rm -f $(TARGETS)

+ 1 - 0
test/README

@@ -12,6 +12,7 @@ These are test programs for the SDL library:
 	testjoystick	List joysticks and watch joystick events
 	testkeys	List the available keyboard keys
 	testloadso	Tests the loadable library layer
+	testlocale  Test Locale API
 	testlock	Hacked up test of multi-threading and locking
 	testmultiaudio	Tests using several audio devices
 	testoverlay2	Tests the overlay flickering/scaling during playback.

+ 13 - 1
test/configure

@@ -640,6 +640,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -720,6 +721,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE}'
@@ -972,6 +974,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1109,7 +1120,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1262,6 +1273,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]

+ 67 - 0
test/testlocale.c

@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely.
+*/
+#include <stdio.h>
+#include "SDL.h"
+
+/* !!! FIXME: move this to the test framework */
+
+static void log_locales(void)
+{
+    SDL_Locale *locales = SDL_GetPreferredLocales();
+    if (locales == NULL) {
+        SDL_Log("Couldn't determine locales: %s", SDL_GetError());
+    } else {
+        SDL_Locale *l;
+        unsigned int total = 0;
+        SDL_Log("Locales, in order of preference:");
+        for (l = locales; l->language; l++) {
+            const char *c = l->country;
+            SDL_Log(" - %s%s%s", l->language, c ? "_" : "", c ? c : "");
+            total++;
+        }
+        SDL_Log("%u locales seen.", total);
+        SDL_free(locales);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+    /* Print locales and languages */
+    if (SDL_Init(SDL_INIT_VIDEO) != -1) {
+        log_locales();
+
+        if ((argc == 2) && (SDL_strcmp(argv[1], "--listen") == 0)) {
+            SDL_bool keep_going = SDL_TRUE;
+            while (keep_going) {
+                SDL_Event e;
+                while (SDL_PollEvent(&e)) {
+                    if (e.type == SDL_QUIT) {
+                        keep_going = SDL_FALSE;
+                    } else if (e.type == SDL_LOCALECHANGED) {
+                        SDL_Log("Saw SDL_LOCALECHANGED event!");
+                        log_locales();
+                    }
+                }
+                SDL_Delay(10);
+            }
+        }
+
+        SDL_Quit();
+    }
+
+   return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */